DIRECTORY Font, FS USING [Close, Error, Open, GetInfo, OpenFile, Read], Imager, ImagerOps, Icons, Rope USING [Fetch, Length, ROPE, Run], UserProfile USING [CallWhenProfileChanges, ProfileChangedProc, Token], VFonts USING [EstablishFont, Font, FontAscent], ViewerExtras USING [ImagerFont], VM USING [Interval, Allocate, AddressForPageNumber, Free, wordsPerPage]; IconsImpl: CEDAR MONITOR IMPORTS Font, FS, Imager, ImagerOps, Rope, UserProfile, VFonts, VM EXPORTS Icons = BEGIN OPEN Icons; ROPE: TYPE = Rope.ROPE; DrawIcon: PUBLIC ENTRY DrawIconProc = { imager: Imager.Context ~ ImagerOps.ImagerFromGraphics[context]; leading: INTEGER = 3; iconInfo: IconRef _ icons[LOOPHOLE[flavor]]; prefix: ROPE _ NIL; IF iconInfo.proc=NIL THEN { IF iconInfo.label THEN { iconFont: Font.FONT; fontHeight: INTEGER; pos: Imager.VEC _ [x+iconInfo.lx, y+iconInfo.ly+iconInfo.lh]; indent: REAL _ 0; map: MapType ~ { pos.y _ pos.y-fontHeight; Imager.SetXY[imager, pos]; pos.y _ pos.y-leading; Imager.ShowRope[imager, rope, start, len]; pos.x _ pos.x+indent; indent _ 0; }; IF Font.RopeWidth[bigIconFont, label].x <= iconInfo.lw THEN { iconFont _ bigIconFont; fontHeight _ bigFontHeight; } ELSE { iconFont _ smallIconFont; fontHeight _ smallFontHeight; indent _ Font.CharWidth[iconFont, ' ].x; }; Imager.ClipRectangle[imager, pos.x, pos.y, iconInfo.lw, -iconInfo.lh]; Imager.SetFont[imager, iconFont]; IF iconInfo.invertLabel THEN Imager.SetColor[imager, Imager.white]; IF iconFont=bigIconFont THEN map[label, 0, INT.LAST] ELSE Decompose[label, iconInfo.lw, indent, iconFont, map]; }; } ELSE iconInfo.proc[flavor, context, x, y, label]; }; GetFonts: ENTRY PROC = { bigFont: VFonts.Font _ VFonts.EstablishFont["Helvetica", 8]; smallFont: VFonts.Font _ VFonts.EstablishFont["Helvetica", 7]; bigFontHeight _ VFonts.FontAscent[bigFont]; smallFontHeight _ VFonts.FontAscent[smallFont]; bigIconFont _ ViewerExtras.ImagerFont[bigFont]; smallIconFont _ ViewerExtras.ImagerFont[smallFont]; }; bigIconFont: Font.FONT; bigFontHeight: INTEGER; smallIconFont: Font.FONT; smallFontHeight: INTEGER; suppressIconPrefix: ROPE _ NIL; ChangePrefix: UserProfile.ProfileChangedProc ~ { suppressIconPrefix _ UserProfile.Token[key: "Viewers.SuppressIconPrefix", default: NIL]; }; MapType: TYPE ~ PROC[rope: ROPE, start, len: INT]; Decompose: PROC[name: ROPE, width, indent: REAL, font: Font.FONT, map: MapType] = { start: INT _ 0; stop: INT _ name.Length[]; extensionStart, extensionLen: INT _ 0; Build: PROC[start: INT] ~ { maxw: REAL _ (IF start=0 THEN width ELSE width-indent); sw: REAL _ 0; -- width of string so far next: INT _ -1; FOR i: INT IN[start..stop) DO c: CHAR ~ name.Fetch[i]; sw _ sw+Font.CharWidth[font, c].x; 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; IF next>start THEN map[name, start, next-start]; IF next0 THEN map[name, extensionStart, extensionLen]; }; 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 { extensionStart _ i; extensionLen _ stop-i; stop _ i; EXIT }; ENDLOOP; Build[start]; }; iconBitmap: REF; maxIcons: CARDINAL = 64; IconArray: TYPE = ARRAY [0..maxIcons) OF IconRef; icons: REF IconArray _ NEW[IconArray _ ALL[NIL]]; nextFlavor: IconFlavor _ document; 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[LOOPHOLE[newFlavor]] _ info; }; IconsFromFile: PROC [file: ROPE] RETURNS [first: IconFlavor, nRead: INTEGER] = TRUSTED { fh: FS.OpenFile _ FS.Open[file]; pages: INT _ FS.GetInfo[fh].pages; space: VM.Interval _ VM.Allocate[count: pages]; iconBase: LONG POINTER TO IconFileFormat _ VM.AddressForPageNumber[space.page]; FS.Read[file: fh, from: 0, nPages: pages, to: iconBase]; first _ nextFlavor; nRead _ pages/(SIZE[IconFileFormat]/VM.wordsPerPage); FOR n: INTEGER IN [0..nRead) DO [] _ NewIcon[NEW[IconRep _ [iconBase.bits, iconBase.label, iconBase.invertLabel, 0--filler--, iconBase.lx, iconBase.ly, iconBase.lw, iconBase.lh]]]; iconBase _ iconBase+SIZE[IconFileFormat]; ENDLOOP; VM.Free[space]; FS.Close[fh]; }; NewIconFromFile: PUBLIC PROC [file: ROPE, n: CARDINAL] RETURNS [newFlavor: IconFlavor] = TRUSTED { fh: FS.OpenFile _ FS.Open[file]; pages: INT _ FS.GetInfo[fh].pages; space: VM.Interval _ VM.Allocate[count: pages]; iconBase: LONG POINTER TO IconFileFormat _ VM.AddressForPageNumber[space.page]; FS.Read[file: fh, from: 0, nPages: pages, to: iconBase]; iconBase _ iconBase + (n*SIZE[IconFileFormat]); newFlavor _ NewIcon[NEW[IconRep _ [iconBase.bits, iconBase.label, iconBase.invertLabel, 0--filler--, iconBase.lx, iconBase.ly, iconBase.lw, iconBase.lh]]]; VM.Free[space]; FS.Close[fh]; }; {-- 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 1982, 1983, 1984 Xerox Corporation. All rights reserved. McGregor on October 20, 1982 4:28 pm Maxwell, January 3, 1983 12:53 pm Plass, April 20, 1983 10:00 am Paul Rovner, August 10, 1983 3:59 pm Russ Atkinson, November 16, 1983 7:19 pm (changed opening of Standard.icons to only use local name, also changed the global variable icons to be a REF to an array, instead of taking 128 words in the global frame!) Doug Wyatt, January 12, 1984 4:17 pm (rewrote Decompose) Doug Wyatt, July 30, 1984 11:23:15 am PDT (added Viewers.SuppressIconPrefix feature) Doug Wyatt, September 4, 1984 3:22:14 pm PDT (converted to Imager) PROC[flavor: IconFlavor, context: Graphics.Context, x, y: INTEGER _ 0, label: ROPE _ NIL] iconBitmap.base _ iconInfo; -- bits guaranteed first in record!!! ImagerOps.DrawBitmap[context, iconBitmap, x, y]; wSlop: INTEGER = 1; OldDecompose: PROC [name: ROPE, width: REAL, font: Graphics.FontRef] RETURNS [segments: LIST OF ROPE _ NIL] = { end: INT _ 0; len: INT _ Rope.Length[name]; haveExtension, inWord: BOOL _ FALSE; SkipToNextWord: PROC [c: CHAR] RETURNS [BOOL] = CHECKED { IF c IN ['A..'Z] OR c = '> OR c IN ['0..'9] THEN { IF inWord THEN RETURN[TRUE] } ELSE inWord _ TRUE; IF c='. THEN RETURN[haveExtension _ TRUE]; end _ end+1; RETURN[FALSE]; }; Build: PROC[start: INT] RETURNS [LIST OF ROPE] = { IF start>=len THEN RETURN[NIL]; end _ start+1; inWord _ FALSE; IF haveExtension THEN end _ len ELSE [] _ Rope.Map[base: name, start: end, action: SkipToNextWord]; RETURN[CONS[name.Substr[start, end-start], Build[end]]]; }; Coalesce: PROC[segs: LIST OF ROPE] RETURNS [LIST OF ROPE] = { c: ROPE; IF segs=NIL OR segs.rest=NIL THEN RETURN[segs]; IF segs.rest.first.Fetch[0]#'. AND Graphics.RopeWidth[font, c _ segs.first.Concat[segs.rest.first]].xw<=width THEN RETURN[Coalesce[CONS[c, segs.rest.rest]]]; RETURN[CONS[segs.first, Coalesce[segs.rest]]]; }; width _ width+wSlop; -- allow small amount of clipping. RETURN[Coalesce[Build[0]]]; }; _ NEW[GraphicsOps.BitmapRep _ [NIL, iconW/16, iconW, iconH]]; We do not handle FS.Error here because BootEssentials.df is supposed to have attached the local name to the correct place. Κ `– "Mesa" style˜šΟc™Jšœ Οmœœ5™EJš$™$J™!J™J™$™(JšœjΟkœ?™¬—™$Jšœ™—™)Jšœ*™*—™,Jšœ™——J˜šŸ ˜ Jšœ˜JšŸœŸœ/˜7Jšœ˜Jšœ ˜ J˜JšœŸœŸœ˜&Jšœ Ÿœ5˜FJšœŸœ#˜/Jšœ Ÿœ˜ JšŸœŸœ@˜HJ˜—Jšœ Ÿ ˜JšŸœŸœ0Ÿ˜BJšŸœ˜ JšœŸœŸœ˜J˜JšŸœŸœŸœ˜J˜šœ ŸœŸœ˜'JšŸœ6Ÿœ ŸœŸœ™YJ˜?Jšœ Ÿœ˜JšœŸœ ˜,JšœŸœŸœ˜šŸœŸœŸœ˜Jšœ%™AJ™0šŸœŸœ˜JšœŸœ˜Jšœ Ÿœ˜Jšœ Ÿœ.˜=JšœŸœ˜˜J˜J˜J˜J˜*J˜!J˜—šŸœ5Ÿœ˜=J˜J˜Jšœ˜—šŸœ˜J˜J˜Jšœ(˜(Jšœ˜—JšœF˜FJ˜!JšŸœŸœ'˜CJšŸœŸœŸœŸœ˜4JšŸœ6˜:Jšœ˜—Jšœ˜—JšŸœ-˜1Jšœ˜J˜—šΟnœŸœŸœ˜J˜J˜+J˜/J˜/J˜3Jšœ˜J˜—JšœŸœ˜JšœŸœ˜J˜JšœŸœ˜JšœŸœ˜J˜JšœŸœŸœ˜J˜˜0JšœSŸœ˜XJ˜J˜—Jš  œŸœŸœŸœŸœ˜2J˜š   œŸœŸœŸœ Ÿœ˜SJšœŸœ˜JšœŸœ˜JšœŸœ˜&š œŸœŸœ˜Jš œŸœŸœ ŸœŸœ˜7JšœŸœ˜'JšœŸœ˜šŸœŸœŸœŸ˜JšœŸœ˜Jšœ"˜"Jš Ÿœ ŸœŸœŸœŸœŸœ ˜MšŸœŸ˜ Jšœ˜1Jš Ÿœ Ÿœ Ÿœ Ÿœ ˜QJšŸœ˜—JšŸœŸœ˜JšŸœ˜—JšŸœ Ÿœ˜0JšŸœ Ÿœ ˜JšŸœŸœŸœ)˜DJ˜—šŸœŸœŸœ˜ Jšœ Ÿœ˜-JšŸœ2Ÿœ Ÿœ˜\J˜—š ŸœŸœŸ œŸœŸ˜(JšŸœŸœ8Ÿœ˜WJšŸœ˜—Jšœ ˜ Jšœ˜J˜—JšœŸœ™š  œŸœŸœ Ÿœ™DJš Ÿœ ŸœŸœŸœŸœ™(Jšœ™JšœŸœ™ JšœŸœ™JšœŸœŸœ™$š  œŸœŸœŸœŸœŸœ™9JšŸœŸœ ŸœŸœŸœ ŸœŸœŸœŸœŸœ™PJšŸœ Ÿœ™JšŸœŸœŸœŸœ™*Jšœ ŸœŸœ™—š œŸœŸœŸœŸœŸœŸœ™2JšŸœ ŸœŸœŸœ™J™Jšœ Ÿœ™JšŸœŸœ ™JšŸœ?™CJšŸœŸœ0™;—š œŸœŸœŸœŸœŸœŸœŸœŸœ™=JšœŸœ™Jš ŸœŸœŸœ ŸœŸœŸœ™/šŸœŸ™"J™J—JšŸœŸœ Ÿœ™/JšŸœŸœ&™1—Jšœ"™7JšŸœ™Jšœ™J™—šœ Ÿœ˜JšœŸœŸœ™=—J˜Jšœ Ÿœ˜Jšœ ŸœŸœŸœ ˜1Jš œŸœ Ÿœ ŸœŸœ˜1J˜J˜"š  œŸœŸœŸœ˜9J˜Jšœ Ÿœ ˜Jš ŸœŸœ ŸœŸœŸœ˜9Jšœ˜J˜—š œŸœŸœŸœ˜HJ˜JšœŸœ˜"Jšœ˜J˜—š   œŸœŸœŸœŸœ˜NJšŸœ˜ JšœŸœ Ÿœ ˜ JšœŸœ˜"Jšœ/˜/Jšœ ŸœŸœŸœ6˜OJšŸœ6˜8J˜JšœŸœ"˜5šŸœŸœŸœ Ÿ˜šœ Ÿœ@˜PJšœ œ8˜C—JšœŸœ˜)JšŸœ˜—J˜JšŸœ ˜ Jšœ˜J˜—š  œŸœŸœŸœŸœ˜6JšŸœ˜!JšŸœ˜ JšœŸœ Ÿœ ˜ JšœŸœ˜"Jšœ/˜/Jšœ ŸœŸœŸœ6˜OJšŸœ6˜8JšœŸœ˜/šœŸœ@˜WJšœ œ8˜C—J˜JšŸœ ˜ Jšœ˜J˜—šœ1˜2JšœŸœŸœ˜J˜ šœ#˜#Jš œŸœ ŸœŸœŸœŸœ˜@—šŸœŸœŸœ*˜8Jšœz™z—J˜J˜—J˜1J˜JšŸœ˜J˜J˜—…—ˆ'j