Logo Search packages:      
Sourcecode: tcd version File versions  Download package

ui.c

/**
 * This module defines helper routines for ncurses.
 */

#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <termios.h>

#include "ui.h"

extern void set_coords(struct coords *co, int top, int left, int bottom,
                       int right)
{
    co->top = top, co->left = left, co->bottom = bottom, co->right = right;
    co->height = bottom - top, co->width = right - left;
}

extern void mvwhsplit(WINDOW * win, int y, int x, int len)
{
    mvwaddch(win, y, x, ACS_LTEE);
    mvwhline(win, y, x + 1, ACS_HLINE, len - 2);
    mvwaddch(win, y, x + len - 1, ACS_RTEE);
}

extern void mvwvsplit(WINDOW * win, int y, int x, int len)
{
    mvwaddch(win, y, x, ACS_TTEE);
    mvwvline(win, y + 1, x, ACS_VLINE, len - 2);
    mvwaddch(win, y + len - 1, x, ACS_BTEE);
}

extern void mvwaddlstr(WINDOW * win, int y, int x, const char *s,
                       int maxlen)
{
    int len = (int) strlen(s);
    wmove(win, y, x);
    if (len > maxlen) {
        while (maxlen > 3 && *s != '\0') {
            waddch(win, (chtype) *s++);
            maxlen--;
        }
        while (maxlen > 0) {
            waddch(win, (chtype) '.');
            maxlen--;
        }
    } else {
        waddstr(win, s);
    }
}

static int int_min(int a, int b)
{
    return (a < b) ? a : b;
}

extern void mvwbox(WINDOW * win, const struct coords *c, const char *title)
{
    const int height = c->bottom - c->top, width = c->right - c->left;
    const int hlen = int_min((int) strlen(title), width - 4);
    mvwaddch(win, c->top, c->left, ACS_ULCORNER);
    whline(win, ACS_HLINE, width - 2);
    mvwaddch(win, c->top, c->right - 1, ACS_URCORNER);
    mvwvline(win, c->top + 1, c->left, ACS_VLINE, height - 2);
    mvwhline(win, c->top + 1, c->left + 1, (chtype) ' ', width - 2);
    mvwvline(win, c->top + 1, c->right - 1, ACS_VLINE, height - 2);
    mvwaddch(win, c->bottom - 1, c->left, ACS_LLCORNER);
    mvwhline(win, c->bottom - 1, c->left + 1, ACS_HLINE, width - 2);
    mvwaddch(win, c->bottom - 1, c->right - 1, ACS_LRCORNER);
    mvwaddnstr(win, c->top, c->left + (width - hlen) / 2, title, hlen);
}

extern int ui_inputbox(char *buf, size_t bufsize, const char *title)
{
    struct coords input;
    int maxy, maxx, result;

    getmaxyx(stdscr, maxy, maxx);
    set_coords(&input, maxy / 2 - 1, 10, maxy / 2 + 2, maxx - 10);

    mvwbox(stdscr, &input, title);

    echo(), curs_set(1);
    result =
        (mvgetnstr(input.top + 1, input.left + 1, buf, (int) bufsize) ==
         ERR) ? -1 : 0;
    noecho(), curs_set(0);

    return result;
}

static void init_colors(void)
{
    start_color();
    init_pair(0, COLOR_BLACK, COLOR_BLACK);
    init_pair(1, COLOR_RED, COLOR_BLACK);
    init_pair(2, COLOR_GREEN, COLOR_BLACK);
    init_pair(3, COLOR_YELLOW, COLOR_BLACK);
    init_pair(4, COLOR_BLUE, COLOR_BLACK);
    init_pair(5, COLOR_MAGENTA, COLOR_BLACK);
    init_pair(6, COLOR_CYAN, COLOR_BLACK);
    init_pair(7, COLOR_WHITE, COLOR_BLACK);
}

static volatile bool window_resized = FALSE;
static void winch_handler(int signum)
{
#ifdef __GNUC__
    (void) signum; /* mark signum as used. */
#endif
    window_resized = TRUE;
}

typedef void (*sighandler_f)(int);
sighandler_f old_winch_handler = NULL;

extern void ui_init(void)
{
    old_winch_handler = signal(SIGWINCH, winch_handler);
    if (initscr() == NULL) {
        fprintf(stderr, "Error: Could not start ncurses\n");
        exit(EXIT_FAILURE);
    }
    if (has_colors()) {
        init_colors();
    }
    cbreak(), keypad(stdscr, TRUE);
    noecho(), curs_set(0), leaveok(stdscr, FALSE);
}

extern void ui_shutdown(void)
{
    sighandler_f current_handler;

    wclear(stdscr);
    wrefresh(stdscr);
    wmove(stdscr, 0, 0);
    endwin();
    if (winch_handler != SIG_ERR) {
        current_handler = signal(SIGWINCH, old_winch_handler);
        if (current_handler != winch_handler) {
            (void) signal(SIGWINCH, current_handler);
        }
    }
}

static void ui_getscreensize(int *height, int *width)
{
    struct winsize ws;

    if (ioctl(0, TIOCGWINSZ, &ws) >= 0) {
        *width = ws.ws_col;
        *height = ws.ws_row;
    } else {
      *width = 80;
      *height = 24;
    }
}

extern int ui_readkey(int delay)
{
    if (window_resized) {
      int width, height;
      window_resized = FALSE;
      ui_getscreensize(&height, &width);
      resizeterm(height, width);
      return KEY_RESIZE;
    }
    if (delay > 0) {
        halfdelay(delay);
    } else {
      /* leave halfdelay mode */
        nocbreak(), cbreak();
    }
    return wgetch(stdscr);
}

Generated by  Doxygen 1.6.0   Back to index