/*--------------------------------------------------------------------------*/ /* MEN.C a point and shoot menu function */ /*--------------------------------------------------------------------------*/ is_select( struct key_in *nkey, int pass_backsp_q /*LG_YES treats backspace as a printable char */ ) { if(nkey->mou_chng_q == LG_YES) { if(nkey->mou_l_bt == LG_YES) return(LG_YES); else return(R_ERR); } else if(nkey->have_char_q == LG_YES) { if(nkey->is_ext_q == LG_YES) return(R_ERR); else if(nkey->charin == '\r') return(LG_YES); else if(nkey->charin == '\b') { if(pass_backsp_q == LG_YES) return(LG_NO); else return(R_ERR); } else if(isprint(nkey->charin)) return(LG_NO); else return(R_ERR); } else return(LG_NO); /*if no nonmovement key or button at all pressed */ } /*----------------------------------*/ struct menu_dat { char *men_line[] /*see p 231, 237*/ int num_lines; int first_option; /*position of first selectable line, or equal to */ /* num_lines if none */ int last option; enum {choose_upcase, choose_any} valid_option; } /*----------------------------------*/ x_menu( struct menu_dat *curr_menu ) { char c; struct key_in *nkey; int a, i, men_width, curr_line, new_line; /* 1. set up the menu */ men_width = max_strlen_in_arr_ptrstr(curr_menu->men_line, curr_menu->num_lines); menu_border(cur_menu->num_lines,men_width); /* set up the menu space */ for(i=0; i < num_lines; i++) /* c. write the lines into it, marking one */ { if(i == first_option) v_attr = NORMAL_VIDEO; else v_attr = REVERSE_VIDEO; put_a_line(curr_menu, i, v_attr, men_width); } cursoff(); curr_line=curr_menu->first_option; /* 2. get in a response */ for(;;) { get_mov_ch(nkey, 8, 24); if(nkey->have_move_q) { /* if its a move, make it, clamping the new position within the menu */ new_line=iclamp( (curr_line+nkey->down_move), curr_menu->first_option, curr_menu->last_option ); cur_line=shift_highlited_line(cur_menu, curr_line, new_line, men_width); } a=is_select( nkey, LG_NO ) if(a == R_ERR) return(R_ERR); /*invalid response */ else if(a == LG_NO) { if(nkey->have_char_q) { if(curr_menu->valid_option == choose_upcase) return(toupper(nkey->charin)); else return(nkey->charin); } else continue; } else if(a == LG_YES) /* parse selection under the cursor, and return that */ { if(curr_menu->valid_option == choose_any) /*if it can be lowercase */ b=opt_str_parse(curr_menu->men_line[curr_line], LG_YES); else b=opt_str_parse(curr_menu->men_line[curr_line], LG_NO); return(b); } } } /*-----------------------------------------------------*/ put_a_line( struct menu_dat *curr_menu, int i, char v_attr, int width ) { scrnputs( i,0, /* on the left edge of screen */ curr_menu->men_line[i], ' ', v_attr, /* select attribute and fill with spaces */ men_width, LG_NO /*don't restore cursor pos */ ); } /*----------------------------------------------------------------------*/ int shift_highlited_line(struct menu_dat *menu, int o_line, int n_line, int men_width) { put_a_line(menu, o_line, REVERSE_VIDEO, men_width); /*unmark the old line */ put_a_line(menu, n_line, NORMAL_VIDEO, men_width); /* and set the new one */ return(n_line); } /*------------------------------------------------------------*/ int opt_str_parse(char *opt_str, int take_lowcase_q) { int c,i; for(i=0;;i++) { c=opt_str[i]; if(c == NULL_BYTE) return(R_ERR);/*end of string: report failure */ else if(isspace(c)) continue; /* ignore spaces, tabs, etc. */ else if(islower(c)) { if(take_lowcase_q == LG_YES) /*it can be lowercase */ return(c); else continue } else return(c); /* if it isn't any of those, it must be an */ /* uppercase, numeral, or punctuation mark */ /* which are always acceptable */ } } /*-----------------------------------------------------*/ menu_border(int rows, int cols) /* use (0,0) to reset, else the number of */ { /* rows and cols to be enclosed */ static int old_rows; static int old_cols; if((rows == 0) && (cols == 0)) /*reset*/ old_rows=old_cols=0; else { /* 1. if the new menu does not cover the old one, blank the old one */ if((old_rows > rows) || (old_cols > cols)) w_roll(0,old_rows, 0, old_cols, old_rows, REVERSE_VIDEO); /* 2. if room, place the botton border */ if( rows < screen_size.rows) { poscurs(rows,0); writechs(E_ASC_LN_DRW_2_HOR, REVERSE_VIDEO, cols); } /* 3. if room, place the right border */ if( cols < screen_size.cols) for(i=0; ((i < rows) && (i < screensize.rows)); i++) { poscurs(i,cols); writechs(E_ASC_LN_DRW_2_VERT, REVERSE_VIDEO, 1); } /* 4. and likewise the bottom corner */ if( (rows < screen_size.rows) && (cols < screen_size.cols) ) { poscurs(rows, cols); writechs(E_ASC_LN_DRW_2_LW_RT, HIGHLIGHT, 1); } } }