diff options
Diffstat (limited to 'Docs/src/bin/halibut/misc.c')
-rwxr-xr-x | Docs/src/bin/halibut/misc.c | 714 |
1 files changed, 357 insertions, 357 deletions
diff --git a/Docs/src/bin/halibut/misc.c b/Docs/src/bin/halibut/misc.c index e1818ad..5fad528 100755 --- a/Docs/src/bin/halibut/misc.c +++ b/Docs/src/bin/halibut/misc.c @@ -1,357 +1,357 @@ -/*
- * misc.c: miscellaneous useful items
- */
-#include <string.h>
-#include "halibut.h"
-
-struct stackTag {
- void **data;
- int sp;
- int size;
-};
-
-stack stk_new(void)
-{
- stack s;
-
- s = mknew(struct stackTag);
- s->sp = 0;
- s->size = 0;
- s->data = NULL;
-
- return s;
-}
-
-void stk_free(stack s)
-{
- sfree(s->data);
- sfree(s);
-}
-
-void stk_push(stack s, void *item)
-{
- if (s->size <= s->sp)
- {
- s->size = s->sp + 32;
- s->data = resize(s->data, s->size);
- }
- s->data[s->sp++] = item;
-}
-
-void *stk_pop(stack s)
-{
- if (s->sp > 0)
- return s->data[--s->sp];
- else
- return NULL;
-}
-
-/*
- * Small routines to amalgamate a string from an input source.
- */
-const rdstring empty_rdstring = { 0, 0, NULL };
-const rdstringc empty_rdstringc = { 0, 0, NULL };
-
-void rdadd(rdstring * rs, wchar_t c)
-{
- if (rs->pos >= rs->size - 1)
- {
- rs->size = rs->pos + 128;
- rs->text = resize(rs->text, rs->size);
- }
- rs->text[rs->pos++] = c;
- rs->text[rs->pos] = 0;
-}
-
-void rdadds(rdstring * rs, wchar_t * p)
-{
- int len = ustrlen(p);
- if (rs->pos >= rs->size - len)
- {
- rs->size = rs->pos + len + 128;
- rs->text = resize(rs->text, rs->size);
- }
- ustrcpy(rs->text + rs->pos, p);
- rs->pos += len;
-}
-
-wchar_t *rdtrim(rdstring * rs)
-{
- rs->text = resize(rs->text, rs->pos + 1);
- return rs->text;
-}
-
-void rdaddc(rdstringc * rs, char c)
-{
- if (rs->pos >= rs->size - 1)
- {
- rs->size = rs->pos + 128;
- rs->text = resize(rs->text, rs->size);
- }
- rs->text[rs->pos++] = c;
- rs->text[rs->pos] = 0;
-}
-
-void rdaddsc(rdstringc * rs, char *p)
-{
- int len = strlen(p);
- if (rs->pos >= rs->size - len)
- {
- rs->size = rs->pos + len + 128;
- rs->text = resize(rs->text, rs->size);
- }
- strcpy(rs->text + rs->pos, p);
- rs->pos += len;
-}
-
-char *rdtrimc(rdstringc * rs)
-{
- rs->text = resize(rs->text, rs->pos + 1);
- return rs->text;
-}
-
-int compare_wordlists(word * a, word * b)
-{
- int t;
- while (a && b)
- {
- if (a->type != b->type)
- return (a->type < b->type ? -1 : +1); /* FIXME? */
- t = a->type;
- if ((t != word_Normal && t != word_Code &&
- t != word_WeakCode && t != word_Emph) || a->alt || b->alt)
- {
- int c;
- if (a->text && b->text)
- {
- c = ustricmp(a->text, b->text);
- if (c)
- return c;
- }
- c = compare_wordlists(a->alt, b->alt);
- if (c)
- return c;
- a = a->next;
- b = b->next;
- } else
- {
- wchar_t *ap = a->text, *bp = b->text;
- while (*ap && *bp)
- {
- wchar_t ac = utolower(*ap), bc = utolower(*bp);
- if (ac != bc)
- return (ac < bc ? -1 : +1);
- if (!*++ap && a->next && a->next->type == t && !a->next->alt)
- a = a->next, ap = a->text;
- if (!*++bp && b->next && b->next->type == t && !b->next->alt)
- b = b->next, bp = b->text;
- }
- if (*ap || *bp)
- return (*ap ? +1 : -1);
- a = a->next;
- b = b->next;
- }
- }
-
- if (a || b)
- return (a ? +1 : -1);
- else
- return 0;
-}
-
-void mark_attr_ends(paragraph * sourceform)
-{
- paragraph *p;
- word *w, *wp;
- for (p = sourceform; p; p = p->next)
- {
- wp = NULL;
- for (w = p->words; w; w = w->next)
- {
- if (isattr(w->type))
- {
- int before = (wp && isattr(wp->type) &&
- sameattr(wp->type, w->type));
- int after = (w->next && isattr(w->next->type) &&
- sameattr(w->next->type, w->type));
- w->aux |= (before ?
- (after ? attr_Always : attr_Last) :
- (after ? attr_First : attr_Only));
- }
- wp = w;
- }
- }
-}
-
-wrappedline *wrap_para(word * text, int width, int subsequentwidth,
- int (*widthfn) (word *))
-{
- wrappedline *head = NULL, **ptr = &head;
- int nwords, wordsize;
- struct wrapword {
- word *begin, *end;
- int width;
- int spacewidth;
- int cost;
- int nwords;
- } *wrapwords;
- int i, j, n;
-
- /*
- * Break the line up into wrappable components.
- */
- nwords = wordsize = 0;
- wrapwords = NULL;
- while (text)
- {
- if (nwords >= wordsize)
- {
- wordsize = nwords + 64;
- wrapwords = srealloc(wrapwords, wordsize * sizeof(*wrapwords));
- }
- wrapwords[nwords].width = 0;
- wrapwords[nwords].begin = text;
- while (text)
- {
- wrapwords[nwords].width += widthfn(text);
- wrapwords[nwords].end = text->next;
- if (text->next && (text->next->type == word_WhiteSpace ||
- text->next->type == word_EmphSpace ||
- text->breaks))
- break;
- text = text->next;
- }
- if (text && text->next && (text->next->type == word_WhiteSpace ||
- text->next->type == word_EmphSpace))
- {
- wrapwords[nwords].spacewidth = widthfn(text->next);
- text = text->next;
- } else
- {
- wrapwords[nwords].spacewidth = 0;
- }
- nwords++;
- if (text)
- text = text->next;
- }
-
- /*
- * Perform the dynamic wrapping algorithm: work backwards from
- * nwords-1, determining the optimal wrapping for each terminal
- * subsequence of the paragraph.
- */
- for (i = nwords; i--;)
- {
- int best = -1;
- int bestcost = 0;
- int cost;
- int linelen = 0, spacewidth = 0;
- int seenspace;
- int thiswidth = (i == 0 ? width : subsequentwidth);
-
- j = 0;
- seenspace = 0;
- while (i + j < nwords)
- {
- /*
- * See what happens if we put j+1 words on this line.
- */
- if (spacewidth)
- seenspace = 1;
- linelen += spacewidth + wrapwords[i + j].width;
- spacewidth = wrapwords[i + j].spacewidth;
- j++;
- if (linelen > thiswidth)
- {
- /*
- * If we're over the width limit, abandon ship,
- * _unless_ there is no best-effort yet (which will
- * only happen if the first word is too long all by
- * itself).
- */
- if (best > 0)
- break;
- }
- if (i + j == nwords)
- {
- /*
- * Special case: if we're at the very end of the
- * paragraph, we don't score penalty points for the
- * white space left on the line.
- */
- cost = 0;
- } else
- {
- cost = (thiswidth - linelen) * (thiswidth - linelen);
- cost += wrapwords[i + j].cost;
- }
- /*
- * We compare bestcost >= cost, not bestcost > cost,
- * because in cases where the costs are identical we
- * want to try to look like the greedy algorithm,
- * because readers are likely to have spent a lot of
- * time looking at greedy-wrapped paragraphs and
- * there's no point violating the Principle of Least
- * Surprise if it doesn't actually gain anything.
- */
- if (best < 0 || bestcost >= cost)
- {
- bestcost = cost;
- best = j;
- }
- }
- /*
- * Now we know the optimal answer for this terminal
- * subsequence, so put it in wrapwords.
- */
- wrapwords[i].cost = bestcost;
- wrapwords[i].nwords = best;
- }
-
- /*
- * We've wrapped the paragraph. Now build the output
- * `wrappedline' list.
- */
- i = 0;
- while (i < nwords)
- {
- wrappedline *w = mknew(wrappedline);
- *ptr = w;
- ptr = &w->next;
- w->next = NULL;
-
- n = wrapwords[i].nwords;
- w->begin = wrapwords[i].begin;
- w->end = wrapwords[i + n - 1].end;
-
- /*
- * Count along the words to find nspaces and shortfall.
- */
- w->nspaces = 0;
- w->shortfall = width;
- for (j = 0; j < n; j++)
- {
- w->shortfall -= wrapwords[i + j].width;
- if (j < n - 1 && wrapwords[i + j].spacewidth)
- {
- w->nspaces++;
- w->shortfall -= wrapwords[i + j].spacewidth;
- }
- }
- i += n;
- }
-
- sfree(wrapwords);
-
- return head;
-}
-
-void wrap_free(wrappedline * w)
-{
- while (w)
- {
- wrappedline *t = w->next;
- sfree(w);
- w = t;
- }
-}
+/* + * misc.c: miscellaneous useful items + */ +#include <string.h> +#include "halibut.h" + +struct stackTag { + void **data; + int sp; + int size; +}; + +stack stk_new(void) +{ + stack s; + + s = mknew(struct stackTag); + s->sp = 0; + s->size = 0; + s->data = NULL; + + return s; +} + +void stk_free(stack s) +{ + sfree(s->data); + sfree(s); +} + +void stk_push(stack s, void *item) +{ + if (s->size <= s->sp) + { + s->size = s->sp + 32; + s->data = resize(s->data, s->size); + } + s->data[s->sp++] = item; +} + +void *stk_pop(stack s) +{ + if (s->sp > 0) + return s->data[--s->sp]; + else + return NULL; +} + +/* + * Small routines to amalgamate a string from an input source. + */ +const rdstring empty_rdstring = { 0, 0, NULL }; +const rdstringc empty_rdstringc = { 0, 0, NULL }; + +void rdadd(rdstring * rs, wchar_t c) +{ + if (rs->pos >= rs->size - 1) + { + rs->size = rs->pos + 128; + rs->text = resize(rs->text, rs->size); + } + rs->text[rs->pos++] = c; + rs->text[rs->pos] = 0; +} + +void rdadds(rdstring * rs, wchar_t * p) +{ + int len = ustrlen(p); + if (rs->pos >= rs->size - len) + { + rs->size = rs->pos + len + 128; + rs->text = resize(rs->text, rs->size); + } + ustrcpy(rs->text + rs->pos, p); + rs->pos += len; +} + +wchar_t *rdtrim(rdstring * rs) +{ + rs->text = resize(rs->text, rs->pos + 1); + return rs->text; +} + +void rdaddc(rdstringc * rs, char c) +{ + if (rs->pos >= rs->size - 1) + { + rs->size = rs->pos + 128; + rs->text = resize(rs->text, rs->size); + } + rs->text[rs->pos++] = c; + rs->text[rs->pos] = 0; +} + +void rdaddsc(rdstringc * rs, char *p) +{ + int len = strlen(p); + if (rs->pos >= rs->size - len) + { + rs->size = rs->pos + len + 128; + rs->text = resize(rs->text, rs->size); + } + strcpy(rs->text + rs->pos, p); + rs->pos += len; +} + +char *rdtrimc(rdstringc * rs) +{ + rs->text = resize(rs->text, rs->pos + 1); + return rs->text; +} + +int compare_wordlists(word * a, word * b) +{ + int t; + while (a && b) + { + if (a->type != b->type) + return (a->type < b->type ? -1 : +1); /* FIXME? */ + t = a->type; + if ((t != word_Normal && t != word_Code && + t != word_WeakCode && t != word_Emph) || a->alt || b->alt) + { + int c; + if (a->text && b->text) + { + c = ustricmp(a->text, b->text); + if (c) + return c; + } + c = compare_wordlists(a->alt, b->alt); + if (c) + return c; + a = a->next; + b = b->next; + } else + { + wchar_t *ap = a->text, *bp = b->text; + while (*ap && *bp) + { + wchar_t ac = utolower(*ap), bc = utolower(*bp); + if (ac != bc) + return (ac < bc ? -1 : +1); + if (!*++ap && a->next && a->next->type == t && !a->next->alt) + a = a->next, ap = a->text; + if (!*++bp && b->next && b->next->type == t && !b->next->alt) + b = b->next, bp = b->text; + } + if (*ap || *bp) + return (*ap ? +1 : -1); + a = a->next; + b = b->next; + } + } + + if (a || b) + return (a ? +1 : -1); + else + return 0; +} + +void mark_attr_ends(paragraph * sourceform) +{ + paragraph *p; + word *w, *wp; + for (p = sourceform; p; p = p->next) + { + wp = NULL; + for (w = p->words; w; w = w->next) + { + if (isattr(w->type)) + { + int before = (wp && isattr(wp->type) && + sameattr(wp->type, w->type)); + int after = (w->next && isattr(w->next->type) && + sameattr(w->next->type, w->type)); + w->aux |= (before ? + (after ? attr_Always : attr_Last) : + (after ? attr_First : attr_Only)); + } + wp = w; + } + } +} + +wrappedline *wrap_para(word * text, int width, int subsequentwidth, + int (*widthfn) (word *)) +{ + wrappedline *head = NULL, **ptr = &head; + int nwords, wordsize; + struct wrapword { + word *begin, *end; + int width; + int spacewidth; + int cost; + int nwords; + } *wrapwords; + int i, j, n; + + /* + * Break the line up into wrappable components. + */ + nwords = wordsize = 0; + wrapwords = NULL; + while (text) + { + if (nwords >= wordsize) + { + wordsize = nwords + 64; + wrapwords = srealloc(wrapwords, wordsize * sizeof(*wrapwords)); + } + wrapwords[nwords].width = 0; + wrapwords[nwords].begin = text; + while (text) + { + wrapwords[nwords].width += widthfn(text); + wrapwords[nwords].end = text->next; + if (text->next && (text->next->type == word_WhiteSpace || + text->next->type == word_EmphSpace || + text->breaks)) + break; + text = text->next; + } + if (text && text->next && (text->next->type == word_WhiteSpace || + text->next->type == word_EmphSpace)) + { + wrapwords[nwords].spacewidth = widthfn(text->next); + text = text->next; + } else + { + wrapwords[nwords].spacewidth = 0; + } + nwords++; + if (text) + text = text->next; + } + + /* + * Perform the dynamic wrapping algorithm: work backwards from + * nwords-1, determining the optimal wrapping for each terminal + * subsequence of the paragraph. + */ + for (i = nwords; i--;) + { + int best = -1; + int bestcost = 0; + int cost; + int linelen = 0, spacewidth = 0; + int seenspace; + int thiswidth = (i == 0 ? width : subsequentwidth); + + j = 0; + seenspace = 0; + while (i + j < nwords) + { + /* + * See what happens if we put j+1 words on this line. + */ + if (spacewidth) + seenspace = 1; + linelen += spacewidth + wrapwords[i + j].width; + spacewidth = wrapwords[i + j].spacewidth; + j++; + if (linelen > thiswidth) + { + /* + * If we're over the width limit, abandon ship, + * _unless_ there is no best-effort yet (which will + * only happen if the first word is too long all by + * itself). + */ + if (best > 0) + break; + } + if (i + j == nwords) + { + /* + * Special case: if we're at the very end of the + * paragraph, we don't score penalty points for the + * white space left on the line. + */ + cost = 0; + } else + { + cost = (thiswidth - linelen) * (thiswidth - linelen); + cost += wrapwords[i + j].cost; + } + /* + * We compare bestcost >= cost, not bestcost > cost, + * because in cases where the costs are identical we + * want to try to look like the greedy algorithm, + * because readers are likely to have spent a lot of + * time looking at greedy-wrapped paragraphs and + * there's no point violating the Principle of Least + * Surprise if it doesn't actually gain anything. + */ + if (best < 0 || bestcost >= cost) + { + bestcost = cost; + best = j; + } + } + /* + * Now we know the optimal answer for this terminal + * subsequence, so put it in wrapwords. + */ + wrapwords[i].cost = bestcost; + wrapwords[i].nwords = best; + } + + /* + * We've wrapped the paragraph. Now build the output + * `wrappedline' list. + */ + i = 0; + while (i < nwords) + { + wrappedline *w = mknew(wrappedline); + *ptr = w; + ptr = &w->next; + w->next = NULL; + + n = wrapwords[i].nwords; + w->begin = wrapwords[i].begin; + w->end = wrapwords[i + n - 1].end; + + /* + * Count along the words to find nspaces and shortfall. + */ + w->nspaces = 0; + w->shortfall = width; + for (j = 0; j < n; j++) + { + w->shortfall -= wrapwords[i + j].width; + if (j < n - 1 && wrapwords[i + j].spacewidth) + { + w->nspaces++; + w->shortfall -= wrapwords[i + j].spacewidth; + } + } + i += n; + } + + sfree(wrapwords); + + return head; +} + +void wrap_free(wrappedline * w) +{ + while (w) + { + wrappedline *t = w->next; + sfree(w); + w = t; + } +} |