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