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:
+17
-21
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user