root/branches/0.10.1/drv_Curses.c

Revision 773, 7.7 kB (checked in by michael, 23 months ago)

backport 768:771 from trunk, version changed to 0.10.1-RC2

  • Property svn:keywords set to Id URL Rev
Line 
1/* $Id$
2 * $URL$
3 *
4 * pure ncurses based text driver
5 *
6 * Copyright (C) 2004 Michael Reinelt <reinelt@eunet.at>
7 * Copyright (C) 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
8 *
9 * based on the old Curses/Text driver which is
10 * Copyright (C) 2001 Leopold Toetsch <lt@toetsch.at>
11 *
12 * This file is part of LCD4Linux.
13 *
14 * LCD4Linux is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
18 *
19 * LCD4Linux is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 *
28 */
29
30/*
31 *
32 * exported fuctions:
33 *
34 * struct DRIVER drv_Curses
35 *
36 */
37
38#include "config.h"
39
40#include <stdlib.h>
41#include <stdio.h>
42#include <string.h>
43#include <unistd.h>
44
45#include <curses.h>
46
47#include "debug.h"
48#include "cfg.h"
49#include "qprintf.h"
50#include "timer.h"
51#include "plugin.h"
52#include "widget.h"
53#include "widget_text.h"
54#include "widget_bar.h"
55#include "widget_keypad.h"
56#include "drv.h"
57#include "drv_generic_text.h"
58#include "drv_generic_keypad.h"
59
60
61static char Name[] = "Curses";
62
63static WINDOW *w = NULL;
64static WINDOW *e = NULL;
65
66static int EROWS;
67
68
69/****************************************/
70/***  hardware dependant functions    ***/
71/****************************************/
72
73static void drv_Curs_clear(void)
74{
75    werase(w);
76    box(w, 0, 0);
77    wrefresh(w);
78}
79
80
81static void drv_Curs_write(const int row, const int col, const char *data, const int len)
82{
83    int l = len;
84    char *p;
85
86    while ((p = strpbrk(data, "\r\n")) != NULL) {
87  *p = '\0';
88    }
89
90    if (col < DCOLS) {
91  if (DCOLS - col < l)
92      l = DCOLS - col;
93  mvwprintw(w, row + 1, col + 1, "%.*s", l, data);
94  wmove(w, DROWS + 1, 0);
95  wrefresh(w);
96    }
97}
98
99
100static void drv_Curs_defchar(const __attribute__ ((unused))
101           int ascii, const __attribute__ ((unused))
102           unsigned char *buffer)
103{
104    /* empty */
105}
106
107
108/* ncures scroll SIGSEGVs on my system, so this is a workaroud */
109
110int curses_error(char *buffer)
111{
112    static int lines = 0;
113    static char *lb[100];
114    int start, i;
115    char *p;
116
117    if (e == NULL)
118  return 0;
119
120    /* replace \r, \n with underscores */
121    while ((p = strpbrk(buffer, "\r\n")) != NULL) {
122  *p = '_';
123    }
124
125    if (lines >= EROWS) {
126  free(lb[0]);
127  for (i = 1; i <= EROWS; i++) {
128      lb[i - 1] = lb[i];
129  }
130  start = 0;
131    } else {
132  start = lines;
133    }
134
135    lb[lines] = strdup(buffer);
136    for (i = start; i <= lines; i++) {
137  mvwprintw(e, i + 1, 1, "%s", lb[i]);
138  wclrtoeol(e);
139    }
140
141    box(e, 0, 0);
142    mvwprintw(e, 0, 3, "Stderr:");
143    wrefresh(e);
144
145    if (lines < EROWS)
146  lines++;
147
148    return 1;
149}
150
151
152static int drv_Curs_start(const char *section, const int quiet)
153{
154    char *s;
155
156    if (!running_foreground) {
157  error("%s: You want me to display on /dev/null? Sorry, I can't ...", Name);
158  error("%s: Maybe you want me to run in foreground? Try '-F'", Name);
159  return -1;
160    }
161
162    s = cfg_get(section, "Size", "20x4");
163    if (s == NULL || *s == '\0') {
164  error("%s: no '%s.Size' entry from %s", Name, section, cfg_source());
165  free(s);
166  return -1;
167    }
168    if (sscanf(s, "%dx%d", &DCOLS, &DROWS) != 2 || DROWS < 1 || DCOLS < 1) {
169  error("%s: bad %s.Size '%s' from %s", Name, section, s, cfg_source());
170  free(s);
171  return -1;
172    }
173    free(s);
174
175    initscr();
176    noecho();
177    debug("%s: curses thinks that COLS=%d LINES=%d", Name, COLS, LINES);
178    w = newwin(DROWS + 2, DCOLS + 2, 0, 0);
179    keypad(w, TRUE);
180    nodelay(w, TRUE);
181
182    EROWS = LINES - DROWS - 3;
183    if (EROWS > 99)
184  EROWS = 99;
185    debug("EROWS=%d", EROWS);
186
187    if (EROWS >= 4) {
188  e = newwin(EROWS, COLS, DROWS + 3, 0);
189  EROWS -= 3;
190  box(e, 0, 0);
191  mvwprintw(e, 0, 3, "Stderr:");
192  wmove(e, 1, 0);
193  wrefresh(e);
194    }
195
196    drv_Curs_clear();
197
198    if (!quiet) {
199  char buffer[40];
200  qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
201  if (drv_generic_text_greet(buffer, NULL)) {
202      sleep(3);
203      drv_Curs_clear();
204  }
205    }
206
207    return 0;
208}
209
210static void drv_Curs_timer(void __attribute__ ((unused)) * notused)
211{
212    int c;
213    while (1) {
214  c = wgetch(w);
215  if (c <= 0)
216      break;
217  drv_generic_keypad_press(c);
218    }
219}
220
221static int drv_Curs_keypad(const int num)
222{
223    int val = 0;
224
225    switch (num) {
226    case KEY_UP:
227  debug("Key Up");
228  val += WIDGET_KEY_PRESSED;
229  val += WIDGET_KEY_UP;
230  break;
231    case KEY_DOWN:
232  debug("Key Down");
233  val += WIDGET_KEY_PRESSED;
234  val += WIDGET_KEY_DOWN;
235  break;
236    case KEY_LEFT:
237  debug("Key Left");
238  val += WIDGET_KEY_PRESSED;
239  val += WIDGET_KEY_LEFT;
240  break;
241    case KEY_RIGHT:
242  debug("Key Right");
243  val += WIDGET_KEY_PRESSED;
244  val += WIDGET_KEY_RIGHT;
245  break;
246    default:
247  debug("Unbound Key '%d'", num);
248  break;
249    }
250
251    return val;
252}
253
254
255/****************************************/
256/***            plugins               ***/
257/****************************************/
258
259/* none at the moment... */
260
261
262/****************************************/
263/***        widget callbacks          ***/
264/****************************************/
265
266/* using drv_generic_text_draw(W) */
267/* using drv_generic_text_bar_draw(W) */
268/* using drv_generic_keypad_draw(W) */
269
270
271/****************************************/
272/***        exported functions        ***/
273/****************************************/
274
275
276/* list models */
277int drv_Curs_list(void)
278{
279    printf("any");
280    return 0;
281}
282
283
284/* initialize driver & display */
285int drv_Curs_init(const char *section, const int quiet)
286{
287    WIDGET_CLASS wc;
288    int ret;
289
290    info("%s: %s", Name, "$Rev$");
291
292    /* display preferences */
293    XRES = 1;     /* pixel width of one char  */
294    YRES = 1;     /* pixel height of one char  */
295    CHARS = 0;      /* number of user-defineable characters */
296    CHAR0 = 0;      /* ASCII of first user-defineable char */
297    GOTO_COST = 0;    /* number of bytes a goto command requires */
298
299    /* real worker functions */
300    drv_generic_text_real_write = drv_Curs_write;
301    drv_generic_text_real_defchar = drv_Curs_defchar;
302    drv_generic_keypad_real_press = drv_Curs_keypad;
303
304    /* regularly process display answers */
305    timer_add(drv_Curs_timer, NULL, 100, 0);
306
307    /* start display */
308    if ((ret = drv_Curs_start(section, quiet)) != 0) {
309  return ret;
310    }
311
312    /* initialize generic text driver */
313    if ((ret = drv_generic_text_init(section, Name)) != 0)
314  return ret;
315
316    /* initialize generic bar driver */
317    if ((ret = drv_generic_text_bar_init(1)) != 0)
318  return ret;
319
320    /* initialize generic key pad driver */
321    if ((ret = drv_generic_keypad_init(section, Name)) != 0)
322  return ret;
323
324    /* add fixed chars to the bar driver */
325    drv_generic_text_bar_add_segment(0, 0, 255, 32);  /* ASCII  32 = blank */
326    drv_generic_text_bar_add_segment(255, 255, 255, '*'); /* asterisk */
327
328    /* register text widget */
329    wc = Widget_Text;
330    wc.draw = drv_generic_text_draw;
331    widget_register(&wc);
332
333    /* register bar widget */
334    wc = Widget_Bar;
335    wc.draw = drv_generic_text_bar_draw;
336    widget_register(&wc);
337
338    /* register plugins */
339    /* none at the moment... */
340
341    return 0;
342}
343
344
345/* close driver & display */
346int drv_Curs_quit(const int quiet)
347{
348
349    info("%s: shutting down.", Name);
350
351    drv_generic_text_quit();
352    drv_generic_keypad_quit();
353
354    /* clear display */
355    drv_Curs_clear();
356
357    /* say goodbye... */
358    if (!quiet) {
359  drv_generic_text_greet("goodbye!", NULL);
360    }
361
362    endwin();
363
364    return (0);
365}
366
367
368DRIVER drv_Curses = {
369    .name = Name,
370    .list = drv_Curs_list,
371    .init = drv_Curs_init,
372    .quit = drv_Curs_quit,
373};
Note: See TracBrowser for help on using the browser.