| File: | src/usr.bin/vi/build/../vi/vi.c |
| Warning: | line 347, column 40 The right operand of '!=' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: vi.c,v 1.23 2022/02/20 19:45:51 tb Exp $ */ | |||
| 2 | ||||
| 3 | /*- | |||
| 4 | * Copyright (c) 1992, 1993, 1994 | |||
| 5 | * The Regents of the University of California. All rights reserved. | |||
| 6 | * Copyright (c) 1992, 1993, 1994, 1995, 1996 | |||
| 7 | * Keith Bostic. All rights reserved. | |||
| 8 | * | |||
| 9 | * See the LICENSE file for redistribution information. | |||
| 10 | */ | |||
| 11 | ||||
| 12 | #include "config.h" | |||
| 13 | ||||
| 14 | #include <sys/types.h> | |||
| 15 | #include <sys/queue.h> | |||
| 16 | #include <sys/time.h> | |||
| 17 | ||||
| 18 | #include <bitstring.h> | |||
| 19 | #include <ctype.h> | |||
| 20 | #include <errno(*__errno()).h> | |||
| 21 | #include <limits.h> | |||
| 22 | #include <stdio.h> | |||
| 23 | #include <stdlib.h> | |||
| 24 | #include <string.h> | |||
| 25 | #include <unistd.h> | |||
| 26 | ||||
| 27 | #include "../common/common.h" | |||
| 28 | #include "vi.h" | |||
| 29 | ||||
| 30 | typedef enum { | |||
| 31 | GC_ERR, GC_ERR_NOFLUSH, GC_EVENT, GC_FATAL, GC_INTERRUPT, GC_OK | |||
| 32 | } gcret_t; | |||
| 33 | ||||
| 34 | static VIKEYS const | |||
| 35 | *v_alias(SCR *, VICMD *, VIKEYS const *); | |||
| 36 | static gcret_t v_cmd(SCR *, VICMD *, VICMD *, VICMD *, int *, int *); | |||
| 37 | static int v_count(SCR *, CHAR_T, u_long *); | |||
| 38 | static void v_dtoh(SCR *); | |||
| 39 | static int v_init(SCR *); | |||
| 40 | static gcret_t v_key(SCR *, int, EVENT *, u_int32_t); | |||
| 41 | static int v_keyword(SCR *); | |||
| 42 | static int v_motion(SCR *, VICMD *, VICMD *, int *); | |||
| 43 | ||||
| 44 | #if defined(DEBUG) && defined(COMLOG) | |||
| 45 | static void v_comlog(SCR *, VICMD *); | |||
| 46 | #endif | |||
| 47 | ||||
| 48 | /* | |||
| 49 | * Side-effect: | |||
| 50 | * The dot structure can be set by the underlying vi functions, | |||
| 51 | * see v_Put() and v_put(). | |||
| 52 | */ | |||
| 53 | #define DOT(&((VI_PRIVATE *)((sp)->vi_private))->sdot) (&VIP(sp)((VI_PRIVATE *)((sp)->vi_private))->sdot) | |||
| 54 | #define DOTMOTION(&((VI_PRIVATE *)((sp)->vi_private))->sdotmotion) (&VIP(sp)((VI_PRIVATE *)((sp)->vi_private))->sdotmotion) | |||
| 55 | ||||
| 56 | /* | |||
| 57 | * vi -- | |||
| 58 | * Main vi command loop. | |||
| 59 | * | |||
| 60 | * PUBLIC: int vi(SCR **); | |||
| 61 | */ | |||
| 62 | int | |||
| 63 | vi(SCR **spp) | |||
| 64 | { | |||
| 65 | GS *gp; | |||
| 66 | MARK abs; | |||
| 67 | SCR *next, *sp; | |||
| 68 | VICMD cmd, *vp; | |||
| 69 | VI_PRIVATE *vip; | |||
| 70 | int comcount, mapped, rval; | |||
| 71 | ||||
| 72 | /* Get the first screen. */ | |||
| 73 | sp = *spp; | |||
| 74 | gp = sp->gp; | |||
| 75 | ||||
| 76 | /* Initialize the command structure. */ | |||
| 77 | vp = &cmd; | |||
| 78 | memset(vp, 0, sizeof(VICMD)); | |||
| 79 | ||||
| 80 | /* Reset strange attraction. */ | |||
| 81 | F_SET(vp, VM_RCM_SET)(((vp)->flags) |= ((0x00000020))); | |||
| 82 | ||||
| 83 | /* Initialize the vi screen. */ | |||
| 84 | if (v_init(sp)) | |||
| ||||
| 85 | return (1); | |||
| 86 | ||||
| 87 | /* Set the focus. */ | |||
| 88 | (void)sp->gp->scr_rename(sp, sp->frp->name, 1); | |||
| 89 | ||||
| 90 | for (vip = VIP(sp)((VI_PRIVATE *)((sp)->vi_private)), rval = 0;;) { | |||
| 91 | /* Resolve messages. */ | |||
| 92 | if (!MAPPED_KEYS_WAITING(sp)(((sp)->gp->i_cnt != 0) && (((&(sp)->gp-> i_event[(sp)->gp->i_next]._u_event._e_ch)->flags) & ((0x02)))) && vs_resolve(sp, NULL((void *)0), 0)) | |||
| 93 | goto ret; | |||
| 94 | ||||
| 95 | /* | |||
| 96 | * If not skipping a refresh, return to command mode and | |||
| 97 | * refresh the screen. | |||
| 98 | */ | |||
| 99 | if (F_ISSET(vip, VIP_S_REFRESH)(((vip)->flags) & ((0x0100)))) | |||
| 100 | F_CLR(vip, VIP_S_REFRESH)(((vip)->flags) &= ~((0x0100))); | |||
| 101 | else { | |||
| 102 | sp->showmode = SM_COMMAND; | |||
| 103 | if (vs_refresh(sp, 0)) | |||
| 104 | goto ret; | |||
| 105 | } | |||
| 106 | ||||
| 107 | /* Set the new favorite position. */ | |||
| 108 | if (F_ISSET(vp, VM_RCM_SET | VM_RCM_SETFNB | VM_RCM_SETNNB)(((vp)->flags) & ((0x00000020 | 0x00000040 | 0x00000100 )))) { | |||
| 109 | F_CLR(vip, VIP_RCM_LAST)(((vip)->flags) &= ~((0x0040))); | |||
| 110 | (void)vs_column(sp, &sp->rcm); | |||
| 111 | } | |||
| 112 | ||||
| 113 | /* | |||
| 114 | * If not currently in a map, log the cursor position, | |||
| 115 | * and set a flag so that this command can become the | |||
| 116 | * DOT command. | |||
| 117 | */ | |||
| 118 | if (MAPPED_KEYS_WAITING(sp)(((sp)->gp->i_cnt != 0) && (((&(sp)->gp-> i_event[(sp)->gp->i_next]._u_event._e_ch)->flags) & ((0x02))))) | |||
| 119 | mapped = 1; | |||
| 120 | else { | |||
| 121 | if (log_cursor(sp)) | |||
| 122 | goto err; | |||
| 123 | mapped = 0; | |||
| 124 | } | |||
| 125 | ||||
| 126 | /* | |||
| 127 | * There may be an ex command waiting, and we returned here | |||
| 128 | * only because we exited a screen or file. In this case, | |||
| 129 | * we simply go back into the ex parser. | |||
| 130 | */ | |||
| 131 | if (EXCMD_RUNNING(gp)(((&(gp)->ecq)->lh_first)->clen != 0)) { | |||
| 132 | vp->kp = &vikeys[':']; | |||
| 133 | goto ex_continue; | |||
| 134 | } | |||
| 135 | ||||
| 136 | /* Refresh the command structure. */ | |||
| 137 | memset(vp, 0, sizeof(VICMD)); | |||
| 138 | ||||
| 139 | /* | |||
| 140 | * We get a command, which may or may not have an associated | |||
| 141 | * motion. If it does, we get it too, calling its underlying | |||
| 142 | * function to get the resulting mark. We then call the | |||
| 143 | * command setting the cursor to the resulting mark. | |||
| 144 | * | |||
| 145 | * !!! | |||
| 146 | * Vi historically flushed mapped characters on error, but | |||
| 147 | * entering extra <escape> characters at the beginning of | |||
| 148 | * a map wasn't considered an error -- in fact, users would | |||
| 149 | * put leading <escape> characters in maps to clean up vi | |||
| 150 | * state before the map was interpreted. Beauty! | |||
| 151 | */ | |||
| 152 | switch (v_cmd(sp, DOT(&((VI_PRIVATE *)((sp)->vi_private))->sdot), vp, NULL((void *)0), &comcount, &mapped)) { | |||
| 153 | case GC_ERR: | |||
| 154 | goto err; | |||
| 155 | case GC_ERR_NOFLUSH: | |||
| 156 | goto gc_err_noflush; | |||
| 157 | case GC_EVENT: | |||
| 158 | if (v_event_exec(sp, vp)) | |||
| 159 | goto err; | |||
| 160 | goto gc_event; | |||
| 161 | case GC_FATAL: | |||
| 162 | goto ret; | |||
| 163 | case GC_INTERRUPT: | |||
| 164 | goto intr; | |||
| 165 | case GC_OK: | |||
| 166 | break; | |||
| 167 | } | |||
| 168 | ||||
| 169 | /* Check for security setting. */ | |||
| 170 | if (F_ISSET(vp->kp, V_SECURE)(((vp->kp)->flags) & ((0x02000000))) && O_ISSET(sp, O_SECURE)((((&(((sp)))->opts[(((O_SECURE)))])->flags) & ( (0x01))) ? (((sp)))->gp->opts[(((sp)))->opts[(((O_SECURE )))].o_cur.val].o_cur.val : (((sp)))->opts[(((O_SECURE)))] .o_cur.val)) { | |||
| 171 | ex_emsg(sp, KEY_NAME(sp, vp->key)((unsigned char)(vp->key) <= 254 ? (sp)->gp->cname [(unsigned char)(vp->key)].name : v_key_name((sp), (vp-> key))), EXM_SECURE); | |||
| 172 | goto err; | |||
| 173 | } | |||
| 174 | ||||
| 175 | /* | |||
| 176 | * Historical practice: if a dot command gets a new count, | |||
| 177 | * any motion component goes away, i.e. "d3w2." deletes a | |||
| 178 | * total of 5 words. | |||
| 179 | */ | |||
| 180 | if (F_ISSET(vp, VC_ISDOT)(((vp)->flags) & ((0x00002000))) && comcount) | |||
| 181 | DOTMOTION(&((VI_PRIVATE *)((sp)->vi_private))->sdotmotion)->count = 1; | |||
| 182 | ||||
| 183 | /* Copy the key flags into the local structure. */ | |||
| 184 | F_SET(vp, vp->kp->flags)(((vp)->flags) |= ((vp->kp->flags))); | |||
| 185 | ||||
| 186 | /* Prepare to set the previous context. */ | |||
| 187 | if (F_ISSET(vp, V_ABS | V_ABS_C | V_ABS_L)(((vp)->flags) & ((0x00004000 | 0x00008000 | 0x00010000 )))) { | |||
| 188 | abs.lno = sp->lno; | |||
| 189 | abs.cno = sp->cno; | |||
| 190 | } | |||
| 191 | ||||
| 192 | /* | |||
| 193 | * Set the three cursor locations to the current cursor. The | |||
| 194 | * underlying routines don't bother if the cursor doesn't move. | |||
| 195 | * This also handles line commands (e.g. Y) defaulting to the | |||
| 196 | * current line. | |||
| 197 | */ | |||
| 198 | vp->m_start.lno = vp->m_stop.lno = vp->m_final.lno = sp->lno; | |||
| 199 | vp->m_start.cno = vp->m_stop.cno = vp->m_final.cno = sp->cno; | |||
| 200 | ||||
| 201 | /* | |||
| 202 | * Do any required motion; v_motion sets the from MARK and the | |||
| 203 | * line mode flag, as well as the VM_RCM flags. | |||
| 204 | */ | |||
| 205 | if (F_ISSET(vp, V_MOTION)(((vp)->flags) & ((0x00200000))) && | |||
| 206 | v_motion(sp, DOTMOTION(&((VI_PRIVATE *)((sp)->vi_private))->sdotmotion), vp, &mapped)) { | |||
| 207 | if (INTERRUPTED(sp)(((((sp)->gp)->flags) & ((0x0004))) || (!v_event_get ((sp), ((void *)0), 0, 0x001) && ((((sp)->gp)-> flags) & ((0x0004)))))) | |||
| 208 | goto intr; | |||
| 209 | goto err; | |||
| 210 | } | |||
| 211 | ||||
| 212 | /* | |||
| 213 | * If a count is set and the command is line oriented, set the | |||
| 214 | * to MARK here relative to the cursor/from MARK. This is for | |||
| 215 | * commands that take both counts and motions, i.e. "4yy" and | |||
| 216 | * "y%". As there's no way the command can know which the user | |||
| 217 | * did, we have to do it here. (There are commands that are | |||
| 218 | * line oriented and that take counts ("#G", "#H"), for which | |||
| 219 | * this calculation is either completely meaningless or wrong. | |||
| 220 | * Each command must validate the value for itself. | |||
| 221 | */ | |||
| 222 | if (F_ISSET(vp, VC_C1SET)(((vp)->flags) & ((0x00000800))) && F_ISSET(vp, VM_LMODE)(((vp)->flags) & ((0x00000008)))) | |||
| 223 | vp->m_stop.lno += vp->count - 1; | |||
| 224 | ||||
| 225 | /* Increment the command count. */ | |||
| 226 | ++sp->ccnt; | |||
| 227 | ||||
| 228 | #if defined(DEBUG) && defined(COMLOG) | |||
| 229 | v_comlog(sp, vp); | |||
| 230 | #endif | |||
| 231 | /* Call the function. */ | |||
| 232 | ex_continue: if (vp->kp->func(sp, vp)) | |||
| 233 | goto err; | |||
| 234 | gc_event: | |||
| 235 | #ifdef DEBUG | |||
| 236 | /* Make sure no function left the temporary space locked. */ | |||
| 237 | if (F_ISSET(gp, G_TMP_INUSE)(((gp)->flags) & ((0x0100)))) { | |||
| 238 | F_CLR(gp, G_TMP_INUSE)(((gp)->flags) &= ~((0x0100))); | |||
| 239 | msgq(sp, M_ERR, | |||
| 240 | "vi: temporary buffer not released"); | |||
| 241 | } | |||
| 242 | #endif | |||
| 243 | /* | |||
| 244 | * If we're exiting this screen, move to the next one, or, if | |||
| 245 | * there aren't any more, return to the main editor loop. The | |||
| 246 | * ordering is careful, don't discard the contents of sp until | |||
| 247 | * the end. | |||
| 248 | */ | |||
| 249 | if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)(((sp)->flags) & ((0x00000200 | 0x00000400)))) { | |||
| 250 | if (file_end(sp, NULL((void *)0), F_ISSET(sp, SC_EXIT_FORCE)(((sp)->flags) & ((0x00000400))))) | |||
| 251 | goto ret; | |||
| 252 | if (vs_discard(sp, &next)) | |||
| 253 | goto ret; | |||
| 254 | if (next == NULL((void *)0) && vs_swap(sp, &next, NULL((void *)0))) | |||
| 255 | goto ret; | |||
| 256 | *spp = next; | |||
| 257 | if (screen_end(sp)) | |||
| 258 | goto ret; | |||
| 259 | if (next == NULL((void *)0)) | |||
| 260 | break; | |||
| 261 | ||||
| 262 | /* Switch screens, change focus. */ | |||
| 263 | sp = next; | |||
| 264 | vip = VIP(sp)((VI_PRIVATE *)((sp)->vi_private)); | |||
| 265 | (void)sp->gp->scr_rename(sp, sp->frp->name, 1); | |||
| 266 | ||||
| 267 | /* Don't trust the cursor. */ | |||
| 268 | F_SET(vip, VIP_CUR_INVALID)(((vip)->flags) |= ((0x0001))); | |||
| 269 | ||||
| 270 | continue; | |||
| 271 | } | |||
| 272 | ||||
| 273 | /* | |||
| 274 | * Set the dot command structure. | |||
| 275 | * | |||
| 276 | * !!! | |||
| 277 | * Historically, commands which used mapped keys did not | |||
| 278 | * set the dot command, with the exception of the text | |||
| 279 | * input commands. | |||
| 280 | */ | |||
| 281 | if (F_ISSET(vp, V_DOT)(((vp)->flags) & ((0x00080000))) && !mapped) { | |||
| 282 | *DOT(&((VI_PRIVATE *)((sp)->vi_private))->sdot) = cmd; | |||
| 283 | F_SET(DOT, VC_ISDOT)((((&((VI_PRIVATE *)((sp)->vi_private))->sdot))-> flags) |= ((0x00002000))); | |||
| 284 | ||||
| 285 | /* | |||
| 286 | * If a count was supplied for both the command and | |||
| 287 | * its motion, the count was used only for the motion. | |||
| 288 | * Turn the count back on for the dot structure. | |||
| 289 | */ | |||
| 290 | if (F_ISSET(vp, VC_C1RESET)(((vp)->flags) & ((0x00000400)))) | |||
| 291 | F_SET(DOT, VC_C1SET)((((&((VI_PRIVATE *)((sp)->vi_private))->sdot))-> flags) |= ((0x00000800))); | |||
| 292 | ||||
| 293 | /* VM flags aren't retained. */ | |||
| 294 | F_CLR(DOT, VM_COMMASK | VM_RCM_MASK)((((&((VI_PRIVATE *)((sp)->vi_private))->sdot))-> flags) &= ~((0x0000000f | 0x000001f0))); | |||
| 295 | } | |||
| 296 | ||||
| 297 | /* | |||
| 298 | * Some vi row movements are "attracted" to the last position | |||
| 299 | * set, i.e. the VM_RCM commands are moths to the VM_RCM_SET | |||
| 300 | * commands' candle. If the movement is to the EOL the vi | |||
| 301 | * command handles it. If it's to the beginning, we handle it | |||
| 302 | * here. | |||
| 303 | * | |||
| 304 | * Note, some commands (e.g. _, ^) don't set the VM_RCM_SETFNB | |||
| 305 | * flag, but do the work themselves. The reason is that they | |||
| 306 | * have to modify the column in case they're being used as a | |||
| 307 | * motion component. Other similar commands (e.g. +, -) don't | |||
| 308 | * have to modify the column because they are always line mode | |||
| 309 | * operations when used as motions, so the column number isn't | |||
| 310 | * of any interest. | |||
| 311 | * | |||
| 312 | * Does this totally violate the screen and editor layering? | |||
| 313 | * You betcha. As they say, if you think you understand it, | |||
| 314 | * you don't. | |||
| 315 | */ | |||
| 316 | switch (F_ISSET(vp, VM_RCM_MASK)(((vp)->flags) & ((0x000001f0)))) { | |||
| 317 | case 0: | |||
| 318 | case VM_RCM_SET0x00000020: | |||
| 319 | break; | |||
| 320 | case VM_RCM0x00000010: | |||
| 321 | vp->m_final.cno = vs_rcm(sp, | |||
| 322 | vp->m_final.lno, F_ISSET(vip, VIP_RCM_LAST)(((vip)->flags) & ((0x0040)))); | |||
| 323 | break; | |||
| 324 | case VM_RCM_SETLAST0x00000080: | |||
| 325 | F_SET(vip, VIP_RCM_LAST)(((vip)->flags) |= ((0x0040))); | |||
| 326 | break; | |||
| 327 | case VM_RCM_SETFNB0x00000040: | |||
| 328 | vp->m_final.cno = 0; | |||
| 329 | /* FALLTHROUGH */ | |||
| 330 | case VM_RCM_SETNNB0x00000100: | |||
| 331 | if (nonblank(sp, vp->m_final.lno, &vp->m_final.cno)) | |||
| 332 | goto err; | |||
| 333 | break; | |||
| 334 | default: | |||
| 335 | abort(); | |||
| 336 | } | |||
| 337 | ||||
| 338 | /* Update the cursor. */ | |||
| 339 | sp->lno = vp->m_final.lno; | |||
| 340 | sp->cno = vp->m_final.cno; | |||
| 341 | ||||
| 342 | /* | |||
| 343 | * Set the absolute mark -- set even if a tags or similar | |||
| 344 | * command, since the tag may be moving to the same file. | |||
| 345 | */ | |||
| 346 | if ((F_ISSET(vp, V_ABS)(((vp)->flags) & ((0x00004000))) || | |||
| 347 | (F_ISSET(vp, V_ABS_L)(((vp)->flags) & ((0x00010000))) && sp->lno != abs.lno) || | |||
| ||||
| 348 | (F_ISSET(vp, V_ABS_C)(((vp)->flags) & ((0x00008000))) && | |||
| 349 | (sp->lno != abs.lno || sp->cno != abs.cno))) && | |||
| 350 | mark_set(sp, ABSMARK1'\'', &abs, 1)) | |||
| 351 | goto err; | |||
| 352 | ||||
| 353 | if (0) { | |||
| 354 | err: if (v_event_flush(sp, CH_MAPPED0x02)) | |||
| 355 | msgq(sp, M_BERR, | |||
| 356 | "Vi command failed: mapped keys discarded"); | |||
| 357 | } | |||
| 358 | ||||
| 359 | /* | |||
| 360 | * Check and clear interrupts. There's an obvious race, but | |||
| 361 | * it's not worth fixing. | |||
| 362 | */ | |||
| 363 | gc_err_noflush: if (INTERRUPTED(sp)(((((sp)->gp)->flags) & ((0x0004))) || (!v_event_get ((sp), ((void *)0), 0, 0x001) && ((((sp)->gp)-> flags) & ((0x0004)))))) { | |||
| 364 | intr: CLR_INTERRUPT(sp)((((sp)->gp)->flags) &= ~((0x0004))); | |||
| 365 | if (v_event_flush(sp, CH_MAPPED0x02)) | |||
| 366 | msgq(sp, M_ERR, | |||
| 367 | "Interrupted: mapped keys discarded"); | |||
| 368 | else | |||
| 369 | msgq(sp, M_ERR, "Interrupted"); | |||
| 370 | } | |||
| 371 | ||||
| 372 | /* If the last command switched screens, update. */ | |||
| 373 | if (F_ISSET(sp, SC_SSWITCH)(((sp)->flags) & ((0x00001000)))) { | |||
| 374 | F_CLR(sp, SC_SSWITCH)(((sp)->flags) &= ~((0x00001000))); | |||
| 375 | ||||
| 376 | /* | |||
| 377 | * If the current screen is still displayed, it will | |||
| 378 | * need a new status line. | |||
| 379 | */ | |||
| 380 | F_SET(sp, SC_STATUS)(((sp)->flags) |= ((0x02000000))); | |||
| 381 | ||||
| 382 | /* Switch screens, change focus. */ | |||
| 383 | sp = sp->nextdisp; | |||
| 384 | vip = VIP(sp)((VI_PRIVATE *)((sp)->vi_private)); | |||
| 385 | (void)sp->gp->scr_rename(sp, sp->frp->name, 1); | |||
| 386 | ||||
| 387 | /* Don't trust the cursor. */ | |||
| 388 | F_SET(vip, VIP_CUR_INVALID)(((vip)->flags) |= ((0x0001))); | |||
| 389 | ||||
| 390 | /* Refresh so we can display messages. */ | |||
| 391 | if (vs_refresh(sp, 1)) | |||
| 392 | return (1); | |||
| 393 | } | |||
| 394 | ||||
| 395 | /* If the last command switched files, change focus. */ | |||
| 396 | if (F_ISSET(sp, SC_FSWITCH)(((sp)->flags) & ((0x00000800)))) { | |||
| 397 | F_CLR(sp, SC_FSWITCH)(((sp)->flags) &= ~((0x00000800))); | |||
| 398 | F_CLR(sp, SC_SCR_TOP)(((sp)->flags) &= ~((0x00000100))); | |||
| 399 | F_SET(sp, SC_SCR_CENTER)(((sp)->flags) |= ((0x00000080))); | |||
| 400 | (void)sp->gp->scr_rename(sp, sp->frp->name, 1); | |||
| 401 | } | |||
| 402 | ||||
| 403 | /* Sync recovery if changes were made. */ | |||
| 404 | if (F_ISSET(sp->ep, F_RCV_SYNC)(((sp->ep)->flags) & ((0x100)))) | |||
| 405 | rcv_sync(sp, 0); | |||
| 406 | ||||
| 407 | /* If leaving vi, return to the main editor loop. */ | |||
| 408 | if (F_ISSET(gp, G_SRESTART)(((gp)->flags) & ((0x0080))) || F_ISSET(sp, SC_EX)(((sp)->flags) & ((0x00000001)))) { | |||
| 409 | *spp = sp; | |||
| 410 | v_dtoh(sp); | |||
| 411 | break; | |||
| 412 | } | |||
| 413 | } | |||
| 414 | if (0) | |||
| 415 | ret: rval = 1; | |||
| 416 | return (rval); | |||
| 417 | } | |||
| 418 | ||||
| 419 | #define KEY(key, ec_flags){ if ((gcret = v_key(sp, 0, &ev, (ec_flags))) != GC_OK) return (gcret); if (ev._u_event._e_ch.value == K_ESCAPE) goto esc; if ((((&ev._u_event._e_ch)->flags) & ((0x02)))) *mappedp = 1; (key) = ev._u_event._e_ch.c; } { \ | |||
| 420 | if ((gcret = v_key(sp, 0, &ev, (ec_flags))) != GC_OK) \ | |||
| 421 | return (gcret); \ | |||
| 422 | if (ev.e_value_u_event._e_ch.value == K_ESCAPE) \ | |||
| 423 | goto esc; \ | |||
| 424 | if (F_ISSET(&ev.e_ch, CH_MAPPED)(((&ev._u_event._e_ch)->flags) & ((0x02)))) \ | |||
| 425 | *mappedp = 1; \ | |||
| 426 | (key) = ev.e_c_u_event._e_ch.c; \ | |||
| 427 | } | |||
| 428 | ||||
| 429 | /* | |||
| 430 | * The O_TILDEOP option makes the ~ command take a motion instead | |||
| 431 | * of a straight count. This is the replacement structure we use | |||
| 432 | * instead of the one currently in the VIKEYS table. | |||
| 433 | * | |||
| 434 | * XXX | |||
| 435 | * This should probably be deleted -- it's not all that useful, and | |||
| 436 | * we get help messages wrong. | |||
| 437 | */ | |||
| 438 | VIKEYS const tmotion = { | |||
| 439 | v_mulcase, V_CNT0x00040000|V_DOT0x00080000|V_MOTION0x00200000|VM_RCM_SET0x00000020, | |||
| 440 | "[count]~[count]motion", | |||
| 441 | " ~ change case to motion" | |||
| 442 | }; | |||
| 443 | ||||
| 444 | /* | |||
| 445 | * v_cmd -- | |||
| 446 | * | |||
| 447 | * The command structure for vi is less complex than ex (and don't think | |||
| 448 | * I'm not grateful!) The command syntax is: | |||
| 449 | * | |||
| 450 | * [count] [buffer] [count] key [[motion] | [buffer] [character]] | |||
| 451 | * | |||
| 452 | * and there are several special cases. The motion value is itself a vi | |||
| 453 | * command, with the syntax: | |||
| 454 | * | |||
| 455 | * [count] key [character] | |||
| 456 | */ | |||
| 457 | static gcret_t | |||
| 458 | v_cmd(SCR *sp, VICMD *dp, VICMD *vp, VICMD *ismotion, int *comcountp, | |||
| 459 | int *mappedp) | |||
| 460 | { | |||
| 461 | enum { COMMANDMODE, ISPARTIAL, NOTPARTIAL } cpart; | |||
| 462 | EVENT ev; | |||
| 463 | VIKEYS const *kp; | |||
| 464 | gcret_t gcret; | |||
| 465 | u_int flags; | |||
| 466 | CHAR_T key; | |||
| 467 | char *s; | |||
| 468 | ||||
| 469 | /* | |||
| 470 | * Get a key. | |||
| 471 | * | |||
| 472 | * <escape> cancels partial commands, i.e. a command where at least | |||
| 473 | * one non-numeric character has been entered. Otherwise, it beeps | |||
| 474 | * the terminal. | |||
| 475 | * | |||
| 476 | * !!! | |||
| 477 | * POSIX 1003.2-1992 explicitly disallows cancelling commands where | |||
| 478 | * all that's been entered is a number, requiring that the terminal | |||
| 479 | * be alerted. | |||
| 480 | */ | |||
| 481 | cpart = ismotion == NULL((void *)0) ? COMMANDMODE : ISPARTIAL; | |||
| 482 | if ((gcret = | |||
| 483 | v_key(sp, ismotion == NULL((void *)0), &ev, EC_MAPCOMMAND0x002)) != GC_OK) { | |||
| 484 | if (gcret == GC_EVENT) | |||
| 485 | vp->ev = ev; | |||
| 486 | return (gcret); | |||
| 487 | } | |||
| 488 | if (ev.e_value_u_event._e_ch.value == K_ESCAPE) | |||
| 489 | goto esc; | |||
| 490 | if (F_ISSET(&ev.e_ch, CH_MAPPED)(((&ev._u_event._e_ch)->flags) & ((0x02)))) | |||
| 491 | *mappedp = 1; | |||
| 492 | key = ev.e_c_u_event._e_ch.c; | |||
| 493 | ||||
| 494 | if (ismotion == NULL((void *)0)) | |||
| 495 | cpart = NOTPARTIAL; | |||
| 496 | ||||
| 497 | /* Pick up optional buffer. */ | |||
| 498 | if (key == '"') { | |||
| 499 | cpart = ISPARTIAL; | |||
| 500 | if (ismotion != NULL((void *)0)) { | |||
| 501 | v_emsg(sp, NULL((void *)0), VIM_COMBUF); | |||
| 502 | return (GC_ERR); | |||
| 503 | } | |||
| 504 | KEY(vp->buffer, 0){ if ((gcret = v_key(sp, 0, &ev, (0))) != GC_OK) return ( gcret); if (ev._u_event._e_ch.value == K_ESCAPE) goto esc; if ((((&ev._u_event._e_ch)->flags) & ((0x02)))) *mappedp = 1; (vp->buffer) = ev._u_event._e_ch.c; }; | |||
| 505 | F_SET(vp, VC_BUFFER)(((vp)->flags) |= ((0x00000200))); | |||
| 506 | ||||
| 507 | KEY(key, EC_MAPCOMMAND){ if ((gcret = v_key(sp, 0, &ev, (0x002))) != GC_OK) return (gcret); if (ev._u_event._e_ch.value == K_ESCAPE) goto esc; if ((((&ev._u_event._e_ch)->flags) & ((0x02)))) *mappedp = 1; (key) = ev._u_event._e_ch.c; }; | |||
| 508 | } | |||
| 509 | ||||
| 510 | /* | |||
| 511 | * Pick up optional count, where a leading 0 is not a count, | |||
| 512 | * it's a command. | |||
| 513 | */ | |||
| 514 | if (isdigit(key) && key != '0') { | |||
| 515 | if (v_count(sp, key, &vp->count)) | |||
| 516 | return (GC_ERR); | |||
| 517 | F_SET(vp, VC_C1SET)(((vp)->flags) |= ((0x00000800))); | |||
| 518 | *comcountp = 1; | |||
| 519 | ||||
| 520 | KEY(key, EC_MAPCOMMAND){ if ((gcret = v_key(sp, 0, &ev, (0x002))) != GC_OK) return (gcret); if (ev._u_event._e_ch.value == K_ESCAPE) goto esc; if ((((&ev._u_event._e_ch)->flags) & ((0x02)))) *mappedp = 1; (key) = ev._u_event._e_ch.c; }; | |||
| 521 | } else | |||
| 522 | *comcountp = 0; | |||
| 523 | ||||
| 524 | /* Pick up optional buffer. */ | |||
| 525 | if (key == '"') { | |||
| 526 | cpart = ISPARTIAL; | |||
| 527 | if (F_ISSET(vp, VC_BUFFER)(((vp)->flags) & ((0x00000200)))) { | |||
| 528 | msgq(sp, M_ERR, "Only one buffer may be specified"); | |||
| 529 | return (GC_ERR); | |||
| 530 | } | |||
| 531 | if (ismotion != NULL((void *)0)) { | |||
| 532 | v_emsg(sp, NULL((void *)0), VIM_COMBUF); | |||
| 533 | return (GC_ERR); | |||
| 534 | } | |||
| 535 | KEY(vp->buffer, 0){ if ((gcret = v_key(sp, 0, &ev, (0))) != GC_OK) return ( gcret); if (ev._u_event._e_ch.value == K_ESCAPE) goto esc; if ((((&ev._u_event._e_ch)->flags) & ((0x02)))) *mappedp = 1; (vp->buffer) = ev._u_event._e_ch.c; }; | |||
| 536 | F_SET(vp, VC_BUFFER)(((vp)->flags) |= ((0x00000200))); | |||
| 537 | ||||
| 538 | KEY(key, EC_MAPCOMMAND){ if ((gcret = v_key(sp, 0, &ev, (0x002))) != GC_OK) return (gcret); if (ev._u_event._e_ch.value == K_ESCAPE) goto esc; if ((((&ev._u_event._e_ch)->flags) & ((0x02)))) *mappedp = 1; (key) = ev._u_event._e_ch.c; }; | |||
| 539 | } | |||
| 540 | ||||
| 541 | /* Check for an OOB command key. */ | |||
| 542 | cpart = ISPARTIAL; | |||
| 543 | if (key > MAXVIKEY126) { | |||
| 544 | v_emsg(sp, KEY_NAME(sp, key)((unsigned char)(key) <= 254 ? (sp)->gp->cname[(unsigned char)(key)].name : v_key_name((sp), (key))), VIM_NOCOM); | |||
| 545 | return (GC_ERR); | |||
| 546 | } | |||
| 547 | kp = &vikeys[vp->key = key]; | |||
| 548 | ||||
| 549 | /* | |||
| 550 | * !!! | |||
| 551 | * Historically, D accepted and then ignored a count. Match it. | |||
| 552 | */ | |||
| 553 | if (vp->key == 'D' && F_ISSET(vp, VC_C1SET)(((vp)->flags) & ((0x00000800)))) { | |||
| 554 | *comcountp = 0; | |||
| 555 | vp->count = 0; | |||
| 556 | F_CLR(vp, VC_C1SET)(((vp)->flags) &= ~((0x00000800))); | |||
| 557 | } | |||
| 558 | ||||
| 559 | /* Check for command aliases. */ | |||
| 560 | if (kp->func == NULL((void *)0) && (kp = v_alias(sp, vp, kp)) == NULL((void *)0)) | |||
| 561 | return (GC_ERR); | |||
| 562 | ||||
| 563 | /* The tildeop option makes the ~ command take a motion. */ | |||
| 564 | if (key == '~' && O_ISSET(sp, O_TILDEOP)((((&(((sp)))->opts[(((O_TILDEOP)))])->flags) & ((0x01))) ? (((sp)))->gp->opts[(((sp)))->opts[(((O_TILDEOP )))].o_cur.val].o_cur.val : (((sp)))->opts[(((O_TILDEOP))) ].o_cur.val)) | |||
| 565 | kp = &tmotion; | |||
| 566 | ||||
| 567 | vp->kp = kp; | |||
| 568 | ||||
| 569 | /* | |||
| 570 | * Find the command. The only legal command with no underlying | |||
| 571 | * function is dot. It's historic practice that <escape> doesn't | |||
| 572 | * just erase the preceding number, it beeps the terminal as well. | |||
| 573 | * It's a common problem, so just beep the terminal unless verbose | |||
| 574 | * was set. | |||
| 575 | */ | |||
| 576 | if (kp->func == NULL((void *)0)) { | |||
| 577 | if (key != '.') { | |||
| 578 | v_emsg(sp, KEY_NAME(sp, key)((unsigned char)(key) <= 254 ? (sp)->gp->cname[(unsigned char)(key)].name : v_key_name((sp), (key))), | |||
| 579 | ev.e_value_u_event._e_ch.value == K_ESCAPE ? VIM_NOCOM_B : VIM_NOCOM); | |||
| 580 | return (GC_ERR); | |||
| 581 | } | |||
| 582 | ||||
| 583 | /* If called for a motion command, stop now. */ | |||
| 584 | if (dp == NULL((void *)0)) | |||
| 585 | goto usage; | |||
| 586 | ||||
| 587 | /* | |||
| 588 | * !!! | |||
| 589 | * If a '.' is immediately entered after an undo command, we | |||
| 590 | * replay the log instead of redoing the last command. This | |||
| 591 | * is necessary because 'u' can't set the dot command -- see | |||
| 592 | * vi/v_undo.c:v_undo for details. | |||
| 593 | */ | |||
| 594 | if (VIP(sp)((VI_PRIVATE *)((sp)->vi_private))->u_ccnt == sp->ccnt) { | |||
| 595 | vp->kp = &vikeys['u']; | |||
| 596 | F_SET(vp, VC_ISDOT)(((vp)->flags) |= ((0x00002000))); | |||
| 597 | return (GC_OK); | |||
| 598 | } | |||
| 599 | ||||
| 600 | /* Otherwise, a repeatable command must have been executed. */ | |||
| 601 | if (!F_ISSET(dp, VC_ISDOT)(((dp)->flags) & ((0x00002000)))) { | |||
| 602 | msgq(sp, M_ERR, "No command to repeat"); | |||
| 603 | return (GC_ERR); | |||
| 604 | } | |||
| 605 | ||||
| 606 | /* Set new count/buffer, if any, and return. */ | |||
| 607 | if (F_ISSET(vp, VC_C1SET)(((vp)->flags) & ((0x00000800)))) { | |||
| 608 | F_SET(dp, VC_C1SET)(((dp)->flags) |= ((0x00000800))); | |||
| 609 | dp->count = vp->count; | |||
| 610 | } | |||
| 611 | if (F_ISSET(vp, VC_BUFFER)(((vp)->flags) & ((0x00000200)))) | |||
| 612 | dp->buffer = vp->buffer; | |||
| 613 | ||||
| 614 | *vp = *dp; | |||
| 615 | return (GC_OK); | |||
| 616 | } | |||
| 617 | ||||
| 618 | /* Set the flags based on the command flags. */ | |||
| 619 | flags = kp->flags; | |||
| 620 | ||||
| 621 | /* Check for illegal count. */ | |||
| 622 | if (F_ISSET(vp, VC_C1SET)(((vp)->flags) & ((0x00000800))) && !LF_ISSET(V_CNT)((flags) & ((0x00040000)))) | |||
| 623 | goto usage; | |||
| 624 | ||||
| 625 | /* Illegal motion command. */ | |||
| 626 | if (ismotion == NULL((void *)0)) { | |||
| 627 | /* Illegal buffer. */ | |||
| 628 | if (!LF_ISSET(V_OBUF)((flags) & ((0x00800000))) && F_ISSET(vp, VC_BUFFER)(((vp)->flags) & ((0x00000200)))) | |||
| 629 | goto usage; | |||
| 630 | ||||
| 631 | /* Required buffer. */ | |||
| 632 | if (LF_ISSET(V_RBUF)((flags) & ((0x01000000)))) { | |||
| 633 | KEY(vp->buffer, 0){ if ((gcret = v_key(sp, 0, &ev, (0))) != GC_OK) return ( gcret); if (ev._u_event._e_ch.value == K_ESCAPE) goto esc; if ((((&ev._u_event._e_ch)->flags) & ((0x02)))) *mappedp = 1; (vp->buffer) = ev._u_event._e_ch.c; }; | |||
| 634 | F_SET(vp, VC_BUFFER)(((vp)->flags) |= ((0x00000200))); | |||
| 635 | } | |||
| 636 | } | |||
| 637 | ||||
| 638 | /* | |||
| 639 | * Special case: '[', ']' and 'Z' commands. Doesn't the fact that | |||
| 640 | * the *single* characters don't mean anything but the *doubled* | |||
| 641 | * characters do, just frost your shorts? | |||
| 642 | */ | |||
| 643 | if (vp->key == '[' || vp->key == ']' || vp->key == 'Z') { | |||
| 644 | /* | |||
| 645 | * Historically, half entered [[, ]] or Z commands weren't | |||
| 646 | * cancelled by <escape>, the terminal was beeped instead. | |||
| 647 | * POSIX.2-1992 probably didn't notice, and requires that | |||
| 648 | * they be cancelled instead of beeping. Seems fine to me. | |||
| 649 | * | |||
| 650 | * Don't set the EC_MAPCOMMAND flag, apparently ] is a popular | |||
| 651 | * vi meta-character, and we don't want the user to wait while | |||
| 652 | * we time out a possible mapping. This *appears* to match | |||
| 653 | * historic vi practice, but with mapping characters, you Just | |||
| 654 | * Never Know. | |||
| 655 | */ | |||
| 656 | KEY(key, 0){ if ((gcret = v_key(sp, 0, &ev, (0))) != GC_OK) return ( gcret); if (ev._u_event._e_ch.value == K_ESCAPE) goto esc; if ((((&ev._u_event._e_ch)->flags) & ((0x02)))) *mappedp = 1; (key) = ev._u_event._e_ch.c; }; | |||
| 657 | ||||
| 658 | if (vp->key != key) { | |||
| 659 | usage: if (ismotion == NULL((void *)0)) | |||
| 660 | s = kp->usage; | |||
| 661 | else if (ismotion->key == '~' && O_ISSET(sp, O_TILDEOP)((((&(((sp)))->opts[(((O_TILDEOP)))])->flags) & ((0x01))) ? (((sp)))->gp->opts[(((sp)))->opts[(((O_TILDEOP )))].o_cur.val].o_cur.val : (((sp)))->opts[(((O_TILDEOP))) ].o_cur.val)) | |||
| 662 | s = tmotion.usage; | |||
| 663 | else | |||
| 664 | s = vikeys[ismotion->key].usage; | |||
| 665 | v_emsg(sp, s, VIM_USAGE); | |||
| 666 | return (GC_ERR); | |||
| 667 | } | |||
| 668 | } | |||
| 669 | /* Special case: 'z' command. */ | |||
| 670 | if (vp->key == 'z') { | |||
| 671 | KEY(vp->character, 0){ if ((gcret = v_key(sp, 0, &ev, (0))) != GC_OK) return ( gcret); if (ev._u_event._e_ch.value == K_ESCAPE) goto esc; if ((((&ev._u_event._e_ch)->flags) & ((0x02)))) *mappedp = 1; (vp->character) = ev._u_event._e_ch.c; }; | |||
| 672 | if (isdigit(vp->character)) { | |||
| 673 | if (v_count(sp, vp->character, &vp->count2)) | |||
| 674 | return (GC_ERR); | |||
| 675 | F_SET(vp, VC_C2SET)(((vp)->flags) |= ((0x00001000))); | |||
| 676 | KEY(vp->character, 0){ if ((gcret = v_key(sp, 0, &ev, (0))) != GC_OK) return ( gcret); if (ev._u_event._e_ch.value == K_ESCAPE) goto esc; if ((((&ev._u_event._e_ch)->flags) & ((0x02)))) *mappedp = 1; (vp->character) = ev._u_event._e_ch.c; }; | |||
| 677 | } | |||
| 678 | } | |||
| 679 | ||||
| 680 | /* | |||
| 681 | * Commands that have motion components can be doubled to | |||
| 682 | * imply the current line. | |||
| 683 | */ | |||
| 684 | if (ismotion != NULL((void *)0) && ismotion->key != key && !LF_ISSET(V_MOVE)((flags) & ((0x00400000)))) { | |||
| 685 | msgq(sp, M_ERR, "%s may not be used as a motion command", | |||
| 686 | KEY_NAME(sp, key)((unsigned char)(key) <= 254 ? (sp)->gp->cname[(unsigned char)(key)].name : v_key_name((sp), (key)))); | |||
| 687 | return (GC_ERR); | |||
| 688 | } | |||
| 689 | ||||
| 690 | /* Required character. */ | |||
| 691 | if (LF_ISSET(V_CHAR)((flags) & ((0x00020000)))) | |||
| 692 | KEY(vp->character, 0){ if ((gcret = v_key(sp, 0, &ev, (0))) != GC_OK) return ( gcret); if (ev._u_event._e_ch.value == K_ESCAPE) goto esc; if ((((&ev._u_event._e_ch)->flags) & ((0x02)))) *mappedp = 1; (vp->character) = ev._u_event._e_ch.c; }; | |||
| 693 | ||||
| 694 | /* Get any associated cursor word. */ | |||
| 695 | if (F_ISSET(kp, V_KEYW)(((kp)->flags) & ((0x00100000))) && v_keyword(sp)) | |||
| 696 | return (GC_ERR); | |||
| 697 | ||||
| 698 | return (GC_OK); | |||
| 699 | ||||
| 700 | esc: switch (cpart) { | |||
| 701 | case COMMANDMODE: | |||
| 702 | msgq(sp, M_BERR, "Already in command mode"); | |||
| 703 | return (GC_ERR_NOFLUSH); | |||
| 704 | case ISPARTIAL: | |||
| 705 | break; | |||
| 706 | case NOTPARTIAL: | |||
| 707 | (void)sp->gp->scr_bell(sp); | |||
| 708 | break; | |||
| 709 | } | |||
| 710 | return (GC_ERR); | |||
| 711 | } | |||
| 712 | ||||
| 713 | /* | |||
| 714 | * v_motion -- | |||
| 715 | * | |||
| 716 | * Get resulting motion mark. | |||
| 717 | */ | |||
| 718 | static int | |||
| 719 | v_motion(SCR *sp, VICMD *dm, VICMD *vp, int *mappedp) | |||
| 720 | { | |||
| 721 | VICMD motion; | |||
| 722 | size_t len; | |||
| 723 | u_long cnt; | |||
| 724 | u_int flags; | |||
| 725 | int tilde_reset, notused; | |||
| 726 | ||||
| 727 | /* | |||
| 728 | * If '.' command, use the dot motion, else get the motion command. | |||
| 729 | * Clear any line motion flags, the subsequent motion isn't always | |||
| 730 | * the same, i.e. "/aaa" may or may not be a line motion. | |||
| 731 | */ | |||
| 732 | if (F_ISSET(vp, VC_ISDOT)(((vp)->flags) & ((0x00002000)))) { | |||
| 733 | motion = *dm; | |||
| 734 | F_SET(&motion, VC_ISDOT)(((&motion)->flags) |= ((0x00002000))); | |||
| 735 | F_CLR(&motion, VM_COMMASK)(((&motion)->flags) &= ~((0x0000000f))); | |||
| 736 | } else { | |||
| 737 | memset(&motion, 0, sizeof(VICMD)); | |||
| 738 | if (v_cmd(sp, NULL((void *)0), &motion, vp, ¬used, mappedp) != GC_OK) | |||
| 739 | return (1); | |||
| 740 | } | |||
| 741 | ||||
| 742 | /* | |||
| 743 | * A count may be provided both to the command and to the motion, in | |||
| 744 | * which case the count is multiplicative. For example, "3y4y" is the | |||
| 745 | * same as "12yy". This count is provided to the motion command and | |||
| 746 | * not to the regular function. | |||
| 747 | */ | |||
| 748 | cnt = motion.count = F_ISSET(&motion, VC_C1SET)(((&motion)->flags) & ((0x00000800))) ? motion.count : 1; | |||
| 749 | if (F_ISSET(vp, VC_C1SET)(((vp)->flags) & ((0x00000800)))) { | |||
| 750 | motion.count *= vp->count; | |||
| 751 | F_SET(&motion, VC_C1SET)(((&motion)->flags) |= ((0x00000800))); | |||
| 752 | ||||
| 753 | /* | |||
| 754 | * Set flags to restore the original values of the command | |||
| 755 | * structure so dot commands can change the count values, | |||
| 756 | * e.g. "2dw" "3." deletes a total of five words. | |||
| 757 | */ | |||
| 758 | F_CLR(vp, VC_C1SET)(((vp)->flags) &= ~((0x00000800))); | |||
| 759 | F_SET(vp, VC_C1RESET)(((vp)->flags) |= ((0x00000400))); | |||
| 760 | } | |||
| 761 | ||||
| 762 | /* | |||
| 763 | * Some commands can be repeated to indicate the current line. In | |||
| 764 | * this case, or if the command is a "line command", set the flags | |||
| 765 | * appropriately. If not a doubled command, run the function to get | |||
| 766 | * the resulting mark. | |||
| 767 | */ | |||
| 768 | if (vp->key == motion.key) { | |||
| 769 | F_SET(vp, VM_LDOUBLE | VM_LMODE)(((vp)->flags) |= ((0x00000004 | 0x00000008))); | |||
| 770 | ||||
| 771 | /* Set the origin of the command. */ | |||
| 772 | vp->m_start.lno = sp->lno; | |||
| 773 | vp->m_start.cno = 0; | |||
| 774 | ||||
| 775 | /* | |||
| 776 | * Set the end of the command. | |||
| 777 | * | |||
| 778 | * If the current line is missing, i.e. the file is empty, | |||
| 779 | * historic vi permitted a "cc" or "!!" command to insert | |||
| 780 | * text. | |||
| 781 | */ | |||
| 782 | vp->m_stop.lno = sp->lno + motion.count - 1; | |||
| 783 | if (db_get(sp, vp->m_stop.lno, 0, NULL((void *)0), &len)) { | |||
| 784 | if (vp->m_stop.lno != 1 || | |||
| 785 | (vp->key != 'c' && vp->key != '!')) { | |||
| 786 | v_emsg(sp, NULL((void *)0), VIM_EMPTY); | |||
| 787 | return (1); | |||
| 788 | } | |||
| 789 | vp->m_stop.cno = 0; | |||
| 790 | } else | |||
| 791 | vp->m_stop.cno = len ? len - 1 : 0; | |||
| 792 | } else { | |||
| 793 | /* | |||
| 794 | * Motion commands change the underlying movement (*snarl*). | |||
| 795 | * For example, "l" is illegal at the end of a line, but "dl" | |||
| 796 | * is not. Set flags so the function knows the situation. | |||
| 797 | */ | |||
| 798 | motion.rkp = vp->kp; | |||
| 799 | ||||
| 800 | /* | |||
| 801 | * XXX | |||
| 802 | * Use yank instead of creating a new motion command, it's a | |||
| 803 | * lot easier for now. | |||
| 804 | */ | |||
| 805 | if (vp->kp == &tmotion) { | |||
| 806 | tilde_reset = 1; | |||
| 807 | vp->kp = &vikeys['y']; | |||
| 808 | } else | |||
| 809 | tilde_reset = 0; | |||
| 810 | ||||
| 811 | /* | |||
| 812 | * Copy the key flags into the local structure, except for the | |||
| 813 | * RCM flags -- the motion command will set the RCM flags in | |||
| 814 | * the vp structure if necessary. This means that the motion | |||
| 815 | * command is expected to determine where the cursor ends up! | |||
| 816 | * However, we save off the current RCM mask and restore it if | |||
| 817 | * it no RCM flags are set by the motion command, with a small | |||
| 818 | * modification. | |||
| 819 | * | |||
| 820 | * We replace the VM_RCM_SET flag with the VM_RCM flag. This | |||
| 821 | * is so that cursor movement doesn't set the relative position | |||
| 822 | * unless the motion command explicitly specified it. This | |||
| 823 | * appears to match historic practice, but I've never been able | |||
| 824 | * to develop a hard-and-fast rule. | |||
| 825 | */ | |||
| 826 | flags = F_ISSET(vp, VM_RCM_MASK)(((vp)->flags) & ((0x000001f0))); | |||
| 827 | if (LF_ISSET(VM_RCM_SET)((flags) & ((0x00000020)))) { | |||
| 828 | LF_SET(VM_RCM)((flags) |= ((0x00000010))); | |||
| 829 | LF_CLR(VM_RCM_SET)((flags) &= ~((0x00000020))); | |||
| 830 | } | |||
| 831 | F_CLR(vp, VM_RCM_MASK)(((vp)->flags) &= ~((0x000001f0))); | |||
| 832 | F_SET(&motion, motion.kp->flags & ~VM_RCM_MASK)(((&motion)->flags) |= ((motion.kp->flags & ~0x000001f0 ))); | |||
| 833 | ||||
| 834 | /* | |||
| 835 | * Set the three cursor locations to the current cursor. This | |||
| 836 | * permits commands like 'j' and 'k', that are line oriented | |||
| 837 | * motions and have special cursor suck semantics when they are | |||
| 838 | * used as standalone commands, to ignore column positioning. | |||
| 839 | */ | |||
| 840 | motion.m_final.lno = | |||
| 841 | motion.m_stop.lno = motion.m_start.lno = sp->lno; | |||
| 842 | motion.m_final.cno = | |||
| 843 | motion.m_stop.cno = motion.m_start.cno = sp->cno; | |||
| 844 | ||||
| 845 | /* Run the function. */ | |||
| 846 | if ((motion.kp->func)(sp, &motion)) | |||
| 847 | return (1); | |||
| 848 | ||||
| 849 | /* | |||
| 850 | * If the current line is missing, i.e. the file is empty, | |||
| 851 | * historic vi allowed "c<motion>" or "!<motion>" to insert | |||
| 852 | * text. Otherwise fail -- most motion commands will have | |||
| 853 | * already failed, but some, e.g. G, succeed in empty files. | |||
| 854 | */ | |||
| 855 | if (!db_exist(sp, vp->m_stop.lno)) { | |||
| 856 | if (vp->m_stop.lno != 1 || | |||
| 857 | (vp->key != 'c' && vp->key != '!')) { | |||
| 858 | v_emsg(sp, NULL((void *)0), VIM_EMPTY); | |||
| 859 | return (1); | |||
| 860 | } | |||
| 861 | vp->m_stop.cno = 0; | |||
| 862 | } | |||
| 863 | ||||
| 864 | /* | |||
| 865 | * XXX | |||
| 866 | * See above. | |||
| 867 | */ | |||
| 868 | if (tilde_reset) | |||
| 869 | vp->kp = &tmotion; | |||
| 870 | ||||
| 871 | /* | |||
| 872 | * Copy cut buffer, line mode and cursor position information | |||
| 873 | * from the motion command structure, i.e. anything that the | |||
| 874 | * motion command can set for us. The commands can flag the | |||
| 875 | * movement as a line motion (see v_sentence) as well as set | |||
| 876 | * the VM_RCM_* flags explicitly. | |||
| 877 | */ | |||
| 878 | F_SET(vp, F_ISSET(&motion, VM_COMMASK | VM_RCM_MASK))(((vp)->flags) |= (((((&motion)->flags) & ((0x0000000f | 0x000001f0)))))); | |||
| 879 | ||||
| 880 | /* | |||
| 881 | * If the motion command set no relative motion flags, use | |||
| 882 | * the (slightly) modified previous values. | |||
| 883 | */ | |||
| 884 | if (!F_ISSET(vp, VM_RCM_MASK)(((vp)->flags) & ((0x000001f0)))) | |||
| 885 | F_SET(vp, flags)(((vp)->flags) |= ((flags))); | |||
| 886 | ||||
| 887 | /* | |||
| 888 | * Commands can change behaviors based on the motion command | |||
| 889 | * used, for example, the ! command repeated the last bang | |||
| 890 | * command if N or n was used as the motion. | |||
| 891 | */ | |||
| 892 | vp->rkp = motion.kp; | |||
| 893 | ||||
| 894 | /* | |||
| 895 | * Motion commands can reset all of the cursor information. | |||
| 896 | * If the motion is in the reverse direction, switch the | |||
| 897 | * from and to MARK's so that it's in a forward direction. | |||
| 898 | * Motions are from the from MARK to the to MARK (inclusive). | |||
| 899 | */ | |||
| 900 | if (motion.m_start.lno > motion.m_stop.lno || | |||
| 901 | (motion.m_start.lno == motion.m_stop.lno && | |||
| 902 | motion.m_start.cno > motion.m_stop.cno)) { | |||
| 903 | vp->m_start = motion.m_stop; | |||
| 904 | vp->m_stop = motion.m_start; | |||
| 905 | } else { | |||
| 906 | vp->m_start = motion.m_start; | |||
| 907 | vp->m_stop = motion.m_stop; | |||
| 908 | } | |||
| 909 | vp->m_final = motion.m_final; | |||
| 910 | } | |||
| 911 | ||||
| 912 | /* | |||
| 913 | * If the command sets dot, save the motion structure. The motion | |||
| 914 | * count was changed above and needs to be reset, that's why this | |||
| 915 | * is done here, and not in the calling routine. | |||
| 916 | */ | |||
| 917 | if (F_ISSET(vp->kp, V_DOT)(((vp->kp)->flags) & ((0x00080000)))) { | |||
| 918 | *dm = motion; | |||
| 919 | dm->count = cnt; | |||
| 920 | } | |||
| 921 | return (0); | |||
| 922 | } | |||
| 923 | ||||
| 924 | /* | |||
| 925 | * v_init -- | |||
| 926 | * Initialize the vi screen. | |||
| 927 | */ | |||
| 928 | static int | |||
| 929 | v_init(SCR *sp) | |||
| 930 | { | |||
| 931 | GS *gp; | |||
| 932 | VI_PRIVATE *vip; | |||
| 933 | ||||
| 934 | gp = sp->gp; | |||
| 935 | vip = VIP(sp)((VI_PRIVATE *)((sp)->vi_private)); | |||
| 936 | ||||
| 937 | /* Switch into vi. */ | |||
| 938 | if (gp->scr_screen(sp, SC_VI0x00000002)) | |||
| 939 | return (1); | |||
| 940 | (void)gp->scr_attr(sp, SA_ALTERNATE, 1); | |||
| 941 | ||||
| 942 | F_CLR(sp, SC_EX | SC_SCR_EX)(((sp)->flags) &= ~((0x00000001 | 0x00000004))); | |||
| 943 | F_SET(sp, SC_VI)(((sp)->flags) |= ((0x00000002))); | |||
| 944 | ||||
| 945 | /* | |||
| 946 | * Initialize screen values. | |||
| 947 | * | |||
| 948 | * Small windows: see vs_refresh(), section 6a. | |||
| 949 | * | |||
| 950 | * Setup: | |||
| 951 | * t_minrows is the minimum rows to display | |||
| 952 | * t_maxrows is the maximum rows to display (rows - 1) | |||
| 953 | * t_rows is the rows currently being displayed | |||
| 954 | */ | |||
| 955 | sp->rows = vip->srows = O_VAL(sp, O_LINES)((((&((sp))->opts[((O_LINES))])->flags) & ((0x01 ))) ? ((sp))->gp->opts[((sp))->opts[((O_LINES))].o_cur .val].o_cur.val : ((sp))->opts[((O_LINES))].o_cur.val); | |||
| 956 | sp->cols = O_VAL(sp, O_COLUMNS)((((&((sp))->opts[((O_COLUMNS))])->flags) & ((0x01 ))) ? ((sp))->gp->opts[((sp))->opts[((O_COLUMNS))].o_cur .val].o_cur.val : ((sp))->opts[((O_COLUMNS))].o_cur.val); | |||
| 957 | sp->t_rows = sp->t_minrows = O_VAL(sp, O_WINDOW)((((&((sp))->opts[((O_WINDOW))])->flags) & ((0x01 ))) ? ((sp))->gp->opts[((sp))->opts[((O_WINDOW))].o_cur .val].o_cur.val : ((sp))->opts[((O_WINDOW))].o_cur.val); | |||
| 958 | if (sp->rows != 1) { | |||
| 959 | if (sp->t_rows > sp->rows - 1) { | |||
| 960 | sp->t_minrows = sp->t_rows = sp->rows - 1; | |||
| 961 | msgq(sp, M_INFO, | |||
| 962 | "Windows option value is too large, max is %u", | |||
| 963 | sp->t_rows); | |||
| 964 | } | |||
| 965 | sp->t_maxrows = sp->rows - 1; | |||
| 966 | } else | |||
| 967 | sp->t_maxrows = 1; | |||
| 968 | sp->woff = 0; | |||
| 969 | ||||
| 970 | /* Create a screen map. */ | |||
| 971 | CALLOC_RET(sp, HMAP, SIZE_HMAP(sp), sizeof(SMAP)){ if ((((((VI_PRIVATE *)((sp)->vi_private))->h_smap)) = calloc(((((VI_PRIVATE *)((sp)->vi_private))->srows + 1 )), (sizeof(SMAP)))) == ((void *)0)) { msgq((sp), M_SYSERR, ( (void *)0)); return (1); } }; | |||
| 972 | TMAP(((VI_PRIVATE *)((sp)->vi_private))->t_smap) = HMAP(((VI_PRIVATE *)((sp)->vi_private))->h_smap) + (sp->t_rows - 1); | |||
| 973 | HMAP(((VI_PRIVATE *)((sp)->vi_private))->h_smap)->lno = sp->lno; | |||
| 974 | HMAP(((VI_PRIVATE *)((sp)->vi_private))->h_smap)->coff = 0; | |||
| 975 | HMAP(((VI_PRIVATE *)((sp)->vi_private))->h_smap)->soff = 1; | |||
| 976 | ||||
| 977 | /* | |||
| 978 | * Fill the screen map from scratch -- try and center the line. That | |||
| 979 | * way if we're starting with a file we've seen before, we'll put the | |||
| 980 | * line in the middle, otherwise, it won't work and we'll end up with | |||
| 981 | * the line at the top. | |||
| 982 | */ | |||
| 983 | F_CLR(sp, SC_SCR_TOP)(((sp)->flags) &= ~((0x00000100))); | |||
| 984 | F_SET(sp, SC_SCR_REFORMAT | SC_SCR_CENTER)(((sp)->flags) |= ((0x00000020 | 0x00000080))); | |||
| 985 | ||||
| 986 | /* Invalidate the cursor. */ | |||
| 987 | F_SET(vip, VIP_CUR_INVALID)(((vip)->flags) |= ((0x0001))); | |||
| 988 | ||||
| 989 | /* Paint the screen image from scratch. */ | |||
| 990 | F_SET(vip, VIP_N_EX_PAINT)(((vip)->flags) |= ((0x0004))); | |||
| 991 | ||||
| 992 | return (0); | |||
| 993 | } | |||
| 994 | ||||
| 995 | /* | |||
| 996 | * v_dtoh -- | |||
| 997 | * Move all but the current screen to the hidden queue. | |||
| 998 | */ | |||
| 999 | static void | |||
| 1000 | v_dtoh(SCR *sp) | |||
| 1001 | { | |||
| 1002 | GS *gp; | |||
| 1003 | SCR *tsp; | |||
| 1004 | int hidden; | |||
| 1005 | ||||
| 1006 | /* Move all screens to the hidden queue, tossing screen maps. */ | |||
| 1007 | hidden = 0; | |||
| 1008 | gp = sp->gp; | |||
| 1009 | while ((tsp = TAILQ_FIRST(&gp->dq)((&gp->dq)->tqh_first))) { | |||
| 1010 | free(_HMAP(tsp)(((VI_PRIVATE *)((tsp)->vi_private))->h_smap)); | |||
| 1011 | _HMAP(tsp)(((VI_PRIVATE *)((tsp)->vi_private))->h_smap) = NULL((void *)0); | |||
| 1012 | TAILQ_REMOVE(&gp->dq, tsp, q)do { if (((tsp)->q.tqe_next) != ((void *)0)) (tsp)->q.tqe_next ->q.tqe_prev = (tsp)->q.tqe_prev; else (&gp->dq) ->tqh_last = (tsp)->q.tqe_prev; *(tsp)->q.tqe_prev = (tsp)->q.tqe_next; ; ; } while (0); | |||
| 1013 | TAILQ_INSERT_TAIL(&gp->hq, tsp, q)do { (tsp)->q.tqe_next = ((void *)0); (tsp)->q.tqe_prev = (&gp->hq)->tqh_last; *(&gp->hq)->tqh_last = (tsp); (&gp->hq)->tqh_last = &(tsp)->q.tqe_next ; } while (0); | |||
| 1014 | ++hidden; | |||
| 1015 | } | |||
| 1016 | ||||
| 1017 | /* Move current screen back to the display queue. */ | |||
| 1018 | TAILQ_REMOVE(&gp->hq, sp, q)do { if (((sp)->q.tqe_next) != ((void *)0)) (sp)->q.tqe_next ->q.tqe_prev = (sp)->q.tqe_prev; else (&gp->hq)-> tqh_last = (sp)->q.tqe_prev; *(sp)->q.tqe_prev = (sp)-> q.tqe_next; ; ; } while (0); | |||
| 1019 | TAILQ_INSERT_TAIL(&gp->dq, sp, q)do { (sp)->q.tqe_next = ((void *)0); (sp)->q.tqe_prev = (&gp->dq)->tqh_last; *(&gp->dq)->tqh_last = (sp); (&gp->dq)->tqh_last = &(sp)->q.tqe_next ; } while (0); | |||
| 1020 | ||||
| 1021 | /* | |||
| 1022 | * XXX | |||
| 1023 | * Don't bother internationalizing this message, it's going to | |||
| 1024 | * go away as soon as we have one-line screens. --TK | |||
| 1025 | */ | |||
| 1026 | if (hidden > 1) | |||
| 1027 | msgq(sp, M_INFO, | |||
| 1028 | "%d screens backgrounded; use :display to list them", | |||
| 1029 | hidden - 1); | |||
| 1030 | } | |||
| 1031 | ||||
| 1032 | /* | |||
| 1033 | * v_keyword -- | |||
| 1034 | * Get the word (or non-word) the cursor is on. | |||
| 1035 | */ | |||
| 1036 | static int | |||
| 1037 | v_keyword(SCR *sp) | |||
| 1038 | { | |||
| 1039 | VI_PRIVATE *vip; | |||
| 1040 | size_t beg, end, len; | |||
| 1041 | int moved, state; | |||
| 1042 | char *p; | |||
| 1043 | ||||
| 1044 | if (db_get(sp, sp->lno, DBG_FATAL0x001, &p, &len)) | |||
| 1045 | return (1); | |||
| 1046 | ||||
| 1047 | /* | |||
| 1048 | * !!! | |||
| 1049 | * Historically, tag commands skipped over any leading whitespace | |||
| 1050 | * characters. Make this true in general when using cursor words. | |||
| 1051 | * If movement, getting a cursor word implies moving the cursor to | |||
| 1052 | * its beginning. Refresh now. | |||
| 1053 | * | |||
| 1054 | * !!! | |||
| 1055 | * Find the beginning/end of the keyword. Keywords are currently | |||
| 1056 | * used for cursor-word searching and for tags. Historical vi | |||
| 1057 | * only used the word in a tag search from the cursor to the end | |||
| 1058 | * of the word, i.e. if the cursor was on the 'b' in " abc ", the | |||
| 1059 | * tag was "bc". For consistency, we make cursor word searches | |||
| 1060 | * follow the same rule. | |||
| 1061 | */ | |||
| 1062 | for (moved = 0, | |||
| 1063 | beg = sp->cno; beg < len && isspace(p[beg]); moved = 1, ++beg); | |||
| 1064 | if (beg >= len) { | |||
| 1065 | msgq(sp, M_BERR, "Cursor not in a word"); | |||
| 1066 | return (1); | |||
| 1067 | } | |||
| 1068 | if (moved) { | |||
| 1069 | sp->cno = beg; | |||
| 1070 | (void)vs_refresh(sp, 0); | |||
| 1071 | } | |||
| 1072 | ||||
| 1073 | /* Find the end of the word. */ | |||
| 1074 | for (state = inword(p[beg])(isalnum(p[beg]) || (p[beg]) == '_'), | |||
| 1075 | end = beg; ++end < len && state == inword(p[end])(isalnum(p[end]) || (p[end]) == '_');); | |||
| 1076 | ||||
| 1077 | vip = VIP(sp)((VI_PRIVATE *)((sp)->vi_private)); | |||
| 1078 | len = (end - beg); | |||
| 1079 | BINC_RET(sp, vip->keyw, vip->klen, len){ void *L__bincp; if ((len) > (vip->klen)) { if ((L__bincp = binc((sp), (vip->keyw), &(vip->klen), (len))) == ((void *)0)) return (1); (vip->keyw) = L__bincp; } }; | |||
| 1080 | memmove(vip->keyw, p + beg, len); | |||
| 1081 | vip->keyw[len] = '\0'; /* XXX */ | |||
| 1082 | return (0); | |||
| 1083 | } | |||
| 1084 | ||||
| 1085 | /* | |||
| 1086 | * v_alias -- | |||
| 1087 | * Check for a command alias. | |||
| 1088 | */ | |||
| 1089 | static VIKEYS const * | |||
| 1090 | v_alias(SCR *sp, VICMD *vp, VIKEYS const *kp) | |||
| 1091 | { | |||
| 1092 | CHAR_T push; | |||
| 1093 | ||||
| 1094 | switch (vp->key) { | |||
| 1095 | case 'C': /* C -> c$ */ | |||
| 1096 | push = '$'; | |||
| 1097 | vp->key = 'c'; | |||
| 1098 | break; | |||
| 1099 | case 'D': /* D -> d$ */ | |||
| 1100 | push = '$'; | |||
| 1101 | vp->key = 'd'; | |||
| 1102 | break; | |||
| 1103 | case 'S': /* S -> c_ */ | |||
| 1104 | push = '_'; | |||
| 1105 | vp->key = 'c'; | |||
| 1106 | break; | |||
| 1107 | case 'Y': /* Y -> y_ */ | |||
| 1108 | push = '_'; | |||
| 1109 | vp->key = 'y'; | |||
| 1110 | break; | |||
| 1111 | default: | |||
| 1112 | return (kp); | |||
| 1113 | } | |||
| 1114 | return (v_event_push(sp, | |||
| 1115 | NULL((void *)0), &push, 1, CH_NOMAP0x04 | CH_QUOTED0x08) ? NULL((void *)0) : &vikeys[vp->key]); | |||
| 1116 | } | |||
| 1117 | ||||
| 1118 | /* | |||
| 1119 | * v_count -- | |||
| 1120 | * Return the next count. | |||
| 1121 | */ | |||
| 1122 | static int | |||
| 1123 | v_count(SCR *sp, CHAR_T fkey, u_long *countp) | |||
| 1124 | { | |||
| 1125 | EVENT ev; | |||
| 1126 | u_long count, tc; | |||
| 1127 | ||||
| 1128 | ev.e_c_u_event._e_ch.c = fkey; | |||
| 1129 | count = tc = 0; | |||
| 1130 | do { | |||
| 1131 | /* | |||
| 1132 | * XXX | |||
| 1133 | * Assume that overflow results in a smaller number. | |||
| 1134 | */ | |||
| 1135 | tc = count * 10 + ev.e_c_u_event._e_ch.c - '0'; | |||
| 1136 | if (count > tc) { | |||
| 1137 | /* Toss to the next non-digit. */ | |||
| 1138 | do { | |||
| 1139 | if (v_key(sp, 0, &ev, | |||
| 1140 | EC_MAPCOMMAND0x002 | EC_MAPNODIGIT0x008) != GC_OK) | |||
| 1141 | return (1); | |||
| 1142 | } while (isdigit(ev.e_c_u_event._e_ch.c)); | |||
| 1143 | msgq(sp, M_ERR, | |||
| 1144 | "Number larger than %lu", ULONG_MAX0xffffffffffffffffUL); | |||
| 1145 | return (1); | |||
| 1146 | } | |||
| 1147 | count = tc; | |||
| 1148 | if (v_key(sp, 0, &ev, EC_MAPCOMMAND0x002 | EC_MAPNODIGIT0x008) != GC_OK) | |||
| 1149 | return (1); | |||
| 1150 | } while (isdigit(ev.e_c_u_event._e_ch.c)); | |||
| 1151 | *countp = count; | |||
| 1152 | return (0); | |||
| 1153 | } | |||
| 1154 | ||||
| 1155 | /* | |||
| 1156 | * v_key -- | |||
| 1157 | * Return the next event. | |||
| 1158 | */ | |||
| 1159 | static gcret_t | |||
| 1160 | v_key(SCR *sp, int command_events, EVENT *evp, u_int32_t ec_flags) | |||
| 1161 | { | |||
| 1162 | u_int32_t quote; | |||
| 1163 | ||||
| 1164 | for (quote = 0;;) { | |||
| 1165 | if (v_event_get(sp, evp, 0, ec_flags | quote)) | |||
| 1166 | return (GC_FATAL); | |||
| 1167 | quote = 0; | |||
| 1168 | ||||
| 1169 | switch (evp->e_event) { | |||
| 1170 | case E_CHARACTER: | |||
| 1171 | /* | |||
| 1172 | * !!! | |||
| 1173 | * Historically, ^V was ignored in the command stream, | |||
| 1174 | * although it had a useful side-effect of interrupting | |||
| 1175 | * mappings. Adding a quoting bit to the call probably | |||
| 1176 | * extends historic practice, but it feels right. | |||
| 1177 | */ | |||
| 1178 | if (evp->e_value_u_event._e_ch.value == K_VLNEXT) { | |||
| 1179 | quote = EC_QUOTED0x010; | |||
| 1180 | break; | |||
| 1181 | } | |||
| 1182 | return (GC_OK); | |||
| 1183 | case E_ERR: | |||
| 1184 | case E_EOF: | |||
| 1185 | return (GC_FATAL); | |||
| 1186 | case E_INTERRUPT: | |||
| 1187 | /* | |||
| 1188 | * !!! | |||
| 1189 | * Historically, vi beeped on command level interrupts. | |||
| 1190 | * | |||
| 1191 | * Historically, vi exited to ex mode if no file was | |||
| 1192 | * named on the command line, and two interrupts were | |||
| 1193 | * generated in a row. (Just figured you might want | |||
| 1194 | * to know that.) | |||
| 1195 | */ | |||
| 1196 | (void)sp->gp->scr_bell(sp); | |||
| 1197 | return (GC_INTERRUPT); | |||
| 1198 | case E_REPAINT: | |||
| 1199 | if (vs_repaint(sp, evp)) | |||
| 1200 | return (GC_FATAL); | |||
| 1201 | break; | |||
| 1202 | case E_WRESIZE: | |||
| 1203 | return (GC_ERR); | |||
| 1204 | case E_QUIT: | |||
| 1205 | case E_WRITE: | |||
| 1206 | if (command_events) | |||
| 1207 | return (GC_EVENT); | |||
| 1208 | /* FALLTHROUGH */ | |||
| 1209 | default: | |||
| 1210 | v_event_err(sp, evp); | |||
| 1211 | return (GC_ERR); | |||
| 1212 | } | |||
| 1213 | } | |||
| 1214 | /* NOTREACHED */ | |||
| 1215 | } | |||
| 1216 | ||||
| 1217 | #if defined(DEBUG) && defined(COMLOG) | |||
| 1218 | /* | |||
| 1219 | * v_comlog -- | |||
| 1220 | * Log the contents of the command structure. | |||
| 1221 | */ | |||
| 1222 | static void | |||
| 1223 | v_comlog(SCR *sp, VICMD *vp) | |||
| 1224 | { | |||
| 1225 | TRACE(sp, "vcmd: %c", vp->key); | |||
| 1226 | if (F_ISSET(vp, VC_BUFFER)(((vp)->flags) & ((0x00000200)))) | |||
| 1227 | TRACE(sp, " buffer: %c", vp->buffer); | |||
| 1228 | if (F_ISSET(vp, VC_C1SET)(((vp)->flags) & ((0x00000800)))) | |||
| 1229 | TRACE(sp, " c1: %lu", vp->count); | |||
| 1230 | if (F_ISSET(vp, VC_C2SET)(((vp)->flags) & ((0x00001000)))) | |||
| 1231 | TRACE(sp, " c2: %lu", vp->count2); | |||
| 1232 | TRACE(sp, " flags: 0x%x\n", vp->flags); | |||
| 1233 | } | |||
| 1234 | #endif |