1
2 // ------------------------------------------------------------------
3 // GoldED+
4 // Copyright (C) 1990-1999 Odinn Sorensen
5 // Copyright (C) 1999-2000 Alexander S. Aganichev
6 // ------------------------------------------------------------------
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 // MA 02111-1307 USA
21 // ------------------------------------------------------------------
22 // $Id: geedit2.cpp,v 1.40 2011/02/22 16:18:21 stas_degteff Exp $
23 // ------------------------------------------------------------------
24 // The Internal Editor (IE), part 2.
25 // ------------------------------------------------------------------
26
27 #include <golded.h>
28 #include <geedit.h>
29 #include <gutlcode.h>
30 #include <gutlclip.h>
31
32 #if defined(__USE_ALLOCA__)
33 #include <malloc.h>
34 #endif
35
36
37 // ------------------------------------------------------------------
38 // Constructor
39
IEclass(int __scol,int __ecol,int __srow,int __erow,int __border)40 IEclass::IEclass(int __scol, int __ecol, int __srow, int __erow, int __border) {
41
42 win_mincol = __scol;
43 win_minrow = __srow;
44 win_maxcol = __ecol;
45 win_maxrow = __erow;
46 win_border = __border;
47
48 win_hasborder = (win_border == 5) ? 0 : 1;
49
50 mincol = 0;
51 minrow = 0;
52 maxcol = win_maxcol - win_mincol - (2*win_hasborder);
53 maxrow = win_maxrow - win_minrow - (2*win_hasborder);
54
55 col = 0;
56 row = 0;
57 ccol = 0;
58 crow = 0;
59
60 chartyped = false;
61 currline = NULL;
62 done = NO;
63 insert = YES;
64 drawlines = 0;
65 drawflag = true;
66 marginquotes = 0;
67 margintext = 0;
68 msgmode = 0;
69 msgptr = NULL;
70 quitnow = NO;
71 thisrow = 0;
72 unfinished = "+$!$+ GoldED Internal Editor: Unfinished Message!";
73 blockcol = -1;
74 selecting = NO;
75
76 throw_new(Undo = new UndoStack(this));
77 windowopen();
78 }
79
80
81 // ------------------------------------------------------------------
82 // Destructor
83
~IEclass()84 IEclass::~IEclass() {
85
86 throw_delete(Undo);
87 windowclose();
88 }
89
90
91 // ------------------------------------------------------------------
92
windowopen()93 void IEclass::windowopen() {
94
95 // Open editor window without clearing the window area
96 #define STYLE_NOCLEAR -1
97 int _tmp = gwin.style;
98 gwin.style = STYLE_NOCLEAR;
99 editwin.open(win_minrow, win_mincol, win_maxrow, win_maxcol, 5, C_READB, C_READW, C_READPB);
100 gwin.style = _tmp;
101 whelppcat(H_Editor);
102 }
103
104
105 // ------------------------------------------------------------------
106
windowclose()107 void IEclass::windowclose() {
108
109 whelpop();
110 // Close editor window without removing the window itself
111 editwin.unlink();
112 }
113
114
115 // ------------------------------------------------------------------
116
Edit__killpastebuf()117 void Edit__killpastebuf() {
118
119 while(Edit__pastebuf) {
120 if(Edit__pastebuf->next) {
121 Edit__pastebuf = Edit__pastebuf->next;
122 throw_xdelete(Edit__pastebuf->prev);
123 }
124 else
125 throw_xdelete(Edit__pastebuf);
126 }
127 }
128
129
130 // ------------------------------------------------------------------
131
Edit__killkillbuf()132 void Edit__killkillbuf() {
133
134 while(Edit__killbuf) {
135 if(Edit__killbuf->prev) {
136 Edit__killbuf = Edit__killbuf->prev;
137 throw_xdelete(Edit__killbuf->next);
138 }
139 else
140 throw_xdelete(Edit__killbuf);
141 }
142 }
143
144
145 // ------------------------------------------------------------------
146
killkillbuf()147 void IEclass::killkillbuf() {
148
149 while(Edit__killbuf) {
150 if(Undo->FixPushLine(Edit__killbuf)) {
151 if(Edit__killbuf->prev) {
152 Edit__killbuf = Edit__killbuf->prev;
153 Edit__killbuf->next = NULL;
154 }
155 else {
156 Edit__killbuf = NULL;
157 }
158 }
159 else {
160 if(Edit__killbuf->prev) {
161 Edit__killbuf = Edit__killbuf->prev;
162 throw_xdelete(Edit__killbuf->next);
163 }
164 else
165 throw_xdelete(Edit__killbuf);
166 }
167 }
168 }
169
170
171 // ------------------------------------------------------------------
172
FreePastebuf()173 void FreePastebuf() {
174
175 Edit__killpastebuf();
176 Edit__killkillbuf();
177 }
178
179
180 // ------------------------------------------------------------------
181
ClearDeleteBuf()182 void IEclass::ClearDeleteBuf() {
183
184 GFTRK("EditClearDeleteBuf");
185
186 killkillbuf();
187 HandleGEvent(EVTT_JOBDONE);
188
189 GFTRK(0);
190 }
191
192
193 // ------------------------------------------------------------------
194
ClearPasteBuf()195 void IEclass::ClearPasteBuf() {
196
197 GFTRK("EditClearPasteBuf");
198
199 killpastebuf();
200 HandleGEvent(EVTT_JOBDONE);
201
202 GFTRK(0);
203 }
204
205
206 // ------------------------------------------------------------------
207
GoBegLine()208 void IEclass::GoBegLine() {
209
210 GFTRK("EditGoBegLine");
211
212 col = mincol;
213
214 if(blockcol != -1)
215 displine(currline, row);
216
217 GFTRK(0);
218 }
219
220
221 // ------------------------------------------------------------------
222
DelLtWord()223 void IEclass::DelLtWord() {
224
225 GFTRK("EditDelLtWord");
226
227 if(col == 0) {
228 DelLeft();
229 GFTRK(0);
230 return;
231 }
232
233 int _ptr, _ptr2;
234 _ptr = _ptr2 = col;
235 _ptr--;
236
237 // test test test test test test test test
238 // test test test test , test test test test
239 // test test test test ,, test test test test
240
241 if(currline->txt[_ptr] == ' ') {
242 while((currline->txt[_ptr] == ' ') and (_ptr > 0))
243 _ptr--;
244 if(currline->txt[_ptr] != ' ')
245 _ptr++;
246 }
247 else if(isxalnum(currline->txt[_ptr])) {
248 while(isxalnum(currline->txt[_ptr]) and (_ptr > 0))
249 _ptr--;
250 while((currline->txt[_ptr] == ' ') and (_ptr > 0))
251 _ptr--;
252 if((currline->txt[_ptr] != ' ') and (_ptr > 0))
253 _ptr++;
254 }
255 else {
256 DelLeft();
257 GFTRK(0);
258 return;
259 }
260
261 col -= _ptr2-_ptr;
262
263 Undo->PushItem(EDIT_UNDO_DEL_TEXT, currline, col, _ptr2-_ptr);
264 currline->txt.erase(_ptr, _ptr2-_ptr);
265
266 wrapdel(&currline, &col, &row);
267
268 GFTRK(0);
269 }
270
271
272 // ------------------------------------------------------------------
273
DelRtWord()274 void IEclass::DelRtWord() {
275
276 GFTRK("EditDelRtWord");
277
278 if((currline->txt.length() == col+1) or (currline->txt[col+1] == '\n')) {
279 DelChar();
280 GFTRK(0);
281 return;
282 }
283
284 int _ptr, _ptr2;
285 _ptr = _ptr2 = col;
286
287 // test test test test, test test test test
288 // test test test test, test test test test
289
290 if(currline->txt[_ptr] == ' ') {
291 while(_ptr != currline->txt.length() and currline->txt[_ptr] == ' ')
292 _ptr++;
293 }
294 else if(isxalnum(currline->txt[_ptr])) {
295 // Delete word
296 while(_ptr != currline->txt.length() and isxalnum(currline->txt[_ptr]))
297 _ptr++;
298 // Delete spaces after word
299 while(_ptr != currline->txt.length() and currline->txt[_ptr] == ' ')
300 _ptr++;
301 }
302 else {
303 DelChar();
304 GFTRK(0);
305 return;
306 }
307
308 Undo->PushItem(EDIT_UNDO_DEL_TEXT, currline, col, _ptr-_ptr2);
309 currline->txt.erase(_ptr2, _ptr-_ptr2);
310
311 wrapdel(&currline, &col, &row);
312
313 GFTRK(0);
314 }
315
316
317 // ------------------------------------------------------------------
318
GoTopMsg()319 void IEclass::GoTopMsg() {
320
321 GFTRK("EditGoTopMsg");
322
323 currline = findfirstline();
324 col = mincol;
325 row = minrow;
326 thisrow = 0;
327 refresh(currline, minrow);
328
329 GFTRK(0);
330 }
331
332
333 // ------------------------------------------------------------------
334
GoBotMsg()335 void IEclass::GoBotMsg() {
336
337 GFTRK("EditGoBotMsg");
338
339 col = mincol;
340 thisrow = 0;
341 currline = findfirstline();
342
343 // Go to the last line in the msg
344 while(currline->next) {
345 currline = currline->next;
346 thisrow++;
347 }
348
349 // Pointer to the line to display at the top of the window
350 Line* _topline = currline;
351
352 // The new cursor row
353 row = MinV(thisrow, maxrow);
354
355 // How many lines to go back to get the top line
356 int _count = row;
357
358 // Go back to get the top line
359 while(_count-- and _topline->prev)
360 _topline = _topline->prev;
361
362 // Refresh the display
363 refresh(_topline, minrow);
364
365 GFTRK(0);
366 }
367
368
369 // ------------------------------------------------------------------
370
GoTopLine()371 void IEclass::GoTopLine() {
372
373 GFTRK("EditGoTopLine");
374
375 int _count = row;
376
377 while(_count-- and currline->prev) {
378 currline = currline->prev;
379 thisrow--;
380 }
381
382 col = mincol;
383 row = minrow;
384
385 if(blockcol != -1)
386 refresh(currline, minrow);
387
388 GFTRK(0);
389 }
390
391
392 // ------------------------------------------------------------------
393
GoBotLine()394 void IEclass::GoBotLine() {
395
396 GFTRK("EditGoBotLine");
397
398 Line *_oldcurrline = currline;
399 int _oldrow = row;
400
401 while((row < maxrow) and currline->next) {
402 currline = currline->next;
403 thisrow++;
404 row++;
405 }
406
407 col = mincol;
408
409 if(blockcol != -1)
410 refresh(_oldcurrline, _oldrow);
411
412 GFTRK(0);
413 }
414
415
416 // ------------------------------------------------------------------
417
findanchor()418 Line* IEclass::findanchor() {
419
420 GFTRK("Editfindanchor");
421
422 // Rewind to the first line
423 Line* _anchor = findfirstline();
424
425 // Search all lines to find the anchor (a line with a block mark)
426 while(not (_anchor->type & GLINE_BLOK) and _anchor->next)
427 _anchor = _anchor->next;
428
429 GFTRK(0);
430
431 // Return pointer to the anchor line or NULL if no anchor was found
432 return (_anchor->type & GLINE_BLOK) ? _anchor : (Line*)NULL;
433 }
434
435
436 // ------------------------------------------------------------------
437
BlockAnchor()438 void IEclass::BlockAnchor() {
439
440 GFTRK("EditBlockAnchor");
441
442 Line* _anchor = findanchor();
443
444 // Is there an anchor already?
445 if(_anchor) {
446
447 // Yes, so replace it with the current line
448
449 // Remove block mark
450 _anchor->type &= ~GLINE_BLOK;
451 blockcol = -1;
452
453 // Is the old anchor different from the current line?
454 if(_anchor != currline) {
455
456 // Set the new anchor
457 _anchor = currline;
458 _anchor->type |= GLINE_BLOK;
459 blockcol = col;
460
461 // Find the line at the top
462 Line* _topline = findtopline();
463
464 // Refresh display to remove the block color on the old anchor line
465 // Just in case the old anchor line is visible
466 refresh(_topline, minrow);
467 }
468
469 // Remove the old contents of the paste buffer
470 killpastebuf();
471 }
472 else {
473
474 for(Line* _line = findfirstline(); _line; _line = _line->next)
475 _line->type &= ~GLINE_BLOK;
476
477 // There was no anchor, so mark the current line as the new anchor
478 currline->type |= GLINE_BLOK;
479 blockcol = col;
480
481 // Refresh the display
482 Line* _topline = findtopline();
483 refresh(_topline, minrow);
484 }
485
486 displine(currline, row);
487
488 GFTRK(0);
489 }
490
491
492 // ------------------------------------------------------------------
493
BlockCopy()494 void IEclass::BlockCopy() {
495
496 GFTRK("EditBlockCopy");
497
498 // Find the anchor, if any
499 Line* _anchor = findanchor();
500
501 // Did we find the anchor?
502 if(_anchor) {
503
504 Line* _firstcopyline = currline;
505 Line* _lastcopyline = currline;
506 int firstcol = col, lastcol = col;
507
508 // Search below to find the anchor line
509 while(_lastcopyline->next and (_lastcopyline != _anchor))
510 _lastcopyline = _lastcopyline->next;
511
512 // Was the anchor line above or on the current line?
513 if(_lastcopyline != _anchor) {
514
515 // The last copy line is the current line
516 _lastcopyline = currline;
517
518 // Search above to find the anchor line
519 while(_firstcopyline->prev and (_firstcopyline != _anchor))
520 _firstcopyline = _firstcopyline->prev;
521 firstcol = blockcol;
522 }
523 else {
524 if(currline != _anchor or blockcol > col)
525 lastcol = blockcol;
526 else
527 firstcol = blockcol;
528 }
529
530 // The _firstcopyline and _lastcopyline pointers
531 // are now pointing where they should
532
533 // Remove the old paste buffer
534 killpastebuf();
535
536 // Pointer to the previous line in the paste buffer
537 Line* _prevline = NULL;
538
539 // Copy lines to the paste buffer
540 while(1) {
541
542 // Allocate a new line
543 Line* _copyline;
544
545 // Copy text and type
546 if(_prevline == NULL)
547 _copyline = new Line(_firstcopyline->txt.c_str() + firstcol);
548 else
549 _copyline = new Line(_firstcopyline->txt.c_str());
550 throw_xnew(_copyline);
551 if(_firstcopyline == _lastcopyline) {
552 if(_prevline)
553 _copyline->txt.erase(lastcol);
554 else
555 _copyline->txt.erase(lastcol-firstcol);
556 }
557 _copyline->type = _firstcopyline->type & ~GLINE_BLOK;
558
559 // Link in the new line
560 _copyline->prev = _prevline;
561 if(_prevline)
562 _prevline->next = _copyline;
563 _copyline->next = NULL;
564
565 // Point the paste buffer to the first line of the copy
566 if(Edit__pastebuf == NULL)
567 Edit__pastebuf = _copyline;
568
569 // Break out of the loop if the last line was copied
570 if(_firstcopyline == _lastcopyline)
571 break;
572
573 // Keep pointer to the new line
574 _prevline = _copyline;
575
576 // Continue with the next line
577 _firstcopyline = _firstcopyline->next;
578 }
579
580 selecting = NO;
581 blockcol = -1;
582 for(Line* _line = findfirstline(); _line; _line = _line->next)
583 _line->type &= ~GLINE_BLOK;
584
585 // Refresh display to remove the block color
586 Line* _topline = findtopline();
587 refresh(_topline, minrow);
588
589 Buf2Clip();
590 }
591 killpastebuf();
592
593 GFTRK(0);
594 }
595
596
597 // ------------------------------------------------------------------
598
BlockDel(Line * anchor)599 void IEclass::BlockDel(Line* anchor) {
600
601 GFTRK("EditBlockDel");
602
603 Line* firstcutline = currline;
604 Line* lastcutline = currline;
605 uint firstcutlinerow = row;
606 uint lastcutlinerow = row;
607 int firstcol = col, lastcol = col;
608
609 // Search below to find the anchor line
610 while(lastcutline->next and (lastcutline != anchor)) {
611 lastcutline = lastcutline->next;
612 lastcutlinerow++;
613 }
614
615 // Was the anchor line above or on the current line?
616 if(lastcutline != anchor) {
617
618 // The last cut line is the current line
619 lastcutline = currline;
620 lastcutlinerow = row;
621
622 // Search above to find the anchor line
623 while(firstcutline->prev and (firstcutline != anchor)) {
624 firstcutline = firstcutline->prev;
625 if(firstcutlinerow)
626 firstcutlinerow--;
627 }
628 firstcol = blockcol;
629 }
630 else {
631 if((currline != anchor) or (blockcol > col))
632 lastcol = blockcol;
633 else
634 firstcol = blockcol;
635 }
636
637 // The firstcutline and lastcutline pointers
638 // are now pointing where they should
639
640 if(firstcutline != lastcutline) {
641 size_t __len = firstcutline->txt.length();
642 firstcutline->txt += lastcutline->txt.c_str()+lastcol;
643
644 // We need to set up prow to prevent cosmetic bugs
645 uint __prow = prow;
646 getthisrow(firstcutline);
647 prow = thisrow;
648 getthisrow(currline);
649 Undo->PushItem(EDIT_UNDO_INS_TEXT, firstcutline, __len);
650 prow = __prow;
651
652 Undo->PushItem(EDIT_UNDO_DEL_TEXT|BATCH_MODE, firstcutline, firstcol, __len-firstcol);
653 firstcutline->txt.erase(firstcol, __len-firstcol);
654 }
655 else {
656 Undo->PushItem(EDIT_UNDO_DEL_TEXT, firstcutline, firstcol, lastcol-firstcol);
657 firstcutline->txt.erase(firstcol, lastcol-firstcol);
658 }
659 setlinetype(firstcutline);
660 firstcutline->type &= ~GLINE_BLOK;
661 blockcol = -1;
662 currline = firstcutline;
663 row = firstcutlinerow;
664 col = firstcol;
665 if(firstcutline != lastcutline) {
666 do {
667 Undo->PushItem(EDIT_UNDO_DEL_LINE|BATCH_MODE, firstcutline = firstcutline->next);
668 } while(firstcutline != lastcutline);
669
670 currline->next = lastcutline->next;
671 if(lastcutline->next)
672 lastcutline->next->prev = currline;
673 }
674
675 // Refresh the display
676 if(not RngV(row, minrow, maxrow)) {
677 row = minrow;
678 wrapdel(&currline, &col, &row, false);
679 refresh(currline, minrow);
680 }
681 else {
682 row = MaxV(firstcutlinerow, minrow);
683 Line* topline = findtopline();
684 wrapdel(&currline, &col, &row, false);
685 refresh(topline, minrow);
686 }
687
688 Line* line;
689 for(line = findfirstline(); line; line = line->next)
690 line->type &= ~GLINE_BLOK;
691
692 selecting = NO;
693
694 GFTRK(0);
695 }
696
697
698 // ------------------------------------------------------------------
699
BlockCut(bool just_delete)700 void IEclass::BlockCut(bool just_delete) {
701
702 GFTRK("EditBlockCut");
703
704 // Find the anchor, if any
705 Line* _anchor = findanchor();
706
707 // Did we find the anchor?
708 if(_anchor) {
709
710 int _blockcol = blockcol;
711
712 if(not just_delete)
713 BlockCopy();
714
715 blockcol = _blockcol;
716
717 BlockDel(_anchor);
718 }
719 else
720 killpastebuf();
721
722 GFTRK(0);
723 }
724
725
726 // ------------------------------------------------------------------
727
BlockPaste()728 void IEclass::BlockPaste() {
729
730 GFTRK("EditBlockPaste");
731
732 killpastebuf();
733 Clip2Buf();
734
735 if(Edit__pastebuf) {
736
737 Line* _pasteline = Edit__pastebuf;
738
739 if(not batch_mode)
740 Undo->PushItem(EDIT_UNDO_VOID);
741
742 // For each of the lines in the paste buffer
743 while(_pasteline) {
744
745 uint curlen = currline->txt.length();
746 uint pastelen = _pasteline->txt.length();
747
748 if(col > curlen)
749 col = curlen;
750
751 if(_pasteline->txt.find('\n') != _pasteline->txt.npos) {
752 // append to current line
753 Undo->PushItem(EDIT_UNDO_DEL_TEXT|BATCH_MODE, currline, col);
754 Line* _newline = insertlinebelow(currline, currline->txt.c_str()+col, BATCH_MODE);
755 currline->txt.erase(col);
756 currline->txt += _pasteline->txt;
757 Undo->PushItem(EDIT_UNDO_INS_TEXT|BATCH_MODE, currline, col, pastelen);
758 setlinetype(currline);
759 col = currline->txt.length();
760 wrapins(&currline, &col, &row, false);
761 currline = _newline;
762 col = 0;
763 if(row < maxrow)
764 row++;
765 }
766 else {
767 // insert into current line
768 currline->txt.insert(col, _pasteline->txt);
769 Undo->PushItem(EDIT_UNDO_INS_TEXT|BATCH_MODE, currline, col, pastelen);
770 col += pastelen;
771 wrapins(&currline, &col, &row, false);
772 }
773
774 setlinetype(currline);
775
776 // Continue with the next line in the paste buffer
777 _pasteline = _pasteline->next;
778 }
779
780 selecting = NO;
781 blockcol = -1;
782 for(Line* _line = findfirstline(); _line; _line = _line->next)
783 _line->type &= ~GLINE_BLOK;
784
785 // Refresh the display
786 Line* _topline = findtopline();
787 refresh(_topline, minrow);
788 }
789
790 GFTRK(0);
791 }
792
793
794 // ------------------------------------------------------------------
795
LoadFile()796 void IEclass::LoadFile() {
797
798 GFTRK("EditLoadFile");
799
800 // Open the file to load
801 gfile _fp(AddPath(CFG->goldpath, EDIT->File()), "rb", CFG->sharemode);
802 if (_fp.isopen())
803 {
804 XlatName __oldxlatimport;
805
806 // Pop up a wait window
807 cursoroff();
808 w_info(LNG->Wait);
809
810 throw_delete(Undo);
811
812 // Find the first line
813 Line* _line = findfirstline();
814
815 // Remove all lines
816 while(_line) {
817 Line* _nextline = _line->next;
818 throw_xdelete(_line);
819 _line = _nextline;
820 }
821
822 // Remove message text and reset pointers
823 throw_release(msgptr->txt);
824 currline = msgptr->lin = NULL;
825
826 // Allocate space for new message text
827 msgptr->txt = (char*)throw_calloc(1, (uint)(_fp.FileLength()+256));
828
829 // Eat the backup marking line
830 char _buf[EDIT_BUFLEN];
831 _fp.Fgets(_buf, sizeof(_buf));
832 if (not striinc(unfinished, _buf))
833 _fp.Rewind();
834
835 // Load the file and close it
836 _fp.Fread(msgptr->txt, (uint)_fp.FileLength());
837 _fp.Fclose();
838
839 // Save current charset
840 strcpy(__oldxlatimport, AA->Xlatimport());
841 AA->SetXlatimport(CFG->xlatlocalset);
842
843 // Index message text
844 msgptr->TextToLines(margintext-1, false);
845 _line = currline = msgptr->lin;
846
847 // Restore charset
848 AA->SetXlatimport(__oldxlatimport);
849
850 // Change lines to internal editor format
851 while(_line) {
852 strtrim(_line->txt);
853 if(_line->type & GLINE_HARD)
854 _line->txt += "\n";
855 else
856 _line->txt += " ";
857 _line = _line->next;
858 }
859
860 // Remove the wait window
861 w_info(NULL);
862
863 // Display the loaded message
864 Line* l = findfirstline();
865 uint i;
866
867 for(i=0; l->next and i<thisrow-row; i++)
868 l = l->next;
869
870 refresh(l, minrow);
871
872 for(i=0; l->next and i<row; i++)
873 l = l->next;
874
875 if(l->next == NULL)
876 row = i;
877 currline = l;
878 col = mincol;
879
880 throw_new(Undo = new UndoStack(this));
881 }
882
883 GFTRK(0);
884 }
885
886
887 // ------------------------------------------------------------------
888
uuencode_enc(int c)889 inline char uuencode_enc(int c) { return (char)(c ? (c & 077) + ' ': '`'); }
890
editimport(Line * __line,char * __filename,bool imptxt)891 void IEclass::editimport(Line* __line, char* __filename, bool imptxt) {
892
893 XlatName __oldxlatimport;
894
895 GFTRK("Editimport");
896
897 // Save the unfinished msg first of all
898 savefile(MODE_UPDATE);
899
900 update_statusline(LNG->ImportFile);
901
902 // Set initial import filename or wildcards
903 if(__filename) {
904 AA->SetInputfile(__filename);
905 }
906 else {
907 if(*AA->Inputfile() == NUL)
908 AA->SetInputfile("*");
909 }
910
911 strcpy(__oldxlatimport, AA->Xlatimport());
912 AA->SetXlatimport(CFG->xlatlocalset);
913
914 strcpy(CFG->inputfile, AA->Inputfile());
915
916 int ImportMode;
917
918 if(imptxt)
919 ImportMode = 0;
920 else {
921
922 GMenuImportTxt MenuImportTxt;
923
924 ImportMode = MenuImportTxt.Run();
925 }
926
927 std::string filenamebuf;
928 Path tmpfile;
929 bool isPipe = NO;
930 bool fileselected = false;
931
932 // Should the imported text be quoted or uuencoded?
933 #define quoteit (ImportMode == 1)
934 #define uuencode (ImportMode == 2)
935 #define base64 (ImportMode == 3)
936 #define getclip (ImportMode == 4)
937 #define binary (uuencode or base64)
938
939 if(in_range(ImportMode, 0, 3) and edit_pathname(CFG->inputfile, sizeof(Path), LNG->ImportWhichFile, H_ImportFile)) {
940
941 AA->SetInputfile(CFG->inputfile);
942
943 // Pointer to the filename string
944 filenamebuf = AA->Inputfile();
945
946 if(filenamebuf.c_str()[0] == '|'){
947 Path cmdline;
948
949 if( not ((*CFG->temppath == NUL ) or is_dir(CFG->temppath)) )
950 {
951 w_info(LNG->TMPinvalidpath);
952 SayBibi();
953 waitkeyt(10000);
954 w_info("");
955 AA->SetXlatimport(__oldxlatimport);
956 GFTRK(0);
957 return;
958 }
959
960 isPipe = YES;
961 mktemp(strxcpy(tmpfile, AddPath(CFG->temppath, "GIXXXXXX"), sizeof(Path)));
962 strxmerge(cmdline, sizeof(Path), filenamebuf.c_str()+1, " > ", tmpfile, NULL);
963 ShellToDos(cmdline, "", BLACK_|_BLACK, NO);
964 filenamebuf = tmpfile;
965 fileselected = true;
966 } else {
967 // Check for wildcards
968 // Is the filename a directory?
969 if(is_dir(filenamebuf)) {
970
971 // Does the filename contain wildcards?
972 if(not strpbrk(filenamebuf.c_str(), "*?")) {
973
974 // Add match-all wildcards
975 AddBackslash(filenamebuf);
976 filenamebuf += "*";
977 }
978 }
979
980 fileselected = true;
981
982 // Does the filename contain wildcards?
983 if(strpbrk(filenamebuf.c_str(), "*?")) {
984
985 // Set selection window title and statusline
986 set_title(LNG->ImportTitle, TCENTER, C_MENUT);
987 update_statuslinef(LNG->ImportStatus, "ST_IMPORTSTATUS", filenamebuf.c_str());
988
989 // Start the file picker
990 fileselected = wpickfile(win_minrow, win_mincol, win_maxrow, win_maxcol, W_BMENU, C_MENUB, C_MENUW, C_MENUS, NO, filenamebuf, maketitle_and_status);
991 }
992 }
993 }
994
995 if (fileselected or getclip)
996 {
997 // Open the file/clipboard
998 gfile fp;
999 gclipbrd clipbrd;
1000
1001 if(getclip)
1002 filenamebuf = CLIP_NAME;
1003
1004 if(getclip ? clipbrd.openread() :
1005 (fp.Fopen(filenamebuf.c_str(), binary ? "rb" : "rt", CFG->sharemode))!=NULL)
1006 {
1007 if (isPipe)
1008 filenamebuf = AA->Inputfile();
1009
1010 const char *imp_filename = (getclip or isPipe) ? filenamebuf.c_str() : CleanFilename(filenamebuf.c_str());
1011
1012 // we need to truncate filename to prevent unpredictable results
1013 int delta = strlen(imp_filename) - margintext;
1014 if(delta > 0) {
1015 filenamebuf.erase(filenamebuf.length()-delta);
1016 imp_filename = (getclip or isPipe) ? filenamebuf.c_str() : CleanFilename(filenamebuf.c_str());
1017 }
1018
1019 update_statuslinef(LNG->ImportStatus, "ST_IMPORTSTATUS", filenamebuf.c_str());
1020
1021 // Allocate paragraph read buffer
1022 char* _parabuf = (char*)throw_malloc(EDIT_PARABUFLEN);
1023
1024 if(__line->prev)
1025 Undo->PushItem(EDIT_UNDO_VOID|PREV_LINE|batch_mode, __line->prev);
1026 else
1027 Undo->PushItem(EDIT_UNDO_VOID|batch_mode, __line);
1028 batch_mode = BATCH_MODE;
1029
1030 // Add import begin text, if any
1031 if (*CFG->importbegin)
1032 {
1033 sprintf(_parabuf, "%s\n", CFG->importbegin);
1034 strischg(_parabuf, "@file", imp_filename);
1035 TokenXlat(MODE_NEW, _parabuf, EDIT_PARABUFLEN, true, msgptr, msgptr, CurrArea);
1036 _parabuf[strlen(_parabuf)-1] = '\n';
1037 _parabuf[margintext] = NUL;
1038 _parabuf[margintext-1] = '\n';
1039 __line = insertlinebelow(__line, _parabuf);
1040 setlinetype(__line);
1041 }
1042
1043 if(uuencode) {
1044
1045 sprintf(_parabuf, "begin 644 %s\n", imp_filename);
1046 _parabuf[margintext] = NUL;
1047 _parabuf[margintext-1] = '\n';
1048 __line = insertlinebelow(__line, _parabuf);
1049 setlinetype(__line);
1050
1051 while (true)
1052 {
1053 char ibuf[80];
1054 char* iptr = ibuf;
1055 char* optr = _parabuf;
1056 int n = fp.Fread(ibuf, 1, 45);
1057 if (n < 45) memset(ibuf+n, 0, 45-n);
1058 *optr++ = uuencode_enc(n);
1059
1060 for(int i=0; i<n; i+=3,iptr+=3) {
1061 *optr++ = uuencode_enc(*iptr >> 2);
1062 *optr++ = uuencode_enc(((*iptr << 4) & 060) | ((iptr[1] >> 4) & 017));
1063 *optr++ = uuencode_enc(((iptr[1] << 2) & 074) | ((iptr[2] >> 6) & 03));
1064 *optr++ = uuencode_enc(iptr[2] & 077);
1065 }
1066 *optr++ = '\n';
1067 *optr = NUL;
1068 __line = insertlinebelow(__line, _parabuf);
1069 // set type to text
1070 __line->type &= ~GLINE_ALL;
1071 if(n <= 0)
1072 break;
1073 }
1074
1075 __line = insertlinebelow(__line, "end\n");
1076 setlinetype(__line);
1077 }
1078 else if(base64) {
1079
1080 base64_engine b64;
1081
1082 sprintf(_parabuf, "Content-type: application/octet-stream; name=\"%s\"\n", imp_filename);
1083 strcpy(_parabuf+margintext-2, "\"\n");
1084 __line = insertlinebelow(__line, _parabuf);
1085 setlinetype(__line);
1086 sprintf(_parabuf, "Content-transfer-encoding: base64\n");
1087 __line = insertlinebelow(__line, _parabuf);
1088 setlinetype(__line);
1089
1090 sprintf(_parabuf, "\n");
1091 __line = insertlinebelow(__line, _parabuf);
1092 setlinetype(__line);
1093
1094 while (true)
1095 {
1096 char ibuf[80];
1097 char* optr = _parabuf;
1098 int n = fp.Fread(ibuf, 1, 54);
1099 optr = b64.encode(optr, ibuf, n);
1100 *optr++ = '\n';
1101 *optr = NUL;
1102 __line = insertlinebelow(__line, _parabuf);
1103 setlinetype(__line);
1104 if(n <= 0)
1105 break;
1106 }
1107 }
1108 else {
1109
1110 int tabsz = CFG->disptabsize ? CFG->disptabsize : 1;
1111 #if defined(__USE_ALLOCA__)
1112 char *spaces = (char*)alloca(tabsz+1);
1113 #else
1114 __extension__ char spaces[tabsz+1];
1115 #endif
1116 memset(spaces, ' ', tabsz);
1117 spaces[tabsz] = NUL;
1118 int level = LoadCharset(AA->Xlatimport(), CFG->xlatlocalset);
1119 size_t buf_len = EDIT_PARABUFLEN;
1120 char* buf = (char*) throw_malloc(EDIT_PARABUFLEN);
1121 Line* saveline = __line->next;
1122 __line->next = NULL;
1123
1124 // Read paragraphs
1125 while (getclip ? clipbrd.read(_parabuf, EDIT_PARABUFLEN-7) : fp.Fgets(_parabuf, EDIT_PARABUFLEN-7))
1126 {
1127 XlatStr(buf, _parabuf, level, CharTable);
1128
1129 // Insert a quotestring if asked
1130 if(quoteit)
1131 strins(" > ", buf, 0);
1132 else {
1133 // Invalidate tearline
1134 if(not CFG->invalidate.tearline.first.empty())
1135 doinvalidate(buf, CFG->invalidate.tearline.first.c_str(), CFG->invalidate.tearline.second.c_str(), true);
1136
1137 // Invalidate originline
1138 if(not CFG->invalidate.origin.first.empty())
1139 doinvalidate(buf, CFG->invalidate.origin.first.c_str(), CFG->invalidate.origin.second.c_str());
1140
1141 // Invalidate SEEN-BY's
1142 if(not CFG->invalidate.seenby.first.empty())
1143 doinvalidate(buf, CFG->invalidate.seenby.first.c_str(), CFG->invalidate.seenby.second.c_str());
1144
1145 // Invalidate CC's
1146 if(not CFG->invalidate.cc.first.empty())
1147 doinvalidate(buf, CFG->invalidate.cc.first.c_str(), CFG->invalidate.cc.second.c_str());
1148
1149 // Invalidate XC's
1150 if(not CFG->invalidate.xc.first.empty())
1151 doinvalidate(buf, CFG->invalidate.xc.first.c_str(), CFG->invalidate.xc.second.c_str());
1152
1153 // Invalidate XP's
1154 if(not CFG->invalidate.xp.first.empty())
1155 doinvalidate(buf, CFG->invalidate.xp.first.c_str(), CFG->invalidate.xp.second.c_str());
1156 }
1157
1158 size_t read_len = strlen(buf);
1159
1160 // Replace tabs
1161 char *ht = buf;
1162 while((ht = strchr(ht, '\t')) != NULL) {
1163 int rposn = ht-buf;
1164 int rstart = rposn%tabsz+1;
1165 *ht = ' ';
1166 if(tabsz > rstart) {
1167 if((read_len + tabsz - rstart) >= (buf_len - 7)) {
1168 buf_len += tabsz;
1169 buf = (char*)throw_realloc(buf, buf_len);
1170 }
1171 strins(spaces+rstart, buf, rposn);
1172 }
1173 }
1174
1175 // Copy the paragraph to the new line and retype it
1176 Line* _newline = __line = insertlinebelow(__line, buf);
1177 setlinetype(_newline);
1178
1179 // If the paragraph is longer than one line
1180 uint _wrapmargin = (_newline->type & GLINE_QUOT) ? marginquotes : margintext;
1181 if(_newline->txt.length() >= _wrapmargin) {
1182
1183 // Wrap it
1184 uint _tmpcol = 0;
1185 uint _tmprow = 0;
1186 _newline = wrapins(&_newline, &_tmpcol, &_tmprow, false);
1187 }
1188
1189 __line = _newline;
1190 }
1191
1192 while(__line->next)
1193 __line = __line->next;
1194 if(not __line->txt.empty() and (*(__line->txt.end()-1) != '\n')) {
1195 Undo->PushItem(EDIT_UNDO_INS_CHAR|BATCH_MODE, __line, __line->txt.length());
1196 __line->txt += '\n';
1197 // Wrap it
1198 uint _tmpcol = 0;
1199 uint _tmprow = 0;
1200 __line = wrapins(&__line, &_tmpcol, &_tmprow, false);
1201 }
1202 __line->next = saveline;
1203 if(saveline)
1204 saveline->prev = __line;
1205
1206 throw_free(buf);
1207 }
1208
1209 // Add import end text, if any
1210 if (*CFG->importend or *CFG->importbegin)
1211 {
1212 sprintf(_parabuf, "%s\n", *CFG->importend ? CFG->importend : CFG->importbegin);
1213 strischg(_parabuf, "@file", imp_filename);
1214 TokenXlat(MODE_NEW, _parabuf, EDIT_PARABUFLEN, true, msgptr, msgptr, CurrArea);
1215 _parabuf[strlen(_parabuf)-1] = '\n';
1216 _parabuf[margintext] = NUL;
1217 _parabuf[margintext-1] = '\n';
1218 __line = insertlinebelow(__line, _parabuf);
1219 setlinetype(__line);
1220 }
1221
1222 throw_free(_parabuf);
1223
1224 if (getclip)
1225 clipbrd.close();
1226 else
1227 fp.Fclose();
1228 }
1229 else {
1230 w_infof(LNG->CouldNotOpen, filenamebuf.c_str());
1231 waitkeyt(10000);
1232 w_info(NULL);
1233 }
1234
1235 if(isPipe)
1236 unlink(tmpfile);
1237 }
1238
1239 AA->SetXlatimport(__oldxlatimport);
1240
1241 GFTRK(0);
1242 }
1243
1244
1245 // ------------------------------------------------------------------
1246
imptxt(char * __filename,bool imptxt)1247 void IEclass::imptxt(char* __filename, bool imptxt) {
1248
1249 GFTRK("Editimptxt");
1250
1251 msgptr->lin = findfirstline();
1252 editimport(currline, __filename, imptxt);
1253 refresh(currline, row);
1254 col = mincol;
1255
1256 GFTRK(0);
1257 }
1258
1259
1260 // ------------------------------------------------------------------
1261
ImportText()1262 void IEclass::ImportText() {
1263
1264 GFTRK("EditImportText");
1265
1266 imptxt(NULL);
1267
1268 GFTRK(0);
1269 }
1270
1271
1272 // ------------------------------------------------------------------
1273
ImportQuotebuf()1274 void IEclass::ImportQuotebuf() {
1275
1276 GFTRK("EditImportQuotebuf");
1277
1278 Path _quotebuf;
1279
1280 GetCurrQuotebuf(_quotebuf);
1281 imptxt(_quotebuf, true);
1282
1283 GFTRK(0);
1284 }
1285
1286
1287 // ------------------------------------------------------------------
1288
editexport(Line * __exportline,int __endat)1289 void IEclass::editexport(Line* __exportline, int __endat) {
1290
1291 GFTRK("Editexport");
1292
1293 update_statusline(LNG->ExportFile);
1294
1295 if (edit_string(Edit__exportfilename, sizeof(Path), LNG->ExportWhatFile, H_ExportFile))
1296 {
1297 // Pointer to export filename
1298 char* _filenameptr = Edit__exportfilename;
1299
1300 // Is append requested?
1301 if(*_filenameptr == '+')
1302 _filenameptr++;
1303
1304 gfile _fp(_filenameptr, (*Edit__exportfilename == '+') ? "at" : "wt", CFG->sharemode);
1305 if (_fp.isopen())
1306 {
1307 update_statuslinef(LNG->ExportStatus, "ST_EXPORTSTATUS", Edit__exportfilename);
1308 _fp.Fputc('\n');
1309
1310 while ((__endat ? __exportline != currline : 1) and __exportline)
1311 {
1312 _fp.Fwrite(__exportline->txt.c_str(), __exportline->txt.length());
1313 if (__exportline->txt.find('\n') == __exportline->txt.npos)
1314 _fp.Fputc('\n');
1315 __exportline = __exportline->next;
1316 }
1317 }
1318 }
1319
1320 GFTRK(0);
1321 }
1322
1323
1324 // ------------------------------------------------------------------
1325
SpellCheck()1326 void IEclass::SpellCheck()
1327 {
1328 GFTRK("EditSpellCheck");
1329
1330 char _buf[EDIT_BUFLEN];
1331 char _buf2[EDIT_BUFLEN];
1332
1333 savefile(MODE_SAVE);
1334 strcpy(_buf, EDIT->SpellChecker());
1335 strcpy(_buf2, AddPath(CFG->goldpath, EDIT->File()));
1336 strchg(_buf2, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR);
1337 strischg(_buf, "@file", _buf2);
1338 gsprintf(PRINTF_DECLARE_BUFFER(_buf2), LNG->SpellChecker, _buf);
1339 ShellToDos(_buf, _buf2, LGREY_|_BLACK, YES);
1340 LoadFile();
1341
1342 GFTRK(0);
1343 }
1344
1345
1346 // ------------------------------------------------------------------
1347
ExportText()1348 void IEclass::ExportText() {
1349
1350 GFTRK("EditExportText");
1351
1352 int endat = NO;
1353 // Line* exportline = findanchor();
1354
1355 // if(exportline)
1356 // endat = YES;
1357 // else
1358 Line* exportline = findfirstline();
1359
1360 editexport(exportline, endat);
1361
1362 GFTRK(0);
1363 }
1364
1365
1366 // ------------------------------------------------------------------
1367
DosShell()1368 void IEclass::DosShell() {
1369
1370 GFTRK("EditDosShell");
1371
1372 char * shell = getenv(GOLD_SHELL_ENV);
1373 if( shell && *shell )
1374 ShellToDos(shell, LNG->DOS_Shell, LGREY_|_BLACK, YES);
1375 cursoron();
1376 cursoroff();
1377
1378 GFTRK(0);
1379 }
1380
1381
1382 // ------------------------------------------------------------------
1383
dispins()1384 void IEclass::dispins() {
1385
1386 GFTRK("Editdispins");
1387
1388 if(insert)
1389 HeaderView->window.prints(5, MAXCOL-6, C_HEADT, LNG->Ins);
1390 else {
1391 vchar _lbuf[6];
1392 for(int c = 0; c < 5; c++)
1393 _lbuf[c] = _box_table(W_BHEAD,1);
1394 _lbuf[5] = NUL;
1395 HeaderView->window.printvs(5, MAXCOL-6, C_HEADB|ACSET, _lbuf);
1396 }
1397
1398 GFTRK(0);
1399 }
1400
1401
1402 // ------------------------------------------------------------------
1403
dispdl()1404 void IEclass::dispdl()
1405 {
1406 GFTRK("Editdispdl");
1407
1408 if (drawlines)
1409 {
1410 const char *lng = (drawlines == 1) ? LNG->DrawSL : LNG->DrawDL;
1411 HeaderView->window.prints(5, MAXCOL-12, C_HEADT, lng);
1412 }
1413 else {
1414 vchar _lbuf[6];
1415 for(int c = 0; c < 5; c++)
1416 _lbuf[c] = _box_table(W_BHEAD,1);
1417 _lbuf[5] = NUL;
1418 HeaderView->window.printvs(5, MAXCOL-12, C_HEADB|ACSET, _lbuf);
1419 }
1420
1421 GFTRK(0);
1422 }
1423
1424
1425 // ------------------------------------------------------------------
1426
ToggleInsert()1427 void IEclass::ToggleInsert() {
1428
1429 GFTRK("EditToggleInsert");
1430
1431 insert = not insert;
1432 dispins();
1433
1434 GFTRK(0);
1435 }
1436
1437
1438 // ------------------------------------------------------------------
1439
ToggleDrawLines()1440 void IEclass::ToggleDrawLines()
1441 {
1442 GFTRK("EditToggleDrawLines");
1443
1444 switch (drawlines)
1445 {
1446 case 0: drawlines = 1; break;
1447 case 1: drawlines = 2; break;
1448 case 2: drawlines = 0; break;
1449 }
1450
1451 dispdl();
1452
1453 GFTRK(0);
1454 }
1455
1456
1457 // ------------------------------------------------------------------
1458
ChrToLines(char chr,byte lines[4])1459 static void ChrToLines(char chr, byte lines[4])
1460 {
1461 lines[0] = lines[1] = lines[2] = lines[3] = 0;
1462
1463 if (chr == _box_table(0, 1)) //hs
1464 lines[0] = lines[1] = 1;
1465 else if (chr == _box_table(1, 1)) //hd
1466 lines[0] = lines[1] = 2;
1467 else if (chr == _box_table(0, 3)) //vs
1468 lines[2] = lines[3] = 1;
1469 else if (chr == _box_table(1, 3)) //vd
1470 lines[2] = lines[3] = 2;
1471
1472 else if (chr == _box_table(0, 0)) //lsus
1473 lines[1] = lines[3] = 1;
1474 else if (chr == _box_table(1, 0)) //ldud
1475 lines[1] = lines[3] = 2;
1476 else if (chr == _box_table(0, 11)) //vsus
1477 lines[0] = lines[1] = lines[3] = 1;
1478 else if (chr == _box_table(1, 11)) //vdud
1479 lines[0] = lines[1] = lines[3] = 2;
1480 else if (chr == _box_table(0, 2)) //rsus
1481 lines[0] = lines[3] = 1;
1482 else if (chr == _box_table(1, 2)) //rdud
1483 lines[0] = lines[3] = 2;
1484
1485 else if (chr == _box_table(0, 9)) //lshs
1486 lines[1] = lines[2] = lines[3] = 1;
1487 else if (chr == _box_table(1, 9)) //ldhd
1488 lines[1] = lines[2] = lines[3] = 2;
1489 else if (chr == _box_table(0, 8)) //vshs
1490 lines[0] = lines[1] = lines[2] = lines[3] = 1;
1491 else if (chr == _box_table(1, 8)) //vdhd
1492 lines[0] = lines[1] = lines[2] = lines[3] = 2;
1493 else if (chr == _box_table(0, 10)) //rshs
1494 lines[0] = lines[2] = lines[3] = 1;
1495 else if (chr == _box_table(1, 10)) //rdhd
1496 lines[0] = lines[2] = lines[3] = 2;
1497
1498 else if (chr == _box_table(0, 5)) //lsds
1499 lines[1] = lines[2] = 1;
1500 else if (chr == _box_table(1, 5)) //lddd
1501 lines[1] = lines[2] = 2;
1502 else if (chr == _box_table(0, 12)) //vsds
1503 lines[0] = lines[1] = lines[2] = 1;
1504 else if (chr == _box_table(1, 12)) //vddd
1505 lines[0] = lines[1] = lines[2] = 2;
1506 else if (chr == _box_table(0, 7)) //rsds
1507 lines[0] = lines[2] = 1;
1508 else if (chr == _box_table(1, 7)) //rddd
1509 lines[0] = lines[2] = 2;
1510
1511 else if (chr == _box_table(2, 0)) //ldus
1512 { lines[1] = 1; lines[3] = 2; }
1513 else if (chr == _box_table(3, 0)) //lsud
1514 { lines[1] = 2; lines[3] = 1; }
1515 else if (chr == _box_table(2, 11)) //vdus
1516 { lines[0] = lines[1] = 1; lines[3] = 2; }
1517 else if (chr == _box_table(3, 11)) //vsud
1518 { lines[0] = lines[1] = 2; lines[3] = 1; }
1519 else if (chr == _box_table(2, 2)) //rdus
1520 { lines[0] = 1; lines[3] = 2; }
1521 else if (chr == _box_table(3, 2)) //rsud
1522 { lines[0] = 2; lines[3] = 1; }
1523
1524 else if (chr == _box_table(2, 9)) //ldhs
1525 { lines[1] = 1; lines[2] = lines[3] = 2; }
1526 else if (chr == _box_table(3, 9)) //lshd
1527 { lines[1] = 2; lines[2] = lines[3] = 1; }
1528 else if (chr == _box_table(2, 8)) //vdhs
1529 { lines[0] = lines[1] = 1; lines[2] = lines[3] = 2; }
1530 else if (chr == _box_table(3, 8)) //vshd
1531 { lines[0] = lines[1] = 2; lines[2] = lines[3] = 1; }
1532 else if (chr == _box_table(2, 10)) //rdhs
1533 { lines[0] = 1; lines[2] = lines[3] = 2; }
1534 else if (chr == _box_table(3, 10)) //rshd
1535 { lines[0] = 2; lines[2] = lines[3] = 1; }
1536
1537 else if (chr == _box_table(2, 5)) //ldds
1538 { lines[1] = 1; lines[2] = 2; }
1539 else if (chr == _box_table(3, 5)) //lsdd
1540 { lines[1] = 2; lines[2] = 1; }
1541 else if (chr == _box_table(2, 12)) //vdds
1542 { lines[0] = lines[1] = 1; lines[2] = 2; }
1543 else if (chr == _box_table(3, 12)) //vsdd
1544 { lines[0] = lines[1] = 2; lines[2] = 1; }
1545 else if (chr == _box_table(2, 7)) //rdds
1546 { lines[0] = 1; lines[2] = 2; }
1547 else if (chr == _box_table(3, 7)) //rsdd
1548 { lines[0] = 2; lines[2] = 1; }
1549 }
1550
1551
1552 // ------------------------------------------------------------------
1553
LinesToChr(byte lines[4])1554 static char LinesToChr(byte lines[4])
1555 {
1556 if (lines[0] == 0)
1557 { if (lines[1] == 0)
1558 { if (lines[2] == 0)
1559 { if (lines[3] == 1) return _box_table(0, 3); //vs
1560 if (lines[3] == 2) return _box_table(1, 3); //vd
1561 } else if (lines[2] == 1)
1562 { if (lines[3] == 0) return _box_table(0, 3); //vs
1563 if (lines[3] == 1) return _box_table(0, 3); //vs
1564 } else if (lines[2] == 2)
1565 { if (lines[3] == 0) return _box_table(1, 3); //vd
1566 if (lines[3] == 2) return _box_table(1, 3); //vd
1567 }
1568 } else if (lines[1] == 1)
1569 { if (lines[2] == 0)
1570 { if (lines[3] == 0) return _box_table(0, 1); //hs
1571 if (lines[3] == 1) return _box_table(0, 0); //lsus
1572 if (lines[3] == 2) return _box_table(2, 0); //ldus
1573 } else if (lines[2] == 1)
1574 { if (lines[3] == 0) return _box_table(0, 5); //lsds
1575 if (lines[3] == 1) return _box_table(0, 9); //lshs
1576 } else if (lines[2] == 2)
1577 { if (lines[3] == 0) return _box_table(2, 5); //ldds
1578 if (lines[3] == 2) return _box_table(2, 9); //ldhs
1579 }
1580 } else if (lines[1] == 2)
1581 { if (lines[2] == 0)
1582 { if (lines[3] == 0) return _box_table(1, 1); //hd
1583 if (lines[3] == 1) return _box_table(3, 0); //lsud
1584 if (lines[3] == 2) return _box_table(1, 0); //ldud
1585 } else if (lines[2] == 1)
1586 { if (lines[3] == 0) return _box_table(3, 5); //lsdd
1587 if (lines[3] == 1) return _box_table(3, 9); //lshd
1588 } else if (lines[2] == 2)
1589 { if (lines[3] == 0) return _box_table(1, 5); //lddd
1590 if (lines[3] == 2) return _box_table(1, 9); //ldhd
1591 }
1592 }
1593 } else if (lines[0] == 1)
1594 { if (lines[1] == 0)
1595 { if (lines[2] == 0)
1596 { if (lines[3] == 0) return _box_table(0, 1); //hs
1597 if (lines[3] == 1) return _box_table(0, 2); //rsus
1598 if (lines[3] == 2) return _box_table(2, 2); //rdus
1599 } else if (lines[2] == 1)
1600 { if (lines[3] == 0) return _box_table(0, 7); //rsds
1601 if (lines[3] == 1) return _box_table(0, 10); //rshs
1602 } else if (lines[2] == 2)
1603 { if (lines[3] == 0) return _box_table(2, 7); //rdds
1604 if (lines[3] == 2) return _box_table(2, 10); //rdhs
1605 }
1606 } else if (lines[1] == 1)
1607 { if (lines[2] == 0)
1608 { if (lines[3] == 0) return _box_table(0, 1); //hs
1609 if (lines[3] == 1) return _box_table(0, 11); //vsus
1610 if (lines[3] == 2) return _box_table(2, 11); //vdus
1611 } else if (lines[2] == 1)
1612 { if (lines[3] == 0) return _box_table(0, 12); //vsds
1613 if (lines[3] == 1) return _box_table(0, 8); //vshs
1614 } else if (lines[2] == 2)
1615 { if (lines[3] == 0) return _box_table(2, 12); //vdds
1616 if (lines[3] == 2) return _box_table(2, 8); //vdhs
1617 }
1618 }
1619 } else if (lines[0] == 2)
1620 { if (lines[1] == 0)
1621 { if (lines[2] == 0)
1622 { if (lines[3] == 0) return _box_table(1, 1); //hd
1623 if (lines[3] == 1) return _box_table(3, 2); //rsud
1624 if (lines[3] == 2) return _box_table(1, 2); //rdud
1625 } else if (lines[2] == 1)
1626 { if (lines[3] == 0) return _box_table(3, 7); //rsdd
1627 if (lines[3] == 1) return _box_table(3, 10); //rshd
1628 } else if (lines[2] == 2)
1629 { if (lines[3] == 0) return _box_table(1, 7); //rddd
1630 if (lines[3] == 2) return _box_table(1, 10); //rdhd
1631 }
1632 } else if (lines[1] == 2)
1633 { if (lines[2] == 0)
1634 { if (lines[3] == 0) return _box_table(1, 1); //hd
1635 if (lines[3] == 1) return _box_table(3, 11); //vsud
1636 if (lines[3] == 2) return _box_table(1, 11); //vdud
1637 } else if (lines[2] == 1)
1638 { if (lines[3] == 0) return _box_table(3, 12); //vsdd
1639 if (lines[3] == 1) return _box_table(3, 8); //vshd
1640 } else if (lines[2] == 2)
1641 { if (lines[3] == 0) return _box_table(1, 12); //vddd
1642 if (lines[3] == 2) return _box_table(1, 8); //vdhd
1643 }
1644 }
1645 }
1646
1647 return 0x20;
1648 }
1649
1650
1651 // ------------------------------------------------------------------
1652
DrawLines(gkey key)1653 void IEclass::DrawLines(gkey key)
1654 {
1655 GFTRK("EditDrawLines");
1656
1657 static byte lines[4];
1658 static int drawx;
1659 static int drawy;
1660
1661 byte type1 = 1;
1662 byte type2 = 1;
1663
1664 (drawlines == 1) ? type2 = 2 : type1 = 2;
1665
1666 //-------------------------
1667 if (drawflag || chartyped)
1668 {
1669 ChrToLines(currline->txt[col], lines);
1670
1671 switch (key)
1672 {
1673 case KK_EditBlockRight:
1674 drawx = -1; drawy = 0;
1675
1676 if ((lines[0] == type1) || (!lines[0] && (lines[2] || lines[3])))
1677 drawx++;
1678 else if ((lines[0] == type2) || (lines[1] == type2))
1679 {
1680 drawx++; lines[0] = lines[1] = 0;
1681 }
1682
1683 break;
1684
1685 case KK_EditBlockLeft:
1686 drawx = +1; drawy = 0;
1687
1688 if ((lines[1] == type1) || (!lines[1] && (lines[2] || lines[3])))
1689 drawx--;
1690 else if ((lines[0] == type2) || (lines[1] == type2))
1691 {
1692 drawx--; lines[0] = lines[1] = 0;
1693 }
1694
1695 break;
1696
1697 case KK_EditBlockDown:
1698 drawx = 0; drawy = -1;
1699
1700 if ((lines[2] == type1) || (!lines[2] && (lines[0] || lines[1])))
1701 drawy++;
1702 else if ((lines[2] == type2) || (lines[3] == type2))
1703 {
1704 drawy++; lines[2] = lines[3] = 0;
1705 }
1706
1707 break;
1708
1709 case KK_EditBlockUp:
1710 drawx = 0; drawy = +1;
1711
1712 if ((lines[3] == type1) || (!lines[3] && (lines[0] || lines[1])))
1713 drawy--;
1714 else if ((lines[2] == type2) || (lines[3] == type2))
1715 {
1716 drawy--; lines[2] = lines[3] = 0;
1717 }
1718
1719 break;
1720 }
1721
1722 drawflag = false;
1723 }
1724
1725 //-------------------------
1726 bool gonext = true;
1727
1728 switch (key)
1729 {
1730 case KK_EditBlockRight:
1731 if (col >= (maxcol-1)) { lines[1] = 0; gonext = false; }
1732
1733 if (!drawx && gonext)
1734 {
1735 drawx = -1; lines[1] = type1;
1736 if (lines[0] == type2) lines[0] = 0;
1737 }
1738 else if (drawx == 1) drawx = -1;
1739 else if (drawx == -1)
1740 {
1741 gonext = false;
1742 drawx++; lines[0] = type1;
1743 if (lines[1] == type2) lines[1] = 0;
1744 }
1745
1746 if (gonext && drawy)
1747 {
1748 if (drawy == -1)
1749 {
1750 drawy++; lines[2] = type1;
1751 lines[0] = lines[3] = 0;
1752 }
1753 else //(drawy == 1)
1754 {
1755 drawy--; lines[3] = type1;
1756 lines[0] = lines[2] = 0;
1757 }
1758 }
1759 break;
1760
1761 case KK_EditBlockLeft:
1762 if (col <= mincol) { lines[0] = 0; gonext = false; }
1763
1764 if (!drawx && gonext)
1765 {
1766 drawx = 1; lines[0] = type1;
1767 if (lines[1] == type2) lines[1] = 0;
1768 }
1769 else if (drawx == -1) drawx = 1;
1770 else if (drawx == 1)
1771 {
1772 gonext = false;
1773 drawx--; lines[1] = type1;
1774 if (lines[0] == type2) lines[0] = 0;
1775 }
1776
1777 if (gonext && drawy)
1778 {
1779 if (drawy == -1)
1780 {
1781 drawy++; lines[2] = type1;
1782 lines[1] = lines[3] = 0;
1783 }
1784 else //(drawy == 1)
1785 {
1786 drawy--; lines[3] = type1;
1787 lines[1] = lines[2] = 0;
1788 }
1789 }
1790 break;
1791
1792 case KK_EditBlockDown:
1793 if (!currline->next) { lines[3] = 0; gonext = false; }
1794
1795 if (!drawy && gonext)
1796 {
1797 drawy = -1; lines[3] = type1;
1798 if (lines[2] == type2) lines[2] = 0;
1799 }
1800 else if (drawy == 1) drawy = -1;
1801 else if (drawy == -1)
1802 {
1803 gonext = false;
1804 drawy++; lines[2] = type1;
1805 if (lines[3] == type2) lines[3] = 0;
1806 }
1807
1808 if (gonext && drawx)
1809 {
1810 if (drawx == -1)
1811 {
1812 drawx++; lines[0] = type1;
1813 lines[1] = lines[2] = 0;
1814 }
1815 else //(drawx == 1)
1816 {
1817 drawx--; lines[1] = type1;
1818 lines[0] = lines[2] = 0;
1819 }
1820 }
1821 break;
1822
1823 case KK_EditBlockUp:
1824 if (!currline->prev) { lines[2] = 0; gonext = false; }
1825
1826 if (!drawy && gonext)
1827 {
1828 drawy = 1; lines[2] = type1;
1829 if (lines[3] == type2) lines[3] = 0;
1830 }
1831 else if (drawy == -1) drawy = 1;
1832 else if (drawy == 1)
1833 {
1834 gonext = false;
1835 drawy--; lines[3] = type1;
1836 if (lines[2] == type2) lines[2] = 0;
1837 }
1838
1839 if (gonext && drawx)
1840 {
1841 if (drawx == -1)
1842 {
1843 drawx++; lines[0] = type1;
1844 lines[1] = lines[3] = 0;
1845 }
1846 else //(drawx == 1)
1847 {
1848 drawx--; lines[1] = type1;
1849 lines[0] = lines[3] = 0;
1850 }
1851 }
1852 break;
1853 }
1854
1855 //-------------------------
1856 char new_chr = LinesToChr(lines);
1857
1858 if (new_chr != currline->txt[col])
1859 {
1860 if (col < (currline->txt.length()-1))
1861 {
1862 Undo->PushItem(EDIT_UNDO_OVR_CHAR);
1863 currline->txt[col] = new_chr;
1864 }
1865 else if (col < maxcol)
1866 {
1867 Undo->PushItem(EDIT_UNDO_INS_CHAR);
1868 currline->txt.insert(col, 1, new_chr);
1869 }
1870
1871 setlinetype(currline);
1872 displine(currline, row);
1873 }
1874
1875 //-------------------------
1876 if (gonext)
1877 {
1878 switch (key)
1879 {
1880 case KK_EditBlockRight: GoRight(); break;
1881 case KK_EditBlockLeft: GoLeft(); break;
1882 default:
1883 (key == KK_EditBlockDown) ? GoDown() : GoUp();
1884 if (col < pcol)
1885 {
1886 size_t len = pcol - col;
1887 Undo->PushItem(EDIT_UNDO_INS_TEXT|BATCH_MODE, currline, col, len);
1888 currline->txt.insert(col, len, ' ');
1889 GoEOL();
1890 }
1891 break;
1892 }
1893
1894 gotorowcol(col, row);
1895 ChrToLines(currline->txt[col], lines);
1896
1897 switch (key)
1898 {
1899 case KK_EditBlockRight:
1900 if ((drawx == -1) && (lines[0] == type1)) drawx++;
1901 break;
1902 case KK_EditBlockLeft:
1903 if ((drawx == +1) && (lines[1] == type1)) drawx--;
1904 break;
1905 case KK_EditBlockDown:
1906 if ((drawy == -1) && (lines[2] == type1)) drawy++;
1907 break;
1908 case KK_EditBlockUp:
1909 if ((drawy == +1) && (lines[3] == type1)) drawy--;
1910 break;
1911 }
1912 }
1913
1914 GFTRK(0);
1915 }
1916
1917
1918 // ------------------------------------------------------------------
1919
Header()1920 void IEclass::Header() {
1921
1922 GFTRK("EditHeader");
1923
1924 windowclose();
1925 EditHeaderinfo(msgmode, *HeaderView);
1926 windowopen();
1927
1928 GFTRK(0);
1929 }
1930
1931
1932 // ------------------------------------------------------------------
1933
Abort()1934 void IEclass::Abort() {
1935
1936 GFTRK("EditAbort");
1937
1938 cursoroff();
1939 GMenuDropmsg MenuDropmsg;
1940 if(MenuDropmsg.Run()) {
1941 done = MODE_QUIT;
1942 }
1943
1944 GFTRK(0);
1945 }
1946
1947
1948 // ------------------------------------------------------------------
1949
AskExit()1950 void IEclass::AskExit() {
1951
1952 GFTRK("EditAskExit");
1953
1954 cursoroff();
1955 GMenuQuit MenuQuit;
1956 gkbd.quitall = make_bool(MenuQuit.Run());
1957 if(gkbd.quitall) {
1958 GMenuDropmsg MenuDropmsg;
1959 if(MenuDropmsg.Run())
1960 done = MODE_QUIT;
1961 else
1962 done = MODE_SAVE;
1963 }
1964
1965 GFTRK(0);
1966 }
1967
1968
1969 // ------------------------------------------------------------------
1970
QuitNow()1971 void IEclass::QuitNow()
1972 {
1973 GFTRK("EditQuitNow");
1974
1975 if (CFG->switches.get(timeoutsavemsg))
1976 {
1977 quitnow = NO;
1978 done = MODE_SAVE;
1979 msgptr->attr.lok1();
1980 }
1981 else
1982 {
1983 quitnow = YES;
1984 done = MODE_QUIT;
1985 }
1986
1987 gkbd.quitall = YES;
1988
1989 GFTRK(0);
1990 }
1991
1992
1993 // ------------------------------------------------------------------
1994
EditMsg(int __mode,uint * __position,GMsg * __msg)1995 int EditMsg(int __mode, uint* __position, GMsg* __msg) {
1996
1997 IEclass Editor(0, MAXCOL-1, MINROW, MAXROW-2, 5);
1998 return Editor.Start(__mode, __position, __msg);
1999 }
2000
2001
2002 // ------------------------------------------------------------------
2003