home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************/
- /* File Id. Lmenu.C */
- /* Author. Stan Milam. */
- /* Date Written. 05/08/89. */
- /* */
- /* (c) Copyright 1989, 1990 by Stan Milam */
- /* */
- /* Comments: The routines in this file allow the creation*/
- /* and use of Lotus style menus. Moreover, more than one */
- /* Lotus menu per window is allowed. More than one menu */
- /* can be stacked into one window. The Mouse can be used */
- /* to make selection and scroll the menus or the arrow & */
- /* PgDn/PgUp keys can be used. Home & End keys move to */
- /* first and last menus respectively. */
- /**********************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <conio.h>
- #include "pcw.i"
- #include "pcwproto.h"
- #include "menu.h"
- #include "keys.h"
-
- #define MSGROW 2
- #define ITEMROW 1
-
- /* Prototype the internal functions */
-
- static void change_menu(LMNUTYPE *menu);
- static void change_bar_pos(LMNUTYPE *menu, int crnt_bar);
- static int search_menu(LMNUTYPE *menu, int select_char);
- static int search_mouse_select(LMNUTYPE *menu, int col);
- static int get_max_bars(LMNUFLDS *ltmp);
-
- /***********************************************************/
- /* Makelmenu */
- /* */
- /* This function when invoked will draw the Lotus menu */
- /* pointed to by *menu. See the LMNUTYPE definition in */
- /* menu.h. */
- /***********************************************************/
-
- WNDPTR *makelmenu(LMNUTYPE *menu) {
-
- MENU_WND *lwnd; /* Pointer to menu window */
-
- lwnd = &menu->lwnd; /* Establish adressablity */
- setborder(lwnd->btype); /* Set borders & colors */
- titlecolor(lwnd->tfclr, lwnd->tbclr);
- bordercolor(lwnd->bfclr, lwnd->bbclr);
-
- lwnd->wnd = wframe(lwnd->urow, lwnd->ucol, /* Frame the menu window */
- lwnd->lrow, lwnd->lcol, /* and store handle in */
- lwnd->fcolor, lwnd->bcolor); /* menu structure */
- if (lwnd->wnd == NULL) return(NULL); /* Check to see of okay */
-
- lwnd->urow = lwnd->wnd->urow; /* Wframe may have */
- lwnd->ucol = lwnd->wnd->ucol; /* adjusted boundries */
- lwnd->lrow = lwnd->wnd->lrow;
- lwnd->lcol = lwnd->wnd->lcol;
-
- qputchar(lwnd->urow+1,lwnd->ucol,lwnd->bfclr,lwnd->bbclr,24); /* Draw the arrows */
- qputchar(lwnd->urow+1,lwnd->lcol,lwnd->bfclr,lwnd->bbclr,25);
-
- wtitle(lwnd->wnd, lwnd->tvloc, lwnd->thloc, lwnd->title); /* Title wnd */
- change_menu(menu); /* Fill window with menu */
- return(lwnd->wnd); /* Contents & return */
- }
-
- /***********************************************************/
- /* LmenuInput */
- /* */
- /* When invoked will manipulate Lotus menu. Returns the */
- /* select_key in the LMNUFLDS. */
- /***********************************************************/
-
- int lmenuinput(LMNUTYPE *menu) {
-
- LMNUFLDS *ltmp, **stmp; /* Pointers to menus */
- MENU_WND *lwnd; /* Pointer the menu parms */
- int ch; /* For keyin() function */
- int max_bars, max_menus; /* How many menus & bars */
- int crnt_wnd, crnt_bar; /* Keep track menus & bars */
- int row, col, bstatus; /* For Mouse */
-
- stmp = (LMNUFLDS **) menu->llist;
- ltmp = stmp[menu->wnd_pos]; /* Get address of 1st menu */
- lwnd = &menu->lwnd; /* Get address of wnd parms */
-
- if (mpresent) hide_mouse(); /* Turn the mouse off so */
- re_order(lwnd->wnd,NORMAL); /* We can reorder the windows */
- if (mpresent) show_mouse(); /* And finally turn it on */
- for (max_menus = 0;stmp[max_menus] != NULL;max_menus++);
- max_menus--; /* and adjust */
- max_bars = get_max_bars(ltmp); /* Get # selects this menu */
- if (mpresent) show_mouse(); /* Turn on the mouse */
- for(;;) { /* Loop forever */
-
- crnt_bar = menu->bar_pos; /* Track current bar pos */
- crnt_wnd = menu->wnd_pos; /* And menu position */
-
-
- ch = keyin();
- switch (ch) { /* Which one? */
- case RITE_MOUSE_KEY :
- case ESC: return(ESC); /* Wants to quit! */
- case BOTH_MOUSE_KEY :
- case ENTER : /* Selects bar pos */
- return(ltmp[menu->bar_pos].select_key);
- case LEFT_MOUSE_KEY :
- get_mpos(&row, &col, &bstatus); /* Get row, col, button stat */
- if (row == lwnd->wnd->urow+1) { /* Select row? */
- if (search_mouse_select(menu, col)) { /* If hot spot */
- change_bar_pos(menu,crnt_bar); /* Change */
- return(ltmp[menu->bar_pos].select_key); /* return */
- }
- else {
- if (col == lwnd->wnd->ucol) { /* Up arrow? */
- menu->wnd_pos--; /* Decrement menu index */
- if (menu->wnd_pos < 0) /* Check if okay */
- menu->wnd_pos = max_menus; /* No - last menu */
- menu->bar_pos = 0; /* First bar pos */
- change_menu(menu); /* Next menu */
- ltmp = stmp[menu->wnd_pos]; /* Address new menu */
- max_bars = get_max_bars(ltmp); /* # bars new menu */
- }
- else { /* Down arrow */
- if (col == lwnd->wnd->lcol) {
- menu->wnd_pos++;
- if (stmp[menu->wnd_pos] == NULL)
- menu->wnd_pos = 0;
- menu->bar_pos = 0;
- change_menu(menu);
- ltmp = stmp[menu->wnd_pos];
- max_bars = get_max_bars(ltmp);
- }
- }
- }
- }
- break;
- case LEFTARROW : /* Prev bar pos */
- case SHFTTAB :
- menu->bar_pos--;
- if (menu->bar_pos < 0) /* Check if < 0 */
- menu->bar_pos = max_bars; /* Set to max bar */
- change_bar_pos(menu, crnt_bar); /* Change bar poisition */
- break;
- case RITEARROW : /* Next bar position */
- case TAB :
- menu->bar_pos++; /* Bump & check */
- if (ltmp[menu->bar_pos].select_key == '\0')
- menu->bar_pos = 0; /* First one if at end */
- change_bar_pos(menu, crnt_bar); /* Change bars */
- break;
- case UPARROW : /* Prev Menu */
- case PGUP:
- if (max_menus == 0) break;
- menu->wnd_pos--; /* Decrement menu index */
- if (menu->wnd_pos < 0) menu->wnd_pos = max_menus;
- menu->bar_pos = 0; /* Set bar index to first */
- change_menu(menu); /* Put out new menu */
- ltmp = stmp[menu->wnd_pos]; /* Address new menu */
- max_bars = get_max_bars(ltmp); /* Count its selections */
- break;
- case DOWNARROW : /* Next menu */
- case PGDN:
- if (max_menus == 0) break;
- menu->wnd_pos++; /* Bump menu index */
- if (stmp[menu->wnd_pos] == NULL) /* See if at end */
- menu->wnd_pos = 0; /* And set to first */
- menu->bar_pos = 0; /* First bar of menu */
- change_menu(menu); /* Put out new menu */
- ltmp = stmp[menu->wnd_pos]; /* Address new menu */
- max_bars = get_max_bars(ltmp); /* Count the selects */
- break;
- case HOME : /* First menu */
- if (menu->wnd_pos == 0) break;
- menu->bar_pos = menu->wnd_pos = 0;
- change_menu(menu);
- ltmp = stmp[0];
- max_bars = get_max_bars(ltmp);
- break;
- case END: /* Last Menu */
- if (menu->wnd_pos == max_menus) break;
- menu->bar_pos = 0;
- menu->wnd_pos = max_menus;
- change_menu(menu);
- ltmp = stmp[menu->wnd_pos];
- max_bars = get_max_bars(ltmp);
- break;
- default :
- if (search_menu(menu, ch)) { /* Search for select match */
- if (crnt_wnd != menu->wnd_pos) { /* In another menu? */
- change_menu(menu); /* Put out new menu */
- ltmp = stmp[menu->wnd_pos]; /* Address new menu */
- return(ltmp[menu->bar_pos].select_key); /* Return */
- }
- if (crnt_bar != menu->bar_pos) { /* Same menu,another bar */
- change_bar_pos(menu, crnt_bar); /* Chg bar pos */
- return(ltmp[menu->bar_pos].select_key); /* Return */
- }
- else /* Must be crnt bar */
- return(ltmp[menu->bar_pos].select_key); /* So Return */
- }
- }
- }
- #ifndef __TURBOC__
- return ( (char) 0 );
- #endif
- }
-
- /***********************************************************/
- /* Change_Menu */
- /* */
- /* When invoked puts menu pointed to by menu->wnd_pos in */
- /* the window. Bar position is determined by menu->bar_pos*/
- /***********************************************************/
-
- static void change_menu(LMNUTYPE *menu) {
-
- int lcv1, col, length;
- LMNUFLDS *ltmp, **stmp;
- MENU_WND *lwnd;
-
- lwnd = &menu->lwnd;
- stmp = (LMNUFLDS **) menu->llist;
- ltmp = stmp[menu->wnd_pos];
- if (mpresent) hide_mouse();
- clr_wnd(lwnd->wnd, 1);
- for (lcv1 = 0; ltmp[lcv1].select_key != (char) NULL; lcv1++)
- wputs(lwnd->wnd, ITEMROW, ltmp[lcv1].select_col, ltmp[lcv1].item);
-
- col = ltmp[menu->bar_pos].select_col;
- length = strlen(ltmp[menu->bar_pos].item);
- w_chg_attr(lwnd->wnd,ITEMROW, col, lwnd->cfclr, lwnd->cbclr, length);
- wputs(lwnd->wnd, MSGROW, 2, ltmp[menu->bar_pos].item_msg);
- if (mpresent) show_mouse();
- }
-
- /***********************************************************/
- /* Search_Menu */
- /* */
- /* Searches thru all menus looking for a select_key match */
- /* with keyboard input. All characters are converted to */
- /* upper case. Returns non-zero if found. Zero if not */
- /* found. If a match is found the menu index and bar index*/
- /* are changed to point to the selected item. */
- /***********************************************************/
-
- static int search_menu(LMNUTYPE *menu, int select_char) {
-
- LMNUFLDS *ltmp, **stmp; /* Menu Pointers */
- int lcv1, lcv2, ch; /* Index variables */
-
- stmp = (LMNUFLDS **) menu->llist; /* Address menu lists */
- select_char = toupper(select_char); /* Uppercase keybd input */
- for (lcv1 = 0; stmp[lcv1] != NULL; lcv1++) { /* Get the menu list */
- ltmp = stmp[lcv1]; /* One menu list at a time */
- for (lcv2 = 0; ltmp[lcv2].select_key != (char) NULL; lcv2++) {
- ch = (char) toupper(ltmp[lcv2].select_key); /* Uppercase select_key */
- if (ch == select_char) { /* Do they match ? */
- menu->bar_pos = lcv2; /* Set bar index */
- menu->wnd_pos = lcv1; /* Set menu index */
- return(1); /* Return TRUE */
- }
- }
- }
- return (0); /* No matches */
- }
-
- /**********************************************************/
- /* Search_Mouse_Select */
- /* */
- /* Runs through all items in a menu to determine if the */
- /* rat was on the item. If a match is found the bar index*/
- /* is updated to reflect the selected item and we return */
- /* a non-zero return code to indicate a match was found. */
- /**********************************************************/
-
- static int search_mouse_select(LMNUTYPE *menu, int col) {
-
- MENU_WND *lwnd;
- LMNUFLDS *ltmp, **stmp;
- int lcv, item_len, item_col;
-
- lwnd = &menu->lwnd; /* Establish Addressability */
- stmp = (LMNUFLDS **) menu->llist;
- ltmp = stmp[menu->wnd_pos];
-
- if (col > lwnd->wnd->ucol) col -= lwnd->wnd->ucol; /* If inside the window determine column in the window */
- else return(0); /* Otherwise not in window so exit */
- for (lcv = 0; ltmp[lcv].select_key != '\0'; lcv++) { /* Search thru all items in list */
- item_col = ltmp[lcv].select_col; /* Get items column */
- item_len = (item_col + strlen(ltmp[lcv].item)) - 1; /* Determine its length on the screen */
- if (col >= item_col && col <= item_len) { /* If mouse on the item */
- menu->bar_pos = lcv; /* Set the bar index */
- return(1); /* Return True */
- }
- }
- return(0); /* No match found */
- }
-
- /**********************************************************/
- /* Change_Bar_Pos */
- /* */
- /* Changes the bar position in the window by changing the */
- /* attribute of the current bar to normal window attribute*/
- /* and changing the attribute of the new item to the color*/
- /* specified for bar color. Got it. Okay, test in five */
- /* minutes! */
- /**********************************************************/
-
- static void change_bar_pos(LMNUTYPE *menu, int crnt_bar) {
-
- int row, col, length;
- LMNUFLDS *ltmp, **stmp;
- MENU_WND *lwnd;
-
- lwnd = &menu->lwnd; /* Establish addressability */
- stmp = (LMNUFLDS **) menu->llist;
- ltmp = stmp[menu->wnd_pos];
- if (mpresent) hide_mouse(); /* If rat home hide from neighbors! */
- length = strlen(ltmp[crnt_bar].item); /* Get length of item on screen */
- col = ltmp[crnt_bar].select_col; /* Get its column */
- w_chg_attr(lwnd->wnd,ITEMROW,col,lwnd->fcolor,lwnd->bcolor,length);/* Change its color attribute */
-
- length = strlen(ltmp[menu->bar_pos].item); /* Get length of new item */
- col = ltmp[menu->bar_pos].select_col; /* Get its column */
- w_chg_attr(lwnd->wnd,ITEMROW,col, lwnd->cfclr, lwnd->cbclr,length);/* Change its color attribute */
-
- col = lwnd->wnd->ucol + 1; /* Now, must clear the message line */
- row = lwnd->wnd->urow + 2;
- length = (lwnd->wnd->lcol - 1) - col;
- qhchar(row, col, lwnd->fcolor, lwnd->bcolor, 32, length); /* Clear the line */
- wputs(lwnd->wnd, 2,2, ltmp[menu->bar_pos].item_msg); /* And write then new message */
- if (mpresent) show_mouse(); /* Finally turn back on the mouse */
- }
-
- /**********************************************************/
- /* Get_Max_Bars */
- /* */
- /* Used to count how many selections for a given menu. */
- /**********************************************************/
-
- static int get_max_bars(LMNUFLDS *ltmp) {
-
- int i;
-
- for (i = 0; ltmp[i].select_key != '\0'; i++); i--;
- return(i);
- }
-