Annotation of src/usr.bin/systat/engine.c, Revision 1.3
1.3 ! canacar 1: /* $Id: engine.c,v 1.2 2008/06/13 01:06:06 canacar Exp $ */
1.1 canacar 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:
1.3 ! canacar 628: tb_start();
1.1 canacar 629: if (tbprintf("%u", age) <= len)
630: goto ok;
631:
1.3 ! canacar 632: tb_start();
1.1 canacar 633: age /= 60;
634: if (tbprintf("%um", age) <= len)
635: goto ok;
636: if (age == 0)
637: goto err;
638:
1.3 ! canacar 639: tb_start();
1.1 canacar 640: age /= 60;
641: if (tbprintf("%uh", age) <= len)
642: goto ok;
643: if (age == 0)
644: goto err;
645:
1.3 ! canacar 646: tb_start();
1.1 canacar 647: age /= 24;
648: if (tbprintf("%ud", age) <= len)
649: goto ok;
650:
651: err:
652: print_fld_str(fld, "*");
653: tb_end();
654: return;
655:
656: ok:
657: print_fld_tb(fld);
658: }
659:
660: void
661: print_fld_sdiv(field_def *fld, u_int64_t size, int div)
662: {
663: int len;
664:
665: if (fld == NULL)
666: return;
667:
668: len = fld->width;
669: if (len < 1)
670: return;
671:
672: tb_start();
673: if (tbprintf("%llu", size) <= len)
674: goto ok;
675:
1.3 ! canacar 676: tb_start();
1.1 canacar 677: size /= div;
678: if (tbprintf("%lluK", size) <= len)
679: goto ok;
680: if (size == 0)
681: goto err;
682:
1.3 ! canacar 683: tb_start();
1.1 canacar 684: size /= div;
685: if (tbprintf("%lluM", size) <= len)
686: goto ok;
687: if (size == 0)
688: goto err;
689:
1.3 ! canacar 690: tb_start();
1.1 canacar 691: size /= div;
692: if (tbprintf("%lluG", size) <= len)
693: goto ok;
694:
695: err:
696: print_fld_str(fld, "*");
697: tb_end();
698: return;
699:
700: ok:
701: print_fld_tb(fld);
702: }
703:
704: void
705: print_fld_size(field_def *fld, u_int64_t size)
706: {
707: print_fld_sdiv(fld, size, 1024);
708: }
709:
710: void
711: print_fld_rate(field_def *fld, double rate)
712: {
713: if (rate < 0) {
714: print_fld_str(fld, "*");
715: } else {
716: print_fld_size(fld, rate);
717: }
718: }
719:
720: void
721: print_fld_bw(field_def *fld, double bw)
722: {
723: if (bw < 0) {
724: print_fld_str(fld, "*");
725: } else {
726: print_fld_sdiv(fld, bw, 1000);
727: }
728: }
729:
730: void
731: print_fld_uint(field_def *fld, unsigned int size)
732: {
733: int len;
734:
735: if (fld == NULL)
736: return;
737:
738: len = fld->width;
739: if (len < 1)
740: return;
741:
742: tb_start();
743: if (tbprintf("%u", size) > len)
744: print_fld_str(fld, "*");
745: else
746: print_fld_tb(fld);
747: tb_end();
748: }
749:
750:
751: /* ordering */
752:
753: void
754: set_order(char *opt)
755: {
756: order_type *o;
757:
758: if (curr_view == NULL || curr_view->mgr == NULL)
759: return;
760:
761: curr_view->mgr->order_curr = curr_view->mgr->order_list;
762:
763: if (opt == NULL)
764: return;
765:
766: o = curr_view->mgr->order_list;
767:
768: if (o == NULL)
769: return;
770:
771: for (;o->name != NULL; o++) {
772: if (strcasecmp(opt, o->match) == 0) {
773: curr_view->mgr->order_curr = o;
774: return;
775: }
776: }
777: }
778:
779: int
780: set_order_hotkey(int ch)
781: {
782: order_type *o;
783: int key = ch;
784:
785: if (curr_view == NULL || curr_view->mgr == NULL)
786: return 0;
787:
788: o = curr_view->mgr->order_list;
789:
790: if (o == NULL)
791: return 0;
792:
793: for (;o->name != NULL; o++) {
794: if (key == o->hotkey) {
795: if (curr_view->mgr->order_curr == o) {
796: sortdir *= -1;
797: } else {
798: curr_view->mgr->order_curr = o;
799: }
800: return 1;
801: }
802: }
803:
804: return 0;
805: }
806:
807: void
808: next_order(void)
809: {
810: order_type *o, *oc;
1.2 canacar 811:
812: if (curr_view->mgr->order_list == NULL)
813: return;
1.1 canacar 814:
815: oc = curr_view->mgr->order_curr;
816:
817: for (o = curr_view->mgr->order_list; o->name != NULL; o++) {
818: if (oc == o) {
819: o++;
820: if (o->name == NULL)
821: break;
822: curr_view->mgr->order_curr = o;
823: return;
824: }
825: }
826:
827: curr_view->mgr->order_curr = curr_view->mgr->order_list;
828: }
829:
830:
831: /* main program functions */
832:
833: int
834: read_view(void)
835: {
836: if (curr_mgr == NULL)
837: return (0);
838:
839: if (paused)
840: return (0);
841:
842: if (curr_mgr->read_fn != NULL)
843: return (curr_mgr->read_fn());
844:
845: return (0);
846: }
847:
848:
849: int
850: disp_update(void)
851: {
852: int lines;
853:
854: if (maxprint < 0)
855: dispstart = 0;
856: else if (dispstart + maxprint > num_disp)
857: dispstart = num_disp - maxprint;
858:
859: if (dispstart < 0)
860: dispstart = 0;
861:
862: if (curr_view == NULL)
863: return 0;
864:
865: if (curr_mgr != NULL) {
866: curr_line = 0;
867:
868: if (curr_mgr->header_fn != NULL) {
869: lines = curr_mgr->header_fn();
870: if (lines < 0)
871: return (1);
872: // home_line = lines++;
873: curr_line = ++lines;
874: home_line = lines + maxprint + 1;
875: }
876:
877: print_title();
878:
879: if (curr_mgr->print_fn != NULL)
880: curr_mgr->print_fn();
881: }
882:
883: return (0);
884: }
885:
886: void
887: sort_view(void)
888: {
889: if (curr_mgr != NULL)
890: if (curr_mgr->sort_fn != NULL)
891: curr_mgr->sort_fn();
892: }
893:
894: void
895: sig_close(int signal)
896: {
897: gotsig_close = 1;
898: }
899:
900: void
901: sig_resize(int signal)
902: {
903: gotsig_resize = 1;
904: }
905:
906: void
907: sig_alarm(int signal)
908: {
909: gotsig_alarm = 1;
910: }
911:
912: void
913: setup_term(int dmax)
914: {
915: max_disp = dmax;
916: maxprint = dmax;
917:
918: if (rawmode) {
919: columns = rawwidth;
920: lines = DEFAULT_HEIGHT;
921: clear_linebuf();
922: } else {
923: if (dmax < 0)
924: dmax = 0;
925:
926: screen = newterm(NULL, stdout, stdin);
927: if (screen == NULL) {
928: rawmode = 1;
929: interactive = 0;
930: setup_term(dmax);
931: return;
932: }
933: columns = COLS;
934: lines = LINES;
935:
936: if (maxprint > lines - HEADER_LINES)
937: maxprint = lines - HEADER_LINES;
938:
939: nonl();
940: keypad(stdscr, TRUE);
941: intrflush(stdscr, FALSE);
942:
943: halfdelay(10);
944: noecho();
945: }
946:
947: if (dmax == 0)
948: maxprint = lines - HEADER_LINES;
949:
950: field_setup();
951: }
952:
953: struct command *
954: command_set(struct command *cmd, const char *init)
955: {
956: struct command *prev = curr_cmd;
957:
958: if (cmd) {
959: if (init) {
960: cmd_len = strlcpy(cmdbuf, init, sizeof(cmdbuf));
961: if (cmd_len >= sizeof(cmdbuf)) {
962: cmdbuf[0] = '\0';
963: cmd_len = 0;
964: }
965: } else {
966: cmd_len = 0;
967: cmdbuf[0] = 0;
968: }
969: }
970: curr_message = NULL;
971: curr_cmd = cmd;
972: need_update = 1;
973: return prev;
974: }
975:
976: const char *
977: message_set(const char *msg) {
978: char *prev = curr_message;
979: if (msg)
980: curr_message = strdup(msg);
981: else
982: curr_message = NULL;
983: free(prev);
984: return NULL;
985: }
986:
987: void
988: print_cmdline(void)
989: {
990: if (curr_cmd) {
991: attron(A_STANDOUT);
992: mvprintw(home_line, 0, "%s: ", curr_cmd->prompt);
993: attroff(A_STANDOUT);
994: printw("%s", cmdbuf);
995: } else if (curr_message) {
996: mvprintw(home_line, 0, "> %s", curr_message);
997: }
998: clrtoeol();
999: }
1000:
1001:
1002: void
1003: cmd_keyboard(int ch)
1004: {
1005: if (curr_cmd == NULL)
1006: return;
1007:
1008: if (ch > 0 && isprint(ch)) {
1009: if (cmd_len < sizeof(cmdbuf) - 1) {
1010: cmdbuf[cmd_len++] = ch;
1011: cmdbuf[cmd_len] = 0;
1012: } else
1013: beep();
1014: }
1015:
1016: switch (ch) {
1017: case KEY_ENTER:
1018: case 0x0a:
1019: case 0x0d:
1020: {
1021: struct command * c = command_set(NULL, NULL);
1022: c->exec();
1023: break;
1024: }
1025: case KEY_BACKSPACE:
1026: case KEY_DC:
1027: case CTRL_H:
1028: if (cmd_len > 0) {
1029: cmdbuf[--cmd_len] = 0;
1030: } else
1031: beep();
1032: break;
1033: case 0x1b:
1034: case CTRL_G:
1035: if (cmd_len > 0) {
1036: cmdbuf[0] = '\0';
1037: cmd_len = 0;
1038: } else
1039: command_set(NULL, NULL);
1040: break;
1041: default:
1042: break;
1043: }
1044: }
1045:
1046: void
1047: keyboard(void)
1048: {
1049: int ch;
1050:
1051: ch = getch();
1052:
1053: if (curr_cmd) {
1054: cmd_keyboard(ch);
1055: print_cmdline();
1056: return;
1057: }
1058:
1059: if (curr_mgr != NULL)
1060: if (curr_mgr->key_fn != NULL)
1061: if (curr_mgr->key_fn(ch))
1062: return;
1063:
1064: if (curr_message != NULL) {
1065: if (ch > 0) {
1066: curr_message = NULL;
1067: need_update = 1;
1068: }
1069: }
1070:
1071: switch (ch) {
1072: case ' ':
1073: gotsig_alarm = 1;
1074: break;
1075: case 'o':
1076: next_order();
1077: need_sort = 1;
1078: break;
1079: case 'p':
1080: paused = !paused;
1081: gotsig_alarm = 1;
1082: break;
1083: case 'q':
1084: gotsig_close = 1;
1085: break;
1086: case 'r':
1087: sortdir *= -1;
1088: need_sort = 1;
1089: break;
1090: case 'v':
1091: /* FALLTHROUGH */
1092: case KEY_RIGHT:
1093: /* FALLTHROUGH */
1094: case CTRL_F:
1095: next_view();
1096: break;
1097: case KEY_LEFT:
1098: /* FALLTHROUGH */
1099: case CTRL_B:
1100: prev_view();
1101: break;
1102: case KEY_DOWN:
1103: /* FALLTHROUGH */
1104: case CTRL_N:
1105: dispstart++;
1106: need_update = 1;
1107: break;
1108: case KEY_UP:
1109: /* FALLTHROUGH */
1110: case CTRL_P:
1111: dispstart--;
1112: need_update = 1;
1113: break;
1114: case KEY_NPAGE:
1115: /* FALLTHROUGH */
1116: case CTRL_V:
1117: dispstart += maxprint;
1118: need_update = 1;
1119: break;
1120: case KEY_PPAGE:
1121: /* FALLTHROUGH */
1122: case META_V:
1123: dispstart -= maxprint;
1124: need_update = 1;
1125: break;
1126: case KEY_HOME:
1127: /* FALLTHROUGH */
1128: case CTRL_A:
1129: dispstart = 0;
1130: need_update = 1;
1131: break;
1132: case KEY_END:
1133: /* FALLTHROUGH */
1134: case CTRL_E:
1135: dispstart = num_disp;
1136: need_update = 1;
1137: break;
1138: case CTRL_L:
1139: clear();
1140: need_update = 1;
1141: break;
1142: default:
1143: break;
1144: }
1145:
1146: if (set_order_hotkey(ch))
1147: need_sort = 1;
1148: else
1149: set_view_hotkey(ch);
1150: }
1151:
1152: void
1153: engine_initialize(void)
1154: {
1155: signal(SIGTERM, sig_close);
1156: signal(SIGINT, sig_close);
1157: signal(SIGQUIT, sig_close);
1158: signal(SIGWINCH, sig_resize);
1159: signal(SIGALRM, sig_alarm);
1160: }
1161:
1162: void
1163: engine_loop(int countmax)
1164: {
1165: int count = 0;
1166:
1167: for (;;) {
1168: if (gotsig_alarm) {
1169: read_view();
1170: need_sort = 1;
1171: gotsig_alarm = 0;
1172: ualarm(udelay, 0);
1173: }
1174:
1175: if (need_sort) {
1176: sort_view();
1177: need_sort = 0;
1178: need_update = 1;
1179:
1180: /* XXX if sort took too long */
1181: if (gotsig_alarm) {
1182: gotsig_alarm = 0;
1183: ualarm(udelay, 0);
1184: }
1185: }
1186:
1187: if (need_update) {
1188: erase();
1189: disp_update();
1190: end_page();
1191: need_update = 0;
1192: if (countmax && ++count >= countmax)
1193: break;
1194: }
1195:
1196: if (gotsig_close)
1197: break;
1198: if (gotsig_resize) {
1199: if (rawmode == 0)
1200: endwin();
1201: setup_term(max_disp);
1202: gotsig_resize = 0;
1203: need_update = 1;
1204: }
1205:
1206: if (interactive && need_update == 0)
1207: keyboard();
1208: else if (interactive == 0)
1209: usleep(udelay);
1210: }
1211:
1212: if (rawmode == 0)
1213: endwin();
1214: }