/* $Id: main.c,v 1.1.1.1 2001/11/08 05:15:13 a-ito Exp $ */
#define MAINPROGRAM
#include "fm.h"
#include <signal.h>
#include <setjmp.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include "terms.h"
#include "myctype.h"
#ifdef MOUSE
#ifdef USE_GPM
#include <gpm.h>
#endif /* USE_GPM */
#if defined(USE_GPM) || defined(USE_SYSMOUSE)
extern int do_getch();
#define getch() do_getch()
#endif /* defined(USE_GPM) || *
* defined(USE_SYSMOUSE) */
#endif
#define DSTR_LEN 256
Hist *LoadHist;
Hist *SaveHist;
Hist *URLHist;
Hist *ShellHist;
Hist *TextHist;
#define N_EVENT_QUEUE 10
typedef struct {
int cmd;
void *user_data;
} Event;
static Event eventQueue[N_EVENT_QUEUE];
static int n_event_queue;
#ifdef USE_MARK
static char *MarkString = NULL;
#endif
static char *SearchString = NULL;
int (*searchRoutine) (Buffer *, char *);
JMP_BUF IntReturn;
static void cmd_loadfile(char *path);
static void cmd_loadURL(char *url, ParsedURL * current);
static void cmd_loadBuffer(Buffer * buf, int prop, int link);
static void keyPressEventProc(int c);
#ifdef USE_MARK
static void cmd_mark(Lineprop * p);
#endif /* USE_MARK */
#ifdef SHOW_PARAMS
int show_params_p = 0;
void show_params(FILE * fp);
#endif
static int display_ok = FALSE;
int w3m_dump = 0;
int w3m_dump_source = 0;
int w3m_dump_head = 0;
static void dump_source(Buffer *);
static void dump_head(Buffer *);
int prec_num = 0;
int prev_key = -1;
int on_target = 1;
static void _goLine(char*);
#define PREC_NUM (prec_num ? prec_num : 1)
#define PREC_LIMIT 10000
#if 0
static int searchKeyNum(void);
#endif
#include "gcmain.c"
#define help() fusage(stdout, 0)
#define usage() fusage(stderr, 1)
static void
fusage(FILE *f, int err)
{
fprintf(f, "version %s\n", version);
fprintf(f, "usage: w3m [options] [URL or filename]\noptions:\n");
fprintf(f, " -t tab set tab width\n");
fprintf(f, " -r ignore backspace effect\n");
fprintf(f, " -l line # of preserved line (default 10000)\n");
#ifdef JP_CHARSET
#ifndef DEBIAN /* disabled by ukai: -s is used for squeeze multi lines */
fprintf(f, " -e EUC-JP\n");
fprintf(f, " -s Shift_JIS\n");
fprintf(f, " -j JIS\n");
#endif
fprintf(f, " -I e|s document code\n");
#endif /* JP_CHARSET */
fprintf(f, " -B load bookmark\n");
fprintf(f, " -bookmark file specify bookmark file\n");
fprintf(f, " -T type specify content-type\n");
fprintf(f, " -m internet message mode\n");
fprintf(f, " -v visual startup mode\n");
#ifdef COLOR
fprintf(f, " -M monochrome display\n");
#endif /* COLOR */
fprintf(f, " -F automatically render frame\n");
fprintf(f, " -dump dump formatted page into stdout\n");
fprintf(f, " -cols width specify column width (used with -dump)\n");
fprintf(f, " -ppc count specify the number of pixels per character (4.0...32.0)\n");
fprintf(f, " -dump_source dump page source into stdout\n");
fprintf(f, " -dump_head dump response of HEAD request into stdout\n");
fprintf(f, " +<num> goto <num> line\n");
fprintf(f, " -num show line number\n");
fprintf(f, " -no-proxy don't use proxy\n");
#ifdef MOUSE
fprintf(f, " -no-mouse don't use mouse\n");
#endif /* MOUSE */
#ifdef USE_COOKIE
fprintf(f, " -cookie use cookie (-no-cookie: don't use cookie)\n");
fprintf(f, " -pauth user:pass proxy authentication\n");
#endif /* USE_COOKIE */
#ifndef KANJI_SYMBOLS
fprintf(f, " -no-graph don't use graphic character\n");
#endif /* not KANJI_SYMBOLS */
#ifdef DEBIAN /* replaced by ukai: pager requires -s */
fprintf(f, " -s squeeze multiple blank lines\n");
#else
fprintf(f, " -S squeeze multiple blank lines\n");
#endif
fprintf(f, " -W toggle wrap search mode\n");
fprintf(f, " -X don't use termcap init/deinit\n");
fprintf(f, " -o opt=value assign value to config option\n");
fprintf(f, " -config file specify config file\n");
fprintf(f, " -debug DO NOT USE\n");
#ifdef SHOW_PARAMS
if (show_params_p)
show_params(f);
#endif
exit(err);
}
static int option_assigned = 0;
extern void parse_proxy(void);
static GC_warn_proc orig_GC_warn_proc = NULL;
#define GC_WARN_KEEP_MAX (20)
static void
wrap_GC_warn_proc(char *msg, GC_word arg)
{
if (fmInitialized) {
static struct {
char *msg;
GC_word arg;
} msg_ring[GC_WARN_KEEP_MAX] = {
{NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0},
{NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0},
{NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0},
{NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0},
};
static int i = 0;
static int n = 0;
static int lock = 0;
int j;
j = (i + n) % (sizeof(msg_ring) / sizeof(msg_ring[0]));
msg_ring[j].msg = msg;
msg_ring[j].arg = arg;
if (n < sizeof(msg_ring) / sizeof(msg_ring[0]))
++n;
else
++i;
if (!lock) {
lock = 1;
for (; n > 0 ; --n, ++i) {
i %= sizeof(msg_ring) / sizeof(msg_ring[0]);
disp_message_nsec(Sprintf(msg_ring[i].msg, (unsigned long)msg_ring[i].arg)->ptr, FALSE, 1, TRUE, FALSE);
}
lock = 0;
}
}
else if (orig_GC_warn_proc)
orig_GC_warn_proc(msg, arg);
else
fprintf(stderr, msg, (unsigned long)arg);
}
int
MAIN(int argc, char **argv, char **envp)
{
Buffer *newbuf = NULL;
char *p, c;
int i;
InputStream redin;
char *line_str = NULL;
char **load_argv;
FormList *request;
int load_argc = 0;
int load_bookmark = FALSE;
int visual_start = FALSE;
#ifndef SYS_ERRLIST
prepare_sys_errlist();
#endif /* not SYS_ERRLIST */
srand48(time(0));
NO_proxy_domains = newTextList();
fileToDelete = newTextList();
load_argv = New_N(char *, argc - 1);
load_argc = 0;
CurrentDir = currentdir();
BookmarkFile = NULL;
rc_dir = expandName(RC_DIR);
i = strlen(rc_dir);
if (i > 1 && rc_dir[i - 1] == '/')
rc_dir[i - 1] = '\0';
config_file = rcFile(CONFIG_FILE);
create_option_search_table();
/* argument search 1 */
for (i = 1; i < argc; i++) {
if (*argv[i] == '-') {
if (!strcmp("-config", argv[i])) {
argv[i] = "-dummy";
if (++i >= argc)
usage();
config_file = argv[i];
argv[i] = "-dummy";
}
else if (!strcmp("-h", argv[i]))
help();
}
}
/* initializations */
init_rc(config_file);
initKeymap();
#ifdef MENU
initMenu();
CurrentMenuData = NULL;
#endif /* MENU */
#ifdef USE_COOKIE
initCookie();
#endif /* USE_COOKIE */
setLocalCookie(); /* setup cookie for local CGI */
LoadHist = newHist();
SaveHist = newHist();
ShellHist = newHist();
TextHist = newHist();
URLHist = newHist();
#ifdef USE_HISTORY
loadHistory(URLHist);
#endif /* not USE_HISTORY */
if (!non_null(HTTP_proxy) &&
((p = getenv("HTTP_PROXY")) ||
(p = getenv("http_proxy")) ||
(p = getenv("HTTP_proxy")))) {
HTTP_proxy = p;
parseURL(p, &HTTP_proxy_parsed, NULL);
}
#ifdef USE_GOPHER
if (!non_null(GOPHER_proxy) &&
((p = getenv("GOPHER_PROXY")) ||
(p = getenv("gopher_proxy")) ||
(p = getenv("GOPHER_proxy")))) {
GOPHER_proxy = p;
parseURL(p, &GOPHER_proxy_parsed, NULL);
}
#endif /* USE_GOPHER */
if (!non_null(FTP_proxy) &&
((p = getenv("FTP_PROXY")) ||
(p = getenv("ftp_proxy")) ||
(p = getenv("FTP_proxy")))) {
FTP_proxy = p;
parseURL(p, &FTP_proxy_parsed, NULL);
}
if (!non_null(NO_proxy) &&
((p = getenv("NO_PROXY")) ||
(p = getenv("no_proxy")) ||
(p = getenv("NO_proxy")))) {
NO_proxy = p;
set_no_proxy(p);
}
if (Editor == NULL && (p = getenv("EDITOR")) != NULL)
Editor = p;
if (Mailer == NULL && (p = getenv("MAILER")) != NULL)
Mailer = p;
/* argument search 2 */
i = 1;
while (i < argc) {
if (*argv[i] == '-') {
if (!strcmp("-t", argv[i])) {
if (++i >= argc)
usage();
if (atoi(argv[i]) != 0)
Tabstop = atoi(argv[i]);
}
else if (!strcmp("-r", argv[i]))
ShowEffect = FALSE;
else if (!strcmp("-l", argv[i])) {
if (++i >= argc)
usage();
PagerMax = atoi(argv[i]);
}
#ifdef JP_CHARSET
#ifndef DEBIAN /* XXX: use -o kanjicode={S|J|E} */
else if (!strcmp("-s", argv[i]))
DisplayCode = CODE_SJIS;
else if (!strcmp("-j", argv[i]))
DisplayCode = CODE_JIS_n;
else if (!strcmp("-e", argv[i]))
DisplayCode = CODE_EUC;
#endif
else if (!strcmp("-I", argv[i])) {
if (++i >= argc)
usage();
DocumentCode = str_to_code(argv[i]);
}
#endif /* JP_CHARSET */
#ifndef KANJI_SYMBOLS
else if (!strcmp("-no-graph", argv[i]))
no_graphic_char = TRUE;
#endif /* not KANJI_SYMBOLS */
else if (!strcmp("-T", argv[i])) {
if (++i >= argc)
usage();
DefaultType = argv[i];
}
else if (!strcmp("-m", argv[i]))
SearchHeader = TRUE;
else if (!strcmp("-v", argv[i]))
visual_start = TRUE;
#ifdef COLOR
else if (!strcmp("-M", argv[i]))
useColor = FALSE;
#endif /* COLOR */
else if (!strcmp("-B", argv[i]))
load_bookmark = TRUE;
else if (!strcmp("-bookmark", argv[i])) {
if (++i >= argc)
usage();
BookmarkFile = argv[i];
if (BookmarkFile[0] != '~' && BookmarkFile[0] != '/') {
Str tmp = Strnew_charp(CurrentDir);
if (Strlastchar(tmp) != '/')
Strcat_char(tmp, '/');
Strcat_charp(tmp, BookmarkFile);
BookmarkFile = cleanupName(tmp->ptr);
}
}
else if (!strcmp("-F", argv[i]))
RenderFrame = TRUE;
else if (!strcmp("-W", argv[i])) {
if (WrapSearch) {
WrapSearch = FALSE;
}
else {
WrapSearch = TRUE;
}
}
else if (!strcmp("-dump", argv[i])) {
w3m_dump = TRUE;
w3m_dump_source = FALSE;
w3m_dump_head = FALSE;
w3m_halfdump = FALSE;
if (COLS == 0)
COLS = 80;
}
else if (!strcmp("-dump_source", argv[i])) {
w3m_dump = TRUE;
w3m_dump_source = TRUE;
w3m_dump_head = FALSE;
w3m_halfdump = FALSE;
if (COLS == 0)
COLS = 80;
}
else if (!strcmp("-dump_head", argv[i])) {
w3m_dump = TRUE;
w3m_dump_head = TRUE;
w3m_dump_source = FALSE;
w3m_halfdump = FALSE;
if (COLS == 0)
COLS = 80;
}
else if (!strcmp("-halfdump", argv[i])) {
w3m_halfdump = TRUE;
w3m_dump = FALSE;
if (COLS == 0)
COLS = 80;
}
else if (!strcmp("-halfload", argv[i])) {
w3m_halfload = TRUE;
w3m_dump = FALSE;
w3m_halfdump = FALSE;
}
else if (!strcmp("-backend", argv[i])) {
w3m_backend = TRUE;
}
else if (!strcmp("-backend_batch", argv[i])) {
w3m_backend = TRUE;
if (++i >= argc)
usage();
if (!backend_batch_commands)
backend_batch_commands = newTextList();
pushText(backend_batch_commands, argv[i]);
}
else if (!strcmp("-cols", argv[i])) {
if (++i >= argc)
usage();
COLS = atoi(argv[i]);
}
else if (!strcmp("-ppc", argv[i])) {
double ppc;
if (++i >= argc)
usage();
ppc = atof(argv[i]);
if (ppc >= MINIMUM_PIXEL_PER_CHAR &&
ppc <= MAXIMUM_PIXEL_PER_CHAR)
pixel_per_char = ppc;
}
else if (!strcmp("-num", argv[i]))
showLineNum = TRUE;
else if (!strcmp("-no-proxy", argv[i]))
Do_not_use_proxy = TRUE;
#ifdef MOUSE
else if (!strcmp("-no-mouse", argv[i])) {
mouse_end();
use_mouse = FALSE;
}
#endif /* MOUSE */
#ifdef USE_COOKIE
else if (!strcmp("-no-cookie", argv[i])) {
use_cookie = FALSE;
}
else if (!strcmp("-cookie", argv[i])) {
use_cookie = TRUE;
}
else if (!strcmp("-pauth", argv[i])) {
if (++i >= argc)
usage();
proxy_auth_cookie = encodeB(argv[i]);
while (argv[i][0]) {
argv[i][0] = '\0';
argv[i]++;
}
}
#endif /* USE_COOKIE */
#ifdef DEBIAN
else if (!strcmp("-s", argv[i]))
#else
else if (!strcmp("-S", argv[i]))
#endif
squeezeBlankLine = TRUE;
else if (!strcmp("-X", argv[i]))
Do_not_use_ti_te = TRUE;
else if (!strcmp("-o", argv[i])) {
#ifdef SHOW_PARAMS
if (++i >= argc || !strcmp(argv[i], "?")) {
show_params_p = 1;
usage();
}
#else
if (++i >= argc)
usage();
#endif
if (!set_param_option(argv[i])) {
/* option set failed */
fprintf(stderr, "%s: bad option\n", argv[i]);
#ifdef SHOW_PARAMS
show_params_p = 1;
usage();
#else
exit(1);
#endif
}
option_assigned = 1;
}
else if (!strcmp("-dummy", argv[i])) {
/* do nothing */
}
else if (!strcmp("-debug", argv[i]))
w3m_debug = TRUE;
else {
usage();
}
}
else if (*argv[i] == '+') {
line_str = argv[i] + 1;
}
else {
load_argv[load_argc++] = argv[i];
}
i++;
}
if (option_assigned) {
parse_proxy();
}
#ifdef __WATT32__
if (w3m_debug)
dbug_init();
sock_init();
#endif
Firstbuf = NULL;
Currentbuf = NULL;
CurrentKey = -1;
if (BookmarkFile == NULL)
BookmarkFile = rcFile(BOOKMARK);
if (!isatty(1) && !w3m_dump && !w3m_halfdump) {
/* redirected output */
w3m_dump = TRUE;
if (COLS == 0)
COLS = 80;
}
if (w3m_backend)
backend();
if (!w3m_dump && !w3m_halfdump)
fmInit();
orig_GC_warn_proc = GC_set_warn_proc(wrap_GC_warn_proc);
if (w3m_halfdump)
printf("<pre>\n");
if (load_argc == 0) {
if (!isatty(0)) {
redin = newFileStream(fdopen(dup(0), "rb"), (void (*)()) pclose);
newbuf = openGeneralPagerBuffer(redin);
dup2(1, 0);
}
else if (load_bookmark) {
newbuf = loadGeneralFile(BookmarkFile, NULL, NO_REFERER, 0, NULL);
if (newbuf == NULL)
fprintf(stderr, "w3m: Can't load bookmark\n");
}
else if (visual_start) {
Str s_page;
s_page = Strnew_charp("<title>W3M startup page</title><center><b>Welcome to ");
#ifdef JP_CHARSET
Strcat_charp(s_page, "<a href='http://ei5nazha.yz.yamagata-u.ac.jp/~aito/w3m/'>");
#else
Strcat_charp(s_page, "<a href='http://ei5nazha.yz.yamagata-u.ac.jp/~aito/w3m/eng/'>");
#endif /* JP_CHARSET */
Strcat_m_charp(s_page,
"w3m</a>!<p><p>This is w3m version ",
version,
"<br>Written by <a href='mailto:aito@ei5sun.yz.yamagata-u.ac.jp'>Akinori Ito</a>",
NULL);
#ifdef DEBIAN
Strcat_m_charp(s_page,
"<p>Debian package is maintained by <a href='mailto:ukai@debian.or.jp'>Fumitoshi UKAI</a>.",
"You can read <a href='file:///usr/share/doc/w3m/'>w3m documents on your local system</a>.",
NULL);
#endif /* DEBIAN */
newbuf = loadHTMLString(s_page);
if (newbuf == NULL)
fprintf(stderr, "w3m: Can't load string\n");
else
newbuf->bufferprop |= (BP_INTERNAL | BP_NO_URL);
}
else if ((p = getenv("HTTP_HOME")) != NULL ||
(p = getenv("WWW_HOME")) != NULL) {
newbuf = loadGeneralFile(p, NULL, NO_REFERER, 0, NULL);
if (newbuf == NULL)
fprintf(stderr, "w3m: Can't load %s\n", p);
}
else {
if (fmInitialized)
fmTerm();
usage();
}
if (newbuf == NULL) {
deleteFiles();
if (fmInitialized) {
sleep_till_anykey(1, 0);
fmTerm();
}
exit(2);
}
i = -1;
}
else {
i = 0;
}
for (; i < load_argc; i++) {
if (i >= 0) {
if (w3m_dump && w3m_dump_head) {
request = New(FormList);
request->method = FORM_METHOD_HEAD;
newbuf = loadGeneralFile(load_argv[i], NULL, NO_REFERER, 0, request);
}
else {
newbuf = loadGeneralFile(load_argv[i], NULL, NO_REFERER, 0, NULL);
}
if (newbuf == NULL) {
fprintf(stderr, "w3m: Can't load %s\n", load_argv[i]);
continue;
}
else if (newbuf == NO_BUFFER)
continue;
switch (newbuf->real_scheme) {
#ifdef USE_NNTP
case SCM_NNTP:
case SCM_NEWS:
#endif /* USE_NNTP */
case SCM_MAILTO:
break;
case SCM_LOCAL:
case SCM_LOCAL_CGI:
unshiftHist(LoadHist, load_argv[i]);
break;
default:
pushHashHist(URLHist, parsedURL2Str(&newbuf->currentURL)->ptr);
break;
}
}
if (newbuf == NO_BUFFER)
continue;
if (w3m_halfdump) {
Currentbuf = Firstbuf = newbuf;
printf("</pre><title>%s</title>\n", htmlquote_str(newbuf->buffername));
deleteFiles();
exit(0);
}
if (w3m_dump) {
Currentbuf = Firstbuf = newbuf;
if (w3m_dump_source)
dump_source(Currentbuf);
else if (w3m_dump_head)
dump_head(Currentbuf);
else {
if (Currentbuf->frameset != NULL && RenderFrame)
rFrame();
saveBuffer(Currentbuf, stdout);
}
deleteFiles();
#ifdef USE_COOKIES
save_cookies();
#endif /* USE_COOKIES */
exit(0);
}
if (Currentbuf == NULL)
Firstbuf = Currentbuf = newbuf;
else {
Currentbuf->nextBuffer = newbuf;
Currentbuf = newbuf;
}
if (Currentbuf && Currentbuf != NO_BUFFER &&
RenderFrame && Currentbuf->frameset != NULL) {
rFrame();
Currentbuf = newbuf;
}
#ifdef BUFINFO
saveBufferInfo();
#endif
}
if (!Firstbuf || Firstbuf == NO_BUFFER) {
if (newbuf == NO_BUFFER) {
if (fmInitialized)
inputStr("Hit any key to quit w3m:", "");
quitfm();
}
deleteFiles();
if (fmInitialized) {
sleep_till_anykey(1, 0);
fmTerm();
}
exit(2);
}
#ifdef SIGWINCH
signal(SIGWINCH, resize_hook);
#else /* not SIGWINCH */
setlinescols();
setupscreen();
#endif /* not SIGWINCH */
Currentbuf = Firstbuf;
displayBuffer(Currentbuf, B_NORMAL);
onA();
if (line_str) {
_goLine(line_str);
}
for (;;) {
/* event processing */
if (n_event_queue > 0) {
for (i = 0; i < n_event_queue; i++) {
CurrentKey = -1;
CurrentKeyData = eventQueue[i].user_data;
#ifdef MENU
CurrentMenuData = NULL;
#endif
w3mFuncList[eventQueue[i].cmd].func();
}
n_event_queue = 0;
}
CurrentKeyData = NULL;
/* get keypress event */
#ifdef MOUSE
if (use_mouse)
mouse_active();
#endif /* MOUSE */
c = getch();
#ifdef MOUSE
if (use_mouse)
mouse_inactive();
#endif /* MOUSE */
if (IS_ASCII(c)) { /* Ascii */
if (((prec_num && c == '0') || '1' <= c) && (c <= '9')) {
prec_num = prec_num * 10 + (int) (c - '0');
if (prec_num > PREC_LIMIT)
prec_num = PREC_LIMIT;
}
else {
keyPressEventProc((int) c);
prec_num = 0;
}
}
prev_key = CurrentKey;
CurrentKey = -1;
}
}
static void
keyPressEventProc(int c)
{
CurrentKey = c;
w3mFuncList[(int) GlobalKeymap[c]].func();
onA();
}
void
pushEvent(int event, void *user_data)
{
if (n_event_queue < N_EVENT_QUEUE) {
eventQueue[n_event_queue].cmd = event;
eventQueue[n_event_queue].user_data = user_data;
n_event_queue++;
}
}
static void
dump_source(Buffer * buf)
{
FILE *f;
char c;
if (buf->sourcefile == NULL)
return;
f = fopen(buf->sourcefile, "r");
if (f == NULL)
return;
while (c = fgetc(f), !feof(f)) {
putchar(c);
}
fclose(f);
}
static void
dump_head(Buffer * buf)
{
TextListItem *ti;
if (buf->document_header == NULL)
return;
for (ti = buf->document_header->first; ti; ti = ti->next) {
printf("%s", ti->ptr);
}
puts("");
}
void
nulcmd(void)
{ /* do nothing */
}
#ifdef __EMX__
void
pcmap(void)
{
w3mFuncList[(int) PcKeymap[(int) getch()].func();
}
#else /* not __EMX__ */
void pcmap(void)
{
}
#endif
void
escmap(void)
{
char c;
c = getch();
if (IS_ASCII(c)) {
CurrentKey = K_ESC | c;
w3mFuncList[(int) EscKeymap[(int) c]].func();
}
}
void
escbmap(void)
{
char c;
c = getch();
if (IS_DIGIT(c))
escdmap(c);
else if (IS_ASCII(c)) {
CurrentKey = K_ESCB | c;
w3mFuncList[(int) EscBKeymap[(int) c]].func();
}
}
void
escdmap(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 == '~') {
CurrentKey = K_ESCD | d;
w3mFuncList[(int) EscDKeymap[d]].func();
}
}
void
tmpClearBuffer(Buffer * buf)
{
if (buf->pagerSource == NULL &&
writeBufferCache(buf) == 0) {
buf->firstLine = NULL;
buf->topLine = NULL;
buf->currentLine = NULL;
buf->lastLine = NULL;
}
}
static Str currentURL(void);
void
saveBufferInfo()
{
FILE *fp;
if ((fp = fopen(rcFile("bufinfo"), "w")) == NULL) {
return;
}
else {
fprintf(fp, "%s\n", currentURL()->ptr);
fclose(fp);
}
}
static void
pushBuffer(Buffer * buf)
{
Buffer *b;
if (clear_buffer)
tmpClearBuffer(Currentbuf);
if (Firstbuf == Currentbuf) {
buf->nextBuffer = Firstbuf;
Firstbuf = Currentbuf = buf;
}
else if ((b = prevBuffer(Firstbuf, Currentbuf)) != NULL) {
b->nextBuffer = buf;
buf->nextBuffer = Currentbuf;
Currentbuf = buf;
}
#ifdef BUFINFO
saveBufferInfo();
#endif
}
static void
delBuffer(Buffer * buf)
{
if (buf == NULL)
return;
if (Currentbuf == buf)
Currentbuf = buf->nextBuffer;
Firstbuf = deleteBuffer(Firstbuf, buf);
if (!Currentbuf)
Currentbuf = Firstbuf;
}
static void
repBuffer(Buffer * oldbuf, Buffer * buf)
{
Firstbuf = replaceBuffer(Firstbuf, oldbuf, buf);
Currentbuf = buf;
}
MySignalHandler
intTrap(SIGNAL_ARG)
{ /* Interrupt catcher */
LONGJMP(IntReturn, 0);
SIGNAL_RETURN;
}
#ifdef SIGWINCH
MySignalHandler
resize_hook(SIGNAL_ARG)
{
setlinescols();
setupscreen();
if (Currentbuf)
displayBuffer(Currentbuf, B_FORCE_REDRAW);
signal(SIGWINCH, resize_hook);
SIGNAL_RETURN;
}
#endif /* SIGWINCH */
/*
* Command functions: These functions are called with a keystroke.
*/
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
static void
nscroll(int n, int mode)
{
Line *curtop = Currentbuf->topLine;
int lnum, tlnum, llnum, diff_n;
if (Currentbuf->firstLine == NULL)
return;
lnum = Currentbuf->currentLine->linenumber;
Currentbuf->topLine = lineSkip(Currentbuf, curtop, n, FALSE);
if (Currentbuf->topLine == curtop) {
lnum += n;
if (lnum < Currentbuf->topLine->linenumber)
lnum = Currentbuf->topLine->linenumber;
else if (lnum > Currentbuf->lastLine->linenumber)
lnum = Currentbuf->lastLine->linenumber;
} else {
tlnum = Currentbuf->topLine->linenumber;
llnum = Currentbuf->topLine->linenumber + LASTLINE - 1;
diff_n = n - (tlnum - curtop->linenumber);
if (lnum < tlnum)
lnum = tlnum + diff_n;
if (lnum > llnum)
lnum = llnum + diff_n;
}
gotoLine(Currentbuf, lnum);
arrangeLine(Currentbuf);
displayBuffer(Currentbuf, mode);
}
/* Move page forward */
void
pgFore(void)
{
#ifdef VI_PREC_NUM
nscroll(PREC_NUM * (LASTLINE - 1), B_NORMAL);
#else /* not VI_PREC_NUM */
nscroll(prec_num ? prec_num : (LASTLINE - 1),
prec_num ? B_SCROLL : B_NORMAL);
#endif /* not VI_PREC_NUM */
}
/* Move page backward */
void
pgBack(void)
{
#ifdef VI_PREC_NUM
nscroll(- PREC_NUM * (LASTLINE - 1), B_NORMAL);
#else /* not VI_PREC_NUM */
nscroll(- (prec_num ? prec_num : (LASTLINE - 1)),
prec_num ? B_SCROLL : B_NORMAL);
#endif /* not VI_PREC_NUM */
}
/* 1 line up */
void
lup1(void)
{
nscroll(PREC_NUM, B_SCROLL);
}
/* 1 line down */
void
ldown1(void)
{
nscroll(-PREC_NUM, B_SCROLL);
}
/* move cursor position to the center of screen */
void
ctrCsrV(void)
{
int offsety;
if (Currentbuf->firstLine == NULL)
return;
offsety = LASTLINE / 2 - Currentbuf->cursorY;
if (offsety != 0) {
/* Currentbuf->currentLine = lineSkip(Currentbuf,
* Currentbuf->currentLine,offsety, FALSE); */
Currentbuf->topLine = lineSkip(Currentbuf, Currentbuf->topLine, -offsety, FALSE);
arrangeLine(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
}
void
ctrCsrH(void)
{
int offsetx;
if (Currentbuf->firstLine == NULL)
return;
offsetx = Currentbuf->cursorX - COLS / 2;
if (offsetx != 0) {
columnSkip(Currentbuf, offsetx);
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
}
/* Redraw screen */
void
rdrwSc(void)
{
clear();
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
/* Search regular expression forward */
void
srchfor(void)
{
MySignalHandler(*prevtrap) ();
char *str;
int i;
int wrapped = 0;
str = inputStrHist("Forward: ", NULL, TextHist);
if (str != NULL && *str == '\0')
str = SearchString;
if (str == NULL || *str == '\0') {
displayBuffer(Currentbuf, B_NORMAL);
return;
}
SearchString = str;
prevtrap = signal(SIGINT, intTrap);
crmode();
if (SETJMP(IntReturn) == 0)
for (i = 0; i < PREC_NUM; i++)
wrapped = forwardSearch(Currentbuf, SearchString);
signal(SIGINT, prevtrap);
term_raw();
displayBuffer(Currentbuf, B_NORMAL);
if (wrapped) {
disp_message("Search wrapped", FALSE);
}
searchRoutine = forwardSearch;
}
/* Search regular expression backward */
void
srchbak(void)
{
MySignalHandler(*prevtrap) ();
char *str;
int i;
int wrapped = 0;
str = inputStrHist("Backward: ", NULL, TextHist);
if (str != NULL && *str == '\0')
str = SearchString;
if (str == NULL || *str == '\0') {
displayBuffer(Currentbuf, B_NORMAL);
return;
}
SearchString = str;
prevtrap = signal(SIGINT, intTrap);
crmode();
if (SETJMP(IntReturn) == 0)
for (i = 0; i < PREC_NUM; i++)
wrapped = backwardSearch(Currentbuf, SearchString);
signal(SIGINT, prevtrap);
term_raw();
displayBuffer(Currentbuf, B_NORMAL);
if (wrapped) {
disp_message("Search wrapped", FALSE);
}
searchRoutine = backwardSearch;
}
static void
srch_nxtprv(int reverse)
{
int i;
int wrapped = 0;
static int (*routine[2]) (Buffer *, char *) =
{
forwardSearch, backwardSearch
};
MySignalHandler(*prevtrap) ();
if (searchRoutine == NULL) {
disp_message("No previous regular expression", TRUE);
return;
}
move(LASTLINE, 0);
addstr(searchRoutine == forwardSearch ? "Forward: " : "Backward: ");
addstr(SearchString);
clrtoeolx();
move(LASTLINE, 0);
refresh();
if (reverse != 0)
reverse = 1;
if (searchRoutine == backwardSearch)
reverse ^= 1;
prevtrap = signal(SIGINT, intTrap);
crmode();
if (SETJMP(IntReturn) == 0)
for (i = 0; i < PREC_NUM; i++)
wrapped = (*routine[reverse]) (Currentbuf, SearchString);
signal(SIGINT, prevtrap);
term_raw();
displayBuffer(Currentbuf, B_NORMAL);
if (wrapped) {
disp_message("Search wrapped", FALSE);
}
}
/* Search next matching */
void
srchnxt(void)
{
srch_nxtprv(0);
}
/* Search previous matching */
void
srchprv(void)
{
srch_nxtprv(1);
}
static void
shiftvisualpos(Buffer * buf, int shift)
{
buf->visualpos -= shift;
if (buf->visualpos >= COLS)
buf->visualpos = COLS - 1;
else if (buf->visualpos < 0)
buf->visualpos = 0;
arrangeLine(buf);
if (buf->visualpos == -shift && buf->cursorX == 0)
buf->visualpos = 0;
}
/* Shift screen left */
void
shiftl(void)
{
int column;
if (Currentbuf->firstLine == NULL)
return;
column = Currentbuf->currentColumn;
columnSkip(Currentbuf, PREC_NUM * (-COLS + 1) + 1);
shiftvisualpos(Currentbuf, Currentbuf->currentColumn - column);
displayBuffer(Currentbuf, B_NORMAL);
}
/* Shift screen right */
void
shiftr(void)
{
int column;
if (Currentbuf->firstLine == NULL)
return;
column = Currentbuf->currentColumn;
columnSkip(Currentbuf, PREC_NUM * (COLS - 1) - 1);
shiftvisualpos(Currentbuf, Currentbuf->currentColumn - column);
displayBuffer(Currentbuf, B_NORMAL);
}
void
col1R(void)
{
Buffer *buf = Currentbuf;
Line *l = buf->currentLine;
int j, column;
if (l == NULL)
return;
for (j = 0; j < PREC_NUM; j++) {
column = buf->currentColumn;
columnSkip(Currentbuf, 1);
if (column == buf->currentColumn)
break;
shiftvisualpos(Currentbuf, 1);
}
displayBuffer(Currentbuf, B_NORMAL);
}
void
col1L(void)
{
Buffer *buf = Currentbuf;
Line *l = buf->currentLine;
int j;
if (l == NULL)
return;
for (j = 0; j < PREC_NUM; j++) {
if (buf->currentColumn == 0)
break;
columnSkip(Currentbuf, -1);
shiftvisualpos(Currentbuf, -1);
}
displayBuffer(Currentbuf, B_NORMAL);
}
/* Execute shell command and read output ac pipe. */
void
pipesh(void)
{
Buffer *buf;
char *cmd;
CurrentKeyData = NULL; /* not allowed in w3m-control: */
cmd = searchKeyData();
if (cmd == NULL || *cmd == '\0') {
cmd = inputLineHist("(read shell[pipe])!", "", IN_COMMAND, ShellHist);
if (cmd == NULL || *cmd == '\0') {
displayBuffer(Currentbuf, B_NORMAL);
return;
}
}
buf = getpipe(cmd);
if (buf == NULL) {
disp_message("Execution failed", FALSE);
}
else {
buf->bufferprop |= (BP_INTERNAL | BP_NO_URL);
if (buf->type == NULL)
buf->type = "text/plain";
pushBuffer(buf);
}
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
/* Execute shell command and load entire output to buffer */
void
readsh(void)
{
Buffer *buf;
MySignalHandler(*prevtrap) ();
char *cmd;
CurrentKeyData = NULL; /* not allowed in w3m-control: */
cmd = searchKeyData();
if (cmd == NULL || *cmd == '\0') {
cmd = inputLineHist("(read shell)!", "", IN_COMMAND, ShellHist);
if (cmd == NULL || *cmd == '\0') {
displayBuffer(Currentbuf, B_NORMAL);
return;
}
}
prevtrap = signal(SIGINT, intTrap);
crmode();
buf = getshell(cmd);
signal(SIGINT, prevtrap);
term_raw();
if (buf == NULL) {
disp_message("Execution failed", FALSE);
}
else {
buf->bufferprop |= (BP_INTERNAL | BP_NO_URL);
if (buf->type == NULL)
buf->type = "text/plain";
pushBuffer(buf);
}
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
/* Execute shell command */
void
execsh(void)
{
#ifdef MOUSE
int use_m = use_mouse;
#endif
char *cmd;
CurrentKeyData = NULL; /* not allowed in w3m-control: */
cmd = searchKeyData();
if (cmd == NULL || *cmd == '\0') {
cmd = inputLineHist("(exec shell)!", "", IN_COMMAND, ShellHist);
}
if (cmd != NULL && *cmd != '\0') {
fmTerm();
system(cmd);
printf("\n[Hit any key]");
fflush(stdout);
#ifdef MOUSE
use_mouse = FALSE;
#endif
fmInit();
getch();
#ifdef MOUSE
use_mouse = use_m;
if (use_mouse)
mouse_init();
#endif
}
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
/* Load file */
void
ldfile(void)
{
char *fn;
fn = searchKeyData();
if (fn == NULL || *fn == '\0') {
fn = inputFilenameHist("(Load)Filename? ", NULL, LoadHist);
if (fn == NULL || *fn == '\0') {
displayBuffer(Currentbuf, B_NORMAL);
return;
}
}
cmd_loadfile(fn);
}
/* Load help file */
void
ldhelp(void)
{
cmd_loadURL(helpFile(HELP_FILE), NULL);
}
static void
cmd_loadfile(char *fn)
{
Buffer *buf;
buf = loadGeneralFile(fn, NULL, NO_REFERER, 0, NULL);
if (buf == NULL) {
char *emsg = Sprintf("%s not found", fn)->ptr;
disp_err_message(emsg, FALSE);
}
else if (buf != NO_BUFFER) {
pushBuffer(buf);
if (RenderFrame && Currentbuf->frameset != NULL)
rFrame();
}
displayBuffer(Currentbuf, B_NORMAL);
}
/* Move cursor left */
void
movL(void)
{
int i;
if (Currentbuf->firstLine == NULL)
return;
for (i = 0; i < PREC_NUM; i++)
cursorLeft(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
/* Move cursor downward */
void
movD(void)
{
int i;
if (Currentbuf->firstLine == NULL)
return;
for (i = 0; i < PREC_NUM; i++)
cursorDown(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
/* move cursor upward */
void
movU(void)
{
int i;
if (Currentbuf->firstLine == NULL)
return;
for (i = 0; i < PREC_NUM; i++)
cursorUp(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
/* Move cursor right */
void
movR(void)
{
int i;
if (Currentbuf->firstLine == NULL)
return;
for (i = 0; i < PREC_NUM; i++)
cursorRight(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
/* movLW, movRW */
/*
* From: Takashi Nishimoto <g96p0935@mse.waseda.ac.jp> Date: Mon, 14 Jun
* 1999 09:29:56 +0900 */
#define IS_WORD_CHAR(c,p) (IS_ALNUM(c) && CharType(p) == PC_ASCII)
static int
prev_nonnull_line(Line * line)
{
Line *l;
for (l = line; l != NULL && l->len == 0; l = l->prev);
if (l == NULL || l->len == 0)
return -1;
Currentbuf->currentLine = l;
if (l != line)
Currentbuf->pos = Currentbuf->currentLine->len;
return 0;
}
void
movLW(void)
{
char *lb;
Lineprop *pb;
Line *pline;
int ppos;
int i;
if (Currentbuf->firstLine == NULL)
return;
for (i = 0; i < PREC_NUM; i++) {
pline = Currentbuf->currentLine;
ppos = Currentbuf->pos;
if (prev_nonnull_line(Currentbuf->currentLine) < 0)
goto end;
while (1) {
lb = Currentbuf->currentLine->lineBuf;
pb = Currentbuf->currentLine->propBuf;
while (Currentbuf->pos > 0 &&
!IS_WORD_CHAR(lb[Currentbuf->pos - 1], pb[Currentbuf->pos - 1])) {
Currentbuf->pos--;
}
if (Currentbuf->pos > 0)
break;
if (prev_nonnull_line(Currentbuf->currentLine->prev) < 0) {
Currentbuf->currentLine = pline;
Currentbuf->pos = ppos;
goto end;
}
Currentbuf->pos = Currentbuf->currentLine->len;
}
lb = Currentbuf->currentLine->lineBuf;
pb = Currentbuf->currentLine->propBuf;
while (Currentbuf->pos > 0 &&
IS_WORD_CHAR(lb[Currentbuf->pos - 1], pb[Currentbuf->pos - 1])) {
Currentbuf->pos--;
}
}
end:
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
static int
next_nonnull_line(Line * line)
{
Line *l;
for (l = line; l != NULL && l->len == 0; l = l->next);
if (l == NULL || l->len == 0)
return -1;
Currentbuf->currentLine = l;
if (l != line)
Currentbuf->pos = 0;
return 0;
}
void
movRW(void)
{
char *lb;
Lineprop *pb;
Line *pline;
int ppos;
int i;
if (Currentbuf->firstLine == NULL)
return;
for (i = 0; i < PREC_NUM; i++) {
pline = Currentbuf->currentLine;
ppos = Currentbuf->pos;
if (next_nonnull_line(Currentbuf->currentLine) < 0)
goto end;
lb = Currentbuf->currentLine->lineBuf;
pb = Currentbuf->currentLine->propBuf;
while (lb[Currentbuf->pos] &&
IS_WORD_CHAR(lb[Currentbuf->pos], pb[Currentbuf->pos]))
Currentbuf->pos++;
while (1) {
while (lb[Currentbuf->pos] &&
!IS_WORD_CHAR(lb[Currentbuf->pos], pb[Currentbuf->pos]))
Currentbuf->pos++;
if (lb[Currentbuf->pos])
break;
if (next_nonnull_line(Currentbuf->currentLine->next) < 0) {
Currentbuf->currentLine = pline;
Currentbuf->pos = ppos;
goto end;
}
Currentbuf->pos = 0;
lb = Currentbuf->currentLine->lineBuf;
pb = Currentbuf->currentLine->propBuf;
}
}
end:
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
/* Question and Quit */
void
qquitfm(void)
{
char *ans;
if (!confirm_on_quit)
quitfm();
ans = inputStr("Do you want to exit w3m? (y or n)", "");
if (ans != NULL && tolower(*ans) == 'y')
quitfm();
displayBuffer(Currentbuf, B_NORMAL);
}
/* Quit */
void
quitfm(void)
{
fmTerm();
deleteFiles();
#ifdef USE_COOKIE
save_cookies();
#endif /* USE_COOKIE */
#ifdef USE_HISTORY
if (SaveURLHist)
saveHistory(URLHist, URLHistSize);
#endif /* USE_HISTORY */
exit(0);
}
/* Select buffer */
void
selBuf(void)
{
Buffer *buf;
int ok;
char cmd;
ok = FALSE;
do {
buf = selectBuffer(Firstbuf, Currentbuf, &cmd);
switch (cmd) {
case 'B':
ok = TRUE;
break;
case '\n':
case ' ':
Currentbuf = buf;
ok = TRUE;
break;
case 'D':
delBuffer(buf);
if (Firstbuf == NULL) {
/* No more buffer */
Firstbuf = nullBuffer();
Currentbuf = Firstbuf;
}
break;
case 'q':
qquitfm();
break;
case 'Q':
quitfm();
break;
}
} while (!ok);
if (clear_buffer) {
for (buf = Firstbuf; buf != NULL; buf = buf->nextBuffer)
tmpClearBuffer(buf);
}
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
/* Suspend (on BSD), or run interactive shell (on SysV) */
void
susp(void)
{
#ifndef SIGSTOP
char *shell;
#endif /* not SIGSTOP */
move(LASTLINE, 0);
clrtoeolx();
refresh();
fmTerm();
#ifndef SIGSTOP
shell = getenv("SHELL");
if (shell == NULL)
shell = "/bin/sh";
system(shell);
#else /* SIGSTOP */
kill((pid_t)0, SIGSTOP);
#endif /* SIGSTOP */
fmInit();
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
/* Go to specified line */
static void
_goLine(char *l)
{
if (l == NULL || *l == '\0' || Currentbuf->currentLine == NULL) {
displayBuffer(Currentbuf, B_FORCE_REDRAW);
return;
}
Currentbuf->pos = 0;
if (((*l == '^') || (*l == '$')) && prec_num) {
gotoRealLine(Currentbuf, prec_num);
}
else if (*l == '^') {
Currentbuf->topLine = Currentbuf->currentLine = Currentbuf->firstLine;
}
else if (*l == '$') {
Currentbuf->topLine = lineSkip(Currentbuf, Currentbuf->lastLine, -(LASTLINE + 1) / 2, TRUE);
Currentbuf->currentLine = Currentbuf->lastLine;
}
else
gotoRealLine(Currentbuf, atoi(l));
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
void
goLine(void)
{
char *l = inputStr("Goto line: ", "");
prec_num = 0;
_goLine(l);
}
void
goLineF(void)
{
_goLine("^");
}
void
goLineL(void)
{
_goLine("$");
}
/* Go to the beginning of the line */
void
linbeg(void)
{
if (Currentbuf->firstLine == NULL)
return;
Currentbuf->pos = 0;
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
/* Go to the bottom of the line */
void
linend(void)
{
if (Currentbuf->firstLine == NULL)
return;
Currentbuf->pos = Currentbuf->currentLine->len - 1;
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
/* Run editor on the current buffer */
void
editBf(void)
{
char *fn = Currentbuf->filename;
char *type = Currentbuf->type;
int top, linenum, cursorY, pos, currentColumn;
Buffer *buf, *fbuf = NULL;
Str cmd;
if (fn == NULL ||
Currentbuf->pagerSource != NULL || /* Behaving as a pager */
(Currentbuf->type == NULL &&
Currentbuf->edit == NULL) || /* Reading shell */
Currentbuf->real_scheme != SCM_LOCAL ||
!strcmp(Currentbuf->currentURL.file, "-") || /* file is std *
* input */
Currentbuf->bufferprop & BP_FRAME) { /* Frame */
disp_err_message("Can't edit other than local file", TRUE);
return;
}
if (Currentbuf->frameset != NULL)
fbuf = Currentbuf->linkBuffer[LB_FRAME];
if (Currentbuf->firstLine == NULL) {
top = 1;
linenum = 1;
} else {
top = Currentbuf->topLine->linenumber;
linenum = Currentbuf->currentLine->linenumber;
}
cursorY = Currentbuf->cursorY;
pos = Currentbuf->pos;
currentColumn = Currentbuf->currentColumn;
if (Currentbuf->edit) {
cmd = unquote_mailcap(Currentbuf->edit,
Currentbuf->real_type,
quoteShell(fn)->ptr, NULL);
}
else {
char *file = quoteShell(fn)->ptr;
if (strcasestr(Editor, "%s")) {
if (strcasestr(Editor, "%d"))
cmd = Sprintf(Editor, linenum, file);
else
cmd = Sprintf(Editor, file);
} else {
if (strcasestr(Editor, "%d"))
cmd = Sprintf(Editor, linenum);
else if (strcasestr(Editor, "vi"))
cmd = Sprintf("%s +%d", Editor, linenum);
else
cmd = Strnew_charp(Editor);
Strcat_m_charp(cmd, " ", file, NULL);
}
}
fmTerm();
system(cmd->ptr);
fmInit();
buf = loadGeneralFile(fn, NULL, NO_REFERER, 0, NULL);
if (buf == NULL) {
disp_err_message("Re-loading failed", FALSE);
buf = nullBuffer();
}
else if (buf == NO_BUFFER) {
buf = nullBuffer();
}
if (fbuf != NULL)
Firstbuf = deleteBuffer(Firstbuf, fbuf);
repBuffer(Currentbuf, buf);
if ((type != NULL) && (buf->type != NULL) &&
((!strcasecmp(buf->type, "text/plain") &&
!strcasecmp(type, "text/html")) ||
(!strcasecmp(buf->type, "text/html") &&
!strcasecmp(type, "text/plain")))) {
vwSrc();
if (Currentbuf != buf)
Firstbuf = deleteBuffer(Firstbuf, buf);
}
if (Currentbuf->firstLine == NULL) {
displayBuffer(Currentbuf, B_FORCE_REDRAW);
return;
}
Currentbuf->topLine = lineSkip(Currentbuf, Currentbuf->topLine, top - 1, FALSE);
gotoLine(Currentbuf, linenum);
Currentbuf->pos = pos;
Currentbuf->currentColumn = currentColumn;
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
/* Run editor on the current screen */
void
editScr(void)
{
int lnum;
Str cmd;
Str tmpf;
FILE *f;
tmpf = tmpfname(TMPF_DFL, NULL);
f = fopen(tmpf->ptr, "w");
if (f == NULL) {
cmd = Sprintf("Can't open %s\n", tmpf->ptr);
disp_err_message(cmd->ptr, TRUE);
return;
}
saveBuffer(Currentbuf, f);
fclose(f);
if (Currentbuf->currentLine)
lnum = Currentbuf->currentLine->linenumber;
else
lnum = 1;
if (strcasestr(Editor, "%s")) {
if (strcasestr(Editor, "%d"))
cmd = Sprintf(Editor, lnum, tmpf->ptr);
else
cmd = Sprintf(Editor, tmpf->ptr);
} else {
if (strcasestr(Editor, "%d"))
cmd = Sprintf(Editor, lnum);
else if (strcasestr(Editor, "vi"))
cmd = Sprintf("%s +%d", Editor, lnum);
else
cmd = Strnew_charp(Editor);
Strcat_m_charp(cmd, " ", tmpf->ptr, NULL);
}
fmTerm();
system(cmd->ptr);
fmInit();
unlink(tmpf->ptr);
gotoLine(Currentbuf, lnum);
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
#ifdef USE_MARK
/* Set / unset mark */
void
_mark(void)
{
Line *l;
if (Currentbuf->firstLine == NULL)
return;
l = Currentbuf->currentLine;
cmd_mark(&l->propBuf[Currentbuf->pos]);
redrawLine(Currentbuf, l, l->linenumber - Currentbuf->topLine->linenumber);
}
static void
cmd_mark(Lineprop * p)
{
if ((*p & PM_MARK) && (*p & PE_STAND))
*p &= ~PE_STAND;
else if (!(*p & PM_MARK) && !(*p & PE_STAND))
*p |= PE_STAND;
*p ^= PM_MARK;
}
/* Go to next mark */
void
nextMk(void)
{
Line *l;
int i;
if (Currentbuf->firstLine == NULL)
return;
i = Currentbuf->pos + 1;
l = Currentbuf->currentLine;
if (i >= l->len) {
i = 0;
l = l->next;
}
while (l != NULL) {
for (; i < l->len; i++) {
if (l->propBuf[i] & PM_MARK) {
Currentbuf->currentLine = l;
Currentbuf->pos = i;
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
return;
}
}
l = l->next;
i = 0;
}
disp_message("No mark exist after here", TRUE);
}
/* Go to previous mark */
void
prevMk(void)
{
Line *l;
int i;
if (Currentbuf->firstLine == NULL)
return;
i = Currentbuf->pos - 1;
l = Currentbuf->currentLine;
if (i < 0) {
l = l->prev;
if (l != NULL)
i = l->len - 1;
}
while (l != NULL) {
for (; i >= 0; i--) {
if (l->propBuf[i] & PM_MARK) {
Currentbuf->currentLine = l;
Currentbuf->pos = i;
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
return;
}
}
l = l->prev;
if (l != NULL)
i = l->len - 1;
}
disp_message("No mark exist before here", TRUE);
}
/* Mark place to which the regular expression matches */
void
reMark(void)
{
Line *l;
char *str;
char *p, *p1, *p2;
str = inputStrHist("(Mark)Regexp: ", MarkString, TextHist);
if (str == NULL || *str == '\0') {
displayBuffer(Currentbuf, B_NORMAL);
return;
}
MarkString = str;
if ((MarkString = regexCompile(MarkString, 1)) != NULL) {
disp_message(MarkString, TRUE);
return;
}
for (l = Currentbuf->firstLine; l != NULL; l = l->next) {
p = l->lineBuf;
for (;;) {
if (regexMatch(p, &l->lineBuf[l->len] - p, p == l->lineBuf) == 1) {
matchedPosition(&p1, &p2);
cmd_mark(l->propBuf + (p1 - l->lineBuf));
p = p2;
}
else
break;
}
}
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
#endif /* USE_MARK */
#ifdef JP_CHARSET
static char *
cURLcode(char *url, Buffer * buf)
{
char *p;
Str s;
for (p = url; *p; p++) {
if (!IS_ASCII(*p)) {
/* URL contains Kanji... uugh */
s = conv(url, InnerCode, buf->document_code);
return s->ptr;
}
}
return url;
}
#else /* not JP_CHARSET */
#define cURLcode(url,buf) (url)
#endif /* not JP_CHARSET */
static Buffer *
loadNormalBuf(Buffer * buf, int renderframe)
{
pushBuffer(buf);
if (renderframe && RenderFrame && Currentbuf->frameset != NULL)
rFrame();
return buf;
}
static Buffer *
loadLink(char *url, char *target, char *referer, FormList * request)
{
Buffer *buf, *nfbuf;
union frameset_element *f_element = NULL;
int flag = 0;
ParsedURL *base, pu;
message(Sprintf("loading %s\n", url)->ptr, 0, 0);
refresh();
base = baseURL(Currentbuf);
if (base == NULL ||
base->scheme == SCM_LOCAL || base->scheme == SCM_LOCAL_CGI)
referer = NO_REFERER;
if (referer == NULL)
referer = parsedURL2Str(&Currentbuf->currentURL)->ptr;
buf = loadGeneralFile(cURLcode(url, Currentbuf),
baseURL(Currentbuf),
referer,
flag,
request);
if (buf == NULL) {
char *emsg = Sprintf("Can't load %s\n", url)->ptr;
disp_err_message(emsg, FALSE);
return NULL;
}
parseURL2(url, &pu, base);
pushHashHist(URLHist, parsedURL2Str(&pu)->ptr);
if (buf == NO_BUFFER) {
return NULL;
}
if (!on_target) /* open link as an indivisual page */
return loadNormalBuf(buf, TRUE);
if (do_download) /* download (thus no need to render frame) */
return loadNormalBuf(buf, FALSE);
if (target == NULL || /* no target specified (that means * this
* page is not a frame page) */
!strcmp(target, "_top") || /* this link is specified to * be
* opened as an indivisual * page */
!(Currentbuf->bufferprop & BP_FRAME) /* This page is not a *
* frame page */
) {
return loadNormalBuf(buf, TRUE);
}
nfbuf = Currentbuf->linkBuffer[LB_N_FRAME];
if (nfbuf == NULL) {
/* original page (that contains <frameset> tag) doesn't exist */
return loadNormalBuf(buf, TRUE);
}
f_element = search_frame(nfbuf->frameset, target);
if (f_element == NULL) {
/* specified target doesn't exist in this frameset */
return loadNormalBuf(buf, TRUE);
}
/* frame page */
/* stack current frameset */
pushFrameTree(&(nfbuf->frameQ),
copyFrameSet(nfbuf->frameset),
Currentbuf->currentLine ?
Currentbuf->currentLine->linenumber : 0,
Currentbuf->pos);
/* delete frame view buffer */
delBuffer(Currentbuf);
Currentbuf = nfbuf;
/* nfbuf->frameset = copyFrameSet(nfbuf->frameset); */
resetFrameElement(f_element, buf, referer, request);
discardBuffer(buf);
rFrame();
{
Anchor *al = NULL;
char *label = pu.label;
if (label && f_element->element->attr == F_BODY) {
al = searchAnchor(f_element->body->nameList, label);
}
if (!al) {
label = Strnew_m_charp("_", target, NULL)->ptr;
al = searchURLLabel(Currentbuf, label);
}
if (al) {
gotoLine(Currentbuf, al->start.line);
Currentbuf->pos = al->start.pos;
arrangeCursor(Currentbuf);
}
}
displayBuffer(Currentbuf, B_NORMAL);
return buf;
}
static void
gotoLabel(char *label)
{
Buffer *buf;
Anchor *al;
int i;
al = searchURLLabel(Currentbuf, label);
if (al == NULL) {
disp_message(Sprintf("%s is not found", label)->ptr, TRUE);
return;
}
buf = newBuffer(Currentbuf->width);
copyBuffer(buf, Currentbuf);
for (i = 0; i < MAX_LB; i++)
buf->linkBuffer[i] = NULL;
buf->currentURL.label = allocStr(label, 0);
pushHashHist(URLHist, parsedURL2Str(&buf->currentURL)->ptr);
(*buf->clone)++;
pushBuffer(buf);
gotoLine(Currentbuf, al->start.line);
Currentbuf->pos = al->start.pos;
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_FORCE_REDRAW);
return;
}
/* follow HREF link */
void
followA(void)
{
Line *l;
Anchor *a;
ParsedURL u;
if (Currentbuf->firstLine == NULL)
return;
l = Currentbuf->currentLine;
a = retrieveCurrentAnchor(Currentbuf);
if (a == NULL) {
followForm();
return;
}
if (*a->url == '#') { /* index within this buffer */
gotoLabel(a->url + 1);
return;
}
parseURL2(a->url, &u, baseURL(Currentbuf));
if (u.scheme == Currentbuf->currentURL.scheme &&
u.port == Currentbuf->currentURL.port &&
((u.host == NULL && Currentbuf->currentURL.host == NULL) ||
(u.host != NULL && Currentbuf->currentURL.host != NULL &&
strcasecmp(u.host, Currentbuf->currentURL.host) == 0)) &&
((u.file == NULL && Currentbuf->currentURL.file == NULL) ||
(u.file != NULL && Currentbuf->currentURL.file != NULL &&
strcmp(u.file, Currentbuf->currentURL.file) == 0))) {
/* index within this buffer */
if (u.label) {
gotoLabel(u.label);
return;
}
}
if (!strncasecmp(a->url, "mailto:", 7)) {
/* invoke external mailer */
Str tmp;
char *to = quoteShell(a->url + 7)->ptr;
if (strcasestr(Mailer, "%s"))
tmp = Sprintf(Mailer, to);
else
tmp = Strnew_m_charp(Mailer, " ", to, NULL);
fmTerm();
system(tmp->ptr);
fmInit();
displayBuffer(Currentbuf, B_FORCE_REDRAW);
return;
}
#ifdef USE_NNTP
else if (!strncasecmp(a->url, "news:", 5) &&
strchr(a->url, '@') == NULL) {
/* news:newsgroup is not supported */
disp_err_message("news:newsgroup_name is not supported", TRUE);
return;
}
#endif /* USE_NNTP */
loadLink(a->url, a->target, a->referer, NULL);
displayBuffer(Currentbuf, B_NORMAL);
}
/* follow HREF link in the buffer */
void
bufferA(void)
{
on_target = FALSE;
followA();
on_target = TRUE;
}
/* view inline image */
void
followI(void)
{
Line *l;
Anchor *a;
Buffer *buf;
if (Currentbuf->firstLine == NULL)
return;
l = Currentbuf->currentLine;
a = retrieveCurrentImg(Currentbuf);
if (a == NULL)
return;
message(Sprintf("loading %s\n", a->url)->ptr, 0, 0);
refresh();
buf = loadGeneralFile(cURLcode(a->url, Currentbuf), baseURL(Currentbuf), NULL, 0, NULL);
if (buf == NULL) {
char *emsg = Sprintf("Can't load %s\n", a->url)->ptr;
disp_err_message(emsg, FALSE);
}
else if (buf != NO_BUFFER) {
pushBuffer(buf);
}
displayBuffer(Currentbuf, B_NORMAL);
}
static void
do_update_form_radio(FormItemList * f, void *data)
{
Buffer *buf = (Buffer *) data;
formUpdateBuffer(&buf->formitem->anchors[f->anchor_num], buf, f);
}
static FormItemList *
save_submit_formlist(FormItemList * src)
{
FormList *list;
FormList *srclist;
FormItemList *srcitem;
FormItemList *item;
FormItemList *ret = NULL;
#ifdef MENU_SELECT
FormSelectOptionItem *opt;
FormSelectOptionItem *curopt;
FormSelectOptionItem *srcopt;
#endif /* MENU_SELECT */
if (src == NULL)
return NULL;
srclist = src->parent;
list = New(FormList);
list->method = srclist->method;
list->action = Strdup(srclist->action);
list->charset = srclist->charset;
list->enctype = srclist->enctype;
list->nitems = srclist->nitems;
list->body = srclist->body;
list->boundary = srclist->boundary;
list->length = srclist->length;
for (srcitem = srclist->item; srcitem; srcitem = srcitem->next) {
item = New(FormItemList);
item->type = srcitem->type;
item->name = Strdup(srcitem->name);
item->value = Strdup(srcitem->value);
item->checked = srcitem->checked;
item->accept = srcitem->accept;
item->size = srcitem->size;
item->rows = srcitem->rows;
item->maxlength = srcitem->maxlength;
#ifdef MENU_SELECT
opt = curopt = NULL;
for (srcopt = srcitem->select_option; srcopt; srcopt = srcopt->next) {
if (!srcopt->checked)
continue;
opt = New(FormSelectOptionItem);
opt->value = Strdup(srcopt->value);
opt->label = Strdup(srcopt->label);
opt->checked = srcopt->checked;
if (item->select_option == NULL) {
item->select_option = curopt = opt;
}
else {
curopt->next = opt;
curopt = curopt->next;
}
}
item->select_option = opt;
if (srcitem->label)
item->label = Strdup(srcitem->label);
#endif /* MENU_SELECT */
item->parent = list;
item->next = NULL;
if (list->lastitem == NULL) {
list->item = list->lastitem = item;
}
else {
list->lastitem->next = item;
list->lastitem = item;
}
if (srcitem == src)
ret = item;
}
return ret;
}
static void
query_from_followform(Str * query, FormItemList * fi, int multipart)
{
FormItemList *f2;
FILE *body = NULL;
if (multipart) {
*query = tmpfname(TMPF_DFL, NULL);
body = fopen((*query)->ptr, "w");
if (body == NULL) {
return;
}
fi->parent->body = (*query)->ptr;
fi->parent->boundary = Sprintf("------------------------------%d%ld%ld%ld",
getpid(), fi->parent, fi->parent->body, fi->parent->boundary)->ptr;
}
*query = Strnew();
for (f2 = fi->parent->item; f2; f2 = f2->next) {
if (f2->name == NULL)
continue;
/* <ISINDEX> is translated into single text form */
if (f2->name->length == 0 &&
(multipart || f2->type != FORM_INPUT_TEXT))
continue;
switch (f2->type) {
case FORM_INPUT_RESET:
/* do nothing */
continue;
case FORM_INPUT_SUBMIT:
case FORM_INPUT_IMAGE:
if (f2 != fi || f2->value == NULL)
continue;
break;
case FORM_INPUT_RADIO:
case FORM_INPUT_CHECKBOX:
if (!f2->checked)
continue;
}
if (multipart) {
if (f2->type == FORM_INPUT_IMAGE) {
*query = Strdup(f2->name);
Strcat_charp(*query, ".x");
form_write_data(body, fi->parent->boundary, (*query)->ptr, "1");
*query = Strdup(f2->name);
Strcat_charp(*query, ".y");
form_write_data(body, fi->parent->boundary, (*query)->ptr, "1");
}
else if (f2->name && f2->name->length > 0) {
/* not IMAGE */
if (f2->value != NULL) {
#ifdef JP_CHARSET
if (fi->parent->charset != 0)
*query = conv_str(f2->value, InnerCode, fi->parent->charset);
else
*query = conv_str(f2->value, InnerCode, Currentbuf->document_code);
#else /* not JP_CHARSET */
*query = f2->value;
#endif /* not JP_CHARSET */
}
if (f2->type == FORM_INPUT_FILE)
form_write_form_file(body, fi->parent->boundary, f2->name->ptr, (*query)->ptr);
else
form_write_data(body, fi->parent->boundary, f2->name->ptr, (*query)->ptr);
}
}
else {
/* not multipart */
if (f2->type == FORM_INPUT_IMAGE) {
Strcat(*query, f2->name);
Strcat_charp(*query, ".x=1&");
Strcat(*query, f2->name);
Strcat_charp(*query, ".y=1");
}
else {
/* not IMAGE */
if (f2->name && f2->name->length > 0) {
Strcat(*query, form_quote(f2->name));
Strcat_char(*query, '=');
}
if (f2->value != NULL) {
if (fi->parent->method == FORM_METHOD_INTERNAL)
Strcat(*query, form_quote(f2->value));
else {
#ifdef JP_CHARSET
if (fi->parent->charset != 0)
Strcat(*query,
form_quote(conv_str(f2->value,
InnerCode,
fi->parent->charset)));
else
Strcat(*query,
form_quote(conv_str(f2->value,
InnerCode,
Currentbuf->document_code)));
#else /* not JP_CHARSET */
Strcat(*query, form_quote(f2->value));
#endif /* not JP_CHARSET */
}
}
}
if (f2->next)
Strcat_char(*query, '&');
}
}
if (multipart) {
fprintf(body, "--%s--\r\n", fi->parent->boundary);
fclose(body);
}
else {
/* remove trailing & */
while (Strlastchar(*query) == '&')
Strshrink(*query, 1);
}
}
/* process form */
void
followForm(void)
{
Line *l;
Anchor *a;
char *p;
FormItemList *fi, *f2;
Str tmp = Strnew(), tmp2 = Strnew();
int multipart = 0;
if (Currentbuf->firstLine == NULL)
return;
l = Currentbuf->currentLine;
a = retrieveCurrentForm(Currentbuf);
if (a == NULL)
return;
fi = (FormItemList *) a->url;
switch (fi->type) {
case FORM_INPUT_TEXT:
p = inputStrHist("TEXT:", fi->value ? fi->value->ptr : NULL, TextHist);
if (p == NULL)
return;
fi->value = Strnew_charp(p);
formUpdateBuffer(a, Currentbuf, fi);
if (fi->accept || fi->parent->nitems == 1)
goto do_submit;
break;
case FORM_INPUT_FILE:
p = inputFilenameHist("Filename:", fi->value ? fi->value->ptr : NULL, NULL);
if (p == NULL)
return;
fi->value = Strnew_charp(p);
formUpdateBuffer(a, Currentbuf, fi);
if (fi->accept || fi->parent->nitems == 1)
goto do_submit;
break;
case FORM_INPUT_PASSWORD:
p = inputLine("TEXT:", fi->value ? fi->value->ptr : NULL, IN_PASSWORD);
if (p == NULL)
return;
fi->value = Strnew_charp(p);
formUpdateBuffer(a, Currentbuf, fi);
if (fi->accept)
goto do_submit;
break;
case FORM_TEXTAREA:
if (fi->rows == 1) {
p = inputStrHist("TEXT:", fi->value ? fi->value->ptr : NULL, TextHist);
if (p == NULL)
return;
fi->value = Strnew_charp(p);
}
else
input_textarea(fi);
formUpdateBuffer(a, Currentbuf, fi);
break;
case FORM_INPUT_RADIO:
form_recheck_radio(fi, Currentbuf, do_update_form_radio);
break;
case FORM_INPUT_CHECKBOX:
fi->checked = !fi->checked;
formUpdateBuffer(a, Currentbuf, fi);
break;
#ifdef MENU_SELECT
case FORM_SELECT:
formChooseOptionByMenu(fi,
Currentbuf->cursorX - Currentbuf->pos + a->start.pos,
Currentbuf->cursorY);
formUpdateBuffer(a, Currentbuf, fi);
break;
#endif /* MENU_SELECT */
case FORM_INPUT_IMAGE:
case FORM_INPUT_SUBMIT:
case FORM_INPUT_BUTTON:
do_submit:
multipart = (fi->parent->method == FORM_METHOD_POST &&
fi->parent->enctype == FORM_ENCTYPE_MULTIPART);
query_from_followform(&tmp, fi, multipart);
tmp2 = Strdup(fi->parent->action);
if (!Strcmp_charp(tmp2, "!CURRENT_URL!")) {
/* It means "current URL" */
tmp2 = parsedURL2Str(&Currentbuf->currentURL);
}
if (fi->parent->method == FORM_METHOD_GET) {
Strcat_charp(tmp2, "?");
Strcat(tmp2, tmp);
loadLink(tmp2->ptr, a->target, NULL, NULL);
}
else if (fi->parent->method == FORM_METHOD_POST) {
Buffer *buf;
if (multipart) {
struct stat st;
stat(fi->parent->body, &st);
fi->parent->length = st.st_size;
}
else {
fi->parent->body = tmp->ptr;
fi->parent->length = tmp->length;
}
buf = loadLink(tmp2->ptr, a->target, NULL, fi->parent);
if (multipart) {
unlink(fi->parent->body);
}
if (buf && !(buf->bufferprop & BP_REDIRECTED)) { /* buf must be Currentbuf */
/* BP_REDIRECTED means that the buffer is obtained through
* Location: header. In this case, buf->form_submit must not be set
* because the page is not loaded by POST method but GET method.
*/
buf->form_submit = save_submit_formlist(fi);
}
}
else if ((fi->parent->method == FORM_METHOD_INTERNAL &&
Strcmp_charp(fi->parent->action,"map") == 0) ||
Currentbuf->bufferprop & BP_INTERNAL) { /* internal */
do_internal(tmp2->ptr, tmp->ptr);
return;
}
else {
disp_err_message("Can't send form because of illegal method.", FALSE);
}
break;
case FORM_INPUT_RESET:
for (f2 = fi->parent->item; f2; f2 = f2->next) {
if (f2->name && f2->value &&
f2->type != FORM_INPUT_RADIO &&
f2->type != FORM_INPUT_CHECKBOX &&
f2->type != FORM_INPUT_SUBMIT &&
f2->type != FORM_INPUT_HIDDEN &&
f2->type != FORM_INPUT_RESET) {
f2->value = Strnew();
formUpdateBuffer(&Currentbuf->formitem->anchors[f2->anchor_num], Currentbuf, f2);
}
}
break;
case FORM_INPUT_HIDDEN:
default:
break;
}
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
static void
drawAnchorCursor0(Buffer * buf, int hseq, int prevhseq, int tline, int eline, int active)
{
int i, j;
Line *l;
Anchor *an;
l = buf->topLine;
for (j = 0; j < buf->href->nanchor; j++) {
an = &buf->href->anchors[j];
if (an->start.line < tline)
continue;
if (an->start.line >= eline)
return;
for (;; l = l->next) {
if (l == NULL)
return;
if (l->linenumber == an->start.line)
break;
}
if (hseq >= 0 && an->hseq == hseq) {
for (i = an->start.pos; i < an->end.pos; i++) {
if (l->propBuf[i] & (PE_IMAGE | PE_ANCHOR | PE_FORM)) {
if (active)
l->propBuf[i] |= PE_ACTIVE;
else
l->propBuf[i] &= ~PE_ACTIVE;
}
}
if (active)
redrawLineRegion(buf, l, l->linenumber - tline,
an->start.pos, an->end.pos);
}
else if (prevhseq >= 0 && an->hseq == prevhseq) {
if (active)
redrawLineRegion(buf, l, l->linenumber - tline,
an->start.pos, an->end.pos);
}
}
}
void
drawAnchorCursor(Buffer * buf)
{
Anchor *an;
int hseq, prevhseq;
int tline, eline;
if (buf->firstLine == NULL)
return;
if (buf->href == NULL)
return;
an = retrieveCurrentAnchor(buf);
if (an != NULL)
hseq = an->hseq;
else
hseq = -1;
tline = buf->topLine->linenumber;
eline = tline + LASTLINE;
prevhseq = buf->hmarklist->prevhseq;
drawAnchorCursor0(buf, hseq, prevhseq, tline, eline, 1);
drawAnchorCursor0(buf, hseq, -1, tline, eline, 0);
buf->hmarklist->prevhseq = hseq;
}
/* underline an anchor if cursor is on the anchor. */
void
onA(void)
{
drawAnchorCursor(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
/* go to the top anchor */
void
topA(void)
{
HmarkerList *hl = Currentbuf->hmarklist;
BufferPoint *po;
Anchor *an;
int hseq;
if (Currentbuf->firstLine == NULL)
return;
if (!hl || hl->nmark == 0)
return;
hseq = 0;
do {
if (hseq >= hl->nmark)
return;
po = hl->marks + hseq;
an = retrieveAnchor(Currentbuf->href, po->line, po->pos);
if (an == NULL)
an = retrieveAnchor(Currentbuf->formitem, po->line, po->pos);
hseq++;
} while (an == NULL);
gotoLine(Currentbuf, po->line);
Currentbuf->pos = po->pos;
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
/* go to the last anchor */
void
lastA(void)
{
HmarkerList *hl = Currentbuf->hmarklist;
BufferPoint *po;
Anchor *an;
int hseq;
if (Currentbuf->firstLine == NULL)
return;
if (!hl || hl->nmark == 0)
return;
hseq = hl->nmark - 1;
do {
if (hseq < 0)
return;
po = hl->marks + hseq;
an = retrieveAnchor(Currentbuf->href, po->line, po->pos);
if (an == NULL)
an = retrieveAnchor(Currentbuf->formitem, po->line, po->pos);
hseq--;
} while (an == NULL);
gotoLine(Currentbuf, po->line);
Currentbuf->pos = po->pos;
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
/* go to the next anchor */
void
nextA(void)
{
HmarkerList *hl = Currentbuf->hmarklist;
BufferPoint *po;
Anchor *an, *pan;
int i, x, y;
if (Currentbuf->firstLine == NULL)
return;
if (!hl || hl->nmark == 0)
return;
an = retrieveCurrentAnchor(Currentbuf);
if (an == NULL)
an = retrieveCurrentForm(Currentbuf);
y = Currentbuf->currentLine->linenumber;
x = Currentbuf->pos;
for (i = 0; i < PREC_NUM; i++) {
pan = an;
if (an && an->hseq >= 0) {
int hseq = an->hseq + 1;
do {
if (hseq >= hl->nmark) {
pan = an;
goto _end;
}
po = &hl->marks[hseq];
an = retrieveAnchor(Currentbuf->href, po->line, po->pos);
if (an == NULL)
an = retrieveAnchor(Currentbuf->formitem, po->line, po->pos);
hseq++;
} while (an == NULL || an == pan);
}
else {
an = closest_next_anchor(Currentbuf->href, NULL, x, y);
an = closest_next_anchor(Currentbuf->formitem, an, x, y);
if (an == NULL) {
an = pan;
break;
}
x = an->start.pos;
y = an->start.line;
}
}
_end:
if (an == NULL || an->hseq < 0)
return;
po = &hl->marks[an->hseq];
gotoLine(Currentbuf, po->line);
Currentbuf->pos = po->pos;
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
/* go to the previous anchor */
void
prevA(void)
{
HmarkerList *hl = Currentbuf->hmarklist;
BufferPoint *po;
Anchor *an, *pan;
int i, x, y;
if (Currentbuf->firstLine == NULL)
return;
if (!hl || hl->nmark == 0)
return;
an = retrieveCurrentAnchor(Currentbuf);
if (an == NULL)
an = retrieveCurrentForm(Currentbuf);
y = Currentbuf->currentLine->linenumber;
x = Currentbuf->pos;
for (i = 0; i < PREC_NUM; i++) {
pan = an;
if (an && an->hseq >= 0) {
int hseq = an->hseq - 1;
do {
if (hseq < 0) {
an = pan;
goto _end;
}
po = hl->marks + hseq;
an = retrieveAnchor(Currentbuf->href, po->line, po->pos);
if (an == NULL)
an = retrieveAnchor(Currentbuf->formitem, po->line, po->pos);
hseq--;
} while (an == NULL || an == pan);
}
else {
an = closest_prev_anchor(Currentbuf->href, NULL, x, y);
an = closest_prev_anchor(Currentbuf->formitem, an, x, y);
if (an == NULL) {
an = pan;
break;
}
x = an->start.pos;
y = an->start.line;
}
}
_end:
if (an == NULL || an->hseq < 0)
return;
po = hl->marks + an->hseq;
gotoLine(Currentbuf, po->line);
Currentbuf->pos = po->pos;
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_NORMAL);
}
static int
checkBackBuffer(Buffer * buf)
{
Buffer *fbuf = buf->linkBuffer[LB_N_FRAME];
if (fbuf) {
if (fbuf->frameQ)
return TRUE; /* Currentbuf has stacked frames */
/* when no frames stacked and next is frame source, try next's
nextBuffer */
if (RenderFrame && fbuf == buf->nextBuffer) {
if (fbuf->nextBuffer != NULL)
return TRUE;
else
return FALSE;
}
}
if (buf->nextBuffer)
return TRUE;
return FALSE;
}
/* delete current buffer and back to the previous buffer */
void
backBf(void)
{
Buffer *buf = Currentbuf->linkBuffer[LB_N_FRAME];
if (!checkBackBuffer(Currentbuf)) {
disp_message("Can't back...", TRUE);
return;
}
delBuffer(Currentbuf);
if (buf) {
if (buf->frameQ) {
long linenumber;
short pos;
struct frameset *fs;
fs = popFrameTree(&(buf->frameQ), &linenumber, &pos);
deleteFrameSet(buf->frameset);
buf->frameset = fs;
if (buf == Currentbuf) {
rFrame();
gotoLine(Currentbuf, linenumber);
arrangeCursor(Currentbuf);
}
} else if (RenderFrame && buf == Currentbuf) {
delBuffer(Currentbuf);
}
}
clear();
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
void
deletePrevBuf()
{
Buffer *buf = Currentbuf->nextBuffer;
if (buf)
delBuffer(buf);
}
static void
cmd_loadURL(char *url, ParsedURL * current)
{
Buffer *buf;
if (!strncasecmp(url, "mailto:", 7)) {
/* invoke external mailer */
Str tmp;
char *to = quoteShell(url + 7)->ptr;
if (strcasestr(Mailer, "%s"))
tmp = Sprintf(Mailer, to);
else
tmp = Strnew_m_charp(Mailer, " ", to, NULL);
fmTerm();
system(tmp->ptr);
fmInit();
displayBuffer(Currentbuf, B_FORCE_REDRAW);
return;
}
#ifdef USE_NNTP
else if (!strncasecmp(url, "news:", 5) &&
strchr(url, '@') == NULL) {
/* news:newsgroup is not supported */
disp_err_message("news:newsgroup_name is not supported", TRUE);
return;
}
#endif /* USE_NNTP */
/* message(Sprintf("loading %s\n", url)->ptr, 0, 0); */
refresh();
buf = loadGeneralFile(url, current, NO_REFERER, 0, NULL);
if (buf == NULL) {
char *emsg = Sprintf("Can't load %s\n", url)->ptr;
disp_err_message(emsg, FALSE);
}
else if (buf != NO_BUFFER) {
pushBuffer(buf);
if (RenderFrame && Currentbuf->frameset != NULL)
rFrame();
}
displayBuffer(Currentbuf, B_NORMAL);
}
/* go to specified URL */
void
goURL(void)
{
char *url;
ParsedURL p_url;
url = searchKeyData();
if (url == NULL) {
if (!(Currentbuf->bufferprop & BP_INTERNAL))
pushHashHist(URLHist, parsedURL2Str(&Currentbuf->currentURL)->ptr);
url = inputLineHist("Goto URL: ", NULL, IN_URL, URLHist);
if (url != NULL)
SKIP_BLANKS(url);
}
if (url == NULL || *url == '\0') {
displayBuffer(Currentbuf, B_FORCE_REDRAW);
return;
}
if (*url == '#') {
gotoLabel(url + 1);
return;
}
parseURL2(url, &p_url, NULL);
pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr);
cmd_loadURL(url, baseURL(Currentbuf));
}
static void
cmd_loadBuffer(Buffer * buf, int prop, int link)
{
if (buf == NULL) {
disp_err_message("Can't load string", FALSE);
}
else if (buf != NO_BUFFER) {
buf->bufferprop |= (BP_INTERNAL | prop);
if (!(buf->bufferprop & BP_NO_URL))
copyParsedURL(&buf->currentURL, &Currentbuf->currentURL);
if (link != LB_NOLINK) {
buf->linkBuffer[REV_LB[link]] = Currentbuf;
Currentbuf->linkBuffer[link] = buf;
}
pushBuffer(buf);
}
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
/* load bookmark */
void
ldBmark(void)
{
cmd_loadURL(BookmarkFile, NULL);
}
/* Add current to bookmark */
void
adBmark(void)
{
Str url, title, tmp;
/* cmd_loadBuffer(load_bookmark_panel(Currentbuf), BP_NO_URL, *
* LB_NOLINK); */
url = form_quote(parsedURL2Str(&Currentbuf->currentURL));
title = form_quote(Strnew_charp(Currentbuf->buffername));
#ifdef __EMX__
tmp = Sprintf("%s/w3mbookmark.exe?mode=panel&bmark=%s&url=%s&title=%s",
get_os2_dft("W3M_LIB_DIR", LIB_DIR), BookmarkFile, url->ptr, title->ptr);
#else /* not __EMX__ */
tmp = Sprintf("%s/w3mbookmark?mode=panel&bmark=%s&url=%s&title=%s",
LIB_DIR, BookmarkFile, url->ptr, title->ptr);
#endif /* not __EMX__ */
cmd_loadURL(tmp->ptr, NULL);
}
/* option setting */
void
ldOpt(void)
{
cmd_loadBuffer(load_option_panel(), BP_NO_URL, LB_NOLINK);
}
/* error message list */
void
msgs(void)
{
cmd_loadBuffer(message_list_panel(), BP_NO_URL, LB_NOLINK);
}
/* page info */
void
pginfo(void)
{
Buffer *buf;
if ((buf = Currentbuf->linkBuffer[LB_N_INFO]) != NULL) {
Currentbuf = buf;
displayBuffer(Currentbuf, B_NORMAL);
return;
}
if ((buf = Currentbuf->linkBuffer[LB_INFO]) != NULL)
delBuffer(buf);
buf = page_info_panel(Currentbuf);
#ifdef JP_CHARSET
if (buf != NULL)
buf->document_code = Currentbuf->document_code;
#endif /* JP_CHARSET */
cmd_loadBuffer(buf, BP_NORMAL, LB_INFO);
}
void
follow_map(struct parsed_tagarg *arg)
{
#ifdef MENU_MAP
Anchor *a;
char *url;
int x;
ParsedURL p_url;
a = retrieveCurrentImg(Currentbuf);
if (a != NULL)
x = Currentbuf->cursorX - Currentbuf->pos + a->start.pos;
else
x = Currentbuf->cursorX;
url = follow_map_menu(Currentbuf, arg, x, Currentbuf->cursorY + 2);
if (url == NULL || *url == '\0')
return;
if (*url == '#') {
gotoLabel(url + 1);
return;
}
parseURL2(url, &p_url, baseURL(Currentbuf));
pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr);
cmd_loadURL(url, baseURL(Currentbuf));
#else
Buffer *buf;
buf = follow_map_panel(Currentbuf, arg);
if (buf != NULL)
cmd_loadBuffer(buf, BP_NORMAL, LB_NOLINK);
#endif
}
#ifdef USE_COOKIE
/* cookie list */
void
cooLst(void)
{
Buffer *buf;
buf = cookie_list_panel();
if (buf != NULL)
cmd_loadBuffer(buf, BP_NO_URL, LB_NOLINK);
}
#endif /* USE_COOKIE */
#ifdef USE_HISTORY
/* History page */
void
ldHist(void)
{
cmd_loadBuffer(historyBuffer(URLHist), BP_NO_URL, LB_NOLINK);
}
#endif /* USE_HISTORY */
/* download HREF link */
void
svA(void)
{
CurrentKeyData = NULL; /* not allowed in w3m-control: */
do_download = TRUE;
followA();
do_download = FALSE;
}
/* download IMG link */
void
svI(void)
{
CurrentKeyData = NULL; /* not allowed in w3m-control: */
do_download = TRUE;
followI();
do_download = FALSE;
}
/* save buffer */
void
svBuf(void)
{
char *file;
FILE *f;
int is_pipe;
CurrentKeyData = NULL; /* not allowed in w3m-control: */
file = searchKeyData();
if (file == NULL || *file == '\0') {
file = inputLineHist("Save buffer to: ", NULL, IN_COMMAND, SaveHist);
if (file == NULL || *file == '\0') {
displayBuffer(Currentbuf, B_FORCE_REDRAW);
return;
}
}
if (*file == '|') {
is_pipe = TRUE;
f = popen(file + 1, "w");
}
else {
file = expandName(file);
if (checkOverWrite(file) < 0)
return;
f = fopen(file, "w");
is_pipe = FALSE;
}
if (f == NULL) {
char *emsg = Sprintf("Can't open %s\n", file)->ptr;
disp_err_message(emsg, TRUE);
return;
}
saveBuffer(Currentbuf, f);
if (is_pipe)
pclose(f);
else
fclose(f);
displayBuffer(Currentbuf, B_NORMAL);
}
/* save source */
void
svSrc(void)
{
if (Currentbuf->sourcefile == NULL)
return;
CurrentKeyData = NULL; /* not allowed in w3m-control: */
PermitSaveToPipe = TRUE;
doFileCopy(Currentbuf->sourcefile,
guess_save_name(Currentbuf->currentURL.file));
PermitSaveToPipe = FALSE;
displayBuffer(Currentbuf, B_NORMAL);
}
static void
_peekURL(int only_img){
Anchor *a;
ParsedURL pu;
static Str s = NULL;
static int offset = 0;
if (Currentbuf->firstLine == NULL)
return;
if (CurrentKey == prev_key && s != NULL) {
if (s->length - offset >= COLS)
offset++;
else if (s->length <= offset) /* bug ? */
offset = 0;
goto disp;
} else {
offset = 0;
}
a = (only_img ? NULL : retrieveCurrentAnchor(Currentbuf));
if (a == NULL) {
a = retrieveCurrentImg(Currentbuf);
if (a == NULL) {
a = retrieveCurrentForm(Currentbuf);
if (a == NULL)
return;
s = Strnew_charp(form2str((FormItemList *) a->url));
goto disp;
}
}
parseURL2(a->url, &pu, baseURL(Currentbuf));
s = parsedURL2Str(&pu);
disp:
if (PREC_NUM > 1 && s->length > (PREC_NUM - 1) * (COLS - 1))
disp_message_nomouse(&s->ptr[(PREC_NUM - 1) * (COLS - 1)], TRUE);
else
disp_message_nomouse(&s->ptr[offset], TRUE);
}
/* peek URL */
void
peekURL(void)
{
_peekURL(0);
}
/* peek URL of image */
void
peekIMG(void)
{
_peekURL(1);
}
/* show current URL */
static Str
currentURL(void)
{
if (Currentbuf->bufferprop & BP_INTERNAL)
return Strnew_size(0);
return parsedURL2Str(&Currentbuf->currentURL);
}
void
curURL(void)
{
static Str s = NULL;
static int offset = 0;
if (Currentbuf->bufferprop & BP_INTERNAL)
return;
if (CurrentKey == prev_key && s != NULL) {
if (s->length - offset >= COLS)
offset++;
else if (s->length <= offset) /* bug ? */
offset = 0;
} else {
offset = 0;
s = currentURL();
}
if (PREC_NUM > 1 && s->length > (PREC_NUM - 1) * (COLS - 1))
disp_message_nomouse(&s->ptr[(PREC_NUM - 1) * (COLS - 1)], TRUE);
else
disp_message_nomouse(&s->ptr[offset], TRUE);
}
/* view HTML source */
void
vwSrc(void)
{
char *fn;
Buffer *buf;
if (Currentbuf->type == NULL ||
Currentbuf->bufferprop & BP_FRAME)
return;
if ((buf = Currentbuf->linkBuffer[LB_SOURCE]) != NULL ||
(buf = Currentbuf->linkBuffer[LB_N_SOURCE]) != NULL) {
Currentbuf = buf;
displayBuffer(Currentbuf, B_NORMAL);
return;
}
if (Currentbuf->sourcefile == NULL) {
if (Currentbuf->pagerSource &&
!strcasecmp(Currentbuf->type, "text/plain")) {
FILE *f;
Str tmpf = tmpfname(TMPF_SRC, NULL);
f = fopen(tmpf->ptr, "w");
if (f == NULL)
return;
saveBufferDelNum(Currentbuf, f, showLineNum);
fclose(f);
fn = tmpf->ptr;
}
else {
return;
}
} else if (Currentbuf->real_scheme == SCM_LOCAL) {
fn = Currentbuf->filename;
} else {
fn = Currentbuf->sourcefile;
}
if (!strcasecmp(Currentbuf->type, "text/html")) {
#ifdef JP_CHARSET
char old_code = DocumentCode;
DocumentCode = Currentbuf->document_code;
#endif
buf = loadFile(fn);
#ifdef JP_CHARSET
DocumentCode = old_code;
#endif
if (buf == NULL)
return;
buf->type = "text/plain";
if (Currentbuf->real_type &&
!strcasecmp(Currentbuf->real_type, "text/html"))
buf->real_type = "text/plain";
else
buf->real_type = Currentbuf->real_type;
buf->bufferprop |= BP_SOURCE;
buf->buffername = Sprintf("source of %s", Currentbuf->buffername)->ptr;
buf->linkBuffer[LB_N_SOURCE] = Currentbuf;
Currentbuf->linkBuffer[LB_SOURCE] = buf;
}
else if (!strcasecmp(Currentbuf->type, "text/plain")) {
char *old_type = DefaultType;
DefaultType = "text/html";
buf = loadGeneralFile(fn, NULL, NO_REFERER, 0, NULL);
DefaultType = old_type;
if (buf == NULL || buf == NO_BUFFER)
return;
if (Currentbuf->real_type &&
!strcasecmp(Currentbuf->real_type, "text/plain"))
buf->real_type = "text/html";
else
buf->real_type = Currentbuf->real_type;
if (!strcmp(buf->buffername, mybasename(fn)))
buf->buffername = Sprintf("HTML view of %s", Currentbuf->buffername)->ptr;
buf->linkBuffer[LB_SOURCE] = Currentbuf;
Currentbuf->linkBuffer[LB_N_SOURCE] = buf;
}
else {
return;
}
buf->currentURL = Currentbuf->currentURL;
buf->real_scheme = Currentbuf->real_scheme;
buf->sourcefile = Currentbuf->sourcefile;
buf->clone = Currentbuf->clone;
(*buf->clone)++;
pushBuffer(buf);
displayBuffer(Currentbuf, B_NORMAL);
}
/* reload */
void
reload(void)
{
Buffer *buf, *fbuf = NULL;
char *type = Currentbuf->type;
Str url;
int top, linenum, cursorY, pos, currentColumn;
FormList *request;
int multipart;
if (Currentbuf->bufferprop & BP_INTERNAL) {
disp_err_message("Can't reload...", FALSE);
return;
}
if (Currentbuf->currentURL.scheme == SCM_LOCAL &&
!strcmp(Currentbuf->currentURL.file, "-")) {
/* file is std input */
disp_err_message("Can't reload stdin", TRUE);
return;
}
if (Currentbuf->firstLine == NULL) {
top = 1;
linenum = 1;
} else {
top = Currentbuf->topLine->linenumber;
linenum = Currentbuf->currentLine->linenumber;
}
cursorY = Currentbuf->cursorY;
pos = Currentbuf->pos;
currentColumn = Currentbuf->currentColumn;
if (Currentbuf->bufferprop & BP_FRAME &&
(fbuf = Currentbuf->linkBuffer[LB_N_FRAME])) {
if (fmInitialized) {
message("Rendering frame", 0, 0);
refresh();
}
if (!(buf = renderFrame(fbuf, 1)))
return;
if (fbuf->linkBuffer[LB_FRAME]) {
if (buf->sourcefile &&
fbuf->linkBuffer[LB_FRAME]->sourcefile &&
!strcmp(buf->sourcefile,
fbuf->linkBuffer[LB_FRAME]->sourcefile))
fbuf->linkBuffer[LB_FRAME]->sourcefile = NULL;
delBuffer(fbuf->linkBuffer[LB_FRAME]);
}
fbuf->linkBuffer[LB_FRAME] = buf;
buf->linkBuffer[LB_N_FRAME] = fbuf;
pushBuffer(buf);
Currentbuf = buf;
if (Currentbuf->firstLine == NULL) {
displayBuffer(Currentbuf, B_FORCE_REDRAW);
return;
}
gotoLine(Currentbuf, linenum);
Currentbuf->pos = pos;
Currentbuf->currentColumn = currentColumn;
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_FORCE_REDRAW);
return;
}
else if (Currentbuf->frameset != NULL)
fbuf = Currentbuf->linkBuffer[LB_FRAME];
multipart = 0;
if (Currentbuf->form_submit) {
request = Currentbuf->form_submit->parent;
if (request->method == FORM_METHOD_POST
&& request->enctype == FORM_ENCTYPE_MULTIPART) {
Str query;
struct stat st;
multipart = 1;
query_from_followform(&query, Currentbuf->form_submit, multipart);
stat(request->body, &st);
request->length = st.st_size;
}
}
else {
request = NULL;
}
url = parsedURL2Str(&Currentbuf->currentURL);
message("Reloading...", 0, 0);
refresh();
buf = loadGeneralFile(url->ptr, NULL, NO_REFERER, RG_NOCACHE, request);
if (multipart)
unlink(request->body);
if (buf == NULL) {
disp_err_message("Can't reload...", FALSE);
return;
}
else if (buf == NO_BUFFER) {
return;
}
buf->form_submit = Currentbuf->form_submit;
if (fbuf != NULL)
Firstbuf = deleteBuffer(Firstbuf, fbuf);
repBuffer(Currentbuf, buf);
if ((type != NULL) && (buf->type != NULL) &&
((!strcasecmp(buf->type, "text/plain") &&
!strcasecmp(type, "text/html")) ||
(!strcasecmp(buf->type, "text/html") &&
!strcasecmp(type, "text/plain")))) {
vwSrc();
if (Currentbuf != buf)
Firstbuf = deleteBuffer(Firstbuf, buf);
}
if (Currentbuf->firstLine == NULL) {
displayBuffer(Currentbuf, B_FORCE_REDRAW);
return;
}
Currentbuf->topLine = lineSkip(Currentbuf, Currentbuf->firstLine, top - 1, FALSE);
gotoLine(Currentbuf, linenum);
Currentbuf->pos = pos;
Currentbuf->currentColumn = currentColumn;
arrangeCursor(Currentbuf);
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
/* mark URL-like patterns as anchors */
void
chkURL(void)
{
static char *url_like_pat[] =
{
"http://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./?=~_\\&+@#,\\$]*",
#ifdef USE_SSL
"https://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./?=~_\\&+@#,\\$]*",
#endif /* USE_SSL */
#ifdef USE_GOPHER
"gopher://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./_]*",
#endif /* USE_GOPHER */
"ftp://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./=_+@#,\\$]*",
#ifdef USE_NNTP
"news:[^<> ][^<> ]*",
"nntp://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./_]*",
#endif /* USE_NNTP */
NULL,
};
int i;
for (i = 0; url_like_pat[i]; i++) {
reAnchor(Currentbuf, url_like_pat[i]);
}
Currentbuf->check_url |= CHK_URL;
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
#ifdef USE_NNTP
/* mark Message-ID-like patterns as NEWS anchors */
void
chkNMID(void)
{
static char *url_like_pat[] =
{
"<[^<> ][^<> ]*@[A-z0-9\\.\\-_][A-z0-9\\.\\-_]*>",
NULL,
};
int i;
for (i = 0; url_like_pat[i]; i++) {
reAnchorNews(Currentbuf, url_like_pat[i]);
}
Currentbuf->check_url |= CHK_NMID;
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
#endif /* USE_NNTP */
/* render frame */
void
rFrame(void)
{
Buffer *buf;
if ((buf = Currentbuf->linkBuffer[LB_FRAME]) != NULL) {
Currentbuf = buf;
displayBuffer(Currentbuf, B_NORMAL);
return;
}
if (Currentbuf->frameset == NULL) {
if ((buf = Currentbuf->linkBuffer[LB_N_FRAME]) != NULL) {
Currentbuf = buf;
displayBuffer(Currentbuf, B_NORMAL);
}
return;
}
if (fmInitialized) {
message("Rendering frame", 0, 0);
refresh();
}
buf = renderFrame(Currentbuf, 0);
if (buf == NULL)
return;
buf->linkBuffer[LB_N_FRAME] = Currentbuf;
Currentbuf->linkBuffer[LB_FRAME] = buf;
pushBuffer(buf);
if (fmInitialized && display_ok)
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
/* spawn external browser */
static void
invoke_browser(char *url)
{
Str tmp;
char *browser = NULL;
int bg = 0;
CurrentKeyData = NULL; /* not allowed in w3m-control: */
browser = searchKeyData();
if (browser == NULL || *browser == '\0') {
switch (prec_num) {
case 0:
case 1:
browser = ExtBrowser;
break;
case 2:
browser = ExtBrowser2;
break;
case 3:
browser = ExtBrowser3;
break;
}
if (browser == NULL || *browser == '\0') {
browser = inputStr("Browse command: ", NULL);
if (browser == NULL || *browser == '\0')
return;
}
}
url = quoteShell(url)->ptr;
if (strcasestr(browser, "%s")) {
tmp = Sprintf(browser, url);
Strremovetrailingspaces(tmp);
if (Strlastchar(tmp) == '&') {
Strshrink(tmp, 1);
bg = 1;
}
}
else {
tmp = Strnew_charp(browser);
Strcat_char(tmp, ' ');
Strcat_charp(tmp, url);
}
fmTerm();
mySystem(tmp->ptr, bg);
fmInit();
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
void
extbrz()
{
if (Currentbuf->bufferprop & BP_INTERNAL) {
disp_err_message("Can't browse...", FALSE);
return;
}
if (Currentbuf->currentURL.scheme == SCM_LOCAL &&
!strcmp(Currentbuf->currentURL.file, "-")) {
/* file is std input */
disp_err_message("Can't browse stdin", TRUE);
return;
}
invoke_browser(parsedURL2Str(&Currentbuf->currentURL)->ptr);
}
void
linkbrz()
{
Anchor *a;
ParsedURL pu;
if (Currentbuf->firstLine == NULL)
return;
a = retrieveCurrentAnchor(Currentbuf);
if (a == NULL)
return;
parseURL2(a->url, &pu, baseURL(Currentbuf));
invoke_browser(parsedURL2Str(&pu)->ptr);
}
/* show current line number and number of lines in the entire document */
void
curlno()
{
Str tmp;
int cur = 0, all, col, len = 0;
if (Currentbuf->currentLine != NULL) {
Line *l = Currentbuf->currentLine;
cur = l->real_linenumber;
if (l->width < 0)
l->width = COLPOS(l, l->len);
len = l->width;
}
col = Currentbuf->currentColumn + Currentbuf->cursorX + 1;
all = (Currentbuf->lastLine ? Currentbuf->lastLine->real_linenumber : Currentbuf->allLine);
if (all == 0 && Currentbuf->lastLine != NULL)
all = Currentbuf->currentLine->real_linenumber;
if (all == 0)
all = 1;
if (Currentbuf->pagerSource && !(Currentbuf->bufferprop & BP_CLOSE))
tmp = Sprintf("line %d col %d/%d", cur, col, len);
else
tmp = Sprintf("line %d/%d (%d%%) col %d/%d",
cur, all, cur * 100 / all, col, len);
#ifdef JP_CHARSET
Strcat_charp(tmp, " ");
Strcat_charp(tmp, code_to_str(Currentbuf->document_code));
#endif /* not JP_CHARSET */
disp_message(tmp->ptr, FALSE);
}
#ifdef MOUSE
/* Addition:mouse event */
#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
#define MOUSE_SCROLL_LINE 5
static void
process_mouse(int btn, int x, int y)
{
int delta_x, delta_y, i;
static int press_btn = MOUSE_BTN_RESET, press_x, press_y;
if (btn == MOUSE_BTN_UP) {
switch (press_btn) {
case MOUSE_BTN1_DOWN:
if (press_x != x || press_y != y) {
delta_x = x - press_x;
delta_y = y - press_y;
if (abs(delta_x) < abs(delta_y) / 3)
delta_x = 0;
if (abs(delta_y) < abs(delta_x) / 3)
delta_y = 0;
if (reverse_mouse) {
delta_y = -delta_y;
delta_x = -delta_x;
}
if (delta_y > 0) {
prec_num = delta_y;
ldown1();
}
else if (delta_y < 0) {
prec_num = -delta_y;
lup1();
}
if (delta_x > 0) {
prec_num = delta_x;
col1L();
}
else if (delta_x < 0) {
prec_num = -delta_x;
col1R();
}
}
else {
if (y == LASTLINE) {
switch (x) {
case 0:
case 1:
backBf();
break;
case 2:
case 3:
pgBack();
break;
case 4:
case 5:
pgFore();
break;
}
return;
}
if (y == Currentbuf->cursorY &&
(x == Currentbuf->cursorX
#ifdef JP_CHARSET
|| (Currentbuf->currentLine != NULL &&
(Currentbuf->currentLine->propBuf[Currentbuf->pos] & PC_KANJI1)
&& x == Currentbuf->cursorX + 1)
#endif /* JP_CHARSET */
)) {
followA();
return;
}
cursorXY(Currentbuf, x, y);
displayBuffer(Currentbuf, B_NORMAL);
}
break;
case MOUSE_BTN2_DOWN:
backBf();
break;
case MOUSE_BTN3_DOWN:
#ifdef MENU
cursorXY(Currentbuf, x, y);
onA();
mainMenu(x, y);
#endif /* MENU */
break;
case MOUSE_BTN4_DOWN_RXVT:
for (i = 0; i < MOUSE_SCROLL_LINE; i++)
ldown1();
break;
case MOUSE_BTN5_DOWN_RXVT:
for (i = 0; i < MOUSE_SCROLL_LINE; i++)
lup1();
break;
}
} else if (btn == MOUSE_BTN4_DOWN_XTERM) {
for (i = 0; i < MOUSE_SCROLL_LINE; i++)
ldown1();
} else if (btn == MOUSE_BTN5_DOWN_XTERM) {
for (i = 0; i < MOUSE_SCROLL_LINE; i++)
lup1();
}
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;
}
}
void
msToggle(void)
{
if (use_mouse) {
use_mouse = FALSE;
}
else {
use_mouse = TRUE;
}
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
void
mouse()
{
int btn, x, y;
btn = (unsigned char) getch() - 32;
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;
process_mouse(btn, x, y);
}
#ifdef USE_GPM
int
gpm_process_mouse(Gpm_Event * event, void *data)
{
int btn, 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;
process_mouse(btn, x - 1, y - 1);
return 0;
}
#endif /* USE_GPM */
#ifdef USE_SYSMOUSE
int
sysm_process_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;
process_mouse(btn, x, y);
return 0;
}
#endif /* USE_SYSMOUSE */
#endif /* MOUSE */
void
wrapToggle(void)
{
if (WrapSearch) {
WrapSearch = FALSE;
disp_message("Wrap search off", FALSE);
}
else {
WrapSearch = TRUE;
disp_message("Wrap search on", FALSE);
}
}
#ifdef DICT
static char *
GetWord(Buffer * buf)
{
Line *l = buf->currentLine;
char *lb = l->lineBuf;
int i, b, e, pos = buf->pos;
i = pos;
while (!IS_ALPHA(lb[i]) && i >= 0)
i--;
pos = i;
while (IS_ALPHA(lb[i]) && i >= 0)
i--;
i++;
if (!IS_ALPHA(lb[i]))
return NULL;
b = i;
i = pos;
while (IS_ALPHA(lb[i]) && i <= l->len - 1)
i++;
e = i - 1;
return Strnew_charp_n(&lb[b], e - b + 1)->ptr;
}
static void
execdict(char *word)
{
Buffer *buf;
Str cmd, bn;
MySignalHandler(*prevtrap) ();
if (word == NULL || *word == '\0') {
displayBuffer(Currentbuf, B_NORMAL);
return;
}
cmd = Strnew_charp(DICTCMD);
Strcat_char(cmd, ' ');
Strcat_charp(cmd, word);
prevtrap = signal(SIGINT, intTrap);
crmode();
buf = getshell(cmd->ptr);
bn = Sprintf("%s %s", DICTBUFFERNAME, word);
buf->buffername = bn->ptr;
buf->filename = word;
signal(SIGINT, prevtrap);
term_raw();
if (buf == NULL) {
disp_message("Execution failed", FALSE);
}
else if (buf->firstLine == NULL) {
/* if the dictionary doesn't describe the word. */
disp_message(Sprintf("Word \"%s\" Not Found", word)->ptr, FALSE);
}
else {
buf->bufferprop |= (BP_INTERNAL | BP_NO_URL);
pushBuffer(buf);
}
displayBuffer(Currentbuf, B_FORCE_REDRAW);
}
void
dictword(void)
{
execdict(inputStr("(dictionary)!", ""));
}
void
dictwordat(void)
{
execdict(GetWord(Currentbuf));
}
#endif /* DICT */
char *
searchKeyData(void)
{
KeyListItem *item;
if (CurrentKeyData != NULL && *CurrentKeyData != '\0')
return allocStr(CurrentKeyData, 0);
#ifdef MENU
if (CurrentMenuData != NULL && *CurrentMenuData != '\0')
return allocStr(CurrentMenuData, 0);
#endif
if (CurrentKey < 0)
return NULL;
item = searchKeyList(&w3mKeyList, CurrentKey);
if (item == NULL || item->data == NULL || *item->data == '\0')
return NULL;
return allocStr(item->data, 0);
}
#if 0
static int
searchKeyNum(void)
{
char *d;
int n = 1;
d = searchKeyData();
if (d != NULL)
n = atoi(d);
return n * PREC_NUM;
}
#endif