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