1*84b940c1SJohn Marino /* $NetBSD: chared.c,v 1.40 2014/06/18 18:12:28 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*84b940c1SJohn Marino __RCSID("$NetBSD: chared.c,v 1.40 2014/06/18 18:12:28 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; 437*84b940c1SJohn Marino el->el_chared.c_aliasfun = NULL; 438*84b940c1SJohn Marino el->el_chared.c_aliasarg = NULL; 43932fe07f8SJohn Marino 44032fe07f8SJohn Marino el->el_map.current = el->el_map.key; 44132fe07f8SJohn Marino 44232fe07f8SJohn Marino el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ 44332fe07f8SJohn Marino el->el_state.doingarg = 0; 44432fe07f8SJohn Marino el->el_state.metanext = 0; 44532fe07f8SJohn Marino el->el_state.argument = 1; 44632fe07f8SJohn Marino el->el_state.lastcmd = ED_UNASSIGNED; 44732fe07f8SJohn Marino 44832fe07f8SJohn Marino ma->level = -1; 44932fe07f8SJohn Marino ma->offset = 0; 45032fe07f8SJohn Marino ma->macro = el_malloc(EL_MAXMACRO * sizeof(*ma->macro)); 45132fe07f8SJohn Marino if (ma->macro == NULL) 45232fe07f8SJohn Marino return -1; 45332fe07f8SJohn Marino return 0; 45432fe07f8SJohn Marino } 45532fe07f8SJohn Marino 45632fe07f8SJohn Marino /* ch_reset(): 45732fe07f8SJohn Marino * Reset the character editor 45832fe07f8SJohn Marino */ 45932fe07f8SJohn Marino protected void 46032fe07f8SJohn Marino ch_reset(EditLine *el, int mclear) 46132fe07f8SJohn Marino { 46232fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer; 46332fe07f8SJohn Marino el->el_line.lastchar = el->el_line.buffer; 46432fe07f8SJohn Marino 46532fe07f8SJohn Marino el->el_chared.c_undo.len = -1; 46632fe07f8SJohn Marino el->el_chared.c_undo.cursor = 0; 46732fe07f8SJohn Marino 46832fe07f8SJohn Marino el->el_chared.c_vcmd.action = NOP; 46932fe07f8SJohn Marino el->el_chared.c_vcmd.pos = el->el_line.buffer; 47032fe07f8SJohn Marino 47132fe07f8SJohn Marino el->el_chared.c_kill.mark = el->el_line.buffer; 47232fe07f8SJohn Marino 47332fe07f8SJohn Marino el->el_map.current = el->el_map.key; 47432fe07f8SJohn Marino 47532fe07f8SJohn Marino el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ 47632fe07f8SJohn Marino el->el_state.doingarg = 0; 47732fe07f8SJohn Marino el->el_state.metanext = 0; 47832fe07f8SJohn Marino el->el_state.argument = 1; 47932fe07f8SJohn Marino el->el_state.lastcmd = ED_UNASSIGNED; 48032fe07f8SJohn Marino 48132fe07f8SJohn Marino el->el_history.eventno = 0; 48232fe07f8SJohn Marino 48332fe07f8SJohn Marino if (mclear) 48432fe07f8SJohn Marino ch__clearmacro(el); 48532fe07f8SJohn Marino } 48632fe07f8SJohn Marino 48732fe07f8SJohn Marino private void 48832fe07f8SJohn Marino ch__clearmacro(EditLine *el) 48932fe07f8SJohn Marino { 49032fe07f8SJohn Marino c_macro_t *ma = &el->el_chared.c_macro; 49132fe07f8SJohn Marino while (ma->level >= 0) 49232fe07f8SJohn Marino el_free(ma->macro[ma->level--]); 49332fe07f8SJohn Marino } 49432fe07f8SJohn Marino 49532fe07f8SJohn Marino /* ch_enlargebufs(): 49632fe07f8SJohn Marino * Enlarge line buffer to be able to hold twice as much characters. 49732fe07f8SJohn Marino * Returns 1 if successful, 0 if not. 49832fe07f8SJohn Marino */ 49932fe07f8SJohn Marino protected int 50032fe07f8SJohn Marino ch_enlargebufs(EditLine *el, size_t addlen) 50132fe07f8SJohn Marino { 50232fe07f8SJohn Marino size_t sz, newsz; 50332fe07f8SJohn Marino Char *newbuffer, *oldbuf, *oldkbuf; 50432fe07f8SJohn Marino 50532fe07f8SJohn Marino sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE); 50632fe07f8SJohn Marino newsz = sz * 2; 50732fe07f8SJohn Marino /* 50832fe07f8SJohn Marino * If newly required length is longer than current buffer, we need 50932fe07f8SJohn Marino * to make the buffer big enough to hold both old and new stuff. 51032fe07f8SJohn Marino */ 51132fe07f8SJohn Marino if (addlen > sz) { 51232fe07f8SJohn Marino while(newsz - sz < addlen) 51332fe07f8SJohn Marino newsz *= 2; 51432fe07f8SJohn Marino } 51532fe07f8SJohn Marino 51632fe07f8SJohn Marino /* 51732fe07f8SJohn Marino * Reallocate line buffer. 51832fe07f8SJohn Marino */ 51932fe07f8SJohn Marino newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer)); 52032fe07f8SJohn Marino if (!newbuffer) 52132fe07f8SJohn Marino return 0; 52232fe07f8SJohn Marino 52332fe07f8SJohn Marino /* zero the newly added memory, leave old data in */ 52432fe07f8SJohn Marino (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 52532fe07f8SJohn Marino 52632fe07f8SJohn Marino oldbuf = el->el_line.buffer; 52732fe07f8SJohn Marino 52832fe07f8SJohn Marino el->el_line.buffer = newbuffer; 52932fe07f8SJohn Marino el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf); 53032fe07f8SJohn Marino el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf); 53132fe07f8SJohn Marino /* don't set new size until all buffers are enlarged */ 53232fe07f8SJohn Marino el->el_line.limit = &newbuffer[sz - EL_LEAVE]; 53332fe07f8SJohn Marino 53432fe07f8SJohn Marino /* 53532fe07f8SJohn Marino * Reallocate kill buffer. 53632fe07f8SJohn Marino */ 53732fe07f8SJohn Marino newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz * 53832fe07f8SJohn Marino sizeof(*newbuffer)); 53932fe07f8SJohn Marino if (!newbuffer) 54032fe07f8SJohn Marino return 0; 54132fe07f8SJohn Marino 54232fe07f8SJohn Marino /* zero the newly added memory, leave old data in */ 54332fe07f8SJohn Marino (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 54432fe07f8SJohn Marino 54532fe07f8SJohn Marino oldkbuf = el->el_chared.c_kill.buf; 54632fe07f8SJohn Marino 54732fe07f8SJohn Marino el->el_chared.c_kill.buf = newbuffer; 54832fe07f8SJohn Marino el->el_chared.c_kill.last = newbuffer + 54932fe07f8SJohn Marino (el->el_chared.c_kill.last - oldkbuf); 55032fe07f8SJohn Marino el->el_chared.c_kill.mark = el->el_line.buffer + 55132fe07f8SJohn Marino (el->el_chared.c_kill.mark - oldbuf); 55232fe07f8SJohn Marino 55332fe07f8SJohn Marino /* 55432fe07f8SJohn Marino * Reallocate undo buffer. 55532fe07f8SJohn Marino */ 55632fe07f8SJohn Marino newbuffer = el_realloc(el->el_chared.c_undo.buf, 55732fe07f8SJohn Marino newsz * sizeof(*newbuffer)); 55832fe07f8SJohn Marino if (!newbuffer) 55932fe07f8SJohn Marino return 0; 56032fe07f8SJohn Marino 56132fe07f8SJohn Marino /* zero the newly added memory, leave old data in */ 56232fe07f8SJohn Marino (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 56332fe07f8SJohn Marino el->el_chared.c_undo.buf = newbuffer; 56432fe07f8SJohn Marino 56532fe07f8SJohn Marino newbuffer = el_realloc(el->el_chared.c_redo.buf, 56632fe07f8SJohn Marino newsz * sizeof(*newbuffer)); 56732fe07f8SJohn Marino if (!newbuffer) 56832fe07f8SJohn Marino return 0; 56932fe07f8SJohn Marino el->el_chared.c_redo.pos = newbuffer + 57032fe07f8SJohn Marino (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf); 57132fe07f8SJohn Marino el->el_chared.c_redo.lim = newbuffer + 57232fe07f8SJohn Marino (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf); 57332fe07f8SJohn Marino el->el_chared.c_redo.buf = newbuffer; 57432fe07f8SJohn Marino 57532fe07f8SJohn Marino if (!hist_enlargebuf(el, sz, newsz)) 57632fe07f8SJohn Marino return 0; 57732fe07f8SJohn Marino 57832fe07f8SJohn Marino /* Safe to set enlarged buffer size */ 57932fe07f8SJohn Marino el->el_line.limit = &el->el_line.buffer[newsz - EL_LEAVE]; 58032fe07f8SJohn Marino if (el->el_chared.c_resizefun) 58132fe07f8SJohn Marino (*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg); 58232fe07f8SJohn Marino return 1; 58332fe07f8SJohn Marino } 58432fe07f8SJohn Marino 58532fe07f8SJohn Marino /* ch_end(): 58632fe07f8SJohn Marino * Free the data structures used by the editor 58732fe07f8SJohn Marino */ 58832fe07f8SJohn Marino protected void 58932fe07f8SJohn Marino ch_end(EditLine *el) 59032fe07f8SJohn Marino { 59132fe07f8SJohn Marino el_free(el->el_line.buffer); 59232fe07f8SJohn Marino el->el_line.buffer = NULL; 59332fe07f8SJohn Marino el->el_line.limit = NULL; 59432fe07f8SJohn Marino el_free(el->el_chared.c_undo.buf); 59532fe07f8SJohn Marino el->el_chared.c_undo.buf = NULL; 59632fe07f8SJohn Marino el_free(el->el_chared.c_redo.buf); 59732fe07f8SJohn Marino el->el_chared.c_redo.buf = NULL; 59832fe07f8SJohn Marino el->el_chared.c_redo.pos = NULL; 59932fe07f8SJohn Marino el->el_chared.c_redo.lim = NULL; 60032fe07f8SJohn Marino el->el_chared.c_redo.cmd = ED_UNASSIGNED; 60132fe07f8SJohn Marino el_free(el->el_chared.c_kill.buf); 60232fe07f8SJohn Marino el->el_chared.c_kill.buf = NULL; 60332fe07f8SJohn Marino ch_reset(el, 1); 60432fe07f8SJohn Marino el_free(el->el_chared.c_macro.macro); 60532fe07f8SJohn Marino el->el_chared.c_macro.macro = NULL; 60632fe07f8SJohn Marino } 60732fe07f8SJohn Marino 60832fe07f8SJohn Marino 60932fe07f8SJohn Marino /* el_insertstr(): 61032fe07f8SJohn Marino * Insert string at cursorI 61132fe07f8SJohn Marino */ 61232fe07f8SJohn Marino public int 61332fe07f8SJohn Marino FUN(el,insertstr)(EditLine *el, const Char *s) 61432fe07f8SJohn Marino { 61532fe07f8SJohn Marino size_t len; 61632fe07f8SJohn Marino 617c8e4d2bfSJohn Marino if (s == NULL || (len = Strlen(s)) == 0) 61832fe07f8SJohn Marino return -1; 61932fe07f8SJohn Marino if (el->el_line.lastchar + len >= el->el_line.limit) { 62032fe07f8SJohn Marino if (!ch_enlargebufs(el, len)) 62132fe07f8SJohn Marino return -1; 62232fe07f8SJohn Marino } 62332fe07f8SJohn Marino 62432fe07f8SJohn Marino c_insert(el, (int)len); 62532fe07f8SJohn Marino while (*s) 62632fe07f8SJohn Marino *el->el_line.cursor++ = *s++; 62732fe07f8SJohn Marino return 0; 62832fe07f8SJohn Marino } 62932fe07f8SJohn Marino 63032fe07f8SJohn Marino 63132fe07f8SJohn Marino /* el_deletestr(): 63232fe07f8SJohn Marino * Delete num characters before the cursor 63332fe07f8SJohn Marino */ 63432fe07f8SJohn Marino public void 63532fe07f8SJohn Marino el_deletestr(EditLine *el, int n) 63632fe07f8SJohn Marino { 63732fe07f8SJohn Marino if (n <= 0) 63832fe07f8SJohn Marino return; 63932fe07f8SJohn Marino 64032fe07f8SJohn Marino if (el->el_line.cursor < &el->el_line.buffer[n]) 64132fe07f8SJohn Marino return; 64232fe07f8SJohn Marino 64332fe07f8SJohn Marino c_delbefore(el, n); /* delete before dot */ 64432fe07f8SJohn Marino el->el_line.cursor -= n; 64532fe07f8SJohn Marino if (el->el_line.cursor < el->el_line.buffer) 64632fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer; 64732fe07f8SJohn Marino } 64832fe07f8SJohn Marino 649*84b940c1SJohn Marino /* el_cursor(): 650*84b940c1SJohn Marino * Move the cursor to the left or the right of the current position 651*84b940c1SJohn Marino */ 652*84b940c1SJohn Marino public int 653*84b940c1SJohn Marino el_cursor(EditLine *el, int n) 654*84b940c1SJohn Marino { 655*84b940c1SJohn Marino if (n == 0) 656*84b940c1SJohn Marino goto out; 657*84b940c1SJohn Marino 658*84b940c1SJohn Marino el->el_line.cursor += n; 659*84b940c1SJohn Marino 660*84b940c1SJohn Marino if (el->el_line.cursor < el->el_line.buffer) 661*84b940c1SJohn Marino el->el_line.cursor = el->el_line.buffer; 662*84b940c1SJohn Marino if (el->el_line.cursor > el->el_line.lastchar) 663*84b940c1SJohn Marino el->el_line.cursor = el->el_line.lastchar; 664*84b940c1SJohn Marino out: 665*84b940c1SJohn Marino return (int)(el->el_line.cursor - el->el_line.buffer); 666*84b940c1SJohn Marino } 667*84b940c1SJohn Marino 66832fe07f8SJohn Marino /* c_gets(): 66932fe07f8SJohn Marino * Get a string 67032fe07f8SJohn Marino */ 67132fe07f8SJohn Marino protected int 67232fe07f8SJohn Marino c_gets(EditLine *el, Char *buf, const Char *prompt) 67332fe07f8SJohn Marino { 67432fe07f8SJohn Marino Char ch; 67532fe07f8SJohn Marino ssize_t len; 67632fe07f8SJohn Marino Char *cp = el->el_line.buffer; 67732fe07f8SJohn Marino 67832fe07f8SJohn Marino if (prompt) { 67932fe07f8SJohn Marino len = (ssize_t)Strlen(prompt); 68032fe07f8SJohn Marino (void)memcpy(cp, prompt, (size_t)len * sizeof(*cp)); 68132fe07f8SJohn Marino cp += len; 68232fe07f8SJohn Marino } 68332fe07f8SJohn Marino len = 0; 68432fe07f8SJohn Marino 68532fe07f8SJohn Marino for (;;) { 68632fe07f8SJohn Marino el->el_line.cursor = cp; 68732fe07f8SJohn Marino *cp = ' '; 68832fe07f8SJohn Marino el->el_line.lastchar = cp + 1; 68932fe07f8SJohn Marino re_refresh(el); 69032fe07f8SJohn Marino 69132fe07f8SJohn Marino if (FUN(el,getc)(el, &ch) != 1) { 69232fe07f8SJohn Marino ed_end_of_file(el, 0); 69332fe07f8SJohn Marino len = -1; 69432fe07f8SJohn Marino break; 69532fe07f8SJohn Marino } 69632fe07f8SJohn Marino 69732fe07f8SJohn Marino switch (ch) { 69832fe07f8SJohn Marino 69932fe07f8SJohn Marino case 0010: /* Delete and backspace */ 70032fe07f8SJohn Marino case 0177: 70132fe07f8SJohn Marino if (len == 0) { 70232fe07f8SJohn Marino len = -1; 70332fe07f8SJohn Marino break; 70432fe07f8SJohn Marino } 70532fe07f8SJohn Marino cp--; 70632fe07f8SJohn Marino continue; 70732fe07f8SJohn Marino 70832fe07f8SJohn Marino case 0033: /* ESC */ 70932fe07f8SJohn Marino case '\r': /* Newline */ 71032fe07f8SJohn Marino case '\n': 71132fe07f8SJohn Marino buf[len] = ch; 71232fe07f8SJohn Marino break; 71332fe07f8SJohn Marino 71432fe07f8SJohn Marino default: 71532fe07f8SJohn Marino if (len >= (ssize_t)(EL_BUFSIZ - 16)) 71632fe07f8SJohn Marino terminal_beep(el); 71732fe07f8SJohn Marino else { 71832fe07f8SJohn Marino buf[len++] = ch; 71932fe07f8SJohn Marino *cp++ = ch; 72032fe07f8SJohn Marino } 72132fe07f8SJohn Marino continue; 72232fe07f8SJohn Marino } 72332fe07f8SJohn Marino break; 72432fe07f8SJohn Marino } 72532fe07f8SJohn Marino 72632fe07f8SJohn Marino el->el_line.buffer[0] = '\0'; 72732fe07f8SJohn Marino el->el_line.lastchar = el->el_line.buffer; 72832fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer; 72932fe07f8SJohn Marino return (int)len; 73032fe07f8SJohn Marino } 73132fe07f8SJohn Marino 73232fe07f8SJohn Marino 73332fe07f8SJohn Marino /* c_hpos(): 73432fe07f8SJohn Marino * Return the current horizontal position of the cursor 73532fe07f8SJohn Marino */ 73632fe07f8SJohn Marino protected int 73732fe07f8SJohn Marino c_hpos(EditLine *el) 73832fe07f8SJohn Marino { 73932fe07f8SJohn Marino Char *ptr; 74032fe07f8SJohn Marino 74132fe07f8SJohn Marino /* 74232fe07f8SJohn Marino * Find how many characters till the beginning of this line. 74332fe07f8SJohn Marino */ 74432fe07f8SJohn Marino if (el->el_line.cursor == el->el_line.buffer) 74532fe07f8SJohn Marino return 0; 74632fe07f8SJohn Marino else { 74732fe07f8SJohn Marino for (ptr = el->el_line.cursor - 1; 74832fe07f8SJohn Marino ptr >= el->el_line.buffer && *ptr != '\n'; 74932fe07f8SJohn Marino ptr--) 75032fe07f8SJohn Marino continue; 75132fe07f8SJohn Marino return (int)(el->el_line.cursor - ptr - 1); 75232fe07f8SJohn Marino } 75332fe07f8SJohn Marino } 75432fe07f8SJohn Marino 75532fe07f8SJohn Marino protected int 75632fe07f8SJohn Marino ch_resizefun(EditLine *el, el_zfunc_t f, void *a) 75732fe07f8SJohn Marino { 75832fe07f8SJohn Marino el->el_chared.c_resizefun = f; 75932fe07f8SJohn Marino el->el_chared.c_resizearg = a; 76032fe07f8SJohn Marino return 0; 76132fe07f8SJohn Marino } 762*84b940c1SJohn Marino 763*84b940c1SJohn Marino protected int 764*84b940c1SJohn Marino ch_aliasfun(EditLine *el, el_afunc_t f, void *a) 765*84b940c1SJohn Marino { 766*84b940c1SJohn Marino el->el_chared.c_aliasfun = f; 767*84b940c1SJohn Marino el->el_chared.c_aliasarg = a; 768*84b940c1SJohn Marino return 0; 769*84b940c1SJohn Marino } 770