From b8448093e2f554744fa5911b2c96174b78f4ae0f Mon Sep 17 00:00:00 2001 From: reinelt <> Date: Wed, 14 Jan 2004 11:33:00 +0000 Subject: [lcd4linux @ 2004-01-14 11:33:00 by reinelt] new plugin 'uname' which does what it's called text widget nearly finished first results displayed on MatrixOrbital --- Makefile.am | 5 +- Makefile.in | 12 +-- cfg.c | 75 +++++++++++----- cfg.h | 37 ++++---- drv_MatrixOrbital.c | 240 +++++++++++++++++++++++++++++++++++++--------------- expr.c | 9 +- layout.c | 10 ++- lcd4linux.c | 9 +- plugin.c | 9 +- plugin_cfg.c | 9 +- plugin_cpuinfo.c | 14 +-- plugin_uname.c | 95 +++++++++++++++++++++ widget.c | 13 ++- widget.h | 16 ++-- widget_text.c | 214 ++++++++++++++++++++++++++++++++++++++++------ 15 files changed, 607 insertions(+), 160 deletions(-) create mode 100644 plugin_uname.c diff --git a/Makefile.am b/Makefile.am index 5e2058c..3afc2ed 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -## Process this file with automake to produce Makefile.in +# Process this file with automake to produce Makefile.in AUTOMAKE_OPTIONS = gnu CLEANFILES = *~ @@ -25,11 +25,12 @@ layout.c layout.h \ timer.c timer.h \ evaluator.c evaluator.h \ widget.c widget.h \ -widget_text.c widget_text.h \ +widget_text.c \ plugin.c plugin.h \ plugin_math.c \ plugin_string.c \ plugin_cfg.c \ +plugin_uname.c \ plugin_cpuinfo.c \ plugin_i2c_sensors.c \ plugin_xmms.c \ diff --git a/Makefile.in b/Makefile.in index 483130b..89fcd4a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -10,6 +10,8 @@ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. +# Process this file with automake to produce Makefile.in + SHELL = @SHELL@ @@ -104,7 +106,7 @@ lcd4linux_LDADD = @DRIVERS@ @DRVLIBS@ #remove next line for liblcd4linux lcd4linux_DEPENDENCIES = @DRIVERS@ -lcd4linux_SOURCES = lcd4linux.c pid.c pid.h hash.c hash.h parser.c parser.h processor.c processor.h layout.c layout.h timer.c timer.h evaluator.c evaluator.h widget.c widget.h widget_text.c widget_text.h plugin.c plugin.h plugin_math.c plugin_string.c plugin_cfg.c plugin_cpuinfo.c plugin_i2c_sensors.c plugin_xmms.c system.c system.h isdn.c isdn.h wifi.c wifi.h mail.c mail.h seti.c seti.h battery.c battery.h dvb.c dvb.h filter.c filter.h exec.c exec.h expr.c expr.h mail2.c socket.c socket.h imon.c imon.h display.c display.h drv.c drv.h debug.c debug.h cfg.c cfg.h lock.c lock.h pixmap.c pixmap.h bar.c bar.h icon.c icon.h fontmap.c fontmap.h udelay.c udelay.h +lcd4linux_SOURCES = lcd4linux.c pid.c pid.h hash.c hash.h parser.c parser.h processor.c processor.h layout.c layout.h timer.c timer.h evaluator.c evaluator.h widget.c widget.h widget_text.c plugin.c plugin.h plugin_math.c plugin_string.c plugin_cfg.c plugin_uname.c plugin_cpuinfo.c plugin_i2c_sensors.c plugin_xmms.c system.c system.h isdn.c isdn.h wifi.c wifi.h mail.c mail.h seti.c seti.h battery.c battery.h dvb.c dvb.h filter.c filter.h exec.c exec.h expr.c expr.h mail2.c socket.c socket.h imon.c imon.h display.c display.h drv.c drv.h debug.c debug.h cfg.c cfg.h lock.c lock.h pixmap.c pixmap.h bar.c bar.h icon.c icon.h fontmap.c fontmap.h udelay.c udelay.h #liblcd4linux_la_DEPENDENCIES = @DRIVERS@ @@ -148,7 +150,7 @@ lcd4linux_OBJECTS = lcd4linux.$(OBJEXT) pid.$(OBJEXT) hash.$(OBJEXT) \ parser.$(OBJEXT) processor.$(OBJEXT) layout.$(OBJEXT) timer.$(OBJEXT) \ evaluator.$(OBJEXT) widget.$(OBJEXT) widget_text.$(OBJEXT) \ plugin.$(OBJEXT) plugin_math.$(OBJEXT) plugin_string.$(OBJEXT) \ -plugin_cfg.$(OBJEXT) plugin_cpuinfo.$(OBJEXT) \ +plugin_cfg.$(OBJEXT) plugin_uname.$(OBJEXT) plugin_cpuinfo.$(OBJEXT) \ plugin_i2c_sensors.$(OBJEXT) plugin_xmms.$(OBJEXT) system.$(OBJEXT) \ isdn.$(OBJEXT) wifi.$(OBJEXT) mail.$(OBJEXT) seti.$(OBJEXT) \ battery.$(OBJEXT) dvb.$(OBJEXT) filter.$(OBJEXT) exec.$(OBJEXT) \ @@ -182,9 +184,9 @@ DEP_FILES = .deps/BeckmannEgle.P .deps/Crystalfontz.P .deps/Cwlinux.P \ .deps/mail.P .deps/mail2.P .deps/parport.P .deps/parser.P .deps/pid.P \ .deps/pixmap.P .deps/plugin.P .deps/plugin_cfg.P .deps/plugin_cpuinfo.P \ .deps/plugin_i2c_sensors.P .deps/plugin_math.P .deps/plugin_string.P \ -.deps/plugin_xmms.P .deps/processor.P .deps/seti.P .deps/socket.P \ -.deps/system.P .deps/timer.P .deps/udelay.P .deps/widget.P \ -.deps/widget_text.P .deps/wifi.P +.deps/plugin_uname.P .deps/plugin_xmms.P .deps/processor.P .deps/seti.P \ +.deps/socket.P .deps/system.P .deps/timer.P .deps/udelay.P \ +.deps/widget.P .deps/widget_text.P .deps/wifi.P SOURCES = $(lcd4linux_SOURCES) $(EXTRA_lcd4linux_SOURCES) OBJECTS = $(lcd4linux_OBJECTS) diff --git a/cfg.c b/cfg.c index 7e0becf..df7fa79 100644 --- a/cfg.c +++ b/cfg.c @@ -1,4 +1,4 @@ -/* $Id: cfg.c,v 1.26 2004/01/11 18:26:02 reinelt Exp $^ +/* $Id: cfg.c,v 1.27 2004/01/14 11:33:00 reinelt Exp $^ * * config file stuff * @@ -23,6 +23,11 @@ * * * $Log: cfg.c,v $ + * Revision 1.27 2004/01/14 11:33:00 reinelt + * new plugin 'uname' which does what it's called + * text widget nearly finished + * first results displayed on MatrixOrbital + * * Revision 1.26 2004/01/11 18:26:02 reinelt * further widget and layout processing * @@ -161,14 +166,23 @@ * This list was allocated be cfg_list() and must be * freed by the caller! * + * cfg_get_raw (section, key, defval) + * return the a value for a given key in a given section + * or if key does not exist. Does NOT evaluate + * the expression. Therefore used to get the expression + * itself! + * * cfg_get (section, key, defval) * return the a value for a given key in a given section - * or if key does not exist + * or if key does not exist. The specified + * value in the config is treated as a expression and + * is evaluated! * * cfg_number (section, key, defval, min, int max, *value) * return the a value for a given key in a given section * convert it into a number with syntax checking - * check if its in a given range + * check if its in a given range. As it uses cfg_get() + * internally, the evaluator is used here, too. * */ @@ -183,6 +197,7 @@ #include #include "debug.h" +#include "evaluator.h" #include "cfg.h" typedef struct { @@ -361,7 +376,7 @@ char *l4l_cfg_list (char *section) } -char *l4l_cfg_get (char *section, char *key, char *defval) +char *l4l_cfg_get_raw (char *section, char *key, char *defval) { int len; char *buffer; @@ -396,33 +411,52 @@ char *l4l_cfg_get (char *section, char *key, char *defval) } -int l4l_cfg_number (char *section, char *key, int defval, int min, int max, int *value) +char *l4l_cfg_get (char *section, char *key, char *defval) { - char *s, *e; + char *expression; + RESULT result = {0, 0.0, NULL}; + expression=cfg_get_raw(section, key, defval); + + if (expression!=NULL && *expression!='\0') { + if (Eval(expression, &result)==0) { + return R2S(&result); + } + } + return defval; +} + + +int l4l_cfg_number (char *section, char *key, int defval, int min, int max, int *value) +{ + char *expression; + RESULT result = {0, 0.0, NULL}; + // start with default value // in case of an (uncatched) error, you have the // default value set, which may be handy... *value=defval; - s=cfg_get(section, key, NULL); - if (s==NULL) { + expression=cfg_get_raw(section, key, NULL); + if (expression==NULL) { return 0; } - *value=strtol(s, &e, 0); - if (*e!='\0') { - error ("bad %s entry '%s' in %s", key, s, cfg_source()); + if (Eval(expression, &result)!=0) { return -1; } + *value=R2N(&result); + DelResult(&result); if (*valuemax) { - error ("bad %s value '%s' in %s, maximum is %d", key, s, cfg_source(), max); + error ("bad %s value '%d' in %s, maximum is %d", key, *value, cfg_source(), max); + *value=max; return -1; } @@ -637,10 +671,11 @@ char *l4l_cfg_source (void) } -int (*cfg_init) (char *source) = l4l_cfg_init; -char *(*cfg_source) (void) = l4l_cfg_source; -int (*cfg_cmd) (char *arg) = l4l_cfg_cmd; -char *(*cfg_list) (char *section) = l4l_cfg_list; -char *(*cfg_get) (char *section, char *key, char *defval) = l4l_cfg_get; -int (*cfg_number) (char *section, char *key, int defval, - int min, int max, int *value) = l4l_cfg_number; +int (*cfg_init) (char *source) = l4l_cfg_init; +char *(*cfg_source) (void) = l4l_cfg_source; +int (*cfg_cmd) (char *arg) = l4l_cfg_cmd; +char *(*cfg_list) (char *section) = l4l_cfg_list; +char *(*cfg_get_raw) (char *section, char *key, char *defval) = l4l_cfg_get_raw; +char *(*cfg_get) (char *section, char *key, char *defval) = l4l_cfg_get; +int (*cfg_number) (char *section, char *key, int defval, + int min, int max, int *value) = l4l_cfg_number; diff --git a/cfg.h b/cfg.h index 49895be..ffd01f6 100644 --- a/cfg.h +++ b/cfg.h @@ -1,4 +1,4 @@ -/* $Id: cfg.h,v 1.8 2004/01/10 20:22:33 reinelt Exp $ +/* $Id: cfg.h,v 1.9 2004/01/14 11:33:00 reinelt Exp $ * * config file stuff * @@ -22,6 +22,11 @@ * * * $Log: cfg.h,v $ + * Revision 1.9 2004/01/14 11:33:00 reinelt + * new plugin 'uname' which does what it's called + * text widget nearly finished + * first results displayed on MatrixOrbital + * * Revision 1.8 2004/01/10 20:22:33 reinelt * added new function 'cfg_list()' (not finished yet) * added layout.c (will replace processor.c someday) @@ -60,20 +65,22 @@ #ifndef _CFG_H_ #define _CFG_H_ -extern int (*cfg_init) (char *source); -extern char *(*cfg_source) (void); -extern int (*cfg_cmd) (char *arg); -extern char *(*cfg_list) (char *section); -extern char *(*cfg_get) (char *section, char *key, char *defval); -extern int (*cfg_number) (char *section, char *key, int defval, - int min, int max, int *value); +extern int (*cfg_init) (char *source); +extern char *(*cfg_source) (void); +extern int (*cfg_cmd) (char *arg); +extern char *(*cfg_list) (char *section); +extern char *(*cfg_get_raw) (char *section, char *key, char *defval); +extern char *(*cfg_get) (char *section, char *key, char *defval); +extern int (*cfg_number) (char *section, char *key, int defval, + int min, int max, int *value); -int l4l_cfg_init (char *file); -char *l4l_cfg_source (void); -int l4l_cfg_cmd (char *arg); -char *l4l_cfg_list (char *section); -char *l4l_cfg_get (char *section, char *key, char *defval); -int l4l_cfg_number (char *section, char *key, int defval, - int min, int max, int *value); +int l4l_cfg_init (char *file); +char *l4l_cfg_source (void); +int l4l_cfg_cmd (char *arg); +char *l4l_cfg_list (char *section); +char *l4l_cfg_get_raw (char *section, char *key, char *defval); +char *l4l_cfg_get (char *section, char *key, char *defval); +int l4l_cfg_number (char *section, char *key, int defval, + int min, int max, int *value); #endif diff --git a/drv_MatrixOrbital.c b/drv_MatrixOrbital.c index 5ca694a..2fdf1ef 100644 --- a/drv_MatrixOrbital.c +++ b/drv_MatrixOrbital.c @@ -1,4 +1,4 @@ -/* $Id: drv_MatrixOrbital.c,v 1.6 2004/01/11 18:26:02 reinelt Exp $ +/* $Id: drv_MatrixOrbital.c,v 1.7 2004/01/14 11:33:00 reinelt Exp $ * * new style driver for Matrix Orbital serial display modules * @@ -23,6 +23,11 @@ * * * $Log: drv_MatrixOrbital.c,v $ + * Revision 1.7 2004/01/14 11:33:00 reinelt + * new plugin 'uname' which does what it's called + * text widget nearly finished + * first results displayed on MatrixOrbital + * * Revision 1.6 2004/01/11 18:26:02 reinelt * further widget and layout processing * @@ -75,6 +80,7 @@ #include "bar.h" #include "icon.h" #include "widget.h" +#include "widget_text.h" // these values are hardcoded @@ -87,11 +93,12 @@ static speed_t Speed; static int Device=-1; static int Model; -static int ROWS, COLS, GPOS; -static int ICONS, PROTOCOL; +static int DROWS, DCOLS; // display size +static int LROWS, LCOLS; // layout size +static int GPOS, ICONS, PROTOCOL; -static char *FrameBuffer1=NULL; -static char *FrameBuffer2=NULL; +static char *LayoutFB=NULL; +static char *DisplayFB=NULL; static int GPO[8]; @@ -239,18 +246,27 @@ static void drv_MO_define_char (int ascii, char *buffer) } +static void drv_MO_goto (int row, int col) +{ + char cmd[5]="\376Gyx"; + cmd[2]=(char)col+1; + cmd[3]=(char)row+1; + drv_MO_write(cmd,4); +} + + static int drv_MO_clear (int full) { int gpo; - memset (FrameBuffer1, ' ', ROWS*COLS*sizeof(char)); + memset (LayoutFB, ' ', LROWS*LCOLS*sizeof(char)); icon_clear(); bar_clear(); memset(GPO, 0, sizeof(GPO)); if (full) { - memset (FrameBuffer2, ' ', ROWS*COLS*sizeof(char)); + memset (DisplayFB, ' ', DROWS*DCOLS*sizeof(char)); switch (PROTOCOL) { case 1: drv_MO_write ("\014", 1); // Clear Screen @@ -273,21 +289,12 @@ static int drv_MO_clear (int full) return 0; } -static void drv_MO_goto (int row, int col) -{ - char cmd[5]="\376Gyx"; - cmd[2]=(char)col+1; - cmd[3]=(char)row+1; - drv_MO_write(cmd,4); -} - - static int drv_MO_put (int row, int col, char *text) { - char *p=FrameBuffer1+row*COLS+col; + char *p=LayoutFB+row*DCOLS+col; char *t=text; - while (*t && col++<=COLS) { + while (*t && col++<=DCOLS) { *p++=*t++; } return 0; @@ -383,65 +390,62 @@ static int drv_MO_start (char *section) // read module type drv_MO_write ("\3767", 2); usleep(1000); - drv_MO_read (buffer, 1); - for (i=0; Models[i].type!=0xff; i++) { - if (Models[i].type == (int)*buffer) break; + if (drv_MO_read (buffer, 1)==1) { + for (i=0; Models[i].type!=0xff; i++) { + if (Models[i].type == (int)*buffer) break; + } + info ("MatrixOrbital: display reports model '%s' (type 0x%02x)", + Models[i].name, Models[i].type); + + // auto-dedection + if (Model==-1) Model=i; + + // auto-dedection matches specified model? + if (Models[i].type!=0xff && Model!=i) { + error ("MatrixOrbital: %s.Model '%s' from %s does not match dedected Model '%s'", + section, model, cfg_source(), Models[i].name); + return -1; + } + + } else { + info ("MatrixOrbital: display detection failed."); } - info ("MatrixOrbital: display identifies itself as a '%s' (type 0x%02x)", - Models[i].name, Models[i].type); - - // auto-dedection - if (Model==-1) Model=i; - // auto-dedection matches specified model? - if (Model!=i) { - error ("MatrixOrbital: %s.Model '%s' from %s does not match dedected Model '%s'", - section, model, cfg_source(), Models[i].name); - return -1; - } - // read serial number drv_MO_write ("\3765", 2); usleep(100000); - drv_MO_read (buffer, 2); - info ("MatrixOrbital: display reports serial number 0x%x", *(short*)buffer); - + if (drv_MO_read (buffer, 2)==2) { + info ("MatrixOrbital: display reports serial number 0x%x", *(short*)buffer); + } + // read version number drv_MO_write ("\3766", 2); usleep(100000); - drv_MO_read (buffer, 1); - info ("MatrixOrbital: display reports firmware version 0x%x", *buffer); - + if (drv_MO_read (buffer, 1)==1) { + info ("MatrixOrbital: display reports firmware version 0x%x", *buffer); + } // initialize global variables - ROWS = Models[Model].rows; - COLS = Models[Model].cols; + DROWS = Models[Model].rows; + DCOLS = Models[Model].cols; GPOS = Models[Model].gpos; PROTOCOL = Models[Model].protocol; - - // init the framebuffers - FrameBuffer1 = (char*)malloc(COLS*ROWS*sizeof(char)); - FrameBuffer2 = (char*)malloc(COLS*ROWS*sizeof(char)); - if (FrameBuffer1==NULL || FrameBuffer2==NULL) { - error ("MatrixOrbital: framebuffer could not be allocated: malloc() failed"); - return -1; - } - // init Icons if (cfg_number(NULL, "Icons", 0, 0, CHARS, &ICONS)<0) return -1; if (ICONS>0) { debug ("reserving %d of %d user-defined characters for icons", ICONS, CHARS); - icon_init(ROWS, COLS, XRES, YRES, CHARS, ICONS, drv_MO_define_char); + icon_init(DROWS, DCOLS, XRES, YRES, CHARS, ICONS, drv_MO_define_char); } // init Bars - bar_init(ROWS, COLS, XRES, YRES, CHARS-ICONS); + bar_init(DROWS, DCOLS, XRES, YRES, CHARS-ICONS); bar_add_segment( 0, 0,255, 32); // ASCII 32 = blank bar_add_segment(255,255,255,255); // ASCII 255 = block - drv_MO_clear(1); + // Fixme: get rid of this function + // drv_MO_clear(1); // Fixme: where to init contrast? drv_MO_contrast(160); @@ -463,19 +467,19 @@ static int drv_MO_flush (void) bar_process(drv_MO_define_char); - for (row=0; row5) break; @@ -484,11 +488,11 @@ static int drv_MO_flush (void) equal=0; } } - drv_MO_write (FrameBuffer1+row*COLS+pos1, pos2-pos1+1); + drv_MO_write (LayoutFB+row*DCOLS+pos1, pos2-pos1+1); } } - memcpy (FrameBuffer2, FrameBuffer1, ROWS*COLS*sizeof(char)); + memcpy (DisplayFB, LayoutFB, DROWS*DCOLS*sizeof(char)); switch (PROTOCOL) { case 1: @@ -651,6 +655,88 @@ static void plugin_rpm (RESULT *result, RESULT *arg1) } +// **************************************** +// *** internal helper functions *** +// **************************************** + +static void drv_MO_resize (int rows, int cols) +{ + char *newFB; + int row, col; + + // Layout FB is large enough + if (rows<=LROWS && cols<=LCOLS) + return; + + // allocate new Layout FB + newFB=malloc(cols*rows*sizeof(char)); + memset (newFB, ' ', rows*cols*sizeof(char)); + + // transfer contents + if (LayoutFB!=NULL) { + for (row=0; rowdata; + char *txt, *fb1, *fb2; + int row, col, len, end; + + debug ("drv_MO_draw_text(%s) x=%2d y=%2d value=<%s>", W->name, W->col, W->row, T->buffer); + + row=W->row; + col=W->col; + txt=T->buffer; + len=strlen(txt); + end=col+len; + + // maybe grow layout framebuffer + drv_MO_resize (W->row, W->col+len-1); + + fb1=LayoutFB+row*LCOLS; + fb2=DisplayFB+row*DCOLS; + + // transfer new text into layout buffer + memcpy (fb1+col, txt, len); + + for (; col<=end; col++) { + int pos1, pos2, equal; + if (fb1[col]==fb2[col]) continue; + drv_MO_goto (row, col); + for (pos1=col, pos2=pos1, col++, equal=0; col<=end; col++) { + if (fb1[col]==fb2[col]) { + // If we find just one equal byte, we don't break, because this + // would require a goto, which takes several bytes, too. + if (++equal>5) break; + } else { + pos2=col; + equal=0; + } + } + memcpy (fb2+pos1, fb1+pos1, pos2-pos1+1); + drv_MO_write (fb2+pos1, pos2-pos1+1); + } + + return 0; +} + // **************************************** // *** exported functions *** @@ -679,9 +765,25 @@ int drv_MO_init (char *section) if ((ret=drv_MO_start (section))!=0) return ret; + // init display framebuffer + DisplayFB = (char*)malloc(DCOLS*DROWS*sizeof(char)); + memset (DisplayFB, ' ', DROWS*DCOLS*sizeof(char)); + + // init layout framebuffer + LROWS = 0; + LCOLS = 0; + LayoutFB=NULL; + drv_MO_resize (DROWS, DCOLS); + + // sanity check + if (LayoutFB==NULL || DisplayFB==NULL) { + error ("MatrixOrbital: framebuffer could not be allocated: malloc() failed"); + return -1; + } + // register text widget wc=Widget_Text; - wc.draw=NULL; //Fixme + wc.draw=drv_MO_draw_text; widget_register(&wc); // register plugins @@ -703,14 +805,14 @@ int drv_MO_quit (void) { close (Device); unlock_port(Port); - if (FrameBuffer1) { - free(FrameBuffer1); - FrameBuffer1=NULL; + if (LayoutFB) { + free(LayoutFB); + LayoutFB=NULL; } - if (FrameBuffer2) { - free(FrameBuffer2); - FrameBuffer2=NULL; + if (DisplayFB) { + free(DisplayFB); + DisplayFB=NULL; } return (0); diff --git a/expr.c b/expr.c index 1b1c5b7..09a6c33 100644 --- a/expr.c +++ b/expr.c @@ -1,4 +1,4 @@ -/* $Id: expr.c,v 1.3 2004/01/12 03:51:01 reinelt Exp $ +/* $Id: expr.c,v 1.4 2004/01/14 11:33:00 reinelt Exp $ * * expr ('y*') functions * This is only a workaround to make the Evaluator usable until @@ -24,6 +24,11 @@ * * * $Log: expr.c,v $ + * Revision 1.4 2004/01/14 11:33:00 reinelt + * new plugin 'uname' which does what it's called + * text widget nearly finished + * first results displayed on MatrixOrbital + * * Revision 1.3 2004/01/12 03:51:01 reinelt * evaluating the 'Variables' section in the config file * @@ -63,7 +68,7 @@ int Expr(int index, char string[EXPR_TXT_LEN], double *val) sprintf(yn, "y%d", index); expression = cfg_get(NULL, yn, NULL); - + if (!expression || !*expression) { error("Empty expression for 'y%d'", index); errs[index]++; diff --git a/layout.c b/layout.c index faa54ee..4f25a7d 100644 --- a/layout.c +++ b/layout.c @@ -1,4 +1,4 @@ -/* $Id: layout.c,v 1.5 2004/01/13 08:18:19 reinelt Exp $ +/* $Id: layout.c,v 1.6 2004/01/14 11:33:00 reinelt Exp $ * * new layouter framework * @@ -23,6 +23,11 @@ * * * $Log: layout.c,v $ + * Revision 1.6 2004/01/14 11:33:00 reinelt + * new plugin 'uname' which does what it's called + * text widget nearly finished + * first results displayed on MatrixOrbital + * * Revision 1.5 2004/01/13 08:18:19 reinelt * timer queues added * liblcd4linux deactivated turing transformation to new layout @@ -68,8 +73,7 @@ int layout_addItem (char *name, int row, int col) { // allocate widget - widget_add (name); - + widget_add (name, row-1, col-1); return 0; } diff --git a/lcd4linux.c b/lcd4linux.c index 0d6290f..76d1f55 100644 --- a/lcd4linux.c +++ b/lcd4linux.c @@ -1,4 +1,4 @@ -/* $Id: lcd4linux.c,v 1.60 2004/01/13 08:18:19 reinelt Exp $ +/* $Id: lcd4linux.c,v 1.61 2004/01/14 11:33:00 reinelt Exp $ * * LCD4Linux * @@ -22,6 +22,11 @@ * * * $Log: lcd4linux.c,v $ + * Revision 1.61 2004/01/14 11:33:00 reinelt + * new plugin 'uname' which does what it's called + * text widget nearly finished + * first results displayed on MatrixOrbital + * * Revision 1.60 2004/01/13 08:18:19 reinelt * timer queues added * liblcd4linux deactivated turing transformation to new layout @@ -591,7 +596,7 @@ int main (int argc, char *argv[]) // check the conf to see if quiet startup is wanted if (!quiet) { - quiet = atoi(cfg_get(NULL, "Quiet", "0")); + cfg_number(NULL, "Quiet", 0, 0, 1, &quiet); } // Fixme: compatibility only... diff --git a/plugin.c b/plugin.c index 3304a00..6328ea9 100644 --- a/plugin.c +++ b/plugin.c @@ -1,4 +1,4 @@ -/* $Id: plugin.c,v 1.10 2004/01/13 10:03:01 reinelt Exp $ +/* $Id: plugin.c,v 1.11 2004/01/14 11:33:00 reinelt Exp $ * * plugin handler for the Evaluator * @@ -22,6 +22,11 @@ * * * $Log: plugin.c,v $ + * Revision 1.11 2004/01/14 11:33:00 reinelt + * new plugin 'uname' which does what it's called + * text widget nearly finished + * first results displayed on MatrixOrbital + * * Revision 1.10 2004/01/13 10:03:01 reinelt * new util 'hash' for associative arrays * new plugin 'cpuinfo' @@ -101,6 +106,7 @@ int plugin_init_math (void); int plugin_init_string (void); int plugin_init_cfg (void); +int plugin_init_uname (void); int plugin_init_cpuinfo (void); int plugin_init_i2c_sensors (void); int plugin_init_xmms (void); @@ -111,6 +117,7 @@ int plugin_init (void) plugin_init_math(); plugin_init_string(); plugin_init_cfg(); + plugin_init_uname(); plugin_init_cpuinfo(); // MR: segfaults here // plugin_init_i2c_sensors(); diff --git a/plugin_cfg.c b/plugin_cfg.c index 0b1a229..de10385 100644 --- a/plugin_cfg.c +++ b/plugin_cfg.c @@ -1,4 +1,4 @@ -/* $Id: plugin_cfg.c,v 1.1 2004/01/13 10:03:01 reinelt Exp $ +/* $Id: plugin_cfg.c,v 1.2 2004/01/14 11:33:00 reinelt Exp $ * * plugin for config file access * @@ -23,6 +23,11 @@ * * * $Log: plugin_cfg.c,v $ + * Revision 1.2 2004/01/14 11:33:00 reinelt + * new plugin 'uname' which does what it's called + * text widget nearly finished + * first results displayed on MatrixOrbital + * * Revision 1.1 2004/01/13 10:03:01 reinelt * new util 'hash' for associative arrays * new plugin 'cpuinfo' @@ -62,7 +67,7 @@ static void load_variables (void) if (strchr(key, '.')!=NULL || strchr(key, ':') !=0) { error ("ignoring variable '%s' from %s: structures not allowed", key, cfg_source()); } else { - expression=cfg_get (section, key, ""); + expression=cfg_get_raw (section, key, ""); if (expression!=NULL && *expression!='\0') { if (Eval(expression, &result)==0) { debug ("Variable %s = '%s' (%f)", key, R2S(&result), R2N(&result)); diff --git a/plugin_cpuinfo.c b/plugin_cpuinfo.c index 031429f..60b0880 100644 --- a/plugin_cpuinfo.c +++ b/plugin_cpuinfo.c @@ -1,4 +1,4 @@ -/* $Id: plugin_cpuinfo.c,v 1.1 2004/01/13 10:03:01 reinelt Exp $ +/* $Id: plugin_cpuinfo.c,v 1.2 2004/01/14 11:33:00 reinelt Exp $ * * plugin for /proc/cpuinfo parsing * @@ -23,6 +23,11 @@ * * * $Log: plugin_cpuinfo.c,v $ + * Revision 1.2 2004/01/14 11:33:00 reinelt + * new plugin 'uname' which does what it's called + * text widget nearly finished + * first results displayed on MatrixOrbital + * * Revision 1.1 2004/01/13 10:03:01 reinelt * new util 'hash' for associative arrays * new plugin 'cpuinfo' @@ -67,7 +72,8 @@ static void my_cpuinfo (RESULT *result, RESULT *arg1) stream=fopen("/proc/cpuinfo", "r"); if (stream==NULL) { error ("fopen(/proc/cpuinfo) failed: %s", strerror(errno)); - goto error; + SetResult(&result, R_STRING, ""); + return; } while (!feof(stream)) { @@ -91,9 +97,7 @@ static void my_cpuinfo (RESULT *result, RESULT *arg1) hash_set (&CPUinfo, key, val); } - fclose (stream); - time(&now); } @@ -101,8 +105,6 @@ static void my_cpuinfo (RESULT *result, RESULT *arg1) val=hash_get(&CPUinfo, key); if (val==NULL) val=""; - error: - // val=""; SetResult(&result, R_STRING, val); } diff --git a/plugin_uname.c b/plugin_uname.c new file mode 100644 index 0000000..95ae17e --- /dev/null +++ b/plugin_uname.c @@ -0,0 +1,95 @@ +/* $Id: plugin_uname.c,v 1.1 2004/01/14 11:33:00 reinelt Exp $ + * + * plugin for uname() syscall + * + * Copyright 2003 Michael Reinelt + * Copyright 2004 The LCD4Linux Team + * + * This file is part of LCD4Linux. + * + * LCD4Linux is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * LCD4Linux is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * $Log: plugin_uname.c,v $ + * Revision 1.1 2004/01/14 11:33:00 reinelt + * new plugin 'uname' which does what it's called + * text widget nearly finished + * first results displayed on MatrixOrbital + * + */ + +/* + * exported functions: + * + * int plugin_init_uname (void) + * adds uname() functions + * + */ + + +#include +#include +#include +#include + +#include "debug.h" +#include "plugin.h" + + + +static void my_uname (RESULT *result, RESULT *arg1) +{ + struct utsname utsbuf; + char *key, *value; + + key=R2S(arg1); + + if (uname(&utsbuf)!=0) { + error("uname() failed: %s", strerror(errno)); + SetResult(&result, R_STRING, ""); + return; + } + + if (strcasecmp(key, "sysname")==0) { + value=utsbuf.sysname; + } else if (strcasecmp(key, "nodename")==0) { + value=utsbuf.nodename; + } else if (strcasecmp(key, "nodename")==0) { + value=utsbuf.nodename; + } else if (strcasecmp(key, "release")==0) { + value=utsbuf.release; + } else if (strcasecmp(key, "version")==0) { + value=utsbuf.version; + } else if (strcasecmp(key, "machine")==0) { + value=utsbuf.machine; +#ifdef _GNU_SOURCE + } else if (strcasecmp(key, "domainname")==0) { + value=utsbuf.domainname; +#endif + } else { + error("uname: unknown field '%s'", key); + value=""; + } + + SetResult(&result, R_STRING, value); +} + + +int plugin_init_uname (void) +{ + AddFunction ("uname", 1, my_uname); + return 0; +} + diff --git a/widget.c b/widget.c index 57a4b5b..b646e38 100644 --- a/widget.c +++ b/widget.c @@ -1,4 +1,4 @@ -/* $Id: widget.c,v 1.7 2004/01/13 08:18:20 reinelt Exp $ +/* $Id: widget.c,v 1.8 2004/01/14 11:33:00 reinelt Exp $ * * generic widget handling * @@ -21,6 +21,11 @@ * * * $Log: widget.c,v $ + * Revision 1.8 2004/01/14 11:33:00 reinelt + * new plugin 'uname' which does what it's called + * text widget nearly finished + * first results displayed on MatrixOrbital + * * Revision 1.7 2004/01/13 08:18:20 reinelt * timer queues added * liblcd4linux deactivated turing transformation to new layout @@ -106,7 +111,7 @@ int widget_register (WIDGET_CLASS *widget) } -int widget_add (char *name) +int widget_add (char *name, int row, int col) { int i; char *section; @@ -125,6 +130,7 @@ int widget_add (char *name) class=cfg_get(section, "class", NULL); if (class==NULL || *class=='\0') { error ("error: widget '%s' has no class!", name); + if (class) free (class); return -1; } @@ -136,6 +142,7 @@ int widget_add (char *name) break; } } + if (class) free (class); if (i==nClasses) { error ("widget '%s': class '%s' not supported"); return -1; @@ -162,6 +169,8 @@ int widget_add (char *name) Widget->name = name; Widget->class = Class; + Widget->row = row; + Widget->col = col; if (Class->init!=0) { Class->init(Widget); diff --git a/widget.h b/widget.h index 95a8586..c1b2785 100644 --- a/widget.h +++ b/widget.h @@ -1,4 +1,4 @@ -/* $Id: widget.h,v 1.6 2004/01/13 08:18:20 reinelt Exp $ +/* $Id: widget.h,v 1.7 2004/01/14 11:33:00 reinelt Exp $ * * generic widget handling * @@ -23,6 +23,11 @@ * * * $Log: widget.h,v $ + * Revision 1.7 2004/01/14 11:33:00 reinelt + * new plugin 'uname' which does what it's called + * text widget nearly finished + * first results displayed on MatrixOrbital + * * Revision 1.6 2004/01/13 08:18:20 reinelt * timer queues added * liblcd4linux deactivated turing transformation to new layout @@ -59,7 +64,6 @@ struct WIDGET; // forward declaration typedef struct WIDGET_CLASS { char *name; int (*init) (struct WIDGET *Self); - int (*update) (struct WIDGET *Self); // Fixme: do we really need this? int (*draw) (struct WIDGET *Self); int (*quit) (struct WIDGET *Self); } WIDGET_CLASS; @@ -68,16 +72,14 @@ typedef struct WIDGET_CLASS { typedef struct WIDGET{ char *name; WIDGET_CLASS *class; + int row; + int col; void *data; } WIDGET; int widget_register (WIDGET_CLASS *widget); -int widget_add (char *name); - - -// some basic widgets -WIDGET_CLASS Widget_Text; +int widget_add (char *name, int row, int col); #endif diff --git a/widget_text.c b/widget_text.c index 4fc1ef8..95401ed 100644 --- a/widget_text.c +++ b/widget_text.c @@ -1,4 +1,4 @@ -/* $Id: widget_text.c,v 1.3 2004/01/13 08:18:20 reinelt Exp $ +/* $Id: widget_text.c,v 1.4 2004/01/14 11:33:00 reinelt Exp $ * * simple text widget handling * @@ -21,6 +21,11 @@ * * * $Log: widget_text.c,v $ + * Revision 1.4 2004/01/14 11:33:00 reinelt + * new plugin 'uname' which does what it's called + * text widget nearly finished + * first results displayed on MatrixOrbital + * * Revision 1.3 2004/01/13 08:18:20 reinelt * timer queues added * liblcd4linux deactivated turing transformation to new layout @@ -49,33 +54,150 @@ #include #include #include +#include #include "debug.h" #include "cfg.h" +#include "evaluator.h" #include "timer.h" #include "widget.h" +#include "widget_text.h" -typedef struct WIDGET_TEXT { - char *value; - char *align; - int width; - int update; -} WIDGET_TEXT; +void widget_text_scroll (void *Self) +{ + WIDGET *W = (WIDGET*)Self; + WIDGET_TEXT *T = W->data; + + int num, len, pad; + char *src, *dst; + + src=T->value; + dst=T->buffer; + num=0; + len=strlen(T->value); + switch (T->align) { + case ALIGN_LEFT: + pad=0; + break; + case ALIGN_CENTER: + pad=(T->width - len)/2; + if (pad<0) pad=0; + break; + case ALIGN_RIGHT: + pad=T->width - len; + if (pad<0) pad=0; + break; + case ALIGN_MARQUEE: + pad=T->width - T->scroll; + T->scroll++; + if (T->scroll >= T->width+len) T->scroll=0; + break; + default: // not reached + pad=0; + } + + // pad blanks on the beginning + while (pad>0) { + *(dst++)=' '; + num++; + pad--; + } + + // overread src (marquee) + while (pad<0) { + src++; + pad++; + } + + // copy content + while (num < T->width) { + if (*src=='\0') break; + *(dst++)=*(src++); + num++; + } + + // pad blanks on the end + while (num < T->width) { + *(dst++)=' '; + num++; + } + *dst='\0'; + + // finally, draw it! + if (W->class->draw) + W->class->draw(W); +} + -void widget_text_callback (void *vSelf) +void widget_text_update (void *Self) { - WIDGET *Self=(WIDGET*)vSelf; + WIDGET *W = (WIDGET*)Self; + WIDGET_TEXT *T = W->data; + RESULT result = {0, 0.0, NULL}; + char *value; - debug ("callback: Self->name=%s", Self->name); + // evaluate expression + Eval(T->expression, &result); + + // string or number? + if (T->precision==0xC0DE) { + value=strdup(R2S(&result)); + } else { + double number=R2N(&result); + int width=T->width; + int precision=T->precision; + // print zero bytes so we can specify NULL as target + // and get the length of the resulting string + int size=snprintf (NULL, 0, "%.*f", precision, number); + // number does not fit into field width: try to reduce precision + if (size>width && precision>0) { + int delta=size-width; + if (delta>precision) delta=precision; + precision-=delta; + size-=delta; + // zero precision: omit decimal point, too + if (precision==0) size--; + } + // number still doesn't fit: display '*****' + if (size>width) { + debug ("overflow"); + value=malloc(width+1); + memset (value, '*', width); + *(value+width)='\0'; + } else { + value=malloc(size+1); + snprintf (value, size+1, "%.*f", precision, number); + } + } + + // has value changed? + if (T->value == NULL || strcmp(T->value, value)!=0) { + // free old value + if (T->value) free (T->value); + T->value=value; + // reset marquee counter + T->scroll=0; + // if there's a marquee scroller active, it has its own + // update callback timer, so we do nothing here; otherwise + // we simply call this scroll callback directly + if (T->align!=ALIGN_MARQUEE) { + widget_text_scroll (Self); + } + } else { + // value is the same, so free our buffer + free (value); + } + + DelResult (&result); } -int widget_text_init (WIDGET *Self) { - - char *section; - WIDGET_TEXT *data; +int widget_text_init (WIDGET *Self) +{ + char *section; char *c; + WIDGET_TEXT *T; // prepare config section // strlen("Widget:")=7 @@ -83,20 +205,65 @@ int widget_text_init (WIDGET *Self) { strcpy(section, "Widget:"); strcat(section, Self->name); - data=malloc(sizeof(WIDGET_TEXT)); + T=malloc(sizeof(WIDGET_TEXT)); + memset (T, 0, sizeof(WIDGET_TEXT)); + + // get raw expression (we evaluate it ourselves) + T->expression = cfg_get_raw (section, "expression", "''"); - data->value = cfg_get (section, "value", "''"); - data->align = cfg_get (section, "align", "L"); + // field width, default 10 + cfg_number (section, "width", 10, 0, 99999, &(T->width)); - cfg_number (section, "width", 5, 0, 99999, &(data->width)); - cfg_number (section, "update", -1, -1, 99999, &(data->update)); + // precision: number of digits after the decimal point (default: none) + // Note: this is the *maximum* precision on small values, + // for larger values the precision may be reduced to fit into the field width. + // The default value 0xC0DE is used to distinguish between numbers and strings: + // if no precision is given, the result is always treated as a string. If a + // precision is specified, the result is treated as a number. + cfg_number (section, "precision", 0xC0DE, 0, 80, &(T->precision)); - free (section); - Self->data=data; + // field alignment: Left (default), Center, Right or Marquee + c = cfg_get (section, "align", "L"); + switch (toupper(*c)) { + case 'L': + T->align=ALIGN_LEFT; + break; + case 'C': + T->align=ALIGN_CENTER; + break; + case 'R': + T->align=ALIGN_RIGHT; + break; + case 'M': + T->align=ALIGN_MARQUEE; + break; + default: + error ("widget %s has unknown alignment '%s', using 'Left'", section, c); + T->align=ALIGN_LEFT; + } + free (c); + + // update interval (msec), default 1 sec + cfg_number (section, "update", 1000, 10, 99999, &(T->update)); - debug ("timer_add: Self=%p Self->name=%s", Self, Self->name); - timer_add (widget_text_callback, Self, 200, 0); + // marquee scroller speed: interval (msec), default 500msec + if (T->align==ALIGN_MARQUEE) { + cfg_number (section, "speed", 500, 10, 99999, &(T->speed)); + } + // buffer + T->buffer=malloc(T->width+1); + + free (section); + Self->data=T; + + timer_add (widget_text_update, Self, T->update, 0); + + // a marquee scroller has its own timer and callback + if (T->align==ALIGN_MARQUEE) { + timer_add (widget_text_scroll, Self, T->speed, 0); + } + return 0; } @@ -117,7 +284,6 @@ int widget_text_quit (WIDGET *Self) { WIDGET_CLASS Widget_Text = { name: "text", init: widget_text_init, - update: NULL, draw: NULL, quit: widget_text_quit, }; -- cgit v1.2.3