-- File: SearchPathToolImpl.mesa - last edit: -- Breisacher.es 28-Jan-86 17:28:35 -- MEW 10-Apr-86 12:38:49 -- Copyright (C) 1985, 1986 by Xerox Corporation. All rights reserved. DIRECTORY Attention, BWSFileTypes, Catalog, Event, FormWindow, Heap USING [Create], MenuData USING [CreateItem, MenuProc], MFileOnNSFile, NSFile, NSString, OptionFile, PropertySheet, Selection, StarDesktop, Window, XString; SearchPathToolImpl: MONITOR IMPORTS Attention, Catalog, Event, FormWindow, Heap, MenuData, MFileOnNSFile, NSFile, NSString, OptionFile, PropertySheet, Selection, StarDesktop, XString = BEGIN -- TYPEs FormItems: TYPE = {add, path, name, remove}; firstElementItem: CARDINAL = FormItems.path.ORD; itemsPerElement: CARDINAL = FormItems.remove.ORD - FormItems.path.ORD + 1; << grunge - no way to associate clientData with a choice item, so I have to keep this data structure with the FormWindow - what a pain. >> RefsHandle: TYPE = LONG POINTER TO Refs; Refs: TYPE = LONG POINTER TO RefSeq; RefSeq: TYPE = RECORD [SEQUENCE l: CARDINAL OF NSFile.Reference]; -- Data zone: UNCOUNTED ZONE = Heap.Create [initial:1]; toolW: Window.Handle ← NIL; -- Procedures Init: PROC = { rb: XString.ReaderBody ← XString.FromSTRING["SearchPathTool"L]; Attention.AddMenuItem[MenuData.CreateItem[ zone: NIL, name: @rb, proc: MenuProc]]; IF UserIsLoggedOn[] THEN [] ← ReadOptionFile[StarDesktop.logon, NIL, NIL]; SetUpWaitForLogonEvent[]; }; MenuProc: MenuData.MenuProc = { rb: XString.ReaderBody ← XString.FromSTRING["SearchPathTool"L]; rb2: XString.ReaderBody ← XString.FromSTRING["SearchPathTool already open!"L]; IF toolW = NIL THEN toolW ← PropertySheet.Create [ formWindowItems: MakeItems, formWindowItemsLayout: DoLayout, menuItemProc: DoIt, size: [0,0], placeToDisplay: [300,300], title: @rb, display: TRUE, clientData: zone.NEW [Refs ← NIL]] ELSE Attention.Post[@rb2]; }; sysRef: NSFile.Reference ← GetSysRef[]; MakeItems: FormWindow.MakeItemsProc = { ith: CARDINAL ← 0; elements: CARDINAL ← 0; refs: RefsHandle ← clientData; Countem: MFileOnNSFile.EachElementProc = {elements ← elements + 1}; EachElement: MFileOnNSFile.EachElementProc = { MakeElementItems [ith, element, refs↑, window]; ith ← ith + 1; }; BEGIN rb: XString.ReaderBody ← XString.FromSTRING["Add An Element"L]; FormWindow.MakeCommandItem [ window: window, myKey: FormItems.add.ORD, commandName: @rb, commandProc: AddElement]; END; MFileOnNSFile.EnumeratePath [Countem]; refs↑ ← zone.NEW [RefSeq [elements]]; MFileOnNSFile.EnumeratePath [EachElement]; }; MakeElementItems: PROCEDURE [ith: CARDINAL, ref: NSFile.Reference, refs: Refs, window: Window.Handle] = { choices: ARRAY [0..3) OF FormWindow.ChoiceItem ← [ [string[0, XString.FromSTRING["Desktop"L]]], [string[1, XString.FromSTRING["SystemFolder"L]]], [string[2, XString.FromSTRING["Other Folder"L]]]]; desktop: NSFile.Reference ← StarDesktop.GetCurrentDesktopFile []; initChoice: CARDINAL = SELECT ref FROM desktop => 0, sysRef => 1, ENDCASE => 2; refs[ith] ← ref; FormWindow.MakeChoiceItem [ window: window, myKey: FormItems.path.ORD + (ith * itemsPerElement), values: DESCRIPTOR[choices], changeProc: ElementChanged, initChoice: initChoice]; BEGIN nameVisibility: FormWindow.Visibility = IF initChoice = 2 THEN visible ELSE invisible; fh: NSFile.Handle; initName: XString.Reader ← NIL; namerb: XString.ReaderBody; attrRec: NSFile.AttributesRecord; attrs: NSFile.Attributes ← NIL; IF nameVisibility = visible THEN { fh ← NSFile.OpenByReference [ref]; attrs ← @attrRec; NSFile.GetAttributes [fh, [[pathname: TRUE]], attrs]; namerb ← XString.FromNSString [attrs.pathname]; initName ← @namerb; NSFile.Close [fh]; }; FormWindow.MakeTextItem [ window: window, myKey: FormItems.name.ORD + (ith * itemsPerElement), width: 400, initString: initName, visibility: nameVisibility]; IF attrs # NIL THEN NSFile.ClearAttributes [attrs]; END; BEGIN rb: XString.ReaderBody ← XString.FromSTRING["Remove"L]; FormWindow.MakeCommandItem [ window: window, myKey: FormItems.remove.ORD + (ith * itemsPerElement), commandName: @rb, commandProc: RemoveElement]; END; }; LayoutElementItems: PROCEDURE [ith: CARDINAL, window: Window.Handle] = { spaceAboveLine: CARDINAL = 10; m: CARDINAL = 5; line: FormWindow.Line; line ← FormWindow.AppendLine [window, spaceAboveLine]; FormWindow.AppendItem [window, FormItems.path.ORD + (ith * itemsPerElement), line, m,,FALSE]; FormWindow.AppendItem [window, FormItems.remove.ORD + (ith * itemsPerElement), line, m,,FALSE]; line ← FormWindow.AppendLine [window, spaceAboveLine]; FormWindow.AppendItem [window, FormItems.name.ORD + (ith * itemsPerElement), line, m,,FALSE]; }; AddElement: FormWindow.CommandProc = { refs: RefsHandle ← FormWindow.GetClientData [window]; count: CARDINAL = (IF refs↑ = NIL THEN 0 ELSE refs.l); temp: Refs ← zone.NEW [RefSeq [count+1]]; FOR i: CARDINAL IN [0..count) DO temp[i] ← refs[i]; ENDLOOP; zone.FREE [refs]; -- not @refs! refs↑ ← temp; MakeElementItems [ith: count, ref: sysRef, refs: refs↑, window: window]; LayoutElementItems [count, window]; FormWindow.Repaint [window]; }; RemoveElement: FormWindow.CommandProc = { refs: RefsHandle ← FormWindow.GetClientData [window]; count: CARDINAL = refs.l; temp: Refs ← zone.NEW [RefSeq [count-1]]; rb: XString.ReaderBody; elementToRemove: CARDINAL = (item - firstElementItem)/itemsPerElement; FOR i: CARDINAL IN [0..elementToRemove) DO temp[i] ← refs[i]; ENDLOOP; FOR i: CARDINAL IN [elementToRemove+1..count-1) DO temp[i-1] ← refs[i]; ENDLOOP; zone.FREE [refs]; -- not @refs! refs↑ ← temp; FormWindow.SetChoiceItemValue [window: window, item: item-2, newValue: FormWindow.GetChoiceItemValue [window, FormItems.path.ORD + ((count-1) * itemsPerElement)], repaint: FALSE]; rb ← FormWindow.LookAtTextItemValue [window, FormItems.name.ORD + ((count-1) * itemsPerElement)]; FormWindow.SetTextItemValue [window: window, item: item-1, newValue: @rb, repaint: FALSE]; FormWindow.DoneLookingAtTextItemValue [window, FormItems.name.ORD + ((count-1) * itemsPerElement)]; FormWindow.DestroyItem [window, FormItems.path.ORD + ((count-1) * itemsPerElement), FALSE]; -- path FormWindow.DestroyItem [window, FormItems.name.ORD + ((count-1) * itemsPerElement), FALSE]; -- name FormWindow.DestroyItem [window, FormItems.remove.ORD + ((count-1) * itemsPerElement), FALSE]; -- me FormWindow.Repaint [window]; }; ElementChanged: FormWindow.ChoiceChangeProc = { refs: RefsHandle ← FormWindow.GetClientData [window]; ith: CARDINAL = (item - firstElementItem)/itemsPerElement; IF calledBecauseOf = client THEN RETURN; SELECT newValue FROM 0 => { refs[ith] ← StarDesktop.GetCurrentDesktopFile []; IF oldValue = 2 THEN FormWindow.SetVisibility [window, item+1, invisible]}; 1 => { refs[ith] ← sysRef; IF oldValue = 2 THEN FormWindow.SetVisibility [window, item+1, invisible]}; ENDCASE => { v: Selection.Value; ref: LONG POINTER TO NSFile.Reference; namerb: XString.ReaderBody; attrRec: NSFile.AttributesRecord; fh: NSFile.Handle; Complain: PROCEDURE = { rb: XString.ReaderBody ← XString.FromSTRING ["Please select a folder before bugging ""Other Folder"""L]; Attention.Post [@rb]; FormWindow.SetChoiceItemValue [window, item, oldValue]; }; IF ~Selection.CanYouConvert [file] THEN {Complain[]; RETURN}; v ← Selection.Convert [file]; IF v.value = NIL THEN {Complain[]; Selection.Free [@v]; RETURN}; ref ← v.value; refs[ith] ← ref↑; fh ← NSFile.OpenByReference [ref↑]; NSFile.GetAttributes [fh, [[pathname: TRUE]], @attrRec]; namerb ← XString.FromNSString [attrRec.pathname]; NSFile.ClearAttributes [@attrRec]; NSFile.Close [fh]; FormWindow.SetTextItemValue [window, item+1, @namerb, FALSE]; FormWindow.SetVisibility [window, item+1, visible]; Selection.Free [@v]; }; }; DoLayout: FormWindow.LayoutProc = { ith: CARDINAL ← 0; tabChoice: fixed FormWindow.TabStops = [fixed[50]]; spaceAboveLine: CARDINAL = 10; m: CARDINAL = 5; line: FormWindow.Line; EachElement: MFileOnNSFile.EachElementProc = { LayoutElementItems [ith, window]; ith ← ith + 1; }; FormWindow.SetTabStops[window: window, tabStops: tabChoice]; line ← FormWindow.AppendLine [window, spaceAboveLine]; FormWindow.AppendItem [window, FormItems.add.ORD, line, m]; MFileOnNSFile.EnumeratePath [EachElement]; }; DoIt: PropertySheet.MenuItemProc = { refs: RefsHandle ← clientData; toolW ← NIL; IF menuItem = done THEN MFileOnNSFile.SetPath [DESCRIPTOR[refs] ! MFileOnNSFile.BadPath => GOTO NoGood]; zone.FREE [refs]; zone.FREE [@refs]; RETURN[ok: TRUE]; EXITS NoGood => { rb: XString.ReaderBody ← XString.FromSTRING ["Bad path"L]; Attention.Post [@rb]; RETURN [ok: FALSE]}; }; GetSysRef: PROCEDURE RETURNS [ref: NSFile.Reference] = { fh: NSFile.Handle ← Catalog.Open [BWSFileTypes.systemFileCatalog]; ref ← NSFile.GetReference [fh]; NSFile.Close [fh]; }; UserIsLoggedOn: PROCEDURE RETURNS [BOOLEAN] = { RETURN[StarDesktop.GetCurrentDesktopFile[] # NSFile.nullReference]}; SetUpWaitForLogonEvent: PROCEDURE = { [] ← Event.AddDependency [ReadOptionFile, NIL, StarDesktop.logon]}; ReadOptionFile: Event.AgentProcedure = { section: XString.ReaderBody ← XString.FromSTRING ["SearchPath"L]; entry: XString.ReaderBody ← XString.FromSTRING ["Element"L]; elements: CARDINAL ← 0; LocalSeq: TYPE = RECORD [SEQUENCE COMPUTED CARDINAL OF NSFile.Reference]; refs: LONG POINTER TO LocalSeq ← NIL; fh: NSFile.Handle; nssElement: NSString.String; Countem: PROCEDURE [element: XString.Reader] = { elements ← elements + 1}; EachElement: PROCEDURE [element: XString.Reader] = { nssElement ← XString.NSStringFromReader [element, zone]; fh ← NSFile.OpenByName [NSFile.nullHandle, nssElement ! NSFile.Error => GOTO BadElement]; refs[elements] ← NSFile.GetReference [fh]; NSFile.Close [fh]; NSString.FreeString [zone, nssElement]; elements ← elements + 1; EXITS BadElement => { rb: XString.ReaderBody ← XString.FromSTRING ["Bad element in UserProfile: "L]; Attention.Post[@rb]; Attention.Post[element, FALSE]; NSString.FreeString [zone, nssElement]}; }; -- Sorta grungy, but easy. Go through elements once just to count them. DO OptionFile.GetStringValue [@section, @entry, Countem, elements ! OptionFile.Error => EXIT]; ENDLOOP; IF elements = 0 THEN { refs ← zone.NEW[LocalSeq[1]]; refs[0] ← StarDesktop.GetCurrentDesktopFile[]; elements ← 1 } ELSE { refs ← zone.NEW[LocalSeq[elements]]; -- Now again to get the values. elements ← 0; DO OptionFile.GetStringValue [@section, @entry, EachElement, elements ! OptionFile.Error => EXIT]; ENDLOOP; }; MFileOnNSFile.SetPath [DESCRIPTOR[refs, elements] ! MFileOnNSFile.BadPath => { rb: XString.ReaderBody ← XString.FromSTRING ["Bad path"L]; Attention.Post [@rb]; CONTINUE}]; zone.FREE [@refs]; }; -- Main line code Init[]; END.