xref: /plan9/sys/src/cmd/aux/antiword/fmt_text.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1*25b329d5SDavid du Colombier /*
2*25b329d5SDavid du Colombier  * fmt_text.c
3*25b329d5SDavid du Colombier  * Copyright (C) 2004 A.J. van Os; Released under GNU GPL
4*25b329d5SDavid du Colombier  *
5*25b329d5SDavid du Colombier  * Description:
6*25b329d5SDavid du Colombier  * Functions to deal with the Formatted Text format
7*25b329d5SDavid du Colombier  *
8*25b329d5SDavid du Colombier  * Based on patches send by: Ofir Reichenberg <ofir@qlusters.com>
9*25b329d5SDavid du Colombier  *
10*25b329d5SDavid du Colombier  * The credit should go to him, but all the bugs are mine.
11*25b329d5SDavid du Colombier  */
12*25b329d5SDavid du Colombier 
13*25b329d5SDavid du Colombier #include <string.h>
14*25b329d5SDavid du Colombier #include "antiword.h"
15*25b329d5SDavid du Colombier 
16*25b329d5SDavid du Colombier /* The character set */
17*25b329d5SDavid du Colombier static encoding_type	eEncoding = encoding_neutral;
18*25b329d5SDavid du Colombier /* Current vertical position information */
19*25b329d5SDavid du Colombier static long		lYtopCurr = 0;
20*25b329d5SDavid du Colombier /* Local representation of the non-breaking space */
21*25b329d5SDavid du Colombier static UCHAR		ucNbsp = 0;
22*25b329d5SDavid du Colombier 
23*25b329d5SDavid du Colombier 
24*25b329d5SDavid du Colombier /*
25*25b329d5SDavid du Colombier  * vPrologueFMT - set options and perform the Formatted Text initialization
26*25b329d5SDavid du Colombier  */
27*25b329d5SDavid du Colombier void
vPrologueFMT(diagram_type * pDiag,const options_type * pOptions)28*25b329d5SDavid du Colombier vPrologueFMT(diagram_type *pDiag, const options_type *pOptions)
29*25b329d5SDavid du Colombier {
30*25b329d5SDavid du Colombier 	fail(pDiag == NULL);
31*25b329d5SDavid du Colombier 	fail(pOptions == NULL);
32*25b329d5SDavid du Colombier 
33*25b329d5SDavid du Colombier 	eEncoding = pOptions->eEncoding;
34*25b329d5SDavid du Colombier 	pDiag->lXleft = 0;
35*25b329d5SDavid du Colombier 	pDiag->lYtop = 0;
36*25b329d5SDavid du Colombier 	lYtopCurr = 0;
37*25b329d5SDavid du Colombier } /* end of vPrologueFMT */
38*25b329d5SDavid du Colombier 
39*25b329d5SDavid du Colombier /*
40*25b329d5SDavid du Colombier  * vPrintFMT - print a Formatted Text string
41*25b329d5SDavid du Colombier  */
42*25b329d5SDavid du Colombier static void
vPrintFMT(FILE * pFile,const char * szString,size_t tStringLength,USHORT usFontstyle)43*25b329d5SDavid du Colombier vPrintFMT(FILE *pFile,
44*25b329d5SDavid du Colombier 	const char *szString, size_t tStringLength, USHORT usFontstyle)
45*25b329d5SDavid du Colombier {
46*25b329d5SDavid du Colombier 	const UCHAR	*pucByte, *pucStart, *pucLast, *pucNonSpace;
47*25b329d5SDavid du Colombier 
48*25b329d5SDavid du Colombier 	fail(szString == NULL);
49*25b329d5SDavid du Colombier 
50*25b329d5SDavid du Colombier 	if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
51*25b329d5SDavid du Colombier 		return;
52*25b329d5SDavid du Colombier 	}
53*25b329d5SDavid du Colombier 
54*25b329d5SDavid du Colombier 	if (eEncoding == encoding_utf_8) {
55*25b329d5SDavid du Colombier 		fprintf(pFile, "%.*s", (int)tStringLength, szString);
56*25b329d5SDavid du Colombier 		return;
57*25b329d5SDavid du Colombier 	}
58*25b329d5SDavid du Colombier 
59*25b329d5SDavid du Colombier 	if (ucNbsp == 0) {
60*25b329d5SDavid du Colombier 		ucNbsp = ucGetNbspCharacter();
61*25b329d5SDavid du Colombier 		DBG_HEX_C(ucNbsp != 0xa0, ucNbsp);
62*25b329d5SDavid du Colombier 	}
63*25b329d5SDavid du Colombier 
64*25b329d5SDavid du Colombier 	pucStart = (UCHAR *)szString;
65*25b329d5SDavid du Colombier 	pucLast = pucStart + tStringLength - 1;
66*25b329d5SDavid du Colombier 	pucNonSpace = pucLast;
67*25b329d5SDavid du Colombier 	while ((*pucNonSpace == (UCHAR)' ' || *pucNonSpace == ucNbsp) &&
68*25b329d5SDavid du Colombier 	       pucNonSpace > pucStart) {
69*25b329d5SDavid du Colombier 		pucNonSpace--;
70*25b329d5SDavid du Colombier 	}
71*25b329d5SDavid du Colombier 
72*25b329d5SDavid du Colombier 	/* 1: The spaces at the start */
73*25b329d5SDavid du Colombier 	pucByte = pucStart;
74*25b329d5SDavid du Colombier 	while ((*pucByte == (UCHAR)' ' || *pucByte == ucNbsp) &&
75*25b329d5SDavid du Colombier 	       pucByte <= pucLast) {
76*25b329d5SDavid du Colombier 		(void)putc(' ', pFile);
77*25b329d5SDavid du Colombier 		pucByte++;
78*25b329d5SDavid du Colombier 	}
79*25b329d5SDavid du Colombier 
80*25b329d5SDavid du Colombier 	if (pucByte > pucLast) {
81*25b329d5SDavid du Colombier 		/* There is no text, just spaces */
82*25b329d5SDavid du Colombier 		return;
83*25b329d5SDavid du Colombier 	}
84*25b329d5SDavid du Colombier 
85*25b329d5SDavid du Colombier 	/* 2: Start the *bold*, /italic/ and _underline_ */
86*25b329d5SDavid du Colombier 	if (bIsBold(usFontstyle)) {
87*25b329d5SDavid du Colombier 		(void)putc('*', pFile);
88*25b329d5SDavid du Colombier 	}
89*25b329d5SDavid du Colombier 	if (bIsItalic(usFontstyle)) {
90*25b329d5SDavid du Colombier 		(void)putc('/', pFile);
91*25b329d5SDavid du Colombier 	}
92*25b329d5SDavid du Colombier 	if (bIsUnderline(usFontstyle)) {
93*25b329d5SDavid du Colombier 		(void)putc('_', pFile);
94*25b329d5SDavid du Colombier 	}
95*25b329d5SDavid du Colombier 
96*25b329d5SDavid du Colombier 	/* 3: The text itself */
97*25b329d5SDavid du Colombier 	while (pucByte <= pucNonSpace) {
98*25b329d5SDavid du Colombier 		if (*pucByte == ucNbsp) {
99*25b329d5SDavid du Colombier 			(void)putc(' ', pFile);
100*25b329d5SDavid du Colombier 		} else {
101*25b329d5SDavid du Colombier 			(void)putc((char)*pucByte, pFile);
102*25b329d5SDavid du Colombier 		}
103*25b329d5SDavid du Colombier 		pucByte++;
104*25b329d5SDavid du Colombier 	}
105*25b329d5SDavid du Colombier 
106*25b329d5SDavid du Colombier 	/* 4: End the *bold*, /italic/ and _underline_ */
107*25b329d5SDavid du Colombier 	if (bIsUnderline(usFontstyle)) {
108*25b329d5SDavid du Colombier 		(void)putc('_', pFile);
109*25b329d5SDavid du Colombier 	}
110*25b329d5SDavid du Colombier 	if (bIsItalic(usFontstyle)) {
111*25b329d5SDavid du Colombier 		(void)putc('/', pFile);
112*25b329d5SDavid du Colombier 	}
113*25b329d5SDavid du Colombier 	if (bIsBold(usFontstyle)) {
114*25b329d5SDavid du Colombier 		(void)putc('*', pFile);
115*25b329d5SDavid du Colombier 	}
116*25b329d5SDavid du Colombier 
117*25b329d5SDavid du Colombier 	/* 5: The spaces at the end */
118*25b329d5SDavid du Colombier 	while (pucByte <= pucLast) {
119*25b329d5SDavid du Colombier 		(void)putc(' ', pFile);
120*25b329d5SDavid du Colombier 		pucByte++;
121*25b329d5SDavid du Colombier 	}
122*25b329d5SDavid du Colombier } /* end of vPrintFMT */
123*25b329d5SDavid du Colombier 
124*25b329d5SDavid du Colombier /*
125*25b329d5SDavid du Colombier  * vMoveTo - move to the given X,Y coordinates
126*25b329d5SDavid du Colombier  *
127*25b329d5SDavid du Colombier  * Move the current position of the given diagram to its X,Y coordinates,
128*25b329d5SDavid du Colombier  * start on a new page if needed
129*25b329d5SDavid du Colombier  */
130*25b329d5SDavid du Colombier static void
vMoveTo(diagram_type * pDiag)131*25b329d5SDavid du Colombier vMoveTo(diagram_type *pDiag)
132*25b329d5SDavid du Colombier {
133*25b329d5SDavid du Colombier 	int	iCount, iNbr;
134*25b329d5SDavid du Colombier 
135*25b329d5SDavid du Colombier 	fail(pDiag == NULL);
136*25b329d5SDavid du Colombier 	fail(pDiag->pOutFile == NULL);
137*25b329d5SDavid du Colombier 
138*25b329d5SDavid du Colombier 	if (pDiag->lYtop != lYtopCurr) {
139*25b329d5SDavid du Colombier 		iNbr = iDrawUnits2Char(pDiag->lXleft);
140*25b329d5SDavid du Colombier 		for (iCount = 0; iCount < iNbr; iCount++) {
141*25b329d5SDavid du Colombier 			(void)putc(FILLER_CHAR, pDiag->pOutFile);
142*25b329d5SDavid du Colombier 		}
143*25b329d5SDavid du Colombier 		lYtopCurr = pDiag->lYtop;
144*25b329d5SDavid du Colombier 	}
145*25b329d5SDavid du Colombier } /* end of vMoveTo */
146*25b329d5SDavid du Colombier 
147*25b329d5SDavid du Colombier /*
148*25b329d5SDavid du Colombier  * vSubstringFMT - print a sub string
149*25b329d5SDavid du Colombier  */
150*25b329d5SDavid du Colombier void
vSubstringFMT(diagram_type * pDiag,const char * szString,size_t tStringLength,long lStringWidth,USHORT usFontstyle)151*25b329d5SDavid du Colombier vSubstringFMT(diagram_type *pDiag,
152*25b329d5SDavid du Colombier 	const char *szString, size_t tStringLength, long lStringWidth,
153*25b329d5SDavid du Colombier 	USHORT usFontstyle)
154*25b329d5SDavid du Colombier {
155*25b329d5SDavid du Colombier 	fail(pDiag == NULL || szString == NULL);
156*25b329d5SDavid du Colombier 	fail(pDiag->pOutFile == NULL);
157*25b329d5SDavid du Colombier 	fail(pDiag->lXleft < 0);
158*25b329d5SDavid du Colombier 	fail(tStringLength != strlen(szString));
159*25b329d5SDavid du Colombier 
160*25b329d5SDavid du Colombier 	if (szString[0] == '\0' || tStringLength == 0) {
161*25b329d5SDavid du Colombier 		return;
162*25b329d5SDavid du Colombier 	}
163*25b329d5SDavid du Colombier 
164*25b329d5SDavid du Colombier 	vMoveTo(pDiag);
165*25b329d5SDavid du Colombier 	vPrintFMT(pDiag->pOutFile, szString, tStringLength, usFontstyle);
166*25b329d5SDavid du Colombier 	pDiag->lXleft += lStringWidth;
167*25b329d5SDavid du Colombier } /* end of vSubstringFMT */
168