1*e99dc071Stb /* $OpenBSD: engine.c,v 1.30 2023/10/10 09:30:06 tb Exp $ */
273baed14Scanacar /*
373baed14Scanacar * Copyright (c) 2001, 2007 Can Erkin Acar <canacar@openbsd.org>
473baed14Scanacar *
573baed14Scanacar * Permission to use, copy, modify, and distribute this software for any
673baed14Scanacar * purpose with or without fee is hereby granted, provided that the above
773baed14Scanacar * copyright notice and this permission notice appear in all copies.
873baed14Scanacar *
973baed14Scanacar * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1073baed14Scanacar * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1173baed14Scanacar * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1273baed14Scanacar * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1373baed14Scanacar * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1473baed14Scanacar * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1573baed14Scanacar * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1673baed14Scanacar */
1773baed14Scanacar
1873baed14Scanacar
192942b3ebSchl #include <sys/ioctl.h>
2073baed14Scanacar #include <sys/types.h>
2173baed14Scanacar #include <sys/queue.h>
2273baed14Scanacar
2373baed14Scanacar #include <ctype.h>
2473baed14Scanacar #include <curses.h>
2573baed14Scanacar #include <signal.h>
2673baed14Scanacar #include <stdlib.h>
2773baed14Scanacar #include <string.h>
28c2688696Scanacar #include <term.h>
2973baed14Scanacar #include <unistd.h>
3007a32fc5Smillert #include <math.h>
31fcad183eSlum #include <err.h>
3273baed14Scanacar
33c2688696Scanacar /* XXX These are defined in term.h and conflict with our variable names */
34c2688696Scanacar #ifdef columns
35c2688696Scanacar #undef columns
36c2688696Scanacar #endif
37c2688696Scanacar
38c2688696Scanacar #ifdef lines
39c2688696Scanacar #undef lines
40c2688696Scanacar #endif
41c2688696Scanacar
4273baed14Scanacar #include "engine.h"
4373baed14Scanacar
44bc249449Sderaadt #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
4573baed14Scanacar
4673baed14Scanacar /* circular linked list of views */
47e0cad388Skrw TAILQ_HEAD(view_list, view_ent) view_head =
48e0cad388Skrw TAILQ_HEAD_INITIALIZER(view_head);
4973baed14Scanacar struct view_ent {
5073baed14Scanacar field_view *view;
51e0cad388Skrw TAILQ_ENTRY(view_ent) entries;
5273baed14Scanacar };
5373baed14Scanacar
5407a32fc5Smillert static struct timespec ts_delay = { 5, 0 };
5507a32fc5Smillert static struct itimerval it_delay = { { 0, 0 }, { 5, 0 } };
5607a32fc5Smillert
5773baed14Scanacar int dispstart = 0;
58ca743186Smartijn int humanreadable = 0;
5973baed14Scanacar int interactive = 1;
60c7d45d65Sreyk int averageonly = 0;
6173baed14Scanacar int maxprint = 0;
6273baed14Scanacar int paused = 0;
6373baed14Scanacar int rawmode = 0;
6473baed14Scanacar int rawwidth = DEFAULT_WIDTH;
6573baed14Scanacar int sortdir = 1;
6673baed14Scanacar int columns, lines;
6773baed14Scanacar u_int32_t num_disp = 0;
6873baed14Scanacar int max_disp = -1;
6973baed14Scanacar
7073baed14Scanacar volatile sig_atomic_t gotsig_close = 0;
7173baed14Scanacar volatile sig_atomic_t gotsig_resize = 0;
7273baed14Scanacar volatile sig_atomic_t gotsig_alarm = 0;
7373baed14Scanacar int need_update = 0;
7473baed14Scanacar int need_sort = 0;
755c280c62Smpf int separate_thousands = 0;
7673baed14Scanacar
7773baed14Scanacar SCREEN *screen;
7873baed14Scanacar
7973baed14Scanacar field_view *curr_view = NULL;
8073baed14Scanacar struct view_ent *curr_view_ent = NULL;
8173baed14Scanacar struct view_manager *curr_mgr = NULL;
8273baed14Scanacar
8373baed14Scanacar int curr_line = 0;
8473baed14Scanacar int home_line = 0;
8573baed14Scanacar
8673baed14Scanacar /* line buffer for raw mode */
8773baed14Scanacar char linebuf[MAX_LINE_BUF];
8873baed14Scanacar int linepos = 0;
8973baed14Scanacar
9073baed14Scanacar /* temp storage for state printing */
9173baed14Scanacar char tmp_buf[MAX_LINE_BUF];
9273baed14Scanacar
9373baed14Scanacar char cmdbuf[MAX_LINE_BUF];
9473baed14Scanacar int cmd_len = -1;
9573baed14Scanacar struct command *curr_cmd = NULL;
9673baed14Scanacar char *curr_message = NULL;
97d539d1daSmartijn enum message_mode message_mode = MESSAGE_NONE;
98d539d1daSmartijn int message_cont = 1;
9973baed14Scanacar
10073baed14Scanacar void print_cmdline(void);
10173baed14Scanacar
10273baed14Scanacar
10373baed14Scanacar /* screen output functions */
10473baed14Scanacar
10573baed14Scanacar char * tb_ptr = NULL;
10673baed14Scanacar int tb_len = 0;
10773baed14Scanacar
10873baed14Scanacar void
tb_start(void)10973baed14Scanacar tb_start(void)
11073baed14Scanacar {
11173baed14Scanacar tb_ptr = tmp_buf;
11273baed14Scanacar tb_len = sizeof(tmp_buf);
11373baed14Scanacar tb_ptr[0] = '\0';
11473baed14Scanacar }
11573baed14Scanacar
11673baed14Scanacar void
tb_end(void)11773baed14Scanacar tb_end(void)
11873baed14Scanacar {
11973baed14Scanacar tb_ptr = NULL;
12073baed14Scanacar tb_len = 0;
12173baed14Scanacar }
12273baed14Scanacar
12373baed14Scanacar int
tbprintf(char * format,...)12473baed14Scanacar tbprintf(char *format, ...)
12573baed14Scanacar {
12673baed14Scanacar int len;
12773baed14Scanacar va_list arg;
12873baed14Scanacar
12973baed14Scanacar if (tb_ptr == NULL || tb_len <= 0)
13073baed14Scanacar return 0;
13173baed14Scanacar
13273baed14Scanacar va_start(arg, format);
13373baed14Scanacar len = vsnprintf(tb_ptr, tb_len, format, arg);
13473baed14Scanacar va_end(arg);
13573baed14Scanacar
13673baed14Scanacar if (len > tb_len)
13773baed14Scanacar tb_end();
13873baed14Scanacar else if (len > 0) {
13973baed14Scanacar tb_ptr += len;
14073baed14Scanacar tb_len -= len;
14173baed14Scanacar }
14273baed14Scanacar
14373baed14Scanacar return len;
14473baed14Scanacar }
14573baed14Scanacar
1465c280c62Smpf int
tbprintft(char * format,...)1475c280c62Smpf tbprintft(char *format, ...)
1485c280c62Smpf {
1495c280c62Smpf int len;
1505c280c62Smpf va_list arg;
1515c280c62Smpf char buf[MAX_LINE_BUF];
1525c280c62Smpf
1535c280c62Smpf if (tb_ptr == NULL || tb_len <= 0)
1545c280c62Smpf return 0;
1555c280c62Smpf
1565c280c62Smpf va_start(arg, format);
1575c280c62Smpf len = vsnprintf(buf, tb_len, format, arg);
1585c280c62Smpf va_end(arg);
1595c280c62Smpf
1605c280c62Smpf if (len > tb_len)
1615c280c62Smpf tb_end();
1625c280c62Smpf else if (len > 0) {
1635c280c62Smpf int d, s;
1645c280c62Smpf int digits, curdigit;
1655c280c62Smpf
1665c280c62Smpf if (!separate_thousands) {
1675c280c62Smpf strlcpy(tb_ptr, buf, tb_len);
1685c280c62Smpf return len;
1695c280c62Smpf }
1705c280c62Smpf
1715c280c62Smpf /* count until we hit a non digit. (e.g. the prefix) */
1725c280c62Smpf for (digits = 0; digits < len; digits++)
17328ce9ad7Sderaadt if (!isdigit((unsigned char)buf[digits]))
1745c280c62Smpf break;
1755c280c62Smpf
1765c280c62Smpf curdigit = digits;
1775c280c62Smpf d = s = 0;
1785c280c62Smpf /* insert thousands separators while copying */
1795c280c62Smpf while (curdigit && d < tb_len) {
1805c280c62Smpf if (curdigit < digits && curdigit % 3 == 0)
1815c280c62Smpf tb_ptr[d++] = ',';
1825c280c62Smpf tb_ptr[d++] = buf[s++];
1835c280c62Smpf curdigit--;
1845c280c62Smpf }
1855c280c62Smpf /* copy the remaining non-digits */
1865c280c62Smpf while (len > digits && d < tb_len) {
1875c280c62Smpf tb_ptr[d++] = buf[s++];
1885c280c62Smpf digits++;
1895c280c62Smpf }
1905c280c62Smpf tb_ptr[d] = '\0';
1915c280c62Smpf tb_ptr += d;
1925c280c62Smpf tb_len -= d;
1935c280c62Smpf len = d;
1945c280c62Smpf }
1955c280c62Smpf return len;
1965c280c62Smpf }
1975c280c62Smpf
19873baed14Scanacar void
move_horiz(int offset)19973baed14Scanacar move_horiz(int offset)
20073baed14Scanacar {
20173baed14Scanacar if (rawmode) {
20273baed14Scanacar if (offset <= 0)
20373baed14Scanacar linepos = 0;
20473baed14Scanacar else if (offset >= MAX_LINE_BUF)
20573baed14Scanacar linepos = MAX_LINE_BUF - 1;
20673baed14Scanacar else
20773baed14Scanacar linepos = offset;
20873baed14Scanacar } else {
20973baed14Scanacar move(curr_line, offset);
21073baed14Scanacar }
21173baed14Scanacar }
21273baed14Scanacar
21373baed14Scanacar void
print_str(int len,const char * str)21473baed14Scanacar print_str(int len, const char *str)
21573baed14Scanacar {
21673baed14Scanacar if (len <= 0)
21773baed14Scanacar return;
21873baed14Scanacar
21973baed14Scanacar if (rawmode) {
220bc249449Sderaadt int length = MINIMUM(len, MAX_LINE_BUF - linepos);
22173baed14Scanacar if (length <= 0)
22273baed14Scanacar return;
22373baed14Scanacar bcopy(str, &linebuf[linepos], length);
22473baed14Scanacar linepos += length;
22573baed14Scanacar } else
22673baed14Scanacar addnstr(str, len);
22773baed14Scanacar }
22873baed14Scanacar
22973baed14Scanacar void
clear_linebuf(void)23073baed14Scanacar clear_linebuf(void)
23173baed14Scanacar {
23273baed14Scanacar memset(linebuf, ' ', MAX_LINE_BUF);
23373baed14Scanacar }
23473baed14Scanacar
23573baed14Scanacar void
end_line(void)23673baed14Scanacar end_line(void)
23773baed14Scanacar {
23873baed14Scanacar if (rawmode) {
23973baed14Scanacar linebuf[rawwidth] = '\0';
24073baed14Scanacar printf("%s\n", linebuf);
24173baed14Scanacar clear_linebuf();
24273baed14Scanacar }
24373baed14Scanacar curr_line++;
24473baed14Scanacar }
24573baed14Scanacar
24673baed14Scanacar void
end_page(void)24773baed14Scanacar end_page(void)
24873baed14Scanacar {
24973baed14Scanacar if (rawmode) {
25073baed14Scanacar linepos = 0;
25173baed14Scanacar clear_linebuf();
252505a14acSsolene fflush(stdout);
25373baed14Scanacar } else {
25473baed14Scanacar move(home_line, 0);
25573baed14Scanacar print_cmdline();
25673baed14Scanacar refresh();
25773baed14Scanacar }
25873baed14Scanacar curr_line = 0;
25973baed14Scanacar }
26073baed14Scanacar
26173baed14Scanacar /* field output functions */
26273baed14Scanacar
26373baed14Scanacar void
print_fld_str(field_def * fld,const char * str)26473baed14Scanacar print_fld_str(field_def *fld, const char *str)
26573baed14Scanacar {
26607fe0f2dScanacar int len, offset;
26773baed14Scanacar char *cpos;
26873baed14Scanacar
26973baed14Scanacar if (str == NULL || fld == NULL)
27073baed14Scanacar return;
27173baed14Scanacar
27273baed14Scanacar if (fld->start < 0)
27373baed14Scanacar return;
27473baed14Scanacar
27573baed14Scanacar len = strlen(str);
27673baed14Scanacar
27773baed14Scanacar if (len >= fld->width) {
27873baed14Scanacar move_horiz(fld->start);
27973baed14Scanacar print_str(fld->width, str);
28073baed14Scanacar } else {
28173baed14Scanacar switch (fld->align) {
28273baed14Scanacar case FLD_ALIGN_RIGHT:
28373baed14Scanacar move_horiz(fld->start + (fld->width - len));
28473baed14Scanacar break;
28573baed14Scanacar case FLD_ALIGN_CENTER:
28673baed14Scanacar move_horiz(fld->start + (fld->width - len) / 2);
28773baed14Scanacar break;
28873baed14Scanacar case FLD_ALIGN_COLUMN:
28973baed14Scanacar if ((cpos = strchr(str, ':')) == NULL) {
29007fe0f2dScanacar offset = (fld->width - len) / 2;
29173baed14Scanacar } else {
29207fe0f2dScanacar offset = (fld->width / 2) - (cpos - str);
29307fe0f2dScanacar if (offset < 0)
29407fe0f2dScanacar offset = 0;
29507fe0f2dScanacar else if (offset > (fld->width - len))
29607fe0f2dScanacar offset = fld->width - len;
29773baed14Scanacar }
29807fe0f2dScanacar move_horiz(fld->start + offset);
29973baed14Scanacar break;
30073baed14Scanacar default:
30173baed14Scanacar move_horiz(fld->start);
30273baed14Scanacar break;
30373baed14Scanacar }
30473baed14Scanacar print_str(len, str);
30573baed14Scanacar }
30673baed14Scanacar }
30773baed14Scanacar
30873baed14Scanacar void
print_bar_title(field_def * fld)30973baed14Scanacar print_bar_title(field_def *fld)
31073baed14Scanacar {
31173baed14Scanacar char buf[16];
31207fe0f2dScanacar int len, i, d, tr, tw, val, pos, cur;
31373baed14Scanacar
31473baed14Scanacar int divs[] = {20, 10, 5, 4, 3, 2, 1, 0};
31573baed14Scanacar
31673baed14Scanacar if (fld->width < 1)
31773baed14Scanacar return;
31873baed14Scanacar
31973baed14Scanacar len = snprintf(buf, sizeof(buf), " %d\\", fld->arg);
32073baed14Scanacar if (len >= sizeof(buf))
32173baed14Scanacar return;
32273baed14Scanacar
32373baed14Scanacar for (i = 0; divs[i]; i++)
32473baed14Scanacar if (divs[i] * len <= fld->width)
32573baed14Scanacar break;
32673baed14Scanacar
32773baed14Scanacar if (divs[i] == 0) {
32873baed14Scanacar print_fld_str(fld, "*****");
32973baed14Scanacar return;
33073baed14Scanacar }
33173baed14Scanacar
33207fe0f2dScanacar d = divs[i];
33373baed14Scanacar
33473baed14Scanacar val = 0;
33573baed14Scanacar pos = 0;
33607fe0f2dScanacar tr = fld->arg % d;
33707fe0f2dScanacar tw = fld->width % d;
33873baed14Scanacar
33973baed14Scanacar tb_start();
34073baed14Scanacar cur = 0;
34107fe0f2dScanacar for(i = 0; i < d; i++) {
34273baed14Scanacar tw += fld->width;
34373baed14Scanacar tr += fld->arg;
34473baed14Scanacar
34507fe0f2dScanacar while (tr >= d) {
34673baed14Scanacar val++;
34707fe0f2dScanacar tr -= d;
34873baed14Scanacar }
34907fe0f2dScanacar while (tw >= d) {
35073baed14Scanacar pos++;
35107fe0f2dScanacar tw -= d;
35273baed14Scanacar }
35373baed14Scanacar
35473baed14Scanacar len = snprintf(buf, sizeof(buf), "%d\\", val);
355807febabSderaadt if (len >= sizeof(buf))
356807febabSderaadt len = strlen(buf);
35773baed14Scanacar while (cur < pos - len) {
35873baed14Scanacar tbprintf(" ");
35973baed14Scanacar cur++;
36073baed14Scanacar }
36173baed14Scanacar tbprintf("%s", buf);
36273baed14Scanacar cur += len;
36373baed14Scanacar }
36473baed14Scanacar
36573baed14Scanacar print_fld_tb(fld);
36673baed14Scanacar }
36773baed14Scanacar
36873baed14Scanacar void
print_fld_bar(field_def * fld,int value)36973baed14Scanacar print_fld_bar(field_def *fld, int value)
37073baed14Scanacar {
37148556a4dSbenno int i, tw, val;
37273baed14Scanacar
37373baed14Scanacar if (fld->width < 1)
37473baed14Scanacar return;
37573baed14Scanacar
37673baed14Scanacar val = 0;
37773baed14Scanacar tw = fld->arg / 2;
37873baed14Scanacar
37973baed14Scanacar tb_start();
38048556a4dSbenno
38173baed14Scanacar for(i = 0; i < fld->width; i++) {
38273baed14Scanacar tw += fld->arg;
38373baed14Scanacar
38473baed14Scanacar while (tw >= fld->width) {
38573baed14Scanacar val++;
38673baed14Scanacar tw -= fld->width;
38773baed14Scanacar }
38873baed14Scanacar if (val > value)
38973baed14Scanacar break;
39073baed14Scanacar tbprintf("#");
39173baed14Scanacar }
39273baed14Scanacar
39373baed14Scanacar print_fld_tb(fld);
39473baed14Scanacar }
39573baed14Scanacar
39673baed14Scanacar void
print_fld_tb(field_def * fld)39773baed14Scanacar print_fld_tb(field_def *fld)
39873baed14Scanacar {
39973baed14Scanacar print_fld_str(fld, tmp_buf);
40073baed14Scanacar tb_end();
40173baed14Scanacar }
40273baed14Scanacar
40373baed14Scanacar void
print_title(void)40473baed14Scanacar print_title(void)
40573baed14Scanacar {
40673baed14Scanacar field_def **fp;
40773baed14Scanacar
40873baed14Scanacar if (curr_view != NULL && curr_view->view != NULL) {
40973baed14Scanacar for (fp = curr_view->view; *fp != NULL; fp++) {
41073baed14Scanacar switch((*fp)->align) {
41173baed14Scanacar case FLD_ALIGN_LEFT:
41273baed14Scanacar case FLD_ALIGN_RIGHT:
41373baed14Scanacar case FLD_ALIGN_CENTER:
41473baed14Scanacar case FLD_ALIGN_COLUMN:
41573baed14Scanacar print_fld_str(*fp, (*fp)->title);
41673baed14Scanacar break;
41773baed14Scanacar case FLD_ALIGN_BAR:
41873baed14Scanacar print_bar_title(*fp);
41973baed14Scanacar break;
42073baed14Scanacar }
42173baed14Scanacar }
42273baed14Scanacar }
42373baed14Scanacar end_line();
42473baed14Scanacar }
42573baed14Scanacar
42673baed14Scanacar /* view related functions */
42773baed14Scanacar void
hide_field(field_def * fld)42873baed14Scanacar hide_field(field_def *fld)
42973baed14Scanacar {
43073baed14Scanacar if (fld == NULL)
43173baed14Scanacar return;
43273baed14Scanacar
43373baed14Scanacar fld->flags |= FLD_FLAG_HIDDEN;
43473baed14Scanacar }
43573baed14Scanacar
43673baed14Scanacar void
show_field(field_def * fld)43773baed14Scanacar show_field(field_def *fld)
43873baed14Scanacar {
43973baed14Scanacar if (fld == NULL)
44073baed14Scanacar return;
44173baed14Scanacar
44273baed14Scanacar fld->flags &= ~((unsigned int) FLD_FLAG_HIDDEN);
44373baed14Scanacar }
44473baed14Scanacar
44573baed14Scanacar void
reset_fields(void)44673baed14Scanacar reset_fields(void)
44773baed14Scanacar {
44873baed14Scanacar field_def **fp;
44973baed14Scanacar field_def *fld;
45073baed14Scanacar
45173baed14Scanacar if (curr_view == NULL)
45273baed14Scanacar return;
45373baed14Scanacar
45473baed14Scanacar if (curr_view->view == NULL)
45573baed14Scanacar return;
45673baed14Scanacar
45773baed14Scanacar for (fp = curr_view->view; *fp != NULL; fp++) {
45873baed14Scanacar fld = *fp;
45973baed14Scanacar fld->start = -1;
46073baed14Scanacar fld->width = fld->norm_width;
46173baed14Scanacar }
46273baed14Scanacar }
46373baed14Scanacar
46473baed14Scanacar void
field_setup(void)46573baed14Scanacar field_setup(void)
46673baed14Scanacar {
46773baed14Scanacar field_def **fp;
46873baed14Scanacar field_def *fld;
46973baed14Scanacar int st, fwid, change;
47073baed14Scanacar int width = columns;
47173baed14Scanacar
47273baed14Scanacar reset_fields();
47373baed14Scanacar
47473baed14Scanacar dispstart = 0;
47573baed14Scanacar st = 0;
47673baed14Scanacar
47773baed14Scanacar for (fp = curr_view->view; *fp != NULL; fp++) {
47873baed14Scanacar fld = *fp;
47973baed14Scanacar if (fld->flags & FLD_FLAG_HIDDEN)
48073baed14Scanacar continue;
48173baed14Scanacar
48273baed14Scanacar if (width <= 1)
48373baed14Scanacar break;
48473baed14Scanacar
48573baed14Scanacar if (st != 1)
48673baed14Scanacar width--;
48773baed14Scanacar
48873baed14Scanacar fld->start = 1;
48973baed14Scanacar fwid = fld->width;
49073baed14Scanacar st++;
49173baed14Scanacar if (fwid >= width) {
49273baed14Scanacar fld->width = width;
49373baed14Scanacar width = 0;
49473baed14Scanacar } else
49573baed14Scanacar width -= fwid;
49673baed14Scanacar }
49773baed14Scanacar
49873baed14Scanacar while (width > 0) {
49973baed14Scanacar change = 0;
50073baed14Scanacar for (fp = curr_view->view; *fp != NULL; fp++) {
50173baed14Scanacar fld = *fp;
50273baed14Scanacar if (fld->flags & FLD_FLAG_HIDDEN)
50373baed14Scanacar continue;
50473baed14Scanacar if ((fld->width < fld->max_width) &&
50573baed14Scanacar (fld->increment <= width)) {
50673baed14Scanacar int w = fld->width + fld->increment;
50773baed14Scanacar if (w > fld->max_width)
50873baed14Scanacar w = fld->max_width;
50973baed14Scanacar width += fld->width - w;
51073baed14Scanacar fld->width = w;
51173baed14Scanacar change = 1;
51273baed14Scanacar }
51373baed14Scanacar if (width <= 0) break;
51473baed14Scanacar }
51573baed14Scanacar if (change == 0) break;
51673baed14Scanacar }
51773baed14Scanacar
51873baed14Scanacar st = 0;
51973baed14Scanacar for (fp = curr_view->view; *fp != NULL; fp++) {
52073baed14Scanacar fld = *fp;
52173baed14Scanacar if (fld->flags & FLD_FLAG_HIDDEN)
52273baed14Scanacar continue;
52373baed14Scanacar if (fld->start < 0) break;
52473baed14Scanacar fld->start = st;
52573baed14Scanacar st += fld->width + 1;
52673baed14Scanacar }
52773baed14Scanacar }
52873baed14Scanacar
52973baed14Scanacar void
set_curr_view(struct view_ent * ve)53073baed14Scanacar set_curr_view(struct view_ent *ve)
53173baed14Scanacar {
53273baed14Scanacar field_view *v;
53373baed14Scanacar
53473baed14Scanacar reset_fields();
53573baed14Scanacar
53673baed14Scanacar if (ve == NULL) {
53773baed14Scanacar curr_view_ent = NULL;
53873baed14Scanacar curr_view = NULL;
53973baed14Scanacar curr_mgr = NULL;
54073baed14Scanacar return;
54173baed14Scanacar }
54273baed14Scanacar
54373baed14Scanacar v = ve->view;
54473baed14Scanacar
54573baed14Scanacar if ((curr_view != NULL) && (curr_mgr != v->mgr)) {
54673baed14Scanacar gotsig_alarm = 1;
54773baed14Scanacar if (v->mgr != NULL && v->mgr->select_fn != NULL)
54873baed14Scanacar v->mgr->select_fn();
54973baed14Scanacar }
55073baed14Scanacar
55173baed14Scanacar curr_view_ent = ve;
55273baed14Scanacar curr_view = v;
55373baed14Scanacar curr_mgr = v->mgr;
55473baed14Scanacar field_setup();
55573baed14Scanacar need_update = 1;
55673baed14Scanacar }
55773baed14Scanacar
55873baed14Scanacar void
add_view(field_view * fv)55973baed14Scanacar add_view(field_view *fv)
56073baed14Scanacar {
56173baed14Scanacar struct view_ent *ent;
56273baed14Scanacar
56373baed14Scanacar if (fv == NULL)
56473baed14Scanacar return;
56573baed14Scanacar
56673baed14Scanacar if (fv->view == NULL || fv->name == NULL || fv->mgr == NULL)
56773baed14Scanacar return;
56873baed14Scanacar
56973baed14Scanacar ent = malloc(sizeof(struct view_ent));
57073baed14Scanacar if (ent == NULL)
57173baed14Scanacar return;
57273baed14Scanacar
57373baed14Scanacar ent->view = fv;
574e0cad388Skrw TAILQ_INSERT_TAIL(&view_head, ent, entries);
57573baed14Scanacar
57673baed14Scanacar if (curr_view == NULL)
57773baed14Scanacar set_curr_view(ent);
57873baed14Scanacar }
57973baed14Scanacar
58073baed14Scanacar int
set_view(const char * opt)5813185e9c1Scanacar set_view(const char *opt)
58273baed14Scanacar {
58373baed14Scanacar struct view_ent *ve, *vm = NULL;
58473baed14Scanacar field_view *v;
58573baed14Scanacar int len;
58673baed14Scanacar
58773baed14Scanacar if (opt == NULL || (len = strlen(opt)) == 0)
58873baed14Scanacar return 1;
58973baed14Scanacar
590e0cad388Skrw TAILQ_FOREACH(ve, &view_head, entries) {
59173baed14Scanacar v = ve->view;
59273baed14Scanacar if (strncasecmp(opt, v->name, len) == 0) {
59373baed14Scanacar if (vm)
59473baed14Scanacar return 1;
59573baed14Scanacar vm = ve;
59673baed14Scanacar }
59773baed14Scanacar }
59873baed14Scanacar
59973baed14Scanacar if (vm) {
60073baed14Scanacar set_curr_view(vm);
60173baed14Scanacar return 0;
60273baed14Scanacar }
60373baed14Scanacar
60473baed14Scanacar return 1;
60573baed14Scanacar }
60673baed14Scanacar
60773baed14Scanacar void
foreach_view(void (* callback)(field_view *))60873baed14Scanacar foreach_view(void (*callback)(field_view *))
60973baed14Scanacar {
61073baed14Scanacar struct view_ent *ve;
61173baed14Scanacar
612e0cad388Skrw TAILQ_FOREACH(ve, &view_head, entries) {
61373baed14Scanacar callback(ve->view);
61473baed14Scanacar }
61573baed14Scanacar }
61673baed14Scanacar
61773baed14Scanacar int
set_view_hotkey(int ch)61873baed14Scanacar set_view_hotkey(int ch)
61973baed14Scanacar {
62073baed14Scanacar struct view_ent *ve;
62173baed14Scanacar field_view *v;
62273baed14Scanacar int key = tolower(ch);
62373baed14Scanacar
624e0cad388Skrw TAILQ_FOREACH(ve, &view_head, entries) {
62573baed14Scanacar v = ve->view;
62673baed14Scanacar if (key == v->hotkey) {
62773baed14Scanacar set_curr_view(ve);
62873baed14Scanacar return 1;
62973baed14Scanacar }
63073baed14Scanacar }
63173baed14Scanacar
63273baed14Scanacar return 0;
63373baed14Scanacar }
63473baed14Scanacar
63573baed14Scanacar void
next_view(void)63673baed14Scanacar next_view(void)
63773baed14Scanacar {
63873baed14Scanacar struct view_ent *ve;
63973baed14Scanacar
640e0cad388Skrw if (TAILQ_EMPTY(&view_head) || curr_view_ent == NULL)
64173baed14Scanacar return;
64273baed14Scanacar
643e0cad388Skrw ve = TAILQ_NEXT(curr_view_ent, entries);
644e0cad388Skrw if (ve == NULL)
645e0cad388Skrw ve = TAILQ_FIRST(&view_head);
64673baed14Scanacar
64773baed14Scanacar set_curr_view(ve);
64873baed14Scanacar }
64973baed14Scanacar
65073baed14Scanacar void
prev_view(void)65173baed14Scanacar prev_view(void)
65273baed14Scanacar {
65373baed14Scanacar struct view_ent *ve;
65473baed14Scanacar
655e0cad388Skrw if (TAILQ_EMPTY(&view_head) || curr_view_ent == NULL)
65673baed14Scanacar return;
65773baed14Scanacar
658e0cad388Skrw ve = TAILQ_PREV(curr_view_ent, view_list, entries);
659e0cad388Skrw if (ve == NULL)
660e0cad388Skrw ve = TAILQ_LAST(&view_head, view_list);
66173baed14Scanacar
66273baed14Scanacar set_curr_view(ve);
66373baed14Scanacar }
66473baed14Scanacar
66573baed14Scanacar /* generic field printing */
66673baed14Scanacar
66773baed14Scanacar void
print_fld_age(field_def * fld,unsigned int age)66873baed14Scanacar print_fld_age(field_def *fld, unsigned int age)
66973baed14Scanacar {
67073baed14Scanacar int len;
67173baed14Scanacar unsigned int h, m, s;
67273baed14Scanacar
67373baed14Scanacar if (fld == NULL)
67473baed14Scanacar return;
67573baed14Scanacar len = fld->width;
67673baed14Scanacar
67773baed14Scanacar if (len < 1)
67873baed14Scanacar return;
67973baed14Scanacar
68073baed14Scanacar s = age % 60;
68173baed14Scanacar m = age / 60;
68273baed14Scanacar h = m / 60;
68373baed14Scanacar m %= 60;
68473baed14Scanacar
68573baed14Scanacar tb_start();
68673baed14Scanacar if (tbprintf("%02u:%02u:%02u", h, m, s) <= len)
68773baed14Scanacar goto ok;
68873baed14Scanacar
68953852b85Scanacar tb_start();
69073baed14Scanacar if (tbprintf("%u", age) <= len)
69173baed14Scanacar goto ok;
69273baed14Scanacar
69353852b85Scanacar tb_start();
69473baed14Scanacar age /= 60;
69573baed14Scanacar if (tbprintf("%um", age) <= len)
69673baed14Scanacar goto ok;
69773baed14Scanacar if (age == 0)
69873baed14Scanacar goto err;
69973baed14Scanacar
70053852b85Scanacar tb_start();
70173baed14Scanacar age /= 60;
70273baed14Scanacar if (tbprintf("%uh", age) <= len)
70373baed14Scanacar goto ok;
70473baed14Scanacar if (age == 0)
70573baed14Scanacar goto err;
70673baed14Scanacar
70753852b85Scanacar tb_start();
70873baed14Scanacar age /= 24;
70973baed14Scanacar if (tbprintf("%ud", age) <= len)
71073baed14Scanacar goto ok;
71173baed14Scanacar
71273baed14Scanacar err:
71373baed14Scanacar print_fld_str(fld, "*");
71473baed14Scanacar tb_end();
71573baed14Scanacar return;
71673baed14Scanacar
71773baed14Scanacar ok:
71873baed14Scanacar print_fld_tb(fld);
71973baed14Scanacar }
72073baed14Scanacar
72173baed14Scanacar void
print_fld_sdiv(field_def * fld,u_int64_t size,int d)72207fe0f2dScanacar print_fld_sdiv(field_def *fld, u_int64_t size, int d)
72373baed14Scanacar {
72473baed14Scanacar int len;
725ca743186Smartijn char *mult = "KMGTPE";
726ca743186Smartijn int i = -1;
72773baed14Scanacar
72873baed14Scanacar if (fld == NULL)
72973baed14Scanacar return;
73073baed14Scanacar
73173baed14Scanacar len = fld->width;
73273baed14Scanacar if (len < 1)
73373baed14Scanacar return;
73473baed14Scanacar
735ca743186Smartijn if (humanreadable) {
736ca743186Smartijn while (size >= 10000 && sizeof(mult) >= i + 1) {
737ca743186Smartijn i++;
73807fe0f2dScanacar size /= d;
739ca743186Smartijn }
740ca743186Smartijn tb_start();
741ca743186Smartijn if (tbprintft("%llu%.1s", size, i == -1 ? "" : mult + i) <= len)
74273baed14Scanacar goto ok;
74373baed14Scanacar goto err;
744ca743186Smartijn }
745ca743186Smartijn do {
74653852b85Scanacar tb_start();
747ca743186Smartijn if (tbprintft("%llu%.1s", size, i == -1 ? "" : mult + i) <= len)
74873baed14Scanacar goto ok;
749ca743186Smartijn i++;
75007fe0f2dScanacar size /= d;
751ca743186Smartijn } while (size != 0 && sizeof(mult) >= i);
75273baed14Scanacar err:
753ca743186Smartijn tb_start();
75473baed14Scanacar print_fld_str(fld, "*");
75573baed14Scanacar tb_end();
75673baed14Scanacar return;
75773baed14Scanacar
75873baed14Scanacar ok:
75973baed14Scanacar print_fld_tb(fld);
76073baed14Scanacar }
76173baed14Scanacar
76273baed14Scanacar void
print_fld_size(field_def * fld,u_int64_t size)76373baed14Scanacar print_fld_size(field_def *fld, u_int64_t size)
76473baed14Scanacar {
76573baed14Scanacar print_fld_sdiv(fld, size, 1024);
76673baed14Scanacar }
76773baed14Scanacar
76873baed14Scanacar void
print_fld_ssdiv(field_def * fld,int64_t size,int d)76907fe0f2dScanacar print_fld_ssdiv(field_def *fld, int64_t size, int d)
7707d8d30a0Scanacar {
7717d8d30a0Scanacar int len;
7727d8d30a0Scanacar
7737d8d30a0Scanacar if (fld == NULL)
7747d8d30a0Scanacar return;
7757d8d30a0Scanacar
7767d8d30a0Scanacar len = fld->width;
7777d8d30a0Scanacar if (len < 1)
7787d8d30a0Scanacar return;
7797d8d30a0Scanacar
7807d8d30a0Scanacar tb_start();
7815c280c62Smpf if (tbprintft("%lld", size) <= len)
7827d8d30a0Scanacar goto ok;
7837d8d30a0Scanacar
7847d8d30a0Scanacar tb_start();
78507fe0f2dScanacar size /= d;
7865c280c62Smpf if (tbprintft("%lldK", size) <= len)
7877d8d30a0Scanacar goto ok;
7887d8d30a0Scanacar if (size == 0)
7897d8d30a0Scanacar goto err;
7907d8d30a0Scanacar
7917d8d30a0Scanacar tb_start();
79207fe0f2dScanacar size /= d;
7935c280c62Smpf if (tbprintft("%lldM", size) <= len)
7947d8d30a0Scanacar goto ok;
7957d8d30a0Scanacar if (size == 0)
7967d8d30a0Scanacar goto err;
7977d8d30a0Scanacar
7987d8d30a0Scanacar tb_start();
79907fe0f2dScanacar size /= d;
8005c280c62Smpf if (tbprintft("%lldG", size) <= len)
8017d8d30a0Scanacar goto ok;
8027d8d30a0Scanacar if (size == 0)
8037d8d30a0Scanacar goto err;
8047d8d30a0Scanacar
8057d8d30a0Scanacar tb_start();
80607fe0f2dScanacar size /= d;
8075c280c62Smpf if (tbprintft("%lldT", size) <= len)
8087d8d30a0Scanacar goto ok;
8097d8d30a0Scanacar
8107d8d30a0Scanacar err:
8117d8d30a0Scanacar print_fld_str(fld, "*");
8127d8d30a0Scanacar tb_end();
8137d8d30a0Scanacar return;
8147d8d30a0Scanacar
8157d8d30a0Scanacar ok:
8167d8d30a0Scanacar print_fld_tb(fld);
8177d8d30a0Scanacar }
8187d8d30a0Scanacar
8197d8d30a0Scanacar void
print_fld_ssize(field_def * fld,int64_t size)8207d8d30a0Scanacar print_fld_ssize(field_def *fld, int64_t size)
8217d8d30a0Scanacar {
8227d8d30a0Scanacar print_fld_ssdiv(fld, size, 1024);
8237d8d30a0Scanacar }
8247d8d30a0Scanacar
8257d8d30a0Scanacar void
print_fld_rate(field_def * fld,double rate)82673baed14Scanacar print_fld_rate(field_def *fld, double rate)
82773baed14Scanacar {
82873baed14Scanacar if (rate < 0) {
82973baed14Scanacar print_fld_str(fld, "*");
83073baed14Scanacar } else {
83173baed14Scanacar print_fld_size(fld, rate);
83273baed14Scanacar }
83373baed14Scanacar }
83473baed14Scanacar
83573baed14Scanacar void
print_fld_bw(field_def * fld,double bw)83673baed14Scanacar print_fld_bw(field_def *fld, double bw)
83773baed14Scanacar {
83873baed14Scanacar if (bw < 0) {
83973baed14Scanacar print_fld_str(fld, "*");
84073baed14Scanacar } else {
84173baed14Scanacar print_fld_sdiv(fld, bw, 1000);
84273baed14Scanacar }
84373baed14Scanacar }
84473baed14Scanacar
84573baed14Scanacar void
print_fld_uint(field_def * fld,unsigned int size)84673baed14Scanacar print_fld_uint(field_def *fld, unsigned int size)
84773baed14Scanacar {
84873baed14Scanacar int len;
84973baed14Scanacar
85073baed14Scanacar if (fld == NULL)
85173baed14Scanacar return;
85273baed14Scanacar
85373baed14Scanacar len = fld->width;
85473baed14Scanacar if (len < 1)
85573baed14Scanacar return;
85673baed14Scanacar
85773baed14Scanacar tb_start();
8585c280c62Smpf if (tbprintft("%u", size) > len)
85973baed14Scanacar print_fld_str(fld, "*");
86073baed14Scanacar else
86173baed14Scanacar print_fld_tb(fld);
86273baed14Scanacar tb_end();
86373baed14Scanacar }
86473baed14Scanacar
865dfea33b3Snaddy void
print_fld_float(field_def * fld,double f,int prec)866dfea33b3Snaddy print_fld_float(field_def *fld, double f, int prec)
867dfea33b3Snaddy {
868dfea33b3Snaddy int len;
869dfea33b3Snaddy
870dfea33b3Snaddy if (fld == NULL)
871dfea33b3Snaddy return;
872dfea33b3Snaddy
873dfea33b3Snaddy len = fld->width;
874dfea33b3Snaddy if (len < 1)
875dfea33b3Snaddy return;
876dfea33b3Snaddy
877dfea33b3Snaddy tb_start();
878dfea33b3Snaddy if (tbprintf("%*.*f", len, prec, f) > len)
879dfea33b3Snaddy print_fld_str(fld, "*");
880dfea33b3Snaddy else
881dfea33b3Snaddy print_fld_tb(fld);
882dfea33b3Snaddy tb_end();
883dfea33b3Snaddy }
884dfea33b3Snaddy
88573baed14Scanacar
88673baed14Scanacar /* ordering */
88773baed14Scanacar
8888d6a960aSmartijn int
foreach_order(void (* callback)(order_type *))8898d6a960aSmartijn foreach_order(void (*callback)(order_type *))
8908d6a960aSmartijn {
8918d6a960aSmartijn order_type *o;
8928d6a960aSmartijn
8938d6a960aSmartijn if (curr_view == NULL || curr_view->mgr == NULL ||
8948d6a960aSmartijn curr_view->mgr->order_list == NULL)
8958d6a960aSmartijn return -1;
8968d6a960aSmartijn o = curr_view->mgr->order_list;
8978d6a960aSmartijn do {
8988d6a960aSmartijn callback(o++);
8998d6a960aSmartijn } while (o->name != NULL);
9008d6a960aSmartijn return 0;
9018d6a960aSmartijn }
9028d6a960aSmartijn
90373baed14Scanacar void
set_order(const char * opt)9043185e9c1Scanacar set_order(const char *opt)
90573baed14Scanacar {
90673baed14Scanacar order_type *o;
90773baed14Scanacar
90873baed14Scanacar if (curr_view == NULL || curr_view->mgr == NULL)
90973baed14Scanacar return;
91073baed14Scanacar
91173baed14Scanacar curr_view->mgr->order_curr = curr_view->mgr->order_list;
91273baed14Scanacar
91373baed14Scanacar if (opt == NULL)
91473baed14Scanacar return;
91573baed14Scanacar
91673baed14Scanacar o = curr_view->mgr->order_list;
91773baed14Scanacar
91873baed14Scanacar if (o == NULL)
91973baed14Scanacar return;
92073baed14Scanacar
92173baed14Scanacar for (;o->name != NULL; o++) {
92273baed14Scanacar if (strcasecmp(opt, o->match) == 0) {
92373baed14Scanacar curr_view->mgr->order_curr = o;
92473baed14Scanacar return;
92573baed14Scanacar }
92673baed14Scanacar }
92773baed14Scanacar }
92873baed14Scanacar
92973baed14Scanacar int
set_order_hotkey(int ch)93073baed14Scanacar set_order_hotkey(int ch)
93173baed14Scanacar {
93273baed14Scanacar order_type *o;
93373baed14Scanacar int key = ch;
93473baed14Scanacar
93573baed14Scanacar if (curr_view == NULL || curr_view->mgr == NULL)
93673baed14Scanacar return 0;
93773baed14Scanacar
93873baed14Scanacar o = curr_view->mgr->order_list;
93973baed14Scanacar
94073baed14Scanacar if (o == NULL)
94173baed14Scanacar return 0;
94273baed14Scanacar
94373baed14Scanacar for (;o->name != NULL; o++) {
94473baed14Scanacar if (key == o->hotkey) {
94573baed14Scanacar if (curr_view->mgr->order_curr == o) {
94673baed14Scanacar sortdir *= -1;
94773baed14Scanacar } else {
94873baed14Scanacar curr_view->mgr->order_curr = o;
94973baed14Scanacar }
95073baed14Scanacar return 1;
95173baed14Scanacar }
95273baed14Scanacar }
95373baed14Scanacar
95473baed14Scanacar return 0;
95573baed14Scanacar }
95673baed14Scanacar
95773baed14Scanacar void
next_order(void)95873baed14Scanacar next_order(void)
95973baed14Scanacar {
96073baed14Scanacar order_type *o, *oc;
96173baed14Scanacar
962f3f02087Scanacar if (curr_view->mgr->order_list == NULL)
963f3f02087Scanacar return;
964f3f02087Scanacar
96573baed14Scanacar oc = curr_view->mgr->order_curr;
96673baed14Scanacar
96773baed14Scanacar for (o = curr_view->mgr->order_list; o->name != NULL; o++) {
96873baed14Scanacar if (oc == o) {
96973baed14Scanacar o++;
97073baed14Scanacar if (o->name == NULL)
97173baed14Scanacar break;
97273baed14Scanacar curr_view->mgr->order_curr = o;
97373baed14Scanacar return;
97473baed14Scanacar }
97573baed14Scanacar }
97673baed14Scanacar
97773baed14Scanacar curr_view->mgr->order_curr = curr_view->mgr->order_list;
97873baed14Scanacar }
97973baed14Scanacar
98073baed14Scanacar
98173baed14Scanacar /* main program functions */
98273baed14Scanacar
98373baed14Scanacar int
read_view(void)98473baed14Scanacar read_view(void)
98573baed14Scanacar {
98673baed14Scanacar if (curr_mgr == NULL)
98773baed14Scanacar return (0);
98873baed14Scanacar
98973baed14Scanacar if (paused)
99073baed14Scanacar return (0);
99173baed14Scanacar
99273baed14Scanacar if (curr_mgr->read_fn != NULL)
99373baed14Scanacar return (curr_mgr->read_fn());
99473baed14Scanacar
99573baed14Scanacar return (0);
99673baed14Scanacar }
99773baed14Scanacar
99873baed14Scanacar
99973baed14Scanacar int
disp_update(void)100073baed14Scanacar disp_update(void)
100173baed14Scanacar {
100207fe0f2dScanacar int li;
100373baed14Scanacar
100473baed14Scanacar if (maxprint < 0)
100573baed14Scanacar dispstart = 0;
100673baed14Scanacar else if (dispstart + maxprint > num_disp)
100773baed14Scanacar dispstart = num_disp - maxprint;
100873baed14Scanacar
100973baed14Scanacar if (dispstart < 0)
101073baed14Scanacar dispstart = 0;
101173baed14Scanacar
101273baed14Scanacar if (curr_view == NULL)
101373baed14Scanacar return 0;
101473baed14Scanacar
101573baed14Scanacar if (curr_mgr != NULL) {
101673baed14Scanacar curr_line = 0;
101773baed14Scanacar
101873baed14Scanacar if (curr_mgr->header_fn != NULL) {
101907fe0f2dScanacar li = curr_mgr->header_fn();
102007fe0f2dScanacar if (li < 0)
102173baed14Scanacar return (1);
102207fe0f2dScanacar curr_line = ++li;
102307fe0f2dScanacar home_line = li + maxprint + 1;
102473baed14Scanacar }
102573baed14Scanacar
102673baed14Scanacar print_title();
102773baed14Scanacar
102873baed14Scanacar if (curr_mgr->print_fn != NULL)
102973baed14Scanacar curr_mgr->print_fn();
103073baed14Scanacar }
103173baed14Scanacar
103273baed14Scanacar return (0);
103373baed14Scanacar }
103473baed14Scanacar
103573baed14Scanacar void
sort_view(void)103673baed14Scanacar sort_view(void)
103773baed14Scanacar {
103873baed14Scanacar if (curr_mgr != NULL)
103973baed14Scanacar if (curr_mgr->sort_fn != NULL)
104073baed14Scanacar curr_mgr->sort_fn();
104173baed14Scanacar }
104273baed14Scanacar
104373baed14Scanacar void
sig_close(int sig)104407fe0f2dScanacar sig_close(int sig)
104573baed14Scanacar {
104673baed14Scanacar gotsig_close = 1;
104773baed14Scanacar }
104873baed14Scanacar
104973baed14Scanacar void
sig_resize(int sig)105007fe0f2dScanacar sig_resize(int sig)
105173baed14Scanacar {
105273baed14Scanacar gotsig_resize = 1;
105373baed14Scanacar }
105473baed14Scanacar
105573baed14Scanacar void
sig_alarm(int sig)105607fe0f2dScanacar sig_alarm(int sig)
105773baed14Scanacar {
105873baed14Scanacar gotsig_alarm = 1;
105973baed14Scanacar }
106073baed14Scanacar
106173baed14Scanacar void
setup_term(int dmax)106273baed14Scanacar setup_term(int dmax)
106373baed14Scanacar {
106473baed14Scanacar max_disp = dmax;
106573baed14Scanacar maxprint = dmax;
106673baed14Scanacar
106773baed14Scanacar if (rawmode) {
106873baed14Scanacar columns = rawwidth;
106973baed14Scanacar lines = DEFAULT_HEIGHT;
107073baed14Scanacar clear_linebuf();
107173baed14Scanacar } else {
107273baed14Scanacar if (dmax < 0)
107373baed14Scanacar dmax = 0;
107473baed14Scanacar
107573baed14Scanacar screen = newterm(NULL, stdout, stdin);
107673baed14Scanacar if (screen == NULL) {
107773baed14Scanacar rawmode = 1;
107873baed14Scanacar interactive = 0;
107973baed14Scanacar setup_term(dmax);
108073baed14Scanacar return;
108173baed14Scanacar }
108273baed14Scanacar columns = COLS;
108373baed14Scanacar lines = LINES;
108473baed14Scanacar
108573baed14Scanacar if (maxprint > lines - HEADER_LINES)
108673baed14Scanacar maxprint = lines - HEADER_LINES;
108773baed14Scanacar
108873baed14Scanacar nonl();
108973baed14Scanacar keypad(stdscr, TRUE);
109073baed14Scanacar intrflush(stdscr, FALSE);
109173baed14Scanacar
109273baed14Scanacar halfdelay(10);
109373baed14Scanacar noecho();
109473baed14Scanacar }
109573baed14Scanacar
109673baed14Scanacar if (dmax == 0)
109773baed14Scanacar maxprint = lines - HEADER_LINES;
109873baed14Scanacar
109973baed14Scanacar field_setup();
110073baed14Scanacar }
110173baed14Scanacar
1102c2688696Scanacar void
do_resize_term(void)110381d8c4e1Snicm do_resize_term(void)
1104c2688696Scanacar {
1105c2688696Scanacar struct winsize ws;
1106c2688696Scanacar
1107c2688696Scanacar if (rawmode)
1108c2688696Scanacar return;
1109c2688696Scanacar
1110c2688696Scanacar if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1)
1111c2688696Scanacar return;
1112c2688696Scanacar
1113c2688696Scanacar resizeterm(ws.ws_row, ws.ws_col);
1114c2688696Scanacar
1115c2688696Scanacar columns = COLS;
1116c2688696Scanacar lines = LINES;
1117c2688696Scanacar
1118c2688696Scanacar maxprint = max_disp;
1119c2688696Scanacar
1120c2688696Scanacar if (maxprint == 0 || maxprint > lines - HEADER_LINES)
1121c2688696Scanacar maxprint = lines - HEADER_LINES;
1122c2688696Scanacar
1123c2688696Scanacar clear();
1124c2688696Scanacar
1125c2688696Scanacar field_setup();
1126c2688696Scanacar }
1127c2688696Scanacar
112873baed14Scanacar struct command *
command_set(struct command * cmd,const char * init)112973baed14Scanacar command_set(struct command *cmd, const char *init)
113073baed14Scanacar {
113173baed14Scanacar struct command *prev = curr_cmd;
113273baed14Scanacar
113373baed14Scanacar if (cmd) {
113473baed14Scanacar if (init) {
113573baed14Scanacar cmd_len = strlcpy(cmdbuf, init, sizeof(cmdbuf));
113673baed14Scanacar if (cmd_len >= sizeof(cmdbuf)) {
113773baed14Scanacar cmdbuf[0] = '\0';
113873baed14Scanacar cmd_len = 0;
113973baed14Scanacar }
114073baed14Scanacar } else {
114173baed14Scanacar cmd_len = 0;
114273baed14Scanacar cmdbuf[0] = 0;
114373baed14Scanacar }
114473baed14Scanacar }
1145e9b50d6aStb message_set(NULL);
114673baed14Scanacar curr_cmd = cmd;
114773baed14Scanacar need_update = 1;
114873baed14Scanacar return prev;
114973baed14Scanacar }
115073baed14Scanacar
1151d539d1daSmartijn void
message_toggle(enum message_mode mode)1152d539d1daSmartijn message_toggle(enum message_mode mode)
1153d539d1daSmartijn {
1154d539d1daSmartijn message_mode = message_mode != mode ? mode : MESSAGE_NONE;
1155d539d1daSmartijn need_update = 1;
1156d539d1daSmartijn message_cont = 1;
1157d539d1daSmartijn }
1158d539d1daSmartijn
115973baed14Scanacar const char *
message_set(const char * msg)1160d539d1daSmartijn message_set(const char *msg)
1161d539d1daSmartijn {
1162d539d1daSmartijn free(curr_message);
1163d539d1daSmartijn
1164d539d1daSmartijn if (msg) {
116573baed14Scanacar curr_message = strdup(msg);
1166d539d1daSmartijn message_cont = 0;
1167d539d1daSmartijn } else {
116873baed14Scanacar curr_message = NULL;
1169d539d1daSmartijn message_cont = 1;
1170d539d1daSmartijn }
117173baed14Scanacar return NULL;
117273baed14Scanacar }
117373baed14Scanacar
117473baed14Scanacar void
print_cmdline(void)117573baed14Scanacar print_cmdline(void)
117673baed14Scanacar {
117773baed14Scanacar if (curr_cmd) {
117873baed14Scanacar attron(A_STANDOUT);
117973baed14Scanacar mvprintw(home_line, 0, "%s: ", curr_cmd->prompt);
118073baed14Scanacar attroff(A_STANDOUT);
118173baed14Scanacar printw("%s", cmdbuf);
118273baed14Scanacar } else if (curr_message) {
118373baed14Scanacar mvprintw(home_line, 0, "> %s", curr_message);
118473baed14Scanacar }
118573baed14Scanacar clrtoeol();
118673baed14Scanacar }
118773baed14Scanacar
118873baed14Scanacar
118973baed14Scanacar void
cmd_keyboard(int ch)119073baed14Scanacar cmd_keyboard(int ch)
119173baed14Scanacar {
119273baed14Scanacar if (curr_cmd == NULL)
119373baed14Scanacar return;
119473baed14Scanacar
119573baed14Scanacar if (ch > 0 && isprint(ch)) {
119673baed14Scanacar if (cmd_len < sizeof(cmdbuf) - 1) {
119773baed14Scanacar cmdbuf[cmd_len++] = ch;
119873baed14Scanacar cmdbuf[cmd_len] = 0;
119973baed14Scanacar } else
120073baed14Scanacar beep();
120173baed14Scanacar }
120273baed14Scanacar
120373baed14Scanacar switch (ch) {
120473baed14Scanacar case KEY_ENTER:
120573baed14Scanacar case 0x0a:
120673baed14Scanacar case 0x0d:
120773baed14Scanacar {
120873baed14Scanacar struct command * c = command_set(NULL, NULL);
12093185e9c1Scanacar c->exec(cmdbuf);
121073baed14Scanacar break;
121173baed14Scanacar }
121273baed14Scanacar case KEY_BACKSPACE:
121373baed14Scanacar case KEY_DC:
121473baed14Scanacar case CTRL_H:
121573baed14Scanacar if (cmd_len > 0) {
121673baed14Scanacar cmdbuf[--cmd_len] = 0;
121773baed14Scanacar } else
121873baed14Scanacar beep();
121973baed14Scanacar break;
122073baed14Scanacar case 0x1b:
122173baed14Scanacar case CTRL_G:
122273baed14Scanacar if (cmd_len > 0) {
122373baed14Scanacar cmdbuf[0] = '\0';
122473baed14Scanacar cmd_len = 0;
122573baed14Scanacar } else
122673baed14Scanacar command_set(NULL, NULL);
122773baed14Scanacar break;
122873baed14Scanacar default:
122973baed14Scanacar break;
123073baed14Scanacar }
123173baed14Scanacar }
123273baed14Scanacar
123373baed14Scanacar void
keyboard(void)123473baed14Scanacar keyboard(void)
123573baed14Scanacar {
123673baed14Scanacar int ch;
123773baed14Scanacar
123873baed14Scanacar ch = getch();
123973baed14Scanacar
124073baed14Scanacar if (curr_cmd) {
124173baed14Scanacar cmd_keyboard(ch);
124273baed14Scanacar print_cmdline();
124373baed14Scanacar return;
124473baed14Scanacar }
124573baed14Scanacar
124673baed14Scanacar if (curr_mgr != NULL)
124773baed14Scanacar if (curr_mgr->key_fn != NULL)
124873baed14Scanacar if (curr_mgr->key_fn(ch))
124973baed14Scanacar return;
125073baed14Scanacar
125173baed14Scanacar if (curr_message != NULL) {
125273baed14Scanacar if (ch > 0) {
1253e9b50d6aStb message_set(NULL);
125473baed14Scanacar need_update = 1;
125573baed14Scanacar }
125673baed14Scanacar }
125773baed14Scanacar
125873baed14Scanacar switch (ch) {
125973baed14Scanacar case ' ':
126073baed14Scanacar gotsig_alarm = 1;
126173baed14Scanacar break;
126273baed14Scanacar case 'o':
126373baed14Scanacar next_order();
126473baed14Scanacar need_sort = 1;
126573baed14Scanacar break;
126673baed14Scanacar case 'p':
126773baed14Scanacar paused = !paused;
126873baed14Scanacar gotsig_alarm = 1;
126973baed14Scanacar break;
127073baed14Scanacar case 'q':
127173baed14Scanacar gotsig_close = 1;
127273baed14Scanacar break;
127373baed14Scanacar case 'r':
127473baed14Scanacar sortdir *= -1;
127573baed14Scanacar need_sort = 1;
127673baed14Scanacar break;
127773baed14Scanacar case 'v':
127873baed14Scanacar /* FALLTHROUGH */
127973baed14Scanacar case KEY_RIGHT:
128073baed14Scanacar /* FALLTHROUGH */
128173baed14Scanacar case CTRL_F:
128273baed14Scanacar next_view();
128373baed14Scanacar break;
128473baed14Scanacar case KEY_LEFT:
128573baed14Scanacar /* FALLTHROUGH */
128673baed14Scanacar case CTRL_B:
128773baed14Scanacar prev_view();
128873baed14Scanacar break;
128973baed14Scanacar case KEY_DOWN:
129073baed14Scanacar /* FALLTHROUGH */
129173baed14Scanacar case CTRL_N:
129273baed14Scanacar dispstart++;
129373baed14Scanacar need_update = 1;
129473baed14Scanacar break;
129573baed14Scanacar case KEY_UP:
129673baed14Scanacar /* FALLTHROUGH */
129773baed14Scanacar case CTRL_P:
129873baed14Scanacar dispstart--;
129973baed14Scanacar need_update = 1;
130073baed14Scanacar break;
130173baed14Scanacar case KEY_NPAGE:
130273baed14Scanacar /* FALLTHROUGH */
130373baed14Scanacar case CTRL_V:
130473baed14Scanacar dispstart += maxprint;
130573baed14Scanacar need_update = 1;
130673baed14Scanacar break;
130773baed14Scanacar case KEY_PPAGE:
130873baed14Scanacar /* FALLTHROUGH */
130973baed14Scanacar case META_V:
131073baed14Scanacar dispstart -= maxprint;
131173baed14Scanacar need_update = 1;
131273baed14Scanacar break;
131373baed14Scanacar case KEY_HOME:
131473baed14Scanacar /* FALLTHROUGH */
131573baed14Scanacar case CTRL_A:
131673baed14Scanacar dispstart = 0;
131773baed14Scanacar need_update = 1;
131873baed14Scanacar break;
131973baed14Scanacar case KEY_END:
132073baed14Scanacar /* FALLTHROUGH */
132173baed14Scanacar case CTRL_E:
132273baed14Scanacar dispstart = num_disp;
132373baed14Scanacar need_update = 1;
132473baed14Scanacar break;
132573baed14Scanacar case CTRL_L:
132673baed14Scanacar clear();
132773baed14Scanacar need_update = 1;
132873baed14Scanacar break;
132973baed14Scanacar default:
133073baed14Scanacar break;
133173baed14Scanacar }
133273baed14Scanacar
133373baed14Scanacar if (set_order_hotkey(ch))
133473baed14Scanacar need_sort = 1;
133573baed14Scanacar else
133673baed14Scanacar set_view_hotkey(ch);
133773baed14Scanacar }
133873baed14Scanacar
133973baed14Scanacar void
engine_initialize(void)134073baed14Scanacar engine_initialize(void)
134173baed14Scanacar {
134273baed14Scanacar signal(SIGTERM, sig_close);
134373baed14Scanacar signal(SIGINT, sig_close);
134473baed14Scanacar signal(SIGQUIT, sig_close);
134573baed14Scanacar signal(SIGWINCH, sig_resize);
134673baed14Scanacar signal(SIGALRM, sig_alarm);
134773baed14Scanacar }
134873baed14Scanacar
134973baed14Scanacar void
engine_loop(int countmax)135073baed14Scanacar engine_loop(int countmax)
135173baed14Scanacar {
135273baed14Scanacar int count = 0;
135373baed14Scanacar
135473baed14Scanacar for (;;) {
135573baed14Scanacar if (gotsig_alarm) {
135673baed14Scanacar read_view();
135773baed14Scanacar need_sort = 1;
135873baed14Scanacar gotsig_alarm = 0;
135907a32fc5Smillert setitimer(ITIMER_REAL, &it_delay, NULL);
136073baed14Scanacar }
136173baed14Scanacar
136273baed14Scanacar if (need_sort) {
136373baed14Scanacar sort_view();
136473baed14Scanacar need_sort = 0;
136573baed14Scanacar need_update = 1;
136673baed14Scanacar
136773baed14Scanacar /* XXX if sort took too long */
136873baed14Scanacar if (gotsig_alarm) {
136973baed14Scanacar gotsig_alarm = 0;
137007a32fc5Smillert setitimer(ITIMER_REAL, &it_delay, NULL);
137173baed14Scanacar }
137273baed14Scanacar }
137373baed14Scanacar
137473baed14Scanacar if (need_update) {
137573baed14Scanacar erase();
1376c7d45d65Sreyk if (!averageonly ||
1377c7d45d65Sreyk (averageonly && count == countmax - 1))
137873baed14Scanacar disp_update();
1379d539d1daSmartijn if (message_cont) {
1380d539d1daSmartijn switch (message_mode) {
1381d539d1daSmartijn case MESSAGE_NONE:
1382d539d1daSmartijn message_set(NULL);
1383d539d1daSmartijn break;
1384d539d1daSmartijn case MESSAGE_HELP:
1385d539d1daSmartijn show_help();
1386d539d1daSmartijn break;
1387d539d1daSmartijn case MESSAGE_VIEW:
1388d539d1daSmartijn show_view();
1389d539d1daSmartijn break;
1390d539d1daSmartijn case MESSAGE_ORDER:
1391d539d1daSmartijn show_order();
1392d539d1daSmartijn break;
1393d539d1daSmartijn }
1394d539d1daSmartijn }
139573baed14Scanacar end_page();
139673baed14Scanacar need_update = 0;
139773baed14Scanacar if (countmax && ++count >= countmax)
139873baed14Scanacar break;
139973baed14Scanacar }
140073baed14Scanacar
140173baed14Scanacar if (gotsig_close)
140273baed14Scanacar break;
140373baed14Scanacar if (gotsig_resize) {
140481d8c4e1Snicm do_resize_term();
140573baed14Scanacar gotsig_resize = 0;
140673baed14Scanacar need_update = 1;
140773baed14Scanacar }
140873baed14Scanacar
140973baed14Scanacar if (interactive && need_update == 0)
141073baed14Scanacar keyboard();
141173baed14Scanacar else if (interactive == 0)
141207a32fc5Smillert nanosleep(&ts_delay, NULL);
141373baed14Scanacar }
141473baed14Scanacar
141573baed14Scanacar if (rawmode == 0)
141673baed14Scanacar endwin();
141773baed14Scanacar }
1418fcad183eSlum
1419fcad183eSlum int
check_termcap(void)1420fcad183eSlum check_termcap(void)
1421fcad183eSlum {
1422fcad183eSlum char *term_name;
1423fcad183eSlum int status;
1424fcad183eSlum static struct termios screen_settings;
1425fcad183eSlum
1426fcad183eSlum if (!interactive)
1427fcad183eSlum /* pretend we have a dumb terminal */
1428fcad183eSlum return(1);
1429fcad183eSlum
1430fcad183eSlum /* get the terminal name */
1431fcad183eSlum term_name = getenv("TERM");
1432fcad183eSlum if (term_name == NULL)
1433fcad183eSlum return(1);
1434fcad183eSlum
1435fcad183eSlum /* now get the termcap entry */
1436fcad183eSlum if ((status = tgetent(NULL, term_name)) != 1) {
1437fcad183eSlum if (status == -1)
1438fcad183eSlum warnx("can't open termcap file");
1439fcad183eSlum else
1440fcad183eSlum warnx("no termcap entry for a `%s' terminal",
1441fcad183eSlum term_name);
1442fcad183eSlum
1443fcad183eSlum /* pretend it's dumb and proceed */
1444fcad183eSlum return(1);
1445fcad183eSlum }
1446fcad183eSlum
1447fcad183eSlum /* "hardcopy" immediately indicates a very stupid terminal */
1448fcad183eSlum if (tgetflag("hc"))
1449fcad183eSlum return(1);
1450fcad183eSlum
1451fcad183eSlum /* get necessary capabilities */
1452fcad183eSlum if (tgetstr("cl", NULL) == NULL || tgetstr("cm", NULL) == NULL)
1453fcad183eSlum return(1);
1454fcad183eSlum
1455fcad183eSlum /* if stdout is not a terminal, pretend we are a dumb terminal */
1456fcad183eSlum if (tcgetattr(STDOUT_FILENO, &screen_settings) == -1)
1457fcad183eSlum return(1);
1458fcad183eSlum
1459fcad183eSlum return(0);
1460fcad183eSlum }
146107a32fc5Smillert
146207a32fc5Smillert void
refresh_delay(double delay)146307a32fc5Smillert refresh_delay(double delay)
146407a32fc5Smillert {
146507a32fc5Smillert double secs, frac;
146607a32fc5Smillert
146707a32fc5Smillert frac = modf(delay, &secs);
146807a32fc5Smillert ts_delay.tv_sec = secs;
146907a32fc5Smillert ts_delay.tv_nsec = frac * 1000000000.0;
147007a32fc5Smillert if (!timespecisset(&ts_delay))
147107a32fc5Smillert ts_delay.tv_nsec = 1000000000;
147207a32fc5Smillert TIMESPEC_TO_TIMEVAL(&it_delay.it_value, &ts_delay);
147307a32fc5Smillert }
1474