Fix compiler warnings (missing #includes etc) thrown up by RedHat.
[sgt/tweak] / actions.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5
6 #include "tweak.h"
7
8 static void act_exit (void);
9 static void act_save (void);
10 static void act_exitsave (void);
11 static void act_top (void);
12 static void act_pgup (void);
13 static void act_up (void);
14 static void act_home (void);
15 static void act_left (void);
16 static void act_right (void);
17 static void act_end (void);
18 static void act_down (void);
19 static void act_pgdn (void);
20 static void act_bottom (void);
21 static void act_togins (void);
22 static void act_chmode (void);
23 extern void act_self_ins (void); /* this one must be external */
24 static void act_delete (void);
25 static void act_delch (void);
26 static void act_mark (void);
27 static void act_cut (void);
28 static void act_copy (void);
29 static void act_paste (void);
30 static void act_susp (void);
31 static void act_goto (void);
32 static void act_togstat (void);
33 static void act_search (void);
34 static void act_recentre (void);
35 static void act_width (void);
36 static void act_offset (void);
37 #ifdef TEST_BUFFER
38 static void act_diagnostics (void);
39 #endif
40
41 keyact parse_action (char *name) {
42 char *names[] = {
43 "exit", "top-of-file", "page-up", "move-up",
44 "begin-line", "move-left", "move-right", "end-line",
45 "move-down", "page-down", "bottom-of-file", "toggle-insert",
46 "change-mode", "delete-left", "delete-right", "mark-place",
47 "cut", "copy", "paste", "suspend", "goto-position",
48 "toggle-status", "search", "save-file", "exit-and-save",
49 "screen-recentre", "new-width", "new-offset"
50 #ifdef TEST_BUFFER
51 , "diagnostics"
52 #endif
53 };
54 keyact actions[] = {
55 act_exit, act_top, act_pgup, act_up, act_home, act_left,
56 act_right, act_end, act_down, act_pgdn, act_bottom,
57 act_togins, act_chmode, act_delete, act_delch, act_mark,
58 act_cut, act_copy, act_paste, act_susp, act_goto,
59 act_togstat, act_search, act_save, act_exitsave,
60 act_recentre, act_width, act_offset
61 #ifdef TEST_BUFFER
62 , act_diagnostics
63 #endif
64 };
65 int i;
66
67 for (i=0; i<sizeof(names)/sizeof(*names); i++)
68 if (!strcmp(name, names[i]))
69 return actions[i];
70 return NULL;
71 }
72
73 static int begline(int x) {
74 int y = x + width-offset;
75 y -= (y % width);
76 y -= width-offset;
77 if (y < 0)
78 y = 0;
79 return y;
80 }
81
82 static int endline(int x) {
83 int y = x + width-offset;
84 y -= (y % width);
85 y += width-1;
86 y -= width-offset;
87 if (y < 0)
88 y = 0;
89 return y;
90 }
91
92 static void act_exit(void) {
93 static char question[] = "File is modified. Save before quitting? [yn] ";
94 if (modified) {
95 int c;
96
97 display_moveto (display_rows-1, 0);
98 display_clear_to_eol ();
99 display_set_colour (COL_MINIBUF);
100 display_write_str (question);
101 display_refresh();
102 do {
103 #if defined(unix) && !defined(GO32)
104 if (update_required) {
105 update();
106 display_moveto (display_rows-1, 0);
107 display_clear_to_eol ();
108 display_set_colour (COL_MINIBUF);
109 display_write_str (question);
110 display_refresh();
111 }
112 safe_update = TRUE;
113 #endif
114 c = display_getkey();
115 #if defined(unix) && !defined(GO32)
116 safe_update = FALSE;
117 #endif
118 if (c >= 'a' && c <= 'z')
119 c += 'A'-'a';
120 } while (c != 'Y' && c != 'N' && c != '\007');
121 if (c == 'Y') {
122 act_save();
123 if (modified)
124 return; /* couldn't save, so don't quit */
125 draw_scr(); /* update the ** on status line! */
126 } else if (c == '\007') {
127 return; /* don't even quit */
128 }
129 }
130 finished = TRUE;
131 }
132
133 static void act_save(void) {
134 static int backed_up = FALSE;
135
136 if (!backed_up) {
137 if (!backup_file()) {
138 display_beep();
139 strcpy (message, "Unable to back up file!");
140 return;
141 }
142 backed_up = TRUE;
143 }
144 if (!save_file()) {
145 display_beep();
146 strcpy (message, "Unable to save file!");
147 return;
148 }
149 modified = FALSE;
150 }
151
152 static void act_exitsave(void) {
153 act_save();
154 draw_scr(); /* update ** on status line */
155 act_exit();
156 }
157
158 static void act_top (void) {
159 cur_pos = top_pos = 0;
160 edit_type = !!edit_type;
161 }
162
163 static void act_pgup(void) {
164 cur_pos -= (scrlines-1)*width;
165 if (cur_pos < 0) {
166 cur_pos = 0;
167 edit_type = !!edit_type;
168 }
169 if (top_pos > cur_pos)
170 top_pos = begline(cur_pos);
171 }
172
173 static void act_up(void) {
174 cur_pos -= width;
175 if (cur_pos < 0) {
176 cur_pos = 0;
177 edit_type = !!edit_type;
178 }
179 if (top_pos > cur_pos)
180 top_pos = begline(cur_pos);
181 }
182
183 static void act_home(void) {
184 cur_pos = begline(cur_pos);
185 if (cur_pos < 0)
186 cur_pos = 0;
187 if (top_pos > cur_pos)
188 top_pos = begline(cur_pos);
189 edit_type = !!edit_type;
190 }
191
192 static void act_left(void) {
193 if (edit_type == 2) {
194 edit_type = 1;
195 return;
196 } else {
197 cur_pos--;
198 edit_type = 2*!!edit_type;
199 if (cur_pos < 0) {
200 cur_pos = 0;
201 edit_type = !!edit_type;
202 }
203 if (top_pos > cur_pos)
204 top_pos = begline(cur_pos);
205 }
206 }
207
208 static void act_right(void) {
209 int new_top;
210
211 if (edit_type == 1) {
212 if (cur_pos < file_size)
213 edit_type = 2;
214 return;
215 } else {
216 cur_pos++;
217 if (cur_pos > file_size)
218 cur_pos = file_size;
219 new_top = cur_pos - (scrlines-1) * width;
220 if (new_top < 0)
221 new_top = 0;
222 new_top = begline(new_top);
223 if (top_pos < new_top)
224 top_pos = new_top;
225 edit_type = !!edit_type;
226 }
227 }
228
229 static void act_end(void) {
230 int new_top;
231
232 cur_pos = endline(cur_pos);
233 edit_type = !!edit_type;
234 if (cur_pos >= file_size)
235 cur_pos = file_size;
236 new_top = cur_pos - (scrlines-1) * width;
237 if (new_top < 0)
238 new_top = 0;
239 new_top = begline(new_top);
240 if (top_pos < new_top)
241 top_pos = new_top;
242 }
243
244 static void act_down(void) {
245 int new_top;
246
247 cur_pos += width;
248 if (cur_pos >= file_size) {
249 cur_pos = file_size;
250 edit_type = !!edit_type;
251 }
252 new_top = cur_pos - (scrlines-1) * width;
253 if (new_top < 0)
254 new_top = 0;
255 new_top = begline(new_top);
256 if (top_pos < new_top)
257 top_pos = new_top;
258 }
259
260 static void act_pgdn(void) {
261 int new_top;
262
263 cur_pos += (scrlines-1) * width;
264 if (cur_pos >= file_size) {
265 cur_pos = file_size;
266 edit_type = !!edit_type;
267 }
268 new_top = cur_pos - (scrlines-1) * width;
269 if (new_top < 0)
270 new_top = 0;
271 new_top = begline(new_top);
272 if (top_pos < new_top)
273 top_pos = new_top;
274 }
275
276 static void act_bottom (void) {
277 int new_top;
278
279 cur_pos = file_size;
280 edit_type = !!edit_type;
281 new_top = cur_pos - (scrlines-1) * width;
282 if (new_top < 0)
283 new_top = 0;
284 new_top = begline(new_top);
285 if (top_pos < new_top)
286 top_pos = new_top;
287 }
288
289 static void act_togins(void) {
290 if (look_mode || fix_mode) {
291 display_beep();
292 sprintf(message, "Can't engage Insert mode when in %s mode",
293 (look_mode ? "LOOK" : "FIX"));
294 insert_mode = FALSE; /* safety! */
295 } else
296 insert_mode = !insert_mode;
297 }
298
299 static void act_chmode(void) {
300 if (ascii_enabled)
301 edit_type = !edit_type; /* 0 -> 1, [12] -> 0 */
302 else if (edit_type == 0) /* just in case */
303 edit_type = 1;
304 }
305
306 void act_self_ins(void) {
307 int insert = insert_mode;
308 unsigned char c;
309
310 if (look_mode) {
311 display_beep();
312 strcpy (message, "Can't modify file in LOOK mode");
313 return;
314 }
315
316 if (edit_type) {
317 if (last_char >= '0' && last_char <= '9')
318 last_char -= '0';
319 else if (last_char >= 'A' && last_char <= 'F')
320 last_char -= 'A'-10;
321 else if (last_char >= 'a' && last_char <= 'f')
322 last_char -= 'a'-10;
323 else {
324 display_beep();
325 strcpy(message, "Not a valid character when in hex editing mode");
326 return;
327 }
328 }
329
330 if ( (!insert || edit_type == 2) && cur_pos == file_size) {
331 display_beep();
332 strcpy(message, "End of file reached");
333 return;
334 }
335
336 switch (edit_type) {
337 case 0: /* ascii mode */
338 c = last_char;
339 break;
340 case 1: /* hex, first digit */
341 if (insert)
342 c = 0;
343 else
344 buf_fetch_data(filedata, &c, 1, cur_pos);
345 c &= 0xF;
346 c |= 16 * last_char;
347 break;
348 case 2: /* hex, second digit */
349 buf_fetch_data(filedata, &c, 1, cur_pos);
350 c &= 0xF0;
351 c |= last_char;
352 insert = FALSE;
353 break;
354 }
355
356 if (insert) {
357 buf_insert_data(filedata, &c, 1, cur_pos);
358 file_size++;
359 modified = TRUE;
360 } else if (cur_pos < file_size) {
361 buf_overwrite_data(filedata, &c, 1, cur_pos);
362 modified = TRUE;
363 } else {
364 display_beep();
365 strcpy(message, "End of file reached");
366 }
367 act_right();
368 }
369
370 static void act_delete(void) {
371 if (!insert_mode || (edit_type!=2 && cur_pos==0)) {
372 display_beep();
373 strcpy (message, "Can't delete while not in Insert mode");
374 } else if (cur_pos > 0 || edit_type == 2) {
375 act_left();
376 buf_delete (filedata, 1, cur_pos);
377 file_size--;
378 edit_type = !!edit_type;
379 modified = TRUE;
380 }
381 }
382
383 static void act_delch(void) {
384 if (!insert_mode) {
385 display_beep();
386 strcpy (message, "Can't delete while not in Insert mode");
387 } else if (cur_pos < file_size) {
388 buf_delete (filedata, 1, cur_pos);
389 file_size--;
390 edit_type = !!edit_type;
391 modified = TRUE;
392 }
393 }
394
395 static void act_mark (void) {
396 if (look_mode) {
397 display_beep();
398 strcpy (message, "Can't cut or paste in LOOK mode");
399 marking = FALSE; /* safety */
400 return;
401 }
402 marking = !marking;
403 mark_point = cur_pos;
404 }
405
406 static void act_cut (void) {
407 long marktop, marksize;
408
409 if (!marking || mark_point==cur_pos) {
410 display_beep();
411 strcpy (message, "Set mark first");
412 return;
413 }
414 if (!insert_mode) {
415 display_beep();
416 strcpy (message, "Can't cut while not in Insert mode");
417 return;
418 }
419 marktop = cur_pos;
420 marksize = mark_point - cur_pos;
421 if (marksize < 0) {
422 marktop += marksize;
423 marksize = -marksize;
424 }
425 if (cutbuffer)
426 buf_free (cutbuffer);
427 cutbuffer = buf_cut (filedata, marksize, marktop);
428 file_size -= marksize;
429 cur_pos = marktop;
430 if (cur_pos < 0)
431 cur_pos = 0;
432 if (top_pos > cur_pos)
433 top_pos = begline(cur_pos);
434 edit_type = !!edit_type;
435 modified = TRUE;
436 marking = FALSE;
437 }
438
439 static void act_copy (void) {
440 int marktop, marksize;
441
442 if (!marking) {
443 display_beep();
444 strcpy (message, "Set mark first");
445 return;
446 }
447 marktop = cur_pos;
448 marksize = mark_point - cur_pos;
449 if (marksize < 0) {
450 marktop += marksize;
451 marksize = -marksize;
452 }
453 if (cutbuffer)
454 buf_free (cutbuffer);
455 cutbuffer = buf_copy (filedata, marksize, marktop);
456 marking = FALSE;
457 }
458
459 static void act_paste (void) {
460 int cutsize, new_top;
461
462 cutsize = buf_length (cutbuffer);
463 if (!insert_mode) {
464 if (cur_pos + cutsize > file_size) {
465 display_beep();
466 strcpy (message, "Too close to end of file to paste");
467 return;
468 }
469 buf_delete (filedata, cutsize, cur_pos);
470 file_size -= cutsize;
471 }
472 buf_paste (filedata, cutbuffer, cur_pos);
473 modified = TRUE;
474 cur_pos += cutsize;
475 file_size += cutsize;
476 edit_type = !!edit_type;
477 new_top = cur_pos - (scrlines-1) * width;
478 if (new_top < 0)
479 new_top = 0;
480 new_top = begline(new_top);
481 if (top_pos < new_top)
482 top_pos = new_top;
483 }
484
485 static void act_susp (void) {
486 suspend();
487 }
488
489 static void act_goto (void) {
490 char buffer[80];
491 long position, new_top;
492 int error;
493
494 if (!get_str("Enter position to go to: ", buffer, FALSE))
495 return; /* user break */
496
497 position = parse_num (buffer, &error);
498 if (error) {
499 display_beep();
500 strcpy (message, "Unable to parse position value");
501 return;
502 }
503
504 if (position < 0 || position > file_size) {
505 display_beep();
506 strcpy (message, "Position is outside bounds of file");
507 return;
508 }
509
510 cur_pos = position;
511 edit_type = !!edit_type;
512 new_top = cur_pos - (scrlines-1) * width;
513 if (new_top < 0)
514 new_top = 0;
515 new_top = begline(new_top);
516 if (top_pos > cur_pos)
517 top_pos = begline(cur_pos);
518 if (top_pos < new_top)
519 top_pos = new_top;
520 }
521
522 static void act_togstat (void) {
523 if (statfmt == decstatus)
524 statfmt = hexstatus;
525 else
526 statfmt = decstatus;
527 }
528
529 static void act_search (void) {
530 char buffer[80];
531 int len, posn, dfapos;
532 DFA dfa;
533 static unsigned char sblk[SEARCH_BLK];
534 static char withdef[] = "Search for (default=last): ";
535 static char withoutdef[] = "Search for: ";
536
537 dfa = last_dfa();
538
539 if (!get_str(dfa ? withdef : withoutdef, buffer, TRUE))
540 return; /* user break */
541 if (!dfa && !*buffer) {
542 strcpy (message, "Search aborted.");
543 return;
544 }
545
546 if (!*buffer) {
547 len = last_len();
548 } else {
549 len = parse_quoted (buffer);
550 if (len == -1) {
551 display_beep();
552 strcpy (message, "Invalid escape sequence in search string");
553 return;
554 }
555 dfa = build_dfa (buffer, len);
556 }
557
558 dfapos = 0;
559
560 for (posn = cur_pos+1; posn < file_size; posn++) {
561 unsigned char *q;
562 int size = SEARCH_BLK;
563
564 if (size > file_size-posn)
565 size = file_size-posn;
566 buf_fetch_data (filedata, sblk, size, posn);
567 q = sblk;
568 while (size--) {
569 posn++;
570 dfapos = dfa[dfapos][*q++];
571 if (dfapos == len) {
572 int new_top;
573
574 cur_pos = posn - len;
575 edit_type = !!edit_type;
576 new_top = cur_pos - (scrlines-1) * width;
577 new_top = begline(new_top);
578 if (top_pos < new_top)
579 top_pos = new_top;
580 return;
581 }
582 }
583 }
584 strcpy (message, "Not found.");
585 }
586
587 static void act_recentre (void) {
588 top_pos = cur_pos - (display_rows-2)/2 * width;
589 if (top_pos < 0)
590 top_pos = 0;
591 top_pos = begline(top_pos);
592 }
593
594 static void act_width (void) {
595 char buffer[80];
596 char prompt[80];
597 long w;
598 long new_top;
599 int error;
600
601 sprintf (prompt, "Enter screen width in bytes (now %d): ", width);
602 if (!get_str (prompt, buffer, FALSE))
603 return;
604 w = parse_num (buffer, &error);
605 if (error) {
606 display_beep();
607 strcpy (message, "Unable to parse width value");
608 return;
609 }
610 if (w > 0) {
611 width = w;
612 fix_offset();
613 new_top = cur_pos - (scrlines-1) * width;
614 new_top = begline(new_top);
615 if (top_pos < new_top)
616 top_pos = new_top;
617 }
618 }
619
620 static void act_offset (void) {
621 char buffer[80];
622 char prompt[80];
623 long o;
624 long new_top;
625 int error;
626
627 sprintf (prompt, "Enter start-of-file offset in bytes (now %d): ",
628 realoffset);
629 if (!get_str (prompt, buffer, FALSE))
630 return;
631 o = parse_num (buffer, &error);
632 if (error) {
633 display_beep();
634 strcpy (message, "Unable to parse offset value");
635 return;
636 }
637 if (o >= 0) {
638 realoffset = o;
639 fix_offset();
640 new_top = cur_pos - (scrlines-1) * width;
641 new_top = begline(new_top);
642 if (top_pos < new_top)
643 top_pos = new_top;
644 }
645 }
646
647 #ifdef TEST_BUFFER
648 static void act_diagnostics(void)
649 {
650 extern void buffer_diagnostic(buffer *buf, char *title);
651
652 buffer_diagnostic(filedata, "filedata");
653 buffer_diagnostic(cutbuffer, "cutbuffer");
654 }
655 #endif