added viewer to main program - display dummy text for testing
[smdp.git] / viewer.c
1 #include <ncurses.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4
5 #include "include/parser.h"
6 #include "include/viewer.h"
7
8 static short white_ramp[24] = { 16, 232, 233, 234, 235, 236,
9                                237, 238, 239, 240, 241, 242,
10                                244, 245, 246, 247, 248, 249,
11                                250, 251, 252, 253, 254, 255 };
12
13 static short blue_ramp[24]  = { 16,  17,  17,  18,  18,  19,
14                                 19,  20,  20,  21,  27,  32,
15                                 33,  38,  39,  44,  45,  45,
16                                 81,  81,  51,  51, 123, 123 };
17
18 static short red_ramp[24]   = { 16,  52,  52,  53,  53,  89,
19                                 89,  90,  90, 126, 127, 127,
20                                163, 163, 164, 164, 200, 200,
21                                201, 201, 207, 207, 213, 213 };
22
23 int ncurses_display(deck_t *deck, int notrans, int nofade) {
24
25     int c = 0;          // char
26     int colors = 0;     // amount of colors supported
27     int fade = 0;       // disable color fading by default
28     int trans = -1;     // enable transparency if term supports it
29     int max_lines = 0;  // max lines per slide
30     int max_cols = 0;   // max columns per line
31
32     // header line 1 is displayed at the top
33     int bar_top = (deck->headers > 0) ? 1 : 0;
34     // header line 2 and 3 are displayed at the bottom
35     int bar_bottom = (deck->headers > 1) ? 1 : 0;
36
37     slide_t *slide = deck->slide;
38     line_t *line;
39
40     while(slide) {
41         // set max_lines if line count exceeded
42         max_lines = (slide->lines > max_lines) ? slide->lines : max_lines;
43         line = slide->line;
44         while(line) {
45             // set max_cols if length exceeded
46             max_cols = (line->length > max_cols) ? line->length : max_cols;
47             line = line->next;
48         }
49         slide = slide->next;
50     }
51
52     // replace stdin with current tty if markdown input was piped
53     freopen("/dev/tty", "rw", stdin);
54
55     // init ncurses
56     initscr();
57
58     if((max_cols > COLS) ||
59        (max_lines + bar_top + bar_bottom + 2 > LINES)) {
60
61         fprintf(stderr, "Error: Terminal size %ix%i to small. Need at least %ix%i.\n",
62             COLS, LINES, max_cols, max_lines + bar_top + bar_bottom + 2);
63         endwin();
64         return(1);
65     }
66
67     // replace stdin with current tty if markdown input was piped
68     freopen("/dev/tty", "rw", stdin);
69
70     // disable cursor
71     curs_set(0);
72
73     // disable output of keyboard typing
74     noecho();
75
76     // make getch() process one char at a time
77     cbreak();
78
79     // enable arrow keys
80     keypad(stdscr,TRUE);
81
82     // set colors
83     if(has_colors() == TRUE) {
84         start_color();
85         use_default_colors();
86
87         if(notrans) trans = 0; // 0 is black
88
89         if(COLORS == 256) {
90             // 256 color mode
91             init_pair(CP_WHITE, 255, trans);
92             init_pair(CP_BLUE, 123, trans);
93             init_pair(CP_RED, 213, trans);
94             init_pair(CP_YELLOW, 208, trans);
95
96             // enable color fading
97             if(!nofade) fade = 1;
98         } else {
99
100             // 8 color mode
101             init_pair(CP_WHITE, 7, trans);
102             init_pair(CP_BLUE, 4, trans);
103             init_pair(CP_RED, 1, trans);
104             init_pair(CP_YELLOW, 3, trans);
105         }
106
107         colors = 1;
108     }
109
110     // set background color of main window
111     if(colors)
112         wbkgd(stdscr, COLOR_PAIR(CP_YELLOW));
113
114     // setup header
115     if(bar_top) {
116         //TODO move cursor to calculated indentation
117         wmove(stdscr, 0, 1);
118         //TODO add text to header
119         wprintw(stdscr, "header");
120     }
121
122     // setup footer
123     if(bar_bottom) {
124         //TODO move cursor to calculated indentation
125         wmove(stdscr, LINES - 1, 1);
126         //TODO add text to footer
127         wprintw(stdscr, "footer");
128     }
129
130     // make header + fooder visible
131     wrefresh(stdscr);
132
133     // setup main window
134     WINDOW *content = newwin(LINES - bar_top - bar_bottom, COLS, 0 + bar_top, 0);
135     if(colors)
136         wbkgd(content, COLOR_PAIR(CP_WHITE));
137
138     slide = deck->slide;
139     while(slide) {
140         // clear main window
141         werase(content);
142
143         //TODO print lines
144         wprintw(content, "content");
145
146         // make content visible
147         wrefresh(content);
148
149         // fade in
150         if(fade)
151             fade_in(content, trans, colors);
152
153         // wait for user input
154         c = getch();
155
156         // evaluate user input
157         switch(c) {
158
159             // show previous slide
160             case KEY_UP:
161             case KEY_LEFT:
162             case KEY_BACKSPACE:
163             case 'h':
164             case 'k':
165                 if(slide->prev)
166                     slide = slide->prev;
167                 break;
168
169             // show next slide
170             case KEY_DOWN:
171             case KEY_RIGHT:
172             case KEY_ENTER:
173             case 'j':
174             case 'l':
175                 if(slide->next)
176                     slide = slide->next;
177                 break;
178
179             // quit
180             case 'q':
181                 // do not fade out on exit
182                 fade = 0;
183                 slide = (void*)0;
184                 break;
185         }
186
187         // fade out
188         if(fade)
189             fade_out(content, trans, colors);
190     }
191
192     endwin();
193
194     return(0);
195 }
196
197 void fade_out(WINDOW *window, int trans, int colors) {
198     int i; // increment
199     if(colors) {
200         for(i = 22; i >= 0; i--) {
201             // darken color pairs
202             init_pair(CP_WHITE, white_ramp[i], trans);
203             init_pair(CP_BLUE, blue_ramp[i], trans);
204             init_pair(CP_RED, red_ramp[i], trans);
205             // refresh window with new color
206             wrefresh(window);
207             // delay for our eyes to recognize the change
208             usleep(FADE_DELAY);
209         }
210     }
211 }
212
213 void fade_in(WINDOW *window, int trans, int colors) {
214     int i; // increment
215     if(colors) {
216         for(i = 0; i <= 23; i++) {
217             // lighten color pairs
218             init_pair(CP_WHITE, white_ramp[i], trans);
219             init_pair(CP_BLUE, blue_ramp[i], trans);
220             init_pair(CP_RED, red_ramp[i], trans);
221             // refresh window with new color
222             wrefresh(window);
223             // delay for our eyes to recognize the change
224             usleep(FADE_DELAY);
225         }
226     }
227 }
228