1 /***************************************************************************
2                           Edit_events.cxx - Event handling for Edit
3                              -------------------
4     begin                : Thu Mar  1 13:15:18 IST 2001
5     copyright            : (C) 2001 by Arie Tal
6     email                : tal_arie@yahoo.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifndef WIN32
19 #       include <unistd.h> //PORT:
20 #endif
21 #include <signal.h>
22 #include <stdio.h>
23 #include <assert.h>
24 #include "Edit.h"
25 #include "Help.h"
26 #include "Action.h"
27 #include <stdlib.h>
28 #include "langdep.h"
29 #include "aSelectionBox.h"
30 #include "aDictionary.h"
31 #include "HebrewEditor.h"
32 
33 #ifndef TRUE
34 #define TRUE 1
35 #define FALSE 0
36 #endif
37 
38 #include "LineEdit.h"
39 
40 
41 void
processAction(Action::Actions act)42 Edit::processAction(Action::Actions act)
43 {
44 //   int i ; // for general use
45    action.getLastChar() ;
46 
47    if (screen_start_line != win->getLastLineNum())
48           win->MessageClear() ;
49    switch (act) {
50      case Action::LaxetCommandHelp:
51           _LaxetCommandHelp(act) ;
52           break ;
53 
54      case Action::SpellWord:
55           _SpellWord(act) ;
56           break ;
57 
58      case Action::SpellLearnAllWords:
59           _LearnAllWords(act) ;
60           break ;
61 
62      case Action::Tab:
63           _Tab(act) ;
64           break ;
65 
66      case Action::MarkBlockBegin:
67           _MarkBlockBegin(act) ;
68           break ;
69 
70      case Action::MarkBlockEnd:
71           _MarkBlockEnd(act) ;
72           break ;
73 
74      case Action::UnmarkBlock:
75           _UnmarkBlock(act) ;
76           break ;
77 
78      case Action::DeleteBlock:
79           _DeleteBlock(act) ;
80           break ;
81 
82      case Action::CopyBlock:
83           _CopyBlock(act) ;
84           break ;
85 
86      case Action::MoveBlock:
87           _MoveBlock(act) ;
88           break ;
89 
90      case Action::Suspend: // suspend this program
91           _Suspend(act) ;
92           break ;
93 
94      case Action::Help:
95           _Help(act) ;
96         break ;
97 
98      case Action::Find:
99           _Find(act) ;
100          break ;
101 
102      case Action::FindReplace:
103           _FindReplace(act) ;
104          break ;
105 
106      case Action::Undo:
107           _Undo(act) ;
108          break ;
109 
110      case Action::Redo:
111           _Redo(act) ;
112          break ;
113 
114      case Action::DeleteChar: // delete current char
115           _DeleteChar(act) ;
116         break ;
117 
118 
119      case Action::BackSpace: // delete previous char
120           _BackSpace(act) ;
121         break ;
122 
123      case Action::DeleteLine: // delete line
124           _DeleteLine(act) ;
125         break ;
126 
127      case Action::SaveFile:
128           _SaveFile(act) ;
129         break ;
130 
131      case Action::ToggleLanguage:
132         _LanguageToggle(act) ;
133         break ;
134 
135      case Action::ChangeDirection: // insert \sethebrew or \unsethebrew commands
136         _ChangeDirection(act) ;
137         break ;
138 
139      case Action::Refresh:
140           _Refresh(act) ;
141           break ;
142 
143      case Action::NewLine:
144           _NewLine(act) ;
145         break ;
146 
147      case Action::Exit:
148           _Exit(act) ;
149         break ;
150 
151      case Action::NextLogicalWord:
152           _NextLogicalWord(act) ;
153         break ;
154 
155      case Action::PreviousLogicalWord:
156           _PreviousLogicalWord(act) ;
157         break ;
158 
159      case Action::RealForwardChar:
160           _RealForwardChar(act) ;
161         break ;
162 
163      case Action::RealBackwardChar:
164           _RealBackwardChar(act) ;
165         break ;
166 
167      case Action::WordRight:
168           _WordRight(act) ;
169         break ;
170 
171      case Action::WordLeft:
172           _WordLeft(act) ;
173         break ;
174 
175      case Action::BackwardChar:
176           _BackwardChar(act) ;
177         break ;
178 
179      case Action::ForwardChar:
180           _ForwardChar(act) ;
181         break ;
182 
183      case Action::NextLine:
184           _NextLine(act) ;
185         break ;
186 
187      case Action::PreviousLine:
188           _PreviousLine(act) ;
189         break ;
190 
191      case Action::Home:
192           _Home(act) ;
193         break ;
194 
195      case Action::End:
196           _End(act) ;
197         break ;
198 
199      case Action::BeginningOfFile:
200           _BeginningOfFile(act) ;
201         break ;
202 
203      case Action::EndOfFile:
204           _EndOfFile(act) ;
205         break ;
206 
207      case Action::PgUp:
208           _PgUp(act) ;
209         break ;
210 
211      case Action::PgDn:
212           _PgDn(act) ;
213         break ;
214 
215      case Action::Char:
216           _Char(act) ;
217         break ;
218 
219      default: // ignore Null action
220         break ;
221    }
222    if ((act != Action::Char)&&(act != Action::DeleteChar) && (act!= Action::BackSpace) && (delay_compilation > 0)) {
223          file.recompile_section(sizex) ;
224          delay_compilation = 0 ;
225          _refresh() ;
226    } else if (delay_compilation >= MAX_DELAY) {
227          file.recompile_section(sizex) ;
228          delay_compilation = 0 ;
229          _refresh() ;
230    }
231 
232    _maketitle() ;
233    win->Move(cury-1+screen_start_line,_x_pos()+screen_start_column) ;
234    win->scr->Refresh() ;
235    win->Refresh() ;
236    last_action = act ;
237 }
238 
239 
240 
241 ///////////////////////////////////////////////////////
242 ////  ACTIONS
243 ///////////////////////////////////////////////////////
244 
245 
246 void
_LanguageToggle(Action::Actions act)247 Edit::_LanguageToggle(Action::Actions act) {
248        if (read_only) return ;
249         if (keyboard_mode == hebrew)
250           keyboard_mode = english ;
251         else
252           keyboard_mode = hebrew ;
253         input.set_mode(keyboard_mode) ;
254 }
255 
256 void
_ChangeDirection(Action::Actions act)257 Edit::_ChangeDirection(Action::Actions act) {
258        if (read_only) return ;
259 
260        undo.invalidate_current() ;
261 
262        Marker _startm = file.getStartMarker() ;
263        Marker _endm = file.getEndMarker() ;
264        Marker before = where() ;
265        aString inserting="\\sethebrew\n" ;
266        if ((file.line(current_line)).getMajorMode()==StrHebrew)
267            inserting = "\\unsethebrew\n" ;
268 
269        _insertDataBlock(before, (char *)(const char*)inserting) ;
270        Marker after = where() ;
271        undo.record_action(UndoSt::ActInsert, inserting, before, after, _startm, _endm) ;
272        _End(act) ;
273        _NextLine(act) ;
274        _Home(act) ;
275        _refresh() ;
276 }
277 
278 void
_MarkBlockBegin(Action::Actions act)279 Edit::_MarkBlockBegin(Action::Actions act)
280 {
281        undo.invalidate_current() ;
282    file.setStartMarker(current_line, curx-1) ;
283    _markBlock(file.getStartMarker(), file.getEndMarker()) ;
284    _markBlock(1) ;
285    _refresh() ;
286 }
287 
288 void
_MarkBlockEnd(Action::Actions act)289 Edit::_MarkBlockEnd(Action::Actions act)
290 {
291        undo.invalidate_current() ;
292    file.setEndMarker(current_line, curx-1) ;
293    _markBlock(file.getStartMarker(), file.getEndMarker()) ;
294    _markBlock(1) ;
295    _refresh() ;
296 }
297 
298 void
_UnmarkBlock(Action::Actions act)299 Edit::_UnmarkBlock(Action::Actions act)
300 {
301        undo.invalidate_current() ;
302           file.unmarkBlock() ;
303            if (act == Action::UnmarkBlock) {
304              he->scratch->file.eraseContent() ;
305              he->scratch->current_offset = 0 ; he->scratch->curx = 1 ; he->scratch->current_line = 1 ;
306             he->scratch->file.recompile_file(sizex) ;
307             he->scratch->_relocate_curx(0) ;
308             he->scratch->modified = 1 ;
309             he->scratch->_calc_curx() ;
310           }
311           _refresh() ;
312 }
313 
314 void
_DeleteBlock(Action::Actions act)315 Edit::_DeleteBlock(Action::Actions act)
316 {
317       if (read_only) return ;
318        undo.invalidate_current() ;
319 
320        Marker _startm = file.getStartMarker() ;
321        Marker _endm = file.getEndMarker() ;
322        Marker before = _startm ;
323        aString data = "" ;
324           if (file.markActive()) {
325            _markBlock(1) ; // copy to he->scratch (sort of a 'cut')
326            Marker startm=file.getStartMarker() ;
327            Marker endm=file.getEndMarker() ;
328                _relocateAtMarker(startm) ;
329             if (act == Action::DeleteBlock) {
330                win->Refresh() ;
331                _refresh() ;
332             }
333             if (endm.line == startm.line) {
334               data += ((aString &)(file.line(startm.line))).at(startm.offset,endm.offset) ;
335                _deleteDataBlock(where(), (char *)(const char*)data) ;
336            } else {
337 //              int cl=current_line ;
338               data += ((aString &)(file.line(startm.line))).at(startm.offset,
339                              ((aString&)(file.line(startm.line))).length()-1) ;
340               data += " \n" ;
341              for (int l = startm.line+1; l <= endm.line ; l++) {
342                    if (l < endm.line) {
343                       data += ((aString &)(file.line(l))) ;
344                       data += '\n' ;
345                    } else
346                     data += ((aString &)(file.line(endm.line))).at(0, endm.offset) ;
347              }
348              _deleteDataBlock(where(), (char *)(const char *)data) ;
349           }
350           if (act == Action::DeleteBlock) {
351              _UnmarkBlock(act) ;
352              file.line(startm.line) ;
353              modified = 1 ;
354              _relocate_curx(0) ;
355              Marker after = where() ;
356              undo.record_action(UndoSt::ActDelete, data, where(), after, _startm, _endm) ;
357              _refresh() ;
358            }
359           }
360 }
361 
362 void
_CopyBlock(Action::Actions act)363 Edit::_CopyBlock(Action::Actions act)
364 {
365  if (read_only) return ;
366        undo.invalidate_current() ;
367 
368   Marker _startm = file.getStartMarker() ;
369   Marker _endm = file.getEndMarker() ;
370   Marker before = where() ;
371   aString data = "" ;
372   if (act == Action::CopyBlock) {
373      Marker startm = file.getStartMarker() ;
374      Marker endm = file.getEndMarker() ;
375     if (((current_line > startm.line) ||
376        (current_line == startm.line)&&(curx > startm.offset+1)) &&
377       ((current_line < endm.line) ||
378        (current_line == endm.line)&&(curx < endm.offset+1))) {
379         // trying to copy a block into a marked block!, illegal now
380          win->Message(MSG_INVALID_COPY_BLOCK) ;
381          return ;
382      }
383   }
384   int curline = current_line ;
385   if (he->scratch->file.isFileEmpty()) {
386       if (file.markActive())
387            _markBlock(1) ;
388   } else if ((he->scratch->from == this) && (act == Action::CopyBlock))
389      _markBlock(1) ;
390 
391   if (!he->scratch->file.isFileEmpty()) {  // I can't use file.markActive now, because a block can be
392     // copied from another buffer,using the he->scratch buffer.
393     if ((he->scratch->file).lines() == 1) {
394       data += ((aString &)((he->scratch->file).line(1))) ; //.at(0,((aString &)((he->scratch->file).line(1))).length()) ; // he->scratch is not compiled anymore so there is no extra space
395       _insertDataBlock(where(), (char *)(const char *)data) ;
396       file.setStartMarker(current_line, curx-1) ;
397       file.setEndMarker(current_line, curx-1+((aString &)((he->scratch->file).line(1))).length()) ;
398       _markBlock() ;
399     } else {
400       file.setStartMarker(current_line, curx-1) ;
401       int cl=current_line ;
402       data += ((aString &)((he->scratch->file).line(1))).at(0,((aString &)((he->scratch->file).line(1))).length()) ;
403       for (int l = 2; l < he->scratch->file.lines() ; l++) {
404         data += '\n' ;
405         data += (aString &)(he->scratch->file.line(l)) ;
406         cl++ ;
407       }
408       aString tmp = ((aString &)((he->scratch->file).line(he->scratch->file.lines()))) ; //.at(0,
409       data += '\n' ;
410       data += tmp ; cl++ ;
411       _insertDataBlock(where(), (char *)(const char*)data) ;
412       file.setEndMarker(cl, tmp.length()) ;
413       _markBlock() ;
414       file.line(curline) ;
415 //      file.recompile_section(sizex) ;
416     }
417     file.line(curline) ;
418     modified = 1 ;
419     _relocate_curx(0) ;
420     Marker after = where() ;
421     if (act == Action::CopyBlock)
422        undo.record_action(UndoSt::ActInsert, data, before, after, _startm, _endm) ;
423     else
424       work_data_block = data ;
425 
426     _refresh() ;
427   }
428 }
429 
430 
431 void
_MoveBlock(Action::Actions act)432 Edit::_MoveBlock(Action::Actions act)
433 {
434   if (read_only) return ;
435        undo.invalidate_current() ;
436   if (he->scratch->file.isFileEmpty()) {
437       if (file.markActive())
438            _markBlock(1) ;
439   }
440   if (he->scratch->from)
441         if (he->scratch->from != this) {
442           win->Message(MSG_INVALID_MOVE_BLOCK_FROM_DIFFERENT_BUFFER) ;
443           return ;
444   }
445   Marker startm = file.getStartMarker() ;
446   Marker endm = file.getEndMarker() ;
447   Marker _startm = file.getStartMarker() ;
448   Marker _endm = file.getEndMarker() ;
449   Marker before = startm ;
450   if (((current_line > startm.line) ||
451        (current_line == startm.line)&&(curx > startm.offset+1)) &&
452       ((current_line < endm.line) ||
453        (current_line == endm.line)&&(curx < endm.offset+1))) {
454     // trying to move a block into a marked block!, illegal now
455     win->Message(MSG_INVALID_MOVE_BLOCK_INTO_MARKED_BLOCK) ;
456     return ;
457   }
458 
459   if (((current_line == endm.line) && (curx == endm.offset+1)) ||
460        ((current_line == startm.line) && (curx == startm.offset+1)))
461        return ; // ignore, just like moving a block right after itself, or right before itself
462 
463 //  int curline = current_line ;
464   if (!he->scratch->file.isFileEmpty()) {
465     // I can't use file.markActive now, because a block can be
466     // copied from another buffer,using the scratch buffer.
467     if (he->scratch->from == this) {
468       Marker newLocale = { current_line, curx-1, cury } ;
469         if ((startm.line == current_line) && (curx > startm.offset+1)) {
470                newLocale.offset -= ( (aString&)(he->scratch->file.line(1)) ).length() ;
471                newLocale.offset_from_top = -1 ;
472               _relocateAtMarker(newLocale) ;
473         } else
474         if ((endm.line == current_line) && (curx > endm.offset+1)) {
475                newLocale.offset -= endm.offset-startm.offset ;
476               if (endm.line > startm.line)
477                newLocale.line -= (endm.line - startm.line)-1 ;
478         } else if (current_line > endm.line)
479               if (endm.line > startm.line)
480                newLocale.line -= (endm.line - startm.line) ;
481         _DeleteBlock(act) ;
482         _relocateAtMarker(newLocale) ; // with same offset from top if needed, so visually it would look as if
483                                                                      // the editor stayed in the same place.
484 //        if (current_line > startm.line) {
485 //               newLocale.line -= he->scratch->file.lines() -1;
486 //            _relocateAtMarker(newLocale) ;
487 //        }
488      }
489     _CopyBlock(act) ;
490     Marker after = where() ;
491     undo.record_action(UndoSt::ActMove, work_data_block, before, after, _startm, _endm) ;
492   }
493 }
494 
495 
496 void
_Suspend(Action::Actions act)497 Edit::_Suspend(Action::Actions act)
498 {
499     undo.invalidate_current() ;
500     action.getLastChar() ;
501     win->Erase() ;
502     if (getenv("HE2_NEW_SHELL_ON_SUSPEND") != NULL)
503        win->TemporaryExit() ;
504     else
505        win->Suspend() ;
506     win->GetMaxYX(&sizey,&sizex) ;
507 //        --sizey ;
508     file.recompile_file(sizex) ;
509     win->Erase() ;
510     win->Refresh();
511     _refresh() ;
512 }
513 
514 void
_Help(Action::Actions act)515 Edit::_Help(Action::Actions act)
516 {
517         if (!read_only) {
518           {
519          aWindow *tmpWin ;
520          win->Message("(Processing help text)") ;
521          aString helpFileName = he->programPrefix ;
522          helpFileName += "/" ;
523          helpFileName += HE_TUTORIAL_FILE_NAME ;
524          Help help(he, tmpWin=new aWindow(win->scr, sizey-6, sizex-11,3,5), (const char *)helpFileName) ;
525 
526          help.processFile() ;
527          help.refresh() ;
528 
529          while (!help.finished())
530             help.processAction(help.getNextAction()) ;
531          // enable to copy text from help
532          if (help.file.markActive())
533            help._markBlock(1) ;
534 
535          delete tmpWin ;
536         }
537 //        win->Erase() ;
538         win->Refresh();
539         _refresh() ;
540         }
541 
542 }
543 
544 void
_Find(Action::Actions act)545 Edit::_Find(Action::Actions act)
546 {
547 //        if (!read_only) {
548              Marker startm = file.getStartMarker() ;
549              Marker endm = file.getEndMarker() ;
550 
551              SearchFor *input_line ;
552 
553               int c =win->Question(QTN_SEARCH_HEBREW_ENGLISH) ;
554               while ((c != 'h')&& (c!='H') && (c!= 'e') && (c!='E'))
555                      c =win->Question(QTN_SEARCH_HEBREW_ENGLISH) ;
556               int sy, sx ;
557               win->scr->GetMaxYX(&sy,&sx) ;
558               aWindow *linewin=new aWindow(win->scr,1,sx,sy-1,0,0) ;
559 
560               if ((c == 'h') || (c == 'H'))
561                    input_line = new SearchForHebrew(he, HEBREW_SEARCH_MESSAGE,linewin,this) ;
562               else
563                    input_line = new SearchFor(he, ENGLISH_SEARCH_MESSAGE,linewin,this) ;
564 
565              Marker current = {current_line, curx-1, cury} ;
566              input_line->refresh() ;
567 
568              while (!input_line->finished())
569                  input_line->processAction(act=input_line->getNextAction()) ;
570              win->MessageClear(1) ;
571              if (act != Action::NewLine) {
572                 _relocateAtMarker(current) ;
573              }
574              delete input_line ;
575              delete linewin ;
576 
577              file.setStartMarker(startm.line, startm.offset) ;
578              file.setEndMarker(endm.line, endm.offset) ;
579              _markBlock() ;
580              win->Refresh() ;
581              _refresh() ;
582 //        }
583 }
584 
585 void
_FindReplace(Action::Actions act)586 Edit::_FindReplace(Action::Actions act)
587 {
588         if (!read_only) {
589              Marker startm = file.getStartMarker() ;
590              Marker endm = file.getEndMarker() ;
591 
592              SearchFor *input_line ;
593 
594               int c =win->Question(QTN_REPLACE_HEBREW_ENGLISH) ;
595               while ((c != 'h')&& (c!='H') && (c!= 'e') && (c!='E'))
596                      c =win->Question(QTN_REPLACE_HEBREW_ENGLISH) ;
597               int sy, sx ;
598               win->scr->GetMaxYX(&sy,&sx) ;
599               aWindow *linewin=new aWindow(win->scr,1,sx,sy-1,0,0) ;
600 
601               if ((c == 'h') || (c == 'H'))
602                    input_line = new SearchForHebrew(he, HEBREW_REPLACE_SEARCH_MESSAGE,linewin,this) ;
603               else
604                    input_line = new SearchFor(he, ENGLISH_REPLACE_SEARCH_MESSAGE,linewin,this) ;
605 
606              Marker current = {current_line, curx-1, cury} ;
607              input_line->refresh() ;
608 
609              while (!input_line->finished())
610                  input_line->processAction(act=input_line->getNextAction()) ;
611              win->MessageClear(1) ;
612              if (act != Action::NewLine) {
613                 _relocateAtMarker(current) ;
614              } else { // begin replacing:
615                 aString textToReplace = input_line->getText() ;
616                 SearchFor *input_line2 ;
617                 if ((c == 'h') || (c == 'H'))
618                    input_line2 = new SearchForHebrew(he, HEBREW_REPLACE_WITH_MESSAGE,linewin,0) ;
619                 else
620                    input_line2 = new SearchFor(he, ENGLISH_REPLACE_WITH_MESSAGE,linewin,0) ;
621                 input_line2->refresh() ;
622 
623                 while (!input_line2->finished())
624                       input_line2->processAction(act=input_line2->getNextAction()) ;
625                 win->MessageClear(1) ;
626                 if (act == Action::NewLine) { // the user wants to start replacing
627                   int cont = 1 ;
628                   int batch_mode = 0 , q = ' ';
629                   while (cont) {
630                    if (!batch_mode)
631                      q = win->Question(QTN_ENGLISH_REPLACE_YES_NO_ALL_CANCEL) ;
632                    switch (q) {
633                       case 'y':
634                       case 'Y': {
635                           Marker before = where() ;
636                           _deleteDataBlock(before, input_line->getText()) ;
637                           _insertDataBlock(before, input_line2->getText()) ;
638                           int len = strlen(input_line2->getText()) ;
639                           for (int i=0; i<len; i++) _relocate_curx(1) ;
640                           Marker after = where() ;
641                           undo.record_action(UndoSt::ActReplace, textToReplace, before, after,
642                                              startm, endm, input_line2->getText()) ;
643                           searchForNext(input_line->getText()) ;
644                           if (after.isEqual(where())) cont = 0 ;
645                         }
646                         break ;
647                       case 'n':
648                       case 'N': {
649                           Marker here = where() ;
650                           searchForNext(input_line->getText()) ;
651                           if (here.isEqual(where())) cont = 0 ;
652 			}
653                         break ;
654                       case 'a':
655                       case 'A':
656                           q = 'Y' ;
657                           batch_mode = 1 ;
658                         break ;
659                       case 'c':
660                       case 'C':
661                           cont = 0 ;
662                         break ;
663                       default:
664                         break ;
665                    }
666                   } // end of while
667                   win->MessageClear(1) ;
668                   delete input_line2 ;
669                 }
670              } // end else begin replacing
671              delete input_line ;
672              delete linewin ;
673              file.setStartMarker(startm.line, startm.offset) ;
674              file.setEndMarker(endm.line, endm.offset) ;
675              _markBlock() ;
676              win->Refresh() ;
677              _refresh() ;
678         }
679 }
680 
681 
682 
683 void
_DeleteChar(Action::Actions act)684 Edit::_DeleteChar(Action::Actions act)
685 {
686   Marker endm=file.getEndMarker() ;
687   Marker startm=file.getStartMarker() ;
688   Marker _endm=file.getEndMarker() ;
689   Marker _startm=file.getStartMarker() ;
690   if (!read_only) {
691      Marker before ;
692      if (act == Action::DeleteChar) {
693         before = where() ;
694         if (act != last_action)
695            undo.invalidate_current() ;
696      } else
697         before = work_marker ;
698 
699      aString data = ""  ;
700 
701     if (curx < (file.line(current_line)).length()) {
702       data = ((aString &)(file.line(current_line))).at(curx-1,curx) ;
703 
704       (file.line(current_line))._delete_ch(curx, current_offset) ;
705       int change = 0 ;
706       if ((startm.line == current_line) && (startm.offset > curx-1)) {
707         file.setStartMarker(startm.line, startm.offset-1) ;
708         change = 1 ;
709       }
710       if ((endm.line == current_line) && (endm.offset > curx-1)) {
711         file.setEndMarker(endm.line, endm.offset-1) ;
712         change = 1 ;
713       }
714       if (change)
715         _markBlock() ;
716       modified =1  ;
717       delay_compilation++ ;
718       file.recompile_section(sizex,0) ;
719     }
720     else if (current_line < file.lines()) {
721       undo.invalidate_current() ;
722       data += " \n" ;
723       int change = 0 ;
724       if (startm.line > current_line+1) {
725         file.setStartMarker(startm.line-1, startm.offset) ;
726         change=1 ;
727       } else if (startm.line == current_line+1) {
728         file.setStartMarker(startm.line-1, startm.offset + (curx-1)) ;
729         change=1 ;
730       }
731       if (endm.line > current_line+1) {
732         file.setEndMarker(endm.line-1, endm.offset) ;
733         change=1 ;
734       } else if (endm.line == current_line+1) {
735         file.setEndMarker(endm.line-1, endm.offset + (curx-1)) ;
736         change=1 ;
737       }
738 //      aString tmp = ((aString &)file.line(current_line)).at(0, ((aString&)file.line(current_line)).length()-1) ;
739 //      tmp+=(const char *)((aString &)file.line(current_line+1)) ;
740 //      ((aString &)file.line(current_line)) = tmp ;
741 //      file.delete_line(current_line+1) ; // WATCH FOR TROUBLE HERE
742       _deleteDataBlock(where(), (char *)(const char*)data) ;
743       if (change)
744         _markBlock() ;
745       modified = 1 ;
746 //      file.recompile_section(sizex) ;
747     }
748     _relocate_curx(0) ;
749     _calc_curx() ;
750     Marker after = where() ;
751     if (act == Action::DeleteChar)
752        undo.record_action(UndoSt::ActDelete, data, before, after, _startm, _endm) ;
753     else
754        undo.record_action(UndoSt::ActBackSpace, data, before, after, _startm, _endm) ;
755     _refresh() ;
756   }
757 
758 }
759 
760 void
_BackSpace(Action::Actions act)761 Edit::_BackSpace(Action::Actions act)
762 {
763   if (!read_only) {
764    if (act != last_action)
765      undo.invalidate_current() ;
766       work_marker = where() ;
767     if (_relocate_curx(-1)) {
768       _DeleteChar(act) ;
769     } /* end if !read_only */
770   }
771 }
772 
773 void
_DeleteLine(Action::Actions act)774 Edit::_DeleteLine(Action::Actions act)
775 {
776   undo.invalidate_current() ;
777   Marker endm=file.getEndMarker() ;
778   Marker startm=file.getStartMarker() ;
779   Marker _endm = file.getEndMarker() ;
780   Marker _startm = file.getStartMarker() ;
781   if (!read_only) {
782     // this is done to imitate emacs behavior
783     // are we at the end of the line ?
784     if (where().offset >= ((aString &)file.line(current_line)).length()-1)
785        _Home(Action::Null) ;
786     Marker before = where() ;
787     aString data = "" ;
788     int changed = 0 ;
789 
790     // if (file.lines() > 1)  // there is no need for that anymore, since DeleteLine does not
791                               // actually delete lines from the file, it let's DeleteChar handle
792                               // that.
793     {
794       if (current_line == file.lines()) { // THE LAST LINE IS BEING DELETED
795         // the last line is also the only marked line
796         if ((startm.line == endm.line) && (startm.line == current_line)) {
797           file.unmarkBlock() ;
798           _markBlock() ;
799         } else // are we trying to delete a last marked line ?
800           if ((endm.line == current_line) && (endm.line > startm.line)) {
801          //   endm.line-- ;
802             endm.offset = where().offset ; // ((aString &)(file.line(current_line-1))).length() ;
803             file.setEndMarker(endm.line, endm.offset) ;
804             changed = 1 ;
805           }
806 
807         data += ((aString &)file.line(current_line)).at(where().offset, ((aString&)file.line(current_line)).length()-1) ;
808 //        _previous_line() ;
809 //        _End(Action::Null) ;
810         Marker after = where() ;
811 //        data += '\n' ;
812 //        data += ((aString &)file.line(current_line+1)).at(0, ((aString&)file.line(current_line+1)).length()-1) ;
813 //        file.delete_line(current_line+1) ;
814         _deleteDataBlock(where(), (char *)(const char*)data) ;
815         undo.record_action(UndoSt::ActDelete, data, before, after, _startm, _endm) ;
816         // if we are at the beginning of the line, only then perform a backspace
817         if (where().offset == 0)
818           _BackSpace(Action::BackSpace) ;
819       } else { // STILL MORE LINES AHEAD
820         if ((startm.line == endm.line) && (startm.line == current_line)) {
821           file.unmarkBlock() ;
822           changed = 1;
823         } else
824           if ((endm.line == current_line) && (endm.line > startm.line)) {
825             // endm.line-- ;
826             endm.offset = where().offset ; // ((aString &)(file.line(current_line-1))).length() ;
827             file.setEndMarker(endm.line, endm.offset) ;
828             changed = 1 ;
829           } else
830             if ((startm.line == current_line) && (startm.line < endm.line) && (startm.offset >= where().offset)) {
831               startm.offset = 0 ;
832               startm.line++ ;
833               file.setStartMarker(startm.line, startm.offset) ;
834 //              endm.line-- ;
835               file.setEndMarker(endm.line, endm.offset) ;
836               changed = 1 ;
837             } /* else {
838               if (startm.line > current_line) {
839                 changed=1 ;
840                 file.setStartMarker(startm.line-1, startm.offset) ;
841               }
842               if (endm.line > current_line) {
843                 changed=1 ;
844                 file.setEndMarker(endm.line-1, endm.offset) ;
845               }
846             }    */
847         Marker after = before ;
848         data += ((aString &)file.line(current_line)).at(where().offset, ((aString&)file.line(current_line)).length()-1) ;
849 //        data += '\n' ;
850 //        file.delete_line(current_line) ;
851         _deleteDataBlock(where(), (char *)(const char*)data) ;
852         undo.record_action(UndoSt::ActDelete, data, before, after, _startm, _endm) ;
853         if (where().offset == 0) {
854           _BackSpace(Action::BackSpace) ;
855           _NextLine(Action::NextLine) ;
856           _Home(Action::Home) ;
857         }
858       }
859       if (changed)
860         _markBlock() ;
861       modified = 1 ;
862     } /*
863     else { // there is only a single line in the file
864       // _Home(Action::Null) ;
865       Marker after = before ;
866       data += ((aString &)file.line(1)).at(before.offset, ((aString&)file.line(1)).length()-1) ;
867       undo.record_action(UndoSt::ActDelete, data, before, after, _startm, _endm) ;
868       _deleteDataBlock(before, (char *)(const char *)data) ;
869 //      (aString &)(file.line(1)) = " " ; // clear the first line
870       file.unmarkBlock() ;
871       _markBlock() ;
872       modified = 1 ;
873     }   */
874 //    file.recompile_section(sizex) ;
875     _refresh() ;
876   }
877   _relocate_curx(0) ;
878 }
879 
880 void
_SaveFile(Action::Actions act)881 Edit::_SaveFile(Action::Actions act)
882 {
883   if (!read_only) {
884     if (file.write_file()) {
885        win->Message(MSG_FILE_SAVED) ;
886        undo.saved_here() ;
887        modified = 0 ;
888     } else {
889        win->Message(MSG_UNABLE_TO_SAVE_FILE) ;
890     }
891   }
892 }
893 
894 void
_Refresh(Action::Actions act)895 Edit::_Refresh(Action::Actions act)
896 {
897    win->TemporaryExit(1) ;
898    win->GetMaxYX(&sizey,&sizex) ;
899 //   --sizey ;
900    file.recompile_file(sizex) ;
901 //   win->Erase() ;
902 //   win->scr->Refresh() ;
903    win->Refresh();
904    _refresh() ;
905 
906 }
907 
908 
909 void
_SpellWord(Action::Actions act)910 Edit::_SpellWord(Action::Actions act)
911 {
912   // find current word
913    aString chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
914    char ch = *(const char *)(chr) ;
915    while ( (strchr(LETTERS,ch)) && ((current_line > 1) || (curx > 1))) {
916         _RealBackwardChar(act) ;
917         chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
918         ch = *(const char *)(chr) ;
919    }
920    if ( (!strchr(LETTERS,ch))){
921         _RealForwardChar(act) ;
922    }
923    aString word = "" ;
924    int count = 0 ;
925    if ((file.line(current_line)).getCurrentXcode(current_offset,_x_pos())==INVALID_HEBREW_WORD) {
926      while ((file.line(current_line)).getCurrentXcode(current_offset,_x_pos())==INVALID_HEBREW_WORD) {
927         word +=  ((aString &)file.line(current_line)).at(curx-1,curx) ;
928         count++ ;
929        _RealForwardChar(act) ;
930      }
931      for (;count>0; count--) _RealBackwardChar(act) ;
932      suggestWords(he->hebrewDictionary, word) ;
933    }
934    if ((file.line(current_line)).getCurrentXcode(current_offset,_x_pos())==INVALID_ENGLISH_WORD) {
935      while ((file.line(current_line)).getCurrentXcode(current_offset,_x_pos())==INVALID_ENGLISH_WORD) {
936         word +=  ((aString &)file.line(current_line)).at(curx-1,curx) ;
937         count++ ;
938        _RealForwardChar(act) ;
939      }
940      for (;count>0; count--) _RealBackwardChar(act) ;
941      suggestWords(he->englishDictionary, word) ;
942    }
943 //   if ((file.line(current_line)).getCurrentXcode(current_offset,_x_pos())==INVALID_LAXET_COMMAND) {
944 //     while ((file.line(current_line)).getCurrentXcode(current_offset,_x_pos())==INVALID_LAXET_COMMAND) {
945 //        word +=  ((aString &)file.line(current_line)).at(curx-1,curx) ;
946 //        count++ ;
947 //       _RealForwardChar(act) ;
948 //     }
949 //     for (;count>0; count--) _RealBackwardChar(act) ;
950 //     suggestWords(he->laxetDictionary, word) ;
951 //   }
952 //   exit(1) ;
953 }
954 
955 #define MAX_SPELLING_RESULTS 10
956 
957 char *
suggestWords(aDictionary * dict,aString & word)958 Edit::suggestWords(aDictionary *dict, aString &word) {
959    if (!read_only) {
960      Marker startm = file.getStartMarker() ;
961      Marker endm = file.getEndMarker() ;
962 //     Marker current = {current_line, curx-1, cury} ;
963 
964      static char *results[MAX_SPELLING_RESULTS] ;
965      int results_count ;
966      dict->findMatchingWords(5,(char *)(const char*)word, results, results_count, MAX_SPELLING_RESULTS) ;
967         aSelectionBox<char *> sb(he, 0, "Close matches", win->scr) ;
968       for (int i=0 ; i<results_count; i++) {
969        sb.addMember(results[i], results[i], 0) ;
970      }
971 
972      char *response = sb.select() ;
973      he->currentEditBuffer->refresh() ;
974      char msg[1000] ;
975      if (response) {
976              sprintf(msg,"Replace '%s' with '%s' (Yes/No/All/Cancel) ?  ",
977               (char *)(const char*)word, response) ;
978              searchFor((char *)(const char *)word) ;
979              int cont = 1 ;
980              int batch_mode = 0 , q = ' ';
981              while (cont) {
982                       if (!batch_mode)
983                         q = win->Question(msg) ;
984                       switch (q) {
985                          case 'y':
986                          case 'Y': {
987                              Marker before = where() ;
988                              _deleteDataBlock(before, (char *)(const char *)word) ;
989                              _insertDataBlock(before, response) ;
990                              int len = strlen(response) ;
991                              for (int i=0; i<len; i++) _relocate_curx(1) ;
992                              Marker after = where() ;
993                              undo.record_action(UndoSt::ActReplace, word,
994                                          before, after,
995                                          startm, endm, response) ;
996                              searchForNext((char *)(const char *)word) ;
997                              if (after.isEqual(where())) cont = 0 ;
998                            }
999                            break ;
1000                          case 'n':
1001                          case 'N': {
1002                              Marker here = where() ;
1003                              searchForNext((char *)(const char *)word) ;
1004                              if (here.isEqual(where())) cont = 0 ;
1005 			   }
1006 		  	   break ;
1007                          case 'a':
1008                          case 'A':
1009                              q = 'Y' ;
1010                              batch_mode = 1 ;
1011                            break ;
1012                          case 'c':
1013                          case 'C':
1014                              cont = 0 ;
1015                            break ;
1016                          default:
1017                            break ;
1018                       }
1019                      } // end of while
1020                      win->MessageClear(1) ;
1021                 file.setStartMarker(startm.line, startm.offset) ;
1022                 file.setEndMarker(endm.line, endm.offset) ;
1023                 _markBlock() ;
1024       } else {
1025           int resp=win->Question("Would you like to add this word to your local dictionary (Yes/No) ?  ") ;
1026           win->MessageClear(1) ;
1027           if (strchr("yY",resp)) {
1028               dict->recordBadWordsOn() ;
1029               dict->findMatch((char *)(const char *)word) ;
1030               dict->recordBadWordsOff() ;
1031               file.recompile_file(sizex) ;
1032           }
1033           refresh() ;
1034       }
1035      return response ;
1036   } // end of if !read_only
1037   return (char *)NULL ;
1038 }
1039 
1040 void
_LearnAllWords(Action::Actions act)1041 Edit::_LearnAllWords(Action::Actions act)
1042 {
1043    he->englishDictionary->recordBadWordsOn() ;
1044    he->hebrewDictionary->recordBadWordsOn() ;
1045    he->laxetDictionary->recordBadWordsOn() ;
1046    file.recompile_file(sizex) ;
1047    he->englishDictionary->recordBadWordsOff() ;
1048    he->hebrewDictionary->recordBadWordsOff() ;
1049    he->laxetDictionary->recordBadWordsOff() ;
1050    win->Refresh();
1051    _refresh() ;
1052 
1053 }
1054 
1055 
1056 void
_NewLine(Action::Actions act)1057 Edit::_NewLine(Action::Actions act)
1058 {
1059   undo.invalidate_current() ;
1060   Marker endm=file.getEndMarker() ;
1061   Marker startm=file.getStartMarker() ;
1062   Marker _endm=file.getEndMarker() ;
1063   Marker _startm=file.getStartMarker() ;
1064   if (!read_only) {
1065     Marker before = where() ;
1066     aString data = "" ;
1067     int changed = 0 ;
1068     if ((startm.line == current_line) && (startm.offset+1 > curx)) {
1069       startm.line++ ;
1070       startm.offset -= (curx-1) ;
1071       changed = 1 ;
1072     } else if (startm.line > current_line) {
1073       startm.line++ ;
1074       changed = 1 ;
1075     }
1076     if ((endm.line == current_line) && (endm.offset >= curx)) {
1077       endm.line++ ;
1078       endm.offset -= (curx-1) ;
1079       changed = 1 ;
1080     } else if (endm.line > current_line) {
1081       endm.line++ ;
1082       changed = 1 ;
1083     }
1084 //    int len = ((aString &)file.line(current_line)).length() ;
1085 //    if (!(((aString &)file.line(current_line)).at(len-1,len) == " "))
1086       data += _newline() ;
1087     if (changed) {
1088       file.setStartMarker(startm.line, startm.offset) ;
1089       file.setEndMarker(endm.line, endm.offset) ;
1090       _markBlock() ;
1091     }
1092     Marker after = where() ;
1093     if (act == Action::NewLine)
1094       undo.record_action(UndoSt::ActInsert, data, before, after, _startm, _endm) ;
1095 
1096      _refresh() ;
1097     modified = 1 ;
1098   // take care of autoindent
1099   }
1100 }
1101 
1102 void
_Exit(Action::Actions act)1103 Edit::_Exit(Action::Actions act)
1104 {
1105   if (!(name == SCRATCH_BUFFER_NAME)) {
1106     if (file.markActive() && (!read_only))
1107        _markBlock(1) ;
1108     int c='y' ;
1109     if (undo.is_modified() && _need_to_save())  {
1110        c=win->Question(QTN_LOOSE_CHANGES) ;
1111    }
1112     while ((c != 'y')&& (c!='Y') && (c!= 'n') && (c!='N'))
1113         c=win->Question(QTN_LOOSE_CHANGES) ;
1114     if ((c == 'n') || (c == 'N')) {
1115           win->MessageClear() ;
1116           _refresh() ;
1117     } else {
1118 //        win->Erase() ;
1119         win->Refresh() ;
1120         continue_edit = FALSE ;
1121      }
1122   }
1123 }
1124 
1125 void
_RealForwardChar(Action::Actions act)1126 Edit::_RealForwardChar(Action::Actions act)
1127 {
1128   _relocate_curx(1) ;
1129 }
1130 
1131 void
_RealBackwardChar(Action::Actions act)1132 Edit::_RealBackwardChar(Action::Actions act)
1133 {
1134   _relocate_curx(-1) ;
1135 }
1136 
1137 void
_NextLogicalWord(Action::Actions act)1138 Edit::_NextLogicalWord(Action::Actions act)
1139 {
1140    aString chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1141    char ch = *(const char *)(chr) ;
1142    while ( (strchr(LETTERS,ch)) && ((current_line < file.lines()) || (curx < ((aString&)file.line(current_line)).length()))) {
1143         _RealForwardChar(act) ;
1144         chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1145         ch = *(const char *)(chr) ;
1146    }
1147    while ( (!strchr(LETTERS,ch)) && ((current_line < file.lines()) || (curx < ((aString&)file.line(current_line)).length()))) {
1148         _RealForwardChar(act) ;
1149         chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1150         ch = *(const char *)(chr) ;
1151    }
1152 }
1153 
1154 void
_PreviousLogicalWord(Action::Actions act)1155 Edit::_PreviousLogicalWord(Action::Actions act)
1156 {
1157    aString chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1158    char ch = *(const char *)(chr) ;
1159    while ( (strchr(LETTERS,ch)) && ((current_line > 1) || (curx > 1))) {
1160         _RealBackwardChar(act) ;
1161         chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1162         ch = *(const char *)(chr) ;
1163    }
1164    while ( (!strchr(LETTERS,ch)) &&((current_line > 1) || (curx > 1))) {
1165         _RealBackwardChar(act) ;
1166         chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1167         ch = *(const char *)(chr) ;
1168    }
1169 }
1170 
1171 void
_WordRight(Action::Actions act)1172 Edit::_WordRight(Action::Actions act)
1173 {
1174    aString chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1175    char ch = *(const char *)(chr) ;
1176    int cur_line = current_line ;
1177    int cur_x = curx ;
1178    int ocur_line ;
1179    int ocur_x = 0 ;
1180 
1181    while ( (strchr(LETTERS,ch)) && ((cur_line != ocur_line) || (cur_x != ocur_x)) ) {
1182         ocur_line = cur_line ;
1183         ocur_x = cur_x ;
1184          _ForwardChar(act) ;
1185         cur_line = current_line ;
1186         cur_x = curx ;
1187         chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1188         ch = *(const char *)(chr) ;
1189    }
1190    while ( (!strchr(LETTERS,ch)) &&((cur_line != ocur_line) || (cur_x != ocur_x)) ) {
1191         ocur_line = cur_line ;
1192         ocur_x = cur_x ;
1193         _ForwardChar(act) ;
1194         cur_line = current_line ;
1195         cur_x = curx ;
1196         chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1197         ch = *(const char *)(chr) ;
1198    }
1199 }
1200 
1201 void
_WordLeft(Action::Actions act)1202 Edit::_WordLeft(Action::Actions act)
1203 {
1204    aString chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1205    char ch = *(const char *)(chr) ;
1206    int cur_line = current_line ;
1207    int cur_x = curx ;
1208    int ocur_line = 0 ;
1209    int  ocur_x = 0 ;
1210 
1211    while ( (strchr(LETTERS,ch)) && ((cur_line != ocur_line) || (cur_x != ocur_x)) ) {
1212         ocur_line = cur_line ;
1213         ocur_x = cur_x ;
1214          _BackwardChar(act) ;
1215         cur_line = current_line ;
1216         cur_x = curx ;
1217         chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1218         ch = *(const char *)(chr) ;
1219    }
1220    while ( (!strchr(LETTERS,ch)) &&((cur_line != ocur_line) || (cur_x != ocur_x)) ) {
1221         ocur_line = cur_line ;
1222         ocur_x = cur_x ;
1223         _BackwardChar(act) ;
1224         cur_line = current_line ;
1225         cur_x = curx ;
1226         chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1227         ch = *(const char *)(chr) ;
1228    }
1229 }
1230 
1231 
1232 void
_ForwardChar(Action::Actions act)1233 Edit::_ForwardChar(Action::Actions act)
1234 {
1235   _forward() ;
1236 }
1237 
1238 void
_BackwardChar(Action::Actions act)1239 Edit::_BackwardChar(Action::Actions act)
1240 {
1241   _backward() ;
1242 }
1243 
1244 void
_NextLine(Action::Actions act)1245 Edit::_NextLine(Action::Actions act)
1246 {
1247    action.getLastChar() ;
1248    _next_line() ;
1249 }
1250 
1251 void
_PreviousLine(Action::Actions act)1252 Edit::_PreviousLine(Action::Actions act)
1253 {
1254    action.getLastChar() ;
1255    _previous_line() ;
1256 }
1257 
1258 void
_Home(Action::Actions act)1259 Edit::_Home(Action::Actions act)
1260 {
1261   for (;curx >1; _relocate_curx(-1)) ;
1262 }
1263 
1264 void
_End(Action::Actions act)1265 Edit::_End(Action::Actions act)
1266 {
1267   int tmp = file.line(current_line).length() ;
1268   for (;curx<tmp ; _relocate_curx(+1)) ;
1269 }
1270 
1271 void
_BeginningOfFile(Action::Actions act)1272 Edit::_BeginningOfFile(Action::Actions act)
1273 {
1274   for (;current_line>1 ; _previous_page(0)) ;
1275   for (;curx>1; _relocate_curx(-1)) ;
1276   win->Refresh() ;
1277   _refresh() ;
1278 }
1279 
1280 void
_EndOfFile(Action::Actions act)1281 Edit::_EndOfFile(Action::Actions act)
1282 {
1283   for (;(current_line < file.lines()) ||
1284        ((current_line == file.lines()) &&
1285         (current_offset <
1286          (file.line(current_line)).line_count(sizex) - 1)) ;
1287        _next_page(0)) ;
1288   _End(Action::Null) ;
1289   win->Refresh() ;
1290   _refresh() ;
1291 }
1292 
1293 void
_PgUp(Action::Actions act)1294 Edit::_PgUp(Action::Actions act)
1295 {
1296   _previous_page() ;
1297   esc = 0 ;
1298 }
1299 
1300 void
_PgDn(Action::Actions act)1301 Edit::_PgDn(Action::Actions act)
1302 {
1303   _next_page() ;
1304   esc = 0 ;
1305 }
1306 
1307 void
_Char(Action::Actions act)1308 Edit::_Char(Action::Actions act)
1309 {
1310    int ch = action.getLastChar() ;
1311    Marker startm = file.getStartMarker() ;
1312    Marker endm = file.getEndMarker() ;
1313    Marker _startm = file.getStartMarker() ;
1314    Marker _endm = file.getEndMarker() ;
1315 
1316    if (act != last_action)
1317      undo.invalidate_current() ;
1318 
1319    if (!read_only) {
1320      Marker before = where() ;
1321      aString data = ""  ;
1322 
1323      int changed = 0 ;
1324      int add = (file.line(current_line))._insert_ch(curx,current_offset,
1325                                                     input.translate_char(ch),
1326                                                     _x_position) ;
1327      data+= input.translate_char(ch) ;
1328      if ((startm.line == current_line) && (startm.offset+1 > curx)) {
1329        startm.offset++ ;
1330        changed = 1 ;
1331      }
1332      if ((endm.line == current_line) && (endm.offset >= curx)) {
1333        endm.offset++ ;
1334        changed = 1 ;
1335      }
1336 
1337      if (changed) {
1338        file.setStartMarker(startm.line, startm.offset) ;
1339        file.setEndMarker(endm.line, endm.offset) ;
1340        _markBlock() ;
1341      }
1342 
1343      delay_compilation++ ;
1344 //     file.recompile_section(sizex, 0) ; // 0 tells recompile_section to not continue after the first line
1345      _relocate_curx(add) ;
1346      win->Move(cury-1+screen_start_line,_x_pos()+screen_start_column) ;
1347      modified = 1 ;
1348      _calc_curx() ;
1349      Marker after = where() ;
1350      undo.record_action(UndoSt::ActInsert, data, before, after, _startm, _endm) ;
1351      _refresh() ;
1352    }
1353 }
1354 
1355 
1356 void
_Undo(Action::Actions act)1357 Edit::_Undo(Action::Actions act)
1358 {
1359    undo.undo_last_action() ;
1360    _relocate_curx(0) ;
1361    int last = undo.get_last_saved() ;
1362    sprintf(buffer, "Undo: %d of %d..+%d modifications since last save", undo.get_current()-last,-last, undo.get_count()-last) ;
1363    win->Message(buffer) ;
1364    _refresh() ;
1365 }
1366 
1367 void
_Redo(Action::Actions act)1368 Edit::_Redo(Action::Actions act)
1369 {
1370    undo.redo_last_action() ;
1371    _relocate_curx(0) ;
1372    int last = undo.get_last_saved() ;
1373    sprintf(buffer, "Redo: %d of %d..+%d modifications since last save", undo.get_current()-last,-last, undo.get_count()-last) ;
1374    win->Message(buffer) ;
1375    _refresh() ;
1376 }
1377 
1378 void
_LaxetCommandHelp(Action::Actions act)1379 Edit::_LaxetCommandHelp(Action::Actions act)
1380 {
1381   // find current word
1382    if ((file.line(current_line)).getCurrentXcode(current_offset,_x_pos())!=VALID_LAXET_COMMAND) {
1383       win->scr->TemporaryExit(0,"latexman asdf",1) ;
1384       refresh() ;
1385       return ;
1386    }
1387 
1388    aString chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1389    char ch = *(const char *)(chr) ;
1390    if (ch == '\\') {
1391       _RealForwardChar(act) ;
1392       chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1393       ch = *(const char *)(chr) ;
1394    }
1395 
1396    while ( (strchr(LETTERS,ch)) && ((current_line > 1) || (curx > 1))) {
1397         _RealBackwardChar(act) ;
1398         chr = ((aString &)file.line(current_line)).at(curx-1,curx) ;
1399         ch = *(const char *)(chr) ;
1400    }
1401    if ( (!strchr(LETTERS,ch))){
1402         _RealForwardChar(act) ;
1403    }
1404    aString word = "" ;
1405    int count = 0 ;
1406    if ((file.line(current_line)).getCurrentXcode(current_offset,_x_pos())==VALID_LAXET_COMMAND) {
1407      while ((file.line(current_line)).getCurrentXcode(current_offset,_x_pos())==VALID_LAXET_COMMAND) {
1408         word +=  ((aString &)file.line(current_line)).at(curx-1,curx) ;
1409         count++ ;
1410        _RealForwardChar(act) ;
1411      }
1412      for (;count>0; count--) _RealBackwardChar(act) ;
1413      char buffer[100] ;
1414      sprintf(buffer, "latexman \\%s", (char *)(const char *)word) ;
1415      win->scr->TemporaryExit(0,buffer,1) ;
1416      refresh() ;
1417    }
1418 }
1419 
1420