Annotation of embedaddon/bmon/src/out_curses.c, revision 1.1
1.1 ! misho 1: /*
! 2: * out_curses.c Curses Output
! 3: *
! 4: * Copyright (c) 2001-2005 Thomas Graf <tgraf@suug.ch>
! 5: *
! 6: * Permission is hereby granted, free of charge, to any person obtaining a
! 7: * copy of this software and associated documentation files (the "Software"),
! 8: * to deal in the Software without restriction, including without limitation
! 9: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
! 10: * and/or sell copies of the Software, and to permit persons to whom the
! 11: * Software is furnished to do so, subject to the following conditions:
! 12: *
! 13: * The above copyright notice and this permission notice shall be included
! 14: * in all copies or substantial portions of the Software.
! 15: *
! 16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
! 17: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
! 18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
! 19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
! 20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
! 21: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
! 22: * DEALINGS IN THE SOFTWARE.
! 23: */
! 24:
! 25: #include <bmon/bmon.h>
! 26: #include <bmon/graph.h>
! 27: #include <bmon/conf.h>
! 28: #include <bmon/itemtab.h>
! 29: #include <bmon/input.h>
! 30: #include <bmon/output.h>
! 31: #include <bmon/node.h>
! 32: #include <bmon/bindings.h>
! 33: #include <bmon/utils.h>
! 34:
! 35: static int initialized;
! 36: static int print_help = 0;
! 37: static int quit_mode = 0;
! 38: static int help_page = 0;
! 39: static int row;
! 40: static int rows;
! 41: static int cols;
! 42:
! 43: static int c_graph_height = 6;
! 44: static int c_use_colors = 1;
! 45: static int c_combined_node_list = 0;
! 46: static int c_graphical_in_list = 0;
! 47: static int c_detailed_in_list = 0;
! 48: static int c_list_in_list = 1;
! 49: static int c_nototal = 0;
! 50: static int c_nosource = 0;
! 51:
! 52: #define NEXT_ROW { \
! 53: row++; \
! 54: if (row >= rows-1) \
! 55: return; \
! 56: move(row,0); \
! 57: }
! 58:
! 59: static void putl(const char *fmt, ...)
! 60: {
! 61: va_list args;
! 62: char buf[2048];
! 63: int x, y;
! 64:
! 65: memset(buf, 0, sizeof(buf));
! 66: getyx(stdscr, y, x);
! 67:
! 68: va_start(args, fmt);
! 69: vsnprintf(buf, sizeof(buf), fmt, args);
! 70: va_end(args);
! 71:
! 72: if (strlen(buf) > cols-x)
! 73: buf[cols-x] = '\0';
! 74: else
! 75: memset(&buf[strlen(buf)], ' ', cols-strlen(buf)-x);
! 76:
! 77: addstr(buf);
! 78: }
! 79:
! 80: static void curses_init(void)
! 81: {
! 82: if (!initscr())
! 83: exit(1);
! 84:
! 85: initialized = 1;
! 86:
! 87: if (!has_colors())
! 88: c_use_colors = 0;
! 89:
! 90: if (c_use_colors) {
! 91: int i;
! 92:
! 93: start_color();
! 94:
! 95: #if defined HAVE_USE_DEFAULT_COLORS
! 96: use_default_colors();
! 97: #endif
! 98: for (i = 1; i < NR_LAYOUTS+1; i++)
! 99: init_pair(i, layout[i].fg, layout[i].bg);
! 100: }
! 101:
! 102: keypad(stdscr, TRUE);
! 103: nonl();
! 104: cbreak();
! 105: noecho();
! 106: nodelay(stdscr, TRUE); /* getch etc. must be non-blocking */
! 107: clear();
! 108: curs_set(0);
! 109: }
! 110:
! 111: static void curses_shutdown(void)
! 112: {
! 113: if (initialized)
! 114: endwin();
! 115: }
! 116:
! 117: static void draw_item_list_entry(item_t *intf, node_t *node)
! 118: {
! 119: int rxprec, txprec, rxpprec, txpprec;
! 120: stat_attr_t *bytes, *packets;
! 121: double rx, tx, rxp, txp;
! 122: char *rx_u, *tx_u, *rxp_u, *txp_u;
! 123: char pad[23];
! 124:
! 125: bytes = lookup_attr(intf, intf->i_major_attr);
! 126: packets = lookup_attr(intf, intf->i_minor_attr);
! 127:
! 128: if (bytes == NULL || packets == NULL)
! 129: return;
! 130:
! 131: rx = cancel_down(attr_get_rx_rate(bytes), bytes->a_unit, &rx_u, &rxprec);
! 132: tx = cancel_down(attr_get_tx_rate(bytes), bytes->a_unit, &tx_u, &txprec);
! 133:
! 134: rxp = cancel_down(attr_get_rx_rate(packets), packets->a_unit, &rxp_u, &rxpprec);
! 135: txp = cancel_down(attr_get_tx_rate(packets), packets->a_unit, &txp_u, &txpprec);
! 136:
! 137: memset(pad, 0, sizeof(pad));
! 138: memset(pad, ' ', intf->i_level < 15 ? intf->i_level : 15);
! 139:
! 140: strncat(pad, intf->i_name, sizeof(pad) - strlen(pad) - 1);
! 141:
! 142: if (intf->i_desc) {
! 143: strncat(pad, " (", sizeof(pad) - strlen(pad) - 1);
! 144: strncat(pad, intf->i_desc, sizeof(pad) - strlen(pad) - 1);
! 145: strncat(pad, ")", sizeof(pad) - strlen(pad) - 1);
! 146: }
! 147: NEXT_ROW;
! 148:
! 149: if (intf->i_index == node->n_selected && node == get_current_node()) {
! 150: if (c_use_colors)
! 151: attrset(COLOR_PAIR(LAYOUT_SELECTED) | layout[LAYOUT_SELECTED].attr);
! 152: else
! 153: attron(A_REVERSE);
! 154: }
! 155:
! 156: printw(" %-3d%s", intf->i_index, (intf->i_flags & ITEM_FLAG_FOLDED) ? "+" : " ");
! 157:
! 158: if (intf->i_index == node->n_selected && node == get_current_node()) {
! 159: if (c_use_colors)
! 160: attrset(COLOR_PAIR(LAYOUT_LIST) | layout[LAYOUT_LIST].attr);
! 161: else
! 162: attroff(A_REVERSE);
! 163: }
! 164:
! 165: putl("%-22s %8.*f%s %8.*f%s %2d%% %8.*f%s %8.*f%s %2d%%", pad,
! 166: rxprec, rx, rx_u, rxpprec, rxp, rxp_u, intf->i_rx_usage,
! 167: txprec, tx, tx_u, txpprec, txp, txp_u, intf->i_tx_usage);
! 168:
! 169: if (intf->i_rx_usage == -1) {
! 170: move(row, 51);
! 171: addstr(" ");
! 172: }
! 173:
! 174: if (intf->i_tx_usage == -1) {
! 175: move(row, 77);
! 176: addstr(" ");
! 177: }
! 178:
! 179: move(row, 28);
! 180: addch(ACS_VLINE);
! 181: move(row, 54);
! 182: addch(ACS_VLINE);
! 183: }
! 184:
! 185: static void handle_child(item_t *intf, void *arg)
! 186: {
! 187: node_t *node = arg;
! 188:
! 189: draw_item_list_entry(intf, node);
! 190: foreach_child(node, intf, handle_child, node);
! 191: }
! 192:
! 193:
! 194: static void draw_item(node_t *node, item_t *intf)
! 195: {
! 196: if (!intf->i_name[0] || row >= (rows - 1) || (intf->i_flags & ITEM_FLAG_IS_CHILD))
! 197: return;
! 198:
! 199: draw_item_list_entry(intf, node);
! 200:
! 201: if (!(intf->i_flags & ITEM_FLAG_FOLDED))
! 202: foreach_child(node, intf, handle_child, node);
! 203: }
! 204:
! 205:
! 206: static void draw_node(node_t *node, void *arg)
! 207: {
! 208: int i, *cnt = (int *) arg;
! 209:
! 210: if (cnt) {
! 211: if (*cnt) {
! 212: int n;
! 213: NEXT_ROW;
! 214: for (n = 1; n < cols; n += 2)
! 215: mvaddch(row, n, ACS_HLINE);
! 216: move(row, 28);
! 217: addch(ACS_VLINE);
! 218: move(row, 54);
! 219: addch(ACS_VLINE);
! 220: }
! 221: (*cnt)++;
! 222: }
! 223:
! 224: attrset(A_BOLD);
! 225: NEXT_ROW;
! 226: if (c_nosource)
! 227: putl("%s", node->n_name);
! 228: else
! 229: putl("%s (%s)", node->n_name,
! 230: node->n_from ? node->n_from : "local");
! 231:
! 232: move(row, 30);
! 233: putl(" Rate # %% Rate # %%");
! 234: attroff(A_BOLD);
! 235:
! 236: move(row, 28);
! 237: addch(ACS_VLINE);
! 238: move(row, 54);
! 239: addch(ACS_VLINE);
! 240:
! 241: if (c_use_colors)
! 242: attrset(COLOR_PAIR(LAYOUT_LIST) | layout[LAYOUT_LIST].attr);
! 243:
! 244: for (i = 0; i < node->n_nitems; i++)
! 245: draw_item(node, &node->n_items[i]);
! 246:
! 247: if (!c_nototal) {
! 248: int rx_maj_prec, tx_maj_prec, rx_min_prec, tx_min_prec;
! 249: double rx_maj, tx_maj, rx_min, tx_min;
! 250: char *rx_maj_u, *tx_maj_u, *rx_min_u, *tx_min_u;
! 251:
! 252: rx_maj = cancel_down(node->n_rx_maj_total, U_BYTES, &rx_maj_u, &rx_maj_prec);
! 253: tx_maj = cancel_down(node->n_tx_maj_total, U_BYTES, &tx_maj_u, &tx_maj_prec);
! 254:
! 255: rx_min = cancel_down(node->n_rx_min_total, U_NUMBER, &rx_min_u, &rx_min_prec);
! 256: tx_min = cancel_down(node->n_tx_min_total, U_NUMBER, &tx_min_u, &tx_min_prec);
! 257:
! 258: NEXT_ROW;
! 259: putl(" %-26s %8.*f%s %8.*f%s %8.*f%s %8.*f%s ", "Total",
! 260: rx_maj_prec, rx_maj, rx_maj_u, rx_min_prec, rx_min, rx_min_u,
! 261: tx_maj_prec, tx_maj, tx_maj_u, tx_min_prec, tx_min, tx_min_u);
! 262:
! 263: move(row, 28);
! 264: addch(ACS_VLINE);
! 265: move(row, 54);
! 266: addch(ACS_VLINE);
! 267: }
! 268:
! 269: if (c_use_colors)
! 270: attrset(COLOR_PAIR(LAYOUT_DEFAULT) | layout[LAYOUT_DEFAULT].attr);
! 271: }
! 272:
! 273: static int lines_required_for_graphical(void)
! 274: {
! 275: item_t *it;
! 276:
! 277: if ((it = get_current_item()))
! 278: return get_ngraphs() * ((2 * c_graph_height) + 5);
! 279: else
! 280: return INT_MAX;
! 281: }
! 282:
! 283: static int lines_required_for_detailed(void)
! 284: {
! 285: if (get_current_item())
! 286: return 2 + ((get_current_item()->i_nattrs + 1) / 2);
! 287: else
! 288: return INT_MAX;
! 289: }
! 290:
! 291: static void __draw_graphic(stat_attr_hist_t *a, int selected, int xunit)
! 292: {
! 293: int w;
! 294: graph_t *g;
! 295: g = create_configued_graph(&a->a_hist, c_graph_height, a->a_unit, xunit);
! 296:
! 297: NEXT_ROW;
! 298: putl("RX %s [%s]",
! 299: g->g_rx.t_y_unit, type2desc(a->a_type));
! 300:
! 301: if (selected) {
! 302: move(row, 72);
! 303: attron(A_BOLD);
! 304: addstr("(sel)");
! 305: attroff(A_BOLD);
! 306: move(row, 0);
! 307: }
! 308:
! 309: for (w = (c_graph_height - 1); w >= 0; w--) {
! 310: NEXT_ROW;
! 311: putl(" %8.2f %s\n", g->g_rx.t_y_scale[w], (char *) g->g_rx.t_data + (w * (HISTORY_SIZE + 1)));
! 312: }
! 313:
! 314: move(row, 71);
! 315: putl("[%.2f%%]", rtiming.rt_variance.v_error);
! 316: NEXT_ROW;
! 317: putl(" 1 5 10 15 20 25 30 35 40 45 50 55 60 %s", g->g_rx.t_x_unit);
! 318:
! 319: NEXT_ROW;
! 320: putl("TX %s", g->g_tx.t_y_unit);
! 321:
! 322: for (w = (c_graph_height - 1); w >= 0; w--) {
! 323: NEXT_ROW;
! 324: putl(" %8.2f %s\n", g->g_tx.t_y_scale[w], (char *) g->g_tx.t_data + (w * (HISTORY_SIZE + 1)));
! 325: }
! 326:
! 327: move(row, 71);
! 328: putl("[%.2f%%]", rtiming.rt_variance.v_error);
! 329: NEXT_ROW;
! 330: putl(" 1 5 10 15 20 25 30 35 40 45 50 55 60 %s", g->g_tx.t_x_unit);
! 331:
! 332: free_graph(g);
! 333: }
! 334:
! 335: static void draw_graphic(void)
! 336: {
! 337: int i;
! 338:
! 339: for (i = 0; i < get_ngraphs(); i++) {
! 340: stat_attr_hist_t *a = (stat_attr_hist_t *) current_attr(i);
! 341:
! 342: if (!(a->a_flags & ATTR_FLAG_HISTORY))
! 343: continue;
! 344:
! 345: if (a)
! 346: __draw_graphic(a, get_current_item()->i_graph_sel == i,
! 347: get_current_item()->i_unit[i]);
! 348:
! 349: if (i < (get_ngraphs() - 1)) {
! 350: int n;
! 351: NEXT_ROW;
! 352: for (n = 1; n < cols-1; n += 2)
! 353: mvaddch(row, n, ACS_HLINE);
! 354: }
! 355: }
! 356:
! 357: }
! 358:
! 359: static void draw_attr_detail(stat_attr_t *attr, void *arg)
! 360: {
! 361: int rxprec, txprec;
! 362: double rx, tx;
! 363: char *rxu, *txu;
! 364: int *t = (int *) arg;
! 365:
! 366: rx = cancel_down(attr_get_rx(attr), attr->a_unit, &rxu, &rxprec);
! 367: tx = cancel_down(attr_get_tx(attr), attr->a_unit, &txu, &txprec);
! 368:
! 369: if (0 == *t) {
! 370: NEXT_ROW;
! 371: putl(" %-12s%9.*f%-3s %9.*f%-3s",
! 372: type2desc(attr->a_type),
! 373: rxprec, rx, rxu, txprec, tx, txu);
! 374:
! 375: if (!(attr->a_flags & ATTR_FLAG_RX_ENABLED)) {
! 376: move(row, 20);
! 377: addstr("N/A");
! 378: }
! 379:
! 380: if (!(attr->a_flags & ATTR_FLAG_TX_ENABLED)) {
! 381: move(row, 33);
! 382: addstr("N/A");
! 383: }
! 384:
! 385: move(row, 40);
! 386: *t = 1;
! 387: } else {
! 388: putl(" %-12s%9.*f%-3s %9.*f%-3s",
! 389: type2desc(attr->a_type),
! 390: rxprec, rx, rxu, txprec, tx, txu);
! 391:
! 392: if (!(attr->a_flags & ATTR_FLAG_RX_ENABLED)) {
! 393: move(row, 60);
! 394: addstr("N/A");
! 395: }
! 396:
! 397: if (!(attr->a_flags & ATTR_FLAG_TX_ENABLED)) {
! 398: move(row, 73);
! 399: addstr("N/A");
! 400: }
! 401:
! 402: move(row, 0);
! 403: *t = 0;
! 404: }
! 405: }
! 406:
! 407: static void draw_detailed(void)
! 408: {
! 409: int start_pos, end_pos, i;
! 410: item_t *intf;
! 411: int attr_flag = 0;
! 412:
! 413: intf = get_current_item();
! 414:
! 415: if (NULL == intf)
! 416: return;
! 417:
! 418: move(row, 39);
! 419: addch(ACS_TTEE);
! 420: move(row, 0);
! 421:
! 422: NEXT_ROW;
! 423: start_pos = row;
! 424: putl(" RX TX " \
! 425: " RX TX");
! 426:
! 427: foreach_attr(intf, draw_attr_detail, &attr_flag);
! 428:
! 429: end_pos = row;
! 430: for (i = start_pos; i <= end_pos; i++) {
! 431: move(i, 39);
! 432: addch(ACS_VLINE);
! 433: }
! 434: move(end_pos, 0);
! 435: }
! 436:
! 437: static void print_quit(void)
! 438: {
! 439: /*
! 440: * This could be done with ncurses windows but i'm way too lazy to
! 441: * look into it
! 442: */
! 443: int i, y = (rows/2) - 2;
! 444: char *text = " Really Quit? (y/n) ";
! 445: int len = strlen(text);
! 446: int x = (cols/2) - (len / 2);
! 447:
! 448: attrset(A_STANDOUT);
! 449: mvaddch(y - 2, x - 1, ACS_ULCORNER);
! 450: mvaddch(y + 2, x - 1, ACS_LLCORNER);
! 451: mvaddch(y - 2, x + len, ACS_URCORNER);
! 452: mvaddch(y + 2, x + len, ACS_LRCORNER);
! 453:
! 454: for (i = 0; i < 3; i++) {
! 455: mvaddch(y - 1 + i, x + len, ACS_VLINE);
! 456: mvaddch(y - 1 + i, x - 1 ,ACS_VLINE);
! 457: }
! 458:
! 459: for (i = 0; i < len; i++) {
! 460: mvaddch(y - 2, x + i, ACS_HLINE);
! 461: mvaddch(y - 1, x + i, ' ');
! 462: mvaddch(y + 1, x + i, ' ');
! 463: mvaddch(y + 2, x + i, ACS_HLINE);
! 464: }
! 465:
! 466: mvaddstr(y, x, text);
! 467: attroff(A_STANDOUT);
! 468: }
! 469:
! 470: static void draw_help(void)
! 471: {
! 472: #define HW 46
! 473: #define HH 19
! 474: int i, y = (rows/2) - (HH/2);
! 475: int x = (cols/2) - (HW/2);
! 476: char pad[HW+1];
! 477:
! 478: memset(pad, ' ', sizeof(pad));
! 479: pad[sizeof(pad) - 1] = '\0';
! 480:
! 481: attron(A_STANDOUT);
! 482:
! 483: for (i = 0; i < HH; i++)
! 484: mvaddnstr(y + i, x, pad, -1);
! 485:
! 486: mvaddch(y - 1, x - 1, ACS_ULCORNER);
! 487: mvaddch(y + HH, x - 1, ACS_LLCORNER);
! 488:
! 489: mvaddch(y - 1, x + HW, ACS_URCORNER);
! 490: mvaddch(y + HH, x + HW, ACS_LRCORNER);
! 491:
! 492: for (i = 0; i < HH; i++) {
! 493: mvaddch(y + i, x - 1, ACS_VLINE);
! 494: mvaddch(y + i, x + HW, ACS_VLINE);
! 495: }
! 496:
! 497: for (i = 0; i < HW; i++) {
! 498: mvaddch(y - 1, x + i, ACS_HLINE);
! 499: mvaddch(y + HH, x + i, ACS_HLINE);
! 500: }
! 501:
! 502: attron(A_BOLD);
! 503: mvaddnstr(y- 1, x+15, "QUICK REFERENCE", -1);
! 504: attron(A_UNDERLINE);
! 505: mvaddnstr(y+ 0, x+3, "Navigation", -1);
! 506: attroff(A_BOLD | A_UNDERLINE);
! 507: mvaddnstr(y+ 0, x+35, "[Page 1/2]", -1);
! 508:
! 509: mvaddnstr(y+ 1, x+5, "Up Previous interface", -1);
! 510: mvaddnstr(y+ 2, x+5, "Down Next interface", -1);
! 511: mvaddnstr(y+ 3, x+5, "Pg-Up Previous node", -1);
! 512: mvaddnstr(y+ 4, x+5, "Pg-Down Next node", -1);
! 513: mvaddnstr(y+ 5, x+5, "< Previous graph", -1);
! 514: mvaddnstr(y+ 6, x+5, "> Next graph", -1);
! 515: mvaddnstr(y+ 7, x+5, "0-9 Goto n-th interface", -1);
! 516: mvaddnstr(y+ 8, x+5, "? Toggle quick reference", -1);
! 517: mvaddnstr(y+ 9, x+5, "q Quit bmon", -1);
! 518:
! 519: attron(A_BOLD | A_UNDERLINE);
! 520: mvaddnstr(y+11, x+3, "Display Settings", -1);
! 521: attroff(A_BOLD | A_UNDERLINE);
! 522:
! 523: mvaddnstr(y+12, x+5, "g Toggle graphical statistics", -1);
! 524: mvaddnstr(y+13, x+5, "d Toggle detailed statistics", -1);
! 525: mvaddnstr(y+14, x+5, "c Toggle combined node list", -1);
! 526: mvaddnstr(y+15, x+5, "l Toggle interface list", -1);
! 527: mvaddnstr(y+16, x+5, "f (Un)fold sub interfaces", -1);
! 528:
! 529: attroff(A_STANDOUT);
! 530: }
! 531:
! 532: static void draw_help_2(void)
! 533: {
! 534: #define HW 46
! 535: #define HH 19
! 536: int i, y = (rows/2) - (HH/2);
! 537: int x = (cols/2) - (HW/2);
! 538: char pad[HW+1];
! 539:
! 540: memset(pad, ' ', sizeof(pad));
! 541: pad[sizeof(pad) - 1] = '\0';
! 542:
! 543: attron(A_STANDOUT);
! 544:
! 545: for (i = 0; i < HH; i++)
! 546: mvaddnstr(y + i, x, pad, -1);
! 547:
! 548: mvaddch(y - 1, x - 1, ACS_ULCORNER);
! 549: mvaddch(y + HH, x - 1, ACS_LLCORNER);
! 550:
! 551: mvaddch(y - 1, x + HW, ACS_URCORNER);
! 552: mvaddch(y + HH, x + HW, ACS_LRCORNER);
! 553:
! 554: for (i = 0; i < HH; i++) {
! 555: mvaddch(y + i, x - 1, ACS_VLINE);
! 556: mvaddch(y + i, x + HW, ACS_VLINE);
! 557: }
! 558:
! 559: for (i = 0; i < HW; i++) {
! 560: mvaddch(y - 1, x + i, ACS_HLINE);
! 561: mvaddch(y + HH, x + i, ACS_HLINE);
! 562: }
! 563:
! 564: attron(A_BOLD);
! 565: mvaddnstr(y- 1, x+15, "QUICK REFERENCE", -1);
! 566: attron(A_UNDERLINE);
! 567: mvaddnstr(y+ 0, x+3, "Graph Management", -1);
! 568: attroff(A_BOLD | A_UNDERLINE);
! 569: mvaddnstr(y+ 0, x+35, "[Page 2/2]", -1);
! 570:
! 571: mvaddnstr(y+ 1, x+5, "n New graph", -1);
! 572: mvaddnstr(y+ 2, x+5, "x Delete graph", -1);
! 573: mvaddnstr(y+ 3, x+5, "a Next attribute", -1);
! 574:
! 575: attron(A_BOLD | A_UNDERLINE);
! 576: mvaddnstr(y+ 5, x+3, "Measurement Units", -1);
! 577: attroff(A_BOLD | A_UNDERLINE);
! 578:
! 579: mvaddnstr(y+ 6, x+5, "R Read Interval", -1);
! 580: mvaddnstr(y+ 7, x+5, "S Seconds", -1);
! 581: mvaddnstr(y+ 8, x+5, "M Minutes", -1);
! 582: mvaddnstr(y+ 9, x+5, "H Hours", -1);
! 583: mvaddnstr(y+10, x+5, "D Days", -1);
! 584: attroff(A_STANDOUT);
! 585: }
! 586:
! 587: static void print_content(void)
! 588: {
! 589: int cnt = 0;
! 590: int required_lines = 0, disable_detailed = 0, disabled_graphical = 0;
! 591:
! 592: if (NULL == get_current_node())
! 593: return;
! 594:
! 595: if (c_list_in_list) {
! 596: NEXT_ROW;
! 597: attron(A_BOLD);
! 598: putl(" Name RX TX");
! 599: attron(A_BOLD);
! 600:
! 601: if (c_use_colors)
! 602: attrset(COLOR_PAIR(LAYOUT_HEADER) | layout[LAYOUT_HEADER].attr);
! 603:
! 604: NEXT_ROW;
! 605: hline(ACS_HLINE, cols);
! 606:
! 607: move(row, 28);
! 608: addch(ACS_TTEE);
! 609: move(row, 54);
! 610: addch(ACS_TTEE);
! 611: move(row, 0);
! 612:
! 613: if (c_combined_node_list)
! 614: foreach_node(draw_node, &cnt);
! 615: else
! 616: draw_node(get_current_node(), NULL);
! 617: } else {
! 618: NEXT_ROW;
! 619: hline(ACS_HLINE, cols);
! 620: move(row, 24);
! 621: addstr(" Press l to enable list view ");
! 622: move(row, 0);
! 623: }
! 624:
! 625: /*
! 626: * calculate lines required for graphical and detailed stats unfolded
! 627: */
! 628: if (c_graphical_in_list)
! 629: required_lines += lines_required_for_graphical();
! 630: else
! 631: required_lines++;
! 632:
! 633: if (c_detailed_in_list)
! 634: required_lines += lines_required_for_detailed();
! 635: else
! 636: required_lines++;
! 637:
! 638: if ((rows - row) <= (required_lines + 1)) {
! 639: /*
! 640: * not enough lines, start over with detailed stats disabled
! 641: */
! 642: required_lines = 0;
! 643: disable_detailed = 1;
! 644:
! 645: /*
! 646: * 1 line for folded detailed stats display
! 647: */
! 648: required_lines++;
! 649:
! 650: if (c_graphical_in_list)
! 651: required_lines += lines_required_for_graphical();
! 652: else
! 653: required_lines++;
! 654:
! 655: if ((rows - row) <= (required_lines + 1)) {
! 656: /*
! 657: * bad luck, not even enough space for graphical stats
! 658: * reserve 2 lines for displaying folded detailed and
! 659: * graphical stats
! 660: */
! 661: required_lines = 2;
! 662: disabled_graphical = 1;
! 663: }
! 664: }
! 665:
! 666: /*
! 667: * Clear out spare space
! 668: */
! 669: while (row < (rows - (required_lines + 2))) {
! 670: NEXT_ROW; putl("");
! 671: move(row, 28);
! 672: addch(ACS_VLINE);
! 673: move(row, 54);
! 674: addch(ACS_VLINE);
! 675: }
! 676:
! 677: NEXT_ROW;
! 678: hline(ACS_HLINE, cols);
! 679:
! 680: if (c_graphical_in_list) {
! 681: if (disabled_graphical) {
! 682: move(row, 15);
! 683: addstr(" Increase screen size to see graphical statistics ");
! 684: move(row, 0);
! 685: } else {
! 686: move(row, 28);
! 687: addch(ACS_BTEE);
! 688: move(row, 54);
! 689: addch(ACS_BTEE);
! 690: move(row, 0);
! 691: draw_graphic();
! 692: }
! 693: } else {
! 694: move(row, 20);
! 695: addstr(" Press g to enable graphical statistics ");
! 696: move(row, 0);
! 697: }
! 698:
! 699: NEXT_ROW;
! 700: hline(ACS_HLINE, cols);
! 701:
! 702: if (c_detailed_in_list) {
! 703: if (disable_detailed) {
! 704: move(row, 15);
! 705: addstr(" Increase screen size to see detailed statistics ");
! 706: move(row, 0);
! 707: } else
! 708: draw_detailed();
! 709: } else {
! 710: move(row, 20);
! 711: addstr(" Press d to enable detailed statistics ");
! 712: move(row, 0);
! 713: }
! 714: }
! 715:
! 716:
! 717:
! 718: static void curses_draw(void)
! 719: {
! 720: if (NULL == get_current_node()) {
! 721: first_node();
! 722: first_item();
! 723: }
! 724:
! 725: row = 0;
! 726: move(0,0);
! 727:
! 728: getmaxyx(stdscr, rows, cols);
! 729:
! 730: if (cols < 80) {
! 731: clear();
! 732: putl("Screen must be at least 80 columns wide");
! 733: refresh();
! 734: return;
! 735: }
! 736:
! 737: if (c_use_colors)
! 738: attrset(COLOR_PAIR(LAYOUT_STATUSBAR) | layout[LAYOUT_STATUSBAR].attr);
! 739: else
! 740: attrset(A_REVERSE);
! 741:
! 742: if (get_current_node() && get_current_item()) {
! 743: putl(" %s on %s",
! 744: get_current_item()->i_name, get_current_node()->n_name);
! 745: }
! 746:
! 747: move(row, COLS - strlen(PACKAGE_STRING) - 1);
! 748: putl("%s", PACKAGE_STRING);
! 749: move(row, 0);
! 750:
! 751: if (c_use_colors)
! 752: attrset(COLOR_PAIR(LAYOUT_DEFAULT) | layout[LAYOUT_DEFAULT].attr);
! 753: else
! 754: attroff(A_REVERSE);
! 755:
! 756: print_content();
! 757:
! 758: if (quit_mode)
! 759: print_quit();
! 760: else if (print_help) {
! 761: if (help_page == 0)
! 762: draw_help();
! 763: else
! 764: draw_help_2();
! 765: }
! 766:
! 767: for (; row < rows-2;) {
! 768: move(++row, 0);
! 769: putl("");
! 770: }
! 771:
! 772: row = rows-1;
! 773: move(row, 0);
! 774:
! 775: if (c_use_colors)
! 776: attrset(COLOR_PAIR(LAYOUT_STATUSBAR) | layout[LAYOUT_STATUSBAR].attr);
! 777: else
! 778: attrset(A_REVERSE);
! 779:
! 780: if (1) {
! 781: char s[27];
! 782: time_t t = time(0);
! 783: double d;
! 784: int h, m;
! 785:
! 786: asctime_r(localtime(&t), s);
! 787: s[strlen(s) - 1] = '\0';
! 788: d = difftime(time(0), start_time);
! 789:
! 790: if (d / 3600) {
! 791: h = (int) d / 3600;
! 792: m = (int) d % 3600;
! 793: m /= 60;
! 794: } else {
! 795: h = 0;
! 796: m = (int) d / 60;
! 797: }
! 798:
! 799: putl(" %s (%dh/%dm)", s, h, m);
! 800: move(row, COLS - strlen("Press ? for help") - 1);
! 801: putl("%s", "Press ? for help");
! 802: move(row, 0);
! 803: }
! 804:
! 805: attrset(0);
! 806: refresh();
! 807: }
! 808:
! 809: static void fold(void)
! 810: {
! 811: item_t *intf = get_current_item();
! 812: node_t *node = get_current_node();
! 813: int fix = 0;
! 814:
! 815: if (NULL == intf || NULL == node)
! 816: return;
! 817:
! 818: if (intf->i_flags & ITEM_FLAG_IS_CHILD)
! 819: fix = 1;
! 820:
! 821: while (intf->i_flags & ITEM_FLAG_IS_CHILD)
! 822: intf = get_item(node, intf->i_parent);
! 823:
! 824: if (intf->i_flags & ITEM_FLAG_FOLDED)
! 825: intf->i_flags &= ~ITEM_FLAG_FOLDED;
! 826: else
! 827: intf->i_flags |= ITEM_FLAG_FOLDED;
! 828:
! 829: if (fix)
! 830: prev_item();
! 831: }
! 832:
! 833: static int handle_input(int ch)
! 834: {
! 835: switch (ch)
! 836: {
! 837: case 'q':
! 838: quit_mode = quit_mode ? 0 : 1;
! 839: return 1;
! 840:
! 841: case 0x1b:
! 842: quit_mode = 0;
! 843: print_help = 0;
! 844: return 1;
! 845:
! 846: case 'y':
! 847: if (quit_mode)
! 848: exit(0);
! 849: break;
! 850:
! 851: case 'a':
! 852: next_attr();
! 853: return 1;
! 854:
! 855: case 'n':
! 856: if (quit_mode)
! 857: quit_mode = 0;
! 858: else
! 859: new_graph();
! 860: return 1;
! 861:
! 862: case 'x':
! 863: del_graph();
! 864: return 1;
! 865:
! 866: case 'f':
! 867: fold();
! 868: return 1;
! 869:
! 870: case 12:
! 871: case KEY_CLEAR:
! 872: #ifdef HAVE_REDRAWWIN
! 873: redrawwin(stdscr);
! 874: #endif
! 875: clear();
! 876: return 1;
! 877:
! 878: case 'c':
! 879: c_combined_node_list = c_combined_node_list ? 0 : 1;
! 880: return 1;
! 881:
! 882: case 'S':
! 883: clear();
! 884: set_graph_unit(X_SEC);
! 885: return 1;
! 886:
! 887: case 'M':
! 888: clear();
! 889: set_graph_unit(X_MIN);
! 890: return 1;
! 891:
! 892: case 'H':
! 893: clear();
! 894: set_graph_unit(X_HOUR);
! 895: return 1;
! 896:
! 897: case 'D':
! 898: clear();
! 899: set_graph_unit(X_DAY);
! 900: return 1;
! 901:
! 902: case 'R':
! 903: clear();
! 904: set_graph_unit(X_READ);
! 905: return 1;
! 906:
! 907: case '?':
! 908: clear();
! 909: print_help = print_help ? 0 : 1;
! 910: return 1;
! 911:
! 912: case 'g':
! 913: c_graphical_in_list = c_graphical_in_list ? 0 : 1;
! 914: return 1;
! 915:
! 916: case 'd':
! 917: c_detailed_in_list = c_detailed_in_list ? 0 : 1;
! 918: return 1;
! 919:
! 920: case 'l':
! 921: c_list_in_list = c_list_in_list ? 0 : 1;
! 922: return 1;
! 923:
! 924: case KEY_PPAGE:
! 925: if (print_help)
! 926: help_page = help_page ? 0 : 1;
! 927: else
! 928: prev_node();
! 929: return 1;
! 930:
! 931: case KEY_NPAGE:
! 932: if (print_help)
! 933: help_page = help_page ? 0 : 1;
! 934: else
! 935: next_node();
! 936: return 1;
! 937:
! 938: case KEY_DOWN:
! 939: if (next_item() == END_OF_LIST) {
! 940: if (next_node() != END_OF_LIST)
! 941: first_item();
! 942: }
! 943: return 1;
! 944:
! 945: case KEY_UP:
! 946: if (prev_item() == END_OF_LIST) {
! 947: if (prev_node() != END_OF_LIST)
! 948: last_item();
! 949: }
! 950: return 1;
! 951:
! 952: case '0':
! 953: case '1':
! 954: case '2':
! 955: case '3':
! 956: case '4':
! 957: case '5':
! 958: case '6':
! 959: case '7':
! 960: case '8':
! 961: case '9':
! 962: goto_item(ch - 48);
! 963: return 1;
! 964:
! 965: case '>':
! 966: next_graph();
! 967: return 1;
! 968:
! 969: case '<':
! 970: prev_graph();
! 971: return 1;
! 972:
! 973: default:
! 974: if (get_current_item())
! 975: if (handle_bindings(ch, get_current_item()->i_name))
! 976: return 1;
! 977: break;
! 978: }
! 979:
! 980: return 0;
! 981: }
! 982:
! 983: static void curses_pre(void)
! 984: {
! 985: for (;;) {
! 986: int ch = getch();
! 987:
! 988: if (ch == -1)
! 989: break;
! 990:
! 991: if (handle_input(ch))
! 992: curses_draw();
! 993: }
! 994: }
! 995:
! 996: static int curses_probe(void)
! 997: {
! 998: /* XXX? */
! 999: return 1;
! 1000: }
! 1001:
! 1002: static void print_module_help(void)
! 1003: {
! 1004: printf(
! 1005: "curses - Curses Output\n" \
! 1006: "\n" \
! 1007: " Interactive curses UI. Type '?' to get some help.\n" \
! 1008: " Author: Thomas Graf <tgraf@suug.ch>\n" \
! 1009: "\n" \
! 1010: " Options:\n" \
! 1011: " fgchar=CHAR Foreground character (default: '*')\n" \
! 1012: " bgchar=CHAR Background character (default: '.')\n" \
! 1013: " nchar=CHAR Noise character (default: ':')\n" \
! 1014: " uchar=CHAR Unknown character (default: '?')\n" \
! 1015: " height=NUM Height of graph (default: 6)\n" \
! 1016: " xunit=UNIT X-Axis Unit (default: seconds)\n" \
! 1017: " yunit=UNIT Y-Axis Unit (default: dynamic)\n" \
! 1018: " nocolors Do not use colors\n" \
! 1019: " nototal Do not print per node total\n" \
! 1020: " nosource Do not print the source of a item\n" \
! 1021: " cnl Combined node list\n" \
! 1022: " graph Show graphical stats by default\n" \
! 1023: " detail Show detailed stats by default\n");
! 1024: }
! 1025:
! 1026: static void curses_set_opts(tv_t *attrs)
! 1027: {
! 1028: while (attrs) {
! 1029: if (!strcasecmp(attrs->type, "fgchar") && attrs->value)
! 1030: set_fg_char(attrs->value[0]);
! 1031: else if (!strcasecmp(attrs->type, "bgchar") && attrs->value)
! 1032: set_bg_char(attrs->value[0]);
! 1033: else if (!strcasecmp(attrs->type, "nchar") && attrs->value)
! 1034: set_noise_char(attrs->value[0]);
! 1035: else if (!strcasecmp(attrs->type, "uchar") && attrs->value)
! 1036: set_unk_char(attrs->value[0]);
! 1037: else if (!strcasecmp(attrs->type, "xunit") && attrs->value)
! 1038: set_x_unit(attrs->value, 1);
! 1039: else if (!strcasecmp(attrs->type, "yunit") && attrs->value)
! 1040: set_y_unit(attrs->value);
! 1041: else if (!strcasecmp(attrs->type, "height") && attrs->value)
! 1042: c_graph_height = strtol(attrs->value, NULL, 0);
! 1043: else if (!strcasecmp(attrs->type, "cnl"))
! 1044: c_combined_node_list = 1;
! 1045: else if (!strcasecmp(attrs->type, "graph"))
! 1046: c_graphical_in_list = 1;
! 1047: else if (!strcasecmp(attrs->type, "detail"))
! 1048: c_detailed_in_list = 1;
! 1049: else if (!strcasecmp(attrs->type, "nocolors"))
! 1050: c_use_colors = 0;
! 1051: else if (!strcasecmp(attrs->type, "nototal"))
! 1052: c_nototal = 1;
! 1053: else if (!strcasecmp(attrs->type, "nosource"))
! 1054: c_nosource = 1;
! 1055: else if (!strcasecmp(attrs->type, "help")) {
! 1056: print_module_help();
! 1057: exit(0);
! 1058: }
! 1059:
! 1060: attrs = attrs->next;
! 1061: }
! 1062: }
! 1063:
! 1064: static struct output_module curses_ops = {
! 1065: .om_name = "curses",
! 1066: .om_init = curses_init,
! 1067: .om_shutdown = curses_shutdown,
! 1068: .om_pre = curses_pre,
! 1069: .om_draw = curses_draw,
! 1070: .om_set_opts = curses_set_opts,
! 1071: .om_probe = curses_probe,
! 1072: };
! 1073:
! 1074: static void __init do_curses_init(void)
! 1075: {
! 1076: register_output_module(&curses_ops);
! 1077: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>