/******************************************************************************\ * Copyright (C) 2001, hexcurse is written by Jewfish and Armoth * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * \******************************************************************************/ #include "hex.h" /******************************************************\ * Description: Inits the menu and the user interface * * that the hex editor uses. * \******************************************************/ void init_menu(WINS *windows) { int x; WINDOW *win; for (x = 1; x < 24; x++) /* blocks all signals */ signal(x, SIG_IGN); /* ignores the sigs */ /*signal(SIGCHLD, SIG_DFL); */ signal(SIGSEGV, catchSegfault); /* catch segfault sig */ /* the following is still under development, please report any bugs found */ signal(SIGWINCH, checkScreenSize); /*catch resize screen */ /* draw the windows */ windows->hex_outline = drawbox(0, 0, LINES, hex_outline_width); windows->ascii_outline = drawbox(0, hex_outline_width + 1, LINES, ascii_outline_width); windows->scrollbar = newwin(LINES, 1, 0, hex_outline_width); windows->hex = newwin(LINES - 2, hex_win_width, 1, 10); windows->ascii = newwin(LINES - 2, ascii_win_width, 1, hex_outline_width + 2); windows->address = newwin(LINES - 2, 9, 1, 1); windows->cur_address = newwin(1, 8, 0, 1); waddch(windows->scrollbar, ACS_UARROW); wattron(windows->scrollbar, A_REVERSE); waddch(windows->scrollbar, ACS_DIAMOND); wattroff(windows->scrollbar, A_REVERSE); for (x = 0; x < LINES - 2; x++) waddch(windows->scrollbar, ACS_CKBOARD); waddch(windows->scrollbar, ACS_DARROW); wrefresh(windows->scrollbar); cbreak(); /* allow cbreak() */ noecho(); /* disable echoing */ raw(); win = windows->hex; for (x = 0; x <= 2; x++) { idlok(win, TRUE); /* enable scrolling */ keypad(win, TRUE); /* enable the keypad */ win = (x == 0) ? windows->ascii:windows->address; } } /******************************************************\ * Description: exit the program printing out an error* * from the errno value. * \******************************************************/ void exit_err(char *err_str) { endwin(); /* end curses screen */ perror(err_str); /* print errno */ printf("\n\n"); exit(EXIT_FAILURE); /* return with exitval*/ } /******************************************************\ * Description: Initialize the curses graphical screen* * If the screen does not support curses * * exit gracefully. * \******************************************************/ void init_screen(void) { if ((initscr()) == NULL) /*couldn't init screen*/ { perror("initscr"); /* print out error */ printf("exiting\n"); exit(EXIT_FAILURE); } } /******************************************************\ * Description: Terminate the curses screen and exit * * out of the program. * \******************************************************/ void screen_exit(int exit_val) { endwin(); /* end curses screeen */ printf("\n"); exit(exit_val); } /******************************************************\ * Description: Initialize function key menu interface* \******************************************************/ void init_fkeys() { slk_set(1, "Help", 1); /* init menu tabs */ slk_set(2, "Save", 1); slk_set(3, "Open", 1); slk_set(4, "Goto", 1); slk_set(5, "Find", 1); slk_set(7, "Hex Edit", 1); slk_set(8, "Quit", 1); slk_set(9, "Quit", 1); slk_noutrefresh(); /* refresh the screen */ } /******************************************************\ * Description: Determines the screen size of the the * * terminal and prompts for the user to * * change the screen. * \******************************************************/ void checkScreenSize(int sig) { int count; clearScreen(windows); endwin(); init_screen(); /* init visuals */ slk_clear(); /* init menu bar */ slk_restore(); /* restore bottom menu*/ slk_noutrefresh(); doupdate(); /* recacl these values*/ BASE = (COLS - 14) / 4; /*base for the number */ hex_outline_width = (BASE * 3) + 11; MAXY = LINES - 3; hex_win_width = BASE * 3; ascii_outline_width = BASE + 2; ascii_win_width = BASE; maxlines = maxLines((fpIN != NULL) ? maxLoc(fpIN) : 0); currentLine = 0; SIZE_CH = TRUE; /* check for term size*/ if ((COLS < MIN_COLS) || (LINES < MIN_LINES)) { /* endwin(); printf("\n\n\n\nscreen size too small\n"); exit(0); */ init_fkeys(); /* define menu bar */ init_menu(windows); /* init windows */ clearScreen(windows); slk_clear(); mvwprintw(windows->hex, 0, 0, "Your screen is too small"); /*mvwprintw(windows->hex, 1, 2, "Resize it to continue");*/ refreshall(windows); doupdate(); } else { init_fkeys(); /* define menu bar */ init_menu(windows); /* init windows */ wmove(windows->hex,0,0); if (fpIN) /* if a file is open */ { for (count = 0; count <= MAXY && count <= maxLines(maxLoc(fpIN)); count++) outline(fpIN, count); /* mvwprintw(windows->cur_address, 0, 0, (printHex) ? "%08X":"%08d", LastLoc); */ mvwprintw(windows->cur_address, 0, 0, "%s", "00000000"); wmove(windows->hex,0,0); /*currentLine = gotoLine(fpIN, 0, LastLoc, maxlines, (editHex) ? windows->hex : windows->ascii); */ } refreshall(windows); wnoutrefresh(windows->cur_address); /* this next refresh is to put the cursor in the correct window */ wnoutrefresh(windows->hex); doupdate(); } } /******************************************************\ * Description: refresh all of the curses windows * \******************************************************/ void refreshall(WINS *win) { slk_noutrefresh(); /* refresh fkeys menu */ wnoutrefresh(win->hex_outline); /* refresh all windows*/ wnoutrefresh(win->ascii_outline); wnoutrefresh(win->scrollbar); wnoutrefresh(win->ascii); wnoutrefresh(win->address); wnoutrefresh(win->hex); } /******************************************************\ * Description: draws a box with the given parameters * * these boxes are used to create the * * user interface. The function returns * * the newly created window * \******************************************************/ WINDOW *drawbox(int y, int x, int height, int width) { WINDOW *win; win = newwin(height, width, y, x); /* create a new window*/ box(win, 0, 0); /* draw the outline */ return win; /*return created win */ } /******************************************************\ * Description: construct a scroll bar that is used * * for scrolling through the hex editor * \******************************************************/ void scrollbar(WINS *windows, int cl, long maxLines) { float x, percent; /* cl really should be a long, it wasn't changed because cl is used * in other functions as an int. Eventually everything should be using * long rather than int */ if (fpIN != NULL) percent = (float)cl/(float)maxLoc(fpIN); /* protect against x/0*/ else percent = 0.0; x = (int)(percent * (float)(LINES)); x = (x < 1) ? 1 : x; x = (x >= (LINES - 1)) ? x = LINES - 2 : x; wattron(windows->scrollbar, A_REVERSE); /* set attribs on bar */ wattron(windows->scrollbar, A_REVERSE); /* set attribs on bar */ mvwaddch(windows->scrollbar, (int)x, 0, ACS_DIAMOND); wattroff(windows->scrollbar, A_REVERSE); wnoutrefresh(windows->scrollbar); /* refresh the bar */ mvwaddch(windows->scrollbar, (int)x, 0, ACS_CKBOARD); } /********************************************************\ * Description: outputs key command help * * Returns: none * \********************************************************/ void printHelp(WINS *win) { WINDOW *ctrl, *help, *small; ctrl = newwin(LINES - 2, 9, 1, 1), help = newwin(LINES - 2, hex_win_width, 1, 10), small = newwin(LINES - 2, ascii_win_width, 1, hex_outline_width + 2); if ((LINES < 18) || (COLS < 78)) /* min size to display*/ { mvwprintw(help, 0, 0, "Screen too small to display help"); wmove(help,0,0); } else { wmove(ctrl,0,0); mvwprintw(ctrl, 0, 1, "Ctrl Key"); /* print in address */ mvwprintw(ctrl, 2, 1, "CTRL+?"); mvwprintw(ctrl, 3, 1, "CTRL+S"); mvwprintw(ctrl, 4, 1, "CTRL+O"); mvwprintw(ctrl, 5, 1, "CTRL+G"); mvwprintw(ctrl, 6, 1, "CTRL+F"); mvwprintw(ctrl, 7, 1, "CTRL+A"); mvwprintw(ctrl, 8, 1, "TAB"); mvwprintw(ctrl, 9, 1, "CTRL+Q"); mvwprintw(ctrl, 11, 1, "CTRL+U"); mvwprintw(ctrl, 12, 1, "CTRL+D"); mvwprintw(ctrl, 13, 1, "CTRL+Z"); mvwprintw(ctrl, 14, 1, "CTRL+T"); mvwprintw(ctrl, 15, 1, "CTRL+B"); mvwprintw(small, 0, 1, "Function Keys"); /* print in ascii */ mvwprintw(small, 2, 1, "Help = F1"); mvwprintw(small, 3, 1, "Save = F2"); mvwprintw(small, 4, 1, "Open = F3"); mvwprintw(small, 5, 1, "Goto = F4"); mvwprintw(small, 6, 1, "Find = F5"); mvwprintw(small, 7, 1, "HexAdres = F6"); mvwprintw(small, 8, 1, "Hex Edit = F7"); mvwprintw(small, 9, 1, "Quit = F8"); mvwprintw(small, 11, 1, "Page up = PGUP"); mvwprintw(small, 12, 1, "Page down= PGDN"); mvwprintw(help, 0, 10, "HexCurse Keyboard Commands"); mvwprintw(help, 2, 2, "Help - you are reading it now"); mvwprintw(help, 3, 2, "Save - saves the current file open"); mvwprintw(help, 4, 2, "Open - opens a new file"); mvwprintw(help, 5, 2, "Goto - goto a specified address"); mvwprintw(help, 6, 2, "Find - search for a hex/ascii value"); mvwprintw(help, 7, 2, "HexAdres - toggle between hex/decimal address"); mvwprintw(help, 8, 2, "Hex Edit - toggle between hex/ASCII windows"); mvwprintw(help, 9, 2, "Quit - exit out of the program"); mvwprintw(help, 11, 2, "Page up - scrolls one screen up"); mvwprintw(help, 12, 2, "Page down- scrolls one screen down"); mvwprintw(help, 13, 2, "Undo - reverts last modification"); mvwprintw(help, 14, 2, "Home - returns to the top of the file"); mvwprintw(help, 15, 2, "End - jumps to the bottom of the file"); mvwprintw(help, 17, 12, "Press enter to continue"); } wnoutrefresh(ctrl); /* refresh new wins */ wnoutrefresh(help); wnoutrefresh(small); doupdate(); /* update screen */ wgetch(ctrl); /* wait for a char */ delwin(ctrl); /* delete help wins */ delwin(help); delwin(small); redrawwin(win->hex); /* redraw previous */ redrawwin(win->ascii); redrawwin(win->address); wnoutrefresh(win->hex); /* refresh */ wnoutrefresh(win->ascii); wnoutrefresh(win->address); doupdate(); /* update screen */ } /********************************************************\ * Description: scrolls window one line up or down * * Returns: none * \********************************************************/ void winscroll(WINS *windows, WINDOW *win, int n, int currentLine) { int row, col; /* row and col */ getyx(win, row, col); /* get cur row/col */ scrollok(windows->hex, TRUE); /* allow scrolling */ scrollok(windows->ascii, TRUE); scrollok(windows->address, TRUE); wscrl(windows->hex, n); /* scroll each win */ wscrl(windows->ascii, n); wscrl(windows->address, n); scrollok(windows->hex, FALSE); /*disable scrolling */ scrollok(windows->ascii, FALSE); scrollok(windows->address, FALSE); wmove(windows->hex, (n == 1) ? MAXY:0, 0); /* place cursor */ wmove(windows->ascii, (n == 1) ? MAXY:0, 0); wmove(windows->address, (n == 1) ? MAXY:0, 0); outline(fpIN, currentLine); /* output line */ wnoutrefresh(windows->hex); /* set win refreshes */ wnoutrefresh(windows->ascii); wnoutrefresh(windows->address); wmove(win, row, col); /* restore cursor */ } /******************************************************\ * Description: Clears the entire screen * \******************************************************/ void clearScreen(WINS *win) { wclear(win->hex); wclear(win->ascii); wclear(win->address); wclear(win->scrollbar); wclear(win->hex_outline); wclear(win->ascii_outline); wclear(win->cur_address); refreshall(win); doupdate(); } /******************************************************\ * Description: Checks if the exit key has been * * pressed. If so, it checks if the * * file has been saved since the last * * modification. If it hasn't it prompts* * the user asking if they would like to * * save. * * Returns: 2 == save, 1 == no save, 0 == cancel * \******************************************************/ int quitProgram(int notChanged, short int ch) { short int str; /* if exit key... */ if ((ch == KEY_F(8)) || (ch == CTRL_AND('q')) || (ch == CTRL_AND('x'))) { if (!notChanged) /* if changes made */ { /* prompt for exit */ str = questionWin("Do you want to save changes? (y/n)"); if (str == 'Y' || str == 'y') /* if yes, save */ return 2; else if ((str != 'N') && (str != 'n')) /* don't quit, cancel */ return 0; } return 1; /* quit, don't save */ } else return 0; /* don't quit */ } /******************************************************\ * Description: Creates a "window popup" where given * * the parameters, and message, it * * creates a window and displays the * * message. Some current restrictions * * are that it must only be one line, and* * it is assumed that the text is padded * * with one space left for the border and* * another space left for aesthetics * \******************************************************/ void popupWin(char *msg, int time) { WINDOW *tmpwin; int y = (LINES / 2) - 3, /* calc location */ len = strlen(msg), x = (COLS - len)/2; y = (y < 2) ? 2 : y; /* minimum height */ time = (!time) ? 2 : time; tmpwin = drawbox(y, x, 5, len + 6); /* create window */ keypad(tmpwin, TRUE); mvwprintw(tmpwin,2,3, msg); /* output mesg */ wmove(tmpwin,2,len+4); wrefresh(tmpwin); if (time == -1) wgetch(tmpwin); else sleep(time); /* wait */ delwin(tmpwin); wtouchln(windows->hex, y - 1, 5, 1); /* touch windows */ wtouchln(windows->ascii, y - 1, 5, 1); wtouchln(windows->address, y - 1, 5, 1); wtouchln(windows->hex_outline, y, 5, 1); wtouchln(windows->ascii_outline, y, 5, 1); wtouchln(windows->scrollbar, y, 5, 1); refreshall(windows); /* refresh all wins */ doupdate(); } /********************************************************\ * Description: Similar to popupWin, only it prmpts the * * user for a character, such as (y/n) * * Returns: Returns character pressed * \********************************************************/ short int questionWin(char *msg) { WINDOW *tmpwin; short int ch; int y = (LINES / 2) - 3, /* calc location */ len = strlen(msg), x = (COLS - len)/2; y = (y < 2) ? 2 : y; /* minimum height */ tmpwin = drawbox(y, x, 5, len + 6); /* create window */ mvwprintw(tmpwin,2,3, msg); wmove(tmpwin,2,len+4); wrefresh(tmpwin); ch = wgetch(tmpwin); delwin(tmpwin); wtouchln(windows->hex, y - 1, 5, 1); /* touch the lines */ wtouchln(windows->ascii, y - 1, 5, 1); /* covered by win */ wtouchln(windows->address, y - 1, 5, 1); wtouchln(windows->hex_outline, y, 5, 1); wtouchln(windows->ascii_outline, y, 5, 1); wtouchln(windows->scrollbar, y, 5, 1); refreshall(windows); /* refresh all wins */ doupdate(); return ch; }