1 Overview of writing code using the menu system
2 ----------------------------------------------
4 This file contains implementation and developer documentation.
5 For simple cases, you should start by using simple.c as a template.
6 complex.c illustrates most of the features available in the menu system.
8 Menu Features currently supported are:
13 * invisible items (useful for dynamic menus), and
15 * Context sensitive help
20 * Arrow Keys, PgUp, PgDn, Home, End Keys
21 * Space to switch state of a checkbox
22 * Enter to choose the item
23 * Escape to exit from it
29 The code usually consists of many stages.
31 * Configuring the menusytem
32 * Installing global handlers [optional]
33 * Populating the menusystem
34 * Executing the menusystem
35 * Processing the result
37 1.1 Configuring the menusystem
38 ------------------------------
39 This includes setting the window the menu system should use,
40 the choice of colors, the title of the menu etc. In most functions
41 calls, a value of -1 indicates that the default value be used.
42 For details about what the arguments are look at function
43 declarations in menu.h
46 // Choose the default title and setup default values for all attributes....
47 init_menusystem(NULL);
48 set_window_size(1,1,23,78); // Leave one row/col border all around
50 // Choose the default values for all attributes and char's
51 // -1 means choose defaults (Actually the next 4 lines are not needed)
52 set_normal_attr (-1,-1,-1,-1);
53 set_status_info (-1,-1);
54 set_title_info (-1,-1);
55 set_misc_info(-1,-1,-1,-1);
58 1.2 Populating the menusystem
59 -----------------------------
60 This involves adding a menu to the system, and the options which
61 should appear in the menu. An example is given below.
64 MAINMENU = add_menu(" Menu Title ",-1);
66 add_item("option1","Status 1",OPT_RUN,"kernel1 arg1=val1",0);
67 add_item("selfloop","Status 2",OPT_SUBMENU,NULL,MAINMENU);
69 add_item("checkbox,"Checkbox Info",OPT_CHECKBOX,NULL,CHECKED);
70 add_item("Exit ","Status String",OPT_EXITMENU,NULL,0);
71 // "any string" not used by the menu system, useful for storing kernel names
72 // NUM = index of submenu if OPT_SUBMENU,
73 // 0/1 default checked state if OPT_CHECKBOX
77 The call to add_menu has two arguments, the first being the title of
78 the menu and the second an upper bound on the number of items in the menu.
79 Putting a -1, will use the default (see MENUSIZE in menu.h). If you try
80 to add more items than specified, the extra items will not appear in
81 the menu. The accuracy of this number affects the memory required
82 to run the system. Currently the code compiles to a .COM file which
83 has a 64K limit on memory used.
85 The call to add_item has five arguments.
86 The first argument is the text which appears in the menu itself.
87 The second argument is the text displayed in the status line.
88 The third argument indicates the type of this menuitem. It is one of
91 * OPT_RUN : executable content
92 * OPT_EXITMENU : exits menu to parent
93 * OPT_SUBMENU : if selected, displays a submenu
94 * OPT_CHECKBOX : associates a boolean with this item which can be toggled
95 * OPT_RADIOMENU: associates this with a radio menu.
96 After execution, the data field of this item will point
97 to the option selected.
98 * OPT_SEP : A menu seperator (visually divide menu into parts)
99 * OPT_RADIOITEM: this item is one of the options in a RADIOMENU
100 * OPT_INACTIVE : A disabled item (user cannot select this)
101 * OPT_INVISIBLE: This item will not be displayed.
103 The fourth argument is the value of the data field. This pointer is just
104 stored. In case of a radiomenu this points to the menuitem chosen (Dont
105 forget to typecase this pointer to (t_menuitem *) when reading this info).
107 The fifth argument is a number whose meaning depends on the type of the
108 item. For a CHECKBOX it should be 0/1 setting the initial state of the
109 checkbox. For a SUBMENU it should be the index of the menu which should
110 be displayed if this option is chosen. For a RADIOMENU it should be the
111 index of the menu which contains all the options (All items in that menu
112 should not of type RADIOITEM are ignored). For all other types, this
113 argument has no meaning at all.
115 A call to add_sep is a convenient shorthand for calling add_item
116 with the type set to OPT_SEP.
118 1.3 Executing the menusystem
119 ----------------------------
120 This is the simplest of all. Just call showmenus, with the index
121 of the main menu as its argument. It returns a pointer to the menu
122 item which was selected by the user.
125 choice = showmenus(MAIN); // Initial menu is the one with index MAIN
128 1.4 Processing the result
129 -------------------------
130 This pointer will either be NULL (user hit Escape) or always point
131 to a menuitem which can be "executed", i.e. it will be of type OPT_RUN.
132 Usually at this point, all we need to do is to ask syslinux to run
133 the command associated with this menuitem. The following code executes
134 the command stored in choice->data (there is no other use for the data
135 field, except for radiomenu's)
140 if (choice->action == OPT_RUN)
142 if (syslinux) runcommand(choice->data);
143 else csprint(choice->data,0x07);
146 csprint("Error in programming!",0x07);
152 Everycall to add_item actually returns a pointer to the menuitem
153 created. This can be useful when using any of the advanced features.
157 For example, every menuitem has an "extra_data" field (a pointer)
158 which the user can use to point any data he/she pleases. The menusystem
159 itself does not use this field in anyway.
163 Every item also has a field called "helpid". It is meant to hold some
164 kind of identifier which can be referenced and used to generate
165 a context sensitive help system. This can be set after a call to
168 add_item("selfloop","Status 2",OPT_SUBMENU,NULL,MAINMENU);
169 set_item_options('A',4516);
172 The first is the shortcut key for this entry. You can put -1 to ensure
173 that the shortcut key is not reset. The second is some unsigned integer.
174 If this value is 0xFFFF, then the helpid is not changed.
176 2.3 Installing global handlers
177 ------------------------------
178 It is possible to register handlers for the menu system. These are
179 user functions which are called by the menusystem in certain
180 situations. Usually the handlers get a pointer to the menusystem
181 datastructure as well as a pointer to the current item selected.
182 Some handlers may get additional information. Some handlers are
183 required to return values while others are not required to do so.
185 Currently the menusystem support three types of global handlers
190 2.3.1 timeout handler
191 ---------------------
192 This is installed using a call to "reg_ontimeout(fn,numsteps,stepsize)"
193 function. fn is a pointer to a function which takes no arguments and
194 returns one of CODE_WAIT, CODE_ENTER, CODE_ESCAPE. This function is
195 called when numsteps*stepsize Centiseconds have gone by without any
196 user input. If the function returns CODE_WAIT then the menusystem
197 waits for user input (for another numsteps*stepsize Centiseconds). If
198 CODE_ENTER or CODE_ESCAPE is returned, then the system pretends that
199 the user hit ENTER or ESCAPE on the keyboard and acts accordingly.
203 This is installed using a call to "reg_handler(HDLR_SCREEN,fn)". fn is
204 a pointer to a function which takes a pointer to the menusystem
205 datastructure and the current item selected and returns nothing.
206 This is called everytime a menu is drawn (i.e. everytime user changes
207 the current selection). This is meant for displaying any additional
208 information which reflects the current state of the system.
212 This is installed using a call to "reg_handler(HDLR_KEYS,fn)". fn is
213 a pointer to a function which takes a pointer to the menusystem
214 datastructure, the current item and the scan code of a key and returns
215 nothing. This function is called when the user presses a key which
216 the menusystem does not know to dealwith. In any case, when this call
217 returns the screen should not have changed in any way. Usually,
218 one can change the active page and display any output needed and
219 reset the active page when you return from this call.
221 complex.c implements a key_handler, which implements a simple
222 context sensitive help system, by displaying the contents of a
223 file whose name is based on the helpid of the active item.
225 Also, complex.c's handler allows certain users to make changes
226 to edit the commands associated with a menu item.
228 2.4 Installing item level handlers
229 ----------------------------------
230 In addition to global handlers, one can also install handlers for each
231 individual item. A handler for an individual item is a function which
232 takes a pointer to the menusystem datastructure and a pointer to the
233 current item and return a structure of type t_handler_return. Currently
234 it has two bit fields "valid" and "refresh".
236 This handler is called when the user hits "enter" on a RUN item, or
237 changes the status of a CHECKBOX, or called *after* a radio menu choice
238 has been set. In all other cases, installing a handler has no effect.
240 The handler can change any of the internal datastructures it pleases.
241 For e.g. in a radiomenu handler, one can change the text displayed
242 on the menuitem depending on which choice was selected (see complex.c
243 for an example). The return values are ignored for RADIOMENU's.
245 In case of RUN items: the return values are used as follows. If the
246 return value of "valid" was false, then this user choice is ignored.
247 This is useful if the handler has useful side effects. For e.g.
248 complex.c has a Login item, whose handler always return INVALID. It
249 sets a global variable to the name of the user logged in, and enables
250 some menu items, and makes some invisible items visible.
252 * If the handler does not change the visibility status of any items,
253 the handler should set "refresh" to 0.
254 * If the handler changes the visibility status of items in the current
255 menu set "refresh" to 1.
256 * If you are changing the visibility status of items in menu's currently
257 not displayed, then you can set "refresh" to 0.
258 * Changing the visibility status of items in another menu
259 which is currently displayed, is not supported. If you do it,
260 the screen contents may not reflect the change until you get to the
261 menu which was changed. When you do get to that menu, you may notice
262 pieces of the old menu still on the screen.
264 In case of CHECKBOXES: the return value of "valid" is ignored. Because,
265 the handler can change the value of checkbox if the user selected value
266 is not appropriate. only the value of "refresh" is honored. In this case
267 all the caveats in the previous paragraph apply.
269 menu.h defines two instances of t_handler_return
270 ACTION_VALID and ACTION_INVALID for common use. These set the valid flag
271 to 1 and 0 respectively and the refresh flag to 0.
273 3. Things to look out for
274 -------------------------
275 When you define the menu system, always declare it in the opposite
276 order, i.e. all lower level menu's should be defined before the higher
277 level menus. This is because in order to define the MAINMENU, you need
278 to know the index assigned to all its submenus.
280 4. Additional Modules
281 ---------------------
282 You can make use of the following additional modules, in writing your
290 This module was written by Th. Gebhardt. This is basically a modification
291 of the DES crypt function obtained by removing the dependence of the
292 original crypt function on C libraries. The following functions are
295 init_passwords(PWDFILE)
296 // Read in the password database from the file
297 authenticate_user(user,pwd)
298 // Checks if user,pwd is valid
300 // Checks if the user has a specified permission
302 // Unloads password database from memory
304 See the sample password file for more details about the file format
305 and the implementation of permissions.
307 See complex.c for a example of how to use this.
311 This can be used to set up a context sensitive help system. The following
312 functions are defined
314 init_help(HELPBASEDIR)
315 // Initialises the help system. All help files will be loaded
316 // from the directory specified.
317 runhelpsystem(context)
318 // Displays the contents of HELPBASEDIR/hlp<context>.txt
320 In order to have a functioning help system, you just need to create
321 the hlp<NNNNN>.txt files and initialize the help system by specifying
324 The first line of this file assumed to be the title of the help screen.
325 You can use ^N and ^O to change attributes absolutely and relatively,
326 i.e. [^O]46 (i.e. Ctrl-O followed by chars 4 and 6) will set the
327 attribute to 46, while [^N]08 will XOR the current attribute with
328 specified number, thus in this case the first [^N]08 will turn on
329 highlighting and the second one will turn it off.