Files
w3m/menu.c
Fumitoshi UKAI e312638d0c [w3m-dev 03730] display decoded URL
* anchor.c (link_list_panel): support DecodeURL
* display.c (make_lastline_link): support DecodeURL
* etc.c (url_unquote_conv): added
* fm.h (DecodeURL): added
* history.c (historyBuffer): support DecodeURL
* indep.c (QUOTE_MAP): added
	(HTML_QUOTE_MAP): added
	(html_quote_char): deleted
	(url_quote): use is_url_quote
	(file_quote): use is_file_quote
	(is_url_safe): deleted
	(Str_form_quote): use is_url_unsafe
	(Str_url_unquote): add safe args
	(is_shell_safe): delete
	(shell_quote): use is_shell_unsafe
* indep.h (QUOTE_MAP): added
	(HTML_QUOTE_MAP): added
	(HTML_QUOTE_MASK): added
	(SHELL_UNSAFE_MASK): added
	(URL_QUOTE_MASK): added
	(FILE_QUOTE_MASK): added
	(URL_UNSAFE_MASK): added
	(GET_QUOTE_TYPE): added
	(is_html_quote): added
	(is_shell_unsafe): added
	(is_url_quote): added
	(is_file_quote): added
	(is_url_unsafe): added
	(html_quote_char): added
	(html_quote_char): deleted
	(Str_url_unquote): added safe
	(form_unquote): Str_url_unquote changes
* linein.c (_prev): support DecodeURL
	(_next): ditto
* main.c (goURL0): support DecodeURL
	(_peekURL): ditto
	(curURL): ditto
* map.c (follow_map_panel): support DecodeURL
	(append_map_info): ditto
	(append_link_info): ditto
	(append_frame_info): ditto
	(page_info_panel): ditto
* menu.c (initSelectMenu): delete SCM_LOCAL_CGI
		support DecodeURL
	(initSelTabMenu): delete SCM_LOCAL_CGI
		support DecodeURL
	(link_menu): support DecodeURL
* parsetagx.c (parse_tag): is_html_quote
* proto.h (url_unquote_conv): added
* rc.c (CMT_DECODE_URL): added
	(params1): add decode_url
* url.c (openURL): Str_url_unquote non safe
From: Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp>
2003-02-05 16:43:56 +00:00

