1 /*
2  * Copyright (C) 1991,1992 NEC Corporation.
3  */
4 #ifndef lint
5 static char rcsid[] =
6 	"$Id: list.c,v 2.9 1994/04/19 10:16:47 uchida Exp $ (NEC)";
7 #endif
8 
9 #include <stdio.h>
10 #include "plain2.h"
11 /*
12  * 1st step:
13  *	Find list head lines
14  * 2nd step:
15  *	Fix list region (containing other text blocks)
16  */
findListHead(begin,end)17 findListHead(begin, end)
18 int	begin;
19 int	end;
20 {
21 	int	indent, l, curType, curHint;
22 	struct	textBlock *listbp, *lhbp, *lastbp;
23 	int	blankPassed = 0;
24 	int	prevListNum;
25 	DBG2(7, "findListHead (%d-%d)\n", begin, end);
26 	curType = texts[begin]->listType;
27 	curHint = texts[begin]->listHint;
28 	indent  = texts[begin]->indent;
29 	/*
30 	 * LIST structure
31 	 *	LIST-+- -> LIST HEAD	"1) list1"
32 	 *	     				xxx
33 	 *	     	-> LIST HEAD    "2) list2"
34 	 *
35 	 *		-> NULL
36 	 */
37 	listbp = newTextBlock(begin, begin+1, TB_LIST);
38 	lhbp   = newTextBlock(begin, begin+1, TB_LISTHD);
39 	listbp->nextBlock = lhbp;
40 	lhbp->superBlock  = listbp;
41 	lastbp        = lhbp;
42 	prevListNum   = texts[begin]->listNum;
43 	for (l = begin + 1; l < end; l++) {
44 		int romanInAlpha;
45 		if (texts[l]->block == NULL && texts[l]->pListHead != NEVER) {
46 			/* special case for "i" and "I"	*/
47 			if (((curType == L_SALPHA
48 			      && texts[l]->listType == L_SROMAN)
49 			     || (curType == L_LALPHA
50 				 && texts[l]->listType == L_LROMAN))
51 			    && prevListNum == alphaVal('h')
52 			    && texts[l]->listNum  == 1)
53 				romanInAlpha = 1;
54 			else
55 				romanInAlpha = 0;
56 			/* end of special case		*/
57 			if ((texts[l]->listType == curType || romanInAlpha)
58 			    && texts[l]->listHint == curHint
59 			    && texts[l]->indent == indent) {
60 				if (curType <= L_ENUM_MAX
61 				    && (texts[l]->listNum != ++prevListNum)) {
62 					/* Number/Alpha List not continuous */
63 					if (!romanInAlpha
64 					    && texts[l]->listNum == 1)
65 						break;
66 					MSG1("\nWarning: non continuous list at line %d\n", l);
67 					MSG1("\t%s\n",codeCvt(texts[l]->body));
68 					if (romanInAlpha)
69 						prevListNum = alphaVal('i');
70 					else
71 						prevListNum =texts[l]->listNum;
72 				}
73 				/* Continuation of same list	*/
74 				lhbp = newTextBlock(l, l + 1 ,TB_LISTHD);
75 				lastbp->nextBlock = lhbp;
76 				lhbp->superBlock  = listbp;
77 				lastbp = lhbp;
78 			}
79 			else if (curType != texts[l]->listType
80 				  && curHint != texts[l]->listHint
81 				  && indent == texts[l]->indent) {
82 				/* Encountered another type of list	*/
83 				/* Check previous list block		*/
84 				break;
85 			}
86 			else if (texts[l]->indent < indent) {
87 				break;
88 			}
89 			blankPassed = 0;
90 		}
91 		else if (texts[l]->block && texts[l]->block->hinted) {
92 			/* Do Nothing	*/
93 		}
94 		else if (!texts[l]->blank
95 			 && texts[l]->indent < indent) {
96 			/* End of the indented block	*/
97 			/* Check previous list block	*/
98 			break;
99 		}
100 		else if (texts[l]->block) {
101 			if (texts[l]->block->type == TB_SECNUM)
102 				break;
103 			if (texts[l]->block->type == TB_LISTHD)
104 				break;
105 		}
106 		/*
107 		 * ex.
108 		 *	1) list1
109 		 *	this is the continuation	<- don't break
110 		 *
111 		 *	2) list2
112 		 *					<- End of List
113 		 *	this is NoT the continuation
114 		 */
115 		else if (texts[l]->blank)
116 			blankPassed = 1;
117 		else if (blankPassed && texts[l]->indent <= indent)
118 			break;
119 	}
120 	if (checkIfList(listbp)
121 	    /*
122 	     * Number/Alpha List should begin with 1
123 	     */
124 	    && curType <= L_ENUM_MAX
125 	    && (texts[begin]->listNum != 1)) {
126 		MSG1("\nWarning[%d] list not start with 1 or A\n", begin);
127 		MSG1("\t%s\n",codeCvt(texts[begin]->body));
128 	}
129 }
130 /*
131  * Check if "toriaezu" marked block is list or not.
132  *	(elements >= 2 && list head ni mieru
133  *	or element == 1 && list head ni chigainai)
134  * If determined as not a list free blocks
135  *	(else region end is determined later)
136  */
137 checkIfList(lbp)
138 struct textBlock *lbp;
139 {
140 	struct	textBlock *lhbp;
141 	int	nitems;
142 	int	allSingleLine = 1;	/* All items are 1 line	*/
143 	int	goodlooking = 0;	/* for Description list	*/
144 	int	rend;
145 	DBG1(7, "checkIfList (%d)\n", lbp->rbegin);
146 	for (lhbp = lbp->nextBlock, nitems = 0; lhbp;
147 	     lhbp = lhbp->nextBlock, nitems++) {
148 		if (lhbp->nextBlock && (lhbp->nextBlock->rbegin - lhbp->rbegin > 1))
149 			allSingleLine = 0;
150 		if (lhbp->nextBlock
151 		    && (lhbp->nextBlock->rbegin - lhbp->rbegin > 1)
152 		    && (texts[lhbp->rbegin + 1]->indent >
153 			texts[lhbp->rbegin]->indent))
154 			/* Following line is indented	*/
155 			goodlooking++;
156 		else if (prevLine(lhbp->rbegin)->blank)
157 			/* Previous Line blank		*/
158 			goodlooking++;
159 	}
160 	if ((nitems <= 1 && texts[lbp->rbegin]->pListHead < DEFINITELY)
161 	    || (texts[lbp->rbegin]->listType == L_DLIST
162 		&& allSingleLine == 0 &&  goodlooking * 4 < nitems)) {
163 		/* Not a list.  Do nothing	*/
164 		for (lhbp = lbp; lhbp; lhbp = lhbp->nextBlock)
165 			free((char *)lhbp);
166 		return 0;
167 	}
168 	for (lhbp = lbp->nextBlock; lhbp; lhbp = lhbp->nextBlock) {
169 		texts[lhbp->rbegin]->block = lhbp;
170 		rend = lhbp->rend;
171 	}
172 	/* Overwrite first line of the list	*/
173 	texts[lbp->rbegin]->block = lbp;
174 	MSG2("%d-%d ", lbp->rbegin, rend - 1);
175 	return 1;
176 }
177 /*
178  * Expand list head with following plain text
179  */
180 expandListHead(lhbp)
181 struct	textBlock *lhbp;
182 {
183 	struct	textBlock *nextTbp;
184 	int	l;
185 	int	indent1, indent2, indentFb, indentFe;
186 
187 	if (texts[lhbp->rbegin]->length * 2 < rightMargin)
188 		/* too Short	*/
189 		return;
190 	if ((nextTbp = texts[lhbp->rend]->block)
191 	    && (nextTbp->type == TB_PLAIN)) {
192 		indent1  = texts[lhbp->rbegin]->indent;
193 		indent2  = listSecBody(texts[lhbp->rbegin])
194 			- texts[lhbp->rbegin]->body;
195 		indentFb = texts[nextTbp->rbegin]->indent;
196 		indentFe = texts[nextTbp->rend - 1]->indent;
197 
198 		if (indentFb ==	indentFe
199 		    && indent1 <= indentFb && indentFb <=indent2
200 		    && indent1 <= indentFe && indentFe <=indent2) {
201 			for (l = lhbp->rend;
202 			     l < nextTbp->rend; l++)
203 				texts[l]->block = lhbp;
204 			lhbp->rend = nextTbp->rend;
205 			free((char *)nextTbp);
206 		}
207 	}
208 }
209 /*
210  * Fix list region
211  *  ex.
212  *	1) list1	      <-+ list region
213  *		sub-bock	|
214  *	2) list2		|
215  *		sub-bock      <-+
216  */
217 fixListEnd(lbp)
218 struct textBlock *lbp;
219 {
220 	struct	textBlock *lhbp;
221 	int	allSingleLine = 1;
222 	int	items = 0;
223 	int	lnum;
224 	for (lhbp = lbp->nextBlock; lhbp->nextBlock; lhbp = lhbp->nextBlock) {
225 		items++;
226 		if (lhbp->rend != lhbp->nextBlock->rbegin)
227 			allSingleLine = 0;
228 		expandListHead(lhbp);
229 		fixListRegion(lhbp->rend, lhbp->nextBlock->rbegin);
230 	}
231 	if (lhbp == lbp->nextBlock)
232 		allSingleLine = 0;
233 	/* Last item of the list	*/
234 	if (items < 2 || !allSingleLine)
235 		expandListHead(lhbp);
236 	lnum = lhbp->rend;
237 	while (lnum < textLines) {
238 		if (texts[lnum]->block
239 		    && minIndentBlock(texts[lnum]->block)
240 		    <= texts[lbp->rbegin]->indent)
241 			break;
242 		if (texts[lnum]->block && texts[lnum]->block->type == TB_LIST)
243 			lnum = fixListEnd(texts[lnum]->block);
244 		else if (texts[lnum]->block)
245 			lnum = texts[lnum]->block->rend;
246 		else
247 			lnum++;
248 	}
249 	lbp->rend = lnum;
250 	return lnum;
251 }
fixListRegion(begin,end)252 fixListRegion(begin, end)
253 int	begin;
254 int	end;
255 {
256 	int	l;
257 	for (l = begin; l < end;) {
258 		if (texts[l]->block && texts[l]->block->type == TB_LIST) {
259 			l = fixListEnd(texts[l]->block);
260 		}
261 		else
262 			l++;
263 	}
264 }
list(begin,end)265 list(begin, end)
266 int	begin;
267 int	end;
268 {
269 	int	l;
270 	for (l = begin; l < end; l++) {
271 		if (texts[l]->block == NULL
272 		    && texts[l]->pListHead != NEVER)
273 			findListHead(l, end);
274 	}
275 }
276