Annotation of embedaddon/bmon/src/out_curses.c, revision 1.1.1.2
1.1 misho 1: /*
2: * out_curses.c Curses Output
3: *
1.1.1.2 ! misho 4: * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
! 5: * Copyright (c) 2013 Red Hat, Inc.
1.1 misho 6: *
7: * Permission is hereby granted, free of charge, to any person obtaining a
8: * copy of this software and associated documentation files (the "Software"),
9: * to deal in the Software without restriction, including without limitation
10: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11: * and/or sell copies of the Software, and to permit persons to whom the
12: * Software is furnished to do so, subject to the following conditions:
13: *
14: * The above copyright notice and this permission notice shall be included
15: * in all copies or substantial portions of the Software.
16: *
17: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23: * DEALINGS IN THE SOFTWARE.
24: */
25:
26: #include <bmon/bmon.h>
27: #include <bmon/conf.h>
1.1.1.2 ! misho 28: #include <bmon/attr.h>
! 29: #include <bmon/element.h>
! 30: #include <bmon/element_cfg.h>
1.1 misho 31: #include <bmon/input.h>
1.1.1.2 ! misho 32: #include <bmon/history.h>
! 33: #include <bmon/graph.h>
1.1 misho 34: #include <bmon/output.h>
35: #include <bmon/utils.h>
36:
1.1.1.2 ! misho 37: enum {
! 38: GRAPH_DISPLAY_SIDE_BY_SIDE = 1,
! 39: GRAPH_DISPLAY_STANDARD = 2,
! 40: };
! 41:
! 42: enum {
! 43: KEY_TOGGLE_LIST = 'l',
! 44: KEY_TOGGLE_GRAPH = 'g',
! 45: KEY_TOGGLE_DETAILS = 'd',
! 46: KEY_TOGGLE_INFO = 'i',
! 47: KEY_COLLECT_HISTORY = 'h',
! 48: };
! 49:
! 50: #define DETAILS_COLS 40
! 51:
! 52: #define LIST_COL_1 31
! 53: #define LIST_COL_2 55
! 54:
! 55: /* Set to element_current() before drawing */
! 56: static struct element *current_element;
! 57:
! 58: static struct attr *current_attr;
! 59:
! 60: /* Length of list to draw, updated in draw_content() */
! 61: static int list_length;
! 62:
! 63: static int list_req;
! 64:
! 65: /* Number of graphs to draw (may be < c_ngraph) */
! 66: static int ngraph;
! 67:
! 68: /*
! 69: * Offset in number of lines within the the element list of the currently
! 70: * selected element. Updated while summing up required lines.
! 71: */
! 72: static unsigned int selection_offset;
! 73:
! 74: /*
! 75: * Offset in number of lines of the first element to be drawn. Updated
! 76: * in draw_content()
! 77: */
! 78: static int offset;
! 79:
! 80: /*
! 81: * Offset to the first graph to draw in number of attributes with graphs.
! 82: */
! 83: static unsigned int graph_offset;
! 84:
! 85: static int graph_display = GRAPH_DISPLAY_STANDARD;
! 86:
! 87: /*
! 88: * Number of detail columns
! 89: */
! 90: static int detail_cols;
! 91: static int info_cols;
! 92:
1.1 misho 93: static int initialized;
1.1.1.2 ! misho 94: static int print_help;
! 95: static int quit_mode;
! 96: static int help_page;
! 97:
! 98: /* Current row */
1.1 misho 99: static int row;
1.1.1.2 ! misho 100:
! 101: /* Number of rows */
1.1 misho 102: static int rows;
1.1.1.2 ! misho 103:
! 104: /* Number of columns */
1.1 misho 105: static int cols;
106:
1.1.1.2 ! misho 107: static int c_show_graph = 1;
! 108: static int c_ngraph = 1;
1.1 misho 109: static int c_use_colors = 1;
1.1.1.2 ! misho 110: static int c_show_details = 0;
! 111: static int c_show_list = 1;
! 112: static int c_show_info = 0;
! 113: static int c_list_min = 6;
! 114:
! 115: static struct graph_cfg c_graph_cfg = {
! 116: .gc_width = 60,
! 117: .gc_height = 6,
! 118: .gc_foreground = '|',
! 119: .gc_background = '.',
! 120: .gc_noise = ':',
! 121: .gc_unknown = '?',
! 122: };
! 123:
! 124: #define NEXT_ROW() \
! 125: do { \
! 126: row++; \
! 127: if (row >= rows - 1) \
! 128: return; \
! 129: move(row, 0); \
! 130: } while(0)
! 131:
! 132: static void apply_layout(int layout)
! 133: {
! 134: if (c_use_colors)
! 135: attrset(COLOR_PAIR(layout) | cfg_layout[layout].l_attr);
! 136: else
! 137: attrset(cfg_layout[layout].l_attr);
! 138: }
! 139:
! 140: char *float2str(double value, int width, int prec, char *buf, size_t len)
! 141: {
! 142: snprintf(buf, len, "%'*.*f", width, value == 0.0f ? 0 : prec, value);
1.1 misho 143:
1.1.1.2 ! misho 144: return buf;
1.1 misho 145: }
146:
1.1.1.2 ! misho 147: static void put_line(const char *fmt, ...)
1.1 misho 148: {
1.1.1.2 ! misho 149: va_list args;
! 150: char buf[2048];
! 151: int x, y;
1.1 misho 152:
1.1.1.2 ! misho 153: memset(buf, 0, sizeof(buf));
! 154: getyx(stdscr, y, x);
1.1 misho 155:
1.1.1.2 ! misho 156: va_start(args, fmt);
! 157: vsnprintf(buf, sizeof(buf), fmt, args);
! 158: va_end(args);
1.1 misho 159:
1.1.1.2 ! misho 160: if (strlen(buf) > cols-x)
! 161: buf[cols - x] = '\0';
! 162: else
! 163: memset(&buf[strlen(buf)], ' ', cols - strlen(buf)-x);
1.1 misho 164:
1.1.1.2 ! misho 165: addstr(buf);
1.1 misho 166: }
167:
1.1.1.2 ! misho 168: static void center_text(const char *fmt, ...)
1.1 misho 169: {
1.1.1.2 ! misho 170: va_list args;
! 171: char *str;
! 172: unsigned int col;
! 173:
! 174: va_start(args, fmt);
! 175: vasprintf(&str, fmt, args);
! 176: va_end(args);
! 177:
! 178: col = (cols / 2) - (strlen(str) / 2);
! 179: if (col > cols - 1)
! 180: col = cols - 1;
! 181:
! 182: move(row, col);
! 183: addstr(str);
! 184: move(row, 0);
! 185:
! 186: free(str);
! 187: }
! 188:
! 189: static int curses_init(void)
! 190: {
! 191: if (!initscr()) {
! 192: fprintf(stderr, "Unable to initialize curses screen\n");
! 193: return -EOPNOTSUPP;
! 194: }
1.1 misho 195:
196: initialized = 1;
197:
198: if (!has_colors())
199: c_use_colors = 0;
200:
201: if (c_use_colors) {
202: int i;
203:
204: start_color();
205:
206: #if defined HAVE_USE_DEFAULT_COLORS
207: use_default_colors();
208: #endif
1.1.1.2 ! misho 209: for (i = 1; i < LAYOUT_MAX+1; i++)
! 210: init_pair(i, cfg_layout[i].l_fg, cfg_layout[i].l_bg);
1.1 misho 211: }
212:
213: keypad(stdscr, TRUE);
214: nonl();
215: cbreak();
216: noecho();
217: nodelay(stdscr, TRUE); /* getch etc. must be non-blocking */
218: clear();
219: curs_set(0);
1.1.1.2 ! misho 220:
! 221: return 0;
1.1 misho 222: }
223:
224: static void curses_shutdown(void)
225: {
226: if (initialized)
227: endwin();
228: }
229:
1.1.1.2 ! misho 230: struct detail_arg
1.1 misho 231: {
1.1.1.2 ! misho 232: int nattr;
! 233: };
1.1 misho 234:
1.1.1.2 ! misho 235: static void draw_attr_detail(struct element *e, struct attr *a, void *arg)
! 236: {
! 237: char *rx_u, *tx_u, buf1[32], buf2[32];
! 238: int rxprec, txprec, ncol;
! 239: struct detail_arg *da = arg;
! 240:
! 241: double rx = unit_value2str(a->a_rx_rate.r_total,
! 242: a->a_def->ad_unit,
! 243: &rx_u, &rxprec);
! 244: double tx = unit_value2str(a->a_tx_rate.r_total,
! 245: a->a_def->ad_unit,
! 246: &tx_u, &txprec);
! 247:
! 248: if (da->nattr >= detail_cols) {
! 249: NEXT_ROW();
! 250: da->nattr = 0;
! 251: }
! 252:
! 253: ncol = (da->nattr * DETAILS_COLS) - 1;
! 254: move(row, ncol);
! 255: if (ncol > 0)
! 256: addch(ACS_VLINE);
1.1 misho 257:
1.1.1.2 ! misho 258: put_line(" %-14.14s %8s%-3s %8s%-3s\n",
! 259: a->a_def->ad_description,
! 260: (a->a_flags & ATTR_RX_ENABLED) ?
! 261: float2str(rx, 8, rxprec, buf1, sizeof(buf1)) : "-", rx_u,
! 262: (a->a_flags & ATTR_TX_ENABLED) ?
! 263: float2str(tx, 8, txprec, buf2, sizeof(buf2)) : "-", tx_u);
1.1 misho 264:
1.1.1.2 ! misho 265: da->nattr++;
! 266: }
1.1 misho 267:
1.1.1.2 ! misho 268: static void draw_details(void)
! 269: {
! 270: int i;
! 271: struct detail_arg arg = {
! 272: .nattr = 0,
! 273: };
1.1 misho 274:
1.1.1.2 ! misho 275: if (!current_element->e_nattrs)
! 276: return;
1.1 misho 277:
1.1.1.2 ! misho 278: for (i = 1; i < detail_cols; i++)
! 279: mvaddch(row, (i * DETAILS_COLS) - 1, ACS_TTEE);
1.1 misho 280:
1.1.1.2 ! misho 281: NEXT_ROW();
! 282: put_line("");
! 283: for (i = 0; i < detail_cols; i++) {
! 284: if (i > 0)
! 285: mvaddch(row, (i * DETAILS_COLS) - 1, ACS_VLINE);
! 286: move(row, (i * DETAILS_COLS) + 22);
! 287: put_line("RX TX");
1.1 misho 288: }
289:
1.1.1.2 ! misho 290: NEXT_ROW();
! 291: element_foreach_attr(current_element, draw_attr_detail, &arg);
! 292:
! 293: /*
! 294: * If the last row was incomplete, not all vlines have been drawn.
! 295: * draw them here
! 296: */
! 297: for (i = 1; i < detail_cols; i++)
! 298: mvaddch(row, (i * DETAILS_COLS - 1), ACS_VLINE);
! 299: }
! 300:
! 301: static void print_message(const char *text)
! 302: {
! 303: int i, y = (rows/2) - 2;
! 304: int len = strlen(text);
! 305: int x = (cols/2) - (len / 2);
! 306:
! 307: attrset(A_STANDOUT);
! 308: mvaddch(y - 2, x - 1, ACS_ULCORNER);
! 309: mvaddch(y + 2, x - 1, ACS_LLCORNER);
! 310: mvaddch(y - 2, x + len, ACS_URCORNER);
! 311: mvaddch(y + 2, x + len, ACS_LRCORNER);
! 312:
! 313: for (i = 0; i < 3; i++) {
! 314: mvaddch(y - 1 + i, x + len, ACS_VLINE);
! 315: mvaddch(y - 1 + i, x - 1 ,ACS_VLINE);
1.1 misho 316: }
317:
1.1.1.2 ! misho 318: for (i = 0; i < len; i++) {
! 319: mvaddch(y - 2, x + i, ACS_HLINE);
! 320: mvaddch(y - 1, x + i, ' ');
! 321: mvaddch(y + 1, x + i, ' ');
! 322: mvaddch(y + 2, x + i, ACS_HLINE);
1.1 misho 323: }
324:
1.1.1.2 ! misho 325: mvaddstr(y, x, text);
! 326: attroff(A_STANDOUT);
! 327:
! 328: row = y + 2;
! 329: }
! 330:
! 331: static void draw_help(void)
! 332: {
! 333: #define HW 46
! 334: #define HH 19
! 335: int i, y = (rows/2) - (HH/2);
! 336: int x = (cols/2) - (HW/2);
! 337: char pad[HW+1];
! 338:
! 339: memset(pad, ' ', sizeof(pad));
! 340: pad[sizeof(pad) - 1] = '\0';
! 341:
! 342: attron(A_STANDOUT);
! 343:
! 344: for (i = 0; i < HH; i++)
! 345: mvaddnstr(y + i, x, pad, -1);
! 346:
! 347: mvaddch(y - 1, x - 1, ACS_ULCORNER);
! 348: mvaddch(y + HH, x - 1, ACS_LLCORNER);
! 349:
! 350: mvaddch(y - 1, x + HW, ACS_URCORNER);
! 351: mvaddch(y + HH, x + HW, ACS_LRCORNER);
1.1 misho 352:
1.1.1.2 ! misho 353: for (i = 0; i < HH; i++) {
! 354: mvaddch(y + i, x - 1, ACS_VLINE);
! 355: mvaddch(y + i, x + HW, ACS_VLINE);
1.1 misho 356: }
357:
1.1.1.2 ! misho 358: for (i = 0; i < HW; i++) {
! 359: mvaddch(y - 1, x + i, ACS_HLINE);
! 360: mvaddch(y + HH, x + i, ACS_HLINE);
1.1 misho 361: }
362:
1.1.1.2 ! misho 363: attron(A_BOLD);
! 364: mvaddnstr(y- 1, x+15, "QUICK REFERENCE", -1);
! 365: attron(A_UNDERLINE);
! 366: mvaddnstr(y+ 0, x+1, "Navigation", -1);
! 367: attroff(A_BOLD | A_UNDERLINE);
! 368:
! 369: mvaddnstr(y+ 1, x+3, "Up, Down Previous/Next element", -1);
! 370: mvaddnstr(y+ 2, x+3, "PgUp, PgDown Scroll up/down entire page", -1);
! 371: mvaddnstr(y+ 3, x+3, "Left, Right Previous/Next attribute", -1);
! 372: mvaddnstr(y+ 4, x+3, "[, ] Previous/Next group", -1);
! 373: mvaddnstr(y+ 5, x+3, "? Toggle quick reference", -1);
! 374: mvaddnstr(y+ 6, x+3, "q Quit bmon", -1);
! 375:
! 376: attron(A_BOLD | A_UNDERLINE);
! 377: mvaddnstr(y+ 8, x+1, "Display Settings", -1);
! 378: attroff(A_BOLD | A_UNDERLINE);
! 379:
! 380: mvaddnstr(y+ 9, x+3, "d Toggle detailed statistics", -1);
! 381: mvaddnstr(y+10, x+3, "l Toggle element list", -1);
! 382: mvaddnstr(y+11, x+3, "i Toggle additional info", -1);
! 383:
! 384: attron(A_BOLD | A_UNDERLINE);
! 385: mvaddnstr(y+13, x+1, "Graph Settings", -1);
! 386: attroff(A_BOLD | A_UNDERLINE);
! 387:
! 388: mvaddnstr(y+14, x+3, "g Toggle graphical statistics", -1);
! 389: mvaddnstr(y+15, x+3, "H Start recording history data", -1);
! 390: mvaddnstr(y+16, x+3, "TAB Switch time unit of graph", -1);
! 391: mvaddnstr(y+17, x+3, "<, > Change number of graphs", -1);
! 392:
! 393: attroff(A_STANDOUT);
! 394:
! 395: row = y + HH;
! 396: }
! 397:
! 398: static int lines_required_for_header(void)
! 399: {
! 400: return 1;
1.1 misho 401: }
402:
1.1.1.2 ! misho 403: static void draw_header(void)
1.1 misho 404: {
1.1.1.2 ! misho 405: apply_layout(LAYOUT_STATUSBAR);
1.1 misho 406:
1.1.1.2 ! misho 407: if (current_element)
! 408: put_line(" %s %c%s%c",
! 409: current_element->e_name,
! 410: current_element->e_description ? '(' : ' ',
! 411: current_element->e_description ? : "",
! 412: current_element->e_description ? ')' : ' ');
! 413: else
! 414: put_line("");
! 415:
! 416: move(row, COLS - strlen(PACKAGE_STRING) - 1);
! 417: put_line("%s", PACKAGE_STRING);
! 418: move(row, 0);
1.1 misho 419: }
420:
1.1.1.2 ! misho 421: static int lines_required_for_statusbar(void)
! 422: {
! 423: return 1;
! 424: }
1.1 misho 425:
1.1.1.2 ! misho 426: static void draw_statusbar(void)
1.1 misho 427: {
1.1.1.2 ! misho 428: static const char *help_text = "Press ? for help";
! 429: char s[27];
! 430: time_t t = time(0);
1.1 misho 431:
1.1.1.2 ! misho 432: apply_layout(LAYOUT_STATUSBAR);
1.1 misho 433:
1.1.1.2 ! misho 434: asctime_r(localtime(&t), s);
! 435: s[strlen(s) - 1] = '\0';
! 436:
! 437: row = rows-1;
! 438: move(row, 0);
! 439: put_line(" %s", s);
! 440:
! 441: move(row, COLS - strlen(help_text) - 1);
! 442: put_line("%s", help_text);
! 443:
! 444: move(row, 0);
1.1 misho 445: }
446:
1.1.1.2 ! misho 447: static void count_attr_graph(struct element *g, struct attr *a, void *arg)
! 448: {
! 449: if (a == current_attr)
! 450: graph_offset = ngraph;
! 451:
! 452: ngraph++;
! 453: }
1.1 misho 454:
1.1.1.2 ! misho 455: static int lines_required_for_graph(void)
1.1 misho 456: {
1.1.1.2 ! misho 457: int lines = 0;
1.1 misho 458:
1.1.1.2 ! misho 459: ngraph = 0;
1.1 misho 460:
1.1.1.2 ! misho 461: if (c_show_graph && current_element) {
! 462: graph_display = GRAPH_DISPLAY_STANDARD;
1.1 misho 463:
1.1.1.2 ! misho 464: element_foreach_attr(current_element, count_attr_graph, NULL);
1.1 misho 465:
1.1.1.2 ! misho 466: if (ngraph > c_ngraph)
! 467: ngraph = c_ngraph;
1.1 misho 468:
1.1.1.2 ! misho 469: /* check if we have room to draw graphs on the same level */
! 470: if (cols > (2 * (c_graph_cfg.gc_width + 10)))
! 471: graph_display = GRAPH_DISPLAY_SIDE_BY_SIDE;
1.1 misho 472:
1.1.1.2 ! misho 473: /* +2 = header + time axis */
! 474: lines = ngraph * (graph_display * (c_graph_cfg.gc_height + 2));
! 475: }
1.1 misho 476:
1.1.1.2 ! misho 477: return lines + 1;
! 478: }
1.1 misho 479:
1.1.1.2 ! misho 480: static int lines_required_for_details(void)
! 481: {
! 482: int lines = 1;
1.1 misho 483:
1.1.1.2 ! misho 484: if (c_show_details && current_element) {
! 485: lines++; /* header */
1.1 misho 486:
1.1.1.2 ! misho 487: detail_cols = cols / DETAILS_COLS;
! 488:
! 489: if (!detail_cols)
! 490: detail_cols = 1;
! 491:
! 492: lines += (current_element->e_nattrs / detail_cols);
! 493: if (current_element->e_nattrs % detail_cols)
! 494: lines++;
1.1 misho 495: }
496:
1.1.1.2 ! misho 497: return lines;
1.1 misho 498: }
499:
1.1.1.2 ! misho 500: static void count_element_lines(struct element_group *g, struct element *e,
! 501: void *arg)
1.1 misho 502: {
1.1.1.2 ! misho 503: int *lines = arg;
1.1 misho 504:
1.1.1.2 ! misho 505: if (e == current_element)
! 506: selection_offset = *lines;
! 507:
! 508: (*lines)++;
1.1 misho 509: }
510:
1.1.1.2 ! misho 511: static void count_group_lines(struct element_group *g, void *arg)
1.1 misho 512: {
1.1.1.2 ! misho 513: int *lines = arg;
! 514:
! 515: /* group title */
! 516: (*lines)++;
! 517:
! 518: group_foreach_element(g, &count_element_lines, arg);
1.1 misho 519: }
520:
1.1.1.2 ! misho 521: static int lines_required_for_list(void)
1.1 misho 522: {
1.1.1.2 ! misho 523: int lines = 0;
1.1 misho 524:
1.1.1.2 ! misho 525: if (c_show_list)
! 526: group_foreach(&count_group_lines, &lines);
! 527: else
! 528: lines = 1;
1.1 misho 529:
1.1.1.2 ! misho 530: return lines;
! 531: }
1.1 misho 532:
1.1.1.2 ! misho 533: static inline int line_visible(int line)
! 534: {
! 535: return line >= offset && line < (offset + list_length);
! 536: }
1.1 misho 537:
1.1.1.2 ! misho 538: static void draw_attr(double rate1, int prec1, char *unit1,
! 539: double rate2, int prec2, char *unit2,
! 540: float usage, int ncol)
! 541: {
! 542: char buf[32];
1.1 misho 543:
1.1.1.2 ! misho 544: move(row, ncol);
! 545: addch(ACS_VLINE);
! 546: printw("%7s%-3s",
! 547: float2str(rate1, 7, prec1, buf, sizeof(buf)), unit1);
1.1 misho 548:
1.1.1.2 ! misho 549: printw("%7s%-3s",
! 550: float2str(rate2, 7, prec2, buf, sizeof(buf)), unit2);
1.1 misho 551:
1.1.1.2 ! misho 552: if (usage != FLT_MAX)
! 553: printw("%2.0f%%", usage);
! 554: else
! 555: printw("%3s", "");
1.1 misho 556: }
557:
1.1.1.2 ! misho 558: static void draw_element(struct element_group *g, struct element *e,
! 559: void *arg)
1.1 misho 560: {
1.1.1.2 ! misho 561: int *line = arg;
! 562:
! 563: apply_layout(LAYOUT_LIST);
! 564:
! 565: if (line_visible(*line)) {
! 566: char *rxu1 = "", *txu1 = "", *rxu2 = "", *txu2 = "";
! 567: double rx1 = 0.0f, tx1 = 0.0f, rx2 = 0.0f, tx2 = 0.0f;
! 568: char pad[IFNAMSIZ + 32];
! 569: int rx1prec = 0, tx1prec = 0, rx2prec = 0, tx2prec = 0;
! 570: struct attr *a;
1.1 misho 571:
1.1.1.2 ! misho 572: NEXT_ROW();
1.1 misho 573:
1.1.1.2 ! misho 574: if (e->e_key_attr[GT_MAJOR] &&
! 575: (a = attr_lookup(e, e->e_key_attr[GT_MAJOR]->ad_id)))
! 576: attr_rate2float(a, &rx1, &rxu1, &rx1prec,
! 577: &tx1, &txu1, &tx1prec);
1.1 misho 578:
1.1.1.2 ! misho 579: if (e->e_key_attr[GT_MINOR] &&
! 580: (a = attr_lookup(e, e->e_key_attr[GT_MINOR]->ad_id)))
! 581: attr_rate2float(a, &rx2, &rxu2, &rx2prec,
! 582: &tx2, &txu2, &tx2prec);
! 583:
! 584: memset(pad, 0, sizeof(pad));
! 585: memset(pad, ' ', e->e_level < 6 ? e->e_level * 2 : 12);
! 586:
! 587: strncat(pad, e->e_name, sizeof(pad) - strlen(pad) - 1);
! 588:
! 589: if (e->e_description) {
! 590: strncat(pad, " (", sizeof(pad) - strlen(pad) - 1);
! 591: strncat(pad, e->e_description, sizeof(pad) - strlen(pad) - 1);
! 592: strncat(pad, ")", sizeof(pad) - strlen(pad) - 1);
1.1 misho 593: }
1.1.1.2 ! misho 594:
! 595: if (*line == offset) {
! 596: attron(A_BOLD);
! 597: addch(ACS_UARROW);
! 598: attroff(A_BOLD);
! 599: addch(' ');
! 600: } else if (e == current_element) {
! 601: apply_layout(LAYOUT_SELECTED);
! 602: addch(' ');
! 603: attron(A_BOLD);
! 604: addch(ACS_RARROW);
! 605: attroff(A_BOLD);
! 606: apply_layout(LAYOUT_LIST);
! 607: } else if (*line == offset + list_length - 1 &&
! 608: *line < (list_req - 1)) {
! 609: attron(A_BOLD);
! 610: addch(ACS_DARROW);
! 611: attroff(A_BOLD);
! 612: addch(' ');
! 613: } else
! 614: printw(" ");
! 615:
! 616: put_line("%-30.30s", pad);
! 617:
! 618: draw_attr(rx1, rx1prec, rxu1, rx2, rx2prec, rxu2,
! 619: e->e_rx_usage, LIST_COL_1);
1.1 misho 620:
1.1.1.2 ! misho 621: draw_attr(tx1, tx1prec, txu1, tx2, tx2prec, txu2,
! 622: e->e_tx_usage, LIST_COL_2);
! 623:
! 624: }
! 625:
! 626: (*line)++;
1.1 misho 627: }
628:
1.1.1.2 ! misho 629: static void draw_group(struct element_group *g, void *arg)
1.1 misho 630: {
1.1.1.2 ! misho 631: int *line = arg;
1.1 misho 632:
1.1.1.2 ! misho 633: if (line_visible(*line)) {
! 634: NEXT_ROW();
! 635: attron(A_BOLD);
! 636: put_line("%s", g->g_hdr->gh_title);
1.1 misho 637:
1.1.1.2 ! misho 638: attroff(A_BOLD);
! 639: mvaddch(row, LIST_COL_1, ACS_VLINE);
! 640: attron(A_BOLD);
! 641: put_line("%7s %7s %%",
! 642: g->g_hdr->gh_column[0],
! 643: g->g_hdr->gh_column[1]);
1.1 misho 644:
1.1.1.2 ! misho 645: attroff(A_BOLD);
! 646: mvaddch(row, LIST_COL_2, ACS_VLINE);
! 647: attron(A_BOLD);
! 648: put_line("%7s %7s %%",
! 649: g->g_hdr->gh_column[2],
! 650: g->g_hdr->gh_column[3]);
1.1 misho 651: }
1.1.1.2 ! misho 652:
! 653: (*line)++;
! 654:
! 655: group_foreach_element(g, draw_element, arg);
1.1 misho 656: }
657:
1.1.1.2 ! misho 658: static void draw_element_list(void)
1.1 misho 659: {
1.1.1.2 ! misho 660: int line = 0;
1.1 misho 661:
1.1.1.2 ! misho 662: group_foreach(draw_group, &line);
! 663: }
1.1 misho 664:
1.1.1.2 ! misho 665: static inline int attr_visible(int nattr)
! 666: {
! 667: return nattr >= graph_offset && nattr < (graph_offset + ngraph);
! 668: }
1.1 misho 669:
1.1.1.2 ! misho 670: static void draw_graph_centered(struct graph *g, int row, int ncol,
! 671: const char *text)
! 672: {
! 673: int hcenter = (g->g_cfg.gc_width / 2) - (strlen(text) / 2) + 8;
! 674:
! 675: if (hcenter < 9)
! 676: hcenter = 9;
! 677:
! 678: mvprintw(row, ncol + hcenter, "%.*s", g->g_cfg.gc_width, text);
1.1 misho 679: }
680:
1.1.1.2 ! misho 681: static void draw_table(struct graph *g, struct graph_table *tbl,
! 682: struct attr *a, struct history *h,
! 683: const char *hdr, int ncol)
1.1 misho 684: {
1.1.1.2 ! misho 685: int i, save_row;
! 686: char buf[32];
1.1 misho 687:
1.1.1.2 ! misho 688: if (!tbl->gt_table) {
! 689: for (i = g->g_cfg.gc_height; i >= 0; i--) {
! 690: move(++row, ncol);
! 691: put_line("");
! 692: }
! 693: return;
! 694: }
1.1 misho 695:
1.1.1.2 ! misho 696: move(++row, ncol);
! 697: put_line("%8s", tbl->gt_y_unit ? : "");
! 698:
! 699: snprintf(buf, sizeof(buf), "(%s %s/%s)",
! 700: hdr, a->a_def->ad_description,
! 701: h ? h->h_definition->hd_name : "?");
! 702:
! 703: draw_graph_centered(g, row, ncol, buf);
! 704:
! 705: //move(row, ncol + g->g_cfg.gc_width - 3);
! 706: //put_line("[err %.2f%%]", rtiming.rt_variance.v_error);
! 707:
! 708: for (i = (g->g_cfg.gc_height - 1); i >= 0; i--) {
! 709: move(++row, ncol);
! 710: put_line("%'8.2f %s",
! 711: tbl->gt_scale[i],
! 712: tbl->gt_table + (i * graph_row_size(&g->g_cfg)));
1.1 misho 713: }
714:
1.1.1.2 ! misho 715: move(++row, ncol);
! 716: put_line(" 1");
! 717:
! 718: for (i = 1; i <= g->g_cfg.gc_width; i++) {
! 719: if (i % 5 == 0) {
! 720: move(row, ncol + i + 7);
! 721: printw("%2d", i);
! 722: }
1.1 misho 723: }
724:
1.1.1.2 ! misho 725: if (!h) {
! 726: const char *t1 = " No history data available. ";
! 727: const char *t2 = " Press h to start collecting history. ";
! 728: int vcenter = g->g_cfg.gc_height / 2;
! 729:
! 730: save_row = row;
! 731: draw_graph_centered(g, save_row - vcenter - 1, ncol, t1);
! 732: draw_graph_centered(g, save_row - vcenter, ncol, t2);
! 733: row = save_row;
! 734: }
1.1 misho 735: }
736:
1.1.1.2 ! misho 737: static void draw_history_graph(struct attr *a, struct history *h)
1.1 misho 738: {
1.1.1.2 ! misho 739: struct graph *g;
! 740: int ncol = 0, save_row;
1.1 misho 741:
1.1.1.2 ! misho 742: g = graph_alloc(h, &c_graph_cfg);
! 743: graph_refill(g, h);
1.1 misho 744:
1.1.1.2 ! misho 745: save_row = row;
! 746: draw_table(g, &g->g_rx, a, h, "RX", ncol);
1.1 misho 747:
1.1.1.2 ! misho 748: if (graph_display == GRAPH_DISPLAY_SIDE_BY_SIDE) {
! 749: ncol = cols / 2;
! 750: row = save_row;
! 751: }
1.1 misho 752:
1.1.1.2 ! misho 753: draw_table(g, &g->g_tx, a, h, "TX", ncol);
1.1 misho 754:
1.1.1.2 ! misho 755: graph_free(g);
! 756: }
1.1 misho 757:
1.1.1.2 ! misho 758: static void draw_attr_graph(struct element *e, struct attr *a, void *arg)
! 759: {
! 760: int *nattr = arg;
1.1 misho 761:
1.1.1.2 ! misho 762: if (attr_visible(*nattr)) {
! 763: struct history_def *sel;
! 764: struct history *h;
1.1 misho 765:
1.1.1.2 ! misho 766: sel = history_current();
! 767: c_graph_cfg.gc_unit = a->a_def->ad_unit;
1.1 misho 768:
1.1.1.2 ! misho 769: list_for_each_entry(h, &a->a_history_list, h_list) {
! 770: if (h->h_definition != sel)
! 771: continue;
1.1 misho 772:
1.1.1.2 ! misho 773: draw_history_graph(a, h);
! 774: goto out;
! 775: }
1.1 misho 776:
1.1.1.2 ! misho 777: draw_history_graph(a, NULL);
! 778: }
! 779:
! 780: out:
! 781: (*nattr)++;
1.1 misho 782: }
783:
1.1.1.2 ! misho 784: static void draw_graph(void)
1.1 misho 785: {
1.1.1.2 ! misho 786: int nattr = 0;
1.1 misho 787:
1.1.1.2 ! misho 788: element_foreach_attr(current_element, &draw_attr_graph, &nattr);
! 789: }
1.1 misho 790:
1.1.1.2 ! misho 791: static int lines_required_for_info(void)
! 792: {
! 793: int lines = 1;
1.1 misho 794:
1.1.1.2 ! misho 795: if (c_show_info) {
! 796: info_cols = cols / DETAILS_COLS;
1.1 misho 797:
1.1.1.2 ! misho 798: if (!info_cols)
! 799: info_cols = 1;
1.1 misho 800:
1.1.1.2 ! misho 801: lines += (current_element->e_ninfo / info_cols);
! 802: if (current_element->e_ninfo % info_cols)
! 803: lines++;
1.1 misho 804: }
805:
1.1.1.2 ! misho 806: return lines;
! 807: }
! 808:
! 809: static void __draw_info(struct element *e, struct info *info, int *ninfo)
! 810: {
! 811: int ncol;
! 812:
! 813: ncol = ((*ninfo) * DETAILS_COLS) - 1;
! 814: move(row, ncol);
! 815: if (ncol > 0)
! 816: addch(ACS_VLINE);
! 817:
! 818: put_line(" %-14.14s %22.22s", info->i_name, info->i_value);
! 819:
! 820: if (++(*ninfo) >= info_cols) {
! 821: NEXT_ROW();
! 822: *ninfo = 0;
1.1 misho 823: }
1.1.1.2 ! misho 824: }
1.1 misho 825:
1.1.1.2 ! misho 826: static void draw_info(void)
! 827: {
! 828: struct info *info;
! 829: int i, ninfo = 0;
1.1 misho 830:
1.1.1.2 ! misho 831: if (!current_element->e_ninfo)
! 832: return;
1.1 misho 833:
1.1.1.2 ! misho 834: for (i = 1; i < detail_cols; i++)
! 835: mvaddch(row, (i * DETAILS_COLS) - 1,
! 836: c_show_details ? ACS_PLUS : ACS_TTEE);
! 837:
! 838: NEXT_ROW();
! 839: list_for_each_entry(info, ¤t_element->e_info_list, i_list)
! 840: __draw_info(current_element, info, &ninfo);
1.1 misho 841:
1.1.1.2 ! misho 842: /*
! 843: * If the last row was incomplete, not all vlines have been drawn.
! 844: * draw them here
! 845: */
! 846: for (i = 1; i < info_cols; i++)
! 847: mvaddch(row, (i * DETAILS_COLS - 1), ACS_VLINE);
1.1 misho 848: }
849:
1.1.1.2 ! misho 850: static void draw_content(void)
1.1 misho 851: {
1.1.1.2 ! misho 852: int graph_req, details_req, lines_available, total_req;
! 853: int info_req, empty_lines;
! 854: int disable_graph = 0, disable_details = 0, disable_info = 0;
1.1 misho 855:
1.1.1.2 ! misho 856: if (!current_element)
1.1 misho 857: return;
858:
1.1.1.2 ! misho 859: /*
! 860: * Reset selection offset. Will be set in lines_required_for_list().
! 861: */
! 862: selection_offset = 0;
! 863: offset = 0;
1.1 misho 864:
1.1.1.2 ! misho 865: /* Reset graph offset, will be set in lines_required_for_graph() */
! 866: graph_offset = 0;
1.1 misho 867:
1.1.1.2 ! misho 868: lines_available = rows - lines_required_for_statusbar()
! 869: - lines_required_for_header();
1.1 misho 870:
1.1.1.2 ! misho 871: list_req = lines_required_for_list();
! 872: graph_req = lines_required_for_graph();
! 873: details_req = lines_required_for_details();
! 874: info_req = lines_required_for_info();
! 875:
! 876: total_req = list_req + graph_req + details_req + info_req;
! 877:
! 878: if (total_req <= lines_available) {
! 879: /*
! 880: * Enough lines available for all data to displayed, all
! 881: * is good. Display the full list.
! 882: */
! 883: list_length = list_req;
! 884: goto draw;
1.1 misho 885: }
886:
887: /*
1.1.1.2 ! misho 888: * Not enough lines available for full list and all details
! 889: * requested...
1.1 misho 890: */
891:
1.1.1.2 ! misho 892: if (c_show_list) {
! 893: /*
! 894: * ... try shortening the list first.
! 895: */
! 896: list_length = lines_available - (total_req - list_req);
! 897: if (list_length >= c_list_min)
! 898: goto draw;
! 899: }
! 900:
! 901: if (c_show_info) {
! 902: /* try disabling info */
! 903: list_length = lines_available - (total_req - info_req + 1);
! 904: if (list_length >= c_list_min) {
! 905: disable_info = 1;
! 906: goto draw;
! 907: }
! 908: }
! 909:
! 910: if (c_show_details) {
! 911: /* ... try disabling details */
! 912: list_length = lines_available - (total_req - details_req + 1);
! 913: if (list_length >= c_list_min) {
! 914: disable_details = 1;
! 915: goto draw;
! 916: }
! 917: }
1.1 misho 918:
1.1.1.2 ! misho 919: /* ... try disabling graph, details, and info */
! 920: list_length = lines_available - 1 - 1 - 1;
! 921: if (list_length >= c_list_min) {
! 922: disable_graph = 1;
! 923: disable_details = 1;
! 924: disable_info = 1;
! 925: goto draw;
! 926: }
! 927:
! 928: NEXT_ROW();
! 929: put_line("A minimum of %d lines is required to display content.\n",
! 930: (rows - lines_available) + c_list_min + 2);
! 931: return;
! 932:
! 933: draw:
! 934: if (selection_offset && list_length > 0) {
1.1 misho 935: /*
1.1.1.2 ! misho 936: * Vertically align the selected element in the middle
! 937: * of the list.
1.1 misho 938: */
1.1.1.2 ! misho 939: offset = selection_offset - (list_length / 2);
1.1 misho 940:
941: /*
1.1.1.2 ! misho 942: * If element 0..(list_length/2) is selected, offset is
! 943: * negative here. Start drawing from first element.
1.1 misho 944: */
1.1.1.2 ! misho 945: if (offset < 0)
! 946: offset = 0;
1.1 misho 947:
1.1.1.2 ! misho 948: /*
! 949: * Ensure the full list length is used if one of the
! 950: * last (list_length/2) elements is selected.
! 951: */
! 952: if (offset > (list_req - list_length))
! 953: offset = (list_req - list_length);
1.1 misho 954:
1.1.1.2 ! misho 955: if (offset >= list_req)
! 956: BUG();
! 957: }
! 958:
! 959: if (c_show_list) {
! 960: draw_element_list();
! 961: } else {
! 962: NEXT_ROW();
! 963: hline(ACS_HLINE, cols);
! 964: center_text(" Press %c to enable list view ",
! 965: KEY_TOGGLE_LIST);
1.1 misho 966: }
967:
968: /*
1.1.1.2 ! misho 969: * Graphical statistics
1.1 misho 970: */
1.1.1.2 ! misho 971: NEXT_ROW();
! 972: hline(ACS_HLINE, cols);
! 973: mvaddch(row, LIST_COL_1, ACS_BTEE);
! 974: mvaddch(row, LIST_COL_2, ACS_BTEE);
! 975:
! 976: if (!c_show_graph)
! 977: center_text(" Press %c to enable graphical statistics ",
! 978: KEY_TOGGLE_GRAPH);
! 979: else {
! 980: if (disable_graph)
! 981: center_text(" Increase screen height to see graphical statistics ");
! 982: else
! 983: draw_graph();
! 984: }
! 985:
! 986: empty_lines = rows - row - details_req - info_req
! 987: - lines_required_for_statusbar() - 1;
! 988:
! 989: while (empty_lines-- > 0) {
! 990: NEXT_ROW();
! 991: put_line("");
1.1 misho 992: }
993:
1.1.1.2 ! misho 994: /*
! 995: * Detailed statistics
! 996: */
! 997: NEXT_ROW();
1.1 misho 998: hline(ACS_HLINE, cols);
999:
1.1.1.2 ! misho 1000: if (!c_show_details)
! 1001: center_text(" Press %c to enable detailed statistics ",
! 1002: KEY_TOGGLE_DETAILS);
! 1003: else {
! 1004: if (disable_details)
! 1005: center_text(" Increase screen height to see detailed statistics ");
! 1006: else
! 1007: draw_details();
1.1 misho 1008: }
1009:
1.1.1.2 ! misho 1010: /*
! 1011: * Additional information
! 1012: */
! 1013: NEXT_ROW();
1.1 misho 1014: hline(ACS_HLINE, cols);
1015:
1.1.1.2 ! misho 1016: if (!c_show_info)
! 1017: center_text(" Press %c to enable additional information ",
! 1018: KEY_TOGGLE_INFO);
! 1019: else {
! 1020: if (disable_info)
! 1021: center_text(" Increase screen height to see additional information ");
! 1022: else
! 1023: draw_info();
1.1 misho 1024: }
1025: }
1026:
1027:
1028: static void curses_draw(void)
1029: {
1030: row = 0;
1031: move(0,0);
1032:
1033: getmaxyx(stdscr, rows, cols);
1.1.1.2 ! misho 1034:
! 1035: if (rows < 4) {
1.1 misho 1036: clear();
1.1.1.2 ! misho 1037: put_line("Screen must be at least 4 rows in height");
! 1038: goto out;
1.1 misho 1039: }
1040:
1.1.1.2 ! misho 1041: if (cols < 48) {
! 1042: clear();
! 1043: put_line("Screen must be at least 48 columns width");
! 1044: goto out;
! 1045: }
! 1046:
! 1047: current_element = element_current();
! 1048: current_attr = attr_current();
1.1 misho 1049:
1.1.1.2 ! misho 1050: draw_header();
! 1051:
! 1052: apply_layout(LAYOUT_DEFAULT);
! 1053: draw_content();
! 1054:
! 1055: /* fill empty lines with blanks */
! 1056: while (row < (rows - 1 - lines_required_for_statusbar())) {
! 1057: move(++row, 0);
! 1058: put_line("");
1.1 misho 1059: }
1060:
1.1.1.2 ! misho 1061: draw_statusbar();
1.1 misho 1062:
1063: if (quit_mode)
1.1.1.2 ! misho 1064: print_message(" Really Quit? (y/n) ");
1.1 misho 1065: else if (print_help) {
1066: if (help_page == 0)
1067: draw_help();
1.1.1.2 ! misho 1068: #if 0
1.1 misho 1069: else
1070: draw_help_2();
1.1.1.2 ! misho 1071: #endif
1.1 misho 1072: }
1073:
1.1.1.2 ! misho 1074: out:
1.1 misho 1075: attrset(0);
1076: refresh();
1077: }
1078:
1079: static int handle_input(int ch)
1080: {
1081: switch (ch)
1082: {
1083: case 'q':
1.1.1.2 ! misho 1084: if (print_help)
! 1085: print_help = 0;
! 1086: else
! 1087: quit_mode = quit_mode ? 0 : 1;
1.1 misho 1088: return 1;
1089:
1090: case 0x1b:
1091: quit_mode = 0;
1092: print_help = 0;
1093: return 1;
1094:
1095: case 'y':
1096: if (quit_mode)
1097: exit(0);
1098: break;
1099:
1100: case 'n':
1101: if (quit_mode)
1102: quit_mode = 0;
1103: return 1;
1104:
1105: case 12:
1106: case KEY_CLEAR:
1107: #ifdef HAVE_REDRAWWIN
1108: redrawwin(stdscr);
1109: #endif
1110: clear();
1111: return 1;
1112:
1.1.1.2 ! misho 1113: case '?':
1.1 misho 1114: clear();
1.1.1.2 ! misho 1115: print_help = 1;
1.1 misho 1116: return 1;
1117:
1.1.1.2 ! misho 1118: case KEY_TOGGLE_GRAPH:
! 1119: c_show_graph = !c_show_graph;
! 1120: if (c_show_graph && !c_ngraph)
! 1121: c_ngraph = 1;
1.1 misho 1122: return 1;
1123:
1.1.1.2 ! misho 1124: case KEY_TOGGLE_DETAILS:
! 1125: c_show_details = !c_show_details;
1.1 misho 1126: return 1;
1127:
1.1.1.2 ! misho 1128: case KEY_TOGGLE_LIST:
! 1129: c_show_list = !c_show_list;
1.1 misho 1130: return 1;
1131:
1.1.1.2 ! misho 1132: case KEY_TOGGLE_INFO:
! 1133: c_show_info = !c_show_info;
1.1 misho 1134: return 1;
1135:
1.1.1.2 ! misho 1136: case KEY_COLLECT_HISTORY:
! 1137: if (current_attr) {
! 1138: attr_start_collecting_history(current_attr);
! 1139: return 1;
! 1140: }
! 1141: break;
! 1142:
! 1143: case KEY_PPAGE:
! 1144: {
! 1145: int i;
! 1146: for (i = 1; i < list_length; i++)
! 1147: element_select_prev();
! 1148: }
1.1 misho 1149: return 1;
1150:
1.1.1.2 ! misho 1151: case KEY_NPAGE:
! 1152: {
! 1153: int i;
! 1154: for (i = 1; i < list_length; i++)
! 1155: element_select_next();
! 1156: }
1.1 misho 1157: return 1;
1158:
1.1.1.2 ! misho 1159: case KEY_DOWN:
! 1160: element_select_next();
1.1 misho 1161: return 1;
1162:
1.1.1.2 ! misho 1163: case KEY_UP:
! 1164: element_select_prev();
1.1 misho 1165: return 1;
1166:
1.1.1.2 ! misho 1167: case KEY_LEFT:
! 1168: attr_select_prev();
1.1 misho 1169: return 1;
1170:
1.1.1.2 ! misho 1171: case KEY_RIGHT:
! 1172: attr_select_next();
1.1 misho 1173: return 1;
1174:
1.1.1.2 ! misho 1175: case ']':
! 1176: group_select_next();
1.1 misho 1177: return 1;
1178:
1.1.1.2 ! misho 1179: case '[':
! 1180: group_select_prev();
1.1 misho 1181: return 1;
1182:
1.1.1.2 ! misho 1183: case '<':
! 1184: c_ngraph--;
! 1185: if (c_ngraph <= 1)
! 1186: c_ngraph = 1;
1.1 misho 1187: return 1;
1188:
1189: case '>':
1.1.1.2 ! misho 1190: c_ngraph++;
! 1191: if (c_ngraph > 32)
! 1192: c_ngraph = 32;
1.1 misho 1193: return 1;
1194:
1.1.1.2 ! misho 1195: case '\t':
! 1196: history_select_next();
1.1 misho 1197: return 1;
1198: }
1199:
1200: return 0;
1201: }
1202:
1203: static void curses_pre(void)
1204: {
1.1.1.2 ! misho 1205: static int init = 0;
! 1206:
! 1207: if (!init) {
! 1208: curses_init();
! 1209: init = 1;
! 1210: }
! 1211:
1.1 misho 1212: for (;;) {
1213: int ch = getch();
1214:
1215: if (ch == -1)
1216: break;
1217:
1218: if (handle_input(ch))
1219: curses_draw();
1220: }
1221: }
1222:
1223: static void print_module_help(void)
1224: {
1225: printf(
1226: "curses - Curses Output\n" \
1227: "\n" \
1.1.1.2 ! misho 1228: " Interactive curses UI. Press '?' to see help.\n" \
1.1 misho 1229: " Author: Thomas Graf <tgraf@suug.ch>\n" \
1230: "\n" \
1231: " Options:\n" \
1232: " fgchar=CHAR Foreground character (default: '*')\n" \
1233: " bgchar=CHAR Background character (default: '.')\n" \
1234: " nchar=CHAR Noise character (default: ':')\n" \
1235: " uchar=CHAR Unknown character (default: '?')\n" \
1.1.1.2 ! misho 1236: " gheight=NUM Height of graph (default: 6)\n" \
! 1237: " gwidth=NUM Width of graph (default: 60)\n" \
! 1238: " ngraph=NUM Number of graphs (default: 1)\n" \
1.1 misho 1239: " nocolors Do not use colors\n" \
1240: " graph Show graphical stats by default\n" \
1.1.1.2 ! misho 1241: " details Show detailed stats by default\n" \
! 1242: " minlist=INT Minimum item list length\n");
1.1 misho 1243: }
1244:
1.1.1.2 ! misho 1245: static void curses_parse_opt(const char *type, const char *value)
1.1 misho 1246: {
1.1.1.2 ! misho 1247: if (!strcasecmp(type, "fgchar") && value)
! 1248: c_graph_cfg.gc_foreground = value[0];
! 1249: else if (!strcasecmp(type, "bgchar") && value)
! 1250: c_graph_cfg.gc_background = value[0];
! 1251: else if (!strcasecmp(type, "nchar") && value)
! 1252: c_graph_cfg.gc_noise = value[0];
! 1253: else if (!strcasecmp(type, "uchar") && value)
! 1254: c_graph_cfg.gc_unknown = value[0];
! 1255: else if (!strcasecmp(type, "gheight") && value)
! 1256: c_graph_cfg.gc_height = strtol(value, NULL, 0);
! 1257: else if (!strcasecmp(type, "gwidth") && value)
! 1258: c_graph_cfg.gc_width = strtol(value, NULL, 0);
! 1259: else if (!strcasecmp(type, "ngraph")) {
! 1260: c_ngraph = strtol(value, NULL, 0);
! 1261: c_show_graph = !!c_ngraph;
! 1262: } else if (!strcasecmp(type, "details"))
! 1263: c_show_details = 1;
! 1264: else if (!strcasecmp(type, "nocolors"))
! 1265: c_use_colors = 0;
! 1266: else if (!strcasecmp(type, "minlist") && value)
! 1267: c_list_min = strtol(value, NULL, 0);
! 1268: else if (!strcasecmp(type, "help")) {
! 1269: print_module_help();
! 1270: exit(0);
1.1 misho 1271: }
1272: }
1273:
1.1.1.2 ! misho 1274: static struct bmon_module curses_ops = {
! 1275: .m_name = "curses",
! 1276: .m_flags = BMON_MODULE_DEFAULT,
! 1277: .m_shutdown = curses_shutdown,
! 1278: .m_pre = curses_pre,
! 1279: .m_do = curses_draw,
! 1280: .m_parse_opt = curses_parse_opt,
1.1 misho 1281: };
1282:
1283: static void __init do_curses_init(void)
1284: {
1.1.1.2 ! misho 1285: output_register(&curses_ops);
1.1 misho 1286: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>