emacs.c revision 1573
1127412Sgad/*- 2127412Sgad * Copyright (c) 1992, 1993 3127412Sgad * The Regents of the University of California. All rights reserved. 4161458Syar * 5161458Syar * This code is derived from software contributed to Berkeley by 6127412Sgad * Christos Zoulas of Cornell University. 7127431Sgad * 8127412Sgad * Redistribution and use in source and binary forms, with or without 9127437Sru * modification, are permitted provided that the following conditions 10127437Sru * are met: 11127412Sgad * 1. Redistributions of source code must retain the above copyright 12127437Sru * notice, this list of conditions and the following disclaimer. 13127437Sru * 2. Redistributions in binary form must reproduce the above copyright 14127412Sgad * notice, this list of conditions and the following disclaimer in the 15161458Syar * documentation and/or other materials provided with the distribution. 16161458Syar * 3. All advertising materials mentioning features or use of this software 17161458Syar * must display the following acknowledgement: 18127412Sgad * 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#ifdef notyet 59 if (el->el_line.cursor == el->el_line.buffer) { /* and the beginning */ 60#endif 61 term_overwrite(el, STReof, 4);/* then do a EOF */ 62 term__flush(); 63 return CC_EOF; 64#ifdef notyet 65 } 66 else { 67 re_goto_bottom(el); 68 *el->el_line.lastchar = '\0'; /* just in case */ 69 return CC_LIST_CHOICES; 70 } 71#endif 72 } 73 else { 74 c_delafter(el, el->el_state.argument); /* delete after dot */ 75 if (el->el_line.cursor > el->el_line.lastchar) 76 el->el_line.cursor = el->el_line.lastchar; /* bounds check */ 77 return CC_REFRESH; 78 } 79} 80 81 82/* em_delete_next_word(): 83 * Cut from cursor to end of current word 84 * [M-d] 85 */ 86protected el_action_t 87/*ARGSUSED*/ 88em_delete_next_word(el, c) 89 EditLine *el; 90 int c; 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, 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; /* 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(el, c) 119 EditLine *el; 120 int c; 121{ 122 char *kp, *cp; 123 124 if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) 125 return CC_ERROR; 126 127 if (el->el_line.lastchar + 128 (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >= 129 el->el_line.limit) 130 return CC_ERROR; 131 132 el->el_chared.c_kill.mark = el->el_line.cursor; 133 cp = el->el_line.cursor; 134 135 /* open the space, */ 136 c_insert(el, 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 */ 153protected el_action_t 154/*ARGSUSED*/ 155em_kill_line(el, c) 156 EditLine *el; 157 int c; 158{ 159 char *kp, *cp; 160 161 cp = el->el_line.buffer; 162 kp = el->el_chared.c_kill.buf; 163 while (cp < el->el_line.lastchar) 164 *kp++ = *cp++; /* copy it */ 165 el->el_chared.c_kill.last = kp; 166 el->el_line.lastchar = el->el_line.buffer; /* zap! -- delete all of it */ 167 el->el_line.cursor = el->el_line.buffer; 168 return CC_REFRESH; 169} 170 171 172/* em_kill_region(): 173 * Cut area between mark and cursor and save in cut buffer 174 * [^W] 175 */ 176protected el_action_t 177/*ARGSUSED*/ 178em_kill_region(el, c) 179 EditLine *el; 180 int c; 181{ 182 char *kp, *cp; 183 184 if (!el->el_chared.c_kill.mark) 185 return CC_ERROR; 186 187 if (el->el_chared.c_kill.mark > el->el_line.cursor) { 188 cp = el->el_line.cursor; 189 kp = el->el_chared.c_kill.buf; 190 while (cp < el->el_chared.c_kill.mark) 191 *kp++ = *cp++; /* copy it */ 192 el->el_chared.c_kill.last = kp; 193 c_delafter(el, cp - el->el_line.cursor); 194 } 195 else { /* mark is before cursor */ 196 cp = el->el_chared.c_kill.mark; 197 kp = el->el_chared.c_kill.buf; 198 while (cp < el->el_line.cursor) 199 *kp++ = *cp++; /* copy it */ 200 el->el_chared.c_kill.last = kp; 201 c_delbefore(el, cp - el->el_chared.c_kill.mark); 202 el->el_line.cursor = el->el_chared.c_kill.mark; 203 } 204 return CC_REFRESH; 205} 206 207 208/* em_copy_region(): 209 * Copy area between mark and cursor to cut buffer 210 * [M-W] 211 */ 212protected el_action_t 213/*ARGSUSED*/ 214em_copy_region(el, c) 215 EditLine *el; 216 int c; 217{ 218 char *kp, *cp; 219 220 if (el->el_chared.c_kill.mark) 221 return CC_ERROR; 222 223 if (el->el_chared.c_kill.mark > el->el_line.cursor) { 224 cp = el->el_line.cursor; 225 kp = el->el_chared.c_kill.buf; 226 while (cp < el->el_chared.c_kill.mark) 227 *kp++ = *cp++; /* copy it */ 228 el->el_chared.c_kill.last = kp; 229 } 230 else { 231 cp = el->el_chared.c_kill.mark; 232 kp = el->el_chared.c_kill.buf; 233 while (cp < el->el_line.cursor) 234 *kp++ = *cp++; /* copy it */ 235 el->el_chared.c_kill.last = kp; 236 } 237 return CC_NORM; 238} 239 240 241/* em_gosmacs_traspose(): 242 * Exchange the two characters before the cursor 243 * Gosling emacs transpose chars [^T] 244 */ 245protected el_action_t 246em_gosmacs_traspose(el, c) 247 EditLine *el; 248 int c; 249{ 250 251 if (el->el_line.cursor > &el->el_line.buffer[1]) { 252 /* must have at least two chars entered */ 253 c = el->el_line.cursor[-2]; 254 el->el_line.cursor[-2] = el->el_line.cursor[-1]; 255 el->el_line.cursor[-1] = c; 256 return CC_REFRESH; 257 } 258 else 259 return CC_ERROR; 260} 261 262 263/* em_next_word(): 264 * Move next to end of current word 265 * [M-f] 266 */ 267protected el_action_t 268/*ARGSUSED*/ 269em_next_word(el, c) 270 EditLine *el; 271 int c; 272{ 273 if (el->el_line.cursor == el->el_line.lastchar) 274 return CC_ERROR; 275 276 el->el_line.cursor = c__next_word(el->el_line.cursor, el->el_line.lastchar, 277 el->el_state.argument, 278 ce__isword); 279 280 if (el->el_map.type == MAP_VI) 281 if (el->el_chared.c_vcmd.action & DELETE) { 282 cv_delfini(el); 283 return CC_REFRESH; 284 } 285 286 return CC_CURSOR; 287} 288 289/* em_upper_case(): 290 * Uppercase the characters from cursor to end of current word 291 * [M-u] 292 */ 293protected el_action_t 294/*ARGSUSED*/ 295em_upper_case(el, c) 296 EditLine *el; 297 int c; 298{ 299 char *cp, *ep; 300 301 ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, 302 el->el_state.argument, ce__isword); 303 304 for (cp = el->el_line.cursor; cp < ep; cp++) 305 if (islower(*cp)) 306 *cp = toupper(*cp); 307 308 el->el_line.cursor = ep; 309 if (el->el_line.cursor > el->el_line.lastchar) 310 el->el_line.cursor = el->el_line.lastchar; 311 return CC_REFRESH; 312} 313 314 315/* em_capitol_case(): 316 * Capitalize the characters from cursor to end of current word 317 * [M-c] 318 */ 319protected el_action_t 320/*ARGSUSED*/ 321em_capitol_case(el, c) 322 EditLine *el; 323 int c; 324{ 325 char *cp, *ep; 326 327 ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, 328 el->el_state.argument, ce__isword); 329 330 for (cp = el->el_line.cursor; cp < ep; cp++) { 331 if (isalpha(*cp)) { 332 if (islower(*cp)) 333 *cp = toupper(*cp); 334 cp++; 335 break; 336 } 337 } 338 for (; cp < ep; cp++) 339 if (isupper(*cp)) 340 *cp = tolower(*cp); 341 342 el->el_line.cursor = ep; 343 if (el->el_line.cursor > el->el_line.lastchar) 344 el->el_line.cursor = el->el_line.lastchar; 345 return CC_REFRESH; 346} 347 348/* em_lower_case(): 349 * Lowercase the characters from cursor to end of current word 350 * [M-l] 351 */ 352protected el_action_t 353/*ARGSUSED*/ 354em_lower_case(el, c) 355 EditLine *el; 356 int c; 357{ 358 char *cp, *ep; 359 360 ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, 361 el->el_state.argument, ce__isword); 362 363 for (cp = el->el_line.cursor; cp < ep; cp++) 364 if (isupper(*cp)) 365 *cp = tolower(*cp); 366 367 el->el_line.cursor = ep; 368 if (el->el_line.cursor > el->el_line.lastchar) 369 el->el_line.cursor = el->el_line.lastchar; 370 return CC_REFRESH; 371} 372 373 374/* em_set_mark(): 375 * Set the mark at cursor 376 * [^@] 377 */ 378protected el_action_t 379/*ARGSUSED*/ 380em_set_mark(el, c) 381 EditLine *el; 382 int c; 383{ 384 el->el_chared.c_kill.mark = el->el_line.cursor; 385 return CC_NORM; 386} 387 388 389/* em_exchange_mark(): 390 * Exchange the cursor and mark 391 * [^X^X] 392 */ 393protected el_action_t 394/*ARGSUSED*/ 395em_exchange_mark(el, c) 396 EditLine *el; 397 int c; 398{ 399 register char *cp; 400 401 cp = el->el_line.cursor; 402 el->el_line.cursor = el->el_chared.c_kill.mark; 403 el->el_chared.c_kill.mark = cp; 404 return CC_CURSOR; 405} 406 407/* em_universal_argument(): 408 * Universal argument (argument times 4) 409 * [^U] 410 */ 411protected el_action_t 412/*ARGSUSED*/ 413em_universal_argument(el, c) 414 EditLine *el; 415 int c; 416{ /* multiply current argument by 4 */ 417 if (el->el_state.argument > 1000000) 418 return CC_ERROR; 419 el->el_state.doingarg = 1; 420 el->el_state.argument *= 4; 421 return CC_ARGHACK; 422} 423 424/* em_meta_next(): 425 * Add 8th bit to next character typed 426 * [<ESC>] 427 */ 428protected el_action_t 429/*ARGSUSED*/ 430em_meta_next(el, c) 431 EditLine *el; 432 int c; 433{ 434 el->el_state.metanext = 1; 435 return CC_ARGHACK; 436} 437 438 439/* em_toggle_overwrite(): 440 * Switch from insert to overwrite mode or vice versa 441 */ 442protected el_action_t 443/*ARGSUSED*/ 444em_toggle_overwrite(el, c) 445 EditLine *el; 446 int c; 447{ 448 el->el_state.inputmode = 449 (el->el_state.inputmode == MODE_INSERT) ? MODE_REPLACE : MODE_INSERT; 450 return CC_NORM; 451} 452 453 454/* em_copy_prev_word(): 455 * Copy current word to cursor 456 */ 457protected el_action_t 458/*ARGSUSED*/ 459em_copy_prev_word(el, c) 460 EditLine *el; 461 int c; 462{ 463 char *cp, *oldc, *dp; 464 465 if (el->el_line.cursor == el->el_line.buffer) 466 return CC_ERROR; 467 468 oldc = el->el_line.cursor; 469 /* does a bounds check */ 470 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, 471 el->el_state.argument, ce__isword); 472 473 c_insert(el, oldc - cp); 474 for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++) 475 *dp++ = *cp; 476 477 el->el_line.cursor = dp; /* put cursor at end */ 478 479 return CC_REFRESH; 480} 481 482 483/* em_inc_search_next(): 484 * Emacs incremental next search 485 */ 486protected el_action_t 487/*ARGSUSED*/ 488em_inc_search_next(el, c) 489 EditLine *el; 490 int c; 491{ 492 el->el_search.patlen = 0; 493 return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY); 494} 495 496 497/* em_inc_search_prev(): 498 * Emacs incremental reverse search 499 */ 500protected el_action_t 501/*ARGSUSED*/ 502em_inc_search_prev(el, c) 503 EditLine *el; 504 int c; 505{ 506 el->el_search.patlen = 0; 507 return ce_inc_search(el, ED_SEARCH_PREV_HISTORY); 508} 509