16 static struct doc
*doc_alloc(int fd
, struct txt
*txt
, struct fmt_ops
*ops
)
18 struct doc
*doc
= xmalloc(sizeof(struct doc
));
26 static void doc_free(struct doc
*doc
)
31 static char *doc_line(struct doc
*doc
, int line
)
33 char *s
= txt_line(doc
->txt
, line
);
35 for (i
= 0; i
< doc
->level
&& s
&& *s
; i
++)
40 static void doc_handle(struct doc
*doc
, int beg
, int end
, int level
);
42 static int doc_head(struct doc
*doc
, int beg
, int end
)
44 char *line
= doc_line(doc
, beg
);
45 char *next
= doc_line(doc
, beg
+ 1);
49 if (!next
|| !*line
|| beg
== end
|| doc
->level
)
52 if (!c
|| !strchr(signs
, *next
))
57 doc
->ops
->head_beg(doc
->fd
, strchr(signs
, *next
) - signs
);
58 doc
->ops
->put(doc
->fd
, line
);
59 doc
->ops
->head_end(doc
->fd
);
63 static char *possible_inline(char *s
) {
64 char *signs
= "*$@\\";
67 if (strchr(signs
, *s
) && !isspace(*(s
+ 1)))
68 if (s
== home
|| isspace(*(s
- 1)))
75 static void fillbuf(char *buf
, int len
, char *beg
, char *end
)
77 int n
= len
- 1 < end
- beg
? len
- 1 : end
- beg
;
82 static char *doc_put_inline(struct doc
*doc
, char *s
)
88 r
= strchr(s
+ 1, *s
);
90 fillbuf(buf
, LENGTH(buf
), s
+ 1, r
);
91 doc
->ops
->put_emph(doc
->fd
, buf
);
96 r
= strchr(s
+ 1, *s
);
98 fillbuf(buf
, LENGTH(buf
), s
, r
+ 1);
99 doc
->ops
->put_raw(doc
->fd
, buf
);
104 for (r
= s
+ 1; isalnum(*r
); r
++);
106 fillbuf(buf
, LENGTH(buf
), s
+ 1, r
);
107 doc
->ops
->put_ref(doc
->fd
, buf
);
111 if (strchr("*$@\\", *(s
+ 1))) {
112 fillbuf(buf
, LENGTH(buf
), s
+ 1, s
+ 2);
113 doc
->ops
->put(doc
->fd
, buf
);
123 static void put_line(struct doc
*doc
, char *s
)
128 char *r
= possible_inline(s
);
131 fillbuf(buf
, LENGTH(buf
), done
, r
);
132 doc
->ops
->put(doc
->fd
, buf
);
134 if ((r
= doc_put_inline(doc
, r
)))
139 doc
->ops
->put(doc
->fd
, done
);
142 static void raw_line(struct doc
*doc
, char *s
)
144 doc
->ops
->put(doc
->fd
, s
);
147 static void put_lines(struct doc
*doc
, int beg
, int end
)
150 for (i
= beg
; i
< end
; i
++) {
151 put_line(doc
, doc_line(doc
, i
));
156 static void raw_lines(struct doc
*doc
, int beg
, int end
)
159 for (i
= beg
; i
< end
; i
++) {
160 raw_line(doc
, doc_line(doc
, i
));
165 static int indents(char *s
)
173 static int islist(char *first
, char *line
)
177 if (!first
|| strlen(first
) < 2)
179 if (first
[1] != ' ' || !strchr(signs
, first
[0]))
183 if (strlen(line
) < 2)
185 return line
[0] == first
[0] && line
[1] == first
[1];
188 static int par_end(struct doc
*doc
, int beg
, int end
)
192 while (i
< end
&& (line
= doc_line(doc
, i
))) {
193 if (!*line
|| indents(line
) || islist(line
, NULL
))
200 static int doc_par(struct doc
*doc
, int beg
, int end
)
203 if (indents(doc_line(doc
, beg
)))
205 doc
->ops
->par_beg(doc
->fd
);
206 i
= par_end(doc
, beg
, end
);
207 put_lines(doc
, beg
, i
);
208 doc
->ops
->par_end(doc
->fd
);
212 static int min(int a
, int b
)
214 return a
< b
? a
: b
;
217 static int doc_deindent(struct doc
*doc
, int n
, int indent
)
221 while ((line
= doc_line(doc
, n
))) {
222 if (*line
&& indents(line
) < indent
)
231 static int doc_block(struct doc
*doc
, int beg
, int end
)
233 int level
= indents(doc_line(doc
, beg
));
237 next
= min(end
, doc_deindent(doc
, beg
+ 1, level
));
238 doc_handle(doc
, beg
, next
, level
);
243 static int doc_list(struct doc
*doc
, int beg
, int end
)
246 char *first
= doc_line(doc
, i
);
248 if (!islist(first
, NULL
))
250 doc
->ops
->list_beg(doc
->fd
);
251 while ((line
= doc_line(doc
, i
)) && islist(first
, line
)) {
252 int next
= min(end
, doc_deindent(doc
, i
+ 1, 2));
254 doc
->ops
->item_beg(doc
->fd
);
257 i
= par_end(doc
, i
, next
);
258 put_lines(doc
, head
, i
);
261 doc_handle(doc
, i
, next
, 2);
263 doc
->ops
->item_end(doc
->fd
);
267 doc
->ops
->list_end(doc
->fd
);
271 static int doc_pre(struct doc
*doc
, int beg
, int end
)
275 doc
->ops
->pre_beg(doc
->fd
);
276 raw_lines(doc
, beg
, end
);
277 doc
->ops
->pre_end(doc
->fd
);
281 static int doc_formula(struct doc
*doc
, int beg
, int end
)
284 if (!doc
->level
|| *doc_line(doc
, beg
) != '=')
286 doc
->ops
->formula_beg(doc
->fd
);
287 for (i
= beg
; i
< end
; i
++) {
288 char *line
= doc_line(doc
, i
);
295 doc
->ops
->formula_end(doc
->fd
);
299 static int (*parts
[])(struct doc
*doc
, int beg
, int end
) =
300 {doc_head
, doc_list
, doc_formula
, doc_pre
, doc_par
, doc_block
};
302 static void doc_handle(struct doc
*doc
, int beg
, int end
, int level
)
309 for (i
= 0; i
< LENGTH(parts
); i
++)
310 if ((c
= parts
[i
](doc
, line
, end
)))
314 put_lines(doc
, line
, line
+ 1);
321 void fmt(int fd
, struct txt
*txt
, struct fmt_ops
*ops
)
323 struct doc
*doc
= doc_alloc(fd
, txt
, ops
);
324 doc
->ops
->doc_beg(fd
);
325 doc_handle(doc
, 0, txt
->n
, 0);
326 doc
->ops
->doc_end(fd
);