1 /******************************************************************************\
2 * Copyright (C) 2001, hexcurse is written by Jewfish and Armoth *
3 * *
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 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the Free Software *
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
17 * *
18 \******************************************************************************/
19 #include "hex.h"
20
21 /******************************************************\
22 * Description: Inits the menu and the user interface *
23 * that the hex editor uses. *
24 \******************************************************/
init_menu(WINS * windows)25 void init_menu(WINS *windows)
26 {
27 int x;
28 WINDOW *win;
29
30 /*signal(SIGCHLD, SIG_DFL); */
31 signal(SIGSEGV, catchSegfault); /* catch segfault sig */
32 /* the following is still under development, please report any bugs found */
33 signal(SIGWINCH, checkScreenSize); /*catch resize screen */
34
35 /* draw the windows */
36 windows->hex_outline = drawbox(0, 0, LINES, hex_outline_width);
37 windows->ascii_outline = drawbox(0, hex_outline_width + 1, LINES,
38 ascii_outline_width);
39 windows->scrollbar = newwin(LINES, 1, 0, hex_outline_width);
40
41 windows->hex = newwin(LINES - 2, hex_win_width, 1, MIN_ADDR_LENGTH + 2);
42 windows->ascii = newwin(LINES - 2, ascii_win_width, 1,
43 hex_outline_width + 2);
44 windows->address = newwin(LINES - 2, MIN_ADDR_LENGTH + 1, 1, 1);
45
46 windows->cur_address = newwin(1, MIN_ADDR_LENGTH, 0, 1);
47
48 waddch(windows->scrollbar, ACS_UARROW);
49 wattron(windows->scrollbar, A_REVERSE);
50 waddch(windows->scrollbar, ACS_DIAMOND);
51 wattroff(windows->scrollbar, A_REVERSE);
52 for (x = 0; x < LINES - 2; x++)
53 waddch(windows->scrollbar, ACS_CKBOARD);
54 waddch(windows->scrollbar, ACS_DARROW);
55 wrefresh(windows->scrollbar);
56
57 cbreak(); /* allow cbreak() */
58 noecho(); /* disable echoing */
59 raw();
60
61 win = windows->hex;
62 for (x = 0; x <= 2; x++)
63 {
64 idlok(win, TRUE); /* enable scrolling */
65
66 keypad(win, TRUE); /* enable the keypad */
67
68 win = (x == 0) ? windows->ascii:windows->address;
69 }
70
71 }
72
73 /******************************************************\
74 * Description: Deallocates the windows *
75 * that the hex editor uses. *
76 \******************************************************/
free_windows(WINS * windows)77 void free_windows(WINS *windows)
78 {
79 delwin(windows->cur_address);
80 windows->cur_address = NULL;
81
82 delwin(windows->address);
83 windows->address = NULL;
84
85 delwin(windows->ascii);
86 windows->ascii = NULL;
87
88 delwin(windows->hex);
89 windows->hex = NULL;
90
91 delwin(windows->scrollbar);
92 windows->scrollbar = NULL;
93
94 delwin(windows->ascii_outline);
95 windows->ascii_outline = NULL;
96
97 delwin(windows->hex_outline);
98 windows->hex_outline = NULL;
99 }
100
101 /******************************************************\
102 * Description: exit the program printing out an error*
103 * from the errno value. *
104 \******************************************************/
exit_err(char * err_str)105 void exit_err(char *err_str)
106 {
107 endwin(); /* end curses screen */
108 perror(err_str); /* print errno */
109 printf("\n\n");
110 exit(EXIT_FAILURE); /* return with exitval*/
111 }
112
113 /******************************************************\
114 * Description: Initialize the curses graphical screen*
115 * If the screen does not support curses *
116 * exit gracefully. *
117 \******************************************************/
init_screen(void)118 void init_screen(void)
119 {
120 if ((initscr()) == NULL) /*couldn't init screen*/
121 {
122 perror("initscr"); /* print out error */
123 printf("exiting\n");
124 exit(EXIT_FAILURE);
125 }
126
127 }
128
129 /******************************************************\
130 * Description: Terminate the curses screen and exit *
131 * out of the program. *
132 \******************************************************/
screen_exit(int exit_val)133 void screen_exit(int exit_val)
134 {
135 endwin(); /* end curses screeen */
136 printf("\n");
137 exit(exit_val);
138 }
139
140 /******************************************************\
141 * Description: Initialize function key menu interface*
142 \******************************************************/
init_fkeys()143 void init_fkeys()
144 {
145 slk_set(1, "Help", 1); /* init menu tabs */
146 slk_set(2, "Save", 1);
147 slk_set(3, "Open", 1);
148 slk_set(4, "Goto", 1);
149 slk_set(5, "Find", 1);
150
151 slk_set(7, "Hex Edit", 1);
152 slk_set(8, "Quit", 1);
153 slk_set(9, "Quit", 1);
154 slk_noutrefresh(); /* refresh the screen */
155 }
156
157 /******************************************************\
158 * Description: Determines the screen size of the the *
159 * terminal and prompts for the user to *
160 * change the screen. *
161 \******************************************************/
checkScreenSize(int sig)162 RETSIGTYPE checkScreenSize(int sig)
163 {
164 int count;
165
166 /* Avoid unused variable warning */
167 UNUSED(sig);
168
169 clearScreen(windows);
170 endwin();
171 init_screen(); /* init visuals */
172 init_colors();
173
174 slk_clear(); /* init menu bar */
175 slk_restore(); /* restore bottom menu*/
176 slk_noutrefresh();
177 doupdate();
178 /* recacl these values*/
179 BASE = (COLS - 6 - MIN_ADDR_LENGTH) / 4; /*base for the number */
180 hex_outline_width = (BASE * 3) + 3 + MIN_ADDR_LENGTH;
181 MAXY = LINES - 3;
182 hex_win_width = BASE * 3;
183 ascii_outline_width = BASE + 2;
184 ascii_win_width = BASE;
185 maxlines = maxLines((fpIN != NULL) ? maxLoc(fpIN) : 0);
186 currentLine = 0;
187 SIZE_CH = TRUE;
188 /* check for term size*/
189 if ((COLS < MIN_COLS) || (LINES < MIN_LINES))
190 {
191 /*
192 endwin();
193 printf("\n\n\n\nscreen size too small\n");
194 exit(0);
195 */
196
197 init_fkeys(); /* define menu bar */
198 init_menu(windows); /* init windows */
199 clearScreen(windows);
200 slk_clear();
201 mvwprintw(windows->hex, 0, 0, "Your screen is too small");
202 /*mvwprintw(windows->hex, 1, 2, "Resize it to continue");*/
203 refreshall(windows);
204 doupdate();
205 }
206 else
207 {
208 init_fkeys(); /* define menu bar */
209 init_menu(windows); /* init windows */
210 wmove(windows->hex,0,0);
211 if (fpIN) /* if a file is open */
212 {
213 for (count = 0; count <= MAXY && count <= maxLines(maxLoc(fpIN));
214 count++)
215 outline(fpIN, count);
216
217 mvwprintw(windows->cur_address, 0, 0, "%0*d", MIN_ADDR_LENGTH, 0);
218 wmove(windows->hex,0,0);
219 }
220
221 refreshall(windows);
222 wnoutrefresh(windows->cur_address);
223 /* this next refresh is to put the cursor in the correct window */
224 wnoutrefresh(windows->hex);
225 doupdate();
226 }
227 }
228
229 /******************************************************\
230 * Description: refresh all of the curses windows *
231 \******************************************************/
refreshall(WINS * win)232 void refreshall(WINS *win)
233 {
234 slk_noutrefresh(); /* refresh fkeys menu */
235 wnoutrefresh(win->hex_outline); /* refresh all windows*/
236 wnoutrefresh(win->ascii_outline);
237 wnoutrefresh(win->scrollbar);
238 wnoutrefresh(win->ascii);
239 wnoutrefresh(win->address);
240 wnoutrefresh(win->hex);
241 }
242
243 /******************************************************\
244 * Description: draws a box with the given parameters *
245 * these boxes are used to create the *
246 * user interface. The function returns *
247 * the newly created window *
248 \******************************************************/
drawbox(int y,int x,int height,int width)249 WINDOW *drawbox(int y, int x, int height, int width)
250 {
251 WINDOW *win;
252 win = newwin(height, width, y, x); /* create a new window*/
253
254 box(win, 0, 0); /* draw the outline */
255
256 return win; /*return created win */
257 }
258
259 /******************************************************\
260 * Description: construct a scroll bar that is used *
261 * for scrolling through the hex editor *
262 \******************************************************/
scrollbar(WINS * windows,int cl,long maxLines)263 void scrollbar(WINS *windows, int cl, long maxLines)
264 {
265 float x, percent;
266
267 /* Avoid unused variable warning */
268 UNUSED(maxLines);
269
270 /* cl really should be a long, it wasn't changed because cl is used
271 * in other functions as an int. Eventually everything should be using
272 * long rather than int */
273
274 if (fpIN != NULL)
275 percent = (float)cl/(float)maxLoc(fpIN); /* protect against x/0*/
276 else
277 percent = 0.0;
278
279 x = (int)(percent * (float)(LINES));
280 x = (x < 1) ? 1 : x;
281 x = (x >= (LINES - 1)) ? LINES - 2 : x;
282
283 wattron(windows->scrollbar, A_REVERSE); /* set attribs on bar */
284 wattron(windows->scrollbar, A_REVERSE); /* set attribs on bar */
285 mvwaddch(windows->scrollbar, (int)x, 0, ACS_DIAMOND);
286 wattroff(windows->scrollbar, A_REVERSE);
287 wnoutrefresh(windows->scrollbar); /* refresh the bar */
288 mvwaddch(windows->scrollbar, (int)x, 0, ACS_CKBOARD);
289 }
290
291 /********************************************************\
292 * Description: outputs key command help *
293 * Returns: none *
294 \********************************************************/
printHelp(WINS * win)295 void printHelp(WINS *win)
296 {
297 WINDOW *ctrl, *help, *small;
298
299 ctrl = newwin(LINES - 2, 9, 1, 1),
300 help = newwin(LINES - 2, hex_win_width, 1, 10),
301 small = newwin(LINES - 2, ascii_win_width, 1, hex_outline_width + 2);
302
303 if ((LINES < 18) || (COLS < 78)) /* min size to display*/
304 {
305 mvwprintw(help, 0, 0, "Screen too small to display help");
306 wmove(help,0,0);
307 }
308 else
309 {
310 wmove(ctrl,0,0);
311 mvwprintw(ctrl, 0, 1, "Ctrl Key"); /* print in address */
312 mvwprintw(ctrl, 2, 1, "CTRL+?");
313 mvwprintw(ctrl, 3, 1, "CTRL+S");
314 mvwprintw(ctrl, 4, 1, "CTRL+O");
315 mvwprintw(ctrl, 5, 1, "CTRL+G");
316 mvwprintw(ctrl, 6, 1, "CTRL+F");
317 mvwprintw(ctrl, 7, 1, "CTRL+A");
318 mvwprintw(ctrl, 8, 1, "TAB");
319 mvwprintw(ctrl, 9, 1, "CTRL+Q");
320 mvwprintw(ctrl, 11, 1, "CTRL+U");
321 mvwprintw(ctrl, 12, 1, "CTRL+D");
322 mvwprintw(ctrl, 13, 1, "CTRL+Z");
323 mvwprintw(ctrl, 14, 1, "CTRL+T");
324 mvwprintw(ctrl, 15, 1, "CTRL+B");
325
326 mvwprintw(small, 0, 1, "Function Keys"); /* print in ascii */
327 mvwprintw(small, 2, 1, "Help = F1");
328 mvwprintw(small, 3, 1, "Save = F2");
329 mvwprintw(small, 4, 1, "Open = F3");
330 mvwprintw(small, 5, 1, "Goto = F4");
331 mvwprintw(small, 6, 1, "Find = F5");
332 mvwprintw(small, 7, 1, "HexAdres = F6");
333 mvwprintw(small, 8, 1, "Hex Edit = F7");
334 mvwprintw(small, 9, 1, "Quit = F8");
335 mvwprintw(small, 11, 1, "Page up = PGUP");
336 mvwprintw(small, 12, 1, "Page down= PGDN");
337
338 mvwprintw(help, 0, 10, "HexCurse Keyboard Commands");
339 mvwprintw(help, 2, 2, "Help - you are reading it now");
340 mvwprintw(help, 3, 2, "Save - saves the current file open");
341 mvwprintw(help, 4, 2, "Open - opens a new file");
342 mvwprintw(help, 5, 2, "Goto - goto a specified address");
343 mvwprintw(help, 6, 2, "Find - search for a hex/ascii value");
344 mvwprintw(help, 7, 2, "HexAdres - toggle between hex/decimal address");
345 mvwprintw(help, 8, 2, "Hex Edit - toggle between hex/ASCII windows");
346 mvwprintw(help, 9, 2, "Quit - exit out of the program");
347 mvwprintw(help, 11, 2, "Page up - scrolls one screen up");
348 mvwprintw(help, 12, 2, "Page down- scrolls one screen down");
349 mvwprintw(help, 13, 2, "Undo - reverts last modification");
350 mvwprintw(help, 14, 2, "Home - returns to the top of the file");
351 mvwprintw(help, 15, 2, "End - jumps to the bottom of the file");
352 mvwprintw(help, 17, 12, "Press enter to continue");
353 }
354
355 wnoutrefresh(ctrl); /* refresh new wins */
356 wnoutrefresh(help);
357 wnoutrefresh(small);
358 doupdate(); /* update screen */
359
360 wgetch(ctrl); /* wait for a char */
361
362 delwin(ctrl); /* delete help wins */
363 delwin(help);
364 delwin(small);
365
366 redrawwin(win->hex); /* redraw previous */
367 redrawwin(win->ascii);
368 redrawwin(win->address);
369
370 wnoutrefresh(win->hex); /* refresh */
371 wnoutrefresh(win->ascii);
372 wnoutrefresh(win->address);
373 doupdate(); /* update screen */
374
375 }
376
377 /********************************************************\
378 * Description: scrolls window one line up or down *
379 * Returns: none *
380 \********************************************************/
winscroll(WINS * windows,WINDOW * win,int n,int currentLine)381 void winscroll(WINS *windows, WINDOW *win, int n, int currentLine)
382 {
383 int row, col; /* row and col */
384
385 getyx(win, row, col); /* get cur row/col */
386
387 scrollok(windows->hex, TRUE); /* allow scrolling */
388 scrollok(windows->ascii, TRUE);
389 scrollok(windows->address, TRUE);
390
391 wscrl(windows->hex, n); /* scroll each win */
392 wscrl(windows->ascii, n);
393 wscrl(windows->address, n);
394
395 scrollok(windows->hex, FALSE); /*disable scrolling */
396 scrollok(windows->ascii, FALSE);
397 scrollok(windows->address, FALSE);
398
399 wmove(windows->hex, (n == 1) ? MAXY:0, 0); /* place cursor */
400 wmove(windows->ascii, (n == 1) ? MAXY:0, 0);
401 wmove(windows->address, (n == 1) ? MAXY:0, 0);
402
403 outline(fpIN, currentLine); /* output line */
404
405 wnoutrefresh(windows->hex); /* set win refreshes */
406 wnoutrefresh(windows->ascii);
407 wnoutrefresh(windows->address);
408
409 wmove(win, row, col); /* restore cursor */
410 }
411
412 /******************************************************\
413 * Description: Clears the entire screen *
414 \******************************************************/
clearScreen(WINS * win)415 void clearScreen(WINS *win)
416 {
417 wclear(win->hex);
418 wclear(win->ascii);
419 wclear(win->address);
420 wclear(win->scrollbar);
421 wclear(win->hex_outline);
422 wclear(win->ascii_outline);
423 wclear(win->cur_address);
424 refreshall(win);
425 doupdate();
426 }
427
428
429 /******************************************************\
430 * Description: Creates a "window popup" where given *
431 * the parameters, and message, it *
432 * creates a window and displays the *
433 * message. Some current restrictions *
434 * are that it must only be one line, and*
435 * it is assumed that the text is padded *
436 * with one space left for the border and*
437 * another space left for aesthetics *
438 \******************************************************/
popupWin(char * msg,int time)439 void popupWin(char *msg, int time)
440 {
441 WINDOW *tmpwin;
442
443 int y = (LINES / 2) - 3, /* calc location */
444 len = strlen(msg),
445 x = (COLS - len)/2;
446
447 y = (y < 2) ? 2 : y; /* minimum height */
448 time = (!time) ? 2 : time;
449
450 tmpwin = drawbox(y, x, 5, len + 6); /* create window */
451
452 keypad(tmpwin, TRUE);
453
454 mvwprintw(tmpwin,2,3, msg); /* output mesg */
455 wmove(tmpwin,2,len+4);
456 wrefresh(tmpwin);
457
458 if (time == -1)
459 wgetch(tmpwin);
460 else
461 sleep(time); /* wait */
462
463 delwin(tmpwin);
464
465 wtouchln(windows->hex, y - 1, 5, 1); /* touch windows */
466 wtouchln(windows->ascii, y - 1, 5, 1);
467 wtouchln(windows->address, y - 1, 5, 1);
468 wtouchln(windows->hex_outline, y, 5, 1);
469 wtouchln(windows->ascii_outline, y, 5, 1);
470 wtouchln(windows->scrollbar, y, 5, 1);
471
472 refreshall(windows); /* refresh all wins */
473
474 doupdate();
475 }
476
477 /********************************************************\
478 * Description: Similar to popupWin, only it prmpts the *
479 * user for a character, such as (y/n) *
480 * Returns: Returns character pressed *
481 \********************************************************/
questionWin(char * msg)482 short int questionWin(char *msg)
483 {
484 WINDOW *tmpwin;
485 short int ch;
486
487 int y = (LINES / 2) - 3, /* calc location */
488 len = strlen(msg),
489 x = (COLS - len)/2;
490
491 y = (y < 2) ? 2 : y; /* minimum height */
492
493 tmpwin = drawbox(y, x, 5, len + 6); /* create window */
494
495 mvwprintw(tmpwin,2,3, msg);
496 wmove(tmpwin,2,len+4);
497 wrefresh(tmpwin);
498
499 ch = wgetch(tmpwin);
500
501 delwin(tmpwin);
502
503 wtouchln(windows->hex, y - 1, 5, 1); /* touch the lines */
504 wtouchln(windows->ascii, y - 1, 5, 1); /* covered by win */
505 wtouchln(windows->address, y - 1, 5, 1);
506 wtouchln(windows->hex_outline, y, 5, 1);
507 wtouchln(windows->ascii_outline, y, 5, 1);
508 wtouchln(windows->scrollbar, y, 5, 1);
509
510 refreshall(windows); /* refresh all wins */
511
512 doupdate();
513
514 return ch;
515 }
516