1 /*- 2 * Copyright (c) 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1992, 1993, 1994, 1995, 1996 5 * Keith Bostic. All rights reserved. 6 * 7 * See the LICENSE file for redistribution information. 8 */ 9 10 #include "config.h" 11 12 #include <sys/types.h> 13 #include <sys/queue.h> 14 #include <sys/time.h> 15 16 #include <bitstring.h> 17 #include <limits.h> 18 #include <stdio.h> 19 #include <string.h> 20 #include <unistd.h> 21 22 #include "../common/common.h" 23 24 enum which {APPEND, CHANGE, INSERT}; 25 26 static int ex_aci(SCR *, EXCMD *, enum which); 27 28 /* 29 * ex_append -- :[line] a[ppend][!] 30 * Append one or more lines of new text after the specified line, 31 * or the current line if no address is specified. 32 * 33 * PUBLIC: int ex_append(SCR *, EXCMD *); 34 */ 35 int 36 ex_append(SCR *sp, EXCMD *cmdp) 37 { 38 return (ex_aci(sp, cmdp, APPEND)); 39 } 40 41 /* 42 * ex_change -- :[line[,line]] c[hange][!] [count] 43 * Change one or more lines to the input text. 44 * 45 * PUBLIC: int ex_change(SCR *, EXCMD *); 46 */ 47 int 48 ex_change(SCR *sp, EXCMD *cmdp) 49 { 50 return (ex_aci(sp, cmdp, CHANGE)); 51 } 52 53 /* 54 * ex_insert -- :[line] i[nsert][!] 55 * Insert one or more lines of new text before the specified line, 56 * or the current line if no address is specified. 57 * 58 * PUBLIC: int ex_insert(SCR *, EXCMD *); 59 */ 60 int 61 ex_insert(SCR *sp, EXCMD *cmdp) 62 { 63 return (ex_aci(sp, cmdp, INSERT)); 64 } 65 66 /* 67 * ex_aci -- 68 * Append, change, insert in ex. 69 */ 70 static int 71 ex_aci(SCR *sp, EXCMD *cmdp, enum which cmd) 72 { 73 CHAR_T *p, *t; 74 GS *gp; 75 TEXT *tp; 76 TEXTH tiq[] = {{ 0 }}; 77 recno_t cnt = 0, lno; 78 size_t len; 79 u_int32_t flags; 80 int need_newline; 81 82 gp = sp->gp; 83 NEEDFILE(sp, cmdp); 84 85 /* 86 * If doing a change, replace lines for as long as possible. Then, 87 * append more lines or delete remaining lines. Changes to an empty 88 * file are appends, inserts are the same as appends to the previous 89 * line. 90 * 91 * !!! 92 * Set the address to which we'll append. We set sp->lno to this 93 * address as well so that autoindent works correctly when get text 94 * from the user. 95 */ 96 lno = cmdp->addr1.lno; 97 sp->lno = lno; 98 if ((cmd == CHANGE || cmd == INSERT) && lno != 0) 99 --lno; 100 101 /* 102 * !!! 103 * If the file isn't empty, cut changes into the unnamed buffer. 104 */ 105 if (cmd == CHANGE && cmdp->addr1.lno != 0 && 106 (cut(sp, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE) || 107 del(sp, &cmdp->addr1, &cmdp->addr2, 1))) 108 return (1); 109 110 /* 111 * !!! 112 * Anything that was left after the command separator becomes part 113 * of the inserted text. Apparently, it was common usage to enter: 114 * 115 * :g/pattern/append|stuff1 116 * 117 * and append the line of text "stuff1" to the lines containing the 118 * pattern. It was also historically legal to enter: 119 * 120 * :append|stuff1 121 * stuff2 122 * . 123 * 124 * and the text on the ex command line would be appended as well as 125 * the text inserted after it. There was an historic bug however, 126 * that the user had to enter *two* terminating lines (the '.' lines) 127 * to terminate text input mode, in this case. This whole thing 128 * could be taken too far, however. Entering: 129 * 130 * :append|stuff1\ 131 * stuff2 132 * stuff3 133 * . 134 * 135 * i.e. mixing and matching the forms confused the historic vi, and, 136 * not only did it take two terminating lines to terminate text input 137 * mode, but the trailing backslashes were retained on the input. We 138 * match historic practice except that we discard the backslashes. 139 * 140 * Input lines specified on the ex command line lines are separated by 141 * <newline>s. If there is a trailing delimiter an empty line was 142 * inserted. There may also be a leading delimiter, which is ignored 143 * unless it's also a trailing delimiter. It is possible to encounter 144 * a termination line, i.e. a single '.', in a global command, but not 145 * necessary if the text insert command was the last of the global 146 * commands. 147 */ 148 if (cmdp->save_cmdlen != 0) { 149 for (p = cmdp->save_cmd, 150 len = cmdp->save_cmdlen; len > 0; p = t) { 151 for (t = p; len > 0 && t[0] != '\n'; ++t, --len); 152 if (t != p || len == 0) { 153 if (F_ISSET(sp, SC_EX_GLOBAL) && 154 t - p == 1 && p[0] == '.') { 155 ++t; 156 if (len > 0) 157 --len; 158 break; 159 } 160 if (db_append(sp, 1, lno++, p, t - p)) 161 return (1); 162 } 163 if (len != 0) { 164 ++t; 165 if (--len == 0 && 166 db_append(sp, 1, lno++, NULL, 0)) 167 return (1); 168 } 169 } 170 /* 171 * If there's any remaining text, we're in a global, and 172 * there's more command to parse. 173 * 174 * !!! 175 * We depend on the fact that non-global commands will eat the 176 * rest of the command line as text input, and before getting 177 * any text input from the user. Otherwise, we'd have to save 178 * off the command text before or during the call to the text 179 * input function below. 180 */ 181 if (len != 0) 182 cmdp->save_cmd = t; 183 cmdp->save_cmdlen = len; 184 } 185 186 if (F_ISSET(sp, SC_EX_GLOBAL)) { 187 if ((sp->lno = lno) == 0 && db_exist(sp, 1)) 188 sp->lno = 1; 189 return (0); 190 } 191 192 /* 193 * If not in a global command, read from the terminal. 194 * 195 * If this code is called by vi, we want to reset the terminal and use 196 * ex's line get routine. It actually works fine if we use vi's get 197 * routine, but it doesn't look as nice. Maybe if we had a separate 198 * window or something, but getting a line at a time looks awkward. 199 * However, depending on the screen that we're using, that may not 200 * be possible. 201 */ 202 if (F_ISSET(sp, SC_VI)) { 203 if (gp->scr_screen(sp, SC_EX)) { 204 ex_wemsg(sp, cmdp->cmd->name, EXM_NOCANON); 205 return (1); 206 } 207 208 /* If we're still in the vi screen, move out explicitly. */ 209 need_newline = !F_ISSET(sp, SC_SCR_EXWROTE); 210 F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE); 211 if (need_newline) 212 (void)ex_puts(sp, "\n"); 213 214 /* 215 * !!! 216 * Users of historical versions of vi sometimes get confused 217 * when they enter append mode, and can't seem to get out of 218 * it. Give them an informational message. 219 */ 220 (void)ex_puts(sp, 221 msg_cat(sp, "273|Entering ex input mode.", NULL)); 222 (void)ex_puts(sp, "\n"); 223 (void)ex_fflush(sp); 224 } 225 226 /* 227 * Set input flags; the ! flag turns off autoindent for append, 228 * change and insert. 229 */ 230 LF_INIT(TXT_DOTTERM | TXT_NUMBER); 231 if (!FL_ISSET(cmdp->iflags, E_C_FORCE) && O_ISSET(sp, O_AUTOINDENT)) 232 LF_SET(TXT_AUTOINDENT); 233 if (O_ISSET(sp, O_BEAUTIFY)) 234 LF_SET(TXT_BEAUTIFY); 235 236 /* 237 * This code can't use the common screen TEXTH structure (sp->tiq), 238 * as it may already be in use, e.g. ":append|s/abc/ABC/" would fail 239 * as we are only halfway through the text when the append code fires. 240 * Use a local structure instead. (The ex code would have to use a 241 * local structure except that we're guaranteed to finish remaining 242 * characters in the common TEXTH structure when they were inserted 243 * into the file, above.) 244 */ 245 TAILQ_INIT(tiq); 246 247 if (ex_txt(sp, tiq, 0, flags)) 248 return (1); 249 250 TAILQ_FOREACH(tp, tiq, q) { 251 if (db_append(sp, 1, lno++, tp->lb, tp->len)) 252 return (1); 253 ++cnt; 254 } 255 256 /* 257 * Set sp->lno to the final line number value (correcting for a 258 * possible 0 value) as that's historically correct for the final 259 * line value, whether or not the user entered any text. 260 */ 261 if ((sp->lno = lno) == 0 && db_exist(sp, 1)) 262 sp->lno = 1; 263 264 return (0); 265 } 266