/* ui.c * This is everything concerned with the visual part of Tap's * user interface (almost). */ /* Copyright (C) 1999 Jonathan duSaint * * This file is part of Tap, an interactive program for reading and * writing data to the serial port to facilitate the reverse * engineering of communication protocols. * * Tap 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, or (at your option) * any later version. * * Tap 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. * * The GNU General Public License is generally kept in a file called * COPYING or LICENSE. If you do not have a copy of the license, write * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "tap.h" /* global variables used to determine window dimensions */ int window_height; int window_width; /* used when in passive mode */ int saved_window_height; /* the windows where all of the action takes place */ WINDOW *input_window; WINDOW *output_window; /* just header/footer information */ WINDOW *status_bar; WINDOW *input_header; WINDOW *output_header; /* this is displayed if there are an even number of lines in the terminal */ WINDOW *title_bar = NULL; /* Write HOW_MUCH bytes from serial_buffer to output_window using * the default format. */ void write_to_output_window (int how_much) { char *inpb, *outb = NULL; inpb = xmalloc (how_much + 1); strncpy (inpb, serial_buffer, how_much); inpb[how_much] = 0; switch (output_format) { case BIN: outb = translate_to_bin (inpb); break; case OCT: outb = translate_to_oct (inpb); break; case HEX: outb = translate_to_hex (inpb); break; case ASCII_RAW: outb = translate_to_ascii_raw (inpb); break; case ASCII_COOKED: outb = translate_to_ascii_cooked (inpb); } waddstr (output_window, outb); wrefresh (output_window); xfree (outb); xfree (inpb); wrefresh (input_window); /* transfer control back to input_window */ } /* The next three functions are for displaying a series of * lines with pagination. */ /* The number of lines which have been printed. */ int lines_printed; /* Initialize pagination */ void page_init (void) { lines_printed = 0; } /* Called after a single line has been printed. Returns 0 if * it is OK to keep printing lines, otherwise 1. */ int page_line_printed (void) { int answer; lines_printed++; /* a full page has been output */ if (!((lines_printed + 1) % window_height)) { waddstr (input_window, "press any key to continue, to quit: "); answer = sgetch (); waddch (input_window, '\n'); if (answer == 'q' || answer == 'Q') return (1); clear_scr (NULL); lines_printed = 0; } return (0); } /* Finalize. This isn't always necessary to call. */ void page_finalize (void) { lines_printed = 0; } /* Print a multiline string to WINDOW with pagination. */ void wprintstr (WINDOW *window, char *string) { char *work_area; int start = 0, end = 0; work_area = xmalloc (strlen (string) + 2); strcpy (work_area, string); if (string[strlen (string) - 1] != '\n') { work_area[strlen (string)] = '\n'; work_area[strlen (string) + 1] = 0; } page_init (); while (1) { while (work_area[end] != '\n') end++; work_area[end] = 0; wprintw (window, "%s\n", work_area + start); start = ++end; if (page_line_printed ()) break; if (work_area[start] == 0) break; } page_finalize (); xfree (work_area); } /* beep and print a message */ void inp_error (char *msg) { beep (); wprintw (input_window, "?? %s\n", msg); wrefresh (input_window); } /* just beep */ void warning_beep (void) { beep (); } /* This is used when going from passive mode into active mode. Changes * the dimensions of input_window. */ void ui_expand_input_window (void) { int pad; WINDOW *twoutput, *twinput; window_height = saved_window_height; pad = 1 - (LINES % 2); twinput = newwin (window_height, window_width, pad + 1, 0); mvwin (output_header, window_height + pad + 1, 0); twoutput = newwin (window_height, window_width, window_height + pad + 2, 0); scrollok (twinput, TRUE); scrollok (twoutput, TRUE); delwin (input_window); delwin (output_window); input_window = twinput; output_window = twoutput; wrefresh (input_window); wrefresh (output_header); wrefresh (output_window); return; } /* This is used when going from active mode into passive mode. Changes * the dimensions of input_window. */ void ui_shrink_input_window (void) { int pad; WINDOW *twoutput, *twinput; if (window_height - 5 < 1) return; saved_window_height = window_height; window_height = 5; pad = 1 - (LINES % 2); twinput = newwin (window_height, window_width, pad + 1, 0); mvwin (output_header, window_height + pad + 1, 0); twoutput = newwin (2 * saved_window_height - 5, window_width, window_height + pad + 2, 0); scrollok (twinput, TRUE); scrollok (twoutput, TRUE); delwin (input_window); delwin (output_window); input_window = twinput; output_window = twoutput; wrefresh (input_window); wrefresh (output_header); wrefresh (output_window); return; } /* set up the user interface */ void init_console_ui (void) { int io_win_height, k, pad = 0; if ((LINES < 11) || (COLS < 70)) { fprintf (stderr, "%s: window too small to be of use\n", pname); endwin (); exit (1); } /* the display should look something like * * ----------- title bar -------------- * | input header | * | | * | input area | * | | * | output header | * | | * | output area | * | | * ---- status area ------------------- * * although if there are an odd number of lines in the terminal, * then there will be no title bar */ io_win_height = ((LINES / 2) + ((LINES % 2) - 1)) - 1; /* create title if space permits */ if (!(LINES % 2)) { pad = 1; title_bar = newwin (1, COLS, 0, 0); wattron (title_bar, A_REVERSE); for (k = 0; k < (COLS - 32) / 2; k++) waddch (title_bar, ' '); waddstr (title_bar, "*** tap - serial line tapper ***"); for (k = 0; k < (COLS - 32) / 2; k++) waddch (title_bar, ' '); wrefresh (title_bar); } input_header = newwin (1, COLS, pad, 0); wattron (input_header, A_REVERSE); waddstr (input_header, "+++ to serial port "); for (k = 19; k < COLS; k++) waddch (input_header, '+'); wrefresh (input_header); input_window = newwin (io_win_height, COLS, 1 + pad, 0); scrollok (input_window, TRUE); output_header = newwin (1, COLS, io_win_height + pad + 1, 0); wattron (output_header, A_REVERSE); waddstr (output_header, "+++ from serial port "); for (k = 21; k < COLS; k++) waddch (output_header, '+'); wrefresh (output_header); output_window = newwin (io_win_height, COLS, io_win_height + pad + 2, 0); scrollok (output_window, TRUE); status_bar = newwin (1, COLS, LINES - 1, 0); wattron (status_bar, A_REVERSE); window_height = io_win_height; window_width = COLS; } /* clean up the user interface */ void destroy_console_ui (void) { delwin (input_window); delwin (output_window); delwin (status_bar); delwin (input_header); delwin (output_header); if (title_bar != NULL) delwin (title_bar); } /* periodically refresh the status bar */ void refresh_console_status_line (void) { int k, len; if (port == NULL) { waddstr (status_bar, "+++ no serial port open "); len = 24; } else { len = 5 + strlen (port); wprintw (status_bar, "+++ %s ", port); } for (k = 0; k < COLS - (len + 25); k++) waddch (status_bar, '+'); waddstr (status_bar, " type `help' for help +++"); wrefresh (status_bar); wmove (status_bar, 0, 0); }