/* * ncurses driver * * Display LCD display at top left of terminal screen * using ncurses. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #ifdef HAVE_NCURSES_H #include #else #include #endif #include "shared/str.h" #include "lcd.h" #include "curses_drv.h" #include "drv_base.h" lcd_logical_driver *curses_drv; // Character used for title bars... #define PAD '#' // #define PAD ACS_BLOCK int ELLIPSIS = 7; ////////////////////////////////////////////////////////////////////////// ////////////////////// For Curses Terminal Output //////////////////////// ////////////////////////////////////////////////////////////////////////// static char icon_char = '@'; static WINDOW *lcd_win; chtype get_color (char *colorstr) { if (strcasecmp(colorstr, "red") == 0) return COLOR_RED; else if (strcasecmp(colorstr, "black") == 0) return COLOR_BLACK; else if (strcasecmp(colorstr, "green") == 0) return COLOR_GREEN; else if (strcasecmp(colorstr, "yellow") == 0) return COLOR_YELLOW; else if (strcasecmp(colorstr, "blue") == 0) return COLOR_BLUE; else if (strcasecmp(colorstr, "magenta") == 0) return COLOR_MAGENTA; else if (strcasecmp(colorstr, "cyan") == 0) return COLOR_CYAN; else if (strcasecmp(colorstr, "white") == 0) return COLOR_WHITE; else return -1; } /* * A few different nice pairs of colors to use... * */ #define DEFAULT_FOREGROUND_COLOR COLOR_CYAN #define DEFAULT_BACKGROUND_COLOR COLOR_BLUE // #define DEFAULT_FOREGROUND_COLOR COLOR_WHITE // #define DEFAULT_BACKGROUND_COLOR COLOR_BLUE // #define DEFAULT_FOREGROUND_COLOR COLOR_WHITE // #define DEFAULT_BACKGROUND_COLOR COLOR_RED chtype set_foreground_color (char * buf) { chtype color; if ((color = get_color(buf)) < 0) color = DEFAULT_FOREGROUND_COLOR; return color; } chtype set_background_color (char * buf) { chtype color; if ((color = get_color(buf)) < 0) color = DEFAULT_BACKGROUND_COLOR; return color; } /* * What position (X,Y) to start the left top corner at... * */ #define TOP_LEFT_X 7 #define TOP_LEFT_Y 7 int curses_drv_init (struct lcd_logical_driver *driver, char *args) { char *argv[64]; int argc; int i; char buf[64]; // Colors.... chtype back_color = DEFAULT_BACKGROUND_COLOR, fore_color = DEFAULT_FOREGROUND_COLOR; // Screen position (top left) int screen_begx = TOP_LEFT_X, screen_begy = TOP_LEFT_Y; memset(&argv, '\0', sizeof(argv)); argc = get_args (argv, args, 64); for (i = 0; i < argc; i++) { if (0 == strcmp (argv[i], "-f") || 0 == strcmp (argv[i], "--forecolor")) { if (i + 1 >= argc) { fprintf (stderr, "curses_init: %s requires an argument\n", argv[i]); return -1; } strncpy(buf, argv[++i], sizeof(buf)); fore_color = set_foreground_color(buf); } else if (0 == strcmp (argv[i], "-b") || 0 == strcmp (argv[i], "--backcolor")) { if (i + 1 >= argc) { fprintf (stderr, "curses_init: %s requires an argument\n", argv[i]); return -1; } strncpy(buf, argv[++i], sizeof(buf)); back_color = set_background_color(buf); } else if (0 == strcmp (argv[i], "-B") || 0 == strcmp (argv[i], "--backlight")) { if (i + 1 >= argc) { fprintf (stderr, "curses_init: %s requires an argument\n", argv[i]); return -1; } // TODO: Backlight... backlight? where? printf ("Sorry, backlight not yet implemented...\n"); } else if (0 == strcmp (argv[i], "-h") || 0 == strcmp (argv[i], "--help")) { printf ("LCDproc [n]curses driver\n" "\t-f\t--forecolor\tChange the foreground color\n" "\t-b\t--backcolor\tChange the backlight's \"off\" color\n" "\t-B\t--backlight\tChange the backlight's \"on\" color\n" "\t-h\t--help\t\tShow this help information\n"); return -1; } else { printf ("Invalid parameter: %s\n", argv[i]); } } curses_drv = driver; // Init curses... initscr (); cbreak (); noecho (); nodelay (stdscr, TRUE); nonl (); intrflush (stdscr, FALSE); keypad (stdscr, TRUE); lcd_win = newwin(curses_drv->hgt + 2, curses_drv->wid + 2, screen_begy, screen_begx); curs_set(0); if (has_colors()) { start_color(); init_pair(1, fore_color, back_color); init_pair(2, back_color, fore_color); init_pair(3, COLOR_WHITE, back_color); } curses_drv_clear (); driver->daemonize = 0; // don't daemonize... // Override output functions... driver->clear = curses_drv_clear; driver->string = curses_drv_string; driver->chr = curses_drv_chr; driver->vbar = curses_drv_vbar; //driver->init_vbar = NULL; driver->hbar = curses_drv_hbar; //driver->init_hbar = NULL; driver->num = curses_drv_num; driver->init_num = curses_drv_init_num; driver->init = curses_drv_init; driver->close = curses_drv_close; driver->flush = curses_drv_flush; driver->flush_box = curses_drv_flush_box; //driver->contrast = NULL; //driver->backlight = NULL; //driver->set_char = NULL; driver->icon = curses_drv_icon; driver->draw_frame = curses_drv_draw_frame; driver->getkey = curses_drv_getkey; // Change the character used for "..." ELLIPSIS = '~'; return 200; // 200 is arbitrary. (must be 1 or more) } static void curses_drv_wborder (WINDOW *win) { int x, y; char buf[128]; if (has_colors()) { wcolor_set(win, 3, NULL); wattron(win, COLOR_PAIR(3) | A_BOLD); } box(win, 0, 0); if (has_colors()) { wcolor_set(win, 1, NULL); wattron(win, COLOR_PAIR(1)); wattroff(win, A_BOLD); } } void curses_drv_close () { // Note that the program leaves a screen on // the display to be left behind after closing; // so don't clear... // // Close curses wrefresh (lcd_win); delwin (lcd_win); move (0, 0); endwin (); if (curses_drv->framebuf != NULL) free (curses_drv->framebuf); curses_drv->framebuf = NULL; } ///////////////////////////////////////////////////////////////// // Clears the LCD screen // void curses_drv_clear () { wbkgdset(lcd_win, COLOR_PAIR(1) | ' '); curses_drv_wborder (lcd_win); werase (lcd_win); } #define ValidX(a) { if (x > curses_drv->wid) { x = curses_drv->wid; } else x < 1 ? 1 : x; } #define ValidY(a) { if (y > curses_drv->hgt) { y = curses_drv->hgt; } else y < 1 ? 1 : y; } ///////////////////////////////////////////////////////////////// // Prints a string on the lcd display, at position (x,y). The // upper-left is (1,1), and the lower right should be (20,4). // void curses_drv_string (int x, int y, char *string) { int i; unsigned char *p; ValidX(x); ValidY(y); p = string; // Convert NULLs and 0xFF in string to // valid printables... while (*p) { switch (*p) { //case 0: -- can never happen? // *p = icon_char; // break; case 255: *p = PAD; break; } p++; } mvwaddstr (lcd_win, y, x, string); } ///////////////////////////////////////////////////////////////// // Prints a character on the lcd display, at position (x,y). The // upper-left is (1,1), and the lower right should be (20,4). // void curses_drv_chr (int x, int y, char c) { ValidX(x); ValidY(y); switch (c) { case 0: c = icon_char; break; case -1: // translates to 255 (ouch!) c = PAD; break; //default: // normal character... } mvwaddch (lcd_win, y, x, c); } ///////////////////////////////////////////////////////////////// // Sets up for big numbers. // void curses_drv_init_num () { ; } ///////////////////////////////////////////////////////////////// // Writes a big number. // void curses_drv_num (int x, int num) { char c; int y, dx; c = '0' + num; // printf(&c,"%1d",num); for (y = 1; y < 5; y++) for (dx = 0; dx < 3; dx++) curses_drv_chr (x + dx, y, c); } ///////////////////////////////////////////////////////////////// // Draws a vertical bar; erases entire column onscreen. // void curses_drv_vbar (int x, int len) { //char map[] = "_.,,ooO8"; char map[] = { ACS_S9, ACS_S9, ACS_S7, ACS_S7, ACS_S3, ACS_S3, ACS_S1, ACS_S1 }; int y; ValidX(x); #define MAX_LINES (curses_drv->cellhgt * curses_drv->hgt) len = len > (MAX_LINES - 1) ? (MAX_LINES - 1) : len; len = len < 0 ? 0 : len; // len is the length of the bar (in pixels/scanlines) // y is one character line (cellhgt pixels/scanlines) for (y = curses_drv->hgt; y > 0 && len > 0; y--) { if (len >= curses_drv->cellhgt) { // write a "full" block to the screen... //curses_drv_chr (x, y, '8'); curses_drv_chr (x, y, ACS_BLOCK); len -= curses_drv->cellhgt; } else { // write a partial block... curses_drv_chr (x, y, map[len-1]); break; } } // move(4-len/lcd.cellhgt, x-1); // vline(0, len/lcd.cellhgt); } ///////////////////////////////////////////////////////////////// // Draws a horizontal bar to the right. // void curses_drv_hbar (int x, int y, int len) { for (; x <= curses_drv->wid && len > 0; x++) { if (len >= curses_drv->cellwid) curses_drv_chr (x, y, '='); else curses_drv_chr (x, y, '-'); len -= curses_drv->cellwid; } // move(y-1, x-1); // hline(0, len/lcd.cellwid); } ///////////////////////////////////////////////////////////////// // Sets character 0 to an icon... // void curses_drv_icon (int which, char dest) { if (dest == 0) switch (which) { case 0: icon_char = '+'; break; case 1: icon_char = '*'; break; default: icon_char = PAD; break; } } ////////////////////////////////////////////////////////////////// // Flushes all output to the lcd... // void curses_drv_flush () { curses_drv_draw_frame (curses_drv->framebuf); } void curses_drv_flush_box (int lft, int top, int rgt, int bot) { curses_drv_flush (); } void curses_drv_draw_frame (char *dat) { curses_drv_wborder (lcd_win); wrefresh (lcd_win); } char curses_drv_getkey () { int i; i = getch (); if (i == KEY_LEFT) return 'D'; if (i == KEY_UP) return 'B'; if (i == KEY_DOWN) return 'C'; if (i == KEY_RIGHT) return 'A'; if (i != ERR) return i; else return 0; }