EditTextView.st
branchdelegated_gc
changeset 5023 a18a03c5c572
child 5085 52e9f87d45c8
child 5087 001f9ac320b2
child 5131 f18ec7b3199b
equal deleted inserted replaced
-1:000000000000 5023:a18a03c5c572
       
     1 "
       
     2  COPYRIGHT (c) 1989 by Claus Gittinger
       
     3               All Rights Reserved
       
     4 
       
     5  This software is furnished under a license and may be used
       
     6  only in accordance with the terms of that license and with the
       
     7  inclusion of the above copyright notice.   This software may not
       
     8  be provided or otherwise made available to, or used by, any
       
     9  other person.  No title to or ownership of the software is
       
    10  hereby transferred.
       
    11 "
       
    12 'From Smalltalk/X, Version:6.2.3.0 on 18-02-2014 at 18:37:41'                   !
       
    13 
       
    14 "{ Package: 'stx:libwidg' }"
       
    15 
       
    16 TextView subclass:#EditTextView
       
    17 	instanceVariableNames:'cursorLine cursorVisibleLine cursorCol cursorShown
       
    18 		prevCursorState readOnly modifiedChannel fixedSize exceptionBlock
       
    19 		cursorFgColor cursorBgColor cursorNoFocusFgColor cursorType
       
    20 		cursorTypeNoFocus typeOfSelection lastAction replacing
       
    21 		showMatchingParenthesis hasKeyboardFocus acceptAction lockUpdates
       
    22 		tabMeansNextField autoIndent insertMode editMode trimBlankLines
       
    23 		wordWrap replacementWordSelectStyle acceptChannel acceptEnabled
       
    24 		st80Mode disableIfInvisible cursorMovementWhenUpdating learnMode
       
    25 		learnedMacro cursorLineHolder cursorColHolder tabRequiresControl
       
    26 		undoSupport lastStringFromReplaceForNextSearch
       
    27 		lastReplacementInfo completionSupport codeAspectHolder'
       
    28 	classVariableNames:'DefaultCursorForegroundColor DefaultCursorBackgroundColor
       
    29 		DefaultCursorType DefaultCursorNoFocusForegroundColor
       
    30 		DefaultCursorTypeNoFocus LastColumnNumberForSort Macros'
       
    31 	poolDictionaries:''
       
    32 	category:'Views-Text'
       
    33 !
       
    34 
       
    35 Object subclass:#EditAction
       
    36 	instanceVariableNames:'userFriendlyInfo'
       
    37 	classVariableNames:''
       
    38 	poolDictionaries:''
       
    39 	privateIn:EditTextView
       
    40 !
       
    41 
       
    42 EditTextView::EditAction subclass:#DeleteRange
       
    43 	instanceVariableNames:'line1 col1 line2 col2'
       
    44 	classVariableNames:''
       
    45 	poolDictionaries:''
       
    46 	privateIn:EditTextView
       
    47 !
       
    48 
       
    49 EditTextView::EditAction subclass:#DeleteCharacters
       
    50 	instanceVariableNames:'line col1 col2'
       
    51 	classVariableNames:''
       
    52 	poolDictionaries:''
       
    53 	privateIn:EditTextView
       
    54 !
       
    55 
       
    56 Object subclass:#EditMode
       
    57 	instanceVariableNames:''
       
    58 	classVariableNames:''
       
    59 	poolDictionaries:''
       
    60 	privateIn:EditTextView
       
    61 !
       
    62 
       
    63 EditTextView::EditMode subclass:#InsertAndSelectMode
       
    64 	instanceVariableNames:''
       
    65 	classVariableNames:''
       
    66 	poolDictionaries:''
       
    67 	privateIn:EditTextView::EditMode
       
    68 !
       
    69 
       
    70 EditTextView::EditMode subclass:#InsertMode
       
    71 	instanceVariableNames:''
       
    72 	classVariableNames:''
       
    73 	poolDictionaries:''
       
    74 	privateIn:EditTextView::EditMode
       
    75 !
       
    76 
       
    77 EditTextView::EditMode subclass:#OverwriteMode
       
    78 	instanceVariableNames:''
       
    79 	classVariableNames:'InsertMode OverwriteMode InsertAndSelectMode'
       
    80 	poolDictionaries:''
       
    81 	privateIn:EditTextView::EditMode
       
    82 !
       
    83 
       
    84 Query subclass:#ExecutingMacroQuery
       
    85 	instanceVariableNames:''
       
    86 	classVariableNames:''
       
    87 	poolDictionaries:''
       
    88 	privateIn:EditTextView
       
    89 !
       
    90 
       
    91 Object subclass:#LastReplacementInfo
       
    92 	instanceVariableNames:'lastReplacement lastStringToReplace lastReplaceWasMatch
       
    93 		lastReplaceIgnoredCase stillCollectingInput previousReplacements'
       
    94 	classVariableNames:''
       
    95 	poolDictionaries:''
       
    96 	privateIn:EditTextView
       
    97 !
       
    98 
       
    99 EditTextView::EditAction subclass:#PasteString
       
   100 	instanceVariableNames:'line col string selected'
       
   101 	classVariableNames:''
       
   102 	poolDictionaries:''
       
   103 	privateIn:EditTextView
       
   104 !
       
   105 
       
   106 EditTextView::EditAction subclass:#ReplaceCharacter
       
   107 	instanceVariableNames:'line col character'
       
   108 	classVariableNames:''
       
   109 	poolDictionaries:''
       
   110 	privateIn:EditTextView
       
   111 !
       
   112 
       
   113 EditTextView::EditAction subclass:#ReplaceCharacters
       
   114 	instanceVariableNames:'line col1 col2 characters'
       
   115 	classVariableNames:''
       
   116 	poolDictionaries:''
       
   117 	privateIn:EditTextView
       
   118 !
       
   119 
       
   120 EditTextView::EditAction subclass:#ReplaceContents
       
   121 	instanceVariableNames:'text'
       
   122 	classVariableNames:''
       
   123 	poolDictionaries:''
       
   124 	privateIn:EditTextView
       
   125 !
       
   126 
       
   127 EditTextView::EditAction subclass:#ReplaceLine
       
   128 	instanceVariableNames:'line text'
       
   129 	classVariableNames:''
       
   130 	poolDictionaries:''
       
   131 	privateIn:EditTextView
       
   132 !
       
   133 
       
   134 EditTextView::EditAction subclass:#ReplaceLines
       
   135 	instanceVariableNames:'line text'
       
   136 	classVariableNames:''
       
   137 	poolDictionaries:''
       
   138 	privateIn:EditTextView
       
   139 !
       
   140 
       
   141 !EditTextView class methodsFor:'documentation'!
       
   142 
       
   143 copyright
       
   144 "
       
   145  COPYRIGHT (c) 1989 by Claus Gittinger
       
   146               All Rights Reserved
       
   147 
       
   148  This software is furnished under a license and may be used
       
   149  only in accordance with the terms of that license and with the
       
   150  inclusion of the above copyright notice.   This software may not
       
   151  be provided or otherwise made available to, or used by, any
       
   152  other person.  No title to or ownership of the software is
       
   153  hereby transferred.
       
   154 "
       
   155 !
       
   156 
       
   157 documentation
       
   158 "
       
   159     a view for editable text - adds editing functionality to TextView
       
   160     Also, it adds accept functionality, and defines a new actionBlock:
       
   161     acceptAction to be performed for accept
       
   162 
       
   163     If used with a model, this is informed by sending it a changeMsg with
       
   164     the current contents as argument.
       
   165     (however, it is possible to define both changeMsg and acceptAction)
       
   166 
       
   167     Please read the historic notice in the ListView class.
       
   168 
       
   169     [Instance variables:]
       
   170 
       
   171         cursorLine              <Number>        line where cursor sits (1..)
       
   172 
       
   173         cursorVisibleLine       <Number>        visible line where cursor sits (1..nLinesShown)
       
   174 
       
   175         cursorCol               <Number>        col where cursor sits (1..)
       
   176 
       
   177         cursorShown             <Boolean>       true, if cursor is currently shown
       
   178 
       
   179         readOnly                <Boolean>       true, if text may not be edited
       
   180 
       
   181         modifiedChannel         <ValueHolder>   holding true, if text has been modified.
       
   182                                                 cleared on accept.
       
   183 
       
   184         acceptChannel           <ValueHolder>   holding true, if text has been accepted.
       
   185 
       
   186         fixedSize               <Boolean>       true, if no lines may be added/removed
       
   187 
       
   188         exceptionBlock          <Block>         block to be evaluated when readonly text is about to be modified
       
   189                                                 if it returns true, the modification will be done anyway.
       
   190                                                 if it returns anything else, the modification is not done.
       
   191 
       
   192         cursorFgColor           <Color>         color used for cursor drawing
       
   193         cursorBgColor           <Color>         color used for cursor drawing
       
   194 
       
   195         cursorType              <Symbol>        how the cursor is drawn; currently implemented
       
   196                                                 are #none, #block (solid-block cursor), #ibeam
       
   197                                                 (vertical bar at insertion point)
       
   198                                                 and #caret (caret below insertion-point).
       
   199                                                 see cursorType: for an up-to-date list.
       
   200 
       
   201         cursorTypeNoFocus       <Symbol>        like above, if view has no focus
       
   202                                                 nil means: hide the cursor.
       
   203 
       
   204         undoAction              <Block>         block which undoes last cut, paste or replace
       
   205                                                 (not yet fully implemented)
       
   206 
       
   207         typeOfSelection         <Symbol>        #paste, if selection created by paste, nil otherwise
       
   208                                                 this affects the next keyPress: if #paste it does not
       
   209                                                 replace; otherwise it replaces the selection.
       
   210 
       
   211         lastCut                 <String>        last cut or replaced string
       
   212 
       
   213         lastReplacementInfo     <LastReplacementInfo>        holds the information about the last replace action
       
   214                                                              lastStringToReplace is the string to be replaced by lastReplacement
       
   215                                                              lastReplacement is the string to replace lastStringToReplace
       
   216 
       
   217         lastStringFromReplaceForNextSearch   <String>        string to be taken be the next search action 
       
   218                                                              (cleared after a new selection)
       
   219 
       
   220         replacing               <Boolean>       true if entered characters replace last selection
       
   221 
       
   222         showMatchingParenthesis <Boolean>       if true, shows matching parenthesis
       
   223                                                 when entering one; this is the default.
       
   224 
       
   225         hasKeyboardFocus        <Boolean>       true if this view has the focus
       
   226 
       
   227         acceptAction            <Block>         accept action - evaluated passing the contents as
       
   228                                                 argument
       
   229 
       
   230         tabMeansNextField       <Boolean>       if true, Tab is ignored as input and shifts keyboard
       
   231                                                 focus to the next field. For editTextViews, this is false
       
   232                                                 by default (i.e. tabs can be entered into the text).
       
   233                                                 For some subclasses (inputFields), this may be true.
       
   234 
       
   235         trimBlankLines          <Boolean>       if true, trailing blanks are
       
   236                                                 removed when editing.
       
   237                                                 Default is true.
       
   238 
       
   239         wordWrap                <Boolean>       Currently not used.
       
   240 
       
   241         lockUpdates             <Boolean>       internal, private
       
   242 
       
   243         prevCursorState         <Boolean>       temporary, private
       
   244 
       
   245         cursorMovementWhenUpdating
       
   246                                 <Symbol>        defines where the cursor is to be positioned if the
       
   247                                                 model changes its value by some outside activity
       
   248                                                 (i.e. not by user input into the field).
       
   249                                                 Can be one of:
       
   250                                                     #keep / nil     -> stay where it was
       
   251                                                     #endOfText      -> cursor to the end
       
   252                                                     #endOfLine      -> stay in the line, but move to end
       
   253                                                     #beginOfText    -> cursor to the beginning
       
   254                                                     #beginOfLine    -> stay in the line, but move to begin
       
   255                                                 The default is #beginOfText
       
   256 
       
   257 
       
   258 
       
   259         dropTarget              <DropTarget|nil> drop operation descriptor or nil (drop disabled)
       
   260 
       
   261 
       
   262     userPreference values:
       
   263         userPreferences.st80EditMode
       
   264                                 <Boolean>       if true, cursor positioning is
       
   265                                                 done as in vi or ST80; i.e.
       
   266                                                 wysiwyg mode is somewhat relaxed,
       
   267                                                 in that the cursor cannot be
       
   268                                                 positioned behind a lines end.
       
   269                                                 This is not yet completely implemented.
       
   270     used globals:
       
   271 
       
   272         DeleteHistory           <Text>          last 1000 lines of deleted text
       
   273                                                 (but only if this variable exists already)
       
   274 
       
   275     [styleSheet parameters:]
       
   276 
       
   277         textCursorForegroundColor <Color>          cursor fg color; default: text background
       
   278         textCursorBackgroundColor <Color>          cursor bg color; default: text foreground
       
   279         textCursorNoFocusForegroundColor
       
   280                                   <Color>          cursor fg color if no focus; default: cursor fg color
       
   281         textCursorType            <Symbol>         cursor type; default:  #block
       
   282 
       
   283     [author:]
       
   284         Claus Gittinger
       
   285 
       
   286     [see also:]
       
   287         CodeView Workspace TextView ListView
       
   288         EditField
       
   289 "
       
   290 !
       
   291 
       
   292 examples
       
   293 "
       
   294   non MVC operation:
       
   295 
       
   296     basic setup:
       
   297                                                                         [exBegin]
       
   298         |top textView|
       
   299 
       
   300         top := StandardSystemView new.
       
   301         top extent:300@200.
       
   302 
       
   303         textView := EditTextView new.
       
   304         textView origin:0.0 @ 0.0 corner:1.0 @ 1.0.
       
   305         top addSubView:textView.
       
   306 
       
   307         textView contents:('/etc/hosts' asFilename contentsOfEntireFile).
       
   308 
       
   309         top open.
       
   310                                                                         [exEnd]
       
   311 
       
   312 
       
   313     with vertical scrollbar:
       
   314                                                                         [exBegin]
       
   315         |top scrollView textView|
       
   316 
       
   317         top := StandardSystemView new.
       
   318         top extent:300@200.
       
   319 
       
   320         scrollView := ScrollableView for:EditTextView.
       
   321         textView := scrollView scrolledView.
       
   322         scrollView origin:0.0 @ 0.0 corner:1.0 @ 1.0.
       
   323         top addSubView:scrollView.
       
   324 
       
   325         textView contents:('/etc/hosts' asFilename contentsOfEntireFile).
       
   326 
       
   327         top open.
       
   328                                                                         [exEnd]
       
   329 
       
   330 
       
   331     with horizontal & vertical scrollbars:
       
   332                                                                         [exBegin]
       
   333         |top scrollView textView|
       
   334 
       
   335         top := StandardSystemView new.
       
   336         top extent:300@200.
       
   337 
       
   338         scrollView := HVScrollableView for:EditTextView.
       
   339         textView := scrollView scrolledView.
       
   340         scrollView origin:0.0 @ 0.0 corner:1.0 @ 1.0.
       
   341         top addSubView:scrollView.
       
   342 
       
   343         textView contents:('/etc/hosts' asFilename contentsOfEntireFile).
       
   344 
       
   345         top open.
       
   346                                                                         [exEnd]
       
   347 
       
   348 
       
   349     set the action for accept:
       
   350                                                                         [exBegin]
       
   351         |top textView|
       
   352 
       
   353         top := StandardSystemView new.
       
   354         top extent:300@200.
       
   355 
       
   356         textView := EditTextView new.
       
   357         textView origin:0.0 @ 0.0 corner:1.0 @ 1.0.
       
   358         top addSubView:textView.
       
   359 
       
   360         textView contents:('/etc/hosts' asFilename contentsOfEntireFile).
       
   361         textView acceptAction:[:contents |
       
   362                                 Transcript showCR:'will not overwrite the file with:'.
       
   363                                 Transcript showCR:contents asString
       
   364                               ].
       
   365         top open.
       
   366                                                                         [exEnd]
       
   367 
       
   368 
       
   369 
       
   370     non-string (text) items:
       
   371                                                                         [exBegin]
       
   372         |top textView list|
       
   373 
       
   374         list := '/etc/hosts' asFilename contentsOfEntireFile asStringCollection.
       
   375         1 to:list size by:2 do:[:nr |
       
   376             list at:nr put:(Text string:(list at:nr)
       
   377                                  emphasis:(Array with:#bold with:(#color->Color red)))
       
   378         ].
       
   379 
       
   380         top := StandardSystemView new.
       
   381         top extent:300@200.
       
   382 
       
   383         textView := EditTextView new.
       
   384         textView origin:0.0 @ 0.0 corner:1.0 @ 1.0.
       
   385         top addSubView:textView.
       
   386 
       
   387         textView contents:list.
       
   388         top open.
       
   389                                                                         [exEnd]
       
   390 
       
   391 
       
   392 
       
   393   MVC operation:
       
   394     (the examples model here is a plug simulating a real model;
       
   395      real world applications would not use a plug ..)
       
   396                                                                         [exBegin]
       
   397         |top textView model|
       
   398 
       
   399         model := Plug new.
       
   400         model respondTo:#accepted:
       
   401                    with:[:newContents |
       
   402                                 Transcript showCR:'will not overwrite the file with:'.
       
   403                                 Transcript showCR:newContents asString
       
   404                         ].
       
   405         model respondTo:#getList
       
   406                    with:['/etc/hosts' asFilename contentsOfEntireFile].
       
   407 
       
   408 
       
   409         top := StandardSystemView new.
       
   410         top extent:300@200.
       
   411 
       
   412         textView := EditTextView new.
       
   413         textView origin:0.0 @ 0.0 corner:1.0 @ 1.0.
       
   414         top addSubView:textView.
       
   415 
       
   416         textView listMessage:#getList;
       
   417                  model:model;
       
   418                  changeMessage:#accepted:;
       
   419                  aspect:#list.
       
   420         top open.
       
   421                                                                         [exEnd]
       
   422 
       
   423 
       
   424     two textViews on the same model:
       
   425                                                                         [exBegin]
       
   426         |top1 textView1 top2 textView2 model currentContents|
       
   427 
       
   428         model := Plug new.
       
   429         model respondTo:#accepted:
       
   430                    with:[:newContents |
       
   431                                 Transcript showCR:'accepted:'.
       
   432                                 Transcript showCR:newContents asString.
       
   433                                 currentContents := newContents.
       
   434                                 model changed:#contents
       
   435                         ].
       
   436         model respondTo:#getList
       
   437                    with:[Transcript showCR:'query'.
       
   438                          currentContents].
       
   439 
       
   440 
       
   441         top1 := StandardSystemView new.
       
   442         top1 extent:300@200.
       
   443 
       
   444         textView1 := EditTextView new.
       
   445         textView1 origin:0.0 @ 0.0 corner:1.0 @ 1.0.
       
   446         top1 addSubView:textView1.
       
   447 
       
   448         textView1 listMessage:#getList;
       
   449                   model:model;
       
   450                   aspect:#contents;
       
   451                   changeMessage:#accepted:.
       
   452         top1 open.
       
   453 
       
   454         top2 := StandardSystemView new.
       
   455         top2 extent:300@200.
       
   456 
       
   457         textView2 := EditTextView new.
       
   458         textView2 origin:0.0 @ 0.0 corner:1.0 @ 1.0.
       
   459         top2 addSubView:textView2.
       
   460 
       
   461         textView2 listMessage:#getList;
       
   462                   model:model;
       
   463                   aspect:#contents;
       
   464                   changeMessage:#accepted:.
       
   465         top2 open.
       
   466                                                                         [exEnd]
       
   467 "
       
   468 ! !
       
   469 
       
   470 !EditTextView class methodsFor:'defaults'!
       
   471 
       
   472 defaultCompletionSupportClass
       
   473     ^ nil
       
   474 
       
   475     "Created: / 26-09-2013 / 17:59:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   476 !
       
   477 
       
   478 st80Mode
       
   479     "return true, if the st80 editing mode is turned on.
       
   480      This setting affects the behavior of the cursor, when positioned
       
   481      beyond the end of a line or the end of the text."
       
   482 
       
   483     ^ UserPreferences current st80EditMode
       
   484 
       
   485    "
       
   486     EditTextView st80Mode:true
       
   487     EditTextView st80Mode:false
       
   488    "
       
   489 
       
   490     "Modified: / 16.1.1998 / 22:54:57 / cg"
       
   491 !
       
   492 
       
   493 st80Mode:aBoolean
       
   494     "turns on/off st80 behavior, where the cursor cannot be positioned
       
   495      beyond the end of a line or the last line"
       
   496 
       
   497     UserPreferences current st80EditMode:aBoolean.
       
   498 
       
   499    "
       
   500     EditTextView st80Mode:true
       
   501     EditTextView st80Mode:false
       
   502    "
       
   503 
       
   504     "Modified: / 16.1.1998 / 22:55:19 / cg"
       
   505 !
       
   506 
       
   507 updateStyleCache
       
   508     "extract values from the styleSheet and cache them in class variables"
       
   509 
       
   510     <resource: #style (#'textCursor.foregroundColor' #'textCursor.backgroundColor'
       
   511                        #'textCursor.noFocusForegroundColor'
       
   512                        #'textCursor.type'
       
   513                        #'textCursor.typeNoFocus'
       
   514                        #'editText.st80Mode')>
       
   515 
       
   516     DefaultCursorForegroundColor := StyleSheet colorAt:'textCursor.foregroundColor'.
       
   517     DefaultCursorBackgroundColor := StyleSheet colorAt:'textCursor.backgroundColor'.
       
   518     DefaultCursorNoFocusForegroundColor := StyleSheet colorAt:'textCursor.noFocusForegroundColor'.
       
   519     DefaultCursorType := StyleSheet at:'textCursor.type' default:#block.
       
   520     DefaultCursorTypeNoFocus := StyleSheet at:'textCursor.typeNoFocus'.
       
   521 
       
   522     "
       
   523      self updateStyleCache
       
   524     "
       
   525 
       
   526     "Modified: / 20.5.1998 / 04:27:41 / cg"
       
   527 ! !
       
   528 
       
   529 !EditTextView class methodsFor:'specs'!
       
   530 
       
   531 searchReplaceDialogSpec
       
   532     "This resource specification was automatically generated
       
   533      by the UIPainter of ST/X."
       
   534 
       
   535     "Do not manually edit this!! If it is corrupted,
       
   536      the UIPainter may not be able to read the specification."
       
   537 
       
   538     "
       
   539      UIPainter new openOnClass:DAPASX::ProjectEditorTextView andSelector:#searchReplaceDialogSpec
       
   540     "
       
   541 
       
   542     <resource: #canvas>
       
   543 
       
   544     ^
       
   545      #(FullSpec
       
   546         name: searchReplaceDialogSpec
       
   547         window:
       
   548        (WindowSpec
       
   549           label: 'String Search and Replace'
       
   550           name: 'String Search and Replace'
       
   551           min: (Point 283 196)
       
   552           max: (Point 283 196)
       
   553           bounds: (Rectangle 0 0 279 192)
       
   554         )
       
   555         component:
       
   556        (SpecCollection
       
   557           collection: (
       
   558            (LabelSpec
       
   559               label: 'Search Pattern:'
       
   560               name: 'label'
       
   561               layout: (LayoutFrame 1 0.0 3 0 -1 1.0 20 0)
       
   562               level: 0
       
   563               translateLabel: true
       
   564               adjust: left
       
   565             )
       
   566            (ComboBoxSpec
       
   567               name: 'patternComboBox'
       
   568               layout: (LayoutFrame 3 0.0 26 0 -3 1.0 48 0)
       
   569               tabable: true
       
   570               model: searchPattern
       
   571               immediateAccept: false
       
   572               acceptOnLeave: true
       
   573               acceptOnReturn: true
       
   574               acceptOnTab: true
       
   575               acceptOnLostFocus: true
       
   576               acceptOnPointerLeave: false
       
   577               autoSelectInitialText: true
       
   578               comboList: patternList
       
   579             )
       
   580            (ComboBoxSpec
       
   581               name: 'replaceComboBox'
       
   582               layout: (LayoutFrame 3 0.0 76 0 -3 1.0 98 0)
       
   583               tabable: true
       
   584               model: replacePattern
       
   585               immediateAccept: false
       
   586               acceptOnLeave: true
       
   587               acceptOnReturn: true
       
   588               acceptOnTab: true
       
   589               acceptOnLostFocus: true
       
   590               acceptOnPointerLeave: false
       
   591               autoSelectInitialText: true
       
   592               comboList: patternList
       
   593             )
       
   594            (CheckBoxSpec
       
   595               label: 'Ignore Case'
       
   596               name: 'ignoreCaseCheckBox'
       
   597               layout: (LayoutFrame 3 0.0 107 0 -3 1.0 130 0)
       
   598               level: 0
       
   599               tabable: true
       
   600               model: ignoreCase
       
   601               translateLabel: true
       
   602             )
       
   603            (VariableVerticalPanelSpec
       
   604               name: 'VariableVerticalPanel1'
       
   605               layout: (LayoutFrame 0 0 -64 1 0 1 -4 1)
       
   606               component:
       
   607              (SpecCollection
       
   608                 collection: (
       
   609                  (HorizontalPanelViewSpec
       
   610                     name: 'HorizontalPanel1'
       
   611                     level: 0
       
   612                     horizontalLayout: fitSpace
       
   613                     verticalLayout: center
       
   614                     horizontalSpace: 3
       
   615                     verticalSpace: 3
       
   616                     ignoreInvisibleComponents: true
       
   617                     reverseOrderIfOKAtLeft: true
       
   618                     component:
       
   619                    (SpecCollection
       
   620                       collection: (
       
   621                        (ActionButtonSpec
       
   622                           label: 'Replace'
       
   623                           name: 'replaceButton'
       
   624                           level: 2
       
   625                           translateLabel: true
       
   626                           tabable: true
       
   627                           model: replaceAction
       
   628                           extent: (Point 134 21)
       
   629                         )
       
   630                        (ActionButtonSpec
       
   631                           label: 'Replace All'
       
   632                           name: 'replaceAllButton'
       
   633                           level: 2
       
   634                           borderWidth: 1
       
   635                           translateLabel: true
       
   636                           tabable: true
       
   637                           model: replaceAllAction
       
   638                           extent: (Point 134 21)
       
   639                         )
       
   640                        )
       
   641 
       
   642                     )
       
   643                   )
       
   644                  (HorizontalPanelViewSpec
       
   645                     name: 'horizontalPanelView'
       
   646                     level: 0
       
   647                     horizontalLayout: fitSpace
       
   648                     verticalLayout: center
       
   649                     horizontalSpace: 3
       
   650                     verticalSpace: 3
       
   651                     ignoreInvisibleComponents: true
       
   652                     reverseOrderIfOKAtLeft: true
       
   653                     component:
       
   654                    (SpecCollection
       
   655                       collection: (
       
   656                        (ActionButtonSpec
       
   657                           label: 'Cancel'
       
   658                           name: 'cancelButton'
       
   659                           level: 2
       
   660                           translateLabel: true
       
   661                           tabable: true
       
   662                           model: cancel
       
   663                           extent: (Point 88 21)
       
   664                         )
       
   665                        (ActionButtonSpec
       
   666                           label: 'Prev'
       
   667                           name: 'prevButton'
       
   668                           level: 2
       
   669                           translateLabel: true
       
   670                           tabable: true
       
   671                           model: prevAction
       
   672                           extent: (Point 89 21)
       
   673                         )
       
   674                        (ActionButtonSpec
       
   675                           label: 'Next'
       
   676                           name: 'nextButton'
       
   677                           level: 2
       
   678                           borderWidth: 1
       
   679                           translateLabel: true
       
   680                           tabable: true
       
   681                           model: nextAction
       
   682                           isDefault: true
       
   683                           extent: (Point 88 21)
       
   684                         )
       
   685                        )
       
   686 
       
   687                     )
       
   688                   )
       
   689                  )
       
   690 
       
   691               )
       
   692               handles: (Any 0.5 1.0)
       
   693             )
       
   694            (LabelSpec
       
   695               label: 'Replace By:'
       
   696               name: 'ReplaceLabel'
       
   697               layout: (LayoutFrame 1 0.0 53 0 -1 1.0 70 0)
       
   698               level: 0
       
   699               translateLabel: true
       
   700               adjust: left
       
   701             )
       
   702            )
       
   703 
       
   704         )
       
   705       )
       
   706 
       
   707     "Modified: / 11-10-2006 / 21:05:09 / cg"
       
   708 ! !
       
   709 
       
   710 !EditTextView methodsFor:'Compatibility-ST80'!
       
   711 
       
   712 autoAccept:aBoolean
       
   713     "ignored for now"
       
   714 
       
   715     "Created: / 5.6.1998 / 15:30:32 / cg "
       
   716 !
       
   717 
       
   718 continuousAccept:aBoolean
       
   719     "ignored for now"
       
   720 
       
   721     "Created: / 19.6.1998 / 00:03:49 / cg"
       
   722 !
       
   723 
       
   724 cutSelection
       
   725     self cut
       
   726 
       
   727     "Created: / 31.10.1997 / 03:29:50 / cg"
       
   728 !
       
   729 
       
   730 deselect
       
   731     "remove the selection"
       
   732 
       
   733     ^ self unselect
       
   734 
       
   735     "Created: / 19.6.1998 / 02:41:54 / cg"
       
   736 !
       
   737 
       
   738 enabled:aBoolean
       
   739 
       
   740     self readOnly:aBoolean not
       
   741 
       
   742     "Created: / 30.3.1999 / 15:10:23 / stefan"
       
   743     "Modified: / 30.3.1999 / 15:10:53 / stefan"
       
   744 !
       
   745 
       
   746 find:pattern
       
   747     self searchFwd:pattern ifAbsent:nil
       
   748 
       
   749     "Created: / 29.1.1999 / 19:09:42 / cg"
       
   750     "Modified: / 29.1.1999 / 19:10:12 / cg"
       
   751 !
       
   752 
       
   753 insert:aString at:aCharacterPosition
       
   754     "insert a string at aCharacterPosition."
       
   755 
       
   756     |line col|
       
   757 
       
   758     line := self lineOfCharacterPosition:aCharacterPosition.
       
   759     col := aCharacterPosition - (self characterPositionOfLine:line col:1) + 1.
       
   760     col < 1 ifTrue:[
       
   761         col := 1
       
   762     ].
       
   763     self insertString:aString atLine:line col:col.
       
   764 
       
   765     "
       
   766      |top v|
       
   767 
       
   768      top := StandardSystemView new.
       
   769      top extent:300@300.
       
   770      v := EditTextView origin:0.0@0.0 corner:1.0@1.0 in:top.
       
   771      top openAndWait.
       
   772      v contents:'1234567890\1234567890\1234567890\' withCRs.
       
   773      v insert:'<- hello there' at:5.
       
   774     "
       
   775 
       
   776     "Modified: / 5.4.1998 / 17:20:08 / cg"
       
   777 !
       
   778 
       
   779 insertAndSelect:aString at:aCharacterPosition
       
   780     "insert a selected string at aCharacterPosition."
       
   781 
       
   782     |line col|
       
   783 
       
   784     line := self lineOfCharacterPosition:aCharacterPosition.
       
   785     col := (aCharacterPosition - (self characterPositionOfLine:line col:1) + 1) max:1.
       
   786     self insertString:aString atLine:line col:col.
       
   787     self selectFromLine:line col:col toLine:line col:col + aString size - 1
       
   788     "
       
   789      |v|
       
   790 
       
   791      v := EditTextView new openAndWait.
       
   792      v contents:'1234567890\1234567890\1234567890\' withCRs.
       
   793      v insertAndSelect:'<- hello there' at:5.
       
   794     "
       
   795 !
       
   796 
       
   797 pasteSelection
       
   798     self paste
       
   799 
       
   800     "Created: / 31.10.1997 / 03:28:53 / cg"
       
   801 !
       
   802 
       
   803 replaceSelectionWith:aString
       
   804     ^ self replaceSelectionBy:aString
       
   805 
       
   806     "Created: / 19.6.1998 / 02:42:32 / cg"
       
   807 !
       
   808 
       
   809 selectAt:pos
       
   810     "move the cursor before cursorPosition."
       
   811 
       
   812     self cursorToCharacterPosition:pos
       
   813 
       
   814     "Modified: / 19.6.1998 / 02:41:28 / cg"
       
   815     "Created: / 19.6.1998 / 02:43:39 / cg"
       
   816 !
       
   817 
       
   818 textHasChanged
       
   819     ^ self modified
       
   820 
       
   821     "Created: / 19.6.1998 / 00:09:43 / cg"
       
   822 !
       
   823 
       
   824 textHasChanged:aBoolean
       
   825     "ST-80 compatibility: set/clear the modified flag."
       
   826 
       
   827     self modified:aBoolean
       
   828 
       
   829     "Created: / 5.2.2000 / 17:07:59 / cg"
       
   830 ! !
       
   831 
       
   832 !EditTextView methodsFor:'accessing'!
       
   833 
       
   834 codeAspect
       
   835     | codeAspect app |
       
   836 
       
   837     codeAspect := codeAspectHolder value.
       
   838     codeAspect notNil ifTrue:[^codeAspect].
       
   839     self editedMethod notNil ifTrue:[^SyntaxHighlighter codeAspectMethod].
       
   840 
       
   841     "/ Applications should set it explictly, however, to make it behavinh like
       
   842     "/ CodeView2, I kept fetching code here for now.
       
   843     ^((app := self topView application) notNil and:[app respondsTo: #codeAspect])
       
   844         ifTrue:[app codeAspect]
       
   845         ifFalse:[nil]
       
   846 
       
   847     "Created: / 27-09-2013 / 09:53:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   848 !
       
   849 
       
   850 codeAspect: aSymbol
       
   851     codeAspectHolder value: aSymbol
       
   852 
       
   853     "Created: / 27-09-2013 / 09:50:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   854 !
       
   855 
       
   856 completionSupport
       
   857     ^ completionSupport
       
   858 !
       
   859 
       
   860 completionSupport:anEditTextViewCompletionSupport
       
   861     completionSupport := anEditTextViewCompletionSupport.
       
   862 !
       
   863 
       
   864 completionSupportClass
       
   865     ^ self class defaultCompletionSupportClass
       
   866 
       
   867     "Created: / 26-09-2013 / 17:54:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   868 !
       
   869 
       
   870 editedClass
       
   871     |cm|
       
   872 
       
   873     cm := self editedMethodOrClass.
       
   874     cm isBehavior ifTrue:[^ cm].
       
   875     cm isMethod ifTrue:[^ cm mclass].
       
   876     ^ nil
       
   877 !
       
   878 
       
   879 editedLanguage
       
   880     ^ nil
       
   881 
       
   882     "Created: / 18-09-2013 / 14:16:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   883 !
       
   884 
       
   885 editedLanguage: aProgrammingLanguage
       
   886     "Sets the edited language. Only defined here to make it polymorph with Workspace"
       
   887 
       
   888     "Created: / 27-09-2013 / 10:15:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   889 !
       
   890 
       
   891 editedMethod
       
   892     |cm|
       
   893 
       
   894     cm := self editedMethodOrClass.
       
   895     cm isMethod ifTrue:[^ cm].
       
   896     cm isBehavior ifTrue:[^ nil].
       
   897     ^ nil
       
   898 !
       
   899 
       
   900 editedMethodOrClass
       
   901     ^ nil
       
   902 !
       
   903 
       
   904 editedMethodOrClass: methodOrClass
       
   905     "Sets the edited method or class. Only defined here to make it polymorph with Workspace"
       
   906 
       
   907     "Created: / 27-09-2013 / 10:10:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   908 !
       
   909 
       
   910 hasSelectionOrTextInCursorLine
       
   911     ^ (self selectionOrTextOfCursorLine:false) notNil
       
   912 !
       
   913 
       
   914 selectionOrTextOfCursorLine
       
   915     ^ self selectionOrTextOfCursorLine:true
       
   916 !
       
   917 
       
   918 selectionOrTextOfCursorLine:doSelect
       
   919     |sel lNr line|
       
   920 
       
   921     sel := self selectionAsString.
       
   922     sel notNil ifTrue:[^ sel].
       
   923 
       
   924     lNr := self cursorLine.
       
   925     line := self listAt:lNr.
       
   926     line notEmptyOrNil ifTrue:[
       
   927         doSelect ifTrue:[
       
   928             self selectLine:lNr.
       
   929         ].
       
   930         ^ line
       
   931     ].
       
   932 
       
   933     ^ nil
       
   934 ! !
       
   935 
       
   936 !EditTextView methodsFor:'accessing-behavior'!
       
   937 
       
   938 acceptAction
       
   939     "return the action to be performed on accept (or nil)"
       
   940 
       
   941     ^ acceptAction
       
   942 !
       
   943 
       
   944 acceptAction:aBlock
       
   945     "set the action to be performed on accept"
       
   946 
       
   947     acceptAction := aBlock
       
   948 !
       
   949 
       
   950 acceptChannel
       
   951     "return the valueHolder holding true if text was accepted.
       
   952      By placing a true into this channel, an accept can also be forced."
       
   953 
       
   954     ^ acceptChannel
       
   955 
       
   956     "Modified: / 30.1.1998 / 14:17:11 / cg"
       
   957 !
       
   958 
       
   959 acceptChannel:aValueHolder
       
   960     "set the valueHolder holding true if text was accepted.
       
   961      By placing a true into this channel, an accept can also be forced."
       
   962 
       
   963     |prev|
       
   964 
       
   965     prev := acceptChannel.
       
   966     acceptChannel := aValueHolder.
       
   967     self setupChannel:aValueHolder for:nil withOld:prev
       
   968 
       
   969     "Created: / 30.1.1998 / 14:51:09 / cg"
       
   970 !
       
   971 
       
   972 acceptEnabled:aBoolean
       
   973     "enable/disable accept. This greys the corresponding item in the menu"
       
   974 
       
   975     acceptEnabled := aBoolean
       
   976 
       
   977     "Created: 7.3.1997 / 11:04:34 / cg"
       
   978 !
       
   979 
       
   980 accepted
       
   981     "return true if text was accepted"
       
   982 
       
   983     ^ acceptChannel value
       
   984 
       
   985     "Created: 14.2.1997 / 16:43:46 / cg"
       
   986 !
       
   987 
       
   988 accepted:aBoolean
       
   989     "set/clear the accepted flag.
       
   990      This may force my current contents to be placed into my model."
       
   991 
       
   992     acceptChannel value:aBoolean.
       
   993 
       
   994     "Created: / 14.2.1997 / 16:44:01 / cg"
       
   995     "Modified: / 30.1.1998 / 14:20:15 / cg"
       
   996 !
       
   997 
       
   998 autoIndent:aBoolean
       
   999     autoIndent := aBoolean
       
  1000 
       
  1001     "Created: 5.3.1996 / 14:37:50 / cg"
       
  1002 !
       
  1003 
       
  1004 codeAspectHolder
       
  1005     ^ codeAspectHolder
       
  1006 !
       
  1007 
       
  1008 codeAspectHolder:something
       
  1009     codeAspectHolder := something.
       
  1010 !
       
  1011 
       
  1012 cursorMovementWhenUpdating
       
  1013     "return what is be done with the cursor,
       
  1014      when I get a new text (via the model or the #contents/#list)
       
  1015      Allowed arguments are:
       
  1016         #keep / nil     -> stay where it was
       
  1017         #endOfText      -> position cursor to the end
       
  1018         #beginOfText    -> position cursor to the beginning
       
  1019         #endOfLine      -> position cursor to the current lines end
       
  1020         #beginOfLine    -> position cursor to the current lines start
       
  1021      The default is #beginOfText.
       
  1022      This may be useful for fields which get new values assigned from
       
  1023      the program (i.e. not from the user)"
       
  1024 
       
  1025     ^ cursorMovementWhenUpdating
       
  1026 
       
  1027     "Modified: 16.12.1995 / 16:27:55 / cg"
       
  1028 !
       
  1029 
       
  1030 cursorMovementWhenUpdating:aSymbolOrNil
       
  1031     "define what should be done with the cursor,
       
  1032      when I get a new text (via the model or the #contents/#list)
       
  1033      Allowed arguments are:
       
  1034         #keep / nil     -> stay where it was
       
  1035         #endOfText      -> position cursor to the end
       
  1036         #beginOfText    -> position cursor to the beginning
       
  1037         #endOfLine      -> position cursor to the current lines end
       
  1038         #beginOfLine    -> position cursor to the current lines start
       
  1039      The default is #beginOfText.
       
  1040      This may be useful for fields which get new values assigned from
       
  1041      the program (i.e. not from the user)"
       
  1042 
       
  1043     cursorMovementWhenUpdating := aSymbolOrNil
       
  1044 
       
  1045     "Modified: 16.12.1995 / 16:27:55 / cg"
       
  1046 !
       
  1047 
       
  1048 disableIfInvisible:aBoolean
       
  1049     disableIfInvisible := aBoolean
       
  1050 !
       
  1051 
       
  1052 dontReplaceSelectionOnInput
       
  1053     "remember that the current selection was created by a paste operation
       
  1054      (as opposed to an explicit selection by the user).
       
  1055      This selection will not be replaced by followup user input,
       
  1056      so multiple pastes will be possible."
       
  1057 
       
  1058     typeOfSelection := #paste
       
  1059 !
       
  1060 
       
  1061 editModeHolder
       
  1062     ^ editMode.
       
  1063 !
       
  1064 
       
  1065 editModeInsert
       
  1066     editMode value:EditMode insertMode
       
  1067 !
       
  1068 
       
  1069 editModeInsertAndSelect
       
  1070     editMode value:EditMode insertAndSelectMode
       
  1071 !
       
  1072 
       
  1073 editModeOverwrite
       
  1074     editMode value:EditMode overwriteMode
       
  1075 !
       
  1076 
       
  1077 exceptionBlock:aBlock
       
  1078     "define the action to be triggered when user tries to modify
       
  1079      readonly text"
       
  1080 
       
  1081     exceptionBlock := aBlock
       
  1082 !
       
  1083 
       
  1084 fixedSize
       
  1085     "make the texts size fixed (no lines may be added).
       
  1086      OBSOLETE: use readOnly"
       
  1087 
       
  1088     <resource:#obsolete>
       
  1089 
       
  1090     |menu|
       
  1091 
       
  1092     self obsoleteMethodWarning:'use #readOnly:'.
       
  1093     readOnly == true ifFalse:[
       
  1094         readOnly := true.
       
  1095         (menu := self middleButtonMenu) notNil ifTrue:[
       
  1096             menu disableAll:#(cut paste replace indent)
       
  1097         ]
       
  1098     ]
       
  1099 
       
  1100     "Modified: 14.2.1997 / 17:35:24 / cg"
       
  1101 !
       
  1102 
       
  1103 insertMode:aBoolean
       
  1104     editMode value:(aBoolean ifTrue:[EditMode insertMode] ifFalse:[EditMode overwriteMode])
       
  1105 
       
  1106     "Created: 6.3.1996 / 12:24:05 / cg"
       
  1107 !
       
  1108 
       
  1109 insertModeHolder
       
  1110     ^ BlockValue
       
  1111         with:[:m | m isInsertMode]
       
  1112         argument:(editMode).
       
  1113 
       
  1114     "Modified: / 08-03-2007 / 22:58:37 / cg"
       
  1115 !
       
  1116 
       
  1117 isInInsertMode
       
  1118     ^ editMode value isInsertMode
       
  1119 !
       
  1120 
       
  1121 isReadOnly
       
  1122     "return true, if the text is readonly."
       
  1123 
       
  1124     ^ readOnly value
       
  1125 
       
  1126     "Modified: 14.2.1997 / 17:35:56 / cg"
       
  1127 !
       
  1128 
       
  1129 modeLabelHolder
       
  1130     "a valueHolder, which contains 'L' (learnMode), I (insertMode) or empty"
       
  1131 
       
  1132     ^ BlockValue
       
  1133         with:[:e :l |
       
  1134             self isReadOnly ifTrue:[
       
  1135                 ''
       
  1136             ] ifFalse:[
       
  1137                 l ifTrue:[ 'L' allBold colorizeAllWith:Color red]
       
  1138                   ifFalse:[ e infoPrintString]]]
       
  1139         argument:(self editModeHolder)
       
  1140         argument:(self learnModeHolder).
       
  1141 
       
  1142     "Modified: / 08-03-2007 / 22:58:59 / cg"
       
  1143 !
       
  1144 
       
  1145 modified
       
  1146     "return true if text was modified"
       
  1147 
       
  1148     ^ modifiedChannel value
       
  1149 !
       
  1150 
       
  1151 modified:aBoolean
       
  1152     "set/clear the modified flag"
       
  1153 
       
  1154     modifiedChannel value:aBoolean
       
  1155 
       
  1156     "Modified: 14.2.1997 / 16:44:05 / cg"
       
  1157 !
       
  1158 
       
  1159 modifiedChannel
       
  1160     "return the valueHolder holding true if text was modified"
       
  1161 
       
  1162     ^ modifiedChannel
       
  1163 !
       
  1164 
       
  1165 modifiedChannel:aValueHolder
       
  1166     "set the valueHolder holding true if text was modified"
       
  1167 
       
  1168     |prev|
       
  1169 
       
  1170     prev := modifiedChannel.
       
  1171     modifiedChannel := aValueHolder.
       
  1172     self setupChannel:aValueHolder for:nil withOld:prev
       
  1173 
       
  1174     "Created: / 30.1.1998 / 14:51:32 / cg"
       
  1175 !
       
  1176 
       
  1177 readOnly
       
  1178     "make the text readonly.
       
  1179      Obsolete because it is obfuscating (looks like a getter)
       
  1180      - use #readOnly:"
       
  1181 
       
  1182     <resource:#obsolete>
       
  1183 
       
  1184     self obsoleteMethodWarning:'use #readOnly:'.
       
  1185     self readOnly:true.
       
  1186 
       
  1187     "Modified: / 14-02-1997 / 17:35:56 / cg"
       
  1188     "Modified (comment): / 02-08-2013 / 16:46:57 / cg"
       
  1189 !
       
  1190 
       
  1191 readOnly:aBoolean
       
  1192     "make the text readonly (aBoolean == true) or writable (aBoolean == false).
       
  1193      The argument may also be a valueHolder."
       
  1194 
       
  1195     readOnly := aBoolean
       
  1196 
       
  1197     "Created: 14.2.1997 / 17:35:39 / cg"
       
  1198 !
       
  1199 
       
  1200 reallyModifiedChannel
       
  1201     "return the valueHolder holding true if text was really modified.
       
  1202      For compatibility with views which use the modified flag for syntax highlighting."
       
  1203 
       
  1204     ^ self modifiedChannel
       
  1205 !
       
  1206 
       
  1207 st80Mode:aBoolean
       
  1208     "set/clear the st80Mode flag.
       
  1209      If on, the cursor wraps at the line end (like in vi or st80);
       
  1210      if off, we have the Rand-editor behavior (random access)"
       
  1211 
       
  1212     st80Mode := aBoolean
       
  1213 
       
  1214     "Created: / 09-11-2010 / 13:55:50 / cg"
       
  1215 !
       
  1216 
       
  1217 tabMeansNextField:aBoolean
       
  1218     "set/clear tabbing to the next field.
       
  1219      If true, Tab is ignored and shifts the keyboard focus.
       
  1220      If false, tabs can be entered into the text.
       
  1221      The default is true for editTextView, false for single-line
       
  1222      input fields."
       
  1223 
       
  1224     tabMeansNextField := aBoolean
       
  1225 !
       
  1226 
       
  1227 tabRequiresControl
       
  1228     "returns true, if a focus tabbing requires a control-key to be pressed.
       
  1229      The default is true for editTextView, false for other widgets,
       
  1230      to allow for easier text entry"
       
  1231 
       
  1232     ^ tabRequiresControl
       
  1233 !
       
  1234 
       
  1235 tabRequiresControl:aBoolean
       
  1236     "controls if a focus tabbing requires a control-key to be pressed.
       
  1237      The default is true for editTextView, false for other widgets,
       
  1238      to allow for easier text entry"
       
  1239 
       
  1240     tabRequiresControl := aBoolean
       
  1241 ! !
       
  1242 
       
  1243 !EditTextView methodsFor:'accessing-contents'!
       
  1244 
       
  1245 at:lineNr basicPut:aLine
       
  1246     "change a line without change notification"
       
  1247 
       
  1248     (self at:lineNr) = aLine ifFalse:[
       
  1249         super at:lineNr put:aLine.
       
  1250     ].
       
  1251 !
       
  1252 
       
  1253 at:lineNr put:aLine
       
  1254     (self at:lineNr) = aLine ifFalse:[
       
  1255         super at:lineNr put:aLine.
       
  1256         self textChanged
       
  1257     ].
       
  1258 !
       
  1259 
       
  1260 characterAfterCursor
       
  1261     "return the character one after the cursor - space if beyond line."
       
  1262 
       
  1263     ^ self characterAtLine:cursorLine col:cursorCol+1
       
  1264 !
       
  1265 
       
  1266 characterBeforeCursor
       
  1267     "return the character to the left of cursor - space if beyond line, nil if at the beginning."
       
  1268 
       
  1269     cursorCol == 1 ifTrue:[^ nil].
       
  1270 
       
  1271     ^ self characterAtLine:cursorLine col:cursorCol-1
       
  1272 
       
  1273     "Created: / 17.6.1998 / 15:16:41 / cg"
       
  1274 !
       
  1275 
       
  1276 characterUnderCursor
       
  1277     "return the character under the cursor - space if beyond line.
       
  1278      For non-block cursors, this is the character immediately to the right
       
  1279      of the insertion-bar or caret."
       
  1280 
       
  1281     ^ self characterAtLine:cursorLine col:cursorCol
       
  1282 !
       
  1283 
       
  1284 contents
       
  1285     "return the contents as a String or Text (i.e. with emphasis)"
       
  1286 
       
  1287     list isNil ifTrue:[^ ''].
       
  1288     self removeTrailingBlankLines.
       
  1289     ^ super contents.
       
  1290 
       
  1291     "Modified: / 04-07-2006 / 19:22:32 / fm"
       
  1292 !
       
  1293 
       
  1294 contents:something
       
  1295     self contents:something keepUndoHistory:false.
       
  1296 !
       
  1297 
       
  1298 contents:something keepUndoHistory:keepUndoHistory
       
  1299     super contents:something.
       
  1300     keepUndoHistory ifFalse:[
       
  1301         undoSupport resetHistories.
       
  1302     ].
       
  1303 !
       
  1304 
       
  1305 contentsAsString
       
  1306     "return the contents as a String (i.e. without emphasis)"
       
  1307 
       
  1308     list isNil ifTrue:[^ ''].
       
  1309     self removeTrailingBlankLines.
       
  1310     ^ (list collect:[:each | each isNil ifTrue:['']
       
  1311                                         ifFalse:[each string]
       
  1312                     ]) asStringWithCRs
       
  1313 !
       
  1314 
       
  1315 cursorCol
       
  1316     "return the cursors col (1..).
       
  1317      This is the absolute col; NOT the visible col"
       
  1318 
       
  1319     ^ cursorCol
       
  1320 !
       
  1321 
       
  1322 cursorColHolder
       
  1323     "return a valueHolder for the cursors column (1..)."
       
  1324 
       
  1325     ^ cursorColHolder
       
  1326 !
       
  1327 
       
  1328 cursorLine
       
  1329     "return the cursors line (1..).
       
  1330      This is the absolute line; NOT the visible line"
       
  1331 
       
  1332     ^ cursorLine
       
  1333 !
       
  1334 
       
  1335 cursorLineHolder
       
  1336     "return a valueHolder for the cursors line (1..).
       
  1337      This is the absolute line; NOT the visible line"
       
  1338 
       
  1339     ^ cursorLineHolder
       
  1340 !
       
  1341 
       
  1342 lineStringBeforeCursor
       
  1343     "return the line's string before the cursor.
       
  1344      Pad with spaces up to the cursor position if beyond the end of line"
       
  1345 
       
  1346     |line|
       
  1347 
       
  1348     line := ((self at:cursorLine) ? '') string.
       
  1349     line size < (cursorCol-1) ifTrue:[
       
  1350         ^ line paddedTo:(cursorCol-1)
       
  1351     ].
       
  1352     ^ line copyTo:(cursorCol-1)
       
  1353 !
       
  1354 
       
  1355 list:something
       
  1356     "position cursor home when setting contents"
       
  1357 
       
  1358     |prevCursorLine prevCursorCol|
       
  1359 
       
  1360     prevCursorLine := cursorLine.
       
  1361     prevCursorCol := cursorCol.
       
  1362 
       
  1363     super list:something.
       
  1364 
       
  1365     (cursorMovementWhenUpdating == #endOfText
       
  1366     or:[cursorMovementWhenUpdating == #end]) ifTrue:[
       
  1367         ^ self cursorToEndOfText
       
  1368     ].
       
  1369 
       
  1370     (cursorMovementWhenUpdating == #endOfLine) ifTrue:[
       
  1371         ^ self cursorLine:prevCursorLine col:(self listAt:cursorLine) size + 1.
       
  1372     ].
       
  1373 
       
  1374     (cursorMovementWhenUpdating == #beginOfText
       
  1375     or:[cursorMovementWhenUpdating == #begin]) ifTrue:[
       
  1376         ^ self cursorHome
       
  1377     ].
       
  1378     (cursorMovementWhenUpdating == #beginOfLine) ifTrue:[
       
  1379         ^ self cursorLine:prevCursorLine col:1.
       
  1380     ].
       
  1381 
       
  1382     "/ default: stay where it was
       
  1383     "/ self cursorLine:prevCursorLine col:prevCursorCol.
       
  1384 !
       
  1385 
       
  1386 setContents:something
       
  1387     |selType|
       
  1388 
       
  1389     undoSupport resetHistories.
       
  1390 
       
  1391     selType := typeOfSelection.
       
  1392     super setContents:something.
       
  1393     typeOfSelection := selType.
       
  1394 
       
  1395     "Created: / 31.3.1998 / 23:35:06 / cg"
       
  1396 ! !
       
  1397 
       
  1398 !EditTextView methodsFor:'accessing-dimensions'!
       
  1399 
       
  1400 absoluteXOfPosition:positionInText 
       
  1401     |accumulatedX container|
       
  1402 
       
  1403     accumulatedX := 0.
       
  1404     container := self.
       
  1405     [ container notNil ] whileTrue:[
       
  1406         accumulatedX := accumulatedX + container origin x.
       
  1407         container := container isTopView ifFalse:[
       
  1408                     container container
       
  1409                 ] ifTrue:[ nil ].
       
  1410     ].
       
  1411     ^ (self xOfPosition:positionInText) + accumulatedX
       
  1412 
       
  1413     "Created: / 16-02-2010 / 10:05:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
  1414 !
       
  1415 
       
  1416 absoluteYOfCursor
       
  1417 
       
  1418     | accumulatedY container |
       
  1419     accumulatedY := 0.
       
  1420     container := self.
       
  1421     [ container notNil ] whileTrue:[
       
  1422         accumulatedY := accumulatedY + container origin y.
       
  1423         container := container isTopView 
       
  1424             ifFalse:[container container]
       
  1425             ifTrue:[nil].
       
  1426     ].
       
  1427     ^(self yOfCursor) + accumulatedY
       
  1428 
       
  1429     "Created: / 27-05-2005 / 07:45:53 / janfrog"
       
  1430     "Modified: / 27-05-2005 / 23:03:40 / janfrog"
       
  1431 !
       
  1432 
       
  1433 xOfCursor
       
  1434     |point|
       
  1435 
       
  1436     cursorVisibleLine isNil ifTrue:[
       
  1437         "/ take the end of the selection, if any
       
  1438         (selectionStartLine notNil 
       
  1439             and:[ self listLineIsVisible:selectionEndLine ])
       
  1440         ifTrue:[
       
  1441             ^ self xOfCol:selectionEndCol inVisibleLine:selectionEndLine.
       
  1442         ].
       
  1443 
       
  1444 "/        point := device 
       
  1445 "/                    translatePoint:(device pointerPosition)
       
  1446 "/                    fromView:nil
       
  1447 "/                    toView:self.
       
  1448 "/        ((self bounds) containsPoint:point) ifTrue:[
       
  1449 "/            ^ point x
       
  1450 "/        ].
       
  1451 "/        ^ 0
       
  1452         ^ nil
       
  1453     ].
       
  1454     ^self xOfCol:cursorCol inVisibleLine:cursorVisibleLine.
       
  1455 
       
  1456     "Created: / 27-05-2005 / 07:43:41 / janfrog"
       
  1457 !
       
  1458 
       
  1459 xOfPosition: positionInText
       
  1460 
       
  1461     | line col |
       
  1462     line := self lineOfCharacterPosition: positionInText.
       
  1463     col  := positionInText - (self characterPositionOfLine:line col:1) + 1.
       
  1464     ^
       
  1465         (self xOfCol:col inVisibleLine:(self listLineToVisibleLine: line))
       
  1466             - viewOrigin x.
       
  1467 
       
  1468     "Created: / 16-02-2010 / 10:04:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
  1469 !
       
  1470 
       
  1471 yOfCursor
       
  1472 
       
  1473     ^self yOfVisibleLine:cursorVisibleLine.
       
  1474 
       
  1475     "Created: / 27-05-2005 / 07:43:41 / janfrog"
       
  1476 !
       
  1477 
       
  1478 yOfPosition: positionInText
       
  1479 
       
  1480     | line |
       
  1481     line := self lineOfCharacterPosition: positionInText.
       
  1482     ^self yOfVisibleLine:(self listLineToVisibleLine: line)
       
  1483 
       
  1484     "Created: / 16-02-2010 / 10:08:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
  1485 ! !
       
  1486 
       
  1487 !EditTextView methodsFor:'accessing-look'!
       
  1488 
       
  1489 cursorForegroundColor:color1 backgroundColor:color2
       
  1490     "set both cursor foreground and cursor background colors"
       
  1491 
       
  1492     |wasOn|
       
  1493 
       
  1494     wasOn := self hideCursor.
       
  1495     cursorFgColor := color1 onDevice:self graphicsDevice.
       
  1496     cursorBgColor := color2 onDevice:self graphicsDevice.
       
  1497     wasOn ifTrue:[self showCursor]
       
  1498 !
       
  1499 
       
  1500 cursorType
       
  1501     "return the style of the text cursor.
       
  1502      Currently, supported are: #none
       
  1503                                #block, #frame, #ibeam, #caret, #solidCaret
       
  1504                                #bigCaret and #bigSolidCaret"
       
  1505 
       
  1506     ^ cursorType
       
  1507 
       
  1508     "Modified: / 5.5.1999 / 14:52:33 / cg"
       
  1509 !
       
  1510 
       
  1511 cursorType:aCursorTypeSymbol
       
  1512     "set the style of the text cursor.
       
  1513      Currently, supported are: #none
       
  1514                                #block, #frame, #ibeam, #caret, #solidCaret
       
  1515                                #bigCaret and #bigSolidCaret"
       
  1516 
       
  1517     cursorType := aCursorTypeSymbol.
       
  1518 
       
  1519     "Created: 21.9.1997 / 13:42:23 / cg"
       
  1520     "Modified: 21.9.1997 / 13:43:35 / cg"
       
  1521 !
       
  1522 
       
  1523 cursorTypeNoFocus
       
  1524     "return the style of the text cursor when the view has no focus.
       
  1525      If left unspecified, this is the same as the regular cursorType."
       
  1526 
       
  1527     ^ cursorTypeNoFocus
       
  1528 
       
  1529     "Created: / 5.5.1999 / 14:52:46 / cg"
       
  1530 !
       
  1531 
       
  1532 cursorTypeNoFocus:aCursorTypeSymbol
       
  1533     "set the style of the text cursor when the view has no focus.
       
  1534      If left unspecified, this is the same as the regular cursorType."
       
  1535 
       
  1536     cursorTypeNoFocus := aCursorTypeSymbol
       
  1537 ! !
       
  1538 
       
  1539 !EditTextView methodsFor:'accessing-replace'!
       
  1540 
       
  1541 lastReplacementInfo
       
  1542     ^ lastReplacementInfo
       
  1543 !
       
  1544 
       
  1545 lastStringToReplace: aString
       
  1546 !
       
  1547 
       
  1548 previousReplacements
       
  1549     "accessor for the code completion"
       
  1550 
       
  1551     ^ lastReplacementInfo previousReplacements
       
  1552 ! !
       
  1553 
       
  1554 !EditTextView methodsFor:'change & update'!
       
  1555 
       
  1556 accept
       
  1557     "accept the current contents by executing the accept-action and/or
       
  1558      changeMessage."
       
  1559 
       
  1560     acceptEnabled == false ifTrue:[
       
  1561         self beep.
       
  1562         ^ self
       
  1563     ].
       
  1564     (disableIfInvisible == true and:[self reallyRealized not]) ifTrue:[
       
  1565         ^ self
       
  1566     ].
       
  1567 
       
  1568     lockUpdates := true.
       
  1569 
       
  1570     "/
       
  1571     "/ ST-80 way of doing it
       
  1572     "/
       
  1573     model notNil ifTrue:[
       
  1574         self sendChangeMessage:changeMsg with:self argForChangeMessage.
       
  1575         acceptChannel value:true withoutNotifying:self.
       
  1576     ].
       
  1577 
       
  1578     "/
       
  1579     "/ ST/X way of doing things
       
  1580     "/ as a historic (and temporary) leftover,
       
  1581     "/ the block is called with a stringCollection
       
  1582     "/ - not with the actual string
       
  1583     "/
       
  1584     acceptAction notNil ifTrue:[
       
  1585         acceptAction value:self list
       
  1586     ].
       
  1587 
       
  1588     lockUpdates := false.
       
  1589 
       
  1590     "Modified: / 30.1.1998 / 14:19:00 / cg"
       
  1591 !
       
  1592 
       
  1593 argForChangeMessage
       
  1594     "return the argument to be passed with the change notification.
       
  1595      Defined as separate method for easier subclassability."
       
  1596 
       
  1597     ^ self contents
       
  1598 
       
  1599     "Modified: 29.4.1996 / 12:42:14 / cg"
       
  1600 !
       
  1601 
       
  1602 getListFromModel
       
  1603     "get my contents from the model.
       
  1604      Redefined to ignore updates resulting from my own changes
       
  1605      (i.e. if lockUpdates is true)."
       
  1606 
       
  1607     "
       
  1608      ignore updates from my own change
       
  1609     "
       
  1610     lockUpdates ifTrue:[
       
  1611         lockUpdates := false.
       
  1612         ^ self
       
  1613     ].
       
  1614     super getListFromModel.
       
  1615     undoSupport resetHistories.
       
  1616 
       
  1617     "/ validate the cursorLine
       
  1618     (cursorLine notNil
       
  1619      and:[ cursorLine > list size ]) ifTrue:[
       
  1620         self cursorLine:list size + 1 col:1
       
  1621     ].
       
  1622 !
       
  1623 
       
  1624 update:something with:aParameter from:changedObject
       
  1625     changedObject == acceptChannel ifTrue:[
       
  1626         acceptChannel value == true ifTrue:[
       
  1627             self accept.
       
  1628         ].
       
  1629         ^ self.
       
  1630     ].
       
  1631     super update:something with:aParameter from:changedObject
       
  1632 
       
  1633     "Created: / 30.1.1998 / 14:15:56 / cg"
       
  1634     "Modified: / 1.2.1998 / 13:15:55 / cg"
       
  1635 ! !
       
  1636 
       
  1637 !EditTextView methodsFor:'cursor handling'!
       
  1638 
       
  1639 basicCursorReturn
       
  1640     "move cursor to start of next line; scroll if at end of visible text"
       
  1641 
       
  1642     |wasOn|
       
  1643 
       
  1644     self checkForExistingLine:(cursorLine + 1).
       
  1645     cursorVisibleLine notNil ifTrue:[
       
  1646         nFullLinesShown notNil ifTrue:[
       
  1647             (cursorVisibleLine >= nFullLinesShown) ifTrue:[self scrollDown]
       
  1648         ]
       
  1649     ].
       
  1650 
       
  1651     wasOn := self hideCursor.
       
  1652     self setValidatedCursorLine:(cursorLine + 1) col:1.
       
  1653     self makeCursorVisibleAndShowCursor:wasOn.
       
  1654 
       
  1655     "Modified: 22.5.1996 / 18:27:34 / cg"
       
  1656 !
       
  1657 
       
  1658 characterPositionOfCursor
       
  1659     ^ self characterPositionOfLine:cursorLine col:cursorCol
       
  1660 !
       
  1661 
       
  1662 cursorBacktab
       
  1663     "move cursor to prev tabstop"
       
  1664 
       
  1665     self cursorCol:(self prevTabBefore:cursorCol).
       
  1666 !
       
  1667 
       
  1668 cursorCol:newCol
       
  1669     "move cursor to some column in the current line"
       
  1670 
       
  1671     |wasOn|
       
  1672 
       
  1673     (cursorCol == newCol) ifTrue:[^ self].
       
  1674 
       
  1675     wasOn := self hideCursor.
       
  1676     self setValidatedCursorCol:newCol.
       
  1677     self makeCursorVisibleAndShowCursor:wasOn.
       
  1678 
       
  1679     "Modified: 22.5.1996 / 14:25:53 / cg"
       
  1680 !
       
  1681 
       
  1682 cursorDown
       
  1683     "move cursor down; scroll if at end of visible text;
       
  1684      beep if at end of physical text."
       
  1685 
       
  1686     |wasOn|
       
  1687 
       
  1688     self cursorDown:1.
       
  1689 
       
  1690     "/ cursor beyond text ?
       
  1691     cursorLine > list size ifTrue:[
       
  1692         wasOn := self hideCursor.
       
  1693         self setValidatedCursorLine:(list size + 1) col:cursorCol.
       
  1694         self makeCursorVisibleAndShowCursor:wasOn.
       
  1695         self beep.
       
  1696     ].
       
  1697 
       
  1698     "Modified: / 10.6.1998 / 17:00:23 / cg"
       
  1699 !
       
  1700 
       
  1701 cursorDown:n
       
  1702     "move cursor down by n lines; scroll if at end of visible text"
       
  1703 
       
  1704     |wasOn nv nL|
       
  1705 
       
  1706     (nL := cursorLine) isNil ifTrue:[
       
  1707         nL := firstLineShown
       
  1708     ].
       
  1709 
       
  1710     self st80EditMode ifTrue:[
       
  1711         nL == list size ifTrue:[
       
  1712             wasOn := self hideCursor.
       
  1713             self setValidatedCursorLine:(list size) col:(self listAt:list size) size + 1.
       
  1714             self makeCursorVisibleAndShowCursor:wasOn.
       
  1715             self beep.
       
  1716             ^ self.
       
  1717         ]
       
  1718     ].
       
  1719 
       
  1720     cursorVisibleLine notNil ifTrue:[
       
  1721         wasOn := self hideCursor.
       
  1722         nv := cursorVisibleLine + n - 1.
       
  1723         (nv >= nFullLinesShown) ifTrue:[
       
  1724             self scrollDown:(nv - nFullLinesShown + 1)
       
  1725         ].
       
  1726         self setValidatedCursorLine:(cursorLine + n) col:cursorCol.
       
  1727         self makeCursorVisibleAndShowCursor:wasOn.
       
  1728     ] ifFalse:[
       
  1729         self setValidatedCursorLine:(nL + n) col:cursorCol.
       
  1730         self makeCursorVisible.
       
  1731     ].
       
  1732 
       
  1733     "Modified: / 10.6.1998 / 16:59:17 / cg"
       
  1734 !
       
  1735 
       
  1736 cursorHome
       
  1737     "scroll to top AND move cursor to first line of text."
       
  1738 
       
  1739     self cursorLine:1 col:1
       
  1740 
       
  1741 "/    |wasOn|
       
  1742 "/
       
  1743 "/    wasOn := self hideCursor.
       
  1744 "/    self scrollToTop.
       
  1745 "/    cursorLine := cursorVisibleLine := 1.
       
  1746 "/    cursorCol := self validateCursorCol:1 inLine:cursorLine.
       
  1747 "/    self makeCursorVisibleAndShowCursor:wasOn.
       
  1748 
       
  1749     "Modified: 22.5.1996 / 18:26:42 / cg"
       
  1750 !
       
  1751 
       
  1752 cursorLeft
       
  1753     "move cursor to left"
       
  1754 
       
  1755     (cursorCol ~~ 1) ifTrue:[
       
  1756         self cursorCol:(cursorCol - 1)
       
  1757     ] ifFalse:[
       
  1758         cursorLine ~~ 1 ifTrue:[
       
  1759             self st80EditMode ifTrue:[
       
  1760                 self cursorUp.
       
  1761                 self cursorToEndOfLine.
       
  1762            ]
       
  1763         ]
       
  1764     ]
       
  1765 
       
  1766     "Modified: / 23.1.1998 / 12:37:13 / cg"
       
  1767 !
       
  1768 
       
  1769 cursorLeft:n
       
  1770     "move cursor to left"
       
  1771 
       
  1772     n timesRepeat:[
       
  1773         self cursorLeft
       
  1774     ].
       
  1775 !
       
  1776 
       
  1777 cursorLine:line col:col
       
  1778     "this positions onto physical - not visible - line"
       
  1779 
       
  1780     |wasOn newCol|
       
  1781 
       
  1782     ((line == cursorLine) and:[col == cursorCol]) ifTrue:[^ self].
       
  1783 
       
  1784     wasOn := self hideCursor.
       
  1785     self setValidatedCursorLine:line.
       
  1786 
       
  1787     (col < 1) ifTrue:[
       
  1788         newCol := 1
       
  1789     ] ifFalse:[
       
  1790         newCol := col.
       
  1791     ].
       
  1792     self st80EditMode ifTrue:[
       
  1793         (cursorLine == list size
       
  1794         and:[cursorLine ~~ line]) ifTrue:[
       
  1795             newCol := (self listAt:(list size)) size + 1.
       
  1796         ]
       
  1797     ].
       
  1798     self setValidatedCursorCol:newCol.
       
  1799     self makeCursorVisibleAndShowCursor:wasOn.
       
  1800 
       
  1801     "Modified: / 20.6.1998 / 18:19:06 / cg"
       
  1802 !
       
  1803 
       
  1804 cursorMovementAllowed
       
  1805     "return true, if the user may move the cursor around
       
  1806      (via button-click, or cursor-key with selection).
       
  1807      By default, true is returned, but this may be redefined
       
  1808      in special subclasses (such as a terminal view), where
       
  1809      this is not wanted"
       
  1810 
       
  1811     ^ true
       
  1812 
       
  1813     "Created: / 18.6.1998 / 14:11:16 / cg"
       
  1814 !
       
  1815 
       
  1816 cursorReturn
       
  1817     "move cursor to start of next line; scroll if at end of visible text"
       
  1818 
       
  1819     self basicCursorReturn
       
  1820 !
       
  1821 
       
  1822 cursorRight
       
  1823     "move cursor to right"
       
  1824 
       
  1825     |l|
       
  1826 
       
  1827     self st80EditMode ifTrue:[
       
  1828         l := (self listAt:cursorLine).
       
  1829         cursorCol >= (l size + 1) ifTrue:[
       
  1830             cursorLine < list size ifTrue:[
       
  1831                 self cursorReturn.
       
  1832             ].
       
  1833             ^ self
       
  1834         ]
       
  1835     ].
       
  1836     self cursorCol:(cursorCol + 1)
       
  1837 
       
  1838     "Modified: / 20.6.1998 / 18:19:07 / cg"
       
  1839 !
       
  1840 
       
  1841 cursorRight:n
       
  1842     "move cursor to right"
       
  1843 
       
  1844     n timesRepeat:[
       
  1845         self cursorRight
       
  1846     ].
       
  1847 !
       
  1848 
       
  1849 cursorShown:aBoolean
       
  1850     "change cursor visibility
       
  1851      return true if cursor was visible before."
       
  1852 
       
  1853     |oldState|
       
  1854 
       
  1855     aBoolean == cursorShown ifTrue:[
       
  1856         ^ cursorShown
       
  1857     ].
       
  1858 
       
  1859     oldState := cursorShown.
       
  1860 
       
  1861     aBoolean ifTrue:[
       
  1862         self drawCursor.
       
  1863     ] ifFalse:[
       
  1864         (cursorShown and:[shown]) ifTrue: [
       
  1865             self undrawCursor.
       
  1866         ].
       
  1867     ].
       
  1868     cursorShown := aBoolean.
       
  1869 
       
  1870     ^ oldState
       
  1871 
       
  1872     "Modified: / 30.3.1999 / 15:32:43 / stefan"
       
  1873     "Created: / 30.3.1999 / 15:59:30 / stefan"
       
  1874 !
       
  1875 
       
  1876 cursorTab
       
  1877     "move cursor to next tabstop"
       
  1878 
       
  1879     self cursorCol:(self nextTabAfter:cursorCol).
       
  1880 !
       
  1881 
       
  1882 cursorToBeginOfLine
       
  1883     "move cursor to the start of the current line"
       
  1884 
       
  1885     |textStart l|
       
  1886 
       
  1887     l := self listAt:cursorLine.
       
  1888     textStart := l isNil ifTrue:[1] ifFalse:[l indexOfNonSeparator].
       
  1889     cursorCol > textStart ifTrue:[
       
  1890         self cursorCol:textStart
       
  1891     ] ifFalse:[
       
  1892         self cursorCol:1
       
  1893     ]
       
  1894 
       
  1895     "Created: / 8.8.2004 / 18:51:21 / janfrog"
       
  1896 !
       
  1897 
       
  1898 cursorToBottom
       
  1899     "move cursor to the last line of text (col 1)"
       
  1900 
       
  1901     |wasOn newTop|
       
  1902 
       
  1903     wasOn := self hideCursor.
       
  1904 
       
  1905     newTop := list size - nFullLinesShown.
       
  1906     (newTop < 1) ifTrue:[
       
  1907         newTop := 1
       
  1908     ].
       
  1909     self scrollToLine:newTop.
       
  1910 
       
  1911     self setValidatedCursorLine:(list size) col:1.
       
  1912 
       
  1913     self makeCursorVisibleAndShowCursor:wasOn.
       
  1914 
       
  1915     "Modified: 22.5.1996 / 18:27:45 / cg"
       
  1916 !
       
  1917 
       
  1918 cursorToCharacterPosition:pos
       
  1919     "compute line/col from character position (1..)
       
  1920      and move the cursor onto that char"
       
  1921 
       
  1922     |line col|
       
  1923 
       
  1924     line := self lineOfCharacterPosition:pos.
       
  1925     col := pos - (self characterPositionOfLine:line col:1) + 1.
       
  1926     self cursorLine:line col:col
       
  1927 
       
  1928     "Created: / 15.1.1998 / 21:55:33 / cg"
       
  1929 !
       
  1930 
       
  1931 cursorToEnd
       
  1932     "move cursor down below last line of text"
       
  1933 
       
  1934     |wasOn newTop lineNr line|
       
  1935 
       
  1936     lineNr := list size.
       
  1937 
       
  1938     cursorLine >= lineNr ifTrue:[
       
  1939         line := self listAt:cursorLine.
       
  1940         (line isEmptyOrNil) ifTrue:[
       
  1941             ^ self
       
  1942         ]
       
  1943     ].
       
  1944 
       
  1945     wasOn := self hideCursor.
       
  1946 
       
  1947     lineNr := lineNr + 1.
       
  1948     newTop :=  lineNr - nFullLinesShown.
       
  1949     (newTop < 1) ifTrue:[
       
  1950         newTop := 1
       
  1951     ].
       
  1952     self scrollToLine:newTop.
       
  1953 
       
  1954     self setValidatedCursorLine:lineNr col:1.
       
  1955 
       
  1956     self makeCursorVisibleAndShowCursor:wasOn.
       
  1957 
       
  1958     "Modified: 22.5.1996 / 18:27:53 / cg"
       
  1959 !
       
  1960 
       
  1961 cursorToEndOfLine
       
  1962     "move cursor to end of current line"
       
  1963 
       
  1964     |line|
       
  1965 
       
  1966     line := (self listAt:cursorLine).
       
  1967     self cursorCol:(line size + 1)
       
  1968 
       
  1969     "Modified: 13.8.1997 / 15:34:02 / cg"
       
  1970 !
       
  1971 
       
  1972 cursorToEndOfText
       
  1973     "move cursor to the end of the text (behind the last character in last line)"
       
  1974 
       
  1975     |wasOn newTop lastLineLength pos|
       
  1976 
       
  1977     wasOn := self hideCursor.
       
  1978 
       
  1979     newTop := list size - nFullLinesShown.
       
  1980     (newTop < 1) ifTrue:[
       
  1981         newTop := 1
       
  1982     ].
       
  1983     self scrollToLine:newTop.
       
  1984 
       
  1985     self setValidatedCursorLine:list size.
       
  1986     lastLineLength := (self listAt:cursorLine) size.
       
  1987     pos := (lastLineLength==0) ifTrue:[0] ifFalse:[lastLineLength+1].
       
  1988     self setCursorCol:(self validateCursorCol:pos inLine:cursorLine).
       
  1989 
       
  1990     self makeCursorVisibleAndShowCursor:wasOn.
       
  1991 
       
  1992     "Modified: / 15-07-2011 / 20:14:43 / cg"
       
  1993 !
       
  1994 
       
  1995 cursorToEndOfWord
       
  1996     "move the cursor to the end of the word"
       
  1997 
       
  1998     (cursorLine > list size) ifTrue:[^ self].
       
  1999 
       
  2000     self wordAtLine:cursorLine col:cursorCol do:[
       
  2001         :beginLine :beginCol :endLine :endCol :style |
       
  2002 
       
  2003         self cursorLine:endLine col:endCol+1
       
  2004     ]
       
  2005 
       
  2006     "Created: / 28-06-2006 / 19:16:30 / cg"
       
  2007 !
       
  2008 
       
  2009 cursorToFirstVisibleLine
       
  2010     "place cursor into the first visible line; do not scroll."
       
  2011 
       
  2012     self cursorLine:(self visibleLineToAbsoluteLine:1) col:1
       
  2013 !
       
  2014 
       
  2015 cursorToLastVisibleLine
       
  2016     "place cursor into the first visible line; do not scroll."
       
  2017 
       
  2018     self cursorLine:(self visibleLineToAbsoluteLine:nFullLinesShown) col:1
       
  2019 !
       
  2020 
       
  2021 cursorToNextWord
       
  2022     "move the cursor to the beginning of the next word"
       
  2023 
       
  2024     |col line searching|
       
  2025 
       
  2026     (cursorLine > list size) ifTrue:[^ self].
       
  2027 
       
  2028     self 
       
  2029         wordAtLine:cursorLine col:cursorCol 
       
  2030         do:[
       
  2031             :beginLine :beginCol :endLine :endCol :style |
       
  2032 
       
  2033             line := endLine.
       
  2034             col := endCol + 1.
       
  2035             searching := true.
       
  2036             [searching and:[(self characterAtLine:line col:col) isSeparator]] whileTrue:[
       
  2037                 self wordAtLine:line col:col do:[
       
  2038                     :beginLine :beginCol :endLine :endCol :style |
       
  2039 
       
  2040                     (line > list size) ifTrue:[
       
  2041                         "break out"
       
  2042                         searching := false
       
  2043                     ] ifFalse:[
       
  2044                         line := endLine.
       
  2045                         col := endCol + 1.
       
  2046                     ]
       
  2047                 ]
       
  2048             ].
       
  2049             self cursorLine:line col:col
       
  2050     ]
       
  2051 !
       
  2052 
       
  2053 cursorToPreviousWord
       
  2054     "move the cursor to the beginning of this or the previous word"
       
  2055 
       
  2056     |col line searching l|
       
  2057 
       
  2058     (cursorLine > list size) ifTrue:[^ self].      "/ this is rubbish
       
  2059 
       
  2060     self wordAtLine:cursorLine col:cursorCol do:[
       
  2061         :beginLine :beginCol :endLine :endCol :style |
       
  2062 
       
  2063         line := beginLine.
       
  2064         col := beginCol.
       
  2065         style == #wordLeft ifTrue:[
       
  2066             col := col + 1
       
  2067         ].
       
  2068 
       
  2069         (cursorLine == line
       
  2070         and:[cursorCol == col]) ifTrue:[
       
  2071             searching := true.
       
  2072 
       
  2073             col > 1 ifTrue:[
       
  2074                 col := col - 1.
       
  2075             ].
       
  2076 
       
  2077             [searching] whileTrue:[
       
  2078                 (col == 1) ifTrue:[
       
  2079                     line == 1 ifTrue:[
       
  2080                         searching := false
       
  2081                     ] ifFalse:[
       
  2082                         line := line - 1.
       
  2083                         l := list at:line.
       
  2084                         col := l size + 1.
       
  2085                     ]
       
  2086                 ] ifFalse:[
       
  2087                     (self characterAtLine:line col:col) isSeparator ifFalse:[
       
  2088                         self wordAtLine:line col:col do:[
       
  2089                             :beginLine :beginCol :endLine :endCol :style |
       
  2090 
       
  2091                             line := beginLine.
       
  2092                             col := beginCol.
       
  2093                             style == #wordLeft ifTrue:[
       
  2094                                 col := col + 1
       
  2095                             ].
       
  2096                             searching := false.
       
  2097                         ]
       
  2098                     ] ifTrue:[
       
  2099                         col := col - 1
       
  2100                     ]
       
  2101                 ]
       
  2102             ]
       
  2103         ].
       
  2104         self cursorLine:line col:col
       
  2105     ]
       
  2106 
       
  2107     "Created: 8.3.1996 / 21:52:48 / cg"
       
  2108     "Modified: 8.3.1996 / 22:12:45 / cg"
       
  2109 !
       
  2110 
       
  2111 cursorToTop
       
  2112     "move cursor to absolute home"
       
  2113 
       
  2114     self cursorLine:1 col:1
       
  2115 !
       
  2116 
       
  2117 cursorUp
       
  2118     "move cursor up; scroll if at start of visible text"
       
  2119 
       
  2120     self cursorUp:1
       
  2121 !
       
  2122 
       
  2123 cursorUp:n
       
  2124     "move cursor up n lines; scroll if at start of visible text"
       
  2125 
       
  2126     |wasOn nv nl|
       
  2127 
       
  2128     cursorLine isNil ifTrue:[
       
  2129         self setCursorLine:(firstLineShown + nFullLinesShown - 1).
       
  2130     ].
       
  2131     nl := cursorLine - n.
       
  2132     nl < 1 ifTrue:[nl := 1].
       
  2133 
       
  2134     (nl ~~ cursorLine) ifTrue: [
       
  2135         wasOn := self hideCursor.
       
  2136         cursorVisibleLine notNil ifTrue:[
       
  2137             nv := cursorVisibleLine - n.
       
  2138             nv < 1 ifTrue:[
       
  2139                 self scrollUp:(nv negated + 1)
       
  2140             ].
       
  2141         ].
       
  2142         self setValidatedCursorLine:nl col:cursorCol.
       
  2143 "/        wasOn ifTrue:[self showCursor].
       
  2144         self makeCursorVisibleAndShowCursor:wasOn.
       
  2145     ]
       
  2146 
       
  2147     "Modified: 22.5.1996 / 18:28:11 / cg"
       
  2148 !
       
  2149 
       
  2150 cursorVisibleLine:visibleLineNr col:colNr
       
  2151     "put cursor to visibleline/col"
       
  2152 
       
  2153     |wasOn newCol listLine|
       
  2154 
       
  2155     wasOn := self hideCursor.
       
  2156 
       
  2157     listLine := self visibleLineToAbsoluteLine:visibleLineNr.
       
  2158     self setValidatedCursorLine:listLine.
       
  2159     cursorVisibleLine := visibleLineNr.
       
  2160 
       
  2161     newCol := colNr.
       
  2162     (newCol < 1) ifTrue:[
       
  2163         newCol := 1
       
  2164     ].
       
  2165     self setValidatedCursorCol:newCol.
       
  2166 
       
  2167     self makeCursorVisibleAndShowCursor:wasOn.
       
  2168 
       
  2169     "Modified: / 20.6.1998 / 18:40:28 / cg"
       
  2170 !
       
  2171 
       
  2172 cursorX:x y:y
       
  2173     "put cursor to position next to x/y coordinate in view"
       
  2174 
       
  2175     |line col|
       
  2176 
       
  2177     line := self visibleLineOfY:y.
       
  2178     col := self colOfX:x inVisibleLine:line.
       
  2179     self cursorVisibleLine:line col:col.
       
  2180 !
       
  2181 
       
  2182 drawCursor
       
  2183     "draw the cursor if shown and cursor is visible.
       
  2184      (but not, if there is a selection - to avoid confusion)"
       
  2185 
       
  2186     shown ifTrue:[
       
  2187         cursorVisibleLine notNil ifTrue:[
       
  2188             self hasSelection ifFalse:[
       
  2189                 self drawCursorCharacter
       
  2190             ]
       
  2191         ]
       
  2192     ]
       
  2193 !
       
  2194 
       
  2195 drawCursor:cursorType with:fgColor and:bgColor
       
  2196     "draw a cursor; the argument cursorType specifies what type
       
  2197      of cursor should be drawn.
       
  2198      Currently, supported are: #none, 
       
  2199                                #block, #frame, #ibeam, #caret, #solidCaret
       
  2200                                #bigCaret and #bigSolidCaret"
       
  2201 
       
  2202     |x y w char y2 x1 x2 oldPaint oldClip|
       
  2203 
       
  2204     self hasSelection ifTrue:[
       
  2205         "
       
  2206          hide cursor, if there is a selection
       
  2207         "
       
  2208         ^ super redrawVisibleLine:cursorVisibleLine col:cursorCol.
       
  2209     ].
       
  2210 
       
  2211     cursorType == #none ifTrue:[
       
  2212         ^ self
       
  2213     ].
       
  2214 
       
  2215     cursorType == #block ifTrue:[
       
  2216         super drawVisibleLine:cursorVisibleLine col:cursorCol with:fgColor and:bgColor.
       
  2217         ^ self
       
  2218     ].
       
  2219     x := (self xOfCol:cursorCol inVisibleLine:cursorVisibleLine) - viewOrigin x.
       
  2220     y := self yOfVisibleLine:cursorVisibleLine.
       
  2221 
       
  2222     oldPaint := self paint. "/ do not clobber GC
       
  2223     cursorType == #frame ifTrue:[
       
  2224         super redrawVisibleLine:cursorVisibleLine col:cursorCol.
       
  2225 
       
  2226         char := self characterUnderCursor asString.
       
  2227         self paint:bgColor.                       
       
  2228         self displayRectangleX:x y:y width:(gc font widthOf:char) height:fontHeight-2.
       
  2229     ] ifFalse:[
       
  2230         self paint:bgColor.
       
  2231         cursorType == #ibeam ifTrue:[
       
  2232             x1 := x - 1.
       
  2233             y2 := y + fontHeight - lineSpacing.
       
  2234             self displayLineFromX:x1 y:y toX:x1 y:y2.
       
  2235             self displayLineFromX:x y:y toX:x y:y2.
       
  2236             ^ self
       
  2237         ].
       
  2238 
       
  2239         cursorType == #Ibeam ifTrue:[
       
  2240             x1 := x - 1.
       
  2241             y := y + 1.
       
  2242             y2 := y + fontHeight - lineSpacing.
       
  2243             self displayLineFromX:x1 y:y toX:x1 y:y2.
       
  2244             self displayLineFromX:x y:y toX:x y:y2.
       
  2245             self displayLineFromX:x1-2 y:y toX:x+2 y:y.
       
  2246             self displayLineFromX:x1-2 y:y2 toX:x+2 y:y2.
       
  2247             ^ self
       
  2248         ].
       
  2249 
       
  2250         y := y + fontHeight - 3.
       
  2251         ((cursorType == #bigCaret) or:[cursorType == #bigSolidCaret]) ifTrue:[
       
  2252             w := (fontWidth * 2 // 3) max:4.
       
  2253             y2 := y + w + (w//2).
       
  2254         ] ifFalse:[
       
  2255             w := (fontWidth // 2) max:4.
       
  2256             y2 := y + w.
       
  2257         ].
       
  2258         x1 := x - w.
       
  2259         x2 := x + w.
       
  2260 
       
  2261         oldClip := self clippingRectangleOrNil.
       
  2262         self clippingRectangle:(margin@margin extent:(width-margin) @ (height-margin)).
       
  2263 
       
  2264         cursorType == #caret ifTrue:[
       
  2265             self lineWidth:2.
       
  2266             self displayLineFromX:x1 y:y2 toX:x y:y.
       
  2267             self displayLineFromX:x y:y toX:x2 y:y2.
       
  2268         ] ifFalse:[
       
  2269             "anything else: solidCaret"
       
  2270 
       
  2271             self fillPolygon:(Array with:(x1 @ y2)
       
  2272                                     with:(x @ y)
       
  2273                                     with:(x2 @ y2))
       
  2274         ].
       
  2275 
       
  2276         self clippingRectangle:oldClip
       
  2277     ].
       
  2278     self paint:oldPaint.
       
  2279 
       
  2280     "Modified: / 15.12.1999 / 22:24:17 / cg"
       
  2281 !
       
  2282 
       
  2283 drawCursorCharacter
       
  2284     "draw the cursor.
       
  2285      (i.e. the cursor if no selection)
       
  2286      - helper for many cursor methods"
       
  2287 
       
  2288     (hasKeyboardFocus
       
  2289      and:[self enabled
       
  2290      and:[self isReadOnly not]]) ifTrue:[
       
  2291         self drawFocusCursor
       
  2292     ] ifFalse:[
       
  2293         self drawNoFocusCursor
       
  2294     ]
       
  2295 
       
  2296     "Modified: / 23.3.1999 / 13:52:48 / cg"
       
  2297 !
       
  2298 
       
  2299 drawFocusCursor
       
  2300     "draw the cursor when the focus is in the view."
       
  2301 
       
  2302     self hasSelection ifTrue:[
       
  2303         ^ super redrawVisibleLine:cursorVisibleLine col:cursorCol.
       
  2304     ].
       
  2305     cursorType == #none ifTrue:[
       
  2306         ^ self undrawCursor
       
  2307     ].
       
  2308     self drawCursor:cursorType with:cursorFgColor and:cursorBgColor.
       
  2309 
       
  2310     "Modified: 22.9.1997 / 00:16:38 / cg"
       
  2311 !
       
  2312 
       
  2313 drawNoFocusCursor
       
  2314     "draw the cursor for the case when the view has no keyboard focus"
       
  2315 
       
  2316     |cType|
       
  2317 
       
  2318     self hasSelection ifTrue:[
       
  2319         ^ super redrawVisibleLine:cursorVisibleLine col:cursorCol.
       
  2320     ].
       
  2321 
       
  2322     cType := cursorTypeNoFocus ? cursorType.
       
  2323     cType == #none ifTrue:[
       
  2324         ^ self undrawCursor
       
  2325     ].
       
  2326 
       
  2327     cType == #block ifTrue:[
       
  2328         ^ self drawCursor:#frame with:cursorNoFocusFgColor and:cursorBgColor
       
  2329     ].
       
  2330 
       
  2331     ^ self drawCursor:cType with:cursorNoFocusFgColor and:cursorNoFocusFgColor.
       
  2332 
       
  2333     "Modified: 22.9.1997 / 00:16:13 / cg"
       
  2334 !
       
  2335 
       
  2336 gotoLine:aLineNumber
       
  2337     "position cursor onto line, aLineNumber.
       
  2338      Make certain that this line is visible"
       
  2339 
       
  2340     self makeLineVisible:aLineNumber.
       
  2341     self unselect.
       
  2342     self cursorLine:aLineNumber col:1
       
  2343 !
       
  2344 
       
  2345 hideCursor
       
  2346     "make cursor invisible if currently invisible"
       
  2347 
       
  2348     ^ self cursorShown:false
       
  2349 
       
  2350     "Modified: / 30.3.1999 / 16:02:28 / stefan"
       
  2351 !
       
  2352 
       
  2353 makeCursorVisible
       
  2354     "scroll text to make cursorline visible
       
  2355      (i.e. to have cursorLine in visible area)"
       
  2356 
       
  2357     |line col|
       
  2358 
       
  2359     cursorLine notNil ifTrue:[
       
  2360         line := cursorLine.
       
  2361         col := cursorCol.
       
  2362         "
       
  2363          if there is a selection, its better to
       
  2364          have its start being visible, instead of the end
       
  2365         "
       
  2366         (selectionStartLine notNil
       
  2367         and:[selectionEndLine notNil]) ifTrue:[
       
  2368             expandingTop ~~ false ifTrue:[
       
  2369                 line := selectionStartLine.
       
  2370                 col := selectionStartCol.
       
  2371             ] ifFalse:[
       
  2372                 line := selectionEndLine.
       
  2373                 col := selectionEndCol
       
  2374             ]
       
  2375         ].
       
  2376         self makeLineVisible:line.
       
  2377         self makeColVisible:col inLine:line
       
  2378     ]
       
  2379 
       
  2380     "Modified: 6.3.1996 / 13:46:46 / cg"
       
  2381 !
       
  2382 
       
  2383 makeCursorVisibleAndShowCursor:flag
       
  2384     "scroll to make cursorLine visible;
       
  2385      if flag is true, draw the cursor"
       
  2386 
       
  2387     self makeCursorVisible.
       
  2388     flag ifTrue:[self showCursor]
       
  2389 !
       
  2390 
       
  2391 setCursorCol:colNr
       
  2392     "strictly private: set the cursorCol"
       
  2393 
       
  2394     cursorCol := (colNr max:1).
       
  2395     cursorColHolder value:cursorCol.
       
  2396 !
       
  2397 
       
  2398 setCursorLine:lineNr
       
  2399     "strictly private: set the cursorLine"
       
  2400 
       
  2401     "/ self assert:(lineNr notNil).
       
  2402 
       
  2403     cursorLine := (lineNr ? 1).
       
  2404     cursorLineHolder value:cursorLine.
       
  2405     self updateCursorVisibleLine.
       
  2406 !
       
  2407 
       
  2408 setCursorLine:lineNr col:colNr
       
  2409     "strictly private: set the cursorLine, col and update the visibleLine"
       
  2410 
       
  2411     self setCursorLine:lineNr.
       
  2412     self setCursorCol:colNr.
       
  2413 !
       
  2414 
       
  2415 setValidatedCursorCol:colNr
       
  2416     "strictly private: set the cursorCol"
       
  2417 
       
  2418     self setCursorCol:(self validateCursorCol:colNr inLine:cursorLine).
       
  2419 !
       
  2420 
       
  2421 setValidatedCursorLine:lineNr
       
  2422     "strictly private: set the cursorLine and update the visibleLine"
       
  2423 
       
  2424     self setCursorLine:(self validateCursorLine:lineNr).
       
  2425 !
       
  2426 
       
  2427 setValidatedCursorLine:lineNr col:colNr
       
  2428     "strictly private: set the cursorLine, col and update the visibleLine"
       
  2429 
       
  2430     self setValidatedCursorLine:lineNr.
       
  2431     self setValidatedCursorCol:colNr.
       
  2432 !
       
  2433 
       
  2434 showCursor
       
  2435     "make cursor visible if currently invisible"
       
  2436 
       
  2437     ^ self cursorShown:true
       
  2438 
       
  2439     "Modified: / 30.3.1999 / 16:02:34 / stefan"
       
  2440 !
       
  2441 
       
  2442 undrawCursor
       
  2443     "undraw the cursor (i.e. redraw the character(s) under the cursor)"
       
  2444 
       
  2445     |prevCol line oldClip x y e1 e2 e3|
       
  2446 
       
  2447     cursorVisibleLine notNil ifTrue:[
       
  2448         prevCol := cursorCol - 1.
       
  2449 
       
  2450         "/ if there is any italic stuff in the cursor line,
       
  2451         "/ redraw it completely (because characters overlap).
       
  2452         cursorCol > 1 ifTrue:[
       
  2453             (line := self listAt:cursorLine) notNil ifTrue:[
       
  2454                 line hasChangeOfEmphasis ifTrue:[
       
  2455                     line size >= (cursorCol-1) ifTrue:[
       
  2456                         e1 := Text extractEmphasis:#italic from:(line emphasisAt:cursorCol-1).
       
  2457                         line size >= (cursorCol) ifTrue:[
       
  2458                             e2 := Text extractEmphasis:#italic from:(line emphasisAt:cursorCol).
       
  2459                             line size >= (cursorCol+1) ifTrue:[
       
  2460                                 e3 := Text extractEmphasis:#italic from:(line emphasisAt:cursorCol+1)
       
  2461                             ].
       
  2462                         ].
       
  2463                     ].
       
  2464                     (e1 notNil or:[e2 notNil or:[e3 notNil]]) ifTrue:[
       
  2465                         ^ super redrawVisibleLine:cursorVisibleLine
       
  2466                     ]
       
  2467                 ]
       
  2468             ]
       
  2469         ].
       
  2470 
       
  2471         ((cursorType == #caret)
       
  2472          or:[cursorType == #solidCaret
       
  2473          or:[cursorType == #bigSolidCaret
       
  2474          or:[cursorType == #bigCaret
       
  2475          or:[cursorType == #Ibeam]]]]) ifTrue:[
       
  2476             "caret-cursor touches 4 characters"
       
  2477             ((cursorCol > 1) and:[fontIsFixedWidth]) ifTrue:[
       
  2478                 super redrawVisibleLine:cursorVisibleLine-1 from:prevCol to:cursorCol.
       
  2479                 super redrawVisibleLine:cursorVisibleLine from:prevCol to:cursorCol.
       
  2480                 super redrawVisibleLine:cursorVisibleLine+1 from:prevCol to:cursorCol.
       
  2481             ] ifFalse:[
       
  2482                 "care for left margin"
       
  2483                 super redrawVisibleLine:cursorVisibleLine; redrawVisibleLine:cursorVisibleLine+1.
       
  2484             ].
       
  2485             ^ self
       
  2486         ].
       
  2487 
       
  2488         cursorType == #ibeam ifTrue:[
       
  2489             "ibeam-cursor touches 2 characters"
       
  2490             cursorCol > 1 ifTrue:[
       
  2491                 super redrawVisibleLine:cursorVisibleLine from:prevCol to:cursorCol.
       
  2492             ] ifFalse:[
       
  2493                 "care for left margin"
       
  2494                 super redrawVisibleLine:cursorVisibleLine.
       
  2495             ].
       
  2496             ^ self
       
  2497         ].
       
  2498 
       
  2499         "block cursor is simple - just one character under cursor"
       
  2500 
       
  2501         "/ however, if italic characters are involved, we must care
       
  2502         "/ for the chars before/after the cursor.
       
  2503         "/ We redraw the part of the previous character which got
       
  2504         "/ detroyed by the block cursor.
       
  2505         "/ (must change the clip, to avoid destroying the prev-prev character)
       
  2506 
       
  2507         line := self visibleAt:cursorVisibleLine.
       
  2508         (line notNil and:[line isText]) ifTrue:[
       
  2509             cursorCol > 1 ifTrue:[
       
  2510                 oldClip := self clippingRectangleOrNil.
       
  2511                 x := (self xOfCol:cursorCol inVisibleLine:cursorVisibleLine) - viewOrigin x.
       
  2512                 y := self yOfVisibleLine:cursorVisibleLine.
       
  2513                 self clippingRectangle:(x@y extent:((gc font width * 2) @ fontHeight)).
       
  2514                 super redrawVisibleLine:cursorVisibleLine from:cursorCol-1 to:cursorCol.
       
  2515                 self clippingRectangle:oldClip.
       
  2516                 ^ self.
       
  2517             ].
       
  2518         ].
       
  2519         super redrawVisibleLine:cursorVisibleLine col:cursorCol
       
  2520     ]
       
  2521 
       
  2522     "Modified: / 15.12.1999 / 22:25:59 / cg"
       
  2523 !
       
  2524 
       
  2525 updateCursorVisibleLine
       
  2526     "strictly private: set the visibleLine from the cursorLine.
       
  2527      notice: visibleLine will be set to nil if the cursor is not visible"
       
  2528 
       
  2529     cursorVisibleLine := self listLineToVisibleLine:cursorLine.
       
  2530 !
       
  2531 
       
  2532 validateCursorCol:col inLine:line
       
  2533     "check of col is a valid cursor position; return a new col-nr if not.
       
  2534      Here, no limits are enforced (and col is returned),
       
  2535      but it may be redefined in EditFields or views which dont like the
       
  2536      cursor to be positioned behind the end of a textLine (vi/st-80 behavior)"
       
  2537 
       
  2538     |l max|
       
  2539 
       
  2540     "/ in ST80 mode,
       
  2541     "/ the cursor may not be positioned beyond the
       
  2542     "/ end of a line or beyond the last line of the text
       
  2543 
       
  2544     self st80EditMode ifTrue:[
       
  2545         l := (self listAt:line).
       
  2546         max := l size + 1.
       
  2547         col > max ifTrue:[
       
  2548             ^ max
       
  2549         ]
       
  2550     ].
       
  2551     ^ col
       
  2552 
       
  2553     "Created: / 22.5.1996 / 14:25:30 / cg"
       
  2554     "Modified: / 20.6.1998 / 18:19:24 / cg"
       
  2555 !
       
  2556 
       
  2557 validateCursorLine:line
       
  2558     "check of line is a valid cursor line; return a fixed line-nr if not.
       
  2559      Here, no limits are enforced (and line is returned), but it may be
       
  2560      redefined in views which dont like the cursor to be positioned
       
  2561      behind the end of the text (vi/st-80 behavior), or want to
       
  2562      skip reserved regions"
       
  2563 
       
  2564     "/
       
  2565     "/ in st80Mode, the cursor may not be positioned
       
  2566     "/ beyond the last line
       
  2567     "/
       
  2568     self st80EditMode ifTrue:[
       
  2569         ^ (line min:(list size)) max:1
       
  2570     ].
       
  2571     ^ line
       
  2572 
       
  2573     "Created: / 22.5.1996 / 18:22:23 / cg"
       
  2574     "Modified: / 20.6.1998 / 18:19:26 / cg"
       
  2575 !
       
  2576 
       
  2577 withCursorOffDo:aBlock
       
  2578     "evaluate aBlock with cursor off; turn it on afterwards."
       
  2579 
       
  2580     (shown not or:[cursorShown not]) ifTrue:[
       
  2581         ^ aBlock value
       
  2582     ].
       
  2583     self hideCursor.
       
  2584     aBlock ensure:[
       
  2585         self showCursor
       
  2586     ]
       
  2587 ! !
       
  2588 
       
  2589 !EditTextView methodsFor:'drag & drop'!
       
  2590 
       
  2591 allowDrop:aBoolean
       
  2592     "enable/disable drop support"
       
  2593 
       
  2594     aBoolean ifFalse:[
       
  2595         dropTarget := nil.
       
  2596     ] ifTrue:[
       
  2597         dropTarget isNil ifTrue:[
       
  2598             dropTarget := DropTarget 
       
  2599                                 receiver:self
       
  2600                                 argument:nil
       
  2601                                 dropSelector:#'drop:'
       
  2602                                 canDropSelector:#'canDrop:'
       
  2603         ]
       
  2604     ].
       
  2605 !
       
  2606 
       
  2607 canDrop:aDropContext
       
  2608     "public from d&d.
       
  2609      I accept textObjects and fileObjects only."
       
  2610 
       
  2611     "/ cg: disabled to avoid unintended drop (is same as copy-past, anyway)
       
  2612     aDropContext sourceWidget == self ifTrue:[^ false].
       
  2613     ^ self canDropObjects:aDropContext dropObjects
       
  2614 
       
  2615     "Modified: / 13-10-2006 / 17:41:09 / cg"
       
  2616 !
       
  2617 
       
  2618 canDropObjects:aCollectionOfDropObjects
       
  2619     "public from d&d.
       
  2620      I accept textObjects and fileObjects only."
       
  2621 
       
  2622     self checkModificationsAllowed ifFalse:[^ false].
       
  2623 
       
  2624     aCollectionOfDropObjects isEmpty ifTrue:[ ^ false ].
       
  2625     ^ aCollectionOfDropObjects conform:[:obj| (obj isTextObject or:[obj isFileObject])]
       
  2626 
       
  2627     "Created: / 13-10-2006 / 15:56:57 / cg"
       
  2628     "Modified: / 13-10-2006 / 17:41:14 / cg"
       
  2629 !
       
  2630 
       
  2631 drop:aDropContext
       
  2632     "public from d&d.
       
  2633      drop objects (new API)"
       
  2634 
       
  2635     self dropObjects:(aDropContext dropObjects)
       
  2636 
       
  2637     "Modified: / 13-10-2006 / 17:41:19 / cg"
       
  2638 !
       
  2639 
       
  2640 dropFileObject:aDropObject
       
  2641     "drop objects
       
  2642      For bw. compatibility, also collections of drop objects are handled (may vanish)"
       
  2643 
       
  2644     |answer text fn pasteWhat sensor dontAskAgainHolder enforcedDropMode app|
       
  2645 
       
  2646     pasteWhat := #name.
       
  2647 
       
  2648     fn := aDropObject asFilename.
       
  2649     (fn exists and:[fn isRegularFile]) ifTrue:[
       
  2650         enforcedDropMode := UserPreferences current enforcedDropModeForFiles.
       
  2651         (enforcedDropMode notNil 
       
  2652         and:[enforcedDropMode ~~ #name or:[fn fileSize <= (1024*1024)]]) ifTrue:[
       
  2653             pasteWhat := enforcedDropMode.
       
  2654         ] ifFalse:[
       
  2655             sensor := self sensor.
       
  2656             (sensor shiftDown or:[sensor ctrlDown]) ifTrue:[
       
  2657                 pasteWhat := #name.
       
  2658             ] ifFalse:[
       
  2659                 (sensor metaDown) ifTrue:[
       
  2660                     pasteWhat := #contents.
       
  2661                 ] ifFalse:[
       
  2662                     dontAskAgainHolder := false asValue.
       
  2663                     answer := Dialog
       
  2664                         confirmWithCancel:(resources
       
  2665                                             stringWithCRs:'Drop the Filename (%1)\or its Contents ?\\Hint: bypass this dialog by pressing SHIFT/CTRL or ALT during the next drop.\SHIFT/CTRL to drop the name, ALT for the contents.'
       
  2666                                             with:fn name allBold)
       
  2667                         labels:#( 'Cancel' 'Name' 'Contents' )
       
  2668                         values:#( nil #name #contents )
       
  2669                         default:#contents
       
  2670                         check:(resources string:'Do not ask again; instead, always paste the contents of small files.') on:dontAskAgainHolder
       
  2671                         title:(resources string:'Drop What').
       
  2672                     answer isNil ifTrue:[ ^ self ].
       
  2673 
       
  2674                     dontAskAgainHolder value ifTrue:[
       
  2675                         UserPreferences current enforcedDropModeForFiles:#contents
       
  2676                     ].
       
  2677                     pasteWhat := answer.
       
  2678                 ]
       
  2679             ]
       
  2680         ].
       
  2681     ].
       
  2682 
       
  2683     pasteWhat == #name ifTrue:[
       
  2684         text := fn pathName
       
  2685     ] ifFalse:[
       
  2686         self withWaitCursorDo:[
       
  2687             text := fn contentsOfEntireFile
       
  2688         ].
       
  2689         (app := self application) notNil ifTrue:[
       
  2690             app droppedFile:fn in:self
       
  2691         ].
       
  2692     ].
       
  2693 
       
  2694     self 
       
  2695         undoablePaste:text 
       
  2696         info:'Drop File'.
       
  2697 
       
  2698     "Created: / 13-10-2006 / 17:38:31 / cg"
       
  2699     "Modified: / 28-07-2007 / 13:27:09 / cg"
       
  2700 !
       
  2701 
       
  2702 dropObject:aDropObject
       
  2703     "drop objects
       
  2704      For bw. compatibility, also collections of drop objects are handled (may vanish)"
       
  2705 
       
  2706     |text|
       
  2707 
       
  2708     (aDropObject isFileObject) ifTrue:[
       
  2709         self dropFileObject:aDropObject
       
  2710     ] ifFalse:[
       
  2711         aDropObject isTextObject ifTrue:[
       
  2712             text := aDropObject theObject.
       
  2713             text isStringCollection ifTrue:[
       
  2714                 text := text asStringWithoutFinalCR
       
  2715             ].
       
  2716         ] ifFalse:[
       
  2717             text := aDropObject theObject asString
       
  2718         ].
       
  2719         self 
       
  2720             undoablePaste:text 
       
  2721             info:'Drop'.
       
  2722     ].
       
  2723 
       
  2724     "Created: / 13-10-2006 / 17:37:05 / cg"
       
  2725     "Modified: / 28-07-2007 / 13:26:53 / cg"
       
  2726 !
       
  2727 
       
  2728 dropObjects:aCollectionOfDropObjects
       
  2729     "public from d&d.
       
  2730      drop objects (old API)"
       
  2731 
       
  2732     aCollectionOfDropObjects do:[:el |
       
  2733         self dropObject:el
       
  2734     ].
       
  2735 
       
  2736     "Created: / 13-10-2006 / 15:59:40 / cg"
       
  2737     "Modified: / 13-10-2006 / 17:41:23 / cg"
       
  2738 ! !
       
  2739 
       
  2740 !EditTextView methodsFor:'editing'!
       
  2741 
       
  2742 convertSelectionToLowercaseOrUppercaseOrUppercaseFirst
       
  2743     "toLower/toUppercaseFirst/toUpper selected text"
       
  2744 
       
  2745     |line1 line2|
       
  2746 
       
  2747     line1 := self selectionStartLine.
       
  2748     line2 := self selectionEndLine.
       
  2749     line1 isNil ifTrue:[
       
  2750         line1 := self perform:#cursorLine ifNotUnderstood:nil.
       
  2751         line1 notNil ifTrue:[
       
  2752             line2 := line1
       
  2753         ]
       
  2754     ].
       
  2755     line1 notNil ifTrue:[
       
  2756         line1 to:line2 do:[:lineNr |
       
  2757             |line col1 col2 isAllLower isLowerFirst isAllUpper isUpperFirst
       
  2758              makeLowercase makeUppercase makeUppercaseFirst makeLowercaseFirst|
       
  2759 
       
  2760             line := (self listAt:lineNr) copy.
       
  2761             line size > 0 ifTrue:[
       
  2762                 lineNr == line1 ifTrue:[
       
  2763                     col1 := selectionStartCol.
       
  2764                 ] ifFalse:[
       
  2765                     col1 := 1.
       
  2766                 ].
       
  2767                 lineNr == line2 ifTrue:[
       
  2768                     col2 := selectionEndCol.
       
  2769                 ] ifFalse:[
       
  2770                     col2 := (self listAt:lineNr) size.
       
  2771                 ].
       
  2772                 isAllLower := isAllUpper := isUpperFirst := isLowerFirst := true.
       
  2773                 col1 to:col2 do:[:col |
       
  2774                     |ch|
       
  2775 
       
  2776                     ch := line at:col.
       
  2777                     ch isUppercase ifTrue:[
       
  2778                         isAllLower := false.
       
  2779                         col == col1 ifTrue:[
       
  2780                             isLowerFirst := false.
       
  2781                         ].
       
  2782                     ] ifFalse:[
       
  2783                         ch isLowercase ifTrue:[
       
  2784                             isAllUpper := false.
       
  2785                             col == col1 ifTrue:[
       
  2786                                 isUpperFirst := false.
       
  2787                             ].
       
  2788                         ]
       
  2789                     ].
       
  2790                 ].
       
  2791 
       
  2792                 makeLowercase := makeUppercase := makeUppercaseFirst := makeLowercaseFirst := false.
       
  2793                 isLowerFirst ifTrue:[
       
  2794                     makeUppercaseFirst := true.
       
  2795                 ] ifFalse:[
       
  2796                     "/ must remember where we come from - otherwise, we end up
       
  2797                     "/ in upperFirst - lowerFirst cycle.
       
  2798                     "/ think about a good place to store this state
       
  2799                     false "(isUpperFirst and:[isAllUpper not])" ifTrue:[
       
  2800                         makeLowercaseFirst := true.
       
  2801                      ] ifFalse:[
       
  2802                         isAllUpper ifTrue:[
       
  2803                             makeLowercase := true.
       
  2804                         ] ifFalse:[
       
  2805                             makeUppercase := true.
       
  2806                         ]
       
  2807                     ]
       
  2808                 ].
       
  2809                 makeUppercaseFirst ifTrue:[
       
  2810                     line at:col1 put:(line at:col1) asUppercase.
       
  2811                 ] ifFalse:[
       
  2812                     makeLowercaseFirst ifTrue:[
       
  2813                         line at:col1 put:(line at:col1) asLowercase.
       
  2814                     ] ifFalse:[
       
  2815                         col1 to:col2 do:[:col |
       
  2816                             |ch|
       
  2817 
       
  2818                             ch := line at:col.
       
  2819                             ch := makeLowercase
       
  2820                                     ifTrue:[ ch asLowercase ]
       
  2821                                     ifFalse:[
       
  2822                                         makeUppercase
       
  2823                                             ifTrue:[ ch asUppercase ]
       
  2824                                             ifFalse:[
       
  2825                                                 col == col1
       
  2826                                                     ifTrue:[ ch asUppercase ]
       
  2827                                                     ifFalse:[ ch asLowercase ]
       
  2828                                             ]
       
  2829                                     ].
       
  2830                             line at:col put:ch.
       
  2831                         ].
       
  2832                     ].
       
  2833                 ].
       
  2834                 self withoutRedrawAt:lineNr put:line.
       
  2835                 self invalidateLine:lineNr.
       
  2836             ].
       
  2837         ].
       
  2838     ]
       
  2839 
       
  2840     "Created: / 14-07-2011 / 11:40:26 / cg"
       
  2841 !
       
  2842 
       
  2843 copyAndDeleteSelection
       
  2844     "copy the selection into the pastBuffer and delete it"
       
  2845 
       
  2846     selectionStartLine notNil ifTrue:[
       
  2847         self setClipboardText:(self selection).
       
  2848         self deleteSelection.
       
  2849     ].
       
  2850 
       
  2851     "Created: 27.1.1996 / 16:23:28 / cg"
       
  2852 !
       
  2853 
       
  2854 deleteCharAtCursor
       
  2855     "delete single character under cursor; does not merge lines"
       
  2856 
       
  2857     |wasOn|
       
  2858 
       
  2859     wasOn := self hideCursor.
       
  2860     self deleteCharAtLine:cursorLine col:cursorCol.
       
  2861     wasOn ifTrue:[self showCursor]
       
  2862 !
       
  2863 
       
  2864 deleteCharAtLine:lineNr col:colNr
       
  2865     "delete a single character at colNr in line lineNr"
       
  2866 
       
  2867     self st80EditMode ifTrue:[
       
  2868         (self listAt:cursorLine) size + 1 = colNr ifTrue:[
       
  2869             | wasOn |
       
  2870             wasOn := self hideCursor.
       
  2871             self
       
  2872                 cursorReturn;
       
  2873                 cursorCol:1;
       
  2874                 deleteCharBeforeCursor.
       
  2875             wasOn ifTrue:[ self showCursor].
       
  2876             ^ self.
       
  2877         ].
       
  2878     ].
       
  2879 
       
  2880     self deleteCharsAtLine:lineNr fromCol:colNr toCol:colNr
       
  2881 !
       
  2882 
       
  2883 deleteCharBeforeCursor
       
  2884     "delete single character to the left of cursor and move cursor to left"
       
  2885 
       
  2886     |soCol wasOn lineNrAboveCursor ln originalLine prevTab|
       
  2887 
       
  2888     wasOn := self hideCursor.
       
  2889     (autoIndent and:[ (tabPositions includes:cursorCol)]) ifTrue:[
       
  2890         prevTab := (self prevTabBefore:cursorCol) max:1.
       
  2891         ln := originalLine := (list at:cursorLine ifAbsent:'') ? ''.
       
  2892         ln size < prevTab ifTrue:[
       
  2893             ln := ln , (String new:prevTab withAll:Character space).
       
  2894         ].
       
  2895         (ln copyTo:prevTab) isBlank ifTrue:[
       
  2896             (ln copyFrom:prevTab+1) isBlank ifTrue:[
       
  2897                 cursorCol > prevTab ifTrue:[
       
  2898                     self st80EditMode ifTrue:[
       
  2899                         "/ ensure that there is no conflict here: st80EditMode will
       
  2900                         "/ not allow a cursor position beyond the end of line,
       
  2901                         "/ so avoid that cursorLine:col: will force us to the beginning of the line
       
  2902                         originalLine size < prevTab ifTrue:[
       
  2903                             self basicListAt:cursorLine put:ln
       
  2904                         ]
       
  2905                     ].
       
  2906                     self cursorLine:cursorLine col:prevTab.
       
  2907                     wasOn ifTrue:[ self showCursor ].
       
  2908                     ^  self
       
  2909                 ].
       
  2910             ] ifFalse:[
       
  2911                 self deleteFromLine:cursorLine col:prevTab toLine:cursorLine col:cursorCol-1.
       
  2912                 self cursorLine:cursorLine col:prevTab.
       
  2913                 wasOn ifTrue:[ self showCursor ].
       
  2914                 ^  self.
       
  2915             ]
       
  2916         ].
       
  2917     ].
       
  2918 
       
  2919 "/        (autoIndent
       
  2920 "/    and:[cursorCol  ~~ 1
       
  2921 "/    and:[cursorLine <= (list size)]])
       
  2922 "/     ifTrue:[
       
  2923 "/        soCol := (self leftIndentForLine:cursorLine) + 1.
       
  2924 "/
       
  2925 "/        (cursorCol == soCol and:[soCol > 1]) ifTrue:[
       
  2926 "/            ln := list at:cursorLine.
       
  2927 "/            (ln notNil and:[(ln indexOfNonSeparatorStartingAt:1) < soCol]) ifTrue:[
       
  2928 "/                soCol := 1
       
  2929 "/            ]
       
  2930 "/        ]
       
  2931 "/    ] ifFalse:[
       
  2932         soCol := 1.
       
  2933 "/    ].
       
  2934 
       
  2935     (cursorCol ~~ soCol and:[cursorCol ~~ 1]) ifTrue:[
       
  2936         "
       
  2937          somewhere in the middle of a line
       
  2938         "
       
  2939         self cursorLeft.
       
  2940         self deleteCharAtLine:cursorLine col:cursorCol.
       
  2941     ] ifFalse:[
       
  2942         "
       
  2943          at begin of line - merge with previous line;
       
  2944          except for the very first line.
       
  2945         "
       
  2946         (cursorLine == 1) ifFalse:[
       
  2947             lineNrAboveCursor := self validateCursorLine:(cursorLine - 1).
       
  2948             lineNrAboveCursor < cursorLine ifTrue:[
       
  2949                 (lineNrAboveCursor > 0 and:[lineNrAboveCursor > list size]) ifTrue:[
       
  2950                     "/ we are beyond the end of the text.
       
  2951                     "/ move the cursor to the previous line.
       
  2952                     self cursorLine:lineNrAboveCursor col:1.
       
  2953                 ] ifFalse:[
       
  2954                     self mergeLine:lineNrAboveCursor removeBlanks:false.
       
  2955                 ]
       
  2956             ]
       
  2957         ]
       
  2958     ].
       
  2959     wasOn ifTrue:[ self showCursor ]
       
  2960 
       
  2961     "Modified: / 16.1.1998 / 22:33:04 / cg"
       
  2962 !
       
  2963 
       
  2964 deleteCharsAtLine:lineNr fromCol:colNr
       
  2965     "delete characters from colNr up to the end in line lineNr"
       
  2966 
       
  2967     |line|
       
  2968 
       
  2969     (line := self listAt:lineNr) notNil ifTrue:[
       
  2970         self deleteCharsAtLine:lineNr fromCol:colNr toCol:(line size)
       
  2971     ]
       
  2972 
       
  2973 !
       
  2974 
       
  2975 deleteCharsAtLine:lineNr fromCol:startCol toCol:endCol
       
  2976     "delete characters from startCol to endCol in line lineNr"
       
  2977 
       
  2978     |deleted|
       
  2979 
       
  2980     deleted := self textFromLine:lineNr col:startCol toLine:lineNr col:endCol.
       
  2981     self basicDeleteCharsAtLine:lineNr fromCol:startCol toCol:endCol.
       
  2982     self addUndo:(PasteString line:lineNr col:startCol string:deleted info:'delete').
       
  2983 !
       
  2984 
       
  2985 deleteCharsAtLine:lineNr toCol:colNr
       
  2986     "delete characters from start up to colNr in line lineNr"
       
  2987 
       
  2988     self deleteCharsAtLine:lineNr fromCol:1 toCol:colNr
       
  2989 
       
  2990 
       
  2991 !
       
  2992 
       
  2993 deleteCursorLine
       
  2994     "delete the line where the cursor sits"
       
  2995 
       
  2996     self deleteLine:cursorLine
       
  2997 !
       
  2998 
       
  2999 deleteFromCharacterPosition:charPos1 to:charPos2
       
  3000     "delete a substring at a character position"
       
  3001 
       
  3002     |line1 col1 line2 col2|
       
  3003 
       
  3004     line1 := self lineOfCharacterPosition:charPos1.
       
  3005     col1 := charPos1 - (self characterPositionOfLine:line1 col:1) + 1.
       
  3006     col1 == 0 ifTrue:[
       
  3007         line1 := line1 - 1.
       
  3008         col1 := (self listAt:line1) size + 1.
       
  3009     ].
       
  3010 
       
  3011     line2 := self lineOfCharacterPosition:charPos2.
       
  3012     col2 := charPos2 - (self characterPositionOfLine:line2 col:1) + 1.
       
  3013 
       
  3014     self deleteFromLine:line1 col:col1 toLine:line2 col:col2.
       
  3015 !
       
  3016 
       
  3017 deleteFromLine:startLine col:startCol toLine:endLine col:endCol
       
  3018     "delete all text from startLine/startCol to endLine/endCol -
       
  3019      joining lines if nescessary"
       
  3020 
       
  3021     |line newLine lineSize nMore|
       
  3022 
       
  3023     self checkModificationsAllowed ifFalse:[ ^ self].
       
  3024     list isNil ifTrue:[^ self].
       
  3025     startLine > list size ifTrue:[ ^ self]. "/ deleted space below text
       
  3026 
       
  3027     (startLine == endLine) ifTrue:[
       
  3028         "/ delete chars within a line
       
  3029         self deleteCharsAtLine:startLine fromCol:startCol toCol:endCol.
       
  3030         ^ self
       
  3031     ].
       
  3032 
       
  3033     ((startCol == 1) and:[endCol == 0]) ifTrue:[
       
  3034         "/ delete full lines only
       
  3035         endLine > startLine ifTrue:[
       
  3036             self deleteFromLine:startLine toLine:(endLine - 1)
       
  3037         ].
       
  3038         ^ self
       
  3039     ].
       
  3040 
       
  3041     "/ delete right rest of 1st line
       
  3042     self deleteCharsAtLine:startLine fromCol:(startCol max:1).
       
  3043 
       
  3044     "/ delete the inner lines ...
       
  3045     endLine > (startLine + 1) ifTrue:[
       
  3046         self deleteFromLine:(startLine + 1) toLine:(endLine - 1)
       
  3047     ].
       
  3048 
       
  3049     (endCol ~~ 0) ifTrue:[
       
  3050         "/ delete the left rest of the last line
       
  3051 
       
  3052         self deleteCharsAtLine:(startLine + 1) toCol:endCol.
       
  3053 
       
  3054         "/ must add blanks, if startCol lies beyond end of startLine
       
  3055         startLine <= list size ifTrue:[
       
  3056             line := list at:startLine.
       
  3057             lineSize := line size.
       
  3058             (startCol > lineSize) ifTrue:[
       
  3059                 newLine := line.
       
  3060                 line isNil ifTrue:[
       
  3061                     newLine := String new:(startCol - 1)
       
  3062                 ] ifFalse:[
       
  3063                     nMore := startCol - 1 - lineSize.
       
  3064                     nMore > 0 ifTrue:[
       
  3065                         newLine := line , (line species new:nMore)
       
  3066                     ]
       
  3067                 ].
       
  3068                 newLine ~~ line ifTrue:[
       
  3069                     self basicListAt:startLine put:newLine.
       
  3070                 ].
       
  3071                 "/ TODO: remember old maxwidth of linerange,
       
  3072                 "/ only clear widthOfWidestLine, if this max
       
  3073                 "/ length was (one of) the longest.
       
  3074                 "/ avoids slow delete with huge texts.
       
  3075                 widthOfWidestLine := nil. "/ i.e. unknown
       
  3076                 self textChanged.
       
  3077             ]
       
  3078         ]
       
  3079     ].
       
  3080 
       
  3081     "/ merge the left rest of 1st line with right rest of last line into one
       
  3082     self mergeLine:startLine removeBlanks:false
       
  3083 
       
  3084     "Modified: / 10-11-1998 / 23:52:59 / cg"
       
  3085     "Modified: / 18-03-2011 / 18:25:01 / az"
       
  3086 !
       
  3087 
       
  3088 deleteFromLine:startLineNr toLine:endLineNr
       
  3089     "delete some lines"
       
  3090 
       
  3091     |deleted|
       
  3092 
       
  3093     deleted := self textFromLine:startLineNr col:1 toLine:endLineNr+1 col:0.
       
  3094     self basicDeleteFromLine:startLineNr toLine:endLineNr.
       
  3095     self addUndo:(PasteString line:startLineNr col:1 string:deleted info:'delete').
       
  3096 !
       
  3097 
       
  3098 deleteLine:lineNr
       
  3099     "delete line"
       
  3100 
       
  3101     self deleteFromLine:lineNr toLine:lineNr
       
  3102 
       
  3103 
       
  3104 !
       
  3105 
       
  3106 deleteLineWithoutRedraw:lineNr
       
  3107     "delete line - no redraw;
       
  3108      return true, if something was really deleted"
       
  3109 
       
  3110     |deleted ret|
       
  3111 
       
  3112     deleted := self textFromLine:lineNr col:1 toLine:lineNr+1 col:0.
       
  3113     ret := self basicDeleteLineWithoutRedraw:lineNr.
       
  3114     self addUndo:(PasteString line:lineNr col:1 string:deleted info:'delete').
       
  3115     ^ ret.
       
  3116 !
       
  3117 
       
  3118 deleteLinesWithoutRedrawFrom:startLine to:endLine
       
  3119     "delete lines - no redraw;
       
  3120      return true, if something was really deleted"
       
  3121 
       
  3122     |lastLine|
       
  3123 
       
  3124     self checkModificationsAllowed ifFalse:[^ false].
       
  3125 
       
  3126     (list isNil or:[startLine > list size]) ifTrue:[^ false].
       
  3127     (endLine > list size) ifTrue:[
       
  3128         lastLine := list size
       
  3129     ] ifFalse:[
       
  3130         lastLine := endLine
       
  3131     ].
       
  3132     self basicListRemoveFromIndex:startLine toIndex:lastLine.
       
  3133     "/ TODO: remember old maxwidth of linerange,
       
  3134     "/ only clear widthOfWidestLine, if this max
       
  3135     "/ length was (one of) the longest.
       
  3136     "/ avoids slow delete with huge texts.
       
  3137     widthOfWidestLine := nil. "/ i.e. unknown
       
  3138     self textChanged.
       
  3139     ^ true
       
  3140 
       
  3141     "Modified: / 10.11.1998 / 23:55:29 / cg"
       
  3142 !
       
  3143 
       
  3144 deleteSelection
       
  3145     "delete the selection"
       
  3146 
       
  3147     |wasOn startLine startCol endLine endCol|
       
  3148 
       
  3149     self checkModificationsAllowed ifFalse:[ ^ self].
       
  3150 
       
  3151     selectionStartLine notNil ifTrue:[
       
  3152         wasOn := self hideCursor.
       
  3153 
       
  3154         startLine := selectionStartLine.
       
  3155         startCol := selectionStartCol.
       
  3156         endLine := selectionEndLine.
       
  3157         endCol := selectionEndCol.
       
  3158         self unselectWithoutRedraw.
       
  3159         self deleteFromLine:startLine col:startCol toLine:endLine col:endCol.
       
  3160         self setCursorLine:startLine col:startCol.
       
  3161 
       
  3162         self makeCursorVisibleAndShowCursor:wasOn
       
  3163     ]
       
  3164 !
       
  3165 
       
  3166 deleteWordBeforeCursor
       
  3167     "delete the word to the left of cursor and move cursor to left"
       
  3168 
       
  3169     |wasOn beginCol beginLine endCol endLine|
       
  3170 
       
  3171     self checkModificationsAllowed ifFalse:[ ^ self].
       
  3172 
       
  3173     wasOn := self hideCursor.
       
  3174     self 
       
  3175         undoableDo:[
       
  3176             endCol := cursorCol-1.
       
  3177             endLine := cursorLine.
       
  3178             self cursorToPreviousWord.
       
  3179             beginCol := cursorCol.
       
  3180             beginLine := cursorLine.
       
  3181             self deleteFromLine:beginLine col:beginCol toLine:endLine col:endCol.
       
  3182         ] 
       
  3183         info:'Delete Word'.
       
  3184     wasOn ifTrue:[ self showCursor ].
       
  3185 
       
  3186     "Modified: / 22.2.2000 / 23:59:04 / cg"
       
  3187 !
       
  3188 
       
  3189 insert:aCharacter atLine:lineNr col:colNr
       
  3190     "insert a single character at lineNr/colNr;
       
  3191      set emphasis to character at current position"
       
  3192 
       
  3193     self basicInsert:aCharacter atLine:lineNr col:colNr.
       
  3194     aCharacter ~~ Character cr ifTrue:[
       
  3195         self addUndo:(DeleteCharacters line:lineNr col:colNr info:'insert').
       
  3196     ]
       
  3197 !
       
  3198 
       
  3199 insertCharAtCursor:aCharacter
       
  3200     "insert a single character at cursor-position - advance cursor."
       
  3201 
       
  3202     |wasOn|
       
  3203 
       
  3204     wasOn := self hideCursor.
       
  3205     aCharacter == Character tab ifTrue:[
       
  3206         "/ needs special care to advance cursor correctly
       
  3207         self insertTabAtCursor
       
  3208     ] ifFalse:[
       
  3209         self insert:aCharacter atLine:cursorLine col:cursorCol.
       
  3210         aCharacter == (Character cr) ifTrue:[
       
  3211             self basicCursorReturn
       
  3212         ] ifFalse:[
       
  3213             self cursorRight.
       
  3214         ].
       
  3215     ].
       
  3216     self makeCursorVisibleAndShowCursor:wasOn.
       
  3217 
       
  3218     "Modified: / 12.6.1998 / 21:50:20 / cg"
       
  3219 !
       
  3220 
       
  3221 insertLine:aString before:lineNr
       
  3222     "insert the line aString before line lineNr"
       
  3223 
       
  3224     ^ self insertLines:(Array with:aString) from:1 to:1  before:lineNr.
       
  3225 
       
  3226     "Modified: 14.5.1996 / 13:42:54 / cg"
       
  3227 !
       
  3228 
       
  3229 insertLines:aStringCollection before:lineNr
       
  3230     "insert a bunch before line lineNr"
       
  3231 
       
  3232     self insertLines:aStringCollection from:1 to:aStringCollection size before:lineNr
       
  3233 
       
  3234     "Modified: 6.9.1995 / 20:51:03 / claus"
       
  3235 !
       
  3236 
       
  3237 insertLines:someText from:start to:end before:lineNr
       
  3238     "insert a bunch of lines before line lineNr.
       
  3239      The cursor position is left unchanged."
       
  3240 
       
  3241     |text indent visLine w nLines "{ Class: SmallInteger }"
       
  3242      srcY "{ Class: SmallInteger }"
       
  3243      dstY "{ Class: SmallInteger }" |
       
  3244 
       
  3245     autoIndent ifTrue:[
       
  3246         indent := self leftIndentForLine:lineNr.
       
  3247 
       
  3248         text := someText 
       
  3249             collect:[:ln||line|
       
  3250                 ln notNil ifTrue:[
       
  3251                     line := ln withoutLeadingSeparators.
       
  3252                     (line isEmpty or:[indent == 0]) ifFalse:[
       
  3253                         line := (String new:indent), line
       
  3254                     ].
       
  3255                     line
       
  3256                 ] ifFalse:[
       
  3257                     nil
       
  3258                 ]
       
  3259             ].
       
  3260     ] ifFalse:[
       
  3261         text := someText
       
  3262     ].
       
  3263 
       
  3264     visLine := self listLineToVisibleLine:lineNr.
       
  3265     (shown not or:[visLine isNil]) ifTrue:[
       
  3266         self withoutRedrawInsertLines:text
       
  3267              from:start to:end
       
  3268              before:lineNr.
       
  3269     ] ifFalse:[
       
  3270         nLines := end - start + 1.
       
  3271         ((visLine + nLines) >= nLinesShown) ifTrue:[
       
  3272             self withoutRedrawInsertLines:text
       
  3273                  from:start to:end
       
  3274                  before:lineNr.
       
  3275             self redrawFromVisibleLine:visLine to:nLinesShown
       
  3276         ] ifFalse:[
       
  3277             w := self widthForScrollBetween:(lineNr + nLines)
       
  3278                                         and:(firstLineShown + nLines + nLinesShown).
       
  3279             srcY := topMargin + ((visLine - 1) * fontHeight).
       
  3280             dstY := srcY + (nLines * fontHeight).
       
  3281 
       
  3282             "/
       
  3283             "/ scroll ...
       
  3284             "/
       
  3285             "
       
  3286              stupid: must catchExpose before inserting new
       
  3287              stuff - since catchExpose may perform redraws
       
  3288             "
       
  3289             self catchExpose.
       
  3290             self withoutRedrawInsertLines:text
       
  3291                  from:start to:end
       
  3292                  before:lineNr.
       
  3293             self
       
  3294                 copyFrom:self
       
  3295                 x:textStartLeft y:srcY
       
  3296                 toX:textStartLeft y:dstY
       
  3297                 width:w
       
  3298                 height:(height - dstY)
       
  3299                 async:true.
       
  3300             self redrawFromVisibleLine:visLine to:(visLine + nLines - 1).
       
  3301             self waitForExpose
       
  3302         ].
       
  3303     ].
       
  3304     widthOfWidestLine notNil ifTrue:[
       
  3305         text do:[:line |
       
  3306             widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:line).
       
  3307         ]
       
  3308     ].
       
  3309     self textChanged.
       
  3310 
       
  3311     "Modified: 29.1.1997 / 13:02:39 / cg"
       
  3312 !
       
  3313 
       
  3314 insertLines:lines withCR:withCr
       
  3315     "insert a bunch of lines at cursor position.
       
  3316      Cursor is moved behind insertion.
       
  3317      If withCr is true, append cr after last line"
       
  3318 
       
  3319     |start end nLines wasOn|
       
  3320 
       
  3321     lines notNil ifTrue:[
       
  3322         nLines := lines size.
       
  3323         (nLines == 1) ifTrue:[
       
  3324             self insertStringAtCursor:(lines at:1).
       
  3325             withCr ifTrue:[
       
  3326                 self insertCharAtCursor:(Character cr)
       
  3327             ]
       
  3328         ] ifFalse:[
       
  3329             (cursorCol ~~ 1) ifTrue:[
       
  3330                 self insertStringAtCursor:(lines at:1).
       
  3331                 self insertCharAtCursor:(Character cr).
       
  3332                 start := 2
       
  3333             ] ifFalse:[
       
  3334                 start := 1
       
  3335             ].
       
  3336             withCr ifTrue:[
       
  3337                 end := nLines
       
  3338             ] ifFalse:[
       
  3339                 end := nLines - 1
       
  3340             ].
       
  3341             (start <= nLines) ifTrue:[
       
  3342                 (end >= start) ifTrue:[
       
  3343                     wasOn := self hideCursor.
       
  3344                     self insertLines:lines from:start to:end before:cursorLine.
       
  3345                     self setCursorLine:(cursorLine + (end - start + 1)).
       
  3346                     wasOn ifTrue:[self showCursor].
       
  3347                 ]
       
  3348             ].
       
  3349             withCr ifFalse:[
       
  3350                 "last line without cr"
       
  3351                 self insertStringAtCursor:(lines at:nLines)
       
  3352             ]
       
  3353         ]
       
  3354     ]
       
  3355 
       
  3356     "Created: / 18.5.1996 / 15:32:06 / cg"
       
  3357     "Modified: / 12.6.1998 / 21:51:16 / cg"
       
  3358 !
       
  3359 
       
  3360 insertLines:lines withCr:withCr
       
  3361     "insert a bunch of lines at cursor position. Cursor
       
  3362      is moved behind insertion.
       
  3363      If withCr is true, append cr after last line"
       
  3364 
       
  3365     <resource:#obsolete>
       
  3366 
       
  3367     self obsoleteMethodWarning:'use #insertLines:withCR:'.
       
  3368     self insertLines:lines withCR:withCr.
       
  3369 
       
  3370     "Modified: 31.7.1997 / 23:07:22 / cg"
       
  3371 !
       
  3372 
       
  3373 insertSelectedStringAtCursor:aString
       
  3374     "insert the argument, aString at cursor position and select it"
       
  3375 
       
  3376     |startLine startCol|
       
  3377 
       
  3378     startLine := cursorLine.
       
  3379     startCol := cursorCol.
       
  3380     self insertStringAtCursor:aString.
       
  3381     self selectFromLine:startLine col:startCol
       
  3382                  toLine:cursorLine col:(cursorCol - 1).
       
  3383     self makeSelectionVisible.
       
  3384 !
       
  3385 
       
  3386 insertString:aString atCharacterPosition:charPos
       
  3387     "insert the argument, aString at a character position"
       
  3388 
       
  3389     |line col|
       
  3390 
       
  3391     line := self lineOfCharacterPosition:charPos.
       
  3392     col := charPos - (self characterPositionOfLine:line col:1) + 1.
       
  3393     self insertString:aString atLine:line col:col
       
  3394 !
       
  3395 
       
  3396 insertString:aString atLine:lineNr col:colNr
       
  3397     "insert the string, aString at line/col;
       
  3398      handle cr's correctly"
       
  3399 
       
  3400     |start           "{ Class: SmallInteger }"
       
  3401      stop            "{ Class: SmallInteger }"
       
  3402      end             "{ Class: SmallInteger }"
       
  3403      subString c
       
  3404      l               "{ Class: SmallInteger }" |
       
  3405 
       
  3406     aString isNil ifTrue:[^ self].
       
  3407     (aString includes:(Character cr)) ifFalse:[
       
  3408         ^ self insertStringWithoutCRs:aString atLine:lineNr col:colNr
       
  3409     ].
       
  3410 
       
  3411     l := lineNr.
       
  3412     c := colNr.
       
  3413     start := 1.
       
  3414     end := aString size.
       
  3415     [start <= end] whileTrue:[
       
  3416         stop := aString indexOf:(Character cr) startingAt:start.
       
  3417         stop == 0 ifTrue:[
       
  3418             stop := end + 1
       
  3419         ].
       
  3420         subString := aString copyFrom:start to:(stop - 1).
       
  3421         self insertStringWithoutCRs:subString atLine:l col:c.
       
  3422         (stop <= end) ifTrue:[
       
  3423             c := c + subString size.
       
  3424             self insert:(Character cr) atLine:l col:c.
       
  3425             l := l + 1.
       
  3426             c := 1
       
  3427         ].
       
  3428         start := stop + 1
       
  3429     ]
       
  3430 
       
  3431     "Modified: / 10.6.1998 / 19:03:59 / cg"
       
  3432 !
       
  3433 
       
  3434 insertStringAtCursor:aString
       
  3435     "insert the argument, aString at cursor position
       
  3436      handle cr's correctly. A nil argument is interpreted as an empty line."
       
  3437 
       
  3438     aString isNil ifTrue:[
       
  3439         "new:"
       
  3440         self insertCharAtCursor:(Character cr).
       
  3441         ^ self
       
  3442     ].
       
  3443     (aString includes:(Character cr)) ifFalse:[
       
  3444         ^ self insertStringWithoutCRsAtCursor:aString
       
  3445     ].
       
  3446 
       
  3447     self insertLines:aString asStringCollection withCR:false.
       
  3448 
       
  3449     "Modified: / 10.6.1998 / 19:03:21 / cg"
       
  3450 !
       
  3451 
       
  3452 insertStringWithoutCRs:aString atLine:lineNr col:colNr
       
  3453     "insert aString (which has no crs) at lineNr/colNr"
       
  3454 
       
  3455     self withoutRedrawInsertStringWithoutCRs:aString atLine:lineNr col:colNr.
       
  3456     shown ifTrue:[
       
  3457         gc font hasOverlappingCharacters ifTrue:[
       
  3458             self invalidateLine:lineNr.
       
  3459         ] ifFalse:[
       
  3460             self redrawLine:lineNr from:colNr
       
  3461         ]
       
  3462     ]
       
  3463 
       
  3464     "Modified: / 09-11-2010 / 13:43:03 / cg"
       
  3465 !
       
  3466 
       
  3467 insertStringWithoutCRsAtCursor:aString
       
  3468     "insert a string (which has no crs) at cursor position
       
  3469      - advance cursor"
       
  3470 
       
  3471     |wasOn oldLen newLen deltaLen|
       
  3472 
       
  3473     aString size > 0 ifTrue:[
       
  3474         wasOn := self hideCursor.
       
  3475         (aString includes:Character tab) ifTrue:[
       
  3476             self checkForExistingLine:cursorLine.
       
  3477             oldLen := (list at:cursorLine) size.
       
  3478             self insertString:aString atLine:cursorLine col:cursorCol.
       
  3479             newLen := (list at:cursorLine) size.
       
  3480             deltaLen := newLen - oldLen.
       
  3481         ] ifFalse:[
       
  3482             self insertString:aString atLine:(cursorLine ? 1) col:cursorCol.
       
  3483             deltaLen := aString size.
       
  3484         ].
       
  3485         self setCursorCol:(cursorCol + deltaLen).
       
  3486         wasOn ifTrue:[self showCursor]
       
  3487     ]
       
  3488 
       
  3489     "Modified: / 10.6.1998 / 20:43:52 / cg"
       
  3490 !
       
  3491 
       
  3492 insertTabAtCursor
       
  3493     "insert spaces to next tab"
       
  3494 
       
  3495     |wasOn nextTab|
       
  3496 
       
  3497     wasOn := self hideCursor.
       
  3498     nextTab := self nextTabAfter:cursorCol.
       
  3499     self insertStringAtCursor:(String new:(nextTab - cursorCol)).
       
  3500     self makeCursorVisibleAndShowCursor:wasOn.
       
  3501 !
       
  3502 
       
  3503 joinLines
       
  3504     "join lines (remove line-break)"
       
  3505 
       
  3506     self checkModificationsAllowed ifFalse:[ ^ self].
       
  3507 
       
  3508     self
       
  3509         undoableDo:[
       
  3510             |line col lineLen|
       
  3511 
       
  3512             line := cursorLine.
       
  3513             col := cursorCol.
       
  3514             lineLen := (list at:line) size.
       
  3515             col > lineLen ifTrue:[
       
  3516                 self insertString:(String new:col-lineLen) atLine:line col:col+1.
       
  3517             ] ifFalse:[
       
  3518                 self deleteCharsAtLine:line fromCol:col toCol:lineLen.
       
  3519             ].
       
  3520             self mergeLine:line removeBlanks:true.
       
  3521             self cursorLine:line col:col.
       
  3522         ]
       
  3523         info:'Join'
       
  3524 !
       
  3525 
       
  3526 mergeLine:lineNr
       
  3527     "merge line lineNr with line lineNr+1"
       
  3528 
       
  3529     self mergeLine:lineNr removeBlanks:true
       
  3530 
       
  3531     "Modified: 9.9.1997 / 09:28:03 / cg"
       
  3532 !
       
  3533 
       
  3534 mergeLine:lineNr removeBlanks:removeBlanks
       
  3535     "merge line lineNr with line lineNr+1"
       
  3536 
       
  3537     |len|
       
  3538 
       
  3539     self checkModificationsAllowed ifFalse:[ ^ self].
       
  3540 
       
  3541     len := (self listAt:lineNr) size.
       
  3542     self nonUndoableDo:[
       
  3543         self basicMergeLine:lineNr removeBlanks:removeBlanks.
       
  3544     ].
       
  3545     self addUndo:(PasteString new line:lineNr col:len+1 string:(Character cr asString) selected:false).
       
  3546 !
       
  3547 
       
  3548 parenthizeSelectionWith:openingCharacter and:closingCharacter
       
  3549     |newSelectionEnd|
       
  3550 
       
  3551     self hasSelection ifFalse:[^ self].
       
  3552 
       
  3553     newSelectionEnd := selectionEndCol.
       
  3554 
       
  3555     (self characterAtLine:selectionStartLine col:selectionStartCol) == openingCharacter ifTrue:[
       
  3556         (self characterAtLine:selectionEndLine col:selectionEndCol) == closingCharacter ifTrue:[
       
  3557             self deleteCharAtLine:selectionEndLine col:selectionEndCol.
       
  3558             newSelectionEnd := newSelectionEnd-1.
       
  3559         ].
       
  3560         self deleteCharAtLine:selectionStartLine col:selectionStartCol.
       
  3561         selectionStartLine == selectionEndLine ifTrue:[
       
  3562             newSelectionEnd := newSelectionEnd-1.
       
  3563         ]
       
  3564     ] ifFalse:[
       
  3565         self insert:closingCharacter atLine:selectionEndLine col:selectionEndCol+1.
       
  3566         newSelectionEnd := newSelectionEnd+1.
       
  3567         self insert:openingCharacter atLine:selectionStartLine col:selectionStartCol.
       
  3568         selectionStartLine == selectionEndLine ifTrue:[
       
  3569             newSelectionEnd := newSelectionEnd+1.
       
  3570         ]
       
  3571     ].
       
  3572     self
       
  3573         selectFromLine:selectionStartLine col:selectionStartCol
       
  3574         toLine:selectionEndLine col:newSelectionEnd.
       
  3575 !
       
  3576 
       
  3577 removeTrailingBlankLines
       
  3578     "remove all blank lines at end of text"
       
  3579 
       
  3580     |lastLine "{ Class: SmallInteger }"
       
  3581      line finished|
       
  3582 
       
  3583     lastLine := list size.
       
  3584     finished := false.
       
  3585     [finished] whileFalse:[
       
  3586         (lastLine <= 1) ifTrue:[
       
  3587             finished := true
       
  3588         ] ifFalse:[
       
  3589             line := list at:lastLine.
       
  3590             line notNil ifTrue:[
       
  3591                 line isBlank ifTrue:[
       
  3592                     self basicListAt:lastLine put:nil.
       
  3593                     line := nil
       
  3594                 ]
       
  3595             ].
       
  3596             line notNil ifTrue:[
       
  3597                 finished := true
       
  3598             ] ifFalse:[
       
  3599                 lastLine := lastLine - 1
       
  3600             ]
       
  3601         ]
       
  3602     ].
       
  3603     (lastLine ~~ list size) ifTrue:[
       
  3604         list grow:lastLine.
       
  3605 "/        self textChanged
       
  3606     ]
       
  3607 !
       
  3608 
       
  3609 replace:aCharacter atLine:lineNr col:colNr
       
  3610     "replace a single character at lineNr/colNr"
       
  3611 
       
  3612     |originalChar|
       
  3613 
       
  3614     originalChar := self characterAtLine:lineNr col:colNr.
       
  3615     self basicReplace:aCharacter atLine:lineNr col:colNr.
       
  3616     self addUndo:(ReplaceCharacters line:lineNr col:colNr character:originalChar info:'replace').
       
  3617 !
       
  3618 
       
  3619 replace:patternArg by:replacePatternArg all:all ignoreCase:ignoreCase
       
  3620     |pattern replacePattern|
       
  3621 
       
  3622     pattern := patternArg string.
       
  3623     replacePattern := replacePatternArg string.
       
  3624     (pattern notEmpty and:[ replacePattern notEmpty ]) ifTrue:[
       
  3625         self rememberSearchPattern:pattern.
       
  3626         self rememberSearchPattern:replacePattern.
       
  3627         LastSearchIgnoredCase := ignoreCase.
       
  3628         self
       
  3629             undoableDo:[
       
  3630                 all ifTrue:[
       
  3631                     self
       
  3632                         replaceString:pattern
       
  3633                         to:replacePattern
       
  3634                         ignoreCase:ignoreCase
       
  3635                 ] ifFalse:[
       
  3636                     (self selectionAsString notNil
       
  3637                         and:[ self selectionAsString sameAs:pattern caseSensitive:ignoreCase not ])
       
  3638                             ifTrue:[
       
  3639                                 self replaceSelectionBy:replacePattern.
       
  3640                                 self
       
  3641                                     search:pattern
       
  3642                                     ignoreCase:ignoreCase
       
  3643                                     forward:(lastSearchDirection = #forward).
       
  3644                             ].
       
  3645                 ]
       
  3646             ]
       
  3647             info:'Replace'
       
  3648     ]
       
  3649 
       
  3650     "Created: / 11-07-2006 / 11:19:57 / fm"
       
  3651 !
       
  3652 
       
  3653 replaceCharAtCursor:aCharacter
       
  3654     "replace a single character at cursor-position - advance cursor"
       
  3655 
       
  3656     |wasOn|
       
  3657 
       
  3658     wasOn := self hideCursor.
       
  3659     aCharacter == (Character cr) ifTrue:[
       
  3660         self cursorReturn
       
  3661     ] ifFalse:[
       
  3662         self replace:aCharacter atLine:cursorLine col:cursorCol.
       
  3663         self cursorRight.
       
  3664     ].
       
  3665     self makeCursorVisibleAndShowCursor:wasOn.
       
  3666 
       
  3667     "Created: 6.3.1996 / 12:27:42 / cg"
       
  3668 !
       
  3669 
       
  3670 replaceContentsWith:newContents
       
  3671     "replace everything"
       
  3672 
       
  3673     |originalContents|
       
  3674 
       
  3675     originalContents := self contents.
       
  3676     self contents:newContents keepUndoHistory:true.
       
  3677     self addUndo:(ReplaceContents text:originalContents info:'replace').
       
  3678 !
       
  3679 
       
  3680 replaceFromCharacterPosition:charPos1 to:charPos2 with:newString
       
  3681     "replace a substring at a character position"
       
  3682 
       
  3683     "/ sigh - insert first, to avoid troible due to shifing-in virtual line ends
       
  3684     self insertString:newString atCharacterPosition:charPos1.
       
  3685     self deleteFromCharacterPosition:charPos1+newString size to:charPos2+newString size.
       
  3686 !
       
  3687 
       
  3688 replaceLine:lineNr with:newText
       
  3689     "replace a line at lineNr"
       
  3690 
       
  3691     |originalLine|
       
  3692 
       
  3693     originalLine := self listAt:lineNr.
       
  3694     originalLine isNil ifTrue:[
       
  3695         self checkForExistingLine:lineNr
       
  3696     ].
       
  3697     self list at:lineNr put:newText.
       
  3698     self addUndo:(ReplaceLine line:lineNr string:originalLine info:'replace').
       
  3699     self invalidateLine:lineNr.
       
  3700 
       
  3701     "Modified: / 12-04-2007 / 09:31:33 / cg"
       
  3702 !
       
  3703 
       
  3704 replaceLines:lines withCR:withCr
       
  3705     "replace a bunch of lines at cursor position. Cursor
       
  3706      is moved behind replacement.
       
  3707      If withCr is true, move to the beginning of the next line
       
  3708      after the last line"
       
  3709 
       
  3710     |line col nLines wasOn|
       
  3711 
       
  3712     lines notNil ifTrue:[
       
  3713         wasOn := self hideCursor.
       
  3714         nLines := lines size.
       
  3715         line := cursorLine.
       
  3716         col := cursorCol.
       
  3717         lines keysAndValuesDo:[:i :l |
       
  3718             self replaceString:(l ? '') atLine:line col:col.
       
  3719             (i ~~ nLines or:[withCr]) ifTrue:[
       
  3720                 line := line + 1.
       
  3721                 col := 1.
       
  3722             ] ifFalse:[
       
  3723                 col := col + (l size).
       
  3724             ]
       
  3725         ].
       
  3726         self cursorLine:line col:col.
       
  3727         self makeCursorVisibleAndShowCursor:wasOn.
       
  3728         "/ wasOn ifTrue:[self showCursor].
       
  3729     ]
       
  3730 
       
  3731     "Created: / 18-05-1996 / 15:32:06 / cg"
       
  3732     "Modified: / 25-07-2013 / 17:00:53 / cg"
       
  3733 !
       
  3734 
       
  3735 replaceSelectionBy:something
       
  3736     "delete the selection (if any) and insert something, a character or string;
       
  3737      leave cursor after insertion"
       
  3738 
       
  3739     self replaceSelectionBy:something keepCursor:false select:false
       
  3740 !
       
  3741 
       
  3742 replaceSelectionBy:something keepCursor:keep
       
  3743     "delete the selection (if any) and insert something, a character or string;
       
  3744      leave cursor after insertion or leave it, depending on keep"
       
  3745 
       
  3746     self replaceSelectionBy:something keepCursor:keep select:false
       
  3747 
       
  3748     "Modified: 9.10.1996 / 16:14:35 / cg"
       
  3749 !
       
  3750 
       
  3751 replaceSelectionBy:something keepCursor:keep select:selectNewText
       
  3752     "delete the selection (if any) and insert something, a character or string;
       
  3753      leave cursor after insertion or leave it, depending on keep.
       
  3754      If selectNewText is true, select the new text; otherwise deselect"
       
  3755 
       
  3756     |sel l c selStartLine selStartCol|
       
  3757 
       
  3758     l := cursorLine.
       
  3759     c := cursorCol.
       
  3760 
       
  3761     sel := self selectionAsString.
       
  3762     sel isNil ifTrue:[
       
  3763         selStartLine := l.
       
  3764         selStartCol := c.
       
  3765     ] ifFalse:[
       
  3766         selStartLine := selectionStartLine.
       
  3767         selStartCol := selectionStartCol.
       
  3768 
       
  3769         self setLastStringToReplace: sel.
       
  3770 
       
  3771         self deleteSelection.
       
  3772         replacing := true.
       
  3773         lastReplacementInfo rememberReplacement.
       
  3774         lastReplacementInfo lastReplacement: ''.
       
  3775         lastReplacementInfo stillCollectingInput:true.
       
  3776         undoSupport actionInfo:'replace'.
       
  3777     ].
       
  3778 
       
  3779     something isCharacter ifTrue:[
       
  3780         lastReplacementInfo lastReplacement notNil ifTrue:[
       
  3781             lastReplacementInfo stillCollectingInput ifTrue:[
       
  3782                 lastReplacementInfo lastReplacement: (lastReplacementInfo lastReplacement copyWith:something).
       
  3783             ].
       
  3784         ].
       
  3785         self isInInsertMode ifTrue:[
       
  3786             self insertCharAtCursor:something
       
  3787         ] ifFalse:[
       
  3788             self replaceCharAtCursor:something
       
  3789         ]
       
  3790     ] ifFalse:[
       
  3791         something isString ifTrue:[
       
  3792             lastReplacementInfo lastReplacement: something.
       
  3793             self isInInsertMode ifTrue:[
       
  3794                 self insertStringAtCursor:something
       
  3795             ] ifFalse:[
       
  3796                 self replaceStringAtCursor:something
       
  3797             ]
       
  3798         ] ifFalse:[
       
  3799             Transcript showCR:'EditTextView: non String-or-Character in replace'.
       
  3800         ].
       
  3801     ].
       
  3802     keep ifTrue:[
       
  3803         self cursorLine:l col:c
       
  3804     ].
       
  3805     selectNewText ifTrue:[
       
  3806         self selectFromLine:selStartLine col:selStartCol toLine:cursorLine col:cursorCol-1
       
  3807     ]
       
  3808 
       
  3809     "Modified: 9.10.1996 / 16:14:35 / cg"
       
  3810 !
       
  3811 
       
  3812 replaceString:aString atLine:lineNr col:colNr
       
  3813     "replace multiple characters starting at lineNr/colNr.
       
  3814      This is not prepared to encounter special chars (except TAB) in the string."
       
  3815 
       
  3816     |originalString|
       
  3817 
       
  3818     self checkModificationsAllowed ifFalse:[ ^ self].
       
  3819 
       
  3820     originalString := self textFromLine:lineNr col:colNr toLine:lineNr col:colNr+aString size-1.
       
  3821 
       
  3822     self basicReplaceString:aString atLine:lineNr col:colNr.
       
  3823     self addUndo:(ReplaceCharacters line:lineNr col:colNr characters:originalString info:'replace').
       
  3824 !
       
  3825 
       
  3826 replaceString:aString to:aNewString ignoreCase:ignoreCase
       
  3827     |continue count|
       
  3828 
       
  3829     self cursorToTop.
       
  3830     self selectFromBeginning.
       
  3831     count := 0.
       
  3832     continue := true.
       
  3833     [ continue ] whileTrue:[
       
  3834         (self selectionAsString notNil
       
  3835         and:[ self selectionAsString sameAs:aString caseSensitive:ignoreCase not ])
       
  3836             ifTrue:[
       
  3837                 self replaceSelectionBy:aNewString.
       
  3838                 count := count + 1.
       
  3839             ].
       
  3840         self
       
  3841             searchFwd:aString
       
  3842             ignoreCase:ignoreCase
       
  3843             ifAbsent:[
       
  3844                 Dialog information:('%1 has been replaced by %2 %3 times' 
       
  3845                                     bindWith:aString with:aNewString with:count).
       
  3846                 continue := false.
       
  3847             ].
       
  3848     ].
       
  3849 
       
  3850     "Created: / 10-07-2006 / 16:42:48 / fm"
       
  3851 !
       
  3852 
       
  3853 replaceStringAtCursor:aString
       
  3854     "replace multiple characters at cursor-position - advance cursor"
       
  3855 
       
  3856     |wasOn i1 i2|
       
  3857 
       
  3858     wasOn := self hideCursor.
       
  3859     (aString includes:Character tab) ifTrue:[
       
  3860         "/ need special care for TAB (to move cursor correctly)
       
  3861         i1 := 1.
       
  3862         [i1 ~~ 0] whileTrue:[
       
  3863             i2 := aString indexOf:Character tab startingAt:i1.
       
  3864             i2 ~~ 0 ifTrue:[
       
  3865                 i1 ~~ i2 ifTrue:[
       
  3866                     self replaceString:(aString copyFrom:i1 to:i2-1) atLine:cursorLine col:cursorCol.
       
  3867                     self cursorCol:(cursorCol + (i2 - i1)).
       
  3868                 ].
       
  3869                 self replaceTABAtCursor.
       
  3870                 i2 := i2 + 1.
       
  3871             ] ifFalse:[
       
  3872                 self replaceString:(aString copyFrom:i1) atLine:cursorLine col:cursorCol.
       
  3873                 self cursorCol:(cursorCol + (aString size - i1 + 1)).
       
  3874             ].
       
  3875             i1 := i2.
       
  3876         ]
       
  3877     ] ifFalse:[
       
  3878         self replaceString:aString atLine:cursorLine col:cursorCol.
       
  3879         self cursorCol:(cursorCol + aString size).
       
  3880     ].
       
  3881     self makeCursorVisibleAndShowCursor:wasOn.
       
  3882 
       
  3883     "Created: / 9.6.1998 / 20:33:20 / cg"
       
  3884     "Modified: / 20.6.1998 / 19:41:02 / cg"
       
  3885 !
       
  3886 
       
  3887 replaceTABAtCursor
       
  3888     "replace a single character at cursor-position by a TAB character"
       
  3889 
       
  3890     |wasOn nextTab|
       
  3891 
       
  3892     wasOn := self hideCursor.
       
  3893     nextTab := self nextTabAfter:cursorCol.
       
  3894     self replaceStringAtCursor:(String new:(nextTab - cursorCol)).
       
  3895     self makeCursorVisibleAndShowCursor:wasOn.
       
  3896 
       
  3897     "Created: / 12.6.1998 / 21:53:23 / cg"
       
  3898 !
       
  3899 
       
  3900 selectWordBeforeCursor
       
  3901     "select the word to the left of cursor"
       
  3902 
       
  3903     |savCursorLine savCursorCol  beginCol beginLine endCol endLine|
       
  3904 
       
  3905     savCursorLine := cursorLine.
       
  3906     savCursorCol := cursorCol.
       
  3907 
       
  3908     endCol := cursorCol-1.
       
  3909     endLine := cursorLine.
       
  3910     self cursorToPreviousWord.
       
  3911     beginCol := cursorCol.     
       
  3912     beginLine := cursorLine.
       
  3913     self cursorLine:savCursorLine col:savCursorCol.
       
  3914     self selectFromLine:beginLine col:beginCol toLine:endLine col:endCol.
       
  3915 
       
  3916     "Created: / 14-06-2011 / 14:46:35 / cg"
       
  3917 !
       
  3918 
       
  3919 splitLine:lineNr before:colNr
       
  3920     "split the line linNr before colNr; the right part (from colNr)
       
  3921      is cut off and inserted after lineNr; the view is redrawn"
       
  3922 
       
  3923     self basicSplitLine:lineNr before:colNr.
       
  3924     self addUndo:(DeleteRange line1:lineNr col1:colNr line2:lineNr+1 col2:0 info:'split').
       
  3925 !
       
  3926 
       
  3927 withoutRedrawAt:lineNr put:aString
       
  3928     "replace a line at lineNr"
       
  3929 
       
  3930     |originalLine|
       
  3931 
       
  3932     originalLine := self listAt:lineNr.
       
  3933     self addUndo:(ReplaceLine line:lineNr string:originalLine info:'replace').
       
  3934     super withoutRedrawAt:lineNr put:aString.
       
  3935 !
       
  3936 
       
  3937 withoutRedrawInsertLine:aString before:lineNr
       
  3938     "insert the argument, aString before line lineNr; the string
       
  3939      becomes line lineNr; everything else is moved down; the view
       
  3940      is not redrawn"
       
  3941 
       
  3942     self basicWithoutRedrawInsertLines:{ aString } from:1 to:1 before:lineNr.
       
  3943     self addUndo:(DeleteRange line1:lineNr col1:1 line2:lineNr+1 col2:0 info:'insert').
       
  3944 !
       
  3945 
       
  3946 withoutRedrawInsertLines:lines from:start to:end before:lineNr
       
  3947     "insert a bunch of lines before line lineNr; the view is not redrawn"
       
  3948 
       
  3949     self basicWithoutRedrawInsertLines:lines from:start to:end before:lineNr.
       
  3950     self isReadOnly ifFalse:[
       
  3951         self addUndo:(DeleteRange line1:lineNr col1:1 line2:lineNr+end-start+1 col2:0 info:'insert').
       
  3952     ].
       
  3953 !
       
  3954 
       
  3955 withoutRedrawInsertStringWithoutCRs:aString atLine:lineNr col:colNr
       
  3956     "insert aString (which has no crs) at lineNr/colNr"
       
  3957 
       
  3958     self basicWithoutRedrawInsertStringWithoutCRs:aString atLine:lineNr col:colNr.
       
  3959     self addUndo:(DeleteRange line1:lineNr col1:colNr line2:lineNr col2:colNr+aString size-1 info:'insert').
       
  3960 !
       
  3961 
       
  3962 wrapLines
       
  3963     "wrap lines (insert line-break)"
       
  3964 
       
  3965     |lineLength answerString string|
       
  3966 
       
  3967     self checkModificationsAllowed ifFalse:[ ^ self].
       
  3968 
       
  3969     self hasSelection ifFalse:[
       
  3970         self selectLine:cursorLine.
       
  3971     ].
       
  3972     string := self selectionAsString.
       
  3973     string isEmptyOrNil ifTrue:[
       
  3974         Dialog information:(resources string:'Nothing selected.').
       
  3975         ^ self.
       
  3976     ].
       
  3977 
       
  3978     answerString := Dialog request:(resources string:'Line length (wrap after how many chars)?') initialAnswer:80.
       
  3979     lineLength := Number readFrom:answerString onError:nil.
       
  3980     lineLength isNil ifTrue:[^ self].
       
  3981     lineLength < 1 ifTrue:[
       
  3982         lineLength := 1.
       
  3983     ].
       
  3984 
       
  3985     self
       
  3986         undoableDo:[
       
  3987             |inStream line col lineLen lastGoodCol lastStartCol word|
       
  3988 
       
  3989             line := selectionStartLine.
       
  3990             col := selectionStartCol.
       
  3991 
       
  3992             self cutSelection.
       
  3993             self cursorLine:line col:col.
       
  3994 
       
  3995             lastGoodCol := col.
       
  3996 
       
  3997             inStream := string readStream.
       
  3998             [ inStream atEnd ] whileFalse:[
       
  3999                 [inStream atEnd not and:[inStream peek isSeparator]] whileTrue:[ inStream next ].
       
  4000                 word := WriteStream on:(String new:10).
       
  4001                 [inStream atEnd not and:[inStream peek isSeparator not]] whileTrue:[ word nextPut:inStream next ].
       
  4002                 (col + 1 + word size > lineLength) ifTrue:[
       
  4003                     self insertCharAtCursor:(Character cr).
       
  4004                     col := 1.
       
  4005                 ] ifFalse:[
       
  4006                     col ~~ 1 ifTrue:[ 
       
  4007                         self insertStringAtCursor:' '.
       
  4008                         col := col + 1.
       
  4009                     ]    
       
  4010                ].
       
  4011                self insertStringAtCursor:word contents.
       
  4012                col := col + word size.
       
  4013             ].
       
  4014         ]
       
  4015         info:'Wrap'
       
  4016 
       
  4017     "Modified: / 01-03-2012 / 19:56:22 / cg"
       
  4018 ! !
       
  4019 
       
  4020 !EditTextView methodsFor:'editing-basic'!
       
  4021 
       
  4022 basicDeleteCharsAtLine:lineNr fromCol:startCol toCol:endCol
       
  4023     "delete characters from startCol to endCol in line lineNr"
       
  4024 
       
  4025     |line lineSize newLine start stop prevWidth newWidth|
       
  4026 
       
  4027     self unselect.
       
  4028 
       
  4029     cursorLine == lineNr ifTrue:[
       
  4030         cursorCol >= startCol ifTrue:[
       
  4031             cursorCol >= endCol ifTrue:[
       
  4032                 cursorCol := startCol.
       
  4033             ] ifFalse:[
       
  4034                 cursorCol := cursorCol - (endCol - startCol + 1).
       
  4035             ]
       
  4036         ].
       
  4037     ].
       
  4038 
       
  4039     line := self listAt:lineNr.
       
  4040 
       
  4041     (self checkModificationsAllowed and:[line notNil]) ifFalse:[^ self].
       
  4042 
       
  4043     lineSize := line size.
       
  4044 
       
  4045     startCol == 0 ifFalse:[ start := startCol ] ifTrue:[ start := 1 ].
       
  4046     endCol > lineSize ifFalse:[ stop  := endCol ] ifTrue:[ stop  := lineSize ].
       
  4047 
       
  4048     stop >= start ifTrue:[
       
  4049         start ~~ 1 ifTrue:[ newLine := line copyFrom:1 to:(start-1) ]
       
  4050                   ifFalse:[ newLine := '' ].
       
  4051 
       
  4052         stop == lineSize ifFalse:[
       
  4053             line bitsPerCharacter > newLine bitsPerCharacter ifTrue:[
       
  4054                 newLine := line string species fromString:newLine.
       
  4055             ].
       
  4056             newLine := newLine, (line copyFrom:(stop + 1) to:lineSize)
       
  4057         ].
       
  4058 
       
  4059         (trimBlankLines and:[newLine isBlank]) ifTrue:[
       
  4060             newLine := nil
       
  4061         ].
       
  4062 
       
  4063         prevWidth := self widthOfLine:lineNr.
       
  4064 
       
  4065         self basicListAt:lineNr put:newLine.
       
  4066 
       
  4067         (prevWidth = widthOfWidestLine) ifTrue:[
       
  4068             "/ remember old width of this line,
       
  4069             "/ only clear widthOfWidestLine, if this lines
       
  4070             "/ length was (one of) the longest.
       
  4071             "/ avoids slow delete with huge texts.
       
  4072             widthOfWidestLine := nil.   "i.e. unknown"
       
  4073 
       
  4074             "/ scroll left if reqiured
       
  4075             viewOrigin x > 0 ifTrue:[
       
  4076                 newWidth := self widthOfLine:lineNr.
       
  4077                 newWidth < (viewOrigin x + width) ifTrue:[
       
  4078                     self scrollHorizontalTo:(newWidth
       
  4079                                              - width
       
  4080                                              + margin + margin
       
  4081                                              + (gc font widthOf:'  '))
       
  4082                 ]
       
  4083             ].
       
  4084             self textChanged.
       
  4085         ] ifFalse:[
       
  4086             self textChanged "/ textChangedButNoSizeChange
       
  4087         ].
       
  4088         gc font hasOverlappingCharacters ifTrue:[
       
  4089             self invalidateLine:lineNr.
       
  4090         ] ifFalse:[
       
  4091             self redrawLine:lineNr from:start.
       
  4092         ].
       
  4093     ].
       
  4094 
       
  4095     "Modified: / 09-11-2010 / 13:42:45 / cg"
       
  4096 !
       
  4097 
       
  4098 basicDeleteFromLine:startLineNr toLine:endLineNr
       
  4099     "delete some lines"
       
  4100 
       
  4101     |wasOn nLines|
       
  4102 
       
  4103     self checkModificationsAllowed ifFalse:[ ^ self].
       
  4104     list isNil ifTrue:[^ self].
       
  4105 
       
  4106     wasOn := self hideCursor.
       
  4107 
       
  4108     "/ isnt this the same as:
       
  4109     "/ self deleteLinesWithoutRedrawFrom:startLineNr to:endLineNr.
       
  4110     startLineNr <= list size ifTrue:[
       
  4111         self basicListRemoveFromIndex:startLineNr toIndex:(endLineNr min:list size).
       
  4112     ].
       
  4113     "/ TODO: remember old maxwidth of linerange,
       
  4114     "/ only clear widthOfWidestLine, if this max
       
  4115     "/ length was (one of) the longest.
       
  4116     "/ avoids slow delete with huge texts.
       
  4117     widthOfWidestLine := nil. "/ i.e. unknown
       
  4118     self textChanged.
       
  4119 
       
  4120     self redrawFromLine:startLineNr.
       
  4121 
       
  4122     nLines := list size.
       
  4123     (firstLineShown >= nLines) ifTrue:[
       
  4124         self makeLineVisible:nLines
       
  4125     ].
       
  4126     wasOn ifTrue:[self showCursor].
       
  4127 
       
  4128     "Modified: / 10-11-1998 / 23:55:05 / cg"
       
  4129     "Modified: / 18-03-2011 / 18:26:23 / az"
       
  4130 !
       
  4131 
       
  4132 basicDeleteLineWithoutRedraw:lineNr
       
  4133     "delete line - no redraw;
       
  4134      return true, if something was really deleted"
       
  4135 
       
  4136     self checkModificationsAllowed ifFalse:[ ^ false].
       
  4137 
       
  4138     (list isNil or:[lineNr > list size]) ifTrue:[^ false].
       
  4139     list removeIndex:lineNr.
       
  4140     "/ TODO: remember old maxwidth of linerange,
       
  4141     "/ only clear widthOfWidestLine, if this max
       
  4142     "/ length was (one of) the longest.
       
  4143     "/ avoids slow delete with huge texts.
       
  4144     widthOfWidestLine := nil. "/ i.e. unknown
       
  4145     self textChanged.
       
  4146     ^ true
       
  4147 
       
  4148     "Modified: / 10.11.1998 / 23:53:24 / cg"
       
  4149 !
       
  4150 
       
  4151 basicInsert:aCharacter atLine:lineNr col:colNr
       
  4152     "insert a single character at lineNr/colNr;
       
  4153      set emphasis to character at current position"
       
  4154 
       
  4155     |line lineSize newLine drawCharacterOnly attribute oldClip x y|
       
  4156 
       
  4157     self checkModificationsAllowed ifFalse:[ ^ self].
       
  4158 
       
  4159     aCharacter == (Character cr) ifTrue:[
       
  4160         self splitLine:lineNr before:colNr.
       
  4161         ^ self
       
  4162     ].
       
  4163 
       
  4164     drawCharacterOnly := false.
       
  4165     self checkForExistingLine:lineNr.
       
  4166     line := list at:lineNr.
       
  4167     lineSize := line size.
       
  4168 
       
  4169     self st80EditMode ifFalse:[
       
  4170         (trimBlankLines
       
  4171         and:[colNr > lineSize
       
  4172         and:[aCharacter == Character space]]) ifTrue:[
       
  4173             ^ self
       
  4174         ]
       
  4175     ].
       
  4176 
       
  4177     (lineSize == 0) ifTrue:[
       
  4178         newLine := aCharacter asString species new:colNr.
       
  4179         drawCharacterOnly := true
       
  4180     ] ifFalse: [
       
  4181         (colNr > lineSize) ifTrue: [
       
  4182             colNr == (lineSize +1) ifTrue:[
       
  4183                 attribute := line emphasisAt:lineSize
       
  4184             ].
       
  4185             newLine := line species new:colNr.
       
  4186             newLine replaceFrom:1 to:lineSize with:line startingAt:1.
       
  4187             drawCharacterOnly := true
       
  4188         ] ifFalse: [
       
  4189             attribute := line emphasisAt:colNr.
       
  4190             newLine   := line species new:(lineSize + 1).
       
  4191 
       
  4192             newLine replaceFrom:1 to:(colNr - 1) with:line startingAt:1.
       
  4193             newLine replaceFrom:(colNr + 1) to:(lineSize + 1) with:line startingAt:colNr
       
  4194         ]
       
  4195     ].
       
  4196 
       
  4197     aCharacter asString bitsPerCharacter > newLine bitsPerCharacter ifTrue:[
       
  4198         newLine := aCharacter asString species fromString:newLine.
       
  4199         line isText ifTrue:[
       
  4200             newLine := newLine asText
       
  4201         ]
       
  4202     ].
       
  4203     newLine at:colNr put:aCharacter.
       
  4204 
       
  4205     attribute notNil ifTrue:[
       
  4206         newLine emphasisAt:colNr put:attribute.
       
  4207     ].
       
  4208 
       
  4209     aCharacter == (Character tab) ifTrue:[
       
  4210         newLine := self withTabsExpanded:newLine.
       
  4211         drawCharacterOnly := false
       
  4212     ].
       
  4213 
       
  4214     self basicListAt:lineNr put:(newLine ifNil:[newLine] ifNotNil:[newLine asSingleByteStringIfPossible]).
       
  4215     widthOfWidestLine notNil ifTrue:[
       
  4216         widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:newLine).
       
  4217     ].
       
  4218     self textChanged.
       
  4219     shown ifTrue:[
       
  4220         "/ care for italic text - in this case, we must also
       
  4221         "/ redraw the character before the insertion in order
       
  4222         "/ to fix the slanted piece of the character.
       
  4223         "/ (but we must clip, to avoid destoying the character before)
       
  4224         (newLine notNil and:[newLine isText]) ifTrue:[
       
  4225             colNr > 1 ifTrue:[
       
  4226                 cursorVisibleLine notNil ifTrue:[
       
  4227                     oldClip := self clippingRectangleOrNil.
       
  4228                     x := (self xOfCol:colNr-1 inVisibleLine:cursorVisibleLine) - viewOrigin x.
       
  4229                     y := self yOfVisibleLine:cursorVisibleLine.
       
  4230 
       
  4231                     gc font hasOverlappingCharacters ifTrue:[
       
  4232                         self invalidateLine:lineNr.
       
  4233                     ] ifFalse:[
       
  4234                         drawCharacterOnly ifTrue:[
       
  4235                             self clippingRectangle:(x@y extent:((gc font width * 2) @ fontHeight)).
       
  4236                             self redrawLine:lineNr from:colNr-1 to:colNr
       
  4237                         ] ifFalse:[
       
  4238                             self clippingRectangle:(x@y extent:((width - x) @ fontHeight)).
       
  4239                             self redrawLine:lineNr from:colNr-1
       
  4240                         ].
       
  4241                         self clippingRectangle:oldClip.
       
  4242                     ].
       
  4243                 ].
       
  4244                 ^ self.
       
  4245             ].
       
  4246         ].
       
  4247         gc font hasOverlappingCharacters ifTrue:[
       
  4248             self invalidateLine:lineNr.
       
  4249         ] ifFalse:[
       
  4250             drawCharacterOnly ifTrue:[
       
  4251                 self redrawLine:lineNr col:colNr
       
  4252             ] ifFalse:[
       
  4253                 self redrawLine:lineNr from:colNr
       
  4254             ]
       
  4255         ]
       
  4256     ]
       
  4257 
       
  4258     "Modified: / 09-11-2010 / 13:43:18 / cg"
       
  4259 !
       
  4260 
       
  4261 basicListAt:lineNr put:newLine
       
  4262     "redefinable for special subclasses (with virtual list)"
       
  4263 
       
  4264     list at:lineNr put:newLine.
       
  4265 !
       
  4266 
       
  4267 basicListRemoveFromIndex:startLineNr toIndex:endLineNr
       
  4268     "redefinable for special subclasses (with virtual list)"
       
  4269 
       
  4270     list removeFromIndex:startLineNr toIndex:(endLineNr min:list size).
       
  4271 !
       
  4272 
       
  4273 basicMergeLine:lineNr removeBlanks:removeBlanks
       
  4274     "merge line lineNr with line lineNr+1"
       
  4275 
       
  4276     |leftPart rightPart bothParts nextLineNr i|
       
  4277 
       
  4278     (list notNil and:[(list size) >= lineNr]) ifFalse:[
       
  4279         "/ empty list or beyond end of text
       
  4280         ^ self
       
  4281     ].
       
  4282     leftPart := self listAt:lineNr.
       
  4283 
       
  4284     leftPart isNil ifTrue:[
       
  4285         leftPart := ''.
       
  4286         autoIndent ifTrue:[
       
  4287             (i := self leftIndentForLine:cursorLine) == 0 ifFalse:[
       
  4288                 leftPart := String new:i
       
  4289             ]
       
  4290         ]
       
  4291     ].
       
  4292     self cursorLine:lineNr col:((leftPart size) + 1).
       
  4293     nextLineNr := self validateCursorLine:(lineNr + 1).
       
  4294 
       
  4295     nextLineNr > (list size) ifFalse:[
       
  4296         (rightPart := self listAt:nextLineNr) isNil ifTrue:[
       
  4297             rightPart := ''
       
  4298         ] ifFalse:[
       
  4299             removeBlanks ifTrue:[
       
  4300                 rightPart := rightPart withoutLeadingSeparators.
       
  4301             ]
       
  4302         ].
       
  4303 
       
  4304         bothParts := leftPart , rightPart.
       
  4305         (trimBlankLines and:[bothParts isBlank]) ifTrue:[bothParts := nil].
       
  4306         self basicListAt:lineNr put:bothParts.
       
  4307         self redrawLine:lineNr.
       
  4308         self deleteLine:nextLineNr
       
  4309     ]
       
  4310 
       
  4311     "Created: 9.9.1997 / 09:27:38 / cg"
       
  4312     "Modified: 9.9.1997 / 09:28:27 / cg"
       
  4313 !
       
  4314 
       
  4315 basicReplace:aCharacter atLine:lineNr col:colNr
       
  4316     "replace a single character at lineNr/colNr"
       
  4317 
       
  4318     |line lineSize newLine drawCharacterOnly|
       
  4319 
       
  4320     self checkModificationsAllowed ifFalse:[ ^ self].
       
  4321 
       
  4322     aCharacter == (Character cr) ifTrue:[
       
  4323         ^ self
       
  4324     ].
       
  4325 
       
  4326     drawCharacterOnly := true.
       
  4327     self checkForExistingLine:lineNr.
       
  4328     line := list at:lineNr.
       
  4329     lineSize := line size.
       
  4330 
       
  4331     (trimBlankLines
       
  4332     and:[colNr > lineSize
       
  4333     and:[aCharacter == Character space]]) ifTrue:[
       
  4334         ^ self
       
  4335     ].
       
  4336 
       
  4337     (lineSize == 0) ifTrue:[
       
  4338         newLine := aCharacter asString species new:colNr.
       
  4339     ] ifFalse: [
       
  4340         (colNr > lineSize) ifTrue: [
       
  4341             newLine := line species new:colNr.
       
  4342             newLine replaceFrom:1 to:lineSize with:line startingAt:1.
       
  4343         ] ifFalse: [
       
  4344             newLine := line copy.
       
  4345         ]
       
  4346     ].
       
  4347     newLine at:colNr put:aCharacter.
       
  4348     aCharacter == (Character tab) ifTrue:[
       
  4349         newLine := self withTabsExpanded:newLine.
       
  4350         drawCharacterOnly := false
       
  4351     ].
       
  4352     self basicListAt:lineNr put:(newLine ifNil:[newLine] ifNotNil:[newLine asSingleByteStringIfPossible]).
       
  4353     widthOfWidestLine notNil ifTrue:[
       
  4354         widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:newLine).
       
  4355     ].
       
  4356     self textChanged.
       
  4357     shown ifTrue:[
       
  4358         gc font hasOverlappingCharacters ifTrue:[
       
  4359             self invalidateLine:lineNr.
       
  4360         ] ifFalse:[
       
  4361             drawCharacterOnly ifTrue:[
       
  4362                 self redrawLine:lineNr col:colNr
       
  4363             ] ifFalse:[
       
  4364                 self redrawLine:lineNr from:colNr
       
  4365             ]
       
  4366         ]
       
  4367     ]
       
  4368 
       
  4369     "Created: / 06-03-1996 / 12:29:20 / cg"
       
  4370     "Modified: / 09-11-2010 / 13:42:54 / cg"
       
  4371 !
       
  4372 
       
  4373 basicReplaceString:aString atLine:lineNr col:colNr
       
  4374     "replace multiple characters starting at lineNr/colNr.
       
  4375      This is not prepared to encounter special chars (except TAB)
       
  4376      in the string."
       
  4377 
       
  4378     |line lineSize newLine endCol|
       
  4379 
       
  4380     self checkModificationsAllowed ifFalse:[ ^ self].
       
  4381 
       
  4382     self checkForExistingLine:lineNr.
       
  4383     line := list at:lineNr.
       
  4384     lineSize := line size.
       
  4385 
       
  4386     endCol := colNr + aString size - 1.
       
  4387     (lineSize == 0) ifTrue:[
       
  4388         newLine := aString species new:endCol.
       
  4389     ] ifFalse: [
       
  4390         (endCol > lineSize) ifTrue: [
       
  4391             aString isText ifTrue:[
       
  4392                 newLine := aString species new:endCol.
       
  4393             ] ifFalse:[
       
  4394                 newLine := line species new:endCol.
       
  4395             ].
       
  4396             newLine replaceFrom:1 to:lineSize with:line startingAt:1.
       
  4397         ] ifFalse: [
       
  4398             aString isText ifTrue:[
       
  4399                 newLine := aString species new:line size.
       
  4400                 newLine replaceFrom:1 to:lineSize with:line startingAt:1.
       
  4401             ] ifFalse:[
       
  4402                 newLine := line copy.
       
  4403             ]
       
  4404         ]
       
  4405     ].
       
  4406     newLine replaceFrom:colNr with:aString.
       
  4407     (aString includes:(Character tab)) ifTrue:[
       
  4408         newLine := self withTabsExpanded:newLine.
       
  4409     ].
       
  4410     self basicListAt:lineNr put:(newLine ifNil:[newLine] ifNotNil:[newLine asSingleByteStringIfPossible]).
       
  4411     widthOfWidestLine notNil ifTrue:[
       
  4412         widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:newLine).
       
  4413     ].
       
  4414     self textChanged.
       
  4415     shown ifTrue:[
       
  4416         gc font hasOverlappingCharacters ifTrue:[
       
  4417             self invalidateLine:lineNr.
       
  4418         ] ifFalse:[
       
  4419             self redrawLine:lineNr from:colNr
       
  4420         ]
       
  4421     ]
       
  4422 
       
  4423     "Created: / 11-06-1998 / 10:38:32 / cg"
       
  4424     "Modified: / 09-11-2010 / 13:42:56 / cg"
       
  4425 !
       
  4426 
       
  4427 basicSplitLine:lineNr before:colNr
       
  4428     "split the line linNr before colNr; the right part (from colNr)
       
  4429      is cut off and inserted after lineNr; the view is redrawn"
       
  4430 
       
  4431     |line lineSize leftRest rightRest visLine w h mustWait
       
  4432      srcY    "{ Class: SmallInteger }" |
       
  4433 
       
  4434     list isNil ifTrue:[ ^ self ].
       
  4435     lineNr > (list size) ifTrue:[ ^ self ].
       
  4436 
       
  4437     (colNr == 1) ifTrue:[
       
  4438         self nonUndoableDo:[
       
  4439             self insertLine:nil before:lineNr.
       
  4440         ].
       
  4441         ^ self
       
  4442     ].
       
  4443 
       
  4444     line := list at:lineNr.
       
  4445     line notNil ifTrue:[
       
  4446         lineSize := line size.
       
  4447         (colNr <= lineSize) ifTrue:[
       
  4448             rightRest := line copyFrom:colNr to:lineSize.
       
  4449             (colNr > 1) ifTrue:[
       
  4450                 leftRest := line copyTo:(colNr - 1)
       
  4451             ]
       
  4452         ] ifFalse:[
       
  4453             leftRest := line
       
  4454         ]
       
  4455     ].
       
  4456     leftRest notNil ifTrue:[
       
  4457         (trimBlankLines and:[leftRest isBlank]) ifTrue:[leftRest := nil]
       
  4458     ].
       
  4459     self basicListAt:lineNr put:leftRest.
       
  4460     self nonUndoableDo:[
       
  4461         self withoutRedrawInsertLine:rightRest before:(lineNr + 1).
       
  4462     ].
       
  4463     visLine := self listLineToVisibleLine:(lineNr).
       
  4464     visLine notNil ifTrue:[
       
  4465         w := self widthForScrollBetween:lineNr
       
  4466                                     and:(firstLineShown + nLinesShown).
       
  4467         srcY := topMargin + (visLine * fontHeight).
       
  4468         h := ((nLinesShown - visLine - 1) * fontHeight).
       
  4469         (mustWait := (w > 0 and:[h > 0])) ifTrue:[
       
  4470             self catchExpose.
       
  4471             self
       
  4472                 copyFrom:self
       
  4473                 x:textStartLeft y:srcY
       
  4474                 toX:textStartLeft y:(srcY + fontHeight)
       
  4475                 width:w
       
  4476                 height:((nLinesShown - visLine - 1) * fontHeight)
       
  4477                 async:true.
       
  4478         ].
       
  4479         self redrawLine:lineNr.
       
  4480         self redrawLine:(lineNr + 1).
       
  4481         mustWait ifTrue:[self waitForExpose]
       
  4482     ].
       
  4483     widthOfWidestLine := nil. "/ unknown
       
  4484     self textChanged.
       
  4485 
       
  4486     "Modified: / 06-12-2010 / 13:12:55 / cg"
       
  4487 !
       
  4488 
       
  4489 basicWithoutRedrawInsertLines:lines from:start to:end before:lineNr
       
  4490     "insert a bunch of lines before line lineNr; the view is not redrawn.
       
  4491      Tabs are expanded here with a tab=8 setting (independent of any editor-setting,
       
  4492      because the text might have been pasted from an alien view."
       
  4493 
       
  4494     |newLine newLines nLines|
       
  4495 
       
  4496     nLines := end - start + 1.
       
  4497     newLines := Array new:(lines size).
       
  4498     start to:end do:[:index |
       
  4499         newLine := lines at:index.
       
  4500         newLine notNil ifTrue:[
       
  4501             newLine isString ifTrue:[
       
  4502                 newLine isBlank ifTrue:[
       
  4503                     newLine := nil
       
  4504                 ] ifFalse:[
       
  4505                     (newLine includes:(Character tab)) ifTrue:[
       
  4506                         newLine := self withTabs:(ListView tab8Positions) expand:newLine
       
  4507                     ]
       
  4508                 ]
       
  4509             ]
       
  4510         ].
       
  4511         newLines at:index put:newLine
       
  4512     ].
       
  4513     list isNil ifTrue: [
       
  4514         list := StringCollection new:(lineNr + nLines + 1)
       
  4515     ] ifFalse: [
       
  4516         list grow:((list size + nLines) max:(lineNr + nLines - 1))
       
  4517     ].
       
  4518 
       
  4519     "I have changed 'replaceFrom:to:with:startingAt:' to correctly handle
       
  4520      overlapping copy - if it didn't, we had to use:"
       
  4521 "
       
  4522     index := list size.
       
  4523     [index > lineNr] whileTrue: [
       
  4524         pIndex := index - 1.
       
  4525         list at:index put:(list at:pIndex).
       
  4526         index := pIndex
       
  4527     ].
       
  4528 "
       
  4529     list replaceFrom:(lineNr + nLines) to:(list size) with:list startingAt:lineNr.
       
  4530     list replaceFrom:lineNr to:(lineNr + nLines - 1) with:newLines startingAt:start.
       
  4531     self contentsChanged
       
  4532 
       
  4533     "Modified: / 07-10-2011 / 15:55:18 / cg"
       
  4534 !
       
  4535 
       
  4536 basicWithoutRedrawInsertStringWithoutCRs:aString atLine:lineNr col:colNr
       
  4537     "insert aString (which has no crs) at lineNr/colNr.
       
  4538      Tabs are expanded here with a tab=8 setting (independent of any editor-setting,
       
  4539      because the text might have been pasted from an alien view."
       
  4540 
       
  4541     |isText strLen line lineSize newLine stringType sz lineCharWidth stringCharWidth|
       
  4542 
       
  4543     (aString isNil) ifTrue:[ ^ self].
       
  4544 
       
  4545     strLen := aString size.
       
  4546     self checkForExistingLine:lineNr.
       
  4547 
       
  4548     stringType := aString string species.
       
  4549     isText     := aString isText.
       
  4550     line       := list at:lineNr.
       
  4551 
       
  4552     line notNil ifTrue:[
       
  4553         lineSize := line size.
       
  4554         line isString ifFalse:[
       
  4555             stringType := line species
       
  4556         ] ifTrue:[
       
  4557             lineCharWidth := line bitsPerCharacter.
       
  4558             stringCharWidth := aString bitsPerCharacter.
       
  4559             lineCharWidth > stringCharWidth ifTrue:[
       
  4560                 stringType := line string species
       
  4561             ] ifFalse:[
       
  4562                 stringCharWidth > lineCharWidth ifTrue:[
       
  4563                     stringType := aString string species
       
  4564                 ]
       
  4565             ].
       
  4566             line isText ifTrue:[ isText := true ]
       
  4567         ].
       
  4568     ] ifFalse:[
       
  4569         lineSize := 0
       
  4570     ].
       
  4571 
       
  4572     ((colNr == 1) and:[lineSize == 0]) ifTrue: [
       
  4573         newLine := aString
       
  4574     ] ifFalse:[
       
  4575         (lineSize == 0 or:[colNr > lineSize]) ifTrue: [
       
  4576             sz := colNr + strLen - 1
       
  4577         ] ifFalse:[
       
  4578             sz := lineSize + strLen
       
  4579         ].
       
  4580 
       
  4581         newLine := stringType new:sz.
       
  4582         isText ifTrue:[
       
  4583             newLine := Text string:newLine
       
  4584         ].
       
  4585 
       
  4586         (lineSize ~~ 0) ifTrue: [
       
  4587             (colNr > lineSize) ifTrue: [
       
  4588                 newLine replaceFrom:1 to:lineSize with:line startingAt:1
       
  4589             ] ifFalse: [
       
  4590                 newLine replaceFrom:1 to:(colNr - 1) with:line startingAt:1.
       
  4591                 newLine replaceFrom:(colNr + strLen) to:(lineSize + strLen) with:line startingAt:colNr
       
  4592             ]
       
  4593         ].
       
  4594         newLine replaceFrom:(colNr max:1) to:(colNr + strLen - 1) with:aString startingAt:1
       
  4595     ].
       
  4596 
       
  4597     (aString includes:(Character tab)) ifTrue:[
       
  4598         newLine := self withTabs:(ListView tab8Positions) expand:newLine
       
  4599     ].
       
  4600 
       
  4601     self basicListAt:lineNr put:(newLine ifNil:[newLine] ifNotNil:[newLine asSingleByteStringIfPossible]).
       
  4602     widthOfWidestLine notNil ifTrue:[
       
  4603         widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:newLine).
       
  4604     ].
       
  4605     self textChanged.
       
  4606 
       
  4607     "Modified: / 25-01-2012 / 00:37:29 / cg"
       
  4608 ! !
       
  4609 
       
  4610 !EditTextView methodsFor:'event handling'!
       
  4611 
       
  4612 buttonPress:button x:x y:y
       
  4613     "hide the cursor when button is activated"
       
  4614 
       
  4615     hasKeyboardFocus := true.
       
  4616     dragIsActive := false.
       
  4617 
       
  4618     completionSupport notNil ifTrue:[ 
       
  4619         "/ also give that guy a chance to close its popup view
       
  4620         completionSupport buttonPress:button x:x y:y
       
  4621     ].
       
  4622 
       
  4623     cursorShown ifTrue: [
       
  4624         self drawCursor
       
  4625     ].
       
  4626 
       
  4627     "On X11, be nice and paste PRIMARY when middle click. 
       
  4628      Note, that middle button on X11 is translated to button
       
  4629      128 in Smalltalk/X - see XWorkstation class>>initializeConstants"
       
  4630     (button == #paste and:[self graphicsDevice platformName == #X11]) ifTrue:[
       
  4631         self undoableDo:[
       
  4632             self paste: (self getClipboardText:#selection).
       
  4633         ].
       
  4634         ^self.
       
  4635     ].
       
  4636 
       
  4637     (button == 1) ifTrue:[
       
  4638         self hideCursor
       
  4639     ].
       
  4640 "/ some very old code from times, when a right-click was a paste in X11
       
  4641 "/
       
  4642 "/    (button == #paste) ifTrue:[
       
  4643 "/        self pasteOrReplace.
       
  4644 "/        ^ self
       
  4645 "/    ].
       
  4646     super buttonPress:button x:x y:y
       
  4647 
       
  4648     "Modified: / 23-03-1999 / 13:51:40 / cg"
       
  4649     "Modified (comment): / 17-04-2012 / 21:02:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
  4650 !
       
  4651 
       
  4652 buttonRelease:button x:x y:y
       
  4653     "move the cursor to the click-position of previous button press"
       
  4654 
       
  4655     |x1 x2 x2_3 newCursorCol|
       
  4656 
       
  4657     (button == 1) ifTrue:[
       
  4658         typeOfSelection := nil.
       
  4659 
       
  4660         dragIsActive ifTrue:[
       
  4661             self unselect
       
  4662         ].
       
  4663         selectionStartLine isNil ifTrue:[
       
  4664             clickCol notNil ifTrue:[
       
  4665                 self cursorMovementAllowed ifTrue:[
       
  4666                     newCursorCol := clickCol.
       
  4667 
       
  4668                     cursorType ~~ #block ifTrue:[
       
  4669                         clickPos notNil ifTrue:[
       
  4670                             "/ we do something special, if the text-cursor's type is not a block-cursor
       
  4671                             "/ (i.e. if its an ibeam).
       
  4672                             "/ adjust clickCol if the user clicked in the right third of a character.
       
  4673                             x1 := self xOfCol:clickCol inVisibleLine:clickLine.  
       
  4674                             x2 := self xOfCol:clickCol+1 inVisibleLine:clickLine.
       
  4675                             x2_3 := x1 + ((x2-x1) * (2/3)).
       
  4676                             (clickPos x >= x2_3) ifTrue:[ newCursorCol := clickCol+1 ].
       
  4677                         ].
       
  4678                     ].
       
  4679                     self cursorLine:clickLine col:newCursorCol.
       
  4680                 ].
       
  4681                 true "self hadSelectionBeforeClick not" ifTrue:[
       
  4682                     list notEmptyOrNil ifTrue:[
       
  4683                         UserPreferences current selectAllWhenClickingBeyondEnd ifTrue:[
       
  4684                             (clickLine >= list size) ifTrue:[
       
  4685                                 (clickLine > (self list size + 2) 
       
  4686                                 or:[ clickCol > (list last size + 5) ]) ifTrue:[
       
  4687                                     self selectAll
       
  4688                                 ].
       
  4689                             ].
       
  4690                         ]
       
  4691                     ]
       
  4692                 ]
       
  4693             ]
       
  4694         ] ifFalse:[
       
  4695             lastStringFromReplaceForNextSearch := nil.  "new selection invalidates remembered string"
       
  4696         ].
       
  4697         self showCursor
       
  4698     ].
       
  4699     super buttonRelease:button x:x y:y
       
  4700 
       
  4701     "Modified: / 07-03-2012 / 18:48:37 / cg"
       
  4702 !
       
  4703 
       
  4704 cursorKeyPress:key shifted:shifted
       
  4705     <resource: #keyboard (#CursorRight #CursorDown #CursorUp #CursorDown)>
       
  4706 
       
  4707     |n|
       
  4708 
       
  4709     self changeTypeOfSelectionTo:nil.
       
  4710 
       
  4711     (key == #CursorRight) ifTrue:[
       
  4712         (shifted and:[selectionStartLine isNil]) ifTrue:[
       
  4713             selectionStartLine := selectionEndLine := clickStartLine := cursorLine.
       
  4714             selectionStartCol := selectionEndCol := clickStartCol := cursorCol.
       
  4715             expandingTop := false.
       
  4716             self validateNewSelection.
       
  4717             self setPrimarySelection.
       
  4718             self selectionChanged.
       
  4719             self redrawLine:selectionStartLine.
       
  4720             ^ self.
       
  4721         ].
       
  4722 
       
  4723         selectionStartLine notNil ifTrue:[
       
  4724             self cursorMovementAllowed ifTrue:[
       
  4725                 "/
       
  4726                 "/ treat the whole selection as cursor
       
  4727                 "/
       
  4728                 self setCursorLine:(selectionEndLine ? selectionStartLine).
       
  4729                 selectionEndCol == 0 ifTrue:[
       
  4730                     selectionEndCol := 1.
       
  4731                 ].
       
  4732                 self setCursorCol:selectionEndCol.
       
  4733                 shifted ifTrue:[
       
  4734                     self expandSelectionRight.
       
  4735                     ^ self
       
  4736                 ].
       
  4737                 self unselect; makeCursorVisible.
       
  4738                 cursorCol == 1 ifTrue:[^ self].
       
  4739             ].
       
  4740         ].
       
  4741         self cursorRight.
       
  4742         ^ self
       
  4743     ].
       
  4744     (key == #CursorDown) ifTrue:[
       
  4745         (shifted and:[selectionStartLine isNil]) ifTrue:[
       
  4746             selectionStartLine := clickStartLine := cursorLine. selectionEndLine := cursorLine + 1.
       
  4747             selectionStartCol := clickStartCol := selectionEndCol := cursorCol.
       
  4748             selectionEndCol == 1 ifTrue:[
       
  4749                 selectionEndCol := 0.
       
  4750             ].
       
  4751             self validateNewSelection.
       
  4752             self selectionChanged.
       
  4753             self redrawLine:selectionStartLine.
       
  4754             expandingTop := false.
       
  4755             self redrawLine:selectionEndLine.
       
  4756             ^ self
       
  4757         ].
       
  4758 
       
  4759         selectionStartLine notNil ifTrue:[
       
  4760             self cursorMovementAllowed ifTrue:[
       
  4761                 "/
       
  4762                 "/ treat the whole selection as cursor
       
  4763                 "/
       
  4764                 self setCursorLine:(selectionEndLine ? selectionStartLine).
       
  4765                 self setCursorCol:selectionStartCol.
       
  4766                 (cursorCol == 0 or:[selectionEndCol == 0]) ifTrue:[
       
  4767                     self setCursorCol:1.
       
  4768                     self setCursorLine:(cursorLine - 1).
       
  4769                 ].
       
  4770                 self makeCursorVisible.
       
  4771 
       
  4772                 shifted ifTrue:[
       
  4773                     clickLine := cursorLine.
       
  4774                     clickCol := cursorCol.
       
  4775                     self expandSelectionDown.
       
  4776                     ^ self
       
  4777                 ].
       
  4778                 self unselect.
       
  4779             ].
       
  4780         ].
       
  4781 
       
  4782         n := 1 + (self sensor compressKeyPressEventsWithKey:#CursorDown).
       
  4783         self cursorDown:n.
       
  4784         "/
       
  4785         "/ flush keyboard to avoid runaway cursor
       
  4786         "/
       
  4787         self sensor flushKeyboardFor:self.
       
  4788         ^ self
       
  4789     ].
       
  4790     (key == #CursorLeft or:[key == #CursorUp]) ifTrue:[
       
  4791         (shifted and:[selectionStartLine isNil]) ifTrue:[
       
  4792             expandingTop := true.
       
  4793             key == #CursorLeft ifTrue:[
       
  4794                 cursorCol > 1 ifTrue:[
       
  4795                     selectionStartLine := selectionEndLine := clickStartLine := cursorLine.
       
  4796                     selectionEndCol := clickStartCol := cursorCol-1.
       
  4797                     selectionStartCol := cursorCol-1.
       
  4798                     self validateNewSelection.
       
  4799                     self selectionChanged.
       
  4800                     self redrawLine:selectionStartLine.
       
  4801                     ^ self
       
  4802                 ]
       
  4803             ] ifFalse:[
       
  4804                 cursorLine > 1 ifTrue:[
       
  4805                     selectionEndLine := clickStartLine := cursorLine.
       
  4806                     selectionEndCol := selectionStartCol := clickStartCol := cursorCol.
       
  4807                     selectionStartLine := cursorLine - 1.
       
  4808                     selectionEndCol == 1 ifTrue:[
       
  4809                         selectionEndCol := 0.
       
  4810                     ].
       
  4811                     self validateNewSelection.
       
  4812                     self selectionChanged.
       
  4813                     self redrawFromLine:selectionStartLine to:cursorLine.
       
  4814                     ^ self
       
  4815                 ]
       
  4816             ]
       
  4817         ].
       
  4818 
       
  4819         selectionStartLine notNil ifTrue:[
       
  4820             self cursorMovementAllowed ifTrue:[
       
  4821                 "/
       
  4822                 "/ treat the whole selection as cursor
       
  4823                 "/
       
  4824                 self setCursorLine:selectionStartLine.
       
  4825                 self setCursorCol:selectionStartCol.
       
  4826                 (key == #CursorLeft) ifTrue:[
       
  4827                     self setCursorCol:(cursorCol+1).  "/ compensate for followup crsr-left
       
  4828                 ].
       
  4829                 self makeCursorVisible.
       
  4830 
       
  4831                 shifted ifTrue:[
       
  4832                     (key == #CursorUp) ifTrue:[
       
  4833                         clickLine := cursorLine.
       
  4834                         self expandSelectionUp.
       
  4835                     ] ifFalse:[
       
  4836                         self expandSelectionLeft.
       
  4837                     ].
       
  4838                     ^ self
       
  4839                 ].
       
  4840                 self unselect.
       
  4841             ].
       
  4842         ].
       
  4843         (key == #CursorLeft) ifTrue:[
       
  4844             self cursorLeft. ^self
       
  4845         ].
       
  4846         (key == #CursorUp)        ifTrue:[
       
  4847             n := 1 + (self sensor compressKeyPressEventsWithKey:#CursorUp).
       
  4848             self cursorUp:n.
       
  4849             "/
       
  4850             "/ flush keyboard to avoid runaway cursor
       
  4851             "/
       
  4852             self sensor flushKeyboardFor:self.
       
  4853             ^ self
       
  4854         ].
       
  4855     ].
       
  4856 
       
  4857     "Modified: / 17-04-2012 / 21:01:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
  4858 !
       
  4859 
       
  4860 doKeyPress:key x:x y:y
       
  4861     "handle keyboard input"
       
  4862 
       
  4863     <resource: #keyboard (#Paste #Insert #PasteFromHistory #Cut #Again #AgainForAll
       
  4864                           #Replace #Undo #Redo #Accept
       
  4865                           #Delete #BasicDelete #BackSpace #BasicBackspace
       
  4866                           #DeleteSpaces #Join
       
  4867                           #SearchMatchingParent #SelectMatchingParents
       
  4868                           #SelectWord #ExpandSelectionByWord
       
  4869                           #SelectToEnd #SelectFromBeginning
       
  4870                           #SelectLine #ExpandSelectionByLine
       
  4871                           #BeginOfLine #EndOfLine #NextWord #PreviousWord
       
  4872                           #CursorRight #CursorDown #CursorLeft #CursorUp
       
  4873                           #Return #Tab #BackTab #NonInsertingTab #Escape
       
  4874                           #GotoLine #BeginOfText #EndOfText
       
  4875                           #InsertLine #DeleteLine
       
  4876                           #SelectLineFromBeginning
       
  4877                           #LearnKeyboardMacro #ExecuteKeyboardMacro #ToggleInsertMode
       
  4878                           #OpenSpecialCharacterWindow
       
  4879                           #'F*' #'f*')>
       
  4880 
       
  4881     |fKeyMacros shiftPressed ctrlPressed i event macroName
       
  4882      immediateCompletion currentUserPrefs|
       
  4883 
       
  4884     currentUserPrefs := UserPreferences current.
       
  4885 
       
  4886     "/ experimental
       
  4887     immediateCompletion := currentUserPrefs immediateCodeCompletion.
       
  4888     (immediateCompletion 
       
  4889     or:[currentUserPrefs codeCompletionOnControlKey
       
  4890     or:[currentUserPrefs codeCompletionOnTabKey]]) ifTrue:[
       
  4891         completionSupport isNil ifTrue:[
       
  4892             self initializeCompletionSupport.
       
  4893         ].
       
  4894     ].
       
  4895     "/ JV: why setting it to nil here?
       
  4896 "/    ifFalse:[
       
  4897 "/        completionService := nil
       
  4898 "/    ].
       
  4899     completionSupport notNil ifTrue:[
       
  4900         (completionSupport handleKeyPress:key x:x y:y) ifTrue:["eaten" ^ self].
       
  4901     ].
       
  4902 
       
  4903     key isSymbol ifTrue:[
       
  4904         (self graphicsDevice modifierKeys includes:key) ifFalse:[
       
  4905             lastReplacementInfo stillCollectingInput:false.
       
  4906         ]
       
  4907     ].
       
  4908     (key == #LearnKeyboardMacro) ifTrue:[
       
  4909         lastReplacementInfo stillCollectingInput:false.
       
  4910         self toggleLearnMode.
       
  4911         ^ self
       
  4912     ].
       
  4913     (key == #ExecuteKeyboardMacro) ifTrue:[
       
  4914         lastReplacementInfo stillCollectingInput:false.
       
  4915         self executeLearnedKeyboardMacro.
       
  4916         ^ self.
       
  4917     ].
       
  4918     (key == #Undo) ifTrue:[self undo. ^self].
       
  4919     (key == #Redo) ifTrue:[self redo. ^self].
       
  4920 
       
  4921     self learnMode ifTrue:[
       
  4922         event := WindowGroup lastEventQuerySignal query.
       
  4923         learnedMacro add:event.
       
  4924     ].
       
  4925 
       
  4926     (self executekeyboardMacroNamed:key) ifTrue:[
       
  4927         "the macro named key exists"
       
  4928         ^ self
       
  4929     ].
       
  4930 
       
  4931     key isSymbol ifFalse:[
       
  4932         "the usual case: key is a character, but maybe a string also (in X11)"
       
  4933         self handleNonCommandKey:key.
       
  4934         ^ self
       
  4935     ].
       
  4936 
       
  4937     event isNil ifTrue:[
       
  4938         event := WindowGroup lastEventQuerySignal query.
       
  4939     ].
       
  4940     shiftPressed := event hasShift.
       
  4941     ctrlPressed := event hasCtrl and:[(event rawKey asString startsWith:'Ctrl') not].
       
  4942 
       
  4943     (key == #DeleteWordBeforeCursor) ifTrue:[
       
  4944         self deleteWordBeforeCursor.
       
  4945         ^ self.
       
  4946     ].
       
  4947 
       
  4948     (key == #BackSpace or:[key == #BasicBackspace]) ifTrue:[
       
  4949         selectionStartLine notNil ifTrue:[
       
  4950             ((key == #BasicBackspace)
       
  4951             or:[ currentUserPrefs deleteSetsClipboardText not ])
       
  4952             ifTrue:[
       
  4953                 self deleteSelection.
       
  4954             ] ifFalse: [
       
  4955                 self copyAndDeleteSelection.
       
  4956             ].
       
  4957         ] ifFalse:[
       
  4958             self makeCursorVisible.
       
  4959 "/          (shiftPressed and:[ ctrlPressed ]) ifTrue:[
       
  4960 "/            self deleteWordBeforeCursor.
       
  4961 "/          ] ifFalse:[
       
  4962             self deleteCharBeforeCursor.
       
  4963 "/          ].
       
  4964         ].
       
  4965         true "immediateCompletion" ifTrue:[ 
       
  4966             completionSupport notNil ifTrue:[ completionSupport postKeyPress:key].
       
  4967         ].
       
  4968         ^ self
       
  4969     ].
       
  4970 
       
  4971     (key == #ToggleAutoIndent) ifTrue:[
       
  4972         self autoIndent:(autoIndent not).
       
  4973         ^ self.
       
  4974     ].
       
  4975 
       
  4976     key == #ToggleInsertMode ifTrue:[
       
  4977         self insertMode:(editMode value == EditMode insertMode) not.
       
  4978         ^ self.
       
  4979     ].
       
  4980 
       
  4981     key == #OpenSpecialCharacterWindow ifTrue:[
       
  4982         CharacterSetView notNil ifTrue:[
       
  4983             self specialCharacters.
       
  4984             ^ self.
       
  4985         ]        
       
  4986     ].
       
  4987 
       
  4988     replacing := false.
       
  4989 
       
  4990     "
       
  4991      Fn      pastes a key-sequence (but only if not overlayed with
       
  4992              another function in the keyboard map)
       
  4993 
       
  4994      see TextView>>:x:y
       
  4995     "
       
  4996     (key at:1) asLowercase == $f ifTrue:[
       
  4997         (('[fF][0-9]' match:key)
       
  4998         or:['[fF][0-9][0-9]' match:key]) ifTrue:[
       
  4999             shiftPressed ifFalse:[
       
  5000                 fKeyMacros := currentUserPrefs functionKeySequences.
       
  5001                 fKeyMacros notNil ifTrue:[
       
  5002                     (fKeyMacros includesKey:key) ifTrue:[
       
  5003                         self pasteOrReplace:(fKeyMacros at:key) asStringCollection.
       
  5004                         ^ self
       
  5005                     ]
       
  5006                 ]
       
  5007             ]
       
  5008         ].
       
  5009     ].
       
  5010 
       
  5011     (key == #'Ctrl8' or:[key == #'Ctrl9']) ifTrue:[
       
  5012         self parenthizeSelectionWith:$( and:$).
       
  5013         ^ self.
       
  5014     ].
       
  5015     (key == #'Ctrl2') ifTrue:[
       
  5016         self parenthizeSelectionWith:$" and:$".
       
  5017         ^ self.
       
  5018     ].
       
  5019     (key == #'Ctrl#') ifTrue:[
       
  5020         self parenthizeSelectionWith:$' and:$'.
       
  5021         ^ self.
       
  5022     ].
       
  5023     (key == #'ConvertSelectionToLowercaseOrUppercaseOrUppercaseFirst') ifTrue:[
       
  5024         self convertSelectionToLowercaseOrUppercaseOrUppercaseFirst.
       
  5025         ^ self.
       
  5026     ].
       
  5027 
       
  5028     (key == #Accept)  ifTrue:[^ self accept].
       
  5029 
       
  5030     ((key == #Paste) or:[key == #Insert or:[key == #PasteFromHistory]]) ifTrue:[self pasteOrReplace. ^self].
       
  5031     (key == #Cut) ifTrue:[self cut. ^self].
       
  5032     (key == #Again) ifTrue:[self again. ^self].
       
  5033     (key == #AgainForAll) ifTrue:[self multipleAgain. ^self].
       
  5034 
       
  5035     (key == #Join) ifTrue:[self joinLines. ^self].
       
  5036     (key == #Replace) ifTrue:[self replace. ^self].
       
  5037     (key == #ExpandSelectionByWord) ifTrue:[
       
  5038         self makeCursorVisible.
       
  5039         self findNextWordAfterSelectionAndAddToSelection.
       
  5040         ^ self
       
  5041     ].
       
  5042     (key == #SelectWord) ifTrue:[
       
  5043         self makeCursorVisible.
       
  5044         self selectWordUnderCursor.
       
  5045         ^ self
       
  5046     ].
       
  5047 
       
  5048     (key == #SearchMatchingParent) ifTrue:[self searchForMatchingParenthesis. ^ self].
       
  5049     (key == #SelectMatchingParents) ifTrue:[self searchForAndSelectMatchingParenthesis. ^ self].
       
  5050     (key == #SelectToEnd) ifTrue:[self selectUpToEnd. ^ self].
       
  5051     (key == #SelectFromBeginning) ifTrue:[self selectFromBeginning. ^ self].
       
  5052 
       
  5053 " disabled - nobody liked it ...
       
  5054   and if you like it, its better done in the keymap.
       
  5055 
       
  5056     (key == #Ctrlb) ifTrue:[self unselect. self cursorLeft. ^ self].
       
  5057     (key == #Ctrlf) ifTrue:[self unselect. self cursorRight. ^ self].
       
  5058     (key == #Ctrln) ifTrue:[self unselect. self cursorDown. ^ self].
       
  5059     (key == #Ctrlp) ifTrue:[self unselect. self cursorUp. ^ self].
       
  5060 "
       
  5061 
       
  5062     (key == #BeginOfLine) ifTrue:[
       
  5063         shiftPressed ifTrue: [
       
  5064             "/ "Original St/X code - now use Ctrl modifier"
       
  5065             "/ self unselect.
       
  5066             "/ self cursorHome.
       
  5067             "Jan's modification"
       
  5068             "/ self addToSelectionAfter:[ self cursorToBeginOfLine ].
       
  5069             "/ Jan's modification modified by his own request ;-))
       
  5070             self selectFromBeginOfLine.
       
  5071         ] ifFalse: [
       
  5072             self unselect.
       
  5073             ctrlPressed ifTrue:[
       
  5074                 self cursorHome.
       
  5075             ] ifFalse:[
       
  5076                 self cursorToBeginOfLine.
       
  5077             ]
       
  5078         ].
       
  5079         ^ self
       
  5080     ].
       
  5081     (key == #EndOfLine) ifTrue:[
       
  5082         shiftPressed ifTrue:[
       
  5083             "/ "Original St/X code - now use Ctrl modifier"
       
  5084             "/ self unselect.
       
  5085             "/ self cursorToBottom
       
  5086             " Jan's modification"
       
  5087             "/ self addToSelectionAfter:[ self cursorToEndOfLine ] .
       
  5088             "/ Jan's modification modified by his own request ;-))
       
  5089             self selectToEndOfLine.
       
  5090         ] ifFalse:[
       
  5091             self unselect.
       
  5092             ctrlPressed ifTrue:[
       
  5093                 self cursorToBottom
       
  5094             ] ifFalse:[
       
  5095                 self cursorToEndOfLine.
       
  5096             ]
       
  5097         ].
       
  5098         ^ self
       
  5099     ].
       
  5100     (key == #NextWord) ifTrue:[self cursorToNextWord. ^self].
       
  5101     (key == #EndOfWord) ifTrue:[self cursorToEndOfWord. ^self].
       
  5102     (key == #PreviousWord) ifTrue:[self cursorToPreviousWord. ^self].
       
  5103     (key == #GotoLine) ifTrue:[self gotoLine. ^self].
       
  5104 
       
  5105     (key == #CursorRight
       
  5106     or:[key == #CursorDown
       
  5107     or:[key == #CursorLeft
       
  5108     or:[key == #CursorUp]]]) ifTrue:[
       
  5109         self cursorKeyPress:key shifted:shiftPressed.
       
  5110         ^ self.
       
  5111     ].
       
  5112 
       
  5113     (key == #NonInsertingReturn) ifTrue:[
       
  5114         self unselect. self cursorReturn.
       
  5115         ^ self
       
  5116     ].
       
  5117 
       
  5118     (key == #Return) ifTrue:[
       
  5119         shiftPressed ifTrue:[
       
  5120             self unselect. self cursorReturn.
       
  5121             ^ self
       
  5122         ].
       
  5123 
       
  5124         self isReadOnly ifTrue:[
       
  5125             self unselect; makeCursorVisible.
       
  5126             self cursorReturn
       
  5127         ] ifFalse:[
       
  5128             self isInInsertMode ifFalse:[
       
  5129                 self cursorReturn.
       
  5130                 autoIndent == true ifTrue:[
       
  5131                     i := self leftIndentForLine:(cursorLine + 1).
       
  5132                     (self listAt:cursorLine) isEmptyOrNil ifTrue:[
       
  5133                         self cursorCol:(i+1 max:1)
       
  5134                     ]
       
  5135                 ]
       
  5136             ] ifTrue:[
       
  5137                 |left right oldIndent|
       
  5138 
       
  5139                 "/ old version just unselected ...
       
  5140                 "/ self unselect; makeCursorVisible.
       
  5141 
       
  5142                 "/ new version deletes ...
       
  5143                 typeOfSelection == #paste ifTrue:[
       
  5144                     self unselect; makeCursorVisible.
       
  5145                 ] ifFalse:[
       
  5146                     self copyAndDeleteSelection.
       
  5147                 ].
       
  5148                 left := (self listAt:cursorLine to:cursorCol-1) ? ''.
       
  5149                 right := (self listAt:cursorLine from:cursorCol) ? ''.
       
  5150                 self insertCharAtCursor:(Character cr).
       
  5151                 autoIndent == true ifTrue:[
       
  5152                     (right isEmpty and:[cursorCol ~~ 1]) ifTrue:[
       
  5153                         "/ nothing to do.
       
  5154                     ] ifFalse:[
       
  5155                         ((self listAt:cursorLine) isEmptyOrNil 
       
  5156                         or:[ cursorCol == 1 ]) ifTrue:[
       
  5157                             i := (self leftIndentForLine:cursorLine).
       
  5158                             left := left withoutSeparators.
       
  5159                             right := right withoutSeparators.
       
  5160                             (left endsWith:'[') ifTrue:[
       
  5161 "/                                i := i + 4.
       
  5162                             ] ifFalse:[
       
  5163                                 (false "(left endsWith:']')" or:[(right startsWith:']')]) ifTrue:[
       
  5164                                     i := i - 4.
       
  5165                                 ].
       
  5166                             ].
       
  5167                             oldIndent := self leftIndentOfLine:cursorLine.
       
  5168                             self indentFromLine:cursorLine toLine:cursorLine by:(i-oldIndent).
       
  5169                             self st80EditMode ifTrue:[
       
  5170                                 (self listAt:cursorLine) size < i ifTrue:[
       
  5171                                     self insertStringAtCursor:(String new:((i-oldIndent) max:0)).
       
  5172                                 ].
       
  5173                             ].
       
  5174                             self cursorCol:(i+1 max:1)
       
  5175                         ].
       
  5176                     ]
       
  5177                 ].
       
  5178             ].
       
  5179         ].
       
  5180         ^ self
       
  5181     ].
       
  5182 
       
  5183     (key == #NonInsertingTab) ifTrue:[
       
  5184         self unselect. self cursorTab.
       
  5185         ^ self
       
  5186     ].
       
  5187     ((key == #BackTab) or:[(key == #Tab)]) ifTrue:[
       
  5188         self tabMeansNextField ifTrue:[^ super keyPress:key x:x y:y].
       
  5189 
       
  5190         self hasSelection ifTrue:[
       
  5191             selectStyle == #line ifTrue:[
       
  5192                 ((key == #Tab) and:[shiftPressed not]) ifTrue:[
       
  5193                     macroName := #IndentBy4.
       
  5194                 ] ifFalse:[
       
  5195                     macroName := #UndentBy4.
       
  5196                 ].
       
  5197                 macroName notNil ifTrue:[
       
  5198                     self executekeyboardMacroNamed:macroName.
       
  5199                 ].
       
  5200             ]
       
  5201         ].
       
  5202 
       
  5203         self unselect.
       
  5204         (key == #Tab) ifTrue:[
       
  5205             (shiftPressed or:[self isInInsertMode not]) ifTrue:[
       
  5206                 self cursorTab.
       
  5207                 ^ self
       
  5208             ].
       
  5209             self insertTabAtCursor.
       
  5210             ^ self
       
  5211         ].
       
  5212         self cursorBacktab.
       
  5213         ^ self
       
  5214     ].
       
  5215 
       
  5216     "/ key == #DeleteSpaces ifTrue:[
       
  5217     (key == #Delete) ifTrue:[
       
  5218         shiftPressed ifTrue:[
       
  5219             [(cursorCol <= (self listAt:cursorLine) size)
       
  5220              and:[self characterUnderCursor isSeparator]] whileTrue:[
       
  5221              self makeCursorVisible.
       
  5222                 self deleteCharAtCursor.
       
  5223             ].
       
  5224             ^ self
       
  5225         ]
       
  5226     ].
       
  5227 
       
  5228     (key == #Delete
       
  5229      or:[key == #BasicDelete]) ifTrue:[
       
  5230         selectionStartLine notNil ifTrue:[  
       
  5231 "/          Again function is not supporting Delete action (on purpose, to avoid replacing the next search string)
       
  5232 "/          To remove text repetetively, use Cut instead.
       
  5233 "/            self setLastStringToReplace: self selection asStringWithoutFinalCR.
       
  5234 "/            lastReplacementInfo lastReplacement: nil.
       
  5235             ((key == #BasicDelete)
       
  5236             or:[currentUserPrefs deleteSetsClipboardText not]) ifTrue:[
       
  5237                 self deleteSelection.
       
  5238             ] ifFalse:[
       
  5239                 self copyAndDeleteSelection.
       
  5240             ].
       
  5241             ^ self
       
  5242         ].
       
  5243         self makeCursorVisible.
       
  5244         self deleteCharAtCursor.
       
  5245         ^ self
       
  5246     ].
       
  5247 
       
  5248     (key == #BeginOfText) ifTrue:[     "i.e. HOME"
       
  5249         self unselect.
       
  5250         cursorVisibleLine == 1 ifTrue:[
       
  5251             self cursorHome.
       
  5252         ] ifFalse:[
       
  5253             self cursorToFirstVisibleLine
       
  5254         ].
       
  5255         ^ self
       
  5256     ].
       
  5257     (key == #EndOfText) ifTrue:[       "i.e. END"
       
  5258         self unselect.
       
  5259         cursorVisibleLine == nFullLinesShown ifTrue:[
       
  5260             self cursorToBottom.
       
  5261         ] ifFalse:[
       
  5262             self cursorToLastVisibleLine
       
  5263         ].
       
  5264         ^ self
       
  5265     ].
       
  5266     ((key == #Escape)
       
  5267     or:[key == #SelectLineFromBeginning]) ifTrue:[
       
  5268         self makeCursorVisible.
       
  5269         self unselect. self selectCursorLineFromBeginning.
       
  5270         ^ self
       
  5271     ].
       
  5272     (key == #SelectLine) ifTrue:[
       
  5273         self makeCursorVisible.
       
  5274         self unselect. self selectCursorLine.
       
  5275         ^ self
       
  5276     ].
       
  5277     (key == #ExpandSelectionByLine) ifTrue:[
       
  5278         "/ self makeCursorVisible.
       
  5279         self selectExpandCursorLine.
       
  5280         ^ self
       
  5281     ].
       
  5282     (key == #DeleteLine) ifTrue:[
       
  5283         self makeCursorVisible.
       
  5284         self unselect. self deleteCursorLine.
       
  5285         ^ self
       
  5286     ].
       
  5287     (key == #InsertLine) ifTrue:[
       
  5288         self makeCursorVisible.
       
  5289         self unselect. self insertLine:nil before:cursorLine.
       
  5290         ^ self
       
  5291     ].
       
  5292 
       
  5293     super keyPress:key x:x y:y
       
  5294 
       
  5295     "Modified: / 06-02-1998 / 11:59:59 / stefan"
       
  5296     "Modified: / 14-07-2011 / 12:08:28 / cg"
       
  5297     "Modified: / 26-09-2013 / 17:52:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
  5298 !
       
  5299 
       
  5300 executeKeyboardMacro:cmdMacro
       
  5301     Error handle:[:ex |
       
  5302         self warn:'Error in keyboard macro: ' , ex description.
       
  5303         ex return.
       
  5304     ] do:[
       
  5305         AbortOperationRequest handle:[:ex |
       
  5306             self warn:'Keyboard macro aborted'.
       
  5307             ex return.
       
  5308         ] do:[
       
  5309             Parser
       
  5310                 evaluate:cmdMacro asString
       
  5311                 receiver:self
       
  5312                 notifying:nil
       
  5313                 compile:false.
       
  5314         ].
       
  5315     ].
       
  5316 !
       
  5317 
       
  5318 handleNonCommandKey:keyArg
       
  5319     |selStartLineBefore selStartColBefore selEndLineBefore selEndColBefore key|
       
  5320 
       
  5321     self isReadOnly ifTrue:[
       
  5322         self flashReadOnly.
       
  5323         ^ self.
       
  5324     ].
       
  5325 
       
  5326     key := keyArg.
       
  5327 
       
  5328     typeOfSelection == #paste ifTrue:[
       
  5329         "pasted selection will NOT be replaced by keystroke"
       
  5330         self unselect
       
  5331     ].
       
  5332 
       
  5333     selStartLineBefore := selectionStartLine.
       
  5334     selStartColBefore := self selectionStartCol.
       
  5335     selEndLineBefore := selectionEndLine.
       
  5336     selEndColBefore := self selectionEndCol.
       
  5337 
       
  5338     (gc characterEncoding ? #'iso10646-1') ~~ #'iso10646-1' ifTrue:[
       
  5339         key isCharacter ifTrue:[
       
  5340             key := CharacterEncoder encode:key from:#'iso10646-1' into:gc characterEncoding.
       
  5341         ] ifFalse:[
       
  5342             key := CharacterEncoder encodeString:key from:#'iso10646-1' into:gc characterEncoding.
       
  5343         ].
       
  5344     ].
       
  5345 
       
  5346     "replace selection by what is typed in -
       
  5347      if word was selected with a space, keep it.
       
  5348      if there was no selection, the key's character is inserted"
       
  5349 
       
  5350     editMode value isInsertAndSelectMode ifTrue:[
       
  5351         selectionStartLine := selectionStartCol := selectionEndLine := selectionEndCol := nil.
       
  5352     ].
       
  5353 
       
  5354     (selectStyle == #wordLeft) ifTrue:[
       
  5355         self replaceSelectionBy:(' ' , key asString)
       
  5356     ] ifFalse:[
       
  5357         (selectStyle == #wordRight) ifTrue:[
       
  5358             self replaceSelectionBy:(key asString , ' ').
       
  5359             self cursorLeft
       
  5360         ] ifFalse:[
       
  5361             self replaceSelectionBy:key
       
  5362         ]
       
  5363     ].
       
  5364     selectStyle := nil.
       
  5365 
       
  5366     editMode value isInsertAndSelectMode ifTrue:[
       
  5367         selectionStartLine := selStartLineBefore.
       
  5368         selectionStartCol := selStartColBefore.
       
  5369         selectionEndLine := selEndLineBefore.
       
  5370         selectionEndCol := selEndColBefore.
       
  5371     ].
       
  5372 
       
  5373     showMatchingParenthesis ifTrue:[
       
  5374         "emacs style parenthesis shower"
       
  5375       (ExecutingMacroQuery query ? false) ifFalse:[
       
  5376         "claus: only do it for closing parenthesis -
       
  5377                 otherwise its too anoying.
       
  5378         "
       
  5379 "
       
  5380         ('()[]{}' includes:key) ifTrue:[
       
  5381 "
       
  5382         (')]}' includes:key) ifTrue:[
       
  5383         self
       
  5384             searchForMatchingParenthesisFromLine:cursorLine col:(cursorCol - 1)
       
  5385             ifFound:[:line :col |
       
  5386                          |savLine savCol sensor|
       
  5387 
       
  5388                          self withCursor:Cursor eye do:[
       
  5389                              savLine := cursorLine.
       
  5390                              savCol := cursorCol.
       
  5391                              self cursorLine:line col:col.
       
  5392                              self flush.
       
  5393 
       
  5394                              "/ want to wait 200ms, but not if another keyPress
       
  5395                              "/ arrives in the meantime ...
       
  5396 
       
  5397                              sensor := self sensor.
       
  5398                              5 timesRepeat:[
       
  5399                                  (sensor hasKeyPressEventFor:self) ifFalse:[
       
  5400                                      Processor activeProcess millisecondDelay:40.
       
  5401                                  ]
       
  5402                              ].
       
  5403                              self cursorLine:savLine col:savCol
       
  5404                          ]
       
  5405                     ]
       
  5406             ifNotFound:[self showNotFound]
       
  5407             onError:[self beep]
       
  5408         ].
       
  5409       ]
       
  5410     ].
       
  5411 
       
  5412 "/    true "autoExpandWhileTyping" ifTrue:[
       
  5413 "/        self wordAtLine:cursorLine col:cursorCol-1 do:[
       
  5414 "/            :beginLine :beginCol :endLine :endCol :style |
       
  5415 "/
       
  5416 "/            self selectFromLine:beginLine col:beginCol toLine:endLine col:endCol.
       
  5417 "/            self selection.
       
  5418 "/            typeOfSelection := #paste.
       
  5419 "/        ].
       
  5420 "/    ].
       
  5421     editMode value isInsertAndSelectMode ifTrue:[
       
  5422         selectionStartLine isNil ifTrue:[
       
  5423             self selectFromLine:cursorLine col:cursorCol-1 toLine:cursorLine col:cursorCol-1.
       
  5424         ] ifFalse:[
       
  5425             self selectFromLine:selectionStartLine col:selectionStartCol toLine:cursorLine col:cursorCol-1.
       
  5426         ].
       
  5427     ].
       
  5428     completionSupport notNil ifTrue:[ completionSupport postKeyPress:keyArg ].
       
  5429 
       
  5430     "Modified (comment): / 25-01-2012 / 00:30:11 / cg"
       
  5431 !
       
  5432 
       
  5433 keyPress:key x:x y:y
       
  5434     "handle keyboard input"
       
  5435 
       
  5436     |wasOn|
       
  5437 
       
  5438     wasOn := cursorShown.
       
  5439 
       
  5440     NoModificationError handle:[:ex |
       
  5441         self flashReadOnly.
       
  5442         (cursorShown not and:[wasOn]) ifTrue:[
       
  5443             self makeCursorVisibleAndShowCursor:wasOn.
       
  5444         ].
       
  5445     ] do:[
       
  5446         self undoableDo:[
       
  5447             self doKeyPress:key x:x y:y
       
  5448         ].
       
  5449     ].
       
  5450     self repairDamage
       
  5451 
       
  5452     "Modified: / 18-04-2011 / 21:35:27 / cg"
       
  5453 !
       
  5454 
       
  5455 mapped
       
  5456     "view was made visible"
       
  5457 
       
  5458     super mapped.
       
  5459     self updateCursorVisibleLine.
       
  5460 !
       
  5461 
       
  5462 requestAutoAccept
       
  5463     "this is invoked when a dialog closes via accept or cancel.
       
  5464      This forces my value to be accepted into my model"
       
  5465 
       
  5466     acceptEnabled == false ifTrue:[
       
  5467         "/ nope -
       
  5468         ^ false
       
  5469     ].
       
  5470     self accept.
       
  5471     ^ true.
       
  5472 !
       
  5473 
       
  5474 sizeChanged:how
       
  5475     "make certain, cursor is visible after the sizechange"
       
  5476 
       
  5477     |cv|
       
  5478 
       
  5479     cv := cursorVisibleLine.
       
  5480     super sizeChanged:how.
       
  5481     cv notNil ifTrue:[
       
  5482         self makeLineVisible:cursorLine
       
  5483     ]
       
  5484 !
       
  5485 
       
  5486 unmapped
       
  5487     super unmapped.
       
  5488 
       
  5489     completionSupport notNil ifTrue:[
       
  5490         completionSupport release.
       
  5491     ].
       
  5492 ! !
       
  5493 
       
  5494 !EditTextView methodsFor:'focus handling'!
       
  5495 
       
  5496 focusOut
       
  5497     super focusOut.
       
  5498 
       
  5499     completionSupport notNil ifTrue:[
       
  5500         completionSupport release.
       
  5501     ].
       
  5502 !
       
  5503 
       
  5504 hasKeyboardFocus:aBoolean
       
  5505     "sent by the windowGroup, a delegate or myself to make me show a block cursor
       
  5506      (otherwise, I would not know about this)"
       
  5507 
       
  5508     hasKeyboardFocus := aBoolean.
       
  5509 
       
  5510     (cursorShown
       
  5511     and:[self enabled
       
  5512     and:[self isReadOnly not]]) ifTrue:[
       
  5513         self drawCursor
       
  5514     ].
       
  5515 
       
  5516     hasKeyboardFocus ifFalse:[
       
  5517         completionSupport notNil ifTrue:[
       
  5518             "/ this is a hack for Windows:
       
  5519             "/ on windows, an activate:false event is first sent to my textView,
       
  5520             "/ then an activate is sent to the completion popup.
       
  5521             "/ this is done BEFORE the buttonPress event is delivered.
       
  5522             "/ therefore, allow for the activate of the completionMenu and it's button event to be processed.
       
  5523             "/ before forcing it to be closed...
       
  5524             Processor addTimedBlock:[completionSupport "release" editViewLostFocus] afterMilliseconds:200.
       
  5525         ].
       
  5526     ].
       
  5527 
       
  5528     "Modified (format): / 06-11-2013 / 15:37:31 / cg"
       
  5529 !
       
  5530 
       
  5531 showFocus:explicit
       
  5532     "in addition to however my superclass thinks how a focusView is to be
       
  5533      displayed, show the cursor when I got the focus"
       
  5534 
       
  5535     self showCursor.
       
  5536     self hasKeyboardFocus:true.
       
  5537     super showFocus:explicit
       
  5538 
       
  5539     "Modified: 11.12.1996 / 16:56:54 / cg"
       
  5540 !
       
  5541 
       
  5542 showNoFocus:explicit
       
  5543     "the view lost the keyboard focus 
       
  5544      (either explicit, via tabbing; or implicit, by pointer movement)
       
  5545       - change any display attributes as req'd."
       
  5546 
       
  5547     super showNoFocus:explicit.
       
  5548     completionSupport notNil ifTrue:[
       
  5549         completionSupport release.
       
  5550     ].
       
  5551 !
       
  5552 
       
  5553 wantsFocusWithPointerEnter
       
  5554     "return true, if I want the focus when
       
  5555      the mouse pointer enters"
       
  5556 
       
  5557     (UserPreferences current focusFollowsMouse ~~ false
       
  5558      and:[(styleSheet at:#'editText.requestFocusOnPointerEnter' default:true)
       
  5559      and:[self enabled
       
  5560      and:[true "self isReadOnly not"]]]
       
  5561     ) ifTrue:[
       
  5562         ^ true
       
  5563     ].
       
  5564 
       
  5565     ^ false
       
  5566 ! !
       
  5567 
       
  5568 !EditTextView methodsFor:'formatting'!
       
  5569 
       
  5570 executekeyboardMacroNamed:macroName
       
  5571     "try to execute the keyboard macro; 
       
  5572      return true if that worked, false otherwise"
       
  5573 
       
  5574     |cmdMacro|
       
  5575 
       
  5576     cmdMacro := UserPreferences current functionKeySequences at:macroName ifAbsent:[^ false].
       
  5577     self
       
  5578         undoableDo:[ self executeKeyboardMacro:cmdMacro ]
       
  5579         info: macroName.
       
  5580     ^ true
       
  5581 
       
  5582     "
       
  5583       EditTextView open
       
  5584                 contents:'bla';
       
  5585                 selectAll;
       
  5586                 executekeyboardMacroNamed:#IndentBy4.
       
  5587       EditTextView open
       
  5588                 contents:'bla';
       
  5589                 selectAll;
       
  5590                 executekeyboardMacroNamed:#blabla.
       
  5591     "
       
  5592 
       
  5593     "Modified: / 14-02-2012 / 11:17:27 / cg"
       
  5594 !
       
  5595 
       
  5596 indent
       
  5597     "indent a line-range - this is done by searching for the
       
  5598      last non-empty line before the selection, and changing the indent
       
  5599      of the selected line-range based on that line's indent."
       
  5600 
       
  5601     |start end|
       
  5602 
       
  5603     selectionStartLine isNil ifTrue:[^ self].
       
  5604 
       
  5605     start := selectionStartLine.
       
  5606     end := selectionEndLine.
       
  5607     (selectionEndCol == 0) ifTrue:[
       
  5608         end := end - 1
       
  5609     ].
       
  5610     self unselect.
       
  5611     self
       
  5612         undoableDo:[self indentFromLine:start toLine:end]
       
  5613         info:'Indent'
       
  5614 !
       
  5615 
       
  5616 indentBy4
       
  5617     self executekeyboardMacroNamed:#IndentBy4.
       
  5618 
       
  5619     "Modified: / 06-04-2011 / 18:52:40 / cg"
       
  5620 !
       
  5621 
       
  5622 indentFromLine:start toLine:end
       
  5623     "indent a line-range - this is done by searching for the
       
  5624      last non-empty line before start, and change the indent
       
  5625      of the selected line-range based on that line's indent."
       
  5626 
       
  5627     |leftStart delta|
       
  5628 
       
  5629     leftStart := self leftIndentForLine:start.
       
  5630     (leftStart == 0) ifTrue:[^ self].
       
  5631 
       
  5632     delta := leftStart - (self leftIndentOfLine:start).
       
  5633     (delta == 0) ifTrue:[^ self].
       
  5634     self indentFromLine:start toLine:end by:delta
       
  5635 !
       
  5636 
       
  5637 indentFromLine:start toLine:end by:delta
       
  5638     "indent a line-range - this is done by searching for the
       
  5639      last non-empty line before start, and change the indent
       
  5640      of the selected line-range based on that line's indent."
       
  5641 
       
  5642     |d line spaces anyChange|
       
  5643 
       
  5644     (delta == 0) ifTrue:[^ self].
       
  5645     (delta > 0) ifTrue:[
       
  5646         spaces := String new:delta
       
  5647     ].
       
  5648 
       
  5649     anyChange := false.
       
  5650     start to:end do:[:lineNr |
       
  5651         line := self listAt:lineNr.
       
  5652         line notNil ifTrue:[
       
  5653             line isBlank ifTrue:[
       
  5654                 self basicListAt:lineNr put:nil
       
  5655             ] ifFalse:[
       
  5656                 (delta > 0) ifTrue:[
       
  5657                     line := spaces , line.
       
  5658                     widthOfWidestLine notNil ifTrue:[
       
  5659                         widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:line).
       
  5660                     ]
       
  5661                 ] ifFalse:[
       
  5662                     "check if deletion is ok"
       
  5663                     d := delta negated + 1.
       
  5664 
       
  5665                     line size > d ifTrue:[
       
  5666                         (line copyTo:(d - 1)) withoutSeparators isEmpty ifTrue:[
       
  5667                             line := line copyFrom:d
       
  5668                         ]
       
  5669                     ].
       
  5670                     widthOfWidestLine := nil
       
  5671                 ].
       
  5672                 self replaceLine:lineNr with:line.
       
  5673                 anyChange := true.
       
  5674             ]
       
  5675         ]
       
  5676     ].
       
  5677 
       
  5678     anyChange ifTrue:[ self textChanged ].
       
  5679 
       
  5680     "/ self redrawFromLine:start to:end
       
  5681 
       
  5682     "Modified: 5.3.1996 / 14:59:18 / cg"
       
  5683 !
       
  5684 
       
  5685 leftIndentForLine:lineNr
       
  5686     "find an appropriate indent for a line.
       
  5687      this is done by searching for the last non-empty line before it
       
  5688      and returning its indent.
       
  5689      cg: changed: only look for the single previous line."
       
  5690 
       
  5691     "SHOULD GO TO ListView"
       
  5692 
       
  5693     |line lnr indent|
       
  5694 
       
  5695     lnr := lineNr.
       
  5696 
       
  5697     "/ [lnr ~~ 1] whileTrue:[
       
  5698     (lnr ~~ 1) ifTrue:[
       
  5699         lnr  := lnr - 1.
       
  5700         line := self listAt:lnr.
       
  5701 
       
  5702         line notNil ifTrue:[
       
  5703             indent := line indexOfNonSeparatorStartingAt:1.
       
  5704             indent ~~ 0 ifTrue:[
       
  5705                 (line endsWith:$[) ifTrue:[
       
  5706                     ^ indent + 4 - 1
       
  5707                 ].
       
  5708                 ^ indent - 1
       
  5709             ]
       
  5710         ]
       
  5711     ].
       
  5712     ^ 0
       
  5713 
       
  5714     "Created: 5.3.1996 / 14:58:53 / cg"
       
  5715 !
       
  5716 
       
  5717 undentBy4
       
  5718     self executekeyboardMacroNamed:#UndentBy4.
       
  5719 
       
  5720     "Modified: / 06-04-2011 / 18:52:49 / cg"
       
  5721 ! !
       
  5722 
       
  5723 !EditTextView methodsFor:'initialization'!
       
  5724 
       
  5725 fetchDeviceResources
       
  5726     "fetch device colors, to avoid reallocation at redraw time"
       
  5727 
       
  5728     super fetchDeviceResources.
       
  5729 
       
  5730     cursorFgColor notNil ifTrue:[cursorFgColor := cursorFgColor onDevice:self graphicsDevice].
       
  5731     cursorBgColor notNil ifTrue:[cursorBgColor := cursorBgColor onDevice:self graphicsDevice].
       
  5732     cursorNoFocusFgColor notNil ifTrue:[cursorNoFocusFgColor := cursorNoFocusFgColor onDevice:self graphicsDevice].
       
  5733 
       
  5734     "Created: 14.1.1997 / 00:15:24 / cg"
       
  5735     "Modified: 18.2.1997 / 15:02:46 / cg"
       
  5736 !
       
  5737 
       
  5738 initEvents
       
  5739     "enable enter/leave events in addition"
       
  5740 
       
  5741     super initEvents.
       
  5742     self enableEnterLeaveEvents
       
  5743 !
       
  5744 
       
  5745 initStyle
       
  5746     "initialize style specific stuff"
       
  5747 
       
  5748     super initStyle.
       
  5749     "/ lineSpacing := 2.       "/ for underwave - also looks better
       
  5750     lockUpdates := false.
       
  5751 
       
  5752     cursorFgColor := DefaultCursorForegroundColor.
       
  5753     cursorFgColor isNil ifTrue:[cursorFgColor := bgColor].
       
  5754     cursorBgColor := DefaultCursorBackgroundColor.
       
  5755     cursorBgColor isNil ifTrue:[cursorBgColor := fgColor].
       
  5756     cursorType isNil ifTrue:[cursorType := DefaultCursorType].
       
  5757     cursorTypeNoFocus isNil ifTrue:[
       
  5758         cursorTypeNoFocus := cursorType.
       
  5759         DefaultCursorTypeNoFocus notNil ifTrue:[
       
  5760             cursorTypeNoFocus := DefaultCursorTypeNoFocus.
       
  5761         ]
       
  5762     ].
       
  5763     cursorNoFocusFgColor := DefaultCursorNoFocusForegroundColor.
       
  5764     cursorNoFocusFgColor isNil ifTrue:[
       
  5765         cursorType ~~ #block ifTrue:[
       
  5766             cursorNoFocusFgColor := cursorBgColor
       
  5767         ] ifFalse:[
       
  5768             cursorNoFocusFgColor := cursorFgColor
       
  5769         ]
       
  5770     ].
       
  5771 
       
  5772     "Modified: / 15.12.1999 / 22:27:45 / cg"
       
  5773 !
       
  5774 
       
  5775 initialize
       
  5776     "initialize a new EditTextView;
       
  5777      setup some instance variables"
       
  5778 
       
  5779     super initialize.
       
  5780 
       
  5781     self level:-1.
       
  5782     readOnly := false.
       
  5783     fixedSize := false.
       
  5784     exceptionBlock := [:errorText | ].
       
  5785     cursorShown := prevCursorState := true.
       
  5786     cursorLine := 1.
       
  5787     cursorVisibleLine := 1.
       
  5788     cursorCol := 1.
       
  5789     cursorLineHolder := 1 asValue.
       
  5790     cursorColHolder := 1 asValue.
       
  5791     modifiedChannel := ValueHolder with:false.
       
  5792     acceptChannel := ValueHolder with:false.
       
  5793     acceptChannel addDependent:self.
       
  5794     showMatchingParenthesis := false.
       
  5795     hasKeyboardFocus := false.
       
  5796     tabMeansNextField := false.
       
  5797     autoIndent := false.
       
  5798     editMode := EditMode insertMode asValue.
       
  5799     learnMode := false asValue.
       
  5800     trimBlankLines := self st80EditMode not.
       
  5801     cursorMovementWhenUpdating := #beginOfText.
       
  5802     lastReplacementInfo := LastReplacementInfo new.
       
  5803 
       
  5804     "/ enable drop by default
       
  5805     self allowDrop:true.        "/ readOnly tested in #canDrop:
       
  5806 
       
  5807     undoSupport := UndoSupport for:self.
       
  5808     codeAspectHolder := nil asValue.
       
  5809 
       
  5810     "Modified: / 27-09-2013 / 09:41:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
  5811 !
       
  5812 
       
  5813 initializeCompletionSupport
       
  5814     |supportClass|
       
  5815 
       
  5816     completionSupport isNil ifTrue:[
       
  5817         (supportClass := self completionSupportClass) notNil ifTrue:[
       
  5818             completionSupport := supportClass for:self.            
       
  5819         ].
       
  5820     ].
       
  5821 
       
  5822     "Created: / 26-09-2013 / 17:51:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
  5823 !
       
  5824 
       
  5825 release
       
  5826     completionSupport notNil ifTrue:[
       
  5827         completionSupport release
       
  5828     ].
       
  5829     super release
       
  5830 ! !
       
  5831 
       
  5832 !EditTextView methodsFor:'macros'!
       
  5833 
       
  5834 executeLearnedKeyboardMacro
       
  5835     "replay the characters as learned previously"
       
  5836 
       
  5837     (self learnMode not and:[learnedMacro size > 0]) ifTrue:[
       
  5838         ExecutingMacroQuery 
       
  5839             answer:true
       
  5840             do:[
       
  5841                 learnedMacro do:[:event |
       
  5842                             WindowGroup lastEventQuerySignal answer:event
       
  5843                             do:[
       
  5844                                 self
       
  5845                                     dispatchEvent:event
       
  5846                                     withFocusOn:nil
       
  5847                                     delegate:false
       
  5848                             ]
       
  5849                 ]
       
  5850             ].
       
  5851     ] ifFalse:[
       
  5852         self flash.
       
  5853     ].
       
  5854 !
       
  5855 
       
  5856 learnMode
       
  5857     "true if currently learning"
       
  5858 
       
  5859     ^ (learnMode value ? false).
       
  5860 !
       
  5861 
       
  5862 learnMode:aBoolean
       
  5863     "toggle the learn-mode"
       
  5864 
       
  5865     |fg bg|
       
  5866 
       
  5867     self learnModeHolder value:aBoolean.
       
  5868 
       
  5869     aBoolean ifTrue:[
       
  5870         learnedMacro := OrderedCollection new.
       
  5871         fg := Color white.
       
  5872         bg := Color black.
       
  5873     ] ifFalse:[
       
  5874         cursorFgColor := fg := (DefaultCursorForegroundColor ? bgColor).
       
  5875         cursorBgColor := bg := (DefaultCursorBackgroundColor ? fgColor).
       
  5876     ].
       
  5877     self cursorForegroundColor:fg backgroundColor:bg.
       
  5878 !
       
  5879 
       
  5880 learnModeHolder
       
  5881     "a holder returning true, if in learn mode"
       
  5882 
       
  5883     learnMode isNil ifTrue:[
       
  5884         learnMode := false asValue
       
  5885     ].
       
  5886     ^ learnMode
       
  5887 !
       
  5888 
       
  5889 rememberLearnedMacroAs: nameString
       
  5890     Macros isNil ifTrue:[
       
  5891         Macros := Dictionary new.
       
  5892     ].
       
  5893     Macros at:nameString put:learnedMacro
       
  5894 !
       
  5895 
       
  5896 toggleLearnMode
       
  5897     "toggle the learn-mode"
       
  5898 
       
  5899     self learnMode:(self learnMode not).
       
  5900 ! !
       
  5901 
       
  5902 !EditTextView methodsFor:'menu & menu actions'!
       
  5903 
       
  5904 babelFishTranslate:fromToModeString
       
  5905     "translate the selected text and paste it after the selection"
       
  5906 
       
  5907     |original translated|
       
  5908 
       
  5909     original := self selectionAsString.
       
  5910     original size == 0 ifTrue:[^ self].
       
  5911 
       
  5912     self withWaitCursorDo:[
       
  5913         (HostNameLookupError , SOAP::SoapImplError) handle:[:ex |
       
  5914             Dialog warn:('Translation failed - WEB Service error:\\%1.' bindWith:ex description allBold) withCRs
       
  5915         ] do:[
       
  5916             translated := SOAP::BabelFishClient new translate:original mode:fromToModeString.
       
  5917         ]
       
  5918     ].
       
  5919 
       
  5920     "/ v pasteOrReplace:translated
       
  5921     self cursorLine:(self selectionEndLine) col:(self selectionEndCol + 1).
       
  5922     self unselect.
       
  5923     self 
       
  5924         undoablePaste:translated 
       
  5925         info:'Translate'
       
  5926 
       
  5927     "Modified: / 28-07-2007 / 13:27:21 / cg"
       
  5928 !
       
  5929 
       
  5930 compareWithClipboard
       
  5931     "compare the selection against the clipboard contents"
       
  5932 
       
  5933     |t1 t2|
       
  5934 
       
  5935     t2 := self getClipboardText.
       
  5936     t2 isEmptyOrNil ifTrue:[
       
  5937         Dialog information:'Clipboard is empty.'.
       
  5938         ^ self.
       
  5939     ].
       
  5940 
       
  5941     self hasSelection ifTrue:[
       
  5942         t1 := self selectionAsString.
       
  5943     ] ifFalse:[
       
  5944         t1 := self contents asString
       
  5945     ].
       
  5946     t1 := t1 string.
       
  5947 
       
  5948     t1 = t2 ifTrue:[
       
  5949         Dialog information:'Strings are equal.'.
       
  5950         ^ self.
       
  5951     ].
       
  5952     DiffTextView
       
  5953         openOn:t1 label:'Editor'
       
  5954         and:t2 label:'Clipboard'
       
  5955 !
       
  5956 
       
  5957 cut
       
  5958     "cut selection into copybuffer"
       
  5959 
       
  5960     self deleteCopyToClipboard:true
       
  5961 !
       
  5962 
       
  5963 defaultForGotoLine
       
  5964     "return a default value to show in the gotoLine box"
       
  5965 
       
  5966     cursorLine notNil ifTrue:[
       
  5967         ^ cursorLine
       
  5968     ].
       
  5969     ^ super defaultForGotoLine
       
  5970 !
       
  5971 
       
  5972 deleteCopyToClipboard:toClipboard
       
  5973     "cut selection into copybuffer"
       
  5974 
       
  5975     |line col history sel |
       
  5976 
       
  5977     (self checkModificationsAllowed) ifFalse:[
       
  5978         self flashReadOnly.
       
  5979         ^ self
       
  5980     ].
       
  5981 
       
  5982     sel := self selection.
       
  5983     sel notNil ifTrue:[
       
  5984         self setLastStringToReplace: sel.
       
  5985 
       
  5986         line := selectionStartLine.
       
  5987         col := selectionStartCol.
       
  5988 
       
  5989         toClipboard ifTrue:[
       
  5990             "
       
  5991              remember in CopyBuffer
       
  5992             "
       
  5993             self setClipboardText:sel. "/ lastString.
       
  5994         ].
       
  5995 
       
  5996         "
       
  5997          append to DeleteHistory (if there is one)
       
  5998         "
       
  5999         history := Smalltalk at:#DeleteHistory.
       
  6000         history notNil ifTrue:[
       
  6001             history addAll:(sel asStringCollection).
       
  6002             history size > 1000 ifTrue:[
       
  6003                 history := history copyFrom:(history size - 1000)
       
  6004             ].
       
  6005         ].
       
  6006 
       
  6007         "
       
  6008          now, delete it
       
  6009         "
       
  6010         self 
       
  6011             undoableDo:[self deleteSelection] 
       
  6012             info:'Delete'.
       
  6013         lastReplacementInfo lastReplacement: nil
       
  6014     ] ifFalse:[
       
  6015         "
       
  6016          a cut without selection will search&cut again
       
  6017         "
       
  6018         self undoableDo:[
       
  6019             self again
       
  6020         ]
       
  6021     ]
       
  6022 
       
  6023     "Modified: / 5.4.1998 / 16:51:53 / cg"
       
  6024 !
       
  6025 
       
  6026 editMenu
       
  6027     "return the views middleButtonMenu"
       
  6028 
       
  6029     <resource: #keyboard (#Again #AgainForAll #Copy #Cut #Paste #Accept 
       
  6030                           #Find #GotoLine #SaveAs #Print
       
  6031                           #PasteFromHistory #Join #Wrap #Undo #Redo 
       
  6032                           #ToggleAutoIndent #ToggleInsertMode 
       
  6033                           #LearnKeyboardMacro #ExecuteKeyboardMacro )>
       
  6034     <resource: #programMenu>
       
  6035 
       
  6036     |items m sub translateItems sortItems miscItems toolItems subSub toolSub
       
  6037      transSub sortSub what undoIdx redoIdx sensor main mainItems|
       
  6038 
       
  6039     items := #(
       
  6040                     ('Redo'             redo           Redo        )
       
  6041                     ('Again (for All)'  multipleAgain  AgainForAll )
       
  6042                     ('-'                                        )
       
  6043                     ('Search...'        search         Find     )
       
  6044                     ('Goto Line...'     gotoLine       GotoLine )
       
  6045                     ('-'                                        )
       
  6046                     ('Tools'            tools                   )
       
  6047                     ('Insert Unicode...' insertUnicode )
       
  6048             ).
       
  6049     CharacterSetView notNil ifTrue:[
       
  6050         items := items ,
       
  6051                     #(
       
  6052                         ('Special Characters...'    specialCharacters  OpenSpecialCharacterWindow )
       
  6053                     ).
       
  6054     ].
       
  6055     items := items , #(
       
  6056                     ('-'                                        )
       
  6057                     ('Save As...'       save           SaveAs   )
       
  6058                     ('Print'            doPrint        Print    )
       
  6059                     ('='                                        )
       
  6060                     ('Misc'             misc           ShiftCtrl) ).
       
  6061 
       
  6062     miscItems := #(
       
  6063                     ('AutoIndent \c'    autoIndent:                  ToggleAutoIndent )
       
  6064                     ('InsertMode \c'    insertMode:                  ToggleInsertMode )
       
  6065                     ('-'                                        )
       
  6066                     ('Paste Previous...'   pasteOrReplaceFromHistory PasteFromHistory )
       
  6067                     ('Join Lines'       joinLines                    Join )
       
  6068                     ('Wrap Lines...'    wrapLines                    Wrap )
       
  6069                     ('-'                                        )
       
  6070                     ('Learn Macro'      learnMode:                   LearnKeyboardMacro)
       
  6071                     ('Execute Macro'    executeLearnedKeyboardMacro  ExecuteKeyboardMacro )
       
  6072                     ('-'                                        )
       
  6073                     ('Insert File...'           insertFile          )
       
  6074                     ('Insert URL Contents...'   insertURL           )
       
  6075                     ('Insert new UUID'      insertUUID          )
       
  6076                     ('Insert Date && Time'  insertDateAndTime   )
       
  6077                     ('-'                                        )
       
  6078                     ('Insert File as String Literal...' insertFileAsStringLiteral  )
       
  6079                     ('Paste as String Literal'          pasteAsStringLiteral       )
       
  6080                     ('-'                                        )
       
  6081                 ).
       
  6082 "/    CharacterSetView notNil ifTrue:[
       
  6083 "/        miscItems := miscItems ,
       
  6084 "/                    #(
       
  6085 "/                        ('Special Characters...'    specialCharacters  OpenSpecialCharacterWindow )
       
  6086 "/                    ).
       
  6087 "/    ].
       
  6088     miscItems := miscItems ,
       
  6089                 #(
       
  6090                     ('Font...'                  changeFont              )
       
  6091 "/                    ('Encoding...'      changeEncoding          )
       
  6092                 ).
       
  6093 
       
  6094     translateItems := #(
       
  6095                     ('English -> German'      (babelFishTranslate: 'en_de')   )
       
  6096                     ('English -> French'      (babelFishTranslate: 'en_fr')   )
       
  6097                     ('English -> Italian'     (babelFishTranslate: 'en_it')   )
       
  6098                     ('English -> Spanish'     (babelFishTranslate: 'en_es')   )
       
  6099                     ('English -> Portuguese'  (babelFishTranslate: 'en_pt')   )
       
  6100                     ('-'                                        )
       
  6101                     ('German -> English'      (babelFishTranslate: 'de_en')   )
       
  6102                     ('French -> English'      (babelFishTranslate: 'fr_en')   )
       
  6103                     ('Italian -> English'     (babelFishTranslate: 'it_en')   )
       
  6104                     ('Spanish -> English'     (babelFishTranslate: 'es_en')   )
       
  6105                     ('Portuguese -> English'  (babelFishTranslate: 'pt_en')   )
       
  6106               ).
       
  6107 
       
  6108     sortItems := #(
       
  6109                     ('Lines'                            (sortSelection:ignoreCase: #lines false)        )
       
  6110                     ('Lines by First Word'              (sortSelection:ignoreCase: #linesByFirstWord false)     )
       
  6111                     ('Lines by n''th Word'              (sortSelection:ignoreCase: #linesByNthWord false)       )
       
  6112                     ('Lines by n''th Number'            (sortSelection:ignoreCase: #linesByNthNumber false)     )
       
  6113                     ('Lines by n''th Hex Number'        (sortSelection:ignoreCase: #linesByNthHexNumber false)     )
       
  6114                     ('Words'                            (sortSelection:ignoreCase: #words false)        )
       
  6115                     ('-'                                                      )
       
  6116                     ('Lines (ignore case)'               (sortSelection:ignoreCase: #lines true)         )
       
  6117                     ('Lines by First Word (ignore case)' (sortSelection:ignoreCase: #linesByFirstWord true)      )
       
  6118                     ('Lines by n''th Word (ignore case)' (sortSelection:ignoreCase: #linesByNthWord true)        )
       
  6119                     ('Words (ignore case)'               (sortSelection:ignoreCase: #words true)         )
       
  6120                     ('-'                                                      )
       
  6121                     ('By Line Length'                    (sortSelection:ignoreCase: #linesByLength nil)         )
       
  6122                     ('Reverse'                           (sortSelection:ignoreCase: #reverse       nil)         )
       
  6123               ).
       
  6124 
       
  6125     toolItems := #(
       
  6126                     ('Indent'                      indent                     )
       
  6127                     ('Toggle Case'      convertSelectionToLowercaseOrUppercaseOrUppercaseFirst   ConvertSelectionToLowercaseOrUppercaseOrUppercaseFirst)
       
  6128                     ('Sort'                        sort                       )
       
  6129                     ('-'                                                      )
       
  6130                     ('Google Spell Check'          googleSpellingSuggestion   )
       
  6131                     ('Builtin Spell Check'         internalSpellingSuggestion   )
       
  6132                     ('Translate'                   babelFishTranslate         )
       
  6133                     ('Compare with Clipboard...'   compareWithClipboard       )
       
  6134               ).
       
  6135 
       
  6136     Smalltalk isStandAloneApp ifFalse:[
       
  6137         toolItems := toolItems , #(
       
  6138                         ('-'                                                      )
       
  6139                         ('Open FileBrowser on It'      openFileBrowserOnIt        )
       
  6140                         ('Open Workspace with It'      openWorkspaceWithIt        )
       
  6141                   ).
       
  6142     ].
       
  6143 
       
  6144     sub := PopUpMenu itemList:items resources:resources performer:model.
       
  6145     sub receiver:self.
       
  6146 
       
  6147     toolSub := PopUpMenu itemList:toolItems resources:resources performer:model.
       
  6148     toolSub receiver:self.
       
  6149     sub subMenuAt:#tools put:toolSub.
       
  6150 
       
  6151     transSub := PopUpMenu itemList:translateItems resources:resources performer:model.
       
  6152     transSub receiver:self.
       
  6153     toolSub subMenuAt:#babelFishTranslate put:transSub.
       
  6154 
       
  6155     sortSub := PopUpMenu itemList:sortItems resources:resources performer:model.
       
  6156     sortSub receiver:self.
       
  6157     toolSub subMenuAt:#sort put:sortSub.
       
  6158 
       
  6159     subSub := PopUpMenu itemList:miscItems resources:resources performer:model.
       
  6160     subSub receiver:self.
       
  6161     subSub checkToggleAt:#autoIndent: put:autoIndent.
       
  6162     subSub checkToggleAt:#insertMode: put:(self isInInsertMode).
       
  6163     subSub checkToggleAt:#learnMode: put:(self learnModeHolder value).
       
  6164 
       
  6165     sub subMenuAt:#misc put:subSub.
       
  6166 
       
  6167     mainItems := #(
       
  6168                     ('Undo'    undo             Undo   )
       
  6169                     ('Again'   again            Again  )
       
  6170                     ('-'                               )
       
  6171                     ('Cut'     cut              Cut    )
       
  6172                     ('Copy'    copySelection    Copy   )
       
  6173                     ('Paste'   pasteOrReplace   Paste  )
       
  6174                     ('-'                               )
       
  6175                     ('Accept'  accept           Accept )
       
  6176                     ('='                               )
       
  6177                     ('More'    others           Ctrl   )
       
  6178               ).
       
  6179     main := PopUpMenu itemList:mainItems resources:resources.
       
  6180     main subMenuAt:#others put:sub.
       
  6181 
       
  6182     sensor := self sensor.
       
  6183     (sensor notNil and:[sensor ctrlDown]) ifTrue:[
       
  6184        sensor shiftDown ifTrue:[
       
  6185             m := subSub
       
  6186         ] ifFalse:[
       
  6187             m := sub
       
  6188         ]
       
  6189     ] ifFalse:[
       
  6190         m := main
       
  6191     ].
       
  6192 
       
  6193     "/ the 'Smalltalk at:' code is here to
       
  6194     "/ avoid making the SOAP package a prerequisite for this package (libwidg)
       
  6195     (Smalltalk at:#'SOAP::GoogleClient') isNil ifTrue:[
       
  6196         "/ GoogleClient new spellingSuggestionOf: 'Smmalltlaak and Soaap'.
       
  6197         m disable:#googleSpellingSuggestion
       
  6198     ].
       
  6199     (Smalltalk at:#'RBSpellChecker') isNil ifTrue:[
       
  6200         m disable:#internalSpellingSuggestion
       
  6201     ].
       
  6202 
       
  6203     HTTPInterface isNil ifTrue:[
       
  6204         m disableAll:#(insertURL)
       
  6205     ].
       
  6206 
       
  6207     self isReadOnly ifTrue:[
       
  6208         m disableAll:#(accept undo again multipleAgain redo
       
  6209                        paste pasteOrReplace pasteOrReplaceFromHistory
       
  6210                        cut indent autoIndent: insertMode:
       
  6211                        insertFile insertFileAsStringLiteral insertURL
       
  6212                        babelFishTranslate googleSpellingSuggestion sort
       
  6213                        convertSelectionToLowercaseOrUppercaseOrUppercaseFirst 
       
  6214                        joinLines wrapLines insertUUID insertDateAndTime pasteAsStringLiteral
       
  6215                        insertUnicode specialCharacters)
       
  6216     ].
       
  6217     self hasSelectionForCopy ifFalse:[
       
  6218         m disable:#copySelection.
       
  6219     ].
       
  6220     self hasSelection ifFalse:[
       
  6221         m disableAll:#(cut googleSpellingSuggestion babelFishTranslate openFileBrowserOnIt openWorkspaceWithIt sort indent).
       
  6222     ] ifTrue:[
       
  6223         (Error handle:[:ex |
       
  6224             ex return:false
       
  6225         ] do:[
       
  6226             |fn|
       
  6227             fn := self selectionAsString.
       
  6228             fn asFilename exists or:[ fn withoutSeparators withoutQuotes asFilename exists ]
       
  6229         ]) ifFalse:[
       
  6230             m disableAll:#(openFileBrowserOnIt).
       
  6231         ]
       
  6232     ].
       
  6233     self hasUndoAction ifFalse:[
       
  6234         m disable:#undo.
       
  6235     ] ifTrue:[
       
  6236         what := undoSupport undoActionInfo.
       
  6237         what notNil ifTrue:[
       
  6238             undoIdx := m indexOf:#undo.
       
  6239             m labelAt:undoIdx put:(resources string:'Undo (%1)' with:what).
       
  6240         ]
       
  6241     ].
       
  6242     self hasRedoAction ifFalse:[
       
  6243         sub disable:#redo.
       
  6244     ] ifTrue:[
       
  6245         what := undoSupport redoActionInfo.
       
  6246         what notNil ifTrue:[
       
  6247             redoIdx := sub indexOf:#redo.
       
  6248             sub labelAt:redoIdx put:(resources string:'Redo (%1)' with:what).
       
  6249         ]
       
  6250     ].
       
  6251     acceptEnabled == false ifTrue:[
       
  6252         m disable:#accept
       
  6253     ].
       
  6254     ^ m.
       
  6255 
       
  6256     "Modified: / 01-03-2012 / 19:56:58 / cg"
       
  6257 !
       
  6258 
       
  6259 getTextSelectionFromHistory
       
  6260     |sel list box history|
       
  6261 
       
  6262     history := self graphicsDevice getCopyBufferHistory copy.
       
  6263     list := history collect:[:entry |
       
  6264                 |text shown|
       
  6265 
       
  6266                 text := entry asString string asCollectionOfLines.
       
  6267                 shown := text detect:[:line| line notEmptyOrNil] ifNone:['      '].
       
  6268                 text size > 1 ifTrue:[
       
  6269                     shown := shown,(resources string:' ... [%1 lines]' with:text size).
       
  6270                 ].
       
  6271                 shown
       
  6272             ].
       
  6273 
       
  6274     box := ListSelectionBox
       
  6275                 title:(resources string:'Clipboard History')
       
  6276                 okText:(resources string:'Paste')
       
  6277                 abortText:(resources string:'Cancel')
       
  6278                 list:list
       
  6279                 action:[:idx | idx notNil ifTrue:[sel := history at:idx]].
       
  6280     box label:(resources string:'Select Previous Copybuffer String').
       
  6281     box useIndex:true.
       
  6282     box show.
       
  6283     ^ sel.
       
  6284 
       
  6285     "Modified: / 25-08-2010 / 22:02:14 / cg"
       
  6286 !
       
  6287 
       
  6288 getTextSelectionOrTextSelectionFromHistory
       
  6289 
       
  6290     self sensor shiftDown ifTrue:[
       
  6291         ^ self getTextSelectionFromHistory
       
  6292     ].
       
  6293 
       
  6294     "/ return either the (xterm-) selection or the clipBoard depending on
       
  6295     "/ the Ctrl-Key state.
       
  6296 
       
  6297     "/ ouch - this used to be ok for ALT-c / ALT-v,
       
  6298     "/ but no longer works with CTRL-c / CTRL-v.
       
  6299     ^ self getClipboardText:#clipboard
       
  6300 
       
  6301 "/    ^ self
       
  6302 "/        getClipboardText:(self sensor ctrlDown
       
  6303 "/                            ifTrue:[#selection]
       
  6304 "/                            ifFalse:[#clipboard])
       
  6305 
       
  6306     "Modified: / 13-07-2011 / 14:55:58 / cg"
       
  6307 !
       
  6308 
       
  6309 googleSpellingSuggestion
       
  6310     "insert the google-spelling suggestion for the selected text.
       
  6311      Requires that the SOAP stuff is loaded and working."
       
  6312 
       
  6313     |text suggestion|
       
  6314 
       
  6315     self withWaitCursorDo:[
       
  6316         text := self selection asString string withoutSeparators.
       
  6317         text size == 0 ifTrue:[^ self].
       
  6318 
       
  6319         "/ the 'Smalltalk at:' code is here to
       
  6320         "/ avoid making the SOAP package a prerequisite for this package (libwidg)
       
  6321         (Smalltalk at:#'SOAP::SoapImplError') handle:[:ex |
       
  6322             Dialog warn:('Spelling correction failed - WEB Service error:\\%1.' bindWith:ex description allBold) withCRs.
       
  6323             ^ self.
       
  6324         ] do:[
       
  6325             suggestion := (Smalltalk at:#'SOAP::GoogleClient') new spellingSuggestionOf:text.
       
  6326         ].
       
  6327         suggestion size == 0 ifTrue:[
       
  6328             self information:('No spelling suggestion from Google for: ' , text).
       
  6329             Transcript showCR:('No spelling suggestion from Google for: ' , text).
       
  6330             ^ self.
       
  6331         ].
       
  6332     ].
       
  6333     self 
       
  6334         undoablePaste:suggestion 
       
  6335         info:'Spelling Suggestion'.
       
  6336 
       
  6337     "Modified: / 28-07-2007 / 13:25:10 / cg"
       
  6338 !
       
  6339 
       
  6340 insertDateAndTime
       
  6341     "insert the curent date and time string"
       
  6342 
       
  6343     typeOfSelection := nil.
       
  6344     self
       
  6345         undoableDo:[ self pasteOrReplace:(Timestamp now printStringRFC1123Format)]
       
  6346         info:'Paste Date and Time'
       
  6347 !
       
  6348 
       
  6349 insertFile
       
  6350     "insert contents of a file
       
  6351      - ask user for filename using a fileSelectionBox."
       
  6352 
       
  6353     self insertFileAsStringLiteral:false
       
  6354 !
       
  6355 
       
  6356 insertFileAsStringLiteral
       
  6357     "insert a file's contents as a string literal.
       
  6358      Almost the same as the insert file, but single-quotes are doubled,
       
  6359      to make it a legal string literal"
       
  6360 
       
  6361     self insertFileAsStringLiteral:true
       
  6362 !
       
  6363 
       
  6364 insertFileAsStringLiteral:asStringLiteral
       
  6365     "insert contents of a file; either as-is or as a string literal.
       
  6366      - ask user for filename using a fileSelectionBox."
       
  6367 
       
  6368     |sel selFn file text ok initial|
       
  6369 
       
  6370     ((sel := self selectionAsString) notEmptyOrNil
       
  6371     and:[ (selFn := sel asFilename) exists
       
  6372     and:[ selFn isRegularFile ]])
       
  6373     ifTrue:[
       
  6374         initial := selFn pathName.
       
  6375     ].
       
  6376 
       
  6377     [
       
  6378         |why|
       
  6379 
       
  6380         file := Dialog
       
  6381             requestFileName:(resources string:'Insert Contents Of:')
       
  6382             default:initial
       
  6383             ok:(resources string:'Insert')
       
  6384             abort:(resources string:'Cancel')
       
  6385             pattern:nil
       
  6386             fromDirectory:directoryForFileDialog.
       
  6387         file isNil ifTrue:[
       
  6388             "cancel"
       
  6389             ^ self.
       
  6390         ].
       
  6391         file := file asFilename.
       
  6392         directoryForFileDialog := file.
       
  6393 
       
  6394         ok := file isReadable and:[file isDirectory not].
       
  6395         ok ifFalse:[
       
  6396             file isReadable ifFalse:[
       
  6397                 why := '%1 is unreadable.\\Please try again.'
       
  6398             ] ifTrue:[
       
  6399                 why := '%1 is a directory.\\Please try again.'
       
  6400             ].
       
  6401             Dialog warn:(resources stringWithCRs:why with:file pathName).
       
  6402         ].
       
  6403     ] doUntil:[ok].
       
  6404 
       
  6405     text := file contentsOfEntireFile.
       
  6406     self
       
  6407         undoableDo:[ self paste:(asStringLiteral ifTrue:[text storeString] ifFalse:[text]) ]
       
  6408         info:'Paste File'
       
  6409 
       
  6410     "Modified: / 28-07-2007 / 13:23:32 / cg"
       
  6411 !
       
  6412 
       
  6413 insertURL
       
  6414     "insert contents of a URL
       
  6415      - ask user for URL using a dialog."
       
  6416 
       
  6417     self insertURLAsStringLiteral:false
       
  6418 !
       
  6419 
       
  6420 insertURLAsStringLiteral:asStringLiteral
       
  6421     "insert contents of a file; either as-is or as a string literal.
       
  6422      - ask user for filename using a fileSelectionBox."
       
  6423 
       
  6424     |sel url text response initial|
       
  6425 
       
  6426     (sel := self selectionAsString) notEmptyOrNil
       
  6427     ifTrue:[
       
  6428         initial := sel.
       
  6429     ].
       
  6430 
       
  6431     url := Dialog
       
  6432         request:(resources string:'Insert Contents of URL:')
       
  6433         initialAnswer:initial
       
  6434         okLabel:(resources string:'Insert')
       
  6435         title:(resources string:'URL').
       
  6436     url isNil ifTrue:[
       
  6437         "cancel"
       
  6438         ^ self.
       
  6439     ].
       
  6440     response := HTTPInterface get:url.
       
  6441     response isErrorResponse ifTrue:[
       
  6442         Dialog warn:(resources string:'Could not fetch the document: %1' with:url).
       
  6443         ^ self.
       
  6444     ].
       
  6445     text := response data asString.
       
  6446 
       
  6447     self
       
  6448         undoableDo:[ 
       
  6449             self paste:(asStringLiteral ifTrue:[text storeString] ifFalse:[text]) 
       
  6450         ]
       
  6451         info:'Insert Contents of URL'
       
  6452 !
       
  6453 
       
  6454 insertUUID
       
  6455     "insert a new UUID's string"
       
  6456 
       
  6457     typeOfSelection := nil.
       
  6458     self
       
  6459         undoableDo:[ self pasteOrReplace:(UUID genUUID printString)]
       
  6460         info:'Paste New UUID'
       
  6461 
       
  6462     "Created: / 28-07-2007 / 13:01:16 / cg"
       
  6463 !
       
  6464 
       
  6465 insertUnicode
       
  6466     "open a Dialog requesting an integer value and insert it as unicode character"
       
  6467 
       
  6468     |unicodePoint unicodeChar unicodeString|
       
  6469 
       
  6470     unicodeString := Dialog request:'Enter unicode (U+01FF or decimal number):'.
       
  6471     unicodeString size < 2 ifTrue:[
       
  6472         ^ self.
       
  6473     ].
       
  6474     (unicodeString second = $+ and:['Uu' includes:unicodeString first]) ifTrue:[
       
  6475         unicodePoint := Integer readFrom:(unicodeString copyFrom:3) radix:16 onError:[^ self].
       
  6476     ] ifFalse:[
       
  6477         unicodePoint := Integer readFrom:unicodeString onError:[^ self].
       
  6478     ].
       
  6479         
       
  6480     unicodeChar := Character value:unicodePoint.
       
  6481     self keyPress:unicodeChar x:0 y:0.
       
  6482     self keyRelease:unicodeChar x:0 y:0.
       
  6483 !
       
  6484 
       
  6485 internalSpellingSuggestion
       
  6486     "insert the internal-spelling suggestion for the selected text.
       
  6487      Requires that the RefactoryBrowser/line/spelCheck stuff is loaded."
       
  6488 
       
  6489     |text suggestions best|
       
  6490 
       
  6491     self withWaitCursorDo:[
       
  6492         text := self selection asString string withoutSeparators.
       
  6493         text size == 0 ifTrue:[^ self].
       
  6494 
       
  6495         suggestions := RBSpellChecker default bestMatchesFor:text.
       
  6496         suggestions size == 0 ifTrue:[
       
  6497             self information:('No spelling suggestion from builtin checker for: ' , text).
       
  6498             Transcript showCR:('No spelling suggestion from builtin checker for: ' , text).
       
  6499             ^ self.
       
  6500         ].
       
  6501         Transcript showCR:suggestions.
       
  6502         best := suggestions first.
       
  6503     ].
       
  6504     self 
       
  6505         undoablePaste:best 
       
  6506         info:'Spelling Suggestion'.
       
  6507 !
       
  6508 
       
  6509 openFileBrowserOnFileNamed:fileNameString
       
  6510     "open a fileBrowser on the given fileNameString"
       
  6511 
       
  6512     |fn|
       
  6513 
       
  6514     fn := fileNameString asFilename.
       
  6515     fn exists ifFalse:[
       
  6516         fn := fileNameString withoutSeparators withoutQuotes asFilename.
       
  6517         fn exists ifFalse:[
       
  6518             ^ self warn:'Oops - file is gone'.
       
  6519         ].
       
  6520     ].
       
  6521     UserPreferences fileBrowserClass openOn:fn
       
  6522 
       
  6523     "Modified: / 06-09-2012 / 14:47:22 / cg"
       
  6524 !
       
  6525 
       
  6526 openFileBrowserOnIt
       
  6527     "open a fileBrowser on the selected fileName"
       
  6528 
       
  6529     |fileNameString|
       
  6530 
       
  6531     fileNameString := self selectionAsString.
       
  6532     self openFileBrowserOnFileNamed:fileNameString
       
  6533 
       
  6534     "Modified: / 06-09-2012 / 14:47:22 / cg"
       
  6535 !
       
  6536 
       
  6537 openWorkspaceWithIt
       
  6538     "open a workspace containing the selected text"
       
  6539 
       
  6540     |text|
       
  6541 
       
  6542     text := self selectionAsString.
       
  6543     WorkspaceApplication openWith:text selected:true
       
  6544 
       
  6545     "Created: / 26-05-2007 / 06:05:22 / cg"
       
  6546 !
       
  6547 
       
  6548 paste
       
  6549     "paste the copybuffer; if there is a selection, unselect first.
       
  6550      Then paste at cursor position."
       
  6551 
       
  6552     self checkModificationsAllowed ifTrue:[
       
  6553         self withSelfAndTextForPasteDo:[:me :text |
       
  6554             me unselect.
       
  6555             me undoablePaste:text
       
  6556         ]
       
  6557     ]
       
  6558 !
       
  6559 
       
  6560 paste:someText
       
  6561     "paste someText at cursor"
       
  6562 
       
  6563     self paste:someText withCR:false
       
  6564 !
       
  6565 
       
  6566 paste:someText withCR:withCR
       
  6567     "paste someText at cursor"
       
  6568 
       
  6569     |s nLines startLine startCol l1 l2 c1 c2 codingErrorReported|
       
  6570 
       
  6571     self checkModificationsAllowed ifFalse:[^ self].
       
  6572     someText isNil ifTrue:[^ self].
       
  6573 
       
  6574     s := someText.
       
  6575     codingErrorReported := false.
       
  6576     CharacterEncoderError handle:[:ex |
       
  6577         |code msg|
       
  6578 
       
  6579         code := ex parameter.
       
  6580         codingErrorReported ifFalse:[
       
  6581             msg := 'Cannot represent pasted string in this Views encoding (',gc characterEncoding,').'.
       
  6582             code notNil ifTrue:[
       
  6583                 msg := msg , '\\Reason: No representation for ' , (code radixPrintStringRadix:16).
       
  6584             ].
       
  6585             Dialog warn:(resources stringWithCRs:msg).
       
  6586             codingErrorReported := true.
       
  6587         ].
       
  6588         ex proceedWith:ex defaultValue
       
  6589     ] do:[
       
  6590         s isString ifTrue:[
       
  6591             s encoding ~~ gc characterEncoding ifTrue:[
       
  6592                 s := s encodeFrom:(s encoding) into:gc characterEncoding.
       
  6593             ].
       
  6594 
       
  6595             s := s asStringCollection.
       
  6596             (someText endsWith:Character cr) ifTrue:[
       
  6597                 "/ s := s copyWith:nil.
       
  6598                 s := s copyWith:'' "/ an empty line at the end
       
  6599 
       
  6600             ]
       
  6601         ] ifFalse:[
       
  6602             s isStringCollection ifTrue:[
       
  6603                 s := s encodeFrom:(s encoding) into:gc characterEncoding.
       
  6604             ] ifFalse:[
       
  6605                 (self
       
  6606                     confirm:(resources
       
  6607                         stringWithCRs:'Selection (%1) is not convertable to Text.\\Paste storeString ?'
       
  6608                         with:s class name)) ifFalse:[^ self].
       
  6609                 s := StringCollection with:s storeString .
       
  6610                 "/ ^ self
       
  6611             ].
       
  6612         ].
       
  6613     ].
       
  6614 
       
  6615     (nLines := s size) == 0 ifTrue:[^ self].
       
  6616     (nLines == 1 and:[(s at:1) size == 0]) ifTrue:[^ self].
       
  6617 
       
  6618     typeOfSelection := #paste.
       
  6619 
       
  6620     startLine := l1 := cursorLine.
       
  6621     startCol := c1 := cursorCol.
       
  6622 
       
  6623     "do not expand tabs into spaces here -
       
  6624      they get expanded in basicWithoutRedrawInsertStringWithoutCRs:aString atLine:lineNr col:colNr.
       
  6625      Some Subviews want to paste with unexpanded tabs!!"
       
  6626 
       
  6627     self insertLines:s withCR:withCR.
       
  6628     l2 := cursorLine.
       
  6629     c2 := (cursorCol - 1).
       
  6630     self selectFromLine:l1 col:c1 toLine:l2 col:c2.
       
  6631     typeOfSelection := #paste. "/ sigh - cleared by #selectFromLine:
       
  6632 
       
  6633     "Modified: / 14-02-1996 / 11:14:14 / stefan"
       
  6634     "Modified: / 25-01-2012 / 00:31:30 / cg"
       
  6635 !
       
  6636 
       
  6637 pasteAsStringLiteral
       
  6638     "insert clipboard string as a string literal.
       
  6639      Almost the same as a normal paste, but single-quotes are doubled,
       
  6640      to make it a legal string literal"
       
  6641 
       
  6642     typeOfSelection := nil.
       
  6643     self
       
  6644         undoableDo:[ self pasteOrReplace:(self getClipboardText storeString) ]
       
  6645         info:'Paste as String Literal'
       
  6646 !
       
  6647 
       
  6648 pasteOrReplace
       
  6649     "paste the copybuffer; if there is a selection, replace it.
       
  6650      otherwise paste at cursor position.
       
  6651      Replace is not done for selections which were created by a paste,
       
  6652      to allow multiple paste operations in a row."
       
  6653 
       
  6654     self withSelfAndTextForPasteDo:[:me :text | me pasteOrReplace:text]
       
  6655 !
       
  6656 
       
  6657 pasteOrReplace:someText
       
  6658     "paste someText; if there is a selection, replace it.
       
  6659      otherwise paste at cursor position. Replace is not done
       
  6660      for originating by a paste, to allow multiple
       
  6661      paste."
       
  6662 
       
  6663     self checkModificationsAllowed ifFalse:[^ self].
       
  6664 
       
  6665     self undoableDo:[
       
  6666         ((self hasSelection == true) and:[typeOfSelection ~~ #paste]) ifTrue:[
       
  6667             self replace:someText
       
  6668         ] ifFalse:[
       
  6669             self paste:someText.
       
  6670         ]
       
  6671     ] info:'Paste/Replace'.
       
  6672 
       
  6673     "Modified: / 30.1.2000 / 02:33:00 / cg"
       
  6674 !
       
  6675 
       
  6676 pasteOrReplaceFromHistory
       
  6677     "paste a previous item from the copybuffer history.
       
  6678      (i.e. repaste some previously deleted or copied text)"
       
  6679 
       
  6680     |text|
       
  6681 
       
  6682     self checkModificationsAllowed ifFalse:[
       
  6683         self flashReadOnly.
       
  6684         ^ self
       
  6685     ].
       
  6686     text := self getTextSelectionFromHistory.
       
  6687     text notNil ifTrue:[
       
  6688         self pasteOrReplace:text
       
  6689     ]
       
  6690 !
       
  6691 
       
  6692 replace
       
  6693     "replace the selection by the contents of the copybuffer"
       
  6694 
       
  6695     self hasSelection ifFalse:[^ self].
       
  6696     self checkModificationsAllowed ifFalse:[^ self].
       
  6697 
       
  6698     self withSelfAndTextForPasteDo:[:me :text |
       
  6699         me undoableDo:[ me replace:text ]
       
  6700         info:'Replace'
       
  6701     ]
       
  6702 !
       
  6703 
       
  6704 replace:someText
       
  6705     "replace the selection by someText"
       
  6706 
       
  6707     |selected selectedString
       
  6708      selStartLine selStartCol selEndLine selEndCol|
       
  6709 
       
  6710     self checkModificationsAllowed ifFalse:[^ self].
       
  6711 
       
  6712     self undoableDo:[
       
  6713         selected := self selection.
       
  6714         selected isNil ifTrue:[
       
  6715             ^ self paste:someText
       
  6716         ].
       
  6717 
       
  6718         self deleteSelection.
       
  6719 
       
  6720         "take care, if we replace a selection without space by a word selected
       
  6721          with one - in this case we usually do not want the space.
       
  6722          But, if we replace a word-selected selection by something without a
       
  6723          space, we DO want the space added."
       
  6724 
       
  6725         selected size == 1 ifTrue:[
       
  6726             selectedString := selected at:1.
       
  6727         ].
       
  6728 
       
  6729         someText size == 1 ifTrue:[
       
  6730             |cutOffSpace addSpace replacement replacementString|
       
  6731 
       
  6732             cutOffSpace := false.
       
  6733             addSpace := false.
       
  6734             replacement := someText copyFrom:1.
       
  6735 
       
  6736             selectedString notNil ifTrue:[
       
  6737                 ((selectedString startsWith:' ') or:[selectedString endsWith:' ']) ifFalse:[
       
  6738                    "selection has no space"
       
  6739 
       
  6740                     ((selectStyle == #wordleft) or:[selectStyle == #wordRight]) ifTrue:[
       
  6741                         cutOffSpace := true
       
  6742                     ]
       
  6743                 ] ifTrue:[
       
  6744                     addSpace := true
       
  6745                 ]
       
  6746             ].
       
  6747             replacementString := replacement at:1.
       
  6748             cutOffSpace ifTrue:[
       
  6749                 (replacementString startsWith:' ') ifTrue:[
       
  6750                     replacementString := replacementString withoutSpaces
       
  6751                 ].
       
  6752             ] ifFalse:[
       
  6753                 selectStyle == #wordLeft ifTrue:[
       
  6754                     "want a space at left"
       
  6755                     (replacementString startsWith:' ') ifFalse:[
       
  6756                         replacementString := replacementString withoutSpaces.
       
  6757                         replacementString := ' ' , replacementString
       
  6758                     ]
       
  6759                 ].
       
  6760                 selectStyle == #wordRight ifTrue:[
       
  6761                     "want a space at right"
       
  6762 
       
  6763                     (replacementString endsWith:' ') ifFalse:[
       
  6764                         replacementString := replacementString withoutSpaces.
       
  6765                         replacementString := replacementString , ' '
       
  6766                     ]
       
  6767                 ].
       
  6768             ].
       
  6769             replacement at:1 put: replacementString.
       
  6770             self paste:replacement.
       
  6771         ] ifFalse:[
       
  6772             self paste:someText
       
  6773         ].
       
  6774         self setLastStringToReplace: selectedString.
       
  6775 
       
  6776         lastReplacementInfo lastReplacement: someText.
       
  6777 
       
  6778         selStartLine := selectionStartLine.
       
  6779         selStartCol := self selectionStartCol.
       
  6780         selEndLine := selectionEndLine.
       
  6781         selEndCol := self selectionEndCol.
       
  6782     ]
       
  6783     info:'Replace'
       
  6784 
       
  6785     "Modified: / 14.2.1996 / 10:37:02 / stefan"
       
  6786     "Modified: / 5.4.1998 / 16:55:28 / cg"
       
  6787 !
       
  6788 
       
  6789 searchReplace
       
  6790     "search for a string - show a box to enter searchpattern
       
  6791      replace for the found searchpattern or replace all searchpattern found to a new pattern - show  a box to enter replacepattern
       
  6792      - currently no regular expressions are handled."
       
  6793 
       
  6794     |searchBox patternHolder replacePatternHolder caseHolder flag ign initialString bindings bldr search modal replace action|
       
  6795 
       
  6796     modal := false "(UserPreferences current searchDialogIsModal)".
       
  6797     lastSearchDirection := #forward.
       
  6798     ign := lastSearchIgnoredCase ? LastSearchIgnoredCase ? true.
       
  6799     caseHolder := ign asValue.
       
  6800     patternHolder := '' asValue.
       
  6801     replacePatternHolder := '' asValue.
       
  6802     lastSearchPattern notNil ifTrue:[
       
  6803         initialString := lastSearchPattern
       
  6804     ].
       
  6805     self hasSelectionWithinSingleLine ifTrue:[
       
  6806         initialString := self selectionAsString
       
  6807     ].
       
  6808     initialString isNil ifTrue:[
       
  6809         LastSearchPatterns size > 0 ifTrue:[
       
  6810             initialString := LastSearchPatterns first
       
  6811         ]
       
  6812     ].
       
  6813     initialString notNil ifTrue:[
       
  6814         patternHolder value:initialString.
       
  6815         replacePatternHolder value:initialString.
       
  6816     ].
       
  6817     flag := true.
       
  6818     search := [:fwd |
       
  6819             self
       
  6820                 search:patternHolder value
       
  6821                 ignoreCase:caseHolder value
       
  6822                 forward:fwd.
       
  6823         ].
       
  6824     replace := [:all |
       
  6825             self
       
  6826                 replace:patternHolder value
       
  6827                 by:replacePatternHolder value
       
  6828                 all:all
       
  6829                 ignoreCase:caseHolder value
       
  6830         ].
       
  6831     bindings := IdentityDictionary new.
       
  6832     bindings at:#searchPattern put:patternHolder.
       
  6833     bindings at:#replacePattern put:replacePatternHolder.
       
  6834     modal ifTrue:[
       
  6835         bindings at:#nextAction
       
  6836             put:[
       
  6837                 flag := true.
       
  6838                 action := search.
       
  6839                 searchBox doAccept.
       
  6840             ].
       
  6841         bindings at:#prevAction
       
  6842             put:[
       
  6843                 flag := false.
       
  6844                 action := search.
       
  6845                 searchBox doAccept.
       
  6846             ].
       
  6847         bindings at:#replaceAction
       
  6848             put:[
       
  6849                 flag := false.
       
  6850                 action := replace.
       
  6851                 searchBox doAccept.
       
  6852             ].
       
  6853         bindings at:#replaceAllAction
       
  6854             put:[
       
  6855                 flag := true.
       
  6856                 action := replace.
       
  6857                 searchBox doAccept.
       
  6858             ].
       
  6859     ] ifFalse:[
       
  6860         bindings at:#nextAction put:[ search value:true. ].
       
  6861         bindings at:#prevAction put:[ search value:false. ].
       
  6862         bindings at:#replaceAction put:[ replace value:false. ].
       
  6863         bindings at:#replaceAllAction put:[ replace value:true. ].
       
  6864     ].
       
  6865     bindings at:#ignoreCase put:caseHolder.
       
  6866     bindings at:#patternList put:LastSearchPatterns.
       
  6867     modal ifTrue:[
       
  6868         searchBox := SimpleDialog new.
       
  6869     ] ifFalse:[
       
  6870         searchBox := ApplicationModel new.
       
  6871         searchBox createBuilder.
       
  6872     ].
       
  6873     searchBox resources:(self resources).
       
  6874     bldr := searchBox builder.
       
  6875     bldr addBindings:bindings.
       
  6876     searchBox allButOpenFrom:(self class searchReplaceDialogSpec).
       
  6877     (bldr componentAt:#nextButton) cursor:(Cursor thumbsUp).
       
  6878     (bldr componentAt:#prevButton) cursor:(Cursor thumbsUp).
       
  6879     (bldr componentAt:#cancelButton) cursor:(Cursor thumbsDown).
       
  6880     modal ifTrue:[
       
  6881         searchBox openDialog.
       
  6882         searchBox accepted ifTrue:[
       
  6883             action value:flag
       
  6884         ].
       
  6885     ] ifFalse:[
       
  6886         (bldr componentAt:#nextButton) isReturnButton:false.
       
  6887         (bldr componentAt:#cancelButton)
       
  6888             label:(resources string:'Close');
       
  6889             action:[ searchBox closeRequest ].
       
  6890 
       
  6891         "/ searchBox masterApplication:self application.
       
  6892 
       
  6893         self topView beMaster.
       
  6894         (searchBox window)
       
  6895             beSlave;
       
  6896             openInGroup:(self windowGroup).
       
  6897 
       
  6898         "/ searchBox window open.
       
  6899 
       
  6900         searchBox window assignKeyboardFocusToFirstInputField.
       
  6901     ]
       
  6902 
       
  6903     "Modified: / 11-07-2006 / 11:20:06 / fm"
       
  6904 !
       
  6905 
       
  6906 showDeleted
       
  6907     "open a readonly editor on all deleted text"
       
  6908 
       
  6909     |v|
       
  6910 
       
  6911     v := EditTextView openWith:(Smalltalk at:#DeleteHistory).
       
  6912     v readOnly:true.
       
  6913     v topView label:'deleted text'.
       
  6914 !
       
  6915 
       
  6916 sort:how ignoreCase:ignoreCase fromLine:start toLine:end
       
  6917     "sort/reorder the selected lines.
       
  6918      how:
       
  6919         #lines
       
  6920         #linesByFirstWord
       
  6921         #linesByNthWord
       
  6922         #linesByNthNumber
       
  6923         #linesByNthHexNumber
       
  6924         #words
       
  6925         #linesByLength
       
  6926         #reverse
       
  6927     "
       
  6928 
       
  6929     |lines extractor innerExtractor fetcher operation lineWise nStr n s words|
       
  6930 
       
  6931     lineWise := true.
       
  6932 
       
  6933     how == #reverse ifTrue:[
       
  6934         operation := [:lines | lines reverse].
       
  6935     ] ifFalse:[
       
  6936         operation := [:linesOrWords |
       
  6937                         linesOrWords sort:[:item1 :item2 | (fetcher value:item1) < (fetcher value:item2)]
       
  6938                      ].
       
  6939 
       
  6940         how == #linesByLength ifTrue:[
       
  6941             fetcher := [:l | l size].
       
  6942         ] ifFalse:[
       
  6943             how == #lines ifTrue:[
       
  6944                 extractor := [:l | l withoutLeadingSeparators].
       
  6945             ] ifFalse:[ 
       
  6946                 how == #linesByFirstWord ifTrue:[
       
  6947                     extractor := [:l | ((l asCollectionOfWords select:[:w | w isEmpty or:[w first isLetterOrDigit]]) at:1 ifAbsent:'')].
       
  6948                 ] ifFalse:[ 
       
  6949                     ((how == #linesByNthWord) or:[ how == #linesByNthNumber  or:[ how == #linesByNthHexNumber]]) ifTrue:[
       
  6950                         nStr := Dialog request:'Word/Column (1..)' initialAnswer:(LastColumnNumberForSort ? 2).
       
  6951                         nStr isEmptyOrNil ifTrue:[^ self].
       
  6952                         n := Integer readFrom:nStr onError:[^ self].
       
  6953                         LastColumnNumberForSort := n.
       
  6954                         extractor := [:l | ((l string asCollectionOfWords) at:n ifAbsent:'')].
       
  6955                         how == #linesByNthNumber ifTrue:[
       
  6956                             innerExtractor := extractor.
       
  6957                             extractor := [:l | Integer readFrom:(innerExtractor value:l) onError:0]
       
  6958                         ] ifFalse:[
       
  6959                             how == #linesByNthHexNumber ifTrue:[
       
  6960                                 innerExtractor := extractor.
       
  6961                                 extractor := [:l | 
       
  6962                                     |s|                                 
       
  6963                                     s := innerExtractor value:l.
       
  6964                                     (s startsWith:'16r') ifTrue:[
       
  6965                                         (Integer readSmalltalkSyntaxFrom:s) ? 0
       
  6966                                     ] ifFalse:[
       
  6967                                         Integer readFrom:s radix:16 onError:[ 0 ]
       
  6968                                     ]
       
  6969                                 ]
       
  6970                             ]
       
  6971                         ].
       
  6972                     ] ifFalse:[ 
       
  6973                         how == #words ifTrue:[
       
  6974                             lineWise := false.
       
  6975                             extractor := [:w | w].
       
  6976                         ] ifFalse:[
       
  6977                             self error:'unknown sort criteria: ', how printString.
       
  6978                         ]
       
  6979                     ]
       
  6980                 ]
       
  6981             ].
       
  6982             ignoreCase ifTrue:[
       
  6983                 fetcher := [:l | (extractor value:l) asLowercase].
       
  6984             ] ifFalse:[
       
  6985                 fetcher := extractor.
       
  6986             ].
       
  6987         ].
       
  6988     ].
       
  6989 
       
  6990     lineWise ifTrue:[
       
  6991         "process the lines of the selection (aka a collection of lines)"
       
  6992         start == end ifTrue:[^ self ].
       
  6993         lines := (start to:end) collect:[:lineNr | (self listAt:lineNr) ? ''].
       
  6994         lines := operation value:lines.
       
  6995         (start to:end) with:lines do:[:lineNr :line | self replaceLine:lineNr with:line].
       
  6996     ] ifFalse:[
       
  6997         "process the whole selection as a string"
       
  6998         s := self selectionAsString.
       
  6999         words := s asCollectionOfWords.
       
  7000         words := operation value:words.
       
  7001         s := words asStringCollection asStringWith:Character space.
       
  7002         self replace:s.
       
  7003     ].
       
  7004     self textChanged.
       
  7005 
       
  7006     "Modified: / 31-03-2012 / 10:59:28 / cg"
       
  7007 !
       
  7008 
       
  7009 sortSelection:how ignoreCase:ignoreCase
       
  7010     "sort the selected lines"
       
  7011 
       
  7012     |start end|
       
  7013 
       
  7014     selectionStartLine isNil ifTrue:[^ self].
       
  7015 
       
  7016     start := selectionStartLine.
       
  7017     end := selectionEndLine.
       
  7018     (selectionEndCol == 0) ifTrue:[
       
  7019         end := end - 1
       
  7020     ].
       
  7021 
       
  7022     self
       
  7023         undoableDo:[ 
       
  7024             self sort:how ignoreCase:ignoreCase fromLine:start toLine:end 
       
  7025         ]
       
  7026         info:'Sort'
       
  7027 
       
  7028     "Modified (format): / 15-02-2012 / 16:52:53 / cg"
       
  7029 !
       
  7030 
       
  7031 specialCharacters
       
  7032     CharacterSetView
       
  7033         openAsInputFor:self
       
  7034         label:'Special Character Input'
       
  7035         clickLabel:'Click to Insert Character'.
       
  7036 !
       
  7037 
       
  7038 undoablePaste:someText
       
  7039     self undoablePaste:someText info:nil.
       
  7040 
       
  7041     "Modified: / 28-07-2007 / 13:25:46 / cg"
       
  7042 !
       
  7043 
       
  7044 undoablePaste:someText info:infoOrNil
       
  7045     self
       
  7046         undoableDo:[
       
  7047             self paste:someText.
       
  7048         ]
       
  7049         info:infoOrNil
       
  7050 
       
  7051     "Created: / 28-07-2007 / 13:25:30 / cg"
       
  7052 !
       
  7053 
       
  7054 undoablePasteOrReplace:someText info:infoOrNil
       
  7055     self
       
  7056         undoableDo:[
       
  7057             self pasteOrReplace:someText.
       
  7058         ]
       
  7059         info:infoOrNil
       
  7060 
       
  7061     "Created: / 28-07-2007 / 13:26:16 / cg"
       
  7062 !
       
  7063 
       
  7064 undoablePasteReplacingAll:someText info:infoOrNil
       
  7065     self
       
  7066         undoableDo:[
       
  7067             self selectAll.
       
  7068             self pasteOrReplace:someText.
       
  7069         ]
       
  7070         info:infoOrNil
       
  7071 
       
  7072     "Created: / 28-07-2007 / 13:25:30 / cg"
       
  7073 !
       
  7074 
       
  7075 withSelfAndTextForPasteDo:aBlock
       
  7076     "common code for paste/replace of the copybuffer"
       
  7077 
       
  7078     |sel|
       
  7079 
       
  7080     self checkModificationsAllowed ifFalse:[
       
  7081         self flashReadOnly.
       
  7082         ^ self
       
  7083     ].
       
  7084 
       
  7085     sel := self getTextSelectionOrTextSelectionFromHistory.
       
  7086     sel notNil ifTrue:[
       
  7087         aBlock value:self value:sel.
       
  7088     ]
       
  7089 ! !
       
  7090 
       
  7091 !EditTextView methodsFor:'private'!
       
  7092 
       
  7093 beep
       
  7094     UserPreferences current beepInEditor ifTrue:[                
       
  7095         super beep
       
  7096     ]
       
  7097 !
       
  7098 
       
  7099 checkModificationsAllowed
       
  7100     "check if the text can be modified (i.e. is not readOnly).
       
  7101      evaluate the exceptionBlock if not.
       
  7102      This block should be provided by the application or user of the textView,
       
  7103      and may show a warnBox or whatever."
       
  7104 
       
  7105     self isReadOnly ifTrue: [
       
  7106         exceptionBlock isNil ifTrue:[
       
  7107             ^ false
       
  7108         ].
       
  7109 
       
  7110         (exceptionBlock value:'Text may not be modified') ~~ true ifTrue:[
       
  7111             ^ false
       
  7112         ]
       
  7113     ].
       
  7114     ^ true
       
  7115 
       
  7116     "Modified: / 17.6.1998 / 15:51:10 / cg"
       
  7117 !
       
  7118 
       
  7119 currentSelectionBgColor
       
  7120     typeOfSelection == #paste ifTrue:[
       
  7121         ^ DefaultAlternativeSelectionBackgroundColor ? selectionBgColor
       
  7122     ].
       
  7123     ^ super currentSelectionBgColor
       
  7124 
       
  7125     "
       
  7126      DefaultAlternativeSelectionBackgroundColor := Color yellow blendWith:Color green
       
  7127     "
       
  7128 !
       
  7129 
       
  7130 currentSelectionFgColor
       
  7131     typeOfSelection == #paste ifTrue:[
       
  7132         ^ DefaultAlternativeSelectionForegroundColor ? selectionFgColor
       
  7133     ].
       
  7134     ^ super currentSelectionFgColor
       
  7135 !
       
  7136 
       
  7137 resetVariablesBeforeNewSearch
       
  7138     "clear the autosearch action, when the first pattern is searched for"
       
  7139 
       
  7140     super resetVariablesBeforeNewSearch.
       
  7141 
       
  7142     "/ new search invalidates remembered string
       
  7143     lastStringFromReplaceForNextSearch := nil.
       
  7144 
       
  7145     "Modified (comment): / 07-03-2012 / 23:21:06 / cg"
       
  7146 !
       
  7147 
       
  7148 setLastStringToReplace: aString
       
  7149 
       
  7150     "This method will set the information coming from the last replace into the replacementInfo"
       
  7151 
       
  7152     |lastReplaceIgnoredCase|
       
  7153 
       
  7154     "/ The searchAction is mantained until a cut/replace or a search with a user selection is done
       
  7155     self clearSearchAction.
       
  7156 
       
  7157     lastReplacementInfo lastStringToReplace: aString.
       
  7158     lastStringFromReplaceForNextSearch := aString.
       
  7159 
       
  7160     "If the replace came after a search, the next replace will have the ignored case from that search action"
       
  7161     lastReplaceIgnoredCase := (typeOfSelection == #search) 
       
  7162                                 ifTrue: [lastSearchIgnoredCase] 
       
  7163                                 ifFalse: [nil].
       
  7164     lastReplacementInfo lastReplaceIgnoredCase: lastReplaceIgnoredCase.
       
  7165 !
       
  7166 
       
  7167 st80EditMode
       
  7168     ^ st80Mode ? (UserPreferences current st80EditMode)
       
  7169 !
       
  7170 
       
  7171 suppressEmphasisInSelection
       
  7172     "selection is shown without emphasis"
       
  7173 
       
  7174     ^ true
       
  7175 !
       
  7176 
       
  7177 textChanged
       
  7178     "my text was modified (internally).
       
  7179      Sent whenever text has been edited (not to confuse with
       
  7180      contentsChanged, which is triggered when the size has changed, and
       
  7181      is used to notify scrollers, other views etc.).
       
  7182 
       
  7183      As some authors of this code have been very sloppy in tha past 
       
  7184      (not sending contentsChanged, but textChanged),
       
  7185      we do it here despite what is written above, to ensure that scrollers update correctly."
       
  7186 
       
  7187     self contentsChanged.
       
  7188     self modified:true.
       
  7189     contentsWasSaved := false
       
  7190 
       
  7191     "Modified: 14.2.1997 / 16:58:38 / cg"
       
  7192 !
       
  7193 
       
  7194 textChangedButNoSizeChange
       
  7195     "my text was modified (internally).
       
  7196      Sent whenever text has been edited (not to confuse with
       
  7197      contentsChanged, which is triggered when the size has changed, and
       
  7198      is used to notify scrollers, other views etc.)"
       
  7199 
       
  7200     self modified:true.
       
  7201     contentsWasSaved := false
       
  7202 
       
  7203     "Modified: 14.2.1997 / 16:58:38 / cg"
       
  7204 ! !
       
  7205 
       
  7206 !EditTextView methodsFor:'queries'!
       
  7207 
       
  7208 currentLine
       
  7209     "the current line (for relative gotos)"
       
  7210 
       
  7211     ^ cursorLine
       
  7212 
       
  7213     "Created: / 17.5.1998 / 20:07:52 / cg"
       
  7214 !
       
  7215 
       
  7216 hasSearchActionSelection
       
  7217 
       
  7218     ^ typeOfSelection == #searchAction
       
  7219 !
       
  7220 
       
  7221 isKeyboardConsumer
       
  7222     "return true, if the receiver is a keyboard consumer;
       
  7223      Return true here, redefined from SimpleView."
       
  7224 
       
  7225     ^ self isReadOnly not
       
  7226 !
       
  7227 
       
  7228 specClass
       
  7229     "redefined, since the name of my specClass is nonStandard (i.e. not EditTextSpec)"
       
  7230 
       
  7231     self class == EditTextView ifTrue:[^ TextEditorSpec].
       
  7232     ^ super specClass
       
  7233 
       
  7234     "Modified: / 31.10.1997 / 19:48:19 / cg"
       
  7235 !
       
  7236 
       
  7237 tabMeansNextField
       
  7238     "return true, if a Tab character should shift focus."
       
  7239 
       
  7240     "if not readOnly, I want my tab keys ..."
       
  7241 
       
  7242     ^ self isReadOnly or:[tabMeansNextField]
       
  7243 
       
  7244     "Created: 7.2.1996 / 19:15:31 / cg"
       
  7245 !
       
  7246 
       
  7247 widthOfContents
       
  7248     "return the width of the contents in pixels
       
  7249      Redefined to add the size of a space (for the cursor).
       
  7250      this enables us to scroll one position further than the longest
       
  7251      line (and possibly see the cursor behind the line)"
       
  7252 
       
  7253     |w dev|
       
  7254 
       
  7255     w := super widthOfContents.
       
  7256     (dev := self graphicsDevice ) isNil ifTrue:[
       
  7257         "/ really don't know ...
       
  7258         dev := Screen current
       
  7259     ].
       
  7260     ^ w + (gc font widthOn:dev)
       
  7261 
       
  7262     "Modified: 28.5.1996 / 19:32:25 / cg"
       
  7263 ! !
       
  7264 
       
  7265 !EditTextView methodsFor:'realization'!
       
  7266 
       
  7267 realize
       
  7268     "make the view visible - scroll to make the cursor visible."
       
  7269 
       
  7270     super realize.
       
  7271 
       
  7272     self makeCursorVisible.
       
  7273     cursorFgColor := cursorFgColor onDevice:self graphicsDevice.
       
  7274     cursorBgColor := cursorBgColor onDevice:self graphicsDevice.
       
  7275 
       
  7276     "Modified: 20.12.1996 / 14:16:05 / cg"
       
  7277     "Created: 24.7.1997 / 18:24:12 / cg"
       
  7278 ! !
       
  7279 
       
  7280 !EditTextView methodsFor:'redrawing'!
       
  7281 
       
  7282 redrawCursorIfBetweenVisibleLine:startVisLine and:endVisLine
       
  7283     "redraw the cursor, if it sits in a line range"
       
  7284 
       
  7285     cursorShown ifTrue:[
       
  7286         cursorVisibleLine notNil ifTrue:[
       
  7287             (cursorVisibleLine between:startVisLine and:endVisLine) ifTrue:[
       
  7288                 self drawCursorCharacter
       
  7289             ]
       
  7290         ]
       
  7291     ]
       
  7292 !
       
  7293 
       
  7294 redrawCursorIfInVisibleLine:visLine
       
  7295     "redraw the cursor, if it sits in visible line"
       
  7296 
       
  7297     cursorShown ifTrue:[
       
  7298         (visLine == cursorVisibleLine) ifTrue:[
       
  7299             self drawCursorCharacter
       
  7300         ]
       
  7301     ]
       
  7302 !
       
  7303 
       
  7304 redrawFromVisibleLine:startVisLine to:endVisLine
       
  7305     "redraw a visible line range"
       
  7306 
       
  7307     super redrawFromVisibleLine:startVisLine to:endVisLine.
       
  7308     self redrawCursorIfBetweenVisibleLine:startVisLine and:endVisLine
       
  7309 !
       
  7310 
       
  7311 redrawVisibleLine:visLine
       
  7312     "redraw a visible line"
       
  7313 
       
  7314     super redrawVisibleLine:visLine.
       
  7315     self redrawCursorIfInVisibleLine:visLine
       
  7316 !
       
  7317 
       
  7318 redrawVisibleLine:visLine col:colNr
       
  7319     "redraw the single character in visibleline at colNr"
       
  7320 
       
  7321     super redrawVisibleLine:visLine col:colNr.
       
  7322     cursorShown ifTrue:[
       
  7323         (visLine == cursorVisibleLine) ifTrue:[
       
  7324             (colNr == cursorCol) ifTrue:[
       
  7325                 self drawCursorCharacter.
       
  7326                 ^ self
       
  7327             ]
       
  7328         ]
       
  7329     ].
       
  7330 
       
  7331     "Modified: / 05-11-2007 / 17:35:53 / cg"
       
  7332 !
       
  7333 
       
  7334 redrawVisibleLine:visLine from:startCol
       
  7335     "redraw a visible line from startCol to the end of line"
       
  7336 
       
  7337     super redrawVisibleLine:visLine from:startCol.
       
  7338     cursorShown ifTrue:[
       
  7339         self redrawCursorIfInVisibleLine:visLine
       
  7340     ]
       
  7341 !
       
  7342 
       
  7343 redrawVisibleLine:visLine from:startCol to:endCol
       
  7344     "redraw a visible line from startCol to endCol"
       
  7345 
       
  7346     super redrawVisibleLine:visLine from:startCol to:endCol.
       
  7347     self redrawCursorIfInVisibleLine:visLine
       
  7348 ! !
       
  7349 
       
  7350 !EditTextView methodsFor:'scrolling'!
       
  7351 
       
  7352 additionalMarginForHorizontalScroll
       
  7353     "return the number of pixels by which we may scroll more than the actual
       
  7354      width of the document would allow.
       
  7355      This is redefined by editable textViews, to allo for the cursor
       
  7356      to be visible if it is positioned right behind the longest line of text.
       
  7357      The default returned here is 10 pixels, which should be ok for most cursors"
       
  7358 
       
  7359     ^ 10 max:gc font width
       
  7360 !
       
  7361 
       
  7362 halfPageDown
       
  7363     "half a page down - to keep cursor on same visible line, it has to be moved
       
  7364      within the real text  "
       
  7365 
       
  7366     |prevCursorLine|
       
  7367 
       
  7368     prevCursorLine := cursorVisibleLine.
       
  7369     super halfPageDown.
       
  7370     self cursorVisibleLine:prevCursorLine col:cursorCol
       
  7371 !
       
  7372 
       
  7373 halfPageUp
       
  7374     "half a page up - to keep cursor on same visible line, it has to be moved
       
  7375      within the real text  "
       
  7376 
       
  7377     |prevCursorLine|
       
  7378 
       
  7379     prevCursorLine := cursorVisibleLine.
       
  7380     super halfPageUp.
       
  7381     self cursorVisibleLine:prevCursorLine col:cursorCol
       
  7382 !
       
  7383 
       
  7384 originChanged:delta
       
  7385     "sent after scrolling - have to show the cursor if it was on before"
       
  7386 
       
  7387     super originChanged:delta.
       
  7388     "
       
  7389      should we move the cursor with the scroll - or leave it ?
       
  7390     "
       
  7391     self updateCursorVisibleLine.
       
  7392     prevCursorState ifTrue:[
       
  7393         self showCursor
       
  7394     ]
       
  7395 
       
  7396     "Modified: / 17.6.1998 / 16:13:24 / cg"
       
  7397 !
       
  7398 
       
  7399 originWillChange
       
  7400     "sent before scrolling - have to hide the cursor"
       
  7401 
       
  7402     prevCursorState := cursorShown.
       
  7403     "/ cursorShown := false.
       
  7404     cursorShown ifTrue:[
       
  7405         self hideCursor
       
  7406     ]
       
  7407 
       
  7408     "Modified: / 6.7.1998 / 13:07:23 / cg"
       
  7409 !
       
  7410 
       
  7411 pageDown
       
  7412     "page down - to keep cursor on same visible line, it has to be moved
       
  7413      within the real text  "
       
  7414 
       
  7415     |prevCursorLine|
       
  7416 
       
  7417     prevCursorLine := cursorVisibleLine.
       
  7418     super pageDown.
       
  7419     self cursorVisibleLine:prevCursorLine col:cursorCol
       
  7420 !
       
  7421 
       
  7422 pageUp
       
  7423     "page up - to keep cursor on same visible line, it has to be moved
       
  7424      within the real text  "
       
  7425 
       
  7426     |prevCursorLine|
       
  7427 
       
  7428     prevCursorLine := cursorVisibleLine.
       
  7429     super pageUp.
       
  7430     self cursorVisibleLine:prevCursorLine col:cursorCol
       
  7431 ! !
       
  7432 
       
  7433 !EditTextView methodsFor:'searching'!
       
  7434 
       
  7435 searchBwd:pattern ifAbsent:aBlock
       
  7436     "do a backward search"
       
  7437 
       
  7438     self searchBwd:pattern ignoreCase:false ifAbsent:aBlock
       
  7439 !
       
  7440 
       
  7441 searchBwd:pattern ignoreCase:ign ifAbsent:aBlock
       
  7442     "do a backward search"
       
  7443 
       
  7444     cursorLine isNil ifTrue:[^ self].
       
  7445     super searchBwd:pattern ignoreCase:ign ifAbsent:aBlock
       
  7446 !
       
  7447 
       
  7448 searchBwd:pattern ignoreCase:ign startingAtLine:startLine col:startCol ifAbsent:aBlock
       
  7449     "do a backward search"
       
  7450 
       
  7451     cursorLine isNil ifTrue:[^ self].
       
  7452 
       
  7453     self
       
  7454         searchBackwardFor:pattern
       
  7455         ignoreCase:ign
       
  7456         startingAtLine:startLine col:startCol
       
  7457         ifFound:[:line :col |
       
  7458             self cursorMovementAllowed ifTrue:[
       
  7459                 self cursorLine:line col:col.
       
  7460             ].
       
  7461             self showMatch:pattern isMatch:false atLine:line col:col.
       
  7462 "/            self makeLineVisible:cursorLine
       
  7463             typeOfSelection := #search]
       
  7464         ifAbsent:aBlock
       
  7465 
       
  7466     "Modified: 9.10.1997 / 13:02:13 / cg"
       
  7467 !
       
  7468 
       
  7469 searchForAndSelectMatchingParenthesis
       
  7470     "select characters enclosed by matching parenthesis if one is under cusor"
       
  7471 
       
  7472     self searchForAndSelectMatchingParenthesisFromLine:cursorLine col:cursorCol
       
  7473 !
       
  7474 
       
  7475 searchForMatchingParenthesis
       
  7476     "search for a matching parenthesis starting at cursor position.
       
  7477      Search for the corresponding character is done forward if its an opening,
       
  7478      backwards if its a closing parenthesis.
       
  7479      Positions the cursor if found, peeps if not"
       
  7480 
       
  7481     self cursorMovementAllowed ifFalse:[^ self].
       
  7482 
       
  7483     self
       
  7484         searchForMatchingParenthesisFromLine:cursorLine col:cursorCol
       
  7485         ifFound:[:line :col | self cursorLine:line col:col]
       
  7486         ifNotFound:[self showNotFound]
       
  7487         onError:[self beep]
       
  7488 
       
  7489     "Modified: 9.10.1997 / 12:56:30 / cg"
       
  7490 !
       
  7491 
       
  7492 searchFwd:pattern ignoreCase:ign match: match startingAtLine:startLine col:startCol ifAbsent:aBlock
       
  7493     "do a forward search"
       
  7494 
       
  7495     cursorLine isNil ifTrue:[^ self].
       
  7496     self 
       
  7497         searchForwardFor:pattern 
       
  7498         ignoreCase:ign
       
  7499         match: match
       
  7500         startingAtLine:startLine col:startCol
       
  7501         ifFound:[:line :col |
       
  7502             self cursorMovementAllowed ifTrue:[
       
  7503                 self cursorLine:line col:col.
       
  7504             ].
       
  7505             self showMatch:pattern isMatch:match atLine:line col:col.
       
  7506 "/            self makeLineVisible:cursorLine
       
  7507             typeOfSelection := #search
       
  7508         ]
       
  7509         ifAbsent:aBlock
       
  7510 
       
  7511     "Modified: 9.10.1997 / 12:57:47 / cg"
       
  7512     "Created: 9.10.1997 / 13:01:12 / cg"
       
  7513 !
       
  7514 
       
  7515 searchFwd:pattern ignoreCase:ign startingAtLine:startLine col:startCol ifAbsent:aBlock
       
  7516     "do a forward search"
       
  7517 
       
  7518     self searchFwd:pattern ignoreCase:ign match: false startingAtLine:startLine col:startCol ifAbsent:aBlock
       
  7519 !
       
  7520 
       
  7521 searchFwd:pattern startingAtLine:startLine col:startCol ifAbsent:aBlock
       
  7522     "do a forward search"
       
  7523 
       
  7524     self searchFwd:pattern ignoreCase:false startingAtLine:startLine col:startCol ifAbsent:aBlock
       
  7525 !
       
  7526 
       
  7527 searchPatternForSearchBar
       
  7528 
       
  7529     "Returns the next searchPattern from the user selection or from the autoSearch"
       
  7530 
       
  7531     |searchPattern|
       
  7532 
       
  7533     searchPattern := self searchPatternFromUserSelectionOrReplace.
       
  7534     searchPattern isNil 
       
  7535         ifTrue: [searchPattern := lastSearchPattern]
       
  7536         ifFalse: [lastSearchPattern := searchPattern].
       
  7537     ^ searchPattern
       
  7538 !
       
  7539 
       
  7540 setSearchPatternWithMatchEscapes: match
       
  7541     "set the searchpattern from the selection if there is one, and position
       
  7542      cursor to start of pattern"
       
  7543 
       
  7544     |sel|
       
  7545 
       
  7546     "/
       
  7547     "/ if the last operation was a replace, set pattern to last
       
  7548     "/ original string (for search after again)
       
  7549     "/ for cut or delete actions allow lastReplacement with nil
       
  7550     "/
       
  7551 "/    (lastStringFromReplaceForNextSearch notNil
       
  7552 "/     and:[typeOfSelection ~~ #search]) ifTrue:[
       
  7553 "/        lastStringFromReplaceForNextSearch isString ifTrue:[
       
  7554 "/            lastSearchPattern := lastStringFromReplaceForNextSearch.
       
  7555 "/        ] ifFalse:[
       
  7556 "/            lastSearchPattern := lastStringFromReplaceForNextSearch asStringWithoutFinalCR.
       
  7557 "/        ].
       
  7558 "/        ^ self
       
  7559 "/    ].
       
  7560 
       
  7561     "/
       
  7562     "/ if there is a selection:
       
  7563     "/    if there was no previous search, take it as search pattern.
       
  7564     "/    if there was a previous search, only take the selection if
       
  7565     "/    it did not result from a paste or from the last search itself.
       
  7566     "/    (to allow search-paste to be repeated)
       
  7567     "/
       
  7568     sel := self selection.
       
  7569     sel notNil ifTrue:[
       
  7570         (lastSearchPattern isNil
       
  7571         or:[typeOfSelection ~~ #paste and:[typeOfSelection ~~ #search]]
       
  7572         ) ifTrue:[
       
  7573             self cursorLine:selectionStartLine col:selectionStartCol.
       
  7574             lastSearchPattern := sel asStringWithoutFinalCR.
       
  7575             match ifTrue:[lastSearchPattern := lastSearchPattern withMatchEscapes].
       
  7576         ]
       
  7577     ]
       
  7578 
       
  7579     "Modified: / 07-05-2011 / 17:25:59 / cg"
       
  7580 !
       
  7581 
       
  7582 showMatch:pattern isMatch:isMatch atLine:line col:col
       
  7583     super showMatch:pattern isMatch:isMatch atLine:line col:col.
       
  7584     typeOfSelection := #search.
       
  7585 !
       
  7586 
       
  7587 startPositionForSearchBackward
       
  7588     ^ self startPositionForSearchBackwardBasedOnCursorOrSelection
       
  7589 !
       
  7590 
       
  7591 startPositionForSearchBackwardBasedOnCursorOrSelection
       
  7592     |startLine startCol|
       
  7593 
       
  7594     selectionStartLine notNil ifTrue:[
       
  7595         startLine := selectionStartLine.
       
  7596         startCol := selectionStartCol
       
  7597     ] ifFalse:[
       
  7598         cursorLine isNil ifTrue:[
       
  7599             startLine := list size.
       
  7600             startCol := self listAt:startLine size.
       
  7601         ] ifFalse:[
       
  7602             startLine := cursorLine min:list size.
       
  7603             startCol := cursorCol
       
  7604         ]
       
  7605     ].
       
  7606 
       
  7607     ^ startCol @ cursorLine
       
  7608 !
       
  7609 
       
  7610 startPositionForSearchForward
       
  7611     ^ self startPositionForSearchForwardBasedOnCursorOrSelection
       
  7612 !
       
  7613 
       
  7614 startPositionForSearchForwardBasedOnCursorOrSelection
       
  7615     |startCol|
       
  7616 
       
  7617     "/ if there is no selection and the cursor is at the origin,
       
  7618     "/ assume its the first search and do not skip the very first match
       
  7619     startCol := cursorCol.
       
  7620     self hasSelection ifTrue:[
       
  7621         ^ selectionEndCol @ selectionEndLine.
       
  7622     ] ifFalse:[
       
  7623         (cursorLine == 1 and:[cursorCol == 1]) ifTrue:[
       
  7624             startCol := 0
       
  7625         ].
       
  7626         startCol := startCol min:(self at:cursorLine) size
       
  7627     ].
       
  7628 
       
  7629     ^ startCol @ cursorLine
       
  7630 
       
  7631     "Modified (format): / 24-05-2012 / 13:58:37 / cg"
       
  7632 ! !
       
  7633 
       
  7634 !EditTextView methodsFor:'selections'!
       
  7635 
       
  7636 addToSelectionAfter:aBlock
       
  7637     "Pokud existuje selekce, upravi ji
       
  7638      podle aktualni pozice kurzoru a pozice
       
  7639      po provedeni blocku.
       
  7640      Urceno k implementaci Shift-Home a Shift-End
       
  7641      Nejak nevim, jak to presneji popsat :-)"
       
  7642 
       
  7643     |startLine startCol endLine endCol |
       
  7644 
       
  7645     self hasSelection ifTrue: [
       
  7646         startLine := selectionStartLine .
       
  7647         startCol := selectionStartCol .
       
  7648         endLine := selectionEndLine .
       
  7649         endCol := selectionEndCol .
       
  7650     ] ifFalse: [
       
  7651         startLine := endLine :=  cursorLine .
       
  7652         startCol := endCol := cursorCol .
       
  7653     ].
       
  7654 
       
  7655     "deselectim a provedu presun kurzoru..."
       
  7656     self unselect .
       
  7657     aBlock value .
       
  7658 
       
  7659     "funguje dost mizerne, jen na jednom radku..."
       
  7660     (startCol - cursorCol) abs <= (endCol - cursorCol) abs
       
  7661         ifTrue: [
       
  7662             startCol := cursorCol.
       
  7663         ] ifFalse: [
       
  7664             endCol := cursorCol - 1.
       
  7665         ].
       
  7666     self selectFromLine:startLine col:startCol toLine: endLine col:endCol .
       
  7667 !
       
  7668 
       
  7669 autoMoveCursorToEndOfSelection
       
  7670     "return true, if the cursor should be automatically moved to the
       
  7671      end of a selection.
       
  7672      Redefined to return false in terminalViews, where the cursor should
       
  7673      not be affected by selecting"
       
  7674 
       
  7675     ^ true
       
  7676 !
       
  7677 
       
  7678 changeTypeOfSelectionTo:newType
       
  7679     typeOfSelection ~~ newType ifTrue:[
       
  7680         typeOfSelection := newType.
       
  7681         selectionStartLine notNil ifTrue:[
       
  7682             self
       
  7683                 redrawFromLine:selectionStartLine col:selectionStartCol
       
  7684                 toLine:selectionEndLine col:selectionEndCol
       
  7685         ].
       
  7686     ].
       
  7687 !
       
  7688 
       
  7689 findNextWordAfterSelectionAndAddToSelection
       
  7690     |selStartCol selStartLine selEndCol selEndLine|
       
  7691 
       
  7692     selectionStartCol isNil ifTrue:[
       
  7693         self selectWordUnderCursor.
       
  7694         ^ self
       
  7695     ].
       
  7696 
       
  7697     selStartCol := selectionStartCol.
       
  7698     selEndCol := selectionEndCol.
       
  7699     selStartLine := selectionStartLine.
       
  7700     selEndLine := selectionEndLine.
       
  7701 
       
  7702     self cursorToNextWord.
       
  7703     self selectWordUnderCursor.
       
  7704 
       
  7705     self selectFromLine:selStartLine col:selStartCol toLine:selectionEndLine col:selectionEndCol.
       
  7706 !
       
  7707 
       
  7708 searchPatternFromUserSelectionOrReplace
       
  7709 
       
  7710     |sel searchPattern|
       
  7711 
       
  7712     "/
       
  7713     "/ if the last operation was a replace, set pattern to last
       
  7714     "/ original string (for search after again)
       
  7715     "/
       
  7716     (lastStringFromReplaceForNextSearch notNil
       
  7717      and:[typeOfSelection ~~ #search]) ifTrue:[
       
  7718         lastStringFromReplaceForNextSearch isString ifTrue:[
       
  7719             searchPattern := lastStringFromReplaceForNextSearch.
       
  7720         ] ifFalse:[
       
  7721             searchPattern := lastStringFromReplaceForNextSearch asStringWithoutFinalCR.
       
  7722         ].
       
  7723         ^ searchPattern
       
  7724     ].
       
  7725 
       
  7726     "/
       
  7727     "/ if there is a selection:
       
  7728     "/    if there was no previous search, take it as search pattern.
       
  7729     "/    if there was a previous search, only take the selection if
       
  7730     "/    it did not result from a paste.
       
  7731     "/    (to allow search-paste to be repeated)
       
  7732     "/
       
  7733     sel := self selection.
       
  7734     sel notNil ifTrue:[
       
  7735         typeOfSelection ~~ #search ifTrue:[
       
  7736             typeOfSelection ~~ #paste ifTrue:[
       
  7737                 self cursorLine:selectionStartLine col:selectionStartCol.
       
  7738                 searchPattern := sel asStringWithoutFinalCR.
       
  7739             ]
       
  7740         ].
       
  7741     ].
       
  7742 
       
  7743     ^ searchPattern
       
  7744 !
       
  7745 
       
  7746 selectAll
       
  7747     "select the whole text.
       
  7748      redefined to send super selectFrom... since we dont want the
       
  7749      cursor to be moved in this case."
       
  7750 
       
  7751     list isNil ifTrue:[
       
  7752         self unselect
       
  7753     ] ifFalse:[
       
  7754         super selectFromLine:1 col:1 toLine:(list size + 1) col:0.
       
  7755         typeOfSelection := nil
       
  7756     ]
       
  7757 
       
  7758     "Modified: 28.2.1997 / 19:14:54 / cg"
       
  7759 !
       
  7760 
       
  7761 selectAllInitially
       
  7762     "select the whole text. This is called only once during the initialization
       
  7763      for editFields which are shown in a table or tree.
       
  7764      The selectAll is called via this method to allow for easier redefinition and
       
  7765      to distinguish auto-select from user-initiated selects."
       
  7766 
       
  7767     self selectAll
       
  7768 !
       
  7769 
       
  7770 selectCursorLine
       
  7771     "select cursorline"
       
  7772 
       
  7773     self selectFromLine:cursorLine col:1 toLine:cursorLine+1 col:0
       
  7774 !
       
  7775 
       
  7776 selectCursorLineFromBeginning
       
  7777     "select cursorline up to cursor position"
       
  7778 
       
  7779     cursorCol > 1 ifTrue:[
       
  7780         self selectFromLine:cursorLine col:1
       
  7781                      toLine:cursorLine col:(cursorCol-1)
       
  7782     ]
       
  7783 
       
  7784     "Modified: 16.8.1996 / 19:14:14 / cg"
       
  7785 !
       
  7786 
       
  7787 selectExpandCursorLine
       
  7788     "expand selection by one line or select cursorline"
       
  7789 
       
  7790     selectionStartLine isNil ifTrue:[
       
  7791         self selectCursorLine
       
  7792     ] ifFalse:[
       
  7793         self selectFromLine:selectionStartLine col:selectionStartCol
       
  7794                      toLine:cursorLine+1 col:0.
       
  7795         self makeLineVisible:selectionEndLine
       
  7796     ]
       
  7797 !
       
  7798 
       
  7799 selectFromBeginOfLine
       
  7800     "select the text from the beginning of the current line to the current cursor position."
       
  7801 
       
  7802     | newCursorCol ln |
       
  7803 
       
  7804     list isNil ifTrue:[
       
  7805         self unselect
       
  7806     ] ifFalse:[
       
  7807         cursorCol > 1 ifTrue:[
       
  7808             ln := list at: cursorLine.
       
  7809             newCursorCol := ln notEmptyOrNil ifTrue:[ln indexOfNonSeparator] ifFalse:[1].
       
  7810             self selectFromLine:cursorLine col:newCursorCol toLine:cursorLine col:cursorCol-1.
       
  7811             cursorCol := newCursorCol.
       
  7812             typeOfSelection := nil
       
  7813         ]
       
  7814     ]
       
  7815 
       
  7816     "Created: / 28-06-2011 / 22:47:04 / cg"
       
  7817     "Modified: / 18-07-2012 / 17:00:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
  7818 !
       
  7819 
       
  7820 selectFromBeginning
       
  7821     "select the text from the beginning to the current cursor position."
       
  7822 
       
  7823     |col|
       
  7824 
       
  7825     list isNil ifTrue:[
       
  7826         self unselect
       
  7827     ] ifFalse:[
       
  7828         cursorCol == 0 ifTrue:[
       
  7829             col := 0
       
  7830         ] ifFalse:[
       
  7831             col := cursorCol - 1
       
  7832         ].
       
  7833         super selectFromLine:1 col:1 toLine:cursorLine col:col.
       
  7834         typeOfSelection := nil
       
  7835     ]
       
  7836 !
       
  7837 
       
  7838 selectFromLine:startLine col:startCol toLine:endLine col:endCol
       
  7839     "when a range is selected, position the cursor behind the selection
       
  7840      for easier editing. Also typeOfSelection is nilled here."
       
  7841 
       
  7842     super selectFromLine:startLine col:startCol toLine:endLine col:endCol.
       
  7843     (selectionEndLine notNil and:[self autoMoveCursorToEndOfSelection]) ifTrue:[
       
  7844         self cursorLine:selectionEndLine col:(selectionEndCol + 1).
       
  7845     ].
       
  7846     typeOfSelection := nil
       
  7847 !
       
  7848 
       
  7849 selectToEndOfLine
       
  7850     "select the text from the current cursor position to the end of the current line"
       
  7851 
       
  7852     | newCursorCol line |
       
  7853 
       
  7854     list isNil ifTrue:[
       
  7855         self unselect
       
  7856     ] ifFalse:[
       
  7857         cursorCol >= 1 ifTrue:[
       
  7858             line := list at: cursorLine.
       
  7859             newCursorCol := line size.
       
  7860             [ newCursorCol > 1 and:[(line at:newCursorCol) isSeparator] ]      
       
  7861                 whileTrue:[newCursorCol := newCursorCol - 1].
       
  7862 
       
  7863             self selectFromLine:cursorLine col:cursorCol toLine:cursorLine col: newCursorCol.
       
  7864             cursorCol := newCursorCol.
       
  7865             typeOfSelection := nil
       
  7866         ]
       
  7867     ]
       
  7868 
       
  7869     "Created: / 28-06-2011 / 23:07:07 / cg"
       
  7870     "Modified: / 30-06-2011 / 19:51:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
  7871 !
       
  7872 
       
  7873 selectUpToEnd
       
  7874     "select the text from the current cursor position to the end."
       
  7875 
       
  7876     list isNil ifTrue:[
       
  7877         self unselect
       
  7878     ] ifFalse:[
       
  7879         super selectFromLine:cursorLine col:cursorCol toLine:(list size + 1) col:0.
       
  7880         typeOfSelection := nil
       
  7881     ]
       
  7882 !
       
  7883 
       
  7884 selectWordUnderCursor
       
  7885     "select the word under the cursor"
       
  7886 
       
  7887     self selectWordAtLine:cursorLine col:cursorCol
       
  7888 !
       
  7889 
       
  7890 unselect
       
  7891     "forget and unhilight selection - must take care of cursor here"
       
  7892 
       
  7893     |wasOn|
       
  7894 
       
  7895     wasOn := self hideCursor.
       
  7896     super unselect.
       
  7897     typeOfSelection := nil.
       
  7898     wasOn ifTrue:[self showCursor]
       
  7899 ! !
       
  7900 
       
  7901 !EditTextView methodsFor:'undo & again'!
       
  7902 
       
  7903 addUndo:action
       
  7904     ^ undoSupport addUndo:action.
       
  7905 !
       
  7906 
       
  7907 again
       
  7908     "repeat the last action (which was a cut or replace).
       
  7909      If current selection is not last string, search forward to
       
  7910      next occurrence of it before repeating the last operation."
       
  7911 
       
  7912     |s l c sel savedSelectStyle startColForSearch 
       
  7913      lastStringToReplace lastReplaceIgnoredCase lastReplaceWasMatch|
       
  7914 
       
  7915     lastStringToReplace := lastReplacementInfo lastStringToReplace.
       
  7916     lastStringToReplace isNil ifTrue:[
       
  7917         ^ false
       
  7918     ].
       
  7919     lastReplaceIgnoredCase := lastReplacementInfo lastReplaceIgnoredCase.
       
  7920     lastReplaceWasMatch := lastReplacementInfo lastReplaceWasMatch.
       
  7921 
       
  7922     self undoableDo:[
       
  7923         s := lastStringToReplace asString.
       
  7924         "remove final cr"
       
  7925         (s endsWith:Character cr) ifTrue:[s := s copyButLast:1].
       
  7926     "/        s := s withoutSpaces.        "XXX - replacing text with spaces ..."
       
  7927 
       
  7928         "set lastStringToReplace as the next search string 
       
  7929          and set lastReplaceIgnoredCase as the next search ignored case flag"
       
  7930         lastStringFromReplaceForNextSearch := s.
       
  7931         lastSearchIgnoredCase := lastReplaceIgnoredCase.
       
  7932 
       
  7933         savedSelectStyle := selectStyle.
       
  7934         selectStyle := nil.
       
  7935 
       
  7936         sel := self selection.
       
  7937 
       
  7938         "if we are already there (after a find), ommit search"
       
  7939 
       
  7940         (sel notNil and:[sel asString withoutSeparators = s]) ifTrue:[
       
  7941             l := selectionStartLine "cursorLine".
       
  7942             c := selectionStartCol "cursorCol".
       
  7943             self deleteSelection.
       
  7944             lastReplacementInfo lastReplacement notNil ifTrue:[
       
  7945                 self insertLines:lastReplacementInfo lastReplacement asStringCollection withCR:false.
       
  7946                 self selectFromLine:l col:c toLine:cursorLine col:(cursorCol - 1).
       
  7947                 typeOfSelection := #paste
       
  7948             ].
       
  7949             selectStyle := savedSelectStyle.
       
  7950             ^ true
       
  7951         ].
       
  7952 
       
  7953         sel isEmptyOrNil ifTrue:[
       
  7954             startColForSearch := cursorCol - 1
       
  7955         ] ifFalse:[
       
  7956             startColForSearch := selectionEndCol ? (cursorCol - 1)
       
  7957         ].
       
  7958         self 
       
  7959             searchForwardFor:s
       
  7960             ignoreCase: lastReplaceIgnoredCase 
       
  7961             match: lastReplaceWasMatch 
       
  7962             startingAtLine:cursorLine col:startColForSearch
       
  7963             ifFound:
       
  7964                 [
       
  7965                     :line :col |
       
  7966 
       
  7967                     |repl|
       
  7968 
       
  7969                     self selectFromLine:line col:col
       
  7970                                  toLine:line col:(col + s size - 1).
       
  7971                     self makeLineVisible:line.
       
  7972 
       
  7973                     self deleteSelection.
       
  7974                     lastReplacementInfo lastReplacement notNil ifTrue:[
       
  7975                         lastReplacementInfo lastReplacement isString ifFalse:[
       
  7976                             repl := lastReplacementInfo lastReplacement asString "withoutSpaces"
       
  7977                         ] ifTrue:[
       
  7978                             repl := lastReplacementInfo lastReplacement "withoutSpaces".
       
  7979                         ].
       
  7980                         self insertLines:repl asStringCollection withCR:false.
       
  7981                         self selectFromLine:line col:col toLine:cursorLine col:(cursorCol - 1).
       
  7982                         undoSupport actionInfo:'replace'.
       
  7983                     ].
       
  7984                     selectStyle := savedSelectStyle.
       
  7985                     typeOfSelection := #paste.
       
  7986                     ^ true
       
  7987                 ]
       
  7988             ifAbsent:
       
  7989                 [
       
  7990                     self sensor compressKeyPressEventsWithKey:#Again.
       
  7991                     self showNotFound.
       
  7992                     selectStyle := savedSelectStyle.
       
  7993                     ^ false
       
  7994                 ].
       
  7995     ].
       
  7996 
       
  7997     ^ true.
       
  7998 
       
  7999     "Modified: 9.10.1996 / 16:14:11 / cg"
       
  8000 !
       
  8001 
       
  8002 hasRedoAction
       
  8003     ^ undoSupport hasRedoAction.
       
  8004 !
       
  8005 
       
  8006 hasUndoAction
       
  8007     ^ undoSupport hasUndoAction.
       
  8008 !
       
  8009 
       
  8010 multipleAgain
       
  8011     "repeat the last action (which was a cut or replace) until search fails"
       
  8012 
       
  8013     [self again] whileTrue:[]
       
  8014 !
       
  8015 
       
  8016 nonUndoableDo:aBlock
       
  8017     undoSupport nonUndoableDo:aBlock.
       
  8018 !
       
  8019 
       
  8020 redo
       
  8021     "undo the last undo"
       
  8022 
       
  8023     undoSupport hasRedoAction ifFalse:[
       
  8024         self beep
       
  8025     ] ifTrue:[
       
  8026         undoSupport redo.
       
  8027     ]
       
  8028 !
       
  8029 
       
  8030 undo
       
  8031     "undo the last edit operation"
       
  8032 
       
  8033     undoSupport hasUndoAction ifFalse:[
       
  8034         self beep
       
  8035     ] ifTrue:[
       
  8036         undoSupport undo.
       
  8037     ]
       
  8038 !
       
  8039 
       
  8040 undoableDo:aBlock
       
  8041     self undoableDo:aBlock info:nil.
       
  8042 
       
  8043     "Modified: / 28-07-2007 / 13:20:14 / cg"
       
  8044 !
       
  8045 
       
  8046 undoableDo:aBlock info:aString
       
  8047     self checkModificationsAllowed ifFalse:[
       
  8048         "/ will trigger an error-dialog there (no need for undo-carekeeping)
       
  8049         aBlock value.
       
  8050     ] ifTrue:[
       
  8051         undoSupport undoableDo:aBlock info:aString.
       
  8052     ].
       
  8053 
       
  8054     "Modified: / 28-07-2007 / 13:21:00 / cg"
       
  8055 ! !
       
  8056 
       
  8057 !EditTextView::EditAction class methodsFor:'instance creation'!
       
  8058 
       
  8059 line1:arg1 col1:arg2 line2:arg3 col2:arg4
       
  8060     ^ self new line1:arg1 col1:arg2 line2:arg3 col2:arg4
       
  8061 !
       
  8062 
       
  8063 line1:arg1 col1:arg2 line2:arg3 col2:arg4 info:info
       
  8064     ^ (self new line1:arg1 col1:arg2 line2:arg3 col2:arg4) info:info
       
  8065 !
       
  8066 
       
  8067 line:arg1 col:arg2 character:arg3
       
  8068     ^ self new line:arg1 col:arg2 character:arg3
       
  8069 !
       
  8070 
       
  8071 line:arg1 col:arg2 character:arg3 info:info
       
  8072     ^ (self new line:arg1 col:arg2 character:arg3) info:info
       
  8073 !
       
  8074 
       
  8075 line:arg1 col:arg2 characters:arg3 info:info
       
  8076     ^ (self new line:arg1 col:arg2 characters:arg3) info:info
       
  8077 !
       
  8078 
       
  8079 line:arg1 col:arg2 info:arg3
       
  8080     ^ self new line:arg1 col:arg2 info:arg3
       
  8081 !
       
  8082 
       
  8083 line:arg1 col:arg2 string:arg3
       
  8084     ^ self new line:arg1 col:arg2 string:arg3
       
  8085 !
       
  8086 
       
  8087 line:arg1 col:arg2 string:arg3 info:info
       
  8088     ^ (self new line:arg1 col:arg2 string:arg3) info:info
       
  8089 !
       
  8090 
       
  8091 line:arg1 string:arg3 info:info
       
  8092     ^ (self new line:arg1 string:arg3) info:info
       
  8093 !
       
  8094 
       
  8095 text:arg info:info
       
  8096     ^ (self new text:arg) info:info
       
  8097 ! !
       
  8098 
       
  8099 !EditTextView::EditAction methodsFor:'accessing'!
       
  8100 
       
  8101 info
       
  8102     ^ userFriendlyInfo
       
  8103 !
       
  8104 
       
  8105 info:aString
       
  8106     userFriendlyInfo := aString
       
  8107 ! !
       
  8108 
       
  8109 !EditTextView::EditAction methodsFor:'combining'!
       
  8110 
       
  8111 canCombineWithPreviousPasteStringAction: aPasteStringAction
       
  8112     ^ false.
       
  8113 
       
  8114     "Created: / 25-09-2006 / 12:16:25 / cg"
       
  8115 ! !
       
  8116 
       
  8117 !EditTextView::EditAction methodsFor:'queries'!
       
  8118 
       
  8119 canCombineWithNext:nextAction
       
  8120     ^ false
       
  8121 ! !
       
  8122 
       
  8123 !EditTextView::DeleteRange methodsFor:'accessing'!
       
  8124 
       
  8125 line1:line1Arg col1:col1Arg line2:line2Arg col2:col2Arg
       
  8126     "set instance variables (automatically generated)"
       
  8127 
       
  8128     self assert:(line1Arg notNil).
       
  8129     self assert:(col1Arg notNil).
       
  8130     self assert:(line2Arg notNil).
       
  8131     self assert:(col2Arg notNil).
       
  8132 
       
  8133     line1 := line1Arg.
       
  8134     col1 := col1Arg.
       
  8135     line2 := line2Arg.
       
  8136     col2 := col2Arg.
       
  8137 ! !
       
  8138 
       
  8139 !EditTextView::DeleteRange methodsFor:'execution'!
       
  8140 
       
  8141 executeIn:editor
       
  8142     editor unselect.
       
  8143     editor
       
  8144         deleteFromLine:line1
       
  8145         col:col1
       
  8146         toLine:line2
       
  8147         col:col2.
       
  8148     editor cursorLine:line1 col:col1.
       
  8149 ! !
       
  8150 
       
  8151 !EditTextView::DeleteCharacters methodsFor:'accessing'!
       
  8152 
       
  8153 col1
       
  8154     ^ col1
       
  8155 !
       
  8156 
       
  8157 col2
       
  8158     ^ col2
       
  8159 !
       
  8160 
       
  8161 line
       
  8162     ^ line
       
  8163 !
       
  8164 
       
  8165 line:lineArg col1:col1Arg col2:col2Arg
       
  8166     "set instance variables (automatically generated)"
       
  8167 
       
  8168     self assert:(lineArg notNil).
       
  8169     self assert:(col1Arg notNil).
       
  8170     self assert:(col2Arg notNil).
       
  8171 
       
  8172     line := lineArg.
       
  8173     col1 := col1Arg.
       
  8174     col2 := col2Arg.
       
  8175 !
       
  8176 
       
  8177 line:lineArg col:colArg info:infoArg
       
  8178     self assert:(lineArg notNil).
       
  8179     self assert:(colArg notNil).
       
  8180 
       
  8181     line := lineArg.
       
  8182     col1 := col2 := colArg.
       
  8183     self info:infoArg.
       
  8184 ! !
       
  8185 
       
  8186 !EditTextView::DeleteCharacters methodsFor:'combining'!
       
  8187 
       
  8188 canCombineWithNext:anotherAction
       
  8189     ^ anotherAction perform:#canCombineWithPreviousDeleteCharactersAction: with:self ifNotUnderstood:false
       
  8190 !
       
  8191 
       
  8192 canCombineWithPreviousDeleteCharactersAction:previousDeleteAction
       
  8193     "I will combine only if we both are single character deletes,
       
  8194      and my col-to-delete is the next after anotherDeleteActions col-to-delete.
       
  8195      (i.e. single-character typing)"
       
  8196 
       
  8197     previousDeleteAction line == line ifTrue:[
       
  8198         previousDeleteAction col2 == (col1-1) ifTrue:[
       
  8199             ^ true
       
  8200         ].
       
  8201     ].
       
  8202 
       
  8203     ^ false
       
  8204 !
       
  8205 
       
  8206 combineWithNext:nextDeleteAction
       
  8207     self assert:(line == nextDeleteAction line).
       
  8208     self assert:(col2 == (nextDeleteAction col1 - 1)).
       
  8209 
       
  8210     col2 := nextDeleteAction col2.
       
  8211     userFriendlyInfo := 'insert ' , (col2 - col1 + 1) printString
       
  8212 ! !
       
  8213 
       
  8214 !EditTextView::DeleteCharacters methodsFor:'execution'!
       
  8215 
       
  8216 executeIn:editor
       
  8217     editor unselect.
       
  8218     editor
       
  8219         deleteFromLine:line
       
  8220         col:col1
       
  8221         toLine:line
       
  8222         col:col2.
       
  8223     editor cursorLine:line col:col1.
       
  8224 ! !
       
  8225 
       
  8226 !EditTextView::EditMode class methodsFor:'constants'!
       
  8227 
       
  8228 insertAndSelectMode
       
  8229     ^ InsertAndSelectMode
       
  8230 !
       
  8231 
       
  8232 insertMode
       
  8233     ^ InsertMode
       
  8234 !
       
  8235 
       
  8236 overwriteMode
       
  8237     ^ OverwriteMode
       
  8238 ! !
       
  8239 
       
  8240 !EditTextView::EditMode class methodsFor:'queries'!
       
  8241 
       
  8242 isInsertAndSelectMode
       
  8243     ^ false
       
  8244 !
       
  8245 
       
  8246 isInsertMode
       
  8247     ^ false
       
  8248 !
       
  8249 
       
  8250 symbolicName
       
  8251     self subclassResponsibility
       
  8252 ! !
       
  8253 
       
  8254 !EditTextView::EditMode::InsertAndSelectMode class methodsFor:'info'!
       
  8255 
       
  8256 infoPrintString
       
  8257     ^ 'IS'
       
  8258 ! !
       
  8259 
       
  8260 !EditTextView::EditMode::InsertAndSelectMode class methodsFor:'queries'!
       
  8261 
       
  8262 isInsertAndSelectMode
       
  8263     ^ true
       
  8264 !
       
  8265 
       
  8266 isInsertMode
       
  8267     ^ true
       
  8268 ! !
       
  8269 
       
  8270 !EditTextView::EditMode::InsertMode class methodsFor:'info'!
       
  8271 
       
  8272 infoPrintString
       
  8273     ^ 'I'
       
  8274 ! !
       
  8275 
       
  8276 !EditTextView::EditMode::InsertMode class methodsFor:'queries'!
       
  8277 
       
  8278 isInsertMode
       
  8279     ^ true
       
  8280 ! !
       
  8281 
       
  8282 !EditTextView::EditMode::OverwriteMode class methodsFor:'info'!
       
  8283 
       
  8284 infoPrintString
       
  8285     ^ 'O'
       
  8286 ! !
       
  8287 
       
  8288 !EditTextView::LastReplacementInfo methodsFor:'accessing'!
       
  8289 
       
  8290 lastReplaceIgnoredCase
       
  8291     ^ lastReplaceIgnoredCase ? false
       
  8292 !
       
  8293 
       
  8294 lastReplaceIgnoredCase:something
       
  8295     lastReplaceIgnoredCase := something.
       
  8296 !
       
  8297 
       
  8298 lastReplaceWasMatch
       
  8299     ^ lastReplaceWasMatch ? false
       
  8300 !
       
  8301 
       
  8302 lastReplaceWasMatch:something
       
  8303     lastReplaceWasMatch := something.
       
  8304 !
       
  8305 
       
  8306 lastReplacement
       
  8307     ^ lastReplacement
       
  8308 !
       
  8309 
       
  8310 lastReplacement:something
       
  8311 "/Transcript showCR: 'lastReplacement:', something printString.
       
  8312     lastReplacement := something.
       
  8313 !
       
  8314 
       
  8315 lastStringToReplace
       
  8316     ^ lastStringToReplace
       
  8317 !
       
  8318 
       
  8319 lastStringToReplace:something
       
  8320     lastStringToReplace := something.
       
  8321 !
       
  8322 
       
  8323 previousReplacements
       
  8324     ^ previousReplacements ? #()
       
  8325 !
       
  8326 
       
  8327 stillCollectingInput
       
  8328     ^ stillCollectingInput
       
  8329 !
       
  8330 
       
  8331 stillCollectingInput:aBoolean
       
  8332     stillCollectingInput := aBoolean.
       
  8333 ! !
       
  8334 
       
  8335 !EditTextView::LastReplacementInfo methodsFor:'history'!
       
  8336 
       
  8337 rememberReplacement
       
  8338     "remember the previous replacement (called when a new one appears).
       
  8339      Mostly for the benefit of the code completion..."
       
  8340 
       
  8341     |oldString newString|
       
  8342 
       
  8343     oldString := lastStringToReplace.
       
  8344     newString := lastReplacement.
       
  8345     (oldString notEmptyOrNil and:[newString notEmptyOrNil]) ifTrue:[
       
  8346         previousReplacements isNil ifTrue:[
       
  8347             previousReplacements := OrderedCollection new.
       
  8348         ].
       
  8349         previousReplacements := previousReplacements reject:[:entry | entry key = oldString].
       
  8350         previousReplacements addFirst:(oldString -> newString).
       
  8351         previousReplacements size > 20 ifTrue:[
       
  8352             previousReplacements removeLast.
       
  8353         ]
       
  8354     ].
       
  8355 ! !
       
  8356 
       
  8357 !EditTextView::PasteString methodsFor:'accessing'!
       
  8358 
       
  8359 col
       
  8360     ^ col
       
  8361 
       
  8362     "Created: / 25-09-2006 / 12:19:59 / cg"
       
  8363 !
       
  8364 
       
  8365 col2
       
  8366     ^ col + string size - 1
       
  8367 
       
  8368     "Created: / 25-09-2006 / 12:20:18 / cg"
       
  8369 !
       
  8370 
       
  8371 line
       
  8372     ^ line
       
  8373 
       
  8374     "Created: / 25-09-2006 / 12:21:08 / cg"
       
  8375 !
       
  8376 
       
  8377 line:lineArg col:colArg string:stringArg
       
  8378     self assert:(lineArg notNil).
       
  8379     self assert:(colArg notNil).
       
  8380     self assert:(stringArg notNil).
       
  8381 
       
  8382     line := lineArg.
       
  8383     col := colArg.
       
  8384     string := stringArg.
       
  8385 !
       
  8386 
       
  8387 line:lineArg col:colArg string:stringArg selected:selectedArg
       
  8388     self assert:(lineArg notNil).
       
  8389     self assert:(colArg notNil).
       
  8390     self assert:(stringArg notNil).
       
  8391 
       
  8392     line := lineArg.
       
  8393     col := colArg.
       
  8394     string := stringArg.
       
  8395     selected := selectedArg.
       
  8396 !
       
  8397 
       
  8398 string
       
  8399     ^ string
       
  8400 
       
  8401     "Created: / 25-09-2006 / 12:25:59 / cg"
       
  8402 ! !
       
  8403 
       
  8404 !EditTextView::PasteString methodsFor:'combining'!
       
  8405 
       
  8406 canCombineWithNext:anotherAction
       
  8407     ^ anotherAction canCombineWithPreviousPasteStringAction:self
       
  8408 
       
  8409     "Created: / 25-09-2006 / 12:15:59 / cg"
       
  8410 !
       
  8411 
       
  8412 canCombineWithPreviousPasteStringAction: previousPasteAction
       
  8413     "I will combine only if we both are single character inserts,
       
  8414      and my col-to-insert is the next after anotherInsertActions end-col.
       
  8415      (i.e. single-character deletes)"
       
  8416 
       
  8417     previousPasteAction line == line ifTrue:[
       
  8418         previousPasteAction col == (self col2+1) ifTrue:[
       
  8419             ^ true
       
  8420         ].
       
  8421     ].
       
  8422 
       
  8423     ^ false
       
  8424 
       
  8425     "Modified: / 25-09-2006 / 12:22:21 / cg"
       
  8426 !
       
  8427 
       
  8428 combineWithNext:nextPasteAction
       
  8429     |s1 s2|
       
  8430 
       
  8431     self assert:(line == nextPasteAction line).
       
  8432     self assert:((col - 1) == (nextPasteAction col2)).
       
  8433 
       
  8434     s1 := nextPasteAction string.
       
  8435     s1 isString ifFalse:[s1 := s1 asStringWith:nil].
       
  8436     s2 := string.
       
  8437     s2 isString ifFalse:[s2 := s2 asStringWith:nil].
       
  8438 
       
  8439     string := s1, s2.
       
  8440     col := nextPasteAction col.
       
  8441     userFriendlyInfo := 'delete ' , string size printString
       
  8442 
       
  8443     "Created: / 25-09-2006 / 12:24:10 / cg"
       
  8444 ! !
       
  8445 
       
  8446 !EditTextView::PasteString methodsFor:'execution'!
       
  8447 
       
  8448 executeIn:editor
       
  8449     editor cursorLine:line col:col.
       
  8450     editor paste:string.
       
  8451     selected ~~ true ifTrue:[
       
  8452         editor unselect
       
  8453     ].
       
  8454 ! !
       
  8455 
       
  8456 !EditTextView::ReplaceCharacter methodsFor:'accessing'!
       
  8457 
       
  8458 col
       
  8459     ^ col
       
  8460 !
       
  8461 
       
  8462 col1
       
  8463     ^ col
       
  8464 !
       
  8465 
       
  8466 col2
       
  8467     ^ col
       
  8468 !
       
  8469 
       
  8470 line
       
  8471     ^ line
       
  8472 !
       
  8473 
       
  8474 line:lineArg col:colArg character:characterArg
       
  8475     line := lineArg.
       
  8476     col := colArg.
       
  8477     character := characterArg.
       
  8478 ! !
       
  8479 
       
  8480 !EditTextView::ReplaceCharacter methodsFor:'execution'!
       
  8481 
       
  8482 executeIn:editor
       
  8483     editor
       
  8484         replace:character
       
  8485         atLine:line
       
  8486         col:col.
       
  8487     editor cursorLine:line col:col.
       
  8488 ! !
       
  8489 
       
  8490 !EditTextView::ReplaceCharacters methodsFor:'accessing'!
       
  8491 
       
  8492 characters
       
  8493     ^ characters
       
  8494 !
       
  8495 
       
  8496 col1
       
  8497     ^ col1
       
  8498 !
       
  8499 
       
  8500 col2
       
  8501     ^ col2
       
  8502 !
       
  8503 
       
  8504 line
       
  8505     ^ line
       
  8506 !
       
  8507 
       
  8508 line:lineArg col:colArg character:characterArg
       
  8509     line := lineArg.
       
  8510     col1 := col2 := colArg.
       
  8511     characters := characterArg asString.
       
  8512 !
       
  8513 
       
  8514 line:lineArg col:colArg characters:charactersArg
       
  8515     line := lineArg.
       
  8516     col1 := colArg.
       
  8517     characters := charactersArg asString.
       
  8518     col2 := col1 + charactersArg size - 1
       
  8519 ! !
       
  8520 
       
  8521 !EditTextView::ReplaceCharacters methodsFor:'combining'!
       
  8522 
       
  8523 canCombineWithNext:anotherAction
       
  8524     ^ anotherAction perform:#canCombineWithPreviousReplaceCharactersAction: with:self ifNotUnderstood:false
       
  8525 !
       
  8526 
       
  8527 canCombineWithPreviousReplaceCharactersAction:previousReplaceAction
       
  8528     "I will combine only if we both are single character deletes,
       
  8529      and my col-to-delete is the next after anotherDeleteActions col-to-delete.
       
  8530      (i.e. single-character typing)"
       
  8531 
       
  8532     previousReplaceAction line == line ifTrue:[
       
  8533         previousReplaceAction col2 == (col1-1) ifTrue:[
       
  8534             ^ true
       
  8535         ].
       
  8536     ].
       
  8537 
       
  8538     ^ false
       
  8539 !
       
  8540 
       
  8541 combineWithNext:nextReplaceAction
       
  8542     self assert:(line == nextReplaceAction line).
       
  8543     self assert:(self col2 == (nextReplaceAction col1 - 1)).
       
  8544 
       
  8545     col2 := nextReplaceAction col2.
       
  8546     userFriendlyInfo := 'replace ' , (col2 - col1 + 1) printString.
       
  8547     characters := characters , nextReplaceAction characters.
       
  8548 ! !
       
  8549 
       
  8550 !EditTextView::ReplaceCharacters methodsFor:'execution'!
       
  8551 
       
  8552 executeIn:editor
       
  8553     editor
       
  8554         replaceString:characters
       
  8555         atLine:line
       
  8556         col:col1.
       
  8557     editor cursorLine:line col:col1.
       
  8558 ! !
       
  8559 
       
  8560 !EditTextView::ReplaceContents methodsFor:'accessing'!
       
  8561 
       
  8562 text:something
       
  8563     text := something.
       
  8564 ! !
       
  8565 
       
  8566 !EditTextView::ReplaceContents methodsFor:'execution'!
       
  8567 
       
  8568 executeIn:editor
       
  8569     editor contents:text
       
  8570 ! !
       
  8571 
       
  8572 !EditTextView::ReplaceLine methodsFor:'accessing'!
       
  8573 
       
  8574 line:lineArg string:stringArg
       
  8575     line := lineArg.
       
  8576     text := stringArg.
       
  8577 ! !
       
  8578 
       
  8579 !EditTextView::ReplaceLine methodsFor:'execution'!
       
  8580 
       
  8581 executeIn:editor
       
  8582     editor list at:line put:text.
       
  8583     editor invalidateLine:line
       
  8584 ! !
       
  8585 
       
  8586 !EditTextView::ReplaceLines methodsFor:'accessing'!
       
  8587 
       
  8588 line:lineArg lines:lineCollectionArg
       
  8589     line := lineArg.
       
  8590     text := lineCollectionArg.
       
  8591 
       
  8592     "Created: / 09-10-2006 / 10:35:22 / cg"
       
  8593 ! !
       
  8594 
       
  8595 !EditTextView::ReplaceLines methodsFor:'execution'!
       
  8596 
       
  8597 executeIn:editor
       
  8598     |lnr|
       
  8599 
       
  8600     lnr := line.
       
  8601     text do:[:eachLine |
       
  8602         editor list at:lnr put:eachLine.
       
  8603         editor invalidateLine:lnr.
       
  8604         lnr := lnr + 1.
       
  8605     ].
       
  8606 
       
  8607     "Modified: / 09-10-2006 / 10:39:16 / cg"
       
  8608 ! !
       
  8609 
       
  8610 !EditTextView class methodsFor:'documentation'!
       
  8611 
       
  8612 version
       
  8613     ^ '$Header: /cvs/stx/stx/libwidg/EditTextView.st,v 1.604.2.1 2014-05-08 08:30:56 stefan Exp $'
       
  8614 !
       
  8615 
       
  8616 version_CVS
       
  8617     ^ '$Header: /cvs/stx/stx/libwidg/EditTextView.st,v 1.604.2.1 2014-05-08 08:30:56 stefan Exp $'
       
  8618 ! !
       
  8619