DIRECTORY Buttons, FS, Commander, Containers, EditSpan, Imager, ImagerBackdoor, ImagerColor, InputFocus, Labels, Menus, NodeProps, NodeStyle, Process, PutGet, Rope, Rules, TableBase, TableOps, TableSelection, TextNode, TiogaOps, TiogaOpsDefs, TIPUser, TSJaMPageBuilder, TSObject, TSOutput, TSOutputDisplay, TSTranslate, TSTypes, ViewerClasses, ViewerOps, ViewerTools; TableToolImpl: CEDAR PROGRAM IMPORTS Buttons, FS, Commander, Containers, EditSpan, InputFocus, Imager, ImagerBackdoor, Labels, Menus, NodeProps, Process, PutGet, Rope, Rules, TableBase, TableOps, TableSelection, TextNode, TiogaOps, TIPUser, TSJaMPageBuilder, TSTranslate, TSTypes, ViewerOps, ViewerTools = BEGIN OPEN TableBase; ROPE: TYPE = Rope.ROPE; indent: INTEGER ~ 4; baseline: INTEGER ~ 16; ToolData: TYPE = REF ToolDataRec; ToolDataRec: TYPE = RECORD [ nameViewer: ViewerClasses.Viewer _ NIL, msgViewer: ViewerClasses.Viewer _ NIL, msgRope: ROPE _ NIL, displayViewer: ViewerClasses.Viewer _ NIL, selection: TableSelection.Selection _ NIL, selectingRowOrColumn: TableSelection.KindOfSelection _ row, callBackProc: DisplayProc _ NIL, entry: RefTableEntry _ NIL, beforeButton: Buttons.Button, afterButton: Buttons.Button, rowButton: Buttons.Button, colButton: Buttons.Button, rootOfTable: TextNode.Ref, galley: TSObject.ItemList, style: NodeStyle.Ref, pleaseStop: BOOLEAN _ FALSE ]; DisplayProc: TYPE = PROCEDURE [dc: Imager.Context, toolData: ToolData]; TableToolInitProc: ViewerClasses.InitProc = { toolData: ToolData _ NEW[ToolDataRec]; curY: INTEGER _ 0; NextY: PROCEDURE RETURNS [y:NAT] = {y _ curY _ curY+baseline}; button: ViewerClasses.Viewer; rule: Rules.Rule; menu: Menus.Menu _ Menus.CreateMenu[]; InsertMenu: PROCEDURE [name: ROPE, proc: Menus.ClickProc, doc: ROPE] = { Menus.InsertMenuEntry[menu, Menus.CreateEntry[ name: name, proc: proc, clientData: toolData, documentation: doc ]]; }; LabelledTextViewer: PROCEDURE [name: ROPE] RETURNS [v: ViewerClasses.Viewer] = { v _ ViewerTools.MakeNewTextViewer[ info:[wx: button.wx+button.ww, wy: curY, ww: 50, wh: button.wh, parent: self, scrollable: FALSE, border: FALSE], paint: TRUE ]; button _ Labels.Create[ info: [name: name, wx: v.wx + v.ww, wy: curY+1, wh: button.wh, parent: self, scrollable: FALSE, border: FALSE], paint: TRUE ]; }; MyButton: PROCEDURE [name: ROPE, x, y: NAT, proc: Buttons.ButtonProc, doc: ROPE _ NIL] RETURNS [Buttons.Button] = { RETURN [Buttons.Create[ info: [name: name, wx: x, wy: y, parent: self, border: FALSE], clientData: toolData, proc: proc, fork: TRUE, paint: TRUE, documentation: doc ]]}; ViewerOps.AddProp[self, $TableToolData, toolData]; containerInitProc[self]; -- since I know its really a $Container, I need to init it for him InsertMenu["DisplayNextTable", DisplayNextTableButton, "Displays the next table found in the document"]; InsertMenu["DisplaySelectedTable", DisplaySelectedTableButton, "Displays the table containing the selection"]; InsertMenu["DisplayDocument", DisplayDocumentButton, "Displays the document"]; InsertMenu["ABORT!", AbortButton, "Aborts the formatting process"]; ViewerOps.SetMenu[self, menu]; toolData.beforeButton _ MyButton[name: "Before ", x: indent, y: curY, proc: BeforeButton]; toolData.afterButton _ MyButton[name: "After ", x: toolData.beforeButton.wx+toolData.beforeButton.ww, y: curY, proc: AfterButton]; rule _ Rules.Create[info: [parent: self, wx: toolData.afterButton.wx+toolData.afterButton.ww, wy: curY, ww: 1, wh: toolData.afterButton.wh+1]]; toolData.rowButton _ MyButton[name: "Row ", x: rule.wx+rule.ww, y: curY, proc: RowButton]; toolData.colButton _ MyButton[name: "Col ", x: toolData.rowButton.wx+toolData.rowButton.ww, y: curY, proc: ColButton]; rule _ Rules.Create[info: [parent: self, wx: toolData.colButton.wx+toolData.colButton.ww, wy: curY, ww: 1, wh: toolData.colButton.wh+1]]; button _ MyButton[name: "Delete ", x: rule.wx+rule.ww, y: curY, proc: DeleteSelButton]; button _ MyButton[name: "Duplicate ", x: button.wx+button.ww, y: curY, proc: DuplicateSelButton]; button _ MyButton[name: "MakeHeader ", x: button.wx+button.ww, y: curY, proc: MakeHeaderButton]; button _ MyButton[name: "Append ", x: button.wx+button.ww, y: curY, proc: AppendButton]; button _ MyButton[name: "Transpose ", x: button.wx+button.ww, y: curY, proc: TransposeButton]; rule _ Rules.Create[info: [parent: self, wx: 0, wy: NextY[], ww: 999, wh: 1]]; Containers.ChildXBound[self, rule]; curY _ curY + 2; button _ MyButton[name: "DocumentName: ", x: indent, y: curY, proc: DocumentNameButton, doc: "Left-click to get selected document name; Middle-click to make current name pending-delete; Right-click to clear the name viewer."]; toolData.nameViewer _ ViewerTools.MakeNewTextViewer[ info:[wx: button.wx+button.ww, wy: curY+1, ww: 50, wh: baseline, parent: self, scrollable: TRUE, border: FALSE], paint: TRUE ]; Containers.ChildXBound[self, toolData.nameViewer]; rule _ Rules.Create[info: [parent: self, wx: 0, wy: NextY[]+1, ww: 999, wh: 1]]; Containers.ChildXBound[self, rule]; curY _ curY + 2; toolData.msgViewer _ ViewerTools.MakeNewTextViewer[ info:[wx: 0, wy: curY, ww: 50, wh: baseline, parent: self, scrollable: TRUE, border: FALSE], paint: TRUE ]; Containers.ChildXBound[self, toolData.msgViewer]; rule _ Rules.Create[info: [parent: self, wx: 0, wy: NextY[], ww: 999, wh: 1]]; Containers.ChildXBound[self, rule]; curY _ curY + 2; toolData.displayViewer _ ViewerOps.CreateViewer[ flavor: $TSDisplay, info: [ wx: 0, wy: curY, ww: 50, wh: baseline, border: FALSE, parent: self, scrollable: FALSE], paint: TRUE]; IF originalTSDisplayPaintProc = NIL THEN originalTSDisplayPaintProc _ toolData.displayViewer.class.paint; Containers.ChildXBound[self, toolData.displayViewer]; Containers.ChildYBound[self, toolData.displayViewer]; }; TableToolDestroyProc: ViewerClasses.DestroyProc = { toolData: ToolData ~ ToolDataFromViewer[self]; IF toolData # NIL AND toolData.selection # NIL AND toolData.selection.table # NIL THEN { BreakTableLinks[toolData.selection.table]; toolData.selection _ NIL; }; IF containerDestroyProc # NIL THEN containerDestroyProc[self]; }; TableToolPaintProc: ViewerClasses.PaintProc = { IF containerPaintProc # NIL THEN [] _ containerPaintProc[self, context, whatChanged, clear]; IF whatChanged = NIL AND clear THEN { toolData: ToolData _ ToolDataFromViewer[self]; IF toolData # NIL AND toolData.galley # NIL THEN TRUSTED { Process.Detach[FORK DisplayTable[toolData]]; }; }; }; AbortButton: Menus.ClickProc = { toolData: ToolData ~ NARROW[clientData]; toolData.pleaseStop _ TRUE; }; DisplayDocumentButton: Menus.ClickProc = { toolData: ToolData ~ NARROW[clientData]; docName: ROPE ~ ViewerTools.GetContents[toolData.nameViewer]; v: ViewerClasses.Viewer ~ ViewerOps.FindViewer[docName]; errorMsg: ROPE _ NIL; root: TextNode.Ref; toolData.pleaseStop _ FALSE; IF v # NIL THEN TRUSTED { root _ LOOPHOLE[TiogaOps.ViewerDoc[v]] } ELSE root _ PutGet.FromFile[docName ! FS.Error => {errorMsg _ error.explanation; CONTINUE}]; IF errorMsg # NIL THEN AppendLogMessage[toolData, Rope.Cat["Document \"", docName, "\" was not found for the reason: ", errorMsg]] ELSE IF root = NIL THEN AppendLogMessage[toolData, Rope.Cat["Viewer \"", docName, "\" wasn't found."]] ELSE { FormatTableFromRoot[toolData, root]; DisplayTable[toolData]; }; }; DisplaySelectedTableButton: Menus.ClickProc = { toolData: ToolData ~ NARROW[clientData]; v: ViewerClasses.Viewer; start: TiogaOps.Location; toolData.pleaseStop _ FALSE; [v, start] _ TiogaOps.GetSelection[primary]; IF v = NIL THEN AppendLogMessage[toolData, "No primary selection for a selected table."] ELSE TRUSTED { node: TextNode.Ref _ LOOPHOLE[start.node]; WHILE node # NIL AND NOT ATableNode[node] DO node _ TextNode.Parent[node]; ENDLOOP; IF node = NIL THEN AppendLogMessage[toolData, "Selected node is not in a table with ArtworkClass Table."] ELSE { FormatTableFromRoot[toolData, node]; DisplayTable[toolData]; ViewerTools.SetContents[toolData.nameViewer, v.name]; }; }; }; ATableNode: PROC [node: TextNode.Ref] RETURNS [BOOLEAN] ~ { IF node = NIL THEN RETURN [FALSE] ELSE { artworkClass: ROPE _ NARROW[NodeProps.GetProp[node, $ArtworkClass]]; RETURN[artworkClass.Equal["Table"]]; }; }; DisplayNextTableButton: Menus.ClickProc = { toolData: ToolData ~ NARROW[clientData]; toolData.pleaseStop _ FALSE; IF toolData.rootOfTable = NIL THEN AppendLogMessage[toolData, "No table previously displayed so I can't find the next one."] ELSE { node: TextNode.Ref _ TextNode.Forward[toolData.rootOfTable].nx; WHILE node # NIL AND NOT ATableNode[node] DO node _ TextNode.Forward[node].nx; ENDLOOP; IF node = NIL THEN { node _ TextNode.Root[toolData.rootOfTable]; WHILE node # NIL AND node # toolData.rootOfTable AND NOT ATableNode[node] DO node _ TextNode.Forward[node].nx; ENDLOOP; }; IF node = NIL OR node = toolData.rootOfTable THEN AppendLogMessage[toolData, "Sorry, no other table found in document."] ELSE { FormatTableFromRoot[toolData, node]; DisplayTable[toolData]; }; }; }; DocumentNameButton: Buttons.ButtonProc = { toolData: ToolData _ NARROW[clientData]; IF mouseButton = red THEN { selectedViewer: ViewerClasses.Viewer _ ViewerTools.GetSelectedViewer[]; sourceName: ROPE _ IF selectedViewer = NIL OR selectedViewer.class.get = NIL THEN NIL ELSE NARROW[selectedViewer.class.get[selectedViewer, $SelChars]]; IF sourceName.Length <= 1 THEN { IF (selectedViewer = NIL) THEN { AppendLogMessage[toolData, "Selection not in text viewer"]; RETURN; } ELSE { WHILE sourceName.Length <= 1 AND selectedViewer # NIL DO sourceName _ selectedViewer.name; selectedViewer _ selectedViewer.parent; ENDLOOP; }; }; IF sourceName.Length > 1 THEN { selectedViewer _ ViewerOps.FindViewer[sourceName]; IF selectedViewer = NIL THEN AppendLogMessage[toolData, Rope.Cat["Viewer \"", sourceName, "\" wasn't found."]] ELSE { ViewerTools.SetContents[toolData.nameViewer, sourceName]; }; }; } ELSE { ViewerTools.SetContents[toolData.nameViewer, ""]; }; ViewerTools.SetSelection[toolData.nameViewer]; }; BeforeButton: Buttons.ButtonProc ~ { toolData: ToolData _ NARROW[clientData]; IF toolData.selection # NIL THEN { toolData.selection.insertion _ before; Buttons.SetDisplayStyle[toolData.beforeButton, $WhiteOnBlack]; Buttons.SetDisplayStyle[toolData.afterButton, $BlackOnWhite]; }; }; AfterButton: Buttons.ButtonProc ~ { toolData: ToolData _ NARROW[clientData]; IF toolData.selection # NIL THEN { toolData.selection.insertion _ after; Buttons.SetDisplayStyle[toolData.beforeButton, $BlackOnWhite]; Buttons.SetDisplayStyle[toolData.afterButton, $WhiteOnBlack]; }; }; RowButton: Buttons.ButtonProc ~ { toolData: ToolData _ NARROW[clientData]; toolData.selectingRowOrColumn _ row; Buttons.SetDisplayStyle[toolData.rowButton, $WhiteOnBlack]; Buttons.SetDisplayStyle[toolData.colButton, $BlackOnWhite]; }; ColButton: Buttons.ButtonProc ~ { toolData: ToolData _ NARROW[clientData]; toolData.selectingRowOrColumn _ column; Buttons.SetDisplayStyle[toolData.rowButton, $BlackOnWhite]; Buttons.SetDisplayStyle[toolData.colButton, $WhiteOnBlack]; }; DeleteSelButton: Buttons.ButtonProc ~ { toolData: ToolData _ NARROW[clientData]; }; DuplicateSelButton: Buttons.ButtonProc ~ { toolData: ToolData _ NARROW[clientData]; }; TransposeButton: Buttons.ButtonProc ~ { toolData: ToolData _ NARROW[clientData]; }; MakeHeaderButton: Buttons.ButtonProc ~ { toolData: ToolData _ NARROW[clientData]; }; AppendButton: Buttons.ButtonProc ~ { toolData: ToolData _ NARROW[clientData]; }; ToolDataFromViewer: PROCEDURE [v: ViewerClasses.Viewer] RETURNS [toolData: ToolData] = { IF v # NIL THEN RETURN [NARROW[ViewerOps.FetchProp[v, $TableToolData]]]; }; TableFromViewer: PROCEDURE [v: ViewerClasses.Viewer] RETURNS [table: RefTable _ NIL] = { r: REF ANY ~ ViewerOps.FetchProp[v, $TableRef]; IF r # NIL AND ISTYPE[r, RefTable] THEN table _ NARROW[r, RefTable]; }; OutputHandleForTool: PROCEDURE [toolData: ToolData] RETURNS [handle: TSOutput.Handle]= { IF toolData # NIL AND toolData.displayViewer # NIL THEN handle _ NARROW[ViewerOps.FetchProp[toolData.displayViewer, $TSDisplayHandle]]; }; FormatTableFromRoot: PROC [toolData: ToolData, rootOfTable: TextNode.Ref] ~ { ENABLE UNWIND => toolData.pleaseStop _ TRUE; IF toolData.pleaseStop THEN RETURN; [toolData.galley, toolData.style] _ TSTranslate.TreeToVlist[rootOfTable]; toolData.rootOfTable _ rootOfTable; }; DisplayTable: PROCEDURE [toolData: ToolData] = { IF toolData.pleaseStop THEN RETURN; UnHookNotifier[toolData]; IF NOT TableSelection.AnEmptySelection[toolData.selection] THEN TakeDownSelection[toolData]; DisplayFormattedTable[toolData]; toolData.selection _ TableSelection.NewSelection[TableFromViewer[toolData.displayViewer]]; HookUpNotifier[toolData]; }; DisplayFormattedTable: PROCEDURE [toolData: ToolData] = { aborted: BOOLEAN _ FALSE; isAborted: PROC RETURNS [BOOLEAN] = { RETURN[toolData.pleaseStop] }; handle: TSOutput.Handle ~ OutputHandleForTool[toolData]; aborted _ TSJaMPageBuilder.RunPageBuilder[ galley: toolData.galley, style: toolData.style, output: handle, abortCheckProc: isAborted, documentName: NIL ]; handle.finishProc[handle]; toolData.pleaseStop _ toolData.pleaseStop OR aborted; }; AppendLogMessage: PROCEDURE [toolData: ToolData, msg: ROPE] = { toolData.msgRope _ toolData.msgRope.Cat[msg, "\n"]; ViewerTools.SetContents[toolData.msgViewer, toolData.msgRope]; [] _ toolData.msgViewer.class.scroll[toolData.msgViewer, thumb, 100]; }; HookUpNotifier: PROCEDURE [toolData: ToolData] = { v: ViewerClasses.Viewer ~ toolData.displayViewer; IF v # NIL THEN { v.class.tipTable _ tableToolTIPTable; v.tipTable _ tableToolTIPTable; v.class.notify _ TableToolNotifier; v.class.paint _ TableToolTSDisplayPaintProc; }; }; UnHookNotifier: PROCEDURE [toolData: ToolData] = { v: ViewerClasses.Viewer ~ toolData.displayViewer; IF v # NIL THEN { v.class.notify _ NoOpNotifier; v.class.paint _ originalTSDisplayPaintProc; }; }; NoOpNotifier: ViewerClasses.NotifyProc = { RETURN; }; TableToolNotifier: ViewerClasses.NotifyProc = { toolData: ToolData _ ToolDataFromViewer[self.parent]; { mouse: TIPUser.TIPScreenCoords; selectedBox: RefTableBox; InputFocus.SetInputFocus[toolData.displayViewer]; FOR list: LIST OF REF ANY _ input, list.rest UNTIL list = NIL DO WITH list.first SELECT FROM x: ATOM => SELECT x FROM $InsertBefore => { toolData.selection.insertion _ before; }; $InsertAfter => { toolData.selection.insertion _ after; }; $Row => { toolData.selectingRowOrColumn _ row; }; $Column => { toolData.selectingRowOrColumn _ column; }; $SelBox => { DoSelectBox[toolData, selectedBox]; }; $SelRow => { DoSelectRowOrCol[toolData, selectedBox, row]; }; $SelCol => { DoSelectRowOrCol[toolData, selectedBox, column ! CouldNotDoIt => GOTO Blink]; }; $SelUpdate => { DoSelectUpdate[toolData, selectedBox]; }; $SelExpand => { DoSelectExpand[toolData, selectedBox]; }; $SelReduce => { DoSelectReduce[toolData, selectedBox]; }; $SelExtend => { DoSelectExtend[toolData, selectedBox]; }; $DuplicateRowOrCol => { DoDuplicateRowOrCol[toolData, selectedBox]; }; $DeleteSelection => { DoDeleteSelection[toolData, selectedBox]; }; $TransposeTable => { DoTransposeTable[toolData, selectedBox]; }; $MakeRowOrColHeader => { DoMakeRowOrColHeader[toolData, selectedBox]; }; $AppendRowOrCol => { DoAppendRowOrCol[toolData, selectedBox]; }; ENDCASE => NULL; z: TIPUser.TIPScreenCoords => { mouse _ z; selectedBox _ ResolveMouseToBox[toolData, mouse]; }; ENDCASE => ERROR; ENDLOOP; EXITS Blink => ViewerOps.BlinkIcon[toolData.displayViewer]; }; }; CouldNotDoIt: SIGNAL = CODE; DoSelectBox: PROCEDURE [toolData: ToolData, selectedBox: RefTableBox] = { IF selectedBox # NIL THEN { TakeDownSelection[toolData]; toolData.selection.list _ LIST[NEW[TableSelection.SelectedThingRec _ [box~selectedBox]]]; toolData.selection.kind _ box; PutUpSelection[toolData]; }; }; DoSelectRowOrCol: PROCEDURE [toolData: ToolData, selectedBox: RefTableBox, which: TableSelection.KindOfSelection] = { IF selectedBox # NIL THEN { IF which # row AND which # column THEN SIGNAL CouldNotDoIt; IF toolData.selection.kind # which --OR NOT TableSelection.WithinSelection[toolData.selection, selectedBox]-- THEN { TakeDownSelection[toolData]; TableSelection.GrowSelection[toolData.selection, IF which = row THEN row ELSE column]; PutUpSelection[toolData]; }; }; }; DoSelectUpdate: PROCEDURE [toolData: ToolData, selectedBox: RefTableBox] = { IF selectedBox # NIL AND TableSelection.ASingleSelection[toolData.selection] THEN { SELECT toolData.selection.kind FROM box => { IF toolData.selection.list.first.box # selectedBox THEN { TakeDownSelection[toolData]; toolData.selection.list _ LIST[NEW[TableSelection.SelectedThingRec _ [box~selectedBox]]]; PutUpSelection[toolData]; }; }; row, column => { }; ENDCASE => ERROR; }; }; DoSelectExpand : PROCEDURE [toolData: ToolData, selectedBox: RefTableBox] = { IF selectedBox # NIL AND NOT TableSelection.AnEmptySelection[toolData.selection] THEN { TakeDownSelection[toolData]; SELECT toolData.selection.kind FROM box => TableSelection.GrowSelection[toolData.selection, row]; row => TableSelection.GrowSelection[toolData.selection, row]; column => TableSelection.GrowSelection[toolData.selection, column]; table => NULL; ENDCASE => ERROR; PutUpSelection[toolData]; }; }; DoSelectReduce: PROCEDURE [toolData: ToolData, selectedBox: RefTableBox] = { IF selectedBox # NIL AND NOT TableSelection.AnEmptySelection[toolData.selection] THEN { currentSelection: TableSelection.SelectionRec ~ toolData.selection^; TakeDownSelection[toolData]; SELECT currentSelection.kind FROM box => { }; row => { }; column => { }; ENDCASE => ERROR; PutUpSelection[toolData]; }; }; DoSelectExtend: PROCEDURE [toolData: ToolData, selectedBox: RefTableBox] = { IF selectedBox # NIL AND NOT TableSelection.AnEmptySelection[toolData.selection] THEN { currentSelection: TableSelection.SelectionRec ~ toolData.selection^; SELECT currentSelection.kind FROM box => NULL; row => { }; column => { }; ENDCASE => ERROR; TakeDownSelection[toolData]; PutUpSelection[toolData]; }; }; DoDeleteSelection: PROCEDURE [toolData: ToolData, selectedBox: RefTableBox] = { IF selectedBox # NIL AND NOT TableSelection.AnEmptySelection[toolData.selection] THEN { currentSelection: TableSelection.SelectionRec ~ toolData.selection^; IF toolData.selectingRowOrColumn = box THEN GOTO Blink; TakeDownSelection[toolData]; RefreshTableDisplay[toolData]; }; EXITS Blink => ViewerOps.BlinkIcon[toolData.displayViewer]; }; DoDuplicateRowOrCol: PROCEDURE [toolData: ToolData, selectedBox: RefTableBox] = { IF selectedBox # NIL AND NOT TableSelection.AnEmptySelection[toolData.selection] THEN { currentSelection: TableSelection.SelectionRec ~ toolData.selection^; IF currentSelection.kind = box THEN GOTO Blink; TakeDownSelection[toolData]; SELECT currentSelection.kind FROM row => { }; column => { }; ENDCASE => GOTO Blink; RefreshTableDisplay[toolData]; }; EXITS Blink => ViewerOps.BlinkIcon[toolData.displayViewer]; }; DoTransposeTable: PROCEDURE [toolData: ToolData, selectedBox: RefTableBox] = { IF selectedBox # NIL AND NOT TableSelection.AnEmptySelection[toolData.selection] THEN { TakeDownSelection[toolData]; TableOps.TransposeTable[toolData.selection.table]; RefreshTableDisplay[toolData]; }; }; DoMakeRowOrColHeader: PROCEDURE [toolData: ToolData, selectedBox: RefTableBox] = { IF selectedBox # NIL AND NOT TableSelection.AnEmptySelection[toolData.selection] AND toolData.selection.kind = toolData.selectingRowOrColumn THEN { currentSelection: TableSelection.SelectionRec ~ toolData.selection^; TakeDownSelection[toolData]; RefreshTableDisplay[toolData]; }; }; DoAppendRowOrCol: PROCEDURE [toolData: ToolData, selectedBox: RefTableBox] = { IF selectedBox # NIL AND NOT TableSelection.AnEmptySelection[toolData.selection] THEN { TakeDownSelection[toolData]; RefreshTableDisplay[toolData]; }; }; RefreshTableDisplay: PROCEDURE [toolData: ToolData] = { oldBranch, oldBranchRoot: TextNode.Ref; newBranch: TextNode.Ref; IF NOT TableSelection.AnEmptySelection[toolData.selection] THEN TakeDownSelection[toolData]; newBranch _ TableToBranch[toolData.selection.table]; oldBranch _ toolData.selection.table.branch; oldBranchRoot _ TextNode.Root[oldBranch]; TRUSTED { TiogaOps.Lock[LOOPHOLE[oldBranchRoot]] }; [] _ EditSpan.MoveOnto[ destRoot: oldBranchRoot, sourceRoot: TextNode.Root[newBranch], dest: TextNode.MakeNodeSpan[oldBranch, TextNode.LastWithin[oldBranch]], source: TextNode.MakeNodeSpan[newBranch, TextNode.LastWithin[newBranch]]]; TRUSTED { TiogaOps.Unlock[LOOPHOLE[oldBranchRoot]] }; BreakTableLinks[toolData.selection.table]; toolData.selection _ NIL; DisplayTable[toolData]; }; BreakTableLinks: PROCEDURE [table: RefTable] = { table.tableGrid _ NIL; table.rowGridPositions _ NIL; table.colGridPositions _ NIL; }; ResolveMouseToBox: PROCEDURE [toolData: ToolData, mouse: TIPUser.TIPScreenCoords] RETURNS [box: RefTableBox _ NIL] = { IF toolData.selection # NIL THEN { handle: TSOutput.Handle ~ OutputHandleForTool[toolData]; table: RefTable ~ toolData.selection.table; displayState: TSOutputDisplay.DisplayState ~ NARROW[handle.outputState]; box _ TableSelection.ResolveToBox[table: table, x: [mouse.mouseX - table.originX], y: [mouse.mouseY - (toolData.displayViewer.ch - displayState.pageHeight) - table.originY]]; }; }; BoxBeforeBox: PROCEDURE [first, second: RefTableBox] RETURNS [before: BOOLEAN] = { RETURN [(first.x.SubDimn[first.boxExtents[left]] <= second.x.SubDimn[second.boxExtents[left]]) AND (first.y.AddDimn[first.boxExtents[up]] >= second.y.AddDimn[second.boxExtents[up]])] }; TakeDownSelection: PROCEDURE [toolData: ToolData] = { IF NOT TableSelection.AnEmptySelection[toolData.selection] THEN PaintSelection[toolData]; toolData.selection.list _ NIL; }; PutUpSelection: PROCEDURE [toolData: ToolData] = { IF NOT TableSelection.AnEmptySelection[toolData.selection] THEN PaintSelection[toolData]; }; PaintSelection: PROCEDURE [toolData: ToolData] = { selection: TableSelection.Selection ~ toolData.selection; PaintSelectedBox: EnumeratedEntryProc = { toolData.entry _ entry; Painter[InvertTableBox, toolData]; }; FOR list: LIST OF TableSelection.SelectedThing _ selection.list, list.rest WHILE list # NIL DO SELECT selection.kind FROM box => { [] _ PaintSelectedBox[selection.table, list.first.box]; }; row => { EnumerateTable[table~selection.table, entryProc~PaintSelectedBox, top~list.first.grid1, bottom~list.first.grid2]; }; column => { EnumerateTable[table~selection.table, entryProc~PaintSelectedBox, left~list.first.grid1, right~list.first.grid2]; }; ENDCASE => ERROR; ENDLOOP; }; InvertTableBox: DisplayProc = { handle: TSOutput.Handle ~ OutputHandleForTool[toolData]; selection: TableSelection.Selection ~ toolData.selection; table: RefTable ~ selection.table; displayState: TSOutputDisplay.DisplayState ~ NARROW[handle.outputState]; xOffset: REAL ~ table.originX; yOffset: REAL ~ table.originY + (toolData.displayViewer.ch - displayState.pageHeight); oldColor: Imager.Color ~ ImagerBackdoor.GetColor[dc]; entry: RefTableEntry ~ toolData.entry; llx: REAL ~ xOffset + table.colGridPositions[entry.left].texPts; lly: REAL ~ yOffset + table.rowGridPositions[entry.bottom].texPts; urx: REAL ~ xOffset + table.colGridPositions[entry.right].texPts; ury: REAL ~ yOffset + table.rowGridPositions[entry.top].texPts; Imager.SetColor[dc, ImagerBackdoor.invert]; Imager.MaskBox[dc, [llx, lly, urx, ury]]; Imager.SetColor[dc, oldColor]; }; Painter: PROCEDURE [proc: DisplayProc, toolData: ToolData] = { toolData.callBackProc _ proc; ViewerOps.PaintViewer[viewer: toolData.displayViewer, hint: client, whatChanged: toolData, clearClient: FALSE]; }; TableToolTSDisplayPaintProc: ViewerClasses.PaintProc = { IF whatChanged # NIL AND ISTYPE[whatChanged, ToolData] THEN { toolData: ToolData ~ NARROW[whatChanged, ToolData]; toolData.callBackProc[context, toolData]; } ELSE IF originalTSDisplayPaintProc # NIL THEN quit _ originalTSDisplayPaintProc[self, context, whatChanged, clear]; }; TableToolExecCommand: Commander.CommandProc = { [] _ ViewerOps.CreateViewer[flavor: $TableTool, info: [name: "TableTool", scrollable: FALSE]] }; originalTSDisplayPaintProc: ViewerClasses.PaintProc _ NIL; tableToolTIPTable: TIPUser.TIPTable _ TIPUser.InstantiateNewTIPTable["TableTool.TIP"]; tableToolViewerClass: ViewerClasses.ViewerClass ~ NEW[ViewerClasses.ViewerClassRec _ ViewerOps.FetchViewerClass[$Container]^]; containerInitProc: ViewerClasses.InitProc _ tableToolViewerClass.init; containerDestroyProc: ViewerClasses.DestroyProc _ tableToolViewerClass.destroy; containerPaintProc: ViewerClasses.PaintProc _ tableToolViewerClass.paint; tableToolViewerClass.init _ TableToolInitProc; tableToolViewerClass.destroy _ TableToolDestroyProc; tableToolViewerClass.paint _ TableToolPaintProc; tableToolViewerClass.bltH _ none; tableToolViewerClass.bltV _ none; tableToolViewerClass.tipTable _ tableToolTIPTable; ViewerOps.RegisterViewerClass[$TableTool, tableToolViewerClass]; Commander.Register[key: "TableTool", proc: TableToolExecCommand, doc: "Create a table formatting tool"]; END. îTableToolImpl.Mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Rick Beach, June 6, 1985 2:36:27 pm PDT nextX: INTEGER; PROC [self: Viewer, context: Imager.Context, whatChanged: REF ANY, clear: BOOL]; get node from selection search from rootOfTable to end of document for the next table search from the root of the document until rootOfTable for the next table we have another table, so format and display it IF NOT TableSelection.AnEmptySelection[toolData.selection] THEN DoDeleteSelection[toolData, toolData.selection.startBox, toolData.selection.kind]; IF NOT TableSelection.AnEmptySelection[toolData.selection] THEN DoDuplicateRowOrCol[toolData, toolData.selection.startBox, toolData.selection.kind]; IF NOT TableSelection.AnEmptySelection[toolData.selection] THEN DoTransposeTable[toolData, toolData.selection.startBox]; IF NOT TableSelection.AnEmptySelection[toolData.selection] THEN DoMakeRowOrColHeader[toolData, toolData.selection.startBox, toolData.selection.kind]; IF NOT TableSelection.AnEmptySelection[toolData.selection] THEN DoAppendRowOrCol[toolData, toolData.selection.startBox, toolData.selection.kind]; copyRoot: TextNode.Ref; copyRoot _ TextNode.Root[ -- copy the subtree for the slow TSetter to avoid locking issues EditSpanSupport.CopySpan[ -- adds an extra root node TextNode.MakeNodeSpan[rootOfTable, TextNode.LastWithin[rootOfTable]]].start.node]; copyRoot _ TextNode.FirstChild[copyRoot]; [toolData.galley, toolData.style] _ TSTranslate.TreeToVlist[copyRoot]; TEditSelection.InvalidateLineCache[]; -- shouldn't be needed in Cedar6.0, try without it Update the selection selectedBox _ SELECT toolData.selection.kind FROM row => RowRootOf[selectedBox, TRUE], column => ColRootOf[selectedBox, TRUE], ENDCASE => ERROR; IF toolData.selection.startBox # selectedBox THEN { TakeDownSelection[toolData]; toolData.selection.startBox _ toolData.selection.endBox _ selectedBox; PutUpSelection[toolData]; }; toolData.selection.startBox _ toolData.selection.endBox _ selectedBox; selectedBox _ RowRootOf[selectedBox, TRUE]; IF BoxBeforeBox[selectedBox, currentSelection.startBox] THEN { toolData.selection.startBox _ selectedBox; toolData.selection.endBox _ currentSelection.endBox; } ELSE { toolData.selection.startBox _ currentSelection.startBox; toolData.selection.endBox _ selectedBox; }; selectedBox _ ColRootOf[selectedBox, TRUE]; IF BoxBeforeBox[selectedBox, currentSelection.startBox] THEN { toolData.selection.startBox _ selectedBox; toolData.selection.endBox _ currentSelection.endBox; } ELSE { toolData.selection.startBox _ currentSelection.startBox; toolData.selection.endBox _ selectedBox; }; selectedBox _ RowRootOf[selectedBox, TRUE]; IF NOT AreRowSiblings[selectedBox, currentSelection.startBox] THEN RETURN; selectedBox _ ColRootOf[selectedBox, TRUE]; IF NOT AreColSiblings[selectedBox, currentSelection.startBox] THEN RETURN; IF BoxBeforeBox[selectedBox, currentSelection.startBox] THEN { toolData.selection.startBox _ selectedBox; toolData.selection.endBox _ currentSelection.endBox; } ELSE { toolData.selection.startBox _ currentSelection.startBox; toolData.selection.endBox _ selectedBox; }; Could use optimization that paints incremental changes in the selection selectedBox _ SELECT toolData.selectingRowOrColumn FROM row => RowRootOf[selectedBox, TRUE], column => ColRootOf[selectedBox, TRUE], ENDCASE => ERROR; IF currentSelection.kind = box AND selectedBox # currentSelection.startBox THEN GOTO Blink; SELECT toolData.selection.kind FROM row => TableOps.DeleteRowStructure[currentSelection.startBox]; column => TableOps.DeleteColStructure[currentSelection.startBox]; ENDCASE => GOTO Blink; selectedBox _ SELECT toolData.selectingRowOrColumn FROM row => RowRootOf[selectedBox, TRUE], column => ColRootOf[selectedBox, TRUE], ENDCASE => ERROR; IF AreRowSiblings[selectedBox, currentSelection.startBox] AND currentSelection.startBox # FirstRowChild[currentSelection.table.tableRoot] THEN TableOps.CopyRowStructure[currentSelection.startBox, selectedBox, currentSelection.insertion, TRUE] ELSE GOTO Blink; IF AreColSiblings[selectedBox, currentSelection.startBox] AND currentSelection.startBox # FirstColChild[currentSelection.table.tableRoot] THEN TableOps.CopyColStructure[currentSelection.startBox, selectedBox, currentSelection.insertion, TRUE] ELSE GOTO Blink; SELECT toolData.selectingRowOrColumn FROM row => TableOps.MakeRowHeader[currentSelection.table, currentSelection.startBox, currentSelection.endBox]; column => TableOps.MakeColHeader[currentSelection.table, currentSelection.startBox, currentSelection.endBox]; ENDCASE => GOTO Blink; SELECT toolData.selectingRowOrColumn FROM row => TableOps.AppendRow[toolData.selection.table]; column => TableOps.AppendCol[toolData.selection.table]; ENDCASE => SIGNAL CouldNotDoIt; PROCEDURE [dc: Imager.Context, toolData: ToolData] Êâ˜code™Kšœ Ïmœ1™K˜K˜K˜&š  œž œžœžœ˜H˜.Kšœ ˜ K˜ Kšœ˜Kšœ˜K˜—K˜—š œž œžœžœ˜Pšœ"˜"šœ?˜?Kšœžœ žœ˜0—Kšœž˜ K˜—˜KšœYžœ žœ˜oKšœž˜ K˜—K˜—š  œž œžœžœ!ž œžœ˜sšžœ˜Kšœ7žœ˜>Kšœ˜Kšœ ˜ Kšœžœ˜ Kšœžœ˜ Kšœ˜Kšœ˜——Kšœ2˜2KšœÏcB˜\K˜K˜hK˜nK˜NK˜CK˜K˜KšœZ˜ZKšœ‚˜‚Kšœ˜KšœZ˜ZKšœv˜vKšœ‰˜‰KšœW˜WKšœa˜aKšœ`˜`KšœX˜XKšœ^˜^K˜KšœN˜NKšœ#˜#K˜K˜Kšœâ˜âšœ4˜4šœ@˜@Kšœžœ žœ˜/—Kšœž˜ Kšœ˜—Kšœ2˜2K˜KšœP˜PKšœ#˜#K˜K˜šœ3˜3šœ,˜,Kšœžœ žœ˜/—Kšœž˜ Kšœ˜—Kšœ1˜1K˜KšœN˜NKšœ#˜#K˜K˜šœ0˜0˜˜Kšœ&˜&Kšœžœ˜Kšœ ˜ Kšœ žœ˜—Kšœžœ˜ ——šžœžœž˜(Kšœ@˜@—Kšœ5˜5Kšœ5˜5K˜—š œ˜3Kšœ.˜.š žœ žœžœžœžœžœ˜XK˜*Kšœžœ˜Kšœ˜—Kšžœžœžœ˜>Kšœ˜—š œ˜/Kšžœ6žœžœ žœ™PKšžœžœžœ<˜\šžœžœžœžœ˜%Kšœ.˜.š žœ žœžœžœžœ˜1Kšžœžœ˜9—Kšœ˜—K˜—šÏa œ˜ Kšœžœ ˜(Kšœžœ˜K˜—š¢œ˜*Kšœžœ ˜(Kšœ žœ0˜=K˜8Kšœ žœžœ˜K˜Kšœžœ˜K˜šžœžœž˜Kšžœ žœ˜2—šž˜Kšœ!žœ)žœ˜WK˜—šžœ žœž˜K˜k—šžœžœžœž˜KšœN˜N—šžœ˜K˜$Kšœ˜Kšœ˜—K˜—š¢œ˜/Kšœžœ ˜(K˜K˜Kšœžœ˜K™K˜,šžœžœž˜KšœH˜H—šžœžœ˜Kšœžœ ˜*š žœžœžœžœž˜,K˜Kšž˜—šžœžœžœ˜KšœV˜V—šžœ˜Kšœ$˜$K˜Kšœ5˜5Kšœ˜—Kšœ˜—K˜—š  œžœžœžœ˜;K•StartOfExpansion[]š žœžœžœžœžœ˜!šžœ˜Kšœžœžœ)˜DKšžœ˜$Kšœ˜—K˜—š¢œ˜+Kšœžœ ˜(Kšœžœ˜šžœžœžœ˜#KšœY˜Y—šžœ˜Kšœ Ïe œ&™=K˜?š žœžœžœžœž˜,K˜!Kšž˜—šžœžœžœ˜Kšœ+£ œ™IK˜+š žœžœžœžœžœž˜LK˜!Kšž˜—Kšœ˜—šžœžœžœžœ˜2KšœF˜F—šžœ˜K™/Kšœ$˜$K˜Kšœ˜—Kšœ˜—K˜—š œ˜*Kšœžœ ˜(šžœžœ˜K˜Gšœ žœ˜Kš žœžœžœžœžœž˜BKšžœžœ6˜A—šžœžœ˜ šžœžœžœ˜ Kšœ;˜;Kšžœ˜Kšœ˜—šžœ˜šžœžœžœž˜8Kšœ!˜!K˜'Kšž˜—Kšœ˜—K˜—šžœžœ˜K˜2šžœž˜KšœQ˜Q—šžœ˜Kšœ9˜9K˜—Kšœ˜—Kšœ˜—šžœ˜Kšœ1˜1Kšœ˜—Kšœ.˜.K˜—š  œ˜$Kšœžœ ˜(šžœžœžœ˜"K˜&K˜>K˜=K˜—K˜—š  œ˜#Kšœžœ ˜(šžœžœ˜"K˜%K˜>K˜=K˜—K˜—š  œ˜!Kšœžœ ˜(K˜$K˜;K˜;K˜—š  œ˜!Kšœžœ ˜(K˜'K˜;K˜;K˜—š œ˜'Kšœžœ ˜(šžœžœ4žœ™@KšœR™R—K˜—š œ˜*Kšœžœ ˜(šžœžœ4žœ™@KšœT™T—K˜—š œ˜'Kšœžœ ˜(šžœžœ4žœ™@Kšœ8™8—K˜—š œ˜(Kšœžœ ˜(šžœžœ4žœ™@KšœU™U—K˜—š  œ˜$Kšœžœ ˜(šžœžœ4žœ™@KšœQ™Q—K˜—š œž œžœ˜XKš žœžœžœžœžœ*˜HK˜—š œž œžœžœ˜XKšœžœžœ%˜/š žœžœžœžœž˜'Kšœžœ˜—K˜—š œž œžœ˜Xš žœ žœžœžœžœ˜8Kšœ žœ@˜O—K˜—š œžœ4˜MKšžœžœžœ˜,K™Kšžœžœžœ˜#™[šœ¡™4K™R——Kšœ)™)KšœF™FKšœI˜IK˜#K˜—š  œž œ˜0Kšžœžœžœ˜#K˜Kšžœžœ5žœ˜\Kšœ ˜ KšœZ˜ZKšœ˜K˜—š œž œ˜9Kšœ žœžœ˜Kš   œžœžœžœžœ˜DKšœ8˜8˜*Kšœ˜Kšœ˜K˜K˜Kšœž˜K˜—K˜Kšœ*žœ ˜5K˜—š œž œžœ˜?Kšœ3˜3Kšœ>˜>KšœE˜EK™XK˜—š œž œ˜2K˜1šžœžœžœ˜K˜%K˜K˜#Kšœ,˜,Kšœ˜—Kšœ˜—š œž œ˜2K˜1šžœžœž˜Kšœ˜K˜+Kšœ˜—Kšœ˜—Kš  œžœ˜5š œ˜/Kšœ5˜5šœ˜Kšœ˜Kšœ˜Kšœ1˜1šžœžœžœžœžœžœžœž˜@šžœ žœž˜šœžœžœž˜šœ˜Kšœ&˜&Kšœ˜—šœ˜Kšœ%˜%Kšœ˜—šœ ˜ Kšœ$˜$Kšœ˜—šœ ˜ Kšœ'˜'Kšœ˜—šœ ˜ Kšœ#˜#Kšœ˜—šœ ˜ Kšœ-˜-Kšœ˜—šœ ˜ KšœAžœ˜MKšœ˜—šœ˜Kšœ&˜&Kšœ˜—šœ˜Kšœ&˜&Kšœ˜—šœ˜Kšœ&˜&Kšœ˜—šœ˜Kšœ&˜&Kšœ˜—šœ˜Kšœ+˜+Kšœ˜—šœ˜Kšœ)˜)Kšœ˜—šœ˜Kšœ(˜(Kšœ˜—šœ˜Kšœ,˜,Kšœ˜—šœ˜Kšœ(˜(Kšœ˜—Kšžœžœ˜—šœ˜Kšœ ˜ Kšœ1˜1Kšœ˜—Kšžœžœ˜—Kšžœ˜—šž˜Kšœ5˜5—Kšœ˜—K˜Kšœžœžœ˜—š  œž œ3˜Išžœžœžœ˜Kšœ˜Kšœžœžœ7˜YKšœ˜Kšœ˜Kšœ˜—K˜—š œž œZ˜ušžœžœžœ˜Kšžœ žœžœžœ˜;šžœ#žœžœCžœ˜tK™Kšœ˜Kšœ1žœ žœžœ ˜VKšœ˜Kšœ˜—Kšœ˜—K˜—š œž œ3˜Lšžœžœžœ5žœ˜Sšžœž˜#šœ˜šžœ1žœ˜9Kšœ˜Kšœžœžœ7˜YKšœ˜Kšœ˜—Kšœ˜—šœ˜šœžœž™1Kšœžœ™$Kšœ!žœ™'Kšžœžœ™—šžœ+žœ™3Kšœ™KšœG™GKšœ™Kšœ™—Kšœ˜—Kšžœžœ˜—Kšœ˜—K˜—š œž œ3˜Mš žœžœžœžœ5žœ˜WKšœ˜šžœž˜#Kšœ=˜=Kšœ=˜=KšœC˜CKšœ žœ˜Kšžœžœ˜—Kšœ˜Kšœ˜—Kšœ˜—š œž œ3˜Lš žœžœžœžœ5žœ˜WKšœD˜DKšœ˜šžœž˜!šœ˜KšœF™FKšœ˜—šœ˜Kšœ%žœ™+šžœ5ž™>Kšœ*™*Kšœ4™4Kšœ™—šžœ™Kšœ8™8Kšœ(™(Kšœ™—Kšœ˜—šœ ˜ Kšœ%žœ™+šžœ5ž™>Kšœ*™*Kšœ4™4Kšœ™—šžœ™Kšœ8™8Kšœ(™(Kšœ™—Kšœ˜—Kšžœžœ˜—Kšœ˜K˜—K˜—š œž œ3˜Lš žœžœžœžœ5žœ˜WKšœD˜Dšžœž˜!Kšœžœ˜ šœ˜Kšœ%žœ™+Kšžœžœ8žœžœ™JKšœ˜—šœ ˜ Kšœ%žœ™+Kšžœžœ8žœžœ™JKšœ˜—Kšžœžœ˜—Kšœ˜šžœ5ž™>Kšœ*™*Kšœ4™4Kšœ™—šž™Kšœ8™8Kšœ(™(Kšœ™—K™GKšœ˜Kšœ˜—Kšœ˜—š œž œ3˜Oš žœžœžœžœ5žœ˜WKšœD˜DKšžœ%žœžœ˜7šœžœž™7Kšœžœ™$Kšœ!žœ™'Kšžœžœ™—šžœžœ)ž™OKšžœ™ —Kšœ˜šžœž™#Kšœ>™>KšœA™AKšžœžœ™—Kšœ˜K˜—šž˜Kšœ5˜5—K˜—š œž œ3˜Qš žœžœžœžœ5žœ˜WKšœD˜DKšžœžœžœ˜/šœžœž™7Kšœžœ™$Kšœ!žœ™'Kšžœ™—Kšœ˜šžœž˜!šœ˜šžœ8žœMž™ŽKšœ^žœ™c—Kšžœžœ™Kšœ˜—šœ ˜ šžœ8žœLž™ŽKšœ^žœ™c—Kšžœžœ™Kšœ˜—Kšžœžœ˜—Kšœ˜K˜—šž˜Kšœ5˜5—K˜—š œž œ3˜Nš žœžœžœžœ5žœ˜WKšœ˜Kšœ2˜2Kšœ˜K˜—K˜—š œž œ3˜Rš žœžœžœžœ5žœ9žœ˜“KšœD˜DKšœ˜šžœž™)šœ™Kšœc™c—šœ ™ Kšœc™c—Kšžœžœ™—Kšœ˜K˜—K˜—š œž œ3˜Nš žœžœžœžœ5žœ˜WKšœ˜šžœž™)Kšœ4™4Kšœ7™7Kšžœžœ™—Kšœ˜K˜—K˜—š œž œ˜7K˜'K˜Kšžœžœ5žœ˜\K˜4K˜,K˜)Kšžœžœ˜3˜K˜K˜%K˜GK˜J—Kšžœžœ˜5K˜*Kšœžœ˜K˜K˜—š œž œ˜0Kšœžœ˜Kšœžœ˜Kšœžœ˜K˜—š œž œ6žœžœ˜všžœžœžœ˜"Kšœ8˜8K˜+Kšœ-žœ˜HKšœ®˜®Kšœ˜—K˜—š  œž œžœ žœ˜RKšžœYžœU˜·K˜—š œž œ˜5šžœžœ5ž˜?K˜—Kšœžœ˜K˜—š œž œ˜2šžœžœ5ž˜?K˜—K˜—š œž œ˜2K˜9š œ˜)K˜K˜"K˜—š žœžœžœ:žœžœž˜^šžœž˜šœ˜Kšœ7˜7Kšœ˜—šœ˜K˜qKšœ˜—šœ ˜ K˜qKšœ˜—Kšžœžœ˜—Kšž˜—K˜—š œ˜Kšž œ)™2Kšœ8˜8K˜9Kšœ"˜"Kšœ-žœ˜HKšœ žœ˜Kšœ žœI˜VK˜5K˜&Kšœžœ7˜@Kšœžœ9˜BKšœžœ8˜AKšœžœ6˜?Kšœ+˜+Kšœ)˜)Kšœ˜K˜—š œž œ+žœ˜?Kšœ˜Kšœhžœ˜oK˜—š œ˜8š žœžœžœžœžœ˜=Kšœžœ˜3Kšœ)˜)Kšœ˜—šžœžœžœž˜-KšœE˜E—K˜—š œ˜/Kšœ]˜]K˜—Kšœ6žœ˜:KšœV˜Všœ1˜1KšžœI˜L—KšœF˜FKšœO˜OKšœI˜IKšœ.˜.Kšœ4˜4Kšœ0˜0Kšœ!˜!Kšœ!˜!Kšœ2˜2K˜@K˜h—K˜Kšžœ˜—…—aP