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