/***********************************************************************\ Editor mined menu handling part \***********************************************************************/ #include "syntax.h" #include "mined.h" #include "io.h" #include "termprop.h" /***********************************************************************\ Menu types and aux. function \***********************************************************************/ typedef struct { char * menuname; int menulen; menuitemtype * menuitems; } menutype; typedef struct { char * (* dispflag) (); void (* toggle) (); char * menutitle; menuitemtype * menu; int menulen; } flagitemtype; static void dummyfunc () { } void fill_menuitem (item, s) menuitemtype * item; char * s; { /* init menuitemtype struct to null */ menuitemtype nullitem; memcpy ((void *) item, (void *) & nullitem, sizeof (menuitemtype)); if (s) { item->itemname = s; item->itemfu = dummyfunc; } else { item->itemname = ""; item->itemfu = separator; } item->hopitemname = ""; item->itemon = (flagfunc) dummyfunc; item->extratag = NIL_PTR; } /***********************************************************************\ Global variables \***********************************************************************/ /* mode tuning */ #define use_graphic_borders (menu_border_style != '@') local int popupmenumargin; local int flags_pos = 62; local int flags_displayed = 9; /* layout tuning */ local int pulldownmenu_width = 12; local int horizontal_bar_width = 1; local int extratag_length = 1; /* display status */ local FLAG popupmenu_active = False; local FLAG menuline_dirty = False; /* state */ local int first_dirty_line = -1; local int last_dirty_line = 0; local int last_menulen; local int last_menuwidth; local FLAG last_disp_only; local char * last_menutitle; /* state for menu history */ local FLAG menu_reposition = False; /* token to go to previous item */ local menuitemtype * last_fullmenu = 0; local menuitemtype * previous_fullmenu = 0; local int previous_menuline = -1; local int previous_scroll = -1; /* menu state for sub-menu positioning */ local int last_menucolumn; local int last_menuline; /* menu state and saved menu status for redrawmenu () */ local int last_popup_column; local int last_popup_line; local int last_popup_item; local int last_is_flag_menu; local int last_minwidth; local int last_scroll; local int last_maxscroll; local int last_popup_index; /***********************************************************************\ Local functions \***********************************************************************/ local void action_menu _((menuitemtype * menu, int menulen, int column, int line, char * title, FLAG is_flag_menu)); local void openmenu _((int i)); local void that_menu _((menuitemtype * menu)); local void unused handleInfomenu _((void)); local void unused handleCombiningmenu _((void)); local void unused handleTextmenu _((void)); local void unused handleBuffermenu _((void)); local void unused handleIndentmenu _((void)); local void unused handleJustifymenu _((void)); local void unused handleParagraphmodemenu _((void)); local void handleScreensizemenu _((void)); /***********************************************************************\ utf8_col_count () returns # of screen columns in the UTF-8 string \***********************************************************************/ local int utf8_col_count (string) char * string; { int count = 0; char * start = string; If string != NIL_PTR Then Dowhile * string != '\0' Do advance_utf8_scr (& string, & count, start); Done Fi return count; } /***********************************************************************\ Flag operations \***********************************************************************/ local void toggle_nothing () { } local char * dispnothing () { return " "; } local void toggle_HOP () { If hop_flag > 0 Then hop_flag = 0; Else hop_flag = 1; Fi displayflags (); } local char * dispHOP () { return hop_flag > 0 ? "#H" : "h"; } #ifdef debug_ring_buffer local char * disp_buffer_open () { static char f [3]; f [0] = '#'; f [1] = buffer_open_flag + '0'; f [2] = '\0'; return f; } #endif local void select_editmode (menu, i) menuitemtype * menu; int i; { If i == 0 Then EDITmode (); Else VIEWmode (); Fi } local char * dispVIEW () { return viewonly ? "#V" : "E"; } local int editorviewon (item, i) menuitemtype * item; int i; { return viewonly == i; } global void toggle_append () { If append_flag Then append_flag = False; Else append_flag = True; Fi displayflags (); } local void select_buffermode (menu, i) menuitemtype * menu; int i; { If i == 0 Then append_flag = False; Else append_flag = True; Fi } local void toggle_pastebuf_mode () { If pastebuf_utf8 Then pastebuf_utf8 = False; Else pastebuf_utf8 = True; Fi displayflags (); } local int pastebuf_utf8on (item, i) menuitemtype * item; int i; { return pastebuf_utf8; } local char * disppastebuf () { If pastebuf_utf8 && ! utf8_text Then If append_flag Then return "##+"; Else return "##="; Fi Else If append_flag Then return "#+"; Else return "="; Fi Fi } local int overwriteorappendon (item, i) menuitemtype * item; int i; { return append_flag == i; } local void toggle_autoindent () { If autoindent Then autoindent = False; Else autoindent = True; Fi } local void select_autoindent (menu, i) menuitemtype * menu; int i; { If i == 0 Then autoindent = True; Else autoindent = False; Fi } local char * disp_autoindent () { If autoindent Then return "#»"; Else return "#¦"; Fi } local int autoindenton (item, i) menuitemtype * item; int i; { return autoindent != i; } local int tabexpansionon (item, i) menuitemtype * item; int i; { return expand_tabs; } local void toggle_JUSlevel () { JUSlevel ++; If JUSlevel > 2 Then JUSlevel = 0; Fi } local void select_justify (menu, i) menuitemtype * menu; int i; { JUSlevel = i; } local char * dispJUSlevel () { If JUSlevel == 0 Then return "j"; Elsif JUSlevel == 1 Then return "#j"; Else return "#J"; Fi } local int justifymodeon (item, i) menuitemtype * item; int i; { return JUSlevel == i; } local void toggle_JUSmode () { JUSmode = 1 - JUSmode; } local void select_paragraph (menu, i) menuitemtype * menu; int i; { JUSmode = i; } local char * dispJUSmode () { return JUSmode == 1 ? "#«" : "# "; } local int paragraphmodeon (item, i) menuitemtype * item; int i; { return JUSmode == i; } local char * prev_text_encoding = ""; global void change_encoding (new_text_encoding) char * new_text_encoding; { If ! streq (get_text_encoding (), new_text_encoding) Then prev_text_encoding = get_text_encoding (); Fi (void) set_text_encoding (new_text_encoding, ' ', "men: change_encoding"); } global void toggle_encoding () { char * curpos = cur_text; char * new_prev_text_encoding = get_text_encoding (); If utf8_text && utf16_file Then error ("Text encoding not switchable when editing UTF-16 file"); ring_bell (); return; Fi /** Determine encoding to switch to: 1. Previously set text encoding (toggle) if defined 2. Terminal encoding if different from current text encoding 3. UTF-8 unless currently UTF-8 4. Latin-1 */ If * prev_text_encoding == '\0' Then prev_text_encoding = get_term_encoding (); If prev_text_encoding == new_prev_text_encoding Then If utf8_text Then prev_text_encoding = "ISO 8859-1"; Else prev_text_encoding = "UTF-8"; Fi Fi Fi /** Special case: instead of UTF-16, switch to UTF-8 unless it's current, then switch to Latin-1 */ If strisprefix ("UTF-16", prev_text_encoding) Then If utf8_text Then prev_text_encoding = "ISO 8859-1"; Else prev_text_encoding = "UTF-8"; Fi Fi If set_text_encoding (prev_text_encoding, ' ', "men: toggle_encoding") Then prev_text_encoding = new_prev_text_encoding; RD (); displaymenuline (); /* move cursor to or behind actual previous character position */ move_address (curpos, y); /* adjust not to stay amidst a character */ move_to (x, y); Fi } local void select_encoding (menu, i) menuitemtype * menu; int i; { char * curpos = cur_text; char * new_prev_text_encoding = get_text_encoding (); #ifdef selectable_term_encoding /* this is a debugging option */ If hop_flag Then If set_term_encoding (menu [i].hopitemname, ' ') Then RD (); move_address (curpos, y); move_to (x, y); Else ring_bell (); Fi return; Fi #endif If utf8_text && utf16_file Then error ("Text encoding not switchable when editing UTF-16 file"); ring_bell (); return; Fi If set_text_encoding (menu [i].hopitemname, ' ', "men: select_encoding") Then #ifdef cjk_term_constraint If cjk_term & ! cjk_text Then error ("Non-CJK text encoding not supported in CJK terminal"); ring_bell (); (void) set_text_encoding (new_prev_text_encoding, ' ', "men: select_encoding prev"); return; Fi #endif If ! streq (new_prev_text_encoding, menu [i].hopitemname) Then prev_text_encoding = new_prev_text_encoding; Fi RD (); menuline_dirty = True; /* move cursor to or behind actual previous character position */ move_address (curpos, y); /* adjust not to stay amidst a character */ move_to (x, y); Else error ("Selected encoding not supported in this version"); ring_bell (); return; Fi } local char encoding_flag [3]; local char * disp_encoding_1 () { encoding_flag [0] = '#'; encoding_flag [1] = text_encoding_flag [0]; encoding_flag [2] = '\0'; return encoding_flag; } local char * disp_encoding_2 () { encoding_flag [0] = '#'; encoding_flag [1] = text_encoding_flag [1]; encoding_flag [2] = '\0'; return encoding_flag; } local int encodingon (item, i) menuitemtype * item; int i; { return streq (item->hopitemname, get_text_encoding ()); } local void toggle_combining () { If encoding_has_combining () Then If combining_screen Then char * curpos = cur_text; If combining_mode Then combining_mode = False; Else combining_mode = True; Fi RD (); displaymenuline (); /* move cursor to actual previous character position */ move_address (curpos, y); /* adjust not to stay amidst a combined character */ /* move_to (x, y); */ Elsif ! combining_mode Then error ("Terminal cannot display combined characters"); Fi Fi } local void select_combining (menu, i) menuitemtype * menu; int i; { If encoding_has_combining () Then If combining_screen Then char * curpos = cur_text; FLAG old_combining_mode = combining_mode; If i == 0 Then combining_mode = True; Else combining_mode = False; Fi If combining_mode != old_combining_mode Then RD (); menuline_dirty = True; /* move cursor to actual previous character position */ move_address (curpos, y); Fi Elsif i == 0 Then error ("Terminal cannot display combined characters"); Fi Fi } local char * disp_combining () { If encoding_has_combining () Then If combining_screen && combining_mode Then return "ç"; Else return "##`"; Fi Else return " "; Fi } local int comborsepon (item, i) menuitemtype * item; int i; { return (! combining_mode) == i; } local char * disp_leftquote () { If smart_quotes Then return quote_mark (quote_type, 0); Else return " "; Fi } local char * disp_rightquote () { int utfcount; unsigned long unichar; char * quotemark; If smart_quotes Then quotemark = quote_mark (quote_type, 0); utf8_info (quotemark, & utfcount, & unichar); If iswide (unichar) Then /* left quote mark used up the space already */ return ""; Else /* proceed to right quote mark */ advance_utf8 (& quotemark); utf8_info (quotemark, & utfcount, & unichar); If iswide (unichar) Then /* no space to display */ return " "; Else return quotemark; Fi Fi Else return " "; Fi } local void toggle_HTML () { If dim_HTML Then dim_HTML = False; Else dim_HTML = True; Fi RD (); } local void select_keymap_entry (menu, i) menuitemtype * menu; int i; { /* strip off optional additional note from mapping tag */ /* this is actually obsolete already as additional notes are explicitly included in the menu table as extratag; leaving in the code for now just in case... */ char tag [55]; char * tp = tag; char * np = menu [i].hopitemname; Dowhile * np && * np != ' ' Do * tp ++ = * np ++; Done * tp = '\0'; /* set input method according to stripped tag */ setKEYMAP (tag); } local int keymapon (item, i) menuitemtype * item; int i; { return strisprefix (keyboard_mapping, item->hopitemname); } local int prev_quote_type = 0; local void select_quote_type (menu, i) menuitemtype * menu; int i; { prev_quote_type = quote_type; set_quote_type (i); } local void toggle_quote_type () { int prev = prev_quote_type; prev_quote_type = quote_type; set_quote_type (prev); } local int quoteon (item, i) menuitemtype * item; int i; { return quote_type == i; } local char km [3]; local char * dispKEYMAP0 () { If allow_keymap Then km [0] = '#'; km [1] = keyboard_mapping [0]; km [2] = '\0'; return km; Else return " "; Fi } local char * dispKEYMAP1 () { If allow_keymap Then km [0] = '#'; km [1] = keyboard_mapping [1]; km [2] = '\0'; return km; Else return " "; Fi } local char * dispinfo () { return "?"; } local void toggle_info () { } local void select_file_info () { hop_flag = 1; FS (); if (always_disp_fstat) { always_disp_code = False; if (! disp_Han_full) { always_disp_Han = False; } } } local void select_char_info () { hop_flag = 1; display_code (); if (always_disp_code) { always_disp_fstat = False; if (! disp_Han_full) { always_disp_Han = False; } } } local void select_Han_info () { always_disp_Han = ! always_disp_Han; if (always_disp_Han && ! disp_Han_full) { always_disp_fstat = False; always_disp_code = False; } } local void toggle_Mandarin () { disp_Han_Mandarin = ! disp_Han_Mandarin; If disp_Han_Mandarin Then always_disp_Han = True; Fi } local void toggle_Cantonese () { disp_Han_Cantonese = ! disp_Han_Cantonese; If disp_Han_Cantonese Then always_disp_Han = True; Fi } local void toggle_Japanese () { disp_Han_Japanese = ! disp_Han_Japanese; If disp_Han_Japanese Then always_disp_Han = True; Fi } local void toggle_Sino_Japanese () { disp_Han_Sino_Japanese = ! disp_Han_Sino_Japanese; If disp_Han_Sino_Japanese Then always_disp_Han = True; Fi } local void toggle_Hangul () { disp_Han_Hangul = ! disp_Han_Hangul; If disp_Han_Hangul Then always_disp_Han = True; Fi } local void toggle_Korean () { disp_Han_Korean = ! disp_Han_Korean; If disp_Han_Korean Then always_disp_Han = True; Fi } local void toggle_Vietnamese () { disp_Han_Vietnamese = ! disp_Han_Vietnamese; If disp_Han_Vietnamese Then always_disp_Han = True; Fi } local void toggle_HanyuPinlu () { disp_Han_HanyuPinlu = ! disp_Han_HanyuPinlu; If disp_Han_HanyuPinlu Then always_disp_Han = True; Fi } local void toggle_Tang () { disp_Han_Tang = ! disp_Han_Tang; If disp_Han_Tang Then always_disp_Han = True; Fi } local void toggle_Han_short_description () { If disp_Han_description && disp_Han_full Then disp_Han_full = False; Else disp_Han_description = ! disp_Han_description; disp_Han_full = False; Fi If disp_Han_description Then always_disp_Han = True; Fi } local void toggle_Han_full_description () { If disp_Han_description && ! disp_Han_full Then disp_Han_full = True; Else disp_Han_description = ! disp_Han_description; disp_Han_full = True; Fi If disp_Han_description Then always_disp_Han = True; Fi } local int infoon_file (menu, i) menuitemtype * menu; int i; { return always_disp_fstat; } local int infoon_char (menu, i) menuitemtype * menu; int i; { return always_disp_code; } local int infoon_Han (menu, i) menuitemtype * menu; int i; { return always_disp_Han; } local int infoon_Mandarin (menu, i) menuitemtype * menu; int i; { return disp_Han_Mandarin; } local int infoon_Cantonese (menu, i) menuitemtype * menu; int i; { return disp_Han_Cantonese; } local int infoon_Japanese (menu, i) menuitemtype * menu; int i; { return disp_Han_Japanese; } local int infoon_Sino_Japanese (menu, i) menuitemtype * menu; int i; { return disp_Han_Sino_Japanese; } local int infoon_Hangul (menu, i) menuitemtype * menu; int i; { return disp_Han_Hangul; } local int infoon_Korean (menu, i) menuitemtype * menu; int i; { return disp_Han_Korean; } local int infoon_Vietnamese (menu, i) menuitemtype * menu; int i; { return disp_Han_Vietnamese; } local int infoon_HanyuPinlu (menu, i) menuitemtype * menu; int i; { return disp_Han_HanyuPinlu; } local int infoon_Tang (menu, i) menuitemtype * menu; int i; { return disp_Han_Tang; } local int infoon_descr_short (menu, i) menuitemtype * menu; int i; { return disp_Han_description && ! disp_Han_full; } local int infoon_descr_full (menu, i) menuitemtype * menu; int i; { return disp_Han_description && disp_Han_full; } /***********************************************************************\ Pulldown menu tables \***********************************************************************/ global void separator () { } local menuitemtype Filemenu [] = { {"Open", EDIT, ""}, {"View", VIEW, ""}, {"Save", WT, ""}, {"Set Name...", NN, ""}, {"Save As...", SAVEAS, ""}, {"Save & Exit", EXED, ""}, {"", separator, ""}, {"Insert file", INSFILE, ""}, {"Copy to file", WB, "Append to file"}, {"Print", PRINT, ""}, {"", separator, ""}, {"Check Out", checkout, ""}, {"Check In", checkin, ""}, {"", separator, ""}, {"Next file", NXTFILE, "First file"}, {"Prev file", PRVFILE, "Last file"}, {"N-th file", NTHFILE, ""}, {"Save Position", SAVPOS, ""}, {"Quit", QUED, ""}, }; local menuitemtype Editmenu [] = { {"Mark", MARK, "Go to Mark"}, {"Cut", CUT, "Cut & Append"}, {"Copy", COPY, "Append"}, {"Paste", PASTE, "Paste Other"}, {"Paste Previous", YANKRING, ""}, {"Paste Other", PASTEEXT, ""}, {"set/go markers", separator, ""}, {"Go to Mark", GOMA, ""}, {"Set marker N", MARKER, ""}, {"Go marker N", GOMARKER, ""}, {"insert", separator, ""}, {"HTML/XML tag", HTML, "Embed in HTML/XML"}, {"Control/Composed", CTRLINS, ""}, {"conversion", separator, ""}, {"Combine mnemonic", (voidfunc) UML, ""}, {"Case toggle", LOWCAP, "Case toggle word"}, {"Word case switch", LOWCAPWORD, ""}, {"char -> code", separator, "code -> char"}, {"Hex bytes", changehex, ""}, {"Unicode value", changeuni, ""}, {"Decimal value", changedec, ""}, {"Octal value", changeoct, ""}, }; local menuitemtype Searchmenu [] = { {"Find", SFW, "Find identifier"}, {"Find backw.", SRV, "Find idf. backw."}, {"Find again", RS, "Previous Search"}, {"", separator, ""}, {"Find Identifier", SIDFW, ""}, {"Find Idf. backw.", SIDRV, ""}, {"Find Character", SCURCHARFW, ""}, {"Find ", (voidfunc) SCORR, "Find wrong enc."}, {"Go to Idf. def.", Stag, "Go to def. ..."}, {"", separator, ""}, {"Substitute", GR, ""}, {"Replace (?)", REPL, ""}, {"Replace on line", LR, ""}, {"", separator, ""}, {"Go to Mark", GOMA, ""}, {"Go to...", GOTO, ""}, }; local menuitemtype Paragraphmenu [] = { {"Justify Clever", JUSclever, "Clever justify other"}, {"Justify Simple", JUS, "Justify other mode"}, {"set parameters", separator, ""}, {"Set Left margin", ADJLM, ""}, {"Set First line left m.", ADJFLM, ""}, {"Set Other lines l. m.", ADJNLM, ""}, {"Set Right margin", ADJRM, ""}, {"Toggle Auto-justif.", toggle_JUSlevel, ""}, {"Toggle Line-end mode", toggle_JUSmode, ""}, }; local menuitemtype Optionsmenu [] = { {"editing features", separator, ""}, {"Toggle auto indent", toggle_autoindent, ""}, {"Word wrap mode...", handleJustifymenu, ""}, {"Paragraph end...", handleParagraphmodemenu, ""}, {"Edit/View only", toggle_VIEWmode, ""}, {"Paste buffer mode...", handleBuffermenu, ""}, {"display settings", separator, ""}, {"Toggle HTML disp", toggle_HTML, ""}, {"Toggle TAB width", toggle_tabsize, ""}, {"Toggle TAB expansion", toggle_tab_expansion, ""}, {"Screen size...", handleScreensizemenu, ""}, {"File info", FS, "Toggle File info"}, {"Char info", display_code, "Toggle Char info"}, {"CJK/Info display...", handleInfomenu, ""}, {"character handling", separator, ""}, {"Text Encoding...", handleEncodingmenu, ""}, {"Combined display", toggle_combining, ""}, {"Input Method...", handleKeymapmenu, ""}, {"Smart Quotes style...", handleQuotemenu, ""}, {"help", separator, ""}, {"Topics", HELP_topics, ""}, {"About mined", ABOUT, ""}, {"Fn bar", display_FHELP, ""}, {"select Fn bar", select_FHELP, ""}, {"toggle Fn bar", toggle_FHELP, ""}, }; local menuitemtype Screensizemenu [] = { #ifdef msdos {"bigger", screenbigger, "video mode"}, {"smaller", screensmaller, "graphic mode"}, {"more lines", screenmorelines, "font bank"}, {"fewer lines", screenlesslines, "char height"}, {"switch line #", LNSW, "cycle line #"}, #else {"bigger", screenbigger, ""}, {"smaller", screensmaller, ""}, {"more lines", screenmorelines, ""}, {"fewer lines", screenlesslines, ""}, {"maximize/restore", maximize_restore_screen, ""}, #endif }; local menutype Pulldownmenu [] = { {"File", arrlen (Filemenu), Filemenu}, {"Edit", arrlen (Editmenu), Editmenu}, {"Search/go", arrlen (Searchmenu), Searchmenu}, {"Paragraph", arrlen (Paragraphmenu), Paragraphmenu}, {"Options", arrlen (Optionsmenu), Optionsmenu}, }; /***********************************************************************\ Flag menu tables \***********************************************************************/ /* Unicode quotation marks and their usage in some languages The UTF-8 codes of all quotation marks are either C2AB or C2BB or start with either E280 or E380. This may help for efficient detection during file loading (e.g. by checking if current_byte & 0xDE == 0xC2). “ 201C; LEFT DOUBLE QUOTATION MARK; DOUBLE TURNED COMMA QUOTATION MARK left English, Spanish, Turkish right German, Danish, Polish, Russian, Romanian, Slovak, Slovenian, Czech, Hungarian ” 201D; RIGHT DOUBLE QUOTATION MARK; DOUBLE COMMA QUOTATION MARK right English, Spanish, Turkish right Dutch, Hungarian left/right Swedish, Finnish right nested traditional Greek „ 201E; DOUBLE LOW-9 QUOTATION MARK; LOW DOUBLE COMMA QUOTATION MARK left German, Danish, Polish, Russian, Romanian, Slovak, Sloven, Czech, Hungarian left Dutch, Hungarian ‟ 201F; DOUBLE HIGH-REVERSED-9 QUOTATION MARK; DOUBLE REVERSED COMMA QUOTATION MARK left nested traditional Greek ‘ 2018; LEFT SINGLE QUOTATION MARK; SINGLE TURNED COMMA QUOTATION MARK ’ 2019; RIGHT SINGLE QUOTATION MARK; SINGLE COMMA QUOTATION MARK ‚ 201A; SINGLE LOW-9 QUOTATION MARK; LOW SINGLE COMMA QUOTATION MARK ? ‛ 201B; SINGLE HIGH-REVERSED-9 QUOTATION MARK; SINGLE REVERSED COMMA QUOTATION MARK « 00AB; LEFT-POINTING DOUBLE ANGLE QUOTATION MARK; LEFT POINTING GUILLEMET left French, Italian, Norwegian, Portuguese, Russian, Slovenian, Turkish right German, Polish, Slovak, Czech, Serbian, Croatian » 00BB; RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK; RIGHT POINTING GUILLEMET right French, Italian, Norwegian, Portuguese, Russian, Slovenian, Turkish left German, Polish, Slovak, Czech, Serbian, Croatian left/right Swedish, Finnish ‹ 2039; SINGLE LEFT-POINTING ANGLE QUOTATION MARK; LEFT POINTING SINGLE GUILLEMET › 203A; SINGLE RIGHT-POINTING ANGLE QUOTATION MARK; RIGHT POINTING SINGLE GUILLEMET C? 〈3008; LEFT ANGLE BRACKET; OPENING ANGLE BRACKET C? 〉3009; RIGHT ANGLE BRACKET; CLOSING ANGLE BRACKET C? 《300A; LEFT DOUBLE ANGLE BRACKET; OPENING DOUBLE ANGLE BRACKET left Chinese C? 》300B; RIGHT DOUBLE ANGLE BRACKET; CLOSING DOUBLE ANGLE BRACKET right Chinese J 「300C; LEFT CORNER BRACKET; OPENING CORNER BRACKET left Japanese J 」300D; RIGHT CORNER BRACKET; CLOSING CORNER BRACKET right Japanese J? 『300E; LEFT WHITE CORNER BRACKET; OPENING WHITE CORNER BRACKET J? 』300F; RIGHT WHITE CORNER BRACKET; CLOSING WHITE CORNER BRACKET */ local menuitemtype Quotemenu [] = { {"\"plain\"", select_quote_type, " \"\" ''", quoteon}, {"typographic", separator, ""}, /* English, Spanish, Turkish, Irish, Portuguese */ {"“English”", select_quote_type, " “” ‘’", quoteon}, #ifdef single_double /* British English */ {"‘British’", select_quote_type, " ‘’ “”", quoteon}, #endif /* German, Danish, Polish, Russian, Romanian, Slovak, Slovenian, Czech, Hungarian, Bulgarian, Serbian, Icelandic, Lithuanian */ {"„German“", select_quote_type, " „“ ‚‘", quoteon}, /* French, Italian, Portuguese, Russian, Slovenian, Turkish, Spanish, Albanian, Greek */ /*w Armenian */ {"French «“.”»", select_quote_type, " «» “”", quoteon}, /* Swiss, Italian, Norwegian, Portuguese, Russian, Slovenian, Turkish, Spanish, Albanian, Greek */ {"«Swiss»", select_quote_type, " «» ‹›", quoteon}, /*w Greek */ {"“Greek„", select_quote_type, " “„ ‘‚", quoteon}, /* Danish, Croatian, German, Polish, Slovak, Czech, Serbian */ {"»Danish«", select_quote_type, " »« ›‹", quoteon}, /* Norwegian */ {"Norweg. «‘’»", select_quote_type, " «» ‘’", quoteon}, /* Swedish, Finnish */ /*w Dutch */ {"”Swedish”", select_quote_type, " ”” ’’", quoteon}, /* Swedish, Finnish */ {"»Finnish»", select_quote_type, " »» ››", quoteon}, /* Hebrew */ {"Hebrew ״.״", select_quote_type, " ״״ ׳׳", quoteon}, #ifdef single_double /* CJK */ {"「亞 CJK」", select_quote_type, "「」 『』", quoteon}, #else /* CJK */ {"「亞 CJK」", select_quote_type, "『』 「」", quoteon}, #endif {"traditional", separator, ""}, /* traditional Dutch, Afrikaans, Hungarian, Polish */ {"„Dutch”", select_quote_type, " „” ‚’", quoteon}, /* traditional Greek */ {"Greek «‟.”»", select_quote_type, " «» ‟”", quoteon}, /* Chinese book marks */ {"《Chinese》", select_quote_type, "《》 〈〉", quoteon}, }; local menuitemtype Keymapmenu [] = { {"none", select_keymap_entry, "--", keymapon}, #ifdef use_keymap_tables #include "keymapsm.t" #endif }; #include "charesub.t" local menuitemtype encodingmenu [] = { {"Unicode", select_encoding, "UTF-8", encodingon}, {"8 Bit", separator, ""}, {"Latin-1", select_encoding, "ISO 8859-1", encodingon}, #include "charemen.t" }; local menuitemtype combiningmenu [] = { {"combined", select_combining, "", comborsepon}, {"separated", select_combining, "", comborsepon}, }; local menuitemtype infomenu [] = { {"File info", select_file_info, "", infoon_file}, {"Char info", select_char_info, "", infoon_char}, {"Han info", select_Han_info, "", infoon_Han}, {"display Han", separator, ""}, {"Bottom line", toggle_Han_short_description, "", infoon_descr_short}, {"Popup display", toggle_Han_full_description, "", infoon_descr_full}, {"pronunciations", separator, ""}, {"Mandarin", toggle_Mandarin, "", infoon_Mandarin}, {"Cantonese", toggle_Cantonese, "", infoon_Cantonese}, {"Japanese", toggle_Japanese, "", infoon_Japanese}, {"Sino-Japanese", toggle_Sino_Japanese, "", infoon_Sino_Japanese}, {"Hangul", toggle_Hangul, "", infoon_Hangul}, {"Korean", toggle_Korean, "", infoon_Korean}, {"Vietnamese", toggle_Vietnamese, "", infoon_Vietnamese}, {"Hanyu Pinlu", toggle_HanyuPinlu, "", infoon_HanyuPinlu}, {"Tang", toggle_Tang, "", infoon_Tang}, }; local menuitemtype textmenu [] = { {"edit", select_editmode, "modify", editorviewon}, {"view", select_editmode, "readonly", editorviewon}, }; local menuitemtype buffermenu [] = { {"overwrite", select_buffermode, "", overwriteorappendon}, {"append", select_buffermode, "", overwriteorappendon}, {"encoding", separator, ""}, {"Unicode", toggle_pastebuf_mode, "", pastebuf_utf8on}, }; local menuitemtype autoindentmenu [] = { {"auto indent", select_autoindent, "", autoindenton}, {"off", select_autoindent, "", autoindenton}, {"", separator, ""}, {"TAB expand", toggle_tab_expansion, "", tabexpansionon}, }; local menuitemtype justifymenu [] = { {"on command", select_justify, "", justifymodeon}, {"at line end", select_justify, "", justifymodeon}, {"always", select_justify, "", justifymodeon}, }; local menuitemtype paragraphmodemenu [] = { {"non-blank line-end", select_paragraph, "", paragraphmodeon}, {"empty line", select_paragraph, "", paragraphmodeon}, }; /***********************************************************************\ Popup menu table \***********************************************************************/ local menuitemtype Popupmenu [] = { {"Mark", MARK, "Go to Mark"}, {"Cut", CUT, "Cut-Append"}, {"Copy", COPY, "Append"}, {"Paste", PASTE, "Paste external"}, {"HTML tag", HTML, "Embed HTML"}, {"", separator, ""}, {"Find", SFW, "FindIdf"}, {"FindReverse", SRV, "FindIdfRev"}, {"FindNext", RS, "Previous Find"}, {"FindIdf", SIDFW, ""}, {"FindIdfRev", SIDRV, ""}, {"Go to Idf. def.", Stag, "Go to def. ..."}, {"Go to Mark", GOMA, ""}, {"Screen size...", handleScreensizemenu, ""}, {"Find matching ()", (voidfunc) SCORR, "Find wrong enc."}, }; /***********************************************************************\ menu structure auxiliary functions \***********************************************************************/ global int count_quote_types () { return arrlen (Quotemenu); } global char * quote_mark (i, n) int i; int n; { char * q = Quotemenu [i].hopitemname; while (* q == ' ') { q ++; } while (n > 0) { advance_utf8 (& q); while (* q == ' ') { q ++; } n --; } return q; } global int lookup_quotes (q) char * q; { int i; For i = 0 While i < arrlen (Quotemenu) Step i ++ Do If strisprefix (q, quote_mark (i, 0)) Then return i; Fi Done For i = 0 While i < arrlen (Quotemenu) Step i ++ Do If strisprefix (q, quote_mark (i, 2)) Then return i; Fi Done return -1; } local menuitemtype * lookup_menuitem (menu, len, hopitem) menuitemtype * menu; int len; char * hopitem; { int i; For i = 0 While i < len Step i ++ Do If streq (hopitem, menu [i].hopitemname) Then return & menu [i]; Fi Done return 0; } global menuitemtype * lookup_Keymap_menuitem (hopitem) char * hopitem; { return lookup_menuitem (Keymapmenu, arrlen (Keymapmenu), hopitem); } /***********************************************************************\ Flag table and next/previous function \***********************************************************************/ local char * dispKEYMAP0 (); local char * dispKEYMAP1 (); local flagitemtype Flagmenu [] = { {dispinfo, toggle_info, "Info display", infomenu, arrlen (infomenu)}, {dispnothing, toggle_nothing, NIL_PTR}, {dispKEYMAP0, toggleKEYMAP, "Input Method", Keymapmenu, arrlen (Keymapmenu)}, {dispKEYMAP1, toggleKEYMAP, "Input Method", Keymapmenu, arrlen (Keymapmenu)}, {dispnothing, toggle_nothing, NIL_PTR}, {disp_leftquote, toggle_quote_type /*quote_type_down*/, "Quotes", Quotemenu, arrlen (Quotemenu)}, {disp_rightquote, toggle_quote_type /*quote_type_up*/, "Quotes", Quotemenu, arrlen (Quotemenu)}, {dispnothing, toggle_nothing, NIL_PTR}, {disp_encoding_1, toggle_encoding, "Encoding", encodingmenu, arrlen (encodingmenu)}, {disp_encoding_2, toggle_encoding, "Encoding", encodingmenu, arrlen (encodingmenu)}, {disp_combining, toggle_combining, "Combining", combiningmenu, arrlen (combiningmenu)}, {dispnothing, toggle_nothing, NIL_PTR}, {dispHOP, toggle_HOP, NIL_PTR}, #ifdef debug_ring_buffer {disp_buffer_open, toggle_nothing, NIL_PTR}, #endif {dispnothing, toggle_nothing, NIL_PTR}, {dispVIEW, toggle_VIEWmode, "Text", textmenu, arrlen (textmenu)}, {disppastebuf, toggle_append, "Paste buf", buffermenu, arrlen (buffermenu)}, {dispnothing, toggle_nothing, NIL_PTR}, {disp_autoindent, toggle_autoindent, "Auto indent", autoindentmenu, arrlen (autoindentmenu)}, {dispJUSlevel, toggle_JUSlevel, "Word wrap", justifymenu, arrlen (justifymenu)}, {dispJUSmode, toggle_JUSmode, "Paragraph ends at", paragraphmodemenu, arrlen (paragraphmodemenu)}, }; local void flag_menu (i) int i; { action_menu (Flagmenu [i].menu, Flagmenu [i].menulen, - (flags_pos + i), 0, Flagmenu [i].menutitle, True); } local FLAG open_next_menu (current_menu) menuitemtype * current_menu; { int i; FLAG passed = False; If current_menu == (menuitemtype *) 0 Then passed = True; Fi If current_menu == Popupmenu && ! (keyshift & alt_mask) Then passed = True; Fi For i = 0 While i < arrlen (Pulldownmenu) Step i ++ Do If Pulldownmenu [i].menuitems == current_menu Then passed = True; If keyshift & alt_mask Then break; Fi Elsif passed Then openmenu (i); return True; Fi Done If current_menu == Popupmenu Then passed = True; Fi For i = 0 While i < arrlen (Flagmenu) Step i ++ Do If Flagmenu [i].menutitle != NIL_PTR && Flagmenu [i].menu == current_menu Then passed = True; If keyshift & alt_mask Then break; Fi Elsif passed && Flagmenu [i].menutitle != NIL_PTR && * ((* Flagmenu [i].dispflag) ()) != ' ' Then /* on a double-column flag menu, move right */ If i + 1 < arrlen (Flagmenu) && Flagmenu [i + 1].menutitle != NIL_PTR && streq (Flagmenu [i].menutitle, Flagmenu [i + 1].menutitle) Then i ++; Fi flag_menu (i); return True; Fi Done If passed Then openmenu (0); return True; Else return False; Fi } local FLAG open_prev_menu (current_menu) menuitemtype * current_menu; { int i; FLAG passed = False; If current_menu == (menuitemtype *) 0 Then passed = True; Fi If current_menu == Popupmenu && ! (keyshift & alt_mask) Then passed = True; Fi For i = arrlen (Pulldownmenu) - 1 While i >= 0 Step i -- Do If Pulldownmenu [i].menuitems == current_menu Then passed = True; If keyshift & alt_mask Then break; Fi Elsif passed Then openmenu (i); return True; Fi Done If current_menu == Popupmenu Then passed = True; Fi For i = arrlen (Flagmenu) - 1 While i >= 0 Step i -- Do If Flagmenu [i].menutitle != NIL_PTR && Flagmenu [i].menu == current_menu Then passed = True; If keyshift & alt_mask Then break; Fi Elsif passed && Flagmenu [i].menutitle != NIL_PTR && * ((* Flagmenu [i].dispflag) ()) != ' ' Then flag_menu (i); return True; Fi Done If passed Then openmenu (arrlen (Pulldownmenu) - 1); return True; Else return False; Fi } /***********************************************************************\ putblock () writes a block graphics character \***********************************************************************/ local void putblock (c) char c; { If horizontal_bar_width == 2 Then /* workaround for xterm remaining background glitch */ putstring (" "); Fi If in_menu_border Then putblockchar (c); Else menuborder_on (); putblockchar (c); menuborder_off (); Fi } /***********************************************************************\ putnstr () writes a string to screen at adjusted length putnstr_mark () does the same and marks given item (word) putnstr_tag () does the same and marks last column with tag \***********************************************************************/ #define dont_debug_item_marking #ifdef debug_item_marking #define trace_item_marking(params) printf params #else #define trace_item_marking(params) #endif local void tagdisp_on () { /*unidisp_on ();*/ menuitem_on (); } local void tagdisp_off () { /*unidisp_off ();*/ menuitem_off (); } local char * putnstr_tag_mark (s, extratag, l, mark_item, fill_line, selected) char * s; char * extratag; int l; int mark_item; FLAG fill_line; FLAG selected; { int i = 0; char * spoi = s; int utfcount; unsigned long unichar; int index = 0; char marked = ' '; FLAG title_active = True; FLAG show_info = True; char * show_char = NIL_PTR; trace_item_marking (("putnstr <%s>\n", s)); If extratag && * extratag Then l -= extratag_length; Fi If mark_item == 0 Then trace_item_marking (("border on @ %d\n", i)); dim_on (); marked = 'b'; Elsif mark_item > 0 Then trace_item_marking (("header on @ %d\n", i)); menuheader_on (); marked = 'h'; Fi Dowhile i < l Do If * spoi == '\0' Then If index == mark_item Then /* end marked item */ trace_item_marking (("end string @ %d\n", i)); menuitem_off (); menuheader_on (); marked = 'h'; Fi index ++; If fill_line Then If title_active Then menuheader_off (); title_active = False; If use_graphic_borders && horizontal_bar_width == 2 && (i & 1) Then putchar (' '); Fi Fi If use_graphic_borders Then If horizontal_bar_width == 1 || ! (i & 1) Then putblock ('q'); Fi Else menudisp_on (); putchar (' '); Fi Else putchar (' '); Fi i ++; Elsif (* spoi & 0x80) != 0 /* UTF-8 character */ Then utf8_info (spoi, & utfcount, & unichar); If index == mark_item && show_info && unichar >= 0x2E80 Then show_char = spoi; show_info = False; Fi put_unichar (unichar); advance_utf8_scr (& spoi, & i, s); If selected && (cjk_term || mapped_term) && no_char (mappedtermchar (unichar)) Then /* restore screen attribute of selected item after highlighted replacement display */ menuheader_on (); Fi Else /* ASCII character */ If * spoi == ' ' Then If index == mark_item Then /* end marked item */ trace_item_marking (("end marked item @ %d\n", i)); menuitem_off (); menuheader_on (); marked = 'h'; Fi index ++; putchar (* spoi ++); If index == mark_item Then /* begin marked item */ trace_item_marking (("begin marked item @ %d\n", i)); menuheader_off (); dim_on (); marked = 'b'; Fi Elsif marked == 'b' && * spoi == ':' Then putchar (* spoi ++); dim_off (); menuitem_on (); marked = 'i'; Else putchar (* spoi ++); Fi i ++; Fi Done If marked == 'h' Then trace_item_marking (("header off @ %d\n", i)); menuheader_off (); Elsif marked == 'b' || marked == 'i' Then trace_item_marking (("border off @ %d\n", i)); menuitem_off (); menuheader_off (); Fi If extratag && * extratag Then tagdisp_on (); put_unichar (utf8value (extratag)); tagdisp_off (); Fi return show_char; } local char * putnstr_mark (s, l, mark_item, fill_line, selected) char * s; int l; int mark_item; FLAG fill_line; FLAG selected; { return putnstr_tag_mark (s, NIL_PTR, l, mark_item, fill_line, selected); } local void putnstr (s, l) char * s; int l; { (void) putnstr_mark (s, l, -2, False, False); } local void putnstr_tag (s, extratag, l, selected) char * s; char * extratag; int l; { (void) putnstr_tag_mark (s, extratag, l, -2, False, selected); } local void putnstr_fill (s, l) char * s; int l; { (void) putnstr_mark (s, l, -2, True, False); } /***********************************************************************\ putborder_top/middle/bottom () writes menu borders \***********************************************************************/ local void putborder_top (x, y, width, title, hook, scrolled) int x, y, width; char * title; FLAG hook; int scrolled; { int i; set_cursor (x, y - 1); If title != NIL_PTR Then If use_graphic_borders Then menuborder_on (); If scrolled Then putblock ('f'); Else putblock ('l'); Fi menuheader_on (); putnstr ("", menumargin); Else menudisp_on (); putnstr ("", 1 + menumargin); Fi If standout_glitch && y == 0 Then For i = 0 While i < width - 2 - 2 * menumargin Step i ++ Do menuheader_on (); putchar (' '); Done set_cursor (x + 1 + menumargin, y - 1); Fi putnstr (title, width - 2 - 2 * menumargin); If use_graphic_borders Then putnstr ("", menumargin); menuheader_off (); menuborder_on (); If scrolled Then putblock ('f'); Elsif hook Then putblock ('k'); /* 'u' ? */ Else putblock ('k'); Fi Else putnstr ("", 1 + menumargin); Fi Else If use_graphic_borders Then menuborder_on (); If horizontal_bar_width == 2 Then /* workaround for xterm bold glitch */ menuheader_off (); Fi If scrolled Then putblock ('f'); Else putblock ('l'); Fi For i = 2 While i < width Step i += horizontal_bar_width Do putblock ('q'); Done If scrolled Then putblock ('f'); Else putblock ('k'); Fi Else menudisp_on (); putnstr ("", width); Fi Fi } local void putborder_middle (x, y, width, subtitle) int x, y, width; char * subtitle; { int i; set_cursor (x, y - 1); If subtitle != NIL_PTR && * subtitle != '\0' Then If use_graphic_borders Then putblock ('t'); menuheader_on (); Else putnstr ("", 1 + menumargin); Fi putnstr_fill (subtitle, width - 2); If use_graphic_borders Then menuheader_off (); menuborder_on (); putblock ('u'); menuborder_off (); Else putnstr ("", 1 + menumargin); Fi Else If use_graphic_borders Then If horizontal_bar_width == 2 Then /* workaround for xterm bold glitch */ menuheader_off (); Fi putblock ('t'); For i = 2 While i < width Step i += horizontal_bar_width Do putblock ('q'); If horizontal_bar_width == 2 Then /* work-around for xterm font handling bug */ menuborder_on (); Fi Done putblock ('u'); menuborder_off (); Else putnstr ("", width); Fi Fi } local void putborder_bottom (x, y, width, scrolled) int x, y, width; int scrolled; { int i; set_cursor (x, y - 1); If use_graphic_borders Then If horizontal_bar_width == 2 Then /* workaround for xterm bold glitch */ menuheader_off (); Fi If scrolled Then putblock ('g'); Else putblock ('m'); Fi For i = 2 While i < width Step i += horizontal_bar_width Do putblock ('q'); If horizontal_bar_width == 2 Then /* work-around for xterm font handling bug */ menuborder_on (); Fi Done If scrolled Then putblock ('g'); Else putblock ('j'); Fi menuborder_off (); Else putnstr ("", width); menudisp_off (); Fi } /***********************************************************************\ number_menus () determines the number of pull-down menus \***********************************************************************/ local int number_menus () { return arrlen (Pulldownmenu); } /***********************************************************************\ calcmenuvalues () determines menu screen positions width_of_menu () determines the display width of the menu \***********************************************************************/ local int width_of_menu (menu, menulen, startcol, isflagmenu, minwidth) menuitemtype * menu; int menulen; int startcol; int isflagmenu; int minwidth; { int i; menuitemtype * item; int width = minwidth; For i = 0 While i < menulen Step i ++ Do char * iname; int itemlen; item = & (menu [i]); itemlen = 2 + 2 * menumargin; If item->itemfu == separator Then itemlen -= isflagmenu; Fi iname = hop_flag > 0 && item->hopitemname && * item->hopitemname ? item->hopitemname : item->itemname; If iname && * iname Then itemlen += utf8_col_count (iname); Fi /* add display length of extra tag if present */ If item->extratag Then itemlen += extratag_length; Fi /* increase maximum if this width is greater */ If itemlen > width Then width = itemlen; Fi Done width += isflagmenu; If width > XMAX Then width = XMAX; Fi If startcol > 0 && startcol + width > XMAX - 1 Then width = XMAX + 1 - startcol; Fi If cjk_width_data_version && (width & 1) Then width ++; Fi return width; } local void calcmenuvalues () { int flags_gap; If cjk_width_data_version Then horizontal_bar_width = 2; Fi /* determine positions for menus and flags display */ pulldownmenu_width = XMAX - arrlen (Flagmenu) - 4; If pulldownmenu_width <= 0 Then pulldownmenu_width = 0; Else pulldownmenu_width /= number_menus (); Fi popupmenumargin = menumargin; If pulldownmenu_width < 10 Then menumargin = 0; Fi /* determine popup menu width: */ If (width_of_menu (Popupmenu, arrlen (Popupmenu), 0, 0, 0) < 15) Then popupmenumargin = 0; Fi /* determine position and length of displayed flags */ flags_pos = XMAX - 2 - arrlen (Flagmenu); flags_gap = flags_pos - number_menus () * pulldownmenu_width; flags_displayed = arrlen (Flagmenu); If flags_gap < 2 Then flags_pos += 2 - flags_gap; flags_displayed -= 2 - flags_gap; Fi } /***********************************************************************\ displaymenuheaders () displays the menu headers displaymenuheader () displays one menu header cleargap () clears the gap between menu headers and flags displayflags () displays the menu flags displaymenuline () displays the menu line \***********************************************************************/ local void displaymenuheader (meni) int meni; { set_cursor (meni * pulldownmenu_width, -1); putchar (' '); menudisp_on (); putnstr ("", menumargin); putnstr (Pulldownmenu [meni].menuname, pulldownmenu_width - 2 - 2 * menumargin); putnstr ("", menumargin); menudisp_off (); putchar (' '); } local void displaymenuheaders_from (firsti) int firsti; { int i; int starti; If menuline_dirty Then starti = 0; menuline_dirty = False; Else starti = firsti; Fi calcmenuvalues (); If pulldownmenu_width < 3 Then return; Fi If standout_glitch Then set_cursor (starti * pulldownmenu_width, -1); clear_eol (); disp_normal (); Fi For i = starti While i < number_menus () Step i ++ Do displaymenuheader (i); Done } local void displaymenuheaders () { displaymenuheaders_from (0); } local void cleargap () { int i; int gappos = number_menus () * pulldownmenu_width; set_cursor (gappos, -1); For i = gappos While i < flags_pos Step i ++ Do putchar (' '); Done } global void displayflags () { int i; char * flags; FLAG is_reverse; If ! MENU Then return; Fi calcmenuvalues (); If pulldownmenu_width < 3 Then return; Fi set_cursor (flags_pos, -1); For i = 0 While i < flags_displayed Step i ++ Do flags = (* Flagmenu [i].dispflag) (); If * flags == '#' Then is_reverse = True; flags ++; If * flags == '#' Then flags ++; combiningdisp_on (); Else menudisp_on (); Fi Else is_reverse = False; Fi If (* flags & 0x80) != 0 Then unsigned long unichar; int utflen; utf8_info (flags, & utflen, & unichar); If (cjk_term || mapped_term) && (is_reverse || unichar == 0xE7) && no_char (mappedtermchar (unichar) ) Then If unichar == 0xAB /* « */ Then putchar ('<'); Elsif unichar == 0xBB /* » */ Then putchar ('>'); Elsif unichar == 0xA6 /* ¦ */ Then putchar ('|'); Elsif unichar == 0xE7 /* ç */ Then putchar (';'); Else put_unichar (unichar); Fi Else put_unichar (unichar); Fi Elsif * flags != 0 Then putchar (* flags); Fi If is_reverse Then disp_normal (); Fi Done flags_changed = False; } global void displaymenuline () { If ! MENU Then return; Fi displaymenuheaders (); cleargap (); displayflags (); clear_eol (); top_line_scrolled = False; } /***********************************************************************\ prepare_menuline prepares menu line to prevent right-to-left menu obstruction \***********************************************************************/ local void prepare_menuline (column, line, menu_line_poi) int column; int line; LINE * * menu_line_poi; { char * cp; LINE * menu_line = * menu_line_poi; If menu_line == NIL_LINE || menu_line == bot_line Then * menu_line_poi = NIL_LINE; Else * menu_line_poi = menu_line->next; Fi If standout_glitch Then set_cursor (column, line - 1); clear_eol (); disp_normal (); Fi If menu_line == tail || menu_line == NIL_LINE Then return; Elsif bidi_screen Then For cp = menu_line->text While * cp != '\0' Step advance_char (& cp) Do If is_right_to_left (unicodevalue (cp)) Then break; Fi Done If * cp != '\0' Then set_cursor (0, line - 1); clear_eol (); Fi Fi } /***********************************************************************\ display_menu () displays the given menu, returns menu width \***********************************************************************/ local void display_menu (fullmenu, menulen, menuwidth, column, line, title, isflagmenu, disp_only, minwidth, scroll, maxscroll) menuitemtype * fullmenu; int menulen; int menuwidth; int column; int line; char * title; int isflagmenu; FLAG disp_only; int minwidth; int scroll, maxscroll; { int i; menuitemtype * item; LINE * menu_line; menuitemtype * menu = fullmenu + scroll; menu_mouse_mode (True); /* save redraw values: */ last_popup_column = column; last_popup_line = line; last_popup_item = -1; last_is_flag_menu = isflagmenu; last_minwidth = minwidth; last_scroll = scroll; last_maxscroll = maxscroll; /* save sub-menu reference */ last_menucolumn = column; /* check if menu headers overwritten */ If line == 0 Then menuline_dirty = True; Fi /* text lines may have to be cleared: */ menu_line = proceed (top_line, line - 1); /* top menu border: */ prepare_menuline (column, line, & menu_line); putborder_top (column, line, menuwidth, title, True, scroll > 0); /* menu items: */ For i = 0 While i < menulen Step i ++ Do prepare_menuline (column, line + 1 + i, & menu_line); item = & (menu [i]); If item->itemfu == separator Then If hop_flag > 0 && item->hopitemname != NIL_PTR && item->hopitemname [0] != '\0' Then putborder_middle (column, line + 1 + i, menuwidth, item->hopitemname); Else putborder_middle (column, line + 1 + i, menuwidth, item->itemname); Fi Else set_cursor (column, line + i); If use_graphic_borders Then putblock ('x'); menuborder_off (); Else putchar (' '); menudisp_off (); Fi putnstr ("", popupmenumargin); If isflagmenu Then If (* item->itemon) (item, i) Then put_menu_marker (); Else putchar (' '); Fi Fi If hop_flag > 0 && item->hopitemname != NIL_PTR && item->hopitemname [0] != '\0' Then putnstr_tag (item->hopitemname, item->extratag, menuwidth - isflagmenu - 2 - 2 * popupmenumargin, False); Else putnstr_tag (item->itemname, item->extratag, menuwidth - isflagmenu - 2 - 2 * popupmenumargin, False); Fi putnstr ("", popupmenumargin); If use_graphic_borders Then menuborder_on (); putblock ('x'); Else menudisp_on (); putchar (' '); Fi Fi Done /* bottom menu border: */ prepare_menuline (column, line + 1 + menulen, & menu_line); putborder_bottom (column, line + 1 + menulen, menuwidth, scroll < maxscroll); If line > 0 && title != NIL_PTR Then /* flag menu */ set_cursor (column + menuwidth - 2 + horizontal_bar_width, line - 1); Else set_cursor (column, line - 1); Fi If first_dirty_line < 0 || line - 1 < first_dirty_line Then first_dirty_line = line - 1; If first_dirty_line < 0 Then first_dirty_line = 0; Fi Fi If line - 1 + menulen + 2 > last_dirty_line Then last_dirty_line = line - 1 + menulen + 2; Fi last_menulen = menulen; last_menuwidth = menuwidth; last_disp_only = disp_only; last_menutitle = title; popupmenu_active = True; last_fullmenu = fullmenu; } /***********************************************************************\ popupmenselected () highlights a selected popup menu item \***********************************************************************/ local void popupmenselected (menu, menu_width, selected, column, line, i, index, isflagmenu) menuitemtype * menu; int menu_width; FLAG selected; int column; int line; int i; int index; int isflagmenu; { menuitemtype * item; FLAG show_info = False; char * show_char; FLAG coloured = index < 0; int unicode_menubar_mode = use_unicode_menubar (); /* save sub-menu reference */ last_menuline = line + i; If i < 0 Then return; Fi /* save redraw values: */ If selected Then last_popup_item = i; last_popup_index = index; Else last_popup_item = -1; Fi set_cursor (column, line + i); /* draw left border element */ If selected && unicode_menubar_mode > 0 Then If coloured Then disp_selected (True, True); Else reverse_on (); Fi If unicode_menubar_mode > 1 Then put_unichar (0x258E); /* ▎ LEFT ONE QUARTER BLOCK */ Else put_unichar (0x258D); /* ▍ LEFT THREE EIGHTHS BLOCK */ Fi Elsif use_graphic_borders Then putblock ('x'); Else menudisp_on (); putchar (' '); menudisp_off (); Fi /* switch to menu item content */ If selected && coloured Then disp_selected (True, False); Else If standout_glitch Then menuheader_off (); /* disp_normal (); ? */ Fi Fi putnstr ("", popupmenumargin); item = & (menu [i]); If isflagmenu Then If (* item->itemon) (item, i) Then put_menu_marker (); If selected && coloured Then disp_selected (True, False); Fi Else putchar (' '); Fi Fi If selected && index >= 0 Then show_char = putnstr_mark (item->itemname, menu_width - isflagmenu - 2 - 2 * popupmenumargin, index, False, selected); show_info = True; Elsif hop_flag > 0 && item->hopitemname != NIL_PTR && item->hopitemname [0] != '\0' Then putnstr_tag (item->hopitemname, item->extratag, menu_width - isflagmenu - 2 - 2 * popupmenumargin, selected); Else putnstr_tag (item->itemname, item->extratag, menu_width - isflagmenu - 2 - 2 * popupmenumargin, selected); Fi putnstr ("", popupmenumargin); /* switch to border */ If selected && coloured Then disp_normal (); Fi /* draw right border element */ If selected && unicode_menubar_mode > 0 Then If coloured Then disp_selected (False, True); Fi If unicode_menubar_mode > 1 Then put_unichar (0x258A); /* ▊ LEFT THREE QUARTERS BLOCK */ Else put_unichar (0x258B); /* ▋ LEFT FIVE EIGHTHS BLOCK */ Fi Elsif use_graphic_borders Then putblock ('x'); Else menudisp_on (); putchar (' '); menudisp_off (); Fi If show_info Then clear_status (); If show_char != NIL_PTR Then display_Han (show_char, True); Fi Elsif selected Then disp_normal (); If ! can_reverse_mode || ! can_hide_cursor Then /* only needed if terminal cannot standout / reverse: */ set_cursor (column, line + i); Fi Fi } /***********************************************************************\ clean_menus () wipes menus which are still displayed clear_menus () clears menus which are still displayed \***********************************************************************/ global void clean_menus () { menu_mouse_mode (False); If popupmenu_active Then LINE * start_line = proceed (top_line, first_dirty_line); int ypos = y; If ypos < first_dirty_line Then /* Han info menu */ ypos = first_dirty_line; Elsif ypos > first_dirty_line + 1 + last_menulen Then /* limit ypos to lower menu border as until 2000.11 */ ypos = first_dirty_line + 1 + last_menulen; Fi display (first_dirty_line, start_line, last_dirty_line - 1 - first_dirty_line, ypos); first_dirty_line = -1; last_dirty_line = 0; set_cursor_xy (); Fi If menuline_dirty Then displaymenuline (); Fi popupmenu_active = False; } local void clear_menus () { clean_menus (); } /***********************************************************************\ redrawmenu () redraws an open menu after screen refresh \***********************************************************************/ global void redrawmenu () { If popupmenu_active Then int item = last_popup_item; display_menu (last_fullmenu, last_menulen, last_menuwidth, last_popup_column, last_popup_line, last_menutitle, last_is_flag_menu, last_disp_only, last_minwidth, last_scroll, last_maxscroll); If item >= 0 Then popupmenselected (last_fullmenu + last_scroll, last_menuwidth, True, last_popup_column, last_popup_line, item, last_popup_index, last_is_flag_menu); Fi If last_disp_only Then menu_mouse_mode (False); set_cursor_xy (); Fi Fi } /***********************************************************************\ is_menu_open () checks if a menu is open used with mouse hilite tracking mode (xterm) \***********************************************************************/ global int is_menu_open () { return popupmenu_active; } /***********************************************************************\ select_item () selects a menu item based on key letter \***********************************************************************/ local int select_item (menu, menulen, curitemno, key) menuitemtype * menu; int menulen; int curitemno; unsigned long key; { int i = curitemno + 1; key |= 0x20; /* normalise to small letter */ Dowhile True Do If i > menulen Then i = 1; If curitemno == 0 Then return 1; Fi Fi If i == curitemno Then return curitemno; Fi If menu [i - 1].itemfu != separator Then char * label; unsigned long letter; If hop_flag > 0 Then label = menu [i - 1].hopitemname; If * label == '\0' Then label = menu [i - 1].itemname; Fi Else label = menu [i - 1].itemname; Fi letter = utf8value (label); Dowhile letter != 0 && ! isLetter (letter) Do advance_utf8 (& label); letter = utf8value (label); Done If case_convert (letter, 1) == case_convert (key, 1) Then return i; Fi Fi i ++; Done /*return curitemno;*/ } /***********************************************************************\ item_count () counts menu items in a menu line string \***********************************************************************/ local int item_count (line) character * line; { character prev = (character) ' '; int count = 0; Dowhile * line != '\0' Do If (character) * line > (character) ' ' && prev == ' ' Then count ++; Fi prev = * line; If prev == (character) '\t' Then prev = (character) ' '; Fi line ++; Done return count; } /***********************************************************************\ action_menu () handles given action menu popup_menu () handles given action or selection menu menu_scroll () moves menu item and, if necessary, scrolls a partially displayed menu \***********************************************************************/ #define dont_debug_menu_scroll #ifdef debug_menu_scroll #define trace_menu_scroll(params) printf params #else #define trace_menu_scroll(params) #endif /** Calculate new menu position and set values. Return True if menu has to be scrolled. */ local FLAG menu_scroll (menu, menulen, delta, fullmenu, scrolloffset, maxscrolloffset, itemno) menuitemtype * * menu; int menulen; int delta; menuitemtype * fullmenu; int * scrolloffset; int maxscrolloffset; int * itemno; { int prev_scrolloffset = * scrolloffset; If delta == 1 Then * itemno += delta; If * itemno > menulen Then If * scrolloffset == maxscrolloffset Then /* cycle at end */ * scrolloffset = 0; * itemno = 1; Else /* scroll 1 item */ * scrolloffset += delta; * itemno -= delta; Fi Fi Dowhile fullmenu [* scrolloffset + * itemno - 1].itemfu == separator Do * itemno += delta; trace_menu_scroll ((" itemno sep ++ %d + %d\n", * itemno, * scrolloffset)); If * itemno > menulen Then If * scrolloffset == maxscrolloffset Then /* cycle at end */ * scrolloffset = 0; * itemno = 1; trace_menu_scroll ((" itemno sep ++ --> %d + %d\n", * itemno, * scrolloffset)); Else /* scroll 1 item */ * scrolloffset += delta; * itemno -= delta; trace_menu_scroll ((" itemno sep ++ -> %d + %d\n", * itemno, * scrolloffset)); Fi Fi Done Elsif delta == -1 Then * itemno += delta; If * itemno < 1 Then If * scrolloffset == 0 Then /* cycle at end */ * scrolloffset = maxscrolloffset; * itemno = menulen; Else /* scroll 1 item */ * scrolloffset += delta; * itemno -= delta; Fi Fi Dowhile fullmenu [* scrolloffset + * itemno - 1].itemfu == separator Do * itemno += delta; If * itemno < 1 Then If * scrolloffset == 0 Then /* cycle at end */ * scrolloffset = maxscrolloffset; * itemno = menulen; Else /* scroll 1 item */ * scrolloffset += delta; * itemno -= delta; Fi Fi Done Elsif delta > 0 Then * itemno += delta; trace_menu_scroll ((" itemno %d + %d\n", * itemno, * scrolloffset)); Dowhile * itemno > menulen Do * scrolloffset += menulen; * itemno -= menulen; trace_menu_scroll (("-> itemno %d + %d\n", * itemno, * scrolloffset)); Done If * scrolloffset > maxscrolloffset Then * itemno += * scrolloffset - maxscrolloffset; * scrolloffset = maxscrolloffset; trace_menu_scroll (("=> itemno %d + %d\n", * itemno, * scrolloffset)); If * scrolloffset == prev_scrolloffset Then /* paging at end: move to menu end item */ * itemno = menulen; trace_menu_scroll (("=> itemno %d + %d\n", * itemno, * scrolloffset)); Fi If * itemno > menulen Then * itemno = menulen; trace_menu_scroll (("=> itemno %d + %d\n", * itemno, * scrolloffset)); Fi Fi If fullmenu [* scrolloffset + * itemno - 1].itemfu == separator Then If * itemno < menulen Then * itemno += 1; Else * itemno -= 1; Fi trace_menu_scroll (("!> itemno %d + %d\n", * itemno, * scrolloffset)); Fi Else * itemno += delta; Dowhile * itemno < 1 Do * scrolloffset -= menulen; * itemno += menulen; Done If * scrolloffset < 0 Then * itemno += * scrolloffset; * scrolloffset = 0; If * scrolloffset == prev_scrolloffset Then /* paging at end: move to menu end item */ * itemno = 1; Fi If * itemno < 1 Then * itemno = 1; Fi Fi If fullmenu [* scrolloffset + * itemno - 1].itemfu == separator Then If * itemno > 1 Then * itemno -= 1; Else * itemno += 1; Fi Fi Fi If * scrolloffset == prev_scrolloffset Then return False; Else * menu = & fullmenu [* scrolloffset]; return True; Fi } /* popup_menu token to ignore 1 (initial) mouse release event */ static FLAG ignore_1releasebutton = False; global int popup_menu (menu, menulen, column, line, title, is_flag_menu, disp_only, select_keys) menuitemtype * menu; int menulen; int column; int line; char * title; FLAG is_flag_menu; FLAG disp_only; /* Han info menu */ char * select_keys; /* pick list */ { menuitemtype * fullmenu = menu; int fullmenulen = menulen; int scrolloffset = 0; int maxscrolloffset = 0; unsigned long c; int startline; int minline; int startcolumn; int itemno; int ret = -1; char * cpoi; char * select; int scol; int select_index = -2; int sticky_index = -2; int minwidth = disp_only ? utf8_col_count (title) + 2 : 0; int menu_width; FLAG ignore_releasebutton; FLAG continue_menu = True; If line == -1 /* suppressed display of menu header line */ Then line = 0; Fi /* set token to ignore 1 mouse release event */ ignore_releasebutton = ignore_1releasebutton; /* set token to ignore initial mouse release event */ ignore_releasebutton = True; /* clear token to ignore 1 mouse release event */ ignore_1releasebutton = False; /* calculate general and specific menu geometry */ calcmenuvalues (); menu_width = width_of_menu (fullmenu, fullmenulen, 0, is_flag_menu, minwidth); /* adjust menu position and check with screen limits */ If column >= 0 Then startcolumn = column; Else startcolumn = 4 - column - menu_width - 2 * horizontal_bar_width; Fi If startcolumn > XMAX - menu_width - 2 * horizontal_bar_width + 2 Then startcolumn = XMAX - menu_width - 2 * horizontal_bar_width + 2; Fi If startcolumn < 0 || menu_width < 3 Then ring_bell (); return ret; Fi startline = line + 1; If startline > YMAX - menulen - 1 Then startline = YMAX - menulen - 1; Fi /* setup partial menu values for menu scrolling */ If is_flag_menu Then minline = 1; Else minline = 0; Fi If startline < minline Then maxscrolloffset = minline - startline; menulen = menulen - maxscrolloffset; startline = minline; Fi /* initial selection */ If select_keys == NIL_PTR Then itemno = 0; Else itemno = 1; select_index = 0; sticky_index = 0; Fi If menu_reposition Then (void) menu_scroll (& menu, menulen, previous_menuline + previous_scroll + 1 - startline, fullmenu, & scrolloffset, maxscrolloffset, & itemno); /* reset repositioning token */ menu_reposition = False; Fi /* remember previous menu in case this sub-menu returns to it */ previous_fullmenu = last_fullmenu; previous_menuline = last_menuline; previous_scroll = last_scroll; /* initial display */ display_menu (fullmenu, menulen, menu_width, startcolumn, startline, title, is_flag_menu, disp_only, minwidth, scrolloffset, maxscrolloffset); If itemno > 0 Then popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Fi /* for display-only menu, skip interactive part */ If disp_only Then menu_mouse_mode (False); return ret; Fi /* interactive menu handling */ Dowhile continue_menu Do flush (); c = readcharacter_allbuttons (); #define dont_debug_buttons #ifdef debug_buttons If command (c) == MOUSEescape Then local char * button_name [] = { "releasebutton", "leftbutton", "middlebutton", "rightbutton", "movebutton", "wheelup", "wheeldown"}; If mouse_button != releasebutton Then printf ("%s\n", button_name [mouse_button]); Else printf ("release (%s)\n", button_name [mouse_prevbutton]); Fi Fi #endif If command (c) == RDwin Then #define winchg_quits_menu #ifdef winchg_quits_menu popupmenu_active = False; RDwin (); clear_menus (); return ret; #else int fullitemno = itemno + scrolloffset; RDwin_nomenu (); /* recalculate general and specific menu geometry */ calcmenuvalues (); menu_width = width_of_menu (fullmenu, fullmenulen, 0, is_flag_menu, minwidth); /* adjust menu position and check with screen limits */ If column >= 0 Then startcolumn = column; Else startcolumn = 4 - column - menu_width - 2 * horizontal_bar_width; Fi If startcolumn > XMAX - menu_width - 2 * horizontal_bar_width + 2 Then startcolumn = XMAX - menu_width - 2 * horizontal_bar_width + 2; Fi If startcolumn < 0 || menu_width < 3 Then ring_bell (); clear_menus (); return ret; Fi /* reset menu geometry to full menu for recalculation */ menulen = fullmenulen; maxscrolloffset = 0; /* recalculate partial display */ startline = line + 1; If startline > YMAX - menulen - 1 Then startline = YMAX - menulen - 1; Fi /* setup partial menu values for menu scrolling */ If is_flag_menu Then minline = 1; Else minline = 0; Fi If startline < minline Then maxscrolloffset = minline - startline; menulen = menulen - maxscrolloffset; startline = minline; Fi #ifdef debug_resize_open_menus printf ("%dx%d start %d len %d max %d\n", YMAX, XMAX, startline, menulen, maxscrolloffset); #endif /* reset and adjust menu scroll */ #define no_winchg_full_reset #ifdef winchg_full_reset menu = fullmenu; scrolloffset = 0; itemno = 0; If fullitemno > 0 Then (void) menu_scroll (& menu, menulen, fullitemno, fullmenu, & scrolloffset, maxscrolloffset, & itemno); Fi #else (void) menu_scroll (& menu, menulen, 0, fullmenu, & scrolloffset, maxscrolloffset, & itemno); #endif /* redisplay */ display_menu (fullmenu, menulen, menu_width, startcolumn, startline, title, is_flag_menu, disp_only, minwidth, scrolloffset, maxscrolloffset); If itemno > 0 Then popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Fi #endif Elsif (c == ' ' && select_keys == NIL_PTR) || command (c) == HOP || command (c) == GOTO || (command (c) == MOUSEescape && mouse_button == middlebutton) Then toggle_HOP (); clear_menus (); /* recalculate x pos to prevent menu display wrap-around */ menu_width = width_of_menu (fullmenu, fullmenulen, 0, is_flag_menu, 0); If column >= 0 Then startcolumn = column; Else startcolumn = 4 - column - menu_width - 2 * horizontal_bar_width; Fi If startcolumn > XMAX - menu_width - 2 * horizontal_bar_width + 2 Then startcolumn = XMAX - menu_width - 2 * horizontal_bar_width + 2; Fi If startline < minline || startcolumn < 0 || menu_width < 3 Then ring_bell (); return ret; Fi /* display the menu */ display_menu (fullmenu, menulen, menu_width, startcolumn, startline, title, is_flag_menu, disp_only, minwidth, scrolloffset, maxscrolloffset); popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Elsif command (c) == MOUSEescape && mouse_button == releasebutton && mouse_prevbutton == middlebutton Then /* ignore */ Elsif select_keys != NIL_PTR && (command (c) == MLF || c == '<') Then If select_index > 0 Then select_index --; Else int prev_itemno = itemno; If menu_scroll (& menu, menulen, - 1, fullmenu, & scrolloffset, maxscrolloffset, & itemno) Then display_menu (fullmenu, menulen, menu_width, startcolumn, startline, title, is_flag_menu, disp_only, minwidth, scrolloffset, maxscrolloffset); Else popupmenselected (menu, menu_width, False, startcolumn, startline, prev_itemno - 1, select_index, is_flag_menu); Fi select_index = item_count (menu [itemno - 1].itemname) - 1; Fi sticky_index = select_index; popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Elsif select_keys != NIL_PTR && (command (c) == MRT || c == '>' || (c == ' ' && selection_space == SPACE_NEXT)) Then If select_index < item_count (menu [itemno - 1].itemname) - 1 Then select_index ++; Else int prev_itemno = itemno; If menu_scroll (& menu, menulen, 1, fullmenu, & scrolloffset, maxscrolloffset, & itemno) Then display_menu (fullmenu, menulen, menu_width, startcolumn, startline, title, is_flag_menu, disp_only, minwidth, scrolloffset, maxscrolloffset); Else popupmenselected (menu, menu_width, False, startcolumn, startline, prev_itemno - 1, select_index, is_flag_menu); Fi select_index = 0; Fi sticky_index = select_index; popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Elsif select_keys != NIL_PTR && (command (c) == HOMEkey || command (c) == smallHOMEkey) Then select_index = 0; sticky_index = 0; popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Elsif select_keys != NIL_PTR && (command (c) == ENDkey || command (c) == smallENDkey) Then select_index = item_count (menu [itemno - 1].itemname) - 1; sticky_index = strlen (select_keys) - 1; popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Elsif command (c) == HOMEkey || command (c) == smallHOMEkey Then int prev_itemno = itemno; If menu_scroll (& menu, menulen, - scrolloffset - menulen, fullmenu, & scrolloffset, maxscrolloffset, & itemno) Then display_menu (fullmenu, menulen, menu_width, startcolumn, startline, title, is_flag_menu, disp_only, minwidth, scrolloffset, maxscrolloffset); Else popupmenselected (menu, menu_width, False, startcolumn, startline, prev_itemno - 1, select_index, is_flag_menu); Fi popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Elsif command (c) == ENDkey || command (c) == smallENDkey Then int prev_itemno = itemno; If menu_scroll (& menu, menulen, maxscrolloffset + menulen, fullmenu, & scrolloffset, maxscrolloffset, & itemno) Then display_menu (fullmenu, menulen, menu_width, startcolumn, startline, title, is_flag_menu, disp_only, minwidth, scrolloffset, maxscrolloffset); Else popupmenselected (menu, menu_width, False, startcolumn, startline, prev_itemno - 1, select_index, is_flag_menu); Fi popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Elsif command (c) == PD Then int prev_itemno = itemno; If menu_scroll (& menu, menulen, menulen, fullmenu, & scrolloffset, maxscrolloffset, & itemno) Then display_menu (fullmenu, menulen, menu_width, startcolumn, startline, title, is_flag_menu, disp_only, minwidth, scrolloffset, maxscrolloffset); Else popupmenselected (menu, menu_width, False, startcolumn, startline, prev_itemno - 1, select_index, is_flag_menu); Fi If select_keys != NIL_PTR Then select_index = item_count (menu [itemno - 1].itemname) - 1; If sticky_index < select_index Then select_index = sticky_index; Fi Fi popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Elsif command (c) == PU Then int prev_itemno = itemno; If menu_scroll (& menu, menulen, - menulen, fullmenu, & scrolloffset, maxscrolloffset, & itemno) Then display_menu (fullmenu, menulen, menu_width, startcolumn, startline, title, is_flag_menu, disp_only, minwidth, scrolloffset, maxscrolloffset); Else popupmenselected (menu, menu_width, False, startcolumn, startline, prev_itemno - 1, select_index, is_flag_menu); Fi If select_keys != NIL_PTR Then select_index = item_count (menu [itemno - 1].itemname) - 1; If sticky_index < select_index Then select_index = sticky_index; Fi Fi popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Elsif command (c) == MDN || (c == ' ' && selection_space == SPACE_NEXTROW) || (command (c) == MOUSEescape && mouse_button == wheeldown) Then int prev_itemno = itemno; If menu_scroll (& menu, menulen, 1, fullmenu, & scrolloffset, maxscrolloffset, & itemno) Then display_menu (fullmenu, menulen, menu_width, startcolumn, startline, title, is_flag_menu, disp_only, minwidth, scrolloffset, maxscrolloffset); Else popupmenselected (menu, menu_width, False, startcolumn, startline, prev_itemno - 1, select_index, is_flag_menu); Fi If select_keys != NIL_PTR Then select_index = item_count (menu [itemno - 1].itemname) - 1; If sticky_index < select_index Then select_index = sticky_index; Fi Fi popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Elsif command (c) == MUP || (command (c) == MOUSEescape && mouse_button == wheelup) Then int prev_itemno = itemno; If menu_scroll (& menu, menulen, - 1, fullmenu, & scrolloffset, maxscrolloffset, & itemno) Then display_menu (fullmenu, menulen, menu_width, startcolumn, startline, title, is_flag_menu, disp_only, minwidth, scrolloffset, maxscrolloffset); Else popupmenselected (menu, menu_width, False, startcolumn, startline, prev_itemno - 1, select_index, is_flag_menu); Fi If select_keys != NIL_PTR Then select_index = item_count (menu [itemno - 1].itemname) - 1; If sticky_index < select_index Then select_index = sticky_index; Fi Fi popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Elsif command (c) == MOUSEescape && mouse_button == releasebutton && ignore_releasebutton Then ignore_releasebutton = False; Elsif command (c) == MOUSEescape && (mouse_button == leftbutton || mouse_button == movebutton || mouse_button == rightbutton ) Then popupmenselected (menu, menu_width, False, startcolumn, startline, itemno - 1, select_index, is_flag_menu); itemno = mouse_ypos - startline + 1; If itemno <= 0 || itemno > menulen || menu [itemno - 1].itemfu == separator Then itemno = 0; Else popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Fi If mouse_button == leftbutton Then continue_menu = False; Fi Elsif command (c) == MOUSEescape && mouse_button == releasebutton && mouse_prevbutton == rightbutton Then continue_menu = False; Elsif select_keys == NIL_PTR && c != FUNcmd && c > (character) ' ' Then int prev_itemno = itemno; int new_itemno = select_item (fullmenu, fullmenulen, itemno + scrolloffset, c); new_itemno -= scrolloffset; If menu_scroll (& menu, menulen, new_itemno - prev_itemno, fullmenu, & scrolloffset, maxscrolloffset, & itemno) Then display_menu (fullmenu, menulen, menu_width, startcolumn, startline, title, is_flag_menu, disp_only, minwidth, scrolloffset, maxscrolloffset); Else popupmenselected (menu, menu_width, False, startcolumn, startline, prev_itemno - 1, select_index, is_flag_menu); Fi popupmenselected (menu, menu_width, True, startcolumn, startline, itemno - 1, select_index, is_flag_menu); Else continue_menu = False; Fi If command (c) == MOUSEescape Then ignore_releasebutton = False; Fi Done If command (c) == MOUSEescape Then /* mouse click */ mouse_xpos -= startcolumn; mouse_ypos -= startline; If mouse_ypos + startline == -1 Then clear_menus (); displaymenuheaders (); openmenuat (mouse_xpos + startcolumn); Elsif mouse_xpos >= 0 && mouse_xpos < menu_width && mouse_ypos >= 0 && mouse_ypos < menulen Then If select_keys != NIL_PTR Then /* determine mouse position in menu line */ /* used for keyboard mapping selection */ select = menu [mouse_ypos].itemname; cpoi = select; ret = 0; scol = 1; Dowhile scol < mouse_xpos && * cpoi != '\0' Do If * cpoi == ' ' Then ret ++; Fi advance_utf8_scr (& cpoi, & scol, select); Done If ret < strlen (select_keys) Then ret = (scrolloffset + mouse_ypos) * strlen (select_keys) + ret; Else ret = -1; Fi Elsif menu [mouse_ypos].itemfu != separator Then popupmenselected (menu, menu_width, True, startcolumn, startline, mouse_ypos, select_index, is_flag_menu); menu_mouse_mode (False); (* menu [mouse_ypos].itemfu) (menu, mouse_ypos); displayflags (); Fi Fi Elsif (c == '\n' || command (c) == SNL || (c == ' ' && select_keys != NIL_PTR && selection_space == SPACE_SELECT) ) && itemno > 0 Then menu_mouse_mode (False); If select_keys != NIL_PTR Then ret = (scrolloffset + itemno - 1) * strlen (select_keys) + select_index; Else (* menu [itemno - 1].itemfu) (menu, itemno - 1); displayflags (); Fi Elsif select_keys != NIL_PTR && c != FUNcmd && c > (character) ' ' Then cpoi = strchr (select_keys, c); If cpoi != NIL_PTR && * cpoi != '\0' Then ret = (scrolloffset + itemno - 1) * strlen (select_keys) + (cpoi - select_keys); Fi Elsif command (c) == MLF && input_active == False Then clear_menus (); If ! open_prev_menu (fullmenu) Then /* set token to position to previously selected item */ menu_reposition = True; /* find previous menu in list of all menus to invoke */ that_menu (previous_fullmenu); Fi Elsif command (c) == MRT && input_active == False Then clear_menus (); If ! open_next_menu (fullmenu) Then /* find one menu right from previous menu */ If ! open_next_menu (previous_fullmenu) Then ring_bell (); error2 ("Internal error: ", "Menu not found"); Fi Fi Fi clear_menus (); If select_keys != NIL_PTR Then clear_status (); Fi return ret; } local void action_menu (menu, menulen, column, line, title, is_flag_menu) menuitemtype * menu; int menulen; int column; int line; char * title; FLAG is_flag_menu; { clear_menus (); (void) popup_menu (menu, menulen, column, line, title, is_flag_menu, False, NIL_PTR); } /***********************************************************************\ Invoking menus explicitly that_menu (m) opens that menu at its native position this_menu_here (m) open given menu at given position openmenuat (c) opens the menu at screen column c openmenu (i) opens the i-th menu \***********************************************************************/ local void that_menu (m) menuitemtype * m; { int i; For i = 0 While i < arrlen (Pulldownmenu) Step i ++ Do If Pulldownmenu [i].menuitems == m Then ignore_1releasebutton = True; action_menu (Pulldownmenu [i].menuitems, Pulldownmenu [i].menulen, i * pulldownmenu_width, -1, Pulldownmenu [i].menuname, False); return; Fi Done For i = 0 While i < arrlen (Flagmenu) Step i ++ Do If Flagmenu [i].menu == m Then ignore_1releasebutton = True; action_menu (Flagmenu [i].menu, Flagmenu [i].menulen, - (flags_pos + i - 1), 0, Flagmenu [i].menutitle, True); return; Fi Done If Popupmenu == m Then ignore_1releasebutton = True; QUICKMENU (); return; Fi ring_bell (); error2 ("Internal error: ", "Menu not found"); } local void this_menu_here (menu, menulen, menutitle) menuitemtype * menu; int menulen; char * menutitle; { ignore_1releasebutton = True; (void) popup_menu (menu, menulen, last_menucolumn + 9, last_menuline, menutitle, False, False, NIL_PTR); } global void openmenuat (column) int column; { int meni; calcmenuvalues (); If pulldownmenu_width < 3 Then return; Fi meni = column / pulldownmenu_width; If meni < 0 || meni >= number_menus () Then /* check if it's a flag toggle position */ meni = column - flags_pos; If meni >= 0 && meni < flags_displayed Then If mouse_button == leftbutton || mouse_button == middlebutton Then (* Flagmenu [meni].toggle) (column); Elsif Flagmenu [meni].menutitle != NIL_PTR Then If * ((* Flagmenu [meni].dispflag) ()) != ' ' Then action_menu ( Flagmenu [meni].menu, Flagmenu [meni].menulen, - (column - 1), 0, Flagmenu [meni].menutitle, True); Fi Fi displayflags (); set_cursor_xy (); Fi Else If mouse_button == middlebutton && hop_flag == 0 Then toggle_HOP (); Fi that_menu (Pulldownmenu [meni].menuitems); Fi } local void openmenu (i) int i; { openmenuat (i * pulldownmenu_width); } /***********************************************************************\ Invoking specific menus \***********************************************************************/ global void FILEMENU () { openmenu (0); } global void EDITMENU () { openmenu (1); } global void SEARCHMENU () { openmenu (2); } global void PARAMENU () { openmenu (3); } global void OPTIONSMENU () { openmenu (4); /*that_menu (Optionsmenu);*/ } global void QUICKMENU () { action_menu (Popupmenu, arrlen (Popupmenu), x, y, NIL_PTR, False); } global void handleQuotemenu () { that_menu (Quotemenu); } global void handleKeymapmenu () { that_menu (Keymapmenu); } global void handleEncodingmenu () { that_menu (encodingmenu); } global void handleFlagmenus () { flag_menu (0); } local void handleInfomenu () { that_menu (infomenu); } local void handleCombiningmenu () { that_menu (combiningmenu); } local void handleTextmenu () { that_menu (textmenu); } local void handleBuffermenu () { that_menu (buffermenu); } local void handleIndentmenu () { that_menu (autoindentmenu); } local void handleJustifymenu () { that_menu (justifymenu); } local void handleParagraphmodemenu () { that_menu (paragraphmodemenu); } local void handleScreensizemenu () { this_menu_here (Screensizemenu, arrlen (Screensizemenu), "Screen size"); } /***********************************************************************\ End \***********************************************************************/