/* Keep looking. */ ul_x += xinc; lr_x += xinc; ul_y += yinc; lr_y += yinc; if (ul_x < 0 || lr_x >= MODEL_2_COLS || ul_y < 0 || (size_t)lr_y >= KEYPAD_HEIGHT) break; } } #if defined(_WIN32) /*[*/ void keypad_click(int x, int y) { size_t i; if (!(menu_is_up & KEYPAD_IS_UP)) return; /* Find it. */ for (i = 0; i < NUM_SENSE; i++) { if (x >= sens[i].ul_x && y >= sens[i].ul_y && x <= sens[i].lr_x && y <= sens[i].lr_y) { push_macro(sens[i].callback, false); break; } } pop_up_keypad(false); }
/************************************************************************ ** get_actuals : Paren must already be found. If all the actuals can ** be read, the macro is pushed and expansion begins. Otherwise, ** this function is quickly exited and lets the tiny lexer take ** care of rescanning. ************************************************************************/ void get_actuals(pdefn_t pdef, int n_formals) { /* ** The only concern with this is that a rescan could finish while ** this is trying to collect actuals. When a rescan finishes, it ** may reset Act_ptr and Exp_ptr. Unless these are saved before the ** end of rescan is handled, the part of the actual collected so far ** would be lost. */ REG ptext_t start; UCHAR c; ptext_t actuals_start; int paste; int level; *Exp_ptr++ = PREVCH(); /* must be oparen */ level = 0; actuals_start = Act_ptr; while( level >= 0) { if(Exp_ptr >= ELIMIT) { fatal_in_macro(10056); } more_white: if( ! can_get_non_white()) { return; } if(CHARMAP(CHECKCH()) == LX_SLASH) { SKIPCH(); if(skip_comment()) { goto more_white; } else { start = Exp_ptr; *Exp_ptr++ = '/'; } } else { start = Exp_ptr; } paste = FALSE; for(;;) { switch(CHARMAP(c = GETCH())) { case LX_CPAREN: if(--level < 0) { goto leave_loop; } break; case LX_COMMA: /* ** if the comma is not at level == 0, it is part of ** a parenthesized list and not a delimiter */ if(level == 0) { goto leave_loop; } break; case LX_SLASH: if( ! skip_comment()) { break; } if(*(Exp_ptr - 1) == ' ') { continue; } c = ' '; break; case LX_CR: case LX_NL: case LX_WHITE: UNGETCH(); /* This char is valid white space */ if( ! can_get_non_white()) { return; } continue; break; case LX_OPAREN: ++level; break; case LX_DQUOTE: case LX_SQUOTE: Exp_ptr = gather_chars(Exp_ptr, c); continue; break; case LX_ID: *Exp_ptr++ = c; while(LXC_IS_IDENT(c = GETCH())) { if(Exp_ptr >= ELIMIT) { fatal_in_macro(10056); } *Exp_ptr++ = c; } if(CHARMAP(c) != LX_MACFORMAL) { UNGETCH(); continue; } paste = TRUE; /* ** FALLTHROUGH */ case LX_MACFORMAL: move_to_exp(do_macformal(&paste)); continue; break; case LX_STRFORMAL: move_to_exp_esc('"', do_strformal()); continue; break; case LX_CHARFORMAL: move_to_exp_esc('\'', do_strformal()); continue; break; case LX_EOS: /* ** Will saving this pointers create dead space in the ** buffers? Yes, but only temporarily. ** ** handle_eos() may reset Act_ptr and Exp_ptr to the ** beginning of the buffers if a rescan is finishing ** and Macro_depth is going to be 0. ANSI allows ** actuals to start within a macro defintion and be ** completed (further actuals and closing paren) later ** in the text. ** ** These buffer pointers will eventually be reset to ** the beginnings of their respective buffers when the ** macro for the actuals being collected right now ** finish rescan ** ** This is special handling for folks who use ** unbalanced parens in macro definitions */ { ptext_t Exp_save; ptext_t Act_save; int eos_res; Exp_save = Exp_ptr; Act_save = Act_ptr; if((eos_res = handle_eos()) & (ACTUAL_EOS | RESCAN_EOS)) { return; } Act_ptr = Act_save; Exp_ptr = Exp_save; if(eos_res == BACKSLASH_EOS) { /* ??? DFP QUESTION */ *Exp_ptr++ = c; /* save the \ */ c = get_non_eof(); /* get char following \ */ break; } } continue; break; } *Exp_ptr++ = c; } leave_loop: /* ** if the last character was whitespace, hose it */ if(CHARMAP(*(Exp_ptr - 1)) == LX_WHITE) { Exp_ptr--; } /* ** if Exp_ptr <= start, foo() was read, don't incr N_actuals */ if(Exp_ptr > start) { N_actuals++; move_to_actual(start, Exp_ptr); } *Exp_ptr++ = c; } P_actuals = actuals_start; if(n_formals < N_actuals) { Msg_Temp = GET_MSG (4002); SET_MSG (Msg_Text, Msg_Temp, Reuse_1); warning(4002); } else if(n_formals > N_actuals) { Msg_Temp = GET_MSG (4003); SET_MSG (Msg_Text, Msg_Temp, Reuse_1); warning(4003); } if(DEFN_TEXT(pdef)) { push_macro(pdef); expand_macro(); } else { /* ** the macro expands to nothing (no definition) ** This essentially means delete the macro and its actuals ** from the expanded text */ Act_ptr = P_actuals; /* reset pointer to get rid of actuals */ Exp_ptr = Save_Exp_ptr; /* delete macro & actuals from exp text */ } }
/************************************************************************ ** can_expand: tries to expand the macro passed to it - returns ** true if it succeeded in expanding it. It will only return FALSE ** if a macro name was found, a paren was expected, and a paren was ** not the next non white character. ************************************************************************/ int can_expand(pdefn_t pdef) { UCHAR c; int n_formals; int return_value = FALSE; Tiny_lexer_nesting = 0; Save_Exp_ptr = Exp_ptr; /* not necessarily EXP_BUFFER */ Macro_line = Linenumber; expand_name: P_actuals = Act_ptr; N_actuals = 0; n_formals = DEFN_NFORMALS(pdef); if( PRE_DEFINED(pdef) ) { push_macro(pdef); DEFN_EXPANDING(CURRENT_MACRO)++; if(rescan_expansion()) { return(TRUE); /* could expand macro */ } } else if( n_formals == 0 ) { return_value = TRUE; if(DEFN_TEXT(pdef)) { push_macro(pdef); expand_definition(); } else { /* ** Macro expands to nothing (no definition). Since it ** didn't have any actuals, Act_ptr is already correct. ** Exp_ptr must be changed however to delete the ** identifier from the expanded text. */ Exp_ptr = Save_Exp_ptr; } } else { if( n_formals == -1 ) { n_formals = 0; } name_comment_paren: if( can_get_non_white()) { if(CHARMAP(CHECKCH()) == LX_SLASH) { SKIPCH(); if(skip_comment()) { goto name_comment_paren; } else { UNGETCH(); } } if(CHARMAP(CHECKCH())==LX_OPAREN) { SKIPCH(); return_value = TRUE; get_actuals(pdef, n_formals); } else { /* ** #define xx(a) a ** xx bar(); ** don't lose white space between "xx" and "bar" */ ptext_t p = Exp_ptr; push_macro(pdef); DEFN_EXPANDING(CURRENT_MACRO)++; Exp_ptr = p; if( rescan_expansion() ) { return(FALSE); } } } else { } } /* ** makes sure a macro is being worked on. At this point, there will ** be a macro to expand, unless the macro expand_the_named_macro was ** passed had no definition text. If it had no defintion text, ** Tiny_lexer_nesting was not incremented. */ while(Tiny_lexer_nesting != 0) { if(Exp_ptr >= ELIMIT) { fatal_in_macro(10056); } switch(CHARMAP(c = GETCH())) { case LX_ID: case LX_MACFORMAL: Save_Exp_ptr = Exp_ptr; if(tl_getid(c) && ((pdef = get_defined())!= 0)) { if(DEFN_EXPANDING(pdef)) { /* ** the macro is already being expanded, so just ** write the do not expand marker and the ** identifier to the expand area. The do not ** expand marker is necessary so this macro ** doesn't get expanded on the rescan */ int len = Reuse_1_length - 1; *Exp_ptr++ = LX_NOEXPANDMARK; *Exp_ptr++ = ((UCHAR)len); } else { /* ** a legal identifier was read, it is defined, and ** it is not currently being expanded. This means ** there is reason to believe it can be expanded. */ goto expand_name; } } if(InIf &&(memcmp(Reuse_1, "defined", 8) ==0)) { do_defined(Reuse_1); } continue; break; case LX_NUMBER: /* getnum with Prep on to keep leading 0x on number */ { int Save_prep = Prep; Prep = TRUE; getnum(c); Prep = Save_prep; } continue; break; case LX_DOT: *Exp_ptr++ = '.'; dot_switch: switch(CHARMAP(c = GETCH())) { case LX_EOS: if(handle_eos() != BACKSLASH_EOS) { if(Tiny_lexer_nesting > 0) { goto dot_switch; } continue; } break; case LX_DOT: *Exp_ptr++ = '.'; if( ! checkop('.')) { break; /* error will be caught on rescan */ } *Exp_ptr++ = '.'; continue; break; case LX_NUMBER: *Exp_ptr++ = c; get_real(Exp_ptr); continue; } UNGETCH(); continue; case LX_CHARFORMAL: move_to_exp_esc('\'', do_strformal()); continue; break; case LX_STRFORMAL: move_to_exp_esc('"', do_strformal()); continue; break; case LX_DQUOTE: case LX_SQUOTE: /* ** gather_chars is called even though the error reported ** on overflow may need to be changed. */ Exp_ptr = gather_chars(Exp_ptr, c); continue; break; case LX_WHITE: while(LXC_IS_WHITE(GETCH())) { ; } UNGETCH(); c = ' '; break; case LX_EOS: if(handle_eos() == BACKSLASH_EOS) { *Exp_ptr++ = c; c = GETCH(); break; } continue; break; } *Exp_ptr++ = c; } return(return_value); }
/* Process a key event while the keypad is up. */ void keypad_key(int k, ucs4_t u) { if (!(menu_is_up & KEYPAD_IS_UP)) return; switch (k) { #if defined(NCURSES_MOUSE_VERSION) /*[*/ case MK_MOUSE: { MEVENT m; size_t i; if (getmouse(&m) != OK) return; if (!(m.bstate & (BUTTON1_PRESSED || BUTTON1_RELEASED))) return; /* Find it. */ for (i = 0; i < NUM_SENSE; i++) { if (m.x >= sens[i].ul_x && m.y >= sens[i].ul_y && m.x <= sens[i].lr_x && m.y <= sens[i].lr_y) { push_macro(sens[i].callback, false); break; } } pop_up_keypad(false); break; } #endif /*]*/ case MK_UP: find_adjacent(0, -1); break; case MK_DOWN: find_adjacent(0, 1); break; case MK_LEFT: find_adjacent(-1, 0); break; case MK_RIGHT: find_adjacent(1, 0); break; case MK_HOME: /* Find the first entry. */ current_sens = &sens[0]; break; case MK_END: /* Find the last entry. */ current_sens = &sens[NUM_SENSE - 1]; break; case MK_ENTER: push_macro(current_sens->callback, false); pop_up_keypad(false); break; case MK_NONE: switch (u) { case '\r': case '\n': push_macro(current_sens->callback, false); break; default: break; } pop_up_keypad(false); break; default: case MK_OTHER: pop_up_keypad(false); break; } screen_changed = true; }