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