IMD 1.17: 19/01/2010 21:10:34 neptune vol 1 6-2-86 neptune, 6/4/86 * , PUniFLEX Backup'From Smalltalk-80 version T2.1.2a, of September 11, 1985 on 4 June 1986 at 11:24:28 am'! !View methodsFor: 'displaying'! display "Display the receiver's border, display the receiver, then display the subViews of the receiver. Can be sent to the top View of a structured picture in order to display the entire structure, or to any particular View in the structure in order to display that View and its subViews. It is typically sent in response to an update request to a View." self displayBorder. f fjTektronix 44042  !"#$%&'()*+,-./01234('&%$#"!  Sensor leftShiftDown ifFalse: [self displayView]. self displaySubViews. self noSelectionSelected.! ! !View methodsFor: 'selection access'! noSelectionSelected "Set the value of the selectionSelected flag to false, indicating there is no saved display form and consequently no selection showing." selectionSelected _ false! selectionIsSelected " Set the value of the selectionSelected flag to true, indicating the saved display form has a selection showing." selectionSelected _ true! setSelection: ? * +-/usr/neptune * , ,  aBoolean "Send the saveSelection message if aBoolean is true, otherwise send a message indicating no selection is set. Send to each of the receiver's subviews." aBoolean ifTrue: [self saveSelection] ifFalse: [self noSelectionSelected]. subViews do: [:aSubView | aSubView setSelection: aBoolean]! ! !View methodsFor: 'scrolling'! scrollBy: aPoint "The x component of aPoint specifies the amount of scrolling in the x direction; the y component specifies the amount of scrolling in the y direct @ * 0changes/usr/neptune 9, 3J J", R3ZJvJ@Rs"zion. The amounts are specified in the receiver's local coordinate system. Scroll the receiver up or down, left or right. The window of the receiver is kept stationary and the subViews and other objects in the receiver are translated relative to it. Scrolling doesn't change the insetDisplayBox or the viewport since the change in the transformation is canceled by the change in the window. In other words, all display objects in the view, except the window, are translated by the scrolling operation." | aRectangle | aRectangle _ self insetDisplayBox. transformation _ transformation scrollBy: aPoint. window _ self getWindow translateBy: aPoint x negated @ aPoint y negated. self unlock. insetDisplayBox _ aRectangle! ! !View methodsFor: 'private'! computeInsetDisplayBox "Compute the View's inset display box by intersecting the superView's inset display box with the View's window transformed to display coordinates and then inseting the result by the border width. It is sent by View|insetDirray initialSelection_ aArray! ! !NodeView methodsFor: 'displaying'! deEmphasizeView (controller isKindOf: ParagraphEditor) ifTrue: [(controller selectionShowing and: [self topView validDisplayForm]) ifTrue: [controller deselectWithEmphasisFlagSet] ifFalse: [controller deselect]]! display self isUnlocked ifTrue: [ controller paragraph recomposeIn: (self insetDisplayBox insetBy: 6 @ 0) clippingBox: self insetDisplayBox. controller recomputeSelection. "ugly initializatisplayBox if the inset display box is nil." displayTransformation isNil ifTrue: [self computeDisplayTransformation]. self isTopView ifTrue: [^(self displayTransform: self getWindow) insetBy: borderWidth] ifFalse: [^(superView insetDisplayBox intersect: (self displayTransform: self getWindow)) insetBy: borderWidth]! ! !SelectionInListView methodsFor: 'controller access'! defaultControllerClass ^ SelectionInListController! ! !NodeView methodsFor: 'update'! newContents controller reson hack: " (controller text isEmpty and: [controller textHasChanged not]) ifTrue: [controller reinitialize. initialSelection isNil ifFalse: [ controller selectAndScrollFrom: (initialSelection at: 1) to: (initialSelection at: 2). initialSelection _ nil]]]. self noSelectionSelected. super display! displayView self clearInside. self controller display! displayView:difference "reposition text and selection after a move operation" controller paragraph moveBy: difference witetstyle. model mergeLinkAttachments. controller reinitialize. self display.! updateRequest | cancel | self controller textHasChanged ifFalse: [^true]. self superView isCollapsed ifFalse: [Display reverse: insetDisplayBox mask: Form gray. Display reverse: (insetDisplayBox insetBy: 4) mask: Form gray]. cancel _ self confirm: 'The text showing has been altered. Do you wish to discard those changes?'. self superView isCollapsed ifFalse: [Display reverse: insetDisplayBox mask: Form gray. Disph: self insetDisplayBox.! ! !StandardSystemView methodsFor: 'deEmphasizing'! deEmphasize "Save the displayForm if appropriate; deEmphasize the view." (self validDisplayForm not) & (Smalltalk saveSpace not) ifTrue: [self saveDisplayForm. self setSelection: true]. self deEmphasizeSubViews. ^self deEmphasizeLabel! ! !AttributeView methodsFor: 'subview creation'! addTypeView: area on: aBrowser | mid | mid _ (area left + area right) * 0.5. self addSubView: (BooleanView on: aBrowser aspect: #alay reverse: (insetDisplayBox insetBy: 4) mask: Form gray]. ^ cancel! ! !NodeView methodsFor: 'controller access'! defaultControllerClass ^NodeController! ! !NodeView methodsFor: 'initialize - release'! initialize super initialize. self insideColor: Form white! newText: aText aText == nil ifTrue: [^ self newText: Text new]. controller paragraph text: aText. self controller scrollToTop; resetState! release super release. self breakDependents! ! !NodeView methodsFor: 'access'! initialSelection: aAsString label: 'string' asText change: #asString: value: true) in: (area copy right: mid) borderWidth: 1. self addSubView: (BooleanView on: aBrowser aspect: #asString label: 'integer' asText change: #asString: value: false) in: (area copy left: mid) borderWidth: 1! ! !NodeStyleView methodsFor: 'subview creation'! addIsArchiveView: area | mid | mid _ (area left + area right) * 0.5. self addSubView: (BooleanView on: (self model) aspect: #isArchive label: 'yes' change: #isArchive: value: true)  in: (area copy right: mid) borderWidth: 1. self addSubView: (BooleanView on: (self model) aspect: #isArchive label: 'no' change: #isArchive: value: false) in: (area copy left: mid) borderWidth: 1.! addLabelView: aString In: aRelativeRectangle | labelView | labelView _ DisplayTextView new model: aString asDisplayText. labelView window: (0@0 extent: 100@100); centered; insideColor: Form white; controller: NoController new. self addSubView: labelView in: aRelativeRectangle borderWidth: 2.! addObjectNaelativeRectangle borderWidth: 1.! addSaveButtonViewIn: aRelativeRectangle | b aSwitchView | b _ Button newOff. b onAction: [model hyperGraph write]. aSwitchView _ SwitchView new model: b. aSwitchView insideColor: Form white. aSwitchView label: (DisplayText text: 'save' asText). aSwitchView borderWidth: 1. self addSubView: aSwitchView in: aRelativeRectangle borderWidth: 1.! addSwitchFor: aString on: anInteger in: aRelativeRectangle | s aSwitchView p mask | mask _ 1 bitShift: anInteger. ((model promeViewIn: aRelativeRectangle objectView _ TextView on: (self model) aspect: #objectNameAsText change: #objectNameFromText: menu: #yellowButtonMenu. objectView window: (0@0 extent: 100 @ 200). objectView borderWidth: 1. self addSubView: objectView in: aRelativeRectangle borderWidth: 2.! addProtectionBitsViewIn: aRelativeRectangle | r a w deltaw| r _ aRelativeRectangle left + (aRelativeRectangle width / 6). a _ aRelativeRectangle copy right: r. w _ 0. deltaw _ a width. self addSwitchFor: 'u r' on:tectionMask) bitAnd: mask) = 0 ifTrue: [s _ Switch newOff] ifFalse: [s _ Switch newOn]. s onAction: [p _ model protectionMask. model protectionMask: (p bitOr: mask)]. s offAction: [p _ model protectionMask. model protectionMask: (p bitAnd: mask bitInvert)]. aSwitchView _ SwitchView new model: s. aSwitchView insideColor: Form white. aSwitchView label: (DisplayText text: aString asText). aSwitchView borderWidth: 1. switchViews at: (anInteger+1) put: aSwitchView. self addSubView: aSwitc 5 in: (a translateBy: w@0). self addSwitchFor: 'u w' on: 4 in: (a translateBy: (w+deltaw)@0). self addSwitchFor: 'g r' on: 3 in: (a translateBy: (w+(2*deltaw))@0). self addSwitchFor: 'g w' on: 2 in: (a translateBy: (w+(3*deltaw))@0). self addSwitchFor: 'o r' on: 1 in: (a translateBy: (w+(4*deltaw))@0). self addSwitchFor: 'o w' on: 0 in: (a translateBy: (w+(5*deltaw))@0).! addRestoreButtonViewIn: aRelativeRectangle | b aSwitchView p | b _ Button newOff. b onAction: [model hyperGraph read. p _ mhView in: aRelativeRectangle borderWidth: 1.! ! !NodeStyleView methodsFor: 'initialization'! clearSwitchViews switchViews _ Array new: 6.! ! !NodeStyleView methodsFor: 'initialize - release'! finish "Does the actual release" super release.! release "Don't want to release subviews or controller because want to reuse them."! ! !NodeVersionsView methodsFor: 'subview creation'! addMajorVersionView: area on: aNodeVersions | l | l _ SelectionInListView on: aNodeVersions aspect: nil change: #changedMaodel protectionMask. #(1 2 3 4 5 6 ) do: [:m | (p bitAnd: (1 bitShift: (m-1))) = 0 ifTrue: [(switchViews at: m) model turnOff] ifFalse: [(switchViews at: m) model turnOn]]. objectView newText: model objectNameAsText; update: #objectNameAsText. objectView controller display]. aSwitchView _ SwitchView new model: b. aSwitchView insideColor: Form white. aSwitchView label: (DisplayText text: 'restore' asText). aSwitchView borderWidth: 1. self addSubView: aSwitchView in: aRjorSelection: list: #convertMajorVersionsTimes menu: #menu initialSelection: nil. self addSubView: l in: area borderWidth: 1! addMinorVersionView: area on: aNodeVersions | l | l _ SelectionInListView on: aNodeVersions aspect: nil change: #changedMinorSelection: list: #convertMinorVersionsTimes menu: #menu initialSelection: nil. self addSubView: l in: area borderWidth: 1! ! !NodeVersionsView methodsFor: 'update'! updateMinorView: index self lastSubView update: nil! ! !NodeVersionsView methodsFor: 'testing'! isMajor ^self firstSubView containsPoint: (Sensor cursorPoint)! ! !ZoomScrollView methodsFor: 'accessing'! graphView: aView graphView _ aView! location ^location! location: aPoint location _ aPoint.! size ^size! size: aPoint size _ aPoint.! ! !ZoomScrollView methodsFor: 'controller access'! defaultControllerClass "Answer the class of the default controller for the receiver." ^ZoomScrollController! ! !ZoomScrollView methodsFor: 'window access'! defaultWindow ^Rectangle origin: 0True: [ location _ (((self inverseDisplayTransform: Sensor cursorPoint) - offset) max: 0@0) min: (1.0@1.0 - size). oldLocation ~= location ifTrue: [ self displayZoomFormAt: oldLocation. oldLocation _ location. self displayZoomForm.]]]. offset ~= nil ifTrue: [self clearInside; displayZoomForm. location ~= previousLocation ifTrue: [self newZoomArea]. Cursor normal show.].! ! !ZoomScrollView methodsFor: 'displaying'! displayOldZoomArea: oldZoomForm at: oldLocation oldZoomForm dis.0@0.0 extent: 1.0@1.0! ! !ZoomScrollView methodsFor: 'changing'! changeSize | oldSize initialSize oldZoomForm oldLocation area | area _ ZoomArea on: size at: location withCursorAt: (self inverseDisplayTransform: Sensor cursorPoint). oldLocation _ location. oldSize _ size. initialSize _ size. self clearInside. self displayOldZoomArea: zoomForm at: oldLocation. self displayZoomForm. area determineActionWithShift: Sensor leftShiftDown. area cursor show. [Sensor yellowButtonPressed] whileTrue: [ playOn: Display at: (self displayTransform: oldLocation) clippingBox: self clippingBox rule: Form over mask: Form veryLightGray.! displayView self makeZoomForm. self clearInside; displayZoomForm.! displayZoomForm self displayZoomForm: zoomForm at: location! displayZoomForm: aForm at: aPoint aForm displayOn: Display at: (self displayTransform: aPoint) clippingBox: self clippingBox rule: Form reverse mask: Form gray.! displayZoomFormAt: aPoint self displayZoomForm: zoomForm at: aPoint area newPosition: (self inverseDisplayTransform: Sensor cursorPoint). size _ area size. location _ area location. oldSize ~= size ifTrue: [ self displayZoomFormAt: oldLocation. oldSize _ size deepCopy. oldLocation _ location deepCopy. self makeZoomForm; displayZoomForm.]]. self clearInside; displayZoomForm. size ~= initialSize ifTrue: [self newZoomArea]. Cursor normal show.! makeZoomForm | p0 p1| p0 _ self displayTransform: location. p1 _ self displayTransform: (location + size). zoom.! ! !ZoomScrollView methodsFor: 'updating'! newZoomArea graphView zoomTo: location*1000 by: (location+size)*1000.! ! !ZoomScrollView methodsFor: 'initialize - release'! release super release. graphView_ nil.! ! !SearchStyleView methodsFor: 'accessing'! findMsg: aMsg findMsg _ aMsg.! invoker: anObject invoker _ anObject.! ! !SearchStyleView methodsFor: 'initialize - release'! finish "Does the actual release" super release.! release "Don't want to release subviews or controller because want Form _ (Form extent: p1 - p0) black.! move | p offset oldLocation previousLocation| p _ self inverseDisplayTransform: Sensor cursorPoint. ((Rectangle origin: location extent: size) containsPoint: p) ifTrue: [Cursor square show. offset _ p - location. oldLocation _ location. previousLocation _ location. self clearInside. self displayOldZoomArea: zoomForm at: oldLocation. self displayZoomForm.] ifFalse: [offset _ nil.]. [Sensor redButtonPressed] whileTrue: [ offset ~= nil ifto reuse them."! ! !SearchStyleView methodsFor: 'subview creation'! addLabelView: aString In: aRelativeRectangle | labelView | labelView _ DisplayTextView new model: (aString asText allBold) asDisplayText. labelView window: (0@0 extent: 100@10); centered; insideColor: Form white; controller: NoController new. self addSubView: labelView in: aRelativeRectangle borderWidth: 1.! addSearchButtonViewIn: aRelativeRectangle |b aSwitchView rpc | b _ Button newOff. b onAction: [model searchEngineMade ifFalse: [rpc _ model hyperGraph rpc. (rpc makeSearch: model searchString) isNil ifTrue: [rpc reportError: 'makeSearch'] ifFalse: [model searchEngineMade: true]]. controller close. invoker perform: findMsg]. aSwitchView _ SwitchView new model: b. aSwitchView insideColor: Form white. aSwitchView label: (DisplayText text: 'search' asText). aSwitchView borderWidth: 1. self addSubView: aSwitchView in: aRelativeRectangle borderWidth: 1.! addSearchStringViewIn: aRelativeRectangle searchStringView l: (DisplayText text: aString asText). aSwitchView borderWidth: 1. self addSubView: aSwitchView in: aRelativeRectangle borderWidth: 1.! addDateBitsViewIn: aRelativeRectangle | r a w deltaw| r _ aRelativeRectangle left + (aRelativeRectangle width / 6). a _ aRelativeRectangle copy right: r. w _ 0. deltaw _ a width. self addButtonFor: 'y +' amount: #nextYear asTime: false inc: true in: (a translateBy: w@0). self addButtonFor: 'y -' amount: #lastYear asTime: false inc: false in: (a translateBy: (w+de_ TextView on: (self model) aspect: #searchStringText change: #searchStringText: menu: #yellowButtonMenu. searchStringView window: (0@0 extent: 1@1). searchStringView borderWidth: 1. self addSubView: searchStringView in: aRelativeRectangle borderWidth: 1.! addTimeViewFor: aTimeSpecifier in: aRelativeRectangle | dateView timeView r | r _ aRelativeRectangle copy right: (aRelativeRectangle left + (aRelativeRectangle width / 2)). dateView _ TextView on: aTimeSpecifier aspect: #dateText change: #dateText:ltaw)@0). self addButtonFor: 'm +' amount: #nextMonth asTime: false inc: true in: (a translateBy: (w+(2*deltaw))@0). self addButtonFor: 'm -' amount: #lastMonth asTime: false inc: false in: (a translateBy: (w+(3*deltaw))@0). self addButtonFor: 'd +' amount: 1 asTime: false inc: true in: (a translateBy: (w+(4*deltaw))@0). self addButtonFor: 'd -' amount: 1 asTime: false inc: false in: (a translateBy: (w+(5*deltaw))@0).! addDateViewIn: aRelativeRectangle | answerView | answerView _ TextView on: (sel menu: #yellowButtonMenu. dateView window: (0@0 extent: 1 @ 1). dateView borderWidth: 1. self addSubView: dateView in: r borderWidth: 1. timeView _ TextView on: aTimeSpecifier aspect: #timeText change: #timeText: menu: #yellowButtonMenu. timeView window: (0@0 extent: 1 @ 1). timeView borderWidth: 1. self addSubView: timeView in: (r translateBy: ((r width)@0)) borderWidth: 1.! ! !TimeSpecifierView methodsFor: 'subview creation'! addButtonFor: aString amount: anAmount asTime: aBoolean1 inc: aBoolean2 f model) aspect: #dateText change: #dateText: menu: #yellowButtonMenu. answerView window: (0@0 extent: 100 @ 200). answerView borderWidth: 1. self addSubView: answerView in: aRelativeRectangle borderWidth: 1.! addLabelView: aString In: aRelativeRectangle | labelView | labelView _ DisplayTextView new model: aString asDisplayText. labelView window: (0@0 extent: 100@100); centered; insideColor: Form white; controller: PromptController new. self addSubView: labelView in: aRelativeRectangle borderWidth: in: aRelativeRectangle | s aSwitchView p | s _ Button newOff. s onAction: (aBoolean1 ifTrue: [[p _ model time. model time: (aBoolean2 ifTrue: [p addTime: anAmount] ifFalse: [p subtractTime: anAmount])]] ifFalse: [ anAmount == 1 ifTrue: [[p _ model date. model date: (aBoolean2 ifTrue: [p addDays: 1] ifFalse: [p subtractDays: 1])]] ifFalse: [[model perform: anAmount]]]). aSwitchView _ SwitchView new model: s. aSwitchView insideColor: Form white. aSwitchView labe1.! addTimeBitsViewIn: aRelativeRectangle | r a w deltaw| r _ aRelativeRectangle left + (aRelativeRectangle width / 6). a _ aRelativeRectangle copy right: r. w _ 0. deltaw _ a width. self addButtonFor: 'h +' amount: (Time fromSeconds: 3600) asTime: true inc: true in: (a translateBy: w@0). self addButtonFor: 'h -' amount: (Time fromSeconds: 3600) asTime: true inc: false in: (a translateBy: (w+deltaw)@0). self addButtonFor: 'm +' amount: (Time fromSeconds: 60) asTime: true inc: true in: (a translateBy: (w+(2*deltaw))@0). self addButtonFor: 'm -' amount: (Time fromSeconds: 60) asTime: true inc: false in: (a translateBy: (w+(3*deltaw))@0). self addButtonFor: 's +' amount: (Time fromSeconds: 1) asTime: true inc: true in: (a translateBy: (w+(4*deltaw))@0). self addButtonFor: 's -' amount: (Time fromSeconds: 1) asTime: true inc: false in: (a translateBy: (w+(5*deltaw))@0).! addTimeViewIn: aRelativeRectangle | answerView | answerView _ TextView on: (self model) aspect: #timeText change: #timeText: er y. x1 _ (pos + bb topCenter) x. y0 _ y1 - (bb width / 8). (Line from: x0@y1 to: x0@y0 withForm: aForm) displayOn: Display at: 0@0 clippingBox: clipRect rule: ruleInteger mask: maskForm. (Line from: x0@y0 to: x1@y0 withForm: aForm) displayOn: Display at: 0@0 clippingBox: clipRect rule: ruleInteger mask: maskForm. (Line from: x1@y0 to: x1@y1 withForm: aForm) displayOn: Display at: 0@0 clippingBox: clipRect rule: ruleInteger mask: maskForm. (Arrow bottomHeadAt: 9) displayOn: Display at: x1@y1 menu: #yellowButtonMenu. answerView window: (0@0 extent: 100 @ 200). answerView borderWidth: 1. self addSubView: answerView in: aRelativeRectangle borderWidth: 1.! ! GraphView comment: 'The following instance variables are used in the manner indicated: xMin - index into the model''s xSortedCollection of the left-most node visible in the current window xMax - index into the model''s xSortedCollection of the right-most node visible in the current window yMin - index into the model''s ySortedCollection ofclippingBox: clipRect rule: ruleInteger mask: maskForm.! displayArrowFrom: fromNode to: toNode "Displays an arrow from fromNode to toNode." | dot | (size > 2) ifTrue: [dot _ Form dotOfSize: 2] ifFalse: [dot _ Form dotOfSize: 1]. self displayArrowFrom: fromNode to: toNode withForm: dot clippingBox: self insetDisplayBox rule: Form under mask: Form black.! displayArrowFrom: fromNode to: toNode withForm: aForm clippingBox: clipRect rule: ruleInteger mask: maskForm "Displays an a the top-most node visible in the current window yMax - index into the model''s ySortedCollection of the bottom-most node visible in the current window visibleNodes - the set of node indices visible in the current window.'! !GraphView methodsFor: 'controller access'! defaultControllerClass "Answer the class of the default controller for the receiver." ^GraphController! ! !GraphView methodsFor: 'window access'! defaultWindow "Answer a Rectangle that will completely contain the receivers model and thenrrow from fromNode to toNode." | places nodePos toPos s nPos tPos nBB tBB xn yn xt yt f | toNode = fromNode ifTrue: [ self displayArrowFor: toNode withForm: aForm clippingBox: clipRect rule: ruleInteger mask: maskForm. ^nil]. places _ model nodePositions. nBB _ (nodeForms at: fromNode) boundingBox. nPos _ self displayTransform: (places at: fromNode). xn _ nPos x. yn _ nPos y. tBB _ (nodeForms at: toNode) boundingBox. tPos _ self displayTransform: (places at: toNode). xt _ tPos x. yt _ tPos  some." ^zoomWindow! ! !GraphView methodsFor: 'displaying'! deEmphasizeView "Make highlighted selection shaded." selectedNode ~= nil ifTrue: [self displaySelectionShaded]! displayArrowFor: aNode withForm: aForm clippingBox: clipRect rule: ruleInteger mask: maskForm "Displays a circular arrow from aNode to aNode" | bb pos pCorner x0 x1 y0 y1| bb _ (nodeForms at: aNode) boundingBox. pos _ self displayTransform: (model nodePositions at: aNode). pCorner _ pos + bb origin. x0 _ pCorner x. y1 _ pCorny. yt < (yn - xn + xt) ifTrue: [ yt < (yn + xn - xt) ifTrue: [ nodePos _ nPos + nBB topCenter. toPos _ tPos + tBB bottomCenter.] ifFalse: [ nodePos _ nPos + nBB rightCenter. toPos _ tPos + tBB leftCenter.] ] ifFalse: [ yt < (yn + xn - xt) ifTrue: [ nodePos _ nPos + nBB leftCenter. toPos _ tPos + tBB rightCenter.] ifFalse: [ nodePos _ nPos + nBB bottomCenter. toPos _ tPos + tBB topCenter.] ]. xt _ toPos x. yt _ toPos y. xn _ nodePos x. yn _ nodePos y. yt < (yn - xn + xt) ifTrue: [ yt < (yn + xn - xt) ifTrue: [f _ Arrow topHeadAt: ((((xt-xn)*8) quo: (yt-yn)) + 9).] ifFalse: [f _ Arrow rightHeadAt: ((((yn-yt)*8) quo: (xt-xn)) + 9).] ] ifFalse: [ yt < (yn + xn - xt) ifTrue: [f _ Arrow leftHeadAt: ((((yt-yn)*8) quo: (xt-xn)) + 9).] ifFalse: [f _ Arrow bottomHeadAt: ((((xn-xt)*8) quo: (yt-yn)) + 9).] ]. f displayOn: Display at: toPos clippingBox: clipRect rule: ruleInteger mask: maskForm. s _ Line from: ((nodePos max: 0@0) min: Display extent) to: ((toPos mBox rule: 12 mask: Form black.! displaySelectionShaded "Display selectedNode shaded when not active window." | f aRectangle position | f _ nodeForms at: selectedNode. position _ self displayTransform: ((model nodePositions) at: selectedNode). aRectangle _ (f computeBoundingBox) moveTo: position. f displayOn: Display at: position clippingBox: self clippingBox rule: Form over mask: Form black. Display fill: aRectangle rule: Form under mask: Form lightGray.! displayView "Display a nax: 0@0) min: Display extent) withForm: aForm. s displayOn: Display at: 0@0 clippingBox: clipRect rule: ruleInteger mask: maskForm.! displayByReferenceArrowFrom: fromNode to: toNode "Displays an arrow from fromNode to toNode." | dot | (size > 2) ifTrue: [dot _ Form dotOfSize: 2] ifFalse: [dot _ Form dotOfSize: 1]. self displayArrowFrom: fromNode to: toNode withForm: dot clippingBox: self insetDisplayBox rule: Form under mask: Form black.! displayByValueArrowFrom: fromNode toumber for each node, an arrow for each link." self formDisplay! emphasizeView "Make shaded selection highlighted." selectedNode ~= nil ifTrue: [self displaySelection]! ! !GraphView methodsFor: 'private'! formDisplay "Displays a graph browser." | nodePos linkAssoc toNodes insetBox insetBoxArea box linkEntry fn tn mask| Cursor execute show. insetBox _ self insetDisplayBox. insetBoxArea _ insetBox area. (insetBoxArea > 300000) ifTrue: [size = 3 ifFalse: [size _ 3. nodeForms _ model forms. : toNode "Displays an arrow from fromNode to toNode." | dot | (size > 2) ifTrue: [dot _ Form dotOfSize: 2] ifFalse: [dot _ Form dotOfSize: 1]. self displayArrowFrom: fromNode to: toNode withForm: dot clippingBox: self insetDisplayBox rule: Form under mask: Form gray.! displayNode: aNode "Display aNode which is not selected." | f aRectangle position| f _ nodeForms at: aNode ifAbsent: [^nil]. f displayOn: Display at: (self displayTransform: ((model nodePositions) at: aNmaxFormHeight _ model maxFormHeight.]] ifFalse: [(insetBoxArea > 100000) ifTrue: [size = 2 ifFalse: [size _ 2. nodeForms _ model forms. maxFormHeight _ (model maxFormHeight) / 2.]] ifFalse: [size = 1 ifFalse:[size _ 1. box _ (Form extent: 7@5) borderWidth: 1. maxFormHeight _ 5. nodeForms _ Dictionary new. (model forms) associationsDo: [:a| nodeForms at: (a key) put: box]]]]. model linksDictionary associationsDo: [:a | linkEntry _ a value. fn _ linkEntry fromNode. tn _ linkEntrode)) clippingBox: self clippingBox rule: Form over mask: Form black. model root = aNode ifTrue: [ position _ self displayTransform: ((model nodePositions) at: aNode). aRectangle _ (f computeBoundingBox) moveTo: position. Display fill: aRectangle rule: Form under mask: Form lightGray.]! displaySelection "Display selectedNode." | f | f _ nodeForms at: selectedNode. f displayOn: Display at: (self displayTransform: ((model nodePositions) at: selectedNode)) clippingBox: self clippingy toNode. (visibleNodes includes: fn) | (visibleNodes includes: tn) ifTrue: [ self displayArrowFrom: fn to: tn]]. visibleNodes do: [:n | n = selectedNode ifTrue: [self displaySelection] ifFalse: [self displayNode: n]]. Cursor normal show.! initializeVisibility | xNodes yNodes xpos ypos m| visibleNodes _ model nodePositions keys. zoomWindow _ Rectangle origin: 0@0 corner: 1000@1000. self initializeZoomStack.! initializeZoomStack zoomStack _ OrderedCollection new.! ! !GraphView methodsFor: 'adding'! addNodeFormForNode: aNode | f | size = 1 ifTrue: [f _ (Form extent: 7@5) borderWidth: 1] ifFalse: [f _ (model forms) at: aNode]. nodeForms at: aNode put: f.! ! !GraphView methodsFor: 'access'! selectedNode ^selectedNode! selectedNode: aNode selectedNode _ aNode.! selectedNodeForm ^(nodeForms at: selectedNode)! zoomView: aView zoomView _ aView.! ! !GraphView methodsFor: 'selecting'! select "Answer with index of node selected; if none selected return nil." | p py oldSelectw) value)+maxHeight)] whileTrue: [low _ low + 1]]]]. ]. (selectedNode = nil) & (oldSelection ~= nil) ifTrue: [self displayNode: oldSelection]. [(p = Sensor cursorPoint) & (Sensor redButtonPressed)] whileTrue. ]. oldSelection ~= nil ifTrue: [oldSelection ~= selectedNode ifTrue:[self displayNode: oldSelection]]. ^selectedNode! ! !GraphView methodsFor: 'updating'! addNode: aNode visibleNodes add: aNode.! deleteNode: aNode visibleNodes remove: aNode ifAbsent: [].! newWindow | vp | zooion n b nodePos pos low mid high orderedNodes a linearSearch maxHeight firstLoop | maxHeight _ model maxFormHeight / (displayTransformation scale y). orderedNodes _ OrderedCollection new: (visibleNodes size). model ySortedNodePositions do: [:a | (visibleNodes includes: a key) ifTrue: [orderedNodes addLast: a]]. oldSelection _ selectedNode. selectedNode _ nil. firstLoop _ true. [firstLoop | Sensor redButtonPressed] whileTrue: [ firstLoop _ false. p _ Sensor cursorPoint. py _ (self inverseDisplamView size: (zoomWindow width / 1000)@(zoomWindow height / 1000); location: (zoomWindow origin)/1000. zoomView displayView. vp _ self getViewport. displayTransformation _ nil. window _ nil. self window: self getWindow viewport: vp.! reinitialize size _ nil. selectedNode _ nil. self initializeVisibility. self newWindow.! updateRequest self model positionsHaveChanged ifFalse: [^true]. ^(self confirm: 'Some node positions have been altered. Do you wish to discard these changes?')! ! !GraphView meyTransform: p) y. linearSearch _ false. selectedNode _ nil. low _ 1. high _ orderedNodes size. [low <= high] whileTrue: [ linearSearch ifTrue: [a _ orderedNodes at: low] ifFalse: [mid _ low + ((high - low) // 2). a _ orderedNodes at: mid]. n _ a key. "node index of current node" pos _ a value. nodePos _ self displayTransform: pos. b _ ((nodeForms at: n) computeBoundingBox) moveTo: nodePos. (b containsPoint: p) ifTrue: [ selectedNode _ a key. oldSelection = nil ifthodsFor: 'un-displaying'! unDisplayArrowFrom: fromNode to: toNode "Clears an arrow from fromNode to toNode." | dot | (size > 2) ifTrue: [dot _ Form dotOfSize: 2] ifFalse: [dot _ Form dotOfSize: 1]. self displayArrowFrom: fromNode to: toNode withForm: dot clippingBox: self insetDisplayBox rule: 0 mask: Form black.! unDisplayNode: aNode "Clear a node from the display" | f | f _ Form extent: ((nodeForms at: aNode) computeBoundingBox corner). f displayOn: Display at: (selTrue: [self displaySelection. oldSelection _ selectedNode] ifFalse: [oldSelection = selectedNode ifFalse:[self displayNode: oldSelection. self displaySelection. oldSelection _ selectedNode]]]. linearSearch ifTrue: [low _ low + 1] ifFalse:[py < (pos y) ifTrue: [high _ mid - 1] ifFalse: [py > ((pos y) + maxHeight) ifTrue: [low _ mid + 1] ifFalse: [linearSearch _ true. [py < ((orderedNodes at: high) value)] whileTrue: [high _ high -1]. [py > (((orderedNodes at: lof displayTransform: ((model nodePositions) at: aNode)) clippingBox: self insetDisplayBox rule: 0 mask: Form white.! ! !GraphView methodsFor: 'zooming'! popFromZoomStack | a| a _ zoomStack removeLast. zoomWindow _ a at: 1. visibleNodes _ a at: 2.! pushToZoomStack zoomStack add: (Array with: zoomWindow with: visibleNodes).! zoomBack zoomStack size = 0 ifTrue: [self flash] ifFalse: [ self popFromZoomStack. self clearInside. self newWindow. self formDisplay.]! zoomOut self pushToZoomStack. visibleNodes _ model nodePositions keys. zoomWindow _ Rectangle origin: 0@0 corner: 1000@1000. self clearInside. self newWindow. self formDisplay! zoomTo: point1 by: point2 | xmin xmax ymin ymax xNodes yNodes m vp | m _ model nodePositions keys size. xmin _ ((model xSortedNodePositions) findFirst: [:e | e value x >= (point1 x - model maxFormWidth)]) max: 1. xmax _ (model xSortedNodePositions) findLast: [:e | e value x <= point2 x]. ymin _ ((model ySortedNodePositions) findFirstn: area borderWidth: 1! addNodeView: area on: aDocument initialSelection: sel | n | n _ TextNode dummyIn: (aDocument hyperGraph). aDocument node: n. self addSubView: (NodeView view: n withSelectedLink: sel) in: area borderWidth: 1! addPredicateViewsIn: area view: topView | topY bottomY nodePredicateLabelView linkPredicateLabelView nodePredicateHolder nodePredicateHolderView cn linkPredicateHolder linkPredicateHolderView cl | topY _ area origin y. bottomY _ area extent y. nodePredicateLabelVi: [:e | e value y >= (point1 y - model maxFormHeight)]) max: 1. ymax _ (model ySortedNodePositions) findLast: [:e | e value y <= point2 y]. xNodes _ SetPlus new: (1 + xmax - xmin). yNodes _ SetPlus new: (1 + ymax - ymin). xmin to: xmax do: [:x | xNodes add: (model xSortedNodePositions at: x) key]. ymin to: ymax do: [:y | yNodes add: (model ySortedNodePositions at: y) key]. self pushToZoomStack. visibleNodes _ xNodes intersect: yNodes. zoomWindow _ Rectangle origin: point1 corner: point2. self clearew _ DisplayTextView new model: 'Nodes:' asDisplayText. nodePredicateLabelView insideColor: Form white; controller: NoController new. nodePredicateLabelView window: (0@0 extent: 1000@1000). topView addSubView: nodePredicateLabelView in: (0.0@topY corner: 0.15@bottomY) borderWidth: 1. linkPredicateLabelView _ DisplayTextView new model: 'Links:' asDisplayText. linkPredicateLabelView insideColor: Form white; controller: NoController new. linkPredicateLabelView window: (0@0 extent: 1000@1000). topView addInside. self newWindow. self formDisplay.! ! !GraphView methodsFor: 'initialize - release'! release super release. zoomView _ nil.! ! !ContextTreeView methodsFor: 'controller access'! defaultControllerClass "Answer the class of the default controller for the receiver." ^ContextTreeController! ! !DocumentView methodsFor: 'subview-creation'! addListView: area on: aBrowser readOnly: RO index: anInteger | list change menu selection | anInteger = 1 ifTrue: [list _ #list1. change _ #select1:. menuSubView: linkPredicateLabelView in: (0.5@topY corner: 0.65@bottomY) borderWidth: 1. nodePredicateHolder _ StringHolder new contents: (model nodePredicate). nodePredicateHolderView _ StringHolderView container: nodePredicateHolder. cn _ PredicateController new. nodePredicateHolderView controller: cn. cn graph: topView model. topView addSubView: nodePredicateHolderView in: (0.15@topY corner: 0.5@bottomY) borderWidth: 1. linkPredicateHolder _ StringHolder new contents: (model linkPredicate). linkPred _ #menu1. selection _ #selection1]. anInteger = 2 ifTrue: [list _ #list2. change _ #select2:. menu _ #menu2. selection _ #selection2]. anInteger = 3 ifTrue: [list _ #list3. change _ #select3:. menu _ #menu3. selection _ #selection3]. anInteger = 4 ifTrue: [list _ #list4. change _ #select4:. menu _ #menu4. selection _ #selection4]. self addSubView: (SelectionInListView on: aBrowser printItems: false oneItem: RO aspect: list change: change list: list menu: menu initialSelection: selection) iicateHolderView _ StringHolderView container: linkPredicateHolder. cl _ PredicateController new. linkPredicateHolderView controller: cl. cl graph: topView model. topView addSubView: linkPredicateHolderView in: (0.65@topY corner: 1@bottomY) borderWidth: 1. cn paragraph clippingRectangle: (0@0 corner: 0.1@0.1). cn accept. cl paragraph clippingRectangle: (0@0 corner: 0.1@0.1). cl accept.! ! !DocumentView methodsFor: 'update'! update: symbol | nh lh | symbol = #newLabel ifTrue: [self resetLabel: (model makeLabel)] ifFalse: [symbol = #flash ifTrue: [self flash]]! updateRequest | nh lh | nh _ (subViews at: 3) model. nh isLocked ifTrue: [^false]. model nodePredicate: (nh contents). lh _ (subViews at: 4) model. lh isLocked ifTrue: [^false]. model linkPredicate: (lh contents). ^true! ! !LinkStyleView methodsFor: 'subview creation'! addDestinationView: area | mid | mid _ (area left + area right) * 0.5. self addSubView: (BooleanView on: (self model) aspect: #destinationByVersion label: 'yes'eanView on: (self model) aspect: #sourceByVersion label: 'no' change: #sourceByVersion: value: true) in: (area copy left: mid) borderWidth: 1.! ! !LinkStyleView methodsFor: 'initialize - release'! finish "Does the actual release" super release.! release "Don't want to release subviews or controller because want to reuse them."! ! !GraphStyleView methodsFor: 'subview creation'! addAbortButtonViewIn: aRelativeRectangle | b aSwitchView | b _ Button newOff. b onAction: [ model actionTaken: true.  change: #destinationByVersion: value: false) in: (area copy right: mid) borderWidth: 1. self addSubView: (BooleanView on: (self model) aspect: #destinationByVersion label: 'no' change: #destinationByVersion: value: true) in: (area copy left: mid) borderWidth: 1.! addLabelView: aString In: aRelativeRectangle | labelView | labelView _ DisplayTextView new model: aString asDisplayText. labelView window: (0@0 extent: 100@100); centered; insideColor: Form white; controller: NoController new. self addSu controller close]. aSwitchView _ SwitchView new model: b. aSwitchView insideColor: Form white. aSwitchView label: (DisplayText text: 'abort' asText). aSwitchView borderWidth: 1. self addSubView: aSwitchView in: aRelativeRectangle borderWidth: 1.! addDirectoryViewIn: aRelativeRectangle | answerView | answerView _ TextView on: (self model) aspect: #directoryText change: #directoryText: menu: #yellowButtonMenu. answerView window: (0@0 extent: 100 @ 200). answerView borderWidth: 1. self addSubView: bView: labelView in: aRelativeRectangle borderWidth: 2.! addRestoreButtonViewIn: aRelativeRectangle | b aSwitchView | b _ Button newOff. b onAction: [model hyperGraph read]. aSwitchView _ SwitchView new model: b. aSwitchView insideColor: Form white. aSwitchView label: (DisplayText text: 'restore' asText). aSwitchView borderWidth: 1. self addSubView: aSwitchView in: aRelativeRectangle borderWidth: 1.! addSaveButtonViewIn: aRelativeRectangle | b aSwitchView | b _ Button newOff. b onAction: [model hanswerView in: aRelativeRectangle borderWidth: 2.! addHostViewIn: aRelativeRectangle | answerView | answerView _ TextView on: (self model) aspect: #hostMachineNameText change: #hostMachineNameText: menu: #yellowButtonMenu. answerView window: (0@0 extent: 100 @ 200). answerView borderWidth: 1. self addSubView: answerView in: aRelativeRectangle borderWidth: 2.! addLabelView: aString In: aRelativeRectangle | labelView | labelView _ DisplayTextView new model: aString asDisplayText. labelView window: (yperGraph write]. aSwitchView _ SwitchView new model: b. aSwitchView insideColor: Form white. aSwitchView label: (DisplayText text: 'save' asText). aSwitchView borderWidth: 1. self addSubView: aSwitchView in: aRelativeRectangle borderWidth: 1.! addSourceView: area | mid | mid _ (area left + area right) * 0.5. self addSubView: (BooleanView on: (self model) aspect: #sourceByVersion label: 'yes' change: #sourceByVersion: value: false) in: (area copy right: mid) borderWidth: 1. self addSubView: (Bool0@0 extent: 100@100); centered; insideColor: Form white; controller: PromptController new. self addSubView: labelView in: aRelativeRectangle borderWidth: 2.! addProceedButtonViewIn: aRelativeRectangle | b aSwitchView | b _ Button newOff. b onAction: [ model actionTaken: true. model proceed: true. controller close]. aSwitchView _ SwitchView new model: b. aSwitchView insideColor: Form white. aSwitchView label: (DisplayText text: 'proceed' asText). aSwitchView borderWidth: 1. self addSubView: aSwitchView in: aRelativeRectangle borderWidth: 1.! addProtectionBitsViewIn: aRelativeRectangle | r a w deltaw| r _ aRelativeRectangle left + (aRelativeRectangle width / 6). a _ aRelativeRectangle copy right: r. w _ 0. deltaw _ a width. self addSwitchFor: 'u r' mask: 2r100000 in: (a translateBy: w@0). self addSwitchFor: 'u w' mask: 2r10000 in: (a translateBy: (w+deltaw)@0). self addSwitchFor: 'g r' mask: 2r1000 in: (a translateBy: (w+(2*deltaw))@0). self addSwitchFor: 'g w' mask: 2r100 in: (a treView _ ScheduledControllers activeController view topView. (activeView notNil and: [activeView isKindOf: StandardSystemView]) ifTrue: [activeView deEmphasize; resetLabelFlag]].! ! !StrikeFont methodsFor: 'accessing'! xTable: anArray xTable _ anArray! ! !LinkFont methodsFor: 'private'! makeDefault name _ 'Link font'. minAscii _ 33. maxAscii _ 34. maxWidth _ 14. ascent _ 11. descent _ 3. strikeLength _ 28. glyphs _ Form extent: 28 @ 14. glyphs copyBits: (Rectangle origin: 0 @ 0 extent: 14anslateBy: (w+(3*deltaw))@0). self addSwitchFor: 'o r' mask: 2r10 in: (a translateBy: (w+(4*deltaw))@0). self addSwitchFor: 'o w' mask: 2r1 in: (a translateBy: (w+(5*deltaw))@0).! addSwitchFor: aString mask: anInteger in: aRelativeRectangle | s aSwitchView p | ((model protectionMask) bitAnd: anInteger) = 0 ifTrue: [s _ Switch newOff] ifFalse: [s _ Switch newOn]. s onAction: [p _ model protectionMask. model protectionMask: (p bitOr: anInteger)]. s offAction: [p _ model protectionMask. m @ 14) from: SourceForm at: 0 @ 0 clippingBox: glyphs boundingBox rule: Form over mask: Form black. glyphs copyBits: (Rectangle origin: 0 @ 0 extent: 14 @ 14) from: DestinationForm at: 14 @ 0 clippingBox: glyphs boundingBox rule: Form over mask: Form black. xTable _ Array new: 257 withAll: 0. xTable at: 35 put: 14. xTable at: 36 put: 28. stopConditions _ Array new: 258 withAll: #characterNotInFont. stopConditions at: 33 put: nil. stopConditions at: 34 put: nil. stopConditions at: 35 put: niodel protectionMask: (p bitAnd: anInteger bitInvert)]. aSwitchView _ SwitchView new model: s. aSwitchView insideColor: Form white. aSwitchView label: (DisplayText text: aString asText). aSwitchView borderWidth: 1. self addSubView: aSwitchView in: aRelativeRectangle borderWidth: 1.! ! !GraphStyleView methodsFor: 'controller access'! defaultControllerClass ^GraphStyleController! ! !FormHolderView methodsFor: 'controller access'! defaultControllerClass ^FormEditor! ! !ControlManager methodsFor: 'displ. stopConditions at: EndOfRun put: #endOfRun. stopConditions at: CrossedX put: #crossedX. subscript _ -3. superscript _ 2. emphasis _ 0. raster _ 62. xOffset _ 0. type _ 32768.! ! !LinkFont methodsFor: 'initialize - release'! initialize ^self makeDefault! ! !LinkFont methodsFor: 'icons'! makeDestinationIcon: aBoolean | f | f _ DestinationForm deepCopy. aBoolean ifTrue: [f borderWidth: 2 mask: Form gray]. ^f! makeNameIcon: aString asSource: aBoolean1 forVersion: aBoolean2 | p r f t prefixFlaying'! restore | activeView | "Clear the screen to gray and then redisplay all the scheduled views." self unschedule: screenController. self scheduleOnBottom: screenController. screenController view window: Display boundingBox. scheduledControllers reverseDo: [:aController | aController class == StandardSystemController ifTrue: [aController view deleteDisplayForm]. aController view display; deEmphasize]. Cursor normal show. ScheduledControllers activeController notNil ifTrue: [activorm | "makes a character icon which contains aString" t _ Text string: aString emphasis: 7. p _ Paragraph withText: t. r _ (p compositionRectangle). f _ Form extent: ((r extent x + 9) @ (r extent y - 2)). aBoolean1 ifTrue: [prefixForm _ SourcePrefixForm] ifFalse: [prefixForm _ DestinationPrefixForm]. f copyBits: (Rectangle origin: -1 @ -1 extent: 6@12) from: prefixForm at: 0 @ 0 clippingBox: f boundingBox rule: Form over mask: Form black. f copyBits: p compositionRectangle from: p asForm at: 7@-1 clippingBox: f boundingBox rule: Form over mask: Form black. aBoolean2 ifTrue: [f borderWidth: 2 mask: Form gray] ifFalse: [f borderWidth: 2]. ^f! makeSourceIcon: aBoolean | f | f _ SourceForm deepCopy. aBoolean ifTrue: [f borderWidth: 2 mask: Form gray]. ^f! ! !LinkFont methodsFor: 'adding characters'! addCharacter: aForm | y myY scale useForm x oldGlyphs oldExtent | "adds a new character to the instance of LinkFont. Glyph for new character is aForm, and the new  start. changeIndex _ i + 1. changeIndex > numChanges ifTrue: [start _ size + 1] ifFalse: [start _ (changeSet at: changeIndex) at: 2. stop _ (changeSet at: changeIndex) at: 3. len _ (changeSet at: changeIndex) at: 4. changeIndex _ changeIndex + 1]]. runs add: (start - head + 1). values add: head. runEncoding _ RunArray runs: runs values: values.! compensateRunsForLinks: links | l c runs charPos count | links isEmpty ifTrue: [^true]. runs _ runEncoindex is returned" maxAscii > 211 ifTrue: [^nil]. useForm _ aForm. y _ aForm extent y. myY _ self height. y > myY ifTrue: [scale _ (y / myY) * 2 @ (y / myY) * 2. useForm _ aForm shrinkBy:scale]. y < myY ifTrue: [scale _ (myY / y) * 2 @ (myY / y) * 2. useForm _ aForm magnifyBy: scale]. x _ useForm extent x. x > maxWidth ifTrue: [maxWidth _ x]. oldGlyphs _ glyphs. oldExtent _ oldGlyphs extent. glyphs _ Form extent: (oldExtent x + x) @ 14. glyphs copyBits: (Rectangle origin: 0 @ 0 extent: ding runs. l _ links first. 1 to: (runs size) do: [:i | charPos _ runs at: i. count _ 0. [(l isNil not) and: [l charPosition <= charPos]] whileTrue: [count _ count + 1. l _ l nextLink]. runs at: i put: (charPos + count). l isNil ifTrue: [^true]].! compensateValuesForLinks: links | l c values charPos count | links isEmpty ifTrue: [^true]. values _ runEncoding values. l _ links first. count _ 0. 1 to: (values size) do: [:i | charPos _ values at: i. [(l isNil not) and: [l charPositionoldExtent) from: oldGlyphs at: 0 @ 0 clippingBox: glyphs boundingBox rule: Form over mask: Form black. glyphs copyBits: (Rectangle origin: 0 @ 0 extent: (useForm extent)) from: useForm at: (oldExtent x) @ 0 clippingBox: glyphs boundingBox rule: Form over mask: Form black. maxAscii _ maxAscii + 1. xTable at: maxAscii + 2 put: (oldExtent x + x). stopConditions at: (maxAscii + 1) put: nil. strikeLength _ oldExtent x + x. ^maxAscii! ! !NodeChangeSet methodsFor: 'private'! buildLineMapFrom:  < charPos]] whileTrue: [count _ count + 1. l _ l nextLink]. values at: i put: (charPos + count). ].! extractDiff: aByteArray text: aText | s i pos c r size offset | size _ aText size. s _ aByteArray size. changeSet _ OrderedCollection new. i _ 1. offset _ 1. "initialize offset to compensate for first index of array == 1 in smalltalk" [i < s] whileTrue: [ c _ aByteArray at: i. i _ i + 1. r _ Array new: 4. r at: 1 put: c. c == 1 ifTrue: ["deletion: index1, index2" r at: 2 put: aText | s size runs values head numChanges changeIndex start stop len | s _ aText string. size _ s size. runs _ OrderedCollection new. values _ OrderedCollection new. head _ 1. numChanges _ changeSet size. numChanges < 1 ifTrue: [start _ size + 1] ifFalse: [start _ (changeSet at: 1) at: 2. stop _ (changeSet at: 1) at: 3. len _ (changeSet at: 1) at: 4. ]. 1 to: numChanges do: [:i | runs add: (start - head). values add: head. head _ stop + 1. runs add: len. values add:((self extractIntFrom: aByteArray startingAt: i) + offset). r at: 3 put: ((self extractIntFrom: aByteArray startingAt: (i + 4)) + offset). r at: 4 put: 1. i _ i + 8. ] ifFalse: [c == 2 ifTrue: ["replacement: index1, index2, string" r at: 2 put: ((self extractIntFrom: aByteArray startingAt: i) + offset). r at: 3 put: ((self extractIntFrom: aByteArray startingAt: (i + 4)) + offset). r at: 4 put: (self extractIntFrom: aByteArray startingAt: (i + 8)). i _ i + 12 + (r at: 4).  ] ifFalse: [c == 3 ifTrue: ["insertion: index string" r at: 2 put: ((self extractIntFrom: aByteArray startingAt: i) + offset). r at: 3 put: (r at: 2) . r at: 4 put: (self extractIntFrom: aByteArray startingAt: (i + 4)). offset _ offset + 1. "compensate for insertion marker" i _ i + 8 + (r at: 4). ] ifFalse: [c == 4 ifTrue: ["addition: string" r at: 2 put: (size + offset). r at: 3 put: ((r at: 2) + 1). r at: 4 put: (self extractIntFrom: aByteArray startingAt: i). ofHaveChanged: false. Cursor normal show.] ifTrue: [Transcript cr; show: 'Can''t change history'. self view flash].! autoPositionNodes "Automatically reposition all of the nodes." | v m | v _ self view. m _ view model. m isHistory ifFalse: [ m root = nil ifTrue: [Transcript cr; show: 'No root defined'. v flash. ^nil]. Cursor execute show. v model autoPosition. v clearInside: Form white. v displayView. Cursor normal show.] ifTrue: [Transcript cr; show: 'Can''t change history'. v flash].!fset _ offset + 1. "compensate for insertion marker" i _ i + 4 + (r at: 4). ]]]]. changeSet add: r ].! extractIntFrom: aByteArray startingAt: pos | s i | s _ 0. i _ pos. 4 timesRepeat: [s _ (s bitShift: 8) + (aByteArray at: i). i _ i + 1]. ^s! firstCharFor: aCharIndex | runs values count index | runs _ runEncoding runs. values _ runEncoding values. count _ runs at: 1. index _ 1. [aCharIndex > count] whileTrue: [ index _ index + 1. count _ count + (runs at: index).]. ^(count - (runs at browseDocument "Spawn a document browser on root" | n nodePredicateHolder linkPredicateHolder subviews r name d rpc | n _ view selectedNode. n = nil ifTrue: [Transcript cr; show: 'No node selected'. view flash. ^nil]. subviews _ view superView subViews. nodePredicateHolder _ subviews nextToLast model. linkPredicateHolder _ subviews last model. (nodePredicateHolder isLocked) | (linkPredicateHolder isLocked) ifTrue: [ Transcript cr; show: 'Node and/or link predicate must be accepted'. view flash: index)) + 1! ! !NodeChangeSet methodsFor: 'testing'! isAdditionAt: anIndex ^(((changeSet at: anIndex) at: 1) == 4)! isDeletionAt: anIndex ^(((changeSet at: anIndex) at: 1) == 1)! isInsertionAt: anIndex ^(((changeSet at: anIndex) at: 1) == 3)! isReplacementAt: anIndex ^(((changeSet at: anIndex) at: 1) == 2)! ! !NodeChangeSet methodsFor: 'access'! changeSet ^changeSet! runEncoding ^runEncoding! ! !GraphController methodsFor: 'menu messages'! accept "Save the node positions in .x and .y attributes.. ^nil]. (rpc _ model hyperGraph rpcFor: (model context)) isNil ifTrue: [^nil]. r _ rpc getNodeAttributeValue: n for: (model hyperGraph iconNameIndex) at: (model nodeVersion: n). r isNil ifTrue: [^nil]. name _ (r at: 1) ifTrue: [r at: 2] ifFalse: [nil]. d _ Document new. d versionTime: (model versionTime); hyperGraph: (model hyperGraph). d nodePredicate: (nodePredicateHolder contents); linkPredicate: (linkPredicateHolder contents). d root: (Array with: n with: (model nodeVersion: n) with: name). Do" | m n p rpc | m _ self model. m isHistory ifFalse: [ (rpc _ m hyperGraph rpcFor: (m context)) isNil ifTrue: [^nil]. (rpc beginTransaction: true) isNil ifTrue: [rpc reportError: 'beginTransaction'. ^nil]. m nodePositions associationsDo: [:a | n _ a key. p _ a value. (m setPositionAttributes: p forNode: n) ifFalse: [ rpc reportErrorAborting: 'setNodeAttributeValue'. ^nil]]. (rpc commitTransaction) ifFalse: [rpc reportErrorAborting: 'commitTransaction'. ^nil]. m positionscumentView openOn: d.! browseGraph "Show the graph implied by the predicates given in the bottom view" | v m nodePredicateHolder linkPredicateHolder subviews reply | "MessageTally spyOn: [" v _ self view. m _ v model. subviews _ v superView subViews. nodePredicateHolder _ subviews nextToLast model. linkPredicateHolder _ subviews last model. (nodePredicateHolder isUnlocked) ifFalse: [subviews nextToLast controller accept]. (linkPredicateHolder isUnlocked) ifFalse: [subviews last controller accept]. m positionsHaveChanged ifTrue: [ reply _ BinaryChoice message: 'Some node positions have been altered. Do you wish to discard these changes?'. reply ifFalse: [Cursor normal show. ^nil]]. (m readGraph: (nodePredicateHolder contents) linkPredicate: (linkPredicateHolder contents) linearly: false depth: 0) isNil ifTrue: [^nil]. v clearInside; reinitialize; displayView. Cursor normal show. "]."! browseNode | v m n rpc | v _ self view. n _ v selectedNode. n = nil ifTrue: [Transcript cr; shsh. ^nil]. (model compareNode: n) ifFalse: [view flash]. Cursor normal show.! createNode | n p icon r rpc | model isHistory ifFalse: [ Cursor crossHair show. Sensor waitButton. Cursor execute show. p _ view inverseDisplayTransform: (Sensor cursorPoint). icon _ FillInTheBlank request: 'Type node name'. (rpc _ model hyperGraph rpcFor: (model context)) isNil ifTrue: [^nil]. (rpc beginTransaction: true) isNil ifTrue: [rpc reportError: 'beginTransaction:'. ^nil]. r _ Node createIn: modow: 'No node selected'. v flash. ^nil]. m _ v model. (rpc _ m hyperGraph rpcFor: (m context)) isNil ifTrue: [v flash. ^nil]. Node open: n versionTime: (m nodeVersion: n) in: (m hyperGraph)! browseNodeAttributes | v m n rpc | v _ self view. n _ v selectedNode. n = nil ifTrue: [Transcript cr; show: 'No node selected'. v flash. ^nil]. m _ v model. (rpc _ m hyperGraph rpcFor: (m context)) isNil ifTrue: [v flash. ^nil]. Attribute openOnNode: n versionTime: (m nodeVersion: n) in: (m hyperGraph)! el hyperGraph. r isNil ifTrue: [^nil]. n _ r nodeIndex. "node index" model addNode: n version: 0 withIcon: icon withPosition: p. (model setPositionAttributes: p forNode: n) ifFalse: [ rpc reportErrorAborting: 'setNodeAttributeValue'. ^nil]. icon size ~= 0 ifTrue: [(model setIconAttribute: icon forNode: n) ifFalse: [ rpc reportErrorAborting: 'setNodeAttributeValue'. ^nil]]. rpc commitTransaction. view addNode: n; addNodeFormForNode: n. view selectedNode ~= nil ifTrue: [view displayNobrowseNodeVersions | v m n rpc | v _ self view. n _ v selectedNode. n = nil ifTrue: [Transcript cr; show: 'No node selected'. v flash. ^nil]. m _ v model. (rpc _ m hyperGraph rpcFor: (m context)) isNil ifTrue: [v flash. ^nil]. NodeVersions openOn: n in: (m hyperGraph)! browseVersionTime | aTimeSpecifier t | aTimeSpecifier _ self view model hyperGraph timeSpecifier. t _ model versionTime. t = 0 ifTrue: [aTimeSpecifier now] ifFalse: [aTimeSpecifier unixVersionTime: t]. TimeSpecifierView opde: view selectedNode]. view selectedNode: n; displaySelection. Cursor normal show.] ifTrue: [Transcript cr; show: 'Can''t change history'. self view flash].! currentVersion model versionTime: 0. model isHistory: false. view superView resetLabel: (model makeLabel)! deleteNode | n r links linkEntry rpc | model isHistory ifFalse: [ n _ view selectedNode. n = nil ifTrue: [Transcript cr; show: 'No node selected'. view flash. ^nil]. (BinaryChoice message: 'Do you really want to delete thisenOn: aTimeSpecifier.! compactGraph model compactGraph ifFalse: [view flash]. Cursor normal show.! compactNode | v n | v _ self view. n _ v selectedNode. n = nil ifTrue: [Transcript cr; show: 'No node selected'. v flash. ^nil]. (model compactNode: n) ifFalse: [view flash]. Cursor normal show.! compareGraph model compareGraph ifFalse: [view flash]. Cursor normal show.! compareNode | v n | v _ self view. n _ v selectedNode. n = nil ifTrue: [Transcript cr; show: 'No node selected'. v fla node?') ifFalse: [^nil]. (rpc _ model hyperGraph rpcFor: (model context)) isNil ifTrue: [^nil]. r _ rpc deleteNode: n. r isNil ifTrue: [ rpc reportError: 'deleteNode'. Cursor normal show. ^nil]. view unDisplayNode: n. links _ model linksDictionary. links associationsDo: [:a | ((a value toNode) = n) | ((a value fromNode) = n) ifTrue: [ linkEntry _ a value. view unDisplayArrowFrom: (linkEntry fromNode) to: (linkEntry toNode)]]. model deleteNode: n. view deleteNode: n; selectedNode: nil. Cursor normal show.] ifTrue: [Transcript cr; show: 'Can''t change history'. self view flash].! editLinkStyle Cursor execute show. self model hyperGraph linkStyle open.! editNodeStyle Cursor execute show. self model hyperGraph nodeStyle open.! fileOut "Files out the graph implied by the predicate given in the bottom view" | v m fileName subviews nodePredicateHolder linkPredicateHolder | v _ self view. m _ v model. subviews _ v superView subViews. nodePredicateHolder _ subviews neversion: 0 from: fromNode to: toNode. v displayArrowFrom: fromNode to: toNode. Cursor normal show.] ifTrue: [Transcript cr; show: 'Can''t change history'. self view flash].! linkTo | v m n fromNode toNode linkResult| v _ self view. n _ v selectedNode. n = nil ifTrue: [Transcript cr; show: 'No node selected'. v flash. ^nil]. m _ v model. m isHistory ifFalse: [ toNode _ v selectedNode. Cursor crossHair show. Sensor waitButton. fromNode _ v select. fromNode isNil ifTrue: [Cursor normal xtToLast model. linkPredicateHolder _ subviews last model. (nodePredicateHolder isUnlocked) & (linkPredicateHolder isUnlocked) ifTrue: [m root = nil ifTrue: [Transcript cr; show: 'No node selected'. v flash. ^nil]. fileName _ FillInTheBlank request: 'Type file name'. fileName size == 0 ifFalse: [ m fileOutGraphNodes: (nodePredicateHolder contents) links: (linkPredicateHolder contents) toFile: fileName depth: depth. Cursor normal show]] ifFalse: [Transcript cr; show: 'Node show. ^nil] ifFalse: [Cursor execute show]. linkResult _ (m hyperGraph) addLinkFrom: fromNode to: toNode. linkResult isNil ifTrue: [Cursor normal show. ^nil]. m addLink: linkResult version: 0 from: fromNode to: toNode. v displayArrowFrom: fromNode to: toNode. Cursor normal show.] ifTrue: [Transcript cr; show: 'Can''t change history'. self view flash].! mergeGraph model mergeGraph ifFalse: [view flash]. Cursor normal show.! mergeNode | v n | v _ self view. n _ v selectedNode. n = and/or link predicate must be accepted'. v flash. ^nil]! hide | v m n r links linkEntry | v _ self view. n _ v selectedNode. n = nil ifTrue: [Transcript cr; show: 'No node selected'. v flash. ^nil]. m _ v model. v unDisplayNode: n. links _ m linksDictionary. links associationsDo: [:a | ((a value toNode) = n) | ((a value fromNode) = n) ifTrue: [ linkEntry _ a value. v unDisplayArrowFrom: (linkEntry fromNode) to: (linkEntry toNode)]]. m deleteNode: n. v selectedNode: nil.! linkFrom | v m nil ifTrue: [Transcript cr; show: 'No node selected'. v flash. ^nil]. (model mergeNode: n) ifFalse: [view flash]. Cursor normal show.! newRoot | v m n oldRoot| v _ self view. m _ v model. n _ v selectedNode. n = nil ifTrue: [Transcript cr; show: 'No node selected'. v flash. ^nil]. oldRoot _ m root. n ~= oldRoot ifTrue:[ m root: n. oldRoot ~= nil ifTrue: [v displayNode: oldRoot.]]! printOut "Prints out the graph implied by the predicate given in the bottom view" | v m fileName subviewsn fromNode toNode linkResult | v _ self view. n _ v selectedNode. n isNil ifTrue: [Transcript cr; show: 'No node selected'. v flash. ^nil]. m _ v model. m isHistory ifFalse: [ fromNode _ v selectedNode. Cursor crossHair show. Sensor waitButton. toNode _ v select. toNode isNil ifTrue: [Cursor normal show. ^nil] ifFalse: [Cursor execute show]. linkResult _ (m hyperGraph) addLinkFrom: fromNode to: toNode. linkResult isNil ifTrue: [Cursor normal show. ^nil]. m addLink: linkResult  nodePredicateHolder linkPredicateHolder | v _ self view. m _ v model. subviews _ v superView subViews. nodePredicateHolder _ subviews nextToLast model. linkPredicateHolder _ subviews last model. (nodePredicateHolder isUnlocked) & (linkPredicateHolder isUnlocked) ifTrue: [m root = nil ifTrue: [Transcript cr; show: 'No node selected'. v flash. ^nil]. fileName _ FillInTheBlank request: 'Type file name'. fileName size == 0 ifFalse: [m printOutGraphNodes: (nodePredicateHolder contents)  links: (linkPredicateHolder contents) toFile: fileName depth: depth. Cursor normal show]] ifFalse: [Transcript cr; show: 'Node and/or link predicate must be accepted'. v flash. ^nil]! redButtonActivity "Takes care of selecting nodes" self view select! repositionNode "Allows repositioning of selected node." | v m n oldPosition links linkEntry fromNode toNode| v _ self view. n _ v selectedNode. n = nil ifTrue: [Transcript cr; show: 'No node selected'. v flash. ^nil]. m _ v model. m isHubviews last model. (nodePredicateHolder isUnlocked) ifFalse: [subviews nextToLast controller accept]. (linkPredicateHolder isUnlocked) ifFalse: [subviews last controller accept]. m positionsHaveChanged ifTrue: [ reply _ BinaryChoice message: 'Some node positions have been altered. Do you wish to discard these changes?'. reply ifFalse: [Cursor normal show. ^nil]]. m root = nil ifTrue: [Transcript cr; show: 'No root defined'. v flash. ^nil]. (m readGraph: (nodePredicateHolder contents) linkPristory ifFalse: [ v unDisplayNode: n. links _ m linksDictionary. links associationsDo: [:a | ((a value toNode) = n) | ((a value fromNode) = n) ifTrue: [ linkEntry _ a value. v unDisplayArrowFrom: (linkEntry fromNode) to: (linkEntry toNode)]]. Cursor crossHair show. Sensor waitButton. Cursor execute show. m repositionNode: n at: (v inverseDisplayTransform:(Sensor cursorPoint)). v displaySelection. links associationsDo: [:a | ((a value toNode) = n) | ((a value fromNode) = n) ifTrue: [ edicate: (linkPredicateHolder contents) linearly: true depth: depth) isNil ifTrue: [^nil]. v clearInside; reinitialize; displayView. Cursor normal show.! zoomBack view zoomBack! zoomIn | r | r _ Rectangle fromUser. view zoomTo: (view inverseDisplayTransform: r origin) by: (view inverseDisplayTransform: r corner).! zoomOut view zoomOut! ! !GraphController methodsFor: 'initialize - release'! initialize super initialize. depth _ 0. self yellowButtonMenu: YellowButtonMenu yellowButtonMessage linkEntry _ a value. fromNode _ linkEntry fromNode. toNode _ linkEntry toNode. v displayArrowFrom: fromNode to: toNode]]. Cursor normal show.] ifTrue: [Transcript cr; show: 'Can''t change history'. v flash].! search self controlTerminate. Cursor execute show. model hyperGraph searchStyle openWithInvoker: self find: #findOccurrences.! setVersionTime | aTimeSpecifier time | time _ self view model hyperGraph timeSpecifier unixVersionTime. model versionTime: time. model isHistory: true. s: YellowButtonMessages! ! !GraphController methodsFor: 'control defaults'! isControlActive ^(view containsPoint: sensor cursorPoint) & sensor blueButtonPressed not! ! !GraphController methodsFor: 'searching'! findOccurrences | searchString n a b r m s rpc g | g _ model hyperGraph. s _ g searchStyle. searchString _ s searchString. n _ model nodes associations. a _ Array new: (n size). 1 to: (n size) do: [:i | b _ Array new: 4. a at: i put: b. m _ n at: i. b at: 1 put: (m key). b at: 2 pview superView resetLabel: (model makeLabel)! traversalDepth "Allows editing the traversal depth" | d | d _ FillInTheBlank request: 'Type traversal depth' initialAnswer: (depth printStringRadix: 10). depth _ d asNumber.! traverseGraph "Show the graph implied by the predicates given in the bottom view" | v m nodePredicateHolder linkPredicateHolder subviews reply | v _ self view. m _ v model. subviews _ v superView subViews. nodePredicateHolder _ subviews nextToLast model. linkPredicateHolder _ sut: (s startingTime). b at: 3 put: (s endingTime). b at: 4 put: 0"starting position"]. (rpc _ g rpcFor: (model context)) isNil ifTrue: [^nil]. r _ rpc searchContents: (n size) nodeList: a nodeAttributes: (Array with: (g iconNameIndex)) code: 0. r isNil ifTrue: [rpc reportError: 'searchContents'. ^nil]. SearchResults openOn: r in: (g)! ! !ContextTreeController methodsFor: 'initialize - release'! initialize super initialize. self yellowButtonMenu: CYellowButtonMenu yellowButtonMessages: CYellowButtonMessages! ! !ContextTreeController methodsFor: 'menu messages'! accept "Save the context positions in .x and .y attributes." | m n p rpc | m _ self model. (rpc _ m hyperGraph rpcFor: (m context)) isNil ifTrue: [^nil]. m isHistory ifFalse: [ (rpc beginTransaction: true) isNil ifTrue: [rpc reportError: 'beginTransaction'. ^nil]. m nodePositions associationsDo: [:a | n _ a key. p _ a value. (m setPositionAttributes: p forContext: n) ifFalse: [ rpc reportErrorAborting: 'sNil ifTrue: [^nil]. parentContext ~= graph currentContext ifTrue: [ r _ rpc openContext: parentContext. r isNil ifTrue: [rpc reportError: 'openContext'. ^nil]]. Cursor crossHair show. Sensor waitButton. Cursor execute show. p _ view inverseDisplayTransform: (Sensor cursorPoint). icon _ FillInTheBlank request: 'Type context name'. (rpc beginTransaction: true) isNil ifTrue: [rpc reportError: 'beginTransaction:'. ^nil]. r _ rpc createContextWithMask: 63. r isNil ifTrue: [^nil]. setContextAttributeValue'. ^nil]]. (rpc commitTransaction) ifFalse: [rpc reportErrorAborting: 'commitTransaction'. ^nil]. m positionsHaveChanged: false. Cursor normal show.] ifTrue: [Transcript cr; show: 'Can''t change history'. self view flash].! browseContextAttributes | n | n _ view selectedNode. n = nil ifTrue: [Transcript cr; show: 'No context selected'. view flash. ^nil]. Attribute openOnContext: n versionTime: (model nodeVersion: n) in: (model hyperGraph)! compactContext | n r enn _ r at: 1. "context index" model addNode: n version: 0 withIcon: icon withPosition: p. (model setPositionAttributes: p forContext: n) ifFalse: [ rpc reportErrorAborting: 'setContextAttributeValue'. ^nil]. icon size ~= 0 ifTrue: [(model setIconAttribute: icon forContext: n) ifFalse: [ rpc reportErrorAborting: 'setContextAttributeValue'. ^nil]]. rpc commitTransaction. graph currentContext: n. icon size ~= 0 ifTrue: [graph contextName: icon] ifFalse: [graph contextName: '']. view tirely rpc | model isHistory ifFalse: [ n _ view selectedNode. n = nil ifTrue: [Transcript cr; show: 'No context selected'. view flash. ^nil]. n ~= model hyperGraph currentContext ifTrue: [ Transcript cr; show: 'Can only compact current context'. view flash. ^nil]. entirely _ BinaryChoice message: 'Do you want to discard all history?'. (rpc _ model hyperGraph rpcFor: (model context)) isNil ifTrue: [^nil]. r _ rpc compactContext: entirely. r isNil ifTrue: [rpc reportError: 'compactCoaddNode: n; addNodeFormForNode: n. view selectedNode ~= nil ifTrue: [view displayNode: view selectedNode]. view selectedNode: n; displaySelection. model addLink: n version: 0 from: parentContext to: n. view displayArrowFrom: parentContext to: n. Cursor normal show.] ifTrue: [Transcript cr; show: 'Can''t change history'. self view flash].! deleteContext | n r links linkEntry rpc | model isHistory ifFalse: [ n _ view selectedNode. n = nil ifTrue: [Transcript cr; show: 'No context selected'ntext'. ^nil]. Cursor normal show] ifTrue: [Transcript cr; show: 'Can''t change history'. self view flash].! createContext | n parentContext p icon r rpc graph | n _ view selectedNode. n isNil ifTrue: [Transcript cr; show: 'No parent context selected'. view flash. ^nil]. model isHistory ifFalse: [ graph _ model hyperGraph. parentContext _ view selectedNode. parentContext isNil ifTrue: [Cursor normal show. ^nil] ifFalse: [Cursor execute show]. (rpc _ graph rpcFor: (model context)) i. view flash. ^nil]. (BinaryChoice message: 'Do you really want to delete this context?') ifFalse: [^nil]. (rpc _ model hyperGraph rpcFor: (model context)) isNil ifTrue: [^nil]. r _ rpc destroyContext: n. r isNil ifTrue: [ rpc reportError: 'destroyContext'. ^nil]. model hyperGraph targetContext = n ifTrue: [model hyperGraph targetContext: nil]. view unDisplayNode: n. links _ model linksDictionary. links associationsDo: [:a | ((a value toNode) = n) | ((a value fromNode) = n) ifTrue: [ linkEntry _ a value. view unDisplayArrowFrom: (linkEntry fromNode) to: (linkEntry toNode)]]. model deleteNode: n. view deleteNode: n; selectedNode: nil. Cursor normal show.] ifTrue: [Transcript cr; show: 'Can''t change history'. self view flash].! enterContext | n r rpc | n _ view selectedNode. (rpc _ model hyperGraph rpcFor: (model context)) isNil ifTrue: [^nil]. n notNil ifTrue: [r _ rpc openContext: n. Cursor normal show. r isNil ifTrue: [rpc reportError: 'openContext'. Node: nil]].! target | c n | n _ view selectedNode. n isNil ifTrue: [Transcript cr; show: 'Context not selected'. view flash. ^nil]. model hyperGraph targetContext: n! traverse view flash.! ! !ParagraphEditor methodsFor: 'editing'! echo: c "Echo the character c at echoLocation and advance echoLocation's x by the width of c. Return if there isn't room on this line for c. The characters will later be composed for real deep inside of paragraph. This is just for echoing the easy cases very fast.^nil]]. model hyperGraph currentContext: n.! query "Show the context tree implied by the predicate given in the bottom view" | v m predicateHolder subviews reply | "MessageTally spyOn: [" v _ self view. m _ v model. subviews _ v superView subViews. predicateHolder _ subviews last model. (predicateHolder isUnlocked) ifFalse: [subviews last controller accept]. m positionsHaveChanged ifTrue: [ reply _ BinaryChoice message: 'Some context positions have been altered. Do you wish to discard these chan" | characterForm ascii character clipRect | clipRect _ paragraph clippingRectangle intersect: paragraph compositionRectangle. clipRect height = 0 ifTrue: [clipRect height: paragraph textStyle lineGrid]. echoLocation x > clipRect right ifTrue: [^c]. ascii _ (character _ c) asciiValue. (ascii < currentFont minAscii or: [ascii > currentFont maxAscii]) ifTrue: [character _ (ascii _ currentFont maxAscii + 1) asCharacter]. characterForm _ currentFont characterForm: character. characterForm displayOnges?'. reply ifFalse: [Cursor normal show. ^nil]]. m readGraph: (predicateHolder contents) linearly: false depth: 0. v clearInside; reinitialize; displayView. Cursor normal show. "]."! showCurrentContext | c n | c _ model hyperGraph currentContext. n _ view selectedNode. c = n ifFalse: [n notNil ifTrue: [view displayNode: n]. (model nodes keys includes: c) ifTrue: [view selectedNode: c; displaySelection] ifFalse: [view flash. Transcript cr; show: 'Context view does not i: Display at: echoLocation clippingBox: clipRect. echoLocation x: echoLocation x + (currentFont widthOf: c). echoForm displayOn: Display at: echoLocation clippingBox: clipRect. ^c! ! !NodeController methodsFor: 'menu messages'! absorb "pastes the contents of the node on the other end of selected link" | sl r offset n t c rpc | model isHistory ifTrue: [Transcript cr; show: 'Only current version can be edited.'. view flash. ^nil]. (rpc _ model graph rpcFor: (model context)) isNil nclude current context'. view selectedNode: nil]].! showTargetContext | c n | c _ model hyperGraph targetContext. c isNil ifTrue: [view flash. Transcript cr; show: 'No target context defined'. ^nil]. n _ view selectedNode. c = n ifFalse: [n notNil ifTrue: [view displayNode: n]. (model nodes keys includes: c) ifTrue: [view selectedNode: c; displaySelection] ifFalse: [view flash. Transcript cr; show: 'Context view does not include target context'. view selectedifTrue: [^nil]. (rpc beginTransaction: true) isNil ifTrue: [rpc reportError: 'beginTransaction:'. ^nil]. sl _ self selectedLinkAttachment. sl = nil ifTrue: [^(self abortTransaction)]. offset _ startBlock stringIndex. "assert sl is the link attachment corresponding to current selection" sl linkIndex = nil ifTrue: [^(self abortTransaction)]. sl isInLink ifTrue: [^(self abortTransaction)]. model deleteAttachment: sl. "delete attachment for original link in old text" r _ rpc getToNode: (sl linkI ndex) at: (sl versionTime). r isNil ifTrue: [rpc reportErrorAborting: 'getTo/FromNode'. ^nil]. model context ~= (r at: 3) ifTrue: [Transcript cr; show: 'Cannot absorb cross context link'. ^(self abortTransaction)]. n _ Node get: (r at: 1) versionTime: (r at: 2) in: (model graph). n isNil ifTrue: [^(self abortTransaction)]. n controller: self. n deleteLink: (n linkOfIndex: (sl linkIndex)). "delete original link to new text" n mergeLinkAttachments. t _ self coerceReplacement: (n contents (model context)) isNil ifTrue: [^nil]. (rpc beginTransaction: true) isNil ifTrue: [rpc reportError: 'beginTransaction:'. ^nil]. charPos _ startBlock stringIndex. n _ Node createIn: (model graph). n = nil ifTrue: [^(self abortTransaction)]. rpc setNodeAttributeValue: (n nodeIndex) for: (model graph iconNameIndex) as: true with: 'Annotation' with: 0. l _ model graph addLinkFrom: model to: n fromCharPos: (startBlock stringIndex) toCharPos: 1. l isNil ifTrue: [rpc reportErrorAborting: ') from: n. self deselect; replaceSelectionWith: t. n links do: [:l | c _ l charPosition + offset - 1. sl _ model linkSameAs: (l linkIndex). r _ model duplicateLink: sl at: c. paragraph text at: c put: r]. self selectAndScroll; updateMarker. n links do: [:l | n deleteLink: l]. "delete old links" r _ rpc deleteNode: (n nodeIndex). "delete old node" r isNil ifTrue: [ rpc reportErrorAborting: 'deleteNode'. ^nil]. rpc commitTransaction. Cursor normal show.! accept self textHasChanged ifFaaddLink'. ^nil]. self newSourceLink: (l at: 1) version: (l at: 2) icon: '@' at: charPos. rpc setLinkAttributeValue: (l at: 1) for: (model graph iconNameIndex) as: true with: '@' with: 0. rpc setLinkAttributeValue: (l at: 1) for: (model graph typeIndex) as: false with: '' with: 1. model isHistory ifFalse: [model timeStamp: (l at: 2)]. rpc commitTransaction. self controlTerminate. Node open: (n nodeIndex) in: (model graph).! browseDocument "opens a document browser rooted at this nodeIndlse: [Transcript cr; show: 'Text has not changed'. view flash. ^nil]. (model changeRequestFrom: view) ifFalse: [Transcript cr; show: 'Only current version can be edited'. view flash. ^nil]. Cursor execute show. model acceptText: (paragraph text). super accept. self unlock. Cursor normal show.! addLink "adds a link in the hyperGraph from current source to destination" | sl r pos | sl _ self selectedLinkAttachment. sl = nil ifTrue: [Transcript cr; show: 'Link must be selected.'. view flash. ^nilex at versionTime" self controlTerminate. model browseDocument! browseGraph "opens a graph browser rooted at this nodeIndex at versionTime" self controlTerminate. model browseGraph! browseLinkAttributes "opens a browser to view the attributes of the selected link" | sl | sl _ self selectedLinkAttachment. sl = nil ifTrue: [Transcript cr; show: 'Link must be selected.'. view flash. ^nil]. self controlTerminate. "assert sl is the link attachment corresponding to current selection" Attribute ope]. Cursor execute show. ((sl linkIndex isNil) and: [(sl sameAs isNil)]) ifTrue: [model addLink] ifFalse: [ (self textHasChanged) & (model isHistory not) ifTrue: [pos _ 0] "make sure we don't attach it off the end" ifFalse: [pos _ startBlock stringIndex]. r _ model duplicateLink: sl at: pos. r isNil ifTrue: [Cursor normal show. ^nil]. paragraph text at: (startBlock stringIndex) put: r. ]. Cursor normal show.! annotate | charPos n l rpc | (rpc _ model graph rpcFor:nOnLink: (sl linkIndex) versionTime: (sl versionTime) in: (model graph)! browseNodeAttributes "opens a browser to view the attributes of this node" self controlTerminate. model browseAttributes! browseNodeDemons "opens a browser to view the demons of this node" self controlTerminate. model browseDemons! browseVersions "opens a browser to view the versions of this node" self controlTerminate. model browseVersions! browseViaLink | r n sl vt rpc | "opens a node browser to the node on the other  end of the link atttached to the current cursor point, may force a node update" sl _ self selectedLinkAttachment. sl = nil ifTrue: [Transcript cr; show: 'Link must be selected.'. view flash. ^nil]. "assert sl is the link attachment corresponding to current selection" sl linkIndex = nil ifTrue: [Transcript cr; show: 'Link is not yet attached.'. view flash. ^nil]. vt _ (model isHistory ifTrue: [model timeStamp] ifFalse: [0]). (rpc _ model graph rpcFor: (model context)) isNil ifTrue: [^nil]. sl isIn show: 'Link must be selected.'. view flash. ^nil]. (model isUnique: sl in: (paragraph text)) ifTrue: [ (sl linkIndex isNil) ifFalse: [(BinaryChoice message: 'Do you really want to delete this link?') ifFalse: [^nil]]. r _ model deleteLink: sl. Cursor normal show. r & (sl linkIndex notNil) ifTrue: [self deleteDisplaying]] ifFalse: [self deleteDisplaying].! deleteSelf "deletes the node that is my model" (model isHistory) ifTrue: [Transcript cr; show: 'Only current version can be delLink ifTrue: [r _ rpc getFromNode: (sl linkIndex) at: vt] ifFalse: [r _ rpc getToNode: (sl linkIndex) at: vt]. r isNil ifTrue: [rpc linkDoesNotExistYetError ifTrue: [self notify: 'Link did not yet exist at specified version time. Proceed to browse current version of link.'. sl isInLink ifTrue: [r _ rpc getFromNode: (sl linkIndex) at: 0] ifFalse: [r _ rpc getToNode: (sl linkIndex) at: 0]. r isNil ifTrue: [rpc reportError: 'getTo/FromNode'. ^nil]] ifFalse: [rpc reporteted.'. view flash. ^nil]. (BinaryChoice message: 'Do you really want to delete this node?') ifFalse: [^nil]. model deleteSelf ifTrue: [ view superView resetLabel: (model makeLabel)]. Cursor normal show.! linkDestination | c v | "defines the current cursor point as a link destination" c _ startBlock stringIndex. (model graph) linkDestination: model. v _ model addLinkDestination: c. self addLinkDisplayingAt: c charValue: v.! linkSource | c v | "defines the current cursor point as a link desError: 'getTo/FromNode'. ^nil]]. model context ~= (r at: 3) ifTrue: [ (BinaryChoice message: 'Cross context link: Do you want to open the new context?') ifFalse: [^nil]. (model graph openContext: (r at: 3)) isNil ifTrue: [^nil]]. self controlTerminate. Node open: (r at: 1) versionTime: (r at: 2) in: (model graph) withSelectedLink: (sl linkIndex)! cancel super cancel. self unlock.! compactSelf | entirely | "compacts the version history of the node that is my model" (model isHistory) ifTtination" c _ startBlock stringIndex. (model graph) linkSource: model. v _ model addLinkSource: c. self addLinkDisplayingAt: c charValue: v.! linkStyleSheet self controlTerminate. model graph linkStyle open.! merge model mergeNode ifFalse: [view flash]. Cursor normal show.! nextLinkInstance "selects the next link attachment that is the same link as the currently selected one" | sl r l t u c | sl _ self selectedLinkAttachment. sl = nil ifTrue: [Transcript cr; show: 'Link must be selected.'. vrue: [Transcript cr; show: 'Only current version can be compacted.'. view flash. ^nil]. entirely _ BinaryChoice message: 'Do you want to discard all history?'. model compactSelf: entirely. Cursor normal show.! compare model compareNode ifFalse: [view flash]. Cursor normal show.! deleteLink "deletes the selected link" | sl r | (model isHistory) ifTrue: [Transcript cr; show: 'Only current version can be edited.'. view flash. ^nil]. sl _ self selectedLinkAttachment. sl = nil ifTrue: [Transcript cr;iew flash. ^nil]. l _ startBlock stringIndex + 1. t _ paragraph text. u _ t size. c _ sl charValue. l to: u do: [:i | ((t at: i) = c and: [(t emphasisAt: i) = MyLinkFont]) ifTrue: [self selectAndScrollFrom:i to: i. ^nil]]. Transcript cr; show: 'No more instances of link.'. view flash. "didn't find it" .! nextUninstantiated "selects the next link attachment that is uninstantiated" | sl l t u c | l _ startBlock stringIndex + 1. t _ paragraph text. u _ t size. l to: u do: [:i | ( (t emphasisAt: i) = MyLinkFont) ifTrue: [sl _model linkAt: (t at: i). (sl linkIndex) isNil ifTrue: [self selectAndScrollFrom: i to: i. ^nil]]]. Transcript cr; show: 'No more uninstantiated links.'. view flash. "didn't find it" .! nodeStyleSheet self controlTerminate. model graph nodeStyle open.! pasteMissingLinks | links t count s i | links _ model links. links isEmpty ifTrue: [^nil]. links do: [:sl | sl charPosition: nil]. t _ paragraph text. i _ 1. count _ 0. (t size) timesRepeat:Transaction: true) isNil ifTrue: [rpc reportError: 'beginTransaction:'. ^nil]. start _ startBlock stringIndex. stop _ stopBlock stringIndex. links _ OrderedCollection new. n _ Node createIn: (model graph). n = nil ifTrue: [^(self abortTransaction)]. cutLinks _ self linksFrom: start to: stop. cutLinks do: [:l | ln _ l deepCopy. ln charPosition: 1. ln sameAs: (ln linkIndex). ln linkIndex: nil. links add: ln]. n links: links. n links do: [:l | r _ rpc copyLink: l from: n. r = nil ifTru [(t emphasisAt: i) = (MyLinkFont) ifTrue: [ sl _ (model linkAt: (t at: i)). sl charPosition: (i - count). count _ count + 1]. i _ i + 1]. t _ Text new. count _ 1. s _ String new: 1. links do: [:sl | (sl charPosition) isNil ifTrue:[ s at: 1 put: sl charValue. t replaceFrom: count to: (count - 1) with: (Text string: s emphasis: MyLinkFont). ]]. self replaceSelectionWith: t.! search self controlTerminate. Cursor execute show. model graph searchStyle openWithInvokere: [rpc reportErrorAborting: 'copyLink'. ^nil]. l linkIndex: (r at: 1). n timeStamp: (r at: 2). l versionTime = 0 ifFalse: [l versionTime: (r at: 2)]. n duplicateLinkAttributesFrom: (l sameAs) for: l]. (n acceptText: (self selection)) ifFalse: [ rpc reportErrorAborting: 'modifyNode'. ^nil]. cutLinks do: [:l | model deleteLink: l]. start < stop ifTrue: [self cut]. l _ model graph addLinkFrom: model to: n fromCharPos: start toCharPos: 1. l isNil ifTrue: [ rpc reportErrorAborting: 'addLin: self find: #findOccurrences.! searchAgain | r a rpc | self textHasChanged ifFalse: [ (rpc _ model graph rpcFor: (model context)) isNil ifTrue: [^nil]. r _ rpc searchContents: 1 nodeList: (Array with: (Array with: (model nodeIndex) with: (model timeStamp) with: (model timeStamp) with: (stopBlock stringIndex))) nodeAttributes: nil code: 1. r isNil ifTrue: [rpc reportError: 'searchContents'. Cursor normal show.^nil]. r size = 0 ifTrue: [view flash. lastUndoSelection _ nil. Cursor nork'. ^nil]. model timeStamp: (l at: 2). icon size = 0 ifTrue: [icon _ nil] ifFalse: [ r _ rpc setNodeAttributeValue: (n nodeIndex) for: (n graph iconNameIndex) as: true with: icon with: 0. r isNil ifTrue: [rpc reportErrorAborting: 'setNodeAttributeValue'. ^nil]. r _ rpc setLinkAttributeValue: (l at: 1) for: (n graph iconNameIndex) as: true with: icon with: 0. r isNil ifTrue: [rpc reportErrorAborting: 'setLinkAttributeValue'. ^nil]]. self newSourceLink: (l at: 1) version: (l atmal show. ^nil]. a _ model adjustSelectedText: (Array with: ((r at: 1) at: 3) with: ((r at: 1) at: 4)). self selectAndScrollFrom: (a at: 1) to: (a at: 2)] ifTrue: [view flash]. Cursor normal show.! separate | start n l stop links c ln r icon cutLinks rpc | model isHistory ifTrue: [Transcript cr; show: 'Only current version can be edited.'. view flash. ^nil]. icon _ FillInTheBlank request: 'Type node name'. (rpc _ model graph rpcFor: (model context)) isNil ifTrue: [^nil]. (rpc begin: 2) icon: icon at: start. self selectAndScrollFrom: start to: start; updateMarker. rpc commitTransaction. self controlTerminate. Node open: (n nodeIndex) in: (model graph).! update (model isHistory) ifTrue: [Transcript cr; show: 'Only current version can be updated.'. view flash. ^nil]. self textHasChanged ifTrue: [ (BinaryChoice message: 'Text has changed, accept needed, proceed without accepting?') ifTrue: [] ifFalse: [^nil]]. model reinitialize. view newContents.  model changed: #contents. model cancelPotentialLinks. view superView resetLabel: (model makeLabel). Cursor normal show.! ! !NodeController methodsFor: 'update'! addLinkDisplayingAt: aCharPosition charValue: aChar | s t v wasCurrent | "Inserts the icon for a link attachment." wasCurrent _ self textHasChanged not. self deselect. self closeTypeIn. s _ String new: 1. s at: 1 put: aChar. t _ Text string: s emphasis: (MyLinkFont). self paragraph replaceFrom: aCharPosition to: (aCharPosition - 1)selectAndScroll. self updateMarker. CurrentSelection _ UndoSelection copy. wasCurrent ifTrue: [self unlock].! deleteIcon: charValue | n t d | d _ ScheduledControllers activeController == view superView controller. n _ Text new. t _ paragraph text. 1 to: (t size) do: [:i | ((t at: i ) = charValue and: [(t emphasisAt: i) = MyLinkFont]) ifTrue: [ paragraph replaceFrom: i to: i with: n displaying: d. ^false]].! linkCharPos: charValue | textSize i contents count | "scans con with: t displaying: true. self selectAndScrollFrom: aCharPosition to: aCharPosition. self updateMarker. CurrentSelection _ UndoSelection copy. wasCurrent ifTrue: [self unlock].! addLinkIcon: aLinkAttachment | r c | r _ aLinkAttachment attributeValues. ((r isNil) or: [(r at: 1) = nil]) ifFalse:[ c _ self addLinkIconForString: (r at: 2) asSource: (aLinkAttachment isInLink not) forVersion: (aLinkAttachment versionTime ~= 0)] ifTrue: [aLinkAttachment isInLink ifTrue: [c _ self addLinkUsingDestintents to find char position of first instance of link index" contents _ paragraph text. textSize _ contents size. i _ 1. count _ 0. textSize timesRepeat: [ (contents emphasisAt: i) = (MyLinkFont) ifTrue: [ (contents at: i) = charValue ifTrue: [^i - count] ifFalse: [count _ count + 1]]. i _ i + 1]. ^nil! linkOffsetCharPos: charValue | textSize i contents | "scans contents to find char position of first instance of link index" contents _ paragraph text. textSize _ contents ationIcon: (aLinkAttachment versionTime ~= 0)] ifFalse: [c _ self addLinkUsingSourceIcon: (aLinkAttachment versionTime ~= 0)]]. ^(Character value: c)! addLinkIconForString: aString asSource: aBoolean1 forVersion: aBoolean2 | linkFont | linkFont _ paragraph textStyle fontAt: MyLinkFont. ^linkFont addCharacter: (linkFont makeNameIcon: aString asSource: aBoolean1 forVersion: aBoolean2)! addLinkUsingDestinationIcon: aBoolean | linkFont | linkFont _ paragraph textStyle fontAt: MyLinkFont. ^size. i _ 1. textSize timesRepeat: [ (contents emphasisAt: i) = (MyLinkFont) ifTrue: [ (contents at: i) = charValue ifTrue: [^i]]. i _ i + 1]. ^nil! newDestinationLink: aLinkIndex version: aTimeStamp icon: aString at: aCharPosition | c | c _ model newLink: aLinkIndex asSource: false version: aTimeStamp icon: aString at: aCharPosition. self addLinkDisplayingAt: aCharPosition charValue: c.! newSourceLink: aLinkIndex version: aTimeStamp icon: aString at: aCharPosition | c | c _ model newLilinkFont addCharacter: (linkFont makeDestinationIcon: aBoolean)! addLinkUsingSourceIcon: aBoolean | linkFont | linkFont _ paragraph textStyle fontAt: MyLinkFont. ^linkFont addCharacter: (linkFont makeSourceIcon: aBoolean)! deleteDisplaying | wasCurrent | "Cut out the current selection and redisplay the paragraph if necessary. Typically used to cut the icon for a link attachment." wasCurrent _ self textHasChanged not. self deselect. self closeTypeIn. super replaceSelectionWith: Text new. self nk: aLinkIndex asSource: true version: aTimeStamp icon: aString at: aCharPosition. self addLinkDisplayingAt: aCharPosition charValue: c.! ! !NodeController methodsFor: 'editing'! acceptIt "Save the current text of the text being edited as the current acceptable version for purposes of canceling." initialText _ paragraph text copy! coerceReplacement: aText from: aNode "prepares model and controller to paste text that contains link attachments" | s n l st c mySl sl a r | s _ aText size. n _ aText co py. l _ NodeController linkFont. st _ String new: 1. 1 to: s do: [:i | ((aText emphasisAt: i) = l) ifTrue: [ c _ aText at: i. sl _ aNode linkAt: c. mySl _ model linkAt: c. ((mySl isNil) or: [(((sl linkIndex) = (mySl linkIndex)) and: [((sl isInLink) = (mySl isInLink))]) not]) ifTrue: [ a _ sl deepCopy. a linkIndex: nil. (sl linkIndex) isNil ifTrue: [ a sameAs: (sl sameAs)] ifFalse: [a sameAs: (sl linkIndex)]. (a sameAs) isNil ifTrue: [n replaceFrifTrue: [rpc reportError: 'abortTransaction:'. ^nil]. ^nil! linksFrom: start to: stop | list t la end | list _ OrderedCollection new. t _ paragraph text. end _ (stop <= t size) ifTrue: [stop] ifFalse: [t size]. start to: end do: [:i | (t emphasisAt: i) = MyLinkFont ifTrue: [ la _ (model linkAt: (t at: i)). la linkIndex notNil ifTrue: [list add: la]]]. ^list! selectedLinkAttachment | c sl | model links isEmpty ifTrue: [^nil]. "quick exit" c _ startBlock stringIndex. c = (stopBlock stom: i to: i with: (Text new)] ifFalse: [ r _ self addLinkIcon: a. a charValue: r. st at: 1 put: r. n replaceFrom: i to: i with: (Text string: st emphasis: MyLinkFont). model insertAttachment: a]]]]. ^n! replaceSelectionWith: aText | t linkEmphasis next la s needsMessaging m n | "overrides ParagraphEditor version, so that link attachment points copied from a different node will be handled correctly" beginTypeInBlock == nil ifTrue: [UndoSelection ringIndex - 1) ifFalse: [^nil]. "more than one char selected" (paragraph text emphasisAt: c) = MyLinkFont ifFalse: [^nil]. "not a link" ^model linkAt: (paragraph text at: c)! ! !NodeController methodsFor: 'composition'! wrappingBox: wrapRectangle clippingBox: clipRectangle paragraph recomposeIn: wrapRectangle clippingBox: clipRectangle. self selectFrom: startBlock stringIndex to: stopBlock stringIndex-1! ! !NodeController methodsFor: 'access'! paragraph ^paragraph! setLastUndoSelection lastUndoSelec_ self selection]. needsMessaging _ false. ((OldCS = aText) and: [WhoSetCS ~~ model]) ifTrue: [needsMessaging _ true. m _ WhoSetCS] ifFalse: [((OldUS = aText) and: [WhoSetUS ~~ model]) ifTrue: [needsMessaging _ true. m _ WhoSetUS]]. needsMessaging ifTrue: [n _ self coerceReplacement: aText from: m] ifFalse: [ n _ aText]. paragraph replaceFrom: startBlock stringIndex to: stopBlock stringIndex - 1 with: n displaying: true. startBlock _ paragraph characterBlockForIndex: startBtion _ UndoSelection! ! !NodeController methodsFor: 'basic control sequence'! controlInitialize super controlInitialize. OldCS == CurrentSelection ifTrue: [CurrentSelection _ MyCurrentSelection]. OldCS _ CurrentSelection. OldUS == UndoSelection ifTrue: [UndoSelection _ MyUndoSelection. lastUndoSelection == OldUS ifTrue: [lastUndoSelection _ MyUndoSelection]]. OldUS _ UndoSelection.! controlTerminate super controlTerminate. OldCS == CurrentSelection ifFalse: [MyCurrentSelection _ CurrentSelelock stringIndex. stopBlock _ paragraph characterBlockForIndex: startBlock stringIndex + n size. self lock.! setEmphasisHere "overrides Paragraph version so that inserted characters won't inherit unique link font" emphasisHere _ paragraph text emphasisAt: startBlock stringIndex. emphasisHere = (MyLinkFont) ifTrue: [emphasisHere _ 1].! ! !NodeController methodsFor: 'private'! abortTransaction | rpc | (rpc _ model graph rpcFor: (model context)) isNil ifTrue: [^nil]. (rpc abortTransaction) isNil ction. CurrentSelection _ model copyWithoutLinks: MyCurrentSelection. WhoSetCS _ model]. OldCS _ CurrentSelection. OldUS == UndoSelection ifFalse: [MyUndoSelection _ UndoSelection. UndoSelection _ model copyWithoutLinks: MyUndoSelection. WhoSetUS _ model]. OldUS _ UndoSelection.! ! !NodeController methodsFor: 'lock access'! isLocked "Answer whether no unsaved modifications have been carried out using the receiver." ^isLockingOn! isUnlocked "Answer whether no unsaved modi fications have been carried out using the receiver." ^isLockingOn not! lock "Turn on the receiver's indication that it is locked." isLockingOn _ true! textHasChanged ^isLockingOn! unlock "Turn off the receiver's indication that it is locked." isLockingOn _ false! ! !NodeController methodsFor: 'initialize - release'! initialize super initialize. isLockingOn _ false.! reinitialize | f | self unlock. self deselect. self changeParagraph: (Paragraph withText: (model contents) style: (paragraph te^(((paragraph characterBlockForIndex: aCharIndex) top) - paragraph clippingRectangle top)! selectAndAlign: offsetY "Scroll until the selection is aligned offsetY from top and then highlight it." | lineHeight deltaY clippingRectangle | lineHeight _ paragraph textStyle lineGrid. clippingRectangle _ paragraph clippingRectangle. deltaY _ stopBlock top - clippingRectangle top - offsetY. deltaY ~= 0 ifTrue: [self scrollBy: (deltaY abs + lineHeight - 1 truncateTo: lineHeight) * deltaY sign]. sextStyle) compositionRectangle: (view insetDisplayBox insetBy: 6@0) clippingRectangle: (view insetDisplayBox)). self noSelectionShowing.! release super release. self breakDependents! resetstyle | f | f _ (LinkFont new). paragraph textStyle fontAt: 25 put: f. ^f! ! !NodeController methodsFor: 'searching'! findOccurrences | searchString r a rpc | searchString _ model graph searchStyle searchString. (rpc _ model graph rpcFor: (model context)) isNil ifTrue: [^nil]. r _ rpc searchContents: 1 lf select! selectAndAlignFrom: start to: stop alignment: offsetY self deselect. startBlock _ paragraph characterBlockForIndex: start. stopBlock _ paragraph characterBlockForIndex: stop + 1. self selectAndAlign: offsetY! selectionOffsetY ^(stopBlock top - paragraph clippingRectangle top)! selectionStart ^startBlock stringIndex! ! !NodeDiffController methodsFor: 'override scrollController'! scrollView: anInteger | c1 s c2 b cs h offsetY | super scrollView: anInteger. lockedScrolling ifTrue: [ c1  nodeList: (Array with: (Array with: (model nodeIndex) with: (model timeStamp) with: (model timeStamp) with: (stopBlock stringIndex))) nodeAttributes: nil code: 1. r isNil ifTrue: [rpc reportError: 'searchContents'. Cursor normal show.^nil]. r size = 0 ifTrue: [view flash. lastUndoSelection _ nil. Cursor normal show. ^nil]. a _ model adjustSelectedText: (Array with: ((r at: 1) at: 3) with: ((r at: 1) at: 4)). self selectAndScrollFrom: (a at: 1) to: (a at: 2). Cursor normal show. view superView_ self. s _ view superView. c1 == (s firstSubView controller) ifTrue: [c2 _ s lastSubView controller. cs _ s model changeSet2] ifFalse: [c2 _ s firstSubView controller. cs _ s model changeSet1]. b _ c1 paragraph characterBlockAtPoint: (paragraph clippingRectangle topLeft). offsetY _ c1 characterOffsetYfor: (cs firstCharFor: (b stringIndex)). b _ c2 paragraph characterBlockForIndex: (cs runEncoding at: (b stringIndex)). c2 alignBlock: b using: offsetY]! ! !NodeDiffController methodsFor: ' emphasizeLabel. self startUp.! ! !NodeDiffController methodsFor: 'alignment'! alignBlock: aBlock using: offsetY "Scroll until aBlock is aligned offsetY from top." | lineHeight deltaY clippingRectangle | lineHeight _ paragraph textStyle lineGrid. clippingRectangle _ paragraph clippingRectangle. deltaY _ aBlock top - clippingRectangle top - offsetY. deltaY ~= 0 ifTrue: [self scrollBy: (deltaY abs + lineHeight - 1 truncateTo: lineHeight) * deltaY sign].! characterOffsetYfor: aCharIndex private'! initializeYellowButtonMenu self yellowButtonMenu: NodeDiffYellowButtonMenu yellowButtonMessages: NodeDiffYellowButtonMessages! ! !NodeDiffController methodsFor: 'override editing'! readKeyboard Sensor flushKeyboard. view flash! ! !NodeDiffController methodsFor: 'menu messages'! alignLines | c1 c2 cs offsetY b s | c1 _ self. s _ view superView. c1 == (s firstSubView controller) ifTrue: [c2 _ s lastSubView controller. cs _ s model changeSet2] ifFalse: [c2 _ s firstSubView controll er. cs _ s model changeSet1]. offsetY _ c1 characterOffsetYfor: (cs firstCharFor: (c1 selectionStart)). b _ c2 paragraph characterBlockForIndex: (cs runEncoding at: (c1 selectionStart)). c2 alignBlock: b using: offsetY! alignLink | c1 c2 linkIndex s v | c1 _ self. v _ view superView. c1 == (v firstSubView controller) ifTrue: [c2 _ v lastSubView controller] ifFalse: [c2 _ v firstSubView controller]. s _ c1 selectedLinkAttachment. s isNil ifTrue: [Transcript cr; show: 'Link must be sele insertAndSelect: t at: (errorLoc at: 1)]. Cursor normal show.! ! !PredicateController methodsFor: 'access'! graph: aGraph graph _ aGraph! ! !GraphStyleController methodsFor: 'control defaults'! isControlActive model actionTaken ifTrue: [^false]. [super isControlActive] whileFalse: [view flash]. ^true! ! !GraphStyleController methodsFor: 'menu messages'! close model actionTaken: true. super close. self controlTerminate! ! !ScreenController methodsFor: 'menu messages'! quit | menu index imageNcted'. c1 view flash. ^nil]. linkIndex _ s linkIndex. s _ c2 model firstInstanceOf: linkIndex. s isNil ifTrue: [Transcript cr; show: 'Link is not defined in other version.'. c2 view flash. ^nil] ifFalse: [c2 selectAndAlignFrom: s to: s alignment: (c1 selectionOffsetY)].! changeSet | c1 c2 cs h offsetY b v | c1 _ self. v _ view superView. c1 == (v firstSubView controller) ifTrue: [v model changeSet1 runEncoding inspect] ifFalse: [v model changeSet2 runEncoding inspect].! lockScrolling lockedame | HyperRPC finishUp. menu _ PopUpMenu labels: ' Save, then quit Quit, without saving Continue ' lines: #(1 2). index _ menu startUp. index = 1 ifTrue: [imageName _ Smalltalk getImageName. imageName isEmpty ifTrue: [^self]. Smalltalk snapshotAs: imageName thenQuit: true]. index = 2 ifTrue: [Smalltalk quit]! save | name | HyperRPC finishUp. name _ Smalltalk getImageName. name isEmpty ifTrue: [^self]. Smalltalk snapshotAs: name thenQuit: false! ! !NodeFormController methodsForScrolling _ true! unlockScrolling lockedScrolling _ false! ! !NodeDiffController methodsFor: 'access'! lockedScrolling ^lockedScrolling! lockedScrolling: aBoolean lockedScrolling _ aBoolean! ! !NodeDiffController methodsFor: 'initialize - release'! initialize super initialize. lockedScrolling _ true.! ! !PredicateController methodsFor: 'menu messages'! accept | r predicate s errorLoc t rpc | super accept. predicate _ self view model contents. (rpc _ graph hyperGraph rpcFor: (graph context)) is: 'menu messages'! accept | s | Cursor execute show. super accept. s _ WriteStream on: (String new). view model storeOn: s. node acceptForm: (s contents). Cursor normal show.! ! !NodeFormController methodsFor: 'access'! node: aNode node _ aNode! ! !ZoomScrollController methodsFor: 'control defaults'! controlActivity | area size location p| size _ view size. location _ view location. [sensor noButtonPressed & self viewHasCursor] whileTrue: [ p _ view inverseDisplayTransform: Sensor cursorPoNil ifTrue: [^nil]. r _ rpc parseExpression: predicate. r isNil ifTrue: [s _ rpc errorMessage. errorLoc _ rpc errorParams. errorLoc size = 0 ifTrue: [rpc reportError: 'parseExpression'. ^nil]. t _ String new: ((s size) + 3). t replaceFrom: 1 to: 3 with: '<- ' startingAt: 1. t replaceFrom: 4 to: (t size) with: s startingAt: 1. self controlTerminate. "These two lines are a hack to overcome some" self controlInitialize. "problems with the StringHolderController." selfint. ((Rectangle origin: location extent: size) containsPoint: p) ifTrue: [ area _ ZoomArea on: size at: location withCursorAt: (view inverseDisplayTransform: Sensor cursorPoint). area determineActionWithShift: false. area cursor show] ifFalse: [Cursor crossHair show] ]. Cursor normal show. super controlActivity! isControlActive ^(view containsPoint: sensor cursorPoint) & sensor blueButtonPressed not! ! !ZoomScrollController methodsFor: 'initialization'! initialize super initia lize. self yellowButtonMenu: YellowButtonMenu yellowButtonMessages: YellowButtonMessages! ! !ZoomScrollController methodsFor: 'menu messages'! contract view location: (view location + (view size*((ZoomRatio - 1.0)/(2*ZoomRatio)))). view size: (view size / ZoomRatio). view displayView; newZoomArea.! expand | newSize newLocation | newSize _ view size * ZoomRatio. view size: (newSize min: 1.0@1.0). newLocation _ view location - (view size*((ZoomRatio - 1.0)/(2*ZoomRatio))). view location: ((newLf the receiver." ^width! width: anInteger "Set the instance variable width of the receiver." width _ anInteger.! ! !NodeEntry methodsFor: 'private'! initialize toNodes _ Set new.! ! !Attribute methodsFor: 'initialize - release'! initialize showSystemAttributes _ false. asString _ true.! ! !Attribute methodsFor: 'access'! asString ^asString! asString: aBoolean asString _ aBoolean. self changed: #asString! attributeNames | result | showSystemAttributes ifTrue: [^attributeNames] ifFalse: [ocation max: 0@0) min: (1.0@1.0 - view size)). view displayView; newZoomArea.! redButtonActivity self view move! yellowButtonActivity self view changeSize! ! !PromptController methodsFor: 'control defaults'! isControlActive ^(view containsPoint: sensor cursorPoint) & (sensor blueButtonPressed not) & (sensor yellowButtonPressed not)! ! !NodeEntry methodsFor: 'accessing'! addToNode: aNode toNodes add: aNode.! icon "Returns the instance variable icon of the receiver." ^icon! icon: aForm "Set tresult _ OrderedCollection new. attributeNames do: [:a | (a at: 1) = $. ifFalse: [result add: a]]. ^result]! value value isNil ifTrue: [^nil]. asString ifTrue: [^value asText] ifFalse: [^(value printStringRadix: 10) asText]! value: newValue value _ newValue. self changed: #value.! ! !Attribute methodsFor: 'testing'! isHistory ^versionTime ~= 0! size ^attributeIndices size! ! !Attribute methodsFor: 'text menu messages'! accept: newValue | rpc i r isString valueAsString valueAsInteger | he instance variable icon of the receiver." icon _ aForm.! isMarked "Returns the instance variable markBit of the receiver." ^markBit! location "Retuns the instance variable point of the receiver." ^point! location: aPoint "Set the instance variable point of the receiver." point _ aPoint.! ordinal "Returns the instance variable ordinal of the receiver." ^ordinal! ordinal: anInteger "Set the instance variable ordinal of the receiver." ordinal _ anInteger.! removeMark "Set the instance varia i _ selectedAttributeIndex. i isNil ifTrue: [^false]. (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. (attributeIndices at: i) = -1 ifTrue: [r _rpc getAttributeIndex: (attributeNames at: i). r isNil ifTrue: [rpc reportError: 'getAttributeIndex'. ^false]. attributeIndices at: i put: r.]. asString ifTrue: [isString _ 1. valueAsString _ newValue string collect: [:char | char = (Character cr) ifTrue: [Character space] ifFalse: [char]]. valueAsInteger _ 0] ifFalse: [isStble markBit of the receiver to false." markBit _ false.! removeToNode: aNode toNodes remove: aNode.! setMark "Set the instance variable markBit of the receiver to true." markBit _ true.! time "Returns the instance variable versionTime of the receiver." ^versionTime! time: aTime "Set the instance variable versionTime of the receiver." versionTime _ aTime.! toNodes "Returns the to node indices of all links from the receiver's node." ^toNodes! width "Returns the instance variable width oring _ 0. valueAsString _ ''. valueAsInteger _ newValue asNumber]. entityType = #context ifTrue: [ r _ rpc setContextAttributeValue: entityIndex for: (attributeIndices at: i) as: asString with: valueAsString with: valueAsInteger] ifFalse: [entityType = #node ifTrue: [ r _ rpc setNodeAttributeValue: entityIndex for: (attributeIndices at: i) as: asString with: valueAsString with: valueAsInteger] ifFalse: [entityType = #link ifTrue: [ r _ rpc setLinkAttributeValue: entityIndex for:  (attributeIndices at: i) as: asString with: valueAsString with: valueAsInteger]]]. Cursor normal show. r isNil ifTrue: [rpc reportError: 'setAttributeValue'. ^false]. isStrings at: i put: asString. asString ifTrue: [attributeValues at: i put: valueAsString. value _ valueAsString] ifFalse: [attributeValues at: i put: valueAsInteger. value _ valueAsInteger]. self changed: #value. ^true! textMenu ^TextMenu! ! !Attribute methodsFor: 'list menu messages'! addAttribute | labels a attributes indibuteIndices at: i)] ifFalse: [entityType = #node ifTrue: [ r _rpc deleteNodeAttribute: entityIndex for: (attributeIndices at: i)] ifFalse: [entityType = #link ifTrue: [ r _rpc deleteLinkAttribute: entityIndex for: (attributeIndices at: i)]]]. r isNil ifTrue: [rpc reportError: 'deleteEntityAttribute'. ^false]]. size _ attributeIndices size. stack _ OrderedCollection new. size - i timesRepeat: [stack addLast: attributeIndices last. attributeIndices removeLast]. attributeIndices removeLaex n rpc | "creates a new attribute " self isHistory ifTrue: [Cursor normal show. self flash. Transcript cr; show: 'cannot change history'. ^nil]. (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. a _ rpc getAttributes: 0. a isNil ifTrue: [Cursor normal show. rpc reportError: 'getAttributes'. ^false]. attributes _ OrderedCollection new. labels _ nil. a do: [:i | n _ i at: 2. (((n at: 1) ~= $.) | showSystemAttributes) & ((attributeNames includes: n) not) ifTrue: [ attributes adst. size - i timesRepeat: [attributeIndices addLast: stack last. stack removeLast]. size - i timesRepeat: [stack addLast: isStrings last. isStrings removeLast]. isStrings removeLast. size - i timesRepeat: [isStrings addLast: stack last. stack removeLast]. size - i timesRepeat: [stack addLast: attributeNames last. attributeNames removeLast]. attributeNames removeLast. size - i timesRepeat: [attributeNames addLast: stack last. stack removeLast]. size - i timesRepeat: [stack addLast: attributeValues lad: n. labels isNil ifTrue: [labels _ n] ifFalse: [labels _ labels,'\',n]]]. Cursor normal show. labels notNil ifTrue: [ index _ (PopUpMenu labels: (labels withCRs)) startUp. index ~= 0 ifTrue: [self addAttribute: (attributes at: index)]] ifFalse: [self flash. Transcript cr; show: 'all attributes defined'].! createAttribute | topView aString | "creates a new attribute " self isHistory ifTrue: [self flash. ^nil]. aString _ FillInTheBlank request: 'Attribute Name'. aStringst. attributeValues removeLast]. attributeValues removeLast. size - i timesRepeat: [attributeValues addLast: stack last. stack removeLast]. selectedAttributeIndex _ nil. self changed: #attributeNames. Cursor normal show.! hideSystemAttributes showSystemAttributes _ false. self changed: #attributeNames.! listMenu ^ListMenu! selectedAttribute | count | selectedAttributeIndex isNil ifTrue: [^nil]. ^(attributeNames at: selectedAttributeIndex)! selectedAttribute: aString | count | aString isNil if size > 0 ifTrue: [ self addAttribute: aString].! deleteAttribute | i r size stack rpc | i _ selectedAttributeIndex. i isNil ifTrue: [Transcript cr; show: 'Attribute must be selected.'. self flash. ^nil]. (attributeIndices at: i) = -1 ifFalse: [(BinaryChoice message: 'Do you really want to delete this attribute?') ifFalse: [^false]. (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. entityType = #context ifTrue: [ r _ rpc deleteContextAttribute: entityIndex for: (attrTrue: [selectedAttributeIndex _ nil. self value: nil. ^true]. count _ 1. attributeNames do: [:a | a = aString ifTrue: [ selectedAttributeIndex _ count. self asString: (isStrings at: count). self value: (attributeValues at: count). ] ifFalse: [count _ count + 1]].! showSystemAttributes showSystemAttributes _ true. self changed: #attributeNames.! update | r rpc | (self isHistory) ifTrue: [Transcript cr; show: 'Cannot edit history'. ^false]. (rpc _ graph rp cFor: context) isNil ifTrue: [^nil]. entityType = #context ifTrue: [ r _ rpc getContextAttributes: entityIndex versionTime: 0] ifFalse: [entityType = #node ifTrue: [ r _ rpc getNodeAttributes: entityIndex versionTime: 0] ifFalse: [entityType = #link ifTrue: [ r _ rpc getLinkAttributes: entityIndex versionTime: 0]]]. r isNil ifTrue: [rpc reportError: 'getEntityAttributes'. ^nil]. self defineAttributes: r. self changed: #attributeNames. Cursor normal show.! ! !Attribute methodsFor: 'private'! ad entityIndex _ anInteger1. versionTime _ anInteger2. entityType _ #node. graph _ aGraph. context _ aGraph currentContext. rpc _ graph rpc. r _ rpc getNodeAttributes: anInteger1 versionTime: anInteger2. r isNil ifTrue: [rpc reportError: 'getNodeAttributes'. ^nil]. self defineAttributes: r. AttributeView openOn: self! defineAttributes: r | numPairs i | numPairs _ r at: 1. attributeIndices _ OrderedCollection new: numPairs. attributeNames _ OrderedCollection new: numPairs. attributeValues _ OrdAttribute: aString (attributeNames includes: aString) ifTrue: [^false]. attributeIndices addLast: -1. attributeNames addLast: aString. attributeValues addLast: ''. selectedAttributeIndex _ attributeNames size. isStrings addLast: true. self changed: #attributeNames! browseContextAttributes: anInteger1 versionTime: anInteger2 in: aGraph | r numPairs rpc | "opens the attribute/value pairs for version anInteger2 of context anInteger1" self initialize. entityIndex _ anInteger1. versionTime _ anInderedCollection new: numPairs. isStrings _ OrderedCollection new: numPairs. i _ 2. [i <= (numPairs + 1)] whileTrue: [ attributeIndices addLast: ((r at: i) at: 1). attributeNames addLast: ((r at: i) at: 2). attributeValues addLast: ((r at: i) at: 3). isStrings addLast: ((r at: i) at: 4). i _ i + 1].! flash self changed: #attributeNames. "really wanted to flash"! makeLabel | r s t rpc c | (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. c _ graph contextName. entiteger2. entityType _ #context. context _ 0. "context attributes are not defined within a context" graph _ aGraph. rpc _ graph rpc. r _ rpc getContextAttributes: anInteger1 versionTime: anInteger2. r isNil ifTrue: [rpc reportError: 'getContextAttributes'. ^nil]. self defineAttributes: r. AttributeView openOn: self! browseLinkAttributes: anInteger1 versionTime: anInteger2 in: aGraph | r numPairs i rpc | "opens the attribute/value pairs for version anInteger2 of Link anInteger1" self initialize. tyType = #context ifTrue: [s _ 'Context Attribute Browser'. r _ rpc getContextAttributeValue: entityIndex for: (graph iconNameIndex) at: 0. ((r notNil) and: [(r at: 1)]) ifTrue: [s _ (r at: 2), ' Attributes']] ifFalse: [entityType = #node ifTrue: [s _ c, ': Node Attribute Browser'. r _ rpc getNodeAttributeValue: entityIndex for: (graph iconNameIndex) at: 0] ifFalse: [entityType = #link ifTrue: [s _ c, ': Link Attribute Browser'. r _ rpc getLinkAttributeValue: entityIndex  entityIndex _ anInteger1. versionTime _ anInteger2. entityType _ #link. graph _ aGraph. context _ aGraph currentContext. rpc _ graph rpc. r _ rpc getLinkAttributes: anInteger1 versionTime: anInteger2. r isNil ifTrue: [rpc reportError: 'getLinkAttributes'. ^nil]. self defineAttributes: r. AttributeView openOn: self! browseNodeAttributes: anInteger1 versionTime: anInteger2 in: aGraph | r numPairs rpc | "opens the attribute/value pairs for version anInteger2 of node anInteger1" self initialize.  for: (graph iconNameIndex) at: 0]]. ((r notNil) and: [(r at: 1)]) ifTrue: [s _ c, ': ', (r at: 2), ' Attributes']]. self isHistory ifTrue: [t _ Time fromUnixSeconds: versionTime. s _ s, ' (', ((t at: 1) printFormat: #(1 2 3 32 2 2)). s _ s, ' ', ((t at: 2) printString), ')' ]. ^s! ! !Attribute methodsFor: 'update-change'! changeRequest | cancel | attributeIndices do: [:a | a = -1 ifTrue: [ ^(self confirm: 'Attribute added, but not accepted. Do you wish to proceed?')]]. ^true! ! !LinkAttachment methodsFor: 'access'! attributeValues ^attributeValues! attributeValues: values "attributeValues is an array with each even element corresponding to the value of an attribute. The correspondence between an even element and the attribute for which it is a value is not explicit, but is maintained by the user of this class. Each odd element of the attributeValues array is a boolean that says whether or not the subsequent value is to be interpreted as a string or a n inte- 5000 max: 0) < endPosition]] whileTrue: [aStream position: position. count _ endPosition - position. [count > 0] whileTrue: [count _ count - 1. aStream next = firstChar ifTrue: [index _ 2. [index <= aString size and: [(aString at: index) = aStream next]] whileTrue: [index _ index + 1]. index > aString size ifTrue: [skipCount _ skipCount - 1. skipCount = 0 ifTrue: [lastEnd _ aStream position]] ifFalse: [aStream position: ger. odd: aBoolean - is the value a string? even: aString or anInteger - the actual value. " attributeValues _ values! charPosition ^charPosition! charPosition: anInteger charPosition _ anInteger! charValue ^charValue! charValue: aChar charValue _ aChar! isInLink ^isInLink! isInLink: aBoolean isInLink _ aBoolean! linkIndex ^linkIndex! linkIndex: anInteger linkIndex _ anInteger! sameAs ^sameAs! sameAs: aLinkIndex sameAs _aLinkIndex! versionTime ^versionTime! versionTime: anInteger versendPosition - count]]]]. ^lastEnd! ! !PopUpMultiMenuContext methodsFor: 'initialization'! withMenu: aPopUpMultiMenu "initializes the receiver" initialMenu _ aPopUpMultiMenu. multiMenus _ OrderedCollection new. markers _ OrderedCollection new. selections _ OrderedCollection new. frames _ OrderedCollection new. savedAreas _ OrderedCollection new.! ! !PopUpMultiMenuContext methodsFor: 'controlling'! buttonPressed: aSymbol "The argument indicates which button should be tested. Answer whether it iionTime _ anInteger! ! !Project methodsFor: 'controlling'! enter "The user has chosen to change the context of the workspace to be that of the receiver. Change the ChangeSet, Transcript, and collection of scheduled views accordingly." ScheduledControllers scheduledControllers do: [:aCont | (aCont class = StandardSystemController ) ifTrue: [aCont view deleteDisplayForm; setSelection: false]]. Smalltalk newChanges: projectChangeSet. CurrentProject _ self. TextCollector newTranscript: projectTrs pressed." aSymbol = #redButton ifTrue: [^Sensor redButtonPressed]. aSymbol = #yellowButton ifTrue: [^Sensor yellowButtonPressed]. aSymbol = #blueButton ifTrue: [^Sensor blueButtonPressed]. ^Sensor anyButtonPressed! return: aValue "cleans up outstanding menus and returns aValue" initialMenu selection: (selections at: 1). [multiMenus isEmpty] whileFalse: [self removeMenu]. ^aValue! startUp: aSymbol | sel offset | "Display and make a selection from the receiver as long as the button denoted banscript. ControlManager newScheduler: projectWindows! ! !ChangeList methodsFor: 'private'! findLast: aString in: aStream skipping: anInteger "Return the position in the stream of the end of the anInteger'th occurrence of aString (presumably a snapshot message)" | firstChar endPosition position count index lastEnd skipCount | firstChar _ aString first. aStream setToEnd. position _ aStream position. skipCount _ anInteger max: 1. [endPosition _ position. lastEnd == nil and: [(position _ endPosition y the symbol, aSymbol, is pressed. Answer the current selection." sel _ initialMenu selection. (sel isNil or: [sel == 0]) ifTrue: [offset _ initialMenu frame extent // 2] ifFalse: [offset _ ((initialMenu frame extent x // 2) @ ((initialMenu frame extent y // initialMenu valueArray size) * (initialMenu selection -1 )))]. ^self startUp: aSymbol at: Sensor cursorPoint - offset! startUp: aSymbol at: aPoint "Display and make a selection from the receiver as long as the button denoted by the symbol, aSymbol, is pressed. Answer the current selection." | cursorPoint oldCursorPoint rtnVal | self addMenu: initialMenu at: aPoint. self addMenu: PopUpMultiMenu null at: frames first inside topRight + (2@0). [self buttonPressed: aSymbol] whileFalse. cursorPoint _ Sensor cursorPoint. [(frames nextToLast inside containsPoint: cursorPoint) ifTrue: [(self buttonPressed: aSymbol) ifTrue: [self markerOn: cursorPoint] ifFalse: [^self return: self markerReturn]] ifFalse: [self marceMenuWith: aPopUpMultiMenu "replaces the receiver's last Menu" | location | aPopUpMultiMenu == multiMenus last ifFalse: [location _ markers nextToLast topRight + (3@1). self removeMenu. self addMenu: aPopUpMultiMenu at: location].! ! !PopUpMultiMenuContext methodsFor: 'marker adjustment'! markerOff: aSymbol ifCancel: aBlk "No item is selected. Attempt to go to another menu" | cursorPoint newIndex | " selections nextToLast ~= 0 ifTrue: [Display reverse: markers nextToLast. selectikerOff: aSymbol ifCancel: [^self return: 0]]. true] whileTrue: [[oldCursorPoint _ cursorPoint. PopUpMultiMenu delayCount timesRepeat: []. cursorPoint _ Sensor cursorPoint. cursorPoint = oldCursorPoint] whileFalse. "for delay"].! ! !PopUpMultiMenuContext methodsFor: 'menu adding-removing'! addMenu: aPopUpMultiMenu at: aPoint "adds a Menu to the receiver" | delta alignment | multiMenus add: aPopUpMultiMenu. markers add: (0@0 corner: multiMenus last form width @ (multiMenus lastons at: (selections size - 1) put: 0]." [cursorPoint _ Sensor cursorPoint. (self buttonPressed: aSymbol) ifFalse: [^aBlk value]. newIndex _ (selections size to: 1 by: -1) detect: [:i | (frames at: i) inside containsPoint: cursorPoint] ifNone: [0]. newIndex = 0] whileTrue. [multiMenus size > newIndex] whileTrue: [self removeMenu]. self addMenu: PopUpMultiMenu null at: frames last inside topRight + (3@0).! markerOn: aPoint "The item whose bounding area contains aPoint should be form height // multiMenus last valueArray size)). selections add: 0. markers size == 1 ifTrue: [alignment _ markers last topLeft] ifFalse: [alignment _ 0 @ (markers last corner y * ((multiMenus last valueArray size) // 2))]. frames add: (multiMenus last frame align: alignment with: aPoint). delta _ frames last amountToTranslateWithin: Display boundingBox. frames last moveBy: delta. markers at: markers size put: (markers last align: markers last topLeft with: (aPoint + delta - (1@0))). savedAreas marked as selected. Highlight its area and set the selection to its index." selections nextToLast = 0 | (markers nextToLast containsPoint: aPoint) not ifTrue: [selections nextToLast = 0 & (markers nextToLast containsPoint: aPoint) ifTrue: [Display reverse: markers nextToLast] ifFalse: [selections nextToLast ~= 0 ifTrue: [Display reverse: markers nextToLast]. markers at: markers size - 1 put: (markers nextToLast align: markers nextToLast topLeft with: m add: (Form fromDisplay: frames last). frames last displayOn: Display. multiMenus last form displayOn: Display at: frames last inside topLeft clippingBox: frames last inside. selections last = 0 ifFalse: [Display reverse: markers last].! removeMenu "removes the receiver's last menu" multiMenus removeLast. markers removeLast. selections removeLast. savedAreas last displayOn: Display at: frames last topLeft clippingBox: frames last. frames removeLast. savedAreas removeLast.! replaarkers nextToLast left @ (self markerTop: aPoint)). Display reverse: markers nextToLast]]. selections at: (selections size - 1) put: (markers nextToLast top - frames nextToLast top // markers nextToLast height + 1). self replaceMenuWith: (selections nextToLast = 0 ifTrue: [PopUpMultiMenu null] ifFalse: [multiMenus nextToLast menuArray at: selections nextToLast]).! markerReturn "clean up, returning selected item" ^multiMenus nextToLast valueArray at: selections nextToLast! markerTop: aPoint "Answer aPoint, gridded to lines in the receiver." ^(aPoint y - frames nextToLast inside top truncateTo: multiMenus nextToLast font height) + frames nextToLast inside top! ! !TimeSpecifier methodsFor: 'menus'! yellowButtonMenu ^YellowButtonMenu! ! !TimeSpecifier methodsFor: 'access'! actionTaken ^false! actionTaken: aBoolean! date ^time at: 1! date: aDate time at: 1 put: aDate. aDate = CurrentDateIndicator ifTrue: [dateText _ CurrentDateText] ifFalse: [dateText _ (aDate printFormat: #(1 m: secondCount). ^secondCount]! unixVersionTime: unixSeconds | d | d = 0 ifTrue: [self current] ifFalse: [d _ self fromUnixSeconds: unixSeconds. self date: (d at: 1). self time: (d at: 2)].! versionTime "returns the specified time and date as seconds" ^((time at: 1) asSeconds + (time at: 2) asSeconds)! ! !TimeSpecifier methodsFor: 'initialize -release'! initialize: aDateAndTime initialTime _ aDateAndTime deepCopy. time _ aDateAndTime. timeText _ (time at: 2) printString asText. dat2 3 32 2 2 )) asText]. self changed: #dateText.! dateText ^dateText! dateText: text | s d | text = CurrentDateText ifTrue: [time at: 1 put: CurrentDateIndicator] ifFalse: [s _ ReadWriteStream with: (text asString). d _ Date readFrom: s reset. time at: 1 put: d]. dateText _ text. ^true! now | d | d _ Time dateAndTimeNow. self date: (d at: 1). self time: (d at: 2).! proceed: aBoolean! time ^time at: 2! time: aTime time at: 2 put: aTime. aTime = CurrentTimeIndicator ifTrue: [timeeText _ ((time at: 1) printFormat: #(1 2 3 32 2 2 )) asText.! ! !TimeSpecifier methodsFor: 'operations'! current self date: CurrentDateIndicator. self time: CurrentTimeIndicator.! lastMonth | d m1 m2 | d _ time at: 1. m1 _ Date daysInMonth: (d monthName) forYear: (d year). d _ d subtractDays: m1. m2 _ Date daysInMonth: (d monthName) forYear: (d year). self date: (m2 > m1 ifTrue: [d subtractDays: (m2 - m1)] ifFalse: [m2 < m1 ifTrue: [d addDays: (m1 - m2)] ifFalse: [d]]).! lastYear |Text _ CurrentTimeText] ifFalse: [timeText _ aTime printString asText]. self changed: #timeText.! timeText ^timeText! timeText: text | s d | text = CurrentTimeText ifTrue: [time at: 2 put: CurrentTimeIndicator] ifFalse: [s _ ReadWriteStream with: (text asString). d _ Time readFrom: s reset. time at: 2 put: d]. timeText _ text. ^true! unixVersionTime | seconds secondCount timeZoneAdjustment | "returns the specified time and date as unix seconds" (time at: 1) = CurrentDateIndicator d delta | d _ time at: 1. delta _ (Date leapYear: (d year)) == 1 ifTrue: [(d day) > 59 ifTrue: [366] ifFalse: [365]] ifFalse: [365]. d _ d subtractDays: delta. delta _ (Date leapYear: (d year)) == 1 ifTrue: [(d day) < 61 ifTrue: [1] ifFalse: [0]] ifFalse: [0]. self date: (d subtractDays: delta)! nextMonth | d | d _ time at: 1. self date: (d addDays: (d daysInMonth))! nextYear | d delta | d _ time at: 1. delta _ (Date leapYear: (d year)) == 1 ifTrue: [(d day) > 59 ifTr ifTrue: [^0] ifFalse: [ seconds _ (time at: 1) asSeconds + (time at: 2) asSeconds. secondCount _ seconds - 2177452800. "subtract in the total seconds from Jan 01, 1901 (the start of Smalltalk time) up to Jan 01, 1970 (the start of Unix time)." "Add 8 hours for Pacific time." timeZoneAdjustment _ 8. "timeZoneAdjustment is an adjustment to GMT" secondCount _ secondCount + (3600 * timeZoneAdjustment). "Correct for daylight savings" secondCount _ secondCount - (self correctedFroue: [365] ifFalse: [366]] ifFalse: [365]. d _ d addDays: delta. delta _ (Date leapYear: (d year)) == 1 ifTrue: [(d day) > 59 ifTrue: [1] ifFalse: [0]] ifFalse: [0]. self date: (d addDays: delta)! ! !TimeSpecifier methodsFor: 'private'! correctedFrom: secondCount "Answer number of seconds needed to correct seconds for dayLight savings. Constants are defined for DST in the United States as follows: firstDayDST is the day of a non-leap year on or before which DST begins or 0 if DST not used. lastDayDST is the day of a non-leap year on or before which DST ends." | theDate theTime dfirst dlast firstDayDST lastDayDST day | firstDayDST _ 120. "the last possible day for DST to start: Apr 30 of a non-leap year" lastDayDST _ 304. "the last possible day for DST to end: Oct 31 of a non-leap year" "Guess the number of days since Jan 1 1901." theDate _ Date fromDays: secondCount // 86400. "secondCount \\ 86400 is the number of seconds that were left over from the estimate of days" thepecifier methodsFor: 'updating'! changeRequest self dateText: (self dateText). self timeText: (self timeText). ^true! ! !LinkEntry methodsFor: 'accessing'! fromNode "Returns the instance variable fromNode of the receiver." ^fromNode! time "Returns the instance variable versionTime of the receiver." ^versionTime! time: aTime "Set the instance variable versionTime of the receiver." versionTime _ aTime.! toNode "Returns the instance variable toNode of the receiver." ^toNode! ! !LinkEntry methTime _ Time fromSeconds: secondCount \\ 86400. "Check for daylight savings time (DST). Correct DST parameters for leap years and adjust to previous Sunday if necessary" firstDayDST = 0 ifTrue: ["DST not used" ^0]. "Calculate the day of the year that DST actually begins, the last Sunday in April." dfirst _ ((Date newDay: (firstDayDST + theDate leap) year: theDate year) previous: #Sunday) day. "Calculate the day of the year that DST actually ends, the last Sunday in October." dlast _ ((Date newDaodsFor: 'private'! initializeFrom: node1 to: node2 fromNode _ node1. toNode _ node2.! ! !TextStyle methodsFor: 'accessing'! fontAt: index "This is private because no object outside TextStyle should depend on the representation of the font family in fontArray" | fontIndex | fontIndex _ index. fontIndex > fontArray size ifTrue: [fontIndex _ fontArray size]. fontIndex < 0 ifTrue: [fontIndex _ 1]. ((fontArray at: fontIndex) isKindOf: StrikeFont) ifTrue: [^fontArray at: fontIndex]. ((fontArrayy: (lastDayDST + theDate leap) year: theDate year) previous: #Sunday) day. day _ theDate day. ((day > dfirst and: [day < dlast]) or: [(day = dfirst and: [theTime hours > 1]) or: [day = dlast and: [theTime hours < 1]]]) ifTrue: "Daylight savings time in effect. Offset by an hour." [^3600]. ^0! fromUnixSeconds: unixSeconds | seconds secondCount timeZoneAdjustment theDate theTime | "returns the time and date from unix seconds" secondCount _ unixSeconds + 2177452800. "add in the total se at: 1) isMemberOf: StrikeFont) ifTrue: [^fontArray at: 1]. self error: 'No valid fonts in font array'.! ! !SearchResults methodsFor: 'access'! context: aContextIndex context _ aContextIndex! hyperGraph: aHyperGraph hyperGraph _ aHyperGraph! listMenu ^YellowButtonMenu! nodeNames ^nodeNames! selectedNode ^selectedNode! selectedNode: aString selectedNode _ aString! ! !SearchResults methodsFor: 'private'! buildNodeList: nodes | s nameAtt n vt | s _ nodes size. nodeList _ nodes. nodeNames _ conds from Jan 01, 1901 (the start of Smalltalk time) up to Jan 01, 1970 (the start of Unix time)." "Subtract 8 hours for Pacific time." timeZoneAdjustment _ 8. "timeZoneAdjustment is an adjustment to GMT" secondCount _ secondCount - (3600 * timeZoneAdjustment). "Correct for daylight savings" secondCount _ secondCount + (self correctedFrom: secondCount). theDate _ Date fromDays: secondCount // 86400. theTime _ Time fromSeconds: secondCount \\ 86400. ^(Array with: theDate with: theTime)! ! !TimeSArray new: s. 1 to: s do: [:i | nameAtt _ (nodes at: i) at: 5. (nameAtt at: 1) ifTrue: [n _ nameAtt at: 2] ifFalse: [n _ 'anon']. vt _ (nodes at: i) at: 2. nodeNames at: i put: (n, ': ', (vt = 0 ifTrue: ['current version'] ifFalse: [ (TimeSpecifier unixSecondsAsString: vt)]))].! ! !SearchResults methodsFor: 'menu messages'! browseNode | i n | selectedNode isNil ifTrue: [ Transcript cr; show: 'Node must be selected.'. self changed: #nodeNames. "really wanted to flash" ^nil]. i _ nodeNames indexOf: selectedNode. n _ nodeList at: i. Node open: (n at: 1) versionTime: (n at: 2) in: hyperGraph withSelectedText: (Array with: (n at: 3) with: (n at: 4))! ! !HyperGraph methodsFor: 'reading - writing'! read self readFrom: projectFileName! readFrom: aFileName | g protectionMask | g _ FileStream oldFileNamed: aFileName. g binary. g readOnly. hostMachineId _ (g nextNumber: 4). "originalMachineId" creationTime _ g nextNumber:4. "creationTime" graphStyle hostMachineNconNameIndex = nil ifTrue: [rpc reportError: 'getAttributeIndex'. ^nil]. objectIndex _ rpc getAttributeIndex: '.object'. objectIndex = nil ifTrue: [rpc reportError: 'getAttributeIndex'. ^nil]. typeIndex _ rpc getAttributeIndex: '.type'. typeIndex = nil ifTrue: [rpc reportError: 'getAttributeIndex'. ^nil]. xPosNameIndex _ rpc getAttributeIndex: '.x'. xPosNameIndex = nil ifTrue: [rpc reportError: 'getAttributeIndex'. ^nil]. yPosNameIndex _ rpc getAttributeIndex: '.y'. yPosNameIndex = nil ifTrue: [rpc ame: (g nextString). " host machine name" graphStyle hostDirectory: (g nextString). "host unix directory name" nodeStyle objectName: (g nextString). "new node object name" protectionMask _ (g next). nodeStyle protectionMask: protectionMask. linkStyle sourceByVersion: (g next = 1). linkStyle destinationByVersion: (g next = 1). nodeStyle isArchive: (g next = 1). g close.! write | g | g _ FileStream oldFileNamed: projectFileName. self writeOn: g.! writeFirstTimeTo: aFileName | g | g _ FileSreportError: 'getAttributeIndex'. ^nil]. demonIndex _ rpc getAttributeIndex: '.demon'. demonIndex = nil ifTrue: [rpc reportError: 'getAttributeIndex'. ^nil].! ! !HyperGraph methodsFor: 'access'! cancelLinkDestination linkDestination = nil ifFalse: [linkDestination destroyLinkDestination.]. linkDestination _ nil! cancelLinkSource linkSource = nil ifFalse: [linkSource destroyLinkSource.]. linkSource _ nil! contextName | r | contextName isNil ifTrue: [ r _ self rpc getContextAttributeValue: currentream newFileNamed: aFileName. self writeOn: g.! writeOn: aFileStream aFileStream binary. aFileStream writeShorten. aFileStream nextNumber: 4 put: hostMachineId. "originalMachineId" aFileStream nextNumber: 4 put: creationTime. "creationTime" aFileStream nextStringPut: (graphStyle hostMachineName). " host machine name" aFileStream nextStringPut: (graphStyle hostDirectory). "host unix directory name" aFileStream nextStringPut: (nodeStyle objectName). "new node object name" aFileStream nextPut: tContext for: iconNameIndex at: 0. r isNil ifTrue: [contextName _ currentContext printString] ifFalse: [(r at:1) = true ifTrue: [contextName _ r at: 2] ifFalse: [contextName _ currentContext printString]]]. ^contextName! contextName: aString contextName _ aString! creationTime ^creationTime! creationTime: anInteger creationTime _ anInteger! currentContext ^currentContext! currentContext: aContextIndex currentContext ~= aContextIndex ifTrue: [ currentContext _ aContextIndex. con(nodeStyle protectionMask). " protection mask" linkStyle sourceByVersion ifTrue: [aFileStream nextPut: 1] ifFalse: [aFileStream nextPut: 0]. linkStyle destinationByVersion ifTrue: [aFileStream nextPut: 1] ifFalse: [aFileStream nextPut: 0]. nodeStyle isArchive ifTrue: [aFileStream nextPut: 1] ifFalse: [aFileStream nextPut: 0]. aFileStream close.! ! !HyperGraph methodsFor: 'private'! setAttributeIndices | rpc | (rpc _ self rpc) isNil ifTrue: [^nil]. iconNameIndex _ rpc getAttributeIndex: '.name'. itextName _ nil].! demonIndex ^demonIndex! graphStyle ^graphStyle! hostMachineId ^hostMachineId! hostMachineId: anInteger hostMachineId _ anInteger! iconNameIndex ^iconNameIndex! linkDestination ^linkDestination! linkDestination: aHyperNode linkDestination = nil ifFalse: [linkDestination destroyLinkDestination.]. linkDestination _ aHyperNode! linkSource ^linkSource! linkSource: aHyperNode linkSource = nil ifFalse: [linkSource destroyLinkSource.]. linkSource _ aHyperNode! linkStyle ^linkStyle! nodeStyle ^nodeStyle! objectIndex ^objectIndex! projectFileName ^projectFileName! projectFileName: aString projectFileName _ aString! searchStyle ^searchStyle! targetContext ^targetContext! targetContext: aContextIndex targetContext _ aContextIndex! timeSpecifier ^timeSpecifier! typeIndex ^typeIndex! xPosNameIndex ^xPosNameIndex! yPosNameIndex ^yPosNameIndex! ! !HyperGraph methodsFor: 'link operations'! addLink | s d icon l r rpc toContext fromContext n | " adds a new link to the hypertext grae _ nil. linkDestination commitLinkDestination: (l at: 1) timeStamp: (l at: 2) icon: icon. linkDestination _ nil. ^l! addLinkFrom: fromNode to: toNode | l icon r rpc | icon _ FillInTheBlank request: 'Type link name'. (rpc _ self rpc) isNil ifTrue: [^nil]. (rpc beginTransaction: true) isNil ifTrue: [rpc reportError: 'beginTransaction:'. ^nil]. l _ rpc addLinkFrom: fromNode to: toNode fromAt: 1 toAt: 1 fromContext: currentContext toContext: currentContext. l isNil ifTrue: [rpc reportEph using source and destination points defined in node browsers. Source and destination attachment points must be defined. " (linkSource = nil) ifTrue: [self notify: 'Link source not defined'. ^nil]. (linkDestination = nil) ifTrue: [self notify: 'Link destination not defined'. ^nil]. s _ linkSource linkSource. d _ linkDestination linkDestination. s isNil | d isNil ifTrue: [^nil]. icon _ FillInTheBlank request: 'Type link name'. (rpc _ self rpc) isNil ifTrue: [^nil]. toContext _ linkDestination crrorAborting: 'addLink'. ^nil]. icon size == 0 ifTrue: [icon _ nil] ifFalse: [r _ rpc setLinkAttributeValue: (l at: 1) for: iconNameIndex as: true with: icon with: 0. r isNil ifTrue: [ rpc reportErrorAborting: 'setLinkAttributeValue'. ^nil]]. rpc commitTransaction. ^(l at: 1)! addLinkFrom: fromNode to: toNode fromCharPos: fromPos toCharPos: toPos | l rpc | " adds a new link to the hypertext graph using link creation defaults" (rpc _ self rpc) isNil ifTrue: [^nil]. l _ rpc addLinontext. fromContext _ linkSource context. l _ rpc addLinkFrom: (linkSource nodeIndex) to: (linkDestination nodeIndex) fromAt: (s charPosition) toAt: (d charPosition) fromContext: fromContext toContext: toContext. l isNil ifTrue: [rpc reportError: 'addLink'. ^nil]. icon size == 0 ifTrue: [icon _ nil] ifFalse: [ r _ rpc setLinkAttributeValue: (l at: 1) for: iconNameIndex as: true with: icon with: 0. r isNil ifTrue: [ rpc reportError: 'setLinkAttributeValue'. ^nil]. "ikFrom: (fromNode nodeIndex) to: (toNode nodeIndex) fromAt: fromPos toAt: toPos fromContext: currentContext toContext: currentContext. l isNil ifTrue: [rpc reportError: 'addLink'. ^nil]. ^l! ! !HyperGraph methodsFor: 'initialize - release'! initialize graphStyle _ GraphStyle new. linkStyle _ LinkStyle new. linkStyle hyperGraph: self. nodeStyle _ NodeStyle new. nodeStyle hyperGraph: self. searchStyle _ SearchStyle new. searchStyle hyperGraph: self. timeSpecifier _ TimeSpecifier now. currf cross context link, must define attribute in both contexts" toContext ~= fromContext ifTrue: [ n _ toContext = currentContext ifTrue: [fromContext] ifFalse: [toContext]. rpc openContext: n. r _ rpc setLinkAttributeValue: (l at: 1) for: iconNameIndex as: true with: icon with: 0. rpc openContext: currentContext. r isNil ifTrue: [ rpc reportError: 'setLinkAttributeValue'. ^nil]. ]]. linkSource commitLinkSource: (l at: 1) timeStamp: (l at: 2) icon: icon. linkSourcentContext _ 1. ^self! ! !HyperGraph methodsFor: 'context access'! openContext: contextIndex | r | r _ HyperRPC open openContext: contextIndex. r isNil ifTrue: [HyperRPC reportError: 'openContext'. ^nil]. currentContext _ contextIndex. contextName _ nil.! rpc ^HyperRPC open! rpcFor: contextIndex | r | (contextIndex = 0) | (contextIndex = currentContext) ifTrue: [ ^HyperRPC open] ifFalse: [(BinaryChoice message: 'Wrong Context: Do you want to reopen the correct context?') ifFalse: [^nil]. r _ HyperRPC open openContext: contextIndex. r isNil ifTrue: [HyperRPC reportError: 'openContext'. ^nil]. currentContext _ contextIndex. contextName _ nil. ^HyperRPC open].! ! !Document methodsFor: 'initialization'! initialize nodeLists _ OrderedCollection with: nil with: nil with: nil with: nil. nodeSelections _ OrderedCollection with: nil with: nil with: nil with: nil. shiftIndex _ 0. shifting _ false. depth _ 0. nodePredicate _ '*'. linkPredicate _ '*'. ^self! ! !Document DocumentView openOn: d.! browseGraph: pane | n rpc | n _ nodeSelections at: (pane + shiftIndex). n = nil ifTrue: [Transcript cr; show: 'No root node selected'. self changed: #flash. ^nil]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. Graph openOn: hyperGraph at: n depth: 0 when: versionTime nodePredicate: nodePredicate linkPredicate: linkPredicate! browseNode: pane | n index rpc | index _ pane + shiftIndex. n _ nodeSelections at: index. n = nil ifTrue: [Transcript cr; show: 'No  methodsFor: 'private'! buildNodeList: nodes exceptFor: nodeIndex | u x n name nn | u _ nodes size. x _ (OrderedCollection new: u). 1 to: u do: [:i | n _ nodes at: i. (n at: 1) = nodeIndex ifFalse: [ name _ (((n at: 3) at: 1) = true) ifTrue: [(n at: 3) at: 2] ifFalse: [(n at: 1) printString]. nn _ Array with: (n at: 1) with: (n at: 2) with: name. x add: nn]. ]. ^x! makeLabel | t aLabel | aLabel _ hyperGraph contextName. versionTime ~= 0 ifTrue: [t _ Time fromUnixSeconnode selected'. self changed: #flash. ^nil]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. Node open: n versionTime: versionTime in: hyperGraph! browseNodeAttributes: pane | n index rpc | index _ pane + shiftIndex. n _ nodeSelections at: index. n = nil ifTrue: [Transcript cr; show: 'No node selected'. self changed: #flash. ^nil]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. Attribute openOnNode: n versionTime: versionTime in: hyperGraph! browseNodeVersions: pane | n indeds: versionTime. aLabel _ aLabel, ': Document Browser (', ((t at: 1) printFormat: #(1 2 3 32 2 2)). aLabel _ aLabel, ' ', ((t at: 2) printString), ')'] ifFalse: [aLabel _ aLabel, ': Document Browser']. ^aLabel! root: r | x | x _ OrderedCollection new. nodeLists at: 1 put: x. (r at: 3) isNil ifTrue: [r at: 3 put: '*']. x add: r.! updatePredicates (self changeRequest) ifTrue: [^true] ifFalse: [Transcript cr; show: 'Node and/or link predicate must be accepted'. self changed: x rpc | index _ pane + shiftIndex. n _ nodeSelections at: index. n = nil ifTrue: [Transcript cr; show: 'No node selected'. self changed: #flash. ^nil]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. NodeVersions openOn: n in: hyperGraph! browseVersionTime | aTimeSpecifier t | aTimeSpecifier _ hyperGraph timeSpecifier. t _ versionTime. t = 0 ifTrue: [aTimeSpecifier now] ifFalse: [aTimeSpecifier unixVersionTime: t]. TimeSpecifierView openOn: aTimeSpecifier.! compactDocument: pane |#flash. ^false].! ! !Document methodsFor: 'menu messages'! browseDocument: pane | n d rpc | n _ nodeSelections at: (pane + shiftIndex). n = nil ifTrue: [Transcript cr; show: 'No root node selected'. self changed: #flash. ^nil]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. d _ Document new. d versionTime: versionTime; hyperGraph: hyperGraph. d nodePredicate: nodePredicate; linkPredicate: linkPredicate. d root: (((nodeLists at: (pane + shiftIndex)) select: [:i | (i at: 1) = n]) at: 1). root r rpc t n entirely | root _ nodeSelections at: (pane + shiftIndex). root isNil ifTrue: [Transcript cr; show: 'No node selected'. self changed: #flash. ^nil]. versionTime ~= 0 ifTrue: [Transcript cr; show: 'Only current version can be compacted.'. ^nil]. entirely _ BinaryChoice message: 'Do you want to discard all history?'. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc linearizeGraph: root at: versionTime depth: depth nodePredicate: nodePredicate linkPredicate: linkPredicate nodeAttributes: nil linkAttributes: nil. r isNil ifTrue: [rpc reportError: 'linearizeGraph'. ^nil]. rpc beginTransaction: true. (r at: 1) do: [:each | r _ rpc compactNode: n entirely: entirely. r isNil ifTrue: [rpc reportErrorAborting: 'compactNode'. ^false]]. rpc commitTransaction. Cursor normal show.! compactNode: pane | n index rpc t r entirely | index _ pane + shiftIndex. n _ nodeSelections at: index. n = nil ifTrue: [Transcript cr; show: 'No node selected'. self changed: #flash. ^hyperGraph targetContext. t isNil ifTrue: [Transcript cr; show: 'No target context defined'. ^nil]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc checkForConflictsFrom: context to: t numNodes: 1 nodeList: (Array with: (Array with: n with: versionTime)). r isNil ifTrue: [rpc reportError: 'checkForConflictsFrom'. ^nil]. Transcript cr; show: 'Sorry, not finished this command yet!!'. Cursor normal show.! createNode: pane | n p icon r rpc vt | (shiftIndex = 0) ifFalse: [Transcripnil]. versionTime ~= 0 ifTrue: [Transcript cr; show: 'Only current version can be compacted.'. ^nil]. entirely _ BinaryChoice message: 'Do you want to discard all history?'. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc compactNode: n entirely: entirely. r isNil ifTrue: [rpc reportError: 'compactNode'. ^false]. Cursor normal show. ^true! compareDocument: pane | root r rpc t n compareNodes | root _ nodeSelections at: (pane + shiftIndex). root isNil ifTrue: [Transcript cr; show:t cr; show: 'Can only create in root pane'. self changed: #flash. ^false]. versionTime = 0 ifTrue: [ icon _ FillInTheBlank request: 'Type node name'. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. (rpc beginTransaction: true) isNil ifTrue: [rpc reportError: 'beginTransaction:'. ^false]. r _ Node createIn: hyperGraph. r isNil ifTrue: [^false]. n _ r nodeIndex. "node index" icon size = 0 ifTrue: [icon _ '*'] ifFalse: [rpc setNodeAttributeValue: n for: (hyperGraph iconNameInd 'No node selected'. self changed: #flash. ^nil]. t _ hyperGraph targetContext. t isNil ifTrue: [Transcript cr; show: 'No target context defined'. ^nil]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc linearizeGraph: root at: versionTime depth: depth nodePredicate: nodePredicate linkPredicate: linkPredicate nodeAttributes: nil linkAttributes: nil. r isNil ifTrue: [rpc reportError: 'linearizeGraph'. ^nil]. compareNodes _ OrderedCollection new: (r at: 1) size. (r at: 1) keys do: ex) as: true with: icon with: 0]. rpc commitTransaction. (nodeLists at: (pane + shiftIndex)) isNil ifTrue: [nodeLists at: (pane + shiftIndex) put: (OrderedCollection new)]. vt _ (versionTime = 0) ifTrue: [0] ifFalse: [r timeStamp]. (nodeLists at: (pane + shiftIndex)) add: (Array with: n with: vt with: icon). self select: pane param: icon. Cursor normal show. ^true] ifFalse: [Transcript cr; show: 'Can''t change history'. self changed: #flash. ^false].! currentVersion versionTi[:each | n add: (Array with: (each at: 1) with: versionTime)]. r _ rpc checkForConflictsFrom: context to: t numNodes: (compareNodes size) nodeList: compareNodes. r isNil ifTrue: [rpc reportError: 'checkForConflictsFrom:'. ^nil]. Transcript cr; show: 'Sorry, not finished this command yet!!'. Cursor normal show.! compareNode: pane | n index rpc t r | index _ pane + shiftIndex. n _ nodeSelections at: index. n = nil ifTrue: [Transcript cr; show: 'No node selected'. self changed: #flash. ^nil]. t _ me _ 0. self changed: #newLabel! deleteNode: pane | n r list rpc | versionTime = 0 ifTrue: [ n _ nodeSelections at: (pane + shiftIndex). n isNil ifTrue: [Transcript cr; show: 'No node selected'. self changed: #flash. ^false]. (BinaryChoice message: 'Do you really want to delete this node?') ifFalse: [^false]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc deleteNode: n. r isNil ifTrue: [ rpc reportError: 'deleteNode'. Cursor normal show. ^false]. list _ nodeLists at: (pane + shiftIndex). r _ list select: [:i | (i at: 1) = n]. list remove: (r at: 1) ifAbsent: []. nodeSelections at: (pane + shiftIndex) put: nil. Cursor normal show. ^true] ifFalse: [Transcript cr; show: 'Can''t change history'. self changed: #flash. ^false].! descendents: pane | ai r index rpc | index _ pane + shiftIndex. ai _ Array new: 1. ai at: 1 put: (hyperGraph iconNameIndex). (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc linearizeGraph: (nodeSelections aearizeGraph: root at: versionTime depth: depth nodePredicate: nodePredicate linkPredicate: linkPredicate nodeAttributes: nil linkAttributes: nil. r isNil ifTrue: [rpc reportError: 'linearizeGraph'. ^nil]. mergeNodes _ OrderedCollection new: (r at: 1) size. (r at: 1) do: [:each | mergeNodes add: (Array with: (each at: 1) with: versionTime)]. r _ rpc mergeContextFrom: context to: t numNodes: (mergeNodes size) nodeList: mergeNodes. r isNil ifTrue: [rpc reportError: 'mergeContext'. ^nil]. Cursor normt: index) at: versionTime depth: 2 nodePredicate: nodePredicate linkPredicate: linkPredicate nodeAttributes: ai linkAttributes: nil. r isNil ifTrue: [^nil]. nodeLists size < (index + 1) ifTrue: [nodeLists add: nil. nodeSelections add: nil]. nodeLists at: (index + 1) put: (self buildNodeList: (r at: 1) exceptFor: (nodeSelections at: index)).! editLinkStyle | aLinkStyle | Cursor execute show. aLinkStyle _ hyperGraph linkStyle. LinkStyleView openOn: aLinkStyle.! editNodeStyle | aNodeStyleal show.! mergeNode: pane | n index rpc t r | index _ pane + shiftIndex. n _ nodeSelections at: index. n = nil ifTrue: [Transcript cr; show: 'No node selected'. self changed: #flash. ^nil]. t _ hyperGraph targetContext. t isNil ifTrue: [Transcript cr; show: 'No target context defined'. ^nil]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc mergeContextFrom: context to: t numNodes: 1 nodeList: (Array with: (Array with: n with: versionTime)). r isNil ifTrue: [rpc reportError: ' | Cursor execute show. aNodeStyle _ hyperGraph nodeStyle. NodeStyleView openOn: aNodeStyle.! fileOut: pane | root fileName rpc | "Files out the document implied by the predicate given in the bottom view" root _ nodeSelections at: (pane + shiftIndex). root isNil ifTrue: [Transcript cr; show: 'No node selected'. self changed: #flash. ^nil]. fileName _ FillInTheBlank request: 'Type file name'. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. fileName size == 0 ifFalse: [ (HyperIO using:mergeContext'. ^nil]. Cursor normal show.! open: pane | s index | index _ pane + shiftIndex. s _ nodeSelections at: index. s isNil ifTrue: [Transcript cr; show: 'No node selected'. self changed: #flash. ^nil]. (node get: s versionTime: versionTime) isNil ifTrue: [self changed: #flash]. Cursor normal show.! printOut: pane | root fileName rpc | "Prints out the document implied by the predicate given in the bottom view" root _ nodeSelections at: (pane + shiftIndex). root isNil ifTrue: [Transcrip rpc) fileOutGraphNodes: nodePredicate links: linkPredicate toFile: fileName at: root for: versionTime depth: depth. Cursor normal show]! mergeDocument: pane | root r rpc t mergeNodes n | root _ nodeSelections at: (pane + shiftIndex). root isNil ifTrue: [Transcript cr; show: 'No node selected'. self changed: #flash. ^nil]. t _ hyperGraph targetContext. t isNil ifTrue: [Transcript cr; show: 'No target context defined'. ^nil]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc lint cr; show: 'No node selected'. self changed: #flash. ^nil]. fileName _ FillInTheBlank request: 'Type file name'. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. fileName size == 0 ifFalse: [ (HyperIO using: rpc) printOutGraphNodes: nodePredicate links: linkPredicate toFile: fileName at: root for: versionTime depth: depth. Cursor normal show]! search: pane | root r rpc | root _ nodeSelections at: (pane + shiftIndex). root isNil ifTrue: [Transcript cr; show: 'No node selected'. self changed: #flash. ^nil]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc linearizeGraph: root at: versionTime depth: depth nodePredicate: nodePredicate linkPredicate: linkPredicate nodeAttributes: nil linkAttributes: nil. r isNil ifTrue: [rpc reportError: 'linearizeGraph'. ^nil]. searchNodes _ r at: 1. Cursor execute show. hyperGraph searchStyle openWithInvoker: self find: #findOccurrences.! setVersionTime | time | time _ hyperGraph timeSpecifier unixVersionTime. versionTime _eNode1 self browseNode: 1! browseNode2 self browseNode: 2! browseNode3 self browseNode: 3! browseNode4 self browseNode: 4! browseNodeAttributes1 self browseNodeAttributes: 1! browseNodeAttributes2 self browseNodeAttributes: 2! browseNodeAttributes3 self browseNodeAttributes: 3! browseNodeAttributes4 self browseNodeAttributes: 4! browseNodeDemons1 self browseNodeDemons: 1! browseNodeDemons2 self browseNodeDemons: 2! browseNodeDemons3 self browseNodeDemons: 3! browseNodeDemons4 self br time. self changed: #newLabel! shiftLeft shiftIndex _ shiftIndex + 1. nodeSelections size < (shiftIndex + 4) ifTrue: [ nodeSelections add: nil. nodeLists add: nil]. shifting _ true. self changed: #list1. self changed: #list2. self changed: #list3. self changed: #list4. shifting _ false.! shiftRight shiftIndex = 0 ifFalse: [ shiftIndex _ shiftIndex - 1. shifting _ true. self changed: #list1. self changed: #list2. self changed: #list3. self changed: #list4. shifting _ falowseNodeDemons: 4! browseNodeVersions1 self browseNodeVersions: 1! browseNodeVersions2 self browseNodeVersions: 2! browseNodeVersions3 self browseNodeVersions: 3! browseNodeVersions4 self browseNodeVersions: 4! compactDocument1 self compactDocument: 1! compactDocument2 self compactDocument: 2! compactDocument3 self compactDocument: 3! compactDocument4 self compactDocument: 4! compactNode1 self compactNode: 1! compactNode2 self compactNode: 2! compactNode3 self compactNode: 3! compactNose. ]! traversalDepth "Allows editing the traversal depth" | d | d _ FillInTheBlank request: 'Type traversal depth' initialAnswer: (depth printStringRadix: 10). depth _ d asNumber.! update | ai r rpc | self updatePredicates ifFalse: [^nil]. ai _ Array new: 1. ai at: 1 put: (hyperGraph iconNameIndex). (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc getGraphViaAttributes: versionTime nodePredicate: nodePredicate linkPredicate: linkPredicate nodeAttributes: ai linkAttribude4 self compactNode: 4! compareDocument1 self compareDocument: 1! compareDocument2 self compareDocument: 2! compareDocument3 self compareDocument: 3! compareDocument4 self compareDocument: 4! compareNode1 self compareNode: 1! compareNode2 self compareNode: 2! compareNode3 self compareNode: 3! compareNode4 self compareNode: 4! createNode1 (self createNode: 1) ifTrue: [ self changed: #list1. (nodeSelections at: (1 + shiftIndex)) notNil ifTrue: [ self descendents1]]! createNode2 (tes: nil. r isNil ifTrue: [^nil]. nodeLists at: 1 put: (self buildNodeList: (r at: 1) exceptFor: nil). self changed: #list1. Cursor normal show.! ! !Document methodsFor: 'pane dispatchers'! browseDocument1 self browseDocument: 1! browseDocument2 self browseDocument: 2! browseDocument3 self browseDocument: 3! browseDocument4 self browseDocument: 4! browseGraph1 self browseGraph: 1! browseGraph2 self browseGraph: 2! browseGraph3 self browseGraph: 3! browseGraph4 self browseGraph: 4! browsself createNode: 2) ifTrue: [ self changed: #list2. (nodeSelections at: (2 + shiftIndex)) notNil ifTrue: [ self descendents2]]! createNode3 (self createNode: 3) ifTrue: [ self changed: #list3. (nodeSelections at: (3 + shiftIndex)) notNil ifTrue: [ self descendents3]]! createNode4 (self createNode: 4) ifTrue: [ self changed: #list4. (nodeSelections at: (4 + shiftIndex)) notNil ifTrue: [ self descendents4]]! deleteNode1 (self deleteNode: 1) ifTrue: [ self changed: #list1. (nodeSelections at: (1 + shiftIndex)) notNil ifTrue: [ self descendents1]]! deleteNode2 (self deleteNode: 2) ifTrue: [ self changed: #list2. (nodeSelections at: (2 + shiftIndex)) notNil ifTrue: [ self descendents2]]! deleteNode3 (self deleteNode: 3) ifTrue: [ self changed: #list3. (nodeSelections at: (3 + shiftIndex)) notNil ifTrue: [ self descendents3]]! deleteNode4 (self deleteNode: 4) ifTrue: [ self changed: #list4. (nodeSelections at: (4 + shiftIndex)) notNil ifTrue: [ self desce at: i) at: 3)]. ^nn! menu1 (ListMenues at: 1) == nil ifTrue: [ListMenues at: 1 put: (MultiActionMenu fromArray: #(('shift' 0 (('left' 2) ('right' 3))) ('version' 0 (('current' 4) ('edit time' 5) ('set time' 6))) () ('document' 0 (('depth' 7) ('printOut' 8) ('fileOut' 9) () ('spawn' 10) ('graph' 11) () ('search ' 22) ('compact ' 27) ('merge ' 23) ('compare ' 25))) ('node' 0 (('create' 13) ('delete' 14) ('compact ' 28) ('merge ' 24) ('compare ' 26) () ('spawn' 15) ('open' 16) ndents4]]! descendents1 self descendents: 1. self changed: #list2. Cursor normal show.! descendents2 self descendents: 2. self changed: #list3. Cursor normal show.! descendents3 self descendents: 3. self changed: #list4. Cursor normal show.! descendents4 self descendents: 4. Cursor normal show.! fileOut1 self fileOut: 1! fileOut2 self fileOut: 2! fileOut3 self fileOut: 3! fileOut4 self fileOut: 4! mergeDocument1 self mergeDocument: 1! mergeDocument2 self mergeDocument: 2! mergeDoc() ('attributes' 18) ('versions' 17) () ('styleSheet' 20))) ('link' 0 (('styleSheet' 21))) () ('update' 1) ) selectors: #(update shiftLeft shiftRight currentVersion browseVersionTime setVersionTime "6" traversalDepth printOut1 fileOut1 browseDocument1 browseGraph1 browseGraphDemons "12" createNode1 deleteNode1 browseNode1 open1 browseNodeVersions1 browseNodeAttributes1 "18" browseNodeDemons1 editNodeStyle editLinkStyle search1 "22" mergeDocument1 mergeNode1 compareDocument1 ument3 self mergeDocument: 3! mergeDocument4 self mergeDocument: 4! mergeNode1 self mergeNode: 1! mergeNode2 self mergeNode: 2! mergeNode3 self mergeNode: 3! mergeNode4 self mergeNode: 4! open1 self open: 1! open2 self open: 2! open3 self open: 3! open4 self open: 4! printOut1 self printOut: 1! printOut2 self printOut: 2! printOut3 self printOut: 3! printOut4 self printOut: 4! search1 self search: 1! search2 self search: 2! search3 self search: 3! search4 self search: 4! compareNode1 compactDocument1 compactNode1 "28"))]. ^ListMenues at: 1 "Document initialize"! menu2 (ListMenues at: 2) == nil ifTrue: [ListMenues at: 2 put: (MultiActionMenu fromArray: #(('shift' 0 (('left' 2) ('right' 3))) ('version' 0 (('current' 4) ('edit time' 5) ('set time' 6))) () ('document' 0 (('depth' 7) ('printOut' 8) ('fileOut' 9) () ('spawn' 10) ('graph' 11) () ('search' 22) ('compact' 27) ('merge' 23) ('compare' 25))) ('node' 0 (('delete' 14) ('compact' 28) ('merg! !Document methodsFor: 'access'! context ^context! context: aContextIndex context _ aContextIndex! hyperGraph ^hyperGraph! hyperGraph: ahyperGraph hyperGraph _ ahyperGraph! linkPredicate ^linkPredicate! linkPredicate: aString linkPredicate _ aString! list1 ^self list: 1! list2 ^self list: 2! list3 ^self list: 3! list4 ^self list: 4! list: pane | s nn index | index _ pane + shiftIndex. s _ (nodeLists at: index) size. nn _ Array new: s. 1 to: s do: [:i | nn at: i put: (((nodeLists at: index)e' 24) ('compare' 26) () ('spawn' 15) ('open' 16) () ('attributes' 18) ('versions' 17) () ('styleSheet' 20))) ('link' 0 (('styleSheet' 21)))) selectors: #(update shiftLeft shiftRight currentVersion browseVersionTime setVersionTime "6" traversalDepth printOut2 fileOut2 browseDocument2 browseGraph2 browseGraphDemons "12" createNode2 deleteNode2 browseNode2 open2 browseNodeVersions2 browseNodeAttributes2 "18" browseNodeDemons2 editNodeStyle editLinkStyle search2 "22" mergeDocument2 mergeNode2 compareDocument2 compareNode2 compactDocument2 compactNode2 "26"))]. ^ListMenues at: 2! menu3 (ListMenues at: 3) == nil ifTrue: [ListMenues at: 3 put: (MultiActionMenu fromArray: #(('shift' 0 (('left' 2) ('right' 3))) ('version' 0 (('current' 4) ('edit time' 5) ('set time' 6))) () ('document' 0 (('depth' 7) ('printOut' 8) ('fileOut' 9) () ('spawn' 10) ('graph' 11) () ('search' 22) ('compact' 27) ('merge' 23) ('compare' 25))) ('node' 0 (('delete' 14) ('compact' 28) ('merge4 compareDocument4 compareNode4 compactDocument4 compactNode4 "26"))]. ^ListMenues at: 4! node: aNode node _ aNode! nodePredicate ^nodePredicate! nodePredicate: aString nodePredicate _ aString! select1: aString shifting ifFalse: [ self select: 1 param: aString. (nodeSelections at: (1 + shiftIndex)) notNil ifTrue: [ self descendents1]]! select2: aString shifting ifFalse: [ self select: 2 param: aString. (nodeSelections at: (2 + shiftIndex)) notNil ifTrue: [ self descendents2]]! select3: aStrin' 24) ('compare' 26) () ('spawn' 15) ('open' 16) () ('attributes' 18) ('versions' 17) () ('styleSheet' 20))) ('link' 0 (('styleSheet' 21)))) selectors: #(update shiftLeft shiftRight currentVersion browseVersionTime setVersionTime "6" traversalDepth printOut3 fileOut3 browseDocument3 browseGraph3 browseGraphDemons "12" createNode3 deleteNode3 browseNode3 open3 browseNodeVersions3 browseNodeAttributes3 "18" browseNodeDemons3 editNodeStyle editLinkStyle search3 "22" mergeDocument3 mergeNodg shifting ifFalse: [ self select: 3 param: aString. (nodeSelections at: (3 + shiftIndex)) notNil ifTrue: [ self descendents3]]! select4: aString shifting ifFalse: [ self select: 4 param: aString. (nodeSelections at: (4 + shiftIndex)) notNil ifTrue: [ self descendents4]].! select: pane param: aString | i changes index size | index _ pane + shiftIndex. changes _ Array with: #list1 with: #list2 with: #list3 with: #list4. aString isNil ifTrue: [ nodeSelections at: index put: nil. size _ ne3 compareDocument3 compareNode3 compactDocument3 compactNode3 "26"))]. ^ListMenues at: 3! menu4 (ListMenues at: 4) == nil ifTrue: [ListMenues at: 4 put: (MultiActionMenu fromArray: #(('shift' 0 (('left' 2) ('right' 3))) ('version' 0 (('current' 4) ('edit time' 5) ('set time' 6))) () ('document' 0 (('depth' 7) ('printOut' 8) ('fileOut' 9) () ('spawn' 10) ('graph' 11) () ('search' 22) ('compact' 27) ('merge' 23) ('compare' 25))) ('node' 0 (('delete' 14) ('compact' 28) ('merge'odeSelections size. index + 1 to: size do: [:i | nodeSelections at: i put: nil. nodeLists at: i put: nil. (i - shiftIndex) <= 4 ifTrue: [self changed: (changes at: (i - shiftIndex))]]] ifFalse: [ i _ 1. [(((nodeLists at: index) at: i) at: 3) = aString] whileFalse: [i _ i + 1]. nodeSelections at: index put: (((nodeLists at: index) at: i) at: 1)].! selection1 ^(self selection: 1)! selection2 ^(self selection: 2)! selection3 ^(self selection: 3)! selection4 ^(self selection: 4)! selec 24) ('compare' 26) () ('spawn' 15) ('open' 16) () ('attributes' 18) ('versions' 17) () ('styleSheet' 20))) ('link' 0 (('styleSheet' 21)))) selectors: #(update shiftLeft shiftRight currentVersion browseVersionTime setVersionTime "6" traversalDepth printOut4 fileOut4 browseDocument4 browseGraph4 browseGraphDemons "12" createNode4 deleteNode4 browseNode4 open4 browseNodeVersions4 browseNodeAttributes4 "18" browseNodeDemons4 editNodeStyle editLinkStyle search4 "22" mergeDocument4 mergeNodetion: pane | index s | index _ shiftIndex + pane. s _ nodeSelections at: index. s isNil ifTrue: [^nil]. (nodeLists at: index) do: [:a | (a at: 1) = s ifTrue: [^(a at: 3)]]! versionTime: t versionTime _ t! ! !Document methodsFor: 'searching'! findOccurrences | searchString a b r s rpc | s _ self hyperGraph searchStyle. searchString _ s searchString. a _ Array new: (searchNodes size). 1 to: (searchNodes size) do: [:i | b _ Array new: 4. a at: i put: b. b at: 1 put: ((searchNodes at: i) at: 1). b at: 2 put: (s startingTime). b at: 3 put: (s endingTime). b at: 4 put: 0"starting position"]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc searchContents: (searchNodes size) nodeList: a nodeAttributes: (Array with: (self hyperGraph iconNameIndex)) code: 0. r isNil ifTrue: [rpc reportError: 'searchContents'. ^nil]. SearchResults openOn: r in: (self hyperGraph)! ! !NodeDiff class methodsFor: 'instance creation'! open: nodeIndex from: vt1 to: vt2 in: aHyperGraph m: 'sourceForm'. DestinationForm _ Form readFrom: 'destinationForm'. SourcePrefixForm _ Form readFrom: 'sourcePrefixForm'. DestinationPrefixForm _ Form readFrom: 'destinationPrefixForm'. "LinkFont initialize"! ! !LinkFont class methodsFor: 'class access'! destinationForm ^DestinationForm copy! sourceForm ^SourceForm copy! ! !GraphController class methodsFor: 'class initialization'! initialize "Initialize the yellow button menu information" YellowButtonMenu _ PopUpMultiMenu fromArray: #( ('grap "shows the differences between two versions of a node" | r p n1 n2 rpc | p _ self new. n1 _ Node get: nodeIndex versionTime: vt1 in: aHyperGraph. n1 isNil ifTrue: [^nil]. (n1 contents isMemberOf: Text) ifFalse: [^nil]. p node1: n1. n2 _ Node get: nodeIndex versionTime: vt2 in: aHyperGraph. n2 isNil ifTrue: [^nil]. (n2 contents isMemberOf: Text) ifFalse: [^nil]. p node2: n2. (rpc _ aHyperGraph rpc) isNil ifTrue: [^nil]. r _ rpc getNodeDifferences: nodeIndex from: vt1 to: vt2. r = nil ifTrue: [rh' 0 (('root' 15) ('depth' 24) () ('printOut' 17) ('fileOut' 18) () ('filter' 11) ('traverse' 14) () ('document' 28) ('search' 29) ('compact' 34) ('merge' 30) ('compare' 32) () ('auto-position' 12) ('accept' 13) )) ('node' 0 (('create' 2) ('delete' 4) ('compact' 35) ('merge' 31) ('compare' 33) () ('browse' 3) () ('attributes' 7) ('versions' 6) () ('reposition' 5) ('style sheet' 20))) ('link' 0 (('linkTo' 9) ('linkFrom' 10) () ('style sheet' 16))) () ('version' 0 (('current' 23) ('edit time' 22) ('setpc reportError: 'getNodeDifferences'. ^nil]. p parseDiff: r into: 1. r _ rpc getNodeDifferences: nodeIndex from: vt2 to: vt1. r = nil ifTrue: [rpc reportError: 'getNodeDifferences'. ^nil]. p parseDiff: r into: 2. NodeDiffView openOn: p with: n1 and: n2! ! !HyperIO class methodsFor: 'instance creation'! using: aHyperRPC | n | n _ super new. n rpc: aHyperRPC. ^n! ! !GraphStyle class methodsFor: 'instance creation'! new ^super new initialize! ! !GraphStyle class methodsFor: 'class initialization' time' 21))) ('zoom' 0 (('in' 25) ('out' 26) () ('full' 27))) ). YellowButtonMessages _ #(browseGraphDemons createNode browseNode deleteNode repositionNode browseNodeVersions browseNodeAttributes browseNodeDemons linkTo linkFrom browseGraph autoPositionNodes accept traverseGraph newRoot editLinkStyle printOut fileOut hide editNodeStyle setVersionTime browseVersionTime currentVersion traversalDepth zoomIn zoomBack zoomOut browseDocument search mergeGraph mergeNode compareGraph compareNode compactGra! initialize DefaultHostMachine _ 'norm'. DefaultHostDirectory _ '/tmp/'. DefaultProtectionMask _ 2r111111. "user r/w, group r/w, other r/w" YellowButtonMenu _ ActionMenu labels: 'again undo copy cut paste accept cancel' lines: #(2 5) selectors: #(again undo copySelection cut paste accept cancel). "GraphStyle initialize"! ! !LinkFont class methodsFor: 'instance creation'! new ^super new initialize! ! !LinkFont class methodsFor: 'class initialization'! initialize | i | SourceForm _ Form readFroph compactNode). "GraphController initialize"! ! !ContextTreeController class methodsFor: 'class initialization'! initialize "Initialize the yellow button menu information" CYellowButtonMenu _ PopUpMultiMenu fromArray: #( ('tree' 0 (('auto-position' 5) ('reposition' 9) ('accept' 6) )) ('context' 0 (('create' 7) ('delete' 8) ('compact' 18) () ('open' 10) ('show current' 1) () ('set target' 2) ('show target ' 4) () ('attributes' 11) () )) () ('version' 0 (('current' 12) ('edit time' 13) ('set time' 14))) ('zoom' 0 (('in' 15) ('out' 16) () ('full' 17))) () ('update' 3)). CYellowButtonMessages _ #(showCurrentContext target query showTargetContext autoPositionNodes accept createContext deleteContext repositionNode enterContext browseContextAttributes currentVersion browseVersionTime setVersionTime zoomIn zoomBack zoomOut compactContext). "ContextTreeController initialize"! ! !NodeController class methodsFor: 'access'! linkFont ^MyLinkFont! ! !NodeController class methodsFor: 'instance crurrentSelection _ nil. MyUndoSelection _ nil. OldCS _ nil. OldUS _ nil. WhoSetCS _ nil. WhoSetUS _ nil. "NodeController initialize"! ! !NodeDiffController class methodsFor: 'instance creation'! new | a f s g | "Answer a new instance of me with a null Paragraph to be edited. " a _ Array new: 25. f _ TextStyle default. s _ f fontArray. a at: 1 put: ((s at: 1) shallowCopy). a at: 2 put: ((s at: 2) deepCopy). g _ (a at: 2) glyphs. (a at: 2) glyphs: (g fill: (g computeBoundingBox) rule: Form ueation'! new | a f s | "Answer a new instance of me with a null Paragraph to be edited. " a _ Array new: 25. f _ TextStyle default. s _ f fontArray. 1 to: 24 do: [:i | a at: i put: ((s at: i) shallowCopy)]. a at: 25 put: (LinkFont new). f newFontArray: a. ^self newParagraph: (Paragraph withText: ('' asText) style: f)! ! !NodeController class methodsFor: 'class initialization'! initialize TextEditorYellowButtonMenu _ PopUpMultiMenu fromArray: #(('again' 1) ('undo' 2) () ('copy' 3) ('cut' 4nder mask: Form gray). a at: 3 put: ((s at: 2) deepCopy). g _ (a at: 3) glyphs. (a at: 3) glyphs: (g fill: (g computeBoundingBox) rule: Form under mask: Form lightGray). 4 to: 24 do: [:i | a at: i put: ((s at: i) shallowCopy)]. a at: 25 put: (LinkFont new). f newFontArray: a. ^self newParagraph: (Paragraph withText: ('' asText) style: f)! ! !NodeDiffController class methodsFor: 'class initialization'! initialize NodeDiffYellowButtonMenu _ PopUpMultiMenu fromArray: #(('copy' 1) () ('brow) ('paste' 5) () ('accept' 6) ('cancel' 7) () ('node' 0 (('delete' 27) ('compact' 31) ('merge' 32) ('compare' 33) () ('browse via link' 16) () ('attributes' 9) ('versions' 11) () ('styleSheet' 25))) ('link' 0 (('source' 12) ('destination' 13) () ('create' 14) ('delete' 15) () ('attributes' 17) () ('nextInstance' 19) ('nextUninstaniated' 20) ('pasteMissingLinks' 21) () ('styleSheet' 26))) ('graph' 0 (('browse graph' 8) ('browse document' 28)() ('absorb link' 22) ('separate' 23) () ('annotate' 24)se graph' 2 ) ('node' 0 (('attributes' 3) ('versions' 5))) ('link' 0 (('browse via link' 6) ('attributes' 7) () ('align' 8))) () ('align' 9) ('scroll mode' 0 (('aligned' 11) ('not aligned' 12))) "() ('changeSet' 10)"). NodeDiffYellowButtonMessages _ #(copySelection browseGraph browseNodeAttributes browseNodeDemons browseVersions browseViaLink browseLinkAttributes alignLink alignLines changeSet lockScrolling unlockScrolling). "NodeDiffController initialize"! ! !BitEditor class methods)) ('search' 0 (('new' 29) ('again' 30))) () ('update' 18)). TextEditorYellowButtonMessages _ #(again undo copySelection cut paste accept cancel browseGraph browseNodeAttributes browseNodeDemons browseVersions linkSource linkDestination addLink deleteLink browseViaLink browseLinkAttributes update nextLinkInstance nextUninstantiated pasteMissingLinks absorb separate annotate nodeStyleSheet linkStyleSheet deleteSelf browseDocument search searchAgain compactSelf merge compare). MyLinkFont _ 25. MyCFor: 'private'! bitEdit: aForm at: magnifiedFormLocation scale: scaleFactor remoteView: remoteView "Creates a BitEditor on aForm. That is, aForm is a small image that will change as a result of the BitEditor changing a second and magnified view of me. magnifiedFormLocation is where the magnified form is to be located on the screen. scaleFactor is the amount of magnification. This method implements a scheduled view containing both a small and magnified view of aForm. Upon accept, aForm is updated." | aFormView scaledFormView bitEditor topView extent menuView lowerRightExtent size newScaleFactor x y tooBig | scaledFormView _ FormHolderView new model: aForm. "Check aForm for allowable size and adjust scaleFactor if necessary." size _ aForm size * scaleFactor x * scaleFactor y. size > WordArray maxSize ifTrue: [ x _ scaleFactor x. y _ scaleFactor y. tooBig _ true. [tooBig and: [((x _ x-1) > 0) & ((y _ y-1) > 0)]] whileTrue: [ size _ aForm size * x * y. tooBig _ size > WordArray maxign: menuView viewport topRight with: scaledFormView viewport bottomRight. extent _ scaledFormView viewport extent + (0 @ lowerRightExtent y) + (4 @ 4). "+4 for borders" topView minimumSize: extent. topView maximumSize: extent. topView translateBy: magnifiedFormLocation. ^topView! ! !NodeFormController class methodsFor: 'instance creation'! openOn: aNode | r f | f _ aNode contents. f size = 0 ifTrue: [f _ Form fromUser. r _ self createOnForm: f.] ifFalse: [r _ self createOnForm: Size]. newScaleFactor _ Point x: (x max: 1) y: (y max: 1)] ifFalse: [newScaleFactor _ scaleFactor]. scaledFormView scaleBy: newScaleFactor. bitEditor _ self new. bitEditor setColor: #black. scaledFormView controller: bitEditor. topView _ StandardSystemView new. remoteView == nil ifTrue: [topView label: 'Bit Editor']. topView borderWidth: 2. topView insideColor: Form white. topView addSubView: scaledFormView. remoteView == nil ifTrue: "If no remote view, then provide a local view of the fo (Compiler new evaluate: f in: nil to: nil notifying: nil ifFail: [^nil])]. r firstSubView controller node: aNode. aNode controller: (r firstSubView controller). r controller open! openOn: aNode withSelectedLink: linkIndex self openOn: aNode! ! !ZoomScrollController class methodsFor: 'instance creation'! initialize YellowButtonMenu _ PopUpMenu labels: 'expand contract'. YellowButtonMessages _ #(expand contract). ZoomRatio _ 1.5. "ZoomScrollController initialize"! ! !NodeEntry class methorm" [aFormView _ FormView new model: scaledFormView workingForm. aFormView controller: NoController new. (aForm isKindOf: OpaqueForm) ifTrue: [scaledFormView insideColor: Form gray. aFormView insideColor: Form white]. aForm height < 50 ifTrue: [aFormView borderWidthLeft: 0 right: 2 top: 2 bottom: 2] ifFalse: [aFormView borderWidthLeft: 0 right: 2 top: 2 bottom: 0]. topView addSubView: aFormView below: scaledFormView] ifFalse: "Otherwise, the remote one should view the samedsFor: 'instance creation'! atTime: aTime atPosition: aPoint withIcon: aForm number: anOrdinal "Create a new instance of a NodeEntry" | n | n _ self new. n time: aTime. n location: aPoint. n icon: aForm. n ordinal: anOrdinal. ^n! new ^super new initialize! ! !Document class methodsFor: 'instance creation'! new ^super new initialize! openOn: aHyperGraph | aDocument | aDocument _ super new initialize. aDocument hyperGraph: aHyperGraph; versionTime: 0. aDocument context: aHyperGraph currentC form" [remoteView model: scaledFormView workingForm]. lowerRightExtent _ remoteView == nil ifTrue: [(scaledFormView viewport width - aFormView viewport width) @ (aFormView viewport height max: 50)] ifFalse: [scaledFormView viewport width @ 50]. menuView _ self buildColorMenu: lowerRightExtent colorCount: ((aForm isMemberOf: OpaqueForm) ifTrue: [3] ifFalse: [2]). menuView model: bitEditor. menuView borderWidthLeft: 0 right: 0 top: 2 bottom: 0. topView addSubView: menuView alontext. aDocument nodePredicate: '*'; linkPredicate: '*'. DocumentView openOn: aDocument! openOn: aHyperGraph nodePredicate: aString1 linkPredicate: aString2 | aDocument | aDocument _ super new initialize. aDocument hyperGraph: aHyperGraph; versionTime: 0. aDocument nodePredicate: aString1; linkPredicate: aString2. aDocument update. DocumentView openOn: aDocument! openOn: aHyperGraph predicates: anArray self openOn: aHyperGraph when: 0 predicates: anArray! openOn: aHyperGraph when: versionTime nodePredicate: aString1 linkPredicate: aString2 | aDocument | aDocument _ super new initialize. aDocument hyperGraph: aHyperGraph; versionTime: versionTime. aDocument context: aHyperGraph currentContext. aDocument nodePredicate: aString1; linkPredicate: aString2. aDocument update. DocumentView openOn: aDocument! openOn: aHyperGraph when: versionTime predicates: anArray | aDocument | aDocument _ super new initialize. aDocument hyperGraph: aHyperGraph; versionTime: versionTime. aDocument contedGraph: string1 linkPredicate: string2 linearly: true depth: 0. GraphView openOn: g nodePredicate: string1 linkPredicate: string2.! openOn: aHyperGraph nodePredicate: aString1 linkPredicate: aString2 "opens a new instance of Graph, composed as a view of current version of hyperGraph" ^self openOn: aHyperGraph when: 0 nodePredicate: aString1 linkPredicate: aString2! openOn: aHyperGraph when: time nodePredicate: string1 linkPredicate: string2 | g | "opens a new instance of Graph, composed as a view of xt: aHyperGraph currentContext. aDocument nodePredicate: (anArray at: 1); linkPredicate: (anArray at: 3). aDocument update. aDocument nodePredicate: (anArray at: 2). DocumentView openOn: aDocument! ! !Document class methodsFor: 'class initialization'! initialize ListMenues _ Array new: 4. "Document initialize"! ! !Graph class methodsFor: 'instance creation'! openOn: aHyperGraph "opens a new instance of Graph, composed as a view of current version of hyperGraph" ^self openOn: aHyperGraph when: 0hyperGraph, whose nodes satisfy string1 and whose links satisfy string2." g _ super new. g hyperGraph: aHyperGraph. g context: aHyperGraph currentContext. g root: nil. g isHistory: (time ~= 0). g versionTime: time. g readGraph: string1 linkPredicate: string2 linearly: false depth: 0. GraphView openOn: g nodePredicate: string1 linkPredicate: string2.! ! !Graph class methodsFor: 'class initialization'! initialize | f | "Initialize the attribute names for x and y node positions." MiniStyle _ Te nodePredicate: '*' linkPredicate: '*'! openOn: aHyperGraph at: nodeIndex depth: depth when: time nodePredicate: string1 linkPredicate: string2 | g | "opens a new instance of Graph, composed as a view of hyperGraph, rooted at nodeIndex, at time, whose nodes satisfy string1 and whose links satisfy string2" g _ super new. g hyperGraph: aHyperGraph. g context: aHyperGraph currentContext. g root: nodeIndex. g isHistory: (time ~= 0). g versionTime: time. g readGraph: string1 linkPredicate: string2 linxtStyle default deepCopy. f _ MiniStyle fontAt: 1 deepCopy. f glyphs: (Form readFrom: 'miniFontForm'). f xTable: # (0 0 3 7 10 14 17 21 23 24 24 24 27 27 27 30 37 41 46 52 58 62 65 69 72 79 83 83 83 86 88 86 89 93 95 99 105 110 118 122 124 127 130 134 139 142 146 148 151 156 159 162 165 169 172 176 179 183 187 189 191 193 196 200 204 211 216 220 224 228 232 236 241 245 247 251 255 259 265 270 274 278 282 286 290 294 299 304 310 314 318 322 325 329 333 337 342 344 348 352 356 360 364 368 372 376 378 381 3early: true depth: depth. GraphView openOn: g nodePredicate: string1 linkPredicate: string2.! openOn: aHyperGraph at: nodeIndex when: time nodePredicate: string1 linkPredicate: string2 | g | "opens a new instance of Graph, composed as a view of hyperGraph, rooted at nodeIndex, at time, whose nodes satisfy string1 and whose links satisfy string2" g _ super new. g hyperGraph: aHyperGraph. g context: aHyperGraph currentContext. g root: nodeIndex. g isHistory: (time ~= 0). g versionTime: time. g rea85 387 393 397 402 406 410 413 416 420 424 429 435 439 444 448 453 455 459 463 466). MiniStyle fontAt: 9 put: f. "Graph initialize"! ! !ContextTree class methodsFor: 'instance creation'! openOn: aHyperGraph "opens a new instance of ContextGraph, composed as a view of current version of hyperGraph" ^self openOn: aHyperGraph when: 0 predicate: '*'! openOn: aHyperGraph predicate: aString "opens a new instance of ContextGraph, composed as a view of current version of hyperGraph" ^self openOn: aHyperGraph when: 0 predicate: aString! openOn: aHyperGraph when: time predicate: string | g | "opens a new instance of Graph, composed as a view of hyperGraph, at time, whose contexts satisfy string" g _ self new. g hyperGraph: aHyperGraph. g context: 0. g root: nil. g isHistory: (time ~= 0). g versionTime: time. g readGraph: string linearly: false depth: 0. ContextTreeView openOn: g predicate: string.! ! !LinkStyle class methodsFor: 'class initialization'! initialize DefaultSourceByVersion _ falsrs: #(browseNode browseDifferences browseAttributes browseGraph browseDocument update). "NodeVersions initialize"! ! !NodeVersions class methodsFor: 'instance creation'! openOn: nodeIndex in: aHyperGraph | v r rpc | v _ self new. (rpc _ aHyperGraph rpc) isNil ifTrue: [^nil]. r _ rpc getNodeVersions: nodeIndex. r = nil ifTrue: [rpc reportError: 'getNodeVersions'. ^nil]. v initialize: r node: nodeIndex graph: aHyperGraph. NodeVersionsView openOn: v! ! !TimeSpecifier class methodsFor: 'instance cre. DefaultDestinationByVersion _ false. "LinkStyle initialize"! ! !LinkStyle class methodsFor: 'instance creation'! new | ls | ls _ super new. ls initialize. ^ls! ! !ZoomArea class methodsFor: 'class initialization'! initialize Cursors _ Array new: 9. Cursors at: 1 put: ZoomCursor allArrow. Cursors at: 2 put: ZoomCursor rightArrow. Cursors at: 3 put: ZoomCursor downArrow. Cursors at: 4 put: ZoomCursor leftArrow. Cursors at: 5 put: ZoomCursor upArrow. Cursors at: 6 put: ZoomCursor upperRigheation'! fromUnixSeconds: unixSeconds | p | "Initialized from the second count returned by a Unix time system call." p _ self new. ^p initialize: (p fromUnixSeconds: unixSeconds)! now ^self new initialize: (Time dateAndTimeNow)! ! !TimeSpecifier class methodsFor: 'class initialization'! initialize YellowButtonMenu _ ActionMenu labels: 'cut paste copy again undo accept cancel current now' lines: #(2 5 6) selectors: #(cut paste copySelection again undo accept cancel current now). CurrentDateIndicattArrow. Cursors at: 7 put: ZoomCursor lowerRightArrow. Cursors at: 8 put: ZoomCursor lowerLeftArrow. Cursors at: 9 put: ZoomCursor upperLeftArrow. CornerRatio _ 0.25 "ZoomArea initialize"! ! !ZoomArea class methodsFor: 'instance creation'! on: relativeSize at: aPoint1 withCursorAt: aPoint2 | area | area _ self new. area initialSize: relativeSize; initialLocation: aPoint1; initialPosition: aPoint2; initialize. ^area! ! !Subtask class methodsFor: 'task management'! kill: aTask aTask kill. Scor _ 0. CurrentDateText _ 'current' asText. CurrentTimeIndicator _ 86400. CurrentTimeText _ '' asText. "TimeSpecifier initialize"! ! !TimeSpecifier class methodsFor: 'time access'! unixSecondsAsString: s | p ss | p _ self new. ss _ p fromUnixSeconds: s. p initialize: ss. ^((p dateText string), ', ', (p timeText))! ! !SearchStyle class methodsFor: 'class initialization'! initialize YellowButtonMenu _ ActionMenu labels: 'again undo copy cut paste accept cancel' lines: #(2 5) selectors: #(agheduledSubtasksAccesssProtect critical: [ScheduledSubtasks remove: aTask ifAbsent: []]! terminateAll "Kill all the scheduled tasks." | tasks | ScheduledSubtasksAccesssProtect critical: [tasks _ ScheduledSubtasks shallowCopy]. tasks do: [:eachTask | Subtask kill: eachTask]! ! !NodeVersions class methodsFor: 'class initialization'! initialize YellowMenu _ ActionMenu labels: 'browse node\browse differences\browse attributes\browse graph\browse document\update' withCRs lines: #(1 4 6) selectoain undo copySelection cut paste accept cancel). "SearchStyle initialize"! ! !SearchStyle class methodsFor: 'instance creation'! new | ss | ss _ super new. ss initialize. ^ss! ! !Text class methodsFor: 'class initialization'! initialize "Initialize constants shared by classes associated with text display. Text initialize." (Smalltalk includes: TextConstants) ifFalse: [Smalltalk at: #TextConstants put: (Dictionary new: 32)]. TextConstants at: #CaretForm put: (Cursor extent: 16@16  fromArray: #( 2r110000000 2r110000000 2r1111000000 2r11111100000 2r11001100000 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0) offset: -8@0). self initTextConstants! ! !SearchResults class methodsFor: 'instance creation'! openOn: nodeList in: aHyperGraph | r topView listView | r _ super new. r hyperGraph: aHyperGraph. r context: aHyperGraph currentContext. r buildNodeList: nodeList. topView _ StandardSystemView model: r label: 'Search Results' minimumSize: 300@150. . y2 _ y3 - dy. ]. s add: x1@y1. s add: x2@y2. s add: fromPoint. s computeCurve. ^s"! ! !Arrow class methodsFor: 'class initialization'! initialize | a f | LeftHeads _ Array new: 17. 1 to: 17 do: [:i | LeftHeads at: i put: (Form extent: 7@15). a _ Arrow from: 7@(i-2) to: 0@7 withForm: (Form dotOfSize: 2). f _ LeftHeads at: i. f offset: 0@-7. a displayAngledAt: 30 length: 6 on: f. ]. RightHeads _ Array new: 17. 1 to: 17 do: [:i | RightHeads at: i put: (Form extent: 7@15). listView _ SelectionInListView on: r aspect: #nodeNames change: #selectedNode: list: #nodeNames menu: #listMenu initialSelection: #selectedNode. listView borderWidth: 1. topView addSubView: listView. topView controller open! ! !SearchResults class methodsFor: 'class initialization'! initialize YellowButtonMenu _ ActionMenu labels: 'browseNode' withCRs lines: #() selectors: #(browseNode). "SearchResults initialize"! ! !Arrow class methodsFor: 'instance creation'! from: fromPoint a _ Arrow from: 0@(i-2) to: 7@7 withForm: (Form dotOfSize: 2). f _ RightHeads at: i. f offset: -7@-7. a displayAngledAt: 30 length: 6 on: f. ]. TopHeads _ Array new: 17. 1 to: 17 do: [:i | TopHeads at: i put: (Form extent: 15@7). a _ Arrow from: (i-2)@7 to: 7@0 withForm: (Form dotOfSize: 2). f _ TopHeads at: i. f offset: -7@0. a displayAngledAt: 30 length: 6 on: f. ]. BottomHeads _ Array new: 17. 1 to: 17 do: [:i | BottomHeads at: i put: (Form extent: 15@7). a _ Arr to: toPoint withForm: aForm "Create a new arrow fromPoint toPoint using aForm." | s | s _ super from: fromPoint to: toPoint withForm: aForm. ^s! splineFrom: fromPoint to: toPoint withForm: aForm "Create a new arrow fromPoint toPoint using aForm." " | s x0 y0 x1 y1 x2 y2 x3 y3 a b dx dy delta a1 b1 a2 b2| s _ super new. s form: aForm. x0 _ toPoint x. y0 _ toPoint y. x3 _ fromPoint x. y3 _fromPoint y. s add: toPoint. delta _ (y3 - y0) / 30. (x0 = x3) ifFalse: [ (y0 = y3) ifFalse: [ a _ (y3ow from: (i-2)@0 to: 7@7 withForm: (Form dotOfSize: 2). f _ BottomHeads at: i. f offset: -7@-7. a displayAngledAt: 30 length: 6 on: f. ]. "Arrow initialize"! ! !Arrow class methodsFor: 'constants'! bottomHeadAt: index ^BottomHeads at: index! leftHeadAt: index ^LeftHeads at: index! rightHeadAt: index ^RightHeads at: index! topHeadAt: index ^TopHeads at: index! ! !ZoomCursor class methodsFor: 'class initialization'! initialize AllArrowCursor _ (Cursor extent: 16@16 fromA-y0)/(x3-x0). b _ ((x0*y3) - (x3*y0)) / (x0 - x3). dx _ (x3 - x0) / 3. x1 _ x0 + dx. x2 _ x3 - dx. y1 _ a*x1 + b. y2 _ a*x2 + b. a1 _ 0-(1/a). b1 _ y1 - (a1*x1). a2 _ 0-(1/a). b2 _ y2 - (a2*x2). x1 _ x1 + delta. y1 _ a1*x1 + b1. x2 _ x2 + delta. y2 _ a2*x2 + b2. ] ifTrue: [ delta _ (x3 - x0) /30. dx _ (x3 - x0) / 3. y1 _ y0 + delta. x1 _ x0 + dx. y2 _ y0 + delta. x2 _ x3 - dx. ] ] ifTrue: [ dy _ (y3 - y0) / 3. x1 _ x0 + delta. y1 _ y0 + dy. x2 _ x0 + deltarray: #( 2r0000000100000000 2r0000001110000000 2r0000011111000000 2r0000111111100000 2r0001000100010000 2r0011000100011000 2r0111000100011100 2r1111111111111110 2r0111000100011100 2r0011000100011000 2r0001000100010000 2r0000111111100000 2r0000011111000000 2r0000001110000000 2r0000000100000000 2r0000000000000000) offset: -7@-7). DownArrowCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000111111100000 2r0000011111000000 2r0000001110000000 2r0000000100000000 2r0000000000000000) offset: -7@-14). LeftArrowCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000000000000 2r0000000000000000 2r0000000000000000 2r0000000000000000 2r0001000000000000 2r0011000000000000 2r0111000000000000 2r1111111111111110 000000001000 2r0000000000001100 2r0000000000001110 2r0001111111111111 2r0001000000001110 2r0001000000001100 2r0001000000001000 2r0001000000000000 2r0001000000000000 2r0001000000000000 2r0001000000000000 2r0001000000000000 2r1111111000000000 2r0111110000000000 2r0011100000000000 2r0001000000000000) offset: -15@-15). LowerLeftArrowCursor _ (Cursor extent: 16@16 fromArray: #( 2r0001000000000000 2r0011000000000000 2r0111000000000000 2r1111111111111000 2r0112r0111000000000000 2r0011000000000000 2r0001000000000000 2r0000000000000000 2r0000000000000000 2r0000000000000000 2r0000000000000000 2r0000000000000000) offset: 0@-7). RightArrowCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000000000000 2r0000000000000000 2r0000000000000000 2r0000000000000000 2r0000000000010000 2r0000000000011000 2r0000000000011100 2r1111111111111110 2r0000000000011100 2r0000000000011000 2r0000000000010000 2r0000000000000000 2r00001000000001000 2r0011000000001000 2r0001000000001000 2r0000000000001000 2r0000000000001000 2r0000000000001000 2r0000000000001000 2r0000000000001000 2r0000000001111111 2r0000000000111110 2r0000000000011100 2r0000000000001000) offset: 0@-15). UpperLeftArrowCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000000001000 2r0000000000011100 2r0000000000111110 2r0000000001111111 2r0000000000001000 2r0000000000001000 2r0000000000001000 2r0000000000001000 2r0000000000000000 2r0000000000000000 2r0000000000000000 2r0000000000000000) offset: -14@-7). UpArrowCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000100000000 2r0000001110000000 2r0000011111000000 2r0000111111100000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000000000000) offset: -7@000000001000 2r0001000000001000 2r0011000000001000 2r0111000000001000 2r1111111111111000 2r0111000000000000 2r0011000000000000 2r0001000000000000) offset: 0@0). "ZoomCursor initialize"! ! !ZoomCursor class methodsFor: 'constants'! allArrow ^AllArrowCursor! downArrow ^DownArrowCursor! leftArrow ^LeftArrowCursor! lowerLeftArrow ^LowerLeftArrowCursor! lowerRightArrow ^LowerRightArrowCursor! rightArrow ^RightArrowCursor! upArrow ^UpArrowCursor! upperLeftArrow ^UpperLef0). UpperRightArrowCursor _ (Cursor extent: 16@16 fromArray: #( 2r0001000000000000 2r0011100000000000 2r0111110000000000 2r1111111000000000 2r0001000000000000 2r0001000000000000 2r0001000000000000 2r0001000000000000 2r0001000000000000 2r0001000000001000 2r0001000000001100 2r0001000000001110 2r0001111111111111 2r0000000000001110 2r0000000000001100 2r0000000000001000) offset: -15@0). LowerRightArrowCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000tArrowCursor! upperRightArrow ^UpperRightArrowCursor! ! HyperRPC class comment: ' HyperRPC is a remote procedure call mechanism that allows the hypertext user interface subsystem (implemented in Smalltalk) to communicate with the hypertext machine (implemented in C and running as a separate process under Unix). Three files are used to communicate with the hyperText machine (HM): a CommandFile is used to pass messages from smalltalk to HM; a ResponseFile is used to pass messages from HM to smalltalk; a ControlFile is used to synchronize the smalltalk process with the HM process. Synchronization is achieved by obtaining exclusive locks on the ControlFile using the unix system call `flock''. This system call has the nice property that a process that is waiting to obtain a lock can be blocked - thus we don''t waste cpu cycles in a busy wait; and the receiver of the message is activated as soon as the message arrives. Typical scenario: 1) Smalltalk has lock on control file, HM is btalk''s turn to acquire the lock, not writable means that it is HM''s turn. '! !HyperRPC class methodsFor: 'instance creation'! open self isReady ifFalse: [self startUp]. HyperRPCErrorCode _ 0. HyperRPCErrorMessage _ nil. HyperRPCErrorParams _ nil. ^self new initialize! ! !HyperRPC class methodsFor: 'class initialization'! cleanUp | d | "cleaning up after the child process crashes" ResponsePipe notNil ifTrue: [ ResponsePipe cleanUp. CommandPipe cleanUp. d _ TekSystemCall wait. d systemlocked waiting to obtain lock. 2) Smalltalk puts messages in CommandFile, and signals to me that command is ready by releasing the lock on ControlFile. 3) HM obtains lock on ControlFile, and Smalltalk blocks waiting to obtain lock. 4) HM passes command message to appropriate server and then puts result message in Response file. 5) HM signals to Smalltalk that response is ready by releasing the lock on ControlFile. 6) Smalltalk obtains lock on ControlFile, and HM Invoke. ResponsePipe _ nil. CommandPipe _ nil].! finishUp "if hypertext system is open, closes any open hypertext windows and terminates execution of hypertext abstract machine process" | m | CommandPipe notNil ifTrue: [ ScheduledControllers scheduledControllers do: [:c | m _ c model. ((m isMemberOf: Node) | (m isMemberOf: Graph) | (m isMemberOf: GraphStyle) | (m isMemberOf: NodeStyle) | (m isMemberOf: LinkStyle) | (m isMemberOf: Attribute) | (m isMemberOf: NodeDiff) | (m isblocks waiting to obtain lock. 7) Now, we''re back in same state as step 1 above and ready to process next command. Unfortunately, the `flock'' system call cannot be used directly as a semiphore because it lacks the notion of a queue; the guy who has been waiting longest to obtain the lock does not necessarily get it first. This deficiency causes a problem in our scheme because after a process gives up its lock, it immediately tries to reobtain the lock (steps 3 and 6, above). To avoid a MemberOf: NodeVersions)) ifTrue: [c closeAndUnschedule]]. HyperRPC open quit].! initialize ResponsePipe _ nil. CommandPipe _ nil.! startUp | d cIn cOut st a b c | d _ TekSystemCall crPipe. d systemInvoke. cIn _ d D0Out. CommandPipe _ HyperPipeStream writeOn: d A0Out. d _ TekSystemCall crPipe. d systemInvoke. ResponsePipe _ HyperPipeStream readOn: d D0Out. cOut _ d A0Out. st _ String with: (Character value:0). a _ Array new: 5. a at: 1 put: '/usr/neptune/hyperLocal', st. a at: 2 putrace condition when a process gives up its lock, the process sets a signal that indicates that it is the other process''s turn to acquire the lock. The former process sits in a busy wait until the latter process signals that it has obtained the lock. In practice the busy wait is very short (less than one quantum of the process scheduler - currently equal to 1 millisecond). The `it''s your turn'' signal has been implemented using the protection bits on the ControlFile: not readable means it is Small: (cIn printString), st. a at: 3 put: (cOut printString), st. a at: 4 put: (ResponsePipe printString), st. a at: 5 put: (CommandPipe printString), st. b _ TekSystemCall vfork. c _ TekSystemCall exec: '/usr/neptune/hyperLocal', st with: a. b systemInvoke. c systemInvoke. "only the parent gets here, close unused ends of pipes" d _ TekSystemCall close: cIn. d systemInvoke. d _ TekSystemCall close: cOut. d systemInvoke.! ! !HyperRPC class methodsFor: 'class access'! errorCode ^HyperRPCErrorCode! errorMessage ^HyperRPCErrorMessage! errorParams ^HyperRPCErrorParams! incompleteTransactionError ^(HyperRPCErrorCode == 44)! isReady "are communications to hypertext srever set up?" ^ResponsePipe notNil! linkDoesNotExistYetError ^(HyperRPCErrorCode == 54)! reportError: aString self notify: aString, ' RPC failed: ', (String with: Character cr), HyperRPCErrorMessage.! reportErrorAborting: aString | s | s _ aString, ' RPC failed: ', (String with: Character cr), HyperRPCErrorMessage. self open abortion' 0 (('accept' 8) ('cancel' 9))) () ('loop' 0) ('file out' 10) ). "add loop" foo menuArrayAt: 4 put: foo. "start up a cursor position" ^foo startUp "PopUpMultiMenu example"! ! !MultiActionMenu class methodsFor: 'instance creation'! fromArray: anArray selectors: selArray | aMenu | aMenu _ self fromArray: anArray. aMenu setSelectors: selArray. ^ aMenu! ! !FormView class methodsFor: 'examples'! exampleOne "Frame a Form (specified by the user) with a border of 5 bits in width andtTransaction. self notify: s. ^nil! ! !PopUpMultiMenu class methodsFor: 'instance creation'! fromArray: anArray "creates a new instance of the receiver, initialized with data in anArray" ^self fromArray: anArray font: (TextStyle default fontAt: 1)! fromArray: anArray font: aFont "creates a new instance of the receiver, initialized with data in anArray" ^self new fromArray: anArray font: aFont! ! !PopUpMultiMenu class methodsFor: 'class initialization'! initialize "initializes class PopUpMultiMenu display it offset 100 x 100 from the corner of the display screen." | f view | f _ Form fromUser. view _ self new model: f. view translateBy: 100 @ 100. view borderWidth: 5. view insideColor: Form white. view display. view release "FormView exampleOne."! ! !NodeView class methodsFor: 'instance creation'! createOn: aNode "creates a view for viewing and modifying aNode" | aNodeView topView r s n s1 | aNodeView _self new. aNodeView model: aNode. aNode controller: (aNodeView controller). a" NullInstance _ (self fromArray: #((' ' 0))) frame: (Quadrangle region: (-1@-1 corner: -1@-1) borderWidth: 1 borderColor: Form black insideColor: Form white); form: (Form extent: 0@0). BlankInstance _ NullInstance. "PopUpMultiMenu initialize"! ! !PopUpMultiMenu class methodsFor: 'special instances'! blank "answers the blank PopUpMultiMenu, which may be used someday to signify a menu that will be computed on the fly." ^BlankInstance! null "answers the null PopUpMultiMenu, which is one wNode mergeLinkAttachments. aNodeView borderWidth: 1. ^aNodeView! openOn: aNode "opens a browser for viewing and modifying aNode" self openOn: aNode withSelectedLink: nil! openOn: aNode withSelectedLink: linkIndex "opens a browser for viewing and modifying aNode" | aNodeView topView s | aNodeView _self new. aNodeView model: aNode. aNode controller: (aNodeView controller). aNode mergeLinkAttachments. linkIndex isNil ifFalse: [s _ aNode firstInstanceOf: linkIndex. s notNil ifTrue: [ ith no selections" ^NullInstance! ! !PopUpMultiMenu class methodsFor: 'timing'! delayCount "answer the # of iterations to delay to allow user to get to next menu before it might disappear" ^80! ! !PopUpMultiMenu class methodsFor: 'examples'! example "creates a PopUpMultiMenu and invokes it" | foo | "create basic menu" foo _ PopUpMultiMenu fromArray: #( ('operations' 0 (('again' 1) ('undo' 2) () ('copy' 3) ('cut' 4) ('paste' 5))) ('execution' 0 (('do it' 6) ('print it' 7))) ('compila aNodeView initialSelection: (Array with: s with: s)]]. topView _ StandardSystemView new. aNodeView borderWidth: 1. topView borderWidth: 1. topView model: aNodeView model. topView addSubView: aNodeView. topView label: (aNode makeLabel). topView minimumSize: 200 @ 150. topView controller open! openOn: aNode withSelectedText: textSel "opens a browser for viewing and modifying aNode" | aNodeView topView s | aNodeView _self new. aNodeView model: aNode. aNode controller: (aNodeView controller). aNode mergeLinkAttachments. textSel isNil ifFalse: [s _ aNode adjustSelectedText: textSel. aNodeView initialSelection: s. aNodeView controller setLastUndoSelection]. topView _ StandardSystemView new. aNodeView borderWidth: 1. topView borderWidth: 1. topView model: aNodeView model. topView addSubView: aNodeView. topView label: (aNode makeLabel). topView minimumSize: 200 @ 150. topView controller open! view: aNode withSelectedLink: linkIndex "creates a view for viewing and mod200@150. topView minimumSize: size. topView resizeMinimumCenteredAt: Sensor cursorPoint. sr _ topView displayBox. savedArea _ Form fromDisplay: sr. lr _ topView labelDisplayBox. labelArea _ Form fromDisplay: lr. Cursor normal show. topView controller startUp. topView release. savedArea displayOn: Display at: (sr origin). labelArea displayOn: Display at: (lr origin).! ! !AttributeView class methodsFor: 'instance creation'! openOn: anAttribute "Create and schedule an instance of me that displays ifying aNode" | aNodeView topView r s n s1 t | aNodeView _self new. aNodeView model: aNode. aNode controller: (aNodeView controller). aNode mergeLinkAttachments. linkIndex isNil ifFalse: [s _ aNode firstInstanceOf: linkIndex. s notNil ifTrue: [ aNodeView initialSelection: (Array with: s with: s)]]. aNodeView borderWidth: 1. ^aNodeView! view: aNode withSelectedText: textSel "creates a view for viewing and modifying aNode" | aNodeView topView r s n s1 t | aNodeView _self new. aNodanAttribute." | topView aLabel listView editView | aLabel _ anAttribute makeLabel. topView _ self model: anAttribute label: aLabel minimumSize: 300@150. listView _ SelectionInListView on: anAttribute aspect: #attributeNames change: #selectedAttribute: list: #attributeNames menu: #listMenu initialSelection: #selectedAttribute. editView _ TextView on: anAttribute aspect: #value change: #accept: menu: #textMenu. topView addSubView: listView in: (0@0 corner: 0.4@1)borderWidth: 1. topView aeView model: aNode. aNode controller: (aNodeView controller). aNode mergeLinkAttachments. textSel isNil ifFalse: [s _ aNode adjustSelectedText: textSel. aNodeView initialSelection: s. aNodeView controller setLastUndoSelection]. aNodeView borderWidth: 1. ^aNodeView! ! !GraphStyleView class methodsFor: 'instance creation'! requestOn: aGraphStyle | topView size savedArea labelArea sr lr| Cursor execute show. topView _ self new. topView borderWidth: 1; model: aGraphStyle; label: 'GrapddTypeView: (0.4@0 corner: 1@0.125) on: anAttribute. topView addSubView: editView in: (0.4@0.125 corner: 1@1) borderWidth: 1. topView controller open! ! !AttributeView class methodsFor: 'examples'! example1 | a numPairs r | a _ Attribute new. numPairs _ 2. r _ Array new: (numPairs + 1). r at:1 put: numPairs. r at:2 put: (Array new: 4). (r at:2) at: 1 put: 1. "attribute index" (r at:2) at: 2 put: 'first Attribute'. "attribute name" (r at:2) at: 3 put: 'value1'. (r at:2) at:4 put: true. r at:3 put: (Ah Style Sheet'. topView addProceedButtonViewIn: (0@0 corner: 0.5@0.1). topView addAbortButtonViewIn: (0.5@0 corner: 1.0@0.1). topView addLabelView: 'Directory' In: (0@0.1 corner: 0.4@0.333). topView addDirectoryViewIn: (0.4@0.1 corner: 1@0.333). topView addLabelView: 'Host Name' In: (0@0.333 corner: 0.4@0.667). topView addHostViewIn: (0.4@0.333 corner: 1.0@0.667). topView addLabelView: 'Protection' In: (0@0.667 corner: 0.4@1.0). topView addProtectionBitsViewIn: (0.4@0.667 corner: 1.0@1.0). size _ rray new: 4). (r at: 3) at: 1 put: 1. "attribute index" (r at: 3) at: 2 put: 'second Attribute'. "attribute name" (r at: 3) at: 3 put: 'value2'. (r at: 3) at:4 put: true. a defineAttributes: r "AttributeView example1"! ! !SearchStyleView class methodsFor: 'instance creation'! openOn: aSearchStyle invoker: aModel findMsg: aMsg | topView size | topView _ self new. aSearchStyle view: topView. topView invoker: aModel; findMsg: aMsg. topView borderWidth: 1; model: aSearchStyle; label: 'Search Style Sheet'. topView addSearchButtonViewIn: (0@0 corner: 1.0@0.15). topView addLabelView: 'regular expression' In: (0@0.15 corner: 0.4@0.4). topView addSearchStringViewIn: (0.4@0.15 corner: 1.0@0.4). topView addLabelView: 'start search in version' In: (0@0.4 corner: 0.4@0.7). topView addTimeViewFor: aSearchStyle startTime in: (0.4@0.4 corner: 1.0@0.7). topView addLabelView: 'end search in version' In: (0@0.7 corner: 0.4@1.0). topView addTimeViewFor: aSearchStyle endTime in: (0.4@0.7 corner: 1.0@1.0). size _onView: (0.4@0.0 extent: 1.0@1.0) on: aNodeVersion. aNodeVersion view: topView. topView controller open! ! !NotifierView class methodsFor: 'instance creation'! openContext: haltContext label: aString contents: contentsString "Create and schedule an instance of me viewing a Debugger on haltContext. The view will be labeled with aString, and shows a short sender stack." | displayPoint cont | ErrorRecursion ifTrue: [ErrorRecursion _ false. self primitiveError: aString]. ErrorRecursion _ tru 320@160. topView minimumSize: size; maximumSize: size. topView controller open! ! !SearchStyleView class methodsFor: 'class initialization'! initialize TimeTitles _ Array with: 'current' with: 'set time' with: 'range from time' with: 'range to time'. "SearchStyleView initialize"! ! !TimeSpecifierView class methodsFor: 'instance creation'! openOn: aTimeSpecifier | topView | Cursor execute show. topView _ self new. topView borderWidth: 1; model: aTimeSpecifier; label: 'Version Time'. topView ae. cont _ ScheduledControllers activeController. (cont notNil and: [cont class ~= ScreenController]) ifTrue: [cont view repaintScrollBar. (Smalltalk saveSpace == false and: [cont view isKindOf: StandardSystemView]) ifTrue: [cont view saveDisplayForm]]. displayPoint _ ScheduledControllers activeController == nil ifTrue: [Display getViewportLocation + (320@240)] ifFalse: [ScheduledControllers activeController view displayBox center]. self openDebugger: (Debugger context: haltContextddLabelView: 'Date' In: (0@0 corner: 0.3@0.5). topView addDateViewIn: (0.3@0 corner: 1@0.25). topView addDateBitsViewIn: (0.3@0.25 corner: 1.0@0.5). topView addLabelView: 'Time' In: (0@0.5 corner: 0.3@1.0). topView addTimeViewIn: (0.3@0.5 corner: 1.0@0.75). topView addTimeBitsViewIn: (0.3@0.75 corner: 1.0@1.0). topView minimumSize: 250@150. Cursor normal show. topView controller open.! ! !NodeVersionsView class methodsFor: 'instance creation'! openOn: aNodeVersion | topView r s n s1 rpc | (rpc ) contents: contentsString label: aString displayAt: displayPoint. ErrorRecursion _ false. Processor activeProcess suspend! ! !GraphView class methodsFor: 'instance creation'! openOn: aGraph nodePredicate: string1 linkPredicate: string2 "Create and schedule a view of aGraph." | topView graphView nodePredicateLabelView linkPredicateLabelView nodePredicateHolderView nodePredicateHolder linkPredicateHolderView linkPredicateHolder zoomView cn cl t | topView _ StandardSystemView new. topView borde_ aNodeVersion graph rpcFor: (aNodeVersion context)) isNil ifTrue: [^nil]. r _ rpc getNodeAttributeValue: (aNodeVersion nodeIndex) for: (aNodeVersion graph iconNameIndex) at: 0. s _ aNodeVersion graph contextName. ((r isNil) or: [(r at: 1) not]) ifTrue: [s _ s, ': Node Version Browser'] ifFalse: [s _ s, ': ', (r at: 2), ' Versions']. topView _ self model: aNodeVersion label: s minimumSize: 250@ 150. topView addMajorVersionView: (0.0@0.0 extent: 0.4@1.0) on: aNodeVersion. topView addMinorVersirWidth: 1; model: aGraph; label: aGraph makeLabel. graphView _ self new model: aGraph; borderWidth: 2; insideColor: Form white; initializeVisibility. topView addSubView: graphView in: (0@0 corner: 1@0.84) borderWidth: 1. zoomView _ ZoomScrollView new. zoomView size: 1@1; borderWidth: 2; insideColor: Form white. zoomView location: 0@0; graphView: graphView. graphView zoomView: zoomView. topView addSubView: zoomView in: (0@0.84 corner: 0.25@1) borderWidth: 1. nodePredicateLabelView _ DisplayTextView new model: 'Nodes:' asDisplayText. nodePredicateLabelView insideColor: Form white; controller: NoController new. topView addSubView: nodePredicateLabelView in: (0.25@0.84 corner: 0.4@0.92) borderWidth: 1. linkPredicateLabelView _ DisplayTextView new model: 'Links:' asDisplayText. linkPredicateLabelView insideColor: Form white; controller: NoController new. topView addSubView: linkPredicateLabelView in: (0.25@0.92 corner: 0.4@1) borderWidth: 1. nodePredicateHolder _ StringHolder new contents: string1. abelView _ DisplayTextView new model: 'Contexts' asDisplayText. predicateLabelView insideColor: Form white; controller: NoController new. topView addSubView: predicateLabelView in: (0.25@0.84 corner: 0.4@1.0) borderWidth: 1. predicateHolder _ StringHolder new contents: string. predicateHolderView _ StringHolderView container: predicateHolder. cn _ PredicateController new. cn graph: aGraph. predicateHolderView controller: cn. topView addSubView: predicateHolderView in: (0.4@0.84 corner: 1@1.0) bord nodePredicateHolderView _ StringHolderView container: nodePredicateHolder. cn _ PredicateController new. cn graph: aGraph. nodePredicateHolderView controller: cn. topView addSubView: nodePredicateHolderView in: (0.4@0.84 corner: 1@0.92) borderWidth: 1. linkPredicateHolder _ StringHolder new contents: string2. linkPredicateHolderView _ StringHolderView container: linkPredicateHolder. cl _ PredicateController new. cl graph: aGraph. linkPredicateHolderView controller: cl. topView addSubView: linkPrerWidth: 1. cn paragraph clippingRectangle: (0@0 corner: 0.1@0.1). cn accept. topView minimumSize: 300 @ 250. topView controller open! ! !LinkStyleView class methodsFor: 'instance creation'! openOn: aLinkStyle | topView size | topView _ self new. aLinkStyle view: topView. topView borderWidth: 1; model: aLinkStyle; label: 'Link Style Sheet'. topView addSaveButtonViewIn: (0@0 corner: 0.5@0.2). topView addRestoreButtonViewIn: (0.5@0 corner: 1.0@0.2). topView addLabelView: 'Source link always curreedicateHolderView in: (0.4@0.92 corner: 1@1) borderWidth: 1. cn paragraph clippingRectangle: (0@0 corner: 0.1@0.1). cn accept. cl paragraph clippingRectangle: (0@0 corner: 0.1@0.1). cl accept. topView minimumSize: 300 @ 250. topView controller open! ! !ContextTreeView class methodsFor: 'instance creation'! openOn: aGraph predicate: string "Create and schedule a view of aContextGraph." | topView graphView predicateLabelView predicateHolderView predicateHolder zoomView cn cl t | topView _ Standarnt?' In: (0@0.2 corner: 0.6@0.6). topView addSourceView: (0.6@0.2 corner: 1.0@0.6). topView addLabelView: 'Destination link always current?' In: (0@0.6 corner: 0.6@1.0). topView addDestinationView: (0.6@0.6 corner: 1.0@1.0). size _ 200@85. topView minimumSize: size; maximumSize: size. topView controller open! ! !ZoomScrollView class methodsFor: 'instance creation'! openOn: relativeSize at: aPoint | topView zoomView | topView _ StandardSystemView new. zoomView _ self new. zoomView size: relativedSystemView new. topView borderWidth: 1; model: aGraph; label: aGraph makeLabel. graphView _ self new model: aGraph; borderWidth: 2; insideColor: Form white; initializeVisibility. topView addSubView: graphView in: (0@0 corner: 1@0.84) borderWidth: 1. zoomView _ ZoomScrollView new. zoomView size: 1@1; borderWidth: 2; insideColor: Form white. zoomView location: 0@0; graphView: graphView. graphView zoomView: zoomView. topView addSubView: zoomView in: (0@0.84 corner: 0.25@1) borderWidth: 1. predicateLSize; borderWidth: 2; insideColor: Form white. zoomView location: aPoint. topView addSubView: zoomView in: (0@0 corner: 1@1) borderWidth: 1. topView controller open.! ! !NodeStyleView class methodsFor: 'instance creation'! openOn: aNodeStyle | topView size | topView _ self new. aNodeStyle view: topView. topView clearSwitchViews. topView borderWidth: 1; model: aNodeStyle; label: 'Node Style Sheet'. topView addSaveButtonViewIn: (0@0 corner: 0.5@0.1). topView addRestoreButtonViewIn: (0.5@0 corner: 1.0@0.1). topView addLabelView: 'Object Name' In: (0@0.1 corner: 0.4@0.4). topView addObjectNameViewIn: (0.4@0.1 corner: 1@0.4). topView addLabelView: 'Archive?' In: (0@0.4 corner: 0.4@0.7). topView addIsArchiveView: (0.4@0.4 corner: 1.0@0.7). topView addLabelView: 'Protection' In: (0@0.7 corner: 0.4@1.0). topView addProtectionBitsViewIn: (0.4@0.7 corner: 1.0@1.0). size _ 200@168. topView minimumSize: size; maximumSize: size. topView controller open.! ! !DocumentView class methodsFor: 'instance dSubView: aNodeView1. topView addSubView: aNodeView2 toRightOf: aNodeView1. s _ aNode1 graph contextName. r _ aNode1 name. r = nil ifTrue: [s _ s, ': Node Browser'] ifFalse: [s _ s, ': ', r]. s1 _ s, ' - Differences'. t _ Time fromUnixSeconds: aNode1 timeStamp. s1 _ s1, ' (', ((t at: 1) printFormat: #(1 2 3 32 2 2)). s1 _ s1, ' ', ((t at: 2) printString), ') vs ('. t _ Time fromUnixSeconds: aNode2 timeStamp. s1 _ s1, ((t at: 1) printFormat: #(1 2 3 32 2 2)). s1 _ s1, ' ', ((t at: 2) printStricreation'! openOn: aDocument | topView aBrowser topY middleY | topY _ 0.10. "change these to re-proportion document browser" middleY _ 0.25. (topView _ self model: aDocument label: (aDocument makeLabel) minimumSize: 400@250) addPredicateViewsIn: (0@0 extent: 1.0@topY) view: topView; addListView: (0@topY extent: 0.25@middleY) on: aDocument readOnly: false index: 1; addListView: (0.25@topY extent: 0.25@middleY) on: aDocument readOnly: false index: 2; addListView: (0.5@topY extent: 0.25@middleY)ng), ')'. topView label: s1. topView minimumSize: 400 @ 150. topView controller open! ! !LinkEntry class methodsFor: 'instance creation'! atTime: aTime from: node1 to: node2 "Create a new instance of a linkEntry." | k | k _ self new. k initializeFrom: node1 to: node2. k time: aTime. ^k! ! !NodeChangeSet class methodsFor: 'instance creation'! from: aByteArray text: aText ^self new extractDiff: aByteArray text: aText! ! !Node class methodsFor: 'creating nodes'! createIn: aHyperGraph "adds a n on: aDocument readOnly: false index: 3; addListView: (0.75@topY extent: 0.25@middleY) on: aDocument readOnly: false index: 4; addNodeView: (0@(topY + middleY) extent: 1.0@1.0) on: aDocument initialSelection: nil. topView controller open! ! !NodeDiffView class methodsFor: 'instance creation'! openOn: aNodeDiff with: aNode1 and: aNode2 "opens a browser for viewing and modifying aNode" | aNodeView1 aNodeView2 topView r s n s1 t | aNodeView1 _NodeView new. aNodeView1 controller: (NodeDiffControllerew node to the hypertext graph" | n | n _ Smalltalk at: (Symbol intern: (aHyperGraph nodeStyle objectName)) ifAbsent: [^nil]. ^(n createNodeIn: aHyperGraph)! createNodeIn: aHyperGraph "adds a new node to the hypertext graph" | r p objectName rpc | p _ aHyperGraph nodeStyle. objectName _ p objectName. (rpc _ aHyperGraph rpc) isNil ifTrue: [^nil]. r _ rpc addNode: (p isArchive) type: (p type) mask: (p protectionMask). r isNil ifTrue: [rpc reportError: 'addNode'. ^nil]. p _ self new. p gr new). aNodeView1 model: aNode1. aNode1 controller: (aNodeView1 controller). aNodeDiff mergeDiffOf: 1. aNodeView1 borderWidth: 1. aNodeView2 _NodeView new. aNodeView2 controller: (NodeDiffController new). aNodeView2 model: aNode2. aNode2 controller: (aNodeView2 controller). aNodeDiff mergeDiffOf: 2. aNodeView2 borderWidth: 1. aNodeDiff buildLineMaps. aNode1 mergeLinkAttachments. aNode2 mergeLinkAttachments. topView _ self new. topView borderWidth: 1. topView model: aNodeDiff. topView adaph: aHyperGraph. p context: aHyperGraph currentContext. p isHistory: false. p nodeIndex: (r at: 1). p numLinks: 0. p links: nil. p contents: String new. p timeStamp: (r at: 2). r _ rpc setNodeAttributeValue: (p nodeIndex) for: (aHyperGraph objectIndex) as: true with: objectName with: 0. r isNil ifTrue: [rpc reportErrorAborting: 'setNodeAttributeValue'. ^nil]. ^p! ! !Node class methodsFor: 'opening nodes'! open: anInteger in: aHyperGraph "accesses current version an existing node, anInteger, from the hypertext graph" ^self open: anInteger versionTime: 0 in: aHyperGraph withSelectedLink: nil! open: anInteger versionTime: t in: aHyperGraph "accesses version t of an existing node, anInteger, from the hypertext graph" ^self open: anInteger versionTime: t in: aHyperGraph withSelectedLink: nil! open: anInteger1 versionTime: anInteger2 in: aHyperGraph withSelectedLink: linkIndex "accesses a specific version of an existing node, anInteger1, from the hypertext graph" | r p ai | p _ self geNil ifTrue: [Transcript cr; show: 'Do not know about node class: '; show: n. ^nil]. p _ c new. ((r at: 4) at: 1) == true ifTrue: [p name: ((r at: 4) at: 2)]. p graph: aHyperGraph. p context: aHyperGraph currentContext. p isHistory: (anInteger2 ~= 0). p nodeIndex: anInteger1. p timeStamp: (r at: 1). p numLinks: (r at: 2). p links: (r at: 3). p contents: (r at: 5). ^p! ! !HyperPipeStream class methodsFor: 'instance creation'! readOn: aFileDesc ^(self new) openReadOnly: aFileDesc! writet: anInteger1 versionTime: anInteger2 in: aHyperGraph. p isNil ifTrue: [^nil]. p viewerClass openOn: p withSelectedLink: linkIndex. "we don't expect to return, if so error" ^nil! open: anInteger1 versionTime: anInteger2 in: aHyperGraph withSelectedText: selText "accesses a specific version of an existing node, anInteger1, from the hypertext graph" | r p ai | p _ self get: anInteger1 versionTime: anInteger2 in: aHyperGraph. p isNil ifTrue: [^nil]. p viewerClass openOn: p withSelectedText: selText. On: aFileDesc ^(self new) openWriteOnly: aFileDesc! ! !Time class methodsFor: 'instance creation'! fromUnixSeconds: unixSeconds "Answer an array of (Date today, Time now) initialized from the second count returned by a Unix time system call. Correct for time zone and daylight savings time." | secondCount timeZoneAdjustment | secondCount _ unixSeconds truncated + 2177452800. "add in the total seconds from Jan 01, 1901 (the start of Smalltalk time) up to Jan 01, 1970 (the start of Unix time)." "S "we don't expect to return, if so error" ^nil! ! !Node class methodsFor: 'instance creation'! dummyIn: aHyperGraph | p | "creates an empty node" p _ self new. p graph: aHyperGraph. p context: aHyperGraph currentContext. p isHistory: false. p nodeIndex: nil. p timeStamp: nil. p numLinks: nil. p links: nil. p contents: (Text new). ^p! get: anInteger1 versionTime: anInteger2 in: aHyperGraph "accesses a specific version of an existing node, anInteger1, from the hypertext graph" | r p ai n c ubtract 8 hours for Pacific time." timeZoneAdjustment _ -8. "timeZoneAdjustment is an adjustment from GMT" secondCount _ secondCount + (3600 * timeZoneAdjustment). ^self correctedFrom: secondCount formatted: #dateAndTime! ! !Time class methodsFor: 'private'! correctedFrom: secondCount formatted: formatted "If formatted is #seconds, answer with the total seconds from Jan 1, 1901 corrected for daylight savings. Otherwise, answer an array of (Date today, Time now). Constants are defined for DST inrpc | ai _ Array new: 2. ai at: 1 put: (aHyperGraph iconNameIndex). ai at: 2 put: (aHyperGraph objectIndex). (rpc _ aHyperGraph rpc) isNil ifTrue: [^nil]. r _ rpc openNode: anInteger1 versionTime: anInteger2 numNodeAttributes: 2 nodeAttributeIndices: ai numLinkAttributes: 1 linkAttributeIndices: ai. r = nil ifTrue: [rpc reportError: 'openNode'. ^nil]. n _ ((r at: 4) at: 3) == true ifTrue: [((r at: 4) at: 4)] ifFalse: ['TextNode']. c _ Smalltalk at: (Symbol intern: n) ifAbsent: [^nil]. c is the United States as follows: firstDayDST is the day of a non-leap year on or before which DST begins or 0 if DST not used. lastDayDST is the day of a non-leap year on or before which DST ends." | theDate theTime dfirst dlast firstDayDST lastDayDST day | firstDayDST _ 120. "the last possible day for DST to start: Apr 30 of a non-leap year" lastDayDST _ 304. "the last possible day for DST to end: Oct 31 of a non-leap year" "Guess the number of days since Jan 1 1901." theDate _ Date fromDays: secondCount // 86400. "secondCount \\ 86400 is the number of seconds that were left over from the estimate of days" formatted == #seconds ifFalse: [theTime _ Time fromSeconds: secondCount \\ 86400]. "Check for daylight savings time (DST). Correct DST parameters for leap years and adjust to previous Sunday if necessary" firstDayDST = 0 ifTrue: ["DST not used" formatted == #seconds ifTrue: [^secondCount] ifFalse: [^Array with: theDate with: theTime]]. "Calculate the day of the year or buffer: aStringOrByteArray nbytes: byteCount. sysCall invoke ifTrue: [ "Successful" (sysCall D0Out > byteCount) ifTrue: [self error: 'Write call returns incorrects number of bytes '] ifFalse: [^sysCall D0Out]] ifFalse: [(sysCall isInterrupted) ifTrue: [^self write: fileDescriptor from: aStringOrByteArray size: byteCount ] ifFalse: [sysCall issueError]]! ! !Attribute class methodsFor: 'instance creation'! openOnContext: anInteger1 versionTime: anInteger2 in: aGraph that DST actually begins, the last Sunday in April." dfirst _ ((Date newDay: (firstDayDST + theDate leap) year: theDate year) previous: #Sunday) day. "Calculate the day of the year that DST actually ends, the last Sunday in October." dlast _ ((Date newDay: (lastDayDST + theDate leap) year: theDate year) previous: #Sunday) day. day _ theDate day. ((day > dfirst and: [day < dlast]) or: [(day = dfirst and: [theTime hours > 1]) or: [day = dlast and: [theTime hours < 1]]]) ifTrue: "Daylight saving "opens the attribute/value pairs for version anInteger2 of context anInteger1" self new browseContextAttributes: anInteger1 versionTime: anInteger2 in: aGraph! openOnLink: anInteger1 versionTime: anInteger2 in: aGraph "opens the attribute/value pairs for version anInteger2 of link anInteger1" self new browseLinkAttributes: anInteger1 versionTime: anInteger2 in: aGraph! openOnNode: anInteger1 versionTime: anInteger2 in: aGraph "opens the attribute/value pairs for version anInteger2 of node anInteger1"s time in effect. Add an hour." [formatted==#seconds ifTrue: [^secondCount + 3600] ifFalse: [theTime hours = 23 ifTrue: [theDate _ theDate addDays: 1. theTime hours: 0] ifFalse: [theTime hours: theTime hours + 1]]]. formatted==#seconds ifTrue: [^secondCount] ifFalse: [^Array with: theDate with: theTime]! ! !NodeStyle class methodsFor: 'class initialization'! initialize YellowButtonMenu _ ActionMenu labels: 'again undo copy cut paste accept cancel' lines: self new browseNodeAttributes: anInteger1 versionTime: anInteger2 in: aGraph! ! !Attribute class methodsFor: 'class initialization'! initialize TextMenu _ ActionMenu labels: 'again\undo\copy\cut\paste\accept\cancel' withCRs lines: #(2 5) selectors: #(again undo copySelection cut paste accept cancel). ListMenu _ ActionMenu labels: 'add attribute\create attribute\delete attribute\show system attributes\hide system attributes\update' withCRs lines: #(3 5) selectors: #(addAttribute creat #(2 5) selectors: #(again undo copySelection cut paste accept cancel). DefaultObjectName _ 'TextNode'. "NodeStyle initialize"! ! !NodeStyle class methodsFor: 'instance creation'! new | ns | ns _ super new. ns initialize. ^ns! ! !TekSystemCall class methodsFor: 'portable operations'! write: fileDescriptor from: aStringOrByteArray size: byteCount "Write byteCount bytes of data from aStringOrByteArray to the file referred to by fileDescriptor." | sysCall | sysCall _ self write: fileDescripteAttribute deleteAttribute showSystemAttributes hideSystemAttributes update). "Attribute initialize"! ! !HyperGraph class methodsFor: 'instance creation'! create: aString "creates a new hypertext graph, polling the user for info and creates a project record in the unix file aString." | g r aGraphStyle m rpc | g _ self new initialize. aGraphStyle _ g graphStyle. aGraphStyle defineGraphParams ifFalse: [^nil]. g nodeStyle protectionMask: (aGraphStyle protectionMask). (rpc _ g rpc) isNil ifTrue: [^nil]. r _ rpc setHostMachine: (aGraphStyle hostMachineName). r isNil ifTrue: [rpc reportError: 'setHostMachine'. ^nil]. r _ rpc createGraphIn: (aGraphStyle hostDirectory) mask: (aGraphStyle protectionMask). r isNil ifTrue: [rpc reportError: 'createGraph'. ^nil]. g hostMachineId: (r at: 1). g creationTime: (r at: 2). g writeFirstTimeTo: aString. g setAttributeIndices. rpc setContextAttributeValue: 1 for: g iconNameIndex as: true with: aString with: 0. g projectFileName: aString. ^g! destroy: arride paragraph editor to allow double-clicking selection of link icons." | openDelimiter closeDelimiter direction match level leftDelimiters rightDelimiters string here hereChar start stop | string _ text string. here _ stringIndex. (here between: 2 and: string size) ifFalse: ["if at beginning or end, select entire string" ^ 1 to: string size + 1]. leftDelimiters _ '([{<''" '. rightDelimiters _ ')]}>''" '. openDelimiter _ string at: here - 1. match _ leftDelimiters indexOf: openDelimiter. String "destroys an existing hypertext graph using info in unix file aString" | g r aGraphStyle rpc | (BinaryChoice message: 'Do you really want to destroy this graph?') ifFalse: [^nil]. g _ self new initialize. aGraphStyle _ g graphStyle. g readFrom: aString. (rpc _ g rpc) isNil ifTrue: [^nil]. r _ rpc setHostMachine: (aGraphStyle hostMachineName). r isNil ifTrue: [rpc reportError: 'setHostMachine'. ^nil]. r _ rpc destroyGraphPath: (aGraphStyle hostDirectory) pid1: (g hostMachineId) pid2: match > 0 ifTrue: ["delimiter is on left -- match to the right" start _ here. direction _ 1. here _ here - 1. closeDelimiter _ rightDelimiters at: match] ifFalse: [openDelimiter _ string at: here. match _ rightDelimiters indexOf: openDelimiter. match > 0 ifTrue: ["delimiter is on right -- match to the left" stop _ here - 1. direction _ -1. closeDelimiter _ leftDelimiters at: match] ifFalse: ["no delimiters -- select a token" direction _ -1]]. (g creationTime). r isNil ifTrue: [rpc reportError: 'destroyGraph'. ^nil]. TekSystemCall remove: aString. ^nil! open: aString "opens an existing hypertext graph using info in unix file aString" | g r aGraphStyle proceed rpc | g _ self new initialize. aGraphStyle _ g graphStyle. g readFrom: aString. (rpc _ g rpc) isNil ifTrue: [^nil]. r _ rpc setHostMachine: (aGraphStyle hostMachineName). r isNil ifTrue: [rpc reportError: 'setHostMachine'. ^nil]. r _ rpc openGraphPath: (aGraphStyle hostDirectorlevel _ 1. "begin code to allow double clicking selection of link icon" ((match = 0) & ((text emphasisAt: here) > 24)) ifTrue: [level _ 0. direction _ 1. start _ here + 1] ifFalse: [(((here - 1) >= 1) & ((string at: here) tokenish not)) ifTrue: [((text emphasisAt: (here - 1)) > 24) ifTrue: [level _ 0. direction _ 1. start _ here - 1]]]. "end code to allow double clicking selection of link icon" [level > 0 and: [direction > 0 ifTrue: [here < string size] ifFalse: [here > 1]]] whily) pid1: (g hostMachineId) pid2: (g creationTime). r isNil ifTrue: [rpc incompleteTransactionError ifTrue: [self notify: (rpc errorMessage), ' Proceed to recover.'. rpc recoverFromCrash ifFalse: [ rpc reportError: 'recoverFromCrash'. ^nil]] ifFalse: [rpc reportError: 'openGraph'. ^nil]]. g setAttributeIndices. g projectFileName: aString. ^g! ! !Paragraph methodsFor: 'selecting'! selectWord: stringIndex "Select delimited text or word--the result of double-clicking. OveeTrue: [hereChar _ string at: (here _ here + direction). match = 0 ifTrue: ["token scan goes left, then right" hereChar tokenish ifTrue: [here = 1 ifTrue: [start _ 1. "go right if hit string start" direction _ 1]] ifFalse: [direction < 0 ifTrue: [start _ here + 1. "go right if hit non-token" direction _ 1] ifFalse: [level _ 0]]] ifFalse: ["bracket match just counts nesting level" hereChar = closeDelimiter ifTrue: [level _ level - 1"leaving nest"] ifFalse: [hereChar = openDelimiter ifTrue: [level _ level + 1"entering deeper nest"]]]]. level > 0 ifTrue: ["in case ran off string end" here _ here + direction]. direction > 0 ifTrue: [^ start to: here] ifFalse: [^ here + 1 to: stop + 1]! ! !Arrow methodsFor: 'private'! headAtAngle: theta length: len "Returns the coordinates of the end of a barb of angle theta for the receiver, an Arrow." | t m0 x0 y0 x1 y1 d xnew ynee: (0-theta) length: d. "super displayOn: Display at: 0@0 clippingBox: clipRect rule: anInteger mask: aForm." f _ super form. (Line from: tip to: end1 withForm: f) displayOn: Display at: 0@0 clippingBox: clipRect rule: anInteger mask: aForm. (Line from: tip to: end2 withForm: f) displayOn: Display at: 0@0 clippingBox: clipRect rule: anInteger mask: aForm.! displayAngledAt: theta length: d on: aForm "Display an arrow with points of length d at an angle theta on form aForm." | tip end1 end2 f| tw bnew mnew a b c r m tantheta xt1 yt1 xt2 yt2 d1 d2 | x0 _ (self endPoint) x. y0 _ (self endPoint) y. x1 _ (self beginPoint) x. y1 _ (self beginPoint) y. tantheta _ (theta*0.0174533) tan. x0 = x1 ifTrue: [ d _ 1. mnew _ 1/tantheta.] ifFalse: [ m0 _ (y1 - y0) / (x1 - x0). d _ 1 - (m0*tantheta). mnew _ (tantheta + m0)/d]. (d abs) < 0.01 ifFalse: [ bnew _ y0 - (mnew*x0). a _ 1 + (mnew squared). b _ 2*((mnew*(bnew-y0)) - x0). c _ (x0 squared) + ((bnew-y0) squared) - (len squared).ip _ self endPoint. end1 _ self headAtAngle: theta length: d. end2 _ self headAtAngle: (0-theta) length: d. "super displayOn: aForm." f _ super form. (Line from: tip to: end1 withForm: f) displayOn: aForm. (Line from: tip to: end2 withForm: f) displayOn: aForm.! ! !OpaqueForm methodsFor: 'displaying'! copyBits: copyRect from: sourceForm at: destPoint clippingBox: clipRect rule: rule mask: mask | sourceFigure sourceShape | (sourceForm isKindOf: OpaqueForm) ifTrue: [sourceFigure _ sourceForm fig r _ (b squared - (4*a*c)) abs sqrt. xt1 _ (r - b)/(2*a). yt1 _ mnew*xt1+ bnew. xt2 _ (0 - r - b)/(2*a). yt2 _ mnew*xt2+ bnew. ] ifTrue: [ xt1 _ x0. yt1 _ y0 + len. xt2 _ x0. yt2 _ y0 - len. ]. d1 _ (xt1 - x1) squared + (yt1 - y1) squared. d2 _ (xt2 - x1) squared + (yt2 - y1) squared. d1 > d2 ifTrue: [^xt2@yt2] ifFalse: [^xt1@yt1]! ! !Arrow methodsFor: 'displaying'! displayAngledAt: theta length: d "Display an arrow with points of length d at an angle theta." | tip end1 end2 f|ure. sourceShape _ sourceForm shape] ifFalse: [sourceFigure _ sourceShape _ sourceForm]. figure copyBits: copyRect from: sourceFigure at: destPoint clippingBox: clipRect rule: rule mask: mask. shape copyBits: copyRect from: sourceShape at: destPoint clippingBox: clipRect rule: rule mask: mask! ! !Graph methodsFor: 'private'! getPositionOf: nodeIndex atVersionTime: aTime "Gets the x-y position attributes for node nodeIndex, and returns it's coordinate position, if the attribute tip _ self endPoint. end1 _ self headAtAngle: theta length: d. end2 _ self headAtAngle: (0-theta) length: d. "super displayOn: Display." f _ super form. (Line from: tip to: end1 withForm: f) display. (Line from: tip to: end2 withForm: f) display.! displayAngledAt: theta length: d clippingBox: clipRect rule: anInteger mask: aForm "Display an arrow with points of length d at an angle theta." | tip end1 end2 f| tip _ self endPoint. end1 _ self headAtAngle: theta length: d. end2 _ self headAtAngls are not found then nil is returned." | r x y rpc | (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc getNodeAttributeValue: nodeIndex for: hyperGraph xPosNameIndex at: aTime. r isNil ifTrue: [^nil]. x _ (r at: 2) asNumber. r _ rpc getNodeAttributeValue: nodeIndex for: hyperGraph yPosNameIndex at: aTime. r isNil ifTrue: [rpc reportError: 'getNodeAttributeValue'. ^nil]. y _ (r at: 2) asNumber. ^x@y! initialize "Initialize instance variables." nodes _ Dictionary new: 100. "of NodeEntry's" nodePositions _ Dictionary new: 100. "of node positions" root _ nil. nextNodeOrdinal _ 1. ySortedNodes _ SortedCollection new: 100; sortBlock: [:a :b | (a value y) < (b value y)]. "A sortedCollection of associations with key a node index and value a Point; the collection is sorted by y-coordinates." xSortedNodes _ SortedCollection new: 100; sortBlock: [:a :b | (a value x) < (b value x)]. "A sortedCollection of associations with key a node index and value a Point; the collection is sorted byNil ifTrue: [^false]. r _ rpc setNodeAttributeValue: nodeIndex for: hyperGraph yPosNameIndex as: false with: '' with: (aPoint y rounded). r isNil ifTrue: [^false]. ^true! ! !Graph methodsFor: 'accessing'! context ^context! context: aContextIndex context _ aContextIndex! forms "Returns a dictionary with keys, node indices, and values, instances of class Form for display." | icons | icons _ Dictionary new. nodes associationsDo: [:a | icons at: (a key) put: (a value icon)]. ^icons! hyperGraph ^ x-coordinates." links _ Dictionary new: 100. "of LinkEntry's" positionsHaveChanged _ false. maxFormHeight _ 17. maxFormWidth _ 1.! makeLabel | t aLabel | aLabel _ hyperGraph contextName. isHistory ifTrue: [t _ Time fromUnixSeconds: versionTime. aLabel _ aLabel, ': Graph Browser (', ((t at: 1) printFormat: #(1 2 3 32 2 2)). aLabel _ aLabel, ' ', ((t at: 2) printString), ')'] ifFalse: [aLabel _ aLabel, ': Graph Browser']. ^aLabel! makeMiniIcon: aString | t p r f | t _ ThyperGraph! hyperGraph: aHyperGraph hyperGraph _ aHyperGraph! isHistory ^isHistory! isHistory: aBoolean isHistory _ aBoolean! linksDictionary ^links! maxFormHeight ^maxFormHeight! maxFormWidth ^maxFormWidth! nodePositions "Return a dictionary with key a node index and value aPoint." ^nodePositions! nodes ^nodes! nodeVersion: aNode "Returns the versionTime of aNode." ^(nodes at: aNode) time! positionsHaveChanged ^positionsHaveChanged! positionsHaveChanged: aBoolean positionsHaveChanged _ext string: aString emphasis: 9. p _ Paragraph withText: t style: MiniStyle. r _ (p compositionRectangle). f _ Form extent: (r extent x + 5) @ (r extent y - 3). f copyBits: p compositionRectangle from: p asForm at: 3@-2 clippingBox: f boundingBox rule: Form over mask: Form black. f borderWidth: 2. maxFormWidth _ maxFormWidth max: f computeBoundingBox width. ^f! setIconAttribute: aString forNode: nodeIndex "Set the icon name attributes, given by aString, for node nodeIndex. aBoolean! root ^root! root: aNodeIndex root _ aNodeIndex! versionTime ^versionTime! versionTime: time versionTime _ time.! xSortedNodePositions "Returns an sortedCollection of associations with key a node index and value aPoint; the collection is sorted by x-coordinates." ^xSortedNodes! ySortedNodePositions "Returns an sortedCollection of associations with key a node index and value aPoint; the collection is sorted by y-coordinates." ^ySortedNodes! ! !Graph methodsFor: 'positioning'! autoPos" | r s rpc | (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc setNodeAttributeValue: nodeIndex for: hyperGraph iconNameIndex as: true with: aString with: 0. ^(r notNil)! setPositionAttributes: aPoint forNode: nodeIndex "Set the x-y position attributes, given by aPoint, for node nodeIndex." | r s rpc | (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc setNodeAttributeValue: nodeIndex for: hyperGraph xPosNameIndex as: false with: '' with: (aPoint x rounded). r isition "Position all the nodes in the receiver" | count width dx dy n c orderedNodes| nodes size = 0 ifTrue: [^nil]. nodes associationsDo: [:a | (a value) removeMark]. self positionsHaveChanged: true. root = nil ifFalse: [ (nodes at: root) setMark. maxDepth _ 1. depth _ 0. orderedNodes _ SortedCollection sortBlock: [:x :y | (x value ordinal) < (y value ordinal)]. c _ OrderedCollection new: (nodes size). nodes associationsDo: [:a | c addLast: a]. orderedNodes addAll: c. self totalWidth: root. nodes associationsDo: [:a | (a value) removeMark]. (nodes at: root) setMark. dx _ 1000/(maxDepth). dy _ 1000/(1 + (nodes at: root) width). self breadthFirstPosition: orderedNodes sonsOf: root at: (20@dy) deltax: dx deltay: dy]. "Nodes still unmarked are not connected in the graph. Count them and then place them evenly spaced across the top of view." count _ 0. nodes associationsDo: [:a | (a value isMarked) ifFalse: [count _ count + 1]]. count ~= 0 ifTrue: [ width _ 1000 / (count + 1dNodes add: (Association key: (a key) value: (a value location))].! totalWidth: aNode "Returns the number of decendants of aNode. Sets the width field of aNode to the number." | unMarkedSons count m | count _ 1. depth _ depth + 1. depth > maxDepth ifTrue: [maxDepth _ depth]. unMarkedSons _ ((nodes at: aNode) toNodes) select: [:n | ((nodes at: n) isMarked) not]. unMarkedSons do: [:n | (nodes at: n) setMark]. unMarkedSons do: [:n | count _ count + (self totalWidth: n)]. (nodes at: aNode) width: co). count _ 1. nodes associationsDo: [:a | n _ a value. (n isMarked) ifFalse: [n location: (count * width) @ 0. count _ count + 1]]]. self resortNodes.! breadthFirstPosition: orderedNodes sonsOf: aNode at: aPoint deltax: dx deltay: dy "Position aNode and recursively its sons." | unMarkedSons x y w n p | w _ (nodes at: aNode) width. x _ aPoint x. y _ aPoint y. p _ x@(y + (dy*w/2)). (nodes at: aNode) location: p. nodePositions at: aNode put: p. unMarkedSons _ ((nodes at: aNode) toNodes) selunt. depth _ depth - 1. ^count! ! !Graph methodsFor: 'adding'! addLink: aLink version: aTime from: fromNode atTime: t1 to: toNode atTime: t2 "add a link to the receiver" | entry oldMaxLink fromNodeEntry toNodeEntry l| fromNodeEntry _ nodes at: fromNode ifAbsent: [^nil]. fromNodeEntry ~= nil ifTrue: [ toNodeEntry _ nodes at: toNode ifAbsent: [^nil]. toNodeEntry ~= nil ifTrue: [ fromNodeEntry addToNode: toNode. entry _ LinkEntry atTime: aTime from: fromNode atTime: t1 to: toNode atTime: t2. ect: [:n | ((nodes at: n) isMarked) not]. unMarkedSons do: [:n | (nodes at: n) setMark]. x _ x + dx. orderedNodes do: [:a | n _ a key. (unMarkedSons includes: n) ifTrue: [ self breadthFirstPosition: orderedNodes sonsOf: n at: x@y deltax: dx deltay: dy. y _ y + ((a value width) * dy)]]! repositionNode: aNode at: aPoint "Reposition aNode." (nodes at: aNode) location: aPoint. positionsHaveChanged _ true. xSortedNodes removeAllSuchThat: [:a | (a key) = aNode]. xSortedNodes add: (Association ke links at: aLink put: entry]]. ^entry! addLink: aLink version: aTime from: fromNode to: toNode "add a link to the receiver" | entry oldMaxLink fromNodeEntry toNodeEntry l| fromNodeEntry _ nodes at: fromNode ifAbsent: [^nil]. fromNodeEntry ~= nil ifTrue: [ toNodeEntry _ nodes at: toNode ifAbsent: [^nil]. toNodeEntry ~= nil ifTrue: [ fromNodeEntry addToNode: toNode. entry _ LinkEntry atTime: aTime from: fromNode to: toNode. links at: aLink put: entry]]. ^entry! addNode: aNode version: aVy: aNode value: ((nodes at: aNode) location)). ySortedNodes removeAllSuchThat: [:a | (a key) = aNode]. ySortedNodes add: (Association key: aNode value: ((nodes at: aNode) location)). nodePositions at: aNode put: aPoint.! resortNodes "Recalculate xSortedNodes and ySortedNodes." xSortedNodes removeAllSuchThat: [:a | true]. nodes associationsDo: [:a | xSortedNodes add: (Association key: (a key) value: (a value location))]. ySortedNodes removeAllSuchThat: [:a | true]. nodes associationsDo: [:a | ySorteersion withIcon: aString withPosition: aPoint "add a node to the receiver" | f p s r pos entry oldMaxNode t a | ((aString isNil) or: [aString size = 0]) ifTrue: [ s _ aNode printStringRadix: 10] ifFalse: [ s_ aString]. f _ iconCache at: s ifAbsent: [ f _ self makeMiniIcon: s. iconCache at: s put: f]. aPoint = nil ifTrue: [pos _ (aNode*10)@100] ifFalse: [pos _ aPoint]. entry _ NodeEntry atTime: aVersion atPosition: pos withIcon: f number: nextNodeOrdinal. nextNodeOrdinal _ nextNodeOrdinal + 1. nodes at: aNode put: entry. nodePositions at: aNode put: pos. a _ Association key: aNode value: entry location. xSortedNodes add: a. ySortedNodes add: a.! ! !Graph methodsFor: 'display acccess'! boundingBox ^(Rectangle origin: 0@0 extent: 1000@1000)! ! !Graph methodsFor: 'writing'! fileOutGraphNodes: aPredString1 links: aPredString2 toFile: aFileName depth: anInteger | rpc | root isNil ifTrue: [^nil]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. ^(HyperIO using: rpc) fil: [p _ ((n at: 3) at: 2) @ ((n at: 3) at: 4)]. self addNode: (n at: 1) version: (n at: 2) withIcon: ((n at: 3) at: 6) withPosition: p. ]. u _ (r at:2) size. 1 to: u do: [:i | n _ ((r at: 2) at: i). self addLink: (n at: 1) version: (n at: 2) from: (n at: 3) to: (n at: 4). ]. "if searchRoot is among the returned nodes, keep it as root" (nodes associationAt: searchRoot ifAbsent: [nil]) notNil ifTrue: [root _ searchRoot].! ! !Graph methodsFor: 'removing'! deleteLink: aLink "Remove aLink from theeOutGraphNodes: aPredString1 links: aPredString2 toFile: aFileName at: root for: versionTime depth: anInteger! printOutGraphNodes: aPredString1 links: aPredString2 toFile: aFileName depth: anInteger | rpc | root isNil ifTrue: [^nil]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. ^(HyperIO using: rpc) printOutGraphNodes: aPredString1 links: aPredString2 toFile: aFileName at: root for: versionTime depth: anInteger! ! !Graph methodsFor: 'reading'! readGraph: string1 linkPredicate: str receiver." | linkEntry | linkEntry _ links at: aLink. (nodes at: linkEntry fromNode) removeToNode: (linkEntry toNode). links removeKey: aLink.! deleteNode: aNode "Remove aNode from the receiver and all its to links" links associations do: [:a | ((a value toNode) = aNode) | ((a value fromNode) = aNode) ifTrue: [self deleteLink: (a key)]]. xSortedNodes removeAllSuchThat: [:a | (a key) = aNode]. ySortedNodes removeAllSuchThat: [:a | (a key) = aNode]. nodes removeKey: aNode. nodePositions ing2 linearly: aBoolean depth: anInteger "Makes the receiver a 'view' with nodes satisfying string1 and links satisfying string2" | r u n ai p searchRoot rpc | searchRoot _ root. self initialize. "Start afresh" iconCache = nil ifTrue: [iconCache _ Dictionary new: 100]. ai _ Array new: 3. ai at: 1 put: (hyperGraph xPosNameIndex). ai at: 2 put: (hyperGraph yPosNameIndex). ai at: 3 put: (hyperGraph iconNameIndex). (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. aBoolean ifTrue: [ r _removeKey: aNode.! ! !Graph methodsFor: 'searching'! search | searchString n a b r m rpc | searchString _ hyperGraph searchStyle searchString. n _ nodes associations. a _ Array new: (n size). 1 to: (n size) do: [:i | b _ Array new: 4. a at: i put: b. m _ n at: i. b at: 1 put: (m key). b at: 2 put: (m value time). b at: 3 put: (b at: 2). b at: 4 put: 0]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc searchContents: (n size) nodeList: a nodeAttributes: (Array wi rpc linearizeGraph: searchRoot at: versionTime depth: anInteger nodePredicate: string1 linkPredicate: string2 nodeAttributes: ai linkAttributes: nil. r isNil ifTrue: [^nil]] ifFalse:[ r _ rpc getGraphViaAttributes: versionTime nodePredicate: string1 linkPredicate: string2 nodeAttributes: ai linkAttributes: nil. r isNil ifTrue: [^nil]]. u _ (r at:1) size. 1 to: u do: [:i | n _ (r at: 1) at: i. ((((n at: 3) at: 1) ~= false) | (((n at: 3) at: 3) ~= false)) ifTrue: [p _ nil] ifFalseth: (hyperGraph iconNameIndex)) code: 0. r isNil ifTrue: [rpc reportError: 'searchContents'. Cursor normal show. ^nil]. SearchResults openOn: r in: hyperGraph! ! !Graph methodsFor: 'merging'! compactGraph | t rpc n r entirely | t _ hyperGraph targetContext. t isNil ifTrue: [Transcript cr; show: 'No target context defined'. ^false]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^true]. entirely _ BinaryChoice message: 'Do you want to discard all history?'. rpc beginTransaction: true. nodes keys do: [:each | r _ rpc compactNode: n entirely: entirely. r isNil ifTrue: [rpc reportErrorAborting: 'compactNode'.^false]]. rpc commitTransaction. ^true! compactNode: aNodeIndex | t rpc r entirely | t _ hyperGraph targetContext. t isNil ifTrue: [Transcript cr; show: 'No target context defined'. ^false]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^true]. entirely _ BinaryChoice message: 'Do you want to discard all history?'. r _ rpc compactNode: aNodeIndex entirely: entirely. r isNi t rpc r | t _ hyperGraph targetContext. t isNil ifTrue: [Transcript cr; show: 'No target context defined'. ^false]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^true]. r _ rpc mergeContextFrom: context to: t numNodes: 1 nodeList: (Array with: (Array with: aNodeIndex with: versionTime)). r isNil ifTrue: [rpc reportError: 'mergeContext'. ^false]. ^true! ! !ContextTree methodsFor: 'reading'! readGraph: string linearly: aBoolean depth: anInteger "Makes the receiver a 'view' with contexts satl ifTrue: [rpc reportError: 'compactNode'. ^false]. ^true! compareGraph | t rpc n r | t _ hyperGraph targetContext. t isNil ifTrue: [Transcript cr; show: 'No target context defined'. ^false]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^true]. n _ OrderedCollection new: nodes size. nodes keys do: [:each | n add: (Array with: each with: versionTime)]. r _ rpc checkForConflictsFrom: context to: t numNodes: (n size) nodeList: n. r isNil ifTrue: [rpc reportError: 'checkForConflictsFrom'. ^falsisfying string" | r u n ai p searchRoot rpc | searchRoot _ root. self initialize. "Start afresh" iconCache = nil ifTrue: [iconCache _ Dictionary new: 100]. ai _ Array new: 3. ai at: 1 put: (hyperGraph xPosNameIndex). ai at: 2 put: (hyperGraph yPosNameIndex). ai at: 3 put: (hyperGraph iconNameIndex). (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^nil]. aBoolean ifTrue: [^nil] ifFalse:[ r _ rpc getContextsViaAttributes: versionTime predicate: string attributes: ai. r isNil ifTre]. Transcript cr; show: 'Sorry, not finished this command yet!!'. ^true! compareNode: aNodeIndex | t rpc r | t _ hyperGraph targetContext. t isNil ifTrue: [Transcript cr; show: 'No target context defined'. ^false]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^true]. r _ rpc checkForConflictsFrom: context to: t numNodes: 1 nodeList: (Array with: (Array with: aNodeIndex with: versionTime)). r isNil ifTrue: [rpc reportError: 'checkForConflictsFrom:'. ^false]. Transcript cr; show: 'Sorry, noue: [^nil]]. u _ (r at:1) size. 1 to: u do: [:i | n _ (r at: 1) at: i. ((((n at: 2) at: 2) = nil) | (((n at: 2) at: 4) = nil)) ifTrue: [p _ nil] ifFalse: [p _ ((n at: 2) at: 2) @ ((n at: 2) at: 4)]. self addNode: (n at: 1) version: versionTime withIcon: ((n at: 2) at: 6) withPosition: p. ]. u _ (r at:2) size. 1 to: u do: [:i | n _ ((r at: 2) at: i). self addLink: i version: versionTime from: (n at: 1) to: (n at: 2). ]. "if searchRoot is among the returned nodes, keep it as root" (nodt finished this command yet!!'. ^true! mergeGraph | t rpc n r | t _ hyperGraph targetContext. t isNil ifTrue: [Transcript cr; show: 'No target context defined'. ^false]. (rpc _ hyperGraph rpcFor: context) isNil ifTrue: [^true]. n _ OrderedCollection new: nodes size. nodes keys do: [:each | n add: (Array with: each with: versionTime)]. r _ rpc mergeContextFrom: context to: t numNodes: (n size) nodeList: n. r isNil ifTrue: [rpc reportError: 'mergeContext'. ^false]. ^true! mergeNode: aNodeIndex |es associationAt: searchRoot ifAbsent: [nil]) notNil ifTrue: [root _ searchRoot].! ! !ContextTree methodsFor: 'private'! makeLabel | t aLabel | isHistory ifTrue: [t _ Time fromUnixSeconds: versionTime. aLabel _ 'Context Tree Browser (', ((t at: 1) printFormat: #(1 2 3 32 2 2)). aLabel _ aLabel, ' ', ((t at: 2) printString), ')'] ifFalse: [aLabel _ 'Context Tree Browser']. ^aLabel! setIconAttribute: aString forContext: contextIndex "Set the icon name attributes, given by aString, for context contextIndex." | r s rpc | (rpc _ hyperGraph rpc) isNil ifTrue: [^nil]. r _ rpc setContextAttributeValue: contextIndex for: hyperGraph iconNameIndex as: true with: aString with: 0. ^(r notNil)! setPositionAttributes: aPoint forContext: contextIndex "Set the x-y position attributes, given by aPoint, for context contextIndex." | r s rpc | (rpc _ hyperGraph rpc) isNil ifTrue: [^nil]. r _ rpc setContextAttributeValue: contextIndex for: hyperGraph xPosNameIndex as: false with: '' wiue: nodeIndex for: attributeIndex at: versionTime "gets the value of attributeIndex for node nodeIndex at time versionTime" | r | toUnix nextPut: 54. "getNodeAttributeValue command" toUnix nextNumber: 4 put: 12. "size of command" toUnix nextNumber: 4 put: nodeIndex. "node index" toUnix nextNumber: 4 put: attributeIndex. "attribute index" toUnix nextNumber: 4 put: versionTime. "versionTime" self waitForResponse isNil ifTrue: [^nil]. r _ Array new: 2. r at: 1 put: ((fromUnix next) = 1). "isStrith: (aPoint x rounded). r isNil ifTrue: [^false]. r _ rpc setContextAttributeValue: contextIndex for: hyperGraph yPosNameIndex as: false with: '' with: (aPoint y rounded). r isNil ifTrue: [^false]. ^true! ! !HyperRPC methodsFor: 'nodeOperations'! compactNode: aNodeIndex entirely: aBoolean "compacts the version history of a node" toUnix nextPut: 52. "compactNode command" toUnix nextNumber: 4 put: 5. "size of command" toUnix nextNumber: 4 put: aNodeIndex. toUnix nextPut: (aBoolean ifTrue: [1] ifFalng" (r at: 1) ifTrue: [r at: 2 put: (self getStringArgument) "string value"] ifFalse: [r at: 2 put: (fromUnix nextNumber: 4) "integer value"]. ^r! getNodeDifferences: nodeIndex from: vt1 to: vt2 "gets the differences between two versions `vt1' & `vt2' of node `nodeIndex'" | r diffSize | toUnix nextPut: 66. "getNodeDifferences command" toUnix nextNumber: 4 put: 12. "size of command" toUnix nextNumber: 4 put: nodeIndex. "node index" toUnix nextNumber: 4 put: vt1. toUnix nextNumber: 4 put: vtse: [0]). ^self waitForResponse! deleteNode: aNodeIndex "deletes a node from the hypertext graph" toUnix nextPut: 63. "deleteNode command" toUnix nextNumber: 4 put: 4. "size of command" toUnix nextNumber: 4 put: aNodeIndex. ^self waitForResponse! deleteNodeAttribute: nodeIndex for: attributeIndex "deletes an attribute/value pair for node nodeIndex" toUnix nextPut: 62. "deleteNodeAttribute command" toUnix nextNumber: 4 put: (8). "size of command" toUnix nextNumber: 4 put: nodeIndex. "node index2. self waitForResponse isNil ifTrue: [^nil]. diffSize _ fromUnix nextNumber: 4. r _ ByteArray new: diffSize. fromUnix next: diffSize into: r. ^r! getNodeTimeStamp: aNodeIndex | r | toUnix nextPut: 52. "getNodeTimeStamp" toUnix nextNumber: 4 put: 4. "size of command" toUnix nextNumber: 4 put: aNodeIndex. self waitForResponse isNil ifTrue: [^nil]. r _ fromUnix nextNumber: 4. ^r! getNodeVersions: nodeIndex | r numMajorVersions numMinorVersions t | "gets the version times for node `nodeI" toUnix nextNumber: 4 put: attributeIndex. "attribute index" ^self waitForResponse! getNodeAttributes: anInteger1 versionTime: anInteger2 "gets the attribute/value pairs for version anInteger1 of node anInteger2" toUnix nextPut: 55. "getNodeAttributes command" toUnix nextNumber: 4 put: 8. "size of command" toUnix nextNumber: 4 put: anInteger1. "node index" toUnix nextNumber: 4 put: anInteger2. "version time" self waitForResponse isNil ifTrue: [^nil]. ^self extractAttributes! getNodeAttributeValndex'" toUnix nextPut: 61. "getNodeVersions command" toUnix nextNumber: 4 put: 4. "size of command" toUnix nextNumber: 4 put: nodeIndex. "node index" self waitForResponse isNil ifTrue: [^nil]. r _ Array new: 2. numMinorVersions _ fromUnix nextNumber: 4. r at: 2 put: (Array new: numMinorVersions). 1 to: numMinorVersions do: [:i | t _ Array new: 2. (r at: 2) at: i put: t. t at: 1 put: (fromUnix nextNumber: 4). t at: 2 put: (self getStringArgument)]. numMajorVersions _ fromUnix nextNumber: 4. r at: 1 put: (Array new: numMajorVersions). 1 to: numMajorVersions do: [:i | t _ Array new: 2. (r at: 1) at: i put: t. t at: 1 put: (fromUnix nextNumber: 4). t at: 2 put: (self getStringArgument)]. ^r! modifyNode: aNode "updates a node in the hypertext graph" | s numLinks a confirmedNumLinks | numLinks _ aNode numLinks. confirmedNumLinks _ aNode confirmedNumLinks. s _ aNode contentsWithoutAttachments. toUnix nextPut: 51. "modifyNode command" toUnix ne: 4 put: (ain at: i)]. toUnix nextPut: nla. "number of link attributes" 1 to: nla do: [:i | toUnix nextNumber: 4 put: (ail at: i)]. self waitForResponse isNil ifTrue: [^nil]. r _ Array new: 5. r at:1 put: (fromUnix nextNumber: 4). "time stamp" numLinks _ fromUnix nextNumber: 4. "number of links" r at: 2 put: numLinks. numLinks = 0 ifFalse: [ l _ Array new: numLinks. r at:3 put: l. 1 to: numLinks do: [:i | a _ LinkAttachment new. a linkIndex: (fromUnix nextNumber: 4). xtNumber: 4 put: (16 + (confirmedNumLinks * 16) + (s size)). "size of command" toUnix nextNumber: 4 put: (aNode nodeIndex). toUnix nextNumber: 4 put: (aNode timeStamp). toUnix nextNumber: 4 put: confirmedNumLinks. confirmedNumLinks = 0 ifFalse: [ a _ aNode links first. numLinks timesRepeat: [ a linkIndex ~= nil ifTrue: [ toUnix nextNumber: 4 put: (a linkIndex). toUnix nextNumber: 4 put: (a charPosition). toUnix nextNumber: 4 put: (a versionTime). a isInLi a charPosition: (fromUnix nextNumber: 4). a versionTime: (fromUnix nextNumber: 4). a isInLink: ((fromUnix nextNumber:4) = 1). a attributeValues: (self extractAttributeValues: nla). l at: i put: a.]]. r at: 4 put: (self extractAttributeValues: nna). l _ fromUnix nextNumber: 4. "size of text contents" fromUnix restIsText. s _ String new: l. s _ fromUnix next: l into: s. r at: 5 put: s. fromUnix binary. ^r! setNodeAttributeValue: nodeIndex for: attributeIndex nk ifTrue: [toUnix nextNumber: 4 put: 1.] ifFalse: [toUnix nextNumber:4 put: 0.]]. a _ a nextLink.]]. toUnix nextNumber: 4 put: (s size). toUnix flush; text. toUnix nextPutAll: s. toUnix flush; binary. self waitForResponse isNil ifTrue: [^nil]. ^fromUnix nextNumber: 4 "new version time"! openNode: anInteger1 versionTime: anInteger2 numNodeAttributes: nna nodeAttributeIndices: ain numLinkAttributes: nla linkAttributeIndices: ail "opens a specific version of a node retrieving its as: isString with: aString with: anInteger "updates an attribute/value pair for node nodeIndex" toUnix nextPut: 53. "setNodeAttributeValue command" toUnix nextNumber: 4 put: (13 + (self stringParamSize: aString)). "size of command" toUnix nextNumber: 4 put: nodeIndex. "node index" toUnix nextNumber: 4 put: attributeIndex. "attribute index" isString ifTrue: [toUnix nextPut: 1] ifFalse: [toUnix nextPut: 0]. "isString" self putStringArgument: aString. "value as string" toUnix nextNumber: 4 put: anIntelink attachments and contents and attribute values corresponding to attribute indices in `ain'. For each link, also sends value corresponding to attribute indices in `ail'." | r g l s numLinks a | toUnix nextPut: 50. "openNode command" toUnix nextNumber: 4 put: (10 + (nna * 4) + (nla * 4)). "size of command" toUnix nextNumber: 4 put: anInteger1. "node index" toUnix nextNumber: 4 put: anInteger2. "version time" toUnix nextPut: nna. "number of node attributes" 1 to: nna do: [:i | toUnix nextNumberger. "integerValue" ^self waitForResponse! ! !HyperRPC methodsFor: 'linkOperations'! copyLink: sl from: aNode "copies a link from the hypertext graph" | r | toUnix nextPut: 91. "copyLink command" toUnix nextNumber: 4 put: 17. "size of command" toUnix nextNumber: 4 put: (sl sameAs). toUnix nextNumber: 4 put: (sl versionTime). (sl isInLink) ifTrue: [r _ 1] ifFalse: [r _ 0]. toUnix nextPut: r. toUnix nextNumber: 4 put: (aNode nodeIndex). toUnix nextNumber: 4 put: (sl charPosition). toUnix nextNumber: 4 put: (aNode context). self waitForResponse isNil ifTrue: [^nil]. r _ Array new: 2. r at: 1 put: (fromUnix nextNumber: 4). "link index" r at: 2 put: (fromUnix nextNumber: 4). "time stamp" ^r! deleteLink: aLinkIndex "deletes a link from the hypertext graph" toUnix nextPut: 80. "deleteLink command" toUnix nextNumber: 4 put: 4. "size of command" toUnix nextNumber: 4 put: aLinkIndex. ^self waitForResponse! deleteLinkAttribute: linkIndex for: attributeIndex "deletes an attribute/valu4 put: attributeIndex. "attribute index" toUnix nextNumber: 4 put: versionTime. "versionTime" self waitForResponse isNil ifTrue: [^nil]. r _ Array new: 2. r at: 1 put: ((fromUnix next) = 1). "isString" (r at: 1) ifTrue: [r at: 2 put: (self getStringArgument) "string value"] ifFalse: [r at: 2 put: (fromUnix nextNumber: 4) "integer value"]. ^r! getToNode: linkIndex at: versionTime "gets the node index and node version index of the destination of linkIndex." | r b | toUnix nextPut: 82. "gee pair for link linkIndex" toUnix nextPut: 89. "deleteLinkAttribute command" toUnix nextNumber: 4 put: (8). "size of command" toUnix nextNumber: 4 put: linkIndex. "link index" toUnix nextNumber: 4 put: attributeIndex. "attribute index" ^self waitForResponse! getFromNode: linkIndex at: versionTime "gets the node index and node version index of the source of linkIndex." | r b | toUnix nextPut: 83. "getFromNode command" toUnix nextNumber: 4 put: 8. "size of command" toUnix nextNumber:4 put: linkItToNode command" toUnix nextNumber: 4 put: 8. "size of command" toUnix nextNumber:4 put: linkIndex. toUnix nextNumber:4 put: versionTime. self waitForResponse isNil ifTrue: [^nil]. r _ Array new: 3. r at:1 put: (fromUnix nextNumber: 4). "the node index" r at:2 put: (fromUnix nextNumber: 4). "the version index" r at:3 put: (fromUnix nextNumber: 4). "the node's context" ^r! setLinkAttributeValue: linkIndex for: attributeIndex as: isString with: aString with: anInteger "updates an attribute/valuendex. toUnix nextNumber:4 put: versionTime. self waitForResponse isNil ifTrue: [^nil]. r _ Array new: 3. r at:1 put: (fromUnix nextNumber: 4). "the node index" r at:2 put: (fromUnix nextNumber: 4). "the version index" r at:3 put: (fromUnix nextNumber: 4). "the node's context" ^r! getLinkAttributes: anInteger1 versionTime: anInteger2 "gets the attribute/value pairs for version anInteger1 of link anInteger2" toUnix nextPut: 88. "getLinkAttributes command" toUnix nextNumber: 4 put: 8. "size of c pair for link linkIndex" toUnix nextPut: 86. "setLinkAttributeValue command" toUnix nextNumber: 4 put: (13 + (self stringParamSize: aString)). "size of command" toUnix nextNumber: 4 put: linkIndex. "link index" toUnix nextNumber: 4 put: attributeIndex. "attribute index" isString ifTrue: [toUnix nextPut: 1] ifFalse: [toUnix nextPut: 0]. "isString" self putStringArgument: aString. "value as string" toUnix nextNumber: 4 put: anInteger. "integerValue" ^self waitForResponse! ! !HyperRPC methodsFor: 'ommand" toUnix nextNumber: 4 put: anInteger1. "link index" toUnix nextNumber: 4 put: anInteger2. "version time" self waitForResponse isNil ifTrue: [^nil]. ^self extractAttributes! getLinkAttributeValue: linkIndex for: attributeIndex at: versionTime "gets the value of attributeIndex for link linkIndex at time versionTime" | r | toUnix nextPut: 87. "getLinkAttributeValue command" toUnix nextNumber: 4 put: 12. "size of command" toUnix nextNumber: 4 put: linkIndex. "link index" toUnix nextNumber: graphOperations'! addLinkFrom: fromNodeIndex to: toNodeIndex fromAt: fromCurPos toAt: toCurPos fromContext: fromContext toContext: toContext "adds a link to the hypertext graph. Returns entityIndex of the new link." | r | toUnix nextPut: 27. "addLink command" toUnix nextNumber: 4 put: 24. "size of command" toUnix nextNumber: 4 put: fromNodeIndex. toUnix nextNumber: 4 put: toNodeIndex. toUnix nextNumber: 4 put: fromCurPos. toUnix nextNumber: 4 put: toCurPos. toUnix nextNumber: 4 put: fromContext . toUnix nextNumber: 4 put: toContext. self waitForResponse isNil ifTrue: [^nil]. r _ Array new: 2. r at: 1 put: (fromUnix nextNumber: 4). "link index" r at: 2 put: (fromUnix nextNumber: 4). "time stamp" ^r! addNode: asArchive type: aByte mask: anInteger "adds a node to the hypertext graph. If asArchive = true then node is created as an archive. Returns entityIndex of the new node." | r b | toUnix nextPut: 26. "addNode command" toUnix nextNumber: 4 put: 6. "size of command" asArchive ifTrxtNumber: 4. r _ Array new: numAtts. 1 to: numAtts do: [:i | v _ Array new: 2. v at: 1 put: (fromUnix nextNumber: 4). "node index" v at: 2 put: (self getStringArgument). r at: i put: v]. ^r! getAttributeValues: attributeIndex at: versionTime "Gets the list of attributes, index and name, that were defined at time versionTime." | r numValues v | toUnix nextPut: 33. "command for getValuesOfAttribute" toUnix nextNumber: 4 put: 8. "size of command" toUnix nextNumber: 4 put: attriue: [b _ 1] ifFalse:[b _ 0]. toUnix nextPut: b. toUnix nextPut: aByte. toUnix nextNumber: 4 put: anInteger. "protection mask" self waitForResponse isNil ifTrue: [^nil]. r _ Array new: 2. r at: 1 put: (fromUnix nextNumber: 4). "node index" r at: 2 put: (fromUnix nextNumber: 4). "time stamp" ^r! createGraphIn: aString mask: anInteger "Creates a new hypertext graph using creation defaults." | r b | toUnix nextPut: 20. "createGraph command" toUnix nextNumber: 4 put: (4 + (self stringParamSize: buteIndex. toUnix nextNumber: 4 put: versionTime. self waitForResponse isNil ifTrue: [^nil]. numValues _ fromUnix nextNumber: 4. r _ self extractAttributeValues: numValues. ^r! getContextsViaAttributes: versionTime predicate: aString1 attributes: ca "Gets a list of contexts and their parentage who satisfy the predicate, aString at versionTime. Also returns the value of the attributes in ca for each context." | r numContexts numLinks v numAtt | numAtt _ (ca = nil) ifTrue: [0] ifFalse: [ca size]aString)). "size of command" self putStringArgument: aString. toUnix nextNumber: 4 put: anInteger. self waitForResponse isNil ifTrue: [^nil]. r _ Array new:2. r at:1 put: (fromUnix nextNumber: 4). r at:2 put: (fromUnix nextNumber: 4). ^r! destroyGraphPath: aString pid1: anInteger1 pid2: anInteger2 "Destroys an existing hypertext graph, identified by anInteger1/anInteger2, in unix directory aString." toUnix nextPut: 21. "command for destroyGraph" toUnix nextNumber: 4 put: (8 + (self stringPara. toUnix nextPut: 112. "command for getContextsViaAttributes" toUnix nextNumber: 4 put: (5 + (self stringParamSize: aString1) + (numAtt * 4)). "size of command" toUnix nextNumber: 4 put: versionTime. self putStringArgument: aString1. toUnix nextPut: numAtt. "number of Attributes" 1 to: numAtt do: [:i | toUnix nextNumber: 4 put: (ca at: i)]. self waitForResponse isNil ifTrue: [^nil]. r _ Array new: 2. numContexts _ fromUnix nextNumber: 4. r at: 1 put: (Array new: numContexts). 1 to: numContextsmSize: aString)). "size of command" toUnix nextNumber: 4 put: anInteger1. toUnix nextNumber: 4 put: anInteger2. self putStringArgument: aString. ^self waitForResponse! getAttributes: versionTime "Gets the list of attributes, index and name, that were defined at time versionTime." | r numAtts v | toUnix nextPut: 32. "command for getAttributes" toUnix nextNumber: 4 put: 4. "size of command" toUnix nextNumber: 4 put: versionTime. self waitForResponse isNil ifTrue: [^nil]. numAtts _ fromUnix ne do: [:i | v _ Array new: 2. (r at: 1) at: i put: v. v at: 1 put: (fromUnix nextNumber: 4). "context index" v at: 2 put: (self extractAttributeValues: numAtt)]. numLinks _ fromUnix nextNumber: 4. r at: 2 put: (Array new: (numLinks)). 1 to: numLinks do: [:i | v _ Array new: 2. (r at: 2) at: i put: v. v at: 1 put: (fromUnix nextNumber: 4). "parent index" v at: 2 put: (fromUnix nextNumber: 4) "child index"]. ^r! getGraphViaAttributes: versionTime nodePredicate: aString1 linkP redicate: aString2 nodeAttributes: na linkAttributes: la "Gets a list of nodes and links who satisfy the predicate, aString at versionTime. Also returns the value of the attributes in na/la for each node and link." | r numNodes numLinks v numNodeAtt numLinkAtt | na = nil ifTrue: [numNodeAtt _ 0] ifFalse: [numNodeAtt _ na size]. la = nil ifTrue: [numLinkAtt _ 0] ifFalse: [numLinkAtt _ la size]. toUnix nextPut: 29. "command for getGraphViaAttributes" toUnix nextNumber: 4 put: (6 + (self stringt versionTime. Also returns the value of the attributes in na/la for each node and link." | r numNodes numLinks v numNodeAtt numLinkAtt | na = nil ifTrue: [numNodeAtt _ 0] ifFalse: [numNodeAtt _ na size]. la = nil ifTrue: [numLinkAtt _ 0] ifFalse: [numLinkAtt _ la size]. toUnix nextPut: 36. "command for linearizeGraph" toUnix nextNumber: 4 put: (14 + (self stringParamSize: aString1) + (self stringParamSize: aString2) +(numNodeAtt * 4) + (numLinkAtt * 4)). "size of command" toUnix nextNumber:ParamSize: aString1) + (self stringParamSize: aString2) + (numNodeAtt * 4) + (numLinkAtt * 4)). "size of command" toUnix nextNumber: 4 put: versionTime. self putStringArgument: aString1. self putStringArgument: aString2. toUnix nextPut: numNodeAtt. "number of node Attributes" 1 to: numNodeAtt do: [:i | toUnix nextNumber: 4 put: (na at: i)]. toUnix nextPut: numLinkAtt. "number of link Attributes" 1 to: numLinkAtt do: [:i | toUnix nextNumber: 4 put: (la at: i)]. self waitForResponse isNil ifTrue: [^n 4 put: nodeIndex. toUnix nextNumber: 4 put: versionTime. toUnix nextNumber: 4 put: anInteger. self putStringArgument: aString1. self putStringArgument: aString2. toUnix nextPut: numNodeAtt. "number of node Attributes" 1 to: numNodeAtt do: [:i | toUnix nextNumber: 4 put: (na at: i)]. toUnix nextPut: numLinkAtt. "number of link Attributes" 1 to: numLinkAtt do: [:i | toUnix nextNumber: 4 put: (la at: i)]. self waitForResponse isNil ifTrue: [^nil]. r _ Array new: 2. numNodes _ fromUnix nextNumber:il]. r _ Array new: 2. numNodes _ fromUnix nextNumber: 4. r at: 1 put: (Array new: numNodes). 1 to: numNodes do: [:i | v _ Array new: 3. (r at: 1) at: i put: v. v at: 1 put: (fromUnix nextNumber: 4). "node index" v at: 2 put: (fromUnix nextNumber: 4). "version time" v at: 3 put: (self extractAttributeValues: numNodeAtt)]. numLinks _ fromUnix nextNumber: 4. r at: 2 put: (Array new: (numLinks)). 1 to: numLinks do: [:i | v _ Array new: 5. (r at: 2) at: i put: v. v at: 1 pu 4. r at: 1 put: (Array new: numNodes). 1 to: numNodes do: [:i | v _ Array new: 3. (r at: 1) at: i put: v. v at: 1 put: (fromUnix nextNumber: 4). "node index" v at: 2 put: (fromUnix nextNumber: 4). "version time" v at: 3 put: (self extractAttributeValues: numNodeAtt)]. numLinks _ fromUnix nextNumber: 4. r at: 2 put: (Array new: (numLinks)). 1 to: numLinks do: [:i | v _ Array new: 5. (r at: 2) at: i put: v. v at: 1 put: (fromUnix nextNumber: 4). "link index" v at: 2 pt: (fromUnix nextNumber: 4). "link index" v at: 2 put: (fromUnix nextNumber: 4). "version time" v at: 3 put: (fromUnix nextNumber: 4). "from node index" v at: 4 put: (fromUnix nextNumber: 4). "to node index" v at: 5 put: (self extractAttributeValues: numLinkAtt)]. ^r! linearizeGraph: nodeIndex at: versionTime depth: anInteger nodePredicate: aString1 linkPredicate: aString2 nodeAttributes: na linkAttributes: la "Gets a list of nodes and links who satisfy the predicate, aString aut: (fromUnix nextNumber: 4). "version time" v at: 3 put: (fromUnix nextNumber: 4). "from node index" v at: 4 put: (fromUnix nextNumber: 4). "to node index" v at: 5 put: (self extractAttributeValues: numLinkAtt)]. ^r! makeSearch: aString toUnix nextPut: 40. "makeSearch" toUnix nextNumber: 4 put: (self stringParamSize: aString). "size of command" self putStringArgument: aString. ^self waitForResponse! openGraphPath: aString pid1: anInteger1 pid2: anInteger2 "Opens an existing h!ypertext graph, identified by anInteger1/anInteger2, in unix directory aString." toUnix nextPut: 22. "command for openGraph" toUnix nextNumber: 4 put: (8 + (self stringParamSize: aString)). "size of command" toUnix nextNumber: 4 put: anInteger1. toUnix nextNumber: 4 put: anInteger2. self putStringArgument: aString. ^self waitForResponse! searchContents: numNodes nodeList: nodes nodeAttributes: na code: c | r n a numNodeAtt | na = nil ifTrue: [numNodeAtt _ 0] ifFalse: [numNodeAtt _ na sizifTrue: [^nil]. ^fromUnix nextNumber: 4! getStringIndex: aString toUnix nextPut: 30. "getStringIndex" toUnix nextNumber: 4 put: (self stringParamSize: aString). "size of command" self putStringArgument: aString. self waitForResponse isNil ifTrue: [^nil]. ^fromUnix nextNumber: 4! getUserName toUnix nextPut: 202. "getUserName" toUnix nextNumber: 4 put: 0. "size of command" self waitForResponse isNil ifTrue: [^nil]. ^self getStringArgument! parseExpression: aString toUnix nextPut: 39. "pae]. toUnix nextPut: 41. "searchContents" toUnix nextNumber: 4 put: (6 + (numNodes * 16) + (numNodeAtt * 4)). "size of command" toUnix nextNumber: 4 put: numNodes. 1 to: numNodes do: [:i | 1 to: 4 do: [:j | toUnix nextNumber: 4 put: ((nodes at: i) at: j)]]. toUnix nextPut: numNodeAtt. "number of node Attributes" 1 to: numNodeAtt do: [:i | toUnix nextNumber: 4 put: (na at: i)]. toUnix nextPut: c. "search strategy code: 0 = all matches, 1 = stop at first match, 2 = stop at each first version matrseExpression" toUnix nextNumber: 4 put: (self stringParamSize: aString). "size of command" self putStringArgument: aString. ^self waitForResponse! quit | d | toUnix nextPut: 1. "quit command" toUnix nextNumber:4 put: 0. "size of command" self waitForResponse. "cleaning up after the child process terminates" ResponsePipe close. ResponsePipe _ nil. CommandPipe close. CommandPipe _ nil. d _ TekSystemCall wait. d systemInvoke.! recoverFromCrash toUnix nextPut: 7. "recoverFromCrash" toUnch" self waitForResponse isNil ifTrue: [^nil]. r _ fromUnix nextNumber: 4. n _ Array new: r. 1 to: r do: [:i | a _ (Array new: 5). n at: i put: a. 1 to: 4 do: [:j | a at: j put: (fromUnix nextNumber: 4)]. a at: 5 put: (self extractAttributeValues: numNodeAtt)]. ^n! ! !HyperRPC methodsFor: 'systemOperations'! abortTransaction toUnix nextPut: 6. "abortTransaction" toUnix nextNumber: 4 put: 0. "size of command" ^self waitForResponse! beginTransaction: isUpdate | r b | toUnix neix nextNumber: 4 put: 0. "size of command" ^self waitForResponse! setHostMachine: aString toUnix nextPut: 201. "set host machine" toUnix nextNumber: 4 put: (self stringParamSize: aString). "size of command" self putStringArgument: aString. ^self waitForResponse! ! !HyperRPC methodsFor: 'contextOperations'! checkForConflictsFrom: fromId to: toId numNodes: numNodes nodeList: nodes | r numConflicts a b | toUnix nextPut: 105. "checkForConflicts" toUnix nextNumber: 4 put: (12 + (numNodes * 8)).xtPut: 4. "beginTransaction" toUnix nextNumber: 4 put: 1. "size of command" isUpdate ifTrue: [b _ 1] ifFalse:[b _ 0]. toUnix nextPut: b. ^self waitForResponse! commitTransaction toUnix nextPut: 5. "commitTransaction" toUnix nextNumber: 4 put: 0. "size of command" ^self waitForResponse! getAttributeIndex: aString toUnix nextPut: 38. "getAttributeIndex" toUnix nextNumber: 4 put: (self stringParamSize: aString). "size of command" self putStringArgument: aString. self waitForResponse isNil  "size of command" toUnix nextNumber: 4 put: fromId. toUnix nextNumber: 4 put: toId. toUnix nextNumber: 4 put: numNodes. 1 to: numNodes do: [:i | 1 to: 2 do: [:j | toUnix nextNumber: 4 put: ((nodes at: i) at: j)]]. self waitForResponse isNil ifTrue: [^nil]. numConflicts _ fromUnix nextNumber: 4. a _ Array new: numConflicts. 1 to: numConflicts do: [:i | b _ Array new: 6. a at: i put: b. b at: 1 put: (fromUnix next). "diff class" b at: 2 put: (fromUnix nextNumber: 4). "entity! index" b at: 3 put: (fromUnix nextNumber: 4). "version time" b at: 4 put: (fromUnix nextNumber: 4). "object index" b at: 5 put: (fromUnix next). "from diff" b at: 6 put: (fromUnix next). "to diff" a at: i put: b]. ^a! compactContext: aBoolean toUnix nextPut: 103. "compactContext" toUnix nextNumber: 4 put: 1. "size of command" toUnix nextPut: (aBoolean ifTrue: [1] ifFalse: [0]). ^self waitForResponse! createContextWithMask: anInteger | r | toUnix nextPuersion time" self waitForResponse isNil ifTrue: [^nil]. ^self extractAttributes! getContextAttributeValue: contextIndex for: attributeIndex at: versionTime "gets the value of attributeIndex for context contextIndex at time versionTime" | r | toUnix nextPut: 107. "getContextAttributeValue command" toUnix nextNumber: 4 put: 12. "size of command" toUnix nextNumber: 4 put: contextIndex. "context index" toUnix nextNumber: 4 put: attributeIndex. "attribute index" toUnix nextNumber: 4 put: versionTime.t: 100. "createContext" toUnix nextNumber: 4 put: 4. "size of command" toUnix nextNumber: 4 put: anInteger. self waitForResponse isNil ifTrue: [^nil]. r _ Array new: 2. r at: 1 put: (fromUnix nextNumber: 4). "context id" r at: 2 put: (fromUnix nextNumber: 4). "creation time" ^r! deleteContextAttribute: contextIndex for: attributeIndex "deletes an attribute/value pair for context contextIndex" toUnix nextPut: 102. "deleteContextAttribute command" toUnix nextNumber: 4 put: (8). "size of command" "versionTime" self waitForResponse isNil ifTrue: [^nil]. r _ Array new: 2. r at: 1 put: ((fromUnix next) = 1). "isString" (r at: 1) ifTrue: [r at: 2 put: (self getStringArgument) "string value"] ifFalse: [r at: 2 put: (fromUnix nextNumber: 4) "integer value"]. ^r! getParentContext: contextId toUnix nextPut: 110. "getParentContextContext" toUnix nextNumber: 4 put: 4. "size of command" toUnix nextNumber: 4 put: contextId. self waitForResponse isNil ifTrue: [^nil]. ^(fromUnix nextNumbe toUnix nextNumber: 4 put: contextIndex. "context index" toUnix nextNumber: 4 put: attributeIndex. "attribute index" ^self waitForResponse! destroyContext: anInteger toUnix nextPut: 102. "destroyContext" toUnix nextNumber: 4 put: 4. "size of command" toUnix nextNumber: 4 put: anInteger. ^self waitForResponse! getChildContexts: contextId | r numChildren | toUnix nextPut: 111. "getChildContexts" toUnix nextNumber: 4 put: 4. "size of command" toUnix nextNumber: 4 put: contextId. self waitr: 4) "context id"! mergeContextFrom: fromContextId to: toContextId numNodes: numNodes nodeList: nodes toUnix nextPut: 104. "mergeContext" toUnix nextNumber: 4 put: (12 + (numNodes * 8)). "size of command" toUnix nextNumber: 4 put: fromContextId. toUnix nextNumber: 4 put: toContextId. toUnix nextNumber: 4 put: numNodes. 1 to: numNodes do: [:i | 1 to: 2 do: [:j | toUnix nextNumber: 4 put: ((nodes at: i) at: j)]]. ^self waitForResponse! openContext: contextId toUnix nextPut: 101. "openContext" ForResponse isNil ifTrue: [^nil]. numChildren _ (fromUnix nextNumber: 4). r _ Array new: numChildren. 1 to: numChildren do: [:i | r at: i put: (fromUnix nextNumber: 4)]. ^r! getContextAttributes: anInteger1 versionTime: anInteger2 "gets the attribute/value pairs for version anInteger1 of context anInteger2" toUnix nextPut: 108. "getContextAttributes command" toUnix nextNumber: 4 put: 8. "size of command" toUnix nextNumber: 4 put: anInteger1. "context index" toUnix nextNumber: 4 put: anInteger2. "vtoUnix nextNumber: 4 put: 4. "size of command" toUnix nextNumber: 4 put: contextId. ^self waitForResponse! setContextAttributeValue: contextIndex for: attributeIndex as: isString with: aString with: anInteger "updates an attribute/value pair for context contextIndex" toUnix nextPut: 106. "setContextAttributeValue command" toUnix nextNumber: 4 put: (13 + (self stringParamSize: aString)). "size of command" toUnix nextNumber: 4 put: contextIndex. "context index" toUnix nextNumber: 4 put: attributeInde"x. "attribute index" isString ifTrue: [toUnix nextPut: 1] ifFalse: [toUnix nextPut: 0]. "isString" self putStringArgument: aString. "value as string" toUnix nextNumber: 4 put: anInteger. "integerValue" ^self waitForResponse! ! !HyperRPC methodsFor: 'private'! extractAttributes | numPairs r i t isString | "reads attribute value pairs from fromUnix file" numPairs _ fromUnix nextNumber:4. r _ Array new: (numPairs + 1). r at: 1 put: numPairs. i _ 1. [i <= numPairs] whileTrue: [t _ r at: (i + CErrorCode _ fromUnix nextNumber: 4. HyperRPCErrorMessage _ self getStringArgument. numParams _ fromUnix nextNumber: 4. HyperRPCErrorParams _ Array new: numParams. 1 to: numParams do: [:i | HyperRPCErrorParams at: i put: (fromUnix nextNumber: 4)]]. Cursor execute show. ^r! ! !HyperRPC methodsFor: 'initialize'! initialize toUnix _ CommandPipe. fromUnix _ ResponsePipe.! ! !HyperRPC methodsFor: 'error access'! errorCode ^HyperRPCErrorCode! errorMessage ^HyperRPCErrorMessage! er1) put: (Array new: 4). t at: 1 put: (fromUnix nextNumber: 4). "attribute index" t at: 2 put: (self getStringArgument). "attribute name" isString _ ((fromUnix next) = 1). t at:4 put: isString. isString ifTrue: [t at: 3 put: (self getStringArgument)] "attribute value as string" ifFalse: [t at: 3 put: (fromUnix nextNumber:4)]. i _ i + 1]. ^r! extractAttributeValues: numAttributes | v j b | numAttributes = 0 ifTrue: [ ^nil]. v _ Array new: (numAttriburorParams ^HyperRPCErrorParams! incompleteTransactionError ^(HyperRPCErrorCode == 44)! linkDoesNotExistYetError ^(HyperRPCErrorCode == 54)! reportError: aString self notify: aString, ' RPC failed: ', (String with: Character cr), HyperRPCErrorMessage.! reportErrorAborting: aString | s | s _ aString, ' RPC failed: ', (String with: Character cr), HyperRPCErrorMessage. self abortTransaction. self notify: s. ^nil! ! !NodeStyle methodsFor: 'menus'! yellowButtonMenu ^YellowButtonMenu! ! !NodeStyle metes * 2). j _ 1. [j < (numAttributes * 2)] whileTrue: [ b _ fromUnix next. b = 2 ifFalse: [v at: j put: (b = 1)]. b = 1 ifTrue: [v at: (j + 1) put: (self getStringArgument)]. b = 0 ifTrue: [v at: (j + 1) put: (fromUnix nextNumber: 4)]. j _ j + 2]. ^v! failed ^nil! getStringArgument | s l | "answer a new string that is determined by reading the stream, fromUnix. Input format is as two-byte size field followed by the sequence of bytes." l _ fromUnix nextNumber: 2. s _ String new: l.thodsFor: 'accessing'! hyperGraph ^hyperGraph! hyperGraph: aHyperGraph hyperGraph _ aHyperGraph! isArchive ^isArchive! isArchive: aBoolean isArchive _ aBoolean. self changed: #isArchive.! objectName ^objectName! objectName: aString objectName _ aString! objectNameAsText ^objectName asText! objectNameFromText: aText | n | n _ aText asString. "object name must be a name of an existing Smalltalk class" (Smalltalk at: (Symbol intern: 'Node') ifAbsent: [^nil]) isNil ifTrue: [ Transcript cr; show:  1 to: l do: [:i | s at: i put: (fromUnix next asCharacter)]. ^s! putStringArgument: aString "put a string using the format: two-byte size field followed by the sequence of bytes." toUnix nextNumber: 2 put: (aString size). aString do: [:char | toUnix nextPut: char asciiValue].! stringParamSize: aString ^(aString size) + 2 "add in two-byte size field"! waitForResponse | r numParams | toUnix flush. Cursor wait show. r _ (fromUnix next == 1) ifTrue: [true] ifFalse: [nil]. r isNil ifTrue: [HyperRP'must be a name of an existing Smalltalk class'. ^false]. objectName _ n. ^true! protectionMask ^protectionMask! protectionMask: anInteger protectionMask _ anInteger! type ^1! view: aView view _ aView! ! !NodeStyle methodsFor: 'initialization'! initialize isArchive _ true. protectionMask _ 0. objectName _ DefaultObjectName.! open view isNil ifTrue: [NodeStyleView openOn: self]. view controller open.! release view _ nil. super release! ! !Node methodsFor: 'update'! cancelPotentialLinks lin"kSource ~= nil ifTrue: [linkSource _ nil. graph cancelLinkSource]. linkDestination ~= nil ifTrue: [linkDestination _ nil. graph cancelLinkDestination].! empty "empties contents of node" controller view updateRequest ifFalse: [^false]. self contents: String new. numLinks _ 0. self links: nil. controller view newContents.! get: n versionTime: vt "accesses a specific version of an existing node, nodeIndex, from the hypertext graph" | r ai m c rpc | controller view updateRequest ifFalse: [^false]. alse: [name _ nil]. self contents: (r at: 5).! release super release. self breakDependents! ! !Node methodsFor: 'link attachment'! deleteAttachment: sl links remove: sl ifAbsent: []. numLinks _ numLinks - 1! insertAttachment: t1 | t2 t3 | t1 nextLink: nil. numLinks _ numLinks + 1. links isEmpty ifTrue: [links add: t1. ^true]. t3 _ t1 charPosition. links first charPosition >= t3 ifTrue: [links addFirst: t1. ^true]. links last charPosition <= t3 ifTrue: [links addLastnodeIndex _ n. ai _ Array new: 2. ai at: 1 put: (graph iconNameIndex). ai at: 2 put: (graph objectIndex). (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc openNode: nodeIndex versionTime: vt numNodeAttributes: 2 nodeAttributeIndices: ai numLinkAttributes: 1 linkAttributeIndices: ai. r = nil ifTrue: [rpc reportError: 'openNode'. ^nil]. m _ ((r at: 4) at: 3) == true ifTrue: [((r at: 4) at: 4)] ifFalse: ['TextNode']. c _ Smalltalk at: (Symbol intern: m) ifAbsent: [^nil]. (c isNil or: t1. ^true]. t2 _ links first. [t2 nextLink charPosition < t3] whileTrue: [t2 _ t2 nextLink]. t1 nextLink: t2 nextLink. t2 nextLink: t1. ^true! ! !Node methodsFor: 'access'! confirmedNumLinks | n | n _ numLinks. linkSource ~= nil ifTrue: [n _ n - 1]. linkDestination ~= nil ifTrue: [n _ n - 1]. ^n! contents ^contents! contents: t1 contents _ t1! contentsWithoutAttachments ^contents! context ^context! context: t1 context _ t1! controller: aNodeController controller _ aNodeController!: [c ~= TextNode]) ifTrue: [Transcript cr; show: 'Can only open TextNode objects, node is '; show: m. ^nil]. isHistory _ vt ~= 0. timeStamp _ (r at: 1). numLinks _ (r at: 2). self links: (r at: 3). self contents: (r at: 5). controller view newContents. ^true! update "updates node in hypertext grap" | r rpc | (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc modifyNode: self. Cursor normal show. r = nil ifTrue: [rpc reportError: 'modifyNode'] ifFalse: [timeStamp _ r]! ! !Nod graph ^graph! graph: t1 graph _ t1! isHistory ^isHistory! isHistory: t1 isHistory _ t1! linkAt: aCharValue | sl | links isEmpty ifTrue: [^nil]. sl _ links first. [(sl charValue) = aCharValue] whileFalse: [sl _ sl nextLink. sl = nil ifTrue: [^nil]]. ^sl! linkOfIndex: linkIndex | sl | sl _ links first. [(sl linkIndex) = linkIndex] whileFalse: [sl _ sl nextLink. sl = nil ifTrue: [^nil]]. ^sl! links ^links! links: linkArray | r c | links _ LinkedList new. numLinks _ 0. linkArraye methodsFor: 'initialize-release'! reinitialize | ai r rpc | ai _ Array new: 1. ai at: 1 put: (graph iconNameIndex). (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc openNode: nodeIndex versionTime: 0 numNodeAttributes: 1 nodeAttributeIndices: ai numLinkAttributes: 1 linkAttributeIndices: ai. r = nil ifTrue: [rpc reportError: 'openNode'. ^nil]. timeStamp _ (r at: 1). numLinks _ (r at: 2). self links: (r at: 3). ((r at: 4) at: 1) = true ifTrue: [name _ ((r at: 4) at: 2)] ifF ~= nil ifTrue: [linkArray do: [:sl | self insertAttachment: sl]]! linkSameAs: linkIndex | sl | sl _ links first. [(sl sameAs) = linkIndex] whileFalse: [sl _ sl nextLink. sl = nil ifTrue: [^nil]]. ^sl! name ^name! name: t1 name _ t1! nodeIndex ^nodeIndex! nodeIndex: t1 nodeIndex _ t1! numLinks ^numLinks! numLinks: t1 numLinks _ t1! timeStamp ^timeStamp! timeStamp: t1 timeStamp _ t1! type ^type! type: anInteger type _ anInteger! ! !Node methodsFor: 'private'! makeLabel | r s t | s# _ graph contextName. r _ name. r isNil ifTrue: [s _ s,': Node Browser'] ifFalse: [s _ s, ': ', r]. isHistory ifTrue: [t _ Time fromUnixSeconds: timeStamp. s _ s, ' (', ((t at: 1) printFormat: #(1 2 3 32 2 2)). s _ s, ' ', ((t at: 2) printString), ')']. ^s! ! !Node methodsFor: 'menu actions'! addLink "adds a link in the hyperGraph from current source to destination" graph addLink.! browseAttributes "opens a browser to view the attributes of this node" | vt | isHistory ifTrue: [vt nkIndex isNil) ifTrue: [ (sl sameAs isNil) ifTrue: [sl isInLink ifTrue: [graph cancelLinkDestination] ifFalse: [graph cancelLinkSource]]] ifFalse: [(rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc deleteLink: (sl linkIndex). r isNil ifTrue: [rpc reportError: 'deleteLink'. ^false]]. self deleteAttachment: sl. ^true! deleteSelf | r rpc | (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc deleteNode: nodeIndex. r isNil ifTrue: [rpc reportError: 'd_ timeStamp] ifFalse: [vt _ 0]. Attribute openOnNode: nodeIndex versionTime: vt in: graph! browseDocument "opens a document browser rooted at this nodeIndex at versionTime" | vt d | isHistory ifTrue: [vt _ timeStamp] ifFalse: [vt _ 0]. d _ Document new. d versionTime: vt; hyperGraph: graph. d root: (Array with: nodeIndex with: vt with: name). DocumentView openOn: d.! browseGraph "opens a graph browser rooted at this nodeIndex at versionTime" | vt | isHistory ifTrue: [vt _ timeStamp] eleteNode'. ^false]. isHistory _ true. ^true! mergeNode | t rpc r | t _ graph targetContext. t isNil ifTrue: [Transcript cr; show: 'No target context defined'. ^false]. (rpc _ graph rpcFor: context) isNil ifTrue: [^true]. r _ rpc mergeContextFrom: context to: t numNodes: 1 nodeList: (Array with: (Array with: nodeIndex with: timeStamp)). r isNil ifTrue: [rpc reportError: 'mergeContext'. ^false]. ^true! ! !FormNode methodsFor: 'defaults'! viewerClass ^NodeFormController! ! !FormNode methodsForifFalse: [vt _ 0]. Graph openOn: graph at: nodeIndex when: vt nodePredicate: '*' linkPredicate: '*'.! browseVersions "opens a browser to view the versions of this node" NodeVersions openOn: nodeIndex in: graph! compactSelf: entirely | r rpc | (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc compactNode: nodeIndex entirely: entirely. r isNil ifTrue: [rpc reportError: 'compactNode'. ^false]. ^true! compareNode | t rpc r | t _ graph targetContext. t isNil ifTrue: [Transcript cr; show: 'menu actions'! acceptForm: aString "isHistory ifTrue: [^false]." contents_ aString. self update. ^true! ! !TextNode methodsFor: 'access'! contents: aString contents _ aString asText! contentsWithoutAttachments | s n stop start runs values a l oldPos | links isEmpty ifTrue: [^contents string]. s _ contents size. n _ String new: s - numLinks. l _ NodeController linkFont. runs _ contents runs runs. values _ contents runs values. start _ 1. oldPos _ 1. 1 to: (values size) do: [:i | (values at: 'No target context defined'. ^false]. (rpc _ graph rpcFor: context) isNil ifTrue: [^true]. r _ rpc checkForConflictsFrom: context to: t numNodes: 1 nodeList: (Array with: (Array with: nodeIndex with: timeStamp)). r isNil ifTrue: [rpc reportError: 'checkForConflictsFrom'. ^false]. Transcript cr; show: 'Sorry, not finished this command yet!!'. ^true! deleteLink: sl | r rpc | "assert sl is the link attachment corresponding to current selection, and only instance of sl appears in the text" (sl li: i) = l ifFalse: [stop _ start + (runs at: i) - 1. n replaceFrom: start to: stop with: contents startingAt: oldPos. start _ stop + 1]. oldPos _ oldPos + (runs at: i)]. ^n! linkDestination | c | linkDestination isNil ifTrue: [^nil]. c _ controller linkCharPos: (linkDestination charValue). c > contents size ifTrue: [c _ contents size]. linkDestination charPosition: c. ^linkDestination! linkSource | c | linkSource isNil ifTrue: [^nil]. c _ controller linkCharPos: (linkSource# charValue). c > contents size ifTrue: [c _ contents size]. linkSource charPosition: c. ^linkSource! ! !TextNode methodsFor: 'defaults'! viewerClass ^NodeView! ! !TextNode methodsFor: 'menu actions'! acceptText: aText isHistory ifTrue: [^false]. contents_ aText. (self updateLinkAttachments) ifFalse: [^false]. self update. ^true! ! !TextNode methodsFor: 'private'! adjustSelectedText: selText | start end a | "selText is an array pair (position, length) in terms of the node's text without embeted for this instance of HyperNode." links isEmpty ifTrue: [^nil]. a _ links first. s _ String new: 1. count _ 0. size _ contents size. numLinks timesRepeat: [ r _ controller addLinkIcon: a. a charValue: r. s at: 1 put: r. t _ Text string: s emphasis: (NodeController linkFont). c _ a charPosition + count. count _ count + 1. c = 0 ifTrue: [c _ 1] ifFalse: [c > (size + count) ifTrue: [c _ size + count]]. contents _ contents copyReplaceFrom: c to: (c - 1) with: t. a _ a nedded link attachments. Compensates for link attachments by extending length to include any embedded link attachments within the selection." start _ (selText at: 1) + 1. "compensate for 0 vs 1 as first array index" end _ start + (selText at: 2). links isEmpty ifFalse: [ a _ links first. numLinks timesRepeat: [ (a charPosition > start) & (a charPosition < end) ifTrue: [end _ end + 1] ifFalse: [(a charPosition < start) ifTrue: [start _ start + 1. end _ end + 1]]. a _ a nextLink]]. ^(ArrayxtLink.].! updateLinkAttachments | a i count runs values pos | "updates links, a linkedList of linkAttachments, with contents of HyperNode" links isEmpty ifTrue: [^true]. links do: [:sl | sl charPosition: nil]. runs _ contents runs runs. values _ contents runs values. i _ 1. count _ 0. pos _ 1. (values size) timesRepeat: [ (values at: i) = (NodeController linkFont) ifTrue: [ (runs at: i) timesRepeat: [ sl _ (self linkAt: (contents at: pos)). (sl charPosition) isNil ifTrue: [sl c with: start with: (end - 1))! copyWithoutLinks: aText | s n l null j p | links isEmpty ifTrue: [^aText]. s _ aText size. n _ aText copy. null _ Text new. l _ NodeController linkFont. p _ 0. 1 to: s do: [:i | ((aText emphasisAt: i) = l) ifTrue: [j _ i - p. p _ p + 1. n replaceFrom: j to: j with: null]]. ^n! firstInstanceOf: linkIndex | textSize i c sl | "scans contents to find char position of first instance of link index" links isEmpty ifTrue: [^nil]. sl _ links first. [sl isNil not harPosition: (pos - count)] ifFalse: [self notify: 'cannot accept: multiple link instances'. ^false]. count _ count + 1. pos _ pos + 1]] ifFalse: [pos _ pos + (runs at: i)].. i _ i + 1]. links do: [:sl | (sl charPosition) isNil ifTrue:[self notify: 'cannot accept: missing link instances'. ^false]. (sl linkIndex) isNil ifTrue:[self notify: 'cannot accept: uninstantiated links'. ^false] ]. ^true! ! !TextNode methodsFor: 'link attachment'! addLinkDeand: [(sl linkIndex) ~= linkIndex]] whileTrue: [sl _ sl nextLink]. sl isNil ifTrue: [^nil]. c _ sl charValue. textSize _ contents size. i _ 1. textSize timesRepeat: [ ((contents at: i) = c and: [(contents emphasisAt: i) = (NodeController linkFont)]) ifTrue: [^i]. i _ i + 1].! mergeLinkAttachments | a c t s count r size | "Merges links, a linkedList of linkAttachments, with contents of HyperNode. Modifies linkFont, which is not created until a paragraph editor has been instanciastination: aCharPosition | a c | "make a proposed link destination attachment" a _ LinkAttachment new. a linkIndex: nil. a charPosition: aCharPosition. a versionTime: ((isHistory | (graph linkStyle destinationByVersion)) ifTrue: [timeStamp] ifFalse: [0]). a isInLink: true. c _ Character value: (controller addLinkUsingDestinationIcon: (a versionTime ~= 0)). a charValue: c. linkDestination _ a. self insertAttachment: a. ^c! addLinkSource: aCharPosition | a c | "make a proposed lin$k source attachment" a _ LinkAttachment new. a linkIndex: nil. a charPosition: aCharPosition. a versionTime: ((isHistory | (graph linkStyle sourceByVersion)) ifTrue: [timeStamp] ifFalse: [0]). a isInLink: false. c _ Character value: (controller addLinkUsingSourceIcon: (a versionTime ~= 0)). a charValue: c. linkSource _ a. self insertAttachment: a. ^c! commitLinkDestination: aLinkIndex timeStamp: aTimeStamp icon: aString | charPos | linkDestination linkIndex: aLinkIndex. isHistory iil]. s linkIndex: (r at: 1). isHistory ifTrue: [s versionTime: (r at: 2)] ifFalse: [s versionTime: 0]. isHistory ifFalse: [timeStamp _ r at: 2]. r _ controller addLinkIcon: s. s charValue: r. unique ifFalse: [self insertAttachment: s]. self duplicateLinkAttributesFrom: linkIndex for: s. ^r! duplicateLinkAttributesFrom: linkIndex for: aNewLinkAtt | r numPairs i sv iv rpc | (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc getLinkAttributes: linkIndex versionTime: (aNewLinkAtt versionTfFalse: [timeStamp _ aTimeStamp]. charPos _ controller linkOffsetCharPos: (linkDestination charValue). self destroyLinkDestination. controller newDestinationLink: aLinkIndex version: aTimeStamp icon: aString at: charPos.! commitLinkSource: aLinkIndex timeStamp: aTimeStamp icon: aString | charPos | linkSource linkIndex: aLinkIndex. isHistory ifFalse: [timeStamp _ aTimeStamp]. charPos _ controller linkOffsetCharPos: (linkSource charValue). self destroyLinkSource. controller newSourceLink: aLinime). r = nil ifTrue: [rpc reportError: 'getLinkAttributes'. ^nil]. numPairs _ r at: 1. i _ 2. [i <= (numPairs + 1)] whileTrue: [ sv _ ''. iv _ 0. ((r at: i) at: 4) ifTrue: [sv _ ((r at: i) at: 3)] ifFalse: [iv _ ((r at: i) at: 3)]. r _ rpc setLinkAttributeValue: (aNewLinkAtt linkIndex) for: ((r at: i) at: 1) as: ((r at: i) at: 4) with: sv with: iv. r = nil ifTrue: [rpc reportError: 'setLinkAttributeValue'. ^nil]. i _ i + 1].! isUnique: sl in: aText | u c l found | "are therekIndex version: aTimeStamp icon: aString at: charPos.! destroyLinkDestination | t1 | self deleteAttachment: linkDestination. controller deleteIcon: (linkDestination charValue). linkDestination _ nil.! destroyLinkSource | t1 | self deleteAttachment: linkSource. controller deleteIcon: (linkSource charValue). linkSource _ nil.! duplicateLink: sl at: aCharPosition | unique linkIndex s r c rpc | "makes a duplicate copy of the link sl, attaching the new one at aCharPosition" unique _ self isUni multiple instances of this link" u _ aText size. c _ sl charValue. l _ NodeController linkFont. found _ false. 1 to: u do: [:i | ((aText at: i) = c and: [(aText emphasisAt: i) = l]) ifTrue: [found ifTrue: [^false]. found _ true]]. ^true! newLink: aLinkIndex asSource: aBoolean version: aTimeStamp icon: aString at: aCharPosition | a c r | "make a proposed link attachment" a _ LinkAttachment new. a linkIndex: aLinkIndex. a charPosition: aCharPosition. a versionTime: ((isHistory | (aBque: sl in: (controller paragraph text). (sl linkIndex isNil) ifTrue: [linkIndex _ sl sameAs] ifFalse: [unique ifTrue: [^nil]. linkIndex _ sl linkIndex]. unique ifTrue: [s _ sl] ifFalse: [s _ sl deepCopy]. aCharPosition > (contents size) ifTrue: [s charPosition: (contents size)] ifFalse: [s charPosition: aCharPosition]. s sameAs: linkIndex. (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc copyLink: s from: self. r = nil ifTrue: [rpc reportError: 'copyLink'. ^noolean & (graph linkStyle sourceByVersion)) | ((aBoolean not) & (graph linkStyle destinationByVersion))) ifTrue: [aTimeStamp] ifFalse: [0]). a isInLink: (aBoolean not). aString isNil ifTrue: [ c _ Character value: (aBoolean ifTrue: [controller addLinkUsingSourceIcon: (a versionTime ~= 0)] ifFalse: [controller addLinkUsingDestinationIcon: (a versionTime ~= 0)])] ifFalse: [c _ Character value: (aBoolean ifTrue: [controller addLinkIconForString: aString a$sSource: true forVersion: ((a versionTime ~= 0))] ifFalse: [controller addLinkIconForString: aString asSource: false forVersion: ((a versionTime ~= 0))]). r _ Array new: 2. r at: 1 put: true. r at: 2 put: aString. a attributeValues: r]. a charValue: c. self insertAttachment: a. ^c! ! !Pen methodsFor: 'accessing'! direction "Answer the receiver's current direction. 0 is towards the right of the screen." ^direction! ! !FileStream methodsFor: 'accessing'! nextPutAll: aCollectioscriptor. fileDescriptor _ nil. filePosition _ self position. readLimit _ writeLimit _ position _ 0! openReadOnly: fd "Open the receiver's file for reading only. Restore its position." fileDescriptor _ fd. fileMode _ #ReadOnly. collection _ ByteArray new: 1024. filePosition _ readLimit _ writeLimit _ position _ 0.! openWriteOnly: fd "Open the receiver's file for writing only. Restore its position." fileDescriptor _ fd. fileMode _ #WriteOnly. collection _ ByteArray new: 1024. filePosition _n "Write the elements of aCollection onto the receiver. If aCollection will fit in the receiver's buffer then buffer it. Otherwise write it directly to the receiver's file. If aCollection is of kind other than String or ByteArray (a Set of Characters, for example) write each of its elements individually." | collectionSize | ((aCollection isKindOf: String) or: [aCollection isKindOf: ByteArray]) ifFalse: [^super nextPutAll: aCollection]. writeLimit - position > (collectionSize _ aCollection size readLimit _ writeLimit _ position _ 0.! restIsText "Set the receiver's file to be buffered in text mode. Copy any already buffered data to the new buffer, a String." self isBinary ifTrue: [collection _ (String new: collection size) replaceFrom: 1 to: (readLimit - position) withByteArray: collection startingAt: (position + 1). readLimit _ (readLimit - position). position _ 0]! ! !HyperPipeStream methodsFor: 'override ExternalStream'! nextNumber: n "Answer the next n bytes as a posi) ifTrue: [^collection replaceFrom: position + 1 to: (position _ position + aCollection size) with: aCollection "answer aCollection?" startingAt: 1]. writeLimit > 0 ifTrue: [self flush] ifFalse: [self beginWriting]. writeLimit > collectionSize ifTrue: [self nextPutAll: aCollection] ifFalse: [self writeAccess. SystemCall write: fileDescriptor from: aCollection size: collectionSize. filePosition _ filePosition + collectionSize]. ^aCollection! ! !HyperPipeStream mettive Integer or LargePositiveInteger." | s | n <= 4 ifTrue: [s _ 0. n timesRepeat: [s _ (s bitShift: 8) + self next]. ^s]. s _ LargePositiveInteger new: n. 1 to: n do: [:i | s at: n + 1 - i put: self next]. "reverse order of significance" ^s truncated! ! !PipeWriteStream methodsFor: 'accessing'! nextPut: aCharacterOrByte | aCollection sysCall newSpecies | "Don't buffer data into the pipe. Answer the data written." newSpecies _ self isBinary ifTrue: [ByteArray] ifFalse: [String].hodsFor: 'override FileStream'! cleanUp "close Os file associated with stream" self isOpen ifFalse: [^self]. SystemCall closeFile: fileDescriptor. fileDescriptor _ nil. filePosition _ self position. readLimit _ writeLimit _ position _ 0! close "Disassociate the receiver with its file in mass storage. If write data is buffered, flush it. If read data is buffered, discard it and adjust filePosition to reflect the loss." self isOpen ifFalse: [^self]. self flush. SystemCall closeFile: fileDe aCollection _ newSpecies new: 1. aCollection at: 1 put: aCharacterOrByte. SystemCall write: fileDescriptor from: aCollection size: 1. ^aCharacterOrByte! nextPutAll: aCollection | sysCall size | "Write the contents of the collection to the pipe. Don't buffer data into the pipe." size _ aCollection size. SystemCall write: fileDescriptor from: aCollection size: size.! ! !PipeReadStream methodsFor: 'accessing'! next: anInteger into: aCollection "Copy the next anInteger bytes from the receiver int%o aCollection. Answer aCollection." | howManyRead increment | howManyRead _ 0. [howManyRead < anInteger] whileTrue: [self atEnd ifTrue: [self pad: aCollection from: (howManyRead + 1) to: anInteger. ^aCollection] ifFalse: [increment _ (readLimit - position) min: (anInteger - howManyRead). aCollection replaceFrom: howManyRead + 1 to: (howManyRead _ howManyRead + increment) with: collection startingAt: position + 1. position _ position + increment]]. ^aColld by the symbol, aSymbol, is pressed. Answer the current selection." ^(PopUpMultiMenuContext new withMenu: self) startUp: aSymbol! startUpBlueButton "Display and make a selection from the receiver as long as the blue button is pressed." ^self startUp: #blueButton! startUpRedButton "Display and make a selection from the receiver as long as the red button is pressed." ^self startUp: #redButton! startUpYellowButton "Display and make a selection from the receiver as long as the yellow button iection! nextAvailable | readSize | "Answer a collection containing all available data from the pipe. Answer an empty collection if no data is available." readSize _ readLimit - position + self size. readSize < 0 ifTrue: [self error: 'Trying to read a negative # of chars']. ^self next: readSize! ! !PipeReadStream methodsFor: 'private'! fill | newSpecies size | "Attempt to fill the buffer from the pipe." newSpecies _ self isBinary ifTrue: [ByteArray] ifFalse: [String]. size _ self sizs pressed." ^self startUp: #yellowButton! ! !PopUpMultiMenu methodsFor: 'accessing'! font "answer the receiver's font" ^font! form "answer the receiver's form" ^form! frame "answer the receiver's frame" ^frame! menuArray "answer the array of menus to return" ^menuArray! menuArrayAt: anInteger put: aValue "reset one of the receivers menu pointers" ^menuArray at: anInteger put: aValue! selection ^selection! selection: aNumber selection _ aNumber! valueArray "answer the array of values to e. collection _ newSpecies new: size. (size = 0) ifTrue: [^readLimit _ position _ 0]. readLimit _ SystemCall read: fileDescriptor into: collection. position _ 0! ! !PipeReadStream methodsFor: 'modes'! binary "Set the receiver's file to be buffered in binary mode. Copy any already buffered data to the new buffer, a ByteArray." self isBinary ifFalse: [collection _ (ByteArray new: collection size) replaceFrom: 1 to: position withString: collection startingAt: 1]! text "Set the receiver'return" ^valueArray! ! !PopUpMultiMenu methodsFor: 'private'! form: aForm "resets the receiver's form" form _ aForm.! frame: aQuadrangle "resets the receiver's frame" frame _ aQuadrangle.! fromArray: anArray font: aFont | currentIndex | labelArray _ OrderedCollection new. valueArray _ OrderedCollection new. menuArray _ OrderedCollection new. lineArray _ OrderedCollection new. font _ aFont. currentIndex _ 0. anArray do: [:x | x isEmpty ifTrue: [lineArray add: currentIndex] ifFalses file to be buffered in text mode. Copy any already buffered data to the new buffer, a String." self isBinary ifTrue: [collection _ (String new: collection size) replaceFrom: 1 to: position withByteArray: collection startingAt: 1]! ! !PopUpMultiMenu methodsFor: 'basic control sequence'! startUp "Show the receiver and give control to the user to make a selection." ^self startUp: #anyButton! startUp: aSymbol "Display and make a selection from the receiver as long as the button denote: [currentIndex _ currentIndex + 1. valueArray add: (x at: 2). menuArray add: (x size > 2 ifTrue: [self class fromArray: (x at: 3) font: aFont] ifFalse: [PopUpMultiMenu null]). labelArray add: x first]]. labelArray _ labelArray asArray. valueArray _ valueArray asArray. menuArray _ menuArray asArray. lineArray _ lineArray asArray. selection _ valueArray size // 2. self rescan.! rescan "Cause me to be recreated for system changes like fonts." | style paraStr%ing labelPara cr | cr _ '\' withCRs. style _ TextStyle fontArray: (Array with: font). style alignment: 2. "centered" style gridForFont: 1 withLead: 0. paraString _ (labelArray inject: '' into: [:prev :el | prev, cr, el]) copyWithoutFirst. labelPara _ Paragraph withText: paraString asText style: style. labelPara composeAll. form _ labelPara asForm. frame _ Quadrangle new. frame region: (labelPara compositionRectangle expandBy: 2). frame borderWidth: (1@1 corner: 3@3). lineArray do: [:line  lower _ (change at: 2). lower <= (size + 1) ifTrue: [contents replaceFrom: lower to: (lower - 1) with: t] ifFalse: [(c isAdditionAt: i) ifTrue: [ lower _ (change at: 2). contents replaceFrom: (lower + 1) to: lower with: t] ]]]]. ].! parseDiff: changes into: anInteger anInteger == 1 ifTrue: [changeSet1 _ NodeChangeSet from: changes text: (node1 contents)] ifFalse: [changeSet2 _ NodeChangeSet from: changes text: (node2 contents)].! ! !NodeVersions methodsFor: 'initialize - release'! | form fill: (0 @ (line * font height) extent: (frame width @ 1)) mask: Form black]. "PopUpMultiMenu allInstancesDo: [:x | x rescan]"! ! !MultiActionMenu methodsFor: 'action symbols'! selectorAt: index ^ selectors at: index! setSelectors: selArray selectors _ selArray! ! !NodeDiff methodsFor: 'access'! changeSet1 ^changeSet1! changeSet2 ^changeSet2! node1: aNode node1 _ aNode! node2: aNode node2 _ aNode! ! !NodeDiff methodsFor: 'private'! buildLineMaps changeSet1 buildLineMapFrom: (node1 initialize: versionsArray node: anInteger graph: aHyperGraph | numMajorVersions numMinorVersions s t d minorVersionsPtr p bound k size | "initializes instance of NodeVersions using arrays returned from getNodeVersions RPC" numMajorVersions _ (versionsArray at: 1) size. majorVersions _ Array new: numMajorVersions. p _ versionsArray at: 1. 1 to: numMajorVersions do: [:i | t _ Time fromUnixSeconds: ((p at: i) at: 1). d _ ((t at: 1) printFormat: #(1 2 3 32 2 2)). d _ d, ' ', ((t at: contents). changeSet2 buildLineMapFrom: (node2 contents). changeSet1 compensateRunsForLinks: (node2 links). changeSet1 compensateValuesForLinks: (node1 links). changeSet2 compensateRunsForLinks: (node1 links). changeSet2 compensateValuesForLinks: (node2 links).! mergeDiffOf: anInteger | c cs change size upper lower t contents | t _ Text string: '^' emphasis: 2. anInteger == 1 ifTrue: [contents _ node1 contents. c _ changeSet1] ifFalse: [contents _ node2 contents. c _ changeSet2]. size _ 2) printString). majorVersions at: i put: (Array with: ((p at: i) at: 1) with: (d, ((p at: i) at: 2)))]. minorVersions _ Array new: numMajorVersions. numMinorVersions _ (versionsArray at: 2) size. s _ SortedCollection sortBlock: [:x :y | (x at: 1) >= (y at: 1)]. 1 to: (versionsArray at: 2) size do: [:i | s add: ((versionsArray at: 2) at: i)]. "assert s is an array of minor versions in nonincreasing order of time" minorVersionsPtr _ 1. 1 to: numMajorVersions do: [:i | "assert all minor versicontents size. cs _ c changeSet. 1 to: (cs size) do: [:i | change _ cs at: i. (c isReplacementAt: i) ifTrue: [ lower _ (change at: 2) min: size. upper _ (change at: 3) min: size. lower <= upper ifTrue: [contents emphasizeFrom: lower to: upper with: 3]] ifFalse: [(c isDeletionAt: i) ifTrue: [ lower _ (change at: 2) min: size. upper _ (change at: 3) min: size. lower <= upper ifTrue: [contents emphasizeFrom: lower to: upper with: 2]] ifFalse: [(c isInsertionAt: i) ifTrue: [ onTimes up to minorVersionPtr are processed" p _ minorVersionsPtr. bound _ (majorVersions at: i) at: 1. p <= numMinorVersions ifTrue:[ ((s at: p) at: 1) >= bound ifTrue: [ [(p <= numMinorVersions) and: [(((s at: p) at: 1) >= bound)]] whileTrue: [p _ p + 1]. size _ p - minorVersionsPtr. minorVersions at: i put: (Array new: size). k _ minorVersionsPtr. 1 to: size do: [:j | t _ Time fromUnixSeconds: ((s at: k) at: 1). d _ ((t at: 1) printFormat: #(1 2 3 32 2 2)). & d _ d, ' ', ((t at: 2) printString), ': '. (minorVersions at: i) at: j put: (Array with: ((s at: k) at: 1) with: (d, ((s at: k) at: 2))). k _ k + 1]. minorVersionsPtr _ p]]]. majorSel _ 0. minorSel _ 0. nodeIndex _ anInteger. graph _ aHyperGraph. context _ aHyperGraph currentContext. view _ nil! ! !NodeVersions methodsFor: 'converting'! convertMajorVersionsTimes | size r | size _ majorVersions size. r _ Array new: size. 1 to: size do: [:i | r at: i put: ((majorVersions  d _ Document new. d versionTime: versionTime; hyperGraph: graph. d root: (Array with: nodeIndex with: versionTime with: name). DocumentView openOn: d.! browseGraph | versionTime rpc | versionTime _ self selectedVersionTime. versionTime = nil ifTrue: [versionTime _ 0]. "current version" (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. Graph openOn: graph at: nodeIndex when: versionTime nodePredicate: '*' linkPredicate: '*'! browseNode | versionTime rpc | versionTime _ self selectedVersiat: i) at: 2)]. ^r! convertMinorVersionsTimes | size r s | majorSel = 0 ifTrue: [^nil]. size _ (minorVersions at: majorSel) size. r _ Array new: size. 1 to: size do: [:i | r at: i put: (((minorVersions at: majorSel) at: i) at: 2)]. ^r! ! !NodeVersions methodsFor: 'private'! selectedVersionTime majorSel = 0 ifTrue: [^nil]. view isMajor ifTrue: [^(majorVersions at: majorSel) at: 1] ifFalse: [minorSel = 0 ifTrue: [^(majorVersions at: majorSel) at: 1] ifFalse: [^((minorVersions at: majorSonTime. versionTime = nil ifTrue: [versionTime _ 0]. "current version" (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. Node open: nodeIndex versionTime: versionTime in: graph! changedMajorSelection: sel | selIndex | view ~= nil ifTrue: [ sel = nil ifTrue: [selIndex _ 0] ifFalse: [selIndex _ view firstSubView getList indexOf: sel]. majorSel _ selIndex. view updateMinorView: selIndex].! changedMinorSelection: sel | selIndex | view ~= nil ifTrue: [ sel = nil ifTrue: [selIndexel) at: minorSel) at: 1]].! ! !NodeVersions methodsFor: 'list messages'! browseAttributes | versionTime rpc | versionTime _ self selectedVersionTime. versionTime = nil ifTrue: [versionTime _ 0]. "current version" (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. Attribute openOnNode: nodeIndex versionTime: versionTime in: graph! browseDifferences | versionTime rpc | versionTime _ self selectedVersionTime. versionTime = nil ifTrue: [Transcript cr; show: 'Must select a version time.'. view flas _ 0] ifFalse: [selIndex _ view lastSubView getList indexOf: sel]. minorSel _ selIndex].! menu ^ YellowMenu! update | r v rpc | (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc getNodeVersions: nodeIndex. r = nil ifTrue: [rpc reportError: 'getNodeVersions'. ^nil]. v _ view. self initialize: r node: nodeIndex graph: graph. view _ v. Cursor normal show. self changed: nil.! ! !NodeVersions methodsFor: 'access'! context ^context! graph ^graph! nodeIndex ^nodeIndex! h. ^nil]. (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. NodeDiff open: nodeIndex from: 0 to: versionTime in: graph.! browseDocument | versionTime d r name rpc | versionTime _ self selectedVersionTime. versionTime = nil ifTrue: [versionTime _ 0]. "current version" (rpc _ graph rpcFor: context) isNil ifTrue: [^nil]. r _ rpc getNodeAttributeValue: nodeIndex for: (graph iconNameIndex) at: versionTime. r isNil ifTrue: [^nil]. name _ (r at: 1) ifTrue: [r at: 2] ifFalse: [nil]. d _ Document new.view: aNodeVersionsView view _ aNodeVersionsView! ! !HyperIO methodsFor: 'writing graphs'! fileOutGraphNodes: aPred1 links: aPred2 toFile: aString at: root for: versionTime depth: anInteger "Outputs to file named aString2, the contents of the nodes traversed using predicates aPred1 and aPred2" | r u n f c | version _ versionTime. f _ FileStream newFileNamed: aString. f text. r _ rpc linearizeGraph: root at: version depth: anInteger nodePredicate: aPred1 linkPredicate: aPred2 nodeAttributes&: nil linkAttributes: nil. r isNil ifTrue: [f close. rpc reportError: 'linearizeGraph'. ^nil]. outFile _ f. lastChar _ Character lf. self buildLinkDict: (r at: 2). nodes _ r at: 1. (self fileOutNode: 1 inLink: nil) isNil ifTrue: [^nil]. self fileOutCrossLinks. f close.! printOutGraphNodes: aPred1 links: aPred2 toFile: aString at: root for: versionTime depth: anInteger "Outputs to file named aString, the contents of the nodes traversed using predicates aPred1 and aPred2" | r u n f c | versstart _ self skipIfEolIn: contents at: start]. end _ (l at: 2) - 1. start < end ifTrue: [ self print: contents from: start to: end. start _ end + 1. lastChar _ contents at: end. start _ self skipIfEolIn: contents at: start]. (((l at: 3) not) & (nextNode <= (nodes size)) and: [(((nodes at: nextNode) at: 1) = toNode)]) ifTrue: [ r _ self fileOutNode: nextNode inLink: l. r isNil ifTrue: [^nil]. nextNode _ r at: 1. (r at: 2) ifFalseion _ versionTime. f _ FileStream newFileNamed: aString. f text. r _ rpc linearizeGraph: root at: version depth: anInteger nodePredicate: aPred1 linkPredicate: aPred2 nodeAttributes: nil linkAttributes: nil. r isNil ifTrue: [f close. rpc reportError: 'linearizeGraph'. ^nil]. outFile _ f. lastChar _ Character lf. self buildLinkDict: (r at: 2). nodes _ r at: 1. (self printOutNode: 1 inLink: nil) isNil ifTrue: [^nil]. f close.! ! !HyperIO methodsFor: 'writing nodes'! fileOutNode: index inLin: [ self lastCharEol ifFalse: [outFile nextPutAll: lfString]. (links at: (l at: 1)) at: 3 put: true. outFile nextPutAll: ('.AT ',((l at: 1) printStringRadix: 10), ' s',lfString). lastChar _ Character lf]] ifFalse: [ (myInLink isNil or: [((l at: 1) ~= (myInLink at: 1))]) ifTrue: [ self lastCharEol ifFalse: [outFile nextPutAll: lfString]. (l at: 3) ifTrue: [c _ ' d'. (links at: (l at: 1)) at: 2 put: true] ifFalse: [c _k: inLink | r n myLinks contents nextNode start toNode lfString end c myInLink | n _ nodes at: index. r _ rpc openNode: (n at: 1) versionTime: version numNodeAttributes: 0 nodeAttributeIndices: nil numLinkAttributes: 0 linkAttributeIndices: nil. r isNil ifTrue: [rpc reportError: 'openNode'. ^nil]. lfString _ String new: 1. lfString at: 1 put: (Character lf). contents _ r at: 5. self lastCharEol ifFalse: [outFile nextPutAll: lfString]. ((inLink notNil) and: [((self inLinkCharPos: (inLink a ' s'. (links at: (l at: 1)) at: 3 put: true]. outFile nextPutAll: ('.AT ',((l at: 1) printStringRadix: 10),c,lfString). lastChar _ Character lf]] ]]. end _ contents size. start < end ifTrue: [self lastCharEol ifTrue: [start _ self skipIfEolIn: contents at: start]. self print: contents from: start to: end. lastChar _ contents at: end]. self lastCharEol ifFalse: [outFile nextPutAll: lfString]. outFile nextPutAll: ('.PO',lfString). lastChar _ Charat: 1) from: (r at: 3)) = 1)]) ifTrue: [outFile nextPutAll: ('.PL',lfString). myInLink _ inLink] ifFalse: [outFile nextPutAll: ('.PU',lfString). myInLink _ nil]. lastChar _ Character lf. self fileOutAttributesForNode: (n at: 1). myInLink notNil ifTrue: [self fileOutAttributesForLink: (myInLink at: 1)]. start _ 1. myLinks _ self buildNodeLinkList: (r at: 3). nextNode _ index + 1. myLinks isNil ifFalse: [ myLinks do: [:l | toNode _ (links at: (l at: 1)) at: 1. self lastCharEol ifTrue: [cter lf. ^Array with: nextNode with: (myInLink notNil)! printOutNode: index inLink: inLink | r n myLinks contents nextNode start toNode end | n _ nodes at: index. r _ rpc openNode: (n at: 1) versionTime: version numNodeAttributes: 0 nodeAttributeIndices: nil numLinkAttributes: 0 linkAttributeIndices: nil. r isNil ifTrue: [rpc reportError: 'openNode'. ^nil]. myLinks _ self buildNodeOutLinkList: (r at: 3). contents _ r at: 5. inLink notNil ifTrue: [start _ self inLinkCharPos: (inLink at: 1)' from: (r at: 3)] ifFalse: [start _ 1]. nextNode _ index + 1. myLinks isNil ifFalse: [ myLinks do: [:l | toNode _ (links at: (l at: 1)) at: 1. ((nextNode <= (nodes size)) and: [((nodes at: nextNode) at: 1) = toNode]) ifTrue: [self lastCharEol ifTrue: [start _ self skipIfEolIn: contents at: start]. end _ (l at: 2) - 1. start < end ifTrue: [ self print: contents from: start to: end. start _ end + 1. lastChar _ contents at: end]. nextNode _ self tStringRadix: 10)]. outFile nextPutAll: lfString]. lastChar _ Character lf. ^true! ! !HyperIO methodsFor: 'private'! buildLinkDict: linkInfo | a v | links _ Dictionary new. linkInfo do: [:l | v _ Array with: (l at: 4) "to node index" with: false "is to char position marked" with: false. "is from char position marked" a _ Association key: (l at: 1) value: v. links add: a]! buildNodeLinkList: nodeLinks | l r | nodeLinks isNil ifTrue: [^nil]. l _ SortedCollection printOutNode: nextNode inLink: l. nextNode isNil ifTrue: [^nil]]]]. end _ contents size. start < end ifTrue: [self lastCharEol ifTrue: [start _ self skipIfEolIn: contents at: start]. self print: contents from: start to: end. lastChar _ contents at: end]. ^nextNode! ! !HyperIO methodsFor: 'writing attributes'! fileOutAttributesForLink: linkIndex | a lfString ap numPairs | . (rpc _ self rpc) isNil ifTrue: [^nil]. a _ rpc getLinkAttributes: linkIndex versionTime: version. sortBlock: [:a :b | (a at: 2) < (b at: 2)]. nodeLinks do: [:la | (links includesKey: (la linkIndex)) ifTrue: [ r _ Array with: (la linkIndex) with: (la charPosition) with: (la isInLink). l add: r]]. ^l! buildNodeOutLinkList: nodeLinks | l r | nodeLinks isNil ifTrue: [^nil]. l _ SortedCollection sortBlock: [:a :b | (a at: 2) < (b at: 2)]. nodeLinks do: [:la | (links includesKey: (la linkIndex)) ifTrue: [ la isInLink ifFalse: [ r _ Array with: (la linkIndex) a isNil ifTrue: [rpc reportError: 'getLinkAttributes'. ^false]. numPairs _ (a at: 1). numPairs = 0 ifTrue: [^true]. lfString _ String new: 1. lfString at: 1 put: (Character lf). 2 to: (numPairs + 1) do: [:i | ap _ (a at: i). outFile nextPutAll: '.LA ',(ap at: 2). (ap at: 4) ifTrue: [outFile nextPutAll: ' s ',(ap at: 3)] ifFalse: [outFile nextPutAll: ' i ', ((ap at: 3) printStringRadix: 10)]. outFile nextPutAll: lfString]. lastChar _ Character lf. ^true! fileOutAttributesFo with: (la charPosition). l add: r]]]. ^l! fileOutCrossLinks | lfString v | lfString _ String new: 1. lfString at: 1 put: (Character lf). self lastCharEol ifFalse: [outFile nextPutAll: lfString]. lastChar _ Character lf. links associations do: [:a | v _ a value. ((v at: 2) & (v at: 3)) ifTrue: [ outFile nextPutAll: ('.LN ', (a key printStringRadix: 10), lfString). self fileOutAttributesForLink: (a key)] ].! inLinkCharPos: linkIndex from: nodeLinks nodeLinks isNil ifTrue: rNode: nodeIndex | a lfString ap numPairs | . a _ rpc getNodeAttributes: nodeIndex versionTime: version. a isNil ifTrue: [rpc reportError: 'getNodeAttributes'. ^false]. numPairs _ (a at: 1). numPairs = 0 ifTrue: [^true]. lfString _ String new: 1. lfString at: 1 put: (Character lf). 2 to: (numPairs + 1) do: [:i | ap _ (a at: i). outFile nextPutAll: '.NA ',(ap at: 2). (ap at: 4) ifTrue: [outFile nextPutAll: ' s ',(ap at: 3)] ifFalse: [outFile nextPutAll: ' i ', ((ap at: 3) prin[^1]. nodeLinks do: [:la | (la linkIndex) = linkIndex ifTrue: [(la charPosition) = 0 ifTrue: [^1] ifFalse: [^la charPosition]]]. ^1! lastCharEol ^((lastChar = (Character cr)) or: [(lastChar = (Character lf))])! print: contents from: start to: end | c cr lf stop s | s _ contents size. s < start ifTrue: [^nil]. stop _ end > s ifTrue: [s] ifFalse: [end]. c _ contents copyFrom: start to: end. "convert cr to lf" cr _ Character cr. lf _ Character lf. c _ c collect: [:char | char = cr ifTrue: [lf]' ifFalse: [char]]. outFile nextPutAll: c.! skipIfEolIn: contents at: start start > (contents size) ifTrue: [^start]. (((contents at: start) = (Character cr)) or: [((contents at: start) = (Character lf))]) ifTrue: [^start + 1]. ^start! ! !HyperIO methodsFor: 'access'! rpc: aHyperRPC rpc _ aHyperRPC! ! !SearchStyle methodsFor: 'accessing'! endingTime ^(endTime unixVersionTime)! endTime ^endTime! hyperGraph ^hyperGraph! hyperGraph: aHyperGraph hyperGraph _ aHyperGraph! searchEngineMade ^seakOptions! ! !LinkStyle methodsFor: 'accessing'! destinationByVersion ^destinationByVersion! destinationByVersion: aBoolean destinationByVersion _ aBoolean. self changed: #destinationByVersion.! hyperGraph ^hyperGraph! hyperGraph: aHyperGraph hyperGraph _ aHyperGraph! sourceByVersion ^sourceByVersion! sourceByVersion: aBoolean sourceByVersion _ aBoolean. self changed: #sourceByVersion.! view: aView view _ aView! ! !LinkStyle methodsFor: 'initialization'! initialize sourceByVersion _ DefaultSourrchEngineMade! searchEngineMade: aBoolean searchEngineMade _ aBoolean! searchString ^searchString! searchString: aString searchString = aString ifFalse: [searchEngineMade _ false. searchString _ aString.]! searchStringText ^searchString asText! searchStringText: aText self searchString: aText asString. ^true! startingTime ^(startTime unixVersionTime)! startTime ^startTime! view: aView view _ aView! ! !SearchStyle methodsFor: 'initialization'! initialize searchString _ ''. searchEngineMceByVersion. destinationByVersion _ DefaultDestinationByVersion.! open view isNil ifTrue: [LinkStyleView openOn: self]. view controller open.! release view _ nil. super release! ! !GraphStyle methodsFor: 'operations'! defineGraphParams proceed _ false. actionTaken _ false. Cursor normal show. GraphStyleView requestOn: self. Cursor execute show. ^proceed! ! !GraphStyle methodsFor: 'initialize - release'! initialize hostMachineName _ DefaultHostMachine. hostDirectory _ DefaultHostDirectory. pade _ false. startTime _ TimeSpecifier now current. endTime _ TimeSpecifier now current.! openWithInvoker: aModel find: aMsg view isNil ifTrue: [SearchStyleView openOn: self invoker: aModel findMsg: aMsg]. view invoker: aModel; findMsg: aMsg. view controller open.! release view _ nil. super release! ! !SearchStyle methodsFor: 'menus'! yellowButtonMenu ^YellowButtonMenu! ! !LinkStyle methodsFor: 'list messages'! changeDestinationOption: sel sel = nil ifTrue: [destinationByVersion _ DefaultDestrotectionMask _ DefaultProtectionMask. ^self! ! !GraphStyle methodsFor: 'menus'! yellowButtonMenu ^YellowButtonMenu! ! !GraphStyle methodsFor: 'access'! actionTaken ^actionTaken! actionTaken: aBoolean actionTaken _ aBoolean! directoryText ^hostDirectory asText! directoryText: aText hostDirectory _ aText asString. ^true! hostDirectory ^hostDirectory! hostDirectory: aString hostDirectory _ aString! hostMachineName ^hostMachineName! hostMachineName: aString hostMachineName _ aString! hostMachineNainationByVersion] ifFalse: [destinationByVersion _ (sel = 'ParticularVersion')].! changeSourceOption: sel sel = nil ifTrue: [sourceByVersion _ DefaultSourceByVersion] ifFalse: [sourceByVersion _ (sel = 'ParticularVersion')].! initialDestinationOption destinationByVersion ifTrue: [^LinkOptions at: 1] ifFalse: [^LinkOptions at: 2]! initialSourceOption sourceByVersion ifTrue: [^LinkOptions at: 1] ifFalse: [^LinkOptions at: 2]! listDestinationOptions ^LinkOptions! listSourceOptions ^LinmeText ^hostMachineName asText! hostMachineNameText: aText hostMachineName _ aText asString. ^true! proceed ^proceed! proceed: aBoolean proceed _ aBoolean! protectionMask ^protectionMask! protectionMask: anInteger protectionMask _ anInteger! ! !SequenceableCollection methodsFor: 'accessing'! nextToLast "Answer the next-to-last element of the receiver." ^self at: self size - 1! ! !SequenceableCollection methodsFor: 'copying'! copyWithoutFirst "Answer a copy the receiver, without the first elemen