Changeset View
Changeset View
Standalone View
Standalone View
lib/libedit/chared.c
/* $NetBSD: chared.c,v 1.49 2016/02/24 14:29:21 christos Exp $ */ | /* $NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 christos Exp $ */ | ||||
/*- | /*- | ||||
* Copyright (c) 1992, 1993 | * Copyright (c) 1992, 1993 | ||||
* The Regents of the University of California. All rights reserved. | * The Regents of the University of California. All rights reserved. | ||||
* | * | ||||
* This code is derived from software contributed to Berkeley by | * This code is derived from software contributed to Berkeley by | ||||
* Christos Zoulas of Cornell University. | * Christos Zoulas of Cornell University. | ||||
* | * | ||||
Show All 22 Lines | |||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include "config.h" | #include "config.h" | ||||
#if !defined(lint) && !defined(SCCSID) | #if !defined(lint) && !defined(SCCSID) | ||||
#if 0 | #if 0 | ||||
static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93"; | static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93"; | ||||
#else | #else | ||||
__RCSID("$NetBSD: chared.c,v 1.49 2016/02/24 14:29:21 christos Exp $"); | __RCSID("$NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 christos Exp $"); | ||||
#endif | #endif | ||||
#endif /* not lint && not SCCSID */ | #endif /* not lint && not SCCSID */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
/* | /* | ||||
* chared.c: Character editor utilities | * chared.c: Character editor utilities | ||||
*/ | */ | ||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include "el.h" | #include "el.h" | ||||
#include "common.h" | #include "common.h" | ||||
#include "fcns.h" | |||||
private void ch__clearmacro (EditLine *); | |||||
/* value to leave unused in line buffer */ | /* value to leave unused in line buffer */ | ||||
#define EL_LEAVE 2 | #define EL_LEAVE 2 | ||||
/* cv_undo(): | /* cv_undo(): | ||||
* Handle state for the vi undo command | * Handle state for the vi undo command | ||||
*/ | */ | ||||
protected void | libedit_private void | ||||
cv_undo(EditLine *el) | cv_undo(EditLine *el) | ||||
{ | { | ||||
c_undo_t *vu = &el->el_chared.c_undo; | c_undo_t *vu = &el->el_chared.c_undo; | ||||
c_redo_t *r = &el->el_chared.c_redo; | c_redo_t *r = &el->el_chared.c_redo; | ||||
size_t size; | size_t size; | ||||
/* Save entire line for undo */ | /* Save entire line for undo */ | ||||
size = (size_t)(el->el_line.lastchar - el->el_line.buffer); | size = (size_t)(el->el_line.lastchar - el->el_line.buffer); | ||||
vu->len = (ssize_t)size; | vu->len = (ssize_t)size; | ||||
vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer); | vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer); | ||||
(void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf)); | (void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf)); | ||||
/* save command info for redo */ | /* save command info for redo */ | ||||
r->count = el->el_state.doingarg ? el->el_state.argument : 0; | r->count = el->el_state.doingarg ? el->el_state.argument : 0; | ||||
r->action = el->el_chared.c_vcmd.action; | r->action = el->el_chared.c_vcmd.action; | ||||
r->pos = r->buf; | r->pos = r->buf; | ||||
r->cmd = el->el_state.thiscmd; | r->cmd = el->el_state.thiscmd; | ||||
r->ch = el->el_state.thisch; | r->ch = el->el_state.thisch; | ||||
} | } | ||||
/* cv_yank(): | /* cv_yank(): | ||||
* Save yank/delete data for paste | * Save yank/delete data for paste | ||||
*/ | */ | ||||
protected void | libedit_private void | ||||
cv_yank(EditLine *el, const Char *ptr, int size) | cv_yank(EditLine *el, const wchar_t *ptr, int size) | ||||
{ | { | ||||
c_kill_t *k = &el->el_chared.c_kill; | c_kill_t *k = &el->el_chared.c_kill; | ||||
(void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf)); | (void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf)); | ||||
k->last = k->buf + size; | k->last = k->buf + size; | ||||
} | } | ||||
/* c_insert(): | /* c_insert(): | ||||
* Insert num characters | * Insert num characters | ||||
*/ | */ | ||||
protected void | libedit_private void | ||||
c_insert(EditLine *el, int num) | c_insert(EditLine *el, int num) | ||||
{ | { | ||||
Char *cp; | wchar_t *cp; | ||||
if (el->el_line.lastchar + num >= el->el_line.limit) { | if (el->el_line.lastchar + num >= el->el_line.limit) { | ||||
if (!ch_enlargebufs(el, (size_t)num)) | if (!ch_enlargebufs(el, (size_t)num)) | ||||
return; /* can't go past end of buffer */ | return; /* can't go past end of buffer */ | ||||
} | } | ||||
if (el->el_line.cursor < el->el_line.lastchar) { | if (el->el_line.cursor < el->el_line.lastchar) { | ||||
/* if I must move chars */ | /* if I must move chars */ | ||||
for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--) | for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--) | ||||
cp[num] = *cp; | cp[num] = *cp; | ||||
} | } | ||||
el->el_line.lastchar += num; | el->el_line.lastchar += num; | ||||
} | } | ||||
/* c_delafter(): | /* c_delafter(): | ||||
* Delete num characters after the cursor | * Delete num characters after the cursor | ||||
*/ | */ | ||||
protected void | libedit_private void | ||||
c_delafter(EditLine *el, int num) | c_delafter(EditLine *el, int num) | ||||
{ | { | ||||
if (el->el_line.cursor + num > el->el_line.lastchar) | if (el->el_line.cursor + num > el->el_line.lastchar) | ||||
num = (int)(el->el_line.lastchar - el->el_line.cursor); | num = (int)(el->el_line.lastchar - el->el_line.cursor); | ||||
if (el->el_map.current != el->el_map.emacs) { | if (el->el_map.current != el->el_map.emacs) { | ||||
cv_undo(el); | cv_undo(el); | ||||
cv_yank(el, el->el_line.cursor, num); | cv_yank(el, el->el_line.cursor, num); | ||||
} | } | ||||
if (num > 0) { | if (num > 0) { | ||||
Char *cp; | wchar_t *cp; | ||||
for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) | for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) | ||||
*cp = cp[num]; | *cp = cp[num]; | ||||
el->el_line.lastchar -= num; | el->el_line.lastchar -= num; | ||||
} | } | ||||
} | } | ||||
/* c_delafter1(): | /* c_delafter1(): | ||||
* Delete the character after the cursor, do not yank | * Delete the character after the cursor, do not yank | ||||
*/ | */ | ||||
protected void | libedit_private void | ||||
c_delafter1(EditLine *el) | c_delafter1(EditLine *el) | ||||
{ | { | ||||
Char *cp; | wchar_t *cp; | ||||
for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) | for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) | ||||
*cp = cp[1]; | *cp = cp[1]; | ||||
el->el_line.lastchar--; | el->el_line.lastchar--; | ||||
} | } | ||||
/* c_delbefore(): | /* c_delbefore(): | ||||
* Delete num characters before the cursor | * Delete num characters before the cursor | ||||
*/ | */ | ||||
protected void | libedit_private void | ||||
c_delbefore(EditLine *el, int num) | c_delbefore(EditLine *el, int num) | ||||
{ | { | ||||
if (el->el_line.cursor - num < el->el_line.buffer) | if (el->el_line.cursor - num < el->el_line.buffer) | ||||
num = (int)(el->el_line.cursor - el->el_line.buffer); | num = (int)(el->el_line.cursor - el->el_line.buffer); | ||||
if (el->el_map.current != el->el_map.emacs) { | if (el->el_map.current != el->el_map.emacs) { | ||||
cv_undo(el); | cv_undo(el); | ||||
cv_yank(el, el->el_line.cursor - num, num); | cv_yank(el, el->el_line.cursor - num, num); | ||||
} | } | ||||
if (num > 0) { | if (num > 0) { | ||||
Char *cp; | wchar_t *cp; | ||||
for (cp = el->el_line.cursor - num; | for (cp = el->el_line.cursor - num; | ||||
cp <= el->el_line.lastchar; | &cp[num] <= el->el_line.lastchar; | ||||
cp++) | cp++) | ||||
*cp = cp[num]; | *cp = cp[num]; | ||||
el->el_line.lastchar -= num; | el->el_line.lastchar -= num; | ||||
} | } | ||||
} | } | ||||
/* c_delbefore1(): | /* c_delbefore1(): | ||||
* Delete the character before the cursor, do not yank | * Delete the character before the cursor, do not yank | ||||
*/ | */ | ||||
protected void | libedit_private void | ||||
c_delbefore1(EditLine *el) | c_delbefore1(EditLine *el) | ||||
{ | { | ||||
Char *cp; | wchar_t *cp; | ||||
for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++) | for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++) | ||||
*cp = cp[1]; | *cp = cp[1]; | ||||
el->el_line.lastchar--; | el->el_line.lastchar--; | ||||
} | } | ||||
/* ce__isword(): | /* ce__isword(): | ||||
* Return if p is part of a word according to emacs | * Return if p is part of a word according to emacs | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
ce__isword(wint_t p) | ce__isword(wint_t p) | ||||
{ | { | ||||
return Isalnum(p) || Strchr(STR("*?_-.[]~="), p) != NULL; | return iswalnum(p) || wcschr(L"*?_-.[]~=", p) != NULL; | ||||
} | } | ||||
/* cv__isword(): | /* cv__isword(): | ||||
* Return if p is part of a word according to vi | * Return if p is part of a word according to vi | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
cv__isword(wint_t p) | cv__isword(wint_t p) | ||||
{ | { | ||||
if (Isalnum(p) || p == '_') | if (iswalnum(p) || p == L'_') | ||||
return 1; | return 1; | ||||
if (Isgraph(p)) | if (iswgraph(p)) | ||||
return 2; | return 2; | ||||
return 0; | return 0; | ||||
} | } | ||||
/* cv__isWord(): | /* cv__isWord(): | ||||
* Return if p is part of a big word according to vi | * Return if p is part of a big word according to vi | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
cv__isWord(wint_t p) | cv__isWord(wint_t p) | ||||
{ | { | ||||
return !Isspace(p); | return !iswspace(p); | ||||
} | } | ||||
/* c__prev_word(): | /* c__prev_word(): | ||||
* Find the previous word | * Find the previous word | ||||
*/ | */ | ||||
protected Char * | libedit_private wchar_t * | ||||
c__prev_word(Char *p, Char *low, int n, int (*wtest)(wint_t)) | c__prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t)) | ||||
{ | { | ||||
p--; | p--; | ||||
while (n--) { | while (n--) { | ||||
while ((p >= low) && !(*wtest)(*p)) | while ((p >= low) && !(*wtest)(*p)) | ||||
p--; | p--; | ||||
while ((p >= low) && (*wtest)(*p)) | while ((p >= low) && (*wtest)(*p)) | ||||
p--; | p--; | ||||
} | } | ||||
/* cp now points to one character before the word */ | /* cp now points to one character before the word */ | ||||
p++; | p++; | ||||
if (p < low) | if (p < low) | ||||
p = low; | p = low; | ||||
/* cp now points where we want it */ | /* cp now points where we want it */ | ||||
return p; | return p; | ||||
} | } | ||||
/* c__next_word(): | /* c__next_word(): | ||||
* Find the next word | * Find the next word | ||||
*/ | */ | ||||
protected Char * | libedit_private wchar_t * | ||||
c__next_word(Char *p, Char *high, int n, int (*wtest)(wint_t)) | c__next_word(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t)) | ||||
{ | { | ||||
while (n--) { | while (n--) { | ||||
while ((p < high) && !(*wtest)(*p)) | while ((p < high) && !(*wtest)(*p)) | ||||
p++; | p++; | ||||
while ((p < high) && (*wtest)(*p)) | while ((p < high) && (*wtest)(*p)) | ||||
p++; | p++; | ||||
} | } | ||||
if (p > high) | if (p > high) | ||||
p = high; | p = high; | ||||
/* p now points where we want it */ | /* p now points where we want it */ | ||||
return p; | return p; | ||||
} | } | ||||
/* cv_next_word(): | /* cv_next_word(): | ||||
* Find the next word vi style | * Find the next word vi style | ||||
*/ | */ | ||||
protected Char * | libedit_private wchar_t * | ||||
cv_next_word(EditLine *el, Char *p, Char *high, int n, int (*wtest)(wint_t)) | cv_next_word(EditLine *el, wchar_t *p, wchar_t *high, int n, | ||||
int (*wtest)(wint_t)) | |||||
{ | { | ||||
int test; | int test; | ||||
while (n--) { | while (n--) { | ||||
test = (*wtest)(*p); | test = (*wtest)(*p); | ||||
while ((p < high) && (*wtest)(*p) == test) | while ((p < high) && (*wtest)(*p) == test) | ||||
p++; | p++; | ||||
/* | /* | ||||
* vi historically deletes with cw only the word preserving the | * vi historically deletes with cw only the word preserving the | ||||
* trailing whitespace! This is not what 'w' does.. | * trailing whitespace! This is not what 'w' does.. | ||||
*/ | */ | ||||
if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT)) | if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT)) | ||||
while ((p < high) && Isspace(*p)) | while ((p < high) && iswspace(*p)) | ||||
p++; | p++; | ||||
} | } | ||||
/* p now points where we want it */ | /* p now points where we want it */ | ||||
if (p > high) | if (p > high) | ||||
return high; | return high; | ||||
else | else | ||||
return p; | return p; | ||||
} | } | ||||
/* cv_prev_word(): | /* cv_prev_word(): | ||||
* Find the previous word vi style | * Find the previous word vi style | ||||
*/ | */ | ||||
protected Char * | libedit_private wchar_t * | ||||
cv_prev_word(Char *p, Char *low, int n, int (*wtest)(wint_t)) | cv_prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t)) | ||||
{ | { | ||||
int test; | int test; | ||||
p--; | p--; | ||||
while (n--) { | while (n--) { | ||||
while ((p > low) && Isspace(*p)) | while ((p > low) && iswspace(*p)) | ||||
p--; | p--; | ||||
test = (*wtest)(*p); | test = (*wtest)(*p); | ||||
while ((p >= low) && (*wtest)(*p) == test) | while ((p >= low) && (*wtest)(*p) == test) | ||||
p--; | p--; | ||||
} | } | ||||
p++; | p++; | ||||
/* p now points where we want it */ | /* p now points where we want it */ | ||||
if (p < low) | if (p < low) | ||||
return low; | return low; | ||||
else | else | ||||
return p; | return p; | ||||
} | } | ||||
/* cv_delfini(): | /* cv_delfini(): | ||||
* Finish vi delete action | * Finish vi delete action | ||||
*/ | */ | ||||
protected void | libedit_private void | ||||
cv_delfini(EditLine *el) | cv_delfini(EditLine *el) | ||||
{ | { | ||||
int size; | int size; | ||||
int action = el->el_chared.c_vcmd.action; | int action = el->el_chared.c_vcmd.action; | ||||
if (action & INSERT) | if (action & INSERT) | ||||
el->el_map.current = el->el_map.key; | el->el_map.current = el->el_map.key; | ||||
Show All 21 Lines | cv_delfini(EditLine *el) | ||||
} | } | ||||
el->el_chared.c_vcmd.action = NOP; | el->el_chared.c_vcmd.action = NOP; | ||||
} | } | ||||
/* cv__endword(): | /* cv__endword(): | ||||
* Go to the end of this word according to vi | * Go to the end of this word according to vi | ||||
*/ | */ | ||||
protected Char * | libedit_private wchar_t * | ||||
cv__endword(Char *p, Char *high, int n, int (*wtest)(wint_t)) | cv__endword(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t)) | ||||
{ | { | ||||
int test; | int test; | ||||
p++; | p++; | ||||
while (n--) { | while (n--) { | ||||
while ((p < high) && Isspace(*p)) | while ((p < high) && iswspace(*p)) | ||||
p++; | p++; | ||||
test = (*wtest)(*p); | test = (*wtest)(*p); | ||||
while ((p < high) && (*wtest)(*p) == test) | while ((p < high) && (*wtest)(*p) == test) | ||||
p++; | p++; | ||||
} | } | ||||
p--; | p--; | ||||
return p; | return p; | ||||
} | } | ||||
/* ch_init(): | /* ch_init(): | ||||
* Initialize the character editor | * Initialize the character editor | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
ch_init(EditLine *el) | ch_init(EditLine *el) | ||||
{ | { | ||||
c_macro_t *ma = &el->el_chared.c_macro; | el->el_line.buffer = el_calloc(EL_BUFSIZ, | ||||
el->el_line.buffer = el_malloc(EL_BUFSIZ * | |||||
sizeof(*el->el_line.buffer)); | sizeof(*el->el_line.buffer)); | ||||
if (el->el_line.buffer == NULL) | if (el->el_line.buffer == NULL) | ||||
return -1; | return -1; | ||||
(void) memset(el->el_line.buffer, 0, EL_BUFSIZ * | |||||
sizeof(*el->el_line.buffer)); | |||||
el->el_line.cursor = el->el_line.buffer; | el->el_line.cursor = el->el_line.buffer; | ||||
el->el_line.lastchar = el->el_line.buffer; | el->el_line.lastchar = el->el_line.buffer; | ||||
el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE]; | el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE]; | ||||
el->el_chared.c_undo.buf = el_malloc(EL_BUFSIZ * | el->el_chared.c_undo.buf = el_calloc(EL_BUFSIZ, | ||||
sizeof(*el->el_chared.c_undo.buf)); | sizeof(*el->el_chared.c_undo.buf)); | ||||
if (el->el_chared.c_undo.buf == NULL) | if (el->el_chared.c_undo.buf == NULL) | ||||
return -1; | return -1; | ||||
(void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ * | |||||
sizeof(*el->el_chared.c_undo.buf)); | |||||
el->el_chared.c_undo.len = -1; | el->el_chared.c_undo.len = -1; | ||||
el->el_chared.c_undo.cursor = 0; | el->el_chared.c_undo.cursor = 0; | ||||
el->el_chared.c_redo.buf = el_malloc(EL_BUFSIZ * | el->el_chared.c_redo.buf = el_calloc(EL_BUFSIZ, | ||||
sizeof(*el->el_chared.c_redo.buf)); | sizeof(*el->el_chared.c_redo.buf)); | ||||
if (el->el_chared.c_redo.buf == NULL) | if (el->el_chared.c_redo.buf == NULL) | ||||
return -1; | return -1; | ||||
el->el_chared.c_redo.pos = el->el_chared.c_redo.buf; | el->el_chared.c_redo.pos = el->el_chared.c_redo.buf; | ||||
el->el_chared.c_redo.lim = el->el_chared.c_redo.buf + EL_BUFSIZ; | el->el_chared.c_redo.lim = el->el_chared.c_redo.buf + EL_BUFSIZ; | ||||
el->el_chared.c_redo.cmd = ED_UNASSIGNED; | el->el_chared.c_redo.cmd = ED_UNASSIGNED; | ||||
el->el_chared.c_vcmd.action = NOP; | el->el_chared.c_vcmd.action = NOP; | ||||
el->el_chared.c_vcmd.pos = el->el_line.buffer; | el->el_chared.c_vcmd.pos = el->el_line.buffer; | ||||
el->el_chared.c_kill.buf = el_malloc(EL_BUFSIZ * | el->el_chared.c_kill.buf = el_calloc(EL_BUFSIZ, | ||||
sizeof(*el->el_chared.c_kill.buf)); | sizeof(*el->el_chared.c_kill.buf)); | ||||
if (el->el_chared.c_kill.buf == NULL) | if (el->el_chared.c_kill.buf == NULL) | ||||
return -1; | return -1; | ||||
(void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ * | |||||
sizeof(*el->el_chared.c_kill.buf)); | |||||
el->el_chared.c_kill.mark = el->el_line.buffer; | el->el_chared.c_kill.mark = el->el_line.buffer; | ||||
el->el_chared.c_kill.last = el->el_chared.c_kill.buf; | el->el_chared.c_kill.last = el->el_chared.c_kill.buf; | ||||
el->el_chared.c_resizefun = NULL; | el->el_chared.c_resizefun = NULL; | ||||
el->el_chared.c_resizearg = NULL; | el->el_chared.c_resizearg = NULL; | ||||
el->el_chared.c_aliasfun = NULL; | el->el_chared.c_aliasfun = NULL; | ||||
el->el_chared.c_aliasarg = NULL; | el->el_chared.c_aliasarg = NULL; | ||||
el->el_map.current = el->el_map.key; | el->el_map.current = el->el_map.key; | ||||
el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ | el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ | ||||
el->el_state.doingarg = 0; | el->el_state.doingarg = 0; | ||||
el->el_state.metanext = 0; | el->el_state.metanext = 0; | ||||
el->el_state.argument = 1; | el->el_state.argument = 1; | ||||
el->el_state.lastcmd = ED_UNASSIGNED; | el->el_state.lastcmd = ED_UNASSIGNED; | ||||
ma->level = -1; | |||||
ma->offset = 0; | |||||
ma->macro = el_malloc(EL_MAXMACRO * sizeof(*ma->macro)); | |||||
if (ma->macro == NULL) | |||||
return -1; | |||||
return 0; | return 0; | ||||
} | } | ||||
/* ch_reset(): | /* ch_reset(): | ||||
* Reset the character editor | * Reset the character editor | ||||
*/ | */ | ||||
protected void | libedit_private void | ||||
ch_reset(EditLine *el, int mclear) | ch_reset(EditLine *el) | ||||
{ | { | ||||
el->el_line.cursor = el->el_line.buffer; | el->el_line.cursor = el->el_line.buffer; | ||||
el->el_line.lastchar = el->el_line.buffer; | el->el_line.lastchar = el->el_line.buffer; | ||||
el->el_chared.c_undo.len = -1; | el->el_chared.c_undo.len = -1; | ||||
el->el_chared.c_undo.cursor = 0; | el->el_chared.c_undo.cursor = 0; | ||||
el->el_chared.c_vcmd.action = NOP; | el->el_chared.c_vcmd.action = NOP; | ||||
el->el_chared.c_vcmd.pos = el->el_line.buffer; | el->el_chared.c_vcmd.pos = el->el_line.buffer; | ||||
el->el_chared.c_kill.mark = el->el_line.buffer; | el->el_chared.c_kill.mark = el->el_line.buffer; | ||||
el->el_map.current = el->el_map.key; | el->el_map.current = el->el_map.key; | ||||
el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ | el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ | ||||
el->el_state.doingarg = 0; | el->el_state.doingarg = 0; | ||||
el->el_state.metanext = 0; | el->el_state.metanext = 0; | ||||
el->el_state.argument = 1; | el->el_state.argument = 1; | ||||
el->el_state.lastcmd = ED_UNASSIGNED; | el->el_state.lastcmd = ED_UNASSIGNED; | ||||
el->el_history.eventno = 0; | el->el_history.eventno = 0; | ||||
if (mclear) | |||||
ch__clearmacro(el); | |||||
} | } | ||||
private void | |||||
ch__clearmacro(EditLine *el) | |||||
{ | |||||
c_macro_t *ma = &el->el_chared.c_macro; | |||||
while (ma->level >= 0) | |||||
el_free(ma->macro[ma->level--]); | |||||
} | |||||
/* ch_enlargebufs(): | /* ch_enlargebufs(): | ||||
* Enlarge line buffer to be able to hold twice as much characters. | * Enlarge line buffer to be able to hold twice as much characters. | ||||
* Returns 1 if successful, 0 if not. | * Returns 1 if successful, 0 if not. | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
ch_enlargebufs(EditLine *el, size_t addlen) | ch_enlargebufs(EditLine *el, size_t addlen) | ||||
{ | { | ||||
size_t sz, newsz; | size_t sz, newsz; | ||||
Char *newbuffer, *oldbuf, *oldkbuf; | wchar_t *newbuffer, *oldbuf, *oldkbuf; | ||||
sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE); | sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE); | ||||
newsz = sz * 2; | newsz = sz * 2; | ||||
/* | /* | ||||
* If newly required length is longer than current buffer, we need | * If newly required length is longer than current buffer, we need | ||||
* to make the buffer big enough to hold both old and new stuff. | * to make the buffer big enough to hold both old and new stuff. | ||||
*/ | */ | ||||
if (addlen > sz) { | if (addlen > sz) { | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | ch_enlargebufs(EditLine *el, size_t addlen) | ||||
if (el->el_chared.c_resizefun) | if (el->el_chared.c_resizefun) | ||||
(*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg); | (*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg); | ||||
return 1; | return 1; | ||||
} | } | ||||
/* ch_end(): | /* ch_end(): | ||||
* Free the data structures used by the editor | * Free the data structures used by the editor | ||||
*/ | */ | ||||
protected void | libedit_private void | ||||
ch_end(EditLine *el) | ch_end(EditLine *el) | ||||
{ | { | ||||
el_free(el->el_line.buffer); | el_free(el->el_line.buffer); | ||||
el->el_line.buffer = NULL; | el->el_line.buffer = NULL; | ||||
el->el_line.limit = NULL; | el->el_line.limit = NULL; | ||||
el_free(el->el_chared.c_undo.buf); | el_free(el->el_chared.c_undo.buf); | ||||
el->el_chared.c_undo.buf = NULL; | el->el_chared.c_undo.buf = NULL; | ||||
el_free(el->el_chared.c_redo.buf); | el_free(el->el_chared.c_redo.buf); | ||||
el->el_chared.c_redo.buf = NULL; | el->el_chared.c_redo.buf = NULL; | ||||
el->el_chared.c_redo.pos = NULL; | el->el_chared.c_redo.pos = NULL; | ||||
el->el_chared.c_redo.lim = NULL; | el->el_chared.c_redo.lim = NULL; | ||||
el->el_chared.c_redo.cmd = ED_UNASSIGNED; | el->el_chared.c_redo.cmd = ED_UNASSIGNED; | ||||
el_free(el->el_chared.c_kill.buf); | el_free(el->el_chared.c_kill.buf); | ||||
el->el_chared.c_kill.buf = NULL; | el->el_chared.c_kill.buf = NULL; | ||||
ch_reset(el, 1); | ch_reset(el); | ||||
el_free(el->el_chared.c_macro.macro); | |||||
el->el_chared.c_macro.macro = NULL; | |||||
} | } | ||||
/* el_insertstr(): | /* el_insertstr(): | ||||
* Insert string at cursorI | * Insert string at cursor | ||||
*/ | */ | ||||
public int | int | ||||
FUN(el,insertstr)(EditLine *el, const Char *s) | el_winsertstr(EditLine *el, const wchar_t *s) | ||||
{ | { | ||||
size_t len; | size_t len; | ||||
if (s == NULL || (len = Strlen(s)) == 0) | if (s == NULL || (len = wcslen(s)) == 0) | ||||
return -1; | return -1; | ||||
if (el->el_line.lastchar + len >= el->el_line.limit) { | if (el->el_line.lastchar + len >= el->el_line.limit) { | ||||
if (!ch_enlargebufs(el, len)) | if (!ch_enlargebufs(el, len)) | ||||
return -1; | return -1; | ||||
} | } | ||||
c_insert(el, (int)len); | c_insert(el, (int)len); | ||||
while (*s) | while (*s) | ||||
*el->el_line.cursor++ = *s++; | *el->el_line.cursor++ = *s++; | ||||
return 0; | return 0; | ||||
} | } | ||||
/* el_deletestr(): | /* el_deletestr(): | ||||
* Delete num characters before the cursor | * Delete num characters before the cursor | ||||
*/ | */ | ||||
public void | void | ||||
el_deletestr(EditLine *el, int n) | el_deletestr(EditLine *el, int n) | ||||
{ | { | ||||
if (n <= 0) | if (n <= 0) | ||||
return; | return; | ||||
if (el->el_line.cursor < &el->el_line.buffer[n]) | if (el->el_line.cursor < &el->el_line.buffer[n]) | ||||
return; | return; | ||||
c_delbefore(el, n); /* delete before dot */ | c_delbefore(el, n); /* delete before dot */ | ||||
el->el_line.cursor -= n; | el->el_line.cursor -= n; | ||||
if (el->el_line.cursor < el->el_line.buffer) | if (el->el_line.cursor < el->el_line.buffer) | ||||
el->el_line.cursor = el->el_line.buffer; | el->el_line.cursor = el->el_line.buffer; | ||||
} | } | ||||
/* el_cursor(): | /* el_cursor(): | ||||
* Move the cursor to the left or the right of the current position | * Move the cursor to the left or the right of the current position | ||||
*/ | */ | ||||
public int | int | ||||
el_cursor(EditLine *el, int n) | el_cursor(EditLine *el, int n) | ||||
{ | { | ||||
if (n == 0) | if (n == 0) | ||||
goto out; | goto out; | ||||
el->el_line.cursor += n; | el->el_line.cursor += n; | ||||
if (el->el_line.cursor < el->el_line.buffer) | if (el->el_line.cursor < el->el_line.buffer) | ||||
el->el_line.cursor = el->el_line.buffer; | el->el_line.cursor = el->el_line.buffer; | ||||
if (el->el_line.cursor > el->el_line.lastchar) | if (el->el_line.cursor > el->el_line.lastchar) | ||||
el->el_line.cursor = el->el_line.lastchar; | el->el_line.cursor = el->el_line.lastchar; | ||||
out: | out: | ||||
return (int)(el->el_line.cursor - el->el_line.buffer); | return (int)(el->el_line.cursor - el->el_line.buffer); | ||||
} | } | ||||
/* c_gets(): | /* c_gets(): | ||||
* Get a string | * Get a string | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
c_gets(EditLine *el, Char *buf, const Char *prompt) | c_gets(EditLine *el, wchar_t *buf, const wchar_t *prompt) | ||||
{ | { | ||||
wchar_t wch; | |||||
ssize_t len; | ssize_t len; | ||||
Char *cp = el->el_line.buffer, ch; | wchar_t *cp = el->el_line.buffer, ch; | ||||
if (prompt) { | if (prompt) { | ||||
len = (ssize_t)Strlen(prompt); | len = (ssize_t)wcslen(prompt); | ||||
(void)memcpy(cp, prompt, (size_t)len * sizeof(*cp)); | (void)memcpy(cp, prompt, (size_t)len * sizeof(*cp)); | ||||
cp += len; | cp += len; | ||||
} | } | ||||
len = 0; | len = 0; | ||||
for (;;) { | for (;;) { | ||||
el->el_line.cursor = cp; | el->el_line.cursor = cp; | ||||
*cp = ' '; | *cp = ' '; | ||||
el->el_line.lastchar = cp + 1; | el->el_line.lastchar = cp + 1; | ||||
re_refresh(el); | re_refresh(el); | ||||
if (el_wgetc(el, &wch) != 1) { | if (el_wgetc(el, &ch) != 1) { | ||||
ed_end_of_file(el, 0); | ed_end_of_file(el, 0); | ||||
len = -1; | len = -1; | ||||
break; | break; | ||||
} | } | ||||
ch = (Char)wch; | |||||
switch (ch) { | switch (ch) { | ||||
case L'\b': /* Delete and backspace */ | case L'\b': /* Delete and backspace */ | ||||
case 0177: | case 0177: | ||||
if (len == 0) { | if (len == 0) { | ||||
len = -1; | len = -1; | ||||
break; | break; | ||||
Show All 25 Lines | c_gets(EditLine *el, wchar_t *buf, const wchar_t *prompt) | ||||
el->el_line.cursor = el->el_line.buffer; | el->el_line.cursor = el->el_line.buffer; | ||||
return (int)len; | return (int)len; | ||||
} | } | ||||
/* c_hpos(): | /* c_hpos(): | ||||
* Return the current horizontal position of the cursor | * Return the current horizontal position of the cursor | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
c_hpos(EditLine *el) | c_hpos(EditLine *el) | ||||
{ | { | ||||
Char *ptr; | wchar_t *ptr; | ||||
/* | /* | ||||
* Find how many characters till the beginning of this line. | * Find how many characters till the beginning of this line. | ||||
*/ | */ | ||||
if (el->el_line.cursor == el->el_line.buffer) | if (el->el_line.cursor == el->el_line.buffer) | ||||
return 0; | return 0; | ||||
else { | else { | ||||
for (ptr = el->el_line.cursor - 1; | for (ptr = el->el_line.cursor - 1; | ||||
ptr >= el->el_line.buffer && *ptr != '\n'; | ptr >= el->el_line.buffer && *ptr != '\n'; | ||||
ptr--) | ptr--) | ||||
continue; | continue; | ||||
return (int)(el->el_line.cursor - ptr - 1); | return (int)(el->el_line.cursor - ptr - 1); | ||||
} | } | ||||
} | } | ||||
protected int | libedit_private int | ||||
ch_resizefun(EditLine *el, el_zfunc_t f, void *a) | ch_resizefun(EditLine *el, el_zfunc_t f, void *a) | ||||
{ | { | ||||
el->el_chared.c_resizefun = f; | el->el_chared.c_resizefun = f; | ||||
el->el_chared.c_resizearg = a; | el->el_chared.c_resizearg = a; | ||||
return 0; | return 0; | ||||
} | } | ||||
protected int | libedit_private int | ||||
ch_aliasfun(EditLine *el, el_afunc_t f, void *a) | ch_aliasfun(EditLine *el, el_afunc_t f, void *a) | ||||
{ | { | ||||
el->el_chared.c_aliasfun = f; | el->el_chared.c_aliasfun = f; | ||||
el->el_chared.c_aliasarg = a; | el->el_chared.c_aliasarg = a; | ||||
return 0; | return 0; | ||||
} | } |