-- 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.