3 * Copyright (C) 2002-2004 A.J. van Os; Released under GNU GPL
6 * Read the property information from a Word for DOS file
15 * tConvertDosDate - convert DOS date format
17 * returns Unix time_t or -1
20 tConvertDosDate(const char *szDosDate
)
26 memset(&tTime
, 0, sizeof(tTime
));
29 if (!isdigit(*pcTmp
)) {
32 tTime
.tm_mon
= (int)(*pcTmp
- '0');
34 if (isdigit(*pcTmp
)) {
36 tTime
.tm_mon
+= (int)(*pcTmp
- '0');
39 /* Get the first separater */
40 if (isalnum(*pcTmp
)) {
45 if (!isdigit(*pcTmp
)) {
48 tTime
.tm_mday
= (int)(*pcTmp
- '0');
50 if (isdigit(*pcTmp
)) {
52 tTime
.tm_mday
+= (int)(*pcTmp
- '0');
55 /* Get the second separater */
56 if (isalnum(*pcTmp
)) {
61 if (!isdigit(*pcTmp
)) {
64 tTime
.tm_year
= (int)(*pcTmp
- '0');
66 if (isdigit(*pcTmp
)) {
68 tTime
.tm_year
+= (int)(*pcTmp
- '0');
71 /* Check the values */
72 if (tTime
.tm_mon
== 0 || tTime
.tm_mday
== 0 || tTime
.tm_mday
> 31) {
75 /* Correct the values */
76 tTime
.tm_mon
--; /* From 01-12 to 00-11 */
77 if (tTime
.tm_year
< 80) {
78 tTime
.tm_year
+= 100; /* 00 means 2000 is 100 */
81 tResult
= mktime(&tTime
);
82 NO_DBG_MSG(ctime(&tResult
));
84 } /* end of tConvertDosDate */
87 * Build the lists with Document Property Information for Word for DOS files
90 vGet0DopInfo(FILE *pFile
, const UCHAR
*aucHeader
)
92 document_block_type tDocument
;
94 ULONG ulBeginSumdInfo
, ulBeginNextBlock
;
98 tDocument
.ucHdrFtrSpecification
= 0;
99 tDocument
.usDefaultTabWidth
= usGetWord(0x70, aucHeader
); /* dxaTab */
100 tDocument
.tCreateDate
= (time_t)-1;
101 tDocument
.tRevisedDate
= (time_t)-1;
103 ulBeginSumdInfo
= 128 * (ULONG
)usGetWord(0x1c, aucHeader
);
104 DBG_HEX(ulBeginSumdInfo
);
105 ulBeginNextBlock
= 128 * (ULONG
)usGetWord(0x6a, aucHeader
);
106 DBG_HEX(ulBeginNextBlock
);
108 if (ulBeginSumdInfo
< ulBeginNextBlock
&& ulBeginNextBlock
!= 0) {
109 /* There is a summary information block */
110 tLen
= (size_t)(ulBeginNextBlock
- ulBeginSumdInfo
);
111 aucBuffer
= xmalloc(tLen
);
112 /* Read the summary information block */
113 if (bReadBytes(aucBuffer
, tLen
, ulBeginSumdInfo
, pFile
)) {
114 usOffset
= usGetWord(12, aucBuffer
);
115 if (aucBuffer
[usOffset
] != 0) {
116 NO_DBG_STRN(aucBuffer
+ usOffset
, 8);
117 tDocument
.tRevisedDate
=
118 tConvertDosDate((char *)aucBuffer
+ usOffset
);
120 usOffset
= usGetWord(14, aucBuffer
);
121 if (aucBuffer
[usOffset
] != 0) {
122 NO_DBG_STRN(aucBuffer
+ usOffset
, 8);
123 tDocument
.tCreateDate
=
124 tConvertDosDate((char *)aucBuffer
+ usOffset
);
127 aucBuffer
= xfree(aucBuffer
);
129 vCreateDocumentInfoList(&tDocument
);
130 } /* end of vGet0DopInfo */
133 * Fill the section information block with information
134 * from a Word for DOS file.
137 vGet0SectionInfo(const UCHAR
*aucGrpprl
, size_t tBytes
,
138 section_block_type
*pSection
)
143 fail(aucGrpprl
== NULL
|| pSection
== NULL
);
149 ucTmp
= ucGetByte(1, aucGrpprl
);
153 pSection
->bNewPage
= ucTmp
!= 0 && ucTmp
!= 1;
158 usCcol
= (USHORT
)ucGetByte(17, aucGrpprl
);
160 } /* end of vGet0SectionInfo */
163 * Build the lists with Section Property Information for Word for DOS files
166 vGet0SepInfo(FILE *pFile
, const UCHAR
*aucHeader
)
168 section_block_type tSection
;
170 ULONG ulBeginOfText
, ulTextOffset
, ulBeginSectInfo
;
171 ULONG ulCharPos
, ulSectPage
, ulBeginNextBlock
;
172 size_t tSectInfoLen
, tIndex
, tSections
, tBytes
;
173 UCHAR aucTmp
[2], aucFpage
[35];
175 fail(pFile
== NULL
|| aucHeader
== NULL
);
178 NO_DBG_HEX(ulBeginOfText
);
179 ulBeginSectInfo
= 128 * (ULONG
)usGetWord(0x18, aucHeader
);
180 DBG_HEX(ulBeginSectInfo
);
181 ulBeginNextBlock
= 128 * (ULONG
)usGetWord(0x1a, aucHeader
);
182 DBG_HEX(ulBeginNextBlock
);
183 if (ulBeginSectInfo
== ulBeginNextBlock
) {
184 /* There is no section information block */
188 /* Get the the number of sections */
189 if (!bReadBytes(aucTmp
, 2, ulBeginSectInfo
, pFile
)) {
192 tSections
= (size_t)usGetWord(0, aucTmp
);
193 NO_DBG_DEC(tSections
);
195 /* Read the Section Descriptors */
196 tSectInfoLen
= 10 * tSections
;
197 NO_DBG_DEC(tSectInfoLen
);
198 aucBuffer
= xmalloc(tSectInfoLen
);
199 if (!bReadBytes(aucBuffer
, tSectInfoLen
, ulBeginSectInfo
+ 4, pFile
)) {
200 aucBuffer
= xfree(aucBuffer
);
203 NO_DBG_PRINT_BLOCK(aucBuffer
, tSectInfoLen
);
205 /* Read the Section Properties */
206 for (tIndex
= 0; tIndex
< tSections
; tIndex
++) {
207 ulTextOffset
= ulGetLong(10 * tIndex
, aucBuffer
);
208 NO_DBG_HEX(ulTextOffset
);
209 ulCharPos
= ulBeginOfText
+ ulTextOffset
;
210 NO_DBG_HEX(ulTextOffset
);
211 ulSectPage
= ulGetLong(10 * tIndex
+ 6, aucBuffer
);
212 NO_DBG_HEX(ulSectPage
);
213 if (ulSectPage
== FC_INVALID
|| /* Must use defaults */
214 ulSectPage
< 128 || /* Should not happen */
215 ulSectPage
>= ulBeginSectInfo
) { /* Should not happen */
216 DBG_HEX_C(ulSectPage
!= FC_INVALID
, ulSectPage
);
217 vDefault2SectionInfoList(ulCharPos
);
220 /* Get the number of bytes to read */
221 if (!bReadBytes(aucTmp
, 1, ulSectPage
, pFile
)) {
224 tBytes
= 1 + (size_t)ucGetByte(0, aucTmp
);
226 if (tBytes
> sizeof(aucFpage
)) {
228 tBytes
= sizeof(aucFpage
);
231 if (!bReadBytes(aucFpage
, tBytes
, ulSectPage
, pFile
)) {
234 NO_DBG_PRINT_BLOCK(aucFpage
, tBytes
);
235 /* Process the bytes */
236 vGetDefaultSection(&tSection
);
237 vGet0SectionInfo(aucFpage
+ 1, tBytes
- 1, &tSection
);
238 vAdd2SectionInfoList(&tSection
, ulCharPos
);
240 /* Clean up before you leave */
241 aucBuffer
= xfree(aucBuffer
);
242 } /* end of vGet0SepInfo */
245 * Fill the style information block with information
246 * from a Word for DOS file.
249 vGet0StyleInfo(int iFodo
, const UCHAR
*aucGrpprl
, style_block_type
*pStyle
)
254 fail(iFodo
<= 0 || aucGrpprl
== NULL
|| pStyle
== NULL
);
256 pStyle
->usIstdNext
= ISTD_NORMAL
;
258 iBytes
= (int)ucGetByte(iFodo
, aucGrpprl
);
263 ucTmp
= ucGetByte(iFodo
+ 1, aucGrpprl
);
264 if ((ucTmp
& BIT(0)) != 0) {
266 if (ucTmp
>= 88 && ucTmp
<= 94) {
267 /* Header levels 1 through 7 */
268 pStyle
->usIstd
= ucTmp
- 87;
269 pStyle
->ucNumLevel
= 1;
276 ucTmp
= ucGetByte(iFodo
+ 2, aucGrpprl
);
277 pStyle
->ucAlignment
= ucTmp
& 0x02;
282 ucTmp
= ucGetByte(iFodo
+ 3, aucGrpprl
);
284 if (ucTmp
>= 88 && ucTmp
<= 94) {
285 /* Header levels 1 through 7 */
286 pStyle
->usIstd
= ucTmp
- 87;
287 pStyle
->ucNumLevel
= 1;
293 pStyle
->sRightIndent
= (short)usGetWord(iFodo
+ 5, aucGrpprl
);
294 NO_DBG_DEC(pStyle
->sRightIndent
);
299 pStyle
->sLeftIndent
= (short)usGetWord(iFodo
+ 7, aucGrpprl
);
300 NO_DBG_DEC(pStyle
->sLeftIndent
);
305 pStyle
->sLeftIndent1
= (short)usGetWord(iFodo
+ 9, aucGrpprl
);
306 NO_DBG_DEC(pStyle
->sLeftIndent1
);
311 pStyle
->usBeforeIndent
= usGetWord(iFodo
+ 13, aucGrpprl
);
312 NO_DBG_DEC(pStyle
->usBeforeIndent
);
317 pStyle
->usAfterIndent
= usGetWord(iFodo
+ 15, aucGrpprl
);
318 NO_DBG_DEC(pStyle
->usAfterIndent
);
319 } /* end of vGet0StyleInfo */
322 * Build the lists with Paragraph Information for Word for DOS files
325 vGet0PapInfo(FILE *pFile
, const UCHAR
*aucHeader
)
327 style_block_type tStyle
;
328 ULONG ulBeginParfInfo
, ulCharPos
, ulCharPosNext
;
329 int iIndex
, iRun
, iFodo
;
332 fail(pFile
== NULL
|| aucHeader
== NULL
);
334 ulBeginParfInfo
= 128 * (ULONG
)usGetWord(0x12, aucHeader
);
335 NO_DBG_HEX(ulBeginParfInfo
);
338 if (!bReadBytes(aucFpage
, 128, ulBeginParfInfo
, pFile
)) {
341 NO_DBG_PRINT_BLOCK(aucFpage
, 128);
342 ulCharPosNext
= ulGetLong(0, aucFpage
);
343 iRun
= (int)ucGetByte(0x7f, aucFpage
);
345 for (iIndex
= 0; iIndex
< iRun
; iIndex
++) {
346 iFodo
= (int)usGetWord(6 * iIndex
+ 8, aucFpage
);
347 if (iFodo
<= 0 || iFodo
> 0x79) {
348 DBG_DEC_C(iFodo
!= (int)0xffff, iFodo
);
351 vFillStyleFromStylesheet(0, &tStyle
);
352 vGet0StyleInfo(iFodo
, aucFpage
+ 4, &tStyle
);
353 ulCharPos
= ulCharPosNext
;
354 ulCharPosNext
= ulGetLong(6 * iIndex
+ 4, aucFpage
);
355 tStyle
.ulFileOffset
= ulCharPos
;
356 vAdd2StyleInfoList(&tStyle
);
358 ulBeginParfInfo
+= 128;
359 } while (ulCharPosNext
== ulBeginParfInfo
);
360 } /* end of vGet0PapInfo */
363 * Fill the font information block with information
364 * from a Word for DOS file.
367 vGet0FontInfo(int iFodo
, const UCHAR
*aucGrpprl
, font_block_type
*pFont
)
372 fail(iFodo
<= 0 || aucGrpprl
== NULL
|| pFont
== NULL
);
374 iBytes
= (int)ucGetByte(iFodo
, aucGrpprl
);
378 /* fBold, fItalic, cFtc */
379 ucTmp
= ucGetByte(iFodo
+ 2, aucGrpprl
);
380 if ((ucTmp
& BIT(0)) != 0) {
381 pFont
->usFontStyle
|= FONT_BOLD
;
383 if ((ucTmp
& BIT(1)) != 0) {
384 pFont
->usFontStyle
|= FONT_ITALIC
;
386 pFont
->ucFontNumber
= ucTmp
>> 2;
387 NO_DBG_DEC(pFont
->ucFontNumber
);
392 pFont
->usFontSize
= (USHORT
)ucGetByte(iFodo
+ 3, aucGrpprl
);
393 NO_DBG_DEC(pFont
->usFontSize
);
397 /* cKul, fStrike, fCaps, fSmallCaps, fVanish */
398 ucTmp
= ucGetByte(iFodo
+ 4, aucGrpprl
);
399 if ((ucTmp
& BIT(0)) != 0 || (ucTmp
& BIT(2)) != 0) {
400 pFont
->usFontStyle
|= FONT_UNDERLINE
;
402 if ((ucTmp
& BIT(1)) != 0) {
403 pFont
->usFontStyle
|= FONT_STRIKE
;
405 if ((ucTmp
& BIT(4)) != 0) {
406 pFont
->usFontStyle
|= FONT_CAPITALS
;
408 if ((ucTmp
& BIT(5)) != 0) {
409 pFont
->usFontStyle
|= FONT_SMALL_CAPITALS
;
411 if ((ucTmp
& BIT(7)) != 0) {
412 pFont
->usFontStyle
|= FONT_HIDDEN
;
414 DBG_HEX(pFont
->usFontStyle
);
419 ucTmp
= ucGetByte(iFodo
+ 6, aucGrpprl
);
422 pFont
->usFontStyle
|= FONT_SUPERSCRIPT
;
423 DBG_MSG("Superscript");
425 pFont
->usFontStyle
|= FONT_SUBSCRIPT
;
426 DBG_MSG("Subscript");
433 ucTmp
= ucGetByte(iFodo
+ 7, aucGrpprl
);
434 switch (ucTmp
& 0x07) {
435 case 0: pFont
->ucFontColor
= FONT_COLOR_BLACK
; break;
436 case 1: pFont
->ucFontColor
= FONT_COLOR_RED
; break;
437 case 2: pFont
->ucFontColor
= FONT_COLOR_GREEN
; break;
438 case 3: pFont
->ucFontColor
= FONT_COLOR_BLUE
; break;
439 case 4: pFont
->ucFontColor
= FONT_COLOR_CYAN
; break;
440 case 5: pFont
->ucFontColor
= FONT_COLOR_MAGENTA
; break;
441 case 6: pFont
->ucFontColor
= FONT_COLOR_YELLOW
; break;
442 case 7: pFont
->ucFontColor
= FONT_COLOR_WHITE
; break;
443 default:pFont
->ucFontColor
= FONT_COLOR_BLACK
; break;
445 NO_DBG_DEC(pFont
->ucFontColor
);
446 } /* end of vGet0FontInfo */
449 * Build the lists with Character Information for Word for DOS files
452 vGet0ChrInfo(FILE *pFile
, const UCHAR
*aucHeader
)
454 font_block_type tFont
;
455 ULONG ulBeginCharInfo
, ulCharPos
, ulCharPosNext
;
456 int iIndex
, iRun
, iFodo
;
459 fail(pFile
== NULL
|| aucHeader
== NULL
);
461 ulBeginCharInfo
= ulGetLong(0x0e, aucHeader
);
462 NO_DBG_HEX(ulBeginCharInfo
);
463 ulBeginCharInfo
= ROUND128(ulBeginCharInfo
);
464 NO_DBG_HEX(ulBeginCharInfo
);
467 if (!bReadBytes(aucFpage
, 128, ulBeginCharInfo
, pFile
)) {
470 NO_DBG_PRINT_BLOCK(aucFpage
, 128);
471 ulCharPosNext
= ulGetLong(0, aucFpage
);
472 iRun
= (int)ucGetByte(0x7f, aucFpage
);
474 for (iIndex
= 0; iIndex
< iRun
; iIndex
++) {
475 iFodo
= (int)usGetWord(6 * iIndex
+ 8, aucFpage
);
476 if (iFodo
<= 0 || iFodo
> 0x79) {
477 DBG_DEC_C(iFodo
!= (int)0xffff, iFodo
);
480 vFillFontFromStylesheet(0, &tFont
);
481 vGet0FontInfo(iFodo
, aucFpage
+ 4, &tFont
);
482 ulCharPos
= ulCharPosNext
;
483 ulCharPosNext
= ulGetLong(6 * iIndex
+ 4, aucFpage
);
484 tFont
.ulFileOffset
= ulCharPos
;
485 vAdd2FontInfoList(&tFont
);
487 ulBeginCharInfo
+= 128;
488 } while (ulCharPosNext
== ulBeginCharInfo
);
489 } /* end of vGet0ChrInfo */