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