1 /*
2 * inline.c:
3 * In-line markup.
4 *
5 * - URLs are turned into links
6 *
7 * - ___ text ___ URL is turned into a link with the given text
8 *
9 * - ||| URL alt-text ||| is turned into an <img> tag with the given
10 * alt-text
11 *
12 * - *** strong ***
13 *
14 * - /// emphasis ///
15 *
16 * - ### cite ###
17 *
18 * - <>&" are turned into the appropriate HTML escapes.
19 *
20 * - \\\ is turned into <br>
21 *
22 * Copyright (c) 2003 Chris Lightfoot. All rights reserved.
23 * Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
24 *
25 */
26
27 static const char rcsid[] = "$Id: inline.c,v 1.3 2003/06/01 11:39:44 chris Exp $";
28
29 #include <assert.h>
30
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "htmlise.h"
35
inline_markup_words(FILE * fp,char ** words,const size_t nwords)36 static void inline_markup_words(FILE *fp, char **words, const size_t nwords) {
37 size_t i;
38 int in_strong = 0, in_em = 0, in_cite = 0;
39
40 /* Go through words applying markup. XXX may generate overlapping tags. */
41 for (i = 0; i < nwords; ++i) {
42 size_t j;
43
44 if (!*words[i])
45 continue;
46 if (strcmp(words[i], "\\\\\\") == 0)
47 fprintf(fp, "<br>");
48 else if (strcmp(words[i], "***") == 0) {
49 if (in_strong)
50 fprintf(fp, "</strong>");
51 else
52 fprintf(fp, "<strong>");
53 in_strong = !in_strong;
54 } else if (strcmp(words[i], "///") == 0) {
55 if (in_em)
56 fprintf(fp, "</em>");
57 else
58 fprintf(fp, "<em>");
59 in_em = !in_em;
60 } else if (strcmp(words[i], "###") == 0) {
61 if (in_cite)
62 fprintf(fp, "</cite>");
63 else
64 fprintf(fp, "<cite>");
65 in_cite = !in_cite;
66 } else if (strcmp(words[i], "|||") == 0) {
67 /* Image. Can't have markup inside the alt text. */
68 for (j = i + 1; j < nwords && strcmp(words[j], "|||") != 0; ++j);
69 if (j < nwords) {
70 fprintf(fp, "<img src=\"%s\" alt=\"", words[i + 1]);
71 i += 2;
72 while (i < j) {
73 fprintf(fp, "%s%s", words[i], i < j ? " " : "");
74 ++i;
75 }
76 /* ++i;*/
77 fprintf(fp, "\">");
78 }
79 } else if (strncmp(words[i], "http://", 7) == 0 || strncmp(words[i], "ftp://", 6) == 0)
80 fprintf(fp, "<a href=\"%s\">%s</a>", words[i], words[i]);
81 else if (strcmp(words[i], "___") == 0) {
82 /* Link. */
83 for (j = i + 2; j < nwords - 1 && strcmp(words[j], "___") != 0; ++j);
84 if (j < nwords - 1) {
85 int lastc = 0;
86 size_t l;
87
88 fprintf(fp, "<a href=\"%s\">", words[j + 1]);
89
90 l = strlen(words[j - 1]) - 1;
91 if (strchr("\"`'.,;:()[]?!", words[j - 1][l])) {
92 lastc = words[j - 1][l];
93 words[j - 1][l] = 0;
94 }
95 /*
96 while (i < j) {
97 size_t l;
98 if (i == j - 1 && strchr("\"`'.,;:()[]", words[i][l = strlen(words[i]) - 1])) {
99 lastc = words[i][l];
100 words[i][l] = 0;
101 }
102 fprintf(fp, "%s%s", words[i++], i < j ? " " : "");
103 }
104 ++i;
105 */
106
107 inline_markup_words(fp, words + i + 1, j - i - 1);
108 fprintf(fp, "</a>");
109 if (lastc)
110 putc(lastc, fp);
111 i = j + 1;
112 }
113 } else
114 fprintf(fp, "%s", words[i]);
115
116 if (i < nwords - 1)
117 putc(' ', fp);
118 }
119
120 }
121
122 /* emit_as_html STREAM PARAGRAPH
123 * Emit PARAGRAPH to STREAM, converting its text to HTML. */
emit_as_html(FILE * fp,const struct paragraph * P)124 void emit_as_html(FILE *fp, const struct paragraph *P) {
125 static char *buf, **words;
126 static size_t buflen, nwordsalloc;
127 size_t i, n, nwords = 0;
128 const char *p;
129 char *q, *ws, *we;
130
131 for (i = 0, n = 0; i < P->nlines; ++i)
132 n += strlen(P->lines[i]) + 1;
133
134 /* Conservative; " (1) -> " (5). */
135 if (!buf || n * 6 + 1 > buflen)
136 buf = realloc(buf, buflen = n * 5 + 1);
137
138 for (i = 0, q = buf; i < P->nlines; ++i) {
139 for (p = P->lines[i]; *p; ++p) {
140 if (*p == '&') {
141 strcpy(q, "&");
142 q += 5;
143 } else if (*p == '<') {
144 strcpy(q, "<");
145 q += 4;
146 } else if (*p == '>') {
147 strcpy(q, ">");
148 q += 4;
149 } else if (*p == '\"') {
150 strcpy(q, """);
151 q += 6;
152 } else
153 *q++ = *p;
154 }
155
156 *q++ = '\n';
157
158 }
159 *q = 0;
160
161 /* Break into words. */
162 if (!words)
163 words = malloc((nwordsalloc = 100) * sizeof *words);
164
165 ws = buf;
166 while (1) {
167 while (*ws && strchr(" \n", *ws)) ++ws;
168 if (!*ws) break;
169
170 /* End of this word. */
171 we = ws + strcspn(ws, " \n");
172 words[nwords++] = ws;
173 if (*we) {
174 *we = 0;
175 ws = we + 1;
176 } else
177 break;
178
179 if (nwords == nwordsalloc)
180 words = realloc(words, (nwordsalloc *= 2) * sizeof *words);
181 }
182
183 inline_markup_words(fp, words, nwords);
184
185 }
186
187