Started on the main view
[tig] / tig.c
CommitLineData
b801d8b2
JF
1/**
2 * TIG(1)
3 * ======
4 *
5 * NAME
6 * ----
7 * tig - text-mode interface for git
8 *
9 * SYNOPSIS
10 * --------
11 * [verse]
12 * tig
13 * tig log [git log options]
14 * tig diff [git diff options]
15 * tig < [git log or git diff output]
16 *
17 * DESCRIPTION
18 * -----------
19 * Browse changes in a git repository.
20 *
21 * OPTIONS
22 * -------
23 *
24 * None.
25 *
26 **/
27
28#define DEBUG
29
30#ifndef DEBUG
31#define NDEBUG
32#endif
33
22f66b0a
JF
34#include <assert.h>
35#include <ctype.h>
36#include <signal.h>
b801d8b2 37#include <stdarg.h>
b801d8b2 38#include <stdio.h>
22f66b0a 39#include <stdlib.h>
b801d8b2 40#include <string.h>
b801d8b2
JF
41
42#include <curses.h>
43#include <form.h>
44
45static void die(const char *err, ...);
46static void report(const char *msg, ...);
47
48#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
49
b801d8b2 50#define KEY_TAB 9
fd85fef1
JF
51#define KEY_ESC 27
52#define KEY_DEL 127
b801d8b2
JF
53
54#define REQ_OFFSET (MAX_COMMAND + 1)
55
56/* Requests for switching between the different views. */
57#define REQ_DIFF (REQ_OFFSET + 0)
58#define REQ_LOG (REQ_OFFSET + 1)
59#define REQ_MAIN (REQ_OFFSET + 2)
22f66b0a 60#define REQ_VIEWS (REQ_OFFSET + 3)
b801d8b2
JF
61
62#define REQ_QUIT (REQ_OFFSET + 11)
63#define REQ_VERSION (REQ_OFFSET + 12)
64#define REQ_STOP (REQ_OFFSET + 13)
65#define REQ_UPDATE (REQ_OFFSET + 14)
66#define REQ_REDRAW (REQ_OFFSET + 15)
fd85fef1
JF
67#define REQ_FIRST_LINE (REQ_OFFSET + 16)
68#define REQ_LAST_LINE (REQ_OFFSET + 17)
b801d8b2 69
fd85fef1 70#define COLOR_CURSOR 42
b801d8b2
JF
71
72/**
73 * KEYS
74 * ----
75 *
76 * d::
77 * diff
78 * l::
79 * log
80 * q::
81 * quit
82 * r::
83 * redraw screen
84 * s::
85 * stop all background loading
86 * j::
87 * down
88 * k::
89 * up
90 * h, ?::
91 * help
92 * v::
93 * version
94 *
95 **/
96
97#define HELP "(d)iff, (l)og, (m)ain, (q)uit, (v)ersion, (h)elp"
98
99struct keymap {
100 int alias;
101 int request;
102};
103
104struct keymap keymap[] = {
fd85fef1 105 /* Cursor navigation */
b801d8b2
JF
106 { KEY_UP, REQ_PREV_LINE },
107 { 'k', REQ_PREV_LINE },
108 { KEY_DOWN, REQ_NEXT_LINE },
109 { 'j', REQ_NEXT_LINE },
fd85fef1
JF
110 { KEY_HOME, REQ_FIRST_LINE },
111 { KEY_END, REQ_LAST_LINE },
112
113 /* Scrolling */
114 { KEY_IC, REQ_SCR_BLINE }, /* scroll field backward a line */
115 { KEY_DC, REQ_SCR_FLINE }, /* scroll field forward a line */
116 { KEY_NPAGE, REQ_SCR_FPAGE }, /* scroll field forward a page */
117 { KEY_PPAGE, REQ_SCR_BPAGE }, /* scroll field backward a page */
118 { 'w', REQ_SCR_FHPAGE }, /* scroll field forward half page */
119 { 's', REQ_SCR_BHPAGE }, /* scroll field backward half page */
b801d8b2
JF
120
121 { 'd', REQ_DIFF },
122 { 'l', REQ_LOG },
123 { 'm', REQ_MAIN },
124
125 /* No input from wgetch() with nodelay() enabled. */
126 { ERR, REQ_UPDATE },
127
128 { KEY_ESC, REQ_QUIT },
129 { 'q', REQ_QUIT },
130 { 's', REQ_STOP },
131 { 'v', REQ_VERSION },
132 { 'r', REQ_REDRAW },
133};
134
135static int
136get_request(int request)
137{
138 int i;
139
140 for (i = 0; i < ARRAY_SIZE(keymap); i++)
141 if (keymap[i].alias == request)
142 return keymap[i].request;
143
144 return request;
145}
146
147
148/*
149 * Viewer
150 */
151
152struct view {
153 char *name;
154 char *cmd;
fd85fef1 155 char *id;
b801d8b2 156
22f66b0a 157
b801d8b2 158 /* Rendering */
22f66b0a
JF
159 int (*read)(struct view *, char *);
160 int (*draw)(struct view *, unsigned int);
161 size_t objsize; /* Size of objects in the line index */
162
b801d8b2 163 WINDOW *win;
fd85fef1 164 int height, width;
b801d8b2
JF
165
166 /* Navigation */
167 unsigned long offset; /* Offset of the window top */
168 unsigned long lineno; /* Current line number */
169
170 /* Buffering */
171 unsigned long lines; /* Total number of lines */
22f66b0a 172 void **line; /* Line index */
b801d8b2
JF
173
174 /* Loading */
175 FILE *pipe;
176};
177
22f66b0a
JF
178struct commit {
179 char id[41];
180 char title[75];
181};
182
183static int pager_draw(struct view *view, unsigned int lineno);
184static int pager_read(struct view *view, char *line);
185
186static int main_draw(struct view *view, unsigned int lineno);
187static int main_read(struct view *view, char *line);
b801d8b2 188
fd85fef1 189#define DIFF_CMD \
b801d8b2
JF
190 "git log --stat -n1 %s ; echo; " \
191 "git diff --find-copies-harder -B -C %s^ %s"
192
193#define LOG_CMD \
194 "git log --stat -n100 %s"
195
fd85fef1
JF
196#define MAIN_CMD \
197 "git log --stat --pretty=raw %s"
198
b801d8b2
JF
199/* The status window at the bottom. Used for polling keystrokes. */
200static WINDOW *status_win;
201
fd85fef1 202#define SIZEOF_ID 1024
22f66b0a 203#define SIZEOF_VIEWS (REQ_VIEWS - REQ_OFFSET)
fd85fef1
JF
204
205char head_id[SIZEOF_ID] = "HEAD";
206char commit_id[SIZEOF_ID] = "HEAD";
207
208static unsigned int current_view;
209static unsigned int nloading;
210
22f66b0a
JF
211static struct view views[];
212static struct view *display[];
213
b801d8b2 214static struct view views[] = {
22f66b0a
JF
215 { "diff", DIFF_CMD, commit_id, pager_read, pager_draw, sizeof(char) },
216 { "log", LOG_CMD, head_id, pager_read, pager_draw, sizeof(struct commit) },
217 { "main", MAIN_CMD, head_id, main_read, main_draw },
b801d8b2
JF
218};
219
220static struct view *display[ARRAY_SIZE(views)];
b801d8b2 221
22f66b0a 222
b801d8b2
JF
223#define foreach_view(view, i) \
224 for (i = 0; i < sizeof(display) && (view = display[i]); i++)
225
226static void
227redraw_view(struct view *view)
228{
229 int lineno;
b801d8b2
JF
230
231 wclear(view->win);
232 wmove(view->win, 0, 0);
233
fd85fef1 234 for (lineno = 0; lineno < view->height; lineno++) {
22f66b0a 235 if (!view->draw(view, lineno))
fd85fef1 236 break;
b801d8b2
JF
237 }
238
239 redrawwin(view->win);
240 wrefresh(view->win);
241}
242
243/* FIXME: Fix percentage. */
244static void
245report_position(struct view *view, int all)
246{
247 report(all ? "line %d of %d (%d%%) viewing from %d"
248 : "line %d of %d",
249 view->lineno + 1,
250 view->lines,
251 view->lines ? view->offset * 100 / view->lines : 0,
252 view->offset);
253}
254
255static void
fd85fef1 256move_view(struct view *view, int lines)
b801d8b2 257{
fd85fef1
JF
258 /* The rendering expects the new offset. */
259 view->offset += lines;
260
261 assert(0 <= view->offset && view->offset < view->lines);
262 assert(lines);
b801d8b2 263
fd85fef1 264 {
22f66b0a
JF
265 int line = lines > 0 ? view->height - lines : 0;
266 int end = line + (lines > 0 ? lines : -lines);
fd85fef1
JF
267
268 wscrl(view->win, lines);
269
22f66b0a
JF
270 for (; line < end; line++) {
271 if (!view->draw(view, line))
fd85fef1
JF
272 break;
273 }
274 }
275
276 /* Move current line into the view. */
277 if (view->lineno < view->offset) {
278 view->lineno = view->offset;
22f66b0a 279 view->draw(view, 0);
fd85fef1
JF
280
281 } else if (view->lineno >= view->offset + view->height) {
282 view->lineno = view->offset + view->height - 1;
22f66b0a 283 view->draw(view, view->lineno - view->offset);
fd85fef1
JF
284 }
285
286 assert(view->offset <= view->lineno && view->lineno <= view->lines);
287
288 redrawwin(view->win);
289 wrefresh(view->win);
290
291 report_position(view, lines);
292}
293static void
294scroll_view(struct view *view, int request)
295{
296 int lines = 1;
b801d8b2
JF
297
298 switch (request) {
fd85fef1
JF
299 case REQ_SCR_FPAGE:
300 lines = view->height;
301 case REQ_SCR_FLINE:
b801d8b2 302 if (view->offset + lines > view->lines)
bde3653a 303 lines = view->lines - view->offset;
b801d8b2 304
fd85fef1 305 if (lines == 0 || view->offset + view->height >= view->lines) {
b801d8b2
JF
306 report("already at last line");
307 return;
308 }
309 break;
310
fd85fef1
JF
311 case REQ_SCR_BPAGE:
312 lines = view->height;
313 case REQ_SCR_BLINE:
b801d8b2
JF
314 if (lines > view->offset)
315 lines = view->offset;
316
317 if (lines == 0) {
318 report("already at first line");
319 return;
320 }
321
fd85fef1 322 lines = -lines;
b801d8b2 323 break;
b801d8b2
JF
324 }
325
fd85fef1
JF
326 move_view(view, lines);
327}
b801d8b2 328
b801d8b2 329
fd85fef1
JF
330static void
331navigate_view(struct view *view, int request)
332{
333 int steps;
b801d8b2 334
fd85fef1
JF
335 switch (request) {
336 case REQ_PREV_LINE:
337 if (view->lineno == 0) {
338 report("already at first line");
339 return;
340 }
341 steps = -1;
342 break;
b801d8b2 343
fd85fef1
JF
344 case REQ_NEXT_LINE:
345 if (view->lineno + 1 >= view->lines) {
346 report("already at last line");
347 return;
348 }
349 steps = 1;
350 break;
b801d8b2 351
fd85fef1
JF
352 case REQ_FIRST_LINE:
353 steps = -view->lineno;
354 break;
b801d8b2 355
fd85fef1
JF
356 case REQ_LAST_LINE:
357 steps = view->lines - view->lineno - 1;
358 }
359
360 view->lineno += steps;
22f66b0a 361 view->draw(view, view->lineno - steps - view->offset);
fd85fef1
JF
362
363 if (view->lineno < view->offset ||
364 view->lineno >= view->offset + view->height) {
365 if (steps < 0 && -steps > view->offset) {
366 steps = -view->offset;
b801d8b2 367 }
fd85fef1
JF
368 move_view(view, steps);
369 return;
b801d8b2
JF
370 }
371
22f66b0a 372 view->draw(view, view->lineno - view->offset);
fd85fef1 373
b801d8b2
JF
374 redrawwin(view->win);
375 wrefresh(view->win);
376
fd85fef1 377 report_position(view, view->height);
b801d8b2
JF
378}
379
380static void
381resize_view(struct view *view)
382{
383 int lines, cols;
384
385 getmaxyx(stdscr, lines, cols);
386
387 if (view->win) {
388 mvwin(view->win, 0, 0);
389 wresize(view->win, lines - 1, cols);
390
391 } else {
392 view->win = newwin(lines - 1, 0, 0, 0);
393 if (!view->win) {
fd85fef1 394 report("failed to create %s view", view->name);
b801d8b2
JF
395 return;
396 }
397 scrollok(view->win, TRUE);
398 }
fd85fef1
JF
399
400 getmaxyx(view->win, view->height, view->width);
b801d8b2
JF
401}
402
403
404static bool
405begin_update(struct view *view)
406{
407 char buf[1024];
408
409 if (view->cmd) {
fd85fef1
JF
410 char *id = view->id;
411
412 if (snprintf(buf, sizeof(buf), view->cmd, id, id, id) < sizeof(buf))
b801d8b2
JF
413 view->pipe = popen(buf, "r");
414
415 if (!view->pipe)
416 return FALSE;
417
418 if (nloading++ == 0)
419 nodelay(status_win, TRUE);
420 }
421
422 display[current_view] = view;
423
424 view->offset = 0;
425 view->lines = 0;
426 view->lineno = 0;
427
428 return TRUE;
429}
430
431static void
432end_update(struct view *view)
433{
434 wattrset(view->win, A_NORMAL);
435 pclose(view->pipe);
436 view->pipe = NULL;
437
438 if (nloading-- == 1)
439 nodelay(status_win, FALSE);
440}
441
442static int
443update_view(struct view *view)
444{
445 char buffer[BUFSIZ];
446 char *line;
22f66b0a 447 void **tmp;
b801d8b2 448 int redraw;
fd85fef1 449 int lines = view->height;
b801d8b2
JF
450
451 if (!view->pipe)
452 return TRUE;
453
fd85fef1 454 /* Only redraw after the first reading session. */
22f66b0a
JF
455 /* FIXME: ... and possibly more. */
456 redraw = view->height > view->lines;
b801d8b2
JF
457
458 tmp = realloc(view->line, sizeof(*view->line) * (view->lines + lines));
459 if (!tmp)
460 goto alloc_error;
461
462 view->line = tmp;
463
464 while ((line = fgets(buffer, sizeof(buffer), view->pipe))) {
465 int linelen;
466
b801d8b2
JF
467 linelen = strlen(line);
468 if (linelen)
469 line[linelen - 1] = 0;
470
22f66b0a 471 if (!view->read(view, line))
b801d8b2 472 goto alloc_error;
fd85fef1
JF
473
474 if (lines-- == 1)
475 break;
b801d8b2
JF
476 }
477
478 if (redraw)
479 redraw_view(view);
480
481 if (ferror(view->pipe)) {
fd85fef1 482 report("failed to read %s", view->cmd);
b801d8b2
JF
483 goto end;
484
485 } else if (feof(view->pipe)) {
486 report_position(view, 0);
487 goto end;
488 }
489
490 return TRUE;
491
492alloc_error:
fd85fef1 493 report("allocation failure");
b801d8b2
JF
494
495end:
496 end_update(view);
497 return FALSE;
498}
499
500
501static struct view *
502switch_view(struct view *prev, int request)
503{
504 struct view *view = &views[request - REQ_OFFSET];
505 struct view *displayed;
506 int i;
507
508 if (view == prev) {
509 foreach_view (displayed, i) ;
510
511 if (i == 1)
fd85fef1 512 report("already in %s view", view->name);
b801d8b2
JF
513 else
514 report("FIXME: Maximize");
515
516 return view;
517
518 } else {
519 foreach_view (displayed, i) {
520 if (view == displayed) {
521 current_view = i;
fd85fef1 522 report("new current view");
b801d8b2
JF
523 return view;
524 }
525 }
526 }
527
528 if (!view->win)
529 resize_view(view);
530
531 /* Reload */
532
533 if (view->line) {
534 for (i = 0; i < view->lines; i++)
535 if (view->line[i])
536 free(view->line[i]);
537
538 free(view->line);
539 view->line = NULL;
540 }
541
542 if (prev && prev->pipe)
543 end_update(prev);
544
545 if (begin_update(view)) {
546 if (!view->cmd)
547 report("%s", HELP);
548 else
549 report("loading...");
550 }
551
552 return view;
553}
554
555
556/* Process a keystroke */
557static int
558view_driver(struct view *view, int key)
559{
560 int request = get_request(key);
561 int i;
562
563 switch (request) {
564 case REQ_NEXT_LINE:
b801d8b2 565 case REQ_PREV_LINE:
fd85fef1
JF
566 case REQ_FIRST_LINE:
567 case REQ_LAST_LINE:
568 if (view)
569 navigate_view(view, request);
570 break;
571
572 case REQ_SCR_FLINE:
573 case REQ_SCR_BLINE:
574 case REQ_SCR_FPAGE:
575 case REQ_SCR_BPAGE:
b801d8b2
JF
576 if (view)
577 scroll_view(view, request);
578 break;
579
580 case REQ_MAIN:
581 case REQ_LOG:
582 case REQ_DIFF:
583 view = switch_view(view, request);
584 break;
585
586 case REQ_REDRAW:
587 redraw_view(view);
588 break;
589
590 case REQ_STOP:
591 foreach_view (view, i) {
592 if (view->pipe) {
593 end_update(view);
594 scroll_view(view, 0);
595 }
596 }
597 break;
598
599 case REQ_VERSION:
600 report("version %s", VERSION);
601 return TRUE;
602
603 case REQ_UPDATE:
604 doupdate();
605 return TRUE;
606
607 case REQ_QUIT:
608 return FALSE;
609
610 default:
611 report(HELP);
612 return TRUE;
613 }
614
615 return TRUE;
616}
617
618
619/*
620 * Rendering
621 */
622
623#define ATTR(line, attr) { (line), sizeof(line) - 1, (attr) }
624
625struct attr {
626 char *line;
627 int linelen;
628 int attr;
629};
630
631static struct attr attrs[] = {
632 ATTR("commit ", COLOR_PAIR(COLOR_GREEN)),
633 ATTR("Author: ", COLOR_PAIR(COLOR_CYAN)),
634 ATTR("Date: ", COLOR_PAIR(COLOR_YELLOW)),
635 ATTR("diff --git ", COLOR_PAIR(COLOR_YELLOW)),
636 ATTR("diff-tree ", COLOR_PAIR(COLOR_BLUE)),
637 ATTR("index ", COLOR_PAIR(COLOR_BLUE)),
638 ATTR("-", COLOR_PAIR(COLOR_RED)),
639 ATTR("+", COLOR_PAIR(COLOR_GREEN)),
640 ATTR("@", COLOR_PAIR(COLOR_MAGENTA)),
641};
642
643static int
22f66b0a 644pager_draw(struct view *view, unsigned int lineno)
b801d8b2
JF
645{
646 char *line;
647 int linelen;
648 int attr = A_NORMAL;
649 int i;
650
fd85fef1
JF
651 if (view->offset + lineno >= view->lines)
652 return FALSE;
653
b801d8b2
JF
654 line = view->line[view->offset + lineno];
655 if (!line) return FALSE;
656
657 linelen = strlen(line);
658
659 for (i = 0; i < ARRAY_SIZE(attrs); i++) {
660 if (linelen < attrs[i].linelen
661 || strncmp(attrs[i].line, line, attrs[i].linelen))
662 continue;
663
664 attr = attrs[i].attr;
665 break;
666 }
667
fd85fef1
JF
668 if (view->offset + lineno == view->lineno) {
669 if (i == 0)
670 strncpy(commit_id, line + 7, SIZEOF_ID);
671 attr = COLOR_PAIR(COLOR_CURSOR) | A_BOLD;
672 }
673
b801d8b2 674 wattrset(view->win, attr);
fd85fef1
JF
675 //mvwprintw(view->win, lineno, 0, "%4d: %s", view->offset + lineno, line);
676 mvwaddstr(view->win, lineno, 0, line);
b801d8b2
JF
677
678 return TRUE;
679}
680
22f66b0a
JF
681static int
682pager_read(struct view *view, char *line)
683{
684 view->line[view->lines] = strdup(line);
685 if (!view->line[view->lines])
686 return FALSE;
687
688 view->lines++;
689 return TRUE;
690}
691
692static int
693main_draw(struct view *view, unsigned int lineno)
694{
695 struct commit *commit;
696 int attr = A_NORMAL;
697
698 if (view->offset + lineno >= view->lines)
699 return FALSE;
700
701 commit = view->line[view->offset + lineno];
702 if (!commit) return FALSE;
703
704 attr = attrs[0].attr;
705
706 if (view->offset + lineno == view->lineno) {
707 strncpy(commit_id, commit->id, SIZEOF_ID);
708 attr = COLOR_PAIR(COLOR_CURSOR) | A_BOLD;
709 }
710
711 mvwaddch(view->win, lineno, 0, ACS_LTEE);
712 wattrset(view->win, attr);
713 mvwaddstr(view->win, lineno, 2, commit->title);
714 wattrset(view->win, A_NORMAL);
715
716 return TRUE;
717}
718
719static int
720main_read(struct view *view, char *line)
721{
722 int linelen = strlen(line);
723 int i;
724
725 for (i = 0; i < ARRAY_SIZE(attrs); i++) {
726 if (linelen < attrs[i].linelen
727 || strncmp(attrs[i].line, line, attrs[i].linelen))
728 continue;
729 break;
730 }
731
732 if (i == 0) {
733 struct commit *commit;
734
735 commit = calloc(1, sizeof(struct commit));
736 if (!commit)
737 return FALSE;
738
739 view->line[view->lines++] = commit;
740
741 strncpy(commit->id, line + 7, 41);
742
743 } else {
744 struct commit *commit = view->line[view->lines - 1];
745
746 if (!commit->title[0] &&
747 linelen > 5 &&
748 !strncmp(line, " ", 4) &&
749 !isspace(line[5]))
750 strncpy(commit->title, line + 4, sizeof(commit->title));
751 }
752
753 return TRUE;
754}
755
756
b801d8b2
JF
757/*
758 * Main
759 */
760
761static void
762quit(int sig)
763{
764 if (status_win)
765 delwin(status_win);
766 endwin();
767
768 /* FIXME: Shutdown gracefully. */
769
770 exit(0);
771}
772
773static void die(const char *err, ...)
774{
775 va_list args;
776
777 endwin();
778
779 va_start(args, err);
780 fputs("tig: ", stderr);
781 vfprintf(stderr, err, args);
782 fputs("\n", stderr);
783 va_end(args);
784
785 exit(1);
786}
787
788static void
789report(const char *msg, ...)
790{
791 va_list args;
792
793 va_start(args, msg);
794
795 werase(status_win);
796 wmove(status_win, 0, 0);
797
fd85fef1 798#if 0
b801d8b2 799 if (display[current_view])
fd85fef1
JF
800 wprintw(status_win, "%s %4s: ", commit_id, display[current_view]->name);
801#endif
b801d8b2
JF
802 vwprintw(status_win, msg, args);
803 wrefresh(status_win);
804
805 va_end(args);
806}
807
808static void
809init_colors(void)
810{
811 int bg = COLOR_BLACK;
812
813 start_color();
814
815 if (use_default_colors() != ERR)
816 bg = -1;
817
818 init_pair(COLOR_BLACK, COLOR_BLACK, bg);
819 init_pair(COLOR_GREEN, COLOR_GREEN, bg);
820 init_pair(COLOR_RED, COLOR_RED, bg);
821 init_pair(COLOR_CYAN, COLOR_CYAN, bg);
822 init_pair(COLOR_WHITE, COLOR_WHITE, bg);
823 init_pair(COLOR_MAGENTA, COLOR_MAGENTA, bg);
824 init_pair(COLOR_BLUE, COLOR_BLUE, bg);
825 init_pair(COLOR_YELLOW, COLOR_YELLOW, bg);
fd85fef1 826 init_pair(COLOR_CURSOR, COLOR_WHITE, COLOR_GREEN);
b801d8b2
JF
827}
828
829int
830main(int argc, char *argv[])
831{
832 int request = REQ_MAIN;
833 int x, y;
834
835 signal(SIGINT, quit);
836
837 initscr(); /* initialize the curses library */
838 nonl(); /* tell curses not to do NL->CR/NL on output */
839 cbreak(); /* take input chars one at a time, no wait for \n */
840 noecho(); /* don't echo input */
841 leaveok(stdscr, TRUE);
842 /* curs_set(0); */
843
844 if (has_colors())
845 init_colors();
846
847 getmaxyx(stdscr, y, x);
848 status_win = newwin(1, 0, y - 1, 0);
849 if (!status_win)
850 die("Failed to create status window");
851
852 /* Enable keyboard mapping */
853 keypad(status_win, TRUE);
854 wattrset(status_win, COLOR_PAIR(COLOR_GREEN));
855
856 while (view_driver(display[current_view], request)) {
857 struct view *view;
858 int i;
859
860 foreach_view (view, i) {
861 if (view->pipe) {
862 update_view(view);
863 }
864 }
865
866 /* Refresh, accept single keystroke of input */
867 request = wgetch(status_win);
868 if (request == KEY_RESIZE) {
869 int lines, cols;
870
871 getmaxyx(stdscr, lines, cols);
872 mvwin(status_win, lines - 1, 0);
873 wresize(status_win, 1, cols - 1);
874 }
875 }
876
877 quit(0);
878
879 return 0;
880}
881
882/**
883 * COPYRIGHT
884 * ---------
885 * Copyright (c) Jonas Fonseca, 2006
886 *
887 * This program is free software; you can redistribute it and/or modify
888 * it under the terms of the GNU General Public License as published by
889 * the Free Software Foundation; either version 2 of the License, or
890 * (at your option) any later version.
891 *
892 * SEE ALSO
893 * --------
894 * link:http://www.kernel.org/pub/software/scm/git/docs/[git(7)],
895 * link:http://www.kernel.org/pub/software/scm/cogito/docs/[cogito(7)]
896 **/