2077 lines
52 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* $Id: menu.c,v 1.31 2003/02/05 16:44:00 ukai Exp $ */
/*
* w3m menu.c
*/
#include <stdio.h>
#include "fm.h"
#include "menu.h"
#include "func.h"
#include "myctype.h"
#include "regex.h"
#ifdef USE_MOUSE
#ifdef USE_GPM
#include <gpm.h>
static int gpm_process_menu_mouse(Gpm_Event * event, void *data);
extern int gpm_process_mouse(Gpm_Event *, void *);
#endif /* USE_GPM */
#ifdef USE_SYSMOUSE
extern int (*sysm_handler) (int x, int y, int nbs, int obs);
static int sysm_process_menu_mouse(int, int, int, int);
extern int sysm_process_mouse(int, int, int, int);
#endif /* USE_SYSMOUSE */
#if defined(USE_GPM) || defined(USE_SYSMOUSE)
#define X_MOUSE_SELECTED (char)0xff
static int X_Mouse_Selection;
extern int do_getch();
#define getch() do_getch()
#endif /* defined(USE_GPM) || defined(USE_SYSMOUSE) */
#endif /* USE_MOUSE */
#ifdef USE_MENU
#ifdef KANJI_SYMBOLS
static char *FRAME[] = {
#ifdef MENU_THIN_FRAME
"", "", "",
"", " ", "",
"", "", "",
#else /* not MENU_THIN_FRAME */
"", "", "",
"", " ", "",
"", "", "",
#endif /* not MENU_THIN_FRAME */
"", ""
};
#define FRAME_WIDTH 2
#define G_start
/**/
#define G_end /**/
#else /* not KANJI_SYMBOLS */
static char *N_FRAME[] = {
"+", "-", "+",
"|", " ", "|",
"+", "-", "+",
":", ":"
};
#define FRAME_WIDTH 1
static char *G_FRAME[] = {
"l", "q", "k",
"x", " ", "x",
"m", "q", "j",
":", ":"
};
static char **FRAME = NULL;
static int graph_mode = FALSE;
#define G_start {if (graph_mode) graphstart();}
#define G_end {if (graph_mode) graphend();}
#endif /* not KANJI_SYMBOLS */
static int mEsc(char c);
static int mEscB(char c);
static int mEscD(char c);
static int mNull(char c);
static int mSelect(char c);
static int mDown(char c);
static int mUp(char c);
static int mLast(char c);
static int mTop(char c);
static int mNext(char c);
static int mPrev(char c);
static int mFore(char c);
static int mBack(char c);
static int mLineU(char c);
static int mLineD(char c);
static int mOk(char c);
static int mCancel(char c);
static int mClose(char c);
static int mSusp(char c);
static int mMouse(char c);
static int mSrchF(char c);
static int mSrchB(char c);
static int mSrchN(char c);
static int mSrchP(char c);
#ifdef __EMX__
static int mPc(char c);
#endif
/* *INDENT-OFF* */
static int (*MenuKeymap[128]) (char c) = {
/* C-@ C-a C-b C-c C-d C-e C-f C-g */
#ifdef __EMX__
mPc, mTop, mPrev, mClose, mNull, mLast, mNext, mNull,
#else
mNull, mTop, mPrev, mClose, mNull, mLast, mNext, mNull,
#endif
/* C-h C-i C-j C-k C-l C-m C-n C-o */
mCancel,mNull, mOk, mNull, mNull, mOk, mDown, mNull,
/* C-p C-q C-r C-s C-t C-u C-v C-w */
mUp, mNull, mSrchB, mSrchF, mNull, mNull, mNext, mNull,
/* C-x C-y C-z C-[ C-\ C-] C-^ C-_ */
mNull, mNull, mSusp, mEsc, mNull, mNull, mNull, mNull,
/* SPC ! " # $ % & ' */
mOk, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
/* ( ) * + , - . / */
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mSrchF,
/* 0 1 2 3 4 5 6 7 */
mNull, mNull, mNull, mNull, mNull, mNull , mNull, mNull,
/* 8 9 : ; < = > ? */
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mSrchB,
/* @ A B C D E F G */
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
/* H I J K L M N O */
mNull, mNull, mLineU, mLineD, mNull, mNull, mSrchP, mNull,
/* P Q R S T U V W */
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
/* X Y Z [ \ ] ^ _ */
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
/* ` a b c d e f g */
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
/* h i j k l m n o */
mCancel,mNull, mDown, mUp, mOk, mNull, mSrchN, mNull,
/* p q r s t u v w */
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
/* x y z { | } ~ DEL */
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mCancel,
};
static int (*MenuEscKeymap[128]) (char c) = {
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
/* O */
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mEscB,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
/* [ */
mNull, mNull, mNull, mEscB, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
/* v */
mNull, mNull, mNull, mNull, mNull, mNull, mPrev, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
};
static int (*MenuEscBKeymap[128]) (char c) = {
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
/* A B C D E */
mNull, mUp, mDown, mOk, mCancel,mClose, mNull, mNull,
/* L M */
mNull, mNull, mNull, mNull, mClose, mMouse, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
};
static int (*MenuEscDKeymap[128]) (char c) = {
/* 0 1 INS 3 4 PgUp, PgDn 7 */
mNull, mNull, mClose, mNull, mNull, mBack, mFore, mNull,
/* 8 9 10 F1 F2 F3 F4 F5 */
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
/* 16 F6 F7 F8 F9 F10 22 23 */
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
/* 24 25 26 27 HELP 29 30 31 */
mNull, mNull, mNull, mNull, mClose, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
};
#ifdef __EMX__
static int (*MenuPcKeymap[256])(char c)={
// Null
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// S-Tab
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// A-q A-w A-E A-r A-t A-y A-u A-i
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// A-o A-p A-[ A-] A-a A-s
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// A-d A-f A-g A-h A-j A-k A-l A-;
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// A-' A-' A-\ A-x A-c A-v
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mPrev,
// A-b A-n A-m A-, A-. A-/ A-+
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// F1 F2 F3 F4 F5
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// F6 F7 F8 F9 F10 Home
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mTop,
// Up PgUp A-/ Left 5 Right C-* End
mUp, mUp, mNull, mCancel,mNull, mOk, mNull, mLast,
// Down PgDn Ins Del S-F1 S-F2 S-F3 S-F4
mDown, mDown, mClose, mCancel,mNull, mNull, mNull, mNull,
// S-F5 S-F6 S-F7 S-F8 S-F9 S-F10 C-F1 C-F2
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// C-F3 C-F4 C-F5 C-F6 C-F7 C-F8 C-F9 C-F10
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// A-F1 A-F2 A-F3 A-F4 A-F5 A-F6 A-F7 A-F8
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// A-F9 A-F10 PrtSc C-Left C-Right C-End C-PgDn C-Home
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// A-1 A-2 A-3 A-4 A-5 A-6 A-7/8 A-9
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// A-0 A - A-= C-PgUp F11 F12 S-F11
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// S-F12 C-F11 C-F12 A-F11 A-F12 C-Up C-/ C-5
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// S-* C-Down C-Ins C-Del C-Tab C - C-+
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull,
// A - A-Tab A-Enter
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 160
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 168
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 176
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 184
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 192
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 200
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 208
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 216
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 224
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 232
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull, // 240
mNull, mNull, mNull, mNull, mNull, mNull, mNull, mNull // 248
};
#endif
/* *INDENT-ON* */
/* --- SelectMenu --- */
static Menu SelectMenu;
static int SelectV = 0;
static void initSelectMenu(void);
static void smChBuf(void);
static int smDelBuf(char c);
/* --- SelectMenu (END) --- */
/* --- SelTabMenu --- */
static Menu SelTabMenu;
static int SelTabV = 0;
static void initSelTabMenu(void);
static void smChTab(void);
static int smDelTab(char c);
/* --- SelTabMenu (END) --- */
/* --- MainMenu --- */
static Menu MainMenu;
#if LANG == JA
static MenuItem MainMenuItem[] = {
/* type label variabel value func popup keys data */
{MENU_FUNC, "戻る (b)", NULL, 0, backBf, NULL, "b", NULL},
{MENU_POPUP, "バッファ選択 (s)", NULL, 0, NULL, &SelectMenu, "s", NULL},
{MENU_POPUP, "タブ選択 (t)", NULL, 0, NULL, &SelTabMenu, "tT", NULL},
{MENU_FUNC, "ソースを表示 (v)", NULL, 0, vwSrc, NULL, "vV", NULL},
{MENU_FUNC, "ソースを編集 (e)", NULL, 0, editBf, NULL, "eE", NULL},
{MENU_FUNC, "ソースを保存 (S)", NULL, 0, svSrc, NULL, "S", NULL},
{MENU_FUNC, "再読み込み (r)", NULL, 0, reload, NULL, "rR", NULL},
{MENU_NOP, "────────", NULL, 0, nulcmd, NULL, "", NULL},
{MENU_FUNC, "リンクを表示 (a)", NULL, 0, followA, NULL, "a", NULL},
{MENU_FUNC, "新タブで表示 (n)", NULL, 0, tabA, NULL, "nN", NULL},
{MENU_FUNC, "リンクを保存 (A)", NULL, 0, svA, NULL, "A", NULL},
{MENU_FUNC, "画像を表示 (i)", NULL, 0, followI, NULL, "i", NULL},
{MENU_FUNC, "画像を保存 (I)", NULL, 0, svI, NULL, "I", NULL},
{MENU_FUNC, "フレーム表示 (f)", NULL, 0, rFrame, NULL, "fF", NULL},
{MENU_NOP, "────────", NULL, 0, nulcmd, NULL, "", NULL},
{MENU_FUNC, "ブックマーク (B)", NULL, 0, ldBmark, NULL, "B", NULL},
{MENU_FUNC, "ヘルプ (h)", NULL, 0, ldhelp, NULL, "hH", NULL},
{MENU_FUNC, "オプション (o)", NULL, 0, ldOpt, NULL, "oO", NULL},
{MENU_NOP, "────────", NULL, 0, nulcmd, NULL, "", NULL},
{MENU_FUNC, "終了 (q)", NULL, 0, qquitfm, NULL, "qQ", NULL},
{MENU_END, "", NULL, 0, nulcmd, NULL, "", NULL},
};
#else /* LANG != JA */
static MenuItem MainMenuItem[] = {
/* type label variable value func popup keys data */
{MENU_FUNC, " Back (b) ", NULL, 0, backBf, NULL, "b", NULL},
{MENU_POPUP, " Select Buffer(s) ", NULL, 0, NULL, &SelectMenu, "s", NULL},
{MENU_POPUP, " Select Tab (t) ", NULL, 0, NULL, &SelTabMenu, "tT", NULL},
{MENU_FUNC, " View Source (v) ", NULL, 0, vwSrc, NULL, "vV", NULL},
{MENU_FUNC, " Edit Source (e) ", NULL, 0, editBf, NULL, "eE", NULL},
{MENU_FUNC, " Save Source (S) ", NULL, 0, svSrc, NULL, "S", NULL},
{MENU_FUNC, " Reload (r) ", NULL, 0, reload, NULL, "rR", NULL},
{MENU_NOP, " ---------------- ", NULL, 0, nulcmd, NULL, "", NULL},
{MENU_FUNC, " Go Link (a) ", NULL, 0, followA, NULL, "a", NULL},
{MENU_FUNC, " on New Tab (n) ", NULL, 0, tabA, NULL, "nN", NULL},
{MENU_FUNC, " Save Link (A) ", NULL, 0, svA, NULL, "A", NULL},
{MENU_FUNC, " View Image (i) ", NULL, 0, followI, NULL, "i", NULL},
{MENU_FUNC, " Save Image (I) ", NULL, 0, svI, NULL, "I", NULL},
{MENU_FUNC, " View Frame (f) ", NULL, 0, rFrame, NULL, "fF", NULL},
{MENU_NOP, " ---------------- ", NULL, 0, nulcmd, NULL, "", NULL},
{MENU_FUNC, " Bookmark (B) ", NULL, 0, ldBmark, NULL, "B", NULL},
{MENU_FUNC, " Help (h) ", NULL, 0, ldhelp, NULL, "hH", NULL},
{MENU_FUNC, " Option (o) ", NULL, 0, ldOpt, NULL, "oO", NULL},
{MENU_NOP, " ---------------- ", NULL, 0, nulcmd, NULL, "", NULL},
{MENU_FUNC, " Quit (q) ", NULL, 0, qquitfm, NULL, "qQ", NULL},
{MENU_END, "", NULL, 0, nulcmd, NULL, "", NULL},
};
#endif /* LANG != JA */
/* --- MainMenu (END) --- */
static MenuList *w3mMenuList;
static Menu *CurrentMenu = NULL;
#define mvaddch(y, x, c) (move(y, x), addch(c))
#define mvaddstr(y, x, str) (move(y, x), addstr(str))
#define mvaddnstr(y, x, str, n) (move(y, x), addnstr_sup(str, n))
void
new_menu(Menu *menu, MenuItem *item)
{
int i, l;
char *p;
menu->cursorX = 0;
menu->cursorY = 0;
menu->x = 0;
menu->y = 0;
menu->nitem = 0;
menu->item = item;
menu->initial = 0;
menu->select = 0;
menu->offset = 0;
menu->active = 0;
if (item == NULL)
return;
for (i = 0; item[i].type != MENU_END; i++) ;
menu->nitem = i;
menu->height = menu->nitem;
for (i = 0; i < 128; i++)
menu->keymap[i] = MenuKeymap[i];
menu->width = 0;
for (i = 0; i < menu->nitem; i++) {
if ((p = item[i].keys) != NULL) {
while (*p) {
if (IS_ASCII(*p)) {
menu->keymap[(int)*p] = mSelect;
menu->keyselect[(int)*p] = i;
}
p++;
}
}
l = strlen(item[i].label);
if (l > menu->width)
menu->width = l;
}
}
void
geom_menu(Menu *menu, int x, int y, int mselect)
{
int win_x, win_y, win_w, win_h;
menu->select = mselect;
if (menu->width % FRAME_WIDTH)
menu->width = (menu->width / FRAME_WIDTH + 1) * FRAME_WIDTH;
win_x = menu->x - FRAME_WIDTH;
win_w = menu->width + 2 * FRAME_WIDTH;
if (win_x + win_w > COLS)
win_x = COLS - win_w;
if (win_x < 0) {
win_x = 0;
if (win_w > COLS) {
menu->width = COLS - 2 * FRAME_WIDTH;
menu->width -= menu->width % FRAME_WIDTH;
win_w = menu->width + 2 * FRAME_WIDTH;
}
}
menu->x = win_x + FRAME_WIDTH;
win_y = menu->y - mselect - 1;
win_h = menu->height + 2;
if (win_y + win_h > LASTLINE)
win_y = LASTLINE - win_h;
if (win_y < 0) {
win_y = 0;
if (win_y + win_h > LASTLINE) {
win_h = LASTLINE - win_y;
menu->height = win_h - 2;
if (menu->height <= mselect)
menu->offset = mselect - menu->height + 1;
}
}
menu->y = win_y + 1;
}
void
draw_all_menu(Menu *menu)
{
if (menu->parent != NULL)
draw_all_menu(menu->parent);
draw_menu(menu);
}
void
draw_menu(Menu *menu)
{
int x, y, w;
int i, j;
x = menu->x - FRAME_WIDTH;
w = menu->width + 2 * FRAME_WIDTH;
y = menu->y - 1;
#ifndef KANJI_SYMBOLS
if (FRAME == NULL) {
if (graph_ok()) {
graph_mode = TRUE;
FRAME = G_FRAME;
}
else {
FRAME = N_FRAME;
}
}
#endif /* not KANJI_SYMBOLS */
if (menu->offset == 0) {
G_start;
mvaddstr(y, x, FRAME[0]);
for (i = FRAME_WIDTH; i < w - FRAME_WIDTH; i += FRAME_WIDTH)
mvaddstr(y, x + i, FRAME[1]);
mvaddstr(y, x + i, FRAME[2]);
G_end;
}
else {
G_start;
mvaddstr(y, x, FRAME[3]);
G_end;
for (i = FRAME_WIDTH; i < w - FRAME_WIDTH; i += FRAME_WIDTH)
mvaddstr(y, x + i, FRAME[4]);
G_start;
mvaddstr(y, x + i, FRAME[5]);
G_end;
i = (w / 2 - 1) / FRAME_WIDTH * FRAME_WIDTH;
mvaddstr(y, x + i, FRAME[9]);
}
for (j = 0; j < menu->height; j++) {
y++;
G_start;
mvaddstr(y, x, FRAME[3]);
G_end;
draw_menu_item(menu, menu->offset + j);
G_start;
mvaddstr(y, x + w - FRAME_WIDTH, FRAME[5]);
G_end;
}
y++;
if (menu->offset + menu->height == menu->nitem) {
G_start;
mvaddstr(y, x, FRAME[6]);
for (i = FRAME_WIDTH; i < w - FRAME_WIDTH; i += FRAME_WIDTH)
mvaddstr(y, x + i, FRAME[7]);
mvaddstr(y, x + i, FRAME[8]);
G_end;
}
else {
G_start;
mvaddstr(y, x, FRAME[3]);
G_end;
for (i = FRAME_WIDTH; i < w - FRAME_WIDTH; i += FRAME_WIDTH)
mvaddstr(y, x + i, FRAME[4]);
G_start;
mvaddstr(y, x + i, FRAME[5]);
G_end;
i = (w / 2 - 1) / FRAME_WIDTH * FRAME_WIDTH;
mvaddstr(y, x + i, FRAME[10]);
}
}
void
draw_menu_item(Menu *menu, int mselect)
{
mvaddnstr(menu->y + mselect - menu->offset, menu->x,
menu->item[mselect].label, menu->width);
}
int
select_menu(Menu *menu, int mselect)
{
if (mselect < 0 || mselect >= menu->nitem)
return (MENU_NOTHING);
if (mselect < menu->offset)
up_menu(menu, menu->offset - mselect);
else if (mselect >= menu->offset + menu->height)
down_menu(menu, mselect - menu->offset - menu->height + 1);
if (menu->select >= menu->offset &&
menu->select < menu->offset + menu->height)
draw_menu_item(menu, menu->select);
menu->select = mselect;
standout();
draw_menu_item(menu, menu->select);
standend();
/*
* move(menu->cursorY, menu->cursorX); */
move(menu->y + mselect - menu->offset, menu->x);
toggle_stand();
refresh();
return (menu->select);
}
void
goto_menu(Menu *menu, int mselect, int down)
{
int select_in;
if (mselect >= menu->nitem)
mselect = menu->nitem - 1;
else if (mselect < 0)
mselect = 0;
select_in = mselect;
while (menu->item[mselect].type == MENU_NOP) {
if (down > 0) {
if (++mselect >= menu->nitem) {
down_menu(menu, select_in - menu->select);
mselect = menu->select;
break;
}
}
else if (down < 0) {
if (--mselect < 0) {
up_menu(menu, menu->select - select_in);
mselect = menu->select;
break;
}
}
else {
return;
}
}
select_menu(menu, mselect);
}
void
up_menu(Menu *menu, int n)
{
if (n < 0 || menu->offset == 0)
return;
menu->offset -= n;
if (menu->offset < 0)
menu->offset = 0;
draw_menu(menu);
}
void
down_menu(Menu *menu, int n)
{
if (n < 0 || menu->offset + menu->height == menu->nitem)
return;
menu->offset += n;
if (menu->offset + menu->height > menu->nitem)
menu->offset = menu->nitem - menu->height;
draw_menu(menu);
}
int
action_menu(Menu *menu)
{
char c;
int mselect;
MenuItem item;
if (menu->active == 0) {
if (menu->parent != NULL)
menu->parent->active = 0;
return (0);
}
draw_all_menu(menu);
select_menu(menu, menu->select);
while (1) {
#ifdef USE_MOUSE
if (use_mouse)
mouse_active();
#endif /* USE_MOUSE */
c = getch();
#ifdef USE_MOUSE
if (use_mouse)
mouse_inactive();
#if defined(USE_GPM) || defined(USE_SYSMOUSE)
if (c == X_MOUSE_SELECTED) {
mselect = X_Mouse_Selection;
if (mselect != MENU_NOTHING)
break;
}
#endif /* defined(USE_GPM) || defined(USE_SYSMOUSE) */
#endif /* USE_MOUSE */
if (IS_ASCII(c)) { /* Ascii */
mselect = (*menu->keymap[(int)c]) (c);
if (mselect != MENU_NOTHING)
break;
}
}
if (mselect >= 0 && mselect < menu->nitem) {
item = menu->item[mselect];
if (item.type & MENU_POPUP) {
popup_menu(menu, item.popup);
return (1);
}
if (menu->parent != NULL)
menu->parent->active = 0;
if (item.type & MENU_VALUE)
*item.variable = item.value;
if (item.type & MENU_FUNC) {
CurrentKey = -1;
CurrentKeyData = NULL;
CurrentCmdData = item.data;
(*item.func) ();
CurrentCmdData = NULL;
}
}
else if (mselect == MENU_CLOSE) {
if (menu->parent != NULL)
menu->parent->active = 0;
}
return (0);
}
void
popup_menu(Menu *parent, Menu *menu)
{
int active = 1;
if (menu->item == NULL || menu->nitem == 0)
return;
if (menu->active)
return;
#ifdef USE_MOUSE
#ifdef USE_GPM
gpm_handler = gpm_process_menu_mouse;
#endif /* USE_GPM */
#ifdef USE_SYSMOUSE
sysm_handler = sysm_process_menu_mouse;
#endif /* USE_SYSMOUSE */
#endif /* USE_MOUSE */
menu->parent = parent;
menu->select = menu->initial;
menu->offset = 0;
menu->active = 1;
if (parent != NULL) {
menu->cursorX = parent->cursorX;
menu->cursorY = parent->cursorY;
guess_menu_xy(parent, menu->width, &menu->x, &menu->y);
}
geom_menu(menu, menu->x, menu->y, menu->select);
CurrentMenu = menu;
while (active) {
active = action_menu(CurrentMenu);
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
menu->active = 0;
CurrentMenu = parent;
#ifdef USE_MOUSE
#ifdef USE_GPM
if (CurrentMenu == NULL)
gpm_handler = gpm_process_mouse;
#endif /* USE_GPM */
#ifdef USE_SYSMOUSE
if (CurrentMenu == NULL)
sysm_handler = sysm_process_mouse;
#endif /* USE_SYSMOUSE */
#endif /* USE_MOUSE */
}
void
guess_menu_xy(Menu *parent, int width, int *x, int *y)
{
*x = parent->x + parent->width + FRAME_WIDTH - 1;
if (*x + width + FRAME_WIDTH > COLS) {
*x = COLS - width - FRAME_WIDTH;
if ((parent->x + parent->width / 2 > *x) &&
(parent->x + parent->width / 2 > COLS / 2))
*x = parent->x - width - FRAME_WIDTH + 1;
}
*y = parent->y + parent->select - parent->offset;
}
void
new_option_menu(Menu *menu, char **label, int *variable, void (*func) ())
{
int i, nitem;
char **p;
MenuItem *item;
if (label == NULL || *label == NULL)
return;
for (i = 0, p = label; *p != NULL; i++, p++) ;
nitem = i;
item = New_N(MenuItem, nitem + 1);
for (i = 0, p = label; i < nitem; i++, p++) {
if (func != NULL)
item[i].type = MENU_VALUE | MENU_FUNC;
else
item[i].type = MENU_VALUE;
item[i].label = *p;
item[i].variable = variable;
item[i].value = i;
item[i].func = func;
item[i].popup = NULL;
item[i].keys = "";
}
item[nitem].type = MENU_END;
new_menu(menu, item);
}
/* --- MenuFunctions --- */
#ifdef __EMX__
static int
mPc(char c)
{
c = getch();
return (MenuPcKeymap[(int)c] (c));
}
#endif
static int
mEsc(char c)
{
c = getch();
return (MenuEscKeymap[(int)c] (c));
}
static int
mEscB(char c)
{
c = getch();
if (IS_DIGIT(c))
return (mEscD(c));
else
return (MenuEscBKeymap[(int)c] (c));
}
static int
mEscD(char c)
{
int d;
d = (int)c - (int)'0';
c = getch();
if (IS_DIGIT(c)) {
d = d * 10 + (int)c - (int)'0';
c = getch();
}
if (c == '~')
return (MenuEscDKeymap[d] (c));
else
return (MENU_NOTHING);
}
static int
mNull(char c)
{
return (MENU_NOTHING);
}
static int
mSelect(char c)
{
if (IS_ASCII(c))
return (select_menu(CurrentMenu, CurrentMenu->keyselect[(int)c]));
else
return (MENU_NOTHING);
}
static int
mDown(char c)
{
if (CurrentMenu->select >= CurrentMenu->nitem - 1)
return (MENU_NOTHING);
goto_menu(CurrentMenu, CurrentMenu->select + 1, 1);
return (MENU_NOTHING);
}
static int
mUp(char c)
{
if (CurrentMenu->select <= 0)
return (MENU_NOTHING);
goto_menu(CurrentMenu, CurrentMenu->select - 1, -1);
return (MENU_NOTHING);
}
static int
mLast(char c)
{
goto_menu(CurrentMenu, CurrentMenu->nitem - 1, -1);
return (MENU_NOTHING);
}
static int
mTop(char c)
{
goto_menu(CurrentMenu, 0, 1);
return (MENU_NOTHING);
}
static int
mNext(char c)
{
int mselect = CurrentMenu->select + CurrentMenu->height;
if (mselect >= CurrentMenu->nitem)
return mLast(c);
down_menu(CurrentMenu, CurrentMenu->height);
goto_menu(CurrentMenu, mselect, -1);
return (MENU_NOTHING);
}
static int
mPrev(char c)
{
int mselect = CurrentMenu->select - CurrentMenu->height;
if (mselect < 0)
return mTop(c);
up_menu(CurrentMenu, CurrentMenu->height);
goto_menu(CurrentMenu, mselect, 1);
return (MENU_NOTHING);
}
static int
mFore(char c)
{
if (CurrentMenu->select >= CurrentMenu->nitem - 1)
return (MENU_NOTHING);
goto_menu(CurrentMenu, (CurrentMenu->select + CurrentMenu->height - 1),
(CurrentMenu->height + 1));
return (MENU_NOTHING);
}
static int
mBack(char c)
{
if (CurrentMenu->select <= 0)
return (MENU_NOTHING);
goto_menu(CurrentMenu, (CurrentMenu->select - CurrentMenu->height + 1),
(-1 - CurrentMenu->height));
return (MENU_NOTHING);
}
static int
mLineU(char c)
{
int mselect = CurrentMenu->select;
if (mselect >= CurrentMenu->nitem)
return mLast(c);
if (CurrentMenu->offset + CurrentMenu->height >= CurrentMenu->nitem)
mselect++;
else {
down_menu(CurrentMenu, 1);
if (mselect < CurrentMenu->offset)
mselect++;
}
goto_menu(CurrentMenu, mselect, 1);
return (MENU_NOTHING);
}
static int
mLineD(char c)
{
int mselect = CurrentMenu->select;
if (mselect <= 0)
return mTop(c);
if (CurrentMenu->offset <= 0)
mselect--;
else {
up_menu(CurrentMenu, 1);
if (mselect >= CurrentMenu->offset + CurrentMenu->height)
mselect--;
}
goto_menu(CurrentMenu, mselect, -1);
return (MENU_NOTHING);
}
static int
mOk(char c)
{
int mselect = CurrentMenu->select;
if (CurrentMenu->item[mselect].type == MENU_NOP)
return (MENU_NOTHING);
return (mselect);
}
static int
mCancel(char c)
{
return (MENU_CANCEL);
}
static int
mClose(char c)
{
return (MENU_CLOSE);
}
static int
mSusp(char c)
{
susp();
draw_all_menu(CurrentMenu);
select_menu(CurrentMenu, CurrentMenu->select);
return (MENU_NOTHING);
}
static char *SearchString = NULL;
int (*menuSearchRoutine) (Menu *, char *, int);
static int
menuForwardSearch(Menu *menu, char *str, int from)
{
int i;
char *p;
if ((p = regexCompile(str, IgnoreCase)) != NULL) {
message(p, 0, 0);
return -1;
}
if (from < 0)
from = 0;
for (i = from; i < menu->nitem; i++)
if (menu->item[i].type != MENU_NOP &&
regexMatch(menu->item[i].label, -1, 1) == 1)
return i;
return -1;
}
static int
menu_search_forward(Menu *menu, int from)
{
char *str;
int found;
str = inputStrHist("Forward: ", NULL, TextHist);
if (str != NULL && *str == '\0')
str = SearchString;
if (str == NULL || *str == '\0')
return -1;
SearchString = str;
menuSearchRoutine = menuForwardSearch;
found = menuForwardSearch(menu, SearchString, from + 1);
if (WrapSearch && found == -1)
found = menuForwardSearch(menu, SearchString, 0);
if (found >= 0)
return found;
disp_message("Not found", TRUE);
return -1;
}
static int
mSrchF(char c)
{
int mselect;
mselect = menu_search_forward(CurrentMenu, CurrentMenu->select);
if (mselect >= 0)
goto_menu(CurrentMenu, mselect, 1);
return (MENU_NOTHING);
}
static int
menuBackwardSearch(Menu *menu, char *str, int from)
{
int i;
char *p;
if ((p = regexCompile(str, IgnoreCase)) != NULL) {
message(p, 0, 0);
return -1;
}
if (from >= menu->nitem)
from = menu->nitem - 1;
for (i = from; i >= 0; i--)
if (menu->item[i].type != MENU_NOP &&
regexMatch(menu->item[i].label, -1, 1) == 1)
return i;
return -1;
}
static int
menu_search_backward(Menu *menu, int from)
{
char *str;
int found;
str = inputStrHist("Backward: ", NULL, TextHist);
if (str != NULL && *str == '\0')
str = SearchString;
if (str == NULL || *str == '\0')
return (MENU_NOTHING);
SearchString = str;
menuSearchRoutine = menuBackwardSearch;
found = menuBackwardSearch(menu, SearchString, from - 1);
if (WrapSearch && found == -1)
found = menuBackwardSearch(menu, SearchString, menu->nitem);
if (found >= 0)
return found;
disp_message("Not found", TRUE);
return -1;
}
static int
mSrchB(char c)
{
int mselect;
mselect = menu_search_backward(CurrentMenu, CurrentMenu->select);
if (mselect >= 0)
goto_menu(CurrentMenu, mselect, -1);
return (MENU_NOTHING);
}
static int
menu_search_next_previous(Menu *menu, int from, int reverse)
{
int found;
static int (*routine[2]) (Menu *, char *, int) = {
menuForwardSearch, menuBackwardSearch};
if (menuSearchRoutine == NULL) {
disp_message("No previous regular expression", TRUE);
return -1;
}
if (reverse != 0)
reverse = 1;
if (menuSearchRoutine == menuBackwardSearch)
reverse ^= 1;
from += reverse ? -1 : 1;
found = (*routine[reverse]) (menu, SearchString, from);
if (WrapSearch && found == -1)
found =
(*routine[reverse]) (menu, SearchString, reverse * menu->nitem);
if (found >= 0)
return found;
disp_message("Not found", TRUE);
return -1;
}
static int
mSrchN(char c)
{
int mselect;
mselect = menu_search_next_previous(CurrentMenu, CurrentMenu->select, 0);
if (mselect >= 0)
goto_menu(CurrentMenu, mselect, 1);
return (MENU_NOTHING);
}
static int
mSrchP(char c)
{
int mselect;
mselect = menu_search_next_previous(CurrentMenu, CurrentMenu->select, 1);
if (mselect >= 0)
goto_menu(CurrentMenu, mselect, -1);
return (MENU_NOTHING);
}
#ifdef USE_MOUSE
#define MOUSE_BTN1_DOWN 0
#define MOUSE_BTN2_DOWN 1
#define MOUSE_BTN3_DOWN 2
#define MOUSE_BTN4_DOWN_RXVT 3
#define MOUSE_BTN5_DOWN_RXVT 4
#define MOUSE_BTN4_DOWN_XTERM 64
#define MOUSE_BTN5_DOWN_XTERM 65
#define MOUSE_BTN_UP 3
#define MOUSE_BTN_RESET -1
static int
mMouse_scroll_line(void)
{
int i = 0;
if (relative_wheel_scroll)
i = (relative_wheel_scroll_ratio * CurrentMenu->height + 99) / 100;
else
i = fixed_wheel_scroll_count;
return i ? i : 1;
}
static int
process_mMouse(int btn, int x, int y)
{
Menu *menu;
int mselect, i;
static int press_btn = MOUSE_BTN_RESET, press_x, press_y;
char c = ' ';
menu = CurrentMenu;
if (x < 0 || x >= COLS || y < 0 || y > LASTLINE)
return (MENU_NOTHING);
if (btn == MOUSE_BTN_UP) {
switch (press_btn) {
case MOUSE_BTN1_DOWN:
case MOUSE_BTN3_DOWN:
if (x < menu->x - FRAME_WIDTH ||
x >= menu->x + menu->width + FRAME_WIDTH ||
y < menu->y - 1 || y >= menu->y + menu->height + 1) {
return (MENU_CANCEL);
}
else if ((x >= menu->x - FRAME_WIDTH &&
x < menu->x) ||
(x >= menu->x + menu->width &&
x < menu->x + menu->width + FRAME_WIDTH)) {
return (MENU_NOTHING);
}
else if (press_y > y) {
for (i = 0; i < press_y - y; i++)
mLineU(c);
return (MENU_NOTHING);
}
else if (press_y < y) {
for (i = 0; i < y - press_y; i++)
mLineD(c);
return (MENU_NOTHING);
}
else if (y == menu->y - 1) {
mPrev(c);
return (MENU_NOTHING);
}
else if (y == menu->y + menu->height) {
mNext(c);
return (MENU_NOTHING);
}
else {
mselect = y - menu->y + menu->offset;
if (menu->item[mselect].type == MENU_NOP)
return (MENU_NOTHING);
return (select_menu(menu, mselect));
}
break;
case MOUSE_BTN4_DOWN_RXVT:
for (i = 0; i < mMouse_scroll_line(); i++)
mLineD(c);
break;
case MOUSE_BTN5_DOWN_RXVT:
for (i = 0; i < mMouse_scroll_line(); i++)
mLineU(c);
break;
}
}
else if (btn == MOUSE_BTN4_DOWN_XTERM) {
for (i = 0; i < mMouse_scroll_line(); i++)
mLineD(c);
}
else if (btn == MOUSE_BTN5_DOWN_XTERM) {
for (i = 0; i < mMouse_scroll_line(); i++)
mLineU(c);
}
if (btn != MOUSE_BTN4_DOWN_RXVT || press_btn == MOUSE_BTN_RESET) {
press_btn = btn;
press_x = x;
press_y = y;
}
else {
press_btn = MOUSE_BTN_RESET;
}
return (MENU_NOTHING);
}
static int
mMouse(char c)
{
int btn, x, y;
btn = (unsigned char)getch() - 32;
#if defined(__CYGWIN__)
if (cygwin_mouse_btn_swapped) {
if (btn == MOUSE_BTN2_DOWN)
btn = MOUSE_BTN3_DOWN;
else if (btn == MOUSE_BTN3_DOWN)
btn = MOUSE_BTN2_DOWN;
}
#endif
x = (unsigned char)getch() - 33;
if (x < 0)
x += 0x100;
y = (unsigned char)getch() - 33;
if (y < 0)
y += 0x100;
/*
* if (x < 0 || x >= COLS || y < 0 || y > LASTLINE) return; */
return process_mMouse(btn, x, y);
}
#ifdef USE_GPM
static int
gpm_process_menu_mouse(Gpm_Event * event, void *data)
{
int btn = MOUSE_BTN_RESET, x, y;
if (event->type & GPM_UP)
btn = MOUSE_BTN_UP;
else if (event->type & GPM_DOWN) {
switch (event->buttons) {
case GPM_B_LEFT:
btn = MOUSE_BTN1_DOWN;
break;
case GPM_B_MIDDLE:
btn = MOUSE_BTN2_DOWN;
break;
case GPM_B_RIGHT:
btn = MOUSE_BTN3_DOWN;
break;
}
}
else {
GPM_DRAWPOINTER(event);
return 0;
}
x = event->x;
y = event->y;
X_Mouse_Selection = process_mMouse(btn, x - 1, y - 1);
return X_MOUSE_SELECTED;
}
#endif /* USE_GPM */
#ifdef USE_SYSMOUSE
static int
sysm_process_menu_mouse(int x, int y, int nbs, int obs)
{
int btn;
int bits;
if (obs & ~nbs)
btn = MOUSE_BTN_UP;
else if (nbs & ~obs) {
bits = nbs & ~obs;
btn = bits & 0x1 ? MOUSE_BTN1_DOWN :
(bits & 0x2 ? MOUSE_BTN2_DOWN :
(bits & 0x4 ? MOUSE_BTN3_DOWN : 0));
}
else /* nbs == obs */
return 0;
X_Mouse_Selection = process_mMouse(btn, x, y);
return X_MOUSE_SELECTED;
}
#endif /* USE_SYSMOUSE */
#else /* not USE_MOUSE */
static int
mMouse(char c)
{
return (MENU_NOTHING);
}
#endif /* not USE_MOUSE */
/* --- MenuFunctions (END) --- */
/* --- MainMenu --- */
void
popupMenu(int x, int y, Menu *menu)
{
initSelectMenu();
initSelTabMenu();
menu->cursorX = Currentbuf->cursorX + Currentbuf->rootX;
menu->cursorY = Currentbuf->cursorY + Currentbuf->rootY;
menu->x = x + FRAME_WIDTH + 1;
menu->y = y + 2;
popup_menu(NULL, menu);
}
void
mainMenu(int x, int y)
{
popupMenu(x, y, &MainMenu);
}
void
mainMn(void)
{
Menu *menu = &MainMenu;
char *data;
int n;
int x = Currentbuf->cursorX + Currentbuf->rootX,
y = Currentbuf->cursorY + Currentbuf->rootY;
data = searchKeyData();
if (data != NULL) {
n = getMenuN(w3mMenuList, data);
if (n < 0)
return;
menu = w3mMenuList[n].menu;
}
#ifdef USE_MOUSE
if (mouse_action.in_action) {
x = mouse_action.cursorX;
y = mouse_action.cursorY;
}
#endif
popupMenu(x, y, menu);
}
/* --- MainMenu (END) --- */
/* --- SelectMenu --- */
void
selMn(void)
{
int x = Currentbuf->cursorX + Currentbuf->rootX,
y = Currentbuf->cursorY + Currentbuf->rootY;
#ifdef USE_MOUSE
if (mouse_action.in_action) {
x = mouse_action.cursorX;
y = mouse_action.cursorY;
}
#endif
popupMenu(x, y, &SelectMenu);
}
static void
initSelectMenu(void)
{
int i, nitem, len = 0, l;
Buffer *buf;
Str str;
char **label;
char *p;
static char *comment = " SPC for select / D for delete buffer ";
SelectV = -1;
for (i = 0, buf = Firstbuf; buf != NULL; i++, buf = buf->nextBuffer) {
if (buf == Currentbuf)
SelectV = i;
}
nitem = i;
label = New_N(char *, nitem + 2);
for (i = 0, buf = Firstbuf; i < nitem; i++, buf = buf->nextBuffer) {
str = Sprintf("<%s>", buf->buffername);
if (buf->filename != NULL) {
switch (buf->currentURL.scheme) {
case SCM_LOCAL:
if (strcmp(buf->currentURL.file, "-")) {
Strcat_char(str, ' ');
Strcat_charp(str,
conv_from_system(buf->currentURL.real_file));
}
break;
/* case SCM_UNKNOWN: */
case SCM_MISSING:
break;
default:
Strcat_char(str, ' ');
p = parsedURL2Str(&buf->currentURL)->ptr;
if (DecodeURL)
p = url_unquote_conv(p, 0);
Strcat_charp(str, p);
break;
}
}
label[i] = str->ptr;
if (len < str->length)
len = str->length;
}
l = strlen(comment);
if (len < l + 4)
len = l + 4;
if (len > COLS - 2 * FRAME_WIDTH)
len = COLS - 2 * FRAME_WIDTH;
len = (len > 1) ? ((len - l + 1) / 2) : 0;
str = Strnew();
for (i = 0; i < len; i++)
Strcat_char(str, '-');
Strcat_charp(str, comment);
for (i = 0; i < len; i++)
Strcat_char(str, '-');
label[nitem] = str->ptr;
label[nitem + 1] = NULL;
new_option_menu(&SelectMenu, label, &SelectV, smChBuf);
SelectMenu.initial = SelectV;
SelectMenu.cursorX = Currentbuf->cursorX + Currentbuf->rootX;
SelectMenu.cursorY = Currentbuf->cursorY + Currentbuf->rootY;
SelectMenu.keymap['D'] = smDelBuf;
SelectMenu.item[nitem].type = MENU_NOP;
}
static void
smChBuf(void)
{
int i;
Buffer *buf;
if (SelectV < 0 || SelectV >= SelectMenu.nitem)
return;
for (i = 0, buf = Firstbuf; i < SelectV; i++, buf = buf->nextBuffer) ;
Currentbuf = buf;
for (buf = Firstbuf; buf != NULL; buf = buf->nextBuffer) {
if (buf == Currentbuf)
continue;
#ifdef USE_IMAGE
deleteImage(buf);
#endif
if (clear_buffer)
tmpClearBuffer(buf);
}
}
static int
smDelBuf(char c)
{
int i, x, y, mselect;
Buffer *buf;
if (CurrentMenu->select < 0 || CurrentMenu->select >= SelectMenu.nitem)
return (MENU_NOTHING);
for (i = 0, buf = Firstbuf; i < CurrentMenu->select;
i++, buf = buf->nextBuffer) ;
if (Currentbuf == buf)
Currentbuf = buf->nextBuffer;
Firstbuf = deleteBuffer(Firstbuf, buf);
if (!Currentbuf)
Currentbuf = nthBuffer(Firstbuf, i - 1);;
if (Firstbuf == NULL) {
Firstbuf = nullBuffer();
Currentbuf = Firstbuf;
}
x = CurrentMenu->x;
y = CurrentMenu->y;
mselect = CurrentMenu->select;
initSelectMenu();
CurrentMenu->x = x;
CurrentMenu->y = y;
geom_menu(CurrentMenu, x, y, 0);
CurrentMenu->select = (mselect <= CurrentMenu->nitem - 2) ? mselect
: (CurrentMenu->nitem - 2);
displayBuffer(Currentbuf, B_FORCE_REDRAW);
draw_all_menu(CurrentMenu);
select_menu(CurrentMenu, CurrentMenu->select);
return (MENU_NOTHING);
}
/* --- SelectMenu (END) --- */
/* --- SelTabMenu --- */
void
tabMn(void)
{
int x = Currentbuf->cursorX + Currentbuf->rootX,
y = Currentbuf->cursorY + Currentbuf->rootY;
#ifdef USE_MOUSE
if (mouse_action.in_action) {
x = mouse_action.cursorX;
y = mouse_action.cursorY;
}
#endif
popupMenu(x, y, &SelTabMenu);
}
static void
initSelTabMenu(void)
{
int i, nitem, len = 0, l;
TabBuffer *tab;
Buffer *buf;
Str str;
char **label;
char *p;
static char *comment = " SPC for select / D for delete tab ";
SelTabV = -1;
for (i = 0, tab = LastTab; tab != NULL; i++, tab = tab->prevTab) {
if (tab == CurrentTab)
SelTabV = i;
}
nitem = i;
label = New_N(char *, nitem + 2);
for (i = 0, tab = LastTab; i < nitem; i++, tab = tab->prevTab) {
buf = tab->currentBuffer;
str = Sprintf("<%s>", buf->buffername);
if (buf->filename != NULL) {
switch (buf->currentURL.scheme) {
case SCM_LOCAL:
if (strcmp(buf->currentURL.file, "-")) {
Strcat_char(str, ' ');
Strcat_charp(str,
conv_from_system(buf->currentURL.real_file));
}
break;
/* case SCM_UNKNOWN: */
case SCM_MISSING:
break;
default:
p = parsedURL2Str(&buf->currentURL)->ptr;
if (DecodeURL)
p = url_unquote_conv(p, 0);
Strcat_charp(str, p);
break;
}
}
label[i] = str->ptr;
if (len < str->length)
len = str->length;
}
l = strlen(comment);
if (len < l + 4)
len = l + 4;
if (len > COLS - 2 * FRAME_WIDTH)
len = COLS - 2 * FRAME_WIDTH;
len = (len > 1) ? ((len - l + 1) / 2) : 0;
str = Strnew();
for (i = 0; i < len; i++)
Strcat_char(str, '-');
Strcat_charp(str, comment);
for (i = 0; i < len; i++)
Strcat_char(str, '-');
label[nitem] = str->ptr;
label[nitem + 1] = NULL;
new_option_menu(&SelTabMenu, label, &SelTabV, smChTab);
SelTabMenu.initial = SelTabV;
SelTabMenu.cursorX = Currentbuf->cursorX + Currentbuf->rootX;
SelTabMenu.cursorY = Currentbuf->cursorY + Currentbuf->rootY;
SelTabMenu.keymap['D'] = smDelTab;
SelTabMenu.item[nitem].type = MENU_NOP;
}
static void
smChTab(void)
{
int i;
TabBuffer *tab;
Buffer *buf;
if (SelTabV < 0 || SelTabV >= SelTabMenu.nitem)
return;
for (i = 0, tab = LastTab; i < SelTabV && tab != NULL;
i++, tab = tab->prevTab) ;
CurrentTab = tab;
for (tab = LastTab; tab != NULL; tab = tab->prevTab) {
if (tab == CurrentTab)
continue;
buf = tab->currentBuffer;
#ifdef USE_IMAGE
deleteImage(buf);
#endif
if (clear_buffer)
tmpClearBuffer(buf);
}
}
static int
smDelTab(char c)
{
int i, x, y, mselect;
TabBuffer *tab;
if (CurrentMenu->select < 0 || CurrentMenu->select >= SelTabMenu.nitem)
return (MENU_NOTHING);
for (i = 0, tab = LastTab; i < CurrentMenu->select && tab != NULL;
i++, tab = tab->prevTab) ;
deleteTab(tab);
x = CurrentMenu->x;
y = CurrentMenu->y;
mselect = CurrentMenu->select;
initSelTabMenu();
CurrentMenu->x = x;
CurrentMenu->y = y;
geom_menu(CurrentMenu, x, y, 0);
CurrentMenu->select = (mselect <= CurrentMenu->nitem - 2) ? mselect
: (CurrentMenu->nitem - 2);
displayBuffer(Currentbuf, B_FORCE_REDRAW);
draw_all_menu(CurrentMenu);
select_menu(CurrentMenu, CurrentMenu->select);
return (MENU_NOTHING);
}
/* --- SelectMenu (END) --- */
/* --- OptionMenu --- */
void
optionMenu(int x, int y, char **label, int *variable, int initial,
void (*func) ())
{
Menu menu;
new_option_menu(&menu, label, variable, func);
menu.cursorX = COLS - 1;
menu.cursorY = LASTLINE;
menu.x = x;
menu.y = y;
menu.initial = initial;
popup_menu(NULL, &menu);
}
/* --- OptionMenu (END) --- */
/* --- InitMenu --- */
void
initMenu(void)
{
FILE *mf;
Str line;
char *p, *s;
int in_menu, nmenu = 0, nitem = 0, type;
MenuItem *item = NULL;
MenuList *list;
w3mMenuList = New_N(MenuList, 3);
w3mMenuList[0].id = "Main";
w3mMenuList[0].menu = &MainMenu;
w3mMenuList[0].item = MainMenuItem;
w3mMenuList[1].id = "Select";
w3mMenuList[1].menu = &SelectMenu;
w3mMenuList[1].item = NULL;
w3mMenuList[2].id = "SelectTab";
w3mMenuList[2].menu = &SelTabMenu;
w3mMenuList[2].item = NULL;
w3mMenuList[3].id = NULL;
if ((mf = fopen(rcFile(MENU_FILE), "rt")) == NULL)
goto create_menu;
in_menu = 0;
while (!feof(mf)) {
line = Strfgets(mf);
Strchop(line);
Strremovefirstspaces(line);
if (line->length == 0)
continue;
p = line->ptr;
s = getWord(&p);
if (*s == '#') /* comment */
continue;
if (in_menu) {
type = setMenuItem(&item[nitem], s, p);
if (type == -1)
continue; /* error */
if (type == MENU_END)
in_menu = 0;
else {
nitem++;
item = New_Reuse(MenuItem, item, (nitem + 1));
w3mMenuList[nmenu].item = item;
item[nitem].type = MENU_END;
}
}
else {
if (strcmp(s, "menu")) /* error */
continue;
s = getQWord(&p);
if (*s == '\0') /* error */
continue;
in_menu = 1;
if ((nmenu = getMenuN(w3mMenuList, s)) != -1)
w3mMenuList[nmenu].item = New(MenuItem);
else
nmenu = addMenuList(&w3mMenuList, s);
item = w3mMenuList[nmenu].item;
nitem = 0;
item[nitem].type = MENU_END;
}
}
fclose(mf);
create_menu:
for (list = w3mMenuList; list->id != NULL; list++) {
if (list->item == NULL)
continue;
new_menu(list->menu, list->item);
}
}
int
setMenuItem(MenuItem *item, char *type, char *line)
{
char *label, *func, *popup, *keys, *data;
int f;
int n;
if (type == NULL || *type == '\0') /* error */
return -1;
if (strcmp(type, "end") == 0) {
item->type = MENU_END;
return MENU_END;
}
else if (strcmp(type, "nop") == 0) {
item->type = MENU_NOP;
item->label = getQWord(&line);
return MENU_NOP;
}
else if (strcmp(type, "func") == 0) {
label = getQWord(&line);
func = getWord(&line);
keys = getQWord(&line);
data = getQWord(&line);
if (*func == '\0') /* error */
return -1;
item->type = MENU_FUNC;
item->label = label;
f = getFuncList(func);
item->func = w3mFuncList[(f >= 0) ? f : FUNCNAME_nulcmd].func;
item->keys = keys;
item->data = data;
return MENU_FUNC;
}
else if (strcmp(type, "popup") == 0) {
label = getQWord(&line);
popup = getQWord(&line);
keys = getQWord(&line);
if (*popup == '\0') /* error */
return -1;
item->type = MENU_POPUP;
item->label = label;
if ((n = getMenuN(w3mMenuList, popup)) == -1)
n = addMenuList(&w3mMenuList, popup);
item->popup = w3mMenuList[n].menu;
item->keys = keys;
return MENU_POPUP;
}
return -1; /* error */
}
int
addMenuList(MenuList **mlist, char *id)
{
int n;
MenuList *list = *mlist;
for (n = 0; list->id != NULL; list++, n++) ;
*mlist = New_Reuse(MenuList, *mlist, (n + 2));
list = *mlist + n;
list->id = id;
list->menu = New(Menu);
list->item = New(MenuItem);
(list + 1)->id = NULL;
return n;
}
int
getMenuN(MenuList *list, char *id)
{
int n;
for (n = 0; list->id != NULL; list++, n++) {
if (strcmp(id, list->id) == 0)
return n;
}
return -1;
}
/* --- InitMenu (END) --- */
LinkList *
link_menu(Buffer *buf)
{
Menu menu;
LinkList *l;
int i, nitem, len = 0, linkV = -1;
char **label;
Str str;
char *p;
if (!buf->linklist)
return NULL;
for (i = 0, l = buf->linklist; l; i++, l = l->next) ;
nitem = i;
label = New_N(char *, nitem + 1);
for (i = 0, l = buf->linklist; l; i++, l = l->next) {
str = Strnew_charp(l->title ? l->title : "(empty)");
if (l->type == LINK_TYPE_REL)
Strcat_charp(str, " [Rel] ");
else if (l->type == LINK_TYPE_REV)
Strcat_charp(str, " [Rev] ");
else
Strcat_charp(str, " ");
if (!l->url)
p = "";
else if (DecodeURL)
p = url_unquote_conv(l->url, buf->document_code);
else
p = l->url;
Strcat_charp(str, p);
label[i] = str->ptr;
if (len < str->length)
len = str->length;
}
label[nitem] = NULL;
new_option_menu(&menu, label, &linkV, NULL);
menu.initial = 0;
menu.cursorX = buf->cursorX + buf->rootX;
menu.cursorY = buf->cursorY + buf->rootY;
menu.x = menu.cursorX + FRAME_WIDTH + 1;
menu.y = menu.cursorY + 2;
popup_menu(NULL, &menu);
if (linkV < 0)
return NULL;
for (i = 0, l = buf->linklist; l; i++, l = l->next) {
if (i == linkV)
return l;
}
return NULL;
}
/* --- LinkMenu (END) --- */
Anchor *
accesskey_menu(Buffer *buf)
{
Menu menu;
AnchorList *al = buf->href;
Anchor *a;
Anchor **ap;
int i, n, nitem = 0, key = -1;
char **label;
char *t;
unsigned char c;
if (!al)
return NULL;
for (i = 0; i < al->nanchor; i++) {
a = &al->anchors[i];
if (!a->slave && a->accesskey && IS_ASCII(a->accesskey))
nitem++;
}
if (!nitem)
return NULL;
label = New_N(char *, nitem + 1);
ap = New_N(Anchor *, nitem);
for (i = 0, n = 0; i < al->nanchor; i++) {
a = &al->anchors[i];
if (!a->slave && a->accesskey && IS_ASCII(a->accesskey)) {
t = getAnchorText(buf, al, a);
label[n] = Sprintf("%c: %s", a->accesskey, t ? t : "")->ptr;
ap[n] = a;
n++;
}
}
label[nitem] = NULL;
new_option_menu(&menu, label, &key, NULL);
menu.initial = 0;
menu.cursorX = buf->cursorX + buf->rootX;
menu.cursorY = buf->cursorY + buf->rootY;
menu.x = menu.cursorX + FRAME_WIDTH + 1;
menu.y = menu.cursorY + 2;
for (i = 0; i < 128; i++)
menu.keyselect[i] = -1;
for (i = 0; i < nitem; i++) {
c = ap[i]->accesskey;
menu.keymap[(int)c] = mSelect;
menu.keyselect[(int)c] = i;
}
for (i = 0; i < nitem; i++) {
c = ap[i]->accesskey;
if (!IS_ALPHA(c) || menu.keyselect[n] >= 0)
continue;
c = TOLOWER(c);
menu.keymap[(int)c] = mSelect;
menu.keyselect[(int)c] = i;
c = TOUPPER(c);
menu.keymap[(int)c] = mSelect;
menu.keyselect[(int)c] = i;
}
a = retrieveCurrentAnchor(buf);
if (a && a->accesskey && IS_ASCII(a->accesskey)) {
for (i = 0; i < nitem; i++) {
if (a->hseq == ap[i]->hseq) {
menu.initial = i;
break;
}
}
}
popup_menu(NULL, &menu);
return (key >= 0) ? ap[key] : NULL;
}
static char lmKeys[] = "abcdefgimopqrstuvwxyz";
static char lmKeys2[] = "1234567890ABCDEFGHILMOPQRSTUVWXYZ";
#define nlmKeys (sizeof(lmKeys) - 1)
#define nlmKeys2 (sizeof(lmKeys2) - 1)
static int
lmGoto(char c)
{
if (IS_ASCII(c) && CurrentMenu->keyselect[(int)c] >= 0) {
goto_menu(CurrentMenu, CurrentMenu->nitem - 1, -1);
goto_menu(CurrentMenu, CurrentMenu->keyselect[(int)c] * nlmKeys, 1);
}
return (MENU_NOTHING);
}
static int
lmSelect(char c)
{
if (IS_ASCII(c))
return select_menu(CurrentMenu, (CurrentMenu->select / nlmKeys) *
nlmKeys + CurrentMenu->keyselect[(int)c]);
else
return (MENU_NOTHING);
}
Anchor *
list_menu(Buffer *buf)
{
Menu menu;
AnchorList *al = buf->href;
Anchor *a;
Anchor **ap;
int i, n, nitem = 0, key = -1, two = FALSE;
char **label;
char *t;
unsigned char c;
if (!al)
return NULL;
for (i = 0; i < al->nanchor; i++) {
a = &al->anchors[i];
if (!a->slave)
nitem++;
}
if (!nitem)
return NULL;
if (nitem >= nlmKeys)
two = TRUE;
label = New_N(char *, nitem + 1);
ap = New_N(Anchor *, nitem);
for (i = 0, n = 0; i < al->nanchor; i++) {
a = &al->anchors[i];
if (!a->slave) {
t = getAnchorText(buf, al, a);
if (!t)
t = "";
if (two && n >= nlmKeys2 * nlmKeys)
label[n] = Sprintf(" : %s", t)->ptr;
else if (two)
label[n] = Sprintf("%c%c: %s", lmKeys2[n / nlmKeys],
lmKeys[n % nlmKeys], t)->ptr;
else
label[n] = Sprintf("%c: %s", lmKeys[n], t)->ptr;
ap[n] = a;
n++;
}
}
label[nitem] = NULL;
new_option_menu(&menu, label, &key, NULL);
menu.initial = 0;
menu.cursorX = buf->cursorX + buf->rootX;
menu.cursorY = buf->cursorY + buf->rootY;
menu.x = menu.cursorX + FRAME_WIDTH + 1;
menu.y = menu.cursorY + 2;
for (i = 0; i < 128; i++)
menu.keyselect[i] = -1;
if (two) {
for (i = 0; i < nlmKeys2; i++) {
c = lmKeys2[i];
menu.keymap[(int)c] = lmGoto;
menu.keyselect[(int)c] = i;
}
for (i = 0; i < nlmKeys; i++) {
c = lmKeys[i];
menu.keymap[(int)c] = lmSelect;
menu.keyselect[(int)c] = i;
}
}
else {
for (i = 0; i < nitem; i++) {
c = lmKeys[i];
menu.keymap[(int)c] = mSelect;
menu.keyselect[(int)c] = i;
}
}
a = retrieveCurrentAnchor(buf);
if (a) {
for (i = 0; i < nitem; i++) {
if (a->hseq == ap[i]->hseq) {
menu.initial = i;
break;
}
}
}
popup_menu(NULL, &menu);
return (key >= 0) ? ap[key] : NULL;
}
#endif /* USE_MENU */