diff --git a/configure.in b/configure.in index aa05f4f..c9e4f2d 100644 --- a/configure.in +++ b/configure.in @@ -159,6 +159,7 @@ LCD_DRIVERS_SELECT AC_OUTPUT(Makefile shared/Makefile server/Makefile + server/commands/Makefile server/drivers/Makefile clients/Makefile clients/lcdproc/Makefile diff --git a/server/Makefile.am b/server/Makefile.am index 0f30558..5038614 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -1,5 +1,5 @@ -SUBDIRS=drivers +SUBDIRS=drivers commands sbin_PROGRAMS=LCDd -LCDd_SOURCES= client_data.c client_data.h client_functions.c client_functions.h client_menu.h clients.c clients.h input.c input.h main.c main.h menu.c menu.h menus.c menus.h parse.c parse.h render.c render.h screen.c screen.h screenlist.c screenlist.h serverscreens.c serverscreens.h sock.c sock.h widget.c widget.h configfile.c configfile.h drivers.c drivers.h driver.c driver.h -LCDd_LDADD = ../shared/libLCDstuff.a +LCDd_SOURCES= client.c client.h clients.c clients.h client_menu.h input.c input.h main.c main.h event.h menu.c menu.h menuscreens.c menuscreens.h parse.c parse.h render.c render.h screen.c screen.h screenlist.c screenlist.h serverscreens.c serverscreens.h sock.c sock.h widget.c widget.h configfile.c configfile.h drivers.c drivers.h driver.c driver.h +LCDd_LDADD = ../shared/libLCDstuff.a commands/libLCDcommands.a INCLUDES = -I$(top_srcdir) diff --git a/server/client.c b/server/client.c new file mode 100644 index 0000000..9d608b1 --- /dev/null +++ b/server/client.c @@ -0,0 +1,263 @@ +/* + * client_data.h + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn + * + */ + +#include +#include +#include + +#include "config.h" + +#include "client.h" +#include "screenlist.h" +#include "render.h" +#include "shared/report.h" +#include "shared/LL.h" + +Client * client_create (int sock) +{ + Client *c; + + debug (RPT_DEBUG, "new_client(%i)", sock); + + /* Allocate new client...*/ + c = malloc (sizeof (Client)); + if (!c) { + report (RPT_ERR, "client_create: Error allocating"); + return NULL; + } + /* Init struct members*/ + c->sock = sock; + c->messages = NULL; + c->backlight = BACKLIGHT_OPEN; + c->heartbeat = HEARTBEAT_OPEN; + + /*Set up message list...*/ + c->messages = LL_new (); + if (!c->messages) { + report (RPT_ERR, "client_create: Error allocating"); + free (c); + return NULL; + } + + c->ack = 0; + c->name = NULL; + c->client_keys = NULL; + + c->screenlist = LL_new(); + + if (!c->screenlist) { + report( RPT_ERR, "client_create: Error allocating"); + return NULL; + } + return c; +} + +int +client_destroy (Client * c) +{ + //int err; + Screen *s; + + debug (RPT_INFO, "client_destroy()"); + + if (!c) + return -1; + + client_close_sock (c); + + /*Free client's other data*/ + c->ack = 0; + + /* Clean up the name...*/ + if (c->name) + free (c->name); + + /* Clean up the key list...*/ + //if (d->client_keys) + // free (d->client_keys); + + /* Clean up the screenlist...*/ + debug( RPT_DEBUG, "client_data_destroy: Cleaning screenlist"); + + for( s=LL_GetFirst (c->screenlist); s; s=LL_GetNext(c->screenlist) ) { + debug( RPT_DEBUG, "client_data_destroy: removing screen %s", s->id); + + /* FIXME? This shouldn't be handled here... + * Now, remove it from the screenlist...*/ + if (screenlist_remove_all (s) < 0) { + /* Not a serious error..*/ + report( RPT_ERR, "client_data_destroy: Error dequeueing screen"); + return 0; + } + /* Free its memory...*/ + screen_destroy (s); + /* Note that the screen is not removed from the list because + * the list will be destroyed anyway... + */ + } + LL_Destroy( c->screenlist); + + /* Remove structure */ + free (c); + + return 0; +} + +void client_close_sock (Client * c) +{ + char *str; + + if (c->sock == EOF ) + return; + + /*Eat the rest of the incoming requests...*/ + debug (RPT_DEBUG, "client_destroy: get_messages"); + while ((str = client_get_message (c))) { + if (str) { + debug (RPT_DEBUG, "client_destroy: kill message %s", str); + free (str); + } + } + + /*close socket...*/ + if (c->sock) { + /*sock_send_string (c->sock, "bye\n");*/ + close(c->sock); + report(RPT_NOTICE, "closed socket for #%d", c->sock); + } + c->sock = EOF; +} + +/*Add and remove messages from the client's queue...*/ +int +client_add_message (Client * c, char *message) +{ + int err = 0; + char *dup; + char *str, *cp; + char delimiters[] = "\n\r\0"; +/* int len;*/ + + debug(RPT_DEBUG, "client_add_message(%s)", message); + + if (!c) + return -1; + if (!message) + return -1; + +/* len = strlen(message); + * if(len < 1) return 0; + */ + + /* Copy the string to avoid overwriting the original...*/ + dup = strdup (message); + if (!dup) { + report(RPT_ERR, "client_add_message: Error allocating"); + return -1; + } + /* Now split the string into lines and enqueue each one...*/ + for (str = strtok (dup, delimiters); str; str = strtok (NULL, delimiters)) { + cp = strdup (str); + debug (RPT_DEBUG, "client_add_message: %s", cp); + err += LL_Enqueue (c->messages, (void *) cp); + } + + /*debug(RPT_DEBUG, "client_add_message(%s): %i errors", message, err);*/ + free (dup); /* Fixed memory leak...*/ + + /* Err is the number of errors encountered...*/ + return err; + +} + +/* Woo-hoo! A simple function. :)*/ +char * +client_get_message (Client * c) +{ + char *str; + + debug(RPT_DEBUG, "client_get_message()"); + + if (!c) + return NULL; + + str = (char *) LL_Dequeue (c->messages); + + /*debug(RPT_DEBUG, "client_get_message: \"%s\"", str);*/ + + return str; +} + + +Screen * +client_find_screen (Client * c, char *id) +{ + Screen *s; + + if (!c) + return NULL; + if (!id) + return NULL; + + debug (RPT_INFO, "client_find_screen(%s)", id); + + LL_Rewind (c->screenlist); + do { + s = LL_Get (c->screenlist); + if ((s) && (0 == strcmp (s->id, id))) { + debug (RPT_DEBUG, "client_find_screen: Found %s", id); + return s; + } + } while (LL_Next (c->screenlist) == 0); + + return NULL; +} + +int +client_add_screen (Client * c, Screen * s) +{ + /* TODO: Check for errors here?*/ + LL_Push (c->screenlist, (void *) s); + + /* Now, add it to the screenlist...*/ + if (screenlist_add (s) < 0) { + report (RPT_ERR, "client_add_screen: Error queueing new screen"); + return -1; + } + + return 0; +} + +int +client_remove_screen (Client * c, Screen * s) +{ + if (!c) + return -1; + if (!s) + return -1; + + /* TODO: Check for errors here?*/ + LL_Remove (c->screenlist, (void *) s); + + /* Now, remove it from the screenlist...*/ + if (screenlist_remove_all (s) < 0) { + /* Not a serious error..*/ + report (RPT_ERR, "client_remove_screen: Error dequeueing screen"); + return 0; + } + return 0; +} + +int client_screen_count (Client * c) +{ + return LL_Length(c->screenlist); +} \ No newline at end of file diff --git a/server/client.h b/server/client.h new file mode 100644 index 0000000..7dfd175 --- /dev/null +++ b/server/client.h @@ -0,0 +1,59 @@ +#ifndef CLIENT_H +#define CLIENT_H + +#include "shared/LL.h" +#include + +#define CLIENT_NAME_SIZE 256 + +typedef struct Client { + char *name; + int ack; + int sock; + char addr[64]; + int backlight; + int heartbeat; + + LinkedList *messages; + + /* and other stuff... doesn't matter yet*/ + LinkedList *screenlist; + + /* TO BE REMOVED */ + char *client_keys; + + /* list of requested keys */ + //LinkedList *keylist; + /* list of client supplied menus */ + //LinkedList *menulist; + +} Client; + +#include "screen.h" + + +/* When a new client connects, set up a new client data struct */ +Client * client_create (int sock); + +/* Destroys the client data */ +int client_destroy (Client * c); + +/* Close the socket */ +void client_close_sock (Client * c); + +/* Add message to the client's queue...*/ +int client_add_message (Client * c, char *message); + +/* Get message from queue */ +char * client_get_message (Client * c); + +/* Find a named screen for the client */ +Screen * client_find_screen (Client * c, char *id); + +int client_add_screen (Client * c, Screen * s); + +int client_remove_screen (Client * c, Screen * s); + +int client_screen_count (Client * c); + +#endif \ No newline at end of file diff --git a/server/client_data.c b/server/client_data.c deleted file mode 100644 index e04e638..0000000 --- a/server/client_data.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * client_data.c - * This file is part of LCDd, the lcdproc server. - * - * This file is released under the GNU General Public License. Refer to the - * COPYING file distributed with this package. - * - * Copyright (c) 1999, William Ferrell, Scott Scriven - * - * - * Creates and destroys a client's data structures. These are mainly - * its name, screen list, and menu list. - * - */ - -#include -#include -#include - -#include "shared/report.h" - -#include "client_data.h" -#include "screen.h" -#include "screenlist.h" - -#define ResetScreenList(a) LL_Rewind(a) -#define NewScreen LL_new -#define NextScreen(a) (screen *)LL_Get(a) -#define MoreScreens(a) (LL_Next(a) == 0) -#define DestroyScreenList(a) LL_Destroy(a) - -int -client_data_init (client_data * d) -{ - if (!d) - return -1; - - d->ack = 0; - d->name = NULL; - d->client_keys = NULL; - - d->screenlist = NewScreen(); - if (!d->screenlist) { - report( RPT_ERR, "client_data_init: Error allocating screenlist"); - return -1; - } - /* TODO: this section... (client menus) - d->menulist = LL_new(); - if(!d->menulist) - { - report( RPT_ERR, "client_data_init: Error allocating menulist"); - return -1; - } - */ - return 0; -} - -int -client_data_destroy (client_data * d) -{ - screen *s; - - report( RPT_INFO, "client_data_destroy"); - - if (!d) - return -1; - - d->ack = 0; - - /* Clean up the name...*/ - if (d->name) - free (d->name); - - /* Clean up the key list...*/ - if (d->client_keys) - free (d->client_keys); - - /* Clean up the screenlist...*/ - debug( RPT_DEBUG, "client_data_destroy: Cleaning screenlist"); - ResetScreenList (d->screenlist); - do { - s = NextScreen(d->screenlist); - if (s) { - debug( RPT_DEBUG, "client_data_destroy: removing screen %s", s->id); - - /* FIXME? This shouldn't be handled here... - * Now, remove it from the screenlist...*/ - if (screenlist_remove_all (s) < 0) { - /* Not a serious error..*/ - report( RPT_ERR, "client_data_destroy: Error dequeueing screen"); - return 0; - } - /* Free its memory...*/ - screen_destroy (s); - } - } while (MoreScreens(d->screenlist)); - DestroyScreenList(d->screenlist); - - /* TODO: clean up the rest of the data...*/ - - return 0; -} diff --git a/server/client_data.h b/server/client_data.h deleted file mode 100644 index aa7c51f..0000000 --- a/server/client_data.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * client_data.h - * This file is part of LCDd, the lcdproc server. - * - * This file is released under the GNU General Public License. Refer to the - * COPYING file distributed with this package. - * - * Copyright (c) 1999, William Ferrell, Scott Scriven - * - */ - -#ifndef CLIENT_DATA_H -#define CLIENT_DATA_H - -#include "shared/LL.h" - -#define CLIENT_NAME_SIZE 256 - -typedef struct client_data { - int ack; - char *name; - /* and other stuff... doesn't matter yet*/ - LinkedList *screenlist; - /* list of requested keys...*/ - char *client_keys ; - LinkedList *menulist; - -} client_data; - -/* sets up an existing (empty) client_data struct*/ -int client_data_init (client_data * d); -/* destroys members of a client's data*/ -int client_data_destroy (client_data * d); - -#endif diff --git a/server/client_functions.c b/server/client_functions.c deleted file mode 100644 index 163c58b..0000000 --- a/server/client_functions.c +++ /dev/null @@ -1,1597 +0,0 @@ -/* - * client_functions.c - * This file is part of LCDd, the lcdproc server. - * - * This file is released under the GNU General Public License. Refer to the - * COPYING file distributed with this package. - * - * Copyright (c) 1999, William Ferrell, Scott Scriven - * - * - * This contains definitions for all the functions which clients can run. - * The functions here are to be called only from parse.c's interpreter. - * - * The client's available function set is defined here, as is the syntax - * for each command. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "shared/report.h" -#include "shared/sockets.h" - -#include "drivers.h" - -#include "main.h" -#include "render.h" -#include "clients.h" -#include "parse.h" -#include "screen.h" -#include "widget.h" -#include "client_functions.h" - -int info_func (client * c, int argc, char **argv); -int sleep_func (client * c, int argc, char **argv); - -client_function commands[] = { - {"test_func", test_func_func}, - {"hello", hello_func}, - {"client_set", client_set_func}, - {"client_add_key", client_add_key_func}, - {"client_del_key", client_del_key_func}, - {"screen_add_key", screen_add_key_func}, - {"screen_del_key", screen_del_key_func}, - {"screen_add", screen_add_func}, - {"screen_del", screen_del_func}, - {"screen_set", screen_set_func}, - {"widget_add", widget_add_func}, - {"widget_del", widget_del_func}, - {"widget_set", widget_set_func}, - {"menu_add", menu_add_func}, - {"menu_del", menu_del_func}, - {"menu_set", menu_set_func}, - {"menu_add_item", menu_add_item_func}, - {"menu_del_item", menu_del_item_func}, - {"menu_set_item", menu_set_item_func}, - /* Misc stuff...*/ - {"backlight", backlight_func}, - {"output", output_func}, - {"noop", noop_func}, - {"info", info_func}, - {"sleep", sleep_func}, - {NULL, NULL}, -}; - -/* Remember: argc counts all arguments, including the command name; - * so it will actually be one more than the number of arguments given - * to the command...*/ - -#define NoArguments (argc == 1) -#define AnyArguments (argc != 1) -#define MoreArgumentsThan(a) (argc > (a)) - -/* TODO: Maybe more error-checking for "->"'s?*/ - -/*************************************************************** - * Debugging only.. prints out a list of arguments it receives - */ -int -test_func_func (client * c, int argc, char **argv) -{ - int i; - char str[256]; - - for (i = 0; i < argc; i++) { - snprintf (str, sizeof(str), "test_func_func: %i -> %s\n", i, argv[i]); - report (RPT_INFO, str); - sock_send_string (c->sock, str); - } - return 0; -} - -/*************************************************************** - * The client must say "hello" before doing anything else. - * - * It returns a string of info about the server to the client - * - * usage: hello - */ -int -hello_func (client * c, int argc, char **argv) -{ - char str[256]; - - /* TODO: Give *real* info about the server/lcd...*/ - - if (AnyArguments) { - sock_send_string (c->sock, "huh? extra parameters ignored\n"); - } - - debug(RPT_INFO, "Hello!"); - - memset(str, '\0', sizeof(str)); - snprintf (str, sizeof(str), "connect LCDproc %s protocol %s lcd wid %i hgt %i cellwid %i cellhgt %i\n", - version, protocol_version, display_props->width, display_props->height, display_props->cellwidth, display_props->cellheight); - -/* lcdproc (client) depends on the above format... - * snprintf (str, sizeof(str), "connect LCDproc %s protocol %s LCD %ix%i with cells %ix%i\n", - * version, protocol_version, lcd.wid, lcd.hgt, lcd.cellwid, lcd.cellhgt); - */ - - sock_send_string (c->sock, str); - - if (c->data) - c->data->ack = 1; - - return 0; -} - -/*************************************************** - * sets info about the client, such as its name - * - * usage: client_set -name - */ -int -client_set_func (client * c, int argc, char **argv) -{ - int i; - char str[16], buf[80]; - - memset(str, '\0', sizeof(str)); - if (!c->data->ack) - return 1; - - if (argc != 3) { - switch (argc) { - case 1: - sock_send_string (c->sock, "huh? usage: client_set -name \n"); - break; - case 2: - sock_send_string (c->sock, "huh? Not enough parameters\n"); - break; - default: - sock_send_string (c->sock, "huh? Too many parameters\n"); - break; - } - return 0; - } - - i = 1; - do { - char *p; - - /* This bit of code means that "-name" is the same as "name"...*/ - p = argv[i]; - if (*p == '-') - p++; - - /* Handle the "name" parameter*/ - if (strcmp (p, "name") == 0) { - i++; - if (argv[i] == '\0') { - snprintf (buf, sizeof(buf), "huh? internal error: no parameter #%d\n", i); - sock_send_string (c->sock, buf); - continue; - } - - if (strlen(argv[i]) > sizeof(str) -1) { - sock_send_string (c->sock, "huh? name too long\n"); - } else { - strncpy(str, argv[i], sizeof(str) - 1); - - debug(RPT_DEBUG, "client_set: name=\"%s\"", argv[i]); - - /* set the name...*/ - if (c->data->name) - free (c->data->name); - - if ((c->data->name = strdup (str)) == NULL) { - sock_send_string(c->sock, "huh? error allocating memory!\n"); - } else { - sock_send_string(c->sock, "success\n"); - i++; /* bypass argument (name string)*/ - } - } - } else { - snprintf (buf, sizeof(buf), "huh? invalid parameter (%s)\n", p); - sock_send_string (c->sock, buf); - } - } while (++i < argc); - - return 0; -} - -/****************************************************************** - * Tells the server the client would like to accept keypresses - * of a particular type - * - * usage: client_add_key - */ -int -client_add_key_func (client * c, int argc, char **argv) -{ - char * keys ; - - if (!c->data->ack) - return 1; - - if (argc != 2) { - switch (argc) { - case 1: - sock_send_string (c->sock, "huh? usage: client_add_key \n"); - break; - default: - sock_send_string (c->sock, "huh? Too many parameters...\n"); - break; - } - return 0; - } - - keys = argv[1]; - debug(RPT_DEBUG, "client_add_key: current client will handle key(s) %s", keys); - - if (!c->data->client_keys) { - /* No keys list, create a new one*/ - c->data->client_keys = strdup( keys ); - } else { - /* Add supplied keys to existing list - * NOTE: There could be duplicates in the resulting list - * That's OK, it's the existence of the key in the list - * that's important. We'll be more careful in the delete - * key function. - */ - char * new ; - int new_len = strlen(c->data->client_keys) + strlen(keys) + 1 ; - - new = realloc( c->data->client_keys, new_len ); - if( new ) { - c->data->client_keys = new ; - strcat( new, keys ); - } else { - sock_send_string(c->sock, "huh? could not allocate memory for new keys\n"); - return 0; - } - } - - if (c->data->client_keys) { - sock_send_string(c->sock, "success\n"); - } else { - sock_send_string(c->sock, "huh? failed\n"); - } - - return 0; -} - -/********************************************************************* - + Tells the server the client would NOT like to accept keypresses - * of a particular type - * - * usage: client_del_key - */ -int -client_del_key_func (client * c, int argc, char **argv) -{ - char * keys ; - - if (!c->data->ack) - return 1; - - if (argc != 2) { - if (argc == 1) { - sock_send_string (c->sock, "huh? usage: client_del_key \n"); - return 0; - } else { - sock_send_string (c->sock, "huh? Too many parameters...\n"); - return 0; - } - } - - keys = argv[1] ; - debug(RPT_DEBUG, "client_del_key: Deleting key(s) %s from client_keys", keys); - - if (c->data->client_keys) { - /* Client has keys, remove keys from the list - * NOTE: We let malloc/realloc remember the length - * of the allocated storage. If keys are later - * added, realloc (in add_key above) will make - * sure there is enough space at c->data->client_keys - */ - char * from ; - char * to ; - - to = from = c->data->client_keys ; - while( *from ) { - /* Is this key to be deleted from the list?*/ - if( strchr( keys, *from ) ) { - /* Yes, skip it*/ - ++from ; - } else { - /* No, save it*/ - *to++ = *from++ ; - } - } - } - - sock_send_string(c->sock, "success\n"); - - return 0; -} - -/********************************************************************** - * Tells the server the client would like to accept keypresses - * of a particular type when the given screen is active on the display - * - * screen_add_key - */ -int -screen_add_key_func (client * c, int argc, char **argv) -{ - /*widget * w ;*/ /* Keys are stored on a WID_KEYS widget */ - screen * s ; /* Attached to a specific screen */ - char * id ; /* Screen ID */ - char * keys ; /* Keys wanted */ - - if (!c->data->ack) - return 1; - - if (argc != 3) { - switch (argc) { - case 1: - sock_send_string (c->sock, "huh? usage: screen_add_key \n"); - break; - case 2: - sock_send_string (c->sock, "huh? You must specify a key list\n"); - break; - default: - sock_send_string (c->sock, "huh? Too many parameters...\n"); - break; - } - return 0; - } - - id = argv[1]; - keys = argv[2]; - debug(RPT_DEBUG, "screen_add_key: Adding key(s) %s to screen %s", keys, id); - - /* Find the screen*/ - s = screen_find (c, id); - if (!s) { - sock_send_string (c->sock, "huh? Invalid screen id\n"); - return 0; - } - - /* Save the keys*/ - if (!s->keys) { - /* Save supplied key list*/ - s->keys = strdup( keys ); - } else { - /* Add supplied keys to existing list - * NOTE: There could be duplicates in the resulting list - * That's OK, it's the existence of the key in the list - * that's important. We'll be more careful in the delete - * key function. - */ - char * new ; - new = realloc( s->keys, strlen(s->keys) + strlen(keys) +1 ); - if( new ) { - s->keys = new ; - strcat( new, keys ); - } else { - sock_send_string(c->sock, "huh? could not allocate memory for new keys\n"); - return 0; - } - } - - if (!s->keys) { - sock_send_string(c->sock, "huh? failed\n"); - } else - sock_send_string(c->sock, "success\n"); - - return 0; -} - -/************************************************************************* - * Tells the server the client would NOT like to accept keypresses - * of a particular type when the given screen is active on the display - * - * usage: screen_del_key - */ -int -screen_del_key_func (client * c, int argc, char **argv) -{ - /*widget * w ;*/ /* Keys are stored on a WID_KEYS widget */ - screen * s ; /* Attached to a specific screen */ - char * id ; /* Screen ID */ - char * keys ; /* Keys wanted */ - - if (!c->data->ack) - return 1; - - if (argc != 3) { - switch (argc) { - case 1: - sock_send_string (c->sock, "huh? usage: screen_del_key \n"); - break; - case 2: - sock_send_string (c->sock, "huh? You must specify a key list\n"); - break; - default: - sock_send_string (c->sock, "huh? Too many parameters\n"); - break; - } - return 0; - } - - id = argv[1] ; - keys = argv[2] ; - debug(RPT_DEBUG, "screen_del_key: Deleting key(s) %s from screen %s", keys, id); - - /* Find the screen*/ - s = screen_find (c, id); - - if (!s) { - sock_send_string (c->sock, "huh? Invalid screen id\n"); - return 0; - } - - /* Do we have keys?*/ - if (s->keys) { - /* Have keys, remove keys from the list - * NOTE: We let malloc/realloc remember the length - * of the allocated storage. If keys are later - * added, realloc (in add_key above) will make - * sure there is enough space at s->keys - */ - char * from ; - char * to ; - - to = from = s->keys ; - while( *from ) { - /* Is this key to be deleted from the list?*/ - if( strchr( keys, *from ) ) { - /* Yes, skip it*/ - ++from ; - } else { - /* No, save it*/ - *to++ = *from++ ; - } - } - to = '\0'; /* terminates the new keys string...*/ - } - - sock_send_string(c->sock, "success\n"); - - return 0; -} - -/*************************************************************** - * Tells the server the client has another screen to offer - * - * usage: screen_add - */ -int -screen_add_func (client * c, int argc, char **argv) -{ - int err = 0; - char scr[128]; - - if (!c->data->ack) - return 1; - - if (argc != 2) { - switch (argc) { - case 1: - sock_send_string (c->sock, "huh? usage: screen_add \n"); - break; - default: - sock_send_string (c->sock, "huh? Too many parameters...\n"); - break; - } - return 0; - } - - debug(RPT_DEBUG, "screen_add: Adding screen %s", argv[1]); - - memset(scr, '\0', sizeof(scr)); - strncpy(scr, argv[1], sizeof(scr) - 1); - - err = screen_add (c, scr); - if (err == 0) - sock_send_string(c->sock, "success\n"); - else if (err < 0) { - report(RPT_WARNING, "screen_add_func: Error adding screen"); - sock_send_string (c->sock, "huh? failed to add screen id#\n"); - } else - sock_send_string (c->sock, "huh? You already have a screen with that id#\n"); - - report(RPT_NOTICE, "added a screen (%s) to the display", scr); - return 0; -} - -/**************************************************************** - * Client requests that the server forget about a screen - * - * usage: screen_del - */ -int -screen_del_func (client * c, int argc, char **argv) -{ - int err = 0; - char scr[128]; - - if (!c->data->ack) - return 1; - - if (argc != 2) { - if (NoArguments) - sock_send_string (c->sock, "huh? usage: screen_del \n"); - else - sock_send_string (c->sock, "huh? Too many parameters...\n"); - return 0; - } - - debug (RPT_DEBUG, "screen_del: Deleting screen %s", argv[1]); - - /* Enforce bounds limits on argv[1]*/ - memset(scr, '\0', sizeof(scr)); - strncpy(scr, argv[1], sizeof(scr) - 1); - - err = screen_remove (c, scr); - if ( err == 0 ) - sock_send_string(c->sock, "success\n"); - else if (err < 0) { - report(RPT_WARNING, "screen_del_func: Error removing screen"); - sock_send_string(c->sock, "huh? failed to remove screen\n"); - } else - sock_send_string (c->sock, "huh? You don't have a screen with that id#\n"); - - report(RPT_NOTICE, "removed a screen (%s) from the display", scr); - return 0; -} - -/*************************************************************** - * Configures info about a particular screen, such as its - * name, priority, or duration - * - * usage: screen_set [ -priority ] [ -name ] [ -duration ] - * [ -wid ] [ -hgt ] [ -heartbeat ] [ -cursor ] - * [ -cursor_x ] [ -cursor_y ] - */ -int -screen_set_func (client * c, int argc, char **argv) -{ - int i; - - int number; - char *id; - screen *s; - - if (!c->data->ack) - return 1; - - if (NoArguments) { - sock_send_string (c->sock, "huh? usage: screen_set [ -priority ] [ -name ] [ -duration ] [ -wid ] [ -hgt ] [ -heartbeat ]\n"); - return 0; - } else if (argc == 2) { - sock_send_string (c->sock, "huh? What do you want to set?\n"); - return 0; - } - - id = argv[1]; - s = screen_find (c, id); - if (!s) { - sock_send_string (c->sock, "huh? Invalid screen id\n"); - return 0; - } - /* Handle the rest of the parameters*/ - for (i = 2; i < argc; i++) { - char *p; - - /* The following code allows us to use p for comparisions, - * ignoring a (valid) single leading '-' - reduces string comparisons - * by half. - */ - - p = argv[i]; - if (*p == '-') - p++; - - /* Handle the "name" parameter*/ - if (strcmp (p, "name") == 0) { - if (argc > i + 1) { - i++; - debug (RPT_DEBUG, "screen_set: name=\"%s\"", argv[i]); - - /* set the name...*/ - if (s->name) - free (s->name); - s->name = strdup (argv[i]); - sock_send_string(c->sock, "success\n"); - } else { - sock_send_string (c->sock, "huh? -name requires a parameter\n"); - } - } - /* Handle the "priority" parameter*/ - else if (strcmp (p, "priority") == 0) { - if (argc > i + 1) { - i++; - debug (RPT_DEBUG, "screen_set: priority=\"%s\"", argv[i]); - - /* set the priority...*/ - number = atoi (argv[i]); - if (number > 0) - s->priority = number; - sock_send_string(c->sock, "success\n"); - } else { - sock_send_string (c->sock, "huh? -priority requires a parameter\n"); - } - } - /* Handle the "duration" parameter*/ - else if (strcmp (p, "duration") == 0) { - if (argc > i + 1) { - i++; - debug (RPT_DEBUG, "screen_set: duration=\"%s\"", argv[i]); - - /* set the duration...*/ - number = atoi (argv[i]); - if (number > 0) - s->duration = number; - sock_send_string(c->sock, "success\n"); - } else { - sock_send_string (c->sock, "huh? -duration requires a parameter\n"); - } - } - /* Handle the "heartbeat" parameter*/ - else if (strcmp (p, "heartbeat") == 0) { - if (argc > i + 1) { - i++; - debug (RPT_DEBUG, "screen_set: heartbeat=\"%s\"", argv[i]); - - /* set the heartbeat type...*/ - if (0 == strcmp (argv[i], "on")) - s->heartbeat = HEARTBEAT_ON; - if (0 == strcmp (argv[i], "heart")) - s->heartbeat = HEARTBEAT_ON; - if (0 == strcmp (argv[i], "normal")) - s->heartbeat = HEARTBEAT_ON; - if (0 == strcmp (argv[i], "default")) - s->heartbeat = HEARTBEAT_ON; - if (0 == strcmp (argv[i], "off")) - s->heartbeat = HEARTBEAT_OFF; - if (0 == strcmp (argv[i], "none")) - s->heartbeat = HEARTBEAT_OFF; - if (0 == strcmp (argv[i], "slash")) - s->heartbeat = HEARTBEAT_SLASH; - sock_send_string(c->sock, "success\n"); - } else { - sock_send_string (c->sock, "huh? -heartbeat requires a parameter\n"); - } - } - /* Handle the "wid" parameter*/ - else if (strcmp (p, "wid") == 0) { - if (argc > i + 1) { - i++; - debug (RPT_DEBUG, "screen_set: wid=\"%s\"", argv[i]); - - /* set the duration...*/ - number = atoi (argv[i]); - if (number > 0) - s->wid = number; - sock_send_string(c->sock, "success\n"); - } else { - sock_send_string (c->sock, "huh? -wid requires a parameter\n"); - } - - } - /* Handle the "hgt" parameter*/ - else if (strcmp (p, "hgt") == 0) { - if (argc > i + 1) { - i++; - debug (RPT_DEBUG, "screen_set: hgt=\"%s\"", argv[i]); - - /* set the duration...*/ - number = atoi (argv[i]); - if (number > 0) - s->hgt = number; - sock_send_string(c->sock, "success\n"); - } else { - sock_send_string (c->sock, "huh? -hgt requires a parameter\n"); - } - } - /* Handle the "timeout" parameter*/ - else if (strcmp (p, "timeout") == 0) { - if (argc > i + 1) { - i++; - debug (RPT_DEBUG, "screen_set: timeout=\"%s\"", argv[i]); - /* set the duration...*/ - number = atoi (argv[i]); - /* Add the timeout value (count of TIME_UNITS) - * to struct, TIME_UNIT is 1/8th of a second - */ - if (number > 0) { - s->timeout = number; - report(RPT_NOTICE, "Timeout set."); - } - sock_send_string(c->sock, "success\n"); - } else { - sock_send_string (c->sock, "huh? -timeout requires a parameter\n"); - } - } - /* Handle the "backlight" parameter*/ - else if (strcmp (argv[i], "backlight") == 0) { - if (argc > i + 1) { - i++; - debug (RPT_DEBUG, "screen_set: backlight=\"%s\"", argv[i]); - /* set the backlight status based on what the client has set*/ - switch(c->backlight_state) { - case BACKLIGHT_OPEN: - if (strcmp ("on", argv[i]) == 0) - s->backlight_state = BACKLIGHT_ON; - - if (strcmp ("off", argv[i]) == 0) - s->backlight_state = BACKLIGHT_OFF; - - if (strcmp ("toggle", argv[i]) == 0) { - if (s->backlight_state == BACKLIGHT_ON) - s->backlight_state = BACKLIGHT_OFF; - else if (s-backlight_state == BACKLIGHT_OFF) - s->backlight_state = BACKLIGHT_ON; - } - - if (strcmp ("blink", argv[i]) == 0) - s->backlight_state |= BACKLIGHT_BLINK; - - if (strcmp ("flash", argv[i]) == 0) - s->backlight_state |= BACKLIGHT_FLASH; - break; - default: - /*If the backlight is not OPEN then inherit its state*/ - s->backlight_state = c->backlight_state; - break; - } - sock_send_string(c->sock, "success\n"); - } else { - sock_send_string (c->sock, "huh? -backlight requires a parameter\n"); - } - } - /* Handle the "cursor" parameter */ - else if (strcmp (argv[i], "cursor") == 0) { - if (argc > i + 1) { - i++; - debug (RPT_DEBUG, "screen_set: cursor=\"%s\"", argv[i]); - - /* set the heartbeat type...*/ - if (0 == strcmp (argv[i], "off")) - s->heartbeat = CURSOR_OFF; - if (0 == strcmp (argv[i], "on")) - s->cursor = CURSOR_DEFAULT_ON; - if (0 == strcmp (argv[i], "under")) - s->cursor = CURSOR_UNDER; - if (0 == strcmp (argv[i], "block")) - s->cursor = CURSOR_BLOCK; - sock_send_string(c->sock, "success\n"); - } else { - sock_send_string (c->sock, "huh? -cursor requires a parameter\n"); - } - } - /* Handle the "cursor_x" parameter */ - else if (strcmp (p, "cursor_x") == 0) { - if (argc > i + 1) { - i++; - debug (RPT_DEBUG, "screen_set: cursor_x=\"%s\"", argv[i]); - - /* set the position...*/ - number = atoi (argv[i]); - if (number > 0 && number <= s->wid) { - s->cursor_x = number; - sock_send_string(c->sock, "success\n"); - } - else { - sock_send_string(c->sock, "huh? cursor position outside screen\n"); - } - } else { - sock_send_string (c->sock, "huh? -cursor_x requires a parameter\n"); - } - } - /* Handle the "cursor_y" parameter */ - else if (strcmp (p, "cursor_y") == 0) { - if (argc > i + 1) { - i++; - debug (RPT_DEBUG, "screen_set: cursor_y=\"%s\"", argv[i]); - - /* set the position...*/ - number = atoi (argv[i]); - if (number > 0 && number <= s->hgt) { - s->cursor_y = number; - sock_send_string(c->sock, "success\n"); - } - else { - sock_send_string(c->sock, "huh? cursor position outside screen\n"); - } - } else { - sock_send_string (c->sock, "huh? -cursor_y requires a parameter\n"); - } - } - - else sock_send_string (c->sock, "huh? invalid parameter\n"); - }/* done checking argv*/ - return 0; -} - -/************************************************************************* - * Adds a widget to a screen, but doesn't give it a value - * - * usage: widget_add [ -in ] - */ -int -widget_add_func (client * c, int argc, char **argv) -{ - int err; - - char *type; - char *sid; - char *wid; - char *in = NULL; - screen *s; - - if (!c->data->ack) - return 1; - - if ((argc < 4) || (argc > 6)) { - switch (argc) { - case 1: - sock_send_string (c->sock, "huh? usage: widget_add [ -in ]\n"); - break; - case 2: - sock_send_string (c->sock, "huh? Widget ID and Widget Type not specified!\n"); - break; - case 3: - sock_send_string (c->sock, "huh? Widget Type not specified!\n"); - break; - default: - sock_send_string (c->sock, "huh? Too many parameters\n"); - break; - } - return 0; - } - - sid = argv[1]; - wid = argv[2]; - - s = screen_find (c, sid); - if (!s) { - sock_send_string (c->sock, "huh? Invalid screen id\n"); - return 0; - } - - type = argv[3]; - - /* Check for additional flags...*/ - if (argc > 4) { - char *p; - - p = argv[4]; - if (*p == '-') - p++; - - /* Handle the "in" flag to place widgets in a container...*/ - if (strcmp (p, "in")) { - if (argc < 6) { - sock_send_string (c->sock, "huh? Specify a frame to place widget in\n"); - return 0; - } - in = argv[5]; - } - } - - /* Add the widget and set its type...*/ - err = widget_add (s, wid, type, in, c->sock); - if (err == 0) - sock_send_string(c->sock, "success\n"); - else { - report(RPT_WARNING, "widget_add_func: Error adding widget"); - sock_send_string(c->sock, "huh? failed\n"); - } - - return 0; -} - -/******************************************************************* - * Removes a widget from a screen, and forgets about it - * - * usage: widget_del - */ -int -widget_del_func (client * c, int argc, char **argv) -{ - int err = 0; - - char *sid; - char *wid; - screen *s; - - if (!c->data->ack) - return 1; - - if (argc != 3) { - switch (argc) { - case 1: - sock_send_string (c->sock, "huh? usage: widget_del \n"); - break; - case 2: - sock_send_string (c->sock, "huh? Specify a widget #id\n"); - break; - default: - sock_send_string (c->sock, "huh? Too many parameters...\n"); - break; - } - return 0; - } - - sid = argv[1]; - wid = argv[2]; - - debug (RPT_DEBUG, "screen_del: Deleting widget %s.%s", sid, wid); - - s = screen_find (c, sid); - if (!s) { - sock_send_string (c->sock, "huh? Invalid screen id\n"); - } - - err = widget_remove (s, wid, c->sock); - if (err == 0) - sock_send_string(c->sock, "success\n"); - else { - report( RPT_WARNING, "widget_del_func: Error removing widget"); - sock_send_string(c->sock, "huh? failed\n"); - } - - return 0; -} - -/******************************************************************** - * Configures information about a widget, such as its size, shape, - * contents, position, speed, etc... - * - * Ack! This is long! - * - * widget_set - */ -int -widget_set_func (client * c, int argc, char **argv) -{ - int i; - - int x, y; - int left, top, right, bottom; - int length, direction; - int width, height; - int speed; - char *sid, *wid; - screen *s; - widget *w; - - if (!c->data->ack) - return 1; - - /* If there weren't enough parameters... - * We can't test for too many, since each widget may have a - * different number - plus, if the argument count is wrong, what ELSE - * could be wrong...? - */ - - if (argc < 4) { - switch (argc) { - case 1: - sock_send_string (c->sock, "huh? usage: widget_set \n"); - break; - case 2: - sock_send_string (c->sock, "huh? You must specify a widget id\n"); - break; - case 3: - sock_send_string (c->sock, "huh? You must send some widget data\n"); - break; - } - return 0; - } - - sid = argv[1]; - wid = argv[2]; - s = screen_find (c, sid); - if (!s) { - sock_send_string (c->sock, "huh? Invalid screen id\n"); - return 0; - } - w = widget_find (s, wid); - if (!w) { - sock_send_string (c->sock, "huh? Invalid widget id\n"); - /* Client Debugging...*/ - { - int i; - report( RPT_WARNING, "huh? Invalid widget id (%s)", wid); - for (i = 0; i < argc; i++) - report( RPT_WARNING, " %.40s ", argv[i]); - } - return 0; - } - /* FIXME? Shouldn't this be handled in widget.c?*/ - i = 3; - switch (w->type) { - case WID_STRING: /* String takes "x y text"*/ - if (argc != i + 3) - sock_send_string (c->sock, "huh? Wrong number of arguments\n"); - else { - if ((!isdigit ((unsigned int) argv[i][0])) || - (!isdigit ((unsigned int) argv[i + 1][0]))) { - sock_send_string (c->sock, "huh? Invalid coordinates\n"); - } else /* Set all the data...*/ - { - x = atoi (argv[i]); - y = atoi (argv[i + 1]); - w->x = x; - w->y = y; - if (w->text) - free (w->text); - w->text = strdup (argv[i + 2]); - if (!w->text) { - report( RPT_WARNING, "widget_set_func: Error allocating string"); - return -1; - } - debug (RPT_DEBUG, "Widget %s set to %s", wid, w->text); - sock_send_string(c->sock, "success\n"); - } - } - break; - case WID_HBAR: /* Hbar takes "x y length"*/ - if (argc != i + 3) - sock_send_string (c->sock, "huh? Wrong number of arguments\n"); - else { - if ((!isdigit ((unsigned int) argv[i][0])) || - (!isdigit ((unsigned int) argv[i + 1][0]))) { - sock_send_string (c->sock, "huh? Invalid coordinates\n"); - } else { - x = atoi (argv[i]); - y = atoi (argv[i + 1]); - length = atoi (argv[i + 2]); - w->x = x; - w->y = y; - w->length = length; - } - debug (RPT_DEBUG, "Widget %s set to %i", wid, w->length); - sock_send_string(c->sock, "success\n"); - } - break; - case WID_VBAR: /* Vbar takes "x y length"*/ - if (argc != i + 3) - sock_send_string (c->sock, "huh? Wrong number of arguments\n"); - else { - if ((!isdigit ((unsigned int) argv[i][0])) || - (!isdigit ((unsigned int) argv[i + 1][0]))) { - sock_send_string (c->sock, "huh? Invalid coordinates\n"); - } else { - x = atoi (argv[i]); - y = atoi (argv[i + 1]); - length = atoi (argv[i + 2]); - w->x = x; - w->y = y; - w->length = length; - } - debug (RPT_DEBUG, "Widget %s set to %i", wid, w->length); - sock_send_string(c->sock, "success\n"); - } - break; - case WID_ICON: /* Icon takes "x y binary_data"*/ - if (argc != i + 3) - sock_send_string (c->sock, "huh? Wrong number of arguments\n"); - else { - if ((!isdigit ((unsigned int) argv[i][0])) || - (!isdigit ((unsigned int) argv[i + 1][0]))) { - sock_send_string (c->sock, "huh? Invalid coordinates\n"); - } else { - x = atoi (argv[i]); - y = atoi (argv[i + 1]); - w->x = x; - w->y = y; - /* TODO: Parse binary data and copy it to widget's data...*/ - } - } - sock_send_string (c->sock, "huh? Widget type not yet implemented\n"); - break; - case WID_TITLE: /* title takes "text"*/ - if (argc != i + 1) - sock_send_string (c->sock, "huh? Wrong number of arguments\n"); - else { - if (w->text) - free (w->text); - w->text = strdup (argv[i]); - if (!w->text) { - report( RPT_WARNING, "widget_set_func: Error allocating string"); - return -1; - } - debug (RPT_DEBUG, "Widget %s set to %s", wid, w->text); - sock_send_string(c->sock, "success\n"); - } - break; - case WID_SCROLLER: /* Scroller takes "left top right bottom direction speed text"*/ - if (argc != i + 7) { - sock_send_string (c->sock, "huh? Wrong number of arguments\n"); - } else { - if ((!isdigit ((unsigned int) argv[i][0])) || - (!isdigit ((unsigned int) argv[i + 1][0])) || - (!isdigit ((unsigned int) argv[i + 2][0])) || - (!isdigit ((unsigned int) argv[i + 3][0]))) { - sock_send_string (c->sock, "huh? Invalid coordinates\n"); - } else { - left = atoi (argv[i]); - /*debug("left: %d",left);*/ - top = atoi (argv[i + 1]); - /*debug("top: %d",top);*/ - right = atoi (argv[i + 2]); - /*debug("right: %d",right);*/ - bottom = atoi (argv[i + 3]); - /*debug("bottom: %d",bottom);*/ - direction = (int) (argv[i + 4][0]); - /*debug("dir: %c",(char)direction);*/ - speed = atoi (argv[i + 5]); - /*debug("speed: %d",speed);*/ - /* Direction must be v or h*/ - if (((char) direction != 'h') && ((char) direction != 'v')) { - sock_send_string (c->sock, "huh? Invalid direction\n"); - } else { - w->left = left; - w->top = top; - w->right = right; - w->bottom = bottom; - w->length = direction; - w->speed = speed; - if (w->text) - free (w->text); - w->text = strdup (argv[i + 6]); - if (!w->text) { - sock_send_string(c->sock, "huh? out of memory\n"); - report( RPT_WARNING, "widget_set_func: Error allocating string"); - return -1; - } - debug (RPT_DEBUG, "Widget %s set to %s", wid, w->text); - sock_send_string(c->sock, "success\n"); - } - } - } - break; - case WID_FRAME: /* Frame takes "left top right bottom wid hgt direction speed"*/ - if (argc != i + 8) { - sock_send_string (c->sock, "huh? Wrong number of arguments\n"); - } else { - if ((!isdigit ((unsigned int) argv[i][0])) || - (!isdigit ((unsigned int) argv[i + 1][0])) || - (!isdigit ((unsigned int) argv[i + 2][0])) || - (!isdigit ((unsigned int) argv[i + 3][0])) || - (!isdigit ((unsigned int) argv[i + 4][0])) || - (!isdigit ((unsigned int) argv[i + 5][0]))) { - sock_send_string (c->sock, "huh? Invalid coordinates\n"); - } else { - left = atoi (argv[i]); - /*debug("left: %d",left);*/ - top = atoi (argv[i + 1]); - /*debug("top: %d",top);*/ - right = atoi (argv[i + 2]); - /*debug("right: %d",right);*/ - bottom = atoi (argv[i + 3]); - /*debug("bottom: %d",bottom);*/ - width = atoi (argv[i + 4]); - /*debug("right: %d",right);*/ - height = atoi (argv[i + 5]); - /*debug("bottom: %d",bottom);*/ - direction = (int) (argv[i + 6][0]); - /*debug("dir: %c",(char)direction);*/ - speed = atoi (argv[i + 7]); - /*debug("speed: %d",speed);*/ - /* Direction must be v or h*/ - if (((char) direction != 'h') && ((char) direction != 'v')) { - sock_send_string (c->sock, "huh? Invalid direction\n"); - } else { - w->left = left; - w->top = top; - w->right = right; - w->bottom = bottom; - w->wid = width; - w->hgt = height; - w->length = direction; - w->speed = speed; - debug (RPT_DEBUG, "Widget %s set to (%i,%i)-(%i,%i) %ix%i", wid, left, top, right, bottom, width, height); - sock_send_string(c->sock, "success\n"); - } - } - } - break; - case WID_NUM: /* Num takes "x num"*/ - if (argc != i + 2) - sock_send_string (c->sock, "huh? Wrong number of arguments\n"); - else { - if (!isdigit ((unsigned int) argv[i][0])) { - sock_send_string (c->sock, "huh? Invalid coordinates\n"); - } else if (!isdigit ((unsigned int) argv[i + 1][0])) { - sock_send_string (c->sock, "huh? Invalid number\n"); - } else { - x = atoi (argv[i]); - y = atoi (argv[i + 1]); - w->x = x; - w->y = y; - } - debug (RPT_DEBUG, "Widget %s set to %i", wid, w->y); - sock_send_string(c->sock, "success\n"); - } - break; - case WID_NONE: - default: - sock_send_string (c->sock, "huh? Widget has no type\n"); - break; - } - - return 0; -} - -/************************************************************* - * Adds a menu to the client; handled by the server... - * - * usage: menu_add ...? - */ -int -menu_add_func (client * c, int argc, char **argv) -{ - - if (!c->data->ack) - return 1; - - sock_send_string (c->sock, "huh? Not implemented yet.\n"); - - return 0; -} - -/**************************************************************** - * Removes a client's menu and all contents from the server - * - * usage: menu_del ...? - */ -int -menu_del_func (client * c, int argc, char **argv) -{ - - if (!c->data->ack) - return 1; - - sock_send_string (c->sock, "huh? Not implemented yet.\n"); - - return 0; -} - -/*********************************************************************** - * Sets info about a menu, but not its items - * - * For example, should the menu be top-level, or buried somewhere? - * - * usage: menu_set ...? - */ -int -menu_set_func (client * c, int argc, char **argv) -{ - - if (!c->data->ack) - return 1; - - sock_send_string (c->sock, "huh? Not implemented yet.\n"); - - return 0; -} - -/************************************************************************* - * Adds an item to a menu - * - * usage: menu_add_item ...? - */ -int -menu_add_item_func (client * c, int argc, char **argv) -{ - - if (!c->data->ack) - return 1; - - sock_send_string (c->sock, "huh? Not implemented yet.\n"); - - return 0; -} - -/************************************************************************* - * Deletes an item from a menu - * - + usage: menu_del_item ...? - */ -int -menu_del_item_func (client * c, int argc, char **argv) -{ - - if (!c->data->ack) - return 1; - - sock_send_string (c->sock, "huh? Not implemented yet.\n"); - - return 0; -} - -/************************************************************************** - * Sets the info about a menu item - * - * For example, text displayed, widget type, value, etc... - * - * usage: menu_set_item ...? - */ -int -menu_set_item_func (client * c, int argc, char **argv) -{ - - if (!c->data->ack) - return 1; - - sock_send_string (c->sock, "huh? Not implemented yet.\n"); - - return 0; -} - -/*************************************************************************** - * Toggles the backlight, if enabled. - * - * usage: backlight - */ -int -backlight_func (client * c, int argc, char **argv) -{ - if (!c->data->ack) - return 1; - - if (argc != 2) { - switch (argc) { - case 1: - sock_send_string (c->sock, "huh? usage: backlight \n"); - break; - default: - sock_send_string (c->sock, "huh? Too many parameters...\n"); - break; - } - return 0; - } - - debug (RPT_DEBUG, "backlight(%s)", argv[1]); - - - backlight = (backlight && 1); /* only preserves ON/OFF bit*/ - - if (strcmp ("on", argv[1]) == 0) { - c->backlight_state = BACKLIGHT_ON; - - } else if (strcmp ("off", argv[1]) == 0) { - c->backlight_state = BACKLIGHT_OFF; - - } else if (strcmp ("toggle", argv[1]) == 0) { - if (c->backlight_state == BACKLIGHT_ON) - c->backlight_state = BACKLIGHT_OFF; - else if (c->backlight_state == BACKLIGHT_OFF) - c->backlight_state = BACKLIGHT_ON; - - } else if (strcmp ("blink", argv[1]) == 0) { - c->backlight_state |= BACKLIGHT_BLINK; - - } else if (strcmp ("flash", argv[1]) == 0) { - c->backlight_state |= BACKLIGHT_FLASH; - } - - sock_send_string(c->sock, "success\n"); - - return 0; - -} - -/**************************************************************************** - * Sets the state of the output port (such as on MtxOrb LCDs) - * - * usage: output - */ -#define ALL_OUTPUTS_ON -1 -#define ALL_OUTPUTS_OFF 0 - -int -output_func (client * c, int argc, char **argv) -{ - /*int rc = 0;*/ - char str[128]; - - if (argc != 2) { - if (NoArguments) - sock_send_string (c->sock, "huh? usage: output -- num may be decimal, hex, or octal\n"); - else - sock_send_string (c->sock, "huh? Too many parameters...\n"); - return 0; - } - - if (0 == strcmp (argv[1], "on")) - output_state = ALL_OUTPUTS_ON; - else if (0 == strcmp (argv[1], "off")) - output_state = ALL_OUTPUTS_OFF; - else { - long out; - char *endptr, *p; - - /* Note that there is no valid range set for - * output_state; thus a value in the 12 digits - * is not considered out of range. - */ - - errno = 0; - - /* errno is set here, because if strtol does not result in - * ERANGE (out of range error) it will not set errno (!). - * At least, this is the case with glibc 2.1.3 ... - */ - - p = argv[1]; - out = strtol(p, &endptr, 0); - - /* From the man page for strtol(3) - * - * In particular, if *nptr is not `\0' but **endptr is - * `\0' on return, the entire string is valid. - * - * In this case, argv[1] is *nptr, and &endptr is **endptr. - */ - - if (errno) { - int space; - - strcat(str, "huh? number argument: "); - space = sizeof(str) - 3 - strlen(str); - - strncat(str, strerror(errno), space); - strcat(str, "\n"); - - sock_send_string (c->sock, str); - return 0; - } else if (*p != '\0' && *endptr == '\0') { - output_state = out; - } else { - sock_send_string (c->sock, "huh? invalid parameter...\n"); - return 0; - } - } - - sock_send_string(c->sock, "success\n"); - - /* Makes sense to me to set the output immediately; - * however, the outputs are currently set in - * draw_screen(screen * s, int timer) - * Whatever for? */ - - /* drivers_output (output_state); */ - - report(RPT_NOTICE, "output states changed"); - return 0; -} - -/**************************************************************************** - * info_func - * - * usage: info - */ -int -info_func (client * c, int argc, char **argv) -{ - char str[1024]; - - if (! NoArguments) { - sock_send_string (c->sock, "huh? Extra arguments ignored...\n"); - } - - memset(str, '\0', sizeof(str)); - snprintf (str, sizeof(str)-1, (char*) drivers_get_info()); - - sock_send_string (c->sock, str); - - return 0; -} - -/******************************************************************************* - * sleep_func - * - * usage: sleep - */ -int -sleep_func (client * c, int argc, char **argv) -{ - int secs; - long out; - char *endptr, *p; - char str[120]; - -#define MAX_SECS 60 -#define MIN_SECS 1 - - if (argc != 2) { - if (NoArguments) - sock_send_string (c->sock, "huh? usage: sleep \n"); - else - sock_send_string (c->sock, "huh? Too many parameters...\n"); - return 0; - } - - errno = 0; - - /* errno is set here, because if strtol does not result in - * ERANGE (out of range error) it will not set errno (!). - * At least, this is the case with glibc 2.1.3 ... - */ - - p = argv[1]; - out = strtol(p, &endptr, 0); - - /* From the man page for strtol(3) - * - * In particular, if *nptr is not `\0' but **endptr is - * `\0' on return, the entire string is valid. - * - * In this case, argv[1] is *nptr, and &endptr is **endptr. - */ - - if (errno) { - int space; - - strcat(str, "huh? number argument: "); - space = sizeof(str) - 3 - strlen(str); - - strncat(str, strerror(errno), space); - strcat(str, "\n"); - - sock_send_string (c->sock, str); - return 0; - } else if (*p != '\0' && *endptr == '\0') { - secs = out; - out = out > MAX_SECS ? MAX_SECS : out; - out = out < MIN_SECS ? MIN_SECS : out; - } else { - sock_send_string (c->sock, "huh? invalid parameter...\n"); - return 0; - } - - /* Repeat until no more remains - should normally be zero - * on exit the first time...*/ - snprintf(str, sizeof(str), "sleeping %d seconds\n", secs); - sock_send_string (c->sock, str); - - /* whoops.... if this takes place as planned, ALL screens - * will "freeze" for the alloted time... - * - * while ((secs = sleep(secs)) > 0) - */ ; - - sock_send_string (c->sock, "huh? ignored (not fully implemented)\n"); - return 0; -} - -/***************************************************************************** - * Does nothing, returns "noop complete" message - * - * This is useful for shell scripts or programs that want to talk - * with LCDproc and not get deadlocked. Send a noop after each - * command and look for the "noop complete" message. - */ -int -noop_func (client * c, int argc, char **argv) -{ - sock_send_string (c->sock, "noop complete\n"); - return 0; -} - -/*end of client_functions.c*/ diff --git a/server/client_functions.h b/server/client_functions.h deleted file mode 100644 index ecc6656..0000000 --- a/server/client_functions.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * client_functions.h - * This file is part of LCDd, the lcdproc server. - * - * This file is released under the GNU General Public License. Refer to the - * COPYING file distributed with this package. - * - * Copyright (c) 1999, William Ferrell, Scott Scriven - * - */ - -#ifndef CLIENT_FUNCTION_H -#define CLIENT_FUNCTION_H - -/* - The function list for clients is stored in a table, and the items each - point to a function to call, defined below. - */ - -typedef struct client_function { - char *keyword; - int (*function) (client * c, int argc, char **argv); -} client_function; - -/* FIXME? Do these really need to be visible from other sources?*/ -int test_func_func (client * c, int argc, char **argv); -int hello_func (client * c, int argc, char **argv); -int client_set_func (client * c, int argc, char **argv); -int client_add_key_func (client * c, int argc, char **argv); -int client_del_key_func (client * c, int argc, char **argv); -int screen_add_key_func (client * c, int argc, char **argv); -int screen_del_key_func (client * c, int argc, char **argv); -int screen_add_func (client * c, int argc, char **argv); -int screen_del_func (client * c, int argc, char **argv); -int screen_set_func (client * c, int argc, char **argv); -int widget_add_func (client * c, int argc, char **argv); -int widget_del_func (client * c, int argc, char **argv); -int widget_set_func (client * c, int argc, char **argv); -int menu_add_func (client * c, int argc, char **argv); -int menu_del_func (client * c, int argc, char **argv); -int menu_set_func (client * c, int argc, char **argv); -int menu_add_item_func (client * c, int argc, char **argv); -int menu_del_item_func (client * c, int argc, char **argv); -int menu_set_item_func (client * c, int argc, char **argv); -int backlight_func (client * c, int argc, char **argv); -int output_func (client * c, int argc, char **argv); -int noop_func (client * c, int argc, char **argv); - -extern client_function commands[]; - -#endif diff --git a/server/clients.c b/server/clients.c index 862b97b..e80c01e 100644 --- a/server/clients.c +++ b/server/clients.c @@ -6,14 +6,12 @@ * COPYING file distributed with this package. * * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn * * * Inits/shuts down client system, - * creates/destroys individual clients, - * enqueues/dequeues messages from clients, * and searches for clients in the list. - * - * :) + * On short: manages the list of clients that are connected. * */ @@ -23,21 +21,21 @@ #include #include "sock.h" +#include "client.h" #include "clients.h" -#include "client_data.h" #include "shared/report.h" #include "render.h" -LinkedList *clients; +LinkedList *clientlist; /* Initialize and kill client list...*/ int -client_init () +clients_init () { debug(RPT_INFO, "client_init()"); - clients = LL_new (); - if (!clients) { + clientlist = LL_new (); + if (!clientlist) { report( RPT_ERR, "client_init: Unable to create client list"); return -1; } @@ -46,220 +44,84 @@ client_init () } int -client_shutdown () +clients_shutdown () { - client *c; + Client *c; - debug (RPT_INFO, "client_shutdown()"); + debug (RPT_INFO, "clients_shutdown()"); - /* Free all client structures... - * Note that the regular list loop doesn't work here, because - * client_destroy() calls LL_Remove() - */ - for (c = LL_Pop (clients); c; c = LL_Pop (clients)) { - debug (RPT_DEBUG, "client_shutdown: ..."); + /* Free all client structures... */ + for (c=LL_GetFirst (clientlist); c; c=LL_GetNext (clientlist) ) { + debug (RPT_DEBUG, "clients_shutdown: ..."); if (c) { - debug (RPT_DEBUG, "client_shutdown: ... %i ...", c->sock); + debug (RPT_DEBUG, "clients_shutdown: ... %i ...", c->sock); if (client_destroy (c) != 0) { - report (RPT_ERR, "client_shutdown: Error freeing client"); + report (RPT_ERR, "clients_shutdown: Error freeing client"); } else { - debug (RPT_DEBUG, "client_shutdown: Freed client..."); + debug (RPT_DEBUG, "clients_shutdown: Freed client..."); } } else { - debug (RPT_DEBUG, "client_shutdown: No client!"); + debug (RPT_DEBUG, "clients_shutdown: No client!"); } } /* Then, free the list...*/ - LL_Destroy (clients); + LL_Destroy (clientlist); - debug (RPT_DEBUG, "client_shutdown: done"); + debug (RPT_DEBUG, "clients_shutdown: done"); return 0; } +int +clients_add_client (Client *c) +{ + /* Add the client to the clients list... */ + return LL_Push (clientlist, c); +} + +int +clients_remove_client (Client *c) +{ + /* Remove the client from the clients list... */ + return (LL_Remove (clientlist, c) == NULL)?-1:0; +} + +Client * +clients_getfirst () +{ + return (Client *) LL_GetFirst(clientlist); +} + +Client * +clients_getnext () +{ + return (Client *) LL_GetNext(clientlist); +} + +int +clients_client_count () +{ + return LL_Length(clientlist); +} + + /* A client is identified by the file descriptor - + associated with it. - * - * Create and destroy clients.... - */ -client * -client_create (int sock) -{ - client *c; - - debug (RPT_DEBUG, "client_create(%i)", sock); - - /* Allocate new client...*/ - c = malloc (sizeof (client)); - if (!c) { - report (RPT_ERR, "client_create: error allocating new client"); - return NULL; - } - /* Init struct members*/ - c->sock = 0; - c->data = NULL; - c->messages = NULL; - - c->sock = sock; - c->backlight_state = backlight; /*By default we get the server setting*/ - - /*Set up message list...*/ - c->messages = LL_new (); - if (!c->messages) { - report (RPT_ERR, "client_create: error allocating message list"); - free (c); - return NULL; - } - /*TODO: allocate and init client data...*/ - c->data = malloc (sizeof (client_data)); - if (!c->data) { - report (RPT_ERR, "client_create: error allocating client data"); - free (c->messages); - free (c); - return NULL; - } else if (client_data_init (c->data) < 0) { - return NULL; - } - /*TODO: Check for errors while adding the client to the list?*/ - LL_Push (clients, (void *) c); - - return c; -} - -int -client_destroy (client * c) -{ - int err; - - char *str; - - debug (RPT_INFO, "client_destroy()"); - - if (!c) - return -1; - - /*Eat the rest of the incoming requests...*/ - debug (RPT_DEBUG, "client_destroy: get_messages"); - while ((str = client_get_message (c))) { - if (str) { - debug (RPT_DEBUG, "client_destroy: kill message %s", str); - free (str); - } - } - - /*close socket...*/ - if (c->sock) { - /*sock_send_string (c->sock, "bye\n");*/ - close(c->sock); - report(RPT_NOTICE, "closed socket for #%d", c->sock); - } - - err = LL_Destroy (c->messages); - - /*Free client's other data*/ - client_data_destroy (c->data); - - /*Remove the client from the clients list...*/ - LL_Remove (clients, c); - - free (c); - - return 0; -} - -/*Add and remove messages from the client's queue...*/ -int -client_add_message (client * c, char *message) -{ - int err = 0; - char *dup; - char *str, *cp; - char delimiters[] = "\n\r\0"; -/* int len;*/ - - debug(RPT_DEBUG, "client_add_message(%s)", message); - - if (!c) - return -1; - if (!message) - return -1; - -/* len = strlen(message); - * if(len < 1) return 0; + * associated with it. Find one. */ - /* Copy the string to avoid overwriting the original...*/ - dup = strdup (message); - if (!dup) { - report(RPT_ERR, "client_add_message: Error allocating new string"); - return -1; - } - /* Now split the string into lines and enqueue each one...*/ - for (str = strtok (dup, delimiters); str; str = strtok (NULL, delimiters)) { - cp = strdup (str); - debug (RPT_DEBUG, "client_add_message: %s", cp); - err += LL_Enqueue (c->messages, (void *) cp); - } - - /*debug(RPT_DEBUG, "client_add_message(%s): %i errors", message, err);*/ - free (dup); /* Fixed memory leak...*/ - - /* Err is the number of errors encountered...*/ - return err; - -} - -/* Woo-hoo! A simple function. :)*/ -char * -client_get_message (client * c) +Client * +clients_find_client_by_sock (int sock) { - char *str; + Client *c; - debug(RPT_DEBUG, "client_get_message()"); + debug(RPT_INFO, "clients_find_client_by_sock(%i)", sock); - if (!c) - return NULL; - - str = (char *) LL_Dequeue (c->messages); - - /*debug(RPT_DEBUG, "client_get_message: \"%s\"", str);*/ - - return str; -} - -/* Get and set the client's data...*/ -int -client_set (client * c, void *data) -{ - /* You know, I really doubt this function will be useful...*/ - return 0; -} - -void * -client_get (client * c) -{ - /* But this one might be handy...*/ - - return NULL; -} - -client * -client_find_sock (int sock) -{ - client *c; - -/* debug(RPT_INFO, "client_find_sock(%i)", sock);*/ - - LL_Rewind (clients); - do { - c = (client *) LL_Get (clients); -/* debug(RPT_DEBUG, "client_find_sock: ... %i ...", c->sock);*/ + for( c=LL_GetFirst(clientlist); c; c=LL_GetNext(clientlist) ) { if (c->sock == sock) { -/* debug(RPT_DEBUG, "client_find_sock: ..! %i !..", c->sock);*/ return c; } - } while (LL_Next (clients) == 0); + } debug (RPT_ERR, "client_find_sock: failed"); diff --git a/server/clients.h b/server/clients.h index a794bba..3c6c2eb 100644 --- a/server/clients.h +++ b/server/clients.h @@ -12,39 +12,25 @@ #ifndef CLIENTS_H #define CLIENTS_H -#include "client_data.h" +#include "client.h" #include "shared/LL.h" -typedef struct client { - int sock; - char addr[64]; - int backlight_state; - LinkedList *messages; - client_data *data; - -} client; - -extern LinkedList *clients; +/* extern LinkedList *clientlist; Not needed outside ? */ /* Initialize and kill client list...*/ -int client_init (); -int client_shutdown (); +int clients_init (); +int clients_shutdown (); -/* Create and destroy clients....*/ -client *client_create (int sock); -int client_destroy (client * c); +/* Add/remove clients (return -1 for error) */ +int clients_add_client (Client *c); +int clients_remove_client (Client *c); -/* Add and remove messages from the client's queue...*/ -int client_add_message (client * c, char *message); -char *client_get_message (client * c); - -/* Get and set the client's data... - * Not used at all yet, and may never be. Oh, well. - */ -int client_set (client * c, void *data); -void *client_get (client * c); +/* List functions */ +Client * clients_getfirst (); +Client * clients_getnext (); +int clients_client_count (); /* Search for a client with a particular filedescriptor...*/ -client *client_find_sock (int sock); +Client * clients_find_client_by_sock (int sock); #endif diff --git a/server/commands/client_commands.c b/server/commands/client_commands.c new file mode 100644 index 0000000..c2878af --- /dev/null +++ b/server/commands/client_commands.c @@ -0,0 +1,354 @@ +/* + * client_commands.c + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn + * + * + * This contains definitions for all the functions which clients can run. + * The functions here are to be called only from parse.c's interpreter. + * + * The client's available function set is defined here, as is the syntax + * for each command. + * + * This particular file defines actions concerning clients. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "shared/report.h" +#include "shared/sockets.h" + +#include "drivers.h" +#include "render.h" +#include "client.h" + +/*************************************************************** + * Debugging only.. prints out a list of arguments it receives + */ +int +test_func_func (Client * c, int argc, char **argv) +{ + int i; + char str[256]; + + for (i = 0; i < argc; i++) { + snprintf (str, sizeof(str), "test_func_func: %i -> %s\n", i, argv[i]); + report (RPT_INFO, str); + sock_send_string (c->sock, str); + } + return 0; +} + +/*************************************************************** + * The client must say "hello" before doing anything else. + * + * It returns a string of info about the server to the client + * + * usage: hello + */ +int +hello_func (Client * c, int argc, char **argv) +{ + char str[256]; + + /* TODO: Give *real* info about the server/lcd...*/ + + if (argc > 1) { + sock_send_string (c->sock, "huh? extra parameters ignored\n"); + } + + debug(RPT_INFO, "Hello!"); + + memset(str, '\0', sizeof(str)); + snprintf (str, sizeof(str), "connect LCDproc %s protocol %s lcd wid %i hgt %i cellwid %i cellhgt %i\n", + VERSION, PROTOCOL_VERSION, display_props->width, display_props->height, display_props->cellwidth, display_props->cellheight); + +/* lcdproc (client) depends on the above format... + * snprintf (str, sizeof(str), "connect LCDproc %s protocol %s LCD %ix%i with cells %ix%i\n", + * version, protocol_version, lcd.wid, lcd.hgt, lcd.cellwid, lcd.cellhgt); + */ + + sock_send_string (c->sock, str); + + c->ack = 1; + + return 0; +} + +/*************************************************** + * sets info about the client, such as its name + * + * usage: client_set -name + */ +int +client_set_func (Client * c, int argc, char **argv) +{ + int i; + char str[16], buf[80]; + + memset(str, '\0', sizeof(str)); + if (!c->ack) + return 1; + + if (argc != 3) { + switch (argc) { + case 1: + sock_send_string (c->sock, "huh? usage: client_set -name \n"); + break; + case 2: + sock_send_string (c->sock, "huh? Not enough parameters\n"); + break; + default: + sock_send_string (c->sock, "huh? Too many parameters\n"); + break; + } + return 0; + } + + i = 1; + do { + char *p; + + /* This bit of code means that "-name" is the same as "name"...*/ + p = argv[i]; + if (*p == '-') + p++; + + /* Handle the "name" parameter*/ + if (strcmp (p, "name") == 0) { + i++; + if (argv[i] == '\0') { + snprintf (buf, sizeof(buf), "huh? internal error: no parameter #%d\n", i); + sock_send_string (c->sock, buf); + continue; + } + + if (strlen(argv[i]) > sizeof(str) -1) { + sock_send_string (c->sock, "huh? name too long\n"); + } else { + strncpy(str, argv[i], sizeof(str) - 1); + + debug(RPT_DEBUG, "client_set: name=\"%s\"", argv[i]); + + /* set the name...*/ + if (c->name) + free (c->name); + + if ((c->name = strdup (str)) == NULL) { + sock_send_string(c->sock, "huh? error allocating memory!\n"); + } else { + sock_send_string(c->sock, "success\n"); + i++; /* bypass argument (name string)*/ + } + } + } else { + snprintf (buf, sizeof(buf), "huh? invalid parameter (%s)\n", p); + sock_send_string (c->sock, buf); + } + } while (++i < argc); + + return 0; +} + +/****************************************************************** + * Tells the server the client would like to accept keypresses + * of a particular type + * + * usage: client_add_key + */ +int +client_add_key_func (Client * c, int argc, char **argv) +{ + char * keys ; + + if (!c->ack) + return 1; + + if (argc != 2) { + switch (argc) { + case 1: + sock_send_string (c->sock, "huh? usage: client_add_key \n"); + break; + default: + sock_send_string (c->sock, "huh? Too many parameters...\n"); + break; + } + return 0; + } + + keys = argv[1]; + debug(RPT_DEBUG, "client_add_key: current client will handle key(s) %s", keys); + + if (!c->client_keys) { + /* No keys list, create a new one*/ + c->client_keys = strdup( keys ); + } else { + /* Add supplied keys to existing list + * NOTE: There could be duplicates in the resulting list + * That's OK, it's the existence of the key in the list + * that's important. We'll be more careful in the delete + * key function. + */ + char * new ; + int new_len = strlen(c->client_keys) + strlen(keys) + 1 ; + + new = realloc( c->client_keys, new_len ); + if( new ) { + c->client_keys = new ; + strcat( new, keys ); + } else { + sock_send_string(c->sock, "huh? could not allocate memory for new keys\n"); + return 0; + } + } + + if (c->client_keys) { + sock_send_string(c->sock, "success\n"); + } else { + sock_send_string(c->sock, "huh? failed\n"); + } + + return 0; +} + +/********************************************************************* + * Tells the server the client would NOT like to accept keypresses + * of a particular type + * + * usage: client_del_key + */ +int +client_del_key_func (Client * c, int argc, char **argv) +{ + char * keys ; + + if (!c->ack) + return 1; + + if (argc != 2) { + if (argc == 1) { + sock_send_string (c->sock, "huh? usage: client_del_key \n"); + return 0; + } else { + sock_send_string (c->sock, "huh? Too many parameters...\n"); + return 0; + } + } + + keys = argv[1] ; + debug(RPT_DEBUG, "client_del_key: Deleting key(s) %s from client_keys", keys); + + if (c->client_keys) { + /* Client has keys, remove keys from the list + * NOTE: We let malloc/realloc remember the length + * of the allocated storage. If keys are later + * added, realloc (in add_key above) will make + * sure there is enough space at c->data->client_keys + */ + char * from ; + char * to ; + + to = from = c->client_keys ; + while( *from ) { + /* Is this key to be deleted from the list?*/ + if( strchr( keys, *from ) ) { + /* Yes, skip it*/ + ++from ; + } else { + /* No, save it*/ + *to++ = *from++ ; + } + } + } + + sock_send_string(c->sock, "success\n"); + + return 0; +} + +/*************************************************************************** + * Toggles the backlight, if enabled. + * + * usage: backlight + */ +int +backlight_func (Client * c, int argc, char **argv) +{ + if (!c->ack) + return 1; + + if (argc != 2) { + switch (argc) { + case 1: + sock_send_string (c->sock, "huh? usage: backlight \n"); + break; + default: + sock_send_string (c->sock, "huh? Too many parameters...\n"); + break; + } + return 0; + } + + debug (RPT_DEBUG, "backlight(%s)", argv[1]); + + + //backlight = (backlight && 1); /* only preserves ON/OFF bit*/ + + if (strcmp ("on", argv[1]) == 0) { + c->backlight = BACKLIGHT_ON; + + } else if (strcmp ("off", argv[1]) == 0) { + c->backlight = BACKLIGHT_OFF; + + } else if (strcmp ("toggle", argv[1]) == 0) { + if (c->backlight == BACKLIGHT_ON) + c->backlight = BACKLIGHT_OFF; + else if (c->backlight == BACKLIGHT_OFF) + c->backlight = BACKLIGHT_ON; + + } else if (strcmp ("blink", argv[1]) == 0) { + c->backlight |= BACKLIGHT_BLINK; + + } else if (strcmp ("flash", argv[1]) == 0) { + c->backlight |= BACKLIGHT_FLASH; + } + + sock_send_string(c->sock, "success\n"); + + return 0; + +} + +/**************************************************************************** + * info_func + * + * usage: info + */ +int +info_func (Client * c, int argc, char **argv) +{ + char str[1024]; + + if (argc > 1) { + sock_send_string (c->sock, "huh? Extra arguments ignored...\n"); + } + + memset(str, '\0', sizeof(str)); + snprintf (str, sizeof(str)-1, (char*) drivers_get_info()); + + sock_send_string (c->sock, str); + + return 0; +} + diff --git a/server/commands/client_commands.h b/server/commands/client_commands.h new file mode 100644 index 0000000..e07fd79 --- /dev/null +++ b/server/commands/client_commands.h @@ -0,0 +1,22 @@ +/* + * client_commands.h + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn + * + */ + +#ifndef COMMANDS_CLIENT_H +#define COMMANDS_CLIENT_H + +int hello_func (Client * c, int argc, char **argv); +int client_set_func (Client * c, int argc, char **argv); +int client_add_key_func (Client * c, int argc, char **argv); +int client_del_key_func (Client * c, int argc, char **argv); +int backlight_func (Client * c, int argc, char **argv); + +#endif \ No newline at end of file diff --git a/server/commands/command_list.c b/server/commands/command_list.c new file mode 100644 index 0000000..05bed6a --- /dev/null +++ b/server/commands/command_list.c @@ -0,0 +1,55 @@ +/* + * commands/command_list.c + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * + * + * This contains definitions for all the functions which clients can run. + * The functions here are to be called only from parse.c's interpreter. + * + * The client's available function set is defined here, as is the syntax + * for each command. + * + */ + +#include "command_list.h" +#include "server_commands.h" +#include "client_commands.h" +#include "screen_commands.h" +#include "widget_commands.h" +#include "menu_commands.h" + +#include + +client_function commands[] = { + {"test_func", test_func_func}, + {"hello", hello_func}, + {"client_set", client_set_func}, + {"client_add_key", client_add_key_func}, + {"client_del_key", client_del_key_func}, +/* {"screen_add_key", screen_add_key_func}, */ +/* {"screen_del_key", screen_del_key_func}, */ + {"screen_add", screen_add_func}, + {"screen_del", screen_del_func}, + {"screen_set", screen_set_func}, + {"widget_add", widget_add_func}, + {"widget_del", widget_del_func}, + {"widget_set", widget_set_func}, + {"menu_add", menu_add_func}, + {"menu_del", menu_del_func}, + {"menu_set", menu_set_func}, + {"menu_add_item", menu_add_item_func}, + {"menu_del_item", menu_del_item_func}, + {"menu_set_item", menu_set_item_func}, + /* Misc stuff...*/ + {"backlight", backlight_func}, + {"output", output_func}, + {"noop", noop_func}, + {"info", info_func}, + {"sleep", sleep_func}, + {NULL, NULL}, +}; diff --git a/server/commands/command_list.h b/server/commands/command_list.h new file mode 100644 index 0000000..75f1688 --- /dev/null +++ b/server/commands/command_list.h @@ -0,0 +1,31 @@ +/* + * commands/command_list.h + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * + */ + +#ifndef COMMANDS_COMMAND_LIST_H +#define COMMANDS_COMMAND_LIST_H + +#include "../client.h" + +/* + The function list for clients is stored in a table, and the items each + point to a function to call, defined below. + */ + +typedef struct client_function { + char *keyword; + int (*function) (Client * c, int argc, char **argv); +} client_function; + +/* FIXME? Do these really need to be visible from other sources?*/ + +extern client_function commands[]; + +#endif diff --git a/server/commands/menu_commands.c b/server/commands/menu_commands.c new file mode 100644 index 0000000..bc80c67 --- /dev/null +++ b/server/commands/menu_commands.c @@ -0,0 +1,139 @@ +/* + * menu_commands.c + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn + * + * + * This contains definitions for all the functions which clients can run. + * The functions here are to be called only from parse.c's interpreter. + * + * The client's available function set is defined here, as is the syntax + * for each command. + * + * This particular file defines actions concerning client supplied menus. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "shared/report.h" +#include "shared/sockets.h" + +#include "client.h" + +/************************************************************* + * Adds a menu to the client; handled by the server... + * + * usage: menu_add ...? + */ +int +menu_add_func (Client * c, int argc, char **argv) +{ + + if (!c->ack) + return 1; + + sock_send_string (c->sock, "huh? Not implemented yet.\n"); + + return 0; +} + +/**************************************************************** + * Removes a client's menu and all contents from the server + * + * usage: menu_del ...? + */ +int +menu_del_func (Client * c, int argc, char **argv) +{ + + if (!c->ack) + return 1; + + sock_send_string (c->sock, "huh? Not implemented yet.\n"); + + return 0; +} + +/*********************************************************************** + * Sets info about a menu, but not its items + * + * For example, should the menu be top-level, or buried somewhere? + * + * usage: menu_set ...? + */ +int +menu_set_func (Client * c, int argc, char **argv) +{ + + if (!c->ack) + return 1; + + sock_send_string (c->sock, "huh? Not implemented yet.\n"); + + return 0; +} + +/************************************************************************* + * Adds an item to a menu + * + * usage: menu_add_item ...? + */ +int +menu_add_item_func (Client * c, int argc, char **argv) +{ + + if (!c->ack) + return 1; + + sock_send_string (c->sock, "huh? Not implemented yet.\n"); + + return 0; +} + +/************************************************************************* + * Deletes an item from a menu + * + + usage: menu_del_item ...? + */ +int +menu_del_item_func (Client * c, int argc, char **argv) +{ + + if (!c->ack) + return 1; + + sock_send_string (c->sock, "huh? Not implemented yet.\n"); + + return 0; +} + +/************************************************************************** + * Sets the info about a menu item + * + * For example, text displayed, widget type, value, etc... + * + * usage: menu_set_item ...? + */ +int +menu_set_item_func (Client * c, int argc, char **argv) +{ + + if (!c->ack) + return 1; + + sock_send_string (c->sock, "huh? Not implemented yet.\n"); + + return 0; +} + diff --git a/server/commands/menu_commands.h b/server/commands/menu_commands.h new file mode 100644 index 0000000..6b26300 --- /dev/null +++ b/server/commands/menu_commands.h @@ -0,0 +1,23 @@ +/* + * menu_commands.h + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn + * + */ + +#ifndef COMMANDS_MENU_H +#define COMMANDS_MENU_H + +int menu_add_func (Client * c, int argc, char **argv); +int menu_del_func (Client * c, int argc, char **argv); +int menu_set_func (Client * c, int argc, char **argv); +int menu_add_item_func (Client * c, int argc, char **argv); +int menu_del_item_func (Client * c, int argc, char **argv); +int menu_set_item_func (Client * c, int argc, char **argv); + +#endif \ No newline at end of file diff --git a/server/commands/screen_commands.c b/server/commands/screen_commands.c new file mode 100644 index 0000000..37d99b7 --- /dev/null +++ b/server/commands/screen_commands.c @@ -0,0 +1,542 @@ +/* + * screens_commands.c + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn + * + * + * This contains definitions for all the functions which clients can run. + * The functions here are to be called only from parse.c's interpreter. + * + * The client's available function set is defined here, as is the syntax + * for each command. + * + * This particular file defines actions concerning screens. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "shared/report.h" +#include "shared/sockets.h" + +#include "client.h" +#include "screen.h" +#include "render.h" + +/*************************************************************** + * Tells the server the client has another screen to offer + * + * usage: screen_add + */ +int +screen_add_func (Client * c, int argc, char **argv) +{ + int err = 0; + Screen * s; + + if (!c->ack) + return 1; + + if (argc != 2) { + switch (argc) { + case 1: + sock_send_string (c->sock, "huh? Usage: screen_add \n"); + break; + default: + sock_send_string (c->sock, "huh? Too many parameters...\n"); + break; + } + return 0; + } + + debug(RPT_DEBUG, "screen_add: Adding screen %s", argv[1]); + + s = client_find_screen (c, argv[1]); + if (s) { + sock_send_string(c->sock, "huh? Screen already exists\n"); + return 0; + } + + s = screen_create (argv[1], c); + if (!s) { + report(RPT_ERR, "screen_add_func: Error creating screen"); + sock_send_string (c->sock, "huh? failed to create screen\n"); + return 0; + } + + err = client_add_screen (c, s); + + if (err == 0) { + sock_send_string(c->sock, "success\n"); + } else { + report(RPT_WARNING, "screen_add_func: Error adding screen"); + sock_send_string (c->sock, "huh? Failed to add screen\n"); + } + report(RPT_NOTICE, "added a screen (%s) to the display", s->id); + return 0; +} + +/**************************************************************** + * Client requests that the server forget about a screen + * + * usage: screen_del + */ +int +screen_del_func (Client * c, int argc, char **argv) +{ + int err = 0; + Screen * s; + + if (!c->ack) + return 1; + + if (argc != 2) { + if (argc == 1) + sock_send_string (c->sock, "huh? Usage: screen_del \n"); + else + sock_send_string (c->sock, "huh? Too many parameters...\n"); + return 0; + } + + debug (RPT_DEBUG, "screen_del: Deleting screen %s", argv[1]); + + s = client_find_screen (c, argv[1]); + if (!s) { + sock_send_string(c->sock, "huh? Unknown screen id\n"); + return 0; + } + + err = client_remove_screen (c, s); + if ( err == 0 ) + sock_send_string(c->sock, "success\n"); + else if (err < 0) { + report(RPT_WARNING, "screen_del_func: Error removing screen"); + sock_send_string(c->sock, "huh? Failed to remove screen\n"); + } else + sock_send_string (c->sock, "huh? Unknown screen id\n"); + + report(RPT_NOTICE, "removed a screen (%s) from the display", argv[1]); + return 0; +} + +/*************************************************************** + * Configures info about a particular screen, such as its + * name, priority, or duration + * + * usage: screen_set [ -priority ] [ -name ] [ -duration ] + * [ -wid ] [ -hgt ] [ -heartbeat ] [ -cursor ] + * [ -cursor_x ] [ -cursor_y ] + */ +int +screen_set_func (Client * c, int argc, char **argv) +{ + int i; + + int number; + char *id; + Screen * s; + + if (!c->ack) + return 1; + + if (argc == 1) { + sock_send_string (c->sock, "huh? Usage: screen_set [ -priority ] [ -name ] [ -duration ] [ -wid ] [ -hgt ] [ -heartbeat ]\n"); + return 0; + } else if (argc == 2) { + sock_send_string (c->sock, "huh? What do you want to set?\n"); + return 0; + } + + id = argv[1]; + s = client_find_screen (c, id); + if (!s) { + sock_send_string (c->sock, "huh? Unknown screen id\n"); + return 0; + } + /* Handle the rest of the parameters*/ + for (i = 2; i < argc; i++) { + char *p; + + /* The following code allows us to use p for comparisions, + * ignoring a (valid) single leading '-' - reduces string comparisons + * by half. + */ + + p = argv[i]; + if (*p == '-') + p++; + + /* Handle the "name" parameter*/ + if (strcmp (p, "name") == 0) { + if (argc > i + 1) { + i++; + debug (RPT_DEBUG, "screen_set: name=\"%s\"", argv[i]); + + /* set the name...*/ + if (s->name) + free (s->name); + s->name = strdup (argv[i]); + sock_send_string(c->sock, "success\n"); + } else { + sock_send_string (c->sock, "huh? -name requires a parameter\n"); + } + } + /* Handle the "priority" parameter*/ + else if (strcmp (p, "priority") == 0) { + if (argc > i + 1) { + i++; + debug (RPT_DEBUG, "screen_set: priority=\"%s\"", argv[i]); + + /* set the priority...*/ + number = atoi (argv[i]); + if (number > 0) + s->priority = number; + sock_send_string(c->sock, "success\n"); + } else { + sock_send_string (c->sock, "huh? -priority requires a parameter\n"); + } + } + /* Handle the "duration" parameter*/ + else if (strcmp (p, "duration") == 0) { + if (argc > i + 1) { + i++; + debug (RPT_DEBUG, "screen_set: duration=\"%s\"", argv[i]); + + /* set the duration...*/ + number = atoi (argv[i]); + if (number > 0) + s->duration = number; + sock_send_string(c->sock, "success\n"); + } else { + sock_send_string (c->sock, "huh? -duration requires a parameter\n"); + } + } + /* Handle the "heartbeat" parameter*/ + else if (strcmp (p, "heartbeat") == 0) { + if (argc > i + 1) { + i++; + debug (RPT_DEBUG, "screen_set: heartbeat=\"%s\"", argv[i]); + + /* set the heartbeat type...*/ + if (0 == strcmp (argv[i], "on")) + s->heartbeat = HEARTBEAT_ON; + else if (0 == strcmp (argv[i], "off")) + s->heartbeat = HEARTBEAT_OFF; + else if (0 == strcmp (argv[i], "open")) + s->heartbeat = HEARTBEAT_OPEN; + sock_send_string(c->sock, "success\n"); + } else { + sock_send_string (c->sock, "huh? -heartbeat requires a parameter\n"); + } + } + /* Handle the "wid" parameter*/ + else if (strcmp (p, "wid") == 0) { + if (argc > i + 1) { + i++; + debug (RPT_DEBUG, "screen_set: wid=\"%s\"", argv[i]); + + /* set the duration...*/ + number = atoi (argv[i]); + if (number > 0) + s->width = number; + sock_send_string(c->sock, "success\n"); + } else { + sock_send_string (c->sock, "huh? -wid requires a parameter\n"); + } + + } + /* Handle the "hgt" parameter*/ + else if (strcmp (p, "hgt") == 0) { + if (argc > i + 1) { + i++; + debug (RPT_DEBUG, "screen_set: hgt=\"%s\"", argv[i]); + + /* set the duration...*/ + number = atoi (argv[i]); + if (number > 0) + s->height = number; + sock_send_string(c->sock, "success\n"); + } else { + sock_send_string (c->sock, "huh? -hgt requires a parameter\n"); + } + } + /* Handle the "timeout" parameter*/ + else if (strcmp (p, "timeout") == 0) { + if (argc > i + 1) { + i++; + debug (RPT_DEBUG, "screen_set: timeout=\"%s\"", argv[i]); + /* set the duration...*/ + number = atoi (argv[i]); + /* Add the timeout value (count of TIME_UNITS) + * to struct, TIME_UNIT is 1/8th of a second + */ + if (number > 0) { + s->timeout = number; + report(RPT_NOTICE, "Timeout set."); + } + sock_send_string(c->sock, "success\n"); + } else { + sock_send_string (c->sock, "huh? -timeout requires a parameter\n"); + } + } + /* Handle the "backlight" parameter*/ + else if (strcmp (p, "backlight") == 0) { + if (argc > i + 1) { + i++; + debug (RPT_DEBUG, "screen_set: backlight=\"%s\"", argv[i]); + /* set the backlight status based on what the client has set*/ + switch(c->backlight) { + case BACKLIGHT_OPEN: + if (strcmp ("on", argv[i]) == 0) + s->backlight = BACKLIGHT_ON; + + if (strcmp ("off", argv[i]) == 0) + s->backlight = BACKLIGHT_OFF; + + if (strcmp ("toggle", argv[i]) == 0) { + if (s->backlight == BACKLIGHT_ON) + s->backlight = BACKLIGHT_OFF; + else if (s-backlight == BACKLIGHT_OFF) + s->backlight = BACKLIGHT_ON; + } + + if (strcmp ("blink", argv[i]) == 0) + s->backlight |= BACKLIGHT_BLINK; + + if (strcmp ("flash", argv[i]) == 0) + s->backlight |= BACKLIGHT_FLASH; + break; + default: + /*If the backlight is not OPEN then inherit its state*/ + s->backlight = c->backlight; + break; + } + sock_send_string(c->sock, "success\n"); + } else { + sock_send_string (c->sock, "huh? -backlight requires a parameter\n"); + } + } + /* Handle the "cursor" parameter */ + else if (strcmp (p, "cursor") == 0) { + if (argc > i + 1) { + i++; + debug (RPT_DEBUG, "screen_set: cursor=\"%s\"", argv[i]); + + /* set the heartbeat type...*/ + if (0 == strcmp (argv[i], "off")) + s->heartbeat = CURSOR_OFF; + if (0 == strcmp (argv[i], "on")) + s->cursor = CURSOR_DEFAULT_ON; + if (0 == strcmp (argv[i], "under")) + s->cursor = CURSOR_UNDER; + if (0 == strcmp (argv[i], "block")) + s->cursor = CURSOR_BLOCK; + sock_send_string(c->sock, "success\n"); + } else { + sock_send_string (c->sock, "huh? -cursor requires a parameter\n"); + } + } + /* Handle the "cursor_x" parameter */ + else if (strcmp (p, "cursor_x") == 0) { + if (argc > i + 1) { + i++; + debug (RPT_DEBUG, "screen_set: cursor_x=\"%s\"", argv[i]); + + /* set the position...*/ + number = atoi (argv[i]); + if (number > 0 && number <= s->width) { + s->cursor_x = number; + sock_send_string(c->sock, "success\n"); + } + else { + sock_send_string(c->sock, "huh? Cursor position outside screen\n"); + } + } else { + sock_send_string (c->sock, "huh? -cursor_x requires a parameter\n"); + } + } + /* Handle the "cursor_y" parameter */ + else if (strcmp (p, "cursor_y") == 0) { + if (argc > i + 1) { + i++; + debug (RPT_DEBUG, "screen_set: cursor_y=\"%s\"", argv[i]); + + /* set the position...*/ + number = atoi (argv[i]); + if (number > 0 && number <= s->height) { + s->cursor_y = number; + sock_send_string(c->sock, "success\n"); + } + else { + sock_send_string(c->sock, "huh? Cursor position outside screen\n"); + } + } else { + sock_send_string (c->sock, "huh? -cursor_y requires a parameter\n"); + } + } + + else sock_send_string (c->sock, "huh? invalid parameter\n"); + }/* done checking argv*/ + return 0; +} + +/********************************************************************** + * Tells the server the client would like to accept keypresses + * of a particular type when the given screen is active on the display + * + * screen_add_key + */ +int +screen_add_key_func (Client * c, int argc, char **argv) +{ + /*widget * w ;*/ /* Keys are stored on a WID_KEYS widget */ + Screen * s ; /* Attached to a specific screen */ + char * id ; /* Screen ID */ + char * keys ; /* Keys wanted */ + + if (!c->ack) + return 1; + + if (argc != 3) { + switch (argc) { + case 1: + sock_send_string (c->sock, "huh? Usage: screen_add_key \n"); + break; + case 2: + sock_send_string (c->sock, "huh? You must specify a key list\n"); + break; + default: + sock_send_string (c->sock, "huh? Too many parameters...\n"); + break; + } + return 0; + } + + id = argv[1]; + keys = argv[2]; + debug(RPT_DEBUG, "screen_add_key: Adding key(s) %s to screen %s", keys, id); + + /* Find the screen*/ + s = client_find_screen (c, id); + if (!s) { + sock_send_string (c->sock, "huh? Unknown screen id\n"); + return 0; + } + + /* Save the keys*/ + if (!s->keys) { + /* Save supplied key list*/ + s->keys = strdup( keys ); + } else { + /* Add supplied keys to existing list + * NOTE: There could be duplicates in the resulting list + * That's OK, it's the existence of the key in the list + * that's important. We'll be more careful in the delete + * key function. + */ + char * new_keys ; + new_keys = realloc( s->keys, strlen(s->keys) + strlen(keys) +1 ); + if (new_keys) { + strcpy (new_keys, s->keys); + strcat (new_keys, keys ); + free (s->keys); + s->keys = new_keys; + } else { + report (RPT_WARNING, "screen_add_key: Allocation error"); + sock_send_string(c->sock, "huh? Could not add new keys\n"); + return 0; + } + } + + if (!s->keys) { + sock_send_string(c->sock, "huh? failed\n"); + } else + sock_send_string(c->sock, "success\n"); + + return 0; +} + +/************************************************************************* + * Tells the server the client would NOT like to accept keypresses + * of a particular type when the given screen is active on the display + * + * usage: screen_del_key + */ +int +screen_del_key_func (Client * c, int argc, char **argv) +{ + /*widget * w ;*/ /* Keys are stored on a WID_KEYS widget */ + Screen * s ; /* Attached to a specific screen */ + char * id ; /* Screen ID */ + char * keys ; /* Keys wanted */ + + if (!c->ack) + return 1; + + if (argc != 3) { + switch (argc) { + case 1: + sock_send_string (c->sock, "huh? Usage: screen_del_key \n"); + break; + case 2: + sock_send_string (c->sock, "huh? You must specify a key list\n"); + break; + default: + sock_send_string (c->sock, "huh? Too many parameters\n"); + break; + } + return 0; + } + + id = argv[1] ; + keys = argv[2] ; + debug(RPT_DEBUG, "screen_del_key: Deleting key(s) %s from screen %s", keys, id); + + /* Find the screen*/ + s = client_find_screen (c, id); + + if (!s) { + sock_send_string (c->sock, "huh? Unknown screen id\n"); + return 0; + } + + /* Do we have keys?*/ + if (s->keys) { + /* Have keys, remove keys from the list + * NOTE: We let malloc/realloc remember the length + * of the allocated storage. If keys are later + * added, realloc (in add_key above) will make + * sure there is enough space at s->keys + */ + char * from ; + char * to ; + + to = from = s->keys ; + while( *from ) { + /* Is this key to be deleted from the list?*/ + if( strchr( keys, *from ) ) { + /* Yes, skip it*/ + ++from ; + } else { + /* No, save it*/ + *to++ = *from++ ; + } + } + to = '\0'; /* terminates the new keys string...*/ + } + + sock_send_string(c->sock, "success\n"); + + return 0; +} + diff --git a/server/commands/screen_commands.h b/server/commands/screen_commands.h new file mode 100644 index 0000000..8c641a9 --- /dev/null +++ b/server/commands/screen_commands.h @@ -0,0 +1,22 @@ +/* + * screen_commands.h + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn + * + */ + +#ifndef COMMANDS_SCREEN_H +#define COMMANDS_SCREEN_H + +int screen_add_func (Client * c, int argc, char **argv); +int screen_del_func (Client * c, int argc, char **argv); +int screen_set_func (Client * c, int argc, char **argv); +int screen_add_key_func (Client * c, int argc, char **argv); +int screen_del_key_func (Client * c, int argc, char **argv); + +#endif \ No newline at end of file diff --git a/server/commands/server_commands.c b/server/commands/server_commands.c new file mode 100644 index 0000000..b0aa2ac --- /dev/null +++ b/server/commands/server_commands.c @@ -0,0 +1,210 @@ +/* + * server_commands.c + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn + * + * + * This contains definitions for all the functions which clients can run. + * The functions here are to be called only from parse.c's interpreter. + * + * The client's available function set is defined here, as is the syntax + * for each command. + * + * This particular file defines actions concerning the server settings. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "shared/report.h" +#include "shared/sockets.h" + +#include "client.h" +#include "render.h" + +/**************************************************************************** + * Sets the state of the output port (such as on MtxOrb LCDs) + * + * usage: output + */ +#define ALL_OUTPUTS_ON -1 +#define ALL_OUTPUTS_OFF 0 + +int +output_func (Client * c, int argc, char **argv) +{ + /*int rc = 0;*/ + char str[128]; + + if (argc != 2) { + if (argc == 1) + sock_send_string (c->sock, "huh? usage: output -- num may be decimal, hex, or octal\n"); + else + sock_send_string (c->sock, "huh? Too many parameters...\n"); + return 0; + } + + if (0 == strcmp (argv[1], "on")) + output_state = ALL_OUTPUTS_ON; + else if (0 == strcmp (argv[1], "off")) + output_state = ALL_OUTPUTS_OFF; + else { + long out; + char *endptr, *p; + + /* Note that there is no valid range set for + * output_state; thus a value in the 12 digits + * is not considered out of range. + */ + + errno = 0; + + /* errno is set here, because if strtol does not result in + * ERANGE (out of range error) it will not set errno (!). + * At least, this is the case with glibc 2.1.3 ... + */ + + p = argv[1]; + out = strtol(p, &endptr, 0); + + /* From the man page for strtol(3) + * + * In particular, if *nptr is not `\0' but **endptr is + * `\0' on return, the entire string is valid. + * + * In this case, argv[1] is *nptr, and &endptr is **endptr. + */ + + if (errno) { + int space; + + strcat(str, "huh? number argument: "); + space = sizeof(str) - 3 - strlen(str); + + strncat(str, strerror(errno), space); + strcat(str, "\n"); + + sock_send_string (c->sock, str); + return 0; + } else if (*p != '\0' && *endptr == '\0') { + output_state = out; + } else { + sock_send_string (c->sock, "huh? invalid parameter...\n"); + return 0; + } + } + + sock_send_string(c->sock, "success\n"); + + /* Makes sense to me to set the output immediately; + * however, the outputs are currently set in + * draw_screen(screen * s, int timer) + * Whatever for? */ + + /* drivers_output (output_state); */ + + report(RPT_NOTICE, "output states changed"); + return 0; +} + +/******************************************************************************* + * sleep_func + * + * usage: sleep + */ +int +sleep_func (Client * c, int argc, char **argv) +{ + int secs; + long out; + char *endptr, *p; + char str[120]; + +#define MAX_SECS 60 +#define MIN_SECS 1 + + if (argc != 2) { + if (argc == 1) + sock_send_string (c->sock, "huh? usage: sleep \n"); + else + sock_send_string (c->sock, "huh? Too many parameters...\n"); + return 0; + } + + errno = 0; + + /* errno is set here, because if strtol does not result in + * ERANGE (out of range error) it will not set errno (!). + * At least, this is the case with glibc 2.1.3 ... + */ + + p = argv[1]; + out = strtol(p, &endptr, 0); + + /* From the man page for strtol(3) + * + * In particular, if *nptr is not `\0' but **endptr is + * `\0' on return, the entire string is valid. + * + * In this case, argv[1] is *nptr, and &endptr is **endptr. + */ + + if (errno) { + int space; + + strcat(str, "huh? number argument: "); + space = sizeof(str) - 3 - strlen(str); + + strncat(str, strerror(errno), space); + strcat(str, "\n"); + + sock_send_string (c->sock, str); + return 0; + } else if (*p != '\0' && *endptr == '\0') { + secs = out; + out = out > MAX_SECS ? MAX_SECS : out; + out = out < MIN_SECS ? MIN_SECS : out; + } else { + sock_send_string (c->sock, "huh? invalid parameter...\n"); + return 0; + } + + /* Repeat until no more remains - should normally be zero + * on exit the first time...*/ + snprintf(str, sizeof(str), "sleeping %d seconds\n", secs); + sock_send_string (c->sock, str); + + /* whoops.... if this takes place as planned, ALL screens + * will "freeze" for the alloted time... + * + * while ((secs = sleep(secs)) > 0) + */ ; + + sock_send_string (c->sock, "huh? ignored (not fully implemented)\n"); + return 0; +} + +/***************************************************************************** + * Does nothing, returns "noop complete" message + * + * This is useful for shell scripts or programs that want to talk + * with LCDproc and not get deadlocked. Send a noop after each + * command and look for the "noop complete" message. + */ +int +noop_func (Client * c, int argc, char **argv) +{ + sock_send_string (c->sock, "noop complete\n"); + return 0; +} + diff --git a/server/commands/server_commands.h b/server/commands/server_commands.h new file mode 100644 index 0000000..7fa61e8 --- /dev/null +++ b/server/commands/server_commands.h @@ -0,0 +1,22 @@ +/* + * server_commands.h + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn + * + */ + +#ifndef COMMANDS_SERVER_H +#define COMMANDS_SERVER_H + +int output_func (Client * c, int argc, char **argv); +int test_func_func (Client * c, int argc, char **argv); +int noop_func (Client * c, int argc, char **argv); +int info_func (Client * c, int argc, char **argv); +int sleep_func (Client * c, int argc, char **argv); + +#endif diff --git a/server/commands/widget_commands.c b/server/commands/widget_commands.c new file mode 100644 index 0000000..8728c17 --- /dev/null +++ b/server/commands/widget_commands.c @@ -0,0 +1,465 @@ +/* + * widget_commands.c + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn + * + * + * This contains definitions for all the functions which clients can run. + * The functions here are to be called only from parse.c's interpreter. + * + * The client's available function set is defined here, as is the syntax + * for each command. + * + * This particular file defines actions concerning widgets. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "shared/report.h" +#include "shared/sockets.h" + +#include "client.h" +#include "screen.h" +#include "widget.h" + + +/************************************************************************* + * Adds a widget to a screen, but doesn't give it a value + * + * usage: widget_add [ -in ] + */ +int +widget_add_func (Client * c, int argc, char **argv) +{ + int err; + char *sid; + char *wid; + WidgetType wtype; + Screen * s; + Widget * w; + + if (!c->ack) + return 1; + + if ((argc < 4) || (argc > 6)) { + sock_send_string (c->sock, "huh? Usage: widget_add [ -in ]\n"); + return 0; + } + + sid = argv[1]; + wid = argv[2]; + + s = client_find_screen (c, sid); + if (!s) { + sock_send_string (c->sock, "huh? Invalid screen id\n"); + return 0; + } + + /* Find widget type */ + wtype = widget_typename_to_type (argv[3]); + if (wtype == WID_NONE) { + sock_send_string (c->sock, "huh? Invalid widget type\n"); + return 0; + } + + /* Check for additional flags...*/ + if (argc > 4) { + char *p; + + p = argv[4]; + if (*p == '-') + p++; + + /* Handle the "in" flag to place widgets in a container...*/ + if (strcmp (p, "in")) { + char * frame_name; + + if (argc < 6) { + sock_send_string (c->sock, "huh? Specify a frame to place widget in\n"); + return 0; + } + + /* Now we replace s with the framescreen. + * This way it will not be plaed in the normal screen + * but in the framescreen. + */ + frame_name = malloc (strlen("frame_") + strlen(argv[5]) + 1); + strcpy (frame_name, "frame_"); + strcat (frame_name, argv[5]); + s = screen_create (frame_name, c); + if (!s) { + report(RPT_WARNING, "widget_add_func: Error creating framescreen"); + sock_send_string(c->sock, "huh? Failed\n"); + return 0; + } + free (frame_name); + } + } + + /* Create the widget */ + w = widget_create (wid, wtype, s); + if (!w) { + report(RPT_WARNING, "widget_add_func: Error adding widget"); + sock_send_string(c->sock, "huh? Failed\n"); + return 0; + } + + /* Add the widget to the screen */ + err = screen_add_widget (s, w); + if (err == 0) + sock_send_string(c->sock, "success\n"); + else { + report(RPT_WARNING, "widget_add_func: Error adding widget"); + sock_send_string(c->sock, "huh? Failed\n"); + } + + return 0; +} + +/******************************************************************* + * Removes a widget from a screen, and forgets about it + * + * usage: widget_del + */ +int +widget_del_func (Client * c, int argc, char **argv) +{ + int err = 0; + + char *sid; + char *wid; + Screen * s; + Widget * w; + + if (!c->ack) + return 1; + + if (argc != 3) { + switch (argc) { + case 1: + sock_send_string (c->sock, "huh? Usage: widget_del \n"); + break; + case 2: + sock_send_string (c->sock, "huh? Specify a widget #id\n"); + break; + default: + sock_send_string (c->sock, "huh? Too many parameters...\n"); + break; + } + return 0; + } + + sid = argv[1]; + wid = argv[2]; + + debug (RPT_DEBUG, "screen_del: Deleting widget %s.%s", sid, wid); + + s = client_find_screen (c, sid); + if (!s) { + sock_send_string (c->sock, "huh? Invalid screen id\n"); + return 0; + } + + w = screen_find_widget (s, wid); + if (!w) { + sock_send_string (c->sock, "huh? Invalid widget id\n"); + return 0; + } + + err = screen_remove_widget (s, w); + if (err == 0) + sock_send_string(c->sock, "success\n"); + else { + report( RPT_WARNING, "widget_del_func: Error removing widget"); + sock_send_string(c->sock, "huh? Failed\n"); + } + + return 0; +} + +/******************************************************************** + * Configures information about a widget, such as its size, shape, + * contents, position, speed, etc... + * + * Ack! This is long! + * + * widget_set + */ +int +widget_set_func (Client * c, int argc, char **argv) +{ + int i; + char * wid; + char * sid; + + int x, y; + int left, top, right, bottom; + int length, direction; + int width, height; + int speed; + Screen * s; + Widget * w; + + if (!c->ack) + return 1; + + /* If there weren't enough parameters... + * We can't test for too many, since each widget may have a + * different number - plus, if the argument count is wrong, what ELSE + * could be wrong...? + */ + + if (argc < 4) { + sock_send_string (c->sock, "huh? Usage: widget_set \n"); + return 0; + } + + /* Find screen */ + sid = argv[1]; + s = client_find_screen (c, sid); + if (!s) { + sock_send_string (c->sock, "huh? Unknown screen id\n"); + return 0; + } + /* Find widget */ + wid = argv[2]; + w = screen_find_widget (s, wid); + if (!w) { + sock_send_string (c->sock, "huh? Unknown widget id\n"); + /* Client Debugging...*/ + { + int i; + report( RPT_WARNING, "huh? Unknown widget id (%s)", argv[2]); + for (i = 0; i < argc; i++) + report( RPT_WARNING, " %.40s ", argv[i]); + } + return 0; + } + i = 3; + switch (w->type) { + case WID_STRING: /* String takes "x y text"*/ + if (argc != i + 3) + sock_send_string (c->sock, "huh? Wrong number of arguments\n"); + else { + if ((!isdigit ((unsigned int) argv[i][0])) || + (!isdigit ((unsigned int) argv[i + 1][0]))) { + sock_send_string (c->sock, "huh? Invalid coordinates\n"); + } else /* Set all the data...*/ + { + x = atoi (argv[i]); + y = atoi (argv[i + 1]); + w->x = x; + w->y = y; + if (w->text) + free (w->text); + w->text = strdup (argv[i + 2]); + if (!w->text) { + debug (RPT_DEBUG, "Widget %s set to %s", wid, w->text); + report( RPT_WARNING, "widget_set_func: Allocation error"); + return -1; + } + debug (RPT_DEBUG, "Widget %s set to %s", wid, w->text); + sock_send_string(c->sock, "success\n"); + } + } + break; + case WID_HBAR: /* Hbar takes "x y length"*/ + if (argc != i + 3) + sock_send_string (c->sock, "huh? Wrong number of arguments\n"); + else { + if ((!isdigit ((unsigned int) argv[i][0])) || + (!isdigit ((unsigned int) argv[i + 1][0]))) { + sock_send_string (c->sock, "huh? Invalid coordinates\n"); + } else { + x = atoi (argv[i]); + y = atoi (argv[i + 1]); + length = atoi (argv[i + 2]); + w->x = x; + w->y = y; + w->length = length; + } + debug (RPT_DEBUG, "Widget %s set to %i", wid, w->length); + sock_send_string(c->sock, "success\n"); + } + break; + case WID_VBAR: /* Vbar takes "x y length"*/ + if (argc != i + 3) + sock_send_string (c->sock, "huh? Wrong number of arguments\n"); + else { + if ((!isdigit ((unsigned int) argv[i][0])) || + (!isdigit ((unsigned int) argv[i + 1][0]))) { + sock_send_string (c->sock, "huh? Invalid coordinates\n"); + } else { + x = atoi (argv[i]); + y = atoi (argv[i + 1]); + length = atoi (argv[i + 2]); + w->x = x; + w->y = y; + w->length = length; + } + debug (RPT_DEBUG, "Widget %s set to %i", wid, w->length); + sock_send_string(c->sock, "success\n"); + } + break; + case WID_ICON: /* Icon takes "x y binary_data"*/ + if (argc != i + 3) + sock_send_string (c->sock, "huh? Wrong number of arguments\n"); + else { + if ((!isdigit ((unsigned int) argv[i][0])) || + (!isdigit ((unsigned int) argv[i + 1][0]))) { + sock_send_string (c->sock, "huh? Invalid coordinates\n"); + } else { + x = atoi (argv[i]); + y = atoi (argv[i + 1]); + w->x = x; + w->y = y; + /* TODO: Parse binary data and copy it to widget's data...*/ + } + } + sock_send_string (c->sock, "huh? Widget type not yet implemented\n"); + break; + case WID_TITLE: /* title takes "text"*/ + if (argc != i + 1) + sock_send_string (c->sock, "huh? Wrong number of arguments\n"); + else { + if (w->text) + free (w->text); + w->text = strdup (argv[i]); + if (!w->text) { + report( RPT_WARNING, "widget_set_func: Allocation error"); + return -1; + } + debug (RPT_DEBUG, "Widget %s set to %s", wid, w->text); + sock_send_string(c->sock, "success\n"); + } + break; + case WID_SCROLLER: /* Scroller takes "left top right bottom direction speed text"*/ + if (argc != i + 7) { + sock_send_string (c->sock, "huh? Wrong number of arguments\n"); + } else { + if ((!isdigit ((unsigned int) argv[i][0])) || + (!isdigit ((unsigned int) argv[i + 1][0])) || + (!isdigit ((unsigned int) argv[i + 2][0])) || + (!isdigit ((unsigned int) argv[i + 3][0]))) { + sock_send_string (c->sock, "huh? Invalid coordinates\n"); + } else { + left = atoi (argv[i]); + /*debug("left: %d",left);*/ + top = atoi (argv[i + 1]); + /*debug("top: %d",top);*/ + right = atoi (argv[i + 2]); + /*debug("right: %d",right);*/ + bottom = atoi (argv[i + 3]); + /*debug("bottom: %d",bottom);*/ + direction = (int) (argv[i + 4][0]); + /*debug("dir: %c",(char)direction);*/ + speed = atoi (argv[i + 5]); + /*debug("speed: %d",speed);*/ + /* Direction must be v or h*/ + if (((char) direction != 'h') && ((char) direction != 'v')) { + sock_send_string (c->sock, "huh? Invalid direction\n"); + } else { + w->left = left; + w->top = top; + w->right = right; + w->bottom = bottom; + w->length = direction; + w->speed = speed; + if (w->text) + free (w->text); + w->text = strdup (argv[i + 6]); + if (!w->text) { + sock_send_string(c->sock, "huh? Failed\n"); + report( RPT_WARNING, "widget_set_func: Allocation error"); + return -1; + } + debug (RPT_DEBUG, "Widget %s set to %s", wid, w->text); + sock_send_string(c->sock, "success\n"); + } + } + } + break; + case WID_FRAME: /* Frame takes "left top right bottom wid hgt direction speed"*/ + if (argc != i + 8) { + sock_send_string (c->sock, "huh? Wrong number of arguments\n"); + } else { + if ((!isdigit ((unsigned int) argv[i][0])) || + (!isdigit ((unsigned int) argv[i + 1][0])) || + (!isdigit ((unsigned int) argv[i + 2][0])) || + (!isdigit ((unsigned int) argv[i + 3][0])) || + (!isdigit ((unsigned int) argv[i + 4][0])) || + (!isdigit ((unsigned int) argv[i + 5][0]))) { + sock_send_string (c->sock, "huh? Invalid coordinates\n"); + } else { + left = atoi (argv[i]); + /*debug("left: %d",left);*/ + top = atoi (argv[i + 1]); + /*debug("top: %d",top);*/ + right = atoi (argv[i + 2]); + /*debug("right: %d",right);*/ + bottom = atoi (argv[i + 3]); + /*debug("bottom: %d",bottom);*/ + width = atoi (argv[i + 4]); + /*debug("right: %d",right);*/ + height = atoi (argv[i + 5]); + /*debug("bottom: %d",bottom);*/ + direction = (int) (argv[i + 6][0]); + /*debug("dir: %c",(char)direction);*/ + speed = atoi (argv[i + 7]); + /*debug("speed: %d",speed);*/ + /* Direction must be v or h*/ + if (((char) direction != 'h') && ((char) direction != 'v')) { + sock_send_string (c->sock, "huh? Invalid direction\n"); + } else { + w->left = left; + w->top = top; + w->right = right; + w->bottom = bottom; + w->width = width; + w->height = height; + w->length = direction; + w->speed = speed; + debug (RPT_DEBUG, "Widget %s set to (%i,%i)-(%i,%i) %ix%i", wid, left, top, right, bottom, width, height); + sock_send_string(c->sock, "success\n"); + } + } + } + break; + case WID_NUM: /* Num takes "x num"*/ + if (argc != i + 2) + sock_send_string (c->sock, "huh? Wrong number of arguments\n"); + else { + if (!isdigit ((unsigned int) argv[i][0])) { + sock_send_string (c->sock, "huh? Invalid coordinates\n"); + } else if (!isdigit ((unsigned int) argv[i + 1][0])) { + sock_send_string (c->sock, "huh? Invalid number\n"); + } else { + x = atoi (argv[i]); + y = atoi (argv[i + 1]); + w->x = x; + w->y = y; + } + debug (RPT_DEBUG, "Widget %s set to %i", wid, w->y); + sock_send_string(c->sock, "success\n"); + } + break; + case WID_NONE: + default: + sock_send_string (c->sock, "huh? Widget has no type\n"); + break; + } + + return 0; +} + diff --git a/server/commands/widget_commands.h b/server/commands/widget_commands.h new file mode 100644 index 0000000..9bf25d7 --- /dev/null +++ b/server/commands/widget_commands.h @@ -0,0 +1,20 @@ +/* + * widget_commands.h + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn + * + */ + +#ifndef COMMANDS_WIDGET_H +#define COMMANDS_WIDGET_H + +int widget_add_func (Client * c, int argc, char **argv); +int widget_del_func (Client * c, int argc, char **argv); +int widget_set_func (Client * c, int argc, char **argv); + +#endif diff --git a/server/input.c b/server/input.c index ecb719f..99ef92b 100644 --- a/server/input.c +++ b/server/input.c @@ -43,19 +43,17 @@ #include "drivers.h" -#include "client_data.h" +#include "client.h" #include "clients.h" #include "screen.h" #include "widget.h" #include "screenlist.h" -#include "menus.h" +//#include "menus.h" #include "input.h" #define KeyWanted(a,b) ((a) && strchr((a), (b))) #define CurrentScreen screenlist_current -#define FirstClient(a) (client *)LL_GetFirst(a); -#define NextClient(a) (client *)LL_GetNext(a); int server_input (int key); @@ -69,9 +67,9 @@ handle_input () { char str[15]; int key; - screen *s; - /*widget *w; */ - client *c; + Screen * s; + /*Widget * w; */ + Client * c; report (RPT_INFO, "handle_input()" ); @@ -103,7 +101,7 @@ handle_input () if (KeyWanted(s->keys, key)) { /* This screen wants this key. Tell it we got one */ snprintf(str, sizeof(str), "key %c\n", key); - sock_send_string(s->parent->sock, str); + sock_send_string(s->client->sock, str); /* Nobody else gets this key */ } @@ -114,17 +112,17 @@ handle_input () else { /* Give key to clients who want it */ - c = FirstClient(clients); + c = clients_getfirst(); while (c) { /* If the client should have this keypress... */ - if(KeyWanted(c->data->client_keys,key)) { + if(KeyWanted(c->client_keys,key)) { /* Send keypress to client */ snprintf(str, sizeof(str), "key %c\n", key); sock_send_string(c->sock, str); break; /* first come, first serve */ }; - c = NextClient(clients); + c = clients_getnext(); } /* while clients */ /* Give server a shot at all keys */ @@ -156,7 +154,8 @@ server_input (int key) break; case INPUT_MAIN_MENU_KEY: debug (RPT_DEBUG, "got the menu key!"); - server_menu (); + //server_menu (); + report (RPT_ERR, "MENU TEMPORATY DISABLED"); break; default: debug (RPT_DEBUG, "server_input: Unused key \"%c\" (%i)", (char) key, key); diff --git a/server/main.c b/server/main.c index 8330dfa..4517ce7 100644 --- a/server/main.c +++ b/server/main.c @@ -391,7 +391,7 @@ process_configfile ( char *configfile ) report( RPT_ERR, "Serverscreen can only be no, noscreen or yes" ); } } - + if( backlight == UNSET_INT ) { s = config_get_string( "server", "backlight", 0, UNSET_STR ); if( strcmp( s, "on" ) == 0 ) { @@ -526,7 +526,7 @@ init_sockets () /* Now init a bunch of required stuff...*/ - if (client_init () < 0) { + if (clients_init () < 0) { report(RPT_ERR, "Error initializing client list"); return -1; } @@ -614,7 +614,7 @@ init_screens () report(RPT_ERR, "Error initializing server screens"); return -1; } - + if (enable_server_screen == SERVER_SCREEN_NOSCREEN) { /* Display the server screen only when there are no other screens */ server_screen->priority = 256; @@ -627,7 +627,7 @@ init_screens () void do_mainloop () { - screen *s = NULL; + Screen *s = NULL; char *message=NULL; report( RPT_INFO, "do_mainloop()" ); @@ -708,7 +708,8 @@ do_mainloop () free(message); } if (s->timeout <= 0) { - screen_remove (s->parent, s->id); + client_remove_screen (s->client, s); + screen_destroy (s); if((message = malloc(256)) == NULL) report(RPT_ERR, "Error allocating message string"); else { @@ -760,7 +761,7 @@ exit_program (int val) /* Shutdown things if server start was complete */ if( serverStarted ) { - client_shutdown (); /* shutdown clients (must come first) */ + clients_shutdown (); /* shutdown clients (must come first) */ screenlist_shutdown (); /* shutdown screens (must come after client_shutdown) */ sock_close_all (); /* close all open sockets (must come after client_shutdown) */ } diff --git a/server/main.h b/server/main.h index adcb877..cfb79d0 100644 --- a/server/main.h +++ b/server/main.h @@ -17,8 +17,6 @@ #include "config.h" #endif -#include "render.h" - /* contains a few things that other parts of the program might want to know about... @@ -35,11 +33,6 @@ void exit_program (int val); /* But I plan to double the framerate soon, or make it variable...*/ /*#define TIME_UNIT (125000/2)*/ -typedef struct screen_size { - char *size; - int wid, hgt; -} screen_size; - #define DEFAULT_SCREEN_PRIORITY 128 #define DEFAULT_SCREEN_DURATION 32 #define DEFAULT_HEARTBEAT HEARTBEAT_ON diff --git a/server/menu.c b/server/menu.c index b72301d..dc68503 100644 --- a/server/menu.c +++ b/server/menu.c @@ -6,6 +6,7 @@ * COPYING file distributed with this package. * * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn * * * Handles server-supplied menus defined by a table. Read menu.h for @@ -19,6 +20,16 @@ * to handle dynamically-changing menus such as the client list. Tcl/Tk * has neat ways to do it. Hmm... * + * NEW DESCRIPTION + * + * Handles a menu and all actions that can be performed on it. + * + * Menus are similar to "pull-down" menus, but have some extra features. + * They can contain "normal" menu items, checkboxes, sliders, "movers", + * etc.. + * + * The servermenu is created from servermenu.c + * */ #include @@ -26,329 +37,205 @@ #include #include -#include "parse.h" -#include "sock.h" -#include "render.h" -#include "main.h" +#include "config.h" -#include "drivers.h" #include "menu.h" -#include "input.h" +#include "shared/report.h" +#include "drivers.h" -/* FIXME: Implement this where it is supposed to be...*/ -void -framedelay () +#include "screen.h" + + +/* Internal menu item drawing functions */ +void menu_build_menu_screen (MenuItem *item, Screen *s); +void menu_build_slider_screen (MenuItem *item, Screen *s); +void menu_build_numeric_screen (MenuItem *item, Screen *s); +void menu_build_string_screen (MenuItem *item, Screen *s); +void menu_update_menu_screen (MenuItem *item, Screen *s); +void menu_update_slider_screen (MenuItem *item, Screen *s); +void menu_update_numeric_screen (MenuItem *item, Screen *s); +void menu_update_string_screen (MenuItem *item, Screen *s); + + +MenuItem *menu_create_add_item (Menu *into_menu, int type, char *id, + EventFunc(*event_func)) { - sock_poll_clients (); - parse_all_client_messages (); + Menu *new_item; - usleep (TIME_UNIT); -} - -static void -draw_heartbeat () -{ - static int timer = 0; - - if (heartbeat) { - /* Set this to pulsate like a real heart beat... */ - /*drivers_icon (!((timer + 4) & 5), 0); */ - /*drivers_chr (display_props->width, 1, 0); */ + /* Allocate space and fill struct */ + new_item = malloc (sizeof(MenuItem)); + if (!new_item) { + report (RPT_ERR, "menu_add_new_item: Could not allocate memory"); + return NULL; } - drivers_flush (); + new_item->type = type; + new_item->id = strdup (id); + if (!new_item->id) { + report (RPT_ERR, "menu_add_new_item: Could not allocate memory"); + return NULL; + } + new_item->event_func = event_func; - timer++; - timer &= 0x0f; -} - -static int PAD = 255; - -typedef struct menu_info { - int selected; - int length; -} menu_info; - -static int draw_menu (Menu menu, menu_info * info); -static int fill_menu_info (Menu menu, menu_info * info); -static int menu_handle_action (menu_item * item); - -static int slid_func (menu_item * item); - -int -do_menu (Menu menu) -{ - menu_info info; - int key = 0; - int status = MENU_OK; - int done = 0; - - int (*func) (); - int (*readfunc) (int); - - if (!menu) - return MENU_ERROR; - - fill_menu_info (menu, &info); - - while (!done) { - /* Keep the cursor off titles... (?) */ - while (menu[info.selected].type == TYPE_TITL) { - info.selected++; - /* If the title is the last thing in the menu... */ - if (!menu[info.selected].text) - info.selected -= 2; - } - - draw_menu (menu, &info); - - /* FIXME: This should use a better keypress interface, which */ - /* FIXME: handles things according to keybindings... */ - - for (key = drivers_getkey (); key == 0; key = drivers_getkey ()) { - /* sleep for 1/8th second... */ - framedelay (); - /* do the heartbeat... */ - draw_heartbeat (); - /* Check for client input... */ - } - printf( "Received key: %c\n", key ); - - /* Handle the key according to the keybindings... */ - switch (key) { - case 'D': - done = 1; - break; - case 'B': - if (info.selected > 0) - info.selected--; - while (menu[info.selected].type == TYPE_TITL) { - if (info.selected > 0) - info.selected--; - else - break; - } - break; - case INPUT_FORWARD_KEY: - if (menu[info.selected + 1].text) - info.selected++; - break; - case INPUT_PAUSE_KEY: - switch (menu[info.selected].type) { - case TYPE_MENU: - status = do_menu (menu[info.selected].data); - break; - case TYPE_FUNC: - func = menu[info.selected].data; - if (func) - status = func (); - break; - case TYPE_CHEK: - readfunc = menu[info.selected].data; - if (readfunc) - status = readfunc (MENU_CHECK); - status &= 0xffff0000; - break; - case TYPE_SLID: - func = menu[info.selected].data; - if (func) - status = slid_func (&menu[info.selected]); - break; - default: - break; - } - - switch (status) { - case MENU_OK: - break; - case MENU_CLOSE: - return MENU_OK; - case MENU_QUIT: - return MENU_QUIT; -/* case MENU_KILL: - * return MENU_KILL; - */ - case MENU_ERROR: - return MENU_ERROR; - } - - /* status = menu_handle_action(&menu[info.selected]);*/ - /* TODO: It should now do special stuff for "mover" widgets, - * TODO: and handle the return code appropriately. - */ - break; - default: - break; - } + /* Clear the type specific data part */ + memset ( &(new_item->data), 0, sizeof(new_item->data)); + if (type == MENUITEM_MENU ) { + /* We have created a menu, create our needed data */ + new_item->data.menu.parent = into_menu; + LL_new (new_item->data.menu.contents); } - return status; - -} - -static int -draw_menu (Menu menu, menu_info * info) -{ - int i; - int x = 1, y = 1; - int top = 0, bottom = 0; - - int (*readfunc) (int); - - /* these should maybe be removed: */ - int wid = display_props->width, hgt = display_props->height; - - if (!menu) - return MENU_ERROR; - - drivers_clear (); - - /* Scroll down until the selected item is centered, if possible...*/ - top = info->selected - (hgt / 2); - if (top < 0) - top = 0; - bottom = top + hgt; - if (bottom > info->length) - bottom = info->length; - top = bottom - hgt; - if (top < 0) - top = 0; - - /* Draw all visible items...*/ - for (i = top; i < bottom; i++, y++) { - if (i == info->selected) - drivers_chr (2, y, '>'); - - switch (menu[i].type) { - case TYPE_TITL: - drivers_chr (1, y, PAD); - drivers_chr (2, y, PAD); - drivers_string (4, y, menu[i].text); - for (x = strlen (menu[i].text) + 5; x <= wid; x++) - drivers_chr (x, y, PAD); - break; - case TYPE_MENU: - drivers_string (3, y, menu[i].text); - drivers_chr (wid, y, '>'); - break; - case TYPE_FUNC: - drivers_string (3, y, menu[i].text); - break; - case TYPE_CHEK: - if (menu[i].data) { - readfunc = menu[i].data; - if (readfunc (MENU_READ)) - drivers_chr (wid, y, 'Y'); - else - drivers_chr (wid, y, 'N'); - } - drivers_string (3, y, menu[i].text); - break; - case TYPE_SLID: - drivers_string (3, y, menu[i].text); - break; - case TYPE_MOVE: - break; - default: - break; - } + if (into_menu) { + /* Add the item to the menu */ + LL_Push (into_menu->data.menu.contents, new_item); } - if (top != 0) - drivers_chr (1, 1, '^'); - if (bottom < info->length) - drivers_chr (1, hgt, 'v'); + return new_item; +} - draw_heartbeat (); - /*drivers_flush(); */ +int menu_destroy_item (Menu *menu, MenuItem *item) +{ + /* Is the item a menu ? */ + if (item->type == MENUITEM_MENU ) { + /* Check if the menu is empty */ + if ( LL_Length(item->data.menu.contents) != 0 ) { + report (RPT_ERR, "menu not empty, cannot be destroyed"); + return -1; + } + /* Destroy our menu data */ + if (item->data.menu.text) + free (item->data.menu.text); + LL_Destroy (item->data.menu.contents); + } + free (item->id); + free (item); + + /* Remove the item from the menu */ + LL_Remove (menu->data.menu.contents, item); return 0; } -static int -fill_menu_info (Menu menu, menu_info * info) +MenuItem *menu_find_item (Menu *menu, char *id) { - int i; - - info->selected = 0; - - /* count the entries in the menu*/ - for (i = 0; menu[i].text; i++); - - info->length = i; - - return 0; - + MenuItem * item; + for( item = menu_getfirst_item(menu); item; item = menu_getnext_item(menu) ) { + if ( strcmp(item->id, id) == 0 ) { + return item; + } + } + return NULL; } -static int -menu_handle_action (menu_item * item) + +/******** MENU SCREEN BUILD FUNCTIONS ********/ + +void menu_build_screen (MenuItem *item, Screen *s) { - return MENU_OK; -} + Widget * w; -static int -slid_func (menu_item * item) -{ - char str[16]; - int key = 0; - int value = 0; - int x, y = 1; - int (*readfunc) (int); - - readfunc = item->data; - - /*drivers_init_hbar (); OBSOLETE */ - - while (key != 'A' && key != 'D') { - /* Draw the title... */ - drivers_clear (); - drivers_chr (1, y, PAD); - drivers_chr (2, y, PAD); - drivers_string (4, y, item->text); - for (x = strlen (item->text) + 5; x <= display_props->width; x++) - drivers_chr (x, y, PAD); - - /* Draw the slider now...*/ - value = readfunc (MENU_READ); - if (value < 0 || value >= MENU_CLOSE) - return value; - snprintf (str, sizeof(str), "%i", value); - if (display_props->height >= 4) { - int promille; - drivers_string (8, 4, str); - value = (display_props->width * display_props->cellwidth * value / 256); - promille = (long) 100 * value / 256; - drivers_hbar (1, 3, display_props->width, promille, BAR_PATTERN_FILLED); - } else { - int promille; - drivers_string (17, 2, str); - value = ((display_props->width - 4) * display_props->cellwidth * value / 256); - promille = (long) 100 * value / 256; - drivers_hbar (1, 2, display_props->width, promille, BAR_PATTERN_FILLED); - } - /*drivers_flush(); */ - - for (key = drivers_getkey (); key == 0; key = drivers_getkey ()) { - /* do the heartbeat... */ - draw_heartbeat (); - /* sleep for 1/8th second... */ - framedelay (); - /* Check for client input... */ - } - - switch (key) { - case 'B': - value = readfunc (MENU_MINUS); - break; - case 'C': - value = readfunc (MENU_PLUS); - break; - } - - if (value >= MENU_CLOSE || value < 0 || key == 'A' || key == 'D') - return value; + if (display_props) { + /* Nothing to build if no display size is known */ + report (RPT_ERR, "menu_build_screen: display size unknown"); + return; } - return MENU_OK; + /* First remove all widgets from the screen */ + for ( w=screen_getfirst_widget(s); w; w=screen_getnext_widget(s) ) { + /* We know these widgets don't have subwidgets */ + screen_remove_widget (s, w); + widget_destroy (w); + } + + switch (item->type) { + case MENUITEM_MENU: + menu_build_menu_screen (item, s); + break; + case MENUITEM_SLIDER: + menu_build_slider_screen (item, s); + break; + case MENUITEM_NUMERIC_INPUT: + menu_build_slider_screen (item, s); + break; + case MENUITEM_STRING_INPUT: + menu_build_slider_screen (item, s); + break; + default: + report (RPT_ERR, "menu_build_screen: given menuitem cannot be active"); + return; + } + menu_update_screen (item, s); } + +void menu_build_menu_screen (MenuItem *item, Screen *s) +{ + Widget * w; + int linenr; + + for (linenr=1; linenrwidth; linenr++) { + char buf[8]; + snprintf (buf, sizeof(buf)-1, "line%d", linenr); + buf[sizeof(buf)-1] = 0; + w = widget_create (buf, WID_STRING, s); + /* (buf will be copied) */ + w->text = strdup(""); + screen_add_widget (s, w); + } +} + +void menu_build_slider_screen (MenuItem *item, Screen *s) +{ +} + +void menu_build_numeric_screen (MenuItem *item, Screen *s) +{ +} + +void menu_build_string_screen (MenuItem *item, Screen *s) +{ +} + +void menu_build_password_screen (MenuItem *item, Screen *s) +{ +} + +/******** MENU SCREEN UPDATE FUNCTIONS ********/ + +void menu_update_screen (MenuItem *item, Screen *s) { + switch (item->type) { + case MENUITEM_MENU: + menu_update_menu_screen (item, s); + break; + case MENUITEM_SLIDER: + menu_update_slider_screen (item, s); + break; + case MENUITEM_NUMERIC_INPUT: + menu_update_slider_screen (item, s); + break; + case MENUITEM_STRING_INPUT: + menu_update_slider_screen (item, s); + break; + default: + report (RPT_ERR, "menu_update_screen: given menuitem cannot be active"); + } +} + +void menu_update_menu_screen (MenuItem *item, Screen *s) +{ +} + +void menu_update_slider_screen (MenuItem *item, Screen *s) +{ + +} + +void menu_update_numeric_screen (MenuItem *item, Screen *s) +{ + +} + +void menu_update_string_screen (MenuItem *item, Screen *s) +{ + +} + diff --git a/server/menu.h b/server/menu.h index 91e56b9..9c1fece 100644 --- a/server/menu.h +++ b/server/menu.h @@ -7,140 +7,186 @@ * * Copyright (c) 1999, William Ferrell, Scott Scriven * + * Defines all the menu data and action. */ #ifndef MENU_H #define MENU_H -#if 0 -/************************************************************************* - Menus! +#include "shared/LL.h" -This is how the LCDproc menu stuff works... +#include "screen.h" -Each item has three values: +/********************************************************************* + * Data definitions of the menustuff + * Do not modify attributes from your code, but call functions. + */ - Title -- Text - Type -- menu, function, checkbox, slider, mover - Data -- Child, ExecFunc, CheckFunc, SlidFunc, ??? +typedef enum MenuItemType { + MENUITEM_NONE = 0, + MENUITEM_TITLE, + MENUITEM_MENU, + MENUITEM_ACTION, + MENUITEM_CHECKBOX, + MENUITEM_SLIDER, + MENUITEM_NUMERIC_INPUT, + MENUITEM_STRING_INPUT, +} MenuItemType; -When an item is picked, do_menu() decides what to do based on type. ---"Menus" will recurse into the "data", assuming it is a child menu. ---"Function"-type items will have their function called. ---CheckBox-type items will have their function called with a "read" - parameter to get an on/off signal, and called with a "set" signal when - picked. ---Sliders will have the same "read" thing, and the "set" function will - take a plus or minus parameter. ---The Movers will act like a label until picked, and then the +/- keys - will both rearrange the menu, and send the item a signal of some sort - to indicate what happened. It will act like a label again after the - user presses Enter again. +typedef enum CheckboxValue { + CHECKBOX_OFF = 0, CHECKBOX_ON, CHECKBOX_GRAY +} CheckboxValue; -The "Data" field will really be a "void *", which is the "generic" -data type in C... -Anyway, this sort of thing would be declared this way: -======================================================================== +/* Return codes from an event value */ +typedef enum MenuEventFuncResult { + MENUEVENTRES_ERROR = -1, /* Something has gone wrong */ + MENUEVENTRES_OK = 0, /* Event handled OK */ + MENUEVENTRES_CLOSE, /* Event handled OK, close the menu now */ + MENUEVENTRES_QUIT /* Event handled OK, close ALL menus now */ +} MenuEventFuncResult; -menu_item MainMenu[] = { - "MENU", 0, 0, // Title - "Options", TYPE_MENU, (void *)OptionsMenu, - "Kill LCDproc", TYPE_FUNC, (void *)Shutdown_func, - 0, 0, 0, -}; +/* Events that can happen */ +typedef enum MenuEventType { + MENUEVENT_SELECT, /* Item has been selected + (menu opened, action selected) */ + MENUEVENT_UPDATE, /* Item has been modified + (checkbox, numeric, string, password) */ + MENUEVENT_PLUS, /* Item has been modified in positive direction + (slider moved) */ + MENUEVENT_MINUS /* Item has been modified in negative direction + (slider moved) */ +} MenuEventType; -menu_item OptionsMenu[] = { - "OPTIONS", TYPE_TITL, 0, // Title - "24-hour Time", TYPE_CHEK, (void *)Time24_func, - "Contrast...", TYPE_SLID, (void *)Contrast_func, - 0, 0, 0, -}; +#define EventFunc(f) MenuEventFuncResult (f) (void *object, MenuEventType event) -///////////////// Elsewhere, we declare these... +typedef struct MenuItem { + int type; /* Type as defined above */ + char *id; /* Internal name for client supplied menus */ + EventFunc (*event_func); + /* Defines event_func to be an event function */ + union data { + struct menu { + char *text; /* Visible name of the submenu */ + int current_item_index; /* At what menuitem is the selector */ + struct MenuItem *parent; /* Parent of this menu */ + LinkedList *contents; /* What's in this menu */ + } menu; + struct checkbox { + char *text; /* Visible name of item */ + CheckboxValue value; /* Current value */ + int allowgray; /* is CHECKBOX_GRAY allowed ? */ + } checkbox; + struct slider { + char *text; /* Visible name of item */ + char *lefttext; /* Text at minimal value */ + char *righttext;/* Text at minimal value */ + int value; /* Current value */ + int minvalue; + int maxvalue; + int stepsize; + } slider; + struct numeric { + char *text; /* Visible name of item */ + int value; /* Current value */ + int maxvalue; + int minvalue; + } numeric; + struct string { + char *text; /* Visible name of item */ + char *value; /* Current value (in a buffer) */ + char passwordchar; /* For passwords */ + int maxlength; + } string; + struct password { + char *text; /* Visible name of item */ + char *value; /* Current value (in a buffer) */ + int maxlength; /* Max allowed length */ + } password; + } data; +} MenuItem; -void Shutdown_func() +#define Menu MenuItem +/* A Menu is a MenuItem too. + * This definition is only for better understanding of this code. + */ + +/********************************************************************* + * Functions to use the menustuff + */ + +MenuItem *menu_create_add_item (Menu *into_menu, int type, char *name, + EventFunc(*event_func)); +/* Creates a new item and adds it to the given menu. + * All attributes if the new item are cleared. + * into_menu What menu should it be in. + * type: type as defined above (determines also how the attributes will + * be filled). + * name: internal name of the item. Never visible. String will be + * copied. + * event_func: the event function that should be called upon actions on this + * item. see event.h. + * The data part of the new item is filled with 0's. + * + * Return value: the new item, of NULL on error. + * + * If you create a new menu, the menu data will automatically be allocated, + * and the contents pointer set to this menu. + * + * To initialize data for the data part, do things like: + * + * yourname = menu_create_add_item (m, MENUITEM_STRING_INPUT, "YourName", + * yourname_change_handler); + * yourname->data.text = strdup ("Your name"); + * yourname->data.maxlength = 10; + * yourname->data.value = malloc (10+1); <--- maxlength + 1 + * yourname->data.value[0] = 0; <--- clear the string + * + * The data NEEDS to be initialized immediately (at least before it's first + * used). + * + */ + +int menu_destroy_item (Menu *menu, MenuItem *item); +/* Deletes item from menu and removes item from memory + * + * If the item is a menu, the menu data will also be deallocated. + * + * Return value: 0 for OK, -1 for error (eg. submenus not empty) + * + * To destroy the data in the data struct, do things like: + * + * free (yourname->data.value); + * free (yourname->data.text); + * menu_destroy_item (yourname); + */ + +static inline MenuItem *menu_getfirst_item (Menu *menu) +/* Retrieves the first item from the list of items in the menu. */ { - // Do something here... - return MENU_KILL; // or MENU_CLOSE, or MENU_OK, or MENU_ERROR + return (MenuItem*) LL_GetFirst( menu->data.menu.contents ); } -int Time24_func(int input) +static inline MenuItem *menu_getnext_item (Menu *menu) +/* Retrieves the next item from the list of items in the menu. + * No other menu calls should be made between menu_first_item() and + * this function, to keep the list-cursor where it is. */ { - if(input == MENU_READ) return status; - if(input == MENU_CHECK) toggle_status(); // does something. - return (status | MENU_OK); - // The status is "or"-ed with the MENU value to let do_menu() - // know what to do after selecting the item. (two return - // values in one. :) - - // Also, "MENU_OK" happens to be zero, so it does not matter - // unless you want something else (like MENU_CLOSE) + return (MenuItem*) LL_GetNext( menu->data.menu.contents ); } -int Contrast_func(int input) -{ - if(input == MENU_READ) return status; - if(input == MENU_PLUS) increment_status(); // does something. - if(input == MENU_MINUS) decrement_status();// does something. - return (status | MENU_OK); -} +MenuItem *menu_find_item (Menu *menu, char *id); +/* Retrieves the first item from the list of items in the menu. */ -===================================================================== +void menu_build_screen (MenuItem *item, Screen *s); +/* Builds the selected menuitem on screen using widgets + * Returns the initial state. + */ -Function return values: - MENU_OK Keeps menu open. - MENU_CLOSE Closes menu after item is picked. - Leaves the parent menus open. - MENU_QUIT Closes all menus after item is picked. - Like a normal pulldown menu. - MENU_KILL Same as MENU_QUIT, so far. - MENU_ERROR Um, for errors? :) - -Also, functions for sliders and checkboxes should return a status value -binary OR-ed with the MENU_ return value. Checkboxes should return 0 or 1, -and sliders should return 0-255. - -**************************************************************************/ -#endif - -/* Return codes from selected menu items...*/ -#define MENU_ERROR -0x7FFF0000 -#define MENU_OK 0 -#define MENU_CLOSE 0x10000 -#define MENU_QUIT 0x20000 -#define MENU_KILL 0x20000 - -/* Menu item Types...*/ -#define TYPE_TITL 0 -#define TYPE_MENU 1 -#define TYPE_FUNC 2 -#define TYPE_CHEK 3 -#define TYPE_SLID 4 -#define TYPE_MOVE 5 - -#define CLIENT_MENU 0x100 -#define CLIENT_FUNC 0x101 -#define CLIENT_CHEK 0x102 -#define CLIENT_SLID 0x103 -#define CLIENT_MOVE 0x104 - -/* User actions, sent to item-handling functions as input.*/ -#define MENU_SELECT 1 -#define MENU_CHECK 2 -#define MENU_PLUS 3 -#define MENU_MINUS 4 -#define MENU_READ 5 - -typedef struct menu_item { - char *text; - int type; - void *data; -} menu_item; - -#define Menu menu_item * - -int do_menu (Menu menu); +void menu_update_screen (MenuItem *item, Screen *s); +/* Updates the widgets of the selected menuitem + * Returns the new state. + */ #endif diff --git a/server/menus.c b/server/menus.c deleted file mode 100644 index 1041109..0000000 --- a/server/menus.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * menus.c - * This file is part of LCDd, the lcdproc server. - * - * This file is released under the GNU General Public License. Refer to the - * COPYING file distributed with this package. - * - * Copyright (c) 1999, William Ferrell, Scott Scriven - * - * - * Defines the default menus the server provides. Also includes the - * plug-in functions attached to menu items... - * - * So far, all menus are static, and not dynamically generated. I'll - * have to find a way to fix this, since many menu items will be dynamic. - * (clients connected, screens available, etc...) - * - */ - -#include -#include -#include - -#include "shared/report.h" - -#include "drivers.h" -#include "drivers.h" - -#include "main.h" -#include "menus.h" -#include "render.h" -#include "serverscreens.h" - -int Shutdown_func (); -int System_halt_func (); -int Reboot_func (); -int Close_func (); -int OK_func (); -int Time24_func (int input); -int Heartbeat_func (int input); -int Backlight_func (int input); -int Server_screen_func (int input); -int Contrast_func (int input); -int Backlight_Brightness_func (int input); -int Backlight_Off_Brightness_func (int input); -int Backlight_Off_func (); -int Backlight_On_func (); -int Backlight_Open_func (); - -menu_item main_menu[] = { - {"LCDproc", 0, 0}, /* Title*/ - {"Options", TYPE_MENU, (void *) options_menu}, - {"Screens", TYPE_MENU, (void *) screens_menu}, - {"Shutdown", TYPE_MENU, (void *) shutdown_menu}, - {0, 0, 0}, - -}; - -menu_item options_menu[] = { - {"OPTIONS", TYPE_TITL, 0}, /* Title*/ -/* "24-hour Time", TYPE_CHEK, (void *)Time24_func,*/ - {"Contrast...", TYPE_SLID, (void *) Contrast_func}, - {"Backlight", TYPE_MENU, (void *) Backlight_menu}, - {"Heartbeat", TYPE_CHEK, (void *) Heartbeat_func}, -/* { "Backlight...", TYPE_SLID, (void *)Backlight_func}, - * "OK", TYPE_FUNC, (void *)OK_func, - * "Close Menu", TYPE_FUNC, (void *)Close_func, - * "Exit Program", TYPE_FUNC, (void *)Shutdown_func, - * "Another Title",TYPE_TITL, 0, - * "Main menu?", TYPE_MENU, (void *)main_menu, - * "Nothing!", TYPE_FUNC, 0, - */ - {0, 0, 0}, -}; - -menu_item screens_menu[] = { - {"SCREENS", TYPE_TITL, 0}, /* Title*/ - {"Server Scr", TYPE_CHEK, (void *) Server_screen_func}, - {0, 0, 0}, -}; - -menu_item shutdown_menu[] = { - {"Shut Down...", TYPE_TITL, 0}, /* Title*/ - {"Kill LCDproc", TYPE_FUNC, (void *) Shutdown_func}, - {"System halt", TYPE_FUNC, (void *) System_halt_func}, - {"Reboot", TYPE_FUNC, (void *) Reboot_func}, - {0, 0, 0}, -}; - -menu_item Backlight_menu[] = { - {"BACKLIGHT MENU", TYPE_TITL, 0}, /* Title*/ - {"Brightness...", TYPE_SLID, (void *) Backlight_Brightness_func}, - {"\"Off\" Brightness", TYPE_SLID, (void *) Backlight_Off_Brightness_func}, - {"Backlight Mode:", TYPE_FUNC, 0}, /* Label*/ - {" - Off", TYPE_FUNC, Backlight_Off_func}, - {" - On", TYPE_FUNC, Backlight_On_func}, - {" - Open", TYPE_FUNC, Backlight_Open_func}, - {0, 0, 0}, -}; - -/************************************************************************ - * Plug-in functions for menu items - */ - -/* Exits the program.*/ -int -Shutdown_func () -{ - exit_program (0); - - return MENU_KILL; -} - -/* Shuts down the system, if possible*/ -int -System_halt_func () -{ - int err; - uid_t id; - - id = geteuid (); - - err = system ("init 0"); - - if (err < 0) - return MENU_KILL; - if (err == 127) - return MENU_KILL; - - /* If we're root, exit*/ - if (id == 0) - exit_program (0); - - /* Otherwise, assume shutdown will fail; and show more stats.*/ - return MENU_KILL; -} - -/* Shuts down the system and restarts it*/ -int -Reboot_func () -{ - int err; - uid_t id; - - id = geteuid (); - - err = system ("init 6"); - - if (err < 0) - return MENU_KILL; - if (err == 127) - return MENU_KILL; - - /* If we're root, exit*/ - if (id == 0) - exit_program (0); - - /* Otherwise, assume shutdown will fail; and show more stats.*/ - return MENU_KILL; -} - -int -Close_func () -{ - return MENU_CLOSE; -} - -int -OK_func () -{ - return MENU_OK; -} - -int -Time24_func (int input) -{ - static int status = 0; - - if (input == MENU_READ) - return status; - if (input == MENU_CHECK) - status ^= 1; /* does something.*/ - return (status | MENU_OK); - /* The status is "or"-ed with the MENU value to let do_menu() - * know what to do after selecting the item. (two return - * values in one. :) - */ - - /* Also, "MENU_OK" happens to be zero, so it does not matter - * unless you want something else (like MENU_CLOSE) - */ -} - -int -Heartbeat_func (int input) -{ - if (input == MENU_READ) - return (heartbeat != HEARTBEAT_OFF); - if (input == MENU_CHECK) { - if (heartbeat) - heartbeat = HEARTBEAT_OFF; - else - heartbeat = HEARTBEAT_OPEN; - } - return ((heartbeat != HEARTBEAT_OFF) | MENU_OK); -} - -int -Backlight_func (int input) -{ - int status = 128; - - switch (backlight) { - case BACKLIGHT_OFF: - if (input == MENU_READ) - status = 0; - if (input == MENU_PLUS) { - backlight = BACKLIGHT_OPEN; - status = 128; - } - if (input == MENU_MINUS) { - status = 0; - } - break; - case BACKLIGHT_ON: - if (input == MENU_READ) - status = 255; - if (input == MENU_PLUS) { - status = 255; - } - if (input == MENU_MINUS) { - backlight = BACKLIGHT_OPEN; - status = 128; - } - break; - case BACKLIGHT_OPEN: - if (input == MENU_READ) - status = 128; - if (input == MENU_PLUS) { - backlight = BACKLIGHT_ON; - backlight_state = BACKLIGHT_ON; - status = 255; - } - if (input == MENU_MINUS) { - backlight = BACKLIGHT_OFF; - backlight_state = BACKLIGHT_OFF; - status = 0; - } - break; - } - - /* - if(input == MENU_READ) return (backlight != BACKLIGHT_OFF); - if(input == MENU_CHECK) - { - if(backlight) backlight = BACKLIGHT_OFF; - else backlight = BACKLIGHT_OPEN; - } - */ - drivers_backlight (backlight_state & BACKLIGHT_ON); - - return (status | MENU_OK); -} - -int -Server_screen_func (int input) -{ - if (input == MENU_READ) - return (server_screen->priority < 256); - if (input == MENU_CHECK) { - if (server_screen->priority < 256) - server_screen->priority = 256; - else - server_screen->priority = DEFAULT_SCREEN_PRIORITY; - } - - return (MENU_OK | (server_screen->priority < 256)); -} - -int -Contrast_func (int input) -{ - static int status = 500; - - status = drivers_get_contrast (); - - if (input == MENU_READ) - return status; - if (input == MENU_PLUS) - status += 5; /* does something.*/ - if (input == MENU_MINUS) - status -= 5; /* does something.*/ - - if (status < 0) - status = 0; - if (status > 1000) - status = 1000; - drivers_set_contrast (status); - - return (status | MENU_OK); -} - -void -server_menu () -{ - debug (RPT_DEBUG, "server_menu()"); - - do_menu (main_menu); - -} - -int -Backlight_Brightness_func (int input) -{ - int status = backlight_brightness; - - if (input == MENU_READ) - return status; - if (input == MENU_PLUS) - status += 5; /* does something.*/ - if (input == MENU_MINUS) - status -= 5; /* does something.*/ - - if (status < 0) - status = 0; - if (status > 255) - status = 255; - drivers_backlight (status); - - backlight_brightness = status; - - return (status | MENU_OK); -} - -int -Backlight_Off_Brightness_func (int input) -{ - int status = backlight_off_brightness; - - if (input == MENU_READ) - return status; - if (input == MENU_PLUS) - status += 5; /* does something.*/ - if (input == MENU_MINUS) - status -= 5; /* does something.*/ - - if (status < 0) - status = 0; - if (status > 255) - status = 255; - drivers_backlight (status); - - backlight_off_brightness = status; - - return (status | MENU_OK); -} - -int -Backlight_Off_func () -{ - backlight_state = BACKLIGHT_OFF; - backlight = BACKLIGHT_OFF; - drivers_backlight (backlight_off_brightness); - return MENU_OK; -} - -int -Backlight_On_func () -{ - backlight_state = BACKLIGHT_ON; - backlight = BACKLIGHT_ON; - drivers_backlight (backlight_brightness * (backlight_state & BACKLIGHT_ON)); - return MENU_OK; -} - -int -Backlight_Open_func () -{ - backlight = BACKLIGHT_OPEN; - return MENU_OK; -} diff --git a/server/menus.h b/server/menus.h deleted file mode 100644 index 7c83562..0000000 --- a/server/menus.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * menus.h - * This file is part of LCDd, the lcdproc server. - * - * This file is released under the GNU General Public License. Refer to the - * COPYING file distributed with this package. - * - * Copyright (c) 1999, William Ferrell, Scott Scriven - * - */ - -#ifndef MENUS_H -#define MENUS_H - -#include "menu.h" - -/* These probably don't need to be defined here... */ -extern menu_item main_menu[]; -extern menu_item options_menu[]; -extern menu_item screens_menu[]; -extern menu_item shutdown_menu[]; -extern menu_item Backlight_menu[]; - -/* Brings up the main menu... */ -void server_menu (); - -#endif diff --git a/server/menuscreens.c b/server/menuscreens.c new file mode 100644 index 0000000..d15763b --- /dev/null +++ b/server/menuscreens.c @@ -0,0 +1,18 @@ +/* + * menuscreens.c + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn + * + * + * Creates the server menu screen (s). + * Handles the keypresses for this screen. + * + */ + + +#include "menuscreens.h" \ No newline at end of file diff --git a/server/menuscreens.h b/server/menuscreens.h new file mode 100644 index 0000000..d078881 --- /dev/null +++ b/server/menuscreens.h @@ -0,0 +1,22 @@ +/* + * menuscreens.h + * This file is part of LCDd, the lcdproc server. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright (c) 1999, William Ferrell, Scott Scriven + * + * Creates all menuscreens, menus and handles the keypresses for the + * menuscreens. + */ + +#ifndef MENUSCREENS_H +#define MENUSCREENS_H + +#include "menu.h" + +MenuEventFuncResult menuscreen_key_handler (); +/* This handler should be called by the real handler for the event */ + +#endif \ No newline at end of file diff --git a/server/parse.c b/server/parse.c index 8daee37..17188e6 100644 --- a/server/parse.c +++ b/server/parse.c @@ -24,7 +24,7 @@ #include "shared/sockets.h" #include "shared/report.h" #include "clients.h" -#include "client_functions.h" +#include "commands/command_list.h" #include "parse.h" /* This is a big function... TOO big. How to trim.... @@ -38,7 +38,7 @@ parse_all_client_messages () { int i; /* int j, len;*/ /*int newtoken, inquote;*/ - client *c; + Client * c; char *str, *p, *q, *s; /* char *tok;*/ int argc; @@ -60,130 +60,125 @@ parse_all_client_messages () #define LINE_TERM_CHAR '\0' #define COMMENT_CHAR '#' - /*debug("parse: Rewinding list...");*/ - LL_Rewind (clients); - do { - /* Get the next client...*/ - /*debug("parse: Getting client...");*/ - c = LL_Get (clients); - if (c) { - /* And parse all its messages...*/ - /*debug(RPT_DEBUG, "parse: Getting messages...");*/ - for (str = client_get_message (c); str; str = client_get_message (c)) { - debug (RPT_DEBUG, "parse: ...%s", str); - /* Now, split up the string...*/ - argc = 0; - i = 0; - q = p = str; + for( c=clients_getfirst(); c; c=clients_getnext()) { - if (*p == COMMENT_CHAR) { - continue; /* found a comment line - skip it...*/ + /* And parse all its messages...*/ + /*debug(RPT_DEBUG, "parse: Getting messages...");*/ + for (str = client_get_message (c); str; str = client_get_message (c)) { + + debug (RPT_DEBUG, "parse: ...%s", str); + /* Now, split up the string...*/ + argc = 0; + i = 0; + q = p = str; + + if (*p == COMMENT_CHAR) { + continue; /* found a comment line - skip it...*/ + } + + debug (RPT_DEBUG, "starting string scan..."); + + do { + /* bypass initial white space...*/ + while ((*p == SEPARATOR_CHAR) && (*p)) { + p++; + q++; } - debug (RPT_DEBUG, "starting string scan..."); + /* If (*p) is null here, we reached the end of + * an empty parameter... so one of two things + * is true: + * + * 1. There is nothing but white space on this line (odd..) + * 2. This is trailing white space (odd... but allowable) + */ - do { - /* bypass initial white space...*/ - while ((*p == SEPARATOR_CHAR) && (*p)) { - p++; - q++; - } - - /* If (*p) is null here, we reached the end of - * an empty parameter... so one of two things - * is true: + if (*p == LINE_TERM_CHAR) { + break; + /* if there are no arguments, argc == 0 and will fail + * appropriately... * - * 1. There is nothing but white space on this line (odd..) - * 2. This is trailing white space (odd... but allowable) + * if this is trailing white space, ignore the argc++ at the + * end and claim this as the end... */ + } + /* Handle quoted strings...*/ + if ((s = strchr(leftquote, *p)) != NULL) { + quoteindex = s - leftquote; + /*debug(RPT_DEBUG, "found <%c> at index [%d] = <%c>", *p, quoteindex, leftquote[quoteindex]);*/ + q = ++p; /* past open quote...*/ + while ((rightquote[quoteindex] != *p) && (*p != LINE_TERM_CHAR)) { + p++; + } if (*p == LINE_TERM_CHAR) { - break; - /* if there are no arguments, argc == 0 and will fail - * appropriately... - * - * if this is trailing white space, ignore the argc++ at the - * end and claim this as the end... + /* We just sucked up the rest of the command line: ERROR!!*/ + snprintf (errmsg, sizeof(errmsg), "huh? unterminated string! missing ending %c\n", + rightquote[quoteindex]); + sock_send_string (c->sock, errmsg); + continue; + } else { + *p = LINE_TERM_CHAR; /* terminate string*/ + p++; /* bypass to next character*/ + /* Note that next character could be a EndOfLine (null) + * if the string was last on the line, or it could be + * something else... is it a blank? */ - } - - /* Handle quoted strings...*/ - if ((s = strchr(leftquote, *p)) != NULL) { - quoteindex = s - leftquote; - /*debug(RPT_DEBUG, "found <%c> at index [%d] = <%c>", *p, quoteindex, leftquote[quoteindex]);*/ - q = ++p; /* past open quote...*/ - while ((rightquote[quoteindex] != *p) && (*p != LINE_TERM_CHAR)) { - p++; - } - if (*p == LINE_TERM_CHAR) { - /* We just sucked up the rest of the command line: ERROR!!*/ - snprintf (errmsg, sizeof(errmsg), "huh? unterminated string! missing ending %c\n", - rightquote[quoteindex]); - sock_send_string (c->sock, errmsg); + if (*p != SEPARATOR_CHAR && *p != LINE_TERM_CHAR) { + sock_send_string (c->sock, "huh? improperly terminated string! (missing whitespace)\n"); continue; - } else { - *p = LINE_TERM_CHAR; /* terminate string*/ - p++; /* bypass to next character*/ - /* Note that next character could be a EndOfLine (null) - * if the string was last on the line, or it could be - * something else... is it a blank? - */ - if (*p != SEPARATOR_CHAR && *p != LINE_TERM_CHAR) { - sock_send_string (c->sock, "huh? improperly terminated string! (missing whitespace)\n"); - continue; - } } - - /* Otherwise, normal string...*/ - } else { - while (*p != SEPARATOR_CHAR && *p != LINE_TERM_CHAR) - p++; } - /* Not end of line?*/ - if (*p) { - *p = LINE_TERM_CHAR; - /*debug(RPT_DEBUG, "found new token: %s", q);*/ - argv[i++] = q; - q = ++p; - } else { - /*debug(RPT_DEBUG, "found new token: %s", q);*/ - argv[i++] = q; - } - /* At the end of this statement, - * *p will be '\0' if end of input reached; - * otherwise, it is the first character of the - * next part of the string. - */ - - - argc++; - } while (*p); - - /*debug(RPT_DEBUG, "exiting string scan...");*/ - - argv[argc] = NULL; - if (argc < 1) - continue; - - /* Now find and call the appropriate function...*/ - invalid = 1; - for (i = 0; commands[i].keyword; i++) { - if (0 == strcmp (argv[0], commands[i].keyword)) { - invalid = commands[i].function (c, argc, argv); - break; /* found our function - don't continue on...*/ - } + /* Otherwise, normal string...*/ + } else { + while (*p != SEPARATOR_CHAR && *p != LINE_TERM_CHAR) + p++; } - if (invalid) { - snprintf (errmsg, sizeof(errmsg), "huh? Invalid command \"%s\"\n", argv[0]); - sock_send_string (c->sock, errmsg); + /* Not end of line?*/ + if (*p) { + *p = LINE_TERM_CHAR; + /*debug(RPT_DEBUG, "found new token: %s", q);*/ + argv[i++] = q; + q = ++p; + } else { + /*debug(RPT_DEBUG, "found new token: %s", q);*/ + argv[i++] = q; } + /* At the end of this statement, + * *p will be '\0' if end of input reached; + * otherwise, it is the first character of the + * next part of the string. + */ - free (str); /* fixed memory leak?*/ - } /* end for(str...)*/ - } /* end if (c)*/ - } while (LL_Next (clients) == 0); + + argc++; + } while (*p); + + /*debug(RPT_DEBUG, "exiting string scan...");*/ + + argv[argc] = NULL; + if (argc < 1) + continue; + + /* Now find and call the appropriate function...*/ + invalid = 1; + for (i = 0; commands[i].keyword; i++) { + if (0 == strcmp (argv[0], commands[i].keyword)) { + invalid = commands[i].function (c, argc, argv); + break; /* found our function - don't continue on...*/ + } + } + + if (invalid) { + snprintf (errmsg, sizeof(errmsg), "huh? Invalid command \"%.40s\"\n", argv[0]); + sock_send_string (c->sock, errmsg); + } + + free (str); /* fixed memory leak?*/ + } /* end for(str...)*/ + } return 0; } diff --git a/server/render.c b/server/render.c index 04124ec..a6e07c9 100644 --- a/server/render.c +++ b/server/render.c @@ -53,9 +53,9 @@ static int reset; static int draw_frame (LinkedList * list, char fscroll, int left, int top, int right, int bottom, int fwid, int fhgt, int fspeed, int timer); int -draw_screen (screen * s, int timer) +draw_screen (Screen * s, int timer) { - static screen *old_s = NULL; + static Screen * old_s = NULL; int tmp = 0, tmp_state = 0; report(RPT_INFO, "draw_screen( screen=\"%.40s\", timer=%d ) ==== START RENDERING ====", s->name, timer ); @@ -82,10 +82,10 @@ draw_screen (screen * s, int timer) * inherit the backlight state from the parent client. This allows * the client to override it's childrens settings. */ - if (s->backlight_state == BACKLIGHT_NOTSET) { - if (s->parent) tmp_state = s->parent->backlight_state; + if (s->backlight == BACKLIGHT_OPEN) { + if (s->client) tmp_state = s->client->backlight; } else { - tmp_state = s->backlight_state; + tmp_state = s->backlight; } /* Set up backlight to the correct state... */ @@ -126,7 +126,7 @@ draw_screen (screen * s, int timer) drivers_output (output_state); /* Draw a frame... */ - draw_frame (s->widgets, 'v', 0, 0, display_props->width, display_props->height, s->wid, s->hgt, (((s->duration / s->hgt) < 1) ? 1 : (s->duration / s->hgt)), timer); + draw_frame (s->widgetlist, 'v', 0, 0, display_props->width, display_props->height, s->width, s->height, (((s->duration / s->height) < 1) ? 1 : (s->duration / s->height)), timer); /*debug(RPT_DEBUG, "draw_screen done"); */ @@ -176,12 +176,12 @@ draw_frame (LinkedList * list, #define VerticalScrolling (fscroll == 'v') #define HorizontalScrolling (fscroll == 'h') - char str[BUFSIZE]; /* scratch buffer */ - widget *w; + char str[BUFSIZE]; /* scratch buffer */ + Widget * w; - int wid, hgt; /* Width and height of visible frame area */ + int vis_width, vis_height; /* Width and height of visible frame area */ int x, y; - int fx, fy; /* Scrolling offset for the frame... */ + int fx, fy; /* Scrolling offset for the frame... */ int length, speed; /*int lines; */ @@ -191,8 +191,8 @@ draw_frame (LinkedList * list, "right=%d, bottom=%d, fwid=%d, fhgt=%d, fspeed=%d, timer=%d )", list, fscroll, left,top, right, bottom, fwid, fhgt, fspeed, timer ); - wid = right - left; /* This is the size of the visible frame area */ - hgt = bottom - top; + vis_width = right - left; /* This is the size of the visible frame area */ + vis_height = bottom - top; fx = 0; fy = 0; @@ -220,8 +220,8 @@ draw_frame (LinkedList * list, } fy %= fhgt; - if (fy > fhgt - hgt) - fy = fhgt - hgt; + if (fy > fhgt - vis_height) + fy = fhgt - vis_height; } else if (HorizontalScrolling) { /* TODO: Frames don't scroll horizontally yet! */ @@ -239,7 +239,7 @@ draw_frame (LinkedList * list, LL_Rewind (list); do { - w = (widget *) LL_Get (list); + w = (Widget *) LL_Get (list); if (!w) return -1; @@ -247,10 +247,10 @@ draw_frame (LinkedList * list, switch (w->type) { case WID_STRING: if (ValidPoint(w) && TextPresent(w)) { - if ((w->y <= hgt + fy) && (w->y > fy)) { - if (w->x > wid) w->x=wid; - strncpy (str, w->text, wid - w->x + 1); - str[wid - w->x + 1] = 0; + if ((w->y <= vis_height + fy) && (w->y > fy)) { + if (w->x > vis_width) w->x=vis_width; + strncpy (str, w->text, vis_width - w->x + 1); + str[vis_width - w->x + 1] = 0; drivers_string (w->x + left, w->y + top - fy, str); } } @@ -261,9 +261,9 @@ draw_frame (LinkedList * list, reset = 0; } if ((w->x > 0) && (w->y > 0)) { - if ((w->y <= hgt + fy) && (w->y > fy)) { + if ((w->y <= vis_height + fy) && (w->y > fy)) { if (w->length > 0) { - if ((w->length / display_props->cellwidth) < wid - w->x + 1) { + if ((w->length / display_props->cellwidth) < vis_width - w->x + 1) { /*was: drivers_hbar (w->x + left, w->y + top - fy, w->length); */ /* improvised len and promille */ int full_len = display_props->width - w->x - left + 1; @@ -311,13 +311,16 @@ draw_frame (LinkedList * list, case WID_TITLE: /* FIXME: Doesn't work quite right in frames...*/ if (!w->text) break; - if (wid < 8) + if (vis_width < 8) break; - memset (str, 255, wid); + /*memset (str, 255, width);*/ + memset (str, '*', vis_width); + /* TODO: Use icon function to draw the bar */ + str[2] = ' '; length = strlen (w->text); - if (length <= wid - 6) { + if (length <= vis_width - 6) { memcpy (str + 3, w->text, length); str[length + 3] = ' '; } else /* Scroll the title, if it doesn't fit...*/ @@ -338,17 +341,17 @@ draw_frame (LinkedList * list, x -= 3; if (x < 0) x = 0; - if (x > length - (wid - 6)) - x = length - (wid - 6); + if (x > length - (vis_width - 6)) + x = length - (vis_width - 6); if (y & 1) /* Scrolling backwards...*/ { - x = (length - (wid - 6)) - x; + x = (length - (vis_width - 6)) - x; } - strncpy (str + 3, w->text + x, (wid - 6)); - str[wid - 3] = ' '; + strncpy (str + 3, w->text + x, (vis_width - 6)); + str[vis_width - 3] = ' '; } - str[wid] = 0; + str[vis_width] = 0; drivers_string (1 + left, 1 + top, str); break; @@ -504,7 +507,7 @@ draw_frame (LinkedList * list, new_bottom = bottom; if (new_left >= right || new_top >= bottom) { /* Do nothing if it's invisible...*/ } else { - draw_frame (w->kids, w->length, new_left, new_top, new_right, new_bottom, w->wid, w->hgt, w->speed, timer); + draw_frame (w->frame_screen->widgetlist, w->length, new_left, new_top, new_right, new_bottom, w->width, w->height, w->speed, timer); } } break; diff --git a/server/render.h b/server/render.h index b9b49b0..b5835eb 100644 --- a/server/render.h +++ b/server/render.h @@ -17,7 +17,6 @@ #define HEARTBEAT_OFF 0 #define HEARTBEAT_ON 1 #define HEARTBEAT_OPEN 2 -#define HEARTBEAT_SLASH 3 #define SERVER_SCREEN_NEVER 0 #define SERVER_SCREEN_NOSCREEN 1 @@ -26,17 +25,21 @@ #define BACKLIGHT_OFF 0 #define BACKLIGHT_ON 1 #define BACKLIGHT_OPEN 2 -#define BACKLIGHT_NOTSET 3 #define BACKLIGHT_BLINK 0x100 #define BACKLIGHT_FLASH 0x200 +#define CURSOR_OFF 0 +#define CURSOR_DEFAULT_ON 1 +#define CURSOR_BLOCK 4 +#define CURSOR_UNDER 5 + extern int heartbeat; extern int backlight; extern int backlight_state; extern int backlight_brightness; extern int backlight_off_brightness; extern int output_state; -int draw_screen (screen * s, int timer); +int draw_screen (Screen * s, int timer); #endif diff --git a/server/screen.c b/server/screen.c index e30d8b8..6bc59fd 100644 --- a/server/screen.c +++ b/server/screen.c @@ -31,34 +31,45 @@ int default_duration = 0; int default_timeout = -1; -screen * -screen_create () +Screen * +screen_create (char * id, Client * client) { - screen *s; + Screen *s; - s = malloc (sizeof (screen)); + s = malloc (sizeof (Screen)); if (!s) { - report(RPT_ERR, "screen_create: Error allocating new screen"); + report(RPT_ERR, "screen_create: Error allocating"); + return NULL; + } + if (!id) { + report (RPT_ERR, "screen_create: Need id string"); + return NULL; + } + /* Client can be NULL for serverscreens and other client-less screens */ + + s->id = strdup(id); + if (!s->id) { + report(RPT_ERR, "screen_create: Error allocating"); return NULL; } - s->id = NULL; s->name = NULL; s->priority = DEFAULT_SCREEN_PRIORITY; s->duration = default_duration; - s->heartbeat = DEFAULT_HEARTBEAT; - s->wid = display_props->width; - s->hgt = display_props->height; + s->backlight = BACKLIGHT_OPEN; + s->heartbeat = HEARTBEAT_OPEN; + s->width = display_props->width; + s->height = display_props->height; s->keys = NULL; - s->parent = NULL; - s->widgets = NULL; - s->timeout = default_timeout; /*ignored unless greater than 0.*/ - s->backlight_state = BACKLIGHT_NOTSET; /*Lets the screen do it's own*/ + s->client = client; + s->widgetlist = NULL; + s->timeout = default_timeout; /*ignored unless greater than 0.*/ + s->backlight = BACKLIGHT_OPEN; /*Lets the screen do it's own*/ /*or do what the client says.*/ - s->widgets = LL_new (); - if (!s->widgets) { - report(RPT_ERR, "screen_create: Error allocating widget list"); + s->widgetlist = LL_new (); + if (!s->widgetlist) { + report(RPT_ERR, "screen_create: Error allocating"); return NULL; } @@ -66,20 +77,18 @@ screen_create () } int -screen_destroy (screen * s) +screen_destroy (Screen * s) { - widget *w; + Widget *w; if (!s) return -1; - LL_Rewind (s->widgets); - do { + for (w=LL_GetFirst(s->widgetlist); w; w=LL_GetNext(s->widgetlist)) { /* Free a widget...*/ - w = LL_Get (s->widgets); widget_destroy (w); - } while (LL_Next (s->widgets) == 0); - LL_Destroy (s->widgets); + } + LL_Destroy (s->widgetlist); if (s->id) free (s->id); @@ -93,99 +102,59 @@ screen_destroy (screen * s) return 0; } -screen * -screen_find (client * c, char *id) +int +screen_add_widget (Screen * s, Widget * w) { - screen *s; + report (RPT_INFO, "screen_add_widget(%s,%s)", s->id, w->id); + if (!s) + return -1; + if (!w) + return 1; - if (!c) + LL_Push (s->widgetlist, (void *) w); + + return 0; +} + +int +screen_remove_widget (Screen * s, Widget * w) +{ + report (RPT_INFO, "screen_remove_widget(%s,%s)", s->id, w->id); + + if (!s) + return -1; + if (!w) + return 1; + + LL_Remove (s->widgetlist, (void *) w); + + return 0; +} + +Widget * +screen_find_widget (Screen * s, char *id) +{ + Widget * w; + + if (!s) return NULL; if (!id) return NULL; - debug (RPT_INFO, "client_find_screen(%s)", id); + debug (RPT_DEBUG, "screen_find_widget(%s,%s)", s->id, id); - LL_Rewind (c->data->screenlist); - do { - s = LL_Get (c->data->screenlist); - if ((s) && (0 == strcmp (s->id, id))) { - debug (RPT_DEBUG, "client_find_screen: Found %s", id); - return s; + for ( w=LL_GetFirst(s->widgetlist); w; w=LL_GetNext(s->widgetlist) ) { + if (0 == strcmp (w->id, id)) { + debug (RPT_DEBUG, "screen_find_widget: Found %s", id); + return w; } - } while (LL_Next (c->data->screenlist) == 0); - + /* Search subscreens recursively */ + if (w->type == WID_FRAME) { + w = widget_search_subs (w, id); + if (w) + return w; + } + } + debug (RPT_DEBUG, "screen_find_widget: Not found"); return NULL; } - -int -screen_add (client * c, char *id) -{ - screen *s; - - if (!c) - return -1; - if (!id) - return -1; - - /* Make sure this screen doesn't already exist...*/ - s = screen_find (c, id); - if (s) { - return 1; - } - - s = screen_create (); - if (!s) { - report (RPT_ERR, "screen_add: Error creating screen"); - return -1; - } - - s->parent = c; - - s->id = strdup (id); - if (!s->id) { - report (RPT_ERR, "screen_add: Error allocating name"); - return -1; - } - /* TODO: Check for errors here?*/ - LL_Push (c->data->screenlist, (void *) s); - - /* Now, add it to the screenlist...*/ - if (screenlist_add (s) < 0) { - report (RPT_ERR, "screen_add: Error queueing new screen"); - return -1; - } - - return 0; -} - -int -screen_remove (client * c, char *id) -{ - screen *s; - - if (!c) - return -1; - if (!id) - return -1; - - /* Make sure this screen *does* exist...*/ - s = screen_find (c, id); - if (!s) { - report (RPT_ERR, "screen_remove: Error finding screen %s", id); - return 1; - } - /* TODO: Check for errors here?*/ - LL_Remove (c->data->screenlist, (void *) s); - - /* Now, remove it from the screenlist...*/ - if (screenlist_remove_all (s) < 0) { - /* Not a serious error..*/ - report (RPT_ERR, "screen_remove: Error dequeueing screen"); - return 0; - } - - /* TODO: Check for errors here too?*/ - screen_destroy (s); - - return 0; -} diff --git a/server/screen.h b/server/screen.h index 981857c..35c6add 100644 --- a/server/screen.h +++ b/server/screen.h @@ -13,34 +13,57 @@ #define SCREEN_H #include "shared/LL.h" -#include "clients.h" -typedef struct screen { +typedef struct Screen { char *id; char *name; - int wid, hgt; - int priority; + int width, height; int duration; - int heartbeat; int timeout; - int backlight_state; - int cursor; - int cursor_x; - int cursor_y; + short int priority; + short int heartbeat; + short int backlight; + short int cursor; + short int cursor_x; + short int cursor_y; char *keys; - LinkedList *widgets; - client *parent; -} screen; + LinkedList *widgetlist; + struct Client *client; +} Screen; + +#include "client.h" +#include "widget.h" + extern int default_duration ; extern int default_priority ; -screen *screen_create (); -int screen_destroy (screen * s); -screen *screen_find (client * c, char *id); +/* Creates a new screen */ +Screen * screen_create (char * id, Client * client); -int screen_add (client * c, char *id); -int screen_remove (client * c, char *id); +/* Destroys a screen */ +int screen_destroy (Screen * s); + +/* Add a widget to a screen */ +int screen_add_widget (Screen * s, Widget * w); + +/* Remove a widget from a screen (does not destroy it) */ +int screen_remove_widget (Screen * s, Widget * w); + +/* List functions */ +static inline Widget * screen_getfirst_widget (Screen * s) +{ + return LL_GetFirst(s->widgetlist); +} + +static inline Widget * screen_getnext_widget (Screen * s) +{ + return LL_GetNext(s->widgetlist); +} + + +/* Find a widget in a screen */ +Widget *screen_find_widget (Screen * s, char *id); #endif diff --git a/server/screenlist.c b/server/screenlist.c index f53dd76..2a7f4fb 100644 --- a/server/screenlist.c +++ b/server/screenlist.c @@ -28,10 +28,10 @@ int timer = 0; LinkedList *screenlist; -int screenlist_add_end (screen * screen); -screen *screenlist_next_roll (); -screen *screenlist_prev_roll (); -screen *screenlist_next_priority (); +int screenlist_add_end (Screen * screen); +Screen *screenlist_next_roll (); +Screen *screenlist_prev_roll (); +Screen *screenlist_next_priority (); int compare_priority (void *one, void *two); int compare_addresses (void *one, void *two); @@ -64,7 +64,7 @@ screenlist_shutdown () } int -screenlist_remove (screen * s) +screenlist_remove (Screen * s) { report (RPT_INFO, "screenlist_remove()"); @@ -75,7 +75,7 @@ screenlist_remove (screen * s) } int -screenlist_remove_all (screen * s) +screenlist_remove_all (Screen * s) { int i = 0; @@ -97,19 +97,19 @@ screenlist_getlist () return screenlist; } -screen * +Screen * screenlist_current () { char str[256]; - screen *s; - static screen *old_s = NULL; - client *c; + Screen * s; + static Screen * old_s = NULL; + Client * c; debug( RPT_INFO, "screenlist_current:"); /*LL_dprint(screenlist);*/ - s = (screen *) LL_GetFirst (screenlist); + s = (Screen *) LL_GetFirst (screenlist); /* FIXME: Make sure the screen/client exists!*/ if (s != old_s) { @@ -124,7 +124,7 @@ screenlist_current () report (RPT_WARNING, "screenlist: Didn't find screen 0x%8x! Client crashed?", (int) old_s); } else { /*debug(RPT_DEBUG, "screenlist_current: ... sending ignore");*/ - c = old_s->parent; + c = old_s->client; if (c) /* Tell the client we're not listening any more...*/ { snprintf (str, sizeof(str), "ignore %s\n", old_s->id); @@ -138,7 +138,7 @@ screenlist_current () } if (s) { /*debug(RPT_DEBUG, "screenlist_current: listening to new screen");*/ - c = s->parent; + c = s->client; if (c) /* Tell the client we're paying attention...*/ { snprintf (str, sizeof(str), "listen %s\n", s->id); @@ -158,16 +158,16 @@ screenlist_current () } int -screenlist_add (screen * s) +screenlist_add (Screen * s) { /* TODO: Different queueing modes...*/ return screenlist_add_end (s); } -screen * +Screen * screenlist_next () { - screen *s; + Screen *s; /*debug(RPT_DEBUG, "Screenlist_next()");*/ @@ -194,10 +194,10 @@ screenlist_next () return s; } -screen * +Screen * screenlist_prev () { - screen *s; + Screen *s; s = screenlist_current (); @@ -219,7 +219,7 @@ screenlist_prev () /* Adds new screens to the end of the screenlist...*/ int -screenlist_add_end (screen * screen) +screenlist_add_end (Screen * screen) { debug (RPT_DEBUG, "screenlist_add_end()"); @@ -227,7 +227,7 @@ screenlist_add_end (screen * screen) } /* Simple round-robin approach to screen cycling...*/ -screen * +Screen * screenlist_next_roll () { /*debug(RPT_DEBUG, "screenlist_next_roll()");*/ @@ -239,7 +239,7 @@ screenlist_next_roll () } /* Strict priority queue approach...*/ -screen * +Screen * screenlist_next_priority () { /*screen *s, *t;*/ @@ -254,7 +254,7 @@ screenlist_next_priority () } /* Simple round-robin approach to screen cycling...*/ -screen * +Screen * screenlist_prev_roll () { /*debug(RPT_DEBUG, "screenlist_prev_roll()");*/ @@ -268,7 +268,7 @@ screenlist_prev_roll () int compare_priority (void *one, void *two) { - screen *a, *b; + Screen *a, *b; /*debug(RPT_DEBUG, "compare_priority: %8x %8x", one, two);*/ @@ -277,8 +277,8 @@ compare_priority (void *one, void *two) if (!two) return 0; - a = (screen *) one; - b = (screen *) two; + a = (Screen *) one; + b = (Screen *) two; /*debug(RPT_DEBUG, "compare_priority: done?");*/ diff --git a/server/screenlist.h b/server/screenlist.h index 68698d0..79d2df0 100644 --- a/server/screenlist.h +++ b/server/screenlist.h @@ -28,13 +28,13 @@ int screenlist_init (); int screenlist_shutdown (); LinkedList *screenlist_getlist (); -screen *screenlist_current (); +Screen *screenlist_current (); -int screenlist_add (screen * s); -screen *screenlist_next (); -screen *screenlist_prev (); +int screenlist_add (Screen * s); +Screen *screenlist_next (); +Screen *screenlist_prev (); -int screenlist_remove (screen * s); -int screenlist_remove_all (screen * s); +int screenlist_remove (Screen * s); +int screenlist_remove_all (Screen * s); #endif diff --git a/server/serverscreens.c b/server/serverscreens.c index 397cec8..7780c54 100644 --- a/server/serverscreens.c +++ b/server/serverscreens.c @@ -23,76 +23,68 @@ #include "shared/report.h" #include "drivers.h" - #include "clients.h" #include "screen.h" #include "screenlist.h" #include "widget.h" - #include "serverscreens.h" -screen *server_screen; -char *id = "ClientList"; -char *name = "Client List"; +Screen * server_screen; char title[256] = "LCDproc Server"; char one[256] = ""; char two[256] = ""; char three[256] = ""; -#define WidgetXPos(w,a) (w)->x = (a) -#define WidgetYPos(w,a) (w)->y = (a) -#define WidgetText(w,a) (w)->text = (a) -#define WidgetString(w,a,b,t) {WidgetXPos(w,a);WidgetYPos(w,b);WidgetText(w,t);} +#define WidgetString(w,a,b,t) {(w)->x=(a);(w)->y=(b);(w)->text=(t);} int server_screen_init () { - widget *w; + Widget * w; debug (RPT_DEBUG, "server_screen_init"); - server_screen = screen_create (); - + server_screen = screen_create ("_server_screen", NULL); if (!server_screen) { report (RPT_ERR, "server_screen_init: Error allocating screen"); return -1; } - server_screen->id = id; - server_screen->name = name; + server_screen->name = "Server screen"; server_screen->duration = 8; /* 1 second, instead of 4...*/ + server_screen->priority = -1; /* TODO: use priorities good */ - if (widget_add (server_screen, "title", "title", NULL, 1) != 0) { - report (RPT_ERR, "server_screen_init: internal error: could not add title widget"); - } - if (widget_add (server_screen, "one", "string", NULL, 1) != 0) { - report (RPT_ERR, "server_screen_init: internal error: could not add title widget"); - } - if (widget_add (server_screen, "two", "string", NULL, 1) != 0) { - report (RPT_ERR, "server_screen_init: internal error: could not add title widget"); - } - if (widget_add (server_screen, "three", "string", NULL, 1) != 0) { - report (RPT_ERR, "server_screen_init: internal error: could not add title widget"); + if ( (w = widget_create ("title", WID_TITLE, server_screen)) == NULL + || screen_add_widget (server_screen, w) != 0 + || (w = widget_create ("one", WID_STRING, server_screen)) == NULL + || screen_add_widget (server_screen, w) != 0 + || (w = widget_create ("two", WID_STRING, server_screen)) == NULL + || screen_add_widget (server_screen, w) != 0 + || (w = widget_create ("three", WID_STRING, server_screen)) == NULL + || screen_add_widget (server_screen, w) != 0 + ) { + report (RPT_ERR, "server_screen_init: Can't create widgets"); + return -1; } /* Now, initialize all the widgets...*/ - if ((w = widget_find (server_screen, "title")) != NULL) { - WidgetText(w,title); + if ((w = screen_find_widget (server_screen, "title")) != NULL) { + w->text = title; } else report (RPT_ERR, "server_screen_init: Can't find title"); - if ((w = widget_find (server_screen, "one")) != NULL) + if ((w = screen_find_widget (server_screen, "one")) != NULL) WidgetString(w,1,2,one) else report (RPT_ERR, "server_screen_init: Can't find widget one"); - if ((w = widget_find (server_screen, "two")) != NULL) + if ((w = screen_find_widget (server_screen, "two")) != NULL) WidgetString(w,1,3,two) else report (RPT_ERR, "server_screen_init: Can't find widget two"); - if ((w = widget_find (server_screen, "three")) != NULL) + if ((w = screen_find_widget (server_screen, "three")) != NULL) WidgetString(w,1,4,three) else report (RPT_ERR, "server_screen_init: Can't find widget three"); @@ -106,15 +98,15 @@ server_screen_init () } static int -screen_count (client *c) { +screen_count (Client * c) { int n; n = 0; - LL_Rewind (c->data->screenlist); + LL_Rewind (c->screenlist); do { - if (LL_Get (c->data->screenlist) != NULL) + if (LL_Get (c->screenlist) != NULL) n++; - } while (LL_Next (c->data->screenlist) == 0); + } while (LL_Next (c->screenlist) == 0); return n; } @@ -122,7 +114,7 @@ screen_count (client *c) { int update_server_screen (int timer) { - client *c; + Client * c; int num_clients; /*screen *s;*/ int num_screens; @@ -131,14 +123,22 @@ update_server_screen (int timer) /*strcpy(title, "LCDproc Server");*/ /* Now get info on the number of connected clients...*/ - num_clients = 0; + num_clients = clients_client_count(); + + /* ... and screens */ num_screens = 0; - LL_Rewind (clients); - do { - c = LL_Get (clients); + for (c = clients_getfirst (); c; c = clients_getnext () ) { + num_screens += client_screen_count(c); + } + +/* if (c) { num_clients++; + num_screens += client_screen_count(c); + num_screens += screen_count(c); +*/ + /* LL_Rewind (c->data->screenlist); */ /* do { */ /* s = LL_Get (c->data->screenlist); */ @@ -146,8 +146,11 @@ update_server_screen (int timer) /* num_screens++; */ /* } */ /* } while (LL_Next (c->data->screenlist) == 0); */ + +/* } - } while (LL_Next (clients) == 0); + } +*/ /* Format strings for the appropriate size display... */ if (display_props->height >= 3) { diff --git a/server/serverscreens.h b/server/serverscreens.h index b88a298..f1f7389 100644 --- a/server/serverscreens.h +++ b/server/serverscreens.h @@ -14,7 +14,7 @@ #include "screen.h" -extern screen *server_screen; +extern Screen * server_screen; int server_screen_init (); int update_server_screen (int timer); diff --git a/server/sock.c b/server/sock.c index d9a26c5..31e9efd 100644 --- a/server/sock.c +++ b/server/sock.c @@ -33,8 +33,11 @@ #include "shared/sockets.h" #include "sock.h" +#include "client.h" #include "clients.h" +#include "screen.h" #include "shared/report.h" +#include "screenlist.h" extern char bind_addr[64]; extern int lcd_port; @@ -142,7 +145,7 @@ sock_poll_clients () struct sockaddr_in clientname; size_t size; struct timeval t; - client *c; + Client * c; debug(RPT_INFO, "sock_poll_clients()"); @@ -162,22 +165,26 @@ sock_poll_clients () if (FD_ISSET (i, &read_fd_set)) { if (i == orig_sock) { /* Connection request on original socket. */ - int new; + int new_sock; size = sizeof (clientname); - new = accept (orig_sock, (struct sockaddr *) &clientname, &size); - if (new < 0) { + new_sock = accept (orig_sock, (struct sockaddr *) &clientname, &size); + if (new_sock < 0) { report (RPT_ERR, "sock_poll_clients: Accept error"); return -1; } report (RPT_INFO, "sock_poll_clients: Connect from host %s:%hd on #%d", - inet_ntoa (clientname.sin_addr), ntohs (clientname.sin_port), new); - FD_SET (new, &active_fd_set); + inet_ntoa (clientname.sin_addr), ntohs (clientname.sin_port), new_sock); + FD_SET (new_sock, &active_fd_set); - fcntl (new, F_SETFL, O_NONBLOCK); + fcntl (new_sock, F_SETFL, O_NONBLOCK); - /* TODO: Create new "client" here... (done?)*/ - if (client_create (new) == NULL) { - report( RPT_ERR, "sock_poll_clients: error creating client %i", i); + /* Create new client */ + if ((c = client_create (new_sock)) == NULL) { + report( RPT_ERR, "sock_poll_clients: Error creating client %i", i); + return -1; + } + if (clients_add_client (c) != 0) { + report( RPT_ERR, "sock_poll_clients: Could not add client %i", i); return -1; } } else { @@ -189,10 +196,11 @@ sock_poll_clients () debug (RPT_DEBUG, "sock_poll_clients: ...done"); if (err < 0) { /* TODO: Destroy a "client" here... (done?)*/ - c = client_find_sock (i); + c = clients_find_client_by_sock (i); if (c) { /*sock_send_string(i, "bye\n");*/ client_destroy (c); + clients_remove_client (c); close (i); FD_CLR (i, &active_fd_set); report (RPT_INFO, "sock_poll_clients: Closed connection %i", i); @@ -200,7 +208,6 @@ sock_poll_clients () report (RPT_ERR, "sock_poll_clients: Can't find client %i", i); } } while (err > 0); - } } } @@ -212,7 +219,7 @@ read_from_client (int filedes) { char buffer[MAXMSG]; int nbytes, i; - client *c; + Client * c; report(RPT_DEBUG, "read_from_client()" ); @@ -241,7 +248,7 @@ read_from_client (int filedes) if (buffer[i] == 0) buffer[i] = '\n'; /* Enqueue a "client message" here...*/ - c = client_find_sock (filedes); + c = clients_find_client_by_sock (filedes); if (c) { client_add_message (c, buffer); } else diff --git a/server/widget.c b/server/widget.c index 9f0ea83..eef7f0b 100644 --- a/server/widget.c +++ b/server/widget.c @@ -23,7 +23,8 @@ #include "widget.h" #include "render.h" -char *types[] = { "none", +char *typenames[] = { + "none", "string", "hbar", "vbar", @@ -32,32 +33,38 @@ char *types[] = { "none", "scroller", "frame", "num", - /*"",*/ NULL, }; -static widget *widget_finder (LinkedList * list, char *id); -static int widget_remover (LinkedList * list, widget * w); +//static widget *widget_finder (LinkedList * list, char *id); +//static int widget_remover (LinkedList * list, widget * w); -widget * -widget_create () +Widget * +widget_create (char *id, WidgetType type, Screen * screen) { - widget *w; + Widget * w; - report (RPT_INFO, "widget_create()"); + report (RPT_INFO, "widget_create(%s,%d)", id, type); - w = malloc (sizeof (widget)); + /* Create it */ + w = malloc (sizeof (Widget)); if (!w) { - report (RPT_DEBUG, "widget_create: Error allocating widget"); + report (RPT_DEBUG, "widget_create: Error allocating"); return NULL; } - w->id = NULL; - w->type = 0; + w->id = strdup(id); + if (!w->id) { + report (RPT_DEBUG, "widget_create: Error allocating"); + return NULL; + } + + w->type = type; + w->screen = screen; w->x = 1; w->y = 1; - w->wid = 0; - w->hgt = 0; + w->width = 0; + w->height = 0; w->left = 1; w->top = 1; w->right = 0; @@ -65,22 +72,30 @@ widget_create () w->length = 1; w->speed = 1; w->text = NULL; - w->kids = NULL; + //w->kids = NULL; + if (w->type == WID_FRAME) { + /* create a screen for the frame widget */ + char * frame_name; + frame_name = malloc (strlen("frame_") + strlen(id) + 1); + strcpy (frame_name, "frame_"); + strcat (frame_name, id); + + w->frame_screen = screen_create (frame_name, screen->client); + + free (frame_name); /* not needed anymore */ + } return w; } int -widget_destroy (widget * w) +widget_destroy (Widget * w) { - LinkedList *list; - widget *foo; + debug (RPT_INFO, "widget_destroy(%s)", w->id); if (!w) return -1; - debug (RPT_INFO, "widget_destroy(%s)", w->id); - if (w->id) free (w->id); /*debug(RPT_DEBUG, "widget_destroy: id...");*/ @@ -88,18 +103,13 @@ widget_destroy (widget * w) free (w->text); /*debug(RPT_DEBUG, "widget_destroy: text...");*/ - /* TODO: Free kids!*/ - if (w->kids) { - list = w->kids; - LL_Rewind (list); - do { - foo = LL_Get (list); - if (foo) - widget_destroy (foo); - } while (0 == LL_Next (list)); + if (w->type == WID_FRAME) { + /* TODO: create a screen for the frame widget */ + } - LL_Destroy (list); - w->kids = NULL; + /* Free subscreen of frame widget too */ + if (w->type == WID_FRAME) { + screen_destroy (w->frame_screen); } free (w); @@ -108,254 +118,33 @@ widget_destroy (widget * w) return 0; } -widget * -widget_find (screen * s, char *id) -{ - /*widget *w, *err;*/ - - if (!s) - return NULL; - if (!id) - return NULL; - - debug (RPT_DEBUG, "widget_find(%s)", id); - - return widget_finder (s->widgets, id); -} - -widget * -widget_finder (LinkedList * list, char *id) -{ - widget *w, *err; - - if (!list) - return NULL; - if (!id) - return NULL; - - debug (RPT_DEBUG, "widget_finder(%s)", id); - - LL_Rewind (list); - do { - /*debug(RPT_DEBUG, "widget_finder: Iteration");*/ - w = LL_Get (list); - if (w) { - /*debug(RPT_DEBUG, "widget_finder: ...");*/ - if (0 == strcmp (w->id, id)) { - debug (RPT_DEBUG, "widget_finder: Found %s", id); - return w; - } - /* Search kids recursively*/ - /*debug(RPT_DEBUG, "widget_finder: ...");*/ - if (w->type == WID_FRAME) { - err = widget_finder (w->kids, id); - if (err) - return err; - } - /*debug(RPT_DEBUG, "widget_finder: ...");*/ - } - - } while (LL_Next (list) == 0); - - return NULL; -} - -int -widget_add (screen * s, char *id, char *type, char *in, int sock) +WidgetType +widget_typename_to_type (char * typename) { + WidgetType wid_type = WID_NONE; int i; - int valid = 0; - int wid_type = 0; - widget *w, *parent; - LinkedList *list; - report (RPT_INFO, "widget_add(%s, %s, %s)", id, type, in); - - if (!s) - return -1; - if (!id) - return -1; - - list = s->widgets; - - if (0 == strcmp (id, "heartbeat")) { - s->heartbeat = HEARTBEAT_ON; /* was 1*/ - return 0; - } - - /* Make sure this screen doesn't already exist...*/ - w = widget_find (s, id); - if (w) { - /* already exists*/ - sock_send_string (sock, "huh? You already have a widget with that id#\n"); - return 1; - } - /* Make sure the container, if any, is real*/ - if (in) { - parent = widget_find (s, in); - if (!parent) { - /* no frame to use as parent*/ - sock_send_string (sock, "huh? Frame doesn't exist\n"); - return 3; - } else { - if (parent->type == WID_FRAME) { - list = parent->kids; - if (!list) - report (RPT_DEBUG, "widget_add: Parent has no kids"); - } else { - /* no frame to use as parent*/ - sock_send_string (sock, "huh? Not a frame\n"); - return 4; - } - } - } - - /* Make sure it's a valid widget type*/ - for (i = 1; types[i]; i++) { - if (0 == strcmp (types[i], type)) { - valid = 1; + for (i = 0; typenames[i]; i++) { + if (strcmp (typenames[i], typename) == 0) { wid_type = i; break; /* it's valid: skip out...*/ } } + return wid_type; +} - if (!valid) { - /* invalid widget type*/ - sock_send_string (sock, "huh? Invalid widget type\n"); - return 2; - } +char * +widget_type_to_typename (WidgetType t) +{ + return typenames[t]; +} - debug (RPT_DEBUG, "widget_add: making widget"); - - /* Now, make it...*/ - w = widget_create (); - if (!w) { - report (RPT_ERR, "widget_add: Error creating widget"); - return -1; - } - - w->id = strdup (id); - if (!w->id) { - report (RPT_ERR, "widget_add: Error allocating id"); - return -1; - } - - w->type = wid_type; - - /* Set up the container's widget list...*/ +Widget * +widget_search_subs (Widget * w, char * id) +{ if (w->type == WID_FRAME) { - if (!w->kids) { - w->kids = LL_new (); - if (!w->kids) { - report (RPT_ERR, "widget_add: error allocating kids for frame"); - return -1; - } - } + return screen_find_widget (w->frame_screen, id); + } else { + return NULL; /* no kids */ } - - /* TODO: Check for errors here?*/ - LL_Push (list, (void *) w); - - return 0; -} - -int -widget_remove (screen * s, char *id, int sock) -{ - widget *w; - LinkedList *list; - - report (RPT_INFO, "widget_remove(%s)", id); - - if (!s) - return -1; - if (!id) - return -1; - - list = s->widgets; - - if (0 == strcmp (id, "heartbeat")) { - s->heartbeat = HEARTBEAT_OFF; /* was 0*/ - return 0; - } - /* Make sure this screen *does* exist...*/ - w = widget_find (s, id); - if (!w) { - sock_send_string (sock, "huh? You don't have a widget with that id#\n"); - report (RPT_ERR, "widget_remove: Error finding widget %s", id); - return 1; - } - -/* TODO: Check for errors here? - * TODO: Make this work with frames... - * LL_Remove(list, (void *)w); - */ - - -/* TODO: Check for errors here? - * widget_destroy(w); - */ - - return widget_remover (list, w); - -/* return 0;*/ -} - -int -widget_remover (LinkedList * list, widget * w) -{ - widget *foo, *bar; - int err; - - debug (RPT_DEBUG, "widget_remover"); - - if (!list) - return 0; - if (!w) - return 0; - - /* Search through the list...*/ - LL_Rewind (list); - do { - /* Test each item*/ - foo = LL_Get (list); - if (foo) { - /* Frames require recursion to search and/or destroy*/ - if (foo->type == WID_FRAME) { - /* If removing a frame, kill all its kids, too...*/ - if (foo == w) { - if (!foo->kids) { - debug (RPT_DEBUG, "widget_remover: frame has no kids"); - } else /* Kill the kids...*/ - { - LL_Rewind (foo->kids); - do { - bar = LL_Get (foo->kids); - err = widget_remover (foo->kids, bar); - } while (0 == LL_Next (foo->kids)); - - /* Then kill the parent...*/ - LL_Remove (list, (void *) w); - widget_destroy (w); - } - - } else /* Otherwise, search the frame recursively...*/ - { - if (!foo->kids) { - debug (RPT_DEBUG, "widget_remover: frame has no kids"); - } else - err = widget_remover (foo->kids, w); - - } - } else /* If not a frame, remove it if it matches...*/ - { - if (foo == w) { - LL_Remove (list, (void *) w); - widget_destroy (w); - } - } - } - } while (0 == LL_Next (list)); - - return 0; } diff --git a/server/widget.h b/server/widget.h index cdd4ec4..d66bd61 100644 --- a/server/widget.h +++ b/server/widget.h @@ -12,42 +12,52 @@ #ifndef WIDGET_H #define WIDGET_H -#include "screen.h" - -typedef struct widget { - char *id; - int type; - /* some sort of data here...*/ - int x, y; /* Position*/ - int wid, hgt; /* Size*/ - int left, top, right, bottom; /* bounding rectangle*/ - int length; /* size or direction*/ - int speed; /* For scroller...*/ - char *text; /* text or binary data*/ - LinkedList *kids; /* Frames can contain more widgets...*/ -} widget; +struct Widget; /* These correspond to the index into the "types" array...*/ -#define WID_NONE 0 -#define WID_STRING 1 -#define WID_HBAR 2 -#define WID_VBAR 3 -#define WID_ICON 4 -#define WID_TITLE 5 -#define WID_SCROLLER 6 -#define WID_FRAME 7 -#define WID_NUM 8 +typedef enum WidgetType { + WID_NONE = 0, + WID_STRING, + WID_HBAR, + WID_VBAR, + WID_ICON, + WID_TITLE, + WID_SCROLLER, + WID_FRAME, + WID_NUM +} WidgetType; + +typedef struct Widget { + char *id; + WidgetType type; + Screen * screen; /* What screen is this widget in ? */ + int x, y; /* Position */ + int width, height; /* Visible size */ + int left, top, right, bottom; /* bounding rectangle */ + int length; /* size or direction */ + int speed; /* For scroller... */ + char *text; /* text or binary data */ + struct Screen * frame_screen; /* frame widget get an associated screen */ + //LinkedList *kids; /* Frames can contain more widgets...*/ +} Widget; + +#include "screen.h" #define WID_MAX_DIR 4 -extern char *types[]; +/* Create new widget */ +Widget * widget_create (char *id, WidgetType type, Screen * screen); -widget *widget_create (); -int widget_destroy (widget * w); +/* Destroy a widget */ +int widget_destroy (Widget * w); -widget *widget_find (screen * s, char *id); +/* Convert a widget typename to a widget type */ +WidgetType widget_typename_to_type (char * typename); -int widget_add (screen * s, char *id, char *type, char *in, int sock); -int widget_remove (screen * s, char *id, int sock); +/* Convert a widget typename to a widget type */ +char *widget_type_to_typename (WidgetType t); + +/* Search subwidgets of a widget */ +Widget * widget_search_subs (Widget * w, char * id); #endif