[comp.lang.smalltalk] cursor movement in st-80 v2.3

bruce@servio.UUCP (Bruce Schuchardt) (06/30/89)

Here is some code that enables use of cursor keys to move the
caret in ParagraphEditor and its subclasses.  The key bindings
are for a Mac adb keyboard - you will need to remap for other
keyboards (see the key code definitions in your manual, add one
to the code generated by your cursor key and replace my value
with yours).

This code also enables 

  use of shift key to extend selection (for both mouse and keyboard)
  
  F1 as "undo"
  F2 as "cut"
  F3 as "copy"
  F4 as "paste"
  F5 as "accept"
  F6 as "cancel"

  F9 as "do it"
  F10 as "print it"
  F11 as "inspect it"

One kernel method is overwritten - processRedButton.  You should
make sure that this does not conflict with changes you may have made
to this method in ParagraphEditor.


----------


!ParagraphEditor methodsFor: 'bjs functions'!

fileOutBJSFunctions
  "ParagraphEditor basicNew fileOutBJSFunctions"
  | x |
  x _ FileStream newFileNamed: 'bjsParagraphFunctions.st'.
  ParagraphEditor fileOutCategory: 'bjs functions' asSymbol
      on: x moveSource: false toFile: 0.
  x nextChunkPut: 'ParagraphEditor basicNew installBJSfunctions'.
  x close!

installBJSfunctions
  "ParagraphEditor basicNew installBJSfunctions"
  "This mapping is for the Macintosh keyboard"

Keyboard
   at: 29 put: #prevChar:key:;
   at: 30 put: #nextChar:key:;
   at: 31 put: #prevLine:key:;
   at: 32 put: #nextLine:key:;

   at: 16r92 put: #undo:key:;  "F1"
   at: 16r93 put: #cut:key:;    "F2"
   at: 16r94 put: #copy:key:;  "F3"
   at: 16r95 put: #paste:key:; "F4"

   at: 16r96 put: #accept:key:;  "F5"
   at: 16r97 put: #cancel:key:;   "F6"

   at: 16r9A put: #doIt:key:;  "F9"
   at: 16r9B put: #printIt:key:; "F10"
   at: 16r9C put: #inspectIt:key:; "F11"!


doIt: stream key: code
  (self respondsTo: #doIt) ifTrue: [
    self closeTypeIn; doIt
    ]
  ifFalse: [
    view flash
    ].
  ^true!

printIt: stream key: code
  (self respondsTo: #printIt) ifTrue: [
    self closeTypeIn; printIt
    ]
  ifFalse: [
    view flash
    ].
  ^true!

inspectIt: stream key: code
  (self respondsTo: #inspectIt) ifTrue: [
    self closeTypeIn; inspectIt
    ]
  ifFalse: [
    view flash
    ].
  ^true!

nextChar: characterStream key: aChar
  "Jump typing cursor over a close-bracket character"
  | stopIndex block |
   stopBlock character isNil ifTrue: [ "handle nil character after cuts"
      stopBlock _ paragraph characterBlockForIndex: stopBlock stringIndex
      ].
  stopBlock character notNil ifTrue: [
    stopIndex _ stopBlock stringIndex.
    self deselect.
    block _ paragraph characterBlockForIndex: stopIndex+1.
    block topLeft > stopBlock topLeft ifTrue: [ "check for scrolling"
      block topLeft y + paragraph textStyle baseline >
        paragraph height ifTrue: [
        paragraph scrollBy: paragraph textStyle lineGrid.
        startBlock _ paragraph characterBlockForIndex: startBlock stringIndex.
        stopBlock _ paragraph characterBlockForIndex: stopBlock stringIndex
        block _ paragraph characterBlockForIndex: block stringIndex.
        self updateMarker
        ]
      ].
    sensor leftShiftDown ifTrue: [
      stopBlock _ block.
      ]
    ifFalse: [
      startBlock _ stopBlock _ block.
      ].
    beginTypeInBlock _ startBlock copy.
    self select
    ]
  ifFalse: [
    self select
    ].
  self setEmphasisHere.
  ^ true!

