1*2718b568SThomas Cort /* $NetBSD: emacs.c,v 1.32 2009/04/25 05:11:37 lukem Exp $ */
2*2718b568SThomas Cort
3*2718b568SThomas Cort /*
4*2718b568SThomas Cort * Emacs-like command line editing and history
5*2718b568SThomas Cort *
6*2718b568SThomas Cort * created by Ron Natalie at BRL
7*2718b568SThomas Cort * modified by Doug Kingston, Doug Gwyn, and Lou Salkind
8*2718b568SThomas Cort * adapted to PD ksh by Eric Gisin
9*2718b568SThomas Cort */
10*2718b568SThomas Cort #include <sys/cdefs.h>
11*2718b568SThomas Cort
12*2718b568SThomas Cort #ifndef lint
13*2718b568SThomas Cort __RCSID("$NetBSD: emacs.c,v 1.32 2009/04/25 05:11:37 lukem Exp $");
14*2718b568SThomas Cort #endif
15*2718b568SThomas Cort
16*2718b568SThomas Cort
17*2718b568SThomas Cort #include "config.h"
18*2718b568SThomas Cort #ifdef EMACS
19*2718b568SThomas Cort
20*2718b568SThomas Cort #include "sh.h"
21*2718b568SThomas Cort #include "ksh_stat.h"
22*2718b568SThomas Cort #include "ksh_dir.h"
23*2718b568SThomas Cort #include <ctype.h>
24*2718b568SThomas Cort #include <locale.h>
25*2718b568SThomas Cort #include "edit.h"
26*2718b568SThomas Cort
27*2718b568SThomas Cort static Area aedit;
28*2718b568SThomas Cort #define AEDIT &aedit /* area for kill ring and macro defns */
29*2718b568SThomas Cort
30*2718b568SThomas Cort #undef CTRL /* _BSD brain damage */
31*2718b568SThomas Cort #define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */
32*2718b568SThomas Cort #define UNCTRL(x) ((x) == 0x7F ? '?' : (x) | 0x40) /* ASCII */
33*2718b568SThomas Cort #define META(x) ((x) & 0x7f)
34*2718b568SThomas Cort #define ISMETA(x) (Flag(FEMACSUSEMETA) && ((x) & 0x80))
35*2718b568SThomas Cort
36*2718b568SThomas Cort
37*2718b568SThomas Cort /* values returned by keyboard functions */
38*2718b568SThomas Cort #define KSTD 0
39*2718b568SThomas Cort #define KEOL 1 /* ^M, ^J */
40*2718b568SThomas Cort #define KINTR 2 /* ^G, ^C */
41*2718b568SThomas Cort
42*2718b568SThomas Cort struct x_ftab {
43*2718b568SThomas Cort int (*xf_func) ARGS((int c));
44*2718b568SThomas Cort const char *xf_name;
45*2718b568SThomas Cort short xf_flags;
46*2718b568SThomas Cort };
47*2718b568SThomas Cort
48*2718b568SThomas Cort /* index into struct x_ftab x_ftab[] - small is good */
49*2718b568SThomas Cort typedef unsigned char Findex;
50*2718b568SThomas Cort
51*2718b568SThomas Cort struct x_defbindings {
52*2718b568SThomas Cort Findex xdb_func; /* XFUNC_* */
53*2718b568SThomas Cort unsigned char xdb_tab;
54*2718b568SThomas Cort unsigned char xdb_char;
55*2718b568SThomas Cort };
56*2718b568SThomas Cort
57*2718b568SThomas Cort #define XF_ARG 1 /* command takes number prefix */
58*2718b568SThomas Cort #define XF_NOBIND 2 /* not allowed to bind to function */
59*2718b568SThomas Cort #define XF_PREFIX 4 /* function sets prefix */
60*2718b568SThomas Cort
61*2718b568SThomas Cort /* Separator for completion */
62*2718b568SThomas Cort #define is_cfs(c) (c == ' ' || c == '\t' || c == '"' || c == '\'')
63*2718b568SThomas Cort #define is_mfs(c) (!(isalnum((unsigned char)c) || c == '_' || c == '$')) /* Separator for motion */
64*2718b568SThomas Cort
65*2718b568SThomas Cort #ifdef OS2
66*2718b568SThomas Cort /* Deal with 8 bit chars & an extra prefix for function key (these two
67*2718b568SThomas Cort * changes increase memory usage from 9,216 bytes to 24,416 bytes...)
68*2718b568SThomas Cort */
69*2718b568SThomas Cort # define CHARMASK 0xFF /* 8-bit ASCII character mask */
70*2718b568SThomas Cort # define X_NTABS 4 /* normal, meta1, meta2, meta3 */
71*2718b568SThomas Cort static int x_prefix3 = 0xE0;
72*2718b568SThomas Cort #else /* OS2 */
73*2718b568SThomas Cort # define CHARMASK 0xFF /* 8-bit character mask */
74*2718b568SThomas Cort # define X_NTABS 3 /* normal, meta1, meta2 */
75*2718b568SThomas Cort #endif /* OS2 */
76*2718b568SThomas Cort #define X_TABSZ (CHARMASK+1) /* size of keydef tables etc */
77*2718b568SThomas Cort
78*2718b568SThomas Cort /* Arguments for do_complete()
79*2718b568SThomas Cort * 0 = enumerate M-= complete as much as possible and then list
80*2718b568SThomas Cort * 1 = complete M-Esc
81*2718b568SThomas Cort * 2 = list M-?
82*2718b568SThomas Cort */
83*2718b568SThomas Cort typedef enum { CT_LIST, /* list the possible completions */
84*2718b568SThomas Cort CT_COMPLETE, /* complete to longest prefix */
85*2718b568SThomas Cort CT_COMPLIST /* complete and then list (if non-exact) */
86*2718b568SThomas Cort } Comp_type;
87*2718b568SThomas Cort
88*2718b568SThomas Cort /* { from 4.9 edit.h */
89*2718b568SThomas Cort /*
90*2718b568SThomas Cort * The following are used for my horizontal scrolling stuff
91*2718b568SThomas Cort */
92*2718b568SThomas Cort static char *xbuf; /* beg input buffer */
93*2718b568SThomas Cort static char *xend; /* end input buffer */
94*2718b568SThomas Cort static char *xcp; /* current position */
95*2718b568SThomas Cort static char *xep; /* current end */
96*2718b568SThomas Cort static char *xbp; /* start of visible portion of input buffer */
97*2718b568SThomas Cort static char *xlp; /* last char visible on screen */
98*2718b568SThomas Cort static int x_adj_ok;
99*2718b568SThomas Cort /*
100*2718b568SThomas Cort * we use x_adj_done so that functions can tell
101*2718b568SThomas Cort * whether x_adjust() has been called while they are active.
102*2718b568SThomas Cort */
103*2718b568SThomas Cort static int x_adj_done;
104*2718b568SThomas Cort
105*2718b568SThomas Cort static int xx_cols;
106*2718b568SThomas Cort static int x_col;
107*2718b568SThomas Cort static int x_displen;
108*2718b568SThomas Cort static int x_arg; /* general purpose arg */
109*2718b568SThomas Cort static int x_arg_defaulted;/* x_arg not explicitly set; defaulted to 1 */
110*2718b568SThomas Cort
111*2718b568SThomas Cort static int xlp_valid;
112*2718b568SThomas Cort /* end from 4.9 edit.h } */
113*2718b568SThomas Cort
114*2718b568SThomas Cort static int x_prefix1 = CTRL('['), x_prefix2 = CTRL('X');
115*2718b568SThomas Cort static char **x_histp; /* history position */
116*2718b568SThomas Cort static int x_nextcmd; /* for newline-and-next */
117*2718b568SThomas Cort static char *xmp; /* mark pointer */
118*2718b568SThomas Cort static Findex x_last_command;
119*2718b568SThomas Cort static Findex (*x_tab)[X_TABSZ]; /* key definition */
120*2718b568SThomas Cort static char *(*x_atab)[X_TABSZ]; /* macro definitions */
121*2718b568SThomas Cort static unsigned char x_bound[(X_TABSZ * X_NTABS + 7) / 8];
122*2718b568SThomas Cort #define KILLSIZE 20
123*2718b568SThomas Cort static char *killstack[KILLSIZE];
124*2718b568SThomas Cort static int killsp, killtp;
125*2718b568SThomas Cort static int x_curprefix;
126*2718b568SThomas Cort static char *macroptr;
127*2718b568SThomas Cort static int prompt_trunc;
128*2718b568SThomas Cort static int prompt_skip;
129*2718b568SThomas Cort
130*2718b568SThomas Cort static int x_ins ARGS((char *cp));
131*2718b568SThomas Cort static void x_delete ARGS((int nc, int push));
132*2718b568SThomas Cort static int x_bword ARGS((void));
133*2718b568SThomas Cort static int x_fword ARGS((void));
134*2718b568SThomas Cort static void x_goto ARGS((char *cp));
135*2718b568SThomas Cort static void x_bs ARGS((int c));
136*2718b568SThomas Cort static int x_size_str ARGS((char *cp));
137*2718b568SThomas Cort static int x_size ARGS((int c));
138*2718b568SThomas Cort static void x_zots ARGS((char *str));
139*2718b568SThomas Cort static void x_zotc ARGS((int c));
140*2718b568SThomas Cort static void x_load_hist ARGS((char **hp));
141*2718b568SThomas Cort static int x_search ARGS((char *pat, int sameline, int offset));
142*2718b568SThomas Cort static int x_match ARGS((char *str, char *pat));
143*2718b568SThomas Cort static void x_redraw ARGS((int limit));
144*2718b568SThomas Cort static void x_push ARGS((int nchars));
145*2718b568SThomas Cort static char * x_mapin ARGS((const char *cp, Area *area));
146*2718b568SThomas Cort static char * x_mapout ARGS((int c));
147*2718b568SThomas Cort static void x_print ARGS((int prefix, int key));
148*2718b568SThomas Cort static void x_adjust ARGS((void));
149*2718b568SThomas Cort static void x_e_ungetc ARGS((int c));
150*2718b568SThomas Cort static int x_e_getc ARGS((void));
151*2718b568SThomas Cort static void x_e_putc ARGS((int c));
152*2718b568SThomas Cort static void x_e_puts ARGS((const char *s));
153*2718b568SThomas Cort static int x_comment ARGS((int c));
154*2718b568SThomas Cort static int x_fold_case ARGS((int c));
155*2718b568SThomas Cort static char *x_lastcp ARGS((void));
156*2718b568SThomas Cort static void do_complete ARGS((int flags, Comp_type type));
157*2718b568SThomas Cort static int x_emacs_putbuf ARGS((const char *s, size_t len));
158*2718b568SThomas Cort
159*2718b568SThomas Cort
160*2718b568SThomas Cort /* The lines between START-FUNC-TAB .. END-FUNC-TAB are run through a
161*2718b568SThomas Cort * script (emacs-gen.sh) that generates emacs.out which contains:
162*2718b568SThomas Cort * - function declarations for x_* functions
163*2718b568SThomas Cort * - defines of the form XFUNC_<name> where <name> is function
164*2718b568SThomas Cort * name, sans leading x_.
165*2718b568SThomas Cort * Note that the script treats #ifdef and { 0, 0, 0} specially - use with
166*2718b568SThomas Cort * caution.
167*2718b568SThomas Cort */
168*2718b568SThomas Cort #include "emacs.out"
169*2718b568SThomas Cort static const struct x_ftab x_ftab[] = {
170*2718b568SThomas Cort /* @START-FUNC-TAB@ */
171*2718b568SThomas Cort { x_abort, "abort", 0 },
172*2718b568SThomas Cort { x_beg_hist, "beginning-of-history", 0 },
173*2718b568SThomas Cort { x_comp_comm, "complete-command", 0 },
174*2718b568SThomas Cort { x_comp_file, "complete-file", 0 },
175*2718b568SThomas Cort { x_complete, "complete", 0 },
176*2718b568SThomas Cort { x_del_back, "delete-char-backward", XF_ARG },
177*2718b568SThomas Cort { x_del_bword, "delete-word-backward", XF_ARG },
178*2718b568SThomas Cort { x_del_char, "delete-char-forward", XF_ARG },
179*2718b568SThomas Cort { x_del_fword, "delete-word-forward", XF_ARG },
180*2718b568SThomas Cort { x_del_line, "kill-line", 0 },
181*2718b568SThomas Cort { x_draw_line, "redraw", 0 },
182*2718b568SThomas Cort { x_end_hist, "end-of-history", 0 },
183*2718b568SThomas Cort { x_end_of_text, "eot", 0 },
184*2718b568SThomas Cort { x_enumerate, "list", 0 },
185*2718b568SThomas Cort { x_eot_del, "eot-or-delete", XF_ARG },
186*2718b568SThomas Cort { x_error, "error", 0 },
187*2718b568SThomas Cort { x_goto_hist, "goto-history", XF_ARG },
188*2718b568SThomas Cort { x_ins_string, "macro-string", XF_NOBIND },
189*2718b568SThomas Cort { x_insert, "auto-insert", XF_ARG },
190*2718b568SThomas Cort { x_kill, "kill-to-eol", XF_ARG },
191*2718b568SThomas Cort { x_kill_region, "kill-region", 0 },
192*2718b568SThomas Cort { x_list_comm, "list-command", 0 },
193*2718b568SThomas Cort { x_list_file, "list-file", 0 },
194*2718b568SThomas Cort { x_literal, "quote", 0 },
195*2718b568SThomas Cort { x_meta1, "prefix-1", XF_PREFIX },
196*2718b568SThomas Cort { x_meta2, "prefix-2", XF_PREFIX },
197*2718b568SThomas Cort { x_meta_yank, "yank-pop", 0 },
198*2718b568SThomas Cort { x_mv_back, "backward-char", XF_ARG },
199*2718b568SThomas Cort { x_mv_begin, "beginning-of-line", 0 },
200*2718b568SThomas Cort { x_mv_bword, "backward-word", XF_ARG },
201*2718b568SThomas Cort { x_mv_end, "end-of-line", 0 },
202*2718b568SThomas Cort { x_mv_forw, "forward-char", XF_ARG },
203*2718b568SThomas Cort { x_mv_fword, "forward-word", XF_ARG },
204*2718b568SThomas Cort { x_newline, "newline", 0 },
205*2718b568SThomas Cort { x_next_com, "down-history", XF_ARG },
206*2718b568SThomas Cort { x_nl_next_com, "newline-and-next", 0 },
207*2718b568SThomas Cort { x_noop, "no-op", 0 },
208*2718b568SThomas Cort { x_prev_com, "up-history", XF_ARG },
209*2718b568SThomas Cort { x_prev_histword, "prev-hist-word", XF_ARG },
210*2718b568SThomas Cort { x_search_char_forw, "search-character-forward", XF_ARG },
211*2718b568SThomas Cort { x_search_char_back, "search-character-backward", XF_ARG },
212*2718b568SThomas Cort { x_search_hist, "search-history", 0 },
213*2718b568SThomas Cort { x_set_mark, "set-mark-command", 0 },
214*2718b568SThomas Cort { x_stuff, "stuff", 0 },
215*2718b568SThomas Cort { x_stuffreset, "stuff-reset", 0 },
216*2718b568SThomas Cort { x_transpose, "transpose-chars", 0 },
217*2718b568SThomas Cort { x_version, "version", 0 },
218*2718b568SThomas Cort { x_xchg_point_mark, "exchange-point-and-mark", 0 },
219*2718b568SThomas Cort { x_yank, "yank", 0 },
220*2718b568SThomas Cort { x_comp_list, "complete-list", 0 },
221*2718b568SThomas Cort { x_expand, "expand-file", 0 },
222*2718b568SThomas Cort { x_fold_capitalize, "capitalize-word", XF_ARG },
223*2718b568SThomas Cort { x_fold_lower, "downcase-word", XF_ARG },
224*2718b568SThomas Cort { x_fold_upper, "upcase-word", XF_ARG },
225*2718b568SThomas Cort { x_set_arg, "set-arg", XF_NOBIND },
226*2718b568SThomas Cort { x_comment, "comment", 0 },
227*2718b568SThomas Cort #ifdef SILLY
228*2718b568SThomas Cort { x_game_of_life, "play-game-of-life", 0 },
229*2718b568SThomas Cort #else
230*2718b568SThomas Cort { 0, 0, 0 },
231*2718b568SThomas Cort #endif
232*2718b568SThomas Cort #ifdef DEBUG
233*2718b568SThomas Cort { x_debug_info, "debug-info", 0 },
234*2718b568SThomas Cort #else
235*2718b568SThomas Cort { 0, 0, 0 },
236*2718b568SThomas Cort #endif
237*2718b568SThomas Cort #ifdef OS2
238*2718b568SThomas Cort { x_meta3, "prefix-3", XF_PREFIX },
239*2718b568SThomas Cort #else
240*2718b568SThomas Cort { 0, 0, 0 },
241*2718b568SThomas Cort #endif
242*2718b568SThomas Cort /* @END-FUNC-TAB@ */
243*2718b568SThomas Cort };
244*2718b568SThomas Cort
245*2718b568SThomas Cort static struct x_defbindings const x_defbindings[] = {
246*2718b568SThomas Cort { XFUNC_del_back, 0, CTRL('?') },
247*2718b568SThomas Cort { XFUNC_del_bword, 1, CTRL('?') },
248*2718b568SThomas Cort { XFUNC_eot_del, 0, CTRL('D') },
249*2718b568SThomas Cort { XFUNC_del_back, 0, CTRL('H') },
250*2718b568SThomas Cort { XFUNC_del_bword, 1, CTRL('H') },
251*2718b568SThomas Cort { XFUNC_del_bword, 1, 'h' },
252*2718b568SThomas Cort { XFUNC_mv_bword, 1, 'b' },
253*2718b568SThomas Cort { XFUNC_mv_fword, 1, 'f' },
254*2718b568SThomas Cort { XFUNC_del_fword, 1, 'd' },
255*2718b568SThomas Cort { XFUNC_mv_back, 0, CTRL('B') },
256*2718b568SThomas Cort { XFUNC_mv_forw, 0, CTRL('F') },
257*2718b568SThomas Cort { XFUNC_search_char_forw, 0, CTRL(']') },
258*2718b568SThomas Cort { XFUNC_search_char_back, 1, CTRL(']') },
259*2718b568SThomas Cort { XFUNC_newline, 0, CTRL('M') },
260*2718b568SThomas Cort { XFUNC_newline, 0, CTRL('J') },
261*2718b568SThomas Cort { XFUNC_end_of_text, 0, CTRL('_') },
262*2718b568SThomas Cort { XFUNC_abort, 0, CTRL('G') },
263*2718b568SThomas Cort { XFUNC_prev_com, 0, CTRL('P') },
264*2718b568SThomas Cort { XFUNC_next_com, 0, CTRL('N') },
265*2718b568SThomas Cort { XFUNC_nl_next_com, 0, CTRL('O') },
266*2718b568SThomas Cort { XFUNC_search_hist, 0, CTRL('R') },
267*2718b568SThomas Cort { XFUNC_beg_hist, 1, '<' },
268*2718b568SThomas Cort { XFUNC_end_hist, 1, '>' },
269*2718b568SThomas Cort { XFUNC_goto_hist, 1, 'g' },
270*2718b568SThomas Cort { XFUNC_mv_end, 0, CTRL('E') },
271*2718b568SThomas Cort { XFUNC_mv_begin, 0, CTRL('A') },
272*2718b568SThomas Cort { XFUNC_draw_line, 0, CTRL('L') },
273*2718b568SThomas Cort { XFUNC_meta1, 0, CTRL('[') },
274*2718b568SThomas Cort { XFUNC_meta2, 0, CTRL('X') },
275*2718b568SThomas Cort { XFUNC_kill, 0, CTRL('K') },
276*2718b568SThomas Cort { XFUNC_yank, 0, CTRL('Y') },
277*2718b568SThomas Cort { XFUNC_meta_yank, 1, 'y' },
278*2718b568SThomas Cort { XFUNC_literal, 0, CTRL('^') },
279*2718b568SThomas Cort { XFUNC_comment, 1, '#' },
280*2718b568SThomas Cort #if defined(BRL) && defined(TIOCSTI)
281*2718b568SThomas Cort { XFUNC_stuff, 0, CTRL('T') },
282*2718b568SThomas Cort #else
283*2718b568SThomas Cort { XFUNC_transpose, 0, CTRL('T') },
284*2718b568SThomas Cort #endif
285*2718b568SThomas Cort { XFUNC_complete, 1, CTRL('[') },
286*2718b568SThomas Cort { XFUNC_comp_list, 0, CTRL('I') },
287*2718b568SThomas Cort { XFUNC_comp_list, 1, '=' },
288*2718b568SThomas Cort { XFUNC_enumerate, 1, '?' },
289*2718b568SThomas Cort { XFUNC_expand, 1, '*' },
290*2718b568SThomas Cort { XFUNC_comp_file, 1, CTRL('X') },
291*2718b568SThomas Cort { XFUNC_comp_comm, 2, CTRL('[') },
292*2718b568SThomas Cort { XFUNC_list_comm, 2, '?' },
293*2718b568SThomas Cort { XFUNC_list_file, 2, CTRL('Y') },
294*2718b568SThomas Cort { XFUNC_set_mark, 1, ' ' },
295*2718b568SThomas Cort { XFUNC_kill_region, 0, CTRL('W') },
296*2718b568SThomas Cort { XFUNC_xchg_point_mark, 2, CTRL('X') },
297*2718b568SThomas Cort { XFUNC_version, 0, CTRL('V') },
298*2718b568SThomas Cort #ifdef DEBUG
299*2718b568SThomas Cort { XFUNC_debug_info, 1, CTRL('H') },
300*2718b568SThomas Cort #endif
301*2718b568SThomas Cort { XFUNC_prev_histword, 1, '.' },
302*2718b568SThomas Cort { XFUNC_prev_histword, 1, '_' },
303*2718b568SThomas Cort { XFUNC_set_arg, 1, '0' },
304*2718b568SThomas Cort { XFUNC_set_arg, 1, '1' },
305*2718b568SThomas Cort { XFUNC_set_arg, 1, '2' },
306*2718b568SThomas Cort { XFUNC_set_arg, 1, '3' },
307*2718b568SThomas Cort { XFUNC_set_arg, 1, '4' },
308*2718b568SThomas Cort { XFUNC_set_arg, 1, '5' },
309*2718b568SThomas Cort { XFUNC_set_arg, 1, '6' },
310*2718b568SThomas Cort { XFUNC_set_arg, 1, '7' },
311*2718b568SThomas Cort { XFUNC_set_arg, 1, '8' },
312*2718b568SThomas Cort { XFUNC_set_arg, 1, '9' },
313*2718b568SThomas Cort { XFUNC_fold_upper, 1, 'U' },
314*2718b568SThomas Cort { XFUNC_fold_upper, 1, 'u' },
315*2718b568SThomas Cort { XFUNC_fold_lower, 1, 'L' },
316*2718b568SThomas Cort { XFUNC_fold_lower, 1, 'l' },
317*2718b568SThomas Cort { XFUNC_fold_capitalize, 1, 'C' },
318*2718b568SThomas Cort { XFUNC_fold_capitalize, 1, 'c' },
319*2718b568SThomas Cort #ifdef OS2
320*2718b568SThomas Cort { XFUNC_meta3, 0, 0xE0 },
321*2718b568SThomas Cort { XFUNC_mv_back, 3, 'K' },
322*2718b568SThomas Cort { XFUNC_mv_forw, 3, 'M' },
323*2718b568SThomas Cort { XFUNC_next_com, 3, 'P' },
324*2718b568SThomas Cort { XFUNC_prev_com, 3, 'H' },
325*2718b568SThomas Cort #endif /* OS2 */
326*2718b568SThomas Cort /* These for ansi arrow keys: arguablely shouldn't be here by
327*2718b568SThomas Cort * default, but its simpler/faster/smaller than using termcap
328*2718b568SThomas Cort * entries.
329*2718b568SThomas Cort */
330*2718b568SThomas Cort { XFUNC_meta2, 1, '[' },
331*2718b568SThomas Cort { XFUNC_meta2, 1, 'O' },
332*2718b568SThomas Cort { XFUNC_prev_com, 2, 'A' },
333*2718b568SThomas Cort { XFUNC_next_com, 2, 'B' },
334*2718b568SThomas Cort { XFUNC_mv_forw, 2, 'C' },
335*2718b568SThomas Cort { XFUNC_mv_back, 2, 'D' },
336*2718b568SThomas Cort };
337*2718b568SThomas Cort
338*2718b568SThomas Cort int
x_emacs(buf,len)339*2718b568SThomas Cort x_emacs(buf, len)
340*2718b568SThomas Cort char *buf;
341*2718b568SThomas Cort size_t len;
342*2718b568SThomas Cort {
343*2718b568SThomas Cort int c;
344*2718b568SThomas Cort const char *p;
345*2718b568SThomas Cort int i;
346*2718b568SThomas Cort Findex f;
347*2718b568SThomas Cort
348*2718b568SThomas Cort xbp = xbuf = buf; xend = buf + len;
349*2718b568SThomas Cort xlp = xcp = xep = buf;
350*2718b568SThomas Cort *xcp = 0;
351*2718b568SThomas Cort xlp_valid = TRUE;
352*2718b568SThomas Cort xmp = NULL;
353*2718b568SThomas Cort x_curprefix = 0;
354*2718b568SThomas Cort macroptr = (char *) 0;
355*2718b568SThomas Cort x_histp = histptr + 1;
356*2718b568SThomas Cort x_last_command = XFUNC_error;
357*2718b568SThomas Cort
358*2718b568SThomas Cort xx_cols = x_cols;
359*2718b568SThomas Cort x_col = promptlen(prompt, &p);
360*2718b568SThomas Cort prompt_skip = p - prompt;
361*2718b568SThomas Cort prompt_trunc = x_col - (x_cols - 3 - MIN_EDIT_SPACE);
362*2718b568SThomas Cort if (prompt_trunc > 0)
363*2718b568SThomas Cort x_col -= prompt_trunc;
364*2718b568SThomas Cort else
365*2718b568SThomas Cort prompt_trunc = 0;
366*2718b568SThomas Cort x_adj_ok = 1;
367*2718b568SThomas Cort x_displen = xx_cols - 2 - x_col;
368*2718b568SThomas Cort x_adj_done = 0;
369*2718b568SThomas Cort
370*2718b568SThomas Cort pprompt(prompt, prompt_trunc);
371*2718b568SThomas Cort
372*2718b568SThomas Cort if (x_nextcmd >= 0) {
373*2718b568SThomas Cort int off = source->line - x_nextcmd;
374*2718b568SThomas Cort if (histptr - histlist >= off)
375*2718b568SThomas Cort x_load_hist(histptr - off);
376*2718b568SThomas Cort x_nextcmd = -1;
377*2718b568SThomas Cort }
378*2718b568SThomas Cort
379*2718b568SThomas Cort while (1) {
380*2718b568SThomas Cort x_flush();
381*2718b568SThomas Cort if ((c = x_e_getc()) < 0)
382*2718b568SThomas Cort return 0;
383*2718b568SThomas Cort
384*2718b568SThomas Cort if (ISMETA(c)) {
385*2718b568SThomas Cort c = META(c);
386*2718b568SThomas Cort x_curprefix = 1;
387*2718b568SThomas Cort }
388*2718b568SThomas Cort
389*2718b568SThomas Cort f = x_curprefix == -1 ? XFUNC_insert
390*2718b568SThomas Cort : x_tab[x_curprefix][c&CHARMASK];
391*2718b568SThomas Cort
392*2718b568SThomas Cort if (!(x_ftab[f].xf_flags & XF_PREFIX)
393*2718b568SThomas Cort && x_last_command != XFUNC_set_arg)
394*2718b568SThomas Cort {
395*2718b568SThomas Cort x_arg = 1;
396*2718b568SThomas Cort x_arg_defaulted = 1;
397*2718b568SThomas Cort }
398*2718b568SThomas Cort i = c | (x_curprefix << 8);
399*2718b568SThomas Cort x_curprefix = 0;
400*2718b568SThomas Cort switch (i = (*x_ftab[f].xf_func)(i)) {
401*2718b568SThomas Cort case KSTD:
402*2718b568SThomas Cort if (!(x_ftab[f].xf_flags & XF_PREFIX))
403*2718b568SThomas Cort x_last_command = f;
404*2718b568SThomas Cort break;
405*2718b568SThomas Cort case KEOL:
406*2718b568SThomas Cort i = xep - xbuf;
407*2718b568SThomas Cort return i;
408*2718b568SThomas Cort case KINTR: /* special case for interrupt */
409*2718b568SThomas Cort trapsig(SIGINT);
410*2718b568SThomas Cort x_mode(FALSE);
411*2718b568SThomas Cort unwind(LSHELL);
412*2718b568SThomas Cort }
413*2718b568SThomas Cort }
414*2718b568SThomas Cort }
415*2718b568SThomas Cort
416*2718b568SThomas Cort static int
x_insert(c)417*2718b568SThomas Cort x_insert(c)
418*2718b568SThomas Cort int c;
419*2718b568SThomas Cort {
420*2718b568SThomas Cort char str[2];
421*2718b568SThomas Cort
422*2718b568SThomas Cort /*
423*2718b568SThomas Cort * Should allow tab and control chars.
424*2718b568SThomas Cort */
425*2718b568SThomas Cort if (c == 0) {
426*2718b568SThomas Cort x_e_putc(BEL);
427*2718b568SThomas Cort return KSTD;
428*2718b568SThomas Cort }
429*2718b568SThomas Cort str[0] = c;
430*2718b568SThomas Cort str[1] = '\0';
431*2718b568SThomas Cort while (x_arg--)
432*2718b568SThomas Cort x_ins(str);
433*2718b568SThomas Cort return KSTD;
434*2718b568SThomas Cort }
435*2718b568SThomas Cort
436*2718b568SThomas Cort static int
x_ins_string(c)437*2718b568SThomas Cort x_ins_string(c)
438*2718b568SThomas Cort int c;
439*2718b568SThomas Cort {
440*2718b568SThomas Cort if (macroptr) {
441*2718b568SThomas Cort x_e_putc(BEL);
442*2718b568SThomas Cort return KSTD;
443*2718b568SThomas Cort }
444*2718b568SThomas Cort macroptr = x_atab[c>>8][c & CHARMASK];
445*2718b568SThomas Cort if (macroptr && !*macroptr) {
446*2718b568SThomas Cort /* XXX bell? */
447*2718b568SThomas Cort macroptr = (char *) 0;
448*2718b568SThomas Cort }
449*2718b568SThomas Cort return KSTD;
450*2718b568SThomas Cort }
451*2718b568SThomas Cort
452*2718b568SThomas Cort static int x_do_ins(const char *cp, int len);
453*2718b568SThomas Cort
454*2718b568SThomas Cort static int
x_do_ins(cp,len)455*2718b568SThomas Cort x_do_ins(cp, len)
456*2718b568SThomas Cort const char *cp;
457*2718b568SThomas Cort int len;
458*2718b568SThomas Cort {
459*2718b568SThomas Cort if (xep+len >= xend) {
460*2718b568SThomas Cort x_e_putc(BEL);
461*2718b568SThomas Cort return -1;
462*2718b568SThomas Cort }
463*2718b568SThomas Cort
464*2718b568SThomas Cort memmove(xcp+len, xcp, xep - xcp + 1);
465*2718b568SThomas Cort memmove(xcp, cp, len);
466*2718b568SThomas Cort xcp += len;
467*2718b568SThomas Cort xep += len;
468*2718b568SThomas Cort return 0;
469*2718b568SThomas Cort }
470*2718b568SThomas Cort
471*2718b568SThomas Cort static int
x_ins(s)472*2718b568SThomas Cort x_ins(s)
473*2718b568SThomas Cort char *s;
474*2718b568SThomas Cort {
475*2718b568SThomas Cort char *cp = xcp;
476*2718b568SThomas Cort register int adj = x_adj_done;
477*2718b568SThomas Cort
478*2718b568SThomas Cort if (x_do_ins(s, strlen(s)) < 0)
479*2718b568SThomas Cort return -1;
480*2718b568SThomas Cort /*
481*2718b568SThomas Cort * x_zots() may result in a call to x_adjust()
482*2718b568SThomas Cort * we want xcp to reflect the new position.
483*2718b568SThomas Cort */
484*2718b568SThomas Cort xlp_valid = FALSE;
485*2718b568SThomas Cort x_lastcp();
486*2718b568SThomas Cort x_adj_ok = (xcp >= xlp);
487*2718b568SThomas Cort x_zots(cp);
488*2718b568SThomas Cort if (adj == x_adj_done) /* has x_adjust() been called? */
489*2718b568SThomas Cort {
490*2718b568SThomas Cort /* no */
491*2718b568SThomas Cort for (cp = xlp; cp > xcp; )
492*2718b568SThomas Cort x_bs(*--cp);
493*2718b568SThomas Cort }
494*2718b568SThomas Cort
495*2718b568SThomas Cort x_adj_ok = 1;
496*2718b568SThomas Cort return 0;
497*2718b568SThomas Cort }
498*2718b568SThomas Cort
499*2718b568SThomas Cort /*
500*2718b568SThomas Cort * this is used for x_escape() in do_complete()
501*2718b568SThomas Cort */
502*2718b568SThomas Cort static int
x_emacs_putbuf(s,len)503*2718b568SThomas Cort x_emacs_putbuf(s, len)
504*2718b568SThomas Cort const char *s;
505*2718b568SThomas Cort size_t len;
506*2718b568SThomas Cort {
507*2718b568SThomas Cort int rval;
508*2718b568SThomas Cort
509*2718b568SThomas Cort if ((rval = x_do_ins(s, len)) != 0)
510*2718b568SThomas Cort return (rval);
511*2718b568SThomas Cort return (rval);
512*2718b568SThomas Cort }
513*2718b568SThomas Cort
514*2718b568SThomas Cort static int
x_del_back(c)515*2718b568SThomas Cort x_del_back(c)
516*2718b568SThomas Cort int c;
517*2718b568SThomas Cort {
518*2718b568SThomas Cort int col = xcp - xbuf;
519*2718b568SThomas Cort
520*2718b568SThomas Cort if (col == 0) {
521*2718b568SThomas Cort x_e_putc(BEL);
522*2718b568SThomas Cort return KSTD;
523*2718b568SThomas Cort }
524*2718b568SThomas Cort if (x_arg > col)
525*2718b568SThomas Cort x_arg = col;
526*2718b568SThomas Cort x_goto(xcp - x_arg);
527*2718b568SThomas Cort x_delete(x_arg, FALSE);
528*2718b568SThomas Cort return KSTD;
529*2718b568SThomas Cort }
530*2718b568SThomas Cort
531*2718b568SThomas Cort static int
x_del_char(c)532*2718b568SThomas Cort x_del_char(c)
533*2718b568SThomas Cort int c;
534*2718b568SThomas Cort {
535*2718b568SThomas Cort int nleft = xep - xcp;
536*2718b568SThomas Cort
537*2718b568SThomas Cort if (!nleft) {
538*2718b568SThomas Cort x_e_putc(BEL);
539*2718b568SThomas Cort return KSTD;
540*2718b568SThomas Cort }
541*2718b568SThomas Cort if (x_arg > nleft)
542*2718b568SThomas Cort x_arg = nleft;
543*2718b568SThomas Cort x_delete(x_arg, FALSE);
544*2718b568SThomas Cort return KSTD;
545*2718b568SThomas Cort }
546*2718b568SThomas Cort
547*2718b568SThomas Cort /* Delete nc chars to the right of the cursor (including cursor position) */
548*2718b568SThomas Cort static void
x_delete(nc,push)549*2718b568SThomas Cort x_delete(nc, push)
550*2718b568SThomas Cort int nc;
551*2718b568SThomas Cort int push;
552*2718b568SThomas Cort {
553*2718b568SThomas Cort int i,j;
554*2718b568SThomas Cort char *cp;
555*2718b568SThomas Cort
556*2718b568SThomas Cort if (nc == 0)
557*2718b568SThomas Cort return;
558*2718b568SThomas Cort if (xmp != NULL && xmp > xcp) {
559*2718b568SThomas Cort if (xcp + nc > xmp)
560*2718b568SThomas Cort xmp = xcp;
561*2718b568SThomas Cort else
562*2718b568SThomas Cort xmp -= nc;
563*2718b568SThomas Cort }
564*2718b568SThomas Cort
565*2718b568SThomas Cort /*
566*2718b568SThomas Cort * This lets us yank a word we have deleted.
567*2718b568SThomas Cort */
568*2718b568SThomas Cort if (push)
569*2718b568SThomas Cort x_push(nc);
570*2718b568SThomas Cort
571*2718b568SThomas Cort xep -= nc;
572*2718b568SThomas Cort cp = xcp;
573*2718b568SThomas Cort j = 0;
574*2718b568SThomas Cort i = nc;
575*2718b568SThomas Cort while (i--) {
576*2718b568SThomas Cort j += x_size(*cp++);
577*2718b568SThomas Cort }
578*2718b568SThomas Cort memmove(xcp, xcp+nc, xep - xcp + 1); /* Copies the null */
579*2718b568SThomas Cort x_adj_ok = 0; /* don't redraw */
580*2718b568SThomas Cort x_zots(xcp);
581*2718b568SThomas Cort /*
582*2718b568SThomas Cort * if we are already filling the line,
583*2718b568SThomas Cort * there is no need to ' ','\b'.
584*2718b568SThomas Cort * But if we must, make sure we do the minimum.
585*2718b568SThomas Cort */
586*2718b568SThomas Cort if ((i = x_displen) > 0)
587*2718b568SThomas Cort {
588*2718b568SThomas Cort j = (j < i) ? j : i;
589*2718b568SThomas Cort i = j;
590*2718b568SThomas Cort while (i--)
591*2718b568SThomas Cort x_e_putc(' ');
592*2718b568SThomas Cort i = j;
593*2718b568SThomas Cort while (i--)
594*2718b568SThomas Cort x_e_putc('\b');
595*2718b568SThomas Cort }
596*2718b568SThomas Cort /*x_goto(xcp);*/
597*2718b568SThomas Cort x_adj_ok = 1;
598*2718b568SThomas Cort xlp_valid = FALSE;
599*2718b568SThomas Cort for (cp = x_lastcp(); cp > xcp; )
600*2718b568SThomas Cort x_bs(*--cp);
601*2718b568SThomas Cort
602*2718b568SThomas Cort return;
603*2718b568SThomas Cort }
604*2718b568SThomas Cort
605*2718b568SThomas Cort static int
x_del_bword(c)606*2718b568SThomas Cort x_del_bword(c)
607*2718b568SThomas Cort int c;
608*2718b568SThomas Cort {
609*2718b568SThomas Cort x_delete(x_bword(), TRUE);
610*2718b568SThomas Cort return KSTD;
611*2718b568SThomas Cort }
612*2718b568SThomas Cort
613*2718b568SThomas Cort static int
x_mv_bword(c)614*2718b568SThomas Cort x_mv_bword(c)
615*2718b568SThomas Cort int c;
616*2718b568SThomas Cort {
617*2718b568SThomas Cort (void)x_bword();
618*2718b568SThomas Cort return KSTD;
619*2718b568SThomas Cort }
620*2718b568SThomas Cort
621*2718b568SThomas Cort static int
x_mv_fword(c)622*2718b568SThomas Cort x_mv_fword(c)
623*2718b568SThomas Cort int c;
624*2718b568SThomas Cort {
625*2718b568SThomas Cort x_goto(xcp + x_fword());
626*2718b568SThomas Cort return KSTD;
627*2718b568SThomas Cort }
628*2718b568SThomas Cort
629*2718b568SThomas Cort static int
x_del_fword(c)630*2718b568SThomas Cort x_del_fword(c)
631*2718b568SThomas Cort int c;
632*2718b568SThomas Cort {
633*2718b568SThomas Cort x_delete(x_fword(), TRUE);
634*2718b568SThomas Cort return KSTD;
635*2718b568SThomas Cort }
636*2718b568SThomas Cort
637*2718b568SThomas Cort static int
x_bword()638*2718b568SThomas Cort x_bword()
639*2718b568SThomas Cort {
640*2718b568SThomas Cort int nc = 0;
641*2718b568SThomas Cort register char *cp = xcp;
642*2718b568SThomas Cort
643*2718b568SThomas Cort if (cp == xbuf) {
644*2718b568SThomas Cort x_e_putc(BEL);
645*2718b568SThomas Cort return 0;
646*2718b568SThomas Cort }
647*2718b568SThomas Cort while (x_arg--)
648*2718b568SThomas Cort {
649*2718b568SThomas Cort while (cp != xbuf && is_mfs(cp[-1]))
650*2718b568SThomas Cort {
651*2718b568SThomas Cort cp--;
652*2718b568SThomas Cort nc++;
653*2718b568SThomas Cort }
654*2718b568SThomas Cort while (cp != xbuf && !is_mfs(cp[-1]))
655*2718b568SThomas Cort {
656*2718b568SThomas Cort cp--;
657*2718b568SThomas Cort nc++;
658*2718b568SThomas Cort }
659*2718b568SThomas Cort }
660*2718b568SThomas Cort x_goto(cp);
661*2718b568SThomas Cort return nc;
662*2718b568SThomas Cort }
663*2718b568SThomas Cort
664*2718b568SThomas Cort static int
x_fword()665*2718b568SThomas Cort x_fword()
666*2718b568SThomas Cort {
667*2718b568SThomas Cort int nc = 0;
668*2718b568SThomas Cort register char *cp = xcp;
669*2718b568SThomas Cort
670*2718b568SThomas Cort if (cp == xep) {
671*2718b568SThomas Cort x_e_putc(BEL);
672*2718b568SThomas Cort return 0;
673*2718b568SThomas Cort }
674*2718b568SThomas Cort while (x_arg--)
675*2718b568SThomas Cort {
676*2718b568SThomas Cort while (cp != xep && is_mfs(*cp))
677*2718b568SThomas Cort {
678*2718b568SThomas Cort cp++;
679*2718b568SThomas Cort nc++;
680*2718b568SThomas Cort }
681*2718b568SThomas Cort while (cp != xep && !is_mfs(*cp))
682*2718b568SThomas Cort {
683*2718b568SThomas Cort cp++;
684*2718b568SThomas Cort nc++;
685*2718b568SThomas Cort }
686*2718b568SThomas Cort }
687*2718b568SThomas Cort return nc;
688*2718b568SThomas Cort }
689*2718b568SThomas Cort
690*2718b568SThomas Cort static void
x_goto(cp)691*2718b568SThomas Cort x_goto(cp)
692*2718b568SThomas Cort register char *cp;
693*2718b568SThomas Cort {
694*2718b568SThomas Cort if (cp < xbp || cp >= (xbp + x_displen))
695*2718b568SThomas Cort {
696*2718b568SThomas Cort /* we are heading off screen */
697*2718b568SThomas Cort xcp = cp;
698*2718b568SThomas Cort x_adjust();
699*2718b568SThomas Cort }
700*2718b568SThomas Cort else
701*2718b568SThomas Cort {
702*2718b568SThomas Cort if (cp < xcp) /* move back */
703*2718b568SThomas Cort {
704*2718b568SThomas Cort while (cp < xcp)
705*2718b568SThomas Cort x_bs(*--xcp);
706*2718b568SThomas Cort }
707*2718b568SThomas Cort else
708*2718b568SThomas Cort {
709*2718b568SThomas Cort if (cp > xcp) /* move forward */
710*2718b568SThomas Cort {
711*2718b568SThomas Cort while (cp > xcp)
712*2718b568SThomas Cort x_zotc(*xcp++);
713*2718b568SThomas Cort }
714*2718b568SThomas Cort }
715*2718b568SThomas Cort }
716*2718b568SThomas Cort }
717*2718b568SThomas Cort
718*2718b568SThomas Cort static void
x_bs(c)719*2718b568SThomas Cort x_bs(c)
720*2718b568SThomas Cort int c;
721*2718b568SThomas Cort {
722*2718b568SThomas Cort register int i;
723*2718b568SThomas Cort i = x_size(c);
724*2718b568SThomas Cort while (i--)
725*2718b568SThomas Cort x_e_putc('\b');
726*2718b568SThomas Cort }
727*2718b568SThomas Cort
728*2718b568SThomas Cort static int
x_size_str(cp)729*2718b568SThomas Cort x_size_str(cp)
730*2718b568SThomas Cort register char *cp;
731*2718b568SThomas Cort {
732*2718b568SThomas Cort register int size = 0;
733*2718b568SThomas Cort while (*cp)
734*2718b568SThomas Cort size += x_size(*cp++);
735*2718b568SThomas Cort return size;
736*2718b568SThomas Cort }
737*2718b568SThomas Cort
738*2718b568SThomas Cort static int
x_size(c)739*2718b568SThomas Cort x_size(c)
740*2718b568SThomas Cort int c;
741*2718b568SThomas Cort {
742*2718b568SThomas Cort if (c=='\t')
743*2718b568SThomas Cort return 4; /* Kludge, tabs are always four spaces. */
744*2718b568SThomas Cort if (iscntrl((unsigned char)c)) /* control char */
745*2718b568SThomas Cort return 2;
746*2718b568SThomas Cort return 1;
747*2718b568SThomas Cort }
748*2718b568SThomas Cort
749*2718b568SThomas Cort static void
x_zots(str)750*2718b568SThomas Cort x_zots(str)
751*2718b568SThomas Cort register char *str;
752*2718b568SThomas Cort {
753*2718b568SThomas Cort register int adj = x_adj_done;
754*2718b568SThomas Cort
755*2718b568SThomas Cort x_lastcp();
756*2718b568SThomas Cort while (*str && str < xlp && adj == x_adj_done)
757*2718b568SThomas Cort x_zotc(*str++);
758*2718b568SThomas Cort }
759*2718b568SThomas Cort
760*2718b568SThomas Cort static void
x_zotc(c)761*2718b568SThomas Cort x_zotc(c)
762*2718b568SThomas Cort int c;
763*2718b568SThomas Cort {
764*2718b568SThomas Cort if (c == '\t') {
765*2718b568SThomas Cort /* Kludge, tabs are always four spaces. */
766*2718b568SThomas Cort x_e_puts(" ");
767*2718b568SThomas Cort } else if (iscntrl((unsigned char)c)) {
768*2718b568SThomas Cort x_e_putc('^');
769*2718b568SThomas Cort x_e_putc(UNCTRL(c));
770*2718b568SThomas Cort } else
771*2718b568SThomas Cort x_e_putc(c);
772*2718b568SThomas Cort }
773*2718b568SThomas Cort
774*2718b568SThomas Cort static int
x_mv_back(c)775*2718b568SThomas Cort x_mv_back(c)
776*2718b568SThomas Cort int c;
777*2718b568SThomas Cort {
778*2718b568SThomas Cort int col = xcp - xbuf;
779*2718b568SThomas Cort
780*2718b568SThomas Cort if (col == 0) {
781*2718b568SThomas Cort x_e_putc(BEL);
782*2718b568SThomas Cort return KSTD;
783*2718b568SThomas Cort }
784*2718b568SThomas Cort if (x_arg > col)
785*2718b568SThomas Cort x_arg = col;
786*2718b568SThomas Cort x_goto(xcp - x_arg);
787*2718b568SThomas Cort return KSTD;
788*2718b568SThomas Cort }
789*2718b568SThomas Cort
790*2718b568SThomas Cort static int
x_mv_forw(c)791*2718b568SThomas Cort x_mv_forw(c)
792*2718b568SThomas Cort int c;
793*2718b568SThomas Cort {
794*2718b568SThomas Cort int nleft = xep - xcp;
795*2718b568SThomas Cort
796*2718b568SThomas Cort if (!nleft) {
797*2718b568SThomas Cort x_e_putc(BEL);
798*2718b568SThomas Cort return KSTD;
799*2718b568SThomas Cort }
800*2718b568SThomas Cort if (x_arg > nleft)
801*2718b568SThomas Cort x_arg = nleft;
802*2718b568SThomas Cort x_goto(xcp + x_arg);
803*2718b568SThomas Cort return KSTD;
804*2718b568SThomas Cort }
805*2718b568SThomas Cort
806*2718b568SThomas Cort static int
x_search_char_forw(c)807*2718b568SThomas Cort x_search_char_forw(c)
808*2718b568SThomas Cort int c;
809*2718b568SThomas Cort {
810*2718b568SThomas Cort char *cp = xcp;
811*2718b568SThomas Cort
812*2718b568SThomas Cort *xep = '\0';
813*2718b568SThomas Cort c = x_e_getc();
814*2718b568SThomas Cort while (x_arg--) {
815*2718b568SThomas Cort if (c < 0
816*2718b568SThomas Cort || ((cp = (cp == xep) ? NULL : strchr(cp + 1, c)) == NULL
817*2718b568SThomas Cort && (cp = strchr(xbuf, c)) == NULL))
818*2718b568SThomas Cort {
819*2718b568SThomas Cort x_e_putc(BEL);
820*2718b568SThomas Cort return KSTD;
821*2718b568SThomas Cort }
822*2718b568SThomas Cort }
823*2718b568SThomas Cort x_goto(cp);
824*2718b568SThomas Cort return KSTD;
825*2718b568SThomas Cort }
826*2718b568SThomas Cort
827*2718b568SThomas Cort static int
x_search_char_back(c)828*2718b568SThomas Cort x_search_char_back(c)
829*2718b568SThomas Cort int c;
830*2718b568SThomas Cort {
831*2718b568SThomas Cort char *cp = xcp, *p;
832*2718b568SThomas Cort
833*2718b568SThomas Cort c = x_e_getc();
834*2718b568SThomas Cort for (; x_arg--; cp = p)
835*2718b568SThomas Cort for (p = cp; ; ) {
836*2718b568SThomas Cort if (p-- == xbuf)
837*2718b568SThomas Cort p = xep;
838*2718b568SThomas Cort if (c < 0 || p == cp) {
839*2718b568SThomas Cort x_e_putc(BEL);
840*2718b568SThomas Cort return KSTD;
841*2718b568SThomas Cort }
842*2718b568SThomas Cort if (*p == c)
843*2718b568SThomas Cort break;
844*2718b568SThomas Cort }
845*2718b568SThomas Cort x_goto(cp);
846*2718b568SThomas Cort return KSTD;
847*2718b568SThomas Cort }
848*2718b568SThomas Cort
849*2718b568SThomas Cort static int
x_newline(c)850*2718b568SThomas Cort x_newline(c)
851*2718b568SThomas Cort int c;
852*2718b568SThomas Cort {
853*2718b568SThomas Cort x_e_putc('\r');
854*2718b568SThomas Cort x_e_putc('\n');
855*2718b568SThomas Cort x_flush();
856*2718b568SThomas Cort *xep++ = '\n';
857*2718b568SThomas Cort return KEOL;
858*2718b568SThomas Cort }
859*2718b568SThomas Cort
860*2718b568SThomas Cort static int
x_end_of_text(c)861*2718b568SThomas Cort x_end_of_text(c)
862*2718b568SThomas Cort int c;
863*2718b568SThomas Cort {
864*2718b568SThomas Cort return KEOL;
865*2718b568SThomas Cort }
866*2718b568SThomas Cort
x_beg_hist(c)867*2718b568SThomas Cort static int x_beg_hist(c) int c; { x_load_hist(histlist); return KSTD;}
868*2718b568SThomas Cort
x_end_hist(c)869*2718b568SThomas Cort static int x_end_hist(c) int c; { x_load_hist(histptr); return KSTD;}
870*2718b568SThomas Cort
x_prev_com(c)871*2718b568SThomas Cort static int x_prev_com(c) int c; { x_load_hist(x_histp - x_arg); return KSTD;}
872*2718b568SThomas Cort
x_next_com(c)873*2718b568SThomas Cort static int x_next_com(c) int c; { x_load_hist(x_histp + x_arg); return KSTD;}
874*2718b568SThomas Cort
875*2718b568SThomas Cort /* Goto a particular history number obtained from argument.
876*2718b568SThomas Cort * If no argument is given history 1 is probably not what you
877*2718b568SThomas Cort * want so we'll simply go to the oldest one.
878*2718b568SThomas Cort */
879*2718b568SThomas Cort static int
x_goto_hist(c)880*2718b568SThomas Cort x_goto_hist(c)
881*2718b568SThomas Cort int c;
882*2718b568SThomas Cort {
883*2718b568SThomas Cort if (x_arg_defaulted)
884*2718b568SThomas Cort x_load_hist(histlist);
885*2718b568SThomas Cort else
886*2718b568SThomas Cort x_load_hist(histptr + x_arg - source->line);
887*2718b568SThomas Cort return KSTD;
888*2718b568SThomas Cort }
889*2718b568SThomas Cort
890*2718b568SThomas Cort static void
x_load_hist(hp)891*2718b568SThomas Cort x_load_hist(hp)
892*2718b568SThomas Cort register char **hp;
893*2718b568SThomas Cort {
894*2718b568SThomas Cort int oldsize;
895*2718b568SThomas Cort
896*2718b568SThomas Cort if (hp < histlist || hp > histptr) {
897*2718b568SThomas Cort x_e_putc(BEL);
898*2718b568SThomas Cort return;
899*2718b568SThomas Cort }
900*2718b568SThomas Cort x_histp = hp;
901*2718b568SThomas Cort oldsize = x_size_str(xbuf);
902*2718b568SThomas Cort strlcpy(xbuf, *hp, xend - xbuf);
903*2718b568SThomas Cort xbp = xbuf;
904*2718b568SThomas Cort xep = xcp = xbuf + strlen(xbuf);
905*2718b568SThomas Cort xlp_valid = FALSE;
906*2718b568SThomas Cort if (xep > x_lastcp())
907*2718b568SThomas Cort x_goto(xep);
908*2718b568SThomas Cort else
909*2718b568SThomas Cort x_redraw(oldsize);
910*2718b568SThomas Cort }
911*2718b568SThomas Cort
912*2718b568SThomas Cort static int
x_nl_next_com(c)913*2718b568SThomas Cort x_nl_next_com(c)
914*2718b568SThomas Cort int c;
915*2718b568SThomas Cort {
916*2718b568SThomas Cort x_nextcmd = source->line - (histptr - x_histp) + 1;
917*2718b568SThomas Cort return (x_newline(c));
918*2718b568SThomas Cort }
919*2718b568SThomas Cort
920*2718b568SThomas Cort static int
x_eot_del(c)921*2718b568SThomas Cort x_eot_del(c)
922*2718b568SThomas Cort int c;
923*2718b568SThomas Cort {
924*2718b568SThomas Cort if (xep == xbuf && x_arg_defaulted)
925*2718b568SThomas Cort return (x_end_of_text(c));
926*2718b568SThomas Cort else
927*2718b568SThomas Cort return (x_del_char(c));
928*2718b568SThomas Cort }
929*2718b568SThomas Cort
930*2718b568SThomas Cort /* reverse incremental history search */
931*2718b568SThomas Cort static int
x_search_hist(c)932*2718b568SThomas Cort x_search_hist(c)
933*2718b568SThomas Cort int c;
934*2718b568SThomas Cort {
935*2718b568SThomas Cort int offset = -1; /* offset of match in xbuf, else -1 */
936*2718b568SThomas Cort char pat [256+1]; /* pattern buffer */
937*2718b568SThomas Cort register char *p = pat;
938*2718b568SThomas Cort Findex f;
939*2718b568SThomas Cort
940*2718b568SThomas Cort *p = '\0';
941*2718b568SThomas Cort while (1) {
942*2718b568SThomas Cort if (offset < 0) {
943*2718b568SThomas Cort x_e_puts("\nI-search: ");
944*2718b568SThomas Cort x_e_puts(pat);
945*2718b568SThomas Cort }
946*2718b568SThomas Cort x_flush();
947*2718b568SThomas Cort if ((c = x_e_getc()) < 0)
948*2718b568SThomas Cort return KSTD;
949*2718b568SThomas Cort f = x_tab[0][c&CHARMASK];
950*2718b568SThomas Cort if (c == CTRL('['))
951*2718b568SThomas Cort break;
952*2718b568SThomas Cort else if (f == XFUNC_search_hist)
953*2718b568SThomas Cort offset = x_search(pat, 0, offset);
954*2718b568SThomas Cort else if (f == XFUNC_del_back) {
955*2718b568SThomas Cort if (p == pat) {
956*2718b568SThomas Cort offset = -1;
957*2718b568SThomas Cort break;
958*2718b568SThomas Cort }
959*2718b568SThomas Cort if (p > pat)
960*2718b568SThomas Cort *--p = '\0';
961*2718b568SThomas Cort if (p == pat)
962*2718b568SThomas Cort offset = -1;
963*2718b568SThomas Cort else
964*2718b568SThomas Cort offset = x_search(pat, 1, offset);
965*2718b568SThomas Cort continue;
966*2718b568SThomas Cort } else if (f == XFUNC_insert) {
967*2718b568SThomas Cort /* add char to pattern */
968*2718b568SThomas Cort /* overflow check... */
969*2718b568SThomas Cort if (p >= &pat[sizeof(pat) - 1]) {
970*2718b568SThomas Cort x_e_putc(BEL);
971*2718b568SThomas Cort continue;
972*2718b568SThomas Cort }
973*2718b568SThomas Cort *p++ = c, *p = '\0';
974*2718b568SThomas Cort if (offset >= 0) {
975*2718b568SThomas Cort /* already have partial match */
976*2718b568SThomas Cort offset = x_match(xbuf, pat);
977*2718b568SThomas Cort if (offset >= 0) {
978*2718b568SThomas Cort x_goto(xbuf + offset + (p - pat) - (*pat == '^'));
979*2718b568SThomas Cort continue;
980*2718b568SThomas Cort }
981*2718b568SThomas Cort }
982*2718b568SThomas Cort offset = x_search(pat, 0, offset);
983*2718b568SThomas Cort } else { /* other command */
984*2718b568SThomas Cort x_e_ungetc(c);
985*2718b568SThomas Cort break;
986*2718b568SThomas Cort }
987*2718b568SThomas Cort }
988*2718b568SThomas Cort if (offset < 0)
989*2718b568SThomas Cort x_redraw(-1);
990*2718b568SThomas Cort return KSTD;
991*2718b568SThomas Cort }
992*2718b568SThomas Cort
993*2718b568SThomas Cort /* search backward from current line */
994*2718b568SThomas Cort static int
x_search(pat,sameline,offset)995*2718b568SThomas Cort x_search(pat, sameline, offset)
996*2718b568SThomas Cort char *pat;
997*2718b568SThomas Cort int sameline;
998*2718b568SThomas Cort int offset;
999*2718b568SThomas Cort {
1000*2718b568SThomas Cort register char **hp;
1001*2718b568SThomas Cort int i;
1002*2718b568SThomas Cort
1003*2718b568SThomas Cort for (hp = x_histp - (sameline ? 0 : 1) ; hp >= histlist; --hp) {
1004*2718b568SThomas Cort i = x_match(*hp, pat);
1005*2718b568SThomas Cort if (i >= 0) {
1006*2718b568SThomas Cort if (offset < 0)
1007*2718b568SThomas Cort x_e_putc('\n');
1008*2718b568SThomas Cort x_load_hist(hp);
1009*2718b568SThomas Cort x_goto(xbuf + i + strlen(pat) - (*pat == '^'));
1010*2718b568SThomas Cort return i;
1011*2718b568SThomas Cort }
1012*2718b568SThomas Cort }
1013*2718b568SThomas Cort x_e_putc(BEL);
1014*2718b568SThomas Cort x_histp = histptr;
1015*2718b568SThomas Cort return -1;
1016*2718b568SThomas Cort }
1017*2718b568SThomas Cort
1018*2718b568SThomas Cort /* return position of first match of pattern in string, else -1 */
1019*2718b568SThomas Cort static int
x_match(str,pat)1020*2718b568SThomas Cort x_match(str, pat)
1021*2718b568SThomas Cort char *str, *pat;
1022*2718b568SThomas Cort {
1023*2718b568SThomas Cort if (*pat == '^') {
1024*2718b568SThomas Cort return (strncmp(str, pat+1, strlen(pat+1)) == 0) ? 0 : -1;
1025*2718b568SThomas Cort } else {
1026*2718b568SThomas Cort char *q = strstr(str, pat);
1027*2718b568SThomas Cort return (q == NULL) ? -1 : q - str;
1028*2718b568SThomas Cort }
1029*2718b568SThomas Cort }
1030*2718b568SThomas Cort
1031*2718b568SThomas Cort static int
x_del_line(c)1032*2718b568SThomas Cort x_del_line(c)
1033*2718b568SThomas Cort int c;
1034*2718b568SThomas Cort {
1035*2718b568SThomas Cort int i, j;
1036*2718b568SThomas Cort
1037*2718b568SThomas Cort *xep = 0;
1038*2718b568SThomas Cort i = xep - xbuf;
1039*2718b568SThomas Cort j = x_size_str(xbuf);
1040*2718b568SThomas Cort xcp = xbuf;
1041*2718b568SThomas Cort x_push(i);
1042*2718b568SThomas Cort xlp = xbp = xep = xbuf;
1043*2718b568SThomas Cort xlp_valid = TRUE;
1044*2718b568SThomas Cort *xcp = 0;
1045*2718b568SThomas Cort xmp = NULL;
1046*2718b568SThomas Cort x_redraw(j);
1047*2718b568SThomas Cort return KSTD;
1048*2718b568SThomas Cort }
1049*2718b568SThomas Cort
1050*2718b568SThomas Cort static int
x_mv_end(c)1051*2718b568SThomas Cort x_mv_end(c)
1052*2718b568SThomas Cort int c;
1053*2718b568SThomas Cort {
1054*2718b568SThomas Cort x_goto(xep);
1055*2718b568SThomas Cort return KSTD;
1056*2718b568SThomas Cort }
1057*2718b568SThomas Cort
1058*2718b568SThomas Cort static int
x_mv_begin(c)1059*2718b568SThomas Cort x_mv_begin(c)
1060*2718b568SThomas Cort int c;
1061*2718b568SThomas Cort {
1062*2718b568SThomas Cort x_goto(xbuf);
1063*2718b568SThomas Cort return KSTD;
1064*2718b568SThomas Cort }
1065*2718b568SThomas Cort
1066*2718b568SThomas Cort static int
x_draw_line(c)1067*2718b568SThomas Cort x_draw_line(c)
1068*2718b568SThomas Cort int c;
1069*2718b568SThomas Cort {
1070*2718b568SThomas Cort x_redraw(-1);
1071*2718b568SThomas Cort return KSTD;
1072*2718b568SThomas Cort
1073*2718b568SThomas Cort }
1074*2718b568SThomas Cort
1075*2718b568SThomas Cort /* Redraw (part of) the line. If limit is < 0, the everything is redrawn
1076*2718b568SThomas Cort * on a NEW line, otherwise limit is the screen column up to which needs
1077*2718b568SThomas Cort * redrawing.
1078*2718b568SThomas Cort */
1079*2718b568SThomas Cort static void
x_redraw(limit)1080*2718b568SThomas Cort x_redraw(limit)
1081*2718b568SThomas Cort int limit;
1082*2718b568SThomas Cort {
1083*2718b568SThomas Cort int i, j;
1084*2718b568SThomas Cort char *cp;
1085*2718b568SThomas Cort
1086*2718b568SThomas Cort x_adj_ok = 0;
1087*2718b568SThomas Cort if (limit == -1)
1088*2718b568SThomas Cort x_e_putc('\n');
1089*2718b568SThomas Cort else
1090*2718b568SThomas Cort x_e_putc('\r');
1091*2718b568SThomas Cort x_flush();
1092*2718b568SThomas Cort if (xbp == xbuf)
1093*2718b568SThomas Cort {
1094*2718b568SThomas Cort pprompt(prompt + prompt_skip, 0);
1095*2718b568SThomas Cort x_col = promptlen(prompt, (const char **) 0);
1096*2718b568SThomas Cort }
1097*2718b568SThomas Cort x_displen = xx_cols - 2 - x_col;
1098*2718b568SThomas Cort xlp_valid = FALSE;
1099*2718b568SThomas Cort cp = x_lastcp();
1100*2718b568SThomas Cort x_zots(xbp);
1101*2718b568SThomas Cort if (xbp != xbuf || xep > xlp)
1102*2718b568SThomas Cort limit = xx_cols;
1103*2718b568SThomas Cort if (limit >= 0)
1104*2718b568SThomas Cort {
1105*2718b568SThomas Cort if (xep > xlp)
1106*2718b568SThomas Cort i = 0; /* we fill the line */
1107*2718b568SThomas Cort else
1108*2718b568SThomas Cort i = limit - (xlp - xbp);
1109*2718b568SThomas Cort
1110*2718b568SThomas Cort for (j = 0; j < i && x_col < (xx_cols - 2); j++)
1111*2718b568SThomas Cort x_e_putc(' ');
1112*2718b568SThomas Cort i = ' ';
1113*2718b568SThomas Cort if (xep > xlp) /* more off screen */
1114*2718b568SThomas Cort {
1115*2718b568SThomas Cort if (xbp > xbuf)
1116*2718b568SThomas Cort i = '*';
1117*2718b568SThomas Cort else
1118*2718b568SThomas Cort i = '>';
1119*2718b568SThomas Cort }
1120*2718b568SThomas Cort else
1121*2718b568SThomas Cort if (xbp > xbuf)
1122*2718b568SThomas Cort i = '<';
1123*2718b568SThomas Cort x_e_putc(i);
1124*2718b568SThomas Cort j++;
1125*2718b568SThomas Cort while (j--)
1126*2718b568SThomas Cort x_e_putc('\b');
1127*2718b568SThomas Cort }
1128*2718b568SThomas Cort for (cp = xlp; cp > xcp; )
1129*2718b568SThomas Cort x_bs(*--cp);
1130*2718b568SThomas Cort x_adj_ok = 1;
1131*2718b568SThomas Cort D__(x_flush();)
1132*2718b568SThomas Cort return;
1133*2718b568SThomas Cort }
1134*2718b568SThomas Cort
1135*2718b568SThomas Cort static int
x_transpose(c)1136*2718b568SThomas Cort x_transpose(c)
1137*2718b568SThomas Cort int c;
1138*2718b568SThomas Cort {
1139*2718b568SThomas Cort char tmp;
1140*2718b568SThomas Cort
1141*2718b568SThomas Cort /* What transpose is meant to do seems to be up for debate. This
1142*2718b568SThomas Cort * is a general summary of the options; the text is abcd with the
1143*2718b568SThomas Cort * upper case character or underscore indicating the cursor position:
1144*2718b568SThomas Cort * Who Before After Before After
1145*2718b568SThomas Cort * at&t ksh in emacs mode: abCd abdC abcd_ (bell)
1146*2718b568SThomas Cort * at&t ksh in gmacs mode: abCd baCd abcd_ abdc_
1147*2718b568SThomas Cort * gnu emacs: abCd acbD abcd_ abdc_
1148*2718b568SThomas Cort * Pdksh currently goes with GNU behavior since I believe this is the
1149*2718b568SThomas Cort * most common version of emacs, unless in gmacs mode, in which case
1150*2718b568SThomas Cort * it does the at&t ksh gmacs mode.
1151*2718b568SThomas Cort * This should really be broken up into 3 functions so users can bind
1152*2718b568SThomas Cort * to the one they want.
1153*2718b568SThomas Cort */
1154*2718b568SThomas Cort if (xcp == xbuf) {
1155*2718b568SThomas Cort x_e_putc(BEL);
1156*2718b568SThomas Cort return KSTD;
1157*2718b568SThomas Cort } else if (xcp == xep || Flag(FGMACS)) {
1158*2718b568SThomas Cort if (xcp - xbuf == 1) {
1159*2718b568SThomas Cort x_e_putc(BEL);
1160*2718b568SThomas Cort return KSTD;
1161*2718b568SThomas Cort }
1162*2718b568SThomas Cort /* Gosling/Unipress emacs style: Swap two characters before the
1163*2718b568SThomas Cort * cursor, do not change cursor position
1164*2718b568SThomas Cort */
1165*2718b568SThomas Cort x_bs(xcp[-1]);
1166*2718b568SThomas Cort x_bs(xcp[-2]);
1167*2718b568SThomas Cort x_zotc(xcp[-1]);
1168*2718b568SThomas Cort x_zotc(xcp[-2]);
1169*2718b568SThomas Cort tmp = xcp[-1];
1170*2718b568SThomas Cort xcp[-1] = xcp[-2];
1171*2718b568SThomas Cort xcp[-2] = tmp;
1172*2718b568SThomas Cort } else {
1173*2718b568SThomas Cort /* GNU emacs style: Swap the characters before and under the
1174*2718b568SThomas Cort * cursor, move cursor position along one.
1175*2718b568SThomas Cort */
1176*2718b568SThomas Cort x_bs(xcp[-1]);
1177*2718b568SThomas Cort x_zotc(xcp[0]);
1178*2718b568SThomas Cort x_zotc(xcp[-1]);
1179*2718b568SThomas Cort tmp = xcp[-1];
1180*2718b568SThomas Cort xcp[-1] = xcp[0];
1181*2718b568SThomas Cort xcp[0] = tmp;
1182*2718b568SThomas Cort x_bs(xcp[0]);
1183*2718b568SThomas Cort x_goto(xcp + 1);
1184*2718b568SThomas Cort }
1185*2718b568SThomas Cort return KSTD;
1186*2718b568SThomas Cort }
1187*2718b568SThomas Cort
1188*2718b568SThomas Cort static int
x_literal(c)1189*2718b568SThomas Cort x_literal(c)
1190*2718b568SThomas Cort int c;
1191*2718b568SThomas Cort {
1192*2718b568SThomas Cort x_curprefix = -1;
1193*2718b568SThomas Cort return KSTD;
1194*2718b568SThomas Cort }
1195*2718b568SThomas Cort
1196*2718b568SThomas Cort static int
x_meta1(c)1197*2718b568SThomas Cort x_meta1(c)
1198*2718b568SThomas Cort int c;
1199*2718b568SThomas Cort {
1200*2718b568SThomas Cort x_curprefix = 1;
1201*2718b568SThomas Cort return KSTD;
1202*2718b568SThomas Cort }
1203*2718b568SThomas Cort
1204*2718b568SThomas Cort static int
x_meta2(c)1205*2718b568SThomas Cort x_meta2(c)
1206*2718b568SThomas Cort int c;
1207*2718b568SThomas Cort {
1208*2718b568SThomas Cort x_curprefix = 2;
1209*2718b568SThomas Cort return KSTD;
1210*2718b568SThomas Cort }
1211*2718b568SThomas Cort
1212*2718b568SThomas Cort #ifdef OS2
1213*2718b568SThomas Cort static int
x_meta3(c)1214*2718b568SThomas Cort x_meta3(c)
1215*2718b568SThomas Cort int c;
1216*2718b568SThomas Cort {
1217*2718b568SThomas Cort x_curprefix = 3;
1218*2718b568SThomas Cort return KSTD;
1219*2718b568SThomas Cort }
1220*2718b568SThomas Cort #endif /* OS2 */
1221*2718b568SThomas Cort
1222*2718b568SThomas Cort static int
x_kill(c)1223*2718b568SThomas Cort x_kill(c)
1224*2718b568SThomas Cort int c;
1225*2718b568SThomas Cort {
1226*2718b568SThomas Cort int col = xcp - xbuf;
1227*2718b568SThomas Cort int lastcol = xep - xbuf;
1228*2718b568SThomas Cort int ndel;
1229*2718b568SThomas Cort
1230*2718b568SThomas Cort if (x_arg_defaulted)
1231*2718b568SThomas Cort x_arg = lastcol;
1232*2718b568SThomas Cort else if (x_arg > lastcol)
1233*2718b568SThomas Cort x_arg = lastcol;
1234*2718b568SThomas Cort ndel = x_arg - col;
1235*2718b568SThomas Cort if (ndel < 0) {
1236*2718b568SThomas Cort x_goto(xbuf + x_arg);
1237*2718b568SThomas Cort ndel = -ndel;
1238*2718b568SThomas Cort }
1239*2718b568SThomas Cort x_delete(ndel, TRUE);
1240*2718b568SThomas Cort return KSTD;
1241*2718b568SThomas Cort }
1242*2718b568SThomas Cort
1243*2718b568SThomas Cort static void
x_push(nchars)1244*2718b568SThomas Cort x_push(nchars)
1245*2718b568SThomas Cort int nchars;
1246*2718b568SThomas Cort {
1247*2718b568SThomas Cort char *cp = str_nsave(xcp, nchars, AEDIT);
1248*2718b568SThomas Cort if (killstack[killsp])
1249*2718b568SThomas Cort afree((void *)killstack[killsp], AEDIT);
1250*2718b568SThomas Cort killstack[killsp] = cp;
1251*2718b568SThomas Cort killsp = (killsp + 1) % KILLSIZE;
1252*2718b568SThomas Cort }
1253*2718b568SThomas Cort
1254*2718b568SThomas Cort static int
x_yank(c)1255*2718b568SThomas Cort x_yank(c)
1256*2718b568SThomas Cort int c;
1257*2718b568SThomas Cort {
1258*2718b568SThomas Cort if (killsp == 0)
1259*2718b568SThomas Cort killtp = KILLSIZE;
1260*2718b568SThomas Cort else
1261*2718b568SThomas Cort killtp = killsp;
1262*2718b568SThomas Cort killtp--;
1263*2718b568SThomas Cort if (killstack[killtp] == 0) {
1264*2718b568SThomas Cort x_e_puts("\nnothing to yank");
1265*2718b568SThomas Cort x_redraw(-1);
1266*2718b568SThomas Cort return KSTD;
1267*2718b568SThomas Cort }
1268*2718b568SThomas Cort xmp = xcp;
1269*2718b568SThomas Cort x_ins(killstack[killtp]);
1270*2718b568SThomas Cort return KSTD;
1271*2718b568SThomas Cort }
1272*2718b568SThomas Cort
1273*2718b568SThomas Cort static int
x_meta_yank(c)1274*2718b568SThomas Cort x_meta_yank(c)
1275*2718b568SThomas Cort int c;
1276*2718b568SThomas Cort {
1277*2718b568SThomas Cort int len;
1278*2718b568SThomas Cort if ((x_last_command != XFUNC_yank && x_last_command != XFUNC_meta_yank)
1279*2718b568SThomas Cort || killstack[killtp] == 0) {
1280*2718b568SThomas Cort killtp = killsp;
1281*2718b568SThomas Cort x_e_puts("\nyank something first");
1282*2718b568SThomas Cort x_redraw(-1);
1283*2718b568SThomas Cort return KSTD;
1284*2718b568SThomas Cort }
1285*2718b568SThomas Cort len = strlen(killstack[killtp]);
1286*2718b568SThomas Cort x_goto(xcp - len);
1287*2718b568SThomas Cort x_delete(len, FALSE);
1288*2718b568SThomas Cort do {
1289*2718b568SThomas Cort if (killtp == 0)
1290*2718b568SThomas Cort killtp = KILLSIZE - 1;
1291*2718b568SThomas Cort else
1292*2718b568SThomas Cort killtp--;
1293*2718b568SThomas Cort } while (killstack[killtp] == 0);
1294*2718b568SThomas Cort x_ins(killstack[killtp]);
1295*2718b568SThomas Cort return KSTD;
1296*2718b568SThomas Cort }
1297*2718b568SThomas Cort
1298*2718b568SThomas Cort static int
x_abort(c)1299*2718b568SThomas Cort x_abort(c)
1300*2718b568SThomas Cort int c;
1301*2718b568SThomas Cort {
1302*2718b568SThomas Cort /* x_zotc(c); */
1303*2718b568SThomas Cort xlp = xep = xcp = xbp = xbuf;
1304*2718b568SThomas Cort xlp_valid = TRUE;
1305*2718b568SThomas Cort *xcp = 0;
1306*2718b568SThomas Cort return KINTR;
1307*2718b568SThomas Cort }
1308*2718b568SThomas Cort
1309*2718b568SThomas Cort static int
x_error(c)1310*2718b568SThomas Cort x_error(c)
1311*2718b568SThomas Cort int c;
1312*2718b568SThomas Cort {
1313*2718b568SThomas Cort x_e_putc(BEL);
1314*2718b568SThomas Cort return KSTD;
1315*2718b568SThomas Cort }
1316*2718b568SThomas Cort
1317*2718b568SThomas Cort static int
x_stuffreset(c)1318*2718b568SThomas Cort x_stuffreset(c)
1319*2718b568SThomas Cort int c;
1320*2718b568SThomas Cort {
1321*2718b568SThomas Cort #ifdef TIOCSTI
1322*2718b568SThomas Cort (void)x_stuff(c);
1323*2718b568SThomas Cort return KINTR;
1324*2718b568SThomas Cort #else
1325*2718b568SThomas Cort x_zotc(c);
1326*2718b568SThomas Cort xlp = xcp = xep = xbp = xbuf;
1327*2718b568SThomas Cort xlp_valid = TRUE;
1328*2718b568SThomas Cort *xcp = 0;
1329*2718b568SThomas Cort x_redraw(-1);
1330*2718b568SThomas Cort return KSTD;
1331*2718b568SThomas Cort #endif
1332*2718b568SThomas Cort }
1333*2718b568SThomas Cort
1334*2718b568SThomas Cort static int
x_stuff(c)1335*2718b568SThomas Cort x_stuff(c)
1336*2718b568SThomas Cort int c;
1337*2718b568SThomas Cort {
1338*2718b568SThomas Cort #if 0 || defined TIOCSTI
1339*2718b568SThomas Cort char ch = c;
1340*2718b568SThomas Cort bool_t savmode = x_mode(FALSE);
1341*2718b568SThomas Cort
1342*2718b568SThomas Cort (void)ioctl(TTY, TIOCSTI, &ch);
1343*2718b568SThomas Cort (void)x_mode(savmode);
1344*2718b568SThomas Cort x_redraw(-1);
1345*2718b568SThomas Cort #endif
1346*2718b568SThomas Cort return KSTD;
1347*2718b568SThomas Cort }
1348*2718b568SThomas Cort
1349*2718b568SThomas Cort static char *
x_mapin(cp,area)1350*2718b568SThomas Cort x_mapin(cp, area)
1351*2718b568SThomas Cort const char *cp;
1352*2718b568SThomas Cort Area *area;
1353*2718b568SThomas Cort {
1354*2718b568SThomas Cort char *new, *op;
1355*2718b568SThomas Cort
1356*2718b568SThomas Cort op = new = str_save(cp, area);
1357*2718b568SThomas Cort while (*cp) {
1358*2718b568SThomas Cort /* XXX -- should handle \^ escape? */
1359*2718b568SThomas Cort if (*cp == '^') {
1360*2718b568SThomas Cort cp++;
1361*2718b568SThomas Cort #ifdef OS2
1362*2718b568SThomas Cort if (*cp == '0') /* To define function keys */
1363*2718b568SThomas Cort *op++ = 0xE0;
1364*2718b568SThomas Cort else
1365*2718b568SThomas Cort #endif /* OS2 */
1366*2718b568SThomas Cort if (*cp >= '?') /* includes '?'; ASCII */
1367*2718b568SThomas Cort *op++ = CTRL(*cp);
1368*2718b568SThomas Cort else {
1369*2718b568SThomas Cort *op++ = '^';
1370*2718b568SThomas Cort cp--;
1371*2718b568SThomas Cort }
1372*2718b568SThomas Cort } else
1373*2718b568SThomas Cort *op++ = *cp;
1374*2718b568SThomas Cort cp++;
1375*2718b568SThomas Cort }
1376*2718b568SThomas Cort *op = '\0';
1377*2718b568SThomas Cort
1378*2718b568SThomas Cort return new;
1379*2718b568SThomas Cort }
1380*2718b568SThomas Cort
1381*2718b568SThomas Cort static char *
x_mapout(c)1382*2718b568SThomas Cort x_mapout(c)
1383*2718b568SThomas Cort int c;
1384*2718b568SThomas Cort {
1385*2718b568SThomas Cort static char buf[8];
1386*2718b568SThomas Cort register char *p = buf;
1387*2718b568SThomas Cort
1388*2718b568SThomas Cort #ifdef OS2
1389*2718b568SThomas Cort if (c == 0xE0) {
1390*2718b568SThomas Cort *p++ = '^';
1391*2718b568SThomas Cort *p++ = '0';
1392*2718b568SThomas Cort } else
1393*2718b568SThomas Cort #endif /* OS2 */
1394*2718b568SThomas Cort if (iscntrl((unsigned char)c)) {
1395*2718b568SThomas Cort *p++ = '^';
1396*2718b568SThomas Cort *p++ = UNCTRL(c);
1397*2718b568SThomas Cort } else
1398*2718b568SThomas Cort *p++ = c;
1399*2718b568SThomas Cort *p = 0;
1400*2718b568SThomas Cort return buf;
1401*2718b568SThomas Cort }
1402*2718b568SThomas Cort
1403*2718b568SThomas Cort static void
x_print(prefix,key)1404*2718b568SThomas Cort x_print(prefix, key)
1405*2718b568SThomas Cort int prefix, key;
1406*2718b568SThomas Cort {
1407*2718b568SThomas Cort if (prefix == 1)
1408*2718b568SThomas Cort shprintf("%s", x_mapout(x_prefix1));
1409*2718b568SThomas Cort if (prefix == 2)
1410*2718b568SThomas Cort shprintf("%s", x_mapout(x_prefix2));
1411*2718b568SThomas Cort #ifdef OS2
1412*2718b568SThomas Cort if (prefix == 3)
1413*2718b568SThomas Cort shprintf("%s", x_mapout(x_prefix3));
1414*2718b568SThomas Cort #endif /* OS2 */
1415*2718b568SThomas Cort shprintf("%s = ", x_mapout(key));
1416*2718b568SThomas Cort if (x_tab[prefix][key] != XFUNC_ins_string)
1417*2718b568SThomas Cort shprintf("%s\n", x_ftab[x_tab[prefix][key]].xf_name);
1418*2718b568SThomas Cort else
1419*2718b568SThomas Cort shprintf("'%s'\n", x_atab[prefix][key]);
1420*2718b568SThomas Cort }
1421*2718b568SThomas Cort
1422*2718b568SThomas Cort int
x_bind(a1,a2,macro,list)1423*2718b568SThomas Cort x_bind(a1, a2, macro, list)
1424*2718b568SThomas Cort const char *a1, *a2;
1425*2718b568SThomas Cort int macro; /* bind -m */
1426*2718b568SThomas Cort int list; /* bind -l */
1427*2718b568SThomas Cort {
1428*2718b568SThomas Cort Findex f;
1429*2718b568SThomas Cort int prefix, key;
1430*2718b568SThomas Cort char *sp = NULL;
1431*2718b568SThomas Cort char *m1, *m2;
1432*2718b568SThomas Cort
1433*2718b568SThomas Cort if (x_tab == NULL) {
1434*2718b568SThomas Cort bi_errorf("cannot bind, not a tty");
1435*2718b568SThomas Cort return 1;
1436*2718b568SThomas Cort }
1437*2718b568SThomas Cort
1438*2718b568SThomas Cort /* List function names */
1439*2718b568SThomas Cort if (list) {
1440*2718b568SThomas Cort for (f = 0; f < NELEM(x_ftab); f++)
1441*2718b568SThomas Cort if (x_ftab[f].xf_name
1442*2718b568SThomas Cort && !(x_ftab[f].xf_flags & XF_NOBIND))
1443*2718b568SThomas Cort shprintf("%s\n", x_ftab[f].xf_name);
1444*2718b568SThomas Cort return 0;
1445*2718b568SThomas Cort }
1446*2718b568SThomas Cort
1447*2718b568SThomas Cort if (a1 == NULL) {
1448*2718b568SThomas Cort for (prefix = 0; prefix < X_NTABS; prefix++)
1449*2718b568SThomas Cort for (key = 0; key < X_TABSZ; key++) {
1450*2718b568SThomas Cort f = x_tab[prefix][key];
1451*2718b568SThomas Cort if (f == XFUNC_insert || f == XFUNC_error
1452*2718b568SThomas Cort || (macro && f != XFUNC_ins_string))
1453*2718b568SThomas Cort continue;
1454*2718b568SThomas Cort x_print(prefix, key);
1455*2718b568SThomas Cort }
1456*2718b568SThomas Cort return 0;
1457*2718b568SThomas Cort }
1458*2718b568SThomas Cort
1459*2718b568SThomas Cort m2 = m1 = x_mapin(a1, ATEMP);
1460*2718b568SThomas Cort prefix = key = 0;
1461*2718b568SThomas Cort for (;; m1++) {
1462*2718b568SThomas Cort key = *m1 & CHARMASK;
1463*2718b568SThomas Cort if (x_tab[prefix][key] == XFUNC_meta1)
1464*2718b568SThomas Cort prefix = 1;
1465*2718b568SThomas Cort else if (x_tab[prefix][key] == XFUNC_meta2)
1466*2718b568SThomas Cort prefix = 2;
1467*2718b568SThomas Cort #ifdef OS2
1468*2718b568SThomas Cort else if (x_tab[prefix][key] == XFUNC_meta3)
1469*2718b568SThomas Cort prefix = 3;
1470*2718b568SThomas Cort #endif /* OS2 */
1471*2718b568SThomas Cort else
1472*2718b568SThomas Cort break;
1473*2718b568SThomas Cort }
1474*2718b568SThomas Cort afree(m2, ATEMP);
1475*2718b568SThomas Cort
1476*2718b568SThomas Cort if (a2 == NULL) {
1477*2718b568SThomas Cort x_print(prefix, key);
1478*2718b568SThomas Cort return 0;
1479*2718b568SThomas Cort }
1480*2718b568SThomas Cort
1481*2718b568SThomas Cort if (*a2 == 0)
1482*2718b568SThomas Cort f = XFUNC_insert;
1483*2718b568SThomas Cort else if (!macro) {
1484*2718b568SThomas Cort for (f = 0; f < NELEM(x_ftab); f++)
1485*2718b568SThomas Cort if (x_ftab[f].xf_name
1486*2718b568SThomas Cort && strcmp(x_ftab[f].xf_name, a2) == 0)
1487*2718b568SThomas Cort break;
1488*2718b568SThomas Cort if (f == NELEM(x_ftab) || x_ftab[f].xf_flags & XF_NOBIND) {
1489*2718b568SThomas Cort bi_errorf("%s: no such function", a2);
1490*2718b568SThomas Cort return 1;
1491*2718b568SThomas Cort }
1492*2718b568SThomas Cort #if 0 /* This breaks the bind commands that map arrow keys */
1493*2718b568SThomas Cort if (f == XFUNC_meta1)
1494*2718b568SThomas Cort x_prefix1 = key;
1495*2718b568SThomas Cort if (f == XFUNC_meta2)
1496*2718b568SThomas Cort x_prefix2 = key;
1497*2718b568SThomas Cort #endif /* 0 */
1498*2718b568SThomas Cort } else {
1499*2718b568SThomas Cort f = XFUNC_ins_string;
1500*2718b568SThomas Cort sp = x_mapin(a2, AEDIT);
1501*2718b568SThomas Cort }
1502*2718b568SThomas Cort
1503*2718b568SThomas Cort if (x_tab[prefix][key] == XFUNC_ins_string && x_atab[prefix][key])
1504*2718b568SThomas Cort afree((void *)x_atab[prefix][key], AEDIT);
1505*2718b568SThomas Cort x_tab[prefix][key] = f;
1506*2718b568SThomas Cort x_atab[prefix][key] = sp;
1507*2718b568SThomas Cort
1508*2718b568SThomas Cort /* Track what the user has bound so x_emacs_keys() won't toast things */
1509*2718b568SThomas Cort if (f == XFUNC_insert)
1510*2718b568SThomas Cort x_bound[(prefix * X_TABSZ + key) / 8] &=
1511*2718b568SThomas Cort ~(1 << ((prefix * X_TABSZ + key) % 8));
1512*2718b568SThomas Cort else
1513*2718b568SThomas Cort x_bound[(prefix * X_TABSZ + key) / 8] |=
1514*2718b568SThomas Cort (1 << ((prefix * X_TABSZ + key) % 8));
1515*2718b568SThomas Cort
1516*2718b568SThomas Cort return 0;
1517*2718b568SThomas Cort }
1518*2718b568SThomas Cort
1519*2718b568SThomas Cort void
x_init_emacs()1520*2718b568SThomas Cort x_init_emacs()
1521*2718b568SThomas Cort {
1522*2718b568SThomas Cort size_t i;
1523*2718b568SThomas Cort register int j;
1524*2718b568SThomas Cort char *locale;
1525*2718b568SThomas Cort
1526*2718b568SThomas Cort ainit(AEDIT);
1527*2718b568SThomas Cort x_nextcmd = -1;
1528*2718b568SThomas Cort
1529*2718b568SThomas Cort x_tab = (Findex (*)[X_TABSZ]) alloc(sizeofN(*x_tab, X_NTABS), AEDIT);
1530*2718b568SThomas Cort for (j = 0; j < X_TABSZ; j++)
1531*2718b568SThomas Cort x_tab[0][j] = XFUNC_insert;
1532*2718b568SThomas Cort for (i = 1; i < X_NTABS; i++)
1533*2718b568SThomas Cort for (j = 0; j < X_TABSZ; j++)
1534*2718b568SThomas Cort x_tab[i][j] = XFUNC_error;
1535*2718b568SThomas Cort for (i = 0; i < NELEM(x_defbindings); i++)
1536*2718b568SThomas Cort x_tab[(unsigned char)x_defbindings[i].xdb_tab][x_defbindings[i].xdb_char]
1537*2718b568SThomas Cort = x_defbindings[i].xdb_func;
1538*2718b568SThomas Cort
1539*2718b568SThomas Cort x_atab = (char *(*)[X_TABSZ]) alloc(sizeofN(*x_atab, X_NTABS), AEDIT);
1540*2718b568SThomas Cort for (i = 1; i < X_NTABS; i++)
1541*2718b568SThomas Cort for (j = 0; j < X_TABSZ; j++)
1542*2718b568SThomas Cort x_atab[i][j] = NULL;
1543*2718b568SThomas Cort
1544*2718b568SThomas Cort /* Determine if we can translate meta key or use 8-bit AscII
1545*2718b568SThomas Cort * XXX - It would be nice if there was a locale attribute to
1546*2718b568SThomas Cort * determine if the locale is 7-bit or not.
1547*2718b568SThomas Cort */
1548*2718b568SThomas Cort locale = setlocale(LC_CTYPE, NULL);
1549*2718b568SThomas Cort if (locale == NULL || !strcmp(locale, "C") || !strcmp(locale, "POSIX"))
1550*2718b568SThomas Cort Flag(FEMACSUSEMETA) = 0;
1551*2718b568SThomas Cort }
1552*2718b568SThomas Cort
1553*2718b568SThomas Cort static void bind_if_not_bound(int p, int k, int func);
1554*2718b568SThomas Cort
1555*2718b568SThomas Cort static void
bind_if_not_bound(p,k,func)1556*2718b568SThomas Cort bind_if_not_bound(p, k, func)
1557*2718b568SThomas Cort int p, k;
1558*2718b568SThomas Cort int func;
1559*2718b568SThomas Cort {
1560*2718b568SThomas Cort /* Has user already bound this key? If so, don't override it */
1561*2718b568SThomas Cort if (x_bound[((p) * X_TABSZ + (k)) / 8]
1562*2718b568SThomas Cort & (1 << (((p) * X_TABSZ + (k)) % 8)))
1563*2718b568SThomas Cort return;
1564*2718b568SThomas Cort
1565*2718b568SThomas Cort x_tab[p][k] = func;
1566*2718b568SThomas Cort }
1567*2718b568SThomas Cort
1568*2718b568SThomas Cort void
x_emacs_keys(ec)1569*2718b568SThomas Cort x_emacs_keys(ec)
1570*2718b568SThomas Cort X_chars *ec;
1571*2718b568SThomas Cort {
1572*2718b568SThomas Cort if (ec->erase >= 0) {
1573*2718b568SThomas Cort bind_if_not_bound(0, ec->erase, XFUNC_del_back);
1574*2718b568SThomas Cort bind_if_not_bound(1, ec->erase, XFUNC_del_bword);
1575*2718b568SThomas Cort }
1576*2718b568SThomas Cort if (ec->kill >= 0)
1577*2718b568SThomas Cort bind_if_not_bound(0, ec->kill, XFUNC_del_line);
1578*2718b568SThomas Cort if (ec->werase >= 0)
1579*2718b568SThomas Cort bind_if_not_bound(0, ec->werase, XFUNC_del_bword);
1580*2718b568SThomas Cort if (ec->intr >= 0)
1581*2718b568SThomas Cort bind_if_not_bound(0, ec->intr, XFUNC_abort);
1582*2718b568SThomas Cort if (ec->quit >= 0)
1583*2718b568SThomas Cort bind_if_not_bound(0, ec->quit, XFUNC_noop);
1584*2718b568SThomas Cort }
1585*2718b568SThomas Cort
1586*2718b568SThomas Cort static int
x_set_mark(c)1587*2718b568SThomas Cort x_set_mark(c)
1588*2718b568SThomas Cort int c;
1589*2718b568SThomas Cort {
1590*2718b568SThomas Cort xmp = xcp;
1591*2718b568SThomas Cort return KSTD;
1592*2718b568SThomas Cort }
1593*2718b568SThomas Cort
1594*2718b568SThomas Cort static int
x_kill_region(c)1595*2718b568SThomas Cort x_kill_region(c)
1596*2718b568SThomas Cort int c;
1597*2718b568SThomas Cort {
1598*2718b568SThomas Cort int rsize;
1599*2718b568SThomas Cort char *xr;
1600*2718b568SThomas Cort
1601*2718b568SThomas Cort if (xmp == NULL) {
1602*2718b568SThomas Cort x_e_putc(BEL);
1603*2718b568SThomas Cort return KSTD;
1604*2718b568SThomas Cort }
1605*2718b568SThomas Cort if (xmp > xcp) {
1606*2718b568SThomas Cort rsize = xmp - xcp;
1607*2718b568SThomas Cort xr = xcp;
1608*2718b568SThomas Cort } else {
1609*2718b568SThomas Cort rsize = xcp - xmp;
1610*2718b568SThomas Cort xr = xmp;
1611*2718b568SThomas Cort }
1612*2718b568SThomas Cort x_goto(xr);
1613*2718b568SThomas Cort x_delete(rsize, TRUE);
1614*2718b568SThomas Cort xmp = xr;
1615*2718b568SThomas Cort return KSTD;
1616*2718b568SThomas Cort }
1617*2718b568SThomas Cort
1618*2718b568SThomas Cort static int
x_xchg_point_mark(c)1619*2718b568SThomas Cort x_xchg_point_mark(c)
1620*2718b568SThomas Cort int c;
1621*2718b568SThomas Cort {
1622*2718b568SThomas Cort char *tmp;
1623*2718b568SThomas Cort
1624*2718b568SThomas Cort if (xmp == NULL) {
1625*2718b568SThomas Cort x_e_putc(BEL);
1626*2718b568SThomas Cort return KSTD;
1627*2718b568SThomas Cort }
1628*2718b568SThomas Cort tmp = xmp;
1629*2718b568SThomas Cort xmp = xcp;
1630*2718b568SThomas Cort x_goto( tmp );
1631*2718b568SThomas Cort return KSTD;
1632*2718b568SThomas Cort }
1633*2718b568SThomas Cort
1634*2718b568SThomas Cort static int
x_version(c)1635*2718b568SThomas Cort x_version(c)
1636*2718b568SThomas Cort int c;
1637*2718b568SThomas Cort {
1638*2718b568SThomas Cort char *o_xbuf = xbuf, *o_xend = xend;
1639*2718b568SThomas Cort char *o_xbp = xbp, *o_xep = xep, *o_xcp = xcp;
1640*2718b568SThomas Cort int lim = x_lastcp() - xbp;
1641*2718b568SThomas Cort
1642*2718b568SThomas Cort xbuf = xbp = xcp = ksh_version + 4;
1643*2718b568SThomas Cort xend = xep = ksh_version + 4 + strlen(ksh_version + 4);
1644*2718b568SThomas Cort x_redraw(lim);
1645*2718b568SThomas Cort x_flush();
1646*2718b568SThomas Cort
1647*2718b568SThomas Cort c = x_e_getc();
1648*2718b568SThomas Cort xbuf = o_xbuf;
1649*2718b568SThomas Cort xend = o_xend;
1650*2718b568SThomas Cort xbp = o_xbp;
1651*2718b568SThomas Cort xep = o_xep;
1652*2718b568SThomas Cort xcp = o_xcp;
1653*2718b568SThomas Cort x_redraw(strlen(ksh_version));
1654*2718b568SThomas Cort
1655*2718b568SThomas Cort if (c < 0)
1656*2718b568SThomas Cort return KSTD;
1657*2718b568SThomas Cort /* This is what at&t ksh seems to do... Very bizarre */
1658*2718b568SThomas Cort if (c != ' ')
1659*2718b568SThomas Cort x_e_ungetc(c);
1660*2718b568SThomas Cort
1661*2718b568SThomas Cort return KSTD;
1662*2718b568SThomas Cort }
1663*2718b568SThomas Cort
1664*2718b568SThomas Cort static int
x_noop(c)1665*2718b568SThomas Cort x_noop(c)
1666*2718b568SThomas Cort int c;
1667*2718b568SThomas Cort {
1668*2718b568SThomas Cort return KSTD;
1669*2718b568SThomas Cort }
1670*2718b568SThomas Cort
1671*2718b568SThomas Cort #ifdef SILLY
1672*2718b568SThomas Cort static int
x_game_of_life(c)1673*2718b568SThomas Cort x_game_of_life(c)
1674*2718b568SThomas Cort int c;
1675*2718b568SThomas Cort {
1676*2718b568SThomas Cort char newbuf [256+1];
1677*2718b568SThomas Cort register char *ip, *op;
1678*2718b568SThomas Cort int i, len;
1679*2718b568SThomas Cort
1680*2718b568SThomas Cort i = xep - xbuf;
1681*2718b568SThomas Cort *xep = 0;
1682*2718b568SThomas Cort len = x_size_str(xbuf);
1683*2718b568SThomas Cort xcp = xbp = xbuf;
1684*2718b568SThomas Cort memmove(newbuf+1, xbuf, i);
1685*2718b568SThomas Cort newbuf[0] = 'A';
1686*2718b568SThomas Cort newbuf[i] = 'A';
1687*2718b568SThomas Cort for (ip = newbuf+1, op = xbuf; --i >= 0; ip++, op++) {
1688*2718b568SThomas Cort /* Empty space */
1689*2718b568SThomas Cort if (*ip < '@' || *ip == '_' || *ip == 0x7F) {
1690*2718b568SThomas Cort /* Two adults, make whoopee */
1691*2718b568SThomas Cort if (ip[-1] < '_' && ip[1] < '_') {
1692*2718b568SThomas Cort /* Make kid look like parents. */
1693*2718b568SThomas Cort *op = '`' + ((ip[-1] + ip[1])/2)%32;
1694*2718b568SThomas Cort if (*op == 0x7F) /* Birth defect */
1695*2718b568SThomas Cort *op = '`';
1696*2718b568SThomas Cort }
1697*2718b568SThomas Cort else
1698*2718b568SThomas Cort *op = ' '; /* nothing happens */
1699*2718b568SThomas Cort continue;
1700*2718b568SThomas Cort }
1701*2718b568SThomas Cort /* Child */
1702*2718b568SThomas Cort if (*ip > '`') {
1703*2718b568SThomas Cort /* All alone, dies */
1704*2718b568SThomas Cort if (ip[-1] == ' ' && ip[1] == ' ')
1705*2718b568SThomas Cort *op = ' ';
1706*2718b568SThomas Cort else /* Gets older */
1707*2718b568SThomas Cort *op = *ip-'`'+'@';
1708*2718b568SThomas Cort continue;
1709*2718b568SThomas Cort }
1710*2718b568SThomas Cort /* Adult */
1711*2718b568SThomas Cort /* Overcrowded, dies */
1712*2718b568SThomas Cort if (ip[-1] >= '@' && ip[1] >= '@') {
1713*2718b568SThomas Cort *op = ' ';
1714*2718b568SThomas Cort continue;
1715*2718b568SThomas Cort }
1716*2718b568SThomas Cort *op = *ip;
1717*2718b568SThomas Cort }
1718*2718b568SThomas Cort *op = 0;
1719*2718b568SThomas Cort x_redraw(len);
1720*2718b568SThomas Cort return KSTD;
1721*2718b568SThomas Cort }
1722*2718b568SThomas Cort #endif
1723*2718b568SThomas Cort
1724*2718b568SThomas Cort /*
1725*2718b568SThomas Cort * File/command name completion routines
1726*2718b568SThomas Cort */
1727*2718b568SThomas Cort
1728*2718b568SThomas Cort
1729*2718b568SThomas Cort static int
x_comp_comm(c)1730*2718b568SThomas Cort x_comp_comm(c)
1731*2718b568SThomas Cort int c;
1732*2718b568SThomas Cort {
1733*2718b568SThomas Cort do_complete(XCF_COMMAND, CT_COMPLETE);
1734*2718b568SThomas Cort return KSTD;
1735*2718b568SThomas Cort }
1736*2718b568SThomas Cort static int
x_list_comm(c)1737*2718b568SThomas Cort x_list_comm(c)
1738*2718b568SThomas Cort int c;
1739*2718b568SThomas Cort {
1740*2718b568SThomas Cort do_complete(XCF_COMMAND, CT_LIST);
1741*2718b568SThomas Cort return KSTD;
1742*2718b568SThomas Cort }
1743*2718b568SThomas Cort static int
x_complete(c)1744*2718b568SThomas Cort x_complete(c)
1745*2718b568SThomas Cort int c;
1746*2718b568SThomas Cort {
1747*2718b568SThomas Cort do_complete(XCF_COMMAND_FILE, CT_COMPLETE);
1748*2718b568SThomas Cort return KSTD;
1749*2718b568SThomas Cort }
1750*2718b568SThomas Cort static int
x_enumerate(c)1751*2718b568SThomas Cort x_enumerate(c)
1752*2718b568SThomas Cort int c;
1753*2718b568SThomas Cort {
1754*2718b568SThomas Cort do_complete(XCF_COMMAND_FILE, CT_LIST);
1755*2718b568SThomas Cort return KSTD;
1756*2718b568SThomas Cort }
1757*2718b568SThomas Cort static int
x_comp_file(c)1758*2718b568SThomas Cort x_comp_file(c)
1759*2718b568SThomas Cort int c;
1760*2718b568SThomas Cort {
1761*2718b568SThomas Cort do_complete(XCF_FILE, CT_COMPLETE);
1762*2718b568SThomas Cort return KSTD;
1763*2718b568SThomas Cort }
1764*2718b568SThomas Cort static int
x_list_file(c)1765*2718b568SThomas Cort x_list_file(c)
1766*2718b568SThomas Cort int c;
1767*2718b568SThomas Cort {
1768*2718b568SThomas Cort do_complete(XCF_FILE, CT_LIST);
1769*2718b568SThomas Cort return KSTD;
1770*2718b568SThomas Cort }
1771*2718b568SThomas Cort static int
x_comp_list(c)1772*2718b568SThomas Cort x_comp_list(c)
1773*2718b568SThomas Cort int c;
1774*2718b568SThomas Cort {
1775*2718b568SThomas Cort do_complete(XCF_COMMAND_FILE, CT_COMPLIST);
1776*2718b568SThomas Cort return KSTD;
1777*2718b568SThomas Cort }
1778*2718b568SThomas Cort static int
x_expand(c)1779*2718b568SThomas Cort x_expand(c)
1780*2718b568SThomas Cort int c;
1781*2718b568SThomas Cort {
1782*2718b568SThomas Cort char **words;
1783*2718b568SThomas Cort int nwords = 0;
1784*2718b568SThomas Cort int start, end;
1785*2718b568SThomas Cort int is_command;
1786*2718b568SThomas Cort int i;
1787*2718b568SThomas Cort
1788*2718b568SThomas Cort nwords = x_cf_glob(XCF_FILE,
1789*2718b568SThomas Cort xbuf, xep - xbuf, xcp - xbuf,
1790*2718b568SThomas Cort &start, &end, &words, &is_command);
1791*2718b568SThomas Cort
1792*2718b568SThomas Cort if (nwords == 0) {
1793*2718b568SThomas Cort x_e_putc(BEL);
1794*2718b568SThomas Cort return KSTD;
1795*2718b568SThomas Cort }
1796*2718b568SThomas Cort
1797*2718b568SThomas Cort x_goto(xbuf + start);
1798*2718b568SThomas Cort x_delete(end - start, FALSE);
1799*2718b568SThomas Cort for (i = 0; i < nwords;) {
1800*2718b568SThomas Cort if (x_escape(words[i], strlen(words[i]), x_emacs_putbuf) < 0 ||
1801*2718b568SThomas Cort (++i < nwords && x_ins(space) < 0))
1802*2718b568SThomas Cort {
1803*2718b568SThomas Cort x_e_putc(BEL);
1804*2718b568SThomas Cort return KSTD;
1805*2718b568SThomas Cort }
1806*2718b568SThomas Cort }
1807*2718b568SThomas Cort x_adjust();
1808*2718b568SThomas Cort
1809*2718b568SThomas Cort return KSTD;
1810*2718b568SThomas Cort }
1811*2718b568SThomas Cort
1812*2718b568SThomas Cort /* type == 0 for list, 1 for complete and 2 for complete-list */
1813*2718b568SThomas Cort static void
do_complete(flags,type)1814*2718b568SThomas Cort do_complete(flags, type)
1815*2718b568SThomas Cort int flags; /* XCF_{COMMAND,FILE,COMMAND_FILE} */
1816*2718b568SThomas Cort Comp_type type;
1817*2718b568SThomas Cort {
1818*2718b568SThomas Cort char **words;
1819*2718b568SThomas Cort int nwords;
1820*2718b568SThomas Cort int start, end, nlen, olen;
1821*2718b568SThomas Cort int is_command;
1822*2718b568SThomas Cort int completed = 0;
1823*2718b568SThomas Cort
1824*2718b568SThomas Cort nwords = x_cf_glob(flags, xbuf, xep - xbuf, xcp - xbuf,
1825*2718b568SThomas Cort &start, &end, &words, &is_command);
1826*2718b568SThomas Cort /* no match */
1827*2718b568SThomas Cort if (nwords == 0) {
1828*2718b568SThomas Cort x_e_putc(BEL);
1829*2718b568SThomas Cort return;
1830*2718b568SThomas Cort }
1831*2718b568SThomas Cort
1832*2718b568SThomas Cort if (type == CT_LIST) {
1833*2718b568SThomas Cort x_print_expansions(nwords, words, is_command);
1834*2718b568SThomas Cort x_redraw(0);
1835*2718b568SThomas Cort x_free_words(nwords, words);
1836*2718b568SThomas Cort return;
1837*2718b568SThomas Cort }
1838*2718b568SThomas Cort
1839*2718b568SThomas Cort olen = end - start;
1840*2718b568SThomas Cort nlen = x_longest_prefix(nwords, words);
1841*2718b568SThomas Cort /* complete */
1842*2718b568SThomas Cort if (nwords == 1 || nlen > olen) {
1843*2718b568SThomas Cort x_goto(xbuf + start);
1844*2718b568SThomas Cort x_delete(olen, FALSE);
1845*2718b568SThomas Cort x_escape(words[0], nlen, x_emacs_putbuf);
1846*2718b568SThomas Cort x_adjust();
1847*2718b568SThomas Cort completed = 1;
1848*2718b568SThomas Cort }
1849*2718b568SThomas Cort /* add space if single non-dir match */
1850*2718b568SThomas Cort if ((nwords == 1) && (!ISDIRSEP(words[0][nlen - 1]))) {
1851*2718b568SThomas Cort x_ins(space);
1852*2718b568SThomas Cort completed = 1;
1853*2718b568SThomas Cort }
1854*2718b568SThomas Cort
1855*2718b568SThomas Cort if (type == CT_COMPLIST && !completed) {
1856*2718b568SThomas Cort x_print_expansions(nwords, words, is_command);
1857*2718b568SThomas Cort completed = 1;
1858*2718b568SThomas Cort }
1859*2718b568SThomas Cort
1860*2718b568SThomas Cort if (completed)
1861*2718b568SThomas Cort x_redraw(0);
1862*2718b568SThomas Cort
1863*2718b568SThomas Cort x_free_words(nwords, words);
1864*2718b568SThomas Cort }
1865*2718b568SThomas Cort
1866*2718b568SThomas Cort /* NAME:
1867*2718b568SThomas Cort * x_adjust - redraw the line adjusting starting point etc.
1868*2718b568SThomas Cort *
1869*2718b568SThomas Cort * DESCRIPTION:
1870*2718b568SThomas Cort * This function is called when we have exceeded the bounds
1871*2718b568SThomas Cort * of the edit window. It increments x_adj_done so that
1872*2718b568SThomas Cort * functions like x_ins and x_delete know that we have been
1873*2718b568SThomas Cort * called and can skip the x_bs() stuff which has already
1874*2718b568SThomas Cort * been done by x_redraw.
1875*2718b568SThomas Cort *
1876*2718b568SThomas Cort * RETURN VALUE:
1877*2718b568SThomas Cort * None
1878*2718b568SThomas Cort */
1879*2718b568SThomas Cort
1880*2718b568SThomas Cort static void
x_adjust()1881*2718b568SThomas Cort x_adjust()
1882*2718b568SThomas Cort {
1883*2718b568SThomas Cort x_adj_done++; /* flag the fact that we were called. */
1884*2718b568SThomas Cort /*
1885*2718b568SThomas Cort * we had a problem if the prompt length > xx_cols / 2
1886*2718b568SThomas Cort */
1887*2718b568SThomas Cort if ((xbp = xcp - (x_displen / 2)) < xbuf)
1888*2718b568SThomas Cort xbp = xbuf;
1889*2718b568SThomas Cort xlp_valid = FALSE;
1890*2718b568SThomas Cort x_redraw(xx_cols);
1891*2718b568SThomas Cort x_flush();
1892*2718b568SThomas Cort }
1893*2718b568SThomas Cort
1894*2718b568SThomas Cort static int unget_char = -1;
1895*2718b568SThomas Cort
1896*2718b568SThomas Cort static void
x_e_ungetc(c)1897*2718b568SThomas Cort x_e_ungetc(c)
1898*2718b568SThomas Cort int c;
1899*2718b568SThomas Cort {
1900*2718b568SThomas Cort unget_char = c;
1901*2718b568SThomas Cort }
1902*2718b568SThomas Cort
1903*2718b568SThomas Cort static int
x_e_getc()1904*2718b568SThomas Cort x_e_getc()
1905*2718b568SThomas Cort {
1906*2718b568SThomas Cort int c;
1907*2718b568SThomas Cort
1908*2718b568SThomas Cort if (unget_char >= 0) {
1909*2718b568SThomas Cort c = unget_char;
1910*2718b568SThomas Cort unget_char = -1;
1911*2718b568SThomas Cort } else {
1912*2718b568SThomas Cort if (macroptr) {
1913*2718b568SThomas Cort c = (unsigned char) *macroptr++;
1914*2718b568SThomas Cort if (!*macroptr)
1915*2718b568SThomas Cort macroptr = (char *) 0;
1916*2718b568SThomas Cort } else
1917*2718b568SThomas Cort c = x_getc();
1918*2718b568SThomas Cort }
1919*2718b568SThomas Cort
1920*2718b568SThomas Cort return c <= CHARMASK ? c : (c & CHARMASK);
1921*2718b568SThomas Cort }
1922*2718b568SThomas Cort
1923*2718b568SThomas Cort static void
x_e_putc(c)1924*2718b568SThomas Cort x_e_putc(c)
1925*2718b568SThomas Cort int c;
1926*2718b568SThomas Cort {
1927*2718b568SThomas Cort if (c == '\r' || c == '\n')
1928*2718b568SThomas Cort x_col = 0;
1929*2718b568SThomas Cort if (x_col < xx_cols)
1930*2718b568SThomas Cort {
1931*2718b568SThomas Cort x_putc(c);
1932*2718b568SThomas Cort switch(c)
1933*2718b568SThomas Cort {
1934*2718b568SThomas Cort case BEL:
1935*2718b568SThomas Cort break;
1936*2718b568SThomas Cort case '\r':
1937*2718b568SThomas Cort case '\n':
1938*2718b568SThomas Cort break;
1939*2718b568SThomas Cort case '\b':
1940*2718b568SThomas Cort x_col--;
1941*2718b568SThomas Cort break;
1942*2718b568SThomas Cort default:
1943*2718b568SThomas Cort x_col++;
1944*2718b568SThomas Cort break;
1945*2718b568SThomas Cort }
1946*2718b568SThomas Cort }
1947*2718b568SThomas Cort if (x_adj_ok && (x_col < 0 || x_col >= (xx_cols - 2)))
1948*2718b568SThomas Cort {
1949*2718b568SThomas Cort x_adjust();
1950*2718b568SThomas Cort }
1951*2718b568SThomas Cort }
1952*2718b568SThomas Cort
1953*2718b568SThomas Cort #ifdef DEBUG
1954*2718b568SThomas Cort static int
x_debug_info(c)1955*2718b568SThomas Cort x_debug_info(c)
1956*2718b568SThomas Cort int c;
1957*2718b568SThomas Cort {
1958*2718b568SThomas Cort x_flush();
1959*2718b568SThomas Cort shellf("\nksh debug:\n");
1960*2718b568SThomas Cort shellf("\tx_col == %d,\t\tx_cols == %d,\tx_displen == %d\n",
1961*2718b568SThomas Cort x_col, xx_cols, x_displen);
1962*2718b568SThomas Cort shellf("\txcp == 0x%lx,\txep == 0x%lx\n", (long) xcp, (long) xep);
1963*2718b568SThomas Cort shellf("\txbp == 0x%lx,\txbuf == 0x%lx\n", (long) xbp, (long) xbuf);
1964*2718b568SThomas Cort shellf("\txlp == 0x%lx\n", (long) xlp);
1965*2718b568SThomas Cort shellf("\txlp == 0x%lx\n", (long) x_lastcp());
1966*2718b568SThomas Cort shellf(newline);
1967*2718b568SThomas Cort x_redraw(-1);
1968*2718b568SThomas Cort return 0;
1969*2718b568SThomas Cort }
1970*2718b568SThomas Cort #endif
1971*2718b568SThomas Cort
1972*2718b568SThomas Cort static void
x_e_puts(s)1973*2718b568SThomas Cort x_e_puts(s)
1974*2718b568SThomas Cort const char *s;
1975*2718b568SThomas Cort {
1976*2718b568SThomas Cort register int adj = x_adj_done;
1977*2718b568SThomas Cort
1978*2718b568SThomas Cort while (*s && adj == x_adj_done)
1979*2718b568SThomas Cort x_e_putc(*s++);
1980*2718b568SThomas Cort }
1981*2718b568SThomas Cort
1982*2718b568SThomas Cort /* NAME:
1983*2718b568SThomas Cort * x_set_arg - set an arg value for next function
1984*2718b568SThomas Cort *
1985*2718b568SThomas Cort * DESCRIPTION:
1986*2718b568SThomas Cort * This is a simple implementation of M-[0-9].
1987*2718b568SThomas Cort *
1988*2718b568SThomas Cort * RETURN VALUE:
1989*2718b568SThomas Cort * KSTD
1990*2718b568SThomas Cort */
1991*2718b568SThomas Cort
1992*2718b568SThomas Cort static int
x_set_arg(c)1993*2718b568SThomas Cort x_set_arg(c)
1994*2718b568SThomas Cort int c;
1995*2718b568SThomas Cort {
1996*2718b568SThomas Cort int n = 0;
1997*2718b568SThomas Cort int first = 1;
1998*2718b568SThomas Cort
1999*2718b568SThomas Cort c &= CHARMASK; /* strip command prefix */
2000*2718b568SThomas Cort for (; c >= 0 && isdigit(c); c = x_e_getc(), first = 0)
2001*2718b568SThomas Cort n = n * 10 + (c - '0');
2002*2718b568SThomas Cort if (c < 0 || first) {
2003*2718b568SThomas Cort x_e_putc(BEL);
2004*2718b568SThomas Cort x_arg = 1;
2005*2718b568SThomas Cort x_arg_defaulted = 1;
2006*2718b568SThomas Cort } else {
2007*2718b568SThomas Cort x_e_ungetc(c);
2008*2718b568SThomas Cort x_arg = n;
2009*2718b568SThomas Cort x_arg_defaulted = 0;
2010*2718b568SThomas Cort }
2011*2718b568SThomas Cort return KSTD;
2012*2718b568SThomas Cort }
2013*2718b568SThomas Cort
2014*2718b568SThomas Cort
2015*2718b568SThomas Cort /* Comment or uncomment the current line. */
2016*2718b568SThomas Cort static int
x_comment(c)2017*2718b568SThomas Cort x_comment(c)
2018*2718b568SThomas Cort int c;
2019*2718b568SThomas Cort {
2020*2718b568SThomas Cort int oldsize = x_size_str(xbuf);
2021*2718b568SThomas Cort int len = xep - xbuf;
2022*2718b568SThomas Cort int ret = x_do_comment(xbuf, xend - xbuf, &len);
2023*2718b568SThomas Cort
2024*2718b568SThomas Cort if (ret < 0)
2025*2718b568SThomas Cort x_e_putc(BEL);
2026*2718b568SThomas Cort else {
2027*2718b568SThomas Cort xep = xbuf + len;
2028*2718b568SThomas Cort *xep = '\0';
2029*2718b568SThomas Cort xcp = xbp = xbuf;
2030*2718b568SThomas Cort x_redraw(oldsize);
2031*2718b568SThomas Cort if (ret > 0)
2032*2718b568SThomas Cort return x_newline('\n');
2033*2718b568SThomas Cort }
2034*2718b568SThomas Cort return KSTD;
2035*2718b568SThomas Cort }
2036*2718b568SThomas Cort
2037*2718b568SThomas Cort
2038*2718b568SThomas Cort /* NAME:
2039*2718b568SThomas Cort * x_prev_histword - recover word from prev command
2040*2718b568SThomas Cort *
2041*2718b568SThomas Cort * DESCRIPTION:
2042*2718b568SThomas Cort * This function recovers the last word from the previous
2043*2718b568SThomas Cort * command and inserts it into the current edit line. If a
2044*2718b568SThomas Cort * numeric arg is supplied then the n'th word from the
2045*2718b568SThomas Cort * start of the previous command is used.
2046*2718b568SThomas Cort *
2047*2718b568SThomas Cort * Bound to M-.
2048*2718b568SThomas Cort *
2049*2718b568SThomas Cort * RETURN VALUE:
2050*2718b568SThomas Cort * KSTD
2051*2718b568SThomas Cort */
2052*2718b568SThomas Cort
2053*2718b568SThomas Cort static int
x_prev_histword(c)2054*2718b568SThomas Cort x_prev_histword(c)
2055*2718b568SThomas Cort int c;
2056*2718b568SThomas Cort {
2057*2718b568SThomas Cort register char *rcp;
2058*2718b568SThomas Cort char *cp;
2059*2718b568SThomas Cort
2060*2718b568SThomas Cort cp = *histptr;
2061*2718b568SThomas Cort if (!cp)
2062*2718b568SThomas Cort x_e_putc(BEL);
2063*2718b568SThomas Cort else if (x_arg_defaulted) {
2064*2718b568SThomas Cort rcp = &cp[strlen(cp) - 1];
2065*2718b568SThomas Cort /*
2066*2718b568SThomas Cort * ignore white-space after the last word
2067*2718b568SThomas Cort */
2068*2718b568SThomas Cort while (rcp > cp && is_cfs(*rcp))
2069*2718b568SThomas Cort rcp--;
2070*2718b568SThomas Cort while (rcp > cp && !is_cfs(*rcp))
2071*2718b568SThomas Cort rcp--;
2072*2718b568SThomas Cort if (is_cfs(*rcp))
2073*2718b568SThomas Cort rcp++;
2074*2718b568SThomas Cort x_ins(rcp);
2075*2718b568SThomas Cort } else {
2076*2718b568SThomas Cort int i;
2077*2718b568SThomas Cort
2078*2718b568SThomas Cort rcp = cp;
2079*2718b568SThomas Cort /*
2080*2718b568SThomas Cort * ignore white-space at start of line
2081*2718b568SThomas Cort */
2082*2718b568SThomas Cort while (*rcp && is_cfs(*rcp))
2083*2718b568SThomas Cort rcp++;
2084*2718b568SThomas Cort while (x_arg-- > 1)
2085*2718b568SThomas Cort {
2086*2718b568SThomas Cort while (*rcp && !is_cfs(*rcp))
2087*2718b568SThomas Cort rcp++;
2088*2718b568SThomas Cort while (*rcp && is_cfs(*rcp))
2089*2718b568SThomas Cort rcp++;
2090*2718b568SThomas Cort }
2091*2718b568SThomas Cort cp = rcp;
2092*2718b568SThomas Cort while (*rcp && !is_cfs(*rcp))
2093*2718b568SThomas Cort rcp++;
2094*2718b568SThomas Cort i = *rcp;
2095*2718b568SThomas Cort *rcp = '\0';
2096*2718b568SThomas Cort x_ins(cp);
2097*2718b568SThomas Cort *rcp = i;
2098*2718b568SThomas Cort }
2099*2718b568SThomas Cort return KSTD;
2100*2718b568SThomas Cort }
2101*2718b568SThomas Cort
2102*2718b568SThomas Cort /* Uppercase N(1) words */
2103*2718b568SThomas Cort static int
x_fold_upper(c)2104*2718b568SThomas Cort x_fold_upper(c)
2105*2718b568SThomas Cort int c;
2106*2718b568SThomas Cort {
2107*2718b568SThomas Cort return x_fold_case('U');
2108*2718b568SThomas Cort }
2109*2718b568SThomas Cort
2110*2718b568SThomas Cort /* Lowercase N(1) words */
2111*2718b568SThomas Cort static int
x_fold_lower(c)2112*2718b568SThomas Cort x_fold_lower(c)
2113*2718b568SThomas Cort int c;
2114*2718b568SThomas Cort {
2115*2718b568SThomas Cort return x_fold_case('L');
2116*2718b568SThomas Cort }
2117*2718b568SThomas Cort
2118*2718b568SThomas Cort /* Lowercase N(1) words */
2119*2718b568SThomas Cort static int
x_fold_capitalize(c)2120*2718b568SThomas Cort x_fold_capitalize(c)
2121*2718b568SThomas Cort int c;
2122*2718b568SThomas Cort {
2123*2718b568SThomas Cort return x_fold_case('C');
2124*2718b568SThomas Cort }
2125*2718b568SThomas Cort
2126*2718b568SThomas Cort /* NAME:
2127*2718b568SThomas Cort * x_fold_case - convert word to UPPER/lower/Capital case
2128*2718b568SThomas Cort *
2129*2718b568SThomas Cort * DESCRIPTION:
2130*2718b568SThomas Cort * This function is used to implement M-U,M-u,M-L,M-l,M-C and M-c
2131*2718b568SThomas Cort * to UPPER case, lower case or Capitalize words.
2132*2718b568SThomas Cort *
2133*2718b568SThomas Cort * RETURN VALUE:
2134*2718b568SThomas Cort * None
2135*2718b568SThomas Cort */
2136*2718b568SThomas Cort
2137*2718b568SThomas Cort static int
x_fold_case(c)2138*2718b568SThomas Cort x_fold_case(c)
2139*2718b568SThomas Cort int c;
2140*2718b568SThomas Cort {
2141*2718b568SThomas Cort char *cp = xcp;
2142*2718b568SThomas Cort
2143*2718b568SThomas Cort if (cp == xep) {
2144*2718b568SThomas Cort x_e_putc(BEL);
2145*2718b568SThomas Cort return KSTD;
2146*2718b568SThomas Cort }
2147*2718b568SThomas Cort while (x_arg--) {
2148*2718b568SThomas Cort /*
2149*2718b568SThomas Cort * first skip over any white-space
2150*2718b568SThomas Cort */
2151*2718b568SThomas Cort while (cp != xep && is_mfs(*cp))
2152*2718b568SThomas Cort cp++;
2153*2718b568SThomas Cort /*
2154*2718b568SThomas Cort * do the first char on its own since it may be
2155*2718b568SThomas Cort * a different action than for the rest.
2156*2718b568SThomas Cort */
2157*2718b568SThomas Cort if (cp != xep) {
2158*2718b568SThomas Cort if (c == 'L') { /* lowercase */
2159*2718b568SThomas Cort if (isupper((unsigned char)*cp))
2160*2718b568SThomas Cort *cp = tolower((unsigned char)*cp);
2161*2718b568SThomas Cort } else { /* uppercase, capitialize */
2162*2718b568SThomas Cort if (islower((unsigned char)*cp))
2163*2718b568SThomas Cort *cp = toupper((unsigned char)*cp);
2164*2718b568SThomas Cort }
2165*2718b568SThomas Cort cp++;
2166*2718b568SThomas Cort }
2167*2718b568SThomas Cort /*
2168*2718b568SThomas Cort * now for the rest of the word
2169*2718b568SThomas Cort */
2170*2718b568SThomas Cort while (cp != xep && !is_mfs((unsigned char)*cp)) {
2171*2718b568SThomas Cort if (c == 'U') { /* uppercase */
2172*2718b568SThomas Cort if (islower((unsigned char)*cp))
2173*2718b568SThomas Cort *cp = toupper((unsigned char)*cp);
2174*2718b568SThomas Cort } else { /* lowercase, capitialize */
2175*2718b568SThomas Cort if (isupper((unsigned char)*cp))
2176*2718b568SThomas Cort *cp = tolower((unsigned char)*cp);
2177*2718b568SThomas Cort }
2178*2718b568SThomas Cort cp++;
2179*2718b568SThomas Cort }
2180*2718b568SThomas Cort }
2181*2718b568SThomas Cort x_goto(cp);
2182*2718b568SThomas Cort return KSTD;
2183*2718b568SThomas Cort }
2184*2718b568SThomas Cort
2185*2718b568SThomas Cort /* NAME:
2186*2718b568SThomas Cort * x_lastcp - last visible char
2187*2718b568SThomas Cort *
2188*2718b568SThomas Cort * SYNOPSIS:
2189*2718b568SThomas Cort * x_lastcp()
2190*2718b568SThomas Cort *
2191*2718b568SThomas Cort * DESCRIPTION:
2192*2718b568SThomas Cort * This function returns a pointer to that char in the
2193*2718b568SThomas Cort * edit buffer that will be the last displayed on the
2194*2718b568SThomas Cort * screen. The sequence:
2195*2718b568SThomas Cort *
2196*2718b568SThomas Cort * for (cp = x_lastcp(); cp > xcp; cp)
2197*2718b568SThomas Cort * x_bs(*--cp);
2198*2718b568SThomas Cort *
2199*2718b568SThomas Cort * Will position the cursor correctly on the screen.
2200*2718b568SThomas Cort *
2201*2718b568SThomas Cort * RETURN VALUE:
2202*2718b568SThomas Cort * cp or NULL
2203*2718b568SThomas Cort */
2204*2718b568SThomas Cort
2205*2718b568SThomas Cort static char *
x_lastcp()2206*2718b568SThomas Cort x_lastcp()
2207*2718b568SThomas Cort {
2208*2718b568SThomas Cort register char *rcp;
2209*2718b568SThomas Cort register int i;
2210*2718b568SThomas Cort
2211*2718b568SThomas Cort if (!xlp_valid)
2212*2718b568SThomas Cort {
2213*2718b568SThomas Cort for (i = 0, rcp = xbp; rcp < xep && i < x_displen; rcp++)
2214*2718b568SThomas Cort i += x_size(*rcp);
2215*2718b568SThomas Cort xlp = rcp;
2216*2718b568SThomas Cort }
2217*2718b568SThomas Cort xlp_valid = TRUE;
2218*2718b568SThomas Cort return (xlp);
2219*2718b568SThomas Cort }
2220*2718b568SThomas Cort
2221*2718b568SThomas Cort #endif /* EDIT */
2222