summaryrefslogtreecommitdiff
path: root/Docs/src/bin/halibut/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'Docs/src/bin/halibut/misc.c')
-rwxr-xr-xDocs/src/bin/halibut/misc.c714
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;
+ }
+}