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