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