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