1c84f3f3cSopenharmony_ci/* $OpenBSD: edit.c,v 1.41 2015/09/01 13:12:31 tedu Exp $ */ 2c84f3f3cSopenharmony_ci/* $OpenBSD: edit.h,v 1.9 2011/05/30 17:14:35 martynas Exp $ */ 3c84f3f3cSopenharmony_ci/* $OpenBSD: emacs.c,v 1.52 2015/09/10 22:48:58 nicm Exp $ */ 4c84f3f3cSopenharmony_ci/* $OpenBSD: vi.c,v 1.30 2015/09/10 22:48:58 nicm Exp $ */ 5c84f3f3cSopenharmony_ci 6c84f3f3cSopenharmony_ci/*- 7c84f3f3cSopenharmony_ci * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 8c84f3f3cSopenharmony_ci * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 9c84f3f3cSopenharmony_ci * 2019, 2020 10c84f3f3cSopenharmony_ci * mirabilos <m@mirbsd.org> 11c84f3f3cSopenharmony_ci * 12c84f3f3cSopenharmony_ci * Provided that these terms and disclaimer and all copyright notices 13c84f3f3cSopenharmony_ci * are retained or reproduced in an accompanying document, permission 14c84f3f3cSopenharmony_ci * is granted to deal in this work without restriction, including un- 15c84f3f3cSopenharmony_ci * limited rights to use, publicly perform, distribute, sell, modify, 16c84f3f3cSopenharmony_ci * merge, give away, or sublicence. 17c84f3f3cSopenharmony_ci * 18c84f3f3cSopenharmony_ci * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 19c84f3f3cSopenharmony_ci * the utmost extent permitted by applicable law, neither express nor 20c84f3f3cSopenharmony_ci * implied; without malicious intent or gross negligence. In no event 21c84f3f3cSopenharmony_ci * may a licensor, author or contributor be held liable for indirect, 22c84f3f3cSopenharmony_ci * direct, other damage, loss, or other issues arising in any way out 23c84f3f3cSopenharmony_ci * of dealing in the work, even if advised of the possibility of such 24c84f3f3cSopenharmony_ci * damage or existence of a defect, except proven that it results out 25c84f3f3cSopenharmony_ci * of said person's immediate fault when using the work as intended. 26c84f3f3cSopenharmony_ci */ 27c84f3f3cSopenharmony_ci 28c84f3f3cSopenharmony_ci#include "sh.h" 29c84f3f3cSopenharmony_ci 30c84f3f3cSopenharmony_ci#ifndef MKSH_NO_CMDLINE_EDITING 31c84f3f3cSopenharmony_ci 32c84f3f3cSopenharmony_ci__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.357 2020/10/31 05:02:17 tg Exp $"); 33c84f3f3cSopenharmony_ci 34c84f3f3cSopenharmony_ci/* 35c84f3f3cSopenharmony_ci * in later versions we might use libtermcap for this, but since external 36c84f3f3cSopenharmony_ci * dependencies are problematic, this has not yet been decided on; another 37c84f3f3cSopenharmony_ci * good string is KSH_ESC_STRING "c" except on hardware terminals like the 38c84f3f3cSopenharmony_ci * DEC VT420 which do a full power cycle then... 39c84f3f3cSopenharmony_ci */ 40c84f3f3cSopenharmony_ci#ifndef MKSH_CLS_STRING 41c84f3f3cSopenharmony_ci#define MKSH_CLS_STRING KSH_ESC_STRING "[;H" KSH_ESC_STRING "[J" 42c84f3f3cSopenharmony_ci#endif 43c84f3f3cSopenharmony_ci 44c84f3f3cSopenharmony_ci#if !defined(MKSH_SMALL) || !MKSH_S_NOVI 45c84f3f3cSopenharmony_cistatic const char ctrl_x_e[] = "fc -e \"${VISUAL:-${EDITOR:-vi}}\" --"; 46c84f3f3cSopenharmony_ci#endif 47c84f3f3cSopenharmony_ci 48c84f3f3cSopenharmony_ci/* tty driver characters we are interested in */ 49c84f3f3cSopenharmony_ci#define EDCHAR_DISABLED 0xFFFFU 50c84f3f3cSopenharmony_ci#define EDCHAR_INITIAL 0xFFFEU 51c84f3f3cSopenharmony_cistatic struct { 52c84f3f3cSopenharmony_ci unsigned short erase; 53c84f3f3cSopenharmony_ci unsigned short kill; 54c84f3f3cSopenharmony_ci unsigned short werase; 55c84f3f3cSopenharmony_ci unsigned short intr; 56c84f3f3cSopenharmony_ci unsigned short quit; 57c84f3f3cSopenharmony_ci unsigned short eof; 58c84f3f3cSopenharmony_ci} edchars; 59c84f3f3cSopenharmony_ci 60c84f3f3cSopenharmony_ci#define isched(x,e) ((unsigned short)(unsigned char)(x) == (e)) 61c84f3f3cSopenharmony_ci#define isedchar(x) (!((x) & ~0xFF)) 62c84f3f3cSopenharmony_ci#ifndef _POSIX_VDISABLE 63c84f3f3cSopenharmony_ci#define toedchar(x) ((unsigned short)(unsigned char)(x)) 64c84f3f3cSopenharmony_ci#else 65c84f3f3cSopenharmony_ci#define toedchar(x) (((_POSIX_VDISABLE != -1) && ((x) == _POSIX_VDISABLE)) ? \ 66c84f3f3cSopenharmony_ci ((unsigned short)EDCHAR_DISABLED) : \ 67c84f3f3cSopenharmony_ci ((unsigned short)(unsigned char)(x))) 68c84f3f3cSopenharmony_ci#endif 69c84f3f3cSopenharmony_ci 70c84f3f3cSopenharmony_ci/* x_cf_glob() flags */ 71c84f3f3cSopenharmony_ci#define XCF_COMMAND BIT(0) /* Do command completion */ 72c84f3f3cSopenharmony_ci#define XCF_FILE BIT(1) /* Do file completion */ 73c84f3f3cSopenharmony_ci#define XCF_FULLPATH BIT(2) /* command completion: store full path */ 74c84f3f3cSopenharmony_ci#define XCF_COMMAND_FILE (XCF_COMMAND | XCF_FILE) 75c84f3f3cSopenharmony_ci#define XCF_IS_COMMAND BIT(3) /* return flag: is command */ 76c84f3f3cSopenharmony_ci#define XCF_IS_NOSPACE BIT(4) /* return flag: do not append a space */ 77c84f3f3cSopenharmony_ci 78c84f3f3cSopenharmony_cistatic char editmode; 79c84f3f3cSopenharmony_cistatic int xx_cols; /* for Emacs mode */ 80c84f3f3cSopenharmony_cistatic int modified; /* buffer has been "modified" */ 81c84f3f3cSopenharmony_cistatic char *holdbufp; /* place to hold last edit buffer */ 82c84f3f3cSopenharmony_ci 83c84f3f3cSopenharmony_ci/* 0=dumb 1=tmux (for now) */ 84c84f3f3cSopenharmony_cistatic uint8_t x_term_mode; 85c84f3f3cSopenharmony_ci 86c84f3f3cSopenharmony_cistatic void x_adjust(void); 87c84f3f3cSopenharmony_cistatic int x_getc(void); 88c84f3f3cSopenharmony_cistatic void x_putcf(int); 89c84f3f3cSopenharmony_cistatic void x_modified(void); 90c84f3f3cSopenharmony_cistatic void x_mode(bool); 91c84f3f3cSopenharmony_cistatic int x_do_comment(char *, ssize_t, ssize_t *); 92c84f3f3cSopenharmony_cistatic void x_print_expansions(int, char * const *, bool); 93c84f3f3cSopenharmony_cistatic int x_cf_glob(int *, const char *, int, int, int *, int *, char ***); 94c84f3f3cSopenharmony_cistatic size_t x_longest_prefix(int, char * const *); 95c84f3f3cSopenharmony_cistatic void x_glob_hlp_add_qchar(char *); 96c84f3f3cSopenharmony_cistatic char *x_glob_hlp_tilde_and_rem_qchar(char *, bool); 97c84f3f3cSopenharmony_cistatic size_t x_basename(const char *, const char *); 98c84f3f3cSopenharmony_cistatic void x_free_words(int, char **); 99c84f3f3cSopenharmony_cistatic int x_escape(const char *, size_t, int (*)(const char *, size_t)); 100c84f3f3cSopenharmony_cistatic int x_emacs(char *); 101c84f3f3cSopenharmony_cistatic void x_init_prompt(bool); 102c84f3f3cSopenharmony_ci#if !MKSH_S_NOVI 103c84f3f3cSopenharmony_cistatic int x_vi(char *); 104c84f3f3cSopenharmony_ci#endif 105c84f3f3cSopenharmony_cistatic void x_intr(int, int) MKSH_A_NORETURN; 106c84f3f3cSopenharmony_ci 107c84f3f3cSopenharmony_ci#define x_flush() shf_flush(shl_out) 108c84f3f3cSopenharmony_ci#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST) 109c84f3f3cSopenharmony_ci#define x_putc(c) x_putcf(c) 110c84f3f3cSopenharmony_ci#else 111c84f3f3cSopenharmony_ci#define x_putc(c) shf_putc((c), shl_out) 112c84f3f3cSopenharmony_ci#endif 113c84f3f3cSopenharmony_ci 114c84f3f3cSopenharmony_cistatic int path_order_cmp(const void *, const void *); 115c84f3f3cSopenharmony_cistatic void glob_table(const char *, XPtrV *, struct table *); 116c84f3f3cSopenharmony_cistatic void glob_path(int, const char *, XPtrV *, const char *); 117c84f3f3cSopenharmony_cistatic int x_file_glob(int *, char *, char ***); 118c84f3f3cSopenharmony_cistatic int x_command_glob(int, char *, char ***); 119c84f3f3cSopenharmony_cistatic int x_locate_word(const char *, int, int, int *, bool *); 120c84f3f3cSopenharmony_ci 121c84f3f3cSopenharmony_cistatic int x_e_getmbc(char *); 122c84f3f3cSopenharmony_ci 123c84f3f3cSopenharmony_ci/* +++ generic editing functions +++ */ 124c84f3f3cSopenharmony_ci 125c84f3f3cSopenharmony_ci/* 126c84f3f3cSopenharmony_ci * read an edited command line 127c84f3f3cSopenharmony_ci */ 128c84f3f3cSopenharmony_ciint 129c84f3f3cSopenharmony_cix_read(char *buf) 130c84f3f3cSopenharmony_ci{ 131c84f3f3cSopenharmony_ci int i; 132c84f3f3cSopenharmony_ci 133c84f3f3cSopenharmony_ci x_mode(true); 134c84f3f3cSopenharmony_ci modified = 1; 135c84f3f3cSopenharmony_ci if (Flag(FEMACS) || Flag(FGMACS)) 136c84f3f3cSopenharmony_ci i = x_emacs(buf); 137c84f3f3cSopenharmony_ci#if !MKSH_S_NOVI 138c84f3f3cSopenharmony_ci else if (Flag(FVI)) 139c84f3f3cSopenharmony_ci i = x_vi(buf); 140c84f3f3cSopenharmony_ci#endif 141c84f3f3cSopenharmony_ci else 142c84f3f3cSopenharmony_ci /* internal error */ 143c84f3f3cSopenharmony_ci i = -1; 144c84f3f3cSopenharmony_ci editmode = 0; 145c84f3f3cSopenharmony_ci x_mode(false); 146c84f3f3cSopenharmony_ci return (i); 147c84f3f3cSopenharmony_ci} 148c84f3f3cSopenharmony_ci 149c84f3f3cSopenharmony_ci/* tty I/O */ 150c84f3f3cSopenharmony_ci 151c84f3f3cSopenharmony_cistatic int 152c84f3f3cSopenharmony_cix_getc(void) 153c84f3f3cSopenharmony_ci{ 154c84f3f3cSopenharmony_ci#ifdef __OS2__ 155c84f3f3cSopenharmony_ci return (_read_kbd(0, 1, 0)); 156c84f3f3cSopenharmony_ci#else 157c84f3f3cSopenharmony_ci char c; 158c84f3f3cSopenharmony_ci ssize_t n; 159c84f3f3cSopenharmony_ci 160c84f3f3cSopenharmony_ci while ((n = blocking_read(0, &c, 1)) < 0 && errno == EINTR) 161c84f3f3cSopenharmony_ci if (trap) { 162c84f3f3cSopenharmony_ci x_mode(false); 163c84f3f3cSopenharmony_ci runtraps(0); 164c84f3f3cSopenharmony_ci#ifdef SIGWINCH 165c84f3f3cSopenharmony_ci if (got_winch) { 166c84f3f3cSopenharmony_ci change_winsz(); 167c84f3f3cSopenharmony_ci if (x_cols != xx_cols && editmode == 1) { 168c84f3f3cSopenharmony_ci /* redraw line in Emacs mode */ 169c84f3f3cSopenharmony_ci xx_cols = x_cols; 170c84f3f3cSopenharmony_ci x_init_prompt(false); 171c84f3f3cSopenharmony_ci x_adjust(); 172c84f3f3cSopenharmony_ci } 173c84f3f3cSopenharmony_ci } 174c84f3f3cSopenharmony_ci#endif 175c84f3f3cSopenharmony_ci x_mode(true); 176c84f3f3cSopenharmony_ci } 177c84f3f3cSopenharmony_ci return ((n == 1) ? (int)(unsigned char)c : -1); 178c84f3f3cSopenharmony_ci#endif 179c84f3f3cSopenharmony_ci} 180c84f3f3cSopenharmony_ci 181c84f3f3cSopenharmony_cistatic void 182c84f3f3cSopenharmony_cix_putcf(int c) 183c84f3f3cSopenharmony_ci{ 184c84f3f3cSopenharmony_ci shf_putc_i(c, shl_out); 185c84f3f3cSopenharmony_ci} 186c84f3f3cSopenharmony_ci 187c84f3f3cSopenharmony_ci/********************************* 188c84f3f3cSopenharmony_ci * Misc common code for vi/emacs * 189c84f3f3cSopenharmony_ci *********************************/ 190c84f3f3cSopenharmony_ci 191c84f3f3cSopenharmony_ci/*- 192c84f3f3cSopenharmony_ci * Handle the commenting/uncommenting of a line. 193c84f3f3cSopenharmony_ci * Returns: 194c84f3f3cSopenharmony_ci * 1 if a carriage return is indicated (comment added) 195c84f3f3cSopenharmony_ci * 0 if no return (comment removed) 196c84f3f3cSopenharmony_ci * -1 if there is an error (not enough room for comment chars) 197c84f3f3cSopenharmony_ci * If successful, *lenp contains the new length. Note: cursor should be 198c84f3f3cSopenharmony_ci * moved to the start of the line after (un)commenting. 199c84f3f3cSopenharmony_ci */ 200c84f3f3cSopenharmony_cistatic int 201c84f3f3cSopenharmony_cix_do_comment(char *buf, ssize_t bsize, ssize_t *lenp) 202c84f3f3cSopenharmony_ci{ 203c84f3f3cSopenharmony_ci ssize_t i, j, len = *lenp; 204c84f3f3cSopenharmony_ci 205c84f3f3cSopenharmony_ci if (len == 0) 206c84f3f3cSopenharmony_ci /* somewhat arbitrary - it's what AT&T ksh does */ 207c84f3f3cSopenharmony_ci return (1); 208c84f3f3cSopenharmony_ci 209c84f3f3cSopenharmony_ci /* Already commented? */ 210c84f3f3cSopenharmony_ci if (buf[0] == '#') { 211c84f3f3cSopenharmony_ci bool saw_nl = false; 212c84f3f3cSopenharmony_ci 213c84f3f3cSopenharmony_ci for (j = 0, i = 1; i < len; i++) { 214c84f3f3cSopenharmony_ci if (!saw_nl || buf[i] != '#') 215c84f3f3cSopenharmony_ci buf[j++] = buf[i]; 216c84f3f3cSopenharmony_ci saw_nl = buf[i] == '\n'; 217c84f3f3cSopenharmony_ci } 218c84f3f3cSopenharmony_ci *lenp = j; 219c84f3f3cSopenharmony_ci return (0); 220c84f3f3cSopenharmony_ci } else { 221c84f3f3cSopenharmony_ci int n = 1; 222c84f3f3cSopenharmony_ci 223c84f3f3cSopenharmony_ci /* See if there's room for the #s - 1 per \n */ 224c84f3f3cSopenharmony_ci for (i = 0; i < len; i++) 225c84f3f3cSopenharmony_ci if (buf[i] == '\n') 226c84f3f3cSopenharmony_ci n++; 227c84f3f3cSopenharmony_ci if (len + n >= bsize) 228c84f3f3cSopenharmony_ci return (-1); 229c84f3f3cSopenharmony_ci /* Now add them... */ 230c84f3f3cSopenharmony_ci for (i = len, j = len + n; --i >= 0; ) { 231c84f3f3cSopenharmony_ci if (buf[i] == '\n') 232c84f3f3cSopenharmony_ci buf[--j] = '#'; 233c84f3f3cSopenharmony_ci buf[--j] = buf[i]; 234c84f3f3cSopenharmony_ci } 235c84f3f3cSopenharmony_ci buf[0] = '#'; 236c84f3f3cSopenharmony_ci *lenp += n; 237c84f3f3cSopenharmony_ci return (1); 238c84f3f3cSopenharmony_ci } 239c84f3f3cSopenharmony_ci} 240c84f3f3cSopenharmony_ci 241c84f3f3cSopenharmony_ci/**************************************************** 242c84f3f3cSopenharmony_ci * Common file/command completion code for vi/emacs * 243c84f3f3cSopenharmony_ci ****************************************************/ 244c84f3f3cSopenharmony_ci 245c84f3f3cSopenharmony_cistatic void 246c84f3f3cSopenharmony_cix_print_expansions(int nwords, char * const *words, bool is_command) 247c84f3f3cSopenharmony_ci{ 248c84f3f3cSopenharmony_ci bool use_copy = false; 249c84f3f3cSopenharmony_ci size_t prefix_len; 250c84f3f3cSopenharmony_ci XPtrV l = { NULL, 0, 0 }; 251c84f3f3cSopenharmony_ci struct columnise_opts co; 252c84f3f3cSopenharmony_ci 253c84f3f3cSopenharmony_ci /* 254c84f3f3cSopenharmony_ci * Check if all matches are in the same directory (in this 255c84f3f3cSopenharmony_ci * case, we want to omit the directory name) 256c84f3f3cSopenharmony_ci */ 257c84f3f3cSopenharmony_ci if (!is_command && 258c84f3f3cSopenharmony_ci (prefix_len = x_longest_prefix(nwords, words)) > 0) { 259c84f3f3cSopenharmony_ci int i; 260c84f3f3cSopenharmony_ci 261c84f3f3cSopenharmony_ci /* Special case for 1 match (prefix is whole word) */ 262c84f3f3cSopenharmony_ci if (nwords == 1) 263c84f3f3cSopenharmony_ci prefix_len = x_basename(words[0], NULL); 264c84f3f3cSopenharmony_ci /* Any (non-trailing) slashes in non-common word suffixes? */ 265c84f3f3cSopenharmony_ci for (i = 0; i < nwords; i++) 266c84f3f3cSopenharmony_ci if (x_basename(words[i] + prefix_len, NULL) > 267c84f3f3cSopenharmony_ci prefix_len) 268c84f3f3cSopenharmony_ci break; 269c84f3f3cSopenharmony_ci /* All in same directory? */ 270c84f3f3cSopenharmony_ci if (i == nwords) { 271c84f3f3cSopenharmony_ci while (prefix_len > 0 && 272c84f3f3cSopenharmony_ci !mksh_cdirsep(words[0][prefix_len - 1])) 273c84f3f3cSopenharmony_ci prefix_len--; 274c84f3f3cSopenharmony_ci use_copy = true; 275c84f3f3cSopenharmony_ci XPinit(l, nwords + 1); 276c84f3f3cSopenharmony_ci for (i = 0; i < nwords; i++) 277c84f3f3cSopenharmony_ci XPput(l, words[i] + prefix_len); 278c84f3f3cSopenharmony_ci XPput(l, NULL); 279c84f3f3cSopenharmony_ci } 280c84f3f3cSopenharmony_ci } 281c84f3f3cSopenharmony_ci /* 282c84f3f3cSopenharmony_ci * Enumerate expansions 283c84f3f3cSopenharmony_ci */ 284c84f3f3cSopenharmony_ci x_putc('\r'); 285c84f3f3cSopenharmony_ci x_putc('\n'); 286c84f3f3cSopenharmony_ci co.shf = shl_out; 287c84f3f3cSopenharmony_ci co.linesep = '\n'; 288c84f3f3cSopenharmony_ci co.do_last = true; 289c84f3f3cSopenharmony_ci co.prefcol = false; 290c84f3f3cSopenharmony_ci pr_list(&co, use_copy ? (char **)XPptrv(l) : words); 291c84f3f3cSopenharmony_ci 292c84f3f3cSopenharmony_ci if (use_copy) 293c84f3f3cSopenharmony_ci /* not x_free_words() */ 294c84f3f3cSopenharmony_ci XPfree(l); 295c84f3f3cSopenharmony_ci} 296c84f3f3cSopenharmony_ci 297c84f3f3cSopenharmony_ci/* 298c84f3f3cSopenharmony_ci * Convert backslash-escaped string to QCHAR-escaped 299c84f3f3cSopenharmony_ci * string useful for globbing; loses QCHAR unless it 300c84f3f3cSopenharmony_ci * can squeeze in, eg. by previous loss of backslash 301c84f3f3cSopenharmony_ci */ 302c84f3f3cSopenharmony_cistatic void 303c84f3f3cSopenharmony_cix_glob_hlp_add_qchar(char *cp) 304c84f3f3cSopenharmony_ci{ 305c84f3f3cSopenharmony_ci char ch, *dp = cp; 306c84f3f3cSopenharmony_ci bool escaping = false; 307c84f3f3cSopenharmony_ci 308c84f3f3cSopenharmony_ci while ((ch = *cp++)) { 309c84f3f3cSopenharmony_ci if (ch == '\\' && !escaping) { 310c84f3f3cSopenharmony_ci escaping = true; 311c84f3f3cSopenharmony_ci continue; 312c84f3f3cSopenharmony_ci } 313c84f3f3cSopenharmony_ci if (escaping || (ch == QCHAR && (cp - dp) > 1)) { 314c84f3f3cSopenharmony_ci /* 315c84f3f3cSopenharmony_ci * empirically made list of chars to escape 316c84f3f3cSopenharmony_ci * for globbing as well as QCHAR itself 317c84f3f3cSopenharmony_ci */ 318c84f3f3cSopenharmony_ci switch (ord(ch)) { 319c84f3f3cSopenharmony_ci case QCHAR: 320c84f3f3cSopenharmony_ci case ORD('$'): 321c84f3f3cSopenharmony_ci case ORD('*'): 322c84f3f3cSopenharmony_ci case ORD('?'): 323c84f3f3cSopenharmony_ci case ORD('['): 324c84f3f3cSopenharmony_ci case ORD('\\'): 325c84f3f3cSopenharmony_ci case ORD('`'): 326c84f3f3cSopenharmony_ci *dp++ = QCHAR; 327c84f3f3cSopenharmony_ci break; 328c84f3f3cSopenharmony_ci } 329c84f3f3cSopenharmony_ci escaping = false; 330c84f3f3cSopenharmony_ci } 331c84f3f3cSopenharmony_ci *dp++ = ch; 332c84f3f3cSopenharmony_ci } 333c84f3f3cSopenharmony_ci *dp = '\0'; 334c84f3f3cSopenharmony_ci} 335c84f3f3cSopenharmony_ci 336c84f3f3cSopenharmony_ci/* 337c84f3f3cSopenharmony_ci * Run tilde expansion on argument string, return the result 338c84f3f3cSopenharmony_ci * after unescaping; if the flag is set, the original string 339c84f3f3cSopenharmony_ci * is freed if changed and assumed backslash-escaped, if not 340c84f3f3cSopenharmony_ci * it is assumed QCHAR-escaped 341c84f3f3cSopenharmony_ci */ 342c84f3f3cSopenharmony_cistatic char * 343c84f3f3cSopenharmony_cix_glob_hlp_tilde_and_rem_qchar(char *s, bool magic_flag) 344c84f3f3cSopenharmony_ci{ 345c84f3f3cSopenharmony_ci char ch, *cp, *dp; 346c84f3f3cSopenharmony_ci 347c84f3f3cSopenharmony_ci /* 348c84f3f3cSopenharmony_ci * On the string, check whether we have a tilde expansion, 349c84f3f3cSopenharmony_ci * and if so, discern "~foo/bar" and "~/baz" from "~blah"; 350c84f3f3cSopenharmony_ci * if we have a directory part (the former), try to expand 351c84f3f3cSopenharmony_ci */ 352c84f3f3cSopenharmony_ci if (*s == '~' && (cp = /* not sdirsep */ strchr(s, '/')) != NULL) { 353c84f3f3cSopenharmony_ci /* ok, so split into "~foo"/"bar" or "~"/"baz" */ 354c84f3f3cSopenharmony_ci *cp++ = 0; 355c84f3f3cSopenharmony_ci /* try to expand the tilde */ 356c84f3f3cSopenharmony_ci if (!(dp = do_tilde(s + 1))) { 357c84f3f3cSopenharmony_ci /* nope, revert damage */ 358c84f3f3cSopenharmony_ci *--cp = '/'; 359c84f3f3cSopenharmony_ci } else { 360c84f3f3cSopenharmony_ci /* ok, expand and replace */ 361c84f3f3cSopenharmony_ci strpathx(cp, dp, cp, 1); 362c84f3f3cSopenharmony_ci if (magic_flag) 363c84f3f3cSopenharmony_ci afree(s, ATEMP); 364c84f3f3cSopenharmony_ci s = cp; 365c84f3f3cSopenharmony_ci } 366c84f3f3cSopenharmony_ci } 367c84f3f3cSopenharmony_ci 368c84f3f3cSopenharmony_ci /* ... convert it from backslash-escaped via QCHAR-escaped... */ 369c84f3f3cSopenharmony_ci if (magic_flag) 370c84f3f3cSopenharmony_ci x_glob_hlp_add_qchar(s); 371c84f3f3cSopenharmony_ci /* ... to unescaped, for comparison with the matches */ 372c84f3f3cSopenharmony_ci cp = dp = s; 373c84f3f3cSopenharmony_ci 374c84f3f3cSopenharmony_ci while ((ch = *cp++)) { 375c84f3f3cSopenharmony_ci if (ch == QCHAR && !(ch = *cp++)) 376c84f3f3cSopenharmony_ci break; 377c84f3f3cSopenharmony_ci *dp++ = ch; 378c84f3f3cSopenharmony_ci } 379c84f3f3cSopenharmony_ci *dp = '\0'; 380c84f3f3cSopenharmony_ci 381c84f3f3cSopenharmony_ci return (s); 382c84f3f3cSopenharmony_ci} 383c84f3f3cSopenharmony_ci 384c84f3f3cSopenharmony_ci/** 385c84f3f3cSopenharmony_ci * Do file globbing: 386c84f3f3cSopenharmony_ci * - does expansion, checks for no match, etc. 387c84f3f3cSopenharmony_ci * - sets *wordsp to array of matching strings 388c84f3f3cSopenharmony_ci * - returns number of matching strings 389c84f3f3cSopenharmony_ci */ 390c84f3f3cSopenharmony_cistatic int 391c84f3f3cSopenharmony_cix_file_glob(int *flagsp, char *toglob, char ***wordsp) 392c84f3f3cSopenharmony_ci{ 393c84f3f3cSopenharmony_ci char **words, *cp; 394c84f3f3cSopenharmony_ci int nwords; 395c84f3f3cSopenharmony_ci XPtrV w; 396c84f3f3cSopenharmony_ci struct source *s, *sold; 397c84f3f3cSopenharmony_ci 398c84f3f3cSopenharmony_ci /* remove all escaping backward slashes */ 399c84f3f3cSopenharmony_ci x_glob_hlp_add_qchar(toglob); 400c84f3f3cSopenharmony_ci 401c84f3f3cSopenharmony_ci /* 402c84f3f3cSopenharmony_ci * Convert "foo*" (toglob) to an array of strings (words) 403c84f3f3cSopenharmony_ci */ 404c84f3f3cSopenharmony_ci sold = source; 405c84f3f3cSopenharmony_ci s = pushs(SWSTR, ATEMP); 406c84f3f3cSopenharmony_ci s->start = s->str = toglob; 407c84f3f3cSopenharmony_ci source = s; 408c84f3f3cSopenharmony_ci if (yylex(ONEWORD | LQCHAR) != LWORD) { 409c84f3f3cSopenharmony_ci source = sold; 410c84f3f3cSopenharmony_ci internal_warningf(Tfg_badsubst); 411c84f3f3cSopenharmony_ci return (0); 412c84f3f3cSopenharmony_ci } 413c84f3f3cSopenharmony_ci source = sold; 414c84f3f3cSopenharmony_ci afree(s, ATEMP); 415c84f3f3cSopenharmony_ci XPinit(w, 32); 416c84f3f3cSopenharmony_ci cp = yylval.cp; 417c84f3f3cSopenharmony_ci while (*cp == CHAR || *cp == QCHAR) 418c84f3f3cSopenharmony_ci cp += 2; 419c84f3f3cSopenharmony_ci nwords = DOGLOB | DOTILDE | DOMARKDIRS; 420c84f3f3cSopenharmony_ci if (*cp != EOS) { 421c84f3f3cSopenharmony_ci /* probably a $FOO expansion */ 422c84f3f3cSopenharmony_ci *flagsp |= XCF_IS_NOSPACE; 423c84f3f3cSopenharmony_ci /* this always results in at most one match */ 424c84f3f3cSopenharmony_ci nwords = 0; 425c84f3f3cSopenharmony_ci } 426c84f3f3cSopenharmony_ci expand(yylval.cp, &w, nwords); 427c84f3f3cSopenharmony_ci XPput(w, NULL); 428c84f3f3cSopenharmony_ci words = (char **)XPclose(w); 429c84f3f3cSopenharmony_ci 430c84f3f3cSopenharmony_ci for (nwords = 0; words[nwords]; nwords++) 431c84f3f3cSopenharmony_ci ; 432c84f3f3cSopenharmony_ci if (nwords == 1) { 433c84f3f3cSopenharmony_ci struct stat statb; 434c84f3f3cSopenharmony_ci 435c84f3f3cSopenharmony_ci /* Expand any tilde and drop all QCHAR for comparison */ 436c84f3f3cSopenharmony_ci toglob = x_glob_hlp_tilde_and_rem_qchar(toglob, false); 437c84f3f3cSopenharmony_ci 438c84f3f3cSopenharmony_ci /* 439c84f3f3cSopenharmony_ci * Check if globbing failed (returned glob pattern), 440c84f3f3cSopenharmony_ci * but be careful (e.g. toglob == "ab*" when the file 441c84f3f3cSopenharmony_ci * "ab*" exists is not an error). 442c84f3f3cSopenharmony_ci * Also, check for empty result - happens if we tried 443c84f3f3cSopenharmony_ci * to glob something which evaluated to an empty 444c84f3f3cSopenharmony_ci * string (e.g., "$FOO" when there is no FOO, etc). 445c84f3f3cSopenharmony_ci */ 446c84f3f3cSopenharmony_ci if ((strcmp(words[0], toglob) == 0 && 447c84f3f3cSopenharmony_ci stat(words[0], &statb) < 0) || 448c84f3f3cSopenharmony_ci words[0][0] == '\0') { 449c84f3f3cSopenharmony_ci x_free_words(nwords, words); 450c84f3f3cSopenharmony_ci words = NULL; 451c84f3f3cSopenharmony_ci nwords = 0; 452c84f3f3cSopenharmony_ci } 453c84f3f3cSopenharmony_ci } 454c84f3f3cSopenharmony_ci 455c84f3f3cSopenharmony_ci if ((*wordsp = nwords ? words : NULL) == NULL && words != NULL) 456c84f3f3cSopenharmony_ci x_free_words(nwords, words); 457c84f3f3cSopenharmony_ci 458c84f3f3cSopenharmony_ci return (nwords); 459c84f3f3cSopenharmony_ci} 460c84f3f3cSopenharmony_ci 461c84f3f3cSopenharmony_ci/* Data structure used in x_command_glob() */ 462c84f3f3cSopenharmony_cistruct path_order_info { 463c84f3f3cSopenharmony_ci char *word; 464c84f3f3cSopenharmony_ci size_t base; 465c84f3f3cSopenharmony_ci size_t path_order; 466c84f3f3cSopenharmony_ci}; 467c84f3f3cSopenharmony_ci 468c84f3f3cSopenharmony_ci/* Compare routine used in x_command_glob() */ 469c84f3f3cSopenharmony_cistatic int 470c84f3f3cSopenharmony_cipath_order_cmp(const void *aa, const void *bb) 471c84f3f3cSopenharmony_ci{ 472c84f3f3cSopenharmony_ci const struct path_order_info *a = (const struct path_order_info *)aa; 473c84f3f3cSopenharmony_ci const struct path_order_info *b = (const struct path_order_info *)bb; 474c84f3f3cSopenharmony_ci int t; 475c84f3f3cSopenharmony_ci 476c84f3f3cSopenharmony_ci if ((t = ascstrcmp(a->word + a->base, b->word + b->base))) 477c84f3f3cSopenharmony_ci return (t); 478c84f3f3cSopenharmony_ci if (a->path_order > b->path_order) 479c84f3f3cSopenharmony_ci return (1); 480c84f3f3cSopenharmony_ci if (a->path_order < b->path_order) 481c84f3f3cSopenharmony_ci return (-1); 482c84f3f3cSopenharmony_ci return (0); 483c84f3f3cSopenharmony_ci} 484c84f3f3cSopenharmony_ci 485c84f3f3cSopenharmony_cistatic int 486c84f3f3cSopenharmony_cix_command_glob(int flags, char *toglob, char ***wordsp) 487c84f3f3cSopenharmony_ci{ 488c84f3f3cSopenharmony_ci char *pat, *fpath; 489c84f3f3cSopenharmony_ci size_t nwords; 490c84f3f3cSopenharmony_ci XPtrV w; 491c84f3f3cSopenharmony_ci struct block *l; 492c84f3f3cSopenharmony_ci 493c84f3f3cSopenharmony_ci /* Convert "foo*" (toglob) to a pattern for future use */ 494c84f3f3cSopenharmony_ci pat = evalstr(toglob, DOPAT | DOTILDE); 495c84f3f3cSopenharmony_ci 496c84f3f3cSopenharmony_ci XPinit(w, 32); 497c84f3f3cSopenharmony_ci 498c84f3f3cSopenharmony_ci glob_table(pat, &w, &keywords); 499c84f3f3cSopenharmony_ci glob_table(pat, &w, &aliases); 500c84f3f3cSopenharmony_ci glob_table(pat, &w, &builtins); 501c84f3f3cSopenharmony_ci for (l = e->loc; l; l = l->next) 502c84f3f3cSopenharmony_ci glob_table(pat, &w, &l->funs); 503c84f3f3cSopenharmony_ci 504c84f3f3cSopenharmony_ci glob_path(flags, pat, &w, path); 505c84f3f3cSopenharmony_ci if ((fpath = str_val(global(TFPATH))) != null) 506c84f3f3cSopenharmony_ci glob_path(flags, pat, &w, fpath); 507c84f3f3cSopenharmony_ci 508c84f3f3cSopenharmony_ci nwords = XPsize(w); 509c84f3f3cSopenharmony_ci 510c84f3f3cSopenharmony_ci if (!nwords) { 511c84f3f3cSopenharmony_ci *wordsp = NULL; 512c84f3f3cSopenharmony_ci XPfree(w); 513c84f3f3cSopenharmony_ci return (0); 514c84f3f3cSopenharmony_ci } 515c84f3f3cSopenharmony_ci /* Sort entries */ 516c84f3f3cSopenharmony_ci if (flags & XCF_FULLPATH) { 517c84f3f3cSopenharmony_ci /* Sort by basename, then path order */ 518c84f3f3cSopenharmony_ci struct path_order_info *info, *last_info = NULL; 519c84f3f3cSopenharmony_ci char **words = (char **)XPptrv(w); 520c84f3f3cSopenharmony_ci size_t i, path_order = 0; 521c84f3f3cSopenharmony_ci 522c84f3f3cSopenharmony_ci info = (struct path_order_info *) 523c84f3f3cSopenharmony_ci alloc2(nwords, sizeof(struct path_order_info), ATEMP); 524c84f3f3cSopenharmony_ci for (i = 0; i < nwords; i++) { 525c84f3f3cSopenharmony_ci info[i].word = words[i]; 526c84f3f3cSopenharmony_ci info[i].base = x_basename(words[i], NULL); 527c84f3f3cSopenharmony_ci if (!last_info || info[i].base != last_info->base || 528c84f3f3cSopenharmony_ci strncmp(words[i], last_info->word, info[i].base) != 0) { 529c84f3f3cSopenharmony_ci last_info = &info[i]; 530c84f3f3cSopenharmony_ci path_order++; 531c84f3f3cSopenharmony_ci } 532c84f3f3cSopenharmony_ci info[i].path_order = path_order; 533c84f3f3cSopenharmony_ci } 534c84f3f3cSopenharmony_ci qsort(info, nwords, sizeof(struct path_order_info), 535c84f3f3cSopenharmony_ci path_order_cmp); 536c84f3f3cSopenharmony_ci for (i = 0; i < nwords; i++) 537c84f3f3cSopenharmony_ci words[i] = info[i].word; 538c84f3f3cSopenharmony_ci afree(info, ATEMP); 539c84f3f3cSopenharmony_ci } else { 540c84f3f3cSopenharmony_ci /* Sort and remove duplicate entries */ 541c84f3f3cSopenharmony_ci char **words = (char **)XPptrv(w); 542c84f3f3cSopenharmony_ci size_t i, j; 543c84f3f3cSopenharmony_ci 544c84f3f3cSopenharmony_ci qsort(words, nwords, sizeof(void *), ascpstrcmp); 545c84f3f3cSopenharmony_ci for (i = j = 0; i < nwords - 1; i++) { 546c84f3f3cSopenharmony_ci if (strcmp(words[i], words[i + 1])) 547c84f3f3cSopenharmony_ci words[j++] = words[i]; 548c84f3f3cSopenharmony_ci else 549c84f3f3cSopenharmony_ci afree(words[i], ATEMP); 550c84f3f3cSopenharmony_ci } 551c84f3f3cSopenharmony_ci words[j++] = words[i]; 552c84f3f3cSopenharmony_ci w.len = nwords = j; 553c84f3f3cSopenharmony_ci } 554c84f3f3cSopenharmony_ci 555c84f3f3cSopenharmony_ci XPput(w, NULL); 556c84f3f3cSopenharmony_ci *wordsp = (char **)XPclose(w); 557c84f3f3cSopenharmony_ci 558c84f3f3cSopenharmony_ci return (nwords); 559c84f3f3cSopenharmony_ci} 560c84f3f3cSopenharmony_ci 561c84f3f3cSopenharmony_ci#define IS_WORDC(c) (!ctype(c, C_EDNWC)) 562c84f3f3cSopenharmony_ci 563c84f3f3cSopenharmony_cistatic int 564c84f3f3cSopenharmony_cix_locate_word(const char *buf, int buflen, int pos, int *startp, 565c84f3f3cSopenharmony_ci bool *is_commandp) 566c84f3f3cSopenharmony_ci{ 567c84f3f3cSopenharmony_ci int start, end; 568c84f3f3cSopenharmony_ci 569c84f3f3cSopenharmony_ci /* Bad call? Probably should report error */ 570c84f3f3cSopenharmony_ci if (pos < 0 || pos > buflen) { 571c84f3f3cSopenharmony_ci *startp = pos; 572c84f3f3cSopenharmony_ci *is_commandp = false; 573c84f3f3cSopenharmony_ci return (0); 574c84f3f3cSopenharmony_ci } 575c84f3f3cSopenharmony_ci /* The case where pos == buflen happens to take care of itself... */ 576c84f3f3cSopenharmony_ci 577c84f3f3cSopenharmony_ci start = pos; 578c84f3f3cSopenharmony_ci /* 579c84f3f3cSopenharmony_ci * Keep going backwards to start of word (has effect of allowing 580c84f3f3cSopenharmony_ci * one blank after the end of a word) 581c84f3f3cSopenharmony_ci */ 582c84f3f3cSopenharmony_ci for (; (start > 0 && IS_WORDC(buf[start - 1])) || 583c84f3f3cSopenharmony_ci (start > 1 && buf[start - 2] == '\\'); start--) 584c84f3f3cSopenharmony_ci ; 585c84f3f3cSopenharmony_ci /* Go forwards to end of word */ 586c84f3f3cSopenharmony_ci for (end = start; end < buflen && IS_WORDC(buf[end]); end++) { 587c84f3f3cSopenharmony_ci if (buf[end] == '\\' && (end + 1) < buflen) 588c84f3f3cSopenharmony_ci end++; 589c84f3f3cSopenharmony_ci } 590c84f3f3cSopenharmony_ci 591c84f3f3cSopenharmony_ci if (is_commandp) { 592c84f3f3cSopenharmony_ci bool iscmd; 593c84f3f3cSopenharmony_ci int p = start - 1; 594c84f3f3cSopenharmony_ci 595c84f3f3cSopenharmony_ci /* Figure out if this is a command */ 596c84f3f3cSopenharmony_ci while (p >= 0 && ctype(buf[p], C_SPACE)) 597c84f3f3cSopenharmony_ci p--; 598c84f3f3cSopenharmony_ci iscmd = p < 0 || ctype(buf[p], C_EDCMD); 599c84f3f3cSopenharmony_ci if (iscmd) { 600c84f3f3cSopenharmony_ci /* 601c84f3f3cSopenharmony_ci * If command has a /, path, etc. is not searched; 602c84f3f3cSopenharmony_ci * only current directory is searched which is just 603c84f3f3cSopenharmony_ci * like file globbing. 604c84f3f3cSopenharmony_ci */ 605c84f3f3cSopenharmony_ci for (p = start; p < end; p++) 606c84f3f3cSopenharmony_ci if (mksh_cdirsep(buf[p])) 607c84f3f3cSopenharmony_ci break; 608c84f3f3cSopenharmony_ci iscmd = p == end; 609c84f3f3cSopenharmony_ci } 610c84f3f3cSopenharmony_ci *is_commandp = iscmd; 611c84f3f3cSopenharmony_ci } 612c84f3f3cSopenharmony_ci *startp = start; 613c84f3f3cSopenharmony_ci 614c84f3f3cSopenharmony_ci return (end - start); 615c84f3f3cSopenharmony_ci} 616c84f3f3cSopenharmony_ci 617c84f3f3cSopenharmony_cistatic int 618c84f3f3cSopenharmony_cix_cf_glob(int *flagsp, const char *buf, int buflen, int pos, int *startp, 619c84f3f3cSopenharmony_ci int *endp, char ***wordsp) 620c84f3f3cSopenharmony_ci{ 621c84f3f3cSopenharmony_ci int len, nwords = 0; 622c84f3f3cSopenharmony_ci char **words = NULL; 623c84f3f3cSopenharmony_ci bool is_command; 624c84f3f3cSopenharmony_ci 625c84f3f3cSopenharmony_ci len = x_locate_word(buf, buflen, pos, startp, &is_command); 626c84f3f3cSopenharmony_ci if (!((*flagsp) & XCF_COMMAND)) 627c84f3f3cSopenharmony_ci is_command = false; 628c84f3f3cSopenharmony_ci /* 629c84f3f3cSopenharmony_ci * Don't do command globing on zero length strings - it takes too 630c84f3f3cSopenharmony_ci * long and isn't very useful. File globs are more likely to be 631c84f3f3cSopenharmony_ci * useful, so allow these. 632c84f3f3cSopenharmony_ci */ 633c84f3f3cSopenharmony_ci if (len == 0 && is_command) 634c84f3f3cSopenharmony_ci return (0); 635c84f3f3cSopenharmony_ci 636c84f3f3cSopenharmony_ci if (len >= 0) { 637c84f3f3cSopenharmony_ci char *toglob, *s; 638c84f3f3cSopenharmony_ci 639c84f3f3cSopenharmony_ci /* 640c84f3f3cSopenharmony_ci * Given a string, copy it and possibly add a '*' to the end. 641c84f3f3cSopenharmony_ci */ 642c84f3f3cSopenharmony_ci 643c84f3f3cSopenharmony_ci strndupx(toglob, buf + *startp, len + /* the '*' */ 1, ATEMP); 644c84f3f3cSopenharmony_ci toglob[len] = '\0'; 645c84f3f3cSopenharmony_ci 646c84f3f3cSopenharmony_ci /* 647c84f3f3cSopenharmony_ci * If the pathname contains a wildcard (an unquoted '*', 648c84f3f3cSopenharmony_ci * '?', or '[') or an extglob, then it is globbed based 649c84f3f3cSopenharmony_ci * on that value (i.e., without the appended '*'). Same 650c84f3f3cSopenharmony_ci * for parameter substitutions (as in “cat $HOME/.ss↹”) 651c84f3f3cSopenharmony_ci * without appending a trailing space (LP: #710539), as 652c84f3f3cSopenharmony_ci * well as for “~foo” (but not “~foo/”). 653c84f3f3cSopenharmony_ci */ 654c84f3f3cSopenharmony_ci for (s = toglob; *s; s++) { 655c84f3f3cSopenharmony_ci if (*s == '\\' && s[1]) 656c84f3f3cSopenharmony_ci s++; 657c84f3f3cSopenharmony_ci else if (ctype(*s, C_QUEST | C_DOLAR) || 658c84f3f3cSopenharmony_ci ord(*s) == ORD('*') || ord(*s) == ORD('[') || 659c84f3f3cSopenharmony_ci /* ?() *() +() @() !() but two already checked */ 660c84f3f3cSopenharmony_ci (ord(s[1]) == ORD('(' /*)*/) && 661c84f3f3cSopenharmony_ci (ord(*s) == ORD('+') || ord(*s) == ORD('@') || 662c84f3f3cSopenharmony_ci ord(*s) == ORD('!')))) { 663c84f3f3cSopenharmony_ci /* 664c84f3f3cSopenharmony_ci * just expand based on the extglob 665c84f3f3cSopenharmony_ci * or parameter 666c84f3f3cSopenharmony_ci */ 667c84f3f3cSopenharmony_ci goto dont_add_glob; 668c84f3f3cSopenharmony_ci } 669c84f3f3cSopenharmony_ci } 670c84f3f3cSopenharmony_ci 671c84f3f3cSopenharmony_ci if (*toglob == '~' && /* not vdirsep */ !vstrchr(toglob, '/')) { 672c84f3f3cSopenharmony_ci /* neither for '~foo' (but '~foo/bar') */ 673c84f3f3cSopenharmony_ci *flagsp |= XCF_IS_NOSPACE; 674c84f3f3cSopenharmony_ci goto dont_add_glob; 675c84f3f3cSopenharmony_ci } 676c84f3f3cSopenharmony_ci 677c84f3f3cSopenharmony_ci /* append a glob */ 678c84f3f3cSopenharmony_ci toglob[len] = '*'; 679c84f3f3cSopenharmony_ci toglob[len + 1] = '\0'; 680c84f3f3cSopenharmony_ci dont_add_glob: 681c84f3f3cSopenharmony_ci /* 682c84f3f3cSopenharmony_ci * Expand (glob) it now. 683c84f3f3cSopenharmony_ci */ 684c84f3f3cSopenharmony_ci 685c84f3f3cSopenharmony_ci nwords = is_command ? 686c84f3f3cSopenharmony_ci x_command_glob(*flagsp, toglob, &words) : 687c84f3f3cSopenharmony_ci x_file_glob(flagsp, toglob, &words); 688c84f3f3cSopenharmony_ci afree(toglob, ATEMP); 689c84f3f3cSopenharmony_ci } 690c84f3f3cSopenharmony_ci if (nwords == 0) { 691c84f3f3cSopenharmony_ci *wordsp = NULL; 692c84f3f3cSopenharmony_ci return (0); 693c84f3f3cSopenharmony_ci } 694c84f3f3cSopenharmony_ci if (is_command) 695c84f3f3cSopenharmony_ci *flagsp |= XCF_IS_COMMAND; 696c84f3f3cSopenharmony_ci *wordsp = words; 697c84f3f3cSopenharmony_ci *endp = *startp + len; 698c84f3f3cSopenharmony_ci 699c84f3f3cSopenharmony_ci return (nwords); 700c84f3f3cSopenharmony_ci} 701c84f3f3cSopenharmony_ci 702c84f3f3cSopenharmony_ci/* 703c84f3f3cSopenharmony_ci * Find longest common prefix 704c84f3f3cSopenharmony_ci */ 705c84f3f3cSopenharmony_cistatic size_t 706c84f3f3cSopenharmony_cix_longest_prefix(int nwords, char * const * words) 707c84f3f3cSopenharmony_ci{ 708c84f3f3cSopenharmony_ci int i; 709c84f3f3cSopenharmony_ci size_t j, prefix_len; 710c84f3f3cSopenharmony_ci char *p; 711c84f3f3cSopenharmony_ci 712c84f3f3cSopenharmony_ci if (nwords <= 0) 713c84f3f3cSopenharmony_ci return (0); 714c84f3f3cSopenharmony_ci 715c84f3f3cSopenharmony_ci prefix_len = strlen(words[0]); 716c84f3f3cSopenharmony_ci for (i = 1; i < nwords; i++) 717c84f3f3cSopenharmony_ci for (j = 0, p = words[i]; j < prefix_len; j++) 718c84f3f3cSopenharmony_ci if (p[j] != words[0][j]) { 719c84f3f3cSopenharmony_ci prefix_len = j; 720c84f3f3cSopenharmony_ci break; 721c84f3f3cSopenharmony_ci } 722c84f3f3cSopenharmony_ci /* false for nwords==1 as 0 = words[0][prefix_len] then */ 723c84f3f3cSopenharmony_ci if (UTFMODE && prefix_len && (rtt2asc(words[0][prefix_len]) & 0xC0) == 0x80) 724c84f3f3cSopenharmony_ci while (prefix_len && (rtt2asc(words[0][prefix_len]) & 0xC0) != 0xC0) 725c84f3f3cSopenharmony_ci --prefix_len; 726c84f3f3cSopenharmony_ci return (prefix_len); 727c84f3f3cSopenharmony_ci} 728c84f3f3cSopenharmony_ci 729c84f3f3cSopenharmony_cistatic void 730c84f3f3cSopenharmony_cix_free_words(int nwords, char **words) 731c84f3f3cSopenharmony_ci{ 732c84f3f3cSopenharmony_ci while (nwords) 733c84f3f3cSopenharmony_ci afree(words[--nwords], ATEMP); 734c84f3f3cSopenharmony_ci afree(words, ATEMP); 735c84f3f3cSopenharmony_ci} 736c84f3f3cSopenharmony_ci 737c84f3f3cSopenharmony_ci/*- 738c84f3f3cSopenharmony_ci * Return the offset of the basename of string s (which ends at se - need not 739c84f3f3cSopenharmony_ci * be null terminated). Trailing slashes are ignored. If s is just a slash, 740c84f3f3cSopenharmony_ci * then the offset is 0 (actually, length - 1). 741c84f3f3cSopenharmony_ci * s Return 742c84f3f3cSopenharmony_ci * /etc 1 743c84f3f3cSopenharmony_ci * /etc/ 1 744c84f3f3cSopenharmony_ci * /etc// 1 745c84f3f3cSopenharmony_ci * /etc/fo 5 746c84f3f3cSopenharmony_ci * foo 0 747c84f3f3cSopenharmony_ci * /// 2 748c84f3f3cSopenharmony_ci * 0 749c84f3f3cSopenharmony_ci */ 750c84f3f3cSopenharmony_cistatic size_t 751c84f3f3cSopenharmony_cix_basename(const char *s, const char *se) 752c84f3f3cSopenharmony_ci{ 753c84f3f3cSopenharmony_ci const char *p; 754c84f3f3cSopenharmony_ci 755c84f3f3cSopenharmony_ci if (se == NULL) 756c84f3f3cSopenharmony_ci se = strnul(s); 757c84f3f3cSopenharmony_ci if (s == se) 758c84f3f3cSopenharmony_ci return (0); 759c84f3f3cSopenharmony_ci 760c84f3f3cSopenharmony_ci /* skip trailing directory separators */ 761c84f3f3cSopenharmony_ci p = se - 1; 762c84f3f3cSopenharmony_ci while (p > s && mksh_cdirsep(*p)) 763c84f3f3cSopenharmony_ci --p; 764c84f3f3cSopenharmony_ci /* drop last component */ 765c84f3f3cSopenharmony_ci while (p > s && !mksh_cdirsep(*p)) 766c84f3f3cSopenharmony_ci --p; 767c84f3f3cSopenharmony_ci if (mksh_cdirsep(*p) && p + 1 < se) 768c84f3f3cSopenharmony_ci ++p; 769c84f3f3cSopenharmony_ci 770c84f3f3cSopenharmony_ci return (p - s); 771c84f3f3cSopenharmony_ci} 772c84f3f3cSopenharmony_ci 773c84f3f3cSopenharmony_ci/* 774c84f3f3cSopenharmony_ci * Apply pattern matching to a table: all table entries that match a pattern 775c84f3f3cSopenharmony_ci * are added to wp. 776c84f3f3cSopenharmony_ci */ 777c84f3f3cSopenharmony_cistatic void 778c84f3f3cSopenharmony_ciglob_table(const char *pat, XPtrV *wp, struct table *tp) 779c84f3f3cSopenharmony_ci{ 780c84f3f3cSopenharmony_ci struct tstate ts; 781c84f3f3cSopenharmony_ci struct tbl *te; 782c84f3f3cSopenharmony_ci 783c84f3f3cSopenharmony_ci ktwalk(&ts, tp); 784c84f3f3cSopenharmony_ci while ((te = ktnext(&ts))) 785c84f3f3cSopenharmony_ci if (gmatchx(te->name, pat, false)) { 786c84f3f3cSopenharmony_ci char *cp; 787c84f3f3cSopenharmony_ci 788c84f3f3cSopenharmony_ci strdupx(cp, te->name, ATEMP); 789c84f3f3cSopenharmony_ci XPput(*wp, cp); 790c84f3f3cSopenharmony_ci } 791c84f3f3cSopenharmony_ci} 792c84f3f3cSopenharmony_ci 793c84f3f3cSopenharmony_cistatic void 794c84f3f3cSopenharmony_ciglob_path(int flags, const char *pat, XPtrV *wp, const char *lpath) 795c84f3f3cSopenharmony_ci{ 796c84f3f3cSopenharmony_ci const char *sp = lpath, *p; 797c84f3f3cSopenharmony_ci char *xp, **words; 798c84f3f3cSopenharmony_ci size_t pathlen, patlen, oldsize, newsize, i, j; 799c84f3f3cSopenharmony_ci XString xs; 800c84f3f3cSopenharmony_ci 801c84f3f3cSopenharmony_ci patlen = strlen(pat); 802c84f3f3cSopenharmony_ci checkoktoadd(patlen, 129 + X_EXTRA); 803c84f3f3cSopenharmony_ci ++patlen; 804c84f3f3cSopenharmony_ci Xinit(xs, xp, patlen + 128, ATEMP); 805c84f3f3cSopenharmony_ci while (sp) { 806c84f3f3cSopenharmony_ci xp = Xstring(xs, xp); 807c84f3f3cSopenharmony_ci if (!(p = cstrchr(sp, MKSH_PATHSEPC))) 808c84f3f3cSopenharmony_ci p = strnul(sp); 809c84f3f3cSopenharmony_ci pathlen = p - sp; 810c84f3f3cSopenharmony_ci if (pathlen) { 811c84f3f3cSopenharmony_ci /* 812c84f3f3cSopenharmony_ci * Copy sp into xp, stuffing any MAGIC characters 813c84f3f3cSopenharmony_ci * on the way 814c84f3f3cSopenharmony_ci */ 815c84f3f3cSopenharmony_ci const char *s = sp; 816c84f3f3cSopenharmony_ci 817c84f3f3cSopenharmony_ci XcheckN(xs, xp, pathlen * 2); 818c84f3f3cSopenharmony_ci while (s < p) { 819c84f3f3cSopenharmony_ci if (ISMAGIC(*s)) 820c84f3f3cSopenharmony_ci *xp++ = MAGIC; 821c84f3f3cSopenharmony_ci *xp++ = *s++; 822c84f3f3cSopenharmony_ci } 823c84f3f3cSopenharmony_ci *xp++ = '/'; 824c84f3f3cSopenharmony_ci pathlen++; 825c84f3f3cSopenharmony_ci } 826c84f3f3cSopenharmony_ci sp = p; 827c84f3f3cSopenharmony_ci XcheckN(xs, xp, patlen); 828c84f3f3cSopenharmony_ci memcpy(xp, pat, patlen); 829c84f3f3cSopenharmony_ci 830c84f3f3cSopenharmony_ci oldsize = XPsize(*wp); 831c84f3f3cSopenharmony_ci /* mark dirs */ 832c84f3f3cSopenharmony_ci glob_str(Xstring(xs, xp), wp, true); 833c84f3f3cSopenharmony_ci newsize = XPsize(*wp); 834c84f3f3cSopenharmony_ci 835c84f3f3cSopenharmony_ci /* Check that each match is executable... */ 836c84f3f3cSopenharmony_ci words = (char **)XPptrv(*wp); 837c84f3f3cSopenharmony_ci for (i = j = oldsize; i < newsize; i++) { 838c84f3f3cSopenharmony_ci if (ksh_access(words[i], X_OK) == 0) { 839c84f3f3cSopenharmony_ci words[j] = words[i]; 840c84f3f3cSopenharmony_ci if (!(flags & XCF_FULLPATH)) 841c84f3f3cSopenharmony_ci memmove(words[j], words[j] + pathlen, 842c84f3f3cSopenharmony_ci strlen(words[j] + pathlen) + 1); 843c84f3f3cSopenharmony_ci j++; 844c84f3f3cSopenharmony_ci } else 845c84f3f3cSopenharmony_ci afree(words[i], ATEMP); 846c84f3f3cSopenharmony_ci } 847c84f3f3cSopenharmony_ci wp->len = j; 848c84f3f3cSopenharmony_ci 849c84f3f3cSopenharmony_ci if (!*sp++) 850c84f3f3cSopenharmony_ci break; 851c84f3f3cSopenharmony_ci } 852c84f3f3cSopenharmony_ci Xfree(xs, xp); 853c84f3f3cSopenharmony_ci} 854c84f3f3cSopenharmony_ci 855c84f3f3cSopenharmony_ci/* 856c84f3f3cSopenharmony_ci * if argument string contains any special characters, they will 857c84f3f3cSopenharmony_ci * be escaped and the result will be put into edit buffer by 858c84f3f3cSopenharmony_ci * keybinding-specific function 859c84f3f3cSopenharmony_ci */ 860c84f3f3cSopenharmony_cistatic int 861c84f3f3cSopenharmony_cix_escape(const char *s, size_t len, int (*putbuf_func)(const char *, size_t)) 862c84f3f3cSopenharmony_ci{ 863c84f3f3cSopenharmony_ci size_t add = 0, wlen = len; 864c84f3f3cSopenharmony_ci int rval = 0; 865c84f3f3cSopenharmony_ci 866c84f3f3cSopenharmony_ci while (wlen - add > 0) 867c84f3f3cSopenharmony_ci if (ctype(s[add], C_IFS | C_EDQ)) { 868c84f3f3cSopenharmony_ci if (putbuf_func(s, add) != 0) { 869c84f3f3cSopenharmony_ci rval = -1; 870c84f3f3cSopenharmony_ci break; 871c84f3f3cSopenharmony_ci } 872c84f3f3cSopenharmony_ci putbuf_func(s[add] == '\n' ? "'" : "\\", 1); 873c84f3f3cSopenharmony_ci putbuf_func(&s[add], 1); 874c84f3f3cSopenharmony_ci if (s[add] == '\n') 875c84f3f3cSopenharmony_ci putbuf_func("'", 1); 876c84f3f3cSopenharmony_ci 877c84f3f3cSopenharmony_ci add++; 878c84f3f3cSopenharmony_ci wlen -= add; 879c84f3f3cSopenharmony_ci s += add; 880c84f3f3cSopenharmony_ci add = 0; 881c84f3f3cSopenharmony_ci } else 882c84f3f3cSopenharmony_ci ++add; 883c84f3f3cSopenharmony_ci if (wlen > 0 && rval == 0) 884c84f3f3cSopenharmony_ci rval = putbuf_func(s, wlen); 885c84f3f3cSopenharmony_ci 886c84f3f3cSopenharmony_ci return (rval); 887c84f3f3cSopenharmony_ci} 888c84f3f3cSopenharmony_ci 889c84f3f3cSopenharmony_ci 890c84f3f3cSopenharmony_ci/* +++ emacs editing mode +++ */ 891c84f3f3cSopenharmony_ci 892c84f3f3cSopenharmony_cistatic Area aedit; 893c84f3f3cSopenharmony_ci#define AEDIT &aedit /* area for kill ring and macro defns */ 894c84f3f3cSopenharmony_ci 895c84f3f3cSopenharmony_ci/* values returned by keyboard functions */ 896c84f3f3cSopenharmony_ci#define KSTD 0 897c84f3f3cSopenharmony_ci#define KEOL 1 /* ^M, ^J */ 898c84f3f3cSopenharmony_ci#define KINTR 2 /* ^G, ^C */ 899c84f3f3cSopenharmony_ci 900c84f3f3cSopenharmony_cistruct x_ftab { 901c84f3f3cSopenharmony_ci int (*xf_func)(int c); 902c84f3f3cSopenharmony_ci const char *xf_name; 903c84f3f3cSopenharmony_ci short xf_flags; 904c84f3f3cSopenharmony_ci}; 905c84f3f3cSopenharmony_ci 906c84f3f3cSopenharmony_cistruct x_defbindings { 907c84f3f3cSopenharmony_ci unsigned char xdb_func; /* XFUNC_* */ 908c84f3f3cSopenharmony_ci unsigned char xdb_tab; 909c84f3f3cSopenharmony_ci unsigned char xdb_char; 910c84f3f3cSopenharmony_ci}; 911c84f3f3cSopenharmony_ci 912c84f3f3cSopenharmony_ci#define XF_ARG 1 /* command takes number prefix */ 913c84f3f3cSopenharmony_ci#define XF_NOBIND 2 /* not allowed to bind to function */ 914c84f3f3cSopenharmony_ci#define XF_PREFIX 4 /* function sets prefix */ 915c84f3f3cSopenharmony_ci 916c84f3f3cSopenharmony_ci#define X_NTABS 4 /* normal, meta1, meta2, pc */ 917c84f3f3cSopenharmony_ci#define X_TABSZ 256 /* size of keydef tables etc */ 918c84f3f3cSopenharmony_ci 919c84f3f3cSopenharmony_ci/*- 920c84f3f3cSopenharmony_ci * Arguments for do_complete() 921c84f3f3cSopenharmony_ci * 0 = enumerate M-= complete as much as possible and then list 922c84f3f3cSopenharmony_ci * 1 = complete M-Esc 923c84f3f3cSopenharmony_ci * 2 = list M-? 924c84f3f3cSopenharmony_ci */ 925c84f3f3cSopenharmony_citypedef enum { 926c84f3f3cSopenharmony_ci CT_LIST, /* list the possible completions */ 927c84f3f3cSopenharmony_ci CT_COMPLETE, /* complete to longest prefix */ 928c84f3f3cSopenharmony_ci CT_COMPLIST /* complete and then list (if non-exact) */ 929c84f3f3cSopenharmony_ci} Comp_type; 930c84f3f3cSopenharmony_ci 931c84f3f3cSopenharmony_ci/* 932c84f3f3cSopenharmony_ci * The following are used for my horizontal scrolling stuff 933c84f3f3cSopenharmony_ci */ 934c84f3f3cSopenharmony_cistatic char *xbuf; /* beg input buffer */ 935c84f3f3cSopenharmony_cistatic char *xend; /* end input buffer */ 936c84f3f3cSopenharmony_cistatic char *xcp; /* current position */ 937c84f3f3cSopenharmony_cistatic char *xep; /* current end */ 938c84f3f3cSopenharmony_cistatic char *xbp; /* start of visible portion of input buffer */ 939c84f3f3cSopenharmony_cistatic char *xlp; /* last char visible on screen */ 940c84f3f3cSopenharmony_cistatic bool x_adj_ok; 941c84f3f3cSopenharmony_ci/* 942c84f3f3cSopenharmony_ci * we use x_adj_done so that functions can tell 943c84f3f3cSopenharmony_ci * whether x_adjust() has been called while they are active. 944c84f3f3cSopenharmony_ci */ 945c84f3f3cSopenharmony_cistatic int x_adj_done; /* is incremented by x_adjust() */ 946c84f3f3cSopenharmony_ci 947c84f3f3cSopenharmony_cistatic int x_displen; 948c84f3f3cSopenharmony_cistatic int x_arg; /* general purpose arg */ 949c84f3f3cSopenharmony_cistatic bool x_arg_defaulted; /* x_arg not explicitly set; defaulted to 1 */ 950c84f3f3cSopenharmony_ci 951c84f3f3cSopenharmony_cistatic bool xlp_valid; /* lastvis pointer was recalculated */ 952c84f3f3cSopenharmony_ci 953c84f3f3cSopenharmony_cistatic char **x_histp; /* history position */ 954c84f3f3cSopenharmony_cistatic int x_nextcmd; /* for newline-and-next */ 955c84f3f3cSopenharmony_cistatic char **x_histncp; /* saved x_histp for " */ 956c84f3f3cSopenharmony_cistatic char **x_histmcp; /* saved x_histp for " */ 957c84f3f3cSopenharmony_cistatic char *xmp; /* mark pointer */ 958c84f3f3cSopenharmony_cistatic unsigned char x_last_command; 959c84f3f3cSopenharmony_cistatic unsigned char (*x_tab)[X_TABSZ]; /* key definition */ 960c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 961c84f3f3cSopenharmony_cistatic char *(*x_atab)[X_TABSZ]; /* macro definitions */ 962c84f3f3cSopenharmony_ci#endif 963c84f3f3cSopenharmony_cistatic unsigned char x_bound[(X_TABSZ * X_NTABS + 7) / 8]; 964c84f3f3cSopenharmony_ci#define KILLSIZE 20 965c84f3f3cSopenharmony_cistatic char *killstack[KILLSIZE]; 966c84f3f3cSopenharmony_cistatic int killsp, killtp; 967c84f3f3cSopenharmony_cistatic int x_curprefix; 968c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 969c84f3f3cSopenharmony_cistatic char *macroptr; /* bind key macro active? */ 970c84f3f3cSopenharmony_ci#endif 971c84f3f3cSopenharmony_ci#if !MKSH_S_NOVI 972c84f3f3cSopenharmony_cistatic int winwidth; /* width of window */ 973c84f3f3cSopenharmony_cistatic char *wbuf[2]; /* window buffers */ 974c84f3f3cSopenharmony_cistatic int wbuf_len; /* length of window buffers (x_cols - 3) */ 975c84f3f3cSopenharmony_cistatic int win; /* window buffer in use */ 976c84f3f3cSopenharmony_cistatic char morec; /* more character at right of window */ 977c84f3f3cSopenharmony_cistatic int holdlen; /* length of holdbuf */ 978c84f3f3cSopenharmony_ci#endif 979c84f3f3cSopenharmony_cistatic int pwidth; /* width of prompt */ 980c84f3f3cSopenharmony_cistatic int prompt_trunc; /* how much of prompt to truncate or -1 */ 981c84f3f3cSopenharmony_cistatic int x_col; /* current column on line */ 982c84f3f3cSopenharmony_ci 983c84f3f3cSopenharmony_cistatic int x_ins(const char *); 984c84f3f3cSopenharmony_cistatic void x_delete(size_t, bool); 985c84f3f3cSopenharmony_cistatic size_t x_bword(void); 986c84f3f3cSopenharmony_cistatic size_t x_fword(bool); 987c84f3f3cSopenharmony_cistatic void x_goto(char *); 988c84f3f3cSopenharmony_cistatic char *x_bs0(char *, char *) MKSH_A_PURE; 989c84f3f3cSopenharmony_cistatic void x_bs3(char **); 990c84f3f3cSopenharmony_cistatic int x_size2(char *, char **); 991c84f3f3cSopenharmony_cistatic void x_zots(char *); 992c84f3f3cSopenharmony_cistatic void x_zotc3(char **); 993c84f3f3cSopenharmony_cistatic void x_vi_zotc(int); 994c84f3f3cSopenharmony_cistatic void x_load_hist(char **); 995c84f3f3cSopenharmony_cistatic int x_search(const char *, int, int); 996c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 997c84f3f3cSopenharmony_cistatic int x_search_dir(int); 998c84f3f3cSopenharmony_ci#endif 999c84f3f3cSopenharmony_cistatic int x_match(const char *, const char *); 1000c84f3f3cSopenharmony_cistatic void x_redraw(int); 1001c84f3f3cSopenharmony_cistatic void x_push(size_t); 1002c84f3f3cSopenharmony_cistatic void x_bind_showone(int, int); 1003c84f3f3cSopenharmony_cistatic void x_e_ungetc(int); 1004c84f3f3cSopenharmony_cistatic int x_e_getc(void); 1005c84f3f3cSopenharmony_cistatic void x_e_putc2(int); 1006c84f3f3cSopenharmony_cistatic void x_e_putc3(const char **); 1007c84f3f3cSopenharmony_cistatic void x_e_puts(const char *); 1008c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 1009c84f3f3cSopenharmony_cistatic int x_fold_case(int); 1010c84f3f3cSopenharmony_ci#endif 1011c84f3f3cSopenharmony_cistatic char *x_lastcp(void); 1012c84f3f3cSopenharmony_cistatic void x_lastpos(void); 1013c84f3f3cSopenharmony_cistatic void do_complete(int, Comp_type); 1014c84f3f3cSopenharmony_cistatic size_t x_nb2nc(size_t) MKSH_A_PURE; 1015c84f3f3cSopenharmony_ci 1016c84f3f3cSopenharmony_cistatic int unget_char = -1; 1017c84f3f3cSopenharmony_ci 1018c84f3f3cSopenharmony_cistatic int x_do_ins(const char *, size_t); 1019c84f3f3cSopenharmony_cistatic void bind_if_not_bound(int, int, int); 1020c84f3f3cSopenharmony_ci 1021c84f3f3cSopenharmony_cienum emacs_funcs { 1022c84f3f3cSopenharmony_ci#define EMACSFN_ENUMS 1023c84f3f3cSopenharmony_ci#include "emacsfn.h" 1024c84f3f3cSopenharmony_ci XFUNC_MAX 1025c84f3f3cSopenharmony_ci}; 1026c84f3f3cSopenharmony_ci 1027c84f3f3cSopenharmony_ci#define EMACSFN_DEFNS 1028c84f3f3cSopenharmony_ci#include "emacsfn.h" 1029c84f3f3cSopenharmony_ci 1030c84f3f3cSopenharmony_cistatic const struct x_ftab x_ftab[] = { 1031c84f3f3cSopenharmony_ci#define EMACSFN_ITEMS 1032c84f3f3cSopenharmony_ci#include "emacsfn.h" 1033c84f3f3cSopenharmony_ci}; 1034c84f3f3cSopenharmony_ci 1035c84f3f3cSopenharmony_ci#ifndef MKSH_LESS_CMDLINE_EDITING 1036c84f3f3cSopenharmony_cistatic struct x_defbindings const x_defbindings[] = { 1037c84f3f3cSopenharmony_ci { XFUNC_del_back, 0, CTRL_QM }, 1038c84f3f3cSopenharmony_ci { XFUNC_del_bword, 1, CTRL_QM }, 1039c84f3f3cSopenharmony_ci { XFUNC_eot_del, 0, CTRL_D }, 1040c84f3f3cSopenharmony_ci { XFUNC_del_back, 0, CTRL_H }, 1041c84f3f3cSopenharmony_ci { XFUNC_del_bword, 1, CTRL_H }, 1042c84f3f3cSopenharmony_ci { XFUNC_del_bword, 1, 'h' }, 1043c84f3f3cSopenharmony_ci { XFUNC_mv_bword, 1, 'b' }, 1044c84f3f3cSopenharmony_ci { XFUNC_mv_fword, 1, 'f' }, 1045c84f3f3cSopenharmony_ci { XFUNC_del_fword, 1, 'd' }, 1046c84f3f3cSopenharmony_ci { XFUNC_mv_back, 0, CTRL_B }, 1047c84f3f3cSopenharmony_ci { XFUNC_mv_forw, 0, CTRL_F }, 1048c84f3f3cSopenharmony_ci { XFUNC_search_char_forw, 0, CTRL_BC }, 1049c84f3f3cSopenharmony_ci { XFUNC_search_char_back, 1, CTRL_BC }, 1050c84f3f3cSopenharmony_ci { XFUNC_newline, 0, CTRL_M }, 1051c84f3f3cSopenharmony_ci { XFUNC_newline, 0, CTRL_J }, 1052c84f3f3cSopenharmony_ci { XFUNC_end_of_text, 0, CTRL_US }, 1053c84f3f3cSopenharmony_ci { XFUNC_abort, 0, CTRL_G }, 1054c84f3f3cSopenharmony_ci { XFUNC_prev_com, 0, CTRL_P }, 1055c84f3f3cSopenharmony_ci { XFUNC_next_com, 0, CTRL_N }, 1056c84f3f3cSopenharmony_ci { XFUNC_nl_next_com, 0, CTRL_O }, 1057c84f3f3cSopenharmony_ci { XFUNC_search_hist, 0, CTRL_R }, 1058c84f3f3cSopenharmony_ci { XFUNC_beg_hist, 1, '<' }, 1059c84f3f3cSopenharmony_ci { XFUNC_end_hist, 1, '>' }, 1060c84f3f3cSopenharmony_ci { XFUNC_goto_hist, 1, 'g' }, 1061c84f3f3cSopenharmony_ci { XFUNC_mv_end, 0, CTRL_E }, 1062c84f3f3cSopenharmony_ci { XFUNC_mv_beg, 0, CTRL_A }, 1063c84f3f3cSopenharmony_ci { XFUNC_draw_line, 0, CTRL_L }, 1064c84f3f3cSopenharmony_ci { XFUNC_cls, 1, CTRL_L }, 1065c84f3f3cSopenharmony_ci { XFUNC_meta1, 0, CTRL_BO }, 1066c84f3f3cSopenharmony_ci { XFUNC_meta2, 0, CTRL_X }, 1067c84f3f3cSopenharmony_ci { XFUNC_kill, 0, CTRL_K }, 1068c84f3f3cSopenharmony_ci { XFUNC_yank, 0, CTRL_Y }, 1069c84f3f3cSopenharmony_ci { XFUNC_meta_yank, 1, 'y' }, 1070c84f3f3cSopenharmony_ci { XFUNC_literal, 0, CTRL_CA }, 1071c84f3f3cSopenharmony_ci { XFUNC_comment, 1, '#' }, 1072c84f3f3cSopenharmony_ci { XFUNC_transpose, 0, CTRL_T }, 1073c84f3f3cSopenharmony_ci { XFUNC_complete, 1, CTRL_BO }, 1074c84f3f3cSopenharmony_ci { XFUNC_comp_list, 0, CTRL_I }, 1075c84f3f3cSopenharmony_ci { XFUNC_comp_list, 1, '=' }, 1076c84f3f3cSopenharmony_ci { XFUNC_enumerate, 1, '?' }, 1077c84f3f3cSopenharmony_ci { XFUNC_expand, 1, '*' }, 1078c84f3f3cSopenharmony_ci { XFUNC_comp_file, 1, CTRL_X }, 1079c84f3f3cSopenharmony_ci { XFUNC_comp_comm, 2, CTRL_BO }, 1080c84f3f3cSopenharmony_ci { XFUNC_list_comm, 2, '?' }, 1081c84f3f3cSopenharmony_ci { XFUNC_list_file, 2, CTRL_Y }, 1082c84f3f3cSopenharmony_ci { XFUNC_set_mark, 1, ' ' }, 1083c84f3f3cSopenharmony_ci { XFUNC_kill_region, 0, CTRL_W }, 1084c84f3f3cSopenharmony_ci { XFUNC_xchg_point_mark, 2, CTRL_X }, 1085c84f3f3cSopenharmony_ci { XFUNC_literal, 0, CTRL_V }, 1086c84f3f3cSopenharmony_ci { XFUNC_version, 1, CTRL_V }, 1087c84f3f3cSopenharmony_ci { XFUNC_prev_histword, 1, '.' }, 1088c84f3f3cSopenharmony_ci { XFUNC_prev_histword, 1, '_' }, 1089c84f3f3cSopenharmony_ci { XFUNC_set_arg, 1, '0' }, 1090c84f3f3cSopenharmony_ci { XFUNC_set_arg, 1, '1' }, 1091c84f3f3cSopenharmony_ci { XFUNC_set_arg, 1, '2' }, 1092c84f3f3cSopenharmony_ci { XFUNC_set_arg, 1, '3' }, 1093c84f3f3cSopenharmony_ci { XFUNC_set_arg, 1, '4' }, 1094c84f3f3cSopenharmony_ci { XFUNC_set_arg, 1, '5' }, 1095c84f3f3cSopenharmony_ci { XFUNC_set_arg, 1, '6' }, 1096c84f3f3cSopenharmony_ci { XFUNC_set_arg, 1, '7' }, 1097c84f3f3cSopenharmony_ci { XFUNC_set_arg, 1, '8' }, 1098c84f3f3cSopenharmony_ci { XFUNC_set_arg, 1, '9' }, 1099c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 1100c84f3f3cSopenharmony_ci { XFUNC_fold_upper, 1, 'U' }, 1101c84f3f3cSopenharmony_ci { XFUNC_fold_upper, 1, 'u' }, 1102c84f3f3cSopenharmony_ci { XFUNC_fold_lower, 1, 'L' }, 1103c84f3f3cSopenharmony_ci { XFUNC_fold_lower, 1, 'l' }, 1104c84f3f3cSopenharmony_ci { XFUNC_fold_capitalise, 1, 'C' }, 1105c84f3f3cSopenharmony_ci { XFUNC_fold_capitalise, 1, 'c' }, 1106c84f3f3cSopenharmony_ci#endif 1107c84f3f3cSopenharmony_ci /* 1108c84f3f3cSopenharmony_ci * These for ANSI arrow keys: arguablely shouldn't be here by 1109c84f3f3cSopenharmony_ci * default, but its simpler/faster/smaller than using termcap 1110c84f3f3cSopenharmony_ci * entries. 1111c84f3f3cSopenharmony_ci */ 1112c84f3f3cSopenharmony_ci { XFUNC_meta2, 1, '[' }, 1113c84f3f3cSopenharmony_ci { XFUNC_meta2, 1, 'O' }, 1114c84f3f3cSopenharmony_ci { XFUNC_prev_com, 2, 'A' }, 1115c84f3f3cSopenharmony_ci { XFUNC_next_com, 2, 'B' }, 1116c84f3f3cSopenharmony_ci { XFUNC_mv_forw, 2, 'C' }, 1117c84f3f3cSopenharmony_ci { XFUNC_mv_back, 2, 'D' }, 1118c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 1119c84f3f3cSopenharmony_ci { XFUNC_vt_hack, 2, '1' }, 1120c84f3f3cSopenharmony_ci { XFUNC_mv_beg | 0x80, 2, '7' }, 1121c84f3f3cSopenharmony_ci { XFUNC_mv_beg, 2, 'H' }, 1122c84f3f3cSopenharmony_ci { XFUNC_mv_end | 0x80, 2, '4' }, 1123c84f3f3cSopenharmony_ci { XFUNC_mv_end | 0x80, 2, '8' }, 1124c84f3f3cSopenharmony_ci { XFUNC_mv_end, 2, 'F' }, 1125c84f3f3cSopenharmony_ci { XFUNC_del_char | 0x80, 2, '3' }, 1126c84f3f3cSopenharmony_ci { XFUNC_del_char, 2, 'P' }, 1127c84f3f3cSopenharmony_ci { XFUNC_search_hist_up | 0x80, 2, '5' }, 1128c84f3f3cSopenharmony_ci { XFUNC_search_hist_dn | 0x80, 2, '6' }, 1129c84f3f3cSopenharmony_ci#endif 1130c84f3f3cSopenharmony_ci /* PC scancodes */ 1131c84f3f3cSopenharmony_ci#if !defined(MKSH_SMALL) || defined(__OS2__) 1132c84f3f3cSopenharmony_ci { XFUNC_meta3, 0, 0 }, 1133c84f3f3cSopenharmony_ci { XFUNC_mv_beg, 3, 71 }, 1134c84f3f3cSopenharmony_ci { XFUNC_prev_com, 3, 72 }, 1135c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 1136c84f3f3cSopenharmony_ci { XFUNC_search_hist_up, 3, 73 }, 1137c84f3f3cSopenharmony_ci#endif 1138c84f3f3cSopenharmony_ci { XFUNC_mv_back, 3, 75 }, 1139c84f3f3cSopenharmony_ci { XFUNC_mv_forw, 3, 77 }, 1140c84f3f3cSopenharmony_ci { XFUNC_mv_end, 3, 79 }, 1141c84f3f3cSopenharmony_ci { XFUNC_next_com, 3, 80 }, 1142c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 1143c84f3f3cSopenharmony_ci { XFUNC_search_hist_dn, 3, 81 }, 1144c84f3f3cSopenharmony_ci#endif 1145c84f3f3cSopenharmony_ci { XFUNC_del_char, 3, 83 }, 1146c84f3f3cSopenharmony_ci#endif 1147c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 1148c84f3f3cSopenharmony_ci /* more non-standard ones */ 1149c84f3f3cSopenharmony_ci { XFUNC_eval_region, 1, CTRL_E }, 1150c84f3f3cSopenharmony_ci { XFUNC_quote_region, 1, 'Q' }, 1151c84f3f3cSopenharmony_ci { XFUNC_edit_line, 2, 'e' } 1152c84f3f3cSopenharmony_ci#endif 1153c84f3f3cSopenharmony_ci}; 1154c84f3f3cSopenharmony_ci#else // MKSH_LESS_CMDLINE_EDITING 1155c84f3f3cSopenharmony_cistatic struct x_defbindings const x_defbindings[] = { 1156c84f3f3cSopenharmony_ci { XFUNC_abort, 0, CTRL_G }, 1157c84f3f3cSopenharmony_ci { XFUNC_newline, 0, CTRL_M }, 1158c84f3f3cSopenharmony_ci { XFUNC_newline, 0, CTRL_J }, 1159c84f3f3cSopenharmony_ci { XFUNC_meta1, 0, CTRL_BO }, 1160c84f3f3cSopenharmony_ci { XFUNC_meta2, 0, CTRL_X }, 1161c84f3f3cSopenharmony_ci { XFUNC_meta2, 1, '[' }, 1162c84f3f3cSopenharmony_ci { XFUNC_meta2, 1, 'O' }, 1163c84f3f3cSopenharmony_ci { XFUNC_prev_com, 0, CTRL_P }, 1164c84f3f3cSopenharmony_ci { XFUNC_prev_com, 2, 'A' }, 1165c84f3f3cSopenharmony_ci { XFUNC_next_com, 0, CTRL_N }, 1166c84f3f3cSopenharmony_ci { XFUNC_next_com, 2, 'B' }, 1167c84f3f3cSopenharmony_ci { XFUNC_complete, 1, CTRL_BO }, 1168c84f3f3cSopenharmony_ci { XFUNC_comp_list, 0, CTRL_I }, 1169c84f3f3cSopenharmony_ci { XFUNC_comp_list, 1, '=' }, 1170c84f3f3cSopenharmony_ci { XFUNC_del_char | 0x80, 2, '3' }, 1171c84f3f3cSopenharmony_ci { XFUNC_del_back, 0, CTRL_QM }, 1172c84f3f3cSopenharmony_ci { XFUNC_del_back, 0, CTRL_H }, 1173c84f3f3cSopenharmony_ci { XFUNC_mv_back, 0, CTRL_B }, 1174c84f3f3cSopenharmony_ci { XFUNC_mv_back, 2, 'D' }, 1175c84f3f3cSopenharmony_ci { XFUNC_mv_forw, 0, CTRL_F }, 1176c84f3f3cSopenharmony_ci { XFUNC_mv_forw, 2, 'C' }, 1177c84f3f3cSopenharmony_ci { XFUNC_mv_forw, 3, 77 } 1178c84f3f3cSopenharmony_ci}; 1179c84f3f3cSopenharmony_ci#endif // MKSH_LESS_CMDLINE_EDITING 1180c84f3f3cSopenharmony_ci 1181c84f3f3cSopenharmony_ci 1182c84f3f3cSopenharmony_cistatic size_t 1183c84f3f3cSopenharmony_cix_nb2nc(size_t nb) 1184c84f3f3cSopenharmony_ci{ 1185c84f3f3cSopenharmony_ci char *cp; 1186c84f3f3cSopenharmony_ci size_t nc = 0; 1187c84f3f3cSopenharmony_ci 1188c84f3f3cSopenharmony_ci for (cp = xcp; cp < (xcp + nb); ++nc) 1189c84f3f3cSopenharmony_ci cp += utf_ptradj(cp); 1190c84f3f3cSopenharmony_ci return (nc); 1191c84f3f3cSopenharmony_ci} 1192c84f3f3cSopenharmony_ci 1193c84f3f3cSopenharmony_cistatic void 1194c84f3f3cSopenharmony_cix_modified(void) 1195c84f3f3cSopenharmony_ci{ 1196c84f3f3cSopenharmony_ci if (!modified) { 1197c84f3f3cSopenharmony_ci x_histmcp = x_histp; 1198c84f3f3cSopenharmony_ci x_histp = histptr + 1; 1199c84f3f3cSopenharmony_ci modified = 1; 1200c84f3f3cSopenharmony_ci } 1201c84f3f3cSopenharmony_ci} 1202c84f3f3cSopenharmony_ci 1203c84f3f3cSopenharmony_ci#ifdef MKSH_SMALL 1204c84f3f3cSopenharmony_ci#define XFUNC_VALUE(f) (f) 1205c84f3f3cSopenharmony_ci#else 1206c84f3f3cSopenharmony_ci#define XFUNC_VALUE(f) (f & 0x7F) 1207c84f3f3cSopenharmony_ci#endif 1208c84f3f3cSopenharmony_ci 1209c84f3f3cSopenharmony_cistatic int 1210c84f3f3cSopenharmony_cix_e_getmbc(char *sbuf) 1211c84f3f3cSopenharmony_ci{ 1212c84f3f3cSopenharmony_ci int c, pos = 0; 1213c84f3f3cSopenharmony_ci unsigned char *buf = (unsigned char *)sbuf; 1214c84f3f3cSopenharmony_ci 1215c84f3f3cSopenharmony_ci memset(buf, 0, 4); 1216c84f3f3cSopenharmony_ci buf[pos++] = c = x_e_getc(); 1217c84f3f3cSopenharmony_ci if (c == -1) 1218c84f3f3cSopenharmony_ci return (-1); 1219c84f3f3cSopenharmony_ci if (UTFMODE) { 1220c84f3f3cSopenharmony_ci if ((rtt2asc(buf[0]) >= (unsigned char)0xC2) && 1221c84f3f3cSopenharmony_ci (rtt2asc(buf[0]) < (unsigned char)0xF0)) { 1222c84f3f3cSopenharmony_ci c = x_e_getc(); 1223c84f3f3cSopenharmony_ci if (c == -1) 1224c84f3f3cSopenharmony_ci return (-1); 1225c84f3f3cSopenharmony_ci if ((rtt2asc(c) & 0xC0) != 0x80) { 1226c84f3f3cSopenharmony_ci x_e_ungetc(c); 1227c84f3f3cSopenharmony_ci return (1); 1228c84f3f3cSopenharmony_ci } 1229c84f3f3cSopenharmony_ci buf[pos++] = c; 1230c84f3f3cSopenharmony_ci } 1231c84f3f3cSopenharmony_ci if ((rtt2asc(buf[0]) >= (unsigned char)0xE0) && 1232c84f3f3cSopenharmony_ci (rtt2asc(buf[0]) < (unsigned char)0xF0)) { 1233c84f3f3cSopenharmony_ci /* XXX x_e_ungetc is one-octet only */ 1234c84f3f3cSopenharmony_ci buf[pos++] = c = x_e_getc(); 1235c84f3f3cSopenharmony_ci if (c == -1) 1236c84f3f3cSopenharmony_ci return (-1); 1237c84f3f3cSopenharmony_ci } 1238c84f3f3cSopenharmony_ci } 1239c84f3f3cSopenharmony_ci return (pos); 1240c84f3f3cSopenharmony_ci} 1241c84f3f3cSopenharmony_ci 1242c84f3f3cSopenharmony_ci/* 1243c84f3f3cSopenharmony_ci * minimum required space to work with on a line - if the prompt 1244c84f3f3cSopenharmony_ci * leaves less space than this on a line, the prompt is truncated 1245c84f3f3cSopenharmony_ci */ 1246c84f3f3cSopenharmony_ci#define MIN_EDIT_SPACE 7 1247c84f3f3cSopenharmony_ci 1248c84f3f3cSopenharmony_cistatic void 1249c84f3f3cSopenharmony_cix_init_prompt(bool doprint) 1250c84f3f3cSopenharmony_ci{ 1251c84f3f3cSopenharmony_ci prompt_trunc = pprompt(prompt, doprint ? 0 : -1); 1252c84f3f3cSopenharmony_ci pwidth = prompt_trunc % x_cols; 1253c84f3f3cSopenharmony_ci prompt_trunc -= pwidth; 1254c84f3f3cSopenharmony_ci if ((mksh_uari_t)pwidth > ((mksh_uari_t)x_cols - 3 - MIN_EDIT_SPACE)) { 1255c84f3f3cSopenharmony_ci /* force newline after prompt */ 1256c84f3f3cSopenharmony_ci prompt_trunc = -1; 1257c84f3f3cSopenharmony_ci pwidth = 0; 1258c84f3f3cSopenharmony_ci if (doprint) 1259c84f3f3cSopenharmony_ci x_e_putc2('\n'); 1260c84f3f3cSopenharmony_ci } 1261c84f3f3cSopenharmony_ci} 1262c84f3f3cSopenharmony_ci 1263c84f3f3cSopenharmony_cistatic int 1264c84f3f3cSopenharmony_cix_emacs(char *buf) 1265c84f3f3cSopenharmony_ci{ 1266c84f3f3cSopenharmony_ci int c, i; 1267c84f3f3cSopenharmony_ci unsigned char f; 1268c84f3f3cSopenharmony_ci 1269c84f3f3cSopenharmony_ci xbp = xbuf = buf; 1270c84f3f3cSopenharmony_ci xend = buf + LINE; 1271c84f3f3cSopenharmony_ci xlp = xcp = xep = buf; 1272c84f3f3cSopenharmony_ci *xcp = 0; 1273c84f3f3cSopenharmony_ci xlp_valid = true; 1274c84f3f3cSopenharmony_ci xmp = NULL; 1275c84f3f3cSopenharmony_ci x_curprefix = 0; 1276c84f3f3cSopenharmony_ci x_histmcp = x_histp = histptr + 1; 1277c84f3f3cSopenharmony_ci x_last_command = XFUNC_error; 1278c84f3f3cSopenharmony_ci 1279c84f3f3cSopenharmony_ci x_init_prompt(true); 1280c84f3f3cSopenharmony_ci x_displen = (xx_cols = x_cols) - 2 - (x_col = pwidth); 1281c84f3f3cSopenharmony_ci x_adj_done = 0; 1282c84f3f3cSopenharmony_ci x_adj_ok = true; 1283c84f3f3cSopenharmony_ci 1284c84f3f3cSopenharmony_ci x_histncp = NULL; 1285c84f3f3cSopenharmony_ci if (x_nextcmd >= 0) { 1286c84f3f3cSopenharmony_ci int off = source->line - x_nextcmd; 1287c84f3f3cSopenharmony_ci if (histptr - history >= off) { 1288c84f3f3cSopenharmony_ci x_load_hist(histptr - off); 1289c84f3f3cSopenharmony_ci x_histncp = x_histp; 1290c84f3f3cSopenharmony_ci } 1291c84f3f3cSopenharmony_ci x_nextcmd = -1; 1292c84f3f3cSopenharmony_ci } 1293c84f3f3cSopenharmony_ci editmode = 1; 1294c84f3f3cSopenharmony_ci while (/* CONSTCOND */ 1) { 1295c84f3f3cSopenharmony_ci x_flush(); 1296c84f3f3cSopenharmony_ci if ((c = x_e_getc()) < 0) 1297c84f3f3cSopenharmony_ci return (0); 1298c84f3f3cSopenharmony_ci 1299c84f3f3cSopenharmony_ci f = x_curprefix == -1 ? XFUNC_insert : 1300c84f3f3cSopenharmony_ci x_tab[x_curprefix][c]; 1301c84f3f3cSopenharmony_ci if (f & 0x80) { 1302c84f3f3cSopenharmony_ci f &= 0x7F; 1303c84f3f3cSopenharmony_ci if ((i = x_e_getc()) != '~') 1304c84f3f3cSopenharmony_ci x_e_ungetc(i); 1305c84f3f3cSopenharmony_ci } 1306c84f3f3cSopenharmony_ci 1307c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 1308c84f3f3cSopenharmony_ci if (f & 0x80) { 1309c84f3f3cSopenharmony_ci f &= 0x7F; 1310c84f3f3cSopenharmony_ci if ((i = x_e_getc()) != '~') 1311c84f3f3cSopenharmony_ci x_e_ungetc(i); 1312c84f3f3cSopenharmony_ci } 1313c84f3f3cSopenharmony_ci 1314c84f3f3cSopenharmony_ci /* avoid bind key macro recursion */ 1315c84f3f3cSopenharmony_ci if (macroptr && f == XFUNC_ins_string) 1316c84f3f3cSopenharmony_ci f = XFUNC_insert; 1317c84f3f3cSopenharmony_ci#endif 1318c84f3f3cSopenharmony_ci 1319c84f3f3cSopenharmony_ci if (!(x_ftab[f].xf_flags & XF_PREFIX) && 1320c84f3f3cSopenharmony_ci x_last_command != XFUNC_set_arg) { 1321c84f3f3cSopenharmony_ci x_arg = 1; 1322c84f3f3cSopenharmony_ci x_arg_defaulted = true; 1323c84f3f3cSopenharmony_ci } 1324c84f3f3cSopenharmony_ci i = c | (x_curprefix << 8); 1325c84f3f3cSopenharmony_ci x_curprefix = 0; 1326c84f3f3cSopenharmony_ci switch ((*x_ftab[f].xf_func)(i)) { 1327c84f3f3cSopenharmony_ci case KSTD: 1328c84f3f3cSopenharmony_ci if (!(x_ftab[f].xf_flags & XF_PREFIX)) 1329c84f3f3cSopenharmony_ci x_last_command = f; 1330c84f3f3cSopenharmony_ci break; 1331c84f3f3cSopenharmony_ci case KEOL: 1332c84f3f3cSopenharmony_ci i = xep - xbuf; 1333c84f3f3cSopenharmony_ci return (i); 1334c84f3f3cSopenharmony_ci case KINTR: 1335c84f3f3cSopenharmony_ci /* special case for interrupt */ 1336c84f3f3cSopenharmony_ci x_intr(SIGINT, c); 1337c84f3f3cSopenharmony_ci } 1338c84f3f3cSopenharmony_ci /* ad-hoc hack for fixing the cursor position */ 1339c84f3f3cSopenharmony_ci x_goto(xcp); 1340c84f3f3cSopenharmony_ci } 1341c84f3f3cSopenharmony_ci} 1342c84f3f3cSopenharmony_ci 1343c84f3f3cSopenharmony_cistatic int 1344c84f3f3cSopenharmony_cix_insert(int c) 1345c84f3f3cSopenharmony_ci{ 1346c84f3f3cSopenharmony_ci static int left, pos, save_arg; 1347c84f3f3cSopenharmony_ci static char str[4]; 1348c84f3f3cSopenharmony_ci 1349c84f3f3cSopenharmony_ci /* 1350c84f3f3cSopenharmony_ci * Should allow tab and control chars. 1351c84f3f3cSopenharmony_ci */ 1352c84f3f3cSopenharmony_ci if (c == 0) { 1353c84f3f3cSopenharmony_ci invmbs: 1354c84f3f3cSopenharmony_ci left = 0; 1355c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1356c84f3f3cSopenharmony_ci return (KSTD); 1357c84f3f3cSopenharmony_ci } 1358c84f3f3cSopenharmony_ci if (UTFMODE) { 1359c84f3f3cSopenharmony_ci if (((rtt2asc(c) & 0xC0) == 0x80) && left) { 1360c84f3f3cSopenharmony_ci str[pos++] = c; 1361c84f3f3cSopenharmony_ci if (!--left) { 1362c84f3f3cSopenharmony_ci str[pos] = '\0'; 1363c84f3f3cSopenharmony_ci x_arg = save_arg; 1364c84f3f3cSopenharmony_ci while (x_arg--) 1365c84f3f3cSopenharmony_ci x_ins(str); 1366c84f3f3cSopenharmony_ci } 1367c84f3f3cSopenharmony_ci return (KSTD); 1368c84f3f3cSopenharmony_ci } 1369c84f3f3cSopenharmony_ci if (left) { 1370c84f3f3cSopenharmony_ci if (x_curprefix == -1) { 1371c84f3f3cSopenharmony_ci /* flush invalid multibyte */ 1372c84f3f3cSopenharmony_ci str[pos] = '\0'; 1373c84f3f3cSopenharmony_ci while (save_arg--) 1374c84f3f3cSopenharmony_ci x_ins(str); 1375c84f3f3cSopenharmony_ci } 1376c84f3f3cSopenharmony_ci } 1377c84f3f3cSopenharmony_ci if ((c >= 0xC2) && (c < 0xE0)) 1378c84f3f3cSopenharmony_ci left = 1; 1379c84f3f3cSopenharmony_ci else if ((c >= 0xE0) && (c < 0xF0)) 1380c84f3f3cSopenharmony_ci left = 2; 1381c84f3f3cSopenharmony_ci else if (c > 0x7F) 1382c84f3f3cSopenharmony_ci goto invmbs; 1383c84f3f3cSopenharmony_ci else 1384c84f3f3cSopenharmony_ci left = 0; 1385c84f3f3cSopenharmony_ci if (left) { 1386c84f3f3cSopenharmony_ci save_arg = x_arg; 1387c84f3f3cSopenharmony_ci pos = 1; 1388c84f3f3cSopenharmony_ci str[0] = c; 1389c84f3f3cSopenharmony_ci return (KSTD); 1390c84f3f3cSopenharmony_ci } 1391c84f3f3cSopenharmony_ci } 1392c84f3f3cSopenharmony_ci left = 0; 1393c84f3f3cSopenharmony_ci str[0] = c; 1394c84f3f3cSopenharmony_ci str[1] = '\0'; 1395c84f3f3cSopenharmony_ci while (x_arg--) 1396c84f3f3cSopenharmony_ci x_ins(str); 1397c84f3f3cSopenharmony_ci return (KSTD); 1398c84f3f3cSopenharmony_ci} 1399c84f3f3cSopenharmony_ci 1400c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 1401c84f3f3cSopenharmony_cistatic int 1402c84f3f3cSopenharmony_cix_ins_string(int c) 1403c84f3f3cSopenharmony_ci{ 1404c84f3f3cSopenharmony_ci macroptr = x_atab[c >> 8][c & 255]; 1405c84f3f3cSopenharmony_ci /* 1406c84f3f3cSopenharmony_ci * we no longer need to bother checking if macroptr is 1407c84f3f3cSopenharmony_ci * not NULL but first char is NUL; x_e_getc() does it 1408c84f3f3cSopenharmony_ci */ 1409c84f3f3cSopenharmony_ci return (KSTD); 1410c84f3f3cSopenharmony_ci} 1411c84f3f3cSopenharmony_ci#endif 1412c84f3f3cSopenharmony_ci 1413c84f3f3cSopenharmony_cistatic int 1414c84f3f3cSopenharmony_cix_do_ins(const char *cp, size_t len) 1415c84f3f3cSopenharmony_ci{ 1416c84f3f3cSopenharmony_ci if (xep + len >= xend) { 1417c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1418c84f3f3cSopenharmony_ci return (-1); 1419c84f3f3cSopenharmony_ci } 1420c84f3f3cSopenharmony_ci memmove(xcp + len, xcp, xep - xcp + 1); 1421c84f3f3cSopenharmony_ci memmove(xcp, cp, len); 1422c84f3f3cSopenharmony_ci xcp += len; 1423c84f3f3cSopenharmony_ci xep += len; 1424c84f3f3cSopenharmony_ci x_modified(); 1425c84f3f3cSopenharmony_ci return (0); 1426c84f3f3cSopenharmony_ci} 1427c84f3f3cSopenharmony_ci 1428c84f3f3cSopenharmony_cistatic int 1429c84f3f3cSopenharmony_cix_ins(const char *s) 1430c84f3f3cSopenharmony_ci{ 1431c84f3f3cSopenharmony_ci char *cp = xcp; 1432c84f3f3cSopenharmony_ci int adj = x_adj_done; 1433c84f3f3cSopenharmony_ci 1434c84f3f3cSopenharmony_ci if (x_do_ins(s, strlen(s)) < 0) 1435c84f3f3cSopenharmony_ci return (-1); 1436c84f3f3cSopenharmony_ci /* 1437c84f3f3cSopenharmony_ci * x_zots() may result in a call to x_adjust() 1438c84f3f3cSopenharmony_ci * we want xcp to reflect the new position. 1439c84f3f3cSopenharmony_ci */ 1440c84f3f3cSopenharmony_ci xlp_valid = false; 1441c84f3f3cSopenharmony_ci x_lastcp(); 1442c84f3f3cSopenharmony_ci x_adj_ok = tobool(xcp >= xlp); 1443c84f3f3cSopenharmony_ci x_zots(cp); 1444c84f3f3cSopenharmony_ci if (adj == x_adj_done) 1445c84f3f3cSopenharmony_ci /* x_adjust() has not been called */ 1446c84f3f3cSopenharmony_ci x_lastpos(); 1447c84f3f3cSopenharmony_ci x_adj_ok = true; 1448c84f3f3cSopenharmony_ci return (0); 1449c84f3f3cSopenharmony_ci} 1450c84f3f3cSopenharmony_ci 1451c84f3f3cSopenharmony_cistatic int 1452c84f3f3cSopenharmony_cix_del_back(int c MKSH_A_UNUSED) 1453c84f3f3cSopenharmony_ci{ 1454c84f3f3cSopenharmony_ci ssize_t i = 0; 1455c84f3f3cSopenharmony_ci 1456c84f3f3cSopenharmony_ci if (xcp == xbuf) { 1457c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1458c84f3f3cSopenharmony_ci return (KSTD); 1459c84f3f3cSopenharmony_ci } 1460c84f3f3cSopenharmony_ci do { 1461c84f3f3cSopenharmony_ci x_goto(xcp - 1); 1462c84f3f3cSopenharmony_ci } while ((++i < x_arg) && (xcp != xbuf)); 1463c84f3f3cSopenharmony_ci x_delete(i, false); 1464c84f3f3cSopenharmony_ci return (KSTD); 1465c84f3f3cSopenharmony_ci} 1466c84f3f3cSopenharmony_ci 1467c84f3f3cSopenharmony_cistatic int 1468c84f3f3cSopenharmony_cix_del_char(int c MKSH_A_UNUSED) 1469c84f3f3cSopenharmony_ci{ 1470c84f3f3cSopenharmony_ci char *cp, *cp2; 1471c84f3f3cSopenharmony_ci size_t i = 0; 1472c84f3f3cSopenharmony_ci 1473c84f3f3cSopenharmony_ci cp = xcp; 1474c84f3f3cSopenharmony_ci while (i < (size_t)x_arg) { 1475c84f3f3cSopenharmony_ci utf_ptradjx(cp, cp2); 1476c84f3f3cSopenharmony_ci if (cp2 > xep) 1477c84f3f3cSopenharmony_ci break; 1478c84f3f3cSopenharmony_ci cp = cp2; 1479c84f3f3cSopenharmony_ci i++; 1480c84f3f3cSopenharmony_ci } 1481c84f3f3cSopenharmony_ci 1482c84f3f3cSopenharmony_ci if (!i) { 1483c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1484c84f3f3cSopenharmony_ci return (KSTD); 1485c84f3f3cSopenharmony_ci } 1486c84f3f3cSopenharmony_ci x_delete(i, false); 1487c84f3f3cSopenharmony_ci return (KSTD); 1488c84f3f3cSopenharmony_ci} 1489c84f3f3cSopenharmony_ci 1490c84f3f3cSopenharmony_ci/* Delete nc chars to the right of the cursor (including cursor position) */ 1491c84f3f3cSopenharmony_cistatic void 1492c84f3f3cSopenharmony_cix_delete(size_t nc, bool push) 1493c84f3f3cSopenharmony_ci{ 1494c84f3f3cSopenharmony_ci size_t i, nb, nw; 1495c84f3f3cSopenharmony_ci char *cp; 1496c84f3f3cSopenharmony_ci 1497c84f3f3cSopenharmony_ci if (nc == 0) 1498c84f3f3cSopenharmony_ci return; 1499c84f3f3cSopenharmony_ci 1500c84f3f3cSopenharmony_ci nw = 0; 1501c84f3f3cSopenharmony_ci cp = xcp; 1502c84f3f3cSopenharmony_ci for (i = 0; i < nc; ++i) { 1503c84f3f3cSopenharmony_ci char *cp2; 1504c84f3f3cSopenharmony_ci int j; 1505c84f3f3cSopenharmony_ci 1506c84f3f3cSopenharmony_ci j = x_size2(cp, &cp2); 1507c84f3f3cSopenharmony_ci if (cp2 > xep) 1508c84f3f3cSopenharmony_ci break; 1509c84f3f3cSopenharmony_ci cp = cp2; 1510c84f3f3cSopenharmony_ci nw += j; 1511c84f3f3cSopenharmony_ci } 1512c84f3f3cSopenharmony_ci nb = cp - xcp; 1513c84f3f3cSopenharmony_ci /* nc = i; */ 1514c84f3f3cSopenharmony_ci 1515c84f3f3cSopenharmony_ci if (xmp != NULL && xmp > xcp) { 1516c84f3f3cSopenharmony_ci if (xcp + nb > xmp) 1517c84f3f3cSopenharmony_ci xmp = xcp; 1518c84f3f3cSopenharmony_ci else 1519c84f3f3cSopenharmony_ci xmp -= nb; 1520c84f3f3cSopenharmony_ci } 1521c84f3f3cSopenharmony_ci /* 1522c84f3f3cSopenharmony_ci * This lets us yank a word we have deleted. 1523c84f3f3cSopenharmony_ci */ 1524c84f3f3cSopenharmony_ci if (push) 1525c84f3f3cSopenharmony_ci x_push(nb); 1526c84f3f3cSopenharmony_ci 1527c84f3f3cSopenharmony_ci xep -= nb; 1528c84f3f3cSopenharmony_ci /* Copies the NUL */ 1529c84f3f3cSopenharmony_ci memmove(xcp, xcp + nb, xep - xcp + 1); 1530c84f3f3cSopenharmony_ci /* don't redraw */ 1531c84f3f3cSopenharmony_ci x_adj_ok = false; 1532c84f3f3cSopenharmony_ci xlp_valid = false; 1533c84f3f3cSopenharmony_ci x_zots(xcp); 1534c84f3f3cSopenharmony_ci /* 1535c84f3f3cSopenharmony_ci * if we are already filling the line, 1536c84f3f3cSopenharmony_ci * there is no need to ' ', '\b'. 1537c84f3f3cSopenharmony_ci * But if we must, make sure we do the minimum. 1538c84f3f3cSopenharmony_ci */ 1539c84f3f3cSopenharmony_ci if ((i = xx_cols - 2 - x_col) > 0 || xep - xlp == 0) { 1540c84f3f3cSopenharmony_ci nw = i = (nw < i) ? nw : i; 1541c84f3f3cSopenharmony_ci while (i--) 1542c84f3f3cSopenharmony_ci x_e_putc2(' '); 1543c84f3f3cSopenharmony_ci if (x_col == xx_cols - 2) { 1544c84f3f3cSopenharmony_ci x_e_putc2((xep > xlp) ? '>' : (xbp > xbuf) ? '<' : ' '); 1545c84f3f3cSopenharmony_ci ++nw; 1546c84f3f3cSopenharmony_ci } 1547c84f3f3cSopenharmony_ci while (nw--) 1548c84f3f3cSopenharmony_ci x_e_putc2('\b'); 1549c84f3f3cSopenharmony_ci } 1550c84f3f3cSopenharmony_ci /*x_goto(xcp);*/ 1551c84f3f3cSopenharmony_ci x_adj_ok = true; 1552c84f3f3cSopenharmony_ci xlp_valid = false; 1553c84f3f3cSopenharmony_ci x_lastpos(); 1554c84f3f3cSopenharmony_ci x_modified(); 1555c84f3f3cSopenharmony_ci return; 1556c84f3f3cSopenharmony_ci} 1557c84f3f3cSopenharmony_ci 1558c84f3f3cSopenharmony_cistatic int 1559c84f3f3cSopenharmony_cix_del_bword(int c MKSH_A_UNUSED) 1560c84f3f3cSopenharmony_ci{ 1561c84f3f3cSopenharmony_ci x_delete(x_bword(), true); 1562c84f3f3cSopenharmony_ci return (KSTD); 1563c84f3f3cSopenharmony_ci} 1564c84f3f3cSopenharmony_ci 1565c84f3f3cSopenharmony_cistatic int 1566c84f3f3cSopenharmony_cix_mv_bword(int c MKSH_A_UNUSED) 1567c84f3f3cSopenharmony_ci{ 1568c84f3f3cSopenharmony_ci x_bword(); 1569c84f3f3cSopenharmony_ci return (KSTD); 1570c84f3f3cSopenharmony_ci} 1571c84f3f3cSopenharmony_ci 1572c84f3f3cSopenharmony_cistatic int 1573c84f3f3cSopenharmony_cix_mv_fword(int c MKSH_A_UNUSED) 1574c84f3f3cSopenharmony_ci{ 1575c84f3f3cSopenharmony_ci x_fword(true); 1576c84f3f3cSopenharmony_ci return (KSTD); 1577c84f3f3cSopenharmony_ci} 1578c84f3f3cSopenharmony_ci 1579c84f3f3cSopenharmony_cistatic int 1580c84f3f3cSopenharmony_cix_del_fword(int c MKSH_A_UNUSED) 1581c84f3f3cSopenharmony_ci{ 1582c84f3f3cSopenharmony_ci x_delete(x_fword(false), true); 1583c84f3f3cSopenharmony_ci return (KSTD); 1584c84f3f3cSopenharmony_ci} 1585c84f3f3cSopenharmony_ci 1586c84f3f3cSopenharmony_cistatic size_t 1587c84f3f3cSopenharmony_cix_bword(void) 1588c84f3f3cSopenharmony_ci{ 1589c84f3f3cSopenharmony_ci size_t nb = 0; 1590c84f3f3cSopenharmony_ci char *cp = xcp; 1591c84f3f3cSopenharmony_ci 1592c84f3f3cSopenharmony_ci if (cp == xbuf) { 1593c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1594c84f3f3cSopenharmony_ci return (0); 1595c84f3f3cSopenharmony_ci } 1596c84f3f3cSopenharmony_ci while (x_arg--) { 1597c84f3f3cSopenharmony_ci while (cp != xbuf && ctype(cp[-1], C_MFS)) { 1598c84f3f3cSopenharmony_ci cp--; 1599c84f3f3cSopenharmony_ci nb++; 1600c84f3f3cSopenharmony_ci } 1601c84f3f3cSopenharmony_ci while (cp != xbuf && !ctype(cp[-1], C_MFS)) { 1602c84f3f3cSopenharmony_ci cp--; 1603c84f3f3cSopenharmony_ci nb++; 1604c84f3f3cSopenharmony_ci } 1605c84f3f3cSopenharmony_ci } 1606c84f3f3cSopenharmony_ci x_goto(cp); 1607c84f3f3cSopenharmony_ci return (x_nb2nc(nb)); 1608c84f3f3cSopenharmony_ci} 1609c84f3f3cSopenharmony_ci 1610c84f3f3cSopenharmony_cistatic size_t 1611c84f3f3cSopenharmony_cix_fword(bool move) 1612c84f3f3cSopenharmony_ci{ 1613c84f3f3cSopenharmony_ci size_t nc; 1614c84f3f3cSopenharmony_ci char *cp = xcp; 1615c84f3f3cSopenharmony_ci 1616c84f3f3cSopenharmony_ci if (cp == xep) { 1617c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1618c84f3f3cSopenharmony_ci return (0); 1619c84f3f3cSopenharmony_ci } 1620c84f3f3cSopenharmony_ci while (x_arg--) { 1621c84f3f3cSopenharmony_ci while (cp != xep && ctype(*cp, C_MFS)) 1622c84f3f3cSopenharmony_ci cp++; 1623c84f3f3cSopenharmony_ci while (cp != xep && !ctype(*cp, C_MFS)) 1624c84f3f3cSopenharmony_ci cp++; 1625c84f3f3cSopenharmony_ci } 1626c84f3f3cSopenharmony_ci nc = x_nb2nc(cp - xcp); 1627c84f3f3cSopenharmony_ci if (move) 1628c84f3f3cSopenharmony_ci x_goto(cp); 1629c84f3f3cSopenharmony_ci return (nc); 1630c84f3f3cSopenharmony_ci} 1631c84f3f3cSopenharmony_ci 1632c84f3f3cSopenharmony_cistatic void 1633c84f3f3cSopenharmony_cix_goto(char *cp) 1634c84f3f3cSopenharmony_ci{ 1635c84f3f3cSopenharmony_ci cp = cp >= xep ? xep : x_bs0(cp, xbuf); 1636c84f3f3cSopenharmony_ci if (cp < xbp || cp >= utf_skipcols(xbp, x_displen, NULL)) { 1637c84f3f3cSopenharmony_ci /* we are heading off screen */ 1638c84f3f3cSopenharmony_ci xcp = cp; 1639c84f3f3cSopenharmony_ci x_adjust(); 1640c84f3f3cSopenharmony_ci } else if (cp < xcp) { 1641c84f3f3cSopenharmony_ci /* move back */ 1642c84f3f3cSopenharmony_ci while (cp < xcp) 1643c84f3f3cSopenharmony_ci x_bs3(&xcp); 1644c84f3f3cSopenharmony_ci } else if (cp > xcp) { 1645c84f3f3cSopenharmony_ci /* move forward */ 1646c84f3f3cSopenharmony_ci while (cp > xcp) 1647c84f3f3cSopenharmony_ci x_zotc3(&xcp); 1648c84f3f3cSopenharmony_ci } 1649c84f3f3cSopenharmony_ci} 1650c84f3f3cSopenharmony_ci 1651c84f3f3cSopenharmony_cistatic char * 1652c84f3f3cSopenharmony_cix_bs0(char *cp, char *lower_bound) 1653c84f3f3cSopenharmony_ci{ 1654c84f3f3cSopenharmony_ci if (UTFMODE) 1655c84f3f3cSopenharmony_ci while ((!lower_bound || (cp > lower_bound)) && 1656c84f3f3cSopenharmony_ci ((rtt2asc(*cp) & 0xC0) == 0x80)) 1657c84f3f3cSopenharmony_ci --cp; 1658c84f3f3cSopenharmony_ci return (cp); 1659c84f3f3cSopenharmony_ci} 1660c84f3f3cSopenharmony_ci 1661c84f3f3cSopenharmony_cistatic void 1662c84f3f3cSopenharmony_cix_bs3(char **p) 1663c84f3f3cSopenharmony_ci{ 1664c84f3f3cSopenharmony_ci int i; 1665c84f3f3cSopenharmony_ci 1666c84f3f3cSopenharmony_ci *p = x_bs0((*p) - 1, NULL); 1667c84f3f3cSopenharmony_ci i = x_size2(*p, NULL); 1668c84f3f3cSopenharmony_ci while (i--) 1669c84f3f3cSopenharmony_ci x_e_putc2('\b'); 1670c84f3f3cSopenharmony_ci} 1671c84f3f3cSopenharmony_ci 1672c84f3f3cSopenharmony_cistatic int 1673c84f3f3cSopenharmony_cix_size2(char *cp, char **dcp) 1674c84f3f3cSopenharmony_ci{ 1675c84f3f3cSopenharmony_ci uint8_t c = *(unsigned char *)cp; 1676c84f3f3cSopenharmony_ci 1677c84f3f3cSopenharmony_ci if (UTFMODE && (rtt2asc(c) > 0x7F)) 1678c84f3f3cSopenharmony_ci return (utf_widthadj(cp, (const char **)dcp)); 1679c84f3f3cSopenharmony_ci if (dcp) 1680c84f3f3cSopenharmony_ci *dcp = cp + 1; 1681c84f3f3cSopenharmony_ci if (c == '\t') 1682c84f3f3cSopenharmony_ci /* Kludge, tabs are always four spaces. */ 1683c84f3f3cSopenharmony_ci return (4); 1684c84f3f3cSopenharmony_ci if (ksh_isctrl(c)) 1685c84f3f3cSopenharmony_ci /* control unsigned char */ 1686c84f3f3cSopenharmony_ci return (2); 1687c84f3f3cSopenharmony_ci return (1); 1688c84f3f3cSopenharmony_ci} 1689c84f3f3cSopenharmony_ci 1690c84f3f3cSopenharmony_cistatic void 1691c84f3f3cSopenharmony_cix_zots(char *str) 1692c84f3f3cSopenharmony_ci{ 1693c84f3f3cSopenharmony_ci int adj = x_adj_done; 1694c84f3f3cSopenharmony_ci 1695c84f3f3cSopenharmony_ci x_lastcp(); 1696c84f3f3cSopenharmony_ci while (*str && str < xlp && x_col < xx_cols && adj == x_adj_done) 1697c84f3f3cSopenharmony_ci x_zotc3(&str); 1698c84f3f3cSopenharmony_ci} 1699c84f3f3cSopenharmony_ci 1700c84f3f3cSopenharmony_cistatic void 1701c84f3f3cSopenharmony_cix_zotc3(char **cp) 1702c84f3f3cSopenharmony_ci{ 1703c84f3f3cSopenharmony_ci unsigned char c = **(unsigned char **)cp; 1704c84f3f3cSopenharmony_ci 1705c84f3f3cSopenharmony_ci if (c == '\t') { 1706c84f3f3cSopenharmony_ci /* Kludge, tabs are always four spaces. */ 1707c84f3f3cSopenharmony_ci x_e_puts(T4spaces); 1708c84f3f3cSopenharmony_ci (*cp)++; 1709c84f3f3cSopenharmony_ci } else if (ksh_isctrl(c)) { 1710c84f3f3cSopenharmony_ci x_e_putc2('^'); 1711c84f3f3cSopenharmony_ci x_e_putc2(ksh_unctrl(c)); 1712c84f3f3cSopenharmony_ci (*cp)++; 1713c84f3f3cSopenharmony_ci } else 1714c84f3f3cSopenharmony_ci x_e_putc3((const char **)cp); 1715c84f3f3cSopenharmony_ci} 1716c84f3f3cSopenharmony_ci 1717c84f3f3cSopenharmony_cistatic int 1718c84f3f3cSopenharmony_cix_mv_back(int c MKSH_A_UNUSED) 1719c84f3f3cSopenharmony_ci{ 1720c84f3f3cSopenharmony_ci if (xcp == xbuf) { 1721c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1722c84f3f3cSopenharmony_ci return (KSTD); 1723c84f3f3cSopenharmony_ci } 1724c84f3f3cSopenharmony_ci while (x_arg--) { 1725c84f3f3cSopenharmony_ci x_goto(xcp - 1); 1726c84f3f3cSopenharmony_ci if (xcp == xbuf) 1727c84f3f3cSopenharmony_ci break; 1728c84f3f3cSopenharmony_ci } 1729c84f3f3cSopenharmony_ci return (KSTD); 1730c84f3f3cSopenharmony_ci} 1731c84f3f3cSopenharmony_ci 1732c84f3f3cSopenharmony_cistatic int 1733c84f3f3cSopenharmony_cix_mv_forw(int c MKSH_A_UNUSED) 1734c84f3f3cSopenharmony_ci{ 1735c84f3f3cSopenharmony_ci char *cp = xcp, *cp2; 1736c84f3f3cSopenharmony_ci 1737c84f3f3cSopenharmony_ci if (xcp == xep) { 1738c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1739c84f3f3cSopenharmony_ci return (KSTD); 1740c84f3f3cSopenharmony_ci } 1741c84f3f3cSopenharmony_ci while (x_arg--) { 1742c84f3f3cSopenharmony_ci utf_ptradjx(cp, cp2); 1743c84f3f3cSopenharmony_ci if (cp2 > xep) 1744c84f3f3cSopenharmony_ci break; 1745c84f3f3cSopenharmony_ci cp = cp2; 1746c84f3f3cSopenharmony_ci } 1747c84f3f3cSopenharmony_ci x_goto(cp); 1748c84f3f3cSopenharmony_ci return (KSTD); 1749c84f3f3cSopenharmony_ci} 1750c84f3f3cSopenharmony_ci 1751c84f3f3cSopenharmony_cistatic int 1752c84f3f3cSopenharmony_cix_search_char_forw(int c MKSH_A_UNUSED) 1753c84f3f3cSopenharmony_ci{ 1754c84f3f3cSopenharmony_ci char *cp = xcp; 1755c84f3f3cSopenharmony_ci char tmp[4]; 1756c84f3f3cSopenharmony_ci 1757c84f3f3cSopenharmony_ci *xep = '\0'; 1758c84f3f3cSopenharmony_ci if (x_e_getmbc(tmp) < 0) { 1759c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1760c84f3f3cSopenharmony_ci return (KSTD); 1761c84f3f3cSopenharmony_ci } 1762c84f3f3cSopenharmony_ci while (x_arg--) { 1763c84f3f3cSopenharmony_ci if ((cp = (cp == xep) ? NULL : strstr(cp + 1, tmp)) == NULL && 1764c84f3f3cSopenharmony_ci (cp = strstr(xbuf, tmp)) == NULL) { 1765c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1766c84f3f3cSopenharmony_ci return (KSTD); 1767c84f3f3cSopenharmony_ci } 1768c84f3f3cSopenharmony_ci } 1769c84f3f3cSopenharmony_ci x_goto(cp); 1770c84f3f3cSopenharmony_ci return (KSTD); 1771c84f3f3cSopenharmony_ci} 1772c84f3f3cSopenharmony_ci 1773c84f3f3cSopenharmony_cistatic int 1774c84f3f3cSopenharmony_cix_search_char_back(int c MKSH_A_UNUSED) 1775c84f3f3cSopenharmony_ci{ 1776c84f3f3cSopenharmony_ci char *cp = xcp, *p, tmp[4]; 1777c84f3f3cSopenharmony_ci bool b; 1778c84f3f3cSopenharmony_ci 1779c84f3f3cSopenharmony_ci if (x_e_getmbc(tmp) < 0) { 1780c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1781c84f3f3cSopenharmony_ci return (KSTD); 1782c84f3f3cSopenharmony_ci } 1783c84f3f3cSopenharmony_ci for (; x_arg--; cp = p) 1784c84f3f3cSopenharmony_ci for (p = cp; ; ) { 1785c84f3f3cSopenharmony_ci if (p-- == xbuf) 1786c84f3f3cSopenharmony_ci p = xep; 1787c84f3f3cSopenharmony_ci if (p == cp) { 1788c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1789c84f3f3cSopenharmony_ci return (KSTD); 1790c84f3f3cSopenharmony_ci } 1791c84f3f3cSopenharmony_ci if ((tmp[1] && ((p+1) > xep)) || 1792c84f3f3cSopenharmony_ci (tmp[2] && ((p+2) > xep))) 1793c84f3f3cSopenharmony_ci continue; 1794c84f3f3cSopenharmony_ci b = true; 1795c84f3f3cSopenharmony_ci if (*p != tmp[0]) 1796c84f3f3cSopenharmony_ci b = false; 1797c84f3f3cSopenharmony_ci if (b && tmp[1] && p[1] != tmp[1]) 1798c84f3f3cSopenharmony_ci b = false; 1799c84f3f3cSopenharmony_ci if (b && tmp[2] && p[2] != tmp[2]) 1800c84f3f3cSopenharmony_ci b = false; 1801c84f3f3cSopenharmony_ci if (b) 1802c84f3f3cSopenharmony_ci break; 1803c84f3f3cSopenharmony_ci } 1804c84f3f3cSopenharmony_ci x_goto(cp); 1805c84f3f3cSopenharmony_ci return (KSTD); 1806c84f3f3cSopenharmony_ci} 1807c84f3f3cSopenharmony_ci 1808c84f3f3cSopenharmony_cistatic int 1809c84f3f3cSopenharmony_cix_newline(int c MKSH_A_UNUSED) 1810c84f3f3cSopenharmony_ci{ 1811c84f3f3cSopenharmony_ci x_e_putc2('\r'); 1812c84f3f3cSopenharmony_ci x_e_putc2('\n'); 1813c84f3f3cSopenharmony_ci x_flush(); 1814c84f3f3cSopenharmony_ci *xep++ = '\n'; 1815c84f3f3cSopenharmony_ci return (KEOL); 1816c84f3f3cSopenharmony_ci} 1817c84f3f3cSopenharmony_ci 1818c84f3f3cSopenharmony_cistatic int 1819c84f3f3cSopenharmony_cix_end_of_text(int c MKSH_A_UNUSED) 1820c84f3f3cSopenharmony_ci{ 1821c84f3f3cSopenharmony_ci unsigned char tmp[1], *cp = tmp; 1822c84f3f3cSopenharmony_ci 1823c84f3f3cSopenharmony_ci *tmp = isedchar(edchars.eof) ? (unsigned char)edchars.eof : 1824c84f3f3cSopenharmony_ci (unsigned char)CTRL_D; 1825c84f3f3cSopenharmony_ci x_zotc3((char **)&cp); 1826c84f3f3cSopenharmony_ci x_putc('\r'); 1827c84f3f3cSopenharmony_ci x_putc('\n'); 1828c84f3f3cSopenharmony_ci x_flush(); 1829c84f3f3cSopenharmony_ci return (KEOL); 1830c84f3f3cSopenharmony_ci} 1831c84f3f3cSopenharmony_ci 1832c84f3f3cSopenharmony_cistatic int 1833c84f3f3cSopenharmony_cix_beg_hist(int c MKSH_A_UNUSED) 1834c84f3f3cSopenharmony_ci{ 1835c84f3f3cSopenharmony_ci x_load_hist(history); 1836c84f3f3cSopenharmony_ci return (KSTD); 1837c84f3f3cSopenharmony_ci} 1838c84f3f3cSopenharmony_ci 1839c84f3f3cSopenharmony_cistatic int 1840c84f3f3cSopenharmony_cix_end_hist(int c MKSH_A_UNUSED) 1841c84f3f3cSopenharmony_ci{ 1842c84f3f3cSopenharmony_ci x_load_hist(histptr); 1843c84f3f3cSopenharmony_ci return (KSTD); 1844c84f3f3cSopenharmony_ci} 1845c84f3f3cSopenharmony_ci 1846c84f3f3cSopenharmony_cistatic int 1847c84f3f3cSopenharmony_cix_prev_com(int c MKSH_A_UNUSED) 1848c84f3f3cSopenharmony_ci{ 1849c84f3f3cSopenharmony_ci x_load_hist(x_histp - x_arg); 1850c84f3f3cSopenharmony_ci return (KSTD); 1851c84f3f3cSopenharmony_ci} 1852c84f3f3cSopenharmony_ci 1853c84f3f3cSopenharmony_cistatic int 1854c84f3f3cSopenharmony_cix_next_com(int c MKSH_A_UNUSED) 1855c84f3f3cSopenharmony_ci{ 1856c84f3f3cSopenharmony_ci x_load_hist(x_histp + x_arg); 1857c84f3f3cSopenharmony_ci return (KSTD); 1858c84f3f3cSopenharmony_ci} 1859c84f3f3cSopenharmony_ci 1860c84f3f3cSopenharmony_ci/* 1861c84f3f3cSopenharmony_ci * Goto a particular history number obtained from argument. 1862c84f3f3cSopenharmony_ci * If no argument is given history 1 is probably not what you 1863c84f3f3cSopenharmony_ci * want so we'll simply go to the oldest one. 1864c84f3f3cSopenharmony_ci */ 1865c84f3f3cSopenharmony_cistatic int 1866c84f3f3cSopenharmony_cix_goto_hist(int c MKSH_A_UNUSED) 1867c84f3f3cSopenharmony_ci{ 1868c84f3f3cSopenharmony_ci if (x_arg_defaulted) 1869c84f3f3cSopenharmony_ci x_load_hist(history); 1870c84f3f3cSopenharmony_ci else 1871c84f3f3cSopenharmony_ci x_load_hist(histptr + x_arg - source->line); 1872c84f3f3cSopenharmony_ci return (KSTD); 1873c84f3f3cSopenharmony_ci} 1874c84f3f3cSopenharmony_ci 1875c84f3f3cSopenharmony_cistatic void 1876c84f3f3cSopenharmony_cix_load_hist(char **hp) 1877c84f3f3cSopenharmony_ci{ 1878c84f3f3cSopenharmony_ci char *sp = NULL; 1879c84f3f3cSopenharmony_ci 1880c84f3f3cSopenharmony_ci if (hp == histptr + 1) { 1881c84f3f3cSopenharmony_ci sp = holdbufp; 1882c84f3f3cSopenharmony_ci modified = 0; 1883c84f3f3cSopenharmony_ci } else if (hp < history || hp > histptr) { 1884c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1885c84f3f3cSopenharmony_ci return; 1886c84f3f3cSopenharmony_ci } 1887c84f3f3cSopenharmony_ci if (sp == NULL) 1888c84f3f3cSopenharmony_ci sp = *hp; 1889c84f3f3cSopenharmony_ci x_histp = hp; 1890c84f3f3cSopenharmony_ci if (modified) 1891c84f3f3cSopenharmony_ci strlcpy(holdbufp, xbuf, LINE); 1892c84f3f3cSopenharmony_ci strlcpy(xbuf, sp, xend - xbuf); 1893c84f3f3cSopenharmony_ci xbp = xbuf; 1894c84f3f3cSopenharmony_ci xep = xcp = strnul(xbuf); 1895c84f3f3cSopenharmony_ci x_adjust(); 1896c84f3f3cSopenharmony_ci modified = 0; 1897c84f3f3cSopenharmony_ci} 1898c84f3f3cSopenharmony_ci 1899c84f3f3cSopenharmony_cistatic int 1900c84f3f3cSopenharmony_cix_nl_next_com(int c MKSH_A_UNUSED) 1901c84f3f3cSopenharmony_ci{ 1902c84f3f3cSopenharmony_ci if (!modified) 1903c84f3f3cSopenharmony_ci x_histmcp = x_histp; 1904c84f3f3cSopenharmony_ci if (!x_histncp || (x_histmcp != x_histncp && x_histmcp != histptr + 1)) 1905c84f3f3cSopenharmony_ci /* fresh start of ^O */ 1906c84f3f3cSopenharmony_ci x_histncp = x_histmcp; 1907c84f3f3cSopenharmony_ci x_nextcmd = source->line - (histptr - x_histncp) + 1; 1908c84f3f3cSopenharmony_ci return (x_newline('\n')); 1909c84f3f3cSopenharmony_ci} 1910c84f3f3cSopenharmony_ci 1911c84f3f3cSopenharmony_cistatic int 1912c84f3f3cSopenharmony_cix_eot_del(int c) 1913c84f3f3cSopenharmony_ci{ 1914c84f3f3cSopenharmony_ci if (xep == xbuf && x_arg_defaulted) 1915c84f3f3cSopenharmony_ci return (x_end_of_text(c)); 1916c84f3f3cSopenharmony_ci else 1917c84f3f3cSopenharmony_ci return (x_del_char(c)); 1918c84f3f3cSopenharmony_ci} 1919c84f3f3cSopenharmony_ci 1920c84f3f3cSopenharmony_ci/* reverse incremental history search */ 1921c84f3f3cSopenharmony_cistatic int 1922c84f3f3cSopenharmony_cix_search_hist(int c) 1923c84f3f3cSopenharmony_ci{ 1924c84f3f3cSopenharmony_ci int offset = -1; /* offset of match in xbuf, else -1 */ 1925c84f3f3cSopenharmony_ci char pat[80 + 1]; /* pattern buffer */ 1926c84f3f3cSopenharmony_ci char *p = pat; 1927c84f3f3cSopenharmony_ci unsigned char f; 1928c84f3f3cSopenharmony_ci 1929c84f3f3cSopenharmony_ci *p = '\0'; 1930c84f3f3cSopenharmony_ci while (/* CONSTCOND */ 1) { 1931c84f3f3cSopenharmony_ci if (offset < 0) { 1932c84f3f3cSopenharmony_ci x_e_puts("\nI-search: "); 1933c84f3f3cSopenharmony_ci x_e_puts(pat); 1934c84f3f3cSopenharmony_ci } 1935c84f3f3cSopenharmony_ci x_flush(); 1936c84f3f3cSopenharmony_ci if ((c = x_e_getc()) < 0) 1937c84f3f3cSopenharmony_ci return (KSTD); 1938c84f3f3cSopenharmony_ci f = x_tab[0][c]; 1939c84f3f3cSopenharmony_ci if (c == CTRL_BO) { 1940c84f3f3cSopenharmony_ci if ((f & 0x7F) == XFUNC_meta1) { 1941c84f3f3cSopenharmony_ci if ((c = x_e_getc()) < 0) 1942c84f3f3cSopenharmony_ci return (KSTD); 1943c84f3f3cSopenharmony_ci f = x_tab[1][c] & 0x7F; 1944c84f3f3cSopenharmony_ci if (f == XFUNC_meta1 || f == XFUNC_meta2) 1945c84f3f3cSopenharmony_ci x_meta1(CTRL_BO); 1946c84f3f3cSopenharmony_ci x_e_ungetc(c); 1947c84f3f3cSopenharmony_ci } 1948c84f3f3cSopenharmony_ci break; 1949c84f3f3cSopenharmony_ci } 1950c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 1951c84f3f3cSopenharmony_ci if (f & 0x80) { 1952c84f3f3cSopenharmony_ci f &= 0x7F; 1953c84f3f3cSopenharmony_ci if ((c = x_e_getc()) != '~') 1954c84f3f3cSopenharmony_ci x_e_ungetc(c); 1955c84f3f3cSopenharmony_ci } 1956c84f3f3cSopenharmony_ci#endif 1957c84f3f3cSopenharmony_ci if (f == XFUNC_search_hist) 1958c84f3f3cSopenharmony_ci offset = x_search(pat, 0, offset); 1959c84f3f3cSopenharmony_ci else if (f == XFUNC_del_back) { 1960c84f3f3cSopenharmony_ci if (p == pat) { 1961c84f3f3cSopenharmony_ci offset = -1; 1962c84f3f3cSopenharmony_ci break; 1963c84f3f3cSopenharmony_ci } 1964c84f3f3cSopenharmony_ci if (p > pat) { 1965c84f3f3cSopenharmony_ci p = x_bs0(p - 1, pat); 1966c84f3f3cSopenharmony_ci *p = '\0'; 1967c84f3f3cSopenharmony_ci } 1968c84f3f3cSopenharmony_ci if (p == pat) 1969c84f3f3cSopenharmony_ci offset = -1; 1970c84f3f3cSopenharmony_ci else 1971c84f3f3cSopenharmony_ci offset = x_search(pat, 1, offset); 1972c84f3f3cSopenharmony_ci continue; 1973c84f3f3cSopenharmony_ci } else if (f == XFUNC_insert) { 1974c84f3f3cSopenharmony_ci /* add char to pattern */ 1975c84f3f3cSopenharmony_ci /* overflow check... */ 1976c84f3f3cSopenharmony_ci if ((size_t)(p - pat) >= sizeof(pat) - 1) { 1977c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 1978c84f3f3cSopenharmony_ci continue; 1979c84f3f3cSopenharmony_ci } 1980c84f3f3cSopenharmony_ci *p++ = c, *p = '\0'; 1981c84f3f3cSopenharmony_ci if (offset >= 0) { 1982c84f3f3cSopenharmony_ci /* already have partial match */ 1983c84f3f3cSopenharmony_ci offset = x_match(xbuf, pat); 1984c84f3f3cSopenharmony_ci if (offset >= 0) { 1985c84f3f3cSopenharmony_ci x_goto(xbuf + offset + (p - pat) - 1986c84f3f3cSopenharmony_ci (*pat == '^' ? 1 : 0)); 1987c84f3f3cSopenharmony_ci continue; 1988c84f3f3cSopenharmony_ci } 1989c84f3f3cSopenharmony_ci } 1990c84f3f3cSopenharmony_ci offset = x_search(pat, 0, offset); 1991c84f3f3cSopenharmony_ci } else if (f == XFUNC_abort) { 1992c84f3f3cSopenharmony_ci if (offset >= 0) 1993c84f3f3cSopenharmony_ci x_load_hist(histptr + 1); 1994c84f3f3cSopenharmony_ci break; 1995c84f3f3cSopenharmony_ci } else { 1996c84f3f3cSopenharmony_ci /* other command */ 1997c84f3f3cSopenharmony_ci x_e_ungetc(c); 1998c84f3f3cSopenharmony_ci break; 1999c84f3f3cSopenharmony_ci } 2000c84f3f3cSopenharmony_ci } 2001c84f3f3cSopenharmony_ci if (offset < 0) 2002c84f3f3cSopenharmony_ci x_redraw('\n'); 2003c84f3f3cSopenharmony_ci return (KSTD); 2004c84f3f3cSopenharmony_ci} 2005c84f3f3cSopenharmony_ci 2006c84f3f3cSopenharmony_ci/* search backward from current line */ 2007c84f3f3cSopenharmony_cistatic int 2008c84f3f3cSopenharmony_cix_search(const char *pat, int sameline, int offset) 2009c84f3f3cSopenharmony_ci{ 2010c84f3f3cSopenharmony_ci char **hp; 2011c84f3f3cSopenharmony_ci int i; 2012c84f3f3cSopenharmony_ci size_t patlen = strlen(pat); 2013c84f3f3cSopenharmony_ci 2014c84f3f3cSopenharmony_ci if (*pat == '^') 2015c84f3f3cSopenharmony_ci --patlen; 2016c84f3f3cSopenharmony_ci for (hp = x_histp - (sameline ? 0 : 1); hp >= history; --hp) { 2017c84f3f3cSopenharmony_ci i = x_match(*hp, pat); 2018c84f3f3cSopenharmony_ci if (i >= 0) { 2019c84f3f3cSopenharmony_ci if (offset < 0) 2020c84f3f3cSopenharmony_ci x_e_putc2('\n'); 2021c84f3f3cSopenharmony_ci x_load_hist(hp); 2022c84f3f3cSopenharmony_ci x_goto(xbuf + i + patlen); 2023c84f3f3cSopenharmony_ci return (i); 2024c84f3f3cSopenharmony_ci } 2025c84f3f3cSopenharmony_ci } 2026c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 2027c84f3f3cSopenharmony_ci x_histp = histptr; 2028c84f3f3cSopenharmony_ci return (-1); 2029c84f3f3cSopenharmony_ci} 2030c84f3f3cSopenharmony_ci 2031c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 2032c84f3f3cSopenharmony_ci/* anchored search up from current line */ 2033c84f3f3cSopenharmony_cistatic int 2034c84f3f3cSopenharmony_cix_search_hist_up(int c MKSH_A_UNUSED) 2035c84f3f3cSopenharmony_ci{ 2036c84f3f3cSopenharmony_ci return (x_search_dir(-1)); 2037c84f3f3cSopenharmony_ci} 2038c84f3f3cSopenharmony_ci 2039c84f3f3cSopenharmony_ci/* anchored search down from current line */ 2040c84f3f3cSopenharmony_cistatic int 2041c84f3f3cSopenharmony_cix_search_hist_dn(int c MKSH_A_UNUSED) 2042c84f3f3cSopenharmony_ci{ 2043c84f3f3cSopenharmony_ci return (x_search_dir(1)); 2044c84f3f3cSopenharmony_ci} 2045c84f3f3cSopenharmony_ci 2046c84f3f3cSopenharmony_ci/* anchored search in the indicated direction */ 2047c84f3f3cSopenharmony_cistatic int 2048c84f3f3cSopenharmony_cix_search_dir(int search_dir /* should've been bool */) 2049c84f3f3cSopenharmony_ci{ 2050c84f3f3cSopenharmony_ci char **hp = x_histp + search_dir; 2051c84f3f3cSopenharmony_ci size_t curs = xcp - xbuf; 2052c84f3f3cSopenharmony_ci 2053c84f3f3cSopenharmony_ci while (histptr >= hp && hp >= history) { 2054c84f3f3cSopenharmony_ci if (strncmp(xbuf, *hp, curs) == 0) { 2055c84f3f3cSopenharmony_ci x_load_hist(hp); 2056c84f3f3cSopenharmony_ci x_goto(xbuf + curs); 2057c84f3f3cSopenharmony_ci break; 2058c84f3f3cSopenharmony_ci } 2059c84f3f3cSopenharmony_ci hp += search_dir; 2060c84f3f3cSopenharmony_ci } 2061c84f3f3cSopenharmony_ci return (KSTD); 2062c84f3f3cSopenharmony_ci} 2063c84f3f3cSopenharmony_ci#endif 2064c84f3f3cSopenharmony_ci 2065c84f3f3cSopenharmony_ci/* return position of first match of pattern in string, else -1 */ 2066c84f3f3cSopenharmony_cistatic int 2067c84f3f3cSopenharmony_cix_match(const char *str, const char *pat) 2068c84f3f3cSopenharmony_ci{ 2069c84f3f3cSopenharmony_ci if (*pat == '^') { 2070c84f3f3cSopenharmony_ci return ((strncmp(str, pat + 1, strlen(pat + 1)) == 0) ? 0 : -1); 2071c84f3f3cSopenharmony_ci } else { 2072c84f3f3cSopenharmony_ci char *q = strstr(str, pat); 2073c84f3f3cSopenharmony_ci return ((q == NULL) ? -1 : q - str); 2074c84f3f3cSopenharmony_ci } 2075c84f3f3cSopenharmony_ci} 2076c84f3f3cSopenharmony_ci 2077c84f3f3cSopenharmony_cistatic int 2078c84f3f3cSopenharmony_cix_del_line(int c MKSH_A_UNUSED) 2079c84f3f3cSopenharmony_ci{ 2080c84f3f3cSopenharmony_ci *xep = 0; 2081c84f3f3cSopenharmony_ci x_push(xep - (xcp = xbuf)); 2082c84f3f3cSopenharmony_ci xlp = xbp = xep = xbuf; 2083c84f3f3cSopenharmony_ci xlp_valid = true; 2084c84f3f3cSopenharmony_ci *xcp = 0; 2085c84f3f3cSopenharmony_ci xmp = NULL; 2086c84f3f3cSopenharmony_ci x_redraw('\r'); 2087c84f3f3cSopenharmony_ci x_modified(); 2088c84f3f3cSopenharmony_ci return (KSTD); 2089c84f3f3cSopenharmony_ci} 2090c84f3f3cSopenharmony_ci 2091c84f3f3cSopenharmony_cistatic int 2092c84f3f3cSopenharmony_cix_mv_end(int c MKSH_A_UNUSED) 2093c84f3f3cSopenharmony_ci{ 2094c84f3f3cSopenharmony_ci x_goto(xep); 2095c84f3f3cSopenharmony_ci return (KSTD); 2096c84f3f3cSopenharmony_ci} 2097c84f3f3cSopenharmony_ci 2098c84f3f3cSopenharmony_cistatic int 2099c84f3f3cSopenharmony_cix_mv_beg(int c MKSH_A_UNUSED) 2100c84f3f3cSopenharmony_ci{ 2101c84f3f3cSopenharmony_ci x_goto(xbuf); 2102c84f3f3cSopenharmony_ci return (KSTD); 2103c84f3f3cSopenharmony_ci} 2104c84f3f3cSopenharmony_ci 2105c84f3f3cSopenharmony_cistatic int 2106c84f3f3cSopenharmony_cix_draw_line(int c MKSH_A_UNUSED) 2107c84f3f3cSopenharmony_ci{ 2108c84f3f3cSopenharmony_ci x_redraw('\n'); 2109c84f3f3cSopenharmony_ci return (KSTD); 2110c84f3f3cSopenharmony_ci} 2111c84f3f3cSopenharmony_ci 2112c84f3f3cSopenharmony_cistatic int 2113c84f3f3cSopenharmony_cix_cls(int c MKSH_A_UNUSED) 2114c84f3f3cSopenharmony_ci{ 2115c84f3f3cSopenharmony_ci shf_puts(MKSH_CLS_STRING, shl_out); 2116c84f3f3cSopenharmony_ci x_redraw(0); 2117c84f3f3cSopenharmony_ci return (KSTD); 2118c84f3f3cSopenharmony_ci} 2119c84f3f3cSopenharmony_ci 2120c84f3f3cSopenharmony_ci/* 2121c84f3f3cSopenharmony_ci * clear line from x_col (current cursor position) to xx_cols - 2, 2122c84f3f3cSopenharmony_ci * then output lastch, then go back to x_col; if lastch is space, 2123c84f3f3cSopenharmony_ci * clear with termcap instead of spaces, or not if line_was_cleared; 2124c84f3f3cSopenharmony_ci * lastch MUST be an ASCII character with wcwidth(lastch) == 1 2125c84f3f3cSopenharmony_ci */ 2126c84f3f3cSopenharmony_cistatic void 2127c84f3f3cSopenharmony_cix_clrtoeol(int lastch, bool line_was_cleared) 2128c84f3f3cSopenharmony_ci{ 2129c84f3f3cSopenharmony_ci int col; 2130c84f3f3cSopenharmony_ci 2131c84f3f3cSopenharmony_ci if (lastch == ' ' && !line_was_cleared && x_term_mode == 1) { 2132c84f3f3cSopenharmony_ci shf_puts(KSH_ESC_STRING "[K", shl_out); 2133c84f3f3cSopenharmony_ci line_was_cleared = true; 2134c84f3f3cSopenharmony_ci } 2135c84f3f3cSopenharmony_ci if (lastch == ' ' && line_was_cleared) 2136c84f3f3cSopenharmony_ci return; 2137c84f3f3cSopenharmony_ci 2138c84f3f3cSopenharmony_ci col = x_col; 2139c84f3f3cSopenharmony_ci while (col < (xx_cols - 2)) { 2140c84f3f3cSopenharmony_ci x_putc(' '); 2141c84f3f3cSopenharmony_ci ++col; 2142c84f3f3cSopenharmony_ci } 2143c84f3f3cSopenharmony_ci x_putc(lastch); 2144c84f3f3cSopenharmony_ci ++col; 2145c84f3f3cSopenharmony_ci while (col > x_col) { 2146c84f3f3cSopenharmony_ci x_putc('\b'); 2147c84f3f3cSopenharmony_ci --col; 2148c84f3f3cSopenharmony_ci } 2149c84f3f3cSopenharmony_ci} 2150c84f3f3cSopenharmony_ci 2151c84f3f3cSopenharmony_ci/* output the prompt, assuming a line has just been started */ 2152c84f3f3cSopenharmony_cistatic void 2153c84f3f3cSopenharmony_cix_pprompt(void) 2154c84f3f3cSopenharmony_ci{ 2155c84f3f3cSopenharmony_ci if (prompt_trunc != -1) 2156c84f3f3cSopenharmony_ci pprompt(prompt, prompt_trunc); 2157c84f3f3cSopenharmony_ci x_col = pwidth; 2158c84f3f3cSopenharmony_ci} 2159c84f3f3cSopenharmony_ci 2160c84f3f3cSopenharmony_ci/* output CR, then redraw the line, clearing to EOL if needed (cr ≠ 0, LF) */ 2161c84f3f3cSopenharmony_cistatic void 2162c84f3f3cSopenharmony_cix_redraw(int cr) 2163c84f3f3cSopenharmony_ci{ 2164c84f3f3cSopenharmony_ci int lch; 2165c84f3f3cSopenharmony_ci 2166c84f3f3cSopenharmony_ci x_adj_ok = false; 2167c84f3f3cSopenharmony_ci /* clear the line */ 2168c84f3f3cSopenharmony_ci x_e_putc2(cr ? cr : '\r'); 2169c84f3f3cSopenharmony_ci x_flush(); 2170c84f3f3cSopenharmony_ci /* display the prompt */ 2171c84f3f3cSopenharmony_ci if (xbp == xbuf) 2172c84f3f3cSopenharmony_ci x_pprompt(); 2173c84f3f3cSopenharmony_ci x_displen = xx_cols - 2 - x_col; 2174c84f3f3cSopenharmony_ci /* display the line content */ 2175c84f3f3cSopenharmony_ci xlp_valid = false; 2176c84f3f3cSopenharmony_ci x_zots(xbp); 2177c84f3f3cSopenharmony_ci /* check whether there is more off-screen */ 2178c84f3f3cSopenharmony_ci lch = xep > xlp ? (xbp > xbuf ? '*' : '>') : (xbp > xbuf) ? '<' : ' '; 2179c84f3f3cSopenharmony_ci /* clear the rest of the line */ 2180c84f3f3cSopenharmony_ci x_clrtoeol(lch, !cr || cr == '\n'); 2181c84f3f3cSopenharmony_ci /* go back to actual cursor position */ 2182c84f3f3cSopenharmony_ci x_lastpos(); 2183c84f3f3cSopenharmony_ci x_adj_ok = true; 2184c84f3f3cSopenharmony_ci} 2185c84f3f3cSopenharmony_ci 2186c84f3f3cSopenharmony_cistatic int 2187c84f3f3cSopenharmony_cix_transpose(int c MKSH_A_UNUSED) 2188c84f3f3cSopenharmony_ci{ 2189c84f3f3cSopenharmony_ci unsigned int tmpa, tmpb; 2190c84f3f3cSopenharmony_ci 2191c84f3f3cSopenharmony_ci /*- 2192c84f3f3cSopenharmony_ci * What transpose is meant to do seems to be up for debate. This 2193c84f3f3cSopenharmony_ci * is a general summary of the options; the text is abcd with the 2194c84f3f3cSopenharmony_ci * upper case character or underscore indicating the cursor position: 2195c84f3f3cSopenharmony_ci * Who Before After Before After 2196c84f3f3cSopenharmony_ci * AT&T ksh in emacs mode: abCd abdC abcd_ (bell) 2197c84f3f3cSopenharmony_ci * AT&T ksh in gmacs mode: abCd baCd abcd_ abdc_ 2198c84f3f3cSopenharmony_ci * gnu emacs: abCd acbD abcd_ abdc_ 2199c84f3f3cSopenharmony_ci * Pdksh currently goes with GNU behavior since I believe this is the 2200c84f3f3cSopenharmony_ci * most common version of emacs, unless in gmacs mode, in which case 2201c84f3f3cSopenharmony_ci * it does the AT&T ksh gmacs mode. 2202c84f3f3cSopenharmony_ci * This should really be broken up into 3 functions so users can bind 2203c84f3f3cSopenharmony_ci * to the one they want. 2204c84f3f3cSopenharmony_ci */ 2205c84f3f3cSopenharmony_ci if (xcp == xbuf) { 2206c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 2207c84f3f3cSopenharmony_ci return (KSTD); 2208c84f3f3cSopenharmony_ci } else if (xcp == xep || Flag(FGMACS)) { 2209c84f3f3cSopenharmony_ci if (xcp - xbuf == 1) { 2210c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 2211c84f3f3cSopenharmony_ci return (KSTD); 2212c84f3f3cSopenharmony_ci } 2213c84f3f3cSopenharmony_ci /* 2214c84f3f3cSopenharmony_ci * Gosling/Unipress emacs style: Swap two characters before 2215c84f3f3cSopenharmony_ci * the cursor, do not change cursor position 2216c84f3f3cSopenharmony_ci */ 2217c84f3f3cSopenharmony_ci x_bs3(&xcp); 2218c84f3f3cSopenharmony_ci if (utf_mbtowc(&tmpa, xcp) == (size_t)-1) { 2219c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 2220c84f3f3cSopenharmony_ci return (KSTD); 2221c84f3f3cSopenharmony_ci } 2222c84f3f3cSopenharmony_ci x_bs3(&xcp); 2223c84f3f3cSopenharmony_ci if (utf_mbtowc(&tmpb, xcp) == (size_t)-1) { 2224c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 2225c84f3f3cSopenharmony_ci return (KSTD); 2226c84f3f3cSopenharmony_ci } 2227c84f3f3cSopenharmony_ci utf_wctomb(xcp, tmpa); 2228c84f3f3cSopenharmony_ci x_zotc3(&xcp); 2229c84f3f3cSopenharmony_ci utf_wctomb(xcp, tmpb); 2230c84f3f3cSopenharmony_ci x_zotc3(&xcp); 2231c84f3f3cSopenharmony_ci } else { 2232c84f3f3cSopenharmony_ci /* 2233c84f3f3cSopenharmony_ci * GNU emacs style: Swap the characters before and under the 2234c84f3f3cSopenharmony_ci * cursor, move cursor position along one. 2235c84f3f3cSopenharmony_ci */ 2236c84f3f3cSopenharmony_ci if (utf_mbtowc(&tmpa, xcp) == (size_t)-1) { 2237c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 2238c84f3f3cSopenharmony_ci return (KSTD); 2239c84f3f3cSopenharmony_ci } 2240c84f3f3cSopenharmony_ci x_bs3(&xcp); 2241c84f3f3cSopenharmony_ci if (utf_mbtowc(&tmpb, xcp) == (size_t)-1) { 2242c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 2243c84f3f3cSopenharmony_ci return (KSTD); 2244c84f3f3cSopenharmony_ci } 2245c84f3f3cSopenharmony_ci utf_wctomb(xcp, tmpa); 2246c84f3f3cSopenharmony_ci x_zotc3(&xcp); 2247c84f3f3cSopenharmony_ci utf_wctomb(xcp, tmpb); 2248c84f3f3cSopenharmony_ci x_zotc3(&xcp); 2249c84f3f3cSopenharmony_ci } 2250c84f3f3cSopenharmony_ci x_modified(); 2251c84f3f3cSopenharmony_ci return (KSTD); 2252c84f3f3cSopenharmony_ci} 2253c84f3f3cSopenharmony_ci 2254c84f3f3cSopenharmony_cistatic int 2255c84f3f3cSopenharmony_cix_literal(int c MKSH_A_UNUSED) 2256c84f3f3cSopenharmony_ci{ 2257c84f3f3cSopenharmony_ci x_curprefix = -1; 2258c84f3f3cSopenharmony_ci return (KSTD); 2259c84f3f3cSopenharmony_ci} 2260c84f3f3cSopenharmony_ci 2261c84f3f3cSopenharmony_cistatic int 2262c84f3f3cSopenharmony_cix_meta1(int c MKSH_A_UNUSED) 2263c84f3f3cSopenharmony_ci{ 2264c84f3f3cSopenharmony_ci x_curprefix = 1; 2265c84f3f3cSopenharmony_ci return (KSTD); 2266c84f3f3cSopenharmony_ci} 2267c84f3f3cSopenharmony_ci 2268c84f3f3cSopenharmony_cistatic int 2269c84f3f3cSopenharmony_cix_meta2(int c MKSH_A_UNUSED) 2270c84f3f3cSopenharmony_ci{ 2271c84f3f3cSopenharmony_ci x_curprefix = 2; 2272c84f3f3cSopenharmony_ci return (KSTD); 2273c84f3f3cSopenharmony_ci} 2274c84f3f3cSopenharmony_ci 2275c84f3f3cSopenharmony_cistatic int 2276c84f3f3cSopenharmony_cix_meta3(int c MKSH_A_UNUSED) 2277c84f3f3cSopenharmony_ci{ 2278c84f3f3cSopenharmony_ci x_curprefix = 3; 2279c84f3f3cSopenharmony_ci return (KSTD); 2280c84f3f3cSopenharmony_ci} 2281c84f3f3cSopenharmony_ci 2282c84f3f3cSopenharmony_cistatic int 2283c84f3f3cSopenharmony_cix_kill(int c MKSH_A_UNUSED) 2284c84f3f3cSopenharmony_ci{ 2285c84f3f3cSopenharmony_ci size_t col = xcp - xbuf; 2286c84f3f3cSopenharmony_ci size_t lastcol = xep - xbuf; 2287c84f3f3cSopenharmony_ci size_t ndel, narg; 2288c84f3f3cSopenharmony_ci 2289c84f3f3cSopenharmony_ci if (x_arg_defaulted || (narg = x_arg) > lastcol) 2290c84f3f3cSopenharmony_ci narg = lastcol; 2291c84f3f3cSopenharmony_ci if (narg < col) { 2292c84f3f3cSopenharmony_ci x_goto(xbuf + narg); 2293c84f3f3cSopenharmony_ci ndel = col - narg; 2294c84f3f3cSopenharmony_ci } else 2295c84f3f3cSopenharmony_ci ndel = narg - col; 2296c84f3f3cSopenharmony_ci x_delete(x_nb2nc(ndel), true); 2297c84f3f3cSopenharmony_ci return (KSTD); 2298c84f3f3cSopenharmony_ci} 2299c84f3f3cSopenharmony_ci 2300c84f3f3cSopenharmony_cistatic void 2301c84f3f3cSopenharmony_cix_push(size_t nchars) 2302c84f3f3cSopenharmony_ci{ 2303c84f3f3cSopenharmony_ci afree(killstack[killsp], AEDIT); 2304c84f3f3cSopenharmony_ci strndupx(killstack[killsp], xcp, nchars, AEDIT); 2305c84f3f3cSopenharmony_ci killsp = (killsp + 1) % KILLSIZE; 2306c84f3f3cSopenharmony_ci} 2307c84f3f3cSopenharmony_ci 2308c84f3f3cSopenharmony_cistatic int 2309c84f3f3cSopenharmony_cix_yank(int c MKSH_A_UNUSED) 2310c84f3f3cSopenharmony_ci{ 2311c84f3f3cSopenharmony_ci if (killsp == 0) 2312c84f3f3cSopenharmony_ci killtp = KILLSIZE; 2313c84f3f3cSopenharmony_ci else 2314c84f3f3cSopenharmony_ci killtp = killsp; 2315c84f3f3cSopenharmony_ci killtp--; 2316c84f3f3cSopenharmony_ci if (killstack[killtp] == 0) { 2317c84f3f3cSopenharmony_ci x_e_puts("\nnothing to yank"); 2318c84f3f3cSopenharmony_ci x_redraw('\n'); 2319c84f3f3cSopenharmony_ci return (KSTD); 2320c84f3f3cSopenharmony_ci } 2321c84f3f3cSopenharmony_ci xmp = xcp; 2322c84f3f3cSopenharmony_ci x_ins(killstack[killtp]); 2323c84f3f3cSopenharmony_ci return (KSTD); 2324c84f3f3cSopenharmony_ci} 2325c84f3f3cSopenharmony_ci 2326c84f3f3cSopenharmony_cistatic int 2327c84f3f3cSopenharmony_cix_meta_yank(int c MKSH_A_UNUSED) 2328c84f3f3cSopenharmony_ci{ 2329c84f3f3cSopenharmony_ci size_t len; 2330c84f3f3cSopenharmony_ci 2331c84f3f3cSopenharmony_ci if ((x_last_command != XFUNC_yank && x_last_command != XFUNC_meta_yank) || 2332c84f3f3cSopenharmony_ci killstack[killtp] == 0) { 2333c84f3f3cSopenharmony_ci killtp = killsp; 2334c84f3f3cSopenharmony_ci x_e_puts("\nyank something first"); 2335c84f3f3cSopenharmony_ci x_redraw('\n'); 2336c84f3f3cSopenharmony_ci return (KSTD); 2337c84f3f3cSopenharmony_ci } 2338c84f3f3cSopenharmony_ci len = strlen(killstack[killtp]); 2339c84f3f3cSopenharmony_ci x_goto(xcp - len); 2340c84f3f3cSopenharmony_ci x_delete(x_nb2nc(len), false); 2341c84f3f3cSopenharmony_ci do { 2342c84f3f3cSopenharmony_ci if (killtp == 0) 2343c84f3f3cSopenharmony_ci killtp = KILLSIZE - 1; 2344c84f3f3cSopenharmony_ci else 2345c84f3f3cSopenharmony_ci killtp--; 2346c84f3f3cSopenharmony_ci } while (killstack[killtp] == 0); 2347c84f3f3cSopenharmony_ci x_ins(killstack[killtp]); 2348c84f3f3cSopenharmony_ci return (KSTD); 2349c84f3f3cSopenharmony_ci} 2350c84f3f3cSopenharmony_ci 2351c84f3f3cSopenharmony_ci/* fake receiving an interrupt */ 2352c84f3f3cSopenharmony_cistatic void 2353c84f3f3cSopenharmony_cix_intr(int signo, int c) 2354c84f3f3cSopenharmony_ci{ 2355c84f3f3cSopenharmony_ci x_vi_zotc(c); 2356c84f3f3cSopenharmony_ci *xep = '\0'; 2357c84f3f3cSopenharmony_ci strip_nuls(xbuf, xep - xbuf); 2358c84f3f3cSopenharmony_ci if (*xbuf) 2359c84f3f3cSopenharmony_ci histsave(&source->line, xbuf, HIST_STORE, true); 2360c84f3f3cSopenharmony_ci xlp = xep = xcp = xbp = xbuf; 2361c84f3f3cSopenharmony_ci xlp_valid = true; 2362c84f3f3cSopenharmony_ci *xcp = 0; 2363c84f3f3cSopenharmony_ci x_modified(); 2364c84f3f3cSopenharmony_ci x_flush(); 2365c84f3f3cSopenharmony_ci trapsig(signo); 2366c84f3f3cSopenharmony_ci x_mode(false); 2367c84f3f3cSopenharmony_ci unwind(LSHELL); 2368c84f3f3cSopenharmony_ci} 2369c84f3f3cSopenharmony_ci 2370c84f3f3cSopenharmony_cistatic int 2371c84f3f3cSopenharmony_cix_abort(int c MKSH_A_UNUSED) 2372c84f3f3cSopenharmony_ci{ 2373c84f3f3cSopenharmony_ci return (KINTR); 2374c84f3f3cSopenharmony_ci} 2375c84f3f3cSopenharmony_ci 2376c84f3f3cSopenharmony_cistatic int 2377c84f3f3cSopenharmony_cix_error(int c MKSH_A_UNUSED) 2378c84f3f3cSopenharmony_ci{ 2379c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 2380c84f3f3cSopenharmony_ci return (KSTD); 2381c84f3f3cSopenharmony_ci} 2382c84f3f3cSopenharmony_ci 2383c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 2384c84f3f3cSopenharmony_ci/* special VT100 style key sequence hack */ 2385c84f3f3cSopenharmony_cistatic int 2386c84f3f3cSopenharmony_cix_vt_hack(int c) 2387c84f3f3cSopenharmony_ci{ 2388c84f3f3cSopenharmony_ci /* we only support PF2-'1' for now */ 2389c84f3f3cSopenharmony_ci if (c != (2 << 8 | '1')) 2390c84f3f3cSopenharmony_ci return (x_error(c)); 2391c84f3f3cSopenharmony_ci 2392c84f3f3cSopenharmony_ci /* what's the next character? */ 2393c84f3f3cSopenharmony_ci switch ((c = x_e_getc())) { 2394c84f3f3cSopenharmony_ci case '~': 2395c84f3f3cSopenharmony_ci x_arg = 1; 2396c84f3f3cSopenharmony_ci x_arg_defaulted = true; 2397c84f3f3cSopenharmony_ci return (x_mv_beg(0)); 2398c84f3f3cSopenharmony_ci case ';': 2399c84f3f3cSopenharmony_ci /* "interesting" sequence detected */ 2400c84f3f3cSopenharmony_ci break; 2401c84f3f3cSopenharmony_ci default: 2402c84f3f3cSopenharmony_ci goto unwind_err; 2403c84f3f3cSopenharmony_ci } 2404c84f3f3cSopenharmony_ci 2405c84f3f3cSopenharmony_ci /* XXX x_e_ungetc is one-octet only */ 2406c84f3f3cSopenharmony_ci if ((c = x_e_getc()) != '5' && c != '3') 2407c84f3f3cSopenharmony_ci goto unwind_err; 2408c84f3f3cSopenharmony_ci 2409c84f3f3cSopenharmony_ci /*- 2410c84f3f3cSopenharmony_ci * At this point, we have read the following octets so far: 2411c84f3f3cSopenharmony_ci * - ESC+[ or ESC+O or Ctrl-X (Prefix 2) 2412c84f3f3cSopenharmony_ci * - 1 (vt_hack) 2413c84f3f3cSopenharmony_ci * - ; 2414c84f3f3cSopenharmony_ci * - 5 (Ctrl key combiner) or 3 (Alt key combiner) 2415c84f3f3cSopenharmony_ci * We can now accept one more octet designating the key. 2416c84f3f3cSopenharmony_ci */ 2417c84f3f3cSopenharmony_ci 2418c84f3f3cSopenharmony_ci switch ((c = x_e_getc())) { 2419c84f3f3cSopenharmony_ci case 'C': 2420c84f3f3cSopenharmony_ci return (x_mv_fword(c)); 2421c84f3f3cSopenharmony_ci case 'D': 2422c84f3f3cSopenharmony_ci return (x_mv_bword(c)); 2423c84f3f3cSopenharmony_ci } 2424c84f3f3cSopenharmony_ci 2425c84f3f3cSopenharmony_ci unwind_err: 2426c84f3f3cSopenharmony_ci x_e_ungetc(c); 2427c84f3f3cSopenharmony_ci return (x_error(c)); 2428c84f3f3cSopenharmony_ci} 2429c84f3f3cSopenharmony_ci#endif 2430c84f3f3cSopenharmony_ci 2431c84f3f3cSopenharmony_ciint 2432c84f3f3cSopenharmony_cix_bind_check(void) 2433c84f3f3cSopenharmony_ci{ 2434c84f3f3cSopenharmony_ci return (x_tab == NULL); 2435c84f3f3cSopenharmony_ci} 2436c84f3f3cSopenharmony_ci 2437c84f3f3cSopenharmony_cistatic XString x_bind_show_xs; 2438c84f3f3cSopenharmony_cistatic char *x_bind_show_xp; 2439c84f3f3cSopenharmony_ci 2440c84f3f3cSopenharmony_cistatic void 2441c84f3f3cSopenharmony_cix_bind_show_ch(unsigned char ch) 2442c84f3f3cSopenharmony_ci{ 2443c84f3f3cSopenharmony_ci Xcheck(x_bind_show_xs, x_bind_show_xp); 2444c84f3f3cSopenharmony_ci switch (ch) { 2445c84f3f3cSopenharmony_ci case ORD('^'): 2446c84f3f3cSopenharmony_ci case ORD('\\'): 2447c84f3f3cSopenharmony_ci case ORD('='): 2448c84f3f3cSopenharmony_ci *x_bind_show_xp++ = '\\'; 2449c84f3f3cSopenharmony_ci *x_bind_show_xp++ = ch; 2450c84f3f3cSopenharmony_ci break; 2451c84f3f3cSopenharmony_ci default: 2452c84f3f3cSopenharmony_ci if (ksh_isctrl(ch)) { 2453c84f3f3cSopenharmony_ci *x_bind_show_xp++ = '^'; 2454c84f3f3cSopenharmony_ci *x_bind_show_xp++ = ksh_unctrl(ch); 2455c84f3f3cSopenharmony_ci } else 2456c84f3f3cSopenharmony_ci *x_bind_show_xp++ = ch; 2457c84f3f3cSopenharmony_ci break; 2458c84f3f3cSopenharmony_ci } 2459c84f3f3cSopenharmony_ci} 2460c84f3f3cSopenharmony_ci 2461c84f3f3cSopenharmony_cistatic void 2462c84f3f3cSopenharmony_cix_bind_showone(int prefix, int key) 2463c84f3f3cSopenharmony_ci{ 2464c84f3f3cSopenharmony_ci unsigned char f = XFUNC_VALUE(x_tab[prefix][key]); 2465c84f3f3cSopenharmony_ci 2466c84f3f3cSopenharmony_ci if (!x_bind_show_xs.areap) 2467c84f3f3cSopenharmony_ci XinitN(x_bind_show_xs, 16, AEDIT); 2468c84f3f3cSopenharmony_ci 2469c84f3f3cSopenharmony_ci x_bind_show_xp = Xstring(x_bind_show_xs, x_bind_show_xp); 2470c84f3f3cSopenharmony_ci shf_puts("bind ", shl_stdout); 2471c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 2472c84f3f3cSopenharmony_ci if (f == XFUNC_ins_string) 2473c84f3f3cSopenharmony_ci shf_puts("-m ", shl_stdout); 2474c84f3f3cSopenharmony_ci#endif 2475c84f3f3cSopenharmony_ci switch (prefix) { 2476c84f3f3cSopenharmony_ci case 1: 2477c84f3f3cSopenharmony_ci x_bind_show_ch(CTRL_BO); 2478c84f3f3cSopenharmony_ci break; 2479c84f3f3cSopenharmony_ci case 2: 2480c84f3f3cSopenharmony_ci x_bind_show_ch(CTRL_X); 2481c84f3f3cSopenharmony_ci break; 2482c84f3f3cSopenharmony_ci case 3: 2483c84f3f3cSopenharmony_ci x_bind_show_ch(0); 2484c84f3f3cSopenharmony_ci break; 2485c84f3f3cSopenharmony_ci } 2486c84f3f3cSopenharmony_ci x_bind_show_ch(key); 2487c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 2488c84f3f3cSopenharmony_ci if (x_tab[prefix][key] & 0x80) 2489c84f3f3cSopenharmony_ci *x_bind_show_xp++ = '~'; 2490c84f3f3cSopenharmony_ci#endif 2491c84f3f3cSopenharmony_ci *x_bind_show_xp = '\0'; 2492c84f3f3cSopenharmony_ci x_bind_show_xp = Xstring(x_bind_show_xs, x_bind_show_xp); 2493c84f3f3cSopenharmony_ci print_value_quoted(shl_stdout, x_bind_show_xp); 2494c84f3f3cSopenharmony_ci shf_putc('=', shl_stdout); 2495c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 2496c84f3f3cSopenharmony_ci if (f == XFUNC_ins_string) { 2497c84f3f3cSopenharmony_ci const unsigned char *cp = (const void *)x_atab[prefix][key]; 2498c84f3f3cSopenharmony_ci unsigned char c; 2499c84f3f3cSopenharmony_ci 2500c84f3f3cSopenharmony_ci while ((c = *cp++)) 2501c84f3f3cSopenharmony_ci x_bind_show_ch(c); 2502c84f3f3cSopenharmony_ci *x_bind_show_xp = '\0'; 2503c84f3f3cSopenharmony_ci x_bind_show_xp = Xstring(x_bind_show_xs, x_bind_show_xp); 2504c84f3f3cSopenharmony_ci print_value_quoted(shl_stdout, x_bind_show_xp); 2505c84f3f3cSopenharmony_ci } else 2506c84f3f3cSopenharmony_ci#endif 2507c84f3f3cSopenharmony_ci shf_puts(x_ftab[f].xf_name, shl_stdout); 2508c84f3f3cSopenharmony_ci shf_putc('\n', shl_stdout); 2509c84f3f3cSopenharmony_ci} 2510c84f3f3cSopenharmony_ci 2511c84f3f3cSopenharmony_ciint 2512c84f3f3cSopenharmony_cix_bind_list(void) 2513c84f3f3cSopenharmony_ci{ 2514c84f3f3cSopenharmony_ci size_t f; 2515c84f3f3cSopenharmony_ci 2516c84f3f3cSopenharmony_ci for (f = 0; f < NELEM(x_ftab); f++) 2517c84f3f3cSopenharmony_ci if (!(x_ftab[f].xf_flags & XF_NOBIND)) 2518c84f3f3cSopenharmony_ci shprintf(Tf_sN, x_ftab[f].xf_name); 2519c84f3f3cSopenharmony_ci return (0); 2520c84f3f3cSopenharmony_ci} 2521c84f3f3cSopenharmony_ci 2522c84f3f3cSopenharmony_ciint 2523c84f3f3cSopenharmony_cix_bind_showall(void) 2524c84f3f3cSopenharmony_ci{ 2525c84f3f3cSopenharmony_ci int prefix, key; 2526c84f3f3cSopenharmony_ci 2527c84f3f3cSopenharmony_ci for (prefix = 0; prefix < X_NTABS; prefix++) 2528c84f3f3cSopenharmony_ci for (key = 0; key < X_TABSZ; key++) 2529c84f3f3cSopenharmony_ci switch (XFUNC_VALUE(x_tab[prefix][key])) { 2530c84f3f3cSopenharmony_ci case XFUNC_error: /* unset */ 2531c84f3f3cSopenharmony_ci case XFUNC_insert: /* auto-insert */ 2532c84f3f3cSopenharmony_ci break; 2533c84f3f3cSopenharmony_ci default: 2534c84f3f3cSopenharmony_ci x_bind_showone(prefix, key); 2535c84f3f3cSopenharmony_ci break; 2536c84f3f3cSopenharmony_ci } 2537c84f3f3cSopenharmony_ci return (0); 2538c84f3f3cSopenharmony_ci} 2539c84f3f3cSopenharmony_ci 2540c84f3f3cSopenharmony_cistatic unsigned int 2541c84f3f3cSopenharmony_cix_bind_getc(const char **ccpp) 2542c84f3f3cSopenharmony_ci{ 2543c84f3f3cSopenharmony_ci unsigned int ch, ec; 2544c84f3f3cSopenharmony_ci 2545c84f3f3cSopenharmony_ci if ((ch = ord(**ccpp))) 2546c84f3f3cSopenharmony_ci ++(*ccpp); 2547c84f3f3cSopenharmony_ci switch (ch) { 2548c84f3f3cSopenharmony_ci case ORD('^'): 2549c84f3f3cSopenharmony_ci ch = ksh_toctrl(**ccpp) | 0x100U; 2550c84f3f3cSopenharmony_ci if (**ccpp) 2551c84f3f3cSopenharmony_ci ++(*ccpp); 2552c84f3f3cSopenharmony_ci break; 2553c84f3f3cSopenharmony_ci case ORD('\\'): 2554c84f3f3cSopenharmony_ci switch ((ec = ord(**ccpp))) { 2555c84f3f3cSopenharmony_ci case ORD('^'): 2556c84f3f3cSopenharmony_ci case ORD('\\'): 2557c84f3f3cSopenharmony_ci case ORD('='): 2558c84f3f3cSopenharmony_ci ch = ec | 0x100U; 2559c84f3f3cSopenharmony_ci ++(*ccpp); 2560c84f3f3cSopenharmony_ci break; 2561c84f3f3cSopenharmony_ci } 2562c84f3f3cSopenharmony_ci break; 2563c84f3f3cSopenharmony_ci } 2564c84f3f3cSopenharmony_ci return (ch); 2565c84f3f3cSopenharmony_ci} 2566c84f3f3cSopenharmony_ci 2567c84f3f3cSopenharmony_ciint 2568c84f3f3cSopenharmony_cix_bind(const char *s SMALLP(bool macro)) 2569c84f3f3cSopenharmony_ci{ 2570c84f3f3cSopenharmony_ci const char *ccp = s; 2571c84f3f3cSopenharmony_ci int prefix, key; 2572c84f3f3cSopenharmony_ci unsigned int c; 2573c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 2574c84f3f3cSopenharmony_ci bool hastilde = false; 2575c84f3f3cSopenharmony_ci char *ms = NULL; 2576c84f3f3cSopenharmony_ci#endif 2577c84f3f3cSopenharmony_ci 2578c84f3f3cSopenharmony_ci prefix = 0; 2579c84f3f3cSopenharmony_ci c = x_bind_getc(&ccp); 2580c84f3f3cSopenharmony_ci if (!c || c == ORD('=')) { 2581c84f3f3cSopenharmony_ci bi_errorf("no key to bind"); 2582c84f3f3cSopenharmony_ci return (1); 2583c84f3f3cSopenharmony_ci } 2584c84f3f3cSopenharmony_ci key = c & 0xFF; 2585c84f3f3cSopenharmony_ci while ((c = x_bind_getc(&ccp)) != ORD('=')) { 2586c84f3f3cSopenharmony_ci if (!c) { 2587c84f3f3cSopenharmony_ci x_bind_showone(prefix, key); 2588c84f3f3cSopenharmony_ci return (0); 2589c84f3f3cSopenharmony_ci } 2590c84f3f3cSopenharmony_ci switch (XFUNC_VALUE(x_tab[prefix][key])) { 2591c84f3f3cSopenharmony_ci case XFUNC_meta1: 2592c84f3f3cSopenharmony_ci prefix = 1; 2593c84f3f3cSopenharmony_ci if (0) 2594c84f3f3cSopenharmony_ci /* FALLTHROUGH */ 2595c84f3f3cSopenharmony_ci case XFUNC_meta2: 2596c84f3f3cSopenharmony_ci prefix = 2; 2597c84f3f3cSopenharmony_ci if (0) 2598c84f3f3cSopenharmony_ci /* FALLTHROUGH */ 2599c84f3f3cSopenharmony_ci case XFUNC_meta3: 2600c84f3f3cSopenharmony_ci prefix = 3; 2601c84f3f3cSopenharmony_ci key = c & 0xFF; 2602c84f3f3cSopenharmony_ci continue; 2603c84f3f3cSopenharmony_ci } 2604c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 2605c84f3f3cSopenharmony_ci if (c == ORD('~')) { 2606c84f3f3cSopenharmony_ci hastilde = true; 2607c84f3f3cSopenharmony_ci continue; 2608c84f3f3cSopenharmony_ci } 2609c84f3f3cSopenharmony_ci#endif 2610c84f3f3cSopenharmony_ci bi_errorf("too long key sequence: %s", s); 2611c84f3f3cSopenharmony_ci return (-1); 2612c84f3f3cSopenharmony_ci } 2613c84f3f3cSopenharmony_ci 2614c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 2615c84f3f3cSopenharmony_ci if (macro) { 2616c84f3f3cSopenharmony_ci char *cp; 2617c84f3f3cSopenharmony_ci 2618c84f3f3cSopenharmony_ci cp = ms = alloc(strlen(ccp) + 1, AEDIT); 2619c84f3f3cSopenharmony_ci while ((c = x_bind_getc(&ccp))) 2620c84f3f3cSopenharmony_ci *cp++ = c; 2621c84f3f3cSopenharmony_ci *cp = '\0'; 2622c84f3f3cSopenharmony_ci c = XFUNC_ins_string; 2623c84f3f3cSopenharmony_ci } else 2624c84f3f3cSopenharmony_ci#endif 2625c84f3f3cSopenharmony_ci if (!*ccp) { 2626c84f3f3cSopenharmony_ci c = XFUNC_insert; 2627c84f3f3cSopenharmony_ci } else { 2628c84f3f3cSopenharmony_ci for (c = 0; c < NELEM(x_ftab); ++c) 2629c84f3f3cSopenharmony_ci if (!strcmp(x_ftab[c].xf_name, ccp)) 2630c84f3f3cSopenharmony_ci break; 2631c84f3f3cSopenharmony_ci if (c == NELEM(x_ftab) || x_ftab[c].xf_flags & XF_NOBIND) { 2632c84f3f3cSopenharmony_ci bi_errorf("%s: no such editing command", ccp); 2633c84f3f3cSopenharmony_ci return (1); 2634c84f3f3cSopenharmony_ci } 2635c84f3f3cSopenharmony_ci } 2636c84f3f3cSopenharmony_ci 2637c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 2638c84f3f3cSopenharmony_ci if (XFUNC_VALUE(x_tab[prefix][key]) == XFUNC_ins_string) 2639c84f3f3cSopenharmony_ci afree(x_atab[prefix][key], AEDIT); 2640c84f3f3cSopenharmony_ci x_atab[prefix][key] = ms; 2641c84f3f3cSopenharmony_ci if (hastilde) 2642c84f3f3cSopenharmony_ci c |= 0x80U; 2643c84f3f3cSopenharmony_ci#endif 2644c84f3f3cSopenharmony_ci x_tab[prefix][key] = c; 2645c84f3f3cSopenharmony_ci 2646c84f3f3cSopenharmony_ci /* track what the user has bound, so x_mode(true) won't toast things */ 2647c84f3f3cSopenharmony_ci if (c == XFUNC_insert) 2648c84f3f3cSopenharmony_ci x_bound[(prefix * X_TABSZ + key) / 8] &= 2649c84f3f3cSopenharmony_ci ~(1 << ((prefix * X_TABSZ + key) % 8)); 2650c84f3f3cSopenharmony_ci else 2651c84f3f3cSopenharmony_ci x_bound[(prefix * X_TABSZ + key) / 8] |= 2652c84f3f3cSopenharmony_ci (1 << ((prefix * X_TABSZ + key) % 8)); 2653c84f3f3cSopenharmony_ci 2654c84f3f3cSopenharmony_ci return (0); 2655c84f3f3cSopenharmony_ci} 2656c84f3f3cSopenharmony_ci 2657c84f3f3cSopenharmony_cistatic void 2658c84f3f3cSopenharmony_cibind_if_not_bound(int p, int k, int func) 2659c84f3f3cSopenharmony_ci{ 2660c84f3f3cSopenharmony_ci int t; 2661c84f3f3cSopenharmony_ci 2662c84f3f3cSopenharmony_ci /* 2663c84f3f3cSopenharmony_ci * Has user already bound this key? 2664c84f3f3cSopenharmony_ci * If so, do not override it. 2665c84f3f3cSopenharmony_ci */ 2666c84f3f3cSopenharmony_ci t = p * X_TABSZ + k; 2667c84f3f3cSopenharmony_ci if (x_bound[t >> 3] & (1 << (t & 7))) 2668c84f3f3cSopenharmony_ci return; 2669c84f3f3cSopenharmony_ci 2670c84f3f3cSopenharmony_ci x_tab[p][k] = func; 2671c84f3f3cSopenharmony_ci} 2672c84f3f3cSopenharmony_ci 2673c84f3f3cSopenharmony_cistatic int 2674c84f3f3cSopenharmony_cix_set_mark(int c MKSH_A_UNUSED) 2675c84f3f3cSopenharmony_ci{ 2676c84f3f3cSopenharmony_ci xmp = xcp; 2677c84f3f3cSopenharmony_ci return (KSTD); 2678c84f3f3cSopenharmony_ci} 2679c84f3f3cSopenharmony_ci 2680c84f3f3cSopenharmony_cistatic int 2681c84f3f3cSopenharmony_cix_kill_region(int c MKSH_A_UNUSED) 2682c84f3f3cSopenharmony_ci{ 2683c84f3f3cSopenharmony_ci size_t rsize; 2684c84f3f3cSopenharmony_ci char *xr; 2685c84f3f3cSopenharmony_ci 2686c84f3f3cSopenharmony_ci if (xmp == NULL) { 2687c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 2688c84f3f3cSopenharmony_ci return (KSTD); 2689c84f3f3cSopenharmony_ci } 2690c84f3f3cSopenharmony_ci if (xmp > xcp) { 2691c84f3f3cSopenharmony_ci rsize = xmp - xcp; 2692c84f3f3cSopenharmony_ci xr = xcp; 2693c84f3f3cSopenharmony_ci } else { 2694c84f3f3cSopenharmony_ci rsize = xcp - xmp; 2695c84f3f3cSopenharmony_ci xr = xmp; 2696c84f3f3cSopenharmony_ci } 2697c84f3f3cSopenharmony_ci x_goto(xr); 2698c84f3f3cSopenharmony_ci x_delete(x_nb2nc(rsize), true); 2699c84f3f3cSopenharmony_ci xmp = xr; 2700c84f3f3cSopenharmony_ci return (KSTD); 2701c84f3f3cSopenharmony_ci} 2702c84f3f3cSopenharmony_ci 2703c84f3f3cSopenharmony_cistatic int 2704c84f3f3cSopenharmony_cix_xchg_point_mark(int c MKSH_A_UNUSED) 2705c84f3f3cSopenharmony_ci{ 2706c84f3f3cSopenharmony_ci char *tmp; 2707c84f3f3cSopenharmony_ci 2708c84f3f3cSopenharmony_ci if (xmp == NULL) { 2709c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 2710c84f3f3cSopenharmony_ci return (KSTD); 2711c84f3f3cSopenharmony_ci } 2712c84f3f3cSopenharmony_ci tmp = xmp; 2713c84f3f3cSopenharmony_ci xmp = xcp; 2714c84f3f3cSopenharmony_ci x_goto(tmp); 2715c84f3f3cSopenharmony_ci return (KSTD); 2716c84f3f3cSopenharmony_ci} 2717c84f3f3cSopenharmony_ci 2718c84f3f3cSopenharmony_cistatic int 2719c84f3f3cSopenharmony_cix_noop(int c MKSH_A_UNUSED) 2720c84f3f3cSopenharmony_ci{ 2721c84f3f3cSopenharmony_ci return (KSTD); 2722c84f3f3cSopenharmony_ci} 2723c84f3f3cSopenharmony_ci 2724c84f3f3cSopenharmony_ci/* 2725c84f3f3cSopenharmony_ci * File/command name completion routines 2726c84f3f3cSopenharmony_ci */ 2727c84f3f3cSopenharmony_cistatic int 2728c84f3f3cSopenharmony_cix_comp_comm(int c MKSH_A_UNUSED) 2729c84f3f3cSopenharmony_ci{ 2730c84f3f3cSopenharmony_ci do_complete(XCF_COMMAND, CT_COMPLETE); 2731c84f3f3cSopenharmony_ci return (KSTD); 2732c84f3f3cSopenharmony_ci} 2733c84f3f3cSopenharmony_ci 2734c84f3f3cSopenharmony_cistatic int 2735c84f3f3cSopenharmony_cix_list_comm(int c MKSH_A_UNUSED) 2736c84f3f3cSopenharmony_ci{ 2737c84f3f3cSopenharmony_ci do_complete(XCF_COMMAND, CT_LIST); 2738c84f3f3cSopenharmony_ci return (KSTD); 2739c84f3f3cSopenharmony_ci} 2740c84f3f3cSopenharmony_ci 2741c84f3f3cSopenharmony_cistatic int 2742c84f3f3cSopenharmony_cix_complete(int c MKSH_A_UNUSED) 2743c84f3f3cSopenharmony_ci{ 2744c84f3f3cSopenharmony_ci do_complete(XCF_COMMAND_FILE, CT_COMPLETE); 2745c84f3f3cSopenharmony_ci return (KSTD); 2746c84f3f3cSopenharmony_ci} 2747c84f3f3cSopenharmony_ci 2748c84f3f3cSopenharmony_cistatic int 2749c84f3f3cSopenharmony_cix_enumerate(int c MKSH_A_UNUSED) 2750c84f3f3cSopenharmony_ci{ 2751c84f3f3cSopenharmony_ci do_complete(XCF_COMMAND_FILE, CT_LIST); 2752c84f3f3cSopenharmony_ci return (KSTD); 2753c84f3f3cSopenharmony_ci} 2754c84f3f3cSopenharmony_ci 2755c84f3f3cSopenharmony_cistatic int 2756c84f3f3cSopenharmony_cix_comp_file(int c MKSH_A_UNUSED) 2757c84f3f3cSopenharmony_ci{ 2758c84f3f3cSopenharmony_ci do_complete(XCF_FILE, CT_COMPLETE); 2759c84f3f3cSopenharmony_ci return (KSTD); 2760c84f3f3cSopenharmony_ci} 2761c84f3f3cSopenharmony_ci 2762c84f3f3cSopenharmony_cistatic int 2763c84f3f3cSopenharmony_cix_list_file(int c MKSH_A_UNUSED) 2764c84f3f3cSopenharmony_ci{ 2765c84f3f3cSopenharmony_ci do_complete(XCF_FILE, CT_LIST); 2766c84f3f3cSopenharmony_ci return (KSTD); 2767c84f3f3cSopenharmony_ci} 2768c84f3f3cSopenharmony_ci 2769c84f3f3cSopenharmony_cistatic int 2770c84f3f3cSopenharmony_cix_comp_list(int c MKSH_A_UNUSED) 2771c84f3f3cSopenharmony_ci{ 2772c84f3f3cSopenharmony_ci do_complete(XCF_COMMAND_FILE, CT_COMPLIST); 2773c84f3f3cSopenharmony_ci return (KSTD); 2774c84f3f3cSopenharmony_ci} 2775c84f3f3cSopenharmony_ci 2776c84f3f3cSopenharmony_cistatic int 2777c84f3f3cSopenharmony_cix_expand(int c MKSH_A_UNUSED) 2778c84f3f3cSopenharmony_ci{ 2779c84f3f3cSopenharmony_ci char **words; 2780c84f3f3cSopenharmony_ci int start, end, nwords, i; 2781c84f3f3cSopenharmony_ci 2782c84f3f3cSopenharmony_ci i = XCF_FILE; 2783c84f3f3cSopenharmony_ci nwords = x_cf_glob(&i, xbuf, xep - xbuf, xcp - xbuf, 2784c84f3f3cSopenharmony_ci &start, &end, &words); 2785c84f3f3cSopenharmony_ci 2786c84f3f3cSopenharmony_ci if (nwords == 0) { 2787c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 2788c84f3f3cSopenharmony_ci return (KSTD); 2789c84f3f3cSopenharmony_ci } 2790c84f3f3cSopenharmony_ci x_goto(xbuf + start); 2791c84f3f3cSopenharmony_ci x_delete(x_nb2nc(end - start), false); 2792c84f3f3cSopenharmony_ci 2793c84f3f3cSopenharmony_ci i = 0; 2794c84f3f3cSopenharmony_ci while (i < nwords) { 2795c84f3f3cSopenharmony_ci if (x_escape(words[i], strlen(words[i]), x_do_ins) < 0 || 2796c84f3f3cSopenharmony_ci (++i < nwords && x_ins(T1space) < 0)) { 2797c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 2798c84f3f3cSopenharmony_ci return (KSTD); 2799c84f3f3cSopenharmony_ci } 2800c84f3f3cSopenharmony_ci } 2801c84f3f3cSopenharmony_ci x_adjust(); 2802c84f3f3cSopenharmony_ci 2803c84f3f3cSopenharmony_ci return (KSTD); 2804c84f3f3cSopenharmony_ci} 2805c84f3f3cSopenharmony_ci 2806c84f3f3cSopenharmony_cistatic void 2807c84f3f3cSopenharmony_cido_complete( 2808c84f3f3cSopenharmony_ci /* XCF_{COMMAND,FILE,COMMAND_FILE} */ 2809c84f3f3cSopenharmony_ci int flags, 2810c84f3f3cSopenharmony_ci /* 0 for list, 1 for complete and 2 for complete-list */ 2811c84f3f3cSopenharmony_ci Comp_type type) 2812c84f3f3cSopenharmony_ci{ 2813c84f3f3cSopenharmony_ci char **words; 2814c84f3f3cSopenharmony_ci int start, end, nlen, olen, nwords; 2815c84f3f3cSopenharmony_ci bool completed; 2816c84f3f3cSopenharmony_ci 2817c84f3f3cSopenharmony_ci nwords = x_cf_glob(&flags, xbuf, xep - xbuf, xcp - xbuf, 2818c84f3f3cSopenharmony_ci &start, &end, &words); 2819c84f3f3cSopenharmony_ci /* no match */ 2820c84f3f3cSopenharmony_ci if (nwords == 0) { 2821c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 2822c84f3f3cSopenharmony_ci return; 2823c84f3f3cSopenharmony_ci } 2824c84f3f3cSopenharmony_ci if (type == CT_LIST) { 2825c84f3f3cSopenharmony_ci x_print_expansions(nwords, words, 2826c84f3f3cSopenharmony_ci tobool(flags & XCF_IS_COMMAND)); 2827c84f3f3cSopenharmony_ci x_redraw(0); 2828c84f3f3cSopenharmony_ci x_free_words(nwords, words); 2829c84f3f3cSopenharmony_ci return; 2830c84f3f3cSopenharmony_ci } 2831c84f3f3cSopenharmony_ci olen = end - start; 2832c84f3f3cSopenharmony_ci nlen = x_longest_prefix(nwords, words); 2833c84f3f3cSopenharmony_ci if (nwords == 1) { 2834c84f3f3cSopenharmony_ci /* 2835c84f3f3cSopenharmony_ci * always complete single matches; 2836c84f3f3cSopenharmony_ci * any expansion of parameter substitution 2837c84f3f3cSopenharmony_ci * is always at most one result, too 2838c84f3f3cSopenharmony_ci */ 2839c84f3f3cSopenharmony_ci completed = true; 2840c84f3f3cSopenharmony_ci } else { 2841c84f3f3cSopenharmony_ci char *unescaped; 2842c84f3f3cSopenharmony_ci 2843c84f3f3cSopenharmony_ci /* make a copy of the original string part */ 2844c84f3f3cSopenharmony_ci strndupx(unescaped, xbuf + start, olen, ATEMP); 2845c84f3f3cSopenharmony_ci 2846c84f3f3cSopenharmony_ci /* expand any tilde and unescape the string for comparison */ 2847c84f3f3cSopenharmony_ci unescaped = x_glob_hlp_tilde_and_rem_qchar(unescaped, true); 2848c84f3f3cSopenharmony_ci 2849c84f3f3cSopenharmony_ci /* 2850c84f3f3cSopenharmony_ci * match iff entire original string is part of the 2851c84f3f3cSopenharmony_ci * longest prefix, implying the latter is at least 2852c84f3f3cSopenharmony_ci * the same size (after unescaping) 2853c84f3f3cSopenharmony_ci */ 2854c84f3f3cSopenharmony_ci completed = !strncmp(words[0], unescaped, strlen(unescaped)); 2855c84f3f3cSopenharmony_ci 2856c84f3f3cSopenharmony_ci afree(unescaped, ATEMP); 2857c84f3f3cSopenharmony_ci } 2858c84f3f3cSopenharmony_ci if (type == CT_COMPLIST && nwords > 1) { 2859c84f3f3cSopenharmony_ci /* 2860c84f3f3cSopenharmony_ci * print expansions, since we didn't get back 2861c84f3f3cSopenharmony_ci * just a single match 2862c84f3f3cSopenharmony_ci */ 2863c84f3f3cSopenharmony_ci x_print_expansions(nwords, words, 2864c84f3f3cSopenharmony_ci tobool(flags & XCF_IS_COMMAND)); 2865c84f3f3cSopenharmony_ci } 2866c84f3f3cSopenharmony_ci if (completed) { 2867c84f3f3cSopenharmony_ci /* expand on the command line */ 2868c84f3f3cSopenharmony_ci xmp = NULL; 2869c84f3f3cSopenharmony_ci xcp = xbuf + start; 2870c84f3f3cSopenharmony_ci xep -= olen; 2871c84f3f3cSopenharmony_ci memmove(xcp, xcp + olen, xep - xcp + 1); 2872c84f3f3cSopenharmony_ci x_escape(words[0], nlen, x_do_ins); 2873c84f3f3cSopenharmony_ci } 2874c84f3f3cSopenharmony_ci x_adjust(); 2875c84f3f3cSopenharmony_ci /* 2876c84f3f3cSopenharmony_ci * append a space if this is a single non-directory match 2877c84f3f3cSopenharmony_ci * and not a parameter or homedir substitution 2878c84f3f3cSopenharmony_ci */ 2879c84f3f3cSopenharmony_ci if (nwords == 1 && !mksh_cdirsep(words[0][nlen - 1]) && 2880c84f3f3cSopenharmony_ci !(flags & XCF_IS_NOSPACE)) { 2881c84f3f3cSopenharmony_ci x_ins(T1space); 2882c84f3f3cSopenharmony_ci } 2883c84f3f3cSopenharmony_ci 2884c84f3f3cSopenharmony_ci x_free_words(nwords, words); 2885c84f3f3cSopenharmony_ci} 2886c84f3f3cSopenharmony_ci 2887c84f3f3cSopenharmony_ci/*- 2888c84f3f3cSopenharmony_ci * NAME: 2889c84f3f3cSopenharmony_ci * x_adjust - redraw the line adjusting starting point etc. 2890c84f3f3cSopenharmony_ci * 2891c84f3f3cSopenharmony_ci * DESCRIPTION: 2892c84f3f3cSopenharmony_ci * This function is called when we have exceeded the bounds 2893c84f3f3cSopenharmony_ci * of the edit window. It increments x_adj_done so that 2894c84f3f3cSopenharmony_ci * functions like x_ins and x_delete know that we have been 2895c84f3f3cSopenharmony_ci * called and can skip the x_bs() stuff which has already 2896c84f3f3cSopenharmony_ci * been done by x_redraw. 2897c84f3f3cSopenharmony_ci * 2898c84f3f3cSopenharmony_ci * RETURN VALUE: 2899c84f3f3cSopenharmony_ci * None 2900c84f3f3cSopenharmony_ci */ 2901c84f3f3cSopenharmony_cistatic void 2902c84f3f3cSopenharmony_cix_adjust(void) 2903c84f3f3cSopenharmony_ci{ 2904c84f3f3cSopenharmony_ci int col_left, n; 2905c84f3f3cSopenharmony_ci 2906c84f3f3cSopenharmony_ci /* flag the fact that we were called */ 2907c84f3f3cSopenharmony_ci x_adj_done++; 2908c84f3f3cSopenharmony_ci 2909c84f3f3cSopenharmony_ci /* 2910c84f3f3cSopenharmony_ci * calculate the amount of columns we need to "go back" 2911c84f3f3cSopenharmony_ci * from xcp to set xbp to (but never < xbuf) to 2/3 of 2912c84f3f3cSopenharmony_ci * the display width; take care of pwidth though 2913c84f3f3cSopenharmony_ci */ 2914c84f3f3cSopenharmony_ci if ((col_left = xx_cols * 2 / 3) < MIN_EDIT_SPACE) { 2915c84f3f3cSopenharmony_ci /* 2916c84f3f3cSopenharmony_ci * cowardly refuse to do anything 2917c84f3f3cSopenharmony_ci * if the available space is too small; 2918c84f3f3cSopenharmony_ci * fall back to dumb pdksh code 2919c84f3f3cSopenharmony_ci */ 2920c84f3f3cSopenharmony_ci if ((xbp = xcp - (x_displen / 2)) < xbuf) 2921c84f3f3cSopenharmony_ci xbp = xbuf; 2922c84f3f3cSopenharmony_ci /* elide UTF-8 fixup as penalty */ 2923c84f3f3cSopenharmony_ci goto x_adjust_out; 2924c84f3f3cSopenharmony_ci } 2925c84f3f3cSopenharmony_ci 2926c84f3f3cSopenharmony_ci /* fix up xbp to just past a character end first */ 2927c84f3f3cSopenharmony_ci xbp = xcp >= xep ? xep : x_bs0(xcp, xbuf); 2928c84f3f3cSopenharmony_ci /* walk backwards */ 2929c84f3f3cSopenharmony_ci while (xbp > xbuf && col_left > 0) { 2930c84f3f3cSopenharmony_ci xbp = x_bs0(xbp - 1, xbuf); 2931c84f3f3cSopenharmony_ci col_left -= (n = x_size2(xbp, NULL)); 2932c84f3f3cSopenharmony_ci } 2933c84f3f3cSopenharmony_ci /* check if we hit the prompt */ 2934c84f3f3cSopenharmony_ci if (xbp == xbuf && xcp != xbuf && col_left >= 0 && col_left < pwidth) { 2935c84f3f3cSopenharmony_ci /* so we did; force scrolling occurs */ 2936c84f3f3cSopenharmony_ci xbp += utf_ptradj(xbp); 2937c84f3f3cSopenharmony_ci } 2938c84f3f3cSopenharmony_ci 2939c84f3f3cSopenharmony_ci x_adjust_out: 2940c84f3f3cSopenharmony_ci xlp_valid = false; 2941c84f3f3cSopenharmony_ci x_redraw('\r'); 2942c84f3f3cSopenharmony_ci x_flush(); 2943c84f3f3cSopenharmony_ci} 2944c84f3f3cSopenharmony_ci 2945c84f3f3cSopenharmony_cistatic void 2946c84f3f3cSopenharmony_cix_e_ungetc(int c) 2947c84f3f3cSopenharmony_ci{ 2948c84f3f3cSopenharmony_ci unget_char = c < 0 ? -1 : (c & 255); 2949c84f3f3cSopenharmony_ci} 2950c84f3f3cSopenharmony_ci 2951c84f3f3cSopenharmony_cistatic int 2952c84f3f3cSopenharmony_cix_e_getc(void) 2953c84f3f3cSopenharmony_ci{ 2954c84f3f3cSopenharmony_ci int c; 2955c84f3f3cSopenharmony_ci 2956c84f3f3cSopenharmony_ci if (unget_char >= 0) { 2957c84f3f3cSopenharmony_ci c = unget_char; 2958c84f3f3cSopenharmony_ci unget_char = -1; 2959c84f3f3cSopenharmony_ci return (c); 2960c84f3f3cSopenharmony_ci } 2961c84f3f3cSopenharmony_ci 2962c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 2963c84f3f3cSopenharmony_ci if (macroptr) { 2964c84f3f3cSopenharmony_ci if ((c = (unsigned char)*macroptr++)) 2965c84f3f3cSopenharmony_ci return (c); 2966c84f3f3cSopenharmony_ci macroptr = NULL; 2967c84f3f3cSopenharmony_ci } 2968c84f3f3cSopenharmony_ci#endif 2969c84f3f3cSopenharmony_ci 2970c84f3f3cSopenharmony_ci return (x_getc()); 2971c84f3f3cSopenharmony_ci} 2972c84f3f3cSopenharmony_ci 2973c84f3f3cSopenharmony_cistatic void 2974c84f3f3cSopenharmony_cix_e_putc2(int c) 2975c84f3f3cSopenharmony_ci{ 2976c84f3f3cSopenharmony_ci int width = 1; 2977c84f3f3cSopenharmony_ci 2978c84f3f3cSopenharmony_ci if (ctype(c, C_CR | C_LF)) 2979c84f3f3cSopenharmony_ci x_col = 0; 2980c84f3f3cSopenharmony_ci if (x_col < xx_cols) { 2981c84f3f3cSopenharmony_ci#ifndef MKSH_EBCDIC 2982c84f3f3cSopenharmony_ci if (UTFMODE && (c > 0x7F)) { 2983c84f3f3cSopenharmony_ci char utf_tmp[3]; 2984c84f3f3cSopenharmony_ci size_t x; 2985c84f3f3cSopenharmony_ci 2986c84f3f3cSopenharmony_ci if (c < 0xA0) 2987c84f3f3cSopenharmony_ci c = 0xFFFD; 2988c84f3f3cSopenharmony_ci x = utf_wctomb(utf_tmp, c); 2989c84f3f3cSopenharmony_ci x_putc(utf_tmp[0]); 2990c84f3f3cSopenharmony_ci if (x > 1) 2991c84f3f3cSopenharmony_ci x_putc(utf_tmp[1]); 2992c84f3f3cSopenharmony_ci if (x > 2) 2993c84f3f3cSopenharmony_ci x_putc(utf_tmp[2]); 2994c84f3f3cSopenharmony_ci width = utf_wcwidth(c); 2995c84f3f3cSopenharmony_ci } else 2996c84f3f3cSopenharmony_ci#endif 2997c84f3f3cSopenharmony_ci x_putc(c); 2998c84f3f3cSopenharmony_ci switch (c) { 2999c84f3f3cSopenharmony_ci case KSH_BEL: 3000c84f3f3cSopenharmony_ci break; 3001c84f3f3cSopenharmony_ci case '\r': 3002c84f3f3cSopenharmony_ci case '\n': 3003c84f3f3cSopenharmony_ci break; 3004c84f3f3cSopenharmony_ci case '\b': 3005c84f3f3cSopenharmony_ci x_col--; 3006c84f3f3cSopenharmony_ci break; 3007c84f3f3cSopenharmony_ci default: 3008c84f3f3cSopenharmony_ci x_col += width; 3009c84f3f3cSopenharmony_ci break; 3010c84f3f3cSopenharmony_ci } 3011c84f3f3cSopenharmony_ci } 3012c84f3f3cSopenharmony_ci if (x_adj_ok && (x_col < 0 || x_col >= (xx_cols - 2))) 3013c84f3f3cSopenharmony_ci x_adjust(); 3014c84f3f3cSopenharmony_ci} 3015c84f3f3cSopenharmony_ci 3016c84f3f3cSopenharmony_cistatic void 3017c84f3f3cSopenharmony_cix_e_putc3(const char **cp) 3018c84f3f3cSopenharmony_ci{ 3019c84f3f3cSopenharmony_ci int width = 1, c = **(const unsigned char **)cp; 3020c84f3f3cSopenharmony_ci 3021c84f3f3cSopenharmony_ci if (ctype(c, C_CR | C_LF)) 3022c84f3f3cSopenharmony_ci x_col = 0; 3023c84f3f3cSopenharmony_ci if (x_col < xx_cols) { 3024c84f3f3cSopenharmony_ci if (UTFMODE && (c > 0x7F)) { 3025c84f3f3cSopenharmony_ci char *cp2; 3026c84f3f3cSopenharmony_ci 3027c84f3f3cSopenharmony_ci width = utf_widthadj(*cp, (const char **)&cp2); 3028c84f3f3cSopenharmony_ci if (cp2 == *cp + 1) { 3029c84f3f3cSopenharmony_ci (*cp)++; 3030c84f3f3cSopenharmony_ci#ifdef MKSH_EBCDIC 3031c84f3f3cSopenharmony_ci x_putc(asc2rtt(0xEF)); 3032c84f3f3cSopenharmony_ci x_putc(asc2rtt(0xBF)); 3033c84f3f3cSopenharmony_ci x_putc(asc2rtt(0xBD)); 3034c84f3f3cSopenharmony_ci#else 3035c84f3f3cSopenharmony_ci shf_puts("\xEF\xBF\xBD", shl_out); 3036c84f3f3cSopenharmony_ci#endif 3037c84f3f3cSopenharmony_ci } else 3038c84f3f3cSopenharmony_ci while (*cp < cp2) 3039c84f3f3cSopenharmony_ci x_putcf(*(*cp)++); 3040c84f3f3cSopenharmony_ci } else { 3041c84f3f3cSopenharmony_ci (*cp)++; 3042c84f3f3cSopenharmony_ci x_putc(c); 3043c84f3f3cSopenharmony_ci } 3044c84f3f3cSopenharmony_ci switch (c) { 3045c84f3f3cSopenharmony_ci case KSH_BEL: 3046c84f3f3cSopenharmony_ci break; 3047c84f3f3cSopenharmony_ci case '\r': 3048c84f3f3cSopenharmony_ci case '\n': 3049c84f3f3cSopenharmony_ci break; 3050c84f3f3cSopenharmony_ci case '\b': 3051c84f3f3cSopenharmony_ci x_col--; 3052c84f3f3cSopenharmony_ci break; 3053c84f3f3cSopenharmony_ci default: 3054c84f3f3cSopenharmony_ci x_col += width; 3055c84f3f3cSopenharmony_ci break; 3056c84f3f3cSopenharmony_ci } 3057c84f3f3cSopenharmony_ci } 3058c84f3f3cSopenharmony_ci if (x_adj_ok && (x_col < 0 || x_col >= (xx_cols - 2))) 3059c84f3f3cSopenharmony_ci x_adjust(); 3060c84f3f3cSopenharmony_ci} 3061c84f3f3cSopenharmony_ci 3062c84f3f3cSopenharmony_cistatic void 3063c84f3f3cSopenharmony_cix_e_puts(const char *s) 3064c84f3f3cSopenharmony_ci{ 3065c84f3f3cSopenharmony_ci int adj = x_adj_done; 3066c84f3f3cSopenharmony_ci 3067c84f3f3cSopenharmony_ci while (*s && adj == x_adj_done) 3068c84f3f3cSopenharmony_ci x_e_putc3(&s); 3069c84f3f3cSopenharmony_ci} 3070c84f3f3cSopenharmony_ci 3071c84f3f3cSopenharmony_ci/*- 3072c84f3f3cSopenharmony_ci * NAME: 3073c84f3f3cSopenharmony_ci * x_set_arg - set an arg value for next function 3074c84f3f3cSopenharmony_ci * 3075c84f3f3cSopenharmony_ci * DESCRIPTION: 3076c84f3f3cSopenharmony_ci * This is a simple implementation of M-[0-9]. 3077c84f3f3cSopenharmony_ci * 3078c84f3f3cSopenharmony_ci * RETURN VALUE: 3079c84f3f3cSopenharmony_ci * KSTD 3080c84f3f3cSopenharmony_ci */ 3081c84f3f3cSopenharmony_cistatic int 3082c84f3f3cSopenharmony_cix_set_arg(int c) 3083c84f3f3cSopenharmony_ci{ 3084c84f3f3cSopenharmony_ci unsigned int n = 0; 3085c84f3f3cSopenharmony_ci bool first = true; 3086c84f3f3cSopenharmony_ci 3087c84f3f3cSopenharmony_ci /* strip command prefix */ 3088c84f3f3cSopenharmony_ci c &= 255; 3089c84f3f3cSopenharmony_ci while (c >= 0 && ctype(c, C_DIGIT)) { 3090c84f3f3cSopenharmony_ci n = n * 10 + ksh_numdig(c); 3091c84f3f3cSopenharmony_ci if (n > LINE) 3092c84f3f3cSopenharmony_ci /* upper bound for repeat */ 3093c84f3f3cSopenharmony_ci goto x_set_arg_too_big; 3094c84f3f3cSopenharmony_ci c = x_e_getc(); 3095c84f3f3cSopenharmony_ci first = false; 3096c84f3f3cSopenharmony_ci } 3097c84f3f3cSopenharmony_ci if (c < 0 || first) { 3098c84f3f3cSopenharmony_ci x_set_arg_too_big: 3099c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 3100c84f3f3cSopenharmony_ci x_arg = 1; 3101c84f3f3cSopenharmony_ci x_arg_defaulted = true; 3102c84f3f3cSopenharmony_ci } else { 3103c84f3f3cSopenharmony_ci x_e_ungetc(c); 3104c84f3f3cSopenharmony_ci x_arg = n; 3105c84f3f3cSopenharmony_ci x_arg_defaulted = false; 3106c84f3f3cSopenharmony_ci } 3107c84f3f3cSopenharmony_ci return (KSTD); 3108c84f3f3cSopenharmony_ci} 3109c84f3f3cSopenharmony_ci 3110c84f3f3cSopenharmony_ci/* Comment or uncomment the current line. */ 3111c84f3f3cSopenharmony_cistatic int 3112c84f3f3cSopenharmony_cix_comment(int c MKSH_A_UNUSED) 3113c84f3f3cSopenharmony_ci{ 3114c84f3f3cSopenharmony_ci ssize_t len = xep - xbuf; 3115c84f3f3cSopenharmony_ci int ret = x_do_comment(xbuf, xend - xbuf, &len); 3116c84f3f3cSopenharmony_ci 3117c84f3f3cSopenharmony_ci if (ret < 0) 3118c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 3119c84f3f3cSopenharmony_ci else { 3120c84f3f3cSopenharmony_ci x_modified(); 3121c84f3f3cSopenharmony_ci xep = xbuf + len; 3122c84f3f3cSopenharmony_ci *xep = '\0'; 3123c84f3f3cSopenharmony_ci xcp = xbp = xbuf; 3124c84f3f3cSopenharmony_ci x_redraw('\r'); 3125c84f3f3cSopenharmony_ci if (ret > 0) 3126c84f3f3cSopenharmony_ci return (x_newline('\n')); 3127c84f3f3cSopenharmony_ci } 3128c84f3f3cSopenharmony_ci return (KSTD); 3129c84f3f3cSopenharmony_ci} 3130c84f3f3cSopenharmony_ci 3131c84f3f3cSopenharmony_cistatic int 3132c84f3f3cSopenharmony_cix_version(int c MKSH_A_UNUSED) 3133c84f3f3cSopenharmony_ci{ 3134c84f3f3cSopenharmony_ci char *o_xbuf = xbuf, *o_xend = xend; 3135c84f3f3cSopenharmony_ci char *o_xbp = xbp, *o_xep = xep, *o_xcp = xcp; 3136c84f3f3cSopenharmony_ci char *v; 3137c84f3f3cSopenharmony_ci 3138c84f3f3cSopenharmony_ci strdupx(v, KSH_VERSION, ATEMP); 3139c84f3f3cSopenharmony_ci 3140c84f3f3cSopenharmony_ci xbuf = xbp = xcp = v; 3141c84f3f3cSopenharmony_ci xend = xep = strnul(v); 3142c84f3f3cSopenharmony_ci x_redraw('\r'); 3143c84f3f3cSopenharmony_ci x_flush(); 3144c84f3f3cSopenharmony_ci 3145c84f3f3cSopenharmony_ci c = x_e_getc(); 3146c84f3f3cSopenharmony_ci xbuf = o_xbuf; 3147c84f3f3cSopenharmony_ci xend = o_xend; 3148c84f3f3cSopenharmony_ci xbp = o_xbp; 3149c84f3f3cSopenharmony_ci xep = o_xep; 3150c84f3f3cSopenharmony_ci xcp = o_xcp; 3151c84f3f3cSopenharmony_ci x_redraw('\r'); 3152c84f3f3cSopenharmony_ci 3153c84f3f3cSopenharmony_ci if (c < 0) 3154c84f3f3cSopenharmony_ci return (KSTD); 3155c84f3f3cSopenharmony_ci /* This is what AT&T ksh seems to do... Very bizarre */ 3156c84f3f3cSopenharmony_ci if (c != ' ') 3157c84f3f3cSopenharmony_ci x_e_ungetc(c); 3158c84f3f3cSopenharmony_ci 3159c84f3f3cSopenharmony_ci afree(v, ATEMP); 3160c84f3f3cSopenharmony_ci return (KSTD); 3161c84f3f3cSopenharmony_ci} 3162c84f3f3cSopenharmony_ci 3163c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 3164c84f3f3cSopenharmony_cistatic int 3165c84f3f3cSopenharmony_cix_edit_line(int c MKSH_A_UNUSED) 3166c84f3f3cSopenharmony_ci{ 3167c84f3f3cSopenharmony_ci if (x_arg_defaulted) { 3168c84f3f3cSopenharmony_ci if (modified) { 3169c84f3f3cSopenharmony_ci *xep = '\0'; 3170c84f3f3cSopenharmony_ci histsave(&source->line, xbuf, HIST_STORE, true); 3171c84f3f3cSopenharmony_ci x_arg = 0; 3172c84f3f3cSopenharmony_ci } else 3173c84f3f3cSopenharmony_ci x_arg = source->line - (histptr - x_histp); 3174c84f3f3cSopenharmony_ci } 3175c84f3f3cSopenharmony_ci if (x_arg) 3176c84f3f3cSopenharmony_ci shf_snprintf(xbuf, xend - xbuf, Tf_sd, ctrl_x_e, x_arg); 3177c84f3f3cSopenharmony_ci else 3178c84f3f3cSopenharmony_ci strlcpy(xbuf, ctrl_x_e, xend - xbuf); 3179c84f3f3cSopenharmony_ci xep = strnul(xbuf); 3180c84f3f3cSopenharmony_ci return (x_newline('\n')); 3181c84f3f3cSopenharmony_ci} 3182c84f3f3cSopenharmony_ci#endif 3183c84f3f3cSopenharmony_ci 3184c84f3f3cSopenharmony_ci/*- 3185c84f3f3cSopenharmony_ci * NAME: 3186c84f3f3cSopenharmony_ci * x_prev_histword - recover word from prev command 3187c84f3f3cSopenharmony_ci * 3188c84f3f3cSopenharmony_ci * DESCRIPTION: 3189c84f3f3cSopenharmony_ci * This function recovers the last word from the previous 3190c84f3f3cSopenharmony_ci * command and inserts it into the current edit line. If a 3191c84f3f3cSopenharmony_ci * numeric arg is supplied then the n'th word from the 3192c84f3f3cSopenharmony_ci * start of the previous command is used. 3193c84f3f3cSopenharmony_ci * As a side effect, trashes the mark in order to achieve 3194c84f3f3cSopenharmony_ci * being called in a repeatable fashion. 3195c84f3f3cSopenharmony_ci * 3196c84f3f3cSopenharmony_ci * Bound to M-. 3197c84f3f3cSopenharmony_ci * 3198c84f3f3cSopenharmony_ci * RETURN VALUE: 3199c84f3f3cSopenharmony_ci * KSTD 3200c84f3f3cSopenharmony_ci */ 3201c84f3f3cSopenharmony_cistatic int 3202c84f3f3cSopenharmony_cix_prev_histword(int c MKSH_A_UNUSED) 3203c84f3f3cSopenharmony_ci{ 3204c84f3f3cSopenharmony_ci char *rcp, *cp; 3205c84f3f3cSopenharmony_ci char **xhp; 3206c84f3f3cSopenharmony_ci int m = 1; 3207c84f3f3cSopenharmony_ci /* -1 = defaulted; 0+ = argument */ 3208c84f3f3cSopenharmony_ci static int last_arg = -1; 3209c84f3f3cSopenharmony_ci 3210c84f3f3cSopenharmony_ci if (x_last_command == XFUNC_prev_histword) { 3211c84f3f3cSopenharmony_ci if (xmp && modified > 1) 3212c84f3f3cSopenharmony_ci x_kill_region(0); 3213c84f3f3cSopenharmony_ci if (modified) 3214c84f3f3cSopenharmony_ci m = modified; 3215c84f3f3cSopenharmony_ci } else 3216c84f3f3cSopenharmony_ci last_arg = x_arg_defaulted ? -1 : x_arg; 3217c84f3f3cSopenharmony_ci xhp = histptr - (m - 1); 3218c84f3f3cSopenharmony_ci if ((xhp < history) || !(cp = *xhp)) { 3219c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 3220c84f3f3cSopenharmony_ci x_modified(); 3221c84f3f3cSopenharmony_ci return (KSTD); 3222c84f3f3cSopenharmony_ci } 3223c84f3f3cSopenharmony_ci x_set_mark(0); 3224c84f3f3cSopenharmony_ci if ((x_arg = last_arg) == -1) { 3225c84f3f3cSopenharmony_ci /* x_arg_defaulted */ 3226c84f3f3cSopenharmony_ci 3227c84f3f3cSopenharmony_ci rcp = &cp[strlen(cp) - 1]; 3228c84f3f3cSopenharmony_ci /* 3229c84f3f3cSopenharmony_ci * ignore white-space after the last word 3230c84f3f3cSopenharmony_ci */ 3231c84f3f3cSopenharmony_ci while (rcp > cp && ctype(*rcp, C_CFS)) 3232c84f3f3cSopenharmony_ci rcp--; 3233c84f3f3cSopenharmony_ci while (rcp > cp && !ctype(*rcp, C_CFS)) 3234c84f3f3cSopenharmony_ci rcp--; 3235c84f3f3cSopenharmony_ci if (ctype(*rcp, C_CFS)) 3236c84f3f3cSopenharmony_ci rcp++; 3237c84f3f3cSopenharmony_ci x_ins(rcp); 3238c84f3f3cSopenharmony_ci } else { 3239c84f3f3cSopenharmony_ci /* not x_arg_defaulted */ 3240c84f3f3cSopenharmony_ci char ch; 3241c84f3f3cSopenharmony_ci 3242c84f3f3cSopenharmony_ci rcp = cp; 3243c84f3f3cSopenharmony_ci /* 3244c84f3f3cSopenharmony_ci * ignore white-space at start of line 3245c84f3f3cSopenharmony_ci */ 3246c84f3f3cSopenharmony_ci while (*rcp && ctype(*rcp, C_CFS)) 3247c84f3f3cSopenharmony_ci rcp++; 3248c84f3f3cSopenharmony_ci while (x_arg-- > 0) { 3249c84f3f3cSopenharmony_ci while (*rcp && !ctype(*rcp, C_CFS)) 3250c84f3f3cSopenharmony_ci rcp++; 3251c84f3f3cSopenharmony_ci while (*rcp && ctype(*rcp, C_CFS)) 3252c84f3f3cSopenharmony_ci rcp++; 3253c84f3f3cSopenharmony_ci } 3254c84f3f3cSopenharmony_ci cp = rcp; 3255c84f3f3cSopenharmony_ci while (*rcp && !ctype(*rcp, C_CFS)) 3256c84f3f3cSopenharmony_ci rcp++; 3257c84f3f3cSopenharmony_ci ch = *rcp; 3258c84f3f3cSopenharmony_ci *rcp = '\0'; 3259c84f3f3cSopenharmony_ci x_ins(cp); 3260c84f3f3cSopenharmony_ci *rcp = ch; 3261c84f3f3cSopenharmony_ci } 3262c84f3f3cSopenharmony_ci if (!modified) 3263c84f3f3cSopenharmony_ci x_histmcp = x_histp; 3264c84f3f3cSopenharmony_ci modified = m + 1; 3265c84f3f3cSopenharmony_ci return (KSTD); 3266c84f3f3cSopenharmony_ci} 3267c84f3f3cSopenharmony_ci 3268c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 3269c84f3f3cSopenharmony_ci/* Uppercase N(1) words */ 3270c84f3f3cSopenharmony_cistatic int 3271c84f3f3cSopenharmony_cix_fold_upper(int c MKSH_A_UNUSED) 3272c84f3f3cSopenharmony_ci{ 3273c84f3f3cSopenharmony_ci return (x_fold_case('U')); 3274c84f3f3cSopenharmony_ci} 3275c84f3f3cSopenharmony_ci 3276c84f3f3cSopenharmony_ci/* Lowercase N(1) words */ 3277c84f3f3cSopenharmony_cistatic int 3278c84f3f3cSopenharmony_cix_fold_lower(int c MKSH_A_UNUSED) 3279c84f3f3cSopenharmony_ci{ 3280c84f3f3cSopenharmony_ci return (x_fold_case('L')); 3281c84f3f3cSopenharmony_ci} 3282c84f3f3cSopenharmony_ci 3283c84f3f3cSopenharmony_ci/* Titlecase N(1) words */ 3284c84f3f3cSopenharmony_cistatic int 3285c84f3f3cSopenharmony_cix_fold_capitalise(int c MKSH_A_UNUSED) 3286c84f3f3cSopenharmony_ci{ 3287c84f3f3cSopenharmony_ci return (x_fold_case('C')); 3288c84f3f3cSopenharmony_ci} 3289c84f3f3cSopenharmony_ci 3290c84f3f3cSopenharmony_ci/*- 3291c84f3f3cSopenharmony_ci * NAME: 3292c84f3f3cSopenharmony_ci * x_fold_case - convert word to UPPER/lower/Capital case 3293c84f3f3cSopenharmony_ci * 3294c84f3f3cSopenharmony_ci * DESCRIPTION: 3295c84f3f3cSopenharmony_ci * This function is used to implement M-U/M-u, M-L/M-l, M-C/M-c 3296c84f3f3cSopenharmony_ci * to UPPER CASE, lower case or Capitalise Words. 3297c84f3f3cSopenharmony_ci * 3298c84f3f3cSopenharmony_ci * RETURN VALUE: 3299c84f3f3cSopenharmony_ci * None 3300c84f3f3cSopenharmony_ci */ 3301c84f3f3cSopenharmony_cistatic int 3302c84f3f3cSopenharmony_cix_fold_case(int c) 3303c84f3f3cSopenharmony_ci{ 3304c84f3f3cSopenharmony_ci char *cp = xcp; 3305c84f3f3cSopenharmony_ci 3306c84f3f3cSopenharmony_ci if (cp == xep) { 3307c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 3308c84f3f3cSopenharmony_ci return (KSTD); 3309c84f3f3cSopenharmony_ci } 3310c84f3f3cSopenharmony_ci while (x_arg--) { 3311c84f3f3cSopenharmony_ci /* 3312c84f3f3cSopenharmony_ci * first skip over any white-space 3313c84f3f3cSopenharmony_ci */ 3314c84f3f3cSopenharmony_ci while (cp != xep && ctype(*cp, C_MFS)) 3315c84f3f3cSopenharmony_ci cp++; 3316c84f3f3cSopenharmony_ci /* 3317c84f3f3cSopenharmony_ci * do the first char on its own since it may be 3318c84f3f3cSopenharmony_ci * a different action than for the rest. 3319c84f3f3cSopenharmony_ci */ 3320c84f3f3cSopenharmony_ci if (cp != xep) { 3321c84f3f3cSopenharmony_ci if (c == 'L') 3322c84f3f3cSopenharmony_ci /* lowercase */ 3323c84f3f3cSopenharmony_ci *cp = ksh_tolower(*cp); 3324c84f3f3cSopenharmony_ci else 3325c84f3f3cSopenharmony_ci /* uppercase, capitalise */ 3326c84f3f3cSopenharmony_ci *cp = ksh_toupper(*cp); 3327c84f3f3cSopenharmony_ci cp++; 3328c84f3f3cSopenharmony_ci } 3329c84f3f3cSopenharmony_ci /* 3330c84f3f3cSopenharmony_ci * now for the rest of the word 3331c84f3f3cSopenharmony_ci */ 3332c84f3f3cSopenharmony_ci while (cp != xep && !ctype(*cp, C_MFS)) { 3333c84f3f3cSopenharmony_ci if (c == 'U') 3334c84f3f3cSopenharmony_ci /* uppercase */ 3335c84f3f3cSopenharmony_ci *cp = ksh_toupper(*cp); 3336c84f3f3cSopenharmony_ci else 3337c84f3f3cSopenharmony_ci /* lowercase, capitalise */ 3338c84f3f3cSopenharmony_ci *cp = ksh_tolower(*cp); 3339c84f3f3cSopenharmony_ci cp++; 3340c84f3f3cSopenharmony_ci } 3341c84f3f3cSopenharmony_ci } 3342c84f3f3cSopenharmony_ci x_goto(cp); 3343c84f3f3cSopenharmony_ci x_modified(); 3344c84f3f3cSopenharmony_ci return (KSTD); 3345c84f3f3cSopenharmony_ci} 3346c84f3f3cSopenharmony_ci#endif 3347c84f3f3cSopenharmony_ci 3348c84f3f3cSopenharmony_ci/*- 3349c84f3f3cSopenharmony_ci * NAME: 3350c84f3f3cSopenharmony_ci * x_lastcp - last visible char 3351c84f3f3cSopenharmony_ci * 3352c84f3f3cSopenharmony_ci * DESCRIPTION: 3353c84f3f3cSopenharmony_ci * This function returns a pointer to that char in the 3354c84f3f3cSopenharmony_ci * edit buffer that will be the last displayed on the 3355c84f3f3cSopenharmony_ci * screen. 3356c84f3f3cSopenharmony_ci */ 3357c84f3f3cSopenharmony_cistatic char * 3358c84f3f3cSopenharmony_cix_lastcp(void) 3359c84f3f3cSopenharmony_ci{ 3360c84f3f3cSopenharmony_ci if (!xlp_valid) { 3361c84f3f3cSopenharmony_ci int i = 0, j; 3362c84f3f3cSopenharmony_ci char *xlp2; 3363c84f3f3cSopenharmony_ci 3364c84f3f3cSopenharmony_ci xlp = xbp; 3365c84f3f3cSopenharmony_ci while (xlp < xep) { 3366c84f3f3cSopenharmony_ci j = x_size2(xlp, &xlp2); 3367c84f3f3cSopenharmony_ci if ((i + j) > x_displen) 3368c84f3f3cSopenharmony_ci break; 3369c84f3f3cSopenharmony_ci i += j; 3370c84f3f3cSopenharmony_ci xlp = xlp2; 3371c84f3f3cSopenharmony_ci } 3372c84f3f3cSopenharmony_ci } 3373c84f3f3cSopenharmony_ci xlp_valid = true; 3374c84f3f3cSopenharmony_ci return (xlp); 3375c84f3f3cSopenharmony_ci} 3376c84f3f3cSopenharmony_ci 3377c84f3f3cSopenharmony_ci/* correctly position the cursor on the screen from end of visible area */ 3378c84f3f3cSopenharmony_cistatic void 3379c84f3f3cSopenharmony_cix_lastpos(void) 3380c84f3f3cSopenharmony_ci{ 3381c84f3f3cSopenharmony_ci char *cp = x_lastcp(); 3382c84f3f3cSopenharmony_ci 3383c84f3f3cSopenharmony_ci while (cp > xcp) 3384c84f3f3cSopenharmony_ci x_bs3(&cp); 3385c84f3f3cSopenharmony_ci} 3386c84f3f3cSopenharmony_ci 3387c84f3f3cSopenharmony_cistatic void 3388c84f3f3cSopenharmony_cix_mode(bool onoff) 3389c84f3f3cSopenharmony_ci{ 3390c84f3f3cSopenharmony_ci static bool x_cur_mode; 3391c84f3f3cSopenharmony_ci 3392c84f3f3cSopenharmony_ci if (x_cur_mode == onoff) 3393c84f3f3cSopenharmony_ci return; 3394c84f3f3cSopenharmony_ci x_cur_mode = onoff; 3395c84f3f3cSopenharmony_ci 3396c84f3f3cSopenharmony_ci if (onoff) { 3397c84f3f3cSopenharmony_ci x_mkraw(tty_fd, NULL, false); 3398c84f3f3cSopenharmony_ci 3399c84f3f3cSopenharmony_ci edchars.erase = toedchar(tty_state.c_cc[VERASE]); 3400c84f3f3cSopenharmony_ci edchars.kill = toedchar(tty_state.c_cc[VKILL]); 3401c84f3f3cSopenharmony_ci edchars.intr = toedchar(tty_state.c_cc[VINTR]); 3402c84f3f3cSopenharmony_ci edchars.quit = toedchar(tty_state.c_cc[VQUIT]); 3403c84f3f3cSopenharmony_ci edchars.eof = toedchar(tty_state.c_cc[VEOF]); 3404c84f3f3cSopenharmony_ci#ifdef VWERASE 3405c84f3f3cSopenharmony_ci edchars.werase = toedchar(tty_state.c_cc[VWERASE]); 3406c84f3f3cSopenharmony_ci#else 3407c84f3f3cSopenharmony_ci edchars.werase = 0; 3408c84f3f3cSopenharmony_ci#endif 3409c84f3f3cSopenharmony_ci 3410c84f3f3cSopenharmony_ci if (!edchars.erase) 3411c84f3f3cSopenharmony_ci edchars.erase = CTRL_H; 3412c84f3f3cSopenharmony_ci if (!edchars.kill) 3413c84f3f3cSopenharmony_ci edchars.kill = CTRL_U; 3414c84f3f3cSopenharmony_ci if (!edchars.intr) 3415c84f3f3cSopenharmony_ci edchars.intr = CTRL_C; 3416c84f3f3cSopenharmony_ci if (!edchars.quit) 3417c84f3f3cSopenharmony_ci edchars.quit = CTRL_BK; 3418c84f3f3cSopenharmony_ci if (!edchars.eof) 3419c84f3f3cSopenharmony_ci edchars.eof = CTRL_D; 3420c84f3f3cSopenharmony_ci if (!edchars.werase) 3421c84f3f3cSopenharmony_ci edchars.werase = CTRL_W; 3422c84f3f3cSopenharmony_ci 3423c84f3f3cSopenharmony_ci if (isedchar(edchars.erase)) { 3424c84f3f3cSopenharmony_ci bind_if_not_bound(0, edchars.erase, XFUNC_del_back); 3425c84f3f3cSopenharmony_ci bind_if_not_bound(1, edchars.erase, XFUNC_del_bword); 3426c84f3f3cSopenharmony_ci } 3427c84f3f3cSopenharmony_ci if (isedchar(edchars.kill)) 3428c84f3f3cSopenharmony_ci bind_if_not_bound(0, edchars.kill, XFUNC_del_line); 3429c84f3f3cSopenharmony_ci if (isedchar(edchars.werase)) 3430c84f3f3cSopenharmony_ci bind_if_not_bound(0, edchars.werase, XFUNC_del_bword); 3431c84f3f3cSopenharmony_ci if (isedchar(edchars.intr)) 3432c84f3f3cSopenharmony_ci bind_if_not_bound(0, edchars.intr, XFUNC_abort); 3433c84f3f3cSopenharmony_ci if (isedchar(edchars.quit)) 3434c84f3f3cSopenharmony_ci bind_if_not_bound(0, edchars.quit, XFUNC_noop); 3435c84f3f3cSopenharmony_ci } else 3436c84f3f3cSopenharmony_ci mksh_tcset(tty_fd, &tty_state); 3437c84f3f3cSopenharmony_ci} 3438c84f3f3cSopenharmony_ci 3439c84f3f3cSopenharmony_ci#if !MKSH_S_NOVI 3440c84f3f3cSopenharmony_ci/* +++ vi editing mode +++ */ 3441c84f3f3cSopenharmony_ci 3442c84f3f3cSopenharmony_cistruct edstate { 3443c84f3f3cSopenharmony_ci char *cbuf; 3444c84f3f3cSopenharmony_ci ssize_t winleft; 3445c84f3f3cSopenharmony_ci ssize_t cbufsize; 3446c84f3f3cSopenharmony_ci ssize_t linelen; 3447c84f3f3cSopenharmony_ci ssize_t cursor; 3448c84f3f3cSopenharmony_ci}; 3449c84f3f3cSopenharmony_ci 3450c84f3f3cSopenharmony_cistatic int vi_hook(int); 3451c84f3f3cSopenharmony_cistatic int nextstate(int); 3452c84f3f3cSopenharmony_cistatic int vi_insert(int); 3453c84f3f3cSopenharmony_cistatic int vi_cmd(int, const char *); 3454c84f3f3cSopenharmony_cistatic int domove(int, const char *, int); 3455c84f3f3cSopenharmony_cistatic int domovebeg(void); 3456c84f3f3cSopenharmony_cistatic int redo_insert(int); 3457c84f3f3cSopenharmony_cistatic void yank_range(int, int); 3458c84f3f3cSopenharmony_cistatic int bracktype(int); 3459c84f3f3cSopenharmony_cistatic void save_cbuf(void); 3460c84f3f3cSopenharmony_cistatic void restore_cbuf(void); 3461c84f3f3cSopenharmony_cistatic int putbuf(const char *, ssize_t, bool); 3462c84f3f3cSopenharmony_cistatic void del_range(int, int); 3463c84f3f3cSopenharmony_cistatic int findch(int, int, bool, bool) MKSH_A_PURE; 3464c84f3f3cSopenharmony_cistatic int forwword(int); 3465c84f3f3cSopenharmony_cistatic int backword(int); 3466c84f3f3cSopenharmony_cistatic int endword(int); 3467c84f3f3cSopenharmony_cistatic int Forwword(int); 3468c84f3f3cSopenharmony_cistatic int Backword(int); 3469c84f3f3cSopenharmony_cistatic int Endword(int); 3470c84f3f3cSopenharmony_cistatic int grabhist(int, int); 3471c84f3f3cSopenharmony_cistatic int grabsearch(const char *, int, int, bool); 3472c84f3f3cSopenharmony_cistatic void redraw_line(bool); 3473c84f3f3cSopenharmony_cistatic void refresh(bool); 3474c84f3f3cSopenharmony_cistatic int outofwin(void); 3475c84f3f3cSopenharmony_cistatic void rewindow(void); 3476c84f3f3cSopenharmony_cistatic int newcol(unsigned char, int); 3477c84f3f3cSopenharmony_cistatic void display(char *, char *, bool); 3478c84f3f3cSopenharmony_cistatic void ed_mov_opt(int, char *); 3479c84f3f3cSopenharmony_cistatic int expand_word(int); 3480c84f3f3cSopenharmony_cistatic int complete_word(int, int); 3481c84f3f3cSopenharmony_cistatic int print_expansions(struct edstate *, int); 3482c84f3f3cSopenharmony_cistatic void vi_error(void); 3483c84f3f3cSopenharmony_cistatic void vi_macro_reset(void); 3484c84f3f3cSopenharmony_cistatic int x_vi_putbuf(const char *, size_t); 3485c84f3f3cSopenharmony_ci#define char_len(c) (ksh_isctrl(c) ? 2 : 1) 3486c84f3f3cSopenharmony_ci 3487c84f3f3cSopenharmony_ci#define vC 0x01 /* a valid command that isn't a vM, vE, vU */ 3488c84f3f3cSopenharmony_ci#define vM 0x02 /* movement command (h, l, etc.) */ 3489c84f3f3cSopenharmony_ci#define vE 0x04 /* extended command (c, d, y) */ 3490c84f3f3cSopenharmony_ci#define vX 0x08 /* long command (@, f, F, t, T, etc.) */ 3491c84f3f3cSopenharmony_ci#define vU 0x10 /* an UN-undoable command (that isn't a vM) */ 3492c84f3f3cSopenharmony_ci#define vB 0x20 /* bad command (^@) */ 3493c84f3f3cSopenharmony_ci#define vZ 0x40 /* repeat count defaults to 0 (not 1) */ 3494c84f3f3cSopenharmony_ci#define vS 0x80 /* search (/, ?) */ 3495c84f3f3cSopenharmony_ci 3496c84f3f3cSopenharmony_ci#define is_bad(c) (classify[rtt2asc(c) & 0x7F] & vB) 3497c84f3f3cSopenharmony_ci#define is_cmd(c) (classify[rtt2asc(c) & 0x7F] & (vM | vE | vC | vU)) 3498c84f3f3cSopenharmony_ci#define is_move(c) (classify[rtt2asc(c) & 0x7F] & vM) 3499c84f3f3cSopenharmony_ci#define is_extend(c) (classify[rtt2asc(c) & 0x7F] & vE) 3500c84f3f3cSopenharmony_ci#define is_long(c) (classify[rtt2asc(c) & 0x7F] & vX) 3501c84f3f3cSopenharmony_ci#define is_undoable(c) (!(classify[rtt2asc(c) & 0x7F] & vU)) 3502c84f3f3cSopenharmony_ci#define is_srch(c) (classify[rtt2asc(c) & 0x7F] & vS) 3503c84f3f3cSopenharmony_ci#define is_zerocount(c) (classify[rtt2asc(c) & 0x7F] & vZ) 3504c84f3f3cSopenharmony_ci 3505c84f3f3cSopenharmony_cistatic const unsigned char classify[128] = { 3506c84f3f3cSopenharmony_ci/* 0 1 2 3 4 5 6 7 */ 3507c84f3f3cSopenharmony_ci/* 0 ^@ ^A ^B ^C ^D ^E ^F ^G */ 3508c84f3f3cSopenharmony_ci vB, 0, 0, 0, 0, vC|vU, vC|vZ, 0, 3509c84f3f3cSopenharmony_ci/* 1 ^H ^I ^J ^K ^L ^M ^N ^O */ 3510c84f3f3cSopenharmony_ci vM, vC|vZ, 0, 0, vC|vU, 0, vC, 0, 3511c84f3f3cSopenharmony_ci/* 2 ^P ^Q ^R ^S ^T ^U ^V ^W */ 3512c84f3f3cSopenharmony_ci vC, 0, vC|vU, 0, 0, 0, vC, 0, 3513c84f3f3cSopenharmony_ci/* 3 ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */ 3514c84f3f3cSopenharmony_ci vC, 0, 0, vC|vZ, 0, 0, 0, 0, 3515c84f3f3cSopenharmony_ci/* 4 <space> ! " # $ % & ' */ 3516c84f3f3cSopenharmony_ci vM, 0, 0, vC, vM, vM, 0, 0, 3517c84f3f3cSopenharmony_ci/* 5 ( ) * + , - . / */ 3518c84f3f3cSopenharmony_ci 0, 0, vC, vC, vM, vC, 0, vC|vS, 3519c84f3f3cSopenharmony_ci/* 6 0 1 2 3 4 5 6 7 */ 3520c84f3f3cSopenharmony_ci vM, 0, 0, 0, 0, 0, 0, 0, 3521c84f3f3cSopenharmony_ci/* 7 8 9 : ; < = > ? */ 3522c84f3f3cSopenharmony_ci 0, 0, 0, vM, 0, vC, 0, vC|vS, 3523c84f3f3cSopenharmony_ci/* 8 @ A B C D E F G */ 3524c84f3f3cSopenharmony_ci vC|vX, vC, vM, vC, vC, vM, vM|vX, vC|vU|vZ, 3525c84f3f3cSopenharmony_ci/* 9 H I J K L M N O */ 3526c84f3f3cSopenharmony_ci 0, vC, 0, 0, 0, 0, vC|vU, vU, 3527c84f3f3cSopenharmony_ci/* A P Q R S T U V W */ 3528c84f3f3cSopenharmony_ci vC, 0, vC, vC, vM|vX, vC, 0, vM, 3529c84f3f3cSopenharmony_ci/* B X Y Z [ \ ] ^ _ */ 3530c84f3f3cSopenharmony_ci vC, vC|vU, 0, vU, vC|vZ, 0, vM, vC|vZ, 3531c84f3f3cSopenharmony_ci/* C ` a b c d e f g */ 3532c84f3f3cSopenharmony_ci 0, vC, vM, vE, vE, vM, vM|vX, vC|vZ, 3533c84f3f3cSopenharmony_ci/* D h i j k l m n o */ 3534c84f3f3cSopenharmony_ci vM, vC, vC|vU, vC|vU, vM, 0, vC|vU, 0, 3535c84f3f3cSopenharmony_ci/* E p q r s t u v w */ 3536c84f3f3cSopenharmony_ci vC, 0, vX, vC, vM|vX, vC|vU, vC|vU|vZ, vM, 3537c84f3f3cSopenharmony_ci/* F x y z { | } ~ ^? */ 3538c84f3f3cSopenharmony_ci vC, vE|vU, 0, 0, vM|vZ, 0, vC, 0 3539c84f3f3cSopenharmony_ci}; 3540c84f3f3cSopenharmony_ci 3541c84f3f3cSopenharmony_ci#define MAXVICMD 3 3542c84f3f3cSopenharmony_ci#define SRCHLEN 40 3543c84f3f3cSopenharmony_ci 3544c84f3f3cSopenharmony_ci#define INSERT 1 3545c84f3f3cSopenharmony_ci#define REPLACE 2 3546c84f3f3cSopenharmony_ci 3547c84f3f3cSopenharmony_ci#define VNORMAL 0 /* command, insert or replace mode */ 3548c84f3f3cSopenharmony_ci#define VARG1 1 /* digit prefix (first, eg, 5l) */ 3549c84f3f3cSopenharmony_ci#define VEXTCMD 2 /* cmd + movement (eg, cl) */ 3550c84f3f3cSopenharmony_ci#define VARG2 3 /* digit prefix (second, eg, 2c3l) */ 3551c84f3f3cSopenharmony_ci#define VXCH 4 /* f, F, t, T, @ */ 3552c84f3f3cSopenharmony_ci#define VFAIL 5 /* bad command */ 3553c84f3f3cSopenharmony_ci#define VCMD 6 /* single char command (eg, X) */ 3554c84f3f3cSopenharmony_ci#define VREDO 7 /* . */ 3555c84f3f3cSopenharmony_ci#define VLIT 8 /* ^V */ 3556c84f3f3cSopenharmony_ci#define VSEARCH 9 /* /, ? */ 3557c84f3f3cSopenharmony_ci#define VVERSION 10 /* <ESC> ^V */ 3558c84f3f3cSopenharmony_ci#define VPREFIX2 11 /* ^[[ and ^[O in insert mode */ 3559c84f3f3cSopenharmony_ci 3560c84f3f3cSopenharmony_cistatic struct edstate *save_edstate(struct edstate *old); 3561c84f3f3cSopenharmony_cistatic void restore_edstate(struct edstate *old, struct edstate *news); 3562c84f3f3cSopenharmony_cistatic void free_edstate(struct edstate *old); 3563c84f3f3cSopenharmony_ci 3564c84f3f3cSopenharmony_cistatic struct edstate ebuf; 3565c84f3f3cSopenharmony_cistatic struct edstate undobuf; 3566c84f3f3cSopenharmony_ci 3567c84f3f3cSopenharmony_cistatic struct edstate *vs; /* current Vi editing mode state */ 3568c84f3f3cSopenharmony_cistatic struct edstate *undo; 3569c84f3f3cSopenharmony_ci 3570c84f3f3cSopenharmony_cistatic char *ibuf; /* input buffer */ 3571c84f3f3cSopenharmony_cistatic bool first_insert; /* set when starting in insert mode */ 3572c84f3f3cSopenharmony_cistatic int saved_inslen; /* saved inslen for first insert */ 3573c84f3f3cSopenharmony_cistatic int inslen; /* length of input buffer */ 3574c84f3f3cSopenharmony_cistatic int srchlen; /* length of current search pattern */ 3575c84f3f3cSopenharmony_cistatic char *ybuf; /* yank buffer */ 3576c84f3f3cSopenharmony_cistatic int yanklen; /* length of yank buffer */ 3577c84f3f3cSopenharmony_cistatic uint8_t fsavecmd = ORD(' '); /* last find command */ 3578c84f3f3cSopenharmony_cistatic int fsavech; /* character to find */ 3579c84f3f3cSopenharmony_cistatic char lastcmd[MAXVICMD]; /* last non-move command */ 3580c84f3f3cSopenharmony_cistatic int lastac; /* argcnt for lastcmd */ 3581c84f3f3cSopenharmony_cistatic uint8_t lastsearch = ORD(' '); /* last search command */ 3582c84f3f3cSopenharmony_cistatic char srchpat[SRCHLEN]; /* last search pattern */ 3583c84f3f3cSopenharmony_cistatic int insert; /* <>0 in insert mode */ 3584c84f3f3cSopenharmony_cistatic int hnum; /* position in history */ 3585c84f3f3cSopenharmony_cistatic int ohnum; /* history line copied (after mod) */ 3586c84f3f3cSopenharmony_cistatic int hlast; /* 1 past last position in history */ 3587c84f3f3cSopenharmony_cistatic int state; 3588c84f3f3cSopenharmony_ci 3589c84f3f3cSopenharmony_ci/* 3590c84f3f3cSopenharmony_ci * Information for keeping track of macros that are being expanded. 3591c84f3f3cSopenharmony_ci * The format of buf is the alias contents followed by a NUL byte followed 3592c84f3f3cSopenharmony_ci * by the name (letter) of the alias. The end of the buffer is marked by 3593c84f3f3cSopenharmony_ci * a double NUL. The name of the alias is stored so recursive macros can 3594c84f3f3cSopenharmony_ci * be detected. 3595c84f3f3cSopenharmony_ci */ 3596c84f3f3cSopenharmony_cistruct macro_state { 3597c84f3f3cSopenharmony_ci unsigned char *p; /* current position in buf */ 3598c84f3f3cSopenharmony_ci unsigned char *buf; /* pointer to macro(s) being expanded */ 3599c84f3f3cSopenharmony_ci size_t len; /* how much data in buffer */ 3600c84f3f3cSopenharmony_ci}; 3601c84f3f3cSopenharmony_cistatic struct macro_state macro; 3602c84f3f3cSopenharmony_ci 3603c84f3f3cSopenharmony_ci/* last input was expanded */ 3604c84f3f3cSopenharmony_cistatic enum expand_mode { 3605c84f3f3cSopenharmony_ci NONE = 0, EXPAND, COMPLETE, PRINT 3606c84f3f3cSopenharmony_ci} expanded; 3607c84f3f3cSopenharmony_ci 3608c84f3f3cSopenharmony_cistatic int 3609c84f3f3cSopenharmony_cix_vi(char *buf) 3610c84f3f3cSopenharmony_ci{ 3611c84f3f3cSopenharmony_ci int c; 3612c84f3f3cSopenharmony_ci 3613c84f3f3cSopenharmony_ci state = VNORMAL; 3614c84f3f3cSopenharmony_ci ohnum = hnum = hlast = histnum(-1) + 1; 3615c84f3f3cSopenharmony_ci insert = INSERT; 3616c84f3f3cSopenharmony_ci saved_inslen = inslen; 3617c84f3f3cSopenharmony_ci first_insert = true; 3618c84f3f3cSopenharmony_ci inslen = 0; 3619c84f3f3cSopenharmony_ci vi_macro_reset(); 3620c84f3f3cSopenharmony_ci 3621c84f3f3cSopenharmony_ci ebuf.cbuf = buf; 3622c84f3f3cSopenharmony_ci if (undobuf.cbuf == NULL) { 3623c84f3f3cSopenharmony_ci ibuf = alloc(LINE, AEDIT); 3624c84f3f3cSopenharmony_ci ybuf = alloc(LINE, AEDIT); 3625c84f3f3cSopenharmony_ci undobuf.cbuf = alloc(LINE, AEDIT); 3626c84f3f3cSopenharmony_ci } 3627c84f3f3cSopenharmony_ci undobuf.cbufsize = ebuf.cbufsize = LINE; 3628c84f3f3cSopenharmony_ci undobuf.linelen = ebuf.linelen = 0; 3629c84f3f3cSopenharmony_ci undobuf.cursor = ebuf.cursor = 0; 3630c84f3f3cSopenharmony_ci undobuf.winleft = ebuf.winleft = 0; 3631c84f3f3cSopenharmony_ci vs = &ebuf; 3632c84f3f3cSopenharmony_ci undo = &undobuf; 3633c84f3f3cSopenharmony_ci 3634c84f3f3cSopenharmony_ci x_init_prompt(true); 3635c84f3f3cSopenharmony_ci x_col = pwidth; 3636c84f3f3cSopenharmony_ci 3637c84f3f3cSopenharmony_ci if (wbuf_len != x_cols - 3 && ((wbuf_len = x_cols - 3))) { 3638c84f3f3cSopenharmony_ci wbuf[0] = aresize(wbuf[0], wbuf_len, AEDIT); 3639c84f3f3cSopenharmony_ci wbuf[1] = aresize(wbuf[1], wbuf_len, AEDIT); 3640c84f3f3cSopenharmony_ci } 3641c84f3f3cSopenharmony_ci if (wbuf_len) { 3642c84f3f3cSopenharmony_ci memset(wbuf[0], ' ', wbuf_len); 3643c84f3f3cSopenharmony_ci memset(wbuf[1], ' ', wbuf_len); 3644c84f3f3cSopenharmony_ci } 3645c84f3f3cSopenharmony_ci winwidth = x_cols - pwidth - 3; 3646c84f3f3cSopenharmony_ci win = 0; 3647c84f3f3cSopenharmony_ci morec = ' '; 3648c84f3f3cSopenharmony_ci holdlen = 0; 3649c84f3f3cSopenharmony_ci 3650c84f3f3cSopenharmony_ci editmode = 2; 3651c84f3f3cSopenharmony_ci x_flush(); 3652c84f3f3cSopenharmony_ci while (/* CONSTCOND */ 1) { 3653c84f3f3cSopenharmony_ci if (macro.p) { 3654c84f3f3cSopenharmony_ci c = (unsigned char)*macro.p++; 3655c84f3f3cSopenharmony_ci /* end of current macro? */ 3656c84f3f3cSopenharmony_ci if (!c) { 3657c84f3f3cSopenharmony_ci /* more macros left to finish? */ 3658c84f3f3cSopenharmony_ci if (*macro.p++) 3659c84f3f3cSopenharmony_ci continue; 3660c84f3f3cSopenharmony_ci /* must be the end of all the macros */ 3661c84f3f3cSopenharmony_ci vi_macro_reset(); 3662c84f3f3cSopenharmony_ci c = x_getc(); 3663c84f3f3cSopenharmony_ci } 3664c84f3f3cSopenharmony_ci } else 3665c84f3f3cSopenharmony_ci c = x_getc(); 3666c84f3f3cSopenharmony_ci 3667c84f3f3cSopenharmony_ci if (c == -1) 3668c84f3f3cSopenharmony_ci break; 3669c84f3f3cSopenharmony_ci if (state != VLIT) { 3670c84f3f3cSopenharmony_ci if (isched(c, edchars.intr) || 3671c84f3f3cSopenharmony_ci isched(c, edchars.quit)) { 3672c84f3f3cSopenharmony_ci /* shove input buffer away */ 3673c84f3f3cSopenharmony_ci xbuf = ebuf.cbuf; 3674c84f3f3cSopenharmony_ci xep = xbuf; 3675c84f3f3cSopenharmony_ci if (ebuf.linelen > 0) 3676c84f3f3cSopenharmony_ci xep += ebuf.linelen; 3677c84f3f3cSopenharmony_ci /* pretend we got an interrupt */ 3678c84f3f3cSopenharmony_ci x_intr(isched(c, edchars.intr) ? 3679c84f3f3cSopenharmony_ci SIGINT : SIGQUIT, c); 3680c84f3f3cSopenharmony_ci } else if (isched(c, edchars.eof) && 3681c84f3f3cSopenharmony_ci state != VVERSION) { 3682c84f3f3cSopenharmony_ci if (vs->linelen == 0) { 3683c84f3f3cSopenharmony_ci x_vi_zotc(c); 3684c84f3f3cSopenharmony_ci c = -1; 3685c84f3f3cSopenharmony_ci break; 3686c84f3f3cSopenharmony_ci } 3687c84f3f3cSopenharmony_ci continue; 3688c84f3f3cSopenharmony_ci } 3689c84f3f3cSopenharmony_ci } 3690c84f3f3cSopenharmony_ci if (vi_hook(c)) 3691c84f3f3cSopenharmony_ci break; 3692c84f3f3cSopenharmony_ci x_flush(); 3693c84f3f3cSopenharmony_ci } 3694c84f3f3cSopenharmony_ci 3695c84f3f3cSopenharmony_ci x_putc('\r'); 3696c84f3f3cSopenharmony_ci x_putc('\n'); 3697c84f3f3cSopenharmony_ci x_flush(); 3698c84f3f3cSopenharmony_ci 3699c84f3f3cSopenharmony_ci if (c == -1 || (ssize_t)LINE <= vs->linelen) 3700c84f3f3cSopenharmony_ci return (-1); 3701c84f3f3cSopenharmony_ci 3702c84f3f3cSopenharmony_ci if (vs->cbuf != buf) 3703c84f3f3cSopenharmony_ci memcpy(buf, vs->cbuf, vs->linelen); 3704c84f3f3cSopenharmony_ci 3705c84f3f3cSopenharmony_ci buf[vs->linelen++] = '\n'; 3706c84f3f3cSopenharmony_ci 3707c84f3f3cSopenharmony_ci return (vs->linelen); 3708c84f3f3cSopenharmony_ci} 3709c84f3f3cSopenharmony_ci 3710c84f3f3cSopenharmony_cistatic int 3711c84f3f3cSopenharmony_civi_hook(int ch) 3712c84f3f3cSopenharmony_ci{ 3713c84f3f3cSopenharmony_ci static char curcmd[MAXVICMD], locpat[SRCHLEN]; 3714c84f3f3cSopenharmony_ci static int cmdlen, argc1, argc2; 3715c84f3f3cSopenharmony_ci 3716c84f3f3cSopenharmony_ci switch (state) { 3717c84f3f3cSopenharmony_ci 3718c84f3f3cSopenharmony_ci case VNORMAL: 3719c84f3f3cSopenharmony_ci /* PC scancodes */ 3720c84f3f3cSopenharmony_ci if (!ch) { 3721c84f3f3cSopenharmony_ci cmdlen = 0; 3722c84f3f3cSopenharmony_ci switch (ch = x_getc()) { 3723c84f3f3cSopenharmony_ci case 71: ch = ORD('0'); goto pseudo_vi_command; 3724c84f3f3cSopenharmony_ci case 72: ch = ORD('k'); goto pseudo_vi_command; 3725c84f3f3cSopenharmony_ci case 73: ch = ORD('A'); goto vi_xfunc_search; 3726c84f3f3cSopenharmony_ci case 75: ch = ORD('h'); goto pseudo_vi_command; 3727c84f3f3cSopenharmony_ci case 77: ch = ORD('l'); goto pseudo_vi_command; 3728c84f3f3cSopenharmony_ci case 79: ch = ORD('$'); goto pseudo_vi_command; 3729c84f3f3cSopenharmony_ci case 80: ch = ORD('j'); goto pseudo_vi_command; 3730c84f3f3cSopenharmony_ci case 81: ch = ORD('B'); goto vi_xfunc_search; 3731c84f3f3cSopenharmony_ci case 83: ch = ORD('x'); goto pseudo_vi_command; 3732c84f3f3cSopenharmony_ci default: ch = 0; goto vi_insert_failed; 3733c84f3f3cSopenharmony_ci } 3734c84f3f3cSopenharmony_ci } 3735c84f3f3cSopenharmony_ci if (insert != 0) { 3736c84f3f3cSopenharmony_ci if (ch == CTRL_V) { 3737c84f3f3cSopenharmony_ci state = VLIT; 3738c84f3f3cSopenharmony_ci ch = ORD('^'); 3739c84f3f3cSopenharmony_ci } 3740c84f3f3cSopenharmony_ci switch (vi_insert(ch)) { 3741c84f3f3cSopenharmony_ci case -1: 3742c84f3f3cSopenharmony_ci vi_insert_failed: 3743c84f3f3cSopenharmony_ci vi_error(); 3744c84f3f3cSopenharmony_ci state = VNORMAL; 3745c84f3f3cSopenharmony_ci break; 3746c84f3f3cSopenharmony_ci case 0: 3747c84f3f3cSopenharmony_ci if (state == VLIT) { 3748c84f3f3cSopenharmony_ci vs->cursor--; 3749c84f3f3cSopenharmony_ci refresh(false); 3750c84f3f3cSopenharmony_ci } else 3751c84f3f3cSopenharmony_ci refresh(insert != 0); 3752c84f3f3cSopenharmony_ci break; 3753c84f3f3cSopenharmony_ci case 1: 3754c84f3f3cSopenharmony_ci return (1); 3755c84f3f3cSopenharmony_ci } 3756c84f3f3cSopenharmony_ci } else { 3757c84f3f3cSopenharmony_ci if (ctype(ch, C_CR | C_LF)) 3758c84f3f3cSopenharmony_ci return (1); 3759c84f3f3cSopenharmony_ci cmdlen = 0; 3760c84f3f3cSopenharmony_ci argc1 = 0; 3761c84f3f3cSopenharmony_ci if (ctype(ch, C_DIGIT) && ord(ch) != ORD('0')) { 3762c84f3f3cSopenharmony_ci argc1 = ksh_numdig(ch); 3763c84f3f3cSopenharmony_ci state = VARG1; 3764c84f3f3cSopenharmony_ci } else { 3765c84f3f3cSopenharmony_ci pseudo_vi_command: 3766c84f3f3cSopenharmony_ci curcmd[cmdlen++] = ch; 3767c84f3f3cSopenharmony_ci state = nextstate(ch); 3768c84f3f3cSopenharmony_ci if (state == VSEARCH) { 3769c84f3f3cSopenharmony_ci save_cbuf(); 3770c84f3f3cSopenharmony_ci vs->cursor = 0; 3771c84f3f3cSopenharmony_ci vs->linelen = 0; 3772c84f3f3cSopenharmony_ci if (putbuf(ord(ch) == ORD('/') ? 3773c84f3f3cSopenharmony_ci "/" : "?", 1, false) != 0) 3774c84f3f3cSopenharmony_ci return (-1); 3775c84f3f3cSopenharmony_ci refresh(false); 3776c84f3f3cSopenharmony_ci } 3777c84f3f3cSopenharmony_ci if (state == VVERSION) { 3778c84f3f3cSopenharmony_ci save_cbuf(); 3779c84f3f3cSopenharmony_ci vs->cursor = 0; 3780c84f3f3cSopenharmony_ci vs->linelen = 0; 3781c84f3f3cSopenharmony_ci putbuf(KSH_VERSION, 3782c84f3f3cSopenharmony_ci strlen(KSH_VERSION), false); 3783c84f3f3cSopenharmony_ci refresh(false); 3784c84f3f3cSopenharmony_ci } 3785c84f3f3cSopenharmony_ci } 3786c84f3f3cSopenharmony_ci } 3787c84f3f3cSopenharmony_ci break; 3788c84f3f3cSopenharmony_ci 3789c84f3f3cSopenharmony_ci case VLIT: 3790c84f3f3cSopenharmony_ci if (is_bad(ch)) { 3791c84f3f3cSopenharmony_ci del_range(vs->cursor, vs->cursor + 1); 3792c84f3f3cSopenharmony_ci vi_error(); 3793c84f3f3cSopenharmony_ci } else 3794c84f3f3cSopenharmony_ci vs->cbuf[vs->cursor++] = ch; 3795c84f3f3cSopenharmony_ci refresh(true); 3796c84f3f3cSopenharmony_ci state = VNORMAL; 3797c84f3f3cSopenharmony_ci break; 3798c84f3f3cSopenharmony_ci 3799c84f3f3cSopenharmony_ci case VVERSION: 3800c84f3f3cSopenharmony_ci restore_cbuf(); 3801c84f3f3cSopenharmony_ci state = VNORMAL; 3802c84f3f3cSopenharmony_ci refresh(false); 3803c84f3f3cSopenharmony_ci break; 3804c84f3f3cSopenharmony_ci 3805c84f3f3cSopenharmony_ci case VARG1: 3806c84f3f3cSopenharmony_ci if (ctype(ch, C_DIGIT)) 3807c84f3f3cSopenharmony_ci argc1 = argc1 * 10 + ksh_numdig(ch); 3808c84f3f3cSopenharmony_ci else { 3809c84f3f3cSopenharmony_ci curcmd[cmdlen++] = ch; 3810c84f3f3cSopenharmony_ci state = nextstate(ch); 3811c84f3f3cSopenharmony_ci } 3812c84f3f3cSopenharmony_ci break; 3813c84f3f3cSopenharmony_ci 3814c84f3f3cSopenharmony_ci case VEXTCMD: 3815c84f3f3cSopenharmony_ci argc2 = 0; 3816c84f3f3cSopenharmony_ci if (ctype(ch, C_DIGIT) && ord(ch) != ORD('0')) { 3817c84f3f3cSopenharmony_ci argc2 = ksh_numdig(ch); 3818c84f3f3cSopenharmony_ci state = VARG2; 3819c84f3f3cSopenharmony_ci return (0); 3820c84f3f3cSopenharmony_ci } else { 3821c84f3f3cSopenharmony_ci curcmd[cmdlen++] = ch; 3822c84f3f3cSopenharmony_ci if (ch == curcmd[0]) 3823c84f3f3cSopenharmony_ci state = VCMD; 3824c84f3f3cSopenharmony_ci else if (is_move(ch)) 3825c84f3f3cSopenharmony_ci state = nextstate(ch); 3826c84f3f3cSopenharmony_ci else 3827c84f3f3cSopenharmony_ci state = VFAIL; 3828c84f3f3cSopenharmony_ci } 3829c84f3f3cSopenharmony_ci break; 3830c84f3f3cSopenharmony_ci 3831c84f3f3cSopenharmony_ci case VARG2: 3832c84f3f3cSopenharmony_ci if (ctype(ch, C_DIGIT)) 3833c84f3f3cSopenharmony_ci argc2 = argc2 * 10 + ksh_numdig(ch); 3834c84f3f3cSopenharmony_ci else { 3835c84f3f3cSopenharmony_ci if (argc1 == 0) 3836c84f3f3cSopenharmony_ci argc1 = argc2; 3837c84f3f3cSopenharmony_ci else 3838c84f3f3cSopenharmony_ci argc1 *= argc2; 3839c84f3f3cSopenharmony_ci curcmd[cmdlen++] = ch; 3840c84f3f3cSopenharmony_ci if (ch == curcmd[0]) 3841c84f3f3cSopenharmony_ci state = VCMD; 3842c84f3f3cSopenharmony_ci else if (is_move(ch)) 3843c84f3f3cSopenharmony_ci state = nextstate(ch); 3844c84f3f3cSopenharmony_ci else 3845c84f3f3cSopenharmony_ci state = VFAIL; 3846c84f3f3cSopenharmony_ci } 3847c84f3f3cSopenharmony_ci break; 3848c84f3f3cSopenharmony_ci 3849c84f3f3cSopenharmony_ci case VXCH: 3850c84f3f3cSopenharmony_ci if (ch == CTRL_BO) 3851c84f3f3cSopenharmony_ci state = VNORMAL; 3852c84f3f3cSopenharmony_ci else { 3853c84f3f3cSopenharmony_ci curcmd[cmdlen++] = ch; 3854c84f3f3cSopenharmony_ci state = VCMD; 3855c84f3f3cSopenharmony_ci } 3856c84f3f3cSopenharmony_ci break; 3857c84f3f3cSopenharmony_ci 3858c84f3f3cSopenharmony_ci case VSEARCH: 3859c84f3f3cSopenharmony_ci if (ctype(ch, C_CR | C_LF) /* || ch == CTRL_BO */ ) { 3860c84f3f3cSopenharmony_ci restore_cbuf(); 3861c84f3f3cSopenharmony_ci /* Repeat last search? */ 3862c84f3f3cSopenharmony_ci if (srchlen == 0) { 3863c84f3f3cSopenharmony_ci if (!srchpat[0]) { 3864c84f3f3cSopenharmony_ci vi_error(); 3865c84f3f3cSopenharmony_ci state = VNORMAL; 3866c84f3f3cSopenharmony_ci refresh(false); 3867c84f3f3cSopenharmony_ci return (0); 3868c84f3f3cSopenharmony_ci } 3869c84f3f3cSopenharmony_ci } else { 3870c84f3f3cSopenharmony_ci locpat[srchlen] = '\0'; 3871c84f3f3cSopenharmony_ci memcpy(srchpat, locpat, srchlen + 1); 3872c84f3f3cSopenharmony_ci } 3873c84f3f3cSopenharmony_ci state = VCMD; 3874c84f3f3cSopenharmony_ci } else if (isched(ch, edchars.erase) || ch == CTRL_H) { 3875c84f3f3cSopenharmony_ci if (srchlen != 0) { 3876c84f3f3cSopenharmony_ci srchlen--; 3877c84f3f3cSopenharmony_ci vs->linelen -= char_len(locpat[srchlen]); 3878c84f3f3cSopenharmony_ci vs->cursor = vs->linelen; 3879c84f3f3cSopenharmony_ci refresh(false); 3880c84f3f3cSopenharmony_ci return (0); 3881c84f3f3cSopenharmony_ci } 3882c84f3f3cSopenharmony_ci restore_cbuf(); 3883c84f3f3cSopenharmony_ci state = VNORMAL; 3884c84f3f3cSopenharmony_ci refresh(false); 3885c84f3f3cSopenharmony_ci } else if (isched(ch, edchars.kill)) { 3886c84f3f3cSopenharmony_ci srchlen = 0; 3887c84f3f3cSopenharmony_ci vs->linelen = 1; 3888c84f3f3cSopenharmony_ci vs->cursor = 1; 3889c84f3f3cSopenharmony_ci refresh(false); 3890c84f3f3cSopenharmony_ci return (0); 3891c84f3f3cSopenharmony_ci } else if (isched(ch, edchars.werase)) { 3892c84f3f3cSopenharmony_ci unsigned int i, n; 3893c84f3f3cSopenharmony_ci struct edstate new_es, *save_es; 3894c84f3f3cSopenharmony_ci 3895c84f3f3cSopenharmony_ci new_es.cursor = srchlen; 3896c84f3f3cSopenharmony_ci new_es.cbuf = locpat; 3897c84f3f3cSopenharmony_ci 3898c84f3f3cSopenharmony_ci save_es = vs; 3899c84f3f3cSopenharmony_ci vs = &new_es; 3900c84f3f3cSopenharmony_ci n = backword(1); 3901c84f3f3cSopenharmony_ci vs = save_es; 3902c84f3f3cSopenharmony_ci 3903c84f3f3cSopenharmony_ci i = (unsigned)srchlen; 3904c84f3f3cSopenharmony_ci while (i-- > n) 3905c84f3f3cSopenharmony_ci vs->linelen -= char_len(locpat[i]); 3906c84f3f3cSopenharmony_ci srchlen = (int)n; 3907c84f3f3cSopenharmony_ci vs->cursor = vs->linelen; 3908c84f3f3cSopenharmony_ci refresh(false); 3909c84f3f3cSopenharmony_ci return (0); 3910c84f3f3cSopenharmony_ci } else { 3911c84f3f3cSopenharmony_ci if (srchlen == SRCHLEN - 1) 3912c84f3f3cSopenharmony_ci vi_error(); 3913c84f3f3cSopenharmony_ci else { 3914c84f3f3cSopenharmony_ci locpat[srchlen++] = ch; 3915c84f3f3cSopenharmony_ci if (ksh_isctrl(ch)) { 3916c84f3f3cSopenharmony_ci if ((size_t)vs->linelen + 2 > 3917c84f3f3cSopenharmony_ci (size_t)vs->cbufsize) 3918c84f3f3cSopenharmony_ci vi_error(); 3919c84f3f3cSopenharmony_ci vs->cbuf[vs->linelen++] = '^'; 3920c84f3f3cSopenharmony_ci vs->cbuf[vs->linelen++] = ksh_unctrl(ch); 3921c84f3f3cSopenharmony_ci } else { 3922c84f3f3cSopenharmony_ci if (vs->linelen >= vs->cbufsize) 3923c84f3f3cSopenharmony_ci vi_error(); 3924c84f3f3cSopenharmony_ci vs->cbuf[vs->linelen++] = ch; 3925c84f3f3cSopenharmony_ci } 3926c84f3f3cSopenharmony_ci vs->cursor = vs->linelen; 3927c84f3f3cSopenharmony_ci refresh(false); 3928c84f3f3cSopenharmony_ci } 3929c84f3f3cSopenharmony_ci return (0); 3930c84f3f3cSopenharmony_ci } 3931c84f3f3cSopenharmony_ci break; 3932c84f3f3cSopenharmony_ci 3933c84f3f3cSopenharmony_ci case VPREFIX2: 3934c84f3f3cSopenharmony_ci vi_xfunc_search: 3935c84f3f3cSopenharmony_ci state = VFAIL; 3936c84f3f3cSopenharmony_ci switch (ch) { 3937c84f3f3cSopenharmony_ci case ORD('A'): 3938c84f3f3cSopenharmony_ci case ORD('B'): 3939c84f3f3cSopenharmony_ci /* the cursor may not be at the BOL */ 3940c84f3f3cSopenharmony_ci if (!vs->cursor) 3941c84f3f3cSopenharmony_ci break; 3942c84f3f3cSopenharmony_ci /* nor further in the line than we can search for */ 3943c84f3f3cSopenharmony_ci if ((size_t)vs->cursor >= sizeof(srchpat) - 1) 3944c84f3f3cSopenharmony_ci vs->cursor = sizeof(srchpat) - 2; 3945c84f3f3cSopenharmony_ci /* anchor the search pattern */ 3946c84f3f3cSopenharmony_ci srchpat[0] = '^'; 3947c84f3f3cSopenharmony_ci /* take current line up to the cursor */ 3948c84f3f3cSopenharmony_ci memcpy(srchpat + 1, vs->cbuf, vs->cursor); 3949c84f3f3cSopenharmony_ci srchpat[vs->cursor + 1] = '\0'; 3950c84f3f3cSopenharmony_ci /* set a magic flag */ 3951c84f3f3cSopenharmony_ci argc1 = 2 + (int)vs->cursor; 3952c84f3f3cSopenharmony_ci /* and emulate a history search */ 3953c84f3f3cSopenharmony_ci /* search backwards if PgUp, forwards for PgDn */ 3954c84f3f3cSopenharmony_ci lastsearch = ch == ORD('A') ? '/' : '?'; 3955c84f3f3cSopenharmony_ci *curcmd = 'n'; 3956c84f3f3cSopenharmony_ci goto pseudo_VCMD; 3957c84f3f3cSopenharmony_ci } 3958c84f3f3cSopenharmony_ci break; 3959c84f3f3cSopenharmony_ci } 3960c84f3f3cSopenharmony_ci 3961c84f3f3cSopenharmony_ci switch (state) { 3962c84f3f3cSopenharmony_ci case VCMD: 3963c84f3f3cSopenharmony_ci pseudo_VCMD: 3964c84f3f3cSopenharmony_ci state = VNORMAL; 3965c84f3f3cSopenharmony_ci switch (vi_cmd(argc1, curcmd)) { 3966c84f3f3cSopenharmony_ci case -1: 3967c84f3f3cSopenharmony_ci vi_error(); 3968c84f3f3cSopenharmony_ci refresh(false); 3969c84f3f3cSopenharmony_ci break; 3970c84f3f3cSopenharmony_ci case 0: 3971c84f3f3cSopenharmony_ci if (insert != 0) 3972c84f3f3cSopenharmony_ci inslen = 0; 3973c84f3f3cSopenharmony_ci refresh(insert != 0); 3974c84f3f3cSopenharmony_ci break; 3975c84f3f3cSopenharmony_ci case 1: 3976c84f3f3cSopenharmony_ci refresh(false); 3977c84f3f3cSopenharmony_ci return (1); 3978c84f3f3cSopenharmony_ci case 2: 3979c84f3f3cSopenharmony_ci /* back from a 'v' command - don't redraw the screen */ 3980c84f3f3cSopenharmony_ci return (1); 3981c84f3f3cSopenharmony_ci } 3982c84f3f3cSopenharmony_ci break; 3983c84f3f3cSopenharmony_ci 3984c84f3f3cSopenharmony_ci case VREDO: 3985c84f3f3cSopenharmony_ci state = VNORMAL; 3986c84f3f3cSopenharmony_ci if (argc1 != 0) 3987c84f3f3cSopenharmony_ci lastac = argc1; 3988c84f3f3cSopenharmony_ci switch (vi_cmd(lastac, lastcmd)) { 3989c84f3f3cSopenharmony_ci case -1: 3990c84f3f3cSopenharmony_ci vi_error(); 3991c84f3f3cSopenharmony_ci refresh(false); 3992c84f3f3cSopenharmony_ci break; 3993c84f3f3cSopenharmony_ci case 0: 3994c84f3f3cSopenharmony_ci if (insert != 0) { 3995c84f3f3cSopenharmony_ci if (lastcmd[0] == 's' || 3996c84f3f3cSopenharmony_ci ksh_eq(lastcmd[0], 'C', 'c')) { 3997c84f3f3cSopenharmony_ci if (redo_insert(1) != 0) 3998c84f3f3cSopenharmony_ci vi_error(); 3999c84f3f3cSopenharmony_ci } else { 4000c84f3f3cSopenharmony_ci if (redo_insert(lastac) != 0) 4001c84f3f3cSopenharmony_ci vi_error(); 4002c84f3f3cSopenharmony_ci } 4003c84f3f3cSopenharmony_ci } 4004c84f3f3cSopenharmony_ci refresh(false); 4005c84f3f3cSopenharmony_ci break; 4006c84f3f3cSopenharmony_ci case 1: 4007c84f3f3cSopenharmony_ci refresh(false); 4008c84f3f3cSopenharmony_ci return (1); 4009c84f3f3cSopenharmony_ci case 2: 4010c84f3f3cSopenharmony_ci /* back from a 'v' command - can't happen */ 4011c84f3f3cSopenharmony_ci break; 4012c84f3f3cSopenharmony_ci } 4013c84f3f3cSopenharmony_ci break; 4014c84f3f3cSopenharmony_ci 4015c84f3f3cSopenharmony_ci case VFAIL: 4016c84f3f3cSopenharmony_ci state = VNORMAL; 4017c84f3f3cSopenharmony_ci vi_error(); 4018c84f3f3cSopenharmony_ci break; 4019c84f3f3cSopenharmony_ci } 4020c84f3f3cSopenharmony_ci return (0); 4021c84f3f3cSopenharmony_ci} 4022c84f3f3cSopenharmony_ci 4023c84f3f3cSopenharmony_cistatic int 4024c84f3f3cSopenharmony_cinextstate(int ch) 4025c84f3f3cSopenharmony_ci{ 4026c84f3f3cSopenharmony_ci if (is_extend(ch)) 4027c84f3f3cSopenharmony_ci return (VEXTCMD); 4028c84f3f3cSopenharmony_ci else if (is_srch(ch)) 4029c84f3f3cSopenharmony_ci return (VSEARCH); 4030c84f3f3cSopenharmony_ci else if (is_long(ch)) 4031c84f3f3cSopenharmony_ci return (VXCH); 4032c84f3f3cSopenharmony_ci else if (ch == '.') 4033c84f3f3cSopenharmony_ci return (VREDO); 4034c84f3f3cSopenharmony_ci else if (ch == CTRL_V) 4035c84f3f3cSopenharmony_ci return (VVERSION); 4036c84f3f3cSopenharmony_ci else if (is_cmd(ch)) 4037c84f3f3cSopenharmony_ci return (VCMD); 4038c84f3f3cSopenharmony_ci else 4039c84f3f3cSopenharmony_ci return (VFAIL); 4040c84f3f3cSopenharmony_ci} 4041c84f3f3cSopenharmony_ci 4042c84f3f3cSopenharmony_cistatic int 4043c84f3f3cSopenharmony_civi_insert(int ch) 4044c84f3f3cSopenharmony_ci{ 4045c84f3f3cSopenharmony_ci int tcursor; 4046c84f3f3cSopenharmony_ci 4047c84f3f3cSopenharmony_ci if (isched(ch, edchars.erase) || ch == CTRL_H) { 4048c84f3f3cSopenharmony_ci if (insert == REPLACE) { 4049c84f3f3cSopenharmony_ci if (vs->cursor == undo->cursor) { 4050c84f3f3cSopenharmony_ci vi_error(); 4051c84f3f3cSopenharmony_ci return (0); 4052c84f3f3cSopenharmony_ci } 4053c84f3f3cSopenharmony_ci if (inslen > 0) 4054c84f3f3cSopenharmony_ci inslen--; 4055c84f3f3cSopenharmony_ci vs->cursor--; 4056c84f3f3cSopenharmony_ci if (vs->cursor >= undo->linelen) 4057c84f3f3cSopenharmony_ci vs->linelen--; 4058c84f3f3cSopenharmony_ci else 4059c84f3f3cSopenharmony_ci vs->cbuf[vs->cursor] = undo->cbuf[vs->cursor]; 4060c84f3f3cSopenharmony_ci } else { 4061c84f3f3cSopenharmony_ci if (vs->cursor == 0) 4062c84f3f3cSopenharmony_ci return (0); 4063c84f3f3cSopenharmony_ci if (inslen > 0) 4064c84f3f3cSopenharmony_ci inslen--; 4065c84f3f3cSopenharmony_ci vs->cursor--; 4066c84f3f3cSopenharmony_ci vs->linelen--; 4067c84f3f3cSopenharmony_ci memmove(&vs->cbuf[vs->cursor], &vs->cbuf[vs->cursor + 1], 4068c84f3f3cSopenharmony_ci vs->linelen - vs->cursor + 1); 4069c84f3f3cSopenharmony_ci } 4070c84f3f3cSopenharmony_ci expanded = NONE; 4071c84f3f3cSopenharmony_ci return (0); 4072c84f3f3cSopenharmony_ci } 4073c84f3f3cSopenharmony_ci if (isched(ch, edchars.kill)) { 4074c84f3f3cSopenharmony_ci if (vs->cursor != 0) { 4075c84f3f3cSopenharmony_ci inslen = 0; 4076c84f3f3cSopenharmony_ci memmove(vs->cbuf, &vs->cbuf[vs->cursor], 4077c84f3f3cSopenharmony_ci vs->linelen - vs->cursor); 4078c84f3f3cSopenharmony_ci vs->linelen -= vs->cursor; 4079c84f3f3cSopenharmony_ci vs->cursor = 0; 4080c84f3f3cSopenharmony_ci } 4081c84f3f3cSopenharmony_ci expanded = NONE; 4082c84f3f3cSopenharmony_ci return (0); 4083c84f3f3cSopenharmony_ci } 4084c84f3f3cSopenharmony_ci if (isched(ch, edchars.werase)) { 4085c84f3f3cSopenharmony_ci if (vs->cursor != 0) { 4086c84f3f3cSopenharmony_ci tcursor = backword(1); 4087c84f3f3cSopenharmony_ci memmove(&vs->cbuf[tcursor], &vs->cbuf[vs->cursor], 4088c84f3f3cSopenharmony_ci vs->linelen - vs->cursor); 4089c84f3f3cSopenharmony_ci vs->linelen -= vs->cursor - tcursor; 4090c84f3f3cSopenharmony_ci if (inslen < vs->cursor - tcursor) 4091c84f3f3cSopenharmony_ci inslen = 0; 4092c84f3f3cSopenharmony_ci else 4093c84f3f3cSopenharmony_ci inslen -= vs->cursor - tcursor; 4094c84f3f3cSopenharmony_ci vs->cursor = tcursor; 4095c84f3f3cSopenharmony_ci } 4096c84f3f3cSopenharmony_ci expanded = NONE; 4097c84f3f3cSopenharmony_ci return (0); 4098c84f3f3cSopenharmony_ci } 4099c84f3f3cSopenharmony_ci /* 4100c84f3f3cSopenharmony_ci * If any chars are entered before escape, trash the saved insert 4101c84f3f3cSopenharmony_ci * buffer (if user inserts & deletes char, ibuf gets trashed and 4102c84f3f3cSopenharmony_ci * we don't want to use it) 4103c84f3f3cSopenharmony_ci */ 4104c84f3f3cSopenharmony_ci if (first_insert && ch != CTRL_BO) 4105c84f3f3cSopenharmony_ci saved_inslen = 0; 4106c84f3f3cSopenharmony_ci switch (ch) { 4107c84f3f3cSopenharmony_ci case '\0': 4108c84f3f3cSopenharmony_ci return (-1); 4109c84f3f3cSopenharmony_ci 4110c84f3f3cSopenharmony_ci case '\r': 4111c84f3f3cSopenharmony_ci case '\n': 4112c84f3f3cSopenharmony_ci return (1); 4113c84f3f3cSopenharmony_ci 4114c84f3f3cSopenharmony_ci case CTRL_BO: 4115c84f3f3cSopenharmony_ci expanded = NONE; 4116c84f3f3cSopenharmony_ci if (first_insert) { 4117c84f3f3cSopenharmony_ci first_insert = false; 4118c84f3f3cSopenharmony_ci if (inslen == 0) { 4119c84f3f3cSopenharmony_ci inslen = saved_inslen; 4120c84f3f3cSopenharmony_ci return (redo_insert(0)); 4121c84f3f3cSopenharmony_ci } 4122c84f3f3cSopenharmony_ci lastcmd[0] = 'a'; 4123c84f3f3cSopenharmony_ci lastac = 1; 4124c84f3f3cSopenharmony_ci } 4125c84f3f3cSopenharmony_ci if (lastcmd[0] == 's' || ksh_eq(lastcmd[0], 'C', 'c')) 4126c84f3f3cSopenharmony_ci return (redo_insert(0)); 4127c84f3f3cSopenharmony_ci else 4128c84f3f3cSopenharmony_ci return (redo_insert(lastac - 1)); 4129c84f3f3cSopenharmony_ci 4130c84f3f3cSopenharmony_ci /* { start nonstandard vi commands */ 4131c84f3f3cSopenharmony_ci case CTRL_X: 4132c84f3f3cSopenharmony_ci expand_word(0); 4133c84f3f3cSopenharmony_ci break; 4134c84f3f3cSopenharmony_ci 4135c84f3f3cSopenharmony_ci case CTRL_F: 4136c84f3f3cSopenharmony_ci complete_word(0, 0); 4137c84f3f3cSopenharmony_ci break; 4138c84f3f3cSopenharmony_ci 4139c84f3f3cSopenharmony_ci case CTRL_E: 4140c84f3f3cSopenharmony_ci print_expansions(vs, 0); 4141c84f3f3cSopenharmony_ci break; 4142c84f3f3cSopenharmony_ci 4143c84f3f3cSopenharmony_ci case CTRL_I: 4144c84f3f3cSopenharmony_ci if (Flag(FVITABCOMPLETE)) { 4145c84f3f3cSopenharmony_ci complete_word(0, 0); 4146c84f3f3cSopenharmony_ci break; 4147c84f3f3cSopenharmony_ci } 4148c84f3f3cSopenharmony_ci /* FALLTHROUGH */ 4149c84f3f3cSopenharmony_ci /* end nonstandard vi commands } */ 4150c84f3f3cSopenharmony_ci 4151c84f3f3cSopenharmony_ci default: 4152c84f3f3cSopenharmony_ci if (vs->linelen >= vs->cbufsize - 1) 4153c84f3f3cSopenharmony_ci return (-1); 4154c84f3f3cSopenharmony_ci ibuf[inslen++] = ch; 4155c84f3f3cSopenharmony_ci if (insert == INSERT) { 4156c84f3f3cSopenharmony_ci memmove(&vs->cbuf[vs->cursor + 1], &vs->cbuf[vs->cursor], 4157c84f3f3cSopenharmony_ci vs->linelen - vs->cursor); 4158c84f3f3cSopenharmony_ci vs->linelen++; 4159c84f3f3cSopenharmony_ci } 4160c84f3f3cSopenharmony_ci vs->cbuf[vs->cursor++] = ch; 4161c84f3f3cSopenharmony_ci if (insert == REPLACE && vs->cursor > vs->linelen) 4162c84f3f3cSopenharmony_ci vs->linelen++; 4163c84f3f3cSopenharmony_ci expanded = NONE; 4164c84f3f3cSopenharmony_ci } 4165c84f3f3cSopenharmony_ci return (0); 4166c84f3f3cSopenharmony_ci} 4167c84f3f3cSopenharmony_ci 4168c84f3f3cSopenharmony_cistatic int 4169c84f3f3cSopenharmony_civi_cmd(int argcnt, const char *cmd) 4170c84f3f3cSopenharmony_ci{ 4171c84f3f3cSopenharmony_ci int ncursor; 4172c84f3f3cSopenharmony_ci int cur, c1, c2; 4173c84f3f3cSopenharmony_ci int any; 4174c84f3f3cSopenharmony_ci bool b; 4175c84f3f3cSopenharmony_ci struct edstate *t; 4176c84f3f3cSopenharmony_ci 4177c84f3f3cSopenharmony_ci if (argcnt == 0 && !is_zerocount(*cmd)) 4178c84f3f3cSopenharmony_ci argcnt = 1; 4179c84f3f3cSopenharmony_ci 4180c84f3f3cSopenharmony_ci if (is_move(*cmd)) { 4181c84f3f3cSopenharmony_ci if ((cur = domove(argcnt, cmd, 0)) >= 0) { 4182c84f3f3cSopenharmony_ci if (cur == vs->linelen && cur != 0) 4183c84f3f3cSopenharmony_ci cur--; 4184c84f3f3cSopenharmony_ci vs->cursor = cur; 4185c84f3f3cSopenharmony_ci } else 4186c84f3f3cSopenharmony_ci return (-1); 4187c84f3f3cSopenharmony_ci } else { 4188c84f3f3cSopenharmony_ci /* Don't save state in middle of macro.. */ 4189c84f3f3cSopenharmony_ci if (is_undoable(*cmd) && !macro.p) { 4190c84f3f3cSopenharmony_ci undo->winleft = vs->winleft; 4191c84f3f3cSopenharmony_ci memmove(undo->cbuf, vs->cbuf, vs->linelen); 4192c84f3f3cSopenharmony_ci undo->linelen = vs->linelen; 4193c84f3f3cSopenharmony_ci undo->cursor = vs->cursor; 4194c84f3f3cSopenharmony_ci lastac = argcnt; 4195c84f3f3cSopenharmony_ci memmove(lastcmd, cmd, MAXVICMD); 4196c84f3f3cSopenharmony_ci } 4197c84f3f3cSopenharmony_ci switch (ord(*cmd)) { 4198c84f3f3cSopenharmony_ci 4199c84f3f3cSopenharmony_ci case CTRL_L: 4200c84f3f3cSopenharmony_ci case CTRL_R: 4201c84f3f3cSopenharmony_ci redraw_line(true); 4202c84f3f3cSopenharmony_ci break; 4203c84f3f3cSopenharmony_ci 4204c84f3f3cSopenharmony_ci case ORD('@'): 4205c84f3f3cSopenharmony_ci { 4206c84f3f3cSopenharmony_ci static char alias[] = "_\0"; 4207c84f3f3cSopenharmony_ci struct tbl *ap; 4208c84f3f3cSopenharmony_ci size_t olen, nlen; 4209c84f3f3cSopenharmony_ci char *p, *nbuf; 4210c84f3f3cSopenharmony_ci 4211c84f3f3cSopenharmony_ci /* lookup letter in alias list... */ 4212c84f3f3cSopenharmony_ci alias[1] = cmd[1]; 4213c84f3f3cSopenharmony_ci ap = ktsearch(&aliases, alias, hash(alias)); 4214c84f3f3cSopenharmony_ci if (!cmd[1] || !ap || !(ap->flag & ISSET)) 4215c84f3f3cSopenharmony_ci return (-1); 4216c84f3f3cSopenharmony_ci /* check if this is a recursive call... */ 4217c84f3f3cSopenharmony_ci if ((p = (char *)macro.p)) 4218c84f3f3cSopenharmony_ci while ((p = strnul(p)) && p[1]) 4219c84f3f3cSopenharmony_ci if (*++p == cmd[1]) 4220c84f3f3cSopenharmony_ci return (-1); 4221c84f3f3cSopenharmony_ci /* insert alias into macro buffer */ 4222c84f3f3cSopenharmony_ci nlen = strlen(ap->val.s) + 1; 4223c84f3f3cSopenharmony_ci olen = !macro.p ? 2 : 4224c84f3f3cSopenharmony_ci macro.len - (macro.p - macro.buf); 4225c84f3f3cSopenharmony_ci /* 4226c84f3f3cSopenharmony_ci * at this point, it's fairly reasonable that 4227c84f3f3cSopenharmony_ci * nlen + olen + 2 doesn't overflow 4228c84f3f3cSopenharmony_ci */ 4229c84f3f3cSopenharmony_ci nbuf = alloc(nlen + 1 + olen, AEDIT); 4230c84f3f3cSopenharmony_ci memcpy(nbuf, ap->val.s, nlen); 4231c84f3f3cSopenharmony_ci nbuf[nlen++] = cmd[1]; 4232c84f3f3cSopenharmony_ci if (macro.p) { 4233c84f3f3cSopenharmony_ci memcpy(nbuf + nlen, macro.p, olen); 4234c84f3f3cSopenharmony_ci afree(macro.buf, AEDIT); 4235c84f3f3cSopenharmony_ci nlen += olen; 4236c84f3f3cSopenharmony_ci } else { 4237c84f3f3cSopenharmony_ci nbuf[nlen++] = '\0'; 4238c84f3f3cSopenharmony_ci nbuf[nlen++] = '\0'; 4239c84f3f3cSopenharmony_ci } 4240c84f3f3cSopenharmony_ci macro.p = macro.buf = (unsigned char *)nbuf; 4241c84f3f3cSopenharmony_ci macro.len = nlen; 4242c84f3f3cSopenharmony_ci } 4243c84f3f3cSopenharmony_ci break; 4244c84f3f3cSopenharmony_ci 4245c84f3f3cSopenharmony_ci case ORD('a'): 4246c84f3f3cSopenharmony_ci modified = 1; 4247c84f3f3cSopenharmony_ci hnum = hlast; 4248c84f3f3cSopenharmony_ci if (vs->linelen != 0) 4249c84f3f3cSopenharmony_ci vs->cursor++; 4250c84f3f3cSopenharmony_ci insert = INSERT; 4251c84f3f3cSopenharmony_ci break; 4252c84f3f3cSopenharmony_ci 4253c84f3f3cSopenharmony_ci case ORD('A'): 4254c84f3f3cSopenharmony_ci modified = 1; 4255c84f3f3cSopenharmony_ci hnum = hlast; 4256c84f3f3cSopenharmony_ci del_range(0, 0); 4257c84f3f3cSopenharmony_ci vs->cursor = vs->linelen; 4258c84f3f3cSopenharmony_ci insert = INSERT; 4259c84f3f3cSopenharmony_ci break; 4260c84f3f3cSopenharmony_ci 4261c84f3f3cSopenharmony_ci case ORD('S'): 4262c84f3f3cSopenharmony_ci vs->cursor = domovebeg(); 4263c84f3f3cSopenharmony_ci del_range(vs->cursor, vs->linelen); 4264c84f3f3cSopenharmony_ci modified = 1; 4265c84f3f3cSopenharmony_ci hnum = hlast; 4266c84f3f3cSopenharmony_ci insert = INSERT; 4267c84f3f3cSopenharmony_ci break; 4268c84f3f3cSopenharmony_ci 4269c84f3f3cSopenharmony_ci case ORD('Y'): 4270c84f3f3cSopenharmony_ci cmd = "y$"; 4271c84f3f3cSopenharmony_ci /* ahhhhhh... */ 4272c84f3f3cSopenharmony_ci 4273c84f3f3cSopenharmony_ci /* FALLTHROUGH */ 4274c84f3f3cSopenharmony_ci case ORD('c'): 4275c84f3f3cSopenharmony_ci case ORD('d'): 4276c84f3f3cSopenharmony_ci case ORD('y'): 4277c84f3f3cSopenharmony_ci if (*cmd == cmd[1]) { 4278c84f3f3cSopenharmony_ci c1 = *cmd == 'c' ? domovebeg() : 0; 4279c84f3f3cSopenharmony_ci c2 = vs->linelen; 4280c84f3f3cSopenharmony_ci } else if (!is_move(cmd[1])) 4281c84f3f3cSopenharmony_ci return (-1); 4282c84f3f3cSopenharmony_ci else { 4283c84f3f3cSopenharmony_ci if ((ncursor = domove(argcnt, &cmd[1], 1)) < 0) 4284c84f3f3cSopenharmony_ci return (-1); 4285c84f3f3cSopenharmony_ci if (*cmd == 'c' && ksh_eq(cmd[1], 'W', 'w') && 4286c84f3f3cSopenharmony_ci !ctype(vs->cbuf[vs->cursor], C_SPACE)) { 4287c84f3f3cSopenharmony_ci do { 4288c84f3f3cSopenharmony_ci --ncursor; 4289c84f3f3cSopenharmony_ci } while (ctype(vs->cbuf[ncursor], C_SPACE)); 4290c84f3f3cSopenharmony_ci ncursor++; 4291c84f3f3cSopenharmony_ci } 4292c84f3f3cSopenharmony_ci if (ncursor > vs->cursor) { 4293c84f3f3cSopenharmony_ci c1 = vs->cursor; 4294c84f3f3cSopenharmony_ci c2 = ncursor; 4295c84f3f3cSopenharmony_ci } else { 4296c84f3f3cSopenharmony_ci c1 = ncursor; 4297c84f3f3cSopenharmony_ci c2 = vs->cursor; 4298c84f3f3cSopenharmony_ci if (cmd[1] == '%') 4299c84f3f3cSopenharmony_ci c2++; 4300c84f3f3cSopenharmony_ci } 4301c84f3f3cSopenharmony_ci } 4302c84f3f3cSopenharmony_ci if (*cmd != 'c' && c1 != c2) 4303c84f3f3cSopenharmony_ci yank_range(c1, c2); 4304c84f3f3cSopenharmony_ci if (*cmd != 'y') { 4305c84f3f3cSopenharmony_ci del_range(c1, c2); 4306c84f3f3cSopenharmony_ci vs->cursor = c1; 4307c84f3f3cSopenharmony_ci } 4308c84f3f3cSopenharmony_ci if (*cmd == 'c') { 4309c84f3f3cSopenharmony_ci modified = 1; 4310c84f3f3cSopenharmony_ci hnum = hlast; 4311c84f3f3cSopenharmony_ci insert = INSERT; 4312c84f3f3cSopenharmony_ci } 4313c84f3f3cSopenharmony_ci break; 4314c84f3f3cSopenharmony_ci 4315c84f3f3cSopenharmony_ci case ORD('p'): 4316c84f3f3cSopenharmony_ci modified = 1; 4317c84f3f3cSopenharmony_ci hnum = hlast; 4318c84f3f3cSopenharmony_ci if (vs->linelen != 0) 4319c84f3f3cSopenharmony_ci vs->cursor++; 4320c84f3f3cSopenharmony_ci while (putbuf(ybuf, yanklen, false) == 0 && 4321c84f3f3cSopenharmony_ci --argcnt > 0) 4322c84f3f3cSopenharmony_ci ; 4323c84f3f3cSopenharmony_ci if (vs->cursor != 0) 4324c84f3f3cSopenharmony_ci vs->cursor--; 4325c84f3f3cSopenharmony_ci if (argcnt != 0) 4326c84f3f3cSopenharmony_ci return (-1); 4327c84f3f3cSopenharmony_ci break; 4328c84f3f3cSopenharmony_ci 4329c84f3f3cSopenharmony_ci case ORD('P'): 4330c84f3f3cSopenharmony_ci modified = 1; 4331c84f3f3cSopenharmony_ci hnum = hlast; 4332c84f3f3cSopenharmony_ci any = 0; 4333c84f3f3cSopenharmony_ci while (putbuf(ybuf, yanklen, false) == 0 && 4334c84f3f3cSopenharmony_ci --argcnt > 0) 4335c84f3f3cSopenharmony_ci any = 1; 4336c84f3f3cSopenharmony_ci if (any && vs->cursor != 0) 4337c84f3f3cSopenharmony_ci vs->cursor--; 4338c84f3f3cSopenharmony_ci if (argcnt != 0) 4339c84f3f3cSopenharmony_ci return (-1); 4340c84f3f3cSopenharmony_ci break; 4341c84f3f3cSopenharmony_ci 4342c84f3f3cSopenharmony_ci case ORD('C'): 4343c84f3f3cSopenharmony_ci modified = 1; 4344c84f3f3cSopenharmony_ci hnum = hlast; 4345c84f3f3cSopenharmony_ci del_range(vs->cursor, vs->linelen); 4346c84f3f3cSopenharmony_ci insert = INSERT; 4347c84f3f3cSopenharmony_ci break; 4348c84f3f3cSopenharmony_ci 4349c84f3f3cSopenharmony_ci case ORD('D'): 4350c84f3f3cSopenharmony_ci yank_range(vs->cursor, vs->linelen); 4351c84f3f3cSopenharmony_ci del_range(vs->cursor, vs->linelen); 4352c84f3f3cSopenharmony_ci if (vs->cursor != 0) 4353c84f3f3cSopenharmony_ci vs->cursor--; 4354c84f3f3cSopenharmony_ci break; 4355c84f3f3cSopenharmony_ci 4356c84f3f3cSopenharmony_ci case ORD('g'): 4357c84f3f3cSopenharmony_ci if (!argcnt) 4358c84f3f3cSopenharmony_ci argcnt = hlast; 4359c84f3f3cSopenharmony_ci /* FALLTHROUGH */ 4360c84f3f3cSopenharmony_ci case ORD('G'): 4361c84f3f3cSopenharmony_ci if (!argcnt) 4362c84f3f3cSopenharmony_ci argcnt = 1; 4363c84f3f3cSopenharmony_ci else 4364c84f3f3cSopenharmony_ci argcnt = hlast - (source->line - argcnt); 4365c84f3f3cSopenharmony_ci if (grabhist(modified, argcnt - 1) < 0) 4366c84f3f3cSopenharmony_ci return (-1); 4367c84f3f3cSopenharmony_ci else { 4368c84f3f3cSopenharmony_ci modified = 0; 4369c84f3f3cSopenharmony_ci hnum = argcnt - 1; 4370c84f3f3cSopenharmony_ci } 4371c84f3f3cSopenharmony_ci break; 4372c84f3f3cSopenharmony_ci 4373c84f3f3cSopenharmony_ci case ORD('i'): 4374c84f3f3cSopenharmony_ci modified = 1; 4375c84f3f3cSopenharmony_ci hnum = hlast; 4376c84f3f3cSopenharmony_ci insert = INSERT; 4377c84f3f3cSopenharmony_ci break; 4378c84f3f3cSopenharmony_ci 4379c84f3f3cSopenharmony_ci case ORD('I'): 4380c84f3f3cSopenharmony_ci modified = 1; 4381c84f3f3cSopenharmony_ci hnum = hlast; 4382c84f3f3cSopenharmony_ci vs->cursor = domovebeg(); 4383c84f3f3cSopenharmony_ci insert = INSERT; 4384c84f3f3cSopenharmony_ci break; 4385c84f3f3cSopenharmony_ci 4386c84f3f3cSopenharmony_ci case ORD('j'): 4387c84f3f3cSopenharmony_ci case ORD('+'): 4388c84f3f3cSopenharmony_ci case CTRL_N: 4389c84f3f3cSopenharmony_ci if (grabhist(modified, hnum + argcnt) < 0) 4390c84f3f3cSopenharmony_ci return (-1); 4391c84f3f3cSopenharmony_ci else { 4392c84f3f3cSopenharmony_ci modified = 0; 4393c84f3f3cSopenharmony_ci hnum += argcnt; 4394c84f3f3cSopenharmony_ci } 4395c84f3f3cSopenharmony_ci break; 4396c84f3f3cSopenharmony_ci 4397c84f3f3cSopenharmony_ci case ORD('k'): 4398c84f3f3cSopenharmony_ci case ORD('-'): 4399c84f3f3cSopenharmony_ci case CTRL_P: 4400c84f3f3cSopenharmony_ci if (grabhist(modified, hnum - argcnt) < 0) 4401c84f3f3cSopenharmony_ci return (-1); 4402c84f3f3cSopenharmony_ci else { 4403c84f3f3cSopenharmony_ci modified = 0; 4404c84f3f3cSopenharmony_ci hnum -= argcnt; 4405c84f3f3cSopenharmony_ci } 4406c84f3f3cSopenharmony_ci break; 4407c84f3f3cSopenharmony_ci 4408c84f3f3cSopenharmony_ci case ORD('r'): 4409c84f3f3cSopenharmony_ci if (vs->linelen == 0) 4410c84f3f3cSopenharmony_ci return (-1); 4411c84f3f3cSopenharmony_ci modified = 1; 4412c84f3f3cSopenharmony_ci hnum = hlast; 4413c84f3f3cSopenharmony_ci if (cmd[1] == 0) 4414c84f3f3cSopenharmony_ci vi_error(); 4415c84f3f3cSopenharmony_ci else { 4416c84f3f3cSopenharmony_ci int n; 4417c84f3f3cSopenharmony_ci 4418c84f3f3cSopenharmony_ci if (vs->cursor + argcnt > vs->linelen) 4419c84f3f3cSopenharmony_ci return (-1); 4420c84f3f3cSopenharmony_ci for (n = 0; n < argcnt; ++n) 4421c84f3f3cSopenharmony_ci vs->cbuf[vs->cursor + n] = cmd[1]; 4422c84f3f3cSopenharmony_ci vs->cursor += n - 1; 4423c84f3f3cSopenharmony_ci } 4424c84f3f3cSopenharmony_ci break; 4425c84f3f3cSopenharmony_ci 4426c84f3f3cSopenharmony_ci case ORD('R'): 4427c84f3f3cSopenharmony_ci modified = 1; 4428c84f3f3cSopenharmony_ci hnum = hlast; 4429c84f3f3cSopenharmony_ci insert = REPLACE; 4430c84f3f3cSopenharmony_ci break; 4431c84f3f3cSopenharmony_ci 4432c84f3f3cSopenharmony_ci case ORD('s'): 4433c84f3f3cSopenharmony_ci if (vs->linelen == 0) 4434c84f3f3cSopenharmony_ci return (-1); 4435c84f3f3cSopenharmony_ci modified = 1; 4436c84f3f3cSopenharmony_ci hnum = hlast; 4437c84f3f3cSopenharmony_ci if (vs->cursor + argcnt > vs->linelen) 4438c84f3f3cSopenharmony_ci argcnt = vs->linelen - vs->cursor; 4439c84f3f3cSopenharmony_ci del_range(vs->cursor, vs->cursor + argcnt); 4440c84f3f3cSopenharmony_ci insert = INSERT; 4441c84f3f3cSopenharmony_ci break; 4442c84f3f3cSopenharmony_ci 4443c84f3f3cSopenharmony_ci case ORD('v'): 4444c84f3f3cSopenharmony_ci if (!argcnt) { 4445c84f3f3cSopenharmony_ci if (modified) { 4446c84f3f3cSopenharmony_ci vs->cbuf[vs->linelen] = '\0'; 4447c84f3f3cSopenharmony_ci histsave(&source->line, vs->cbuf, 4448c84f3f3cSopenharmony_ci HIST_STORE, true); 4449c84f3f3cSopenharmony_ci } else 4450c84f3f3cSopenharmony_ci argcnt = source->line + 1 - 4451c84f3f3cSopenharmony_ci (hlast - hnum); 4452c84f3f3cSopenharmony_ci } 4453c84f3f3cSopenharmony_ci if (argcnt) 4454c84f3f3cSopenharmony_ci shf_snprintf(vs->cbuf, vs->cbufsize, Tf_sd, 4455c84f3f3cSopenharmony_ci ctrl_x_e, argcnt); 4456c84f3f3cSopenharmony_ci else 4457c84f3f3cSopenharmony_ci strlcpy(vs->cbuf, ctrl_x_e, vs->cbufsize); 4458c84f3f3cSopenharmony_ci vs->linelen = strlen(vs->cbuf); 4459c84f3f3cSopenharmony_ci return (2); 4460c84f3f3cSopenharmony_ci 4461c84f3f3cSopenharmony_ci case ORD('x'): 4462c84f3f3cSopenharmony_ci if (vs->linelen == 0) 4463c84f3f3cSopenharmony_ci return (-1); 4464c84f3f3cSopenharmony_ci modified = 1; 4465c84f3f3cSopenharmony_ci hnum = hlast; 4466c84f3f3cSopenharmony_ci if (vs->cursor + argcnt > vs->linelen) 4467c84f3f3cSopenharmony_ci argcnt = vs->linelen - vs->cursor; 4468c84f3f3cSopenharmony_ci yank_range(vs->cursor, vs->cursor + argcnt); 4469c84f3f3cSopenharmony_ci del_range(vs->cursor, vs->cursor + argcnt); 4470c84f3f3cSopenharmony_ci break; 4471c84f3f3cSopenharmony_ci 4472c84f3f3cSopenharmony_ci case ORD('X'): 4473c84f3f3cSopenharmony_ci if (vs->cursor > 0) { 4474c84f3f3cSopenharmony_ci modified = 1; 4475c84f3f3cSopenharmony_ci hnum = hlast; 4476c84f3f3cSopenharmony_ci if (vs->cursor < argcnt) 4477c84f3f3cSopenharmony_ci argcnt = vs->cursor; 4478c84f3f3cSopenharmony_ci yank_range(vs->cursor - argcnt, vs->cursor); 4479c84f3f3cSopenharmony_ci del_range(vs->cursor - argcnt, vs->cursor); 4480c84f3f3cSopenharmony_ci vs->cursor -= argcnt; 4481c84f3f3cSopenharmony_ci } else 4482c84f3f3cSopenharmony_ci return (-1); 4483c84f3f3cSopenharmony_ci break; 4484c84f3f3cSopenharmony_ci 4485c84f3f3cSopenharmony_ci case ORD('u'): 4486c84f3f3cSopenharmony_ci t = vs; 4487c84f3f3cSopenharmony_ci vs = undo; 4488c84f3f3cSopenharmony_ci undo = t; 4489c84f3f3cSopenharmony_ci break; 4490c84f3f3cSopenharmony_ci 4491c84f3f3cSopenharmony_ci case ORD('U'): 4492c84f3f3cSopenharmony_ci if (!modified) 4493c84f3f3cSopenharmony_ci return (-1); 4494c84f3f3cSopenharmony_ci if (grabhist(modified, ohnum) < 0) 4495c84f3f3cSopenharmony_ci return (-1); 4496c84f3f3cSopenharmony_ci modified = 0; 4497c84f3f3cSopenharmony_ci hnum = ohnum; 4498c84f3f3cSopenharmony_ci break; 4499c84f3f3cSopenharmony_ci 4500c84f3f3cSopenharmony_ci case ORD('?'): 4501c84f3f3cSopenharmony_ci if (hnum == hlast) 4502c84f3f3cSopenharmony_ci hnum = -1; 4503c84f3f3cSopenharmony_ci /* ahhh */ 4504c84f3f3cSopenharmony_ci 4505c84f3f3cSopenharmony_ci /* FALLTHROUGH */ 4506c84f3f3cSopenharmony_ci case ORD('/'): 4507c84f3f3cSopenharmony_ci c1 = 1; 4508c84f3f3cSopenharmony_ci srchlen = 0; 4509c84f3f3cSopenharmony_ci lastsearch = *cmd; 4510c84f3f3cSopenharmony_ci if (0) 4511c84f3f3cSopenharmony_ci /* FALLTHROUGH */ 4512c84f3f3cSopenharmony_ci case ORD('n'): 4513c84f3f3cSopenharmony_ci case ORD('N'): 4514c84f3f3cSopenharmony_ci c1 = 0; 4515c84f3f3cSopenharmony_ci if (lastsearch == ORD(' ')) 4516c84f3f3cSopenharmony_ci return (-1); 4517c84f3f3cSopenharmony_ci b = (lastsearch == ORD('?')); 4518c84f3f3cSopenharmony_ci if (*cmd == 'N') 4519c84f3f3cSopenharmony_ci b = !b; 4520c84f3f3cSopenharmony_ci if ((c2 = grabsearch(srchpat, modified, hnum, b)) < 0) { 4521c84f3f3cSopenharmony_ci if (c1) { 4522c84f3f3cSopenharmony_ci restore_cbuf(); 4523c84f3f3cSopenharmony_ci refresh(false); 4524c84f3f3cSopenharmony_ci } 4525c84f3f3cSopenharmony_ci return (-1); 4526c84f3f3cSopenharmony_ci } else { 4527c84f3f3cSopenharmony_ci modified = 0; 4528c84f3f3cSopenharmony_ci hnum = c2; 4529c84f3f3cSopenharmony_ci ohnum = hnum; 4530c84f3f3cSopenharmony_ci } 4531c84f3f3cSopenharmony_ci if (argcnt >= 2) { 4532c84f3f3cSopenharmony_ci /* flag from cursor-up command */ 4533c84f3f3cSopenharmony_ci vs->cursor = argcnt - 2; 4534c84f3f3cSopenharmony_ci return (0); 4535c84f3f3cSopenharmony_ci } 4536c84f3f3cSopenharmony_ci break; 4537c84f3f3cSopenharmony_ci case ORD('_'): 4538c84f3f3cSopenharmony_ci { 4539c84f3f3cSopenharmony_ci bool inspace; 4540c84f3f3cSopenharmony_ci char *p, *sp; 4541c84f3f3cSopenharmony_ci 4542c84f3f3cSopenharmony_ci if (histnum(-1) < 0) 4543c84f3f3cSopenharmony_ci return (-1); 4544c84f3f3cSopenharmony_ci p = *histpos(); 4545c84f3f3cSopenharmony_ci if (argcnt) { 4546c84f3f3cSopenharmony_ci while (ctype(*p, C_SPACE)) 4547c84f3f3cSopenharmony_ci p++; 4548c84f3f3cSopenharmony_ci while (*p && --argcnt) { 4549c84f3f3cSopenharmony_ci while (*p && !ctype(*p, C_SPACE)) 4550c84f3f3cSopenharmony_ci p++; 4551c84f3f3cSopenharmony_ci while (ctype(*p, C_SPACE)) 4552c84f3f3cSopenharmony_ci p++; 4553c84f3f3cSopenharmony_ci } 4554c84f3f3cSopenharmony_ci if (!*p) 4555c84f3f3cSopenharmony_ci return (-1); 4556c84f3f3cSopenharmony_ci sp = p; 4557c84f3f3cSopenharmony_ci } else { 4558c84f3f3cSopenharmony_ci sp = p; 4559c84f3f3cSopenharmony_ci inspace = false; 4560c84f3f3cSopenharmony_ci while (*p) { 4561c84f3f3cSopenharmony_ci if (ctype(*p, C_SPACE)) 4562c84f3f3cSopenharmony_ci inspace = true; 4563c84f3f3cSopenharmony_ci else if (inspace) { 4564c84f3f3cSopenharmony_ci inspace = false; 4565c84f3f3cSopenharmony_ci sp = p; 4566c84f3f3cSopenharmony_ci } 4567c84f3f3cSopenharmony_ci p++; 4568c84f3f3cSopenharmony_ci } 4569c84f3f3cSopenharmony_ci p = sp; 4570c84f3f3cSopenharmony_ci } 4571c84f3f3cSopenharmony_ci modified = 1; 4572c84f3f3cSopenharmony_ci hnum = hlast; 4573c84f3f3cSopenharmony_ci if (vs->cursor != vs->linelen) 4574c84f3f3cSopenharmony_ci vs->cursor++; 4575c84f3f3cSopenharmony_ci while (*p && !ctype(*p, C_SPACE)) { 4576c84f3f3cSopenharmony_ci argcnt++; 4577c84f3f3cSopenharmony_ci p++; 4578c84f3f3cSopenharmony_ci } 4579c84f3f3cSopenharmony_ci if (putbuf(T1space, 1, false) != 0 || 4580c84f3f3cSopenharmony_ci putbuf(sp, argcnt, false) != 0) { 4581c84f3f3cSopenharmony_ci if (vs->cursor != 0) 4582c84f3f3cSopenharmony_ci vs->cursor--; 4583c84f3f3cSopenharmony_ci return (-1); 4584c84f3f3cSopenharmony_ci } 4585c84f3f3cSopenharmony_ci insert = INSERT; 4586c84f3f3cSopenharmony_ci } 4587c84f3f3cSopenharmony_ci break; 4588c84f3f3cSopenharmony_ci 4589c84f3f3cSopenharmony_ci case ORD('~'): 4590c84f3f3cSopenharmony_ci { 4591c84f3f3cSopenharmony_ci char *p; 4592c84f3f3cSopenharmony_ci int i; 4593c84f3f3cSopenharmony_ci 4594c84f3f3cSopenharmony_ci if (vs->linelen == 0) 4595c84f3f3cSopenharmony_ci return (-1); 4596c84f3f3cSopenharmony_ci for (i = 0; i < argcnt; i++) { 4597c84f3f3cSopenharmony_ci p = &vs->cbuf[vs->cursor]; 4598c84f3f3cSopenharmony_ci if (ctype(*p, C_LOWER)) { 4599c84f3f3cSopenharmony_ci modified = 1; 4600c84f3f3cSopenharmony_ci hnum = hlast; 4601c84f3f3cSopenharmony_ci *p = ksh_toupper(*p); 4602c84f3f3cSopenharmony_ci } else if (ctype(*p, C_UPPER)) { 4603c84f3f3cSopenharmony_ci modified = 1; 4604c84f3f3cSopenharmony_ci hnum = hlast; 4605c84f3f3cSopenharmony_ci *p = ksh_tolower(*p); 4606c84f3f3cSopenharmony_ci } 4607c84f3f3cSopenharmony_ci if (vs->cursor < vs->linelen - 1) 4608c84f3f3cSopenharmony_ci vs->cursor++; 4609c84f3f3cSopenharmony_ci } 4610c84f3f3cSopenharmony_ci break; 4611c84f3f3cSopenharmony_ci } 4612c84f3f3cSopenharmony_ci 4613c84f3f3cSopenharmony_ci case ORD('#'): 4614c84f3f3cSopenharmony_ci { 4615c84f3f3cSopenharmony_ci int ret = x_do_comment(vs->cbuf, vs->cbufsize, 4616c84f3f3cSopenharmony_ci &vs->linelen); 4617c84f3f3cSopenharmony_ci if (ret >= 0) 4618c84f3f3cSopenharmony_ci vs->cursor = 0; 4619c84f3f3cSopenharmony_ci return (ret); 4620c84f3f3cSopenharmony_ci } 4621c84f3f3cSopenharmony_ci 4622c84f3f3cSopenharmony_ci /* AT&T ksh */ 4623c84f3f3cSopenharmony_ci case ORD('='): 4624c84f3f3cSopenharmony_ci /* Nonstandard vi/ksh */ 4625c84f3f3cSopenharmony_ci case CTRL_E: 4626c84f3f3cSopenharmony_ci print_expansions(vs, 1); 4627c84f3f3cSopenharmony_ci break; 4628c84f3f3cSopenharmony_ci 4629c84f3f3cSopenharmony_ci 4630c84f3f3cSopenharmony_ci /* Nonstandard vi/ksh */ 4631c84f3f3cSopenharmony_ci case CTRL_I: 4632c84f3f3cSopenharmony_ci if (!Flag(FVITABCOMPLETE)) 4633c84f3f3cSopenharmony_ci return (-1); 4634c84f3f3cSopenharmony_ci complete_word(1, argcnt); 4635c84f3f3cSopenharmony_ci break; 4636c84f3f3cSopenharmony_ci 4637c84f3f3cSopenharmony_ci /* some annoying AT&T kshs */ 4638c84f3f3cSopenharmony_ci case CTRL_BO: 4639c84f3f3cSopenharmony_ci if (!Flag(FVIESCCOMPLETE)) 4640c84f3f3cSopenharmony_ci return (-1); 4641c84f3f3cSopenharmony_ci /* FALLTHROUGH */ 4642c84f3f3cSopenharmony_ci /* AT&T ksh */ 4643c84f3f3cSopenharmony_ci case ORD('\\'): 4644c84f3f3cSopenharmony_ci /* Nonstandard vi/ksh */ 4645c84f3f3cSopenharmony_ci case CTRL_F: 4646c84f3f3cSopenharmony_ci complete_word(1, argcnt); 4647c84f3f3cSopenharmony_ci break; 4648c84f3f3cSopenharmony_ci 4649c84f3f3cSopenharmony_ci 4650c84f3f3cSopenharmony_ci /* AT&T ksh */ 4651c84f3f3cSopenharmony_ci case ORD('*'): 4652c84f3f3cSopenharmony_ci /* Nonstandard vi/ksh */ 4653c84f3f3cSopenharmony_ci case CTRL_X: 4654c84f3f3cSopenharmony_ci expand_word(1); 4655c84f3f3cSopenharmony_ci break; 4656c84f3f3cSopenharmony_ci 4657c84f3f3cSopenharmony_ci 4658c84f3f3cSopenharmony_ci /* mksh: cursor movement */ 4659c84f3f3cSopenharmony_ci case ORD('['): 4660c84f3f3cSopenharmony_ci case ORD('O'): 4661c84f3f3cSopenharmony_ci state = VPREFIX2; 4662c84f3f3cSopenharmony_ci if (vs->linelen != 0) 4663c84f3f3cSopenharmony_ci vs->cursor++; 4664c84f3f3cSopenharmony_ci insert = INSERT; 4665c84f3f3cSopenharmony_ci return (0); 4666c84f3f3cSopenharmony_ci } 4667c84f3f3cSopenharmony_ci if (insert == 0 && vs->cursor != 0 && vs->cursor >= vs->linelen) 4668c84f3f3cSopenharmony_ci vs->cursor--; 4669c84f3f3cSopenharmony_ci } 4670c84f3f3cSopenharmony_ci return (0); 4671c84f3f3cSopenharmony_ci} 4672c84f3f3cSopenharmony_ci 4673c84f3f3cSopenharmony_cistatic int 4674c84f3f3cSopenharmony_cidomove(int argcnt, const char *cmd, int sub) 4675c84f3f3cSopenharmony_ci{ 4676c84f3f3cSopenharmony_ci int ncursor = 0, i = 0, t; 4677c84f3f3cSopenharmony_ci unsigned int bcount; 4678c84f3f3cSopenharmony_ci 4679c84f3f3cSopenharmony_ci switch (ord(*cmd)) { 4680c84f3f3cSopenharmony_ci case ORD('b'): 4681c84f3f3cSopenharmony_ci if (!sub && vs->cursor == 0) 4682c84f3f3cSopenharmony_ci return (-1); 4683c84f3f3cSopenharmony_ci ncursor = backword(argcnt); 4684c84f3f3cSopenharmony_ci break; 4685c84f3f3cSopenharmony_ci 4686c84f3f3cSopenharmony_ci case ORD('B'): 4687c84f3f3cSopenharmony_ci if (!sub && vs->cursor == 0) 4688c84f3f3cSopenharmony_ci return (-1); 4689c84f3f3cSopenharmony_ci ncursor = Backword(argcnt); 4690c84f3f3cSopenharmony_ci break; 4691c84f3f3cSopenharmony_ci 4692c84f3f3cSopenharmony_ci case ORD('e'): 4693c84f3f3cSopenharmony_ci if (!sub && vs->cursor + 1 >= vs->linelen) 4694c84f3f3cSopenharmony_ci return (-1); 4695c84f3f3cSopenharmony_ci ncursor = endword(argcnt); 4696c84f3f3cSopenharmony_ci if (sub && ncursor < vs->linelen) 4697c84f3f3cSopenharmony_ci ncursor++; 4698c84f3f3cSopenharmony_ci break; 4699c84f3f3cSopenharmony_ci 4700c84f3f3cSopenharmony_ci case ORD('E'): 4701c84f3f3cSopenharmony_ci if (!sub && vs->cursor + 1 >= vs->linelen) 4702c84f3f3cSopenharmony_ci return (-1); 4703c84f3f3cSopenharmony_ci ncursor = Endword(argcnt); 4704c84f3f3cSopenharmony_ci if (sub && ncursor < vs->linelen) 4705c84f3f3cSopenharmony_ci ncursor++; 4706c84f3f3cSopenharmony_ci break; 4707c84f3f3cSopenharmony_ci 4708c84f3f3cSopenharmony_ci case ORD('f'): 4709c84f3f3cSopenharmony_ci case ORD('F'): 4710c84f3f3cSopenharmony_ci case ORD('t'): 4711c84f3f3cSopenharmony_ci case ORD('T'): 4712c84f3f3cSopenharmony_ci fsavecmd = *cmd; 4713c84f3f3cSopenharmony_ci fsavech = cmd[1]; 4714c84f3f3cSopenharmony_ci /* FALLTHROUGH */ 4715c84f3f3cSopenharmony_ci case ORD(','): 4716c84f3f3cSopenharmony_ci case ORD(';'): 4717c84f3f3cSopenharmony_ci if (fsavecmd == ORD(' ')) 4718c84f3f3cSopenharmony_ci return (-1); 4719c84f3f3cSopenharmony_ci i = ksh_eq(fsavecmd, 'F', 'f'); 4720c84f3f3cSopenharmony_ci t = rtt2asc(fsavecmd) > rtt2asc('a'); 4721c84f3f3cSopenharmony_ci if (*cmd == ',') 4722c84f3f3cSopenharmony_ci t = !t; 4723c84f3f3cSopenharmony_ci if ((ncursor = findch(fsavech, argcnt, tobool(t), 4724c84f3f3cSopenharmony_ci tobool(i))) < 0) 4725c84f3f3cSopenharmony_ci return (-1); 4726c84f3f3cSopenharmony_ci if (sub && t) 4727c84f3f3cSopenharmony_ci ncursor++; 4728c84f3f3cSopenharmony_ci break; 4729c84f3f3cSopenharmony_ci 4730c84f3f3cSopenharmony_ci case ORD('h'): 4731c84f3f3cSopenharmony_ci case CTRL_H: 4732c84f3f3cSopenharmony_ci if (!sub && vs->cursor == 0) 4733c84f3f3cSopenharmony_ci return (-1); 4734c84f3f3cSopenharmony_ci ncursor = vs->cursor - argcnt; 4735c84f3f3cSopenharmony_ci if (ncursor < 0) 4736c84f3f3cSopenharmony_ci ncursor = 0; 4737c84f3f3cSopenharmony_ci break; 4738c84f3f3cSopenharmony_ci 4739c84f3f3cSopenharmony_ci case ORD(' '): 4740c84f3f3cSopenharmony_ci case ORD('l'): 4741c84f3f3cSopenharmony_ci if (!sub && vs->cursor + 1 >= vs->linelen) 4742c84f3f3cSopenharmony_ci return (-1); 4743c84f3f3cSopenharmony_ci if (vs->linelen != 0) { 4744c84f3f3cSopenharmony_ci ncursor = vs->cursor + argcnt; 4745c84f3f3cSopenharmony_ci if (ncursor > vs->linelen) 4746c84f3f3cSopenharmony_ci ncursor = vs->linelen; 4747c84f3f3cSopenharmony_ci } 4748c84f3f3cSopenharmony_ci break; 4749c84f3f3cSopenharmony_ci 4750c84f3f3cSopenharmony_ci case ORD('w'): 4751c84f3f3cSopenharmony_ci if (!sub && vs->cursor + 1 >= vs->linelen) 4752c84f3f3cSopenharmony_ci return (-1); 4753c84f3f3cSopenharmony_ci ncursor = forwword(argcnt); 4754c84f3f3cSopenharmony_ci break; 4755c84f3f3cSopenharmony_ci 4756c84f3f3cSopenharmony_ci case ORD('W'): 4757c84f3f3cSopenharmony_ci if (!sub && vs->cursor + 1 >= vs->linelen) 4758c84f3f3cSopenharmony_ci return (-1); 4759c84f3f3cSopenharmony_ci ncursor = Forwword(argcnt); 4760c84f3f3cSopenharmony_ci break; 4761c84f3f3cSopenharmony_ci 4762c84f3f3cSopenharmony_ci case ORD('0'): 4763c84f3f3cSopenharmony_ci ncursor = 0; 4764c84f3f3cSopenharmony_ci break; 4765c84f3f3cSopenharmony_ci 4766c84f3f3cSopenharmony_ci case ORD('^'): 4767c84f3f3cSopenharmony_ci ncursor = domovebeg(); 4768c84f3f3cSopenharmony_ci break; 4769c84f3f3cSopenharmony_ci 4770c84f3f3cSopenharmony_ci case ORD('|'): 4771c84f3f3cSopenharmony_ci ncursor = argcnt; 4772c84f3f3cSopenharmony_ci if (ncursor > vs->linelen) 4773c84f3f3cSopenharmony_ci ncursor = vs->linelen; 4774c84f3f3cSopenharmony_ci if (ncursor) 4775c84f3f3cSopenharmony_ci ncursor--; 4776c84f3f3cSopenharmony_ci break; 4777c84f3f3cSopenharmony_ci 4778c84f3f3cSopenharmony_ci case ORD('$'): 4779c84f3f3cSopenharmony_ci if (vs->linelen != 0) 4780c84f3f3cSopenharmony_ci ncursor = vs->linelen; 4781c84f3f3cSopenharmony_ci else 4782c84f3f3cSopenharmony_ci ncursor = 0; 4783c84f3f3cSopenharmony_ci break; 4784c84f3f3cSopenharmony_ci 4785c84f3f3cSopenharmony_ci case ORD('%'): 4786c84f3f3cSopenharmony_ci ncursor = vs->cursor; 4787c84f3f3cSopenharmony_ci while (ncursor < vs->linelen && 4788c84f3f3cSopenharmony_ci (i = bracktype(vs->cbuf[ncursor])) == 0) 4789c84f3f3cSopenharmony_ci ncursor++; 4790c84f3f3cSopenharmony_ci if (ncursor == vs->linelen) 4791c84f3f3cSopenharmony_ci return (-1); 4792c84f3f3cSopenharmony_ci bcount = 1; 4793c84f3f3cSopenharmony_ci do { 4794c84f3f3cSopenharmony_ci if (i > 0) { 4795c84f3f3cSopenharmony_ci if (++ncursor >= vs->linelen) 4796c84f3f3cSopenharmony_ci return (-1); 4797c84f3f3cSopenharmony_ci } else { 4798c84f3f3cSopenharmony_ci if (--ncursor < 0) 4799c84f3f3cSopenharmony_ci return (-1); 4800c84f3f3cSopenharmony_ci } 4801c84f3f3cSopenharmony_ci t = bracktype(vs->cbuf[ncursor]); 4802c84f3f3cSopenharmony_ci if (t == i) 4803c84f3f3cSopenharmony_ci bcount++; 4804c84f3f3cSopenharmony_ci else if (t == -i) 4805c84f3f3cSopenharmony_ci bcount--; 4806c84f3f3cSopenharmony_ci } while (bcount != 0); 4807c84f3f3cSopenharmony_ci if (sub && i > 0) 4808c84f3f3cSopenharmony_ci ncursor++; 4809c84f3f3cSopenharmony_ci break; 4810c84f3f3cSopenharmony_ci 4811c84f3f3cSopenharmony_ci default: 4812c84f3f3cSopenharmony_ci return (-1); 4813c84f3f3cSopenharmony_ci } 4814c84f3f3cSopenharmony_ci return (ncursor); 4815c84f3f3cSopenharmony_ci} 4816c84f3f3cSopenharmony_ci 4817c84f3f3cSopenharmony_cistatic int 4818c84f3f3cSopenharmony_cidomovebeg(void) 4819c84f3f3cSopenharmony_ci{ 4820c84f3f3cSopenharmony_ci int ncursor = 0; 4821c84f3f3cSopenharmony_ci 4822c84f3f3cSopenharmony_ci while (ncursor < vs->linelen - 1 && 4823c84f3f3cSopenharmony_ci ctype(vs->cbuf[ncursor], C_SPACE)) 4824c84f3f3cSopenharmony_ci ncursor++; 4825c84f3f3cSopenharmony_ci return (ncursor); 4826c84f3f3cSopenharmony_ci} 4827c84f3f3cSopenharmony_ci 4828c84f3f3cSopenharmony_cistatic int 4829c84f3f3cSopenharmony_ciredo_insert(int count) 4830c84f3f3cSopenharmony_ci{ 4831c84f3f3cSopenharmony_ci while (count-- > 0) 4832c84f3f3cSopenharmony_ci if (putbuf(ibuf, inslen, tobool(insert == REPLACE)) != 0) 4833c84f3f3cSopenharmony_ci return (-1); 4834c84f3f3cSopenharmony_ci if (vs->cursor > 0) 4835c84f3f3cSopenharmony_ci vs->cursor--; 4836c84f3f3cSopenharmony_ci insert = 0; 4837c84f3f3cSopenharmony_ci return (0); 4838c84f3f3cSopenharmony_ci} 4839c84f3f3cSopenharmony_ci 4840c84f3f3cSopenharmony_cistatic void 4841c84f3f3cSopenharmony_ciyank_range(int a, int b) 4842c84f3f3cSopenharmony_ci{ 4843c84f3f3cSopenharmony_ci yanklen = b - a; 4844c84f3f3cSopenharmony_ci if (yanklen != 0) 4845c84f3f3cSopenharmony_ci memmove(ybuf, &vs->cbuf[a], yanklen); 4846c84f3f3cSopenharmony_ci} 4847c84f3f3cSopenharmony_ci 4848c84f3f3cSopenharmony_cistatic int 4849c84f3f3cSopenharmony_cibracktype(int ch) 4850c84f3f3cSopenharmony_ci{ 4851c84f3f3cSopenharmony_ci switch (ord(ch)) { 4852c84f3f3cSopenharmony_ci 4853c84f3f3cSopenharmony_ci case ORD('('): 4854c84f3f3cSopenharmony_ci return (1); 4855c84f3f3cSopenharmony_ci 4856c84f3f3cSopenharmony_ci case ORD('['): 4857c84f3f3cSopenharmony_ci return (2); 4858c84f3f3cSopenharmony_ci 4859c84f3f3cSopenharmony_ci case ORD('{'): 4860c84f3f3cSopenharmony_ci return (3); 4861c84f3f3cSopenharmony_ci 4862c84f3f3cSopenharmony_ci case ORD(')'): 4863c84f3f3cSopenharmony_ci return (-1); 4864c84f3f3cSopenharmony_ci 4865c84f3f3cSopenharmony_ci case ORD(']'): 4866c84f3f3cSopenharmony_ci return (-2); 4867c84f3f3cSopenharmony_ci 4868c84f3f3cSopenharmony_ci case ORD('}'): 4869c84f3f3cSopenharmony_ci return (-3); 4870c84f3f3cSopenharmony_ci 4871c84f3f3cSopenharmony_ci default: 4872c84f3f3cSopenharmony_ci return (0); 4873c84f3f3cSopenharmony_ci } 4874c84f3f3cSopenharmony_ci} 4875c84f3f3cSopenharmony_ci 4876c84f3f3cSopenharmony_ci/* 4877c84f3f3cSopenharmony_ci * Non user interface editor routines below here 4878c84f3f3cSopenharmony_ci */ 4879c84f3f3cSopenharmony_ci 4880c84f3f3cSopenharmony_cistatic void 4881c84f3f3cSopenharmony_cisave_cbuf(void) 4882c84f3f3cSopenharmony_ci{ 4883c84f3f3cSopenharmony_ci memmove(holdbufp, vs->cbuf, vs->linelen); 4884c84f3f3cSopenharmony_ci holdlen = vs->linelen; 4885c84f3f3cSopenharmony_ci holdbufp[holdlen] = '\0'; 4886c84f3f3cSopenharmony_ci} 4887c84f3f3cSopenharmony_ci 4888c84f3f3cSopenharmony_cistatic void 4889c84f3f3cSopenharmony_cirestore_cbuf(void) 4890c84f3f3cSopenharmony_ci{ 4891c84f3f3cSopenharmony_ci vs->cursor = 0; 4892c84f3f3cSopenharmony_ci vs->linelen = holdlen; 4893c84f3f3cSopenharmony_ci memmove(vs->cbuf, holdbufp, holdlen); 4894c84f3f3cSopenharmony_ci} 4895c84f3f3cSopenharmony_ci 4896c84f3f3cSopenharmony_ci/* return a new edstate */ 4897c84f3f3cSopenharmony_cistatic struct edstate * 4898c84f3f3cSopenharmony_cisave_edstate(struct edstate *old) 4899c84f3f3cSopenharmony_ci{ 4900c84f3f3cSopenharmony_ci struct edstate *news; 4901c84f3f3cSopenharmony_ci 4902c84f3f3cSopenharmony_ci news = alloc(sizeof(struct edstate), AEDIT); 4903c84f3f3cSopenharmony_ci news->cbuf = alloc(old->cbufsize, AEDIT); 4904c84f3f3cSopenharmony_ci memcpy(news->cbuf, old->cbuf, old->linelen); 4905c84f3f3cSopenharmony_ci news->cbufsize = old->cbufsize; 4906c84f3f3cSopenharmony_ci news->linelen = old->linelen; 4907c84f3f3cSopenharmony_ci news->cursor = old->cursor; 4908c84f3f3cSopenharmony_ci news->winleft = old->winleft; 4909c84f3f3cSopenharmony_ci return (news); 4910c84f3f3cSopenharmony_ci} 4911c84f3f3cSopenharmony_ci 4912c84f3f3cSopenharmony_cistatic void 4913c84f3f3cSopenharmony_cirestore_edstate(struct edstate *news, struct edstate *old) 4914c84f3f3cSopenharmony_ci{ 4915c84f3f3cSopenharmony_ci memcpy(news->cbuf, old->cbuf, old->linelen); 4916c84f3f3cSopenharmony_ci news->linelen = old->linelen; 4917c84f3f3cSopenharmony_ci news->cursor = old->cursor; 4918c84f3f3cSopenharmony_ci news->winleft = old->winleft; 4919c84f3f3cSopenharmony_ci free_edstate(old); 4920c84f3f3cSopenharmony_ci} 4921c84f3f3cSopenharmony_ci 4922c84f3f3cSopenharmony_cistatic void 4923c84f3f3cSopenharmony_cifree_edstate(struct edstate *old) 4924c84f3f3cSopenharmony_ci{ 4925c84f3f3cSopenharmony_ci afree(old->cbuf, AEDIT); 4926c84f3f3cSopenharmony_ci afree(old, AEDIT); 4927c84f3f3cSopenharmony_ci} 4928c84f3f3cSopenharmony_ci 4929c84f3f3cSopenharmony_ci/* 4930c84f3f3cSopenharmony_ci * this is used for calling x_escape() in complete_word() 4931c84f3f3cSopenharmony_ci */ 4932c84f3f3cSopenharmony_cistatic int 4933c84f3f3cSopenharmony_cix_vi_putbuf(const char *s, size_t len) 4934c84f3f3cSopenharmony_ci{ 4935c84f3f3cSopenharmony_ci return (putbuf(s, len, false)); 4936c84f3f3cSopenharmony_ci} 4937c84f3f3cSopenharmony_ci 4938c84f3f3cSopenharmony_cistatic int 4939c84f3f3cSopenharmony_ciputbuf(const char *buf, ssize_t len, bool repl) 4940c84f3f3cSopenharmony_ci{ 4941c84f3f3cSopenharmony_ci if (len == 0) 4942c84f3f3cSopenharmony_ci return (0); 4943c84f3f3cSopenharmony_ci if (repl) { 4944c84f3f3cSopenharmony_ci if (vs->cursor + len >= vs->cbufsize) 4945c84f3f3cSopenharmony_ci return (-1); 4946c84f3f3cSopenharmony_ci if (vs->cursor + len > vs->linelen) 4947c84f3f3cSopenharmony_ci vs->linelen = vs->cursor + len; 4948c84f3f3cSopenharmony_ci } else { 4949c84f3f3cSopenharmony_ci if (vs->linelen + len >= vs->cbufsize) 4950c84f3f3cSopenharmony_ci return (-1); 4951c84f3f3cSopenharmony_ci memmove(&vs->cbuf[vs->cursor + len], &vs->cbuf[vs->cursor], 4952c84f3f3cSopenharmony_ci vs->linelen - vs->cursor); 4953c84f3f3cSopenharmony_ci vs->linelen += len; 4954c84f3f3cSopenharmony_ci } 4955c84f3f3cSopenharmony_ci memmove(&vs->cbuf[vs->cursor], buf, len); 4956c84f3f3cSopenharmony_ci vs->cursor += len; 4957c84f3f3cSopenharmony_ci return (0); 4958c84f3f3cSopenharmony_ci} 4959c84f3f3cSopenharmony_ci 4960c84f3f3cSopenharmony_cistatic void 4961c84f3f3cSopenharmony_cidel_range(int a, int b) 4962c84f3f3cSopenharmony_ci{ 4963c84f3f3cSopenharmony_ci if (vs->linelen != b) 4964c84f3f3cSopenharmony_ci memmove(&vs->cbuf[a], &vs->cbuf[b], vs->linelen - b); 4965c84f3f3cSopenharmony_ci vs->linelen -= b - a; 4966c84f3f3cSopenharmony_ci} 4967c84f3f3cSopenharmony_ci 4968c84f3f3cSopenharmony_cistatic int 4969c84f3f3cSopenharmony_cifindch(int ch, int cnt, bool forw, bool incl) 4970c84f3f3cSopenharmony_ci{ 4971c84f3f3cSopenharmony_ci int ncursor; 4972c84f3f3cSopenharmony_ci 4973c84f3f3cSopenharmony_ci if (vs->linelen == 0) 4974c84f3f3cSopenharmony_ci return (-1); 4975c84f3f3cSopenharmony_ci ncursor = vs->cursor; 4976c84f3f3cSopenharmony_ci while (cnt--) { 4977c84f3f3cSopenharmony_ci do { 4978c84f3f3cSopenharmony_ci if (forw) { 4979c84f3f3cSopenharmony_ci if (++ncursor == vs->linelen) 4980c84f3f3cSopenharmony_ci return (-1); 4981c84f3f3cSopenharmony_ci } else { 4982c84f3f3cSopenharmony_ci if (--ncursor < 0) 4983c84f3f3cSopenharmony_ci return (-1); 4984c84f3f3cSopenharmony_ci } 4985c84f3f3cSopenharmony_ci } while (vs->cbuf[ncursor] != ch); 4986c84f3f3cSopenharmony_ci } 4987c84f3f3cSopenharmony_ci if (!incl) { 4988c84f3f3cSopenharmony_ci if (forw) 4989c84f3f3cSopenharmony_ci ncursor--; 4990c84f3f3cSopenharmony_ci else 4991c84f3f3cSopenharmony_ci ncursor++; 4992c84f3f3cSopenharmony_ci } 4993c84f3f3cSopenharmony_ci return (ncursor); 4994c84f3f3cSopenharmony_ci} 4995c84f3f3cSopenharmony_ci 4996c84f3f3cSopenharmony_cistatic int 4997c84f3f3cSopenharmony_ciforwword(int argcnt) 4998c84f3f3cSopenharmony_ci{ 4999c84f3f3cSopenharmony_ci int ncursor; 5000c84f3f3cSopenharmony_ci 5001c84f3f3cSopenharmony_ci ncursor = vs->cursor; 5002c84f3f3cSopenharmony_ci while (ncursor < vs->linelen && argcnt--) { 5003c84f3f3cSopenharmony_ci if (ctype(vs->cbuf[ncursor], C_ALNUX)) 5004c84f3f3cSopenharmony_ci while (ncursor < vs->linelen && 5005c84f3f3cSopenharmony_ci ctype(vs->cbuf[ncursor], C_ALNUX)) 5006c84f3f3cSopenharmony_ci ncursor++; 5007c84f3f3cSopenharmony_ci else if (!ctype(vs->cbuf[ncursor], C_SPACE)) 5008c84f3f3cSopenharmony_ci while (ncursor < vs->linelen && 5009c84f3f3cSopenharmony_ci !ctype(vs->cbuf[ncursor], C_ALNUX | C_SPACE)) 5010c84f3f3cSopenharmony_ci ncursor++; 5011c84f3f3cSopenharmony_ci while (ncursor < vs->linelen && 5012c84f3f3cSopenharmony_ci ctype(vs->cbuf[ncursor], C_SPACE)) 5013c84f3f3cSopenharmony_ci ncursor++; 5014c84f3f3cSopenharmony_ci } 5015c84f3f3cSopenharmony_ci return (ncursor); 5016c84f3f3cSopenharmony_ci} 5017c84f3f3cSopenharmony_ci 5018c84f3f3cSopenharmony_cistatic int 5019c84f3f3cSopenharmony_cibackword(int argcnt) 5020c84f3f3cSopenharmony_ci{ 5021c84f3f3cSopenharmony_ci int ncursor; 5022c84f3f3cSopenharmony_ci 5023c84f3f3cSopenharmony_ci ncursor = vs->cursor; 5024c84f3f3cSopenharmony_ci while (ncursor > 0 && argcnt--) { 5025c84f3f3cSopenharmony_ci while (--ncursor > 0 && ctype(vs->cbuf[ncursor], C_SPACE)) 5026c84f3f3cSopenharmony_ci ; 5027c84f3f3cSopenharmony_ci if (ncursor > 0) { 5028c84f3f3cSopenharmony_ci if (ctype(vs->cbuf[ncursor], C_ALNUX)) 5029c84f3f3cSopenharmony_ci while (--ncursor >= 0 && 5030c84f3f3cSopenharmony_ci ctype(vs->cbuf[ncursor], C_ALNUX)) 5031c84f3f3cSopenharmony_ci ; 5032c84f3f3cSopenharmony_ci else 5033c84f3f3cSopenharmony_ci while (--ncursor >= 0 && 5034c84f3f3cSopenharmony_ci !ctype(vs->cbuf[ncursor], C_ALNUX | C_SPACE)) 5035c84f3f3cSopenharmony_ci ; 5036c84f3f3cSopenharmony_ci ncursor++; 5037c84f3f3cSopenharmony_ci } 5038c84f3f3cSopenharmony_ci } 5039c84f3f3cSopenharmony_ci return (ncursor); 5040c84f3f3cSopenharmony_ci} 5041c84f3f3cSopenharmony_ci 5042c84f3f3cSopenharmony_cistatic int 5043c84f3f3cSopenharmony_ciendword(int argcnt) 5044c84f3f3cSopenharmony_ci{ 5045c84f3f3cSopenharmony_ci int ncursor; 5046c84f3f3cSopenharmony_ci 5047c84f3f3cSopenharmony_ci ncursor = vs->cursor; 5048c84f3f3cSopenharmony_ci while (ncursor < vs->linelen && argcnt--) { 5049c84f3f3cSopenharmony_ci while (++ncursor < vs->linelen - 1 && 5050c84f3f3cSopenharmony_ci ctype(vs->cbuf[ncursor], C_SPACE)) 5051c84f3f3cSopenharmony_ci ; 5052c84f3f3cSopenharmony_ci if (ncursor < vs->linelen - 1) { 5053c84f3f3cSopenharmony_ci if (ctype(vs->cbuf[ncursor], C_ALNUX)) 5054c84f3f3cSopenharmony_ci while (++ncursor < vs->linelen && 5055c84f3f3cSopenharmony_ci ctype(vs->cbuf[ncursor], C_ALNUX)) 5056c84f3f3cSopenharmony_ci ; 5057c84f3f3cSopenharmony_ci else 5058c84f3f3cSopenharmony_ci while (++ncursor < vs->linelen && 5059c84f3f3cSopenharmony_ci !ctype(vs->cbuf[ncursor], C_ALNUX | C_SPACE)) 5060c84f3f3cSopenharmony_ci ; 5061c84f3f3cSopenharmony_ci ncursor--; 5062c84f3f3cSopenharmony_ci } 5063c84f3f3cSopenharmony_ci } 5064c84f3f3cSopenharmony_ci return (ncursor); 5065c84f3f3cSopenharmony_ci} 5066c84f3f3cSopenharmony_ci 5067c84f3f3cSopenharmony_cistatic int 5068c84f3f3cSopenharmony_ciForwword(int argcnt) 5069c84f3f3cSopenharmony_ci{ 5070c84f3f3cSopenharmony_ci int ncursor; 5071c84f3f3cSopenharmony_ci 5072c84f3f3cSopenharmony_ci ncursor = vs->cursor; 5073c84f3f3cSopenharmony_ci while (ncursor < vs->linelen && argcnt--) { 5074c84f3f3cSopenharmony_ci while (ncursor < vs->linelen && 5075c84f3f3cSopenharmony_ci !ctype(vs->cbuf[ncursor], C_SPACE)) 5076c84f3f3cSopenharmony_ci ncursor++; 5077c84f3f3cSopenharmony_ci while (ncursor < vs->linelen && 5078c84f3f3cSopenharmony_ci ctype(vs->cbuf[ncursor], C_SPACE)) 5079c84f3f3cSopenharmony_ci ncursor++; 5080c84f3f3cSopenharmony_ci } 5081c84f3f3cSopenharmony_ci return (ncursor); 5082c84f3f3cSopenharmony_ci} 5083c84f3f3cSopenharmony_ci 5084c84f3f3cSopenharmony_cistatic int 5085c84f3f3cSopenharmony_ciBackword(int argcnt) 5086c84f3f3cSopenharmony_ci{ 5087c84f3f3cSopenharmony_ci int ncursor; 5088c84f3f3cSopenharmony_ci 5089c84f3f3cSopenharmony_ci ncursor = vs->cursor; 5090c84f3f3cSopenharmony_ci while (ncursor > 0 && argcnt--) { 5091c84f3f3cSopenharmony_ci while (--ncursor >= 0 && ctype(vs->cbuf[ncursor], C_SPACE)) 5092c84f3f3cSopenharmony_ci ; 5093c84f3f3cSopenharmony_ci while (ncursor >= 0 && !ctype(vs->cbuf[ncursor], C_SPACE)) 5094c84f3f3cSopenharmony_ci ncursor--; 5095c84f3f3cSopenharmony_ci ncursor++; 5096c84f3f3cSopenharmony_ci } 5097c84f3f3cSopenharmony_ci return (ncursor); 5098c84f3f3cSopenharmony_ci} 5099c84f3f3cSopenharmony_ci 5100c84f3f3cSopenharmony_cistatic int 5101c84f3f3cSopenharmony_ciEndword(int argcnt) 5102c84f3f3cSopenharmony_ci{ 5103c84f3f3cSopenharmony_ci int ncursor; 5104c84f3f3cSopenharmony_ci 5105c84f3f3cSopenharmony_ci ncursor = vs->cursor; 5106c84f3f3cSopenharmony_ci while (ncursor < vs->linelen - 1 && argcnt--) { 5107c84f3f3cSopenharmony_ci while (++ncursor < vs->linelen - 1 && 5108c84f3f3cSopenharmony_ci ctype(vs->cbuf[ncursor], C_SPACE)) 5109c84f3f3cSopenharmony_ci ; 5110c84f3f3cSopenharmony_ci if (ncursor < vs->linelen - 1) { 5111c84f3f3cSopenharmony_ci while (++ncursor < vs->linelen && 5112c84f3f3cSopenharmony_ci !ctype(vs->cbuf[ncursor], C_SPACE)) 5113c84f3f3cSopenharmony_ci ; 5114c84f3f3cSopenharmony_ci ncursor--; 5115c84f3f3cSopenharmony_ci } 5116c84f3f3cSopenharmony_ci } 5117c84f3f3cSopenharmony_ci return (ncursor); 5118c84f3f3cSopenharmony_ci} 5119c84f3f3cSopenharmony_ci 5120c84f3f3cSopenharmony_cistatic int 5121c84f3f3cSopenharmony_cigrabhist(int save, int n) 5122c84f3f3cSopenharmony_ci{ 5123c84f3f3cSopenharmony_ci char *hptr; 5124c84f3f3cSopenharmony_ci 5125c84f3f3cSopenharmony_ci if (n < 0 || n > hlast) 5126c84f3f3cSopenharmony_ci return (-1); 5127c84f3f3cSopenharmony_ci if (n == hlast) { 5128c84f3f3cSopenharmony_ci restore_cbuf(); 5129c84f3f3cSopenharmony_ci ohnum = n; 5130c84f3f3cSopenharmony_ci return (0); 5131c84f3f3cSopenharmony_ci } 5132c84f3f3cSopenharmony_ci (void)histnum(n); 5133c84f3f3cSopenharmony_ci if ((hptr = *histpos()) == NULL) { 5134c84f3f3cSopenharmony_ci internal_warningf("grabhist: bad history array"); 5135c84f3f3cSopenharmony_ci return (-1); 5136c84f3f3cSopenharmony_ci } 5137c84f3f3cSopenharmony_ci if (save) 5138c84f3f3cSopenharmony_ci save_cbuf(); 5139c84f3f3cSopenharmony_ci if ((vs->linelen = strlen(hptr)) >= vs->cbufsize) 5140c84f3f3cSopenharmony_ci vs->linelen = vs->cbufsize - 1; 5141c84f3f3cSopenharmony_ci memmove(vs->cbuf, hptr, vs->linelen); 5142c84f3f3cSopenharmony_ci vs->cursor = 0; 5143c84f3f3cSopenharmony_ci ohnum = n; 5144c84f3f3cSopenharmony_ci return (0); 5145c84f3f3cSopenharmony_ci} 5146c84f3f3cSopenharmony_ci 5147c84f3f3cSopenharmony_cistatic int 5148c84f3f3cSopenharmony_cigrabsearch(const char *pat, int save, int start, bool fwd) 5149c84f3f3cSopenharmony_ci{ 5150c84f3f3cSopenharmony_ci char *hptr; 5151c84f3f3cSopenharmony_ci int hist; 5152c84f3f3cSopenharmony_ci bool anchored; 5153c84f3f3cSopenharmony_ci 5154c84f3f3cSopenharmony_ci if ((start == 0 && !fwd) || (start >= hlast - 1 && fwd)) 5155c84f3f3cSopenharmony_ci return (-1); 5156c84f3f3cSopenharmony_ci if (fwd) 5157c84f3f3cSopenharmony_ci start++; 5158c84f3f3cSopenharmony_ci else 5159c84f3f3cSopenharmony_ci start--; 5160c84f3f3cSopenharmony_ci anchored = *pat == '^' ? (++pat, true) : false; 5161c84f3f3cSopenharmony_ci if ((hist = findhist(start, pat, fwd, anchored)) < 0) { 5162c84f3f3cSopenharmony_ci /* (start != 0 && fwd && match(holdbufp, pat) >= 0) */ 5163c84f3f3cSopenharmony_ci if (start != 0 && fwd && strcmp(holdbufp, pat) >= 0) { 5164c84f3f3cSopenharmony_ci restore_cbuf(); 5165c84f3f3cSopenharmony_ci return (0); 5166c84f3f3cSopenharmony_ci } else 5167c84f3f3cSopenharmony_ci return (-1); 5168c84f3f3cSopenharmony_ci } 5169c84f3f3cSopenharmony_ci if (save) 5170c84f3f3cSopenharmony_ci save_cbuf(); 5171c84f3f3cSopenharmony_ci histnum(hist); 5172c84f3f3cSopenharmony_ci hptr = *histpos(); 5173c84f3f3cSopenharmony_ci if ((vs->linelen = strlen(hptr)) >= vs->cbufsize) 5174c84f3f3cSopenharmony_ci vs->linelen = vs->cbufsize - 1; 5175c84f3f3cSopenharmony_ci memmove(vs->cbuf, hptr, vs->linelen); 5176c84f3f3cSopenharmony_ci vs->cursor = 0; 5177c84f3f3cSopenharmony_ci return (hist); 5178c84f3f3cSopenharmony_ci} 5179c84f3f3cSopenharmony_ci 5180c84f3f3cSopenharmony_cistatic void 5181c84f3f3cSopenharmony_ciredraw_line(bool newl) 5182c84f3f3cSopenharmony_ci{ 5183c84f3f3cSopenharmony_ci if (wbuf_len) 5184c84f3f3cSopenharmony_ci memset(wbuf[win], ' ', wbuf_len); 5185c84f3f3cSopenharmony_ci if (newl) { 5186c84f3f3cSopenharmony_ci x_putc('\r'); 5187c84f3f3cSopenharmony_ci x_putc('\n'); 5188c84f3f3cSopenharmony_ci } 5189c84f3f3cSopenharmony_ci x_pprompt(); 5190c84f3f3cSopenharmony_ci morec = ' '; 5191c84f3f3cSopenharmony_ci} 5192c84f3f3cSopenharmony_ci 5193c84f3f3cSopenharmony_cistatic void 5194c84f3f3cSopenharmony_cirefresh(bool leftside) 5195c84f3f3cSopenharmony_ci{ 5196c84f3f3cSopenharmony_ci if (outofwin()) 5197c84f3f3cSopenharmony_ci rewindow(); 5198c84f3f3cSopenharmony_ci display(wbuf[1 - win], wbuf[win], leftside); 5199c84f3f3cSopenharmony_ci win = 1 - win; 5200c84f3f3cSopenharmony_ci} 5201c84f3f3cSopenharmony_ci 5202c84f3f3cSopenharmony_cistatic int 5203c84f3f3cSopenharmony_cioutofwin(void) 5204c84f3f3cSopenharmony_ci{ 5205c84f3f3cSopenharmony_ci int cur, col; 5206c84f3f3cSopenharmony_ci 5207c84f3f3cSopenharmony_ci if (vs->cursor < vs->winleft) 5208c84f3f3cSopenharmony_ci return (1); 5209c84f3f3cSopenharmony_ci col = 0; 5210c84f3f3cSopenharmony_ci cur = vs->winleft; 5211c84f3f3cSopenharmony_ci while (cur < vs->cursor) 5212c84f3f3cSopenharmony_ci col = newcol((unsigned char)vs->cbuf[cur++], col); 5213c84f3f3cSopenharmony_ci if (col >= winwidth) 5214c84f3f3cSopenharmony_ci return (1); 5215c84f3f3cSopenharmony_ci return (0); 5216c84f3f3cSopenharmony_ci} 5217c84f3f3cSopenharmony_ci 5218c84f3f3cSopenharmony_cistatic void 5219c84f3f3cSopenharmony_cirewindow(void) 5220c84f3f3cSopenharmony_ci{ 5221c84f3f3cSopenharmony_ci int tcur, tcol; 5222c84f3f3cSopenharmony_ci int holdcur1, holdcol1; 5223c84f3f3cSopenharmony_ci int holdcur2, holdcol2; 5224c84f3f3cSopenharmony_ci 5225c84f3f3cSopenharmony_ci holdcur1 = holdcur2 = tcur = 0; 5226c84f3f3cSopenharmony_ci holdcol1 = holdcol2 = tcol = 0; 5227c84f3f3cSopenharmony_ci while (tcur < vs->cursor) { 5228c84f3f3cSopenharmony_ci if (tcol - holdcol2 > winwidth / 2) { 5229c84f3f3cSopenharmony_ci holdcur1 = holdcur2; 5230c84f3f3cSopenharmony_ci holdcol1 = holdcol2; 5231c84f3f3cSopenharmony_ci holdcur2 = tcur; 5232c84f3f3cSopenharmony_ci holdcol2 = tcol; 5233c84f3f3cSopenharmony_ci } 5234c84f3f3cSopenharmony_ci tcol = newcol((unsigned char)vs->cbuf[tcur++], tcol); 5235c84f3f3cSopenharmony_ci } 5236c84f3f3cSopenharmony_ci while (tcol - holdcol1 > winwidth / 2) 5237c84f3f3cSopenharmony_ci holdcol1 = newcol((unsigned char)vs->cbuf[holdcur1++], 5238c84f3f3cSopenharmony_ci holdcol1); 5239c84f3f3cSopenharmony_ci vs->winleft = holdcur1; 5240c84f3f3cSopenharmony_ci} 5241c84f3f3cSopenharmony_ci 5242c84f3f3cSopenharmony_cistatic int 5243c84f3f3cSopenharmony_cinewcol(unsigned char ch, int col) 5244c84f3f3cSopenharmony_ci{ 5245c84f3f3cSopenharmony_ci if (ch == '\t') 5246c84f3f3cSopenharmony_ci return ((col | 7) + 1); 5247c84f3f3cSopenharmony_ci return (col + char_len(ch)); 5248c84f3f3cSopenharmony_ci} 5249c84f3f3cSopenharmony_ci 5250c84f3f3cSopenharmony_cistatic void 5251c84f3f3cSopenharmony_cidisplay(char *wb1, char *wb2, bool leftside) 5252c84f3f3cSopenharmony_ci{ 5253c84f3f3cSopenharmony_ci unsigned char ch; 5254c84f3f3cSopenharmony_ci char *twb1, *twb2, mc; 5255c84f3f3cSopenharmony_ci int cur, col, cnt; 5256c84f3f3cSopenharmony_ci int ncol = 0; 5257c84f3f3cSopenharmony_ci int moreright; 5258c84f3f3cSopenharmony_ci 5259c84f3f3cSopenharmony_ci col = 0; 5260c84f3f3cSopenharmony_ci cur = vs->winleft; 5261c84f3f3cSopenharmony_ci moreright = 0; 5262c84f3f3cSopenharmony_ci twb1 = wb1; 5263c84f3f3cSopenharmony_ci while (col < winwidth && cur < vs->linelen) { 5264c84f3f3cSopenharmony_ci if (cur == vs->cursor && leftside) 5265c84f3f3cSopenharmony_ci ncol = col + pwidth; 5266c84f3f3cSopenharmony_ci if ((ch = vs->cbuf[cur]) == '\t') 5267c84f3f3cSopenharmony_ci do { 5268c84f3f3cSopenharmony_ci *twb1++ = ' '; 5269c84f3f3cSopenharmony_ci } while (++col < winwidth && (col & 7) != 0); 5270c84f3f3cSopenharmony_ci else if (col < winwidth) { 5271c84f3f3cSopenharmony_ci if (ksh_isctrl(ch)) { 5272c84f3f3cSopenharmony_ci *twb1++ = '^'; 5273c84f3f3cSopenharmony_ci if (++col < winwidth) { 5274c84f3f3cSopenharmony_ci *twb1++ = ksh_unctrl(ch); 5275c84f3f3cSopenharmony_ci col++; 5276c84f3f3cSopenharmony_ci } 5277c84f3f3cSopenharmony_ci } else { 5278c84f3f3cSopenharmony_ci *twb1++ = ch; 5279c84f3f3cSopenharmony_ci col++; 5280c84f3f3cSopenharmony_ci } 5281c84f3f3cSopenharmony_ci } 5282c84f3f3cSopenharmony_ci if (cur == vs->cursor && !leftside) 5283c84f3f3cSopenharmony_ci ncol = col + pwidth - 1; 5284c84f3f3cSopenharmony_ci cur++; 5285c84f3f3cSopenharmony_ci } 5286c84f3f3cSopenharmony_ci if (cur == vs->cursor) 5287c84f3f3cSopenharmony_ci ncol = col + pwidth; 5288c84f3f3cSopenharmony_ci if (col < winwidth) { 5289c84f3f3cSopenharmony_ci while (col < winwidth) { 5290c84f3f3cSopenharmony_ci *twb1++ = ' '; 5291c84f3f3cSopenharmony_ci col++; 5292c84f3f3cSopenharmony_ci } 5293c84f3f3cSopenharmony_ci } else 5294c84f3f3cSopenharmony_ci moreright++; 5295c84f3f3cSopenharmony_ci *twb1 = ' '; 5296c84f3f3cSopenharmony_ci 5297c84f3f3cSopenharmony_ci col = pwidth; 5298c84f3f3cSopenharmony_ci cnt = winwidth; 5299c84f3f3cSopenharmony_ci twb1 = wb1; 5300c84f3f3cSopenharmony_ci twb2 = wb2; 5301c84f3f3cSopenharmony_ci while (cnt--) { 5302c84f3f3cSopenharmony_ci if (*twb1 != *twb2) { 5303c84f3f3cSopenharmony_ci if (x_col != col) 5304c84f3f3cSopenharmony_ci ed_mov_opt(col, wb1); 5305c84f3f3cSopenharmony_ci x_putc(*twb1); 5306c84f3f3cSopenharmony_ci x_col++; 5307c84f3f3cSopenharmony_ci } 5308c84f3f3cSopenharmony_ci twb1++; 5309c84f3f3cSopenharmony_ci twb2++; 5310c84f3f3cSopenharmony_ci col++; 5311c84f3f3cSopenharmony_ci } 5312c84f3f3cSopenharmony_ci if (vs->winleft > 0 && moreright) 5313c84f3f3cSopenharmony_ci /* 5314c84f3f3cSopenharmony_ci * POSIX says to use * for this but that is a globbing 5315c84f3f3cSopenharmony_ci * character and may confuse people; + is more innocuous 5316c84f3f3cSopenharmony_ci */ 5317c84f3f3cSopenharmony_ci mc = '+'; 5318c84f3f3cSopenharmony_ci else if (vs->winleft > 0) 5319c84f3f3cSopenharmony_ci mc = '<'; 5320c84f3f3cSopenharmony_ci else if (moreright) 5321c84f3f3cSopenharmony_ci mc = '>'; 5322c84f3f3cSopenharmony_ci else 5323c84f3f3cSopenharmony_ci mc = ' '; 5324c84f3f3cSopenharmony_ci if (mc != morec) { 5325c84f3f3cSopenharmony_ci ed_mov_opt(pwidth + winwidth + 1, wb1); 5326c84f3f3cSopenharmony_ci x_putc(mc); 5327c84f3f3cSopenharmony_ci x_col++; 5328c84f3f3cSopenharmony_ci morec = mc; 5329c84f3f3cSopenharmony_ci } 5330c84f3f3cSopenharmony_ci if (x_col != ncol) 5331c84f3f3cSopenharmony_ci ed_mov_opt(ncol, wb1); 5332c84f3f3cSopenharmony_ci} 5333c84f3f3cSopenharmony_ci 5334c84f3f3cSopenharmony_cistatic void 5335c84f3f3cSopenharmony_cied_mov_opt(int col, char *wb) 5336c84f3f3cSopenharmony_ci{ 5337c84f3f3cSopenharmony_ci if (col < x_col) { 5338c84f3f3cSopenharmony_ci if (col + 1 < x_col - col) { 5339c84f3f3cSopenharmony_ci x_putc('\r'); 5340c84f3f3cSopenharmony_ci x_pprompt(); 5341c84f3f3cSopenharmony_ci while (x_col++ < col) 5342c84f3f3cSopenharmony_ci x_putcf(*wb++); 5343c84f3f3cSopenharmony_ci } else { 5344c84f3f3cSopenharmony_ci while (x_col-- > col) 5345c84f3f3cSopenharmony_ci x_putc('\b'); 5346c84f3f3cSopenharmony_ci } 5347c84f3f3cSopenharmony_ci } else { 5348c84f3f3cSopenharmony_ci wb = &wb[x_col - pwidth]; 5349c84f3f3cSopenharmony_ci while (x_col++ < col) 5350c84f3f3cSopenharmony_ci x_putcf(*wb++); 5351c84f3f3cSopenharmony_ci } 5352c84f3f3cSopenharmony_ci x_col = col; 5353c84f3f3cSopenharmony_ci} 5354c84f3f3cSopenharmony_ci 5355c84f3f3cSopenharmony_ci 5356c84f3f3cSopenharmony_ci/* replace word with all expansions (ie, expand word*) */ 5357c84f3f3cSopenharmony_cistatic int 5358c84f3f3cSopenharmony_ciexpand_word(int cmd) 5359c84f3f3cSopenharmony_ci{ 5360c84f3f3cSopenharmony_ci static struct edstate *buf; 5361c84f3f3cSopenharmony_ci int rval = 0, nwords, start, end, i; 5362c84f3f3cSopenharmony_ci char **words; 5363c84f3f3cSopenharmony_ci 5364c84f3f3cSopenharmony_ci /* Undo previous expansion */ 5365c84f3f3cSopenharmony_ci if (cmd == 0 && expanded == EXPAND && buf) { 5366c84f3f3cSopenharmony_ci restore_edstate(vs, buf); 5367c84f3f3cSopenharmony_ci buf = 0; 5368c84f3f3cSopenharmony_ci expanded = NONE; 5369c84f3f3cSopenharmony_ci return (0); 5370c84f3f3cSopenharmony_ci } 5371c84f3f3cSopenharmony_ci if (buf) { 5372c84f3f3cSopenharmony_ci free_edstate(buf); 5373c84f3f3cSopenharmony_ci buf = 0; 5374c84f3f3cSopenharmony_ci } 5375c84f3f3cSopenharmony_ci 5376c84f3f3cSopenharmony_ci i = XCF_COMMAND_FILE | XCF_FULLPATH; 5377c84f3f3cSopenharmony_ci nwords = x_cf_glob(&i, vs->cbuf, vs->linelen, vs->cursor, 5378c84f3f3cSopenharmony_ci &start, &end, &words); 5379c84f3f3cSopenharmony_ci if (nwords == 0) { 5380c84f3f3cSopenharmony_ci vi_error(); 5381c84f3f3cSopenharmony_ci return (-1); 5382c84f3f3cSopenharmony_ci } 5383c84f3f3cSopenharmony_ci 5384c84f3f3cSopenharmony_ci buf = save_edstate(vs); 5385c84f3f3cSopenharmony_ci expanded = EXPAND; 5386c84f3f3cSopenharmony_ci del_range(start, end); 5387c84f3f3cSopenharmony_ci vs->cursor = start; 5388c84f3f3cSopenharmony_ci i = 0; 5389c84f3f3cSopenharmony_ci while (i < nwords) { 5390c84f3f3cSopenharmony_ci if (x_escape(words[i], strlen(words[i]), x_vi_putbuf) != 0) { 5391c84f3f3cSopenharmony_ci rval = -1; 5392c84f3f3cSopenharmony_ci break; 5393c84f3f3cSopenharmony_ci } 5394c84f3f3cSopenharmony_ci if (++i < nwords && putbuf(T1space, 1, false) != 0) { 5395c84f3f3cSopenharmony_ci rval = -1; 5396c84f3f3cSopenharmony_ci break; 5397c84f3f3cSopenharmony_ci } 5398c84f3f3cSopenharmony_ci } 5399c84f3f3cSopenharmony_ci i = buf->cursor - end; 5400c84f3f3cSopenharmony_ci if (rval == 0 && i > 0) 5401c84f3f3cSopenharmony_ci vs->cursor += i; 5402c84f3f3cSopenharmony_ci modified = 1; 5403c84f3f3cSopenharmony_ci hnum = hlast; 5404c84f3f3cSopenharmony_ci insert = INSERT; 5405c84f3f3cSopenharmony_ci lastac = 0; 5406c84f3f3cSopenharmony_ci refresh(false); 5407c84f3f3cSopenharmony_ci return (rval); 5408c84f3f3cSopenharmony_ci} 5409c84f3f3cSopenharmony_ci 5410c84f3f3cSopenharmony_cistatic int 5411c84f3f3cSopenharmony_cicomplete_word(int cmd, int count) 5412c84f3f3cSopenharmony_ci{ 5413c84f3f3cSopenharmony_ci static struct edstate *buf; 5414c84f3f3cSopenharmony_ci int rval, nwords, start, end, flags; 5415c84f3f3cSopenharmony_ci size_t match_len; 5416c84f3f3cSopenharmony_ci char **words; 5417c84f3f3cSopenharmony_ci char *match; 5418c84f3f3cSopenharmony_ci bool is_unique; 5419c84f3f3cSopenharmony_ci 5420c84f3f3cSopenharmony_ci /* Undo previous completion */ 5421c84f3f3cSopenharmony_ci if (cmd == 0 && expanded == COMPLETE && buf) { 5422c84f3f3cSopenharmony_ci print_expansions(buf, 0); 5423c84f3f3cSopenharmony_ci expanded = PRINT; 5424c84f3f3cSopenharmony_ci return (0); 5425c84f3f3cSopenharmony_ci } 5426c84f3f3cSopenharmony_ci if (cmd == 0 && expanded == PRINT && buf) { 5427c84f3f3cSopenharmony_ci restore_edstate(vs, buf); 5428c84f3f3cSopenharmony_ci buf = 0; 5429c84f3f3cSopenharmony_ci expanded = NONE; 5430c84f3f3cSopenharmony_ci return (0); 5431c84f3f3cSopenharmony_ci } 5432c84f3f3cSopenharmony_ci if (buf) { 5433c84f3f3cSopenharmony_ci free_edstate(buf); 5434c84f3f3cSopenharmony_ci buf = 0; 5435c84f3f3cSopenharmony_ci } 5436c84f3f3cSopenharmony_ci 5437c84f3f3cSopenharmony_ci /* 5438c84f3f3cSopenharmony_ci * XCF_FULLPATH for count 'cause the menu printed by 5439c84f3f3cSopenharmony_ci * print_expansions() was done this way. 5440c84f3f3cSopenharmony_ci */ 5441c84f3f3cSopenharmony_ci flags = XCF_COMMAND_FILE; 5442c84f3f3cSopenharmony_ci if (count) 5443c84f3f3cSopenharmony_ci flags |= XCF_FULLPATH; 5444c84f3f3cSopenharmony_ci nwords = x_cf_glob(&flags, vs->cbuf, vs->linelen, vs->cursor, 5445c84f3f3cSopenharmony_ci &start, &end, &words); 5446c84f3f3cSopenharmony_ci if (nwords == 0) { 5447c84f3f3cSopenharmony_ci vi_error(); 5448c84f3f3cSopenharmony_ci return (-1); 5449c84f3f3cSopenharmony_ci } 5450c84f3f3cSopenharmony_ci if (count) { 5451c84f3f3cSopenharmony_ci int i; 5452c84f3f3cSopenharmony_ci 5453c84f3f3cSopenharmony_ci count--; 5454c84f3f3cSopenharmony_ci if (count >= nwords) { 5455c84f3f3cSopenharmony_ci vi_error(); 5456c84f3f3cSopenharmony_ci x_print_expansions(nwords, words, 5457c84f3f3cSopenharmony_ci tobool(flags & XCF_IS_COMMAND)); 5458c84f3f3cSopenharmony_ci x_free_words(nwords, words); 5459c84f3f3cSopenharmony_ci redraw_line(false); 5460c84f3f3cSopenharmony_ci return (-1); 5461c84f3f3cSopenharmony_ci } 5462c84f3f3cSopenharmony_ci /* 5463c84f3f3cSopenharmony_ci * Expand the count'th word to its basename 5464c84f3f3cSopenharmony_ci */ 5465c84f3f3cSopenharmony_ci if (flags & XCF_IS_COMMAND) { 5466c84f3f3cSopenharmony_ci match = words[count] + 5467c84f3f3cSopenharmony_ci x_basename(words[count], NULL); 5468c84f3f3cSopenharmony_ci /* If more than one possible match, use full path */ 5469c84f3f3cSopenharmony_ci for (i = 0; i < nwords; i++) 5470c84f3f3cSopenharmony_ci if (i != count && 5471c84f3f3cSopenharmony_ci strcmp(words[i] + x_basename(words[i], 5472c84f3f3cSopenharmony_ci NULL), match) == 0) { 5473c84f3f3cSopenharmony_ci match = words[count]; 5474c84f3f3cSopenharmony_ci break; 5475c84f3f3cSopenharmony_ci } 5476c84f3f3cSopenharmony_ci } else 5477c84f3f3cSopenharmony_ci match = words[count]; 5478c84f3f3cSopenharmony_ci match_len = strlen(match); 5479c84f3f3cSopenharmony_ci is_unique = true; 5480c84f3f3cSopenharmony_ci /* expanded = PRINT; next call undo */ 5481c84f3f3cSopenharmony_ci } else { 5482c84f3f3cSopenharmony_ci match = words[0]; 5483c84f3f3cSopenharmony_ci match_len = x_longest_prefix(nwords, words); 5484c84f3f3cSopenharmony_ci /* next call will list completions */ 5485c84f3f3cSopenharmony_ci expanded = COMPLETE; 5486c84f3f3cSopenharmony_ci is_unique = nwords == 1; 5487c84f3f3cSopenharmony_ci } 5488c84f3f3cSopenharmony_ci 5489c84f3f3cSopenharmony_ci buf = save_edstate(vs); 5490c84f3f3cSopenharmony_ci del_range(start, end); 5491c84f3f3cSopenharmony_ci vs->cursor = start; 5492c84f3f3cSopenharmony_ci 5493c84f3f3cSopenharmony_ci /* 5494c84f3f3cSopenharmony_ci * escape all shell-sensitive characters and put the result into 5495c84f3f3cSopenharmony_ci * command buffer 5496c84f3f3cSopenharmony_ci */ 5497c84f3f3cSopenharmony_ci rval = x_escape(match, match_len, x_vi_putbuf); 5498c84f3f3cSopenharmony_ci 5499c84f3f3cSopenharmony_ci if (rval == 0 && is_unique) { 5500c84f3f3cSopenharmony_ci /* 5501c84f3f3cSopenharmony_ci * If exact match, don't undo. Allows directory completions 5502c84f3f3cSopenharmony_ci * to be used (ie, complete the next portion of the path). 5503c84f3f3cSopenharmony_ci */ 5504c84f3f3cSopenharmony_ci expanded = NONE; 5505c84f3f3cSopenharmony_ci 5506c84f3f3cSopenharmony_ci /* 5507c84f3f3cSopenharmony_ci * append a space if this is a non-directory match 5508c84f3f3cSopenharmony_ci * and not a parameter or homedir substitution 5509c84f3f3cSopenharmony_ci */ 5510c84f3f3cSopenharmony_ci if (match_len > 0 && !mksh_cdirsep(match[match_len - 1]) && 5511c84f3f3cSopenharmony_ci !(flags & XCF_IS_NOSPACE)) 5512c84f3f3cSopenharmony_ci rval = putbuf(T1space, 1, false); 5513c84f3f3cSopenharmony_ci } 5514c84f3f3cSopenharmony_ci x_free_words(nwords, words); 5515c84f3f3cSopenharmony_ci 5516c84f3f3cSopenharmony_ci modified = 1; 5517c84f3f3cSopenharmony_ci hnum = hlast; 5518c84f3f3cSopenharmony_ci insert = INSERT; 5519c84f3f3cSopenharmony_ci /* prevent this from being redone... */ 5520c84f3f3cSopenharmony_ci lastac = 0; 5521c84f3f3cSopenharmony_ci refresh(false); 5522c84f3f3cSopenharmony_ci 5523c84f3f3cSopenharmony_ci return (rval); 5524c84f3f3cSopenharmony_ci} 5525c84f3f3cSopenharmony_ci 5526c84f3f3cSopenharmony_cistatic int 5527c84f3f3cSopenharmony_ciprint_expansions(struct edstate *est, int cmd MKSH_A_UNUSED) 5528c84f3f3cSopenharmony_ci{ 5529c84f3f3cSopenharmony_ci int start, end, nwords, i; 5530c84f3f3cSopenharmony_ci char **words; 5531c84f3f3cSopenharmony_ci 5532c84f3f3cSopenharmony_ci i = XCF_COMMAND_FILE | XCF_FULLPATH; 5533c84f3f3cSopenharmony_ci nwords = x_cf_glob(&i, est->cbuf, est->linelen, est->cursor, 5534c84f3f3cSopenharmony_ci &start, &end, &words); 5535c84f3f3cSopenharmony_ci if (nwords == 0) { 5536c84f3f3cSopenharmony_ci vi_error(); 5537c84f3f3cSopenharmony_ci return (-1); 5538c84f3f3cSopenharmony_ci } 5539c84f3f3cSopenharmony_ci x_print_expansions(nwords, words, tobool(i & XCF_IS_COMMAND)); 5540c84f3f3cSopenharmony_ci x_free_words(nwords, words); 5541c84f3f3cSopenharmony_ci redraw_line(false); 5542c84f3f3cSopenharmony_ci return (0); 5543c84f3f3cSopenharmony_ci} 5544c84f3f3cSopenharmony_ci#endif /* !MKSH_S_NOVI */ 5545c84f3f3cSopenharmony_ci 5546c84f3f3cSopenharmony_ci/* Similar to x_zotc(emacs.c), but no tab weirdness */ 5547c84f3f3cSopenharmony_cistatic void 5548c84f3f3cSopenharmony_cix_vi_zotc(int c) 5549c84f3f3cSopenharmony_ci{ 5550c84f3f3cSopenharmony_ci if (ksh_isctrl(c)) { 5551c84f3f3cSopenharmony_ci x_putc('^'); 5552c84f3f3cSopenharmony_ci c = ksh_unctrl(c); 5553c84f3f3cSopenharmony_ci } 5554c84f3f3cSopenharmony_ci x_putc(c); 5555c84f3f3cSopenharmony_ci} 5556c84f3f3cSopenharmony_ci 5557c84f3f3cSopenharmony_ci#if !MKSH_S_NOVI 5558c84f3f3cSopenharmony_cistatic void 5559c84f3f3cSopenharmony_civi_error(void) 5560c84f3f3cSopenharmony_ci{ 5561c84f3f3cSopenharmony_ci /* Beem out of any macros as soon as an error occurs */ 5562c84f3f3cSopenharmony_ci vi_macro_reset(); 5563c84f3f3cSopenharmony_ci x_putc(KSH_BEL); 5564c84f3f3cSopenharmony_ci x_flush(); 5565c84f3f3cSopenharmony_ci} 5566c84f3f3cSopenharmony_ci 5567c84f3f3cSopenharmony_cistatic void 5568c84f3f3cSopenharmony_civi_macro_reset(void) 5569c84f3f3cSopenharmony_ci{ 5570c84f3f3cSopenharmony_ci if (macro.p) { 5571c84f3f3cSopenharmony_ci afree(macro.buf, AEDIT); 5572c84f3f3cSopenharmony_ci memset((char *)¯o, 0, sizeof(macro)); 5573c84f3f3cSopenharmony_ci } 5574c84f3f3cSopenharmony_ci} 5575c84f3f3cSopenharmony_ci#endif /* !MKSH_S_NOVI */ 5576c84f3f3cSopenharmony_ci 5577c84f3f3cSopenharmony_ci/* called from main.c */ 5578c84f3f3cSopenharmony_civoid 5579c84f3f3cSopenharmony_cix_init(void) 5580c84f3f3cSopenharmony_ci{ 5581c84f3f3cSopenharmony_ci int i, j; 5582c84f3f3cSopenharmony_ci 5583c84f3f3cSopenharmony_ci /* 5584c84f3f3cSopenharmony_ci * set edchars to force initial binding, except we need 5585c84f3f3cSopenharmony_ci * default values for ^W for some deficient systems… 5586c84f3f3cSopenharmony_ci */ 5587c84f3f3cSopenharmony_ci edchars.erase = edchars.kill = edchars.intr = edchars.quit = 5588c84f3f3cSopenharmony_ci edchars.eof = EDCHAR_INITIAL; 5589c84f3f3cSopenharmony_ci edchars.werase = 027; 5590c84f3f3cSopenharmony_ci 5591c84f3f3cSopenharmony_ci /* command line editing specific memory allocation */ 5592c84f3f3cSopenharmony_ci ainit(AEDIT); 5593c84f3f3cSopenharmony_ci holdbufp = alloc(LINE, AEDIT); 5594c84f3f3cSopenharmony_ci 5595c84f3f3cSopenharmony_ci /* initialise Emacs command line editing mode */ 5596c84f3f3cSopenharmony_ci x_nextcmd = -1; 5597c84f3f3cSopenharmony_ci 5598c84f3f3cSopenharmony_ci x_tab = alloc2(X_NTABS, sizeof(*x_tab), AEDIT); 5599c84f3f3cSopenharmony_ci for (j = 0; j < X_TABSZ; j++) 5600c84f3f3cSopenharmony_ci x_tab[0][j] = XFUNC_insert; 5601c84f3f3cSopenharmony_ci for (i = 1; i < X_NTABS; i++) 5602c84f3f3cSopenharmony_ci for (j = 0; j < X_TABSZ; j++) 5603c84f3f3cSopenharmony_ci x_tab[i][j] = XFUNC_error; 5604c84f3f3cSopenharmony_ci for (i = 0; i < (int)NELEM(x_defbindings); i++) 5605c84f3f3cSopenharmony_ci x_tab[x_defbindings[i].xdb_tab][x_defbindings[i].xdb_char] 5606c84f3f3cSopenharmony_ci = x_defbindings[i].xdb_func; 5607c84f3f3cSopenharmony_ci 5608c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 5609c84f3f3cSopenharmony_ci x_atab = alloc2(X_NTABS, sizeof(*x_atab), AEDIT); 5610c84f3f3cSopenharmony_ci for (i = 1; i < X_NTABS; i++) 5611c84f3f3cSopenharmony_ci for (j = 0; j < X_TABSZ; j++) 5612c84f3f3cSopenharmony_ci x_atab[i][j] = NULL; 5613c84f3f3cSopenharmony_ci#endif 5614c84f3f3cSopenharmony_ci} 5615c84f3f3cSopenharmony_ci 5616c84f3f3cSopenharmony_ci#ifdef DEBUG_LEAKS 5617c84f3f3cSopenharmony_civoid 5618c84f3f3cSopenharmony_cix_done(void) 5619c84f3f3cSopenharmony_ci{ 5620c84f3f3cSopenharmony_ci if (x_tab != NULL) 5621c84f3f3cSopenharmony_ci afreeall(AEDIT); 5622c84f3f3cSopenharmony_ci} 5623c84f3f3cSopenharmony_ci#endif 5624c84f3f3cSopenharmony_ci 5625c84f3f3cSopenharmony_civoid 5626c84f3f3cSopenharmony_cix_initterm(const char *termtype) 5627c84f3f3cSopenharmony_ci{ 5628c84f3f3cSopenharmony_ci /* default must be 0 (bss) */ 5629c84f3f3cSopenharmony_ci x_term_mode = 0; 5630c84f3f3cSopenharmony_ci /* catch any of the TERM types tmux uses, don’t ask m̲e̲ about it… */ 5631c84f3f3cSopenharmony_ci switch (*termtype) { 5632c84f3f3cSopenharmony_ci case 's': 5633c84f3f3cSopenharmony_ci if (!strncmp(termtype, "screen", 6) && 5634c84f3f3cSopenharmony_ci (termtype[6] == '\0' || termtype[6] == '-')) 5635c84f3f3cSopenharmony_ci x_term_mode = 1; 5636c84f3f3cSopenharmony_ci break; 5637c84f3f3cSopenharmony_ci case 't': 5638c84f3f3cSopenharmony_ci if (!strncmp(termtype, "tmux", 4) && 5639c84f3f3cSopenharmony_ci (termtype[4] == '\0' || termtype[4] == '-')) 5640c84f3f3cSopenharmony_ci x_term_mode = 1; 5641c84f3f3cSopenharmony_ci break; 5642c84f3f3cSopenharmony_ci } 5643c84f3f3cSopenharmony_ci} 5644c84f3f3cSopenharmony_ci 5645c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 5646c84f3f3cSopenharmony_cistatic char * 5647c84f3f3cSopenharmony_cix_eval_region_helper(const char *cmd, size_t len) 5648c84f3f3cSopenharmony_ci{ 5649c84f3f3cSopenharmony_ci char * volatile cp; 5650c84f3f3cSopenharmony_ci newenv(E_ERRH); 5651c84f3f3cSopenharmony_ci 5652c84f3f3cSopenharmony_ci if (!kshsetjmp(e->jbuf)) { 5653c84f3f3cSopenharmony_ci char *wds = alloc(len + 3, ATEMP); 5654c84f3f3cSopenharmony_ci 5655c84f3f3cSopenharmony_ci wds[0] = FUNASUB; 5656c84f3f3cSopenharmony_ci memcpy(wds + 1, cmd, len); 5657c84f3f3cSopenharmony_ci wds[len + 1] = '\0'; 5658c84f3f3cSopenharmony_ci wds[len + 2] = EOS; 5659c84f3f3cSopenharmony_ci 5660c84f3f3cSopenharmony_ci cp = evalstr(wds, DOSCALAR); 5661c84f3f3cSopenharmony_ci afree(wds, ATEMP); 5662c84f3f3cSopenharmony_ci strdupx(cp, cp, AEDIT); 5663c84f3f3cSopenharmony_ci } else 5664c84f3f3cSopenharmony_ci /* command cannot be parsed */ 5665c84f3f3cSopenharmony_ci cp = NULL; 5666c84f3f3cSopenharmony_ci quitenv(NULL); 5667c84f3f3cSopenharmony_ci return (cp); 5668c84f3f3cSopenharmony_ci} 5669c84f3f3cSopenharmony_ci 5670c84f3f3cSopenharmony_cistatic int 5671c84f3f3cSopenharmony_cix_operate_region(char *(*helper)(const char *, size_t)) 5672c84f3f3cSopenharmony_ci{ 5673c84f3f3cSopenharmony_ci char *rgbeg, *rgend, *cp; 5674c84f3f3cSopenharmony_ci size_t newlen; 5675c84f3f3cSopenharmony_ci /* only for LINE overflow checking */ 5676c84f3f3cSopenharmony_ci size_t restlen; 5677c84f3f3cSopenharmony_ci 5678c84f3f3cSopenharmony_ci if (xmp == NULL) { 5679c84f3f3cSopenharmony_ci rgbeg = xbuf; 5680c84f3f3cSopenharmony_ci rgend = xep; 5681c84f3f3cSopenharmony_ci } else if (xmp < xcp) { 5682c84f3f3cSopenharmony_ci rgbeg = xmp; 5683c84f3f3cSopenharmony_ci rgend = xcp; 5684c84f3f3cSopenharmony_ci } else { 5685c84f3f3cSopenharmony_ci rgbeg = xcp; 5686c84f3f3cSopenharmony_ci rgend = xmp; 5687c84f3f3cSopenharmony_ci } 5688c84f3f3cSopenharmony_ci 5689c84f3f3cSopenharmony_ci x_e_putc2('\r'); 5690c84f3f3cSopenharmony_ci x_clrtoeol(' ', false); 5691c84f3f3cSopenharmony_ci x_flush(); 5692c84f3f3cSopenharmony_ci x_mode(false); 5693c84f3f3cSopenharmony_ci cp = helper(rgbeg, rgend - rgbeg); 5694c84f3f3cSopenharmony_ci x_mode(true); 5695c84f3f3cSopenharmony_ci 5696c84f3f3cSopenharmony_ci if (cp == NULL) { 5697c84f3f3cSopenharmony_ci /* error return from helper */ 5698c84f3f3cSopenharmony_ci x_eval_region_err: 5699c84f3f3cSopenharmony_ci x_e_putc2(KSH_BEL); 5700c84f3f3cSopenharmony_ci x_redraw('\r'); 5701c84f3f3cSopenharmony_ci return (KSTD); 5702c84f3f3cSopenharmony_ci } 5703c84f3f3cSopenharmony_ci 5704c84f3f3cSopenharmony_ci newlen = strlen(cp); 5705c84f3f3cSopenharmony_ci restlen = xep - rgend; 5706c84f3f3cSopenharmony_ci /* check for LINE overflow, until this is dynamically allocated */ 5707c84f3f3cSopenharmony_ci if (rgbeg + newlen + restlen >= xend) 5708c84f3f3cSopenharmony_ci goto x_eval_region_err; 5709c84f3f3cSopenharmony_ci 5710c84f3f3cSopenharmony_ci xmp = rgbeg; 5711c84f3f3cSopenharmony_ci xcp = rgbeg + newlen; 5712c84f3f3cSopenharmony_ci xep = xcp + restlen; 5713c84f3f3cSopenharmony_ci memmove(xcp, rgend, restlen + /* NUL */ 1); 5714c84f3f3cSopenharmony_ci memcpy(xmp, cp, newlen); 5715c84f3f3cSopenharmony_ci afree(cp, AEDIT); 5716c84f3f3cSopenharmony_ci x_adjust(); 5717c84f3f3cSopenharmony_ci x_modified(); 5718c84f3f3cSopenharmony_ci return (KSTD); 5719c84f3f3cSopenharmony_ci} 5720c84f3f3cSopenharmony_ci 5721c84f3f3cSopenharmony_cistatic int 5722c84f3f3cSopenharmony_cix_eval_region(int c MKSH_A_UNUSED) 5723c84f3f3cSopenharmony_ci{ 5724c84f3f3cSopenharmony_ci return (x_operate_region(x_eval_region_helper)); 5725c84f3f3cSopenharmony_ci} 5726c84f3f3cSopenharmony_ci 5727c84f3f3cSopenharmony_cistatic char * 5728c84f3f3cSopenharmony_cix_quote_region_helper(const char *cmd, size_t len) 5729c84f3f3cSopenharmony_ci{ 5730c84f3f3cSopenharmony_ci char *s; 5731c84f3f3cSopenharmony_ci size_t newlen; 5732c84f3f3cSopenharmony_ci struct shf shf; 5733c84f3f3cSopenharmony_ci 5734c84f3f3cSopenharmony_ci strndupx(s, cmd, len, ATEMP); 5735c84f3f3cSopenharmony_ci newlen = len < 256 ? 256 : 4096; 5736c84f3f3cSopenharmony_ci shf_sopen(alloc(newlen, AEDIT), newlen, SHF_WR | SHF_DYNAMIC, &shf); 5737c84f3f3cSopenharmony_ci shf.areap = AEDIT; 5738c84f3f3cSopenharmony_ci shf.flags |= SHF_ALLOCB; 5739c84f3f3cSopenharmony_ci print_value_quoted(&shf, s); 5740c84f3f3cSopenharmony_ci afree(s, ATEMP); 5741c84f3f3cSopenharmony_ci return (shf_sclose(&shf)); 5742c84f3f3cSopenharmony_ci} 5743c84f3f3cSopenharmony_ci 5744c84f3f3cSopenharmony_cistatic int 5745c84f3f3cSopenharmony_cix_quote_region(int c MKSH_A_UNUSED) 5746c84f3f3cSopenharmony_ci{ 5747c84f3f3cSopenharmony_ci return (x_operate_region(x_quote_region_helper)); 5748c84f3f3cSopenharmony_ci} 5749c84f3f3cSopenharmony_ci#endif /* !MKSH_SMALL */ 5750c84f3f3cSopenharmony_ci#endif /* !MKSH_NO_CMDLINE_EDITING */ 5751