1313981Spfg/* $NetBSD: vi.c,v 1.55 2016/03/02 19:24:20 christos Exp $ */ 2276881Sbapt 31573Srgrimes/*- 41573Srgrimes * Copyright (c) 1992, 1993 51573Srgrimes * The Regents of the University of California. All rights reserved. 61573Srgrimes * 71573Srgrimes * This code is derived from software contributed to Berkeley by 81573Srgrimes * Christos Zoulas of Cornell University. 91573Srgrimes * 101573Srgrimes * Redistribution and use in source and binary forms, with or without 111573Srgrimes * modification, are permitted provided that the following conditions 121573Srgrimes * are met: 131573Srgrimes * 1. Redistributions of source code must retain the above copyright 141573Srgrimes * notice, this list of conditions and the following disclaimer. 151573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161573Srgrimes * notice, this list of conditions and the following disclaimer in the 171573Srgrimes * documentation and/or other materials provided with the distribution. 18148834Sstefanf * 3. Neither the name of the University nor the names of its contributors 191573Srgrimes * may be used to endorse or promote products derived from this software 201573Srgrimes * without specific prior written permission. 211573Srgrimes * 221573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321573Srgrimes * SUCH DAMAGE. 331573Srgrimes */ 341573Srgrimes 35276881Sbapt#include "config.h" 361573Srgrimes#if !defined(lint) && !defined(SCCSID) 37276881Sbapt#if 0 381573Srgrimesstatic char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; 39276881Sbapt#else 40313981Spfg__RCSID("$NetBSD: vi.c,v 1.55 2016/03/02 19:24:20 christos Exp $"); 41276881Sbapt#endif 421573Srgrimes#endif /* not lint && not SCCSID */ 4384260Sobrien#include <sys/cdefs.h> 4484260Sobrien__FBSDID("$FreeBSD: stable/11/lib/libedit/vi.c 313981 2017-02-20 03:33:59Z pfg $"); 451573Srgrimes 461573Srgrimes/* 471573Srgrimes * vi.c: Vi mode commands. 481573Srgrimes */ 49313981Spfg#include <sys/wait.h> 50313981Spfg#include <ctype.h> 51313981Spfg#include <limits.h> 52313981Spfg#include <stdlib.h> 53313981Spfg#include <string.h> 54313981Spfg#include <unistd.h> 55313981Spfg 561573Srgrimes#include "el.h" 57313981Spfg#include "common.h" 58313981Spfg#include "emacs.h" 59313981Spfg#include "vi.h" 601573Srgrimes 61313981Spfgprivate el_action_t cv_action(EditLine *, wint_t); 62313981Spfgprivate el_action_t cv_paste(EditLine *, wint_t); 631573Srgrimes 641573Srgrimes/* cv_action(): 651573Srgrimes * Handle vi actions. 661573Srgrimes */ 671573Srgrimesprivate el_action_t 68313981Spfgcv_action(EditLine *el, wint_t c) 691573Srgrimes{ 701573Srgrimes 71148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 72148834Sstefanf /* 'cc', 'dd' and (possibly) friends */ 73313981Spfg if (c != (wint_t)el->el_chared.c_vcmd.action) 74148834Sstefanf return CC_ERROR; 75148834Sstefanf 76148834Sstefanf if (!(c & YANK)) 77148834Sstefanf cv_undo(el); 78148834Sstefanf cv_yank(el, el->el_line.buffer, 79237448Spfg (int)(el->el_line.lastchar - el->el_line.buffer)); 8084260Sobrien el->el_chared.c_vcmd.action = NOP; 8184260Sobrien el->el_chared.c_vcmd.pos = 0; 82148923Sstefanf if (!(c & YANK)) { 83148923Sstefanf el->el_line.lastchar = el->el_line.buffer; 84148923Sstefanf el->el_line.cursor = el->el_line.buffer; 85148923Sstefanf } 8684260Sobrien if (c & INSERT) 8784260Sobrien el->el_map.current = el->el_map.key; 888870Srgrimes 89276881Sbapt return CC_REFRESH; 9084260Sobrien } 9184260Sobrien el->el_chared.c_vcmd.pos = el->el_line.cursor; 9284260Sobrien el->el_chared.c_vcmd.action = c; 93276881Sbapt return CC_ARGHACK; 941573Srgrimes} 951573Srgrimes 961573Srgrimes/* cv_paste(): 971573Srgrimes * Paste previous deletion before or after the cursor 981573Srgrimes */ 9984260Sobrienprivate el_action_t 100313981Spfgcv_paste(EditLine *el, wint_t c) 1011573Srgrimes{ 102148834Sstefanf c_kill_t *k = &el->el_chared.c_kill; 103237448Spfg size_t len = (size_t)(k->last - k->buf); 10484260Sobrien 105148834Sstefanf if (k->buf == NULL || len == 0) 106276881Sbapt return CC_ERROR; 1071573Srgrimes#ifdef DEBUG_PASTE 108313981Spfg (void) fprintf(el->el_errfile, "Paste: \"" FSTARSTR "\"\n", (int)len, 109313981Spfg k->buf); 1101573Srgrimes#endif 1111573Srgrimes 112148834Sstefanf cv_undo(el); 113148834Sstefanf 11484260Sobrien if (!c && el->el_line.cursor < el->el_line.lastchar) 11584260Sobrien el->el_line.cursor++; 1168870Srgrimes 117237448Spfg c_insert(el, (int)len); 118148834Sstefanf if (el->el_line.cursor + len > el->el_line.lastchar) 119276881Sbapt return CC_ERROR; 120276881Sbapt (void) memcpy(el->el_line.cursor, k->buf, len * 121276881Sbapt sizeof(*el->el_line.cursor)); 122148923Sstefanf 123276881Sbapt return CC_REFRESH; 1241573Srgrimes} 1251573Srgrimes 1261573Srgrimes 1278870Srgrimes/* vi_paste_next(): 1281573Srgrimes * Vi paste previous deletion to the right of the cursor 1291573Srgrimes * [p] 1301573Srgrimes */ 1311573Srgrimesprotected el_action_t 1321573Srgrimes/*ARGSUSED*/ 133313981Spfgvi_paste_next(EditLine *el, wint_t c __attribute__((__unused__))) 1341573Srgrimes{ 13584260Sobrien 136276881Sbapt return cv_paste(el, 0); 1371573Srgrimes} 1381573Srgrimes 1391573Srgrimes 1408870Srgrimes/* vi_paste_prev(): 1411573Srgrimes * Vi paste previous deletion to the left of the cursor 1421573Srgrimes * [P] 1431573Srgrimes */ 1441573Srgrimesprotected el_action_t 1451573Srgrimes/*ARGSUSED*/ 146313981Spfgvi_paste_prev(EditLine *el, wint_t c __attribute__((__unused__))) 1471573Srgrimes{ 14884260Sobrien 149276881Sbapt return cv_paste(el, 1); 1501573Srgrimes} 1511573Srgrimes 1521573Srgrimes 153148834Sstefanf/* vi_prev_big_word(): 1541573Srgrimes * Vi move to the previous space delimited word 1551573Srgrimes * [B] 1561573Srgrimes */ 1571573Srgrimesprotected el_action_t 1581573Srgrimes/*ARGSUSED*/ 159313981Spfgvi_prev_big_word(EditLine *el, wint_t c __attribute__((__unused__))) 1601573Srgrimes{ 1611573Srgrimes 16284260Sobrien if (el->el_line.cursor == el->el_line.buffer) 163276881Sbapt return CC_ERROR; 1641573Srgrimes 165148834Sstefanf el->el_line.cursor = cv_prev_word(el->el_line.cursor, 16684260Sobrien el->el_line.buffer, 16784260Sobrien el->el_state.argument, 168148834Sstefanf cv__isWord); 1691573Srgrimes 170148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 17184260Sobrien cv_delfini(el); 172276881Sbapt return CC_REFRESH; 17384260Sobrien } 174276881Sbapt return CC_CURSOR; 1751573Srgrimes} 1761573Srgrimes 1771573Srgrimes 1788870Srgrimes/* vi_prev_word(): 1791573Srgrimes * Vi move to the previous word 18037199Sbrian * [b] 1811573Srgrimes */ 1821573Srgrimesprotected el_action_t 1831573Srgrimes/*ARGSUSED*/ 184313981Spfgvi_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) 1851573Srgrimes{ 1861573Srgrimes 18784260Sobrien if (el->el_line.cursor == el->el_line.buffer) 188276881Sbapt return CC_ERROR; 1891573Srgrimes 190148834Sstefanf el->el_line.cursor = cv_prev_word(el->el_line.cursor, 19184260Sobrien el->el_line.buffer, 19284260Sobrien el->el_state.argument, 19384260Sobrien cv__isword); 1941573Srgrimes 195148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 19684260Sobrien cv_delfini(el); 197276881Sbapt return CC_REFRESH; 19884260Sobrien } 199276881Sbapt return CC_CURSOR; 2001573Srgrimes} 2011573Srgrimes 2021573Srgrimes 203148834Sstefanf/* vi_next_big_word(): 2041573Srgrimes * Vi move to the next space delimited word 2051573Srgrimes * [W] 2061573Srgrimes */ 2071573Srgrimesprotected el_action_t 2081573Srgrimes/*ARGSUSED*/ 209313981Spfgvi_next_big_word(EditLine *el, wint_t c __attribute__((__unused__))) 2101573Srgrimes{ 2111573Srgrimes 212148834Sstefanf if (el->el_line.cursor >= el->el_line.lastchar - 1) 213276881Sbapt return CC_ERROR; 2141573Srgrimes 21584260Sobrien el->el_line.cursor = cv_next_word(el, el->el_line.cursor, 216148834Sstefanf el->el_line.lastchar, el->el_state.argument, cv__isWord); 2171573Srgrimes 21884260Sobrien if (el->el_map.type == MAP_VI) 219148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 22084260Sobrien cv_delfini(el); 221276881Sbapt return CC_REFRESH; 22284260Sobrien } 223276881Sbapt return CC_CURSOR; 2241573Srgrimes} 2251573Srgrimes 22684260Sobrien 2278870Srgrimes/* vi_next_word(): 2281573Srgrimes * Vi move to the next word 2291573Srgrimes * [w] 2301573Srgrimes */ 2311573Srgrimesprotected el_action_t 2321573Srgrimes/*ARGSUSED*/ 233313981Spfgvi_next_word(EditLine *el, wint_t c __attribute__((__unused__))) 2341573Srgrimes{ 2351573Srgrimes 236148834Sstefanf if (el->el_line.cursor >= el->el_line.lastchar - 1) 237276881Sbapt return CC_ERROR; 2381573Srgrimes 23984260Sobrien el->el_line.cursor = cv_next_word(el, el->el_line.cursor, 240148834Sstefanf el->el_line.lastchar, el->el_state.argument, cv__isword); 2411573Srgrimes 24284260Sobrien if (el->el_map.type == MAP_VI) 243148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 24484260Sobrien cv_delfini(el); 245276881Sbapt return CC_REFRESH; 24684260Sobrien } 247276881Sbapt return CC_CURSOR; 2481573Srgrimes} 2491573Srgrimes 2501573Srgrimes 2518870Srgrimes/* vi_change_case(): 2521573Srgrimes * Vi change case of character under the cursor and advance one character 2531573Srgrimes * [~] 2541573Srgrimes */ 2551573Srgrimesprotected el_action_t 256313981Spfgvi_change_case(EditLine *el, wint_t c) 2571573Srgrimes{ 258148834Sstefanf int i; 25984260Sobrien 260148834Sstefanf if (el->el_line.cursor >= el->el_line.lastchar) 261276881Sbapt return CC_ERROR; 262148834Sstefanf cv_undo(el); 263148834Sstefanf for (i = 0; i < el->el_state.argument; i++) { 264148834Sstefanf 265276881Sbapt c = *el->el_line.cursor; 266276881Sbapt if (Isupper(c)) 267276881Sbapt *el->el_line.cursor = Tolower(c); 268276881Sbapt else if (Islower(c)) 269276881Sbapt *el->el_line.cursor = Toupper(c); 270148834Sstefanf 271148834Sstefanf if (++el->el_line.cursor >= el->el_line.lastchar) { 272148834Sstefanf el->el_line.cursor--; 273148834Sstefanf re_fastaddc(el); 274148834Sstefanf break; 275148834Sstefanf } 27684260Sobrien re_fastaddc(el); 27784260Sobrien } 278148834Sstefanf return CC_NORM; 2791573Srgrimes} 2801573Srgrimes 2811573Srgrimes 2828870Srgrimes/* vi_change_meta(): 2831573Srgrimes * Vi change prefix command 2841573Srgrimes * [c] 2851573Srgrimes */ 2861573Srgrimesprotected el_action_t 2871573Srgrimes/*ARGSUSED*/ 288313981Spfgvi_change_meta(EditLine *el, wint_t c __attribute__((__unused__))) 2891573Srgrimes{ 29084260Sobrien 29184260Sobrien /* 29284260Sobrien * Delete with insert == change: first we delete and then we leave in 29384260Sobrien * insert mode. 29484260Sobrien */ 295276881Sbapt return cv_action(el, DELETE | INSERT); 2961573Srgrimes} 2971573Srgrimes 2981573Srgrimes 2998870Srgrimes/* vi_insert_at_bol(): 3001573Srgrimes * Vi enter insert mode at the beginning of line 3011573Srgrimes * [I] 3021573Srgrimes */ 3031573Srgrimesprotected el_action_t 3041573Srgrimes/*ARGSUSED*/ 305313981Spfgvi_insert_at_bol(EditLine *el, wint_t c __attribute__((__unused__))) 3061573Srgrimes{ 3071573Srgrimes 30884260Sobrien el->el_line.cursor = el->el_line.buffer; 309148834Sstefanf cv_undo(el); 31084260Sobrien el->el_map.current = el->el_map.key; 311276881Sbapt return CC_CURSOR; 3121573Srgrimes} 3131573Srgrimes 3141573Srgrimes 3158870Srgrimes/* vi_replace_char(): 3161573Srgrimes * Vi replace character under the cursor with the next character typed 3171573Srgrimes * [r] 3181573Srgrimes */ 3191573Srgrimesprotected el_action_t 3201573Srgrimes/*ARGSUSED*/ 321313981Spfgvi_replace_char(EditLine *el, wint_t c __attribute__((__unused__))) 3221573Srgrimes{ 32384260Sobrien 324148834Sstefanf if (el->el_line.cursor >= el->el_line.lastchar) 325148834Sstefanf return CC_ERROR; 326148834Sstefanf 32784260Sobrien el->el_map.current = el->el_map.key; 32884260Sobrien el->el_state.inputmode = MODE_REPLACE_1; 329148834Sstefanf cv_undo(el); 330276881Sbapt return CC_ARGHACK; 3311573Srgrimes} 3321573Srgrimes 3331573Srgrimes 3348870Srgrimes/* vi_replace_mode(): 3351573Srgrimes * Vi enter replace mode 3361573Srgrimes * [R] 3371573Srgrimes */ 3381573Srgrimesprotected el_action_t 3391573Srgrimes/*ARGSUSED*/ 340313981Spfgvi_replace_mode(EditLine *el, wint_t c __attribute__((__unused__))) 3411573Srgrimes{ 34284260Sobrien 34384260Sobrien el->el_map.current = el->el_map.key; 34484260Sobrien el->el_state.inputmode = MODE_REPLACE; 345148834Sstefanf cv_undo(el); 346276881Sbapt return CC_NORM; 3471573Srgrimes} 3481573Srgrimes 3491573Srgrimes 3508870Srgrimes/* vi_substitute_char(): 3511573Srgrimes * Vi replace character under the cursor and enter insert mode 35237199Sbrian * [s] 3531573Srgrimes */ 3541573Srgrimesprotected el_action_t 3551573Srgrimes/*ARGSUSED*/ 356313981Spfgvi_substitute_char(EditLine *el, wint_t c __attribute__((__unused__))) 3571573Srgrimes{ 35884260Sobrien 35984260Sobrien c_delafter(el, el->el_state.argument); 36084260Sobrien el->el_map.current = el->el_map.key; 361276881Sbapt return CC_REFRESH; 3621573Srgrimes} 3631573Srgrimes 3641573Srgrimes 3658870Srgrimes/* vi_substitute_line(): 3661573Srgrimes * Vi substitute entire line 3671573Srgrimes * [S] 3681573Srgrimes */ 3691573Srgrimesprotected el_action_t 3701573Srgrimes/*ARGSUSED*/ 371313981Spfgvi_substitute_line(EditLine *el, wint_t c __attribute__((__unused__))) 3721573Srgrimes{ 37384260Sobrien 374148834Sstefanf cv_undo(el); 375148834Sstefanf cv_yank(el, el->el_line.buffer, 376237448Spfg (int)(el->el_line.lastchar - el->el_line.buffer)); 37784260Sobrien (void) em_kill_line(el, 0); 37884260Sobrien el->el_map.current = el->el_map.key; 379276881Sbapt return CC_REFRESH; 3801573Srgrimes} 3811573Srgrimes 3821573Srgrimes 3838870Srgrimes/* vi_change_to_eol(): 3841573Srgrimes * Vi change to end of line 3851573Srgrimes * [C] 3861573Srgrimes */ 3871573Srgrimesprotected el_action_t 3881573Srgrimes/*ARGSUSED*/ 389313981Spfgvi_change_to_eol(EditLine *el, wint_t c __attribute__((__unused__))) 3901573Srgrimes{ 39184260Sobrien 392148834Sstefanf cv_undo(el); 393148834Sstefanf cv_yank(el, el->el_line.cursor, 394237448Spfg (int)(el->el_line.lastchar - el->el_line.cursor)); 39584260Sobrien (void) ed_kill_line(el, 0); 39684260Sobrien el->el_map.current = el->el_map.key; 397276881Sbapt return CC_REFRESH; 3981573Srgrimes} 3991573Srgrimes 4001573Srgrimes 4011573Srgrimes/* vi_insert(): 4021573Srgrimes * Vi enter insert mode 4031573Srgrimes * [i] 4041573Srgrimes */ 4051573Srgrimesprotected el_action_t 4061573Srgrimes/*ARGSUSED*/ 407313981Spfgvi_insert(EditLine *el, wint_t c __attribute__((__unused__))) 4081573Srgrimes{ 4091573Srgrimes 41084260Sobrien el->el_map.current = el->el_map.key; 411148834Sstefanf cv_undo(el); 412276881Sbapt return CC_NORM; 4131573Srgrimes} 4141573Srgrimes 4151573Srgrimes 4161573Srgrimes/* vi_add(): 4178870Srgrimes * Vi enter insert mode after the cursor 4181573Srgrimes * [a] 4191573Srgrimes */ 4201573Srgrimesprotected el_action_t 4211573Srgrimes/*ARGSUSED*/ 422313981Spfgvi_add(EditLine *el, wint_t c __attribute__((__unused__))) 4231573Srgrimes{ 424148834Sstefanf int ret; 42537199Sbrian 42684260Sobrien el->el_map.current = el->el_map.key; 42784260Sobrien if (el->el_line.cursor < el->el_line.lastchar) { 42884260Sobrien el->el_line.cursor++; 42984260Sobrien if (el->el_line.cursor > el->el_line.lastchar) 43084260Sobrien el->el_line.cursor = el->el_line.lastchar; 43184260Sobrien ret = CC_CURSOR; 43284260Sobrien } else 43384260Sobrien ret = CC_NORM; 4341573Srgrimes 435148834Sstefanf cv_undo(el); 4361573Srgrimes 437276881Sbapt return (el_action_t)ret; 4381573Srgrimes} 4391573Srgrimes 4401573Srgrimes 4411573Srgrimes/* vi_add_at_eol(): 4421573Srgrimes * Vi enter insert mode at end of line 4431573Srgrimes * [A] 4441573Srgrimes */ 4451573Srgrimesprotected el_action_t 4461573Srgrimes/*ARGSUSED*/ 447313981Spfgvi_add_at_eol(EditLine *el, wint_t c __attribute__((__unused__))) 4481573Srgrimes{ 4491573Srgrimes 45084260Sobrien el->el_map.current = el->el_map.key; 45184260Sobrien el->el_line.cursor = el->el_line.lastchar; 452148834Sstefanf cv_undo(el); 453276881Sbapt return CC_CURSOR; 4541573Srgrimes} 4551573Srgrimes 4561573Srgrimes 4571573Srgrimes/* vi_delete_meta(): 4588870Srgrimes * Vi delete prefix command 4591573Srgrimes * [d] 4601573Srgrimes */ 4611573Srgrimesprotected el_action_t 4621573Srgrimes/*ARGSUSED*/ 463313981Spfgvi_delete_meta(EditLine *el, wint_t c __attribute__((__unused__))) 4641573Srgrimes{ 46584260Sobrien 466276881Sbapt return cv_action(el, DELETE); 4671573Srgrimes} 4681573Srgrimes 4691573Srgrimes 470148834Sstefanf/* vi_end_big_word(): 4718870Srgrimes * Vi move to the end of the current space delimited word 4728870Srgrimes * [E] 4731573Srgrimes */ 4741573Srgrimesprotected el_action_t 4751573Srgrimes/*ARGSUSED*/ 476313981Spfgvi_end_big_word(EditLine *el, wint_t c __attribute__((__unused__))) 4771573Srgrimes{ 4781573Srgrimes 47984260Sobrien if (el->el_line.cursor == el->el_line.lastchar) 480276881Sbapt return CC_ERROR; 4811573Srgrimes 48284260Sobrien el->el_line.cursor = cv__endword(el->el_line.cursor, 483148834Sstefanf el->el_line.lastchar, el->el_state.argument, cv__isWord); 4841573Srgrimes 485148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 48684260Sobrien el->el_line.cursor++; 48784260Sobrien cv_delfini(el); 488276881Sbapt return CC_REFRESH; 48984260Sobrien } 490276881Sbapt return CC_CURSOR; 4911573Srgrimes} 4921573Srgrimes 4931573Srgrimes 494148834Sstefanf/* vi_end_word(): 4951573Srgrimes * Vi move to the end of the current word 4961573Srgrimes * [e] 4971573Srgrimes */ 4981573Srgrimesprotected el_action_t 4991573Srgrimes/*ARGSUSED*/ 500313981Spfgvi_end_word(EditLine *el, wint_t c __attribute__((__unused__))) 5011573Srgrimes{ 5021573Srgrimes 50384260Sobrien if (el->el_line.cursor == el->el_line.lastchar) 504276881Sbapt return CC_ERROR; 5051573Srgrimes 50684260Sobrien el->el_line.cursor = cv__endword(el->el_line.cursor, 507148834Sstefanf el->el_line.lastchar, el->el_state.argument, cv__isword); 5081573Srgrimes 509148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 51084260Sobrien el->el_line.cursor++; 51184260Sobrien cv_delfini(el); 512276881Sbapt return CC_REFRESH; 51384260Sobrien } 514276881Sbapt return CC_CURSOR; 5151573Srgrimes} 5161573Srgrimes 5171573Srgrimes 5181573Srgrimes/* vi_undo(): 5191573Srgrimes * Vi undo last change 5201573Srgrimes * [u] 5211573Srgrimes */ 5221573Srgrimesprotected el_action_t 5231573Srgrimes/*ARGSUSED*/ 524313981Spfgvi_undo(EditLine *el, wint_t c __attribute__((__unused__))) 5251573Srgrimes{ 526148834Sstefanf c_undo_t un = el->el_chared.c_undo; 5271573Srgrimes 528148834Sstefanf if (un.len == -1) 529148834Sstefanf return CC_ERROR; 5301573Srgrimes 531148834Sstefanf /* switch line buffer and undo buffer */ 532148834Sstefanf el->el_chared.c_undo.buf = el->el_line.buffer; 533148834Sstefanf el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer; 534237448Spfg el->el_chared.c_undo.cursor = 535237448Spfg (int)(el->el_line.cursor - el->el_line.buffer); 536148834Sstefanf el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer); 537148834Sstefanf el->el_line.buffer = un.buf; 538148834Sstefanf el->el_line.cursor = un.buf + un.cursor; 539148834Sstefanf el->el_line.lastchar = un.buf + un.len; 5401573Srgrimes 541276881Sbapt return CC_REFRESH; 5421573Srgrimes} 5431573Srgrimes 5441573Srgrimes 5451573Srgrimes/* vi_command_mode(): 5461573Srgrimes * Vi enter command mode (use alternative key bindings) 5471573Srgrimes * [<ESC>] 5481573Srgrimes */ 5491573Srgrimesprotected el_action_t 5501573Srgrimes/*ARGSUSED*/ 551313981Spfgvi_command_mode(EditLine *el, wint_t c __attribute__((__unused__))) 5521573Srgrimes{ 5531573Srgrimes 55484260Sobrien /* [Esc] cancels pending action */ 55584260Sobrien el->el_chared.c_vcmd.action = NOP; 55684260Sobrien el->el_chared.c_vcmd.pos = 0; 5571573Srgrimes 55884260Sobrien el->el_state.doingarg = 0; 55984260Sobrien 56084260Sobrien el->el_state.inputmode = MODE_INSERT; 56184260Sobrien el->el_map.current = el->el_map.alt; 5621573Srgrimes#ifdef VI_MOVE 56384260Sobrien if (el->el_line.cursor > el->el_line.buffer) 56484260Sobrien el->el_line.cursor--; 5651573Srgrimes#endif 566276881Sbapt return CC_CURSOR; 5671573Srgrimes} 5681573Srgrimes 56984260Sobrien 5701573Srgrimes/* vi_zero(): 5718870Srgrimes * Vi move to the beginning of line 5721573Srgrimes * [0] 5731573Srgrimes */ 5741573Srgrimesprotected el_action_t 575313981Spfgvi_zero(EditLine *el, wint_t c) 5761573Srgrimes{ 57784260Sobrien 578148834Sstefanf if (el->el_state.doingarg) 579148834Sstefanf return ed_argument_digit(el, c); 580148834Sstefanf 581148834Sstefanf el->el_line.cursor = el->el_line.buffer; 582148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 583148834Sstefanf cv_delfini(el); 584276881Sbapt return CC_REFRESH; 58584260Sobrien } 586276881Sbapt return CC_CURSOR; 5871573Srgrimes} 5881573Srgrimes 5891573Srgrimes 5901573Srgrimes/* vi_delete_prev_char(): 591313981Spfg * Vi move to previous character (backspace) 592148834Sstefanf * [^H] in insert mode only 5938870Srgrimes */ 5941573Srgrimesprotected el_action_t 5951573Srgrimes/*ARGSUSED*/ 596313981Spfgvi_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) 5971573Srgrimes{ 5981573Srgrimes 599148834Sstefanf if (el->el_line.cursor <= el->el_line.buffer) 600276881Sbapt return CC_ERROR; 6011573Srgrimes 602148834Sstefanf c_delbefore1(el); 603148834Sstefanf el->el_line.cursor--; 604276881Sbapt return CC_REFRESH; 60584260Sobrien} 6061573Srgrimes 60784260Sobrien 6081573Srgrimes/* vi_list_or_eof(): 6091573Srgrimes * Vi list choices for completion or indicate end of file if empty line 6101573Srgrimes * [^D] 6111573Srgrimes */ 6121573Srgrimesprotected el_action_t 6131573Srgrimes/*ARGSUSED*/ 614313981Spfgvi_list_or_eof(EditLine *el, wint_t c) 6151573Srgrimes{ 61684260Sobrien 617148834Sstefanf if (el->el_line.cursor == el->el_line.lastchar) { 618148834Sstefanf if (el->el_line.cursor == el->el_line.buffer) { 619276881Sbapt terminal_writec(el, c); /* then do a EOF */ 620276881Sbapt return CC_EOF; 621148834Sstefanf } else { 622148834Sstefanf /* 623148834Sstefanf * Here we could list completions, but it is an 624148834Sstefanf * error right now 625148834Sstefanf */ 626276881Sbapt terminal_beep(el); 627276881Sbapt return CC_ERROR; 628148834Sstefanf } 629148834Sstefanf } else { 6301573Srgrimes#ifdef notyet 63184260Sobrien re_goto_bottom(el); 63284260Sobrien *el->el_line.lastchar = '\0'; /* just in case */ 633276881Sbapt return CC_LIST_CHOICES; 634148834Sstefanf#else 635148834Sstefanf /* 636148834Sstefanf * Just complain for now. 637148834Sstefanf */ 638276881Sbapt terminal_beep(el); 639276881Sbapt return CC_ERROR; 640148834Sstefanf#endif 64184260Sobrien } 6421573Srgrimes} 6431573Srgrimes 6441573Srgrimes 6451573Srgrimes/* vi_kill_line_prev(): 6468870Srgrimes * Vi cut from beginning of line to cursor 6471573Srgrimes * [^U] 6481573Srgrimes */ 6491573Srgrimesprotected el_action_t 6501573Srgrimes/*ARGSUSED*/ 651313981Spfgvi_kill_line_prev(EditLine *el, wint_t c __attribute__((__unused__))) 6521573Srgrimes{ 653276881Sbapt Char *kp, *cp; 6541573Srgrimes 65584260Sobrien cp = el->el_line.buffer; 65684260Sobrien kp = el->el_chared.c_kill.buf; 65784260Sobrien while (cp < el->el_line.cursor) 65884260Sobrien *kp++ = *cp++; /* copy it */ 65984260Sobrien el->el_chared.c_kill.last = kp; 660237448Spfg c_delbefore(el, (int)(el->el_line.cursor - el->el_line.buffer)); 66184260Sobrien el->el_line.cursor = el->el_line.buffer; /* zap! */ 662276881Sbapt return CC_REFRESH; 6631573Srgrimes} 6641573Srgrimes 6651573Srgrimes 6661573Srgrimes/* vi_search_prev(): 6671573Srgrimes * Vi search history previous 6681573Srgrimes * [?] 6691573Srgrimes */ 6701573Srgrimesprotected el_action_t 6711573Srgrimes/*ARGSUSED*/ 672313981Spfgvi_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) 6731573Srgrimes{ 67484260Sobrien 675276881Sbapt return cv_search(el, ED_SEARCH_PREV_HISTORY); 6761573Srgrimes} 6771573Srgrimes 6781573Srgrimes 6791573Srgrimes/* vi_search_next(): 6801573Srgrimes * Vi search history next 6811573Srgrimes * [/] 6821573Srgrimes */ 6831573Srgrimesprotected el_action_t 6841573Srgrimes/*ARGSUSED*/ 685313981Spfgvi_search_next(EditLine *el, wint_t c __attribute__((__unused__))) 6861573Srgrimes{ 68784260Sobrien 688276881Sbapt return cv_search(el, ED_SEARCH_NEXT_HISTORY); 6891573Srgrimes} 6901573Srgrimes 6911573Srgrimes 6921573Srgrimes/* vi_repeat_search_next(): 6931573Srgrimes * Vi repeat current search in the same search direction 6941573Srgrimes * [n] 6951573Srgrimes */ 6961573Srgrimesprotected el_action_t 6971573Srgrimes/*ARGSUSED*/ 698313981Spfgvi_repeat_search_next(EditLine *el, wint_t c __attribute__((__unused__))) 6991573Srgrimes{ 70084260Sobrien 70184260Sobrien if (el->el_search.patlen == 0) 702276881Sbapt return CC_ERROR; 70384260Sobrien else 704276881Sbapt return cv_repeat_srch(el, el->el_search.patdir); 7051573Srgrimes} 7061573Srgrimes 7071573Srgrimes 7081573Srgrimes/* vi_repeat_search_prev(): 7091573Srgrimes * Vi repeat current search in the opposite search direction 7101573Srgrimes * [N] 7111573Srgrimes */ 7121573Srgrimes/*ARGSUSED*/ 7131573Srgrimesprotected el_action_t 714313981Spfgvi_repeat_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) 7151573Srgrimes{ 71684260Sobrien 71784260Sobrien if (el->el_search.patlen == 0) 718276881Sbapt return CC_ERROR; 71984260Sobrien else 72084260Sobrien return (cv_repeat_srch(el, 72184260Sobrien el->el_search.patdir == ED_SEARCH_PREV_HISTORY ? 72284260Sobrien ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY)); 7231573Srgrimes} 7241573Srgrimes 7251573Srgrimes 7261573Srgrimes/* vi_next_char(): 7271573Srgrimes * Vi move to the character specified next 7281573Srgrimes * [f] 7291573Srgrimes */ 7301573Srgrimesprotected el_action_t 7311573Srgrimes/*ARGSUSED*/ 732313981Spfgvi_next_char(EditLine *el, wint_t c __attribute__((__unused__))) 7331573Srgrimes{ 734148834Sstefanf return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0); 7351573Srgrimes} 7361573Srgrimes 7371573Srgrimes 7381573Srgrimes/* vi_prev_char(): 7391573Srgrimes * Vi move to the character specified previous 7401573Srgrimes * [F] 7411573Srgrimes */ 7421573Srgrimesprotected el_action_t 7431573Srgrimes/*ARGSUSED*/ 744313981Spfgvi_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) 7451573Srgrimes{ 746148834Sstefanf return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0); 7471573Srgrimes} 7481573Srgrimes 7491573Srgrimes 7501573Srgrimes/* vi_to_next_char(): 7511573Srgrimes * Vi move up to the character specified next 7521573Srgrimes * [t] 7531573Srgrimes */ 7541573Srgrimesprotected el_action_t 7551573Srgrimes/*ARGSUSED*/ 756313981Spfgvi_to_next_char(EditLine *el, wint_t c __attribute__((__unused__))) 7571573Srgrimes{ 758148834Sstefanf return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1); 7591573Srgrimes} 7601573Srgrimes 7611573Srgrimes 7621573Srgrimes/* vi_to_prev_char(): 7631573Srgrimes * Vi move up to the character specified previous 7641573Srgrimes * [T] 7651573Srgrimes */ 7661573Srgrimesprotected el_action_t 7671573Srgrimes/*ARGSUSED*/ 768313981Spfgvi_to_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) 7691573Srgrimes{ 770148834Sstefanf return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1); 7711573Srgrimes} 7721573Srgrimes 7731573Srgrimes 7741573Srgrimes/* vi_repeat_next_char(): 7751573Srgrimes * Vi repeat current character search in the same search direction 7761573Srgrimes * [;] 7771573Srgrimes */ 7781573Srgrimesprotected el_action_t 7791573Srgrimes/*ARGSUSED*/ 780313981Spfgvi_repeat_next_char(EditLine *el, wint_t c __attribute__((__unused__))) 7811573Srgrimes{ 7821573Srgrimes 783148834Sstefanf return cv_csearch(el, el->el_search.chadir, el->el_search.chacha, 784148834Sstefanf el->el_state.argument, el->el_search.chatflg); 7851573Srgrimes} 7861573Srgrimes 7871573Srgrimes 7881573Srgrimes/* vi_repeat_prev_char(): 7891573Srgrimes * Vi repeat current character search in the opposite search direction 7901573Srgrimes * [,] 7911573Srgrimes */ 7921573Srgrimesprotected el_action_t 7931573Srgrimes/*ARGSUSED*/ 794313981Spfgvi_repeat_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) 7951573Srgrimes{ 796148834Sstefanf el_action_t r; 797148834Sstefanf int dir = el->el_search.chadir; 7981573Srgrimes 799148834Sstefanf r = cv_csearch(el, -dir, el->el_search.chacha, 800148834Sstefanf el->el_state.argument, el->el_search.chatflg); 801148834Sstefanf el->el_search.chadir = dir; 802148834Sstefanf return r; 803148834Sstefanf} 80484260Sobrien 805148834Sstefanf 806148834Sstefanf/* vi_match(): 807148834Sstefanf * Vi go to matching () {} or [] 808148834Sstefanf * [%] 809148834Sstefanf */ 810148834Sstefanfprotected el_action_t 811148834Sstefanf/*ARGSUSED*/ 812313981Spfgvi_match(EditLine *el, wint_t c __attribute__((__unused__))) 813148834Sstefanf{ 814276881Sbapt const Char match_chars[] = STR("()[]{}"); 815276881Sbapt Char *cp; 816237448Spfg size_t delta, i, count; 817276881Sbapt Char o_ch, c_ch; 818148834Sstefanf 819148834Sstefanf *el->el_line.lastchar = '\0'; /* just in case */ 820148834Sstefanf 821276881Sbapt i = Strcspn(el->el_line.cursor, match_chars); 822148834Sstefanf o_ch = el->el_line.cursor[i]; 823148834Sstefanf if (o_ch == 0) 824148834Sstefanf return CC_ERROR; 825276881Sbapt delta = (size_t)(Strchr(match_chars, o_ch) - match_chars); 826148834Sstefanf c_ch = match_chars[delta ^ 1]; 827148834Sstefanf count = 1; 828148834Sstefanf delta = 1 - (delta & 1) * 2; 829148834Sstefanf 830148834Sstefanf for (cp = &el->el_line.cursor[i]; count; ) { 831148834Sstefanf cp += delta; 832148834Sstefanf if (cp < el->el_line.buffer || cp >= el->el_line.lastchar) 833148834Sstefanf return CC_ERROR; 834148834Sstefanf if (*cp == o_ch) 835148834Sstefanf count++; 836148834Sstefanf else if (*cp == c_ch) 837148834Sstefanf count--; 838148834Sstefanf } 839148834Sstefanf 840148834Sstefanf el->el_line.cursor = cp; 841148834Sstefanf 842148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 843148834Sstefanf /* NB posix says char under cursor should NOT be deleted 844148834Sstefanf for -ve delta - this is different to netbsd vi. */ 845148834Sstefanf if (delta > 0) 846148834Sstefanf el->el_line.cursor++; 847148834Sstefanf cv_delfini(el); 848276881Sbapt return CC_REFRESH; 849148834Sstefanf } 850276881Sbapt return CC_CURSOR; 8511573Srgrimes} 852148834Sstefanf 853148834Sstefanf/* vi_undo_line(): 854148834Sstefanf * Vi undo all changes to line 855148834Sstefanf * [U] 856148834Sstefanf */ 857148834Sstefanfprotected el_action_t 858148834Sstefanf/*ARGSUSED*/ 859313981Spfgvi_undo_line(EditLine *el, wint_t c __attribute__((__unused__))) 860148834Sstefanf{ 861148834Sstefanf 862148834Sstefanf cv_undo(el); 863148834Sstefanf return hist_get(el); 864148834Sstefanf} 865148834Sstefanf 866148834Sstefanf/* vi_to_column(): 867148834Sstefanf * Vi go to specified column 868148834Sstefanf * [|] 869148834Sstefanf * NB netbsd vi goes to screen column 'n', posix says nth character 870148834Sstefanf */ 871148834Sstefanfprotected el_action_t 872148834Sstefanf/*ARGSUSED*/ 873313981Spfgvi_to_column(EditLine *el, wint_t c __attribute__((__unused__))) 874148834Sstefanf{ 875148834Sstefanf 876148834Sstefanf el->el_line.cursor = el->el_line.buffer; 877148834Sstefanf el->el_state.argument--; 878148834Sstefanf return ed_next_char(el, 0); 879148834Sstefanf} 880148834Sstefanf 881148834Sstefanf/* vi_yank_end(): 882148834Sstefanf * Vi yank to end of line 883148834Sstefanf * [Y] 884148834Sstefanf */ 885148834Sstefanfprotected el_action_t 886148834Sstefanf/*ARGSUSED*/ 887313981Spfgvi_yank_end(EditLine *el, wint_t c __attribute__((__unused__))) 888148834Sstefanf{ 889148834Sstefanf 890148834Sstefanf cv_yank(el, el->el_line.cursor, 891237448Spfg (int)(el->el_line.lastchar - el->el_line.cursor)); 892148834Sstefanf return CC_REFRESH; 893148834Sstefanf} 894148834Sstefanf 895148834Sstefanf/* vi_yank(): 896148834Sstefanf * Vi yank 897148834Sstefanf * [y] 898148834Sstefanf */ 899148834Sstefanfprotected el_action_t 900148834Sstefanf/*ARGSUSED*/ 901313981Spfgvi_yank(EditLine *el, wint_t c __attribute__((__unused__))) 902148834Sstefanf{ 903148834Sstefanf 904148834Sstefanf return cv_action(el, YANK); 905148834Sstefanf} 906148834Sstefanf 907148834Sstefanf/* vi_comment_out(): 908148834Sstefanf * Vi comment out current command 909148848Sstefanf * [#] 910148834Sstefanf */ 911148834Sstefanfprotected el_action_t 912148834Sstefanf/*ARGSUSED*/ 913313981Spfgvi_comment_out(EditLine *el, wint_t c __attribute__((__unused__))) 914148834Sstefanf{ 915148834Sstefanf 916148834Sstefanf el->el_line.cursor = el->el_line.buffer; 917148834Sstefanf c_insert(el, 1); 918148834Sstefanf *el->el_line.cursor = '#'; 919148834Sstefanf re_refresh(el); 920148834Sstefanf return ed_newline(el, 0); 921148834Sstefanf} 922148834Sstefanf 923148834Sstefanf/* vi_alias(): 924148834Sstefanf * Vi include shell alias 925148834Sstefanf * [@] 926148848Sstefanf * NB: posix implies that we should enter insert mode, however 927148834Sstefanf * this is against historical precedent... 928148834Sstefanf */ 929148834Sstefanfprotected el_action_t 930148834Sstefanf/*ARGSUSED*/ 931313981Spfgvi_alias(EditLine *el, wint_t c __attribute__((__unused__))) 932148834Sstefanf{ 933148834Sstefanf char alias_name[3]; 934276881Sbapt const char *alias_text; 935148834Sstefanf 936276881Sbapt if (el->el_chared.c_aliasfun == NULL) 937148834Sstefanf return CC_ERROR; 938148834Sstefanf 939148834Sstefanf alias_name[0] = '_'; 940148834Sstefanf alias_name[2] = 0; 941148834Sstefanf if (el_getc(el, &alias_name[1]) != 1) 942148834Sstefanf return CC_ERROR; 943148834Sstefanf 944276881Sbapt alias_text = (*el->el_chared.c_aliasfun)(el->el_chared.c_aliasarg, 945276881Sbapt alias_name); 946148834Sstefanf if (alias_text != NULL) 947276881Sbapt FUN(el,push)(el, ct_decode_string(alias_text, &el->el_scratch)); 948148834Sstefanf return CC_NORM; 949148834Sstefanf} 950148834Sstefanf 951148834Sstefanf/* vi_to_history_line(): 952148834Sstefanf * Vi go to specified history file line. 953148834Sstefanf * [G] 954148834Sstefanf */ 955148834Sstefanfprotected el_action_t 956148834Sstefanf/*ARGSUSED*/ 957313981Spfgvi_to_history_line(EditLine *el, wint_t c __attribute__((__unused__))) 958148834Sstefanf{ 959148834Sstefanf int sv_event_no = el->el_history.eventno; 960148834Sstefanf el_action_t rval; 961148834Sstefanf 962148834Sstefanf 963148834Sstefanf if (el->el_history.eventno == 0) { 964276881Sbapt (void) Strncpy(el->el_history.buf, el->el_line.buffer, 965148834Sstefanf EL_BUFSIZ); 966148834Sstefanf el->el_history.last = el->el_history.buf + 967148834Sstefanf (el->el_line.lastchar - el->el_line.buffer); 968148834Sstefanf } 969148834Sstefanf 970148834Sstefanf /* Lack of a 'count' means oldest, not 1 */ 971148834Sstefanf if (!el->el_state.doingarg) { 972148834Sstefanf el->el_history.eventno = 0x7fffffff; 973148834Sstefanf hist_get(el); 974148834Sstefanf } else { 975148834Sstefanf /* This is brain dead, all the rest of this code counts 976148834Sstefanf * upwards going into the past. Here we need count in the 977148834Sstefanf * other direction (to match the output of fc -l). 978148834Sstefanf * I could change the world, but this seems to suffice. 979148834Sstefanf */ 980148834Sstefanf el->el_history.eventno = 1; 981148834Sstefanf if (hist_get(el) == CC_ERROR) 982148834Sstefanf return CC_ERROR; 983313981Spfg el->el_history.eventno = 1 + el->el_history.ev.num 984148834Sstefanf - el->el_state.argument; 985148834Sstefanf if (el->el_history.eventno < 0) { 986148834Sstefanf el->el_history.eventno = sv_event_no; 987148834Sstefanf return CC_ERROR; 988148834Sstefanf } 989148834Sstefanf } 990148834Sstefanf rval = hist_get(el); 991148834Sstefanf if (rval == CC_ERROR) 992148834Sstefanf el->el_history.eventno = sv_event_no; 993148834Sstefanf return rval; 994148834Sstefanf} 995148834Sstefanf 996148834Sstefanf/* vi_histedit(): 997148834Sstefanf * Vi edit history line with vi 998148834Sstefanf * [v] 999148834Sstefanf */ 1000148834Sstefanfprotected el_action_t 1001148834Sstefanf/*ARGSUSED*/ 1002313981Spfgvi_histedit(EditLine *el, wint_t c __attribute__((__unused__))) 1003148834Sstefanf{ 1004148834Sstefanf int fd; 1005148834Sstefanf pid_t pid; 1006237448Spfg ssize_t st; 1007237448Spfg int status; 1008148834Sstefanf char tempfile[] = "/tmp/histedit.XXXXXXXXXX"; 1009276881Sbapt char *cp = NULL; 1010276881Sbapt size_t len; 1011276881Sbapt Char *line = NULL; 1012148834Sstefanf 1013148834Sstefanf if (el->el_state.doingarg) { 1014148834Sstefanf if (vi_to_history_line(el, 0) == CC_ERROR) 1015148834Sstefanf return CC_ERROR; 1016148834Sstefanf } 1017148834Sstefanf 1018148834Sstefanf fd = mkstemp(tempfile); 1019148834Sstefanf if (fd < 0) 1020148834Sstefanf return CC_ERROR; 1021276881Sbapt len = (size_t)(el->el_line.lastchar - el->el_line.buffer); 1022276881Sbapt#define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX) 1023276881Sbapt cp = el_malloc(TMP_BUFSIZ * sizeof(*cp)); 1024276881Sbapt if (cp == NULL) 1025276881Sbapt goto error; 1026276881Sbapt line = el_malloc(len * sizeof(*line) + 1); 1027276881Sbapt if (line == NULL) 1028276881Sbapt goto error; 1029276881Sbapt Strncpy(line, el->el_line.buffer, len); 1030276881Sbapt line[len] = '\0'; 1031276881Sbapt ct_wcstombs(cp, line, TMP_BUFSIZ - 1); 1032276881Sbapt cp[TMP_BUFSIZ - 1] = '\0'; 1033276881Sbapt len = strlen(cp); 1034276881Sbapt write(fd, cp, len); 1035276881Sbapt write(fd, "\n", (size_t)1); 1036148834Sstefanf pid = fork(); 1037148834Sstefanf switch (pid) { 1038148834Sstefanf case -1: 1039276881Sbapt goto error; 1040148834Sstefanf case 0: 1041148834Sstefanf close(fd); 1042237448Spfg execlp("vi", "vi", tempfile, (char *)NULL); 1043148834Sstefanf exit(0); 1044148834Sstefanf /*NOTREACHED*/ 1045148834Sstefanf default: 1046237448Spfg while (waitpid(pid, &status, 0) != pid) 1047148834Sstefanf continue; 1048237448Spfg lseek(fd, (off_t)0, SEEK_SET); 1049290065Sjilles st = read(fd, cp, TMP_BUFSIZ - 1); 1050276881Sbapt if (st > 0) { 1051290065Sjilles cp[st] = '\0'; 1052290065Sjilles len = (size_t)(el->el_line.limit - el->el_line.buffer); 1053276881Sbapt len = ct_mbstowcs(el->el_line.buffer, cp, len); 1054290065Sjilles if (len > 0 && el->el_line.buffer[len - 1] == '\n') 1055276881Sbapt --len; 1056276881Sbapt } 1057276881Sbapt else 1058276881Sbapt len = 0; 1059276881Sbapt el->el_line.cursor = el->el_line.buffer; 1060276881Sbapt el->el_line.lastchar = el->el_line.buffer + len; 1061276881Sbapt el_free(cp); 1062276881Sbapt el_free(line); 1063148834Sstefanf break; 1064148834Sstefanf } 1065148834Sstefanf 1066148834Sstefanf close(fd); 1067148834Sstefanf unlink(tempfile); 1068148834Sstefanf /* return CC_REFRESH; */ 1069148834Sstefanf return ed_newline(el, 0); 1070276881Sbapterror: 1071276881Sbapt el_free(line); 1072276881Sbapt el_free(cp); 1073276881Sbapt close(fd); 1074276881Sbapt unlink(tempfile); 1075276881Sbapt return CC_ERROR; 1076148834Sstefanf} 1077148834Sstefanf 1078148834Sstefanf/* vi_history_word(): 1079148834Sstefanf * Vi append word from previous input line 1080148834Sstefanf * [_] 1081148834Sstefanf * Who knows where this one came from! 1082148834Sstefanf * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_' 1083148834Sstefanf */ 1084148834Sstefanfprotected el_action_t 1085148834Sstefanf/*ARGSUSED*/ 1086313981Spfgvi_history_word(EditLine *el, wint_t c __attribute__((__unused__))) 1087148834Sstefanf{ 1088276881Sbapt const Char *wp = HIST_FIRST(el); 1089276881Sbapt const Char *wep, *wsp; 1090148834Sstefanf int len; 1091276881Sbapt Char *cp; 1092276881Sbapt const Char *lim; 1093148834Sstefanf 1094148834Sstefanf if (wp == NULL) 1095148834Sstefanf return CC_ERROR; 1096148834Sstefanf 1097297757Spfg wep = wsp = NULL; 1098148834Sstefanf do { 1099276881Sbapt while (Isspace(*wp)) 1100148834Sstefanf wp++; 1101148834Sstefanf if (*wp == 0) 1102148834Sstefanf break; 1103148834Sstefanf wsp = wp; 1104276881Sbapt while (*wp && !Isspace(*wp)) 1105148834Sstefanf wp++; 1106148834Sstefanf wep = wp; 1107276881Sbapt } while ((!el->el_state.doingarg || --el->el_state.argument > 0) 1108276881Sbapt && *wp != 0); 1109148834Sstefanf 1110297757Spfg if (wsp == NULL || (el->el_state.doingarg && el->el_state.argument != 0)) 1111148834Sstefanf return CC_ERROR; 1112148834Sstefanf 1113148834Sstefanf cv_undo(el); 1114237448Spfg len = (int)(wep - wsp); 1115148834Sstefanf if (el->el_line.cursor < el->el_line.lastchar) 1116148834Sstefanf el->el_line.cursor++; 1117148834Sstefanf c_insert(el, len + 1); 1118148834Sstefanf cp = el->el_line.cursor; 1119148834Sstefanf lim = el->el_line.limit; 1120148834Sstefanf if (cp < lim) 1121148834Sstefanf *cp++ = ' '; 1122148834Sstefanf while (wsp < wep && cp < lim) 1123148834Sstefanf *cp++ = *wsp++; 1124148834Sstefanf el->el_line.cursor = cp; 1125148834Sstefanf 1126148834Sstefanf el->el_map.current = el->el_map.key; 1127148834Sstefanf return CC_REFRESH; 1128148834Sstefanf} 1129148834Sstefanf 1130148834Sstefanf/* vi_redo(): 1131148834Sstefanf * Vi redo last non-motion command 1132148834Sstefanf * [.] 1133148834Sstefanf */ 1134148834Sstefanfprotected el_action_t 1135148834Sstefanf/*ARGSUSED*/ 1136313981Spfgvi_redo(EditLine *el, wint_t c __attribute__((__unused__))) 1137148834Sstefanf{ 1138148834Sstefanf c_redo_t *r = &el->el_chared.c_redo; 1139148834Sstefanf 1140148834Sstefanf if (!el->el_state.doingarg && r->count) { 1141148834Sstefanf el->el_state.doingarg = 1; 1142148834Sstefanf el->el_state.argument = r->count; 1143148834Sstefanf } 1144148834Sstefanf 1145148834Sstefanf el->el_chared.c_vcmd.pos = el->el_line.cursor; 1146148834Sstefanf el->el_chared.c_vcmd.action = r->action; 1147148834Sstefanf if (r->pos != r->buf) { 1148148834Sstefanf if (r->pos + 1 > r->lim) 1149148834Sstefanf /* sanity */ 1150148834Sstefanf r->pos = r->lim - 1; 1151148834Sstefanf r->pos[0] = 0; 1152276881Sbapt FUN(el,push)(el, r->buf); 1153148834Sstefanf } 1154148834Sstefanf 1155148834Sstefanf el->el_state.thiscmd = r->cmd; 1156148834Sstefanf el->el_state.thisch = r->ch; 1157276881Sbapt return (*el->el_map.func[r->cmd])(el, r->ch); 1158148834Sstefanf} 1159