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 doc_put(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 doc_lines(struct doc
*doc
, int beg
, int end
)
145 for (i
= beg
; i
< end
; i
++) {
146 doc_put(doc
, doc_line(doc
, i
));
151 static int indents(char *s
)
159 static int islist(char *first
, char *line
)
163 if (!first
|| strlen(first
) < 2)
165 if (first
[1] != ' ' || !strchr(signs
, first
[0]))
169 if (strlen(line
) < 2)
171 return line
[0] == first
[0] && line
[1] == first
[1];
174 static int par_end(struct doc
*doc
, int beg
, int end
)
178 while (i
< end
&& (line
= doc_line(doc
, i
))) {
179 if (!*line
|| indents(line
) || islist(line
, NULL
))
186 static int doc_par(struct doc
*doc
, int beg
, int end
)
189 if (indents(doc_line(doc
, beg
)))
191 doc
->ops
->par_beg(doc
->fd
);
192 i
= par_end(doc
, beg
, end
);
193 doc_lines(doc
, beg
, i
);
194 doc
->ops
->par_end(doc
->fd
);
198 static int min(int a
, int b
)
200 return a
< b
? a
: b
;
203 static int doc_deindent(struct doc
*doc
, int n
, int indent
)
207 while ((line
= doc_line(doc
, n
))) {
208 if (*line
&& indents(line
) < indent
)
217 static int doc_block(struct doc
*doc
, int beg
, int end
)
219 int level
= indents(doc_line(doc
, beg
));
223 next
= min(end
, doc_deindent(doc
, beg
+ 1, level
));
224 doc_handle(doc
, beg
, next
, level
);
229 static int doc_list(struct doc
*doc
, int beg
, int end
)
232 char *first
= doc_line(doc
, i
);
234 if (!islist(first
, NULL
))
236 doc
->ops
->list_beg(doc
->fd
);
237 while ((line
= doc_line(doc
, i
)) && islist(first
, line
)) {
238 int next
= min(end
, doc_deindent(doc
, i
+ 1, 2));
240 doc
->ops
->item_beg(doc
->fd
);
243 i
= par_end(doc
, i
, next
);
244 doc_lines(doc
, head
, i
);
247 doc_handle(doc
, i
, next
, 2);
249 doc
->ops
->item_end(doc
->fd
);
253 doc
->ops
->list_end(doc
->fd
);
257 static int doc_pre(struct doc
*doc
, int beg
, int end
)
262 doc
->ops
->pre_beg(doc
->fd
);
263 for (i
= beg
; i
< end
; i
++) {
264 doc_put(doc
, doc_line(doc
, i
));
267 doc
->ops
->pre_end(doc
->fd
);
271 static int doc_formula(struct doc
*doc
, int beg
, int end
)
274 if (!doc
->level
|| *doc_line(doc
, beg
) != '=')
276 doc
->ops
->formula_beg(doc
->fd
);
277 for (i
= beg
; i
< end
; i
++) {
278 char *line
= doc_line(doc
, i
);
285 doc
->ops
->formula_end(doc
->fd
);
289 static int (*parts
[])(struct doc
*doc
, int beg
, int end
) =
290 {doc_head
, doc_list
, doc_formula
, doc_pre
, doc_par
, doc_block
};
292 static void doc_handle(struct doc
*doc
, int beg
, int end
, int level
)
299 for (i
= 0; i
< LENGTH(parts
); i
++)
300 if ((c
= parts
[i
](doc
, line
, end
)))
304 doc_lines(doc
, line
, line
+ 1);
311 void fmt(int fd
, struct txt
*txt
, struct fmt_ops
*ops
)
313 struct doc
*doc
= doc_alloc(fd
, txt
, ops
);
314 doc
->ops
->doc_beg(fd
);
315 doc_handle(doc
, 0, txt
->n
, 0);
316 doc
->ops
->doc_end(fd
);