21 #define PAIR(c1, c2) (((c2) << 8) | (c1))
28 {PAIR('E', 'Q'), PAIR('E', 'N'), B_RAW
},
29 {PAIR('P', 'S'), PAIR('P', 'E'), B_RAW
},
30 {PAIR('T', 'S'), PAIR('T', 'E'), B_RAW
},
40 static struct fmt
*fmt_alloc(struct doc
*doc
, struct txt
*txt
,
43 struct fmt
*fmt
= xmalloc(sizeof(struct fmt
));
51 static void fmt_free(struct fmt
*fmt
)
56 static char *fmt_line(struct fmt
*fmt
, int line
)
58 char *s
= txt_line(fmt
->txt
, line
);
60 for (i
= 0; i
< fmt
->level
&& s
&& *s
; i
++)
65 static struct marker
*marker_char(char c
)
68 for (i
= 0; i
< LENGTH(markers
); i
++)
69 if (markers
[i
].beg
== c
)
74 static char *possible_inline(char *s
)
77 struct marker
*m
= NULL
;
81 if ((s
== home
|| isspace(*(s
- 1))) && !isspace(*(s
+ 1)))
82 if ((m
= marker_char(*s
)))
89 static void fillbuf(char *buf
, int len
, char *beg
, char *end
)
91 int n
= len
- 1 < end
- beg
? len
- 1 : end
- beg
;
96 static char *fmt_put_inline(struct fmt
*fmt
, char *s
)
100 struct marker
*marker
;
102 if (marker_char(*(s
+ 1))) {
103 fillbuf(buf
, LENGTH(buf
), s
+ 1, s
+ 2);
104 fmt
->ops
->put(fmt
->doc
, buf
);
109 marker
= marker_char(*s
);
110 if (marker
&& marker
->end
)
111 r
= strchr(s
+ 1, marker
->end
);
112 if (marker
&& !marker
->end
)
113 for (r
= s
+ 1; isalnum(*r
); r
++);
115 fillbuf(buf
, LENGTH(buf
), s
+ 1, r
);
116 fmt
->ops
->put_txt(fmt
->doc
, buf
, marker
->id
);
123 static void put_text(struct fmt
*fmt
, char *s
)
128 char *r
= possible_inline(s
);
131 fillbuf(buf
, LENGTH(buf
), done
, r
);
132 fmt
->ops
->put(fmt
->doc
, buf
);
134 if ((r
= fmt_put_inline(fmt
, r
)))
139 fmt
->ops
->put(fmt
->doc
, done
);
142 static void raw_line(struct fmt
*fmt
, char *s
)
144 fmt
->ops
->put(fmt
->doc
, s
);
147 static void put_line(struct fmt
*fmt
, int n
)
149 put_text(fmt
, fmt_line(fmt
, n
));
153 static void put_lines(struct fmt
*fmt
, int beg
, int end
)
156 for (i
= beg
; i
< end
; i
++)
160 static void raw_lines(struct fmt
*fmt
, int beg
, int end
)
163 for (i
= beg
; i
< end
; i
++) {
164 raw_line(fmt
, fmt_line(fmt
, i
));
169 static int indents(char *s
)
177 static int islist(char *first
, char *line
)
181 if (!first
|| strlen(first
) < 2)
183 if (first
[1] != ' ' || !strchr(signs
, first
[0]))
187 if (strlen(line
) < 2)
189 return line
[0] == first
[0] && line
[1] == first
[1];
192 static void fmt_handle(struct fmt
*fmt
, int beg
, int end
, int level
);
194 static int fmt_head(struct fmt
*fmt
, int beg
, int end
)
196 char *line
= fmt_line(fmt
, beg
);
197 char *next
= fmt_line(fmt
, beg
+ 1);
201 if (!next
|| !*line
|| beg
== end
|| fmt
->level
)
204 if (!c
|| !strchr(signs
, *next
))
209 fmt
->ops
->head_beg(fmt
->doc
, strchr(signs
, *next
) - signs
);
211 fmt
->ops
->head_end(fmt
->doc
, strchr(signs
, *next
) - signs
);
215 static int cmd_line(struct fmt
*fmt
, int i
)
217 return !fmt
->level
&& *fmt_line(fmt
, i
) == '.';
220 static int par_end(struct fmt
*fmt
, int beg
, int end
)
224 while (i
< end
&& (line
= fmt_line(fmt
, i
))) {
225 if (!*line
|| indents(line
) || islist(line
, NULL
) || cmd_line(fmt
, i
))
232 static int fmt_par(struct fmt
*fmt
, int beg
, int end
)
235 if (indents(fmt_line(fmt
, beg
)) || cmd_line(fmt
, beg
))
237 fmt
->ops
->par_beg(fmt
->doc
);
238 i
= par_end(fmt
, beg
, end
);
239 put_lines(fmt
, beg
, i
);
240 fmt
->ops
->par_end(fmt
->doc
);
244 static int fmt_rawline(struct fmt
*fmt
, int beg
, int end
)
246 if (*fmt_line(fmt
, beg
) != '.')
248 raw_lines(fmt
, beg
, beg
+ 1);
252 static int min(int a
, int b
)
254 return a
< b
? a
: b
;
257 static int fmt_deindent(struct fmt
*fmt
, int n
, int indent
)
261 while ((line
= fmt_line(fmt
, n
))) {
262 if (*line
&& indents(line
) < indent
)
271 static int fmt_pre(struct fmt
*fmt
, int beg
, int end
)
273 int level
= indents(fmt_line(fmt
, beg
));
274 int next
= min(end
, fmt_deindent(fmt
, beg
+ 1, level
));
276 fmt
->ops
->block_beg(fmt
->doc
, fmt_line(fmt
, beg
), B_PRE
);
277 raw_lines(fmt
, beg
, next
);
278 fmt
->ops
->block_end(fmt
->doc
, fmt_line(fmt
, next
), B_PRE
);
283 static int fmt_block(struct fmt
*fmt
, int beg
, int end
)
285 struct block
*block
= NULL
;
289 line
= fmt_line(fmt
, beg
);
291 return fmt_pre(fmt
, beg
, end
);
294 for (i
= 0; i
< LENGTH(blocks
); i
++) {
297 if (blocks
[i
].beg
== c1
|| blocks
[i
].beg
== PAIR(c1
, c2
)) {
307 line
= fmt_line(fmt
, next
++);
310 if (block
->end
== c1
|| block
->end
== PAIR(c1
, c2
))
313 fmt
->ops
->block_beg(fmt
->doc
, fmt_line(fmt
, beg
), block
->id
);
315 raw_lines(fmt
, beg
+ 1, next
- 1);
316 fmt
->ops
->block_end(fmt
->doc
, fmt_line(fmt
, next
- 1), block
->id
);
320 static int fmt_list(struct fmt
*fmt
, int beg
, int end
)
323 char *first
= fmt_line(fmt
, i
);
325 if (!islist(first
, NULL
))
327 fmt
->ops
->list_beg(fmt
->doc
);
328 while ((line
= fmt_line(fmt
, i
)) && islist(first
, line
)) {
329 int next
= min(end
, fmt_deindent(fmt
, i
+ 1, 2));
331 fmt
->ops
->item_beg(fmt
->doc
);
334 i
= par_end(fmt
, i
, next
);
335 put_lines(fmt
, head
, i
);
338 fmt_handle(fmt
, i
, next
, 2);
340 fmt
->ops
->item_end(fmt
->doc
);
344 fmt
->ops
->list_end(fmt
->doc
);
348 static int table_columns(char *line
)
351 for (n
= 0; *line
; n
++) {
352 while (*line
== '\t')
354 while (*line
&& *line
!= '\t')
360 static void table_row(struct fmt
*fmt
, char *s
)
363 if (*s
== '=' || *s
== '-')
365 fmt
->ops
->row_beg(fmt
->doc
);
368 while (*s
&& *s
!= '\t')
370 fmt
->ops
->entry_beg(fmt
->doc
);
371 fillbuf(buf
, LENGTH(buf
), r
, s
);
373 fmt
->ops
->entry_end(fmt
->doc
);
377 fmt
->ops
->row_end(fmt
->doc
);
380 static int fmt_table(struct fmt
*fmt
, int beg
, int end
)
384 if (*fmt_line(fmt
, beg
) != '=')
386 n
= table_columns(fmt_line(fmt
, beg
+ 1));
387 fmt
->ops
->table_beg(fmt
->doc
, n
);
388 for (i
= beg
+ 1; i
< end
; i
++) {
389 if (!fmt
->level
&& !*fmt_line(fmt
, i
))
391 table_row(fmt
, fmt_line(fmt
, i
));
393 fmt
->ops
->table_end(fmt
->doc
);
397 static int (*parts
[])(struct fmt
*fmt
, int beg
, int end
) =
398 {fmt_head
, fmt_list
, fmt_table
, fmt_block
, fmt_rawline
, fmt_par
};
400 static void fmt_handle(struct fmt
*fmt
, int beg
, int end
, int level
)
407 if (!*fmt_line(fmt
, line
)) {
408 put_line(fmt
, line
++);
411 for (i
= 0; i
< LENGTH(parts
); i
++)
412 if ((c
= parts
[i
](fmt
, line
, end
)))
416 put_line(fmt
, line
++);
421 void format(struct doc
*doc
, struct txt
*txt
, struct fmt_ops
*ops
)
423 struct fmt
*fmt
= fmt_alloc(doc
, txt
, ops
);
424 fmt
->ops
->doc_beg(doc
);
425 fmt_handle(fmt
, 0, txt
->n
, 0);
426 fmt
->ops
->doc_end(doc
);