1 /* $NetBSD: v_event.c,v 1.3 2014/01/26 21:43:45 christos Exp $ */ 2 /*- 3 * Copyright (c) 1996 4 * Keith Bostic. All rights reserved. 5 * 6 * See the LICENSE file for redistribution information. 7 */ 8 9 #include "config.h" 10 11 #include <sys/cdefs.h> 12 #if 0 13 #ifndef lint 14 static const char sccsid[] = "Id: v_event.c,v 8.21 2001/06/25 15:19:31 skimo Exp (Berkeley) Date: 2001/06/25 15:19:31 "; 15 #endif /* not lint */ 16 #else 17 __RCSID("$NetBSD: v_event.c,v 1.3 2014/01/26 21:43:45 christos Exp $"); 18 #endif 19 20 #include <sys/types.h> 21 #include <sys/queue.h> 22 #include <sys/time.h> 23 24 #include <bitstring.h> 25 #include <ctype.h> 26 #include <errno.h> 27 #include <limits.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <unistd.h> 32 33 #include "../common/common.h" 34 #include "../ipc/ip.h" 35 #include "vi.h" 36 37 /* 38 * v_c_settop -- 39 * Scrollbar position. 40 */ 41 static int 42 v_c_settop(SCR *sp, VICMD *vp) 43 { 44 SMAP *smp; 45 size_t x = 0, y = LASTLINE(sp); /* Future: change to -1 to not 46 * display the cursor 47 */ 48 size_t tx, ty = -1; 49 50 /* 51 * We want to scroll the screen, without changing the cursor position. 52 * So, we fill the screen map and then flush it to the screen. Then, 53 * set the VIP_S_REFRESH flag so the main vi loop doesn't update the 54 * screen. When the next real command happens, the refresh code will 55 * notice that the screen map is way wrong and fix it. 56 * 57 * XXX 58 * There may be a serious performance problem here -- we're doing no 59 * optimization whatsoever, which means that we're copying the entire 60 * screen out to the X11 screen code on each change. 61 */ 62 if (vs_sm_fill(sp, vp->ev.e_lno, P_TOP)) 63 return (1); 64 for (smp = HMAP; smp <= TMAP; ++smp) { 65 SMAP_FLUSH(smp); 66 if (vs_line(sp, smp, &ty, &tx)) 67 return (1); 68 if (ty != (size_t)-1) { 69 y = ty; 70 x = tx; 71 } 72 } 73 (void)sp->gp->scr_move(sp, y, x); 74 75 F_SET(VIP(sp), VIP_S_REFRESH); 76 77 return (sp->gp->scr_refresh(sp, 0)); 78 } 79 80 /* 81 * v_edit -- 82 * Edit command. 83 */ 84 static int 85 v_edit(SCR *sp, VICMD *vp) 86 { 87 EXCMD cmd; 88 89 ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0); 90 argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len); 91 return (v_exec_ex(sp, vp, &cmd)); 92 } 93 94 /* 95 * v_editopt -- 96 * Set an option value. 97 */ 98 static int 99 v_editopt(SCR *sp, VICMD *vp) 100 { 101 int rval; 102 const char *np; 103 size_t nlen; 104 char *p2; 105 106 INT2CHAR(sp, vp->ev.e_str2, STRLEN(vp->ev.e_str2)+1, np, nlen); 107 p2 = strdup(np); 108 rval = api_opts_set(sp, vp->ev.e_str1, p2, 109 vp->ev.e_val1, vp->ev.e_val1); 110 if (sp->gp->scr_reply != NULL) 111 (void)sp->gp->scr_reply(sp, rval, NULL); 112 free(p2); 113 return (rval); 114 } 115 116 /* 117 * v_editsplit -- 118 * Edit in a split screen. 119 */ 120 static int 121 v_editsplit(SCR *sp, VICMD *vp) 122 { 123 EXCMD cmd; 124 125 ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0); 126 F_SET(&cmd, E_NEWSCREEN); 127 argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len); 128 return (v_exec_ex(sp, vp, &cmd)); 129 } 130 131 /* 132 * v_tag -- 133 * Tag command. 134 */ 135 static int 136 v_tag(SCR *sp, VICMD *vp) 137 { 138 EXCMD cmd; 139 140 if (v_curword(sp)) 141 return (1); 142 143 ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0); 144 argv_exp0(sp, &cmd, VIP(sp)->keyw, STRLEN(VIP(sp)->keyw)); 145 return (v_exec_ex(sp, vp, &cmd)); 146 } 147 148 /* 149 * v_tagas -- 150 * Tag on the supplied string. 151 */ 152 static int 153 v_tagas(SCR *sp, VICMD *vp) 154 { 155 EXCMD cmd; 156 157 ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0); 158 argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len); 159 return (v_exec_ex(sp, vp, &cmd)); 160 } 161 162 /* 163 * v_tagsplit -- 164 * Tag in a split screen. 165 */ 166 static int 167 v_tagsplit(SCR *sp, VICMD *vp) 168 { 169 EXCMD cmd; 170 171 if (v_curword(sp)) 172 return (1); 173 174 ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0); 175 F_SET(&cmd, E_NEWSCREEN); 176 argv_exp0(sp, &cmd, VIP(sp)->keyw, STRLEN(VIP(sp)->keyw)); 177 return (v_exec_ex(sp, vp, &cmd)); 178 } 179 180 /* 181 * v_quit -- 182 * Quit command. 183 */ 184 static int 185 v_quit(SCR *sp, VICMD *vp) 186 { 187 EXCMD cmd; 188 189 ex_cinit(sp, &cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0); 190 return (v_exec_ex(sp, vp, &cmd)); 191 } 192 193 /* 194 * v_erepaint -- 195 * Repaint selected lines from the screen. 196 * 197 * PUBLIC: int v_erepaint __P((SCR *, EVENT *)); 198 */ 199 int 200 v_erepaint(SCR *sp, EVENT *evp) 201 { 202 SMAP *smp; 203 204 for (; evp->e_flno <= evp->e_tlno; ++evp->e_flno) { 205 smp = HMAP + evp->e_flno - 1; 206 SMAP_FLUSH(smp); 207 if (vs_line(sp, smp, NULL, NULL)) 208 return (1); 209 } 210 return (0); 211 } 212 213 /* 214 * v_sel_end -- 215 * End selection. 216 */ 217 static int 218 v_sel_end(SCR *sp, EVENT *evp) 219 { 220 SMAP *smp; 221 VI_PRIVATE *vip; 222 223 smp = HMAP + evp->e_lno; 224 if (smp > TMAP) { 225 /* XXX */ 226 return (1); 227 } 228 229 vip = VIP(sp); 230 vip->sel.lno = smp->lno; 231 vip->sel.cno = 232 vs_colpos(sp, smp->lno, evp->e_cno + (smp->soff - 1) * sp->cols); 233 return (0); 234 } 235 236 /* 237 * v_sel_start -- 238 * Start selection. 239 */ 240 static int 241 v_sel_start(SCR *sp, EVENT *evp) 242 { 243 SMAP *smp; 244 VI_PRIVATE *vip; 245 246 smp = HMAP + evp->e_lno; 247 if (smp > TMAP) { 248 /* XXX */ 249 return (1); 250 } 251 252 vip = VIP(sp); 253 vip->sel.lno = smp->lno; 254 vip->sel.cno = 255 vs_colpos(sp, smp->lno, evp->e_cno + (smp->soff - 1) * sp->cols); 256 return (0); 257 } 258 259 /* 260 * v_wq -- 261 * Write and quit command. 262 */ 263 static int 264 v_wq(SCR *sp, VICMD *vp) 265 { 266 EXCMD cmd; 267 268 ex_cinit(sp, &cmd, C_WQ, 0, OOBLNO, OOBLNO, 0); 269 270 cmd.addr1.lno = 1; 271 if (db_last(sp, &cmd.addr2.lno)) 272 return (1); 273 return (v_exec_ex(sp, vp, &cmd)); 274 } 275 276 /* 277 * v_write -- 278 * Write command. 279 */ 280 static int 281 v_write(SCR *sp, VICMD *vp) 282 { 283 EXCMD cmd; 284 285 ex_cinit(sp, &cmd, C_WRITE, 0, OOBLNO, OOBLNO, 0); 286 287 cmd.addr1.lno = 1; 288 if (db_last(sp, &cmd.addr2.lno)) 289 return (1); 290 return (v_exec_ex(sp, vp, &cmd)); 291 } 292 293 /* 294 * v_writeas -- 295 * Write command. 296 */ 297 static int 298 v_writeas(SCR *sp, VICMD *vp) 299 { 300 EXCMD cmd; 301 302 ex_cinit(sp, &cmd, C_WRITE, 0, OOBLNO, OOBLNO, 0); 303 argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len); 304 305 cmd.addr1.lno = 1; 306 if (db_last(sp, &cmd.addr2.lno)) 307 return (1); 308 return (v_exec_ex(sp, vp, &cmd)); 309 } 310 311 /* 312 * v_event -- 313 * Find the event associated with a function. 314 * 315 * PUBLIC: int v_event __P((SCR *, VICMD *)); 316 */ 317 int 318 v_event(SCR *sp, VICMD *vp) 319 { 320 /* This array maps events to vi command functions. */ 321 #define VIKEYDEF(a, b) { a, b, NULL, NULL } 322 static VIKEYS const vievents[] = { 323 #define V_C_SETTOP 0 /* VI_C_SETTOP */ 324 VIKEYDEF(v_c_settop, 0), 325 #define V_EDIT 1 /* VI_EDIT */ 326 VIKEYDEF(v_edit, 0), 327 #define V_EDITOPT 2 /* VI_EDITOPT */ 328 VIKEYDEF(v_editopt, 0), 329 #define V_EDITSPLIT 3 /* VI_EDITSPLIT */ 330 VIKEYDEF(v_editsplit, 0), 331 #define V_EMARK 4 /* VI_MOUSE_MOVE */ 332 VIKEYDEF(v_emark, V_ABS_L|V_MOVE), 333 #define V_QUIT 5 /* VI_QUIT */ 334 VIKEYDEF(v_quit, 0), 335 #define V_SEARCH 6 /* VI_SEARCH */ 336 VIKEYDEF(v_esearch, V_ABS_L|V_MOVE), 337 #define V_TAG 7 /* VI_TAG */ 338 VIKEYDEF(v_tag, 0), 339 #define V_TAGAS 8 /* VI_TAGAS */ 340 VIKEYDEF(v_tagas, 0), 341 #define V_TAGSPLIT 9 /* VI_TAGSPLIT */ 342 VIKEYDEF(v_tagsplit, 0), 343 #define V_WQ 10 /* VI_WQ */ 344 VIKEYDEF(v_wq, 0), 345 #define V_WRITE 11 /* VI_WRITE */ 346 VIKEYDEF(v_write, 0), 347 #define V_WRITEAS 12 /* VI_WRITEAS */ 348 VIKEYDEF(v_writeas, 0), 349 }; 350 351 switch (vp->ev.e_ipcom) { 352 case VI_C_BOL: 353 vp->kp = &vikeys['0']; 354 break; 355 case VI_C_BOTTOM: 356 vp->kp = &vikeys['G']; 357 break; 358 case VI_C_DEL: 359 vp->kp = &vikeys['x']; 360 break; 361 case VI_C_DOWN: 362 F_SET(vp, VC_C1SET); 363 vp->count = vp->ev.e_lno; 364 vp->kp = &vikeys['\012']; 365 break; 366 case VI_C_EOL: 367 vp->kp = &vikeys['$']; 368 break; 369 case VI_C_INSERT: 370 vp->kp = &vikeys['i']; 371 break; 372 case VI_C_LEFT: 373 vp->kp = &vikeys['\010']; 374 break; 375 case VI_C_PGDOWN: 376 F_SET(vp, VC_C1SET); 377 vp->count = vp->ev.e_lno; 378 vp->kp = &vikeys['\006']; 379 break; 380 case VI_C_PGUP: 381 F_SET(vp, VC_C1SET); 382 vp->count = vp->ev.e_lno; 383 vp->kp = &vikeys['\002']; 384 break; 385 case VI_C_RIGHT: 386 vp->kp = &vikeys['\040']; 387 break; 388 case VI_C_SEARCH: 389 vp->kp = &vievents[V_SEARCH]; 390 break; 391 case VI_C_SETTOP: 392 vp->kp = &vievents[V_C_SETTOP]; 393 break; 394 case VI_C_TOP: 395 F_SET(vp, VC_C1SET); 396 vp->count = 1; 397 vp->kp = &vikeys['G']; 398 break; 399 case VI_C_UP: 400 F_SET(vp, VC_C1SET); 401 vp->count = vp->ev.e_lno; 402 vp->kp = &vikeys['\020']; 403 break; 404 case VI_EDIT: 405 vp->kp = &vievents[V_EDIT]; 406 break; 407 case VI_EDITOPT: 408 vp->kp = &vievents[V_EDITOPT]; 409 break; 410 case VI_EDITSPLIT: 411 vp->kp = &vievents[V_EDITSPLIT]; 412 break; 413 case VI_MOUSE_MOVE: 414 vp->kp = &vievents[V_EMARK]; 415 break; 416 case VI_SEL_END: 417 v_sel_end(sp, &vp->ev); 418 /* XXX RETURN IGNORE */ 419 break; 420 case VI_SEL_START: 421 v_sel_start(sp, &vp->ev); 422 /* XXX RETURN IGNORE */ 423 break; 424 case VI_QUIT: 425 vp->kp = &vievents[V_QUIT]; 426 break; 427 case VI_TAG: 428 vp->kp = &vievents[V_TAG]; 429 break; 430 case VI_TAGAS: 431 vp->kp = &vievents[V_TAGAS]; 432 break; 433 case VI_TAGSPLIT: 434 vp->kp = &vievents[V_TAGSPLIT]; 435 break; 436 case VI_UNDO: 437 vp->kp = &vikeys['u']; 438 break; 439 case VI_WQ: 440 vp->kp = &vievents[V_WQ]; 441 break; 442 case VI_WRITE: 443 vp->kp = &vievents[V_WRITE]; 444 break; 445 case VI_WRITEAS: 446 vp->kp = &vievents[V_WRITEAS]; 447 break; 448 default: 449 return (1); 450 } 451 return (0); 452 } 453