1 /* windows.c by Adam Rogoyski <apoc@laker.net> Temperanc on EFNet irc
2 * Copyright (C) 1998, 1999 Adam Rogoyski
3 * --- GNU General Public License Disclamer ---
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14
15 #include "hexedit.h"
16
17
18 /* Brings up Jump to offset window, to relocate to a different part
19 * of the file. Uses one string box and takes input in octal, decimal,
20 * and hex.
21 */
22 void
popupGotoOffset(long filesize)23 popupGotoOffset (long filesize)
24 #define OFFSET_BOX_STRING_BOX 12
25 #define OFFSET_BOX_HEIGHT 8
26 #define OFFSET_BOX_WIDTH 50
27 #define OFFSET_STRING_BUF 11
28 {
29 char *offstr = NULL;
30 char offsetstr[OFFSET_STRING_BUF];
31 unsigned long off = 0x00;
32 WINDOW *wpopup = popupWindow (OFFSET_BOX_WIDTH, OFFSET_BOX_HEIGHT);
33 struct sigaction sig_new, sig_old;
34
35 /* signal (SIGINT, SIG_IGN); */
36 sig_new.sa_handler = SIG_IGN;
37 memset (&sig_new.sa_mask, 0x00, sizeof (sigset_t));
38 sig_new.sa_flags = 0;
39 sigaction (SIGINT, &sig_new, &sig_old);
40
41 wmove (wpopup, 1, (OFFSET_BOX_WIDTH / 2) - (strlen ("Goto Offset") / 2));
42 wprintw (wpopup, "Goto Offset");
43 wmove (wpopup, 5, 2);
44 wprintw (wpopup, " Hint: Decimal 255 = Hex 0xFF = Octal 0377");
45 wmove (wpopup, 3, (OFFSET_BOX_WIDTH / 2) -
46 (OFFSET_BOX_STRING_BOX / 2)
47 - (strlen ("Offset:") / 2));
48 wprintw (wpopup, "Offset: ");
49 memset (offsetstr, 0, OFFSET_STRING_BUF);
50
51 sprintf (offsetstr, "0x");
52 /* uncomment to have eof offset autofilled in string box
53 sprintf (offsetstr, "0x%08lX", filesize);
54 */
55 werase (Globals.whelp);
56 wmove (Globals.whelp, 0, 0);
57 wprintw (Globals.whelp, "^G/^X/Escape Cancel ^U Clear input");
58 wrefresh (Globals.whelp);
59
60 offstr = stringBox (wpopup, 3, (OFFSET_BOX_WIDTH / 2),
61 OFFSET_BOX_STRING_BOX,
62 OFFSET_BOX_STRING_BOX, offsetstr);
63 if (!*offstr)
64 off = offset;
65 else
66 {
67 errno = 0;
68 off = strtoul (offstr, NULL, 0);
69 if (errno) /* Possible ERANGE return */
70 offset = 0;
71 else if (off > filesize)
72 offset = filesize;
73 else
74 offset = off;
75 cursor_x = mappos (offset & M_0x0F);
76 cursor_y = MAIN_TOP_LINE;
77 }
78 free (offstr);
79 delwin (wpopup);
80 /* signal (SIGINT, handleInterrupt); */
81 sigaction (SIGINT, &sig_old, NULL);
82 }
83
84
85 /* Print the whole line between the box border. */
86 static void
print_line(WINDOW * win,int cols,int y,char c)87 print_line (WINDOW *win, int cols, int y, char c)
88 {
89 int i = 0;
90
91 wmove (win, y, 1);
92 for (i = 0; i < (cols - 2); i++)
93 wprintw (win, "%c", c);
94 }
95
96
97 void
do_outer_help_box(WINDOW * win,int y,int lines)98 do_outer_help_box (WINDOW *win, int y, int lines)
99 {
100 box (win, 0, 0);
101
102 wmove (win, 0, (COLS / 2) - (strlen ("Help Menu") / 2) - 2);
103 wprintw (win, "Help Menu");
104
105 if (y > 0)
106 {
107 wmove (win, 0, COLS - strlen ("(more)") - 1);
108 wprintw (win, "(more)");
109 }
110 if ((y + lines) < (Globals.help_msg_count + 1))
111 {
112 wmove (win, MAIN_BOTTOM_LINE, COLS - strlen ("(more)") - 1);
113 wprintw (win, "(more)");
114 }
115
116 }
117
118
119 /*
120 initialize the help at the start of the program so that it's dynamic
121 so we can have the right help when you start up, then it will be easy.
122
123 */
124
125
126 void
popupHelp(void)127 popupHelp (void)
128 #define HELP_BOX_HEIGHT MAIN_HEIGHT
129 #define HELP_BOX_WIDTH COLS
130 #define STRING_BUF 80
131 {
132 /* Unless you change what you shouldn't, this is fine */
133 char s[STRING_BUF];
134 int i = 0;
135 int y = 0;
136 WINDOW *wpopup = popupWindow (HELP_BOX_WIDTH, HELP_BOX_HEIGHT);
137 struct sigaction sig_new, sig_old;
138 wchar_t in = 0;
139
140 /* signal (SIGINT, SIG_IGN); */
141 sig_new.sa_handler = SIG_IGN;
142 memset (&sig_new.sa_mask, 0x00, sizeof (sigset_t));
143 sig_new.sa_flags = 0;
144 sigaction (SIGINT, &sig_new, &sig_old);
145
146 wattrset (wpopup, color_term ? COLOR_PAIR(1) : A_NORMAL);
147 mvwin (wpopup, MAIN_TOP_LINE, 0);
148
149 do_outer_help_box (wpopup, 0, LINES - 3);
150
151 for (y = 1; y < MAIN_BOTTOM_LINE; y++)
152 print_line (wpopup, HELP_BOX_WIDTH, y, ' ');
153
154 memset (s, 0x00, STRING_BUF);
155 #ifdef HAVE_SNPRINTF
156 snprintf (s, STRING_BUF,
157 "[N]Curses Hexedit %s Adam Rogoyski <apoc@laker.net>", VERSION);
158 #else
159 sprintf (s,
160 "[N]Curses Hexedit %s Adam Rogoyski <apoc@laker.net>", VERSION);
161 #endif
162 werase (Globals.whelp);
163 wmove (Globals.whelp, 0, (COLS / 2) - (strlen (s) / 2));
164 wprintw (Globals.whelp, "%s", s);
165 wrefresh (Globals.whelp);
166
167 y = 0;
168 help_print (wpopup, y, LINES - 3);
169
170 wrefresh (wpopup);
171
172 while ((in = getch ()))
173 {
174 switch (in)
175 {
176 case '\n':
177 case ESCAPE_CHARACTER:
178 case CONTROL_C:
179 case CONTROL_G:
180 case CONTROL_X:
181 case 'q':
182 case 'Q':
183 delwin (wpopup);
184 sigaction (SIGINT, &sig_old, NULL);
185 return;
186
187 case KEY_DOWN:
188 case 'j':
189 case 'J':
190 if ((y + LINES - 5) < (Globals.help_msg_count - 1))
191 y++;
192 break;
193
194 case KEY_UP:
195 case 'k':
196 case 'K':
197 if (y > 0)
198 y--;
199 break;
200
201 default:
202 continue;
203
204 }
205
206 for (i = 1; i < MAIN_BOTTOM_LINE; i++)
207 print_line (wpopup, HELP_BOX_WIDTH, i, ' ');
208
209 help_print (wpopup, y, LINES - 3);
210 do_outer_help_box (wpopup, y, LINES - 3);
211
212 wrefresh (wpopup);
213 }
214
215 delwin (wpopup);
216
217 /* signal (SIGINT, handleInterrupt); */
218 sigaction (SIGINT, &sig_old, NULL);
219 }
220
221
222 /* Brings up a popup window and prompts with a stringbox for the
223 * filename to save as.
224 */
225 int
popupFileSave(void)226 popupFileSave (void)
227 #define FILE_SAVE_STRING_BOX 50
228 #define FILE_SAVE_STRING_BOX_MAX PATH_MAX
229 #define FILE_SAVE_HEIGHT 6
230 #define FILE_SAVE_WIDTH 70
231 {
232 int result = 0;
233 int saved = 0;
234 char *filename = NULL;
235 FILE *fp = NULL;
236 WINDOW *wpopup = popupWindow (FILE_SAVE_WIDTH, FILE_SAVE_HEIGHT);
237 struct sigaction sig_new, sig_old;
238
239 /* signal (SIGINT, SIG_IGN); */
240 sig_new.sa_handler = SIG_IGN;
241 memset (&sig_new.sa_mask, 0x00, sizeof (sigset_t));
242 sig_new.sa_flags = 0;
243 sigaction (SIGINT, &sig_new, &sig_old);
244
245 wmove (wpopup, 1, (FILE_SAVE_WIDTH / 2) - (strlen ("Save File") / 2));
246 wprintw (wpopup, "Save File");
247 wmove (wpopup, 3, 2);
248 wprintw (wpopup, "Filename: ");
249 werase (Globals.whelp);
250 wmove (Globals.whelp, 0, 0);
251 wprintw (Globals.whelp, "^G/^X/Escape Cancel");
252 wrefresh (Globals.whelp);
253 filename = stringBox (wpopup, 3, 2 + strlen ("Filename: "),
254 FILE_SAVE_STRING_BOX_MAX,
255 FILE_SAVE_STRING_BOX, (char *) Globals.filename);
256 chompWhiteSpace (filename);
257
258 if (!filename);
259 else if (!*filename)
260 {
261 free (filename);
262 filename = NULL;
263 }
264 else
265 {
266 if (!strcmp (Globals.filename, filename))
267 {
268 fclose (Globals.fp);
269 fp = fopen (filename, "r+b");
270 Globals.fp = fp;
271 }
272 else
273 fp = fopen (filename, "wb");
274 if (!fp)
275 {
276 wattroff (wpopup, A_REVERSE);
277 werase (wpopup);
278 box (wpopup, 0, 0);
279 wmove (wpopup, 1, (FILE_SAVE_WIDTH / 2)
280 - (strlen ("Cannot Save File") / 2));
281 wprintw (wpopup, "Cannot Save File");
282 wmove (wpopup, FILE_SAVE_HEIGHT - 3, (FILE_SAVE_WIDTH / 2) -
283 (strlen (strerror (errno)) + strlen ("Reason: ")) / 2);
284 wprintw (wpopup, "Reason: %s", strerror (errno));
285 wrefresh (wpopup);
286 getch ();
287 if (!strcmp (Globals.filename, filename))
288 {
289 Globals.fp = fopen (Globals.filename, "rb");
290 if (!Globals.fp)
291 die_horribly ("Cannot save to original file, nor reopen it",
292 NULL);
293 }
294 if (filename)
295 free (filename);
296 filename = NULL;
297 }
298 else
299 {
300 int buf = 0;
301 unsigned long i = 0;
302 int len = Globals.filesize + 1;
303
304 /* If it's all in memory just write it out to the file */
305 if (Globals.fullsize)
306 {
307 while (len > 0)
308 {
309 if (len > DEFAULT_READ_BUFFER)
310 buf = DEFAULT_READ_BUFFER;
311 else
312 buf = len;
313 result = fwrite (filebuf + i, 1, buf, fp);
314 if (result > 0)
315 len -= result;
316 else
317 len = 0;
318 i += result;
319 }
320 ftruncate (fileno (fp), Globals.filesize);
321 }
322 /* If not, we read it from the old file, make the neccessary
323 * changes, and then write it to the new file (possibly the
324 * same file.
325 */
326 else
327 {
328 /* Two situations:
329 * 1. If we are writing to the same file, we just add the
330 * changes (fast).
331 * 2. If we are writing to a new file, we need to re-read
332 * the entire old file and make the changes as we go (slow).
333 */
334 if (!strcmp (Globals.filename, filename) || Globals.fixed_disk)
335 /* same file, just add the changes */
336 {
337 /* cycle through the hash and write all the changes */
338 commit_changes_in_hash (fp);
339 }
340 else
341 /* different file, re-read whole old one and add changes */
342 {
343 unsigned char buffer[DEFAULT_READ_BUFFER];
344 unsigned char c = '\0';
345 int pos = 0;
346 int result2 = 0;
347 int tst = 0;
348
349 memset (buffer, 0x00, DEFAULT_READ_BUFFER);
350 while (len > 0)
351 {
352 if (len > DEFAULT_READ_BUFFER)
353 buf = DEFAULT_READ_BUFFER;
354 else
355 buf = len;
356
357 result = fseek (Globals.fp, pos, SEEK_SET);
358 if (result < 0)
359 die_horribly ("Cannot re-read original file",
360 Globals.filename);
361
362 result = fread (buffer, 1, buf, Globals.fp);
363 if (ferror (Globals.fp))
364 die_horribly ("Cannot re-read original file",
365 Globals.filename);
366 /* Make edited changes to file */
367 for (i = pos; i < (pos + result); i++)
368 {
369 if (!hash_lookup (i, &c))
370 buffer[i - pos] = c;
371 }
372
373
374 tst = fseek (fp, pos, SEEK_SET);
375 if (tst < 0)
376 die_horribly ("Cannot read file",
377 filename);
378
379 result2 = fwrite (buffer, 1, result, fp);
380 if (result2 != result)
381 die_horribly ("Cannot write new file correctly", "fwrite");
382 if (result > 0)
383 len -= result;
384 else
385 len = 0;
386 pos += result;
387 }
388 free ((char *) Globals.filename);
389 Globals.filename = filename;
390 filename = NULL;
391 }
392 }
393 fflush (fp);
394 result = 0;
395 if (fp != Globals.fp)
396 result = fclose (fp);
397 else
398 result = fflush (fp);
399 if (result == -1)
400 {
401 wattroff (wpopup, A_REVERSE);
402 werase (wpopup);
403 box (wpopup, 0, 0);
404 wmove (wpopup, 1, (FILE_SAVE_WIDTH / 2)
405 - (strlen ("Cannot Save File") / 2));
406 wprintw (wpopup, "bCannot Save File");
407 wmove (wpopup, FILE_SAVE_HEIGHT - 3, (FILE_SAVE_WIDTH / 2) -
408 (strlen (strerror (errno)) + strlen ("Reason: ")) / 2);
409 wprintw (wpopup, "Reason: %s", strerror (errno));
410 wrefresh (wpopup);
411 if (filename)
412 free (filename);
413 filename = NULL;
414 getch ();
415 }
416 else
417 {
418 saved = 1;
419 Globals.modified = 0;
420 }
421 }
422 if (filename)
423 {
424 free ((char *) Globals.filename);
425 Globals.filename = filename;
426 filename = NULL;
427 }
428 }
429 if (filename)
430 free (filename);
431 delwin (wpopup);
432 /* signal (SIGINT, handleInterrupt); */
433 sigaction (SIGINT, &sig_old, NULL);
434 return saved;
435 }
436
437
438 /* XXX This is really ugly, this needs to be redone eventually. I
439 * want to add search/replace type things, but it's too ugly, needs
440 * to be totaly redone, I don't feel like figuring out how it works.
441 * I must have been up really late.
442 */
443 void
search(int findnext)444 search (int findnext)
445 #define SEARCH_BOX_WIDTH 60
446 #define SEARCH_BOX_HEIGHT 10
447 #define SEARCH_STRING_BOX 50
448 #define SEARCH_STRING_BOX_MAX 50
449 {
450 char *options[] = { "Find Next",
451 "search for text string",
452 "search for Hex bytes" };
453 static unsigned char *laststr = NULL;
454 static int first = 1;
455 static int last_str_len = 0;
456 static unsigned char *s = NULL;
457 int done = 0;
458 int selection = 0;
459 wchar_t in = 0;
460 WINDOW *wpopup = popupWindow (SEARCH_BOX_WIDTH, SEARCH_BOX_HEIGHT);
461 struct sigaction sig_new, sig_old;
462
463 if (findnext && !laststr)
464 return;
465
466 /* signal (SIGINT, SIG_IGN); */
467 sig_new.sa_handler = SIG_IGN;
468 memset (&sig_new.sa_mask, 0x00, sizeof (sigset_t));
469 sig_new.sa_flags = 0;
470 sigaction (SIGINT, &sig_new, &sig_old);
471
472
473 werase (Globals.whelp);
474 wmove (Globals.whelp, 0, 0);
475 wprintw (Globals.whelp,
476 "^G/^X/Escape Cancel F/N Find Next A Text Search H Hex Search");
477 wrefresh (Globals.whelp);
478
479 wmove (wpopup, 1, (SEARCH_BOX_WIDTH / 2) - (strlen ("Search") / 2));
480 wprintw (wpopup, "Search");
481 if (first)
482 selection = 1;
483 if (!first)
484 wattrset (wpopup, A_REVERSE);
485 wmove (wpopup, 3, (SEARCH_BOX_WIDTH / 2) - (strlen (options[0]) / 2));
486 wprintw (wpopup, "%s", options[0]);
487 if (!first)
488 wattroff (wpopup, A_REVERSE);
489 if (first)
490 wattrset (wpopup, A_REVERSE);
491 wmove (wpopup, 5, (SEARCH_BOX_WIDTH / 2) - (strlen (options[1]) / 2));
492 wprintw (wpopup, "%s", options[1]);
493 if (first)
494 wattroff (wpopup, A_REVERSE);
495 wmove (wpopup, 7, (SEARCH_BOX_WIDTH / 2) - (strlen (options[2]) / 2));
496 wprintw (wpopup, "%s", options[2]);
497 if (findnext)
498 {
499 selection = 0;
500 done = 1;
501 }
502 else
503 wrefresh (wpopup);
504 while (!done && ((in = getch()) != '\n'))
505 {
506 switch (in)
507 {
508 case 'f':
509 case 'F':
510 case 'n':
511 case 'N':
512 first = 0;
513 done = 1;
514 selection = 0;
515 break;
516 case 'a':
517 case 'A':
518 first = 0;
519 done = 1;
520 selection = 1;
521 break;
522 case 'h':
523 case 'H':
524 first = 0;
525 done = 1;
526 selection = 2;
527 break;
528 case CONTROL_C:
529 case CONTROL_G:
530 case CONTROL_X:
531 case ESCAPE_CHARACTER:
532 done = -1;
533 break;
534 case KEY_UP:
535 case KEY_DOWN:
536 case 'j':
537 case 'J':
538 case 'k':
539 case 'K':
540 if (toupper (in) == 'J')
541 in = KEY_DOWN;
542 else if (toupper (in) == 'K')
543 in = KEY_UP;
544 if ((in == KEY_UP) && (selection == 0))
545 selection = 2;
546 else if (in == KEY_UP)
547 selection--;
548 if ((in == KEY_DOWN) && (selection == 2))
549 selection = 0;
550 else if (in == KEY_DOWN)
551 selection++;
552 if (first && (selection == 0) && (in == KEY_UP))
553 selection = 2;
554 else if (first && (selection == 0) && (in == KEY_DOWN))
555 selection = 1;
556 if (selection == 0)
557 wattrset (wpopup, A_REVERSE);
558 wmove (wpopup, 3, (SEARCH_BOX_WIDTH / 2) - (strlen (options[0]) / 2));
559 wprintw (wpopup, "%s", options[0]);
560 if (selection == 0)
561 wattroff (wpopup, A_REVERSE);
562 if (selection == 1)
563 wattrset (wpopup, A_REVERSE);
564 wmove (wpopup, 5, (SEARCH_BOX_WIDTH / 2) - (strlen (options[1]) / 2));
565 wprintw (wpopup, "%s", options[1]);
566 if (selection == 1)
567 wattroff (wpopup, A_REVERSE);
568 if (selection == 2)
569 wattrset (wpopup, A_REVERSE);
570 wmove (wpopup, 7, (SEARCH_BOX_WIDTH / 2) - (strlen (options[2]) / 2));
571 wprintw (wpopup, "%s", options[2]);
572 if (selection == 2)
573 wattroff (wpopup, A_REVERSE);
574 wrefresh (wpopup);
575 break;
576 }
577 }
578 if (done == -1)
579 {
580 /* signal (SIGINT, handleInterrupt); */
581 sigaction (SIGINT, &sig_old, NULL);
582 return;
583 }
584 done = 0;
585 wmove (wpopup, 3, (SEARCH_BOX_WIDTH / 2) - (strlen (options[0]) / 2));
586 wprintw (wpopup, "%*c", strlen (options[0]), ' ');
587 wmove (wpopup, 5, (SEARCH_BOX_WIDTH / 2) - (strlen (options[1]) / 2));
588 wprintw (wpopup, "%*c", strlen (options[1]), ' ');
589 wmove (wpopup, 7, (SEARCH_BOX_WIDTH / 2) - (strlen (options[2]) / 2));
590 wprintw (wpopup, "%*c", strlen (options[2]), ' ');
591 if (selection == 0)
592 {
593 struct foundit *spot = NULL;
594 if (offset < Globals.filesize - 1)
595 spot = boyer_moore_search (laststr, offset + 1,
596 last_str_len,
597 Globals.filesize - offset);
598 if (spot && spot->flag)
599 {
600 offset += spot->offset + 1; /* started search one character
601 ahead of offset */
602 cursor_y = 1;
603 cursor_x = mappos (offset & M_0x0F);
604 }
605 else
606 {
607 int i = 0;
608 wattroff (wpopup, A_REVERSE);
609 wmove (wpopup, (SEARCH_BOX_HEIGHT / 2) + 1, 1);
610 for (i = 2; i < SEARCH_BOX_WIDTH; i++)
611 wprintw (wpopup, " ");
612 wmove (wpopup, (SEARCH_BOX_HEIGHT / 2) + 1, (SEARCH_BOX_WIDTH / 2)
613 - (strlen ("** String not found **") / 2));
614 wprintw (wpopup, "** String not found **");
615 wrefresh (wpopup);
616 getch ();
617 }
618 }
619 else if (selection == 1)
620 {
621 unsigned char *str = NULL;
622 unsigned char *strb = NULL;
623 if (laststr)
624 {
625 free (laststr);
626 laststr = NULL;
627 }
628 wmove (wpopup, 1, (SEARCH_BOX_WIDTH / 2) - (strlen ("Text String")
629 / 2));
630 wprintw (wpopup, "Text String");
631 str = strb = (unsigned char *)
632 stringBox (wpopup, (SEARCH_BOX_HEIGHT / 2) + 1,
633 (SEARCH_BOX_WIDTH - SEARCH_STRING_BOX) / 2,
634 SEARCH_STRING_BOX_MAX,
635 SEARCH_STRING_BOX, NULL);
636 s = (unsigned char *) str;
637 laststr = s;
638 for (str = s + SEARCH_STRING_BOX_MAX - 1; str != (s - 1); str--)
639 {
640 if (*str != ' ')
641 {
642 *(str + 1) = '\0';
643 done = 1;
644 break;
645 }
646 }
647 if (Globals.charset == EBCDIC_CHAR_SET)
648 {
649 unsigned char *p = s;
650 while (*p)
651 {
652 *p = findEBCDIC (*p);
653 p++;
654 }
655 }
656 if (done)
657 {
658 struct foundit *spot = NULL;
659 if (offset < Globals.filesize - 1)
660 spot = boyer_moore_search (s, offset + 1,
661 last_str_len = strlen ((char *) s),
662 Globals.filesize - offset);
663 if (spot && spot->flag)
664 {
665 offset += spot->offset + 1; /* started search one character
666 ahead of offset */
667 cursor_y = 1;
668 cursor_x = mappos (offset & M_0x0F);
669 }
670 else
671 {
672 int i = 0;
673 wattroff (wpopup, A_REVERSE);
674 wmove (wpopup, (SEARCH_BOX_HEIGHT / 2) + 1, 1);
675 for (i = 2; i < SEARCH_BOX_WIDTH; i++)
676 wprintw (wpopup, " ");
677 wmove (wpopup, (SEARCH_BOX_HEIGHT / 2) + 1, (SEARCH_BOX_WIDTH / 2)
678 - (strlen ("** String not found **") / 2));
679 wprintw (wpopup, "** String not found **");
680 wrefresh (wpopup);
681 getch ();
682 }
683 }
684 }
685 else if (selection == 2)
686 {
687 #define BYTE_SEARCH_LENGTH 16
688 struct ret_string *retr;
689 wmove (wpopup, 1, (SEARCH_BOX_WIDTH / 2) - (strlen ("Byte Search")
690 / 2));
691 wprintw (wpopup, "Byte Search");
692 retr = hex_string_box (wpopup, BYTE_SEARCH_LENGTH, SEARCH_BOX_WIDTH);
693 if (retr)
694 {
695 struct foundit *spot = NULL;
696 if (offset < Globals.filesize - 1)
697 spot = boyer_moore_search (retr->str, offset + 1,
698 last_str_len = retr->len,
699 Globals.filesize - offset);
700 if (spot && spot->flag)
701 {
702 offset += spot->offset + 1; /* started search one character
703 ahead of offset */
704 cursor_y = 1;
705 cursor_x = mappos (offset & M_0x0F);
706 if (laststr)
707 free (laststr);
708 laststr = malloc (retr->len + 1);
709 memset (laststr, 0x00, retr->len + 1);
710 memcpy (laststr, retr->str, retr->len);
711 free (retr->str);
712 retr->str = NULL;
713 retr->len = 0;
714 }
715 else
716 {
717 int i = 0;
718 wattroff (wpopup, A_REVERSE);
719 wmove (wpopup, (SEARCH_BOX_HEIGHT / 2) + 1, 1);
720 for (i = 2; i < SEARCH_BOX_WIDTH; i++)
721 wprintw (wpopup, " ");
722 wmove (wpopup, (SEARCH_BOX_HEIGHT / 2) + 1, (SEARCH_BOX_WIDTH / 2)
723 - (strlen ("** String not found **") / 2));
724 wprintw (wpopup, "** String not found **");
725 wrefresh (wpopup);
726 getch ();
727 }
728 }
729 }
730 first = 0;
731 /* signal (SIGINT, handleInterrupt); */
732 sigaction (SIGINT, &sig_old, NULL);
733 delwin (wpopup);
734 }
735
736
737 /* Brings up a prompt in the help window and prompts for the relative
738 * offset to jump by.
739 */
740 void
jump_relative_offset(wchar_t sign)741 jump_relative_offset (wchar_t sign)
742 /* pass sign as '+' or '-' to prompt for an offset to jump to relative
743 * to current offset.
744 * pass sign as 0 to jump relative to current offset the amount prompted
745 * last time we called this routine.
746 */
747 {
748 static wchar_t in = '\0';
749 static unsigned long offs = 0x00;
750 unsigned long offst = offset;
751
752 if (sign)
753 {
754 offs = 0x00;
755 werase (Globals.whelp);
756 wmove (Globals.whelp, 0, 0);
757 wprintw (Globals.whelp, "Offset: 0x%08lX %c 0x", offset, sign);
758 wrefresh (Globals.whelp);
759
760 while ((in = getch ()) != '\n')
761 {
762 if (!isHexChar (in))
763 {
764 switch (in)
765 {
766 case BACKSPACE:
767 case CONTROL_H:
768 case KEY_BACKSPACE:
769 case KEY_DC:
770 #ifdef __PDCURSES__
771 case CTL_BKSP:
772 #endif
773 offs >>= 4;
774 break;
775
776 case CONTROL_U:
777 offs = 0x00;
778 break;
779
780 case CONTROL_G:
781 case CONTROL_X:
782 printHelpWindow ();
783 wrefresh (Globals.whelp);
784 move (cursor_y, cursor_x);
785 refresh ();
786 return;
787
788 default:
789 continue;
790 }
791 }
792 else
793 {
794 /* shift left to make room for new hex digit and or it in least
795 * significant place
796 */
797 offs <<= 4;
798 offs |= getHexValue (in);
799 }
800
801 werase (Globals.whelp);
802 wmove (Globals.whelp, 0, 0);
803 wprintw (Globals.whelp, "Offset: 0x%08lX %c 0x%lX",
804 offset, sign, offs);
805 wrefresh (Globals.whelp);
806 }
807 }
808
809 if (sign)
810 in = sign;
811
812 if (offs)
813 {
814 if (in == '+')
815 {
816 offst += offs;
817 /* Check for overflow */
818 if (offst > Globals.filesize)
819 {
820 offst = Globals.filesize;
821 do_beep ();
822 }
823 }
824 else
825 {
826 offst -= offs;
827 /* Check for unsigned underflow */
828 if (offst > Globals.filesize)
829 {
830 offst = 0x00;
831 do_beep ();
832 }
833 }
834
835 }
836
837 cursor_x = mappos (offst & M_0x0F);
838 cursor_y = 1;
839
840 offset = offst;
841
842 printStatusWindow ();
843 printHelpWindow ();
844 drawdump (offset);
845 wrefresh (Globals.wmain);
846 wrefresh (Globals.wstatus);
847 wrefresh (Globals.whelp);
848 move (cursor_y, cursor_x);
849 refresh ();
850 }
851