cleanup, convert to cmake project

This commit is contained in:
2020-11-12 17:07:06 -05:00
parent 71f6baaafa
commit 48c8d75767
146 changed files with 1757 additions and 13961 deletions

735
src/antiword.h Normal file
View File

@@ -0,0 +1,735 @@
/*
* antiword.h
* Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Generic include file for project 'Antiword'
*/
#if !defined(__antiword_h)
#define __antiword_h 1
#if defined(DEBUG) == defined(NDEBUG)
#error Exactly one of the DEBUG and NDEBUG flags MUST be set
#endif /* DEBUG == NDEBUG */
#include <stdio.h>
#include <limits.h>
#if defined(__riscos)
#include "DeskLib:Font.h"
#include "DeskLib:Wimp.h"
#include "Desklib:Window.h"
#include "drawfile.h"
#define window_ANY event_ANY
#define icon_ANY event_ANY
#else
#include <sys/types.h>
#endif /* __riscos */
#include "wordconst.h"
#include "wordtypes.h"
#include "fail.h"
#include "debug.h"
/* Constants */
#if !defined(PATH_MAX)
#if defined(__riscos)
#define PATH_MAX 255
#else
#if defined(MAXPATHLEN)
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX 1024
#endif /* MAXPATHLEN */
#endif /* __riscos */
#endif /* !PATH_MAX */
#if !defined(CHAR_BIT)
#define CHAR_BIT 8
#endif /* CHAR_BIT */
#if !defined(TIME_T_MIN)
#define TIME_T_MIN ((time_t)0 < (time_t)-1 ?\
(time_t)0 :\
(time_t)1 << (sizeof(time_t) * CHAR_BIT - 1))
#endif /* TIMER_T_MIN */
#if !defined(TIME_T_MAX)
#if defined(__TURBOC__) /* Turbo C chokes on the subtraction below */
#define TIME_T_MAX (LONG_MAX)
#else /* All others */
#define TIME_T_MAX (~(time_t)0 - TIME_T_MIN)
#endif /* __TURBOC__ */
#endif /* TIME_T_MAX */
#if !defined(SIZE_T_MAX)
#define SIZE_T_MAX (~(size_t)0)
#endif /* SIZE_T_MAX */
#if defined(__riscos)
#define FILE_SEPARATOR "."
#elif defined(__dos) || defined(__CYGMING__)
#define FILE_SEPARATOR "\\"
#else /* All others */
#define FILE_SEPARATOR "/"
#endif /* __riscos */
/* PNG chunk names */
#define PNG_CN_IDAT 0x49444154
#define PNG_CN_IEND 0x49454e44
#define PNG_CN_IHDR 0x49484452
#define PNG_CN_PLTE 0x504c5445
/* The screen width */
#define MIN_SCREEN_WIDTH 45
#define DEFAULT_SCREEN_WIDTH 76
#define MAX_SCREEN_WIDTH 145
#if defined(__riscos)
/* The scale factors as percentages */
#define MIN_SCALE_FACTOR 25
#define DEFAULT_SCALE_FACTOR 100
#define MAX_SCALE_FACTOR 400
/* Filetypes */
#define FILETYPE_MSWORD 0xae6
#define FILETYPE_DRAW 0xaff
#define FILETYPE_JPEG 0xc85
#define FILETYPE_POSCRIPT 0xff5
#define FILETYPE_SPRITE 0xff9
#define FILETYPE_TEXT 0xfff
/* The button numbers in the choices window */
#define CHOICES_DEFAULT_BUTTON 3
#define CHOICES_SAVE_BUTTON 2
#define CHOICES_CANCEL_BUTTON 1
#define CHOICES_APPLY_BUTTON 0
#define CHOICES_BREAK_BUTTON 6
#define CHOICES_BREAK_WRITEABLE 7
#define CHOICES_BREAK_UP_BUTTON 8
#define CHOICES_BREAK_DOWN_BUTTON 9
#define CHOICES_NO_BREAK_BUTTON 11
#define CHOICES_AUTOFILETYPE_BUTTON 14
#define CHOICES_HIDDEN_TEXT_BUTTON 22
#define CHOICES_WITH_IMAGES_BUTTON 17
#define CHOICES_NO_IMAGES_BUTTON 18
#define CHOICES_TEXTONLY_BUTTON 19
#define CHOICES_SCALE_WRITEABLE 25
#define CHOICES_SCALE_UP_BUTTON 26
#define CHOICES_SCALE_DOWN_BUTTON 27
/* The button numbers in the scale view window */
#define SCALE_CANCEL_BUTTON 1
#define SCALE_SCALE_BUTTON 0
#define SCALE_SCALE_WRITEABLE 3
#define SCALE_50_PCT 5
#define SCALE_75_PCT 6
#define SCALE_100_PCT 7
#define SCALE_150_PCT 8
/* Save menu fields */
#define SAVEMENU_SCALEVIEW 0
#define SAVEMENU_SAVEDRAW 1
#define SAVEMENU_SAVETEXT 2
#else
/* Margins for the PostScript version */
#define PS_LEFT_MARGIN (72 * 640L)
#define PS_RIGHT_MARGIN (48 * 640L)
#define PS_TOP_MARGIN (72 * 640L)
#define PS_BOTTOM_MARGIN (72 * 640L)
#endif /* __riscos */
/* Macros */
#define STREQ(x,y) (*(x) == *(y) && strcmp(x,y) == 0)
#define STRNEQ(x,y,n) (*(x) == *(y) && strncmp(x,y,n) == 0)
#if defined(__dos) || defined(__EMX__)
#define STRCEQ(x,y) (stricmp(x,y) == 0)
#else
#define STRCEQ(x,y) (strcasecmp(x,y) == 0)
#endif /* __dos or __EMX__ */
#define elementsof(a) (sizeof(a) / sizeof(a[0]))
#define odd(x) (((x)&0x01)!=0)
#define ROUND4(x) (((x)+3)&~0x03)
#define ROUND128(x) (((x)+127)&~0x7f)
#define BIT(x) (1UL << (x))
#if !defined(max)
#define max(x,y) ((x)>(y)?(x):(y))
#endif /* !max */
#if !defined(min)
#define min(x,y) ((x)<(y)?(x):(y))
#endif /* !min */
#if defined(__riscos)
/* The name of the table font */
#define TABLE_FONT "Corpus.Medium"
/* Names of the default fonts */
#define FONT_MONOSPACED_PLAIN "Corpus.Medium"
#define FONT_MONOSPACED_BOLD "Corpus.Bold"
#define FONT_MONOSPACED_ITALIC "Corpus.Medium.Oblique"
#define FONT_MONOSPACED_BOLDITALIC "Corpus.Bold.Oblique"
#define FONT_SERIF_PLAIN "Trinity.Medium"
#define FONT_SERIF_BOLD "Trinity.Bold"
#define FONT_SERIF_ITALIC "Trinity.Medium.Italic"
#define FONT_SERIF_BOLDITALIC "Trinity.Bold.Italic"
#define FONT_SANS_SERIF_PLAIN "Homerton.Medium"
#define FONT_SANS_SERIF_BOLD "Homerton.Bold"
#define FONT_SANS_SERIF_ITALIC "Homerton.Medium.Oblique"
#define FONT_SANS_SERIF_BOLDITALIC "Homerton.Bold.Oblique"
#else
/* The name of the table font */
#define TABLE_FONT "Courier"
/* Names of the default fonts */
#define FONT_MONOSPACED_PLAIN "Courier"
#define FONT_MONOSPACED_BOLD "Courier-Bold"
#define FONT_MONOSPACED_ITALIC "Courier-Oblique"
#define FONT_MONOSPACED_BOLDITALIC "Courier-BoldOblique"
#define FONT_SERIF_PLAIN "Times-Roman"
#define FONT_SERIF_BOLD "Times-Bold"
#define FONT_SERIF_ITALIC "Times-Italic"
#define FONT_SERIF_BOLDITALIC "Times-BoldItalic"
#define FONT_SANS_SERIF_PLAIN "Helvetica"
#define FONT_SANS_SERIF_BOLD "Helvetica-Bold"
#define FONT_SANS_SERIF_ITALIC "Helvetica-Oblique"
#define FONT_SANS_SERIF_BOLDITALIC "Helvetica-BoldOblique"
/* The name of the antiword directories and the font information file */
#if defined(__dos)
#define GLOBAL_ANTIWORD_DIR "C:\\antiword"
#define ANTIWORD_DIR "antiword"
#define FONTNAMES_FILE "fontname.txt"
#elif defined(__amigaos)
#define GLOBAL_ANTIWORD_DIR "SYS:.antiword"
#define ANTIWORD_DIR ".antiword"
#define FONTNAMES_FILE "fontnames"
#elif defined(N_PLAT_NLM)
#define GLOBAL_ANTIWORD_DIR "SYS:/antiword"
#define ANTIWORD_DIR "antiword"
#define FONTNAMES_FILE "fontname.txt"
#elif defined(__vms)
#define GLOBAL_ANTIWORD_DIR "/usr/share/antiword"
#define ANTIWORD_DIR "antiword"
#define FONTNAMES_FILE "fontnames"
#elif defined(__BEOS__)
#define GLOBAL_ANTIWORD_DIR "/boot/home/config/apps/antiword"
#define ANTIWORD_DIR "antiword"
#define FONTNAMES_FILE "fontnames"
#elif defined(__CYGMING__)
#define GLOBAL_ANTIWORD_DIR "C:\\antiword"
#define ANTIWORD_DIR "antiword"
#define FONTNAMES_FILE "fontnames"
#elif defined(__Plan9__)
#define GLOBAL_ANTIWORD_DIR "/sys/lib/antiword"
#define ANTIWORD_DIR "lib/antiword"
#define FONTNAMES_FILE "fontnames"
#elif defined(__sun__)
#define GLOBAL_ANTIWORD_DIR "/usr/local/share/antiword"
#define ANTIWORD_DIR ".antiword"
#define FONTNAMES_FILE "fontnames"
#else /* All others */
#define GLOBAL_ANTIWORD_DIR "/usr/share/antiword"
#define ANTIWORD_DIR ".antiword"
#define FONTNAMES_FILE "fontnames"
#endif /* __dos */
/* The names of grouped mapping files */
/* ASCII */
#define MAPPING_FILE_CP437 "cp437.txt"
/* Latin1 */
#define MAPPING_FILE_8859_1 "8859-1.txt"
/* Latin2 */
#define MAPPING_FILE_8859_2 "8859-2.txt"
#define MAPPING_FILE_CP852 "cp852.txt"
#define MAPPING_FILE_CP1250 "cp1250.txt"
/* Cyrillic */
#define MAPPING_FILE_8859_5 "8859-5.txt"
#define MAPPING_FILE_KOI8_R "koi8-r.txt"
#define MAPPING_FILE_KOI8_U "koi8-u.txt"
#define MAPPING_FILE_CP866 "cp866.txt"
#define MAPPING_FILE_CP1251 "cp1251.txt"
/* Latin9 */
#define MAPPING_FILE_8859_15 "8859-15.txt"
/* UTF-8 */
#define MAPPING_FILE_UTF_8 "UTF-8.txt"
#endif /* __riscos */
/* Prototypes */
/* asc85enc.c */
extern void vASCII85EncodeByte(FILE *, int);
extern void vASCII85EncodeArray(FILE *, FILE *, size_t);
extern void vASCII85EncodeFile(FILE *, FILE *, size_t);
/* blocklist.c */
extern void vDestroyTextBlockList(void);
extern BOOL bAdd2TextBlockList(const text_block_type *);
extern void vSplitBlockList(FILE *, ULONG, ULONG, ULONG, ULONG, ULONG,
ULONG, ULONG, ULONG, BOOL);
extern BOOL bExistsHdrFtr(void);
extern BOOL bExistsTextBox(void);
extern BOOL bExistsHdrTextBox(void);
extern USHORT usNextChar(FILE *, list_id_enum, ULONG *, ULONG *, USHORT *);
extern USHORT usToHdrFtrPosition(FILE *, ULONG);
extern USHORT usToFootnotePosition(FILE *, ULONG);
extern ULONG ulCharPos2FileOffsetX(ULONG, list_id_enum *);
extern ULONG ulCharPos2FileOffset(ULONG);
extern ULONG ulHdrFtrOffset2CharPos(ULONG);
extern ULONG ulGetSeqNumber(ULONG);
#if defined(__riscos)
extern ULONG ulGetDocumentLength(void);
#endif /* __riscos */
/* chartrans.c */
extern UCHAR ucGetBulletCharacter(conversion_type, encoding_type);
extern UCHAR ucGetNbspCharacter(void);
extern BOOL bReadCharacterMappingTable(FILE *);
extern ULONG ulTranslateCharacters(USHORT, ULONG, int, conversion_type,
encoding_type, BOOL);
extern ULONG ulToUpper(ULONG);
/* datalist.c */
extern void vDestroyDataBlockList(void);
extern BOOL bAdd2DataBlockList(const data_block_type *);
extern ULONG ulGetDataOffset(FILE *);
extern BOOL bSetDataOffset(FILE *, ULONG);
extern int iNextByte(FILE *);
extern USHORT usNextWord(FILE *);
extern ULONG ulNextLong(FILE *);
extern USHORT usNextWordBE(FILE *);
extern ULONG ulNextLongBE(FILE *);
extern size_t tSkipBytes(FILE *, size_t);
extern ULONG ulDataPos2FileOffset(ULONG);
/* depot.c */
extern void vDestroySmallBlockList(void);
extern BOOL bCreateSmallBlockList(ULONG, const ULONG *, size_t);
extern ULONG ulDepotOffset(ULONG, size_t);
/* dib2eps & dib2sprt.c */
extern BOOL bTranslateDIB(diagram_type *,
FILE *, ULONG, const imagedata_type *);
#if defined(__dos)
/* dos.c */
extern int iGetCodepage(void);
#endif /* __dos */
/* doclist.c */
extern void vDestroyDocumentInfoList(void);
extern void vCreateDocumentInfoList(const document_block_type *);
extern UCHAR ucGetDopHdrFtrSpecification(void);
/* draw.c & output.c */
extern BOOL bAddDummyImage(diagram_type *, const imagedata_type *);
extern diagram_type *pCreateDiagram(const char *, const char *);
extern void vPrologue2(diagram_type *, int);
extern void vMove2NextLine(diagram_type *, drawfile_fontref, USHORT);
extern void vSubstring2Diagram(diagram_type *,
char *, size_t, long, UCHAR, USHORT,
drawfile_fontref, USHORT, USHORT);
extern void vStartOfParagraph1(diagram_type *, long);
extern void vStartOfParagraph2(diagram_type *);
extern void vEndOfParagraph(diagram_type *, drawfile_fontref, USHORT, long);
extern void vEndOfPage(diagram_type *, long, BOOL);
extern void vSetHeaders(diagram_type *, USHORT);
extern void vStartOfList(diagram_type *, UCHAR, BOOL);
extern void vEndOfList(diagram_type *);
extern void vStartOfListItem(diagram_type *, BOOL);
extern void vEndOfTable(diagram_type *);
extern BOOL bAddTableRow(diagram_type *, char **, int,
const short *, UCHAR);
#if defined(__riscos)
extern BOOL bDestroyDiagram(event_pollblock *, void *);
extern void vImage2Diagram(diagram_type *, const imagedata_type *,
UCHAR *, size_t);
extern BOOL bVerifyDiagram(diagram_type *);
extern void vShowDiagram(diagram_type *);
extern void vMainButtonClick(mouse_block *);
extern BOOL bMainKeyPressed(event_pollblock *, void *);
extern BOOL bMainEventHandler(event_pollblock *, void *);
extern BOOL bRedrawMainWindow(event_pollblock *, void *);
extern BOOL bScaleOpenAction(event_pollblock *, void *);
extern void vSetTitle(diagram_type *);
extern void vScaleButtonClick(mouse_block *, diagram_type *);
extern BOOL bScaleKeyPressed(event_pollblock *, void *);
extern BOOL bScaleEventHandler(event_pollblock *, void *);
#else
extern void vImagePrologue(diagram_type *, const imagedata_type *);
extern void vImageEpilogue(diagram_type *);
extern void vDestroyDiagram(diagram_type *);
#endif /* __riscos */
/* finddata.c */
extern BOOL bAddDataBlocks(ULONG , ULONG, ULONG, const ULONG *, size_t);
extern BOOL bGet6DocumentData(FILE *, ULONG,
const ULONG *, size_t, const UCHAR *);
/* findtext.c */
extern BOOL bAddTextBlocks(ULONG , ULONG, BOOL,
USHORT, ULONG, const ULONG *, size_t);
extern BOOL bGet6DocumentText(FILE *, BOOL, ULONG,
const ULONG *, size_t, const UCHAR *);
extern BOOL bGet8DocumentText(FILE *, const pps_info_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *);
/* fmt_text.c */
extern void vPrologueFMT(diagram_type *, const options_type *);
extern void vSubstringFMT(diagram_type *, const char *, size_t, long,
USHORT);
/* fontlist.c */
extern void vDestroyFontInfoList(void);
extern void vCorrectFontValues(font_block_type *);
extern void vAdd2FontInfoList(const font_block_type *);
extern const font_block_type *pGetNextFontInfoListItem(
const font_block_type *);
/* fonts.c */
extern int iGetFontByNumber(UCHAR, USHORT);
extern const char *szGetOurFontname(int);
extern int iFontname2Fontnumber(const char *, USHORT);
extern void vCreate0FontTable(void);
extern void vCreate2FontTable(FILE *, int, const UCHAR *);
extern void vCreate6FontTable(FILE *, ULONG,
const ULONG *, size_t, const UCHAR *);
extern void vCreate8FontTable(FILE *, const pps_info_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *);
extern void vDestroyFontTable(void);
extern const font_table_type *pGetNextFontTableRecord(
const font_table_type *);
extern size_t tGetFontTableLength(void);
extern void vCorrectFontTable(conversion_type, encoding_type);
extern long lComputeSpaceWidth(drawfile_fontref, USHORT);
/* fonts_r.c & fonts_u.c */
extern FILE *pOpenFontTableFile(void);
extern void vCloseFont(void);
extern drawfile_fontref tOpenFont(UCHAR, USHORT, USHORT);
extern drawfile_fontref tOpenTableFont(USHORT);
extern long lComputeStringWidth(const char *, size_t, drawfile_fontref, USHORT);
extern size_t tCountColumns(const char *, size_t);
extern size_t tGetCharacterLength(const char *);
/* fonts_u.c */
#if !defined(__riscos)
extern const char *szGetFontname(drawfile_fontref);
#endif /* !__riscos */
/* hdrftrlist.c */
extern void vDestroyHdrFtrInfoList(void);
extern void vCreat8HdrFtrInfoList(const ULONG *, size_t);
extern void vCreat6HdrFtrInfoList(const ULONG *, size_t);
extern void vCreat2HdrFtrInfoList(const ULONG *, size_t);
extern const hdrftr_block_type *pGetHdrFtrInfo(int, BOOL, BOOL, BOOL);
extern void vPrepareHdrFtrText(FILE *);
#if defined(__riscos)
/* icons.c */
extern void vUpdateIcon(window_handle, icon_block *);
extern void vUpdateRadioButton(window_handle, icon_handle, BOOL);
extern void vUpdateWriteable(window_handle, icon_handle, const char *);
extern void vUpdateWriteableNumber(window_handle, icon_handle, int);
#endif /* __riscos */
/* imgexam.c */
extern image_info_enum eExamineImage(FILE *, ULONG, imagedata_type *);
/* imgtrans */
extern BOOL bTranslateImage(diagram_type *,
FILE *, BOOL, ULONG, const imagedata_type *);
/* jpeg2eps.c & jpeg2spr.c */
extern BOOL bTranslateJPEG(diagram_type *,
FILE *, ULONG, size_t, const imagedata_type *);
/* listlist.c */
extern void vDestroyListInfoList(void);
extern void vBuildLfoList(const UCHAR *, size_t);
extern void vAdd2ListInfoList(ULONG, USHORT, UCHAR,
const list_block_type *);
extern const list_block_type *pGetListInfo(USHORT, UCHAR);
extern USHORT usGetListValue(int, int, const style_block_type *);
/* misc.c */
#if !defined(__riscos)
extern const char *szGetHomeDirectory(void);
extern const char *szGetAntiwordDirectory(void);
#endif /* !__riscos */
extern long lGetFilesize(const char *);
#if defined(DEBUG)
extern void vPrintBlock(const char *, int, const UCHAR *, size_t);
extern void vPrintUnicode(const char *, int, const UCHAR *, size_t);
extern BOOL bCheckDoubleLinkedList(output_type *);
#endif /* DEBUG */
extern BOOL bReadBytes(UCHAR *, size_t, ULONG, FILE *);
extern BOOL bReadBuffer(FILE *, ULONG, const ULONG *, size_t, size_t,
UCHAR *, ULONG, size_t);
extern ULONG ulColor2Color(UCHAR);
extern output_type *pSplitList(output_type *);
extern size_t tNumber2Roman(UINT, BOOL, char *);
extern size_t tNumber2Alpha(UINT, BOOL, char *);
extern char *unincpy(char *, const UCHAR *, size_t);
extern size_t unilen(const UCHAR *);
extern const char *szBasename(const char *);
extern long lComputeLeading(USHORT);
extern size_t tUcs2Utf8(ULONG, char *, size_t);
extern void vGetBulletValue(conversion_type, encoding_type, char *, size_t);
extern BOOL bAllZero(const UCHAR *, size_t);
extern BOOL bGetNormalizedCodeset(char *, size_t, BOOL *);
extern const char *szGetDefaultMappingFile(void);
extern time_t tConvertDTTM(ULONG);
/* notes.c */
extern void vDestroyNotesInfoLists(void);
extern void vGetNotesInfo(FILE *, const pps_info_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *, int);
extern void vPrepareFootnoteText(FILE *);
extern const char *szGetFootnootText(UINT);
extern notetype_enum eGetNotetype(ULONG);
/* options.c */
extern int iReadOptions(int, char **);
extern void vGetOptions(options_type *);
#if defined(__riscos)
extern void vChoicesOpenAction(window_handle);
extern BOOL bChoicesMouseClick(event_pollblock *, void *);
extern BOOL bChoicesKeyPressed(event_pollblock *, void *);
#endif /* __riscos */
/* out2window.c */
extern void vSetLeftIndentation(diagram_type *, long);
extern void vAlign2Window(diagram_type *, output_type *,
long, UCHAR);
extern void vJustify2Window(diagram_type *, output_type *,
long, long, UCHAR);
extern void vResetStyles(void);
extern size_t tStyle2Window(char *, size_t, const style_block_type *,
const section_block_type *);
extern void vTableRow2Window(diagram_type *, output_type *,
const row_block_type *, conversion_type, int);
/* pdf.c */
extern void vCreateInfoDictionary(diagram_type *, int);
extern void vProloguePDF(diagram_type *,
const char *, const options_type *);
extern void vEpiloguePDF(diagram_type *);
extern void vImageProloguePDF(diagram_type *, const imagedata_type *);
extern void vImageEpiloguePDF(diagram_type *);
extern BOOL bAddDummyImagePDF(diagram_type *, const imagedata_type *);
extern void vAddFontsPDF(diagram_type *);
extern void vMove2NextLinePDF(diagram_type *, USHORT);
extern void vSubstringPDF(diagram_type *,
char *, size_t, long, UCHAR, USHORT,
drawfile_fontref, USHORT, USHORT);
extern void vStartOfParagraphPDF(diagram_type *, long);
extern void vEndOfParagraphPDF(diagram_type *, USHORT, long);
extern void vEndOfPagePDF(diagram_type *, BOOL);
/* pictlist.c */
extern void vDestroyPictInfoList(void);
extern void vAdd2PictInfoList(const picture_block_type *);
extern ULONG ulGetPictInfoListItem(ULONG);
/* png2eps.c & png2spr.c */
extern BOOL bTranslatePNG(diagram_type *,
FILE *, ULONG, size_t, const imagedata_type *);
/* postscript.c */
extern void vProloguePS(diagram_type *,
const char *, const char *, const options_type *);
extern void vEpiloguePS(diagram_type *);
extern void vImageProloguePS(diagram_type *, const imagedata_type *);
extern void vImageEpiloguePS(diagram_type *);
extern BOOL bAddDummyImagePS(diagram_type *, const imagedata_type *);
extern void vAddFontsPS(diagram_type *);
extern void vMove2NextLinePS(diagram_type *, USHORT);
extern void vSubstringPS(diagram_type *,
char *, size_t, long, UCHAR, USHORT,
drawfile_fontref, USHORT, USHORT);
extern void vStartOfParagraphPS(diagram_type *, long);
extern void vEndOfParagraphPS(diagram_type *, USHORT, long);
extern void vEndOfPagePS(diagram_type *, BOOL);
/* prop0.c */
extern void vGet0DopInfo(FILE *, const UCHAR *);
extern void vGet0SepInfo(FILE *, const UCHAR *);
extern void vGet0PapInfo(FILE *, const UCHAR *);
extern void vGet0ChrInfo(FILE *, const UCHAR *);
/* prop2.c */
extern void vGet2DopInfo(FILE *, const UCHAR *);
extern void vGet2SepInfo(FILE *, const UCHAR *);
extern void vGet2HdrFtrInfo(FILE *, const UCHAR *);
extern row_info_enum eGet2RowInfo(int,
const UCHAR *, int, row_block_type *);
extern void vGet2StyleInfo(int,
const UCHAR *, int, style_block_type *);
extern void vGet2PapInfo(FILE *, const UCHAR *);
extern void vGet1FontInfo(int,
const UCHAR *, size_t, font_block_type *);
extern void vGet2FontInfo(int,
const UCHAR *, size_t, font_block_type *);
extern void vGet2ChrInfo(FILE *, int, const UCHAR *);
/* prop6.c */
extern void vGet6DopInfo(FILE *, ULONG, const ULONG *, size_t,
const UCHAR *);
extern void vGet6SepInfo(FILE *, ULONG, const ULONG *, size_t,
const UCHAR *);
extern void vGet6HdrFtrInfo(FILE *, ULONG, const ULONG *, size_t,
const UCHAR *);
extern row_info_enum eGet6RowInfo(int,
const UCHAR *, int, row_block_type *);
extern void vGet6StyleInfo(int,
const UCHAR *, int, style_block_type *);
extern void vGet6PapInfo(FILE *, ULONG, const ULONG *, size_t,
const UCHAR *);
extern void vGet6FontInfo(int, USHORT,
const UCHAR *, int, font_block_type *);
extern void vGet6ChrInfo(FILE *, ULONG, const ULONG *, size_t,
const UCHAR *);
/* prop8.c */
extern void vGet8DopInfo(FILE *, const pps_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *);
extern void vGet8SepInfo(FILE *, const pps_info_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *);
extern void vGet8HdrFtrInfo(FILE *, const pps_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *);
extern row_info_enum eGet8RowInfo(int,
const UCHAR *, int, row_block_type *);
extern void vGet8StyleInfo(int,
const UCHAR *, int, style_block_type *);
extern void vGet8LstInfo(FILE *, const pps_info_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *);
extern void vGet8PapInfo(FILE *, const pps_info_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *);
extern void vGet8FontInfo(int, USHORT,
const UCHAR *, int, font_block_type *);
extern void vGet8ChrInfo(FILE *, const pps_info_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *);
/* properties.c */
extern void vGetPropertyInfo(FILE *, const pps_info_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *, int);
extern row_info_enum ePropMod2RowInfo(USHORT, int);
/* propmod.c */
extern void vDestroyPropModList(void);
extern void vAdd2PropModList(const UCHAR *);
extern const UCHAR *aucReadPropModListItem(USHORT);
/* rowlist.c */
extern void vDestroyRowInfoList(void);
extern void vAdd2RowInfoList(const row_block_type *);
extern const row_block_type *pGetNextRowInfoListItem(void);
/* riscos.c */
#if defined(__riscos)
extern int iGetFiletype(const char *);
extern void vSetFiletype(const char *, int);
extern BOOL bMakeDirectory(const char *);
extern int iReadCurrentAlphabetNumber(void);
extern int iGetRiscOsVersion(void);
extern BOOL bDrawRenderDiag360(void *, size_t,
window_redrawblock *, double, os_error *);
#if defined(DEBUG)
extern BOOL bGetJpegInfo(UCHAR *, size_t);
#endif /* DEBUG */
#endif /* __riscos */
/* saveas.c */
#if defined(__riscos)
extern BOOL bSaveTextfile(event_pollblock *, void *);
extern BOOL bSaveDrawfile(event_pollblock *, void *);
#endif /* __riscos */
/* sectlist.c */
extern void vDestroySectionInfoList(void);
extern void vAdd2SectionInfoList(const section_block_type *, ULONG);
extern void vGetDefaultSection(section_block_type *);
extern void vDefault2SectionInfoList(ULONG);
extern const section_block_type *
pGetSectionInfo(const section_block_type *, ULONG);
extern size_t tGetNumberOfSections(void);
extern UCHAR ucGetSepHdrFtrSpecification(size_t);
/* stylelist.c */
extern void vDestroyStyleInfoList(void);
extern level_type_enum eGetNumType(UCHAR);
extern void vCorrectStyleValues(style_block_type *);
extern void vAdd2StyleInfoList(const style_block_type *);
extern const style_block_type *pGetNextStyleInfoListItem(
const style_block_type *);
extern const style_block_type *pGetNextTextStyle(const style_block_type *);
extern USHORT usGetIstd(ULONG);
extern BOOL bStyleImpliesList(const style_block_type *, int);
/* stylesheet.c */
extern void vDestroyStylesheetList(void);
extern USHORT usStc2istd(UCHAR);
extern void vGet2Stylesheet(FILE *, int, const UCHAR *);
extern void vGet6Stylesheet(FILE *, ULONG, const ULONG *, size_t,
const UCHAR *);
extern void vGet8Stylesheet(FILE *, const pps_info_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *);
extern void vFillStyleFromStylesheet(USHORT, style_block_type *);
extern void vFillFontFromStylesheet(USHORT, font_block_type *);
/* summary.c */
extern void vDestroySummaryInfo(void);
extern void vSet0SummaryInfo(FILE *, const UCHAR *);
extern void vSet2SummaryInfo(FILE *, int, const UCHAR *);
extern void vSet6SummaryInfo(FILE *, const pps_info_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *);
extern void vSet8SummaryInfo(FILE *, const pps_info_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *);
extern const char *szGetTitle(void);
extern const char *szGetSubject(void);
extern const char *szGetAuthor(void);
extern const char *szGetLastSaveDtm(void);
extern const char *szGetModDate(void);
extern const char *szGetCreationDate(void);
extern const char *szGetCompany(void);
extern const char *szGetLanguage(void);
/* tabstop.c */
extern void vSetDefaultTabWidth(FILE *, const pps_info_type *,
const ULONG *, size_t, const ULONG *, size_t,
const UCHAR *, int);
extern long lGetDefaultTabWidth(void);
/* text.c */
extern void vPrologueTXT(diagram_type *, const options_type *);
extern void vEpilogueTXT(FILE *);
extern void vMove2NextLineTXT(diagram_type *);
extern void vSubstringTXT(diagram_type *, const char *, size_t, long);
extern void vStartOfParagraphTXT(diagram_type *, long);
extern void vEndOfParagraphTXT(diagram_type *, long);
extern void vEndOfPageTXT(diagram_type *, long);
/* unix.c */
extern void werr(int, const char *, ...);
#if !defined(__riscos)
extern void Hourglass_On(void);
extern void Hourglass_Off(void);
#endif /* !__riscos */
/* utf8.c */
#if !defined(__riscos)
extern long utf8_strwidth(const char *, size_t);
extern int utf8_chrlength(const char *);
extern BOOL is_locale_utf8(void);
#endif /* !__riscos */
/* word2text.c */
extern BOOL bOutputContainsText(const output_type *);
extern BOOL bWordDecryptor(FILE *, long, diagram_type *);
extern output_type *pHdrFtrDecryptor(FILE *, ULONG, ULONG);
extern char *szFootnoteDecryptor(FILE *, ULONG, ULONG);
/* worddos.c */
extern int iInitDocumentDOS(FILE *, long);
/* wordlib.c */
extern BOOL bIsWordForDosFile(FILE *, long);
extern BOOL bIsRtfFile(FILE *);
extern BOOL bIsWordPerfectFile(FILE *);
extern BOOL bIsWinWord12File(FILE *, long);
extern BOOL bIsMacWord45File(FILE *);
extern int iGuessVersionNumber(FILE *, long);
extern int iGetVersionNumber(const UCHAR *);
extern BOOL bIsOldMacFile(void);
extern int iInitDocument(FILE *, long);
extern void vFreeDocument(void);
/* wordmac.c */
extern int iInitDocumentMAC(FILE *, long);
/* wordole.c */
extern int iInitDocumentOLE(FILE *, long);
/* wordwin.c */
extern int iInitDocumentWIN(FILE *, long);
/* xmalloc.c */
extern void *xmalloc(size_t);
extern void *xcalloc(size_t, size_t);
extern void *xrealloc(void *, size_t);
extern char *xstrdup(const char *);
extern void *xfree(void *);
/* xml.c */
extern void vCreateBookIntro(diagram_type *, int);
extern void vPrologueXML(diagram_type *, const options_type *);
extern void vEpilogueXML(diagram_type *);
extern void vMove2NextLineXML(diagram_type *);
extern void vSubstringXML(diagram_type *,
const char *, size_t, long, USHORT);
extern void vStartOfParagraphXML(diagram_type *, UINT);
extern void vEndOfParagraphXML(diagram_type *, UINT);
extern void vEndOfPageXML(diagram_type *);
extern void vSetHeadersXML(diagram_type *, USHORT);
extern void vStartOfListXML(diagram_type *, UCHAR, BOOL);
extern void vEndOfListXML(diagram_type *);
extern void vStartOfListItemXML(diagram_type *, BOOL);
extern void vEndOfTableXML(diagram_type *);
extern void vAddTableRowXML(diagram_type *, char **, int,
const short *, UCHAR);
#endif /* __antiword_h */

154
src/asc85enc.c Normal file
View File

@@ -0,0 +1,154 @@
/*
* asc85enc.c
* Copyright (C) 2000-2003 A.J. van Os; Released under GPL
*
* Description:
* Functions to for ASCII 85 encoding
*
*====================================================================
* This part of the software is based on:
* asc85ec.c - ASCII85 and Hex encoding for PostScript Level 2 and PDF
* Copyright (C) 1994-99 Thomas Merz (tm@muc.de)
*====================================================================
* The credit should go to him, but all the bugs are mine.
*/
#include <stdio.h>
#include "antiword.h"
static const ULONG aulPower85[5] = {
1UL, 85UL, 85UL * 85, 85UL * 85 * 85, 85UL * 85 * 85 * 85,
};
static int iOutBytes = 0; /* Number of characters in an output line */
static char cCharPrev = '\0';
/*
* Two percent characters at the start of a line will cause trouble
* with some post-processing software. In order to avoid this, we
* simply insert a line break if we encounter two percent characters
* at the start of the line. Of course, this rather simplistic
* algorithm may lead to a large line count in pathological cases,
* but the chance for hitting such a case is very small, and even
* so it's only a cosmetic flaw and not a functional restriction.
*/
/*
* vOutputByte - output one byte
*/
static void
vOutputByte(ULONG ulChar, FILE *pOutFile)
{
if (iOutBytes == 1 && cCharPrev == '%' && ulChar == (ULONG)'%') {
if (putc('\n', pOutFile) != EOF) {
iOutBytes = 0;
}
}
if (putc((int)ulChar, pOutFile) == EOF) {
return;
}
iOutBytes++;
if (iOutBytes > 63) {
if (putc('\n', pOutFile) != EOF) {
iOutBytes = 0;
}
}
cCharPrev = (char)ulChar;
} /* end of vOutputByte */
/*
* vASCII85EncodeByte - ASCII 85 encode a byte
*/
void
vASCII85EncodeByte(FILE *pOutFile, int iByte)
{
static ULONG ulBuffer[4] = { 0, 0, 0, 0 };
static int iInBuffer = 0;
ULONG ulValue, ulTmp;
int iIndex;
fail(pOutFile == NULL);
fail(iInBuffer < 0);
fail(iInBuffer > 3);
if (iByte == EOF) {
/* End Of File, time to clean up */
if (iInBuffer > 0 && iInBuffer < 4) {
/* Encode the remaining bytes */
ulValue = 0;
for (iIndex = iInBuffer - 1; iIndex >= 0; iIndex--) {
ulValue |=
ulBuffer[iIndex] << (8 * (3 - iIndex));
}
for (iIndex = 4; iIndex >= 4 - iInBuffer; iIndex--) {
ulTmp = ulValue / aulPower85[iIndex];
vOutputByte(ulTmp + '!', pOutFile);
ulValue -= ulTmp * aulPower85[iIndex];
}
}
/* Add the End Of Data marker */
(void)putc('~', pOutFile);
(void)putc('>', pOutFile);
(void)putc('\n', pOutFile);
/* Reset the control variables */
iInBuffer = 0;
iOutBytes = 0;
cCharPrev = '\0';
return;
}
ulBuffer[iInBuffer] = (ULONG)iByte & 0xff;
iInBuffer++;
if (iInBuffer >= 4) {
ulValue = (ulBuffer[0] << 24) | (ulBuffer[1] << 16) |
(ulBuffer[2] << 8) | ulBuffer[3];
if (ulValue == 0) {
vOutputByte((ULONG)'z', pOutFile); /* Shortcut for 0 */
} else {
for (iIndex = 4; iIndex >= 0; iIndex--) {
ulTmp = ulValue / aulPower85[iIndex];
vOutputByte(ulTmp + '!', pOutFile);
ulValue -= ulTmp * aulPower85[iIndex];
}
}
/* Reset the buffer */
iInBuffer = 0;
}
} /* end of vASCII85EncodeByte */
/*
* vASCII85EncodeArray - ASCII 85 encode a byte array
*/
void
vASCII85EncodeArray(FILE *pInFile, FILE *pOutFile, size_t tLength)
{
size_t tCount;
int iByte;
fail(pInFile == NULL);
fail(pOutFile == NULL);
DBG_DEC(tLength);
for (tCount = 0; tCount < tLength; tCount++) {
iByte = iNextByte(pInFile);
if (iByte == EOF) {
break;
}
vASCII85EncodeByte(pOutFile, iByte);
}
} /* end of vASCII85EncodeArray */
/*
* vASCII85EncodeFile - ASCII 85 encode part of a file
*/
void
vASCII85EncodeFile(FILE *pInFile, FILE *pOutFile, size_t tLength)
{
fail(pInFile == NULL);
fail(pOutFile == NULL);
fail(tLength == 0);
vASCII85EncodeArray(pInFile, pOutFile, tLength);
vASCII85EncodeByte(pOutFile, EOF);
} /* end of vASCII85EncodeFile */

823
src/blocklist.c Normal file
View File

@@ -0,0 +1,823 @@
/*
* blocklist.c
* Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
*
* Description:
* Build, read and destroy the lists of Word "text" blocks
*/
#include <stdlib.h>
#include "antiword.h"
/*
* Private structure to hide the way the information
* is stored from the rest of the program
*/
typedef struct list_mem_tag {
text_block_type tInfo;
struct list_mem_tag *pNext;
} list_mem_type;
typedef struct readinfo_tag {
list_mem_type *pBlockCurrent;
ULONG ulBlockOffset;
size_t tByteNext;
UCHAR aucBlock[BIG_BLOCK_SIZE];
} readinfo_type;
/* Variables to describe the start of the block lists */
static list_mem_type *pTextAnchor = NULL;
static list_mem_type *pFootnoteAnchor = NULL;
static list_mem_type *pHdrFtrAnchor = NULL;
static list_mem_type *pMacroAnchor = NULL;
static list_mem_type *pAnnotationAnchor = NULL;
static list_mem_type *pEndnoteAnchor = NULL;
static list_mem_type *pTextBoxAnchor = NULL;
static list_mem_type *pHdrTextBoxAnchor = NULL;
/* Variable needed to build the block list */
static list_mem_type *pBlockLast = NULL;
/* Variable needed to read the block lists */
static readinfo_type tOthers = { NULL, 0, 0, };
static readinfo_type tHdrFtr = { NULL, 0, 0, };
static readinfo_type tFootnote = { NULL, 0, 0, };
/*
* pFreeOneList - free a text block list
*
* Will always return NULL
*/
static list_mem_type *
pFreeOneList(list_mem_type *pAnchor)
{
list_mem_type *pCurr, *pNext;
pCurr = pAnchor;
while (pCurr != NULL) {
pNext = pCurr->pNext;
pCurr = xfree(pCurr);
pCurr = pNext;
}
return NULL;
} /* end of pFreeOneList */
/*
* vDestroyTextBlockList - destroy the text block lists
*/
void
vDestroyTextBlockList(void)
{
DBG_MSG("vDestroyTextBlockList");
/* Free the lists one by one */
pTextAnchor = pFreeOneList(pTextAnchor);
pFootnoteAnchor = pFreeOneList(pFootnoteAnchor);
pHdrFtrAnchor = pFreeOneList(pHdrFtrAnchor);
pMacroAnchor = pFreeOneList(pMacroAnchor);
pAnnotationAnchor = pFreeOneList(pAnnotationAnchor);
pEndnoteAnchor = pFreeOneList(pEndnoteAnchor);
pTextBoxAnchor = pFreeOneList(pTextBoxAnchor);
pHdrTextBoxAnchor = pFreeOneList(pHdrTextBoxAnchor);
/* Reset all the controle variables */
pBlockLast = NULL;
tOthers.pBlockCurrent = NULL;
tHdrFtr.pBlockCurrent = NULL;
tFootnote.pBlockCurrent = NULL;
} /* end of vDestroyTextBlockList */
/*
* bAdd2TextBlockList - add an element to the text block list
*
* returns: TRUE when successful, otherwise FALSE
*/
BOOL
bAdd2TextBlockList(const text_block_type *pTextBlock)
{
list_mem_type *pListMember;
fail(pTextBlock == NULL);
fail(pTextBlock->ulFileOffset == FC_INVALID);
fail(pTextBlock->ulCharPos == CP_INVALID);
fail(pTextBlock->ulLength == 0);
fail(pTextBlock->bUsesUnicode && odd(pTextBlock->ulLength));
NO_DBG_MSG("bAdd2TextBlockList");
NO_DBG_HEX(pTextBlock->ulFileOffset);
NO_DBG_HEX(pTextBlock->ulCharPos);
NO_DBG_HEX(pTextBlock->ulLength);
NO_DBG_DEC(pTextBlock->bUsesUnicode);
NO_DBG_DEC(pTextBlock->usPropMod);
if (pTextBlock->ulFileOffset == FC_INVALID ||
pTextBlock->ulCharPos == CP_INVALID ||
pTextBlock->ulLength == 0 ||
(pTextBlock->bUsesUnicode && odd(pTextBlock->ulLength))) {
werr(0, "Software (textblock) error");
return FALSE;
}
/*
* Check for continuous blocks of the same character size and
* the same properties modifier
*/
if (pBlockLast != NULL &&
pBlockLast->tInfo.ulFileOffset +
pBlockLast->tInfo.ulLength == pTextBlock->ulFileOffset &&
pBlockLast->tInfo.ulCharPos +
pBlockLast->tInfo.ulLength == pTextBlock->ulCharPos &&
pBlockLast->tInfo.bUsesUnicode == pTextBlock->bUsesUnicode &&
pBlockLast->tInfo.usPropMod == pTextBlock->usPropMod) {
/* These are continous blocks */
pBlockLast->tInfo.ulLength += pTextBlock->ulLength;
return TRUE;
}
/* Make a new block */
pListMember = xmalloc(sizeof(list_mem_type));
/* Add the block to the list */
pListMember->tInfo = *pTextBlock;
pListMember->pNext = NULL;
if (pTextAnchor == NULL) {
pTextAnchor = pListMember;
} else {
fail(pBlockLast == NULL);
pBlockLast->pNext = pListMember;
}
pBlockLast = pListMember;
return TRUE;
} /* end of bAdd2TextBlockList */
/*
* vSpitList - Split the list in two
*/
static void
vSpitList(list_mem_type **ppAnchorCurr, list_mem_type **ppAnchorNext,
ULONG ulListLen)
{
list_mem_type *pCurr;
long lCharsToGo, lBytesTooFar;
fail(ppAnchorCurr == NULL);
fail(ppAnchorNext == NULL);
fail(ulListLen > (ULONG)LONG_MAX);
pCurr = NULL;
lCharsToGo = (long)ulListLen;
lBytesTooFar = -1;
if (ulListLen != 0) {
DBG_DEC(ulListLen);
for (pCurr = *ppAnchorCurr;
pCurr != NULL;
pCurr = pCurr->pNext) {
NO_DBG_DEC(pCurr->tInfo.ulLength);
fail(pCurr->tInfo.ulLength == 0);
fail(pCurr->tInfo.ulLength > (ULONG)LONG_MAX);
if (pCurr->tInfo.bUsesUnicode) {
fail(odd(pCurr->tInfo.ulLength));
lCharsToGo -= (long)(pCurr->tInfo.ulLength / 2);
if (lCharsToGo < 0) {
lBytesTooFar = -2 * lCharsToGo;
}
} else {
lCharsToGo -= (long)pCurr->tInfo.ulLength;
if (lCharsToGo < 0) {
lBytesTooFar = -lCharsToGo;
}
}
if (lCharsToGo <= 0) {
break;
}
}
}
/* Split the list */
if (ulListLen == 0) {
/* Current blocklist is empty */
*ppAnchorNext = *ppAnchorCurr;
*ppAnchorCurr = NULL;
} else if (pCurr == NULL) {
/* No blocks for the next list */
*ppAnchorNext = NULL;
} else if (lCharsToGo == 0) {
/* Move the integral number of blocks to the next list */
*ppAnchorNext = pCurr->pNext;
pCurr->pNext = NULL;
} else {
/* Split the part current block list, part next block list */
DBG_DEC(lBytesTooFar);
fail(lBytesTooFar <= 0);
*ppAnchorNext = xmalloc(sizeof(list_mem_type));
DBG_HEX(pCurr->tInfo.ulFileOffset);
(*ppAnchorNext)->tInfo.ulFileOffset =
pCurr->tInfo.ulFileOffset +
pCurr->tInfo.ulLength -
lBytesTooFar;
DBG_HEX((*ppAnchorNext)->tInfo.ulFileOffset);
DBG_HEX(pCurr->tInfo.ulCharPos);
(*ppAnchorNext)->tInfo.ulCharPos =
pCurr->tInfo.ulCharPos +
pCurr->tInfo.ulLength -
lBytesTooFar;
DBG_HEX((*ppAnchorNext)->tInfo.ulCharPos);
(*ppAnchorNext)->tInfo.ulLength = (ULONG)lBytesTooFar;
pCurr->tInfo.ulLength -= (ULONG)lBytesTooFar;
(*ppAnchorNext)->tInfo.bUsesUnicode = pCurr->tInfo.bUsesUnicode;
(*ppAnchorNext)->tInfo.usPropMod = pCurr->tInfo.usPropMod;
/* Move the integral number of blocks to the next list */
(*ppAnchorNext)->pNext = pCurr->pNext;
pCurr->pNext = NULL;
}
} /* end of vSpitList */
#if defined(DEBUG) || defined(__riscos)
/*
* ulComputeListLength - compute the length of a list
*
* returns the list length in characters
*/
static ULONG
ulComputeListLength(const list_mem_type *pAnchor)
{
const list_mem_type *pCurr;
ULONG ulTotal;
ulTotal = 0;
for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
fail(pCurr->tInfo.ulLength == 0);
if (pCurr->tInfo.bUsesUnicode) {
fail(odd(pCurr->tInfo.ulLength));
ulTotal += pCurr->tInfo.ulLength / 2;
} else {
ulTotal += pCurr->tInfo.ulLength;
}
}
return ulTotal;
} /* end of ulComputeListLength */
#endif /* DEBUG || __riscos */
#if defined(DEBUG)
/*
* vCheckList - check the number of bytes in a block list
*/
static void
vCheckList(const list_mem_type *pAnchor, ULONG ulListLen, char *szMsg)
{
ULONG ulTotal;
ulTotal = ulComputeListLength(pAnchor);
DBG_DEC(ulTotal);
if (ulTotal != ulListLen) {
DBG_DEC(ulListLen);
werr(1, szMsg);
}
} /* end of vCheckList */
#endif /* DEBUG */
/*
* bIsEmptyBox - check to see if the given text box is empty
*/
static BOOL
bIsEmptyBox(FILE *pFile, const list_mem_type *pAnchor)
{
const list_mem_type *pCurr;
size_t tIndex, tSize;
UCHAR *aucBuffer;
char cChar;
fail(pFile == NULL);
if (pAnchor == NULL) {
return TRUE;
}
aucBuffer = NULL;
for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
fail(pCurr->tInfo.ulLength == 0);
tSize = (size_t)pCurr->tInfo.ulLength;
#if defined(__dos) && !defined(__DJGPP__)
if (pCurr->tInfo.ulLength > 0xffffUL) {
tSize = 0xffff;
}
#endif /* __dos && !__DJGPP__ */
fail(aucBuffer != NULL);
aucBuffer = xmalloc(tSize);
if (!bReadBytes(aucBuffer, tSize,
pCurr->tInfo.ulFileOffset, pFile)) {
aucBuffer = xfree(aucBuffer);
return FALSE;
}
for (tIndex = 0; tIndex < tSize; tIndex++) {
cChar = (char)aucBuffer[tIndex];
switch (cChar) {
case '\0': case '\r': case '\n':
case '\f': case '\t': case '\v':
case ' ':
break;
default:
aucBuffer = xfree(aucBuffer);
return FALSE;
}
}
aucBuffer = xfree(aucBuffer);
}
fail(aucBuffer != NULL);
return TRUE;
} /* end of bIsEmptyBox */
/*
* vSplitBlockList - split the block list in the various parts
*
* Split the blocklist in a Text block list, a Footnote block list, a
* HeaderFooter block list, a Macro block list, an Annotation block list,
* an Endnote block list, a TextBox list and a HeaderTextBox list.
*
* NOTE:
* The various ul*Len input parameters are given in characters, but the
* length of the blocks are in bytes.
*/
void
vSplitBlockList(FILE *pFile, ULONG ulTextLen, ULONG ulFootnoteLen,
ULONG ulHdrFtrLen, ULONG ulMacroLen, ULONG ulAnnotationLen,
ULONG ulEndnoteLen, ULONG ulTextBoxLen, ULONG ulHdrTextBoxLen,
BOOL bMustExtend)
{
list_mem_type *apAnchors[8];
list_mem_type *pGarbageAnchor, *pCurr;
size_t tIndex;
DBG_MSG("vSplitBlockList");
pGarbageAnchor = NULL;
DBG_MSG_C(ulTextLen != 0, "Text block list");
vSpitList(&pTextAnchor, &pFootnoteAnchor, ulTextLen);
DBG_MSG_C(ulFootnoteLen != 0, "Footnote block list");
vSpitList(&pFootnoteAnchor, &pHdrFtrAnchor, ulFootnoteLen);
DBG_MSG_C(ulHdrFtrLen != 0, "Header/Footer block list");
vSpitList(&pHdrFtrAnchor, &pMacroAnchor, ulHdrFtrLen);
DBG_MSG_C(ulMacroLen != 0, "Macro block list");
vSpitList(&pMacroAnchor, &pAnnotationAnchor, ulMacroLen);
DBG_MSG_C(ulAnnotationLen != 0, "Annotation block list");
vSpitList(&pAnnotationAnchor, &pEndnoteAnchor, ulAnnotationLen);
DBG_MSG_C(ulEndnoteLen != 0, "Endnote block list");
vSpitList(&pEndnoteAnchor, &pTextBoxAnchor, ulEndnoteLen);
DBG_MSG_C(ulTextBoxLen != 0, "Textbox block list");
vSpitList(&pTextBoxAnchor, &pHdrTextBoxAnchor, ulTextBoxLen);
DBG_MSG_C(ulHdrTextBoxLen != 0, "HeaderTextbox block list");
vSpitList(&pHdrTextBoxAnchor, &pGarbageAnchor, ulHdrTextBoxLen);
/* Free the garbage block list, this should not be needed */
DBG_DEC_C(pGarbageAnchor != NULL, pGarbageAnchor->tInfo.ulLength);
pGarbageAnchor = pFreeOneList(pGarbageAnchor);
#if defined(DEBUG)
vCheckList(pTextAnchor, ulTextLen, "Software error (Text)");
vCheckList(pFootnoteAnchor, ulFootnoteLen, "Software error (Footnote)");
vCheckList(pHdrFtrAnchor, ulHdrFtrLen, "Software error (Hdr/Ftr)");
vCheckList(pMacroAnchor, ulMacroLen, "Software error (Macro)");
vCheckList(pAnnotationAnchor, ulAnnotationLen,
"Software error (Annotation)");
vCheckList(pEndnoteAnchor, ulEndnoteLen, "Software error (Endnote)");
vCheckList(pTextBoxAnchor, ulTextBoxLen, "Software error (TextBox)");
vCheckList(pHdrTextBoxAnchor, ulHdrTextBoxLen,
"Software error (HdrTextBox)");
#endif /* DEBUG */
/* Remove the list if the text box is empty */
if (bIsEmptyBox(pFile, pTextBoxAnchor)) {
pTextBoxAnchor = pFreeOneList(pTextBoxAnchor);
}
if (bIsEmptyBox(pFile, pHdrTextBoxAnchor)) {
pHdrTextBoxAnchor = pFreeOneList(pHdrTextBoxAnchor);
}
if (!bMustExtend) {
return;
}
/*
* All blocks (except the last one) must have a length that
* is a multiple of the Big Block Size
*/
apAnchors[0] = pTextAnchor;
apAnchors[1] = pFootnoteAnchor;
apAnchors[2] = pHdrFtrAnchor;
apAnchors[3] = pMacroAnchor;
apAnchors[4] = pAnnotationAnchor;
apAnchors[5] = pEndnoteAnchor;
apAnchors[6] = pTextBoxAnchor;
apAnchors[7] = pHdrTextBoxAnchor;
for (tIndex = 0; tIndex < elementsof(apAnchors); tIndex++) {
for (pCurr = apAnchors[tIndex];
pCurr != NULL;
pCurr = pCurr->pNext) {
if (pCurr->pNext != NULL &&
pCurr->tInfo.ulLength % BIG_BLOCK_SIZE != 0) {
DBG_DEC(tIndex);
DBG_HEX(pCurr->tInfo.ulFileOffset);
DBG_HEX(pCurr->tInfo.ulCharPos);
DBG_DEC(pCurr->tInfo.ulLength);
pCurr->tInfo.ulLength /= BIG_BLOCK_SIZE;
pCurr->tInfo.ulLength++;
pCurr->tInfo.ulLength *= BIG_BLOCK_SIZE;
DBG_DEC(pCurr->tInfo.ulLength);
}
}
}
} /* end of vSplitBlockList */
#if defined(__riscos)
/*
* ulGetDocumentLength - get the total character length of the printable lists
*
* returns: The total number of characters
*/
ULONG
ulGetDocumentLength(void)
{
long ulTotal;
DBG_MSG("ulGetDocumentLength");
ulTotal = ulComputeListLength(pTextAnchor);
ulTotal += ulComputeListLength(pFootnoteAnchor);
ulTotal += ulComputeListLength(pEndnoteAnchor);
ulTotal += ulComputeListLength(pTextBoxAnchor);
ulTotal += ulComputeListLength(pHdrTextBoxAnchor);
DBG_DEC(ulTotal);
return ulTotal;
} /* end of ulGetDocumentLength */
#endif /* __riscos */
#if 0
/*
* bExistsHdrFtr - are there headers and/or footers?
*/
BOOL
bExistsHdrFtr(void)
{
return pHdrFtrAnchor != NULL &&
pHdrFtrAnchor->tInfo.ulLength != 0;
} /* end of bExistsHdrFtr */
#endif
/*
* bExistsTextBox - is there a text box?
*/
BOOL
bExistsTextBox(void)
{
return pTextBoxAnchor != NULL &&
pTextBoxAnchor->tInfo.ulLength != 0;
} /* end of bExistsTextBox */
/*
* bExistsHdrTextBox - is there a header text box?
*/
BOOL
bExistsHdrTextBox(void)
{
return pHdrTextBoxAnchor != NULL &&
pHdrTextBoxAnchor->tInfo.ulLength != 0;
} /* end of bExistsHdrTextBox */
/*
* usGetNextByte - get the next byte from the specified block list
*/
static USHORT
usGetNextByte(FILE *pFile, readinfo_type *pInfoCurrent, list_mem_type *pAnchor,
ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
{
ULONG ulReadOff;
size_t tReadLen;
fail(pInfoCurrent == NULL);
if (pInfoCurrent->pBlockCurrent == NULL ||
pInfoCurrent->tByteNext >= sizeof(pInfoCurrent->aucBlock) ||
pInfoCurrent->ulBlockOffset + pInfoCurrent->tByteNext >=
pInfoCurrent->pBlockCurrent->tInfo.ulLength) {
if (pInfoCurrent->pBlockCurrent == NULL) {
/* First block, first part */
pInfoCurrent->pBlockCurrent = pAnchor;
pInfoCurrent->ulBlockOffset = 0;
} else if (pInfoCurrent->ulBlockOffset +
sizeof(pInfoCurrent->aucBlock) <
pInfoCurrent->pBlockCurrent->tInfo.ulLength) {
/* Same block, next part */
pInfoCurrent->ulBlockOffset +=
sizeof(pInfoCurrent->aucBlock);
} else {
/* Next block, first part */
pInfoCurrent->pBlockCurrent =
pInfoCurrent->pBlockCurrent->pNext;
pInfoCurrent->ulBlockOffset = 0;
}
if (pInfoCurrent->pBlockCurrent == NULL) {
/* Past the last part of the last block */
return (USHORT)EOF;
}
tReadLen = (size_t)
(pInfoCurrent->pBlockCurrent->tInfo.ulLength -
pInfoCurrent->ulBlockOffset);
if (tReadLen > sizeof(pInfoCurrent->aucBlock)) {
tReadLen = sizeof(pInfoCurrent->aucBlock);
}
ulReadOff = pInfoCurrent->pBlockCurrent->tInfo.ulFileOffset +
pInfoCurrent->ulBlockOffset;
if (!bReadBytes(pInfoCurrent->aucBlock,
tReadLen, ulReadOff, pFile)) {
/* Don't read from this list any longer */
pInfoCurrent->pBlockCurrent = NULL;
return (USHORT)EOF;
}
pInfoCurrent->tByteNext = 0;
}
if (pulFileOffset != NULL) {
*pulFileOffset =
pInfoCurrent->pBlockCurrent->tInfo.ulFileOffset +
pInfoCurrent->ulBlockOffset +
pInfoCurrent->tByteNext;
}
if (pulCharPos != NULL) {
*pulCharPos =
pInfoCurrent->pBlockCurrent->tInfo.ulCharPos +
pInfoCurrent->ulBlockOffset +
pInfoCurrent->tByteNext;
}
if (pusPropMod != NULL) {
*pusPropMod = pInfoCurrent->pBlockCurrent->tInfo.usPropMod;
}
return (USHORT)pInfoCurrent->aucBlock[pInfoCurrent->tByteNext++];
} /* end of usGetNextByte */
/*
* usGetNextChar - get the next character from the specified block list
*/
static USHORT
usGetNextChar(FILE *pFile, list_id_enum eListID,
ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
{
readinfo_type *pReadinfo;
list_mem_type *pAnchor;
USHORT usLSB, usMSB;
switch (eListID) {
case text_list:
pReadinfo = &tOthers;
pAnchor = pTextAnchor;
break;
case footnote_list:
pReadinfo = &tFootnote;
pAnchor = pFootnoteAnchor;
break;
case hdrftr_list:
pReadinfo = &tHdrFtr;
pAnchor = pHdrFtrAnchor;
break;
case endnote_list:
pReadinfo = &tOthers;
pAnchor = pEndnoteAnchor;
break;
case textbox_list:
pReadinfo = &tOthers;
pAnchor = pTextBoxAnchor;
break;
case hdrtextbox_list:
pReadinfo = &tOthers;
pAnchor = pHdrTextBoxAnchor;
break;
default:
DBG_DEC(eListID);
return (USHORT)EOF;
}
usLSB = usGetNextByte(pFile, pReadinfo, pAnchor,
pulFileOffset, pulCharPos, pusPropMod);
if (usLSB == (USHORT)EOF) {
return (USHORT)EOF;
}
fail(pReadinfo->pBlockCurrent == NULL);
if (pReadinfo->pBlockCurrent->tInfo.bUsesUnicode) {
usMSB = usGetNextByte(pFile,
pReadinfo, pAnchor, NULL, NULL, NULL);
} else {
usMSB = 0x00;
}
if (usMSB == (USHORT)EOF) {
DBG_MSG("usGetNextChar: Unexpected EOF");
DBG_HEX_C(pulFileOffset != NULL, *pulFileOffset);
DBG_HEX_C(pulCharPos != NULL, *pulCharPos);
return (USHORT)EOF;
}
return (usMSB << 8) | usLSB;
} /* end of usGetNextChar */
/*
* usNextChar - get the next character from the given block list
*/
USHORT
usNextChar(FILE *pFile, list_id_enum eListID,
ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
{
USHORT usRetVal;
fail(pFile == NULL);
usRetVal = usGetNextChar(pFile, eListID,
pulFileOffset, pulCharPos, pusPropMod);
if (usRetVal == (USHORT)EOF) {
if (pulFileOffset != NULL) {
*pulFileOffset = FC_INVALID;
}
if (pulCharPos != NULL) {
*pulCharPos = CP_INVALID;
}
if (pusPropMod != NULL) {
*pusPropMod = IGNORE_PROPMOD;
}
}
return usRetVal;
} /* end of usNextChar */
/*
* usToHdrFtrPosition - Go to a character position in header/foorter list
*
* Returns the character found on the specified character position
*/
USHORT
usToHdrFtrPosition(FILE *pFile, ULONG ulCharPos)
{
ULONG ulCharPosCurr;
USHORT usChar;
tHdrFtr.pBlockCurrent = NULL; /* To reset the header/footer list */
do {
usChar = usNextChar(pFile,
hdrftr_list, NULL, &ulCharPosCurr, NULL);
} while (usChar != (USHORT)EOF && ulCharPosCurr != ulCharPos);
return usChar;
} /* end of usToHdrFtrPosition */
/*
* usToFootnotePosition - Go to a character position in footnote list
*
* Returns the character found on the specified character position
*/
USHORT
usToFootnotePosition(FILE *pFile, ULONG ulCharPos)
{
ULONG ulCharPosCurr;
USHORT usChar;
tFootnote.pBlockCurrent = NULL; /* To reset the footnote list */
do {
usChar = usNextChar(pFile,
footnote_list, NULL, &ulCharPosCurr, NULL);
} while (usChar != (USHORT)EOF && ulCharPosCurr != ulCharPos);
return usChar;
} /* end of usToFootnotePosition */
/*
* Convert a character position to an offset in the file.
* Logical to physical offset.
*
* Returns: FC_INVALID: in case of error
* otherwise: the computed file offset
*/
ULONG
ulCharPos2FileOffsetX(ULONG ulCharPos, list_id_enum *peListID)
{
static list_id_enum eListIDs[8] = {
text_list, footnote_list, hdrftr_list,
macro_list, annotation_list, endnote_list,
textbox_list, hdrtextbox_list,
};
list_mem_type *apAnchors[8];
list_mem_type *pCurr;
list_id_enum eListGuess;
ULONG ulBestGuess;
size_t tIndex;
fail(peListID == NULL);
if (ulCharPos == CP_INVALID) {
*peListID = no_list;
return FC_INVALID;
}
apAnchors[0] = pTextAnchor;
apAnchors[1] = pFootnoteAnchor;
apAnchors[2] = pHdrFtrAnchor;
apAnchors[3] = pMacroAnchor;
apAnchors[4] = pAnnotationAnchor;
apAnchors[5] = pEndnoteAnchor;
apAnchors[6] = pTextBoxAnchor;
apAnchors[7] = pHdrTextBoxAnchor;
eListGuess = no_list; /* Best guess is no list */
ulBestGuess = FC_INVALID; /* Best guess is "file offset not found" */
for (tIndex = 0; tIndex < elementsof(apAnchors); tIndex++) {
for (pCurr = apAnchors[tIndex];
pCurr != NULL;
pCurr = pCurr->pNext) {
if (ulCharPos == pCurr->tInfo.ulCharPos +
pCurr->tInfo.ulLength &&
pCurr->pNext != NULL) {
/*
* The character position is one beyond this
* block, so we guess it's the first byte of
* the next block (if there is a next block)
*/
eListGuess= eListIDs[tIndex];
ulBestGuess = pCurr->pNext->tInfo.ulFileOffset;
}
if (ulCharPos < pCurr->tInfo.ulCharPos ||
ulCharPos >= pCurr->tInfo.ulCharPos +
pCurr->tInfo.ulLength) {
/* Character position is not in this block */
continue;
}
/* The character position is in the current block */
*peListID = eListIDs[tIndex];
return pCurr->tInfo.ulFileOffset +
ulCharPos - pCurr->tInfo.ulCharPos;
}
}
/* Passed beyond the end of the last list */
NO_DBG_HEX(ulCharPos);
NO_DBG_HEX(ulBestGuess);
*peListID = eListGuess;
return ulBestGuess;
} /* end of ulCharPos2FileOffsetX */
/*
* Convert a character position to an offset in the file.
* Logical to physical offset.
*
* Returns: FC_INVALID: in case of error
* otherwise: the computed file offset
*/
ULONG
ulCharPos2FileOffset(ULONG ulCharPos)
{
list_id_enum eListID;
return ulCharPos2FileOffsetX(ulCharPos, &eListID);
} /* end of ulCharPos2FileOffset */
/*
* Convert an offset in the header/footer list to a character position.
*
* Returns: CP_INVALID: in case of error
* otherwise: the computed character position
*/
ULONG
ulHdrFtrOffset2CharPos(ULONG ulHdrFtrOffset)
{
list_mem_type *pCurr;
ULONG ulOffset;
ulOffset = ulHdrFtrOffset;
for (pCurr = pHdrFtrAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
if (ulOffset >= pCurr->tInfo.ulLength) {
/* The offset is not in this block */
ulOffset -= pCurr->tInfo.ulLength;
continue;
}
return pCurr->tInfo.ulCharPos + ulOffset;
}
return CP_INVALID;
} /* end of ulHdrFtrOffset2CharPos */
/*
* Get the sequence number beloning to the given file offset
*
* Returns the sequence number
*/
ULONG
ulGetSeqNumber(ULONG ulFileOffset)
{
list_mem_type *pCurr;
ULONG ulSeq;
if (ulFileOffset == FC_INVALID) {
return FC_INVALID;
}
ulSeq = 0;
for (pCurr = pTextAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
if (ulFileOffset >= pCurr->tInfo.ulFileOffset &&
ulFileOffset < pCurr->tInfo.ulFileOffset +
pCurr->tInfo.ulLength) {
/* The file offset is within the current textblock */
return ulSeq + ulFileOffset - pCurr->tInfo.ulFileOffset;
}
ulSeq += pCurr->tInfo.ulLength;
}
return FC_INVALID;
} /* end of ulGetSeqNumber */

720
src/chartrans.c Normal file
View File

@@ -0,0 +1,720 @@
/*
* chartrans.c
* Copyright (C) 1999-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Translate Word characters to local representation
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#if defined(__STDC_ISO_10646__)
#include <wctype.h>
#endif /* __STDC_ISO_10646__ */
#include "antiword.h"
static const USHORT usCp850[] = { /* DOS implementation of Latin1 */
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
0x00ff, 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x00d7, 0x0192,
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
0x00bf, 0x00ae, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00c1, 0x00c2, 0x00c0,
0x00a9, 0x2563, 0x2551, 0x2557, 0x255d, 0x00a2, 0x00a5, 0x2510,
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x00e3, 0x00c3,
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x00a4,
0x00f0, 0x00d0, 0x00ca, 0x00cb, 0x00c8, 0x0131, 0x00cd, 0x00ce,
0x00cf, 0x2518, 0x250c, 0x2588, 0x2584, 0x00a6, 0x00cc, 0x2580,
0x00d3, 0x00df, 0x00d4, 0x00d2, 0x00f5, 0x00d5, 0x00b5, 0x00fe,
0x00de, 0x00da, 0x00db, 0x00d9, 0x00fd, 0x00dd, 0x00af, 0x00b4,
0x00ad, 0x00b1, 0x2017, 0x00be, 0x00b6, 0x00a7, 0x00f7, 0x00b8,
0x00b0, 0x00a8, 0x00b7, 0x00b9, 0x00b3, 0x00b2, 0x25a0, 0x00a0,
};
static const USHORT usCp1250[] = { /* Windows implementation of Latin2 */
0x20ac, 0x003f, 0x201a, 0x003f, 0x201e, 0x2026, 0x2020, 0x2021,
0x003f, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
0x003f, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
0x003f, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7,
0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9,
};
static const USHORT usCp1251[] = { /* Windows implementation of Cyrillic */
0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021,
0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,
0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
0x00f3, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,
0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7,
0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,
0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7,
0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
};
static const USHORT usCp1252[] = { /* Windows implementation of Latin1 */
0x20ac, 0x003f, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x003f, 0x017d, 0x003f,
0x003f, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x003f, 0x017e, 0x0178,
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff,
};
static const USHORT usMacRoman[] = { /* Apple implementation of Latin1 */
0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x2126, 0x00e6, 0x00f8,
0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
0x00ff, 0x0178, 0x2044, 0x00a4, 0x2039, 0x203a, 0xfb01, 0xfb02,
0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1,
0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
0x003f, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7,
};
static const USHORT usPrivateArea[] = {
0x0020, 0x0021, 0x2200, 0x0023, 0x2203, 0x0025, 0x0026, 0x220d,
0x0028, 0x0029, 0x2217, 0x002b, 0x002c, 0x2212, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x2019, 0x003e, 0x003f,
0x201d, 0x201c, 0x0392, 0x03a7, 0x0394, 0x0395, 0x03a6, 0x0393,
0x0397, 0x0399, 0x03d1, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f,
0x03a0, 0x0398, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03c2, 0x03a9,
0x039e, 0x03a8, 0x0396, 0x005b, 0x2234, 0x005d, 0x22a5, 0x005f,
0x003f, 0x03b1, 0x03b2, 0x03c7, 0x03b4, 0x03b5, 0x03c6, 0x03b3,
0x03b7, 0x03b9, 0x03d5, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf,
0x03c0, 0x03b8, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03d6, 0x03c9,
0x03be, 0x03c8, 0x03b6, 0x007b, 0x007c, 0x007d, 0x223c, 0x003f,
0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f,
0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f,
0x003f, 0x003f, 0x003f, 0x2022, 0x003f, 0x003f, 0x003f, 0x003f,
0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f,
0x20ac, 0x03d2, 0x2032, 0x2264, 0x2044, 0x221e, 0x0192, 0x2663,
0x2666, 0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193,
0x00b0, 0x00b1, 0x2033, 0x2265, 0x00d7, 0x221d, 0x2202, 0x2022,
0x00f7, 0x2260, 0x2261, 0x2248, 0x2026, 0x007c, 0x23af, 0x21b5,
0x2135, 0x2111, 0x211c, 0x2118, 0x2297, 0x2295, 0x2205, 0x2229,
0x222a, 0x2283, 0x2287, 0x2284, 0x2282, 0x2286, 0x2208, 0x2209,
0x2220, 0x2207, 0x00ae, 0x00a9, 0x2122, 0x220f, 0x221a, 0x22c5,
0x00ac, 0x2227, 0x2228, 0x21d4, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
0x22c4, 0x3008, 0x00ae, 0x00a9, 0x2122, 0x2211, 0x239b, 0x239c,
0x239d, 0x23a1, 0x23a2, 0x23a3, 0x23a7, 0x23a8, 0x23a9, 0x23aa,
0x003f, 0x3009, 0x222b, 0x2320, 0x23ae, 0x2321, 0x239e, 0x239f,
0x23a0, 0x23a4, 0x23a5, 0x23a6, 0x23ab, 0x23ac, 0x23ad, 0x003f,
};
typedef struct char_table_tag {
UCHAR ucLocal;
USHORT usUnicode;
} char_table_type;
static char_table_type atCharTable[256];
static size_t tNextPosFree = 0;
/*
* iCompare - compare two records
*
* Compares two records. For use by qsort(3C) and bsearch(3C).
*
* returns -1 if rec1 < rec2, 0 if rec1 == rec2, 1 if rec1 > rec2
*/
static int
iCompare(const void *pvRecord1, const void *pvRecord2)
{
USHORT usUnicode1, usUnicode2;
usUnicode1 = ((char_table_type *)pvRecord1)->usUnicode;
usUnicode2 = ((char_table_type *)pvRecord2)->usUnicode;
if (usUnicode1 < usUnicode2) {
return -1;
}
if (usUnicode1 > usUnicode2) {
return 1;
}
return 0;
} /* end of iCompare */
/*
* pGetCharTableRecord - get the character table record
*
* returns a pointer to the record when found, otherwise NULL
*/
static const char_table_type *
pGetCharTableRecord(USHORT usUnicode)
{
char_table_type tKey;
if (tNextPosFree == 0) {
return NULL;
}
tKey.usUnicode = usUnicode;
tKey.ucLocal = 0;
return (char_table_type *)bsearch(&tKey,
atCharTable,
tNextPosFree, sizeof(atCharTable[0]),
iCompare);
} /* end of pGetCharTableRecord */
/*
* ucGetBulletCharacter - get the local representation of the bullet
*/
UCHAR
ucGetBulletCharacter(conversion_type eConversionType, encoding_type eEncoding)
{
#if defined(__riscos)
return 0x8f;
#else
const char_table_type *pRec;
fail(eEncoding == encoding_utf_8);
if (eEncoding == encoding_latin_1 &&
(eConversionType == conversion_ps ||
eConversionType == conversion_pdf)) {
/* Ugly, but it makes the PostScript and PDF look better */
return (UCHAR)143;
}
if (eConversionType != conversion_text &&
eConversionType != conversion_fmt_text) {
pRec = pGetCharTableRecord(UNICODE_BULLET);
if (pRec != NULL) {
return pRec->ucLocal;
}
pRec = pGetCharTableRecord(UNICODE_BULLET_OPERATOR);
if (pRec != NULL) {
return pRec->ucLocal;
}
pRec = pGetCharTableRecord(UNICODE_MIDDLE_DOT);
if (pRec != NULL) {
return pRec->ucLocal;
}
}
return (UCHAR)'.';
#endif /* __riscos */
} /* end of ucGetBulletCharacter */
/*
* ucGetNbspCharacter - get the local representation of the non-breaking space
*/
UCHAR
ucGetNbspCharacter(void)
{
const char_table_type *pRec;
pRec = pGetCharTableRecord(0x00a0); /* Unicode non-breaking space */
if (pRec == NULL) {
DBG_MSG("Non-breaking space record not found");
/* No value found, use the best guess */
return (UCHAR)0xa0;
}
return pRec->ucLocal;
} /* end of ucGetNbspCharacter */
/*
* bReadCharacterMappingTable - read the mapping table
*
* Read the character mapping table from file and have the contents sorted
*
* returns TRUE if successful, otherwise FALSE
*/
BOOL
bReadCharacterMappingTable(FILE *pFile)
{
char *pcTmp;
ULONG ulUnicode;
UINT uiLocal;
int iFields;
char szLine[81];
if (pFile == NULL) {
return FALSE;
}
/* Clean the table first */
(void)memset(atCharTable, 0, sizeof(atCharTable));
/* Fill the table */
while (fgets(szLine, (int)sizeof(szLine), pFile)) {
if (szLine[0] == '#' ||
szLine[0] == '\r' ||
szLine[0] == '\n') {
/* Comment or empty line */
continue;
}
iFields = sscanf(szLine, "%x %lx %*s", &uiLocal, &ulUnicode);
if (iFields != 2) {
pcTmp = strchr(szLine, '\r');
if (pcTmp != NULL) {
*pcTmp = '\0';
}
pcTmp = strchr(szLine, '\n');
if (pcTmp != NULL) {
*pcTmp = '\0';
}
werr(0, "Syntax error in: '%s'", szLine);
continue;
}
if (uiLocal > 0xff || ulUnicode > 0xffff) {
werr(0, "Syntax error in: '%02x %04lx'",
uiLocal, ulUnicode);
continue;
}
/* Store only the relevant entries */
if (uiLocal != ulUnicode || uiLocal >= 0x80) {
atCharTable[tNextPosFree].ucLocal = (UCHAR)uiLocal;
atCharTable[tNextPosFree].usUnicode = (USHORT)ulUnicode;
tNextPosFree++;
}
if (tNextPosFree >= elementsof(atCharTable)) {
werr(0, "Too many entries in the character mapping "
"file. Ignoring the rest.");
break;
}
}
if (tNextPosFree != 0) {
DBG_HEX(atCharTable[0].usUnicode);
DBG_HEX(atCharTable[tNextPosFree - 1].usUnicode);
qsort(atCharTable,
tNextPosFree, sizeof(atCharTable[0]),
iCompare);
DBG_HEX(atCharTable[0].usUnicode);
DBG_HEX(atCharTable[tNextPosFree - 1].usUnicode);
}
return TRUE;
} /* end of bReadCharacterMappingTable */
/*
* ulTranslateCharacters - Translate characters to local representation
*
* Translate all characters to local representation
*
* returns the translated character
*/
ULONG
ulTranslateCharacters(USHORT usChar, ULONG ulFileOffset, int iWordVersion,
conversion_type eConversionType, encoding_type eEncoding,
BOOL bUseMacCharSet)
{
const char_table_type *pTmp;
const USHORT *usCharSet;
usCharSet = NULL;
if (bUseMacCharSet) {
/* Macintosh character set */
usCharSet = usMacRoman;
} else if (iWordVersion == 0) {
/* DOS character set */
usCharSet = usCp850;
} else {
/* Windows character set */
switch (eEncoding) {
case encoding_latin_2:
usCharSet = usCp1250;
break;
case encoding_cyrillic:
usCharSet = usCp1251;
break;
case encoding_latin_1:
default:
usCharSet = usCp1252;
break;
}
}
fail(usCharSet == NULL);
if (usChar >= 0x80 && usChar <= 0x9f) {
/* Translate implementation defined characters */
usChar = usCharSet[usChar - 0x80];
} else if (iWordVersion < 8 && usChar >= 0xa0 && usChar <= 0xff) {
/* Translate old character set to Unixcode */
usChar = usCharSet[usChar - 0x80];
}
/* Microsoft Unicode to real Unicode */
if (usChar >= 0xf020 && usChar <= 0xf0ff) {
DBG_HEX_C(usPrivateArea[usChar - 0xf020] == 0x003f, usChar);
usChar = usPrivateArea[usChar - 0xf020];
}
/* Characters with a special meaning in Word */
switch (usChar) {
case IGNORE_CHARACTER:
case FOOTNOTE_SEPARATOR:
case FOOTNOTE_CONTINUATION:
case ANNOTATION:
case FRAME:
case LINE_FEED:
case WORD_SOFT_HYPHEN:
case UNICODE_HYPHENATION_POINT:
return IGNORE_CHARACTER;
case PICTURE:
case TABLE_SEPARATOR:
case TAB:
case HARD_RETURN:
case PAGE_BREAK:
case PAR_END:
case COLUMN_FEED:
return (ULONG)usChar;
case FOOTNOTE_OR_ENDNOTE:
NO_DBG_HEX(ulFileOffset);
switch (eGetNotetype(ulFileOffset)) {
case notetype_is_footnote:
return FOOTNOTE_CHAR;
case notetype_is_endnote:
return ENDNOTE_CHAR;
default:
return UNKNOWN_NOTE_CHAR;
}
case WORD_UNBREAKABLE_JOIN:
return (ULONG)OUR_UNBREAKABLE_JOIN;
default:
break;
}
if (eEncoding != encoding_utf_8) {
/* Latin characters in an oriental text */
if (usChar >= 0xff01 && usChar <= 0xff5e) {
usChar -= 0xfee0;
}
}
if (eEncoding == encoding_latin_1 &&
(eConversionType == conversion_ps ||
eConversionType == conversion_pdf)) {
/* Ugly, but it makes the PostScript and PDF look better */
switch (usChar) {
case UNICODE_ELLIPSIS:
return 140;
case UNICODE_TRADEMARK_SIGN:
return 141;
case UNICODE_PER_MILLE_SIGN:
return 142;
case UNICODE_BULLET:
case UNICODE_BULLET_OPERATOR:
case UNICODE_BLACK_CLUB_SUIT:
return 143;
case UNICODE_LEFT_SINGLE_QMARK:
return 144;
case UNICODE_RIGHT_SINGLE_QMARK:
return 145;
case UNICODE_SINGLE_LEFT_ANGLE_QMARK:
return 146;
case UNICODE_SINGLE_RIGHT_ANGLE_QMARK:
return 147;
case UNICODE_LEFT_DOUBLE_QMARK:
return 148;
case UNICODE_RIGHT_DOUBLE_QMARK:
return 149;
case UNICODE_DOUBLE_LOW_9_QMARK:
return 150;
case UNICODE_EN_DASH:
return 151;
case UNICODE_EM_DASH:
return 152;
case UNICODE_MINUS_SIGN:
return 153;
case UNICODE_CAPITAL_LIGATURE_OE:
return 154;
case UNICODE_SMALL_LIGATURE_OE:
return 155;
case UNICODE_DAGGER:
return 156;
case UNICODE_DOUBLE_DAGGER:
return 157;
case UNICODE_SMALL_LIGATURE_FI:
return 158;
case UNICODE_SMALL_LIGATURE_FL:
return 159;
default:
break;
}
}
if (eConversionType == conversion_pdf) {
if (eEncoding == encoding_latin_1) {
switch (usChar) {
case UNICODE_EURO_SIGN:
return 128;
default:
break;
}
} else if (eEncoding == encoding_latin_2) {
switch (usChar) {
case UNICODE_CAPITAL_D_WITH_STROKE:
case UNICODE_SMALL_D_WITH_STROKE:
return 0x3f;
default:
break;
}
}
}
if (usChar < 0x80) {
/* US ASCII */
if (usChar < 0x20 || usChar == 0x7f) {
/* Ignore control characters */
DBG_HEX(usChar);
DBG_FIXME();
return IGNORE_CHARACTER;
}
return (ULONG)usChar;
}
if (eEncoding == encoding_utf_8) {
/* No need to convert Unicode characters */
return (ULONG)usChar;
}
/* Unicode to local representation */
pTmp = pGetCharTableRecord(usChar);
if (pTmp != NULL) {
DBG_HEX_C(usChar >= 0x7f && usChar <= 0x9f, usChar);
return (ULONG)pTmp->ucLocal;
}
/* Fancy characters to simple US ASCII */
switch (usChar) {
case UNICODE_SMALL_F_HOOK:
return (ULONG)'f';
case UNICODE_GREEK_CAPITAL_CHI:
return (ULONG)'X';
case UNICODE_GREEK_SMALL_UPSILON:
return (ULONG)'v';
case UNICODE_MODIFIER_CIRCUMFLEX:
case UNICODE_UPWARDS_ARROW:
return (ULONG)'^';
case UNICODE_SMALL_TILDE:
case UNICODE_TILDE_OPERATOR:
return (ULONG)'~';
case UNICODE_EN_QUAD:
case UNICODE_EM_QUAD:
case UNICODE_EN_SPACE:
case UNICODE_EM_SPACE:
case UNICODE_THREE_PER_EM_SPACE:
case UNICODE_FOUR_PER_EM_SPACE:
case UNICODE_SIX_PER_EM_SPACE:
case UNICODE_FIGURE_SPACE:
case UNICODE_PUNCTUATION_SPACE:
case UNICODE_THIN_SPACE:
case UNICODE_NARROW_NO_BREAK_SPACE:
case UNICODE_LIGHT_SHADE:
case UNICODE_MEDIUM_SHADE:
case UNICODE_DARK_SHADE:
return (ULONG)' ';
case UNICODE_LEFT_DOUBLE_QMARK:
case UNICODE_RIGHT_DOUBLE_QMARK:
case UNICODE_DOUBLE_LOW_9_QMARK:
case UNICODE_DOUBLE_HIGH_REV_9_QMARK:
case UNICODE_DOUBLE_PRIME:
return (ULONG)'"';
case UNICODE_LEFT_SINGLE_QMARK:
case UNICODE_RIGHT_SINGLE_QMARK:
case UNICODE_SINGLE_LOW_9_QMARK:
case UNICODE_SINGLE_HIGH_REV_9_QMARK:
case UNICODE_PRIME:
return (ULONG)'\'';
case UNICODE_HYPHEN:
case UNICODE_NON_BREAKING_HYPHEN:
case UNICODE_FIGURE_DASH:
case UNICODE_EN_DASH:
case UNICODE_EM_DASH:
case UNICODE_HORIZONTAL_BAR:
case UNICODE_MINUS_SIGN:
case UNICODE_BD_LIGHT_HORIZONTAL:
case UNICODE_BD_DOUBLE_HORIZONTAL:
return (ULONG)'-';
case UNICODE_DOUBLE_VERTICAL_LINE:
case UNICODE_BD_LIGHT_VERTICAL:
case UNICODE_BD_DOUBLE_VERTICAL:
return (ULONG)'|';
case UNICODE_DOUBLE_LOW_LINE:
return (ULONG)'_';
case UNICODE_DAGGER:
return (ULONG)'+';
case UNICODE_DOUBLE_DAGGER:
return (ULONG)'#';
case UNICODE_BULLET:
case UNICODE_BULLET_OPERATOR:
case UNICODE_BLACK_CLUB_SUIT:
return (ULONG)ucGetBulletCharacter(eConversionType, eEncoding);
case UNICODE_ONE_DOT_LEADER:
case UNICODE_TWO_DOT_LEADER:
return (ULONG)'.';
case UNICODE_ELLIPSIS:
#if defined(__riscos)
return (ULONG)OUR_ELLIPSIS;
#else
if (ulFileOffset == 0) {
return (ULONG)OUR_ELLIPSIS;
}
return UNICODE_ELLIPSIS;
#endif /* __riscos */
case UNICODE_DOUBLE_LEFT_ANGLE_QMARK:
case UNICODE_TRIANGULAR_BULLET:
case UNICODE_SINGLE_LEFT_ANGLE_QMARK:
case UNICODE_LEFTWARDS_ARROW:
return (ULONG)'<';
case UNICODE_DOUBLE_RIGHT_ANGLE_QMARK:
case UNICODE_SINGLE_RIGHT_ANGLE_QMARK:
case UNICODE_RIGHTWARDS_ARROW:
return (ULONG)'>';
case UNICODE_UNDERTIE:
return (ULONG)'-';
case UNICODE_N_ARY_SUMMATION:
return (ULONG)'S';
case UNICODE_EURO_SIGN:
return (ULONG)'E';
case UNICODE_CIRCLE:
case UNICODE_SQUARE:
return (ULONG)'O';
case UNICODE_DIAMOND:
return (ULONG)OUR_DIAMOND;
case UNICODE_NUMERO_SIGN:
return (ULONG)'N';
case UNICODE_KELVIN_SIGN:
return (ULONG)'K';
case UNICODE_DOWNWARDS_ARROW:
return (ULONG)'v';
case UNICODE_FRACTION_SLASH:
case UNICODE_DIVISION_SLASH:
return (ULONG)'/';
case UNICODE_ASTERISK_OPERATOR:
return (ULONG)'*';
case UNICODE_RATIO:
return (ULONG)':';
case UNICODE_BD_LIGHT_DOWN_RIGHT:
case UNICODE_BD_LIGHT_DOWN_AND_LEFT:
case UNICODE_BD_LIGHT_UP_AND_RIGHT:
case UNICODE_BD_LIGHT_UP_AND_LEFT:
case UNICODE_BD_LIGHT_VERTICAL_AND_RIGHT:
case UNICODE_BD_LIGHT_VERTICAL_AND_LEFT:
case UNICODE_BD_LIGHT_DOWN_AND_HORIZONTAL:
case UNICODE_BD_LIGHT_UP_AND_HORIZONTAL:
case UNICODE_BD_LIGHT_VERTICAL_AND_HORIZONTAL:
case UNICODE_BD_DOUBLE_DOWN_AND_RIGHT:
case UNICODE_BD_DOUBLE_DOWN_AND_LEFT:
case UNICODE_BD_DOUBLE_UP_AND_RIGHT:
case UNICODE_BD_DOUBLE_UP_AND_LEFT:
case UNICODE_BD_DOUBLE_VERTICAL_AND_RIGHT:
case UNICODE_BD_DOUBLE_VERTICAL_AND_LEFT:
case UNICODE_BD_DOUBLE_DOWN_AND_HORIZONTAL:
case UNICODE_BD_DOUBLE_UP_AND_HORIZONTAL:
case UNICODE_BD_DOUBLE_VERTICAL_AND_HORIZONTAL:
case UNICODE_BLACK_SQUARE:
return (ULONG)'+';
case UNICODE_HAIR_SPACE:
case UNICODE_ZERO_WIDTH_SPACE:
case UNICODE_ZERO_WIDTH_NON_JOINER:
case UNICODE_ZERO_WIDTH_JOINER:
case UNICODE_LEFT_TO_RIGHT_MARK:
case UNICODE_RIGHT_TO_LEFT_MARK:
case UNICODE_LEFT_TO_RIGHT_EMBEDDING:
case UNICODE_RIGHT_TO_LEFT_EMBEDDING:
case UNICODE_POP_DIRECTIONAL_FORMATTING:
case UNICODE_LEFT_TO_RIGHT_OVERRIDE:
case UNICODE_RIGHT_TO_LEFT_OVERRIDE:
case UNICODE_ZERO_WIDTH_NO_BREAK_SPACE:
return IGNORE_CHARACTER;
default:
break;
}
if (usChar == UNICODE_TRADEMARK_SIGN) {
/*
* No local representation, it doesn't look like anything in
* US-ASCII and a question mark does more harm than good.
*/
return IGNORE_CHARACTER;
}
if (usChar >= 0xa0 && usChar <= 0xff) {
/* Before Word 97, Word did't use Unicode */
return (ULONG)usChar;
}
DBG_HEX_C(usChar < 0x3000 || usChar >= 0xd800, ulFileOffset);
DBG_HEX_C(usChar < 0x3000 || usChar >= 0xd800, usChar);
DBG_MSG_C(usChar >= 0xe000 && usChar < 0xf900, "Private Use Area");
/* Untranslated Unicode character */
return 0x3f;
} /* end of ulTranslateCharacters */
/*
* ulToUpper - convert letter to upper case
*
* This function converts a letter to upper case. Unlike toupper(3) this
* function is independent from the settings of locale. This comes in handy
* for people who have to read Word documents in more than one language or
* contain more than one language.
*
* returns the converted letter, or ulChar if the conversion was not possible.
*/
ULONG
ulToUpper(ULONG ulChar)
{
if (ulChar < 0x80) {
/* US ASCII: use standard function */
return (ULONG)toupper((int)ulChar);
}
if (ulChar >= 0xe0 && ulChar <= 0xfe && ulChar != 0xf7) {
/*
* Lower case accented characters
* 0xf7 is Division sign; 0xd7 is Multiplication sign
* 0xff is y with diaeresis; 0xdf is Sharp s
*/
return ulChar & ~0x20;
}
#if defined(__STDC_ISO_10646__)
/*
* If this is ISO C99 and all locales have wchar_t = ISO 10646
* (e.g., glibc 2.2 or newer), then use standard function
*/
if (ulChar > 0xff) {
return (ULONG)towupper((wint_t)ulChar);
}
#endif /* __STDC_ISO_10646__ */
return ulChar;
} /* end of ulToUpper */

374
src/datalist.c Normal file
View File

@@ -0,0 +1,374 @@
/*
* datalist.c
* Copyright (C) 2000-2002 A.J. van Os; Released under GPL
*
* Description:
* Build, read and destroy a list of Word data blocks
*/
#include <stdlib.h>
#include <errno.h>
#include "antiword.h"
#if defined(__riscos)
#define EIO 42
#endif /* __riscos */
/*
* Private structure to hide the way the information
* is stored from the rest of the program
*/
typedef struct data_mem_tag {
data_block_type tInfo;
struct data_mem_tag *pNext;
} data_mem_type;
/* Variable to describe the start of the data block list */
static data_mem_type *pAnchor = NULL;
/* Variable needed to read the data block list */
static data_mem_type *pBlockLast = NULL;
/* Variable needed to read the data block list */
static data_mem_type *pBlockCurrent = NULL;
static ULONG ulBlockOffset = 0;
static size_t tByteNext = 0;
/* Last block read */
static UCHAR aucBlock[BIG_BLOCK_SIZE];
/*
* vDestroyDataBlockList - destroy the data block list
*/
void
vDestroyDataBlockList(void)
{
data_mem_type *pCurr, *pNext;
DBG_MSG("vDestroyDataBlockList");
pCurr = pAnchor;
while (pCurr != NULL) {
pNext = pCurr->pNext;
pCurr = xfree(pCurr);
pCurr = pNext;
}
pAnchor = NULL;
/* Reset all the control variables */
pBlockLast = NULL;
pBlockCurrent = NULL;
ulBlockOffset = 0;
tByteNext = 0;
} /* end of vDestroyDataBlockList */
/*
* bAdd2DataBlockList - add an element to the data block list
*
* Returns TRUE when successful, otherwise FALSE
*/
BOOL
bAdd2DataBlockList(const data_block_type *pDataBlock)
{
data_mem_type *pListMember;
fail(pDataBlock == NULL);
fail(pDataBlock->ulFileOffset == FC_INVALID);
fail(pDataBlock->ulDataPos == CP_INVALID);
fail(pDataBlock->ulLength == 0);
NO_DBG_MSG("bAdd2DataBlockList");
NO_DBG_HEX(pDataBlock->ulFileOffset);
NO_DBG_HEX(pDataBlock->ulDataPos);
NO_DBG_HEX(pDataBlock->ulLength);
if (pDataBlock->ulFileOffset == FC_INVALID ||
pDataBlock->ulDataPos == CP_INVALID ||
pDataBlock->ulLength == 0) {
werr(0, "Software (datablock) error");
return FALSE;
}
/* Check for continuous blocks */
if (pBlockLast != NULL &&
pBlockLast->tInfo.ulFileOffset +
pBlockLast->tInfo.ulLength == pDataBlock->ulFileOffset &&
pBlockLast->tInfo.ulDataPos +
pBlockLast->tInfo.ulLength == pDataBlock->ulDataPos) {
/* These are continous blocks */
pBlockLast->tInfo.ulLength += pDataBlock->ulLength;
return TRUE;
}
/* Make a new block */
pListMember = xmalloc(sizeof(data_mem_type));
/* Add the block to the data list */
pListMember->tInfo = *pDataBlock;
pListMember->pNext = NULL;
if (pAnchor == NULL) {
pAnchor = pListMember;
} else {
fail(pBlockLast == NULL);
pBlockLast->pNext = pListMember;
}
pBlockLast = pListMember;
return TRUE;
} /* end of bAdd2DataBlockList */
/*
* ulGetDataOffset - get the offset in the data block list
*
* Get the fileoffset the current position in the data block list
*/
ULONG
ulGetDataOffset(FILE *pFile)
{
return pBlockCurrent->tInfo.ulFileOffset + ulBlockOffset + tByteNext;
} /* end of ulGetDataOffset */
/*
* bSetDataOffset - set the offset in the data block list
*
* Make the given fileoffset the current position in the data block list
*/
BOOL
bSetDataOffset(FILE *pFile, ULONG ulFileOffset)
{
data_mem_type *pCurr;
size_t tReadLen;
DBG_HEX(ulFileOffset);
for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
if (ulFileOffset < pCurr->tInfo.ulFileOffset ||
ulFileOffset >= pCurr->tInfo.ulFileOffset +
pCurr->tInfo.ulLength) {
/* The file offset is not in this block */
continue;
}
/* Compute the maximum number of bytes to read */
tReadLen = (size_t)(pCurr->tInfo.ulFileOffset +
pCurr->tInfo.ulLength -
ulFileOffset);
/* Compute the real number of bytes to read */
if (tReadLen > sizeof(aucBlock)) {
tReadLen = sizeof(aucBlock);
}
/* Read the bytes */
if (!bReadBytes(aucBlock, tReadLen, ulFileOffset, pFile)) {
return FALSE;
}
/* Set the control variables */
pBlockCurrent = pCurr;
ulBlockOffset = ulFileOffset - pCurr->tInfo.ulFileOffset;
tByteNext = 0;
return TRUE;
}
return FALSE;
} /* end of bSetDataOffset */
/*
* iNextByte - get the next byte from the data block list
*/
int
iNextByte(FILE *pFile)
{
ULONG ulReadOff;
size_t tReadLen;
fail(pBlockCurrent == NULL);
if (tByteNext >= sizeof(aucBlock) ||
ulBlockOffset + tByteNext >= pBlockCurrent->tInfo.ulLength) {
if (ulBlockOffset + sizeof(aucBlock) <
pBlockCurrent->tInfo.ulLength) {
/* Same block, next part */
ulBlockOffset += sizeof(aucBlock);
} else {
/* Next block, first part */
pBlockCurrent = pBlockCurrent->pNext;
ulBlockOffset = 0;
}
if (pBlockCurrent == NULL) {
/* Past the last part of the last block */
errno = EIO;
return EOF;
}
tReadLen = (size_t)
(pBlockCurrent->tInfo.ulLength - ulBlockOffset);
if (tReadLen > sizeof(aucBlock)) {
tReadLen = sizeof(aucBlock);
}
ulReadOff = pBlockCurrent->tInfo.ulFileOffset + ulBlockOffset;
if (!bReadBytes(aucBlock, tReadLen, ulReadOff, pFile)) {
errno = EIO;
return EOF;
}
tByteNext = 0;
}
return (int)aucBlock[tByteNext++];
} /* end of iNextByte */
/*
* usNextWord - get the next word from the data block list
*
* Read a two byte value in Little Endian order, that means MSB last
*
* All return values can be valid so errno is set in case of error
*/
USHORT
usNextWord(FILE *pFile)
{
USHORT usLSB, usMSB;
usLSB = (USHORT)iNextByte(pFile);
if (usLSB == (USHORT)EOF) {
errno = EIO;
return (USHORT)EOF;
}
usMSB = (USHORT)iNextByte(pFile);
if (usMSB == (USHORT)EOF) {
DBG_MSG("usNextWord: Unexpected EOF");
errno = EIO;
return (USHORT)EOF;
}
return (usMSB << 8) | usLSB;
} /* end of usNextWord */
/*
* ulNextLong - get the next long from the data block list
*
* Read a four byte value in Little Endian order, that means MSW last
*
* All return values can be valid so errno is set in case of error
*/
ULONG
ulNextLong(FILE *pFile)
{
ULONG ulLSW, ulMSW;
ulLSW = (ULONG)usNextWord(pFile);
if (ulLSW == (ULONG)EOF) {
errno = EIO;
return (ULONG)EOF;
}
ulMSW = (ULONG)usNextWord(pFile);
if (ulMSW == (ULONG)EOF) {
DBG_MSG("ulNextLong: Unexpected EOF");
errno = EIO;
return (ULONG)EOF;
}
return (ulMSW << 16) | ulLSW;
} /* end of ulNextLong */
/*
* usNextWordBE - get the next two byte value
*
* Read a two byte value in Big Endian order, that means MSB first
*
* All return values can be valid so errno is set in case of error
*/
USHORT
usNextWordBE(FILE *pFile)
{
USHORT usLSB, usMSB;
usMSB = (USHORT)iNextByte(pFile);
if (usMSB == (USHORT)EOF) {
errno = EIO;
return (USHORT)EOF;
}
usLSB = (USHORT)iNextByte(pFile);
if (usLSB == (USHORT)EOF) {
DBG_MSG("usNextWordBE: Unexpected EOF");
errno = EIO;
return (USHORT)EOF;
}
return (usMSB << 8) | usLSB;
} /* end of usNextWordBE */
/*
* ulNextLongBE - get the next four byte value
*
* Read a four byte value in Big Endian order, that means MSW first
*
* All return values can be valid so errno is set in case of error
*/
ULONG
ulNextLongBE(FILE *pFile)
{
ULONG ulLSW, ulMSW;
ulMSW = (ULONG)usNextWordBE(pFile);
if (ulMSW == (ULONG)EOF) {
errno = EIO;
return (ULONG)EOF;
}
ulLSW = (ULONG)usNextWordBE(pFile);
if (ulLSW == (ULONG)EOF) {
DBG_MSG("ulNextLongBE: Unexpected EOF");
errno = EIO;
return (ULONG)EOF;
}
return (ulMSW << 16) | ulLSW;
} /* end of ulNextLongBE */
/*
* tSkipBytes - skip over the given number of bytes
*
* Returns the number of skipped bytes
*/
size_t
tSkipBytes(FILE *pFile, size_t tToSkip)
{
size_t tToGo, tMaxMove, tMove;
fail(pFile == NULL);
fail(pBlockCurrent == NULL);
tToGo = tToSkip;
while (tToGo != 0) {
/* Goto the end of the current block */
tMaxMove = min(sizeof(aucBlock) - tByteNext,
(size_t)(pBlockCurrent->tInfo.ulLength -
ulBlockOffset - tByteNext));
tMove = min(tMaxMove, tToGo);
tByteNext += tMove;
tToGo -= tMove;
if (tToGo != 0) {
/* Goto the next block */
if (iNextByte(pFile) == EOF) {
return tToSkip - tToGo;
}
tToGo--;
}
}
return tToSkip;
} /* end of tSkipBytes */
/*
* Translate a data position to an offset in the file.
* Logical to physical offset.
*
* Returns: FC_INVALID: in case of error
* otherwise: the computed file offset
*/
ULONG
ulDataPos2FileOffset(ULONG ulDataPos)
{
data_mem_type *pCurr;
fail(ulDataPos == CP_INVALID);
for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
if (ulDataPos < pCurr->tInfo.ulDataPos ||
ulDataPos >= pCurr->tInfo.ulDataPos +
pCurr->tInfo.ulLength) {
/* The data offset is not in this block, try the next */
continue;
}
/* The data offset is in the current block */
return pCurr->tInfo.ulFileOffset +
ulDataPos -
pCurr->tInfo.ulDataPos;
}
/* Passed beyond the end of the list */
DBG_HEX_C(ulDataPos != 0, ulDataPos);
return FC_INVALID;
} /* end of ulDataPos2FileOffset */

117
src/debug.h Normal file
View File

@@ -0,0 +1,117 @@
/*
* debug.h
* Copyright (C) 1998-2005 A.J. van Os; Released under GPL
*
* Description:
* Macro's for debuging.
*/
#if !defined(__debug_h)
#define __debug_h 1
#include <stdio.h>
#include <ctype.h>
#if defined(DEBUG)
#define DBG_MSG(t) (void)fprintf(stderr,\
"%s[%3d]: %.240s\n",\
__FILE__, __LINE__, (t))
#define DBG_STRN(t,m) (void)fprintf(stderr,\
"%s[%3d]: %d '%.*s'\n",\
__FILE__, __LINE__,\
(int)(m), (int)(m), (const char *)(t))
#define DBG_CHR(m) (void)fprintf(stderr,\
"%s[%3d]: "#m" = %3d 0x%02x '%c'\n",\
__FILE__, __LINE__,\
(int)(m), (unsigned int)(unsigned char)(m),\
isprint((int)(unsigned char)(m))?(char)(m):' ')
#define DBG_DEC(m) (void)fprintf(stderr,\
"%s[%3d]: "#m" = %ld\n",\
__FILE__, __LINE__, (long)(m))
#define DBG_HEX(m) (void)fprintf(stderr,\
"%s[%3d]: "#m" = 0x%02lx\n",\
__FILE__, __LINE__, (unsigned long)(m))
#define DBG_FLT(m) (void)fprintf(stderr,\
"%s[%3d]: "#m" = %.3f\n",\
__FILE__, __LINE__, (double)(m))
#define DBG_FIXME() (void)fprintf(stderr,\
"%s[%3d]: FIXME\n",\
__FILE__, __LINE__)
#define DBG_PRINT_BLOCK(b,m) vPrintBlock(__FILE__, __LINE__,(b),(m))
#define DBG_UNICODE(t) vPrintUnicode(__FILE__, __LINE__,\
(const UCHAR *)(t),unilen(t))
#define DBG_UNICODE_N(t,m) vPrintUnicode(__FILE__, __LINE__,\
(const UCHAR *)(t),(m))
#define DBG_MSG_C(c,t) do { if (c) DBG_MSG(t); } while(0)
#define DBG_STRN_C(c,t,m) do { if (c) DBG_STRN(t,m); } while(0)
#define DBG_CHR_C(c,m) do { if (c) DBG_CHR(m); } while(0)
#define DBG_DEC_C(c,m) do { if (c) DBG_DEC(m); } while(0)
#define DBG_HEX_C(c,m) do { if (c) DBG_HEX(m); } while(0)
#define DBG_FLT_C(c,m) do { if (c) DBG_FLT(m); } while(0)
#else
#define DBG_MSG(t) /* EMPTY */
#define DBG_STRN(t,m) /* EMPTY */
#define DBG_CHR(m) /* EMPTY */
#define DBG_DEC(m) /* EMPTY */
#define DBG_HEX(m) /* EMPTY */
#define DBG_FLT(m) /* EMPTY */
#define DBG_FIXME() /* EMPTY */
#define DBG_PRINT_BLOCK(b,m) /* EMPTY */
#define DBG_UNICODE(t) /* EMPTY */
#define DBG_UNICODE_N(t,m) /* EMPTY */
#define DBG_MSG_C(c,t) /* EMPTY */
#define DBG_STRN_C(c,t,m) /* EMPTY */
#define DBG_CHR_C(c,m) /* EMPTY */
#define DBG_DEC_C(c,m) /* EMPTY */
#define DBG_HEX_C(c,m) /* EMPTY */
#define DBG_FLT_C(c,m) /* EMPTY */
#endif /* DEBUG */
#define NO_DBG_MSG(t) /* EMPTY */
#define NO_DBG_STRN(t,m) /* EMPTY */
#define NO_DBG_CHR(m) /* EMPTY */
#define NO_DBG_DEC(m) /* EMPTY */
#define NO_DBG_HEX(m) /* EMPTY */
#define NO_DBG_FLT(m) /* EMPTY */
#define NO_DBG_PRINT_BLOCK(b,m) /* EMPTY */
#define NO_DBG_UNICODE(t) /* EMPTY */
#define NO_DBG_UNICODE_N(t,m) /* EMPTY */
#define NO_DBG_MSG_C(c,t) /* EMPTY */
#define NO_DBG_STRN_C(c,t,m) /* EMPTY */
#define NO_DBG_CHR_C(c,m) /* EMPTY */
#define NO_DBG_DEC_C(c,m) /* EMPTY */
#define NO_DBG_HEX_C(c,m) /* EMPTY */
#define NO_DBG_FLT_C(c,m) /* EMPTY */
#if defined(TRACE)
#define TRACE_MSG(t) do {\
(void)fprintf(stderr,\
"%s[%3d]: TRACE:%.40s\n",\
__FILE__, __LINE__, (t));\
(void)fflush(stderr);\
} while(0)
#else
#define TRACE_MSG(t) /* EMPTY */
#endif /* TRACE */
#endif /* !__debug_h */

114
src/depot.c Normal file
View File

@@ -0,0 +1,114 @@
/*
* depot.c
* Copyright (C) 1998-2002 A.J. van Os; Released under GPL
*
* Description:
* Functions to compute the depot offset
*/
#include "antiword.h"
#define SIZE_RATIO (BIG_BLOCK_SIZE/SMALL_BLOCK_SIZE)
static ULONG *aulSmallBlockList = NULL;
static size_t tSmallBlockListLen = 0;
/*
* vDestroySmallBlockList - destroy the small block list
*/
void
vDestroySmallBlockList(void)
{
DBG_MSG("vDestroySmallBlockList");
aulSmallBlockList = xfree(aulSmallBlockList);
tSmallBlockListLen = 0;
} /* end of vDestroySmalBlockList */
/*
* vCreateSmallBlockList - create the small block list
*
* returns: TRUE when successful, otherwise FALSE
*/
BOOL
bCreateSmallBlockList(ULONG ulStartblock, const ULONG *aulBBD, size_t tBBDLen)
{
ULONG ulTmp;
size_t tSize;
int iIndex;
fail(aulSmallBlockList != NULL);
fail(tSmallBlockListLen != 0);
fail(ulStartblock > MAX_BLOCKNUMBER && ulStartblock != END_OF_CHAIN);
fail(aulBBD == NULL);
fail(tBBDLen == 0);
/* Find the length of the small block list */
for (tSmallBlockListLen = 0, ulTmp = ulStartblock;
tSmallBlockListLen < tBBDLen && ulTmp != END_OF_CHAIN;
tSmallBlockListLen++, ulTmp = aulBBD[ulTmp]) {
if (ulTmp >= (ULONG)tBBDLen) {
DBG_DEC(ulTmp);
DBG_DEC(tBBDLen);
werr(1, "The Big Block Depot is damaged");
}
}
DBG_DEC(tSmallBlockListLen);
if (tSmallBlockListLen == 0) {
/* There is no small block list */
fail(ulStartblock != END_OF_CHAIN);
aulSmallBlockList = NULL;
return TRUE;
}
/* Create the small block list */
tSize = tSmallBlockListLen * sizeof(ULONG);
aulSmallBlockList = xmalloc(tSize);
for (iIndex = 0, ulTmp = ulStartblock;
iIndex < (int)tBBDLen && ulTmp != END_OF_CHAIN;
iIndex++, ulTmp = aulBBD[ulTmp]) {
if (ulTmp >= (ULONG)tBBDLen) {
DBG_DEC(ulTmp);
DBG_DEC(tBBDLen);
werr(1, "The Big Block Depot is damaged");
}
aulSmallBlockList[iIndex] = ulTmp;
NO_DBG_DEC(aulSmallBlockList[iIndex]);
}
return TRUE;
} /* end of bCreateSmallBlockList */
/*
* ulDepotOffset - get the depot offset the block list
*/
ULONG
ulDepotOffset(ULONG ulIndex, size_t tBlockSize)
{
ULONG ulTmp;
size_t tTmp;
fail(ulIndex >= ULONG_MAX / BIG_BLOCK_SIZE);
switch (tBlockSize) {
case BIG_BLOCK_SIZE:
return (ulIndex + 1) * BIG_BLOCK_SIZE;
case SMALL_BLOCK_SIZE:
tTmp = (size_t)(ulIndex / SIZE_RATIO);
ulTmp = ulIndex % SIZE_RATIO;
if (aulSmallBlockList == NULL ||
tTmp >= tSmallBlockListLen) {
DBG_HEX(aulSmallBlockList);
DBG_DEC(tSmallBlockListLen);
DBG_DEC(tTmp);
return 0;
}
return ((aulSmallBlockList[tTmp] + 1) * SIZE_RATIO +
ulTmp) * SMALL_BLOCK_SIZE;
default:
DBG_DEC(tBlockSize);
DBG_FIXME();
return 0;
}
} /* end of ulDepotOffset */

509
src/dib2eps.c Normal file
View File

@@ -0,0 +1,509 @@
/*
* dib2eps.c
* Copyright (C) 2000-2003 A.J. van Os; Released under GPL
*
* Description:
* Functions to translate dib pictures into eps
*
*================================================================
* This part of the software is based on:
* The Windows Bitmap Decoder Class part of paintlib
* Paintlib is copyright (c) 1996-2000 Ulrich von Zadow
*================================================================
* The credit should go to him, but all the bugs are mine.
*/
#include <stdio.h>
#include "antiword.h"
/*
* vDecode1bpp - decode an uncompressed 1 bit per pixel image
*/
static void
vDecode1bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
{
size_t tPadding;
int iX, iY, iN, iByte, iTmp, iEighthWidth, iUse;
DBG_MSG("vDecode1bpp");
fail(pOutFile == NULL);
fail(pImg == NULL);
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 2);
DBG_DEC(pImg->iWidth);
DBG_DEC(pImg->iHeight);
iEighthWidth = (pImg->iWidth + 7) / 8;
tPadding = (size_t)(ROUND4(iEighthWidth) - iEighthWidth);
for (iY = 0; iY < pImg->iHeight; iY++) {
for (iX = 0; iX < iEighthWidth; iX++) {
iByte = iNextByte(pInFile);
if (iByte == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
if (iX == iEighthWidth - 1 && pImg->iWidth % 8 != 0) {
iUse = pImg->iWidth % 8;
} else {
iUse = 8;
}
for (iN = 0; iN < iUse; iN++) {
switch (iN) {
case 0: iTmp = (iByte & 0x80) / 128; break;
case 1: iTmp = (iByte & 0x40) / 64; break;
case 2: iTmp = (iByte & 0x20) / 32; break;
case 3: iTmp = (iByte & 0x10) / 16; break;
case 4: iTmp = (iByte & 0x08) / 8; break;
case 5: iTmp = (iByte & 0x04) / 4; break;
case 6: iTmp = (iByte & 0x02) / 2; break;
case 7: iTmp = (iByte & 0x01); break;
default: iTmp = 0; break;
}
vASCII85EncodeByte(pOutFile, iTmp);
}
}
(void)tSkipBytes(pInFile, tPadding);
}
vASCII85EncodeByte(pOutFile, EOF);
} /* end of vDecode1bpp */
/*
* vDecode4bpp - decode an uncompressed 4 bits per pixel image
*/
static void
vDecode4bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
{
size_t tPadding;
int iX, iY, iN, iByte, iTmp, iHalfWidth, iUse;
DBG_MSG("vDecode4bpp");
fail(pInFile == NULL);
fail(pOutFile == NULL);
fail(pImg == NULL);
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
DBG_DEC(pImg->iWidth);
DBG_DEC(pImg->iHeight);
iHalfWidth = (pImg->iWidth + 1) / 2;
tPadding = (size_t)(ROUND4(iHalfWidth) - iHalfWidth);
for (iY = 0; iY < pImg->iHeight; iY++) {
for (iX = 0; iX < iHalfWidth; iX++) {
iByte = iNextByte(pInFile);
if (iByte == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
if (iX == iHalfWidth - 1 && odd(pImg->iWidth)) {
iUse = 1;
} else {
iUse = 2;
}
for (iN = 0; iN < iUse; iN++) {
if (odd(iN)) {
iTmp = iByte & 0x0f;
} else {
iTmp = (iByte & 0xf0) / 16;
}
vASCII85EncodeByte(pOutFile, iTmp);
}
}
(void)tSkipBytes(pInFile, tPadding);
}
vASCII85EncodeByte(pOutFile, EOF);
} /* end of vDecode4bpp */
/*
* vDecode8bpp - decode an uncompressed 8 bits per pixel image
*/
static void
vDecode8bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
{
size_t tPadding;
int iX, iY, iByte;
DBG_MSG("vDecode8bpp");
fail(pInFile == NULL);
fail(pOutFile == NULL);
fail(pImg == NULL);
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
DBG_DEC(pImg->iWidth);
DBG_DEC(pImg->iHeight);
tPadding = (size_t)(ROUND4(pImg->iWidth) - pImg->iWidth);
for (iY = 0; iY < pImg->iHeight; iY++) {
for (iX = 0; iX < pImg->iWidth; iX++) {
iByte = iNextByte(pInFile);
if (iByte == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
vASCII85EncodeByte(pOutFile, iByte);
}
(void)tSkipBytes(pInFile, tPadding);
}
vASCII85EncodeByte(pOutFile, EOF);
} /* end of vDecode8bpp */
/*
* vDecode24bpp - decode an uncompressed 24 bits per pixel image
*/
static void
vDecode24bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
{
size_t tPadding;
int iX, iY, iBlue, iGreen, iRed, iTripleWidth;
DBG_MSG("vDecode24bpp");
fail(pInFile == NULL);
fail(pOutFile == NULL);
fail(pImg == NULL);
fail(!pImg->bColorImage);
DBG_DEC(pImg->iWidth);
DBG_DEC(pImg->iHeight);
iTripleWidth = pImg->iWidth * 3;
tPadding = (size_t)(ROUND4(iTripleWidth) - iTripleWidth);
for (iY = 0; iY < pImg->iHeight; iY++) {
for (iX = 0; iX < pImg->iWidth; iX++) {
/* Change from BGR order to RGB order */
iBlue = iNextByte(pInFile);
if (iBlue == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
iGreen = iNextByte(pInFile);
if (iGreen == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
iRed = iNextByte(pInFile);
if (iRed == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
vASCII85EncodeByte(pOutFile, iRed);
vASCII85EncodeByte(pOutFile, iGreen);
vASCII85EncodeByte(pOutFile, iBlue);
}
(void)tSkipBytes(pInFile, tPadding);
}
vASCII85EncodeByte(pOutFile, EOF);
} /* end of vDecode24bpp */
/*
* vDecodeRle4 - decode a RLE compressed 4 bits per pixel image
*/
static void
vDecodeRle4(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
{
int iX, iY, iByte, iTmp, iRunLength, iRun;
BOOL bEOF, bEOL;
DBG_MSG("vDecodeRle4");
fail(pInFile == NULL);
fail(pOutFile == NULL);
fail(pImg == NULL);
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
DBG_DEC(pImg->iWidth);
DBG_DEC(pImg->iHeight);
bEOF = FALSE;
for (iY = 0; iY < pImg->iHeight && !bEOF; iY++) {
bEOL = FALSE;
iX = 0;
while (!bEOL) {
iRunLength = iNextByte(pInFile);
if (iRunLength == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
if (iRunLength != 0) {
/*
* Encoded packet:
* RunLength pixels, all the "same" value
*/
iByte = iNextByte(pInFile);
if (iByte == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
for (iRun = 0; iRun < iRunLength; iRun++) {
if (odd(iRun)) {
iTmp = iByte & 0x0f;
} else {
iTmp = (iByte & 0xf0) / 16;
}
if (iX < pImg->iWidth) {
vASCII85EncodeByte(pOutFile, iTmp);
}
iX++;
}
continue;
}
/* Literal or escape */
iRunLength = iNextByte(pInFile);
if (iRunLength == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
if (iRunLength == 0) { /* End of line escape */
bEOL = TRUE;
} else if (iRunLength == 1) { /* End of file escape */
bEOF = TRUE;
bEOL = TRUE;
} else if (iRunLength == 2) { /* Delta escape */
DBG_MSG("RLE4: encountered delta escape");
bEOF = TRUE;
bEOL = TRUE;
} else { /* Literal packet */
iByte = 0;
for (iRun = 0; iRun < iRunLength; iRun++) {
if (odd(iRun)) {
iTmp = iByte & 0x0f;
} else {
iByte = iNextByte(pInFile);
if (iByte == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
iTmp = (iByte & 0xf0) / 16;
}
if (iX < pImg->iWidth) {
vASCII85EncodeByte(pOutFile, iTmp);
}
iX++;
}
/* Padding if the number of bytes is odd */
if (odd((iRunLength + 1) / 2)) {
(void)tSkipBytes(pInFile, 1);
}
}
}
DBG_DEC_C(iX != pImg->iWidth, iX);
}
vASCII85EncodeByte(pOutFile, EOF);
} /* end of vDecodeRle4 */
/*
* vDecodeRle8 - decode a RLE compressed 8 bits per pixel image
*/
static void
vDecodeRle8(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
{
int iX, iY, iByte, iRunLength, iRun;
BOOL bEOF, bEOL;
DBG_MSG("vDecodeRle8");
fail(pInFile == NULL);
fail(pOutFile == NULL);
fail(pImg == NULL);
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
DBG_DEC(pImg->iWidth);
DBG_DEC(pImg->iHeight);
bEOF = FALSE;
for (iY = 0; iY < pImg->iHeight && !bEOF; iY++) {
bEOL = FALSE;
iX = 0;
while (!bEOL) {
iRunLength = iNextByte(pInFile);
if (iRunLength == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
if (iRunLength != 0) {
/*
* Encoded packet:
* RunLength pixels, all the same value
*/
iByte = iNextByte(pInFile);
if (iByte == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
for (iRun = 0; iRun < iRunLength; iRun++) {
if (iX < pImg->iWidth) {
vASCII85EncodeByte(pOutFile, iByte);
}
iX++;
}
continue;
}
/* Literal or escape */
iRunLength = iNextByte(pInFile);
if (iRunLength == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
if (iRunLength == 0) { /* End of line escape */
bEOL = TRUE;
} else if (iRunLength == 1) { /* End of file escape */
bEOF = TRUE;
bEOL = TRUE;
} else if (iRunLength == 2) { /* Delta escape */
DBG_MSG("RLE8: encountered delta escape");
bEOF = TRUE;
bEOL = TRUE;
} else { /* Literal packet */
for (iRun = 0; iRun < iRunLength; iRun++) {
iByte = iNextByte(pInFile);
if (iByte == EOF) {
vASCII85EncodeByte(pOutFile, EOF);
return;
}
if (iX < pImg->iWidth) {
vASCII85EncodeByte(pOutFile, iByte);
}
iX++;
}
/* Padding if the number of bytes is odd */
if (odd(iRunLength)) {
(void)tSkipBytes(pInFile, 1);
}
}
}
DBG_DEC_C(iX != pImg->iWidth, iX);
}
vASCII85EncodeByte(pOutFile, EOF);
} /* end of vDecodeRle8 */
/*
* vDecodeDIB - decode a dib picture
*/
static void
vDecodeDIB(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
{
size_t tHeaderSize;
fail(pInFile == NULL);
fail(pOutFile == NULL);
fail(pImg == NULL);
/* Skip the bitmap info header */
tHeaderSize = (size_t)ulNextLong(pInFile);
(void)tSkipBytes(pInFile, tHeaderSize - 4);
/* Skip the colortable */
if (pImg->uiBitsPerComponent <= 8) {
(void)tSkipBytes(pInFile,
(size_t)(pImg->iColorsUsed *
((tHeaderSize > 12) ? 4 : 3)));
}
switch (pImg->uiBitsPerComponent) {
case 1:
fail(pImg->eCompression != compression_none);
vDecode1bpp(pInFile, pOutFile, pImg);
break;
case 4:
fail(pImg->eCompression != compression_none &&
pImg->eCompression != compression_rle4);
if (pImg->eCompression == compression_rle4) {
vDecodeRle4(pInFile, pOutFile, pImg);
} else {
vDecode4bpp(pInFile, pOutFile, pImg);
}
break;
case 8:
fail(pImg->eCompression != compression_none &&
pImg->eCompression != compression_rle8);
if (pImg->eCompression == compression_rle8) {
vDecodeRle8(pInFile, pOutFile, pImg);
} else {
vDecode8bpp(pInFile, pOutFile, pImg);
}
break;
case 24:
fail(pImg->eCompression != compression_none);
vDecode24bpp(pInFile, pOutFile, pImg);
break;
default:
DBG_DEC(pImg->uiBitsPerComponent);
break;
}
} /* end of vDecodeDIB */
#if defined(DEBUG)
/*
* vCopy2File
*/
static void
vCopy2File(FILE *pInFile, ULONG ulFileOffset, size_t tPictureLen)
{
static int iPicCounter = 0;
FILE *pOutFile;
size_t tIndex;
int iTmp;
char szFilename[30];
if (!bSetDataOffset(pInFile, ulFileOffset)) {
return;
}
sprintf(szFilename, "/tmp/pic/pic%04d.bmp", ++iPicCounter);
pOutFile = fopen(szFilename, "wb");
if (pOutFile == NULL) {
return;
}
/* Turn a dib into a bmp by adding a fake 14 byte header */
(void)putc('B', pOutFile);
(void)putc('M', pOutFile);
for (iTmp = 0; iTmp < 12; iTmp++) {
if (putc(0, pOutFile) == EOF) {
break;
}
}
for (tIndex = 0; tIndex < tPictureLen; tIndex++) {
iTmp = iNextByte(pInFile);
if (putc(iTmp, pOutFile) == EOF) {
break;
}
}
(void)fclose(pOutFile);
} /* end of vCopy2File */
#endif /* DEBUG */
/*
* bTranslateDIB - translate a DIB picture
*
* This function translates a picture from dib to eps
*
* return TRUE when sucessful, otherwise FALSE
*/
BOOL
bTranslateDIB(diagram_type *pDiag, FILE *pInFile,
ULONG ulFileOffset, const imagedata_type *pImg)
{
#if defined(DEBUG)
fail(pImg->tPosition > pImg->tLength);
vCopy2File(pInFile, ulFileOffset, pImg->tLength - pImg->tPosition);
#endif /* DEBUG */
/* Seek to start position of DIB data */
if (!bSetDataOffset(pInFile, ulFileOffset)) {
return FALSE;
}
vImagePrologue(pDiag, pImg);
vDecodeDIB(pInFile, pDiag->pOutFile, pImg);
vImageEpilogue(pDiag);
return TRUE;
} /* end of bTranslateDIB */

597
src/dib2sprt.c Normal file
View File

@@ -0,0 +1,597 @@
/*
* dib2sprt.c
* Copyright (C) 2000-2003 A.J. van Os; Released under GPL
*
* Description:
* Functions to translate dib pictures into sprites
*/
#include <stdio.h>
#include <string.h>
#include "DeskLib:Error.h"
#include "DeskLib:Sprite.h"
#include "antiword.h"
#if 0 /* defined(DEBUG) */
static int iPicCounter = 0;
#endif /* DEBUG */
/*
* iGetByteWidth - compute the number of bytes needed for a row of pixels
*/
static int
iGetByteWidth(const imagedata_type *pImg)
{
switch (pImg->uiBitsPerComponent) {
case 1:
return (pImg->iWidth + 31) / 32 * sizeof(int);
case 4:
return (pImg->iWidth + 7) / 8 * sizeof(int);
case 8:
case 24:
return (pImg->iWidth + 3) / 4 * sizeof(int);
default:
DBG_DEC(pImg->uiBitsPerComponent);
return 0;
}
} /* end of iGetByteWidth */
/*
* pCreateBlankSprite - Create a blank sprite.
*
* Create a blank sprite and add a palette if needed
*
* returns a pointer to the sprite when successful, otherwise NULL
*/
static sprite_areainfo *
pCreateBlankSprite(const imagedata_type *pImg, size_t *pSize)
{
sprite_areainfo *pArea;
UCHAR *pucTmp;
size_t tSize;
screen_modeval uMode;
int iIndex, iPaletteEntries;
TRACE_MSG("pCreateBlankSprite");
fail(pImg == NULL);
fail(pSize == NULL);
switch (pImg->uiBitsPerComponent) {
case 1:
uMode.screen_mode = 18;
iPaletteEntries = 2;
break;
case 4:
uMode.screen_mode = 20;
iPaletteEntries = 16;
break;
case 8:
case 24:
uMode.screen_mode = 21;
iPaletteEntries = 0;
break;
default:
DBG_DEC(pImg->uiBitsPerComponent);
return NULL;
}
fail(iPaletteEntries < 0 || iPaletteEntries > 16);
/* Get memory for the sprite */
tSize = sizeof(sprite_areainfo) +
Sprite_MemorySize(pImg->iWidth, pImg->iHeight, uMode,
iPaletteEntries > 0 ? sprite_HASPAL : sprite_HASNOMASKPAL);
DBG_DEC(tSize);
pArea = xmalloc(tSize);
/* Initialise sprite area */
pArea->areasize = tSize;
pArea->numsprites = 0;
pArea->firstoffset = sizeof(sprite_areainfo);
pArea->freeoffset = sizeof(sprite_areainfo);
/* Create a blank sprite */
Error_CheckFatal(Sprite_Create(pArea, "wordimage",
iPaletteEntries > 0 ? 1 : 0,
pImg->iWidth, pImg->iHeight, uMode));
/* Add the palette */
pucTmp = (UCHAR *)pArea + pArea->firstoffset + sizeof(sprite_header);
for (iIndex = 0; iIndex < iPaletteEntries; iIndex++) {
/* First color */
*pucTmp++ = 0;
*pucTmp++ = pImg->aucPalette[iIndex][0];
*pucTmp++ = pImg->aucPalette[iIndex][1];
*pucTmp++ = pImg->aucPalette[iIndex][2];
/* Second color */
*pucTmp++ = 0;
*pucTmp++ = pImg->aucPalette[iIndex][0];
*pucTmp++ = pImg->aucPalette[iIndex][1];
*pucTmp++ = pImg->aucPalette[iIndex][2];
}
*pSize = tSize;
return pArea;
} /* end of pCreateBlankSprite */
/*
* iReduceColor - reduce from 24 bit to 8 bit color
*
* Reduce 24 bit true colors to RISC OS default 256 color palette
*
* returns the resulting color
*/
static int
iReduceColor(int iRed, int iGreen, int iBlue)
{
int iResult;
iResult = (iBlue & 0x80) ? 0x80 : 0;
iResult |= (iGreen & 0x80) ? 0x40 : 0;
iResult |= (iGreen & 0x40) ? 0x20 : 0;
iResult |= (iRed & 0x80) ? 0x10 : 0;
iResult |= (iBlue & 0x40) ? 0x08 : 0;
iResult |= (iRed & 0x40) ? 0x04 : 0;
iResult |= ((iRed | iGreen | iBlue) & 0x20) ? 0x02 : 0;
iResult |= ((iRed | iGreen | iBlue) & 0x10) ? 0x01 : 0;
return iResult;
} /* end of iReduceColor */
/*
* vDecode1bpp - decode an uncompressed 1 bit per pixel image
*/
static void
vDecode1bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
{
int iX, iY, iByteWidth, iOffset, iTmp, iEighthWidth, iPadding;
UCHAR ucTmp;
DBG_MSG("vDecode1bpp");
fail(pFile == NULL);
fail(pucData == NULL);
fail(pImg == NULL);
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 2);
iByteWidth = iGetByteWidth(pImg);
iEighthWidth = (pImg->iWidth + 7) / 8;
iPadding = ROUND4(iEighthWidth) - iEighthWidth;
for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
for (iX = 0; iX < iEighthWidth; iX++) {
iTmp = iNextByte(pFile);
if (iTmp == EOF) {
return;
}
/* Reverse the bit order */
ucTmp = (iTmp & BIT(0)) ? (UCHAR)BIT(7) : 0;
ucTmp |= (iTmp & BIT(1)) ? (UCHAR)BIT(6) : 0;
ucTmp |= (iTmp & BIT(2)) ? (UCHAR)BIT(5) : 0;
ucTmp |= (iTmp & BIT(3)) ? (UCHAR)BIT(4) : 0;
ucTmp |= (iTmp & BIT(4)) ? (UCHAR)BIT(3) : 0;
ucTmp |= (iTmp & BIT(5)) ? (UCHAR)BIT(2) : 0;
ucTmp |= (iTmp & BIT(6)) ? (UCHAR)BIT(1) : 0;
ucTmp |= (iTmp & BIT(7)) ? (UCHAR)BIT(0) : 0;
iOffset = iY * iByteWidth + iX;
*(pucData + iOffset) = ucTmp;
}
(void)tSkipBytes(pFile, iPadding);
}
} /* end of vDecode1bpp */
/*
* vDecode4bpp - decode an uncompressed 4 bits per pixel image
*/
static void
vDecode4bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
{
int iX, iY, iByteWidth, iOffset, iTmp, iHalfWidth, iPadding;
UCHAR ucTmp;
DBG_MSG("vDecode4bpp");
fail(pFile == NULL);
fail(pucData == NULL);
fail(pImg == NULL);
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
iByteWidth = iGetByteWidth(pImg);
iHalfWidth = (pImg->iWidth + 1) / 2;
iPadding = ROUND4(iHalfWidth) - iHalfWidth;
for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
for (iX = 0; iX < iHalfWidth; iX++) {
iTmp = iNextByte(pFile);
if (iTmp == EOF) {
return;
}
/* Reverse the nibble order */
ucTmp = (iTmp & 0xf0) >> 4;
ucTmp |= (iTmp & 0x0f) << 4;
iOffset = iY * iByteWidth + iX;
*(pucData + iOffset) = ucTmp;
}
(void)tSkipBytes(pFile, iPadding);
}
} /* end of vDecode4bpp */
/*
* vDecode8bpp - decode an uncompressed 8 bits per pixel image
*/
static void
vDecode8bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
{
int iX, iY, iByteWidth, iOffset, iIndex, iPadding;
DBG_MSG("vDecode8bpp");
fail(pFile == NULL);
fail(pucData == NULL);
fail(pImg == NULL);
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
iByteWidth = iGetByteWidth(pImg);
iPadding = ROUND4(pImg->iWidth) - pImg->iWidth;
for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
for (iX = 0; iX < pImg->iWidth; iX++) {
iIndex = iNextByte(pFile);
if (iIndex == EOF) {
return;
}
iOffset = iY * iByteWidth + iX;
*(pucData + iOffset) = iReduceColor(
pImg->aucPalette[iIndex][0],
pImg->aucPalette[iIndex][1],
pImg->aucPalette[iIndex][2]);
}
(void)tSkipBytes(pFile, iPadding);
}
} /* end of vDecode8bpp */
/*
* vDecode24bpp - decode an uncompressed 24 bits per pixel image
*/
static void
vDecode24bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
{
int iX, iY, iTripleWidth, iByteWidth, iOffset, iPadding;
int iRed, iGreen, iBlue;
DBG_MSG("vDecode24bpp");
fail(pFile == NULL);
fail(pucData == NULL);
fail(pImg == NULL);
iByteWidth = iGetByteWidth(pImg);
iTripleWidth = pImg->iWidth * 3;
iPadding = ROUND4(iTripleWidth) - iTripleWidth;
for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
for (iX = 0; iX < pImg->iWidth; iX++) {
iBlue = iNextByte(pFile);
if (iBlue == EOF) {
return;
}
iGreen = iNextByte(pFile);
if (iGreen == EOF) {
return;
}
iRed = iNextByte(pFile);
if (iRed == EOF) {
return;
}
iOffset = iY * iByteWidth + iX;
*(pucData + iOffset) =
iReduceColor(iRed, iGreen, iBlue);
}
(void)tSkipBytes(pFile, iPadding);
}
} /* end of vDecode24bpp */
/*
* vDecodeRle4 - decode a RLE compressed 4 bits per pixel image
*/
static void
vDecodeRle4(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
{
int iX, iY, iByteWidth, iOffset, iTmp, iHalfWidth;
int iRun, iRunLength, iHalfRun;
BOOL bEOL;
UCHAR ucTmp;
DBG_MSG("vDecodeRle4");
fail(pFile == NULL);
fail(pucData == NULL);
fail(pImg == NULL);
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
DBG_DEC(pImg->iWidth);
DBG_DEC(pImg->iHeight);
iByteWidth = iGetByteWidth(pImg);
iHalfWidth = (pImg->iWidth + 1) / 2;
for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
bEOL = FALSE;
iX = 0;
while (!bEOL) {
iRunLength = iNextByte(pFile);
if (iRunLength == EOF) {
return;
}
if (iRunLength != 0) {
/*
* Encoded packet:
* RunLength pixels, all the "same" value
*/
iTmp = iNextByte(pFile);
if (iTmp == EOF) {
return;
}
/* Reverse the nibble order */
ucTmp = (iTmp & 0xf0) >> 4;
ucTmp |= (iTmp & 0x0f) << 4;
iHalfRun = (iRunLength + 1) / 2;
for (iRun = 0; iRun < iHalfRun; iRun++) {
if (iX < iHalfWidth) {
iOffset = iY * iByteWidth + iX;
*(pucData + iOffset) = ucTmp;
}
iX++;
}
continue;
}
/* Literal or escape */
iRunLength = iNextByte(pFile);
if (iRunLength == EOF) {
return;
}
if (iRunLength == 0) { /* End of line escape */
bEOL = TRUE;
} else if (iRunLength == 1) { /* End of file escape */
return;
} else if (iRunLength == 2) { /* Delta escape */
DBG_MSG("RLE4: encountered delta escape");
return;
} else { /* Literal packet */
iHalfRun = (iRunLength + 1) / 2;
for (iRun = 0; iRun < iHalfRun; iRun++) {
iTmp = iNextByte(pFile);
if (iTmp == EOF) {
return;
}
/* Reverse the nibble order */
ucTmp = (iTmp & 0xf0) >> 4;
ucTmp |= (iTmp & 0x0f) << 4;
if (iX < iHalfWidth) {
iOffset = iY * iByteWidth + iX;
*(pucData + iOffset) = ucTmp;
}
iX++;
}
/* Padding if the number of bytes is odd */
if (odd(iHalfRun)) {
(void)tSkipBytes(pFile, 1);
}
}
}
DBG_DEC_C(iX != iHalfWidth, iX);
}
} /* end of vDecodeRle4 */
/*
* vDecodeRle8 - decode a RLE compressed 8 bits per pixel image
*/
static void
vDecodeRle8(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
{
int iX, iY, iRun, iRunLength, iOffset, iIndex, iByteWidth;
BOOL bEOL;
DBG_MSG("vDecodeRle8");
fail(pFile == NULL);
fail(pucData == NULL);
fail(pImg == NULL);
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
DBG_DEC(pImg->iWidth);
DBG_DEC(pImg->iHeight);
iByteWidth = iGetByteWidth(pImg);
for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
bEOL = FALSE;
iX = 0;
while (!bEOL) {
iRunLength = iNextByte(pFile);
if (iRunLength == EOF) {
return;
}
if (iRunLength != 0) {
/*
* Encoded packet:
* RunLength pixels, all the same value
*/
iIndex = iNextByte(pFile);
if (iIndex == EOF) {
return;
}
for (iRun = 0; iRun < iRunLength; iRun++) {
if (iX < pImg->iWidth) {
iOffset = iY * iByteWidth + iX;
*(pucData + iOffset) =
iReduceColor(
pImg->aucPalette[iIndex][0],
pImg->aucPalette[iIndex][1],
pImg->aucPalette[iIndex][2]);
}
iX++;
}
continue;
}
/* Literal or escape */
iRunLength = iNextByte(pFile);
if (iRunLength == EOF) {
return;
}
if (iRunLength == 0) { /* End of line escape */
bEOL = TRUE;
} else if (iRunLength == 1) { /* End of file escape */
return;
} else if (iRunLength == 2) { /* Delta escape */
DBG_MSG("RLE8: encountered delta escape");
return;
} else { /* Literal packet */
for (iRun = 0; iRun < iRunLength; iRun++) {
iIndex = iNextByte(pFile);
if (iIndex == EOF) {
return;
}
if (iX < pImg->iWidth) {
iOffset = iY * iByteWidth + iX;
*(pucData + iOffset) =
iReduceColor(
pImg->aucPalette[iIndex][0],
pImg->aucPalette[iIndex][1],
pImg->aucPalette[iIndex][2]);
}
iX++;
}
/* Padding if the number of bytes is odd */
if (odd(iRunLength)) {
(void)tSkipBytes(pFile, 1);
}
}
}
DBG_DEC_C(iX != pImg->iWidth, iX);
}
} /* end of vDecodeRle8 */
#if 0 /* defined(DEBUG) */
static void
vCopy2File(UCHAR *pucSprite, size_t tSpriteSize)
{
FILE *pOutFile;
int iIndex;
char szFilename[30];
sprintf(szFilename, "<Wimp$ScrapDir>.sprt%04d", ++iPicCounter);
pOutFile = fopen(szFilename, "wb");
if (pOutFile == NULL) {
return;
}
DBG_MSG(szFilename);
for (iIndex = 4; iIndex < (int)tSpriteSize; iIndex++) {
if (putc(pucSprite[iIndex], pOutFile) == EOF) {
break;
}
}
(void)fclose(pOutFile);
vSetFiletype(szFilename, FILETYPE_SPRITE);
} /* end of vCopy2File */
#endif /* DEBUG */
/*
* vDecodeDIB - decode a dib picture
*/
static void
vDecodeDIB(diagram_type *pDiag, FILE *pFile, const imagedata_type *pImg)
{
sprite_areainfo *pSprite;
UCHAR *pucPalette, *pucData;
size_t tSpriteSize;
int iHeaderSize;
/* Skip the bitmap info header */
iHeaderSize = (int)ulNextLong(pFile);
(void)tSkipBytes(pFile, iHeaderSize - 4);
/* Skip the colortable */
if (pImg->uiBitsPerComponent <= 8) {
(void)tSkipBytes(pFile,
pImg->iColorsUsed * ((iHeaderSize > 12) ? 4 : 3));
}
/* Create an blank sprite */
pSprite = pCreateBlankSprite(pImg, &tSpriteSize);
pucPalette = (UCHAR *)pSprite +
pSprite->firstoffset + sizeof(sprite_header);
/* Add the pixel information */
switch (pImg->uiBitsPerComponent) {
case 1:
fail(pImg->eCompression != compression_none);
pucData = pucPalette + 2 * 8;
vDecode1bpp(pFile, pucData, pImg);
break;
case 4:
fail(pImg->eCompression != compression_none &&
pImg->eCompression != compression_rle4);
pucData = pucPalette + 16 * 8;
if (pImg->eCompression == compression_rle4) {
vDecodeRle4(pFile, pucData, pImg);
} else {
vDecode4bpp(pFile, pucData, pImg);
}
break;
case 8:
fail(pImg->eCompression != compression_none &&
pImg->eCompression != compression_rle8);
pucData = pucPalette + 0 * 8;
if (pImg->eCompression == compression_rle8) {
vDecodeRle8(pFile, pucData, pImg);
} else {
vDecode8bpp(pFile, pucData, pImg);
}
break;
case 24:
fail(pImg->eCompression != compression_none);
pucData = pucPalette + 0 * 8;
vDecode24bpp(pFile, pucData, pImg);
break;
default:
DBG_DEC(pImg->uiBitsPerComponent);
break;
}
#if 0 /* defined(DEBUG) */
vCopy2File((UCHAR *)pSprite, tSpriteSize);
#endif /* DEBUG */
/* Add the sprite to the Draw file */
vImage2Diagram(pDiag, pImg,
(UCHAR *)pSprite + pSprite->firstoffset,
tSpriteSize - pSprite->firstoffset);
/* Clean up before you leave */
pSprite = xfree(pSprite);
} /* end of vDecodeDIB */
/*
* bTranslateDIB - translate a DIB picture
*
* This function translates a picture from dib to sprite
*
* return TRUE when sucessful, otherwise FALSE
*/
BOOL
bTranslateDIB(diagram_type *pDiag, FILE *pFile,
ULONG ulFileOffset, const imagedata_type *pImg)
{
/* Seek to start position of DIB data */
if (!bSetDataOffset(pFile, ulFileOffset)) {
return FALSE;
}
vDecodeDIB(pDiag, pFile, pImg);
return TRUE;
} /* end of bTranslateDIB */

75
src/doclist.c Normal file
View File

@@ -0,0 +1,75 @@
/*
* doclist.c
* Copyright (C) 2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Build, read and destroy list(s) of Word document information
*
* Note:
* There is no real list there is always one document per document
*/
#include "antiword.h"
#define HALF_INCH 36000L /* In millipoints */
/* Variables needed to write the Document Information List */
static document_block_type *pAnchor = NULL;
static document_block_type tInfo;
/*
* vDestroyDocumentInfoList - destroy the Document Information List
*/
void
vDestroyDocumentInfoList(void)
{
DBG_MSG("vDestroyDocumentInfoList");
pAnchor = NULL;
} /* end of vDestoryDocumentInfoList */
/*
* vCreateDocumentInfoList - create the Document Information List
*/
void
vCreateDocumentInfoList(const document_block_type *pDocument)
{
fail(pDocument == NULL);
fail(pAnchor != NULL);
tInfo = *pDocument;
pAnchor = &tInfo;
} /* end of vCreateDocumentInfoList */
/*
* lGetDefaultTabWidth - get the default tabwidth in millipoints
*/
long
lGetDefaultTabWidth(void)
{
long lDefaultTabWidth;
USHORT usTmp;
if (pAnchor == NULL) {
DBG_FIXME();
return HALF_INCH;
}
usTmp = pAnchor->usDefaultTabWidth;
lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
NO_DBG_DEC(lDefaultTabWidth);
return lDefaultTabWidth;
} /* end of lGetDefaultTabWidth */
/*
* ucGetDopHdrFtrSpecification - get the Heder/footer specification
*/
UCHAR
ucGetDopHdrFtrSpecification(void)
{
if (pAnchor == NULL) {
DBG_FIXME();
return 0x00;
}
return pAnchor->ucHdrFtrSpecification;
} /* end of ucGetDopHdrFtrSpecification */

1047
src/draw.c Normal file

File diff suppressed because it is too large Load Diff

46
src/draw.h Normal file
View File

@@ -0,0 +1,46 @@
/*
* draw.h
* Copyright (C) 2001 A.J. van Os; Released under GPL
*
* Description:
* Constants and macros to deal with the Draw format
*/
#if !defined(__draw_h)
#define __draw_h 1
#include "drawftypes.h"
typedef struct draw_jpegstrhdr_tag {
draw_tagtyp tag; /* 1 word */
draw_sizetyp size; /* 1 word */
draw_bboxtyp bbox; /* 4 words */
int width; /* 1 word */
int height; /* 1 word */
int xdpi; /* 1 word */
int ydpi; /* 1 word */
int trfm[6]; /* 6 words */
int len; /* 1 word */
} draw_jpegstrhdr;
typedef struct draw_jpegstr_tag {
draw_tagtyp tag; /* 1 word */
draw_sizetyp size; /* 1 word */
draw_bboxtyp bbox; /* 4 words */
int width; /* 1 word */
int height; /* 1 word */
int xdpi; /* 1 word */
int ydpi; /* 1 word */
int trfm[6]; /* 6 words */
int len; /* 1 word */
unsigned char *jpeg;
} draw_jpegstr;
typedef union draw_imageType_tag {
draw_spristr *sprite;
draw_jpegstr *jpeg;
char *bytep;
int *wordp;
} draw_imageType;
#endif /* !__draw_h */

422
src/drawfile.c Normal file
View File

@@ -0,0 +1,422 @@
/*
* drawfile.c
* Copyright (C) 2005 A.J. van Os; Released under GPL
*
* Description:
* Functions to process with the Draw diagram
*/
#include <string.h>
#include "DeskLib:Error.h"
#include "DeskLib:SWI.h"
#include "drawfile.h"
#include "antiword.h"
#define DRAWFILE_OBJECT_TOO_SMALL 200
#define DRAWFILE_NO_TEXT 201
#define DRAWFILE_BAD_CHARACTER 202
#define DRAWFILE_SMALL_MEMORY 203
#define DRAWFILE_PATH_WITHOUT_LINES 204
#define DRAWFILE_BAD_PATH_TYPE 205
#define DRAWFILE_PATH_WITHOUT_END 206
#define DRAWFILE_BAD_SPRITE_SIZE 207
#define DRAWFILE_BAD_JPEG_SIZE 208
#define DRAWFILE_TOO_SMALL 209
#define DRAWFILE_NOT_A_DRAWFILE 210
#define DRAWFILE_OBJECT_SIZE 211
#define DRAWFILE_MANY_FONTTABLES 212
#define DRAWFILE_TEXT_NO_FONT 213
#define DRAWFILE_OBJECT_UNEXPECTED 214
#define DRAWFILE_SIZE_ERROR 215
typedef struct drawfile_error_tag {
int iErrorNumber;
const char *szErrorText;
} drawfile_error_type;
static const drawfile_error_type atErrors[] = {
{ DRAWFILE_OBJECT_TOO_SMALL, "Object too small"},
{ DRAWFILE_NO_TEXT, "Text object without text"},
{ DRAWFILE_BAD_CHARACTER, "Bad character in string"},
{ DRAWFILE_SMALL_MEMORY, "Not enough memory reserved"},
{ DRAWFILE_PATH_WITHOUT_LINES, "This path has no lines"},
{ DRAWFILE_BAD_PATH_TYPE, "Bad path-type in path"},
{ DRAWFILE_PATH_WITHOUT_END, "No end of path seen"},
{ DRAWFILE_BAD_SPRITE_SIZE, "Bad sprite size"},
{ DRAWFILE_BAD_JPEG_SIZE, "Bad jpeg size"},
{ DRAWFILE_TOO_SMALL, "Too small to be a drawfile"},
{ DRAWFILE_NOT_A_DRAWFILE, "Not a drawfile"},
{ DRAWFILE_OBJECT_SIZE, "Object with incorrect size"},
{ DRAWFILE_MANY_FONTTABLES, "More than one font table"},
{ DRAWFILE_TEXT_NO_FONT, "Text, but no font table seen"},
{ DRAWFILE_OBJECT_UNEXPECTED, "Unexpected object type"},
{ DRAWFILE_SIZE_ERROR, "Sizes don't match"},
};
/*
* pFillError - error number to error struct
*/
static os_error *
pFillError(int iErrorNumber)
{
static os_error tError;
const drawfile_error_type *pTmp;
const char *szErrorText;
szErrorText = "Unknown error";
for (pTmp = atErrors; pTmp < atErrors + elementsof(atErrors); pTmp++) {
if (iErrorNumber == pTmp->iErrorNumber) {
szErrorText = pTmp->szErrorText;
break;
}
}
tError.errnum = iErrorNumber;
strncpy(tError.errmess, szErrorText, sizeof(tError.errmess) - 1);
tError.errmess[sizeof(tError.errmess) - 1] = '\0';
DBG_DEC(tError.errnum);
DBG_MSG(tError.errmess);
return &tError;
} /* end of pFillError */
/*
* Drawfile_BBox - Find the bounding box of a diagram
*/
os_error *
Drawfile_Bbox(drawfile_bbox_flags flags,
drawfile_diagram const *diagram,
int size,
os_trfm const *trfm,
wimp_box *bbox)
{
return SWI(5, 0, DrawFile_BBox | XOS_Bit,
flags, diagram, size, trfm, bbox);
} /* end of Drawfile_Bbox */
/*
* Drawfile_CreateDiagram - create an empty drawfile diagram
*/
os_error *
Drawfile_CreateDiagram(drawfile_info *pInfo, size_t tMemorySize,
const char *szCreator, wimp_box tBbox)
{
drawfile_diagram *pDiag;
if (tMemorySize < offsetof(drawfile_diagram, objects)) {
return pFillError(DRAWFILE_SMALL_MEMORY);
}
pDiag = (drawfile_diagram *)pInfo->data;
strncpy(pDiag->tag, "Draw", 4);
pDiag->major_version = 201;
pDiag->minor_version = 0;
strncpy(pDiag->source, szCreator, sizeof(pDiag->source));
pDiag->bbox = tBbox;
/* Memory in use */
pInfo->length = offsetof(drawfile_diagram, objects);
return NULL;
} /* end of Drawfile_CreateDiagram */
/*
* Drawfile_AppendObject - append an object to a diagram
*/
os_error *
Drawfile_AppendObject(drawfile_info *pInfo, size_t tMemorySize,
const drawfile_object *pObject, BOOL bRebind)
{
wimp_box *pMainBbox;
const wimp_box *pBbox;
byte *pAfter;
if (tMemorySize < pInfo->length + pObject->size) {
return pFillError(DRAWFILE_OBJECT_TOO_SMALL);
}
/* After the last object */
pAfter = (byte *)pInfo->data + pInfo->length;
/* Copy in the new data */
memcpy(pAfter, pObject, pObject->size);
/* Rebind if needed */
if (bRebind) {
pMainBbox = &((drawfile_diagram *)pInfo->data)->bbox;
switch (pObject->type) {
case drawfile_TYPE_FONT_TABLE:
pBbox = NULL;
break;
case drawfile_TYPE_TEXT:
pBbox = &pObject->data.text.bbox;
break;
case drawfile_TYPE_PATH:
pBbox = &pObject->data.path.bbox;
break;
case drawfile_TYPE_SPRITE:
pBbox = &pObject->data.sprite.bbox;
break;
case drawfile_TYPE_GROUP:
pBbox = &pObject->data.group.bbox;
break;
case drawfile_TYPE_TAGGED:
pBbox = &pObject->data.tagged.bbox;
break;
case drawfile_TYPE_TEXT_AREA:
pBbox = &pObject->data.text_area.bbox;
break;
case drawfile_TYPE_TEXT_COLUMN:
pBbox = NULL;
break;
case drawfile_TYPE_OPTIONS:
pBbox = &pObject->data.options.bbox;
break;
case drawfile_TYPE_TRFM_TEXT:
pBbox = &pObject->data.trfm_text.bbox;
break;
case drawfile_TYPE_TRFM_SPRITE:
pBbox = &pObject->data.trfm_sprite.bbox;
break;
case drawfile_TYPE_JPEG:
pBbox = &pObject->data.jpeg.bbox;
break;
default:
pBbox = NULL;
break;
}
if (pBbox != NULL) {
if (pBbox->min.x < pMainBbox->min.x) {
pMainBbox->min.x = pBbox->min.x;
}
if (pBbox->min.y < pMainBbox->min.y) {
pMainBbox->min.y = pBbox->min.y;
}
if (pBbox->max.x > pMainBbox->max.x) {
pMainBbox->max.x = pBbox->max.x;
}
if (pBbox->max.y > pMainBbox->max.y) {
pMainBbox->max.y = pBbox->max.y;
}
}
}
/* Memory in use */
pInfo->length += pObject->size;
return NULL;
} /* end of Drawfile_AppendObject */
/*
* Replaces the draw_render_diag function from RISC_OSLib
*/
os_error *
Drawfile_RenderDiagram(drawfile_info *pInfo, window_redrawblock *pRedraw,
double dScale)
{
int aiTransform[6];
fail(pInfo == NULL);
fail(pInfo->data == NULL);
fail(pRedraw == NULL);
fail(dScale < 0.01);
aiTransform[0] = (int)(dScale * 0x10000);
aiTransform[1] = 0;
aiTransform[2] = 0;
aiTransform[3] = (int)(dScale * 0x10000);
aiTransform[4] = (pRedraw->rect.min.x - pRedraw->scroll.x) * 256;
aiTransform[5] = (pRedraw->rect.max.y - pRedraw->scroll.y) * 256;
return SWI(6, 0, DrawFile_Render | XOS_Bit,
0, pInfo->data, pInfo->length, aiTransform, &pRedraw->rect, 0);
} /* end of Drawfile_RenderDiagram */
/*
* pVerifyText - verify a text object
*/
static os_error *
pVerifyText(const drawfile_text *pText)
{
const unsigned char *pucTmp;
if (pText->text[0] == '\0') {
return pFillError(DRAWFILE_NO_TEXT);
}
pucTmp = (const unsigned char *)pText->text;
while (*pucTmp != '\0') {
if (*pucTmp < 0x20 || *pucTmp == 0x7f) {
return pFillError(DRAWFILE_BAD_CHARACTER);
}
pucTmp++;
}
return NULL;
} /* end of pVerifyText */
/*
* pVerifyPath - verify a path object
*/
static os_error *
pVerifyPath(const drawfile_path *pPath, int iSize)
{
const int *piTmp;
int iElements;
BOOL bLine;
bLine = FALSE;
iElements = (iSize - offsetof(drawfile_path, path)) / 4;
for (piTmp = pPath->path; piTmp < pPath->path + iElements; piTmp++) {
switch(*piTmp) {
case drawfile_PATH_END_PATH:
if (bLine) {
return NULL;
}
return pFillError(DRAWFILE_PATH_WITHOUT_LINES);
case drawfile_PATH_LINE_TO:
bLine = TRUE;
piTmp += 2;
break;
case drawfile_PATH_MOVE_TO:
piTmp += 2;
break;
case drawfile_PATH_CLOSE_LINE:
bLine = TRUE;
break;
default:
return pFillError(DRAWFILE_BAD_PATH_TYPE);
}
}
return pFillError(DRAWFILE_PATH_WITHOUT_END);
} /* end of pVerifyPath */
/*
* pVerifySprite - verify a sprite object
*/
static os_error *
pVerifySprite(const drawfile_sprite *pSprite, int iSize)
{
iSize -= offsetof(drawfile_sprite, header);
if (iSize < pSprite->header.offset_next) {
DBG_DEC(iSize);
DBG_DEC(pSprite->header.offset_next);
return pFillError(DRAWFILE_BAD_SPRITE_SIZE);
}
return NULL;
} /* end of pVerifySprite */
/*
* pVerifyJpeg - verify a jpeg object
*/
static os_error *
pVerifyJpeg(const drawfile_jpeg *pJpeg, int iSize)
{
iSize -= offsetof(drawfile_jpeg, data);
if (iSize < pJpeg->len) {
DBG_DEC(iSize);
DBG_DEC(pJpeg->len);
return pFillError(DRAWFILE_BAD_JPEG_SIZE);
}
return NULL;
} /* end of pVerifyJpeg */
/*
* Drawfile_VerifyDiagram - Verify the diagram generated from the Word file
*
* returns NULL if the diagram is correct
*/
os_error *
Drawfile_VerifyDiagram(drawfile_info *pInfo)
{
drawfile_diagram *pDiag;
drawfile_object *pObj;
os_error *pError;
const char *pcTmp;
int iToGo, iFontTables;
BOOL bTypeFontTable;
TRACE_MSG("Drawfile_VerifyDiagram");
fail(pInfo == NULL);
if (pInfo->length < offsetof(drawfile_diagram, objects)) {
return pFillError(DRAWFILE_TOO_SMALL);
}
pDiag = (drawfile_diagram *)pInfo->data;
if (strncmp(pDiag->tag, "Draw", 4) != 0 ||
pDiag->major_version != 201 ||
pDiag->minor_version != 0) {
return pFillError(DRAWFILE_NOT_A_DRAWFILE);
}
iToGo = pInfo->length - offsetof(drawfile_diagram, objects);
pcTmp = (const char *)pInfo->data + offsetof(drawfile_diagram, objects);
iFontTables = 0;
bTypeFontTable = FALSE;
while (iToGo > 0) {
pObj = (drawfile_object *)pcTmp;
if (pObj->size < 0 || pObj->size % 4 != 0) {
return pFillError(DRAWFILE_OBJECT_SIZE);
}
switch (pObj->type) {
case drawfile_TYPE_FONT_TABLE:
if (bTypeFontTable) {
return pFillError(DRAWFILE_MANY_FONTTABLES);
}
bTypeFontTable = TRUE;
break;
case drawfile_TYPE_TEXT:
if (pObj->data.text.style.font_ref != 0 &&
!bTypeFontTable) {
return pFillError(DRAWFILE_TEXT_NO_FONT);
}
pError = pVerifyText(&pObj->data.text);
if (pError != NULL) {
return pError;
}
break;
case drawfile_TYPE_PATH:
pError = pVerifyPath(&pObj->data.path,
pObj->size - offsetof(drawfile_object, data));
if (pError != NULL) {
return pError;
}
break;
case drawfile_TYPE_SPRITE:
pError = pVerifySprite(&pObj->data.sprite,
pObj->size - offsetof(drawfile_object, data));
if (pError != NULL) {
return pError;
}
break;
case drawfile_TYPE_JPEG:
pError = pVerifyJpeg(&pObj->data.jpeg,
pObj->size - offsetof(drawfile_object, data));
if (pError != NULL) {
return pError;
}
break;
default:
DBG_DEC(pObj->type);
return pFillError(DRAWFILE_OBJECT_UNEXPECTED);
}
pcTmp += pObj->size;
iToGo -= pObj->size;
}
if (iToGo < 0) {
return pFillError(DRAWFILE_SIZE_ERROR);
}
return NULL;
} /* end of Drawfile_VerifyDiagram */
/*
* Drawfile_QueryBox - Find the bounding box of a diagram
*/
void
Drawfile_QueryBox(drawfile_info *pInfo, wimp_box *pRect, BOOL bScreenUnits)
{
fail(pInfo == NULL);
fail(pRect == NULL);
Error_CheckFatal(Drawfile_Bbox(0,
pInfo->data, pInfo->length, NULL, pRect));
if (bScreenUnits) {
pRect->min.x = Drawfile_DrawToScreen(pRect->min.x);
pRect->min.y = Drawfile_DrawToScreen(pRect->min.y);
pRect->max.x = Drawfile_DrawToScreen(pRect->max.x);
pRect->max.y = Drawfile_DrawToScreen(pRect->max.y);
}
} /* end of Drawfile_QueryBox */

433
src/drawfile.h Normal file
View File

@@ -0,0 +1,433 @@
/*
* drawfile.h
* Copyright (C) 2005 A.J. van Os; Released under GNU GPL
*
* Description:
* Include file to deal with drawfiles
*
* Based on:
* C header file for DrawFile
* written by DefMod (May 4 2004) on Tue May 4 13:34:17 2004
* Jonathan Coxhead, jonathan@doves.demon.co.uk, 21 Aug 1995
* OSLib---efficient, type-safe, transparent, extensible,
* register-safe A P I coverage of RISC O S
* Copyright (C) 1994 Jonathan Coxhead
*
* All credit should go to him, but all the bugs are mine
*/
#if !defined(__drawfile_h)
#define __drawfile_h
#include "DeskLib:Sprite.h"
#include "DeskLib:Wimp.h"
#if !defined(BOOL)
#define BOOL int
#define TRUE 1
#define FALSE 0
#endif /* !BOOL */
/*********************
* Conversion macros *
*********************/
#define Drawfile_DrawToScreen(i) ((i) / 256)
#define Drawfile_ScreenToDraw(i) ((i) * 256)
/**********************************
* SWI names and SWI reason codes *
**********************************/
#define DrawFile_Render 0x45540
#define DrawFile_BBox 0x45541
#define DrawFile_DeclareFonts 0x45542
/********************
* Type definitions *
********************/
typedef unsigned int bits;
typedef unsigned char byte;
typedef byte drawfile_fontref;
typedef byte drawfile_path_style_flags;
typedef bits drawfile_text_flags;
typedef bits drawfile_render_flags;
typedef bits drawfile_declare_fonts_flags;
typedef bits drawfile_paper_options;
typedef bits drawfile_entry_mode;
typedef enum {
drawfile_TYPE_FONT_TABLE = 0,
drawfile_TYPE_TEXT = 1,
drawfile_TYPE_PATH = 2,
drawfile_TYPE_SPRITE = 5,
drawfile_TYPE_GROUP = 6,
drawfile_TYPE_TAGGED = 7,
drawfile_TYPE_TEXT_AREA = 9,
drawfile_TYPE_TEXT_COLUMN = 10,
drawfile_TYPE_OPTIONS = 11,
drawfile_TYPE_TRFM_TEXT = 12,
drawfile_TYPE_TRFM_SPRITE = 13,
drawfile_TYPE_JPEG = 16
} drawfile_type;
typedef enum {
drawfile_PATH_END_PATH = 0,
drawfile_PATH_CONTINUATION = 1,
drawfile_PATH_MOVE_TO = 2,
drawfile_PATH_SPECIAL_MOVE_TO = 3,
drawfile_PATH_CLOSE_GAP = 4,
drawfile_PATH_CLOSE_LINE = 5,
drawfile_PATH_BEZIER_TO = 6,
drawfile_PATH_GAP_TO = 7,
drawfile_PATH_LINE_TO = 8
} drawfile_path_type;
typedef struct {
int start;
int element_count;
int elements [6];
} draw_dash_pattern;
typedef struct {
int entries [3] [2];
} os_trfm;
typedef struct {
void *data;
size_t length;
} drawfile_info;
typedef struct {
drawfile_fontref font_ref;
char font_name [1];
} drawfile_font_def;
typedef struct {
drawfile_fontref font_ref;
byte reserved [3];
} drawfile_text_style;
typedef struct {
drawfile_path_style_flags flags;
byte reserved;
byte cap_width;
byte cap_length;
} drawfile_path_style;
typedef struct {
drawfile_font_def font_def[1];
} drawfile_font_table;
typedef struct {
wimp_box bbox;
palette_entry fill;
palette_entry bg_hint;
drawfile_text_style style;
int xsize;
int ysize;
wimp_coord base;
char text [1];
} drawfile_text;
typedef struct {
wimp_box bbox;
palette_entry fill;
palette_entry outline;
int width;
drawfile_path_style style;
int path [1];
} drawfile_path;
typedef struct {
wimp_box bbox;
palette_entry fill;
palette_entry outline;
int width;
drawfile_path_style style;
draw_dash_pattern pattern;
int path [1];
} drawfile_path_with_pattern;
typedef struct {
wimp_box bbox;
sprite_header header;
byte data [1];
} drawfile_sprite;
typedef struct {
wimp_box bbox;
char name [12];
int objects [1];
} drawfile_group;
typedef struct {
wimp_box bbox;
drawfile_type tag;
int object [1];
} drawfile_tagged;
typedef struct {
wimp_box box;
} drawfile_text_column;
typedef struct {
struct {
drawfile_type type;
int size;
drawfile_text_column data;
} columns [1];
} drawfile_text_column_list;
typedef struct {
drawfile_type type;
int reserved [2];
palette_entry fill;
palette_entry bg_hint;
char text [1];
} drawfile_area_text;
typedef struct {
wimp_box bbox;
drawfile_text_column_list header;
drawfile_area_text area_text;
} drawfile_text_area;
typedef struct {
wimp_box bbox;
int paper_size;
drawfile_paper_options paper_options;
double grid_spacing;
int grid_division;
BOOL isometric;
BOOL auto_adjust;
BOOL show;
BOOL lock;
BOOL cm;
int zoom_mul;
int zoom_div;
BOOL zoom_lock;
BOOL toolbox;
drawfile_entry_mode entry_mode;
int undo_size;
} drawfile_options;
typedef struct {
wimp_box bbox;
os_trfm trfm;
drawfile_text_flags flags;
palette_entry fill;
palette_entry bg_hint;
drawfile_text_style style;
int xsize;
int ysize;
wimp_coord base;
char text [1];
} drawfile_trfm_text;
typedef struct {
wimp_box bbox;
os_trfm trfm;
sprite_header header;
byte data [1];
} drawfile_trfm_sprite;
typedef struct {
wimp_box bbox;
int width;
int height;
int xdpi;
int ydpi;
os_trfm trfm;
int len;
byte data [1];
} drawfile_jpeg;
/* ------------------------------------------------------------------------
* Type: drawfile_object
*
* Description: This type is used to declare pointers rather than objects
*/
typedef struct {
drawfile_type type;
int size;
union {
drawfile_font_table font_table;
drawfile_text text;
drawfile_path path;
drawfile_path_with_pattern path_with_pattern;
drawfile_sprite sprite;
drawfile_group group;
drawfile_tagged tagged;
drawfile_text_column text_column;
drawfile_text_area text_area;
drawfile_options options;
drawfile_trfm_text trfm_text;
drawfile_trfm_sprite trfm_sprite;
drawfile_jpeg jpeg;
} data;
} drawfile_object;
typedef struct {
char tag [4];
int major_version;
int minor_version;
char source [12];
wimp_box bbox;
drawfile_object objects [1];
} drawfile_diagram;
typedef bits drawfile_bbox_flags;
typedef struct {
drawfile_object *object;
drawfile_diagram *diagram;
drawfile_object *font_table;
drawfile_declare_fonts_flags flags;
os_error *error;
} drawfile_declare_fonts_state;
/************************
* Constant definitions *
************************/
#define error_DRAW_FILE_NOT_DRAW 0x20C00u
#define error_DRAW_FILE_VERSION 0x20C01u
#define error_DRAW_FILE_FONT_TAB 0x20C02u
#define error_DRAW_FILE_BAD_FONT_NO 0x20C03u
#define error_DRAW_FILE_BAD_MODE 0x20C04u
#define error_DRAW_FILE_BAD_FILE 0x20C05u
#define error_DRAW_FILE_BAD_GROUP 0x20C06u
#define error_DRAW_FILE_BAD_TAG 0x20C07u
#define error_DRAW_FILE_SYNTAX 0x20C08u
#define error_DRAW_FILE_FONT_NO 0x20C09u
#define error_DRAW_FILE_AREA_VER 0x20C0Au
#define error_DRAW_FILE_NO_AREA_VER 0x20C0Bu
#define drawfile_PATH_MITRED ((drawfile_path_style_flags) 0x0u)
#define drawfile_PATH_ROUND ((drawfile_path_style_flags) 0x1u)
#define drawfile_PATH_BEVELLED ((drawfile_path_style_flags) 0x2u)
#define drawfile_PATH_BUTT ((drawfile_path_style_flags) 0x0u)
#define drawfile_PATH_SQUARE ((drawfile_path_style_flags) 0x2u)
#define drawfile_PATH_TRIANGLE ((drawfile_path_style_flags) 0x3u)
#define drawfile_PATH_JOIN_SHIFT 0
#define drawfile_PATH_JOIN ((drawfile_path_style_flags) 0x3u)
#define drawfile_PATH_END_SHIFT 2
#define drawfile_PATH_END ((drawfile_path_style_flags) 0xCu)
#define drawfile_PATH_START_SHIFT 4
#define drawfile_PATH_START ((drawfile_path_style_flags) 0x30u)
#define drawfile_PATH_WINDING_EVEN_ODD ((drawfile_path_style_flags) 0x40u)
#define drawfile_PATH_DASHED ((drawfile_path_style_flags) 0x80u)
#define drawfile_PATH_CAP_WIDTH_SHIFT 16
#define drawfile_PATH_CAP_WIDTH ((drawfile_path_style_flags) 0xFF0000u)
#define drawfile_PATH_CAP_LENGTH_SHIFT 24
#define drawfile_PATH_CAP_LENGTH ((drawfile_path_style_flags) 0xFF000000u)
#define drawfile_TEXT_KERN ((drawfile_text_flags) 0x1u)
#define drawfile_TEXT_RIGHT_TO_LEFT ((drawfile_text_flags) 0x2u)
#define drawfile_TEXT_UNDERLINE ((drawfile_text_flags) 0x4u)
#define drawfile_RENDER_BBOXES ((drawfile_render_flags) 0x1u)
#define drawfile_RENDER_SUPPRESS ((drawfile_render_flags) 0x2u)
#define drawfile_RENDER_GIVEN_FLATNESS ((drawfile_render_flags) 0x4u)
#define drawfile_RENDER_GIVEN_COLOUR_MAPPING ((drawfile_render_flags) 0x8u)
#define drawfile_NO_DOWNLOAD ((drawfile_declare_fonts_flags) 0x1u)
#define drawfile_PAPER_SHOW ((drawfile_paper_options) 0x1u)
#define drawfile_PAPER_LANDSCAPE ((drawfile_paper_options) 0x10u)
#define drawfile_PAPER_DEFAULT ((drawfile_paper_options) 0x100u)
#define drawfile_ENTRY_MODE_LINE ((drawfile_entry_mode) 0x1u)
#define drawfile_ENTRY_MODE_CLOSED_LINE ((drawfile_entry_mode) 0x2u)
#define drawfile_ENTRY_MODE_CURVE ((drawfile_entry_mode) 0x4u)
#define drawfile_ENTRY_MODE_CLOSED_CURVE ((drawfile_entry_mode) 0x8u)
#define drawfile_ENTRY_MODE_RECTANGLE ((drawfile_entry_mode) 0x10u)
#define drawfile_ENTRY_MODE_ELLIPSE ((drawfile_entry_mode) 0x20u)
#define drawfile_ENTRY_MODE_TEXT_LINE ((drawfile_entry_mode) 0x40u)
#define drawfile_ENTRY_MODE_SELECT ((drawfile_entry_mode) 0x80u)
/*************************
* Function declarations *
*************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/* ------------------------------------------------------------------------
* Function: drawfile_render()
*
* Description: Calls SWI 0x45540
*
* Input: flags - value of R0 on entry
* diagram - value of R1 on entry
* size - value of R2 on entry
* trfm - value of R3 on entry
* clip - value of R4 on entry
* flatness - value of R5 on entry
*/
extern os_error *Drawfile_Render (drawfile_render_flags flags,
drawfile_diagram const *diagram,
int size,
os_trfm const *trfm,
wimp_box const *clip,
int flatness);
/* ------------------------------------------------------------------------
* Function: drawfile_bbox()
*
* Description: Calls SWI 0x45541
*
* Input: flags - value of R0 on entry
* diagram - value of R1 on entry
* size - value of R2 on entry
* trfm - value of R3 on entry
* bbox - value of R4 on entry
*/
extern os_error *Drawfile_Bbox (drawfile_bbox_flags flags,
drawfile_diagram const *diagram,
int size,
os_trfm const *trfm,
wimp_box *bbox);
/* ------------------------------------------------------------------------
* Function: Drawfile_DeclareFonts()
*
* Description: Calls SWI 0x45542
*
* Input: flags - value of R0 on entry
* diagram - value of R1 on entry
* size - value of R2 on entry
*/
extern os_error *Drawfile_DeclareFonts (drawfile_declare_fonts_flags flags,
drawfile_diagram const *diagram,
int size);
/* ------------------------------------------------------------------------
* Function: Drawfile_CreateDiagram()
*
*/
extern os_error * Drawfile_CreateDiagram(drawfile_info *info, size_t memory,
const char *creator, wimp_box box);
extern os_error *Drawfile_AppendObject(drawfile_info *info, size_t memory,
const drawfile_object *object, BOOL rebind);
extern os_error *Drawfile_RenderDiagram(drawfile_info *info,
window_redrawblock *redraw, double scale);
extern os_error *Drawfile_VerifyDiagram(drawfile_info *info);
extern void Drawfile_QueryBox(drawfile_info *info,
wimp_box *rect, BOOL screenUnits);
#if defined(__cplusplus)
}
#endif /* __cplusplus */
#endif /* __drawfile.h */

26
src/fail.c Normal file
View File

@@ -0,0 +1,26 @@
/*
* fail.c
* Copyright (C) 1998 A.J. van Os
*
* Description:
* An alternative form of assert()
*/
#include <stdlib.h>
#include "antiword.h"
#if !defined(NDEBUG)
void
__fail(char *szExpression, char *szFilename, int iLineNumber)
{
if (szExpression == NULL || szFilename == NULL) {
werr(1, "Internal error: no expression");
}
#if defined(DEBUG)
fprintf(stderr, "%s[%3d]: Internal error in '%s'\n",
szFilename, iLineNumber, szExpression);
#endif /* DEBUG */
werr(1, "Internal error in '%s' in file %s at line %d",
szExpression, szFilename, iLineNumber);
} /* end of __fail */
#endif /* !NDEBUG */

22
src/fail.h Normal file
View File

@@ -0,0 +1,22 @@
/*
* fail.h
* Copyright (C) 1998-2000 A.J. van Os; Released under GPL
*
* Description:
* Support for an alternative form of assert()
*/
#if !defined(__fail_h)
#define __fail_h 1
#undef fail
#if defined(NDEBUG)
#define fail(e) ((void)0)
#else
#define fail(e) ((e) ? __fail(#e, __FILE__, __LINE__) : (void)0)
#endif /* NDEBUG */
extern void __fail(char *, char *, int);
#endif /* __fail_h */

154
src/finddata.c Normal file
View File

@@ -0,0 +1,154 @@
/*
* finddata.c
* Copyright (C) 2000-2002 A.J. van Os; Released under GPL
*
* Description:
* Find the blocks that contain the data of MS Word files
*/
#include <stdio.h>
#include <stdlib.h>
#include "antiword.h"
/*
* bAddDataBlocks - Add the blocks to the data block list
*
* Returns TRUE when successful, otherwise FALSE
*/
BOOL
bAddDataBlocks(ULONG ulDataPosFirst, ULONG ulTotalLength,
ULONG ulStartBlock, const ULONG *aulBBD, size_t tBBDLen)
{
data_block_type tDataBlock;
ULONG ulDataPos, ulOffset, ulIndex;
long lToGo;
BOOL bSuccess;
fail(ulTotalLength > (ULONG)LONG_MAX);
fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
fail(aulBBD == NULL);
NO_DBG_HEX(ulDataPosFirst);
NO_DBG_DEC(ulTotalLength);
lToGo = (long)ulTotalLength;
ulDataPos = ulDataPosFirst;
ulOffset = ulDataPosFirst;
for (ulIndex = ulStartBlock;
ulIndex != END_OF_CHAIN && lToGo > 0;
ulIndex = aulBBD[ulIndex]) {
if (ulIndex == UNUSED_BLOCK || ulIndex >= (ULONG)tBBDLen) {
DBG_DEC(ulIndex);
DBG_DEC(tBBDLen);
return FALSE;
}
if (ulOffset >= BIG_BLOCK_SIZE) {
ulOffset -= BIG_BLOCK_SIZE;
continue;
}
tDataBlock.ulFileOffset =
(ulIndex + 1) * BIG_BLOCK_SIZE + ulOffset;
tDataBlock.ulDataPos = ulDataPos;
tDataBlock.ulLength = min(BIG_BLOCK_SIZE - ulOffset,
(ULONG)lToGo);
fail(tDataBlock.ulLength > BIG_BLOCK_SIZE);
ulOffset = 0;
if (!bAdd2DataBlockList(&tDataBlock)) {
DBG_HEX(tDataBlock.ulFileOffset);
DBG_HEX(tDataBlock.ulDataPos);
DBG_DEC(tDataBlock.ulLength);
return FALSE;
}
ulDataPos += tDataBlock.ulLength;
lToGo -= (long)tDataBlock.ulLength;
}
bSuccess = lToGo == 0 ||
(ulTotalLength == (ULONG)LONG_MAX && ulIndex == END_OF_CHAIN);
DBG_DEC_C(!bSuccess, lToGo);
DBG_DEC_C(!bSuccess, ulTotalLength);
DBG_DEC_C(!bSuccess, ulIndex);
return bSuccess;
} /* end of bAddDataBlocks */
/*
* bGet6DocumentData - make a list of the data blocks of Word 6/7 files
*
* Code for "fast saved" files.
*
* Returns TRUE when successful, otherwise FALSE
*/
BOOL
bGet6DocumentData(FILE *pFile, ULONG ulStartBlock,
const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
{
UCHAR *aucBuffer;
ULONG ulBeginTextInfo, ulOffset, ulTotLength;
size_t tTextInfoLen;
int iIndex, iOff, iType, iLen, iPieces;
DBG_MSG("bGet6DocumentData");
fail(pFile == NULL);
fail(aulBBD == NULL);
fail(aucHeader == NULL);
ulBeginTextInfo = ulGetLong(0x160, aucHeader);
DBG_HEX(ulBeginTextInfo);
tTextInfoLen = (size_t)ulGetLong(0x164, aucHeader);
DBG_DEC(tTextInfoLen);
aucBuffer = xmalloc(tTextInfoLen);
if (!bReadBuffer(pFile, ulStartBlock,
aulBBD, tBBDLen, BIG_BLOCK_SIZE,
aucBuffer, ulBeginTextInfo, tTextInfoLen)) {
aucBuffer = xfree(aucBuffer);
return FALSE;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tTextInfoLen);
iOff = 0;
while (iOff < (int)tTextInfoLen) {
iType = (int)ucGetByte(iOff, aucBuffer);
iOff++;
if (iType == 0) {
iOff++;
continue;
}
iLen = (int)usGetWord(iOff, aucBuffer);
iOff += 2;
if (iType == 1) {
iOff += iLen;
continue;
}
if (iType != 2) {
werr(0, "Unknown type of 'fastsaved' format");
aucBuffer = xfree(aucBuffer);
return FALSE;
}
/* Type 2 */
NO_DBG_DEC(iLen);
iOff += 2;
iPieces = (iLen - 4) / 12;
DBG_DEC(iPieces);
for (iIndex = 0; iIndex < iPieces; iIndex++) {
ulOffset = ulGetLong(
iOff + (iPieces + 1) * 4 + iIndex * 8 + 2,
aucBuffer);
ulTotLength = ulGetLong(iOff + (iIndex + 1) * 4,
aucBuffer) -
ulGetLong(iOff + iIndex * 4,
aucBuffer);
if (!bAddDataBlocks(ulOffset, ulTotLength,
ulStartBlock,
aulBBD, tBBDLen)) {
aucBuffer = xfree(aucBuffer);
return FALSE;
}
}
break;
}
aucBuffer = xfree(aucBuffer);
return TRUE;
} /* end of bGet6DocumentData */

289
src/findtext.c Normal file
View File

@@ -0,0 +1,289 @@
/*
* findtext.c
* Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Find the blocks that contain the text of MS Word files
*/
#include <stdio.h>
#include <stdlib.h>
#include "antiword.h"
/*
* bAddTextBlocks - Add the blocks to the text block list
*
* Returns TRUE when successful, FALSE if not
*/
BOOL
bAddTextBlocks(ULONG ulCharPosFirst, ULONG ulTotalLength,
BOOL bUsesUnicode, USHORT usPropMod,
ULONG ulStartBlock, const ULONG *aulBBD, size_t tBBDLen)
{
text_block_type tTextBlock;
ULONG ulCharPos, ulOffset, ulIndex;
long lToGo;
fail(ulTotalLength > (ULONG)LONG_MAX / 2);
fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
fail(aulBBD == NULL);
NO_DBG_HEX(ulCharPosFirst);
NO_DBG_DEC(ulTotalLength);
if (bUsesUnicode) {
/* One character equals two bytes */
NO_DBG_MSG("Uses Unicode");
lToGo = (long)ulTotalLength * 2;
} else {
/* One character equals one byte */
NO_DBG_MSG("Uses ASCII");
lToGo = (long)ulTotalLength;
}
ulCharPos = ulCharPosFirst;
ulOffset = ulCharPosFirst;
for (ulIndex = ulStartBlock;
ulIndex != END_OF_CHAIN && lToGo > 0;
ulIndex = aulBBD[ulIndex]) {
if (ulIndex >= (ULONG)tBBDLen) {
DBG_DEC(ulIndex);
DBG_DEC(tBBDLen);
werr(1, "The Big Block Depot is damaged");
}
if (ulOffset >= BIG_BLOCK_SIZE) {
ulOffset -= BIG_BLOCK_SIZE;
continue;
}
tTextBlock.ulFileOffset =
(ulIndex + 1) * BIG_BLOCK_SIZE + ulOffset;
tTextBlock.ulCharPos = ulCharPos;
tTextBlock.ulLength = min(BIG_BLOCK_SIZE - ulOffset,
(ULONG)lToGo);
tTextBlock.bUsesUnicode = bUsesUnicode;
tTextBlock.usPropMod = usPropMod;
ulOffset = 0;
if (!bAdd2TextBlockList(&tTextBlock)) {
DBG_HEX(tTextBlock.ulFileOffset);
DBG_HEX(tTextBlock.ulCharPos);
DBG_DEC(tTextBlock.ulLength);
DBG_DEC(tTextBlock.bUsesUnicode);
DBG_DEC(tTextBlock.usPropMod);
return FALSE;
}
ulCharPos += tTextBlock.ulLength;
lToGo -= (long)tTextBlock.ulLength;
}
DBG_DEC_C(lToGo != 0, lToGo);
return lToGo == 0;
} /* end of bAddTextBlocks */
/*
* bGet6DocumentText - make a list of the text blocks of Word 6/7 files
*
* Code for "fast saved" files.
*
* Returns TRUE when successful, FALSE if not
*/
BOOL
bGet6DocumentText(FILE *pFile, BOOL bUsesUnicode, ULONG ulStartBlock,
const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
{
UCHAR *aucBuffer;
ULONG ulBeginTextInfo, ulTextOffset, ulTotLength;
size_t tTextInfoLen;
int iIndex, iType, iOff, iLen, iPieces;
USHORT usPropMod;
DBG_MSG("bGet6DocumentText");
fail(pFile == NULL);
fail(aulBBD == NULL);
fail(aucHeader == NULL);
ulBeginTextInfo = ulGetLong(0x160, aucHeader); /* fcClx */
DBG_HEX(ulBeginTextInfo);
tTextInfoLen = (size_t)ulGetLong(0x164, aucHeader); /* lcbClx */
DBG_DEC(tTextInfoLen);
aucBuffer = xmalloc(tTextInfoLen);
if (!bReadBuffer(pFile, ulStartBlock,
aulBBD, tBBDLen, BIG_BLOCK_SIZE,
aucBuffer, ulBeginTextInfo, tTextInfoLen)) {
aucBuffer = xfree(aucBuffer);
return FALSE;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tTextInfoLen);
iOff = 0;
while ((size_t)iOff < tTextInfoLen) {
iType = (int)ucGetByte(iOff, aucBuffer);
iOff++;
if (iType == 0) {
DBG_FIXME();
iOff++;
continue;
}
if (iType == 1) {
iLen = (int)usGetWord(iOff, aucBuffer);
vAdd2PropModList(aucBuffer + iOff);
iOff += iLen + 2;
continue;
}
if (iType != 2) {
werr(0, "Unknown type of 'fastsaved' format");
aucBuffer = xfree(aucBuffer);
return FALSE;
}
/* Type 2 */
iLen = (int)usGetWord(iOff, aucBuffer);
NO_DBG_DEC(iLen);
iOff += 4;
iPieces = (iLen - 4) / 12;
DBG_DEC(iPieces);
for (iIndex = 0; iIndex < iPieces; iIndex++) {
ulTextOffset = ulGetLong(
iOff + (iPieces + 1) * 4 + iIndex * 8 + 2,
aucBuffer);
usPropMod = usGetWord(
iOff + (iPieces + 1) * 4 + iIndex * 8 + 6,
aucBuffer);
ulTotLength = ulGetLong(iOff + (iIndex + 1) * 4,
aucBuffer) -
ulGetLong(iOff + iIndex * 4,
aucBuffer);
NO_DBG_HEX_C(usPropMod != 0, usPropMod);
if (!bAddTextBlocks(ulTextOffset, ulTotLength,
bUsesUnicode, usPropMod,
ulStartBlock,
aulBBD, tBBDLen)) {
aucBuffer = xfree(aucBuffer);
return FALSE;
}
}
break;
}
aucBuffer = xfree(aucBuffer);
return TRUE;
} /* end of bGet6DocumentText */
/*
* bGet8DocumentText - make a list of the text blocks of Word 8/97 files
*
* Returns TRUE when successful, FALSE if not
*/
BOOL
bGet8DocumentText(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader)
{
const ULONG *aulBlockDepot;
UCHAR *aucBuffer;
ULONG ulTextOffset, ulBeginTextInfo;
ULONG ulTotLength, ulLen;
long lIndex, lPieces, lOff;
size_t tTextInfoLen, tBlockDepotLen, tBlockSize;
int iType, iLen;
BOOL bUsesUnicode;
USHORT usPropMod;
DBG_MSG("bGet8DocumentText");
fail(pFile == NULL || pPPS == NULL);
fail(aulBBD == NULL || aulSBD == NULL);
fail(aucHeader == NULL);
ulBeginTextInfo = ulGetLong(0x1a2, aucHeader); /* fcClx */
DBG_HEX(ulBeginTextInfo);
tTextInfoLen = (size_t)ulGetLong(0x1a6, aucHeader); /* lcbClx */
DBG_DEC(tTextInfoLen);
DBG_DEC(pPPS->tTable.ulSB);
DBG_HEX(pPPS->tTable.ulSize);
if (pPPS->tTable.ulSize == 0) {
return FALSE;
}
if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
/* Use the Small Block Depot */
aulBlockDepot = aulSBD;
tBlockDepotLen = tSBDLen;
tBlockSize = SMALL_BLOCK_SIZE;
} else {
/* Use the Big Block Depot */
aulBlockDepot = aulBBD;
tBlockDepotLen = tBBDLen;
tBlockSize = BIG_BLOCK_SIZE;
}
aucBuffer = xmalloc(tTextInfoLen);
if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
aulBlockDepot, tBlockDepotLen, tBlockSize,
aucBuffer, ulBeginTextInfo, tTextInfoLen)) {
aucBuffer = xfree(aucBuffer);
return FALSE;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tTextInfoLen);
lOff = 0;
while (lOff < (long)tTextInfoLen) {
iType = (int)ucGetByte(lOff, aucBuffer);
lOff++;
if (iType == 0) {
DBG_FIXME();
lOff++;
continue;
}
if (iType == 1) {
iLen = (int)usGetWord(lOff, aucBuffer);
vAdd2PropModList(aucBuffer + lOff);
lOff += (long)iLen + 2;
continue;
}
if (iType != 2) {
werr(0, "Unknown type of 'fastsaved' format");
aucBuffer = xfree(aucBuffer);
return FALSE;
}
/* Type 2 */
ulLen = ulGetLong(lOff, aucBuffer);
if (ulLen < 4) {
DBG_DEC(ulLen);
return FALSE;
}
lOff += 4;
lPieces = (long)((ulLen - 4) / 12);
DBG_DEC(lPieces);
for (lIndex = 0; lIndex < lPieces; lIndex++) {
ulTextOffset = ulGetLong(
lOff + (lPieces + 1) * 4 + lIndex * 8 + 2,
aucBuffer);
usPropMod = usGetWord(
lOff + (lPieces + 1) * 4 + lIndex * 8 + 6,
aucBuffer);
ulTotLength = ulGetLong(lOff + (lIndex + 1) * 4,
aucBuffer) -
ulGetLong(lOff + lIndex * 4,
aucBuffer);
if ((ulTextOffset & BIT(30)) == 0) {
bUsesUnicode = TRUE;
} else {
bUsesUnicode = FALSE;
ulTextOffset &= ~BIT(30);
ulTextOffset /= 2;
}
NO_DBG_HEX_C(usPropMod != 0, usPropMod);
if (!bAddTextBlocks(ulTextOffset, ulTotLength,
bUsesUnicode, usPropMod,
pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen)) {
aucBuffer = xfree(aucBuffer);
return FALSE;
}
}
break;
}
aucBuffer = xfree(aucBuffer);
return TRUE;
} /* end of bGet8DocumentText */

167
src/fmt_text.c Normal file
View File

@@ -0,0 +1,167 @@
/*
* fmt_text.c
* Copyright (C) 2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Functions to deal with the Formatted Text format
*
* Based on patches send by: Ofir Reichenberg <ofir@qlusters.com>
*
* The credit should go to him, but all the bugs are mine.
*/
#include <string.h>
#include "antiword.h"
/* The character set */
static encoding_type eEncoding = encoding_neutral;
/* Current vertical position information */
static long lYtopCurr = 0;
/* Local representation of the non-breaking space */
static UCHAR ucNbsp = 0;
/*
* vPrologueFMT - set options and perform the Formatted Text initialization
*/
void
vPrologueFMT(diagram_type *pDiag, const options_type *pOptions)
{
fail(pDiag == NULL);
fail(pOptions == NULL);
eEncoding = pOptions->eEncoding;
pDiag->lXleft = 0;
pDiag->lYtop = 0;
lYtopCurr = 0;
} /* end of vPrologueFMT */
/*
* vPrintFMT - print a Formatted Text string
*/
static void
vPrintFMT(FILE *pFile,
const char *szString, size_t tStringLength, USHORT usFontstyle)
{
const UCHAR *pucByte, *pucStart, *pucLast, *pucNonSpace;
fail(szString == NULL);
if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
return;
}
if (eEncoding == encoding_utf_8) {
fprintf(pFile, "%.*s", (int)tStringLength, szString);
return;
}
if (ucNbsp == 0) {
ucNbsp = ucGetNbspCharacter();
DBG_HEX_C(ucNbsp != 0xa0, ucNbsp);
}
pucStart = (UCHAR *)szString;
pucLast = pucStart + tStringLength - 1;
pucNonSpace = pucLast;
while ((*pucNonSpace == (UCHAR)' ' || *pucNonSpace == ucNbsp) &&
pucNonSpace > pucStart) {
pucNonSpace--;
}
/* 1: The spaces at the start */
pucByte = pucStart;
while ((*pucByte == (UCHAR)' ' || *pucByte == ucNbsp) &&
pucByte <= pucLast) {
(void)putc(' ', pFile);
pucByte++;
}
if (pucByte > pucLast) {
/* There is no text, just spaces */
return;
}
/* 2: Start the *bold*, /italic/ and _underline_ */
if (bIsBold(usFontstyle)) {
(void)putc('*', pFile);
}
if (bIsItalic(usFontstyle)) {
(void)putc('/', pFile);
}
if (bIsUnderline(usFontstyle)) {
(void)putc('_', pFile);
}
/* 3: The text itself */
while (pucByte <= pucNonSpace) {
if (*pucByte == ucNbsp) {
(void)putc(' ', pFile);
} else {
(void)putc((char)*pucByte, pFile);
}
pucByte++;
}
/* 4: End the *bold*, /italic/ and _underline_ */
if (bIsUnderline(usFontstyle)) {
(void)putc('_', pFile);
}
if (bIsItalic(usFontstyle)) {
(void)putc('/', pFile);
}
if (bIsBold(usFontstyle)) {
(void)putc('*', pFile);
}
/* 5: The spaces at the end */
while (pucByte <= pucLast) {
(void)putc(' ', pFile);
pucByte++;
}
} /* end of vPrintFMT */
/*
* vMoveTo - move to the given X,Y coordinates
*
* Move the current position of the given diagram to its X,Y coordinates,
* start on a new page if needed
*/
static void
vMoveTo(diagram_type *pDiag)
{
int iCount, iNbr;
fail(pDiag == NULL);
fail(pDiag->pOutFile == NULL);
if (pDiag->lYtop != lYtopCurr) {
iNbr = iDrawUnits2Char(pDiag->lXleft);
for (iCount = 0; iCount < iNbr; iCount++) {
(void)putc(FILLER_CHAR, pDiag->pOutFile);
}
lYtopCurr = pDiag->lYtop;
}
} /* end of vMoveTo */
/*
* vSubstringFMT - print a sub string
*/
void
vSubstringFMT(diagram_type *pDiag,
const char *szString, size_t tStringLength, long lStringWidth,
USHORT usFontstyle)
{
fail(pDiag == NULL || szString == NULL);
fail(pDiag->pOutFile == NULL);
fail(pDiag->lXleft < 0);
fail(tStringLength != strlen(szString));
if (szString[0] == '\0' || tStringLength == 0) {
return;
}
vMoveTo(pDiag);
vPrintFMT(pDiag->pOutFile, szString, tStringLength, usFontstyle);
pDiag->lXleft += lStringWidth;
} /* end of vSubstringFMT */

2251
src/fontinfo.h Normal file

File diff suppressed because it is too large Load Diff

173
src/fontlist.c Normal file
View File

@@ -0,0 +1,173 @@
/*
* fontlist.c
* Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Build, read and destroy a list of Word font information
*/
#include <stdlib.h>
#include <stddef.h>
#include "antiword.h"
/*
* Private structure to hide the way the information
* is stored from the rest of the program
*/
typedef struct font_desc_tag {
font_block_type tInfo;
struct font_desc_tag *pNext;
} font_mem_type;
/* Variables needed to write the Font Information List */
static font_mem_type *pAnchor = NULL;
static font_mem_type *pFontLast = NULL;
/*
* vDestroyFontInfoList - destroy the Font Information List
*/
void
vDestroyFontInfoList(void)
{
font_mem_type *pCurr, *pNext;
DBG_MSG("vDestroyFontInfoList");
/* Free the Font Information List */
pCurr = pAnchor;
while (pCurr != NULL) {
pNext = pCurr->pNext;
pCurr = xfree(pCurr);
pCurr = pNext;
}
pAnchor = NULL;
/* Reset all control variables */
pFontLast = NULL;
} /* end of vDestroyFontInfoList */
/*
* vCorrectFontValues - correct font values to values Antiword can use
*/
void
vCorrectFontValues(font_block_type *pFontBlock)
{
UINT uiRealSize;
USHORT usRealStyle;
uiRealSize = pFontBlock->usFontSize;
usRealStyle = pFontBlock->usFontStyle;
if (bIsSmallCapitals(pFontBlock->usFontStyle)) {
/* Small capitals become normal capitals in a smaller font */
uiRealSize = (uiRealSize * 4 + 2) / 5;
usRealStyle &= ~FONT_SMALL_CAPITALS;
usRealStyle |= FONT_CAPITALS;
}
if (bIsSuperscript(pFontBlock->usFontStyle) ||
bIsSubscript(pFontBlock->usFontStyle)) {
/* Superscript and subscript use a smaller fontsize */
uiRealSize = (uiRealSize * 2 + 1) / 3;
}
if (uiRealSize < MIN_FONT_SIZE) {
DBG_DEC(uiRealSize);
uiRealSize = MIN_FONT_SIZE;
} else if (uiRealSize > MAX_FONT_SIZE) {
DBG_DEC(uiRealSize);
uiRealSize = MAX_FONT_SIZE;
}
pFontBlock->usFontSize = (USHORT)uiRealSize;
if (pFontBlock->ucFontColor == 8) {
/* White text to light gray text */
pFontBlock->ucFontColor = 16;
}
pFontBlock->usFontStyle = usRealStyle;
} /* end of vCorrectFontValues */
/*
* vAdd2FontInfoList - Add an element to the Font Information List
*/
void
vAdd2FontInfoList(const font_block_type *pFontBlock)
{
font_mem_type *pListMember;
fail(pFontBlock == NULL);
NO_DBG_MSG("bAdd2FontInfoList");
if (pFontBlock->ulFileOffset == FC_INVALID) {
/*
* This offset is really past the end of the file,
* so don't waste any memory by storing it.
*/
return;
}
NO_DBG_HEX(pFontBlock->ulFileOffset);
NO_DBG_DEC_C(pFontBlock->ucFontNumber != 0,
pFontBlock->ucFontNumber);
NO_DBG_DEC_C(pFontBlock->usFontSize != DEFAULT_FONT_SIZE,
pFontBlock->usFontSize);
NO_DBG_DEC_C(pFontBlock->ucFontColor != 0,
pFontBlock->ucFontColor);
NO_DBG_HEX_C(pFontBlock->usFontStyle != 0x00,
pFontBlock->usFontStyle);
if (pFontLast != NULL &&
pFontLast->tInfo.ulFileOffset == pFontBlock->ulFileOffset) {
/*
* If two consecutive fonts share the same
* offset, remember only the last font
*/
fail(pFontLast->pNext != NULL);
pFontLast->tInfo = *pFontBlock;
return;
}
/* Create list member */
pListMember = xmalloc(sizeof(font_mem_type));
/* Fill the list member */
pListMember->tInfo = *pFontBlock;
pListMember->pNext = NULL;
/* Correct the values where needed */
vCorrectFontValues(&pListMember->tInfo);
/* Add the new member to the list */
if (pAnchor == NULL) {
pAnchor = pListMember;
} else {
fail(pFontLast == NULL);
pFontLast->pNext = pListMember;
}
pFontLast = pListMember;
} /* end of vAdd2FontInfoList */
/*
* Get the record that follows the given recored in the Font Information List
*/
const font_block_type *
pGetNextFontInfoListItem(const font_block_type *pCurr)
{
const font_mem_type *pRecord;
size_t tOffset;
if (pCurr == NULL) {
if (pAnchor == NULL) {
/* There are no records */
return NULL;
}
/* The first record is the only one without a predecessor */
return &pAnchor->tInfo;
}
tOffset = offsetof(font_mem_type, tInfo);
/* Many casts to prevent alignment warnings */
pRecord = (font_mem_type *)(void *)((char *)pCurr - tOffset);
fail(pCurr != &pRecord->tInfo);
if (pRecord->pNext == NULL) {
/* The last record has no successor */
return NULL;
}
return &pRecord->pNext->tInfo;
} /* end of pGetNextFontInfoListItem */

1018
src/fonts.c Normal file

File diff suppressed because it is too large Load Diff

251
src/fonts_r.c Normal file
View File

@@ -0,0 +1,251 @@
/*
* fonts_r.c
* Copyright (C) 1999-2002 A.J. van Os; Released under GPL
*
* Description:
* Functions to deal with fonts (RiscOs version)
*/
#include <stdlib.h>
#include <string.h>
#include "DeskLib:Font.h"
#include "drawfile.h"
#include "antiword.h"
static font_handle tFontCurr = (font_handle)-1;
/*
* pOpenFontTableFile - open the Font translation file
* Copy the file to the proper place if necessary.
*
* Returns the file pointer or NULL
*/
FILE *
pOpenFontTableFile(void)
{
FILE *pFileR, *pFileW;
char *szFontNamesFile;
size_t tSize;
BOOL bFailed;
char acBuffer[256];
pFileR = fopen("<AntiWord$FontNamesFile>", "r");
if (pFileR != NULL) {
/* The font table is already in the right directory */
return pFileR;
}
szFontNamesFile = getenv("AntiWord$FontNamesSave");
if (szFontNamesFile == NULL) {
werr(0, "Warning: Name of the FontNames file not found");
return NULL;
}
DBG_MSG(szFontNamesFile);
pFileR = fopen("<AntiWord$Dir>.Resources.Default", "r");
if (pFileR == NULL) {
werr(0, "I can't find 'Resources.Default'");
return NULL;
}
/* Here the default font translation table is known to exist */
if (!bMakeDirectory(szFontNamesFile)) {
werr(0,
"I can't make a directory for the FontNames file");
return NULL;
}
/* Here the proper directory is known to exist */
pFileW = fopen(szFontNamesFile, "w");
if (pFileW == NULL) {
(void)fclose(pFileR);
werr(0, "I can't create a default FontNames file");
return NULL;
}
/* Here the proper directory is known to be writeable */
/* Copy the default FontNames file */
bFailed = FALSE;
while (!feof(pFileR)) {
tSize = fread(acBuffer, 1, sizeof(acBuffer), pFileR);
if (ferror(pFileR)) {
DBG_MSG("Read error");
bFailed = TRUE;
break;
}
if (fwrite(acBuffer, 1, tSize, pFileW) != tSize) {
DBG_MSG("Write error");
bFailed = TRUE;
break;
}
}
(void)fclose(pFileW);
(void)fclose(pFileR);
if (bFailed) {
DBG_MSG("Copying the FontNames file failed");
(void)remove(szFontNamesFile);
return NULL;
}
return fopen(szFontNamesFile, "r");
} /* end of pOpenFontTableFile */
/*
* vCloseFont - close the current font, if any
*/
void
vCloseFont(void)
{
os_error *e;
NO_DBG_MSG("vCloseFont");
if (tFontCurr == (font_handle)-1) {
return;
}
e = Font_LoseFont(tFontCurr);
if (e != NULL) {
werr(0, "Close font error %d: %s", e->errnum, e->errmess);
}
tFontCurr = (font_handle)-1;
} /* end of vCloseFont */
/*
* tOpenFont - make the specified font the current font
*
* Returns the font reference number for use in a draw file
*/
drawfile_fontref
tOpenFont(UCHAR ucWordFontNumber, USHORT usFontStyle, USHORT usWordFontSize)
{
os_error *e;
const char *szOurFontname;
font_handle tFont;
int iFontnumber;
NO_DBG_MSG("tOpenFont");
NO_DBG_DEC(ucWordFontNumber);
NO_DBG_HEX(usFontStyle);
NO_DBG_DEC(usWordFontSize);
/* Keep the relevant bits */
usFontStyle &= FONT_BOLD|FONT_ITALIC;
NO_DBG_HEX(usFontStyle);
iFontnumber = iGetFontByNumber(ucWordFontNumber, usFontStyle);
szOurFontname = szGetOurFontname(iFontnumber);
if (szOurFontname == NULL || szOurFontname[0] == '\0') {
tFontCurr = (font_handle)-1;
return (byte)0;
}
NO_DBG_MSG(szOurFontname);
e = Font_FindFont(&tFont, (char *)szOurFontname,
(int)usWordFontSize * 8, (int)usWordFontSize * 8,
0, 0);
if (e != NULL) {
switch (e->errnum) {
case 523:
werr(0, "%s", e->errmess);
break;
default:
werr(0, "Open font error %d: %s",
e->errnum, e->errmess);
break;
}
tFontCurr = (font_handle)-1;
return (drawfile_fontref)0;
}
tFontCurr = tFont;
NO_DBG_DEC(tFontCurr);
return (drawfile_fontref)(iFontnumber + 1);
} /* end of tOpenFont */
/*
* tOpenTableFont - make the table font the current font
*
* Returns the font reference number for use in a draw file
*/
drawfile_fontref
tOpenTableFont(USHORT usWordFontSize)
{
int iWordFontnumber;
NO_DBG_MSG("tOpenTableFont");
iWordFontnumber = iFontname2Fontnumber(TABLE_FONT, FONT_REGULAR);
if (iWordFontnumber < 0 || iWordFontnumber > (int)UCHAR_MAX) {
DBG_DEC(iWordFontnumber);
tFontCurr = (font_handle)-1;
return (drawfile_fontref)0;
}
return tOpenFont((UCHAR)iWordFontnumber, FONT_REGULAR, usWordFontSize);
} /* end of tOpenTableFont */
/*
* lComputeStringWidth - compute the string width
*
* Returns the string width in millipoints
*/
long
lComputeStringWidth(const char *szString, size_t tStringLength,
drawfile_fontref tFontRef, USHORT usFontSize)
{
font_string tStr;
os_error *e;
fail(szString == NULL);
fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
if (szString[0] == '\0' || tStringLength == 0) {
/* Empty string */
return 0;
}
if (tStringLength == 1 && szString[0] == TABLE_SEPARATOR) {
/* Font_strwidth doesn't like control characters */
return 0;
}
if (tFontCurr == (font_handle)-1) {
/* No current font, use systemfont */
return lChar2MilliPoints(tStringLength);
}
tStr.s = (char *)szString;
tStr.x = INT_MAX;
tStr.y = INT_MAX;
tStr.split = -1;
tStr.term = tStringLength;
e = Font_StringWidth(&tStr);
if (e == NULL) {
return (long)tStr.x;
}
DBG_DEC(e->errnum);
DBG_MSG(e->errmess);
DBG_DEC(tStringLength);
DBG_MSG(szString);
werr(0, "String width error %d: %s", e->errnum, e->errmess);
return lChar2MilliPoints(tStringLength);
} /* end of lComputeStringWidth */
/*
* tCountColumns - count the number of columns in a string
*
* Returns the number of columns
*/
size_t
tCountColumns(const char *szString, size_t tLength)
{
fail(szString == NULL);
/* One byte, one character, one column */
return tLength;
} /* end of tCountColumns */
/*
* tGetCharacterLength - the length of the specified character in bytes
*
* Returns the length in bytes
*/
size_t
tGetCharacterLength(const char *szString)
{
return 1;
} /* end of tGetCharacterLength */

305
src/fonts_u.c Normal file
View File

@@ -0,0 +1,305 @@
/*
* fonts_u.c
* Copyright (C) 1999-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Functions to deal with fonts (Unix version)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "antiword.h"
#include "fontinfo.h"
/* Don't use fonts, just plain text */
static BOOL bUsePlainText = TRUE;
/* Which character set should be used */
static encoding_type eEncoding = encoding_neutral;
/*
* pOpenFontTableFile - open the Font translation file
*
* Returns the file pointer or NULL
*/
FILE *
pOpenFontTableFile(void)
{
FILE *pFile;
const char *szHome, *szAntiword, *szGlobalFile;
char szEnvironmentFile[PATH_MAX+1];
char szLocalFile[PATH_MAX+1];
szEnvironmentFile[0] = '\0';
szLocalFile[0] = '\0';
/* Try the environment version of the fontnames file */
szAntiword = szGetAntiwordDirectory();
if (szAntiword != NULL && szAntiword[0] != '\0') {
if (strlen(szAntiword) +
sizeof(FILE_SEPARATOR FONTNAMES_FILE) >=
sizeof(szEnvironmentFile)) {
werr(0,
"The name of your ANTIWORDHOME directory is too long");
return NULL;
}
sprintf(szEnvironmentFile, "%s%s",
szAntiword,
FILE_SEPARATOR FONTNAMES_FILE);
DBG_MSG(szEnvironmentFile);
pFile = fopen(szEnvironmentFile, "r");
if (pFile != NULL) {
return pFile;
}
}
/* Try the local version of the fontnames file */
szHome = szGetHomeDirectory();
if (strlen(szHome) +
sizeof(FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE) >=
sizeof(szLocalFile)) {
werr(0, "The name of your HOME directory is too long");
return NULL;
}
sprintf(szLocalFile, "%s%s",
szHome,
FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE);
DBG_MSG(szLocalFile);
pFile = fopen(szLocalFile, "r");
if (pFile != NULL) {
return pFile;
}
/* Try the global version of the fontnames file */
szGlobalFile = GLOBAL_ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE;
DBG_MSG(szGlobalFile);
pFile = fopen(szGlobalFile, "r");
if (pFile != NULL) {
return pFile;
}
if (szEnvironmentFile[0] != '\0') {
werr(0, "I can not open your fontnames file.\n"
"Neither '%s' nor\n"
"'%s' nor\n"
"'%s' can be opened for reading.",
szEnvironmentFile, szLocalFile, szGlobalFile);
} else {
werr(0, "I can not open your fontnames file.\n"
"Neither '%s' nor\n"
"'%s' can be opened for reading.",
szLocalFile, szGlobalFile);
}
return NULL;
} /* end of pOpenFontTableFile */
/*
* vCloseFont - close the current font, if any
*/
void
vCloseFont(void)
{
NO_DBG_MSG("vCloseFont");
/* For safety: to be overwritten at the next call of tOpenfont() */
eEncoding = encoding_neutral;
bUsePlainText = TRUE;
} /* end of vCloseFont */
/*
* tOpenFont - make the specified font the current font
*
* Returns the font reference number
*/
drawfile_fontref
tOpenFont(UCHAR ucWordFontNumber, USHORT usFontStyle, USHORT usWordFontSize)
{
options_type tOptions;
const char *szOurFontname;
size_t tIndex;
int iFontnumber;
NO_DBG_MSG("tOpenFont");
NO_DBG_DEC(ucWordFontNumber);
NO_DBG_HEX(usFontStyle);
NO_DBG_DEC(usWordFontSize);
/* Keep the relevant bits */
usFontStyle &= FONT_BOLD|FONT_ITALIC;
NO_DBG_HEX(usFontStyle);
vGetOptions(&tOptions);
eEncoding = tOptions.eEncoding;
bUsePlainText = tOptions.eConversionType != conversion_draw &&
tOptions.eConversionType != conversion_ps &&
tOptions.eConversionType != conversion_pdf;
if (bUsePlainText) {
/* Plain text, no fonts */
return (drawfile_fontref)0;
}
iFontnumber = iGetFontByNumber(ucWordFontNumber, usFontStyle);
szOurFontname = szGetOurFontname(iFontnumber);
if (szOurFontname == NULL || szOurFontname[0] == '\0') {
DBG_DEC(iFontnumber);
return (drawfile_fontref)0;
}
NO_DBG_MSG(szOurFontname);
for (tIndex = 0; tIndex < elementsof(szFontnames); tIndex++) {
if (STREQ(szFontnames[tIndex], szOurFontname)) {
NO_DBG_DEC(tIndex);
return (drawfile_fontref)tIndex;
}
}
return (drawfile_fontref)0;
} /* end of tOpenFont */
/*
* tOpenTableFont - make the table font the current font
*
* Returns the font reference number
*/
drawfile_fontref
tOpenTableFont(USHORT usWordFontSize)
{
options_type tOptions;
int iWordFontnumber;
NO_DBG_MSG("tOpenTableFont");
vGetOptions(&tOptions);
eEncoding = tOptions.eEncoding;
bUsePlainText = tOptions.eConversionType != conversion_draw &&
tOptions.eConversionType != conversion_ps &&
tOptions.eConversionType != conversion_pdf;
if (bUsePlainText) {
/* Plain text, no fonts */
return (drawfile_fontref)0;
}
iWordFontnumber = iFontname2Fontnumber(TABLE_FONT, FONT_REGULAR);
if (iWordFontnumber < 0 || iWordFontnumber > (int)UCHAR_MAX) {
DBG_DEC(iWordFontnumber);
return (drawfile_fontref)0;
}
return tOpenFont((UCHAR)iWordFontnumber, FONT_REGULAR, usWordFontSize);
} /* end of tOpenTableFont */
/*
* szGetFontname - get the fontname
*/
const char *
szGetFontname(drawfile_fontref tFontRef)
{
fail((size_t)(UCHAR)tFontRef >= elementsof(szFontnames));
return szFontnames[(int)(UCHAR)tFontRef];
} /* end of szGetFontname */
/*
* lComputeStringWidth - compute the string width
*
* Note: the fontsize is specified in half-points!
* the stringlength is specified in bytes, not characters!
*
* Returns the string width in millipoints
*/
long
lComputeStringWidth(const char *szString, size_t tStringLength,
drawfile_fontref tFontRef, USHORT usFontSize)
{
USHORT *ausCharWidths;
UCHAR *pucChar;
long lRelWidth;
size_t tIndex;
int iFontRef;
fail(szString == NULL);
fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
if (szString[0] == '\0' || tStringLength == 0) {
/* Empty string */
return 0;
}
if (eEncoding == encoding_utf_8) {
fail(!bUsePlainText);
return lChar2MilliPoints(
utf8_strwidth(szString, tStringLength));
}
if (bUsePlainText) {
/* No current font, use "systemfont" */
return lChar2MilliPoints(tStringLength);
}
if (eEncoding == encoding_cyrillic) {
/* FIXME: until the character tables are available */
return (tStringLength * 600L * (long)usFontSize + 1) / 2;
}
DBG_DEC_C(eEncoding != encoding_latin_1 &&
eEncoding != encoding_latin_2, eEncoding);
fail(eEncoding != encoding_latin_1 &&
eEncoding != encoding_latin_2);
/* Compute the relative string width */
iFontRef = (int)(UCHAR)tFontRef;
if (eEncoding == encoding_latin_2) {
ausCharWidths = ausCharacterWidths2[iFontRef];
} else {
ausCharWidths = ausCharacterWidths1[iFontRef];
}
lRelWidth = 0;
for (tIndex = 0, pucChar = (UCHAR *)szString;
tIndex < tStringLength;
tIndex++, pucChar++) {
lRelWidth += (long)ausCharWidths[(int)*pucChar];
}
/* Compute the absolute string width */
return (lRelWidth * (long)usFontSize + 1) / 2;
} /* end of lComputeStringWidth */
/*
* tCountColumns - count the number of columns in a string
*
* Note: the length is specified in bytes!
* A UTF-8 a character can be 0, 1 or 2 columns wide.
*
* Returns the number of columns
*/
size_t
tCountColumns(const char *szString, size_t tLength)
{
fail(szString == NULL);
if (eEncoding != encoding_utf_8) {
/* One byte, one character, one column */
return tLength;
}
return (size_t)utf8_strwidth(szString, tLength);
} /* end of tCountColumns */
/*
* tGetCharacterLength - the length of the specified character in bytes
*
* Returns the length in bytes
*/
size_t
tGetCharacterLength(const char *szString)
{
fail(szString == NULL);
if (eEncoding != encoding_utf_8) {
return 1;
}
return (size_t)utf8_chrlength(szString);
} /* end of tGetCharacterLength */

371
src/hdrftrlist.c Normal file
View File

@@ -0,0 +1,371 @@
/*
* hdrftrlist.c
* Copyright (C) 2004,2005 A.J. van Os; Released under GNU GPL
*
* Description:
* Build, read and destroy list(s) of Word Header/footer information
*/
#include <string.h>
#include "antiword.h"
#define HDR_EVEN_PAGES 0
#define HDR_ODD_PAGES 1
#define FTR_EVEN_PAGES 2
#define FTR_ODD_PAGES 3
#define HDR_FIRST_PAGE 4
#define FTR_FIRST_PAGE 5
/*
* Private structures to hide the way the information
* is stored from the rest of the program
*/
typedef struct hdrftr_local_tag {
hdrftr_block_type tInfo;
ULONG ulCharPosStart;
ULONG ulCharPosNext;
BOOL bUseful;
BOOL bTextOriginal;
} hdrftr_local_type;
typedef struct hdrftr_mem_tag {
hdrftr_local_type atElement[6];
} hdrftr_mem_type;
/* Variables needed to write the Header/footer Information List */
static hdrftr_mem_type *pHdrFtrList = NULL;
static size_t tHdrFtrLen = 0;
/*
* vDestroyHdrFtrInfoList - destroy the Header/footer Information List
*/
void
vDestroyHdrFtrInfoList(void)
{
hdrftr_mem_type *pRecord;
output_type *pCurr, *pNext;
size_t tHdrFtr, tIndex;
DBG_MSG("vDestroyHdrFtrInfoList");
/* Free the Header/footer Information List */
for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) {
pRecord = pHdrFtrList + tHdrFtr;
for (tIndex = 0;
tIndex < elementsof(pRecord->atElement);
tIndex++) {
if (!pRecord->atElement[tIndex].bTextOriginal) {
continue;
}
pCurr = pRecord->atElement[tIndex].tInfo.pText;
while (pCurr != NULL) {
pCurr->szStorage = xfree(pCurr->szStorage);
pNext = pCurr->pNext;
pCurr = xfree(pCurr);
pCurr = pNext;
}
}
}
pHdrFtrList = xfree(pHdrFtrList);
/* Reset all control variables */
tHdrFtrLen = 0;
} /* end of vDestroyHdrFtrInfoList */
/*
* vCreat8HdrFtrInfoList - Create the Header/footer Information List
*/
void
vCreat8HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength)
{
hdrftr_mem_type *pListMember;
size_t tHdrFtr, tIndex, tMainIndex;
fail(aulCharPos == NULL);
DBG_DEC(tLength);
if (tLength <= 1) {
return;
}
tHdrFtrLen = tLength / 12;
if (tLength % 12 != 0 && tLength % 12 != 1) {
tHdrFtrLen++;
}
DBG_DEC(tHdrFtrLen);
pHdrFtrList = xcalloc(tHdrFtrLen, sizeof(hdrftr_mem_type));
for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) {
pListMember = pHdrFtrList + tHdrFtr;
for (tIndex = 0, tMainIndex = tHdrFtr * 12;
tIndex < 6 && tMainIndex < tLength;
tIndex++, tMainIndex++) {
pListMember->atElement[tIndex].tInfo.pText = NULL;
pListMember->atElement[tIndex].ulCharPosStart =
aulCharPos[tMainIndex];
if (tMainIndex + 1 < tLength) {
pListMember->atElement[tIndex].ulCharPosNext =
aulCharPos[tMainIndex + 1];
} else {
pListMember->atElement[tIndex].ulCharPosNext =
aulCharPos[tMainIndex];
}
}
}
} /* end of vCreat8HdrFtrInfoList */
/*
* vCreat6HdrFtrInfoList - Create the Header/footer Information List
*/
void
vCreat6HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength)
{
static const size_t atIndex[] =
{ SIZE_T_MAX, SIZE_T_MAX, FTR_FIRST_PAGE, HDR_FIRST_PAGE,
FTR_ODD_PAGES, FTR_EVEN_PAGES, HDR_ODD_PAGES, HDR_EVEN_PAGES,
};
hdrftr_mem_type *pListMember;
size_t tHdrFtr, tTmp, tIndex, tMainIndex, tBit;
UCHAR ucDopSpecification, ucSepSpecification;
fail(aulCharPos == NULL);
DBG_DEC(tLength);
if (tLength <= 1) {
return;
}
tHdrFtrLen = tGetNumberOfSections();
if (tHdrFtrLen == 0) {
tHdrFtrLen = 1;
}
DBG_DEC(tHdrFtrLen);
pHdrFtrList = xcalloc(tHdrFtrLen, sizeof(hdrftr_mem_type));
/* Get the start index in aulCharPos */
ucDopSpecification = ucGetDopHdrFtrSpecification();
DBG_HEX(ucDopSpecification & 0xe0);
tMainIndex = 0;
for (tBit = 7; tBit >= 5; tBit--) {
if ((ucDopSpecification & BIT(tBit)) != 0) {
tMainIndex++;
}
}
DBG_DEC(tMainIndex);
for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) {
ucSepSpecification = ucGetSepHdrFtrSpecification(tHdrFtr);
DBG_HEX(ucSepSpecification & 0xfc);
pListMember = pHdrFtrList + tHdrFtr;
for (tTmp = 0;
tTmp < elementsof(pListMember->atElement);
tTmp++) {
pListMember->atElement[tTmp].tInfo.pText = NULL;
}
for (tBit = 7; tBit >= 2; tBit--) {
if (tMainIndex >= tLength) {
break;
}
if ((ucSepSpecification & BIT(tBit)) == 0) {
continue;
}
tIndex = atIndex[tBit];
fail(tIndex >= 6);
pListMember->atElement[tIndex].ulCharPosStart =
aulCharPos[tMainIndex];
if (tMainIndex + 1 < tLength) {
pListMember->atElement[tIndex].ulCharPosNext =
aulCharPos[tMainIndex + 1];
} else {
pListMember->atElement[tIndex].ulCharPosNext =
aulCharPos[tMainIndex];
}
tMainIndex++;
}
}
} /* end of vCreat6HdrFtrInfoList */
/*
* vCreat2HdrFtrInfoList - Create the Header/footer Information List
*/
void
vCreat2HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength)
{
vCreat6HdrFtrInfoList(aulCharPos, tLength);
} /* end of vCreat2HdrFtrInfoList */
/*
* pGetHdrFtrInfo - get the Header/footer information
*/
const hdrftr_block_type *
pGetHdrFtrInfo(int iSectionIndex,
BOOL bWantHeader, BOOL bOddPage, BOOL bFirstInSection)
{
hdrftr_mem_type *pCurr;
fail(iSectionIndex < 0);
fail(pHdrFtrList == NULL && tHdrFtrLen != 0);
if (pHdrFtrList == NULL || tHdrFtrLen == 0) {
/* No information */
return NULL;
}
if (iSectionIndex < 0) {
iSectionIndex = 0;
} else if (iSectionIndex >= (int)tHdrFtrLen) {
iSectionIndex = (int)(tHdrFtrLen - 1);
}
pCurr = pHdrFtrList + iSectionIndex;
if (bFirstInSection) {
if (bWantHeader) {
return &pCurr->atElement[HDR_FIRST_PAGE].tInfo;
} else {
return &pCurr->atElement[FTR_FIRST_PAGE].tInfo;
}
} else {
if (bWantHeader) {
if (bOddPage) {
return &pCurr->atElement[HDR_ODD_PAGES].tInfo;
} else {
return &pCurr->atElement[HDR_EVEN_PAGES].tInfo;
}
} else {
if (bOddPage) {
return &pCurr->atElement[FTR_ODD_PAGES].tInfo;
} else {
return &pCurr->atElement[FTR_EVEN_PAGES].tInfo;
}
}
}
} /* end of pGetHdrFtrInfo */
/*
* lComputeHdrFtrHeight - compute the height of a header or footer
*
* Returns the height in DrawUnits
*/
static long
lComputeHdrFtrHeight(const output_type *pAnchor)
{
const output_type *pCurr;
long lTotal;
USHORT usFontSizeMax;
lTotal = 0;
usFontSizeMax = 0;
for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
if (pCurr->tNextFree == 1) {
if (pCurr->szStorage[0] == PAR_END) {
/* End of a paragraph */
lTotal += lComputeLeading(usFontSizeMax);
lTotal += lMilliPoints2DrawUnits(
(long)pCurr->usFontSize * 200);
usFontSizeMax = 0;
continue;
}
if (pCurr->szStorage[0] == HARD_RETURN) {
/* End of a line */
lTotal += lComputeLeading(usFontSizeMax);
usFontSizeMax = 0;
continue;
}
}
if (pCurr->usFontSize > usFontSizeMax) {
usFontSizeMax = pCurr->usFontSize;
}
}
if (usFontSizeMax != 0) {
/* Height of the last paragraph */
lTotal += lComputeLeading(usFontSizeMax);
}
return lTotal;
} /* end of lComputeHdrFtrHeight */
/*
* vPrepareHdrFtrText - prepare the header/footer text
*/
void
vPrepareHdrFtrText(FILE *pFile)
{
hdrftr_mem_type *pCurr, *pPrev;
hdrftr_local_type *pTmp;
output_type *pText;
size_t tHdrFtr, tIndex;
fail(pFile == NULL);
fail(pHdrFtrList == NULL && tHdrFtrLen != 0);
if (pHdrFtrList == NULL || tHdrFtrLen == 0) {
/* No information */
return;
}
/* Fill text, text height and useful-ness */
for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) {
pCurr = pHdrFtrList + tHdrFtr;
for (tIndex = 0;
tIndex < elementsof(pHdrFtrList->atElement);
tIndex++) {
pTmp = &pCurr->atElement[tIndex];
pTmp->bUseful =
pTmp->ulCharPosStart != pTmp->ulCharPosNext;
if (pTmp->bUseful) {
pText = pHdrFtrDecryptor(pFile,
pTmp->ulCharPosStart,
pTmp->ulCharPosNext);
pTmp->tInfo.pText = pText;
pTmp->tInfo.lHeight =
lComputeHdrFtrHeight(pText);
pTmp->bTextOriginal = pText != NULL;
} else {
pTmp->tInfo.pText = NULL;
pTmp->tInfo.lHeight = 0;
pTmp->bTextOriginal = FALSE;
}
}
}
/* Replace not-useful records by using inheritance */
if (pHdrFtrList->atElement[HDR_FIRST_PAGE].bUseful) {
pTmp = &pHdrFtrList->atElement[HDR_ODD_PAGES];
if (!pTmp->bUseful) {
*pTmp = pHdrFtrList->atElement[HDR_FIRST_PAGE];
pTmp->bTextOriginal = FALSE;
}
pTmp = &pHdrFtrList->atElement[HDR_EVEN_PAGES];
if (!pTmp->bUseful) {
*pTmp = pHdrFtrList->atElement[HDR_FIRST_PAGE];
pTmp->bTextOriginal = FALSE;
}
}
if (pHdrFtrList->atElement[FTR_FIRST_PAGE].bUseful) {
pTmp = &pHdrFtrList->atElement[FTR_ODD_PAGES];
if (!pTmp->bUseful) {
*pTmp = pHdrFtrList->atElement[FTR_FIRST_PAGE];
pTmp->bTextOriginal = FALSE;
}
pTmp = &pHdrFtrList->atElement[FTR_EVEN_PAGES];
if (!pTmp->bUseful) {
*pTmp = pHdrFtrList->atElement[FTR_FIRST_PAGE];
pTmp->bTextOriginal = FALSE;
}
}
for (tHdrFtr = 1, pCurr = &pHdrFtrList[1];
tHdrFtr < tHdrFtrLen;
tHdrFtr++, pCurr++) {
pPrev = pCurr - 1;
for (tIndex = 0;
tIndex < elementsof(pHdrFtrList->atElement);
tIndex++) {
if (!pCurr->atElement[tIndex].bUseful &&
pPrev->atElement[tIndex].bUseful) {
pCurr->atElement[tIndex] =
pPrev->atElement[tIndex];
pCurr->atElement[tIndex].bTextOriginal = FALSE;
}
}
}
} /* end of vPrepareHdrFtrText */

96
src/icons.c Normal file
View File

@@ -0,0 +1,96 @@
/*
* icons.c
* Copyright (C) 1998-2001 A.J. van Os; Released under GPL
*
* Description:
* Update window icons
*/
#include <string.h>
#include "DeskLib:Error.h"
#include "DeskLib:WimpSWIs.h"
#include "antiword.h"
void
vUpdateIcon(window_handle tWindow, icon_block *pIcon)
{
window_redrawblock tRedraw;
BOOL bMore;
tRedraw.window = tWindow;
tRedraw.rect = pIcon->workarearect;
Error_CheckFatal(Wimp_UpdateWindow(&tRedraw, &bMore));
while (bMore) {
Error_CheckFatal(Wimp_PlotIcon(pIcon));
Error_CheckFatal(Wimp_GetRectangle(&tRedraw, &bMore));
}
} /* end of vUpdateIcon */
void
vUpdateRadioButton(window_handle tWindow, icon_handle tIconNumber,
BOOL bSelected)
{
icon_block tIcon;
Error_CheckFatal(Wimp_GetIconState(tWindow, tIconNumber, &tIcon));
DBG_DEC(tIconNumber);
DBG_HEX(tIcon.flags.data.selected);
if (bSelected == (tIcon.flags.data.selected == 1)) {
/* No update needed */
return;
}
Error_CheckFatal(Wimp_SetIconState(tWindow, tIconNumber,
bSelected ? 0x00200000 : 0, 0x00200000));
vUpdateIcon(tWindow, &tIcon);
} /* end of vUpdateRadioButton */
/*
* vUpdateWriteable - update a writeable icon with a string
*/
void
vUpdateWriteable(window_handle tWindow, icon_handle tIconNumber,
const char *szString)
{
icon_block tIcon;
caret_block tCaret;
int iLen;
fail(szString == NULL);
NO_DBG_DEC(tIconNumber);
NO_DBG_MSG(szString);
Error_CheckFatal(Wimp_GetIconState(tWindow, tIconNumber, &tIcon));
NO_DBG_HEX(tIcon.flags);
if (!tIcon.flags.data.text || !tIcon.flags.data.indirected) {
werr(1, "Icon %d must be indirected text", (int)tIconNumber);
return;
}
strncpy(tIcon.data.indirecttext.buffer,
szString,
tIcon.data.indirecttext.bufflen - 1);
/* Ensure the caret is behind the last character of the text */
Error_CheckFatal(Wimp_GetCaretPosition(&tCaret));
if (tCaret.window == tWindow && tCaret.icon == tIconNumber) {
iLen = strlen(tIcon.data.indirecttext.buffer);
if (tCaret.index != iLen) {
tCaret.index = iLen;
Error_CheckFatal(Wimp_SetCaretPosition(&tCaret));
}
}
Error_CheckFatal(Wimp_SetIconState(tWindow, tIconNumber, 0, 0));
vUpdateIcon(tWindow, &tIcon);
} /* end of vUpdateWriteable */
/*
* vUpdateWriteableNumber - update a writeable icon with a number
*/
void
vUpdateWriteableNumber(window_handle tWindow, icon_handle tIconNumber,
int iNumber)
{
char szTmp[1+3*sizeof(int)+1];
(void)sprintf(szTmp, "%d", iNumber);
vUpdateWriteable(tWindow, tIconNumber, szTmp);
} /* end of vUpdateWriteableNumber */

1044
src/imgexam.c Normal file

File diff suppressed because it is too large Load Diff

71
src/imgtrans.c Normal file
View File

@@ -0,0 +1,71 @@
/*
* imgtrans.c
* Copyright (C) 2000-2002 A.J. van Os; Released under GPL
*
* Description:
* Generic functions to translate Word images
*/
#include <stdio.h>
#include "antiword.h"
/*
* bTranslateImage - translate the image
*
* This function reads the type of the given image and and gets it translated.
*
* return TRUE when sucessful, otherwise FALSE
*/
BOOL
bTranslateImage(diagram_type *pDiag, FILE *pFile, BOOL bMinimalInformation,
ULONG ulFileOffsetImage, const imagedata_type *pImg)
{
options_type tOptions;
DBG_MSG("bTranslateImage");
fail(pDiag == NULL);
fail(pFile == NULL);
fail(ulFileOffsetImage == FC_INVALID);
fail(pImg == NULL);
fail(pImg->iHorSizeScaled <= 0);
fail(pImg->iVerSizeScaled <= 0);
vGetOptions(&tOptions);
fail(tOptions.eImageLevel == level_no_images);
if (bMinimalInformation) {
return bAddDummyImage(pDiag, pImg);
}
switch (pImg->eImageType) {
case imagetype_is_dib:
return bTranslateDIB(pDiag, pFile,
ulFileOffsetImage + pImg->tPosition,
pImg);
case imagetype_is_jpeg:
return bTranslateJPEG(pDiag, pFile,
ulFileOffsetImage + pImg->tPosition,
pImg->tLength - pImg->tPosition,
pImg);
case imagetype_is_png:
if (tOptions.eImageLevel == level_ps_2) {
return bAddDummyImage(pDiag, pImg);
}
return bTranslatePNG(pDiag, pFile,
ulFileOffsetImage + pImg->tPosition,
pImg->tLength - pImg->tPosition,
pImg);
case imagetype_is_emf:
case imagetype_is_wmf:
case imagetype_is_pict:
case imagetype_is_external:
/* FIXME */
return bAddDummyImage(pDiag, pImg);
case imagetype_is_unknown:
default:
DBG_DEC(pImg->eImageType);
return bAddDummyImage(pDiag, pImg);
}
} /* end of bTranslateImage */

74
src/jpeg2eps.c Normal file
View File

@@ -0,0 +1,74 @@
/*
* jpeg2eps.c
* Copyright (C) 2000-2002 A.J. van Os; Released under GPL
*
* Description:
* Functions to translate jpeg pictures into eps
*
*/
#include <stdio.h>
#include "antiword.h"
#if defined(DEBUG)
static int iPicCounter = 0;
#endif /* DEBUG */
#if defined(DEBUG)
/*
* vCopy2File
*/
static void
vCopy2File(FILE *pFile, ULONG ulFileOffset, size_t tPictureLen)
{
FILE *pOutFile;
size_t tIndex;
int iTmp;
char szFilename[30];
if (!bSetDataOffset(pFile, ulFileOffset)) {
return;
}
sprintf(szFilename, "/tmp/pic/pic%04d.jpg", ++iPicCounter);
pOutFile = fopen(szFilename, "wb");
if (pOutFile == NULL) {
return;
}
for (tIndex = 0; tIndex < tPictureLen; tIndex++) {
iTmp = iNextByte(pFile);
if (putc(iTmp, pOutFile) == EOF) {
break;
}
}
(void)fclose(pOutFile);
} /* end of vCopy2File */
#endif /* DEBUG */
/*
* bTranslateJPEG - translate a JPEG picture
*
* This function translates a picture from jpeg to eps
*
* return TRUE when sucessful, otherwise FALSE
*/
BOOL
bTranslateJPEG(diagram_type *pDiag, FILE *pFile,
ULONG ulFileOffset, size_t tPictureLen, const imagedata_type *pImg)
{
#if defined(DEBUG)
vCopy2File(pFile, ulFileOffset, tPictureLen);
#endif /* DEBUG */
/* Seek to start position of JPEG data */
if (!bSetDataOffset(pFile, ulFileOffset)) {
return FALSE;
}
vImagePrologue(pDiag, pImg);
vASCII85EncodeFile(pFile, pDiag->pOutFile, tPictureLen);
vImageEpilogue(pDiag);
return TRUE;
} /* end of bTranslateJPEG */

97
src/jpeg2sprt.c Normal file
View File

@@ -0,0 +1,97 @@
/*
* jpeg2sprt.c
* Copyright (C) 2000-2002 A.J. van Os; Released under GPL
*
* Description:
* Functions to translate jpeg pictures into sprites
*/
#include <stdio.h>
#include "antiword.h"
#if 0 /* defined(DEBUG) */
static int iPicCounter = 0;
#endif /* DEBUG */
#if 0 /* defined(DEBUG) */
static void
vCopy2File(UCHAR *pucJpeg, size_t tJpegSize)
{
FILE *pOutFile;
size_t tIndex;
char szFilename[30];
sprintf(szFilename, "<Wimp$ScrapDir>.jpeg%04d", ++iPicCounter);
pOutFile = fopen(szFilename, "wb");
if (pOutFile == NULL) {
return;
}
DBG_MSG(szFilename);
for (tIndex = 0; tIndex < tJpegSize; tIndex++) {
if (putc(pucJpeg[tIndex], pOutFile) == EOF) {
break;
}
}
(void)fclose(pOutFile);
vSetFiletype(szFilename, FILETYPE_JPEG);
} /* end of vCopy2File */
#endif /* DEBUG */
/*
* bSave2Draw - save the JPEG picture to the Draw file
*
* This function puts a JPEG picture in a Draw file
*
* return TRUE when sucessful, otherwise FALSE
*/
BOOL
bSave2Draw(diagram_type *pDiag, FILE *pFile,
size_t tJpegSize, const imagedata_type *pImg)
{
UCHAR *pucJpeg, *pucTmp;
size_t tLen;
int iByte;
pucJpeg = xmalloc(tJpegSize);
for (pucTmp = pucJpeg, tLen = 0; tLen < tJpegSize; pucTmp++, tLen++) {
iByte = iNextByte(pFile);
if (iByte == EOF) {
return FALSE;
}
*pucTmp = (UCHAR)iByte;
}
#if 0 /* defined(DEBUG) */
vCopy2File(pucJpeg, tJpegSize);
#endif /* DEBUG */
/* Add the JPEG to the Draw file */
vImage2Diagram(pDiag, pImg, pucJpeg, tJpegSize);
xfree(pucJpeg);
return TRUE;
} /* end of bSave2Draw */
/*
* bTranslateJPEG - translate a JPEG picture
*
* This function translates a picture from jpeg to sprite
*
* return TRUE when sucessful, otherwise FALSE
*/
BOOL
bTranslateJPEG(diagram_type *pDiag, FILE *pFile,
ULONG ulFileOffset, size_t tPictureLen, const imagedata_type *pImg)
{
/* Seek to start position of JPEG data */
if (!bSetDataOffset(pFile, ulFileOffset)) {
return FALSE;
}
if (iGetRiscOsVersion() >= 360) {
return bSave2Draw(pDiag, pFile, tPictureLen, pImg);
}
/* JPEG is not supported until RISC OS 3.6 */
return bAddDummyImage(pDiag, pImg);
} /* end of bTranslateJPEG */

330
src/listlist.c Normal file
View File

@@ -0,0 +1,330 @@
/*
* listlist.c
* Copyright (C) 2002,2003 A.J. van Os; Released under GPL
*
* Description:
* Build, read and destroy a list of Word list information
*
* Note:
* This list only exists when the Word document is saved by Word 8 or later
*/
#include "antiword.h"
/*
* Private structure to hide the way the information
* is stored from the rest of the program
*/
typedef struct list_desc_tag {
list_block_type tInfo;
ULONG ulListID;
USHORT usIstd;
UCHAR ucListLevel;
struct list_desc_tag *pNext;
} list_desc_type;
typedef struct list_value_tag {
USHORT usValue;
USHORT usListIndex;
UCHAR ucListLevel;
struct list_value_tag *pNext;
} list_value_type;
/* Variables needed to describe the LFO list (pllfo) */
static ULONG *aulLfoList = NULL;
static USHORT usLfoLen = 0;
/* Variables needed to write the List Information List */
static list_desc_type *pAnchor = NULL;
static list_desc_type *pBlockLast = NULL;
/* Variable needed for numbering new lists */
static list_value_type *pValues = NULL;
/* Variables needed for numbering old lists */
static int iOldListSeqNumber = 0;
static USHORT usOldListValue = 0;
/*
* vDestroyListInfoList - destroy the List Information List
*/
void
vDestroyListInfoList(void)
{
list_desc_type *pCurr, *pNext;
list_value_type *pValueCurr, *pValueNext;
DBG_MSG("vDestroyListInfoList");
/* Free the LFO list */
usLfoLen = 0;
aulLfoList = xfree(aulLfoList);
/* Free the List Information List */
pCurr = pAnchor;
while (pCurr != NULL) {
pNext = pCurr->pNext;
pCurr = xfree(pCurr);
pCurr = pNext;
}
pAnchor = NULL;
/* Reset all control variables */
pBlockLast = NULL;
/* Free the values list */
pValueCurr = pValues;
while (pValueCurr != NULL) {
pValueNext = pValueCurr->pNext;
pValueCurr = xfree(pValueCurr);
pValueCurr = pValueNext;
}
pValues = NULL;
/* Reset the values for the old lists */
iOldListSeqNumber = 0;
usOldListValue = 0;
} /* end of vDestroyListInfoList */
/*
* vBuildLfoList - build the LFO list (pllfo)
*/
void
vBuildLfoList(const UCHAR *aucBuffer, size_t tBufLen)
{
size_t tRecords;
int iIndex;
fail(aucBuffer == NULL);
if (tBufLen < 4) {
return;
}
tRecords = (size_t)ulGetLong(0, aucBuffer);
NO_DBG_DEC(tRecords);
if (4 + 16 * tRecords > tBufLen || tRecords >= 0x7fff) {
/* Just a sanity check */
DBG_DEC(tRecords);
DBG_DEC(4 + 16 * tRecords);
DBG_DEC(tBufLen);
return;
}
aulLfoList = xcalloc(tRecords, sizeof(ULONG));
for (iIndex = 0; iIndex < (int)tRecords; iIndex++) {
aulLfoList[iIndex] = ulGetLong(4 + 16 * iIndex, aucBuffer);
NO_DBG_HEX(aulLfoList[iIndex]);
}
usLfoLen = (USHORT)tRecords;
} /* end of vBuildLfoList */
/*
* vAdd2ListInfoList - add an element to the List Information list
*/
void
vAdd2ListInfoList(ULONG ulListID, USHORT usIstd, UCHAR ucListLevel,
const list_block_type *pListBlock)
{
list_desc_type *pListMember;
fail(pListBlock == NULL);
NO_DBG_HEX(ulListID);
NO_DBG_DEC(usIstd);
NO_DBG_DEC(ucListLevel);
NO_DBG_DEC(pListBlock->ulStartAt);
NO_DBG_DEC(pListBlock->bNoRestart);
NO_DBG_DEC(pListBlock->sLeftIndent);
NO_DBG_HEX(pListBlock->ucNFC);
NO_DBG_HEX(pListBlock->usListChar);
/* Create list member */
pListMember = xmalloc(sizeof(list_desc_type));
/* Fill the list member */
pListMember->tInfo = *pListBlock;
pListMember->ulListID = ulListID;
pListMember->usIstd = usIstd;
pListMember->ucListLevel = ucListLevel;
pListMember->pNext = NULL;
/* Correct the values where needed */
if (pListMember->tInfo.ulStartAt > 0xffff) {
DBG_DEC(pListMember->tInfo.ulStartAt);
pListMember->tInfo.ulStartAt = 1;
}
/* Add the new member to the list */
if (pAnchor == NULL) {
pAnchor = pListMember;
} else {
fail(pBlockLast == NULL);
pBlockLast->pNext = pListMember;
}
pBlockLast = pListMember;
} /* end of vAdd2ListInfoList */
/*
* Get a matching record from the List Information List
*
* Returns NULL if no matching records is found
*/
const list_block_type *
pGetListInfo(USHORT usListIndex, UCHAR ucListLevel)
{
list_desc_type *pCurr;
list_block_type *pNearMatch;
ULONG ulListID;
if (usListIndex == 0) {
return NULL;
}
if (usListIndex - 1 >= usLfoLen || ucListLevel > 8) {
DBG_DEC(usListIndex);
DBG_DEC(ucListLevel);
return NULL;
}
fail(aulLfoList == NULL);
ulListID = aulLfoList[usListIndex - 1];
NO_DBG_HEX(ulListID);
pNearMatch = NULL;
for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
if (pCurr->ulListID != ulListID) {
/* No match */
continue;
}
if (pCurr->ucListLevel == ucListLevel) {
/* Exact match */
return &pCurr->tInfo;
}
if (pCurr->ucListLevel == 0) {
/* Near match */
pNearMatch = &pCurr->tInfo;
}
}
/* No exact match, use a near match if any */
return pNearMatch;
} /* end of pGetListInfo */
/*
* Get a matching record from the List Information List
*
* Returns NULL if no matching records is found
*/
const list_block_type *
pGetListInfoByIstd(USHORT usIstd)
{
list_desc_type *pCurr;
if (usIstd == ISTD_INVALID || usIstd == STI_NIL || usIstd == STI_USER) {
return NULL;
}
for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
if (pCurr->usIstd == usIstd) {
return &pCurr->tInfo;
}
}
return NULL;
} /* end of pGetListInfoByIstd */
/*
* vRestartListValues - reset the less significant list levels
*/
static void
vRestartListValues(USHORT usListIndex, UCHAR ucListLevel)
{
list_value_type *pPrev, *pCurr, *pNext;
int iCounter;
iCounter = 0;
pPrev = NULL;
pCurr = pValues;
while (pCurr != NULL) {
if (pCurr->usListIndex != usListIndex ||
pCurr->ucListLevel <= ucListLevel) {
pPrev = pCurr;
pCurr = pCurr->pNext;
continue;
}
/* Reset the level by deleting the record */
pNext = pCurr->pNext;
if (pPrev == NULL) {
pValues = pNext;
} else {
pPrev->pNext = pNext;
}
DBG_DEC(pCurr->usListIndex);
DBG_DEC(pCurr->ucListLevel);
pCurr = xfree(pCurr);
pCurr = pNext;
iCounter++;
}
DBG_DEC_C(iCounter > 0, iCounter);
} /* end of vRestartListValues */
/*
* usGetListValue - Get the current value of the given list
*
* Returns the value of the given list
*/
USHORT
usGetListValue(int iListSeqNumber, int iWordVersion,
const style_block_type *pStyle)
{
list_value_type *pCurr;
USHORT usValue;
fail(iListSeqNumber < 0);
fail(iListSeqNumber < iOldListSeqNumber);
fail(iWordVersion < 0);
fail(pStyle == NULL);
if (iListSeqNumber <= 0) {
return 0;
}
if (iWordVersion < 8) {
/* Old style list */
if (iListSeqNumber == iOldListSeqNumber ||
(iListSeqNumber == iOldListSeqNumber + 1 &&
eGetNumType(pStyle->ucNumLevel) == level_type_sequence)) {
if (!pStyle->bNumPause) {
usOldListValue++;
}
} else {
usOldListValue = pStyle->usStartAt;
}
iOldListSeqNumber = iListSeqNumber;
return usOldListValue;
}
/* New style list */
if (pStyle->usListIndex == 0 ||
pStyle->usListIndex - 1 >= usLfoLen ||
pStyle->ucListLevel > 8) {
/* Out of range; no need to search */
return 0;
}
for (pCurr = pValues; pCurr != NULL; pCurr = pCurr->pNext) {
if (pCurr->usListIndex == pStyle->usListIndex &&
pCurr->ucListLevel == pStyle->ucListLevel) {
/* Record found; increment and return the value */
pCurr->usValue++;
usValue = pCurr->usValue;
if (!pStyle->bNoRestart) {
vRestartListValues(pStyle->usListIndex,
pStyle->ucListLevel);
}
return usValue;
}
}
/* Record not found; create it and add it to the front of the list */
pCurr = xmalloc(sizeof(list_value_type));
pCurr->usValue = pStyle->usStartAt;
pCurr->usListIndex = pStyle->usListIndex;
pCurr->ucListLevel = pStyle->ucListLevel;
pCurr->pNext = pValues;
pValues = pCurr;
usValue = pCurr->usValue;
if (!pStyle->bNoRestart) {
vRestartListValues(pStyle->usListIndex, pStyle->ucListLevel);
}
return usValue;
} /* end of usGetListValue */

520
src/main_ros.c Normal file
View File

@@ -0,0 +1,520 @@
/*
* main_ros.c
*
* Released under GPL
*
* Copyright (C) 1998-2005 A.J. van Os
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Description:
* The main program of !Antiword (RISC OS version)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DeskLib:Dialog2.h"
#include "DeskLib:Error.h"
#include "DeskLib:Event.h"
#include "DeskLib:EventMsg.h"
#include "DeskLib:Handler.h"
#include "DeskLib:Menu.h"
#include "DeskLib:Resource.h"
#include "DeskLib:Screen.h"
#include "DeskLib:Template.h"
#include "DeskLib:Window.h"
#if defined(__GNUC__)
#include "flexlib:flex.h"
#endif /* __GNUC__ */
#include "version.h"
#include "antiword.h"
/* The name of this program */
static char *szTask = "!Antiword";
/* The window handle of the choices window */
static window_handle tChoicesWindow = 0;
/* Dummy diagram with the iconbar menu pointer */
static diagram_type tDummyDiagram;
/* Program information Box */
static dialog2_block *pInfoBox = NULL;
/* Info box fields */
#define PURPOSE_INFO_FIELD 2
#define AUTHOR_INFO_FIELD 3
#define VERSION_INFO_FIELD 4
#define STATUS_INFO_FIELD 5
/* Iconbar menu fields */
#define ICONBAR_INFO_FIELD 0
#define ICONBAR_CHOICES_FIELD 1
#define ICONBAR_QUIT_FIELD 2
/*
* bBarInfo - Show iconbar information
*/
static BOOL
bBarInfo(event_pollblock *pEvent, void *pvReference)
{
diagram_type *pDiag;
TRACE_MSG("bBarInfo");
fail(pEvent == NULL);
fail(pEvent->type != event_SEND);
fail(pEvent->data.message.header.action != message_MENUWARN);
fail(pvReference == NULL);
pDiag = (diagram_type *)pvReference;
if (menu_currentopen != pDiag->pSaveMenu ||
pEvent->data.message.data.menuwarn.selection[0] != ICONBAR_INFO_FIELD) {
return FALSE;
}
Dialog2_OpenDialogMenuLeaf(pEvent, pInfoBox);
return TRUE;
} /* end of bBarInfo */
/*
* vBarInfoSetText - Set the iconbar infobox text
*/
static void
vBarInfoSetText(dialog2_block *pBox)
{
TRACE_MSG("vBarInfoSetText");
fail(pBox == NULL);
fail(pBox != pInfoBox);
Icon_SetText(pBox->window, PURPOSE_INFO_FIELD, PURPOSESTRING);
Icon_SetText(pBox->window, AUTHOR_INFO_FIELD, AUTHORSTRING);
Icon_SetText(pBox->window, VERSION_INFO_FIELD, VERSIONSTRING);
Icon_SetText(pBox->window, STATUS_INFO_FIELD, STATUSSTRING);
} /* end of vBarInfoSetText */
/*
* bMouseButtonClick - respond to mouse button click
*/
static BOOL
bMouseButtonClick(event_pollblock *pEvent, void *pvReference)
{
diagram_type *pDiag;
menu_ptr pMenu;
int iPosY;
TRACE_MSG("bMouseButtonClick");
fail(pEvent == NULL);
fail(pEvent->type != event_CLICK);
fail(pvReference == NULL);
pDiag = (diagram_type *)pvReference;
if (pEvent->data.mouse.button.data.menu) {
pMenu = pDiag->pSaveMenu;
iPosY = (pMenu == tDummyDiagram.pSaveMenu) ?
-1 : pEvent->data.mouse.pos.y;
Menu_Show(pMenu, pEvent->data.mouse.pos.x, iPosY);
return TRUE;
}
if (pEvent->data.mouse.window == pDiag->tMainWindow &&
pEvent->data.mouse.icon == -1) {
vMainButtonClick(&pEvent->data.mouse);
return TRUE;
}
if (pEvent->data.mouse.window == pDiag->tScaleWindow &&
pEvent->data.mouse.icon >= 0) {
vScaleButtonClick(&pEvent->data.mouse, pDiag);
return TRUE;
}
return FALSE;
} /* end of bMouseButtonClick */
/*
* bAutoRedrawWindow - the redraw is handled by the WIMP
*/
static BOOL
bAutoRedrawWindow(event_pollblock *pEvent, void *pvReference)
{
return TRUE;
} /* end of bAutoRedrawWindow */
static BOOL
bSaveSelect(event_pollblock *pEvent, void *pvReference)
{
TRACE_MSG("bSaveSelect");
fail(pEvent == NULL);
fail(pEvent->type != event_MENU);
fail(pvReference == NULL);
DBG_DEC(pEvent->data.selection[0]);
switch (pEvent->data.selection[0]) {
case SAVEMENU_SCALEVIEW:
return bScaleOpenAction(pEvent, pvReference);
case SAVEMENU_SAVEDRAW:
return bSaveDrawfile(pEvent, pvReference);
case SAVEMENU_SAVETEXT:
return bSaveTextfile(pEvent, pvReference);
default:
DBG_DEC(pEvent->data.selection[0]);
return FALSE;
}
} /* end of bSaveSelect */
/*
* Create the window for the text from the given file
*/
static diagram_type *
pCreateTextWindow(const char *szFilename)
{
diagram_type *pDiag;
TRACE_MSG("pCreateTextWindow");
fail(szFilename == NULL || szFilename[0] == '\0');
/* Create the diagram */
pDiag = pCreateDiagram(szTask+1, szFilename);
if (pDiag == NULL) {
werr(0, "Sorry, no new diagram object");
return NULL;
}
/* Prepare a save menu for this diagram */
pDiag->pSaveMenu = Menu_New(szTask+1,
">Scale view,"
">Save (Drawfile) F3,"
">Save (Text only) \213F3");
if (pDiag->pSaveMenu == NULL) {
werr(1, "Sorry, no Savemenu object");
}
Menu_Warn(pDiag->pSaveMenu, SAVEMENU_SCALEVIEW,
TRUE, bScaleOpenAction, pDiag);
Menu_Warn(pDiag->pSaveMenu, SAVEMENU_SAVEDRAW,
TRUE, bSaveDrawfile, pDiag);
Menu_Warn(pDiag->pSaveMenu, SAVEMENU_SAVETEXT,
TRUE, bSaveTextfile, pDiag);
/* Claim events for the main window */
Event_Claim(event_REDRAW, pDiag->tMainWindow, icon_ANY,
bRedrawMainWindow, pDiag);
Event_Claim(event_CLOSE, pDiag->tMainWindow, icon_ANY,
bDestroyDiagram, pDiag);
Event_Claim(event_CLICK, pDiag->tMainWindow, icon_ANY,
bMouseButtonClick, pDiag);
Event_Claim(event_KEY, pDiag->tMainWindow, icon_ANY,
bMainKeyPressed, pDiag);
/* Claim events for the scale window */
Event_Claim(event_REDRAW, pDiag->tScaleWindow, icon_ANY,
bAutoRedrawWindow, NULL);
Event_Claim(event_CLICK, pDiag->tScaleWindow, icon_ANY,
bMouseButtonClick, pDiag);
Event_Claim(event_KEY, pDiag->tScaleWindow, icon_ANY,
bScaleKeyPressed, pDiag);
/* Set the window title */
vSetTitle(pDiag);
return pDiag;
} /* end of pCreateTextWindow */
/*
* vProcessFile - process one file
*/
static void
vProcessFile(const char *szFilename, int iFiletype)
{
options_type tOptions;
FILE *pFile;
diagram_type *pDiag;
long lFilesize;
int iWordVersion;
TRACE_MSG("vProcessFile");
fail(szFilename == NULL || szFilename[0] == '\0');
DBG_MSG(szFilename);
pFile = fopen(szFilename, "rb");
if (pFile == NULL) {
werr(0, "I can't open '%s' for reading", szFilename);
return;
}
lFilesize = lGetFilesize(szFilename);
if (lFilesize < 0) {
(void)fclose(pFile);
werr(0, "I can't get the size of '%s'", szFilename);
return;
}
iWordVersion = iGuessVersionNumber(pFile, lFilesize);
if (iWordVersion < 0 || iWordVersion == 3) {
if (bIsRtfFile(pFile)) {
werr(0, "%s is not a Word Document."
" It is probably a Rich Text Format file",
szFilename);
} if (bIsWordPerfectFile(pFile)) {
werr(0, "%s is not a Word Document."
" It is probably a Word Perfect file",
szFilename);
} else {
werr(0, "%s is not a Word Document.", szFilename);
}
(void)fclose(pFile);
return;
}
/* Reset any reading done during file-testing */
rewind(pFile);
if (iFiletype != FILETYPE_MSWORD) {
vGetOptions(&tOptions);
if (tOptions.bAutofiletypeAllowed) {
vSetFiletype(szFilename, FILETYPE_MSWORD);
}
}
pDiag = pCreateTextWindow(szFilename);
if (pDiag == NULL) {
(void)fclose(pFile);
return;
}
(void)bWordDecryptor(pFile, lFilesize, pDiag);
Error_CheckFatal(Drawfile_VerifyDiagram(&pDiag->tInfo));
vShowDiagram(pDiag);
TRACE_MSG("After vShowDiagram");
TRACE_MSG("before debug print");
DBG_HEX(pFile);
TRACE_MSG("before fclose");
(void)fclose(pFile);
TRACE_MSG("after fclose");
} /* end of vProcessFile */
/*
* vSendAck - send an acknowledge
*/
static void
vSendAck(event_pollblock *pEvent)
{
message_block tMessage;
TRACE_MSG("vSendAck");
fail(pEvent == NULL);
fail(pEvent->type != event_SEND && pEvent->type != event_SENDWANTACK);
fail(pEvent->data.message.header.action != message_DATALOAD &&
pEvent->data.message.header.action != message_DATAOPEN);
tMessage.header.action = message_DATALOADACK;
tMessage.header.size = sizeof(tMessage);
tMessage.header.yourref = pEvent->data.message.header.myref;
Error_CheckFatal(Wimp_SendMessage(event_SEND, &tMessage,
pEvent->data.message.header.sender, 0));
} /* end of vSendAck */
static BOOL
bEventMsgHandler(event_pollblock *pEvent, void *pvReference)
{
TRACE_MSG("bEventMsgHandler");
fail(pEvent == NULL);
switch (pEvent->type) {
case event_SEND:
case event_SENDWANTACK:
switch (pEvent->data.message.header.action) {
case message_CLOSEDOWN:
exit(EXIT_SUCCESS);
break;
case message_DATALOAD:
case message_DATAOPEN:
vProcessFile(
pEvent->data.message.data.dataload.filename,
pEvent->data.message.data.dataload.filetype);
vSendAck(pEvent);
break;
default:
DBG_DEC(pEvent->data.message.header.action);
break;
}
return TRUE;
default:
DBG_DEC(pEvent->type);
return FALSE;
}
} /* end of bEventMsgHandler */
/*
* bMenuSelect - select from the iconbar menu
*/
static BOOL
bMenuSelect(event_pollblock *pEvent, void *pvReference)
{
TRACE_MSG("bMenuSelect");
fail(pEvent == NULL);
fail(pEvent->type != event_MENU);
DBG_DEC(pEvent->data.selection[0]);
switch (pEvent->data.selection[0]) {
case ICONBAR_INFO_FIELD:
return bBarInfo(pEvent, pvReference);
case ICONBAR_CHOICES_FIELD:
vChoicesOpenAction(tChoicesWindow);
Window_BringToFront(tChoicesWindow);
break;
case ICONBAR_QUIT_FIELD:
TRACE_MSG("before exit");
exit(EXIT_SUCCESS);
break;
default:
DBG_DEC(pEvent->data.selection[0]);
break;
}
return TRUE;
} /* end of bMenuSelect */
/*
* bMenuClick - respond to an menu click
*/
static BOOL
bMenuClick(event_pollblock *pEvent, void *pvReference)
{
TRACE_MSG("bMenuClick");
fail(pEvent == NULL);
fail(pEvent->type != event_MENU);
if (menu_currentopen == tDummyDiagram.pSaveMenu) {
return bMenuSelect(pEvent, pvReference);
} else if (pvReference == NULL) {
return FALSE;
}
return bSaveSelect(pEvent, pvReference);
} /* end of bMenuClick */
static void
vTemplates(void)
{
TRACE_MSG("vTemplates");
Template_Initialise();
Template_LoadFile("Templates");
tChoicesWindow = Window_Create("Choices", template_TITLEMIN);
if (tChoicesWindow == 0) {
werr(1, "I can't find the 'Choices' template");
}
/* Claim events for the choices window */
Event_Claim(event_REDRAW, tChoicesWindow, icon_ANY,
bAutoRedrawWindow, NULL);
Event_Claim(event_CLICK, tChoicesWindow, icon_ANY,
bChoicesMouseClick, NULL);
Event_Claim(event_KEY, tChoicesWindow, icon_ANY,
bChoicesKeyPressed, NULL);
} /* end of vTemplates */
static void
vInitialise(void)
{
int aiMessages[] = {0};
icon_handle tBarIcon;
TRACE_MSG("vInitialise");
Resource_Initialise(szTask+1);
Event_Initialise3(szTask+1, 310, aiMessages);
EventMsg_Initialise();
Screen_CacheModeInfo();
#if defined(__GNUC__)
flex_init(szTask+1, 0, 0);
flex_set_budge(1);
#endif /* __GNUC__ */
vTemplates();
/* Prepare iconbar menu */
tDummyDiagram.tInfo.data = NULL;
tDummyDiagram.tInfo.length = 0;
tDummyDiagram.pSaveMenu = Menu_New(szTask+1, ">Info,Choices...,Quit");
if (tDummyDiagram.pSaveMenu == NULL) {
werr(1, "Sorry, no Barmenu object");
}
pInfoBox = Dialog2_CreateDialogBlock("ProgInfo", -1, -1,
vBarInfoSetText, NULL, NULL);
if (pInfoBox == NULL) {
werr(1, "Sorry, no Infobox object");
}
Menu_Warn(tDummyDiagram.pSaveMenu, ICONBAR_INFO_FIELD,
TRUE, bBarInfo, &tDummyDiagram);
/* Create an icon on the icon bar */
tBarIcon = Icon_BarIcon(szTask, iconbar_RIGHT);
Event_Claim(event_CLICK, window_ICONBAR, tBarIcon,
bMouseButtonClick, &tDummyDiagram);
/* Generic claims */
Event_Claim(event_OPEN, window_ANY, icon_ANY,
Handler_OpenWindow, NULL);
Event_Claim(event_CLOSE, window_ANY, icon_ANY,
Handler_CloseWindow, NULL);
Event_Claim(event_MENU, window_ANY, icon_ANY,
bMenuClick, NULL);
EventMsg_Claim(message_DATALOAD, window_ICONBAR,
bEventMsgHandler, NULL);
EventMsg_Claim(message_MODECHANGE, window_ANY,
Handler_ModeChange, NULL);
} /* end of vInitialise */
int
main(int argc, char **argv)
{
int iFirst, iFiletype;
TRACE_MSG("main");
vInitialise();
iFirst = iReadOptions(argc, argv);
if (iFirst != 1) {
return EXIT_FAILURE;
}
if (argc > 1) {
iFiletype = iGetFiletype(argv[1]);
if (iFiletype < 0) {
return EXIT_FAILURE;
}
vProcessFile(argv[1], iFiletype);
TRACE_MSG("main after vProcessFile");
}
for (;;) {
Event_Poll();
}
} /* end of main */

321
src/main_u.c Normal file
View File

@@ -0,0 +1,321 @@
/*
* main_u.c
*
* Released under GPL
*
* Copyright (C) 1998-2004 A.J. van Os
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Description:
* The main program of 'antiword' (Unix version)
*/
#include <stdio.h>
#include <stdlib.h>
#if defined(__dos)
#include <fcntl.h>
#include <io.h>
#endif /* __dos */
#if defined(__CYGWIN__) || defined(__CYGMING__)
# ifdef X_LOCALE
# include <X11/Xlocale.h>
# else
# include <locale.h>
# endif
#else
#include <locale.h>
#endif /* __CYGWIN__ || __CYGMING__ */
#if defined(N_PLAT_NLM)
#if !defined(_VA_LIST)
#include "NW-only/nw_os.h"
#endif /* !_VA_LIST */
#include "getopt.h"
#endif /* N_PLAT_NLM */
#include "version.h"
#include "antiword.h"
/* The name of this program */
static const char *szTask = NULL;
static void
vUsage(void)
{
fprintf(stderr, "\tName: %s\n", szTask);
fprintf(stderr, "\tPurpose: "PURPOSESTRING"\n");
fprintf(stderr, "\tAuthor: "AUTHORSTRING"\n");
fprintf(stderr, "\tVersion: "VERSIONSTRING);
#if defined(__dos)
fprintf(stderr, VERSIONSTRING2);
#endif /* __dos */
fprintf(stderr, "\n");
fprintf(stderr, "\tStatus: "STATUSSTRING"\n");
fprintf(stderr,
"\tUsage: %s [switches] wordfile1 [wordfile2 ...]\n", szTask);
fprintf(stderr,
"\tSwitches: [-f|-t|-a papersize|-p papersize|-x dtd]"
"[-m mapping][-w #][-i #][-Ls]\n");
fprintf(stderr, "\t\t-f formatted text output\n");
fprintf(stderr, "\t\t-t text output (default)\n");
fprintf(stderr, "\t\t-a <paper size name> Adobe PDF output\n");
fprintf(stderr, "\t\t-p <paper size name> PostScript output\n");
fprintf(stderr, "\t\t paper size like: a4, letter or legal\n");
fprintf(stderr, "\t\t-x <dtd> XML output\n");
fprintf(stderr, "\t\t like: db (DocBook)\n");
fprintf(stderr, "\t\t-m <mapping> character mapping file\n");
fprintf(stderr, "\t\t-w <width> in characters of text output\n");
fprintf(stderr, "\t\t-i <level> image level (PostScript only)\n");
fprintf(stderr, "\t\t-L use landscape mode (PostScript only)\n");
fprintf(stderr, "\t\t-r Show removed text\n");
fprintf(stderr, "\t\t-s Show hidden (by Word) text\n");
} /* end of vUsage */
/*
* pStdin2TmpFile - save stdin in a temporary file
*
* returns: the pointer to the temporary file or NULL
*/
static FILE *
pStdin2TmpFile(long *lFilesize)
{
FILE *pTmpFile;
size_t tSize;
BOOL bFailure;
UCHAR aucBytes[BUFSIZ];
DBG_MSG("pStdin2TmpFile");
fail(lFilesize == NULL);
/* Open the temporary file */
pTmpFile = tmpfile();
if (pTmpFile == NULL) {
return NULL;
}
#if defined(__dos)
/* Stdin must be read as a binary stream */
setmode(fileno(stdin), O_BINARY);
#endif /* __dos */
/* Copy stdin to the temporary file */
*lFilesize = 0;
bFailure = TRUE;
for (;;) {
tSize = fread(aucBytes, 1, sizeof(aucBytes), stdin);
if (tSize == 0) {
bFailure = feof(stdin) == 0;
break;
}
if (fwrite(aucBytes, 1, tSize, pTmpFile) != tSize) {
bFailure = TRUE;
break;
}
*lFilesize += (long)tSize;
}
#if defined(__dos)
/* Switch stdin back to a text stream */
setmode(fileno(stdin), O_TEXT);
#endif /* __dos */
/* Deal with the result of the copy action */
if (bFailure) {
*lFilesize = 0;
(void)fclose(pTmpFile);
return NULL;
}
rewind(pTmpFile);
return pTmpFile;
} /* end of pStdin2TmpFile */
/*
* bProcessFile - process a single file
*
* returns: TRUE when the given file is a supported Word file, otherwise FALSE
*/
static BOOL
bProcessFile(const char *szFilename)
{
FILE *pFile;
diagram_type *pDiag;
long lFilesize;
int iWordVersion;
BOOL bResult;
fail(szFilename == NULL || szFilename[0] == '\0');
DBG_MSG(szFilename);
if (szFilename[0] == '-' && szFilename[1] == '\0') {
pFile = pStdin2TmpFile(&lFilesize);
if (pFile == NULL) {
werr(0, "I can't save the standard input to a file");
return FALSE;
}
} else {
pFile = fopen(szFilename, "rb");
if (pFile == NULL) {
werr(0, "I can't open '%s' for reading", szFilename);
return FALSE;
}
lFilesize = lGetFilesize(szFilename);
if (lFilesize < 0) {
(void)fclose(pFile);
werr(0, "I can't get the size of '%s'", szFilename);
return FALSE;
}
}
iWordVersion = iGuessVersionNumber(pFile, lFilesize);
if (iWordVersion < 0 || iWordVersion == 3) {
if (bIsRtfFile(pFile)) {
werr(0, "%s is not a Word Document."
" It is probably a Rich Text Format file",
szFilename);
} if (bIsWordPerfectFile(pFile)) {
werr(0, "%s is not a Word Document."
" It is probably a Word Perfect file",
szFilename);
} else {
#if defined(__dos)
werr(0, "%s is not a Word Document or the filename"
" is not in the 8+3 format.", szFilename);
#else
werr(0, "%s is not a Word Document.", szFilename);
#endif /* __dos */
}
(void)fclose(pFile);
return FALSE;
}
/* Reset any reading done during file testing */
rewind(pFile);
pDiag = pCreateDiagram(szTask, szFilename);
if (pDiag == NULL) {
(void)fclose(pFile);
return FALSE;
}
bResult = bWordDecryptor(pFile, lFilesize, pDiag);
vDestroyDiagram(pDiag);
(void)fclose(pFile);
return bResult;
} /* end of bProcessFile */
int
main(int argc, char **argv)
{
options_type tOptions;
const char *szWordfile;
int iFirst, iIndex, iGoodCount;
BOOL bUsage, bMultiple, bUseTXT, bUseXML;
if (argc <= 0) {
return EXIT_FAILURE;
}
szTask = szBasename(argv[0]);
if (argc <= 1) {
iFirst = 1;
bUsage = TRUE;
} else {
iFirst = iReadOptions(argc, argv);
bUsage = iFirst <= 0;
}
if (bUsage) {
vUsage();
return iFirst < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
#if defined(N_PLAT_NLM) && !defined(_VA_LIST)
nwinit();
#endif /* N_PLAT_NLM && !_VA_LIST */
vGetOptions(&tOptions);
#if !defined(__dos)
if (is_locale_utf8()) {
#if defined(__STDC_ISO_10646__)
/*
* If the user wants UTF-8 and the envirionment variables
* support UTF-8, than set the locale accordingly
*/
if (tOptions.eEncoding == encoding_utf_8) {
if (setlocale(LC_CTYPE, "") == NULL) {
werr(1, "Can't set the UTF-8 locale! "
"Check LANG, LC_CTYPE, LC_ALL.");
}
DBG_MSG("The UTF-8 locale has been set");
} else {
(void)setlocale(LC_CTYPE, "C");
}
#endif /* __STDC_ISO_10646__ */
} else {
if (setlocale(LC_CTYPE, "") == NULL) {
werr(0, "Can't set the locale! Will use defaults");
(void)setlocale(LC_CTYPE, "C");
}
DBG_MSG("The locale has been set");
}
#endif /* !__dos */
bMultiple = argc - iFirst > 1;
bUseTXT = tOptions.eConversionType == conversion_text ||
tOptions.eConversionType == conversion_fmt_text;
bUseXML = tOptions.eConversionType == conversion_xml;
iGoodCount = 0;
#if defined(__dos)
if (tOptions.eConversionType == conversion_pdf) {
/* PDF must be written as a binary stream */
setmode(fileno(stdout), O_BINARY);
}
#endif /* __dos */
if (bUseXML) {
fprintf(stdout,
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<!DOCTYPE %s PUBLIC \"-//OASIS//DTD DocBook XML V4.1.2//EN\"\n"
"\t\"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd\">\n",
bMultiple ? "set" : "book");
if (bMultiple) {
fprintf(stdout, "<set>\n");
}
}
for (iIndex = iFirst; iIndex < argc; iIndex++) {
if (bMultiple && bUseTXT) {
szWordfile = szBasename(argv[iIndex]);
fprintf(stdout, "::::::::::::::\n");
fprintf(stdout, "%s\n", szWordfile);
fprintf(stdout, "::::::::::::::\n");
}
if (bProcessFile(argv[iIndex])) {
iGoodCount++;
}
}
if (bMultiple && bUseXML) {
fprintf(stdout, "</set>\n");
}
DBG_DEC(iGoodCount);
return iGoodCount <= 0 ? EXIT_FAILURE : EXIT_SUCCESS;
} /* end of main */

894
src/misc.c Normal file
View File

@@ -0,0 +1,894 @@
/*
* misc.c
* Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
*
* Description:
* Miscellaneous functions
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#if defined(__riscos)
#include "DeskLib:SWI.h"
#else
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif /* __riscos */
#if !defined(S_ISREG)
#define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
#endif /* !S_ISREG */
#include "antiword.h"
#if defined(__vms)
#include <unixlib.h>
#endif
#if !defined(__riscos)
/*
* szGetHomeDirectory - get the name of the home directory
*/
const char *
szGetHomeDirectory(void)
{
const char *szHome;
#if defined(__vms)
szHome = decc$translate_vms(getenv("HOME"));
#elif defined(__Plan9__)
szHome = getenv("home");
#else
szHome = getenv("HOME");
#endif /* __vms */
if (szHome == NULL || szHome[0] == '\0') {
#if defined(N_PLAT_NLM)
szHome = "SYS:";
#elif defined(__dos)
szHome = "C:";
#else
werr(0, "I can't find the name of your HOME directory");
szHome = "";
#endif /* __dos */
}
return szHome;
} /* end of szGetHomeDirectory */
/*
* szGetAntiwordDirectory - get the name of the Antiword directory
*/
const char *
szGetAntiwordDirectory(void)
{
#if defined(__vms)
return decc$translate_vms(getenv("ANTIWORDHOME"));
#else
return getenv("ANTIWORDHOME");
#endif /* __vms */
} /* end of szGetAntiwordDirectory */
#endif /* !__riscos */
/*
* Get the size of the specified file.
* Returns -1 if the file does not exist or is not a proper file.
*/
long
lGetFilesize(const char *szFilename)
{
#if defined(__riscos)
os_error *e;
int iType, iSize;
e = SWI(2, 5, SWI_OS_File | XOS_Bit,
17, szFilename,
&iType, NULL, NULL, NULL, &iSize);
if (e != NULL) {
werr(0, "Get Filesize error %d: %s",
e->errnum, e->errmess);
return -1;
}
if (iType != 1) {
/* It's not a proper file or the file does not exist */
return -1;
}
return (long)iSize;
#else
struct stat tBuffer;
errno = 0;
if (stat(szFilename, &tBuffer) != 0) {
werr(0, "Get Filesize error %d", errno);
return -1;
}
if (!S_ISREG(tBuffer.st_mode)) {
/* It's not a regular file */
return -1;
}
return (long)tBuffer.st_size;
#endif /* __riscos */
} /* end of lGetFilesize */
#if defined(DEBUG)
void
vPrintBlock(const char *szFile, int iLine,
const UCHAR *aucBlock, size_t tLength)
{
int i, j;
fail(szFile == NULL || iLine < 0 || aucBlock == NULL);
fprintf(stderr, "%s[%3d]:\n", szFile, iLine);
for (i = 0; i < 32; i++) {
if (16 * i >= (int)tLength) {
return;
}
fprintf(stderr, "%03x: ", (unsigned int)(16 * i));
for (j = 0; j < 16; j++) {
if (16 * i + j < (int)tLength) {
fprintf(stderr, "%02x ",
(unsigned int)aucBlock[16 * i + j]);
}
}
fprintf(stderr, "\n");
}
} /* end of vPrintBlock */
void
vPrintUnicode(const char *szFile, int iLine, const UCHAR *aucUni, size_t tLen)
{
char *szASCII;
fail(tLen % 2 != 0);
tLen /= 2; /* Length in bytes to length in characters */
szASCII = xmalloc(tLen + 1);
(void)unincpy(szASCII, aucUni, tLen);
szASCII[tLen] = '\0';
(void)fprintf(stderr, "%s[%3d]: %.*s\n",
szFile, iLine, (int)tLen, szASCII);
szASCII = xfree(szASCII);
} /* end of vPrintUnicode */
BOOL
bCheckDoubleLinkedList(output_type *pAnchor)
{
output_type *pCurr, *pLast;
int iInList;
pLast = pAnchor;
iInList = 0;
for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
pLast = pCurr;
iInList++;
}
NO_DBG_DEC(iInList);
for (pCurr = pLast; pCurr != NULL; pCurr = pCurr->pPrev) {
pLast = pCurr;
iInList--;
}
DBG_DEC_C(iInList != 0, iInList);
return pAnchor == pLast && iInList == 0;
} /* end of bCheckDoubleLinkedList */
#endif /* DEBUG */
/*
* bReadBytes
* This function reads the specified number of bytes from the specified file,
* starting from the specified offset.
* Returns TRUE when successfull, otherwise FALSE
*/
BOOL
bReadBytes(UCHAR *aucBytes, size_t tMemb, ULONG ulOffset, FILE *pFile)
{
fail(aucBytes == NULL || pFile == NULL || ulOffset > (ULONG)LONG_MAX);
if (ulOffset > (ULONG)LONG_MAX) {
return FALSE;
}
if (fseek(pFile, (long)ulOffset, SEEK_SET) != 0) {
return FALSE;
}
if (fread(aucBytes, sizeof(UCHAR), tMemb, pFile) != tMemb) {
return FALSE;
}
return TRUE;
} /* end of bReadBytes */
/*
* bReadBuffer
* This function fills the specified buffer with the specified number of bytes,
* starting at the specified offset within the Big/Small Block Depot.
*
* Returns TRUE when successful, otherwise FALSE
*/
BOOL
bReadBuffer(FILE *pFile, ULONG ulStartBlock,
const ULONG *aulBlockDepot, size_t tBlockDepotLen, size_t tBlockSize,
UCHAR *aucBuffer, ULONG ulOffset, size_t tToRead)
{
ULONG ulBegin, ulIndex;
size_t tLen;
fail(pFile == NULL);
fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
fail(aulBlockDepot == NULL);
fail(tBlockSize != BIG_BLOCK_SIZE && tBlockSize != SMALL_BLOCK_SIZE);
fail(aucBuffer == NULL);
fail(tToRead == 0);
for (ulIndex = ulStartBlock;
ulIndex != END_OF_CHAIN && tToRead != 0;
ulIndex = aulBlockDepot[ulIndex]) {
if (ulIndex >= (ULONG)tBlockDepotLen) {
DBG_DEC(ulIndex);
DBG_DEC(tBlockDepotLen);
if (tBlockSize >= BIG_BLOCK_SIZE) {
werr(1, "The Big Block Depot is damaged");
} else {
werr(1, "The Small Block Depot is damaged");
}
}
if (ulOffset >= (ULONG)tBlockSize) {
ulOffset -= tBlockSize;
continue;
}
ulBegin = ulDepotOffset(ulIndex, tBlockSize) + ulOffset;
tLen = min(tBlockSize - (size_t)ulOffset, tToRead);
ulOffset = 0;
if (!bReadBytes(aucBuffer, tLen, ulBegin, pFile)) {
werr(0, "Read big block 0x%lx not possible", ulBegin);
return FALSE;
}
aucBuffer += tLen;
tToRead -= tLen;
}
DBG_DEC_C(tToRead != 0, tToRead);
return tToRead == 0;
} /* end of bReadBuffer */
/*
* Convert a Word colornumber into a true color for use in a drawfile
*
* Returns the true color
*/
ULONG
ulColor2Color(UCHAR ucFontColor)
{
static const ULONG aulColorTable[] = {
/* 0 */ 0x00000000UL, /* Automatic */
/* 1 */ 0x00000000UL, /* Black */
/* 2 */ 0xff000000UL, /* Blue */
/* 3 */ 0xffff0000UL, /* Turquoise */
/* 4 */ 0x00ff0000UL, /* Bright Green */
/* 5 */ 0xff00ff00UL, /* Pink */
/* 6 */ 0x0000ff00UL, /* Red */
/* 7 */ 0x00ffff00UL, /* Yellow */
/* 8 */ 0xffffff00UL, /* White */
/* 9 */ 0x80000000UL, /* Dark Blue */
/* 10 */ 0x80800000UL, /* Teal */
/* 11 */ 0x00800000UL, /* Green */
/* 12 */ 0x80008000UL, /* Violet */
/* 13 */ 0x00008000UL, /* Dark Red */
/* 14 */ 0x00808000UL, /* Dark Yellow */
/* 15 */ 0x80808000UL, /* Gray 50% */
/* 16 */ 0xc0c0c000UL, /* Gray 25% */
};
if ((size_t)ucFontColor >= elementsof(aulColorTable)) {
return aulColorTable[0];
}
return aulColorTable[(int)ucFontColor];
} /* end of ulColor2Color */
/*
* iFindSplit - find a place to split the string
*
* returns the index of the split character or -1 if no split found.
*/
static int
iFindSplit(const char *szString, size_t tStringLen)
{
size_t tSplit;
if (tStringLen == 0) {
return -1;
}
tSplit = tStringLen - 1;
while (tSplit >= 1) {
if (szString[tSplit] == ' ' ||
(szString[tSplit] == '-' && szString[tSplit - 1] != ' ')) {
return (int)tSplit;
}
tSplit--;
}
return -1;
} /* end of iFindSplit */
/*
* pSplitList - split the specified list in a printable part and a leftover part
*
* returns the pointer to the leftover part
*/
output_type *
pSplitList(output_type *pAnchor)
{
output_type *pCurr, *pLeftOver;
int iIndex;
fail(pAnchor == NULL);
for (pCurr = pAnchor; pCurr->pNext != NULL; pCurr = pCurr->pNext)
; /* EMPTY */
iIndex = -1;
for (; pCurr != NULL; pCurr = pCurr->pPrev) {
iIndex = iFindSplit(pCurr->szStorage, pCurr->tNextFree);
if (iIndex >= 0) {
break;
}
}
if (pCurr == NULL || iIndex < 0) {
/* No split, no leftover */
return NULL;
}
/* Split over the iIndex-th character */
NO_DBG_MSG("pLeftOver");
pLeftOver = xmalloc(sizeof(*pLeftOver));
fail(pCurr->tNextFree < (size_t)iIndex);
pLeftOver->tStorageSize = pCurr->tNextFree - (size_t)iIndex;
pLeftOver->szStorage = xmalloc(pLeftOver->tStorageSize);
pLeftOver->tNextFree = pCurr->tNextFree - (size_t)iIndex - 1;
(void)strncpy(pLeftOver->szStorage,
pCurr->szStorage + iIndex + 1, pLeftOver->tNextFree);
pLeftOver->szStorage[pLeftOver->tNextFree] = '\0';
NO_DBG_MSG(pLeftOver->szStorage);
pLeftOver->ucFontColor = pCurr->ucFontColor;
pLeftOver->usFontStyle = pCurr->usFontStyle;
pLeftOver->tFontRef = pCurr->tFontRef;
pLeftOver->usFontSize = pCurr->usFontSize;
pLeftOver->lStringWidth = lComputeStringWidth(
pLeftOver->szStorage,
pLeftOver->tNextFree,
pLeftOver->tFontRef,
pLeftOver->usFontSize);
pLeftOver->pPrev = NULL;
pLeftOver->pNext = pCurr->pNext;
if (pLeftOver->pNext != NULL) {
pLeftOver->pNext->pPrev = pLeftOver;
}
fail(!bCheckDoubleLinkedList(pLeftOver));
NO_DBG_MSG("pAnchor");
NO_DBG_HEX(pCurr->szStorage[iIndex]);
while (iIndex >= 0 && isspace((int)(UCHAR)pCurr->szStorage[iIndex])) {
iIndex--;
}
pCurr->tNextFree = (size_t)iIndex + 1;
pCurr->szStorage[pCurr->tNextFree] = '\0';
NO_DBG_MSG(pCurr->szStorage);
pCurr->lStringWidth = lComputeStringWidth(
pCurr->szStorage,
pCurr->tNextFree,
pCurr->tFontRef,
pCurr->usFontSize);
pCurr->pNext = NULL;
fail(!bCheckDoubleLinkedList(pAnchor));
return pLeftOver;
} /* end of pSplitList */
/*
* tNumber2Roman - convert a number to Roman Numerals
*
* returns the number of characters written
*/
size_t
tNumber2Roman(UINT uiNumber, BOOL bUpperCase, char *szOutput)
{
char *outp, *p, *q;
UINT uiNextVal, uiValue;
fail(szOutput == NULL);
uiNumber %= 4000; /* Very high numbers can't be represented */
if (uiNumber == 0) {
szOutput[0] = '\0';
return 0;
}
outp = szOutput;
p = bUpperCase ? "M\2D\5C\2L\5X\2V\5I" : "m\2d\5c\2l\5x\2v\5i";
uiValue = 1000;
for (;;) {
while (uiNumber >= uiValue) {
*outp++ = *p;
uiNumber -= uiValue;
}
if (uiNumber == 0) {
*outp = '\0';
fail(outp < szOutput);
return (size_t)(outp - szOutput);
}
q = p + 1;
uiNextVal = uiValue / (UINT)(UCHAR)*q;
if ((int)*q == 2) { /* magic */
uiNextVal /= (UINT)(UCHAR)*(q += 2);
}
if (uiNumber + uiNextVal >= uiValue) {
*outp++ = *++q;
uiNumber += uiNextVal;
} else {
p++;
uiValue /= (UINT)(UCHAR)(*p++);
}
}
} /* end of tNumber2Roman */
/*
* iNumber2Alpha - convert a number to alphabetic "numbers"
*
* returns the number of characters written
*/
size_t
tNumber2Alpha(UINT uiNumber, BOOL bUpperCase, char *szOutput)
{
char *outp;
UINT uiTmp;
fail(szOutput == NULL);
if (uiNumber == 0) {
szOutput[0] = '\0';
return 0;
}
outp = szOutput;
uiTmp = (UINT)(bUpperCase ? 'A': 'a');
if (uiNumber <= 26) {
uiNumber -= 1;
*outp++ = (char)(uiTmp + uiNumber);
} else if (uiNumber <= 26U + 26U*26U) {
uiNumber -= 26 + 1;
*outp++ = (char)(uiTmp + uiNumber / 26);
*outp++ = (char)(uiTmp + uiNumber % 26);
} else if (uiNumber <= 26U + 26U*26U + 26U*26U*26U) {
uiNumber -= 26 + 26*26 + 1;
*outp++ = (char)(uiTmp + uiNumber / (26*26));
*outp++ = (char)(uiTmp + uiNumber / 26 % 26);
*outp++ = (char)(uiTmp + uiNumber % 26);
}
*outp = '\0';
fail(outp < szOutput);
return (size_t)(outp - szOutput);
} /* end of tNumber2Alpha */
/*
* unincpy - copy a counted Unicode string to an single-byte string
*/
char *
unincpy(char *s1, const UCHAR *s2, size_t n)
{
char *pcDest;
ULONG ulChar;
size_t tLen;
USHORT usUni;
for (pcDest = s1, tLen = 0; tLen < n; pcDest++, tLen++) {
usUni = usGetWord(tLen * 2, s2);
if (usUni == 0) {
break;
}
ulChar = ulTranslateCharacters(usUni, 0, 8,
conversion_unknown, encoding_neutral, FALSE);
if (ulChar == IGNORE_CHARACTER) {
ulChar = (ULONG)'?';
}
*pcDest = (char)ulChar;
}
for (; tLen < n; tLen++) {
*pcDest++ = '\0';
}
return s1;
} /* end of unincpy */
/*
* unilen - calculate the length of a Unicode string
*
* returns the length in bytes
*/
size_t
unilen(const UCHAR *s)
{
size_t tLen;
USHORT usUni;
tLen = 0;
for (;;) {
usUni = usGetWord(tLen, s);
if (usUni == 0) {
return tLen;
}
tLen += 2;
}
} /* end of unilen */
/*
* szBaseName - get the basename of the specified filename
*/
const char *
szBasename(const char *szFilename)
{
const char *szTmp;
fail(szFilename == NULL);
if (szFilename == NULL || szFilename[0] == '\0') {
return "null";
}
szTmp = strrchr(szFilename, FILE_SEPARATOR[0]);
if (szTmp == NULL) {
return szFilename;
}
return ++szTmp;
} /* end of szBasename */
/*
* lComputeLeading - compute the leading
*
* NOTE: the fontsize is specified in half points
*
* Returns the leading in drawunits
*/
long
lComputeLeading(USHORT usFontSize)
{
long lLeading;
lLeading = (long)usFontSize * 500L;
if (usFontSize < 18) { /* Small text: 112% */
lLeading *= 112;
} else if (usFontSize < 28) { /* Normal text: 124% */
lLeading *= 124;
} else if (usFontSize < 48) { /* Small headlines: 104% */
lLeading *= 104;
} else { /* Large headlines: 100% */
lLeading *= 100;
}
lLeading = lMilliPoints2DrawUnits(lLeading);
lLeading += 50;
lLeading /= 100;
return lLeading;
} /* end of lComputeLeading */
/*
* Convert a UCS character to an UTF-8 string
*
* Returns the string length of the result
*/
size_t
tUcs2Utf8(ULONG ulChar, char *szResult, size_t tMaxResultLen)
{
if (szResult == NULL || tMaxResultLen == 0) {
return 0;
}
if (ulChar < 0x80 && tMaxResultLen >= 2) {
szResult[0] = (char)ulChar;
szResult[1] = '\0';
return 1;
}
if (ulChar < 0x800 && tMaxResultLen >= 3) {
szResult[0] = (char)(0xc0 | ulChar >> 6);
szResult[1] = (char)(0x80 | (ulChar & 0x3f));
szResult[2] = '\0';
return 2;
}
if (ulChar < 0x10000 && tMaxResultLen >= 4) {
szResult[0] = (char)(0xe0 | ulChar >> 12);
szResult[1] = (char)(0x80 | (ulChar >> 6 & 0x3f));
szResult[2] = (char)(0x80 | (ulChar & 0x3f));
szResult[3] = '\0';
return 3;
}
if (ulChar < 0x200000 && tMaxResultLen >= 5) {
szResult[0] = (char)(0xf0 | ulChar >> 18);
szResult[1] = (char)(0x80 | (ulChar >> 12 & 0x3f));
szResult[2] = (char)(0x80 | (ulChar >> 6 & 0x3f));
szResult[3] = (char)(0x80 | (ulChar & 0x3f));
szResult[4] = '\0';
return 4;
}
szResult[0] = '\0';
return 0;
} /* end of tUcs2Utf8 */
/*
* vGetBulletValue - get the bullet value for the conversing type and encoding
*/
void
vGetBulletValue(conversion_type eConversionType, encoding_type eEncoding,
char *szResult, size_t tMaxResultLen)
{
fail(szResult == NULL);
fail(tMaxResultLen < 2);
if (eEncoding == encoding_utf_8) {
(void)tUcs2Utf8(UNICODE_BULLET, szResult, tMaxResultLen);
} else {
szResult[0] = (char)ucGetBulletCharacter(eConversionType,
eEncoding);
szResult[1] = '\0';
}
} /* end of vGetBulletValue */
/*
* bAllZero - are all bytes zero?
*/
BOOL
bAllZero(const UCHAR *aucBytes, size_t tLength)
{
size_t tIndex;
if (aucBytes == NULL || tLength == 0) {
return TRUE;
}
for (tIndex = 0; tIndex < tLength; tIndex++) {
if (aucBytes[tIndex] != 0) {
return FALSE;
}
}
return TRUE;
} /* end of bAllZero */
#if !defined(__riscos)
/*
* GetCodesetFromLocale - get the codeset from the current locale
*
* Original version: Copyright (C) 1999 Bruno Haible
* Syntax:
* language[_territory][.codeset][@modifier][+special][,[sponsor][_revision]]
*
* Returns TRUE when sucessful, otherwise FALSE
*/
static BOOL
bGetCodesetFromLocale(char *szCodeset, size_t tMaxCodesetLength, BOOL *pbEuro)
{
#if !defined(__dos)
const char *szLocale;
const char *pcTmp;
size_t tIndex;
char szModifier[6];
#endif /* __dos */
if (pbEuro != NULL) {
*pbEuro = FALSE; /* Until proven otherwise */
}
if (szCodeset == NULL || tMaxCodesetLength == 0) {
return FALSE;
}
#if defined(__dos)
if (tMaxCodesetLength < 2 + sizeof(int) * 3 + 1) {
DBG_DEC(tMaxCodesetLength);
DBG_DEC(2 + sizeof(int) * 3 + 1);
return FALSE;
}
/* Get the active codepage from DOS */
sprintf(szCodeset, "cp%d", iGetCodepage());
DBG_MSG(szCodeset);
#else
/* Get the locale from the environment */
szLocale = getenv("LC_ALL");
if (szLocale == NULL || szLocale[0] == '\0') {
szLocale = getenv("LC_CTYPE");
if (szLocale == NULL || szLocale[0] == '\0') {
szLocale = getenv("LANG");
}
}
if (szLocale == NULL || szLocale[0] == '\0') {
/* No locale, so no codeset name and no modifier */
return FALSE;
}
DBG_MSG(szLocale);
pcTmp = strchr(szLocale, '.');
if (pcTmp == NULL) {
/* No codeset name */
szCodeset[0] = '\0';
} else {
/* Copy the codeset name */
pcTmp++;
for (tIndex = 0; tIndex < tMaxCodesetLength; tIndex++) {
if (*pcTmp == '@' || *pcTmp == '+' ||
*pcTmp == ',' || *pcTmp == '_' ||
*pcTmp == '\0') {
szCodeset[tIndex] = '\0';
break;
}
szCodeset[tIndex] = *pcTmp;
pcTmp++;
}
szCodeset[tMaxCodesetLength - 1] = '\0';
}
if (pbEuro == NULL) {
/* No need to get the modifier */
return TRUE;
}
pcTmp = strchr(szLocale, '@');
if (pcTmp != NULL) {
/* Copy the modifier */
pcTmp++;
for (tIndex = 0; tIndex < sizeof(szModifier); tIndex++) {
if (*pcTmp == '+' || *pcTmp == ',' ||
*pcTmp == '_' || *pcTmp == '\0') {
szModifier[tIndex] = '\0';
break;
}
szModifier[tIndex] = *pcTmp;
pcTmp++;
}
szModifier[sizeof(szModifier) - 1] = '\0';
*pbEuro = STRCEQ(szModifier, "Euro");
}
#endif /* __dos */
return TRUE;
} /* end of bGetCodesetFromLocale */
/*
* GetNormalizedCodeset - get the normalized codeset from the current locale
*
* Returns TRUE when sucessful, otherwise FALSE
*/
BOOL
bGetNormalizedCodeset(char *szCodeset, size_t tMaxCodesetLength, BOOL *pbEuro)
{
BOOL bOnlyDigits;
const char *pcSrc;
char *pcDest;
char *szTmp, *szCodesetNorm;
if (pbEuro != NULL) {
*pbEuro = FALSE; /* Until proven otherwise */
}
if (szCodeset == NULL || tMaxCodesetLength < 4) {
return FALSE;
}
/* Get the codeset name */
szTmp = xmalloc(tMaxCodesetLength - 3);
if (!bGetCodesetFromLocale(szTmp, tMaxCodesetLength - 3, pbEuro)) {
szTmp = xfree(szTmp);
return FALSE;
}
/* Normalize the codeset name */
szCodesetNorm = xmalloc(tMaxCodesetLength - 3);
bOnlyDigits = TRUE;
pcDest = szCodesetNorm;
for (pcSrc = szTmp; *pcSrc != '\0'; pcSrc++) {
if (isalnum(*pcSrc)) {
*pcDest = tolower(*pcSrc);
if (!isdigit(*pcDest)) {
bOnlyDigits = FALSE;
}
pcDest++;
}
}
*pcDest = '\0';
DBG_MSG(szCodesetNorm);
/* Add "iso" when szCodesetNorm contains all digits */
if (bOnlyDigits && szCodesetNorm[0] != '\0') {
fail(strlen(szCodesetNorm) + 3 >= tMaxCodesetLength);
sprintf(szCodeset, "iso%s", szCodesetNorm);
} else {
fail(strlen(szCodesetNorm) >= tMaxCodesetLength);
strncpy(szCodeset, szCodesetNorm, pcDest - szCodesetNorm + 1);
szCodeset[tMaxCodesetLength - 1] = '\0';
}
DBG_MSG(szCodeset);
/* Clean up and leave */
szCodesetNorm = xfree(szCodesetNorm);
szTmp = xfree(szTmp);
return TRUE;
} /* end of bGetNormalizedCodeset */
/*
* szGetDefaultMappingFile - get the default mapping file
*
* Returns the basename of the default mapping file
*/
const char *
szGetDefaultMappingFile(void)
{
static const struct {
const char *szCodeset;
const char *szMappingFile;
} atMappingFile[] = {
{ "iso88591", MAPPING_FILE_8859_1 },
{ "iso88592", MAPPING_FILE_8859_2 },
{ "iso88593", "8859-3.txt" },
{ "iso88594", "8859-4.txt" },
{ "iso88595", "8859-5.txt" },
{ "iso88596", MAPPING_FILE_8859_5 },
{ "iso88597", "8859-7.txt" },
{ "iso88598", "8859-8.txt" },
{ "iso88599", "8859-9.txt" },
{ "iso885910", "8859-10.txt" },
{ "iso885913", "8859-13.txt" },
{ "iso885914", "8859-14.txt" },
{ "iso885915", MAPPING_FILE_8859_15 },
{ "iso885916", "8859-16.txt" },
{ "koi8r", MAPPING_FILE_KOI8_R },
{ "koi8u", MAPPING_FILE_KOI8_U },
{ "utf8", MAPPING_FILE_UTF_8 },
{ "cp437", MAPPING_FILE_CP437 },
{ "cp850", "cp850.txt" },
{ "cp852", MAPPING_FILE_CP852 },
{ "cp862", "cp862.txt" },
{ "cp864", "cp864.txt" },
{ "cp866", MAPPING_FILE_CP866 },
{ "cp1250", MAPPING_FILE_CP1250 },
{ "cp1251", MAPPING_FILE_CP1251 },
{ "cp1252", "cp1252.txt" },
};
size_t tIndex;
BOOL bEuro;
char szCodeset[20];
szCodeset[0] = '\0';
bEuro = FALSE;
/* Get the normalized codeset name */
if (!bGetNormalizedCodeset(szCodeset, sizeof(szCodeset), &bEuro)) {
return MAPPING_FILE_8859_1;
}
if (szCodeset[0] == '\0') {
if (bEuro) {
/* Default mapping file (with Euro sign) */
return MAPPING_FILE_8859_15;
} else {
/* Default mapping file (without Euro sign) */
return MAPPING_FILE_8859_1;
}
}
/* Find the name in the table */
for (tIndex = 0; tIndex < elementsof(atMappingFile); tIndex++) {
if (STREQ(atMappingFile[tIndex].szCodeset, szCodeset)) {
return atMappingFile[tIndex].szMappingFile;
}
}
/* Default default mapping file */
#if defined(__dos)
return MAPPING_FILE_CP437;
#else
return MAPPING_FILE_8859_1;
#endif /* __dos */
} /* end of szGetDefaultMappingFile */
#endif /* !__riscos */
/*
* tConvertDTTM - convert Windows Date and Time format
*
* returns Unix time_t or -1
*/
time_t
tConvertDTTM(ULONG ulDTTM)
{
struct tm tTime;
time_t tResult;
if (ulDTTM == 0) {
return (time_t)-1;
}
memset(&tTime, 0, sizeof(tTime));
tTime.tm_min = (int)(ulDTTM & 0x0000003f);
tTime.tm_hour = (int)((ulDTTM & 0x000007c0) >> 6);
tTime.tm_mday = (int)((ulDTTM & 0x0000f800) >> 11);
tTime.tm_mon = (int)((ulDTTM & 0x000f0000) >> 16);
tTime.tm_year = (int)((ulDTTM & 0x1ff00000) >> 20);
tTime.tm_isdst = -1;
tTime.tm_mon--; /* From 01-12 to 00-11 */
tResult = mktime(&tTime);
NO_DBG_MSG(ctime(&tResult));
return tResult;
} /* end of tConvertDTTM */

876
src/notes.c Normal file
View File

@@ -0,0 +1,876 @@
/*
* notes.c
* Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
*
* Description:
* Functions to tell the difference between footnotes and endnotes
*/
#include "antiword.h"
/*
* Private structures to hide the way the information
* is stored from the rest of the program
*/
typedef struct footnote_local_tag {
footnote_block_type tInfo;
ULONG ulCharPosStart;
ULONG ulCharPosNext;
BOOL bUseful;
} footnote_local_type;
/* Variables needed to write the Footnote and Endnote information */
static ULONG *aulFootnoteList = NULL;
static size_t tFootnoteListLength = 0;
static ULONG *aulEndnoteList = NULL;
static size_t tEndnoteListLength = 0;
/* Variables needed to write the Footnote Text */
static footnote_local_type *pFootnoteText = NULL;
static size_t tFootnoteTextLength = 0;
/*
* Destroy the lists with footnote and endnote information
*/
void
vDestroyNotesInfoLists(void)
{
footnote_local_type *pRecord;
size_t tFootnote;
TRACE_MSG("vDestroyNotesInfoLists");
/* Free the lists and reset all control variables */
aulEndnoteList = xfree(aulEndnoteList);
aulFootnoteList = xfree(aulFootnoteList);
tEndnoteListLength = 0;
tFootnoteListLength = 0;
for (tFootnote = 0; tFootnote < tFootnoteTextLength; tFootnote++) {
pRecord = pFootnoteText + tFootnote;
pRecord->tInfo.szText = xfree(pRecord->tInfo.szText);
}
pFootnoteText = xfree(pFootnoteText);
tFootnoteTextLength = 0;
} /* end of vDestroyNotesInfoLists */
/*
* Build the list with footnote information for Word for DOS files
*/
static void
vGet0FootnotesInfoAndText(FILE *pFile, const UCHAR *aucHeader)
{
footnote_local_type *pCurr;
UCHAR *aucBuffer;
ULONG ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
ULONG ulCharPos, ulBeginNextBlock;
size_t tFootnotes, tFootnoteInfoLen;
size_t tIndex;
UCHAR aucTmp[2];
TRACE_MSG("vGet0FootnotesInfoAndText");
fail(pFile == NULL || aucHeader == NULL);
ulBeginOfText = 128;
NO_DBG_HEX(ulBeginOfText);
ulBeginFootnoteInfo = 128 * (ULONG)usGetWord(0x14, aucHeader);
DBG_HEX(ulBeginFootnoteInfo);
ulBeginNextBlock = 128 * (ULONG)usGetWord(0x16, aucHeader);
DBG_HEX(ulBeginNextBlock);
if (ulBeginFootnoteInfo == ulBeginNextBlock) {
DBG_MSG("No Footnotes in this document");
return;
}
/* Read the the number of footnotes + 1 */
if (!bReadBytes(aucTmp, 2, ulBeginFootnoteInfo, pFile)) {
return;
}
tFootnotes = (size_t)usGetWord(0, aucTmp);
if (tFootnotes < 2) {
DBG_MSG("No Footnotes in this document (2)");
}
DBG_DEC(tFootnotes);
tFootnoteInfoLen = 8 * tFootnotes;
aucBuffer = xmalloc(tFootnoteInfoLen);
if (!bReadBytes(aucBuffer,
tFootnoteInfoLen, ulBeginFootnoteInfo + 4, pFile)) {
aucBuffer = xfree(aucBuffer);
return;
}
DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
/* Get footnote information */
fail(tFootnoteListLength != 0);
tFootnoteListLength = tFootnotes - 1;
fail(tFootnoteListLength == 0);
fail(aulFootnoteList != NULL);
aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
ulOffset = ulGetLong(tIndex * 8, aucBuffer);
DBG_HEX(ulOffset);
ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
DBG_HEX(ulFileOffset);
aulFootnoteList[tIndex] = ulFileOffset;
}
/* Get footnote text */
fail(tFootnoteTextLength != 0);
tFootnoteTextLength = tFootnotes - 1;
fail(tFootnoteTextLength == 0);
fail(pFootnoteText != NULL);
pFootnoteText = xcalloc(tFootnoteTextLength,
sizeof(footnote_local_type));
for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
pCurr = pFootnoteText + tIndex;
pCurr->tInfo.szText = NULL;
ulOffset = ulGetLong(tIndex * 8 + 4, aucBuffer);
DBG_HEX(ulOffset);
ulCharPos = ulBeginOfText + ulOffset;
DBG_HEX(ulCharPos);
DBG_HEX(ulCharPos2FileOffset(ulCharPos));
pCurr->ulCharPosStart = ulCharPos;
ulOffset = ulGetLong((tIndex + 1) * 8 + 4, aucBuffer);
DBG_HEX(ulOffset);
ulCharPos = ulBeginOfText + ulOffset;
DBG_HEX(ulCharPos);
DBG_HEX(ulCharPos2FileOffset(ulCharPos));
pCurr->ulCharPosNext = ulCharPos;
pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
}
aucBuffer = xfree(aucBuffer);
} /* end of vGet0FootnotesInfoAndText */
/*
* Build the lists note information for Word for DOS files
*/
static void
vGet0NotesInfo(FILE *pFile, const UCHAR *aucHeader)
{
TRACE_MSG("vGet0NotesInfo");
vGet0FootnotesInfoAndText(pFile, aucHeader);
/* There are no endnotes in a Word for DOS file */
} /* end of vGet0NotesInfo */
/*
* Build the list with footnote information for WinWord 1/2 files
*/
static void
vGet2FootnotesInfo(FILE *pFile, const UCHAR *aucHeader)
{
UCHAR *aucBuffer;
ULONG ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
size_t tFootnoteInfoLen;
size_t tIndex;
TRACE_MSG("vGet2FootnotesInfo");
fail(pFile == NULL || aucHeader == NULL);
ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
NO_DBG_HEX(ulBeginOfText);
ulBeginFootnoteInfo = ulGetLong(0x64, aucHeader); /* fcPlcffndRef */
NO_DBG_HEX(ulBeginFootnoteInfo);
tFootnoteInfoLen = (size_t)usGetWord(0x68, aucHeader); /* cbPlcffndRef */
NO_DBG_DEC(tFootnoteInfoLen);
if (tFootnoteInfoLen < 10) {
DBG_MSG("No Footnotes in this document");
return;
}
aucBuffer = xmalloc(tFootnoteInfoLen);
if (!bReadBytes(aucBuffer,
tFootnoteInfoLen, ulBeginFootnoteInfo, pFile)) {
aucBuffer = xfree(aucBuffer);
return;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
fail(tFootnoteListLength != 0);
tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
fail(tFootnoteListLength == 0);
fail(aulFootnoteList != NULL);
aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
NO_DBG_HEX(ulOffset);
ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
NO_DBG_HEX(ulFileOffset);
aulFootnoteList[tIndex] = ulFileOffset;
}
aucBuffer = xfree(aucBuffer);
} /* end of vGet2FootnotesInfo */
/*
* Build the list with footnote text information for WinWord 1/2 files
*/
static void
vGet2FootnotesText(FILE *pFile, const UCHAR *aucHeader)
{
footnote_local_type *pCurr;
UCHAR *aucBuffer;
ULONG ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
size_t tFootnoteTextLen;
size_t tIndex;
TRACE_MSG("vGet2FootnotesText");
fail(pFile == NULL || aucHeader == NULL);
ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
ulBeginOfFootnotes += ulGetLong(0x34, aucHeader); /* ccpText */
NO_DBG_HEX(ulBeginOfFootnotes);
ulBeginFootnoteText = ulGetLong(0x6a, aucHeader); /* fcPlcffndTxt */
NO_DBG_HEX(ulBeginFootnoteText);
tFootnoteTextLen =
(size_t)usGetWord(0x6e, aucHeader); /* cbPlcffndTxt */
NO_DBG_DEC(tFootnoteTextLen);
if (tFootnoteTextLen < 12) {
DBG_MSG("No Footnote text in this document");
return;
}
aucBuffer = xmalloc(tFootnoteTextLen);
if (!bReadBytes(aucBuffer,
tFootnoteTextLen, ulBeginFootnoteText, pFile)) {
aucBuffer = xfree(aucBuffer);
return;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
fail(tFootnoteTextLength != 0);
tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
fail(tFootnoteTextLength == 0);
fail(pFootnoteText != NULL);
pFootnoteText = xcalloc(tFootnoteTextLength,
sizeof(footnote_local_type));
for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
pCurr = pFootnoteText + tIndex;
pCurr->tInfo.szText = NULL;
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
NO_DBG_HEX(ulOffset);
ulCharPos = ulBeginOfFootnotes + ulOffset;
NO_DBG_HEX(ulCharPos);
NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
pCurr->ulCharPosStart = ulCharPos;
ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
NO_DBG_HEX(ulOffset);
ulCharPos = ulBeginOfFootnotes + ulOffset;
NO_DBG_HEX(ulCharPos);
NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
pCurr->ulCharPosNext = ulCharPos;
pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
}
aucBuffer = xfree(aucBuffer);
} /* end of vGet2FootnotesText */
/*
* Build the lists note information for WinWord 1/2 files
*/
static void
vGet2NotesInfo(FILE *pFile, const UCHAR *aucHeader)
{
TRACE_MSG("vGet2NotesInfo");
vGet2FootnotesInfo(pFile, aucHeader);
vGet2FootnotesText(pFile, aucHeader);
/* There are no endnotes in a WinWord 1/2 file */
} /* end of vGet2NotesInfo */
/*
* Build the list with footnote information for Word 6/7 files
*/
static void
vGet6FootnotesInfo(FILE *pFile, ULONG ulStartBlock,
const ULONG *aulBBD, size_t tBBDLen,
const UCHAR *aucHeader)
{
UCHAR *aucBuffer;
ULONG ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
size_t tFootnoteInfoLen;
size_t tIndex;
TRACE_MSG("vGet6FootnotesInfo");
fail(pFile == NULL || aucHeader == NULL);
fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
fail(aulBBD == NULL);
ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
NO_DBG_HEX(ulBeginOfText);
ulBeginFootnoteInfo = ulGetLong(0x68, aucHeader); /* fcPlcffndRef */
NO_DBG_HEX(ulBeginFootnoteInfo);
tFootnoteInfoLen =
(size_t)ulGetLong(0x6c, aucHeader); /* lcbPlcffndRef */
NO_DBG_DEC(tFootnoteInfoLen);
if (tFootnoteInfoLen < 10) {
DBG_MSG("No Footnotes in this document");
return;
}
aucBuffer = xmalloc(tFootnoteInfoLen);
if (!bReadBuffer(pFile, ulStartBlock,
aulBBD, tBBDLen, BIG_BLOCK_SIZE,
aucBuffer, ulBeginFootnoteInfo, tFootnoteInfoLen)) {
aucBuffer = xfree(aucBuffer);
return;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
fail(tFootnoteListLength != 0);
tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
fail(tFootnoteListLength == 0);
fail(aulFootnoteList != NULL);
aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
NO_DBG_HEX(ulOffset);
ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
NO_DBG_HEX(ulFileOffset);
aulFootnoteList[tIndex] = ulFileOffset;
}
aucBuffer = xfree(aucBuffer);
} /* end of vGet6FootnotesInfo */
/*
* Build the list with footnote text information for Word 6/7 files
*/
static void
vGet6FootnotesText(FILE *pFile, ULONG ulStartBlock,
const ULONG *aulBBD, size_t tBBDLen,
const UCHAR *aucHeader)
{
footnote_local_type *pCurr;
UCHAR *aucBuffer;
ULONG ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
size_t tFootnoteTextLen;
size_t tIndex;
TRACE_MSG("vGet6FootnotesText");
fail(pFile == NULL || aucHeader == NULL);
fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
fail(aulBBD == NULL);
ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
ulBeginOfFootnotes += ulGetLong(0x34, aucHeader); /* ccpText */
NO_DBG_HEX(ulBeginOfFootnotes);
ulBeginFootnoteText = ulGetLong(0x70, aucHeader); /* fcPlcffndTxt */
NO_DBG_HEX(ulBeginFootnoteText);
tFootnoteTextLen =
(size_t)ulGetLong(0x74, aucHeader); /* lcbPlcffndTxt */
NO_DBG_DEC(tFootnoteTextLen);
if (tFootnoteTextLen < 12) {
DBG_MSG("No Footnote text in this document");
return;
}
aucBuffer = xmalloc(tFootnoteTextLen);
if (!bReadBuffer(pFile, ulStartBlock,
aulBBD, tBBDLen, BIG_BLOCK_SIZE,
aucBuffer, ulBeginFootnoteText, tFootnoteTextLen)) {
aucBuffer = xfree(aucBuffer);
return;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
fail(tFootnoteTextLength != 0);
tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
fail(tFootnoteTextLength == 0);
fail(pFootnoteText != NULL);
pFootnoteText = xcalloc(tFootnoteTextLength,
sizeof(footnote_local_type));
for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
pCurr = pFootnoteText + tIndex;
pCurr->tInfo.szText = NULL;
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
NO_DBG_HEX(ulOffset);
ulCharPos = ulBeginOfFootnotes + ulOffset;
NO_DBG_HEX(ulCharPos);
NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
pCurr->ulCharPosStart = ulCharPos;
ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
NO_DBG_HEX(ulOffset);
ulCharPos = ulBeginOfFootnotes + ulOffset;
NO_DBG_HEX(ulCharPos);
NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
pCurr->ulCharPosNext = ulCharPos;
pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
}
aucBuffer = xfree(aucBuffer);
} /* end of vGet6FootnotesText */
/*
* Build the list with endnote information for Word 6/7 files
*/
static void
vGet6EndnotesInfo(FILE *pFile, ULONG ulStartBlock,
const ULONG *aulBBD, size_t tBBDLen,
const UCHAR *aucHeader)
{
UCHAR *aucBuffer;
ULONG ulFileOffset, ulBeginOfText, ulOffset, ulBeginEndnoteInfo;
size_t tEndnoteInfoLen;
size_t tIndex;
TRACE_MSG("vGet6EndnotesInfo");
fail(pFile == NULL || aucHeader == NULL);
fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
fail(aulBBD == NULL);
ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
NO_DBG_HEX(ulBeginOfText);
ulBeginEndnoteInfo = ulGetLong(0x1d2, aucHeader); /* fcPlcfendRef */
NO_DBG_HEX(ulBeginEndnoteInfo);
tEndnoteInfoLen =
(size_t)ulGetLong(0x1d6, aucHeader); /* lcbPlcfendRef */
NO_DBG_DEC(tEndnoteInfoLen);
if (tEndnoteInfoLen < 10) {
DBG_MSG("No Endnotes in this document");
return;
}
aucBuffer = xmalloc(tEndnoteInfoLen);
if (!bReadBuffer(pFile, ulStartBlock,
aulBBD, tBBDLen, BIG_BLOCK_SIZE,
aucBuffer, ulBeginEndnoteInfo, tEndnoteInfoLen)) {
aucBuffer = xfree(aucBuffer);
return;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tEndnoteInfoLen);
fail(tEndnoteListLength != 0);
tEndnoteListLength = (tEndnoteInfoLen - 4) / 6;
fail(tEndnoteListLength == 0);
fail(aulEndnoteList != NULL);
aulEndnoteList = xcalloc(tEndnoteListLength, sizeof(ULONG));
for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
NO_DBG_HEX(ulOffset);
ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
NO_DBG_HEX(ulFileOffset);
aulEndnoteList[tIndex] = ulFileOffset;
}
aucBuffer = xfree(aucBuffer);
} /* end of vGet6EndnotesInfo */
/*
* Build the lists note information for Word 6/7 files
*/
static void
vGet6NotesInfo(FILE *pFile, ULONG ulStartBlock,
const ULONG *aulBBD, size_t tBBDLen,
const UCHAR *aucHeader)
{
TRACE_MSG("vGet6NotesInfo");
vGet6FootnotesInfo(pFile, ulStartBlock,
aulBBD, tBBDLen, aucHeader);
vGet6FootnotesText(pFile, ulStartBlock,
aulBBD, tBBDLen, aucHeader);
vGet6EndnotesInfo(pFile, ulStartBlock,
aulBBD, tBBDLen, aucHeader);
} /* end of vGet6NotesInfo */
/*
* Build the list with footnote information for Word 8/9/10 files
*/
static void
vGet8FootnotesInfo(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader)
{
const ULONG *aulBlockDepot;
UCHAR *aucBuffer;
ULONG ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
size_t tFootnoteInfoLen, tBlockDepotLen, tBlockSize;
size_t tIndex;
TRACE_MSG("vGet8FootnotesInfo");
ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
NO_DBG_HEX(ulBeginOfText);
ulBeginFootnoteInfo = ulGetLong(0xaa, aucHeader); /* fcPlcffndRef */
NO_DBG_HEX(ulBeginFootnoteInfo);
tFootnoteInfoLen =
(size_t)ulGetLong(0xae, aucHeader); /* lcbPlcffndRef */
NO_DBG_DEC(tFootnoteInfoLen);
if (tFootnoteInfoLen < 10) {
DBG_MSG("No Footnotes in this document");
return;
}
NO_DBG_DEC(pPPS->tTable.ulSB);
NO_DBG_HEX(pPPS->tTable.ulSize);
if (pPPS->tTable.ulSize == 0) {
DBG_MSG("No footnotes information");
return;
}
if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
/* Use the Small Block Depot */
aulBlockDepot = aulSBD;
tBlockDepotLen = tSBDLen;
tBlockSize = SMALL_BLOCK_SIZE;
} else {
/* Use the Big Block Depot */
aulBlockDepot = aulBBD;
tBlockDepotLen = tBBDLen;
tBlockSize = BIG_BLOCK_SIZE;
}
aucBuffer = xmalloc(tFootnoteInfoLen);
if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
aulBlockDepot, tBlockDepotLen, tBlockSize,
aucBuffer, ulBeginFootnoteInfo, tFootnoteInfoLen)) {
aucBuffer = xfree(aucBuffer);
return;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
fail(tFootnoteListLength != 0);
tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
fail(tFootnoteListLength == 0);
fail(aulFootnoteList != NULL);
aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
NO_DBG_HEX(ulOffset);
ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
NO_DBG_HEX(ulFileOffset);
aulFootnoteList[tIndex] = ulFileOffset;
}
aucBuffer = xfree(aucBuffer);
} /* end of vGet8FootnotesInfo */
/*
* Build the list with footnote text information for Word 8/9/10 files
*/
static void
vGet8FootnotesText(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader)
{
footnote_local_type *pCurr;
const ULONG *aulBlockDepot;
UCHAR *aucBuffer;
ULONG ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
size_t tFootnoteTextLen, tBlockDepotLen, tBlockSize;
size_t tIndex;
TRACE_MSG("vGet8FootnotesText");
ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
ulBeginOfFootnotes += ulGetLong(0x4c, aucHeader); /* ccpText */
NO_DBG_HEX(ulBeginOfFootnotes);
ulBeginFootnoteText = ulGetLong(0xb2, aucHeader); /* fcPlcffndTxt */
NO_DBG_HEX(ulBeginFootnoteText);
tFootnoteTextLen =
(size_t)ulGetLong(0xb6, aucHeader); /* lcbPlcffndTxt */
NO_DBG_DEC(tFootnoteTextLen);
if (tFootnoteTextLen < 12) {
DBG_MSG("No Footnote text in this document");
return;
}
NO_DBG_DEC(pPPS->tTable.ulSB);
NO_DBG_HEX(pPPS->tTable.ulSize);
if (pPPS->tTable.ulSize == 0) {
DBG_MSG("No footnote text information");
return;
}
if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
/* Use the Small Block Depot */
aulBlockDepot = aulSBD;
tBlockDepotLen = tSBDLen;
tBlockSize = SMALL_BLOCK_SIZE;
} else {
/* Use the Big Block Depot */
aulBlockDepot = aulBBD;
tBlockDepotLen = tBBDLen;
tBlockSize = BIG_BLOCK_SIZE;
}
aucBuffer = xmalloc(tFootnoteTextLen);
if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
aulBlockDepot, tBlockDepotLen, tBlockSize,
aucBuffer, ulBeginFootnoteText, tFootnoteTextLen)) {
aucBuffer = xfree(aucBuffer);
return;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
fail(tFootnoteTextLength != 0);
tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
fail(tFootnoteTextLength == 0);
fail(pFootnoteText != NULL);
pFootnoteText = xcalloc(tFootnoteTextLength,
sizeof(footnote_local_type));
for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
pCurr = pFootnoteText + tIndex;
pCurr->tInfo.szText = NULL;
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
NO_DBG_HEX(ulOffset);
ulCharPos = ulBeginOfFootnotes + ulOffset;
NO_DBG_HEX(ulCharPos);
NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
pCurr->ulCharPosStart = ulCharPos;
ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
NO_DBG_HEX(ulOffset);
ulCharPos = ulBeginOfFootnotes + ulOffset;
NO_DBG_HEX(ulCharPos);
NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
pCurr->ulCharPosNext = ulCharPos;
pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
}
aucBuffer = xfree(aucBuffer);
} /* end of vGet8FootnotesText */
/*
* Build the list with endnote information for Word 8/9/10 files
*/
static void
vGet8EndnotesInfo(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader)
{
const ULONG *aulBlockDepot;
UCHAR *aucBuffer;
ULONG ulFileOffset, ulBeginOfText, ulOffset, ulBeginEndnoteInfo;
size_t tEndnoteInfoLen, tBlockDepotLen, tBlockSize;
size_t tIndex;
TRACE_MSG("vGet8EndnotesInfo");
ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
NO_DBG_HEX(ulBeginOfText);
ulBeginEndnoteInfo = ulGetLong(0x20a, aucHeader); /* fcPlcfendRef */
NO_DBG_HEX(ulBeginEndnoteInfo);
tEndnoteInfoLen = (size_t)ulGetLong(0x20e, aucHeader); /* lcbPlcfendRef */
NO_DBG_DEC(tEndnoteInfoLen);
if (tEndnoteInfoLen < 10) {
DBG_MSG("No endnotes in this document");
return;
}
NO_DBG_DEC(pPPS->tTable.ulSB);
NO_DBG_HEX(pPPS->tTable.ulSize);
if (pPPS->tTable.ulSize == 0) {
DBG_MSG("No endnotes information");
return;
}
if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
/* Use the Small Block Depot */
aulBlockDepot = aulSBD;
tBlockDepotLen = tSBDLen;
tBlockSize = SMALL_BLOCK_SIZE;
} else {
/* Use the Big Block Depot */
aulBlockDepot = aulBBD;
tBlockDepotLen = tBBDLen;
tBlockSize = BIG_BLOCK_SIZE;
}
aucBuffer = xmalloc(tEndnoteInfoLen);
if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
aulBlockDepot, tBlockDepotLen, tBlockSize,
aucBuffer, ulBeginEndnoteInfo, tEndnoteInfoLen)) {
aucBuffer = xfree(aucBuffer);
return;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tEndnoteInfoLen);
fail(tEndnoteListLength != 0);
tEndnoteListLength = (tEndnoteInfoLen - 4) / 6;
fail(tEndnoteListLength == 0);
fail(aulEndnoteList != NULL);
aulEndnoteList = xcalloc(tEndnoteListLength, sizeof(ULONG));
for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
NO_DBG_HEX(ulOffset);
ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
NO_DBG_HEX(ulFileOffset);
aulEndnoteList[tIndex] = ulFileOffset;
}
aucBuffer = xfree(aucBuffer);
} /* end of vGet8EndnotesInfo */
/*
* Build the lists with footnote and endnote information for Word 8/9/10 files
*/
static void
vGet8NotesInfo(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader)
{
TRACE_MSG("vGet8NotesInfo");
vGet8FootnotesInfo(pFile, pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
vGet8FootnotesText(pFile, pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
vGet8EndnotesInfo(pFile, pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
} /* end of vGet8NotesInfo */
/*
* Build the lists with footnote and endnote information
*/
void
vGetNotesInfo(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader, int iWordVersion)
{
TRACE_MSG("vGetNotesInfo");
fail(pFile == NULL);
fail(pPPS == NULL && iWordVersion >= 6);
fail(aulBBD == NULL && tBBDLen != 0);
fail(aulSBD == NULL && tSBDLen != 0);
fail(aucHeader == NULL);
switch (iWordVersion) {
case 0:
vGet0NotesInfo(pFile, aucHeader);
break;
case 1:
case 2:
vGet2NotesInfo(pFile, aucHeader);
break;
case 4:
case 5:
break;
case 6:
case 7:
vGet6NotesInfo(pFile, pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen, aucHeader);
break;
case 8:
vGet8NotesInfo(pFile, pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
break;
default:
werr(0, "Sorry, no notes information");
break;
}
} /* end of vGetNotesInfo */
/*
* vPrepareFootnoteText - prepare the footnote text
*/
void
vPrepareFootnoteText(FILE *pFile)
{
footnote_local_type *pCurr;
size_t tFootnote;
fail(pFile == NULL);
fail(pFootnoteText == NULL && tFootnoteTextLength != 0);
if (pFootnoteText == NULL || tFootnoteTextLength == 0) {
/* No information */
return;
}
/* Fill text and useful-ness */
for (tFootnote = 0; tFootnote < tFootnoteTextLength; tFootnote++) {
pCurr = pFootnoteText + tFootnote;
pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
if (pCurr->bUseful) {
pCurr->tInfo.szText = szFootnoteDecryptor(pFile,
pCurr->ulCharPosStart,
pCurr->ulCharPosNext);
} else {
pCurr->tInfo.szText = NULL;
}
}
} /* end of vPrepareFootnoteText */
/*
* szGetFootnootText - get the text of the spefified footnote
*/
const char *
szGetFootnootText(UINT uiFootnoteIndex)
{
if ((size_t)uiFootnoteIndex >= tFootnoteTextLength) {
return NULL;
}
return pFootnoteText[uiFootnoteIndex].tInfo.szText;
} /* end of szGetFootnootText */
/*
* Get the notetype of the note at the given fileoffset
*/
notetype_enum
eGetNotetype(ULONG ulFileOffset)
{
size_t tIndex;
TRACE_MSG("eGetNotetype");
fail(aulFootnoteList == NULL && tFootnoteListLength != 0);
fail(aulEndnoteList == NULL && tEndnoteListLength != 0);
/* Go for the easy answers first */
if (tFootnoteListLength == 0 && tEndnoteListLength == 0) {
return notetype_is_unknown;
}
if (tEndnoteListLength == 0) {
return notetype_is_footnote;
}
if (tFootnoteListLength == 0) {
return notetype_is_endnote;
}
/* No easy answer, so we search */
for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
if (aulFootnoteList[tIndex] == ulFileOffset) {
return notetype_is_footnote;
}
}
for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
if (aulEndnoteList[tIndex] == ulFileOffset) {
return notetype_is_endnote;
}
}
/* Not found */
return notetype_is_unknown;
} /* end of eGetNotetype */

950
src/options.c Normal file
View File

@@ -0,0 +1,950 @@
/*
* options.c
* Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Read and write the options
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__riscos)
#include "DeskLib:Error.h"
#include "DeskLib:Wimp.h"
#else
#include <stdlib.h>
#if defined(__dos) || defined(N_PLAT_NLM)
extern int getopt(int, char **, const char *);
#else
#include <unistd.h>
#endif /* __dos */
#endif /* __riscos */
#include "antiword.h"
#if defined(__riscos)
#define PARAGRAPH_BREAK "set paragraph_break=%d"
#define AUTOFILETYPE "set autofiletype_allowed=%d"
#define USE_OUTLINEFONTS "set use_outlinefonts=%d"
#define SHOW_IMAGES "set show_images=%d"
#define HIDE_HIDDEN_TEXT "set hide_hidden_text=%d"
#define SCALE_FACTOR_START "set scale_factor_start=%d"
#else
#define LEAFNAME_SIZE (32+1)
#endif /* __riscos */
/* Current values for options */
static options_type tOptionsCurr;
#if defined(__riscos)
/* Temporary values for options */
static options_type tOptionsTemp;
#else
typedef struct papersize_tag {
char szName[16]; /* Papersize name */
USHORT usWidth; /* In points */
USHORT usHeight; /* In points */
} papersize_type;
static const papersize_type atPaperSizes[] = {
{ "10x14", 720, 1008 },
{ "a3", 842, 1191 },
{ "a4", 595, 842 },
{ "a5", 420, 595 },
{ "b4", 729, 1032 },
{ "b5", 516, 729 },
{ "executive", 540, 720 },
{ "folio", 612, 936 },
{ "legal", 612, 1008 },
{ "letter", 612, 792 },
{ "note", 540, 720 },
{ "quarto", 610, 780 },
{ "statement", 396, 612 },
{ "tabloid", 792, 1224 },
{ "", 0, 0 },
};
#endif /* __riscos */
/* Default values for options */
static const options_type tOptionsDefault = {
DEFAULT_SCREEN_WIDTH,
#if defined(__riscos)
conversion_draw,
#else
conversion_text,
#endif /* __riscos */
TRUE,
TRUE,
FALSE,
encoding_latin_1,
INT_MAX,
INT_MAX,
level_default,
#if defined(__riscos)
TRUE,
DEFAULT_SCALE_FACTOR,
#endif /* __riscos */
};
#if !defined(__riscos)
/*
* bCorrectPapersize - see if the papersize is correct
*
* TRUE if the papersize is correct, otherwise FALSE
*/
static BOOL
bCorrectPapersize(const char *szName, conversion_type eConversionType)
{
const papersize_type *pPaperSize;
for (pPaperSize = atPaperSizes;
pPaperSize->szName[0] != '\0';
pPaperSize++) {
if (!STRCEQ(pPaperSize->szName, szName)) {
continue;
}
DBG_DEC(pPaperSize->usWidth);
DBG_DEC(pPaperSize->usHeight);
tOptionsCurr.eConversionType = eConversionType;
tOptionsCurr.iPageHeight = (int)pPaperSize->usHeight;
tOptionsCurr.iPageWidth = (int)pPaperSize->usWidth;
return TRUE;
}
return FALSE;
} /* end of bCorrectPapersize */
/*
* szCreateSuffix - create a suffix for the file
*
* Returns the suffix
*/
static const char *
szCreateSuffix(const char *szLeafname)
{
const char *pcDot;
pcDot = strrchr(szLeafname, '.');
if (pcDot != NULL && STRCEQ(pcDot, ".txt")) {
/* There is already a .txt suffix, no need for another one */
return "";
}
return ".txt";
} /* end of szCreateSuffix */
/*
* eMappingFile2Encoding - convert the mapping file to an encoding
*/
static encoding_type
eMappingFile2Encoding(const char *szLeafname)
{
char szMappingFile[LEAFNAME_SIZE+4];
fail(szLeafname == NULL);
if (strlen(szLeafname) + 4 >= sizeof(szMappingFile)) {
DBG_MSG(szLeafname);
return encoding_latin_1;
}
sprintf(szMappingFile, "%s%s", szLeafname, szCreateSuffix(szLeafname));
DBG_MSG(szMappingFile);
if (STRCEQ(szMappingFile, MAPPING_FILE_UTF_8)) {
return encoding_utf_8;
}
if (STRCEQ(szMappingFile, MAPPING_FILE_CP852) ||
STRCEQ(szMappingFile, MAPPING_FILE_CP1250) ||
STRCEQ(szMappingFile, MAPPING_FILE_8859_2)) {
return encoding_latin_2;
}
if (STRCEQ(szMappingFile, MAPPING_FILE_KOI8_R) ||
STRCEQ(szMappingFile, MAPPING_FILE_KOI8_U) ||
STRCEQ(szMappingFile, MAPPING_FILE_CP866) ||
STRCEQ(szMappingFile, MAPPING_FILE_CP1251) ||
STRCEQ(szMappingFile, MAPPING_FILE_8859_5)) {
return encoding_cyrillic;
}
return encoding_latin_1;
} /* end of eMappingFile2Encoding */
#endif /* !__riscos */
/*
* pOpenCharacterMappingFile - open the mapping file
*
* Returns the file pointer or NULL
*/
static FILE *
pOpenCharacterMappingFile(const char *szLeafname)
{
#if !defined(__riscos)
FILE *pFile;
const char *szHome, *szAntiword, *szSuffix;
size_t tFilenameLen;
char szMappingFile[PATH_MAX+1];
#endif /* !__riscos */
if (szLeafname == NULL || szLeafname[0] == '\0') {
return NULL;
}
DBG_MSG(szLeafname);
#if defined(__riscos)
return fopen(szLeafname, "r");
#else
/* Set the suffix */
szSuffix = szCreateSuffix(szLeafname);
/* Set length */
tFilenameLen = strlen(szLeafname) + strlen(szSuffix);
/* Try the environment version of the mapping file */
szAntiword = szGetAntiwordDirectory();
if (szAntiword != NULL && szAntiword[0] != '\0') {
if (strlen(szAntiword) + tFilenameLen <
sizeof(szMappingFile) -
sizeof(FILE_SEPARATOR)) {
sprintf(szMappingFile,
"%s" FILE_SEPARATOR "%s%s",
szAntiword, szLeafname, szSuffix);
DBG_MSG(szMappingFile);
pFile = fopen(szMappingFile, "r");
if (pFile != NULL) {
return pFile;
}
} else {
werr(0, "Environment mappingfilename ignored");
}
}
/* Try the local version of the mapping file */
szHome = szGetHomeDirectory();
if (strlen(szHome) + tFilenameLen <
sizeof(szMappingFile) -
sizeof(ANTIWORD_DIR) -
2 * sizeof(FILE_SEPARATOR)) {
sprintf(szMappingFile,
"%s" FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR "%s%s",
szHome, szLeafname, szSuffix);
DBG_MSG(szMappingFile);
pFile = fopen(szMappingFile, "r");
if (pFile != NULL) {
return pFile;
}
} else {
werr(0, "Local mappingfilename too long, ignored");
}
/* Try the global version of the mapping file */
if (tFilenameLen <
sizeof(szMappingFile) -
sizeof(GLOBAL_ANTIWORD_DIR) -
sizeof(FILE_SEPARATOR)) {
sprintf(szMappingFile,
GLOBAL_ANTIWORD_DIR FILE_SEPARATOR "%s%s",
szLeafname, szSuffix);
DBG_MSG(szMappingFile);
pFile = fopen(szMappingFile, "r");
if (pFile != NULL) {
return pFile;
}
} else {
werr(0, "Global mappingfilename too long, ignored");
}
werr(0, "I can't open your mapping file (%s%s)\n"
"It is not in '%s" FILE_SEPARATOR ANTIWORD_DIR "' nor in '"
GLOBAL_ANTIWORD_DIR "'.", szLeafname, szSuffix, szHome);
return NULL;
#endif /* __riscos */
} /* end of pOpenCharacterMappingFile */
/*
* vCloseCharacterMappingFile - close the mapping file
*/
static void
vCloseCharacterMappingFile(FILE *pFile)
{
(void)fclose(pFile);
} /* end of pCloseCharacterMappingFile */
/*
* iReadOptions - read options
*
* returns: -1: error
* 0: help
* >0: index first file argument
*/
int
iReadOptions(int argc, char **argv)
{
#if defined(__riscos)
FILE *pFile;
const char *szAlphabet;
int iAlphabet;
char szLine[81];
#else
extern char *optarg;
extern int optind;
char *pcChar, *szTmp;
int iChar;
char szLeafname[LEAFNAME_SIZE];
#endif /* __riscos */
FILE *pCharacterMappingFile;
int iTmp;
BOOL bSuccess;
DBG_MSG("iReadOptions");
/* Defaults */
tOptionsCurr = tOptionsDefault;
#if defined(__riscos)
/* Choices file */
pFile = fopen("<AntiWord$ChoicesFile>", "r");
DBG_MSG_C(pFile == NULL, "Choices file not found");
DBG_HEX_C(pFile != NULL, pFile);
if (pFile != NULL) {
while (fgets(szLine, (int)sizeof(szLine), pFile) != NULL) {
DBG_MSG(szLine);
if (szLine[0] == '#' ||
szLine[0] == '\r' ||
szLine[0] == '\n') {
continue;
}
if (sscanf(szLine, PARAGRAPH_BREAK, &iTmp) == 1 &&
(iTmp == 0 ||
(iTmp >= MIN_SCREEN_WIDTH &&
iTmp <= MAX_SCREEN_WIDTH))) {
tOptionsCurr.iParagraphBreak = iTmp;
DBG_DEC(tOptionsCurr.iParagraphBreak);
} else if (sscanf(szLine, AUTOFILETYPE, &iTmp)
== 1) {
tOptionsCurr.bAutofiletypeAllowed =
iTmp != 0;
DBG_DEC(tOptionsCurr.bAutofiletypeAllowed);
} else if (sscanf(szLine, USE_OUTLINEFONTS, &iTmp)
== 1) {
tOptionsCurr.eConversionType =
iTmp == 0 ?
conversion_text : conversion_draw;
DBG_DEC(tOptionsCurr.eConversionType);
} else if (sscanf(szLine, SHOW_IMAGES, &iTmp)
== 1) {
tOptionsCurr.eImageLevel = iTmp != 0 ?
level_default : level_no_images;
} else if (sscanf(szLine, HIDE_HIDDEN_TEXT, &iTmp)
== 1) {
tOptionsCurr.bHideHiddenText = iTmp != 0;
DBG_DEC(tOptionsCurr.bHideHiddenText);
} else if (sscanf(szLine, SCALE_FACTOR_START, &iTmp)
== 1) {
if (iTmp >= MIN_SCALE_FACTOR &&
iTmp <= MAX_SCALE_FACTOR) {
tOptionsCurr.iScaleFactor = iTmp;
DBG_DEC(tOptionsCurr.iScaleFactor);
}
}
}
(void)fclose(pFile);
}
iAlphabet = iReadCurrentAlphabetNumber();
switch (iAlphabet) {
case 101: /* ISO-8859-1 aka Latin1 */
szAlphabet = "<AntiWord$Latin1>";
break;
case 112: /* ISO-8859-15 aka Latin9 */
szAlphabet = "<AntiWord$Latin9>";
break;
default:
werr(0, "Alphabet '%d' is not supported", iAlphabet);
return -1;
}
pCharacterMappingFile = pOpenCharacterMappingFile(szAlphabet);
if (pCharacterMappingFile != NULL) {
bSuccess = bReadCharacterMappingTable(pCharacterMappingFile);
vCloseCharacterMappingFile(pCharacterMappingFile);
} else {
bSuccess = FALSE;
}
return bSuccess ? 1 : -1;
#else
/* Environment */
szTmp = getenv("COLUMNS");
if (szTmp != NULL) {
DBG_MSG(szTmp);
iTmp = (int)strtol(szTmp, &pcChar, 10);
if (*pcChar == '\0') {
iTmp -= 4; /* This is for the edge */
if (iTmp < MIN_SCREEN_WIDTH) {
iTmp = MIN_SCREEN_WIDTH;
} else if (iTmp > MAX_SCREEN_WIDTH) {
iTmp = MAX_SCREEN_WIDTH;
}
tOptionsCurr.iParagraphBreak = iTmp;
DBG_DEC(tOptionsCurr.iParagraphBreak);
}
}
strncpy(szLeafname, szGetDefaultMappingFile(), sizeof(szLeafname) - 1);
szLeafname[sizeof(szLeafname) - 1] = '\0';
/* Command line */
while ((iChar = getopt(argc, argv, "La:fhi:m:p:rstw:x:")) != -1) {
switch (iChar) {
case 'L':
tOptionsCurr.bUseLandscape = TRUE;
break;
case 'a':
if (!bCorrectPapersize(optarg, conversion_pdf)) {
werr(0, "-a without a valid papersize");
return -1;
}
break;
case 'f':
tOptionsCurr.eConversionType = conversion_fmt_text;
break;
case 'h':
return 0;
case 'i':
iTmp = (int)strtol(optarg, &pcChar, 10);
if (*pcChar != '\0') {
break;
}
switch (iTmp) {
case 0:
tOptionsCurr.eImageLevel = level_gs_special;
break;
case 1:
tOptionsCurr.eImageLevel = level_no_images;
break;
case 2:
tOptionsCurr.eImageLevel = level_ps_2;
break;
case 3:
tOptionsCurr.eImageLevel = level_ps_3;
break;
default:
tOptionsCurr.eImageLevel = level_default;
break;
}
DBG_DEC(tOptionsCurr.eImageLevel);
break;
case 'm':
if (tOptionsCurr.eConversionType == conversion_xml) {
werr(0, "XML doesn't need a mapping file");
break;
}
strncpy(szLeafname, optarg, sizeof(szLeafname) - 1);
szLeafname[sizeof(szLeafname) - 1] = '\0';
DBG_MSG(szLeafname);
break;
case 'p':
if (!bCorrectPapersize(optarg, conversion_ps)) {
werr(0, "-p without a valid papersize");
return -1;
}
break;
case 'r':
tOptionsCurr.bRemoveRemovedText = FALSE;
break;
case 's':
tOptionsCurr.bHideHiddenText = FALSE;
break;
case 't':
tOptionsCurr.eConversionType = conversion_text;
break;
case 'w':
iTmp = (int)strtol(optarg, &pcChar, 10);
if (*pcChar == '\0') {
if (iTmp != 0 && iTmp < MIN_SCREEN_WIDTH) {
iTmp = MIN_SCREEN_WIDTH;
} else if (iTmp > MAX_SCREEN_WIDTH) {
iTmp = MAX_SCREEN_WIDTH;
}
tOptionsCurr.iParagraphBreak = iTmp;
DBG_DEC(tOptionsCurr.iParagraphBreak);
}
break;
case 'x':
if (STREQ(optarg, "db")) {
tOptionsCurr.iParagraphBreak = 0;
tOptionsCurr.eConversionType = conversion_xml;
strcpy(szLeafname, MAPPING_FILE_UTF_8);
} else {
werr(0, "-x %s is not supported", optarg);
return -1;
}
break;
default:
return -1;
}
}
tOptionsCurr.eEncoding = eMappingFile2Encoding(szLeafname);
DBG_DEC(tOptionsCurr.eEncoding);
if (tOptionsCurr.eConversionType == conversion_ps &&
tOptionsCurr.eEncoding == encoding_utf_8) {
werr(0,
"The combination PostScript and UTF-8 is not supported");
return -1;
}
if (tOptionsCurr.eConversionType == conversion_pdf &&
tOptionsCurr.eEncoding == encoding_utf_8) {
werr(0,
"The combination PDF and UTF-8 is not supported");
return -1;
}
if (tOptionsCurr.eConversionType == conversion_pdf &&
tOptionsCurr.eEncoding == encoding_cyrillic) {
werr(0,
"The combination PDF and Cyrillic is not supported");
return -1;
}
if (tOptionsCurr.eConversionType == conversion_ps ||
tOptionsCurr.eConversionType == conversion_pdf) {
/* PostScript or PDF mode */
if (tOptionsCurr.bUseLandscape) {
/* Swap the page height and width */
iTmp = tOptionsCurr.iPageHeight;
tOptionsCurr.iPageHeight = tOptionsCurr.iPageWidth;
tOptionsCurr.iPageWidth = iTmp;
}
/* The paragraph break depends on the width of the paper */
tOptionsCurr.iParagraphBreak = iMilliPoints2Char(
(long)tOptionsCurr.iPageWidth * 1000 -
lDrawUnits2MilliPoints(
PS_LEFT_MARGIN + PS_RIGHT_MARGIN));
DBG_DEC(tOptionsCurr.iParagraphBreak);
}
pCharacterMappingFile = pOpenCharacterMappingFile(szLeafname);
if (pCharacterMappingFile != NULL) {
bSuccess = bReadCharacterMappingTable(pCharacterMappingFile);
vCloseCharacterMappingFile(pCharacterMappingFile);
} else {
bSuccess = FALSE;
}
return bSuccess ? optind : -1;
#endif /* __riscos */
} /* end of iReadOptions */
/*
* vGetOptions - get a copy of the current option values
*/
void
vGetOptions(options_type *pOptions)
{
fail(pOptions == NULL);
*pOptions = tOptionsCurr;
} /* end of vGetOptions */
#if defined(__riscos)
/*
* vWriteOptions - write the current options to the Options file
*/
static void
vWriteOptions(void)
{
FILE *pFile;
char *szOptionsFile;
TRACE_MSG("vWriteOptions");
szOptionsFile = getenv("AntiWord$ChoicesSave");
if (szOptionsFile == NULL) {
werr(0, "Warning: Name of the Choices file not found");
return;
}
if (!bMakeDirectory(szOptionsFile)) {
werr(0,
"Warning: I can't make a directory for the Choices file");
return;
}
pFile = fopen(szOptionsFile, "w");
if (pFile == NULL) {
werr(0, "Warning: I can't write the Choices file");
return;
}
(void)fprintf(pFile, PARAGRAPH_BREAK"\n",
tOptionsCurr.iParagraphBreak);
(void)fprintf(pFile, AUTOFILETYPE"\n",
tOptionsCurr.bAutofiletypeAllowed);
(void)fprintf(pFile, USE_OUTLINEFONTS"\n",
tOptionsCurr.eConversionType == conversion_text ? 0 : 1);
(void)fprintf(pFile, SHOW_IMAGES"\n",
tOptionsCurr.eImageLevel == level_no_images ? 0 : 1);
(void)fprintf(pFile, HIDE_HIDDEN_TEXT"\n",
tOptionsCurr.bHideHiddenText);
(void)fprintf(pFile, SCALE_FACTOR_START"\n",
tOptionsCurr.iScaleFactor);
(void)fclose(pFile);
} /* end of vWriteOptions */
/*
* vChoicesOpenAction - action to be taken when the Choices window opens
*/
void
vChoicesOpenAction(window_handle tWindow)
{
TRACE_MSG("vChoicesOpenAction");
tOptionsTemp = tOptionsCurr;
if (tOptionsTemp.iParagraphBreak == 0) {
vUpdateRadioButton(tWindow, CHOICES_BREAK_BUTTON, FALSE);
vUpdateRadioButton(tWindow, CHOICES_NO_BREAK_BUTTON, TRUE);
vUpdateWriteableNumber(tWindow, CHOICES_BREAK_WRITEABLE,
DEFAULT_SCREEN_WIDTH);
} else {
vUpdateRadioButton(tWindow, CHOICES_BREAK_BUTTON, TRUE);
vUpdateRadioButton(tWindow, CHOICES_NO_BREAK_BUTTON, FALSE);
vUpdateWriteableNumber(tWindow,
CHOICES_BREAK_WRITEABLE,
tOptionsTemp.iParagraphBreak);
}
vUpdateRadioButton(tWindow, CHOICES_AUTOFILETYPE_BUTTON,
tOptionsTemp.bAutofiletypeAllowed);
vUpdateRadioButton(tWindow, CHOICES_HIDDEN_TEXT_BUTTON,
tOptionsTemp.bHideHiddenText);
if (tOptionsTemp.eConversionType == conversion_draw) {
vUpdateRadioButton(tWindow,
CHOICES_WITH_IMAGES_BUTTON,
tOptionsTemp.eImageLevel != level_no_images);
vUpdateRadioButton(tWindow,
CHOICES_NO_IMAGES_BUTTON,
tOptionsTemp.eImageLevel == level_no_images);
vUpdateRadioButton(tWindow,
CHOICES_TEXTONLY_BUTTON, FALSE);
} else {
vUpdateRadioButton(tWindow,
CHOICES_WITH_IMAGES_BUTTON, FALSE);
vUpdateRadioButton(tWindow,
CHOICES_NO_IMAGES_BUTTON, FALSE);
vUpdateRadioButton(tWindow,
CHOICES_TEXTONLY_BUTTON, TRUE);
}
vUpdateWriteableNumber(tWindow,
CHOICES_SCALE_WRITEABLE, tOptionsTemp.iScaleFactor);
TRACE_MSG("end of vChoicesOpenAction");
} /* end of vChoicesOpenAction */
/*
* vDefaultButtonAction - action when the default button is clicked
*/
static void
vDefaultButtonAction(window_handle tWindow)
{
TRACE_MSG("vDefaultButtonAction");
tOptionsTemp = tOptionsDefault;
vUpdateRadioButton(tWindow, CHOICES_BREAK_BUTTON, TRUE);
vUpdateRadioButton(tWindow, CHOICES_NO_BREAK_BUTTON, FALSE);
vUpdateWriteableNumber(tWindow, CHOICES_BREAK_WRITEABLE,
tOptionsTemp.iParagraphBreak);
vUpdateRadioButton(tWindow, CHOICES_AUTOFILETYPE_BUTTON,
tOptionsTemp.bAutofiletypeAllowed);
vUpdateRadioButton(tWindow, CHOICES_HIDDEN_TEXT_BUTTON,
tOptionsTemp.bHideHiddenText);
vUpdateRadioButton(tWindow, CHOICES_WITH_IMAGES_BUTTON,
tOptionsTemp.eConversionType == conversion_draw &&
tOptionsTemp.eImageLevel != level_no_images);
vUpdateRadioButton(tWindow, CHOICES_NO_IMAGES_BUTTON,
tOptionsTemp.eConversionType == conversion_draw &&
tOptionsTemp.eImageLevel == level_no_images);
vUpdateRadioButton(tWindow, CHOICES_TEXTONLY_BUTTON,
tOptionsTemp.eConversionType == conversion_text);
vUpdateWriteableNumber(tWindow, CHOICES_SCALE_WRITEABLE,
tOptionsTemp.iScaleFactor);
} /* end of vDefaultButtonAction */
/*
* vApplyButtonAction - action to be taken when the OK button is clicked
*/
static void
vApplyButtonAction(void)
{
TRACE_MSG("vApplyButtonAction");
tOptionsCurr = tOptionsTemp;
} /* end of vApplyButtonAction */
/*
* vSaveButtonAction - action to be taken when the save button is clicked
*/
static void
vSaveButtonAction(void)
{
TRACE_MSG("vSaveButtonAction");
vApplyButtonAction();
vWriteOptions();
} /* end of vSaveButtonAction */
/*
* vSetParagraphBreak - set the paragraph break to the given number
*/
static void
vSetParagraphBreak(window_handle tWindow, int iNumber)
{
tOptionsTemp.iParagraphBreak = iNumber;
if (tOptionsTemp.iParagraphBreak == 0) {
return;
}
vUpdateWriteableNumber(tWindow,
CHOICES_BREAK_WRITEABLE,
tOptionsTemp.iParagraphBreak);
} /* end of vSetParagraphBreak */
/*
* vChangeParagraphBreak - change the paragraph break with the given number
*/
static void
vChangeParagraphBreak(window_handle tWindow, int iNumber)
{
int iTmp;
iTmp = tOptionsTemp.iParagraphBreak + iNumber;
if (iTmp < MIN_SCREEN_WIDTH || iTmp > MAX_SCREEN_WIDTH) {
/* Ignore */
return;
}
tOptionsTemp.iParagraphBreak = iTmp;
vUpdateWriteableNumber(tWindow,
CHOICES_BREAK_WRITEABLE,
tOptionsTemp.iParagraphBreak);
} /* end of vChangeParagraphBreak */
/*
* vChangeAutofiletype - invert the permission to autofiletype
*/
static void
vChangeAutofiletype(window_handle tWindow)
{
tOptionsTemp.bAutofiletypeAllowed =
!tOptionsTemp.bAutofiletypeAllowed;
vUpdateRadioButton(tWindow,
CHOICES_AUTOFILETYPE_BUTTON,
tOptionsTemp.bAutofiletypeAllowed);
} /* end of vChangeAutofiletype */
/*
* vChangeHiddenText - invert the hide/show hidden text
*/
static void
vChangeHiddenText(window_handle tWindow)
{
tOptionsTemp.bHideHiddenText = !tOptionsTemp.bHideHiddenText;
vUpdateRadioButton(tWindow,
CHOICES_HIDDEN_TEXT_BUTTON,
tOptionsTemp.bHideHiddenText);
} /* end of vChangeHiddenText */
/*
* vUseFontsImages - use outline fonts, show images
*/
static void
vUseFontsImages(BOOL bUseOutlineFonts, BOOL bShowImages)
{
tOptionsTemp.eConversionType =
bUseOutlineFonts ? conversion_draw : conversion_text;
tOptionsTemp.eImageLevel =
bUseOutlineFonts && bShowImages ?
level_default : level_no_images;
} /* end of vUseFontsImages */
/*
* vSetScaleFactor - set the scale factor to the given number
*/
static void
vSetScaleFactor(window_handle tWindow, int iNumber)
{
tOptionsTemp.iScaleFactor = iNumber;
vUpdateWriteableNumber(tWindow,
CHOICES_SCALE_WRITEABLE,
tOptionsTemp.iScaleFactor);
} /* end of vSetScaleFactor */
/*
* vChangeScaleFactor - change the scale factor with the given number
*/
static void
vChangeScaleFactor(window_handle tWindow, int iNumber)
{
int iTmp;
iTmp = tOptionsTemp.iScaleFactor + iNumber;
if (iTmp < MIN_SCALE_FACTOR || iTmp > MAX_SCALE_FACTOR) {
/* Ignore */
return;
}
tOptionsTemp.iScaleFactor = iTmp;
vUpdateWriteableNumber(tWindow,
CHOICES_SCALE_WRITEABLE,
tOptionsTemp.iScaleFactor);
} /* end of vChangeScaleFactor */
/*
* bChoicesMouseClick - handle a mouse click in the Choices window
*/
BOOL
bChoicesMouseClick(event_pollblock *pEvent, void *pvReference)
{
icon_handle tAction;
mouse_block *pMouse;
BOOL bCloseWindow;
TRACE_MSG("bChoicesMouseClick");
fail(pEvent == NULL);
fail(pEvent->type != event_CLICK);
pMouse = &pEvent->data.mouse;
if (!pMouse->button.data.select && !pMouse->button.data.adjust) {
/* Not handled here */
DBG_HEX(pMouse->button.value);
return FALSE;
}
/* Which action should be taken */
tAction = pMouse->icon;
if (pMouse->button.data.adjust) {
/* The adjust button reverses the direction */
switch (pMouse->icon) {
case CHOICES_BREAK_UP_BUTTON:
tAction = CHOICES_BREAK_DOWN_BUTTON;
break;
case CHOICES_BREAK_DOWN_BUTTON:
tAction = CHOICES_BREAK_UP_BUTTON;
break;
case CHOICES_SCALE_UP_BUTTON:
tAction = CHOICES_SCALE_DOWN_BUTTON;
break;
case CHOICES_SCALE_DOWN_BUTTON:
tAction = CHOICES_SCALE_UP_BUTTON;
break;
default:
break;
}
}
/* Actions */
bCloseWindow = FALSE;
switch (tAction) {
case CHOICES_DEFAULT_BUTTON:
vDefaultButtonAction(pMouse->window);
break;
case CHOICES_SAVE_BUTTON:
vSaveButtonAction();
break;
case CHOICES_CANCEL_BUTTON:
bCloseWindow = TRUE;
break;
case CHOICES_APPLY_BUTTON:
vApplyButtonAction();
bCloseWindow = TRUE;
break;
case CHOICES_BREAK_BUTTON:
vSetParagraphBreak(pMouse->window, DEFAULT_SCREEN_WIDTH);
break;
case CHOICES_BREAK_UP_BUTTON:
vChangeParagraphBreak(pMouse->window, 1);
break;
case CHOICES_BREAK_DOWN_BUTTON:
vChangeParagraphBreak(pMouse->window, -1);
break;
case CHOICES_NO_BREAK_BUTTON:
vSetParagraphBreak(pMouse->window, 0);
break;
case CHOICES_AUTOFILETYPE_BUTTON:
vChangeAutofiletype(pMouse->window);
break;
case CHOICES_HIDDEN_TEXT_BUTTON:
vChangeHiddenText(pMouse->window);
break;
case CHOICES_WITH_IMAGES_BUTTON:
vUseFontsImages(TRUE, TRUE);
break;
case CHOICES_NO_IMAGES_BUTTON:
vUseFontsImages(TRUE, FALSE);
break;
case CHOICES_TEXTONLY_BUTTON:
vUseFontsImages(FALSE, FALSE);
break;
case CHOICES_SCALE_UP_BUTTON:
vChangeScaleFactor(pMouse->window, 5);
break;
case CHOICES_SCALE_DOWN_BUTTON:
vChangeScaleFactor(pMouse->window, -5);
break;
default:
DBG_DEC(pMouse->icon);
break;
}
if (bCloseWindow) {
Error_CheckFatal(Wimp_CloseWindow(pMouse->window));
}
return TRUE;
} /* end of bChoicesMouseClick */
/*
* bChoicesKeyPressed - handle a key in the Choices window
*/
BOOL
bChoicesKeyPressed(event_pollblock *pEvent, void *pvReference)
{
icon_block tIcon;
caret_block *pCaret;
char *pcChar;
int iNumber;
DBG_MSG("bChoicesKeyPressed");
fail(pEvent == NULL);
fail(pEvent->type != event_KEY);
if (pEvent->data.key.code != '\r') {
Error_CheckFatal(Wimp_ProcessKey(pEvent->data.key.code));
return TRUE;
}
pCaret = &pEvent->data.key.caret;
Error_CheckFatal(Wimp_GetIconState(pCaret->window, pCaret->icon, &tIcon));
if (!tIcon.flags.data.text || !tIcon.flags.data.indirected) {
werr(1, "Icon %d must be indirected text", (int)pCaret->icon);
}
iNumber = (int)strtol(tIcon.data.indirecttext.buffer, &pcChar, 10);
switch(pCaret->icon) {
case CHOICES_BREAK_WRITEABLE:
if (*pcChar != '\0' && *pcChar != '\r') {
DBG_DEC(*pcChar);
iNumber = DEFAULT_SCREEN_WIDTH;
} else if (iNumber < MIN_SCREEN_WIDTH) {
iNumber = MIN_SCREEN_WIDTH;
} else if (iNumber > MAX_SCREEN_WIDTH) {
iNumber = MAX_SCREEN_WIDTH;
}
vSetParagraphBreak(pCaret->window, iNumber);
break;
case CHOICES_SCALE_WRITEABLE:
if (*pcChar != '\0' && *pcChar != '\r') {
DBG_DEC(*pcChar);
iNumber = DEFAULT_SCALE_FACTOR;
} else if (iNumber < MIN_SCALE_FACTOR) {
iNumber = MIN_SCALE_FACTOR;
} else if (iNumber > MAX_SCALE_FACTOR) {
iNumber = MAX_SCALE_FACTOR;
}
vSetScaleFactor(pCaret->window, iNumber);
break;
default:
DBG_DEC(pCaret->icon);
break;
}
return TRUE;
} /* end of bChoicesKeyPressed */
#endif /* __riscos */

768
src/out2window.c Normal file
View File

@@ -0,0 +1,768 @@
/*
* out2window.c
* Copyright (C) 1998-2005 A.J. van Os; Released under GPL
*
* Description:
* Output to a text window
*/
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "antiword.h"
/* Used for numbering the chapters */
static unsigned int auiHdrCounter[9];
/*
* vString2Diagram - put a string into a diagram
*/
static void
vString2Diagram(diagram_type *pDiag, output_type *pAnchor)
{
output_type *pOutput;
long lWidth;
USHORT usMaxFontSize;
TRACE_MSG("vString2Diagram");
fail(pDiag == NULL);
fail(pAnchor == NULL);
/* Compute the maximum fontsize in this string */
usMaxFontSize = MIN_FONT_SIZE;
for (pOutput = pAnchor; pOutput != NULL; pOutput = pOutput->pNext) {
if (pOutput->usFontSize > usMaxFontSize) {
usMaxFontSize = pOutput->usFontSize;
}
}
/* Goto the next line */
vMove2NextLine(pDiag, pAnchor->tFontRef, usMaxFontSize);
/* Output all substrings */
for (pOutput = pAnchor; pOutput != NULL; pOutput = pOutput->pNext) {
lWidth = lMilliPoints2DrawUnits(pOutput->lStringWidth);
vSubstring2Diagram(pDiag, pOutput->szStorage,
pOutput->tNextFree, lWidth, pOutput->ucFontColor,
pOutput->usFontStyle, pOutput->tFontRef,
pOutput->usFontSize, usMaxFontSize);
}
/* Goto the start of the line */
pDiag->lXleft = 0;
TRACE_MSG("leaving vString2Diagram");
} /* end of vString2Diagram */
/*
* vSetLeftIndentation - set the left indentation of the specified diagram
*/
void
vSetLeftIndentation(diagram_type *pDiag, long lLeftIndentation)
{
long lX;
TRACE_MSG("vSetLeftIndentation");
fail(pDiag == NULL);
fail(lLeftIndentation < 0);
lX = lMilliPoints2DrawUnits(lLeftIndentation);
if (lX > 0) {
pDiag->lXleft = lX;
} else {
pDiag->lXleft = 0;
}
} /* end of vSetLeftIndentation */
/*
* lComputeNetWidth - compute the net string width
*/
static long
lComputeNetWidth(output_type *pAnchor)
{
output_type *pTmp;
long lNetWidth;
TRACE_MSG("lComputeNetWidth");
fail(pAnchor == NULL);
/* Step 1: Count all but the last sub-string */
lNetWidth = 0;
for (pTmp = pAnchor; pTmp->pNext != NULL; pTmp = pTmp->pNext) {
fail(pTmp->lStringWidth < 0);
lNetWidth += pTmp->lStringWidth;
}
fail(pTmp == NULL);
fail(pTmp->pNext != NULL);
/* Step 2: remove the white-space from the end of the string */
while (pTmp->tNextFree != 0 &&
isspace((int)(UCHAR)pTmp->szStorage[pTmp->tNextFree - 1])) {
pTmp->szStorage[pTmp->tNextFree - 1] = '\0';
pTmp->tNextFree--;
NO_DBG_DEC(pTmp->lStringWidth);
pTmp->lStringWidth = lComputeStringWidth(
pTmp->szStorage,
pTmp->tNextFree,
pTmp->tFontRef,
pTmp->usFontSize);
NO_DBG_DEC(pTmp->lStringWidth);
}
/* Step 3: Count the last sub-string */
lNetWidth += pTmp->lStringWidth;
return lNetWidth;
} /* end of lComputeNetWidth */
/*
* iComputeHoles - compute number of holes
* (A hole is a number of whitespace characters followed by a
* non-whitespace character)
*/
static int
iComputeHoles(output_type *pAnchor)
{
output_type *pTmp;
size_t tIndex;
int iCounter;
BOOL bWasSpace, bIsSpace;
TRACE_MSG("iComputeHoles");
fail(pAnchor == NULL);
iCounter = 0;
bIsSpace = FALSE;
/* Count the holes */
for (pTmp = pAnchor; pTmp != NULL; pTmp = pTmp->pNext) {
fail(pTmp->tNextFree != strlen(pTmp->szStorage));
for (tIndex = 0; tIndex <= pTmp->tNextFree; tIndex++) {
bWasSpace = bIsSpace;
bIsSpace = isspace((int)(UCHAR)pTmp->szStorage[tIndex]);
if (bWasSpace && !bIsSpace) {
iCounter++;
}
}
}
return iCounter;
} /* end of iComputeHoles */
/*
* vAlign2Window - Align a string and insert it into the text
*/
void
vAlign2Window(diagram_type *pDiag, output_type *pAnchor,
long lScreenWidth, UCHAR ucAlignment)
{
long lNetWidth, lLeftIndentation;
TRACE_MSG("vAlign2Window");
fail(pDiag == NULL || pAnchor == NULL);
fail(lScreenWidth < lChar2MilliPoints(MIN_SCREEN_WIDTH));
lNetWidth = lComputeNetWidth(pAnchor);
if (lScreenWidth > lChar2MilliPoints(MAX_SCREEN_WIDTH) ||
lNetWidth <= 0) {
/*
* Screenwidth is "infinite", so no alignment is possible
* Don't bother to align an empty line
*/
vString2Diagram(pDiag, pAnchor);
TRACE_MSG("leaving vAlign2Window #1");
return;
}
switch (ucAlignment) {
case ALIGNMENT_CENTER:
lLeftIndentation = (lScreenWidth - lNetWidth) / 2;
DBG_DEC_C(lLeftIndentation < 0, lLeftIndentation);
if (lLeftIndentation > 0) {
vSetLeftIndentation(pDiag, lLeftIndentation);
}
break;
case ALIGNMENT_RIGHT:
lLeftIndentation = lScreenWidth - lNetWidth;
DBG_DEC_C(lLeftIndentation < 0, lLeftIndentation);
if (lLeftIndentation > 0) {
vSetLeftIndentation(pDiag, lLeftIndentation);
}
break;
case ALIGNMENT_JUSTIFY:
case ALIGNMENT_LEFT:
default:
break;
}
vString2Diagram(pDiag, pAnchor);
TRACE_MSG("leaving vAlign2Window #2");
} /* end of vAlign2Window */
/*
* vJustify2Window - Justify a string and insert it into the text
*/
void
vJustify2Window(diagram_type *pDiag, output_type *pAnchor,
long lScreenWidth, long lRightIndentation, UCHAR ucAlignment)
{
output_type *pTmp;
char *pcNew, *pcOld, *szStorage;
long lNetWidth, lSpaceWidth, lToAdd;
int iFillerLen, iHoles;
TRACE_MSG("vJustify2Window");
fail(pDiag == NULL || pAnchor == NULL);
fail(lScreenWidth < MIN_SCREEN_WIDTH);
fail(lRightIndentation > 0);
if (ucAlignment != ALIGNMENT_JUSTIFY) {
vAlign2Window(pDiag, pAnchor, lScreenWidth, ucAlignment);
return;
}
lNetWidth = lComputeNetWidth(pAnchor);
if (lScreenWidth > lChar2MilliPoints(MAX_SCREEN_WIDTH) ||
lNetWidth <= 0) {
/*
* Screenwidth is "infinite", so justify is not possible
* Don't bother to justify an empty line
*/
vString2Diagram(pDiag, pAnchor);
TRACE_MSG("leaving vJustify2Window #1");
return;
}
/* Justify */
fail(ucAlignment != ALIGNMENT_JUSTIFY);
lSpaceWidth = lComputeStringWidth(" ", 1,
pAnchor->tFontRef, pAnchor->usFontSize);
lToAdd = lScreenWidth -
lNetWidth -
lDrawUnits2MilliPoints(pDiag->lXleft) +
lRightIndentation;
#if defined(DEBUG)
if (lToAdd / lSpaceWidth < -1) {
DBG_DEC(lSpaceWidth);
DBG_DEC(lToAdd);
DBG_DEC(lScreenWidth);
DBG_DEC(lNetWidth);
DBG_DEC(lDrawUnits2MilliPoints(pDiag->lXleft));
DBG_DEC(pDiag->lXleft);
DBG_DEC(lRightIndentation);
}
#endif /* DEBUG */
lToAdd /= lSpaceWidth;
DBG_DEC_C(lToAdd < 0, lToAdd);
if (lToAdd <= 0) {
vString2Diagram(pDiag, pAnchor);
TRACE_MSG("leaving vJustify2Window #2");
return;
}
/* Justify by adding spaces */
iHoles = iComputeHoles(pAnchor);
for (pTmp = pAnchor; pTmp != NULL; pTmp = pTmp->pNext) {
fail(pTmp->tNextFree != strlen(pTmp->szStorage));
fail(lToAdd < 0);
szStorage = xmalloc(pTmp->tNextFree + (size_t)lToAdd + 1);
pcNew = szStorage;
for (pcOld = pTmp->szStorage; *pcOld != '\0'; pcOld++) {
*pcNew++ = *pcOld;
if (*pcOld == ' ' &&
*(pcOld + 1) != ' ' &&
iHoles > 0) {
iFillerLen = (int)(lToAdd / iHoles);
lToAdd -= iFillerLen;
iHoles--;
for (; iFillerLen > 0; iFillerLen--) {
*pcNew++ = ' ';
}
}
}
*pcNew = '\0';
pTmp->szStorage = xfree(pTmp->szStorage);
pTmp->szStorage = szStorage;
pTmp->tStorageSize = pTmp->tNextFree + (size_t)lToAdd + 1;
pTmp->lStringWidth +=
(pcNew - szStorage - (long)pTmp->tNextFree) *
lSpaceWidth;
fail(pcNew < szStorage);
pTmp->tNextFree = (size_t)(pcNew - szStorage);
fail(pTmp->tNextFree != strlen(pTmp->szStorage));
}
DBG_DEC_C(lToAdd != 0, lToAdd);
vString2Diagram(pDiag, pAnchor);
TRACE_MSG("leaving vJustify2Window #3");
} /* end of vJustify2Window */
/*
* vResetStyles - reset the style information variables
*/
void
vResetStyles(void)
{
TRACE_MSG("vResetStyles");
(void)memset(auiHdrCounter, 0, sizeof(auiHdrCounter));
} /* end of vResetStyles */
/*
* tStyle2Window - Add the style characters to the line
*
* Returns the length of the resulting string
*/
size_t
tStyle2Window(char *szLine, size_t tLineSize, const style_block_type *pStyle,
const section_block_type *pSection)
{
char *pcTxt;
size_t tIndex, tStyleIndex;
BOOL bNeedPrevLvl;
level_type_enum eNumType;
UCHAR ucNFC;
TRACE_MSG("tStyle2Window");
fail(szLine == NULL || pStyle == NULL || pSection == NULL);
if (pStyle->usIstd == 0 || pStyle->usIstd > 9) {
szLine[0] = '\0';
return 0;
}
/* Set the numbers */
tStyleIndex = (size_t)pStyle->usIstd - 1;
for (tIndex = 0; tIndex < 9; tIndex++) {
if (tIndex == tStyleIndex) {
auiHdrCounter[tIndex]++;
} else if (tIndex > tStyleIndex) {
auiHdrCounter[tIndex] = 0;
} else if (auiHdrCounter[tIndex] == 0) {
auiHdrCounter[tIndex] = 1;
}
}
eNumType = eGetNumType(pStyle->ucNumLevel);
if (eNumType != level_type_outline) {
szLine[0] = '\0';
return 0;
}
/* Print the numbers */
pcTxt = szLine;
bNeedPrevLvl = (pSection->usNeedPrevLvl & BIT(tStyleIndex)) != 0;
for (tIndex = 0; tIndex <= tStyleIndex; tIndex++) {
if (tIndex == tStyleIndex ||
(bNeedPrevLvl && tIndex < tStyleIndex)) {
if (pcTxt - szLine >= tLineSize - 25) {
/* Prevent a possible buffer overflow */
DBG_DEC(pcTxt - szLine);
DBG_DEC(tLineSize - 25);
DBG_FIXME();
szLine[0] = '\0';
return 0;
}
ucNFC = pSection->aucNFC[tIndex];
switch(ucNFC) {
case LIST_ARABIC_NUM:
case LIST_NUMBER_TXT:
case LIST_ORDINAL_TXT:
pcTxt += sprintf(pcTxt, "%u",
auiHdrCounter[tIndex]);
break;
case LIST_UPPER_ROMAN:
case LIST_LOWER_ROMAN:
pcTxt += tNumber2Roman(
auiHdrCounter[tIndex],
ucNFC == LIST_UPPER_ROMAN,
pcTxt);
break;
case LIST_UPPER_ALPHA:
case LIST_LOWER_ALPHA:
pcTxt += tNumber2Alpha(
auiHdrCounter[tIndex],
ucNFC == LIST_UPPER_ALPHA,
pcTxt);
break;
case LIST_OUTLINE_NUM:
pcTxt += sprintf(pcTxt, "%02u",
auiHdrCounter[tIndex]);
break;
default:
DBG_DEC(ucNFC);
DBG_FIXME();
pcTxt += sprintf(pcTxt, "%u",
auiHdrCounter[tIndex]);
break;
}
if (tIndex < tStyleIndex) {
*pcTxt++ = '.';
} else if (tIndex == tStyleIndex) {
*pcTxt++ = ' ';
}
}
}
*pcTxt = '\0';
NO_DBG_MSG_C((int)pStyle->usIstd >= 1 &&
(int)pStyle->usIstd <= 9 &&
eNumType != level_type_none &&
eNumType != level_type_outline, szLine);
NO_DBG_MSG_C(szLine[0] != '\0', szLine);
fail(pcTxt < szLine);
return (size_t)(pcTxt - szLine);
} /* end of tStyle2Window */
/*
* vRemoveRowEnd - remove the end of table row indicator
*
* Remove the double TABLE_SEPARATOR characters from the end of the string.
* Special: remove the TABLE_SEPARATOR, 0x0a sequence
*/
static void
vRemoveRowEnd(char *szRowTxt)
{
int iLastIndex;
TRACE_MSG("vRemoveRowEnd");
fail(szRowTxt == NULL || szRowTxt[0] == '\0');
iLastIndex = (int)strlen(szRowTxt) - 1;
if (szRowTxt[iLastIndex] == TABLE_SEPARATOR ||
szRowTxt[iLastIndex] == (char)0x0a) {
szRowTxt[iLastIndex] = '\0';
iLastIndex--;
} else {
DBG_HEX(szRowTxt[iLastIndex]);
}
if (iLastIndex >= 0 && szRowTxt[iLastIndex] == (char)0x0a) {
szRowTxt[iLastIndex] = '\0';
iLastIndex--;
}
if (iLastIndex >= 0 && szRowTxt[iLastIndex] == TABLE_SEPARATOR) {
szRowTxt[iLastIndex] = '\0';
return;
}
DBG_DEC(iLastIndex);
DBG_HEX(szRowTxt[iLastIndex]);
DBG_MSG(szRowTxt);
} /* end of vRemoveRowEnd */
/*
* tComputeStringLengthMax - max string length in relation to max column width
*
* Return the maximum string length
*/
static size_t
tComputeStringLengthMax(const char *szString, size_t tColumnWidthMax)
{
const char *pcTmp;
size_t tLengthMax, tLenPrev, tLen, tWidth;
TRACE_MSG("tComputeStringLengthMax");
fail(szString == NULL);
fail(tColumnWidthMax == 0);
pcTmp = strchr(szString, '\n');
if (pcTmp != NULL) {
tLengthMax = (size_t)(pcTmp - szString + 1);
} else {
tLengthMax = strlen(szString);
}
if (tLengthMax == 0) {
return 0;
}
tLen = 0;
tWidth = 0;
for (;;) {
tLenPrev = tLen;
tLen += tGetCharacterLength(szString + tLen);
DBG_DEC_C(tLen > tLengthMax, tLen);
DBG_DEC_C(tLen > tLengthMax, tLengthMax);
fail(tLen > tLengthMax);
tWidth = tCountColumns(szString, tLen);
if (tWidth > tColumnWidthMax) {
return tLenPrev;
}
if (tLen >= tLengthMax) {
return tLengthMax;
}
}
} /* end of tComputeStringLengthMax */
/*
* tGetBreakingPoint - get the number of bytes that fit the column
*
* Returns the number of bytes that fit the column
*/
static size_t
tGetBreakingPoint(const char *szString,
size_t tLen, size_t tWidth, size_t tColumnWidthMax)
{
int iIndex;
TRACE_MSG("tGetBreakingPoint");
fail(szString == NULL);
fail(tLen > strlen(szString));
fail(tWidth > tColumnWidthMax);
if (tWidth < tColumnWidthMax ||
(tWidth == tColumnWidthMax &&
(szString[tLen] == ' ' ||
szString[tLen] == '\n' ||
szString[tLen] == '\0'))) {
/* The string already fits, do nothing */
return tLen;
}
/* Search for a breaking point */
for (iIndex = (int)tLen - 1; iIndex >= 0; iIndex--) {
if (szString[iIndex] == ' ') {
return (size_t)iIndex;
}
}
/* No breaking point found, just fill the column */
return tLen;
} /* end of tGetBreakingPoint */
/*
* tComputeColumnWidthMax - compute the maximum column width
*/
static size_t
tComputeColumnWidthMax(short sWidth, long lCharWidth, double dFactor)
{
size_t tColumnWidthMax;
TRACE_MSG("tComputeColumnWidthMax");
fail(sWidth < 0);
fail(lCharWidth <= 0);
fail(dFactor <= 0.0);
tColumnWidthMax = (size_t)(
(lTwips2MilliPoints(sWidth) * dFactor + lCharWidth / 2.0) /
lCharWidth);
if (tColumnWidthMax == 0) {
/* Minimum column width */
return 1;
}
if (tColumnWidthMax > 1) {
/* Make room for the TABLE_SEPARATOR_CHAR */
tColumnWidthMax--;
}
NO_DBG_DEC(tColumnWidthMax);
return tColumnWidthMax;
} /* end of tComputeColumnWidthMax */
/*
* vTableRow2Window - put a table row into a diagram
*/
void
vTableRow2Window(diagram_type *pDiag, output_type *pOutput,
const row_block_type *pRowInfo,
conversion_type eConversionType, int iParagraphBreak)
{
output_type tRow;
char *aszColTxt[TABLE_COLUMN_MAX];
char *szLine, *pcTxt;
double dMagnify;
long lCharWidthLarge, lCharWidthSmall;
size_t tColumnWidthTotal, atColumnWidthMax[TABLE_COLUMN_MAX];
size_t tSize, tColumnWidthMax, tWidth, tLen;
int iIndex, iNbrOfColumns, iTmp;
BOOL bNotReady;
TRACE_MSG("vTableRow2Window");
fail(pDiag == NULL || pOutput == NULL || pRowInfo == NULL);
fail(pOutput->szStorage == NULL);
fail(pOutput->pNext != NULL);
fail(iParagraphBreak < 0);
/* Character sizes */
lCharWidthLarge = lComputeStringWidth("W", 1,
pOutput->tFontRef, pOutput->usFontSize);
NO_DBG_DEC(lCharWidthLarge);
lCharWidthSmall = lComputeStringWidth("i", 1,
pOutput->tFontRef, pOutput->usFontSize);
NO_DBG_DEC(lCharWidthSmall);
/* For the time being: use a fixed width font */
fail(lCharWidthLarge != lCharWidthSmall);
vRemoveRowEnd(pOutput->szStorage);
/* Split the row text into a set of column texts */
aszColTxt[0] = pOutput->szStorage;
for (iNbrOfColumns = 1;
iNbrOfColumns < TABLE_COLUMN_MAX;
iNbrOfColumns++) {
aszColTxt[iNbrOfColumns] =
strchr(aszColTxt[iNbrOfColumns - 1],
TABLE_SEPARATOR);
if (aszColTxt[iNbrOfColumns] == NULL) {
break;
}
*aszColTxt[iNbrOfColumns] = '\0';
aszColTxt[iNbrOfColumns]++;
NO_DBG_DEC(iNbrOfColumns);
NO_DBG_MSG(aszColTxt[iNbrOfColumns]);
}
/* Work around a bug in Word */
while (iNbrOfColumns > (int)pRowInfo->ucNumberOfColumns &&
pRowInfo->asColumnWidth[iNbrOfColumns] == 0) {
iNbrOfColumns--;
}
DBG_DEC_C(iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns,
iNbrOfColumns);
DBG_DEC_C(iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns,
pRowInfo->ucNumberOfColumns);
if (iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns) {
werr(0, "Skipping an unmatched table row");
return;
}
#if defined(__FULL_TEXT_SEARCH)
/* No table formatting: use for full-text search (untested) */
for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
fprintf(pDiag->pOutFile, "%s\n" , aszColTxt[iIndex]);
}
#else
if (bAddTableRow(pDiag, aszColTxt, iNbrOfColumns,
pRowInfo->asColumnWidth, pRowInfo->ucBorderInfo)) {
/* All work has been done */
return;
}
/* Fill the table with maximum column widths */
if (eConversionType == conversion_text ||
eConversionType == conversion_fmt_text) {
if (iParagraphBreak == 0 ||
iParagraphBreak >= MAX_SCREEN_WIDTH) {
dMagnify = (double)MAX_SCREEN_WIDTH;
} else if (iParagraphBreak <= MIN_SCREEN_WIDTH) {
dMagnify = (double)MIN_SCREEN_WIDTH;
} else {
dMagnify = (double)iParagraphBreak;
}
dMagnify /= (double)DEFAULT_SCREEN_WIDTH;
DBG_FLT_C(dMagnify < 0.99 || dMagnify > 1.01, dMagnify);
} else {
dMagnify = 1.0;
}
tColumnWidthTotal = 0;
for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
atColumnWidthMax[iIndex] = tComputeColumnWidthMax(
pRowInfo->asColumnWidth[iIndex],
lCharWidthLarge,
dMagnify);
tColumnWidthTotal += atColumnWidthMax[iIndex];
}
/*
* Get enough space for the row.
* Worst case: three bytes per UTF-8 character
*/
tSize = 3 * (1 + tColumnWidthTotal + (size_t)iNbrOfColumns + 3);
szLine = xmalloc(tSize);
do {
/* Print one line of a table row */
bNotReady = FALSE;
pcTxt = szLine;
*pcTxt++ = TABLE_SEPARATOR_CHAR;
for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
tColumnWidthMax = atColumnWidthMax[iIndex];
if (aszColTxt[iIndex] == NULL) {
/* Add an empty column */
for (iTmp = 0;
iTmp < (int)tColumnWidthMax;
iTmp++) {
*pcTxt++ = (char)FILLER_CHAR;
}
*pcTxt++ = TABLE_SEPARATOR_CHAR;
*pcTxt = '\0';
continue;
}
/* Compute the length and width of the column text */
tLen = tComputeStringLengthMax(
aszColTxt[iIndex], tColumnWidthMax);
NO_DBG_DEC(tLen);
while (tLen != 0 &&
(aszColTxt[iIndex][tLen - 1] == '\n' ||
aszColTxt[iIndex][tLen - 1] == ' ')) {
aszColTxt[iIndex][tLen - 1] = ' ';
tLen--;
}
tWidth = tCountColumns(aszColTxt[iIndex], tLen);
fail(tWidth > tColumnWidthMax);
tLen = tGetBreakingPoint(aszColTxt[iIndex],
tLen, tWidth, tColumnWidthMax);
tWidth = tCountColumns(aszColTxt[iIndex], tLen);
if (tLen == 0 && *aszColTxt[iIndex] == '\0') {
/* No text at all */
aszColTxt[iIndex] = NULL;
} else {
/* Add the text */
pcTxt += sprintf(pcTxt,
"%.*s", (int)tLen, aszColTxt[iIndex]);
if (tLen == 0 && *aszColTxt[iIndex] != ' ') {
tLen = tGetCharacterLength(
aszColTxt[iIndex]);
DBG_CHR(*aszColTxt[iIndex]);
DBG_FIXME();
fail(tLen == 0);
}
aszColTxt[iIndex] += tLen;
while (*aszColTxt[iIndex] == ' ') {
aszColTxt[iIndex]++;
}
if (*aszColTxt[iIndex] == '\0') {
/* This row is now complete */
aszColTxt[iIndex] = NULL;
} else {
/* This row needs more lines */
bNotReady = TRUE;
}
}
/* Fill up the rest */
for (iTmp = 0;
iTmp < (int)tColumnWidthMax - (int)tWidth;
iTmp++) {
*pcTxt++ = (char)FILLER_CHAR;
}
/* End of column */
*pcTxt++ = TABLE_SEPARATOR_CHAR;
*pcTxt = '\0';
}
/* Output the table row line */
*pcTxt = '\0';
tRow = *pOutput;
tRow.szStorage = szLine;
fail(pcTxt < szLine);
tRow.tNextFree = (size_t)(pcTxt - szLine);
tRow.lStringWidth = lComputeStringWidth(
tRow.szStorage,
tRow.tNextFree,
tRow.tFontRef,
tRow.usFontSize);
vString2Diagram(pDiag, &tRow);
TRACE_MSG("after vString2Diagram in vTableRow2Window");
} while (bNotReady);
/* Clean up before you leave */
szLine = xfree(szLine);
TRACE_MSG("leaving vTableRow2Window");
#endif /* __FULL_TEXT_SEARCH */
} /* end of vTableRow2Window */

538
src/output.c Normal file
View File

@@ -0,0 +1,538 @@
/*
* output.c
* Copyright (C) 2002-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Generic output generating functions
*/
#include "antiword.h"
static conversion_type eConversionType = conversion_unknown;
static encoding_type eEncoding = encoding_neutral;
/*
* vPrologue1 - get options and call a specific initialization
*/
static void
vPrologue1(diagram_type *pDiag, const char *szTask, const char *szFilename)
{
options_type tOptions;
fail(pDiag == NULL);
fail(szTask == NULL || szTask[0] == '\0');
vGetOptions(&tOptions);
eConversionType = tOptions.eConversionType;
eEncoding = tOptions.eEncoding;
switch (eConversionType) {
case conversion_text:
vPrologueTXT(pDiag, &tOptions);
break;
case conversion_fmt_text:
vPrologueFMT(pDiag, &tOptions);
break;
case conversion_ps:
vProloguePS(pDiag, szTask, szFilename, &tOptions);
break;
case conversion_xml:
vPrologueXML(pDiag, &tOptions);
break;
case conversion_pdf:
vProloguePDF(pDiag, szTask, &tOptions);
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vPrologue1 */
/*
* vEpilogue - clean up after everything is done
*/
static void
vEpilogue(diagram_type *pDiag)
{
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
vEpilogueTXT(pDiag->pOutFile);
break;
case conversion_ps:
vEpiloguePS(pDiag);
break;
case conversion_xml:
vEpilogueXML(pDiag);
break;
case conversion_pdf:
vEpiloguePDF(pDiag);
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vEpilogue */
/*
* vImagePrologue - perform image initialization
*/
void
vImagePrologue(diagram_type *pDiag, const imagedata_type *pImg)
{
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
break;
case conversion_ps:
vImageProloguePS(pDiag, pImg);
break;
case conversion_xml:
break;
case conversion_pdf:
vImageProloguePDF(pDiag, pImg);
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vImagePrologue */
/*
* vImageEpilogue - clean up an image
*/
void
vImageEpilogue(diagram_type *pDiag)
{
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
break;
case conversion_ps:
vImageEpiloguePS(pDiag);
break;
case conversion_xml:
break;
case conversion_pdf:
vImageEpiloguePDF(pDiag);
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vImageEpilogue */
/*
* bAddDummyImage - add a dummy image
*
* return TRUE when successful, otherwise FALSE
*/
BOOL
bAddDummyImage(diagram_type *pDiag, const imagedata_type *pImg)
{
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
return FALSE;
case conversion_ps:
return bAddDummyImagePS(pDiag, pImg);
case conversion_xml:
return FALSE;
case conversion_pdf:
return bAddDummyImagePDF(pDiag, pImg);
default:
DBG_DEC(eConversionType);
return FALSE;
}
} /* end of bAddDummyImage */
/*
* pCreateDiagram - create and initialize a diagram
*
* remark: does not return if the diagram can't be created
*/
diagram_type *
pCreateDiagram(const char *szTask, const char *szFilename)
{
diagram_type *pDiag;
fail(szTask == NULL || szTask[0] == '\0');
DBG_MSG("pCreateDiagram");
/* Get the necessary memory */
pDiag = xmalloc(sizeof(diagram_type));
/* Initialization */
pDiag->pOutFile = stdout;
vPrologue1(pDiag, szTask, szFilename);
/* Return success */
return pDiag;
} /* end of pCreateDiagram */
/*
* vDestroyDiagram - remove a diagram by freeing the memory it uses
*/
void
vDestroyDiagram(diagram_type *pDiag)
{
DBG_MSG("vDestroyDiagram");
fail(pDiag == NULL);
if (pDiag == NULL) {
return;
}
vEpilogue(pDiag);
pDiag = xfree(pDiag);
} /* end of vDestroyDiagram */
/*
* vPrologue2 - call a specific initialization
*/
void
vPrologue2(diagram_type *pDiag, int iWordVersion)
{
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
break;
case conversion_ps:
vAddFontsPS(pDiag);
break;
case conversion_xml:
vCreateBookIntro(pDiag, iWordVersion);
break;
case conversion_pdf:
vCreateInfoDictionary(pDiag, iWordVersion);
vAddFontsPDF(pDiag);
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vPrologue2 */
/*
* vMove2NextLine - move to the next line
*/
void
vMove2NextLine(diagram_type *pDiag, drawfile_fontref tFontRef,
USHORT usFontSize)
{
fail(pDiag == NULL);
fail(pDiag->pOutFile == NULL);
fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
vMove2NextLineTXT(pDiag);
break;
case conversion_ps:
vMove2NextLinePS(pDiag, usFontSize);
break;
case conversion_xml:
vMove2NextLineXML(pDiag);
break;
case conversion_pdf:
vMove2NextLinePDF(pDiag, usFontSize);
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vMove2NextLine */
/*
* vSubstring2Diagram - put a sub string into a diagram
*/
void
vSubstring2Diagram(diagram_type *pDiag,
char *szString, size_t tStringLength, long lStringWidth,
UCHAR ucFontColor, USHORT usFontstyle, drawfile_fontref tFontRef,
USHORT usFontSize, USHORT usMaxFontSize)
{
switch (eConversionType) {
case conversion_text:
vSubstringTXT(pDiag, szString, tStringLength, lStringWidth);
break;
case conversion_fmt_text:
vSubstringFMT(pDiag, szString, tStringLength, lStringWidth,
usFontstyle);
break;
case conversion_ps:
vSubstringPS(pDiag, szString, tStringLength, lStringWidth,
ucFontColor, usFontstyle, tFontRef,
usFontSize, usMaxFontSize);
break;
case conversion_xml:
vSubstringXML(pDiag, szString, tStringLength, lStringWidth,
usFontstyle);
break;
case conversion_pdf:
vSubstringPDF(pDiag, szString, tStringLength, lStringWidth,
ucFontColor, usFontstyle, tFontRef,
usFontSize, usMaxFontSize);
break;
default:
DBG_DEC(eConversionType);
break;
}
pDiag->lXleft += lStringWidth;
} /* end of vSubstring2Diagram */
/*
* Create a start of paragraph (phase 1)
* Before indentation, list numbering, bullets etc.
*/
void
vStartOfParagraph1(diagram_type *pDiag, long lBeforeIndentation)
{
fail(pDiag == NULL);
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
vStartOfParagraphTXT(pDiag, lBeforeIndentation);
break;
case conversion_ps:
vStartOfParagraphPS(pDiag, lBeforeIndentation);
break;
case conversion_xml:
break;
case conversion_pdf:
vStartOfParagraphPDF(pDiag, lBeforeIndentation);
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vStartOfParagraph1 */
/*
* Create a start of paragraph (phase 2)
* After indentation, list numbering, bullets etc.
*/
void
vStartOfParagraph2(diagram_type *pDiag)
{
fail(pDiag == NULL);
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
break;
case conversion_ps:
break;
case conversion_xml:
vStartOfParagraphXML(pDiag, 1);
break;
case conversion_pdf:
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vStartOfParagraph2 */
/*
* Create an end of paragraph
*/
void
vEndOfParagraph(diagram_type *pDiag,
drawfile_fontref tFontRef, USHORT usFontSize, long lAfterIndentation)
{
fail(pDiag == NULL);
fail(pDiag->pOutFile == NULL);
fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
fail(lAfterIndentation < 0);
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
vEndOfParagraphTXT(pDiag, lAfterIndentation);
break;
case conversion_ps:
vEndOfParagraphPS(pDiag, usFontSize, lAfterIndentation);
break;
case conversion_xml:
vEndOfParagraphXML(pDiag, 1);
break;
case conversion_pdf:
vEndOfParagraphPDF(pDiag, usFontSize, lAfterIndentation);
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vEndOfParagraph */
/*
* Create an end of page
*/
void
vEndOfPage(diagram_type *pDiag, long lAfterIndentation, BOOL bNewSection)
{
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
vEndOfPageTXT(pDiag, lAfterIndentation);
break;
case conversion_ps:
vEndOfPagePS(pDiag, bNewSection);
break;
case conversion_xml:
vEndOfPageXML(pDiag);
break;
case conversion_pdf:
vEndOfPagePDF(pDiag, bNewSection);
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vEndOfPage */
/*
* vSetHeaders - set the headers
*/
void
vSetHeaders(diagram_type *pDiag, USHORT usIstd)
{
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
break;
case conversion_ps:
break;
case conversion_xml:
vSetHeadersXML(pDiag, usIstd);
break;
case conversion_pdf:
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vSetHeaders */
/*
* Create a start of list
*/
void
vStartOfList(diagram_type *pDiag, UCHAR ucNFC, BOOL bIsEndOfTable)
{
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
break;
case conversion_ps:
break;
case conversion_xml:
vStartOfListXML(pDiag, ucNFC, bIsEndOfTable);
break;
case conversion_pdf:
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vStartOfList */
/*
* Create an end of list
*/
void
vEndOfList(diagram_type *pDiag)
{
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
break;
case conversion_ps:
break;
case conversion_xml:
vEndOfListXML(pDiag);
break;
case conversion_pdf:
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vEndOfList */
/*
* Create a start of a list item
*/
void
vStartOfListItem(diagram_type *pDiag, BOOL bNoMarks)
{
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
break;
case conversion_ps:
break;
case conversion_xml:
vStartOfListItemXML(pDiag, bNoMarks);
break;
case conversion_pdf:
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vStartOfListItem */
/*
* Create an end of a table
*/
void
vEndOfTable(diagram_type *pDiag)
{
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
break;
case conversion_ps:
break;
case conversion_xml:
vEndOfTableXML(pDiag);
break;
case conversion_pdf:
break;
default:
DBG_DEC(eConversionType);
break;
}
} /* end of vEndOfTable */
/*
* Add a table row
*
* Returns TRUE when conversion type is XML
*/
BOOL
bAddTableRow(diagram_type *pDiag, char **aszColTxt,
int iNbrOfColumns, const short *asColumnWidth, UCHAR ucBorderInfo)
{
switch (eConversionType) {
case conversion_text:
case conversion_fmt_text:
break;
case conversion_ps:
break;
case conversion_xml:
vAddTableRowXML(pDiag, aszColTxt,
iNbrOfColumns, asColumnWidth,
ucBorderInfo);
return TRUE;
case conversion_pdf:
break;
default:
DBG_DEC(eConversionType);
break;
}
return FALSE;
} /* end of bAddTableRow */

1148
src/pdf.c Normal file

File diff suppressed because it is too large Load Diff

109
src/pictlist.c Normal file
View File

@@ -0,0 +1,109 @@
/*
* pictlist.c
* Copyright (C) 2000-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Build, read and destroy a list of Word picture information
*/
#include <stdlib.h>
#include "antiword.h"
/*
* Private structure to hide the way the information
* is stored from the rest of the program
*/
typedef struct picture_mem_tag {
picture_block_type tInfo;
struct picture_mem_tag *pNext;
} picture_mem_type;
/* Variables needed to write the Picture Information List */
static picture_mem_type *pAnchor = NULL;
static picture_mem_type *pPictureLast = NULL;
/*
* vDestroyPictInfoList - destroy the Picture Information List
*/
void
vDestroyPictInfoList(void)
{
picture_mem_type *pCurr, *pNext;
DBG_MSG("vDestroyPictInfoList");
/* Free the Picture Information List */
pCurr = pAnchor;
while (pCurr != NULL) {
pNext = pCurr->pNext;
pCurr = xfree(pCurr);
pCurr = pNext;
}
pAnchor = NULL;
/* Reset all control variables */
pPictureLast = NULL;
} /* end of vDestroyPictInfoList */
/*
* vAdd2PictInfoList - Add an element to the Picture Information List
*/
void
vAdd2PictInfoList(const picture_block_type *pPictureBlock)
{
picture_mem_type *pListMember;
fail(pPictureBlock == NULL);
NO_DBG_MSG("bAdd2PictInfoList");
if (pPictureBlock->ulFileOffset == FC_INVALID) {
/*
* This offset is really past the end of the file,
* so don't waste any memory by storing it.
*/
return;
}
if (pPictureBlock->ulFileOffsetPicture == FC_INVALID) {
/*
* The place where this picture is supposed to be stored
* doesn't exist.
*/
return;
}
NO_DBG_HEX(pPictureBlock->ulFileOffset);
NO_DBG_HEX(pPictureBlock->ulFileOffsetPicture);
NO_DBG_HEX(pPictureBlock->ulPictureOffset);
/* Create list member */
pListMember = xmalloc(sizeof(picture_mem_type));
/* Fill the list member */
pListMember->tInfo = *pPictureBlock;
pListMember->pNext = NULL;
/* Add the new member to the list */
if (pAnchor == NULL) {
pAnchor = pListMember;
} else {
fail(pPictureLast == NULL);
pPictureLast->pNext = pListMember;
}
pPictureLast = pListMember;
} /* end of vAdd2PictInfoList */
/*
* Get the info with the given file offset from the Picture Information List
*/
ULONG
ulGetPictInfoListItem(ULONG ulFileOffset)
{
picture_mem_type *pCurr;
for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
if (pCurr->tInfo.ulFileOffset == ulFileOffset) {
return pCurr->tInfo.ulFileOffsetPicture;
}
}
return FC_INVALID;
} /* end of ulGetPictInfoListItem */

191
src/png2eps.c Normal file
View File

@@ -0,0 +1,191 @@
/*
* png2eps.c
* Copyright (C) 2000-2002 A.J. van Os; Released under GPL
*
* Description:
* Functions to translate png images into eps
*
*/
#include <stdio.h>
#include <ctype.h>
#include "antiword.h"
#if defined(DEBUG)
static int iPicCounter = 0;
#endif /* DEBUG */
/*
* tSkipToData - skip until a IDAT chunk is found
*
* returns the length of the pixeldata or -1 in case of error
*/
static size_t
tSkipToData(FILE *pFile, size_t tMaxBytes, size_t *ptSkipped)
{
ULONG ulName, ulTmp;
size_t tDataLength, tToSkip;
int iCounter;
fail(pFile == NULL);
fail(ptSkipped == NULL);
/* Examine chunks */
while (*ptSkipped + 8 < tMaxBytes) {
tDataLength = (size_t)ulNextLongBE(pFile);
DBG_DEC(tDataLength);
*ptSkipped += 4;
ulName = 0x00;
for (iCounter = 0; iCounter < 4; iCounter++) {
ulTmp = (ULONG)iNextByte(pFile);
if (!isalpha((int)ulTmp)) {
DBG_HEX(ulTmp);
return (size_t)-1;
}
ulName <<= 8;
ulName |= ulTmp;
}
DBG_HEX(ulName);
*ptSkipped += 4;
if (ulName == PNG_CN_IEND) {
break;
}
if (ulName == PNG_CN_IDAT) {
return tDataLength;
}
tToSkip = tDataLength + 4;
if (tToSkip >= tMaxBytes - *ptSkipped) {
DBG_DEC(tToSkip);
DBG_DEC(tMaxBytes - *ptSkipped);
return (size_t)-1;
}
(void)tSkipBytes(pFile, tToSkip);
*ptSkipped += tToSkip;
}
return (size_t)-1;
} /* end of iSkipToData */
/*
* iFindFirstPixelData - find the first pixeldata if a PNG image
*
* returns the length of the pixeldata or -1 in case of error
*/
static size_t
tFindFirstPixelData(FILE *pFile, size_t tMaxBytes, size_t *ptSkipped)
{
fail(pFile == NULL);
fail(tMaxBytes == 0);
fail(ptSkipped == NULL);
if (tMaxBytes < 8) {
DBG_DEC(tMaxBytes);
return (size_t)-1;
}
/* Skip over the PNG signature */
(void)tSkipBytes(pFile, 8);
*ptSkipped = 8;
return tSkipToData(pFile, tMaxBytes, ptSkipped);
} /* end of iFindFirstPixelData */
/*
* tFindNextPixelData - find the next pixeldata if a PNG image
*
* returns the length of the pixeldata or -1 in case of error
*/
static size_t
tFindNextPixelData(FILE *pFile, size_t tMaxBytes, size_t *ptSkipped)
{
fail(pFile == NULL);
fail(tMaxBytes == 0);
fail(ptSkipped == NULL);
if (tMaxBytes < 4) {
DBG_DEC(tMaxBytes);
return (size_t)-1;
}
/* Skip over the crc */
(void)tSkipBytes(pFile, 4);
*ptSkipped = 4;
return tSkipToData(pFile, tMaxBytes, ptSkipped);
} /* end of tFindNextPixelData */
#if defined(DEBUG)
/*
* vCopy2File
*/
static void
vCopy2File(FILE *pFile, ULONG ulFileOffset, size_t tPictureLen)
{
FILE *pOutFile;
size_t tIndex;
int iTmp;
char szFilename[30];
if (!bSetDataOffset(pFile, ulFileOffset)) {
return;
}
sprintf(szFilename, "/tmp/pic/pic%04d.png", ++iPicCounter);
pOutFile = fopen(szFilename, "wb");
if (pOutFile == NULL) {
return;
}
for (tIndex = 0; tIndex < tPictureLen; tIndex++) {
iTmp = iNextByte(pFile);
if (putc(iTmp, pOutFile) == EOF) {
break;
}
}
(void)fclose(pOutFile);
} /* end of vCopy2File */
#endif /* DEBUG */
/*
* bTranslatePNG - translate a PNG image
*
* This function translates an image from png to eps
*
* return TRUE when sucessful, otherwise FALSE
*/
BOOL
bTranslatePNG(diagram_type *pDiag, FILE *pFile,
ULONG ulFileOffset, size_t tPictureLen, const imagedata_type *pImg)
{
size_t tMaxBytes, tDataLength, tSkipped;
#if defined(DEBUG)
vCopy2File(pFile, ulFileOffset, tPictureLen);
#endif /* DEBUG */
/* Seek to start position of PNG data */
if (!bSetDataOffset(pFile, ulFileOffset)) {
return FALSE;
}
tMaxBytes = tPictureLen;
tDataLength = tFindFirstPixelData(pFile, tMaxBytes, &tSkipped);
if (tDataLength == (size_t)-1) {
return FALSE;
}
vImagePrologue(pDiag, pImg);
do {
tMaxBytes -= tSkipped;
vASCII85EncodeArray(pFile, pDiag->pOutFile, tDataLength);
tMaxBytes -= tDataLength;
tDataLength = tFindNextPixelData(pFile, tMaxBytes, &tSkipped);
} while (tDataLength != (size_t)-1);
vASCII85EncodeByte(pDiag->pOutFile, EOF);
vImageEpilogue(pDiag);
return TRUE;
} /* end of bTranslatePNG */

26
src/png2sprt.c Normal file
View File

@@ -0,0 +1,26 @@
/*
* png2sprt.c
* Copyright (C) 2000 A.J. van Os; Released under GPL
*
* Description:
* Functions to translate png pictures into sprites
*/
#include <stdio.h>
#include "antiword.h"
/*
* bTranslatePNG - translate a PNG picture
*
* This function translates a picture from png to sprite
*
* return TRUE when sucessful, otherwise FALSE
*/
BOOL
bTranslatePNG(diagram_type *pDiag, FILE *pFile,
ULONG ulFileOffset, size_t tPictureLen, const imagedata_type *pImg)
{
/* PNG is not supported yet */
return bAddDummyImage(pDiag, pImg);
} /* end of bTranslatePNG */

1171
src/postscript.c Normal file

File diff suppressed because it is too large Load Diff

489
src/prop0.c Normal file
View File

@@ -0,0 +1,489 @@
/*
* prop0.c
* Copyright (C) 2002-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Read the property information from a Word for DOS file
*/
#include <string.h>
#include <time.h>
#include "antiword.h"
/*
* tConvertDosDate - convert DOS date format
*
* returns Unix time_t or -1
*/
static time_t
tConvertDosDate(const char *szDosDate)
{
struct tm tTime;
const char *pcTmp;
time_t tResult;
memset(&tTime, 0, sizeof(tTime));
pcTmp = szDosDate;
/* Get the month */
if (!isdigit(*pcTmp)) {
return (time_t)-1;
}
tTime.tm_mon = (int)(*pcTmp - '0');
pcTmp++;
if (isdigit(*pcTmp)) {
tTime.tm_mon *= 10;
tTime.tm_mon += (int)(*pcTmp - '0');
pcTmp++;
}
/* Get the first separater */
if (isalnum(*pcTmp)) {
return (time_t)-1;
}
pcTmp++;
/* Get the day */
if (!isdigit(*pcTmp)) {
return (time_t)-1;
}
tTime.tm_mday = (int)(*pcTmp - '0');
pcTmp++;
if (isdigit(*pcTmp)) {
tTime.tm_mday *= 10;
tTime.tm_mday += (int)(*pcTmp - '0');
pcTmp++;
}
/* Get the second separater */
if (isalnum(*pcTmp)) {
return (time_t)-1;
}
pcTmp++;
/* Get the year */
if (!isdigit(*pcTmp)) {
return (time_t)-1;
}
tTime.tm_year = (int)(*pcTmp - '0');
pcTmp++;
if (isdigit(*pcTmp)) {
tTime.tm_year *= 10;
tTime.tm_year += (int)(*pcTmp - '0');
pcTmp++;
}
/* Check the values */
if (tTime.tm_mon == 0 || tTime.tm_mday == 0 || tTime.tm_mday > 31) {
return (time_t)-1;
}
/* Correct the values */
tTime.tm_mon--; /* From 01-12 to 00-11 */
if (tTime.tm_year < 80) {
tTime.tm_year += 100; /* 00 means 2000 is 100 */
}
tTime.tm_isdst = -1;
tResult = mktime(&tTime);
NO_DBG_MSG(ctime(&tResult));
return tResult;
} /* end of tConvertDosDate */
/*
* Build the lists with Document Property Information for Word for DOS files
*/
void
vGet0DopInfo(FILE *pFile, const UCHAR *aucHeader)
{
document_block_type tDocument;
UCHAR *aucBuffer;
ULONG ulBeginSumdInfo, ulBeginNextBlock;
size_t tLen;
USHORT usOffset;
tDocument.ucHdrFtrSpecification = 0;
tDocument.usDefaultTabWidth = usGetWord(0x70, aucHeader); /* dxaTab */
tDocument.tCreateDate = (time_t)-1;
tDocument.tRevisedDate = (time_t)-1;
ulBeginSumdInfo = 128 * (ULONG)usGetWord(0x1c, aucHeader);
DBG_HEX(ulBeginSumdInfo);
ulBeginNextBlock = 128 * (ULONG)usGetWord(0x6a, aucHeader);
DBG_HEX(ulBeginNextBlock);
if (ulBeginSumdInfo < ulBeginNextBlock && ulBeginNextBlock != 0) {
/* There is a summary information block */
tLen = (size_t)(ulBeginNextBlock - ulBeginSumdInfo);
aucBuffer = xmalloc(tLen);
/* Read the summary information block */
if (bReadBytes(aucBuffer, tLen, ulBeginSumdInfo, pFile)) {
usOffset = usGetWord(12, aucBuffer);
if (aucBuffer[usOffset] != 0) {
NO_DBG_STRN(aucBuffer + usOffset, 8);
tDocument.tRevisedDate =
tConvertDosDate((char *)aucBuffer + usOffset);
}
usOffset = usGetWord(14, aucBuffer);
if (aucBuffer[usOffset] != 0) {
NO_DBG_STRN(aucBuffer + usOffset, 8);
tDocument.tCreateDate =
tConvertDosDate((char *)aucBuffer + usOffset);
}
}
aucBuffer = xfree(aucBuffer);
}
vCreateDocumentInfoList(&tDocument);
} /* end of vGet0DopInfo */
/*
* Fill the section information block with information
* from a Word for DOS file.
*/
static void
vGet0SectionInfo(const UCHAR *aucGrpprl, size_t tBytes,
section_block_type *pSection)
{
USHORT usCcol;
UCHAR ucTmp;
fail(aucGrpprl == NULL || pSection == NULL);
if (tBytes < 2) {
return;
}
/* bkc */
ucTmp = ucGetByte(1, aucGrpprl);
DBG_HEX(ucTmp);
ucTmp &= 0x07;
DBG_HEX(ucTmp);
pSection->bNewPage = ucTmp != 0 && ucTmp != 1;
if (tBytes < 18) {
return;
}
/* ccolM1 */
usCcol = (USHORT)ucGetByte(17, aucGrpprl);
DBG_DEC(usCcol);
} /* end of vGet0SectionInfo */
/*
* Build the lists with Section Property Information for Word for DOS files
*/
void
vGet0SepInfo(FILE *pFile, const UCHAR *aucHeader)
{
section_block_type tSection;
UCHAR *aucBuffer;
ULONG ulBeginOfText, ulTextOffset, ulBeginSectInfo;
ULONG ulCharPos, ulSectPage, ulBeginNextBlock;
size_t tSectInfoLen, tIndex, tSections, tBytes;
UCHAR aucTmp[2], aucFpage[35];
fail(pFile == NULL || aucHeader == NULL);
ulBeginOfText = 128;
NO_DBG_HEX(ulBeginOfText);
ulBeginSectInfo = 128 * (ULONG)usGetWord(0x18, aucHeader);
DBG_HEX(ulBeginSectInfo);
ulBeginNextBlock = 128 * (ULONG)usGetWord(0x1a, aucHeader);
DBG_HEX(ulBeginNextBlock);
if (ulBeginSectInfo == ulBeginNextBlock) {
/* There is no section information block */
return;
}
/* Get the the number of sections */
if (!bReadBytes(aucTmp, 2, ulBeginSectInfo, pFile)) {
return;
}
tSections = (size_t)usGetWord(0, aucTmp);
NO_DBG_DEC(tSections);
/* Read the Section Descriptors */
tSectInfoLen = 10 * tSections;
NO_DBG_DEC(tSectInfoLen);
aucBuffer = xmalloc(tSectInfoLen);
if (!bReadBytes(aucBuffer, tSectInfoLen, ulBeginSectInfo + 4, pFile)) {
aucBuffer = xfree(aucBuffer);
return;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
/* Read the Section Properties */
for (tIndex = 0; tIndex < tSections; tIndex++) {
ulTextOffset = ulGetLong(10 * tIndex, aucBuffer);
NO_DBG_HEX(ulTextOffset);
ulCharPos = ulBeginOfText + ulTextOffset;
NO_DBG_HEX(ulTextOffset);
ulSectPage = ulGetLong(10 * tIndex + 6, aucBuffer);
NO_DBG_HEX(ulSectPage);
if (ulSectPage == FC_INVALID || /* Must use defaults */
ulSectPage < 128 || /* Should not happen */
ulSectPage >= ulBeginSectInfo) { /* Should not happen */
DBG_HEX_C(ulSectPage != FC_INVALID, ulSectPage);
vDefault2SectionInfoList(ulCharPos);
continue;
}
/* Get the number of bytes to read */
if (!bReadBytes(aucTmp, 1, ulSectPage, pFile)) {
continue;
}
tBytes = 1 + (size_t)ucGetByte(0, aucTmp);
NO_DBG_DEC(tBytes);
if (tBytes > sizeof(aucFpage)) {
DBG_DEC(tBytes);
tBytes = sizeof(aucFpage);
}
/* Read the bytes */
if (!bReadBytes(aucFpage, tBytes, ulSectPage, pFile)) {
continue;
}
NO_DBG_PRINT_BLOCK(aucFpage, tBytes);
/* Process the bytes */
vGetDefaultSection(&tSection);
vGet0SectionInfo(aucFpage + 1, tBytes - 1, &tSection);
vAdd2SectionInfoList(&tSection, ulCharPos);
}
/* Clean up before you leave */
aucBuffer = xfree(aucBuffer);
} /* end of vGet0SepInfo */
/*
* Fill the style information block with information
* from a Word for DOS file.
*/
static void
vGet0StyleInfo(int iFodo, const UCHAR *aucGrpprl, style_block_type *pStyle)
{
int iBytes;
UCHAR ucTmp;
fail(iFodo <= 0 || aucGrpprl == NULL || pStyle == NULL);
pStyle->usIstdNext = ISTD_NORMAL;
iBytes = (int)ucGetByte(iFodo, aucGrpprl);
if (iBytes < 1) {
return;
}
/* stc if styled */
ucTmp = ucGetByte(iFodo + 1, aucGrpprl);
if ((ucTmp & BIT(0)) != 0) {
ucTmp >>= 1;
if (ucTmp >= 88 && ucTmp <= 94) {
/* Header levels 1 through 7 */
pStyle->usIstd = ucTmp - 87;
pStyle->ucNumLevel = 1;
}
}
if (iBytes < 2) {
return;
}
/* jc */
ucTmp = ucGetByte(iFodo + 2, aucGrpprl);
pStyle->ucAlignment = ucTmp & 0x02;
if (iBytes < 3) {
return;
}
/* stc */
ucTmp = ucGetByte(iFodo + 3, aucGrpprl);
ucTmp &= 0x7f;
if (ucTmp >= 88 && ucTmp <= 94) {
/* Header levels 1 through 7 */
pStyle->usIstd = ucTmp - 87;
pStyle->ucNumLevel = 1;
}
if (iBytes < 6) {
return;
}
/* dxaRight */
pStyle->sRightIndent = (short)usGetWord(iFodo + 5, aucGrpprl);
NO_DBG_DEC(pStyle->sRightIndent);
if (iBytes < 8) {
return;
}
/* dxaLeft */
pStyle->sLeftIndent = (short)usGetWord(iFodo + 7, aucGrpprl);
NO_DBG_DEC(pStyle->sLeftIndent);
if (iBytes < 10) {
return;
}
/* dxaLeft1 */
pStyle->sLeftIndent1 = (short)usGetWord(iFodo + 9, aucGrpprl);
NO_DBG_DEC(pStyle->sLeftIndent1);
if (iBytes < 14) {
return;
}
/* dyaBefore */
pStyle->usBeforeIndent = usGetWord(iFodo + 13, aucGrpprl);
NO_DBG_DEC(pStyle->usBeforeIndent);
if (iBytes < 16) {
return;
}
/* dyaAfter */
pStyle->usAfterIndent = usGetWord(iFodo + 15, aucGrpprl);
NO_DBG_DEC(pStyle->usAfterIndent);
} /* end of vGet0StyleInfo */
/*
* Build the lists with Paragraph Information for Word for DOS files
*/
void
vGet0PapInfo(FILE *pFile, const UCHAR *aucHeader)
{
style_block_type tStyle;
ULONG ulBeginParfInfo, ulCharPos, ulCharPosNext;
int iIndex, iRun, iFodo;
UCHAR aucFpage[128];
fail(pFile == NULL || aucHeader == NULL);
ulBeginParfInfo = 128 * (ULONG)usGetWord(0x12, aucHeader);
NO_DBG_HEX(ulBeginParfInfo);
do {
if (!bReadBytes(aucFpage, 128, ulBeginParfInfo, pFile)) {
return;
}
NO_DBG_PRINT_BLOCK(aucFpage, 128);
ulCharPosNext = ulGetLong(0, aucFpage);
iRun = (int)ucGetByte(0x7f, aucFpage);
NO_DBG_DEC(iRun);
for (iIndex = 0; iIndex < iRun; iIndex++) {
iFodo = (int)usGetWord(6 * iIndex + 8, aucFpage);
if (iFodo <= 0 || iFodo > 0x79) {
DBG_DEC_C(iFodo != (int)0xffff, iFodo);
continue;
}
vFillStyleFromStylesheet(0, &tStyle);
vGet0StyleInfo(iFodo, aucFpage + 4, &tStyle);
ulCharPos = ulCharPosNext;
ulCharPosNext = ulGetLong(6 * iIndex + 4, aucFpage);
tStyle.ulFileOffset = ulCharPos;
vAdd2StyleInfoList(&tStyle);
}
ulBeginParfInfo += 128;
} while (ulCharPosNext == ulBeginParfInfo);
} /* end of vGet0PapInfo */
/*
* Fill the font information block with information
* from a Word for DOS file.
*/
static void
vGet0FontInfo(int iFodo, const UCHAR *aucGrpprl, font_block_type *pFont)
{
int iBytes;
UCHAR ucTmp;
fail(iFodo <= 0 || aucGrpprl == NULL || pFont == NULL);
iBytes = (int)ucGetByte(iFodo, aucGrpprl);
if (iBytes < 2) {
return;
}
/* fBold, fItalic, cFtc */
ucTmp = ucGetByte(iFodo + 2, aucGrpprl);
if ((ucTmp & BIT(0)) != 0) {
pFont->usFontStyle |= FONT_BOLD;
}
if ((ucTmp & BIT(1)) != 0) {
pFont->usFontStyle |= FONT_ITALIC;
}
pFont->ucFontNumber = ucTmp >> 2;
NO_DBG_DEC(pFont->ucFontNumber);
if (iBytes < 3) {
return;
}
/* cHps */
pFont->usFontSize = (USHORT)ucGetByte(iFodo + 3, aucGrpprl);
NO_DBG_DEC(pFont->usFontSize);
if (iBytes < 4) {
return;
}
/* cKul, fStrike, fCaps, fSmallCaps, fVanish */
ucTmp = ucGetByte(iFodo + 4, aucGrpprl);
if ((ucTmp & BIT(0)) != 0 || (ucTmp & BIT(2)) != 0) {
pFont->usFontStyle |= FONT_UNDERLINE;
}
if ((ucTmp & BIT(1)) != 0) {
pFont->usFontStyle |= FONT_STRIKE;
}
if ((ucTmp & BIT(4)) != 0) {
pFont->usFontStyle |= FONT_CAPITALS;
}
if ((ucTmp & BIT(5)) != 0) {
pFont->usFontStyle |= FONT_SMALL_CAPITALS;
}
if ((ucTmp & BIT(7)) != 0) {
pFont->usFontStyle |= FONT_HIDDEN;
}
DBG_HEX(pFont->usFontStyle);
if (iBytes < 6) {
return;
}
/* cIss */
ucTmp = ucGetByte(iFodo + 6, aucGrpprl);
if (ucTmp != 0) {
if (ucTmp < 128) {
pFont->usFontStyle |= FONT_SUPERSCRIPT;
DBG_MSG("Superscript");
} else {
pFont->usFontStyle |= FONT_SUBSCRIPT;
DBG_MSG("Subscript");
}
}
if (iBytes < 7) {
return;
}
/* cIco */
ucTmp = ucGetByte(iFodo + 7, aucGrpprl);
switch (ucTmp & 0x07) {
case 0: pFont->ucFontColor = FONT_COLOR_BLACK; break;
case 1: pFont->ucFontColor = FONT_COLOR_RED; break;
case 2: pFont->ucFontColor = FONT_COLOR_GREEN; break;
case 3: pFont->ucFontColor = FONT_COLOR_BLUE; break;
case 4: pFont->ucFontColor = FONT_COLOR_CYAN; break;
case 5: pFont->ucFontColor = FONT_COLOR_MAGENTA; break;
case 6: pFont->ucFontColor = FONT_COLOR_YELLOW; break;
case 7: pFont->ucFontColor = FONT_COLOR_WHITE; break;
default:pFont->ucFontColor = FONT_COLOR_BLACK; break;
}
NO_DBG_DEC(pFont->ucFontColor);
} /* end of vGet0FontInfo */
/*
* Build the lists with Character Information for Word for DOS files
*/
void
vGet0ChrInfo(FILE *pFile, const UCHAR *aucHeader)
{
font_block_type tFont;
ULONG ulBeginCharInfo, ulCharPos, ulCharPosNext;
int iIndex, iRun, iFodo;
UCHAR aucFpage[128];
fail(pFile == NULL || aucHeader == NULL);
ulBeginCharInfo = ulGetLong(0x0e, aucHeader);
NO_DBG_HEX(ulBeginCharInfo);
ulBeginCharInfo = ROUND128(ulBeginCharInfo);
NO_DBG_HEX(ulBeginCharInfo);
do {
if (!bReadBytes(aucFpage, 128, ulBeginCharInfo, pFile)) {
return;
}
NO_DBG_PRINT_BLOCK(aucFpage, 128);
ulCharPosNext = ulGetLong(0, aucFpage);
iRun = (int)ucGetByte(0x7f, aucFpage);
NO_DBG_DEC(iRun);
for (iIndex = 0; iIndex < iRun; iIndex++) {
iFodo = (int)usGetWord(6 * iIndex + 8, aucFpage);
if (iFodo <= 0 || iFodo > 0x79) {
DBG_DEC_C(iFodo != (int)0xffff, iFodo);
continue;
}
vFillFontFromStylesheet(0, &tFont);
vGet0FontInfo(iFodo, aucFpage + 4, &tFont);
ulCharPos = ulCharPosNext;
ulCharPosNext = ulGetLong(6 * iIndex + 4, aucFpage);
tFont.ulFileOffset = ulCharPos;
vAdd2FontInfoList(&tFont);
}
ulBeginCharInfo += 128;
} while (ulCharPosNext == ulBeginCharInfo);
} /* end of vGet0ChrInfo */

1067
src/prop2.c Normal file

File diff suppressed because it is too large Load Diff

1141
src/prop6.c Normal file

File diff suppressed because it is too large Load Diff

1496
src/prop8.c Normal file

File diff suppressed because it is too large Load Diff

198
src/properties.c Normal file
View File

@@ -0,0 +1,198 @@
/*
* properties.c
* Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
*
* Description:
* Read the properties information from a MS Word file
*/
#include <stdlib.h>
#include <string.h>
#include "antiword.h"
/*
* Build the lists with Property Information
*/
void
vGetPropertyInfo(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader, int iWordVersion)
{
options_type tOptions;
TRACE_MSG("vGetPropertyInfo");
fail(pFile == NULL);
fail(pPPS == NULL && iWordVersion >= 6);
fail(aulBBD == NULL && tBBDLen != 0);
fail(aulSBD == NULL && tSBDLen != 0);
fail(aucHeader == NULL);
/* Get the options */
vGetOptions(&tOptions);
/* Get the property information per Word version */
switch (iWordVersion) {
case 0:
vGet0DopInfo(pFile, aucHeader);
vGet0SepInfo(pFile, aucHeader);
vGet0PapInfo(pFile, aucHeader);
if (tOptions.eConversionType == conversion_draw ||
tOptions.eConversionType == conversion_ps ||
tOptions.eConversionType == conversion_xml ||
tOptions.eConversionType == conversion_fmt_text ||
tOptions.eConversionType == conversion_pdf) {
vGet0ChrInfo(pFile, aucHeader);
}
if (tOptions.eConversionType == conversion_draw ||
tOptions.eConversionType == conversion_ps ||
tOptions.eConversionType == conversion_pdf) {
vCreate0FontTable();
}
vSet0SummaryInfo(pFile, aucHeader);
break;
case 1:
case 2:
vGet2Stylesheet(pFile, iWordVersion, aucHeader);
vGet2DopInfo(pFile, aucHeader);
vGet2SepInfo(pFile, aucHeader);
vGet2PapInfo(pFile, aucHeader);
if (tOptions.eConversionType == conversion_ps ||
tOptions.eConversionType == conversion_pdf) {
vGet2HdrFtrInfo(pFile, aucHeader);
}
if (tOptions.eConversionType == conversion_draw ||
tOptions.eConversionType == conversion_ps ||
tOptions.eConversionType == conversion_xml ||
tOptions.eConversionType == conversion_fmt_text ||
tOptions.eConversionType == conversion_pdf) {
vGet2ChrInfo(pFile, iWordVersion, aucHeader);
}
if (tOptions.eConversionType == conversion_draw ||
tOptions.eConversionType == conversion_ps ||
tOptions.eConversionType == conversion_pdf) {
vCreate2FontTable(pFile, iWordVersion, aucHeader);
}
vSet2SummaryInfo(pFile, iWordVersion, aucHeader);
break;
case 4:
case 5:
break;
case 6:
case 7:
vGet6Stylesheet(pFile, pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen, aucHeader);
vGet6DopInfo(pFile, pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen, aucHeader);
vGet6SepInfo(pFile, pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen, aucHeader);
vGet6PapInfo(pFile, pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen, aucHeader);
if (tOptions.eConversionType == conversion_ps ||
tOptions.eConversionType == conversion_pdf) {
vGet6HdrFtrInfo(pFile, pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen, aucHeader);
}
if (tOptions.eConversionType == conversion_draw ||
tOptions.eConversionType == conversion_ps ||
tOptions.eConversionType == conversion_xml ||
tOptions.eConversionType == conversion_fmt_text ||
tOptions.eConversionType == conversion_pdf) {
vGet6ChrInfo(pFile, pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen, aucHeader);
}
if (tOptions.eConversionType == conversion_draw ||
tOptions.eConversionType == conversion_ps ||
tOptions.eConversionType == conversion_pdf) {
vCreate6FontTable(pFile, pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen, aucHeader);
}
vSet6SummaryInfo(pFile, pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
break;
case 8:
vGet8LstInfo(pFile, pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
vGet8Stylesheet(pFile, pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
vGet8DopInfo(pFile, &pPPS->tTable,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
vGet8SepInfo(pFile, pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
vGet8PapInfo(pFile, pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
if (tOptions.eConversionType == conversion_ps ||
tOptions.eConversionType == conversion_pdf) {
vGet8HdrFtrInfo(pFile, &pPPS->tTable,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
}
if (tOptions.eConversionType == conversion_draw ||
tOptions.eConversionType == conversion_ps ||
tOptions.eConversionType == conversion_xml ||
tOptions.eConversionType == conversion_fmt_text ||
tOptions.eConversionType == conversion_pdf) {
vGet8ChrInfo(pFile, pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
}
if (tOptions.eConversionType == conversion_draw ||
tOptions.eConversionType == conversion_ps ||
tOptions.eConversionType == conversion_pdf) {
vCreate8FontTable(pFile, pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
}
vSet8SummaryInfo(pFile, pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
break;
default:
DBG_DEC(iWordVersion);
DBG_FIXME();
werr(0, "Sorry, no property information");
break;
}
/* Temporarily: Correct the font table */
vCorrectFontTable(tOptions.eConversionType, tOptions.eEncoding);
} /* end of vGetPropertyInfo */
/*
* ePropMod2RowInfo - Turn the Property Modifier into row information
*
* Returns: the row information
*/
row_info_enum
ePropMod2RowInfo(USHORT usPropMod, int iWordVersion)
{
row_block_type tRow;
const UCHAR *aucPropMod;
int iLen;
TRACE_MSG("ePropMod2RowInfo");
aucPropMod = aucReadPropModListItem(usPropMod);
if (aucPropMod == NULL) {
return found_nothing;
}
iLen = (int)usGetWord(0, aucPropMod);
switch (iWordVersion) {
case 0:
return found_nothing;
case 1:
case 2:
return eGet2RowInfo(0, aucPropMod + 2, iLen, &tRow);
case 4:
case 5:
return found_nothing;
case 6:
case 7:
return eGet6RowInfo(0, aucPropMod + 2, iLen, &tRow);
case 8:
return eGet8RowInfo(0, aucPropMod + 2, iLen, &tRow);
default:
DBG_DEC(iWordVersion);
DBG_FIXME();
return found_nothing;
}
} /* end of ePropMod2RowInfo */

110
src/propmod.c Normal file
View File

@@ -0,0 +1,110 @@
/*
* propmod.c
* Copyright (C) 2001-2003 A.J. van Os; Released under GPL
*
* Description:
* Build, read and destroy a list (array) of Word property modifiers
*/
#include <stdio.h>
#include <string.h>
#include "antiword.h"
#if defined(DEBUG)
#define ELEMENTS_TO_ADD 3
#else
#define ELEMENTS_TO_ADD 30
#endif /* DEBUG */
/* Variables needed to write the property modifier list */
static UCHAR **ppAnchor = NULL;
static size_t tNextFree = 0;
static size_t tMaxElements = 0;
/*
* vDestroyPropModList - destroy the property modifier list
*/
void
vDestroyPropModList(void)
{
size_t tIndex;
DBG_MSG("vDestroyPropModList");
/* Free all the elements of the list */
for (tIndex = 0; tIndex < tNextFree; tIndex++) {
ppAnchor[tIndex] = xfree(ppAnchor[tIndex]);
}
/* Free the list itself */
ppAnchor = xfree(ppAnchor);
/* Reset all control variables */
tNextFree = 0;
tMaxElements = 0;
} /* end of vDestroyPropModList */
/*
* vAdd2PropModList - add an element to the property modifier list
*/
void
vAdd2PropModList(const UCHAR *aucPropMod)
{
size_t tSize, tLen;
fail(aucPropMod == NULL);
NO_DBG_MSG("vAdd2PropModList");
if (tNextFree >= tMaxElements) {
tMaxElements += ELEMENTS_TO_ADD;
tSize = tMaxElements * sizeof(UCHAR **);
ppAnchor = xrealloc(ppAnchor, tSize);
}
NO_DBG_DEC(tNextFree);
tLen = 2 + (size_t)usGetWord(0, aucPropMod);
NO_DBG_HEX(tLen);
NO_DBG_PRINT_BLOCK(pucPropMod, tLen);
ppAnchor[tNextFree] = xmalloc(tLen);
memcpy(ppAnchor[tNextFree], aucPropMod, tLen);
tNextFree++;
} /* end of vAdd2PropModList */
/*
* aucReadPropModListItem - get an item of the property modifier list
*/
const UCHAR *
aucReadPropModListItem(USHORT usPropMod)
{
static UCHAR aucBuffer[4];
size_t tIndex;
if (usPropMod == IGNORE_PROPMOD) {
/* This Properties Modifier must be ignored */
return NULL;
}
if (!odd(usPropMod)) {
/* Variant 1: The information is in the input ifself */
aucBuffer[0] = 2;
aucBuffer[1] = 0;
aucBuffer[2] = (UCHAR)((usPropMod & 0x00fe) >> 1);
aucBuffer[3] = (UCHAR)((usPropMod & 0xff00) >> 8);
return aucBuffer;
}
if (ppAnchor == NULL) {
/* No information available */
return NULL;
}
/* Variant 2: The input contains an index */
tIndex = (size_t)(usPropMod >> 1);
if (tIndex >= tNextFree) {
DBG_HEX(usPropMod);
DBG_DEC(tIndex);
DBG_DEC(tNextFree);
return NULL;
}
return ppAnchor[tIndex];
} /* end of aucGetPropModListItem */

251
src/riscos.c Normal file
View File

@@ -0,0 +1,251 @@
/*
* riscos.c
* Copyright (C) 2001,2002 A.J. van Os; Released under GPL
*
* Description:
* RISC OS only functions
*/
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "DeskLib:Error.h"
#include "DeskLib:SWI.h"
#include "antiword.h"
#if !defined(DrawFile_Render)
#define DrawFile_Render 0x045540
#endif /* !DrawFile_Render */
#if !defined(JPEG_Info)
#define JPEG_Info 0x049980
#endif /* !JPEG_Info */
/*
* werr - write an error message and exit if needed
*/
void
werr(int iFatal, const char *szFormat, ...)
{
va_list tArg;
va_start(tArg, szFormat);
Error_Report(iFatal, (char *)szFormat, tArg);
va_end(tArg);
switch (iFatal) {
case 0: /* The message is just a warning, so no exit */
return;
case 1: /* Fatal error with a standard exit */
exit(EXIT_FAILURE);
default: /* Fatal error with a non-standard exit */
exit(iFatal);
}
} /* end of werr */
/*
* iGetFiletype
* This function will get the filetype of the given file.
* returns the filetype.
*/
int
iGetFiletype(const char *szFilename)
{
os_error *e;
int iType;
fail(szFilename == NULL || szFilename[0] == '\0');
e = SWI(2, 7, SWI_OS_File | XOS_Bit,
23, szFilename,
NULL, NULL, NULL, NULL, NULL, NULL, &iType);
if (e == NULL) {
return iType;
}
werr(0, "Get Filetype error %d: %s", e->errnum, e->errmess);
return -1;
} /* end of iGetFiletype */
/*
* vSetFiletype
* This procedure will set the filetype of the given file to the given
* type.
*/
void
vSetFiletype(const char *szFilename, int iFiletype)
{
os_error *e;
fail(szFilename == NULL || szFilename[0] == '\0');
if (iFiletype < 0x000 || iFiletype > 0xfff) {
return;
}
e = SWI(3, 0, SWI_OS_File | XOS_Bit,
18, szFilename, iFiletype);
if (e != NULL) {
switch (e->errnum) {
case 0x000113: /* ROM */
case 0x0104e1: /* Read-only floppy DOSFS */
case 0x0108c9: /* Read-only floppy ADFS */
case 0x013803: /* Read-only ArcFS */
case 0x80344a: /* CD-ROM */
break;
default:
werr(0, "Set Filetype error %d: %s",
e->errnum, e->errmess);
break;
}
}
} /* end of vSetFileType */
/*
* Check if the directory part of the given file exists, make the directory
* if it does not exist yet.
* Returns TRUE in case of success, otherwise FALSE.
*/
BOOL
bMakeDirectory(const char *szFilename)
{
os_error *e;
char *pcLastDot;
int iObjectType;
char szDirectory[PATH_MAX+1];
DBG_MSG("bMakeDirectory");
fail(szFilename == NULL || szFilename[0] == '\0');
DBG_MSG(szFilename);
if (strlen(szFilename) >= sizeof(szDirectory)) {
DBG_DEC(strlen(szFilename));
return FALSE;
}
strcpy(szDirectory, szFilename);
pcLastDot = strrchr(szDirectory, '.');
if (pcLastDot == NULL) {
/* No directory equals current directory */
DBG_MSG("No directory part given");
return TRUE;
}
*pcLastDot = '\0';
DBG_MSG(szDirectory);
/* Check if the name exists */
e = SWI(2, 1, SWI_OS_File | XOS_Bit,
17, szDirectory,
&iObjectType);
if (e != NULL) {
werr(0, "Directory check %d: %s", e->errnum, e->errmess);
return FALSE;
}
if (iObjectType == 2) {
/* The name exists and it is a directory */
DBG_MSG("The directory already exists");
return TRUE;
}
if (iObjectType != 0) {
/* The name exists and it is not a directory */
DBG_DEC(iObjectType);
return FALSE;
}
/* The name does not exist, make the directory */
e = SWI(5, 0, SWI_OS_File | XOS_Bit,
8, szDirectory, 0, 0, 0);
if (e != NULL) {
werr(0, "I can't make a directory %d: %s",
e->errnum, e->errmess);
return FALSE;
}
return TRUE;
} /* end of bMakeDirectory */
/*
* iReadCurrentAlphabetNumber
* This function reads the current Alphabet number.
* Returns the current Alphabet number when successful, otherwise -1
*/
int
iReadCurrentAlphabetNumber(void)
{
os_error *e;
int iAlphabetNumber;
e = SWI(2, 2, SWI_OS_Byte | XOS_Bit,
71, 127,
NULL, &iAlphabetNumber);
if (e == NULL) {
return iAlphabetNumber;
}
werr(0, "Read alphabet error %d: %s", e->errnum, e->errmess);
return -1;
} /* end of iReadCurrentAlphabetNumber */
/*
* iGetRiscOsVersion - get the RISC OS version number
*
* returns the RISC OS version * 100
*/
int
iGetRiscOsVersion(void)
{
os_error *e;
int iVersion;
e = SWI(3, 2, SWI_OS_Byte | XOS_Bit,
129, 0, 0xff,
NULL, &iVersion);
if (e != NULL) {
werr(0, "Read RISC OS version error %d: %s",
e->errnum, e->errmess);
return 0;
}
switch (iVersion) {
case 0xa0: /* Arthur 1.20 */
return 120;
case 0xa1: /* RISC OS 2.00 */
return 200;
case 0xa2: /* RISC OS 2.01 */
return 201;
case 0xa3: /* RISC OS 3.00 */
return 300;
case 0xa4: /* RISC OS 3.1x */
return 310;
case 0xa5: /* RISC OS 3.50 */
return 350;
case 0xa6: /* RISC OS 3.60 */
return 360;
case 0xa7: /* RISC OS 3.7x */
return 370;
case 0xa8: /* RISC OS 4.0x */
return 400;
default:
if (iVersion >= 0xa9 && iVersion <= 0xaf) {
/* RISC OS 4.10 and up */
return 410;
}
/* Unknown version */
return 0;
}
} /* end of iGetRiscOsVersion */
#if defined(DEBUG)
BOOL
bGetJpegInfo(UCHAR *pucJpeg, size_t tJpegSize)
{
os_error *e;
int iReg0, iReg4, iReg5;
e = SWI(3, 6, JPEG_Info | XOS_Bit,
0x00, pucJpeg, tJpegSize,
&iReg0, NULL, NULL, NULL, &iReg4, &iReg5);
if (e == NULL) {
if (iReg0 & BIT(2)) {
DBG_MSG("Pixel density is a simple ratio");
} else {
DBG_MSG("Pixel density is in dpi");
}
DBG_DEC(iReg4);
DBG_DEC(iReg5);
return TRUE;
}
werr(0, "JPEG Info error %d: %s", e->errnum, e->errmess);
return FALSE;
} /* end of bGetJpegInfo */
#endif /* DEBUG */

117
src/rowlist.c Normal file
View File

@@ -0,0 +1,117 @@
/*
* rowlist.c
* Copyright (C) 1998-2004 A.J. van Os; Released under GPL
*
* Description:
* Build, read and destroy a list of Word table-row information
*/
#include <stdlib.h>
#include <string.h>
#include "antiword.h"
/*
* Private structure to hide the way the information
* is stored from the rest of the program
*/
typedef struct row_desc_tag {
row_block_type tInfo;
struct row_desc_tag *pNext;
} row_desc_type;
/* Variables needed to write the Row Information List */
static row_desc_type *pAnchor = NULL;
static row_desc_type *pRowLast = NULL;
/* Variable needed to read the Row Information List */
static row_desc_type *pRowCurrent = NULL;
/*
* vDestroyRowInfoList - destroy the Row Information List
*/
void
vDestroyRowInfoList(void)
{
row_desc_type *pCurr, *pNext;
DBG_MSG("vDestroyRowInfoList");
/* Free the Row Information List */
pCurr = pAnchor;
while (pCurr != NULL) {
pNext = pCurr->pNext;
pCurr = xfree(pCurr);
pCurr = pNext;
}
pAnchor = NULL;
/* Reset all control variables */
pRowLast = NULL;
pRowCurrent = NULL;
} /* end of vDestroyRowInfoList */
/*
* vAdd2RowInfoList - Add an element to the Row Information List
*/
void
vAdd2RowInfoList(const row_block_type *pRowBlock)
{
row_desc_type *pListMember;
short *psTmp;
int iIndex;
fail(pRowBlock == NULL);
if (pRowBlock->ulFileOffsetStart == FC_INVALID ||
pRowBlock->ulFileOffsetEnd == FC_INVALID ||
pRowBlock->ulFileOffsetStart == pRowBlock->ulFileOffsetEnd) {
DBG_HEX_C(pRowBlock->ulFileOffsetStart != FC_INVALID,
pRowBlock->ulFileOffsetStart);
DBG_HEX_C(pRowBlock->ulFileOffsetEnd != FC_INVALID,
pRowBlock->ulFileOffsetEnd);
return;
}
NO_DBG_HEX(pRowBlock->ulFileOffsetStart);
NO_DBG_HEX(pRowBlock->ulFileOffsetEnd);
NO_DBG_DEC(pRowBlock->ucNumberOfColumns);
/* Create the new list member */
pListMember = xmalloc(sizeof(row_desc_type));
/* Fill the new list member */
pListMember->tInfo = *pRowBlock;
pListMember->pNext = NULL;
/* Correct the values where needed */
for (iIndex = 0, psTmp = pListMember->tInfo.asColumnWidth;
iIndex < (int)pListMember->tInfo.ucNumberOfColumns;
iIndex++, psTmp++) {
if (*psTmp < 0) {
*psTmp = 0;
DBG_MSG("The column width was negative");
}
}
/* Add the new member to the list */
if (pAnchor == NULL) {
pAnchor = pListMember;
pRowCurrent = pListMember;
} else {
fail(pRowLast == NULL);
pRowLast->pNext = pListMember;
}
pRowLast = pListMember;
} /* end of vAdd2RowInfoList */
/*
* Get the next item in the Row Information List
*/
const row_block_type *
pGetNextRowInfoListItem(void)
{
const row_block_type *pItem;
if (pRowCurrent == NULL) {
return NULL;
}
pItem = &pRowCurrent->tInfo;
pRowCurrent = pRowCurrent->pNext;
return pItem;
} /* end of pGetNextRowInfoListItem */

387
src/saveas.c Normal file
View File

@@ -0,0 +1,387 @@
/*
* saveas.c
* Copyright (C) 1998-2001 A.J. van Os; Released under GPL
*
* Description:
* Functions to save the results as a textfile or a drawfile
*/
#include <stdio.h>
#include <string.h>
#include "DeskLib:Menu.h"
#include "DeskLib:Save.h"
#include "DeskLib:Template.h"
#include "DeskLib:Window.h"
#include "drawfile.h"
#include "antiword.h"
/* The window handle of the save window */
static window_handle tSaveWindow = 0;
/* Xfer_send box fields */
#define DRAG_SPRITE 3
#define OK_BUTTON 0
#define CANCEL_BUTTON (-1)
#define FILENAME_ICON 2
/*
* saveas - a wrapper around Save_InitSaveWindowhandler
*/
static void
saveas(int iFileType, char *szOutfile, size_t tEstSize,
save_filesaver save_function, void *pvReference)
{
TRACE_MSG("saveas");
if (tSaveWindow == 0) {
tSaveWindow = Window_Create("xfer_send", template_TITLEMIN);
}
Icon_SetText(tSaveWindow, FILENAME_ICON, szOutfile);
Window_Show(tSaveWindow, open_UNDERPOINTER);
(void)Save_InitSaveWindowHandler(tSaveWindow, FALSE, TRUE, TRUE,
DRAG_SPRITE, OK_BUTTON, CANCEL_BUTTON, FILENAME_ICON,
save_function, NULL, NULL, tEstSize, iFileType, pvReference);
} /* end of saveas */
static BOOL
bWrite2File(void *pvBytes, size_t tSize, FILE *pFile, const char *szFilename)
{
if (fwrite(pvBytes, sizeof(char), tSize, pFile) != tSize) {
werr(0, "I can't write to '%s'", szFilename);
return FALSE;
}
return TRUE;
} /* end of bWrite2File */
/*
* bText2File - Save the generated draw file to a Text file
*/
static BOOL
bText2File(char *szFilename, void *pvHandle)
{
FILE *pFile;
diagram_type *pDiag;
drawfile_object *pObj;
drawfile_text *pText;
const char *pcTmp;
int iToGo, iX, iYtopPrev, iHeight, iLines;
BOOL bFirst, bIndent, bSuccess;
TRACE_MSG("bText2File");
fail(szFilename == NULL || szFilename[0] == '\0');
fail(pvHandle == NULL);
DBG_MSG(szFilename);
pDiag = (diagram_type *)pvHandle;
pFile = fopen(szFilename, "w");
if (pFile == NULL) {
werr(0, "I can't open '%s' for writing", szFilename);
return FALSE;
}
bFirst = TRUE;
iYtopPrev = 0;
iHeight = (int)lWord2DrawUnits20(DEFAULT_FONT_SIZE);
bSuccess = TRUE;
fail(pDiag->tInfo.length < offsetof(drawfile_diagram, objects));
iToGo = pDiag->tInfo.length - offsetof(drawfile_diagram, objects);
DBG_DEC(iToGo);
pcTmp = (const char *)pDiag->tInfo.data +
offsetof(drawfile_diagram, objects);
while (iToGo > 0 && bSuccess) {
pObj = (drawfile_object *)pcTmp;
switch (pObj->type) {
case drawfile_TYPE_TEXT:
pText = &pObj->data.text;
/* Compute the number of lines */
iLines = (iYtopPrev - pText->bbox.max.y +
iHeight / 2) / iHeight;
DBG_DEC_C(iLines < 0, iYtopPrev);
DBG_DEC_C(iLines < 0, pText->bbox.max.y);
fail(iLines < 0);
bIndent = iLines > 0 || bFirst;
bFirst = FALSE;
/* Print the newlines */
while (iLines > 0 && bSuccess) {
bSuccess = bWrite2File("\n",
1, pFile, szFilename);
iLines--;
}
/* Print the indentation */
if (bIndent && bSuccess) {
for (iX = Drawfile_ScreenToDraw(8);
iX <= pText->bbox.min.x && bSuccess;
iX += Drawfile_ScreenToDraw(16)) {
bSuccess = bWrite2File(" ",
1, pFile, szFilename);
}
}
if (!bSuccess) {
break;
}
/* Print the text object */
bSuccess = bWrite2File(pText->text,
strlen(pText->text), pFile, szFilename);
/* Setup for the next object */
iYtopPrev = pText->bbox.max.y;
iHeight = pText->bbox.max.y - pText->bbox.min.y;
break;
case drawfile_TYPE_FONT_TABLE:
case drawfile_TYPE_PATH:
case drawfile_TYPE_SPRITE:
case drawfile_TYPE_JPEG:
/* These are not relevant in a textfile */
break;
default:
DBG_DEC(pObj->type);
bSuccess = FALSE;
break;
}
pcTmp += pObj->size;
iToGo -= pObj->size;
}
DBG_DEC_C(iToGo != 0, iToGo);
if (bSuccess) {
bSuccess = bWrite2File("\n", 1, pFile, szFilename);
}
(void)fclose(pFile);
if (bSuccess) {
vSetFiletype(szFilename, FILETYPE_TEXT);
} else {
(void)remove(szFilename);
werr(0, "Unable to save textfile '%s'", szFilename);
}
return bSuccess;
} /* end of bText2File */
/*
* bSaveTextfile - save the diagram as a text file
*/
BOOL
bSaveTextfile(event_pollblock *pEvent, void *pvReference)
{
diagram_type *pDiag;
size_t tRecLen, tNbrRecs, tEstSize;
TRACE_MSG("bSaveTextfile");
fail(pEvent == NULL);
fail(pvReference == NULL);
pDiag = (diagram_type *)pvReference;
switch (pEvent->type) {
case event_SEND: /* From a menu */
fail(pEvent->data.message.header.action != message_MENUWARN);
if (menu_currentopen != pDiag->pSaveMenu ||
pEvent->data.message.data.menuwarn.selection[0] !=
SAVEMENU_SAVETEXT) {
return FALSE;
}
break;
case event_KEY: /* From a key short cut */
if (pEvent->data.key.caret.window != pDiag->tMainWindow) {
return FALSE;
}
break;
default:
DBG_DEC(pEvent->type);
return FALSE;
}
tRecLen = sizeof(drawfile_text) + DEFAULT_SCREEN_WIDTH * 2 / 3;
tNbrRecs = pDiag->tInfo.length / tRecLen + 1;
tEstSize = tNbrRecs * DEFAULT_SCREEN_WIDTH * 2 / 3;
DBG_DEC(tEstSize);
saveas(FILETYPE_TEXT, "WordText", tEstSize, bText2File, pDiag);
return TRUE;
} /* end of bSaveTextfile */
/*
* bDraw2File - Save the generated draw file to a Draw file
*
* Remark: This is not a simple copy action. The origin of the
* coordinates (0,0) must move from the top-left corner to the
* bottom-left corner.
*/
static BOOL
bDraw2File(char *szFilename, void *pvHandle)
{
FILE *pFile;
diagram_type *pDiagram;
wimp_box *pBbox;
drawfile_object *pObj;
drawfile_text *pText;
drawfile_path *pPath;
drawfile_sprite *pSprite;
drawfile_jpeg *pJpeg;
int *piPath;
char *pcTmp;
int iYadd, iToGo, iSize;
BOOL bSuccess;
TRACE_MSG("bDraw2File");
fail(szFilename == NULL || szFilename[0] == '\0');
fail(pvHandle == NULL);
NO_DBG_MSG(szFilename);
pDiagram = (diagram_type *)pvHandle;
pFile = fopen(szFilename, "wb");
if (pFile == NULL) {
werr(0, "I can't open '%s' for writing", szFilename);
return FALSE;
}
iToGo = pDiagram->tInfo.length;
DBG_DEC(iToGo);
pcTmp = pDiagram->tInfo.data;
bSuccess = bWrite2File(pcTmp,
offsetof(drawfile_diagram, bbox), pFile, szFilename);
if (bSuccess) {
pcTmp += offsetof(drawfile_diagram, bbox);
iToGo -= offsetof(drawfile_diagram, bbox);
pBbox = (wimp_box *)pcTmp;
iYadd = -pBbox->min.y;
pBbox->min.y += iYadd;
pBbox->max.y += iYadd;
bSuccess = bWrite2File(pcTmp,
sizeof(*pBbox), pFile, szFilename);
iToGo -= sizeof(*pBbox);
DBG_DEC(iToGo);
pcTmp += sizeof(*pBbox);
} else {
iYadd = 0;
}
while (iToGo > 0 && bSuccess) {
pObj = (drawfile_object *)pcTmp;
iSize = pObj->size;
switch (pObj->type) {
case drawfile_TYPE_FONT_TABLE:
bSuccess = bWrite2File(pcTmp,
iSize, pFile, szFilename);
pcTmp += iSize;
iToGo -= iSize;
break;
case drawfile_TYPE_TEXT:
pText = &pObj->data.text;
/* First correct the coordinates */
pText->bbox.min.y += iYadd;
pText->bbox.max.y += iYadd;
pText->base.y += iYadd;
/* Now write the information to file */
bSuccess = bWrite2File(pcTmp,
iSize, pFile, szFilename);
pcTmp += pObj->size;
iToGo -= pObj->size;
break;
case drawfile_TYPE_PATH:
pPath = &pObj->data.path;
/* First correct the coordinates */
pPath->bbox.min.y += iYadd;
pPath->bbox.max.y += iYadd;
/* Now write the information to file */
bSuccess = bWrite2File(pPath,
sizeof(*pPath), pFile, szFilename);
pcTmp += sizeof(*pPath);
iSize = pObj->size - sizeof(*pPath);
fail(iSize < 14 * sizeof(int));
/* Second correct the path coordinates */
piPath = xmalloc(iSize);
memcpy(piPath, pcTmp, iSize);
piPath[ 2] += iYadd;
piPath[ 5] += iYadd;
piPath[ 8] += iYadd;
piPath[11] += iYadd;
if (bSuccess) {
bSuccess = bWrite2File(piPath,
iSize, pFile, szFilename);
pcTmp += iSize;
}
piPath = xfree(piPath);
iToGo -= pObj->size;
break;
case drawfile_TYPE_SPRITE:
pSprite = &pObj->data.sprite;
/* First correct the coordinates */
pSprite->bbox.min.y += iYadd;
pSprite->bbox.max.y += iYadd;
/* Now write the information to file */
bSuccess = bWrite2File(pcTmp,
iSize, pFile, szFilename);
pcTmp += pObj->size;
iToGo -= pObj->size;
break;
case drawfile_TYPE_JPEG:
pJpeg = &pObj->data.jpeg;
/* First correct the coordinates */
pJpeg->bbox.min.y += iYadd;
pJpeg->bbox.max.y += iYadd;
pJpeg->trfm.entries[2][1] += iYadd;
/* Now write the information to file */
bSuccess = bWrite2File(pcTmp,
iSize, pFile, szFilename);
pcTmp += pObj->size;
iToGo -= pObj->size;
break;
default:
DBG_DEC(pObj->type);
bSuccess = FALSE;
break;
}
}
DBG_DEC_C(iToGo != 0, iToGo);
(void)fclose(pFile);
if (bSuccess) {
vSetFiletype(szFilename, FILETYPE_DRAW);
} else {
(void)remove(szFilename);
werr(0, "Unable to save drawfile '%s'", szFilename);
}
return bSuccess;
} /* end of bDraw2File */
/*
* bSaveDrawfile - save the diagram as a draw file
*/
BOOL
bSaveDrawfile(event_pollblock *pEvent, void *pvReference)
{
diagram_type *pDiag;
size_t tEstSize;
TRACE_MSG("bSaveDrawfile");
fail(pEvent == NULL);
fail(pvReference == NULL);
pDiag = (diagram_type *)pvReference;
switch (pEvent->type) {
case event_SEND: /* From a menu */
fail(pEvent->data.message.header.action != message_MENUWARN);
if (menu_currentopen != pDiag->pSaveMenu ||
pEvent->data.message.data.menuwarn.selection[0] !=
SAVEMENU_SAVEDRAW) {
return FALSE;
}
break;
case event_KEY: /* From a key short cut */
if (pEvent->data.key.caret.window != pDiag->tMainWindow) {
return FALSE;
}
break;
default:
DBG_DEC(pEvent->type);
return FALSE;
}
tEstSize = pDiag->tInfo.length;
DBG_DEC(tEstSize);
saveas(FILETYPE_DRAW, "WordDraw", tEstSize, bDraw2File, pDiag);
return TRUE;
} /* end of bSaveDrawfile */

165
src/sectlist.c Normal file
View File

@@ -0,0 +1,165 @@
/*
* sectlist.c
* Copyright (C) 2001-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Build, read and destroy list(s) of Word section information
*/
#include <stddef.h>
#include <string.h>
#include "antiword.h"
/*
* Private structure to hide the way the information
* is stored from the rest of the program
*/
typedef struct section_mem_tag {
section_block_type tInfo;
ULONG ulCharPos;
struct section_mem_tag *pNext;
} section_mem_type;
/* Variables needed to write the Section Information List */
static section_mem_type *pAnchor = NULL;
static section_mem_type *pSectionLast = NULL;
/*
* vDestroySectionInfoList - destroy the Section Information List
*/
void
vDestroySectionInfoList(void)
{
section_mem_type *pCurr, *pNext;
DBG_MSG("vDestroySectionInfoList");
/* Free the Section Information List */
pCurr = pAnchor;
while (pCurr != NULL) {
pNext = pCurr->pNext;
pCurr = xfree(pCurr);
pCurr = pNext;
}
pAnchor = NULL;
/* Reset all control variables */
pSectionLast = NULL;
} /* end of vDestroySectionInfoList */
/*
* vAdd2SectionInfoList - Add an element to the Section Information List
*/
void
vAdd2SectionInfoList(const section_block_type *pSection, ULONG ulCharPos)
{
section_mem_type *pListMember;
fail(pSection == NULL);
/* Create list member */
pListMember = xmalloc(sizeof(section_mem_type));
/* Fill the list member */
pListMember->tInfo = *pSection;
pListMember->ulCharPos = ulCharPos;
pListMember->pNext = NULL;
/* Add the new member to the list */
if (pAnchor == NULL) {
pAnchor = pListMember;
} else {
fail(pSectionLast == NULL);
pSectionLast->pNext = pListMember;
}
pSectionLast = pListMember;
} /* vAdd2SectionInfoList */
/*
* vGetDefaultSection - fill the section struct with default values
*/
void
vGetDefaultSection(section_block_type *pSection)
{
(void)memset(pSection, 0, sizeof(*pSection));
pSection->bNewPage = TRUE;
} /* end of vGetDefaultSection */
/*
* vDefault2SectionInfoList - Add a default to the Section Information List
*/
void
vDefault2SectionInfoList(ULONG ulCharPos)
{
section_block_type tSection;
vGetDefaultSection(&tSection);
vAdd2SectionInfoList(&tSection, ulCharPos);
} /* end of vDefault2SectionInfoList */
/*
* pGetSectionInfo - get the section information
*/
const section_block_type *
pGetSectionInfo(const section_block_type *pOld, ULONG ulCharPos)
{
const section_mem_type *pCurr;
if (pOld == NULL || ulCharPos == 0) {
if (pAnchor == NULL) {
/* There are no records, make one */
vDefault2SectionInfoList(0);
fail(pAnchor == NULL);
}
/* The first record */
NO_DBG_MSG("First record");
return &pAnchor->tInfo;
}
NO_DBG_HEX(ulCharPos);
for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
NO_DBG_HEX(pCurr->ulCharPos);
if (ulCharPos == pCurr->ulCharPos ||
ulCharPos + 1 == pCurr->ulCharPos) {
NO_DBG_HEX(pCurr->ulCharPos);
return &pCurr->tInfo;
}
}
return pOld;
} /* end of pGetSectionInfo */
/*
* tGetNumberOfSections - get the number of sections
*/
size_t
tGetNumberOfSections(void)
{
const section_mem_type *pCurr;
size_t tCounter;
for (tCounter = 0, pCurr = pAnchor;
pCurr != NULL;
tCounter++, pCurr = pCurr->pNext)
; /* Empty */
return tCounter;
} /* end of tGetNumberOfSections */
/*
* ucGetSepHdrFtrSpecification - get the Heder/footer specification
*/
UCHAR
ucGetSepHdrFtrSpecification(size_t tSectionNumber)
{
const section_mem_type *pCurr;
size_t tIndex;
for (tIndex = 0, pCurr = pAnchor;
tIndex < tSectionNumber && pCurr != NULL;
tIndex++, pCurr = pCurr->pNext)
; /* Empty */
if (pCurr == NULL) {
DBG_DEC(tSectionNumber);
DBG_FIXME();
return 0x00;
}
return pCurr->tInfo.ucHdrFtrSpecification;
} /* end of ucGetSepHdrFtrSpecification */

145
src/startup.c Normal file
View File

@@ -0,0 +1,145 @@
/*
* startup.c
* Copyright (C) 1998-2001 A.J. van Os; Released under GPL
*
* Description:
* Try to force a single startup of !Antiword
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "DeskLib:Error.h"
#include "DeskLib:Event.h"
#include "DeskLib:SWI.h"
#include "antiword.h"
#if !defined(TaskManager_EnumerateTasks)
#define TaskManager_EnumerateTasks 0x042681
#endif /* TaskManager_EnumerateTasks */
/*
* bIsMatch - decide whether the two strings match
*
* like strcmp, but this one ignores case
*/
static BOOL
bIsMatch(const char *szStr1, const char *szStr2)
{
const char *pcTmp1, *pcTmp2;
for (pcTmp1 = szStr1, pcTmp2 = szStr2;
*pcTmp1 != '\0';
pcTmp1++, pcTmp2++) {
if (toupper(*pcTmp1) != toupper(*pcTmp2)) {
return FALSE;
}
}
return *pcTmp2 == '\0';
} /* end of bIsMatch */
/*
* tGetTaskHandle - get the task handle of the given task
*
* returns the task handle when found, otherwise 0
*/
static task_handle
tGetTaskHandle(const char *szTaskname)
{
const char *pcTmp;
int iReg0, iIndex;
int aiBuffer[4];
char szTmp[21];
iReg0 = 0;
do {
/* Get info on the next task */
Error_CheckFatal(SWI(3, 1, TaskManager_EnumerateTasks | XOS_Bit,
iReg0, aiBuffer, sizeof(aiBuffer), &iReg0));
/* Copy the (control character terminated) task name */
for (iIndex = 0, pcTmp = (const char *)aiBuffer[1];
iIndex < elementsof(szTmp);
iIndex++, pcTmp++) {
if (iscntrl(*pcTmp)) {
szTmp[iIndex] = '\0';
break;
}
szTmp[iIndex] = *pcTmp;
}
szTmp[elementsof(szTmp) - 1] = '\0';
if (bIsMatch(szTmp, szTaskname)) {
/* Task found */
return (task_handle)aiBuffer[0];
}
} while (iReg0 >= 0);
/* Task not found */
return 0;
} /* end of tGetTaskHandle */
int
main(int argc, char **argv)
{
message_block tMsg;
task_handle tTaskHandle;
size_t tArgLen;
int aiMessages[] = {0};
char szCommand[512];
Event_Initialise3("StartUp", 310, aiMessages);
if (argc > 1) {
tArgLen = strlen(argv[1]);
} else {
tArgLen = 0;
}
if (tArgLen >= sizeof(tMsg.data.dataload.filename)) {
werr(1, "Input filename too long");
return EXIT_FAILURE;
}
tTaskHandle = tGetTaskHandle("antiword");
if (tTaskHandle == 0) {
/* Antiword is not active */
strcpy(szCommand, "chain:<Antiword$Dir>.!Antiword");
if (argc > 1) {
strcat(szCommand, " ");
strcat(szCommand, argv[1]);
}
#if defined(DEBUG)
strcat(szCommand, " ");
strcat(szCommand, "2><Antiword$Dir>.Debug");
#endif /* DEBUG */
system(szCommand);
/* If we reach here something has gone wrong */
return EXIT_FAILURE;
}
/* Antiword is active */
if (argc > 1) {
/*
* Send the argument to Antiword by imitating a
* drag-and-drop to Antiword's iconbar icon
*/
memset(&tMsg, 0, sizeof(tMsg));
tMsg.header.size = ROUND4(offsetof(message_block, data) +
offsetof(message_dataload, filename) +
1 + tArgLen);
tMsg.header.yourref = 0;
tMsg.header.action = message_DATALOAD;
tMsg.data.dataload.window = window_ICONBAR;
tMsg.data.dataload.icon = -1;
tMsg.data.dataload.size = 0;
tMsg.data.dataload.filetype = FILETYPE_MSWORD;
strcpy(tMsg.data.dataload.filename, argv[1]);
Error_CheckFatal(Wimp_SendMessage(event_SEND,
&tMsg, tTaskHandle, 0));
return EXIT_SUCCESS;
} else {
/* Give an error message and return */
werr(1, "Antiword is already running");
return EXIT_FAILURE;
}
} /* end of main */

487
src/stylelist.c Normal file
View File

@@ -0,0 +1,487 @@
/*
* stylelist.c
* Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
*
* Description:
* Build, read and destroy a list of Word style information
*/
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include "antiword.h"
/*
* Private structure to hide the way the information
* is stored from the rest of the program
*/
typedef struct style_mem_tag {
style_block_type tInfo;
ULONG ulSequenceNumber;
struct style_mem_tag *pNext;
} style_mem_type;
/* Variables needed to write the Style Information List */
static style_mem_type *pAnchor = NULL;
static style_mem_type *pStyleLast = NULL;
/* The type of conversion */
static conversion_type eConversionType = conversion_unknown;
/* The character set encoding */
static encoding_type eEncoding = encoding_neutral;
/* Values for efficiency reasons */
static const style_mem_type *pMidPtr = NULL;
static BOOL bMoveMidPtr = FALSE;
static BOOL bInSequence = TRUE;
/*
* vDestroyStyleInfoList - destroy the Style Information List
*/
void
vDestroyStyleInfoList(void)
{
style_mem_type *pCurr, *pNext;
DBG_MSG("vDestroyStyleInfoList");
/* Free the Style Information List */
pCurr = pAnchor;
while (pCurr != NULL) {
pNext = pCurr->pNext;
pCurr = xfree(pCurr);
pCurr = pNext;
}
pAnchor = NULL;
/* Reset all control variables */
pStyleLast = NULL;
pMidPtr = NULL;
bMoveMidPtr = FALSE;
bInSequence = TRUE;
} /* end of vDestroyStyleInfoList */
/*
* vConvertListCharacter - convert the list character
*/
static void
vConvertListCharacter(UCHAR ucNFC, USHORT usListChar, char *szListChar)
{
options_type tOptions;
size_t tLen;
fail(szListChar == NULL);
fail(szListChar[0] != '\0');
if (usListChar < 0x80 && isprint((int)usListChar)) {
DBG_CHR_C(isalnum((int)usListChar), usListChar);
szListChar[0] = (char)usListChar;
szListChar[1] = '\0';
return;
}
if (ucNFC != LIST_SPECIAL &&
ucNFC != LIST_SPECIAL2 &&
ucNFC != LIST_BULLETS) {
szListChar[0] = '.';
szListChar[1] = '\0';
return;
}
if (eConversionType == conversion_unknown ||
eEncoding == encoding_neutral) {
vGetOptions(&tOptions);
eConversionType = tOptions.eConversionType;
eEncoding = tOptions.eEncoding;
}
switch (usListChar) {
case 0x0000: case 0x00b7: case 0x00fe: case 0xf021: case 0xf043:
case 0xf06c: case 0xf093: case 0xf0b7:
usListChar = 0x2022; /* BULLET */
break;
case 0x0096: case 0xf02d:
usListChar = 0x2013; /* EN DASH */
break;
case 0x00a8:
usListChar = 0x2666; /* BLACK DIAMOND SUIT */
break;
case 0x00de:
usListChar = 0x21d2; /* RIGHTWARDS DOUBLE ARROW */
break;
case 0x00e0: case 0xf074:
usListChar = 0x25ca; /* LOZENGE */
break;
case 0x00e1:
usListChar = 0x2329; /* LEFT ANGLE BRACKET */
break;
case 0xf020:
usListChar = 0x0020; /* SPACE */
break;
case 0xf041:
usListChar = 0x270c; /* VICTORY HAND */
break;
case 0xf066:
usListChar = 0x03d5; /* GREEK PHI SYMBOL */
break;
case 0xf06e:
usListChar = 0x25a0; /* BLACK SQUARE */
break;
case 0xf06f: case 0xf070: case 0xf0a8:
usListChar = 0x25a1; /* WHITE SQUARE */
break;
case 0xf071:
usListChar = 0x2751; /* LOWER RIGHT SHADOWED WHITE SQUARE */
break;
case 0xf075: case 0xf077:
usListChar = 0x25c6; /* BLACK DIAMOND */
break;
case 0xf076:
usListChar = 0x2756; /* BLACK DIAMOND MINUS WHITE X */
break;
case 0xf0a7:
usListChar = 0x25aa; /* BLACK SMALL SQUARE */
break;
case 0xf0d8:
usListChar = 0x27a2; /* RIGHTWARDS ARROWHEAD */
break;
case 0xf0e5:
usListChar = 0x2199; /* SOUTH WEST ARROW */
break;
case 0xf0f0:
usListChar = 0x21e8; /* RIGHTWARDS WHITE ARROW */
break;
case 0xf0fc:
usListChar = 0x2713; /* CHECK MARK */
break;
default:
if ((usListChar >= 0xe000 && usListChar < 0xf900) ||
(usListChar < 0x80 && !isprint((int)usListChar))) {
/*
* All remaining private area characters and all
* remaining non-printable ASCII characters to their
* default bullet character
*/
DBG_HEX(usListChar);
DBG_FIXME();
if (ucNFC == LIST_SPECIAL || ucNFC == LIST_SPECIAL2) {
usListChar = 0x2190; /* LEFTWARDS ARROW */
} else {
usListChar = 0x2022; /* BULLET */
}
}
break;
}
if (eEncoding == encoding_utf_8) {
tLen = tUcs2Utf8(usListChar, szListChar, 4);
szListChar[tLen] = '\0';
} else {
switch (usListChar) {
case 0x03d5: case 0x25a1: case 0x25c6: case 0x25ca:
case 0x2751:
szListChar[0] = 'o';
break;
case 0x2013: case 0x2500:
szListChar[0] = '-';
break;
case 0x2190: case 0x2199: case 0x2329:
szListChar[0] = '<';
break;
case 0x21d2:
szListChar[0] = '=';
break;
case 0x21e8: case 0x27a2:
szListChar[0] = '>';
break;
case 0x25a0: case 0x25aa:
szListChar[0] = '.';
break;
case 0x2666:
szListChar[0] = OUR_DIAMOND;
break;
case 0x270c:
szListChar[0] = 'x';
break;
case 0x2713:
szListChar[0] = 'V';
break;
case 0x2756:
szListChar[0] = '*';
break;
case 0x2022:
default:
vGetBulletValue(eConversionType, eEncoding,
szListChar, 2);
break;
}
tLen = 1;
}
szListChar[tLen] = '\0';
} /* end of vConvertListCharacter */
/*
* eGetNumType - get the level type from the given level number
*
* Returns the level type
*/
level_type_enum
eGetNumType(UCHAR ucNumLevel)
{
switch (ucNumLevel) {
case 1: case 2: case 3: case 4: case 5:
case 6: case 7: case 8: case 9:
return level_type_outline;
case 10:
return level_type_numbering;
case 11:
return level_type_sequence;
case 12:
return level_type_pause;
default:
return level_type_none;
}
} /* end of eGetNumType */
/*
* vCorrectStyleValues - correct style values that Antiword can't use
*/
void
vCorrectStyleValues(style_block_type *pStyleBlock)
{
if (pStyleBlock->usBeforeIndent > 0x7fff) {
pStyleBlock->usBeforeIndent = 0;
} else if (pStyleBlock->usBeforeIndent > 2160) {
/* 2160 twips = 1.5 inches or 38.1 mm */
DBG_DEC(pStyleBlock->usBeforeIndent);
pStyleBlock->usBeforeIndent = 2160;
}
if (pStyleBlock->usIstd >= 1 &&
pStyleBlock->usIstd <= 9 &&
pStyleBlock->usBeforeIndent < HEADING_GAP) {
NO_DBG_DEC(pStyleBlock->usBeforeIndent);
pStyleBlock->usBeforeIndent = HEADING_GAP;
}
if (pStyleBlock->usAfterIndent > 0x7fff) {
pStyleBlock->usAfterIndent = 0;
} else if (pStyleBlock->usAfterIndent > 2160) {
/* 2160 twips = 1.5 inches or 38.1 mm */
DBG_DEC(pStyleBlock->usAfterIndent);
pStyleBlock->usAfterIndent = 2160;
}
if (pStyleBlock->usIstd >= 1 &&
pStyleBlock->usIstd <= 9 &&
pStyleBlock->usAfterIndent < HEADING_GAP) {
NO_DBG_DEC(pStyleBlock->usAfterIndent);
pStyleBlock->usAfterIndent = HEADING_GAP;
}
if (pStyleBlock->sLeftIndent < 0) {
pStyleBlock->sLeftIndent = 0;
}
if (pStyleBlock->sRightIndent > 0) {
pStyleBlock->sRightIndent = 0;
}
vConvertListCharacter(pStyleBlock->ucNFC,
pStyleBlock->usListChar,
pStyleBlock->szListChar);
} /* end of vCorrectStyleValues */
/*
* vAdd2StyleInfoList - Add an element to the Style Information List
*/
void
vAdd2StyleInfoList(const style_block_type *pStyleBlock)
{
style_mem_type *pListMember;
fail(pStyleBlock == NULL);
NO_DBG_MSG("bAdd2StyleInfoList");
if (pStyleBlock->ulFileOffset == FC_INVALID) {
NO_DBG_DEC(pStyleBlock->usIstd);
return;
}
NO_DBG_HEX(pStyleBlock->ulFileOffset);
NO_DBG_DEC_C(pStyleBlock->sLeftIndent != 0,
pStyleBlock->sLeftIndent);
NO_DBG_DEC_C(pStyleBlock->sRightIndent != 0,
pStyleBlock->sRightIndent);
NO_DBG_DEC_C(pStyleBlock->bNumPause, pStyleBlock->bNumPause);
NO_DBG_DEC_C(pStyleBlock->usIstd != 0, pStyleBlock->usIstd);
NO_DBG_DEC_C(pStyleBlock->usStartAt != 1, pStyleBlock->usStartAt);
NO_DBG_DEC_C(pStyleBlock->usAfterIndent != 0,
pStyleBlock->usAfterIndent);
NO_DBG_DEC_C(pStyleBlock->ucAlignment != 0, pStyleBlock->ucAlignment);
NO_DBG_DEC(pStyleBlock->ucNFC);
NO_DBG_HEX(pStyleBlock->usListChar);
if (pStyleLast != NULL &&
pStyleLast->tInfo.ulFileOffset == pStyleBlock->ulFileOffset) {
/*
* If two consecutive styles share the same
* offset, remember only the last style
*/
fail(pStyleLast->pNext != NULL);
pStyleLast->tInfo = *pStyleBlock;
/* Correct the values where needed */
vCorrectStyleValues(&pStyleLast->tInfo);
return;
}
/* Create list member */
pListMember = xmalloc(sizeof(style_mem_type));
/* Fill the list member */
pListMember->tInfo = *pStyleBlock;
pListMember->pNext = NULL;
/* Add the sequence number */
pListMember->ulSequenceNumber =
ulGetSeqNumber(pListMember->tInfo.ulFileOffset);
/* Correct the values where needed */
vCorrectStyleValues(&pListMember->tInfo);
/* Add the new member to the list */
if (pAnchor == NULL) {
pAnchor = pListMember;
/* For efficiency */
pMidPtr = pAnchor;
bMoveMidPtr = FALSE;
bInSequence = TRUE;
} else {
fail(pStyleLast == NULL);
pStyleLast->pNext = pListMember;
/* For efficiency */
if (bMoveMidPtr) {
pMidPtr = pMidPtr->pNext;
bMoveMidPtr = FALSE;
} else {
bMoveMidPtr = TRUE;
}
if (bInSequence) {
bInSequence = pListMember->ulSequenceNumber >
pStyleLast->ulSequenceNumber;
}
}
pStyleLast = pListMember;
} /* end of vAdd2StyleInfoList */
/*
* Get the record that follows the given recored in the Style Information List
*/
const style_block_type *
pGetNextStyleInfoListItem(const style_block_type *pCurr)
{
const style_mem_type *pRecord;
size_t tOffset;
if (pCurr == NULL) {
if (pAnchor == NULL) {
/* There are no records */
return NULL;
}
/* The first record is the only one without a predecessor */
return &pAnchor->tInfo;
}
tOffset = offsetof(style_mem_type, tInfo);
/* Many casts to prevent alignment warnings */
pRecord = (style_mem_type *)(void *)((char *)pCurr - tOffset);
fail(pCurr != &pRecord->tInfo);
if (pRecord->pNext == NULL) {
/* The last record has no successor */
return NULL;
}
return &pRecord->pNext->tInfo;
} /* end of pGetNextStyleInfoListItem */
/*
* Get the next text style
*/
const style_block_type *
pGetNextTextStyle(const style_block_type *pCurr)
{
const style_block_type *pRecord;
pRecord = pCurr;
do {
pRecord = pGetNextStyleInfoListItem(pRecord);
} while (pRecord != NULL &&
(pRecord->eListID == hdrftr_list ||
pRecord->eListID == macro_list ||
pRecord->eListID == annotation_list));
return pRecord;
} /* end of pGetNextTextStyle */
/*
* usGetIstd - get the istd that belongs to the given file offset
*/
USHORT
usGetIstd(ULONG ulFileOffset)
{
const style_mem_type *pCurr, *pBest, *pStart;
ULONG ulSeq, ulBest;
ulSeq = ulGetSeqNumber(ulFileOffset);
if (ulSeq == FC_INVALID) {
return ISTD_NORMAL;
}
NO_DBG_HEX(ulFileOffset);
NO_DBG_DEC(ulSeq);
if (bInSequence &&
pMidPtr != NULL &&
ulSeq > pMidPtr->ulSequenceNumber) {
/* The istd is in the second half of the chained list */
pStart = pMidPtr;
} else {
pStart = pAnchor;
}
pBest = NULL;
ulBest = 0;
for (pCurr = pStart; pCurr != NULL; pCurr = pCurr->pNext) {
if (pCurr->ulSequenceNumber != FC_INVALID &&
(pBest == NULL || pCurr->ulSequenceNumber > ulBest) &&
pCurr->ulSequenceNumber <= ulSeq) {
pBest = pCurr;
ulBest = pCurr->ulSequenceNumber;
}
if (bInSequence && pCurr->ulSequenceNumber > ulSeq) {
break;
}
}
NO_DBG_DEC(ulBest);
if (pBest == NULL) {
return ISTD_NORMAL;
}
NO_DBG_DEC(pBest->tInfo.usIstd);
return pBest->tInfo.usIstd;
} /* end of usGetIstd */
/*
* bStyleImpliesList - does style info implies being part of a list
*
* Decide whether the style information implies that the given paragraph is
* part of a list
*
* Returns TRUE when the paragraph is part of a list, otherwise FALSE
*/
BOOL
bStyleImpliesList(const style_block_type *pStyle, int iWordVersion)
{
fail(pStyle == NULL);
fail(iWordVersion < 0);
if (pStyle->usIstd >= 1 && pStyle->usIstd <= 9) {
/* These are heading levels */
return FALSE;
}
if (iWordVersion < 8) {
/* Check for old style lists */
return pStyle->ucNumLevel != 0;
}
/* Check for new style lists */
return pStyle->usListIndex != 0;
} /* end of bStyleImpliesList */

838
src/stylesheet.c Normal file
View File

@@ -0,0 +1,838 @@
/*
* stylesheet.c
* Copyright (C) 2001-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Build, read and destroy a list of stylesheet information
*
*/
#include <string.h>
#include "antiword.h"
#define SGC_PAP 1
#define SGC_CHP 2
/* Variables needed to describe the stylesheet list */
static style_block_type *atStyleInfo = NULL;
static font_block_type *atFontInfo = NULL;
static BOOL *abFilled = NULL;
static size_t tStdCount = 0;
/*
* vDestroyStylesheetList - destroy the stylesheet list
*/
void
vDestroyStylesheetList(void)
{
DBG_MSG("vDestroyStylesheetList");
tStdCount = 0;
atStyleInfo = xfree(atStyleInfo);
atFontInfo = xfree(atFontInfo);
abFilled = xfree(abFilled);
} /* end of vDestroyStylesheetList */
/*
* vGetDefaultStyle - fill the style struct with default values
*/
static void
vGetDefaultStyle(style_block_type *pStyle)
{
(void)memset(pStyle, 0, sizeof(*pStyle));
pStyle->usIstd = ISTD_INVALID;
pStyle->usIstdNext = ISTD_INVALID;
pStyle->usStartAt = 1;
pStyle->ucListLevel = 9;
} /* end of vGetDefaultStyle */
/*
* vGetDefaultFont - fill the font struct with default values
*/
static void
vGetDefaultFont(font_block_type *pFont, USHORT usDefaultFontNumber)
{
(void)memset(pFont, 0, sizeof(*pFont));
pFont->usFontSize = DEFAULT_FONT_SIZE;
if (usDefaultFontNumber <= (USHORT)UCHAR_MAX) {
pFont->ucFontNumber = (UCHAR)usDefaultFontNumber;
} else {
DBG_DEC(usDefaultFontNumber);
DBG_FIXME();
pFont->ucFontNumber = 0;
}
} /* end of vGetDefaultFont */
/*
* iGetStyleIndex - get the index of the record with the specified istd
*
* returns the index when found, otherwise -1
*/
static int
iGetStyleIndex(USHORT usIstd)
{
int iIndex;
fail(abFilled == NULL);
if (usIstd == ISTD_INVALID || abFilled == NULL) {
return -1;
}
for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
if (abFilled[iIndex] && atStyleInfo[iIndex].usIstd == usIstd) {
/* The record is filled and the istd matches */
return iIndex;
}
}
return -1;
} /* end of iGetStyleIndex */
/*
* Get a build-in style for Winword 1/2
*/
static void
vGetBuildinStyle(UCHAR ucStc, style_block_type *pStyle)
{
fail(pStyle == NULL);
/* Start with de defaults */
vGetDefaultStyle(pStyle);
/* Add the build-in style info */
switch (ucStc) {
case 246:
case 247:
case 248:
case 249:
case 250:
case 255:
pStyle->sLeftIndent = 720;
break;
case 251:
case 252:
pStyle->sLeftIndent = 360;
break;
case 253:
pStyle->usBeforeIndent = 120;
break;
case 254:
pStyle->usBeforeIndent = 240;
break;
default:
if (ucStc >= 233 && ucStc <= 239) {
pStyle->sLeftIndent = (239 - (short)ucStc) * 360;
}
if (ucStc >= 225 && ucStc <= 232) {
pStyle->sLeftIndent = (232 - (short)ucStc) * 720;
pStyle->sRightIndent = 720;
}
break;
}
} /* end of vGetBuildinStyle */
/*
* Get a build-in fontstyle for Winword 1/2
*/
static void
vGetBuildinFont(UCHAR ucStc, font_block_type *pFont)
{
fail(pFont == NULL);
/* Start with de defaults */
vGetDefaultFont(pFont, 0);
/* Add the build-in fontstyle info */
switch (ucStc) {
case 223:
case 244:
pFont->usFontSize = 16;
break;
case 246:
case 247:
case 248:
pFont->usFontStyle |= FONT_ITALIC;
break;
case 249:
pFont->usFontStyle |= FONT_UNDERLINE;
break;
case 250:
pFont->usFontStyle |= FONT_BOLD;
break;
case 251:
pFont->usFontStyle |= FONT_UNDERLINE;
pFont->usFontSize = 24;
break;
case 252:
pFont->usFontStyle |= FONT_BOLD;
pFont->usFontSize = 24;
break;
case 253:
pFont->ucFontNumber = 2;
pFont->usFontStyle |= FONT_BOLD;
pFont->usFontSize = 24;
break;
case 254:
pFont->ucFontNumber = 2;
pFont->usFontStyle |= (FONT_BOLD|FONT_UNDERLINE);
pFont->usFontSize = 24;
break;
default:
break;
}
} /* end of vGetBuildinFont */
/*
* Convert a stylecode (stc) as used by WinWord 1/2 into a styleindex (istd)
* as used by Word 6 and up
*/
USHORT
usStc2istd(UCHAR ucStc)
{
/* Old nil style to new nil style */
if (ucStc == 222) {
return STI_NIL;
}
/* Heading 1 through 9 must become istd 1 through 9 */
/* so 254 through 246 must become 1 through 9 and vice versa */
if ((ucStc >= 1 && ucStc <= 9) ||
(ucStc >= 246 && ucStc <= 254)) {
return 255 - (USHORT)ucStc;
}
return (USHORT)ucStc;
} /* end of usStd2istd */
/*
* Build the lists with Stylesheet Information for WinWord 1/2 files
*/
void
vGet2Stylesheet(FILE *pFile, int iWordVersion, const UCHAR *aucHeader)
{
style_block_type *pStyle;
font_block_type *pFont;
UCHAR *aucBuffer;
ULONG ulBeginStshInfo;
size_t tStshInfoLen, tName, tChpx, tPapx, tMaxIndex;
int iStIndex, iChpxIndex, iPapxIndex, iSt, iChpx, iPapx;
int iStd, iIndex, iBaseStyleIndex, iCounter;
USHORT usBaseStyle;
UCHAR ucStc, ucStcNext, ucStcBase;
fail(pFile == NULL || aucHeader == NULL);
fail(iWordVersion != 1 && iWordVersion != 2);
ulBeginStshInfo = ulGetLong(0x5e, aucHeader); /* fcStshf */
NO_DBG_HEX(ulBeginStshInfo);
tStshInfoLen = (size_t)usGetWord(0x62, aucHeader); /* cbStshf */
NO_DBG_DEC(tStshInfoLen);
aucBuffer = xmalloc(tStshInfoLen);
if (!bReadBytes(aucBuffer, tStshInfoLen, ulBeginStshInfo, pFile)) {
aucBuffer = xfree(aucBuffer);
return;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tStshInfoLen);
fail(2 > tStshInfoLen);
iStd = (int)usGetWord(0, aucBuffer);
fail(2 + 2 > tStshInfoLen);
tName = (size_t)usGetWord(2, aucBuffer);
fail(2 + tName + 2 > tStshInfoLen);
tChpx = (size_t)usGetWord(2 + tName, aucBuffer);
fail(2 + tName + tChpx + 2 > tStshInfoLen);
tPapx = (size_t)usGetWord(2 + tName + tChpx, aucBuffer);
fail(2 + tName + tChpx + tPapx + 2 > tStshInfoLen);
tStdCount = (size_t)usGetWord(2 + tName + tChpx + tPapx, aucBuffer);
NO_DBG_HEX(tStdCount);
atStyleInfo = xcalloc(tStdCount, sizeof(style_block_type));
atFontInfo = xcalloc(tStdCount, sizeof(font_block_type));
abFilled = xcalloc(tStdCount, sizeof(BOOL));
do {
iCounter = 0;
iStIndex = 2 + 2;
iChpxIndex = 2 + (int)tName + 2;
iPapxIndex = 2 + (int)tName + (int)tChpx + 2;
tMaxIndex = 2 + tName + tChpx + tPapx + 2;
/* Read the styles one-by-one */
for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
pStyle = &atStyleInfo[iIndex];
pFont = &atFontInfo[iIndex];
iSt = (int)ucGetByte(iStIndex, aucBuffer);
iChpx = (int)ucGetByte(iChpxIndex, aucBuffer);
iPapx = (int)ucGetByte(iPapxIndex, aucBuffer);
NO_DBG_HEX(iSt);
NO_DBG_HEX(iChpx);
NO_DBG_HEX(iPapx);
if (iSt == 0xff || tMaxIndex + 1 >= tStshInfoLen) {
/* Undefined style or no information */
iStIndex++;
iChpxIndex++;
iPapxIndex++;
tMaxIndex += 2;
if (!abFilled[iIndex]) {
DBG_HEX_C(iChpx != 0xff, iChpx);
DBG_HEX_C(iPapx != 0xff, iPapx);
vGetDefaultStyle(pStyle);
vGetDefaultFont(pFont, 0);
abFilled[iIndex] = TRUE;
}
continue;
}
NO_DBG_STRN(aucBuffer + iStIndex + 1, iSt);
iStIndex += iSt + 1;
ucStcNext = ucGetByte(tMaxIndex, aucBuffer);
ucStcBase = ucGetByte(tMaxIndex + 1, aucBuffer);
ucStc = (UCHAR)((iIndex - iStd) & 0xff);
NO_DBG_DEC(ucStc);
if (iChpx == 0xff || iPapx == 0xff) {
/* Use a build-in style */
iChpxIndex++;
iPapxIndex++;
tMaxIndex += 2;
if (!abFilled[iIndex]) {
DBG_HEX_C(iChpx != 0xff, iChpx);
DBG_HEX_C(iPapx != 0xff, iPapx);
vGetBuildinStyle(ucStc, pStyle);
pStyle->usIstd = usStc2istd(ucStc);
pStyle->usIstdNext =
usStc2istd(ucStcNext);
vGetBuildinFont(ucStc, pFont);
abFilled[iIndex] = TRUE;
}
continue;
}
if (abFilled[iIndex]) {
/* This record has already been filled */
iChpxIndex += iChpx + 1;
iPapxIndex += iPapx + 1;
tMaxIndex += 2;
continue;
}
usBaseStyle = usStc2istd(ucStcBase);
if (usBaseStyle == STI_NIL) {
/* Based on the Nil style */
vGetDefaultStyle(pStyle);
vGetDefaultFont(pFont, 0);
} else {
iBaseStyleIndex = iGetStyleIndex(usBaseStyle);
NO_DBG_DEC(iBaseStyleIndex);
if (iBaseStyleIndex < 0) {
/* This style is not known yet */
iChpxIndex += iChpx + 1;
iPapxIndex += iPapx + 1;
tMaxIndex += 2;
continue;
}
fail(iBaseStyleIndex >= (int)tStdCount);
fail(!abFilled[iBaseStyleIndex]);
/* Based on the specified base style */
*pStyle = atStyleInfo[iBaseStyleIndex];
*pFont = atFontInfo[iBaseStyleIndex];
}
pStyle->usIstd = usStc2istd(ucStc);
pStyle->usIstdNext = usStc2istd(ucStcNext);
abFilled[iIndex] = TRUE;
iCounter++;
/* Add the changes if any */
switch (iChpx) {
case 0x00:
case 0xff:
iChpxIndex++;
break;
default:
NO_DBG_PRINT_BLOCK(aucBuffer + iChpxIndex + 1,
iChpx);
if (iWordVersion == 1) {
vGet1FontInfo(0,
aucBuffer + iChpxIndex + 1,
(size_t)iChpx, pFont);
} else {
vGet2FontInfo(0,
aucBuffer + iChpxIndex + 1,
(size_t)iChpx, pFont);
}
iChpxIndex += iChpx + 1;
break;
}
switch (iPapx) {
case 0x00:
case 0xff:
iPapxIndex++;
break;
default:
NO_DBG_PRINT_BLOCK(aucBuffer + iPapxIndex + 8,
iPapx - 7);
vGet2StyleInfo(0, aucBuffer + iPapxIndex + 8,
iPapx - 7, pStyle);
iPapxIndex += iPapx + 1;
break;
}
tMaxIndex += 2;
}
NO_DBG_DEC(iCounter);
} while (iCounter > 0);
/* Fill records that are still empty */
for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
if (!abFilled[iIndex]) {
NO_DBG_DEC(iIndex);
vGetDefaultStyle(&atStyleInfo[iIndex]);
vGetDefaultFont(&atFontInfo[iIndex], 0);
}
}
/* Clean up before you leave */
abFilled = xfree(abFilled);
aucBuffer = xfree(aucBuffer);
} /* end of vGet2Stylesheet */
/*
* Build the lists with Stylesheet Information for Word 6/7 files
*/
void
vGet6Stylesheet(FILE *pFile, ULONG ulStartBlock,
const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
{
style_block_type *pStyle;
font_block_type *pFont;
UCHAR *aucBuffer;
ULONG ulBeginStshInfo;
size_t tStshInfoLen, tOffset, tStdLen, tStdBaseInFile;
size_t tPos, tNameLen, tUpxLen;
int iIndex, iBaseStyleIndex, iCounter;
USHORT usTmp, usUpxCount, usStyleType, usBaseStyle;
USHORT usFtcStandardChpStsh;
fail(pFile == NULL || aucHeader == NULL);
fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
fail(aulBBD == NULL);
ulBeginStshInfo = ulGetLong(0x60, aucHeader); /* fcStshf */
NO_DBG_HEX(ulBeginStshInfo);
tStshInfoLen = (size_t)ulGetLong(0x64, aucHeader); /* lcbStshf */
NO_DBG_DEC(tStshInfoLen);
aucBuffer = xmalloc(tStshInfoLen);
if (!bReadBuffer(pFile, ulStartBlock,
aulBBD, tBBDLen, BIG_BLOCK_SIZE,
aucBuffer, ulBeginStshInfo, tStshInfoLen)) {
aucBuffer = xfree(aucBuffer);
return;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tStshInfoLen);
tStdCount = (size_t)usGetWord(2, aucBuffer);
NO_DBG_DEC(tStdCount);
tStdBaseInFile = (size_t)usGetWord(4, aucBuffer);
usFtcStandardChpStsh = usGetWord(14, aucBuffer);
NO_DBG_DEC(usFtcStandardChpStsh);
atStyleInfo = xcalloc(tStdCount, sizeof(style_block_type));
atFontInfo = xcalloc(tStdCount, sizeof(font_block_type));
abFilled = xcalloc(tStdCount, sizeof(BOOL));
do {
iCounter = 0;
/* Read the styles one-by-one */
for (iIndex = 0, tOffset = 2 + (size_t)usGetWord(0, aucBuffer);
iIndex < (int)tStdCount;
iIndex++, tOffset += 2 + tStdLen) {
NO_DBG_DEC(tOffset);
tStdLen = (size_t)usGetWord(tOffset, aucBuffer);
NO_DBG_DEC(tStdLen);
if (abFilled[iIndex]) {
/* This record has already been filled */
continue;
}
pStyle = &atStyleInfo[iIndex];
pFont = &atFontInfo[iIndex];
if (tStdLen == 0) {
/* Empty record */
vGetDefaultStyle(pStyle);
vGetDefaultFont(pFont, usFtcStandardChpStsh);
abFilled[iIndex] = TRUE;
continue;
}
usTmp = usGetWord(tOffset + 4, aucBuffer);
usStyleType = usTmp % 16;
usBaseStyle = usTmp / 16;
NO_DBG_DEC(usStyleType);
NO_DBG_DEC(usBaseStyle);
if (usBaseStyle == STI_NIL || usBaseStyle == STI_USER) {
/* Based on the Nil style */
vGetDefaultStyle(pStyle);
vGetDefaultFont(pFont, usFtcStandardChpStsh);
} else {
iBaseStyleIndex = iGetStyleIndex(usBaseStyle);
NO_DBG_DEC(iBaseStyleIndex);
if (iBaseStyleIndex < 0) {
/* This base style is not known yet */
continue;
}
fail(iBaseStyleIndex >= (int)tStdCount);
fail(!abFilled[iBaseStyleIndex]);
/* Based on the specified base style */
*pStyle = atStyleInfo[iBaseStyleIndex];
pStyle->usIstd = ISTD_INVALID;
*pFont = atFontInfo[iBaseStyleIndex];
}
abFilled[iIndex] = TRUE;
iCounter++;
/* STD */
usTmp = usGetWord(tOffset + 6, aucBuffer);
usUpxCount = usTmp % 16;
pStyle->usIstdNext = usTmp / 16;;
NO_DBG_DEC(usUpxCount);
tPos = 2 + tStdBaseInFile;
NO_DBG_DEC(tPos);
tNameLen = (size_t)ucGetByte(tOffset + tPos, aucBuffer);
NO_DBG_DEC(tNameLen);
NO_DBG_STRN(aucBuffer + tOffset + tPos + 1, tNameLen);
tNameLen++; /* Include the ASCII NULL character */
tPos += 1 + tNameLen;
if (odd(tPos)) {
tPos++;
}
NO_DBG_DEC(tPos);
if (tPos >= tStdLen) {
continue;
}
tUpxLen = (size_t)usGetWord(tOffset + tPos, aucBuffer);
NO_DBG_DEC(tUpxLen);
if (tPos + tUpxLen > tStdLen) {
/* UPX length too large to be a record */
DBG_DEC_C(tPos + tUpxLen > tStdLen,
tPos + tUpxLen);
continue;
}
if (usStyleType == SGC_PAP && usUpxCount >= 1) {
if (tUpxLen >= 2) {
NO_DBG_PRINT_BLOCK(
aucBuffer + tOffset + tPos + 2,
tUpxLen);
pStyle->usIstd = usGetWord(
tOffset + tPos + 2, aucBuffer);
NO_DBG_DEC(pStyle->usIstd);
NO_DBG_DEC(pStyle->usIstdNext);
vGet6StyleInfo(0,
aucBuffer + tOffset + tPos + 4,
tUpxLen - 2, pStyle);
NO_DBG_DEC(pStyle->sLeftIndent);
NO_DBG_DEC(pStyle->sRightIndent);
NO_DBG_HEX(pStyle->ucAlignment);
}
tPos += 2 + tUpxLen;
if (odd(tPos)) {
tPos++;
}
NO_DBG_DEC(tPos);
tUpxLen = (size_t)usGetWord(
tOffset + tPos, aucBuffer);
NO_DBG_DEC(tUpxLen);
}
if (tUpxLen == 0 || tPos + tUpxLen > tStdLen) {
/* Too small or too large to be a record */
DBG_DEC_C(tPos + tUpxLen > tStdLen,
tPos + tUpxLen);
continue;
}
if ((usStyleType == SGC_PAP && usUpxCount >= 2) ||
(usStyleType == SGC_CHP && usUpxCount >= 1)) {
NO_DBG_PRINT_BLOCK(
aucBuffer + tOffset + tPos + 2,
tUpxLen);
vGet6FontInfo(0, ISTD_INVALID,
aucBuffer + tOffset + tPos + 2,
(int)tUpxLen, pFont);
NO_DBG_DEC(pFont->usFontSize);
NO_DBG_DEC(pFont->ucFontcolor);
NO_DBG_HEX(pFont->usFontStyle);
}
}
NO_DBG_DEC(iCounter);
} while (iCounter > 0);
/* Fill records that are still empty */
for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
if (!abFilled[iIndex]) {
NO_DBG_DEC(iIndex);
vGetDefaultStyle(&atStyleInfo[iIndex]);
vGetDefaultFont(&atFontInfo[iIndex],
usFtcStandardChpStsh);
}
}
/* Clean up before you leave */
abFilled = xfree(abFilled);
aucBuffer = xfree(aucBuffer);
} /* end of vGet6Stylesheet */
/*
* Build the lists with Stylesheet Information for Word 8/9/10 files
*/
void
vGet8Stylesheet(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader)
{
style_block_type *pStyle;
font_block_type *pFont;
const ULONG *aulBlockDepot;
UCHAR *aucBuffer;
ULONG ulBeginStshInfo;
size_t tStshInfoLen, tBlockDepotLen, tOffset, tStdLen, tStdBaseInFile;
size_t tBlockSize, tPos, tNameLen, tUpxLen;
int iIndex, iBaseStyleIndex, iCounter;
USHORT usTmp, usUpxCount, usStyleType, usBaseStyle;
USHORT usFtcStandardChpStsh;
fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
fail(aulBBD == NULL || aulSBD == NULL);
ulBeginStshInfo = ulGetLong(0xa2, aucHeader); /* fcStshf */
NO_DBG_HEX(ulBeginStshInfo);
tStshInfoLen = (size_t)ulGetLong(0xa6, aucHeader); /* lcbStshf */
NO_DBG_DEC(tStshInfoLen);
NO_DBG_DEC(pPPS->tTable.ulSB);
NO_DBG_HEX(pPPS->tTable.ulSize);
if (pPPS->tTable.ulSize == 0) {
DBG_MSG("No stylesheet information");
return;
}
if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
/* Use the Small Block Depot */
aulBlockDepot = aulSBD;
tBlockDepotLen = tSBDLen;
tBlockSize = SMALL_BLOCK_SIZE;
} else {
/* Use the Big Block Depot */
aulBlockDepot = aulBBD;
tBlockDepotLen = tBBDLen;
tBlockSize = BIG_BLOCK_SIZE;
}
aucBuffer = xmalloc(tStshInfoLen);
if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
aulBlockDepot, tBlockDepotLen, tBlockSize,
aucBuffer, ulBeginStshInfo, tStshInfoLen)) {
aucBuffer = xfree(aucBuffer);
return;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tStshInfoLen);
tStdCount = (size_t)usGetWord(2, aucBuffer);
NO_DBG_DEC(tStdCount);
tStdBaseInFile = (size_t)usGetWord(4, aucBuffer);
usFtcStandardChpStsh = usGetWord(14, aucBuffer);
NO_DBG_DEC(usFtcStandardChpStsh);
atStyleInfo = xcalloc(tStdCount, sizeof(style_block_type));
atFontInfo = xcalloc(tStdCount, sizeof(font_block_type));
abFilled = xcalloc(tStdCount, sizeof(BOOL));
do {
iCounter = 0;
/* Read the styles one-by-one */
for (iIndex = 0, tOffset = 2 + (size_t)usGetWord(0, aucBuffer);
iIndex < (int)tStdCount;
iIndex++, tOffset += 2 + tStdLen) {
NO_DBG_DEC(tOffset);
tStdLen = (size_t)usGetWord(tOffset, aucBuffer);
NO_DBG_DEC(tStdLen);
if (abFilled[iIndex]) {
/* This record has already been filled */
continue;
}
pStyle = &atStyleInfo[iIndex];
pFont = &atFontInfo[iIndex];
if (tStdLen == 0) {
/* Empty record */
vGetDefaultStyle(pStyle);
vGetDefaultFont(pFont, usFtcStandardChpStsh);
abFilled[iIndex] = TRUE;
continue;
}
usTmp = usGetWord(tOffset + 4, aucBuffer);
usStyleType = usTmp % 16;
usBaseStyle = usTmp / 16;
NO_DBG_DEC(usStyleType);
NO_DBG_DEC(usBaseStyle);
if (usBaseStyle == STI_NIL || usBaseStyle == STI_USER) {
/* Based on the Nil style */
vGetDefaultStyle(pStyle);
vGetDefaultFont(pFont, usFtcStandardChpStsh);
} else {
iBaseStyleIndex = iGetStyleIndex(usBaseStyle);
NO_DBG_DEC(iBaseStyleIndex);
if (iBaseStyleIndex < 0) {
/* This base style is not known yet */
continue;
}
fail(iBaseStyleIndex >= (int)tStdCount);
fail(!abFilled[iBaseStyleIndex]);
/* Based on the specified base style */
*pStyle = atStyleInfo[iBaseStyleIndex];
pStyle->usIstd = ISTD_INVALID;
*pFont = atFontInfo[iBaseStyleIndex];
}
abFilled[iIndex] = TRUE;
iCounter++;
/* STD */
usTmp = usGetWord(tOffset + 6, aucBuffer);
usUpxCount = usTmp % 16;
pStyle->usIstdNext = usTmp / 16;
NO_DBG_DEC(usUpxCount);
tPos = 2 + tStdBaseInFile;
NO_DBG_DEC(tPos);
tNameLen = (size_t)usGetWord(tOffset + tPos, aucBuffer);
NO_DBG_DEC(tNameLen);
tNameLen *= 2; /* From Unicode characters to bytes */
NO_DBG_UNICODE_N(aucBuffer + tOffset + tPos + 2,
tNameLen);
tNameLen += 2; /* Include the Unicode NULL character */
tPos += 2 + tNameLen;
if (odd(tPos)) {
tPos++;
}
NO_DBG_DEC(tPos);
if (tPos >= tStdLen) {
continue;
}
tUpxLen = (size_t)usGetWord(tOffset + tPos, aucBuffer);
NO_DBG_DEC(tUpxLen);
if (tPos + tUpxLen > tStdLen) {
/* UPX length too large to be a record */
DBG_DEC_C(tPos + tUpxLen > tStdLen,
tPos + tUpxLen);
continue;
}
if (usStyleType == SGC_PAP && usUpxCount >= 1) {
if (tUpxLen >= 2) {
NO_DBG_PRINT_BLOCK(
aucBuffer + tOffset + tPos + 2,
tUpxLen);
pStyle->usIstd = usGetWord(
tOffset + tPos + 2, aucBuffer);
NO_DBG_DEC(pStyle->usIstd);
NO_DBG_DEC(pStyle->usIstdNext);
vGet8StyleInfo(0,
aucBuffer + tOffset + tPos + 4,
tUpxLen - 2, pStyle);
NO_DBG_DEC(pStyle->sLeftIndent);
NO_DBG_DEC(pStyle->sRightIndent);
NO_DBG_HEX(pStyle->ucAlignment);
}
tPos += 2 + tUpxLen;
if (odd(tPos)) {
tPos++;
}
NO_DBG_DEC(tPos);
tUpxLen = (size_t)usGetWord(
tOffset + tPos, aucBuffer);
NO_DBG_DEC(tUpxLen);
}
if (tUpxLen == 0 || tPos + tUpxLen > tStdLen) {
/* Too small or too large to be a record */
DBG_DEC_C(tPos + tUpxLen > tStdLen,
tPos + tUpxLen);
continue;
}
if ((usStyleType == SGC_PAP && usUpxCount >= 2) ||
(usStyleType == SGC_CHP && usUpxCount >= 1)) {
NO_DBG_PRINT_BLOCK(
aucBuffer + tOffset + tPos + 2,
tUpxLen);
vGet8FontInfo(0, ISTD_INVALID,
aucBuffer + tOffset + tPos + 2,
(int)tUpxLen, pFont);
NO_DBG_DEC(pFont->usFontSize);
NO_DBG_DEC(pFont->ucFontcolor);
NO_DBG_HEX(pFont->usFontStyle);
}
}
NO_DBG_DEC(iCounter);
} while (iCounter > 0);
/* Fill records that are still empty */
for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
if (!abFilled[iIndex]) {
NO_DBG_DEC(iIndex);
vGetDefaultStyle(&atStyleInfo[iIndex]);
vGetDefaultFont(&atFontInfo[iIndex],
usFtcStandardChpStsh);
}
}
/* Clean up before you leave */
abFilled = xfree(abFilled);
aucBuffer = xfree(aucBuffer);
} /* end of vGet8Stylesheet */
/*
* vFillStyleFromStylesheet - fill a style struct with stylesheet info
*/
void
vFillStyleFromStylesheet(USHORT usIstd, style_block_type *pStyle)
{
int iIndex;
fail(pStyle == NULL);
if (usIstd != ISTD_INVALID && usIstd != STI_NIL && usIstd != STI_USER) {
for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
if (atStyleInfo[iIndex].usIstd == usIstd) {
/* Right index found; return style */
*pStyle = atStyleInfo[iIndex];
return;
}
}
}
vGetDefaultStyle(pStyle);
pStyle->usIstd = usIstd;
} /* end of vFillStyleFromStylesheet */
/*
* vFillFontFromStylesheet - fill a font struct with stylesheet info
*/
void
vFillFontFromStylesheet(USHORT usIstd, font_block_type *pFont)
{
int iIndex;
fail(pFont == NULL);
if (usIstd != ISTD_INVALID && usIstd != STI_NIL && usIstd != STI_USER) {
for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
if (atStyleInfo[iIndex].usIstd == usIstd) {
/* Right index found; return font */
*pFont = atFontInfo[iIndex];
return;
}
}
}
vGetDefaultFont(pFont, 0);
} /* end of vFillFontFromStylesheet */

888
src/summary.c Normal file
View File

@@ -0,0 +1,888 @@
/*
* summary.c
* Copyright (C) 2002-2005 A.J. van Os; Released under GNU GPL
*
* Description:
* Read the summary information of a Word document
*/
#include <time.h>
#include <string.h>
#include "antiword.h"
#define P_HEADER_SZ 28
#define P_SECTIONLIST_SZ 20
#define P_LENGTH_SZ 4
#define P_SECTION_MAX_SZ (2 * P_SECTIONLIST_SZ + P_LENGTH_SZ)
#define P_SECTION_SZ(x) ((x) * P_SECTIONLIST_SZ + P_LENGTH_SZ)
#define PID_TITLE 2
#define PID_SUBJECT 3
#define PID_AUTHOR 4
#define PID_CREATE_DTM 12
#define PID_LASTSAVE_DTM 13
#define PID_APPNAME 18
#define PIDD_MANAGER 14
#define PIDD_COMPANY 15
#define VT_LPSTR 30
#define VT_FILETIME 64
#define TIME_OFFSET_HI 0x019db1de
#define TIME_OFFSET_LO 0xd53e8000
static char *szTitle = NULL;
static char *szSubject = NULL;
static char *szAuthor = NULL;
static time_t tCreateDtm = (time_t)-1;
static time_t tLastSaveDtm= (time_t)-1;
static char *szAppName = NULL;
static char *szManager = NULL;
static char *szCompany = NULL;
static USHORT usLid = (USHORT)-1;
/*
* vDestroySummaryInfo - destroy the summary information
*/
void
vDestroySummaryInfo(void)
{
TRACE_MSG("vDestroySummaryInfo");
szTitle = xfree(szTitle);
szSubject = xfree(szSubject);
szAuthor = xfree(szAuthor);
tCreateDtm = (time_t)-1;
tLastSaveDtm = (time_t)-1;
szAppName = xfree(szAppName);
szManager = xfree(szManager);
szCompany = xfree(szCompany);
usLid = (USHORT)-1;
} /* end of vDestroySummaryInfo */
/*
* tConvertDosDate - convert DOS date format
*
* returns Unix time_t or -1
*/
static time_t
tConvertDosDate(const char *szDosDate)
{
struct tm tTime;
const char *pcTmp;
time_t tResult;
memset(&tTime, 0, sizeof(tTime));
pcTmp = szDosDate;
/* Get the month */
if (!isdigit(*pcTmp)) {
return (time_t)-1;
}
tTime.tm_mon = (int)(*pcTmp - '0');
pcTmp++;
if (isdigit(*pcTmp)) {
tTime.tm_mon *= 10;
tTime.tm_mon += (int)(*pcTmp - '0');
pcTmp++;
}
/* Get the first separater */
if (isalnum(*pcTmp)) {
return (time_t)-1;
}
pcTmp++;
/* Get the day */
if (!isdigit(*pcTmp)) {
return (time_t)-1;
}
tTime.tm_mday = (int)(*pcTmp - '0');
pcTmp++;
if (isdigit(*pcTmp)) {
tTime.tm_mday *= 10;
tTime.tm_mday += (int)(*pcTmp - '0');
pcTmp++;
}
/* Get the second separater */
if (isalnum(*pcTmp)) {
return (time_t)-1;
}
pcTmp++;
/* Get the year */
if (!isdigit(*pcTmp)) {
return (time_t)-1;
}
tTime.tm_year = (int)(*pcTmp - '0');
pcTmp++;
if (isdigit(*pcTmp)) {
tTime.tm_year *= 10;
tTime.tm_year += (int)(*pcTmp - '0');
pcTmp++;
}
/* Check the values */
if (tTime.tm_mon == 0 || tTime.tm_mday == 0 || tTime.tm_mday > 31) {
return (time_t)-1;
}
/* Correct the values */
tTime.tm_mon--; /* From 01-12 to 00-11 */
if (tTime.tm_year < 80) {
tTime.tm_year += 100; /* 00 means 2000 is 100 */
}
tTime.tm_isdst = -1;
tResult = mktime(&tTime);
NO_DBG_MSG(ctime(&tResult));
return tResult;
} /* end of tConvertDosDate */
/*
* szLpstr - get a zero terminate string property
*/
static char *
szLpstr(ULONG ulOffset, const UCHAR *aucBuffer)
{
char *szStart, *szResult, *szTmp;
size_t tSize;
tSize = (size_t)ulGetLong(ulOffset + 4, aucBuffer);
NO_DBG_DEC(tSize);
if (tSize == 0) {
return NULL;
}
/* Remove white space from the start of the string */
szStart = (char *)aucBuffer + ulOffset + 8;
NO_DBG_MSG(szStart);
fail(strlen(szStart) >= tSize);
while (isspace(*szStart)) {
szStart++;
}
if (szStart[0] == '\0') {
return NULL;
}
szResult = xstrdup(szStart);
/* Remove white space from the end of the string */
szTmp = szResult + strlen(szResult) - 1;
while (isspace(*szTmp)) {
*szTmp = '\0';
szTmp--;
}
NO_DBG_MSG(szResult);
return szResult;
} /* end of szLpstr */
/*
* tFiletime - get a filetime property
*/
static time_t
tFiletime(ULONG ulOffset, const UCHAR *aucBuffer)
{
double dHi, dLo, dTmp;
ULONG ulHi, ulLo;
time_t tResult;
ulLo = ulGetLong(ulOffset + 4, aucBuffer);
ulHi = ulGetLong(ulOffset + 8, aucBuffer);
NO_DBG_HEX(ulHi);
NO_DBG_HEX(ulLo);
/* Move the starting point from 01 Jan 1601 to 01 Jan 1970 */
dHi = (double)ulHi - (double)TIME_OFFSET_HI;
dLo = (double)ulLo - (double)TIME_OFFSET_LO;
NO_DBG_FLT(dHi);
NO_DBG_FLT(dLo);
/* Combine the values and divide by 10^7 to get seconds */
dTmp = dLo / 10000000.0; /* 10^7 */
dTmp += dHi * 429.4967926; /* 2^32 / 10^7 */
NO_DBG_FLT(dTmp);
/* Make a time_t */
if (dTmp - 0.5 < TIME_T_MIN || dTmp + 0.5 > TIME_T_MAX) {
return (time_t)-1;
}
tResult = dTmp < 0.0 ? (time_t)(dTmp - 0.5) : (time_t)(dTmp + 0.5);
NO_DBG_MSG(ctime(&tResult));
return tResult;
} /* end of tFiletime */
/*
* vAnalyseSummaryInfo - analyse the summary information
*/
static void
vAnalyseSummaryInfo(const UCHAR *aucBuffer)
{
ULONG ulOffset;
size_t tIndex, tCount, tPropID, tPropType;
tCount = (size_t)ulGetLong(4, aucBuffer);
DBG_DEC(tCount);
for (tIndex = 0; tIndex < tCount; tIndex++) {
tPropID = (size_t)ulGetLong(8 + tIndex * 8, aucBuffer);
ulOffset = ulGetLong(12 + tIndex * 8, aucBuffer);
NO_DBG_DEC(tPropID);
NO_DBG_HEX(ulOffset);
tPropType = (size_t)ulGetLong(ulOffset, aucBuffer);
NO_DBG_DEC(tPropType);
switch (tPropID) {
case PID_TITLE:
if (tPropType == VT_LPSTR && szTitle == NULL) {
szTitle = szLpstr(ulOffset, aucBuffer);
}
break;
case PID_SUBJECT:
if (tPropType == VT_LPSTR && szSubject == NULL) {
szSubject = szLpstr(ulOffset, aucBuffer);
}
break;
case PID_AUTHOR:
if (tPropType == VT_LPSTR && szAuthor == NULL) {
szAuthor = szLpstr(ulOffset, aucBuffer);
}
break;
case PID_CREATE_DTM:
if (tPropType == VT_FILETIME &&
tCreateDtm == (time_t)-1) {
tCreateDtm = tFiletime(ulOffset, aucBuffer);
}
break;
case PID_LASTSAVE_DTM:
if (tPropType == VT_FILETIME &&
tLastSaveDtm == (time_t)-1) {
tLastSaveDtm = tFiletime(ulOffset, aucBuffer);
}
break;
case PID_APPNAME:
if (tPropType == VT_LPSTR && szAppName == NULL) {
szAppName = szLpstr(ulOffset, aucBuffer);
}
break;
default:
break;
}
}
} /* end of vAnalyseSummaryInfo */
/*
* vAnalyseDocumentSummaryInfo - analyse the document summary information
*/
static void
vAnalyseDocumentSummaryInfo(const UCHAR *aucBuffer)
{
ULONG ulOffset;
size_t tIndex, tCount, tPropID, tPropType;
tCount = (size_t)ulGetLong(4, aucBuffer);
DBG_DEC(tCount);
for (tIndex = 0; tIndex < tCount; tIndex++) {
tPropID = (size_t)ulGetLong(8 + tIndex * 8, aucBuffer);
ulOffset = ulGetLong(12 + tIndex * 8, aucBuffer);
NO_DBG_DEC(tPropID);
NO_DBG_HEX(ulOffset);
tPropType = (size_t)ulGetLong(ulOffset, aucBuffer);
NO_DBG_DEC(tPropType);
switch (tPropID) {
case PIDD_MANAGER:
if (tPropType == VT_LPSTR && szManager == NULL) {
szManager = szLpstr(ulOffset, aucBuffer);
}
break;
case PIDD_COMPANY:
if (tPropType == VT_LPSTR && szCompany == NULL) {
szCompany = szLpstr(ulOffset, aucBuffer);
}
break;
default:
break;
}
}
} /* end of vAnalyseDocumentSummaryInfo */
/*
* pucAnalyseSummaryInfoHeader-
*/
static UCHAR *
pucAnalyseSummaryInfoHeader(FILE *pFile,
ULONG ulStartBlock, ULONG ulSize,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen)
{
const ULONG *aulBlockDepot;
UCHAR *aucBuffer;
size_t tBlockDepotLen, tBlockSize, tSectionCount, tLength;
ULONG ulTmp, ulOffset;
USHORT usLittleEndian, usEmpty, usOS, usVersion;
UCHAR aucHdr[P_HEADER_SZ], aucSecLst[P_SECTION_MAX_SZ];
if (ulSize < MIN_SIZE_FOR_BBD_USE) {
/* Use the Small Block Depot */
aulBlockDepot = aulSBD;
tBlockDepotLen = tSBDLen;
tBlockSize = SMALL_BLOCK_SIZE;
} else {
/* Use the Big Block Depot */
aulBlockDepot = aulBBD;
tBlockDepotLen = tBBDLen;
tBlockSize = BIG_BLOCK_SIZE;
}
if (tBlockDepotLen == 0) {
DBG_MSG("The Block Depot length is zero");
return NULL;
}
/* Read the Summery Information header */
if (!bReadBuffer(pFile, ulStartBlock,
aulBlockDepot, tBlockDepotLen, tBlockSize,
aucHdr, 0, P_HEADER_SZ)) {
return NULL;
}
NO_DBG_PRINT_BLOCK(aucHdr, P_HEADER_SZ);
/* Analyse the Summery Information header */
usLittleEndian = usGetWord(0, aucHdr);
if (usLittleEndian != 0xfffe) {
DBG_HEX(usLittleEndian);
DBG_MSG_C(usLittleEndian == 0xfeff, "Big endian");
return NULL;
}
usEmpty = usGetWord(2, aucHdr);
if (usEmpty != 0x0000) {
DBG_DEC(usEmpty);
return NULL;
}
ulTmp = ulGetLong(4, aucHdr);
DBG_HEX(ulTmp);
usOS = (USHORT)(ulTmp >> 16);
usVersion = (USHORT)(ulTmp & 0xffff);
switch (usOS) {
case 0:
DBG_MSG("Win16");
DBG_HEX(usVersion);
break;
case 1:
DBG_MSG("MacOS");
DBG_HEX(usVersion);
break;
case 2:
DBG_MSG("Win32");
DBG_HEX(usVersion);
break;
default:
DBG_DEC(usOS);
DBG_HEX(usVersion);
break;
}
tSectionCount = (size_t)ulGetLong(24, aucHdr);
DBG_DEC_C(tSectionCount != 1 && tSectionCount != 2, tSectionCount);
if (tSectionCount != 1 && tSectionCount != 2) {
return NULL;
}
/* Read the Summery Information Section Lists */
if (!bReadBuffer(pFile, ulStartBlock,
aulBlockDepot, tBlockDepotLen, tBlockSize,
aucSecLst, P_HEADER_SZ, P_SECTION_SZ(tSectionCount))) {
return NULL;
}
NO_DBG_PRINT_BLOCK(aucSecLst, P_SECTION_SZ(tSectionCount));
ulTmp = ulGetLong(0, aucSecLst);
DBG_HEX(ulTmp);
ulTmp = ulGetLong(4, aucSecLst);
DBG_HEX(ulTmp);
ulTmp = ulGetLong(8, aucSecLst);
DBG_HEX(ulTmp);
ulTmp = ulGetLong(12, aucSecLst);
DBG_HEX(ulTmp);
ulOffset = ulGetLong(16, aucSecLst);
DBG_DEC_C(ulOffset != P_HEADER_SZ + P_SECTIONLIST_SZ &&
ulOffset != P_HEADER_SZ + 2 * P_SECTIONLIST_SZ,
ulOffset);
fail(ulOffset != P_HEADER_SZ + P_SECTIONLIST_SZ &&
ulOffset != P_HEADER_SZ + 2 * P_SECTIONLIST_SZ);
tLength =
(size_t)ulGetLong(tSectionCount * P_SECTIONLIST_SZ, aucSecLst);
NO_DBG_HEX(tLength);
fail(ulOffset + tLength > ulSize);
/* Read the Summery Information */
aucBuffer = xmalloc(tLength);
if (!bReadBuffer(pFile, ulStartBlock,
aulBlockDepot, tBlockDepotLen, tBlockSize,
aucBuffer, ulOffset, tLength)) {
aucBuffer = xfree(aucBuffer);
return NULL;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tLength);
return aucBuffer;
} /* end of pucAnalyseSummaryInfoHeader */
/*
* vSet0SummaryInfo - set summary information from a Word for DOS file
*/
void
vSet0SummaryInfo(FILE *pFile, const UCHAR *aucHeader)
{
UCHAR *aucBuffer;
ULONG ulBeginSumdInfo, ulBeginNextBlock;
size_t tLen;
USHORT usCodepage, usOffset;
TRACE_MSG("vSet0SummaryInfo");
fail(pFile == NULL || aucHeader == NULL);
/* First check the header */
usCodepage = usGetWord(0x7e, aucHeader);
DBG_DEC(usCodepage);
switch (usCodepage) {
case 850: usLid = 0x0809; break; /* Latin1 -> British English */
case 862: usLid = 0x040d; break; /* Hebrew */
case 866: usLid = 0x0419; break; /* Russian */
case 0:
case 437:
default: usLid = 0x0409; break; /* ASCII -> American English */
}
/* Second check the summary information block */
ulBeginSumdInfo = 128 * (ULONG)usGetWord(0x1c, aucHeader);
DBG_HEX(ulBeginSumdInfo);
ulBeginNextBlock = 128 * (ULONG)usGetWord(0x6a, aucHeader);
DBG_HEX(ulBeginNextBlock);
if (ulBeginSumdInfo >= ulBeginNextBlock || ulBeginNextBlock == 0) {
/* There is no summary information block */
return;
}
tLen = (size_t)(ulBeginNextBlock - ulBeginSumdInfo);
aucBuffer = xmalloc(tLen);
/* Read the summary information block */
if (!bReadBytes(aucBuffer, tLen, ulBeginSumdInfo, pFile)) {
return;
}
usOffset = usGetWord(0, aucBuffer);
if (aucBuffer[usOffset] != 0) {
NO_DBG_MSG(aucBuffer + usOffset);
szTitle = xstrdup((char *)aucBuffer + usOffset);
}
usOffset = usGetWord(2, aucBuffer);
if (aucBuffer[usOffset] != 0) {
NO_DBG_MSG(aucBuffer + usOffset);
szAuthor = xstrdup((char *)aucBuffer + usOffset);
}
usOffset = usGetWord(12, aucBuffer);
if (aucBuffer[usOffset] != 0) {
NO_DBG_STRN(aucBuffer + usOffset, 8);
tLastSaveDtm = tConvertDosDate((char *)aucBuffer + usOffset);
}
usOffset = usGetWord(14, aucBuffer);
if (aucBuffer[usOffset] != 0) {
NO_DBG_STRN(aucBuffer + usOffset, 8);
tCreateDtm = tConvertDosDate((char *)aucBuffer + usOffset);
}
aucBuffer = xfree(aucBuffer);
} /* end of vSet0SummaryInfo */
/*
* vSet2SummaryInfo - set summary information from a WinWord 1/2 file
*/
void
vSet2SummaryInfo(FILE *pFile, int iWordVersion, const UCHAR *aucHeader)
{
UCHAR *aucBuffer;
ULONG ulBeginSumdInfo, ulBeginDocpInfo, ulTmp;
size_t tSumdInfoLen, tDocpInfoLen, tLen, tCounter, tStart;
TRACE_MSG("vSet2SummaryInfo");
fail(pFile == NULL || aucHeader == NULL);
fail(iWordVersion != 1 && iWordVersion != 2);
/* First check the header */
usLid = usGetWord(0x06, aucHeader); /* Language IDentification */
DBG_HEX(usLid);
if (usLid < 999 && iWordVersion == 1) {
switch (usLid) {
case 1: usLid = 0x0409; break; /* American English */
case 2: usLid = 0x0c0c; break; /* Canadian French */
case 31: usLid = 0x0413; break; /* Dutch */
case 33: usLid = 0x040c; break; /* French */
case 34: usLid = 0x040a; break; /* Spanish */
case 36: usLid = 0x040e; break; /* Hungarian */
case 39: usLid = 0x0410; break; /* Italian */
case 44: usLid = 0x0809; break; /* British English */
case 45: usLid = 0x0406; break; /* Danish */
case 46: usLid = 0x041f; break; /* Swedish */
case 47: usLid = 0x0414; break; /* Norwegian */
case 48: usLid = 0x0415; break; /* Polish */
case 49: usLid = 0x0407; break; /* German */
case 351: usLid = 0x0816; break; /* Portuguese */
case 358: usLid = 0x040b; break; /* Finnish */
default:
DBG_DEC(usLid);
DBG_FIXME();
usLid = 0x0409; /* American English */
break;
}
}
if (iWordVersion != 2) {
/* Unknown where to find the associated strings */
return;
}
/* Second check the associated strings */
ulBeginSumdInfo = ulGetLong(0x118, aucHeader); /* fcSttbfAssoc */
DBG_HEX(ulBeginSumdInfo);
tSumdInfoLen = (size_t)usGetWord(0x11c, aucHeader); /* cbSttbfAssoc */
DBG_DEC(tSumdInfoLen);
if (tSumdInfoLen == 0) {
/* There is no summary information */
return;
}
aucBuffer = xmalloc(tSumdInfoLen);
if (!bReadBytes(aucBuffer, tSumdInfoLen, ulBeginSumdInfo, pFile)) {
aucBuffer = xfree(aucBuffer);
return;
}
NO_DBG_PRINT_BLOCK(aucBuffer, tSumdInfoLen);
tLen = (size_t)ucGetByte(0, aucBuffer);
DBG_DEC_C(tSumdInfoLen != tLen, tSumdInfoLen);
DBG_DEC_C(tSumdInfoLen != tLen, tLen);
tStart = 1;
for (tCounter = 0; tCounter < 17; tCounter++) {
if (tStart >= tSumdInfoLen) {
break;
}
tLen = (size_t)ucGetByte(tStart, aucBuffer);
if (tLen != 0) {
NO_DBG_DEC(tCounter);
NO_DBG_STRN(aucBuffer + tStart + 1, tLen);
switch (tCounter) {
case 3:
szTitle = xmalloc(tLen + 1);
strncpy(szTitle,
(char *)aucBuffer + tStart + 1, tLen);
szTitle[tLen] = '\0';
break;
case 4:
szSubject = xmalloc(tLen + 1);
strncpy(szSubject,
(char *)aucBuffer + tStart + 1, tLen);
szSubject[tLen] = '\0';
break;
case 7:
szAuthor = xmalloc(tLen + 1);
strncpy(szAuthor,
(char *)aucBuffer + tStart + 1, tLen);
szAuthor[tLen] = '\0';
break;
default:
break;
}
}
tStart += tLen + 1;
}
aucBuffer = xfree(aucBuffer);
/* Third check the document properties */
ulBeginDocpInfo = ulGetLong(0x112, aucHeader); /* fcDop */
DBG_HEX(ulBeginDocpInfo);
tDocpInfoLen = (size_t)usGetWord(0x116, aucHeader); /* cbDop */
DBG_DEC(tDocpInfoLen);
if (tDocpInfoLen < 12) {
return;
}
aucBuffer = xmalloc(tDocpInfoLen);
if (!bReadBytes(aucBuffer, tDocpInfoLen, ulBeginDocpInfo, pFile)) {
aucBuffer = xfree(aucBuffer);
return;
}
ulTmp = ulGetLong(0x14, aucBuffer); /* dttmCreated */
tCreateDtm = tConvertDTTM(ulTmp);
ulTmp = ulGetLong(0x18, aucBuffer); /* dttmRevised */
tLastSaveDtm = tConvertDTTM(ulTmp);
aucBuffer = xfree(aucBuffer);
} /* end of vSet2SummaryInfo */
/*
* vSetSummaryInfoOLE - set summary information from a Word 6+ file
*/
static void
vSetSummaryInfoOLE(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen)
{
UCHAR *pucBuffer;
fail(pFile == NULL || pPPS == NULL);
fail(aulBBD == NULL || aulSBD == NULL);
/* Summary Information */
pucBuffer = pucAnalyseSummaryInfoHeader(pFile,
pPPS->tSummaryInfo.ulSB, pPPS->tSummaryInfo.ulSize,
aulBBD, tBBDLen, aulSBD, tSBDLen);
if (pucBuffer != NULL) {
vAnalyseSummaryInfo(pucBuffer);
pucBuffer = xfree(pucBuffer);
}
/* Document Summary Information */
pucBuffer = pucAnalyseSummaryInfoHeader(pFile,
pPPS->tDocSummaryInfo.ulSB, pPPS->tDocSummaryInfo.ulSize,
aulBBD, tBBDLen, aulSBD, tSBDLen);
if (pucBuffer != NULL) {
vAnalyseDocumentSummaryInfo(pucBuffer);
pucBuffer = xfree(pucBuffer);
}
} /* end of vSetSummaryInfoOLE */
/*
* vSet6SummaryInfo - set summary information from a Word 6/7 file
*/
void
vSet6SummaryInfo(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader)
{
TRACE_MSG("vSet6SummaryInfo");
/* Header Information */
usLid = usGetWord(0x06, aucHeader); /* Language IDentification */
DBG_HEX(usLid);
/* Summery Information */
vSetSummaryInfoOLE(pFile, pPPS, aulBBD, tBBDLen, aulSBD, tSBDLen);
} /* end of vSet6SummaryInfo */
/*
* vSet8SummaryInfo - set summary information a Word 8/9/10 file
*/
void
vSet8SummaryInfo(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader)
{
USHORT usTmp;
TRACE_MSG("vSet8SummaryInfo");
/* Header Information */
usTmp = usGetWord(0x0a, aucHeader);
if (usTmp & BIT(14)) {
/* Language IDentification Far East */
usLid = usGetWord(0x3c, aucHeader);
} else {
/* Language IDentification */
usLid = usGetWord(0x06, aucHeader);
}
DBG_HEX(usLid);
/* Summery Information */
vSetSummaryInfoOLE(pFile, pPPS, aulBBD, tBBDLen, aulSBD, tSBDLen);
} /* end of vSet8SummaryInfo */
/*
* szGetTitle - get the title field
*/
const char *
szGetTitle(void)
{
return szTitle;
} /* end of szGetTitle */
/*
* szGetSubject - get the subject field
*/
const char *
szGetSubject(void)
{
return szSubject;
} /* end of szGetSubject */
/*
* szGetAuthor - get the author field
*/
const char *
szGetAuthor(void)
{
return szAuthor;
} /* end of szGetAuthor */
/*
* szGetLastSaveDtm - get the last save date field
*/
const char *
szGetLastSaveDtm(void)
{
static char szTime[12];
struct tm *pTime;
if (tLastSaveDtm == (time_t)-1) {
return NULL;
}
pTime = localtime(&tLastSaveDtm);
if (pTime == NULL) {
return NULL;
}
sprintf(szTime, "%04d-%02d-%02d",
pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday);
return szTime;
} /* end of szGetLastSaveDtm */
/*
* szGetModDate - get the last save date field
*/
const char *
szGetModDate(void)
{
static char szTime[20];
struct tm *pTime;
if (tLastSaveDtm == (time_t)-1) {
return NULL;
}
pTime = localtime(&tLastSaveDtm);
if (pTime == NULL) {
return NULL;
}
sprintf(szTime, "D:%04d%02d%02d%02d%02d",
pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday,
pTime->tm_hour, pTime->tm_min);
return szTime;
} /* end of szGetModDate */
/*
* szGetCreationDate - get the last save date field
*/
const char *
szGetCreationDate(void)
{
static char szTime[20];
struct tm *pTime;
if (tCreateDtm == (time_t)-1) {
return NULL;
}
pTime = localtime(&tCreateDtm);
if (pTime == NULL) {
return NULL;
}
sprintf(szTime, "D:%04d%02d%02d%02d%02d",
pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday,
pTime->tm_hour, pTime->tm_min);
return szTime;
} /* end of szGetCreationDate */
/*
* szGetCompany - get the company field
*/
const char *
szGetCompany(void)
{
return szCompany;
} /* end of szGetCompany */
/*
* szGetLanguage - get de language field
*/
const char *
szGetLanguage(void)
{
if (usLid == (USHORT)-1) {
/* No Language IDentification */
return NULL;
}
if (usLid < 999) {
/* This is a Locale, not a Language IDentification */
DBG_DEC(usLid);
return NULL;
}
/* Exceptions to the general rule */
switch (usLid) {
case 0x0404: return "zh_TW"; /* Traditional Chinese */
case 0x0804: return "zh_CN"; /* Simplified Chinese */
case 0x0c04: return "zh_HK"; /* Hong Kong Chinese */
case 0x1004: return "zh_SG"; /* Singapore Chinese */
case 0x0807: return "de_CH"; /* Swiss German */
case 0x0409: return "en_US"; /* American English */
case 0x0809: return "en_GB"; /* British English */
case 0x0c09: return "en_AU"; /* Australian English */
case 0x080a: return "es_MX"; /* Mexican Spanish */
case 0x080c: return "fr_BE"; /* Belgian French */
case 0x0c0c: return "fr_CA"; /* Canadian French */
case 0x100c: return "fr_CH"; /* Swiss French */
case 0x0810: return "it_CH"; /* Swiss Italian */
case 0x0813: return "nl_BE"; /* Belgian Dutch */
case 0x0416: return "pt_BR"; /* Brazilian Portuguese */
case 0x081a:
case 0x0c1a: return "sr"; /* Serbian */
case 0x081d: return "sv_FI"; /* Finland Swedish */
default:
break;
}
/* The general rule */
switch (usLid & 0x00ff) {
case 0x01: return "ar"; /* Arabic */
case 0x02: return "bg"; /* Bulgarian */
case 0x03: return "ca"; /* Catalan */
case 0x04: return "zh"; /* Chinese */
case 0x05: return "cs"; /* Czech */
case 0x06: return "da"; /* Danish */
case 0x07: return "de"; /* German */
case 0x08: return "el"; /* Greek */
case 0x09: return "en"; /* English */
case 0x0a: return "es"; /* Spanish */
case 0x0b: return "fi"; /* Finnish */
case 0x0c: return "fr"; /* French */
case 0x0d: return "he"; /* Hebrew */
case 0x0e: return "hu"; /* Hungarian */
case 0x0f: return "is"; /* Icelandic */
case 0x10: return "it"; /* Italian */
case 0x11: return "ja"; /* Japanese */
case 0x12: return "ko"; /* Korean */
case 0x13: return "nl"; /* Dutch */
case 0x14: return "no"; /* Norwegian */
case 0x15: return "pl"; /* Polish */
case 0x16: return "pt"; /* Portuguese */
case 0x17: return "rm"; /* Rhaeto-Romance */
case 0x18: return "ro"; /* Romanian */
case 0x19: return "ru"; /* Russian */
case 0x1a: return "hr"; /* Croatian */
case 0x1b: return "sk"; /* Slovak */
case 0x1c: return "sq"; /* Albanian */
case 0x1d: return "sv"; /* Swedish */
case 0x1e: return "th"; /* Thai */
case 0x1f: return "tr"; /* Turkish */
case 0x20: return "ur"; /* Urdu */
case 0x21: return "id"; /* Indonesian */
case 0x22: return "uk"; /* Ukrainian */
case 0x23: return "be"; /* Belarusian */
case 0x24: return "sl"; /* Slovenian */
case 0x25: return "et"; /* Estonian */
case 0x26: return "lv"; /* Latvian */
case 0x27: return "lt"; /* Lithuanian */
case 0x29: return "fa"; /* Farsi */
case 0x2a: return "vi"; /* Viet Nam */
case 0x2b: return "hy"; /* Armenian */
case 0x2c: return "az"; /* Azeri */
case 0x2d: return "eu"; /* Basque */
case 0x2f: return "mk"; /* Macedonian */
case 0x36: return "af"; /* Afrikaans */
case 0x37: return "ka"; /* Georgian */
case 0x38: return "fo"; /* Faeroese */
case 0x39: return "hi"; /* Hindi */
case 0x3e: return "ms"; /* Malay */
case 0x3f: return "kk"; /* Kazakh */
default:
DBG_HEX(usLid);
DBG_FIXME();
return NULL;
}
} /* end of szGetLanguage */

212
src/tabstop.c Normal file
View File

@@ -0,0 +1,212 @@
/*
* tabstops.c
* Copyright (C) 1999-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Read the tab stop information from a MS Word file
*/
#include <stdio.h>
#include "antiword.h"
#define HALF_INCH 36000L /* In millipoints */
static long lDefaultTabWidth = HALF_INCH;
/*
* vSet0DefaultTabWidth -
*/
static void
vSet0DefaultTabWidth(const UCHAR *aucHeader)
{
USHORT usTmp;
fail(aucHeader == NULL);
usTmp = usGetWord(0x70, aucHeader); /* dxaTab */
DBG_DEC(usTmp);
lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
DBG_DEC(lDefaultTabWidth);
} /* end of vSet0DefaultTabWidth */
/*
* vSet2DefaultTabWidth -
*/
static void
vSet2DefaultTabWidth(FILE *pFile, const UCHAR *aucHeader)
{
UCHAR *aucBuffer;
ULONG ulBeginDocpInfo;
size_t tDocpInfoLen;
USHORT usTmp;
fail(pFile == NULL || aucHeader == NULL);
ulBeginDocpInfo = ulGetLong(0x112, aucHeader); /* fcDop */
DBG_HEX(ulBeginDocpInfo);
tDocpInfoLen = (size_t)usGetWord(0x116, aucHeader); /* cbDop */
DBG_DEC(tDocpInfoLen);
if (tDocpInfoLen < 12) {
DBG_MSG("No TAB information");
return;
}
aucBuffer = xmalloc(tDocpInfoLen);
if (!bReadBytes(aucBuffer, tDocpInfoLen, ulBeginDocpInfo, pFile)) {
aucBuffer = xfree(aucBuffer);
return;
}
usTmp = usGetWord(0x0a, aucBuffer); /* dxaTab */
lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
DBG_DEC(lDefaultTabWidth);
aucBuffer = xfree(aucBuffer);
} /* end of vSet2DefaultTabWidth */
/*
* vSet6DefaultTabWidth -
*/
static void
vSet6DefaultTabWidth(FILE *pFile, ULONG ulStartBlock,
const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
{
UCHAR *aucBuffer;
ULONG ulBeginDocpInfo;
size_t tDocpInfoLen;
USHORT usTmp;
ulBeginDocpInfo = ulGetLong(0x150, aucHeader); /* fcDop */
DBG_HEX(ulBeginDocpInfo);
tDocpInfoLen = (size_t)ulGetLong(0x154, aucHeader); /* lcbDop */
DBG_DEC(tDocpInfoLen);
if (tDocpInfoLen < 12) {
DBG_MSG("No TAB information");
return;
}
aucBuffer = xmalloc(tDocpInfoLen);
if (!bReadBuffer(pFile, ulStartBlock,
aulBBD, tBBDLen, BIG_BLOCK_SIZE,
aucBuffer, ulBeginDocpInfo, tDocpInfoLen)) {
aucBuffer = xfree(aucBuffer);
return;
}
usTmp = usGetWord(0x0a, aucBuffer); /* dxaTab */
lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
DBG_DEC(lDefaultTabWidth);
aucBuffer = xfree(aucBuffer);
} /* end of vSet6DefaultTabWidth */
/*
* vSet8DefaultTabWidth -
*/
static void
vSet8DefaultTabWidth(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader)
{
const ULONG *aulBlockDepot;
UCHAR *aucBuffer;
ULONG ulBeginDocpInfo;
size_t tDocpInfoLen, tBlockDepotLen, tBlockSize;
USHORT usTmp;
ulBeginDocpInfo = ulGetLong(0x192, aucHeader); /* fcDop */
DBG_HEX(ulBeginDocpInfo);
tDocpInfoLen = (size_t)ulGetLong(0x196, aucHeader); /* lcbDop */
DBG_DEC(tDocpInfoLen);
if (tDocpInfoLen < 12) {
DBG_MSG("No TAB information");
return;
}
DBG_DEC(pPPS->tTable.ulSB);
DBG_HEX(pPPS->tTable.ulSize);
if (pPPS->tTable.ulSize == 0) {
DBG_MSG("No TAB information");
return;
}
if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
/* Use the Small Block Depot */
aulBlockDepot = aulSBD;
tBlockDepotLen = tSBDLen;
tBlockSize = SMALL_BLOCK_SIZE;
} else {
/* Use the Big Block Depot */
aulBlockDepot = aulBBD;
tBlockDepotLen = tBBDLen;
tBlockSize = BIG_BLOCK_SIZE;
}
aucBuffer = xmalloc(tDocpInfoLen);
if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
aulBlockDepot, tBlockDepotLen, tBlockSize,
aucBuffer, ulBeginDocpInfo, tDocpInfoLen)) {
aucBuffer = xfree(aucBuffer);
return;
}
usTmp = usGetWord(0x0a, aucBuffer); /* dxaTab */
lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
DBG_DEC(lDefaultTabWidth);
aucBuffer = xfree(aucBuffer);
} /* end of vSet8DefaultTabWidth */
/*
* vSetDefaultTabWidth -
*/
void
vSetDefaultTabWidth(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader, int iWordVersion)
{
fail(pFile == NULL && iWordVersion >= 1);
fail(pPPS == NULL && iWordVersion >= 6);
fail(aulBBD == NULL && tBBDLen != 0);
fail(aulSBD == NULL && tSBDLen != 0);
fail(aucHeader == NULL);
/* Reset to the default default value */
lDefaultTabWidth = HALF_INCH;
switch (iWordVersion) {
case 0:
vSet0DefaultTabWidth(aucHeader);
break;
case 1:
case 2:
vSet2DefaultTabWidth(pFile, aucHeader);
break;
case 4:
case 5:
break;
case 6:
case 7:
vSet6DefaultTabWidth(pFile, pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen, aucHeader);
break;
case 8:
vSet8DefaultTabWidth(pFile, pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
break;
default:
werr(0, "Sorry, no TAB information");
break;
}
} /* end of vSetDefaultTabWidth */
#if 0
/*
* lGetDefaultTabWidth - Get the default tabwidth in millipoints
*/
long
lGetDefaultTabWidth(void)
{
if (lDefaultTabWidth <= 0) {
DBG_DEC(lDefaultTabWidth);
return lTwips2MilliPoints(1);
}
return lDefaultTabWidth;
} /* end of lGetDefaultTabWidth */
#endif

182
src/text.c Normal file
View File

@@ -0,0 +1,182 @@
/*
* text.c
* Copyright (C) 1999-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Functions to deal with the Text format
*
*/
#include <string.h>
#include "antiword.h"
/* The character set */
static encoding_type eEncoding = encoding_neutral;
/* Current vertical position information */
static long lYtopCurr = 0;
/* Local representation of the non-breaking space */
static UCHAR ucNbsp = 0;
/*
* vPrologueTXT - set options and perform the Text initialization
*/
void
vPrologueTXT(diagram_type *pDiag, const options_type *pOptions)
{
fail(pDiag == NULL);
fail(pOptions == NULL);
eEncoding = pOptions->eEncoding;
pDiag->lXleft = 0;
pDiag->lYtop = 0;
lYtopCurr = 0;
} /* end of vPrologueTXT */
/*
* vEpilogueTXT - clean up after everything is done
*/
void
vEpilogueTXT(FILE *pOutFile)
{
fail(pOutFile == NULL);
fprintf(pOutFile, "\n");
} /* end of vEpilogueTXT */
/*
* vPrintTXT - print a Text string
*/
static void
vPrintTXT(FILE *pFile, const char *szString, size_t tStringLength)
{
const UCHAR *ucBytes;
size_t tCount;
fail(szString == NULL);
if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
return;
}
if (eEncoding == encoding_utf_8) {
fprintf(pFile, "%.*s", (int)tStringLength, szString);
return;
}
if (ucNbsp == 0) {
ucNbsp = ucGetNbspCharacter();
DBG_HEX_C(ucNbsp != 0xa0, ucNbsp);
}
ucBytes = (UCHAR *)szString;
for (tCount = 0; tCount < tStringLength ; tCount++) {
if (ucBytes[tCount] == ucNbsp) {
(void)putc(' ', pFile);
} else {
(void)putc(szString[tCount], pFile);
}
}
} /* end of vPrintTXT */
/*
* vMoveTo - move to the given X,Y coordinates
*
* Move the current position of the given diagram to its X,Y coordinates,
* start on a new page if needed
*/
static void
vMoveTo(diagram_type *pDiag)
{
int iCount, iNbr;
fail(pDiag == NULL);
fail(pDiag->pOutFile == NULL);
if (pDiag->lYtop != lYtopCurr) {
iNbr = iDrawUnits2Char(pDiag->lXleft);
for (iCount = 0; iCount < iNbr; iCount++) {
(void)putc(FILLER_CHAR, pDiag->pOutFile);
}
lYtopCurr = pDiag->lYtop;
}
} /* end of vMoveTo */
/*
* vMove2NextLineTXT - move to the next line
*/
void
vMove2NextLineTXT(diagram_type *pDiag)
{
fail(pDiag == NULL);
fail(pDiag->pOutFile == NULL);
pDiag->lYtop++;
(void)fprintf(pDiag->pOutFile, "\n");
} /* end of vMove2NextLineTXT */
/*
* vSubstringTXT - print a sub string
*/
void
vSubstringTXT(diagram_type *pDiag,
const char *szString, size_t tStringLength, long lStringWidth)
{
fail(pDiag == NULL || szString == NULL);
fail(pDiag->pOutFile == NULL);
fail(pDiag->lXleft < 0);
fail(tStringLength != strlen(szString));
if (szString[0] == '\0' || tStringLength == 0) {
return;
}
vMoveTo(pDiag);
vPrintTXT(pDiag->pOutFile, szString, tStringLength);
pDiag->lXleft += lStringWidth;
} /* end of vSubstringTXT */
/*
* Create an start of paragraph by moving the y-top mark
*/
void
vStartOfParagraphTXT(diagram_type *pDiag, long lBeforeIndentation)
{
fail(pDiag == NULL);
fail(lBeforeIndentation < 0);
if (lBeforeIndentation >= lTwips2MilliPoints(HEADING_GAP)) {
/* A large gap is replaced by an empty line */
vMove2NextLineTXT(pDiag);
}
} /* end of vStartOfParagraphTXT */
/*
* Create an end of paragraph by moving the y-top mark
*/
void
vEndOfParagraphTXT(diagram_type *pDiag, long lAfterIndentation)
{
fail(pDiag == NULL);
fail(pDiag->pOutFile == NULL);
fail(lAfterIndentation < 0);
if (pDiag->lXleft > 0) {
/* To the start of the line */
vMove2NextLineTXT(pDiag);
}
if (lAfterIndentation >= lTwips2MilliPoints(HEADING_GAP)) {
/* A large gap is replaced by an empty line */
vMove2NextLineTXT(pDiag);
}
} /* end of vEndOfParagraphTXT */
/*
* Create an end of page
*/
void
vEndOfPageTXT(diagram_type *pDiag, long lAfterIndentation)
{
vEndOfParagraphTXT(pDiag, lAfterIndentation);
} /* end of vEndOfPageTXT */

45
src/unix.c Normal file
View File

@@ -0,0 +1,45 @@
/*
* unix.c
* Copyright (C) 1998-2000 A.J. van Os; Released under GPL
*
* Description:
* Unix approximations of RISC-OS functions
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "antiword.h"
/*
* werr - write an error message and exit if needed
*/
void
werr(int iFatal, const char *szFormat, ...)
{
va_list tArg;
va_start(tArg, szFormat);
(void)vfprintf(stderr, szFormat, tArg);
va_end(tArg);
fprintf(stderr, "\n");
switch (iFatal) {
case 0: /* The message is just a warning, so no exit */
return;
case 1: /* Fatal error with a standard exit */
exit(EXIT_FAILURE);
default: /* Fatal error with a non-standard exit */
exit(iFatal);
}
} /* end of werr */
void
Hourglass_On(void)
{
} /* end of Hourglass_On */
void
Hourglass_Off(void)
{
} /* end of Hourglass_Off */

260
src/utf8.c Normal file
View File

@@ -0,0 +1,260 @@
/*
* utf8.c
* Copyright (C) 2001-2004 A.J. van Os; Released under GPL
*
*====================================================================
* This part of the software is based on:
* An implementation of wcwidth() as defined in
* "The Single UNIX Specification, Version 2, The Open Group, 1997"
* <http://www.UNIX-systems.org/online.html>
* Markus Kuhn -- 2001-01-12 -- public domain
*====================================================================
* The credit should go to him, but all the bugs are mine.
*/
#include <stdlib.h>
#include <string.h>
#include "antiword.h"
struct interval {
USHORT first;
USHORT last;
};
/* Sorted list of non-overlapping intervals of non-spacing characters */
static const struct interval combining[] = {
{ 0x0300, 0x034E }, { 0x0360, 0x0362 }, { 0x0483, 0x0486 },
{ 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 },
{ 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
{ 0x05C4, 0x05C4 }, { 0x064B, 0x0655 }, { 0x0670, 0x0670 },
{ 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
{ 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
{ 0x07A6, 0x07B0 }, { 0x0901, 0x0902 }, { 0x093C, 0x093C },
{ 0x0941, 0x0948 }, { 0x094D, 0x094D }, { 0x0951, 0x0954 },
{ 0x0962, 0x0963 }, { 0x0981, 0x0981 }, { 0x09BC, 0x09BC },
{ 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 },
{ 0x0A02, 0x0A02 }, { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 },
{ 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 },
{ 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 },
{ 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, { 0x0B01, 0x0B01 },
{ 0x0B3C, 0x0B3C }, { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 },
{ 0x0B4D, 0x0B4D }, { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 },
{ 0x0BC0, 0x0BC0 }, { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 },
{ 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 },
{ 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
{ 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, { 0x0DCA, 0x0DCA },
{ 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 },
{ 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 },
{ 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD },
{ 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 },
{ 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 },
{ 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, { 0x0F99, 0x0FBC },
{ 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, { 0x1032, 0x1032 },
{ 0x1036, 0x1037 }, { 0x1039, 0x1039 }, { 0x1058, 0x1059 },
{ 0x1160, 0x11FF }, { 0x17B7, 0x17BD }, { 0x17C6, 0x17C6 },
{ 0x17C9, 0x17D3 }, { 0x180B, 0x180E }, { 0x18A9, 0x18A9 },
{ 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x206A, 0x206F },
{ 0x20D0, 0x20E3 }, { 0x302A, 0x302F }, { 0x3099, 0x309A },
{ 0xFB1E, 0xFB1E }, { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF },
{ 0xFFF9, 0xFFFB }
};
/* Auxiliary function for binary search in interval table */
static BOOL
bIsZeroWidthChar(ULONG ucs)
{
int low = 0;
int high = elementsof(combining) - 1;
int mid;
if (ucs < (ULONG)combining[low].first ||
ucs > (ULONG)combining[high].last) {
return FALSE;
}
while (high >= low) {
mid = (low + high) / 2;
if (ucs > (ULONG)combining[mid].last) {
low = mid + 1;
} else if (ucs < (ULONG)combining[mid].first) {
high = mid - 1;
} else {
return TRUE;
}
}
return FALSE;
} /* end of bIsZeroWidthChar */
/* The following functions define the column width of an ISO 10646
* character as follows:
*
* - The null character (U+0000) has a column width of 0.
*
* - Other C0/C1 control characters and DEL will lead to a return
* value of -1.
*
* - Non-spacing and enclosing combining characters (general
* category code Mn or Me in the Unicode database) have a
* column width of 0.
*
* - Other format characters (general category code Cf in the Unicode
* database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
*
* - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
* have a column width of 0.
*
* - Spacing characters in the East Asian Wide (W) or East Asian
* FullWidth (F) category as defined in Unicode Technical
* Report #11 have a column width of 2.
*
* - All remaining characters (including all printable
* ISO 8859-1 and WGL4 characters, Unicode control characters,
* etc.) have a column width of 1.
*
* This implementation assumes that all characters are encoded
* in ISO 10646.
*
* This function is not named wcwidth() to prevent name clashes
*/
static int
iWcWidth(ULONG ucs)
{
/* Test for 8-bit control characters */
if (ucs == 0) {
return 0;
}
if (ucs < 0x20 || (ucs >= 0x7f && ucs < 0xa0)) {
NO_DBG_HEX(ucs);
return -1;
}
/* Binary search in table of non-spacing characters */
if (bIsZeroWidthChar(ucs)) {
return 0;
}
/* Ucs is not a combining or C0/C1 control character */
return 1 +
(ucs >= 0x1100 &&
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
(ucs >= 0x2e80 && ucs <= 0xa4cf && (ucs & ~0x0011) != 0x300a &&
ucs != 0x303f) || /* CJK ... Yi */
(ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
(ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
(ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
(ucs >= 0xff00 && ucs <= 0xff5f) || /* Fullwidth Forms */
(ucs >= 0xffe0 && ucs <= 0xffe6) ||
(ucs >= 0x20000 && ucs <= 0x2ffff)));
} /* end of iWcWidth */
/*
* utf8_to_ucs - convert from UTF-8 to UCS
*
* Returns the UCS character,
* Fills in the number of bytes in the UTF-8 character
*/
static ULONG
utf8_to_ucs(const char *p, int iStrLen, int *piUtfLen)
{
ULONG ulUcs;
int iIndex, iCharLen;
fail(p == NULL || piUtfLen == NULL);
fail(iStrLen < 1);
ulUcs = (ULONG)(UCHAR)p[0];
if (ulUcs < 0x80) {
*piUtfLen = 1;
return ulUcs;
}
if (ulUcs < 0xe0){
iCharLen = 2;
ulUcs &= 0x1f;
} else if (ulUcs < 0xf0){
iCharLen = 3;
ulUcs &= 0x0f;
} else if (ulUcs < 0xf8){
iCharLen = 4;
ulUcs &= 0x07;
} else if (ulUcs < 0xfc){
iCharLen = 5;
ulUcs &= 0x03;
} else {
iCharLen = 6;
ulUcs &= 0x01;
}
for (iIndex = 1; iIndex < iCharLen; iIndex++) {
ulUcs <<= 6;
if (iIndex < iStrLen) {
ulUcs |= (ULONG)(UCHAR)p[iIndex] & 0x3f;
}
}
*piUtfLen = iCharLen;
return ulUcs;
} /* end of utf8_to_ucs */
/*
* utf8_strwidth - compute the string width of an UTF-8 string
*
* Returns the string width in columns
*/
long
utf8_strwidth(const char *pcString, size_t tNumchars)
{
ULONG ulUcs;
long lTotal;
int iToGo, iWidth, iUtflen;
fail(pcString == NULL || tNumchars > (size_t)INT_MAX);
lTotal = 0;
iToGo = (int)tNumchars;
while (iToGo > 0 && *pcString != '\0') {
ulUcs = utf8_to_ucs(pcString, iToGo, &iUtflen);
iWidth = iWcWidth(ulUcs);
if (iWidth > 0) {
lTotal += iWidth;
}
pcString += iUtflen;
iToGo -= iUtflen;
}
NO_DBG_DEC(lTotal);
return lTotal;
} /* end of utf8_strwidth */
/*
* utf8_chrlength - get the number of bytes in an UTF-8 character
*
* Returns the number of bytes
*/
int
utf8_chrlength(const char *p)
{
int iUtflen;
fail(p == NULL);
iUtflen = -1; /* Just to make sure */
(void)utf8_to_ucs(p, INT_MAX, &iUtflen);
NO_DBG_DEC(iUtflen);
return iUtflen;
} /* end of utf8_chrlength */
/*
* is_locale_utf8 - return TRUE if the locale is UTF-8
*/
BOOL
is_locale_utf8(void)
{
char szCodeset[20];
szCodeset[0] = '\0';
if (!bGetNormalizedCodeset(szCodeset, sizeof(szCodeset), NULL)) {
return FALSE;
}
DBG_MSG(szCodeset);
return STREQ(szCodeset, "utf8");
} /* end of is_locale_utf8 */

37
src/version.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* version.h
* Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
*
* Description:
* Version and release information
*/
#if !defined(__version_h)
#define __version_h 1
/* Strings for the info box */
#define PURPOSESTRING "Display MS-Word files"
#if defined(__riscos)
#define AUTHORSTRING "<22> 1998-2005 Adri van Os"
#else
#define AUTHORSTRING "(C) 1998-2005 Adri van Os"
#endif /* __riscos */
#define VERSIONSTRING "0.37 (21 Oct 2005)"
#if defined(__dos)
#if defined(__DJGPP__)
#define VERSIONSTRING2 " # 32-bit Protected Mode"
#else
#define VERSIONSTRING2 " # 16-bit Real Mode"
#endif /* __DJGPP__ */
#endif /* __dos */
#if defined(DEBUG)
#define STATUSSTRING "DEBUG version"
#else
#define STATUSSTRING "GNU General Public License"
#endif /* DEBUG */
#endif /* __version_h */

1505
src/word2text.c Normal file

File diff suppressed because it is too large Load Diff

321
src/wordconst.h Normal file
View File

@@ -0,0 +1,321 @@
/*
* wordconst.h
* Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Constants and macros for the interpretation of MS Word files
*/
#if !defined(__wordconst_h)
#define __wordconst_h 1
/*
* A bit odd definition of the type Boolean, but RISC OS insists
* on this and Linux/Unix doesn't mind.
*/
#if !defined(BOOL)
#define BOOL int
#define TRUE 1
#define FALSE 0
#endif /* !BOOL */
/* Block sizes */
#define HEADER_SIZE 768
#define BIG_BLOCK_SIZE 512
#define PROPERTY_SET_STORAGE_SIZE 128
#define SMALL_BLOCK_SIZE 64
/* Switch size of Depot use */
#define MIN_SIZE_FOR_BBD_USE 0x1000
/* Table sizes */
#define TABLE_COLUMN_MAX 31
/* Maximum number of tabs positions in a paragraph */
#define NUMBER_OF_TABS_MAX 64
/* Font sizes (in half-points) */
#define MIN_FONT_SIZE 8
#define DEFAULT_FONT_SIZE 20
#define MAX_FONT_SIZE 240
#define MIN_TABLEFONT_SIZE 16
#define MAX_TABLEFONT_SIZE 20
/* Font styles */
#define FONT_REGULAR 0x0000
#define FONT_BOLD 0x0001
#define FONT_ITALIC 0x0002
#define FONT_UNDERLINE 0x0004
#define FONT_CAPITALS 0x0008
#define FONT_SMALL_CAPITALS 0x0010
#define FONT_STRIKE 0x0020
#define FONT_HIDDEN 0x0040
#define FONT_MARKDEL 0x0080
#define FONT_SUPERSCRIPT 0x0100
#define FONT_SUBSCRIPT 0x0200
/* Font colors */
#define FONT_COLOR_DEFAULT 0
#define FONT_COLOR_BLACK 1
#define FONT_COLOR_BLUE 2
#define FONT_COLOR_CYAN 3
#define FONT_COLOR_GREEN 4
#define FONT_COLOR_MAGENTA 5
#define FONT_COLOR_RED 6
#define FONT_COLOR_YELLOW 7
#define FONT_COLOR_WHITE 8
/* Special block numbers */
#define END_OF_CHAIN 0xfffffffeUL
#define UNUSED_BLOCK 0xffffffffUL
/* Blocksize (512 bytes) and maximum filesize (4 GB) gives 0..7fffff */
#define MAX_BLOCKNUMBER 0x007fffffUL
/* Invalid character position */
#define CP_INVALID 0xffffffffUL
/* Invalid file offset */
#define FC_INVALID 0xffffffffUL
/* Special istd values */
#define ISTD_INVALID USHRT_MAX
#define ISTD_NORMAL 0
/* Properties modifier without value */
#define IGNORE_PROPMOD 0
/* Types of lists */
#define LIST_ARABIC_NUM 0x00
#define LIST_UPPER_ROMAN 0x01
#define LIST_LOWER_ROMAN 0x02
#define LIST_UPPER_ALPHA 0x03
#define LIST_LOWER_ALPHA 0x04
#define LIST_ORDINAL_NUM 0x05
#define LIST_NUMBER_TXT 0x06
#define LIST_ORDINAL_TXT 0x07
#define LIST_OUTLINE_NUM 0x16
#define LIST_SPECIAL 0x17
#define LIST_SPECIAL2 0x19
#define LIST_BULLETS 0xff
/* Types of paragraph alignment */
#define ALIGNMENT_LEFT 0x00
#define ALIGNMENT_CENTER 0x01
#define ALIGNMENT_RIGHT 0x02
#define ALIGNMENT_JUSTIFY 0x03
/* Minimum vertical space before and after a heading line */
#define HEADING_GAP 120 /* twips */
/* Style identifier */
#define STI_USER 0xffe
#define STI_NIL 0xfff
/* Table border style codes */
#define TABLE_BORDER_TOP 0x01
#define TABLE_BORDER_LEFT 0x02
#define TABLE_BORDER_BOTTOM 0x04
#define TABLE_BORDER_RIGHT 0x08
/* Macros */
/* Get macros */
#define ucGetByte(i,a) ((unsigned char)(a[i]))
#define usGetWord(i,a) ((unsigned short)\
((unsigned int)(a[(i)+1])<<8|\
(unsigned int)(a[i])))
#define ulGetLong(i,a) ((unsigned long)(a[i])|\
(unsigned long)(a[(i)+1])<<8|\
(unsigned long)(a[(i)+2])<<16|\
(unsigned long)(a[(i)+3])<<24)
#define usGetWordBE(i,a) ((unsigned short)\
((unsigned int)(a[i])<<8|\
(unsigned int)(a[(i)+1])))
#define ulGetLongBE(i,a) ((unsigned long)(a[(i)+3])|\
(unsigned long)(a[(i)+2])<<8|\
(unsigned long)(a[(i)+1])<<16|\
(unsigned long)(a[i])<<24)
/* Font style macros */
#define bIsBold(x) (((x) & FONT_BOLD) == FONT_BOLD)
#define bIsItalic(x) (((x) & FONT_ITALIC) == FONT_ITALIC)
#define bIsUnderline(x) (((x) & FONT_UNDERLINE) == FONT_UNDERLINE)
#define bIsCapitals(x) (((x) & FONT_CAPITALS) == FONT_CAPITALS)
#define bIsSmallCapitals(x) (((x) & FONT_SMALL_CAPITALS) == FONT_SMALL_CAPITALS)
#define bIsStrike(x) (((x) & FONT_STRIKE) == FONT_STRIKE)
#define bIsHidden(x) (((x) & FONT_HIDDEN) == FONT_HIDDEN)
#define bIsMarkDel(x) (((x) & FONT_MARKDEL) == FONT_MARKDEL)
#define bIsSuperscript(x) (((x) & FONT_SUPERSCRIPT) == FONT_SUPERSCRIPT)
#define bIsSubscript(x) (((x) & FONT_SUBSCRIPT) == FONT_SUBSCRIPT)
/* Table border style code macros */
#define bIsTableBorderTop(x) (((x) & TABLE_BORDER_TOP) == TABLE_BORDER_TOP)
#define bIsTableBorderLeft(x) (((x) & TABLE_BORDER_LEFT) == TABLE_BORDER_LEFT)
#define bIsTableBorderBottom(x) (((x) & TABLE_BORDER_BOTTOM) == TABLE_BORDER_BOTTOM)
#define bIsTableBorderRight(x) (((x) & TABLE_BORDER_RIGHT) == TABLE_BORDER_RIGHT)
/* Computation macros */
#if defined(__riscos)
/* From Words half-points to draw units (plus a percentage) */
#define lWord2DrawUnits00(x) ((long)(x) * 320)
#define lWord2DrawUnits20(x) ((long)(x) * 384)
#define lToBaseLine(x) ((long)(x) * 45)
#endif /* __riscos */
/* From twips (1/20 of a point) to millipoints */
#define lTwips2MilliPoints(x) ((long)(x) * 50)
/* From twips (1/20 of a point) to points */
#define dTwips2Points(x) ((double)(x) / 20.0)
/* From default characters (16 OS units wide) to millipoints */
#define lChar2MilliPoints(x) ((long)(x) * 6400)
#define iMilliPoints2Char(x) (int)(((long)(x) + 3200) / 6400)
#define iDrawUnits2Char(x) (int)(((long)(x) + 2048) / 4096)
/* From draw units (1/180*256 inch) to millipoints (1/72*1000 inch) */
#define lDrawUnits2MilliPoints(x) (((long)(x) * 25 + 8) / 16)
#define lMilliPoints2DrawUnits(x) (((long)(x) * 16 + 12) / 25)
#define lPoints2DrawUnits(x) ((long)(x) * 640)
#define dDrawUnits2Points(x) ((double)(x) / 640.0)
/* Special characters */
#define IGNORE_CHARACTER 0x00 /* ^@ */
#define PICTURE 0x01 /* ^A */
#define FOOTNOTE_OR_ENDNOTE 0x02 /* ^B */
#define FOOTNOTE_SEPARATOR 0x03 /* ^C */
#define FOOTNOTE_CONTINUATION 0x04 /* ^D */
#define ANNOTATION 0x05 /* ^E */
#define TABLE_SEPARATOR 0x07 /* ^G */
#define FRAME 0x08 /* ^H */
#define TAB 0x09 /* ^I */
/* End of line characters */
#define LINE_FEED 0x0a /* ^J */
#define HARD_RETURN 0x0b /* ^K */
#define PAGE_BREAK 0x0c /* ^L */
#define PAR_END 0x0d /* ^M */
#define COLUMN_FEED 0x0e /* ^N */
/* Embedded stuff */
#define START_EMBEDDED 0x13 /* ^S */
#define END_IGNORE 0x14 /* ^T */
#define END_EMBEDDED 0x15 /* ^U */
/* Special characters */
#if defined(DEBUG)
#define FILLER_CHAR '~'
#else
#define FILLER_CHAR ' '
#endif /* DEBUG */
#define TABLE_SEPARATOR_CHAR '|'
/* Pseudo characters. These must be outside the Unicode range */
#define FOOTNOTE_CHAR ((unsigned long)0xffff + 1)
#define ENDNOTE_CHAR ((unsigned long)0xffff + 2)
#define UNKNOWN_NOTE_CHAR ((unsigned long)0xffff + 3)
/* Charactercodes as used by Word */
#define WORD_UNBREAKABLE_JOIN 0x1e
#define WORD_SOFT_HYPHEN 0x1f
/* Unicode characters */
#define UNICODE_DOUBLE_LEFT_ANGLE_QMARK 0x00ab
#define UNICODE_MIDDLE_DOT 0x00b7
#define UNICODE_DOUBLE_RIGHT_ANGLE_QMARK 0x00bb
#define UNICODE_CAPITAL_D_WITH_STROKE 0x0110
#define UNICODE_SMALL_D_WITH_STROKE 0x0111
#define UNICODE_CAPITAL_LIGATURE_OE 0x0152
#define UNICODE_SMALL_LIGATURE_OE 0x0153
#define UNICODE_SMALL_F_HOOK 0x0192
#define UNICODE_GREEK_CAPITAL_CHI 0x03a7
#define UNICODE_GREEK_SMALL_UPSILON 0x03c5
#define UNICODE_MODIFIER_CIRCUMFLEX 0x02c6
#define UNICODE_SMALL_TILDE 0x02dc
#define UNICODE_SMALL_LETTER_OMEGA 0x03c9
#define UNICODE_EN_QUAD 0x2000
#define UNICODE_EM_QUAD 0x2001
#define UNICODE_EN_SPACE 0x2002
#define UNICODE_EM_SPACE 0x2003
#define UNICODE_THREE_PER_EM_SPACE 0x2004
#define UNICODE_FOUR_PER_EM_SPACE 0x2005
#define UNICODE_SIX_PER_EM_SPACE 0x2006
#define UNICODE_FIGURE_SPACE 0x2007
#define UNICODE_PUNCTUATION_SPACE 0x2008
#define UNICODE_THIN_SPACE 0x2009
#define UNICODE_HAIR_SPACE 0x200a
#define UNICODE_ZERO_WIDTH_SPACE 0x200b
#define UNICODE_ZERO_WIDTH_NON_JOINER 0x200c
#define UNICODE_ZERO_WIDTH_JOINER 0x200d
#define UNICODE_LEFT_TO_RIGHT_MARK 0x200e
#define UNICODE_RIGHT_TO_LEFT_MARK 0x200f
#define UNICODE_HYPHEN 0x2010
#define UNICODE_NON_BREAKING_HYPHEN 0x2011
#define UNICODE_FIGURE_DASH 0x2012
#define UNICODE_EN_DASH 0x2013
#define UNICODE_EM_DASH 0x2014
#define UNICODE_HORIZONTAL_BAR 0x2015
#define UNICODE_DOUBLE_VERTICAL_LINE 0x2016
#define UNICODE_DOUBLE_LOW_LINE 0x2017
#define UNICODE_LEFT_SINGLE_QMARK 0x2018
#define UNICODE_RIGHT_SINGLE_QMARK 0x2019
#define UNICODE_SINGLE_LOW_9_QMARK 0x201a
#define UNICODE_SINGLE_HIGH_REV_9_QMARK 0x201b
#define UNICODE_LEFT_DOUBLE_QMARK 0x201c
#define UNICODE_RIGHT_DOUBLE_QMARK 0x201d
#define UNICODE_DOUBLE_LOW_9_QMARK 0x201e
#define UNICODE_DOUBLE_HIGH_REV_9_QMARK 0x201f
#define UNICODE_DAGGER 0x2020
#define UNICODE_DOUBLE_DAGGER 0x2021
#define UNICODE_BULLET 0x2022
#define UNICODE_TRIANGULAR_BULLET 0x2023
#define UNICODE_ONE_DOT_LEADER 0x2024
#define UNICODE_TWO_DOT_LEADER 0x2025
#define UNICODE_ELLIPSIS 0x2026
#define UNICODE_HYPHENATION_POINT 0x2027
#define UNICODE_LEFT_TO_RIGHT_EMBEDDING 0x202a
#define UNICODE_RIGHT_TO_LEFT_EMBEDDING 0x202b
#define UNICODE_POP_DIRECTIONAL_FORMATTING 0x202c
#define UNICODE_LEFT_TO_RIGHT_OVERRIDE 0x202d
#define UNICODE_RIGHT_TO_LEFT_OVERRIDE 0x202e
#define UNICODE_NARROW_NO_BREAK_SPACE 0x202f
#define UNICODE_PER_MILLE_SIGN 0x2030
#define UNICODE_PRIME 0x2032
#define UNICODE_DOUBLE_PRIME 0x2033
#define UNICODE_SINGLE_LEFT_ANGLE_QMARK 0x2039
#define UNICODE_SINGLE_RIGHT_ANGLE_QMARK 0x203a
#define UNICODE_UNDERTIE 0x203f
#define UNICODE_FRACTION_SLASH 0x2044
#define UNICODE_EURO_SIGN 0x20ac
#define UNICODE_CIRCLE 0x20dd
#define UNICODE_SQUARE 0x20de
#define UNICODE_DIAMOND 0x20df
#define UNICODE_NUMERO_SIGN 0x2116
#define UNICODE_TRADEMARK_SIGN 0x2122
#define UNICODE_KELVIN_SIGN 0x212a
#define UNICODE_LEFTWARDS_ARROW 0x2190
#define UNICODE_UPWARDS_ARROW 0x2191
#define UNICODE_RIGHTWARDS_ARROW 0x2192
#define UNICODE_DOWNWARDS_ARROW 0x2193
#define UNICODE_N_ARY_SUMMATION 0x2211
#define UNICODE_MINUS_SIGN 0x2212
#define UNICODE_DIVISION_SLASH 0x2215
#define UNICODE_ASTERISK_OPERATOR 0x2217
#define UNICODE_BULLET_OPERATOR 0x2219
#define UNICODE_RATIO 0x2236
#define UNICODE_TILDE_OPERATOR 0x223c
#define UNICODE_BD_LIGHT_HORIZONTAL 0x2500
#define UNICODE_BD_LIGHT_VERTICAL 0x2502
#define UNICODE_BD_LIGHT_DOWN_RIGHT 0x250c
#define UNICODE_BD_LIGHT_DOWN_AND_LEFT 0x2510
#define UNICODE_BD_LIGHT_UP_AND_RIGHT 0x2514
#define UNICODE_BD_LIGHT_UP_AND_LEFT 0x2518
#define UNICODE_BD_LIGHT_VERTICAL_AND_RIGHT 0x251c
#define UNICODE_BD_LIGHT_VERTICAL_AND_LEFT 0x2524
#define UNICODE_BD_LIGHT_DOWN_AND_HORIZONTAL 0x252c
#define UNICODE_BD_LIGHT_UP_AND_HORIZONTAL 0x2534
#define UNICODE_BD_LIGHT_VERTICAL_AND_HORIZONTAL 0x253c
#define UNICODE_BD_DOUBLE_HORIZONTAL 0x2550
#define UNICODE_BD_DOUBLE_VERTICAL 0x2551
#define UNICODE_BD_DOUBLE_DOWN_AND_RIGHT 0x2554
#define UNICODE_BD_DOUBLE_DOWN_AND_LEFT 0x2557
#define UNICODE_BD_DOUBLE_UP_AND_RIGHT 0x255a
#define UNICODE_BD_DOUBLE_UP_AND_LEFT 0x255d
#define UNICODE_BD_DOUBLE_VERTICAL_AND_RIGHT 0x2560
#define UNICODE_BD_DOUBLE_VERTICAL_AND_LEFT 0x2563
#define UNICODE_BD_DOUBLE_DOWN_AND_HORIZONTAL 0x2566
#define UNICODE_BD_DOUBLE_UP_AND_HORIZONTAL 0x2569
#define UNICODE_BD_DOUBLE_VERTICAL_AND_HORIZONTAL 0x256c
#define UNICODE_LIGHT_SHADE 0x2591
#define UNICODE_MEDIUM_SHADE 0x2592
#define UNICODE_DARK_SHADE 0x2593
#define UNICODE_BLACK_SQUARE 0x25a0
#define UNICODE_BLACK_CLUB_SUIT 0x2663
#define UNICODE_SMALL_LIGATURE_FI 0xfb01
#define UNICODE_SMALL_LIGATURE_FL 0xfb02
#define UNICODE_ZERO_WIDTH_NO_BREAK_SPACE 0xfeff
#if defined(__riscos)
#define OUR_ELLIPSIS 0x8c
#define OUR_EM_DASH 0x98
#define OUR_UNBREAKABLE_JOIN 0x99
#else
#define OUR_ELLIPSIS '.'
#define OUR_EM_DASH '-'
#define OUR_UNBREAKABLE_JOIN '-'
#endif /* __riscos */
#define OUR_DIAMOND '-'
#endif /* __wordconst_h */

110
src/worddos.c Normal file
View File

@@ -0,0 +1,110 @@
/*
* worddos.c
* Copyright (C) 2002-2005 A.J. van Os; Released under GNU GPL
*
* Description:
* Deal with the DOS internals of a MS Word file
*/
#include "antiword.h"
/*
* bGetDocumentText - make a list of the text blocks of a Word document
*
* Return TRUE when succesful, otherwise FALSE
*/
static BOOL
bGetDocumentText(FILE *pFile, long lFilesize, const UCHAR *aucHeader)
{
text_block_type tTextBlock;
ULONG ulTextLen;
BOOL bFastSaved;
UCHAR ucDocStatus, ucVersion;
fail(pFile == NULL);
fail(lFilesize < 128);
fail(aucHeader == NULL);
/* Get the status flags from the header */
ucDocStatus = ucGetByte(0x75, aucHeader);
DBG_HEX(ucDocStatus);
bFastSaved = (ucDocStatus & BIT(1)) != 0;
DBG_MSG_C(bFastSaved, "This document is Fast Saved");
ucVersion = ucGetByte(0x74, aucHeader);
DBG_DEC(ucVersion);
DBG_MSG_C(ucVersion == 0, "Written by Word 4.0 or earlier");
DBG_MSG_C(ucVersion == 3, "Word 5.0 format, but not written by Word");
DBG_MSG_C(ucVersion == 4, "Written by Word 5.x");
if (bFastSaved) {
werr(0, "Word for DOS: autosave documents are not supported");
return FALSE;
}
/* Get length information */
ulTextLen = ulGetLong(0x0e, aucHeader);
DBG_HEX(ulTextLen);
ulTextLen -= 128;
DBG_DEC(ulTextLen);
tTextBlock.ulFileOffset = 128;
tTextBlock.ulCharPos = 128;
tTextBlock.ulLength = ulTextLen;
tTextBlock.bUsesUnicode = FALSE;
tTextBlock.usPropMod = IGNORE_PROPMOD;
if (!bAdd2TextBlockList(&tTextBlock)) {
DBG_HEX(tTextBlock.ulFileOffset);
DBG_HEX(tTextBlock.ulCharPos);
DBG_DEC(tTextBlock.ulLength);
DBG_DEC(tTextBlock.bUsesUnicode);
DBG_DEC(tTextBlock.usPropMod);
return FALSE;
}
return TRUE;
} /* end of bGetDocumentText */
/*
* iInitDocumentDOS - initialize an DOS document
*
* Returns the version of Word that made the document or -1
*/
int
iInitDocumentDOS(FILE *pFile, long lFilesize)
{
int iWordVersion;
BOOL bSuccess;
USHORT usIdent;
UCHAR aucHeader[128];
fail(pFile == NULL);
if (lFilesize < 128) {
return -1;
}
/* Read the headerblock */
if (!bReadBytes(aucHeader, 128, 0x00, pFile)) {
return -1;
}
/* Get the "magic number" from the header */
usIdent = usGetWord(0x00, aucHeader);
DBG_HEX(usIdent);
fail(usIdent != 0xbe31); /* Word for DOS */
iWordVersion = iGetVersionNumber(aucHeader);
if (iWordVersion != 0) {
werr(0, "This file is not from 'Word for DOS'.");
return -1;
}
bSuccess = bGetDocumentText(pFile, lFilesize, aucHeader);
if (bSuccess) {
vGetPropertyInfo(pFile, NULL,
NULL, 0, NULL, 0,
aucHeader, iWordVersion);
vSetDefaultTabWidth(pFile, NULL,
NULL, 0, NULL, 0,
aucHeader, iWordVersion);
vGetNotesInfo(pFile, NULL,
NULL, 0, NULL, 0,
aucHeader, iWordVersion);
}
return bSuccess ? iWordVersion : -1;
} /* end of iInitDocumentDOS */

359
src/wordlib.c Normal file
View File

@@ -0,0 +1,359 @@
/*
* wordlib.c
* Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Deal with the internals of a MS Word file
*/
#include "antiword.h"
static BOOL bOldMacFile = FALSE;
/*
* Common part of the file checking functions
*/
static BOOL
bCheckBytes(FILE *pFile, const UCHAR *aucBytes, size_t tBytes)
{
int iIndex, iChar;
fail(pFile == NULL || aucBytes == NULL || tBytes == 0);
rewind(pFile);
for (iIndex = 0; iIndex < (int)tBytes; iIndex++) {
iChar = getc(pFile);
if (iChar == EOF || iChar != (int)aucBytes[iIndex]) {
NO_DBG_HEX(iChar);
NO_DBG_HEX(aucBytes[iIndex]);
return FALSE;
}
}
return TRUE;
} /* end of bCheckBytes */
/*
* This function checks whether the given file is or is not a "Word for DOS"
* document
*/
BOOL
bIsWordForDosFile(FILE *pFile, long lFilesize)
{
static UCHAR aucBytes[] =
{ 0x31, 0xbe, 0x00, 0x00, 0x00, 0xab }; /* Word for DOS */
DBG_MSG("bIsWordForDosFile");
if (pFile == NULL || lFilesize < 0) {
DBG_MSG("No proper file given");
return FALSE;
}
if (lFilesize < 128) {
DBG_MSG("File too small to be a Word document");
return FALSE;
}
return bCheckBytes(pFile, aucBytes, elementsof(aucBytes));
} /* end of bIsWordForDosFile */
/*
* This function checks whether the given file is or is not a file with an
* OLE envelope (That is a document made by Word 6 or later)
*/
static BOOL
bIsWordFileWithOLE(FILE *pFile, long lFilesize)
{
static UCHAR aucBytes[] =
{ 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
int iTailLen;
if (pFile == NULL || lFilesize < 0) {
DBG_MSG("No proper file given");
return FALSE;
}
if (lFilesize < (long)BIG_BLOCK_SIZE * 3) {
DBG_MSG("This file is too small to be a Word document");
return FALSE;
}
iTailLen = (int)(lFilesize % BIG_BLOCK_SIZE);
switch (iTailLen) {
case 0: /* No tail, as it should be */
break;
case 1:
case 2: /* Filesize mismatch or a buggy email program */
if ((int)(lFilesize % 3) == iTailLen) {
DBG_DEC(lFilesize);
return FALSE;
}
/*
* Ignore extra bytes caused by buggy email programs.
* They have bugs in their base64 encoding or decoding.
* 3 bytes -> 4 ascii chars -> 3 bytes
*/
DBG_MSG("Document with extra bytes");
break;
default: /* Wrong filesize for a Word document */
DBG_DEC(lFilesize);
DBG_DEC(iTailLen);
return FALSE;
}
return bCheckBytes(pFile, aucBytes, elementsof(aucBytes));
} /* end of bIsWordFileWithOLE */
/*
* This function checks whether the given file is or is not a RTF document
*/
BOOL
bIsRtfFile(FILE *pFile)
{
static UCHAR aucBytes[] =
{ '{', '\\', 'r', 't', 'f', '1' };
DBG_MSG("bIsRtfFile");
return bCheckBytes(pFile, aucBytes, elementsof(aucBytes));
} /* end of bIsRtfFile */
/*
* This function checks whether the given file is or is not a WP document
*/
BOOL
bIsWordPerfectFile(FILE *pFile)
{
static UCHAR aucBytes[] =
{ 0xff, 'W', 'P', 'C' };
DBG_MSG("bIsWordPerfectFile");
return bCheckBytes(pFile, aucBytes, elementsof(aucBytes));
} /* end of bIsWordPerfectFile */
/*
* This function checks whether the given file is or is not a "Win Word 1 or 2"
* document
*/
BOOL
bIsWinWord12File(FILE *pFile, long lFilesize)
{
static UCHAR aucBytes[2][4] = {
{ 0x9b, 0xa5, 0x21, 0x00 }, /* Win Word 1.x */
{ 0xdb, 0xa5, 0x2d, 0x00 }, /* Win Word 2.0 */
};
int iIndex;
DBG_MSG("bIsWinWord12File");
if (pFile == NULL || lFilesize < 0) {
DBG_MSG("No proper file given");
return FALSE;
}
if (lFilesize < 384) {
DBG_MSG("This file is too small to be a Word document");
return FALSE;
}
for (iIndex = 0; iIndex < (int)elementsof(aucBytes); iIndex++) {
if (bCheckBytes(pFile,
aucBytes[iIndex],
elementsof(aucBytes[iIndex]))) {
return TRUE;
}
}
return FALSE;
} /* end of bIsWinWord12File */
/*
* This function checks whether the given file is or is not a "Mac Word 4 or 5"
* document
*/
BOOL
bIsMacWord45File(FILE *pFile)
{
static UCHAR aucBytes[2][6] = {
{ 0xfe, 0x37, 0x00, 0x1c, 0x00, 0x00 }, /* Mac Word 4 */
{ 0xfe, 0x37, 0x00, 0x23, 0x00, 0x00 }, /* Mac Word 5 */
};
int iIndex;
DBG_MSG("bIsMacWord45File");
for (iIndex = 0; iIndex < (int)elementsof(aucBytes); iIndex++) {
if (bCheckBytes(pFile,
aucBytes[iIndex],
elementsof(aucBytes[iIndex]))) {
return TRUE;
}
}
return FALSE;
} /* end of bIsMacWord45File */
/*
* iGuessVersionNumber - guess the Word version number from first few bytes
*
* Returns the guessed version number or -1 when no guess it possible
*/
int
iGuessVersionNumber(FILE *pFile, long lFilesize)
{
if(bIsWordForDosFile(pFile, lFilesize)) {
return 0;
}
if (bIsWinWord12File(pFile, lFilesize)) {
return 2;
}
if (bIsMacWord45File(pFile)) {
return 5;
}
if (bIsWordFileWithOLE(pFile, lFilesize)) {
return 6;
}
return -1;
} /* end of iGuessVersionNumber */
/*
* iGetVersionNumber - get the Word version number from the header
*
* Returns the version number or -1 when unknown
*/
int
iGetVersionNumber(const UCHAR *aucHeader)
{
USHORT usFib, usChse;
usFib = usGetWord(0x02, aucHeader);
if (usFib >= 0x1000) {
/* To big: must be MacWord using Big Endian */
DBG_HEX(usFib);
usFib = usGetWordBE(0x02, aucHeader);
}
DBG_DEC(usFib);
bOldMacFile = FALSE;
switch (usFib) {
case 0:
DBG_MSG("Word for DOS");
return 0;
case 28:
DBG_MSG("Word 4 for Macintosh");
bOldMacFile = TRUE;
return 4;
case 33:
DBG_MSG("Word 1.x for Windows");
return 1;
case 35:
DBG_MSG("Word 5 for Macintosh");
bOldMacFile = TRUE;
return 5;
case 45:
DBG_MSG("Word 2 for Windows");
return 2;
case 101:
case 102:
DBG_MSG("Word 6 for Windows");
return 6;
case 103:
case 104:
usChse = usGetWord(0x14, aucHeader);
DBG_DEC(usChse);
switch (usChse) {
case 0:
DBG_MSG("Word 7 for Win95");
return 7;
case 256:
DBG_MSG("Word 6 for Macintosh");
bOldMacFile = TRUE;
return 6;
default:
DBG_FIXME();
if ((int)ucGetByte(0x05, aucHeader) == 0xe0) {
DBG_MSG("Word 7 for Win95");
return 7;
}
DBG_MSG("Word 6 for Macintosh");
bOldMacFile = TRUE;
return 6;
}
default:
usChse = usGetWord(0x14, aucHeader);
DBG_DEC(usChse);
if (usFib < 192) {
/* Unknown or unsupported version of Word */
DBG_DEC(usFib);
return -1;
}
DBG_MSG_C(usChse != 256, "Word97 for Win95/98/NT");
DBG_MSG_C(usChse == 256, "Word98 for Macintosh");
return 8;
}
} /* end of iGetVersionNumber */
/*
* TRUE if the current file was made by Word version 6 or older on an
* Apple Macintosh, otherwise FALSE.
* This function hides the methode of how to find out from the rest of the
* program.
*/
BOOL
bIsOldMacFile(void)
{
return bOldMacFile;
} /* end of bIsOldMacFile */
/*
* iInitDocument - initialize a document
*
* Returns the version of Word that made the document or -1
*/
int
iInitDocument(FILE *pFile, long lFilesize)
{
int iGuess, iWordVersion;
iGuess = iGuessVersionNumber(pFile, lFilesize);
switch (iGuess) {
case 0:
iWordVersion = iInitDocumentDOS(pFile, lFilesize);
break;
case 2:
iWordVersion = iInitDocumentWIN(pFile, lFilesize);
break;
case 5:
iWordVersion = iInitDocumentMAC(pFile, lFilesize);
break;
case 6:
iWordVersion = iInitDocumentOLE(pFile, lFilesize);
break;
default:
DBG_DEC(iGuess);
iWordVersion = -1;
break;
}
return iWordVersion;
} /* end of iInitDocument */
/*
* vFreeDocument - free a document by free-ing its parts
*/
void
vFreeDocument(void)
{
DBG_MSG("vFreeDocument");
/* Free the memory */
vDestroyTextBlockList();
vDestroyDataBlockList();
vDestroyListInfoList();
vDestroyRowInfoList();
vDestroyStyleInfoList();
vDestroyFontInfoList();
vDestroyStylesheetList();
vDestroyPictInfoList();
vDestroyDocumentInfoList();
vDestroySectionInfoList();
vDestroyHdrFtrInfoList();
vDestroyPropModList();
vDestroyNotesInfoLists();
vDestroyFontTable();
vDestroySummaryInfo();
} /* end of vFreeDocument */

108
src/wordmac.c Normal file
View File

@@ -0,0 +1,108 @@
/*
* wordmac.c
* Copyright (C) 2002-2004 A.J. van Os; Released under GNU GPL
*
* Description:
* Deal with the MAC internals of a MS Word file
*/
#include "antiword.h"
/*
* bGetDocumentText - make a list of the text blocks of a Word document
*
* Return TRUE when succesful, otherwise FALSE
*/
static BOOL
bGetDocumentText(FILE *pFile, const UCHAR *aucHeader)
{
text_block_type tTextBlock;
ULONG ulBeginOfText, ulEndOfText;
ULONG ulTextLen;
UCHAR ucDocStatus;
BOOL bFastSaved;
fail(pFile == NULL);
fail(aucHeader == NULL);
DBG_MSG("bGetDocumentText");
NO_DBG_PRINT_BLOCK(aucHeader, 0x20);
/* Get the status flags from the header */
ucDocStatus = ucGetByte(0x0a, aucHeader);
DBG_HEX(ucDocStatus);
bFastSaved = (ucDocStatus & BIT(5)) != 0;
DBG_MSG_C(bFastSaved, "This document is Fast Saved");
if (bFastSaved) {
werr(0, "MacWord: fast saved documents are not supported yet");
return FALSE;
}
/* Get length information */
ulBeginOfText = ulGetLongBE(0x14, aucHeader);
DBG_HEX(ulBeginOfText);
ulEndOfText = ulGetLongBE(0x18, aucHeader);
DBG_HEX(ulEndOfText);
ulTextLen = ulEndOfText - ulBeginOfText;
DBG_DEC(ulTextLen);
tTextBlock.ulFileOffset = ulBeginOfText;
tTextBlock.ulCharPos = ulBeginOfText;
tTextBlock.ulLength = ulTextLen;
tTextBlock.bUsesUnicode = FALSE;
tTextBlock.usPropMod = IGNORE_PROPMOD;
if (!bAdd2TextBlockList(&tTextBlock)) {
DBG_HEX(tTextBlock.ulFileOffset);
DBG_HEX(tTextBlock.ulCharPos);
DBG_DEC(tTextBlock.ulLength);
DBG_DEC(tTextBlock.bUsesUnicode);
DBG_DEC(tTextBlock.usPropMod);
return FALSE;
}
return TRUE;
} /* end of bGetDocumentText */
/*
* iInitDocumentMAC - initialize an MAC document
*
* Returns the version of Word that made the document or -1
*/
int
iInitDocumentMAC(FILE *pFile, long lFilesize)
{
int iWordVersion;
BOOL bSuccess;
USHORT usIdent;
UCHAR aucHeader[256];
fail(pFile == NULL);
if (lFilesize < 256) {
return -1;
}
/* Read the headerblock */
if (!bReadBytes(aucHeader, 256, 0x00, pFile)) {
return -1;
}
/* Get the "magic number" from the header */
usIdent = usGetWord(0x00, aucHeader);
DBG_HEX(usIdent);
fail(usIdent != 0x37fe); /* MacWord 4 and 5 */
iWordVersion = iGetVersionNumber(aucHeader);
if (iWordVersion != 4 && iWordVersion != 5) {
werr(0, "This file is not from ''Mac Word 4 or 5'.");
return -1;
}
bSuccess = bGetDocumentText(pFile, aucHeader);
if (bSuccess) {
vGetPropertyInfo(pFile, NULL,
NULL, 0, NULL, 0,
aucHeader, iWordVersion);
vSetDefaultTabWidth(pFile, NULL,
NULL, 0, NULL, 0,
aucHeader, iWordVersion);
}
return bSuccess ? iWordVersion : -1;
} /* end of iInitDocumentMAC */

804
src/wordole.c Normal file
View File

@@ -0,0 +1,804 @@
/*
* wordole.c
* Copyright (C) 1998-2004 A.J. van Os; Released under GPL
*
* Description:
* Deal with the OLE internals of a MS Word file
*/
#include <string.h>
#include "antiword.h"
/* Private type for Property Set Storage entries */
typedef struct pps_entry_tag {
ULONG ulNext;
ULONG ulPrevious;
ULONG ulDir;
ULONG ulSB;
ULONG ulSize;
int iLevel;
char szName[32];
UCHAR ucType;
} pps_entry_type;
/* Show that a PPS number or index should not be used */
#define PPS_NUMBER_INVALID 0xffffffffUL
/* Macro to make sure all such statements will be identical */
#define FREE_ALL() \
do {\
vDestroySmallBlockList();\
aulRootList = xfree(aulRootList);\
aulSbdList = xfree(aulSbdList);\
aulBbdList = xfree(aulBbdList);\
aulSBD = xfree(aulSBD);\
aulBBD = xfree(aulBBD);\
} while(0)
/*
* ulReadLong - read four bytes from the given file and offset
*/
static ULONG
ulReadLong(FILE *pFile, ULONG ulOffset)
{
UCHAR aucBytes[4];
fail(pFile == NULL);
if (!bReadBytes(aucBytes, 4, ulOffset, pFile)) {
werr(1, "Read long 0x%lx not possible", ulOffset);
}
return ulGetLong(0, aucBytes);
} /* end of ulReadLong */
/*
* vName2String - turn the name into a proper string.
*/
static void
vName2String(char *szName, const UCHAR *aucBytes, size_t tNameSize)
{
char *pcChar;
size_t tIndex;
fail(aucBytes == NULL || szName == NULL);
if (tNameSize < 2) {
szName[0] = '\0';
return;
}
for (tIndex = 0, pcChar = szName;
tIndex < 2 * tNameSize;
tIndex += 2, pcChar++) {
*pcChar = (char)aucBytes[tIndex];
}
szName[tNameSize - 1] = '\0';
} /* end of vName2String */
/*
* tReadBlockIndices - read the Big/Small Block Depot indices
*
* Returns the number of indices read
*/
static size_t
tReadBlockIndices(FILE *pFile, ULONG *aulBlockDepot,
size_t tMaxRec, ULONG ulOffset)
{
size_t tDone;
int iIndex;
UCHAR aucBytes[BIG_BLOCK_SIZE];
fail(pFile == NULL || aulBlockDepot == NULL);
fail(tMaxRec == 0);
/* Read a big block with BBD or SBD indices */
if (!bReadBytes(aucBytes, BIG_BLOCK_SIZE, ulOffset, pFile)) {
werr(0, "Reading big block from 0x%lx is not possible",
ulOffset);
return 0;
}
/* Split the big block into indices, an index is four bytes */
tDone = min(tMaxRec, (size_t)BIG_BLOCK_SIZE / 4);
for (iIndex = 0; iIndex < (int)tDone; iIndex++) {
aulBlockDepot[iIndex] = ulGetLong(4 * iIndex, aucBytes);
NO_DBG_DEC(aulBlockDepot[iIndex]);
}
return tDone;
} /* end of tReadBlockIndices */
/*
* bGetBBD - get the Big Block Depot indices from the index-blocks
*/
static BOOL
bGetBBD(FILE *pFile, const ULONG *aulDepot, size_t tDepotLen,
ULONG *aulBBD, size_t tBBDLen)
{
ULONG ulBegin;
size_t tToGo, tDone;
int iIndex;
fail(pFile == NULL || aulDepot == NULL || aulBBD == NULL);
DBG_MSG("bGetBBD");
tToGo = tBBDLen;
for (iIndex = 0; iIndex < (int)tDepotLen && tToGo != 0; iIndex++) {
ulBegin = (aulDepot[iIndex] + 1) * BIG_BLOCK_SIZE;
NO_DBG_HEX(ulBegin);
tDone = tReadBlockIndices(pFile, aulBBD, tToGo, ulBegin);
fail(tDone > tToGo);
if (tDone == 0) {
return FALSE;
}
aulBBD += tDone;
tToGo -= tDone;
}
return tToGo == 0;
} /* end of bGetBBD */
/*
* bGetSBD - get the Small Block Depot indices from the index-blocks
*/
static BOOL
bGetSBD(FILE *pFile, const ULONG *aulDepot, size_t tDepotLen,
ULONG *aulSBD, size_t tSBDLen)
{
ULONG ulBegin;
size_t tToGo, tDone;
int iIndex;
fail(pFile == NULL || aulDepot == NULL || aulSBD == NULL);
DBG_MSG("bGetSBD");
tToGo = tSBDLen;
for (iIndex = 0; iIndex < (int)tDepotLen && tToGo != 0; iIndex++) {
fail(aulDepot[iIndex] >= ULONG_MAX / BIG_BLOCK_SIZE);
ulBegin = (aulDepot[iIndex] + 1) * BIG_BLOCK_SIZE;
NO_DBG_HEX(ulBegin);
tDone = tReadBlockIndices(pFile, aulSBD, tToGo, ulBegin);
fail(tDone > tToGo);
if (tDone == 0) {
return FALSE;
}
aulSBD += tDone;
tToGo -= tDone;
}
return tToGo == 0;
} /* end of bGetSBD */
/*
* vComputePPSlevels - compute the levels of the Property Set Storage entries
*/
static void
vComputePPSlevels(pps_entry_type *atPPSlist, pps_entry_type *pNode,
int iLevel, int iRecursionLevel)
{
fail(atPPSlist == NULL || pNode == NULL);
fail(iLevel < 0 || iRecursionLevel < 0);
if (iRecursionLevel > 25) {
/* This removes the possibility of an infinite recursion */
DBG_DEC(iRecursionLevel);
return;
}
if (pNode->iLevel <= iLevel) {
/* Avoid entering a loop */
DBG_DEC(iLevel);
DBG_DEC(pNode->iLevel);
return;
}
pNode->iLevel = iLevel;
if (pNode->ulDir != PPS_NUMBER_INVALID) {
vComputePPSlevels(atPPSlist,
&atPPSlist[pNode->ulDir],
iLevel + 1,
iRecursionLevel + 1);
}
if (pNode->ulNext != PPS_NUMBER_INVALID) {
vComputePPSlevels(atPPSlist,
&atPPSlist[pNode->ulNext],
iLevel,
iRecursionLevel + 1);
}
if (pNode->ulPrevious != PPS_NUMBER_INVALID) {
vComputePPSlevels(atPPSlist,
&atPPSlist[pNode->ulPrevious],
iLevel,
iRecursionLevel + 1);
}
} /* end of vComputePPSlevels */
/*
* bGetPPS - search the Property Set Storage for three sets
*
* Return TRUE if the WordDocument PPS is found
*/
static BOOL
bGetPPS(FILE *pFile,
const ULONG *aulRootList, size_t tRootListLen, pps_info_type *pPPS)
{
pps_entry_type *atPPSlist;
ULONG ulBegin, ulOffset, ulTmp;
size_t tNbrOfPPS, tNameSize;
int iIndex, iStartBlock, iRootIndex;
BOOL bWord, bExcel;
UCHAR aucBytes[PROPERTY_SET_STORAGE_SIZE];
fail(pFile == NULL || aulRootList == NULL || pPPS == NULL);
DBG_MSG("bGetPPS");
NO_DBG_DEC(tRootListLen);
bWord = FALSE;
bExcel = FALSE;
(void)memset(pPPS, 0, sizeof(*pPPS));
/* Read and store all the Property Set Storage entries */
tNbrOfPPS = tRootListLen * BIG_BLOCK_SIZE / PROPERTY_SET_STORAGE_SIZE;
atPPSlist = xcalloc(tNbrOfPPS, sizeof(pps_entry_type));
iRootIndex = 0;
for (iIndex = 0; iIndex < (int)tNbrOfPPS; iIndex++) {
ulTmp = (ULONG)iIndex * PROPERTY_SET_STORAGE_SIZE;
iStartBlock = (int)(ulTmp / BIG_BLOCK_SIZE);
ulOffset = ulTmp % BIG_BLOCK_SIZE;
ulBegin = (aulRootList[iStartBlock] + 1) * BIG_BLOCK_SIZE +
ulOffset;
NO_DBG_HEX(ulBegin);
if (!bReadBytes(aucBytes, PROPERTY_SET_STORAGE_SIZE,
ulBegin, pFile)) {
werr(0, "Reading PPS %d is not possible", iIndex);
atPPSlist = xfree(atPPSlist);
return FALSE;
}
tNameSize = (size_t)usGetWord(0x40, aucBytes);
tNameSize = (tNameSize + 1) / 2;
vName2String(atPPSlist[iIndex].szName, aucBytes, tNameSize);
atPPSlist[iIndex].ucType = ucGetByte(0x42, aucBytes);
if (atPPSlist[iIndex].ucType == 5) {
iRootIndex = iIndex;
}
atPPSlist[iIndex].ulPrevious = ulGetLong(0x44, aucBytes);
atPPSlist[iIndex].ulNext = ulGetLong(0x48, aucBytes);
atPPSlist[iIndex].ulDir = ulGetLong(0x4c, aucBytes);
atPPSlist[iIndex].ulSB = ulGetLong(0x74, aucBytes);
atPPSlist[iIndex].ulSize = ulGetLong(0x78, aucBytes);
atPPSlist[iIndex].iLevel = INT_MAX;
if ((atPPSlist[iIndex].ulPrevious >= (ULONG)tNbrOfPPS &&
atPPSlist[iIndex].ulPrevious != PPS_NUMBER_INVALID) ||
(atPPSlist[iIndex].ulNext >= (ULONG)tNbrOfPPS &&
atPPSlist[iIndex].ulNext != PPS_NUMBER_INVALID) ||
(atPPSlist[iIndex].ulDir >= (ULONG)tNbrOfPPS &&
atPPSlist[iIndex].ulDir != PPS_NUMBER_INVALID)) {
DBG_DEC(iIndex);
DBG_DEC(atPPSlist[iIndex].ulPrevious);
DBG_DEC(atPPSlist[iIndex].ulNext);
DBG_DEC(atPPSlist[iIndex].ulDir);
DBG_DEC(tNbrOfPPS);
werr(0, "The Property Set Storage is damaged");
atPPSlist = xfree(atPPSlist);
return FALSE;
}
}
#if 0 /* defined(DEBUG) */
DBG_MSG("Before");
for (iIndex = 0; iIndex < (int)tNbrOfPPS; iIndex++) {
DBG_MSG(atPPSlist[iIndex].szName);
DBG_HEX(atPPSlist[iIndex].ulDir);
DBG_HEX(atPPSlist[iIndex].ulPrevious);
DBG_HEX(atPPSlist[iIndex].ulNext);
DBG_DEC(atPPSlist[iIndex].ulSB);
DBG_HEX(atPPSlist[iIndex].ulSize);
DBG_DEC(atPPSlist[iIndex].iLevel);
}
#endif /* DEBUG */
/* Add level information to each entry */
vComputePPSlevels(atPPSlist, &atPPSlist[iRootIndex], 0, 0);
/* Check the entries on level 1 for the required information */
NO_DBG_MSG("After");
for (iIndex = 0; iIndex < (int)tNbrOfPPS; iIndex++) {
#if 0 /* defined(DEBUG) */
DBG_MSG(atPPSlist[iIndex].szName);
DBG_HEX(atPPSlist[iIndex].ulDir);
DBG_HEX(atPPSlist[iIndex].ulPrevious);
DBG_HEX(atPPSlist[iIndex].ulNext);
DBG_DEC(atPPSlist[iIndex].ulSB);
DBG_HEX(atPPSlist[iIndex].ulSize);
DBG_DEC(atPPSlist[iIndex].iLevel);
#endif /* DEBUG */
if (atPPSlist[iIndex].iLevel != 1 ||
atPPSlist[iIndex].ucType != 2 ||
atPPSlist[iIndex].szName[0] == '\0' ||
atPPSlist[iIndex].ulSize == 0) {
/* This entry can be ignored */
continue;
}
if (pPPS->tWordDocument.ulSize == 0 &&
STREQ(atPPSlist[iIndex].szName, "WordDocument")) {
pPPS->tWordDocument.ulSB = atPPSlist[iIndex].ulSB;
pPPS->tWordDocument.ulSize = atPPSlist[iIndex].ulSize;
bWord = TRUE;
} else if (pPPS->tData.ulSize == 0 &&
STREQ(atPPSlist[iIndex].szName, "Data")) {
pPPS->tData.ulSB = atPPSlist[iIndex].ulSB;
pPPS->tData.ulSize = atPPSlist[iIndex].ulSize;
} else if (pPPS->t0Table.ulSize == 0 &&
STREQ(atPPSlist[iIndex].szName, "0Table")) {
pPPS->t0Table.ulSB = atPPSlist[iIndex].ulSB;
pPPS->t0Table.ulSize = atPPSlist[iIndex].ulSize;
} else if (pPPS->t1Table.ulSize == 0 &&
STREQ(atPPSlist[iIndex].szName, "1Table")) {
pPPS->t1Table.ulSB = atPPSlist[iIndex].ulSB;
pPPS->t1Table.ulSize = atPPSlist[iIndex].ulSize;
} else if (pPPS->tSummaryInfo.ulSize == 0 &&
STREQ(atPPSlist[iIndex].szName,
"\005SummaryInformation")) {
pPPS->tSummaryInfo.ulSB = atPPSlist[iIndex].ulSB;
pPPS->tSummaryInfo.ulSize = atPPSlist[iIndex].ulSize;
} else if (pPPS->tDocSummaryInfo.ulSize == 0 &&
STREQ(atPPSlist[iIndex].szName,
"\005DocumentSummaryInformation")) {
pPPS->tDocSummaryInfo.ulSB = atPPSlist[iIndex].ulSB;
pPPS->tDocSummaryInfo.ulSize = atPPSlist[iIndex].ulSize;
} else if (STREQ(atPPSlist[iIndex].szName, "Book") ||
STREQ(atPPSlist[iIndex].szName, "Workbook")) {
bExcel = TRUE;
}
}
/* Free the space for the Property Set Storage entries */
atPPSlist = xfree(atPPSlist);
/* Draw your conclusions */
if (bWord) {
return TRUE;
}
if (bExcel) {
werr(0, "Sorry, but this is an Excel spreadsheet");
} else {
werr(0, "This OLE file does not contain a Word document");
}
return FALSE;
} /* end of bGetPPS */
/*
* vGetBbdList - make a list of the places to find big blocks
*/
static void
vGetBbdList(FILE *pFile, int iNbr, ULONG *aulBbdList, ULONG ulOffset)
{
int iIndex;
fail(pFile == NULL);
fail(iNbr > 127);
fail(aulBbdList == NULL);
NO_DBG_DEC(iNbr);
for (iIndex = 0; iIndex < iNbr; iIndex++) {
aulBbdList[iIndex] =
ulReadLong(pFile, ulOffset + 4 * (ULONG)iIndex);
NO_DBG_DEC(iIndex);
NO_DBG_HEX(aulBbdList[iIndex]);
}
} /* end of vGetBbdList */
/*
* bGetDocumentText - make a list of the text blocks of a Word document
*
* Return TRUE when succesful, otherwise FALSE
*/
static BOOL
bGetDocumentText(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader, int iWordVersion)
{
ULONG ulBeginOfText;
ULONG ulTextLen, ulFootnoteLen, ulEndnoteLen;
ULONG ulHdrFtrLen, ulMacroLen, ulAnnotationLen;
ULONG ulTextBoxLen, ulHdrTextBoxLen;
UINT uiQuickSaves;
BOOL bFarEastWord, bTemplate, bFastSaved, bEncrypted, bSuccess;
USHORT usIdent, usDocStatus;
fail(pFile == NULL || pPPS == NULL);
fail(aulBBD == NULL);
fail(aulSBD == NULL);
DBG_MSG("bGetDocumentText");
/* Get the "magic number" from the header */
usIdent = usGetWord(0x00, aucHeader);
DBG_HEX(usIdent);
bFarEastWord = usIdent == 0x8098 || usIdent == 0x8099 ||
usIdent == 0xa697 || usIdent == 0xa699;
/* Get the status flags from the header */
usDocStatus = usGetWord(0x0a, aucHeader);
DBG_HEX(usDocStatus);
bTemplate = (usDocStatus & BIT(0)) != 0;
DBG_MSG_C(bTemplate, "This document is a Template");
bFastSaved = (usDocStatus & BIT(2)) != 0;
uiQuickSaves = (UINT)(usDocStatus & 0x00f0) >> 4;
DBG_MSG_C(bFastSaved, "This document is Fast Saved");
DBG_DEC_C(bFastSaved, uiQuickSaves);
bEncrypted = (usDocStatus & BIT(8)) != 0;
if (bEncrypted) {
werr(0, "Encrypted documents are not supported");
return FALSE;
}
/* Get length information */
ulBeginOfText = ulGetLong(0x18, aucHeader);
DBG_HEX(ulBeginOfText);
switch (iWordVersion) {
case 6:
case 7:
ulTextLen = ulGetLong(0x34, aucHeader);
ulFootnoteLen = ulGetLong(0x38, aucHeader);
ulHdrFtrLen = ulGetLong(0x3c, aucHeader);
ulMacroLen = ulGetLong(0x40, aucHeader);
ulAnnotationLen = ulGetLong(0x44, aucHeader);
ulEndnoteLen = ulGetLong(0x48, aucHeader);
ulTextBoxLen = ulGetLong(0x4c, aucHeader);
ulHdrTextBoxLen = ulGetLong(0x50, aucHeader);
break;
case 8:
ulTextLen = ulGetLong(0x4c, aucHeader);
ulFootnoteLen = ulGetLong(0x50, aucHeader);
ulHdrFtrLen = ulGetLong(0x54, aucHeader);
ulMacroLen = ulGetLong(0x58, aucHeader);
ulAnnotationLen = ulGetLong(0x5c, aucHeader);
ulEndnoteLen = ulGetLong(0x60, aucHeader);
ulTextBoxLen = ulGetLong(0x64, aucHeader);
ulHdrTextBoxLen = ulGetLong(0x68, aucHeader);
break;
default:
werr(0, "This version of Word is not supported");
return FALSE;
}
DBG_DEC(ulTextLen);
DBG_DEC(ulFootnoteLen);
DBG_DEC(ulHdrFtrLen);
DBG_DEC(ulMacroLen);
DBG_DEC(ulAnnotationLen);
DBG_DEC(ulEndnoteLen);
DBG_DEC(ulTextBoxLen);
DBG_DEC(ulHdrTextBoxLen);
/* Make a list of the text blocks */
switch (iWordVersion) {
case 6:
case 7:
if (bFastSaved) {
bSuccess = bGet6DocumentText(pFile,
bFarEastWord,
pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen,
aucHeader);
} else {
bSuccess = bAddTextBlocks(ulBeginOfText,
ulTextLen +
ulFootnoteLen +
ulHdrFtrLen +
ulMacroLen + ulAnnotationLen +
ulEndnoteLen +
ulTextBoxLen + ulHdrTextBoxLen,
bFarEastWord,
IGNORE_PROPMOD,
pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen);
}
break;
case 8:
bSuccess = bGet8DocumentText(pFile,
pPPS,
aulBBD, tBBDLen, aulSBD, tSBDLen,
aucHeader);
break;
default:
werr(0, "This version of Word is not supported");
bSuccess = FALSE;
break;
}
if (bSuccess) {
vSplitBlockList(pFile,
ulTextLen,
ulFootnoteLen,
ulHdrFtrLen,
ulMacroLen,
ulAnnotationLen,
ulEndnoteLen,
ulTextBoxLen,
ulHdrTextBoxLen,
!bFastSaved && iWordVersion == 8);
} else {
vDestroyTextBlockList();
werr(0, "I can't find the text of this document");
}
return bSuccess;
} /* end of bGetDocumentText */
/*
* vGetDocumentData - make a list of the data blocks of a Word document
*/
static void
vGetDocumentData(FILE *pFile, const pps_info_type *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const UCHAR *aucHeader, int iWordVersion)
{
options_type tOptions;
ULONG ulBeginOfText;
BOOL bFastSaved, bHasImages, bSuccess;
USHORT usDocStatus;
fail(pFile == NULL);
fail(pPPS == NULL);
fail(aulBBD == NULL);
/* Get the options */
vGetOptions(&tOptions);
/* Get the status flags from the header */
usDocStatus = usGetWord(0x0a, aucHeader);
DBG_HEX(usDocStatus);
bFastSaved = (usDocStatus & BIT(2)) != 0;
bHasImages = (usDocStatus & BIT(3)) != 0;
if (!bHasImages ||
tOptions.eConversionType == conversion_text ||
tOptions.eConversionType == conversion_fmt_text ||
tOptions.eConversionType == conversion_xml ||
tOptions.eImageLevel == level_no_images) {
/*
* No images in the document or text-only output or
* no images wanted, so no data blocks will be needed
*/
vDestroyDataBlockList();
return;
}
/* Get length information */
ulBeginOfText = ulGetLong(0x18, aucHeader);
DBG_HEX(ulBeginOfText);
/* Make a list of the data blocks */
switch (iWordVersion) {
case 6:
case 7:
/*
* The data blocks are in the text stream. The text stream
* is in "fast saved" format or "normal saved" format
*/
if (bFastSaved) {
bSuccess = bGet6DocumentData(pFile,
pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen,
aucHeader);
} else {
bSuccess = bAddDataBlocks(ulBeginOfText,
(ULONG)LONG_MAX,
pPPS->tWordDocument.ulSB,
aulBBD, tBBDLen);
}
break;
case 8:
/*
* The data blocks are in the data stream. The data stream
* is always in "normal saved" format
*/
bSuccess = bAddDataBlocks(0, (ULONG)LONG_MAX,
pPPS->tData.ulSB, aulBBD, tBBDLen);
break;
default:
werr(0, "This version of Word is not supported");
bSuccess = FALSE;
break;
}
if (!bSuccess) {
vDestroyDataBlockList();
werr(0, "I can't find the data of this document");
}
} /* end of vGetDocumentData */
/*
* iInitDocumentOLE - initialize an OLE document
*
* Returns the version of Word that made the document or -1
*/
int
iInitDocumentOLE(FILE *pFile, long lFilesize)
{
pps_info_type PPS_info;
ULONG *aulBBD, *aulSBD;
ULONG *aulRootList, *aulBbdList, *aulSbdList;
ULONG ulBdbListStart, ulAdditionalBBDlist;
ULONG ulRootStartblock, ulSbdStartblock, ulSBLstartblock;
ULONG ulStart, ulTmp;
long lMaxBlock;
size_t tBBDLen, tSBDLen, tNumBbdBlocks, tRootListLen;
int iWordVersion, iIndex, iToGo;
BOOL bSuccess;
USHORT usIdent, usDocStatus;
UCHAR aucHeader[HEADER_SIZE];
fail(pFile == NULL);
lMaxBlock = lFilesize / BIG_BLOCK_SIZE - 2;
DBG_DEC(lMaxBlock);
if (lMaxBlock < 1) {
return -1;
}
tBBDLen = (size_t)(lMaxBlock + 1);
tNumBbdBlocks = (size_t)ulReadLong(pFile, 0x2c);
DBG_DEC(tNumBbdBlocks);
ulRootStartblock = ulReadLong(pFile, 0x30);
DBG_DEC(ulRootStartblock);
ulSbdStartblock = ulReadLong(pFile, 0x3c);
DBG_DEC(ulSbdStartblock);
ulAdditionalBBDlist = ulReadLong(pFile, 0x44);
DBG_HEX(ulAdditionalBBDlist);
ulSBLstartblock = ulReadLong(pFile,
(ulRootStartblock + 1) * BIG_BLOCK_SIZE + 0x74);
DBG_DEC(ulSBLstartblock);
tSBDLen = (size_t)(ulReadLong(pFile,
(ulRootStartblock + 1) * BIG_BLOCK_SIZE + 0x78) /
SMALL_BLOCK_SIZE);
/* All to be xcalloc-ed pointers to NULL */
aulRootList = NULL;
aulSbdList = NULL;
aulBbdList = NULL;
aulSBD = NULL;
aulBBD = NULL;
/* Big Block Depot */
aulBbdList = xcalloc(tNumBbdBlocks, sizeof(ULONG));
aulBBD = xcalloc(tBBDLen, sizeof(ULONG));
iToGo = (int)tNumBbdBlocks;
vGetBbdList(pFile, min(iToGo, 109), aulBbdList, 0x4c);
ulStart = 109;
iToGo -= 109;
while (ulAdditionalBBDlist != END_OF_CHAIN && iToGo > 0) {
ulBdbListStart = (ulAdditionalBBDlist + 1) * BIG_BLOCK_SIZE;
vGetBbdList(pFile, min(iToGo, 127),
aulBbdList + ulStart, ulBdbListStart);
ulAdditionalBBDlist = ulReadLong(pFile,
ulBdbListStart + 4 * 127);
DBG_DEC(ulAdditionalBBDlist);
DBG_HEX(ulAdditionalBBDlist);
ulStart += 127;
iToGo -= 127;
}
if (!bGetBBD(pFile, aulBbdList, tNumBbdBlocks, aulBBD, tBBDLen)) {
FREE_ALL();
return -1;
}
aulBbdList = xfree(aulBbdList);
/* Small Block Depot */
aulSbdList = xcalloc(tBBDLen, sizeof(ULONG));
aulSBD = xcalloc(tSBDLen, sizeof(ULONG));
for (iIndex = 0, ulTmp = ulSbdStartblock;
iIndex < (int)tBBDLen && ulTmp != END_OF_CHAIN;
iIndex++, ulTmp = aulBBD[ulTmp]) {
if (ulTmp >= (ULONG)tBBDLen) {
DBG_DEC(ulTmp);
DBG_DEC(tBBDLen);
werr(1, "The Big Block Depot is damaged");
}
aulSbdList[iIndex] = ulTmp;
NO_DBG_HEX(aulSbdList[iIndex]);
}
if (!bGetSBD(pFile, aulSbdList, tBBDLen, aulSBD, tSBDLen)) {
FREE_ALL();
return -1;
}
aulSbdList = xfree(aulSbdList);
/* Root list */
for (tRootListLen = 0, ulTmp = ulRootStartblock;
tRootListLen < tBBDLen && ulTmp != END_OF_CHAIN;
tRootListLen++, ulTmp = aulBBD[ulTmp]) {
if (ulTmp >= (ULONG)tBBDLen) {
DBG_DEC(ulTmp);
DBG_DEC(tBBDLen);
werr(1, "The Big Block Depot is damaged");
}
}
if (tRootListLen == 0) {
werr(0, "No Rootlist found");
FREE_ALL();
return -1;
}
aulRootList = xcalloc(tRootListLen, sizeof(ULONG));
for (iIndex = 0, ulTmp = ulRootStartblock;
iIndex < (int)tBBDLen && ulTmp != END_OF_CHAIN;
iIndex++, ulTmp = aulBBD[ulTmp]) {
if (ulTmp >= (ULONG)tBBDLen) {
DBG_DEC(ulTmp);
DBG_DEC(tBBDLen);
werr(1, "The Big Block Depot is damaged");
}
aulRootList[iIndex] = ulTmp;
NO_DBG_DEC(aulRootList[iIndex]);
}
fail(tRootListLen != (size_t)iIndex);
bSuccess = bGetPPS(pFile, aulRootList, tRootListLen, &PPS_info);
aulRootList = xfree(aulRootList);
if (!bSuccess) {
FREE_ALL();
return -1;
}
/* Small block list */
if (!bCreateSmallBlockList(ulSBLstartblock, aulBBD, tBBDLen)) {
FREE_ALL();
return -1;
}
if (PPS_info.tWordDocument.ulSize < MIN_SIZE_FOR_BBD_USE) {
DBG_DEC(PPS_info.tWordDocument.ulSize);
FREE_ALL();
werr(0, "I'm afraid the text stream of this file "
"is too small to handle.");
return -1;
}
/* Read the headerblock */
if (!bReadBuffer(pFile, PPS_info.tWordDocument.ulSB,
aulBBD, tBBDLen, BIG_BLOCK_SIZE,
aucHeader, 0, HEADER_SIZE)) {
FREE_ALL();
return -1;
}
usIdent = usGetWord(0x00, aucHeader);
DBG_HEX(usIdent);
fail(usIdent != 0x8098 && /* Word 7 for oriental languages */
usIdent != 0x8099 && /* Word 7 for oriental languages */
usIdent != 0xa5dc && /* Word 6 & 7 */
usIdent != 0xa5ec && /* Word 7 & 97 & 98 */
usIdent != 0xa697 && /* Word 7 for oriental languages */
usIdent != 0xa699); /* Word 7 for oriental languages */
iWordVersion = iGetVersionNumber(aucHeader);
if (iWordVersion < 6) {
FREE_ALL();
werr(0, "This file is from a version of Word before Word 6.");
return -1;
}
/* Get the status flags from the header */
usDocStatus = usGetWord(0x0a, aucHeader);
if (usDocStatus & BIT(9)) {
PPS_info.tTable = PPS_info.t1Table;
} else {
PPS_info.tTable = PPS_info.t0Table;
}
/* Clean the entries that should not be used */
memset(&PPS_info.t0Table, 0, sizeof(PPS_info.t0Table));
memset(&PPS_info.t1Table, 0, sizeof(PPS_info.t1Table));
bSuccess = bGetDocumentText(pFile, &PPS_info,
aulBBD, tBBDLen, aulSBD, tSBDLen,
aucHeader, iWordVersion);
if (bSuccess) {
vGetDocumentData(pFile, &PPS_info,
aulBBD, tBBDLen, aucHeader, iWordVersion);
vGetPropertyInfo(pFile, &PPS_info,
aulBBD, tBBDLen, aulSBD, tSBDLen,
aucHeader, iWordVersion);
vSetDefaultTabWidth(pFile, &PPS_info,
aulBBD, tBBDLen, aulSBD, tSBDLen,
aucHeader, iWordVersion);
vGetNotesInfo(pFile, &PPS_info,
aulBBD, tBBDLen, aulSBD, tSBDLen,
aucHeader, iWordVersion);
}
FREE_ALL();
return bSuccess ? iWordVersion : -1;
} /* end of iInitDocumentOLE */

317
src/wordtypes.h Normal file
View File

@@ -0,0 +1,317 @@
/*
* wordtypes.h
* Copyright (C) 1998-2004 A.J. van Os; Released under GPL
*
* Description:
* Typedefs for the interpretation of MS Word files
*/
#if !defined(__wordtypes_h)
#define __wordtypes_h 1
#include <time.h>
#if defined(__riscos)
#include "DeskLib:Font.h"
#include "DeskLib:Wimp.h"
#endif /* __riscos */
typedef unsigned char UCHAR;
typedef unsigned short USHORT;
typedef unsigned int UINT;
typedef unsigned long ULONG;
#if defined(__riscos)
typedef struct diagram_tag {
drawfile_info tInfo;
window_handle tMainWindow;
window_handle tScaleWindow;
menu_ptr pSaveMenu;
long lXleft; /* In DrawUnits */
long lYtop; /* In DrawUnits */
size_t tMemorySize;
int iScaleFactorCurr; /* In percentage */
int iScaleFactorTemp; /* In percentage */
char szFilename[19+1];
} diagram_type;
#else
typedef struct diagram_tag {
FILE *pOutFile;
long lXleft; /* In DrawUnits */
long lYtop; /* In DrawUnits */
} diagram_type;
typedef UCHAR drawfile_fontref;
#endif /* __riscos */
typedef struct output_tag {
char *szStorage;
long lStringWidth; /* In millipoints */
size_t tStorageSize;
size_t tNextFree;
USHORT usFontStyle;
USHORT usFontSize;
UCHAR ucFontColor;
drawfile_fontref tFontRef;
struct output_tag *pPrev;
struct output_tag *pNext;
} output_type;
/* Types of conversion */
typedef enum conversion_tag {
conversion_unknown = 0,
conversion_text,
conversion_draw,
conversion_ps,
conversion_xml,
conversion_pdf,
conversion_fmt_text
} conversion_type;
/* Types of encoding */
typedef enum encoding_tag {
encoding_neutral = 100,
encoding_latin_1 = 801,
encoding_latin_2 = 802,
encoding_cyrillic = 805,
encoding_utf_8 = 1601
} encoding_type;
/* Font translation table entry */
typedef struct font_table_tag {
USHORT usFontStyle;
UCHAR ucWordFontNumber;
UCHAR ucFFN;
UCHAR ucEmphasis;
UCHAR ucInUse;
char szWordFontname[65];
char szOurFontname[33];
} font_table_type;
/* Options */
typedef enum image_level_tag {
level_gs_special = 0,
level_no_images,
level_ps_2,
level_ps_3,
level_default = level_ps_2
} image_level_enum;
typedef struct options_tag {
int iParagraphBreak;
conversion_type eConversionType;
BOOL bHideHiddenText;
BOOL bRemoveRemovedText;
BOOL bUseLandscape;
encoding_type eEncoding;
int iPageHeight; /* In points */
int iPageWidth; /* In points */
image_level_enum eImageLevel;
#if defined(__riscos)
BOOL bAutofiletypeAllowed;
int iScaleFactor; /* As a percentage */
#endif /* __riscos */
} options_type;
/* Property Set Storage */
typedef struct pps_tag {
ULONG ulSB;
ULONG ulSize;
} pps_type;
typedef struct pps_info_tag {
pps_type tWordDocument; /* Text stream */
pps_type tData; /* Data stream */
pps_type tTable; /* Table stream */
pps_type tSummaryInfo; /* Summary Information */
pps_type tDocSummaryInfo;/* Document Summary Information */
pps_type t0Table; /* Table 0 stream */
pps_type t1Table; /* Table 1 stream */
} pps_info_type;
/* Record of data block information */
typedef struct data_block_tag {
ULONG ulFileOffset;
ULONG ulDataPos;
ULONG ulLength;
} data_block_type;
/* Record of text block information */
typedef struct text_block_tag {
ULONG ulFileOffset;
ULONG ulCharPos;
ULONG ulLength;
BOOL bUsesUnicode; /* This block uses 16 bits per character */
USHORT usPropMod;
} text_block_type;
/* Record of the document block information */
typedef struct document_block_tag {
time_t tCreateDate; /* Unix timestamp */
time_t tRevisedDate; /* Unix timestamp */
USHORT usDefaultTabWidth; /* In twips */
UCHAR ucHdrFtrSpecification;
} document_block_type;
/* Record of table-row block information */
typedef struct row_block_tag {
ULONG ulFileOffsetStart;
ULONG ulFileOffsetEnd;
ULONG ulCharPosStart;
ULONG ulCharPosEnd;
short asColumnWidth[TABLE_COLUMN_MAX+1]; /* In twips */
UCHAR ucNumberOfColumns;
UCHAR ucBorderInfo;
} row_block_type;
/* Various level types */
typedef enum level_type_tag {
level_type_none = 0,
level_type_outline,
level_type_numbering,
level_type_sequence,
level_type_pause
} level_type_enum;
typedef enum list_id_tag {
no_list = 0,
text_list,
footnote_list,
hdrftr_list,
macro_list,
annotation_list,
endnote_list,
textbox_list,
hdrtextbox_list,
end_of_lists
} list_id_enum;
/* Linked list of style description information */
typedef struct style_block_tag {
ULONG ulFileOffset; /* The style start with this character */
list_id_enum eListID;/* The fileoffset is in this list */
BOOL bNumPause;
BOOL bNoRestart; /* Don't restart by more significant levels */
USHORT usIstd; /* Current style */
USHORT usIstdNext; /* Next style unless overruled */
USHORT usStartAt; /* Number at the start of a list */
USHORT usBeforeIndent; /* Vertical indent before paragraph in twips */
USHORT usAfterIndent; /* Vertical indent after paragraph in twips */
USHORT usListIndex; /* Before Word 8 this field was not filled */
USHORT usListChar; /* Character for an itemized list (Unicode) */
short sLeftIndent; /* Left indentation in twips */
short sLeftIndent1; /* First line left indentation in twips */
short sRightIndent; /* Right indentation in twips */
UCHAR ucAlignment;
UCHAR ucNFC; /* Number format code */
UCHAR ucNumLevel;
UCHAR ucListLevel; /* Before Word 8 this field was not filled */
char szListChar[4]; /* Character for an itemized list */
} style_block_type;
/* Font description information */
typedef struct font_block_tag {
ULONG ulFileOffset;
USHORT usFontStyle;
USHORT usFontSize;
UCHAR ucFontNumber;
UCHAR ucFontColor;
} font_block_type;
/* Picture description information */
typedef struct picture_block_tag {
ULONG ulFileOffset;
ULONG ulFileOffsetPicture;
ULONG ulPictureOffset;
} picture_block_type;
/* Section description information */
typedef struct section_block_tag {
BOOL bNewPage;
USHORT usNeedPrevLvl; /* Print previous level numbers */
USHORT usHangingIndent;
UCHAR aucNFC[9]; /* Number format code */
UCHAR ucHdrFtrSpecification; /* Which headers/footers Word < 8 */
} section_block_type;
/* Header/footer description information */
typedef struct hdrftr_block_tag {
output_type *pText;
long lHeight; /* In DrawUnits */
} hdrftr_block_type;
/* Footnote description information */
typedef struct footnote_block_tag {
char *szText;
} footnote_block_type;
/* List description information */
typedef struct list_block_tag {
ULONG ulStartAt; /* Number at the start of a list */
BOOL bNoRestart; /* Don't restart by more significant levels */
USHORT usListChar; /* Character for an itemized list (Unicode) */
short sLeftIndent; /* Left indentation in twips */
UCHAR ucNFC; /* Number format code */
} list_block_type;
/* Types of images */
typedef enum imagetype_tag {
imagetype_is_unknown = 0,
imagetype_is_external,
imagetype_is_emf,
imagetype_is_wmf,
imagetype_is_pict,
imagetype_is_jpeg,
imagetype_is_png,
imagetype_is_dib
} imagetype_enum;
/* Types of compression */
typedef enum compression_tag {
compression_unknown = 0,
compression_none,
compression_rle4,
compression_rle8,
compression_jpeg,
compression_zlib
} compression_enum;
/* Image information */
typedef struct imagedata_tag {
/* The type of the image */
imagetype_enum eImageType;
/* Information from the Word document */
size_t tPosition;
size_t tLength;
int iHorSizeScaled; /* Size in points */
int iVerSizeScaled; /* Size in points */
/* Information from the image */
int iWidth; /* Size in pixels */
int iHeight; /* Size in pixels */
int iComponents; /* Number of color components */
UINT uiBitsPerComponent; /* Bits per color component */
BOOL bAdobe; /* Image includes Adobe comment marker */
compression_enum eCompression; /* Type of compression */
BOOL bColorImage; /* Is color image */
int iColorsUsed; /* 0 = uses the maximum number of colors */
UCHAR aucPalette[256][3]; /* RGB palette */
} imagedata_type;
typedef enum row_info_tag {
found_nothing,
found_a_cell,
found_not_a_cell,
found_end_of_row,
found_not_end_of_row
} row_info_enum;
typedef enum notetype_tag {
notetype_is_footnote,
notetype_is_endnote,
notetype_is_unknown
} notetype_enum;
typedef enum image_info_tag {
image_no_information,
image_minimal_information,
image_full_information
} image_info_enum;
#endif /* __wordtypes_h */

209
src/wordwin.c Normal file
View File

@@ -0,0 +1,209 @@
/*
* wordwin.c
* Copyright (C) 2002-2005 A.J. van Os; Released under GPL
*
* Description:
* Deal with the WIN internals of a MS Word file
*/
#include "antiword.h"
/*
* bGetDocumentText - make a list of the text blocks of a Word document
*
* Return TRUE when succesful, otherwise FALSE
*/
static BOOL
bGetDocumentText(FILE *pFile, const UCHAR *aucHeader)
{
text_block_type tTextBlock;
ULONG ulBeginOfText;
ULONG ulTextLen, ulFootnoteLen;
ULONG ulHdrFtrLen, ulMacroLen, ulAnnotationLen;
UINT uiQuickSaves;
USHORT usDocStatus;
BOOL bTemplate, bFastSaved, bEncrypted, bSuccess;
fail(pFile == NULL);
fail(aucHeader == NULL);
DBG_MSG("bGetDocumentText");
/* Get the status flags from the header */
usDocStatus = usGetWord(0x0a, aucHeader);
DBG_HEX(usDocStatus);
bTemplate = (usDocStatus & BIT(0)) != 0;
DBG_MSG_C(bTemplate, "This document is a Template");
bFastSaved = (usDocStatus & BIT(2)) != 0;
uiQuickSaves = (UINT)(usDocStatus & 0x00f0) >> 4;
DBG_MSG_C(bFastSaved, "This document is Fast Saved");
DBG_DEC_C(bFastSaved, uiQuickSaves);
if (bFastSaved) {
werr(0, "Word2: fast saved documents are not supported yet");
return FALSE;
}
bEncrypted = (usDocStatus & BIT(8)) != 0;
if (bEncrypted) {
werr(0, "Encrypted documents are not supported");
return FALSE;
}
/* Get length information */
ulBeginOfText = ulGetLong(0x18, aucHeader);
DBG_HEX(ulBeginOfText);
ulTextLen = ulGetLong(0x34, aucHeader);
ulFootnoteLen = ulGetLong(0x38, aucHeader);
ulHdrFtrLen = ulGetLong(0x3c, aucHeader);
ulMacroLen = ulGetLong(0x40, aucHeader);
ulAnnotationLen = ulGetLong(0x44, aucHeader);
DBG_DEC(ulTextLen);
DBG_DEC(ulFootnoteLen);
DBG_DEC(ulHdrFtrLen);
DBG_DEC(ulMacroLen);
DBG_DEC(ulAnnotationLen);
if (bFastSaved) {
bSuccess = FALSE;
} else {
tTextBlock.ulFileOffset = ulBeginOfText;
tTextBlock.ulCharPos = ulBeginOfText;
tTextBlock.ulLength = ulTextLen +
ulFootnoteLen +
ulHdrFtrLen + ulMacroLen + ulAnnotationLen;
tTextBlock.bUsesUnicode = FALSE;
tTextBlock.usPropMod = IGNORE_PROPMOD;
bSuccess = bAdd2TextBlockList(&tTextBlock);
DBG_HEX_C(!bSuccess, tTextBlock.ulFileOffset);
DBG_HEX_C(!bSuccess, tTextBlock.ulCharPos);
DBG_DEC_C(!bSuccess, tTextBlock.ulLength);
DBG_DEC_C(!bSuccess, tTextBlock.bUsesUnicode);
DBG_DEC_C(!bSuccess, tTextBlock.usPropMod);
}
if (bSuccess) {
vSplitBlockList(pFile,
ulTextLen,
ulFootnoteLen,
ulHdrFtrLen,
ulMacroLen,
ulAnnotationLen,
0,
0,
0,
FALSE);
} else {
vDestroyTextBlockList();
werr(0, "I can't find the text of this document");
}
return bSuccess;
} /* end of bGetDocumentText */
/*
* vGetDocumentData - make a list of the data blocks of a Word document
*/
static void
vGetDocumentData(FILE *pFile, const UCHAR *aucHeader)
{
data_block_type tDataBlock;
options_type tOptions;
ULONG ulEndOfText, ulBeginCharInfo;
BOOL bFastSaved, bHasImages, bSuccess;
USHORT usDocStatus;
/* Get the options */
vGetOptions(&tOptions);
/* Get the status flags from the header */
usDocStatus = usGetWord(0x0a, aucHeader);
DBG_HEX(usDocStatus);
bFastSaved = (usDocStatus & BIT(2)) != 0;
bHasImages = (usDocStatus & BIT(3)) != 0;
if (!bHasImages ||
tOptions.eConversionType == conversion_text ||
tOptions.eConversionType == conversion_fmt_text ||
tOptions.eConversionType == conversion_xml ||
tOptions.eImageLevel == level_no_images) {
/*
* No images in the document or text-only output or
* no images wanted, so no data blocks will be needed
*/
vDestroyDataBlockList();
return;
}
if (bFastSaved) {
bSuccess = FALSE;
} else {
/* This datablock is too big, but it contains all images */
ulEndOfText = ulGetLong(0x1c, aucHeader);
DBG_HEX(ulEndOfText);
ulBeginCharInfo = ulGetLong(0xa0, aucHeader);
DBG_HEX(ulBeginCharInfo);
if (ulBeginCharInfo > ulEndOfText) {
tDataBlock.ulFileOffset = ulEndOfText;
tDataBlock.ulDataPos = ulEndOfText;
tDataBlock.ulLength = ulBeginCharInfo - ulEndOfText;
bSuccess = bAdd2DataBlockList(&tDataBlock);
DBG_HEX_C(!bSuccess, tDataBlock.ulFileOffset);
DBG_HEX_C(!bSuccess, tDataBlock.ulDataPos);
DBG_DEC_C(!bSuccess, tDataBlock.ulLength);
} else {
bSuccess = ulBeginCharInfo == ulEndOfText;
}
}
if (!bSuccess) {
vDestroyDataBlockList();
werr(0, "I can't find the data of this document");
}
} /* end of vGetDocumentData */
/*
* iInitDocumentWIN - initialize an WIN document
*
* Returns the version of Word that made the document or -1
*/
int
iInitDocumentWIN(FILE *pFile, long lFilesize)
{
int iWordVersion;
BOOL bSuccess;
USHORT usIdent;
UCHAR aucHeader[384];
fail(pFile == NULL);
if (lFilesize < 384) {
return -1;
}
/* Read the headerblock */
if (!bReadBytes(aucHeader, 384, 0x00, pFile)) {
return -1;
}
/* Get the "magic number" from the header */
usIdent = usGetWord(0x00, aucHeader);
DBG_HEX(usIdent);
fail(usIdent != 0xa59b && /* WinWord 1.x */
usIdent != 0xa5db); /* WinWord 2.0 */
iWordVersion = iGetVersionNumber(aucHeader);
if (iWordVersion != 1 && iWordVersion != 2) {
werr(0, "This file is not from ''Win Word 1 or 2'.");
return -1;
}
bSuccess = bGetDocumentText(pFile, aucHeader);
if (bSuccess) {
vGetDocumentData(pFile, aucHeader);
vGetPropertyInfo(pFile, NULL,
NULL, 0, NULL, 0,
aucHeader, iWordVersion);
vSetDefaultTabWidth(pFile, NULL,
NULL, 0, NULL, 0,
aucHeader, iWordVersion);
vGetNotesInfo(pFile, NULL,
NULL, 0, NULL, 0,
aucHeader, iWordVersion);
}
return bSuccess ? iWordVersion : -1;
} /* end of iInitDocumentWIN */

136
src/xmalloc.c Normal file
View File

@@ -0,0 +1,136 @@
/*
* xmalloc.c
* Copyright (C) 1998-2005 A.J. van Os
*
* Description:
* Extended malloc and friends
*/
#include <stdlib.h>
#include <string.h>
#include "antiword.h"
static char *szMessage =
"Memory allocation failed, unable to continue";
#if defined(__dos) && !defined(__DJGPP__)
static char *szDosMessage =
"DOS can't allocate this kind of memory, unable to continue";
#endif /* __dos && !__DJGPP__ */
/*
* xmalloc - Allocates dynamic memory
*
* See malloc(3), but unlike malloc(3) xmalloc does not return in case
* of error.
*/
void *
xmalloc(size_t tSize)
{
void *pvTmp;
TRACE_MSG("xmalloc");
if (tSize == 0) {
tSize = 1;
}
pvTmp = malloc(tSize);
if (pvTmp == NULL) {
DBG_MSG("xmalloc returned NULL");
DBG_DEC(tSize);
werr(1, szMessage);
}
return pvTmp;
} /* end of xmalloc */
/*
* xcalloc - Allocates and zeros dynamic memory
*
* See calloc(3), but unlike calloc(3) xcalloc does not return in case of error
*/
void *
xcalloc(size_t tNmemb, size_t tSize)
{
void *pvTmp;
TRACE_MSG("xcalloc");
#if defined(__dos) && !defined(__DJGPP__)
if ((ULONG)tNmemb * (ULONG)tSize > 0xffffUL) {
DBG_DEC((ULONG)tNmemb * (ULONG)tSize);
werr(1, szDosMessage);
}
#endif /* __dos && !__DJGPP__ */
if (tNmemb == 0 || tSize == 0) {
tNmemb = 1;
tSize = 1;
}
pvTmp = calloc(tNmemb, tSize);
if (pvTmp == NULL) {
DBG_MSG("xcalloc returned NULL");
werr(1, szMessage);
}
return pvTmp;
} /* end of xcalloc */
/*
* xrealloc - Changes the size of a memory object
*
* See realloc(3), but unlike realloc(3) xrealloc does not return in case
* of error.
*/
void *
xrealloc(void *pvArg, size_t tSize)
{
void *pvTmp;
TRACE_MSG("xrealloc");
pvTmp = realloc(pvArg, tSize);
if (pvTmp == NULL) {
DBG_MSG("realloc returned NULL");
werr(1, szMessage);
}
return pvTmp;
} /* end of xrealloc */
/*
* xstrdup - Duplicate a string
*
* See strdup(3), but unlike strdup(3) xstrdup does not return in case
* of error.
*
* NOTE:
* Does not use strdup(3), because some systems don't have it.
*/
char *
xstrdup(const char *szArg)
{
char *szTmp;
TRACE_MSG("xstrdup");
szTmp = xmalloc(strlen(szArg) + 1);
strcpy(szTmp, szArg);
return szTmp;
} /* end of xstrdup */
/*
* xfree - Deallocates dynamic memory
*
* See free(3).
*
* returns NULL;
* This makes p=xfree(p) possible, free memory and overwrite the pointer to it.
*/
void *
xfree(void *pvArg)
{
TRACE_MSG("xfree");
if (pvArg != NULL) {
free(pvArg);
}
return NULL;
} /* end of xfree */

1438
src/xml.c Normal file

File diff suppressed because it is too large Load Diff