1*c8e4d2bfSJohn Marino /* $NetBSD: chared.c,v 1.37 2012/07/18 17:12:39 christos Exp $ */ 232fe07f8SJohn Marino 332fe07f8SJohn Marino /*- 432fe07f8SJohn Marino * Copyright (c) 1992, 1993 532fe07f8SJohn Marino * The Regents of the University of California. All rights reserved. 632fe07f8SJohn Marino * 732fe07f8SJohn Marino * This code is derived from software contributed to Berkeley by 832fe07f8SJohn Marino * Christos Zoulas of Cornell University. 932fe07f8SJohn Marino * 1032fe07f8SJohn Marino * Redistribution and use in source and binary forms, with or without 1132fe07f8SJohn Marino * modification, are permitted provided that the following conditions 1232fe07f8SJohn Marino * are met: 1332fe07f8SJohn Marino * 1. Redistributions of source code must retain the above copyright 1432fe07f8SJohn Marino * notice, this list of conditions and the following disclaimer. 1532fe07f8SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright 1632fe07f8SJohn Marino * notice, this list of conditions and the following disclaimer in the 1732fe07f8SJohn Marino * documentation and/or other materials provided with the distribution. 1832fe07f8SJohn Marino * 3. Neither the name of the University nor the names of its contributors 1932fe07f8SJohn Marino * may be used to endorse or promote products derived from this software 2032fe07f8SJohn Marino * without specific prior written permission. 2132fe07f8SJohn Marino * 2232fe07f8SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2332fe07f8SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2432fe07f8SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2532fe07f8SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2632fe07f8SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2732fe07f8SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2832fe07f8SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2932fe07f8SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3032fe07f8SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3132fe07f8SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3232fe07f8SJohn Marino * SUCH DAMAGE. 3332fe07f8SJohn Marino */ 3432fe07f8SJohn Marino 3532fe07f8SJohn Marino #include "config.h" 3632fe07f8SJohn Marino #if !defined(lint) && !defined(SCCSID) 3732fe07f8SJohn Marino #if 0 3832fe07f8SJohn Marino static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93"; 3932fe07f8SJohn Marino #else 40*c8e4d2bfSJohn Marino __RCSID("$NetBSD: chared.c,v 1.37 2012/07/18 17:12:39 christos Exp $"); 4132fe07f8SJohn Marino #endif 4232fe07f8SJohn Marino #endif /* not lint && not SCCSID */ 4332fe07f8SJohn Marino 4432fe07f8SJohn Marino /* 4532fe07f8SJohn Marino * chared.c: Character editor utilities 4632fe07f8SJohn Marino */ 4732fe07f8SJohn Marino #include <stdlib.h> 4832fe07f8SJohn Marino #include "el.h" 4932fe07f8SJohn Marino 5032fe07f8SJohn Marino private void ch__clearmacro (EditLine *); 5132fe07f8SJohn Marino 5232fe07f8SJohn Marino /* value to leave unused in line buffer */ 5332fe07f8SJohn Marino #define EL_LEAVE 2 5432fe07f8SJohn Marino 5532fe07f8SJohn Marino /* cv_undo(): 5632fe07f8SJohn Marino * Handle state for the vi undo command 5732fe07f8SJohn Marino */ 5832fe07f8SJohn Marino protected void 5932fe07f8SJohn Marino cv_undo(EditLine *el) 6032fe07f8SJohn Marino { 6132fe07f8SJohn Marino c_undo_t *vu = &el->el_chared.c_undo; 6232fe07f8SJohn Marino c_redo_t *r = &el->el_chared.c_redo; 6332fe07f8SJohn Marino size_t size; 6432fe07f8SJohn Marino 6532fe07f8SJohn Marino /* Save entire line for undo */ 6632fe07f8SJohn Marino size = (size_t)(el->el_line.lastchar - el->el_line.buffer); 6732fe07f8SJohn Marino vu->len = (ssize_t)size; 6832fe07f8SJohn Marino vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer); 6932fe07f8SJohn Marino (void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf)); 7032fe07f8SJohn Marino 7132fe07f8SJohn Marino /* save command info for redo */ 7232fe07f8SJohn Marino r->count = el->el_state.doingarg ? el->el_state.argument : 0; 7332fe07f8SJohn Marino r->action = el->el_chared.c_vcmd.action; 7432fe07f8SJohn Marino r->pos = r->buf; 7532fe07f8SJohn Marino r->cmd = el->el_state.thiscmd; 7632fe07f8SJohn Marino r->ch = el->el_state.thisch; 7732fe07f8SJohn Marino } 7832fe07f8SJohn Marino 7932fe07f8SJohn Marino /* cv_yank(): 8032fe07f8SJohn Marino * Save yank/delete data for paste 8132fe07f8SJohn Marino */ 8232fe07f8SJohn Marino protected void 8332fe07f8SJohn Marino cv_yank(EditLine *el, const Char *ptr, int size) 8432fe07f8SJohn Marino { 8532fe07f8SJohn Marino c_kill_t *k = &el->el_chared.c_kill; 8632fe07f8SJohn Marino 8732fe07f8SJohn Marino (void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf)); 8832fe07f8SJohn Marino k->last = k->buf + size; 8932fe07f8SJohn Marino } 9032fe07f8SJohn Marino 9132fe07f8SJohn Marino 9232fe07f8SJohn Marino /* c_insert(): 9332fe07f8SJohn Marino * Insert num characters 9432fe07f8SJohn Marino */ 9532fe07f8SJohn Marino protected void 9632fe07f8SJohn Marino c_insert(EditLine *el, int num) 9732fe07f8SJohn Marino { 9832fe07f8SJohn Marino Char *cp; 9932fe07f8SJohn Marino 10032fe07f8SJohn Marino if (el->el_line.lastchar + num >= el->el_line.limit) { 10132fe07f8SJohn Marino if (!ch_enlargebufs(el, (size_t)num)) 10232fe07f8SJohn Marino return; /* can't go past end of buffer */ 10332fe07f8SJohn Marino } 10432fe07f8SJohn Marino 10532fe07f8SJohn Marino if (el->el_line.cursor < el->el_line.lastchar) { 10632fe07f8SJohn Marino /* if I must move chars */ 10732fe07f8SJohn Marino for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--) 10832fe07f8SJohn Marino cp[num] = *cp; 10932fe07f8SJohn Marino } 11032fe07f8SJohn Marino el->el_line.lastchar += num; 11132fe07f8SJohn Marino } 11232fe07f8SJohn Marino 11332fe07f8SJohn Marino 11432fe07f8SJohn Marino /* c_delafter(): 11532fe07f8SJohn Marino * Delete num characters after the cursor 11632fe07f8SJohn Marino */ 11732fe07f8SJohn Marino protected void 11832fe07f8SJohn Marino c_delafter(EditLine *el, int num) 11932fe07f8SJohn Marino { 12032fe07f8SJohn Marino 12132fe07f8SJohn Marino if (el->el_line.cursor + num > el->el_line.lastchar) 12232fe07f8SJohn Marino num = (int)(el->el_line.lastchar - el->el_line.cursor); 12332fe07f8SJohn Marino 12432fe07f8SJohn Marino if (el->el_map.current != el->el_map.emacs) { 12532fe07f8SJohn Marino cv_undo(el); 12632fe07f8SJohn Marino cv_yank(el, el->el_line.cursor, num); 12732fe07f8SJohn Marino } 12832fe07f8SJohn Marino 12932fe07f8SJohn Marino if (num > 0) { 13032fe07f8SJohn Marino Char *cp; 13132fe07f8SJohn Marino 13232fe07f8SJohn Marino for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) 13332fe07f8SJohn Marino *cp = cp[num]; 13432fe07f8SJohn Marino 13532fe07f8SJohn Marino el->el_line.lastchar -= num; 13632fe07f8SJohn Marino } 13732fe07f8SJohn Marino } 13832fe07f8SJohn Marino 13932fe07f8SJohn Marino 14032fe07f8SJohn Marino /* c_delafter1(): 14132fe07f8SJohn Marino * Delete the character after the cursor, do not yank 14232fe07f8SJohn Marino */ 14332fe07f8SJohn Marino protected void 14432fe07f8SJohn Marino c_delafter1(EditLine *el) 14532fe07f8SJohn Marino { 14632fe07f8SJohn Marino Char *cp; 14732fe07f8SJohn Marino 14832fe07f8SJohn Marino for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) 14932fe07f8SJohn Marino *cp = cp[1]; 15032fe07f8SJohn Marino 15132fe07f8SJohn Marino el->el_line.lastchar--; 15232fe07f8SJohn Marino } 15332fe07f8SJohn Marino 15432fe07f8SJohn Marino 15532fe07f8SJohn Marino /* c_delbefore(): 15632fe07f8SJohn Marino * Delete num characters before the cursor 15732fe07f8SJohn Marino */ 15832fe07f8SJohn Marino protected void 15932fe07f8SJohn Marino c_delbefore(EditLine *el, int num) 16032fe07f8SJohn Marino { 16132fe07f8SJohn Marino 16232fe07f8SJohn Marino if (el->el_line.cursor - num < el->el_line.buffer) 16332fe07f8SJohn Marino num = (int)(el->el_line.cursor - el->el_line.buffer); 16432fe07f8SJohn Marino 16532fe07f8SJohn Marino if (el->el_map.current != el->el_map.emacs) { 16632fe07f8SJohn Marino cv_undo(el); 16732fe07f8SJohn Marino cv_yank(el, el->el_line.cursor - num, num); 16832fe07f8SJohn Marino } 16932fe07f8SJohn Marino 17032fe07f8SJohn Marino if (num > 0) { 17132fe07f8SJohn Marino Char *cp; 17232fe07f8SJohn Marino 17332fe07f8SJohn Marino for (cp = el->el_line.cursor - num; 17432fe07f8SJohn Marino cp <= el->el_line.lastchar; 17532fe07f8SJohn Marino cp++) 17632fe07f8SJohn Marino *cp = cp[num]; 17732fe07f8SJohn Marino 17832fe07f8SJohn Marino el->el_line.lastchar -= num; 17932fe07f8SJohn Marino } 18032fe07f8SJohn Marino } 18132fe07f8SJohn Marino 18232fe07f8SJohn Marino 18332fe07f8SJohn Marino /* c_delbefore1(): 18432fe07f8SJohn Marino * Delete the character before the cursor, do not yank 18532fe07f8SJohn Marino */ 18632fe07f8SJohn Marino protected void 18732fe07f8SJohn Marino c_delbefore1(EditLine *el) 18832fe07f8SJohn Marino { 18932fe07f8SJohn Marino Char *cp; 19032fe07f8SJohn Marino 19132fe07f8SJohn Marino for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++) 19232fe07f8SJohn Marino *cp = cp[1]; 19332fe07f8SJohn Marino 19432fe07f8SJohn Marino el->el_line.lastchar--; 19532fe07f8SJohn Marino } 19632fe07f8SJohn Marino 19732fe07f8SJohn Marino 19832fe07f8SJohn Marino /* ce__isword(): 19932fe07f8SJohn Marino * Return if p is part of a word according to emacs 20032fe07f8SJohn Marino */ 20132fe07f8SJohn Marino protected int 20232fe07f8SJohn Marino ce__isword(Int p) 20332fe07f8SJohn Marino { 20432fe07f8SJohn Marino return Isalnum(p) || Strchr(STR("*?_-.[]~="), p) != NULL; 20532fe07f8SJohn Marino } 20632fe07f8SJohn Marino 20732fe07f8SJohn Marino 20832fe07f8SJohn Marino /* cv__isword(): 20932fe07f8SJohn Marino * Return if p is part of a word according to vi 21032fe07f8SJohn Marino */ 21132fe07f8SJohn Marino protected int 21232fe07f8SJohn Marino cv__isword(Int p) 21332fe07f8SJohn Marino { 21432fe07f8SJohn Marino if (Isalnum(p) || p == '_') 21532fe07f8SJohn Marino return 1; 21632fe07f8SJohn Marino if (Isgraph(p)) 21732fe07f8SJohn Marino return 2; 21832fe07f8SJohn Marino return 0; 21932fe07f8SJohn Marino } 22032fe07f8SJohn Marino 22132fe07f8SJohn Marino 22232fe07f8SJohn Marino /* cv__isWord(): 22332fe07f8SJohn Marino * Return if p is part of a big word according to vi 22432fe07f8SJohn Marino */ 22532fe07f8SJohn Marino protected int 22632fe07f8SJohn Marino cv__isWord(Int p) 22732fe07f8SJohn Marino { 22832fe07f8SJohn Marino return !Isspace(p); 22932fe07f8SJohn Marino } 23032fe07f8SJohn Marino 23132fe07f8SJohn Marino 23232fe07f8SJohn Marino /* c__prev_word(): 23332fe07f8SJohn Marino * Find the previous word 23432fe07f8SJohn Marino */ 23532fe07f8SJohn Marino protected Char * 23632fe07f8SJohn Marino c__prev_word(Char *p, Char *low, int n, int (*wtest)(Int)) 23732fe07f8SJohn Marino { 23832fe07f8SJohn Marino p--; 23932fe07f8SJohn Marino 24032fe07f8SJohn Marino while (n--) { 24132fe07f8SJohn Marino while ((p >= low) && !(*wtest)(*p)) 24232fe07f8SJohn Marino p--; 24332fe07f8SJohn Marino while ((p >= low) && (*wtest)(*p)) 24432fe07f8SJohn Marino p--; 24532fe07f8SJohn Marino } 24632fe07f8SJohn Marino 24732fe07f8SJohn Marino /* cp now points to one character before the word */ 24832fe07f8SJohn Marino p++; 24932fe07f8SJohn Marino if (p < low) 25032fe07f8SJohn Marino p = low; 25132fe07f8SJohn Marino /* cp now points where we want it */ 25232fe07f8SJohn Marino return p; 25332fe07f8SJohn Marino } 25432fe07f8SJohn Marino 25532fe07f8SJohn Marino 25632fe07f8SJohn Marino /* c__next_word(): 25732fe07f8SJohn Marino * Find the next word 25832fe07f8SJohn Marino */ 25932fe07f8SJohn Marino protected Char * 26032fe07f8SJohn Marino c__next_word(Char *p, Char *high, int n, int (*wtest)(Int)) 26132fe07f8SJohn Marino { 26232fe07f8SJohn Marino while (n--) { 26332fe07f8SJohn Marino while ((p < high) && !(*wtest)(*p)) 26432fe07f8SJohn Marino p++; 26532fe07f8SJohn Marino while ((p < high) && (*wtest)(*p)) 26632fe07f8SJohn Marino p++; 26732fe07f8SJohn Marino } 26832fe07f8SJohn Marino if (p > high) 26932fe07f8SJohn Marino p = high; 27032fe07f8SJohn Marino /* p now points where we want it */ 27132fe07f8SJohn Marino return p; 27232fe07f8SJohn Marino } 27332fe07f8SJohn Marino 27432fe07f8SJohn Marino /* cv_next_word(): 27532fe07f8SJohn Marino * Find the next word vi style 27632fe07f8SJohn Marino */ 27732fe07f8SJohn Marino protected Char * 27832fe07f8SJohn Marino cv_next_word(EditLine *el, Char *p, Char *high, int n, int (*wtest)(Int)) 27932fe07f8SJohn Marino { 28032fe07f8SJohn Marino int test; 28132fe07f8SJohn Marino 28232fe07f8SJohn Marino while (n--) { 28332fe07f8SJohn Marino test = (*wtest)(*p); 28432fe07f8SJohn Marino while ((p < high) && (*wtest)(*p) == test) 28532fe07f8SJohn Marino p++; 28632fe07f8SJohn Marino /* 28732fe07f8SJohn Marino * vi historically deletes with cw only the word preserving the 28832fe07f8SJohn Marino * trailing whitespace! This is not what 'w' does.. 28932fe07f8SJohn Marino */ 29032fe07f8SJohn Marino if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT)) 29132fe07f8SJohn Marino while ((p < high) && Isspace(*p)) 29232fe07f8SJohn Marino p++; 29332fe07f8SJohn Marino } 29432fe07f8SJohn Marino 29532fe07f8SJohn Marino /* p now points where we want it */ 29632fe07f8SJohn Marino if (p > high) 29732fe07f8SJohn Marino return high; 29832fe07f8SJohn Marino else 29932fe07f8SJohn Marino return p; 30032fe07f8SJohn Marino } 30132fe07f8SJohn Marino 30232fe07f8SJohn Marino 30332fe07f8SJohn Marino /* cv_prev_word(): 30432fe07f8SJohn Marino * Find the previous word vi style 30532fe07f8SJohn Marino */ 30632fe07f8SJohn Marino protected Char * 30732fe07f8SJohn Marino cv_prev_word(Char *p, Char *low, int n, int (*wtest)(Int)) 30832fe07f8SJohn Marino { 30932fe07f8SJohn Marino int test; 31032fe07f8SJohn Marino 31132fe07f8SJohn Marino p--; 31232fe07f8SJohn Marino while (n--) { 31332fe07f8SJohn Marino while ((p > low) && Isspace(*p)) 31432fe07f8SJohn Marino p--; 31532fe07f8SJohn Marino test = (*wtest)(*p); 31632fe07f8SJohn Marino while ((p >= low) && (*wtest)(*p) == test) 31732fe07f8SJohn Marino p--; 31832fe07f8SJohn Marino } 31932fe07f8SJohn Marino p++; 32032fe07f8SJohn Marino 32132fe07f8SJohn Marino /* p now points where we want it */ 32232fe07f8SJohn Marino if (p < low) 32332fe07f8SJohn Marino return low; 32432fe07f8SJohn Marino else 32532fe07f8SJohn Marino return p; 32632fe07f8SJohn Marino } 32732fe07f8SJohn Marino 32832fe07f8SJohn Marino 32932fe07f8SJohn Marino /* cv_delfini(): 33032fe07f8SJohn Marino * Finish vi delete action 33132fe07f8SJohn Marino */ 33232fe07f8SJohn Marino protected void 33332fe07f8SJohn Marino cv_delfini(EditLine *el) 33432fe07f8SJohn Marino { 33532fe07f8SJohn Marino int size; 33632fe07f8SJohn Marino int action = el->el_chared.c_vcmd.action; 33732fe07f8SJohn Marino 33832fe07f8SJohn Marino if (action & INSERT) 33932fe07f8SJohn Marino el->el_map.current = el->el_map.key; 34032fe07f8SJohn Marino 34132fe07f8SJohn Marino if (el->el_chared.c_vcmd.pos == 0) 34232fe07f8SJohn Marino /* sanity */ 34332fe07f8SJohn Marino return; 34432fe07f8SJohn Marino 34532fe07f8SJohn Marino size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos); 34632fe07f8SJohn Marino if (size == 0) 34732fe07f8SJohn Marino size = 1; 34832fe07f8SJohn Marino el->el_line.cursor = el->el_chared.c_vcmd.pos; 34932fe07f8SJohn Marino if (action & YANK) { 35032fe07f8SJohn Marino if (size > 0) 35132fe07f8SJohn Marino cv_yank(el, el->el_line.cursor, size); 35232fe07f8SJohn Marino else 35332fe07f8SJohn Marino cv_yank(el, el->el_line.cursor + size, -size); 35432fe07f8SJohn Marino } else { 35532fe07f8SJohn Marino if (size > 0) { 35632fe07f8SJohn Marino c_delafter(el, size); 35732fe07f8SJohn Marino re_refresh_cursor(el); 35832fe07f8SJohn Marino } else { 35932fe07f8SJohn Marino c_delbefore(el, -size); 36032fe07f8SJohn Marino el->el_line.cursor += size; 36132fe07f8SJohn Marino } 36232fe07f8SJohn Marino } 36332fe07f8SJohn Marino el->el_chared.c_vcmd.action = NOP; 36432fe07f8SJohn Marino } 36532fe07f8SJohn Marino 36632fe07f8SJohn Marino 36732fe07f8SJohn Marino /* cv__endword(): 36832fe07f8SJohn Marino * Go to the end of this word according to vi 36932fe07f8SJohn Marino */ 37032fe07f8SJohn Marino protected Char * 37132fe07f8SJohn Marino cv__endword(Char *p, Char *high, int n, int (*wtest)(Int)) 37232fe07f8SJohn Marino { 37332fe07f8SJohn Marino int test; 37432fe07f8SJohn Marino 37532fe07f8SJohn Marino p++; 37632fe07f8SJohn Marino 37732fe07f8SJohn Marino while (n--) { 37832fe07f8SJohn Marino while ((p < high) && Isspace(*p)) 37932fe07f8SJohn Marino p++; 38032fe07f8SJohn Marino 38132fe07f8SJohn Marino test = (*wtest)(*p); 38232fe07f8SJohn Marino while ((p < high) && (*wtest)(*p) == test) 38332fe07f8SJohn Marino p++; 38432fe07f8SJohn Marino } 38532fe07f8SJohn Marino p--; 38632fe07f8SJohn Marino return p; 38732fe07f8SJohn Marino } 38832fe07f8SJohn Marino 38932fe07f8SJohn Marino /* ch_init(): 39032fe07f8SJohn Marino * Initialize the character editor 39132fe07f8SJohn Marino */ 39232fe07f8SJohn Marino protected int 39332fe07f8SJohn Marino ch_init(EditLine *el) 39432fe07f8SJohn Marino { 39532fe07f8SJohn Marino c_macro_t *ma = &el->el_chared.c_macro; 39632fe07f8SJohn Marino 39732fe07f8SJohn Marino el->el_line.buffer = el_malloc(EL_BUFSIZ * 39832fe07f8SJohn Marino sizeof(*el->el_line.buffer)); 39932fe07f8SJohn Marino if (el->el_line.buffer == NULL) 40032fe07f8SJohn Marino return -1; 40132fe07f8SJohn Marino 40232fe07f8SJohn Marino (void) memset(el->el_line.buffer, 0, EL_BUFSIZ * 40332fe07f8SJohn Marino sizeof(*el->el_line.buffer)); 40432fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer; 40532fe07f8SJohn Marino el->el_line.lastchar = el->el_line.buffer; 40632fe07f8SJohn Marino el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE]; 40732fe07f8SJohn Marino 40832fe07f8SJohn Marino el->el_chared.c_undo.buf = el_malloc(EL_BUFSIZ * 40932fe07f8SJohn Marino sizeof(*el->el_chared.c_undo.buf)); 41032fe07f8SJohn Marino if (el->el_chared.c_undo.buf == NULL) 41132fe07f8SJohn Marino return -1; 41232fe07f8SJohn Marino (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ * 41332fe07f8SJohn Marino sizeof(*el->el_chared.c_undo.buf)); 41432fe07f8SJohn Marino el->el_chared.c_undo.len = -1; 41532fe07f8SJohn Marino el->el_chared.c_undo.cursor = 0; 41632fe07f8SJohn Marino el->el_chared.c_redo.buf = el_malloc(EL_BUFSIZ * 41732fe07f8SJohn Marino sizeof(*el->el_chared.c_redo.buf)); 41832fe07f8SJohn Marino if (el->el_chared.c_redo.buf == NULL) 41932fe07f8SJohn Marino return -1; 42032fe07f8SJohn Marino el->el_chared.c_redo.pos = el->el_chared.c_redo.buf; 42132fe07f8SJohn Marino el->el_chared.c_redo.lim = el->el_chared.c_redo.buf + EL_BUFSIZ; 42232fe07f8SJohn Marino el->el_chared.c_redo.cmd = ED_UNASSIGNED; 42332fe07f8SJohn Marino 42432fe07f8SJohn Marino el->el_chared.c_vcmd.action = NOP; 42532fe07f8SJohn Marino el->el_chared.c_vcmd.pos = el->el_line.buffer; 42632fe07f8SJohn Marino 42732fe07f8SJohn Marino el->el_chared.c_kill.buf = el_malloc(EL_BUFSIZ * 42832fe07f8SJohn Marino sizeof(*el->el_chared.c_kill.buf)); 42932fe07f8SJohn Marino if (el->el_chared.c_kill.buf == NULL) 43032fe07f8SJohn Marino return -1; 43132fe07f8SJohn Marino (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ * 43232fe07f8SJohn Marino sizeof(*el->el_chared.c_kill.buf)); 43332fe07f8SJohn Marino el->el_chared.c_kill.mark = el->el_line.buffer; 43432fe07f8SJohn Marino el->el_chared.c_kill.last = el->el_chared.c_kill.buf; 43532fe07f8SJohn Marino el->el_chared.c_resizefun = NULL; 43632fe07f8SJohn Marino el->el_chared.c_resizearg = NULL; 43732fe07f8SJohn Marino 43832fe07f8SJohn Marino el->el_map.current = el->el_map.key; 43932fe07f8SJohn Marino 44032fe07f8SJohn Marino el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ 44132fe07f8SJohn Marino el->el_state.doingarg = 0; 44232fe07f8SJohn Marino el->el_state.metanext = 0; 44332fe07f8SJohn Marino el->el_state.argument = 1; 44432fe07f8SJohn Marino el->el_state.lastcmd = ED_UNASSIGNED; 44532fe07f8SJohn Marino 44632fe07f8SJohn Marino ma->level = -1; 44732fe07f8SJohn Marino ma->offset = 0; 44832fe07f8SJohn Marino ma->macro = el_malloc(EL_MAXMACRO * sizeof(*ma->macro)); 44932fe07f8SJohn Marino if (ma->macro == NULL) 45032fe07f8SJohn Marino return -1; 45132fe07f8SJohn Marino return 0; 45232fe07f8SJohn Marino } 45332fe07f8SJohn Marino 45432fe07f8SJohn Marino /* ch_reset(): 45532fe07f8SJohn Marino * Reset the character editor 45632fe07f8SJohn Marino */ 45732fe07f8SJohn Marino protected void 45832fe07f8SJohn Marino ch_reset(EditLine *el, int mclear) 45932fe07f8SJohn Marino { 46032fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer; 46132fe07f8SJohn Marino el->el_line.lastchar = el->el_line.buffer; 46232fe07f8SJohn Marino 46332fe07f8SJohn Marino el->el_chared.c_undo.len = -1; 46432fe07f8SJohn Marino el->el_chared.c_undo.cursor = 0; 46532fe07f8SJohn Marino 46632fe07f8SJohn Marino el->el_chared.c_vcmd.action = NOP; 46732fe07f8SJohn Marino el->el_chared.c_vcmd.pos = el->el_line.buffer; 46832fe07f8SJohn Marino 46932fe07f8SJohn Marino el->el_chared.c_kill.mark = el->el_line.buffer; 47032fe07f8SJohn Marino 47132fe07f8SJohn Marino el->el_map.current = el->el_map.key; 47232fe07f8SJohn Marino 47332fe07f8SJohn Marino el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ 47432fe07f8SJohn Marino el->el_state.doingarg = 0; 47532fe07f8SJohn Marino el->el_state.metanext = 0; 47632fe07f8SJohn Marino el->el_state.argument = 1; 47732fe07f8SJohn Marino el->el_state.lastcmd = ED_UNASSIGNED; 47832fe07f8SJohn Marino 47932fe07f8SJohn Marino el->el_history.eventno = 0; 48032fe07f8SJohn Marino 48132fe07f8SJohn Marino if (mclear) 48232fe07f8SJohn Marino ch__clearmacro(el); 48332fe07f8SJohn Marino } 48432fe07f8SJohn Marino 48532fe07f8SJohn Marino private void 48632fe07f8SJohn Marino ch__clearmacro(EditLine *el) 48732fe07f8SJohn Marino { 48832fe07f8SJohn Marino c_macro_t *ma = &el->el_chared.c_macro; 48932fe07f8SJohn Marino while (ma->level >= 0) 49032fe07f8SJohn Marino el_free(ma->macro[ma->level--]); 49132fe07f8SJohn Marino } 49232fe07f8SJohn Marino 49332fe07f8SJohn Marino /* ch_enlargebufs(): 49432fe07f8SJohn Marino * Enlarge line buffer to be able to hold twice as much characters. 49532fe07f8SJohn Marino * Returns 1 if successful, 0 if not. 49632fe07f8SJohn Marino */ 49732fe07f8SJohn Marino protected int 49832fe07f8SJohn Marino ch_enlargebufs(EditLine *el, size_t addlen) 49932fe07f8SJohn Marino { 50032fe07f8SJohn Marino size_t sz, newsz; 50132fe07f8SJohn Marino Char *newbuffer, *oldbuf, *oldkbuf; 50232fe07f8SJohn Marino 50332fe07f8SJohn Marino sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE); 50432fe07f8SJohn Marino newsz = sz * 2; 50532fe07f8SJohn Marino /* 50632fe07f8SJohn Marino * If newly required length is longer than current buffer, we need 50732fe07f8SJohn Marino * to make the buffer big enough to hold both old and new stuff. 50832fe07f8SJohn Marino */ 50932fe07f8SJohn Marino if (addlen > sz) { 51032fe07f8SJohn Marino while(newsz - sz < addlen) 51132fe07f8SJohn Marino newsz *= 2; 51232fe07f8SJohn Marino } 51332fe07f8SJohn Marino 51432fe07f8SJohn Marino /* 51532fe07f8SJohn Marino * Reallocate line buffer. 51632fe07f8SJohn Marino */ 51732fe07f8SJohn Marino newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer)); 51832fe07f8SJohn Marino if (!newbuffer) 51932fe07f8SJohn Marino return 0; 52032fe07f8SJohn Marino 52132fe07f8SJohn Marino /* zero the newly added memory, leave old data in */ 52232fe07f8SJohn Marino (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 52332fe07f8SJohn Marino 52432fe07f8SJohn Marino oldbuf = el->el_line.buffer; 52532fe07f8SJohn Marino 52632fe07f8SJohn Marino el->el_line.buffer = newbuffer; 52732fe07f8SJohn Marino el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf); 52832fe07f8SJohn Marino el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf); 52932fe07f8SJohn Marino /* don't set new size until all buffers are enlarged */ 53032fe07f8SJohn Marino el->el_line.limit = &newbuffer[sz - EL_LEAVE]; 53132fe07f8SJohn Marino 53232fe07f8SJohn Marino /* 53332fe07f8SJohn Marino * Reallocate kill buffer. 53432fe07f8SJohn Marino */ 53532fe07f8SJohn Marino newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz * 53632fe07f8SJohn Marino sizeof(*newbuffer)); 53732fe07f8SJohn Marino if (!newbuffer) 53832fe07f8SJohn Marino return 0; 53932fe07f8SJohn Marino 54032fe07f8SJohn Marino /* zero the newly added memory, leave old data in */ 54132fe07f8SJohn Marino (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 54232fe07f8SJohn Marino 54332fe07f8SJohn Marino oldkbuf = el->el_chared.c_kill.buf; 54432fe07f8SJohn Marino 54532fe07f8SJohn Marino el->el_chared.c_kill.buf = newbuffer; 54632fe07f8SJohn Marino el->el_chared.c_kill.last = newbuffer + 54732fe07f8SJohn Marino (el->el_chared.c_kill.last - oldkbuf); 54832fe07f8SJohn Marino el->el_chared.c_kill.mark = el->el_line.buffer + 54932fe07f8SJohn Marino (el->el_chared.c_kill.mark - oldbuf); 55032fe07f8SJohn Marino 55132fe07f8SJohn Marino /* 55232fe07f8SJohn Marino * Reallocate undo buffer. 55332fe07f8SJohn Marino */ 55432fe07f8SJohn Marino newbuffer = el_realloc(el->el_chared.c_undo.buf, 55532fe07f8SJohn Marino newsz * sizeof(*newbuffer)); 55632fe07f8SJohn Marino if (!newbuffer) 55732fe07f8SJohn Marino return 0; 55832fe07f8SJohn Marino 55932fe07f8SJohn Marino /* zero the newly added memory, leave old data in */ 56032fe07f8SJohn Marino (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 56132fe07f8SJohn Marino el->el_chared.c_undo.buf = newbuffer; 56232fe07f8SJohn Marino 56332fe07f8SJohn Marino newbuffer = el_realloc(el->el_chared.c_redo.buf, 56432fe07f8SJohn Marino newsz * sizeof(*newbuffer)); 56532fe07f8SJohn Marino if (!newbuffer) 56632fe07f8SJohn Marino return 0; 56732fe07f8SJohn Marino el->el_chared.c_redo.pos = newbuffer + 56832fe07f8SJohn Marino (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf); 56932fe07f8SJohn Marino el->el_chared.c_redo.lim = newbuffer + 57032fe07f8SJohn Marino (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf); 57132fe07f8SJohn Marino el->el_chared.c_redo.buf = newbuffer; 57232fe07f8SJohn Marino 57332fe07f8SJohn Marino if (!hist_enlargebuf(el, sz, newsz)) 57432fe07f8SJohn Marino return 0; 57532fe07f8SJohn Marino 57632fe07f8SJohn Marino /* Safe to set enlarged buffer size */ 57732fe07f8SJohn Marino el->el_line.limit = &el->el_line.buffer[newsz - EL_LEAVE]; 57832fe07f8SJohn Marino if (el->el_chared.c_resizefun) 57932fe07f8SJohn Marino (*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg); 58032fe07f8SJohn Marino return 1; 58132fe07f8SJohn Marino } 58232fe07f8SJohn Marino 58332fe07f8SJohn Marino /* ch_end(): 58432fe07f8SJohn Marino * Free the data structures used by the editor 58532fe07f8SJohn Marino */ 58632fe07f8SJohn Marino protected void 58732fe07f8SJohn Marino ch_end(EditLine *el) 58832fe07f8SJohn Marino { 58932fe07f8SJohn Marino el_free(el->el_line.buffer); 59032fe07f8SJohn Marino el->el_line.buffer = NULL; 59132fe07f8SJohn Marino el->el_line.limit = NULL; 59232fe07f8SJohn Marino el_free(el->el_chared.c_undo.buf); 59332fe07f8SJohn Marino el->el_chared.c_undo.buf = NULL; 59432fe07f8SJohn Marino el_free(el->el_chared.c_redo.buf); 59532fe07f8SJohn Marino el->el_chared.c_redo.buf = NULL; 59632fe07f8SJohn Marino el->el_chared.c_redo.pos = NULL; 59732fe07f8SJohn Marino el->el_chared.c_redo.lim = NULL; 59832fe07f8SJohn Marino el->el_chared.c_redo.cmd = ED_UNASSIGNED; 59932fe07f8SJohn Marino el_free(el->el_chared.c_kill.buf); 60032fe07f8SJohn Marino el->el_chared.c_kill.buf = NULL; 60132fe07f8SJohn Marino ch_reset(el, 1); 60232fe07f8SJohn Marino el_free(el->el_chared.c_macro.macro); 60332fe07f8SJohn Marino el->el_chared.c_macro.macro = NULL; 60432fe07f8SJohn Marino } 60532fe07f8SJohn Marino 60632fe07f8SJohn Marino 60732fe07f8SJohn Marino /* el_insertstr(): 60832fe07f8SJohn Marino * Insert string at cursorI 60932fe07f8SJohn Marino */ 61032fe07f8SJohn Marino public int 61132fe07f8SJohn Marino FUN(el,insertstr)(EditLine *el, const Char *s) 61232fe07f8SJohn Marino { 61332fe07f8SJohn Marino size_t len; 61432fe07f8SJohn Marino 615*c8e4d2bfSJohn Marino if (s == NULL || (len = Strlen(s)) == 0) 61632fe07f8SJohn Marino return -1; 61732fe07f8SJohn Marino if (el->el_line.lastchar + len >= el->el_line.limit) { 61832fe07f8SJohn Marino if (!ch_enlargebufs(el, len)) 61932fe07f8SJohn Marino return -1; 62032fe07f8SJohn Marino } 62132fe07f8SJohn Marino 62232fe07f8SJohn Marino c_insert(el, (int)len); 62332fe07f8SJohn Marino while (*s) 62432fe07f8SJohn Marino *el->el_line.cursor++ = *s++; 62532fe07f8SJohn Marino return 0; 62632fe07f8SJohn Marino } 62732fe07f8SJohn Marino 62832fe07f8SJohn Marino 62932fe07f8SJohn Marino /* el_deletestr(): 63032fe07f8SJohn Marino * Delete num characters before the cursor 63132fe07f8SJohn Marino */ 63232fe07f8SJohn Marino public void 63332fe07f8SJohn Marino el_deletestr(EditLine *el, int n) 63432fe07f8SJohn Marino { 63532fe07f8SJohn Marino if (n <= 0) 63632fe07f8SJohn Marino return; 63732fe07f8SJohn Marino 63832fe07f8SJohn Marino if (el->el_line.cursor < &el->el_line.buffer[n]) 63932fe07f8SJohn Marino return; 64032fe07f8SJohn Marino 64132fe07f8SJohn Marino c_delbefore(el, n); /* delete before dot */ 64232fe07f8SJohn Marino el->el_line.cursor -= n; 64332fe07f8SJohn Marino if (el->el_line.cursor < el->el_line.buffer) 64432fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer; 64532fe07f8SJohn Marino } 64632fe07f8SJohn Marino 64732fe07f8SJohn Marino /* c_gets(): 64832fe07f8SJohn Marino * Get a string 64932fe07f8SJohn Marino */ 65032fe07f8SJohn Marino protected int 65132fe07f8SJohn Marino c_gets(EditLine *el, Char *buf, const Char *prompt) 65232fe07f8SJohn Marino { 65332fe07f8SJohn Marino Char ch; 65432fe07f8SJohn Marino ssize_t len; 65532fe07f8SJohn Marino Char *cp = el->el_line.buffer; 65632fe07f8SJohn Marino 65732fe07f8SJohn Marino if (prompt) { 65832fe07f8SJohn Marino len = (ssize_t)Strlen(prompt); 65932fe07f8SJohn Marino (void)memcpy(cp, prompt, (size_t)len * sizeof(*cp)); 66032fe07f8SJohn Marino cp += len; 66132fe07f8SJohn Marino } 66232fe07f8SJohn Marino len = 0; 66332fe07f8SJohn Marino 66432fe07f8SJohn Marino for (;;) { 66532fe07f8SJohn Marino el->el_line.cursor = cp; 66632fe07f8SJohn Marino *cp = ' '; 66732fe07f8SJohn Marino el->el_line.lastchar = cp + 1; 66832fe07f8SJohn Marino re_refresh(el); 66932fe07f8SJohn Marino 67032fe07f8SJohn Marino if (FUN(el,getc)(el, &ch) != 1) { 67132fe07f8SJohn Marino ed_end_of_file(el, 0); 67232fe07f8SJohn Marino len = -1; 67332fe07f8SJohn Marino break; 67432fe07f8SJohn Marino } 67532fe07f8SJohn Marino 67632fe07f8SJohn Marino switch (ch) { 67732fe07f8SJohn Marino 67832fe07f8SJohn Marino case 0010: /* Delete and backspace */ 67932fe07f8SJohn Marino case 0177: 68032fe07f8SJohn Marino if (len == 0) { 68132fe07f8SJohn Marino len = -1; 68232fe07f8SJohn Marino break; 68332fe07f8SJohn Marino } 68432fe07f8SJohn Marino cp--; 68532fe07f8SJohn Marino continue; 68632fe07f8SJohn Marino 68732fe07f8SJohn Marino case 0033: /* ESC */ 68832fe07f8SJohn Marino case '\r': /* Newline */ 68932fe07f8SJohn Marino case '\n': 69032fe07f8SJohn Marino buf[len] = ch; 69132fe07f8SJohn Marino break; 69232fe07f8SJohn Marino 69332fe07f8SJohn Marino default: 69432fe07f8SJohn Marino if (len >= (ssize_t)(EL_BUFSIZ - 16)) 69532fe07f8SJohn Marino terminal_beep(el); 69632fe07f8SJohn Marino else { 69732fe07f8SJohn Marino buf[len++] = ch; 69832fe07f8SJohn Marino *cp++ = ch; 69932fe07f8SJohn Marino } 70032fe07f8SJohn Marino continue; 70132fe07f8SJohn Marino } 70232fe07f8SJohn Marino break; 70332fe07f8SJohn Marino } 70432fe07f8SJohn Marino 70532fe07f8SJohn Marino el->el_line.buffer[0] = '\0'; 70632fe07f8SJohn Marino el->el_line.lastchar = el->el_line.buffer; 70732fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer; 70832fe07f8SJohn Marino return (int)len; 70932fe07f8SJohn Marino } 71032fe07f8SJohn Marino 71132fe07f8SJohn Marino 71232fe07f8SJohn Marino /* c_hpos(): 71332fe07f8SJohn Marino * Return the current horizontal position of the cursor 71432fe07f8SJohn Marino */ 71532fe07f8SJohn Marino protected int 71632fe07f8SJohn Marino c_hpos(EditLine *el) 71732fe07f8SJohn Marino { 71832fe07f8SJohn Marino Char *ptr; 71932fe07f8SJohn Marino 72032fe07f8SJohn Marino /* 72132fe07f8SJohn Marino * Find how many characters till the beginning of this line. 72232fe07f8SJohn Marino */ 72332fe07f8SJohn Marino if (el->el_line.cursor == el->el_line.buffer) 72432fe07f8SJohn Marino return 0; 72532fe07f8SJohn Marino else { 72632fe07f8SJohn Marino for (ptr = el->el_line.cursor - 1; 72732fe07f8SJohn Marino ptr >= el->el_line.buffer && *ptr != '\n'; 72832fe07f8SJohn Marino ptr--) 72932fe07f8SJohn Marino continue; 73032fe07f8SJohn Marino return (int)(el->el_line.cursor - ptr - 1); 73132fe07f8SJohn Marino } 73232fe07f8SJohn Marino } 73332fe07f8SJohn Marino 73432fe07f8SJohn Marino protected int 73532fe07f8SJohn Marino ch_resizefun(EditLine *el, el_zfunc_t f, void *a) 73632fe07f8SJohn Marino { 73732fe07f8SJohn Marino el->el_chared.c_resizefun = f; 73832fe07f8SJohn Marino el->el_chared.c_resizearg = a; 73932fe07f8SJohn Marino return 0; 74032fe07f8SJohn Marino } 741