1 /* o_buffer.cpp
2 *
3 * Copyright (c) 1994-1996, Marko Macek
4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
8 */
9
10 #include "c_color.h"
11 #include "c_config.h"
12 #include "c_history.h"
13 #include "e_mark.h"
14 #include "e_tags.h"
15 #include "e_undo.h"
16 #include "ftever.h"
17 #include "i_modelview.h"
18 #include "i_view.h"
19 #include "o_cvsdiff.h"
20 #include "o_messages.h"
21 #include "o_svndiff.h"
22 #include "s_files.h"
23 #include "s_string.h"
24 #include "s_util.h"
25
26 #include <ctype.h>
27 #include <time.h>
28
29 SearchReplaceOptions LSearch;
30 int suspendLoads = 0;
31
CreateViewPort(EView * V)32 EViewPort *EBuffer::CreateViewPort(EView *V) {
33 V->Port = new EEditPort(this, V);
34 AddView(V);
35
36 if (Loaded == 0 && !suspendLoads) {
37 Load();
38
39 #ifdef CONFIG_OBJ_MESSAGES
40 if (CompilerMsgs)
41 CompilerMsgs->FindFileErrors(this);
42 #endif
43 #ifdef CONFIG_OBJ_CVS
44 if (CvsDiffView) CvsDiffView->FindFileLines(this);
45 #endif
46
47 #ifdef CONFIG_OBJ_SVN
48 if (SvnDiffView) SvnDiffView->FindFileLines(this);
49 #endif
50
51 markIndex.retrieveForBuffer(this);
52
53 #ifdef CONFIG_HISTORY
54 int r, c;
55
56 if (RetrieveFPos(FileName, r, c) == 1)
57 SetNearPosR(c, r);
58 //printf("setting to c:%d r:%d f:%s", c, r, FileName);
59 V->Port->GetPos();
60 V->Port->ReCenter = 1;
61
62 #ifdef CONFIG_BOOKMARKS
63 if (BFI (this,BFI_SaveBookmarks)==3) RetrieveBookmarks(this);
64 #endif
65 #endif
66 }
67 return V->Port;
68 }
69
EEditPort(EBuffer * B,EView * V)70 EEditPort::EEditPort(EBuffer *B, EView *V) :
71 EViewPort(V),
72 Buffer(B),
73 OldTP(-1, -1),
74 Rows(0),
75 Cols(0)
76 {
77 GetPos();
78
79 if (V && V->MView && V->MView->Win) {
80 V->MView->ConQuerySize(&Cols, &Rows);
81 Rows--;
82 }
83 }
84
~EEditPort()85 EEditPort::~EEditPort() {
86 StorePos();
87 }
88
Resize(int Width,int Height)89 void EEditPort::Resize(int Width, int Height) {
90 Cols = Width;
91 Rows = Height - 1;
92 RedrawAll();
93 }
94
SetTop(int Col,int Line)95 int EEditPort::SetTop(int Col, int Line) {
96 int A, B;
97
98 if (Line >= Buffer->VCount) Line = Buffer->VCount - 1;
99 if (Line < 0) Line = 0;
100
101 A = Line;
102 B = Line + Rows;
103
104 TP.Row = Line;
105 TP.Col = Col;
106
107 if (A >= Buffer->VCount) A = Buffer->VCount - 1;
108 if (B >= Buffer->VCount) {
109 B = Buffer->VCount - 1;
110 }
111 Buffer->Draw(Buffer->VToR(A), -1);
112 return 1;
113 }
114
StorePos()115 void EEditPort::StorePos() {
116 Buffer->CP = CP;
117 Buffer->TP = TP;
118 }
119
GetPos()120 void EEditPort::GetPos() {
121 CP = Buffer->CP;
122 TP = Buffer->TP;
123 }
124
ScrollY(int Delta)125 void EEditPort::ScrollY(int Delta) {
126 // optimization
127 // no need to scroll (clear) entire window which we are about to redraw
128 if (Delta >= Rows || -Delta >= Rows)
129 return ;
130
131 if (Delta < 0) {
132 Delta = -Delta;
133 if (Delta > Rows) return;
134 View->MView->ConScroll(csDown, 0, 0, Cols, Rows, hcPlain_Background, Delta);
135 } else {
136 if (Delta > Rows) return;
137 View->MView->ConScroll(csUp, 0, 0, Cols, Rows, hcPlain_Background, Delta);
138 }
139 }
140
DrawLine(int L,TDrawBuffer B)141 void EEditPort::DrawLine(int L, TDrawBuffer B) {
142 if (L < TP.Row) return;
143 if (L >= TP.Row + Rows) return;
144 if (View->MView->Win->GetViewContext() == View->MView)
145 View->MView->ConPutBox(0, L - TP.Row, Cols, 1, B);
146 // printf("%d %d (%d %d %d %d)\n", 0, L - TP.Row, view->sX, view->sY, view->sW, view->sH);
147 }
148
RedrawAll()149 void EEditPort::RedrawAll() {
150 Buffer->Draw(TP.Row, -1);
151 /// Redraw(0, 0, Cols, Rows);
152 }
153
GetContext()154 int EBuffer::GetContext() {
155 return CONTEXT_FILE;
156 }
157
HandleEvent(TEvent & Event)158 void EEditPort::HandleEvent(TEvent &Event) {
159 EViewPort::HandleEvent(Event);
160 switch (Event.What) {
161 case evKeyDown:
162 {
163 char Ch;
164 if (GetCharFromEvent(Event, &Ch)) {
165 if (Buffer->BeginMacro() == 0)
166 return ;
167 Buffer->TypeChar(Ch);
168 Event.What = evNone;
169 }
170 }
171 break;
172 case evCommand:
173 switch (Event.Msg.Command) {
174 case cmVScrollUp:
175 Buffer->ScrollDown(Event.Msg.Param1);
176 Event.What = evNone;
177 break;
178 case cmVScrollDown:
179 Buffer->ScrollUp(Event.Msg.Param1);
180 Event.What = evNone;
181 break;
182 case cmVScrollPgUp:
183 Buffer->ScrollDown(Rows);
184 Event.What = evNone;
185 break;
186 case cmVScrollPgDn:
187 Buffer->ScrollUp(Rows);
188 Event.What = evNone;
189 break;
190 case cmVScrollMove:
191 {
192 int ypos;
193
194 // fprintf(stderr, "Pos = %d\n\x7", Event.Msg.Param1);
195 ypos = Buffer->CP.Row - TP.Row;
196 Buffer->SetNearPos(Buffer->CP.Col, Event.Msg.Param1 + ypos);
197 SetTop(TP.Col, Event.Msg.Param1);
198 RedrawAll();
199 }
200 Event.What = evNone;
201 break;
202 case cmHScrollLeft:
203 Buffer->ScrollRight(Event.Msg.Param1);
204 Event.What = evNone;
205 break;
206 case cmHScrollRight:
207 Buffer->ScrollLeft(Event.Msg.Param1);
208 Event.What = evNone;
209 break;
210 case cmHScrollPgLt:
211 Buffer->ScrollRight(Cols);
212 Event.What = evNone;
213 break;
214 case cmHScrollPgRt:
215 Buffer->ScrollLeft(Cols);
216 Event.What = evNone;
217 break;
218 case cmHScrollMove:
219 {
220 int xpos;
221
222 xpos = Buffer->CP.Col - TP.Col;
223 Buffer->SetNearPos(Event.Msg.Param1 + xpos, Buffer->CP.Row);
224 SetTop(Event.Msg.Param1, TP.Row);
225 RedrawAll();
226 }
227 Event.What = evNone;
228 break;
229 }
230 break;
231 #ifdef CONFIG_MOUSE
232 case evMouseDown:
233 case evMouseMove:
234 case evMouseAuto:
235 case evMouseUp:
236 HandleMouse(Event);
237 break;
238 #endif
239 }
240 }
241 #ifdef CONFIG_MOUSE
HandleMouse(TEvent & Event)242 void EEditPort::HandleMouse(TEvent &Event) {
243 int x, y, xx, yy, W, H;
244
245 View->MView->ConQuerySize(&W, &H);
246
247 x = Event.Mouse.X;
248 y = Event.Mouse.Y;
249
250 if (Event.What != evMouseDown || y < H - 1) {
251 xx = x + TP.Col;
252 yy = y + TP.Row;
253 if (yy >= Buffer->VCount) yy = Buffer->VCount - 1;
254 if (yy < 0) yy = 0;
255 if (xx < 0) xx = 0;
256
257 switch (Event.What) {
258 case evMouseDown:
259 if (Event.Mouse.Y == H - 1)
260 break;
261 if (View->MView->Win->CaptureMouse(1))
262 View->MView->MouseCaptured = 1;
263 else
264 break;
265
266 View->MView->MouseMoved = 0;
267
268 if (Event.Mouse.Buttons == 1) {
269 // left mouse button down
270 Buffer->SetNearPos(xx, yy);
271 switch (Event.Mouse.Count % 5) {
272 case 1:
273 break;
274 case 2:
275 Buffer->BlockSelectWord();
276 break;
277 case 3:
278 Buffer->BlockSelectLine();
279 break;
280 case 4:
281 Buffer->BlockSelectPara();
282 break;
283 }
284 // Window->Buffer->Redraw();
285 if (SystemClipboard) {
286 // note: copy to second clipboard
287 Buffer->NextCommand();
288 Buffer->BlockCopy(0, 1);
289 }
290 Event.What = evNone;
291 } else if (Event.Mouse.Buttons == 2) {
292 // right mouse button down
293 Buffer->SetNearPos(xx, yy);
294 }
295 break;
296 case evMouseAuto:
297 case evMouseMove:
298 if (View->MView->MouseCaptured) {
299 if (Event.Mouse.Buttons == 1) {
300 // left mouse button move
301 if (!View->MView->MouseMoved) {
302 if (Event.Mouse.KeyMask == kfCtrl) Buffer->BlockMarkColumn();
303 else if (Event.Mouse.KeyMask == kfAlt) Buffer->BlockMarkLine();
304 else Buffer->BlockMarkStream();
305 Buffer->BlockUnmark();
306 if (Event.What == evMouseMove)
307 View->MView->MouseMoved = 1;
308 }
309 Buffer->BlockExtendBegin();
310 Buffer->SetNearPos(xx, yy);
311 Buffer->BlockExtendEnd();
312 } else if (Event.Mouse.Buttons == 2) {
313 // right mouse button move
314 if (Event.Mouse.KeyMask == kfAlt) {
315 } else {
316 Buffer->SetNearPos(xx, yy);
317 }
318 }
319
320 Event.What = evNone;
321 }
322 break;
323 /* case evMouseAuto:
324 if (View->MView->MouseCaptured) {
325 Event.What = evNone;
326 }
327 break;*/
328 case evMouseUp:
329 if (View->MView->MouseCaptured)
330 View->MView->Win->CaptureMouse(0);
331 else
332 break;
333 View->MView->MouseCaptured = 0;
334 if (Event.Mouse.Buttons == 1) {
335 // left mouse button up
336 if (View->MView->MouseMoved)
337 if (SystemClipboard) {
338 // note: copy to second clipboard
339 Buffer->NextCommand();
340 Buffer->BlockCopy(0, 1);
341 }
342 }
343 if (Event.Mouse.Buttons == 2) {
344 // right mouse button up
345 if (!View->MView->MouseMoved) {
346 EEventMap *Map = View->MView->Win->GetEventMap();
347 const char *MName = 0;
348
349 if (Map)
350 MName = Map->GetMenu(EM_LocalMenu);
351 if (MName == 0)
352 MName = "Local";
353 View->MView->Win->Parent->PopupMenu(MName);
354 }
355 }
356 if (Event.Mouse.Buttons == 4) {
357 // middle mouse button up
358 if (SystemClipboard) {
359 // note: copy to second clipboard
360 Buffer->NextCommand();
361 if (Event.Mouse.KeyMask == 0)
362 Buffer->BlockPasteStream(1);
363 else if (Event.Mouse.KeyMask == kfCtrl)
364 Buffer->BlockPasteColumn(1);
365 else if (Event.Mouse.KeyMask == kfAlt)
366 Buffer->BlockPasteLine(1);
367 }
368 }
369 Event.What = evNone;
370 break;
371 }
372 }
373 }
374 #endif
375
UpdateView()376 void EEditPort::UpdateView() {
377 Buffer->Redraw();
378 }
379
RepaintView()380 void EEditPort::RepaintView() {
381 RedrawAll();
382 }
383
UpdateStatus()384 void EEditPort::UpdateStatus() {
385 }
386
RepaintStatus()387 void EEditPort::RepaintStatus() {
388 //Buffer->Redraw();
389 }
390
GetEventMap()391 EEventMap *EBuffer::GetEventMap() {
392 return FindActiveMap(Mode);
393 }
394
BeginMacro()395 int EBuffer::BeginMacro() {
396 return NextCommand();
397 }
398
399 // *INDENT-OFF*
ExecCommand(ExCommands Command,ExState & State)400 int EBuffer::ExecCommand(ExCommands Command, ExState &State) {
401 switch (Command) {
402 case ExMoveUp: return MoveUp();
403 case ExMoveDown: return MoveDown();
404 case ExMoveLeft: return MoveLeft();
405 case ExMoveRight: return MoveRight();
406 case ExMovePrev: return MovePrev();
407 case ExMoveNext: return MoveNext();
408 case ExMoveWordLeft: return MoveWordLeft();
409 case ExMoveWordRight: return MoveWordRight();
410 case ExMoveWordPrev: return MoveWordPrev();
411 case ExMoveWordNext: return MoveWordNext();
412 case ExMoveWordEndLeft: return MoveWordEndLeft();
413 case ExMoveWordEndRight: return MoveWordEndRight();
414 case ExMoveWordEndPrev: return MoveWordEndPrev();
415 case ExMoveWordEndNext: return MoveWordEndNext();
416 case ExMoveWordOrCapLeft: return MoveWordOrCapLeft();
417 case ExMoveWordOrCapRight: return MoveWordOrCapRight();
418 case ExMoveWordOrCapPrev: return MoveWordOrCapPrev();
419 case ExMoveWordOrCapNext: return MoveWordOrCapNext();
420 case ExMoveWordOrCapEndLeft: return MoveWordOrCapEndLeft();
421 case ExMoveWordOrCapEndRight: return MoveWordOrCapEndRight();
422 case ExMoveWordOrCapEndPrev: return MoveWordOrCapEndPrev();
423 case ExMoveWordOrCapEndNext: return MoveWordOrCapEndNext();
424 case ExMoveLineStart: return MoveLineStart();
425 case ExMoveLineEnd: return MoveLineEnd();
426 case ExMovePageStart: return MovePageStart();
427 case ExMovePageEnd: return MovePageEnd();
428 case ExMovePageUp: return MovePageUp();
429 case ExMovePageDown: return MovePageDown();
430 case ExMovePageLeft: return MovePageLeft();
431 case ExMovePageRight: return MovePageEnd();
432 case ExMoveFileStart: return MoveFileStart();
433 case ExMoveFileEnd: return MoveFileEnd();
434 case ExMoveBlockStart: return MoveBlockStart();
435 case ExMoveBlockEnd: return MoveBlockEnd();
436 case ExMoveFirstNonWhite: return MoveFirstNonWhite();
437 case ExMoveLastNonWhite: return MoveLastNonWhite();
438 case ExMovePrevEqualIndent: return MovePrevEqualIndent();
439 case ExMoveNextEqualIndent: return MoveNextEqualIndent();
440 case ExMovePrevTab: return MovePrevTab();
441 case ExMoveNextTab: return MoveNextTab();
442 case ExMoveTabStart: return MoveTabStart();
443 case ExMoveTabEnd: return MoveTabEnd();
444 case ExMoveLineTop: return MoveLineTop();
445 case ExMoveLineCenter: return MoveLineCenter();
446 case ExMoveLineBottom: return MoveLineBottom();
447 case ExMoveBeginOrNonWhite: return MoveBeginOrNonWhite();
448 case ExMoveBeginLinePageFile: return MoveBeginLinePageFile();
449 case ExMoveEndLinePageFile: return MoveEndLinePageFile();
450 case ExScrollLeft: return ScrollLeft(State);
451 case ExScrollRight: return ScrollRight(State);
452 case ExScrollDown: return ScrollDown(State);
453 case ExScrollUp: return ScrollUp(State);
454 case ExKillLine: return KillLine();
455 case ExKillChar: return KillChar();
456 case ExKillCharPrev: return KillCharPrev();
457 case ExKillWord: return KillWord();
458 case ExKillWordPrev: return KillWordPrev();
459 case ExKillWordOrCap: return KillWordOrCap();
460 case ExKillWordOrCapPrev: return KillWordOrCapPrev();
461 case ExKillToLineStart: return KillToLineStart();
462 case ExKillToLineEnd: return KillToLineEnd();
463 case ExKillBlock: return KillBlock();
464 case ExBackSpace: return BackSpace();
465 case ExDelete: return Delete();
466 case ExCharCaseUp: return CharCaseUp();
467 case ExCharCaseDown: return CharCaseDown();
468 case ExCharCaseToggle: return CharCaseToggle();
469 case ExLineCaseUp: return LineCaseUp();
470 case ExLineCaseDown: return LineCaseDown();
471 case ExLineCaseToggle: return LineCaseToggle();
472 case ExLineInsert: return LineInsert();
473 case ExLineAdd: return LineAdd();
474 case ExLineSplit: return LineSplit();
475 case ExLineJoin: return LineJoin();
476 case ExLineNew: return LineNew();
477 case ExLineIndent: return LineIndent();
478 case ExLineTrim: return LineTrim();
479 case ExLineCenter: return LineCenter();
480 case ExInsertSpacesToTab:
481 {
482 int no;
483
484 if(State.GetIntParam(View, &no) == 0)
485 no = 0;
486 return InsertSpacesToTab(no);
487 }
488 case ExInsertTab: return InsertTab();
489 case ExInsertSpace: return InsertSpace();
490 case ExWrapPara:
491 #ifdef CONFIG_WORDWRAP
492 return WrapPara();
493 #else
494 return 0;
495 #endif
496 case ExInsPrevLineChar: return InsPrevLineChar();
497 case ExInsPrevLineToEol: return InsPrevLineToEol();
498 case ExLineDuplicate: return LineDuplicate();
499 case ExBlockBegin: return BlockBegin();
500 case ExBlockEnd: return BlockEnd();
501 case ExBlockUnmark: return BlockUnmark();
502 case ExBlockCut: return BlockCut(0);
503 case ExBlockCopy: return BlockCopy(0);
504 case ExBlockCutAppend: return BlockCut(1);
505 case ExBlockCopyAppend: return BlockCopy(1);
506 case ExClipClear: return ClipClear();
507 case ExBlockPaste: return BlockPaste();
508 case ExBlockKill: return BlockKill();
509 case ExBlockIndent:
510 {
511 int saved_persistence, ret_code;
512
513 saved_persistence = BFI(this, BFI_PersistentBlocks);
514 BFI_SET(this, BFI_PersistentBlocks, 1);
515 ret_code = BlockIndent();
516 BFI_SET(this, BFI_PersistentBlocks, saved_persistence);
517 return ret_code;
518 }
519 case ExBlockUnindent:
520 {
521 int saved_persistence, ret_code;
522
523 saved_persistence = BFI(this, BFI_PersistentBlocks);
524 BFI_SET(this, BFI_PersistentBlocks, 1);
525 ret_code = BlockUnindent();
526 BFI_SET(this, BFI_PersistentBlocks, saved_persistence);
527 return ret_code;
528 }
529 case ExBlockClear: return BlockClear();
530 case ExBlockMarkStream: return BlockMarkStream();
531 case ExBlockMarkLine: return BlockMarkLine();
532 case ExBlockMarkColumn: return BlockMarkColumn();
533 case ExBlockCaseUp: return BlockCaseUp();
534 case ExBlockCaseDown: return BlockCaseDown();
535 case ExBlockCaseToggle: return BlockCaseToggle();
536 case ExBlockExtendBegin: return BlockExtendBegin();
537 case ExBlockExtendEnd: return BlockExtendEnd();
538 case ExBlockReIndent: return BlockReIndent();
539 case ExBlockSelectWord: return BlockSelectWord();
540 case ExBlockSelectLine: return BlockSelectLine();
541 case ExBlockSelectPara: return BlockSelectPara();
542 case ExBlockUnTab: return BlockUnTab();
543 case ExBlockEnTab: return BlockEnTab();
544 #ifdef CONFIG_UNDOREDO
545 case ExUndo: return Undo();
546 case ExRedo: return Redo();
547 #else
548 case ExUndo: return 0;
549 case ExRedo: return 0;
550 #endif
551 case ExMatchBracket: return MatchBracket();
552 case ExMovePrevPos: return MovePrevPos();
553 case ExMoveSavedPosCol: return MoveSavedPosCol();
554 case ExMoveSavedPosRow: return MoveSavedPosRow();
555 case ExMoveSavedPos: return MoveSavedPos();
556 case ExSavePos: return SavePos();
557 case ExCompleteWord: return CompleteWord();
558 case ExBlockPasteStream: return BlockPasteStream();
559 case ExBlockPasteLine: return BlockPasteLine();
560 case ExBlockPasteColumn: return BlockPasteColumn();
561 case ExBlockPasteOver: return BlockPasteOver();
562 case ExShowPosition: return ShowPosition();
563 case ExFoldCreate: return FoldCreate(VToR(CP.Row));
564 case ExFoldDestroy: return FoldDestroy(VToR(CP.Row));
565 case ExFoldDestroyAll: return FoldDestroyAll();
566 case ExFoldPromote: return FoldPromote(VToR(CP.Row));
567 case ExFoldDemote: return FoldDemote(VToR(CP.Row));
568 case ExFoldOpen: return FoldOpen(VToR(CP.Row));
569 case ExFoldOpenNested: return FoldOpenNested();
570 case ExFoldClose: return FoldClose(VToR(CP.Row));
571 case ExFoldOpenAll: return FoldOpenAll();
572 case ExFoldCloseAll: return FoldCloseAll();
573 case ExFoldToggleOpenClose: return FoldToggleOpenClose();
574 case ExFoldCreateAtRoutines: return FoldCreateAtRoutines();
575 case ExMoveFoldTop: return MoveFoldTop();
576 case ExMoveFoldPrev: return MoveFoldPrev();
577 case ExMoveFoldNext: return MoveFoldNext();
578 case ExFileSave: return Save();
579 case ExFilePrint: return FilePrint();
580 case ExBlockPrint: return BlockPrint();
581 case ExBlockTrim: return BlockTrim();
582 case ExFileTrim: return FileTrim();
583 case ExHilitWord:
584 #ifdef CONFIG_WORD_HILIT
585 return HilitWord();
586 #else
587 return 0;
588 #endif
589 case ExSearchWordPrev: return SearchWord(SEARCH_BACK | SEARCH_NEXT);
590 case ExSearchWordNext: return SearchWord(SEARCH_NEXT);
591 case ExHilitMatchBracket: return HilitMatchBracket();
592 case ExToggleAutoIndent: return ToggleAutoIndent();
593 case ExToggleInsert: return ToggleInsert();
594 case ExToggleExpandTabs: return ToggleExpandTabs();
595 case ExToggleShowTabs: return ToggleShowTabs();
596 case ExToggleUndo: return ToggleUndo();
597 case ExToggleReadOnly: return ToggleReadOnly();
598 case ExToggleKeepBackups: return ToggleKeepBackups();
599 case ExToggleMatchCase: return ToggleMatchCase();
600 case ExToggleBackSpKillTab: return ToggleBackSpKillTab();
601 case ExToggleDeleteKillTab: return ToggleDeleteKillTab();
602 case ExToggleSpaceTabs: return ToggleSpaceTabs();
603 case ExToggleIndentWithTabs: return ToggleIndentWithTabs();
604 case ExToggleBackSpUnindents: return ToggleBackSpUnindents();
605 case ExToggleWordWrap: return ToggleWordWrap();
606 case ExToggleTrim: return ToggleTrim();
607 case ExToggleShowMarkers: return ToggleShowMarkers();
608 case ExToggleHilitTags: return ToggleHilitTags();
609 case ExToggleShowBookmarks: return ToggleShowBookmarks();
610 case ExToggleMakeBackups: return ToggleMakeBackups();
611 case ExSetLeftMargin: return SetLeftMargin();
612 case ExSetRightMargin: return SetRightMargin();
613 case ExSetIndentWithTabs: return SetIndentWithTabs(State);
614
615 // stuff with UI
616 case ExMoveToLine: return MoveToLine(State);
617 case ExMoveToColumn: return MoveToColumn(State);
618 case ExFoldCreateByRegexp: return FoldCreateByRegexp(State);
619 #ifdef CONFIG_BOOKMARKS
620 case ExPlaceBookmark: return PlaceBookmark(State);
621 case ExRemoveBookmark: return RemoveBookmark(State);
622 case ExGotoBookmark: return GotoBookmark(State);
623 #else
624 case ExPlaceBookmark: return 0;
625 case ExRemoveBookmark: return 0;
626 case ExGotoBookmark: return 0;
627 #endif
628 case ExPlaceGlobalBookmark: return PlaceGlobalBookmark(State);
629 case ExPushGlobalBookmark: return PushGlobalBookmark();
630 case ExInsertString: return InsertString(State);
631 case ExSelfInsert: return SelfInsert(State);
632 case ExFileReload: return FileReload(State);
633 case ExFileSaveAs: return FileSaveAs(State);
634 case ExFileWriteTo: return FileWriteTo(State);
635 case ExBlockRead: return BlockRead(State);
636 case ExBlockReadStream: return BlockReadStream(State);
637 case ExBlockReadLine: return BlockReadLine(State);
638 case ExBlockReadColumn: return BlockReadColumn(State);
639 case ExBlockWrite: return BlockWrite(State);
640 case ExBlockSort: return BlockSort(0);
641 case ExBlockSortReverse: return BlockSort(1);
642 case ExFind: return Find(State);
643 case ExFindReplace: return FindReplace(State);
644 case ExFindRepeat: return FindRepeat(State);
645 case ExFindRepeatOnce: return FindRepeatOnce(State);
646 case ExFindRepeatReverse: return FindRepeatReverse(State);
647 case ExSearch: return Search(State);
648 case ExSearchB: return SearchB(State);
649 case ExSearchRx: return SearchRx(State);
650 case ExSearchAgain: return SearchAgain(State);
651 case ExSearchAgainB: return SearchAgainB(State);
652 case ExSearchReplace: return SearchReplace(State);
653 case ExSearchReplaceB: return SearchReplaceB(State);
654 case ExSearchReplaceRx: return SearchReplaceRx(State);
655 case ExInsertChar: return InsertChar(State);
656 case ExTypeChar: return TypeChar(State);
657 case ExChangeMode: return ChangeMode(State);
658 //case ExChangeKeys: return ChangeKeys(State);
659 case ExChangeFlags: return ChangeFlags(State);
660 case ExChangeTabSize: return ChangeTabSize(State);
661 case ExChangeLeftMargin: return ChangeLeftMargin(State);
662 case ExChangeRightMargin: return ChangeRightMargin(State);
663 case ExASCIITable:
664 #ifdef CONFIG_I_ASCII
665 return ASCIITable(State);
666 #else
667 return 0;
668 #endif
669 case ExCharTrans: return CharTrans(State);
670 case ExLineTrans: return LineTrans(State);
671 case ExBlockTrans: return BlockTrans(State);
672
673 #ifdef CONFIG_TAGS
674 case ExTagFind: return FindTag(State);
675 case ExTagFindWord: return FindTagWord(State);
676 #endif
677
678 case ExSetCIndentStyle: return SetCIndentStyle(State);
679
680 case ExBlockMarkFunction: return BlockMarkFunction();
681 case ExIndentFunction: return IndentFunction();
682 case ExMoveFunctionPrev: return MoveFunctionPrev();
683 case ExMoveFunctionNext: return MoveFunctionNext();
684 case ExInsertDate: return InsertDate(State);
685 case ExInsertUid: return InsertUid();
686 case ExShowHelpWord: return ShowHelpWord(State);
687 default:
688 ;
689 }
690 return EModel::ExecCommand(Command, State);
691 }
692 // *INDENT-ON*
693
HandleEvent(TEvent & Event)694 void EBuffer::HandleEvent(TEvent &Event) {
695 EModel::HandleEvent(Event);
696 }
697
MoveToLine(ExState & State)698 int EBuffer::MoveToLine(ExState &State) {
699 int No = 0;
700
701 if (State.GetIntParam(View, &No) == 0) {
702 char Num[10];
703
704 sprintf(Num, "%d", VToR(CP.Row) + 1);
705 if (View->MView->Win->GetStr("Goto Line", sizeof(Num), Num, HIST_POSITION) == 0)
706 return 0;
707 No = atol(Num);
708 }
709 return SetNearPosR(CP.Col, No - 1);
710 }
711
MoveToColumn(ExState & State)712 int EBuffer::MoveToColumn(ExState &State) {
713 int No = 0;
714
715 if (State.GetIntParam(View, &No) == 0) {
716 char Num[10];
717
718 sprintf(Num, "%d", CP.Col + 1);
719 if (View->MView->Win->GetStr("Goto Column", 8, Num, HIST_POSITION) == 0) return 0;
720 No = atol(Num);
721 }
722 return SetNearPos(No - 1, CP.Row);
723 }
724
FoldCreateByRegexp(ExState & State)725 int EBuffer::FoldCreateByRegexp(ExState &State) {
726 char strbuf[1024] = "";
727
728 if (State.GetStrParam(View, strbuf, sizeof(strbuf)) == 0) {
729 if (View->MView->Win->GetStr("Create Fold Regexp", sizeof(strbuf), strbuf, HIST_REGEXP) == 0) return 0;
730 }
731 return FoldCreateByRegexp(strbuf);
732 }
733
734 #ifdef CONFIG_BOOKMARKS
PlaceUserBookmark(const char * n,EPoint P)735 int EBuffer::PlaceUserBookmark(const char *n,EPoint P) {
736 char name[256+4] = "_BMK";
737 int result;
738 EPoint prev;
739
740 strcpy (name+4,n);
741 if (GetBookmark (name,prev)==0) {
742 prev.Row=-1;prev.Col=-1;
743 }
744 result=PlaceBookmark(name, P);
745 if (result) {
746 if (BFI (this,BFI_ShowBookmarks)) {
747 FullRedraw ();
748 }
749 if (BFI (this,BFI_SaveBookmarks)==1||BFI (this,BFI_SaveBookmarks)==2) {
750 if (!Modify ()) return result; // Never try to save to read-only
751 #ifdef CONFIG_UNDOREDO
752 if (BFI(this, BFI_Undo)) {
753 if (PushULong(prev.Row) == 0) return 0;
754 if (PushULong(prev.Col) == 0) return 0;
755 if (PushUData(n, strlen(n) + 1) == 0) return 0;
756 if (PushULong(strlen (n)+1) == 0) return 0;
757 if (PushUChar(ucPlaceUserBookmark) == 0) return 0;
758 }
759 #endif
760 }
761 }
762 return result;
763 }
764
RemoveUserBookmark(const char * n)765 int EBuffer::RemoveUserBookmark(const char *n) {
766 char name[256+4] = "_BMK";
767 int result;
768 EPoint p;
769
770 strcpy (name+4,n);
771 GetBookmark (name,p); // p is valid only if remove is successful
772 result=RemoveBookmark(name);
773 if (result) {
774 if (BFI (this,BFI_ShowBookmarks)) {
775 FullRedraw ();
776 }
777 if (BFI (this,BFI_SaveBookmarks)==1||BFI (this,BFI_SaveBookmarks)==2) {
778 if (!Modify ()) return result; // Never try to save to read-only
779 #ifdef CONFIG_UNDOREDO
780 if (PushULong(p.Row) == 0) return 0;
781 if (PushULong(p.Col) == 0) return 0;
782 if (PushUData((void *)n,strlen (n)+1) == 0) return 0;
783 if (PushULong(strlen (n)+1) == 0) return 0;
784 if (PushUChar(ucRemoveUserBookmark) == 0) return 0;
785 #endif
786 }
787 }
788 return result;
789 }
790
GotoUserBookmark(const char * n)791 int EBuffer::GotoUserBookmark(const char *n) {
792 char name[256+4] = "_BMK";
793
794 strcpy (name+4,n);
795 return GotoBookmark(name);
796 }
797
GetUserBookmarkForLine(int searchFrom,int searchForLine,const EBookmark * & eb)798 int EBuffer::GetUserBookmarkForLine(int searchFrom, int searchForLine, const EBookmark* &eb) {
799 int i = searchFrom;
800
801 while ((i = GetBookmarkForLine(i, searchForLine, eb) != -1))
802 if (strncmp(eb->GetName(), "_BMK", 4) == 0)
803 return i;
804
805 return -1;
806 }
807
PlaceBookmark(ExState & State)808 int EBuffer::PlaceBookmark(ExState &State) {
809 char name[256] = "";
810 EPoint P = CP;
811
812 P.Row = VToR(P.Row);
813
814 if (State.GetStrParam(View, name, sizeof(name)) == 0)
815 if (View->MView->Win->GetStr("Place Bookmark", sizeof(name), name, HIST_BOOKMARK) == 0) return 0;
816 return PlaceUserBookmark(name, P);
817 }
818
RemoveBookmark(ExState & State)819 int EBuffer::RemoveBookmark(ExState &State) {
820 char name[256] = "";
821
822 if (State.GetStrParam(View, name, sizeof(name)) == 0)
823 if (View->MView->Win->GetStr("Remove Bookmark", sizeof(name), name, HIST_BOOKMARK) == 0) return 0;
824 return RemoveUserBookmark(name);
825 }
826
GotoBookmark(ExState & State)827 int EBuffer::GotoBookmark(ExState &State) {
828 char name[256] = "";
829
830 if (State.GetStrParam(View, name, sizeof(name)) == 0)
831 if (View->MView->Win->GetStr("Goto Bookmark", sizeof(name), name, HIST_BOOKMARK) == 0) return 0;
832 return GotoUserBookmark(name);
833 }
834 #endif
835
PlaceGlobalBookmark(ExState & State)836 int EBuffer::PlaceGlobalBookmark(ExState &State) {
837 char name[256] = "";
838 EPoint P = CP;
839
840 P.Row = VToR(P.Row);
841
842 if (State.GetStrParam(View, name, sizeof(name)) == 0)
843 if (View->MView->Win->GetStr("Place Global Bookmark", sizeof(name), name, HIST_BOOKMARK) == 0) return 0;
844 if (markIndex.insert(name, this, P) == 0) {
845 Msg(S_ERROR, "Error placing global bookmark %s.", name);
846 }
847 return 1;
848 }
849
PushGlobalBookmark()850 int EBuffer::PushGlobalBookmark() {
851 EPoint P = CP;
852
853 P.Row = VToR(P.Row);
854 EMark *m = markIndex.pushMark(this, P);
855 if (m)
856 Msg(S_INFO, "Placed bookmark %s", m->GetName());
857 return m ? 1 : 0;
858 }
859
InsertChar(ExState & State)860 int EBuffer::InsertChar(ExState &State) {
861 char Ch;
862 int No;
863
864 if (State.GetIntParam(View, &No) == 0) {
865 TEvent E;
866 E.What = evKeyDown;
867 E.Key.Code = View->MView->Win->GetChar("Quote Char:");
868 if (!GetCharFromEvent(E, &Ch)) return 0;
869 No = Ch;
870 }
871 if (No < 0 || No > 255) return 0;
872 Ch = char(No);
873 return InsertChar(Ch);
874 }
875
TypeChar(ExState & State)876 int EBuffer::TypeChar(ExState &State) {
877 char Ch;
878 int No;
879
880 if (State.GetIntParam(View, &No) == 0) {
881 TEvent E;
882 E.What = evKeyDown;
883 E.Key.Code = View->MView->Win->GetChar(0);
884 if (!GetCharFromEvent(E, &Ch)) return 0;
885 No = Ch;
886 }
887 if (No < 0 || No > 255) return 0;
888 Ch = char(No);
889 return TypeChar(Ch);
890 }
891
InsertString(ExState & State)892 int EBuffer::InsertString(ExState &State) {
893 char strbuf[1024] = "";
894
895 if (State.GetStrParam(View, strbuf, sizeof(strbuf)) == 0) {
896 if (View->MView->Win->GetStr("Insert String", sizeof(strbuf), strbuf, HIST_DEFAULT) == 0)
897 return 0;
898 }
899 return InsertString(strbuf, strlen(strbuf));
900 }
901
902 extern int LastEventChar;
903
SelfInsert(ExState &)904 int EBuffer::SelfInsert(ExState &/*State*/) {
905 if (LastEventChar != -1)
906 return TypeChar(char(LastEventChar));
907 return 0;
908 }
909
FileReload(ExState &)910 int EBuffer::FileReload(ExState &/*State*/) {
911 if (Modified) {
912 switch (View->MView->Win->Choice(GPC_ERROR, "File Modified",
913 2,
914 "&Reload",
915 "&Cancel",
916 "%s", FileName))
917 {
918 case 0:
919 break;
920 case 1:
921 case -1:
922 default:
923 return 0;
924 }
925 }
926 // GetNewNumber();
927 return Reload();
928 }
929
FileSaveAs(const char * FName)930 int EBuffer::FileSaveAs(const char *FName) {
931 char Name[MAXPATH];
932
933 if (ExpandPath(FName, Name, sizeof(Name)) == -1) {
934 View->MView->Win->Choice(GPC_ERROR, "Error", 1, "O&K", "Invalid path: %s.", FName);
935 return 0;
936 }
937 if (FindFile(Name) == 0) {
938 if (FileExists(Name)) {
939 switch (View->MView->Win->Choice(GPC_ERROR, "File Exists",
940 2,
941 "&Overwrite",
942 "&Cancel",
943 "%s", Name))
944 {
945 case 0:
946 break;
947 case 1:
948 case -1:
949 default:
950 return 0;
951
952 }
953 }
954 free(FileName);
955 FileName = strdup(Name);
956 UpdateTitle();
957 return Save();
958 } else {
959 View->MView->Win->Choice(GPC_ERROR, "Error", 1, "O&K", "Already editing '%s.'", Name);
960 return 0;
961 }
962 }
963
FileSaveAs(ExState & State)964 int EBuffer::FileSaveAs(ExState &State) {
965 char FName[MAXPATH];
966
967 strcpy(FName, FileName);
968 if (State.GetStrParam(View, FName, sizeof(FName)) == 0)
969 if (View->MView->Win->GetFile("Save As", sizeof(FName), FName, HIST_PATH, GF_SAVEAS) == 0)
970 return 0;
971 return FileSaveAs(FName);
972 }
973
FileWriteTo(const char * FName)974 int EBuffer::FileWriteTo(const char *FName) {
975 char Name[MAXPATH];
976
977 if (ExpandPath(FName, Name, sizeof(Name)) == -1) {
978 View->MView->Win->Choice(GPC_ERROR, "Error", 1, "O&K", "Invalid path: %s.", FName);
979 return 0;
980 }
981 if (FindFile(Name) == 0) {
982 if (FileExists(Name)) {
983 switch (View->MView->Win->Choice(GPC_ERROR, "File Exists",
984 2,
985 "&Overwrite",
986 "&Cancel",
987 "%s", Name))
988 {
989 case 0:
990 break;
991 case 1:
992 case -1:
993 default:
994 return 0;
995 }
996 }
997 return SaveTo(Name);
998 } else {
999 View->MView->Win->Choice(GPC_ERROR, "Error", 1, "O&K", "Already editing '%s.'", Name);
1000 return 0;
1001 }
1002 }
1003
FileWriteTo(ExState & State)1004 int EBuffer::FileWriteTo(ExState &State) {
1005 char FName[MAXPATH];
1006
1007 strcpy(FName, FileName);
1008 if (State.GetStrParam(View, FName, sizeof(FName)) == 0)
1009 if (View->MView->Win->GetFile("Write To", sizeof(FName), FName, HIST_PATH, GF_SAVEAS) == 0) return 0;
1010 return FileWriteTo(FName);
1011 }
1012
BlockReadX(ExState & State,int blockMode)1013 int EBuffer::BlockReadX(ExState &State, int blockMode) {
1014 char Name[MAXPATH];
1015 char FName[MAXPATH];
1016
1017 if (JustDirectory(FileName, FName, sizeof(FName)) == -1) return 0;
1018 SlashDir(FName);
1019 if (State.GetStrParam(View, FName, sizeof(FName)) == 0)
1020 if (View->MView->Win->GetFile("Read block", sizeof(FName), FName, HIST_PATH, GF_OPEN) == 0) return 0;
1021
1022 if (ExpandPath(FName, Name, sizeof(Name)) == -1) {
1023 View->MView->Win->Choice(GPC_ERROR, "Error", 1, "O&K", "Invalid path: %s.", FName);
1024 return 0;
1025 }
1026 return BlockReadFrom(FName, blockMode);
1027 }
1028
BlockRead(ExState & State)1029 int EBuffer::BlockRead(ExState &State) {
1030 return BlockReadX(State, BlockMode);
1031 }
1032
BlockReadStream(ExState & State)1033 int EBuffer::BlockReadStream(ExState &State) {
1034 return BlockReadX(State, bmStream);
1035 }
1036
BlockReadLine(ExState & State)1037 int EBuffer::BlockReadLine(ExState &State) {
1038 return BlockReadX(State, bmLine);
1039 }
1040
BlockReadColumn(ExState & State)1041 int EBuffer::BlockReadColumn(ExState &State) {
1042 return BlockReadX(State, bmColumn);
1043 }
1044
BlockWrite(ExState & State)1045 int EBuffer::BlockWrite(ExState &State) {
1046 char Name[MAXPATH];
1047 char FName[MAXPATH];
1048 int Append = 0;
1049
1050 if (JustDirectory(FileName, FName, sizeof(FName)) == -1) return 0;
1051 SlashDir(FName);
1052 if (State.GetStrParam(View, FName, sizeof(FName)) == 0)
1053 if (View->MView->Win->GetFile("Write block", sizeof(FName), FName, HIST_PATH, GF_SAVEAS) == 0)
1054 return 0;
1055
1056 if (ExpandPath(FName, Name, sizeof(Name)) == -1) {
1057 View->MView->Win->Choice(GPC_ERROR, "Error", 1, "O&K", "Invalid path: %s.", FName);
1058 return 0;
1059 }
1060 if (FindFile(Name) == 0) {
1061 if (FileExists(Name)) {
1062 switch (View->MView->Win->Choice(GPC_ERROR, "File Exists",
1063 3,
1064 "&Overwrite",
1065 "&Append",
1066 "&Cancel",
1067 "%s", Name))
1068 {
1069 case 0:
1070 break;
1071 case 1:
1072 Append = 1;
1073 break;
1074 case 2:
1075 case -1:
1076 default:
1077 return 0;
1078
1079 }
1080 }
1081 } else {
1082 View->MView->Win->Choice(GPC_ERROR, "Error", 1, "O&K", "Already editing '%s.'", Name);
1083 return 0;
1084 }
1085 return BlockWriteTo(Name, Append);
1086 }
1087
Find(ExState & State)1088 int EBuffer::Find(ExState &State) {
1089 char find[MAXSEARCH+1] = "";
1090 char options[32] = "";
1091
1092 if (State.GetStrParam(View, find, sizeof(find)) != 0) {
1093 if (State.GetStrParam(View, options, sizeof(options)) == 0)
1094 strcpy(options, BFS(this, BFS_DefFindOpt));
1095
1096 LSearch.ok = 0;
1097 strcpy(LSearch.strSearch, find);
1098 LSearch.strReplace[0] = 0;
1099 LSearch.Options = 0;
1100 if (ParseSearchOptions(0, options, LSearch.Options) == 0) return 0;
1101 LSearch.ok = 1;
1102 } else if ((HaveGUIDialogs & GUIDLG_FIND) && GUIDialogs) {
1103 LSearch.ok = 0;
1104 LSearch.strSearch[0] = 0;
1105 LSearch.strReplace[0] = 0;
1106 LSearch.Options = 0;
1107 if (BFS(this, BFS_DefFindOpt))
1108 strcpy(options, BFS(this, BFS_DefFindOpt));
1109 if (ParseSearchOptions(0, options, LSearch.Options) == 0)
1110 LSearch.Options = 0;
1111
1112 if (DLGGetFind(View->MView->Win, LSearch) == 0)
1113 return 0;
1114 } else {
1115 if (BFS(this, BFS_DefFindOpt))
1116 strcpy(options, BFS(this, BFS_DefFindOpt));
1117 if (View->MView->Win->GetStr("Find", sizeof(find), find, HIST_SEARCH) == 0) return 0;
1118 if (View->MView->Win->GetStr("Options (All/Block/Cur/Delln/Glob/Igncase/Joinln/Rev/Word/regX)", sizeof(options), options, HIST_SEARCHOPT) == 0) return 0;
1119
1120 LSearch.ok = 0;
1121 strcpy(LSearch.strSearch, find);
1122 LSearch.strReplace[0] = 0;
1123 LSearch.Options = 0;
1124 if (ParseSearchOptions(0, options, LSearch.Options) == 0) return 0;
1125 LSearch.ok = 1;
1126 }
1127 if (LSearch.ok == 0) return 0;
1128 LSearch.Options |= SEARCH_CENTER;
1129 if (Find(LSearch) == 0) return 0;
1130 return 1;
1131 }
1132
FindReplace(ExState & State)1133 int EBuffer::FindReplace(ExState &State) {
1134 char find[MAXSEARCH+1] = "";
1135 char replace[MAXSEARCH+1] = "";
1136 char options[32] = "";
1137
1138 if (State.GetStrParam(View, find, sizeof(find)) != 0) {
1139 if (State.GetStrParam(View, replace, sizeof(replace)) == 0)
1140 return 0;
1141 if (State.GetStrParam(View, options, sizeof(options)) == 0)
1142 return 0;
1143
1144 LSearch.ok = 0;
1145 strcpy(LSearch.strSearch, find);
1146 strcpy(LSearch.strReplace, replace);
1147 LSearch.Options = 0;
1148 if (ParseSearchOptions(1, options, LSearch.Options) == 0) return 0;
1149 LSearch.Options |= SEARCH_REPLACE;
1150 LSearch.ok = 1;
1151 } else if ((HaveGUIDialogs & GUIDLG_FINDREPLACE) && GUIDialogs) {
1152 LSearch.ok = 0;
1153 LSearch.strSearch[0] = 0;
1154 LSearch.strReplace[0] = 0;
1155 LSearch.Options = 0;
1156 if (BFS(this, BFS_DefFindReplaceOpt))
1157 strcpy(options, BFS(this, BFS_DefFindReplaceOpt));
1158 if (ParseSearchOptions(1, options, LSearch.Options) == 0)
1159 LSearch.Options = 0;
1160 if (DLGGetFindReplace(View->MView->Win, LSearch) == 0)
1161 return 0;
1162 } else {
1163 if (BFS(this, BFS_DefFindReplaceOpt))
1164 strcpy(options, BFS(this, BFS_DefFindReplaceOpt));
1165 if (State.GetStrParam(View, find, sizeof(find)) == 0)
1166 if (View->MView->Win->GetStr("Find", sizeof(find), find, HIST_SEARCH) == 0) return 0;
1167 if (State.GetStrParam(View, replace, sizeof(replace)) == 0)
1168 if (View->MView->Win->GetStr("Replace", sizeof(replace), replace, HIST_SEARCH) == 0) return 0;
1169 if (State.GetStrParam(View, options, sizeof(options)) == 0)
1170 if (View->MView->Win->GetStr("Options (All/Block/Cur/Delln/Glob/Igncase/Joinln/Rev/Noask/Word/regX)", sizeof(options), options, HIST_SEARCHOPT) == 0) return 0;
1171
1172 LSearch.ok = 0;
1173 strcpy(LSearch.strSearch, find);
1174 strcpy(LSearch.strReplace, replace);
1175 LSearch.Options = 0;
1176 if (ParseSearchOptions(1, options, LSearch.Options) == 0) return 0;
1177 LSearch.Options |= SEARCH_REPLACE;
1178 LSearch.ok = 1;
1179 }
1180 if (LSearch.ok == 0) return 0;
1181 LSearch.Options |= SEARCH_CENTER;
1182 if (Find(LSearch) == 0) return 0;
1183 return 1;
1184 }
1185
FindRepeat(ExState & State)1186 int EBuffer::FindRepeat(ExState &State) {
1187 if (LSearch.ok == 0) return Find(State);
1188 LSearch.Options |= SEARCH_NEXT;
1189 LSearch.Options &= ~SEARCH_GLOBAL;
1190 if (Find(LSearch) == 0) return 0;
1191 return 1;
1192 }
1193
FindRepeatReverse(ExState & State)1194 int EBuffer::FindRepeatReverse(ExState &State) {
1195 int rc;
1196
1197 if (LSearch.ok == 0) return Find(State);
1198 LSearch.Options |= SEARCH_NEXT;
1199 LSearch.Options &= ~SEARCH_GLOBAL;
1200 LSearch.Options ^= SEARCH_BACK;
1201 rc = Find(LSearch);
1202 LSearch.Options ^= SEARCH_BACK;
1203 return rc;
1204 }
1205
FindRepeatOnce(ExState & State)1206 int EBuffer::FindRepeatOnce(ExState &State) {
1207 if (LSearch.ok == 0) return Find(State);
1208 LSearch.Options |= SEARCH_NEXT;
1209 LSearch.Options &= ~SEARCH_GLOBAL;
1210 LSearch.Options &= ~SEARCH_ALL;
1211 if (Find(LSearch) == 0) return 0;
1212 return 1;
1213 }
1214
ChangeMode(ExState & State)1215 int EBuffer::ChangeMode(ExState &State) {
1216 char Mode[32] = "";
1217 int rc;
1218
1219 if (State.GetStrParam(View, Mode, sizeof(Mode)) == 0)
1220 if (View->MView->Win->GetStr("Mode", sizeof(Mode), Mode, HIST_SETUP) == 0) return 0;
1221
1222 rc = ChangeMode(Mode);
1223 FullRedraw();
1224 return rc;
1225 }
1226
ChangeKeys(ExState & State)1227 int EBuffer::ChangeKeys(ExState &State) {
1228 int rc;
1229 char Mode[32] = "";
1230
1231 if (State.GetStrParam(View, Mode, sizeof(Mode)) == 0)
1232 if (View->MView->Win->GetStr("Mode", sizeof(Mode), Mode, HIST_SETUP) == 0) return 0;
1233
1234 rc = ChangeKeys(Mode);
1235 FullRedraw();
1236 return rc;
1237 }
1238
ChangeFlags(ExState & State)1239 int EBuffer::ChangeFlags(ExState &State) {
1240 int rc;
1241 char Mode[32] = "";
1242
1243 if (State.GetStrParam(View, Mode, sizeof(Mode)) == 0)
1244 if (View->MView->Win->GetStr("Mode", sizeof(Mode), Mode, HIST_SETUP) == 0) return 0;
1245
1246 rc = ChangeFlags(Mode);
1247 FullRedraw();
1248 return rc;
1249 }
1250
ChangeTabSize(ExState & State)1251 int EBuffer::ChangeTabSize(ExState &State) {
1252 int No;
1253
1254 if (State.GetIntParam(View, &No) == 0) {
1255 char Num[10];
1256
1257 sprintf(Num, "%d", BFI(this, BFI_TabSize));
1258 if (View->MView->Win->GetStr("TabSize", sizeof(Num), Num, HIST_SETUP) == 0) return 0;
1259 No = atol(Num);
1260 }
1261 if (No < 1) return 0;
1262 if (No > 32) return 0;
1263 BFI(this, BFI_TabSize) = No;
1264 FullRedraw();
1265 return 1;
1266 }
1267
SetIndentWithTabs(ExState & State)1268 int EBuffer::SetIndentWithTabs(ExState &State) {
1269 int No;
1270
1271 if (State.GetIntParam(View, &No) == 0) return 0;
1272 Flags.num[BFI_IndentWithTabs] = No ? 1 : 0;
1273 return 1;
1274 }
1275
ChangeRightMargin(ExState & State)1276 int EBuffer::ChangeRightMargin(ExState &State) {
1277 char Num[10];
1278 int No;
1279
1280 if (State.GetIntParam(View, &No) == 0) {
1281 sprintf(Num, "%d", BFI(this, BFI_RightMargin) + 1);
1282 if (View->MView->Win->GetStr("RightMargin", sizeof(Num), Num, HIST_SETUP) == 0) return 0;
1283 No = atol(Num) - 1;
1284 }
1285 if (No <= 1) return 0;
1286 BFI(this, BFI_RightMargin) = No;
1287 Msg(S_INFO, "RightMargin set to %d.", No + 1);
1288 return 1;
1289 }
1290
ChangeLeftMargin(ExState & State)1291 int EBuffer::ChangeLeftMargin(ExState &State) {
1292 char Num[10];
1293 int No;
1294
1295 if (State.GetIntParam(View, &No) == 0) {
1296 sprintf(Num, "%d", BFI(this, BFI_LeftMargin) + 1);
1297 if (View->MView->Win->GetStr("LeftMargin", sizeof(Num), Num, HIST_SETUP) == 0) return 0;
1298 No = atol(Num) - 1;
1299 }
1300 if (No < 0) return 0;
1301 BFI(this, BFI_LeftMargin) = No;
1302 Msg(S_INFO, "LeftMargin set to %d.", No + 1);
1303 return 1;
1304 }
1305
1306
CanQuit()1307 int EBuffer::CanQuit() {
1308 if (Modified)
1309 return 0;
1310 else
1311 return 1;
1312 }
1313
ConfQuit(GxView * V,int multiFile)1314 int EBuffer::ConfQuit(GxView *V, int multiFile) {
1315 if (Modified) {
1316 if (multiFile) {
1317 switch (V->Choice(GPC_ERROR,
1318 "File Modified",
1319 5,
1320 "&Save",
1321 "&As",
1322 "A&ll",
1323 "&Discard",
1324 "&Cancel",
1325 "%s", FileName))
1326 {
1327 case 0: /* Save */
1328 if (Save() == 0) return 0;
1329 break;
1330 case 1: /* As */
1331 {
1332 char FName[MAXPATH];
1333 strcpy(FName, FileName);
1334 if (V->GetFile("Save As", sizeof(FName), FName, HIST_PATH, GF_SAVEAS) == 0) return 0;
1335 if (FileSaveAs(FName) == 0) return 0;
1336 }
1337 break;
1338 case 2: /* Save all */
1339 return -2;
1340 case 3: /* Discard */
1341 break;
1342 case 4: /* Cancel */
1343 case -1:
1344 default:
1345 return 0;
1346 }
1347 }else {
1348 switch (V->Choice(GPC_ERROR,
1349 "File Modified",
1350 4,
1351 "&Save",
1352 "&As",
1353 "&Discard",
1354 "&Cancel",
1355 "%s", FileName))
1356 {
1357 case 0: /* Save */
1358 if (Save() == 0) return 0;
1359 break;
1360 case 1: /* As */
1361 {
1362 char FName[MAXPATH];
1363 strcpy(FName, FileName);
1364 if (V->GetFile("Save As", sizeof(FName), FName, HIST_PATH, GF_SAVEAS) == 0) return 0;
1365 if (FileSaveAs(FName) == 0) return 0;
1366 }
1367 break;
1368 case 2: /* Discard */
1369 break;
1370 case 3: /* Cancel */
1371 case -1:
1372 default:
1373 return 0;
1374 }
1375 }
1376 }
1377 return 1;
1378 }
1379
GetName(char * AName,size_t MaxLen)1380 void EBuffer::GetName(char *AName, size_t MaxLen) {
1381 strlcpy(AName, FileName, MaxLen);
1382 }
1383
GetPath(char * APath,size_t MaxLen)1384 void EBuffer::GetPath(char *APath, size_t MaxLen) {
1385 JustDirectory(FileName, APath, MaxLen);
1386 }
1387
GetInfo(char * AInfo,size_t)1388 void EBuffer::GetInfo(char *AInfo, size_t /*MaxLen*/) {
1389 char buf[256] = {0};
1390 char winTitle[256] = {0};
1391
1392 JustFileName(FileName, buf, sizeof(buf));
1393 if (buf[0] == '\0') // if there is no filename, try the directory name.
1394 JustLastDirectory(FileName, buf, sizeof(buf));
1395
1396 if (buf[0] != 0) // if there is a file/dir name, stick it in here.
1397 {
1398 strlcat(winTitle, buf, sizeof(winTitle));
1399 strlcat(winTitle, " - ", sizeof(winTitle));
1400 }
1401 strlcat(winTitle, FileName, sizeof(winTitle));
1402
1403 sprintf(AInfo,
1404 "%2d %04d:%03d%c%-150s ",
1405 ModelNo,
1406 1 + CP.Row, 1 + CP.Col,
1407 Modified ? '*': ' ',
1408 winTitle);
1409 }
1410
GetTitle(char * ATitle,size_t MaxLen,char * ASTitle,size_t SMaxLen)1411 void EBuffer::GetTitle(char *ATitle, size_t MaxLen, char *ASTitle, size_t SMaxLen) {
1412
1413 strlcpy(ATitle, FileName, MaxLen);
1414 char *p = SepRChr(FileName);
1415 strlcpy(ASTitle, (p) ? p + 1 : FileName, SMaxLen);
1416 }
1417
1418 #ifdef CONFIG_I_ASCII
ASCIITable(ExState &)1419 int EBuffer::ASCIITable(ExState &/*State*/) {
1420 int rc;
1421
1422 rc = View->MView->Win->PickASCII();
1423 if (rc != -1)
1424 return InsertChar(char(rc));
1425
1426 return 0;
1427 }
1428 #endif
1429
ScrollLeft(ExState & State)1430 int EBuffer::ScrollLeft(ExState &State) {
1431 int Cols;
1432
1433 if (State.GetIntParam(View, &Cols) == 0)
1434 Cols = 8;
1435 return ScrollLeft(Cols);
1436 }
1437
ScrollRight(ExState & State)1438 int EBuffer::ScrollRight(ExState &State) {
1439 int Cols;
1440
1441 if (State.GetIntParam(View, &Cols) == 0)
1442 Cols = 8;
1443 return ScrollRight(Cols);
1444 }
1445
ScrollDown(ExState & State)1446 int EBuffer::ScrollDown(ExState &State) {
1447 int Rows;
1448
1449 if (State.GetIntParam(View, &Rows) == 0)
1450 Rows = 1;
1451 return ScrollDown(Rows);
1452 }
1453
ScrollUp(ExState & State)1454 int EBuffer::ScrollUp(ExState &State) {
1455 int Rows;
1456
1457 if (State.GetIntParam(View, &Rows) == 0)
1458 Rows = 1;
1459 return ScrollUp(Rows);
1460 }
1461
1462 #ifdef CONFIG_TAGS
FindTag(ExState & State)1463 int EBuffer::FindTag(ExState &State) {
1464 char Tag[MAXSEARCH] = "";
1465
1466 if (State.GetStrParam(View, Tag, sizeof(Tag)) == 0)
1467 if (View->MView->Win->GetStr("Find tag", sizeof(Tag), Tag, HIST_SEARCH) == 0) return 0;
1468
1469 int j = 2;
1470 while (j--) {
1471 int i;
1472
1473 i = TagFind(this, View, Tag);
1474 if (i > 0)
1475 return 1;
1476 else if (j && (i < 0)) {
1477 /* Try autoload tags */
1478 if (View->ExecCommand(ExTagLoad, State) == 0)
1479 break;
1480 } else {
1481 Msg(S_INFO, "Tag '%s' not found.", Tag);
1482 break;
1483 }
1484 }
1485 return 0;
1486
1487 }
1488 #endif
1489
1490 // these two will probably be replaced in the future
InsertDate(ExState & State)1491 int EBuffer::InsertDate(ExState &State) {
1492 char strArg[128] = "";
1493 char buf[128], *p;
1494
1495 time_t t;
1496
1497 time(&t);
1498
1499 if (State.GetStrParam(View, strArg, sizeof(strArg))) {
1500 struct tm *tt = localtime(&t);
1501 strftime(buf, sizeof(buf), strArg, tt);
1502 buf[sizeof(buf) - 1] = 0;
1503 } else {
1504 //** 012345678901234567890123
1505 //** Wed Jan 02 02:23:54 1991
1506 p = ctime(&t);
1507 sprintf(buf, "%.10s %.4s", p, p + 20);
1508 }
1509 //puts(buf);
1510
1511 return InsertString(buf, strlen(buf));
1512 }
1513
1514
InsertUid()1515 int EBuffer::InsertUid() {
1516 const char *p = getenv("USER");
1517 if (p == 0) p = getenv("NAME");
1518 if (p == 0) p = getenv("ID");
1519 // mostly for Windows. Why they can't just be standard, I don't know...
1520 if (p == 0) p = getenv("USERNAME");
1521 if (p == 0) {
1522 Msg(S_INFO, "User ID not set ($USER).");
1523 //return 0;
1524 p = "UNKNOWN USER";
1525 }
1526 return InsertString(p, strlen(p));
1527 }
1528
ShowHelpWord(ExState & State)1529 int EBuffer::ShowHelpWord(ExState &State) {
1530 //** Code for BlockSelectWord to find the word under the cursor,
1531 const char *achr = "+-_."; // these are accepted characters
1532 char buf[128];
1533 int Y = VToR(CP.Row);
1534 PELine L = RLine(Y);
1535 int P;
1536
1537 P = CharOffset(L, CP.Col);
1538
1539 // fix \b for the case of CATBS
1540 for(int i = 0; i < P; i++) {
1541 //printf("%d - %d %d %c %c\n", i, P, L->Chars[i],
1542 //L->Chars[i], L->Chars[P]);
1543 if ((L->Chars[i] == '\b') && (P < (L->Count - 2)))
1544 P += 2;
1545 }
1546 size_t len = 0;
1547 if (P < L->Count) {
1548 // To start of word,
1549 while ((P > 0)
1550 && ((L->Chars[P - 1] == '\b') || isalnum(L->Chars[P - 1])
1551 || (strchr(achr, L->Chars[P - 1]) != NULL)))
1552 P--; // '_' for underline is hidden in achr
1553 if ((P < (L->Count - 1)) && (L->Chars[P] == '\b'))
1554 P++;
1555 // To end of word,
1556 while ((len < (sizeof(buf) - 1)) && (P < L->Count)) {
1557 if (((P + 1) < L->Count) && (L->Chars[P + 1] == '\b'))
1558 P += 2;
1559 else if (isalnum(L->Chars[P])
1560 || (strchr(achr, L->Chars[P]) != NULL))
1561 buf[len++] = L->Chars[P++];
1562 else
1563 break;
1564 }
1565 }
1566 buf[len] = 0;
1567 //printf("Word: %s\n", buf);
1568 //if (buf[0] == 0) {
1569 // Msg(INFO, "No valid word under the cursor.");
1570 // return 0;
1571 //}
1572 return View->SysShowHelp(State, buf[0] ? buf : 0);
1573 }
1574
GetStrVar(int var,char * str,size_t buflen)1575 int EBuffer::GetStrVar(int var, char *str, size_t buflen) {
1576 if (buflen == 0)
1577 return 0;
1578 //puts("variable EBuffer\x7");
1579 switch (var) {
1580 case mvFilePath:
1581 //puts("variable FilePath\x7");
1582 strncpy(str, FileName, buflen);
1583 str[buflen - 1] = 0;
1584 return 1;
1585
1586 case mvFileName:
1587 JustFileName(FileName, str, buflen);
1588 return 1;
1589
1590 case mvFileDirectory:
1591 JustDirectory(FileName, str, buflen);
1592 return 1;
1593 case mvFileBaseName:
1594 {
1595 char buf[MAXPATH];
1596 char *dot, *dot2;
1597
1598 JustFileName(FileName, buf, sizeof(buf));
1599
1600 dot = strchr(buf, '.');
1601 while ((dot2 = strchr(dot + 1, '.')) != NULL)
1602 dot = dot2;
1603 if (dot)
1604 *dot = 0;
1605 strlcpy(str, buf, buflen);
1606 }
1607 return 1;
1608
1609 case mvFileExtension:
1610 {
1611 char buf[MAXPATH];
1612 char *dot;
1613
1614 JustFileName(FileName, buf, sizeof(buf));
1615
1616 dot = strrchr(buf, '.');
1617 if (dot)
1618 strlcpy(str, dot, buflen);
1619 else
1620 str[0] = 0;
1621 }
1622 return 1;
1623
1624 case mvChar:
1625 {
1626 PELine L;
1627 int P;
1628
1629 L = RLine(CP.Row);
1630 P = CharOffset(L, CP.Col);
1631
1632 strlcpy(str, "", buflen);
1633
1634 if (ChClass(L->Chars[P]))
1635 {
1636 char tmp[2];
1637
1638 // make copy of character
1639 tmp[0] = L->Chars[P];
1640 tmp[1] = 0;
1641
1642 strlcat(str, tmp, buflen);
1643 }
1644 }
1645 return 1;
1646
1647 case mvWord:
1648 {
1649 PELine L;
1650 int P, C;
1651 int wordBegin, wordEnd;
1652
1653 L = RLine(CP.Row);
1654 P = CharOffset(L, CP.Col);
1655
1656 strlcpy(str, "", buflen);
1657
1658 if (ChClass(L->Chars[P]))
1659 {
1660 C = ChClassK(L->Chars[P]);
1661
1662 // search start of word
1663 while ((P>0) && (C == ChClassK(L->Chars[P-1]))) P--;
1664
1665 wordBegin = P;
1666
1667 // search end of word
1668 while ((P< L->Count) && (C == ChClassK(L->Chars[P]))) P++;
1669
1670 wordEnd = P;
1671
1672 // calculate total length for buffer copy
1673 size_t length = wordEnd - wordBegin;
1674
1675 if ((length + 1) < buflen)
1676 {
1677 length++;
1678 } else
1679 {
1680 length = buflen;
1681 }
1682
1683 // copy word to buffer
1684 strlcpy(str, &L->Chars[wordBegin], length);
1685 }
1686 }
1687 return 1;
1688
1689 case mvLine:
1690 {
1691 PELine L;
1692
1693 L = RLine(CP.Row);
1694
1695 strlcpy(str, "", buflen);
1696
1697 if (L->Count > 0)
1698 {
1699 // calculate total length for buffer copy
1700 size_t length = L->Count;
1701
1702 if ((length + 1) < buflen)
1703 {
1704 length++;
1705 } else
1706 {
1707 length = buflen;
1708 }
1709
1710 // copy word to buffer
1711 strlcpy(str, L->Chars, length);
1712 }
1713 }
1714 return 1;
1715
1716 case mvFTEVer:
1717 strlcpy(str, VERSION, buflen);
1718 return 1;
1719 }
1720
1721 return EModel::GetStrVar(var, str, buflen);
1722 }
1723
GetIntVar(int var,int * value)1724 int EBuffer::GetIntVar(int var, int *value) {
1725 switch (var) {
1726 case mvCurRow: *value = VToR(CP.Row) + 1; return 1;
1727 case mvCurCol: *value = CP.Col; return 1;
1728 }
1729 return EModel::GetIntVar(var, value);
1730 }
1731