listlist.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. * listlist.c
  3. * Copyright (C) 2002,2003 A.J. van Os; Released under GPL
  4. *
  5. * Description:
  6. * Build, read and destroy a list of Word list information
  7. *
  8. * Note:
  9. * This list only exists when the Word document is saved by Word 8 or later
  10. */
  11. #include "antiword.h"
  12. /*
  13. * Private structure to hide the way the information
  14. * is stored from the rest of the program
  15. */
  16. typedef struct list_desc_tag {
  17. list_block_type tInfo;
  18. ULONG ulListID;
  19. USHORT usIstd;
  20. UCHAR ucListLevel;
  21. struct list_desc_tag *pNext;
  22. } list_desc_type;
  23. typedef struct list_value_tag {
  24. USHORT usValue;
  25. USHORT usListIndex;
  26. UCHAR ucListLevel;
  27. struct list_value_tag *pNext;
  28. } list_value_type;
  29. /* Variables needed to describe the LFO list (pllfo) */
  30. static ULONG *aulLfoList = NULL;
  31. static USHORT usLfoLen = 0;
  32. /* Variables needed to write the List Information List */
  33. static list_desc_type *pAnchor = NULL;
  34. static list_desc_type *pBlockLast = NULL;
  35. /* Variable needed for numbering new lists */
  36. static list_value_type *pValues = NULL;
  37. /* Variables needed for numbering old lists */
  38. static int iOldListSeqNumber = 0;
  39. static USHORT usOldListValue = 0;
  40. /*
  41. * vDestroyListInfoList - destroy the List Information List
  42. */
  43. void
  44. vDestroyListInfoList(void)
  45. {
  46. list_desc_type *pCurr, *pNext;
  47. list_value_type *pValueCurr, *pValueNext;
  48. DBG_MSG("vDestroyListInfoList");
  49. /* Free the LFO list */
  50. usLfoLen = 0;
  51. aulLfoList = xfree(aulLfoList);
  52. /* Free the List Information List */
  53. pCurr = pAnchor;
  54. while (pCurr != NULL) {
  55. pNext = pCurr->pNext;
  56. pCurr = xfree(pCurr);
  57. pCurr = pNext;
  58. }
  59. pAnchor = NULL;
  60. /* Reset all control variables */
  61. pBlockLast = NULL;
  62. /* Free the values list */
  63. pValueCurr = pValues;
  64. while (pValueCurr != NULL) {
  65. pValueNext = pValueCurr->pNext;
  66. pValueCurr = xfree(pValueCurr);
  67. pValueCurr = pValueNext;
  68. }
  69. pValues = NULL;
  70. /* Reset the values for the old lists */
  71. iOldListSeqNumber = 0;
  72. usOldListValue = 0;
  73. } /* end of vDestroyListInfoList */
  74. /*
  75. * vBuildLfoList - build the LFO list (pllfo)
  76. */
  77. void
  78. vBuildLfoList(const UCHAR *aucBuffer, size_t tBufLen)
  79. {
  80. size_t tRecords;
  81. int iIndex;
  82. fail(aucBuffer == NULL);
  83. if (tBufLen < 4) {
  84. return;
  85. }
  86. tRecords = (size_t)ulGetLong(0, aucBuffer);
  87. NO_DBG_DEC(tRecords);
  88. if (4 + 16 * tRecords > tBufLen || tRecords >= 0x7fff) {
  89. /* Just a sanity check */
  90. DBG_DEC(tRecords);
  91. DBG_DEC(4 + 16 * tRecords);
  92. DBG_DEC(tBufLen);
  93. return;
  94. }
  95. aulLfoList = xcalloc(tRecords, sizeof(ULONG));
  96. for (iIndex = 0; iIndex < (int)tRecords; iIndex++) {
  97. aulLfoList[iIndex] = ulGetLong(4 + 16 * iIndex, aucBuffer);
  98. NO_DBG_HEX(aulLfoList[iIndex]);
  99. }
  100. usLfoLen = (USHORT)tRecords;
  101. } /* end of vBuildLfoList */
  102. /*
  103. * vAdd2ListInfoList - add an element to the List Information list
  104. */
  105. void
  106. vAdd2ListInfoList(ULONG ulListID, USHORT usIstd, UCHAR ucListLevel,
  107. const list_block_type *pListBlock)
  108. {
  109. list_desc_type *pListMember;
  110. fail(pListBlock == NULL);
  111. NO_DBG_HEX(ulListID);
  112. NO_DBG_DEC(usIstd);
  113. NO_DBG_DEC(ucListLevel);
  114. NO_DBG_DEC(pListBlock->ulStartAt);
  115. NO_DBG_DEC(pListBlock->bNoRestart);
  116. NO_DBG_DEC(pListBlock->sLeftIndent);
  117. NO_DBG_HEX(pListBlock->ucNFC);
  118. NO_DBG_HEX(pListBlock->usListChar);
  119. /* Create list member */
  120. pListMember = xmalloc(sizeof(list_desc_type));
  121. /* Fill the list member */
  122. pListMember->tInfo = *pListBlock;
  123. pListMember->ulListID = ulListID;
  124. pListMember->usIstd = usIstd;
  125. pListMember->ucListLevel = ucListLevel;
  126. pListMember->pNext = NULL;
  127. /* Correct the values where needed */
  128. if (pListMember->tInfo.ulStartAt > 0xffff) {
  129. DBG_DEC(pListMember->tInfo.ulStartAt);
  130. pListMember->tInfo.ulStartAt = 1;
  131. }
  132. /* Add the new member to the list */
  133. if (pAnchor == NULL) {
  134. pAnchor = pListMember;
  135. } else {
  136. fail(pBlockLast == NULL);
  137. pBlockLast->pNext = pListMember;
  138. }
  139. pBlockLast = pListMember;
  140. } /* end of vAdd2ListInfoList */
  141. /*
  142. * Get a matching record from the List Information List
  143. *
  144. * Returns NULL if no matching records is found
  145. */
  146. const list_block_type *
  147. pGetListInfo(USHORT usListIndex, UCHAR ucListLevel)
  148. {
  149. list_desc_type *pCurr;
  150. list_block_type *pNearMatch;
  151. ULONG ulListID;
  152. if (usListIndex == 0) {
  153. return NULL;
  154. }
  155. if (usListIndex - 1 >= usLfoLen || ucListLevel > 8) {
  156. DBG_DEC(usListIndex);
  157. DBG_DEC(ucListLevel);
  158. return NULL;
  159. }
  160. fail(aulLfoList == NULL);
  161. ulListID = aulLfoList[usListIndex - 1];
  162. NO_DBG_HEX(ulListID);
  163. pNearMatch = NULL;
  164. for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
  165. if (pCurr->ulListID != ulListID) {
  166. /* No match */
  167. continue;
  168. }
  169. if (pCurr->ucListLevel == ucListLevel) {
  170. /* Exact match */
  171. return &pCurr->tInfo;
  172. }
  173. if (pCurr->ucListLevel == 0) {
  174. /* Near match */
  175. pNearMatch = &pCurr->tInfo;
  176. }
  177. }
  178. /* No exact match, use a near match if any */
  179. return pNearMatch;
  180. } /* end of pGetListInfo */
  181. /*
  182. * Get a matching record from the List Information List
  183. *
  184. * Returns NULL if no matching records is found
  185. */
  186. const list_block_type *
  187. pGetListInfoByIstd(USHORT usIstd)
  188. {
  189. list_desc_type *pCurr;
  190. if (usIstd == ISTD_INVALID || usIstd == STI_NIL || usIstd == STI_USER) {
  191. return NULL;
  192. }
  193. for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
  194. if (pCurr->usIstd == usIstd) {
  195. return &pCurr->tInfo;
  196. }
  197. }
  198. return NULL;
  199. } /* end of pGetListInfoByIstd */
  200. /*
  201. * vRestartListValues - reset the less significant list levels
  202. */
  203. static void
  204. vRestartListValues(USHORT usListIndex, UCHAR ucListLevel)
  205. {
  206. list_value_type *pPrev, *pCurr, *pNext;
  207. int iCounter;
  208. iCounter = 0;
  209. pPrev = NULL;
  210. pCurr = pValues;
  211. while (pCurr != NULL) {
  212. if (pCurr->usListIndex != usListIndex ||
  213. pCurr->ucListLevel <= ucListLevel) {
  214. pPrev = pCurr;
  215. pCurr = pCurr->pNext;
  216. continue;
  217. }
  218. /* Reset the level by deleting the record */
  219. pNext = pCurr->pNext;
  220. if (pPrev == NULL) {
  221. pValues = pNext;
  222. } else {
  223. pPrev->pNext = pNext;
  224. }
  225. DBG_DEC(pCurr->usListIndex);
  226. DBG_DEC(pCurr->ucListLevel);
  227. pCurr = xfree(pCurr);
  228. pCurr = pNext;
  229. iCounter++;
  230. }
  231. DBG_DEC_C(iCounter > 0, iCounter);
  232. } /* end of vRestartListValues */
  233. /*
  234. * usGetListValue - Get the current value of the given list
  235. *
  236. * Returns the value of the given list
  237. */
  238. USHORT
  239. usGetListValue(int iListSeqNumber, int iWordVersion,
  240. const style_block_type *pStyle)
  241. {
  242. list_value_type *pCurr;
  243. USHORT usValue;
  244. fail(iListSeqNumber < 0);
  245. fail(iListSeqNumber < iOldListSeqNumber);
  246. fail(iWordVersion < 0);
  247. fail(pStyle == NULL);
  248. if (iListSeqNumber <= 0) {
  249. return 0;
  250. }
  251. if (iWordVersion < 8) {
  252. /* Old style list */
  253. if (iListSeqNumber == iOldListSeqNumber ||
  254. (iListSeqNumber == iOldListSeqNumber + 1 &&
  255. eGetNumType(pStyle->ucNumLevel) == level_type_sequence)) {
  256. if (!pStyle->bNumPause) {
  257. usOldListValue++;
  258. }
  259. } else {
  260. usOldListValue = pStyle->usStartAt;
  261. }
  262. iOldListSeqNumber = iListSeqNumber;
  263. return usOldListValue;
  264. }
  265. /* New style list */
  266. if (pStyle->usListIndex == 0 ||
  267. pStyle->usListIndex - 1 >= usLfoLen ||
  268. pStyle->ucListLevel > 8) {
  269. /* Out of range; no need to search */
  270. return 0;
  271. }
  272. for (pCurr = pValues; pCurr != NULL; pCurr = pCurr->pNext) {
  273. if (pCurr->usListIndex == pStyle->usListIndex &&
  274. pCurr->ucListLevel == pStyle->ucListLevel) {
  275. /* Record found; increment and return the value */
  276. pCurr->usValue++;
  277. usValue = pCurr->usValue;
  278. if (!pStyle->bNoRestart) {
  279. vRestartListValues(pStyle->usListIndex,
  280. pStyle->ucListLevel);
  281. }
  282. return usValue;
  283. }
  284. }
  285. /* Record not found; create it and add it to the front of the list */
  286. pCurr = xmalloc(sizeof(list_value_type));
  287. pCurr->usValue = pStyle->usStartAt;
  288. pCurr->usListIndex = pStyle->usListIndex;
  289. pCurr->ucListLevel = pStyle->ucListLevel;
  290. pCurr->pNext = pValues;
  291. pValues = pCurr;
  292. usValue = pCurr->usValue;
  293. if (!pStyle->bNoRestart) {
  294. vRestartListValues(pStyle->usListIndex, pStyle->ucListLevel);
  295. }
  296. return usValue;
  297. } /* end of usGetListValue */