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 14static 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 */ 41static int 42v_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 */ 84static int 85v_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 */ 98static int 99v_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 */ 120static int 121v_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 */ 135static int 136v_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 */ 152static int 153v_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 */ 166static int 167v_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 */ 184static int 185v_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 */ 199int 200v_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 */ 217static int 218v_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 */ 240static int 241v_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 */ 263static int 264v_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 */ 280static int 281v_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 */ 297static int 298v_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 */ 317int 318v_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