Annotation of OpenXM_contrib2/fep/fep_edit.c, Revision 1.8
1.1 noro 1: /* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */
2:
1.7 fujimoto 3: #if defined(ANDROID)
4: #include <strings.h>
5: #define index(s,c) strchr(s,c)
6: #define rindex(s,c) strrchr(s,c)
7: #endif
8:
1.1 noro 9: #ifndef lint
10: static char rcsid[]=
11: "$Id: fep_edit.c,v 4.10 1995/01/20 08:15:55 utashiro Exp $ (SRA)";
12: #endif /* lint */
13:
14: #include <stdio.h>
1.4 ohara 15: #include <stdlib.h>
1.8 ! noro 16: #include <unistd.h>
1.4 ohara 17: #include <string.h>
1.1 noro 18: #include <sys/types.h>
19: #include <sys/stat.h>
20: #include <sys/ioctl.h>
21: #ifdef TERMIOS
22: #include <termios.h>
23: #if defined(__linux__) || defined(__CYGWIN__)
24: #ifndef _POSIX_VDISABLE
25: #define _POSIX_VDISABLE '\0'
26: #endif
27: #endif
28: #else
29: #include <sgtty.h>
30: #endif
31: #include <sys/time.h>
32: #include <ctype.h>
33: #if defined(__CYGWIN__)
34: #include <sys/dirent.h>
35: #define direct dirent
1.7 fujimoto 36: #elif defined(sun) || defined(__FreeBSD__) || defined(ANDROID)
1.2 noro 37: #include <dirent.h>
38: #define direct dirent
39: #include <unistd.h>
1.1 noro 40: #else
41: #include <sys/dir.h>
42: #endif
43: #include <sys/file.h>
44: #include <setjmp.h>
45: #include "fep_defs.h"
46: #include "fep_glob.h"
47: #include "fep_funcs.h"
48:
49: CHAR *CommandLine; /* pointer to command line buffer */
50: CHAR *KillBuffer; /* pointer to kill buffer */
51: int CurrentPosition; /* current cursor position */
52: int MarkPosition = -1; /* Marked position */
53: EDITMODE editmode = NOTYET; /* edtimode EMACS, VI */
54: EDITSTATUS editstatus = NOTEDITING;/* EDITING, NOTEDITING */
55:
56: int maxline = MAXCMDLEN; /* maximum length of command line */
57: int NeedNewLine; /* add new line flag */
58: int NeedSave; /* need to save to history */
59: int Transparency = OFF; /* transparent flag */
60: int Through = OFF; /* through flag */
61: int eof_occured = 0; /* eof has been occured */
62: jmp_buf jbuf; /* jump buffer */
63:
64: FUNC *curFuncTab; /* current function table */
65: FUNC *altFuncTab; /* alternative function table */
66:
1.8 ! noro 67: void ls (DIR *dirp, char *prefixstring);
! 68:
1.1 noro 69: /*
70: * Default binding table
71: */
72: BINDENT emacsBindings[] = {
73: /* NULL */ {"\0", mark},
74: /* ^A */ {"\\^A", beginning_of_line},
75: /* ^B */ {"\\^B", backward_character},
76: /* ^D */ {"\\^D", delete_next_character},
77: /* ^E */ {"\\^E", end_of_line},
78: /* ^F */ {"\\^F", forward_character},
79: /* ^I */ {"\\^I", insert_tab},
80: /* ^J */ {"\\^J", new_line},
81: /* ^K */ {"\\^K", kill_to_end_of_line},
82: /* ^L */ {"\\^L", clear_screen},
83: /* ^M */ {"\\^M", new_line},
84: /* ^N */ {"\\^N", next_history},
85: /* ^P */ {"\\^P", previous_history},
86: /* ^T */ {"\\^T", previous_history},
87: /* ^Y */ {"\\^Y", yank_from_kill_buffer},
88: /* ^^ */ {"\\^^", toggle_through},
89: /* esc-b */ {"\\^[b", backward_word},
90: /* esc-B */ {"\\^[B", backward_Word},
91: /* esc-d */ {"\\^[d", delete_next_word},
92: /* esc-D */ {"\\^[D", delete_next_Word},
93: /* esc-f */ {"\\^[f", forward_word},
94: /* esc-F */ {"\\^[F", forward_Word},
95: /* esc-h */ {"\\^[h", delete_previous_word},
96: /* esc-H */ {"\\^[H", delete_previous_Word},
97: /* esc-l */ {"\\^[l", list_file_name},
98: /* esc-L */ {"\\^[L", list_file_name},
99: /* esc-n */ {"\\^[n", insert_next_history},
100: /* esc-N */ {"\\^[N", insert_next_history},
101: /* esc-p */ {"\\^[p", insert_previous_history},
102: /* esc-P */ {"\\^[P", insert_previous_history},
103: /* esc-. */ {"\\^[.", insert_current_history},
104: /* esc-esc */ {"\\^[\\^[", expand_file_name},
105: /* esc-"-" */ {"\\^[-", toggle_through},
106: /* esc-_ */ {"\\^[_", invoke_shell},
107: /* esc-< */ {"\\^[<", search_reverse},
108: /* esc-> */ {"\\^[>", search_forward},
109: /* esc-? */ {"\\^[?", show_help},
110: /* ^X-^B */ {"\\^X\\^B", show_bindings},
111: /* ^X-B */ {"\\^XB", show_bindings},
112: /* ^X-b */ {"\\^Xb", show_bindings},
113: /* ^X-^H */ {"\\^X\\^H", show_history},
114: /* ^X-H */ {"\\^XH", show_history},
115: /* ^X-h */ {"\\^Xh", show_history},
116: /* ^X-^V */ {"\\^X\\^V", view_buffer},
117: /* ^X-^K */ {"\\^X\\^K", kill_to_top_of_line},
118: /* ^X-^L */ {"\\^X\\^L", fep_repaint},
119: /* ^X-^C */ {"\\^X\\^C", (FUNC)terminate},
120: /* ^X-^D */ {"\\^X\\^D", send_eof},
121: /* ^X-( */ {"\\^X(", fep_start_script},
122: /* ^X-) */ {"\\^X)", fep_end_script},
123: /* */ {NULL, NULL}
124: };
125:
126: /*
127: * Initialize function table buffer
128: */
1.8 ! noro 129: void init_bind_table ()
1.1 noro 130: {
131:
132: curFuncTab = (FUNC *) calloc (sizeof (FUNC), 256);
133: altFuncTab = (FUNC *) calloc (sizeof (FUNC), 256);
134: if (curFuncTab == 0 || altFuncTab == 0) {
135: printf ("Can't allocate space for function table\n");
136: exit (1);
137: }
138: }
139:
140: /*
141: * Initialize function table
142: */
143: char strspace [256], *strspace_addr = strspace;
144:
1.8 ! noro 145: void init_edit_params ()
1.1 noro 146: {
147: struct indirect *idp;
148: char *cp, *getenv();
149: char sbuf[2048], *term, *tgetstr();
150:
151: if (term = look_var ("term")) {
152: if (tgetent (sbuf, term) == 1) {
153: if (lines == 0)
154: lines = tgetnum ("li");
155: if (columns == 0)
156: columns = tgetnum ("co");
157: term_clear = tgetstr ("cl", &strspace_addr);
158: }
159: }
160:
161: if (lines == 0)
162: lines = 24;
163: if (columns == 0)
164: columns = 80;
165:
166: sprintf (sbuf, "%d", lines);
167: set_var ("crt", sbuf);
168:
169: if (editmode == NOTYET) {
170: if (look_var ("editmode"))
171: set_var ("editmode", look_var ("editmode"));
172: else
173: set_var ("editmode", "emacs");
174: }
175:
1.6 ohara 176: sprintf (sbuf, "%d", lines);
177: set_var ("showhist", sbuf);
1.1 noro 178:
179: /*
180: * Read startup file
181: */
182: sourceRcFile ();
183:
184: /*
185: * Read history if 'history-file' is set
186: */
187: {
188: char *cp, *mk_home_relative ();
189:
190: if (look_var ("savehist") && (cp = look_var ("history-file"))) {
191: cp = mk_home_relative (cp);
192:
193: if (access (cp, R_OK) == 0)
194: read_history (cp);
195: }
196: }
197:
198: /*
199: * Initialize command line buffer
200: */
201: CommandLine = (CHAR *) calloc (maxline, 1);
202: KillBuffer = (CHAR *) calloc (maxline, 1);
203: if (CommandLine == 0 || KillBuffer == 0) {
204: perror ("Edit line buffer");
205: exit (1);
206: }
207: (void) strcpy (CommandLine, "");
208: (void) strcpy (KillBuffer, "");
209: CurrentPosition = 0;
210: }
211:
212: /*
213: * Initialize emacs bindings
214: */
1.8 ! noro 215: void initEmacsBindings (FUNC cft[], FUNC aft[])
1.1 noro 216: {
217: register int i;
218: BINDENT *ftp;
219:
220: for (i = 0; i < 256; i++)
221: cft[i] = self_insert;
222:
223: #define import(table,key,fn) if((int)key>0)table[(int)key]=fn
224:
225: #ifdef TERMIOS
226: /* Now, using cbreak mode
227: import (cft, initial_ttymode.c_cc[VSTART], ignore);
228: import (cft, initial_ttymode.c_cc[VSTOP], ignore);
229: */
230: #if 0
231: import (cft, initial_ttymode.c_cc[VINTR], insert_and_flush);
232: #else
233: /* added by noro */
234: import (cft, initial_ttymode.c_cc[VINTR], send_int_sig);
235: /* XXX : this may not be necessary */
236: import (aft, initial_ttymode.c_cc[VINTR], send_int_sig);
237: #endif
238: import (cft, initial_ttymode.c_cc[VQUIT], insert_and_flush);
239: /* Now, EOF will be sent on empty line.
240: import (cft, initial_ttymode.c_cc[VEOF], send_eof);
241: */
242: #ifdef VSWTC
243: import (cft, initial_ttymode.c_cc[VSWTC], insert_and_flush);
244: #endif
245: import (cft, initial_ttymode.c_cc[VSUSP], insert_and_flush);
246: /* ^Y is used for yank-from-kill-buffer
247: import (cft, initial_ttymode.c_cc[VDSUSP], self_insert);
248: */
249: import (cft, initial_ttymode.c_cc[VREPRINT], reprint);
1.3 ohara 250: #ifdef VDISCARD
1.1 noro 251: import (cft, initial_ttymode.c_cc[VDISCARD], self_insert);
1.3 ohara 252: #endif
1.1 noro 253: import (cft, initial_ttymode.c_cc[VWERASE], delete_previous_word);
254: import (cft, initial_ttymode.c_cc[VLNEXT], literal_next);
255: import (cft, initial_ttymode.c_cc[VERASE], delete_previous_character);
256: import (cft, initial_ttymode.c_cc[VKILL], delete_line);
257: #else
258: /* Now, using cbreak mode
259: import (cft, tchars_buf.t_startc, ignore);
260: import (cft, tchars_buf.t_stopc, ignore);
261: */
262: #if 0
263: import (cft, tchars_buf.t_intrc, insert_and_flush);
264: #else
265: import (cft, tchars_buf.t_intrc, send_int_sig);
266: import (aft, tchars_buf.t_intrc, send_int_sig);
267: #endif
268: import (cft, tchars_buf.t_quitc, insert_and_flush);
269: /* Now, EOF will be sent on empty line.
270: import (cft, tchars_buf.t_eofc, send_eof);
271: */
272: import (cft, tchars_buf.t_brkc, insert_and_flush);
273: import (cft, ltchars_buf.t_suspc, insert_and_flush);
274: /* ^Y is used for yank-from-kill-buffer
275: import (cft, ltchars_buf.t_dsuspc, self_insert);
276: */
277: import (cft, ltchars_buf.t_rprntc, reprint);
278: import (cft, ltchars_buf.t_flushc, self_insert);
279: import (cft, ltchars_buf.t_werasc, delete_previous_word);
280: import (cft, ltchars_buf.t_lnextc, literal_next);
281: import (cft, initial_ttymode.sg_erase, delete_previous_character);
282: import (cft, initial_ttymode.sg_kill, delete_line);
283: #endif
284:
285: #undef import
286:
287: /*
288: * Set default bindings
289: */
290: for (ftp = emacsBindings; ftp->bt_s; ftp++) {
291: bind_key (cft, ftp->bt_func, ftp->bt_s, fep_abort);
292: }
293: }
294:
295: /*
296: * Main function of front end program
297: */
1.8 ! noro 298: CHAR * mygetline()
1.1 noro 299: {
300: int c;
301: CHAR *execute_command, *check_alias();
302: char *remained;
303: int processed;
304:
305: (void) strcpy (CommandLine, "");
306: CurrentPosition = 0;
307: resetCurrentHistory ();
308:
309: RETRY:
310: (void) fflush (stdout);
311: NeedNewLine = 0;
312: NeedSave = 0;
313: editstatus = EDITING;
314: processed = 0;
315: (void) setjmp (jbuf);
316:
317: /*
318: * If there is file pointer for I/O redirection,
319: * read input from the pointer and return
320: */
321: if (redirect_fp) {
322:
323: /*
324: * Check output from sub-process
325: */
326: swallow_output();
327:
328: if (fgets (CommandLine, MAXCMDLEN, redirect_fp)) {
329: ++redirect_line;
330: execute_command = CommandLine;
331: goto RETURN;
332: }
333: else {
334: if (look_var ("verbose"))
335: printf ("%d lines redirected\n", redirect_line);
336: errorBell ();
337: if (redirect_pid) {
338: pclose (redirect_fp);
339: redirect_pid = 0;
340: }
341: else
342: fclose (redirect_fp);
343: redirect_fp = NULL;
344: }
345: }
346:
347: while ((c = getcharacter ()) >= (CHAR) 0) {
348: int status;
349:
350: /*
351: * In transparet mode
352: */
353: if (Through == ON || Transparency == ON) {
354: if (*curFuncTab[(int) c] == toggle_through ||
355: *curFuncTab[(int) c] == fix_transparency) {
356: (*curFuncTab[(int) c])();
357: goto RETRY;
358: }
359: else {
360: CommandLine[CurrentPosition] = c;
361: CommandLine[CurrentPosition + 1] = '\0';
362: return (CommandLine);
363: }
364: }
365:
366: /*
367: * If find EOF character on top of empty line
368: * and the variable "send-eof-on-empty-line" is set
369: * call send_eof
370: */
371: if (
372: #ifdef TERMIOS
373: c == initial_ttymode.c_cc[VEOF]
374: #else
375: c == tchars_buf.t_eofc
376: #endif
377: && curFuncTab[c] != send_eof
378: && ! look_var ("ignore-eof")
379: && CommandLine [0] == '\0'
380: ) {
381: if (!eof_occured && look_var ("alarm-on-eof")) {
382: eof_occured = 1;
383: status = alarm_on_eof (c);
384: }
385: else
386: status = send_eof (c);
387: }
388: else {
389: eof_occured = 0;
390: status = callfunc (curFuncTab, c);
391: }
392:
393: (void) fflush (stdout);
394: if (status == 1) /* end of line editing */
395: break;
396: else /* continue line editing */
397: continue;
398: }
399: editstatus = NOTEDITING;
400:
401: REPROCESS:
402:
403: /*
404: * Check command line refer history or not
405: */
406: if (refer_history () == PROCESSED)
407: goto RETRY;
408:
409: /*
410: * Check alias list
411: */
412: if (!processed && !look_var ("noalias")
413: && (execute_command = check_alias (CommandLine))
414: ) {
415: if (look_var ("verbose"))
416: printf ("%s\n", execute_command);
417: }
418: else
419: execute_command = CommandLine;
420:
421:
422: /*
423: * Check builtin function, and execute it.
424: */
425: if (executeBuiltInFunction (execute_command, &remained) == PROCESSED) {
426: if (!processed)
427: addHistory (CommandLine);
428: CommandLine[0] = '\0';
429: CurrentPosition = 0;
430: if (remained && *remained) {
431: strcpy (CommandLine, remained);
432: processed = 1;
433: goto REPROCESS;
434: }
435: if (!redirect_fp)
436: fputs (prompt, stdout);
437: goto RETRY;
438: }
439:
440: if (NeedSave) {
441: if (!is_empty_line (CommandLine) || !look_var ("ignore-empty-line"))
442: if (!processed)
443: addHistory (CommandLine);
444: /*
445: * put string to buffer
446: */
447: buf_put (output_buffer, CommandLine);
448: if (NeedNewLine == 1)
449: buf_put (output_buffer, "\n");
450: }
451:
452: if (NeedNewLine == 1)
453: (void) strcat (execute_command, "\n");
454:
455: RETURN:
456: return (execute_command);
457: }
458:
459: /*
460: * Invoke appropliate function according to fucntion table
461: * Return value 1 means exit from line editing
462: */
1.8 ! noro 463: int callfunc (FUNC ft[], int c)
1.1 noro 464: {
465:
466: if (isIndirect(ft[(int) c])) {
467: FUNC *nft = maskIndirect (ft[(int)c]);
468: char nc;
469:
470: nc = (CHAR) getcharacter();
471: return (callfunc (nft, nc));
472: }
473: else
474: return ((*ft[(int) c]) (c));
475: }
476:
477: /*
478: * Beep and do nothing
479: */
1.8 ! noro 480: int fep_abort()
1.1 noro 481: {
482: (void) errorBell ();
483: return (0);
484: }
485:
486: /*
487: * Insert the character self
488: */
1.8 ! noro 489: int self_insert(CHAR c)
1.1 noro 490: {
491: register int i, nbyte = 1, currentNull;
492: #ifdef KANJI
493: CHAR byte2;
494: #endif /* KANJI */
495:
496: currentNull = strlen (CommandLine);
497:
498: if (currentNull >= maxline) {
499: errorBell();
500: return (0);
501: }
502:
503: if (isctlchar(CommandLine[CurrentPosition]))
504: (void) putchar (BS);
505: #ifdef KANJI
506: if (iskanji (c)) {
507: byte2 = (CHAR) getcharacter ();
508: putchar (c);
509: putchar (byte2);
510: nbyte = 2;
511: }
512: else
513: #endif /* KANJI */
514: putChar (c);
515: reverse_strcpy (
516: &CommandLine[CurrentPosition] + nbyte,
517: &CommandLine[CurrentPosition]
518: );
519: CurrentPosition += nbyte;
520: CommandLine[CurrentPosition - nbyte] = c;
521: #ifdef KANJI
522: if (nbyte > 1) {
523: CommandLine[CurrentPosition - 1] = byte2;
524: }
525: #endif /* KANJI */
526: printS (&CommandLine [CurrentPosition]);
527:
528: if (CommandLine[CurrentPosition] != '\0') {
529: repeat (BS, howlong (&CommandLine[CurrentPosition + 1], 0));
530: (void) putchar (BS);
531: }
532: return (0);
533: }
534:
535: /*
536: * Insert string in current position
537: */
1.8 ! noro 538: int insert_string (CHAR *s)
1.1 noro 539: {
540: register int i, nbyte = strlen (s), currentNull;
541:
542: currentNull = strlen (CommandLine);
543:
544: if (currentNull + nbyte >= maxline - 1) {
545: errorBell();
546: return (0);
547: }
548:
549: if (isctlchar(CommandLine[CurrentPosition]))
550: (void) putchar (BS);
551: printS (s);
552: reverse_strcpy (
553: &CommandLine[CurrentPosition] + nbyte, /* to */
554: &CommandLine[CurrentPosition] /* from */
555: );
556: bcopy (s, &CommandLine[CurrentPosition], nbyte);
557: CurrentPosition += nbyte;
558:
559: if (CommandLine[CurrentPosition] != '\0') {
560: printS (&CommandLine[CurrentPosition]);
561: repeat (BS, howlong (&CommandLine[CurrentPosition], 0));
562: }
563: return (0);
564: }
565:
566: /*
567: * Yank string from kill buffer.
568: */
1.8 ! noro 569: void yank_from_kill_buffer ()
1.1 noro 570: {
571: insert_string (KillBuffer);
572: }
573:
574: /*
575: * Set mark to current position
576: */
1.8 ! noro 577: int mark ()
1.1 noro 578: {
579: set_mark (CurrentPosition);
580: return (0);
581: }
582:
583: /*
584: * Set mark to specified position
585: */
1.8 ! noro 586: int set_mark (int pos)
1.1 noro 587: {
588: MarkPosition = pos;
589: return (0);
590: }
591:
592: /*
593: * Delete area from mark to current position to kill buffer
594: */
1.8 ! noro 595: int delete_to_kill_buffer ()
1.1 noro 596: {
597: int n = abs (CurrentPosition - MarkPosition);
598:
599: if (MarkPosition < 0) {
600: errorBell();
601: return (0);
602: }
603:
604: if (CurrentPosition == MarkPosition)
605: return;
606:
607: if (CurrentPosition > MarkPosition) {
608: (void) moveto (MarkPosition);
609: }
610:
611: return (delete_next_n_character (n));
612: }
613:
614: /*
615: * Move to specified position.
616: */
1.8 ! noro 617: void moveto (int position)
1.1 noro 618: {
619: if (position < CurrentPosition)
620: while (position < CurrentPosition)
621: (void) backward_n_character (1);
622: else
623: while (position > CurrentPosition
624: #ifdef KANJI
625: && !(CurrentPosition + 1 == position
626: && iskanji (CommandLine[CurrentPosition]))
627: #endif /* KANJI */
628: )
629: (void) forward_n_character (1);
630: }
631:
632: /*
633: * Move cursor to top of line
634: */
1.8 ! noro 635: int beginning_of_line()
1.1 noro 636: {
637: register int i;
638:
639: for (i = CurrentPosition; i > 0; i--) {
640: if (isctlchar (CommandLine[i]))
641: (void) putchar (BS);
642: (void) putchar (BS);
643: }
644: CurrentPosition = 0;
645: return (0);
646: }
647:
648: #ifdef KANJI
649: #define INC(i) if(iskanji(CommandLine[i])) i+=2; else i++;
650: #define DEC(i) if(i>=2 && iskanji_in_string(CommandLine, i-2)) i-=2; else i--;
651: #else /* KANJI */
652: #define INC(i) i++
653: #define DEC(i) i--
654: #endif /* KANJI */
655:
656: /*
657: * Move cursor to end of line
658: */
1.8 ! noro 659: int end_of_line()
1.1 noro 660: {
661: register int i;
662:
663: for (i = CurrentPosition; CommandLine[i]; i++) {
664: if (isctlchar (CommandLine[i]))
665: (void) putchar (unctl(CommandLine[i]));
666: else
667: (void) putchar (CommandLine[i]);
668: if (isctlchar(CommandLine[i+1]))
669: (void) putchar ('^');
670: }
671: CurrentPosition = i;
672: return (0);
673: }
674:
675: /*
676: * Move cursor left one space
677: */
1.8 ! noro 678: int backward_character()
1.1 noro 679: {
680:
681: return (backward_n_character (1));
682: }
683:
684: /*
685: * Move cursor left "n" space
686: */
1.8 ! noro 687: int backward_n_character(int n)
1.1 noro 688: {
689: int space;
690: int i = CurrentPosition;
691:
692: if (n == 0)
693: return (0);
694: else if (n < 0)
695: return (forward_n_character (-n));
696: else if (n > CurrentPosition) {
697: errorBell ();
698: return (0);
699: }
700:
701: while (n-- && i >= 0) {
702: if (isctlchar (CommandLine[i]))
703: putchar (BS);
704: #ifdef KANJI
705: if (i > 0 && iskanji_in_string (CommandLine, i-2)) {
706: (void) putchar (BS);
707: (void) putchar (BS);
708: i--;
709: }
710: else
711: #endif /* KANJI */
712: putchar (BS);
713: i--;
714: }
715: CurrentPosition = i;
716: return (0);
717: }
718:
719: /*
720: * Move cursor backward one word
721: */
1.8 ! noro 722: int backward_word ()
1.1 noro 723: {
724:
725: return (backward_n_word (1));
726: }
727:
728: /*
729: * Move cursor backward n word
730: */
1.8 ! noro 731: int backward_n_word (int n)
1.1 noro 732: {
733: register int i = CurrentPosition, nchars = 0;
734:
735: if (i == 0) {
736: errorBell ();
737: return (0);
738: }
739:
740: #ifdef KANJI
741: while (n--) {
742: DEC(i);
743: nchars++;
744:
745: while (1) {
746: if (i >= 2 && iskanji_in_string (CommandLine, i-2))
747: break;
748: else if (i > 0 && !iswordchar (CommandLine[i]))
749: i -= 1;
750: else
751: break;
752:
753: nchars++;
754: }
755: while (1) {
756: if (i >= 2 && iskanji_in_string (CommandLine, i - 2))
757: i -= 2;
758: else if (i > 0 && iswordchar (CommandLine [i -1]))
759: i -= 1;
760: else
761: break;
762: nchars++;
763: }
764: }
765: #else /* KANJI */
766: while (n--) {
767: i--, nchars++;
768: while (i > 0 && !iswordchar (CommandLine [i])) {
769: i--, nchars++;
770: }
771: while (i > 0 && iswordchar (CommandLine [i - 1])) {
772: i--, nchars++;
773: }
774: }
775: #endif /* KANJI */
776: return (backward_n_character (nchars));
777: }
778:
779: /*
780: * Move cursor backward one Word
781: */
1.8 ! noro 782: int backward_Word ()
1.1 noro 783: {
784:
785: return (backward_n_Word (1));
786: }
787:
788: /*
789: * Move cursor backward n Word
790: */
1.8 ! noro 791: int backward_n_Word (int n)
1.1 noro 792: {
793: register int i = CurrentPosition, nchars = 0;
794:
795: if (i == 0) {
796: errorBell ();
797: return (0);
798: }
799:
800: #ifdef KANJI
801: while (n--) {
802: DEC(i);
803: nchars++;
804:
805: while (1) {
806: if (i > 1 && iskanji_in_string (CommandLine, i - 2))
807: break;
808: else if (i > 0 && !iswordchar (CommandLine[i]))
809: i -= 1;
810: else
811: break;
812:
813: nchars++;
814: }
815: while (1) {
816: if (i > 2 && iskanji_in_string (CommandLine, i - 2))
817: i -= 2;
818: else if (i > 0 && iswordchar (CommandLine [i - 1]))
819: i -= 1;
820: else
821: break;
822: nchars++;
823: }
824: }
825: #else /* KANJI */
826: while (n--) {
827: i--, nchars++;
828: while (i > 0 && !isWordchar (CommandLine [i]))
829: i--, nchars++;
830: while (i > 0 && isWordchar (CommandLine [i - 1]))
831: i--, nchars++;
832: }
833: #endif /* KANJI */
834: return (backward_n_character (nchars));
835: }
836:
837: /*
838: * Move cursor forward one character
839: */
1.8 ! noro 840: int forward_character()
1.1 noro 841: {
842:
843: return (forward_n_character (1));
844: }
845:
846: /*
847: * Move cursor forward n character
848: */
1.8 ! noro 849: int forward_n_character(int n)
1.1 noro 850: {
851: int space;
852: register int i = CurrentPosition;
853:
854: if (n == 0)
855: return (0);
856: else if (n < 0)
857: return (backward_n_character (-n));
858:
859: if (CommandLine [CurrentPosition] == '\0') {
860: errorBell ();
861: return (0);
862: }
863:
864: #ifdef KANJI
865: if (iskanji (CommandLine[i])) {
866: (void) putchar (CommandLine[i++]);
867: (void) putchar (CommandLine[i++]);
868: }
869: else
870: #endif /* KANJI */
871: if (isctlchar(CommandLine[i])) {
872: (void) putchar (unctl (CommandLine [i]));
873: i++;
874: }
875: else
876: (void) putchar (CommandLine[i++]);
877:
878: while (--n && CommandLine [i]) {
879: #ifdef KANJI
880: if (iskanji (CommandLine[i])) {
881: (void) putchar (CommandLine[i++]);
882: (void) putchar (CommandLine[i++]);
883: }
884: else
885: #endif /* KANJI */
886: putChar (CommandLine [i++]);
887: }
888:
889: if (isctlchar (CommandLine [i]))
890: putchar ('^');
891:
892: CurrentPosition = i;
893:
894: return (0);
895: }
896:
897: /*
898: * Move cursor forward one word
899: */
1.8 ! noro 900: int forward_word ()
1.1 noro 901: {
902: return (forward_n_word (1));
903: }
904:
905: /*
906: * Move cursor forward n word
907: */
1.8 ! noro 908: int forward_n_word (int n)
1.1 noro 909: {
910: register int i = CurrentPosition, nchars = 0;
911:
912: if (CommandLine [i] == '\0') {
913: errorBell ();
914: return (0);
915: }
916:
917: while (n--) {
918: while (CommandLine [i] && iswordchar (CommandLine [i])) {
919: INC(i);
920: nchars++;
921: }
922: while (CommandLine [i] && !iswordchar (CommandLine [i])) {
923: INC(i);
924: nchars++;
925: }
926: }
927: return (forward_n_character (nchars));
928: }
929:
930: /*
931: * Move cursor forward one word
932: */
1.8 ! noro 933: int forward_Word ()
1.1 noro 934: {
935: return (forward_n_Word (1));
936: }
937:
938: /*
939: * Move cursor forward n word
940: */
1.8 ! noro 941: int forward_n_Word (int n)
1.1 noro 942: {
943: register int i = CurrentPosition, nchars = 0;
944:
945: if (CommandLine [i] == '\0') {
946: errorBell ();
947: return (0);
948: }
949:
950: while (n--) {
951: while (CommandLine [i] && isWordchar (CommandLine [i])) {
952: INC(i);
953: nchars++;
954: }
955: while (CommandLine [i] && !isWordchar (CommandLine [i])) {
956: INC(i);
957: nchars++;
958: }
959: }
960: return (forward_n_character (nchars));
961: }
962:
963: /*
964: * Forward to end of word
965: */
1.8 ! noro 966: int forward_to_end_of_word ()
1.1 noro 967: {
968:
969: return (forward_to_end_of_n_word (1));
970: }
971:
972: /*
973: * Forward to end of n word
974: */
1.8 ! noro 975: int forward_to_end_of_n_word (int n)
1.1 noro 976: {
977: register int i = CurrentPosition, nchars = 0;
978:
979: if (CommandLine [i] == '\0') {
980: errorBell ();
981: return (0);
982: }
983:
984: INC(i);
985: while (n--) {
986: while (CommandLine [i] && !iswordchar (CommandLine [i])) {
987: INC(i);
988: nchars++;
989: }
990: while (CommandLine [i] && iswordchar (CommandLine [i])) {
991: INC(i);
992: nchars++;
993: }
994: }
995: DEC(i);
996: return (forward_n_character (nchars));
997: }
998:
999: /*
1000: * Forward to end of word
1001: */
1.8 ! noro 1002: int forward_to_end_of_Word ()
1.1 noro 1003: {
1004:
1005: return (forward_to_end_of_n_Word (1));
1006: }
1007:
1008: /*
1009: * Forward to end of n word
1010: */
1.8 ! noro 1011: int forward_to_end_of_n_Word (int n)
1.1 noro 1012: {
1013: register int i = CurrentPosition, nchars = 0;
1014:
1015: if (CommandLine [i] == '\0') {
1016: errorBell ();
1017: return (0);
1018: }
1019:
1020: INC(i);
1021: while (n--) {
1022: while (CommandLine [i] && !isWordchar (CommandLine [i])) {
1023: INC(i);
1024: nchars++;
1025: }
1026: while (CommandLine [i] && isWordchar (CommandLine [i])) {
1027: INC(i);
1028: nchars++;
1029: }
1030: }
1031: DEC(i);
1032: return (forward_n_character (nchars));
1033: }
1034:
1035: /*
1036: * Delete previous one character
1037: */
1.8 ! noro 1038: int delete_previous_character()
1.1 noro 1039: {
1040:
1041: return (delete_previous_n_character (1));
1042: }
1043:
1044: /*
1045: * Delete previous n characters
1046: */
1.8 ! noro 1047: int delete_previous_n_character(int n)
1.1 noro 1048: {
1049: register int i, nbyte;
1050: int deleteArea, restArea;
1051:
1052: if (CurrentPosition < n) {
1053: errorBell ();
1054: return (0);
1055: }
1056:
1057: #ifdef KANJI
1058: for (nbyte = 0, i = CurrentPosition; n-- > 0 && i;)
1059: if (i > 1 && iskanji_in_string (CommandLine, i - 2))
1060: i -= 2, nbyte += 2;
1061: else
1062: i -= 1, nbyte += 1;
1063: #else /* KANJI */
1064: nbyte = n;
1065: #endif /* KANJI */
1066:
1067: deleteArea = howlong (&CommandLine[CurrentPosition - nbyte], nbyte);
1068: restArea = howlong (&CommandLine[CurrentPosition], 0);
1069: if (isctlchar(CommandLine[CurrentPosition]))
1070: (void) putchar (BS);
1071: repeat(BS, deleteArea);
1072: CurrentPosition -= nbyte;
1073: strcpy (KillBuffer, &CommandLine [CurrentPosition]);
1074: KillBuffer [nbyte] = '\0';
1075: for (i = CurrentPosition; CommandLine[i + nbyte]; i++) {
1076: CommandLine[i] = CommandLine[i + nbyte];
1077: putChar (CommandLine[i]);
1078: }
1079: CommandLine[i] = '\0';
1080: repeat(SP, deleteArea);
1081: repeat(BS, deleteArea);
1082: if (isctlchar (CommandLine[CurrentPosition]))
1083: repeat(BS, restArea - 1);
1084: else
1085: repeat(BS, restArea);
1086:
1087: return (0);
1088: }
1089:
1090: /*
1091: * Delete previous one word
1092: */
1.8 ! noro 1093: int delete_previous_word()
1.1 noro 1094: {
1095:
1096: return (delete_previous_n_word (1));
1097: }
1098:
1099: /*
1100: * Delete previous n word
1101: */
1.8 ! noro 1102: int delete_previous_n_word(int n)
1.1 noro 1103: {
1104: register int i = CurrentPosition, nchars = 0;
1105:
1106: if (i == 0) {
1107: errorBell();
1108: return (0);
1109: }
1110:
1111: #ifdef KANJI
1112: while (n--) {
1113: if (i>1 && iskanji_in_string (CommandLine, i-2))
1114: i--;
1115: i--, nchars++;
1116:
1117: while (1) {
1118: if (i > 1 && iskanji_in_string (CommandLine, i-2))
1119: break;
1120: else if (i > 0 && !iswordchar (CommandLine[i]))
1121: i -= 1;
1122: else
1123: break;
1124:
1125: nchars++;
1126: }
1127: while (1) {
1128: if (i > 2 && iskanji_in_string (CommandLine, i - 2))
1129: i -= 2;
1130: else if (i > 0 && iswordchar (CommandLine [i -1]))
1131: i -= 1;
1132: else
1133: break;
1134: nchars++;
1135: }
1136: }
1137: #else /* KANJI */
1138: while (n--) {
1139: i--, nchars++;
1140: while (i > 0 && !iswordchar (CommandLine [i]))
1141: i--, nchars++;
1142: while (i > 0 && iswordchar (CommandLine [i - 1]))
1143: i--, nchars++;
1144: }
1145: #endif /* KANJI */
1146:
1147: return (delete_previous_n_character (nchars));
1148: }
1149:
1150: /*
1151: * Delete previous one word
1152: */
1.8 ! noro 1153: int delete_previous_Word()
1.1 noro 1154: {
1155:
1156: return (delete_previous_n_Word (1));
1157: }
1158:
1159: /*
1160: * Delete previous n word
1161: */
1.8 ! noro 1162: int delete_previous_n_Word(int n)
1.1 noro 1163: {
1164: register int i = CurrentPosition, nchars = 0;
1165:
1166: if (i == 0) {
1167: errorBell();
1168: return (0);
1169: }
1170:
1171: #ifdef KANJI
1172: while (n--) {
1173: if (i>1 && iskanji_in_string (CommandLine, i-2))
1174: i--;
1175: i--, nchars++;
1176:
1177: while (1) {
1178: if (i > 1 && iskanji_in_string (CommandLine, i-2))
1179: break;
1180: else if (i > 0 && !isWordchar (CommandLine[i]))
1181: i -= 1;
1182: else
1183: break;
1184:
1185: nchars++;
1186: }
1187: while (1) {
1188: if (i > 2 && iskanji_in_string (CommandLine, i - 2))
1189: i -= 2;
1190: else if (i > 0 && isWordchar (CommandLine [i -1]))
1191: i -= 1;
1192: else
1193: break;
1194: nchars++;
1195: }
1196: }
1197: #else /* KANJI */
1198: while (n--) {
1199: i--, nchars++;
1200: while (i > 0 && !isWordchar (CommandLine [i]))
1201: i--, nchars++;
1202: while (i > 0 && isWordchar (CommandLine [i - 1]))
1203: i--, nchars++;
1204: }
1205: #endif /* KANJI */
1206:
1207: return (delete_previous_n_character (nchars));
1208: }
1209:
1210: /*
1211: * Delete next one character
1212: */
1.8 ! noro 1213: int delete_next_character ()
1.1 noro 1214: {
1215:
1216: return (delete_next_n_character (1));
1217: }
1218:
1219: /*
1220: * Delete next n character
1221: */
1.8 ! noro 1222: int delete_next_n_character (int n)
1.1 noro 1223: {
1224: register int i, nbyte;
1225: int deleteArea, restArea;
1226:
1227: if (strlen (&CommandLine [CurrentPosition]) < n) {
1228: errorBell ();
1229: return (0);
1230: }
1231:
1232: #ifdef KANJI
1233: {
1234: register CHAR *cp = &CommandLine[CurrentPosition];
1235:
1236: nbyte = 0;
1237: while (n-- > 0 && *cp)
1238: if (iskanji (*cp))
1239: cp += 2, nbyte += 2;
1240: else
1241: cp++, nbyte++;
1242: }
1243: #else /* KANJI */
1244: nbyte = n;
1245: #endif /* KANJI */
1246:
1247: deleteArea = howlong (&CommandLine[CurrentPosition], nbyte);
1248: restArea = howlong (&CommandLine[CurrentPosition + nbyte], 0);
1249: if (isctlchar(CommandLine[CurrentPosition]))
1250: (void) putchar (BS);
1251: strcpy (KillBuffer, CommandLine + CurrentPosition);
1252: KillBuffer [nbyte] = '\0';
1253: for (i = CurrentPosition; CommandLine[i + nbyte]; i++) {
1254: CommandLine[i] = CommandLine[i + nbyte];
1255: putChar (CommandLine[i]);
1256: }
1257: CommandLine[i] = '\0';
1258: repeat(SP, deleteArea);
1259: repeat(BS, deleteArea);
1260: if (isctlchar (CommandLine[CurrentPosition]))
1261: repeat(BS, restArea - 1);
1262: else
1263: repeat(BS, restArea);
1264:
1265: return (0);
1266: }
1267:
1268: /*
1269: * Delete next one word
1270: */
1.8 ! noro 1271: int delete_next_word ()
1.1 noro 1272: {
1273: return (delete_next_n_word (1));
1274: }
1275:
1276: /*
1277: * Delete next n word
1278: */
1.8 ! noro 1279: int delete_next_n_word (int n)
1.1 noro 1280: {
1281: register int i = CurrentPosition, nchars = 0;
1282:
1283: if (CommandLine [i] == '\0') {
1284: errorBell ();
1285: return (0);
1286: }
1287:
1288: while (n--) {
1289: while (CommandLine [i] && iswordchar (CommandLine [i])) {
1290: INC(i);
1291: nchars++;
1292: }
1293: while (CommandLine [i] && !iswordchar (CommandLine [i])) {
1294: INC(i);
1295: nchars++;
1296: }
1297: }
1298: return (delete_next_n_character (nchars));
1299: }
1300:
1301: /*
1302: * Delete next one word
1303: */
1.8 ! noro 1304: int delete_next_Word ()
1.1 noro 1305: {
1306: return (delete_next_n_Word (1));
1307: }
1308:
1309: /*
1310: * Delete next n word
1311: */
1.8 ! noro 1312: int delete_next_n_Word (int n)
1.1 noro 1313: {
1314: register int i = CurrentPosition, nchars = 0;
1315:
1316: if (CommandLine [i] == '\0') {
1317: errorBell ();
1318: return (0);
1319: }
1320:
1321: while (n--) {
1322: while (CommandLine [i] && isWordchar (CommandLine [i])) {
1323: INC(i);
1324: nchars++;
1325: }
1326: while (CommandLine [i] && !isWordchar (CommandLine [i])) {
1327: INC(i);
1328: nchars++;
1329: }
1330: }
1331: return (delete_next_n_character (nchars));
1332: }
1333:
1334: /*
1335: * Erase whole line
1336: */
1.8 ! noro 1337: int delete_line()
1.1 noro 1338: {
1339: register int i = CurrentPosition;
1340: register int len;
1341:
1342: len = howlong (CommandLine, 0);
1343:
1344: /*
1345: * If cursor is there right part of line, move it to end of line
1346: * and erase character by character from end
1347: */
1348: if (howlong (CommandLine, CurrentPosition + 1) > len / 2) {
1349: (void) end_of_line ();
1350: repeat_string ("\b \b", len);
1351: }
1352: /*
1353: * If cursor is there on left part of line, move it to top of line
1354: * and erase line at once
1355: */
1356: else {
1357: (void) beginning_of_line ();
1358: if (isctlchar (CommandLine[0]))
1359: putchar (BS);
1360: repeat (SP, len);
1361: repeat (BS, len);
1362: }
1363: strcpy (KillBuffer, CommandLine);
1364: CurrentPosition = 0;
1365: CommandLine [0] = '\0';
1366: return (0);
1367: }
1368:
1369: /*
1370: * Delete characters from current position to top of line
1371: */
1.8 ! noro 1372: int kill_to_top_of_line()
1.1 noro 1373: {
1374: int i = CurrentPosition;
1375:
1376: (void) beginning_of_line();
1377: return (delete_next_n_character (i));
1378: }
1379:
1380: /*
1381: * Delete characters from current position to end of line
1382: */
1.8 ! noro 1383: int kill_to_end_of_line()
1.1 noro 1384: {
1385: register int i, backCnt = 0;
1386:
1387: if (isctlchar(CommandLine[CurrentPosition])) {
1388: (void) putchar(BS);
1389: }
1390: for (i = CurrentPosition; CommandLine[i]; i++) {
1391: if (isctlchar(CommandLine[i])) {
1392: fputs(" ", stdout);
1393: backCnt++;
1394: }
1395: else
1396: (void) putchar (SP);
1397: backCnt++;
1398: }
1399: for (; backCnt; backCnt--)
1400: (void) putchar (BS);
1401: strcpy (KillBuffer, CommandLine + CurrentPosition);
1402: CommandLine[CurrentPosition] = '\0';
1403: return (0);
1404: }
1405:
1406: /*
1407: * Insert tab to current cursor position
1408: */
1.8 ! noro 1409: int insert_tab()
1.1 noro 1410: {
1411:
1412: /* sorry, not implemented */
1413: return (self_insert ('\t'));
1414: }
1415:
1416: /*
1417: * Process new line
1418: */
1.8 ! noro 1419: int new_line()
1.1 noro 1420: {
1421:
1422: (void) end_of_line;
1423: fputs ("\r\n", stdout);
1424: NeedNewLine = 1;
1425: NeedSave = 1;
1426:
1427: return (1);
1428: }
1429:
1430: /*
1431: * Check current position is top-of-line
1432: */
1.8 ! noro 1433: int is_tol()
1.1 noro 1434: {
1435: return (CurrentPosition == 0);
1436: }
1437:
1438: /*
1439: * Check current position is end-of-line
1440: */
1.8 ! noro 1441: int is_eol()
1.1 noro 1442: {
1443: return (CommandLine [CurrentPosition] == '\0');
1444: }
1445:
1446: /*
1447: * Check command line if it refer history or not
1448: */
1.8 ! noro 1449: int refer_history()
1.1 noro 1450: {
1451: char *historyExtract ();
1452: char *his;
1453:
1454: if (CommandLine[0] != '!')
1455: return (NOT_PROCESSED);
1456:
1457: if (his = historyExtract (CommandLine)) {
1458: (void) strcpy (CommandLine, his);
1459: CurrentPosition = strlen (CommandLine);
1460: }
1461: else {
1462: fputs (CommandLine, stdout);
1463: fputs (" : Event not found.\r\n", stdout);
1464: (void) strcpy (CommandLine, "");
1465: CurrentPosition = 0;
1466: }
1467: fputs (prompt, stdout);
1468: print_com_line ();
1469: return (PROCESSED);
1470: }
1471:
1472: #define FORWARD 1
1473: #define REVERSE 2
1474:
1.8 ! noro 1475: int search_reverse ()
1.1 noro 1476: {
1477: return (search_history (REVERSE));
1478: }
1479:
1.8 ! noro 1480: int search_forward ()
1.1 noro 1481: {
1482: return (search_history (FORWARD));
1483: }
1484:
1.8 ! noro 1485: int search_history (int direct)
1.1 noro 1486: {
1487: char *his, *search_reverse_history(), *search_forward_history();
1488: char *(*func)();
1489:
1490: if (direct == FORWARD)
1491: func = search_forward_history;
1492: else
1493: func = search_reverse_history;
1494:
1495: AGAIN:
1496: if (his = (*func) (0)) {
1497: if (eq (his, CommandLine))
1498: goto AGAIN;
1499:
1500: (void) delete_line ();
1501: (void) insert_string (his);
1502: CurrentPosition = strlen (CommandLine);
1503: }
1504: else {
1505: (void) errorBell ();
1506:
1507: if (look_var ("verbose")) {
1508: char *cp;
1509:
1510: if ((cp = look_var ("search-string")) == NULL)
1511: cp = "";
1512: (void) clear_edit_line ();
1513: fprintf (stdout, "\"%s\": No match.\r\n", cp);
1514: (void) recover_edit_line (1);
1515: }
1516: }
1517:
1518: return 0;
1519: }
1520:
1521:
1522: /*
1523: * Insert the character and flush buffer
1524: */
1.8 ! noro 1525: int insert_and_flush(char c)
1.1 noro 1526: {
1527: (void) self_insert (c);
1528: return (1);
1529: }
1530:
1531: /*
1532: * Insert the character, but it means EOL. Therefore move cursor backward and
1533: * flush buffer
1534: */
1.8 ! noro 1535: int send_eof()
1.1 noro 1536: {
1537: #ifdef TERMIOS
1538: char c = initial_ttymode.c_cc[VEOF];
1539: #else
1540: char c = tchars_buf.t_eofc;
1541: #endif
1542:
1543: (void) self_insert (c);
1544: if (isctlchar (c))
1545: fputs ("\b\b", stdout);
1546: else
1547: fputs ("\b", stdout);
1548: return (1);
1549: }
1550:
1551: /*
1552: * Alarm for EOF on only the first time finding eof character
1553: */
1.8 ! noro 1554: int alarm_on_eof ()
1.1 noro 1555: {
1556:
1557: errorBell ();
1558: (void) clear_edit_line ();
1559: printf ("EOF -- one more eof character to send eof to the process.\n");
1560: (void) recover_edit_line (1);
1561: }
1562:
1563: /*
1564: * Clear screen
1565: */
1.8 ! noro 1566: int clear_screen()
1.1 noro 1567: {
1568:
1569: if (term_clear) {
1570: (void) clear_edit_line ();
1571: fputs (term_clear, stdout);
1572: (void) recover_edit_line (1);
1573: }
1574: else
1575: errorBell ();
1576:
1577: return (0);
1578: }
1579:
1580: typedef enum {HOP_INSERT, HOP_REPLACE} HISTOP;
1581: typedef enum {HDIR_PREV, HDIR_CURRENT, HDIR_NEXT} HISTDIR;
1582:
1.8 ! noro 1583: int serv_history(HISTOP op, HISTDIR dir);
! 1584:
1.1 noro 1585: /*
1586: * Get next history entry
1587: */
1.8 ! noro 1588: int next_history()
1.1 noro 1589: {
1590: return (serv_history (HOP_REPLACE, HDIR_NEXT));
1591: }
1592:
1593: /*
1594: * Get next history entry
1595: */
1.8 ! noro 1596: int previous_history()
1.1 noro 1597: {
1598: return (serv_history (HOP_REPLACE, HDIR_PREV));
1599: }
1600:
1601: /*
1602: * Insert next history entry
1603: */
1.8 ! noro 1604: int insert_current_history()
1.1 noro 1605: {
1606: return (serv_history (HOP_INSERT, HDIR_CURRENT));
1607: }
1608:
1609: /*
1610: * Insert next history entry
1611: */
1.8 ! noro 1612: int insert_next_history()
1.1 noro 1613: {
1614: return (serv_history (HOP_INSERT, HDIR_NEXT));
1615: }
1616:
1617: /*
1618: * Insert next history entry
1619: */
1.8 ! noro 1620: int insert_previous_history()
1.1 noro 1621: {
1622: return (serv_history (HOP_INSERT, HDIR_PREV));
1623: }
1624:
1625: /*
1626: * Get previous history
1627: */
1.8 ! noro 1628: int serv_history(HISTOP op, HISTDIR dir)
1.1 noro 1629: {
1630: register char *cp;
1631: char *getPreviousHistory (), *getNextHistory (), *getCurrentHistory ();
1632: int diff;
1633:
1634: switch (dir) {
1635: case HDIR_PREV: cp = getPreviousHistory (); break;
1636: case HDIR_NEXT: cp = getNextHistory (); break;
1637: case HDIR_CURRENT: cp = getCurrentHistory (); break;
1638: default: cp = (char*)0;
1639: }
1640:
1641: if (cp == (char *)0) {
1642: errorBell ();
1643: return (0);
1644: }
1645:
1646: if (op == HOP_REPLACE)
1647: (void) delete_line ();
1648: (void) insert_string (cp);
1649: return (0);
1650: }
1651:
1652: /*
1653: * Show history
1654: */
1.8 ! noro 1655: void show_history()
1.1 noro 1656: {
1657:
1658: (void) clear_edit_line ();
1659: hist_showHistory (lookd_var ("showhist"));
1660: (void) recover_edit_line (1);
1661: }
1662:
1663: /*
1664: * Do nothing
1665: */
1.8 ! noro 1666: int ignore()
1.1 noro 1667: {
1668: return(0);
1669: }
1670:
1671: /*
1672: * Next character is literal
1673: */
1.8 ! noro 1674: int literal_next()
1.1 noro 1675: {
1676:
1677: return (self_insert (getcharacter ()));
1678: }
1679:
1680: /*
1681: * Reprint command line
1682: */
1.8 ! noro 1683: int reprint()
1.1 noro 1684: {
1685:
1686: (void) clear_edit_line ();
1687: (void) recover_edit_line (1);
1688: return (0);
1689: }
1690:
1691: /*
1692: * Print whole command line and move cursor to the current position
1693: */
1.8 ! noro 1694: void print_com_line()
1.1 noro 1695: {
1696:
1697: printS (CommandLine);
1698: if (CommandLine[CurrentPosition] != '\0') {
1699: repeat (BS, howlong(&CommandLine[CurrentPosition + 1], 0));
1700: (void) putchar (BS);
1701: }
1702: }
1703:
1704: /*
1705: * Calcurate space of string using "^" for control character
1706: */
1.8 ! noro 1707: int howlong(char *s, int n)
1.1 noro 1708: {
1709: register char *sp;
1710: register int area = 0;
1711:
1712: if (n == 0)
1713: n = -1;
1714: for (sp = s; *sp && n; sp++, n--) {
1715: if (isctlchar(*sp))
1716: area += 2;
1717: else
1718: area += 1;
1719: }
1720: return (area);
1721: }
1722:
1723: /*
1724: * Repeat puting character n times
1725: */
1.8 ! noro 1726: void repeat(char c, int n)
1.1 noro 1727: {
1728: for (n = n; n; n--)
1729: (void) putchar(c);
1730: }
1731:
1732: /*
1733: * Repeat putting string n times
1734: */
1.8 ! noro 1735: void repeat_string(char *s, int n)
1.1 noro 1736: {
1737: for (n = n; n; n--)
1738: fputs(s, stdout);
1739: }
1740:
1741: /*
1742: * Expand file name
1743: */
1.8 ! noro 1744: int expand_file_name ()
1.1 noro 1745: {
1746: CHAR *cp, *start_expand;
1747: char *x_dirname();
1748: char dir[256];
1749: char *fileList[256];
1750: CHAR line[256];
1751: DIR *dirp, *x_opendir();
1752: struct direct *dp;
1753: int found = 0;
1754: int i;
1755: int tilde_expanded = 0;
1.7 fujimoto 1756: #if !defined(ANDROID)
1.1 noro 1757: CHAR *index(), *rindex();
1.7 fujimoto 1758: #endif
1.1 noro 1759:
1760: if (delimiters == NULL)
1761: delimiters = DEFAULT_DELIMITERS;
1762: strcpy (line, CommandLine);
1763: for (cp = &line[CurrentPosition] - 1; cp > line ; --cp) {
1764: if (index (delimiters, *(cp - 1)))
1765: break;
1766: }
1767: start_expand = cp;
1768: if (any ('/', cp)) {
1769: (void) strcpy (dir, cp);
1770: *(rindex (dir, '/') + 1) = '\0';
1771: cp = (CHAR *) (rindex (cp, '/') + 1);
1772: }
1773: else
1774: strcpy (dir, ".");
1775:
1776: if ((dirp = x_opendir (dir)) == NULL) {
1777: errorBell ();
1778: return (0);
1779: }
1780:
1781: for (dp = readdir(dirp), i = 0; dp != NULL; dp = readdir(dirp)) {
1782:
1783: if (*cp == '\0')
1784: break;
1785:
1786: if (*cp != '.' && *(dp->d_name) == '.')
1787: continue;
1788:
1789: if (prefix (cp, dp->d_name)) {
1790: char *fcp;
1791:
1792: # ifdef ALLOCA
1793: fcp = (char *) alloca (strlen (dp->d_name) + 1);
1794: # else /* ALLOCA */
1795: fcp = (char *) malloc (strlen (dp->d_name) + 1);
1796: # endif /* ALLOCA */
1797: if (fcp == 0) {
1798: fputs ("\r\n", stdout);
1799: perror ("alloca:");
1800: reprint ();
1801: longjmp (jbuf, 1);
1802: }
1803: strcpy (fcp, dp->d_name);
1804: fileList [i++] = fcp;
1805: }
1806: }
1807: fileList [i] = (char *) 0;
1808:
1809: if (*start_expand == '~' && look_var ("expand-tilde")) {
1810: char buf [256], *p;
1811:
1812: strcpy (buf, start_expand);
1813: p = x_dirname (buf);
1814: if (!eq (p, buf)) {
1815: (void) moveto (start_expand - line);
1816: (void) kill_to_end_of_line ();
1817: (void) insert_string (x_dirname (buf));
1818: tilde_expanded = 1;
1819: }
1820: }
1821:
1822: switch (i) {
1823:
1824: case 0:
1825: if (tilde_expanded == 0)
1826: errorBell ();
1827: break;
1828:
1829: case 1:
1830: (void) end_of_line ();
1831: (void) insert_string (fileList[0] + strlen (cp));
1832: break;
1833:
1834: default:
1835: {
1836: char *one, *other;
1837: char *c1, *c2;
1838: int i;
1839:
1840: one = fileList [0];
1841: for (i = 1; other = fileList [i]; i++) {
1842: for (c1 = one, c2 = other; *c1 && *c2; c1++, c2++)
1843: if (*c1 != *c2)
1844: break;
1845: *c1 = '\0';
1846: }
1847: errorBell ();
1848: (void) end_of_line ();
1849: (void) insert_string (fileList[0] + strlen (cp));
1850: }
1851: break;
1852: }
1853:
1854: # ifndef ALLOCA
1855: for (i = 0; fileList [i]; i++)
1856: free (fileList [i]);
1857: # endif /* ALLOCA */
1858:
1859: closedir(dirp);
1860: return (0);
1861: }
1862:
1863: /*
1864: * List file name
1865: */
1.8 ! noro 1866: int list_file_name ()
1.1 noro 1867: {
1868: CHAR *cp;
1869: char dir[256];
1870: DIR *dirp, *x_opendir();
1.7 fujimoto 1871: #if !defined(ANDROID)
1.1 noro 1872: CHAR *index(), *rindex();
1.7 fujimoto 1873: #endif
1.1 noro 1874:
1875: if (delimiters == NULL)
1876: delimiters = DEFAULT_DELIMITERS;
1877: for (cp = (CHAR *) index (CommandLine, '\0'); cp > CommandLine ; --cp) {
1878: if (index (delimiters, *(cp - 1))) {
1879: break;
1880: }
1881: }
1882: #ifdef RINFO
1883: /*
1884: * This is an experimental code for rinfod, which serves remote
1885: * information about file, process, etc.
1886: */
1887: if (any (':', cp)) {
1888: char *host, *pattern;
1889:
1890: (void) strcpy (dir, cp);
1891: host = dir;
1892: *(index (host, ':')) = '\0';
1893: pattern = (index (cp, ':') + 1);;
1894:
1895: (void) clear_edit_line();
1896: list_remote_file (host, pattern);
1897: (void) recover_edit_line (1);
1898: return;
1899: }
1900: #endif
1901: if (any ('/', cp)) {
1902: (void) strcpy (dir, cp);
1903: *(rindex (dir, '/') + 1) = '\0';
1904: cp = (CHAR *) (rindex (cp, '/') + 1);
1905: }
1906: else
1907: strcpy (dir, ".");
1908:
1909:
1910: if ((dirp = x_opendir (dir)) == NULL) {
1911: errorBell ();
1912: return (0);
1913: }
1914:
1915: (void) clear_edit_line();
1916: ls (dirp, cp);
1917: closedir(dirp);
1918: (void) recover_edit_line (1);
1919:
1920: return (0);
1921: }
1922:
1923: int rememberPosition;
1924:
1.8 ! noro 1925: void clear_edit_line ()
1.1 noro 1926: {
1927:
1928: if (editstatus == NOTEDITING)
1929: return;
1930:
1931: rememberPosition = CurrentPosition;
1932: (void) end_of_line ();
1933: (void) fputs ("\r\n", stdout);
1934: }
1935:
1.8 ! noro 1936: void recover_edit_line (int put_prompt)
1.1 noro 1937: {
1938:
1939: if (editstatus == NOTEDITING)
1940: return;
1941:
1942: if (rememberPosition < 0)
1943: return;
1944: CurrentPosition = rememberPosition;
1945: rememberPosition = -1;
1946: if (put_prompt && prompt)
1947: fputs (prompt, stdout);
1948: (void) print_com_line();
1949: }
1950:
1951: #define MAXFILES 256
1952:
1953: /*
1954: * Do ls
1955: */
1.8 ! noro 1956: void ls (DIR *dirp, char *prefixstring)
1.1 noro 1957: {
1958: struct direct *dp;
1959: char *fileList[MAXFILES + 1];
1960: int i, j;
1961: int maxlen = 0;
1962: int files; /* number of file */
1963: int fpl; /* file par line */
1964: int cpf; /* column par file */
1965: int fpc; /* file par column */
1966: int COL = 80;
1967: char format[10];
1968: int scmp();
1969:
1970: for (dp = readdir(dirp), i = 0; dp != NULL; dp = readdir(dirp)) {
1971: char *fcp;
1972:
1973: if (i >= MAXFILES) {
1974: printf ("Too many files\n");
1975: break;
1976: }
1977:
1978: if (dp->d_ino == (unsigned long) 0
1979: || (prefixstring[0] != '.' && dp->d_name[0] == '.'))
1980: continue;
1981: if (prefix (prefixstring, dp->d_name)) {
1982: # ifdef ALLOCA
1983: fcp = (char *) alloca (strlen (dp->d_name) + 1);
1984: # else /* ALLOCA */
1985: fcp = (char *) malloc (strlen (dp->d_name) + 1);
1986: # endif /* ALLOCA */
1987: if (fcp == 0) {
1988: fputs ("\r\n", stdout);
1989: perror ("alloca:");
1990: reprint ();
1991: longjmp (jbuf, 1);
1992: }
1993: strcpy (fcp, dp->d_name);
1994: fileList [i++] = fcp;
1995: maxlen = max (maxlen, strlen (dp->d_name));
1996: }
1997: }
1998: fileList [i] = (char *) 0;
1999:
2000: if (i == 0)
2001: goto BACK;
2002:
2003: files = i;
2004:
2005: qsort (fileList, i, sizeof (char *), scmp);
2006:
2007: if (debug)
2008: printf ("%d files\n", files);
2009:
2010: cpf = maxlen + 1;
2011: fpl = COL / cpf;
2012: if (fpl == 0) fpl = 1;
2013: fpc = (files + fpl - 1) / fpl;
2014:
2015: sprintf (format, "%%-%ds", cpf);
2016: for (i = 0; i < fpc; i++) {
2017: for (j = 0; j < fpl - 1; j++)
2018: if (i + j * fpc < files)
2019: printf (format, fileList[i + (j * fpc)]);
2020: if (i + (fpc * (fpl - 1)) < files)
2021: printf ("%s", fileList[i + (fpc * (fpl - 1))]);
2022: fputs ("\n", stdout);
2023: }
2024:
2025: BACK:
2026:
2027: # ifndef ALLOCA
2028: for (i = 0; fileList [i]; i++)
2029: free (fileList [i]);
2030: # endif /* ALLOCA */
2031: return;
2032: }
2033:
2034: #ifdef RINFO
2035:
2036: #include "../rinfo/rinfo.h"
2037:
1.8 ! noro 2038: void list_remote_file (char *host, char *pattern)
1.1 noro 2039: {
2040: struct slist *slp, *getfilelist();
2041: int i, j;
2042: char format [64];
2043: int COL = 80;
2044: int maxlen, cpf, fpl, fpc;
2045: int files;
2046:
2047: slp = getfilelist (host, pattern);
2048: files = slp->s_cnt;
2049:
2050: COL = 80;
2051: maxlen = 0;
2052: for (i = 0; i < files; i++) {
2053: int len;
2054:
2055: if ((len = strlen (*(slp->s_list + i))) > maxlen)
2056: maxlen = len;
2057: }
2058:
2059: cpf = maxlen + 1;
2060: fpl = COL / cpf;
2061: if (fpl == 0)
2062: fpl = 1;
2063: fpc = (files + fpl - 1) / fpl;
2064:
2065: sprintf (format, "%%-%ds", cpf);
2066: for (i = 0; i < fpc; i++) {
2067: for (j = 0; j < fpl - 1; j++) {
2068: if (i + j * fpc < slp->s_cnt)
2069: printf (format, *(slp->s_list + (i + (j * fpc))));
2070: }
2071: if (i + (fpc * (fpl - 1)) < files)
2072: printf ("%s", slp->s_list[i + (fpc * (fpl - 1))]);
2073: fputs ("\n", stdout);
2074: }
2075: }
2076: #endif /* RINFO */
2077:
1.8 ! noro 2078: /*
! 2079: FUNC ft[]; Function table
! 2080: FUNC func; Function to be binded
! 2081: char *s; String to bind
! 2082: FUNC dfunc; Default function for table allocating
! 2083: */
! 2084:
! 2085: int bind_key (FUNC ft[], FUNC func, char *s, FUNC dfunc)
1.1 noro 2086: {
2087: char tmps[16];
2088:
2089: if (s[0] == '\\' && s[1] == '^' && s[2] != '\0') {
2090: tmps[0] = toctrl (s[2]);
2091: strcpy (&tmps[1], &s[3]);
2092: s = tmps;
2093: }
2094:
2095: /*
2096: * If the string contain only one character, put the function to
2097: * appropriate position in the table.
2098: */
2099: if (*(s+1) == '\0') {
2100: if (isIndirect (ft[(int) *s]))
2101: free (maskIndirect (ft[(int) *s]));
2102:
2103: ft[(int) *s] = func;
2104: return (1);
2105: }
2106: else {
2107: FUNC *nft = (FUNC *) 0;
2108: int status;
2109:
2110: /*
2111: * If the entry doesn't have indirect function table, allocate it.
2112: */
2113: if (! (isIndirect (ft[(int) *s]))) {
2114: register int i;
2115:
2116: nft = (FUNC *) calloc (sizeof (FUNC), 256);
2117: /*
2118: * If failed in allocating, return 0.
2119: */
2120: if (nft == 0)
2121: return (0);
2122:
2123: /*
2124: * Initialize the table with default function
2125: */
2126: for (i = 0; i < 256; i++)
2127: nft [i] = dfunc;
2128: ft[(int) *s] = setIndirect (nft);
2129: }
2130:
2131: status = bind_key (maskIndirect (ft[(int) *s]), func, s+1, dfunc);
2132: /*
2133: * If the binding failed and the table was allocated in this function
2134: * free the table and return with same status.
2135: */
2136: if (status == 0 && nft)
2137: free (nft);
2138: return (status);
2139: }
2140: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>