1 1.50 christos /* $NetBSD: common.c,v 1.50 2024/06/30 16:29:42 christos Exp $ */ 2 1.2 lukem 3 1.1 cgd /*- 4 1.1 cgd * Copyright (c) 1992, 1993 5 1.1 cgd * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * This code is derived from software contributed to Berkeley by 8 1.1 cgd * Christos Zoulas of Cornell University. 9 1.1 cgd * 10 1.1 cgd * Redistribution and use in source and binary forms, with or without 11 1.1 cgd * modification, are permitted provided that the following conditions 12 1.1 cgd * are met: 13 1.1 cgd * 1. Redistributions of source code must retain the above copyright 14 1.1 cgd * notice, this list of conditions and the following disclaimer. 15 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 cgd * notice, this list of conditions and the following disclaimer in the 17 1.1 cgd * documentation and/or other materials provided with the distribution. 18 1.16 agc * 3. Neither the name of the University nor the names of its contributors 19 1.1 cgd * may be used to endorse or promote products derived from this software 20 1.1 cgd * without specific prior written permission. 21 1.1 cgd * 22 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.1 cgd * SUCH DAMAGE. 33 1.1 cgd */ 34 1.1 cgd 35 1.11 christos #include "config.h" 36 1.1 cgd #if !defined(lint) && !defined(SCCSID) 37 1.2 lukem #if 0 38 1.1 cgd static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93"; 39 1.2 lukem #else 40 1.50 christos __RCSID("$NetBSD: common.c,v 1.50 2024/06/30 16:29:42 christos Exp $"); 41 1.2 lukem #endif 42 1.1 cgd #endif /* not lint && not SCCSID */ 43 1.1 cgd 44 1.1 cgd /* 45 1.1 cgd * common.c: Common Editor functions 46 1.1 cgd */ 47 1.37 christos #include <ctype.h> 48 1.37 christos #include <string.h> 49 1.37 christos 50 1.1 cgd #include "el.h" 51 1.35 christos #include "common.h" 52 1.45 christos #include "fcns.h" 53 1.35 christos #include "parse.h" 54 1.35 christos #include "vi.h" 55 1.1 cgd 56 1.8 simonb /* ed_end_of_file(): 57 1.1 cgd * Indicate end of file 58 1.1 cgd * [^D] 59 1.1 cgd */ 60 1.46 christos libedit_private el_action_t 61 1.1 cgd /*ARGSUSED*/ 62 1.31 christos ed_end_of_file(EditLine *el, wint_t c __attribute__((__unused__))) 63 1.9 lukem { 64 1.9 lukem 65 1.9 lukem re_goto_bottom(el); 66 1.9 lukem *el->el_line.lastchar = '\0'; 67 1.26 christos return CC_EOF; 68 1.1 cgd } 69 1.1 cgd 70 1.1 cgd 71 1.8 simonb /* ed_insert(): 72 1.1 cgd * Add character to the line 73 1.1 cgd * Insert a character [bound to all insert keys] 74 1.1 cgd */ 75 1.46 christos libedit_private el_action_t 76 1.31 christos ed_insert(EditLine *el, wint_t c) 77 1.9 lukem { 78 1.13 christos int count = el->el_state.argument; 79 1.1 cgd 80 1.9 lukem if (c == '\0') 81 1.26 christos return CC_ERROR; 82 1.1 cgd 83 1.9 lukem if (el->el_line.lastchar + el->el_state.argument >= 84 1.10 jdolecek el->el_line.limit) { 85 1.10 jdolecek /* end of buffer space, try to allocate more */ 86 1.13 christos if (!ch_enlargebufs(el, (size_t) count)) 87 1.10 jdolecek return CC_ERROR; /* error allocating more */ 88 1.10 jdolecek } 89 1.9 lukem 90 1.13 christos if (count == 1) { 91 1.12 christos if (el->el_state.inputmode == MODE_INSERT 92 1.12 christos || el->el_line.cursor >= el->el_line.lastchar) 93 1.12 christos c_insert(el, 1); 94 1.9 lukem 95 1.43 christos *el->el_line.cursor++ = c; 96 1.9 lukem re_fastaddc(el); /* fast refresh for one char. */ 97 1.9 lukem } else { 98 1.12 christos if (el->el_state.inputmode != MODE_REPLACE_1) 99 1.12 christos c_insert(el, el->el_state.argument); 100 1.9 lukem 101 1.13 christos while (count-- && el->el_line.cursor < el->el_line.lastchar) 102 1.43 christos *el->el_line.cursor++ = c; 103 1.9 lukem re_refresh(el); 104 1.9 lukem } 105 1.1 cgd 106 1.9 lukem if (el->el_state.inputmode == MODE_REPLACE_1) 107 1.12 christos return vi_command_mode(el, 0); 108 1.1 cgd 109 1.26 christos return CC_NORM; 110 1.1 cgd } 111 1.1 cgd 112 1.1 cgd 113 1.8 simonb /* ed_delete_prev_word(): 114 1.1 cgd * Delete from beginning of current word to cursor 115 1.1 cgd * [M-^?] [^W] 116 1.1 cgd */ 117 1.46 christos libedit_private el_action_t 118 1.1 cgd /*ARGSUSED*/ 119 1.31 christos ed_delete_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) 120 1.9 lukem { 121 1.43 christos wchar_t *cp, *p, *kp; 122 1.9 lukem 123 1.9 lukem if (el->el_line.cursor == el->el_line.buffer) 124 1.26 christos return CC_ERROR; 125 1.9 lukem 126 1.9 lukem cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, 127 1.9 lukem el->el_state.argument, ce__isword); 128 1.9 lukem 129 1.9 lukem for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++) 130 1.9 lukem *kp++ = *p; 131 1.9 lukem el->el_chared.c_kill.last = kp; 132 1.9 lukem 133 1.22 christos c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */ 134 1.9 lukem el->el_line.cursor = cp; 135 1.9 lukem if (el->el_line.cursor < el->el_line.buffer) 136 1.9 lukem el->el_line.cursor = el->el_line.buffer; /* bounds check */ 137 1.26 christos return CC_REFRESH; 138 1.1 cgd } 139 1.1 cgd 140 1.1 cgd 141 1.8 simonb /* ed_delete_next_char(): 142 1.1 cgd * Delete character under cursor 143 1.1 cgd * [^D] [x] 144 1.1 cgd */ 145 1.46 christos libedit_private el_action_t 146 1.1 cgd /*ARGSUSED*/ 147 1.31 christos ed_delete_next_char(EditLine *el, wint_t c __attribute__((__unused__))) 148 1.1 cgd { 149 1.27 christos #ifdef DEBUG_EDIT 150 1.9 lukem #define EL el->el_line 151 1.40 christos (void) fprintf(el->el_errfile, 152 1.41 christos "\nD(b: %p(%ls) c: %p(%ls) last: %p(%ls) limit: %p(%ls)\n", 153 1.6 christos EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, 154 1.6 christos EL.lastchar, EL.limit, EL.limit); 155 1.1 cgd #endif 156 1.9 lukem if (el->el_line.cursor == el->el_line.lastchar) { 157 1.9 lukem /* if I'm at the end */ 158 1.9 lukem if (el->el_map.type == MAP_VI) { 159 1.9 lukem if (el->el_line.cursor == el->el_line.buffer) { 160 1.9 lukem /* if I'm also at the beginning */ 161 1.1 cgd #ifdef KSHVI 162 1.26 christos return CC_ERROR; 163 1.1 cgd #else 164 1.19 christos /* then do an EOF */ 165 1.25 christos terminal_writec(el, c); 166 1.26 christos return CC_EOF; 167 1.1 cgd #endif 168 1.9 lukem } else { 169 1.1 cgd #ifdef KSHVI 170 1.9 lukem el->el_line.cursor--; 171 1.1 cgd #else 172 1.26 christos return CC_ERROR; 173 1.1 cgd #endif 174 1.9 lukem } 175 1.29 christos } else 176 1.26 christos return CC_ERROR; 177 1.1 cgd } 178 1.9 lukem c_delafter(el, el->el_state.argument); /* delete after dot */ 179 1.29 christos if (el->el_map.type == MAP_VI && 180 1.29 christos el->el_line.cursor >= el->el_line.lastchar && 181 1.9 lukem el->el_line.cursor > el->el_line.buffer) 182 1.9 lukem /* bounds check */ 183 1.9 lukem el->el_line.cursor = el->el_line.lastchar - 1; 184 1.26 christos return CC_REFRESH; 185 1.1 cgd } 186 1.1 cgd 187 1.1 cgd 188 1.8 simonb /* ed_kill_line(): 189 1.1 cgd * Cut to the end of line 190 1.1 cgd * [^K] [^K] 191 1.1 cgd */ 192 1.46 christos libedit_private el_action_t 193 1.1 cgd /*ARGSUSED*/ 194 1.31 christos ed_kill_line(EditLine *el, wint_t c __attribute__((__unused__))) 195 1.9 lukem { 196 1.43 christos wchar_t *kp, *cp; 197 1.9 lukem 198 1.9 lukem cp = el->el_line.cursor; 199 1.9 lukem kp = el->el_chared.c_kill.buf; 200 1.9 lukem while (cp < el->el_line.lastchar) 201 1.9 lukem *kp++ = *cp++; /* copy it */ 202 1.9 lukem el->el_chared.c_kill.last = kp; 203 1.9 lukem /* zap! -- delete to end */ 204 1.9 lukem el->el_line.lastchar = el->el_line.cursor; 205 1.26 christos return CC_REFRESH; 206 1.1 cgd } 207 1.1 cgd 208 1.1 cgd 209 1.8 simonb /* ed_move_to_end(): 210 1.1 cgd * Move cursor to the end of line 211 1.1 cgd * [^E] [^E] 212 1.1 cgd */ 213 1.46 christos libedit_private el_action_t 214 1.1 cgd /*ARGSUSED*/ 215 1.31 christos ed_move_to_end(EditLine *el, wint_t c __attribute__((__unused__))) 216 1.1 cgd { 217 1.9 lukem 218 1.9 lukem el->el_line.cursor = el->el_line.lastchar; 219 1.9 lukem if (el->el_map.type == MAP_VI) { 220 1.13 christos if (el->el_chared.c_vcmd.action != NOP) { 221 1.9 lukem cv_delfini(el); 222 1.26 christos return CC_REFRESH; 223 1.9 lukem } 224 1.21 aymeric #ifdef VI_MOVE 225 1.50 christos if (el->el_line.cursor > el->el_line.buffer) 226 1.50 christos el->el_line.cursor--; 227 1.21 aymeric #endif 228 1.1 cgd } 229 1.26 christos return CC_CURSOR; 230 1.1 cgd } 231 1.1 cgd 232 1.1 cgd 233 1.8 simonb /* ed_move_to_beg(): 234 1.1 cgd * Move cursor to the beginning of line 235 1.1 cgd * [^A] [^A] 236 1.1 cgd */ 237 1.46 christos libedit_private el_action_t 238 1.1 cgd /*ARGSUSED*/ 239 1.31 christos ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__))) 240 1.9 lukem { 241 1.9 lukem 242 1.9 lukem el->el_line.cursor = el->el_line.buffer; 243 1.9 lukem 244 1.9 lukem if (el->el_map.type == MAP_VI) { 245 1.9 lukem /* We want FIRST non space character */ 246 1.41 christos while (iswspace(*el->el_line.cursor)) 247 1.9 lukem el->el_line.cursor++; 248 1.13 christos if (el->el_chared.c_vcmd.action != NOP) { 249 1.9 lukem cv_delfini(el); 250 1.26 christos return CC_REFRESH; 251 1.9 lukem } 252 1.1 cgd } 253 1.26 christos return CC_CURSOR; 254 1.1 cgd } 255 1.1 cgd 256 1.1 cgd 257 1.8 simonb /* ed_transpose_chars(): 258 1.1 cgd * Exchange the character to the left of the cursor with the one under it 259 1.1 cgd * [^T] [^T] 260 1.1 cgd */ 261 1.46 christos libedit_private el_action_t 262 1.31 christos ed_transpose_chars(EditLine *el, wint_t c) 263 1.9 lukem { 264 1.9 lukem 265 1.9 lukem if (el->el_line.cursor < el->el_line.lastchar) { 266 1.9 lukem if (el->el_line.lastchar <= &el->el_line.buffer[1]) 267 1.26 christos return CC_ERROR; 268 1.9 lukem else 269 1.9 lukem el->el_line.cursor++; 270 1.9 lukem } 271 1.9 lukem if (el->el_line.cursor > &el->el_line.buffer[1]) { 272 1.9 lukem /* must have at least two chars entered */ 273 1.9 lukem c = el->el_line.cursor[-2]; 274 1.9 lukem el->el_line.cursor[-2] = el->el_line.cursor[-1]; 275 1.43 christos el->el_line.cursor[-1] = c; 276 1.26 christos return CC_REFRESH; 277 1.9 lukem } else 278 1.26 christos return CC_ERROR; 279 1.1 cgd } 280 1.1 cgd 281 1.1 cgd 282 1.8 simonb /* ed_next_char(): 283 1.1 cgd * Move to the right one character 284 1.1 cgd * [^F] [^F] 285 1.1 cgd */ 286 1.46 christos libedit_private el_action_t 287 1.1 cgd /*ARGSUSED*/ 288 1.31 christos ed_next_char(EditLine *el, wint_t c __attribute__((__unused__))) 289 1.1 cgd { 290 1.43 christos wchar_t *lim = el->el_line.lastchar; 291 1.1 cgd 292 1.13 christos if (el->el_line.cursor >= lim || 293 1.13 christos (el->el_line.cursor == lim - 1 && 294 1.13 christos el->el_map.type == MAP_VI && 295 1.13 christos el->el_chared.c_vcmd.action == NOP)) 296 1.26 christos return CC_ERROR; 297 1.1 cgd 298 1.9 lukem el->el_line.cursor += el->el_state.argument; 299 1.13 christos if (el->el_line.cursor > lim) 300 1.13 christos el->el_line.cursor = lim; 301 1.1 cgd 302 1.9 lukem if (el->el_map.type == MAP_VI) 303 1.13 christos if (el->el_chared.c_vcmd.action != NOP) { 304 1.9 lukem cv_delfini(el); 305 1.26 christos return CC_REFRESH; 306 1.9 lukem } 307 1.26 christos return CC_CURSOR; 308 1.1 cgd } 309 1.1 cgd 310 1.1 cgd 311 1.8 simonb /* ed_prev_word(): 312 1.1 cgd * Move to the beginning of the current word 313 1.1 cgd * [M-b] [b] 314 1.1 cgd */ 315 1.46 christos libedit_private el_action_t 316 1.1 cgd /*ARGSUSED*/ 317 1.31 christos ed_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) 318 1.1 cgd { 319 1.1 cgd 320 1.9 lukem if (el->el_line.cursor == el->el_line.buffer) 321 1.26 christos return CC_ERROR; 322 1.1 cgd 323 1.9 lukem el->el_line.cursor = c__prev_word(el->el_line.cursor, 324 1.9 lukem el->el_line.buffer, 325 1.9 lukem el->el_state.argument, 326 1.9 lukem ce__isword); 327 1.1 cgd 328 1.9 lukem if (el->el_map.type == MAP_VI) 329 1.13 christos if (el->el_chared.c_vcmd.action != NOP) { 330 1.9 lukem cv_delfini(el); 331 1.26 christos return CC_REFRESH; 332 1.9 lukem } 333 1.26 christos return CC_CURSOR; 334 1.1 cgd } 335 1.1 cgd 336 1.1 cgd 337 1.8 simonb /* ed_prev_char(): 338 1.1 cgd * Move to the left one character 339 1.1 cgd * [^B] [^B] 340 1.1 cgd */ 341 1.46 christos libedit_private el_action_t 342 1.1 cgd /*ARGSUSED*/ 343 1.31 christos ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) 344 1.1 cgd { 345 1.1 cgd 346 1.9 lukem if (el->el_line.cursor > el->el_line.buffer) { 347 1.9 lukem el->el_line.cursor -= el->el_state.argument; 348 1.9 lukem if (el->el_line.cursor < el->el_line.buffer) 349 1.9 lukem el->el_line.cursor = el->el_line.buffer; 350 1.9 lukem 351 1.9 lukem if (el->el_map.type == MAP_VI) 352 1.13 christos if (el->el_chared.c_vcmd.action != NOP) { 353 1.9 lukem cv_delfini(el); 354 1.26 christos return CC_REFRESH; 355 1.9 lukem } 356 1.26 christos return CC_CURSOR; 357 1.9 lukem } else 358 1.26 christos return CC_ERROR; 359 1.1 cgd } 360 1.1 cgd 361 1.1 cgd 362 1.8 simonb /* ed_quoted_insert(): 363 1.1 cgd * Add the next character typed verbatim 364 1.1 cgd * [^V] [^V] 365 1.1 cgd */ 366 1.46 christos libedit_private el_action_t 367 1.48 christos /*ARGSUSED*/ 368 1.48 christos ed_quoted_insert(EditLine *el, wint_t c __attribute__((__unused__))) 369 1.9 lukem { 370 1.9 lukem int num; 371 1.48 christos wchar_t ch; 372 1.9 lukem 373 1.9 lukem tty_quotemode(el); 374 1.48 christos num = el_wgetc(el, &ch); 375 1.9 lukem tty_noquotemode(el); 376 1.9 lukem if (num == 1) 377 1.48 christos return ed_insert(el, ch); 378 1.9 lukem else 379 1.26 christos return ed_end_of_file(el, 0); 380 1.1 cgd } 381 1.1 cgd 382 1.1 cgd 383 1.8 simonb /* ed_digit(): 384 1.1 cgd * Adds to argument or enters a digit 385 1.1 cgd */ 386 1.46 christos libedit_private el_action_t 387 1.31 christos ed_digit(EditLine *el, wint_t c) 388 1.9 lukem { 389 1.9 lukem 390 1.41 christos if (!iswdigit(c)) 391 1.26 christos return CC_ERROR; 392 1.9 lukem 393 1.9 lukem if (el->el_state.doingarg) { 394 1.9 lukem /* if doing an arg, add this in... */ 395 1.9 lukem if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT) 396 1.9 lukem el->el_state.argument = c - '0'; 397 1.9 lukem else { 398 1.9 lukem if (el->el_state.argument > 1000000) 399 1.26 christos return CC_ERROR; 400 1.9 lukem el->el_state.argument = 401 1.9 lukem (el->el_state.argument * 10) + (c - '0'); 402 1.9 lukem } 403 1.26 christos return CC_ARGHACK; 404 1.12 christos } 405 1.9 lukem 406 1.12 christos return ed_insert(el, c); 407 1.1 cgd } 408 1.1 cgd 409 1.1 cgd 410 1.8 simonb /* ed_argument_digit(): 411 1.1 cgd * Digit that starts argument 412 1.1 cgd * For ESC-n 413 1.1 cgd */ 414 1.46 christos libedit_private el_action_t 415 1.31 christos ed_argument_digit(EditLine *el, wint_t c) 416 1.9 lukem { 417 1.9 lukem 418 1.41 christos if (!iswdigit(c)) 419 1.26 christos return CC_ERROR; 420 1.9 lukem 421 1.9 lukem if (el->el_state.doingarg) { 422 1.9 lukem if (el->el_state.argument > 1000000) 423 1.26 christos return CC_ERROR; 424 1.9 lukem el->el_state.argument = (el->el_state.argument * 10) + 425 1.9 lukem (c - '0'); 426 1.9 lukem } else { /* else starting an argument */ 427 1.9 lukem el->el_state.argument = c - '0'; 428 1.9 lukem el->el_state.doingarg = 1; 429 1.9 lukem } 430 1.26 christos return CC_ARGHACK; 431 1.1 cgd } 432 1.1 cgd 433 1.1 cgd 434 1.8 simonb /* ed_unassigned(): 435 1.1 cgd * Indicates unbound character 436 1.1 cgd * Bound to keys that are not assigned 437 1.1 cgd */ 438 1.46 christos libedit_private el_action_t 439 1.1 cgd /*ARGSUSED*/ 440 1.28 christos ed_unassigned(EditLine *el __attribute__((__unused__)), 441 1.31 christos wint_t c __attribute__((__unused__))) 442 1.9 lukem { 443 1.9 lukem 444 1.26 christos return CC_ERROR; 445 1.1 cgd } 446 1.1 cgd 447 1.1 cgd 448 1.44 christos /* ed_ignore(): 449 1.44 christos * Input characters that have no effect 450 1.44 christos * [^C ^O ^Q ^S ^Z ^\ ^]] [^C ^O ^Q ^S ^\] 451 1.1 cgd */ 452 1.46 christos libedit_private el_action_t 453 1.1 cgd /*ARGSUSED*/ 454 1.44 christos ed_ignore(EditLine *el __attribute__((__unused__)), 455 1.31 christos wint_t c __attribute__((__unused__))) 456 1.8 simonb { 457 1.9 lukem 458 1.26 christos return CC_NORM; 459 1.1 cgd } 460 1.1 cgd 461 1.1 cgd 462 1.8 simonb /* ed_newline(): 463 1.1 cgd * Execute command 464 1.1 cgd * [^J] 465 1.1 cgd */ 466 1.46 christos libedit_private el_action_t 467 1.1 cgd /*ARGSUSED*/ 468 1.31 christos ed_newline(EditLine *el, wint_t c __attribute__((__unused__))) 469 1.9 lukem { 470 1.9 lukem 471 1.9 lukem re_goto_bottom(el); 472 1.9 lukem *el->el_line.lastchar++ = '\n'; 473 1.9 lukem *el->el_line.lastchar = '\0'; 474 1.26 christos return CC_NEWLINE; 475 1.1 cgd } 476 1.1 cgd 477 1.1 cgd 478 1.8 simonb /* ed_delete_prev_char(): 479 1.1 cgd * Delete the character to the left of the cursor 480 1.1 cgd * [^?] 481 1.1 cgd */ 482 1.46 christos libedit_private el_action_t 483 1.1 cgd /*ARGSUSED*/ 484 1.31 christos ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) 485 1.9 lukem { 486 1.9 lukem 487 1.9 lukem if (el->el_line.cursor <= el->el_line.buffer) 488 1.26 christos return CC_ERROR; 489 1.9 lukem 490 1.9 lukem c_delbefore(el, el->el_state.argument); 491 1.9 lukem el->el_line.cursor -= el->el_state.argument; 492 1.9 lukem if (el->el_line.cursor < el->el_line.buffer) 493 1.9 lukem el->el_line.cursor = el->el_line.buffer; 494 1.26 christos return CC_REFRESH; 495 1.1 cgd } 496 1.1 cgd 497 1.1 cgd 498 1.8 simonb /* ed_clear_screen(): 499 1.1 cgd * Clear screen leaving current line at the top 500 1.1 cgd * [^L] 501 1.1 cgd */ 502 1.46 christos libedit_private el_action_t 503 1.1 cgd /*ARGSUSED*/ 504 1.31 christos ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__))) 505 1.9 lukem { 506 1.9 lukem 507 1.25 christos terminal_clear_screen(el); /* clear the whole real screen */ 508 1.9 lukem re_clear_display(el); /* reset everything */ 509 1.26 christos return CC_REFRESH; 510 1.1 cgd } 511 1.1 cgd 512 1.1 cgd 513 1.8 simonb /* ed_redisplay(): 514 1.1 cgd * Redisplay everything 515 1.1 cgd * ^R 516 1.1 cgd */ 517 1.46 christos libedit_private el_action_t 518 1.1 cgd /*ARGSUSED*/ 519 1.38 christos ed_redisplay(EditLine *el __attribute__((__unused__)), 520 1.31 christos wint_t c __attribute__((__unused__))) 521 1.1 cgd { 522 1.9 lukem 523 1.26 christos return CC_REDISPLAY; 524 1.1 cgd } 525 1.1 cgd 526 1.1 cgd 527 1.8 simonb /* ed_start_over(): 528 1.1 cgd * Erase current line and start from scratch 529 1.1 cgd * [^G] 530 1.1 cgd */ 531 1.46 christos libedit_private el_action_t 532 1.1 cgd /*ARGSUSED*/ 533 1.31 christos ed_start_over(EditLine *el, wint_t c __attribute__((__unused__))) 534 1.1 cgd { 535 1.9 lukem 536 1.47 christos ch_reset(el); 537 1.26 christos return CC_REFRESH; 538 1.1 cgd } 539 1.1 cgd 540 1.1 cgd 541 1.8 simonb /* ed_sequence_lead_in(): 542 1.1 cgd * First character in a bound sequence 543 1.1 cgd * Placeholder for external keys 544 1.1 cgd */ 545 1.46 christos libedit_private el_action_t 546 1.1 cgd /*ARGSUSED*/ 547 1.38 christos ed_sequence_lead_in(EditLine *el __attribute__((__unused__)), 548 1.31 christos wint_t c __attribute__((__unused__))) 549 1.1 cgd { 550 1.9 lukem 551 1.26 christos return CC_NORM; 552 1.1 cgd } 553 1.1 cgd 554 1.1 cgd 555 1.8 simonb /* ed_prev_history(): 556 1.1 cgd * Move to the previous history line 557 1.1 cgd * [^P] [k] 558 1.1 cgd */ 559 1.46 christos libedit_private el_action_t 560 1.1 cgd /*ARGSUSED*/ 561 1.31 christos ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__))) 562 1.9 lukem { 563 1.9 lukem char beep = 0; 564 1.13 christos int sv_event = el->el_history.eventno; 565 1.9 lukem 566 1.12 christos el->el_chared.c_undo.len = -1; 567 1.9 lukem *el->el_line.lastchar = '\0'; /* just in case */ 568 1.9 lukem 569 1.9 lukem if (el->el_history.eventno == 0) { /* save the current buffer 570 1.9 lukem * away */ 571 1.42 christos (void) wcsncpy(el->el_history.buf, el->el_line.buffer, 572 1.9 lukem EL_BUFSIZ); 573 1.9 lukem el->el_history.last = el->el_history.buf + 574 1.9 lukem (el->el_line.lastchar - el->el_line.buffer); 575 1.9 lukem } 576 1.9 lukem el->el_history.eventno += el->el_state.argument; 577 1.9 lukem 578 1.9 lukem if (hist_get(el) == CC_ERROR) { 579 1.13 christos if (el->el_map.type == MAP_VI) { 580 1.13 christos el->el_history.eventno = sv_event; 581 1.13 christos } 582 1.9 lukem beep = 1; 583 1.9 lukem /* el->el_history.eventno was fixed by first call */ 584 1.9 lukem (void) hist_get(el); 585 1.9 lukem } 586 1.9 lukem if (beep) 587 1.13 christos return CC_REFRESH_BEEP; 588 1.13 christos return CC_REFRESH; 589 1.1 cgd } 590 1.1 cgd 591 1.1 cgd 592 1.8 simonb /* ed_next_history(): 593 1.1 cgd * Move to the next history line 594 1.1 cgd * [^N] [j] 595 1.1 cgd */ 596 1.46 christos libedit_private el_action_t 597 1.1 cgd /*ARGSUSED*/ 598 1.31 christos ed_next_history(EditLine *el, wint_t c __attribute__((__unused__))) 599 1.1 cgd { 600 1.13 christos el_action_t beep = CC_REFRESH, rval; 601 1.1 cgd 602 1.12 christos el->el_chared.c_undo.len = -1; 603 1.9 lukem *el->el_line.lastchar = '\0'; /* just in case */ 604 1.1 cgd 605 1.9 lukem el->el_history.eventno -= el->el_state.argument; 606 1.1 cgd 607 1.9 lukem if (el->el_history.eventno < 0) { 608 1.9 lukem el->el_history.eventno = 0; 609 1.13 christos beep = CC_REFRESH_BEEP; 610 1.9 lukem } 611 1.13 christos rval = hist_get(el); 612 1.13 christos if (rval == CC_REFRESH) 613 1.13 christos return beep; 614 1.13 christos return rval; 615 1.13 christos 616 1.1 cgd } 617 1.1 cgd 618 1.1 cgd 619 1.8 simonb /* ed_search_prev_history(): 620 1.1 cgd * Search previous in history for a line matching the current 621 1.1 cgd * next search history [M-P] [K] 622 1.1 cgd */ 623 1.46 christos libedit_private el_action_t 624 1.1 cgd /*ARGSUSED*/ 625 1.31 christos ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__))) 626 1.9 lukem { 627 1.43 christos const wchar_t *hp; 628 1.9 lukem int h; 629 1.36 christos int found = 0; 630 1.9 lukem 631 1.9 lukem el->el_chared.c_vcmd.action = NOP; 632 1.12 christos el->el_chared.c_undo.len = -1; 633 1.9 lukem *el->el_line.lastchar = '\0'; /* just in case */ 634 1.9 lukem if (el->el_history.eventno < 0) { 635 1.1 cgd #ifdef DEBUG_EDIT 636 1.9 lukem (void) fprintf(el->el_errfile, 637 1.9 lukem "e_prev_search_hist(): eventno < 0;\n"); 638 1.1 cgd #endif 639 1.9 lukem el->el_history.eventno = 0; 640 1.26 christos return CC_ERROR; 641 1.9 lukem } 642 1.9 lukem if (el->el_history.eventno == 0) { 643 1.42 christos (void) wcsncpy(el->el_history.buf, el->el_line.buffer, 644 1.9 lukem EL_BUFSIZ); 645 1.9 lukem el->el_history.last = el->el_history.buf + 646 1.9 lukem (el->el_line.lastchar - el->el_line.buffer); 647 1.9 lukem } 648 1.9 lukem if (el->el_history.ref == NULL) 649 1.26 christos return CC_ERROR; 650 1.1 cgd 651 1.9 lukem hp = HIST_FIRST(el); 652 1.9 lukem if (hp == NULL) 653 1.26 christos return CC_ERROR; 654 1.1 cgd 655 1.9 lukem c_setpat(el); /* Set search pattern !! */ 656 1.1 cgd 657 1.9 lukem for (h = 1; h <= el->el_history.eventno; h++) 658 1.9 lukem hp = HIST_NEXT(el); 659 1.1 cgd 660 1.9 lukem while (hp != NULL) { 661 1.1 cgd #ifdef SDEBUG 662 1.49 ryo (void) fprintf(el->el_errfile, "Comparing with \"%ls\"\n", hp); 663 1.1 cgd #endif 664 1.42 christos if ((wcsncmp(hp, el->el_line.buffer, (size_t) 665 1.9 lukem (el->el_line.lastchar - el->el_line.buffer)) || 666 1.9 lukem hp[el->el_line.lastchar - el->el_line.buffer]) && 667 1.9 lukem c_hmatch(el, hp)) { 668 1.36 christos found = 1; 669 1.9 lukem break; 670 1.9 lukem } 671 1.9 lukem h++; 672 1.9 lukem hp = HIST_NEXT(el); 673 1.9 lukem } 674 1.1 cgd 675 1.9 lukem if (!found) { 676 1.1 cgd #ifdef SDEBUG 677 1.9 lukem (void) fprintf(el->el_errfile, "not found\n"); 678 1.1 cgd #endif 679 1.26 christos return CC_ERROR; 680 1.9 lukem } 681 1.9 lukem el->el_history.eventno = h; 682 1.1 cgd 683 1.26 christos return hist_get(el); 684 1.1 cgd } 685 1.1 cgd 686 1.1 cgd 687 1.8 simonb /* ed_search_next_history(): 688 1.1 cgd * Search next in history for a line matching the current 689 1.1 cgd * [M-N] [J] 690 1.1 cgd */ 691 1.46 christos libedit_private el_action_t 692 1.1 cgd /*ARGSUSED*/ 693 1.31 christos ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__))) 694 1.1 cgd { 695 1.43 christos const wchar_t *hp; 696 1.9 lukem int h; 697 1.36 christos int found = 0; 698 1.1 cgd 699 1.9 lukem el->el_chared.c_vcmd.action = NOP; 700 1.12 christos el->el_chared.c_undo.len = -1; 701 1.9 lukem *el->el_line.lastchar = '\0'; /* just in case */ 702 1.1 cgd 703 1.9 lukem if (el->el_history.eventno == 0) 704 1.26 christos return CC_ERROR; 705 1.1 cgd 706 1.9 lukem if (el->el_history.ref == NULL) 707 1.26 christos return CC_ERROR; 708 1.1 cgd 709 1.9 lukem hp = HIST_FIRST(el); 710 1.9 lukem if (hp == NULL) 711 1.26 christos return CC_ERROR; 712 1.1 cgd 713 1.9 lukem c_setpat(el); /* Set search pattern !! */ 714 1.1 cgd 715 1.9 lukem for (h = 1; h < el->el_history.eventno && hp; h++) { 716 1.1 cgd #ifdef SDEBUG 717 1.49 ryo (void) fprintf(el->el_errfile, "Comparing with \"%ls\"\n", hp); 718 1.1 cgd #endif 719 1.42 christos if ((wcsncmp(hp, el->el_line.buffer, (size_t) 720 1.9 lukem (el->el_line.lastchar - el->el_line.buffer)) || 721 1.9 lukem hp[el->el_line.lastchar - el->el_line.buffer]) && 722 1.9 lukem c_hmatch(el, hp)) 723 1.9 lukem found = h; 724 1.9 lukem hp = HIST_NEXT(el); 725 1.9 lukem } 726 1.1 cgd 727 1.9 lukem if (!found) { /* is it the current history number? */ 728 1.9 lukem if (!c_hmatch(el, el->el_history.buf)) { 729 1.1 cgd #ifdef SDEBUG 730 1.9 lukem (void) fprintf(el->el_errfile, "not found\n"); 731 1.1 cgd #endif 732 1.26 christos return CC_ERROR; 733 1.9 lukem } 734 1.1 cgd } 735 1.9 lukem el->el_history.eventno = found; 736 1.1 cgd 737 1.26 christos return hist_get(el); 738 1.1 cgd } 739 1.1 cgd 740 1.1 cgd 741 1.1 cgd /* ed_prev_line(): 742 1.1 cgd * Move up one line 743 1.1 cgd * Could be [k] [^p] 744 1.1 cgd */ 745 1.46 christos libedit_private el_action_t 746 1.1 cgd /*ARGSUSED*/ 747 1.31 christos ed_prev_line(EditLine *el, wint_t c __attribute__((__unused__))) 748 1.9 lukem { 749 1.43 christos wchar_t *ptr; 750 1.9 lukem int nchars = c_hpos(el); 751 1.8 simonb 752 1.9 lukem /* 753 1.9 lukem * Move to the line requested 754 1.9 lukem */ 755 1.9 lukem if (*(ptr = el->el_line.cursor) == '\n') 756 1.9 lukem ptr--; 757 1.9 lukem 758 1.9 lukem for (; ptr >= el->el_line.buffer; ptr--) 759 1.9 lukem if (*ptr == '\n' && --el->el_state.argument <= 0) 760 1.9 lukem break; 761 1.9 lukem 762 1.9 lukem if (el->el_state.argument > 0) 763 1.26 christos return CC_ERROR; 764 1.9 lukem 765 1.9 lukem /* 766 1.9 lukem * Move to the beginning of the line 767 1.9 lukem */ 768 1.9 lukem for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--) 769 1.9 lukem continue; 770 1.9 lukem 771 1.9 lukem /* 772 1.9 lukem * Move to the character requested 773 1.9 lukem */ 774 1.9 lukem for (ptr++; 775 1.9 lukem nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 776 1.9 lukem ptr++) 777 1.9 lukem continue; 778 1.9 lukem 779 1.9 lukem el->el_line.cursor = ptr; 780 1.26 christos return CC_CURSOR; 781 1.1 cgd } 782 1.1 cgd 783 1.1 cgd 784 1.1 cgd /* ed_next_line(): 785 1.1 cgd * Move down one line 786 1.1 cgd * Could be [j] [^n] 787 1.1 cgd */ 788 1.46 christos libedit_private el_action_t 789 1.1 cgd /*ARGSUSED*/ 790 1.31 christos ed_next_line(EditLine *el, wint_t c __attribute__((__unused__))) 791 1.9 lukem { 792 1.43 christos wchar_t *ptr; 793 1.9 lukem int nchars = c_hpos(el); 794 1.8 simonb 795 1.9 lukem /* 796 1.9 lukem * Move to the line requested 797 1.9 lukem */ 798 1.9 lukem for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++) 799 1.9 lukem if (*ptr == '\n' && --el->el_state.argument <= 0) 800 1.9 lukem break; 801 1.9 lukem 802 1.9 lukem if (el->el_state.argument > 0) 803 1.26 christos return CC_ERROR; 804 1.9 lukem 805 1.9 lukem /* 806 1.9 lukem * Move to the character requested 807 1.9 lukem */ 808 1.9 lukem for (ptr++; 809 1.9 lukem nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 810 1.9 lukem ptr++) 811 1.9 lukem continue; 812 1.9 lukem 813 1.9 lukem el->el_line.cursor = ptr; 814 1.26 christos return CC_CURSOR; 815 1.1 cgd } 816 1.1 cgd 817 1.1 cgd 818 1.8 simonb /* ed_command(): 819 1.1 cgd * Editline extended command 820 1.1 cgd * [M-X] [:] 821 1.1 cgd */ 822 1.46 christos libedit_private el_action_t 823 1.1 cgd /*ARGSUSED*/ 824 1.31 christos ed_command(EditLine *el, wint_t c __attribute__((__unused__))) 825 1.9 lukem { 826 1.43 christos wchar_t tmpbuf[EL_BUFSIZ]; 827 1.9 lukem int tmplen; 828 1.9 lukem 829 1.42 christos tmplen = c_gets(el, tmpbuf, L"\n: "); 830 1.25 christos terminal__putc(el, '\n'); 831 1.9 lukem 832 1.14 christos if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) 833 1.25 christos terminal_beep(el); 834 1.9 lukem 835 1.14 christos el->el_map.current = el->el_map.key; 836 1.14 christos re_clear_display(el); 837 1.14 christos return CC_REFRESH; 838 1.1 cgd } 839