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