Added support for client supplied menus.

Also modified existing menustuff slightly (on some points I made some
things more consistent).
This commit is contained in:
robijn
2002-06-28 23:35:55 +00:00
parent a621a06268
commit 8ff8857eda
16 changed files with 1154 additions and 402 deletions
+17 -21
View File
@@ -19,6 +19,8 @@
#include "client.h" #include "client.h"
#include "screenlist.h" #include "screenlist.h"
#include "render.h" #include "render.h"
#include "input.h"
#include "menuitem.h"
#include "shared/report.h" #include "shared/report.h"
#include "shared/LL.h" #include "shared/LL.h"
@@ -50,7 +52,7 @@ Client * client_create (int sock)
c->ack = 0; c->ack = 0;
c->name = NULL; c->name = NULL;
c->client_keys = NULL; c->menu = NULL;
c->screenlist = LL_new(); c->screenlist = LL_new();
@@ -74,30 +76,10 @@ client_destroy (Client * c)
client_close_sock (c); 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...*/ /* Clean up the screenlist...*/
debug( RPT_DEBUG, "client_data_destroy: Cleaning screenlist"); debug( RPT_DEBUG, "client_data_destroy: Cleaning screenlist");
for( s=LL_GetFirst (c->screenlist); s; s=LL_GetNext(c->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...*/ /* Free its memory...*/
screen_destroy (s); screen_destroy (s);
/* Note that the screen is not removed from the list because /* Note that the screen is not removed from the list because
@@ -106,6 +88,20 @@ client_destroy (Client * c)
} }
LL_Destroy( c->screenlist); LL_Destroy( c->screenlist);
/* Destroy the client's menu, if it exists */
if (c->menu)
menuitem_destroy (c->menu);
/* Forget client's key reservations */
input_release_client_keys (c);
/* Free client's other data */
c->ack = 0;
/* Clean up the name...*/
if (c->name)
free (c->name);
/* Remove structure */ /* Remove structure */
free (c); free (c);
+20 -9
View File
@@ -1,3 +1,20 @@
/*
* client.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
*
* Defines all the client data and actions.
*/
#include "menu.h"
#include "menuitem.h"
/* These headers are placed here on purpose ! (circular references) */
#ifndef CLIENT_H #ifndef CLIENT_H
#define CLIENT_H #define CLIENT_H
@@ -16,22 +33,16 @@ typedef struct Client {
LinkedList *messages; LinkedList *messages;
/* and other stuff... doesn't matter yet*/ /* The list of screens */
LinkedList *screenlist; LinkedList *screenlist;
/* TO BE REMOVED */ /* Maybe it has created a menu */
char *client_keys; Menu * menu;
/* list of requested keys */
//LinkedList *keylist;
/* list of client supplied menus */
//LinkedList *menulist;
} Client; } Client;
#include "screen.h" #include "screen.h"
/* When a new client connects, set up a new client data struct */ /* When a new client connects, set up a new client data struct */
Client * client_create (int sock); Client * client_create (int sock);
+36 -71
View File
@@ -32,6 +32,7 @@
#include "drivers.h" #include "drivers.h"
#include "render.h" #include "render.h"
#include "client.h" #include "client.h"
#include "input.h"
/*************************************************************** /***************************************************************
* Debugging only.. prints out a list of arguments it receives * Debugging only.. prints out a list of arguments it receives
@@ -165,59 +166,51 @@ client_set_func (Client * c, int argc, char **argv)
* Tells the server the client would like to accept keypresses * Tells the server the client would like to accept keypresses
* of a particular type * of a particular type
* *
* usage: client_add_key <keylist> * usage: client_add_key [-exclusively|-shared] {<key>}+
*/ */
#define BUFLEN 80
int int
client_add_key_func (Client * c, int argc, char **argv) client_add_key_func (Client * c, int argc, char **argv)
{ {
char * keys ; int exclusively = 0;
int argnr;
char errmsg[BUFLEN];
if (!c->ack) if (!c->ack)
return 1; return 1;
if (argc != 2) { if (argc < 2) {
switch (argc) { switch (argc) {
case 1: case 1:
sock_send_string (c->sock, "huh? usage: client_add_key <keylist>\n"); sock_send_string (c->sock, "huh? Usage: client_add_key [-exclusively|-shared] {<key>}+\n");
break;
default:
sock_send_string (c->sock, "huh? Too many parameters...\n");
break; break;
} }
return 0; return 0;
} }
keys = argv[1]; argnr = 1;
debug(RPT_DEBUG, "client_add_key: current client will handle key(s) %s", keys); if( argv[argnr][0] == '-' ) {
if( strcmp( argv[argnr], "-shared") == 0 ) {
if (!c->client_keys) { exclusively = 0;
/* No keys list, create a new one*/ }
c->client_keys = strdup( keys ); else if( strcmp( argv[argnr], "-exclusively") == 0 ) {
} else { exclusively = 1;
/* Add supplied keys to existing list }
* NOTE: There could be duplicates in the resulting list else {
* That's OK, it's the existence of the key in the list snprintf( errmsg, BUFLEN-1, "huh? Invalid option: %s\n", argv[argnr] );
* that's important. We'll be more careful in the delete errmsg[BUFLEN-1] = 0;
* key function. sock_send_string( c->sock, errmsg );
*/ }
char * new ; argnr ++;
int new_len = strlen(c->client_keys) + strlen(keys) + 1 ; }
for ( ; argnr < argc; argnr++ ) {
new = realloc( c->client_keys, new_len ); if( input_reserve_key( argv[argnr], exclusively, c ) < 0 ) {
if( new ) { snprintf( errmsg, BUFLEN-1, "huh? Could not reserve key \"%s\"\n", argv[argnr] );
c->client_keys = new ; errmsg[BUFLEN-1] = 0;
strcat( new, keys ); sock_send_string( c->sock, errmsg );
} else {
sock_send_string(c->sock, "huh? could not allocate memory for new keys\n");
return 0;
} }
} }
sock_send_string(c->sock, "success\n");
if (c->client_keys) {
sock_send_string(c->sock, "success\n");
} else {
sock_send_string(c->sock, "huh? failed\n");
}
return 0; return 0;
} }
@@ -226,52 +219,24 @@ client_add_key_func (Client * c, int argc, char **argv)
* Tells the server the client would NOT like to accept keypresses * Tells the server the client would NOT like to accept keypresses
* of a particular type * of a particular type
* *
* usage: client_del_key <keylist> * usage: client_del_key {<key>}+
*/ */
int int
client_del_key_func (Client * c, int argc, char **argv) client_del_key_func (Client * c, int argc, char **argv)
{ {
char * keys ; int argnr;
if (!c->ack) if (!c->ack)
return 1; return 1;
if (argc != 2) { if (argc < 2) {
if (argc == 1) { sock_send_string (c->sock, "huh? Usage: client_del_key {<key>}+\n");
sock_send_string (c->sock, "huh? usage: client_del_key <keylist>\n"); return 0;
return 0;
} else {
sock_send_string (c->sock, "huh? Too many parameters...\n");
return 0;
}
} }
keys = argv[1] ; for( argnr=1; argnr < argc; argnr++) {
debug(RPT_DEBUG, "client_del_key: Deleting key(s) %s from client_keys", keys); input_release_key( argv[argnr], c );
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"); sock_send_string(c->sock, "success\n");
return 0; return 0;
+1 -4
View File
@@ -12,7 +12,7 @@
* The functions here are to be called only from parse.c's interpreter. * 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 * The client's available function set is defined here, as is the syntax
* for each command. * for each command. <-- TODO !
* *
*/ */
@@ -39,9 +39,6 @@ client_function commands[] = {
{"widget_add", widget_add_func}, {"widget_add", widget_add_func},
{"widget_del", widget_del_func}, {"widget_del", widget_del_func},
{"widget_set", widget_set_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_add_item", menu_add_item_func},
{"menu_del_item", menu_del_item_func}, {"menu_del_item", menu_del_item_func},
{"menu_set_item", menu_set_item_func}, {"menu_set_item", menu_set_item_func},
+579 -60
View File
@@ -19,121 +19,640 @@
* *
*/ */
#include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stddef.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <dlfcn.h>
#include <errno.h> #include <errno.h>
#include "shared/report.h" #include "shared/report.h"
#include "shared/sockets.h" #include "shared/sockets.h"
#include "menu.h"
#include "menuitem.h"
#include "menuscreens.h"
#include "client.h" #include "client.h"
/************************************************************* MenuEventFunc(menu_commands_handler);
* 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;
}
/************************************************************************* /*************************************************************************
* menu_add_item_func
*
* Adds an item to a menu * Adds an item to a menu
* *
* usage: menu_add_item ...? * Usage: menu_add_item <menuid> <newitemid> <type> [<text>]
* You should use "" as id for the client's main menu. This menu will be
* created automatically when you add an item to it the first time.
* You (currently?) cannot create a menu in the main level yourself.
* The names you use for items should be unique for your client.
* The text is the visible text for the item.
*
* The following types are available:
* - menu
* - action
* - checkbox
* - ring (a kind of listbox of one line)
* - slider
* - numeric
* - alpha
*/ */
int int
menu_add_item_func (Client * c, int argc, char **argv) menu_add_item_func (Client * c, int argc, char **argv)
{ {
char * menu_id;
char * item_id;
char * text = NULL;
Menu * menu = NULL;
MenuItem * item;
MenuItemType itemtype;
if (!c->ack) if (!c->ack)
return 1; return 1;
sock_send_string (c->sock, "huh? Not implemented yet.\n"); if (!c->name) {
sock_send_string (c->sock, "huh? You need to give your client a name first\n");
return 0;
}
if ((argc < 4 )) {
sock_send_string (c->sock, "huh? Usage: menu_add_item <menuid> <newitemid> <type> [<text>]\n");
return 0;
}
menu_id = argv[1];
item_id = argv[2];
/* Does the client have a menu already ? */
if (!c->menu) {
/* We need to create it */
c->menu = menu_create ("_client_menu_", menu_commands_handler, c->name, c);
menu_add_item (main_menu, c->menu);
}
if ( menu_id[0] == 0 ) {
/* No menu specified = client's main menu */
menu = c->menu;
} else {
/* A specified menu */
menu = menu_find_item (c->menu, menu_id, true);
}
if (!menu) {
sock_send_string (c->sock, "huh? Cannot find menu id\n");
return 0;
}
item = menu_find_item (c->menu, item_id, true);
if (item) {
sock_send_string (c->sock, "huh? Item id already in use\n");
return 0;
}
/* Find menuitem type */
itemtype = menuitem_typename_to_type (argv[3]);
if (itemtype == -1) {
sock_send_string (c->sock, "huh? Invalid menuitem type\n");
return 0;
}
/* Is a text given ? */
if (argc >= 5) {
text = argv[4];
}
else {
text = "";
}
/* Create the menuitem */
switch (itemtype) {
case MENUITEM_MENU:
item = menu_create (item_id, menu_commands_handler, text, c);
break;
case MENUITEM_ACTION:
item = menuitem_create_action (item_id, menu_commands_handler, text,
MENURESULT_NONE);
break;
case MENUITEM_CHECKBOX:
item = menuitem_create_checkbox (item_id, menu_commands_handler, text,
false, false);
break;
case MENUITEM_RING:
item = menuitem_create_ring (item_id, menu_commands_handler, text,
"", 0);
break;
case MENUITEM_SLIDER:
item = menuitem_create_slider (item_id, menu_commands_handler, text,
"", "", 0, 100, 1, 25);
break;
case MENUITEM_NUMERIC:
item = menuitem_create_numeric (item_id, menu_commands_handler, text,
0, 100, 0);
break;
case MENUITEM_ALPHA:
item = menuitem_create_alpha (item_id, menu_commands_handler, text,
0, 0, 10, true, false, true, "-./", "");
break;
}
menu_add_item (menu, item);
sock_send_string(c->sock, "success\n");
return 0; return 0;
} }
/************************************************************************* /*************************************************************************
* menu_del_item_func
*
* Deletes an item from a menu * Deletes an item from a menu
* *
+ usage: menu_del_item ...? * Usage: menu_del_item <menuid> <itemid>
* The given item in the given menu will be deleted. If you have deleted all
* the items from your client menu, that menu will automatically be removed.
*/ */
int int
menu_del_item_func (Client * c, int argc, char **argv) menu_del_item_func (Client * c, int argc, char **argv)
{ {
Menu * menu;
MenuItem * item;
char * menu_id;
char * item_id;
if (!c->ack) if (!c->ack)
return 1; return 1;
sock_send_string (c->sock, "huh? Not implemented yet.\n"); if ((argc < 4 )) {
sock_send_string (c->sock, "huh? Usage: menu_del_item <menuid> <itemid>\n");
return 0;
}
menu_id = argv[1];
item_id = argv[2];
if ( menu_id[0] == 0 ) {
/* No menu specified = client's main menu */
menu = c->menu;
} else {
/* A specified menu */
menu = menu_find_item (c->menu, menu_id, true);
}
if (!menu) {
sock_send_string (c->sock, "huh? Cannot find menu id\n");
return 0;
}
item = menu_find_item (c->menu, item_id, true);
if (!item) {
sock_send_string (c->sock, "huh? Cannot find item\n");
return 0;
}
menu_remove_item (menu, item);
menuitem_destroy (item);
sock_send_string(c->sock, "success\n");
return 0; return 0;
} }
/************************************************************************** /**************************************************************************
* menu_set_item_func
* Sets the info about a menu item * Sets the info about a menu item
* *
* For example, text displayed, widget type, value, etc... * For example, text displayed, value, etc...
* *
* usage: menu_set_item ...? * Usage: menu_set_item <menuid> <itemid> {<option>}+
* The following parameters can be set per item:
* (you should include the - in the option)
*
* For all types:
* -text "text" ("")
* Sets the visible text.
*
* menu:
* (has no extra settable options)
*
* action:
* -menu_result none|close|quit (none)
* Sets what to do with the menu when this action is selected:
* - none: the menu stays as it is.
* - close: the menu closes and returns to a higher level.
* - quit: quits the menu completely so you can foreground your app.
*
* checkbox:
* -value off|on|gray (off)
* Sets its current value.
* -allow_gray false|true (false)
* Sets if a grayed checkbox is allowed.
*
* ring:
* -value <int> (0)
* Sets the index in the stringlist that is currently selected.
* -strings <string> (empty)
* The subsequent strings that can be selected. They should be
* tab-separated in ONE string.
*
* slider:
* -value <int> (0)
* Sets its current value.
* -mintext <string> ("")
* -maxtex <string> ("")
* Text at the minimal and maximal side. On small displays these might
* not be displayed.
* -minvalue <int> (0)
* -maxvalue <int> (100)
* The minimum and maximum value of the slider.
* -stepsize <int> (1)
* The stepsize of the slider. If you use 0, you can control it yourself
* completely.
*
* numeric:
* -value <int> (0)
* Sets its current value.
* -minvalue <int> (0)
* -maxvalue <int> (100)
* The minimum and maximum value that are allowed. If you make one of
* them negative, the user will be able to enter negative numbers too.
* Maybe floats will work too in the future.
*
* alpha:
* -value <string>
* Sets its current value. ("")
* -password_char <char> (none)
* -minlength <int> (0)
* -maxlength <int> (10)
* Set the minimum and maximum allowed length.
* -allow_caps false|true (true)
* -allow_noncaps false|true (false)
* -allow_numbers false|true (true)
* Allows these groups of characters.
* -allowed_extra <string> ("")
* The chars in this string are also allowed.
*
* Hmm, this is getting very big. We might need a some real parser after all.
*/ */
int int
menu_set_item_func (Client * c, int argc, char **argv) menu_set_item_func (Client * c, int argc, char **argv)
{ {
typedef enum AttrType { NOVALUE, BOOLEAN, CHECKBOX_VALUE, SHORT, INT,
FLOAT, STRING } AttrType;
struct OptionTable {
MenuItemType menuitem_type; /* For what MenuItem type is
the option ?
Use -1 for ALL types. */
char * name; /* The option concerned */
AttrType attr_type; /* Type of value */
int attr_offset; /* Where to put it the value
in the structure.
Use -1 to process it
yourself. */
/* Watch out with STRING, it will free() the current value
* and reallocate for the new value !! If you don't want
* that, use -1 for offset, to process it yourself. */
} option_table[] = {
{ -1, "text", STRING, offsetof(MenuItem,text) },
{ MENUITEM_ACTION, "menu_result", STRING, -1 },
{ MENUITEM_CHECKBOX, "value", CHECKBOX_VALUE, offsetof(MenuItem,data.checkbox.value) },
{ MENUITEM_CHECKBOX, "allow_gray", BOOLEAN, offsetof(MenuItem,data.checkbox.allow_gray) },
{ MENUITEM_RING, "value", SHORT, offsetof(MenuItem,data.ring.value) },
{ MENUITEM_RING, "strings", STRING, -1 },
{ MENUITEM_SLIDER, "value", INT, offsetof(MenuItem,data.slider.value) },
{ MENUITEM_SLIDER, "minvalue", INT, offsetof(MenuItem,data.slider.minvalue) },
{ MENUITEM_SLIDER, "maxvalue", INT, offsetof(MenuItem,data.slider.maxvalue) },
{ MENUITEM_SLIDER, "stepsize", INT, offsetof(MenuItem,data.slider.stepsize) },
{ MENUITEM_SLIDER, "mintext", STRING, offsetof(MenuItem,data.slider.mintext) },
{ MENUITEM_SLIDER, "maxtext", STRING, offsetof(MenuItem,data.slider.maxtext) },
{ MENUITEM_NUMERIC, "value", INT, offsetof(MenuItem,data.numeric.value) },
{ MENUITEM_NUMERIC, "minvalue", INT, offsetof(MenuItem,data.numeric.minvalue) },
{ MENUITEM_NUMERIC, "maxvalue", INT, offsetof(MenuItem,data.numeric.maxvalue) },
/*{ MENUITEM_NUMERIC, "allow_decimals",BOOLEAN, offsetof(MenuItem,data.numeric.allow_decimals) },*/
{ MENUITEM_ALPHA, "value", STRING, offsetof(MenuItem,data.alpha.value) },
{ MENUITEM_ALPHA, "minlength", SHORT, offsetof(MenuItem,data.alpha.minlength) },
{ MENUITEM_ALPHA, "maxlength", SHORT, offsetof(MenuItem,data.alpha.maxlength) },
{ MENUITEM_ALPHA, "password_char",STRING, -1 },
{ MENUITEM_ALPHA, "allow_caps", BOOLEAN, offsetof(MenuItem,data.alpha.allow_caps) },
{ MENUITEM_ALPHA, "allow_noncaps",BOOLEAN, offsetof(MenuItem,data.alpha.allow_noncaps) },
{ MENUITEM_ALPHA, "allow_numbers",BOOLEAN, offsetof(MenuItem,data.alpha.allow_numbers) },
{ MENUITEM_ALPHA, "allowed_extra",STRING, offsetof(MenuItem,data.alpha.allowed_extra) },
{ -1, NULL, -1, -1 }
};
bool bool_value = false;
CheckboxValue checkbox_value = CHECKBOX_OFF;
short short_value = 0;
int int_value = 0;
float float_value = 0;
char * string_value = NULL;
Menu * menu;
MenuItem * item;
char * menu_id;
char * item_id;
int argnr;
char buf[80];
if (!c->ack) if (!c->ack)
return 1; return 1;
sock_send_string (c->sock, "huh? Not implemented yet.\n"); if ((argc < 4 )) {
sock_send_string (c->sock, "huh? Usage: menu_set_item <menuid> <itemid> {<option>}+\n");
return 0;
}
menu_id = argv[1];
item_id = argv[2];
if ( menu_id[0] == 0 ) {
/* No menu specified = client's main menu */
menu = c->menu;
} else {
/* A specified menu */
menu = menu_find_item (c->menu, menu_id, true);
}
if (!menu) {
sock_send_string (c->sock, "huh? Cannot find menu id\n");
return 0;
}
item = menu_find_item (c->menu, item_id, true);
if (!item) {
sock_send_string (c->sock, "huh? Cannot find item\n");
return 0;
}
/* Scan all arguments */
for( argnr = 3; argnr < argc; argnr ++) {
int option_nr = -1;
int found_option_name = 0;
int error = 0;
void * location;
char * p;
/* Find the option in the table */
if( argv[argnr][0] == '-' ) {
int i;
for( i=0; option_table[i].name; i++ ) {
if( strcmp( argv[argnr]+1, option_table[i].name ) == 0 ) {
found_option_name = 1;
if( item->type == option_table[i].menuitem_type
|| option_table[i].menuitem_type == -1 ) {
option_nr = i;
}
}
}
}
else {
snprintf( buf, sizeof(buf), "huh? Found non-option: \"%.40s\"\n", argv[argnr] );
sock_send_string (c->sock, buf);
continue; /* Skip to next arg */
}
if( option_nr == -1 ) {
if( found_option_name ) {
snprintf( buf, sizeof(buf), "huh? Option not valid for menuitem type: \"%.40s\"\n", argv[argnr] );
} else {
snprintf( buf, sizeof(buf), "huh? Unknown option: \"%.40s\"\n", argv[argnr] );
}
sock_send_string (c->sock, buf);
continue; /* Skip to next arg */
}
/* OK, we now know we have an option that is valid for the item type. */
/* Check for value */
if( option_table[option_nr].attr_type != NOVALUE ) {
if( argnr + 1 >= argc ) {
snprintf( buf, sizeof(buf), "huh? Missing value at option: \"%.40s\"\n", argv[argnr] );
sock_send_string (c->sock, buf);
continue; /* Skip to next arg (probably is not existing :) */
}
}
/* Process the value that goes with the option */
location = (void*)item + option_table[option_nr].attr_offset;
switch( option_table[option_nr].attr_type ) {
case NOVALUE:
break;
case BOOLEAN:
if( strcmp( argv[argnr+1], "false" ) == 0 ) {
bool_value = false;
} else if( strcmp( argv[argnr+1], "true" ) == 0 ) {
bool_value = true;
} else {
error = 1;
break;
}
if( option_table[option_nr].attr_offset != -1 ) {
*(bool *)location = bool_value;
}
break;
case CHECKBOX_VALUE:
if( strcmp( argv[argnr+1], "off" ) == 0 ) {
checkbox_value = CHECKBOX_OFF;
} else if( strcmp( argv[argnr+1], "on" ) == 0 ) {
checkbox_value = CHECKBOX_ON;
} else if( strcmp( argv[argnr+1], "gray" ) == 0 ) {
checkbox_value = CHECKBOX_GRAY;
} else {
error = 1;
break;
}
if( option_table[option_nr].attr_offset != -1 ) {
*(CheckboxValue *)location = checkbox_value;
}
break;
case SHORT:
short_value = strtol( argv[argnr+1], &p, 0 );
if( argv[argnr+1][0] == 0
|| *p != 0 ) {
error = 1;
break;
}
if( option_table[option_nr].attr_offset != -1 ) {
*(short*)location = short_value;
}
break;
case INT:
int_value = strtol( argv[argnr+1], &p, 0 );
if( argv[argnr+1][0] == 0
|| *p != 0 ) {
error = 1;
break;
}
if( option_table[option_nr].attr_offset != -1 ) {
*(int*)location = int_value;
}
break;
case FLOAT:
float_value = strtod( argv[argnr+1], &p );
if( argv[argnr+1][0] == 0
|| *p != 0 ) {
error = 1;
break;
}
if( option_table[option_nr].attr_offset != -1 ) {
*(float*)location = float_value;
}
break;
case STRING:
string_value = argv[argnr+1];
if( option_table[option_nr].attr_offset != -1 ) {
free( *(char**)location );
*(char**)location = strdup( string_value );
}
break;
}
switch( error ) {
case 1:
snprintf( buf, sizeof(buf), "huh? Could not interpret value at option: \"%.40s\"\n", argv[argnr] );
sock_send_string (c->sock, buf);
argnr ++;
continue; /* Skip current option and the invalid value */
}
/* And at last process extra things for certain options.
* Most useful for the attr_offset==-1 stuff. */
switch (item->type) {
case MENUITEM_ACTION:
if( strcmp( argv[argnr]+1, "menu_result" ) == 0 ) {
if( strcmp( argv[argnr+1], "none" ) == 0 ) {
item->data.action.menu_result = MENURESULT_NONE;
} else if( strcmp( argv[argnr+1], "close" ) == 0 ) {
item->data.action.menu_result = MENURESULT_CLOSE;
} else if( strcmp( argv[argnr+1], "quit" ) == 0 ) {
item->data.action.menu_result = MENURESULT_QUIT;
} else {
error = 1;
}
}
break;
case MENUITEM_SLIDER:
if( item->data.slider.value < item->data.slider.minvalue ) {
item->data.slider.value = item->data.slider.minvalue;
} else if( item->data.slider.value > item->data.slider.maxvalue ) {
item->data.slider.value = item->data.slider.maxvalue;
}
break;
case MENUITEM_RING:
if( strcmp( argv[argnr]+1, "strings" ) == 0 ) {
free (item->data.ring.strings);
item->data.ring.strings = tablist2linkedlist (string_value);
}
item->data.ring.value %= LL_Length( item->data.ring.strings );
break;
case MENUITEM_NUMERIC:
menuitem_reset (item);
break;
case MENUITEM_ALPHA:
if( strcmp( argv[argnr]+1, "password_char" ) == 0 ) {
item->data.alpha.password_char = string_value[0];
}
else if( strcmp( argv[argnr]+1, "maxlength" ) == 0 ) {
char * new_buf;
if( short_value < 0 || short_value > 1000 ) {
error = 2;
break;
}
new_buf = malloc( short_value + 1 );
strncpy( new_buf, item->data.alpha.value, short_value );
new_buf[short_value] = 0; /* terminate */
free( item->data.alpha.value );
item->data.alpha.value = new_buf;
free( item->data.alpha.edit_str );
item->data.alpha.edit_str = malloc( short_value + 1 );
item->data.alpha.edit_str[0] = 0;
}
else if( strcmp( argv[argnr]+1, "value" ) == 0 ) {
strncpy( item->data.alpha.value, string_value, item->data.alpha.maxlength );
item->data.alpha.value[ item->data.alpha.maxlength ] = 0; /* terminate */
}
menuitem_reset (item);
break;
default:
break;
}
switch( error ) {
case 1:
snprintf( buf, sizeof(buf), "huh? Could not interpret value at option: \"%.40s\"\n", argv[argnr] );
sock_send_string (c->sock, buf);
continue; /* Skip to next arg and retry it as an option */
case 2:
snprintf( buf, sizeof(buf), "huh? Value out of range at option: \"%.40s\"\n", argv[argnr] );
sock_send_string (c->sock, buf);
argnr ++;
continue; /* Skip current option and the invalid value */
}
if( active_menuitem && menuscreen ) {
/* We need to rebuild the screen */
menuitem_build_screen( active_menuitem, menuscreen );
menuitem_update_screen( active_menuitem, menuscreen );
}
if( option_table[option_nr].attr_type != NOVALUE ) {
/* Skip the now used argument */
argnr ++;
}
}
sock_send_string(c->sock, "success\n");
return 0; return 0;
} }
MenuEventFunc (menu_commands_handler)
{
char buf[80] = "";
Client * c;
MenuItem * i;
/* Compose message */
if( event == MENUEVENT_UPDATE
|| event == MENUEVENT_MINUS
|| event == MENUEVENT_PLUS ) {
switch( item->type ) {
case MENUITEM_CHECKBOX:
snprintf (buf, sizeof(buf)-1, "menuevent %s %.40s %s\n",
menuitem_eventtype_to_eventtypename(event),
item->id, ((char*[]){"off","on","gray"})[item->data.checkbox.value] );
break;
case MENUITEM_SLIDER:
snprintf (buf, sizeof(buf)-1, "menuevent %s %.40s %d\n",
menuitem_eventtype_to_eventtypename(event),
item->id, item->data.slider.value );
break;
case MENUITEM_RING:
snprintf (buf, sizeof(buf)-1, "menuevent %s %.40s %d\n",
menuitem_eventtype_to_eventtypename(event),
item->id, item->data.ring.value );
break;
case MENUITEM_NUMERIC:
snprintf (buf, sizeof(buf)-1, "menuevent %s %.40s %d\n",
menuitem_eventtype_to_eventtypename(event),
item->id, item->data.numeric.value );
break;
case MENUITEM_ALPHA:
snprintf (buf, sizeof(buf)-1, "menuevent %s %.40s %.40s\n",
menuitem_eventtype_to_eventtypename(event),
item->id, item->data.alpha.value );
break;
default:
snprintf (buf, sizeof(buf)-1, "menuevent %s %.40s\n",
menuitem_eventtype_to_eventtypename(event),
item->id);
}
}
else {
snprintf (buf, sizeof(buf)-1, "menuevent %s %.40s\n",
menuitem_eventtype_to_eventtypename(event),
item->id);
}
buf[sizeof(buf)-1] = 0;
/* Where should the message go to ? */
for( i = item; i && i->parent != main_menu; i = item->parent );
c = (Client *) i->data.menu.association;
if( !c ) {
report( RPT_ERR, "%s: Could not find client of item \"%s\"", __FUNCTION__, item->id );
return -1;
}
/* Send it */
sock_send_string (c->sock, buf);
return 0;
}
+2 -3
View File
@@ -195,6 +195,8 @@ main (int argc, char **argv)
/* Startup the server*/ /* Startup the server*/
ESSENTIAL( init_drivers() ); ESSENTIAL( init_drivers() );
ESSENTIAL( init_sockets() ); ESSENTIAL( init_sockets() );
ESSENTIAL( init_input() );
ESSENTIAL( init_menu() );
ESSENTIAL( init_screens() ); ESSENTIAL( init_screens() );
ESSENTIAL( drop_privs(user) ); ESSENTIAL( drop_privs(user) );
@@ -212,9 +214,6 @@ main (int argc, char **argv)
} }
#endif #endif
ESSENTIAL( init_input() );
ESSENTIAL( init_menu() );
do_mainloop(); do_mainloop();
/* This loop never stops; we'll get out only with a signal...*/ /* This loop never stops; we'll get out only with a signal...*/
+40 -29
View File
@@ -26,6 +26,7 @@
#include "config.h" #include "config.h"
#include "menuitem.h"
#include "menu.h" #include "menu.h"
#include "shared/report.h" #include "shared/report.h"
#include "drivers.h" #include "drivers.h"
@@ -93,7 +94,7 @@ menu_destroy_all_items (Menu *menu)
} }
} }
MenuItem *menu_find_item (Menu *menu, char *id) MenuItem *menu_find_item (Menu *menu, char *id, bool recursive)
{ {
MenuItem * item; MenuItem * item;
@@ -103,6 +104,13 @@ MenuItem *menu_find_item (Menu *menu, char *id)
if ( strcmp(item->id, id) == 0 ) { if ( strcmp(item->id, id) == 0 ) {
return item; return item;
} }
else if (recursive && item->type == MENUITEM_MENU) {
MenuItem * res;
res = menu_find_item (item, id, recursive);
if (res) {
return res;
}
}
} }
return NULL; return NULL;
} }
@@ -262,23 +270,30 @@ void menu_update_screen (MenuItem *menu, Screen *s)
} }
break; break;
case MENUITEM_RING: case MENUITEM_RING:
/* Limit string length and add ringstring */ if (subitem->data.ring.value >= LL_Length(subitem->data.ring.strings)) {
p = LL_GetByIndex (subitem->data.ring.strings, subitem->data.ring.value); /* No strings available */
if (strlen(p) > display_props->width - 3) { memcpy (w->text, subitem->text, display_props->width - 2);
short a = display_props->width - 3; w->text[ display_props->width - 2 ] = 0;
/* We need to limit the ring string and DON'T
* display the item text */
strcpy (w->text, " ");
memcpy (w->text + 1, p, a);
w->text[a + 1] = 0;
} }
else { else {
short b = display_props->width - 2 - strlen (p); /* Limit string length and add ringstring */
short c = min (strlen (subitem->text), b - 1); p = LL_GetByIndex (subitem->data.ring.strings, subitem->data.ring.value);
/* We don't limit the ring string */ if (strlen(p) > display_props->width - 3) {
memset (w->text, ' ', b); short a = display_props->width - 3;
memcpy (w->text, subitem->text, c); /* We need to limit the ring string and DON'T
strcpy (w->text + b, p); * display the item text */
strcpy (w->text, " ");
memcpy (w->text + 1, p, a);
w->text[a + 1] = 0;
}
else {
short b = display_props->width - 2 - strlen (p);
short c = min (strlen (subitem->text), b - 1);
/* We don't limit the ring string */
memset (w->text, ' ', b);
memcpy (w->text, subitem->text, c);
strcpy (w->text + b, p);
}
} }
break; break;
default: default:
@@ -324,12 +339,8 @@ MenuResult menu_handle_input (Menu *menu, MenuToken token, char * key)
switch (subitem->type) { switch (subitem->type) {
case MENUITEM_ACTION: case MENUITEM_ACTION:
if (subitem->event_func) if (subitem->event_func)
subitem->event_func (subitem, MENUEVENT_ENTER); subitem->event_func (subitem, MENUEVENT_SELECT);
if (subitem->data.action.quit_menu) return subitem->data.action.menu_result; return MENURESULT_QUIT;
return MENURESULT_QUIT;
if (subitem->data.action.close_menu)
return MENURESULT_CLOSE;
return MENURESULT_OK;
case MENUITEM_CHECKBOX: case MENUITEM_CHECKBOX:
if (subitem->data.checkbox.allow_gray) { if (subitem->data.checkbox.allow_gray) {
subitem->data.checkbox.value = (subitem->data.checkbox.value + 1) % 3; subitem->data.checkbox.value = (subitem->data.checkbox.value + 1) % 3;
@@ -339,18 +350,18 @@ MenuResult menu_handle_input (Menu *menu, MenuToken token, char * key)
} }
if (subitem->event_func) if (subitem->event_func)
subitem->event_func (subitem, MENUEVENT_UPDATE); subitem->event_func (subitem, MENUEVENT_UPDATE);
return MENURESULT_OK; return MENURESULT_NONE;
case MENUITEM_RING: case MENUITEM_RING:
subitem->data.ring.value = (subitem->data.ring.value + 1) % LL_Length (subitem->data.ring.strings); subitem->data.ring.value = (subitem->data.ring.value + 1) % LL_Length (subitem->data.ring.strings);
if (subitem->event_func) if (subitem->event_func)
subitem->event_func (subitem, MENUEVENT_UPDATE); subitem->event_func (subitem, MENUEVENT_UPDATE);
return MENURESULT_OK; return MENURESULT_NONE;
case MENUITEM_MENU: case MENUITEM_MENU:
case MENUITEM_SLIDER: case MENUITEM_SLIDER:
case MENUITEM_NUMERIC: case MENUITEM_NUMERIC:
case MENUITEM_ALPHA: case MENUITEM_ALPHA:
if (subitem->event_func) //if (subitem->event_func)
subitem->event_func (subitem, MENUEVENT_ENTER); // subitem->event_func (subitem, MENUEVENT_ENTER);
return MENURESULT_ENTER; return MENURESULT_ENTER;
default: default:
break; break;
@@ -368,7 +379,7 @@ MenuResult menu_handle_input (Menu *menu, MenuToken token, char * key)
menu->data.menu.scroll --; menu->data.menu.scroll --;
} }
} }
return MENURESULT_OK; return MENURESULT_NONE;
case MENUTOKEN_DOWN: case MENUTOKEN_DOWN:
if (menu->data.menu.selector_pos < LL_Length(menu->data.menu.contents) - 1) { if (menu->data.menu.selector_pos < LL_Length(menu->data.menu.contents) - 1) {
menu->data.menu.selector_pos ++; menu->data.menu.selector_pos ++;
@@ -376,10 +387,10 @@ MenuResult menu_handle_input (Menu *menu, MenuToken token, char * key)
if (menu->data.menu.selector_pos - menu->data.menu.scroll + 2 > display_props->height) { if (menu->data.menu.selector_pos - menu->data.menu.scroll + 2 > display_props->height) {
menu->data.menu.scroll ++; menu->data.menu.scroll ++;
} }
return MENURESULT_OK; return MENURESULT_NONE;
case MENUTOKEN_OTHER: case MENUTOKEN_OTHER:
/* TODO: move to the selected number and enter it */ /* TODO: move to the selected number and enter it */
return MENURESULT_OK; return MENURESULT_NONE;
} }
return MENURESULT_ERROR; return MENURESULT_ERROR;
} }
+10 -11
View File
@@ -8,20 +8,15 @@
* Copyright (c) 1999, William Ferrell, Scott Scriven * Copyright (c) 1999, William Ferrell, Scott Scriven
* *
* Defines all the menu data and actions. * Defines all the menu data and actions.
*
*/ */
#include "menuitem.h"
/* These headers are placed here on purpose ! (circular references) */
#ifndef MENU_H #ifndef MENU_H
#define MENU_H #define MENU_H
struct MenuData;
#include "menuitem.h"
#include "shared/LL.h"
#include "screen.h"
#ifndef bool #ifndef bool
# define bool short # define bool short
# define true 1 # define true 1
@@ -31,11 +26,15 @@ struct MenuData;
#define min(a,b) (((a) < (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b)) #define max(a,b) (((a) > (b)) ? (a) : (b))
#include "shared/LL.h"
typedef MenuItem Menu; typedef MenuItem Menu;
/* A Menu is a MenuItem too. /* A Menu is a MenuItem too.
* This definition is only for better understanding of this code. * This definition is only for better understanding of this code.
*/ */
#include "screen.h"
Menu *menu_create (char *id, MenuEventFunc(*event_func), Menu *menu_create (char *id, MenuEventFunc(*event_func),
char *text, void *association); char *text, void *association);
/* Creates a new menu. /* Creates a new menu.
@@ -86,8 +85,8 @@ static inline MenuItem *menu_get_current_item (Menu *menu)
menu->data.menu.selector_pos); menu->data.menu.selector_pos);
} }
MenuItem *menu_find_item (Menu *menu, char *id); MenuItem *menu_find_item (Menu *menu, char *id, bool recursive);
/* Retrieves the first item from the list of items in the menu. */ /* Finds an item in the menu by the given id. */
void menu_reset (Menu *menu); void menu_reset (Menu *menu);
/* Resets it to initial state. /* Resets it to initial state.
+134 -80
View File
@@ -24,6 +24,8 @@
#define MAX_NUMERIC_LEN 40 #define MAX_NUMERIC_LEN 40
char *error_strs[] = {"", "Out of range", "Too long", "Too short"}; char *error_strs[] = {"", "Out of range", "Too long", "Too short"};
char *menuitemtypenames[] = {"menu", "action", "checkbox", "ring", "slider", "numeric", "alpha"};
char *menueventtypenames[] = {"select", "update", "plus", "minus"};
void menuitem_destroy_action (MenuItem *item); void menuitem_destroy_action (MenuItem *item);
void menuitem_destroy_checkbox (MenuItem *item); void menuitem_destroy_checkbox (MenuItem *item);
@@ -43,9 +45,10 @@ void menuitem_update_screen_slider (MenuItem *item, Screen *s);
void menuitem_update_screen_numeric (MenuItem *item, Screen *s); void menuitem_update_screen_numeric (MenuItem *item, Screen *s);
void menuitem_update_screen_alpha (MenuItem *item, Screen *s); void menuitem_update_screen_alpha (MenuItem *item, Screen *s);
MenuResult menuitem_handle_input_slider (MenuItem *item, MenuToken token, char * key); MenuResult menuitem_process_input_slider (MenuItem *item, MenuToken token, char * key);
MenuResult menuitem_handle_input_numeric (MenuItem *item, MenuToken token, char * key); MenuResult menuitem_process_input_numeric (MenuItem *item, MenuToken token, char * key);
MenuResult menuitem_handle_input_alpha (MenuItem *item, MenuToken token, char * key); MenuResult menuitem_process_input_alpha (MenuItem *item, MenuToken token, char * key);
/******** FUNCTION TABLES ********/ /******** FUNCTION TABLES ********/
/* Tables with functions to call for all different item types */ /* Tables with functions to call for all different item types */
@@ -54,6 +57,7 @@ void (*destructor_table[NUM_ITEMTYPES] ) (MenuItem *item) =
{ {
menu_destroy, menu_destroy,
NULL, NULL,
NULL,
menuitem_destroy_ring, menuitem_destroy_ring,
menuitem_destroy_slider, menuitem_destroy_slider,
menuitem_destroy_numeric, menuitem_destroy_numeric,
@@ -90,15 +94,15 @@ void (*update_screen_table[NUM_ITEMTYPES] ) (MenuItem *item, Screen *s) =
menuitem_update_screen_alpha menuitem_update_screen_alpha
}; };
MenuResult (*handle_input_table[NUM_ITEMTYPES] ) (MenuItem *item, MenuToken token, char *key) = MenuResult (*process_input_table[NUM_ITEMTYPES] ) (MenuItem *item, MenuToken token, char *key) =
{ {
menu_handle_input, menu_handle_input,
NULL, NULL,
NULL, NULL,
NULL, NULL,
menuitem_handle_input_slider, menuitem_process_input_slider,
menuitem_handle_input_numeric, menuitem_process_input_numeric,
menuitem_handle_input_alpha menuitem_process_input_alpha
}; };
/******** METHODS ********/ /******** METHODS ********/
@@ -138,16 +142,15 @@ MenuItem *menuitem_create (MenuItemType type, char *id, MenuEventFunc(*event_fun
} }
MenuItem *menuitem_create_action (char *id, MenuEventFunc(*event_func), MenuItem *menuitem_create_action (char *id, MenuEventFunc(*event_func),
char *text, bool close_menu, bool quit_menu) char *text, MenuResult menu_result)
{ {
MenuItem *new_item; MenuItem *new_item;
debug (RPT_DEBUG, "%s( id=\"%s\", event_func=%p, text=\"%s\", close_menu=%d )", debug (RPT_DEBUG, "%s( id=\"%s\", event_func=%p, text=\"%s\", close_menu=%d )",
__FUNCTION__, id, event_func, text, close_menu); __FUNCTION__, id, event_func, text, menu_result);
new_item = menuitem_create (MENUITEM_ACTION, id, event_func, text); new_item = menuitem_create (MENUITEM_ACTION, id, event_func, text);
new_item->data.action.close_menu = close_menu; new_item->data.action.menu_result = menu_result;
new_item->data.action.quit_menu = quit_menu;
return new_item; return new_item;
} }
@@ -171,33 +174,12 @@ MenuItem *menuitem_create_ring (char *id, MenuEventFunc(*event_func),
char *text, char *strings, short value) char *text, char *strings, short value)
{ {
MenuItem *new_item; MenuItem *new_item;
char *tabptr, *p, *new_s;
debug (RPT_DEBUG, "%s( id=\"%s\", event_func=%p, text=\"%s\", strings=\"%s\", value=%d )", debug (RPT_DEBUG, "%s( id=\"%s\", event_func=%p, text=\"%s\", strings=\"%s\", value=%d )",
__FUNCTION__, id, event_func, text, strings, value); __FUNCTION__, id, event_func, text, strings, value);
new_item = menuitem_create (MENUITEM_RING, id, event_func, text); new_item = menuitem_create (MENUITEM_RING, id, event_func, text);
new_item->data.ring.strings = tablist2linkedlist (strings);
/* parse strings */
p = strings;
new_item->data.ring.strings = LL_new();
while ((tabptr = strchr(p, '\t')) != NULL) {
int len = (int)(tabptr - p);
/* Alloc and copy substring */
new_s = malloc (len + 1);
strncpy (new_s, p, len);
new_s[len] = 0;
LL_Push (new_item->data.ring.strings, new_s);
/* Go to next string */
p = tabptr + 1;
}
/* Add last string */
new_s = strdup (p);
LL_Push (new_item->data.ring.strings, new_s);
new_item->data.ring.value = value; new_item->data.ring.value = value;
return new_item; return new_item;
@@ -246,7 +228,6 @@ MenuItem *menuitem_create_alpha (char *id, MenuEventFunc(*event_func),
char *allowed_extra, char *value) char *allowed_extra, char *value)
{ {
MenuItem *new_item; MenuItem *new_item;
char * chars;
debug (RPT_DEBUG, "%s( id=\"%s\", event_func=%p, text=\"%s\", password_char=%d, maxlength=%d, value=\"%s\" )", debug (RPT_DEBUG, "%s( id=\"%s\", event_func=%p, text=\"%s\", password_char=%d, maxlength=%d, value=\"%s\" )",
__FUNCTION__, id, event_func, text, password_char, maxlength, value); __FUNCTION__, id, event_func, text, password_char, maxlength, value);
@@ -256,24 +237,15 @@ MenuItem *menuitem_create_alpha (char *id, MenuEventFunc(*event_func),
new_item->data.alpha.minlength = minlength; new_item->data.alpha.minlength = minlength;
new_item->data.alpha.maxlength = maxlength; new_item->data.alpha.maxlength = maxlength;
new_item->data.alpha.allow_caps = allow_caps;
new_item->data.alpha.allow_noncaps = allow_noncaps;
new_item->data.alpha.allow_numbers = allow_numbers;
new_item->data.alpha.allowed_extra = strdup (allowed_extra);
new_item->data.alpha.value = malloc (maxlength + 1); new_item->data.alpha.value = malloc (maxlength + 1);
strncpy (new_item->data.alpha.value, value, maxlength); strncpy (new_item->data.alpha.value, value, maxlength);
new_item->data.alpha.value[maxlength] = 0; new_item->data.alpha.value[maxlength] = 0;
/* Create list of allowed chars */
chars = malloc (26 + 26 + 10 + strlen(allowed_extra) + 1);
chars[0] = 0;
if (allow_caps)
strcat (chars, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
if (allow_noncaps)
strcat (chars, "abcdefghijklmnopqrstuvwxyz");
if (allow_numbers)
strcat (chars, "0123456789");
if (allowed_extra) {
strcat (chars, allowed_extra);
}
new_item->data.alpha.allowed_chars = chars;
new_item->data.alpha.edit_str = malloc (maxlength + 1); new_item->data.alpha.edit_str = malloc (maxlength + 1);
return new_item; return new_item;
@@ -335,7 +307,7 @@ void menuitem_destroy_alpha (MenuItem *item)
debug (RPT_DEBUG, "%s( item=\"%s\" )", __FUNCTION__, item->id); debug (RPT_DEBUG, "%s( item=\"%s\" )", __FUNCTION__, item->id);
/* These strings should always be allocated */ /* These strings should always be allocated */
free (item->data.alpha.allowed_chars); free (item->data.alpha.allowed_extra);
free (item->data.alpha.value); free (item->data.alpha.value);
free (item->data.alpha.edit_str); free (item->data.alpha.edit_str);
} }
@@ -611,8 +583,8 @@ void menuitem_update_screen_alpha (MenuItem *item, Screen *s)
if (item->data.alpha.password_char == 0) { if (item->data.alpha.password_char == 0) {
strcpy (w->text, item->data.alpha.edit_str); strcpy (w->text, item->data.alpha.edit_str);
} else { } else {
memset (item->data.alpha.edit_str, 0, item->data.alpha.maxlength+1); memset (w->text, item->data.alpha.password_char, strlen (item->data.alpha.edit_str));
memset (item->data.alpha.edit_str, item->data.alpha.password_char, strlen (item->data.alpha.edit_str)); w->text[ strlen (item->data.alpha.edit_str) ] = 0;
} }
s->cursor = CURSOR_DEFAULT_ON; s->cursor = CURSOR_DEFAULT_ON;
@@ -629,23 +601,23 @@ void menuitem_update_screen_alpha (MenuItem *item, Screen *s)
/******** MENU SCREEN INPUT HANDLING FUNCTIONS ********/ /******** MENU SCREEN INPUT HANDLING FUNCTIONS ********/
MenuResult menuitem_handle_input (MenuItem *item, MenuToken token, char * key) MenuResult menuitem_process_input (MenuItem *item, MenuToken token, char * key)
{ {
MenuResult (*handle_input) (MenuItem *item, MenuToken token, char * key); MenuResult (*process_input) (MenuItem *item, MenuToken token, char * key);
debug (RPT_DEBUG, "%s( item=\"%s\", token=%d, key=\"%s\" )", __FUNCTION__, item->id, token, key); debug (RPT_DEBUG, "%s( item=\"%s\", token=%d, key=\"%s\" )", __FUNCTION__, item->id, token, key);
/* Call type specific screen building function */ /* Call type specific screen building function */
handle_input = handle_input_table [item->type]; process_input = process_input_table [item->type];
if (handle_input ) { if (process_input ) {
return handle_input (item, token, key); return process_input (item, token, key);
} else { } else {
report (RPT_ERR, "%s: given menuitem cannot be active", __FUNCTION__); report (RPT_ERR, "%s: given menuitem cannot be active", __FUNCTION__);
return MENURESULT_ERROR; return MENURESULT_ERROR;
} }
} }
MenuResult menuitem_handle_input_slider (MenuItem *item, MenuToken token, char * key) MenuResult menuitem_process_input_slider (MenuItem *item, MenuToken token, char * key)
{ {
debug (RPT_DEBUG, "%s( item=\"%s\", token=%d, key=\"%s\" )", __FUNCTION__, item->id, token, key); debug (RPT_DEBUG, "%s( item=\"%s\", token=%d, key=\"%s\" )", __FUNCTION__, item->id, token, key);
@@ -658,20 +630,20 @@ MenuResult menuitem_handle_input_slider (MenuItem *item, MenuToken token, char *
item->data.slider.value + item->data.slider.stepsize); item->data.slider.value + item->data.slider.stepsize);
if (item->event_func) if (item->event_func)
item->event_func (item, MENUEVENT_PLUS); item->event_func (item, MENUEVENT_PLUS);
return MENURESULT_OK; return MENURESULT_NONE;
case MENUTOKEN_DOWN: case MENUTOKEN_DOWN:
item->data.slider.value = max (item->data.slider.minvalue, item->data.slider.value = max (item->data.slider.minvalue,
item->data.slider.value - item->data.slider.stepsize); item->data.slider.value - item->data.slider.stepsize);
if (item->event_func) if (item->event_func)
item->event_func (item, MENUEVENT_MINUS); item->event_func (item, MENUEVENT_MINUS);
return MENURESULT_OK; return MENURESULT_NONE;
case MENUTOKEN_OTHER: case MENUTOKEN_OTHER:
} }
return MENURESULT_ERROR; return MENURESULT_ERROR;
} }
MenuResult menuitem_handle_input_numeric (MenuItem *item, MenuToken token, char * key) MenuResult menuitem_process_input_numeric (MenuItem *item, MenuToken token, char * key)
{ {
char buf1[MAX_NUMERIC_LEN]; char buf1[MAX_NUMERIC_LEN];
char buf2[MAX_NUMERIC_LEN]; char buf2[MAX_NUMERIC_LEN];
@@ -710,7 +682,7 @@ MenuResult menuitem_handle_input_numeric (MenuItem *item, MenuToken token, char
memset (str, 0, MAX_NUMERIC_LEN); memset (str, 0, MAX_NUMERIC_LEN);
snprintf (str, MAX_NUMERIC_LEN, format_str, item->data.numeric.value); snprintf (str, MAX_NUMERIC_LEN, format_str, item->data.numeric.value);
} }
return MENURESULT_OK; return MENURESULT_NONE;
case MENUTOKEN_ENTER: case MENUTOKEN_ENTER:
if (str[pos] == 0) { if (str[pos] == 0) {
int value; int value;
@@ -728,7 +700,7 @@ MenuResult menuitem_handle_input_numeric (MenuItem *item, MenuToken token, char
*/ */
item->data.numeric.error_code = 1; item->data.numeric.error_code = 1;
item->data.numeric.edit_pos = 0; item->data.numeric.edit_pos = 0;
return MENURESULT_OK; return MENURESULT_NONE;
} }
/* OK, store value */ /* OK, store value */
@@ -746,13 +718,13 @@ MenuResult menuitem_handle_input_numeric (MenuItem *item, MenuToken token, char
item->data.numeric.edit_pos ++; item->data.numeric.edit_pos ++;
} }
} }
return MENURESULT_OK; return MENURESULT_NONE;
case MENUTOKEN_UP: case MENUTOKEN_UP:
if (pos >= max_len) { if (pos >= max_len) {
/* We're not allowed to add anything anymore */ /* We're not allowed to add anything anymore */
item->data.numeric.error_code = 2; item->data.numeric.error_code = 2;
item->data.numeric.edit_pos = 0; item->data.numeric.edit_pos = 0;
return MENURESULT_OK; return MENURESULT_NONE;
} }
if (allow_signed && pos == 0) { if (allow_signed && pos == 0) {
/* make negative */ /* make negative */
@@ -767,13 +739,13 @@ MenuResult menuitem_handle_input_numeric (MenuItem *item, MenuToken token, char
str[pos] = '0'; str[pos] = '0';
} }
} }
return MENURESULT_OK; return MENURESULT_NONE;
case MENUTOKEN_DOWN: case MENUTOKEN_DOWN:
if (pos >= max_len) { if (pos >= max_len) {
/* We're not allowed to add anything anymore */ /* We're not allowed to add anything anymore */
item->data.numeric.error_code = 2; item->data.numeric.error_code = 2;
item->data.numeric.edit_pos = 0; item->data.numeric.edit_pos = 0;
return MENURESULT_OK; return MENURESULT_NONE;
} }
if (allow_signed && pos == 0) { if (allow_signed && pos == 0) {
/* make negative */ /* make negative */
@@ -788,28 +760,28 @@ MenuResult menuitem_handle_input_numeric (MenuItem *item, MenuToken token, char
str[pos] = '9'; str[pos] = '9';
} }
} }
return MENURESULT_OK; return MENURESULT_NONE;
case MENUTOKEN_OTHER: case MENUTOKEN_OTHER:
if (pos >= max_len) { if (pos >= max_len) {
/* We're not allowed to add anything anymore */ /* We're not allowed to add anything anymore */
item->data.numeric.error_code = 2; item->data.numeric.error_code = 2;
item->data.numeric.edit_pos = 0; item->data.numeric.edit_pos = 0;
return MENURESULT_OK; return MENURESULT_NONE;
} }
/* proces numeric keys */ /* proces numeric keys */
if ( strlen(key) == 1 && key[0] >= '0' && key[0] <= '9') { if ( strlen(key) == 1 && key[0] >= '0' && key[0] <= '9') {
str[pos] = key[0]; str[pos] = key[0];
item->data.numeric.edit_pos ++; item->data.numeric.edit_pos ++;
} }
return MENURESULT_OK; return MENURESULT_NONE;
} }
return MENURESULT_ERROR; return MENURESULT_ERROR;
} }
MenuResult menuitem_handle_input_alpha (MenuItem *item, MenuToken token, char * key) MenuResult menuitem_process_input_alpha (MenuItem *item, MenuToken token, char * key)
{ {
char * p; char * p;
char * chars = item->data.alpha.allowed_chars; static char * chars = NULL;
/* To make life easy... */ /* To make life easy... */
char *str = item->data.alpha.edit_str; char *str = item->data.alpha.edit_str;
@@ -817,6 +789,17 @@ MenuResult menuitem_handle_input_alpha (MenuItem *item, MenuToken token, char *
debug (RPT_DEBUG, "%s( item=\"%s\", token=%d, key=\"%s\" )", __FUNCTION__, item->id, token, key); debug (RPT_DEBUG, "%s( item=\"%s\", token=%d, key=\"%s\" )", __FUNCTION__, item->id, token, key);
/* Create list of allowed chars */
chars = realloc (chars, 26 + 26 + 10 + strlen(item->data.alpha.allowed_extra) + 1);
chars[0] = 0; /* clear string */
if (item->data.alpha.allow_caps)
strcat (chars, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
if (item->data.alpha.allow_noncaps)
strcat (chars, "abcdefghijklmnopqrstuvwxyz");
if (item->data.alpha.allow_numbers)
strcat (chars, "0123456789");
strcat (chars, item->data.alpha.allowed_extra);
/* Clear the error */ /* Clear the error */
item->data.alpha.error_code = 0; item->data.alpha.error_code = 0;
@@ -831,7 +814,7 @@ MenuResult menuitem_handle_input_alpha (MenuItem *item, MenuToken token, char *
memset (str, 0, item->data.alpha.maxlength+1); memset (str, 0, item->data.alpha.maxlength+1);
strcpy (str, item->data.alpha.value); strcpy (str, item->data.alpha.value);
} }
return MENURESULT_OK; return MENURESULT_NONE;
case MENUTOKEN_ENTER: case MENUTOKEN_ENTER:
if (str[item->data.alpha.edit_pos] == 0) { if (str[item->data.alpha.edit_pos] == 0) {
/* The user completed his input */ /* The user completed his input */
@@ -839,7 +822,7 @@ MenuResult menuitem_handle_input_alpha (MenuItem *item, MenuToken token, char *
/* It's not too short ? */ /* It's not too short ? */
if (strlen (item->data.alpha.edit_str) < item->data.alpha.minlength) { if (strlen (item->data.alpha.edit_str) < item->data.alpha.minlength) {
item->data.alpha.error_code = 3; item->data.alpha.error_code = 3;
return MENURESULT_OK; return MENURESULT_NONE;
} }
/* Store value */ /* Store value */
@@ -857,13 +840,13 @@ MenuResult menuitem_handle_input_alpha (MenuItem *item, MenuToken token, char *
item->data.alpha.edit_pos ++; item->data.alpha.edit_pos ++;
} }
} }
return MENURESULT_OK; return MENURESULT_NONE;
case MENUTOKEN_UP: case MENUTOKEN_UP:
if (pos >= item->data.alpha.maxlength) { if (pos >= item->data.alpha.maxlength) {
/* We're not allowed to add anything anymore */ /* We're not allowed to add anything anymore */
item->data.alpha.error_code = 2; item->data.alpha.error_code = 2;
item->data.numeric.edit_pos = 0; item->data.numeric.edit_pos = 0;
return MENURESULT_OK; return MENURESULT_NONE;
} }
if (str[pos] == 0) { if (str[pos] == 0) {
/* User goes past EOL */ /* User goes past EOL */
@@ -878,13 +861,13 @@ MenuResult menuitem_handle_input_alpha (MenuItem *item, MenuToken token, char *
str[pos] = 0; str[pos] = 0;
} }
} }
return MENURESULT_OK; return MENURESULT_NONE;
case MENUTOKEN_DOWN: case MENUTOKEN_DOWN:
if (pos >= item->data.alpha.maxlength) { if (pos >= item->data.alpha.maxlength) {
/* We're not allowed to add anything anymore */ /* We're not allowed to add anything anymore */
item->data.alpha.error_code = 2; item->data.alpha.error_code = 2;
item->data.numeric.edit_pos = 0; item->data.numeric.edit_pos = 0;
return MENURESULT_OK; return MENURESULT_NONE;
} }
if (str[pos] == 0) { if (str[pos] == 0) {
/* User goes past EOL */ /* User goes past EOL */
@@ -902,21 +885,92 @@ MenuResult menuitem_handle_input_alpha (MenuItem *item, MenuToken token, char *
str[pos] = 0; str[pos] = 0;
} }
} }
return MENURESULT_OK; return MENURESULT_NONE;
case MENUTOKEN_OTHER: case MENUTOKEN_OTHER:
if (pos >= item->data.alpha.maxlength) { if (pos >= item->data.alpha.maxlength) {
/* We're not allowed to add anything anymore */ /* We're not allowed to add anything anymore */
item->data.alpha.error_code = 2; item->data.alpha.error_code = 2;
item->data.numeric.edit_pos = 0; item->data.numeric.edit_pos = 0;
return MENURESULT_OK; return MENURESULT_NONE;
} }
/* proces other keys */ /* proces other keys */
if ( strlen(key) == 1 && key[0] >= ' ' && key[0] <= 'Z') { if ( strlen(key) == 1 && key[0] >= ' ' && key[0] <= 'Z') {
str[pos] = key[0]; str[pos] = key[0];
item->data.alpha.edit_pos ++; item->data.alpha.edit_pos ++;
} }
return MENURESULT_OK; return MENURESULT_NONE;
} }
return MENURESULT_ERROR; return MENURESULT_ERROR;
} }
LinkedList * tablist2linkedlist (char *strings)
{
char *tabptr, *p, *new_s;
LinkedList * list;
list = LL_new();
/* Parse strings */
p = strings;
while ((tabptr = strchr(p, '\t')) != NULL) {
int len = (int)(tabptr - p);
/* Alloc and copy substring */
new_s = malloc (len + 1);
strncpy (new_s, p, len);
new_s[len] = 0;
LL_Push (list, new_s);
/* Go to next string */
p = tabptr + 1;
}
/* Add last string */
new_s = strdup (p);
LL_Push (list, new_s);
return list;
}
MenuItemType menuitem_typename_to_type (char *name)
{
MenuItemType type;
for (type = 0; type < NUM_ITEMTYPES; type ++) {
if (strcmp (menuitemtypenames[type], name) == 0) {
return type;
}
}
return -1;
}
char *menuitem_type_to_typename (MenuItemType type)
{
if (type >= 0 && type < NUM_ITEMTYPES) {
return menuitemtypenames[type];
}
else {
return NULL;
}
}
MenuEventType menuitem_eventtypename_to_eventtype (char *name)
{
MenuEventType type;
for (type = 0; type < NUM_EVENTTYPES; type ++) {
if (strcmp (menueventtypenames[type], name) == 0) {
return type;
}
}
return -1;
}
char *menuitem_eventtype_to_eventtypename (MenuEventType type)
{
if (type >= 0 && type < NUM_EVENTTYPES) {
return menueventtypenames[type];
}
else {
return NULL;
}
}
+28 -15
View File
@@ -27,8 +27,6 @@
#include "shared/LL.h" #include "shared/LL.h"
#include "screen.h"
#ifndef bool #ifndef bool
# define bool short # define bool short
# define true 1 # define true 1
@@ -42,7 +40,6 @@
*/ */
#define NUM_ITEMTYPES 7 #define NUM_ITEMTYPES 7
typedef enum MenuItemType { /* These values are used in the */ typedef enum MenuItemType { /* These values are used in the */
MENUITEM_MENU = 0, /* function tables in menuitem.c ! */ MENUITEM_MENU = 0, /* function tables in menuitem.c ! */
MENUITEM_ACTION = 1, MENUITEM_ACTION = 1,
@@ -69,7 +66,7 @@ typedef enum MenuToken {
/* Return codes from an input handler */ /* Return codes from an input handler */
typedef enum MenuResult { typedef enum MenuResult {
MENURESULT_ERROR = -1, /* Something has gone wrong */ MENURESULT_ERROR = -1, /* Something has gone wrong */
MENURESULT_OK = 0, /* Token handled OK */ MENURESULT_NONE = 0, /* Token handled OK, no extra action */
MENURESULT_ENTER, /* Token handled OK, enter the selected MENURESULT_ENTER, /* Token handled OK, enter the selected
menuitem now */ menuitem now */
MENURESULT_CLOSE, /* Token handled OK, close the current MENURESULT_CLOSE, /* Token handled OK, close the current
@@ -78,16 +75,15 @@ typedef enum MenuResult {
} MenuResult; } MenuResult;
/* Events caused by a menuitem */ /* Events caused by a menuitem */
#define NUM_EVENTTYPES 4
typedef enum MenuEventType { typedef enum MenuEventType {
MENUEVENT_ENTER, /* Item has been entered MENUEVENT_SELECT = 0, /* Item has been selected
(menu opened, action chosen) (action chosen) */
Can be used to trigger one-time update of
the items in a menu. */
MENUEVENT_UPDATE, /* Item has been modified MENUEVENT_UPDATE, /* Item has been modified
(checkbox, numeric, alphanumeric) */ (checkbox, numeric, alphanumeric) */
MENUEVENT_PLUS, /* Item has been modified in positive direction MENUEVENT_PLUS, /* Item has been modified in positive direction
(slider moved) */ (slider moved) */
MENUEVENT_MINUS /* Item has been modified in negative direction MENUEVENT_MINUS, /* Item has been modified in negative direction
(slider moved) */ (slider moved) */
} MenuEventType; } MenuEventType;
@@ -121,8 +117,9 @@ typedef struct MenuItem {
LinkedList *contents; /* What's in this menu */ LinkedList *contents; /* What's in this menu */
} menu; } menu;
struct action { struct action {
bool close_menu; /* Close active menu ? */ enum MenuResult menu_result;
bool quit_menu; /* Close entire menu ? */ /* What to do when selected ?
Nothing, close or quit ? */
} action; } action;
struct checkbox { struct checkbox {
bool allow_gray; /* Is CHECKBOX_GRAY allowed ? */ bool allow_gray; /* Is CHECKBOX_GRAY allowed ? */
@@ -143,7 +140,7 @@ typedef struct MenuItem {
struct numeric { struct numeric {
int maxvalue; int maxvalue;
int minvalue; int minvalue;
short allowed_decimals; /* Number of numbers behind dot */ //short allowed_decimals; /* Number of numbers behind dot */
int value; /* Current value */ int value; /* Current value */
char *edit_str; /* Value while being edited */ char *edit_str; /* Value while being edited */
short edit_pos; /* Position while editing */ short edit_pos; /* Position while editing */
@@ -153,7 +150,10 @@ typedef struct MenuItem {
char password_char; /* For passwords */ char password_char; /* For passwords */
short minlength; short minlength;
short maxlength; short maxlength;
char *allowed_chars; /* Allowed characters */ bool allow_caps; /* Caps allowed ? */
bool allow_noncaps; /* Non-caps allowed ? */
bool allow_numbers; /* Numbers allowed ? */
char *allowed_extra; /* Allowed extra characters */
char *value; /* Current value */ char *value; /* Current value */
char *edit_str; /* Value while being edited */ char *edit_str; /* Value while being edited */
short edit_pos; /* Position while editing */ short edit_pos; /* Position while editing */
@@ -163,6 +163,8 @@ typedef struct MenuItem {
} MenuItem; } MenuItem;
#include "screen.h"
/********************************************************************* /*********************************************************************
* Functions to use the menustuff * Functions to use the menustuff
*/ */
@@ -187,7 +189,7 @@ MenuItem *menuitem_create (MenuItemType type, char *id,
* *
*/ */
MenuItem *menuitem_create_action (char *id, MenuEventFunc(*event_func), MenuItem *menuitem_create_action (char *id, MenuEventFunc(*event_func),
char *text, bool close_menu, bool quit_menu); char *text, MenuResult menu_result);
/* Creates a an action item (a string only). /* Creates a an action item (a string only).
* Generated events: MENUEVENT_ENTER when user selects the item. * Generated events: MENUEVENT_ENTER when user selects the item.
*/ */
@@ -269,9 +271,20 @@ void menuitem_update_screen (MenuItem *item, Screen *s);
* Fills all widget attributes with the corrrect values. * Fills all widget attributes with the corrrect values.
*/ */
MenuResult menuitem_handle_input (MenuItem *item, MenuToken token, char * key); MenuResult menuitem_process_input (MenuItem *item, MenuToken token, char * key);
/* Does something with the given input. /* Does something with the given input.
* key is only used if token is MENUTOKEN_OTHER. * key is only used if token is MENUTOKEN_OTHER.
*/ */
LinkedList * tablist2linkedlist (char * strings);
/* Converts a tab-separated list to a LinkedList. */
MenuItemType menuitem_typename_to_type (char *name);
char *menuitem_type_to_typename (MenuItemType type);
MenuEventType menuitem_eventtypename_to_eventtype (char *name);
char *menuitem_eventtype_to_eventtypename (MenuEventType type);
#endif #endif
+51 -45
View File
@@ -46,11 +46,10 @@ Menu * screens_menu;
void menuscreen_create_menu (); void menuscreen_create_menu ();
MenuEventFunc (menuscreen_heartbeat); MenuEventFunc (heartbeat_handler);
MenuEventFunc (menuscreen_backlight); MenuEventFunc (backlight_handler);
MenuEventFunc (menuscreen_contrast); MenuEventFunc (contrast_handler);
MenuEventFunc (menuscreen_brightness); MenuEventFunc (brightness_handler);
MenuEventFunc (menuscreen_screens);
int init_menu() int init_menu()
{ {
@@ -126,13 +125,13 @@ void menuscreen_key_handler (char *key)
return; return;
} }
res = menuitem_handle_input (active_menuitem, token, key); res = menuitem_process_input (active_menuitem, token, key);
switch (res) { switch (res) {
case MENURESULT_ERROR: case MENURESULT_ERROR:
report (RPT_ERR, "%s: Error from menu_handle_input", __FUNCTION__); report (RPT_ERR, "%s: Error from menu_handle_input", __FUNCTION__);
break; break;
case MENURESULT_OK: case MENURESULT_NONE:
/* Nothing extra to be done */ /* Nothing extra to be done */
break; break;
case MENURESULT_ENTER: case MENURESULT_ENTER:
@@ -189,13 +188,13 @@ void menuscreen_create_menu ()
options_menu = menu_create ("options", NULL, "Options", NULL); options_menu = menu_create ("options", NULL, "Options", NULL);
menu_add_item (main_menu, options_menu); menu_add_item (main_menu, options_menu);
screens_menu = menu_create ("screens", menuscreen_screens, "Screens", NULL); screens_menu = menu_create ("screens", NULL, "Screens", NULL);
menu_add_item (main_menu, screens_menu); menu_add_item (main_menu, screens_menu);
checkbox = menuitem_create_checkbox ("heartbeat", menuscreen_heartbeat, "Heartbeat", true, heartbeat); checkbox = menuitem_create_checkbox ("heartbeat", heartbeat_handler, "Heartbeat", true, heartbeat);
menu_add_item (options_menu, checkbox); menu_add_item (options_menu, checkbox);
checkbox = menuitem_create_checkbox ("backlight", menuscreen_backlight, "Backlight", true, backlight); checkbox = menuitem_create_checkbox ("backlight", backlight_handler, "Backlight", true, backlight);
menu_add_item (options_menu, checkbox); menu_add_item (options_menu, checkbox);
for (driver = drivers_getfirst(); driver; driver = drivers_getnext()) { for (driver = drivers_getfirst(); driver; driver = drivers_getnext()) {
@@ -209,14 +208,14 @@ void menuscreen_create_menu ()
driver_menu = menu_create (driver->name, NULL, driver->name, driver); driver_menu = menu_create (driver->name, NULL, driver->name, driver);
menu_add_item (options_menu, driver_menu); menu_add_item (options_menu, driver_menu);
if (contrast_avail) { if (contrast_avail) {
slider = menuitem_create_slider ("contrast", menuscreen_contrast, "Contrast", "min", "max", 0, 1000, 100, 500); slider = menuitem_create_slider ("contrast", contrast_handler, "Contrast", "min", "max", 0, 1000, 100, 500);
menu_add_item (driver_menu, slider); menu_add_item (driver_menu, slider);
} }
if (brightness_avail) { if (brightness_avail) {
slider = menuitem_create_slider ("onbrightness", menuscreen_brightness, "On Brightness", "min", "max", 0, 1000, 100, 500); slider = menuitem_create_slider ("onbrightness", brightness_handler, "On Brightness", "min", "max", 0, 1000, 100, 500);
menu_add_item (driver_menu, slider); menu_add_item (driver_menu, slider);
slider = menuitem_create_slider ("offbrightness", menuscreen_brightness, "Off Brightness", "min", "max", 0, 1000, 100, 500); slider = menuitem_create_slider ("offbrightness", brightness_handler, "Off Brightness", "min", "max", 0, 1000, 100, 500);
menu_add_item (driver_menu, slider); menu_add_item (driver_menu, slider);
} }
} }
@@ -224,11 +223,11 @@ void menuscreen_create_menu ()
test_menu = menu_create ("test", NULL, "Test menu", NULL); test_menu = menu_create ("test", NULL, "Test menu", NULL);
menu_add_item (main_menu, test_menu); menu_add_item (main_menu, test_menu);
test_item = menuitem_create_action ("", NULL, "Action", false, false); test_item = menuitem_create_action ("", NULL, "Action", MENURESULT_NONE);
menu_add_item (test_menu, test_item); menu_add_item (test_menu, test_item);
test_item = menuitem_create_action ("", NULL, "Action,closing", true, false); test_item = menuitem_create_action ("", NULL, "Action,closing", MENURESULT_CLOSE);
menu_add_item (test_menu, test_item); menu_add_item (test_menu, test_item);
test_item = menuitem_create_action ("", NULL, "Action,quiting", true, true); test_item = menuitem_create_action ("", NULL, "Action,quiting", MENURESULT_QUIT);
menu_add_item (test_menu, test_item); menu_add_item (test_menu, test_item);
test_item = menuitem_create_checkbox ("", NULL, "Checkbox", false, false); test_item = menuitem_create_checkbox ("", NULL, "Checkbox", false, false);
@@ -255,7 +254,7 @@ void menuscreen_create_menu ()
menu_add_item (test_menu, test_item); menu_add_item (test_menu, test_item);
} }
MenuEventFunc (menuscreen_heartbeat) MenuEventFunc (heartbeat_handler)
{ {
debug (RPT_DEBUG, "%s( item=%s, event=%d )", __FUNCTION__, item->id, event); debug (RPT_DEBUG, "%s( item=%s, event=%d )", __FUNCTION__, item->id, event);
@@ -268,7 +267,7 @@ MenuEventFunc (menuscreen_heartbeat)
return 0; return 0;
} }
MenuEventFunc (menuscreen_backlight) MenuEventFunc (backlight_handler)
{ {
debug (RPT_DEBUG, "%s( item=%s, event=%d )", __FUNCTION__, item->id, event); debug (RPT_DEBUG, "%s( item=%s, event=%d )", __FUNCTION__, item->id, event);
@@ -282,7 +281,7 @@ MenuEventFunc (menuscreen_backlight)
return 0; return 0;
} }
MenuEventFunc (menuscreen_contrast) MenuEventFunc (contrast_handler)
{ {
debug (RPT_DEBUG, "%s( item=%s, event=%d )", __FUNCTION__, item->id, event); debug (RPT_DEBUG, "%s( item=%s, event=%d )", __FUNCTION__, item->id, event);
@@ -302,7 +301,7 @@ MenuEventFunc (menuscreen_contrast)
return 0; return 0;
} }
MenuEventFunc (menuscreen_brightness) MenuEventFunc (brightness_handler)
{ {
debug (RPT_DEBUG, "%s( item=%s, event=%d )", __FUNCTION__, item->id, event); debug (RPT_DEBUG, "%s( item=%s, event=%d )", __FUNCTION__, item->id, event);
@@ -324,39 +323,46 @@ MenuEventFunc (menuscreen_brightness)
return 0; return 0;
} }
MenuEventFunc (menuscreen_screens) void
menuscreen_add_screen (Screen * s)
{ {
debug (RPT_DEBUG, "%s( item=%s, event=%d )", __FUNCTION__, item->id, event); Menu * m;
MenuItem * mi;
if (event == MENUEVENT_ENTER) { debug (RPT_DEBUG, "%s( Screen=\"%s\" )", __FUNCTION__, s->id);
/* We are entering this menu */
Screen * s;
Menu * m;
MenuItem * mi;
/* Clean the screens menu */ if (!screens_menu)
menu_destroy_all_items (screens_menu); return; /* When screens have not been created ... */
/* Read list of screens */ /* Create a menu entry for the screen */
for (s = LL_GetFirst(screenlist_getlist()); s; s = LL_GetNext(screenlist_getlist())) { m = menu_create (s->id, NULL, s->name?s->name:s->id, s);
menu_add_item (screens_menu, m);
/* TODO: don't display screens that have _ at start of id */ /* And add some items for it... */
mi = menuitem_create_action ("", NULL, "(don't work yet)", MENURESULT_NONE);
menu_add_item (m, mi);
m = menu_create (s->id, NULL, s->name?s->name:s->id, s); mi = menuitem_create_action ("", NULL, "To Front", MENURESULT_QUIT);
menu_add_item (screens_menu, m); menu_add_item (m, mi);
mi = menuitem_create_action ("", NULL, "To Front", true, true); mi = menuitem_create_checkbox ("", NULL, "Visible", false, true);
menu_add_item (m, mi); menu_add_item (m, mi);
mi = menuitem_create_checkbox ("", NULL, "Visible", false, true); mi = menuitem_create_numeric ("", NULL, "Duration", 2, 3600, s->duration);
menu_add_item (m, mi); menu_add_item (m, mi);
mi = menuitem_create_numeric ("", NULL, "Duration", 2, 3600, s->duration); mi = menuitem_create_numeric ("", NULL, "Priority", 0, 255, s->priority);
menu_add_item (m, mi); menu_add_item (m, mi);
}
mi = menuitem_create_numeric ("", NULL, "Priority", -1, 4, s->priority); void
menu_add_item (m, mi); menuscreen_remove_screen (Screen * s)
} {
} Menu * m;
return 0;
debug (RPT_DEBUG, "%s( Screen=\"%s\" )", __FUNCTION__, s->id);
m = menu_find_item (screens_menu, s->id, false);
menu_remove_item (screens_menu, m);
menuitem_destroy (m);
} }
+8 -1
View File
@@ -18,6 +18,8 @@
#include "screen.h" #include "screen.h"
extern Screen * menuscreen; extern Screen * menuscreen;
extern MenuItem * active_menuitem;
extern Menu * main_menu;
int init_menu(); int init_menu();
@@ -30,5 +32,10 @@ void menuscreen_key_handler (char *key);
/* This handler handles the keypresses for the menu. /* This handler handles the keypresses for the menu.
*/ */
#endif void menuscreen_add_screen (Screen * s);
/* Adds a menu for the given screen */
void menuscreen_remove_screen (Screen * s);
/* Removes the menu of the screen */
#endif
+180 -2
View File
@@ -31,10 +31,10 @@
* TODO: Simplify... simplify... * TODO: Simplify... simplify...
*/ */
#define MAX_ARGUMENTS 256 #define MAX_ARGUMENTS 40
int int
parse_all_client_messages () parse_all_client_messages2 ()
{ {
int i; /* int j, len;*/ int i; /* int j, len;*/
/*int newtoken, inquote;*/ /*int newtoken, inquote;*/
@@ -182,3 +182,181 @@ parse_all_client_messages ()
return 0; return 0;
} }
int parse_message (char * str, Client * c);
int
parse_all_client_messages ()
{
Client * c;
char * str;
debug( RPT_DEBUG, "parse_all_client_messages()" );
for( c=clients_getfirst(); c; c=clients_getnext()) {
/* And parse all its messages...*/
/*debug(RPT_DEBUG, "parse: Getting messages...");*/
for (str = client_get_message (c); str; str = client_get_message (c)) {
parse_message (str, c);
free (str);
}
}
return 0;
}
int parse_message (char * str, Client * c)
{
typedef enum { ST_INITIAL, ST_WHITESPACE, ST_IGNORE, ST_ARGUMENT, ST_FINAL } State;
State state = ST_INITIAL;
char escape_chars[] = "nrt";
char escape_trans[] = "\n\r\t";
char errmsg[256];
int error = 0;
char used_quote = 0; /* The quote used to open a quote string */
int pos = 0;
char ch;
int i;
int argc =0 ;
char *argv[MAX_ARGUMENTS];
int argpos = 0;
void close_arg () {
argv[argc][argpos] = 0;
argv[argc+1] = argv[argc] + argpos + 1;
argc ++;
argpos = 0;
}
argv[0] = malloc(strlen(str)+1);
/* We will create a new string that is shorter or equally long as
* the original string str.
*/
while( state != ST_FINAL ) {
ch = str[pos++];
switch( state ) {
case ST_INITIAL:
case ST_WHITESPACE:
switch( ch ) {
case '\r':
case '\t':
case ' ':
break;
case '\n':
case 0:
state = ST_FINAL;
break;
default:
state = ST_ARGUMENT;
pos --; /* Rescan current char */
}
break;
case ST_IGNORE:
switch( ch ) {
case '\n':
state = ST_FINAL;
break;
}
break;
case ST_ARGUMENT:
switch( ch ) {
case '\r':
case '\t':
case ' ':
if (used_quote) {
/* We're in a quoted string, add it */
argv[argc][argpos++] = ch;
}
else {
close_arg();
state = ST_WHITESPACE;
}
break;
case '\n':
if (used_quote) {
/* Just ad it */
argv[argc][argpos++] = ch;
break;
}
/* else go to case 0 */
case 0:
if (used_quote) {
error = 2;
}
close_arg();
state = ST_FINAL;
break;
case '\\':
if (str[pos]) {
/* We solve quoted chars here right away */
char * p;
p = strchr( escape_chars, str[pos++] );
if (p != NULL) {
/* Insert a replacement for the code */
argv[argc][argpos++] = escape_trans[(int)*p];
}
else {
/* Copy char litterally */
argv[argc][argpos++] = str[pos];
}
}
else {
close_arg();
error = 2;
state = ST_FINAL;
}
case '\"':
case '{':
if (!used_quote) {
used_quote = ch;
break;
}
/* else fall through to default... */
default:
if (used_quote) {
/* Have we reached the end of the
* quote already ?
*/
if ((used_quote == '{' && ch == '}')
|| (used_quote == '\"' && ch == '\"')) {
used_quote = 0;
break;
}
}
argv[argc][argpos++] = ch;
}
break;
case ST_FINAL:
/* This will never be reached */
break;
}
}
argv[argc] = NULL;
if (error) {
snprintf (errmsg, sizeof(errmsg), "huh? Could not parse command\n");
sock_send_string (c->sock, errmsg);
}
/* Now find and call the appropriate function...*/
error = 1;
for (i = 0; commands[i].keyword; i++) {
if (0 == strcmp (argv[0], commands[i].keyword)) {
error = commands[i].function (c, argc, argv);
break; /* found our function - don't continue on...*/
}
}
if (error == 1) {
snprintf (errmsg, sizeof(errmsg), "huh? Invalid command \"%.40s\"\n", argv[0]);
sock_send_string (c->sock, errmsg);
}
else if (error) {
snprintf (errmsg, sizeof(errmsg), "huh? Function returned error \"%.40s\"\n", argv[0]);
sock_send_string (c->sock, errmsg);
}
return 0;
}
+6
View File
@@ -75,6 +75,8 @@ screen_create (char * id, Client * client)
return NULL; return NULL;
} }
menuscreen_add_screen (s);
return s; return s;
} }
@@ -86,6 +88,10 @@ screen_destroy (Screen * s)
if (!s) if (!s)
return -1; return -1;
menuscreen_remove_screen (s);
screenlist_remove (s);
for (w=LL_GetFirst(s->widgetlist); w; w=LL_GetNext(s->widgetlist)) { for (w=LL_GetFirst(s->widgetlist); w; w=LL_GetNext(s->widgetlist)) {
/* Free a widget...*/ /* Free a widget...*/
widget_destroy (w); widget_destroy (w);
+7 -1
View File
@@ -9,10 +9,16 @@
* *
*/ */
#include "menu.h"
#include "menuitem.h"
#include "client.h"
/* These headers are placed here on purpose ! (circular references) */
#ifndef SCREEN_H #ifndef SCREEN_H
#define SCREEN_H #define SCREEN_H
#include "shared/LL.h" #include "shared/LL.h"
#include "client.h"
typedef struct Screen { typedef struct Screen {
char *id; char *id;
@@ -31,13 +37,13 @@ typedef struct Screen {
struct Client *client; struct Client *client;
} Screen; } Screen;
#include "client.h"
#include "widget.h" #include "widget.h"
extern int default_duration ; extern int default_duration ;
extern int default_priority ; extern int default_priority ;
#include "client.h"
/* Creates a new screen */ /* Creates a new screen */
Screen * screen_create (char * id, Client * client); Screen * screen_create (char * id, Client * client);
+35 -50
View File
@@ -22,6 +22,7 @@
#include "shared/report.h" #include "shared/report.h"
#include "drivers/lcd.h"
#include "drivers.h" #include "drivers.h"
#include "clients.h" #include "clients.h"
#include "screen.h" #include "screen.h"
@@ -31,60 +32,46 @@
Screen * server_screen; Screen * server_screen;
char title[256] = "LCDproc Server"; #define MAX_SERVERSCREEN_WIDTH 40
char one[256] = "";
char two[256] = "";
char three[256] = "";
int int
server_screen_init () server_screen_init ()
{ {
Widget * w; Widget * w;
int line;
debug (RPT_DEBUG, "server_screen_init"); debug (RPT_DEBUG, "server_screen_init");
/* Create the screen */
server_screen = screen_create ("_server_screen", NULL); server_screen = screen_create ("_server_screen", NULL);
if (!server_screen) { if (!server_screen) {
report (RPT_ERR, "server_screen_init: Error allocating screen"); report (RPT_ERR, "server_screen_init: Error allocating screen");
return -1; return -1;
} }
server_screen->name = "Server screen"; server_screen->name = "Server screen";
server_screen->duration = 8; /* 1 second, instead of 4...*/ server_screen->duration = 8; /* 1 second, instead of 4...*/
server_screen->priority = -1; /* TODO: use priorities good */ server_screen->priority = -1; /* TODO: use priorities good */
if ( (w = widget_create ("title", WID_TITLE, server_screen)) == NULL /* Create all the widgets...*/
|| screen_add_widget (server_screen, w) != 0 for (line=1; line<=4; line++) {
|| (w = widget_create ("one", WID_STRING, server_screen)) == NULL char id[8];
|| screen_add_widget (server_screen, w) != 0 sprintf (id, "line%d", line);
|| (w = widget_create ("two", WID_STRING, server_screen)) == NULL
|| screen_add_widget (server_screen, w) != 0 w = widget_create (id, WID_STRING, server_screen);
|| (w = widget_create ("three", WID_STRING, server_screen)) == NULL if (!w) {
|| screen_add_widget (server_screen, w) != 0 report (RPT_ERR, "server_screen_init: Can't create a widget");
) { return -1;
report (RPT_ERR, "server_screen_init: Can't create widgets"); }
return -1; screen_add_widget (server_screen, w);
w->x = 1;
w->y = line;
w->text = malloc (MAX_SERVERSCREEN_WIDTH+1);
if (line == 1) {
w->type = WID_TITLE;
strncpy (w->text, "LCDproc Server", MAX_SERVERSCREEN_WIDTH);
}
} }
/* Now, initialize all the widgets...*/
w = screen_find_widget (server_screen, "title");
w->text = strdup (title);
w = screen_find_widget (server_screen, "one");
w->x = 1;
w->y = 2;
w->text = strdup (one);
w = screen_find_widget (server_screen, "two");
w->x = 1;
w->y = 3;
w->text = strdup (two);
w = screen_find_widget (server_screen, "three");
w->x = 1;
w->y = 4;
w->text = strdup (three);
/* And enqueue the screen*/ /* And enqueue the screen*/
screenlist_add (server_screen); screenlist_add (server_screen);
@@ -97,13 +84,10 @@ int
update_server_screen (int timer) update_server_screen (int timer)
{ {
Client * c; Client * c;
Widget * w;
int num_clients; int num_clients;
/*screen *s;*/
int num_screens; int num_screens;
/* Draw a title...*/
/*strcpy(title, "LCDproc Server");*/
/* Now get info on the number of connected clients...*/ /* Now get info on the number of connected clients...*/
num_clients = clients_client_count(); num_clients = clients_client_count();
@@ -115,19 +99,20 @@ update_server_screen (int timer)
/* Format strings for the appropriate size display... */ /* Format strings for the appropriate size display... */
if (display_props->height >= 3) { if (display_props->height >= 3) {
snprintf (one, sizeof(one), "Clients: %i", num_clients); w = screen_find_widget (server_screen, "line2");
snprintf (two, sizeof(two), "Screens: %i", num_screens); snprintf (w->text, MAX_SERVERSCREEN_WIDTH,
"Clients: %i", num_clients);
w = screen_find_widget (server_screen, "line3");
snprintf (w->text, MAX_SERVERSCREEN_WIDTH,
"Screens: %i", num_screens);
} else { } else {
if (display_props->width >= 20) w = screen_find_widget (server_screen, "line2");
snprintf (one, sizeof(one), "%i Client%s, %i Screen%s", num_clients, /*if (display_props->width >= 20)*/
(num_clients == 1) ? "" : "s", num_screens, snprintf (w->text, MAX_SERVERSCREEN_WIDTH,
(num_screens == 1) ? "" : "s"); "Cli: %i Scr: %i",
else /* 16x2 size*/ num_clients, num_screens);
snprintf (one, sizeof(one), "%i Cli%s, %i Scr%s", num_clients, /*else * 16x2 size */
(num_clients == 1) ? "" : "s", num_screens,
(num_screens == 1) ? "" : "s");
} }
return 0; return 0;
} }