From: acilia@mail.ptl.com.mt (Andrew Cilia) Newsgroups: comp.databases.informix Subject: Table-driven ring menu Date: 30 Sep 1997 09:33:26 -0400 #ident "@(#)menpro:Menu Processor" define men_array array[2,32] of record men_mncd like mndt_tabl.mndt_mncd, men_numb like mndt_tabl.mndt_numb, men_type like mndt_tabl.mndt_type, men_text char(37), men_path like mndt_tabl.mndt_path end record, men_start like mndt_tabl.mndt_mncd, dbe_xplan char(30) main define f_user char(10) defer interrupt defer quit let f_user = fgl_getenv("LOGNAME") open window menwind at 2,2 with 22 rows, 78 columns attribute (border) let dbe_xplan=fgl_getenv("DBEXPLAIN") if dbe_xplan = "Y" then set explain on else set explain off end if let men_start=fgl_getenv("MENU") call show_menu(men_start) end main function show_menu(wrk_mncd) define wrk_mncd char(6), end_menu char(1), men_idx1 smallint, men_idx2 smallint, sav_indx smallint, f_date date, wrk_mnnm like mnms_tabl.mnms_mnnm let end_menu = "N" while end_menu = "N" clear window menwind let f_date = today select mnms_mnnm into wrk_mnnm from mnms_tabl where mnms_tabl.mnms_mncd = wrk_mncd display wrk_mnnm, " ", g_user.user_logn, f_date using "dd/mm/yyyy", " ", wrk_mncd at 03,01 attribute(reverse) call fgl_drawbox(1,78,20,1) display " " at 20,1 display " " at 20,78 menu men_array[1,1].men_mncd before menu declare men_curs cursor for select * from mndt_tabl where mndt_mncd = wrk_mncd for men_idx1 = 1 to 32 let men_array[1,men_idx1].men_text = men_idx1 using "&&" initialize men_array[2,men_idx1].* to null end for let men_idx1 = 1 let men_idx2 = 1 foreach men_curs into men_array[2,men_idx2].men_mncd, men_array[2,men_idx2].men_numb, men_array[2,men_idx2].men_type, men_array[2,men_idx2].men_text, men_array[2,men_idx2].men_path if men_array[2,men_idx2].men_type = "P" or men_array[2,men_idx2].men_type = "F" or men_array[2,men_idx2].men_type = "M" then let men_array[2,men_idx2].men_text = men_idx1 using "&&", "-", men_array[2,men_idx2].men_text let men_array[1,men_idx1].* = men_array[2,men_idx2].* let men_idx1 = men_idx1 + 1 if men_array[2,men_idx2].men_type = "M" then let men_array[2,men_idx2].men_text = men_array[2,men_idx2].men_text clipped, " ..." end if end if let men_idx2 = men_idx2 + 1 end foreach let sav_indx = men_idx2 -1 for men_idx1 = men_idx1 to 32 hide option men_array[1,men_idx1].men_text end for if sav_indx < 9 then call scr1_loop(4,20,1,sav_indx) else if sav_indx > 8 and sav_indx < 16 then call scr1_loop(4,20,1,sav_indx) else call scr1_loop(4,2,1,sav_indx/2) call scr1_loop(4,41,(sav_indx/2)+1,sav_indx) end if end if command men_array[1,1].men_text if run_option (men_array[1,1].*) = "M" then exit menu end if command men_array[1,2].men_text if run_option (men_array[1,2].*) = "M" then exit menu end if command men_array[1,3].men_text if run_option (men_array[1,3].*) = "M" then exit menu end if command men_array[1,4].men_text if run_option (men_array[1,4].*) = "M" then exit menu end if command men_array[1,5].men_text if run_option (men_array[1,5].*) = "M" then exit menu end if command men_array[1,6].men_text if run_option (men_array[1,6].*) = "M" then exit menu end if command men_array[1,7].men_text if run_option (men_array[1,7].*) = "M" then exit menu end if command men_array[1,8].men_text if run_option (men_array[1,8].*) = "M" then exit menu end if command men_array[1,9].men_text if run_option (men_array[1,9].*) = "M" then exit menu end if command men_array[1,10].men_text if run_option (men_array[1,10].*) = "M" then exit menu end if command men_array[1,11].men_text if run_option (men_array[1,11].*) = "M" then exit menu end if command men_array[1,12].men_text if run_option (men_array[1,12].*) = "M" then exit menu end if command men_array[1,13].men_text if run_option (men_array[1,13].*) = "M" then exit menu end if command men_array[1,14].men_text if run_option (men_array[1,14].*) = "M" then exit menu end if command men_array[1,15].men_text if run_option (men_array[1,15].*) = "M" then exit menu end if command men_array[1,16].men_text if run_option (men_array[1,16].*) = "M" then exit menu end if command men_array[1,17].men_text if run_option (men_array[1,17].*) = "M" then exit menu end if command men_array[1,18].men_text if run_option (men_array[1,18].*) = "M" then exit menu end if command men_array[1,19].men_text if run_option (men_array[1,19].*) = "M" then exit menu end if command men_array[1,20].men_text if run_option (men_array[1,20].*) = "M" then exit menu end if command men_array[1,21].men_text if run_option (men_array[1,21].*) = "M" then exit menu end if command men_array[1,22].men_text if run_option (men_array[1,22].*) = "M" then exit menu end if command men_array[1,23].men_text if run_option (men_array[1,23].*) = "M" then exit menu end if command men_array[1,24].men_text if run_option (men_array[1,24].*) = "M" then exit menu end if command men_array[1,25].men_text if run_option (men_array[1,25].*) = "M" then exit menu end if command men_array[1,26].men_text if run_option (men_array[1,26].*) = "M" then exit menu end if command men_array[1,27].men_text if run_option (men_array[1,27].*) = "M" then exit menu end if command men_array[1,28].men_text if run_option (men_array[1,28].*) = "M" then exit menu end if command men_array[1,29].men_text if run_option (men_array[1,29].*) = "M" then exit menu end if command men_array[1,30].men_text if run_option (men_array[1,30].*) = "M" then exit menu end if command men_array[1,31].men_text if run_option (men_array[1,31].*) = "M" then exit menu end if command men_array[1,32].men_text if run_option (men_array[1,32].*) = "M" then exit menu end if command key (Esc,"E","X") let end_menu = "Y" Exit Menu command "Quit" let end_menu = "Y" Exit Menu end menu end while end function function run_option(wrk_recd) define wrk_recd record wrk_mncd like mndt_tabl.mndt_mncd, wrk_numb like mndt_tabl.mndt_numb, wrk_type like mndt_tabl.mndt_type, wrk_text char(37), wrk_path like mndt_tabl.mndt_path end record, wrk_rowid integer if wrk_recd.wrk_type = "M" then call show_menu(wrk_recd.wrk_path) else if wrk_recd.wrk_type = "P" then run wrk_recd.wrk_path clipped else if wrk_recd.wrk_type = "F" then call redirector(wrk_recd.wrk_path) end if end if end if return wrk_recd.wrk_type end function function scr1_loop(strt_line, strt_post, strt_indx, stop_indx) define strt_line smallint, strt_post smallint, strt_indx smallint, stop_indx smallint for strt_indx = strt_indx to stop_indx display men_array[2,strt_indx].men_text at strt_line, strt_post let strt_line = strt_line + 1 end for end function The schemas of the tables you will need are below: create table mnms_tabl ( mnms_mncd char(6) not null, mnms_synm char(30) not null, mnms_mnnm char(40) not null ); create unique cluster index mnms_idx1 on mnms_tabl(mnms_mncd); create table mndt_tabl ( mndt_mncd char(6) not null, mndt_numb smallint not null, mndt_type char(1) not null, mndt_text char(34) not null, mndt_path char(34) not null ); create unique cluster index mndt_idx1 on mndt_tabl (mndt_mncd,mndt_numb); Just a little explanation: MNMS is the Menu header which contains a system name and a menu name. This is linked to MNDT in a one to many relationship where each MNDT is a menu option. The row contains a sequence number, an option type, the text of the option and a path to the executable or function. Now there are 4 mndt_types: "T" is just text which is displayed on the screen, "M" which leads to a submenu (i.e. mndt_path must contain a menu code), "P" which runs a free-standing program (i.e. mndt_path must contain something like "fglgo xyz" or "vi xyz.4gl") and finally "F" which leads to a function. Since I have not found any way to call a variable function name, "F" is implemented via a function called redirector which is a massive case statement of the form "CASE function when "a()" call a() when "b()" call b() .... otherwise display "don't know that one!" The program takes care of centering the options on the screen and looks pretty good. If you get this working and make it sexier, please send me a copy. Andrew Cilia - Philip Toledo Limited At 14:11 29/09/97 -0400, you wrote: >MIS Dept wrote: >> >> We're modifying our menu structure for our homegrown Informix code. Instead of creating >> a ring menu with all various front-end programs linked into a single executable, we're >> looking to split out the various front-ends into separate executables, then create a >> table-driven menu structure. While we can make a 'drop down' style menu relatively >> easy, we would like to keep the ring menu structure for our user community. Any way to >> create a table-driven ring menu? I figure that someone may have already asked this >> question, but I could find no reference in the newsgroup archive. > >Here's a kludge to accomplish this: > >1) Initialize arrays of strings for menu choices and prompts to NULL. >2) In the code, physically before executing the menu statement, fetch > the actual choices and prompts into the array. >3) Create a menu with the maximum number of items possible using > an array of variables for the choice and prompt strings for all. In > the code for BEFORE MENU clause test if the choice for each array > element corresponding to the menu item is NULL, if NULL execute HIDE > OPTION choice[n] otherwise execute SHOW OPTION choice[n]. >4) The command for each choice (except any fixed choices like EXIT) > would be a call to a function, passing the choice number or name, > which would execute the appropriate code based on the argument(s) > passed to it. This function could be written in 4GL with a big case > statement or "C" using an array of function names or id#s and > function pointers. > >You get the picture. The only rub is the phrase "maximum possible >number of choices" this may be hard to determine at coding time. > >Art S. Kagel >