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