Annotation of src/usr.bin/systat/engine.c, Revision 1.1
1.1 ! canacar 1: /* $Id: engine.c,v 1.7 2007/10/02 04:17:37 canacar Exp $ */
! 2: /*
! 3: * Copyright (c) 2001, 2007 Can Erkin Acar <canacar@openbsd.org>
! 4: *
! 5: * Permission to use, copy, modify, and distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17:
! 18:
! 19:
! 20: #include <sys/types.h>
! 21: #include <sys/queue.h>
! 22:
! 23: #include <ctype.h>
! 24: #include <curses.h>
! 25: #include <signal.h>
! 26: #include <stdlib.h>
! 27: #include <string.h>
! 28: #include <unistd.h>
! 29:
! 30: #include "engine.h"
! 31:
! 32: #ifndef MIN
! 33: #define MIN(a,b) (((a)<(b))?(a):(b))
! 34: #endif
! 35:
! 36: /* circular linked list of views */
! 37: CIRCLEQ_HEAD(view_list, view_ent) view_head =
! 38: CIRCLEQ_HEAD_INITIALIZER(view_head);
! 39: struct view_ent {
! 40: field_view *view;
! 41: CIRCLEQ_ENTRY(view_ent) entries;
! 42: };
! 43:
! 44: useconds_t udelay = 5000000;
! 45: int dispstart = 0;
! 46: int interactive = 1;
! 47: int maxprint = 0;
! 48: int paused = 0;
! 49: int rawmode = 0;
! 50: int rawwidth = DEFAULT_WIDTH;
! 51: int sortdir = 1;
! 52: int columns, lines;
! 53: u_int32_t num_disp = 0;
! 54: int max_disp = -1;
! 55:
! 56: volatile sig_atomic_t gotsig_close = 0;
! 57: volatile sig_atomic_t gotsig_resize = 0;
! 58: volatile sig_atomic_t gotsig_alarm = 0;
! 59: int need_update = 0;
! 60: int need_sort = 0;
! 61:
! 62: SCREEN *screen;
! 63:
! 64: field_view *curr_view = NULL;
! 65: struct view_ent *curr_view_ent = NULL;
! 66: struct view_manager *curr_mgr = NULL;
! 67:
! 68: int curr_line = 0;
! 69: int home_line = 0;
! 70:
! 71: /* line buffer for raw mode */
! 72: char linebuf[MAX_LINE_BUF];
! 73: int linepos = 0;
! 74:
! 75: /* temp storage for state printing */
! 76: char tmp_buf[MAX_LINE_BUF];
! 77:
! 78: char cmdbuf[MAX_LINE_BUF];
! 79: int cmd_len = -1;
! 80: struct command *curr_cmd = NULL;
! 81: char *curr_message = NULL;
! 82:
! 83: void print_cmdline(void);
! 84:
! 85:
! 86: /* screen output functions */
! 87:
! 88: char * tb_ptr = NULL;
! 89: int tb_len = 0;
! 90:
! 91: void
! 92: tb_start(void)
! 93: {
! 94: tb_ptr = tmp_buf;
! 95: tb_len = sizeof(tmp_buf);
! 96: tb_ptr[0] = '\0';
! 97: }
! 98:
! 99: void
! 100: tb_end(void)
! 101: {
! 102: tb_ptr = NULL;
! 103: tb_len = 0;
! 104: }
! 105:
! 106: int
! 107: tbprintf(char *format, ...)
! 108: GCC_PRINTFLIKE(1,2) /* defined in curses.h */
! 109: {
! 110: int len;
! 111: va_list arg;
! 112:
! 113: if (tb_ptr == NULL || tb_len <= 0)
! 114: return 0;
! 115:
! 116: va_start(arg, format);
! 117: len=vsnprintf(tb_ptr, tb_len, format, arg);
! 118: va_end(arg);
! 119:
! 120: if (len > tb_len)
! 121: tb_end();
! 122: else if (len > 0) {
! 123: tb_ptr += len;
! 124: tb_len -= len;
! 125: }
! 126:
! 127: return len;
! 128: }
! 129:
! 130: void
! 131: move_horiz(int offset)
! 132: {
! 133: if (rawmode) {
! 134: if (offset <= 0)
! 135: linepos = 0;
! 136: else if (offset >= MAX_LINE_BUF)
! 137: linepos = MAX_LINE_BUF - 1;
! 138: else
! 139: linepos = offset;
! 140: } else {
! 141: move(curr_line, offset);
! 142: }
! 143: }
! 144:
! 145: void
! 146: print_str(int len, const char *str)
! 147: {
! 148: if (len <= 0)
! 149: return;
! 150:
! 151: if (rawmode) {
! 152: int length = MIN(len, MAX_LINE_BUF - linepos);
! 153: if (length <= 0)
! 154: return;
! 155: bcopy(str, &linebuf[linepos], length);
! 156: linepos += length;
! 157: } else
! 158: addnstr(str, len);
! 159: }
! 160:
! 161: void
! 162: clear_linebuf(void)
! 163: {
! 164: memset(linebuf, ' ', MAX_LINE_BUF);
! 165: }
! 166:
! 167: void
! 168: end_line(void)
! 169: {
! 170: if (rawmode) {
! 171: linebuf[rawwidth] = '\0';
! 172: printf("%s\n", linebuf);
! 173: clear_linebuf();
! 174: }
! 175: curr_line++;
! 176: }
! 177:
! 178: void
! 179: end_page(void)
! 180: {
! 181: if (rawmode) {
! 182: linepos = 0;
! 183: clear_linebuf();
! 184: } else {
! 185: move(home_line, 0);
! 186: print_cmdline();
! 187: refresh();
! 188: }
! 189: curr_line = 0;
! 190: }
! 191:
! 192: void
! 193: rawaddstr(char *s)
! 194: {
! 195: if (rawmode)
! 196: printf("%s", s);
! 197: else
! 198: addstr(s);
! 199: }
! 200:
! 201: /* field output functions */
! 202:
! 203: void
! 204: print_fld_str(field_def *fld, const char *str)
! 205: {
! 206: int len, move;
! 207: char *cpos;
! 208:
! 209: if (str == NULL || fld == NULL)
! 210: return;
! 211:
! 212: if (fld->start < 0)
! 213: return;
! 214:
! 215: len = strlen(str);
! 216:
! 217: if (len >= fld->width) {
! 218: move_horiz(fld->start);
! 219: print_str(fld->width, str);
! 220: } else {
! 221: switch (fld->align) {
! 222: case FLD_ALIGN_RIGHT:
! 223: move_horiz(fld->start + (fld->width - len));
! 224: break;
! 225: case FLD_ALIGN_CENTER:
! 226: move_horiz(fld->start + (fld->width - len) / 2);
! 227: break;
! 228: case FLD_ALIGN_COLUMN:
! 229: if ((cpos = strchr(str, ':')) == NULL) {
! 230: move = (fld->width - len) / 2;
! 231: } else {
! 232: move = (fld->width / 2) - (cpos - str);
! 233: if (move < 0)
! 234: move = 0;
! 235: else if (move > (fld->width - len))
! 236: move = fld->width - len;
! 237: }
! 238: move_horiz(fld->start + move);
! 239: break;
! 240: default:
! 241: move_horiz(fld->start);
! 242: break;
! 243: }
! 244: print_str(len, str);
! 245: }
! 246: }
! 247:
! 248: void
! 249: print_bar_title(field_def *fld)
! 250: {
! 251: char buf[16];
! 252: int len, div, i, tr, tw, val, pos, cur;
! 253:
! 254: int divs[] = {20, 10, 5, 4, 3, 2, 1, 0};
! 255:
! 256: if (fld->width < 1)
! 257: return;
! 258:
! 259: len = snprintf(buf, sizeof(buf), " %d\\", fld->arg);
! 260: if (len >= sizeof(buf))
! 261: return;
! 262:
! 263: for (i = 0; divs[i]; i++)
! 264: if (divs[i] * len <= fld->width)
! 265: break;
! 266:
! 267: if (divs[i] == 0) {
! 268: print_fld_str(fld, "*****");
! 269: return;
! 270: }
! 271:
! 272: div = divs[i];
! 273:
! 274: val = 0;
! 275: pos = 0;
! 276: tr = fld->arg % div;
! 277: tw = fld->width % div;
! 278:
! 279: tb_start();
! 280: cur = 0;
! 281: for(i = 0; i < div; i++) {
! 282: tw += fld->width;
! 283: tr += fld->arg;
! 284:
! 285: while (tr >= div) {
! 286: val++;
! 287: tr -= div;
! 288: }
! 289: while (tw >= div) {
! 290: pos++;
! 291: tw -= div;
! 292: }
! 293:
! 294: len = snprintf(buf, sizeof(buf), "%d\\", val);
! 295: while (cur < pos - len) {
! 296: tbprintf(" ");
! 297: cur++;
! 298: }
! 299: tbprintf("%s", buf);
! 300: cur += len;
! 301: }
! 302:
! 303: print_fld_tb(fld);
! 304: }
! 305:
! 306: void
! 307: print_fld_bar(field_def *fld, int value)
! 308: {
! 309: int i, tw, val, cur;
! 310:
! 311: if (fld->width < 1)
! 312: return;
! 313:
! 314: val = 0;
! 315: tw = fld->arg / 2;
! 316:
! 317: tb_start();
! 318: cur = 0;
! 319: for(i = 0; i < fld->width; i++) {
! 320: tw += fld->arg;
! 321:
! 322: while (tw >= fld->width) {
! 323: val++;
! 324: tw -= fld->width;
! 325: }
! 326: if (val > value)
! 327: break;
! 328: tbprintf("#");
! 329: }
! 330:
! 331: print_fld_tb(fld);
! 332: }
! 333:
! 334: void
! 335: print_fld_tb(field_def *fld)
! 336: {
! 337: print_fld_str(fld, tmp_buf);
! 338: tb_end();
! 339: }
! 340:
! 341: void
! 342: print_title(void)
! 343: {
! 344: field_def **fp;
! 345:
! 346: if (curr_view != NULL && curr_view->view != NULL) {
! 347: for (fp = curr_view->view; *fp != NULL; fp++) {
! 348: switch((*fp)->align) {
! 349: case FLD_ALIGN_LEFT:
! 350: case FLD_ALIGN_RIGHT:
! 351: case FLD_ALIGN_CENTER:
! 352: case FLD_ALIGN_COLUMN:
! 353: print_fld_str(*fp, (*fp)->title);
! 354: break;
! 355: case FLD_ALIGN_BAR:
! 356: print_bar_title(*fp);
! 357: break;
! 358: }
! 359: }
! 360: }
! 361: end_line();
! 362: }
! 363:
! 364: /* view related functions */
! 365: void
! 366: hide_field(field_def *fld)
! 367: {
! 368: if (fld == NULL)
! 369: return;
! 370:
! 371: fld->flags |= FLD_FLAG_HIDDEN;
! 372: }
! 373:
! 374: void
! 375: show_field(field_def *fld)
! 376: {
! 377: if (fld == NULL)
! 378: return;
! 379:
! 380: fld->flags &= ~((unsigned int) FLD_FLAG_HIDDEN);
! 381: }
! 382:
! 383: void
! 384: reset_fields(void)
! 385: {
! 386: field_def **fp;
! 387: field_def *fld;
! 388:
! 389: if (curr_view == NULL)
! 390: return;
! 391:
! 392: if (curr_view->view == NULL)
! 393: return;
! 394:
! 395: for (fp = curr_view->view; *fp != NULL; fp++) {
! 396: fld = *fp;
! 397: fld->start = -1;
! 398: fld->width = fld->norm_width;
! 399: }
! 400: }
! 401:
! 402: void
! 403: field_setup(void)
! 404: {
! 405: field_def **fp;
! 406: field_def *fld;
! 407: int st, fwid, change;
! 408: int width = columns;
! 409:
! 410: reset_fields();
! 411:
! 412: dispstart = 0;
! 413: st = 0;
! 414:
! 415: for (fp = curr_view->view; *fp != NULL; fp++) {
! 416: fld = *fp;
! 417: if (fld->flags & FLD_FLAG_HIDDEN)
! 418: continue;
! 419:
! 420: if (width <= 1)
! 421: break;
! 422:
! 423: if (st != 1)
! 424: width--;
! 425:
! 426: fld->start = 1;
! 427: fwid = fld->width;
! 428: st++;
! 429: if (fwid >= width) {
! 430: fld->width = width;
! 431: width = 0;
! 432: } else
! 433: width -= fwid;
! 434: }
! 435:
! 436: change = 0;
! 437: while (width > 0) {
! 438: change = 0;
! 439: for (fp = curr_view->view; *fp != NULL; fp++) {
! 440: fld = *fp;
! 441: if (fld->flags & FLD_FLAG_HIDDEN)
! 442: continue;
! 443: if ((fld->width < fld->max_width) &&
! 444: (fld->increment <= width)) {
! 445: int w = fld->width + fld->increment;
! 446: if (w > fld->max_width)
! 447: w = fld->max_width;
! 448: width += fld->width - w;
! 449: fld->width = w;
! 450: change = 1;
! 451: }
! 452: if (width <= 0) break;
! 453: }
! 454: if (change == 0) break;
! 455: }
! 456:
! 457: st = 0;
! 458: for (fp = curr_view->view; *fp != NULL; fp++) {
! 459: fld = *fp;
! 460: if (fld->flags & FLD_FLAG_HIDDEN)
! 461: continue;
! 462: if (fld->start < 0) break;
! 463: fld->start = st;
! 464: st += fld->width + 1;
! 465: }
! 466: }
! 467:
! 468: void
! 469: set_curr_view(struct view_ent *ve)
! 470: {
! 471: field_view *v;
! 472:
! 473: reset_fields();
! 474:
! 475: if (ve == NULL) {
! 476: curr_view_ent = NULL;
! 477: curr_view = NULL;
! 478: curr_mgr = NULL;
! 479: return;
! 480: }
! 481:
! 482: v = ve->view;
! 483:
! 484: if ((curr_view != NULL) && (curr_mgr != v->mgr)) {
! 485: gotsig_alarm = 1;
! 486: if (v->mgr != NULL && v->mgr->select_fn != NULL)
! 487: v->mgr->select_fn();
! 488: }
! 489:
! 490: curr_view_ent = ve;
! 491: curr_view = v;
! 492: curr_mgr = v->mgr;
! 493: field_setup();
! 494: need_update = 1;
! 495: }
! 496:
! 497: void
! 498: add_view(field_view *fv)
! 499: {
! 500: struct view_ent *ent;
! 501:
! 502: if (fv == NULL)
! 503: return;
! 504:
! 505: if (fv->view == NULL || fv->name == NULL || fv->mgr == NULL)
! 506: return;
! 507:
! 508: ent = malloc(sizeof(struct view_ent));
! 509: if (ent == NULL)
! 510: return;
! 511:
! 512: ent->view = fv;
! 513: CIRCLEQ_INSERT_TAIL(&view_head, ent, entries);
! 514:
! 515: if (curr_view == NULL)
! 516: set_curr_view(ent);
! 517: }
! 518:
! 519: int
! 520: set_view(char *opt)
! 521: {
! 522: struct view_ent *ve, *vm = NULL;
! 523: field_view *v;
! 524: int len;
! 525:
! 526: if (opt == NULL || (len = strlen(opt)) == 0)
! 527: return 1;
! 528:
! 529: CIRCLEQ_FOREACH(ve, &view_head, entries) {
! 530: v = ve->view;
! 531: if (strncasecmp(opt, v->name, len) == 0) {
! 532: if (vm)
! 533: return 1;
! 534: vm = ve;
! 535: }
! 536: }
! 537:
! 538: if (vm) {
! 539: set_curr_view(vm);
! 540: return 0;
! 541: }
! 542:
! 543: return 1;
! 544: }
! 545:
! 546: void
! 547: foreach_view(void (*callback)(field_view *))
! 548: {
! 549: struct view_ent *ve;
! 550:
! 551: CIRCLEQ_FOREACH(ve, &view_head, entries) {
! 552: callback(ve->view);
! 553: }
! 554: }
! 555:
! 556: int
! 557: set_view_hotkey(int ch)
! 558: {
! 559: struct view_ent *ve;
! 560: field_view *v;
! 561: int key = tolower(ch);
! 562:
! 563: CIRCLEQ_FOREACH(ve, &view_head, entries) {
! 564: v = ve->view;
! 565: if (key == v->hotkey) {
! 566: set_curr_view(ve);
! 567: return 1;
! 568: }
! 569: }
! 570:
! 571: return 0;
! 572: }
! 573:
! 574: void
! 575: next_view(void)
! 576: {
! 577: struct view_ent *ve;
! 578:
! 579: if (CIRCLEQ_EMPTY(&view_head) || curr_view_ent == NULL)
! 580: return;
! 581:
! 582: ve = CIRCLEQ_NEXT(curr_view_ent, entries);
! 583: if (ve == CIRCLEQ_END(&view_head))
! 584: ve = CIRCLEQ_FIRST(&view_head);
! 585:
! 586: set_curr_view(ve);
! 587: }
! 588:
! 589: void
! 590: prev_view(void)
! 591: {
! 592: struct view_ent *ve;
! 593:
! 594: if (CIRCLEQ_EMPTY(&view_head) || curr_view_ent == NULL)
! 595: return;
! 596:
! 597: ve = CIRCLEQ_PREV(curr_view_ent, entries);
! 598: if (ve == CIRCLEQ_END(&view_head))
! 599: ve = CIRCLEQ_LAST(&view_head);
! 600:
! 601: set_curr_view(ve);
! 602: }
! 603:
! 604: /* generic field printing */
! 605:
! 606: void
! 607: print_fld_age(field_def *fld, unsigned int age)
! 608: {
! 609: int len;
! 610: unsigned int h, m, s;
! 611:
! 612: if (fld == NULL)
! 613: return;
! 614: len = fld->width;
! 615:
! 616: if (len < 1)
! 617: return;
! 618:
! 619: s = age % 60;
! 620: m = age / 60;
! 621: h = m / 60;
! 622: m %= 60;
! 623:
! 624: tb_start();
! 625: if (tbprintf("%02u:%02u:%02u", h, m, s) <= len)
! 626: goto ok;
! 627:
! 628: if (tbprintf("%u", age) <= len)
! 629: goto ok;
! 630:
! 631: age /= 60;
! 632: if (tbprintf("%um", age) <= len)
! 633: goto ok;
! 634: if (age == 0)
! 635: goto err;
! 636:
! 637: age /= 60;
! 638: if (tbprintf("%uh", age) <= len)
! 639: goto ok;
! 640: if (age == 0)
! 641: goto err;
! 642:
! 643: age /= 24;
! 644: if (tbprintf("%ud", age) <= len)
! 645: goto ok;
! 646:
! 647: err:
! 648: print_fld_str(fld, "*");
! 649: tb_end();
! 650: return;
! 651:
! 652: ok:
! 653: print_fld_tb(fld);
! 654: }
! 655:
! 656: void
! 657: print_fld_sdiv(field_def *fld, u_int64_t size, int div)
! 658: {
! 659: int len;
! 660:
! 661: if (fld == NULL)
! 662: return;
! 663:
! 664: len = fld->width;
! 665: if (len < 1)
! 666: return;
! 667:
! 668: tb_start();
! 669: if (tbprintf("%llu", size) <= len)
! 670: goto ok;
! 671:
! 672: size /= div;
! 673: if (tbprintf("%lluK", size) <= len)
! 674: goto ok;
! 675: if (size == 0)
! 676: goto err;
! 677:
! 678: size /= div;
! 679: if (tbprintf("%lluM", size) <= len)
! 680: goto ok;
! 681: if (size == 0)
! 682: goto err;
! 683:
! 684: size /= div;
! 685: if (tbprintf("%lluG", size) <= len)
! 686: goto ok;
! 687:
! 688: err:
! 689: print_fld_str(fld, "*");
! 690: tb_end();
! 691: return;
! 692:
! 693: ok:
! 694: print_fld_tb(fld);
! 695: }
! 696:
! 697: void
! 698: print_fld_size(field_def *fld, u_int64_t size)
! 699: {
! 700: print_fld_sdiv(fld, size, 1024);
! 701: }
! 702:
! 703: void
! 704: print_fld_rate(field_def *fld, double rate)
! 705: {
! 706: if (rate < 0) {
! 707: print_fld_str(fld, "*");
! 708: } else {
! 709: print_fld_size(fld, rate);
! 710: }
! 711: }
! 712:
! 713: void
! 714: print_fld_bw(field_def *fld, double bw)
! 715: {
! 716: if (bw < 0) {
! 717: print_fld_str(fld, "*");
! 718: } else {
! 719: print_fld_sdiv(fld, bw, 1000);
! 720: }
! 721: }
! 722:
! 723: void
! 724: print_fld_uint(field_def *fld, unsigned int size)
! 725: {
! 726: int len;
! 727:
! 728: if (fld == NULL)
! 729: return;
! 730:
! 731: len = fld->width;
! 732: if (len < 1)
! 733: return;
! 734:
! 735: tb_start();
! 736: if (tbprintf("%u", size) > len)
! 737: print_fld_str(fld, "*");
! 738: else
! 739: print_fld_tb(fld);
! 740: tb_end();
! 741: }
! 742:
! 743:
! 744: /* ordering */
! 745:
! 746: void
! 747: set_order(char *opt)
! 748: {
! 749: order_type *o;
! 750:
! 751: if (curr_view == NULL || curr_view->mgr == NULL)
! 752: return;
! 753:
! 754: curr_view->mgr->order_curr = curr_view->mgr->order_list;
! 755:
! 756: if (opt == NULL)
! 757: return;
! 758:
! 759: o = curr_view->mgr->order_list;
! 760:
! 761: if (o == NULL)
! 762: return;
! 763:
! 764: for (;o->name != NULL; o++) {
! 765: if (strcasecmp(opt, o->match) == 0) {
! 766: curr_view->mgr->order_curr = o;
! 767: return;
! 768: }
! 769: }
! 770: }
! 771:
! 772: int
! 773: set_order_hotkey(int ch)
! 774: {
! 775: order_type *o;
! 776: int key = ch;
! 777:
! 778: if (curr_view == NULL || curr_view->mgr == NULL)
! 779: return 0;
! 780:
! 781: o = curr_view->mgr->order_list;
! 782:
! 783: if (o == NULL)
! 784: return 0;
! 785:
! 786: for (;o->name != NULL; o++) {
! 787: if (key == o->hotkey) {
! 788: if (curr_view->mgr->order_curr == o) {
! 789: sortdir *= -1;
! 790: } else {
! 791: curr_view->mgr->order_curr = o;
! 792: }
! 793: return 1;
! 794: }
! 795: }
! 796:
! 797: return 0;
! 798: }
! 799:
! 800: void
! 801: next_order(void)
! 802: {
! 803: order_type *o, *oc;
! 804:
! 805: oc = curr_view->mgr->order_curr;
! 806:
! 807: for (o = curr_view->mgr->order_list; o->name != NULL; o++) {
! 808: if (oc == o) {
! 809: o++;
! 810: if (o->name == NULL)
! 811: break;
! 812: curr_view->mgr->order_curr = o;
! 813: return;
! 814: }
! 815: }
! 816:
! 817: curr_view->mgr->order_curr = curr_view->mgr->order_list;
! 818: }
! 819:
! 820:
! 821: /* main program functions */
! 822:
! 823: int
! 824: read_view(void)
! 825: {
! 826: if (curr_mgr == NULL)
! 827: return (0);
! 828:
! 829: if (paused)
! 830: return (0);
! 831:
! 832: if (curr_mgr->read_fn != NULL)
! 833: return (curr_mgr->read_fn());
! 834:
! 835: return (0);
! 836: }
! 837:
! 838:
! 839: int
! 840: disp_update(void)
! 841: {
! 842: int lines;
! 843:
! 844: if (maxprint < 0)
! 845: dispstart = 0;
! 846: else if (dispstart + maxprint > num_disp)
! 847: dispstart = num_disp - maxprint;
! 848:
! 849: if (dispstart < 0)
! 850: dispstart = 0;
! 851:
! 852: if (curr_view == NULL)
! 853: return 0;
! 854:
! 855: if (curr_mgr != NULL) {
! 856: curr_line = 0;
! 857:
! 858: if (curr_mgr->header_fn != NULL) {
! 859: lines = curr_mgr->header_fn();
! 860: if (lines < 0)
! 861: return (1);
! 862: // home_line = lines++;
! 863: curr_line = ++lines;
! 864: home_line = lines + maxprint + 1;
! 865: }
! 866:
! 867: print_title();
! 868:
! 869: if (curr_mgr->print_fn != NULL)
! 870: curr_mgr->print_fn();
! 871: }
! 872:
! 873: return (0);
! 874: }
! 875:
! 876: void
! 877: sort_view(void)
! 878: {
! 879: if (curr_mgr != NULL)
! 880: if (curr_mgr->sort_fn != NULL)
! 881: curr_mgr->sort_fn();
! 882: }
! 883:
! 884: void
! 885: sig_close(int signal)
! 886: {
! 887: gotsig_close = 1;
! 888: }
! 889:
! 890: void
! 891: sig_resize(int signal)
! 892: {
! 893: gotsig_resize = 1;
! 894: }
! 895:
! 896: void
! 897: sig_alarm(int signal)
! 898: {
! 899: gotsig_alarm = 1;
! 900: }
! 901:
! 902: void
! 903: setup_term(int dmax)
! 904: {
! 905: max_disp = dmax;
! 906: maxprint = dmax;
! 907:
! 908: if (rawmode) {
! 909: columns = rawwidth;
! 910: lines = DEFAULT_HEIGHT;
! 911: clear_linebuf();
! 912: } else {
! 913: if (dmax < 0)
! 914: dmax = 0;
! 915:
! 916: screen = newterm(NULL, stdout, stdin);
! 917: if (screen == NULL) {
! 918: rawmode = 1;
! 919: interactive = 0;
! 920: setup_term(dmax);
! 921: return;
! 922: }
! 923: columns = COLS;
! 924: lines = LINES;
! 925:
! 926: if (maxprint > lines - HEADER_LINES)
! 927: maxprint = lines - HEADER_LINES;
! 928:
! 929: nonl();
! 930: keypad(stdscr, TRUE);
! 931: intrflush(stdscr, FALSE);
! 932:
! 933: halfdelay(10);
! 934: noecho();
! 935: }
! 936:
! 937: if (dmax == 0)
! 938: maxprint = lines - HEADER_LINES;
! 939:
! 940: field_setup();
! 941: }
! 942:
! 943: struct command *
! 944: command_set(struct command *cmd, const char *init)
! 945: {
! 946: struct command *prev = curr_cmd;
! 947:
! 948: if (cmd) {
! 949: if (init) {
! 950: cmd_len = strlcpy(cmdbuf, init, sizeof(cmdbuf));
! 951: if (cmd_len >= sizeof(cmdbuf)) {
! 952: cmdbuf[0] = '\0';
! 953: cmd_len = 0;
! 954: }
! 955: } else {
! 956: cmd_len = 0;
! 957: cmdbuf[0] = 0;
! 958: }
! 959: }
! 960: curr_message = NULL;
! 961: curr_cmd = cmd;
! 962: need_update = 1;
! 963: return prev;
! 964: }
! 965:
! 966: const char *
! 967: message_set(const char *msg) {
! 968: char *prev = curr_message;
! 969: if (msg)
! 970: curr_message = strdup(msg);
! 971: else
! 972: curr_message = NULL;
! 973: free(prev);
! 974: return NULL;
! 975: }
! 976:
! 977: void
! 978: print_cmdline(void)
! 979: {
! 980: if (curr_cmd) {
! 981: attron(A_STANDOUT);
! 982: mvprintw(home_line, 0, "%s: ", curr_cmd->prompt);
! 983: attroff(A_STANDOUT);
! 984: printw("%s", cmdbuf);
! 985: } else if (curr_message) {
! 986: mvprintw(home_line, 0, "> %s", curr_message);
! 987: }
! 988: clrtoeol();
! 989: }
! 990:
! 991:
! 992: void
! 993: cmd_keyboard(int ch)
! 994: {
! 995: if (curr_cmd == NULL)
! 996: return;
! 997:
! 998: if (ch > 0 && isprint(ch)) {
! 999: if (cmd_len < sizeof(cmdbuf) - 1) {
! 1000: cmdbuf[cmd_len++] = ch;
! 1001: cmdbuf[cmd_len] = 0;
! 1002: } else
! 1003: beep();
! 1004: }
! 1005:
! 1006: switch (ch) {
! 1007: case KEY_ENTER:
! 1008: case 0x0a:
! 1009: case 0x0d:
! 1010: {
! 1011: struct command * c = command_set(NULL, NULL);
! 1012: c->exec();
! 1013: break;
! 1014: }
! 1015: case KEY_BACKSPACE:
! 1016: case KEY_DC:
! 1017: case CTRL_H:
! 1018: if (cmd_len > 0) {
! 1019: cmdbuf[--cmd_len] = 0;
! 1020: } else
! 1021: beep();
! 1022: break;
! 1023: case 0x1b:
! 1024: case CTRL_G:
! 1025: if (cmd_len > 0) {
! 1026: cmdbuf[0] = '\0';
! 1027: cmd_len = 0;
! 1028: } else
! 1029: command_set(NULL, NULL);
! 1030: break;
! 1031: default:
! 1032: break;
! 1033: }
! 1034: }
! 1035:
! 1036: void
! 1037: keyboard(void)
! 1038: {
! 1039: int ch;
! 1040:
! 1041: ch = getch();
! 1042:
! 1043: if (curr_cmd) {
! 1044: cmd_keyboard(ch);
! 1045: print_cmdline();
! 1046: return;
! 1047: }
! 1048:
! 1049: if (curr_mgr != NULL)
! 1050: if (curr_mgr->key_fn != NULL)
! 1051: if (curr_mgr->key_fn(ch))
! 1052: return;
! 1053:
! 1054: if (curr_message != NULL) {
! 1055: if (ch > 0) {
! 1056: curr_message = NULL;
! 1057: need_update = 1;
! 1058: }
! 1059: }
! 1060:
! 1061: switch (ch) {
! 1062: case ' ':
! 1063: gotsig_alarm = 1;
! 1064: break;
! 1065: case 'o':
! 1066: next_order();
! 1067: need_sort = 1;
! 1068: break;
! 1069: case 'p':
! 1070: paused = !paused;
! 1071: gotsig_alarm = 1;
! 1072: break;
! 1073: case 'q':
! 1074: gotsig_close = 1;
! 1075: break;
! 1076: case 'r':
! 1077: sortdir *= -1;
! 1078: need_sort = 1;
! 1079: break;
! 1080: case 'v':
! 1081: /* FALLTHROUGH */
! 1082: case KEY_RIGHT:
! 1083: /* FALLTHROUGH */
! 1084: case CTRL_F:
! 1085: next_view();
! 1086: break;
! 1087: case KEY_LEFT:
! 1088: /* FALLTHROUGH */
! 1089: case CTRL_B:
! 1090: prev_view();
! 1091: break;
! 1092: case KEY_DOWN:
! 1093: /* FALLTHROUGH */
! 1094: case CTRL_N:
! 1095: dispstart++;
! 1096: need_update = 1;
! 1097: break;
! 1098: case KEY_UP:
! 1099: /* FALLTHROUGH */
! 1100: case CTRL_P:
! 1101: dispstart--;
! 1102: need_update = 1;
! 1103: break;
! 1104: case KEY_NPAGE:
! 1105: /* FALLTHROUGH */
! 1106: case CTRL_V:
! 1107: dispstart += maxprint;
! 1108: need_update = 1;
! 1109: break;
! 1110: case KEY_PPAGE:
! 1111: /* FALLTHROUGH */
! 1112: case META_V:
! 1113: dispstart -= maxprint;
! 1114: need_update = 1;
! 1115: break;
! 1116: case KEY_HOME:
! 1117: /* FALLTHROUGH */
! 1118: case CTRL_A:
! 1119: dispstart = 0;
! 1120: need_update = 1;
! 1121: break;
! 1122: case KEY_END:
! 1123: /* FALLTHROUGH */
! 1124: case CTRL_E:
! 1125: dispstart = num_disp;
! 1126: need_update = 1;
! 1127: break;
! 1128: case CTRL_L:
! 1129: clear();
! 1130: need_update = 1;
! 1131: break;
! 1132: default:
! 1133: break;
! 1134: }
! 1135:
! 1136: if (set_order_hotkey(ch))
! 1137: need_sort = 1;
! 1138: else
! 1139: set_view_hotkey(ch);
! 1140: }
! 1141:
! 1142: void
! 1143: engine_initialize(void)
! 1144: {
! 1145: signal(SIGTERM, sig_close);
! 1146: signal(SIGINT, sig_close);
! 1147: signal(SIGQUIT, sig_close);
! 1148: signal(SIGWINCH, sig_resize);
! 1149: signal(SIGALRM, sig_alarm);
! 1150: }
! 1151:
! 1152: void
! 1153: engine_loop(int countmax)
! 1154: {
! 1155: int count = 0;
! 1156:
! 1157: for (;;) {
! 1158: if (gotsig_alarm) {
! 1159: read_view();
! 1160: need_sort = 1;
! 1161: gotsig_alarm = 0;
! 1162: ualarm(udelay, 0);
! 1163: }
! 1164:
! 1165: if (need_sort) {
! 1166: sort_view();
! 1167: need_sort = 0;
! 1168: need_update = 1;
! 1169:
! 1170: /* XXX if sort took too long */
! 1171: if (gotsig_alarm) {
! 1172: gotsig_alarm = 0;
! 1173: ualarm(udelay, 0);
! 1174: }
! 1175: }
! 1176:
! 1177: if (need_update) {
! 1178: erase();
! 1179: disp_update();
! 1180: end_page();
! 1181: need_update = 0;
! 1182: if (countmax && ++count >= countmax)
! 1183: break;
! 1184: }
! 1185:
! 1186: if (gotsig_close)
! 1187: break;
! 1188: if (gotsig_resize) {
! 1189: if (rawmode == 0)
! 1190: endwin();
! 1191: setup_term(max_disp);
! 1192: gotsig_resize = 0;
! 1193: need_update = 1;
! 1194: }
! 1195:
! 1196: if (interactive && need_update == 0)
! 1197: keyboard();
! 1198: else if (interactive == 0)
! 1199: usleep(udelay);
! 1200: }
! 1201:
! 1202: if (rawmode == 0)
! 1203: endwin();
! 1204: }