3 #include <string.h> // strchr
6 #include "include/parser.h"
7 #include "include/viewer.h"
9 static short white_ramp[24] = { 16, 232, 233, 234, 235, 236,
10 237, 238, 239, 240, 241, 242,
11 244, 245, 246, 247, 248, 249,
12 250, 251, 252, 253, 254, 255 };
14 static short blue_ramp[24] = { 16, 17, 17, 18, 18, 19,
15 19, 20, 20, 21, 27, 32,
16 33, 38, 39, 44, 45, 45,
17 81, 81, 51, 51, 123, 123 };
19 static short red_ramp[24] = { 16, 52, 52, 53, 53, 89,
20 89, 90, 90, 126, 127, 127,
21 163, 163, 164, 164, 200, 200,
22 201, 201, 207, 207, 213, 213 };
24 int ncurses_display(deck_t *deck, int notrans, int nofade) {
27 int l = 0; // line number
28 int colors = 0; // amount of colors supported
29 int fade = 0; // disable color fading by default
30 int trans = -1; // enable transparency if term supports it
31 int max_lines = 0; // max lines per slide
32 int max_cols = 0; // max columns per line
33 int offset; // text offset
35 // header line 1 is displayed at the top
36 int bar_top = (deck->headers > 0) ? 1 : 0;
37 // header line 2 and 3 are displayed at the bottom
38 int bar_bottom = (deck->headers > 1) ? 1 : 0;
40 slide_t *slide = deck->slide;
44 // set max_lines if line count exceeded
45 max_lines = (slide->lines > max_lines) ? slide->lines : max_lines;
48 // set max_cols if length exceeded
49 max_cols = (line->length > max_cols) ? line->length : max_cols;
55 // replace stdin with current tty if markdown input was piped
56 freopen("/dev/tty", "rw", stdin);
61 if((max_cols > COLS) ||
62 (max_lines + bar_top + bar_bottom + 2 > LINES)) {
64 fprintf(stderr, "Error: Terminal size %ix%i to small. Need at least %ix%i.\n",
65 COLS, LINES, max_cols, max_lines + bar_top + bar_bottom + 2);
70 // replace stdin with current tty if markdown input was piped
71 freopen("/dev/tty", "rw", stdin);
76 // disable output of keyboard typing
79 // make getch() process one char at a time
86 if(has_colors() == TRUE) {
90 if(notrans) trans = 0; // 0 is black
94 init_pair(CP_WHITE, 255, trans);
95 init_pair(CP_BLUE, 123, trans);
96 init_pair(CP_RED, 213, trans);
97 init_pair(CP_YELLOW, 208, trans);
99 // enable color fading
100 if(!nofade) fade = 1;
104 init_pair(CP_WHITE, 7, trans);
105 init_pair(CP_BLUE, 4, trans);
106 init_pair(CP_RED, 1, trans);
107 init_pair(CP_YELLOW, 3, trans);
113 // set background color of main window
115 wbkgd(stdscr, COLOR_PAIR(CP_YELLOW));
120 offset = next_blank(line->text, 0) + 1;
121 // add text to header
123 0, (COLS - line->length + offset) / 2,
124 "%s", &line->text->text[offset]);
129 line = deck->header->next;
130 offset = next_blank(line->text, 0) + 1;
131 // add text to left footer
134 "%s", &line->text->text[offset]);
136 if(deck->headers > 2) {
137 line = deck->header->next->next;
138 offset = next_blank(line->text, 0) + 1;
139 // add text to right footer
141 LINES - 1, COLS - line->length + offset - 3,
142 "%s", &line->text->text[offset]);
146 // make header + fooder visible
150 WINDOW *content = newwin(LINES - bar_top - bar_bottom, COLS, 0 + bar_top, 0);
152 wbkgd(content, COLOR_PAIR(CP_WHITE));
164 add_line(content, l, (COLS - max_cols) / 2, line, max_cols);
169 // make content visible
174 fade_in(content, trans, colors);
176 // re-enable fading after any undefined key press
177 if(COLORS == 256 && !nofade) fade = 1;
179 // wait for user input
182 // evaluate user input
185 // show previous slide
188 case 8: // BACKSPACE (ascii)
189 case 127: // BACKSPACE (xterm)
190 case 263: // BACKSPACE (getty)
210 // do not fade out on exit
216 // disable fading on undefined key press
223 fade_out(content, trans, colors);
231 void add_line(WINDOW *window, int y, int x, line_t *line, int max_cols) {
232 int i = 0; // increment
233 char *c; // char pointer for iteration
234 char *special = "\\*_"; // list of interpreted chars
235 cstack_t *stack = cstack_init();
237 if(line->text->text) {
238 int offset = 0; // text offset
239 offset = next_nonblank(line->text, 0);
242 if(CHECK_BIT(line->bits, IS_CODE)) {
244 // set static offset for code
245 offset = CODE_INDENT;
247 // reverse color for code blocks
248 wattron(window, A_REVERSE);
253 "%s", &line->text->text[offset]);
256 } else if(CHECK_BIT(line->bits, IS_QUOTE)) {
257 //TODO replace greater sign with color block
259 //FIXME remove dummy print code
262 "%s", &line->text->text[offset]);
267 if(CHECK_BIT(line->bits, IS_H1) || CHECK_BIT(line->bits, IS_H2)) {
269 // set headline color
270 wattron(window, COLOR_PAIR(CP_BLUE));
272 // enable underline for H1
273 if(CHECK_BIT(line->bits, IS_H1))
274 wattron(window, A_UNDERLINE);
277 while(line->text->text[offset] == '#')
278 offset = next_word(line->text, offset);
283 "%s", &line->text->text[offset]);
285 wattroff(window, A_UNDERLINE);
288 // move the cursor in position
291 // for each char in line
292 c = line->text->text;
295 // if char is in special char list
296 if(strchr(special, *c)) {
298 // closing special char (or second backslash)
299 if(is_attron(stack, *c)) {
302 // print escaped backslash
304 wprintw(window, "%c", *c);
308 wattron(window, COLOR_PAIR(CP_WHITE));
312 wattroff(window, A_UNDERLINE);
316 // remove top special char from stack
319 // treat special as regular char
320 } else if(is_attron(stack, '\\')) {
321 wprintw(window, "%c", *c);
323 // remove backslash from stack
326 // opening special char
331 wattron(window, COLOR_PAIR(CP_RED));
335 wattron(window, A_UNDERLINE);
337 // do nothing for backslashes
340 // push special char to stack
341 (stack->push)(stack, *c);
345 // print regular char
346 wprintw(window, "%c", *c);
352 //TODO pop stack until empty
356 // fill rest off line with spaces
357 for(i = getcurx(window) - x; i < max_cols; i++)
358 wprintw(window, "%s", " ");
360 // reset to default color
361 wattron(window, COLOR_PAIR(CP_WHITE));
362 wattroff(window, A_UNDERLINE);
363 wattroff(window, A_REVERSE);
366 (stack->delete)(stack);
369 int is_attron(cstack_t *stack, char c) {
370 // test if char is on top of stack
371 if(stack->head >= 0) {
372 if((stack->top)(stack) == c) {
379 void fade_out(WINDOW *window, int trans, int colors) {
382 for(i = 22; i >= 0; i--) {
383 // darken color pairs
384 init_pair(CP_WHITE, white_ramp[i], trans);
385 init_pair(CP_BLUE, blue_ramp[i], trans);
386 init_pair(CP_RED, red_ramp[i], trans);
387 // refresh window with new color
389 // delay for our eyes to recognize the change
395 void fade_in(WINDOW *window, int trans, int colors) {
398 for(i = 0; i <= 23; i++) {
399 // lighten color pairs
400 init_pair(CP_WHITE, white_ramp[i], trans);
401 init_pair(CP_BLUE, blue_ramp[i], trans);
402 init_pair(CP_RED, red_ramp[i], trans);
403 // refresh window with new color
405 // delay for our eyes to recognize the change