/*
* This file is part of the uHex project.
* Copyright (C) 2013-2015 Mateusz Viste
*
* Curses I/O driver that allows to port uHex to non-DOS platforms.
*
* 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.
*/
#include <curses.h>
#include <stdio.h> /* this one contains the NULL definition */
#include "io.h" /* include self headers for control */
int curx = 0, cury = 0;
int getkeybuf = 0;
WINDOW *mywindow;
/* inits the IO subsystem */
void io_init(void) {
mywindow = initscr();
start_color();
raw();
noecho();
keypad(stdscr, TRUE); /* capture arrow keys */
timeout(100); /* getch blocks for 50ms max */
set_escdelay(50); /* ESC should wait for 50ms max */
nonl(); /* allow ncurses to detect KEY_ENTER */
}
void io_close(void) {
endwin();
}
void cursor_hide(void) {
curs_set(0);
refresh();
}
void cursor_show(void) {
curs_set(1);
refresh();
}
void locate(int row, int column) {
move(row, column);
}
void printchar(char c, int attr) {
attrset(COLOR_PAIR(attr));
/* curses is unable to print the ascii representation of a control char */
if ((c < 32) || (c > 126)) {
addch('.');
} else {
addch(c);
}
/* attroff(COLOR_PAIR(attr)); */
refresh();
}
void printattrstringyx(int y, int x, char *sym, int *attr, int len) {
int i, prev_attr;
/* Use color of the first symbol */
prev_attr = attr[0];
attrset(COLOR_PAIR(prev_attr));
/* Begin symbols output */
locate(y, x);
for (i = 0; i < len; i++) {
int cur_attr = attr[i];
char c = sym[i];
/* Attribute selection */
if (cur_attr != prev_attr) {
prev_attr = cur_attr;
attrset(COLOR_PAIR(cur_attr));
}
/* Type the symbol */
if ((c < 32) || (c > 126)) {
addch('.');
} else {
addch(c);
}
}
}
/* waits for a keypress and return it. Returns 0 for extended keystroke, then
function must be called again to return scan code. */
int getkey(void) {
int res;
if (getkeybuf > 0) {
res = getkeybuf;
getkeybuf = 0;
return(res);
}
for (;;) {
res = wgetch(mywindow);
if (res == KEY_MOUSE) continue; /* ignore mouse events */
if (res == ERR) continue; /* no input available */
/* either ESC or ALT+some key */
if (res == 27) {
res = wgetch(mywindow);
if (res == ERR) {
res = 27;
} else { /* this is an ALT+something combination */
switch (res) {
case 'f': return(0x121);
case 'h': return(0x123);
case 'j': return(0x124);
case 's': return(0x11F);
case 'u': return(0x116);
}
}
}
switch (res) {
case KEY_LEFT:
getkeybuf = 0x4B;
return(0);
case KEY_RIGHT:
getkeybuf = 0x4D;
return(0);
case KEY_UP:
getkeybuf = 0x48;
return(0);
case KEY_DOWN:
getkeybuf = 0x50;
return(0);
case KEY_BACKSPACE:
return(8);
case KEY_ENTER:
return(13);
case KEY_PPAGE: /* PAGEUP */
getkeybuf = 0x49;
return(0);
case KEY_NPAGE: /* PGDOWN */
getkeybuf = 0x51;
return(0);
case KEY_HOME:
getkeybuf = 0x47;
return(0);
case KEY_END:
getkeybuf = 0x4F;
return(0);
default:
break;
}
break;
}
/* return the scancode as-is otherwise */
return(res);
}
void cls(int colattr) {
int x, y;
int maxrows, maxcols;
clear();
getmaxyx(mywindow, maxrows, maxcols);
if (maxcols > 80) maxcols = 80;
attrset(COLOR_PAIR(colattr));
for (y = 0; y < maxrows; y++) {
for (x = 0; x < maxcols; x++) {
mvaddch(y, x, ' ');
}
}
/* bkgd(COLOR_PAIR(colattr)); */
locate(0,0);
refresh();
}
void getcurvideomode(int *termwidth, int *termheight, int *colorflag) {
getmaxyx(mywindow, *termheight, *termwidth);
*colorflag = has_colors();
}
/* translates a 'dos' color (ie. CGA index) into a curses color constant */
static int doscol2curse(int doscol) {
switch (doscol & 7) { /* curses aren't that much flexible when it comes to bright colors */
case 0: return(COLOR_BLACK);
case 1: return(COLOR_BLUE);
case 2: return(COLOR_GREEN);
case 3: return(COLOR_CYAN);
case 4: return(COLOR_RED);
case 5: return(COLOR_MAGENTA);
case 6: return(COLOR_YELLOW);
case 7: return(COLOR_WHITE);
}
return(0);
}
int computecolor(int doscol) {
static int colorcount = 0;
colorcount += 1;
init_pair(colorcount, doscol2curse(doscol & 0x0f), doscol2curse(doscol >> 4));
return(colorcount);
}