diff --git a/src/template.c b/src/template.c
index 160b8ce..62e639b 100644
--- a/src/template.c
+++ b/src/template.c
@@ -37,6 +37,16 @@ enum paratype {
HL
};
+static const struct {
+ char c;
+ char *escape;
+} escapes[] = {
+ {'&', "&"},
+ {';', ";"},
+ {'<', "<"},
+ {'>', ">"},
+};
+
static int parsepara(struct linefile *infile, FILE *outfile);
static enum paratype identifypara(char *line, char **contentret);
@@ -53,6 +63,16 @@ static int parahardcase(struct linefile *infile, FILE *outfile,
static int paracodecase(struct linefile *infile, FILE *outfile,
char *line, char *buff,
char *vars, enum paratype type);
+static long strsearch(char *data, long start, size_t datalen, char c, int reps);
+/* strsearch finds instances in data with reps repetitions of c. returns the
+ * last instance in the first group. For example:
+ *
+ * c = '.', reps = 2, data = " ...", returns 2
+ * c = '.', reps = 2, data = ".. ...", returns 4
+ * c = '.', reps = 1, data = " ...", returns 3
+ * */
+static int writedata(char *data, size_t len, FILE *outfile);
+static int writesimple(char *data, size_t len, FILE *outfile);
static void ungetline(struct linefile *file, char *line);
static char *getline(struct linefile *file);
@@ -217,7 +237,7 @@ static int paraeasycase(struct linefile *infile, FILE *outfile,
fprintf(outfile, "<%s>", tag);
for (;;) {
- fwrite(buff, sizeof(*buff), writelen, outfile);
+ writedata(buff, writelen, outfile);
free(line);
line = getline(infile);
if (line == NULL)
@@ -250,7 +270,7 @@ static int parahardcase(struct linefile *infile, FILE *outfile,
if (linetag != NULL)
fprintf(outfile, "<%s>", linetag);
- fwrite(buff, sizeof(*buff), writelen, outfile);
+ writedata(buff, writelen, outfile);
if (islinebreak(line))
fputs("
", outfile);
if (linetag != NULL)
@@ -301,7 +321,7 @@ static int paracodecase(struct linefile *infile, FILE *outfile,
}
if (newtype != CODEBACK)
- fputs(buff, outfile);
+ writesimple(buff, -1, outfile);
free(line);
line = getline(infile);
@@ -323,6 +343,113 @@ static int paracodecase(struct linefile *infile, FILE *outfile,
return 0;
}
+static long strsearch(char *data, long start, size_t datalen,
+ char c, int reps) {
+ long i;
+
+ for (i = start; data[i] == c; ++i) ;
+
+ while (i + reps - 1 < datalen) {
+ int j;
+ for (j = 0; j < reps; ++j)
+ if (data[i + j] != c)
+ goto failure;
+ goto success;
+ continue;
+failure:
+ ++i;
+ }
+ return -1;
+
+success:
+ while (data[i + reps] == c && i + reps < datalen)
+ ++i;
+ return i;
+}
+
+/* TODO: Finish this */
+static int writedata(char *data, size_t len, FILE *outfile) {
+ long i;
+ long start;
+ long end;
+ for (i = 0; i < len; ++i) {
+ switch (data[i]) {
+#define STANDOUT_CHAR(c) \
+ case c: \
+ if (data[i + 1] == c) { \
+ start = i + 2; \
+ end = strsearch(data, start, len, \
+ c, 2); \
+ goto bold; \
+ } \
+ start = i + 1; \
+ end = strsearch(data, start, len, c, 1); \
+ goto italic;
+ STANDOUT_CHAR('*');
+ STANDOUT_CHAR('_');
+ italic:
+ if (end < 0) {
+ putchar(data[i]);
+ break;
+ }
+ fputs("", outfile);
+ writedata(data + start, end - start, outfile);
+ fputs("", outfile);
+ i = end;
+ break;
+ bold:
+ if (end < 0) {
+ putchar(data[i]);
+ break;
+ }
+ fputs("", outfile);
+ writedata(data + start, end - start, outfile);
+ fputs("", outfile);
+ i = end + 1;
+ break;
+
+ case '`':
+ end = strsearch(data, i, len, '`', 1);
+ if (end < 0)
+ break;
+ fputs("", outfile);
+ writedata(data + i, end - i, outfile);
+ fputs("", outfile);
+ i = end;
+ break;
+ default: {
+ int j;
+ for (j = 0; j < sizeof escapes / sizeof *escapes; ++j) {
+ if (escapes[j].c == data[i]) {
+ fputs(escapes[j].escape, outfile);
+ goto end;
+ }
+ }
+ fputc(data[i], outfile);
+end:
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+static int writesimple(char *data, size_t len, FILE *outfile) {
+ long i;
+ for (i = 0; (len < 0 && data[i] != '\0') || i < len; ++i) {
+ int j;
+ for (j = 0; j < sizeof escapes / sizeof *escapes; ++j) {
+ if (escapes[j].c == data[i]) {
+ fputs(escapes[j].escape, outfile);
+ goto end;
+ }
+ }
+ fputc(data[i], outfile);
+end:;
+ }
+ return 0;
+}
+
static void ungetline(struct linefile *file, char *line) {
file->prevline = line;
}