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