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 "screenlist.h"
#include "render.h"
#include "input.h"
#include "menuitem.h"
#include "shared/report.h"
#include "shared/LL.h"
@@ -50,7 +52,7 @@ Client * client_create (int sock)
c->ack = 0;
c->name = NULL;
c->client_keys = NULL;
c->menu = NULL;
c->screenlist = LL_new();
@@ -74,30 +76,10 @@ client_destroy (Client * 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...*/
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
@@ -106,6 +88,20 @@ client_destroy (Client * c)
}
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 */
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
#define CLIENT_H
@@ -16,22 +33,16 @@ typedef struct Client {
LinkedList *messages;
/* and other stuff... doesn't matter yet*/
/* The list of screens */
LinkedList *screenlist;
/* TO BE REMOVED */
char *client_keys;
/* list of requested keys */
//LinkedList *keylist;
/* list of client supplied menus */
//LinkedList *menulist;
/* Maybe it has created a menu */
Menu * menu;
} Client;
#include "screen.h"
/* When a new client connects, set up a new client data struct */
Client * client_create (int sock);
+36 -71
View File
@@ -32,6 +32,7 @@
#include "drivers.h"
#include "render.h"
#include "client.h"
#include "input.h"
/***************************************************************
* 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
* of a particular type
*
* usage: client_add_key <keylist>
* usage: client_add_key [-exclusively|-shared] {<key>}+
*/
#define BUFLEN 80
int
client_add_key_func (Client * c, int argc, char **argv)
{
char * keys ;
int exclusively = 0;
int argnr;
char errmsg[BUFLEN];
if (!c->ack)
return 1;
if (argc != 2) {
if (argc < 2) {
switch (argc) {
case 1:
sock_send_string (c->sock, "huh? usage: client_add_key <keylist>\n");
break;
default:
sock_send_string (c->sock, "huh? Too many parameters...\n");
sock_send_string (c->sock, "huh? Usage: client_add_key [-exclusively|-shared] {<key>}+\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;
argnr = 1;
if( argv[argnr][0] == '-' ) {
if( strcmp( argv[argnr], "-shared") == 0 ) {
exclusively = 0;
}
else if( strcmp( argv[argnr], "-exclusively") == 0 ) {
exclusively = 1;
}
else {
snprintf( errmsg, BUFLEN-1, "huh? Invalid option: %s\n", argv[argnr] );
errmsg[BUFLEN-1] = 0;
sock_send_string( c->sock, errmsg );
}
argnr ++;
}
for ( ; argnr < argc; argnr++ ) {
if( input_reserve_key( argv[argnr], exclusively, c ) < 0 ) {
snprintf( errmsg, BUFLEN-1, "huh? Could not reserve key \"%s\"\n", argv[argnr] );
errmsg[BUFLEN-1] = 0;
sock_send_string( c->sock, errmsg );
}
}
if (c->client_keys) {
sock_send_string(c->sock, "success\n");
} else {
sock_send_string(c->sock, "huh? failed\n");
}
sock_send_string(c->sock, "success\n");
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
* of a particular type
*
* usage: client_del_key <keylist>
* usage: client_del_key {<key>}+
*/
int
client_del_key_func (Client * c, int argc, char **argv)
{
char * keys ;
int argnr;
if (!c->ack)
return 1;
if (argc != 2) {
if (argc == 1) {
sock_send_string (c->sock, "huh? usage: client_del_key <keylist>\n");
return 0;
} else {
sock_send_string (c->sock, "huh? Too many parameters...\n");
return 0;
}
if (argc < 2) {
sock_send_string (c->sock, "huh? Usage: client_del_key {<key>}+\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++ ;
}
}
for( argnr=1; argnr < argc; argnr++) {
input_release_key( argv[argnr], c );
}
sock_send_string(c->sock, "success\n");
return 0;
+1 -4
View File
@@ -12,7 +12,7 @@
* 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.
* for each command. <-- TODO !
*
*/
@@ -39,9 +39,6 @@ client_function commands[] = {
{"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},
+579 -60
View File
@@ -19,121 +19,640 @@
*
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <dlfcn.h>
#include <errno.h>
#include "shared/report.h"
#include "shared/sockets.h"
#include "menu.h"
#include "menuitem.h"
#include "menuscreens.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;
}
MenuEventFunc(menu_commands_handler);
/*************************************************************************
* menu_add_item_func
*
* 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
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)
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;
}
/*************************************************************************
* menu_del_item_func
*
* 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
menu_del_item_func (Client * c, int argc, char **argv)
{
Menu * menu;
MenuItem * item;
char * menu_id;
char * item_id;
if (!c->ack)
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;
}
/**************************************************************************
* menu_set_item_func
* 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
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)
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;
}
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*/
ESSENTIAL( init_drivers() );
ESSENTIAL( init_sockets() );
ESSENTIAL( init_input() );
ESSENTIAL( init_menu() );
ESSENTIAL( init_screens() );
ESSENTIAL( drop_privs(user) );
@@ -212,9 +214,6 @@ main (int argc, char **argv)
}
#endif
ESSENTIAL( init_input() );
ESSENTIAL( init_menu() );
do_mainloop();
/* This loop never stops; we'll get out only with a signal...*/
+40 -29
View File
@@ -26,6 +26,7 @@
#include "config.h"
#include "menuitem.h"
#include "menu.h"
#include "shared/report.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;
@@ -103,6 +104,13 @@ MenuItem *menu_find_item (Menu *menu, char *id)
if ( strcmp(item->id, id) == 0 ) {
return item;
}
else if (recursive && item->type == MENUITEM_MENU) {
MenuItem * res;
res = menu_find_item (item, id, recursive);
if (res) {
return res;
}
}
}
return NULL;
}
@@ -262,23 +270,30 @@ void menu_update_screen (MenuItem *menu, Screen *s)
}
break;
case MENUITEM_RING:
/* Limit string length and add ringstring */
p = LL_GetByIndex (subitem->data.ring.strings, subitem->data.ring.value);
if (strlen(p) > display_props->width - 3) {
short a = display_props->width - 3;
/* 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;
if (subitem->data.ring.value >= LL_Length(subitem->data.ring.strings)) {
/* No strings available */
memcpy (w->text, subitem->text, display_props->width - 2);
w->text[ display_props->width - 2 ] = 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);
/* Limit string length and add ringstring */
p = LL_GetByIndex (subitem->data.ring.strings, subitem->data.ring.value);
if (strlen(p) > display_props->width - 3) {
short a = display_props->width - 3;
/* 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 {
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;
default:
@@ -324,12 +339,8 @@ MenuResult menu_handle_input (Menu *menu, MenuToken token, char * key)
switch (subitem->type) {
case MENUITEM_ACTION:
if (subitem->event_func)
subitem->event_func (subitem, MENUEVENT_ENTER);
if (subitem->data.action.quit_menu)
return MENURESULT_QUIT;
if (subitem->data.action.close_menu)
return MENURESULT_CLOSE;
return MENURESULT_OK;
subitem->event_func (subitem, MENUEVENT_SELECT);
return subitem->data.action.menu_result; return MENURESULT_QUIT;
case MENUITEM_CHECKBOX:
if (subitem->data.checkbox.allow_gray) {
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)
subitem->event_func (subitem, MENUEVENT_UPDATE);
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUITEM_RING:
subitem->data.ring.value = (subitem->data.ring.value + 1) % LL_Length (subitem->data.ring.strings);
if (subitem->event_func)
subitem->event_func (subitem, MENUEVENT_UPDATE);
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUITEM_MENU:
case MENUITEM_SLIDER:
case MENUITEM_NUMERIC:
case MENUITEM_ALPHA:
if (subitem->event_func)
subitem->event_func (subitem, MENUEVENT_ENTER);
//if (subitem->event_func)
// subitem->event_func (subitem, MENUEVENT_ENTER);
return MENURESULT_ENTER;
default:
break;
@@ -368,7 +379,7 @@ MenuResult menu_handle_input (Menu *menu, MenuToken token, char * key)
menu->data.menu.scroll --;
}
}
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUTOKEN_DOWN:
if (menu->data.menu.selector_pos < LL_Length(menu->data.menu.contents) - 1) {
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) {
menu->data.menu.scroll ++;
}
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUTOKEN_OTHER:
/* TODO: move to the selected number and enter it */
return MENURESULT_OK;
return MENURESULT_NONE;
}
return MENURESULT_ERROR;
}
+10 -11
View File
@@ -8,20 +8,15 @@
* Copyright (c) 1999, William Ferrell, Scott Scriven
*
* Defines all the menu data and actions.
*
*/
#include "menuitem.h"
/* These headers are placed here on purpose ! (circular references) */
#ifndef MENU_H
#define MENU_H
struct MenuData;
#include "menuitem.h"
#include "shared/LL.h"
#include "screen.h"
#ifndef bool
# define bool short
# define true 1
@@ -31,11 +26,15 @@ struct MenuData;
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
#include "shared/LL.h"
typedef MenuItem Menu;
/* A Menu is a MenuItem too.
* This definition is only for better understanding of this code.
*/
#include "screen.h"
Menu *menu_create (char *id, MenuEventFunc(*event_func),
char *text, void *association);
/* Creates a new menu.
@@ -86,8 +85,8 @@ static inline MenuItem *menu_get_current_item (Menu *menu)
menu->data.menu.selector_pos);
}
MenuItem *menu_find_item (Menu *menu, char *id);
/* Retrieves the first item from the list of items in the menu. */
MenuItem *menu_find_item (Menu *menu, char *id, bool recursive);
/* Finds an item in the menu by the given id. */
void menu_reset (Menu *menu);
/* Resets it to initial state.
+134 -80
View File
@@ -24,6 +24,8 @@
#define MAX_NUMERIC_LEN 40
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_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_alpha (MenuItem *item, Screen *s);
MenuResult menuitem_handle_input_slider (MenuItem *item, MenuToken token, char * key);
MenuResult menuitem_handle_input_numeric (MenuItem *item, MenuToken token, char * key);
MenuResult menuitem_handle_input_alpha (MenuItem *item, MenuToken token, char * key);
MenuResult menuitem_process_input_slider (MenuItem *item, MenuToken token, char * key);
MenuResult menuitem_process_input_numeric (MenuItem *item, MenuToken token, char * key);
MenuResult menuitem_process_input_alpha (MenuItem *item, MenuToken token, char * key);
/******** FUNCTION TABLES ********/
/* Tables with functions to call for all different item types */
@@ -54,6 +57,7 @@ void (*destructor_table[NUM_ITEMTYPES] ) (MenuItem *item) =
{
menu_destroy,
NULL,
NULL,
menuitem_destroy_ring,
menuitem_destroy_slider,
menuitem_destroy_numeric,
@@ -90,15 +94,15 @@ void (*update_screen_table[NUM_ITEMTYPES] ) (MenuItem *item, Screen *s) =
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,
NULL,
NULL,
NULL,
menuitem_handle_input_slider,
menuitem_handle_input_numeric,
menuitem_handle_input_alpha
menuitem_process_input_slider,
menuitem_process_input_numeric,
menuitem_process_input_alpha
};
/******** METHODS ********/
@@ -138,16 +142,15 @@ MenuItem *menuitem_create (MenuItemType type, char *id, MenuEventFunc(*event_fun
}
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;
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->data.action.close_menu = close_menu;
new_item->data.action.quit_menu = quit_menu;
new_item->data.action.menu_result = menu_result;
return new_item;
}
@@ -171,33 +174,12 @@ MenuItem *menuitem_create_ring (char *id, MenuEventFunc(*event_func),
char *text, char *strings, short value)
{
MenuItem *new_item;
char *tabptr, *p, *new_s;
debug (RPT_DEBUG, "%s( id=\"%s\", event_func=%p, text=\"%s\", strings=\"%s\", value=%d )",
__FUNCTION__, id, event_func, text, strings, value);
new_item = menuitem_create (MENUITEM_RING, id, event_func, text);
/* 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.strings = tablist2linkedlist (strings);
new_item->data.ring.value = value;
return new_item;
@@ -246,7 +228,6 @@ MenuItem *menuitem_create_alpha (char *id, MenuEventFunc(*event_func),
char *allowed_extra, char *value)
{
MenuItem *new_item;
char * chars;
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);
@@ -256,24 +237,15 @@ MenuItem *menuitem_create_alpha (char *id, MenuEventFunc(*event_func),
new_item->data.alpha.minlength = minlength;
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);
strncpy (new_item->data.alpha.value, value, maxlength);
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);
return new_item;
@@ -335,7 +307,7 @@ void menuitem_destroy_alpha (MenuItem *item)
debug (RPT_DEBUG, "%s( item=\"%s\" )", __FUNCTION__, item->id);
/* 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.edit_str);
}
@@ -611,8 +583,8 @@ void menuitem_update_screen_alpha (MenuItem *item, Screen *s)
if (item->data.alpha.password_char == 0) {
strcpy (w->text, item->data.alpha.edit_str);
} else {
memset (item->data.alpha.edit_str, 0, item->data.alpha.maxlength+1);
memset (item->data.alpha.edit_str, item->data.alpha.password_char, strlen (item->data.alpha.edit_str));
memset (w->text, 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;
@@ -629,23 +601,23 @@ void menuitem_update_screen_alpha (MenuItem *item, Screen *s)
/******** 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);
/* Call type specific screen building function */
handle_input = handle_input_table [item->type];
if (handle_input ) {
return handle_input (item, token, key);
process_input = process_input_table [item->type];
if (process_input ) {
return process_input (item, token, key);
} else {
report (RPT_ERR, "%s: given menuitem cannot be active", __FUNCTION__);
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);
@@ -658,20 +630,20 @@ MenuResult menuitem_handle_input_slider (MenuItem *item, MenuToken token, char *
item->data.slider.value + item->data.slider.stepsize);
if (item->event_func)
item->event_func (item, MENUEVENT_PLUS);
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUTOKEN_DOWN:
item->data.slider.value = max (item->data.slider.minvalue,
item->data.slider.value - item->data.slider.stepsize);
if (item->event_func)
item->event_func (item, MENUEVENT_MINUS);
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUTOKEN_OTHER:
}
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 buf2[MAX_NUMERIC_LEN];
@@ -710,7 +682,7 @@ MenuResult menuitem_handle_input_numeric (MenuItem *item, MenuToken token, char
memset (str, 0, MAX_NUMERIC_LEN);
snprintf (str, MAX_NUMERIC_LEN, format_str, item->data.numeric.value);
}
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUTOKEN_ENTER:
if (str[pos] == 0) {
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.edit_pos = 0;
return MENURESULT_OK;
return MENURESULT_NONE;
}
/* OK, store value */
@@ -746,13 +718,13 @@ MenuResult menuitem_handle_input_numeric (MenuItem *item, MenuToken token, char
item->data.numeric.edit_pos ++;
}
}
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUTOKEN_UP:
if (pos >= max_len) {
/* We're not allowed to add anything anymore */
item->data.numeric.error_code = 2;
item->data.numeric.edit_pos = 0;
return MENURESULT_OK;
return MENURESULT_NONE;
}
if (allow_signed && pos == 0) {
/* make negative */
@@ -767,13 +739,13 @@ MenuResult menuitem_handle_input_numeric (MenuItem *item, MenuToken token, char
str[pos] = '0';
}
}
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUTOKEN_DOWN:
if (pos >= max_len) {
/* We're not allowed to add anything anymore */
item->data.numeric.error_code = 2;
item->data.numeric.edit_pos = 0;
return MENURESULT_OK;
return MENURESULT_NONE;
}
if (allow_signed && pos == 0) {
/* make negative */
@@ -788,28 +760,28 @@ MenuResult menuitem_handle_input_numeric (MenuItem *item, MenuToken token, char
str[pos] = '9';
}
}
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUTOKEN_OTHER:
if (pos >= max_len) {
/* We're not allowed to add anything anymore */
item->data.numeric.error_code = 2;
item->data.numeric.edit_pos = 0;
return MENURESULT_OK;
return MENURESULT_NONE;
}
/* proces numeric keys */
if ( strlen(key) == 1 && key[0] >= '0' && key[0] <= '9') {
str[pos] = key[0];
item->data.numeric.edit_pos ++;
}
return MENURESULT_OK;
return MENURESULT_NONE;
}
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 * chars = item->data.alpha.allowed_chars;
static char * chars = NULL;
/* To make life easy... */
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);
/* 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 */
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);
strcpy (str, item->data.alpha.value);
}
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUTOKEN_ENTER:
if (str[item->data.alpha.edit_pos] == 0) {
/* The user completed his input */
@@ -839,7 +822,7 @@ MenuResult menuitem_handle_input_alpha (MenuItem *item, MenuToken token, char *
/* It's not too short ? */
if (strlen (item->data.alpha.edit_str) < item->data.alpha.minlength) {
item->data.alpha.error_code = 3;
return MENURESULT_OK;
return MENURESULT_NONE;
}
/* Store value */
@@ -857,13 +840,13 @@ MenuResult menuitem_handle_input_alpha (MenuItem *item, MenuToken token, char *
item->data.alpha.edit_pos ++;
}
}
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUTOKEN_UP:
if (pos >= item->data.alpha.maxlength) {
/* We're not allowed to add anything anymore */
item->data.alpha.error_code = 2;
item->data.numeric.edit_pos = 0;
return MENURESULT_OK;
return MENURESULT_NONE;
}
if (str[pos] == 0) {
/* User goes past EOL */
@@ -878,13 +861,13 @@ MenuResult menuitem_handle_input_alpha (MenuItem *item, MenuToken token, char *
str[pos] = 0;
}
}
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUTOKEN_DOWN:
if (pos >= item->data.alpha.maxlength) {
/* We're not allowed to add anything anymore */
item->data.alpha.error_code = 2;
item->data.numeric.edit_pos = 0;
return MENURESULT_OK;
return MENURESULT_NONE;
}
if (str[pos] == 0) {
/* User goes past EOL */
@@ -902,21 +885,92 @@ MenuResult menuitem_handle_input_alpha (MenuItem *item, MenuToken token, char *
str[pos] = 0;
}
}
return MENURESULT_OK;
return MENURESULT_NONE;
case MENUTOKEN_OTHER:
if (pos >= item->data.alpha.maxlength) {
/* We're not allowed to add anything anymore */
item->data.alpha.error_code = 2;
item->data.numeric.edit_pos = 0;
return MENURESULT_OK;
return MENURESULT_NONE;
}
/* proces other keys */
if ( strlen(key) == 1 && key[0] >= ' ' && key[0] <= 'Z') {
str[pos] = key[0];
item->data.alpha.edit_pos ++;
}
return MENURESULT_OK;
return MENURESULT_NONE;
}
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 "screen.h"
#ifndef bool
# define bool short
# define true 1
@@ -42,7 +40,6 @@
*/
#define NUM_ITEMTYPES 7
typedef enum MenuItemType { /* These values are used in the */
MENUITEM_MENU = 0, /* function tables in menuitem.c ! */
MENUITEM_ACTION = 1,
@@ -69,7 +66,7 @@ typedef enum MenuToken {
/* Return codes from an input handler */
typedef enum MenuResult {
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
menuitem now */
MENURESULT_CLOSE, /* Token handled OK, close the current
@@ -78,16 +75,15 @@ typedef enum MenuResult {
} MenuResult;
/* Events caused by a menuitem */
#define NUM_EVENTTYPES 4
typedef enum MenuEventType {
MENUEVENT_ENTER, /* Item has been entered
(menu opened, action chosen)
Can be used to trigger one-time update of
the items in a menu. */
MENUEVENT_SELECT = 0, /* Item has been selected
(action chosen) */
MENUEVENT_UPDATE, /* Item has been modified
(checkbox, numeric, alphanumeric) */
MENUEVENT_PLUS, /* Item has been modified in positive direction
(slider moved) */
MENUEVENT_MINUS /* Item has been modified in negative direction
MENUEVENT_MINUS, /* Item has been modified in negative direction
(slider moved) */
} MenuEventType;
@@ -121,8 +117,9 @@ typedef struct MenuItem {
LinkedList *contents; /* What's in this menu */
} menu;
struct action {
bool close_menu; /* Close active menu ? */
bool quit_menu; /* Close entire menu ? */
enum MenuResult menu_result;
/* What to do when selected ?
Nothing, close or quit ? */
} action;
struct checkbox {
bool allow_gray; /* Is CHECKBOX_GRAY allowed ? */
@@ -143,7 +140,7 @@ typedef struct MenuItem {
struct numeric {
int maxvalue;
int minvalue;
short allowed_decimals; /* Number of numbers behind dot */
//short allowed_decimals; /* Number of numbers behind dot */
int value; /* Current value */
char *edit_str; /* Value while being edited */
short edit_pos; /* Position while editing */
@@ -153,7 +150,10 @@ typedef struct MenuItem {
char password_char; /* For passwords */
short minlength;
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 *edit_str; /* Value while being edited */
short edit_pos; /* Position while editing */
@@ -163,6 +163,8 @@ typedef struct MenuItem {
} MenuItem;
#include "screen.h"
/*********************************************************************
* 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),
char *text, bool close_menu, bool quit_menu);
char *text, MenuResult menu_result);
/* Creates a an action item (a string only).
* 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.
*/
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.
* 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
+51 -45
View File
@@ -46,11 +46,10 @@ Menu * screens_menu;
void menuscreen_create_menu ();
MenuEventFunc (menuscreen_heartbeat);
MenuEventFunc (menuscreen_backlight);
MenuEventFunc (menuscreen_contrast);
MenuEventFunc (menuscreen_brightness);
MenuEventFunc (menuscreen_screens);
MenuEventFunc (heartbeat_handler);
MenuEventFunc (backlight_handler);
MenuEventFunc (contrast_handler);
MenuEventFunc (brightness_handler);
int init_menu()
{
@@ -126,13 +125,13 @@ void menuscreen_key_handler (char *key)
return;
}
res = menuitem_handle_input (active_menuitem, token, key);
res = menuitem_process_input (active_menuitem, token, key);
switch (res) {
case MENURESULT_ERROR:
report (RPT_ERR, "%s: Error from menu_handle_input", __FUNCTION__);
break;
case MENURESULT_OK:
case MENURESULT_NONE:
/* Nothing extra to be done */
break;
case MENURESULT_ENTER:
@@ -189,13 +188,13 @@ void menuscreen_create_menu ()
options_menu = menu_create ("options", NULL, "Options", NULL);
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);
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);
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);
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);
menu_add_item (options_menu, driver_menu);
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);
}
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);
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);
}
}
@@ -224,11 +223,11 @@ void menuscreen_create_menu ()
test_menu = menu_create ("test", NULL, "Test menu", NULL);
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);
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);
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);
test_item = menuitem_create_checkbox ("", NULL, "Checkbox", false, false);
@@ -255,7 +254,7 @@ void menuscreen_create_menu ()
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);
@@ -268,7 +267,7 @@ MenuEventFunc (menuscreen_heartbeat)
return 0;
}
MenuEventFunc (menuscreen_backlight)
MenuEventFunc (backlight_handler)
{
debug (RPT_DEBUG, "%s( item=%s, event=%d )", __FUNCTION__, item->id, event);
@@ -282,7 +281,7 @@ MenuEventFunc (menuscreen_backlight)
return 0;
}
MenuEventFunc (menuscreen_contrast)
MenuEventFunc (contrast_handler)
{
debug (RPT_DEBUG, "%s( item=%s, event=%d )", __FUNCTION__, item->id, event);
@@ -302,7 +301,7 @@ MenuEventFunc (menuscreen_contrast)
return 0;
}
MenuEventFunc (menuscreen_brightness)
MenuEventFunc (brightness_handler)
{
debug (RPT_DEBUG, "%s( item=%s, event=%d )", __FUNCTION__, item->id, event);
@@ -324,39 +323,46 @@ MenuEventFunc (menuscreen_brightness)
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) {
/* We are entering this menu */
Screen * s;
Menu * m;
MenuItem * mi;
debug (RPT_DEBUG, "%s( Screen=\"%s\" )", __FUNCTION__, s->id);
/* Clean the screens menu */
menu_destroy_all_items (screens_menu);
if (!screens_menu)
return; /* When screens have not been created ... */
/* Read list of screens */
for (s = LL_GetFirst(screenlist_getlist()); s; s = LL_GetNext(screenlist_getlist())) {
/* Create a menu entry for the screen */
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);
menu_add_item (screens_menu, m);
mi = menuitem_create_action ("", NULL, "To Front", MENURESULT_QUIT);
menu_add_item (m, mi);
mi = menuitem_create_action ("", NULL, "To Front", true, true);
menu_add_item (m, mi);
mi = menuitem_create_checkbox ("", NULL, "Visible", false, true);
menu_add_item (m, mi);
mi = menuitem_create_checkbox ("", NULL, "Visible", false, true);
menu_add_item (m, mi);
mi = menuitem_create_numeric ("", NULL, "Duration", 2, 3600, s->duration);
menu_add_item (m, mi);
mi = menuitem_create_numeric ("", NULL, "Duration", 2, 3600, s->duration);
menu_add_item (m, mi);
mi = menuitem_create_numeric ("", NULL, "Priority", 0, 255, s->priority);
menu_add_item (m, mi);
}
mi = menuitem_create_numeric ("", NULL, "Priority", -1, 4, s->priority);
menu_add_item (m, mi);
}
}
return 0;
void
menuscreen_remove_screen (Screen * s)
{
Menu * m;
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"
extern Screen * menuscreen;
extern MenuItem * active_menuitem;
extern Menu * main_menu;
int init_menu();
@@ -30,5 +32,10 @@ void menuscreen_key_handler (char *key);
/* 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...
*/
#define MAX_ARGUMENTS 256
#define MAX_ARGUMENTS 40
int
parse_all_client_messages ()
parse_all_client_messages2 ()
{
int i; /* int j, len;*/
/*int newtoken, inquote;*/
@@ -182,3 +182,181 @@ parse_all_client_messages ()
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;
}
menuscreen_add_screen (s);
return s;
}
@@ -86,6 +88,10 @@ screen_destroy (Screen * s)
if (!s)
return -1;
menuscreen_remove_screen (s);
screenlist_remove (s);
for (w=LL_GetFirst(s->widgetlist); w; w=LL_GetNext(s->widgetlist)) {
/* Free a widget...*/
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
#define SCREEN_H
#include "shared/LL.h"
#include "client.h"
typedef struct Screen {
char *id;
@@ -31,13 +37,13 @@ typedef struct Screen {
struct Client *client;
} Screen;
#include "client.h"
#include "widget.h"
extern int default_duration ;
extern int default_priority ;
#include "client.h"
/* Creates a new screen */
Screen * screen_create (char * id, Client * client);
+35 -50
View File
@@ -22,6 +22,7 @@
#include "shared/report.h"
#include "drivers/lcd.h"
#include "drivers.h"
#include "clients.h"
#include "screen.h"
@@ -31,60 +32,46 @@
Screen * server_screen;
char title[256] = "LCDproc Server";
char one[256] = "";
char two[256] = "";
char three[256] = "";
#define MAX_SERVERSCREEN_WIDTH 40
int
server_screen_init ()
{
Widget * w;
int line;
debug (RPT_DEBUG, "server_screen_init");
/* Create the screen */
server_screen = screen_create ("_server_screen", NULL);
if (!server_screen) {
report (RPT_ERR, "server_screen_init: Error allocating screen");
return -1;
}
server_screen->name = "Server screen";
server_screen->duration = 8; /* 1 second, instead of 4...*/
server_screen->priority = -1; /* TODO: use priorities good */
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;
/* Create all the widgets...*/
for (line=1; line<=4; line++) {
char id[8];
sprintf (id, "line%d", line);
w = widget_create (id, WID_STRING, server_screen);
if (!w) {
report (RPT_ERR, "server_screen_init: Can't create a widget");
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*/
screenlist_add (server_screen);
@@ -97,13 +84,10 @@ int
update_server_screen (int timer)
{
Client * c;
Widget * w;
int num_clients;
/*screen *s;*/
int num_screens;
/* Draw a title...*/
/*strcpy(title, "LCDproc Server");*/
/* Now get info on the number of connected clients...*/
num_clients = clients_client_count();
@@ -115,19 +99,20 @@ update_server_screen (int timer)
/* Format strings for the appropriate size display... */
if (display_props->height >= 3) {
snprintf (one, sizeof(one), "Clients: %i", num_clients);
snprintf (two, sizeof(two), "Screens: %i", num_screens);
w = screen_find_widget (server_screen, "line2");
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 {
if (display_props->width >= 20)
snprintf (one, sizeof(one), "%i Client%s, %i Screen%s", num_clients,
(num_clients == 1) ? "" : "s", num_screens,
(num_screens == 1) ? "" : "s");
else /* 16x2 size*/
snprintf (one, sizeof(one), "%i Cli%s, %i Scr%s", num_clients,
(num_clients == 1) ? "" : "s", num_screens,
(num_screens == 1) ? "" : "s");
w = screen_find_widget (server_screen, "line2");
/*if (display_props->width >= 20)*/
snprintf (w->text, MAX_SERVERSCREEN_WIDTH,
"Cli: %i Scr: %i",
num_clients, num_screens);
/*else * 16x2 size */
}
return 0;
}