aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--draw.c107
-rw-r--r--driver.c47
-rw-r--r--main.c63
-rw-r--r--sayeth.h22
5 files changed, 140 insertions, 101 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 673e65d..f80bc24 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@ if (MSVC)
add_compile_options(/W4 /WX)
else()
# lots of warnings and all warnings as errors
- add_compile_options(-Wall -Wextra -pedantic -Werror)
+ add_compile_options(-Wall -Wextra -pedantic)
endif()
add_executable(sayeth main.c driver.c draw.c)
diff --git a/draw.c b/draw.c
index 55c840f..d6a032b 100644
--- a/draw.c
+++ b/draw.c
@@ -2,20 +2,22 @@
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
+#include <wchar.h>
#include "sayeth.h"
size_t START_Y_BOX = 0;
size_t START_Y_CARET = 0;
size_t START_Y_DATA = 0;
-const char *A_TAB = " ";
-char wspace = ' ';
-char box_top_left = '\0';
-char box_top = '\0';
-char box_top_right = '\0';
-char box_side = '\0';
-char box_bottom_left = '\0';
-char box_bottom = '\0';
-char box_bottom_right = '\0';
+const wchar_t *A_TAB = L" ";
+wchar_t wspace = L' ';
+wchar_t box_top_left = L'\0';
+wchar_t box_top = L'\0';
+wchar_t box_top_right = L'\0';
+wchar_t box_side = L'\0';
+wchar_t box_bottom_left = L'\0';
+wchar_t box_bottom = L'\0';
+wchar_t box_bottom_right = L'\0';
+extern int do_fill;
void box_draw_top(size_t y, size_t longest) {
repchar(wspace, y);
@@ -41,20 +43,20 @@ void box_draw_end_line(size_t longest, size_t len) {
repchar(box_side, 1);
}
-int box_printf(const char *fmt, ...) {
+int box_printf(const wchar_t *fmt, ...) {
int count;
va_list list;
va_start(list, fmt);
size_t len = 0;
- char data[INPUT_BUFSIZ] = {0};
- char output[INPUT_BUFSIZ] = {0};
- count = vsnprintf(data, sizeof(data) - 1, fmt, list);
+ wchar_t data[INPUT_BUFSIZ] = {0};
+ wchar_t output[INPUT_BUFSIZ] = {0};
+ count = vswprintf(data, sizeof(data) - 1, fmt, list);
// convert tabs to spaces
- for (size_t i = 0, n = 0; i < strlen(data) && n < sizeof(output); i++, n++) {
- if (data[i] == '\t') {
- strcat(&output[n], A_TAB);
- n = n + strlen(A_TAB) - 1;
+ for (size_t i = 0, n = 0; i < wcslen(data) && n < sizeof(output); i++, n++) {
+ if (data[i] == L'\t') {
+ wcscat(&output[n], A_TAB);
+ n = n + wcslen(A_TAB) - 1;
continue;
}
output[n] = data[i];
@@ -63,10 +65,10 @@ int box_printf(const char *fmt, ...) {
size_t longest = get_longest_line(output);
box_draw_top(START_Y_BOX, longest);
- puts("");
+ wprintf(L"\n");
- for (size_t i = 0; i < strlen(output); i++) {
- if (i == strlen(output) - 1) {
+ for (size_t i = 0; i < wcslen(output); i++) {
+ if (i == wcslen(output) - 1) {
box_draw_end_line(longest, len);
continue;
}
@@ -77,36 +79,36 @@ int box_printf(const char *fmt, ...) {
if (output[i] == '\n') {
box_draw_end_line(longest, len);
- putc('\n', stdout);
+ putwc('\n', stdout);
len = 0;
continue;
}
- putc(output[i], stdout);
+ putwc(output[i], stdout);
len++;
}
- puts("");
+ wprintf(L"\n");
box_draw_bottom(START_Y_BOX, longest);
va_end(list);
return count;
}
-void caret_draw(char *data, size_t indent, size_t attached) {
- if (!strlen(data))
+void caret_draw(wchar_t *data, size_t indent, size_t attached) {
+ if (!wcslen(data))
return;
if (!attached)
repchar(wspace, START_Y_BOX);
- for (size_t i = 0; i < strlen(data); i++) {
- if (data[i] == '\\' && isalpha(data[i + 1])) {
+ for (size_t i = 0; i < wcslen(data); i++) {
+ if (data[i] == L'\\' && isalpha(data[i + 1])) {
i++;
switch (data[i]) {
case 'n':
- putc('\n', stdout);
- if (i == strlen(data) - 1)
+ putwc(L'\n', stdout);
+ if (i == wcslen(data) - 1)
continue;
repchar(wspace, indent);
continue;
@@ -114,25 +116,46 @@ void caret_draw(char *data, size_t indent, size_t attached) {
continue;
}
}
- putc(data[i], stdout);
+ putwc(data[i], stdout);
}
}
+size_t count_lines(wchar_t *s) {
+ size_t count = 0;
+ wchar_t *ptr = s;
-void data_draw(char *data, size_t indent) {
+ while (*ptr != L'\0') {
+ if (*ptr == L'\n')
+ count++;
+ ptr++;
+ }
+ return count;
+}
+
+void data_draw(wchar_t *data, size_t indent) {
size_t len = 0;
- for (size_t i = 0; i < strlen(data); i++) {
- if (len == 0) {
- repchar(wspace, indent);
+ wchar_t *inbuf = wcsdup(data);
+ size_t longest = get_longest_line(inbuf);
+ size_t lines = count_lines(inbuf);
+ wchar_t buf[DATA_BUFSIZ] = {0};
+
+ wchar_t *token = NULL;
+ wchar_t *ptr;
+ token = wcstok(inbuf, L"\n", &ptr);
+ for (size_t i = 0; token != NULL; i++) {
+ memset(buf, '\0', sizeof(buf));
+ for (size_t y = 0; y < indent; y++) {
+ buf[y] = wspace;
}
-
- if (data[i] == '\n') {
- putc('\n', stdout);
- len = 0;
- continue;
+ wcscat(buf, token);
+ len = wcslen(buf);
+ if (i < lines) {
+ for (size_t y = len; y < longest + (indent * 2); y++) {
+ buf[y] = wspace;
+ }
+ wcscat(buf, L"\n");
}
-
- putc(data[i], stdout);
- len++;
+ wprintf(L"%S", buf);
+ token = wcstok(NULL, L"\n", &ptr);
}
}
diff --git a/driver.c b/driver.c
index e308397..1e8b701 100644
--- a/driver.c
+++ b/driver.c
@@ -1,8 +1,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include "sayeth.h"
+extern int do_fill;
extern size_t START_Y_BOX;
extern size_t START_Y_CARET;
extern size_t START_Y_DATA;
@@ -35,52 +37,52 @@ struct Driver *driver_load(char *filename) {
}
for (size_t i = 0; i < 9; i++) {
- char buf[INPUT_BUFSIZ] = {0};
+ wchar_t buf[INPUT_BUFSIZ] = {0};
ssize_t lastpos = ftell(fp);
- if (fgets(buf, sizeof(buf) - 1, fp) == NULL) {
+ if (fgetws(buf, sizeof(buf) - 1, fp) == NULL) {
break;
}
- if (!strlen(buf) || buf[0] == '#') {
+ if (!wcslen(buf) || buf[0] == '#') {
i--;
continue;
}
- buf[strlen(buf) - 1] = '\0';
+ buf[wcslen(buf) - 1] = '\0';
switch (i) {
case 0:
- driver->name = strdup(buf);
+ driver->name = wcsdup(buf);
if (!driver->name) {
fclose(fp);
return NULL;
}
break;
case 1:
- driver->box_indent = strtol(buf, NULL, 10);
+ driver->box_indent = wcstol(buf, NULL, 10);
break;
case 2:
- driver->box_elements = strdup(buf);
+ driver->box_elements = wcsdup(buf);
if (!driver->box_elements) {
fclose(fp);
return NULL;
}
break;
case 3:
- driver->caret_pos = strtol(buf, NULL, 10);
+ driver->caret_pos = wcstol(buf, NULL, 10);
break;
case 4:
- driver->caret_indent = strtol(buf, NULL, 10);
+ driver->caret_indent = wcstol(buf, NULL, 10);
break;
case 5:
- driver->caret_attached = strtol(buf, NULL, 10);
+ driver->caret_attached = wcstol(buf, NULL, 10);
break;
case 6:
- driver->caret = strdup(buf);
+ driver->caret = wcsdup(buf);
if (!driver->caret) {
fclose(fp);
return NULL;
}
break;
case 7:
- driver->data_indent = strtol(buf, 0, 10);
+ driver->data_indent = wcstol(buf, 0, 10);
break;
case 8:
driver->data = calloc(DATA_BUFSIZ, sizeof(*driver->data));
@@ -88,9 +90,12 @@ struct Driver *driver_load(char *filename) {
fclose(fp);
return NULL;
}
- // rewind to beginning of the data section
fseek(fp, lastpos, SEEK_SET);
- fread(driver->data, 1, DATA_BUFSIZ - 1, fp);
+ wint_t c = 0;
+ size_t n = 0;
+ while ((c = fgetwc(fp)) != WEOF) {
+ driver->data[n++] = (wchar_t) c;
+ }
break;
default:
break;
@@ -129,7 +134,7 @@ int driver_register(struct Driver *driver) {
return 0;
}
-void drivers_free() {
+void drivers_free(void) {
for (size_t i = 0; i < drivers_alloc; i++) {
if (drivers[i]) {
if (drivers[i]->name)
@@ -145,8 +150,8 @@ void drivers_free() {
}
free(drivers);
}
-void driver_run(struct Driver *driver, char *input) {
- char *elem = driver->box_elements;
+void driver_run(struct Driver *driver, wchar_t *input) {
+ wchar_t *elem = driver->box_elements;
box_top_left = elem[0];
box_top = elem[1];
box_top_right = elem[2];
@@ -159,7 +164,7 @@ void driver_run(struct Driver *driver, char *input) {
START_Y_DATA = driver->data_indent;
if (!driver->caret_pos) {
- box_printf("%s", input);
+ box_printf(L"%S", input);
caret_draw(driver->caret, START_Y_CARET, driver->caret_attached);
}
@@ -169,13 +174,13 @@ void driver_run(struct Driver *driver, char *input) {
if (driver->caret_pos) {
caret_draw(driver->caret, START_Y_CARET, driver->caret_attached);
- box_printf("%s", input);
+ box_printf(L"%S", input);
}
}
-struct Driver *driver_lookup(char *name) {
+struct Driver *driver_lookup(wchar_t *name) {
for (size_t i = 0; drivers[i] != NULL; i++) {
- if (!strcmp(drivers[i]->name, name)) {
+ if (!wcscmp(drivers[i]->name, name)) {
return drivers[i];
}
}
diff --git a/main.c b/main.c
index ada0c16..7078e72 100644
--- a/main.c
+++ b/main.c
@@ -5,9 +5,12 @@
#include <dirent.h>
#include <errno.h>
#include <limits.h>
+#include <wchar.h>
+#include <locale.h>
#include "config.h"
#include "sayeth.h"
+int do_fill = 1;
extern char wspace;
extern struct Driver **drivers;
extern size_t drivers_alloc;
@@ -18,9 +21,9 @@ extern size_t drivers_used;
* @param ch character to repeat
* @param limit number of times to repeat
*/
-void repchar(char ch, size_t limit) {
+void repchar(wchar_t ch, size_t limit) {
while (limit > 0) {
- putc(ch, stdout);
+ putwc(ch, stdout);
limit--;
}
}
@@ -30,34 +33,30 @@ void repchar(char ch, size_t limit) {
* @param s the string
* @return longest line
*/
-size_t get_longest_line(char *s) {
+size_t get_longest_line(wchar_t *s) {
size_t *lengths;
- size_t len;
- size_t linecount;
+ size_t linecount = 0;
size_t longest;
- char *ch = s;
+ wchar_t *ch = s;
+ wchar_t *buf = wcsdup(s);
- linecount = 0;
- while (*ch != '\0') {
- if (*ch == '\n')
- linecount++;
- ch++;
- }
+ wchar_t *token = NULL;
+ wchar_t *ptr;
+ token = wcstok(buf, L"\n", &ptr);
+ if (token) linecount++;
+ for (; (token = wcstok(NULL, L"\n", &ptr)) != NULL; linecount++);
+ wcscpy(buf, s);
lengths = calloc(linecount + 1, sizeof(*lengths));
if (!lengths) {
return ULONG_MAX;
}
- len = 0;
- for (size_t i = 0, line = 0; i < strlen(s); i++) {
- if (s[i] == '\n') {
- lengths[line] = len;
- line++;
- len = 0;
- continue;
- }
- len++;
+ token = wcstok(buf, L"\n", &ptr);
+ for (size_t i = 0; token != NULL; i++) {
+ size_t len = wcslen(token);
+ lengths[i] = len;
+ token = wcstok(NULL, L"\n", &ptr);
}
longest = lengths[0];
@@ -67,6 +66,7 @@ size_t get_longest_line(char *s) {
}
}
free(lengths);
+ free(buf);
return longest;
}
@@ -82,8 +82,9 @@ void usage(char *prog) {
}
int main(int argc, char *argv[]) {
- char driver_name[255] = {0};
- char input[INPUT_BUFSIZ] = {0};
+ setlocale(LC_ALL, "");
+ char *driver_name = calloc(255, sizeof(*driver_name));
+ char *input = calloc(INPUT_BUFSIZ, sizeof(*input));
struct Driver *driver = NULL;
char *driver_dir = getenv("SAYETH_DRIVERS");
if (!driver_dir) {
@@ -176,14 +177,24 @@ int main(int argc, char *argv[]) {
input[strlen(input)] = '\n';
}
- driver = driver_lookup(driver_name);
+ size_t reqsize = 0;
+ wchar_t wdriver_name[INPUT_BUFSIZ] = {0};
+ wchar_t winput[INPUT_BUFSIZ] = {0};
+ mbstate_t mbs;
+ memset(&mbs, 0, sizeof(mbs));
+ mbsrtowcs(wdriver_name, &driver_name, 255 - 1, &mbs);
+ mbsrtowcs(winput, &input, INPUT_BUFSIZ - 1, &mbs);
+ //reqsize = wcstombs(input, NULL, 0);
+ //wcstombs(input, winput, reqsize);
+
+ driver = driver_lookup(wdriver_name);
if (!driver) {
fprintf(stderr, "Driver not found\n");
exit(1);
}
- driver_run(driver, input);
- puts("");
+ driver_run(driver, winput);
+ wprintf(L"\n");
drivers_free();
free(driver_dir);
return 0;
diff --git a/sayeth.h b/sayeth.h
index dea73c9..c3d84c7 100644
--- a/sayeth.h
+++ b/sayeth.h
@@ -12,9 +12,9 @@
#define DRIVERS_ALLOC_DEFAULT 128
struct Driver {
- char *name; // Driver name (passed to '-d' argument)
+ wchar_t *name; // Driver name (passed to '-d' argument)
size_t box_indent; // Shift box n columns to the right
- char *box_elements; // Border characters
+ wchar_t *box_elements; // Border characters
// top left, top, top right, sides, bottom left, bottom, bottom right
// e.g. "/-\|\-/'
/*
@@ -25,7 +25,7 @@ struct Driver {
size_t caret_pos; // Above or below the box
size_t caret_indent; // Shift caret n columns to the right
size_t caret_attached; // Inject a new line *after* art data, or not?
- char *caret; // Caret characters
+ wchar_t *caret; // Caret characters
// e.g. "\n \ |\n \ |\n \|\n"
/*
* \ |
@@ -33,24 +33,24 @@ struct Driver {
* \|
*/
size_t data_indent; // Shift art data n columns to the right
- char *data; // Art data (up to size: DATA_BUFSIZ - 1)
+ wchar_t *data; // Art data (up to size: DATA_BUFSIZ - 1)
};
-void repchar(char ch, size_t limit);
-size_t get_longest_line(char *s);
+void repchar(wchar_t ch, size_t limit);
+size_t get_longest_line(wchar_t *s);
struct Driver *driver_load(char *filename);
-struct Driver *driver_lookup(char *name);
+struct Driver *driver_lookup(wchar_t *name);
int driver_register(struct Driver *driver);
-void driver_run(struct Driver *driver, char *input);
+void driver_run(struct Driver *driver, wchar_t *input);
void drivers_free(void);
void box_draw_top(size_t y, size_t longest);
void box_draw_bottom(size_t y, size_t longest);
void box_draw_next_line(size_t y);
void box_draw_end_line(size_t longest, size_t len);
-int box_printf(const char *fmt, ...);
+int box_printf(const wchar_t *fmt, ...);
-void caret_draw(char *data, size_t indent, size_t attached);
-void data_draw(char *data, size_t indent);
+void caret_draw(wchar_t *data, size_t indent, size_t attached);
+void data_draw(wchar_t *data, size_t indent);
#endif //SAYETH_SAYETH_H