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 * %sccs.include.redist.c% 9 */ 10 11 #if !defined(lint) && !defined(SCCSID) 12 static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 06/04/93"; 13 #endif /* not lint && not SCCSID */ 14 15 /* 16 * emacs.c: Emacs functions 17 */ 18 #include "sys.h" 19 #include "el.h" 20 21 /* em_delete_or_list(): 22 * Delete character under cursor or list completions if at end of line 23 * [^D] 24 */ 25 protected el_action_t 26 /*ARGSUSED*/ 27 em_delete_or_list(el, c) 28 EditLine *el; 29 int c; 30 { 31 if (el->el_line.cursor == el->el_line.lastchar) { /* if I'm at the end */ 32 #ifdef notyet 33 if (el->el_line.cursor == el->el_line.buffer) { /* and the beginning */ 34 #endif 35 term_overwrite(el, STReof, 4);/* then do a EOF */ 36 term__flush(); 37 return CC_EOF; 38 #ifdef notyet 39 } 40 else { 41 re_goto_bottom(el); 42 *el->el_line.lastchar = '\0'; /* just in case */ 43 return CC_LIST_CHOICES; 44 } 45 #endif 46 } 47 else { 48 c_delafter(el, el->el_state.argument); /* delete after dot */ 49 if (el->el_line.cursor > el->el_line.lastchar) 50 el->el_line.cursor = el->el_line.lastchar; /* bounds check */ 51 return CC_REFRESH; 52 } 53 } 54 55 56 /* em_delete_next_word(): 57 * Cut from cursor to end of current word 58 * [M-d] 59 */ 60 protected el_action_t 61 /*ARGSUSED*/ 62 em_delete_next_word(el, c) 63 EditLine *el; 64 int c; 65 { 66 char *cp, *p, *kp; 67 68 if (el->el_line.cursor == el->el_line.lastchar) 69 return CC_ERROR; 70 71 cp = c__next_word(el->el_line.cursor, el->el_line.lastchar, 72 el->el_state.argument, ce__isword); 73 74 for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++) 75 /* save the text */ 76 *kp++ = *p; 77 el->el_chared.c_kill.last = kp; 78 79 c_delafter(el, cp - el->el_line.cursor); /* delete after dot */ 80 if (el->el_line.cursor > el->el_line.lastchar) 81 el->el_line.cursor = el->el_line.lastchar; /* bounds check */ 82 return CC_REFRESH; 83 } 84 85 86 /* em_yank(): 87 * Paste cut buffer at cursor position 88 * [^Y] 89 */ 90 protected el_action_t 91 /*ARGSUSED*/ 92 em_yank(el, c) 93 EditLine *el; 94 int c; 95 { 96 char *kp, *cp; 97 98 if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) 99 return CC_ERROR; 100 101 if (el->el_line.lastchar + 102 (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >= 103 el->el_line.limit) 104 return CC_ERROR; 105 106 el->el_chared.c_kill.mark = el->el_line.cursor; 107 cp = el->el_line.cursor; 108 109 /* open the space, */ 110 c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf); 111 /* copy the chars */ 112 for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++) 113 *cp++ = *kp; 114 115 /* if an arg, cursor at beginning else cursor at end */ 116 if (el->el_state.argument == 1) 117 el->el_line.cursor = cp; 118 119 return CC_REFRESH; 120 } 121 122 123 /* em_kill_line(): 124 * Cut the entire line and save in cut buffer 125 * [^U] 126 */ 127 protected el_action_t 128 /*ARGSUSED*/ 129 em_kill_line(el, c) 130 EditLine *el; 131 int c; 132 { 133 char *kp, *cp; 134 135 cp = el->el_line.buffer; 136 kp = el->el_chared.c_kill.buf; 137 while (cp < el->el_line.lastchar) 138 *kp++ = *cp++; /* copy it */ 139 el->el_chared.c_kill.last = kp; 140 el->el_line.lastchar = el->el_line.buffer; /* zap! -- delete all of it */ 141 el->el_line.cursor = el->el_line.buffer; 142 return CC_REFRESH; 143 } 144 145 146 /* em_kill_region(): 147 * Cut area between mark and cursor and save in cut buffer 148 * [^W] 149 */ 150 protected el_action_t 151 /*ARGSUSED*/ 152 em_kill_region(el, c) 153 EditLine *el; 154 int c; 155 { 156 char *kp, *cp; 157 158 if (!el->el_chared.c_kill.mark) 159 return CC_ERROR; 160 161 if (el->el_chared.c_kill.mark > el->el_line.cursor) { 162 cp = el->el_line.cursor; 163 kp = el->el_chared.c_kill.buf; 164 while (cp < el->el_chared.c_kill.mark) 165 *kp++ = *cp++; /* copy it */ 166 el->el_chared.c_kill.last = kp; 167 c_delafter(el, cp - el->el_line.cursor); 168 } 169 else { /* mark is before cursor */ 170 cp = el->el_chared.c_kill.mark; 171 kp = el->el_chared.c_kill.buf; 172 while (cp < el->el_line.cursor) 173 *kp++ = *cp++; /* copy it */ 174 el->el_chared.c_kill.last = kp; 175 c_delbefore(el, cp - el->el_chared.c_kill.mark); 176 el->el_line.cursor = el->el_chared.c_kill.mark; 177 } 178 return CC_REFRESH; 179 } 180 181 182 /* em_copy_region(): 183 * Copy area between mark and cursor to cut buffer 184 * [M-W] 185 */ 186 protected el_action_t 187 /*ARGSUSED*/ 188 em_copy_region(el, c) 189 EditLine *el; 190 int c; 191 { 192 char *kp, *cp; 193 194 if (el->el_chared.c_kill.mark) 195 return CC_ERROR; 196 197 if (el->el_chared.c_kill.mark > el->el_line.cursor) { 198 cp = el->el_line.cursor; 199 kp = el->el_chared.c_kill.buf; 200 while (cp < el->el_chared.c_kill.mark) 201 *kp++ = *cp++; /* copy it */ 202 el->el_chared.c_kill.last = kp; 203 } 204 else { 205 cp = el->el_chared.c_kill.mark; 206 kp = el->el_chared.c_kill.buf; 207 while (cp < el->el_line.cursor) 208 *kp++ = *cp++; /* copy it */ 209 el->el_chared.c_kill.last = kp; 210 } 211 return CC_NORM; 212 } 213 214 215 /* em_gosmacs_traspose(): 216 * Exchange the two characters before the cursor 217 * Gosling emacs transpose chars [^T] 218 */ 219 protected el_action_t 220 em_gosmacs_traspose(el, c) 221 EditLine *el; 222 int c; 223 { 224 225 if (el->el_line.cursor > &el->el_line.buffer[1]) { 226 /* must have at least two chars entered */ 227 c = el->el_line.cursor[-2]; 228 el->el_line.cursor[-2] = el->el_line.cursor[-1]; 229 el->el_line.cursor[-1] = c; 230 return CC_REFRESH; 231 } 232 else 233 return CC_ERROR; 234 } 235 236 237 /* em_next_word(): 238 * Move next to end of current word 239 * [M-f] 240 */ 241 protected el_action_t 242 /*ARGSUSED*/ 243 em_next_word(el, c) 244 EditLine *el; 245 int c; 246 { 247 if (el->el_line.cursor == el->el_line.lastchar) 248 return CC_ERROR; 249 250 el->el_line.cursor = c__next_word(el->el_line.cursor, el->el_line.lastchar, 251 el->el_state.argument, 252 ce__isword); 253 254 if (el->el_map.type == MAP_VI) 255 if (el->el_chared.c_vcmd.action & DELETE) { 256 cv_delfini(el); 257 return CC_REFRESH; 258 } 259 260 return CC_CURSOR; 261 } 262 263 /* em_upper_case(): 264 * Uppercase the characters from cursor to end of current word 265 * [M-u] 266 */ 267 protected el_action_t 268 /*ARGSUSED*/ 269 em_upper_case(el, c) 270 EditLine *el; 271 int c; 272 { 273 char *cp, *ep; 274 275 ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, 276 el->el_state.argument, ce__isword); 277 278 for (cp = el->el_line.cursor; cp < ep; cp++) 279 if (islower(*cp)) 280 *cp = toupper(*cp); 281 282 el->el_line.cursor = ep; 283 if (el->el_line.cursor > el->el_line.lastchar) 284 el->el_line.cursor = el->el_line.lastchar; 285 return CC_REFRESH; 286 } 287 288 289 /* em_capitol_case(): 290 * Capitalize the characters from cursor to end of current word 291 * [M-c] 292 */ 293 protected el_action_t 294 /*ARGSUSED*/ 295 em_capitol_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 (isalpha(*cp)) { 306 if (islower(*cp)) 307 *cp = toupper(*cp); 308 cp++; 309 break; 310 } 311 } 312 for (; cp < ep; cp++) 313 if (isupper(*cp)) 314 *cp = tolower(*cp); 315 316 el->el_line.cursor = ep; 317 if (el->el_line.cursor > el->el_line.lastchar) 318 el->el_line.cursor = el->el_line.lastchar; 319 return CC_REFRESH; 320 } 321 322 /* em_lower_case(): 323 * Lowercase the characters from cursor to end of current word 324 * [M-l] 325 */ 326 protected el_action_t 327 /*ARGSUSED*/ 328 em_lower_case(el, c) 329 EditLine *el; 330 int c; 331 { 332 char *cp, *ep; 333 334 ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, 335 el->el_state.argument, ce__isword); 336 337 for (cp = el->el_line.cursor; cp < ep; cp++) 338 if (isupper(*cp)) 339 *cp = tolower(*cp); 340 341 el->el_line.cursor = ep; 342 if (el->el_line.cursor > el->el_line.lastchar) 343 el->el_line.cursor = el->el_line.lastchar; 344 return CC_REFRESH; 345 } 346 347 348 /* em_set_mark(): 349 * Set the mark at cursor 350 * [^@] 351 */ 352 protected el_action_t 353 /*ARGSUSED*/ 354 em_set_mark(el, c) 355 EditLine *el; 356 int c; 357 { 358 el->el_chared.c_kill.mark = el->el_line.cursor; 359 return CC_NORM; 360 } 361 362 363 /* em_exchange_mark(): 364 * Exchange the cursor and mark 365 * [^X^X] 366 */ 367 protected el_action_t 368 /*ARGSUSED*/ 369 em_exchange_mark(el, c) 370 EditLine *el; 371 int c; 372 { 373 register char *cp; 374 375 cp = el->el_line.cursor; 376 el->el_line.cursor = el->el_chared.c_kill.mark; 377 el->el_chared.c_kill.mark = cp; 378 return CC_CURSOR; 379 } 380 381 /* em_universal_argument(): 382 * Universal argument (argument times 4) 383 * [^U] 384 */ 385 protected el_action_t 386 /*ARGSUSED*/ 387 em_universal_argument(el, c) 388 EditLine *el; 389 int c; 390 { /* multiply current argument by 4 */ 391 if (el->el_state.argument > 1000000) 392 return CC_ERROR; 393 el->el_state.doingarg = 1; 394 el->el_state.argument *= 4; 395 return CC_ARGHACK; 396 } 397 398 /* em_meta_next(): 399 * Add 8th bit to next character typed 400 * [<ESC>] 401 */ 402 protected el_action_t 403 /*ARGSUSED*/ 404 em_meta_next(el, c) 405 EditLine *el; 406 int c; 407 { 408 el->el_state.metanext = 1; 409 return CC_ARGHACK; 410 } 411 412 413 /* em_toggle_overwrite(): 414 * Switch from insert to overwrite mode or vice versa 415 */ 416 protected el_action_t 417 /*ARGSUSED*/ 418 em_toggle_overwrite(el, c) 419 EditLine *el; 420 int c; 421 { 422 el->el_state.inputmode = 423 (el->el_state.inputmode == MODE_INSERT) ? MODE_REPLACE : MODE_INSERT; 424 return CC_NORM; 425 } 426 427 428 /* em_copy_prev_word(): 429 * Copy current word to cursor 430 */ 431 protected el_action_t 432 /*ARGSUSED*/ 433 em_copy_prev_word(el, c) 434 EditLine *el; 435 int c; 436 { 437 char *cp, *oldc, *dp; 438 439 if (el->el_line.cursor == el->el_line.buffer) 440 return CC_ERROR; 441 442 oldc = el->el_line.cursor; 443 /* does a bounds check */ 444 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, 445 el->el_state.argument, ce__isword); 446 447 c_insert(el, oldc - cp); 448 for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++) 449 *dp++ = *cp; 450 451 el->el_line.cursor = dp; /* put cursor at end */ 452 453 return CC_REFRESH; 454 } 455 456 457 /* em_inc_search_next(): 458 * Emacs incremental next search 459 */ 460 protected el_action_t 461 /*ARGSUSED*/ 462 em_inc_search_next(el, c) 463 EditLine *el; 464 int c; 465 { 466 el->el_search.patlen = 0; 467 return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY); 468 } 469 470 471 /* em_inc_search_prev(): 472 * Emacs incremental reverse search 473 */ 474 protected el_action_t 475 /*ARGSUSED*/ 476 em_inc_search_prev(el, c) 477 EditLine *el; 478 int c; 479 { 480 el->el_search.patlen = 0; 481 return ce_inc_search(el, ED_SEARCH_PREV_HISTORY); 482 } 483