#include "common.h"
typedef struct _cstack_t {
- char *content;
+ wchar_t *content;
size_t alloc;
size_t size;
int head;
- void (*push)(struct _cstack_t *self, char c);
- char (*pop)(struct _cstack_t *self);
- bool (*top)(struct _cstack_t *self, char c);
+ void (*push)(struct _cstack_t *self, wchar_t c);
+ wchar_t (*pop)(struct _cstack_t *self);
+ bool (*top)(struct _cstack_t *self, wchar_t c);
bool (*empty)(struct _cstack_t *self);
void (*delete)(struct _cstack_t *self);
} cstack_t;
cstack_t *cstack_init();
-void cstack_push(cstack_t *self, char c);
-char cstack_pop(cstack_t *self);
-bool cstack_top(cstack_t *self, char c);
+void cstack_push(cstack_t *self, wchar_t c);
+wchar_t cstack_pop(cstack_t *self);
+bool cstack_top(cstack_t *self, wchar_t c);
bool cstack_empty(cstack_t *self);
void cstack_delete(cstack_t *self);
#define REALLOC_ADD 10
typedef struct _cstring_t {
- char *text;
+ wchar_t *value;
size_t size;
size_t alloc;
- void (*expand)(struct _cstring_t *self, char x);
- void (*expand_arr)(struct _cstring_t *self, char *x);
+ void (*expand)(struct _cstring_t *self, wchar_t x);
+ void (*expand_arr)(struct _cstring_t *self, wchar_t *x);
void (*strip)(struct _cstring_t *self, int pos, int len);
void (*reset)(struct _cstring_t *self);
void (*delete)(struct _cstring_t *self);
} cstring_t;
cstring_t *cstring_init();
-void cstring_expand(cstring_t *self, char x);
-void cstring_expand_arr(cstring_t *self, char *x);
+void cstring_expand(cstring_t *self, wchar_t x);
+void cstring_expand_arr(cstring_t *self, wchar_t *x);
void cstring_strip(cstring_t *self, int pos, int len);
void cstring_reset(cstring_t *self);
void cstring_delete(cstring_t *self);
IS_UNORDERED_LIST_3,
IS_UNORDERED_LIST_EXT,
IS_CENTER,
+ IS_STOP,
IS_EMPTY
};
struct _slide_t *prev;
struct _slide_t *next;
int lines;
+ int stop;
} slide_t;
typedef struct _deck_t {
#include "markdown.h"
#include "cstack.h"
+#if defined( CYGWIN )
+#undef WEOF
+#define WEOF (0xffff)
+#endif // defined( CYGWIN )
+
#define EXPAND_TABS 4
#define CODE_INDENT 4
#define UNORDERED_LIST_MAX_LEVEL 3
int markdown_analyse(cstring_t *text, int prev);
void markdown_debug(deck_t *deck, int debug);
void adjust_line_length(line_t *line);
-bool is_utf8(char ch);
-int length_utf8(char ch);
int next_nonblank(cstring_t *text, int i);
int prev_blank(cstring_t *text, int i);
int next_blank(cstring_t *text, int i);
*/
typedef struct _url_t {
- char *link_name;
- char *target;
+ wchar_t *link_name;
+ wchar_t *target;
int x;
int y;
struct _url_t *next;
} url_t;
void url_init(void);
-int url_add(const char *link_name, int link_name_length, const char *target, int target_length, int x, int y);
-char * url_get_target(int index);
-char * url_get_name(int index);
+int url_add(const wchar_t *link_name, int link_name_length, const wchar_t *target, int target_length, int x, int y);
+wchar_t* url_get_target(int index);
+wchar_t* url_get_name(int index);
int url_get_amount(void);
void url_purge(void);
void url_dump(void);
-int url_count_inline(const char *line);
-int url_len_inline(const char *text);
+int url_count_inline(const wchar_t *line);
+int url_len_inline(const wchar_t *value);
#endif // !defined( URL_H )
*
*/
+#define _GNU_SOURCE // enable ncurses wchar support
+#define _XOPEN_SOURCE_EXTENDED 1 // enable ncurses wchar support
+
#if defined( WIN32 )
#include <curses.h>
#else
int ncurses_display(deck_t *deck, int notrans, int nofade, int invert, int reload, int noreload);
void add_line(WINDOW *window, int y, int x, line_t *line, int max_cols, int colors);
-void inline_display(WINDOW *window, const char *c, const int colors);
+void inline_display(WINDOW *window, const wchar_t *c, const int colors);
void fade_out(WINDOW *window, int trans, int colors, int invert);
void fade_in(WINDOW *window, int trans, int colors, int invert);
int int_length (int val);
ifeq ($(OS),Windows_NT)
ifeq (,$(findstring CYGWIN,$(UNAME_S)))
CPPFLAGS += -DWIN32
+ else
+ CPPFLAGS += -DCYGWIN
endif
endif
*
*/
+#include <wchar.h>
#include <stdio.h> // fprintf
#include <stdlib.h> // malloc, realloc
return stack;
}
-void cstack_push(cstack_t *self, char c) {
+void cstack_push(cstack_t *self, wchar_t c) {
if(self->size + sizeof(c) > self->alloc) {
- self->alloc += (sizeof(char));
+ self->alloc += (sizeof(wchar_t));
if((self->content = realloc(self->content, self->alloc)) == NULL) {
fprintf(stderr, "%s\n", "cstack_push() failed to reallocate memory.");
exit(EXIT_FAILURE);
}
}
self->content[++self->head] = c;
- self->size += (sizeof(char));
+ self->size += (sizeof(wchar_t));
}
-char cstack_pop(cstack_t *self) {
- self->size -= (sizeof(char));
+wchar_t cstack_pop(cstack_t *self) {
+ self->size -= (sizeof(wchar_t));
return self->content[self->head--];
}
-bool cstack_top(cstack_t *self, char c) {
+bool cstack_top(cstack_t *self, wchar_t c) {
return self->head >= 0 && self->content[self->head] == c;
}
*
*/
-#include <string.h> // strlen, memmove
+#include <wchar.h> // wcslen, wcscat, wmemmove
#include <stdio.h> // fprintf
#include <stdlib.h> // malloc, realloc
cstring_t *cstring_init() {
cstring_t *x = NULL;
if((x = malloc(sizeof(cstring_t))) != NULL) {
- x->text = NULL;
+ x->value = NULL;
x->size = x->alloc = 0;
x->expand = cstring_expand;
x->expand_arr = cstring_expand_arr;
return x;
}
-void cstring_expand(cstring_t *self, char x) {
- if(self->size + sizeof(x) + sizeof(char) > self->alloc) {
- self->alloc += (REALLOC_ADD * sizeof(char));
- if((self->text = realloc(self->text, self->alloc)) == NULL) {
+void cstring_expand(cstring_t *self, wchar_t x) {
+ if((self->size + 2) * sizeof(wchar_t) > self->alloc) {
+ self->alloc += (REALLOC_ADD * sizeof(wchar_t));
+ if((self->value = realloc(self->value, self->alloc)) == NULL) {
fprintf(stderr, "%s\n", "cstring_expand() failed to reallocate memory.");
exit(EXIT_FAILURE);
}
}
- self->text[self->size] = x;
- self->text[self->size+1] = '\0';
- self->size = strlen(self->text);
+ self->value[self->size] = x;
+ self->value[self->size+1] = L'\0';
+ self->size = wcslen(self->value);
}
-void cstring_expand_arr(cstring_t *self, char *x) {
- if(self->size + strlen(x) + sizeof(char) > self->alloc) {
- self->alloc = ((strlen(x) + self->size + 1) * sizeof(char));
- if((self->text = realloc(self->text, self->alloc)) == NULL) {
- fprintf(stderr, "%s\n", "cstring_expand() failed to reallocate memory.");
+void cstring_expand_arr(cstring_t *self, wchar_t *x) {
+ if((self->size + wcslen(x) + 1) * sizeof(wchar_t) > self->alloc) {
+ self->alloc = ((self->size + wcslen(x) + 1) * sizeof(wchar_t));
+ if((self->value = realloc(self->value, self->alloc)) == NULL) {
+ fprintf(stderr, "%s\n", "cstring_expand_arr() failed to reallocate memory.");
exit(EXIT_FAILURE);
}
}
- self->text = strcat(self->text, x);
- self->size = strlen(self->text);
- self->text[self->size+1] = '\0';
+ self->value = wcscat(self->value, x);
+ self->size = wcslen(self->value);
+ self->value[self->size+1] = L'\0';
}
void cstring_strip(cstring_t *self, int pos, int len) {
if(pos + len >= self->size) {
if(pos <= self->size) {
- self->text[pos] = '\0';
+ self->value[pos] = L'\0';
self->size = pos;
}
return;
}
- memmove(&self->text[pos], &self->text[pos+len], self->size - pos - len+1);
+ wmemmove(&self->value[pos], &self->value[pos+len], self->size - pos - len+1);
self->size -= len;
}
void cstring_reset(cstring_t *self) {
- free(self->text);
- self->text = NULL;
+ free(self->value);
+ self->value = NULL;
self->size = self->alloc = 0;
}
void cstring_delete(cstring_t *self) {
- free(self->text);
+ free(self->value);
free(self);
}
#include <errno.h>
#include <getopt.h>
+#include <locale.h> // setlocale
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
}
}
+ // set locale to read and display UTF-8 correctly in ncurses
+ setlocale(LC_CTYPE, "en_US.UTF8");
+
// open file or set input to STDIN
char *file = NULL;
FILE *input;
slide_t *x = malloc(sizeof(slide_t));
x->line = NULL;
x->prev = x->next = NULL;
- x->lines = 0;
+ x->lines = x->stop = 0;
return x;
}
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
#include <string.h>
#include "parser.h"
deck_t *markdown_load(FILE *input) {
- int c = 0; // char
+ wchar_t c = L'\0'; // char
int i = 0; // increment
int hc = 0; // header count
int lc = 0; // line count
// initialize bits as empty line
SET_BIT(bits, IS_EMPTY);
- while ((c = fgetc(input)) != EOF) {
+ while ((c = fgetwc(input)) != WEOF) {
if (ferror(input)) {
fprintf(stderr, "markdown_load() failed to read input: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
- if(c == '\n') {
+ if(c == L'\n') {
// markdown analyse
prev = bits;
// clear text
(text->reset)(text);
+ } else if(line && CHECK_BIT(bits, IS_STOP)) {
+
+ // set stop bit on last line
+ SET_BIT(line->bits, IS_STOP);
+
+ // clear text
+ (text->reset)(text);
+
// if text is markdown hr
} else if(CHECK_BIT(bits, IS_HR) &&
CHECK_BIT(line->bits, IS_EMPTY)) {
line->offset = next_nonblank(text, 0);
// adjust line length dynamicaly - excluding markup
- if(line->text->text)
+ if(line->text->value)
adjust_line_length(line);
// new text
text = cstring_init();
}
- } else if(c == '\t') {
+ } else if(c == L'\t') {
// expand tab to spaces
for (i = 0; i < EXPAND_TABS; i++) {
- (text->expand)(text, ' ');
+ (text->expand)(text, L' ');
}
- } else if(c == '\\') {
+ } else if(c == L'\\') {
// add char to line
(text->expand)(text, c);
// and do not increase line count
if(next_nonblank(text, 0) < CODE_INDENT) {
- c = fgetc(input);
+ c = fgetwc(input);
(text->expand)(text, c);
-
- if(is_utf8(c)) {
-
- // if utf-8 char > 1 byte add remaing to line
- for(i = 0; i < length_utf8(c) - 1; i++) {
- c = fgetc(input);
- (text->expand)(text, c);
- }
- }
-
}
- } else if(isprint(c) || isspace((unsigned char) c)) {
+ } else if(iswprint(c) || iswspace(c)) {
// add char to line
(text->expand)(text, c);
-
- } else if(is_utf8(c)) {
-
- // add char to line
- (text->expand)(text, c);
-
- // if utf-8 char > 1 byte add remaing to line
- for(i = 0; i < length_utf8(c) - 1; i++) {
- c = fgetc(input);
- (text->expand)(text, c);
- }
}
}
(text->delete)(text);
// detect header
line = deck->slide->line;
- if(line && line->text->size > 0 && line->text->text[0] == '%') {
+ if(line && line->text->size > 0 && line->text->value[0] == L'%') {
// assign header to deck
deck->header = line;
// find first non-header line
- while(line && line->text->size > 0 && line->text->text[0] == '%') {
+ while(line && line->text->size > 0 && line->text->value[0] == L'%') {
hc++;
line = line->next;
}
const int unordered_list_offset = unordered_list_level_offset[unordered_list_level];
// return IS_EMPTY on null pointers
- if(!text || !text->text) {
+ if(!text || !text->value) {
SET_BIT(bits, IS_EMPTY);
return bits;
}
// count leading spaces
offset = next_nonblank(text, 0);
+ // IS_STOP
+ if((offset < CODE_INDENT || !CHECK_BIT(prev, IS_CODE)) &&
+ (!wcsncmp(&text->value[offset], L"<br>", 4) ||
+ !wcsncmp(&text->value[offset], L"<BR>", 4) ||
+ !wcsncmp(&text->value[offset], L"^", 1))) {
+ SET_BIT(bits, IS_STOP);
+ return bits;
+ }
+
// strip trailing spaces
- for(eol = text->size; eol > offset && isspace((unsigned char) text->text[eol - 1]); eol--);
+ for(eol = text->size; eol > offset && iswspace(text->value[eol - 1]); eol--);
// IS_UNORDERED_LIST_#
if(text->size >= offset + 2 &&
- (text->text[offset] == '*' || text->text[offset] == '-') &&
- text->text[offset + 1] == ' ') {
+ (text->value[offset] == L'*' || text->value[offset] == L'-') &&
+ iswspace(text->value[offset + 1])) {
// if different from last lines offset
if(offset != unordered_list_offset) {
// IS_CODE
if(offset >= CODE_INDENT &&
(CHECK_BIT(prev, IS_EMPTY) ||
- CHECK_BIT(prev, IS_CODE))) {
+ CHECK_BIT(prev, IS_CODE) ||
+ CHECK_BIT(prev, IS_STOP))) {
SET_BIT(bits, IS_CODE);
} else {
// IS_QUOTE
- if(text->text[offset] == '>') {
+ if(text->value[offset] == L'>') {
SET_BIT(bits, IS_QUOTE);
}
// IS_CENTER
if(text->size >= offset + 3 &&
- text->text[offset] == '-' &&
- text->text[offset + 1] == '>' &&
- text->text[offset + 2] == ' ') {
+ text->value[offset] == L'-' &&
+ text->value[offset + 1] == L'>' &&
+ iswspace(text->value[offset + 2])) {
SET_BIT(bits, IS_CENTER);
// remove start tag
eol -= 3;
if(text->size >= offset + 3 &&
- text->text[eol - 1] == '-' &&
- text->text[eol - 2] == '<' &&
- text->text[eol - 3] == ' ') {
+ text->value[eol - 1] == L'-' &&
+ text->value[eol - 2] == L'<' &&
+ iswspace(text->value[eol - 3])) {
// remove end tags
(text->strip)(text, eol - 3, 3);
// adjust end of line
- for(eol = text->size; eol > offset && isspace((unsigned char) text->text[eol - 1]); eol--);
+ for(eol = text->size; eol > offset && iswspace(text->value[eol - 1]); eol--);
}
}
for(i = offset; i < eol; i++) {
- if(text->text[i] == ' ') {
+ if(iswspace(text->value[i])) {
spaces++;
} else {
- switch(text->text[i]) {
- case '=': equals++; break;
- case '#': hashes++; break;
- case '*': stars++; break;
- case '-': minus++; break;
- case '\\': other++; i++; break;
+ switch(text->value[i]) {
+ case L'=': equals++; break;
+ case L'#': hashes++; break;
+ case L'*': stars++; break;
+ case L'-': minus++; break;
+ case L'\\': other++; i++; break;
default: other++; break;
}
}
// IS_H1
if(equals > 0 &&
- hashes + stars + minus + spaces + other == 0) {
+ hashes + stars + minus + spaces + other == 0) {
SET_BIT(bits, IS_H1);
}
- if(text->text[offset] == '#' &&
- text->text[offset+1] == ' ') {
+ if(text->value[offset] == L'#' &&
+ iswspace(text->value[offset+1])) {
SET_BIT(bits, IS_H1);
SET_BIT(bits, IS_H1_ATX);
}
// IS_H2
if(minus > 0 &&
- equals + hashes + stars + spaces + other == 0) {
+ equals + hashes + stars + spaces + other == 0) {
SET_BIT(bits, IS_H2);
}
- if(text->text[offset] == '#' &&
- text->text[offset+1] == '#' &&
- text->text[offset+2] == ' ') {
+ if(text->value[offset] == L'#' &&
+ text->value[offset+1] == L'#' &&
+ iswspace(text->value[offset+2])) {
SET_BIT(bits, IS_H2);
SET_BIT(bits, IS_H2_ATX);
}
line_t *header;
if(debug == 1) {
- fprintf(stderr, "headers: %i\nslides: %i\n", deck->headers, deck->slides);
+ fwprintf(stderr, L"headers: %i\nslides: %i\n", deck->headers, deck->slides);
} else if(debug > 1) {
header = deck->header;
while(header &&
header->length > 0 &&
- header->text->text[0] == '%') {
+ header->text->value[0] == L'%') {
// skip descriptor word (e.g. %title:)
offset = next_blank(header->text, 0) + 1;
- fprintf(stderr, "header: %s\n", &header->text->text[offset]);
+ fwprintf(stderr, L"header: %S\n", &header->text->value[offset]);
header = header->next;
}
}
sc++;
if(debug == 1) {
- fprintf(stderr, " slide %i: %i lines\n", sc, slide->lines);
+ fwprintf(stderr, L" slide %i: %i lines\n", sc, slide->lines);
} else if(debug > 1) {
// also print bits and line length
- fprintf(stderr, " slide %i:\n", sc);
+ fwprintf(stderr, L" slide %i:\n", sc);
line = slide->line;
lc = 0;
while(line) {
lc++;
- fprintf(stderr, " line %i: bits = %i, length = %i\n", lc, line->bits, line->length);
+ fwprintf(stderr, L" line %i: bits = %i, length = %i\n", lc, line->bits, line->length);
line = line->next;
}
}
void adjust_line_length(line_t *line) {
int l = 0;
- const static char *special = "\\*_`"; // list of interpreted chars
- const char *c = &line->text->text[line->offset];
+ const static wchar_t *special = L"\\*_`"; // list of interpreted chars
+ const wchar_t *c = &line->text->value[line->offset];
cstack_t *stack = cstack_init();
// for each char in line
for(; *c; c++) {
// if char is in special char list
- if(strchr(special, *c)) {
+ if(wcschr(special, *c)) {
// closing special char (or second backslash)
if((stack->top)(stack, *c)) {
- if(*c == '\\') l++;
+ if(*c == L'\\') l++;
(stack->pop)(stack);
// treat special as regular char
- } else if((stack->top)(stack, '\\')) {
+ } else if((stack->top)(stack, L'\\')) {
l++;
(stack->pop)(stack);
} else {
// remove backslash from stack
- if((stack->top)(stack, '\\'))
+ if((stack->top)(stack, L'\\'))
(stack->pop)(stack);
l++;
}
(stack->delete)(stack);
}
-bool is_utf8(char ch) {
- return (ch & 0x80) != 0x00;
-}
-
-int length_utf8(char ch) {
-
- int i = 0; // increment
-
- while(is_utf8(ch)) {
- i++;
- ch <<= 1;
- }
-
- return i;
-}
-
int next_nonblank(cstring_t *text, int i) {
- while ((i < text->size) && isspace((unsigned char) (text->text)[i]))
+ while ((i < text->size) && iswspace((text->value)[i]))
i++;
return i;
}
int prev_blank(cstring_t *text, int i) {
- while ((i > 0) && !isspace((unsigned char) (text->text)[i]))
+ while ((i > 0) && !iswspace((text->value)[i]))
i--;
return i;
}
int next_blank(cstring_t *text, int i) {
- while ((i < text->size) && !isspace((unsigned char) (text->text)[i]))
+ while ((i < text->size) && !iswspace((text->value)[i]))
i++;
return i;
#include <stdlib.h>
#include <assert.h>
-#include <string.h>
+#include <wchar.h>
#include <stdio.h>
#include "url.h"
init_ok = 1;
}
-int url_add(const char *link_name, int link_name_length, const char *target, int target_length, int x, int y) {
+int url_add(const wchar_t *link_name, int link_name_length, const wchar_t *target, int target_length, int x, int y) {
if (!init_ok) return -1;
url_t *tmp = NULL;
assert(tmp);
}
- tmp -> link_name = calloc(link_name_length+1, sizeof(char));
+ tmp -> link_name = calloc(link_name_length+1, sizeof(wchar_t));
assert(tmp->link_name);
- strncpy(tmp->link_name, link_name, link_name_length);
+ wcsncpy(tmp->link_name, link_name, link_name_length);
tmp->link_name[link_name_length] = '\0';
- tmp->target = calloc(target_length+1, sizeof(char));
+ tmp->target = calloc(target_length+1, sizeof(wchar_t));
assert(tmp->target);
- strncpy(tmp->target, target, target_length);
+ wcsncpy(tmp->target, target, target_length);
tmp->target[target_length] = '\0';
tmp->x = x;
return index_max-1;
}
-char * url_get_target(int index) {
+wchar_t * url_get_target(int index) {
if (!init_ok) return NULL;
url_t *tmp = list;
} else return NULL;
}
-char * url_get_name(int index) {
+wchar_t * url_get_name(int index) {
url_t *tmp = list;
while (index > 0 && tmp && tmp->next) {
return index_max;
}
-int url_count_inline(const char *line) {
+int url_count_inline(const wchar_t *line) {
int count = 0;
- const char *i = line;
+ const wchar_t *i = line;
for (; *i; i++) {
if (*i == '\\') {
} else if ( *i == '[' && *(i+1) != ']') {
while (*i && *i != ']') i++;
i++;
- if (*i == '(' && strchr(i, ')')) {
+ if (*i == '(' && wcschr(i, ')')) {
count ++;
- i = strchr(i, ')');
+ i = wcschr(i, ')');
}
}
}
return count;
}
-int url_len_inline(const char *text) {
+int url_len_inline(const wchar_t *value) {
int count = 0;
- const char *i = text;
+ const wchar_t *i = value;
for (; *i; i++) {
if (*i == '\\') {
} else if ( *i == '[' && *(i+1) != ']') {
while (*i && *i != ']') i++;
i++;
- if (*i == '(' && strchr(i, ')')) {
+ if (*i == '(' && wcschr(i, ')')) {
while (*i && *i != ')') {
count++;
i++;
*/
#include <ctype.h> // isalnum
-#include <locale.h> // setlocale
-#include <string.h> // strchr
+#include <wchar.h> // wcschr
+#include <wctype.h> // iswalnum
+#include <string.h> // strcpy
#include <unistd.h> // usleep
-
#include "viewer.h"
// color ramp for fading from black to color
int max_lines = 0; // max lines per slide
int max_cols = 0; // max columns per line
int offset; // text offset
+ int stop = 0; // passed stop bits per slide
// header line 1 is displayed at the top
int bar_top = (deck->headers > 0) ? 1 : 0;
slide_t *slide = deck->slide;
line_t *line;
- // set locale to display UTF-8 correctly in ncurses
- setlocale(LC_CTYPE, "");
-
// init ncurses
initscr();
while(line && line->text) {
- if (line->text->text)
- lc += url_count_inline(line->text->text);
+ if (line->text->value)
+ lc += url_count_inline(line->text->value);
- if (line->text->text)
- line->length -= url_len_inline(line->text->text);
+ if (line->text->value)
+ line->length -= url_len_inline(line->text->value);
if(line->length > COLS) {
i = line->length;
endwin();
// print error
- 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");
+ fwprintf(stderr, L"Error: Terminal width (%i columns) too small. Need at least %i columns.\n", COLS, i);
+ fwprintf(stderr, L"You may need to shorten some lines by inserting line breaks.\n");
// no reload
return 0;
endwin();
// 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");
+ fwprintf(stderr, L"Error: Terminal height (%i lines) too small. Need at least %i lines.\n", LINES, max_lines + bar_top + bar_bottom);
+ fwprintf(stderr, L"You may need to add additional horizontal rules (---) to split your file in shorter slides.\n");
// no reload
return 0;
line = deck->header;
offset = next_blank(line->text, 0) + 1;
// add text to header
- mvwprintw(stdscr,
- 0, (COLS - line->length + offset) / 2,
- "%s", &line->text->text[offset]);
+ mvwaddwstr(stdscr,
+ 0, (COLS - line->length + offset) / 2,
+ &line->text->value[offset]);
}
// setup footer
line = deck->header->next;
offset = next_blank(line->text, 0) + 1;
// add text to left footer
- mvwprintw(stdscr,
- LINES - 1, 3,
- "%s", &line->text->text[offset]);
+ mvwaddwstr(stdscr,
+ LINES - 1, 3,
+ &line->text->value[offset]);
}
+
// add slide number to right footer
mvwprintw(stdscr,
LINES - 1, COLS - int_length(deck->slides) - int_length(sc) - 6,
wrefresh(stdscr);
line = slide->line;
- l = 0;
+ l = stop = 0;
// print lines
while(line) {
add_line(content, l, (COLS - max_cols) / 2, line, max_cols, colors);
+
+ // raise stop counter if we pass a line having a stop bit
+ if(CHECK_BIT(line->bits, IS_STOP))
+ stop++;
+
l += (line->length / COLS) + 1;
line = line->next;
+
+ // only stop here if we didn't stop here recently
+ if(stop > slide->stop)
+ break;
}
- 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));
+ // print pandoc URL references
+ // only if we already printed all lines of the current slide
+ if(!line) {
+ 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] ", i);
+ waddwstr(content, url_get_target(i));
+ }
}
// make content visible
i = 0;
switch(c) {
- // show previous slide
+ // show previous slide or stop bit
case KEY_UP:
case KEY_LEFT:
case KEY_PPAGE:
case 263: // BACKSPACE (getty)
case 'h':
case 'k':
- if(slide->prev) {
- slide = slide->prev;
- sc--;
+ if(stop > 1 || (stop == 1 && !line)) {
+ // show current slide again
+ // but stop one stop bit earlier
+ slide->stop--;
} else {
- fade = false;
+ if(slide->prev) {
+ // show previous slide
+ slide = slide->prev;
+ sc--;
+ } else {
+ // do nothing
+ fade = false;
+ }
}
break;
- // show next slide
+ // show next slide or stop bit
case KEY_DOWN:
case KEY_RIGHT:
case KEY_NPAGE:
case ' ': // SPACE
case 'j':
case 'l':
- if(slide->next) {
- slide = slide->next;
- sc++;
+ if(stop && line) {
+ // show current slide again
+ // but stop one stop bit later (or at end of slide)
+ slide->stop++;
} else {
- fade = false;
+ if(slide->next) {
+ // show next slide
+ slide = slide->next;
+ sc++;
+ } else {
+ // do nothing
+ fade = false;
+ }
}
break;
void add_line(WINDOW *window, int y, int x, line_t *line, int max_cols, int colors) {
- if(!line->text->text) {
+ if(!line->text->value) {
return;
}
"%s", prompt);
if(!CHECK_BIT(line->bits, IS_CODE))
- inline_display(window, &line->text->text[offset], colors);
+ inline_display(window, &line->text->value[offset], colors);
// IS_UNORDERED_LIST_2
} else if(CHECK_BIT(line->bits, IS_UNORDERED_LIST_2)) {
"%s", prompt);
if(!CHECK_BIT(line->bits, IS_CODE))
- inline_display(window, &line->text->text[offset], colors);
+ inline_display(window, &line->text->value[offset], colors);
// IS_UNORDERED_LIST_1
} else if(CHECK_BIT(line->bits, IS_UNORDERED_LIST_1)) {
"%s", prompt);
if(!CHECK_BIT(line->bits, IS_CODE))
- inline_display(window, &line->text->text[offset], colors);
+ inline_display(window, &line->text->value[offset], colors);
}
// IS_CODE
wattron(window, COLOR_PAIR(CP_BLACK));
// print whole lines
- wprintw(window,
- "%s", &line->text->text[offset]);
+ waddwstr(window, &line->text->value[offset]);
}
if(!CHECK_BIT(line->bits, IS_UNORDERED_LIST_1) &&
// IS_QUOTE
if(CHECK_BIT(line->bits, IS_QUOTE)) {
- while(line->text->text[offset] == '>') {
+ while(line->text->value[offset] == '>') {
// print a reverse color block
if(colors) {
wattron(window, COLOR_PAIR(CP_BLACK));
// find next quote or break
offset++;
- if(line->text->text[offset] == ' ')
+ if(line->text->value[offset] == ' ')
offset = next_word(line->text, offset);
}
- inline_display(window, &line->text->text[offset], colors);
+ inline_display(window, &line->text->value[offset], colors);
} else {
// IS_CENTER
wattron(window, A_UNDERLINE);
// skip hashes
- while(line->text->text[offset] == '#')
+ while(line->text->value[offset] == '#')
offset = next_word(line->text, offset);
// print whole lines
- wprintw(window,
- "%s", &line->text->text[offset]);
+ waddwstr(window, &line->text->value[offset]);
wattroff(window, A_UNDERLINE);
// no line-wide markdown
} else {
- inline_display(window, &line->text->text[offset], colors);
+ inline_display(window, &line->text->value[offset], colors);
}
}
}
wattroff(window, A_UNDERLINE);
}
-void inline_display(WINDOW *window, const char *c, const int colors) {
- const static char *special = "\\*_`!["; // list of interpreted chars
- const char *i = c; // iterator
- const char *start_link_name, *start_url;
+void inline_display(WINDOW *window, const wchar_t *c, const int colors) {
+ const static wchar_t *special = L"\\*_`!["; // list of interpreted chars
+ const wchar_t *i = c; // iterator
+ const wchar_t *start_link_name, *start_url;
int length_link_name, url_num;
cstack_t *stack = cstack_init();
for(; *i; i++) {
// if char is in special char list
- if(strchr(special, *i)) {
+ if(wcschr(special, *i)) {
// closing special char (or second backslash)
// only if not followed by :alnum:
if((stack->top)(stack, *i) &&
- (!isalnum((int)i[1]) || *(i + 1) == '\0' || *i == '\\')) {
+ (!iswalnum(i[1]) || *(i + 1) == L'\0' || *i == L'\\')) {
switch(*i) {
// print escaped backslash
- case '\\':
- wprintw(window, "%c", *i);
+ case L'\\':
+ waddnwstr(window, i, 1);
break;
// disable highlight
- case '*':
+ case L'*':
if(colors)
wattron(window, COLOR_PAIR(CP_WHITE));
break;
// disable underline
- case '_':
+ case L'_':
wattroff(window, A_UNDERLINE);
break;
// disable inline code
- case '`':
+ case L'`':
if(colors)
wattron(window, COLOR_PAIR(CP_WHITE));
break;
(stack->pop)(stack);
// treat special as regular char
- } else if((stack->top)(stack, '\\')) {
- wprintw(window, "%c", *i);
+ } else if((stack->top)(stack, L'\\')) {
+ waddnwstr(window, i, 1);
// remove backslash from stack
(stack->pop)(stack);
// and of cause after another emphasis markup
//TODO this condition looks ugly
if(i == c ||
- *(i - 1) == ' ' ||
- ((*(i - 1) == '_' || *(i - 1) == '*') && ((i - 1) == c || *(i - 2) == ' ')) ||
- *i == '\\') {
+ iswspace(*(i - 1)) ||
+ ((iswspace(*(i - 1)) || *(i - 1) == L'*' || *(i - 1) == L'_') &&
+ ((i - 1) == c || iswspace(*(i - 2)))) ||
+ *i == L'\\') {
// url in pandoc style
- if ((*i == '[' && strchr(i, ']')) ||
- (*i == '!' && *(i + 1) == '[' && strchr(i, ']'))) {
+ if ((*i == L'[' && wcschr(i, L']')) ||
+ (*i == L'!' && *(i + 1) == L'[' && wcschr(i, L']'))) {
- if (*i == '!') i++;
+ if (*i == L'!') i++;
- if (strchr(i, ']')[1] == '(') {
+ if (wcschr(i, L']')[1] == L'(') {
i++;
// turn higlighting and underlining on
// print the content of the label
// the label is printed as is
do {
- wprintw(window, "%c", *i);
+ waddnwstr(window, i, 1);
i++;
- } while (*i != ']');
+ } while (*i != L']');
length_link_name = i - 1 - start_link_name;
start_url = i;
- while (*i != ')') i++;
+ while (*i != L')') i++;
- url_num = url_add(start_link_name, length_link_name, start_url, i - start_url, 0,0);
+ url_num = url_add(start_link_name, length_link_name, start_url, i - start_url, 0, 0);
wprintw(window, " [%d]", url_num);
} else switch(*i) {
// enable highlight
- case '*':
+ case L'*':
if(colors)
wattron(window, COLOR_PAIR(CP_RED));
break;
// enable underline
- case '_':
+ case L'_':
wattron(window, A_UNDERLINE);
break;
// enable inline code
- case '`':
+ case L'`':
if(colors)
wattron(window, COLOR_PAIR(CP_BLACK));
break;
(stack->push)(stack, *i);
} else {
- wprintw(window, "%c", *i);
+ waddnwstr(window, i, 1);
}
}
} else {
// remove backslash from stack
- if((stack->top)(stack, '\\'))
+ if((stack->top)(stack, L'\\'))
(stack->pop)(stack);
// print regular char
- wprintw(window, "%c", *i);
+ waddnwstr(window, i, 1);
}
}
while(!(stack->empty)(stack)) {
switch((stack->pop)(stack)) {
// disable highlight
- case '*':
+ case L'*':
if(colors)
wattron(window, COLOR_PAIR(CP_WHITE));
break;
// disable underline
- case '_':
+ case L'_':
wattroff(window, A_UNDERLINE);
break;
// disable inline code
- case '`':
+ case L'`':
if(colors)
wattron(window, COLOR_PAIR(CP_WHITE));
break;
--- /dev/null
+%title: UTF-8 Test Presentation
+
+_Tables:_
+
+┍━━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━━━┑
+│ Cell 1 │ Cell 2 │ Cell 3 │ Cell 4 │
+├──────────┼──────────┼──────────┼──────────┤
+│ Cell 5 │ Cell 6 │ Cell 7 │ Cell 8 │
+┕━━━━━━━━━━┷━━━━━━━━━━┷━━━━━━━━━━┷━━━━━━━━━━┙
+
+---
+
+_Greek:_
+
+Apò mēkhanês Theós
+
+ἀπὸ μηχανῆς Θεός
+
+---
+
+_Chinese:_
+
+bù zuō sǐ jiù bú huì sǐ
+
+不作死就不会死
+
+---
+
+_Japanese:_
+
+Saru mo ki kara ochiru
+
+猿も木から落ちる。
+
+---
+
+_ASCII art:_
+
+ ██████████████
+ ██▓▓▓▓▓▓▓▓▓ M ▓████
+ ██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██
+ ██████░░░░██░░██████
+ ██░░░░████░░██░░░░░░░░██
+ ██░░░░████░░░░██░░░░░░██
+ ████░░░░░░██████████
+ ██░░░░░░░░░░░░░██
+ ██░░░░░░░░░██
+ ██░░░░░░██
+ ██▓▓████▓▓▓█
+ ██▓▓▓▓▓▓████▓▓█
+ ██▓▓▓▓▓▓███░░███░
+ ██░░░░░░███████
+ ██░░░░███████
+ ██████████
+ ██▓▓▓▓▓▓▓▓▓██
+ █████████████
+