xref: /plan9/sys/src/cmd/aux/antiword/out2window.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1f5736e95SDavid du Colombier /*
2f5736e95SDavid du Colombier  * out2window.c
3*25b329d5SDavid du Colombier  * Copyright (C) 1998-2005 A.J. van Os; Released under GPL
4f5736e95SDavid du Colombier  *
5f5736e95SDavid du Colombier  * Description:
6f5736e95SDavid du Colombier  * Output to a text window
7f5736e95SDavid du Colombier  */
8f5736e95SDavid du Colombier 
9f5736e95SDavid du Colombier #include <string.h>
10f5736e95SDavid du Colombier #include <stdlib.h>
11f5736e95SDavid du Colombier #include <ctype.h>
12f5736e95SDavid du Colombier #include "antiword.h"
13f5736e95SDavid du Colombier 
14f5736e95SDavid du Colombier /* Used for numbering the chapters */
15f5736e95SDavid du Colombier static unsigned int	auiHdrCounter[9];
16f5736e95SDavid du Colombier 
17f5736e95SDavid du Colombier 
18f5736e95SDavid du Colombier /*
19f5736e95SDavid du Colombier  * vString2Diagram - put a string into a diagram
20f5736e95SDavid du Colombier  */
21f5736e95SDavid du Colombier static void
vString2Diagram(diagram_type * pDiag,output_type * pAnchor)22f5736e95SDavid du Colombier vString2Diagram(diagram_type *pDiag, output_type *pAnchor)
23f5736e95SDavid du Colombier {
24f5736e95SDavid du Colombier 	output_type	*pOutput;
25f5736e95SDavid du Colombier 	long		lWidth;
26f5736e95SDavid du Colombier 	USHORT		usMaxFontSize;
27f5736e95SDavid du Colombier 
28*25b329d5SDavid du Colombier 	TRACE_MSG("vString2Diagram");
29*25b329d5SDavid du Colombier 
30f5736e95SDavid du Colombier 	fail(pDiag == NULL);
31f5736e95SDavid du Colombier 	fail(pAnchor == NULL);
32f5736e95SDavid du Colombier 
33f5736e95SDavid du Colombier 	/* Compute the maximum fontsize in this string */
34f5736e95SDavid du Colombier 	usMaxFontSize = MIN_FONT_SIZE;
35f5736e95SDavid du Colombier 	for (pOutput = pAnchor; pOutput != NULL; pOutput = pOutput->pNext) {
36f5736e95SDavid du Colombier 		if (pOutput->usFontSize > usMaxFontSize) {
37f5736e95SDavid du Colombier 			usMaxFontSize = pOutput->usFontSize;
38f5736e95SDavid du Colombier 		}
39f5736e95SDavid du Colombier 	}
40f5736e95SDavid du Colombier 
41f5736e95SDavid du Colombier 	/* Goto the next line */
42f5736e95SDavid du Colombier 	vMove2NextLine(pDiag, pAnchor->tFontRef, usMaxFontSize);
43f5736e95SDavid du Colombier 
44f5736e95SDavid du Colombier 	/* Output all substrings */
45f5736e95SDavid du Colombier 	for (pOutput = pAnchor; pOutput != NULL; pOutput = pOutput->pNext) {
46f5736e95SDavid du Colombier 		lWidth = lMilliPoints2DrawUnits(pOutput->lStringWidth);
47f5736e95SDavid du Colombier 		vSubstring2Diagram(pDiag, pOutput->szStorage,
48f5736e95SDavid du Colombier 			pOutput->tNextFree, lWidth, pOutput->ucFontColor,
49f5736e95SDavid du Colombier 			pOutput->usFontStyle, pOutput->tFontRef,
50f5736e95SDavid du Colombier 			pOutput->usFontSize, usMaxFontSize);
51f5736e95SDavid du Colombier 	}
52f5736e95SDavid du Colombier 
53f5736e95SDavid du Colombier 	/* Goto the start of the line */
54f5736e95SDavid du Colombier 	pDiag->lXleft = 0;
55*25b329d5SDavid du Colombier 	TRACE_MSG("leaving vString2Diagram");
56f5736e95SDavid du Colombier } /* end of vString2Diagram */
57f5736e95SDavid du Colombier 
58f5736e95SDavid du Colombier /*
59f5736e95SDavid du Colombier  * vSetLeftIndentation - set the left indentation of the specified diagram
60f5736e95SDavid du Colombier  */
61f5736e95SDavid du Colombier void
vSetLeftIndentation(diagram_type * pDiag,long lLeftIndentation)62f5736e95SDavid du Colombier vSetLeftIndentation(diagram_type *pDiag, long lLeftIndentation)
63f5736e95SDavid du Colombier {
64f5736e95SDavid du Colombier 	long	lX;
65f5736e95SDavid du Colombier 
66*25b329d5SDavid du Colombier 	TRACE_MSG("vSetLeftIndentation");
67*25b329d5SDavid du Colombier 
68f5736e95SDavid du Colombier 	fail(pDiag == NULL);
69f5736e95SDavid du Colombier 	fail(lLeftIndentation < 0);
70f5736e95SDavid du Colombier 
71f5736e95SDavid du Colombier 	lX = lMilliPoints2DrawUnits(lLeftIndentation);
72f5736e95SDavid du Colombier 	if (lX > 0) {
73f5736e95SDavid du Colombier 		pDiag->lXleft = lX;
74f5736e95SDavid du Colombier 	} else {
75f5736e95SDavid du Colombier 		pDiag->lXleft = 0;
76f5736e95SDavid du Colombier 	}
77f5736e95SDavid du Colombier } /* end of vSetLeftIndentation */
78f5736e95SDavid du Colombier 
79f5736e95SDavid du Colombier /*
80f5736e95SDavid du Colombier  * lComputeNetWidth - compute the net string width
81f5736e95SDavid du Colombier  */
82f5736e95SDavid du Colombier static long
lComputeNetWidth(output_type * pAnchor)83f5736e95SDavid du Colombier lComputeNetWidth(output_type *pAnchor)
84f5736e95SDavid du Colombier {
85f5736e95SDavid du Colombier 	output_type	*pTmp;
86f5736e95SDavid du Colombier 	long		lNetWidth;
87f5736e95SDavid du Colombier 
88*25b329d5SDavid du Colombier 	TRACE_MSG("lComputeNetWidth");
89*25b329d5SDavid du Colombier 
90f5736e95SDavid du Colombier 	fail(pAnchor == NULL);
91f5736e95SDavid du Colombier 
92f5736e95SDavid du Colombier 	/* Step 1: Count all but the last sub-string */
93f5736e95SDavid du Colombier 	lNetWidth = 0;
94f5736e95SDavid du Colombier 	for (pTmp = pAnchor; pTmp->pNext != NULL; pTmp = pTmp->pNext) {
95f5736e95SDavid du Colombier 		fail(pTmp->lStringWidth < 0);
96f5736e95SDavid du Colombier 		lNetWidth += pTmp->lStringWidth;
97f5736e95SDavid du Colombier 	}
98f5736e95SDavid du Colombier 	fail(pTmp == NULL);
99f5736e95SDavid du Colombier 	fail(pTmp->pNext != NULL);
100f5736e95SDavid du Colombier 
101f5736e95SDavid du Colombier 	/* Step 2: remove the white-space from the end of the string */
102f5736e95SDavid du Colombier 	while (pTmp->tNextFree != 0 &&
103f5736e95SDavid du Colombier 	       isspace((int)(UCHAR)pTmp->szStorage[pTmp->tNextFree - 1])) {
104f5736e95SDavid du Colombier 		pTmp->szStorage[pTmp->tNextFree - 1] = '\0';
105f5736e95SDavid du Colombier 		pTmp->tNextFree--;
106f5736e95SDavid du Colombier 		NO_DBG_DEC(pTmp->lStringWidth);
107f5736e95SDavid du Colombier 		pTmp->lStringWidth = lComputeStringWidth(
108f5736e95SDavid du Colombier 						pTmp->szStorage,
109f5736e95SDavid du Colombier 						pTmp->tNextFree,
110f5736e95SDavid du Colombier 						pTmp->tFontRef,
111f5736e95SDavid du Colombier 						pTmp->usFontSize);
112f5736e95SDavid du Colombier 		NO_DBG_DEC(pTmp->lStringWidth);
113f5736e95SDavid du Colombier 	}
114f5736e95SDavid du Colombier 
115f5736e95SDavid du Colombier 	/* Step 3: Count the last sub-string */
116f5736e95SDavid du Colombier 	lNetWidth += pTmp->lStringWidth;
117f5736e95SDavid du Colombier 	return lNetWidth;
118f5736e95SDavid du Colombier } /* end of lComputeNetWidth */
119f5736e95SDavid du Colombier 
120f5736e95SDavid du Colombier /*
121f5736e95SDavid du Colombier  * iComputeHoles - compute number of holes
122f5736e95SDavid du Colombier  * (A hole is a number of whitespace characters followed by a
123f5736e95SDavid du Colombier  *  non-whitespace character)
124f5736e95SDavid du Colombier  */
125f5736e95SDavid du Colombier static int
iComputeHoles(output_type * pAnchor)126f5736e95SDavid du Colombier iComputeHoles(output_type *pAnchor)
127f5736e95SDavid du Colombier {
128f5736e95SDavid du Colombier 	output_type	*pTmp;
129f5736e95SDavid du Colombier 	size_t	tIndex;
130f5736e95SDavid du Colombier 	int	iCounter;
131f5736e95SDavid du Colombier 	BOOL	bWasSpace, bIsSpace;
132f5736e95SDavid du Colombier 
133*25b329d5SDavid du Colombier 	TRACE_MSG("iComputeHoles");
134*25b329d5SDavid du Colombier 
135f5736e95SDavid du Colombier 	fail(pAnchor == NULL);
136f5736e95SDavid du Colombier 
137f5736e95SDavid du Colombier 	iCounter = 0;
138f5736e95SDavid du Colombier 	bIsSpace = FALSE;
139f5736e95SDavid du Colombier 	/* Count the holes */
140f5736e95SDavid du Colombier 	for (pTmp = pAnchor; pTmp != NULL; pTmp = pTmp->pNext) {
141f5736e95SDavid du Colombier 		fail(pTmp->tNextFree != strlen(pTmp->szStorage));
142f5736e95SDavid du Colombier 		for (tIndex = 0; tIndex <= pTmp->tNextFree; tIndex++) {
143f5736e95SDavid du Colombier 			bWasSpace = bIsSpace;
144f5736e95SDavid du Colombier 			bIsSpace = isspace((int)(UCHAR)pTmp->szStorage[tIndex]);
145f5736e95SDavid du Colombier 			if (bWasSpace && !bIsSpace) {
146f5736e95SDavid du Colombier 				iCounter++;
147f5736e95SDavid du Colombier 			}
148f5736e95SDavid du Colombier 		}
149f5736e95SDavid du Colombier 	}
150f5736e95SDavid du Colombier 	return iCounter;
151f5736e95SDavid du Colombier } /* end of iComputeHoles */
152f5736e95SDavid du Colombier 
153f5736e95SDavid du Colombier /*
154*25b329d5SDavid du Colombier  * vAlign2Window - Align a string and insert it into the text
155f5736e95SDavid du Colombier  */
156f5736e95SDavid du Colombier void
vAlign2Window(diagram_type * pDiag,output_type * pAnchor,long lScreenWidth,UCHAR ucAlignment)157f5736e95SDavid du Colombier vAlign2Window(diagram_type *pDiag, output_type *pAnchor,
158f5736e95SDavid du Colombier 	long lScreenWidth, UCHAR ucAlignment)
159f5736e95SDavid du Colombier {
160f5736e95SDavid du Colombier 	long	lNetWidth, lLeftIndentation;
161f5736e95SDavid du Colombier 
162*25b329d5SDavid du Colombier 	TRACE_MSG("vAlign2Window");
163*25b329d5SDavid du Colombier 
164f5736e95SDavid du Colombier 	fail(pDiag == NULL || pAnchor == NULL);
165f5736e95SDavid du Colombier 	fail(lScreenWidth < lChar2MilliPoints(MIN_SCREEN_WIDTH));
166f5736e95SDavid du Colombier 
167f5736e95SDavid du Colombier 	lNetWidth = lComputeNetWidth(pAnchor);
168f5736e95SDavid du Colombier 
169f5736e95SDavid du Colombier 	if (lScreenWidth > lChar2MilliPoints(MAX_SCREEN_WIDTH) ||
170f5736e95SDavid du Colombier 	    lNetWidth <= 0) {
171f5736e95SDavid du Colombier 		/*
172f5736e95SDavid du Colombier 		 * Screenwidth is "infinite", so no alignment is possible
173f5736e95SDavid du Colombier 		 * Don't bother to align an empty line
174f5736e95SDavid du Colombier 		 */
175f5736e95SDavid du Colombier 		vString2Diagram(pDiag, pAnchor);
176*25b329d5SDavid du Colombier 		TRACE_MSG("leaving vAlign2Window #1");
177f5736e95SDavid du Colombier 		return;
178f5736e95SDavid du Colombier 	}
179f5736e95SDavid du Colombier 
180f5736e95SDavid du Colombier 	switch (ucAlignment) {
181f5736e95SDavid du Colombier 	case ALIGNMENT_CENTER:
182f5736e95SDavid du Colombier 		lLeftIndentation = (lScreenWidth - lNetWidth) / 2;
183f5736e95SDavid du Colombier 		DBG_DEC_C(lLeftIndentation < 0, lLeftIndentation);
184f5736e95SDavid du Colombier 		if (lLeftIndentation > 0) {
185f5736e95SDavid du Colombier 			vSetLeftIndentation(pDiag, lLeftIndentation);
186f5736e95SDavid du Colombier 		}
187f5736e95SDavid du Colombier 		break;
188f5736e95SDavid du Colombier 	case ALIGNMENT_RIGHT:
189f5736e95SDavid du Colombier 		lLeftIndentation = lScreenWidth - lNetWidth;
190f5736e95SDavid du Colombier 		DBG_DEC_C(lLeftIndentation < 0, lLeftIndentation);
191f5736e95SDavid du Colombier 		if (lLeftIndentation > 0) {
192f5736e95SDavid du Colombier 			vSetLeftIndentation(pDiag, lLeftIndentation);
193f5736e95SDavid du Colombier 		}
194f5736e95SDavid du Colombier 		break;
195f5736e95SDavid du Colombier 	case ALIGNMENT_JUSTIFY:
196f5736e95SDavid du Colombier 	case ALIGNMENT_LEFT:
197f5736e95SDavid du Colombier 	default:
198f5736e95SDavid du Colombier 		break;
199f5736e95SDavid du Colombier 	}
200f5736e95SDavid du Colombier 	vString2Diagram(pDiag, pAnchor);
201*25b329d5SDavid du Colombier 	TRACE_MSG("leaving vAlign2Window #2");
202f5736e95SDavid du Colombier } /* end of vAlign2Window */
203f5736e95SDavid du Colombier 
204f5736e95SDavid du Colombier /*
205*25b329d5SDavid du Colombier  * vJustify2Window - Justify a string and insert it into the text
206f5736e95SDavid du Colombier  */
207f5736e95SDavid du Colombier void
vJustify2Window(diagram_type * pDiag,output_type * pAnchor,long lScreenWidth,long lRightIndentation,UCHAR ucAlignment)208f5736e95SDavid du Colombier vJustify2Window(diagram_type *pDiag, output_type *pAnchor,
209f5736e95SDavid du Colombier 	long lScreenWidth, long lRightIndentation, UCHAR ucAlignment)
210f5736e95SDavid du Colombier {
211f5736e95SDavid du Colombier 	output_type	*pTmp;
212f5736e95SDavid du Colombier 	char	*pcNew, *pcOld, *szStorage;
213f5736e95SDavid du Colombier 	long	lNetWidth, lSpaceWidth, lToAdd;
214f5736e95SDavid du Colombier 	int	iFillerLen, iHoles;
215f5736e95SDavid du Colombier 
216*25b329d5SDavid du Colombier 	TRACE_MSG("vJustify2Window");
217*25b329d5SDavid du Colombier 
218f5736e95SDavid du Colombier 	fail(pDiag == NULL || pAnchor == NULL);
219f5736e95SDavid du Colombier 	fail(lScreenWidth < MIN_SCREEN_WIDTH);
220f5736e95SDavid du Colombier 	fail(lRightIndentation > 0);
221f5736e95SDavid du Colombier 
222f5736e95SDavid du Colombier 	if (ucAlignment != ALIGNMENT_JUSTIFY) {
223f5736e95SDavid du Colombier 		vAlign2Window(pDiag, pAnchor, lScreenWidth, ucAlignment);
224f5736e95SDavid du Colombier 		return;
225f5736e95SDavid du Colombier 	}
226f5736e95SDavid du Colombier 
227f5736e95SDavid du Colombier 	lNetWidth = lComputeNetWidth(pAnchor);
228f5736e95SDavid du Colombier 
229f5736e95SDavid du Colombier 	if (lScreenWidth > lChar2MilliPoints(MAX_SCREEN_WIDTH) ||
230f5736e95SDavid du Colombier 	    lNetWidth <= 0) {
231f5736e95SDavid du Colombier 		/*
232f5736e95SDavid du Colombier 		 * Screenwidth is "infinite", so justify is not possible
233*25b329d5SDavid du Colombier 		 * Don't bother to justify an empty line
234f5736e95SDavid du Colombier 		 */
235f5736e95SDavid du Colombier 		vString2Diagram(pDiag, pAnchor);
236*25b329d5SDavid du Colombier 		TRACE_MSG("leaving vJustify2Window #1");
237f5736e95SDavid du Colombier 		return;
238f5736e95SDavid du Colombier 	}
239f5736e95SDavid du Colombier 
240f5736e95SDavid du Colombier 	/* Justify */
241f5736e95SDavid du Colombier 	fail(ucAlignment != ALIGNMENT_JUSTIFY);
242f5736e95SDavid du Colombier 	lSpaceWidth = lComputeStringWidth(" ", 1,
243f5736e95SDavid du Colombier 				pAnchor->tFontRef, pAnchor->usFontSize);
244f5736e95SDavid du Colombier 	lToAdd = lScreenWidth -
245f5736e95SDavid du Colombier 			lNetWidth -
246f5736e95SDavid du Colombier 			lDrawUnits2MilliPoints(pDiag->lXleft) +
247f5736e95SDavid du Colombier 			lRightIndentation;
248f5736e95SDavid du Colombier #if defined(DEBUG)
249f5736e95SDavid du Colombier 	if (lToAdd / lSpaceWidth < -1) {
250f5736e95SDavid du Colombier 		DBG_DEC(lSpaceWidth);
251f5736e95SDavid du Colombier 		DBG_DEC(lToAdd);
252f5736e95SDavid du Colombier 		DBG_DEC(lScreenWidth);
253f5736e95SDavid du Colombier 		DBG_DEC(lNetWidth);
254f5736e95SDavid du Colombier 		DBG_DEC(lDrawUnits2MilliPoints(pDiag->lXleft));
255f5736e95SDavid du Colombier 		DBG_DEC(pDiag->lXleft);
256f5736e95SDavid du Colombier 		DBG_DEC(lRightIndentation);
257f5736e95SDavid du Colombier 	}
258f5736e95SDavid du Colombier #endif /* DEBUG */
259f5736e95SDavid du Colombier 	lToAdd /= lSpaceWidth;
260f5736e95SDavid du Colombier 	DBG_DEC_C(lToAdd < 0, lToAdd);
261f5736e95SDavid du Colombier 	if (lToAdd <= 0) {
262f5736e95SDavid du Colombier 		vString2Diagram(pDiag, pAnchor);
263*25b329d5SDavid du Colombier 		TRACE_MSG("leaving vJustify2Window #2");
264f5736e95SDavid du Colombier 		return;
265f5736e95SDavid du Colombier 	}
266f5736e95SDavid du Colombier 
267f5736e95SDavid du Colombier 	/* Justify by adding spaces */
268*25b329d5SDavid du Colombier 	iHoles = iComputeHoles(pAnchor);
269f5736e95SDavid du Colombier 	for (pTmp = pAnchor; pTmp != NULL; pTmp = pTmp->pNext) {
270f5736e95SDavid du Colombier 		fail(pTmp->tNextFree != strlen(pTmp->szStorage));
271f5736e95SDavid du Colombier 		fail(lToAdd < 0);
272f5736e95SDavid du Colombier 		szStorage = xmalloc(pTmp->tNextFree + (size_t)lToAdd + 1);
273f5736e95SDavid du Colombier 		pcNew = szStorage;
274f5736e95SDavid du Colombier 		for (pcOld = pTmp->szStorage; *pcOld != '\0'; pcOld++) {
275f5736e95SDavid du Colombier 			*pcNew++ = *pcOld;
276f5736e95SDavid du Colombier 			if (*pcOld == ' ' &&
277f5736e95SDavid du Colombier 			    *(pcOld + 1) != ' ' &&
278f5736e95SDavid du Colombier 			    iHoles > 0) {
279f5736e95SDavid du Colombier 				iFillerLen = (int)(lToAdd / iHoles);
280f5736e95SDavid du Colombier 				lToAdd -= iFillerLen;
281f5736e95SDavid du Colombier 				iHoles--;
282f5736e95SDavid du Colombier 				for (; iFillerLen > 0; iFillerLen--) {
283f5736e95SDavid du Colombier 					*pcNew++ = ' ';
284f5736e95SDavid du Colombier 				}
285f5736e95SDavid du Colombier 			}
286f5736e95SDavid du Colombier 		}
287f5736e95SDavid du Colombier 		*pcNew = '\0';
288f5736e95SDavid du Colombier 		pTmp->szStorage = xfree(pTmp->szStorage);
289f5736e95SDavid du Colombier 		pTmp->szStorage = szStorage;
290f5736e95SDavid du Colombier 		pTmp->tStorageSize = pTmp->tNextFree + (size_t)lToAdd + 1;
291f5736e95SDavid du Colombier 		pTmp->lStringWidth +=
292f5736e95SDavid du Colombier 			(pcNew - szStorage - (long)pTmp->tNextFree) *
293f5736e95SDavid du Colombier 			lSpaceWidth;
294f5736e95SDavid du Colombier 		fail(pcNew < szStorage);
295f5736e95SDavid du Colombier 		pTmp->tNextFree = (size_t)(pcNew - szStorage);
296f5736e95SDavid du Colombier 		fail(pTmp->tNextFree != strlen(pTmp->szStorage));
297f5736e95SDavid du Colombier 	}
298f5736e95SDavid du Colombier 	DBG_DEC_C(lToAdd != 0, lToAdd);
299f5736e95SDavid du Colombier 	vString2Diagram(pDiag, pAnchor);
300*25b329d5SDavid du Colombier 	TRACE_MSG("leaving vJustify2Window #3");
301f5736e95SDavid du Colombier } /* end of vJustify2Window */
302f5736e95SDavid du Colombier 
303f5736e95SDavid du Colombier /*
304f5736e95SDavid du Colombier  * vResetStyles - reset the style information variables
305f5736e95SDavid du Colombier  */
306f5736e95SDavid du Colombier void
vResetStyles(void)307f5736e95SDavid du Colombier vResetStyles(void)
308f5736e95SDavid du Colombier {
309*25b329d5SDavid du Colombier 	TRACE_MSG("vResetStyles");
310*25b329d5SDavid du Colombier 
311f5736e95SDavid du Colombier 	(void)memset(auiHdrCounter, 0, sizeof(auiHdrCounter));
312f5736e95SDavid du Colombier } /* end of vResetStyles */
313f5736e95SDavid du Colombier 
314f5736e95SDavid du Colombier /*
315*25b329d5SDavid du Colombier  * tStyle2Window - Add the style characters to the line
316f5736e95SDavid du Colombier  *
317f5736e95SDavid du Colombier  * Returns the length of the resulting string
318f5736e95SDavid du Colombier  */
319f5736e95SDavid du Colombier size_t
tStyle2Window(char * szLine,size_t tLineSize,const style_block_type * pStyle,const section_block_type * pSection)320*25b329d5SDavid du Colombier tStyle2Window(char *szLine, size_t tLineSize, const style_block_type *pStyle,
321f5736e95SDavid du Colombier 	const section_block_type *pSection)
322f5736e95SDavid du Colombier {
323f5736e95SDavid du Colombier 	char	*pcTxt;
324*25b329d5SDavid du Colombier 	size_t	tIndex, tStyleIndex;
325f5736e95SDavid du Colombier 	BOOL	bNeedPrevLvl;
326f5736e95SDavid du Colombier 	level_type_enum	eNumType;
327f5736e95SDavid du Colombier 	UCHAR	ucNFC;
328f5736e95SDavid du Colombier 
329*25b329d5SDavid du Colombier 	TRACE_MSG("tStyle2Window");
330*25b329d5SDavid du Colombier 
331f5736e95SDavid du Colombier 	fail(szLine == NULL || pStyle == NULL || pSection == NULL);
332f5736e95SDavid du Colombier 
333f5736e95SDavid du Colombier 	if (pStyle->usIstd == 0 || pStyle->usIstd > 9) {
334f5736e95SDavid du Colombier 		szLine[0] = '\0';
335f5736e95SDavid du Colombier 		return 0;
336f5736e95SDavid du Colombier 	}
337f5736e95SDavid du Colombier 
338f5736e95SDavid du Colombier 	/* Set the numbers */
339*25b329d5SDavid du Colombier 	tStyleIndex = (size_t)pStyle->usIstd - 1;
340*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex < 9; tIndex++) {
341*25b329d5SDavid du Colombier 		if (tIndex == tStyleIndex) {
342*25b329d5SDavid du Colombier 			auiHdrCounter[tIndex]++;
343*25b329d5SDavid du Colombier 		} else if (tIndex > tStyleIndex) {
344*25b329d5SDavid du Colombier 			auiHdrCounter[tIndex] = 0;
345*25b329d5SDavid du Colombier 		} else if (auiHdrCounter[tIndex] == 0) {
346*25b329d5SDavid du Colombier 			auiHdrCounter[tIndex] = 1;
347f5736e95SDavid du Colombier 		}
348f5736e95SDavid du Colombier 	}
349f5736e95SDavid du Colombier 
350f5736e95SDavid du Colombier 	eNumType = eGetNumType(pStyle->ucNumLevel);
351f5736e95SDavid du Colombier 	if (eNumType != level_type_outline) {
352f5736e95SDavid du Colombier 		szLine[0] = '\0';
353f5736e95SDavid du Colombier 		return 0;
354f5736e95SDavid du Colombier 	}
355f5736e95SDavid du Colombier 
356f5736e95SDavid du Colombier 	/* Print the numbers */
357*25b329d5SDavid du Colombier 	pcTxt = szLine;
358*25b329d5SDavid du Colombier 	bNeedPrevLvl = (pSection->usNeedPrevLvl & BIT(tStyleIndex)) != 0;
359*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex <= tStyleIndex; tIndex++) {
360*25b329d5SDavid du Colombier 		if (tIndex == tStyleIndex ||
361*25b329d5SDavid du Colombier 		    (bNeedPrevLvl && tIndex < tStyleIndex)) {
362*25b329d5SDavid du Colombier 			if (pcTxt - szLine >= tLineSize - 25) {
363*25b329d5SDavid du Colombier 				/* Prevent a possible buffer overflow */
364*25b329d5SDavid du Colombier 				DBG_DEC(pcTxt - szLine);
365*25b329d5SDavid du Colombier 				DBG_DEC(tLineSize - 25);
366*25b329d5SDavid du Colombier 				DBG_FIXME();
367*25b329d5SDavid du Colombier 				szLine[0] = '\0';
368*25b329d5SDavid du Colombier 				return 0;
369*25b329d5SDavid du Colombier 			}
370*25b329d5SDavid du Colombier 			ucNFC = pSection->aucNFC[tIndex];
371f5736e95SDavid du Colombier 			switch(ucNFC) {
372f5736e95SDavid du Colombier 			case LIST_ARABIC_NUM:
373*25b329d5SDavid du Colombier 			case LIST_NUMBER_TXT:
374*25b329d5SDavid du Colombier 			case LIST_ORDINAL_TXT:
375f5736e95SDavid du Colombier 				pcTxt += sprintf(pcTxt, "%u",
376*25b329d5SDavid du Colombier 					auiHdrCounter[tIndex]);
377f5736e95SDavid du Colombier 				break;
378f5736e95SDavid du Colombier 			case LIST_UPPER_ROMAN:
379f5736e95SDavid du Colombier 			case LIST_LOWER_ROMAN:
380f5736e95SDavid du Colombier 				pcTxt += tNumber2Roman(
381*25b329d5SDavid du Colombier 					auiHdrCounter[tIndex],
382f5736e95SDavid du Colombier 					ucNFC == LIST_UPPER_ROMAN,
383f5736e95SDavid du Colombier 					pcTxt);
384f5736e95SDavid du Colombier 				break;
385f5736e95SDavid du Colombier 			case LIST_UPPER_ALPHA:
386f5736e95SDavid du Colombier 			case LIST_LOWER_ALPHA:
387f5736e95SDavid du Colombier 				pcTxt += tNumber2Alpha(
388*25b329d5SDavid du Colombier 					auiHdrCounter[tIndex],
389f5736e95SDavid du Colombier 					ucNFC == LIST_UPPER_ALPHA,
390f5736e95SDavid du Colombier 					pcTxt);
391f5736e95SDavid du Colombier 				break;
392*25b329d5SDavid du Colombier 			case LIST_OUTLINE_NUM:
393*25b329d5SDavid du Colombier 				pcTxt += sprintf(pcTxt, "%02u",
394*25b329d5SDavid du Colombier 					auiHdrCounter[tIndex]);
395*25b329d5SDavid du Colombier 				break;
396f5736e95SDavid du Colombier 			default:
397f5736e95SDavid du Colombier 				DBG_DEC(ucNFC);
398f5736e95SDavid du Colombier 				DBG_FIXME();
399f5736e95SDavid du Colombier 				pcTxt += sprintf(pcTxt, "%u",
400*25b329d5SDavid du Colombier 					auiHdrCounter[tIndex]);
401f5736e95SDavid du Colombier 				break;
402f5736e95SDavid du Colombier 			}
403*25b329d5SDavid du Colombier 			if (tIndex < tStyleIndex) {
404f5736e95SDavid du Colombier 				*pcTxt++ = '.';
405*25b329d5SDavid du Colombier 			} else if (tIndex == tStyleIndex) {
406f5736e95SDavid du Colombier 				*pcTxt++ = ' ';
407f5736e95SDavid du Colombier 			}
408f5736e95SDavid du Colombier 		}
409f5736e95SDavid du Colombier 	}
410f5736e95SDavid du Colombier 	*pcTxt = '\0';
411f5736e95SDavid du Colombier 	NO_DBG_MSG_C((int)pStyle->usIstd >= 1 &&
412f5736e95SDavid du Colombier 		(int)pStyle->usIstd <= 9 &&
413f5736e95SDavid du Colombier 		eNumType != level_type_none &&
414f5736e95SDavid du Colombier 		eNumType != level_type_outline, szLine);
415f5736e95SDavid du Colombier 	NO_DBG_MSG_C(szLine[0] != '\0', szLine);
416f5736e95SDavid du Colombier 	fail(pcTxt < szLine);
417f5736e95SDavid du Colombier 	return (size_t)(pcTxt - szLine);
418f5736e95SDavid du Colombier } /* end of tStyle2Window */
419f5736e95SDavid du Colombier 
420f5736e95SDavid du Colombier /*
421f5736e95SDavid du Colombier  * vRemoveRowEnd - remove the end of table row indicator
422f5736e95SDavid du Colombier  *
423f5736e95SDavid du Colombier  * Remove the double TABLE_SEPARATOR characters from the end of the string.
424f5736e95SDavid du Colombier  * Special: remove the TABLE_SEPARATOR, 0x0a sequence
425f5736e95SDavid du Colombier  */
426f5736e95SDavid du Colombier static void
vRemoveRowEnd(char * szRowTxt)427f5736e95SDavid du Colombier vRemoveRowEnd(char *szRowTxt)
428f5736e95SDavid du Colombier {
429f5736e95SDavid du Colombier 	int	iLastIndex;
430f5736e95SDavid du Colombier 
431*25b329d5SDavid du Colombier 	TRACE_MSG("vRemoveRowEnd");
432*25b329d5SDavid du Colombier 
433f5736e95SDavid du Colombier 	fail(szRowTxt == NULL || szRowTxt[0] == '\0');
434f5736e95SDavid du Colombier 
435f5736e95SDavid du Colombier 	iLastIndex = (int)strlen(szRowTxt) - 1;
436f5736e95SDavid du Colombier 
437f5736e95SDavid du Colombier 	if (szRowTxt[iLastIndex] == TABLE_SEPARATOR ||
438*25b329d5SDavid du Colombier 	    szRowTxt[iLastIndex] == (char)0x0a) {
439f5736e95SDavid du Colombier 		szRowTxt[iLastIndex] = '\0';
440f5736e95SDavid du Colombier 		iLastIndex--;
441f5736e95SDavid du Colombier 	} else {
442f5736e95SDavid du Colombier 		DBG_HEX(szRowTxt[iLastIndex]);
443f5736e95SDavid du Colombier 	}
444f5736e95SDavid du Colombier 
445*25b329d5SDavid du Colombier 	if (iLastIndex >= 0 && szRowTxt[iLastIndex] == (char)0x0a) {
446f5736e95SDavid du Colombier 		szRowTxt[iLastIndex] = '\0';
447f5736e95SDavid du Colombier 		iLastIndex--;
448f5736e95SDavid du Colombier 	}
449f5736e95SDavid du Colombier 
450f5736e95SDavid du Colombier 	if (iLastIndex >= 0 && szRowTxt[iLastIndex] == TABLE_SEPARATOR) {
451f5736e95SDavid du Colombier 		szRowTxt[iLastIndex] = '\0';
452f5736e95SDavid du Colombier 		return;
453f5736e95SDavid du Colombier 	}
454f5736e95SDavid du Colombier 
455f5736e95SDavid du Colombier 	DBG_DEC(iLastIndex);
456f5736e95SDavid du Colombier 	DBG_HEX(szRowTxt[iLastIndex]);
457f5736e95SDavid du Colombier 	DBG_MSG(szRowTxt);
458f5736e95SDavid du Colombier } /* end of vRemoveRowEnd */
459f5736e95SDavid du Colombier 
460f5736e95SDavid du Colombier /*
461f5736e95SDavid du Colombier  * tComputeStringLengthMax - max string length in relation to max column width
462f5736e95SDavid du Colombier  *
463f5736e95SDavid du Colombier  * Return the maximum string length
464f5736e95SDavid du Colombier  */
465f5736e95SDavid du Colombier static size_t
tComputeStringLengthMax(const char * szString,size_t tColumnWidthMax)466f5736e95SDavid du Colombier tComputeStringLengthMax(const char *szString, size_t tColumnWidthMax)
467f5736e95SDavid du Colombier {
468f5736e95SDavid du Colombier 	const char	*pcTmp;
469f5736e95SDavid du Colombier 	size_t	tLengthMax, tLenPrev, tLen, tWidth;
470f5736e95SDavid du Colombier 
471*25b329d5SDavid du Colombier 	TRACE_MSG("tComputeStringLengthMax");
472*25b329d5SDavid du Colombier 
473f5736e95SDavid du Colombier 	fail(szString == NULL);
474f5736e95SDavid du Colombier 	fail(tColumnWidthMax == 0);
475f5736e95SDavid du Colombier 
476f5736e95SDavid du Colombier 	pcTmp = strchr(szString, '\n');
477f5736e95SDavid du Colombier 	if (pcTmp != NULL) {
478f5736e95SDavid du Colombier 		tLengthMax = (size_t)(pcTmp - szString + 1);
479f5736e95SDavid du Colombier 	} else {
480f5736e95SDavid du Colombier 		tLengthMax = strlen(szString);
481f5736e95SDavid du Colombier 	}
482f5736e95SDavid du Colombier 	if (tLengthMax == 0) {
483f5736e95SDavid du Colombier 		return 0;
484f5736e95SDavid du Colombier 	}
485f5736e95SDavid du Colombier 
486f5736e95SDavid du Colombier 	tLen = 0;
487f5736e95SDavid du Colombier 	tWidth = 0;
488f5736e95SDavid du Colombier 	for (;;) {
489f5736e95SDavid du Colombier 		tLenPrev = tLen;
490f5736e95SDavid du Colombier 		tLen += tGetCharacterLength(szString + tLen);
491f5736e95SDavid du Colombier 		DBG_DEC_C(tLen > tLengthMax, tLen);
492f5736e95SDavid du Colombier 		DBG_DEC_C(tLen > tLengthMax, tLengthMax);
493f5736e95SDavid du Colombier 		fail(tLen > tLengthMax);
494f5736e95SDavid du Colombier 		tWidth = tCountColumns(szString, tLen);
495f5736e95SDavid du Colombier 		if (tWidth > tColumnWidthMax) {
496f5736e95SDavid du Colombier 			return tLenPrev;
497f5736e95SDavid du Colombier 		}
498f5736e95SDavid du Colombier 		if (tLen >= tLengthMax) {
499f5736e95SDavid du Colombier 			return tLengthMax;
500f5736e95SDavid du Colombier 		}
501f5736e95SDavid du Colombier 	}
502f5736e95SDavid du Colombier } /* end of tComputeStringLengthMax */
503f5736e95SDavid du Colombier 
504f5736e95SDavid du Colombier /*
505f5736e95SDavid du Colombier  * tGetBreakingPoint - get the number of bytes that fit the column
506f5736e95SDavid du Colombier  *
507f5736e95SDavid du Colombier  * Returns the number of bytes that fit the column
508f5736e95SDavid du Colombier  */
509f5736e95SDavid du Colombier static size_t
tGetBreakingPoint(const char * szString,size_t tLen,size_t tWidth,size_t tColumnWidthMax)510f5736e95SDavid du Colombier tGetBreakingPoint(const char *szString,
511f5736e95SDavid du Colombier 	size_t tLen, size_t tWidth, size_t tColumnWidthMax)
512f5736e95SDavid du Colombier {
513f5736e95SDavid du Colombier 	int	iIndex;
514f5736e95SDavid du Colombier 
515*25b329d5SDavid du Colombier 	TRACE_MSG("tGetBreakingPoint");
516*25b329d5SDavid du Colombier 
517f5736e95SDavid du Colombier 	fail(szString == NULL);
518f5736e95SDavid du Colombier 	fail(tLen > strlen(szString));
519f5736e95SDavid du Colombier 	fail(tWidth > tColumnWidthMax);
520f5736e95SDavid du Colombier 
521f5736e95SDavid du Colombier 	if (tWidth < tColumnWidthMax ||
522f5736e95SDavid du Colombier 	    (tWidth == tColumnWidthMax &&
523f5736e95SDavid du Colombier 	     (szString[tLen] == ' ' ||
524f5736e95SDavid du Colombier 	      szString[tLen] == '\n' ||
525f5736e95SDavid du Colombier 	      szString[tLen] == '\0'))) {
526f5736e95SDavid du Colombier 		/* The string already fits, do nothing */
527f5736e95SDavid du Colombier 		return tLen;
528f5736e95SDavid du Colombier 	}
529f5736e95SDavid du Colombier 	/* Search for a breaking point */
530f5736e95SDavid du Colombier 	for (iIndex = (int)tLen - 1; iIndex >= 0; iIndex--) {
531f5736e95SDavid du Colombier 		if (szString[iIndex] == ' ') {
532f5736e95SDavid du Colombier 			return (size_t)iIndex;
533f5736e95SDavid du Colombier 		}
534f5736e95SDavid du Colombier 	}
535f5736e95SDavid du Colombier 	/* No breaking point found, just fill the column */
536f5736e95SDavid du Colombier 	return tLen;
537f5736e95SDavid du Colombier } /* end of tGetBreakingPoint */
538f5736e95SDavid du Colombier 
539f5736e95SDavid du Colombier /*
540*25b329d5SDavid du Colombier  * tComputeColumnWidthMax - compute the maximum column width
541*25b329d5SDavid du Colombier  */
542*25b329d5SDavid du Colombier static size_t
tComputeColumnWidthMax(short sWidth,long lCharWidth,double dFactor)543*25b329d5SDavid du Colombier tComputeColumnWidthMax(short sWidth, long lCharWidth, double dFactor)
544*25b329d5SDavid du Colombier {
545*25b329d5SDavid du Colombier 	size_t	tColumnWidthMax;
546*25b329d5SDavid du Colombier 
547*25b329d5SDavid du Colombier 	TRACE_MSG("tComputeColumnWidthMax");
548*25b329d5SDavid du Colombier 
549*25b329d5SDavid du Colombier 	fail(sWidth < 0);
550*25b329d5SDavid du Colombier 	fail(lCharWidth <= 0);
551*25b329d5SDavid du Colombier 	fail(dFactor <= 0.0);
552*25b329d5SDavid du Colombier 
553*25b329d5SDavid du Colombier 	tColumnWidthMax = (size_t)(
554*25b329d5SDavid du Colombier 		(lTwips2MilliPoints(sWidth) * dFactor + lCharWidth / 2.0) /
555*25b329d5SDavid du Colombier 		 lCharWidth);
556*25b329d5SDavid du Colombier 	if (tColumnWidthMax == 0) {
557*25b329d5SDavid du Colombier 		/* Minimum column width */
558*25b329d5SDavid du Colombier 		return 1;
559*25b329d5SDavid du Colombier 	}
560*25b329d5SDavid du Colombier 	if (tColumnWidthMax > 1) {
561*25b329d5SDavid du Colombier 		/* Make room for the TABLE_SEPARATOR_CHAR */
562*25b329d5SDavid du Colombier 		tColumnWidthMax--;
563*25b329d5SDavid du Colombier 	}
564*25b329d5SDavid du Colombier 	NO_DBG_DEC(tColumnWidthMax);
565*25b329d5SDavid du Colombier 	return tColumnWidthMax;
566*25b329d5SDavid du Colombier } /* end of tComputeColumnWidthMax */
567*25b329d5SDavid du Colombier 
568*25b329d5SDavid du Colombier /*
569f5736e95SDavid du Colombier  * vTableRow2Window - put a table row into a diagram
570f5736e95SDavid du Colombier  */
571f5736e95SDavid du Colombier void
vTableRow2Window(diagram_type * pDiag,output_type * pOutput,const row_block_type * pRowInfo,conversion_type eConversionType,int iParagraphBreak)572f5736e95SDavid du Colombier vTableRow2Window(diagram_type *pDiag, output_type *pOutput,
573*25b329d5SDavid du Colombier 	const row_block_type *pRowInfo,
574*25b329d5SDavid du Colombier 	conversion_type eConversionType, int iParagraphBreak)
575f5736e95SDavid du Colombier {
576f5736e95SDavid du Colombier 	output_type	tRow;
577f5736e95SDavid du Colombier 	char	*aszColTxt[TABLE_COLUMN_MAX];
578f5736e95SDavid du Colombier 	char	*szLine, *pcTxt;
579*25b329d5SDavid du Colombier 	double	dMagnify;
580f5736e95SDavid du Colombier 	long	lCharWidthLarge, lCharWidthSmall;
581*25b329d5SDavid du Colombier 	size_t	tColumnWidthTotal, atColumnWidthMax[TABLE_COLUMN_MAX];
582f5736e95SDavid du Colombier 	size_t	tSize, tColumnWidthMax, tWidth, tLen;
583f5736e95SDavid du Colombier 	int	iIndex, iNbrOfColumns, iTmp;
584f5736e95SDavid du Colombier 	BOOL	bNotReady;
585f5736e95SDavid du Colombier 
586*25b329d5SDavid du Colombier 	TRACE_MSG("vTableRow2Window");
587*25b329d5SDavid du Colombier 
588f5736e95SDavid du Colombier 	fail(pDiag == NULL || pOutput == NULL || pRowInfo == NULL);
589f5736e95SDavid du Colombier 	fail(pOutput->szStorage == NULL);
590f5736e95SDavid du Colombier 	fail(pOutput->pNext != NULL);
591*25b329d5SDavid du Colombier 	fail(iParagraphBreak < 0);
592f5736e95SDavid du Colombier 
593f5736e95SDavid du Colombier 	/* Character sizes */
594f5736e95SDavid du Colombier 	lCharWidthLarge = lComputeStringWidth("W", 1,
595f5736e95SDavid du Colombier 				pOutput->tFontRef, pOutput->usFontSize);
596f5736e95SDavid du Colombier 	NO_DBG_DEC(lCharWidthLarge);
597f5736e95SDavid du Colombier 	lCharWidthSmall = lComputeStringWidth("i", 1,
598f5736e95SDavid du Colombier 				pOutput->tFontRef, pOutput->usFontSize);
599f5736e95SDavid du Colombier 	NO_DBG_DEC(lCharWidthSmall);
600f5736e95SDavid du Colombier 	/* For the time being: use a fixed width font */
601f5736e95SDavid du Colombier 	fail(lCharWidthLarge != lCharWidthSmall);
602f5736e95SDavid du Colombier 
603f5736e95SDavid du Colombier 	vRemoveRowEnd(pOutput->szStorage);
604f5736e95SDavid du Colombier 
605f5736e95SDavid du Colombier 	/* Split the row text into a set of column texts */
606f5736e95SDavid du Colombier 	aszColTxt[0] = pOutput->szStorage;
607f5736e95SDavid du Colombier 	for (iNbrOfColumns = 1;
608f5736e95SDavid du Colombier 	     iNbrOfColumns < TABLE_COLUMN_MAX;
609f5736e95SDavid du Colombier 	     iNbrOfColumns++) {
610f5736e95SDavid du Colombier 		aszColTxt[iNbrOfColumns] =
611f5736e95SDavid du Colombier 				strchr(aszColTxt[iNbrOfColumns - 1],
612f5736e95SDavid du Colombier 					TABLE_SEPARATOR);
613f5736e95SDavid du Colombier 		if (aszColTxt[iNbrOfColumns] == NULL) {
614f5736e95SDavid du Colombier 			break;
615f5736e95SDavid du Colombier 		}
616f5736e95SDavid du Colombier 		*aszColTxt[iNbrOfColumns] = '\0';
617f5736e95SDavid du Colombier 		aszColTxt[iNbrOfColumns]++;
618f5736e95SDavid du Colombier 		NO_DBG_DEC(iNbrOfColumns);
619f5736e95SDavid du Colombier 		NO_DBG_MSG(aszColTxt[iNbrOfColumns]);
620f5736e95SDavid du Colombier 	}
621f5736e95SDavid du Colombier 
622*25b329d5SDavid du Colombier 	/* Work around a bug in Word */
623*25b329d5SDavid du Colombier 	while (iNbrOfColumns > (int)pRowInfo->ucNumberOfColumns &&
624*25b329d5SDavid du Colombier 	       pRowInfo->asColumnWidth[iNbrOfColumns] == 0) {
625*25b329d5SDavid du Colombier 		iNbrOfColumns--;
626*25b329d5SDavid du Colombier 	}
627*25b329d5SDavid du Colombier 
628f5736e95SDavid du Colombier 	DBG_DEC_C(iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns,
629f5736e95SDavid du Colombier 		iNbrOfColumns);
630f5736e95SDavid du Colombier 	DBG_DEC_C(iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns,
631f5736e95SDavid du Colombier 		pRowInfo->ucNumberOfColumns);
632f5736e95SDavid du Colombier 	if (iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns) {
633f5736e95SDavid du Colombier 		werr(0, "Skipping an unmatched table row");
634f5736e95SDavid du Colombier 		return;
635f5736e95SDavid du Colombier 	}
636f5736e95SDavid du Colombier 
637*25b329d5SDavid du Colombier #if defined(__FULL_TEXT_SEARCH)
638*25b329d5SDavid du Colombier 	/* No table formatting: use for full-text search (untested) */
639*25b329d5SDavid du Colombier 	for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
640*25b329d5SDavid du Colombier 		fprintf(pDiag->pOutFile, "%s\n" , aszColTxt[iIndex]);
641*25b329d5SDavid du Colombier 	}
642*25b329d5SDavid du Colombier #else
643f5736e95SDavid du Colombier 	if (bAddTableRow(pDiag, aszColTxt, iNbrOfColumns,
644f5736e95SDavid du Colombier 			pRowInfo->asColumnWidth, pRowInfo->ucBorderInfo)) {
645f5736e95SDavid du Colombier 		/* All work has been done */
646f5736e95SDavid du Colombier 		return;
647f5736e95SDavid du Colombier 	}
648f5736e95SDavid du Colombier 
649*25b329d5SDavid du Colombier 	/* Fill the table with maximum column widths */
650*25b329d5SDavid du Colombier 	if (eConversionType == conversion_text ||
651*25b329d5SDavid du Colombier 	    eConversionType == conversion_fmt_text) {
652*25b329d5SDavid du Colombier 		if (iParagraphBreak == 0 ||
653*25b329d5SDavid du Colombier 		    iParagraphBreak >= MAX_SCREEN_WIDTH) {
654*25b329d5SDavid du Colombier 			dMagnify = (double)MAX_SCREEN_WIDTH;
655*25b329d5SDavid du Colombier 		} else if (iParagraphBreak <= MIN_SCREEN_WIDTH) {
656*25b329d5SDavid du Colombier 			dMagnify = (double)MIN_SCREEN_WIDTH;
657*25b329d5SDavid du Colombier 		} else {
658*25b329d5SDavid du Colombier 			dMagnify = (double)iParagraphBreak;
659*25b329d5SDavid du Colombier 		}
660*25b329d5SDavid du Colombier 		dMagnify /= (double)DEFAULT_SCREEN_WIDTH;
661*25b329d5SDavid du Colombier 		DBG_FLT_C(dMagnify < 0.99 || dMagnify > 1.01, dMagnify);
662*25b329d5SDavid du Colombier 	} else {
663*25b329d5SDavid du Colombier 		dMagnify = 1.0;
664*25b329d5SDavid du Colombier 	}
665*25b329d5SDavid du Colombier 	tColumnWidthTotal = 0;
666*25b329d5SDavid du Colombier 	for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
667*25b329d5SDavid du Colombier 		atColumnWidthMax[iIndex] = tComputeColumnWidthMax(
668*25b329d5SDavid du Colombier 					pRowInfo->asColumnWidth[iIndex],
669*25b329d5SDavid du Colombier 					lCharWidthLarge,
670*25b329d5SDavid du Colombier 					dMagnify);
671*25b329d5SDavid du Colombier 		tColumnWidthTotal += atColumnWidthMax[iIndex];
672*25b329d5SDavid du Colombier 	}
673*25b329d5SDavid du Colombier 
674f5736e95SDavid du Colombier 	/*
675f5736e95SDavid du Colombier 	 * Get enough space for the row.
676f5736e95SDavid du Colombier 	 * Worst case: three bytes per UTF-8 character
677f5736e95SDavid du Colombier 	 */
678*25b329d5SDavid du Colombier 	tSize = 3 * (1 + tColumnWidthTotal + (size_t)iNbrOfColumns + 3);
679f5736e95SDavid du Colombier 	szLine = xmalloc(tSize);
680f5736e95SDavid du Colombier 
681f5736e95SDavid du Colombier 	do {
682f5736e95SDavid du Colombier 		/* Print one line of a table row */
683f5736e95SDavid du Colombier 		bNotReady = FALSE;
684f5736e95SDavid du Colombier 		pcTxt = szLine;
685f5736e95SDavid du Colombier 		*pcTxt++ = TABLE_SEPARATOR_CHAR;
686f5736e95SDavid du Colombier 		for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
687*25b329d5SDavid du Colombier 			tColumnWidthMax = atColumnWidthMax[iIndex];
688f5736e95SDavid du Colombier 			if (aszColTxt[iIndex] == NULL) {
689f5736e95SDavid du Colombier 				/* Add an empty column */
690f5736e95SDavid du Colombier 				for (iTmp = 0;
691f5736e95SDavid du Colombier 				     iTmp < (int)tColumnWidthMax;
692f5736e95SDavid du Colombier 				     iTmp++) {
693f5736e95SDavid du Colombier 					*pcTxt++ = (char)FILLER_CHAR;
694f5736e95SDavid du Colombier 				}
695f5736e95SDavid du Colombier 				*pcTxt++ = TABLE_SEPARATOR_CHAR;
696f5736e95SDavid du Colombier 				*pcTxt = '\0';
697f5736e95SDavid du Colombier 				continue;
698f5736e95SDavid du Colombier 			}
699f5736e95SDavid du Colombier 			/* Compute the length and width of the column text */
700f5736e95SDavid du Colombier 			tLen = tComputeStringLengthMax(
701f5736e95SDavid du Colombier 					aszColTxt[iIndex], tColumnWidthMax);
702f5736e95SDavid du Colombier 			NO_DBG_DEC(tLen);
703f5736e95SDavid du Colombier 			while (tLen != 0 &&
704f5736e95SDavid du Colombier 					(aszColTxt[iIndex][tLen - 1] == '\n' ||
705f5736e95SDavid du Colombier 					 aszColTxt[iIndex][tLen - 1] == ' ')) {
706f5736e95SDavid du Colombier 				aszColTxt[iIndex][tLen - 1] = ' ';
707f5736e95SDavid du Colombier 				tLen--;
708f5736e95SDavid du Colombier 			}
709f5736e95SDavid du Colombier 			tWidth = tCountColumns(aszColTxt[iIndex], tLen);
710f5736e95SDavid du Colombier 			fail(tWidth > tColumnWidthMax);
711f5736e95SDavid du Colombier 			tLen = tGetBreakingPoint(aszColTxt[iIndex],
712f5736e95SDavid du Colombier 					tLen, tWidth, tColumnWidthMax);
713f5736e95SDavid du Colombier 			tWidth = tCountColumns(aszColTxt[iIndex], tLen);
714f5736e95SDavid du Colombier 			if (tLen == 0 && *aszColTxt[iIndex] == '\0') {
715f5736e95SDavid du Colombier 				/* No text at all */
716f5736e95SDavid du Colombier 				aszColTxt[iIndex] = NULL;
717f5736e95SDavid du Colombier 			} else {
718f5736e95SDavid du Colombier 				/* Add the text */
719f5736e95SDavid du Colombier 				pcTxt += sprintf(pcTxt,
720f5736e95SDavid du Colombier 					"%.*s", (int)tLen, aszColTxt[iIndex]);
721f5736e95SDavid du Colombier 				if (tLen == 0 && *aszColTxt[iIndex] != ' ') {
722f5736e95SDavid du Colombier 					tLen = tGetCharacterLength(
723f5736e95SDavid du Colombier 							aszColTxt[iIndex]);
724f5736e95SDavid du Colombier 					DBG_CHR(*aszColTxt[iIndex]);
725f5736e95SDavid du Colombier 					DBG_FIXME();
726f5736e95SDavid du Colombier 					fail(tLen == 0);
727f5736e95SDavid du Colombier 				}
728f5736e95SDavid du Colombier 				aszColTxt[iIndex] += tLen;
729f5736e95SDavid du Colombier 				while (*aszColTxt[iIndex] == ' ') {
730f5736e95SDavid du Colombier 					aszColTxt[iIndex]++;
731f5736e95SDavid du Colombier 				}
732f5736e95SDavid du Colombier 				if (*aszColTxt[iIndex] == '\0') {
733f5736e95SDavid du Colombier 					/* This row is now complete */
734f5736e95SDavid du Colombier 					aszColTxt[iIndex] = NULL;
735f5736e95SDavid du Colombier 				} else {
736f5736e95SDavid du Colombier 					/* This row needs more lines */
737f5736e95SDavid du Colombier 					bNotReady = TRUE;
738f5736e95SDavid du Colombier 				}
739f5736e95SDavid du Colombier 			}
740f5736e95SDavid du Colombier 			/* Fill up the rest */
741f5736e95SDavid du Colombier 			for (iTmp = 0;
742f5736e95SDavid du Colombier 			     iTmp < (int)tColumnWidthMax - (int)tWidth;
743f5736e95SDavid du Colombier 			     iTmp++) {
744f5736e95SDavid du Colombier 				*pcTxt++ = (char)FILLER_CHAR;
745f5736e95SDavid du Colombier 			}
746f5736e95SDavid du Colombier 			/* End of column */
747f5736e95SDavid du Colombier 			*pcTxt++ = TABLE_SEPARATOR_CHAR;
748f5736e95SDavid du Colombier 			*pcTxt = '\0';
749f5736e95SDavid du Colombier 		}
750f5736e95SDavid du Colombier 		/* Output the table row line */
751f5736e95SDavid du Colombier 		*pcTxt = '\0';
752f5736e95SDavid du Colombier 		tRow = *pOutput;
753f5736e95SDavid du Colombier 		tRow.szStorage = szLine;
754f5736e95SDavid du Colombier 		fail(pcTxt < szLine);
755f5736e95SDavid du Colombier 		tRow.tNextFree = (size_t)(pcTxt - szLine);
756f5736e95SDavid du Colombier 		tRow.lStringWidth = lComputeStringWidth(
757f5736e95SDavid du Colombier 					tRow.szStorage,
758f5736e95SDavid du Colombier 					tRow.tNextFree,
759f5736e95SDavid du Colombier 					tRow.tFontRef,
760f5736e95SDavid du Colombier 					tRow.usFontSize);
761f5736e95SDavid du Colombier 		vString2Diagram(pDiag, &tRow);
762*25b329d5SDavid du Colombier 		TRACE_MSG("after vString2Diagram in vTableRow2Window");
763f5736e95SDavid du Colombier 	} while (bNotReady);
764f5736e95SDavid du Colombier 	/* Clean up before you leave */
765f5736e95SDavid du Colombier 	szLine = xfree(szLine);
766*25b329d5SDavid du Colombier 	TRACE_MSG("leaving vTableRow2Window");
767*25b329d5SDavid du Colombier #endif /* __FULL_TEXT_SEARCH */
768f5736e95SDavid du Colombier } /* end of vTableRow2Window */
769