nextLine: characterStream key: aChar
  " "
  |  block |
  self deselect.
  (stopBlock bottomLeft y + paragraph textStyle lineGrid) >
    paragraph compositionRectangle corner y     ifTrue: [
    paragraph scrollBy: paragraph textStyle lineGrid.
    startBlock _ paragraph characterBlockForIndex: startBlock stringIndex.
    stopBlock _ paragraph characterBlockForIndex: stopBlock stringIndex.
    self updateMarker
    ].
  block _ paragraph characterBlockAtPoint: stopBlock topLeft +
      (0 @ (paragraph textStyle lineGrid + 1)).
  sensor leftShiftDown ifTrue: [
    stopBlock _ block
    ]
  ifFalse: [
    stopBlock _ startBlock _ block
    ].
  beginTypeInBlock _ startBlock copy.
  self select.
  self setEmphasisHere.
  ^true!

prevChar: characterStream key: aChar
  "Jump typing cursor over a close-bracket character"
  | startIndex block |
  startBlock stringIndex > 1 ifTrue:    [
    startIndex _ startBlock stringIndex.
    self deselect.
    block _ paragraph characterBlockForIndex: startIndex-1.
    block topLeft y < startBlock topLeft y ifTrue: [ "check for scrolling"
      block topLeft y < paragraph compositionRectangle origin y ifTrue: [
        paragraph scrollBy: paragraph textStyle lineGrid negated.
        startBlock _ paragraph characterBlockForIndex: startBlock stringIndex.
        stopBlock _ paragraph characterBlockForIndex: stopBlock stringIndex.
        block _ paragraph characterBlockForIndex: block stringIndex.
        self updateMarker
      ]  ].
    sensor leftShiftDown ifTrue: [
      startBlock _ block
      ]
    ifFalse: [
      startBlock _ stopBlock _ block.
      ].
    beginTypeInBlock _ startBlock copy.
    self select
    ]
  ifFalse:  [
    self select
    ].
  self setEmphasisHere.
  ^ true!

prevLine: characterStream key: aChar
  " "
|  block |
self deselect.
(startBlock topLeft y - paragraph textStyle lineGrid) <
    paragraph compositionRectangle origin y      ifTrue: [
  paragraph scrollBy: paragraph textStyle lineGrid negated.
  startBlock _ paragraph characterBlockForIndex: startBlock stringIndex.
  stopBlock _ paragraph characterBlockForIndex: stopBlock stringIndex.
  self updateMarker
  ].
block _ paragraph characterBlockAtPoint: startBlock topLeft -
    (0 @ (paragraph textStyle lineGrid - 1)).
sensor leftShiftDown ifTrue: [
  startBlock _ block
  ]
ifFalse: [
  startBlock _ stopBlock _ block
  ].
beginTypeInBlock _ startBlock copy.
self select.
self setEmphasisHere.
^true!

processRedButton
    "The user pressed a red mouse button, meaning create a new text selection.
    Highlighting the selection is carried out by the paragraph itself.  Double
    clicking causes a selection of the area between the nearest enclosing
    delimitors;  extension is based on both ends if different."

    | selectionBlocks block1 block2 |
    self deselect.
    self closeTypeIn.
    selectionBlocks _ paragraph mouseSelect: startBlock to: stopBlock.
    selectionShowing _ true.
    sensor leftShiftDown ifTrue: [
        block1 _ selectionBlocks at: 1.
        block2 _ selectionBlocks at: 2.
        block1 = block2 ifTrue: [
            paragraph displayCaretForBlock: block1.
            block1 <= startBlock ifTrue: [ startBlock _ block1 ]
            ifFalse: [ stopBlock _ block1 ].
            ]
        ifFalse: [
            paragraph reverseFrom: block1 to: block2.
            block1 < startBlock ifTrue: [ startBlock _ block1 ].
            block2 > stopBlock ifTrue: [ stopBlock _ block2 ]
            ].
        paragraph reverseFrom: startBlock to: stopBlock.
        selectionShowing _ true.
        ]
    ifFalse: [
        startBlock _ selectionBlocks at: 1.
        stopBlock _ selectionBlocks at: 2
        ].
    self updateMarker.
    self setEmphasisHere!

!ParagraphEditor basicNew installBJSfunctions!

----------
-- 
 --------                                --------------
| Bruce Schuchardt          Ph: (503) 629-8383         |
| Beaverton, OR           uucp: ...ogccse!servio!bruce |
 --------------                                --------