/* * Copyright (c) 2011, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This file is part of the Contiki operating system. * * Author: François Revol */ #include #include #include #include #include #include #include "contiki.h" #include "ctk/ctk.h" #include "ctk-curses.h" /* references: * http://math.hws.edu/orr/s04/cpsc225/curses.html * http://linux.die.net/man/3/ncurses * http://linux.die.net/HOWTO/NCURSES-Programming-HOWTO/index.html */ #define MKPAIR(bg, fg) (bg << 3 | fg) static unsigned char width; static unsigned char height; static unsigned char color; static unsigned char reversed; static ctk_arch_key_t keys[256]; static unsigned char keys_in, keys_out; static unsigned char available; static unsigned short xpos; static unsigned short ypos; static unsigned char button; /* map CTK colors to curses colors */ static unsigned char ctk_color_map[8] = { COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE }; /*-----------------------------------------------------------------------------------*/ static unsigned char map_color(unsigned char color) { unsigned char c; c = ctk_color_map[color & 0x0f]; c |= ctk_color_map[(color >> 4) & 0x07] << 4; return c; } /*-----------------------------------------------------------------------------------*/ static void ctrlhandler(int sig) { /* make sure we call console_exit() to leave the terminal in a clean state */ exit(EXIT_SUCCESS); } /*-----------------------------------------------------------------------------------*/ void console_init(void) { /* mouse support is ncurses-specific */ #ifdef NCURSES_MOUSE_VERSION mmask_t oldmask; #endif static unsigned char done; int bg, fg; if(done) { return; } done = 1; initscr(); start_color(); cbreak(); /* don't echo typed characters */ noecho(); /* disable return -> newline translation */ nonl(); /* hide text cursor, CTK draws its own */ curs_set(0); intrflush(stdscr, FALSE); keypad(stdscr, TRUE); #ifdef NCURSES_MOUSE_VERSION /* done here because ctk_mouse_init() is called before anyway */ mousemask(ALL_MOUSE_EVENTS, &oldmask); #endif screensize(&width, &height); /* we must declare all possible color pairs */ for(fg = 0; fg < 8; fg++) { for(bg = 0; bg < 8; bg++) { init_pair(MKPAIR(bg, fg), fg, bg); } } /* set window title */ putp("\033]0;Contiki\a"); /* don't block on read, just timeout 1ms */ timeout(1); /* make sure we return the terminal in a clean state */ signal(SIGINT, ctrlhandler); atexit(console_exit); } /*-----------------------------------------------------------------------------------*/ void console_exit(void) { static unsigned char done; if(done) { return; } done = 1; revers(0); clrscr(); gotoxy(0, 0); endwin(); } /*-----------------------------------------------------------------------------------*/ unsigned char console_resize(void) { unsigned char new_width; unsigned char new_height; screensize(&new_width, &new_height); if(new_width != width || new_height != height) { width = new_width; height = new_height; return 1; } return 0; } /*-----------------------------------------------------------------------------------*/ static void setcolor(void) { int bg, fg; int attrs; fg = (color & 0x0F); bg = (color & 0xF0) >> 4; attrs = COLOR_PAIR(MKPAIR(bg, fg)); if(reversed) { attrs |= WA_REVERSE; } attrset(attrs); } /*-----------------------------------------------------------------------------------*/ unsigned char wherex(void) { int x, y; getyx(stdscr, y, x); (void)y; return (unsigned char)x; } /*-----------------------------------------------------------------------------------*/ unsigned char wherey(void) { int x, y; getyx(stdscr, y, x); (void)x; return (unsigned char)y; } /*-----------------------------------------------------------------------------------*/ void clrscr(void) { clear(); } /*-----------------------------------------------------------------------------------*/ void bgcolor(unsigned char c) { c = map_color(c); color = ((c << 4) | (color & 0xF0)); /* Presume this to be one of the first calls. */ console_init(); } /*-----------------------------------------------------------------------------------*/ void bordercolor(unsigned char c) { /* Presume this to be one of the first calls. */ console_init(); } /*-----------------------------------------------------------------------------------*/ void screensize(unsigned char *x, unsigned char *y) { int mx, my; getmaxyx(stdscr, my, mx); *x = (unsigned char)mx; *y = (unsigned char)my; } /*-----------------------------------------------------------------------------------*/ void revers(unsigned char c) { reversed = c; setcolor(); } /*-----------------------------------------------------------------------------------*/ void console_cputc(char c) { int ch = c; /* usually ACS_* don't fit in a char */ switch (c) { case CH_ULCORNER: ch = ACS_ULCORNER; break; case CH_LLCORNER: ch = ACS_LLCORNER; break; case CH_URCORNER: ch = ACS_URCORNER; break; case CH_LRCORNER: ch = ACS_LRCORNER; break; default: break; } addch(ch); refresh(); } /*-----------------------------------------------------------------------------------*/ void console_cputs(char *str) { addstr(str); refresh(); } /*-----------------------------------------------------------------------------------*/ void cclear(unsigned char length) { hline(' ', length); refresh(); } /*-----------------------------------------------------------------------------------*/ void chline(unsigned char length) { hline(ACS_HLINE, length); refresh(); } /*-----------------------------------------------------------------------------------*/ void cvline(unsigned char length) { vline(ACS_VLINE, length); } /*-----------------------------------------------------------------------------------*/ void gotoxy(unsigned char x, unsigned char y) { move(y, x); } /*-----------------------------------------------------------------------------------*/ void cclearxy(unsigned char x, unsigned char y, unsigned char length) { gotoxy(x, y); cclear(length); } /*-----------------------------------------------------------------------------------*/ void chlinexy(unsigned char x, unsigned char y, unsigned char length) { gotoxy(x, y); chline(length); } /*-----------------------------------------------------------------------------------*/ void cvlinexy(unsigned char x, unsigned char y, unsigned char length) { gotoxy(x, y); cvline(length); } /*-----------------------------------------------------------------------------------*/ void cputsxy(unsigned char x, unsigned char y, char *str) { gotoxy(x, y); console_cputs(str); } /*-----------------------------------------------------------------------------------*/ void cputcxy(unsigned char x, unsigned char y, char c) { gotoxy(x, y); console_cputc(c); } /*-----------------------------------------------------------------------------------*/ void textcolor(unsigned char c) { color = map_color(c); setcolor(); } /*-----------------------------------------------------------------------------------*/ static void console_readkey(int k) { ctk_arch_key_t key; key = (ctk_arch_key_t) k; /*fprintf(stderr, "key: %d\n", k); */ switch (k) { #ifdef NCURSES_MOUSE_VERSION case KEY_MOUSE: { MEVENT event; if(getmouse(&event) == OK) { xpos = event.x; ypos = event.y; button = event.bstate & BUTTON1_PRESSED || event.bstate & BUTTON1_CLICKED || event.bstate & BUTTON1_DOUBLE_CLICKED; /*fprintf(stderr, "mevent: %d: %d, %d, %d, %lx ; %d\n", event.id, event.x, event.y, event.z, event.bstate, button); */ } return; } #endif case KEY_LEFT: key = CH_CURS_LEFT; break; case KEY_UP: key = CH_CURS_UP; break; case KEY_RIGHT: key = CH_CURS_RIGHT; break; case KEY_DOWN: key = CH_CURS_DOWN; break; case KEY_F(9): /* Gnome uses F10 as menu trigger now... */ case KEY_F(10): key = CTK_CONF_MENU_KEY; break; case '\r': case KEY_ENTER: key = CH_ENTER; break; case 127: case KEY_BACKSPACE: case KEY_DC: key = CH_DEL; break; case KEY_BTAB: case KEY_CTAB: case KEY_PPAGE: case KEY_PREVIOUS: key = CTK_CONF_WIDGETUP_KEY; break; case KEY_NPAGE: case KEY_NEXT: key = CTK_CONF_WIDGETDOWN_KEY; break; case KEY_STAB: case KEY_HOME: case KEY_END: key = CTK_CONF_WINDOWSWITCH_KEY; break; default: break; } if(key == 0) { return; } memset(keys + keys_in, key, sizeof(ctk_arch_key_t)); keys_in++; available++; } /*-----------------------------------------------------------------------------------*/ static void console_read(void) { int k; k = getch(); if(k != ERR) { console_readkey(k); } } /*-----------------------------------------------------------------------------------*/ char ctk_arch_getkey(void) { char k; console_read(); k = keys[keys_out++]; available--; return k; } /*-----------------------------------------------------------------------------------*/ unsigned char ctk_arch_keyavail(void) { console_read(); return available; } /*-----------------------------------------------------------------------------------*/ void ctk_mouse_init(void) { } /*-----------------------------------------------------------------------------------*/ unsigned short ctk_mouse_x(void) { console_read(); return xpos; } /*-----------------------------------------------------------------------------------*/ unsigned short ctk_mouse_y(void) { console_read(); return ypos; } /*-----------------------------------------------------------------------------------*/ unsigned short ctk_mouse_xtoc(unsigned short x) { return x; } /*-----------------------------------------------------------------------------------*/ unsigned short ctk_mouse_ytoc(unsigned short y) { return y; } /*-----------------------------------------------------------------------------------*/ unsigned char ctk_mouse_button(void) { console_read(); return button; } /*-----------------------------------------------------------------------------------*/ void ctk_mouse_hide(void) { } /*-----------------------------------------------------------------------------------*/ void ctk_mouse_show(void) { } /*-----------------------------------------------------------------------------------*/