emacs.c revision 268782
121526Sdavidn/*- 225901Sgpalmer * Copyright (c) 1992, 1993 321526Sdavidn * The Regents of the University of California. All rights reserved. 421526Sdavidn * 521526Sdavidn * This code is derived from software contributed to Berkeley by 621526Sdavidn * Christos Zoulas of Cornell University. 721526Sdavidn * 821526Sdavidn * Redistribution and use in source and binary forms, with or without 921526Sdavidn * modification, are permitted provided that the following conditions 1021526Sdavidn * are met: 1121526Sdavidn * 1. Redistributions of source code must retain the above copyright 1243220Sdg * notice, this list of conditions and the following disclaimer. 1321526Sdavidn * 2. Redistributions in binary form must reproduce the above copyright 1421526Sdavidn * notice, this list of conditions and the following disclaimer in the 1539375Smsmith * documentation and/or other materials provided with the distribution. 1639375Smsmith * 3. Neither the name of the University nor the names of its contributors 1721526Sdavidn * may be used to endorse or promote products derived from this software 1842149Shoek * without specific prior written permission. 1921526Sdavidn * 2021526Sdavidn * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2121526Sdavidn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2221526Sdavidn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2321526Sdavidn * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2421526Sdavidn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2543220Sdg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2621526Sdavidn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2742515Sasami * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2839375Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2939375Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3039375Smsmith * SUCH DAMAGE. 3139375Smsmith * 3239375Smsmith * $NetBSD: emacs.c,v 1.22 2009/02/15 21:55:23 christos Exp $ 3339375Smsmith */ 3439375Smsmith 3539375Smsmith#if !defined(lint) && !defined(SCCSID) 3639375Smsmithstatic char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93"; 3721538Sdavidn#endif /* not lint && not SCCSID */ 3821526Sdavidn#include <sys/cdefs.h> 3939375Smsmith__FBSDID("$FreeBSD: stable/10/lib/libedit/emacs.c 268782 2014-07-17 02:14:25Z pfg $"); 4021526Sdavidn 4121943Sdavidn/* 4221538Sdavidn * emacs.c: Emacs functions 4339375Smsmith */ 4439375Smsmith#include "sys.h" 4539375Smsmith#include "el.h" 4621538Sdavidn 4739375Smsmith/* em_delete_or_list(): 4839375Smsmith * Delete character under cursor or list completions if at end of line 4921538Sdavidn * [^D] 5039375Smsmith */ 5121526Sdavidnprotected el_action_t 5239375Smsmith/*ARGSUSED*/ 5339375Smsmithem_delete_or_list(EditLine *el, int c) 5439424Sdt{ 5539375Smsmith 5639375Smsmith if (el->el_line.cursor == el->el_line.lastchar) { 5739375Smsmith /* if I'm at the end */ 5839375Smsmith if (el->el_line.cursor == el->el_line.buffer) { 5921526Sdavidn /* and the beginning */ 6021526Sdavidn term_writec(el, c); /* then do an EOF */ 6139375Smsmith return (CC_EOF); 6221526Sdavidn } else { 6321526Sdavidn /* 6439375Smsmith * Here we could list completions, but it is an 6539375Smsmith * error right now 6621526Sdavidn */ 6721526Sdavidn term_beep(el); 6839375Smsmith return (CC_ERROR); 6921526Sdavidn } 7039375Smsmith } else { 7139375Smsmith if (el->el_state.doingarg) 7239375Smsmith c_delafter(el, el->el_state.argument); 7321526Sdavidn else 7421526Sdavidn c_delafter1(el); 7521526Sdavidn if (el->el_line.cursor > el->el_line.lastchar) 7639375Smsmith el->el_line.cursor = el->el_line.lastchar; 7739375Smsmith /* bounds check */ 7839375Smsmith return (CC_REFRESH); 7939375Smsmith } 8039375Smsmith} 8139375Smsmith 8239375Smsmith 8339375Smsmith/* em_delete_next_word(): 8439375Smsmith * Cut from cursor to end of current word 8539375Smsmith * [M-d] 8639375Smsmith */ 8721526Sdavidnprotected el_action_t 8839375Smsmith/*ARGSUSED*/ 8939375Smsmithem_delete_next_word(EditLine *el, int c __unused) 9021526Sdavidn{ 9139375Smsmith char *cp, *p, *kp; 9239375Smsmith 9339375Smsmith if (el->el_line.cursor == el->el_line.lastchar) 9421526Sdavidn return (CC_ERROR); 9539375Smsmith 9639375Smsmith cp = c__next_word(el->el_line.cursor, el->el_line.lastchar, 9721526Sdavidn el->el_state.argument, ce__isword); 9821526Sdavidn 9939375Smsmith for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++) 10039375Smsmith /* save the text */ 10139375Smsmith *kp++ = *p; 10221526Sdavidn el->el_chared.c_kill.last = kp; 10339375Smsmith 10439375Smsmith c_delafter(el, (int)(cp - el->el_line.cursor)); /* delete after dot */ 10539375Smsmith if (el->el_line.cursor > el->el_line.lastchar) 10639375Smsmith el->el_line.cursor = el->el_line.lastchar; 10739375Smsmith /* bounds check */ 10839375Smsmith return (CC_REFRESH); 10939375Smsmith} 11039375Smsmith 11139375Smsmith 11239375Smsmith/* em_yank(): 11339375Smsmith * Paste cut buffer at cursor position 11439375Smsmith * [^Y] 11539375Smsmith */ 11639375Smsmithprotected el_action_t 11721526Sdavidn/*ARGSUSED*/ 11821526Sdavidnem_yank(EditLine *el, int c __unused) 11939375Smsmith{ 12039375Smsmith char *kp, *cp; 12139375Smsmith 12239375Smsmith if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) 12339375Smsmith return (CC_NORM); 12439375Smsmith 12543220Sdg if (el->el_line.lastchar + 12639375Smsmith (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >= 12739375Smsmith el->el_line.limit) 12842587Sasami return (CC_ERROR); 12939375Smsmith 13039375Smsmith el->el_chared.c_kill.mark = el->el_line.cursor; 13139375Smsmith cp = el->el_line.cursor; 13239375Smsmith 13339375Smsmith /* open the space, */ 13439375Smsmith c_insert(el, 13539375Smsmith (int)(el->el_chared.c_kill.last - el->el_chared.c_kill.buf)); 13639375Smsmith /* copy the chars */ 13739375Smsmith for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++) 13839375Smsmith *cp++ = *kp; 13939375Smsmith 14039375Smsmith /* if an arg, cursor at beginning else cursor at end */ 14139375Smsmith if (el->el_state.argument == 1) 14239375Smsmith el->el_line.cursor = cp; 14339375Smsmith 14421526Sdavidn return (CC_REFRESH); 14521526Sdavidn} 14639375Smsmith 14739375Smsmith 14839375Smsmith/* em_kill_line(): 14939375Smsmith * Cut the entire line and save in cut buffer 15039375Smsmith * [^U] 15139375Smsmith */ 15239375Smsmithprotected el_action_t 15339375Smsmith/*ARGSUSED*/ 15439375Smsmithem_kill_line(EditLine *el, int c __unused) 15539375Smsmith{ 15639375Smsmith char *kp, *cp; 15739375Smsmith 15839375Smsmith cp = el->el_line.buffer; 15925369Sache kp = el->el_chared.c_kill.buf; 16025369Sache while (cp < el->el_line.lastchar) 16139375Smsmith *kp++ = *cp++; /* copy it */ 16239375Smsmith el->el_chared.c_kill.last = kp; 16339375Smsmith /* zap! -- delete all of it */ 16439375Smsmith el->el_line.lastchar = el->el_line.buffer; 16539375Smsmith el->el_line.cursor = el->el_line.buffer; 16639375Smsmith return (CC_REFRESH); 16739375Smsmith} 16839375Smsmith 16939375Smsmith 17039375Smsmith/* em_kill_region(): 17139375Smsmith * Cut area between mark and cursor and save in cut buffer 17239375Smsmith * [^W] 17339375Smsmith */ 17439375Smsmithprotected el_action_t 17539375Smsmith/*ARGSUSED*/ 17639375Smsmithem_kill_region(EditLine *el, int c __unused) 17739375Smsmith{ 17839375Smsmith char *kp, *cp; 17939375Smsmith 18039375Smsmith if (!el->el_chared.c_kill.mark) 18139375Smsmith return (CC_ERROR); 18239375Smsmith 18339375Smsmith if (el->el_chared.c_kill.mark > el->el_line.cursor) { 18439375Smsmith cp = el->el_line.cursor; 18539375Smsmith kp = el->el_chared.c_kill.buf; 18639375Smsmith while (cp < el->el_chared.c_kill.mark) 18739375Smsmith *kp++ = *cp++; /* copy it */ 18839375Smsmith el->el_chared.c_kill.last = kp; 18939375Smsmith c_delafter(el, (int)(cp - el->el_line.cursor)); 19039375Smsmith } else { /* mark is before cursor */ 19139375Smsmith cp = el->el_chared.c_kill.mark; 19239375Smsmith kp = el->el_chared.c_kill.buf; 19339375Smsmith while (cp < el->el_line.cursor) 19439375Smsmith *kp++ = *cp++; /* copy it */ 19539375Smsmith el->el_chared.c_kill.last = kp; 19639375Smsmith c_delbefore(el, (int)(cp - el->el_chared.c_kill.mark)); 19739375Smsmith el->el_line.cursor = el->el_chared.c_kill.mark; 19839375Smsmith } 19939375Smsmith return (CC_REFRESH); 20039375Smsmith} 20139375Smsmith 20239375Smsmith 20339375Smsmith/* em_copy_region(): 20439375Smsmith * Copy area between mark and cursor to cut buffer 20539375Smsmith * [M-W] 20639375Smsmith */ 20739375Smsmithprotected el_action_t 20839375Smsmith/*ARGSUSED*/ 20939375Smsmithem_copy_region(EditLine *el, int c __unused) 21039375Smsmith{ 21139375Smsmith char *kp, *cp; 21239375Smsmith 21339375Smsmith if (!el->el_chared.c_kill.mark) 21439375Smsmith return (CC_ERROR); 21539375Smsmith 21639375Smsmith if (el->el_chared.c_kill.mark > el->el_line.cursor) { 21739375Smsmith cp = el->el_line.cursor; 21839375Smsmith kp = el->el_chared.c_kill.buf; 21939375Smsmith while (cp < el->el_chared.c_kill.mark) 22039375Smsmith *kp++ = *cp++; /* copy it */ 22139375Smsmith el->el_chared.c_kill.last = kp; 22239375Smsmith } else { 22339375Smsmith cp = el->el_chared.c_kill.mark; 22439375Smsmith kp = el->el_chared.c_kill.buf; 22539375Smsmith while (cp < el->el_line.cursor) 22639375Smsmith *kp++ = *cp++; /* copy it */ 22739375Smsmith el->el_chared.c_kill.last = kp; 22839375Smsmith } 22939375Smsmith return (CC_NORM); 23039375Smsmith} 23139375Smsmith 23239375Smsmith 23339375Smsmith/* em_gosmacs_transpose(): 23439375Smsmith * Exchange the two characters before the cursor 23539375Smsmith * Gosling emacs transpose chars [^T] 23639375Smsmith */ 23739375Smsmithprotected el_action_t 23839375Smsmithem_gosmacs_transpose(EditLine *el, int c) 23939375Smsmith{ 24039375Smsmith 24139375Smsmith if (el->el_line.cursor > &el->el_line.buffer[1]) { 24239375Smsmith /* must have at least two chars entered */ 24339375Smsmith c = el->el_line.cursor[-2]; 24439375Smsmith el->el_line.cursor[-2] = el->el_line.cursor[-1]; 24539375Smsmith el->el_line.cursor[-1] = c; 24639375Smsmith return (CC_REFRESH); 24739375Smsmith } else 24839375Smsmith return (CC_ERROR); 24939375Smsmith} 25039375Smsmith 25139375Smsmith 25239375Smsmith/* em_next_word(): 25339375Smsmith * Move next to end of current word 25439375Smsmith * [M-f] 25539375Smsmith */ 25639375Smsmithprotected el_action_t 25739375Smsmith/*ARGSUSED*/ 25839375Smsmithem_next_word(EditLine *el, int c __unused) 25939375Smsmith{ 26039375Smsmith if (el->el_line.cursor == el->el_line.lastchar) 26139375Smsmith return (CC_ERROR); 26239375Smsmith 26339375Smsmith el->el_line.cursor = c__next_word(el->el_line.cursor, 26439375Smsmith el->el_line.lastchar, 26539375Smsmith el->el_state.argument, 26639375Smsmith ce__isword); 26739375Smsmith 26839375Smsmith if (el->el_map.type == MAP_VI) 26939375Smsmith if (el->el_chared.c_vcmd.action != NOP) { 27039375Smsmith cv_delfini(el); 27139375Smsmith return (CC_REFRESH); 27239375Smsmith } 27339375Smsmith return (CC_CURSOR); 27439375Smsmith} 27539375Smsmith 27639375Smsmith 27739375Smsmith/* em_upper_case(): 27839375Smsmith * Uppercase the characters from cursor to end of current word 27939375Smsmith * [M-u] 28039375Smsmith */ 28139375Smsmithprotected el_action_t 28239375Smsmith/*ARGSUSED*/ 28339375Smsmithem_upper_case(EditLine *el, int c __unused) 28439375Smsmith{ 28539375Smsmith char *cp, *ep; 28639375Smsmith 28739375Smsmith ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, 28839375Smsmith el->el_state.argument, ce__isword); 28939375Smsmith 29039375Smsmith for (cp = el->el_line.cursor; cp < ep; cp++) 29139375Smsmith if (islower((unsigned char)*cp)) 29239375Smsmith *cp = toupper((unsigned char)*cp); 29339375Smsmith 29439375Smsmith el->el_line.cursor = ep; 29539375Smsmith if (el->el_line.cursor > el->el_line.lastchar) 29639375Smsmith el->el_line.cursor = el->el_line.lastchar; 29739375Smsmith return (CC_REFRESH); 29839375Smsmith} 29939375Smsmith 30039375Smsmith 30139375Smsmith/* em_capitol_case(): 30239375Smsmith * Capitalize the characters from cursor to end of current word 30339375Smsmith * [M-c] 30439375Smsmith */ 30539375Smsmithprotected el_action_t 30639375Smsmith/*ARGSUSED*/ 30739375Smsmithem_capitol_case(EditLine *el, int c __unused) 30839375Smsmith{ 30939375Smsmith char *cp, *ep; 31039375Smsmith 31139375Smsmith ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, 31239375Smsmith el->el_state.argument, ce__isword); 31339375Smsmith 31439375Smsmith for (cp = el->el_line.cursor; cp < ep; cp++) { 31539375Smsmith if (isalpha((unsigned char)*cp)) { 31639375Smsmith if (islower((unsigned char)*cp)) 31739375Smsmith *cp = toupper((unsigned char)*cp); 31839375Smsmith cp++; 31939375Smsmith break; 32039375Smsmith } 32139375Smsmith } 32239375Smsmith for (; cp < ep; cp++) 32339375Smsmith if (isupper((unsigned char)*cp)) 32439375Smsmith *cp = tolower((unsigned char)*cp); 32539375Smsmith 32639375Smsmith el->el_line.cursor = ep; 32742113Scwt if (el->el_line.cursor > el->el_line.lastchar) 328 el->el_line.cursor = el->el_line.lastchar; 329 return (CC_REFRESH); 330} 331 332 333/* em_lower_case(): 334 * Lowercase the characters from cursor to end of current word 335 * [M-l] 336 */ 337protected el_action_t 338/*ARGSUSED*/ 339em_lower_case(EditLine *el, int c __unused) 340{ 341 char *cp, *ep; 342 343 ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, 344 el->el_state.argument, ce__isword); 345 346 for (cp = el->el_line.cursor; cp < ep; cp++) 347 if (isupper((unsigned char)*cp)) 348 *cp = tolower((unsigned char)*cp); 349 350 el->el_line.cursor = ep; 351 if (el->el_line.cursor > el->el_line.lastchar) 352 el->el_line.cursor = el->el_line.lastchar; 353 return (CC_REFRESH); 354} 355 356 357/* em_set_mark(): 358 * Set the mark at cursor 359 * [^@] 360 */ 361protected el_action_t 362/*ARGSUSED*/ 363em_set_mark(EditLine *el, int c __unused) 364{ 365 366 el->el_chared.c_kill.mark = el->el_line.cursor; 367 return (CC_NORM); 368} 369 370 371/* em_exchange_mark(): 372 * Exchange the cursor and mark 373 * [^X^X] 374 */ 375protected el_action_t 376/*ARGSUSED*/ 377em_exchange_mark(EditLine *el, int c __unused) 378{ 379 char *cp; 380 381 cp = el->el_line.cursor; 382 el->el_line.cursor = el->el_chared.c_kill.mark; 383 el->el_chared.c_kill.mark = cp; 384 return (CC_CURSOR); 385} 386 387 388/* em_universal_argument(): 389 * Universal argument (argument times 4) 390 * [^U] 391 */ 392protected el_action_t 393/*ARGSUSED*/ 394em_universal_argument(EditLine *el, int c __unused) 395{ /* multiply current argument by 4 */ 396 397 if (el->el_state.argument > 1000000) 398 return (CC_ERROR); 399 el->el_state.doingarg = 1; 400 el->el_state.argument *= 4; 401 return (CC_ARGHACK); 402} 403 404 405/* em_meta_next(): 406 * Add 8th bit to next character typed 407 * [<ESC>] 408 */ 409protected el_action_t 410/*ARGSUSED*/ 411em_meta_next(EditLine *el, int c __unused) 412{ 413 414 el->el_state.metanext = 1; 415 return (CC_ARGHACK); 416} 417 418 419/* em_toggle_overwrite(): 420 * Switch from insert to overwrite mode or vice versa 421 */ 422protected el_action_t 423/*ARGSUSED*/ 424em_toggle_overwrite(EditLine *el, int c __unused) 425{ 426 427 el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ? 428 MODE_REPLACE : MODE_INSERT; 429 return (CC_NORM); 430} 431 432 433/* em_copy_prev_word(): 434 * Copy current word to cursor 435 */ 436protected el_action_t 437/*ARGSUSED*/ 438em_copy_prev_word(EditLine *el, int c __unused) 439{ 440 char *cp, *oldc, *dp; 441 442 if (el->el_line.cursor == el->el_line.buffer) 443 return (CC_ERROR); 444 445 oldc = el->el_line.cursor; 446 /* does a bounds check */ 447 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, 448 el->el_state.argument, ce__isword); 449 450 c_insert(el, (int)(oldc - cp)); 451 for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++) 452 *dp++ = *cp; 453 454 el->el_line.cursor = dp;/* put cursor at end */ 455 456 return (CC_REFRESH); 457} 458 459 460/* em_inc_search_next(): 461 * Emacs incremental next search 462 */ 463protected el_action_t 464/*ARGSUSED*/ 465em_inc_search_next(EditLine *el, int c __unused) 466{ 467 468 el->el_search.patlen = 0; 469 return (ce_inc_search(el, ED_SEARCH_NEXT_HISTORY)); 470} 471 472 473/* em_inc_search_prev(): 474 * Emacs incremental reverse search 475 */ 476protected el_action_t 477/*ARGSUSED*/ 478em_inc_search_prev(EditLine *el, int c __unused) 479{ 480 481 el->el_search.patlen = 0; 482 return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY)); 483} 484 485 486/* em_delete_prev_char(): 487 * Delete the character to the left of the cursor 488 * [^?] 489 */ 490protected el_action_t 491/*ARGSUSED*/ 492em_delete_prev_char(EditLine *el, int c __unused) 493{ 494 495 if (el->el_line.cursor <= el->el_line.buffer) 496 return (CC_ERROR); 497 498 if (el->el_state.doingarg) 499 c_delbefore(el, el->el_state.argument); 500 else 501 c_delbefore1(el); 502 el->el_line.cursor -= el->el_state.argument; 503 if (el->el_line.cursor < el->el_line.buffer) 504 el->el_line.cursor = el->el_line.buffer; 505 return (CC_REFRESH); 506} 507