3 #include <string.h> // strchr
6 #include "include/viewer.h"
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 };
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 };
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 };
23 int ncurses_display(deck_t *deck, int notrans, int nofade) {
26 int l = 0; // line number
27 int colors = 0; // amount of colors supported
28 int fade = 0; // disable color fading by default
29 int trans = -1; // enable transparency if term supports it
30 int max_lines = 0; // max lines per slide
31 int max_cols = 0; // max columns per line
32 int offset; // text offset
34 // header line 1 is displayed at the top
35 int bar_top = (deck->headers > 0) ? 1 : 0;
36 // header line 2 and 3 are displayed at the bottom
37 int bar_bottom = (deck->headers > 1) ? 1 : 0;
39 slide_t *slide = deck->slide;
43 // set max_lines if line count exceeded
44 max_lines = (slide->lines > max_lines) ? slide->lines : max_lines;
47 // set max_cols if length exceeded
48 max_cols = (line->length > max_cols) ? line->length : max_cols;
54 // replace stdin with current tty if markdown input was piped
55 freopen("/dev/tty", "rw", stdin);
60 if((max_cols > COLS) ||
61 (max_lines + bar_top + bar_bottom + 2 > LINES)) {
63 fprintf(stderr, "Error: Terminal size %ix%i to small. Need at least %ix%i.\n",
64 COLS, LINES, max_cols, max_lines + bar_top + bar_bottom + 2);
69 // replace stdin with current tty if markdown input was piped
70 freopen("/dev/tty", "rw", stdin);
75 // disable output of keyboard typing
78 // make getch() process one char at a time
85 if(has_colors() == TRUE) {
89 if(notrans) trans = 0; // 0 is black
93 init_pair(CP_WHITE, 255, trans);
94 init_pair(CP_BLUE, 123, trans);
95 init_pair(CP_RED, 213, trans);
96 init_pair(CP_YELLOW, 208, trans);
98 // enable color fading
103 init_pair(CP_WHITE, 7, trans);
104 init_pair(CP_BLUE, 4, trans);
105 init_pair(CP_RED, 1, trans);
106 init_pair(CP_YELLOW, 3, trans);
112 // set background color of main window
114 wbkgd(stdscr, COLOR_PAIR(CP_YELLOW));
119 offset = next_blank(line->text, 0) + 1;
120 // add text to header
122 0, (COLS - line->length + offset) / 2,
123 "%s", &line->text->text[offset]);
128 line = deck->header->next;
129 offset = next_blank(line->text, 0) + 1;
130 // add text to left footer
133 "%s", &line->text->text[offset]);
135 if(deck->headers > 2) {
136 line = deck->header->next->next;
137 offset = next_blank(line->text, 0) + 1;
138 // add text to right footer
140 LINES - 1, COLS - line->length + offset - 3,
141 "%s", &line->text->text[offset]);
145 // make header + fooder visible
149 WINDOW *content = newwin(LINES - bar_top - bar_bottom, COLS, 0 + bar_top, 0);
151 wbkgd(content, COLOR_PAIR(CP_WHITE));
163 add_line(content, l, (COLS - max_cols) / 2, line, max_cols);
168 // make content visible
173 fade_in(content, trans, colors);
175 // re-enable fading after any undefined key press
176 if(COLORS == 256 && !nofade) fade = 1;
178 // wait for user input
181 // evaluate user input
184 // show previous slide
187 case 8: // BACKSPACE (ascii)
188 case 127: // BACKSPACE (xterm)
189 case 263: // BACKSPACE (getty)
209 // do not fade out on exit
215 // disable fading on undefined key press
222 fade_out(content, trans, colors);
230 void add_line(WINDOW *window, int y, int x, line_t *line, int max_cols) {
231 int i = 0; // increment
232 char *c; // char pointer for iteration
233 char *special = "\\*_"; // list of interpreted chars
234 cstack_t *stack = cstack_init();
236 if(line->text->text) {
237 int offset = 0; // text offset
238 offset = next_nonblank(line->text, 0);
241 if(CHECK_BIT(line->bits, IS_CODE)) {
243 // set static offset for code
244 offset = CODE_INDENT;
246 // reverse color for code blocks
247 wattron(window, A_REVERSE);
252 "%s", &line->text->text[offset]);
255 } else if(CHECK_BIT(line->bits, IS_QUOTE)) {
256 //TODO replace greater sign with color block
258 //FIXME remove dummy print code
261 "%s", &line->text->text[offset]);
266 if(CHECK_BIT(line->bits, IS_H1) || CHECK_BIT(line->bits, IS_H2)) {
268 // set headline color
269 wattron(window, COLOR_PAIR(CP_BLUE));
271 // enable underline for H1
272 if(CHECK_BIT(line->bits, IS_H1))
273 wattron(window, A_UNDERLINE);
276 while(line->text->text[offset] == '#')
277 offset = next_word(line->text, offset);
282 "%s", &line->text->text[offset]);
284 wattroff(window, A_UNDERLINE);
287 // move the cursor in position
290 // for each char in line
291 c = line->text->text;
294 // if char is in special char list
295 if(strchr(special, *c)) {
297 // closing special char (or second backslash)
298 if(is_attron(stack, *c)) {
301 // print escaped backslash
303 wprintw(window, "%c", *c);
307 wattron(window, COLOR_PAIR(CP_WHITE));
311 wattroff(window, A_UNDERLINE);
315 // remove top special char from stack
318 // treat special as regular char
319 } else if(is_attron(stack, '\\')) {
320 wprintw(window, "%c", *c);
322 // remove backslash from stack
325 // opening special char
330 wattron(window, COLOR_PAIR(CP_RED));
334 wattron(window, A_UNDERLINE);
336 // do nothing for backslashes
339 // push special char to stack
340 (stack->push)(stack, *c);
344 // print regular char
345 wprintw(window, "%c", *c);
351 //TODO pop stack until empty
355 // fill rest off line with spaces
356 for(i = getcurx(window) - x; i < max_cols; i++)
357 wprintw(window, "%s", " ");
359 // reset to default color
360 wattron(window, COLOR_PAIR(CP_WHITE));
361 wattroff(window, A_UNDERLINE);
362 wattroff(window, A_REVERSE);
365 (stack->delete)(stack);
368 int is_attron(cstack_t *stack, char c) {
369 // test if char is on top of stack
370 if(stack->head >= 0) {
371 if((stack->top)(stack) == c) {
378 void fade_out(WINDOW *window, int trans, int colors) {
381 for(i = 22; i >= 0; i--) {
382 // darken color pairs
383 init_pair(CP_WHITE, white_ramp[i], trans);
384 init_pair(CP_BLUE, blue_ramp[i], trans);
385 init_pair(CP_RED, red_ramp[i], trans);
386 // refresh window with new color
388 // delay for our eyes to recognize the change
394 void fade_in(WINDOW *window, int trans, int colors) {
397 for(i = 0; i <= 23; i++) {
398 // lighten color pairs
399 init_pair(CP_WHITE, white_ramp[i], trans);
400 init_pair(CP_BLUE, blue_ramp[i], trans);
401 init_pair(CP_RED, red_ramp[i], trans);
402 // refresh window with new color
404 // delay for our eyes to recognize the change