1*7f399375SBaptiste Daroussin /* $NetBSD: chared.c,v 1.62 2022/02/08 21:13:22 rillig 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*7f399375SBaptiste Daroussin __RCSID("$NetBSD: chared.c,v 1.62 2022/02/08 21:13:22 rillig 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) 417d0ef721eSBaptiste Daroussin return -1; 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) 428d0ef721eSBaptiste Daroussin return -1; 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; 445d0ef721eSBaptiste Daroussin } 446d0ef721eSBaptiste Daroussin 447d0ef721eSBaptiste Daroussin /* ch_reset(): 448d0ef721eSBaptiste Daroussin * Reset the character editor 449d0ef721eSBaptiste Daroussin */ 450d0ef721eSBaptiste Daroussin libedit_private void 451d0ef721eSBaptiste Daroussin ch_reset(EditLine *el) 452d0ef721eSBaptiste Daroussin { 453d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.buffer; 454d0ef721eSBaptiste Daroussin el->el_line.lastchar = el->el_line.buffer; 455d0ef721eSBaptiste Daroussin 456d0ef721eSBaptiste Daroussin el->el_chared.c_undo.len = -1; 457d0ef721eSBaptiste Daroussin el->el_chared.c_undo.cursor = 0; 458d0ef721eSBaptiste Daroussin 459d0ef721eSBaptiste Daroussin el->el_chared.c_vcmd.action = NOP; 460d0ef721eSBaptiste Daroussin el->el_chared.c_vcmd.pos = el->el_line.buffer; 461d0ef721eSBaptiste Daroussin 462d0ef721eSBaptiste Daroussin el->el_chared.c_kill.mark = el->el_line.buffer; 463d0ef721eSBaptiste Daroussin 464d0ef721eSBaptiste Daroussin el->el_map.current = el->el_map.key; 465d0ef721eSBaptiste Daroussin 466d0ef721eSBaptiste Daroussin el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ 467d0ef721eSBaptiste Daroussin el->el_state.doingarg = 0; 468d0ef721eSBaptiste Daroussin el->el_state.metanext = 0; 469d0ef721eSBaptiste Daroussin el->el_state.argument = 1; 470d0ef721eSBaptiste Daroussin el->el_state.lastcmd = ED_UNASSIGNED; 471d0ef721eSBaptiste Daroussin 472d0ef721eSBaptiste Daroussin el->el_history.eventno = 0; 473d0ef721eSBaptiste Daroussin } 474d0ef721eSBaptiste Daroussin 475d0ef721eSBaptiste Daroussin /* ch_enlargebufs(): 476d0ef721eSBaptiste Daroussin * Enlarge line buffer to be able to hold twice as much characters. 477d0ef721eSBaptiste Daroussin * Returns 1 if successful, 0 if not. 478d0ef721eSBaptiste Daroussin */ 479d0ef721eSBaptiste Daroussin libedit_private int 480d0ef721eSBaptiste Daroussin ch_enlargebufs(EditLine *el, size_t addlen) 481d0ef721eSBaptiste Daroussin { 482d0ef721eSBaptiste Daroussin size_t sz, newsz; 483d0ef721eSBaptiste Daroussin wchar_t *newbuffer, *oldbuf, *oldkbuf; 484d0ef721eSBaptiste Daroussin 485d0ef721eSBaptiste Daroussin sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE); 486d0ef721eSBaptiste Daroussin newsz = sz * 2; 487d0ef721eSBaptiste Daroussin /* 488d0ef721eSBaptiste Daroussin * If newly required length is longer than current buffer, we need 489d0ef721eSBaptiste Daroussin * to make the buffer big enough to hold both old and new stuff. 490d0ef721eSBaptiste Daroussin */ 491d0ef721eSBaptiste Daroussin if (addlen > sz) { 492d0ef721eSBaptiste Daroussin while(newsz - sz < addlen) 493d0ef721eSBaptiste Daroussin newsz *= 2; 494d0ef721eSBaptiste Daroussin } 495d0ef721eSBaptiste Daroussin 496d0ef721eSBaptiste Daroussin /* 497d0ef721eSBaptiste Daroussin * Reallocate line buffer. 498d0ef721eSBaptiste Daroussin */ 499d0ef721eSBaptiste Daroussin newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer)); 500d0ef721eSBaptiste Daroussin if (!newbuffer) 501d0ef721eSBaptiste Daroussin return 0; 502d0ef721eSBaptiste Daroussin 503d0ef721eSBaptiste Daroussin /* zero the newly added memory, leave old data in */ 504d0ef721eSBaptiste Daroussin (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 505d0ef721eSBaptiste Daroussin 506d0ef721eSBaptiste Daroussin oldbuf = el->el_line.buffer; 507d0ef721eSBaptiste Daroussin 508d0ef721eSBaptiste Daroussin el->el_line.buffer = newbuffer; 509d0ef721eSBaptiste Daroussin el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf); 510d0ef721eSBaptiste Daroussin el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf); 511d0ef721eSBaptiste Daroussin /* don't set new size until all buffers are enlarged */ 512d0ef721eSBaptiste Daroussin el->el_line.limit = &newbuffer[sz - EL_LEAVE]; 513d0ef721eSBaptiste Daroussin 514d0ef721eSBaptiste Daroussin /* 515d0ef721eSBaptiste Daroussin * Reallocate kill buffer. 516d0ef721eSBaptiste Daroussin */ 517d0ef721eSBaptiste Daroussin newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz * 518d0ef721eSBaptiste Daroussin sizeof(*newbuffer)); 519d0ef721eSBaptiste Daroussin if (!newbuffer) 520d0ef721eSBaptiste Daroussin return 0; 521d0ef721eSBaptiste Daroussin 522d0ef721eSBaptiste Daroussin /* zero the newly added memory, leave old data in */ 523d0ef721eSBaptiste Daroussin (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 524d0ef721eSBaptiste Daroussin 525d0ef721eSBaptiste Daroussin oldkbuf = el->el_chared.c_kill.buf; 526d0ef721eSBaptiste Daroussin 527d0ef721eSBaptiste Daroussin el->el_chared.c_kill.buf = newbuffer; 528d0ef721eSBaptiste Daroussin el->el_chared.c_kill.last = newbuffer + 529d0ef721eSBaptiste Daroussin (el->el_chared.c_kill.last - oldkbuf); 530d0ef721eSBaptiste Daroussin el->el_chared.c_kill.mark = el->el_line.buffer + 531d0ef721eSBaptiste Daroussin (el->el_chared.c_kill.mark - oldbuf); 532d0ef721eSBaptiste Daroussin 533d0ef721eSBaptiste Daroussin /* 534d0ef721eSBaptiste Daroussin * Reallocate undo buffer. 535d0ef721eSBaptiste Daroussin */ 536d0ef721eSBaptiste Daroussin newbuffer = el_realloc(el->el_chared.c_undo.buf, 537d0ef721eSBaptiste Daroussin newsz * sizeof(*newbuffer)); 538d0ef721eSBaptiste Daroussin if (!newbuffer) 539d0ef721eSBaptiste Daroussin return 0; 540d0ef721eSBaptiste Daroussin 541d0ef721eSBaptiste Daroussin /* zero the newly added memory, leave old data in */ 542d0ef721eSBaptiste Daroussin (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); 543d0ef721eSBaptiste Daroussin el->el_chared.c_undo.buf = newbuffer; 544d0ef721eSBaptiste Daroussin 545d0ef721eSBaptiste Daroussin newbuffer = el_realloc(el->el_chared.c_redo.buf, 546d0ef721eSBaptiste Daroussin newsz * sizeof(*newbuffer)); 547d0ef721eSBaptiste Daroussin if (!newbuffer) 548d0ef721eSBaptiste Daroussin return 0; 549d0ef721eSBaptiste Daroussin el->el_chared.c_redo.pos = newbuffer + 550d0ef721eSBaptiste Daroussin (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf); 551d0ef721eSBaptiste Daroussin el->el_chared.c_redo.lim = newbuffer + 552d0ef721eSBaptiste Daroussin (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf); 553d0ef721eSBaptiste Daroussin el->el_chared.c_redo.buf = newbuffer; 554d0ef721eSBaptiste Daroussin 555d0ef721eSBaptiste Daroussin if (!hist_enlargebuf(el, sz, newsz)) 556d0ef721eSBaptiste Daroussin return 0; 557d0ef721eSBaptiste Daroussin 558d0ef721eSBaptiste Daroussin /* Safe to set enlarged buffer size */ 559d0ef721eSBaptiste Daroussin el->el_line.limit = &el->el_line.buffer[newsz - EL_LEAVE]; 560d0ef721eSBaptiste Daroussin if (el->el_chared.c_resizefun) 561d0ef721eSBaptiste Daroussin (*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg); 562d0ef721eSBaptiste Daroussin return 1; 563d0ef721eSBaptiste Daroussin } 564d0ef721eSBaptiste Daroussin 565d0ef721eSBaptiste Daroussin /* ch_end(): 566d0ef721eSBaptiste Daroussin * Free the data structures used by the editor 567d0ef721eSBaptiste Daroussin */ 568d0ef721eSBaptiste Daroussin libedit_private void 569d0ef721eSBaptiste Daroussin ch_end(EditLine *el) 570d0ef721eSBaptiste Daroussin { 571d0ef721eSBaptiste Daroussin el_free(el->el_line.buffer); 572d0ef721eSBaptiste Daroussin el->el_line.buffer = NULL; 573d0ef721eSBaptiste Daroussin el->el_line.limit = NULL; 574d0ef721eSBaptiste Daroussin el_free(el->el_chared.c_undo.buf); 575d0ef721eSBaptiste Daroussin el->el_chared.c_undo.buf = NULL; 576d0ef721eSBaptiste Daroussin el_free(el->el_chared.c_redo.buf); 577d0ef721eSBaptiste Daroussin el->el_chared.c_redo.buf = NULL; 578d0ef721eSBaptiste Daroussin el->el_chared.c_redo.pos = NULL; 579d0ef721eSBaptiste Daroussin el->el_chared.c_redo.lim = NULL; 580d0ef721eSBaptiste Daroussin el->el_chared.c_redo.cmd = ED_UNASSIGNED; 581d0ef721eSBaptiste Daroussin el_free(el->el_chared.c_kill.buf); 582d0ef721eSBaptiste Daroussin el->el_chared.c_kill.buf = NULL; 583d0ef721eSBaptiste Daroussin ch_reset(el); 584d0ef721eSBaptiste Daroussin } 585d0ef721eSBaptiste Daroussin 586d0ef721eSBaptiste Daroussin 587d0ef721eSBaptiste Daroussin /* el_insertstr(): 588d0ef721eSBaptiste Daroussin * Insert string at cursor 589d0ef721eSBaptiste Daroussin */ 590d0ef721eSBaptiste Daroussin int 591d0ef721eSBaptiste Daroussin el_winsertstr(EditLine *el, const wchar_t *s) 592d0ef721eSBaptiste Daroussin { 593d0ef721eSBaptiste Daroussin size_t len; 594d0ef721eSBaptiste Daroussin 595d0ef721eSBaptiste Daroussin if (s == NULL || (len = wcslen(s)) == 0) 596d0ef721eSBaptiste Daroussin return -1; 597d0ef721eSBaptiste Daroussin if (el->el_line.lastchar + len >= el->el_line.limit) { 598d0ef721eSBaptiste Daroussin if (!ch_enlargebufs(el, len)) 599d0ef721eSBaptiste Daroussin return -1; 600d0ef721eSBaptiste Daroussin } 601d0ef721eSBaptiste Daroussin 602d0ef721eSBaptiste Daroussin c_insert(el, (int)len); 603d0ef721eSBaptiste Daroussin while (*s) 604d0ef721eSBaptiste Daroussin *el->el_line.cursor++ = *s++; 605d0ef721eSBaptiste Daroussin return 0; 606d0ef721eSBaptiste Daroussin } 607d0ef721eSBaptiste Daroussin 608d0ef721eSBaptiste Daroussin 609d0ef721eSBaptiste Daroussin /* el_deletestr(): 610d0ef721eSBaptiste Daroussin * Delete num characters before the cursor 611d0ef721eSBaptiste Daroussin */ 612d0ef721eSBaptiste Daroussin void 613d0ef721eSBaptiste Daroussin el_deletestr(EditLine *el, int n) 614d0ef721eSBaptiste Daroussin { 615d0ef721eSBaptiste Daroussin if (n <= 0) 616d0ef721eSBaptiste Daroussin return; 617d0ef721eSBaptiste Daroussin 618d0ef721eSBaptiste Daroussin if (el->el_line.cursor < &el->el_line.buffer[n]) 619d0ef721eSBaptiste Daroussin return; 620d0ef721eSBaptiste Daroussin 621d0ef721eSBaptiste Daroussin c_delbefore(el, n); /* delete before dot */ 622d0ef721eSBaptiste Daroussin el->el_line.cursor -= n; 623d0ef721eSBaptiste Daroussin if (el->el_line.cursor < el->el_line.buffer) 624d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.buffer; 625d0ef721eSBaptiste Daroussin } 626d0ef721eSBaptiste Daroussin 627*7f399375SBaptiste Daroussin /* el_deletestr1(): 628*7f399375SBaptiste Daroussin * Delete characters between start and end 629*7f399375SBaptiste Daroussin */ 630*7f399375SBaptiste Daroussin int 631*7f399375SBaptiste Daroussin el_deletestr1(EditLine *el, int start, int end) 632*7f399375SBaptiste Daroussin { 633*7f399375SBaptiste Daroussin size_t line_length, len; 634*7f399375SBaptiste Daroussin wchar_t *p1, *p2; 635*7f399375SBaptiste Daroussin 636*7f399375SBaptiste Daroussin if (end <= start) 637*7f399375SBaptiste Daroussin return 0; 638*7f399375SBaptiste Daroussin 639*7f399375SBaptiste Daroussin line_length = (size_t)(el->el_line.lastchar - el->el_line.buffer); 640*7f399375SBaptiste Daroussin 641*7f399375SBaptiste Daroussin if (start >= (int)line_length || end >= (int)line_length) 642*7f399375SBaptiste Daroussin return 0; 643*7f399375SBaptiste Daroussin 644*7f399375SBaptiste Daroussin len = (size_t)(end - start); 645*7f399375SBaptiste Daroussin if (len > line_length - (size_t)end) 646*7f399375SBaptiste Daroussin len = line_length - (size_t)end; 647*7f399375SBaptiste Daroussin 648*7f399375SBaptiste Daroussin p1 = el->el_line.buffer + start; 649*7f399375SBaptiste Daroussin p2 = el->el_line.buffer + end; 650*7f399375SBaptiste Daroussin for (size_t i = 0; i < len; i++) { 651*7f399375SBaptiste Daroussin *p1++ = *p2++; 652*7f399375SBaptiste Daroussin el->el_line.lastchar--; 653*7f399375SBaptiste Daroussin } 654*7f399375SBaptiste Daroussin 655*7f399375SBaptiste Daroussin if (el->el_line.cursor < el->el_line.buffer) 656*7f399375SBaptiste Daroussin el->el_line.cursor = el->el_line.buffer; 657*7f399375SBaptiste Daroussin 658*7f399375SBaptiste Daroussin return end - start; 659*7f399375SBaptiste Daroussin } 660*7f399375SBaptiste Daroussin 661*7f399375SBaptiste Daroussin /* el_wreplacestr(): 662*7f399375SBaptiste Daroussin * Replace the contents of the line with the provided string 663*7f399375SBaptiste Daroussin */ 664*7f399375SBaptiste Daroussin int 665*7f399375SBaptiste Daroussin el_wreplacestr(EditLine *el, const wchar_t *s) 666*7f399375SBaptiste Daroussin { 667*7f399375SBaptiste Daroussin size_t len; 668*7f399375SBaptiste Daroussin wchar_t * p; 669*7f399375SBaptiste Daroussin 670*7f399375SBaptiste Daroussin if (s == NULL || (len = wcslen(s)) == 0) 671*7f399375SBaptiste Daroussin return -1; 672*7f399375SBaptiste Daroussin 673*7f399375SBaptiste Daroussin if (el->el_line.buffer + len >= el->el_line.limit) { 674*7f399375SBaptiste Daroussin if (!ch_enlargebufs(el, len)) 675*7f399375SBaptiste Daroussin return -1; 676*7f399375SBaptiste Daroussin } 677*7f399375SBaptiste Daroussin 678*7f399375SBaptiste Daroussin p = el->el_line.buffer; 679*7f399375SBaptiste Daroussin for (size_t i = 0; i < len; i++) 680*7f399375SBaptiste Daroussin *p++ = *s++; 681*7f399375SBaptiste Daroussin 682*7f399375SBaptiste Daroussin el->el_line.buffer[len] = '\0'; 683*7f399375SBaptiste Daroussin el->el_line.lastchar = el->el_line.buffer + len; 684*7f399375SBaptiste Daroussin if (el->el_line.cursor > el->el_line.lastchar) 685*7f399375SBaptiste Daroussin el->el_line.cursor = el->el_line.lastchar; 686*7f399375SBaptiste Daroussin 687*7f399375SBaptiste Daroussin return 0; 688*7f399375SBaptiste Daroussin } 689*7f399375SBaptiste Daroussin 690d0ef721eSBaptiste Daroussin /* el_cursor(): 691d0ef721eSBaptiste Daroussin * Move the cursor to the left or the right of the current position 692d0ef721eSBaptiste Daroussin */ 693d0ef721eSBaptiste Daroussin int 694d0ef721eSBaptiste Daroussin el_cursor(EditLine *el, int n) 695d0ef721eSBaptiste Daroussin { 696d0ef721eSBaptiste Daroussin if (n == 0) 697d0ef721eSBaptiste Daroussin goto out; 698d0ef721eSBaptiste Daroussin 699d0ef721eSBaptiste Daroussin el->el_line.cursor += n; 700d0ef721eSBaptiste Daroussin 701d0ef721eSBaptiste Daroussin if (el->el_line.cursor < el->el_line.buffer) 702d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.buffer; 703d0ef721eSBaptiste Daroussin if (el->el_line.cursor > el->el_line.lastchar) 704d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.lastchar; 705d0ef721eSBaptiste Daroussin out: 706d0ef721eSBaptiste Daroussin return (int)(el->el_line.cursor - el->el_line.buffer); 707d0ef721eSBaptiste Daroussin } 708d0ef721eSBaptiste Daroussin 709d0ef721eSBaptiste Daroussin /* c_gets(): 710d0ef721eSBaptiste Daroussin * Get a string 711d0ef721eSBaptiste Daroussin */ 712d0ef721eSBaptiste Daroussin libedit_private int 713d0ef721eSBaptiste Daroussin c_gets(EditLine *el, wchar_t *buf, const wchar_t *prompt) 714d0ef721eSBaptiste Daroussin { 715d0ef721eSBaptiste Daroussin ssize_t len; 716d0ef721eSBaptiste Daroussin wchar_t *cp = el->el_line.buffer, ch; 717d0ef721eSBaptiste Daroussin 718d0ef721eSBaptiste Daroussin if (prompt) { 719d0ef721eSBaptiste Daroussin len = (ssize_t)wcslen(prompt); 720d0ef721eSBaptiste Daroussin (void)memcpy(cp, prompt, (size_t)len * sizeof(*cp)); 721d0ef721eSBaptiste Daroussin cp += len; 722d0ef721eSBaptiste Daroussin } 723d0ef721eSBaptiste Daroussin len = 0; 724d0ef721eSBaptiste Daroussin 725d0ef721eSBaptiste Daroussin for (;;) { 726d0ef721eSBaptiste Daroussin el->el_line.cursor = cp; 727d0ef721eSBaptiste Daroussin *cp = ' '; 728d0ef721eSBaptiste Daroussin el->el_line.lastchar = cp + 1; 729d0ef721eSBaptiste Daroussin re_refresh(el); 730d0ef721eSBaptiste Daroussin 731d0ef721eSBaptiste Daroussin if (el_wgetc(el, &ch) != 1) { 732d0ef721eSBaptiste Daroussin ed_end_of_file(el, 0); 733d0ef721eSBaptiste Daroussin len = -1; 734d0ef721eSBaptiste Daroussin break; 735d0ef721eSBaptiste Daroussin } 736d0ef721eSBaptiste Daroussin 737d0ef721eSBaptiste Daroussin switch (ch) { 738d0ef721eSBaptiste Daroussin 739d0ef721eSBaptiste Daroussin case L'\b': /* Delete and backspace */ 740d0ef721eSBaptiste Daroussin case 0177: 741d0ef721eSBaptiste Daroussin if (len == 0) { 742d0ef721eSBaptiste Daroussin len = -1; 743d0ef721eSBaptiste Daroussin break; 744d0ef721eSBaptiste Daroussin } 745d0ef721eSBaptiste Daroussin len--; 746d0ef721eSBaptiste Daroussin cp--; 747d0ef721eSBaptiste Daroussin continue; 748d0ef721eSBaptiste Daroussin 749d0ef721eSBaptiste Daroussin case 0033: /* ESC */ 750d0ef721eSBaptiste Daroussin case L'\r': /* Newline */ 751d0ef721eSBaptiste Daroussin case L'\n': 752d0ef721eSBaptiste Daroussin buf[len] = ch; 753d0ef721eSBaptiste Daroussin break; 754d0ef721eSBaptiste Daroussin 755d0ef721eSBaptiste Daroussin default: 756d0ef721eSBaptiste Daroussin if (len >= (ssize_t)(EL_BUFSIZ - 16)) 757d0ef721eSBaptiste Daroussin terminal_beep(el); 758d0ef721eSBaptiste Daroussin else { 759d0ef721eSBaptiste Daroussin buf[len++] = ch; 760d0ef721eSBaptiste Daroussin *cp++ = ch; 761d0ef721eSBaptiste Daroussin } 762d0ef721eSBaptiste Daroussin continue; 763d0ef721eSBaptiste Daroussin } 764d0ef721eSBaptiste Daroussin break; 765d0ef721eSBaptiste Daroussin } 766d0ef721eSBaptiste Daroussin 767d0ef721eSBaptiste Daroussin el->el_line.buffer[0] = '\0'; 768d0ef721eSBaptiste Daroussin el->el_line.lastchar = el->el_line.buffer; 769d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.buffer; 770d0ef721eSBaptiste Daroussin return (int)len; 771d0ef721eSBaptiste Daroussin } 772d0ef721eSBaptiste Daroussin 773d0ef721eSBaptiste Daroussin 774d0ef721eSBaptiste Daroussin /* c_hpos(): 775d0ef721eSBaptiste Daroussin * Return the current horizontal position of the cursor 776d0ef721eSBaptiste Daroussin */ 777d0ef721eSBaptiste Daroussin libedit_private int 778d0ef721eSBaptiste Daroussin c_hpos(EditLine *el) 779d0ef721eSBaptiste Daroussin { 780d0ef721eSBaptiste Daroussin wchar_t *ptr; 781d0ef721eSBaptiste Daroussin 782d0ef721eSBaptiste Daroussin /* 783d0ef721eSBaptiste Daroussin * Find how many characters till the beginning of this line. 784d0ef721eSBaptiste Daroussin */ 785d0ef721eSBaptiste Daroussin if (el->el_line.cursor == el->el_line.buffer) 786d0ef721eSBaptiste Daroussin return 0; 787d0ef721eSBaptiste Daroussin else { 788d0ef721eSBaptiste Daroussin for (ptr = el->el_line.cursor - 1; 789d0ef721eSBaptiste Daroussin ptr >= el->el_line.buffer && *ptr != '\n'; 790d0ef721eSBaptiste Daroussin ptr--) 791d0ef721eSBaptiste Daroussin continue; 792d0ef721eSBaptiste Daroussin return (int)(el->el_line.cursor - ptr - 1); 793d0ef721eSBaptiste Daroussin } 794d0ef721eSBaptiste Daroussin } 795d0ef721eSBaptiste Daroussin 796d0ef721eSBaptiste Daroussin libedit_private int 797d0ef721eSBaptiste Daroussin ch_resizefun(EditLine *el, el_zfunc_t f, void *a) 798d0ef721eSBaptiste Daroussin { 799d0ef721eSBaptiste Daroussin el->el_chared.c_resizefun = f; 800d0ef721eSBaptiste Daroussin el->el_chared.c_resizearg = a; 801d0ef721eSBaptiste Daroussin return 0; 802d0ef721eSBaptiste Daroussin } 803d0ef721eSBaptiste Daroussin 804d0ef721eSBaptiste Daroussin libedit_private int 805d0ef721eSBaptiste Daroussin ch_aliasfun(EditLine *el, el_afunc_t f, void *a) 806d0ef721eSBaptiste Daroussin { 807d0ef721eSBaptiste Daroussin el->el_chared.c_aliasfun = f; 808d0ef721eSBaptiste Daroussin el->el_chared.c_aliasarg = a; 809d0ef721eSBaptiste Daroussin return 0; 810d0ef721eSBaptiste Daroussin } 811