1*baff8195SBaptiste Daroussin /* $NetBSD: chared.c,v 1.63 2022/10/30 19:11:31 christos Exp $ */ 2d0ef721eSBaptiste Daroussin 3d0ef721eSBaptiste Daroussin /*- 4d0ef721eSBaptiste Daroussin * Copyright (c) 1992, 1993 5d0ef721eSBaptiste Daroussin * The Regents of the University of California. All rights reserved. 6d0ef721eSBaptiste Daroussin * 7d0ef721eSBaptiste Daroussin * This code is derived from software contributed to Berkeley by 8d0ef721eSBaptiste Daroussin * Christos Zoulas of Cornell University. 9d0ef721eSBaptiste Daroussin * 10d0ef721eSBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 11d0ef721eSBaptiste Daroussin * modification, are permitted provided that the following conditions 12d0ef721eSBaptiste Daroussin * are met: 13d0ef721eSBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 14d0ef721eSBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 15d0ef721eSBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 16d0ef721eSBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 17d0ef721eSBaptiste Daroussin * documentation and/or other materials provided with the distribution. 18d0ef721eSBaptiste Daroussin * 3. Neither the name of the University nor the names of its contributors 19d0ef721eSBaptiste Daroussin * may be used to endorse or promote products derived from this software 20d0ef721eSBaptiste Daroussin * without specific prior written permission. 21d0ef721eSBaptiste Daroussin * 22d0ef721eSBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23d0ef721eSBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24d0ef721eSBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25d0ef721eSBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26d0ef721eSBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27d0ef721eSBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28d0ef721eSBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29d0ef721eSBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30d0ef721eSBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31d0ef721eSBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32d0ef721eSBaptiste Daroussin * SUCH DAMAGE. 33d0ef721eSBaptiste Daroussin */ 34d0ef721eSBaptiste Daroussin 35d0ef721eSBaptiste Daroussin #include "config.h" 36d0ef721eSBaptiste Daroussin #if !defined(lint) && !defined(SCCSID) 37d0ef721eSBaptiste Daroussin #if 0 38d0ef721eSBaptiste Daroussin static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93"; 39d0ef721eSBaptiste Daroussin #else 40*baff8195SBaptiste Daroussin __RCSID("$NetBSD: chared.c,v 1.63 2022/10/30 19:11:31 christos Exp $"); 41d0ef721eSBaptiste Daroussin #endif 42d0ef721eSBaptiste Daroussin #endif /* not lint && not SCCSID */ 43d0ef721eSBaptiste Daroussin 44d0ef721eSBaptiste Daroussin /* 45d0ef721eSBaptiste Daroussin * chared.c: Character editor utilities 46d0ef721eSBaptiste Daroussin */ 47d0ef721eSBaptiste Daroussin #include <ctype.h> 48d0ef721eSBaptiste Daroussin #include <stdlib.h> 49d0ef721eSBaptiste Daroussin #include <string.h> 50d0ef721eSBaptiste Daroussin 51d0ef721eSBaptiste Daroussin #include "el.h" 52d0ef721eSBaptiste Daroussin #include "common.h" 53d0ef721eSBaptiste Daroussin #include "fcns.h" 54d0ef721eSBaptiste Daroussin 55d0ef721eSBaptiste Daroussin /* value to leave unused in line buffer */ 56d0ef721eSBaptiste Daroussin #define EL_LEAVE 2 57d0ef721eSBaptiste Daroussin 58d0ef721eSBaptiste Daroussin /* cv_undo(): 59d0ef721eSBaptiste Daroussin * Handle state for the vi undo command 60d0ef721eSBaptiste Daroussin */ 61d0ef721eSBaptiste Daroussin libedit_private void 62d0ef721eSBaptiste Daroussin cv_undo(EditLine *el) 63d0ef721eSBaptiste Daroussin { 64d0ef721eSBaptiste Daroussin c_undo_t *vu = &el->el_chared.c_undo; 65d0ef721eSBaptiste Daroussin c_redo_t *r = &el->el_chared.c_redo; 66d0ef721eSBaptiste Daroussin size_t size; 67d0ef721eSBaptiste Daroussin 68d0ef721eSBaptiste Daroussin /* Save entire line for undo */ 69d0ef721eSBaptiste Daroussin size = (size_t)(el->el_line.lastchar - el->el_line.buffer); 70d0ef721eSBaptiste Daroussin vu->len = (ssize_t)size; 71d0ef721eSBaptiste Daroussin vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer); 72d0ef721eSBaptiste Daroussin (void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf)); 73d0ef721eSBaptiste Daroussin 74d0ef721eSBaptiste Daroussin /* save command info for redo */ 75d0ef721eSBaptiste Daroussin r->count = el->el_state.doingarg ? el->el_state.argument : 0; 76d0ef721eSBaptiste Daroussin r->action = el->el_chared.c_vcmd.action; 77d0ef721eSBaptiste Daroussin r->pos = r->buf; 78d0ef721eSBaptiste Daroussin r->cmd = el->el_state.thiscmd; 79d0ef721eSBaptiste Daroussin r->ch = el->el_state.thisch; 80d0ef721eSBaptiste Daroussin } 81d0ef721eSBaptiste Daroussin 82d0ef721eSBaptiste Daroussin /* cv_yank(): 83d0ef721eSBaptiste Daroussin * Save yank/delete data for paste 84d0ef721eSBaptiste Daroussin */ 85d0ef721eSBaptiste Daroussin libedit_private void 86d0ef721eSBaptiste Daroussin cv_yank(EditLine *el, const wchar_t *ptr, int size) 87d0ef721eSBaptiste Daroussin { 88d0ef721eSBaptiste Daroussin c_kill_t *k = &el->el_chared.c_kill; 89d0ef721eSBaptiste Daroussin 90d0ef721eSBaptiste Daroussin (void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf)); 91d0ef721eSBaptiste Daroussin k->last = k->buf + size; 92d0ef721eSBaptiste Daroussin } 93d0ef721eSBaptiste Daroussin 94d0ef721eSBaptiste Daroussin 95d0ef721eSBaptiste Daroussin /* c_insert(): 96d0ef721eSBaptiste Daroussin * Insert num characters 97d0ef721eSBaptiste Daroussin */ 98d0ef721eSBaptiste Daroussin libedit_private void 99d0ef721eSBaptiste Daroussin c_insert(EditLine *el, int num) 100d0ef721eSBaptiste Daroussin { 101d0ef721eSBaptiste Daroussin wchar_t *cp; 102d0ef721eSBaptiste Daroussin 103d0ef721eSBaptiste Daroussin if (el->el_line.lastchar + num >= el->el_line.limit) { 104d0ef721eSBaptiste Daroussin if (!ch_enlargebufs(el, (size_t)num)) 105d0ef721eSBaptiste Daroussin return; /* can't go past end of buffer */ 106d0ef721eSBaptiste Daroussin } 107d0ef721eSBaptiste Daroussin 108d0ef721eSBaptiste Daroussin if (el->el_line.cursor < el->el_line.lastchar) { 109d0ef721eSBaptiste Daroussin /* if I must move chars */ 110d0ef721eSBaptiste Daroussin for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--) 111d0ef721eSBaptiste Daroussin cp[num] = *cp; 112d0ef721eSBaptiste Daroussin } 113d0ef721eSBaptiste Daroussin el->el_line.lastchar += num; 114d0ef721eSBaptiste Daroussin } 115d0ef721eSBaptiste Daroussin 116d0ef721eSBaptiste Daroussin 117d0ef721eSBaptiste Daroussin /* c_delafter(): 118d0ef721eSBaptiste Daroussin * Delete num characters after the cursor 119d0ef721eSBaptiste Daroussin */ 120d0ef721eSBaptiste Daroussin libedit_private void 121d0ef721eSBaptiste Daroussin c_delafter(EditLine *el, int num) 122d0ef721eSBaptiste Daroussin { 123d0ef721eSBaptiste Daroussin 124d0ef721eSBaptiste Daroussin if (el->el_line.cursor + num > el->el_line.lastchar) 125d0ef721eSBaptiste Daroussin num = (int)(el->el_line.lastchar - el->el_line.cursor); 126d0ef721eSBaptiste Daroussin 127d0ef721eSBaptiste Daroussin if (el->el_map.current != el->el_map.emacs) { 128d0ef721eSBaptiste Daroussin cv_undo(el); 129d0ef721eSBaptiste Daroussin cv_yank(el, el->el_line.cursor, num); 130d0ef721eSBaptiste Daroussin } 131d0ef721eSBaptiste Daroussin 132d0ef721eSBaptiste Daroussin if (num > 0) { 133d0ef721eSBaptiste Daroussin wchar_t *cp; 134d0ef721eSBaptiste Daroussin 135d0ef721eSBaptiste Daroussin for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) 136d0ef721eSBaptiste Daroussin *cp = cp[num]; 137d0ef721eSBaptiste Daroussin 138d0ef721eSBaptiste Daroussin el->el_line.lastchar -= num; 139d0ef721eSBaptiste Daroussin } 140d0ef721eSBaptiste Daroussin } 141d0ef721eSBaptiste Daroussin 142d0ef721eSBaptiste Daroussin 143d0ef721eSBaptiste Daroussin /* c_delafter1(): 144d0ef721eSBaptiste Daroussin * Delete the character after the cursor, do not yank 145d0ef721eSBaptiste Daroussin */ 146d0ef721eSBaptiste Daroussin libedit_private void 147d0ef721eSBaptiste Daroussin c_delafter1(EditLine *el) 148d0ef721eSBaptiste Daroussin { 149d0ef721eSBaptiste Daroussin wchar_t *cp; 150d0ef721eSBaptiste Daroussin 151d0ef721eSBaptiste Daroussin for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) 152d0ef721eSBaptiste Daroussin *cp = cp[1]; 153d0ef721eSBaptiste Daroussin 154d0ef721eSBaptiste Daroussin el->el_line.lastchar--; 155d0ef721eSBaptiste Daroussin } 156d0ef721eSBaptiste Daroussin 157d0ef721eSBaptiste Daroussin 158d0ef721eSBaptiste Daroussin /* c_delbefore(): 159d0ef721eSBaptiste Daroussin * Delete num characters before the cursor 160d0ef721eSBaptiste Daroussin */ 161d0ef721eSBaptiste Daroussin libedit_private void 162d0ef721eSBaptiste Daroussin c_delbefore(EditLine *el, int num) 163d0ef721eSBaptiste Daroussin { 164d0ef721eSBaptiste Daroussin 165d0ef721eSBaptiste Daroussin if (el->el_line.cursor - num < el->el_line.buffer) 166d0ef721eSBaptiste Daroussin num = (int)(el->el_line.cursor - el->el_line.buffer); 167d0ef721eSBaptiste Daroussin 168d0ef721eSBaptiste Daroussin if (el->el_map.current != el->el_map.emacs) { 169d0ef721eSBaptiste Daroussin cv_undo(el); 170d0ef721eSBaptiste Daroussin cv_yank(el, el->el_line.cursor - num, num); 171d0ef721eSBaptiste Daroussin } 172d0ef721eSBaptiste Daroussin 173d0ef721eSBaptiste Daroussin if (num > 0) { 174d0ef721eSBaptiste Daroussin wchar_t *cp; 175d0ef721eSBaptiste Daroussin 176d0ef721eSBaptiste Daroussin for (cp = el->el_line.cursor - num; 177d0ef721eSBaptiste Daroussin &cp[num] <= el->el_line.lastchar; 178d0ef721eSBaptiste Daroussin cp++) 179d0ef721eSBaptiste Daroussin *cp = cp[num]; 180d0ef721eSBaptiste Daroussin 181d0ef721eSBaptiste Daroussin el->el_line.lastchar -= num; 182d0ef721eSBaptiste Daroussin } 183d0ef721eSBaptiste Daroussin } 184d0ef721eSBaptiste Daroussin 185d0ef721eSBaptiste Daroussin 186d0ef721eSBaptiste Daroussin /* c_delbefore1(): 187d0ef721eSBaptiste Daroussin * Delete the character before the cursor, do not yank 188d0ef721eSBaptiste Daroussin */ 189d0ef721eSBaptiste Daroussin libedit_private void 190d0ef721eSBaptiste Daroussin c_delbefore1(EditLine *el) 191d0ef721eSBaptiste Daroussin { 192d0ef721eSBaptiste Daroussin wchar_t *cp; 193d0ef721eSBaptiste Daroussin 194d0ef721eSBaptiste Daroussin for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++) 195d0ef721eSBaptiste Daroussin *cp = cp[1]; 196d0ef721eSBaptiste Daroussin 197d0ef721eSBaptiste Daroussin el->el_line.lastchar--; 198d0ef721eSBaptiste Daroussin } 199d0ef721eSBaptiste Daroussin 200d0ef721eSBaptiste Daroussin 201d0ef721eSBaptiste Daroussin /* ce__isword(): 202d0ef721eSBaptiste Daroussin * Return if p is part of a word according to emacs 203d0ef721eSBaptiste Daroussin */ 204d0ef721eSBaptiste Daroussin libedit_private int 205d0ef721eSBaptiste Daroussin ce__isword(wint_t p) 206d0ef721eSBaptiste Daroussin { 207d0ef721eSBaptiste Daroussin return iswalnum(p) || wcschr(L"*?_-.[]~=", p) != NULL; 208d0ef721eSBaptiste Daroussin } 209d0ef721eSBaptiste Daroussin 210d0ef721eSBaptiste Daroussin 211d0ef721eSBaptiste Daroussin /* cv__isword(): 212d0ef721eSBaptiste Daroussin * Return if p is part of a word according to vi 213d0ef721eSBaptiste Daroussin */ 214d0ef721eSBaptiste Daroussin libedit_private int 215d0ef721eSBaptiste Daroussin cv__isword(wint_t p) 216d0ef721eSBaptiste Daroussin { 217d0ef721eSBaptiste Daroussin if (iswalnum(p) || p == L'_') 218d0ef721eSBaptiste Daroussin return 1; 219d0ef721eSBaptiste Daroussin if (iswgraph(p)) 220d0ef721eSBaptiste Daroussin return 2; 221d0ef721eSBaptiste Daroussin return 0; 222d0ef721eSBaptiste Daroussin } 223d0ef721eSBaptiste Daroussin 224d0ef721eSBaptiste Daroussin 225d0ef721eSBaptiste Daroussin /* cv__isWord(): 226d0ef721eSBaptiste Daroussin * Return if p is part of a big word according to vi 227d0ef721eSBaptiste Daroussin */ 228d0ef721eSBaptiste Daroussin libedit_private int 229d0ef721eSBaptiste Daroussin cv__isWord(wint_t p) 230d0ef721eSBaptiste Daroussin { 231d0ef721eSBaptiste Daroussin return !iswspace(p); 232d0ef721eSBaptiste Daroussin } 233d0ef721eSBaptiste Daroussin 234d0ef721eSBaptiste Daroussin 235d0ef721eSBaptiste Daroussin /* c__prev_word(): 236d0ef721eSBaptiste Daroussin * Find the previous word 237d0ef721eSBaptiste Daroussin */ 238d0ef721eSBaptiste Daroussin libedit_private wchar_t * 239d0ef721eSBaptiste Daroussin c__prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t)) 240d0ef721eSBaptiste Daroussin { 241d0ef721eSBaptiste Daroussin p--; 242d0ef721eSBaptiste Daroussin 243d0ef721eSBaptiste Daroussin while (n--) { 244d0ef721eSBaptiste Daroussin while ((p >= low) && !(*wtest)(*p)) 245d0ef721eSBaptiste Daroussin p--; 246d0ef721eSBaptiste Daroussin while ((p >= low) && (*wtest)(*p)) 247d0ef721eSBaptiste Daroussin p--; 248d0ef721eSBaptiste Daroussin } 249d0ef721eSBaptiste Daroussin 250d0ef721eSBaptiste Daroussin /* cp now points to one character before the word */ 251d0ef721eSBaptiste Daroussin p++; 252d0ef721eSBaptiste Daroussin if (p < low) 253d0ef721eSBaptiste Daroussin p = low; 254d0ef721eSBaptiste Daroussin /* cp now points where we want it */ 255d0ef721eSBaptiste Daroussin return p; 256d0ef721eSBaptiste Daroussin } 257d0ef721eSBaptiste Daroussin 258d0ef721eSBaptiste Daroussin 259d0ef721eSBaptiste Daroussin /* c__next_word(): 260d0ef721eSBaptiste Daroussin * Find the next word 261d0ef721eSBaptiste Daroussin */ 262d0ef721eSBaptiste Daroussin libedit_private wchar_t * 263d0ef721eSBaptiste Daroussin c__next_word(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t)) 264d0ef721eSBaptiste Daroussin { 265d0ef721eSBaptiste Daroussin while (n--) { 266d0ef721eSBaptiste Daroussin while ((p < high) && !(*wtest)(*p)) 267d0ef721eSBaptiste Daroussin p++; 268d0ef721eSBaptiste Daroussin while ((p < high) && (*wtest)(*p)) 269d0ef721eSBaptiste Daroussin p++; 270d0ef721eSBaptiste Daroussin } 271d0ef721eSBaptiste Daroussin if (p > high) 272d0ef721eSBaptiste Daroussin p = high; 273d0ef721eSBaptiste Daroussin /* p now points where we want it */ 274d0ef721eSBaptiste Daroussin return p; 275d0ef721eSBaptiste Daroussin } 276d0ef721eSBaptiste Daroussin 277d0ef721eSBaptiste Daroussin /* cv_next_word(): 278d0ef721eSBaptiste Daroussin * Find the next word vi style 279d0ef721eSBaptiste Daroussin */ 280d0ef721eSBaptiste Daroussin libedit_private wchar_t * 281d0ef721eSBaptiste Daroussin cv_next_word(EditLine *el, wchar_t *p, wchar_t *high, int n, 282d0ef721eSBaptiste Daroussin int (*wtest)(wint_t)) 283d0ef721eSBaptiste Daroussin { 284d0ef721eSBaptiste Daroussin int test; 285d0ef721eSBaptiste Daroussin 286d0ef721eSBaptiste Daroussin while (n--) { 287d0ef721eSBaptiste Daroussin test = (*wtest)(*p); 288d0ef721eSBaptiste Daroussin while ((p < high) && (*wtest)(*p) == test) 289d0ef721eSBaptiste Daroussin p++; 290d0ef721eSBaptiste Daroussin /* 291d0ef721eSBaptiste Daroussin * vi historically deletes with cw only the word preserving the 292d0ef721eSBaptiste Daroussin * trailing whitespace! This is not what 'w' does.. 293d0ef721eSBaptiste Daroussin */ 294d0ef721eSBaptiste Daroussin if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT)) 295d0ef721eSBaptiste Daroussin while ((p < high) && iswspace(*p)) 296d0ef721eSBaptiste Daroussin p++; 297d0ef721eSBaptiste Daroussin } 298d0ef721eSBaptiste Daroussin 299d0ef721eSBaptiste Daroussin /* p now points where we want it */ 300d0ef721eSBaptiste Daroussin if (p > high) 301d0ef721eSBaptiste Daroussin return high; 302d0ef721eSBaptiste Daroussin else 303d0ef721eSBaptiste Daroussin return p; 304d0ef721eSBaptiste Daroussin } 305d0ef721eSBaptiste Daroussin 306d0ef721eSBaptiste Daroussin 307d0ef721eSBaptiste Daroussin /* cv_prev_word(): 308d0ef721eSBaptiste Daroussin * Find the previous word vi style 309d0ef721eSBaptiste Daroussin */ 310d0ef721eSBaptiste Daroussin libedit_private wchar_t * 311d0ef721eSBaptiste Daroussin cv_prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t)) 312d0ef721eSBaptiste Daroussin { 313d0ef721eSBaptiste Daroussin int test; 314d0ef721eSBaptiste Daroussin 315d0ef721eSBaptiste Daroussin p--; 316d0ef721eSBaptiste Daroussin while (n--) { 317d0ef721eSBaptiste Daroussin while ((p > low) && iswspace(*p)) 318d0ef721eSBaptiste Daroussin p--; 319d0ef721eSBaptiste Daroussin test = (*wtest)(*p); 320d0ef721eSBaptiste Daroussin while ((p >= low) && (*wtest)(*p) == test) 321d0ef721eSBaptiste Daroussin p--; 322d0ef721eSBaptiste Daroussin } 323d0ef721eSBaptiste Daroussin p++; 324d0ef721eSBaptiste Daroussin 325d0ef721eSBaptiste Daroussin /* p now points where we want it */ 326d0ef721eSBaptiste Daroussin if (p < low) 327d0ef721eSBaptiste Daroussin return low; 328d0ef721eSBaptiste Daroussin else 329d0ef721eSBaptiste Daroussin return p; 330d0ef721eSBaptiste Daroussin } 331d0ef721eSBaptiste Daroussin 332d0ef721eSBaptiste Daroussin 333d0ef721eSBaptiste Daroussin /* cv_delfini(): 334d0ef721eSBaptiste Daroussin * Finish vi delete action 335d0ef721eSBaptiste Daroussin */ 336d0ef721eSBaptiste Daroussin libedit_private void 337d0ef721eSBaptiste Daroussin cv_delfini(EditLine *el) 338d0ef721eSBaptiste Daroussin { 339d0ef721eSBaptiste Daroussin int size; 340d0ef721eSBaptiste Daroussin int action = el->el_chared.c_vcmd.action; 341d0ef721eSBaptiste Daroussin 342d0ef721eSBaptiste Daroussin if (action & INSERT) 343d0ef721eSBaptiste Daroussin el->el_map.current = el->el_map.key; 344d0ef721eSBaptiste Daroussin 345d0ef721eSBaptiste Daroussin if (el->el_chared.c_vcmd.pos == 0) 346d0ef721eSBaptiste Daroussin /* sanity */ 347d0ef721eSBaptiste Daroussin return; 348d0ef721eSBaptiste Daroussin 349d0ef721eSBaptiste Daroussin size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos); 350d0ef721eSBaptiste Daroussin if (size == 0) 351d0ef721eSBaptiste Daroussin size = 1; 352d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_chared.c_vcmd.pos; 353d0ef721eSBaptiste Daroussin if (action & YANK) { 354d0ef721eSBaptiste Daroussin if (size > 0) 355d0ef721eSBaptiste Daroussin cv_yank(el, el->el_line.cursor, size); 356d0ef721eSBaptiste Daroussin else 357d0ef721eSBaptiste Daroussin cv_yank(el, el->el_line.cursor + size, -size); 358d0ef721eSBaptiste Daroussin } else { 359d0ef721eSBaptiste Daroussin if (size > 0) { 360d0ef721eSBaptiste Daroussin c_delafter(el, size); 361d0ef721eSBaptiste Daroussin re_refresh_cursor(el); 362d0ef721eSBaptiste Daroussin } else { 363d0ef721eSBaptiste Daroussin c_delbefore(el, -size); 364d0ef721eSBaptiste Daroussin el->el_line.cursor += size; 365d0ef721eSBaptiste Daroussin } 366d0ef721eSBaptiste Daroussin } 367d0ef721eSBaptiste Daroussin el->el_chared.c_vcmd.action = NOP; 368d0ef721eSBaptiste Daroussin } 369d0ef721eSBaptiste Daroussin 370d0ef721eSBaptiste Daroussin 371d0ef721eSBaptiste Daroussin /* cv__endword(): 372d0ef721eSBaptiste Daroussin * Go to the end of this word according to vi 373d0ef721eSBaptiste Daroussin */ 374d0ef721eSBaptiste Daroussin libedit_private wchar_t * 375d0ef721eSBaptiste Daroussin cv__endword(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t)) 376d0ef721eSBaptiste Daroussin { 377d0ef721eSBaptiste Daroussin int test; 378d0ef721eSBaptiste Daroussin 379d0ef721eSBaptiste Daroussin p++; 380d0ef721eSBaptiste Daroussin 381d0ef721eSBaptiste Daroussin while (n--) { 382d0ef721eSBaptiste Daroussin while ((p < high) && iswspace(*p)) 383d0ef721eSBaptiste Daroussin p++; 384d0ef721eSBaptiste Daroussin 385d0ef721eSBaptiste Daroussin test = (*wtest)(*p); 386d0ef721eSBaptiste Daroussin while ((p < high) && (*wtest)(*p) == test) 387d0ef721eSBaptiste Daroussin p++; 388d0ef721eSBaptiste Daroussin } 389d0ef721eSBaptiste Daroussin p--; 390d0ef721eSBaptiste Daroussin return p; 391d0ef721eSBaptiste Daroussin } 392d0ef721eSBaptiste Daroussin 393d0ef721eSBaptiste Daroussin /* ch_init(): 394d0ef721eSBaptiste Daroussin * Initialize the character editor 395d0ef721eSBaptiste Daroussin */ 396d0ef721eSBaptiste Daroussin libedit_private int 397d0ef721eSBaptiste Daroussin ch_init(EditLine *el) 398d0ef721eSBaptiste Daroussin { 399d0ef721eSBaptiste Daroussin el->el_line.buffer = el_calloc(EL_BUFSIZ, 400d0ef721eSBaptiste Daroussin sizeof(*el->el_line.buffer)); 401d0ef721eSBaptiste Daroussin if (el->el_line.buffer == NULL) 402d0ef721eSBaptiste Daroussin return -1; 403d0ef721eSBaptiste Daroussin 404d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.buffer; 405d0ef721eSBaptiste Daroussin el->el_line.lastchar = el->el_line.buffer; 406d0ef721eSBaptiste Daroussin el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE]; 407d0ef721eSBaptiste Daroussin 408d0ef721eSBaptiste Daroussin el->el_chared.c_undo.buf = el_calloc(EL_BUFSIZ, 409d0ef721eSBaptiste Daroussin sizeof(*el->el_chared.c_undo.buf)); 410d0ef721eSBaptiste Daroussin if (el->el_chared.c_undo.buf == NULL) 411d0ef721eSBaptiste Daroussin return -1; 412d0ef721eSBaptiste Daroussin el->el_chared.c_undo.len = -1; 413d0ef721eSBaptiste Daroussin el->el_chared.c_undo.cursor = 0; 414d0ef721eSBaptiste Daroussin el->el_chared.c_redo.buf = el_calloc(EL_BUFSIZ, 415d0ef721eSBaptiste Daroussin sizeof(*el->el_chared.c_redo.buf)); 416d0ef721eSBaptiste Daroussin if (el->el_chared.c_redo.buf == NULL) 417*baff8195SBaptiste Daroussin goto out; 418d0ef721eSBaptiste Daroussin el->el_chared.c_redo.pos = el->el_chared.c_redo.buf; 419d0ef721eSBaptiste Daroussin el->el_chared.c_redo.lim = el->el_chared.c_redo.buf + EL_BUFSIZ; 420d0ef721eSBaptiste Daroussin el->el_chared.c_redo.cmd = ED_UNASSIGNED; 421d0ef721eSBaptiste Daroussin 422d0ef721eSBaptiste Daroussin el->el_chared.c_vcmd.action = NOP; 423d0ef721eSBaptiste Daroussin el->el_chared.c_vcmd.pos = el->el_line.buffer; 424d0ef721eSBaptiste Daroussin 425d0ef721eSBaptiste Daroussin el->el_chared.c_kill.buf = el_calloc(EL_BUFSIZ, 426d0ef721eSBaptiste Daroussin sizeof(*el->el_chared.c_kill.buf)); 427d0ef721eSBaptiste Daroussin if (el->el_chared.c_kill.buf == NULL) 428*baff8195SBaptiste Daroussin goto out; 429d0ef721eSBaptiste Daroussin el->el_chared.c_kill.mark = el->el_line.buffer; 430d0ef721eSBaptiste Daroussin el->el_chared.c_kill.last = el->el_chared.c_kill.buf; 431d0ef721eSBaptiste Daroussin el->el_chared.c_resizefun = NULL; 432d0ef721eSBaptiste Daroussin el->el_chared.c_resizearg = NULL; 433d0ef721eSBaptiste Daroussin el->el_chared.c_aliasfun = NULL; 434d0ef721eSBaptiste Daroussin el->el_chared.c_aliasarg = NULL; 435d0ef721eSBaptiste Daroussin 436d0ef721eSBaptiste Daroussin el->el_map.current = el->el_map.key; 437d0ef721eSBaptiste Daroussin 438d0ef721eSBaptiste Daroussin el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ 439d0ef721eSBaptiste Daroussin el->el_state.doingarg = 0; 440d0ef721eSBaptiste Daroussin el->el_state.metanext = 0; 441d0ef721eSBaptiste Daroussin el->el_state.argument = 1; 442d0ef721eSBaptiste Daroussin el->el_state.lastcmd = ED_UNASSIGNED; 443d0ef721eSBaptiste Daroussin 444d0ef721eSBaptiste Daroussin return 0; 445*baff8195SBaptiste Daroussin out: 446*baff8195SBaptiste Daroussin ch_end(el); 447*baff8195SBaptiste Daroussin return -1; 448d0ef721eSBaptiste Daroussin } 449d0ef721eSBaptiste Daroussin 450d0ef721eSBaptiste Daroussin /* ch_reset(): 451d0ef721eSBaptiste Daroussin * Reset the character editor 452d0ef721eSBaptiste Daroussin */ 453d0ef721eSBaptiste Daroussin libedit_private void 454d0ef721eSBaptiste Daroussin ch_reset(EditLine *el) 455d0ef721eSBaptiste Daroussin { 456d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.buffer; 457d0ef721eSBaptiste Daroussin el->el_line.lastchar = el->el_line.buffer; 458d0ef721eSBaptiste Daroussin 459d0ef721eSBaptiste Daroussin el->el_chared.c_undo.len = -1; 460d0ef721eSBaptiste Daroussin el->el_chared.c_undo.cursor = 0; 461d0ef721eSBaptiste Daroussin 462d0ef721eSBaptiste Daroussin el->el_chared.c_vcmd.action = NOP; 463d0ef721eSBaptiste Daroussin el->el_chared.c_vcmd.pos = el->el_line.buffer; 464d0ef721eSBaptiste Daroussin 465d0ef721eSBaptiste Daroussin el->el_chared.c_kill.mark = el->el_line.buffer; 466d0ef721eSBaptiste Daroussin 467d0ef721eSBaptiste Daroussin el->el_map.current = el->el_map.key; 468d0ef721eSBaptiste Daroussin 469d0ef721eSBaptiste Daroussin el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ 470d0ef721eSBaptiste Daroussin el->el_state.doingarg = 0; 471d0ef721eSBaptiste Daroussin el->el_state.metanext = 0; 472d0ef721eSBaptiste Daroussin el->el_state.argument = 1; 473d0ef721eSBaptiste Daroussin el->el_state.lastcmd = ED_UNASSIGNED; 474d0ef721eSBaptiste Daroussin 475d0ef721eSBaptiste Daroussin el->el_history.eventno = 0; 476d0ef721eSBaptiste Daroussin } 477d0ef721eSBaptiste Daroussin 478d0ef721eSBaptiste Daroussin /* ch_enlargebufs(): 479d0ef721eSBaptiste Daroussin * Enlarge line buffer to be able to hold twice as much characters. 480d0ef721eSBaptiste Daroussin * Returns 1 if successful, 0 if not. 481d0ef721eSBaptiste Daroussin */ 482d0ef721eSBaptiste Daroussin libedit_private int 483d0ef721eSBaptiste Daroussin ch_enlargebufs(EditLine *el, size_t addlen) 484d0ef721eSBaptiste Daroussin { 485d0ef721eSBaptiste Daroussin size_t sz, newsz; 486d0ef721eSBaptiste Daroussin wchar_t *newbuffer, *oldbuf, *oldkbuf; 487d0ef721eSBaptiste Daroussin 488d0ef721eSBaptiste Daroussin sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE); 489d0ef721eSBaptiste Daroussin newsz = sz * 2; 490d0ef721eSBaptiste Daroussin /* 491d0ef721eSBaptiste Daroussin * If newly required length is longer than current buffer, we need 492d0ef721eSBaptiste Daroussin * to make the buffer big enough to hold both old and new stuff. 493d0ef721eSBaptiste Daroussin */ 494d0ef721eSBaptiste Daroussin if (addlen > sz) { 495d0ef721eSBaptiste Daroussin while(newsz - sz < addlen) 496d0ef721eSBaptiste Daroussin newsz *= 2; 497d0ef721eSBaptiste Daroussin } 498d0ef721eSBaptiste Daroussin 499d0ef721eSBaptiste Daroussin /* 500d0ef721eSBaptiste Daroussin * Reallocate line buffer. 501d0ef721eSBaptiste Daroussin */ 502d0ef721eSBaptiste Daroussin newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer)); 503d0ef721eSBaptiste Daroussin if (!newbuffer) 504d0ef721eSBaptiste Daroussin return 0; 505d0ef721eSBaptiste Daroussin 506d0ef721eSBaptiste Daroussin /* zero the newly added memory, leave old data in */ 507d0ef721eSBaptiste Daroussin (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 508d0ef721eSBaptiste Daroussin 509d0ef721eSBaptiste Daroussin oldbuf = el->el_line.buffer; 510d0ef721eSBaptiste Daroussin 511d0ef721eSBaptiste Daroussin el->el_line.buffer = newbuffer; 512d0ef721eSBaptiste Daroussin el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf); 513d0ef721eSBaptiste Daroussin el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf); 514d0ef721eSBaptiste Daroussin /* don't set new size until all buffers are enlarged */ 515d0ef721eSBaptiste Daroussin el->el_line.limit = &newbuffer[sz - EL_LEAVE]; 516d0ef721eSBaptiste Daroussin 517d0ef721eSBaptiste Daroussin /* 518d0ef721eSBaptiste Daroussin * Reallocate kill buffer. 519d0ef721eSBaptiste Daroussin */ 520d0ef721eSBaptiste Daroussin newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz * 521d0ef721eSBaptiste Daroussin sizeof(*newbuffer)); 522d0ef721eSBaptiste Daroussin if (!newbuffer) 523d0ef721eSBaptiste Daroussin return 0; 524d0ef721eSBaptiste Daroussin 525d0ef721eSBaptiste Daroussin /* zero the newly added memory, leave old data in */ 526d0ef721eSBaptiste Daroussin (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 527d0ef721eSBaptiste Daroussin 528d0ef721eSBaptiste Daroussin oldkbuf = el->el_chared.c_kill.buf; 529d0ef721eSBaptiste Daroussin 530d0ef721eSBaptiste Daroussin el->el_chared.c_kill.buf = newbuffer; 531d0ef721eSBaptiste Daroussin el->el_chared.c_kill.last = newbuffer + 532d0ef721eSBaptiste Daroussin (el->el_chared.c_kill.last - oldkbuf); 533d0ef721eSBaptiste Daroussin el->el_chared.c_kill.mark = el->el_line.buffer + 534d0ef721eSBaptiste Daroussin (el->el_chared.c_kill.mark - oldbuf); 535d0ef721eSBaptiste Daroussin 536d0ef721eSBaptiste Daroussin /* 537d0ef721eSBaptiste Daroussin * Reallocate undo buffer. 538d0ef721eSBaptiste Daroussin */ 539d0ef721eSBaptiste Daroussin newbuffer = el_realloc(el->el_chared.c_undo.buf, 540d0ef721eSBaptiste Daroussin newsz * sizeof(*newbuffer)); 541d0ef721eSBaptiste Daroussin if (!newbuffer) 542d0ef721eSBaptiste Daroussin return 0; 543d0ef721eSBaptiste Daroussin 544d0ef721eSBaptiste Daroussin /* zero the newly added memory, leave old data in */ 545d0ef721eSBaptiste Daroussin (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 546d0ef721eSBaptiste Daroussin el->el_chared.c_undo.buf = newbuffer; 547d0ef721eSBaptiste Daroussin 548d0ef721eSBaptiste Daroussin newbuffer = el_realloc(el->el_chared.c_redo.buf, 549d0ef721eSBaptiste Daroussin newsz * sizeof(*newbuffer)); 550d0ef721eSBaptiste Daroussin if (!newbuffer) 551d0ef721eSBaptiste Daroussin return 0; 552d0ef721eSBaptiste Daroussin el->el_chared.c_redo.pos = newbuffer + 553d0ef721eSBaptiste Daroussin (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf); 554d0ef721eSBaptiste Daroussin el->el_chared.c_redo.lim = newbuffer + 555d0ef721eSBaptiste Daroussin (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf); 556d0ef721eSBaptiste Daroussin el->el_chared.c_redo.buf = newbuffer; 557d0ef721eSBaptiste Daroussin 558d0ef721eSBaptiste Daroussin if (!hist_enlargebuf(el, sz, newsz)) 559d0ef721eSBaptiste Daroussin return 0; 560d0ef721eSBaptiste Daroussin 561d0ef721eSBaptiste Daroussin /* Safe to set enlarged buffer size */ 562d0ef721eSBaptiste Daroussin el->el_line.limit = &el->el_line.buffer[newsz - EL_LEAVE]; 563d0ef721eSBaptiste Daroussin if (el->el_chared.c_resizefun) 564d0ef721eSBaptiste Daroussin (*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg); 565d0ef721eSBaptiste Daroussin return 1; 566d0ef721eSBaptiste Daroussin } 567d0ef721eSBaptiste Daroussin 568d0ef721eSBaptiste Daroussin /* ch_end(): 569d0ef721eSBaptiste Daroussin * Free the data structures used by the editor 570d0ef721eSBaptiste Daroussin */ 571d0ef721eSBaptiste Daroussin libedit_private void 572d0ef721eSBaptiste Daroussin ch_end(EditLine *el) 573d0ef721eSBaptiste Daroussin { 574d0ef721eSBaptiste Daroussin el_free(el->el_line.buffer); 575d0ef721eSBaptiste Daroussin el->el_line.buffer = NULL; 576d0ef721eSBaptiste Daroussin el->el_line.limit = NULL; 577d0ef721eSBaptiste Daroussin el_free(el->el_chared.c_undo.buf); 578d0ef721eSBaptiste Daroussin el->el_chared.c_undo.buf = NULL; 579d0ef721eSBaptiste Daroussin el_free(el->el_chared.c_redo.buf); 580d0ef721eSBaptiste Daroussin el->el_chared.c_redo.buf = NULL; 581d0ef721eSBaptiste Daroussin el->el_chared.c_redo.pos = NULL; 582d0ef721eSBaptiste Daroussin el->el_chared.c_redo.lim = NULL; 583d0ef721eSBaptiste Daroussin el->el_chared.c_redo.cmd = ED_UNASSIGNED; 584d0ef721eSBaptiste Daroussin el_free(el->el_chared.c_kill.buf); 585d0ef721eSBaptiste Daroussin el->el_chared.c_kill.buf = NULL; 586d0ef721eSBaptiste Daroussin ch_reset(el); 587d0ef721eSBaptiste Daroussin } 588d0ef721eSBaptiste Daroussin 589d0ef721eSBaptiste Daroussin 590d0ef721eSBaptiste Daroussin /* el_insertstr(): 591d0ef721eSBaptiste Daroussin * Insert string at cursor 592d0ef721eSBaptiste Daroussin */ 593d0ef721eSBaptiste Daroussin int 594d0ef721eSBaptiste Daroussin el_winsertstr(EditLine *el, const wchar_t *s) 595d0ef721eSBaptiste Daroussin { 596d0ef721eSBaptiste Daroussin size_t len; 597d0ef721eSBaptiste Daroussin 598d0ef721eSBaptiste Daroussin if (s == NULL || (len = wcslen(s)) == 0) 599d0ef721eSBaptiste Daroussin return -1; 600d0ef721eSBaptiste Daroussin if (el->el_line.lastchar + len >= el->el_line.limit) { 601d0ef721eSBaptiste Daroussin if (!ch_enlargebufs(el, len)) 602d0ef721eSBaptiste Daroussin return -1; 603d0ef721eSBaptiste Daroussin } 604d0ef721eSBaptiste Daroussin 605d0ef721eSBaptiste Daroussin c_insert(el, (int)len); 606d0ef721eSBaptiste Daroussin while (*s) 607d0ef721eSBaptiste Daroussin *el->el_line.cursor++ = *s++; 608d0ef721eSBaptiste Daroussin return 0; 609d0ef721eSBaptiste Daroussin } 610d0ef721eSBaptiste Daroussin 611d0ef721eSBaptiste Daroussin 612d0ef721eSBaptiste Daroussin /* el_deletestr(): 613d0ef721eSBaptiste Daroussin * Delete num characters before the cursor 614d0ef721eSBaptiste Daroussin */ 615d0ef721eSBaptiste Daroussin void 616d0ef721eSBaptiste Daroussin el_deletestr(EditLine *el, int n) 617d0ef721eSBaptiste Daroussin { 618d0ef721eSBaptiste Daroussin if (n <= 0) 619d0ef721eSBaptiste Daroussin return; 620d0ef721eSBaptiste Daroussin 621d0ef721eSBaptiste Daroussin if (el->el_line.cursor < &el->el_line.buffer[n]) 622d0ef721eSBaptiste Daroussin return; 623d0ef721eSBaptiste Daroussin 624d0ef721eSBaptiste Daroussin c_delbefore(el, n); /* delete before dot */ 625d0ef721eSBaptiste Daroussin el->el_line.cursor -= n; 626d0ef721eSBaptiste Daroussin if (el->el_line.cursor < el->el_line.buffer) 627d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.buffer; 628d0ef721eSBaptiste Daroussin } 629d0ef721eSBaptiste Daroussin 6307f399375SBaptiste Daroussin /* el_deletestr1(): 6317f399375SBaptiste Daroussin * Delete characters between start and end 6327f399375SBaptiste Daroussin */ 6337f399375SBaptiste Daroussin int 6347f399375SBaptiste Daroussin el_deletestr1(EditLine *el, int start, int end) 6357f399375SBaptiste Daroussin { 6367f399375SBaptiste Daroussin size_t line_length, len; 6377f399375SBaptiste Daroussin wchar_t *p1, *p2; 6387f399375SBaptiste Daroussin 6397f399375SBaptiste Daroussin if (end <= start) 6407f399375SBaptiste Daroussin return 0; 6417f399375SBaptiste Daroussin 6427f399375SBaptiste Daroussin line_length = (size_t)(el->el_line.lastchar - el->el_line.buffer); 6437f399375SBaptiste Daroussin 6447f399375SBaptiste Daroussin if (start >= (int)line_length || end >= (int)line_length) 6457f399375SBaptiste Daroussin return 0; 6467f399375SBaptiste Daroussin 6477f399375SBaptiste Daroussin len = (size_t)(end - start); 6487f399375SBaptiste Daroussin if (len > line_length - (size_t)end) 6497f399375SBaptiste Daroussin len = line_length - (size_t)end; 6507f399375SBaptiste Daroussin 6517f399375SBaptiste Daroussin p1 = el->el_line.buffer + start; 6527f399375SBaptiste Daroussin p2 = el->el_line.buffer + end; 6537f399375SBaptiste Daroussin for (size_t i = 0; i < len; i++) { 6547f399375SBaptiste Daroussin *p1++ = *p2++; 6557f399375SBaptiste Daroussin el->el_line.lastchar--; 6567f399375SBaptiste Daroussin } 6577f399375SBaptiste Daroussin 6587f399375SBaptiste Daroussin if (el->el_line.cursor < el->el_line.buffer) 6597f399375SBaptiste Daroussin el->el_line.cursor = el->el_line.buffer; 6607f399375SBaptiste Daroussin 6617f399375SBaptiste Daroussin return end - start; 6627f399375SBaptiste Daroussin } 6637f399375SBaptiste Daroussin 6647f399375SBaptiste Daroussin /* el_wreplacestr(): 6657f399375SBaptiste Daroussin * Replace the contents of the line with the provided string 6667f399375SBaptiste Daroussin */ 6677f399375SBaptiste Daroussin int 6687f399375SBaptiste Daroussin el_wreplacestr(EditLine *el, const wchar_t *s) 6697f399375SBaptiste Daroussin { 6707f399375SBaptiste Daroussin size_t len; 6717f399375SBaptiste Daroussin wchar_t * p; 6727f399375SBaptiste Daroussin 6737f399375SBaptiste Daroussin if (s == NULL || (len = wcslen(s)) == 0) 6747f399375SBaptiste Daroussin return -1; 6757f399375SBaptiste Daroussin 6767f399375SBaptiste Daroussin if (el->el_line.buffer + len >= el->el_line.limit) { 6777f399375SBaptiste Daroussin if (!ch_enlargebufs(el, len)) 6787f399375SBaptiste Daroussin return -1; 6797f399375SBaptiste Daroussin } 6807f399375SBaptiste Daroussin 6817f399375SBaptiste Daroussin p = el->el_line.buffer; 6827f399375SBaptiste Daroussin for (size_t i = 0; i < len; i++) 6837f399375SBaptiste Daroussin *p++ = *s++; 6847f399375SBaptiste Daroussin 6857f399375SBaptiste Daroussin el->el_line.buffer[len] = '\0'; 6867f399375SBaptiste Daroussin el->el_line.lastchar = el->el_line.buffer + len; 6877f399375SBaptiste Daroussin if (el->el_line.cursor > el->el_line.lastchar) 6887f399375SBaptiste Daroussin el->el_line.cursor = el->el_line.lastchar; 6897f399375SBaptiste Daroussin 6907f399375SBaptiste Daroussin return 0; 6917f399375SBaptiste Daroussin } 6927f399375SBaptiste Daroussin 693d0ef721eSBaptiste Daroussin /* el_cursor(): 694d0ef721eSBaptiste Daroussin * Move the cursor to the left or the right of the current position 695d0ef721eSBaptiste Daroussin */ 696d0ef721eSBaptiste Daroussin int 697d0ef721eSBaptiste Daroussin el_cursor(EditLine *el, int n) 698d0ef721eSBaptiste Daroussin { 699d0ef721eSBaptiste Daroussin if (n == 0) 700d0ef721eSBaptiste Daroussin goto out; 701d0ef721eSBaptiste Daroussin 702d0ef721eSBaptiste Daroussin el->el_line.cursor += n; 703d0ef721eSBaptiste Daroussin 704d0ef721eSBaptiste Daroussin if (el->el_line.cursor < el->el_line.buffer) 705d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.buffer; 706d0ef721eSBaptiste Daroussin if (el->el_line.cursor > el->el_line.lastchar) 707d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.lastchar; 708d0ef721eSBaptiste Daroussin out: 709d0ef721eSBaptiste Daroussin return (int)(el->el_line.cursor - el->el_line.buffer); 710d0ef721eSBaptiste Daroussin } 711d0ef721eSBaptiste Daroussin 712d0ef721eSBaptiste Daroussin /* c_gets(): 713d0ef721eSBaptiste Daroussin * Get a string 714d0ef721eSBaptiste Daroussin */ 715d0ef721eSBaptiste Daroussin libedit_private int 716d0ef721eSBaptiste Daroussin c_gets(EditLine *el, wchar_t *buf, const wchar_t *prompt) 717d0ef721eSBaptiste Daroussin { 718d0ef721eSBaptiste Daroussin ssize_t len; 719d0ef721eSBaptiste Daroussin wchar_t *cp = el->el_line.buffer, ch; 720d0ef721eSBaptiste Daroussin 721d0ef721eSBaptiste Daroussin if (prompt) { 722d0ef721eSBaptiste Daroussin len = (ssize_t)wcslen(prompt); 723d0ef721eSBaptiste Daroussin (void)memcpy(cp, prompt, (size_t)len * sizeof(*cp)); 724d0ef721eSBaptiste Daroussin cp += len; 725d0ef721eSBaptiste Daroussin } 726d0ef721eSBaptiste Daroussin len = 0; 727d0ef721eSBaptiste Daroussin 728d0ef721eSBaptiste Daroussin for (;;) { 729d0ef721eSBaptiste Daroussin el->el_line.cursor = cp; 730d0ef721eSBaptiste Daroussin *cp = ' '; 731d0ef721eSBaptiste Daroussin el->el_line.lastchar = cp + 1; 732d0ef721eSBaptiste Daroussin re_refresh(el); 733d0ef721eSBaptiste Daroussin 734d0ef721eSBaptiste Daroussin if (el_wgetc(el, &ch) != 1) { 735d0ef721eSBaptiste Daroussin ed_end_of_file(el, 0); 736d0ef721eSBaptiste Daroussin len = -1; 737d0ef721eSBaptiste Daroussin break; 738d0ef721eSBaptiste Daroussin } 739d0ef721eSBaptiste Daroussin 740d0ef721eSBaptiste Daroussin switch (ch) { 741d0ef721eSBaptiste Daroussin 742d0ef721eSBaptiste Daroussin case L'\b': /* Delete and backspace */ 743d0ef721eSBaptiste Daroussin case 0177: 744d0ef721eSBaptiste Daroussin if (len == 0) { 745d0ef721eSBaptiste Daroussin len = -1; 746d0ef721eSBaptiste Daroussin break; 747d0ef721eSBaptiste Daroussin } 748d0ef721eSBaptiste Daroussin len--; 749d0ef721eSBaptiste Daroussin cp--; 750d0ef721eSBaptiste Daroussin continue; 751d0ef721eSBaptiste Daroussin 752d0ef721eSBaptiste Daroussin case 0033: /* ESC */ 753d0ef721eSBaptiste Daroussin case L'\r': /* Newline */ 754d0ef721eSBaptiste Daroussin case L'\n': 755d0ef721eSBaptiste Daroussin buf[len] = ch; 756d0ef721eSBaptiste Daroussin break; 757d0ef721eSBaptiste Daroussin 758d0ef721eSBaptiste Daroussin default: 759d0ef721eSBaptiste Daroussin if (len >= (ssize_t)(EL_BUFSIZ - 16)) 760d0ef721eSBaptiste Daroussin terminal_beep(el); 761d0ef721eSBaptiste Daroussin else { 762d0ef721eSBaptiste Daroussin buf[len++] = ch; 763d0ef721eSBaptiste Daroussin *cp++ = ch; 764d0ef721eSBaptiste Daroussin } 765d0ef721eSBaptiste Daroussin continue; 766d0ef721eSBaptiste Daroussin } 767d0ef721eSBaptiste Daroussin break; 768d0ef721eSBaptiste Daroussin } 769d0ef721eSBaptiste Daroussin 770d0ef721eSBaptiste Daroussin el->el_line.buffer[0] = '\0'; 771d0ef721eSBaptiste Daroussin el->el_line.lastchar = el->el_line.buffer; 772d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.buffer; 773d0ef721eSBaptiste Daroussin return (int)len; 774d0ef721eSBaptiste Daroussin } 775d0ef721eSBaptiste Daroussin 776d0ef721eSBaptiste Daroussin 777d0ef721eSBaptiste Daroussin /* c_hpos(): 778d0ef721eSBaptiste Daroussin * Return the current horizontal position of the cursor 779d0ef721eSBaptiste Daroussin */ 780d0ef721eSBaptiste Daroussin libedit_private int 781d0ef721eSBaptiste Daroussin c_hpos(EditLine *el) 782d0ef721eSBaptiste Daroussin { 783d0ef721eSBaptiste Daroussin wchar_t *ptr; 784d0ef721eSBaptiste Daroussin 785d0ef721eSBaptiste Daroussin /* 786d0ef721eSBaptiste Daroussin * Find how many characters till the beginning of this line. 787d0ef721eSBaptiste Daroussin */ 788d0ef721eSBaptiste Daroussin if (el->el_line.cursor == el->el_line.buffer) 789d0ef721eSBaptiste Daroussin return 0; 790d0ef721eSBaptiste Daroussin else { 791d0ef721eSBaptiste Daroussin for (ptr = el->el_line.cursor - 1; 792d0ef721eSBaptiste Daroussin ptr >= el->el_line.buffer && *ptr != '\n'; 793d0ef721eSBaptiste Daroussin ptr--) 794d0ef721eSBaptiste Daroussin continue; 795d0ef721eSBaptiste Daroussin return (int)(el->el_line.cursor - ptr - 1); 796d0ef721eSBaptiste Daroussin } 797d0ef721eSBaptiste Daroussin } 798d0ef721eSBaptiste Daroussin 799d0ef721eSBaptiste Daroussin libedit_private int 800d0ef721eSBaptiste Daroussin ch_resizefun(EditLine *el, el_zfunc_t f, void *a) 801d0ef721eSBaptiste Daroussin { 802d0ef721eSBaptiste Daroussin el->el_chared.c_resizefun = f; 803d0ef721eSBaptiste Daroussin el->el_chared.c_resizearg = a; 804d0ef721eSBaptiste Daroussin return 0; 805d0ef721eSBaptiste Daroussin } 806d0ef721eSBaptiste Daroussin 807d0ef721eSBaptiste Daroussin libedit_private int 808d0ef721eSBaptiste Daroussin ch_aliasfun(EditLine *el, el_afunc_t f, void *a) 809d0ef721eSBaptiste Daroussin { 810d0ef721eSBaptiste Daroussin el->el_chared.c_aliasfun = f; 811d0ef721eSBaptiste Daroussin el->el_chared.c_aliasarg = a; 812d0ef721eSBaptiste Daroussin return 0; 813d0ef721eSBaptiste Daroussin } 814