1*ae19eda8Szrj /* $NetBSD: chared.c,v 1.57 2017/10/11 06:49:03 abhinav 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*ae19eda8Szrj __RCSID("$NetBSD: chared.c,v 1.57 2017/10/11 06:49:03 abhinav Exp $"); 4132fe07f8SJohn Marino #endif 4232fe07f8SJohn Marino #endif /* not lint && not SCCSID */ 4332fe07f8SJohn Marino 4432fe07f8SJohn Marino /* 4532fe07f8SJohn Marino * chared.c: Character editor utilities 4632fe07f8SJohn Marino */ 4712db70c8Szrj #include <ctype.h> 4832fe07f8SJohn Marino #include <stdlib.h> 4912db70c8Szrj #include <string.h> 5032fe07f8SJohn Marino 5112db70c8Szrj #include "el.h" 5212db70c8Szrj #include "common.h" 5312db70c8Szrj #include "fcns.h" 5432fe07f8SJohn Marino 5532fe07f8SJohn Marino /* value to leave unused in line buffer */ 5632fe07f8SJohn Marino #define EL_LEAVE 2 5732fe07f8SJohn Marino 5832fe07f8SJohn Marino /* cv_undo(): 5932fe07f8SJohn Marino * Handle state for the vi undo command 6032fe07f8SJohn Marino */ 6112db70c8Szrj libedit_private void 6232fe07f8SJohn Marino cv_undo(EditLine *el) 6332fe07f8SJohn Marino { 6432fe07f8SJohn Marino c_undo_t *vu = &el->el_chared.c_undo; 6532fe07f8SJohn Marino c_redo_t *r = &el->el_chared.c_redo; 6632fe07f8SJohn Marino size_t size; 6732fe07f8SJohn Marino 6832fe07f8SJohn Marino /* Save entire line for undo */ 6932fe07f8SJohn Marino size = (size_t)(el->el_line.lastchar - el->el_line.buffer); 7032fe07f8SJohn Marino vu->len = (ssize_t)size; 7132fe07f8SJohn Marino vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer); 7232fe07f8SJohn Marino (void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf)); 7332fe07f8SJohn Marino 7432fe07f8SJohn Marino /* save command info for redo */ 7532fe07f8SJohn Marino r->count = el->el_state.doingarg ? el->el_state.argument : 0; 7632fe07f8SJohn Marino r->action = el->el_chared.c_vcmd.action; 7732fe07f8SJohn Marino r->pos = r->buf; 7832fe07f8SJohn Marino r->cmd = el->el_state.thiscmd; 7932fe07f8SJohn Marino r->ch = el->el_state.thisch; 8032fe07f8SJohn Marino } 8132fe07f8SJohn Marino 8232fe07f8SJohn Marino /* cv_yank(): 8332fe07f8SJohn Marino * Save yank/delete data for paste 8432fe07f8SJohn Marino */ 8512db70c8Szrj libedit_private void 8612db70c8Szrj cv_yank(EditLine *el, const wchar_t *ptr, int size) 8732fe07f8SJohn Marino { 8832fe07f8SJohn Marino c_kill_t *k = &el->el_chared.c_kill; 8932fe07f8SJohn Marino 9032fe07f8SJohn Marino (void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf)); 9132fe07f8SJohn Marino k->last = k->buf + size; 9232fe07f8SJohn Marino } 9332fe07f8SJohn Marino 9432fe07f8SJohn Marino 9532fe07f8SJohn Marino /* c_insert(): 9632fe07f8SJohn Marino * Insert num characters 9732fe07f8SJohn Marino */ 9812db70c8Szrj libedit_private void 9932fe07f8SJohn Marino c_insert(EditLine *el, int num) 10032fe07f8SJohn Marino { 10112db70c8Szrj wchar_t *cp; 10232fe07f8SJohn Marino 10332fe07f8SJohn Marino if (el->el_line.lastchar + num >= el->el_line.limit) { 10432fe07f8SJohn Marino if (!ch_enlargebufs(el, (size_t)num)) 10532fe07f8SJohn Marino return; /* can't go past end of buffer */ 10632fe07f8SJohn Marino } 10732fe07f8SJohn Marino 10832fe07f8SJohn Marino if (el->el_line.cursor < el->el_line.lastchar) { 10932fe07f8SJohn Marino /* if I must move chars */ 11032fe07f8SJohn Marino for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--) 11132fe07f8SJohn Marino cp[num] = *cp; 11232fe07f8SJohn Marino } 11332fe07f8SJohn Marino el->el_line.lastchar += num; 11432fe07f8SJohn Marino } 11532fe07f8SJohn Marino 11632fe07f8SJohn Marino 11732fe07f8SJohn Marino /* c_delafter(): 11832fe07f8SJohn Marino * Delete num characters after the cursor 11932fe07f8SJohn Marino */ 12012db70c8Szrj libedit_private void 12132fe07f8SJohn Marino c_delafter(EditLine *el, int num) 12232fe07f8SJohn Marino { 12332fe07f8SJohn Marino 12432fe07f8SJohn Marino if (el->el_line.cursor + num > el->el_line.lastchar) 12532fe07f8SJohn Marino num = (int)(el->el_line.lastchar - el->el_line.cursor); 12632fe07f8SJohn Marino 12732fe07f8SJohn Marino if (el->el_map.current != el->el_map.emacs) { 12832fe07f8SJohn Marino cv_undo(el); 12932fe07f8SJohn Marino cv_yank(el, el->el_line.cursor, num); 13032fe07f8SJohn Marino } 13132fe07f8SJohn Marino 13232fe07f8SJohn Marino if (num > 0) { 13312db70c8Szrj wchar_t *cp; 13432fe07f8SJohn Marino 13532fe07f8SJohn Marino for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) 13632fe07f8SJohn Marino *cp = cp[num]; 13732fe07f8SJohn Marino 13832fe07f8SJohn Marino el->el_line.lastchar -= num; 13932fe07f8SJohn Marino } 14032fe07f8SJohn Marino } 14132fe07f8SJohn Marino 14232fe07f8SJohn Marino 14332fe07f8SJohn Marino /* c_delafter1(): 14432fe07f8SJohn Marino * Delete the character after the cursor, do not yank 14532fe07f8SJohn Marino */ 14612db70c8Szrj libedit_private void 14732fe07f8SJohn Marino c_delafter1(EditLine *el) 14832fe07f8SJohn Marino { 14912db70c8Szrj wchar_t *cp; 15032fe07f8SJohn Marino 15132fe07f8SJohn Marino for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) 15232fe07f8SJohn Marino *cp = cp[1]; 15332fe07f8SJohn Marino 15432fe07f8SJohn Marino el->el_line.lastchar--; 15532fe07f8SJohn Marino } 15632fe07f8SJohn Marino 15732fe07f8SJohn Marino 15832fe07f8SJohn Marino /* c_delbefore(): 15932fe07f8SJohn Marino * Delete num characters before the cursor 16032fe07f8SJohn Marino */ 16112db70c8Szrj libedit_private void 16232fe07f8SJohn Marino c_delbefore(EditLine *el, int num) 16332fe07f8SJohn Marino { 16432fe07f8SJohn Marino 16532fe07f8SJohn Marino if (el->el_line.cursor - num < el->el_line.buffer) 16632fe07f8SJohn Marino num = (int)(el->el_line.cursor - el->el_line.buffer); 16732fe07f8SJohn Marino 16832fe07f8SJohn Marino if (el->el_map.current != el->el_map.emacs) { 16932fe07f8SJohn Marino cv_undo(el); 17032fe07f8SJohn Marino cv_yank(el, el->el_line.cursor - num, num); 17132fe07f8SJohn Marino } 17232fe07f8SJohn Marino 17332fe07f8SJohn Marino if (num > 0) { 17412db70c8Szrj wchar_t *cp; 17532fe07f8SJohn Marino 17632fe07f8SJohn Marino for (cp = el->el_line.cursor - num; 17732fe07f8SJohn Marino cp <= el->el_line.lastchar; 17832fe07f8SJohn Marino cp++) 17932fe07f8SJohn Marino *cp = cp[num]; 18032fe07f8SJohn Marino 18132fe07f8SJohn Marino el->el_line.lastchar -= num; 18232fe07f8SJohn Marino } 18332fe07f8SJohn Marino } 18432fe07f8SJohn Marino 18532fe07f8SJohn Marino 18632fe07f8SJohn Marino /* c_delbefore1(): 18732fe07f8SJohn Marino * Delete the character before the cursor, do not yank 18832fe07f8SJohn Marino */ 18912db70c8Szrj libedit_private void 19032fe07f8SJohn Marino c_delbefore1(EditLine *el) 19132fe07f8SJohn Marino { 19212db70c8Szrj wchar_t *cp; 19332fe07f8SJohn Marino 19432fe07f8SJohn Marino for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++) 19532fe07f8SJohn Marino *cp = cp[1]; 19632fe07f8SJohn Marino 19732fe07f8SJohn Marino el->el_line.lastchar--; 19832fe07f8SJohn Marino } 19932fe07f8SJohn Marino 20032fe07f8SJohn Marino 20132fe07f8SJohn Marino /* ce__isword(): 20232fe07f8SJohn Marino * Return if p is part of a word according to emacs 20332fe07f8SJohn Marino */ 20412db70c8Szrj libedit_private int 20512db70c8Szrj ce__isword(wint_t p) 20632fe07f8SJohn Marino { 20712db70c8Szrj return iswalnum(p) || wcschr(L"*?_-.[]~=", p) != NULL; 20832fe07f8SJohn Marino } 20932fe07f8SJohn Marino 21032fe07f8SJohn Marino 21132fe07f8SJohn Marino /* cv__isword(): 21232fe07f8SJohn Marino * Return if p is part of a word according to vi 21332fe07f8SJohn Marino */ 21412db70c8Szrj libedit_private int 21512db70c8Szrj cv__isword(wint_t p) 21632fe07f8SJohn Marino { 21712db70c8Szrj if (iswalnum(p) || p == L'_') 21832fe07f8SJohn Marino return 1; 21912db70c8Szrj if (iswgraph(p)) 22032fe07f8SJohn Marino return 2; 22132fe07f8SJohn Marino return 0; 22232fe07f8SJohn Marino } 22332fe07f8SJohn Marino 22432fe07f8SJohn Marino 22532fe07f8SJohn Marino /* cv__isWord(): 22632fe07f8SJohn Marino * Return if p is part of a big word according to vi 22732fe07f8SJohn Marino */ 22812db70c8Szrj libedit_private int 22912db70c8Szrj cv__isWord(wint_t p) 23032fe07f8SJohn Marino { 23112db70c8Szrj return !iswspace(p); 23232fe07f8SJohn Marino } 23332fe07f8SJohn Marino 23432fe07f8SJohn Marino 23532fe07f8SJohn Marino /* c__prev_word(): 23632fe07f8SJohn Marino * Find the previous word 23732fe07f8SJohn Marino */ 23812db70c8Szrj libedit_private wchar_t * 23912db70c8Szrj c__prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t)) 24032fe07f8SJohn Marino { 24132fe07f8SJohn Marino p--; 24232fe07f8SJohn Marino 24332fe07f8SJohn Marino while (n--) { 24432fe07f8SJohn Marino while ((p >= low) && !(*wtest)(*p)) 24532fe07f8SJohn Marino p--; 24632fe07f8SJohn Marino while ((p >= low) && (*wtest)(*p)) 24732fe07f8SJohn Marino p--; 24832fe07f8SJohn Marino } 24932fe07f8SJohn Marino 25032fe07f8SJohn Marino /* cp now points to one character before the word */ 25132fe07f8SJohn Marino p++; 25232fe07f8SJohn Marino if (p < low) 25332fe07f8SJohn Marino p = low; 25432fe07f8SJohn Marino /* cp now points where we want it */ 25532fe07f8SJohn Marino return p; 25632fe07f8SJohn Marino } 25732fe07f8SJohn Marino 25832fe07f8SJohn Marino 25932fe07f8SJohn Marino /* c__next_word(): 26032fe07f8SJohn Marino * Find the next word 26132fe07f8SJohn Marino */ 26212db70c8Szrj libedit_private wchar_t * 26312db70c8Szrj c__next_word(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t)) 26432fe07f8SJohn Marino { 26532fe07f8SJohn Marino while (n--) { 26632fe07f8SJohn Marino while ((p < high) && !(*wtest)(*p)) 26732fe07f8SJohn Marino p++; 26832fe07f8SJohn Marino while ((p < high) && (*wtest)(*p)) 26932fe07f8SJohn Marino p++; 27032fe07f8SJohn Marino } 27132fe07f8SJohn Marino if (p > high) 27232fe07f8SJohn Marino p = high; 27332fe07f8SJohn Marino /* p now points where we want it */ 27432fe07f8SJohn Marino return p; 27532fe07f8SJohn Marino } 27632fe07f8SJohn Marino 27732fe07f8SJohn Marino /* cv_next_word(): 27832fe07f8SJohn Marino * Find the next word vi style 27932fe07f8SJohn Marino */ 28012db70c8Szrj libedit_private wchar_t * 28112db70c8Szrj cv_next_word(EditLine *el, wchar_t *p, wchar_t *high, int n, 28212db70c8Szrj int (*wtest)(wint_t)) 28332fe07f8SJohn Marino { 28432fe07f8SJohn Marino int test; 28532fe07f8SJohn Marino 28632fe07f8SJohn Marino while (n--) { 28732fe07f8SJohn Marino test = (*wtest)(*p); 28832fe07f8SJohn Marino while ((p < high) && (*wtest)(*p) == test) 28932fe07f8SJohn Marino p++; 29032fe07f8SJohn Marino /* 29132fe07f8SJohn Marino * vi historically deletes with cw only the word preserving the 29232fe07f8SJohn Marino * trailing whitespace! This is not what 'w' does.. 29332fe07f8SJohn Marino */ 29432fe07f8SJohn Marino if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT)) 29512db70c8Szrj while ((p < high) && iswspace(*p)) 29632fe07f8SJohn Marino p++; 29732fe07f8SJohn Marino } 29832fe07f8SJohn Marino 29932fe07f8SJohn Marino /* p now points where we want it */ 30032fe07f8SJohn Marino if (p > high) 30132fe07f8SJohn Marino return high; 30232fe07f8SJohn Marino else 30332fe07f8SJohn Marino return p; 30432fe07f8SJohn Marino } 30532fe07f8SJohn Marino 30632fe07f8SJohn Marino 30732fe07f8SJohn Marino /* cv_prev_word(): 30832fe07f8SJohn Marino * Find the previous word vi style 30932fe07f8SJohn Marino */ 31012db70c8Szrj libedit_private wchar_t * 31112db70c8Szrj cv_prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t)) 31232fe07f8SJohn Marino { 31332fe07f8SJohn Marino int test; 31432fe07f8SJohn Marino 31532fe07f8SJohn Marino p--; 31632fe07f8SJohn Marino while (n--) { 31712db70c8Szrj while ((p > low) && iswspace(*p)) 31832fe07f8SJohn Marino p--; 31932fe07f8SJohn Marino test = (*wtest)(*p); 32032fe07f8SJohn Marino while ((p >= low) && (*wtest)(*p) == test) 32132fe07f8SJohn Marino p--; 32232fe07f8SJohn Marino } 32332fe07f8SJohn Marino p++; 32432fe07f8SJohn Marino 32532fe07f8SJohn Marino /* p now points where we want it */ 32632fe07f8SJohn Marino if (p < low) 32732fe07f8SJohn Marino return low; 32832fe07f8SJohn Marino else 32932fe07f8SJohn Marino return p; 33032fe07f8SJohn Marino } 33132fe07f8SJohn Marino 33232fe07f8SJohn Marino 33332fe07f8SJohn Marino /* cv_delfini(): 33432fe07f8SJohn Marino * Finish vi delete action 33532fe07f8SJohn Marino */ 33612db70c8Szrj libedit_private void 33732fe07f8SJohn Marino cv_delfini(EditLine *el) 33832fe07f8SJohn Marino { 33932fe07f8SJohn Marino int size; 34032fe07f8SJohn Marino int action = el->el_chared.c_vcmd.action; 34132fe07f8SJohn Marino 34232fe07f8SJohn Marino if (action & INSERT) 34332fe07f8SJohn Marino el->el_map.current = el->el_map.key; 34432fe07f8SJohn Marino 34532fe07f8SJohn Marino if (el->el_chared.c_vcmd.pos == 0) 34632fe07f8SJohn Marino /* sanity */ 34732fe07f8SJohn Marino return; 34832fe07f8SJohn Marino 34932fe07f8SJohn Marino size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos); 35032fe07f8SJohn Marino if (size == 0) 35132fe07f8SJohn Marino size = 1; 35232fe07f8SJohn Marino el->el_line.cursor = el->el_chared.c_vcmd.pos; 35332fe07f8SJohn Marino if (action & YANK) { 35432fe07f8SJohn Marino if (size > 0) 35532fe07f8SJohn Marino cv_yank(el, el->el_line.cursor, size); 35632fe07f8SJohn Marino else 35732fe07f8SJohn Marino cv_yank(el, el->el_line.cursor + size, -size); 35832fe07f8SJohn Marino } else { 35932fe07f8SJohn Marino if (size > 0) { 36032fe07f8SJohn Marino c_delafter(el, size); 36132fe07f8SJohn Marino re_refresh_cursor(el); 36232fe07f8SJohn Marino } else { 36332fe07f8SJohn Marino c_delbefore(el, -size); 36432fe07f8SJohn Marino el->el_line.cursor += size; 36532fe07f8SJohn Marino } 36632fe07f8SJohn Marino } 36732fe07f8SJohn Marino el->el_chared.c_vcmd.action = NOP; 36832fe07f8SJohn Marino } 36932fe07f8SJohn Marino 37032fe07f8SJohn Marino 37132fe07f8SJohn Marino /* cv__endword(): 37232fe07f8SJohn Marino * Go to the end of this word according to vi 37332fe07f8SJohn Marino */ 37412db70c8Szrj libedit_private wchar_t * 37512db70c8Szrj cv__endword(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t)) 37632fe07f8SJohn Marino { 37732fe07f8SJohn Marino int test; 37832fe07f8SJohn Marino 37932fe07f8SJohn Marino p++; 38032fe07f8SJohn Marino 38132fe07f8SJohn Marino while (n--) { 38212db70c8Szrj while ((p < high) && iswspace(*p)) 38332fe07f8SJohn Marino p++; 38432fe07f8SJohn Marino 38532fe07f8SJohn Marino test = (*wtest)(*p); 38632fe07f8SJohn Marino while ((p < high) && (*wtest)(*p) == test) 38732fe07f8SJohn Marino p++; 38832fe07f8SJohn Marino } 38932fe07f8SJohn Marino p--; 39032fe07f8SJohn Marino return p; 39132fe07f8SJohn Marino } 39232fe07f8SJohn Marino 39332fe07f8SJohn Marino /* ch_init(): 39432fe07f8SJohn Marino * Initialize the character editor 39532fe07f8SJohn Marino */ 39612db70c8Szrj libedit_private int 39732fe07f8SJohn Marino ch_init(EditLine *el) 39832fe07f8SJohn Marino { 39932fe07f8SJohn Marino el->el_line.buffer = el_malloc(EL_BUFSIZ * 40032fe07f8SJohn Marino sizeof(*el->el_line.buffer)); 40132fe07f8SJohn Marino if (el->el_line.buffer == NULL) 40232fe07f8SJohn Marino return -1; 40332fe07f8SJohn Marino 40432fe07f8SJohn Marino (void) memset(el->el_line.buffer, 0, EL_BUFSIZ * 40532fe07f8SJohn Marino sizeof(*el->el_line.buffer)); 40632fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer; 40732fe07f8SJohn Marino el->el_line.lastchar = el->el_line.buffer; 40832fe07f8SJohn Marino el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE]; 40932fe07f8SJohn Marino 41032fe07f8SJohn Marino el->el_chared.c_undo.buf = el_malloc(EL_BUFSIZ * 41132fe07f8SJohn Marino sizeof(*el->el_chared.c_undo.buf)); 41232fe07f8SJohn Marino if (el->el_chared.c_undo.buf == NULL) 41332fe07f8SJohn Marino return -1; 41432fe07f8SJohn Marino (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ * 41532fe07f8SJohn Marino sizeof(*el->el_chared.c_undo.buf)); 41632fe07f8SJohn Marino el->el_chared.c_undo.len = -1; 41732fe07f8SJohn Marino el->el_chared.c_undo.cursor = 0; 41832fe07f8SJohn Marino el->el_chared.c_redo.buf = el_malloc(EL_BUFSIZ * 41932fe07f8SJohn Marino sizeof(*el->el_chared.c_redo.buf)); 42032fe07f8SJohn Marino if (el->el_chared.c_redo.buf == NULL) 42132fe07f8SJohn Marino return -1; 42232fe07f8SJohn Marino el->el_chared.c_redo.pos = el->el_chared.c_redo.buf; 42332fe07f8SJohn Marino el->el_chared.c_redo.lim = el->el_chared.c_redo.buf + EL_BUFSIZ; 42432fe07f8SJohn Marino el->el_chared.c_redo.cmd = ED_UNASSIGNED; 42532fe07f8SJohn Marino 42632fe07f8SJohn Marino el->el_chared.c_vcmd.action = NOP; 42732fe07f8SJohn Marino el->el_chared.c_vcmd.pos = el->el_line.buffer; 42832fe07f8SJohn Marino 42932fe07f8SJohn Marino el->el_chared.c_kill.buf = el_malloc(EL_BUFSIZ * 43032fe07f8SJohn Marino sizeof(*el->el_chared.c_kill.buf)); 43132fe07f8SJohn Marino if (el->el_chared.c_kill.buf == NULL) 43232fe07f8SJohn Marino return -1; 43332fe07f8SJohn Marino (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ * 43432fe07f8SJohn Marino sizeof(*el->el_chared.c_kill.buf)); 43532fe07f8SJohn Marino el->el_chared.c_kill.mark = el->el_line.buffer; 43632fe07f8SJohn Marino el->el_chared.c_kill.last = el->el_chared.c_kill.buf; 43732fe07f8SJohn Marino el->el_chared.c_resizefun = NULL; 43832fe07f8SJohn Marino el->el_chared.c_resizearg = NULL; 43984b940c1SJohn Marino el->el_chared.c_aliasfun = NULL; 44084b940c1SJohn Marino el->el_chared.c_aliasarg = NULL; 44132fe07f8SJohn Marino 44232fe07f8SJohn Marino el->el_map.current = el->el_map.key; 44332fe07f8SJohn Marino 44432fe07f8SJohn Marino el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ 44532fe07f8SJohn Marino el->el_state.doingarg = 0; 44632fe07f8SJohn Marino el->el_state.metanext = 0; 44732fe07f8SJohn Marino el->el_state.argument = 1; 44832fe07f8SJohn Marino el->el_state.lastcmd = ED_UNASSIGNED; 44932fe07f8SJohn Marino 45032fe07f8SJohn Marino return 0; 45132fe07f8SJohn Marino } 45232fe07f8SJohn Marino 45332fe07f8SJohn Marino /* ch_reset(): 45432fe07f8SJohn Marino * Reset the character editor 45532fe07f8SJohn Marino */ 45612db70c8Szrj libedit_private void 45712db70c8Szrj ch_reset(EditLine *el) 45832fe07f8SJohn Marino { 45932fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer; 46032fe07f8SJohn Marino el->el_line.lastchar = el->el_line.buffer; 46132fe07f8SJohn Marino 46232fe07f8SJohn Marino el->el_chared.c_undo.len = -1; 46332fe07f8SJohn Marino el->el_chared.c_undo.cursor = 0; 46432fe07f8SJohn Marino 46532fe07f8SJohn Marino el->el_chared.c_vcmd.action = NOP; 46632fe07f8SJohn Marino el->el_chared.c_vcmd.pos = el->el_line.buffer; 46732fe07f8SJohn Marino 46832fe07f8SJohn Marino el->el_chared.c_kill.mark = el->el_line.buffer; 46932fe07f8SJohn Marino 47032fe07f8SJohn Marino el->el_map.current = el->el_map.key; 47132fe07f8SJohn Marino 47232fe07f8SJohn Marino el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ 47332fe07f8SJohn Marino el->el_state.doingarg = 0; 47432fe07f8SJohn Marino el->el_state.metanext = 0; 47532fe07f8SJohn Marino el->el_state.argument = 1; 47632fe07f8SJohn Marino el->el_state.lastcmd = ED_UNASSIGNED; 47732fe07f8SJohn Marino 47832fe07f8SJohn Marino el->el_history.eventno = 0; 47932fe07f8SJohn Marino } 48032fe07f8SJohn Marino 48132fe07f8SJohn Marino /* ch_enlargebufs(): 48232fe07f8SJohn Marino * Enlarge line buffer to be able to hold twice as much characters. 48332fe07f8SJohn Marino * Returns 1 if successful, 0 if not. 48432fe07f8SJohn Marino */ 48512db70c8Szrj libedit_private int 48632fe07f8SJohn Marino ch_enlargebufs(EditLine *el, size_t addlen) 48732fe07f8SJohn Marino { 48832fe07f8SJohn Marino size_t sz, newsz; 48912db70c8Szrj wchar_t *newbuffer, *oldbuf, *oldkbuf; 49032fe07f8SJohn Marino 49132fe07f8SJohn Marino sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE); 49232fe07f8SJohn Marino newsz = sz * 2; 49332fe07f8SJohn Marino /* 49432fe07f8SJohn Marino * If newly required length is longer than current buffer, we need 49532fe07f8SJohn Marino * to make the buffer big enough to hold both old and new stuff. 49632fe07f8SJohn Marino */ 49732fe07f8SJohn Marino if (addlen > sz) { 49832fe07f8SJohn Marino while(newsz - sz < addlen) 49932fe07f8SJohn Marino newsz *= 2; 50032fe07f8SJohn Marino } 50132fe07f8SJohn Marino 50232fe07f8SJohn Marino /* 50332fe07f8SJohn Marino * Reallocate line buffer. 50432fe07f8SJohn Marino */ 50532fe07f8SJohn Marino newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer)); 50632fe07f8SJohn Marino if (!newbuffer) 50732fe07f8SJohn Marino return 0; 50832fe07f8SJohn Marino 50932fe07f8SJohn Marino /* zero the newly added memory, leave old data in */ 51032fe07f8SJohn Marino (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 51132fe07f8SJohn Marino 51232fe07f8SJohn Marino oldbuf = el->el_line.buffer; 51332fe07f8SJohn Marino 51432fe07f8SJohn Marino el->el_line.buffer = newbuffer; 51532fe07f8SJohn Marino el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf); 51632fe07f8SJohn Marino el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf); 51732fe07f8SJohn Marino /* don't set new size until all buffers are enlarged */ 51832fe07f8SJohn Marino el->el_line.limit = &newbuffer[sz - EL_LEAVE]; 51932fe07f8SJohn Marino 52032fe07f8SJohn Marino /* 52132fe07f8SJohn Marino * Reallocate kill buffer. 52232fe07f8SJohn Marino */ 52332fe07f8SJohn Marino newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz * 52432fe07f8SJohn Marino sizeof(*newbuffer)); 52532fe07f8SJohn Marino if (!newbuffer) 52632fe07f8SJohn Marino return 0; 52732fe07f8SJohn Marino 52832fe07f8SJohn Marino /* zero the newly added memory, leave old data in */ 52932fe07f8SJohn Marino (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 53032fe07f8SJohn Marino 53132fe07f8SJohn Marino oldkbuf = el->el_chared.c_kill.buf; 53232fe07f8SJohn Marino 53332fe07f8SJohn Marino el->el_chared.c_kill.buf = newbuffer; 53432fe07f8SJohn Marino el->el_chared.c_kill.last = newbuffer + 53532fe07f8SJohn Marino (el->el_chared.c_kill.last - oldkbuf); 53632fe07f8SJohn Marino el->el_chared.c_kill.mark = el->el_line.buffer + 53732fe07f8SJohn Marino (el->el_chared.c_kill.mark - oldbuf); 53832fe07f8SJohn Marino 53932fe07f8SJohn Marino /* 54032fe07f8SJohn Marino * Reallocate undo buffer. 54132fe07f8SJohn Marino */ 54232fe07f8SJohn Marino newbuffer = el_realloc(el->el_chared.c_undo.buf, 54332fe07f8SJohn Marino newsz * sizeof(*newbuffer)); 54432fe07f8SJohn Marino if (!newbuffer) 54532fe07f8SJohn Marino return 0; 54632fe07f8SJohn Marino 54732fe07f8SJohn Marino /* zero the newly added memory, leave old data in */ 54832fe07f8SJohn Marino (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 54932fe07f8SJohn Marino el->el_chared.c_undo.buf = newbuffer; 55032fe07f8SJohn Marino 55132fe07f8SJohn Marino newbuffer = el_realloc(el->el_chared.c_redo.buf, 55232fe07f8SJohn Marino newsz * sizeof(*newbuffer)); 55332fe07f8SJohn Marino if (!newbuffer) 55432fe07f8SJohn Marino return 0; 55532fe07f8SJohn Marino el->el_chared.c_redo.pos = newbuffer + 55632fe07f8SJohn Marino (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf); 55732fe07f8SJohn Marino el->el_chared.c_redo.lim = newbuffer + 55832fe07f8SJohn Marino (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf); 55932fe07f8SJohn Marino el->el_chared.c_redo.buf = newbuffer; 56032fe07f8SJohn Marino 56132fe07f8SJohn Marino if (!hist_enlargebuf(el, sz, newsz)) 56232fe07f8SJohn Marino return 0; 56332fe07f8SJohn Marino 56432fe07f8SJohn Marino /* Safe to set enlarged buffer size */ 56532fe07f8SJohn Marino el->el_line.limit = &el->el_line.buffer[newsz - EL_LEAVE]; 56632fe07f8SJohn Marino if (el->el_chared.c_resizefun) 56732fe07f8SJohn Marino (*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg); 56832fe07f8SJohn Marino return 1; 56932fe07f8SJohn Marino } 57032fe07f8SJohn Marino 57132fe07f8SJohn Marino /* ch_end(): 57232fe07f8SJohn Marino * Free the data structures used by the editor 57332fe07f8SJohn Marino */ 57412db70c8Szrj libedit_private void 57532fe07f8SJohn Marino ch_end(EditLine *el) 57632fe07f8SJohn Marino { 57732fe07f8SJohn Marino el_free(el->el_line.buffer); 57832fe07f8SJohn Marino el->el_line.buffer = NULL; 57932fe07f8SJohn Marino el->el_line.limit = NULL; 58032fe07f8SJohn Marino el_free(el->el_chared.c_undo.buf); 58132fe07f8SJohn Marino el->el_chared.c_undo.buf = NULL; 58232fe07f8SJohn Marino el_free(el->el_chared.c_redo.buf); 58332fe07f8SJohn Marino el->el_chared.c_redo.buf = NULL; 58432fe07f8SJohn Marino el->el_chared.c_redo.pos = NULL; 58532fe07f8SJohn Marino el->el_chared.c_redo.lim = NULL; 58632fe07f8SJohn Marino el->el_chared.c_redo.cmd = ED_UNASSIGNED; 58732fe07f8SJohn Marino el_free(el->el_chared.c_kill.buf); 58832fe07f8SJohn Marino el->el_chared.c_kill.buf = NULL; 58912db70c8Szrj ch_reset(el); 59032fe07f8SJohn Marino } 59132fe07f8SJohn Marino 59232fe07f8SJohn Marino 59332fe07f8SJohn Marino /* el_insertstr(): 594*ae19eda8Szrj * Insert string at cursor 59532fe07f8SJohn Marino */ 59612db70c8Szrj int 59712db70c8Szrj el_winsertstr(EditLine *el, const wchar_t *s) 59832fe07f8SJohn Marino { 59932fe07f8SJohn Marino size_t len; 60032fe07f8SJohn Marino 60112db70c8Szrj if (s == NULL || (len = wcslen(s)) == 0) 60232fe07f8SJohn Marino return -1; 60332fe07f8SJohn Marino if (el->el_line.lastchar + len >= el->el_line.limit) { 60432fe07f8SJohn Marino if (!ch_enlargebufs(el, len)) 60532fe07f8SJohn Marino return -1; 60632fe07f8SJohn Marino } 60732fe07f8SJohn Marino 60832fe07f8SJohn Marino c_insert(el, (int)len); 60932fe07f8SJohn Marino while (*s) 61032fe07f8SJohn Marino *el->el_line.cursor++ = *s++; 61132fe07f8SJohn Marino return 0; 61232fe07f8SJohn Marino } 61332fe07f8SJohn Marino 61432fe07f8SJohn Marino 61532fe07f8SJohn Marino /* el_deletestr(): 61632fe07f8SJohn Marino * Delete num characters before the cursor 61732fe07f8SJohn Marino */ 61812db70c8Szrj void 61932fe07f8SJohn Marino el_deletestr(EditLine *el, int n) 62032fe07f8SJohn Marino { 62132fe07f8SJohn Marino if (n <= 0) 62232fe07f8SJohn Marino return; 62332fe07f8SJohn Marino 62432fe07f8SJohn Marino if (el->el_line.cursor < &el->el_line.buffer[n]) 62532fe07f8SJohn Marino return; 62632fe07f8SJohn Marino 62732fe07f8SJohn Marino c_delbefore(el, n); /* delete before dot */ 62832fe07f8SJohn Marino el->el_line.cursor -= n; 62932fe07f8SJohn Marino if (el->el_line.cursor < el->el_line.buffer) 63032fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer; 63132fe07f8SJohn Marino } 63232fe07f8SJohn Marino 63384b940c1SJohn Marino /* el_cursor(): 63484b940c1SJohn Marino * Move the cursor to the left or the right of the current position 63584b940c1SJohn Marino */ 63612db70c8Szrj int 63784b940c1SJohn Marino el_cursor(EditLine *el, int n) 63884b940c1SJohn Marino { 63984b940c1SJohn Marino if (n == 0) 64084b940c1SJohn Marino goto out; 64184b940c1SJohn Marino 64284b940c1SJohn Marino el->el_line.cursor += n; 64384b940c1SJohn Marino 64484b940c1SJohn Marino if (el->el_line.cursor < el->el_line.buffer) 64584b940c1SJohn Marino el->el_line.cursor = el->el_line.buffer; 64684b940c1SJohn Marino if (el->el_line.cursor > el->el_line.lastchar) 64784b940c1SJohn Marino el->el_line.cursor = el->el_line.lastchar; 64884b940c1SJohn Marino out: 64984b940c1SJohn Marino return (int)(el->el_line.cursor - el->el_line.buffer); 65084b940c1SJohn Marino } 65184b940c1SJohn Marino 65232fe07f8SJohn Marino /* c_gets(): 65332fe07f8SJohn Marino * Get a string 65432fe07f8SJohn Marino */ 65512db70c8Szrj libedit_private int 65612db70c8Szrj c_gets(EditLine *el, wchar_t *buf, const wchar_t *prompt) 65732fe07f8SJohn Marino { 65832fe07f8SJohn Marino ssize_t len; 65912db70c8Szrj wchar_t *cp = el->el_line.buffer, ch; 66032fe07f8SJohn Marino 66132fe07f8SJohn Marino if (prompt) { 66212db70c8Szrj len = (ssize_t)wcslen(prompt); 66332fe07f8SJohn Marino (void)memcpy(cp, prompt, (size_t)len * sizeof(*cp)); 66432fe07f8SJohn Marino cp += len; 66532fe07f8SJohn Marino } 66632fe07f8SJohn Marino len = 0; 66732fe07f8SJohn Marino 66832fe07f8SJohn Marino for (;;) { 66932fe07f8SJohn Marino el->el_line.cursor = cp; 67032fe07f8SJohn Marino *cp = ' '; 67132fe07f8SJohn Marino el->el_line.lastchar = cp + 1; 67232fe07f8SJohn Marino re_refresh(el); 67332fe07f8SJohn Marino 67412db70c8Szrj if (el_wgetc(el, &ch) != 1) { 67532fe07f8SJohn Marino ed_end_of_file(el, 0); 67632fe07f8SJohn Marino len = -1; 67732fe07f8SJohn Marino break; 67832fe07f8SJohn Marino } 67932fe07f8SJohn Marino 68032fe07f8SJohn Marino switch (ch) { 68132fe07f8SJohn Marino 68212db70c8Szrj case L'\b': /* Delete and backspace */ 68332fe07f8SJohn Marino case 0177: 68432fe07f8SJohn Marino if (len == 0) { 68532fe07f8SJohn Marino len = -1; 68632fe07f8SJohn Marino break; 68732fe07f8SJohn Marino } 68812db70c8Szrj len--; 68932fe07f8SJohn Marino cp--; 69032fe07f8SJohn Marino continue; 69132fe07f8SJohn Marino 69232fe07f8SJohn Marino case 0033: /* ESC */ 69312db70c8Szrj case L'\r': /* Newline */ 69412db70c8Szrj case L'\n': 69532fe07f8SJohn Marino buf[len] = ch; 69632fe07f8SJohn Marino break; 69732fe07f8SJohn Marino 69832fe07f8SJohn Marino default: 69932fe07f8SJohn Marino if (len >= (ssize_t)(EL_BUFSIZ - 16)) 70032fe07f8SJohn Marino terminal_beep(el); 70132fe07f8SJohn Marino else { 70232fe07f8SJohn Marino buf[len++] = ch; 70332fe07f8SJohn Marino *cp++ = ch; 70432fe07f8SJohn Marino } 70532fe07f8SJohn Marino continue; 70632fe07f8SJohn Marino } 70732fe07f8SJohn Marino break; 70832fe07f8SJohn Marino } 70932fe07f8SJohn Marino 71032fe07f8SJohn Marino el->el_line.buffer[0] = '\0'; 71132fe07f8SJohn Marino el->el_line.lastchar = el->el_line.buffer; 71232fe07f8SJohn Marino el->el_line.cursor = el->el_line.buffer; 71332fe07f8SJohn Marino return (int)len; 71432fe07f8SJohn Marino } 71532fe07f8SJohn Marino 71632fe07f8SJohn Marino 71732fe07f8SJohn Marino /* c_hpos(): 71832fe07f8SJohn Marino * Return the current horizontal position of the cursor 71932fe07f8SJohn Marino */ 72012db70c8Szrj libedit_private int 72132fe07f8SJohn Marino c_hpos(EditLine *el) 72232fe07f8SJohn Marino { 72312db70c8Szrj wchar_t *ptr; 72432fe07f8SJohn Marino 72532fe07f8SJohn Marino /* 72632fe07f8SJohn Marino * Find how many characters till the beginning of this line. 72732fe07f8SJohn Marino */ 72832fe07f8SJohn Marino if (el->el_line.cursor == el->el_line.buffer) 72932fe07f8SJohn Marino return 0; 73032fe07f8SJohn Marino else { 73132fe07f8SJohn Marino for (ptr = el->el_line.cursor - 1; 73232fe07f8SJohn Marino ptr >= el->el_line.buffer && *ptr != '\n'; 73332fe07f8SJohn Marino ptr--) 73432fe07f8SJohn Marino continue; 73532fe07f8SJohn Marino return (int)(el->el_line.cursor - ptr - 1); 73632fe07f8SJohn Marino } 73732fe07f8SJohn Marino } 73832fe07f8SJohn Marino 73912db70c8Szrj libedit_private int 74032fe07f8SJohn Marino ch_resizefun(EditLine *el, el_zfunc_t f, void *a) 74132fe07f8SJohn Marino { 74232fe07f8SJohn Marino el->el_chared.c_resizefun = f; 74332fe07f8SJohn Marino el->el_chared.c_resizearg = a; 74432fe07f8SJohn Marino return 0; 74532fe07f8SJohn Marino } 74684b940c1SJohn Marino 74712db70c8Szrj libedit_private int 74884b940c1SJohn Marino ch_aliasfun(EditLine *el, el_afunc_t f, void *a) 74984b940c1SJohn Marino { 75084b940c1SJohn Marino el->el_chared.c_aliasfun = f; 75184b940c1SJohn Marino el->el_chared.c_aliasarg = a; 75284b940c1SJohn Marino return 0; 75384b940c1SJohn Marino } 754