11573Srgrimes/*- 21573Srgrimes * Copyright (c) 1992, 1993 31573Srgrimes * The Regents of the University of California. All rights reserved. 41573Srgrimes * 51573Srgrimes * This code is derived from software contributed to Berkeley by 61573Srgrimes * Christos Zoulas of Cornell University. 71573Srgrimes * 81573Srgrimes * Redistribution and use in source and binary forms, with or without 91573Srgrimes * modification, are permitted provided that the following conditions 101573Srgrimes * are met: 111573Srgrimes * 1. Redistributions of source code must retain the above copyright 121573Srgrimes * notice, this list of conditions and the following disclaimer. 131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141573Srgrimes * notice, this list of conditions and the following disclaimer in the 151573Srgrimes * documentation and/or other materials provided with the distribution. 16148834Sstefanf * 3. Neither the name of the University nor the names of its contributors 171573Srgrimes * may be used to endorse or promote products derived from this software 181573Srgrimes * without specific prior written permission. 191573Srgrimes * 201573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301573Srgrimes * SUCH DAMAGE. 3184260Sobrien * 32238178Spfg * $NetBSD: chared.c,v 1.27 2009/02/15 21:55:23 christos Exp $ 331573Srgrimes */ 341573Srgrimes 351573Srgrimes#if !defined(lint) && !defined(SCCSID) 361573Srgrimesstatic char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93"; 371573Srgrimes#endif /* not lint && not SCCSID */ 3884260Sobrien#include <sys/cdefs.h> 3984260Sobrien__FBSDID("$FreeBSD$"); 401573Srgrimes 418870Srgrimes/* 421573Srgrimes * chared.c: Character editor utilities 431573Srgrimes */ 441573Srgrimes#include "sys.h" 451573Srgrimes 461573Srgrimes#include <stdlib.h> 471573Srgrimes#include "el.h" 481573Srgrimes 49148834Sstefanfprivate void ch__clearmacro(EditLine *); 50148834Sstefanf 5184260Sobrien/* value to leave unused in line buffer */ 5284260Sobrien#define EL_LEAVE 2 5384260Sobrien 541573Srgrimes/* cv_undo(): 551573Srgrimes * Handle state for the vi undo command 561573Srgrimes */ 571573Srgrimesprotected void 58148834Sstefanfcv_undo(EditLine *el) 591573Srgrimes{ 6084260Sobrien c_undo_t *vu = &el->el_chared.c_undo; 61148834Sstefanf c_redo_t *r = &el->el_chared.c_redo; 62238178Spfg size_t size; 63148834Sstefanf 64148834Sstefanf /* Save entire line for undo */ 65148834Sstefanf size = el->el_line.lastchar - el->el_line.buffer; 66148834Sstefanf vu->len = size; 67238178Spfg vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer); 68148834Sstefanf memcpy(vu->buf, el->el_line.buffer, size); 69148834Sstefanf 70148834Sstefanf /* save command info for redo */ 71148834Sstefanf r->count = el->el_state.doingarg ? el->el_state.argument : 0; 72148834Sstefanf r->action = el->el_chared.c_vcmd.action; 73148834Sstefanf r->pos = r->buf; 74148834Sstefanf r->cmd = el->el_state.thiscmd; 75148834Sstefanf r->ch = el->el_state.thisch; 761573Srgrimes} 771573Srgrimes 78148834Sstefanf/* cv_yank(): 79148834Sstefanf * Save yank/delete data for paste 80148834Sstefanf */ 81148834Sstefanfprotected void 82148834Sstefanfcv_yank(EditLine *el, const char *ptr, int size) 83148834Sstefanf{ 84148834Sstefanf c_kill_t *k = &el->el_chared.c_kill; 851573Srgrimes 86238178Spfg memcpy(k->buf, ptr, (size_t)size); 87148834Sstefanf k->last = k->buf + size; 88148834Sstefanf} 89148834Sstefanf 90148834Sstefanf 918870Srgrimes/* c_insert(): 921573Srgrimes * Insert num characters 931573Srgrimes */ 941573Srgrimesprotected void 9584260Sobrienc_insert(EditLine *el, int num) 961573Srgrimes{ 9784260Sobrien char *cp; 981573Srgrimes 99148834Sstefanf if (el->el_line.lastchar + num >= el->el_line.limit) { 100238178Spfg if (!ch_enlargebufs(el, (size_t)num)) 101148834Sstefanf return; /* can't go past end of buffer */ 102148834Sstefanf } 1031573Srgrimes 10484260Sobrien if (el->el_line.cursor < el->el_line.lastchar) { 10584260Sobrien /* if I must move chars */ 10684260Sobrien for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--) 10784260Sobrien cp[num] = *cp; 10884260Sobrien } 10984260Sobrien el->el_line.lastchar += num; 11084260Sobrien} 1111573Srgrimes 1121573Srgrimes 1131573Srgrimes/* c_delafter(): 1141573Srgrimes * Delete num characters after the cursor 1151573Srgrimes */ 1161573Srgrimesprotected void 11784260Sobrienc_delafter(EditLine *el, int num) 1181573Srgrimes{ 1191573Srgrimes 12084260Sobrien if (el->el_line.cursor + num > el->el_line.lastchar) 121238178Spfg num = (int)(el->el_line.lastchar - el->el_line.cursor); 1221573Srgrimes 123148834Sstefanf if (el->el_map.current != el->el_map.emacs) { 124148834Sstefanf cv_undo(el); 125148834Sstefanf cv_yank(el, el->el_line.cursor, num); 126148834Sstefanf } 127148834Sstefanf 12884260Sobrien if (num > 0) { 12984260Sobrien char *cp; 1301573Srgrimes 13184260Sobrien for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) 13284260Sobrien *cp = cp[num]; 1331573Srgrimes 13484260Sobrien el->el_line.lastchar -= num; 13584260Sobrien } 1361573Srgrimes} 1371573Srgrimes 1381573Srgrimes 139148834Sstefanf/* c_delafter1(): 140148834Sstefanf * Delete the character after the cursor, do not yank 141148834Sstefanf */ 142148834Sstefanfprotected void 143148834Sstefanfc_delafter1(EditLine *el) 144148834Sstefanf{ 145148834Sstefanf char *cp; 146148834Sstefanf 147148834Sstefanf for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) 148148834Sstefanf *cp = cp[1]; 149148834Sstefanf 150148834Sstefanf el->el_line.lastchar--; 151148834Sstefanf} 152148834Sstefanf 153148834Sstefanf 1541573Srgrimes/* c_delbefore(): 1551573Srgrimes * Delete num characters before the cursor 1561573Srgrimes */ 1571573Srgrimesprotected void 15884260Sobrienc_delbefore(EditLine *el, int num) 1591573Srgrimes{ 1601573Srgrimes 16184260Sobrien if (el->el_line.cursor - num < el->el_line.buffer) 162238178Spfg num = (int)(el->el_line.cursor - el->el_line.buffer); 1631573Srgrimes 164148834Sstefanf if (el->el_map.current != el->el_map.emacs) { 165148834Sstefanf cv_undo(el); 166148834Sstefanf cv_yank(el, el->el_line.cursor - num, num); 167148834Sstefanf } 168148834Sstefanf 16984260Sobrien if (num > 0) { 17084260Sobrien char *cp; 1711573Srgrimes 17284260Sobrien for (cp = el->el_line.cursor - num; 17384260Sobrien cp <= el->el_line.lastchar; 17484260Sobrien cp++) 17584260Sobrien *cp = cp[num]; 1761573Srgrimes 17784260Sobrien el->el_line.lastchar -= num; 17884260Sobrien } 1791573Srgrimes} 1801573Srgrimes 1811573Srgrimes 182148834Sstefanf/* c_delbefore1(): 183148834Sstefanf * Delete the character before the cursor, do not yank 184148834Sstefanf */ 185148834Sstefanfprotected void 186148834Sstefanfc_delbefore1(EditLine *el) 187148834Sstefanf{ 188148834Sstefanf char *cp; 189148834Sstefanf 190148834Sstefanf for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++) 191148834Sstefanf *cp = cp[1]; 192148834Sstefanf 193148834Sstefanf el->el_line.lastchar--; 194148834Sstefanf} 195148834Sstefanf 196148834Sstefanf 1971573Srgrimes/* ce__isword(): 1981573Srgrimes * Return if p is part of a word according to emacs 1991573Srgrimes */ 2001573Srgrimesprotected int 20184260Sobrience__isword(int p) 2021573Srgrimes{ 203148834Sstefanf return (isalnum(p) || strchr("*?_-.[]~=", p) != NULL); 2041573Srgrimes} 2051573Srgrimes 2061573Srgrimes 2071573Srgrimes/* cv__isword(): 208148834Sstefanf * Return if p is part of a word according to vi 2091573Srgrimes */ 2101573Srgrimesprotected int 21184260Sobriencv__isword(int p) 2121573Srgrimes{ 213148834Sstefanf if (isalnum(p) || p == '_') 214148834Sstefanf return 1; 215148834Sstefanf if (isgraph(p)) 216148834Sstefanf return 2; 217148834Sstefanf return 0; 21837199Sbrian} 21937199Sbrian 22037199Sbrian 221148834Sstefanf/* cv__isWord(): 222148834Sstefanf * Return if p is part of a big word according to vi 22337199Sbrian */ 22437199Sbrianprotected int 225148834Sstefanfcv__isWord(int p) 22637199Sbrian{ 227148834Sstefanf return (!isspace(p)); 2281573Srgrimes} 2291573Srgrimes 2301573Srgrimes 2311573Srgrimes/* c__prev_word(): 2321573Srgrimes * Find the previous word 2331573Srgrimes */ 2341573Srgrimesprotected char * 23584260Sobrienc__prev_word(char *p, char *low, int n, int (*wtest)(int)) 2361573Srgrimes{ 23784260Sobrien p--; 2381573Srgrimes 23984260Sobrien while (n--) { 24084260Sobrien while ((p >= low) && !(*wtest)((unsigned char) *p)) 24184260Sobrien p--; 24284260Sobrien while ((p >= low) && (*wtest)((unsigned char) *p)) 24384260Sobrien p--; 24484260Sobrien } 2451573Srgrimes 24684260Sobrien /* cp now points to one character before the word */ 24784260Sobrien p++; 24884260Sobrien if (p < low) 24984260Sobrien p = low; 25084260Sobrien /* cp now points where we want it */ 25184260Sobrien return (p); 2521573Srgrimes} 2531573Srgrimes 2541573Srgrimes 2551573Srgrimes/* c__next_word(): 2561573Srgrimes * Find the next word 2571573Srgrimes */ 2581573Srgrimesprotected char * 25984260Sobrienc__next_word(char *p, char *high, int n, int (*wtest)(int)) 2601573Srgrimes{ 26184260Sobrien while (n--) { 26284260Sobrien while ((p < high) && !(*wtest)((unsigned char) *p)) 26384260Sobrien p++; 26484260Sobrien while ((p < high) && (*wtest)((unsigned char) *p)) 26584260Sobrien p++; 26684260Sobrien } 26784260Sobrien if (p > high) 26884260Sobrien p = high; 26984260Sobrien /* p now points where we want it */ 27084260Sobrien return (p); 2711573Srgrimes} 2721573Srgrimes 2731573Srgrimes/* cv_next_word(): 2741573Srgrimes * Find the next word vi style 2751573Srgrimes */ 2761573Srgrimesprotected char * 27784260Sobriencv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int)) 2781573Srgrimes{ 27984260Sobrien int test; 2801573Srgrimes 28184260Sobrien while (n--) { 28284260Sobrien test = (*wtest)((unsigned char) *p); 28384260Sobrien while ((p < high) && (*wtest)((unsigned char) *p) == test) 28484260Sobrien p++; 28584260Sobrien /* 28684260Sobrien * vi historically deletes with cw only the word preserving the 28784260Sobrien * trailing whitespace! This is not what 'w' does.. 28884260Sobrien */ 289148834Sstefanf if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT)) 29084260Sobrien while ((p < high) && isspace((unsigned char) *p)) 29184260Sobrien p++; 29284260Sobrien } 2931573Srgrimes 29484260Sobrien /* p now points where we want it */ 29584260Sobrien if (p > high) 29684260Sobrien return (high); 29784260Sobrien else 29884260Sobrien return (p); 2991573Srgrimes} 3001573Srgrimes 3011573Srgrimes 3021573Srgrimes/* cv_prev_word(): 3031573Srgrimes * Find the previous word vi style 3041573Srgrimes */ 3051573Srgrimesprotected char * 306148834Sstefanfcv_prev_word(char *p, char *low, int n, int (*wtest)(int)) 3071573Srgrimes{ 30884260Sobrien int test; 3091573Srgrimes 310148834Sstefanf p--; 31184260Sobrien while (n--) { 312148834Sstefanf while ((p > low) && isspace((unsigned char) *p)) 313148834Sstefanf p--; 31484260Sobrien test = (*wtest)((unsigned char) *p); 31584260Sobrien while ((p >= low) && (*wtest)((unsigned char) *p) == test) 31684260Sobrien p--; 31784260Sobrien } 318148834Sstefanf p++; 3191573Srgrimes 32084260Sobrien /* p now points where we want it */ 32184260Sobrien if (p < low) 32284260Sobrien return (low); 32384260Sobrien else 32484260Sobrien return (p); 3251573Srgrimes} 3261573Srgrimes 3271573Srgrimes 3281573Srgrimes#ifdef notdef 3291573Srgrimes/* c__number(): 3301573Srgrimes * Ignore character p points to, return number appearing after that. 3311573Srgrimes * A '$' by itself means a big number; "$-" is for negative; '^' means 1. 3321573Srgrimes * Return p pointing to last char used. 3331573Srgrimes */ 3341573Srgrimesprotected char * 33584260Sobrienc__number( 33684260Sobrien char *p, /* character position */ 33784260Sobrien int *num, /* Return value */ 33884260Sobrien int dval) /* dval is the number to subtract from like $-3 */ 3391573Srgrimes{ 34084260Sobrien int i; 34184260Sobrien int sign = 1; 3421573Srgrimes 34384260Sobrien if (*++p == '^') { 34484260Sobrien *num = 1; 34584260Sobrien return (p); 3461573Srgrimes } 34784260Sobrien if (*p == '$') { 34884260Sobrien if (*++p != '-') { 34984260Sobrien *num = 0x7fffffff; /* Handle $ */ 35084260Sobrien return (--p); 35184260Sobrien } 35284260Sobrien sign = -1; /* Handle $- */ 35384260Sobrien ++p; 35484260Sobrien } 35584260Sobrien for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0') 35684260Sobrien continue; 35784260Sobrien *num = (sign < 0 ? dval - i : i); 35884260Sobrien return (--p); 3591573Srgrimes} 3601573Srgrimes#endif 3611573Srgrimes 3621573Srgrimes/* cv_delfini(): 3631573Srgrimes * Finish vi delete action 3641573Srgrimes */ 3651573Srgrimesprotected void 36684260Sobriencv_delfini(EditLine *el) 3671573Srgrimes{ 36884260Sobrien int size; 369148834Sstefanf int action = el->el_chared.c_vcmd.action; 3701573Srgrimes 371148834Sstefanf if (action & INSERT) 37284260Sobrien el->el_map.current = el->el_map.key; 3731573Srgrimes 37484260Sobrien if (el->el_chared.c_vcmd.pos == 0) 375148834Sstefanf /* sanity */ 37684260Sobrien return; 3771573Srgrimes 378238178Spfg size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos); 379148834Sstefanf if (size == 0) 380148834Sstefanf size = 1; 381148834Sstefanf el->el_line.cursor = el->el_chared.c_vcmd.pos; 382148834Sstefanf if (action & YANK) { 383148834Sstefanf if (size > 0) 384148834Sstefanf cv_yank(el, el->el_line.cursor, size); 385148834Sstefanf else 386148834Sstefanf cv_yank(el, el->el_line.cursor + size, -size); 38784260Sobrien } else { 388148834Sstefanf if (size > 0) { 389148834Sstefanf c_delafter(el, size); 390148834Sstefanf re_refresh_cursor(el); 391148834Sstefanf } else { 392148834Sstefanf c_delbefore(el, -size); 393148834Sstefanf el->el_line.cursor += size; 394148834Sstefanf } 39584260Sobrien } 396148834Sstefanf el->el_chared.c_vcmd.action = NOP; 3971573Srgrimes} 3981573Srgrimes 3991573Srgrimes 4001573Srgrimes#ifdef notdef 4011573Srgrimes/* ce__endword(): 4021573Srgrimes * Go to the end of this word according to emacs 4031573Srgrimes */ 4041573Srgrimesprotected char * 40584260Sobrience__endword(char *p, char *high, int n) 4061573Srgrimes{ 40784260Sobrien p++; 4081573Srgrimes 40984260Sobrien while (n--) { 41084260Sobrien while ((p < high) && isspace((unsigned char) *p)) 41184260Sobrien p++; 41284260Sobrien while ((p < high) && !isspace((unsigned char) *p)) 41384260Sobrien p++; 41484260Sobrien } 4151573Srgrimes 41684260Sobrien p--; 41784260Sobrien return (p); 4181573Srgrimes} 4191573Srgrimes#endif 4201573Srgrimes 4211573Srgrimes 4221573Srgrimes/* cv__endword(): 4231573Srgrimes * Go to the end of this word according to vi 4241573Srgrimes */ 4251573Srgrimesprotected char * 426148834Sstefanfcv__endword(char *p, char *high, int n, int (*wtest)(int)) 4271573Srgrimes{ 428148834Sstefanf int test; 429148834Sstefanf 43084260Sobrien p++; 4311573Srgrimes 43284260Sobrien while (n--) { 43384260Sobrien while ((p < high) && isspace((unsigned char) *p)) 43484260Sobrien p++; 4351573Srgrimes 436148834Sstefanf test = (*wtest)((unsigned char) *p); 437148834Sstefanf while ((p < high) && (*wtest)((unsigned char) *p) == test) 438148834Sstefanf p++; 43984260Sobrien } 44084260Sobrien p--; 44184260Sobrien return (p); 4421573Srgrimes} 4431573Srgrimes 4441573Srgrimes/* ch_init(): 4451573Srgrimes * Initialize the character editor 4461573Srgrimes */ 4471573Srgrimesprotected int 44884260Sobriench_init(EditLine *el) 4491573Srgrimes{ 450148834Sstefanf c_macro_t *ma = &el->el_chared.c_macro; 451148834Sstefanf 45284260Sobrien el->el_line.buffer = (char *) el_malloc(EL_BUFSIZ); 45384260Sobrien if (el->el_line.buffer == NULL) 45484260Sobrien return (-1); 4551573Srgrimes 45684260Sobrien (void) memset(el->el_line.buffer, 0, EL_BUFSIZ); 45784260Sobrien el->el_line.cursor = el->el_line.buffer; 45884260Sobrien el->el_line.lastchar = el->el_line.buffer; 459148834Sstefanf el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE]; 4601573Srgrimes 46184260Sobrien el->el_chared.c_undo.buf = (char *) el_malloc(EL_BUFSIZ); 46284260Sobrien if (el->el_chared.c_undo.buf == NULL) 46384260Sobrien return (-1); 46484260Sobrien (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ); 465148834Sstefanf el->el_chared.c_undo.len = -1; 466148834Sstefanf el->el_chared.c_undo.cursor = 0; 467148834Sstefanf el->el_chared.c_redo.buf = (char *) el_malloc(EL_BUFSIZ); 468148834Sstefanf if (el->el_chared.c_redo.buf == NULL) 469148834Sstefanf return (-1); 470148834Sstefanf el->el_chared.c_redo.pos = el->el_chared.c_redo.buf; 471148834Sstefanf el->el_chared.c_redo.lim = el->el_chared.c_redo.buf + EL_BUFSIZ; 472148834Sstefanf el->el_chared.c_redo.cmd = ED_UNASSIGNED; 4731573Srgrimes 47484260Sobrien el->el_chared.c_vcmd.action = NOP; 47584260Sobrien el->el_chared.c_vcmd.pos = el->el_line.buffer; 4761573Srgrimes 47784260Sobrien el->el_chared.c_kill.buf = (char *) el_malloc(EL_BUFSIZ); 47884260Sobrien if (el->el_chared.c_kill.buf == NULL) 47984260Sobrien return (-1); 48084260Sobrien (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ); 48184260Sobrien el->el_chared.c_kill.mark = el->el_line.buffer; 48284260Sobrien el->el_chared.c_kill.last = el->el_chared.c_kill.buf; 4831573Srgrimes 48484260Sobrien el->el_map.current = el->el_map.key; 4851573Srgrimes 48684260Sobrien el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ 48784260Sobrien el->el_state.doingarg = 0; 48884260Sobrien el->el_state.metanext = 0; 48984260Sobrien el->el_state.argument = 1; 49084260Sobrien el->el_state.lastcmd = ED_UNASSIGNED; 49184260Sobrien 492148834Sstefanf ma->level = -1; 493148834Sstefanf ma->offset = 0; 494148834Sstefanf ma->macro = (char **) el_malloc(EL_MAXMACRO * sizeof(char *)); 495148834Sstefanf if (ma->macro == NULL) 49684260Sobrien return (-1); 49784260Sobrien return (0); 4981573Srgrimes} 4991573Srgrimes 5001573Srgrimes/* ch_reset(): 5011573Srgrimes * Reset the character editor 5021573Srgrimes */ 5031573Srgrimesprotected void 504148834Sstefanfch_reset(EditLine *el, int mclear) 5051573Srgrimes{ 50684260Sobrien el->el_line.cursor = el->el_line.buffer; 50784260Sobrien el->el_line.lastchar = el->el_line.buffer; 5081573Srgrimes 509148834Sstefanf el->el_chared.c_undo.len = -1; 510148834Sstefanf el->el_chared.c_undo.cursor = 0; 5111573Srgrimes 51284260Sobrien el->el_chared.c_vcmd.action = NOP; 51384260Sobrien el->el_chared.c_vcmd.pos = el->el_line.buffer; 5141573Srgrimes 51584260Sobrien el->el_chared.c_kill.mark = el->el_line.buffer; 5161573Srgrimes 51784260Sobrien el->el_map.current = el->el_map.key; 5181573Srgrimes 51984260Sobrien el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ 52084260Sobrien el->el_state.doingarg = 0; 52184260Sobrien el->el_state.metanext = 0; 52284260Sobrien el->el_state.argument = 1; 52384260Sobrien el->el_state.lastcmd = ED_UNASSIGNED; 5241573Srgrimes 525148897Sstefanf el->el_history.eventno = 0; 526148897Sstefanf 527148834Sstefanf if (mclear) 528148834Sstefanf ch__clearmacro(el); 529148834Sstefanf} 5301573Srgrimes 531148834Sstefanfprivate void 532238178Spfgch__clearmacro(EditLine *el) 533148834Sstefanf{ 534148834Sstefanf c_macro_t *ma = &el->el_chared.c_macro; 535148834Sstefanf while (ma->level >= 0) 536148834Sstefanf el_free((ptr_t)ma->macro[ma->level--]); 5371573Srgrimes} 5381573Srgrimes 53984260Sobrien/* ch_enlargebufs(): 54084260Sobrien * Enlarge line buffer to be able to hold twice as much characters. 54184260Sobrien * Returns 1 if successful, 0 if not. 54284260Sobrien */ 54384260Sobrienprotected int 544238178Spfgch_enlargebufs(EditLine *el, size_t addlen) 54584260Sobrien{ 54684260Sobrien size_t sz, newsz; 54784260Sobrien char *newbuffer, *oldbuf, *oldkbuf; 5481573Srgrimes 54984260Sobrien sz = el->el_line.limit - el->el_line.buffer + EL_LEAVE; 55084260Sobrien newsz = sz * 2; 55184260Sobrien /* 55284260Sobrien * If newly required length is longer than current buffer, we need 55384260Sobrien * to make the buffer big enough to hold both old and new stuff. 55484260Sobrien */ 55584260Sobrien if (addlen > sz) { 55684260Sobrien while(newsz - sz < addlen) 55784260Sobrien newsz *= 2; 55884260Sobrien } 55984260Sobrien 56084260Sobrien /* 56184260Sobrien * Reallocate line buffer. 56284260Sobrien */ 56384260Sobrien newbuffer = el_realloc(el->el_line.buffer, newsz); 56484260Sobrien if (!newbuffer) 56584260Sobrien return 0; 56684260Sobrien 56784260Sobrien /* zero the newly added memory, leave old data in */ 56884260Sobrien (void) memset(&newbuffer[sz], 0, newsz - sz); 56984260Sobrien 57084260Sobrien oldbuf = el->el_line.buffer; 57184260Sobrien 57284260Sobrien el->el_line.buffer = newbuffer; 57384260Sobrien el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf); 57484260Sobrien el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf); 575148834Sstefanf /* don't set new size until all buffers are enlarged */ 576148834Sstefanf el->el_line.limit = &newbuffer[sz - EL_LEAVE]; 57784260Sobrien 57884260Sobrien /* 57984260Sobrien * Reallocate kill buffer. 58084260Sobrien */ 58184260Sobrien newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz); 58284260Sobrien if (!newbuffer) 58384260Sobrien return 0; 58484260Sobrien 58584260Sobrien /* zero the newly added memory, leave old data in */ 58684260Sobrien (void) memset(&newbuffer[sz], 0, newsz - sz); 58784260Sobrien 58884260Sobrien oldkbuf = el->el_chared.c_kill.buf; 58984260Sobrien 59084260Sobrien el->el_chared.c_kill.buf = newbuffer; 59184260Sobrien el->el_chared.c_kill.last = newbuffer + 59284260Sobrien (el->el_chared.c_kill.last - oldkbuf); 59384260Sobrien el->el_chared.c_kill.mark = el->el_line.buffer + 59484260Sobrien (el->el_chared.c_kill.mark - oldbuf); 59584260Sobrien 59684260Sobrien /* 59784260Sobrien * Reallocate undo buffer. 59884260Sobrien */ 59984260Sobrien newbuffer = el_realloc(el->el_chared.c_undo.buf, newsz); 60084260Sobrien if (!newbuffer) 60184260Sobrien return 0; 60284260Sobrien 60384260Sobrien /* zero the newly added memory, leave old data in */ 60484260Sobrien (void) memset(&newbuffer[sz], 0, newsz - sz); 605148834Sstefanf el->el_chared.c_undo.buf = newbuffer; 60684260Sobrien 607148834Sstefanf newbuffer = el_realloc(el->el_chared.c_redo.buf, newsz); 608148834Sstefanf if (!newbuffer) 609148834Sstefanf return 0; 610148834Sstefanf el->el_chared.c_redo.pos = newbuffer + 611148834Sstefanf (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf); 612148834Sstefanf el->el_chared.c_redo.lim = newbuffer + 613148834Sstefanf (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf); 614148834Sstefanf el->el_chared.c_redo.buf = newbuffer; 61584260Sobrien 61684260Sobrien if (!hist_enlargebuf(el, sz, newsz)) 61784260Sobrien return 0; 61884260Sobrien 619148834Sstefanf /* Safe to set enlarged buffer size */ 620148834Sstefanf el->el_line.limit = &el->el_line.buffer[newsz - EL_LEAVE]; 62184260Sobrien return 1; 62284260Sobrien} 62384260Sobrien 6241573Srgrimes/* ch_end(): 6251573Srgrimes * Free the data structures used by the editor 6261573Srgrimes */ 6271573Srgrimesprotected void 62884260Sobriench_end(EditLine *el) 6291573Srgrimes{ 63084260Sobrien el_free((ptr_t) el->el_line.buffer); 63184260Sobrien el->el_line.buffer = NULL; 63284260Sobrien el->el_line.limit = NULL; 63384260Sobrien el_free((ptr_t) el->el_chared.c_undo.buf); 63484260Sobrien el->el_chared.c_undo.buf = NULL; 635148834Sstefanf el_free((ptr_t) el->el_chared.c_redo.buf); 636148834Sstefanf el->el_chared.c_redo.buf = NULL; 637148834Sstefanf el->el_chared.c_redo.pos = NULL; 638148834Sstefanf el->el_chared.c_redo.lim = NULL; 639148834Sstefanf el->el_chared.c_redo.cmd = ED_UNASSIGNED; 64084260Sobrien el_free((ptr_t) el->el_chared.c_kill.buf); 64184260Sobrien el->el_chared.c_kill.buf = NULL; 642148834Sstefanf ch_reset(el, 1); 64384260Sobrien el_free((ptr_t) el->el_chared.c_macro.macro); 64484260Sobrien el->el_chared.c_macro.macro = NULL; 6451573Srgrimes} 6461573Srgrimes 6471573Srgrimes 6481573Srgrimes/* el_insertstr(): 6491573Srgrimes * Insert string at cursorI 6501573Srgrimes */ 6511573Srgrimespublic int 65284260Sobrienel_insertstr(EditLine *el, const char *s) 6531573Srgrimes{ 65484260Sobrien size_t len; 6551573Srgrimes 65684260Sobrien if ((len = strlen(s)) == 0) 65784260Sobrien return (-1); 65884260Sobrien if (el->el_line.lastchar + len >= el->el_line.limit) { 65984260Sobrien if (!ch_enlargebufs(el, len)) 66084260Sobrien return (-1); 66184260Sobrien } 6621573Srgrimes 66384260Sobrien c_insert(el, (int)len); 66484260Sobrien while (*s) 66584260Sobrien *el->el_line.cursor++ = *s++; 66684260Sobrien return (0); 6671573Srgrimes} 6681573Srgrimes 6691573Srgrimes 6701573Srgrimes/* el_deletestr(): 6711573Srgrimes * Delete num characters before the cursor 6721573Srgrimes */ 6731573Srgrimespublic void 67484260Sobrienel_deletestr(EditLine *el, int n) 6751573Srgrimes{ 67684260Sobrien if (n <= 0) 67784260Sobrien return; 6781573Srgrimes 67984260Sobrien if (el->el_line.cursor < &el->el_line.buffer[n]) 68084260Sobrien return; 6811573Srgrimes 68284260Sobrien c_delbefore(el, n); /* delete before dot */ 68384260Sobrien el->el_line.cursor -= n; 68484260Sobrien if (el->el_line.cursor < el->el_line.buffer) 68584260Sobrien el->el_line.cursor = el->el_line.buffer; 6861573Srgrimes} 6871573Srgrimes 6881573Srgrimes/* c_gets(): 6891573Srgrimes * Get a string 6901573Srgrimes */ 6911573Srgrimesprotected int 692148834Sstefanfc_gets(EditLine *el, char *buf, const char *prompt) 6931573Srgrimes{ 69484260Sobrien char ch; 695238178Spfg ssize_t len; 696148834Sstefanf char *cp = el->el_line.buffer; 6971573Srgrimes 698148834Sstefanf if (prompt) { 699148834Sstefanf len = strlen(prompt); 700238178Spfg memcpy(cp, prompt, (size_t)len); 701148834Sstefanf cp += len; 702148834Sstefanf } 703148834Sstefanf len = 0; 704148834Sstefanf 705148834Sstefanf for (;;) { 706148834Sstefanf el->el_line.cursor = cp; 707148834Sstefanf *cp = ' '; 708148834Sstefanf el->el_line.lastchar = cp + 1; 709148834Sstefanf re_refresh(el); 710148834Sstefanf 711148834Sstefanf if (el_getc(el, &ch) != 1) { 712148834Sstefanf ed_end_of_file(el, 0); 713148834Sstefanf len = -1; 714148834Sstefanf break; 715148834Sstefanf } 716148834Sstefanf 71784260Sobrien switch (ch) { 718148834Sstefanf 71984260Sobrien case '\010': /* Delete and backspace */ 72084260Sobrien case '\177': 721238178Spfg if (len == 0) { 722148834Sstefanf len = -1; 723148834Sstefanf break; 72484260Sobrien } 725148834Sstefanf cp--; 726148834Sstefanf continue; 7271573Srgrimes 72884260Sobrien case '\033': /* ESC */ 72984260Sobrien case '\r': /* Newline */ 73084260Sobrien case '\n': 731148834Sstefanf buf[len] = ch; 73284260Sobrien break; 7331573Srgrimes 73484260Sobrien default: 735148834Sstefanf if (len >= EL_BUFSIZ - 16) 73684260Sobrien term_beep(el); 73784260Sobrien else { 73884260Sobrien buf[len++] = ch; 739148834Sstefanf *cp++ = ch; 74084260Sobrien } 741148834Sstefanf continue; 74284260Sobrien } 743148834Sstefanf break; 7441573Srgrimes } 745148834Sstefanf 746148834Sstefanf el->el_line.buffer[0] = '\0'; 747148834Sstefanf el->el_line.lastchar = el->el_line.buffer; 748148834Sstefanf el->el_line.cursor = el->el_line.buffer; 749238178Spfg return (int)len; 7501573Srgrimes} 7511573Srgrimes 7521573Srgrimes 7531573Srgrimes/* c_hpos(): 7541573Srgrimes * Return the current horizontal position of the cursor 7551573Srgrimes */ 7561573Srgrimesprotected int 75784260Sobrienc_hpos(EditLine *el) 7581573Srgrimes{ 75984260Sobrien char *ptr; 7601573Srgrimes 76184260Sobrien /* 76284260Sobrien * Find how many characters till the beginning of this line. 76384260Sobrien */ 76484260Sobrien if (el->el_line.cursor == el->el_line.buffer) 76584260Sobrien return (0); 76684260Sobrien else { 76784260Sobrien for (ptr = el->el_line.cursor - 1; 76884260Sobrien ptr >= el->el_line.buffer && *ptr != '\n'; 76984260Sobrien ptr--) 77084260Sobrien continue; 771238178Spfg return (int)(el->el_line.cursor - ptr - 1); 77284260Sobrien } 7731573Srgrimes} 774