xref: /plan9/sys/src/cmd/aux/antiword/text.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1 /*
2  * text.c
3  * Copyright (C) 1999-2004 A.J. van Os; Released under GNU GPL
4  *
5  * Description:
6  * Functions to deal with the Text format
7  *
8  */
9 
10 #include <string.h>
11 #include "antiword.h"
12 
13 /* The character set */
14 static encoding_type	eEncoding = encoding_neutral;
15 /* Current vertical position information */
16 static long		lYtopCurr = 0;
17 /* Local representation of the non-breaking space */
18 static UCHAR		ucNbsp = 0;
19 
20 
21 /*
22  * vPrologueTXT - set options and perform the Text initialization
23  */
24 void
vPrologueTXT(diagram_type * pDiag,const options_type * pOptions)25 vPrologueTXT(diagram_type *pDiag, const options_type *pOptions)
26 {
27 	fail(pDiag == NULL);
28 	fail(pOptions == NULL);
29 
30 	eEncoding = pOptions->eEncoding;
31 	pDiag->lXleft = 0;
32 	pDiag->lYtop = 0;
33 	lYtopCurr = 0;
34 } /* end of vPrologueTXT */
35 
36 /*
37  * vEpilogueTXT - clean up after everything is done
38  */
39 void
vEpilogueTXT(FILE * pOutFile)40 vEpilogueTXT(FILE *pOutFile)
41 {
42 	fail(pOutFile == NULL);
43 
44 	fprintf(pOutFile, "\n");
45 } /* end of vEpilogueTXT */
46 
47 /*
48  * vPrintTXT - print a Text string
49  */
50 static void
vPrintTXT(FILE * pFile,const char * szString,size_t tStringLength)51 vPrintTXT(FILE *pFile, const char *szString, size_t tStringLength)
52 {
53 	const UCHAR	*ucBytes;
54 	size_t		tCount;
55 
56 	fail(szString == NULL);
57 
58 	if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
59 		return;
60 	}
61 
62 	if (eEncoding == encoding_utf_8) {
63 		fprintf(pFile, "%.*s", (int)tStringLength, szString);
64 		return;
65 	}
66 
67 	if (ucNbsp == 0) {
68 		ucNbsp = ucGetNbspCharacter();
69 		DBG_HEX_C(ucNbsp != 0xa0, ucNbsp);
70 	}
71 
72 	ucBytes = (UCHAR *)szString;
73 	for (tCount = 0; tCount < tStringLength ; tCount++) {
74 		if (ucBytes[tCount] == ucNbsp) {
75 			(void)putc(' ', pFile);
76 		} else {
77 			(void)putc(szString[tCount], pFile);
78 		}
79 	}
80 } /* end of vPrintTXT */
81 
82 /*
83  * vMoveTo - move to the given X,Y coordinates
84  *
85  * Move the current position of the given diagram to its X,Y coordinates,
86  * start on a new page if needed
87  */
88 static void
vMoveTo(diagram_type * pDiag)89 vMoveTo(diagram_type *pDiag)
90 {
91 	int	iCount, iNbr;
92 
93 	fail(pDiag == NULL);
94 	fail(pDiag->pOutFile == NULL);
95 
96 	if (pDiag->lYtop != lYtopCurr) {
97 		iNbr = iDrawUnits2Char(pDiag->lXleft);
98 		for (iCount = 0; iCount < iNbr; iCount++) {
99 			(void)putc(FILLER_CHAR, pDiag->pOutFile);
100 		}
101 		lYtopCurr = pDiag->lYtop;
102 	}
103 } /* end of vMoveTo */
104 
105 /*
106  * vMove2NextLineTXT - move to the next line
107  */
108 void
vMove2NextLineTXT(diagram_type * pDiag)109 vMove2NextLineTXT(diagram_type *pDiag)
110 {
111 	fail(pDiag == NULL);
112 	fail(pDiag->pOutFile == NULL);
113 
114 	pDiag->lYtop++;
115 	(void)fprintf(pDiag->pOutFile, "\n");
116 } /* end of vMove2NextLineTXT */
117 
118 /*
119  * vSubstringTXT - print a sub string
120  */
121 void
vSubstringTXT(diagram_type * pDiag,const char * szString,size_t tStringLength,long lStringWidth)122 vSubstringTXT(diagram_type *pDiag,
123 	const char *szString, size_t tStringLength, long lStringWidth)
124 {
125 	fail(pDiag == NULL || szString == NULL);
126 	fail(pDiag->pOutFile == NULL);
127 	fail(pDiag->lXleft < 0);
128 	fail(tStringLength != strlen(szString));
129 
130 	if (szString[0] == '\0' || tStringLength == 0) {
131 		return;
132 	}
133 
134 	vMoveTo(pDiag);
135 	vPrintTXT(pDiag->pOutFile, szString, tStringLength);
136 	pDiag->lXleft += lStringWidth;
137 } /* end of vSubstringTXT */
138 
139 /*
140  * Create an start of paragraph by moving the y-top mark
141  */
142 void
vStartOfParagraphTXT(diagram_type * pDiag,long lBeforeIndentation)143 vStartOfParagraphTXT(diagram_type *pDiag, long lBeforeIndentation)
144 {
145 	fail(pDiag == NULL);
146 	fail(lBeforeIndentation < 0);
147 
148 	if (lBeforeIndentation >= lTwips2MilliPoints(HEADING_GAP)) {
149 		/* A large gap is replaced by an empty line */
150 		vMove2NextLineTXT(pDiag);
151 	}
152 } /* end of vStartOfParagraphTXT */
153 
154 /*
155  * Create an end of paragraph by moving the y-top mark
156  */
157 void
vEndOfParagraphTXT(diagram_type * pDiag,long lAfterIndentation)158 vEndOfParagraphTXT(diagram_type *pDiag, long lAfterIndentation)
159 {
160 	fail(pDiag == NULL);
161 	fail(pDiag->pOutFile == NULL);
162 	fail(lAfterIndentation < 0);
163 
164 	if (pDiag->lXleft > 0) {
165 		/* To the start of the line */
166 		vMove2NextLineTXT(pDiag);
167 	}
168 
169 	if (lAfterIndentation >= lTwips2MilliPoints(HEADING_GAP)) {
170 		/* A large gap is replaced by an empty line */
171 		vMove2NextLineTXT(pDiag);
172 	}
173 } /* end of vEndOfParagraphTXT */
174 
175 /*
176  * Create an end of page
177  */
178 void
vEndOfPageTXT(diagram_type * pDiag,long lAfterIndentation)179 vEndOfPageTXT(diagram_type *pDiag, long lAfterIndentation)
180 {
181 	vEndOfParagraphTXT(pDiag, lAfterIndentation);
182 } /* end of vEndOfPageTXT */
183