Files
w3m/menu.c
Fumitoshi UKAI b411c1109d fix indent
2003-09-24 18:48:58 +00:00

2123 lines
53 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.38 2003/09/24 18:49: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
static char **FRAME;
static int FRAME_WIDTH;
static int graph_mode = FALSE;
#define G_start {if (graph_mode) graphstart();}
#define G_end {if (graph_mode) graphend();}
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 wc_ces MainMenuCharset = WC_CES_EUC_JP; /* charset of source code */
static int MainMenuEncode = FALSE;
static MenuItem MainMenuItem[] = {
/* type label variabel value func popup keys data */
{MENU_FUNC, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> (b)", NULL, 0, backBf, NULL, "b", NULL},
{MENU_POPUP, "<EFBFBD>Хåե<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (s)", NULL, 0, NULL, &SelectMenu, "s", NULL},
{MENU_POPUP, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (t)", NULL, 0, NULL, &SelTabMenu, "tT", NULL},
{MENU_FUNC, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɽ<EFBFBD><EFBFBD> (v)", NULL, 0, vwSrc, NULL, "vV", NULL},
{MENU_FUNC, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD> (e)", NULL, 0, editBf, NULL, "eE", NULL},
{MENU_FUNC, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¸ (S)", NULL, 0, svSrc, NULL, "S", NULL},
{MENU_FUNC, "<EFBFBD><EFBFBD><EFBFBD>ɤ߹<EFBFBD><EFBFBD><EFBFBD> (r)", NULL, 0, reload, NULL, "rR", NULL},
{MENU_NOP, "----------------", NULL, 0, nulcmd, NULL, "", NULL},
{MENU_FUNC, "<EFBFBD><EFBFBD><EFBFBD>󥯤<EFBFBD>ɽ<EFBFBD><EFBFBD> (a)", NULL, 0, followA, NULL, "a", NULL},
{MENU_FUNC, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD>ɽ<EFBFBD><EFBFBD> (n)", NULL, 0, tabA, NULL, "nN", NULL},
{MENU_FUNC, "<EFBFBD><EFBFBD><EFBFBD>󥯤<EFBFBD><EFBFBD><EFBFBD>¸ (A)", NULL, 0, svA, NULL, "A", NULL},
{MENU_FUNC, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɽ<EFBFBD><EFBFBD> (i)", NULL, 0, followI, NULL, "i", NULL},
{MENU_FUNC, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¸ (I)", NULL, 0, svI, NULL, "I", NULL},
{MENU_FUNC, "<EFBFBD>ե졼<EFBFBD><EFBFBD>ɽ<EFBFBD><EFBFBD> (f)", NULL, 0, rFrame, NULL, "fF", NULL},
{MENU_NOP, "----------------", NULL, 0, nulcmd, NULL, "", NULL},
{MENU_FUNC, "<EFBFBD>֥å<EFBFBD><EFBFBD>ޡ<EFBFBD><EFBFBD><EFBFBD> (B)", NULL, 0, ldBmark, NULL, "B", NULL},
{MENU_FUNC, "<EFBFBD>إ<EFBFBD><EFBFBD><EFBFBD> (h)", NULL, 0, ldhelp, NULL, "hH", NULL},
{MENU_FUNC, "<EFBFBD><EFBFBD><EFBFBD>ץ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (o)", NULL, 0, ldOpt, NULL, "oO", NULL},
{MENU_NOP, "----------------", NULL, 0, nulcmd, NULL, "", NULL},
{MENU_FUNC, "<EFBFBD><EFBFBD>λ (q)", NULL, 0, qquitfm, NULL, "qQ", NULL},
{MENU_END, "", NULL, 0, nulcmd, NULL, "", NULL},
};
#else /* LANG != JA */
#ifdef USE_M17N
/* FIXME: gettextize here */
static wc_ces MainMenuCharset = WC_CES_US_ASCII;
#if ENABLE_NLS
static int MainMenuEncode = FALSE;
#else
static int MainMenuEncode = TRUE;
#endif
#endif
static MenuItem MainMenuItem[] = {
/* type label variable value func popup keys data */
{MENU_FUNC, N_(" Back (b) "), NULL, 0, backBf, NULL, "b", NULL},
{MENU_POPUP, N_(" Select Buffer(s) "), NULL, 0, NULL, &SelectMenu, "s",
NULL},
{MENU_POPUP, N_(" Select Tab (t) "), NULL, 0, NULL, &SelTabMenu, "tT",
NULL},
{MENU_FUNC, N_(" View Source (v) "), NULL, 0, vwSrc, NULL, "vV", NULL},
{MENU_FUNC, N_(" Edit Source (e) "), NULL, 0, editBf, NULL, "eE", NULL},
{MENU_FUNC, N_(" Save Source (S) "), NULL, 0, svSrc, NULL, "S", NULL},
{MENU_FUNC, N_(" Reload (r) "), NULL, 0, reload, NULL, "rR", NULL},
{MENU_NOP, N_(" ---------------- "), NULL, 0, nulcmd, NULL, "", NULL},
{MENU_FUNC, N_(" Go Link (a) "), NULL, 0, followA, NULL, "a", NULL},
{MENU_FUNC, N_(" on New Tab (n) "), NULL, 0, tabA, NULL, "nN", NULL},
{MENU_FUNC, N_(" Save Link (A) "), NULL, 0, svA, NULL, "A", NULL},
{MENU_FUNC, N_(" View Image (i) "), NULL, 0, followI, NULL, "i", NULL},
{MENU_FUNC, N_(" Save Image (I) "), NULL, 0, svI, NULL, "I", NULL},
{MENU_FUNC, N_(" View Frame (f) "), NULL, 0, rFrame, NULL, "fF", NULL},
{MENU_NOP, N_(" ---------------- "), NULL, 0, nulcmd, NULL, "", NULL},
{MENU_FUNC, N_(" Bookmark (B) "), NULL, 0, ldBmark, NULL, "B", NULL},
{MENU_FUNC, N_(" Help (h) "), NULL, 0, ldhelp, NULL, "hH", NULL},
{MENU_FUNC, N_(" Option (o) "), NULL, 0, ldOpt, NULL, "oO", NULL},
{MENU_NOP, N_(" ---------------- "), NULL, 0, nulcmd, NULL, "", NULL},
{MENU_FUNC, N_(" 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 = get_strwidth(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;
if (menu->offset == 0) {
G_start;
mvaddstr(y, x, FRAME[3]);
for (i = FRAME_WIDTH; i < w - FRAME_WIDTH; i += FRAME_WIDTH)
mvaddstr(y, x + i, FRAME[10]);
mvaddstr(y, x + i, FRAME[6]);
G_end;
}
else {
G_start;
mvaddstr(y, x, FRAME[5]);
G_end;
for (i = FRAME_WIDTH; i < w - FRAME_WIDTH; i++)
mvaddstr(y, x + i, " ");
G_start;
mvaddstr(y, x + i, FRAME[5]);
G_end;
i = (w / 2 - 1) / FRAME_WIDTH * FRAME_WIDTH;
mvaddstr(y, x + i, ":");
}
for (j = 0; j < menu->height; j++) {
y++;
G_start;
mvaddstr(y, x, FRAME[5]);
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[9]);
for (i = FRAME_WIDTH; i < w - FRAME_WIDTH; i += FRAME_WIDTH)
mvaddstr(y, x + i, FRAME[10]);
mvaddstr(y, x + i, FRAME[12]);
G_end;
}
else {
G_start;
mvaddstr(y, x, FRAME[5]);
G_end;
for (i = FRAME_WIDTH; i < w - FRAME_WIDTH; i++)
mvaddstr(y, x + i, " ");
G_start;
mvaddstr(y, x + i, FRAME[5]);
G_end;
i = (w / 2 - 1) / FRAME_WIDTH * FRAME_WIDTH;
mvaddstr(y, x + i, ":");
}
}
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);
}
static void
set_menu_frame(void)
{
if (graph_ok()) {
graph_mode = TRUE;
FRAME_WIDTH = 1;
FRAME = graph_symbol;
}
else {
graph_mode = FALSE;
#ifdef USE_M17N
FRAME_WIDTH = 0;
FRAME = get_symbol(DisplayCharset, &FRAME_WIDTH);
if (!WcOption.use_wide)
FRAME_WIDTH = 1;
#else
FRAME_WIDTH = 1;
FRAME = get_symbol();
#endif
}
}
/* --- 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;
#ifdef USE_M17N
if (SearchConv && !WcOption.pre_conv &&
Currentbuf->document_charset != DisplayCharset)
str = wtf_conv_fit(str, Currentbuf->document_charset);
#endif
menuSearchRoutine = menuForwardSearch;
found = menuForwardSearch(menu, str, from + 1);
if (WrapSearch && found == -1)
found = menuForwardSearch(menu, str, 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 -1;
SearchString = str;
#ifdef USE_M17N
if (SearchConv && !WcOption.pre_conv &&
Currentbuf->document_charset != DisplayCharset)
str = wtf_conv_fit(str, Currentbuf->document_charset);
#endif
menuSearchRoutine = menuBackwardSearch;
found = menuBackwardSearch(menu, str, from - 1);
if (WrapSearch && found == -1)
found = menuBackwardSearch(menu, str, 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};
char *str;
if (menuSearchRoutine == NULL) {
disp_message("No previous regular expression", TRUE);
return -1;
}
#ifdef USE_M17N
str = SearchString;
if (SearchConv && !WcOption.pre_conv &&
Currentbuf->document_charset != DisplayCharset)
str = wtf_conv_fit(str, Currentbuf->document_charset);
#endif
if (reverse != 0)
reverse = 1;
if (menuSearchRoutine == menuBackwardSearch)
reverse ^= 1;
from += reverse ? -1 : 1;
found = (*routine[reverse]) (menu, str, from);
if (WrapSearch && found == -1)
found = (*routine[reverse]) (menu, str, 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)
{
set_menu_frame();
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 = get_strwidth(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;
set_menu_frame();
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 --- */
static void
interpret_menu(FILE * mf)
{
Str line;
char *p, *s;
int in_menu = 0, nmenu = 0, nitem = 0, type;
MenuItem *item = NULL;
#ifdef USE_M17N
wc_ces charset = SystemCharset;
#endif
while (!feof(mf)) {
line = Strfgets(mf);
Strchop(line);
Strremovefirstspaces(line);
if (line->length == 0)
continue;
#ifdef USE_M17N
line = wc_Str_conv(line, charset, InnerCharset);
#endif
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")) {
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;
}
#ifdef USE_M17N
else if (!strcmp(s, "charset") || !strcmp(s, "encoding")) {
s = getQWord(&p);
if (*s == '\0') /* error */
continue;
charset = wc_guess_charset(s, charset);
}
#endif
}
}
void
initMenu(void)
{
FILE *mf;
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;
#ifdef USE_M17N
if (!MainMenuEncode) {
MenuItem *item;
#if ENABLE_NLS
/* FIXME: charset that gettext(3) returns */
MainMenuCharset = SystemCharset;
#endif
for (item = MainMenuItem; item->type != MENU_END; item++)
item->label =
wc_conv(gettext(item->label), MainMenuCharset,
InnerCharset)->ptr;
MainMenuEncode = TRUE;
}
#endif
if ((mf = fopen(confFile(MENU_FILE), "rt")) != NULL) {
interpret_menu(mf);
fclose(mf);
}
if ((mf = fopen(rcFile(MENU_FILE), "rt")) != NULL) {
interpret_menu(mf);
fclose(mf);
}
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_charset);
else
p = l->url;
Strcat_charp(str, p);
label[i] = str->ptr;
if (len < str->length)
len = str->length;
}
label[nitem] = NULL;
set_menu_frame();
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;
set_menu_frame();
set_menu_frame();
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 */