Navigate to any slide number
[smdp.git] / src / viewer.c
index 447d3fe..b540b1a 100644 (file)
@@ -60,7 +60,7 @@ static short red_ramp_invert[24]   = { 15, 231, 231, 224, 224, 225,
                                       206, 207, 201, 200, 199, 199,
                                       198, 198, 197, 197, 196, 196};
 
-int ncurses_display(deck_t *deck, int notrans, int nofade, int invert) {
+int ncurses_display(deck_t *deck, int notrans, int nofade, int invert, int reload, int noreload) {
 
     int c = 0;          // char
     int i = 0;          // iterate
@@ -93,7 +93,14 @@ int ncurses_display(deck_t *deck, int notrans, int nofade, int invert) {
         lc = 0;
         line = slide->line;
 
-        while(line) {
+        while(line && line->text) {
+
+            if (line->text->text)
+                lc += url_count_inline(line->text->text);
+
+            if (line->text->text)
+                line->length -= url_len_inline(line->text->text);
+
             if(line->length > COLS) {
                 i = line->length;
                 offset = 0;
@@ -113,7 +120,8 @@ int ncurses_display(deck_t *deck, int notrans, int nofade, int invert) {
                         fprintf(stderr, "Error: Terminal width (%i columns) too small. Need at least %i columns.\n", COLS, i);
                         fprintf(stderr, "You may need to shorten some lines by inserting line breaks.\n");
 
-                        return 1;
+                        // no reload
+                        return 0;
                     }
 
                     // set max_cols
@@ -147,9 +155,10 @@ int ncurses_display(deck_t *deck, int notrans, int nofade, int invert) {
 
         // print error
         fprintf(stderr, "Error: Terminal height (%i lines) too small. Need at least %i lines.\n", LINES, max_lines + bar_top + bar_bottom);
-        fprintf(stderr, "You may need to add additional horizontal rules ('***') to split your file in shorter slides.\n");
+        fprintf(stderr, "You may need to add additional horizontal rules (---) to split your file in shorter slides.\n");
 
-        return 1;
+        // no reload
+        return 0;
     }
 
     // disable cursor
@@ -233,7 +242,21 @@ int ncurses_display(deck_t *deck, int notrans, int nofade, int invert) {
         wbkgd(content, COLOR_PAIR(CP_WHITE));
 
     slide = deck->slide;
+
+    // find slide to reload
+    while(reload > 1 && reload <= deck->slides) {
+        slide = slide->next;
+        sc++;
+        reload--;
+    }
+
+    // reset reload indicator
+    reload = 0;
+
     while(slide) {
+
+        url_init();
+
         // clear windows
         werase(content);
         werase(stdscr);
@@ -266,6 +289,7 @@ int ncurses_display(deck_t *deck, int notrans, int nofade, int invert) {
                   "%d / %d", sc, deck->slides);
 
         // make header + fooder visible
+        wrefresh(content);
         wrefresh(stdscr);
 
         line = slide->line;
@@ -278,6 +302,13 @@ int ncurses_display(deck_t *deck, int notrans, int nofade, int invert) {
             line = line->next;
         }
 
+        int i, ymax;
+        getmaxyx( content, ymax, i );
+        for (i = 0; i < url_get_amount(); i++) {
+            mvwprintw(content, ymax - url_get_amount() - 1 + i, 3,
+                      "[%d] %s", i, url_get_target(i));
+        }
+
         // make content visible
         wrefresh(content);
 
@@ -330,16 +361,17 @@ int ncurses_display(deck_t *deck, int notrans, int nofade, int invert) {
                 break;
 
             // show slide n
-            case '9': i++;
-            case '8': i++;
-            case '7': i++;
-            case '6': i++;
-            case '5': i++;
-            case '4': i++;
-            case '3': i++;
-            case '2': i++;
-            case '1': i++;
-                if(i <= deck->slides) {
+            case '9':
+            case '8':
+            case '7':
+            case '6':
+            case '5':
+            case '4':
+            case '3':
+            case '2':
+            case '1':
+                i = get_slide_number(c);
+                if(i > 0 && i <= deck->slides) {
                     while(sc != i) {
                         // search forward
                         if(sc < i) {
@@ -377,10 +409,24 @@ int ncurses_display(deck_t *deck, int notrans, int nofade, int invert) {
                 }
                 break;
 
+            // reload
+            case 'r':
+                if(noreload == 0) {
+                    // reload slide N
+                    reload = sc;
+                    slide = NULL;
+                } else {
+                    // disable fading if reload is not possible
+                    fade = false;
+                }
+                break;
+
             // quit
             case 'q':
                 // do not fade out on exit
                 fade = false;
+                // do not reload
+                reload = 0;
                 slide = NULL;
                 break;
 
@@ -393,11 +439,20 @@ int ncurses_display(deck_t *deck, int notrans, int nofade, int invert) {
         // fade out
         if(fade)
             fade_out(content, trans, colors, invert);
+
+        url_purge();
     }
 
+    // disable ncurses
     endwin();
 
-    return 0;
+    // free ncurses memory
+    delwin(content);
+    if(reload == 0)
+        delwin(stdscr);
+
+    // return reload indicator (0 means no reload)
+    return reload;
 }
 
 void add_line(WINDOW *window, int y, int x, line_t *line, int max_cols, int colors) {
@@ -559,8 +614,10 @@ void add_line(WINDOW *window, int y, int x, line_t *line, int max_cols, int colo
 }
 
 void inline_display(WINDOW *window, const char *c, const int colors) {
-    const static char *special = "\\*_`"; // list of interpreted chars
+    const static char *special = "\\*_`!["; // list of interpreted chars
     const char *i = c; // iterator
+    const char *start_link_name, *start_url;
+    int length_link_name, url_num;
     cstack_t *stack = cstack_init();
 
 
@@ -573,7 +630,7 @@ void inline_display(WINDOW *window, const char *c, const int colors) {
             // closing special char (or second backslash)
             // only if not followed by :alnum:
             if((stack->top)(stack, *i) &&
-               (!isalnum(*(i + 1)) || *(i + 1) == '\0' || *i == '\\')) {
+               (!isalnum((int)i[1]) || *(i + 1) == '\0' || *i == '\\')) {
 
                 switch(*i) {
                     // print escaped backslash
@@ -611,12 +668,57 @@ void inline_display(WINDOW *window, const char *c, const int colors) {
 
                 // emphasis or code span can start after new-line or space only
                 // and of cause after another emphasis markup
-                if(*(i - 1) == ' ' ||
-                   ((*(i - 1) == '_' || *(i - 1) == '*') && (*(i - 2) == ' ' || (i - 1) == c)) ||
-                   *i == '\\' ||
-                   i == c) {
+                //TODO this condition looks ugly
+                if(i == c ||
+                   *(i - 1) == ' ' ||
+                   ((*(i - 1) == '_' || *(i - 1) == '*') && ((i - 1) == c || *(i - 2) == ' ')) ||
+                   *i == '\\') {
+
+                    // url in pandoc style
+                    if ((*i == '[' && strchr(i, ']')) ||
+                        (*i == '!' && *(i + 1) == '[' && strchr(i, ']'))) {
 
-                    switch(*i) {
+                        if (*i == '!') i++;
+
+                        if (strchr(i, ']')[1] == '(') {
+                            i++;
+
+                            // turn higlighting and underlining on
+                            if (colors)
+                                wattron(window, COLOR_PAIR(CP_BLUE));
+                            wattron(window, A_UNDERLINE);
+
+                            start_link_name = i;
+
+                            // print the content of the label
+                            // the label is printed as is
+                            do {
+                                wprintw(window, "%c", *i);
+                                i++;
+                            } while (*i != ']');
+
+                            length_link_name = i - 1 - start_link_name;
+
+                            i++;
+                            i++;
+
+                            start_url = i;
+
+                            while (*i != ')') i++;
+
+                            url_num = url_add(start_link_name, length_link_name, start_url, i - start_url, 0,0);
+
+                            wprintw(window, " [%d]", url_num);
+
+                            // turn highlighting and underlining off
+                            wattroff(window, A_UNDERLINE);
+                            wattron(window, COLOR_PAIR(CP_WHITE));
+
+                        } else {
+                            wprintw(window, "[");
+                        }
+
+                    } else switch(*i) {
                         // enable highlight
                         case '*':
                             if(colors)
@@ -738,3 +840,20 @@ int int_length (int val) {
     }
     return l;
 }
+
+int get_slide_number(char init) {
+    int retval = init - '0';
+    char c;
+    // block for tenths of a second when using getch, ERR if no input
+    halfdelay(GOTO_SLIDE_DELAY);
+    while((c = getch()) != ERR) {
+        if (c < '0' || c > '9') {
+            retval = -1;
+            break;
+        }
+        retval = (retval * 10) + (c - '0');
+    }
+    nocbreak();     // cancel half delay mode
+    cbreak();       // go back to cbreak
+    return retval;
+}