DIRECTORY Atom USING [GetPName, MakeAtom], Buttons USING [Button, ButtonProc, Create, SetDisplayStyle], ChoiceButtons USING [ChoiceDoesntExist, EnumTypeRef, BuildEnumTypeSelection, GetSelectedButton, UpdateChoiceButtons], Containers USING [ ChildXBound, ChildYBound, Container, Create ], Icons USING [ IconFlavor, NewIconFromFile ], IO USING [atom, STREAM, PutRope, PutFR, real, RIS, RopeFromROS, rope, ROS], Labels USING [Create, Label, Set], LoganBerry USING [AttributeType, AttributeValue, BuildIndices, Close, CompactLogs, DeleteEntry, Describe, Entry, Error, ErrorCode, IndexInfo, nullDB, Open, OpenDB, SchemaInfo, WriteEntry], LoganQuery USING [AbortQuery, AttributePattern, AttributePatternRec, AttributePatterns, BooleanFilterEntries, Cursor, EndGenerate, NextEntry, ParseBooleanQuery, ParseTree, PatternsToEntry, QueryEntries, QueryPlan, ReadAttributePatterns, WriteAttributePatterns, SyntaxError], LoganQueryClass USING [MergeEntries], Menus USING [AppendMenuEntry, ChangeNumberOfLines, ClickProc, CreateEntry, CreateMenu, GetNumberOfLines, Menu, MenuLine], MessageWindow USING [Append, Blink], PatternMatch USING [EachPairAction, Pairs], RefTab USING [Ref, EachPairAction, Fetch, Pairs, Create, Store], Rope USING [Concat, Equal, IsEmpty, Length, SkipTo, Substr, ROPE], Rules USING [ Create, Rule ], TiogaButtons USING [CreateButton, CreateViewer, TiogaButtonProc], TypeScript USING [ Create, ChangeLooks, PutChar, PutRope ], ViewerBLT USING [ChangeNumberOfLines], ViewerClasses USING [ Viewer, <> ViewerFlavor, ViewerRec ], ViewerEvents USING [ EventProc, RegisterEventProc ], ViewerOps USING [AddProp, CreateViewer, MoveViewer, PaintViewer], ViewerTools USING [GetContents, MakeNewTextViewer, SetContents, SetSelection], LoganBerryBrowser; LoganBerryBrowserImpl: CEDAR PROGRAM IMPORTS Atom, Buttons, ChoiceButtons, Containers, Icons, IO, Labels, LoganBerry, LoganQuery, LoganQueryClass, Menus, MessageWindow, PatternMatch, RefTab, Rope, Rules, TiogaButtons, TypeScript, ViewerBLT, ViewerEvents, ViewerOps, ViewerTools EXPORTS LoganBerryBrowser = BEGIN ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; Viewer: TYPE = ViewerClasses.Viewer; BrowserTool: TYPE = LoganBerryBrowser.Tool; DBList: TYPE = LIST OF LoganBerryBrowser.DBInfo; DisplayProc: TYPE = LoganBerryBrowser.DisplayProc; FormField: TYPE = REF FormFieldRec; FormFieldRec: TYPE = RECORD [ textViewer: Viewer, patternButton: ChoiceButtons.EnumTypeRef, feedbackArea: Labels.Label ]; HistoryData: TYPE = REF HistoryDataRec; HistoryDataRec: TYPE = RECORD [ tool: BrowserTool, cmd: ROPE, form: LoganQuery.AttributePatterns, other: ROPE ]; browserIcon: Icons.IconFlavor ¬ tool; itemHeight: CARDINAL = 14; interItemHeight: CARDINAL = 3; ruleHeight: CARDINAL = 1; patternButtonWidth: CARDINAL = 100; patternHSpace: CARDINAL = 5; feedbackHSpace: CARDINAL = 350; historyHeight: CARDINAL = 100; defaultPattern: ROPE ¬ "DWIM"; MakeEntryForm: PROC [tool: BrowserTool] RETURNS [] ~ { AddPattern: PatternMatch.EachPairAction ~ { patternChoices ¬ CONS[name, patternChoices]; }; patternChoices: LIST OF ROPE ¬ LIST["DWIM"]; prompt: Viewer; [] ¬ PatternMatch.Pairs[AddPattern]; tool.entryform ¬ RefTab.Create[]; FOR k: LIST OF LoganBerry.AttributeType ¬ tool.fields, k.rest WHILE k # NIL DO field: FormField ¬ NEW[FormFieldRec]; field.patternButton ¬ ChoiceButtons.BuildEnumTypeSelection[viewer: tool.details, x: patternHSpace, y: tool.height, buttonNames: patternChoices, default: defaultPattern, style: flipThru, maxWidth: patternButtonWidth]; prompt ¬ Buttons.Create[info: [name: Rope.Concat[Atom.GetPName[k.first], ":"], wx: field.patternButton.nextx, wy: tool.height, parent: tool.outer, scrollable: FALSE, border: FALSE], proc: SelectTextField, clientData: field]; field.textViewer ¬ ViewerTools.MakeNewTextViewer[info: [wx: prompt.wx + prompt.ww + patternHSpace, wy: tool.height, wh: itemHeight, ww: 9999, parent: tool.outer, scrollable: FALSE, border: FALSE]]; Containers.ChildXBound[container: tool.outer, child: field.textViewer]; field.feedbackArea ¬ Labels.Create[info: [parent: tool.details, wx: feedbackHSpace, wy: tool.height, ww: 9999, wh: 0, border: FALSE, scrollable: FALSE]]; tool.height ¬ tool.height + itemHeight + interItemHeight; [] ¬ RefTab.Store[tool.entryform, k.first, field]; ENDLOOP; IF tool.wantInputArea THEN { prompt ¬ Buttons.Create[info: [name: "other attributes:", wx: patternHSpace, wy: tool.height, parent: tool.outer, scrollable: TRUE, border: FALSE], proc: SelectInputArea, clientData: tool]; tool.inputArea ¬ ViewerTools.MakeNewTextViewer[info: [wx: prompt.wx + prompt.ww + patternHSpace, wy: tool.height, wh: itemHeight, ww: 9999, parent: tool.outer, border: FALSE]]; Containers.ChildXBound[container: tool.outer, child: tool.inputArea]; tool.height ¬ tool.height + itemHeight + interItemHeight; }; }; SelectTextField: Buttons.ButtonProc = { field: FormField = NARROW[clientData]; ViewerTools.SetSelection[field.textViewer, NIL]; }; SelectInputArea: Buttons.ButtonProc = { tool: BrowserTool = NARROW[clientData]; ViewerTools.SetSelection[tool.inputArea, NIL]; }; MakeDatabaseButton: PROC [tool: BrowserTool] RETURNS [] ~ { button: Buttons.Button; xpos: INT ¬ 0; IF tool.databases.rest = NIL THEN RETURN; -- only a single database to choose from so don't need selection buttons button ¬ Labels.Create[info: [name: "Databases: ", wx: xpos, wy: tool.height, parent: tool.details, scrollable: FALSE, border: FALSE]]; FOR d: DBList ¬ tool.databases, d.rest WHILE d#NIL DO xpos ¬ xpos + button.ww; button ¬ Buttons.Create[ info: [name: d.first.shortname, wx: xpos, wy: tool.height, parent: tool.details, border: TRUE], proc: ToggleDatabaseButton, fork: FALSE, paint: FALSE, clientData: d.first ]; Buttons.SetDisplayStyle[button, IF d.first.selected THEN $WhiteOnBlack ELSE $BlackOnWhite]; ENDLOOP; tool.height ¬ tool.height + itemHeight + interItemHeight; }; ToggleDatabaseButton: Buttons.ButtonProc ~ { db: LoganBerryBrowser.DBInfo = NARROW [clientData]; db.selected ¬ NOT db.selected; Buttons.SetDisplayStyle[parent, IF db.selected THEN $WhiteOnBlack ELSE $BlackOnWhite]; }; MakeSortButton: PROC [tool: BrowserTool] RETURNS [] ~ { choices: LIST OF ROPE ¬ NIL; IF NOT tool.wantSortButton THEN RETURN; FOR i: LIST OF LoganBerry.IndexInfo ¬ tool.databases.first.schema.indices, i.rest WHILE i#NIL DO choices ¬ CONS[Atom.GetPName[i.first.key], choices]; ENDLOOP; choices ¬ CONS["ANY", choices]; tool.height ¬ tool.height + interItemHeight; tool.sortButton ¬ ChoiceButtons.BuildEnumTypeSelection[viewer: tool.details, x: patternHSpace, y: tool.height, title: "Order by:", buttonNames: choices, default: "ANY", style: menuSelection --vs. flipThru--]; tool.queryFeedback ¬ Labels.Create[info: [parent: tool.details, wx: MAX[tool.sortButton.nextx, feedbackHSpace], wy: tool.height, ww: 9999, wh: 0, border: FALSE, scrollable: FALSE]]; tool.height ¬ tool.height + itemHeight + interItemHeight; }; ReadEntryForm: PUBLIC PROC [tool: BrowserTool] RETURNS [form: LoganQuery.AttributePatterns, other: Rope.ROPE, orderBy: LoganBerry.AttributeType] ~ { NextField: RefTab.EachPairAction = { text: ROPE; label: ATOM = NARROW[key]; field: FormField = NARROW[val]; text ¬ ViewerTools.GetContents[field.textViewer]; IF NOT Rope.Equal[text, ""] THEN { fv: LoganQuery.AttributePattern ¬ NEW[LoganQuery.AttributePatternRec]; fv.attr.type ¬ label; fv.attr.value ¬ text; fv.ptype ¬ ChoiceButtons.GetSelectedButton[field.patternButton]; IF form=NIL THEN form ¬ end ¬ LIST[fv] ELSE {end.rest ¬ LIST[fv]; end ¬ end.rest;}; }; Labels.Set[field.feedbackArea, NIL]; RETURN[quit: FALSE]; }; end, otherPatterns: LoganQuery.AttributePatterns; form ¬ NIL; [] ¬ RefTab.Pairs[tool.entryform, NextField]; other ¬ ViewerTools.GetContents[tool.inputArea]; AddToHistory[tool, form, other]; orderBy ¬ Atom.MakeAtom[ChoiceButtons.GetSelectedButton[tool.sortButton]]; IF orderBy = $ANY THEN orderBy ¬ NIL; Labels.Set[tool.queryFeedback, NIL]; }; RestoreEntryForm: PUBLIC PROC [tool: BrowserTool, form: LoganQuery.AttributePatterns, other: ROPE] RETURNS [] ~ { RestoreField: RefTab.EachPairAction = { label: ATOM = NARROW[key]; field: FormField = NARROW[val]; f: LoganQuery.AttributePatterns; FOR f ¬ form, f.rest WHILE f # NIL DO IF f.first.attr.type = label THEN EXIT; ENDLOOP; IF f # NIL THEN { ChoiceButtons.UpdateChoiceButtons[tool.details, field.patternButton, f.first.ptype ! ChoiceButtons.ChoiceDoesntExist => CONTINUE]; ViewerTools.SetContents[field.textViewer, f.first.attr.value, FALSE]; } ELSE { ViewerTools.SetContents[field.textViewer, "", FALSE]; }; Labels.Set[field.feedbackArea, NIL, FALSE]; RETURN[quit: FALSE]; }; ChoiceButtons.UpdateChoiceButtons[tool.details, tool.sortButton, Atom.GetPName[form.first.attr.type] ! ChoiceButtons.ChoiceDoesntExist => CONTINUE]; Labels.Set[tool.queryFeedback, NIL, FALSE]; [] ¬ RefTab.Pairs[tool.entryform, RestoreField]; ViewerTools.SetContents[tool.inputArea, other, FALSE]; ViewerOps.PaintViewer[viewer: tool.outer, hint: all]; }; ReportFeedback: PUBLIC PROC [plan: LoganQuery.QueryPlan, tool: BrowserTool] RETURNS [] ~ { Labels.Set[tool.queryFeedback, IO.PutFR["(%g - %3.2f)", IO.atom[plan.first.attr.type], IO.real[plan.first.cost]]]; FOR p: LoganQuery.QueryPlan ¬ plan, p.rest WHILE p # NIL DO ff: FormField ¬ NARROW[RefTab.Fetch[tool.entryform, p.first.attr.type].val]; IF ff#NIL THEN Labels.Set[ff.feedbackArea, IO.PutFR["%g(%g)", IO.rope[p.first.errMsg], IO.rope[p.first.infoMsg]]]; ENDLOOP; }; AppendPatterns: PROC [p1, p2: LoganQuery.AttributePatterns] RETURNS [LoganQuery.AttributePatterns] ~ { temp: LoganQuery.AttributePatterns ¬ p1; IF p1 = NIL THEN RETURN[p2]; UNTIL temp.rest = NIL DO temp ¬ temp.rest ENDLOOP; temp.rest ¬ p2; RETURN[p1]; }; AddToHistory: PUBLIC PROC [tool: BrowserTool, form: LoganQuery.AttributePatterns, other: ROPE] RETURNS [] ~ { data: HistoryData = NEW[HistoryDataRec ¬ [tool, NIL, form, other]]; line: STREAM ¬ IO.ROS[]; LoganQuery.WriteAttributePatterns[line, form]; IO.PutRope[line, " "]; IO.PutRope[line, other]; [] ¬ TiogaButtons.CreateButton[viewer: tool.history, rope: IO.RopeFromROS[line], proc: HistoryButtonProc, clientData: data]; }; HistoryButtonProc: TiogaButtons.TiogaButtonProc = { data: HistoryData ¬ NARROW[clientData]; RestoreEntryForm[data.tool, data.form, data.other]; }; DividingLine: PROC [tool: BrowserTool] RETURNS [] ~ { rule: Rules.Rule; rule ¬ Rules.Create[info: [parent: tool.outer, wx: 0, wy: tool.height, ww: 9999, wh: ruleHeight]]; Containers.ChildXBound[tool.outer, rule]; -- constrain rule to be width of parent tool.height ¬ tool.height + ruleHeight; }; HideViewer: PROC [v: Viewer] RETURNS [] ~ { ViewerOps.MoveViewer[viewer: v, x: 2000, y: v.wy, w: v.ww, h: v.wh]; }; UnHideViewer: PROC [v: Viewer] RETURNS [] ~ { ViewerOps.MoveViewer[viewer: v, x: 0, y: v.wy, w: v.ww, h: v.wh]; }; ResetViewer: PROC [v: Viewer] RETURNS [] ~ { v.class.init[v]; }; CreateTool: PUBLIC PROC [db: LoganBerry.OpenDB ¬ LoganBerry.nullDB, tool: BrowserTool] = { innerInfo: ViewerClasses.ViewerRec; IF db#LoganBerry.nullDB THEN tool.databases ¬ LIST[NEW[LoganBerryBrowser.DBInfoRec ¬ [db: db]]]; IF tool.databases = NIL THEN { MessageWindow.Append[message: "No LoganBerry database specified to browse!", clearFirst: TRUE]; RETURN; }; FOR d: DBList ¬ tool.databases, d.rest WHILE d#NIL DO prev, loc: INT ¬ 1; d.first.schema ¬ LoganBerry.Describe[db: d.first.db]; WHILE loc < Rope.Length[d.first.schema.dbName] DO prev ¬ loc; loc ¬ Rope.SkipTo[s: d.first.schema.dbName, pos: prev+1, skip: "/>]"]; ENDLOOP; d.first.shortname ¬ Rope.Substr[base: d.first.schema.dbName, start: prev+1]; ENDLOOP; SetDefaults[tool]; tool.outer ¬ Containers.Create[info: [ name: tool.name, icon: tool.icon, label: tool.databases.first.shortname, iconic: FALSE, column: left, menu: tool.menu, scrollable: FALSE]]; Menus.ChangeNumberOfLines[tool.menu, 1]; ViewerBLT.ChangeNumberOfLines[tool.outer, 1]; ViewerOps.AddProp[viewer: tool.outer, prop: $BrowserTool, val: tool]; [] ¬ ViewerEvents.RegisterEventProc[proc: DestroyProc, event: destroy, filter: tool.outer]; tool.details ¬ Containers.Create[info: [ parent: tool.outer, ww: 9999, wh: 9999, scrollable: FALSE, border: FALSE]]; Containers.ChildXBound[container: tool.outer, child: tool.details]; Containers.ChildYBound[container: tool.outer, child: tool.details]; tool.height ¬ interItemHeight; MakeDatabaseButton[tool]; MakeEntryForm[tool]; MakeSortButton[tool]; DividingLine[tool]; tool.history ¬ TiogaButtons.CreateViewer[info: [ parent: tool.outer, wy: tool.height, ww: 9999, wh: historyHeight, border: TRUE]]; Containers.ChildXBound[tool.outer, tool.history]; -- constrain rule to be width of parent HideViewer[tool.history]; innerInfo ¬ [ name: "LoganBerry Browser output", parent: tool.outer, wx: 0, wy: tool.height, ww: 9999, wh: 9999, border: FALSE]; tool.inner ¬ SELECT tool.innerFlavor FROM $Typescript => TypeScript.Create[info: innerInfo], ENDCASE => ViewerOps.CreateViewer[flavor: tool.innerFlavor, info: innerInfo]; Containers.ChildXBound[tool.outer, tool.inner]; -- constrain rule to be width of parent Containers.ChildYBound[tool.outer, tool.inner]; -- constrain rule to be height of parent }; PrintEntry: PUBLIC PROC [entry: LoganBerry.Entry, tool: BrowserTool] = { IF tool.innerFlavor#$TypeScript THEN { MessageWindow.Append[message: "Wrong flavor of browser's output viewer", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN; }; FOR e: LoganBerry.Entry ¬ entry, e.rest UNTIL e = NIL DO IF e.first.type#NIL THEN { TypeScript.ChangeLooks[tool.inner, 'b]; -- print atribute type in bold TypeScript.PutRope[tool.inner, Atom.GetPName[e.first.type]]; TypeScript.ChangeLooks[tool.inner, ' ]; -- restore normal looks TypeScript.PutRope[tool.inner, ": "]; }; TypeScript.PutRope[tool.inner, e.first.value]; TypeScript.PutChar[tool.inner, '\n]; ENDLOOP; TypeScript.PutChar[tool.inner, '\n]; }; PrintEntryAsButton: PUBLIC PROC [entry: LoganBerry.Entry, tool: BrowserTool, proc: TiogaButtons.TiogaButtonProc, clientData: REF ANY ¬ NIL] = { EntryToRope: PROC [entry: LoganBerry.Entry] RETURNS [rope: ROPE] ~ { rope ¬ NIL; FOR l: LoganBerry.Entry ¬ entry, l.rest WHILE l # NIL DO IF l.first.type#NIL THEN rope ¬ IO.PutFR["%g%g: ", IO.rope[rope], IO.atom[l.first.type]]; rope ¬ IO.PutFR["%g%g\n", IO.rope[rope], IO.rope[l.first.value]]; ENDLOOP; }; IF tool.innerFlavor#$TiogaButtons THEN { MessageWindow.Append[message: "Wrong flavor of browser's output viewer", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN; }; [] ¬ TiogaButtons.CreateButton[viewer: tool.inner, rope: EntryToRope[entry], proc: proc, clientData: clientData]; }; StopProc: PUBLIC Menus.ClickProc = TRUSTED { tool: BrowserTool ¬ NARROW[clientData]; put: DisplayProc ¬ GetDisplayProc[tool]; LoganQuery.AbortQuery[tool.cursor]; put[LIST[[NIL, "-- Aborted"]], tool]; }; warningThreshold: REAL = 0.75; -- give warning if 3/4 of the database must be searched BrowseProc: PUBLIC Menus.ClickProc = { ENABLE { LoganBerry.Error => {ReportLBError[ec, explanation, NARROW[clientData]]; CONTINUE}; LoganQuery.SyntaxError => {ReportLBError[$BadQuery, explanation, NARROW[clientData]]; CONTINUE}; }; tool: BrowserTool ¬ NARROW[clientData]; put: DisplayProc ¬ GetDisplayProc[tool]; form: LoganQuery.AttributePatterns; base: LoganBerry.AttributeType; other: ROPE; queryTree: LoganQuery.ParseTree ¬ NIL; newcursor: LoganQuery.Cursor; plan: LoganQuery.QueryPlan; entry: LoganBerry.Entry; IF mouseButton # blue THEN ResetViewer[tool.inner]; [form, other, base] ¬ ReadEntryForm[tool]; IF NOT Rope.IsEmpty[other] THEN { queryTree ¬ LoganQuery.ParseBooleanQuery[IO.RIS[other]]; }; tool.cursor.class ¬ NIL; FOR d: DBList ¬ tool.databases, d.rest WHILE d#NIL DO IF d.first.selected THEN { [newcursor, plan] ¬ LoganQuery.QueryEntries[db: d.first.db, patterns: form, baseIndex: base]; IF queryTree # NIL THEN newcursor ¬ LoganQuery.BooleanFilterEntries[input: newcursor, query: queryTree, inputOrder: plan.first.attr.type, primaryKey: d.first.schema.indices.first.key]; IF tool.cursor.class=NIL THEN tool.cursor ¬ newcursor ELSE tool.cursor ¬ LoganQueryClass.MergeEntries[input1: newcursor, input2: tool.cursor, atype: plan.first.attr.type]; }; ENDLOOP; IF tool.cursor.class=NIL THEN { ReportLBError[$NoOp, "No database selected", tool]; RETURN; }; ReportFeedback[plan, tool]; IF plan.first.cost > warningThreshold THEN MessageWindow.Append[message: "Browsing complete database...", clearFirst: TRUE]; entry ¬ LoganQuery.NextEntry[tool.cursor]; WHILE entry # NIL DO put[entry, tool]; entry ¬ LoganQuery.NextEntry[tool.cursor]; ENDLOOP; put[LIST[[NIL, "-- Done."]], tool]; LoganQuery.EndGenerate[tool.cursor]; }; UpdateProc: PUBLIC Menus.ClickProc = { DoUpdateOrReplace[tool: NARROW[clientData], replace: FALSE, reset: mouseButton # blue]; }; ReplaceProc: PUBLIC Menus.ClickProc = { DoUpdateOrReplace[tool: NARROW[clientData], replace: TRUE, reset: mouseButton # blue]; }; DoUpdateOrReplace: PROC [tool: BrowserTool, replace: BOOLEAN ¬ FALSE, reset: BOOLEAN ¬ FALSE] ~ { ENABLE { LoganBerry.Error => {ReportLBError[ec, explanation, tool]; CONTINUE}; LoganQuery.SyntaxError => {ReportLBError[$MalformedAttribute, explanation, tool]; CONTINUE}; }; put: DisplayProc ¬ GetDisplayProc[tool]; form: LoganQuery.AttributePatterns; other: ROPE; entry: LoganBerry.Entry; dbinfo: LoganBerryBrowser.DBInfo ¬ NIL; IF reset THEN ResetViewer[tool.inner]; [form, other,] ¬ ReadEntryForm[tool]; IF NOT Rope.IsEmpty[other] THEN { otherPatterns: LoganQuery.AttributePatterns ¬ LoganQuery.ReadAttributePatterns[IO.RIS[other]]; form ¬ AppendPatterns[form, otherPatterns]; }; entry ¬ LoganQuery.PatternsToEntry[form]; FOR d: DBList ¬ tool.databases, d.rest WHILE d#NIL DO IF d.first.selected THEN IF dbinfo=NIL THEN dbinfo ¬ d.first ELSE {ReportLBError[$Update, "Please select a single database", tool]; RETURN;}; ENDLOOP; IF dbinfo=NIL THEN { ReportLBError[$NoOp, "No database selected", tool]; RETURN; }; LoganBerry.WriteEntry[db: dbinfo.db, entry: entry, replace: replace]; put[entry, tool]; put[LIST[[NIL, "-- Done."]], tool]; }; DeleteProc: PUBLIC Menus.ClickProc = { ENABLE { LoganBerry.Error => {ReportLBError[ec, explanation, NARROW[clientData]]; CONTINUE}; LoganQuery.SyntaxError => {ReportLBError[$BadQuery, explanation, NARROW[clientData]]; CONTINUE}; }; tool: BrowserTool ¬ NARROW[clientData]; put: DisplayProc ¬ GetDisplayProc[tool]; form: LoganQuery.AttributePatterns; base: LoganBerry.AttributeType; other: ROPE; queryTree: LoganQuery.ParseTree ¬ NIL; entry: LoganBerry.Entry; primaryKey: LoganBerry.AttributeType = tool.databases.first.schema.indices.first.key; plan: LoganQuery.QueryPlan; dbinfo: LoganBerryBrowser.DBInfo ¬ NIL; IF mouseButton # blue THEN ResetViewer[tool.inner]; [form, other, base] ¬ ReadEntryForm[tool]; FOR d: DBList ¬ tool.databases, d.rest WHILE d#NIL DO IF d.first.selected THEN IF dbinfo=NIL THEN dbinfo ¬ d.first ELSE {ReportLBError[$Delete, "Please select a single database", tool]; RETURN;}; ENDLOOP; IF dbinfo=NIL THEN { ReportLBError[$NoOp, "No database selected", tool]; RETURN; }; [tool.cursor, plan] ¬ LoganQuery.QueryEntries[db: dbinfo.db, patterns: form, baseIndex: base]; IF NOT Rope.IsEmpty[other] THEN { queryTree ¬ LoganQuery.ParseBooleanQuery[IO.RIS[other]]; tool.cursor ¬ LoganQuery.BooleanFilterEntries[input: tool.cursor, query: queryTree, inputOrder: plan.first.attr.type, primaryKey: dbinfo.schema.indices.first.key]; }; ReportFeedback[plan, tool]; put[LIST[[NIL, "-- Deleting..."]], tool]; tool.lastDeletes ¬ NIL; entry ¬ LoganQuery.NextEntry[tool.cursor]; WHILE entry # NIL DO LoganBerry.DeleteEntry[db: dbinfo.db, key: primaryKey, value: GetAttributeValue[entry, primaryKey]]; tool.lastDeletes ¬ CONS[entry, tool.lastDeletes]; put[entry, tool]; entry ¬ LoganQuery.NextEntry[tool.cursor]; ENDLOOP; put[LIST[[NIL, "-- Done."]], tool]; LoganQuery.EndGenerate[tool.cursor]; }; UnDeleteProc: PUBLIC Menus.ClickProc = { ENABLE LoganBerry.Error => {ReportLBError[ec, explanation, NARROW[clientData]]; CONTINUE}; tool: BrowserTool ¬ NARROW[clientData]; put: DisplayProc ¬ GetDisplayProc[tool]; dbinfo: LoganBerryBrowser.DBInfo ¬ NIL; IF mouseButton # blue THEN ResetViewer[tool.inner]; FOR d: DBList ¬ tool.databases, d.rest WHILE d#NIL DO IF d.first.selected THEN IF dbinfo=NIL THEN dbinfo ¬ d.first ELSE {ReportLBError[$UnDelete, "Please select a single database", tool]; RETURN;}; ENDLOOP; IF dbinfo=NIL THEN { ReportLBError[$NoOp, "No database selected", tool]; RETURN; }; put[LIST[[NIL, "-- UnDeleting..."]], tool]; FOR l: LIST OF LoganBerry.Entry ¬ tool.lastDeletes, l.rest WHILE l#NIL DO LoganBerry.WriteEntry[db: dbinfo.db, entry: l.first ! LoganBerry.Error => {ReportLBError[ec, explanation, tool]; CONTINUE};]; put[l.first, tool]; ENDLOOP; tool.lastDeletes ¬ NIL; -- can't undo an undelete put[LIST[[NIL, "-- Done."]], tool]; }; DetailsProc: PUBLIC Menus.ClickProc = { tool: BrowserTool ¬ NARROW[clientData]; IF tool.details.wx = 0 THEN HideViewer[tool.details] ELSE UnHideViewer[tool.details]; }; HistoryProc: PUBLIC Menus.ClickProc = { tool: BrowserTool ¬ NARROW[clientData]; IF tool.history.wx = 0 THEN { HideViewer[tool.history]; ViewerOps.MoveViewer[viewer: tool.inner, x: tool.inner.wx, y: tool.inner.wy - historyHeight, w: tool.inner.ww, h: tool.inner.wh]; tool.height ¬ tool.height - historyHeight; } ELSE { ViewerOps.MoveViewer[viewer: tool.inner, x: tool.inner.wx, y: tool.inner.wy + historyHeight, w: tool.inner.ww, h: tool.inner.wh]; UnHideViewer[tool.history]; tool.height ¬ tool.height + historyHeight; }; }; DestroyProc: ViewerEvents.EventProc = { }; SetDefaults: PROC [tool: BrowserTool] RETURNS [] ~ { IF tool.name = NIL THEN tool.name ¬ Rope.Concat["LoganBerry Browser: ", tool.databases.first.schema.dbName]; IF tool.menu = NIL THEN { tool.menu ¬ StandardMainMenu[tool]; }; IF tool.innerFlavor = NIL THEN tool.innerFlavor ¬ $TypeScript; IF tool.icon = unInit THEN tool.icon ¬ browserIcon; IF tool.fields = NIL THEN tool.fields ¬ IndexKeys[tool]; }; IndexKeys: PROC [tool: BrowserTool] RETURNS [fields: LIST OF LoganBerry.AttributeType] ~ { tail: LIST OF LoganBerry.AttributeType ¬ NIL; FOR i: LIST OF LoganBerry.IndexInfo ¬ tool.databases.first.schema.indices, i.rest WHILE i#NIL DO IF tail#NIL THEN {tail.rest ¬ LIST[i.first.key]; tail ¬ tail.rest;} ELSE {fields ¬ tail ¬ LIST[i.first.key];} ENDLOOP; }; StandardMainMenu: PROC [tool: BrowserTool] RETURNS [menu: Menus.Menu] ~ { AppendMenu: PROC[menu: Menus.Menu, name: ROPE, proc: Menus.ClickProc, line: Menus.MenuLine ¬ 0, guarded: BOOL ¬ FALSE] = { Menus.AppendMenuEntry[ menu: menu, entry: Menus.CreateEntry[name: name, proc: proc, clientData: tool, guarded: guarded], line: line ]; }; menu ¬ Menus.CreateMenu[lines: 2]; AppendMenu[menu, "STOP!", StopProc]; AppendMenu[menu, "Browse", BrowseProc]; AppendMenu[menu, "Update", UpdateProc]; AppendMenu[menu, "Replace", ReplaceProc]; AppendMenu[menu, "Delete", DeleteProc, 0, TRUE]; AppendMenu[menu, "UnDelete", UnDeleteProc, 0, TRUE]; AppendMenu[menu, "History", HistoryProc]; AppendMenu[menu, "Details", DetailsProc]; AppendMenu[menu, "AdminOps", AdminOpsProc]; AppendMenu[menu, "Open", OpenProc, 1]; AppendMenu[menu, "Close", CloseProc, 1, TRUE]; AppendMenu[menu, "BuildIndices", BuildIndicesProc, 1, TRUE]; AppendMenu[menu, "CompactLogs", CompactLogsProc, 1, TRUE]; }; AdminOpsProc: PUBLIC Menus.ClickProc = { tool: BrowserTool ¬ NARROW[clientData]; newCount: CARDINAL ¬ IF Menus.GetNumberOfLines[tool.menu] = 1 THEN 2 ELSE 1; Menus.ChangeNumberOfLines[tool.menu, newCount]; ViewerBLT.ChangeNumberOfLines[tool.outer, newCount]; }; OpenProc: PUBLIC Menus.ClickProc = { tool: BrowserTool ¬ NARROW[clientData]; FOR d: DBList ¬ tool.databases, d.rest WHILE d#NIL DO IF d.first.selected THEN d.first.db ¬ LoganBerry.Open[dbName: d.first.schema.dbName ! LoganBerry.Error => {ReportLBError[ec, explanation, tool]; CONTINUE}]; ENDLOOP; }; CloseProc: PUBLIC Menus.ClickProc = { tool: BrowserTool ¬ NARROW[clientData]; FOR d: DBList ¬ tool.databases, d.rest WHILE d#NIL DO IF d.first.selected THEN LoganBerry.Close[db: d.first.db ! LoganBerry.Error => {ReportLBError[ec, explanation, tool]; CONTINUE}]; ENDLOOP; }; BuildIndicesProc: PUBLIC Menus.ClickProc = { tool: BrowserTool ¬ NARROW[clientData]; FOR d: DBList ¬ tool.databases, d.rest WHILE d#NIL DO IF d.first.selected THEN LoganBerry.BuildIndices[db: d.first.db ! LoganBerry.Error => {ReportLBError[ec, explanation, tool]; CONTINUE}]; ENDLOOP; }; CompactLogsProc: PUBLIC Menus.ClickProc = { tool: BrowserTool ¬ NARROW[clientData]; FOR d: DBList ¬ tool.databases, d.rest WHILE d#NIL DO IF d.first.selected THEN LoganBerry.CompactLogs[db: d.first.db ! LoganBerry.Error => {ReportLBError[ec, explanation, tool]; CONTINUE}]; ENDLOOP; }; GetAttributeValue: PROC [entry: LoganBerry.Entry, type: LoganBerry.AttributeType] RETURNS [LoganBerry.AttributeValue] ~ { FOR e: LoganBerry.Entry ¬ entry, e.rest WHILE e # NIL DO IF e.first.type = type THEN RETURN[e.first.value]; ENDLOOP; RETURN[NIL]; }; ReportLBError: PROC [ec: LoganBerry.ErrorCode, explanation: ROPE, tool: BrowserTool] RETURNS [] ~ { put: DisplayProc ¬ GetDisplayProc[tool]; put[LIST[[$ERROR, IO.PutFR["%g - %g", IO.atom[ec], IO.rope[explanation]]]], tool]; }; GetDisplayProc: PROC [tool: BrowserTool] RETURNS [proc: DisplayProc] ~ { RETURN[IF tool.display=NIL THEN PrintEntry ELSE tool.display]; }; browserIcon ¬ Icons.NewIconFromFile[file: "LoganBerry.icons", n: 0 ! ANY => CONTINUE]; END. 7ŠLoganBerryBrowserImpl.mesa Copyright Ó 1985, 1992 by Xerox Corporation. All rights reserved. Doug Terry, July 17, 1992 2:32 pm PDT Brian Oki, June 19, 1990 1:00 pm PDT A tool for interactively browsing LoganBerry databases. Types Viewer layout Entry form [parent: ViewerClasses.Viewer, clientData: REF ANY _ NIL, mouseButton: ViewerClasses.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [parent: ViewerClasses.Viewer, clientData: REF ANY _ NIL, mouseButton: ViewerClasses.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [parent: ViewerClasses.Viewer, clientData: REF ANY _ NIL, mouseButton: ViewerClasses.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN] The following 2 lines are commented out since the other field may contain a boolean query: otherPatterns ¬ LoganQuery.ReadAttributePatterns[IO.RIS[other]]; form ¬ AppendPatterns[form, otherPatterns]; [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN] History viewer The History viewer contains lines representing commands that could have been typed to a commandTool to achieve the same result as the operations invoked via the browser tool. Each of these lines is a TiogaButton that, when buttoned, causes the entry form to be filled in with the various values. [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] Left mouse button => restore the entry form; Middle => restore form and re-execute (not currently implemented). Misc. viewer stuff Create main tool Get database info FOR d: DBList _ tool.databases, d.rest WHILE d#NIL DO name: PFS.PATH; comp: PFSNames.Component; d.first.schema _ LoganBerry.Describe[db: d.first.db]; name _ PFSNames.ExpandName[PFS.PathFromRope[d.first.schema.dbName]]; d.first.schema.dbName _ PFS.RopeFromPath[name]; comp _ PFSNames.ShortName[name]; d.first.shortname _ comp.name.base; ENDLOOP; Initialize tool create command section create input form create history viewer create output browser Write entry in browser's typescript viewer. Builds a tioga button in the browser's inner viewer. Command menu [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [viewer: ViewerClasses.Viewer, event: ViewerEvents.ViewerEvent, before: BOOL] RETURNS [abort: BOOL _ FALSE] -- Does nothing at the moment tool: BrowserTool _ NARROW[ViewerOps.FetchProp[viewer: viewer, prop: $BrowserTool]]; LoganBerry.Close[db: tool.databases.first.db ! LoganBerry.Error => {ReportLBError[ec, explanation, tool]; CONTINUE}]; Default browser operations --first line-- --second line-- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] Looks up the display proc associated with the specified browser. Initialization Doug Terry, November 27, 1985 3:22:06 pm PST taken from WPBrowserToolImpl.mesa changes to: DIRECTORY, LoganBerryBrowserTool, browserIcon, db, dbFileName, NamedFilter, Commander, END, BrowseProc, DetailsProc, HistoryProc, MakeMainMenu, BrowserToolRec, MakeBrowserTool, itemHeight, interItemHeight, ruleHeight, patternButtonWidth, patternHSpace, historyHeight, AppendMenu (local of MakeMainMenu), MakeEntryForm, AppendEntry (local of MakeEntryForm), MakeSortButton, DividingLine, FormFieldRec, AddToSortList (local of MakeSortButton), StopProc, BrowseProc, DoQuery, PutEntry (local of DoQuery), NewFilter (local of DoQuery), ROPE, STREAM Doug Terry, November 27, 1985 4:05:43 pm PST changes to: PutEntry (local of DoQuery), MakeSortButton, DIRECTORY Doug Terry, November 27, 1985 5:56:01 pm PST changes to: MakeSortButton, AddToSortList (local of MakeSortButton), DIRECTORY, DestroyProc, MakeMainMenu, MakeBrowserTool, browserIcon, Commander, LoganBerryBrowserTool Doug Terry, November 27, 1985 6:18:58 pm PST changes to: MakeBrowserTool Doug Terry, January 23, 1986 8:41:38 pm PST changes to: DestroyProc, MakeBrowserTool Doug Terry, January 31, 1986 2:46:52 pm PST changes to: AdminOpsProc, OpenProc, CloseProc, BuildIndiciesProc, CompactLogsProc, DestroyProc, MakeMainMenu, DIRECTORY, AppendMenu (local of MakeMainMenu), MakeBrowserTool, LoganBerryBrowserTool Doug Terry, January 31, 1986 2:53:26 pm PST changes to: AdminOpsProc, MakeMainMenu, MakeBrowserTool, AppendMenu (local of MakeMainMenu) Doug Terry, January 31, 1986 5:21:25 pm PST changes to: AppendMenu (local of MakeMainMenu), MakeMainMenu, MakeBrowserTool, BrowseProc, DIRECTORY Doug Terry, March 5, 1986 6:18:08 pm PST Now calls LoganBerry.Describe to obtain the list of available indices and catches LoganBerry.Errors. changes to: DIRECTORY, MakeEntryForm, OpenProc, CloseProc, BuildIndiciesProc, CompactLogsProc, DestroyProc, MakeBrowserTool, PutEntry (local of DoQuery) Doug Terry, April 24, 1986 9:47:20 am PST Changed to use LoganBerryStub. changes to: DIRECTORY, LoganBerryBrowserTool, BrowserToolRec, OpenProc, MakeBrowserTool, DoQuery, ReportLBError Doug Terry, April 24, 1986 9:51:16 am PST changes to: DIRECTORY, LoganBerryBrowserTool, BrowserToolRec, OpenProc, MakeBrowserTool, DoQuery, ReportLBError Doug Terry, July 1, 1986 6:00:40 pm PDT Added History facility. changes to: FormFieldRec, FormValue, FormValueRec, FormContents, MakeSortButton, ReadEntryForm, NextField (local of ReadEntryForm), AddToHistory, AddToLine (local of AddToHistory), RestoreFromHistory, HistoryButtonProc, DoQuery, BrowseProc, RestoreEntryForm, PutEntry, GetAttributeValue, DIRECTORY, LoganBerryBrowserTool, ROPE, STREAM, HistoryData, HistoryDataRec, RestoreField (local of RestoreEntryForm), HistoryProc, DetailsProc, UnHideViewer, HideViewer, MakeBrowserTool Doug Terry, July 1, 1986 9:04:42 pm PDT changes to: BuildIndicesProc, MakeMainMenu Doug Terry, October 16, 1986 5:58:19 pm PDT changes to: DoQuery Doug Terry, October 22, 1986 4:10:21 pm PDT Changed to use LoganBerryCommands and provide a similar model of operation; added support for updates and deletes. changes to: BrowserToolRec, UpdateProc, DeleteProc, DetailsProc, MakeMainMenu, MakeInputArea, MakeSortButton, MakeBrowserTool, FormContents, BrowseProc, AddToHistory, HistoryButtonProc, NextField (local of ReadEntryForm), RestoreField (local of RestoreEntryForm), RestoreEntryForm, DoQuery, AttributePattern, AttributePatternRec, HistoryDataRec, MakeEntryForm, ReadEntryForm, DoQuery, DIRECTORY, LoganBerryBrowserTool, PutEntry (local of DoOp), DeleteEntry (local of DoOp) Doug Terry, October 31, 1986 4:56:08 pm PST Exports and uses CreateTool operation. changes to: DIRECTORY, LoganBerryBrowserImpl, BrowserToolRec, AttributePattern, AttributePatternRec, AttributePatterns, MakeEntryForm, AddToHistory, CreateTool, DoOp, PutEntry (local of DoOp), MakeBrowserTool, browserIcon Doug Terry, November 2, 1986 7:00:17 pm PST Added support for subrange filtering and UnDelete. changes to: BrowserToolRec, UnDeleteProc, DetailsProc, MakeEntryForm, DeleteEntry (local of DoOp), DoOp Doug Terry, November 23, 1986 9:29:41 pm PST Moved support for filtered queries to this module; removed any command registrations. changes to: LoganBerryBrowserImpl, HistoryDataRec, historyHeight, MakeMainMenu, HistoryButtonProc, UnHideViewer, CreateTool, SyntaxError, Read, LoganQuery, FilteredQuery, Subrange, ReportLBError, browserIcon, DIRECTORY, BrowserToolRec, PrintEntry, PutEntry (local of DoOp), DoOp Doug Terry, November 24, 1986 4:58:48 pm PST Added new filters: DWIM, NumSubrange, DateSubrange, DateAndTime. changes to: OptimalStart, NamedFilter, subrangeCache, ParseSubrange, ToDash (local of ParseSubrange), Subrange, NumSubrange, DateSubrange, srCache, nsrCache, dsrCache, DateSubrange, DIRECTORY, LoganBerryBrowserImpl, FilteredQuery, NamedFilter, MakeEntryForm Doug Terry, December 4, 1986 6:59:04 pm PST Changed CreateTool to create inner (output) viewers of various flavors. changes to: DIRECTORY, CreateTool Doug Terry, December 15, 1986 6:31:17 pm PST Stop! now calls Process.Abort, which raises ABORTED, which is caught in DoOp. changes to: OptimalStart, BaseStartEnd, DIRECTORY, LoganBerryBrowserImpl, BrowserToolRec, StopProc, DoOp, PutEntry (local of DoOp), DeleteEntry (local of DoOp) Doug Terry, December 22, 1986 5:12:02 pm PST changes to: historyHeight, patternChoices, defaultPattern, MakeEntryForm Doug Terry, December 23, 1986 4:11:02 pm PST changes to: ReadEntryForm, NextField (local of ReadEntryForm), SyntaxError, QueryWarning, FilteredQuery, DoOp Doug Terry, December 29, 1986 3:04:30 pm PST Added computation of start and end for various types of base indices; uses estimated query cost to select the optimal base index if one is not specified. changes to: BaseStartEnd, Bump (local of BaseStartEnd), Upper (local of BaseStartEnd), Lower (local of BaseStartEnd), MakeEntryForm, ReadEntryForm, CreateTool, FilteredQuery, GetIndexType, QueryCost changes to: Bump (local of BaseStartEnd), warningThreshold, QueryWarning, FilteredQuery Doug Terry, December 29, 1986 4:36:38 pm PST changes to: warningThreshold, QueryWarning, FilteredQuery, Bump (local of BaseStartEnd), Feedback, RegisterFeedbackArea Doug Terry, January 27, 1987 5:57:51 pm PST changes to: DIRECTORY, LoganBerryBrowserImpl, DoOp, BrowserToolRec, UnDeleteProc, MakeEntryForm, MakeSortButton, CreateTool Doug Terry, January 28, 1987 10:58:00 am PST Added calls to LoganBerryExtras to get the ordering of indices; reduced assumptions about the flavor of the inner viewer (used to assume it was a typescript in various places); made Delete and UnDelete call the client-provided DisplayProc; added calls to the OpProc for $LBUnDelete and $LBStop. changes to: MakeEntryForm changes to: DIRECTORY, LoganBerryBrowserImpl, EntryToPatterns, AppendPatterns, DoOp changes to: BrowseProc, DeleteProc, UnDeleteProc, UnHideViewer, ResetViewer, ReportLBError Doug Terry, January 28, 1987 9:26:14 pm PST changes to: BrowseProc, UpdateProc, DeleteProc, UnDeleteProc, OpenProc, CloseProc, BuildIndicesProc, CompactLogsProc, DestroyProc, UnHideViewer, ResetViewer, DoOp, DeleteEntry (local of DoOp), UnDeleteEntry (local of DoOp), ReportLBError Doug Terry, January 29, 1987 1:47:06 pm PST changes to: BrowserToolRec, MakeSortButton, DIRECTORY, LoganBerryBrowserImpl, FilteredQuery, DeleteEntry (local of DoOp), DoOp, ClearFeedback, ReportFeedback, ReportLBError Doug Terry, January 29, 1987 3:42:53 pm PST changes to: patternHSpace, feedbackHSpace, MakeSortButton, DIRECTORY, FormFieldRec, MakeEntryForm, NextField (local of ReadEntryForm), ReadEntryForm, RestoreField (local of RestoreEntryForm), RestoreEntryForm, DeleteEntry (local of DoOp), ReportFeedback (local of DoOp), DoOp, FilteredQuery, AnalyzePattern Doug Terry, February 24, 1987 2:04:02 pm PST Changed the way browsers are customized; clients are now responsible for providing the main menu and operations (see "Default browser operations") changes to: BrowserTool, DetailsProc, CreateTool, SetDefaults, StandardMainMenu, BrowseProc, DoOp, MakeEntryForm, StandardMainMenu, ReadEntryForm, RestoreEntryForm, ReportFeedback, AddToHistory, PrintEntry, PutEntry (local of DoOp), DeleteEntry (local of DoOp), Feedback (local of DoOp), DataRec, SetDefaults, ReportLBError, DIRECTORY Doug Terry, February 24, 1987 2:30:23 pm PST changes to: StandardMainMenu, CreateTool, SetDefaults, DIRECTORY Doug Terry, March 4, 1987 10:48:08 am PST changes to: defaultPattern Doug Terry, April 15, 1987 11:45:33 am PDT Moved query facilities to LoganQueryImpl; this module should mainly be concerned with the user interface. changes to: defaultPattern, CreateTool, PrintEntry, StopProc, BrowseProc, UpdateProc, DeleteProc, UnDeleteProc, DetailsProc, HistoryProc, SetDefaults, StandardMainMenu Doug Terry, June 15, 1987 8:24:25 pm PDT Added facilities for browsing several LoganBerry databases with the same browser tool, e.g. merged queries. changes to: DIRECTORY, BrowserTool, DBList, MakeDatabaseButton, ToggleDatabaseButton, MakeSortButton, CreateTool, BrowseProc, UpdateProc, DeleteProc, UnDeleteProc, DestroyProc, SetDefaults, IndexKeys, OpenProc, CloseProc, BuildIndicesProc, CompactLogsProc, MakeEntryForm, RestoreEntryForm Doug Terry, July 27, 1987 7:07:28 pm PDT Changed to support LoganBerryBrowserExtras interface; removed all reliance on typescripts in standard menu procs. changes to: DIRECTORY, LoganBerryBrowserImpl, AdminOpsProc, OpenProc, CloseProc, BuildIndicesProc, CompactLogsProc, DBList, DisplayProc, PrintEntry, StopProc, DeleteProc, UnDeleteProc, ReportLBError, GetDisplayProc, PrintEntryAsButton, DisplayTable, RegisterDisplayProc, EntryToRope (local of PrintEntryAsButton), BrowserTool Doug Terry, July 17, 1992 11:37:07 am PDT Changed "other" field of browser to be parsed as a boolean query for Browse and Delete operations. Ê/B–(cedarcode) style•NewlineDelimiter ˜– "Cedar" stylešœ™Icode– "Cedar" stylešœ Ïeœ6™BK™%K™$—K˜J™7K˜šÏk ˜ Kšœžœ˜ Kšœžœ/˜ -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]š¡ œ˜'Kš£:™:Kšœžœžœ˜Kšœžœ˜Kšœ ˜ šžœžœžœž˜%Kšžœžœžœ˜'Kšžœ˜—šžœžœžœ˜Kšœxžœ˜‚Kšœ>žœ˜EKšœ˜—šžœ˜Kšœ.žœ˜5K˜—Kšœžœžœ˜+Kšžœžœ˜K˜—KšœŠžœ˜”Kšœžœžœ˜+K˜0Kšœ/žœ˜6Kšœ5˜5K˜K˜—š¡œžœžœ1žœ˜ZKšœžœžœžœ˜ršžœ(žœžœž˜;Kšœžœ6˜LKš žœžœžœžœžœžœ˜rKšžœ˜—K˜K˜—š¡œžœ(žœ#˜fK˜(Kšžœžœžœžœ˜Kšžœ žœžœžœ˜2K˜Kšžœ˜ K˜——J™™J™J™®J™xJ™š ¡ œžœžœ@žœžœ˜mKšœžœžœ˜CKšœžœžœžœ˜Kšœ.˜.Kšžœ˜Kšžœ˜Kšœ;žœ?˜|K˜—K˜–‚ -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE]š¡œ"˜3Kš£~™~K™oKšœžœ ˜'Kšœ3˜3K˜K˜——J™™J™š¡ œžœžœ˜5K˜K˜bKšœ+¢'˜RK˜'K˜K˜—š¡ œžœ žœ˜+K–n[viewer: ViewerClasses.Viewer, x: INTEGER, y: INTEGER, w: INTEGER, h: INTEGER, paint: BOOL _ TRUE]šœD˜DK˜—K˜š¡ œžœ žœ˜-KšœA˜AK˜K˜—š¡ œžœ žœ˜,Kšœ˜Kšœ˜K˜——J™™K˜š¡ œžœžœC˜ZKšœ#˜#K˜K™šžœž˜Kšœžœžœ*˜C—šžœžœžœ˜KšœYžœ˜_Kšžœ˜K˜—šžœ$žœžœž˜5Kšœ žœ˜K˜5šžœ*ž˜1K˜ K˜FKšžœ˜ —K˜LKšžœ˜—šžœ$žœžœž™5Kšœžœžœ™J™Kšœ5™5Kšœžœ&™DKšœžœ™/Kšœ ™ Kšœ#™#Kšžœ™—˜K˜—K™K˜Kšœ™˜&Kšœ˜Kšœ˜Kšœ&˜&Kšœžœ˜K˜ Kšœ˜Kšœ žœ˜—Kšœ(˜(K˜-K–>[viewer: ViewerClasses.Viewer, prop: ATOM, val: REF ANY]šœE˜EK–s[proc: ViewerEvents.EventProc, event: ViewerEvents.ViewerEvent, filter: REF ANY _ NIL, before: BOOL _ TRUE]˜[Kšœ™˜(Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ žœ˜Kšœžœ˜—K–B[container: Containers.Container, child: ViewerClasses.Viewer]šœC˜CK–B[container: Containers.Container, child: ViewerClasses.Viewer]šœC˜CK˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ™˜0Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœžœ˜—Kšœ3¢'˜ZKšœ˜Kšœ™˜ Kšœ"˜"Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœžœ˜—šœ žœž˜)Kšœ2˜2K–ê[flavor: ViewerClasses.ViewerFlavor, info: ViewerClasses.ViewerRec _ [class: NIL, wx: 0, wy: 0, ww: 0, wh: 0, cx: 0, cy: 0, cw: 0, ch: 0, lock: [process: PROCESS#0B, count: 0B (0)], tipTable: NIL, name: NIL, file: NIL, label: NIL, menu: NIL, icon: 177777B?, column: left, caption: FALSE, scrollable: TRUE, hscrollable: FALSE, iconic: TRUE, border: TRUE, newVersion: FALSE, newFile: FALSE, visible: TRUE, offDeskTop: FALSE, destroyed: FALSE, init: FALSE, saveInProgress: FALSE, inhibitDestroy: FALSE, guardDestroy: FALSE, paintingWedged: FALSE, spare0: FALSE, spare1: FALSE, spare2: FALSE, spare3: FALSE, spare4: FALSE, spare5: FALSE, spare6: FALSE, position: 0, openHeight: 0, link: NIL, parent: NIL, sibling: NIL, child: NIL, props: NIL, data: NIL], paint: BOOL _ TRUE]šžœF˜M—Kšœ1¢'˜XKšœ1¢(˜YK˜K˜—š¡ œžœžœ1˜HKšœ+™+šžœžœ˜&K–-[message: ROPE, clearFirst: BOOL _ FALSE]šœUžœ˜[K–[]šœ˜Kšžœ˜K˜—šžœ%žœžœž˜8šžœžœžœ˜Kšœ)¢˜GKšœ<˜K˜—K˜J™—™K˜K–[file: ROPE, n: CARDINAL]šœEžœžœ˜V—K˜Kšžœ˜™,K™!Kš œ Ïr–œ¥œ¥;œ¥)œ¥ œ¥™¬—™,Kšœ ¥œ¥™B—™,Kšœ ¥œ¥f™©—™,Kšœ ¥™—™+Kšœ ¥™(—™+Kšœ ¥wœ¥(™Ã—™+Kšœ ¥7œ™[—™+Kšœ ¥ œ¥6™d—™(K™dKšœ ¥yœ™˜—™)K™Kšœ ¥c™o—™)Kšœ ¥c™o—™'K™Kšœ ¥]œ¥œ¥Æœ¥E™Ú—™'Kšœ ¥™*—™+Kšœ ¥™—™+Kšœr™rKš œ ¥·œ¥œ¥¥œ¥ œ™Ø—™+K™&Kšœ ¥£œ¥™Ý—™+K™2Kšœ ¥Eœ¥™g—™,K™UKšœ ¥ôœ¥™–—™,K™@Kšœ ¥?œ¥™—™+K™GKšœ ¥™!—™,K™MKšœ ¥fœ¥ œ™Ÿ—™,Kšœ ¥<™H—™,Kšœ ¥œ¥0™m—™,K™™Kšœ ¥œ¥œ¥œ¥R™ÆKšœ ¥œ¥/™W—™,Kšœ ¥3œ¥ ™w—™+Kšœ ¥o™{—™,K™¦Kšœ ¥ ™Kšœ ¥G™SKšœ ¥N™Z—™+Kšœ ¥£œ¥œ¥™í—™+Kšœ ¥\œ¥4™¬—™+Kš œ ¥`œ¥œ¥œ¥œ¥%™²—™,K™’Kšœ ¥Ëœ¥ œ¥ œ¥0™Î—™,Kšœ ¥4™@—™)Kšœ ¥™—™*K™iKšœ ¥›™§—™(K™kKšœ ¥”™ —™(K™qKšœ ¥Žœ¥ ™Å—™)K™b—K™K™K™K™K™K™—…—c6Ê