1 /*
2 * fbcmdmove.cc
3 *
4 * Copyright (C) 1998 Jiann-Ching Liu
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "qe_config.h"
11 #include "colors.h"
12 #include "keymap.h"
13 #include "filebuffer.h"
14 #include <ctype.h>
15
16 /***************************************************************************/
17 // check character is word smymbol
18 //
19
isword(int ch)20 int filebuffer::isword(int ch) {
21
22 return(isalpha(ch) || isdigit(ch) || ch=='_');
23 }
24
cmd_beginline(void)25 int filebuffer::cmd_beginline(void) {
26 if (mode == FB_DATAAREA_MODE) {
27 cursor_x = buffer_x = workbufidx = 0;
28 if (left_col_no != 0) {
29 left_col_no = 0;
30 refresh_clientarea(1);
31 }
32 } else {
33 if (cmdline_idx < screen_x -1) {
34 cmdline_idx = 0;
35 } else {
36 cmdline_idx = 0;
37 refresh_cmdarea();
38 }
39 }
40 return 0;
41 }
42
43
44
cmd_endline(void)45 int filebuffer::cmd_endline(void) {
46 if (mode == FB_DATAAREA_MODE) {
47 buffer_x = workbuflen;
48 workbufidx = workbuflen;
49
50 if (workbuflen < screen_x) {
51 cursor_x = workbuflen;
52 if (left_col_no != 0) {
53 left_col_no = 0;
54 refresh_clientarea(1);
55 }
56 } else {
57 unsigned int tmpval = left_col_no;
58 cursor_x = screen_x - 1;
59 left_col_no = workbuflen - screen_x + 1;
60 if (left_col_no != tmpval) {
61 refresh_clientarea(1);
62 }
63 }
64 } else {
65 int oldval = cmdline_idx;
66
67 if ((cmdline_idx = strlen(cmdline)) != oldval) {
68 refresh_cmdarea();
69 }
70 }
71 return 0;
72 }
73
cmd_left(void)74 int filebuffer::cmd_left(void) {
75 if (mode == FB_DATAAREA_MODE) {
76 workbufidx = workbufidx > 0 ? workbufidx - 1 : 0;
77 buffer_x = workbufidx;
78
79 if (cursor_x > 0) {
80 cursor_x--;
81 } else {
82 if (left_col_no != 0) {
83 left_col_no--;
84 refresh_clientarea(1);
85 }
86 }
87 } else {
88 int oldval = cmdline_idx;
89
90 cmdline_idx = cmdline_idx > 0 ? cmdline_idx - 1 : 0;
91
92 if (oldval > screen_x + 1)
93 refresh_cmdarea();
94 }
95 return 0;
96 }
97
cmd_right(void)98 int filebuffer::cmd_right(void) {
99 if (mode == FB_DATAAREA_MODE) {
100 if (workbufidx < MAX_BUFFER_LEN-2) {
101 workbufidx = workbufidx + 1;
102 buffer_x = workbufidx;
103 if (cursor_x < screen_x - 1) {
104 cursor_x++;
105 } else {
106 left_col_no++;
107 refresh_clientarea(1);
108 }
109 }
110 } else {
111 int len = strlen(cmdline);
112 cmdline_idx = cmdline_idx < len ? cmdline_idx + 1 : len;
113
114 if (cmdline_idx >= screen_x + 1)
115 refresh_cmdarea();
116 }
117 return 0;
118 }
119
cmd_tab(void)120 int filebuffer::cmd_tab(void) {
121 for (int i = buffer_x % TAB_SPACE; i < TAB_SPACE; i++)
122 cmd_right();
123 return 0;
124 }
125
126
127 ////////////////////////////////////////////////////////////////////////
128
129
cmd_up(void)130 int filebuffer::cmd_up(void) {
131 cmd_cursor_data();
132
133 if (buffer_y > 0) {
134 write_workbuffer(QE_IF_NECESSARY);
135 buffer_y--;
136 current = current->previous;
137 if (cursor_y == 0) {
138 top_line_no--;
139 topline = topline->previous;
140 refresh_clientarea(0);
141 } else {
142 cursor_y--;
143 }
144 load_workbuffer();
145 } else {
146 if (top_line_no != -1) {
147 top_line_no = -1;
148 topline = head;
149 cursor_y++;
150 refresh_clientarea(1);
151 }
152 }
153 return 0;
154 }
155
cmd_down(void)156 int filebuffer::cmd_down(void) {
157 cmd_cursor_data();
158
159 if (buffer_y < total_line - 1) {
160 write_workbuffer(QE_IF_NECESSARY);
161 buffer_y++;
162 current = current->next;
163 if (cursor_y == screen_y-4) {
164 top_line_no++;
165 topline = topline->next;
166 refresh_clientarea(0);
167 } else {
168 cursor_y++;
169 }
170 load_workbuffer();
171 } else {
172 if (cursor_y == screen_y-4) {
173 top_line_no++;
174 topline = topline->next;
175 cursor_y--;
176 refresh_clientarea(1);
177 }
178 }
179 return 0;
180 }
181
cmd_pgup(void)182 int filebuffer::cmd_pgup(void) {
183 if (top_line_no != -1) {
184 write_workbuffer(QE_IF_NECESSARY);
185 for (int i = 1; top_line_no >= 0 && i < screen_y-3; i++) {
186 topline = topline->previous;
187 top_line_no--;
188
189 if (buffer_y > 0) {
190 current = current->previous;
191 buffer_y--;
192 } else {
193 cursor_y++;
194 }
195 }
196 refresh_clientarea(0);
197 load_workbuffer();
198 }
199 return 0;
200 }
201
cmd_pgdn(void)202 int filebuffer::cmd_pgdn(void) {
203 if (top_line_no + screen_y - 4 < total_line) {
204 write_workbuffer(QE_IF_NECESSARY);
205 for (int i = 1; top_line_no + screen_y - 4 < total_line &&
206 i < screen_y-3; i++, top_line_no++) {
207 topline = topline->next;
208 if (buffer_y < total_line - 1) {
209 current = current->next;
210 buffer_y++;
211 } else {
212 cursor_y--;
213 }
214 }
215 refresh_clientarea(0);
216 load_workbuffer();
217 }
218 return 0;
219 }
220
cmd_top(void)221 int filebuffer::cmd_top(void) {
222 cmd_cursor_data();
223 if (buffer_y != 0) {
224 write_workbuffer(QE_IF_NECESSARY);
225 buffer_y = 0;
226 cursor_y = 1;
227 top_line_no = -1;
228 topline = head;
229 current = head->next;
230 refresh_clientarea(0);
231 load_workbuffer();
232 }
233
234 return 0;
235 }
236
cmd_bottom(void)237 int filebuffer::cmd_bottom(void) {
238 int i;
239
240 cmd_cursor_data();
241
242 if (buffer_y != total_line - 1) {
243 write_workbuffer(QE_IF_NECESSARY);
244
245 buffer_y = total_line - 1;
246 current = tail->previous;
247
248 topline = current;
249 top_line_no = buffer_y;
250
251 for (i = 0; i < screen_y-5 && top_line_no >= 0 ; i++) {
252 topline = topline->previous;
253 top_line_no--;
254 }
255 cursor_y = i;
256 refresh_clientarea(0);
257 load_workbuffer();
258 }
259 return 0;
260 }
261
cmd_top_edge(void)262 int filebuffer::cmd_top_edge(void) {
263 int updateflag = 0;
264
265 cmd_cursor_data();
266
267 while ((buffer_y > top_line_no) && (buffer_y > 0)) {
268 if (! updateflag) write_workbuffer(QE_IF_NECESSARY);
269 updateflag = 1;
270 buffer_y--;
271 cursor_y--;
272 current = current->previous;
273 }
274
275 if (updateflag) load_workbuffer();
276
277 return 0;
278 }
279
cmd_bottom_edge(void)280 int filebuffer::cmd_bottom_edge(void) {
281 int updateflag = 0;
282
283 cmd_cursor_data();
284
285 while ((buffer_y < top_line_no + screen_y -4)&&(buffer_y < total_line-1)) {
286 if (! updateflag) write_workbuffer(QE_IF_NECESSARY);
287 updateflag = 1;
288 buffer_y++;
289 cursor_y++;
290 current = current->next;
291 }
292
293 if (updateflag) load_workbuffer();
294
295 return 0;
296 }
297
cmd_scrollup(void)298 int filebuffer::cmd_scrollup(void) {
299 cmd_cursor_data();
300
301 if (top_line_no + screen_y - 4 < total_line) {
302 write_workbuffer(QE_IF_NECESSARY);
303 top_line_no++;
304 topline = topline->next;
305 if (buffer_y == total_line-1) {
306 cursor_y--;
307 } else {
308 current = current->next;
309 buffer_y++;
310 }
311 load_workbuffer();
312 refresh_clientarea(0);
313 } else {
314 return cmd_down();
315 }
316 // wprintw(win, "[scrollup]");
317 return 0;
318 }
319
cmd_scrolldown(void)320 int filebuffer::cmd_scrolldown(void) {
321 cmd_cursor_data();
322
323 if (top_line_no > -1 && buffer_y > 0) {
324 write_workbuffer(QE_IF_NECESSARY);
325 top_line_no--;
326 topline = topline->previous;
327 current = current->previous;
328 buffer_y--;
329 load_workbuffer();
330 refresh_clientarea(0);
331 } else {
332 return cmd_up();
333 }
334 return 0;
335 }
336
cmd_scrollleft(void)337 int filebuffer::cmd_scrollleft(void) {
338 cmd_cursor_data();
339
340 if (left_col_no + screen_x < MAX_BUFFER_LEN-1) {
341 unsigned int org = left_col_no;
342
343 cmd_right();
344
345 if (org == left_col_no) {
346 left_col_no++;
347 cursor_x--;
348 refresh_clientarea(1);
349 }
350 } else {
351 cmd_right();
352 }
353 return 0;
354 }
355
cmd_scrollright(void)356 int filebuffer::cmd_scrollright(void) {
357 cmd_cursor_data();
358 if (left_col_no > 0) {
359 unsigned int org = left_col_no;
360
361 cmd_left();
362
363 if (org == left_col_no) {
364 left_col_no--;
365 cursor_x++;
366 refresh_clientarea(1);
367 }
368 } else {
369 cmd_left();
370 }
371 return 0;
372 }
373
374 /***************************************************************************/
375 // Move cursor end of word
376 // Macro : [end word] [we]
377 // Status : OK
378 //
379
cmd_wordend(void)380 int filebuffer::cmd_wordend(void) {
381 cmd_cursor_data();
382
383
384 while (isword(workbuffer[workbufidx]) && workbufidx< workbuflen)
385 {
386 moveto(buffer_y, workbufidx);
387 workbufidx++;
388 }
389
390 return 0;
391 }
392
393 /***************************************************************************/
394 // Move cursor begin of word
395 // Macro : [begin word] [wb]
396 // Status : OK
397 //
398
cmd_wordbegin(void)399 int filebuffer::cmd_wordbegin(void) {
400 cmd_cursor_data();
401
402 while (isword(workbuffer[workbufidx]) && workbufidx>0)
403 {
404 moveto(buffer_y, workbufidx);
405 workbufidx--;
406 }
407
408 return 0;
409 }
410
411 /***************************************************************************/
412 // Move cursor to next word
413 // Macro : [next word] [nw]
414 // Status : OK
415 //
416
cmd_wordnext(void)417 int filebuffer::cmd_wordnext(void) {
418 cmd_cursor_data();
419
420 while (isword(workbuffer[workbufidx]) && workbufidx< workbuflen)
421 {
422 moveto(buffer_y, workbufidx);
423 workbufidx++;
424 }
425
426 while (!isword(workbuffer[workbufidx]) && workbufidx< workbuflen)
427 {
428 moveto(buffer_y, workbufidx);
429 workbufidx++;
430 }
431 return 0;
432 }
433
434 /***************************************************************************/
435 // Drop Anchor bookmark0
436 // Macro : [set0]
437 // Status : OK
438 // Remark : Better use for system internal use
439
cmd_setbook0(void)440 int filebuffer::cmd_setbook0(void) {
441
442 setbook0x = workbufidx;
443 setbook0y = buffer_y;
444 return 0;
445 }
446
447 /***************************************************************************/
448 // Drop Anchor bookmark1
449 // Macro : [set1]
450 // Status : OK
451
cmd_setbook1(void)452 int filebuffer::cmd_setbook1(void) {
453
454 setbook1x = workbufidx;
455 setbook1y = buffer_y;
456 return 0;
457 }
458
459 /***************************************************************************/
460 // Drop Anchor bookmark2
461 // Macro : [set2]
462 // Status : OK
463
cmd_setbook2(void)464 int filebuffer::cmd_setbook2(void) {
465
466 setbook2x = workbufidx;
467 setbook2y = buffer_y;
468 return 0;
469 }
470
471 /***************************************************************************/
472 // go Anchor bookmark0
473 // Macro : [go0]
474 // Status : OK
475 // Remark : Better use for system internal use
476
cmd_gobook0(void)477 int filebuffer::cmd_gobook0(void) {
478 cmd_cursor_data();
479 moveto(setbook0y, setbook0x);
480 workbufidx = setbook0x;
481 buffer_y = setbook0y;
482 return 0;
483 }
484
485 /***************************************************************************/
486 // go Anchor bookmark1
487 // Macro : [go1]
488 // Status : OK
489 //
490
cmd_gobook1(void)491 int filebuffer::cmd_gobook1(void) {
492 cmd_cursor_data();
493 moveto(setbook1y, setbook1x);
494 workbufidx = setbook1x;
495 buffer_y = setbook1y;
496 return 0;
497 }
498
499 /***************************************************************************/
500 // go Anchor bookmark2
501 // Macro : [go2]
502 // Status : OK
503 //
504 //
505
cmd_gobook2(void)506 int filebuffer::cmd_gobook2(void) {
507 cmd_cursor_data();
508 moveto(setbook2y, setbook2x);
509 workbufidx = setbook2x;
510 buffer_y = setbook2y;
511 return 0;
512 }
513
514 /***************************************************************************/
515 // duplicate upper line char
516 // status : not finish
517 // I don't know how to place chatactor to current buffer
518 // but it's easy to replace by macro
519 // [up][mb][down][cm][unmark][right]
520
cmd_dupchar(void)521 int filebuffer::cmd_dupchar(void) {
522 char ch;
523
524 cmd_cursor_data();
525
526 write_workbuffer(QE_IF_NECESSARY);
527
528 if (buffer_y>1) {
529 buffer_y--;
530 current = current->previous;
531 load_workbuffer();
532 ch = workbuffer[workbufidx];
533 printf("%d",ch);
534 buffer_y++;
535 current = current->next;
536 workbuffer[workbufidx++]=ch;
537 mvwinsch(win,buffer_y,workbufidx,ch);
538 moveto(buffer_y,workbufidx);
539 refresh_clientarea(0);
540 }
541 return 0;
542 }
543
544
545
cmd_centerline(void)546 int filebuffer::cmd_centerline(void) {
547 int cl = (screen_y - 3) / 2;
548 int oldy = cursor_y;
549
550 cmd_cursor_data();
551
552 while (topline != head && cursor_y < cl) {
553 topline = topline->previous;
554 top_line_no--;
555 cursor_y++;
556 }
557
558 while (cursor_y > cl) {
559 topline = topline->next;
560 top_line_no++;
561 cursor_y--;
562 }
563 if (oldy != cursor_y) refresh_clientarea(1);
564 return 0;
565 }
566
cmd_backword(void)567 int filebuffer::cmd_backword(void) {
568 int i, found;
569
570 for (i = buffer_x; i >= 0; i--)
571 if (workbuffer[i] == ' ') break;
572
573 for (found = 0; i >= 0; i--) {
574 if (workbuffer[i] != ' ') {
575 found = 1;
576 break;
577 }
578 }
579
580 if (found) {
581 int need_refresh;
582
583 for (; i > 0; i--)
584 if (workbuffer[i-1] == ' ') break;
585
586 for (need_refresh = 0; workbufidx > i; workbufidx--, buffer_x--) {
587 if (cursor_x > 0) {
588 cursor_x--;
589 } else {
590 left_col_no--;
591 need_refresh = 1;
592 }
593 }
594 if (need_refresh) refresh_clientarea(1);
595 } else if (current->previous != head) {
596 cmd_up();
597 cmd_endline();
598 return cmd_backword();
599 }
600
601 return 0;
602 }
603
cmd_tabword(void)604 int filebuffer::cmd_tabword(void) {
605 static int level = 0;
606 int i, found;
607
608 i = buffer_x;
609
610 if (level++ == 0)
611 for (; i < workbuflen; i++)
612 if (workbuffer[i] == ' ')
613 break;
614
615 for (found = 0; i < workbuflen; i++) {
616 if (workbuffer[i] != ' ') {
617 found = 1;
618 break;
619 }
620 }
621
622 if (found) {
623 int need_refresh;
624
625 for (need_refresh = 0; workbufidx < i; workbufidx++, buffer_x++) {
626 if (cursor_x < screen_x - 1) {
627 cursor_x++;
628 } else {
629 left_col_no++;
630 need_refresh = 1;
631 }
632 }
633 if (need_refresh) refresh_clientarea(1);
634 } else if (current->next != tail) {
635 cmd_down();
636 cmd_beginline();
637 cmd_tabword();
638 }
639 level--;
640 return 0;
641 }
642
moveto(const int y,const int x)643 void filebuffer::moveto(const int y, const int x) {
644 int need_refresh = 0;
645
646 write_workbuffer(QE_IF_NECESSARY);
647
648 if (y < top_line_no) {
649 int yy = maximum(y, 0);
650
651 for (; top_line_no > -1 && buffer_y > yy; buffer_y--) {
652 topline = topline->previous;
653 current = current->previous;
654 top_line_no--;
655 }
656
657 for (; buffer_y > yy; buffer_y--) {
658 current = current->previous;
659 cursor_y--;
660 }
661
662 need_refresh = 1;
663 } else if (y > top_line_no + screen_y - 4) {
664 int yy = minimum(y, total_line-1);
665
666 for (; buffer_y < yy; buffer_y++) {
667 topline = topline->next;
668 current = current->next;
669 top_line_no++;
670 }
671 need_refresh = 1;
672 } else {
673 for (; buffer_y > y; buffer_y--) {
674 current = current->previous;
675 cursor_y--;
676 }
677 for (; buffer_y < y; buffer_y++) {
678 current = current->next;
679 cursor_y++;
680 }
681 }
682
683 unsigned int xx = minimum(maximum(x, 0), MAX_BUFFER_LEN-1);
684
685 if (xx < left_col_no || xx > left_col_no + screen_x - 1) {
686 left_col_no = 0;
687
688 for (left_col_no = 0; xx > left_col_no + screen_x - 1; left_col_no++)
689 ;
690 need_refresh = 1;
691 }
692
693 buffer_x = xx;
694 cursor_x = buffer_x - left_col_no;
695
696 load_workbuffer();
697
698 if (need_refresh) refresh_clientarea(0);
699 }
700
701
cmd_gotoline(void)702 int filebuffer::cmd_gotoline(void) {
703 WINDOW *mw;
704 char buffer[MAX_BUFFER_LEN+1];
705 int key, idx = 0, len = 0;
706 int finish = 0;
707 const char linenumstr[] = "Line Number: ";
708 char fmt[10];
709 int startpos = strlen(linenumstr) + 2;
710 const int numlen = 12;
711
712
713 int width = startpos + numlen + 2;
714
715 mw = newwin(3, width, screen_y / 2 - 2, (screen_x - width)/ 2 );
716
717 setattr(mw, ATTRIBUTE_goto_text);
718
719 sprintf(fmt, " %%-%ds", width-3);
720
721 box(mw, 0, 0);
722 mvwprintw(mw, 1, 1, fmt, linenumstr);
723 keypad(mw, TRUE);
724 nodelay(mw, FALSE);
725
726 sprintf(fmt, "%%-%ds", numlen);
727
728 wmove(mw, 1, startpos);
729
730 while (! finish) {
731 switch(key = wgetch(mw)) {
732 case KEY_LEFT:
733 if (idx > 0) {
734 idx--;
735 wmove(mw, 1, startpos + idx);
736 }
737 break;
738 case KEY_RIGHT:
739 if (idx < len) {
740 idx++;
741 wmove(mw, 1, startpos + idx);
742 }
743 break;
744 case KEY_BACKSPACE:
745 case KEY_DC:
746 if (idx < len) {
747 for (int i = idx; i < len; i++)
748 buffer[i] = buffer[i+1];
749 buffer[--len] = '\0';
750 mvwprintw(mw, 1, startpos, fmt, buffer);
751 wmove(mw, 1, startpos + idx);
752 }
753 break;
754 case ' ':
755 finish = 1;
756 break;
757 case KEY_ENTER:
758 case KEY_RETURN:
759 case KEY_LINEFEED:
760 finish = 2;
761 break;
762 default:
763 if (key >= '0' && key <= '9') {
764 if (idx < numlen) {
765 buffer[idx] = key;
766 mvwaddch(mw, 1, startpos + idx, key);
767 idx++;
768 len = maximum(len, idx);
769 } else {
770 beep();
771 }
772 }
773 break;
774 }
775 }
776
777 delwin(mw);
778 touchwin(win);
779 wrefresh(win);
780
781 if (finish == 2 && len > 0) {
782 buffer[len] = '\0';
783 moveto(atoi(buffer)-1, buffer_x);
784 }
785
786 return 0;
787 }
788
cmd_goto_currline(int cy,int cx)789 int filebuffer::cmd_goto_currline(int cy, int cx) {
790 cmd_cursor_data();
791 moveto(cy, cx);
792 buffer_y = cy;
793 workbufidx = cx;
794 return 0;
795
796 }
797
798 /***************************************************************************/
799 // move cursor to line number
800 // macro : [goto line]
801 // status : OK
802
803
cmd_goto_line(void)804 int filebuffer::cmd_goto_line(void) {
805 static char str[7];
806 static char idx = 0;
807 int key = 0;
808 int curr_line = 0;
809 const char *fmtstr = "Ctrl-G: stop. Goto Line: %s";
810 str[idx] = '\0';
811 display_messages(fmtstr, str);
812
813 write_workbuffer(QE_IF_NECESSARY);
814
815 while (1) {
816 for (int finish = 0; ! finish;) {
817 if (isdigit(key = wgetch(win))) {
818 str[idx] = key;
819 idx = (idx < 5) ? idx+1 : idx;
820 } else {
821 switch (key) {
822 case KEY_ENTER:
823 case KEY_RETURN:
824 case KEY_LINEFEED:
825 curr_line = atoi(str)-1; // get input line number
826 cmd_goto_currline(curr_line, workbufidx);
827 finish = 1;
828 return 0;
829 case KEY_BACKSPACE:
830 idx = (idx > 0) ? idx-1 : idx;
831 str[idx] = '\0'; // end of string
832 display_messages(fmtstr, str); // update string
833 break;
834 case KEY_CTRL('g'):
835 cmd_cursor_data();
836 display_messages();
837 return 0;
838 default:
839 break;
840
841
842 } // end of switch
843 }
844 str[idx] = '\0';
845 display_messages(fmtstr, str);
846
847
848 } // end of isdigit
849 }
850 return 0;
851 }
852
853 /***************************************************************************/
854 // mark work under cursor
855 // macro : [mark word]
856 // status : OK
857
cmd_markword(void)858 int filebuffer::cmd_markword(void) {
859 int idx=0;
860
861 cmd_cursor_data();
862 cmd_unmark();
863 cmd_setbook0(); // save current position in templete book
864 cmd_wordbegin(); // begin of word
865 cmd_right();
866 cmd_markblock();
867 write_workbuffer(QE_IF_NECESSARY);
868 while (isword(workbuffer[workbufidx]) && workbufidx< workbuflen)
869 {
870 if (idx>21) break;
871 patstr[idx++]=workbuffer[workbufidx];
872 moveto(buffer_y, workbufidx);
873 workbufidx++;
874 }
875 patstr[idx]='\0';
876 cmd_markblock();
877 cmd_gobook0();
878 // printf("%s",patstr);
879 return 0;
880 }
881
882
883