/******************************************************************** Richard's Menu Tools July 1990 Revision 1.0 Released as public domain ********************************************************************/ #define TRUE 1 #define FALSE 0 #include "alloc.h" #include "conio.h" #include "rmt10.h" /******************************************************************** Name : menu_show_item Input : menu-pointer entry number to show selected-state flag Output: none Descr.: displays the entry which corresponds to the entry-number in normal,selected or disabled color (depends on selected-state flag and entry status) and highlights the hot-key-char. if entry is enabled. ********************************************************************/ void menu_show_item(void *mnu_ptr, unsigned ent_nr, int selflg) { char *bstr; struct mnu_entry *ment; struct mnu_hdr *mhdr; char blstr[82]; bstr = " "; /* init pointer */ mhdr = mnu_ptr; ment = mnu_ptr; ment += ent_nr * mnu_esize + mnu_hsize; strncpy(blstr,bstr,mhdr->maxmsg+2); blstr[mhdr->maxmsg+2] = 0; if (ment->status & mnu_selectable) if (selflg) { textattr(mhdr->mcolor); gotoxy(39-div(mhdr->maxmsg,2),mhdr->msgln); cprintf("%s",blstr); gotoxy(40-div(strlen(ment->msg),2),mhdr->msgln); printf("%s",ment->msg); textattr(mhdr->scolor); } else textattr(mhdr->ncolor); else textattr(mhdr->dcolor); gotoxy(ment->x,ment->y); cprintf("%s",ment->txt); /* if (!selflg && ment->status & mnu_selectable) { */ if ((ment->status & mnu_selectable) == 1) { if (!selflg) textattr(mhdr->hcolor); else textattr((mhdr->scolor & 0xf0) | (mhdr->hcolor & 0x0f)); gotoxy(ment->x + ment->HKpos,ment->y); cprintf("%c",ment->txt[ment->HKpos]); } } /******************************************************************** Name : menu-proc Input : menu-pointer Output: number of selected entry (-1 if 'ESC' is pressed) Descr.: processes the menu in a way that it takes care of highliting the current entry, checking all the pressed keys, calling an entry-function(if enabled) and returns the number of the selected entry. ********************************************************************/ char menu_proc(void *mnu_ptr) { struct mnu_hdr *mhdr; struct mnu_entry *ment; int pos_cnt,old_pos,cur_pos; unsigned *ent_cnt; int key; int spkey; int retval; int act_entry,mnu_ex; int i; /* init pointer */ mhdr = mnu_ptr; ment = mnu_ptr; ment += mnu_hsize; pos_cnt = 0; while (((ment->status & mnu_selectable) == 0) && (pos_cnt < mhdr->cnt-1)) { ment = mnu_ptr; ment += ++pos_cnt * mnu_esize + mnu_hsize; } menu_show_item(mnu_ptr, pos_cnt,TRUE); do { do { key = getch(); if (key == 0) { /* scan-code following for special-key */ spkey = TRUE; key = getch(); } else { spkey = FALSE; if (key >= 'a' && key <= 'z') key -= 32; } menu_show_item(mnu_ptr, pos_cnt,FALSE); old_pos = pos_cnt; act_entry = mnu_ex = FALSE; do { switch (spkey) { case TRUE: switch (key) { case 75: if ((mhdr->status & mnu_horact) != 0) { pos_cnt--; if (pos_cnt < 0) pos_cnt = mhdr->cnt - 1; } else if ((mhdr->status & mnu_horsel) != 0) { act_entry = TRUE; } break; case 72: if ((mhdr->status & mnu_veract) != 0) { pos_cnt--; if (pos_cnt < 0) pos_cnt = mhdr->cnt - 1; } else if ((mhdr->status & mnu_versel) != 0) { act_entry = TRUE; } break; case 77: if ((mhdr->status & mnu_horact) != 0) { pos_cnt++; if (pos_cnt == mhdr->cnt) pos_cnt = 0; } else if ((mhdr->status & mnu_horsel) != 0) { act_entry = TRUE; } break; case 80: if ((mhdr->status & mnu_veract) != 0) { pos_cnt++; if (pos_cnt == mhdr->cnt) pos_cnt = 0; } else if ((mhdr->status & mnu_versel) != 0) { act_entry = TRUE; } break; } break; case FALSE: switch (key) { case 13: act_entry = TRUE; break; case 27: mnu_ex = TRUE; break; default: for (i = 0; i < mhdr->cnt; i++) { cur_pos = (old_pos + i + 1) % mhdr->cnt; ment = mnu_ptr; ment += cur_pos * mnu_esize + mnu_hsize; if (ment->status & mnu_selectable && ment->HKey == key) { pos_cnt = cur_pos; act_entry = mhdr->status & mnu_autoselect; break; } } break; } } ment = mnu_ptr; ment += pos_cnt * mnu_esize + mnu_hsize; } while (!(ment->status & mnu_selectable) && old_pos != pos_cnt); menu_show_item(mnu_ptr, pos_cnt,TRUE); } while (!act_entry && !mnu_ex); if (ment->func != NULL && !mnu_ex) { (*ment->func)(); menu_show_item(mnu_ptr, pos_cnt,FALSE); menu_show_item(mnu_ptr, pos_cnt,TRUE); } else mnu_ex = TRUE; } while (!mnu_ex); if (act_entry) retval = pos_cnt; else retval = -1; return(retval); } /******************************************************************** Name : menu_add Input : menu-pointer x-position of the entry y-position of the entry entry-text corresponding message line hot-key-char. position (entry-textv relative) hot-key-char. status: bit 0: mnu_selectable - entry selectable entry-function Output: none Descr.: stores the information for the entry and shows it in normal state The different hot-key-char. position and hot-key-char. enables you to highlight one char. in the entry-text and make the menu respond to an other key (i.e. if you have a special char.-set) the entry-function will be called if the entry is selected, and the pointer is not NULL ********************************************************************/ void menu_add(void *mnu_ptr, int x, int y, char *ent_txt, char *ent_msg, int hkpos, char hk, int stat, void (*func)()) { struct mnu_hdr *mhdr; struct mnu_entry *ment; /* init pointer */ mhdr = mnu_ptr; ment = mnu_ptr; ment += mhdr->cnt * mnu_esize + mnu_hsize; /* save menu-entry data */ ment->x = x; ment->y = y; ment->txt = ent_txt; ment->msg = ent_msg; ment->HKpos = hkpos; ment->HKey = hk; ment->func = func; ment->status = stat; if (strlen(ent_msg) > mhdr->maxmsg) mhdr->maxmsg = strlen(ent_msg); (mhdr->cnt)++; /* show menu-entry text */ menu_show_item(mnu_ptr, mhdr->cnt - 1, FALSE); } /******************************************************************** Name : menu_init Input : number of menu enries color for normal entry (textattr-form: backgnd*16+foregnd) color for selected entry color for deactivated entry color for hot-key-char. color for message-line status: bit 0: mnu_autoselect - entries are selected by pressing the hotkey 1: mnu_horact - horizontal cursor-keys are active for moving 2: mnu_veract - vertical cursor-keys are active for moving 3: mnu_horsel - horizontal cursor-keys select entry 4: mnu_versel - vertical cursor-keys select entry y-position for message-line Output: pointer to allocated memory Descr.: Allocates the needed memory for the menu, saves the header data and returns the pointer to the allocated memory. ********************************************************************/ void *menu_init(size_t nr_ent, int nclr, int sclr, int dclr, int hclr, int mclr, int stat, int msgln) /* in: max_ent... number of menu entries out: pointer to reserved memory */ { void *mnu_ptr; struct mnu_hdr *mhdr; unsigned ccc; mhdr = mnu_ptr = malloc(nr_ent*sizeof(struct mnu_entry) + sizeof(struct mnu_hdr)); if (mnu_ptr != NULL) { mhdr->cnt = 0; /* entry counter */ mhdr->ncolor = nclr; /* normal entry color */ mhdr->scolor = sclr; /* selected entry color */ mhdr->dcolor = dclr; /* deactivated entry color */ mhdr->hcolor = hclr; /* hot-key-char. color */ mhdr->mcolor = mclr; /* message-line color */ mhdr->msgln = msgln; /* y-position of the message line */ mhdr->maxmsg = 0; /* length of the longest message line */ mhdr->status = stat; /* menu status */ } return(mnu_ptr); } /******************************************************************** Name : menu_exit Input : menu-pointer Output: none Descr.: Takes the pointer to the allocated memory for the menu and frees it. ********************************************************************/ void menu_exit(void *mnu_ptr) { free(mnu_ptr); }