MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
emacs.c
1 /* $NetBSD: emacs.c,v 1.25 2011/07/29 15:16:33 christos Exp $ */
2 
3 /*-
4  * Copyright (c) 1992, 1993
5  * The Regents of the University of California. All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Christos Zoulas of Cornell University.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  * may be used to endorse or promote products derived from this software
20  * without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include "config.h"
36 #if !defined(lint) && !defined(SCCSID)
37 #if 0
38 static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93";
39 #else
40 #endif
41 #endif /* not lint && not SCCSID */
42 
43 /*
44  * emacs.c: Emacs functions
45  */
46 #include "el.h"
47 
48 /* em_delete_or_list():
49  * Delete character under cursor or list completions if at end of line
50  * [^D]
51  */
52 protected el_action_t
53 /*ARGSUSED*/
54 em_delete_or_list(EditLine *el, Int c)
55 {
56 
57  if (el->el_line.cursor == el->el_line.lastchar) {
58  /* if I'm at the end */
59  if (el->el_line.cursor == el->el_line.buffer) {
60  /* and the beginning */
61  terminal_writec(el, c); /* then do an EOF */
62  return CC_EOF;
63  } else {
64  /*
65  * Here we could list completions, but it is an
66  * error right now
67  */
68  terminal_beep(el);
69  return CC_ERROR;
70  }
71  } else {
72  if (el->el_state.doingarg)
73  c_delafter(el, el->el_state.argument);
74  else
75  c_delafter1(el);
76  if (el->el_line.cursor > el->el_line.lastchar)
77  el->el_line.cursor = el->el_line.lastchar;
78  /* bounds check */
79  return CC_REFRESH;
80  }
81 }
82 
83 
84 /* em_delete_next_word():
85  * Cut from cursor to end of current word
86  * [M-d]
87  */
88 protected el_action_t
89 /*ARGSUSED*/
90 em_delete_next_word(EditLine *el, Int c __attribute__((__unused__)))
91 {
92  Char *cp, *p, *kp;
93 
94  if (el->el_line.cursor == el->el_line.lastchar)
95  return CC_ERROR;
96 
97  cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
98  el->el_state.argument, ce__isword);
99 
100  for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
101  /* save the text */
102  *kp++ = *p;
103  el->el_chared.c_kill.last = kp;
104 
105  c_delafter(el, (int)(cp - el->el_line.cursor)); /* delete after dot */
106  if (el->el_line.cursor > el->el_line.lastchar)
107  el->el_line.cursor = el->el_line.lastchar;
108  /* bounds check */
109  return CC_REFRESH;
110 }
111 
112 
113 /* em_yank():
114  * Paste cut buffer at cursor position
115  * [^Y]
116  */
117 protected el_action_t
118 /*ARGSUSED*/
119 em_yank(EditLine *el, Int c __attribute__((__unused__)))
120 {
121  Char *kp, *cp;
122 
123  if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
124  return CC_NORM;
125 
126  if (el->el_line.lastchar +
127  (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
128  el->el_line.limit)
129  return CC_ERROR;
130 
131  el->el_chared.c_kill.mark = el->el_line.cursor;
132  cp = el->el_line.cursor;
133 
134  /* open the space, */
135  c_insert(el,
136  (int)(el->el_chared.c_kill.last - el->el_chared.c_kill.buf));
137  /* copy the chars */
138  for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
139  *cp++ = *kp;
140 
141  /* if an arg, cursor at beginning else cursor at end */
142  if (el->el_state.argument == 1)
143  el->el_line.cursor = cp;
144 
145  return CC_REFRESH;
146 }
147 
148 
149 /* em_kill_line():
150  * Cut the entire line and save in cut buffer
151  * [^U]
152  */
153 protected el_action_t
154 /*ARGSUSED*/
155 em_kill_line(EditLine *el, Int c __attribute__((__unused__)))
156 {
157  Char *kp, *cp;
158 
159  cp = el->el_line.buffer;
160  kp = el->el_chared.c_kill.buf;
161  while (cp < el->el_line.lastchar)
162  *kp++ = *cp++; /* copy it */
163  el->el_chared.c_kill.last = kp;
164  /* zap! -- delete all of it */
165  el->el_line.lastchar = el->el_line.buffer;
166  el->el_line.cursor = el->el_line.buffer;
167  return CC_REFRESH;
168 }
169 
170 
171 /* em_kill_region():
172  * Cut area between mark and cursor and save in cut buffer
173  * [^W]
174  */
175 protected el_action_t
176 /*ARGSUSED*/
177 em_kill_region(EditLine *el, Int c __attribute__((__unused__)))
178 {
179  Char *kp, *cp;
180 
181  if (!el->el_chared.c_kill.mark)
182  return CC_ERROR;
183 
184  if (el->el_chared.c_kill.mark > el->el_line.cursor) {
185  cp = el->el_line.cursor;
186  kp = el->el_chared.c_kill.buf;
187  while (cp < el->el_chared.c_kill.mark)
188  *kp++ = *cp++; /* copy it */
189  el->el_chared.c_kill.last = kp;
190  c_delafter(el, (int)(cp - el->el_line.cursor));
191  } else { /* mark is before cursor */
192  cp = el->el_chared.c_kill.mark;
193  kp = el->el_chared.c_kill.buf;
194  while (cp < el->el_line.cursor)
195  *kp++ = *cp++; /* copy it */
196  el->el_chared.c_kill.last = kp;
197  c_delbefore(el, (int)(cp - el->el_chared.c_kill.mark));
198  el->el_line.cursor = el->el_chared.c_kill.mark;
199  }
200  return CC_REFRESH;
201 }
202 
203 
204 /* em_copy_region():
205  * Copy area between mark and cursor to cut buffer
206  * [M-W]
207  */
208 protected el_action_t
209 /*ARGSUSED*/
210 em_copy_region(EditLine *el, Int c __attribute__((__unused__)))
211 {
212  Char *kp, *cp;
213 
214  if (!el->el_chared.c_kill.mark)
215  return CC_ERROR;
216 
217  if (el->el_chared.c_kill.mark > el->el_line.cursor) {
218  cp = el->el_line.cursor;
219  kp = el->el_chared.c_kill.buf;
220  while (cp < el->el_chared.c_kill.mark)
221  *kp++ = *cp++; /* copy it */
222  el->el_chared.c_kill.last = kp;
223  } else {
224  cp = el->el_chared.c_kill.mark;
225  kp = el->el_chared.c_kill.buf;
226  while (cp < el->el_line.cursor)
227  *kp++ = *cp++; /* copy it */
228  el->el_chared.c_kill.last = kp;
229  }
230  return CC_NORM;
231 }
232 
233 
234 /* em_gosmacs_transpose():
235  * Exchange the two characters before the cursor
236  * Gosling emacs transpose chars [^T]
237  */
238 protected el_action_t
239 em_gosmacs_transpose(EditLine *el, Int c)
240 {
241 
242  if (el->el_line.cursor > &el->el_line.buffer[1]) {
243  /* must have at least two chars entered */
244  c = el->el_line.cursor[-2];
245  el->el_line.cursor[-2] = el->el_line.cursor[-1];
246  el->el_line.cursor[-1] = c;
247  return CC_REFRESH;
248  } else
249  return CC_ERROR;
250 }
251 
252 
253 /* em_next_word():
254  * Move next to end of current word
255  * [M-f]
256  */
257 protected el_action_t
258 /*ARGSUSED*/
259 em_next_word(EditLine *el, Int c __attribute__((__unused__)))
260 {
261  if (el->el_line.cursor == el->el_line.lastchar)
262  return CC_ERROR;
263 
264  el->el_line.cursor = c__next_word(el->el_line.cursor,
265  el->el_line.lastchar,
266  el->el_state.argument,
267  ce__isword);
268 
269  if (el->el_map.type == MAP_VI)
270  if (el->el_chared.c_vcmd.action != NOP) {
271  cv_delfini(el);
272  return CC_REFRESH;
273  }
274  return CC_CURSOR;
275 }
276 
277 
278 /* em_upper_case():
279  * Uppercase the characters from cursor to end of current word
280  * [M-u]
281  */
282 protected el_action_t
283 /*ARGSUSED*/
284 em_upper_case(EditLine *el, Int c __attribute__((__unused__)))
285 {
286  Char *cp, *ep;
287 
288  ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
289  el->el_state.argument, ce__isword);
290 
291  for (cp = el->el_line.cursor; cp < ep; cp++)
292  if (Islower(*cp))
293  *cp = Toupper(*cp);
294 
295  el->el_line.cursor = ep;
296  if (el->el_line.cursor > el->el_line.lastchar)
297  el->el_line.cursor = el->el_line.lastchar;
298  return CC_REFRESH;
299 }
300 
301 
302 /* em_capitol_case():
303  * Capitalize the characters from cursor to end of current word
304  * [M-c]
305  */
306 protected el_action_t
307 /*ARGSUSED*/
308 em_capitol_case(EditLine *el, Int c __attribute__((__unused__)))
309 {
310  Char *cp, *ep;
311 
312  ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
313  el->el_state.argument, ce__isword);
314 
315  for (cp = el->el_line.cursor; cp < ep; cp++) {
316  if (Isalpha(*cp)) {
317  if (Islower(*cp))
318  *cp = Toupper(*cp);
319  cp++;
320  break;
321  }
322  }
323  for (; cp < ep; cp++)
324  if (Isupper(*cp))
325  *cp = Tolower(*cp);
326 
327  el->el_line.cursor = ep;
328  if (el->el_line.cursor > el->el_line.lastchar)
329  el->el_line.cursor = el->el_line.lastchar;
330  return CC_REFRESH;
331 }
332 
333 
334 /* em_lower_case():
335  * Lowercase the characters from cursor to end of current word
336  * [M-l]
337  */
338 protected el_action_t
339 /*ARGSUSED*/
340 em_lower_case(EditLine *el, Int c __attribute__((__unused__)))
341 {
342  Char *cp, *ep;
343 
344  ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
345  el->el_state.argument, ce__isword);
346 
347  for (cp = el->el_line.cursor; cp < ep; cp++)
348  if (Isupper(*cp))
349  *cp = Tolower(*cp);
350 
351  el->el_line.cursor = ep;
352  if (el->el_line.cursor > el->el_line.lastchar)
353  el->el_line.cursor = el->el_line.lastchar;
354  return CC_REFRESH;
355 }
356 
357 
358 /* em_set_mark():
359  * Set the mark at cursor
360  * [^@]
361  */
362 protected el_action_t
363 /*ARGSUSED*/
364 em_set_mark(EditLine *el, Int c __attribute__((__unused__)))
365 {
366 
367  el->el_chared.c_kill.mark = el->el_line.cursor;
368  return CC_NORM;
369 }
370 
371 
372 /* em_exchange_mark():
373  * Exchange the cursor and mark
374  * [^X^X]
375  */
376 protected el_action_t
377 /*ARGSUSED*/
378 em_exchange_mark(EditLine *el, Int c __attribute__((__unused__)))
379 {
380  Char *cp;
381 
382  cp = el->el_line.cursor;
383  el->el_line.cursor = el->el_chared.c_kill.mark;
384  el->el_chared.c_kill.mark = cp;
385  return CC_CURSOR;
386 }
387 
388 
389 /* em_universal_argument():
390  * Universal argument (argument times 4)
391  * [^U]
392  */
393 protected el_action_t
394 /*ARGSUSED*/
395 em_universal_argument(EditLine *el, Int c __attribute__((__unused__)))
396 { /* multiply current argument by 4 */
397 
398  if (el->el_state.argument > 1000000)
399  return CC_ERROR;
400  el->el_state.doingarg = 1;
401  el->el_state.argument *= 4;
402  return CC_ARGHACK;
403 }
404 
405 
406 /* em_meta_next():
407  * Add 8th bit to next character typed
408  * [<ESC>]
409  */
410 protected el_action_t
411 /*ARGSUSED*/
412 em_meta_next(EditLine *el, Int c __attribute__((__unused__)))
413 {
414 
415  el->el_state.metanext = 1;
416  return CC_ARGHACK;
417 }
418 
419 
420 /* em_toggle_overwrite():
421  * Switch from insert to overwrite mode or vice versa
422  */
423 protected el_action_t
424 /*ARGSUSED*/
425 em_toggle_overwrite(EditLine *el, Int c __attribute__((__unused__)))
426 {
427 
428  el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
429  MODE_REPLACE : MODE_INSERT;
430  return CC_NORM;
431 }
432 
433 
434 /* em_copy_prev_word():
435  * Copy current word to cursor
436  */
437 protected el_action_t
438 /*ARGSUSED*/
439 em_copy_prev_word(EditLine *el, Int c __attribute__((__unused__)))
440 {
441  Char *cp, *oldc, *dp;
442 
443  if (el->el_line.cursor == el->el_line.buffer)
444  return CC_ERROR;
445 
446  oldc = el->el_line.cursor;
447  /* does a bounds check */
448  cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
449  el->el_state.argument, ce__isword);
450 
451  c_insert(el, (int)(oldc - cp));
452  for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
453  *dp++ = *cp;
454 
455  el->el_line.cursor = dp;/* put cursor at end */
456 
457  return CC_REFRESH;
458 }
459 
460 
461 /* em_inc_search_next():
462  * Emacs incremental next search
463  */
464 protected el_action_t
465 /*ARGSUSED*/
466 em_inc_search_next(EditLine *el, Int c __attribute__((__unused__)))
467 {
468 
469  el->el_search.patlen = 0;
470  return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY);
471 }
472 
473 
474 /* em_inc_search_prev():
475  * Emacs incremental reverse search
476  */
477 protected el_action_t
478 /*ARGSUSED*/
479 em_inc_search_prev(EditLine *el, Int c __attribute__((__unused__)))
480 {
481 
482  el->el_search.patlen = 0;
483  return ce_inc_search(el, ED_SEARCH_PREV_HISTORY);
484 }
485 
486 
487 /* em_delete_prev_char():
488  * Delete the character to the left of the cursor
489  * [^?]
490  */
491 protected el_action_t
492 /*ARGSUSED*/
493 em_delete_prev_char(EditLine *el, Int c __attribute__((__unused__)))
494 {
495 
496  if (el->el_line.cursor <= el->el_line.buffer)
497  return CC_ERROR;
498 
499  if (el->el_state.doingarg)
500  c_delbefore(el, el->el_state.argument);
501  else
502  c_delbefore1(el);
503  el->el_line.cursor -= el->el_state.argument;
504  if (el->el_line.cursor < el->el_line.buffer)
505  el->el_line.cursor = el->el_line.buffer;
506  return CC_REFRESH;
507 }