| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721 |
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #include <ctype.h>
- #include <stdarg.h>
- #include "vt.h"
- #include "misc.h"
- #include "xio.h"
- #include "vbi.h"
- #include "fdset.h"
- #include "search.h"
- #include "export.h"
- #include "ui.h"
- static void vtwin_event(struct vtwin *w, struct vt_event *ev);
- static void msg(struct vtwin *w, u8 *str, ...);
- static void err(struct vtwin *w, u8 *str, ...);
- #define hist(w,o) ((w)->hist + (((w)->hist_top + (o)) & (N_HISTORY-1)))
- static int inc_hex(int i, int bcd_mode)
- {
- i++;
- if (bcd_mode)
- {
- if ((i & 0x000f) > 0x0009)
- i = (i + 0x0010) & 0x0ff0;
- if ((i & 0x00f0) > 0x090)
- i = (i + 0x0100) & 0x0f00;
- if ((i & 0x0f00) > 0x0900)
- i = (i + 0x1000) & 0xf000;
- }
- return i;
- }
- static int dec_hex(int i, int bcd_mode)
- {
- i--;
- if (bcd_mode)
- {
- if ((i & 0x000f) > 0x0009)
- i = (i & 0xfff0) + 0x0009;
- if ((i & 0x00f0) > 0x0090)
- i = (i & 0xff00) + 0x0099;
- if ((i & 0x0f00) > 0x0900)
- i = (i & 0xf000) + 0x0999;
- }
- return i;
- }
- static void set_title(struct vtwin *w)
- {
- char buf[32], buf2[32];
- if (w->subno == ANY_SUB)
- sprintf(buf, "%x", w->pgno);
- else
- sprintf(buf, "%x/%x", w->pgno, w->subno);
- if (w->searching)
- sprintf(buf2, "(%s)", buf);
- else
- sprintf(buf2, "%s", buf);
- xio_title(w->xw, buf2);
- }
- static void query_page(struct vtwin *w, int pgno, int subno)
- {
- w->pgno = pgno;
- w->subno = subno;
- w->searching = 1;
- w->hold = 0; //subno != ANY_SUB;
- xio_set_concealed(w->xw, w->revealed = 0);
- if (hist(w, 0)->pgno != pgno ||
- (hist(w,0)->subno == ANY_SUB && subno != ANY_SUB))
- w->hist_top++;
- hist(w, 0)->pgno = pgno;
- hist(w, 0)->subno = subno;
- hist(w, 1)->pgno = 0; // end marker
- xio_cancel_selection(w->xw);
- if (vbi_query_page(w->vbi, pgno, subno) == 0)
- {
- w->vtp = 0;
- }
- set_title(w);
- }
- static void new_or_query(struct vtwin *w, int pgno, int subno, int new_win)
- {
- if (new_win)
- {
- if (w->child)
- query_page(w->child, pgno, subno);
- else
- vtwin_new(w->xw->xio, w->vbi, 0, w, pgno, subno);
- }
- else
- query_page(w, pgno, subno);
- }
- static int _next_pgno(int *arg, struct vt_page *vtp)
- {
- int pgno = vtp->pgno;
- if (arg[0] == pgno) // want different page
- return 0;
- if (arg[1]) // and not a hex page
- for (; pgno; pgno >>=4)
- if ((pgno & 15) > 9)
- return 0;
- return 1;
- }
- static int _next_subno(int *arg, struct vt_page *vtp)
- {
- return vtp->pgno == arg[0]; // only subpages of this page
- }
- static void do_next_pgno(struct vtwin *w, int dir, int bcd_mode, int subs,
- int new_win)
- {
- struct vt_page *vtp;
- struct vtwin *cw = (new_win && w->child) ? w->child : w;
- int pgno = cw->pgno;
- int subno = cw->subno;
- if (w->vbi->cache)
- {
- int arg[2];
- arg[0] = pgno;
- arg[1] = bcd_mode;
- if (vtp = w->vbi->cache->op->foreach_pg(w->vbi->cache,
- pgno, subno, dir, subs ? _next_subno:_next_pgno, &arg))
- {
- new_or_query(w, vtp->pgno, subs ? vtp->subno : ANY_SUB, new_win);
- return;
- }
- }
- err(w, "No page.");
- }
- #define notdigit(x) (not isdigit((x)))
- static int chk_screen_fromto(u8 *p, int x, int *n1, int *n2)
- {
- p += x;
- if (x >= 0 && x+5 < 42)
- if (notdigit(p[1]) || notdigit(p[0]))
- if (isdigit(p[2]))
- if (p[3] == '/' || p[3] == ':')
- if (isdigit(p[4]))
- if (notdigit(p[5]) || notdigit(p[6])) /* p[6] is save here */
- {
- *n1 = p[2] % 16;
- if (isdigit(p[1]))
- *n1 += p[1] % 16 * 16;
- *n2 = p[4] % 16;
- if (isdigit(p[5]))
- *n2 = *n2 * 16 + p[5] % 16;
- return 1;
- }
- return 0;
- }
- static int chk_screen_pgno(u8 *p, int x, int *pgno, int *subno)
- {
- p += x;
- if (x >= 0 && x+4 < 42)
- if (notdigit(p[0]) && notdigit(p[4]))
- if (isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]))
- {
- *pgno = p[1] % 16 * 256 + p[2] % 16 * 16 + p[3] % 16;
- if (*pgno >= 0x100 && *pgno <= 0x999)
- {
- *subno = ANY_SUB;
- if (x+6 < 42)
- if (p[4] == '.' || p[4] == '/')
- if (isdigit(p[5]))
- if (notdigit(p[6]) || notdigit(p[7])) /* p[7] is save here */
- {
- *subno = p[5] % 16;
- if (isdigit(p[6]))
- *subno = *subno * 16 + p[6] % 16;
- }
- // hackhackhack:
- // pgno followed by start box gets subno 1
- if (x+4 < 42 && p[4] == 11)
- *subno = 1;
- return 1;
- }
- }
- return 0;
- }
- static void do_screen_pgno(struct vtwin *w, int x, int y, int new_win)
- {
- u8 buf[42];
- int n1, n2, i;
- if (x >= 0 && x < 40)
- {
- if (xio_get_line(w->xw, y, buf+1) == 0)
- {
- buf[0] = buf[41] = ' ';
- x++;
- for (i = -6; i < 35; i++)
- {
- if (w->vtp == 0 || w->vtp->subno != 0)
- if (chk_screen_fromto(buf, x+i, &n1, &n2))
- {
- // subno cycling works wrong with children.
- // so middle button cycles backwards...
- if (w->subno != ANY_SUB)
- n1 = w->subno;
- n1 = new_win ? dec_hex(n1, 1) : inc_hex(n1, 1);
- if (n1 < 1)
- n1 = n2;
- if (n1 > n2)
- n1 = 1;
- new_or_query(w, w->pgno, n1, 0);
- return;
- }
- if (i >= -4)
- if (chk_screen_pgno(buf, x+i, &n1, &n2))
- {
- new_or_query(w, n1, n2, new_win);
- return;
- }
- }
- }
- }
- err(w, "No page.");
- }
- static void do_flof_pgno(struct vtwin *w, int button, int x, int new_win)
- {
- struct vt_page *vtp = w->vtp;
- int lk = 99, i, c;
- if (vtp && vtp->flof)
- {
- switch (button)
- {
- case 1 ... 3:
- for (i = 0; i <= x && i < 40; ++i)
- if ((c = vtp->data[24][i]) < 8) // fg-color code
- lk = c;
- lk = "x\0\1\2\3x\3x"[lk]; // color -> link#
- break;
- case KEY_F(1): lk = 0; break;
- case KEY_F(2): lk = 1; break;
- case KEY_F(3): lk = 2; break;
- case KEY_F(4): lk = 3; break;
- case KEY_F(5): lk = 5; break;
- }
- if (lk < 6 && (vtp->link[lk].pgno & 0xff) != 0xff)
- {
- new_or_query(w, vtp->link[lk].pgno, vtp->link[lk].subno, new_win);
- return;
- }
- }
- else
- {
- switch (button)
- {
- case 1 ... 3: lk = x / 8; break;
- case KEY_F(1): lk = 0; break;
- case KEY_F(2): lk = 1; break;
- case KEY_F(3): lk = 2; break;
- case KEY_F(4): lk = 3; break;
- case KEY_F(5): lk = 4; break;
- }
- switch (lk)
- {
- case 0: new_or_query(w, 0x100, ANY_SUB, new_win); return;
- case 1: do_next_pgno(w, -1, 1, 0, new_win); return;
- case 2: new_or_query(w, 0x900, ANY_SUB, new_win); return;
- case 3: do_next_pgno(w, 1, 1, 0, new_win); return;
- case 4: new_or_query(w, 0x999, ANY_SUB, new_win); return;
- }
- }
- err(w, "No page.");
- }
- static void do_hist_pgno(struct vtwin *w)
- {
- if (hist(w, -1)->pgno)
- {
- w->hist_top--;
- query_page(w, hist(w, 0)->pgno, hist(w, 0)->subno);
- }
- else
- err(w, "Empty history.");
- }
- static void put_head_line(struct vtwin *w, u8 *p)
- {
- char buf[40];
- if (p == 0)
- xio_get_line(w->xw, 0, buf);
- else
- memcpy(buf + 8, p + 8, 32);
- if (w->subno == ANY_SUB)
- sprintf(buf, "\2%3x \5\xb7", w->pgno);
- else
- sprintf(buf, "\2S%02x \5\xb7", w->subno & 0xff);
- if (w->searching)
- buf[0] = 1;
- if (w->hold)
- buf[4] = 'H';
- if (w->xw->concealed)
- buf[6] = '*';
- buf[7] = 7;
- xio_put_line(w->xw, 0, buf);
- }
- static void put_menu_line(struct vtwin *w)
- {
- if (w->status > 0)
- xio_put_line(w->xw, 24, w->statusline);
- else if (w->vtp && w->vtp->flof)
- xio_put_line(w->xw, 24, w->vtp->data[24]);
- else
- xio_put_line(w->xw, 24, "\0 100 \4<< \6Help \4>>\0 999 ");
- }
- static void _msg(struct vtwin *w, u8 *str, va_list args)
- {
- u8 buf[128];
- int i;
- i = vsprintf(buf, str, args);
- if (i > W)
- i = W;
- memset(w->statusline, ' ', W);
- memcpy(w->statusline + (W-i+1)/2, buf, i);
- w->status = 6;
- put_menu_line(w);
- }
- static void msg(struct vtwin *w, u8 *str, ...)
- {
- va_list args;
- va_start(args, str);
- _msg(w, str, args);
- va_end(args);
- }
- static void err(struct vtwin *w, u8 *str, ...)
- {
- va_list args;
- va_start(args, str);
- _msg(w, str, args);
- va_end(args);
- }
- static void next_search(struct vtwin *w, int rev)
- {
- if (w->search)
- {
- int pgno = w->pgno;
- int subno = w->subno;
- int dir = rev ? -w->searchdir : w->searchdir;
- if (search_next(w->search, &pgno, &subno, dir) == 0)
- {
- query_page(w, pgno, subno);
- if (not w->searching && w->search->len)
- xio_set_selection(w->xw, w->search->x, w->search->y,
- w->search->x + w->search->len - 1, w->search->y);
- return;
- }
- else
- err(w, "Pattern not found.");
- }
- else
- err(w, "No search pattern.");
- }
- static void start_search(struct vtwin *w, u8 *string)
- {
- if (not string)
- return;
- if (*string)
- {
- if (w->search)
- search_end(w->search);
- w->search = search_start(w->vbi->cache, string);
- if (w->search == 0)
- {
- err(w, "Bad search pattern.");
- return;
- }
- }
- next_search(w, 0);
- }
- static void start_save2(struct vtwin *w, u8 *name)
- {
- if (name && *name)
- if (export(w->export, w->vtp, name))
- err(w, export_errstr());
- export_close(w->export);
- w->export = 0;
- put_menu_line(w);
- }
- struct vtwin * vtwin_new(struct xio *xio, struct vbi *vbi, char *geom,
- struct vtwin *parent, int pgno, int subno)
- {
- struct vtwin *w;
- if (not(w = malloc(sizeof(*w))))
- goto fail1;
- if (not (w->xw = xio_open_win(xio, geom)))
- goto fail2;
- w->vbi = vbi;
- w->vtp = 0;
- w->search = 0;
- w->export = 0;
- w->parent = parent;
- w->child = 0;
- if (parent && parent->child)
- fatal("internal error: parent already has a child != 0");
- if (parent)
- parent->child = w;
- w->hist_top = 1;
- hist(w,0)->pgno = 0;
- hist(w,1)->pgno = 0;
- w->status = 0;
- xio_set_handler(w->xw, vtwin_event, w);
- vbi_add_handler(w->vbi, vtwin_event, w);
- query_page(w, pgno, subno);
- return w;
- fail2:
- free(w);
- fail1:
- return 0;
- }
- static void vtwin_close(struct vtwin *w)
- {
- if (w->parent)
- w->parent->child = w->child;
- if (w->child)
- w->child->parent = w->parent;
- if (w->search)
- search_end(w->search);
- if (w->export)
- export_close(w->export);
- vbi_del_handler(w->vbi, vtwin_event, w);
- xio_close_win(w->xw, 1);
- free(w);
- }
- static void vtwin_event(struct vtwin *w, struct vt_event *ev)
- {
- struct xio_win *xw = w->xw;
- int i;
- switch (ev->type)
- {
- case EV_CLOSE:
- vtwin_close(w);
- break;
- case EV_TIMER:
- if (w->status > 0 && --w->status == 0)
- put_menu_line(w);
- break;
- case EV_KEY:
- {
- switch (ev->i1)
- {
- case '0' ... '9':
- i = ev->i1 - '0';
- if (w->pgno >= 0x100)
- {
- if (i == 0)
- break;
- w->pgno = i;
- }
- else
- {
- w->pgno = w->pgno * 16 + i;
- if (w->pgno >= 0x100)
- query_page(w, w->pgno, ANY_SUB);
- }
- break;
- case 'q':
- case '\e':
- vtwin_close(w);
- break;
- case 'h':
- query_page(w, 0x900, ANY_SUB);
- break;
- case 'e':
- if (w->vbi->cache)
- {
- i = w->vbi->cache->op->mode(w->vbi->cache,
- CACHE_MODE_ERC, 0);
- w->vbi->cache->op->mode(w->vbi->cache,
- CACHE_MODE_ERC, !i);
- msg(w, "Error reduction %sabled.", i ? "dis" : "en");
- }
- break;
- case 'o':
- if (vtwin_new(xw->xio, w->vbi, 0, 0, w->pgno, w->subno) == 0)
- err(w, "Unable to open new window.");
- break;
- case KEY_RIGHT:
- do_next_pgno(w, 1, not ev->i2, 0, 0);
- break;
- case KEY_LEFT:
- do_next_pgno(w, -1, not ev->i2, 0, 0);
- break;
- case KEY_UP:
- do_next_pgno(w, -1, not ev->i2, 1, 0);
- break;
- case KEY_DOWN:
- do_next_pgno(w, 1, not ev->i2, 1, 0);
- break;
- case '\b':
- do_hist_pgno(w);
- break;
- case ' ':
- w->hold = !w->hold;
- break;
- case 'c':
- vbi_reset(w->vbi);
- break;
- case 'i':
- if (w->vtp && w->vtp->flof &&
- (w->vtp->link[5].pgno & 0xff) != 0xff)
- query_page(w, w->vtp->link[5].pgno,
- w->vtp->link[5].subno);
- else
- query_page(w, 0x100, ANY_SUB);
- break;
- case 'r':
- xio_set_concealed(xw, w->revealed = !w->revealed);
- break;
- case KEY_F(1) ... KEY_F(5):
- do_flof_pgno(w, ev->i1, 0, ev->i2);
- break;
- case 'n':
- next_search(w, 0);
- break;
- case 'N':
- next_search(w, 1);
- break;
- default:
- err(w, "Unused key.");
- break;
- }
- break;
- }
- case EV_RESET:
- {
- if (w->search)
- search_end(w->search);
- w->search = 0;
- query_page(w, w->pgno, w->subno);
- msg(w, "Cache cleared!");
- break;
- }
- case EV_MOUSE:
- {
- if (ev->i1 == 3)
- do_hist_pgno(w);
- else if (ev->i1 == 5) // wheel mouse
- do_next_pgno(w, 1, not ev->i2, 0, 0);
- else if (ev->i1 == 4) // wheel mouse
- do_next_pgno(w, -1, not ev->i2, 0, 0);
- else if (ev->i1 == 7) // dual wheel mouse
- do_next_pgno(w, 1, not ev->i2, 1, 0);
- else if (ev->i1 == 6) // dual wheel mouse
- do_next_pgno(w, -1, not ev->i2, 1, 0);
- else if (ev->i4 == 24)
- do_flof_pgno(w, ev->i1, ev->i3, ev->i1 == 2);
- else if (ev->i4 == 0 && ev->i3 < 5)
- {
- if (ev->i1 == 1)
- w->hold = !w->hold;
- else
- vtwin_new(xw->xio, w->vbi, 0, 0, w->pgno, w->subno);
- }
- else if (ev->i4 == 0 && ev->i3 < 8)
- {
- if (ev->i1 == 2 && w->child)
- w = w->child;
- xio_set_concealed(w->xw, w->revealed = !w->revealed);
- }
- else
- do_screen_pgno(w, ev->i3, ev->i4, ev->i1 == 2);
- break;
- }
- case EV_PAGE:
- {
- struct vt_page *vtp = ev->p1;
- if (0)
- if (vtp->errors)
- printf("errors=%4d\n",vtp->errors);
- if (w->searching || not(w->hold || ev->i1))
- if (vtp->pgno == w->pgno)
- if (w->subno == ANY_SUB || vtp->subno == w->subno)
- {
- w->searching = 0;
- w->vtp = vtp;
- put_head_line(w, vtp->data[0]);
- for (i = 1; i < 24; ++i)
- xio_put_line(w->xw, i, vtp->data[i]);
- put_menu_line(w);
- set_title(w);
- }
- break;
- }
- case EV_HEADER:
- {
- u8 *p = ev->p1;
- int hdr_mag = ev->i1 / 256;
- int flags = ev->i3;
- int mag = w->pgno;
- if (mag >= 0x10)
- mag = mag >> 4;
- if (mag >= 0x10)
- mag = mag >> 4;
- if (flags & PG_OUTOFSEQ)
- p = 0;
- else
- if (~flags & PG_MAGSERIAL)
- if (mag != hdr_mag)
- p = 0;
- put_head_line(w, p);
- break;
- }
- case EV_XPACKET:
- {
- #if 0 /* VPS data (seems to be unused in .de */
- u8 *p = ev->p1;
- if (ev->i1 == 8 && ev->i2 == 30 && p[0]/2 == 1)
- {
- int i;
- int pil, cni, pty, misc;
- for (i = 7; i < 20; ++i)
- p[i] = hamm8(p+i, &ev->i3);
- if (ev->i3 & 0xf000) /* uncorrectable errors */
- break;
- cni = p[9] + p[15]/4*16 + p[16]%4*64 + p[10]%4*256
- + p[16]/4*1024 + p[17]*4096;
- pty = p[18] + p[19]*16;
- pil = p[10]/4 + p[11]*4 + p[12]*64 + p[13]*1024
- + p[14]*16384 + p[15]%4*262144;
- misc = p[7] + p[8]*16;
- err(w, "%02x %04x %05x %02x: %.20s", misc, cni, pil, pty, p+20);
- }
- #endif
- break;
- }
- case EV_ERR:
- {
- char *errmsg = ev->p1;
- if (errmsg != NULL && *errmsg != '\0')
- {
- err(w, errmsg);
- w->status = 30;
- ev->p1 = NULL;
- free(errmsg);
- }
- break;
- }
- }
- }
|