summaryrefslogtreecommitdiff
path: root/support/word2x/text-fmt.cc
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/word2x/text-fmt.cc
Initial commit
Diffstat (limited to 'support/word2x/text-fmt.cc')
-rw-r--r--support/word2x/text-fmt.cc287
1 files changed, 287 insertions, 0 deletions
diff --git a/support/word2x/text-fmt.cc b/support/word2x/text-fmt.cc
new file mode 100644
index 0000000000..3d032462b9
--- /dev/null
+++ b/support/word2x/text-fmt.cc
@@ -0,0 +1,287 @@
+/* $Id: text-fmt.cc,v 1.13 1997/04/13 04:15:33 dps Exp $ */
+
+/* Everything is declared as static to avoid namespace polution but */
+/* is reachable externally via the exported table (and this it the */
+/* only way they get called). */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#else /* Do not have alloca.h */
+ #ifdef _AIX
+#pragma alloca
+#else /* not _AIX */
+extern "C" char *alloca(int);
+#endif /* _AIX */
+#endif /* HAVE_ALLOCA_H */
+#endif /* __GNUC__ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "interface.h"
+#include "lib.h"
+#include "text-table.h"
+
+/* Local data */
+struct text_data
+{
+ text_table *tabl;
+ int col;
+ int row;
+ int margin;
+ int l_indent;
+};
+
+/* Most of these values are thanks to catdoc by
+ * Victor B. Wagner <vitus@agropc.msk.su> et al */
+static const cmap char_map[]=
+{
+ { 0x1E, "-" }, // Unbreakable join
+ { 0x1F, "" }, // Soft hypen
+ { 0x7f, "" }, // Delete 127s
+ { 0x85, "..." }, // Dots
+ { 0x91, "`" }, // 91 = left quote
+ { 0x92, "'" }, // 92 = right quote
+ { 0x93, "\"" }, // 93 = opening double quote
+ { 0x94, "\"" }, // 94 = closing double quote
+ { 0x95, "o" }, // 95 = Bullet
+ { 0x96, "-" }, // em-dash
+ { 0x97, "-" }, // en-dash
+ { 0x99, "(tm)" }, // Trademark
+ { 0xA0, " " }, // Unbreakable space
+ { 0xA3, "<=" }, // Less than or = came out as A3
+ { 0xA9, "(c)" }, // Copyright
+ { 0xAB, "<<" }, // Openning << quotes
+ { 0xAE, "(R)" }, // Reserved sign
+ { 0xB3, ">=" }, // Greater than or = came out as B3
+ { 0xBB, ">>" }, // Closing >> quotes
+};
+
+/* Allocate local data */
+static void *allocate_txt(void)
+{
+ struct text_data *tdata;
+
+ tdata=new(struct text_data);
+ tdata->tabl=NULL;
+ tdata->margin=0;
+ tdata->l_indent=0;
+ return tdata;
+}
+
+static void txt_code(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ d=d;
+ switch(*(t->data.d))
+ {
+ case CH_PAGE:
+ if (fmt->flags.new_pages)
+ fputc('\014', out);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Free local data */
+static void free_txt(void *d)
+{
+ struct text_data *tdata;
+
+ tdata=(struct text_data *) d;
+ if (tdata->tabl!=NULL)
+ delete(tdata->tabl);
+}
+
+
+/* list start increases margin */
+static void inc_margin(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct text_data *tdata;
+ t=t;
+ fmt=fmt;
+ out=out;
+
+ tdata=(struct text_data *) d;
+ tdata->margin+=4;
+}
+
+
+/* list start decreases margin */
+static void dec_margin(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct text_data *tdata;
+ t=t;
+ fmt=fmt;
+ out=out;
+
+ tdata=(struct text_data *) d;
+ tdata->margin-=4;
+}
+
+
+/* items are easy */
+static void txt_item(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ tblock *ts;
+ const char *s;
+ int i, m;
+ struct text_data *dp;
+
+ fmt=fmt; // No need for fmt
+ dp=(struct text_data *) d;
+ ts=map_string(t->data.d, char_map);
+ s=*ts;
+ fputc('\n', out);
+ m=dp->margin-strlen(s)-1;
+ for (i=0; i<m; i++)
+ fputc(' ', out);
+ fputs(s, out);
+ fputc(' ', out);
+ dp->l_indent=dp->margin;
+ delete(ts);
+}
+
+
+/* Paragraphs are easy */
+static void fold_para(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ tblock *b, *ts;
+ const char *s;
+ char *nl;
+ struct text_data *dp;
+ int i;
+
+ dp=(struct text_data *) d;
+ if (dp->margin==0 || (nl=(char *) alloca(dp->margin+2))==NULL)
+ nl="\n";
+ else
+ {
+ *nl='\n';
+ for (i=1; i<=dp->margin; i++)
+ *(nl+i)=' ';
+ *(nl+dp->margin+1)='\0';
+ }
+ ts=map_string(t->data.d, char_map);
+ b=word_wrap((*ts), nl, nl, fmt->maxline-(dp->margin), 0);
+ delete(ts);
+ s=*b;
+ for (i=dp->l_indent; i<dp->margin; i++)
+ fputc(' ', out);
+ fputs(s, out);
+ fputs("\n\n", out);
+ dp->l_indent=0;
+ delete(b);
+}
+
+/* Start a table === allocate table and initialise */
+static void alloc_tbl(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct text_data *tdata;
+
+ out=out;
+ fmt=fmt;
+ tdata=(struct text_data *) d;
+ tdata->col=0;
+ tdata->row=0;
+ tdata->tabl=new(text_table)(t->data.table.cols, t->data.table.rows);
+}
+
+
+/* End of a table==print the table */
+static void format_tbl(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct text_data *tdata;
+
+ t=t;
+ tdata=(struct text_data *) d;
+ tdata->tabl->print_table(fmt->maxline, out); // Print table
+ delete(tdata->tabl);
+ tdata->tabl=NULL;
+}
+
+/* start row==set column to 0 */
+static void start_row(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct text_data *tdata;
+
+ out=out;
+ fmt=fmt;
+ t=t;
+ tdata=(struct text_data *) d;
+ tdata->col=0;
+}
+
+/* end row==add one to row */
+static void inc_row(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct text_data *tdata;
+
+ out=out;
+ fmt=fmt;
+ t=t;
+ tdata=(struct text_data *) d;
+ tdata->row++;
+}
+
+
+/* Start field === set field */
+static void set_field(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct tblock *ts;
+ struct text_data *tdata;
+
+ out=out;
+ fmt=fmt;
+ ts=map_string(t->data.d, char_map);
+ tdata=(struct text_data *) d;
+ tdata->tabl->set(tdata->col, tdata->row, (*ts));
+ delete(ts);
+}
+
+/* end field==add one to col */
+static void inc_col(const tok_seq::tok *t, const docfmt *fmt, FILE *out,
+ void *d)
+{
+ struct text_data *tdata;
+
+ out=out;
+ fmt=fmt;
+ t=t;
+ tdata=(struct text_data *) d;
+ tdata->col++;
+}
+
+/* pointers to the functions that do the work */
+docfmt txtfmt=
+{
+ { 0 }, // No page breaks
+ 76, // Width
+ "\n", // Use \n as line ends
+ allocate_txt, // Allocate space
+ free_txt, // Free text
+ {
+ { null_proc, null_proc }, // End and start of document---do nothing
+ { fold_para, null_proc }, // Paragraph
+ { alloc_tbl, format_tbl }, // Start/end table
+ { set_field, inc_col }, // Start/end field
+ { start_row, inc_row }, // Start/end row
+ { null_proc, null_proc }, // Throw away embed messages
+ { inc_margin, dec_margin }, // list start and end
+ { txt_item, null_proc}, // Items
+ { txt_code, null_proc}, // Code
+ { null_proc, null_proc } // Do not understanding anything else
+ }
+};