DIRECTORY Basics USING [bytesPerWord], Cursors USING [SetCursor], FS USING [Error, StreamOpen], Icons USING [DrawIconProc, IconFileFormat, IconFlavor, iconH, IconRef, IconRep, iconW], Imager USING [ClipRectangleI, Font, SetColor, SetFont, SetXYI, ShowRope, white], ImagerBackdoor USING [DrawBits], InputFocus USING [GetInputFocus, SetInputFocus], IO USING [EndOfStream, SetIndex, STREAM, UnsafeGetBlock], Menus USING [FindEntry, MenuEntry], MessageWindow USING [Append, Blink, Confirm], Process USING [Detach], Rope USING [Concat, Fetch, Length, ROPE, Run, Substr], TIPUser USING [InstantiateNewTIPTable, TIPScreenCoords, TIPTable], UserProfile USING [CallWhenProfileChanges, ProfileChangedProc, Token], VFonts USING [CharWidth, EstablishFont, FontAscent, StringWidth], ViewerClasses USING [ModifyProc, NotifyProc, Viewer], ViewerOps USING [DestroyViewer, OpenIcon, PaintViewer, ChangeColumn, SaveViewer], ViewerPrivate USING [], ViewerTools USING [SelPosRec, SetSelection], WindowManager USING [colorDisplayOn]; IconsImpl: CEDAR MONITOR IMPORTS Cursors, FS, Imager, ImagerBackdoor, InputFocus, IO, Menus, MessageWindow, Process, Rope, TIPUser, UserProfile, VFonts, ViewerOps, ViewerTools, WindowManager EXPORTS Icons, ViewerPrivate SHARES Menus = BEGIN OPEN Icons; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; Viewer: TYPE = ViewerClasses.Viewer; bigFont: Imager.Font _ NIL; bigFontHeight: INTEGER _ 0; smallFont: Imager.Font _ NIL; smallFontHeight: INTEGER _ 0; suppressIconPrefix: ROPE _ NIL; maxIcons: CARDINAL = 64; IconArray: TYPE = ARRAY [0..maxIcons) OF IconRef; icons: REF IconArray _ NEW[IconArray _ ALL[NIL]]; nextFlavor: IconFlavor _ document; DrawIcon: PUBLIC ENTRY DrawIconProc = { leading: INTEGER = 3; iconInfo: IconRef ~ icons[ORD[flavor]]; prefix: ROPE _ NIL; IF iconInfo.proc=NIL THEN { ImagerBackdoor.DrawBits[context: context, base: LOOPHOLE[iconInfo], wordsPerLine: iconW/16, sMin: 0, fMin: 0, sSize: iconH, fSize: iconW, tx: x, ty: y+iconH]; IF iconInfo.label THEN { iconFont: Imager.Font; fontHeight: INTEGER; ix: INTEGER _ x+iconInfo.lx; iy: INTEGER _ y+iconInfo.ly+iconInfo.lh; indent: INTEGER _ 0; segments: LIST OF ROPE _ NIL; IF VFonts.StringWidth[label, bigFont]<=iconInfo.lw THEN { iconFont _ bigFont; fontHeight _ bigFontHeight; segments _ LIST[label]; } ELSE { iconFont _ smallFont; fontHeight _ smallFontHeight; indent _ VFonts.CharWidth[' , iconFont]; segments _ Decompose[label, iconInfo.lw, indent, iconFont]; }; Imager.ClipRectangleI[context, ix, iy, iconInfo.lw, -iconInfo.lh]; Imager.SetFont[context, iconFont]; IF iconInfo.invertLabel THEN Imager.SetColor[context, Imager.white]; FOR list: LIST OF ROPE _ segments, list.rest UNTIL list=NIL DO rope: ROPE ~ list.first; iy _ iy-fontHeight; Imager.SetXYI[context, ix, iy]; iy _ iy-leading; Imager.ShowRope[context, rope]; IF list=segments THEN ix _ ix+indent; ENDLOOP; }; } ELSE iconInfo.proc[flavor, context, x, y, label]; }; GetFonts: ENTRY PROC = { bigFont _ VFonts.EstablishFont["Helvetica", 8]; bigFontHeight _ VFonts.FontAscent[bigFont]; smallFont _ VFonts.EstablishFont["Helvetica", 7]; smallFontHeight _ VFonts.FontAscent[smallFont]; }; ChangePrefix: UserProfile.ProfileChangedProc ~ { suppressIconPrefix _ UserProfile.Token[key: "Viewers.SuppressIconPrefix", default: NIL]; }; Decompose: PROC [name: ROPE, width, indent: INTEGER, font: Imager.Font] RETURNS [segments: LIST OF ROPE _ NIL] = { start: INT _ 0; stop: INT _ name.Length[]; extension: ROPE _ NIL; Build: PROC[start: INT] RETURNS[LIST OF ROPE] ~ { maxw: INTEGER _ (IF start=0 THEN width ELSE width-indent); sw: INTEGER _ 0; -- width of string so far next: INT _ -1; IF start>=stop THEN RETURN[IF extension=NIL THEN NIL ELSE LIST[extension]]; FOR i: INT IN[start..stop) DO c: CHAR ~ name.Fetch[i]; sw _ sw+VFonts.CharWidth[c, font]; IF sw>maxw THEN { IF next<0 THEN next _ MAX[i, start+1]; EXIT }; -- stop here SELECT c FROM '], '>, '/, ' => next _ i+1; -- could end a line IN['A..'Z], IN['0..'9] => IF i>start THEN next _ i; -- next line could start here ENDCASE; REPEAT FINISHED => next _ stop; ENDLOOP; RETURN[CONS[name.Substr[start: start, len: next-start], Build[next]]]; }; IF suppressIconPrefix#NIL THEN { prefixLen: INT ~ suppressIconPrefix.Length[]; IF Rope.Run[s1: name, s2: suppressIconPrefix, case: FALSE]=prefixLen THEN start _ prefixLen; }; FOR i: INT DECREASING IN[start..stop) DO IF name.Fetch[i]='. THEN { extension _ name.Substr[start: i]; stop _ i; EXIT }; ENDLOOP; RETURN[Build[start]]; }; NewFlavor: ENTRY PROC RETURNS [newFlavor: IconFlavor] = { newFlavor _ nextFlavor; nextFlavor _ SUCC[newFlavor]; IF LOOPHOLE[nextFlavor, CARDINAL] >= maxIcons THEN ERROR; }; NewIcon: PUBLIC PROC [info: IconRef] RETURNS [newFlavor: IconFlavor] = { newFlavor _ NewFlavor[]; icons[ORD[newFlavor]] _ info; }; IconRefFromStream: PROC[stream: STREAM, n: CARDINAL] RETURNS [IconRef] ~ { format: IconFileFormat; -- 512 words! bytesPerIcon: INT ~ SIZE[IconFileFormat]*Basics.bytesPerWord; IO.SetIndex[stream, bytesPerIcon*n]; TRUSTED { base: LONG POINTER TO IconFileFormat ~ @format; bytesRead: INT ~ IO.UnsafeGetBlock[stream, [base: LOOPHOLE[base], count: bytesPerIcon]]; IF bytesRead#bytesPerIcon THEN ERROR IO.EndOfStream[stream]; }; RETURN[NEW[IconRep _ [bits: format.bits, label: format.label, invertLabel: format.invertLabel, lx: format.lx, ly: format.ly, lw: format.lw, lh: format.lh]]]; }; IconsFromFile: ENTRY PROC [file: ROPE] RETURNS [first: IconFlavor, nRead: INTEGER] ~ { ENABLE UNWIND => NULL; stream: STREAM ~ FS.StreamOpen[file]; first _ nextFlavor; FOR nRead _ 0, nRead+1 DO info: IconRef ~ IconRefFromStream[stream, nRead ! IO.EndOfStream => EXIT]; icons[ORD[nextFlavor]] _ info; nextFlavor _ nextFlavor.SUCC; ENDLOOP; }; NewIconFromFile: PUBLIC PROC [file: ROPE, n: CARDINAL] RETURNS [newFlavor: IconFlavor] ~ { stream: STREAM ~ FS.StreamOpen[file]; info: IconRef ~ IconRefFromStream[stream, n ! IO.EndOfStream => GOTO Fail]; RETURN[NewIcon[info]]; EXITS Fail => RETURN[unInit]; }; IconNotify: PUBLIC ViewerClasses.NotifyProc = { mx, my: INTEGER; closeOthers, switchDisplays: BOOL _ FALSE; FOR l: LIST OF REF ANY _ input, l.rest UNTIL l = NIL DO WITH l.first SELECT FROM z: TIPUser.TIPScreenCoords => [mouseX: mx, mouseY: my] _ z^; z: ATOM => SELECT z FROM $OpenDesktop, $ResetDesktop => { IF self.class.flavor = $DeskTop THEN self.class.notify[self, input]; RETURN}; $SetInputFocus => SELECT self.class.flavor FROM $Text => ViewerTools.SetSelection[self, NEW[ViewerTools.SelPosRec_[]]]; $Typescript, $Chat => ViewerTools.SetSelection[self]; ENDCASE; $CloseOthers => closeOthers _ TRUE; $Color => IF WindowManager.colorDisplayOn THEN ViewerOps.ChangeColumn[self, color]; $Delete => DestroyIcon[self]; $Save => { entry: Menus.MenuEntry = Menus.FindEntry[self.menu, "Save"]; MessageWindow.Append["Saving icon . . . ", TRUE]; IF entry = NIL THEN ViewerOps.SaveViewer[self] ELSE entry.proc[self]; MessageWindow.Append["done."]}; $Left => ViewerOps.ChangeColumn[self, left]; $MouseMove => Cursors.SetCursor[textPointer]; $Open => ViewerOps.OpenIcon[self, closeOthers]; $Right => ViewerOps.ChangeColumn[self, right]; $Select => SelectIcon[self]; $TogglePos => ViewerOps.ChangeColumn[self, SELECT self.column FROM left => right, right => left, color => left, ENDCASE => ERROR]; ENDCASE => NULL; ENDCASE => NULL; ENDLOOP; }; IconModify: PUBLIC ViewerClasses.ModifyProc = { SELECT change FROM set => ViewerOps.PaintViewer[self, all]; kill => {selectedIcon _ NIL; ViewerOps.PaintViewer[self, all]}; ENDCASE; }; selectedIcon: PUBLIC ViewerClasses.Viewer _ NIL; DestroyIcon: PROC [icon: Viewer] = { IF icon.inhibitDestroy THEN { MessageWindow.Append["That icon cannot be destroyed.", TRUE]; MessageWindow.Blink[]; RETURN}; IF icon.link = NIL AND (icon.newVersion OR icon.newFile) THEN TRUSTED {Process.Detach[FORK ConfirmDestroyIcon[icon]]} -- fork for confirmation ELSE ViewerOps.DestroyViewer[icon]; }; ConfirmDestroyIcon: PROC [icon: Viewer] = { IF MessageWindow.Confirm[Rope.Concat["Confirm delete (and loss of edits) for icon: ", icon.name]] THEN ViewerOps.DestroyViewer[icon]; }; SelectIcon: PROC [viewer: Viewer] = { IF InputFocus.GetInputFocus[].owner#viewer THEN { InputFocus.SetInputFocus[NIL]; -- kill old so we don't smash selectedIcon selectedIcon _ viewer; InputFocus.SetInputFocus[viewer]; }; }; iconTIP: PUBLIC TIPUser.TIPTable _ TIPUser.InstantiateNewTIPTable["Icons.tip"]; {-- Font and Icon initialization takes place here. ok: BOOL _ TRUE; GetFonts[]; [] _ IconsFromFile["Standard.icons" ! FS.Error => IF error.group # bug THEN {ok _ FALSE; CONTINUE}]; IF NOT ok THEN [] _ IconsFromFile["[]<>Standard.icons"]; }; UserProfile.CallWhenProfileChanges[ChangePrefix]; END. ͺIconsImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Plass, April 20, 1983 10:00 am Doug Wyatt, April 15, 1985 5:45:51 pm PST Russ Atkinson (RRA) May 6, 1986 11:12:57 pm PDT Global Icon variables Icon procedures Icon Manager (formerly IconManagerImpl) Initialization We do not handle FS.Error here because BootEssentials.df is supposed to have attached the local name to the correct place. Κ – "Mesa" style˜codešœ™Kšœ Οmœ7™BK™K™)K™/—˜šΟk ˜ Kšœžœ˜Kšœžœ ˜Kšžœžœ˜KšœžœL˜WKšœžœD˜PKšœžœ ˜ Kšœ žœ ˜0Kšžœžœžœ˜9Kšœžœ˜#Kšœžœ˜-Kšœžœ ˜Kšœžœžœ˜6Kšœžœ5˜BKšœ žœ5˜FKšœžœ5˜AKšœžœ"˜5Kšœ žœB˜QKšœžœ˜Kšœ žœ˜,Kšœžœ˜%——K˜šΠbl œžœž˜Kšžœ žœ&žœj˜₯Kšžœ˜Kšžœ˜ Kšœžœžœ˜K˜Kšžœžœžœ˜Kšžœžœžœžœ˜Kšœžœ˜$K˜—šœ™K˜Kšœžœ˜Kšœžœ˜K˜Kšœžœ˜Kšœžœ˜K˜šœžœžœ˜K˜—Kšœ žœ˜Kšœ žœžœžœ ˜1Kš œžœ žœ žœžœ˜1K˜K˜"K˜—šœ™K˜šΟnœžœžœ˜'Kšœ žœ˜Kšœžœ ˜'Kšœžœžœ˜šžœžœžœ˜Kšœ0žœg˜Ÿšžœžœ˜K˜Kšœ žœ˜Kšœžœ˜Kšœžœ˜(Kšœžœ˜Kš œ žœžœžœžœ˜šžœ1žœ˜9K˜K˜Kšœ žœ˜Kšœ˜—šžœ˜Kšœ˜K˜Kšœ(˜(K˜;Kšœ˜—KšœB˜BKšœ"˜"Kšžœžœ(˜Dš žœžœžœžœžœžœž˜>Kšœžœ˜K˜Kšœ˜K˜Kšœ˜Kšžœžœ˜%Kšžœ˜—Kšœ˜—Kšœ˜—Kšžœ-˜1Kšœ˜K˜—š œžœžœ˜Kšœ/˜/Kšœ+˜+Kšœ1˜1Kšœ/˜/Kšœ˜K˜—š  œ$˜0KšœSžœ˜XK˜K˜—š  œžœžœžœ˜GKš žœ žœžœžœžœ˜*Kšœžœ˜Kšœžœ˜Kšœ žœžœ˜š œžœžœžœžœžœžœ˜1Kš œžœžœ žœžœ˜:KšœžœΟc˜*Kšœžœ˜Kšžœ žœžœžœ žœžœžœžœžœ ˜Kšžœžœžœž˜Kšœžœ˜Kšœ"˜"Kš žœ žœžœžœžœžœ‘ ˜Mšžœž˜ Kšœ‘˜1Kš žœ žœ žœ žœ ‘˜QKšžœ˜—Kšžœžœ˜Kšžœ˜—Kšžœžœ;˜FK˜—šžœžœžœ˜ Kšœ žœ˜-Kšžœ2žœ žœ˜\K˜—š žœžœž œžœž˜(Kšžœžœ0žœ˜OKšžœ˜—Kšžœ˜Kšœ˜K˜—š  œžœžœžœ˜9K˜Kšœ žœ ˜Kš žœžœ žœžœžœ˜9Kšœ˜K˜—š œžœžœžœ˜HK˜Kšœžœ˜Kšœ˜K˜—š  œžœ žœžœžœ˜JKšœ‘ ˜%Kšœžœžœ%˜=Kšžœ"˜$šžœ˜ Kšœžœžœžœ˜/Kšœ žœžœžœ˜XKšžœžœžœžœ˜