Annotation of src/usr.bin/systat/engine.c, Revision 1.2
1.2 ! canacar 1: /* $Id: engine.c,v 1.1 2008/06/12 22:26:01 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:
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;
1.2 ! canacar 804:
! 805: if (curr_view->mgr->order_list == NULL)
! 806: return;
1.1 canacar 807:
808: oc = curr_view->mgr->order_curr;
809:
810: for (o = curr_view->mgr->order_list; o->name != NULL; o++) {
811: if (oc == o) {
812: o++;
813: if (o->name == NULL)
814: break;
815: curr_view->mgr->order_curr = o;
816: return;
817: }
818: }
819:
820: curr_view->mgr->order_curr = curr_view->mgr->order_list;
821: }
822:
823:
824: /* main program functions */
825:
826: int
827: read_view(void)
828: {
829: if (curr_mgr == NULL)
830: return (0);
831:
832: if (paused)
833: return (0);
834:
835: if (curr_mgr->read_fn != NULL)
836: return (curr_mgr->read_fn());
837:
838: return (0);
839: }
840:
841:
842: int
843: disp_update(void)
844: {
845: int lines;
846:
847: if (maxprint < 0)
848: dispstart = 0;
849: else if (dispstart + maxprint > num_disp)
850: dispstart = num_disp - maxprint;
851:
852: if (dispstart < 0)
853: dispstart = 0;
854:
855: if (curr_view == NULL)
856: return 0;
857:
858: if (curr_mgr != NULL) {
859: curr_line = 0;
860:
861: if (curr_mgr->header_fn != NULL) {
862: lines = curr_mgr->header_fn();
863: if (lines < 0)
864: return (1);
865: // home_line = lines++;
866: curr_line = ++lines;
867: home_line = lines + maxprint + 1;
868: }
869:
870: print_title();
871:
872: if (curr_mgr->print_fn != NULL)
873: curr_mgr->print_fn();
874: }
875:
876: return (0);
877: }
878:
879: void
880: sort_view(void)
881: {
882: if (curr_mgr != NULL)
883: if (curr_mgr->sort_fn != NULL)
884: curr_mgr->sort_fn();
885: }
886:
887: void
888: sig_close(int signal)
889: {
890: gotsig_close = 1;
891: }
892:
893: void
894: sig_resize(int signal)
895: {
896: gotsig_resize = 1;
897: }
898:
899: void
900: sig_alarm(int signal)
901: {
902: gotsig_alarm = 1;
903: }
904:
905: void
906: setup_term(int dmax)
907: {
908: max_disp = dmax;
909: maxprint = dmax;
910:
911: if (rawmode) {
912: columns = rawwidth;
913: lines = DEFAULT_HEIGHT;
914: clear_linebuf();
915: } else {
916: if (dmax < 0)
917: dmax = 0;
918:
919: screen = newterm(NULL, stdout, stdin);
920: if (screen == NULL) {
921: rawmode = 1;
922: interactive = 0;
923: setup_term(dmax);
924: return;
925: }
926: columns = COLS;
927: lines = LINES;
928:
929: if (maxprint > lines - HEADER_LINES)
930: maxprint = lines - HEADER_LINES;
931:
932: nonl();
933: keypad(stdscr, TRUE);
934: intrflush(stdscr, FALSE);
935:
936: halfdelay(10);
937: noecho();
938: }
939:
940: if (dmax == 0)
941: maxprint = lines - HEADER_LINES;
942:
943: field_setup();
944: }
945:
946: struct command *
947: command_set(struct command *cmd, const char *init)
948: {
949: struct command *prev = curr_cmd;
950:
951: if (cmd) {
952: if (init) {
953: cmd_len = strlcpy(cmdbuf, init, sizeof(cmdbuf));
954: if (cmd_len >= sizeof(cmdbuf)) {
955: cmdbuf[0] = '\0';
956: cmd_len = 0;
957: }
958: } else {
959: cmd_len = 0;
960: cmdbuf[0] = 0;
961: }
962: }
963: curr_message = NULL;
964: curr_cmd = cmd;
965: need_update = 1;
966: return prev;
967: }
968:
969: const char *
970: message_set(const char *msg) {
971: char *prev = curr_message;
972: if (msg)
973: curr_message = strdup(msg);
974: else
975: curr_message = NULL;
976: free(prev);
977: return NULL;
978: }
979:
980: void
981: print_cmdline(void)
982: {
983: if (curr_cmd) {
984: attron(A_STANDOUT);
985: mvprintw(home_line, 0, "%s: ", curr_cmd->prompt);
986: attroff(A_STANDOUT);
987: printw("%s", cmdbuf);
988: } else if (curr_message) {
989: mvprintw(home_line, 0, "> %s", curr_message);
990: }
991: clrtoeol();
992: }
993:
994:
995: void
996: cmd_keyboard(int ch)
997: {
998: if (curr_cmd == NULL)
999: return;
1000:
1001: if (ch > 0 && isprint(ch)) {
1002: if (cmd_len < sizeof(cmdbuf) - 1) {
1003: cmdbuf[cmd_len++] = ch;
1004: cmdbuf[cmd_len] = 0;
1005: } else
1006: beep();
1007: }
1008:
1009: switch (ch) {
1010: case KEY_ENTER:
1011: case 0x0a:
1012: case 0x0d:
1013: {
1014: struct command * c = command_set(NULL, NULL);
1015: c->exec();
1016: break;
1017: }
1018: case KEY_BACKSPACE:
1019: case KEY_DC:
1020: case CTRL_H:
1021: if (cmd_len > 0) {
1022: cmdbuf[--cmd_len] = 0;
1023: } else
1024: beep();
1025: break;
1026: case 0x1b:
1027: case CTRL_G:
1028: if (cmd_len > 0) {
1029: cmdbuf[0] = '\0';
1030: cmd_len = 0;
1031: } else
1032: command_set(NULL, NULL);
1033: break;
1034: default:
1035: break;
1036: }
1037: }
1038:
1039: void
1040: keyboard(void)
1041: {
1042: int ch;
1043:
1044: ch = getch();
1045:
1046: if (curr_cmd) {
1047: cmd_keyboard(ch);
1048: print_cmdline();
1049: return;
1050: }
1051:
1052: if (curr_mgr != NULL)
1053: if (curr_mgr->key_fn != NULL)
1054: if (curr_mgr->key_fn(ch))
1055: return;
1056:
1057: if (curr_message != NULL) {
1058: if (ch > 0) {
1059: curr_message = NULL;
1060: need_update = 1;
1061: }
1062: }
1063:
1064: switch (ch) {
1065: case ' ':
1066: gotsig_alarm = 1;
1067: break;
1068: case 'o':
1069: next_order();
1070: need_sort = 1;
1071: break;
1072: case 'p':
1073: paused = !paused;
1074: gotsig_alarm = 1;
1075: break;
1076: case 'q':
1077: gotsig_close = 1;
1078: break;
1079: case 'r':
1080: sortdir *= -1;
1081: need_sort = 1;
1082: break;
1083: case 'v':
1084: /* FALLTHROUGH */
1085: case KEY_RIGHT:
1086: /* FALLTHROUGH */
1087: case CTRL_F:
1088: next_view();
1089: break;
1090: case KEY_LEFT:
1091: /* FALLTHROUGH */
1092: case CTRL_B:
1093: prev_view();
1094: break;
1095: case KEY_DOWN:
1096: /* FALLTHROUGH */
1097: case CTRL_N:
1098: dispstart++;
1099: need_update = 1;
1100: break;
1101: case KEY_UP:
1102: /* FALLTHROUGH */
1103: case CTRL_P:
1104: dispstart--;
1105: need_update = 1;
1106: break;
1107: case KEY_NPAGE:
1108: /* FALLTHROUGH */
1109: case CTRL_V:
1110: dispstart += maxprint;
1111: need_update = 1;
1112: break;
1113: case KEY_PPAGE:
1114: /* FALLTHROUGH */
1115: case META_V:
1116: dispstart -= maxprint;
1117: need_update = 1;
1118: break;
1119: case KEY_HOME:
1120: /* FALLTHROUGH */
1121: case CTRL_A:
1122: dispstart = 0;
1123: need_update = 1;
1124: break;
1125: case KEY_END:
1126: /* FALLTHROUGH */
1127: case CTRL_E:
1128: dispstart = num_disp;
1129: need_update = 1;
1130: break;
1131: case CTRL_L:
1132: clear();
1133: need_update = 1;
1134: break;
1135: default:
1136: break;
1137: }
1138:
1139: if (set_order_hotkey(ch))
1140: need_sort = 1;
1141: else
1142: set_view_hotkey(ch);
1143: }
1144:
1145: void
1146: engine_initialize(void)
1147: {
1148: signal(SIGTERM, sig_close);
1149: signal(SIGINT, sig_close);
1150: signal(SIGQUIT, sig_close);
1151: signal(SIGWINCH, sig_resize);
1152: signal(SIGALRM, sig_alarm);
1153: }
1154:
1155: void
1156: engine_loop(int countmax)
1157: {
1158: int count = 0;
1159:
1160: for (;;) {
1161: if (gotsig_alarm) {
1162: read_view();
1163: need_sort = 1;
1164: gotsig_alarm = 0;
1165: ualarm(udelay, 0);
1166: }
1167:
1168: if (need_sort) {
1169: sort_view();
1170: need_sort = 0;
1171: need_update = 1;
1172:
1173: /* XXX if sort took too long */
1174: if (gotsig_alarm) {
1175: gotsig_alarm = 0;
1176: ualarm(udelay, 0);
1177: }
1178: }
1179:
1180: if (need_update) {
1181: erase();
1182: disp_update();
1183: end_page();
1184: need_update = 0;
1185: if (countmax && ++count >= countmax)
1186: break;
1187: }
1188:
1189: if (gotsig_close)
1190: break;
1191: if (gotsig_resize) {
1192: if (rawmode == 0)
1193: endwin();
1194: setup_term(max_disp);
1195: gotsig_resize = 0;
1196: need_update = 1;
1197: }
1198:
1199: if (interactive && need_update == 0)
1200: keyboard();
1201: else if (interactive == 0)
1202: usleep(udelay);
1203: }
1204:
1205: if (rawmode == 0)
1206: endwin();
1207: }