mirror of
https://github.com/simon987/antiword.git
synced 2025-12-16 05:19:02 +00:00
cleanup, convert to cmake project
This commit is contained in:
735
src/antiword.h
Normal file
735
src/antiword.h
Normal 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
154
src/asc85enc.c
Normal 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
823
src/blocklist.c
Normal 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
720
src/chartrans.c
Normal 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
374
src/datalist.c
Normal 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
117
src/debug.h
Normal 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
114
src/depot.c
Normal 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
509
src/dib2eps.c
Normal 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
597
src/dib2sprt.c
Normal 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
75
src/doclist.c
Normal 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
1047
src/draw.c
Normal file
File diff suppressed because it is too large
Load Diff
46
src/draw.h
Normal file
46
src/draw.h
Normal 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
422
src/drawfile.c
Normal 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
433
src/drawfile.h
Normal 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
26
src/fail.c
Normal 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
22
src/fail.h
Normal 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
154
src/finddata.c
Normal 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
289
src/findtext.c
Normal 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
167
src/fmt_text.c
Normal 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
2251
src/fontinfo.h
Normal file
File diff suppressed because it is too large
Load Diff
173
src/fontlist.c
Normal file
173
src/fontlist.c
Normal 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
1018
src/fonts.c
Normal file
File diff suppressed because it is too large
Load Diff
251
src/fonts_r.c
Normal file
251
src/fonts_r.c
Normal 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
305
src/fonts_u.c
Normal 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
371
src/hdrftrlist.c
Normal 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
96
src/icons.c
Normal 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
1044
src/imgexam.c
Normal file
File diff suppressed because it is too large
Load Diff
71
src/imgtrans.c
Normal file
71
src/imgtrans.c
Normal 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
74
src/jpeg2eps.c
Normal 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
97
src/jpeg2sprt.c
Normal 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
330
src/listlist.c
Normal 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
520
src/main_ros.c
Normal 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
321
src/main_u.c
Normal 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
894
src/misc.c
Normal 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
876
src/notes.c
Normal 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
950
src/options.c
Normal 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
768
src/out2window.c
Normal 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
538
src/output.c
Normal 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 */
|
||||
109
src/pictlist.c
Normal file
109
src/pictlist.c
Normal 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
191
src/png2eps.c
Normal 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
26
src/png2sprt.c
Normal 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
1171
src/postscript.c
Normal file
File diff suppressed because it is too large
Load Diff
489
src/prop0.c
Normal file
489
src/prop0.c
Normal 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
1067
src/prop2.c
Normal file
File diff suppressed because it is too large
Load Diff
1141
src/prop6.c
Normal file
1141
src/prop6.c
Normal file
File diff suppressed because it is too large
Load Diff
1496
src/prop8.c
Normal file
1496
src/prop8.c
Normal file
File diff suppressed because it is too large
Load Diff
198
src/properties.c
Normal file
198
src/properties.c
Normal 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
110
src/propmod.c
Normal 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
251
src/riscos.c
Normal 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
117
src/rowlist.c
Normal 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
387
src/saveas.c
Normal 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
165
src/sectlist.c
Normal 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
145
src/startup.c
Normal 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
487
src/stylelist.c
Normal 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
838
src/stylesheet.c
Normal 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
888
src/summary.c
Normal 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
212
src/tabstop.c
Normal 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
182
src/text.c
Normal 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
45
src/unix.c
Normal 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
260
src/utf8.c
Normal 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
37
src/version.h
Normal 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
1505
src/word2text.c
Normal file
File diff suppressed because it is too large
Load Diff
321
src/wordconst.h
Normal file
321
src/wordconst.h
Normal 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
110
src/worddos.c
Normal 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
359
src/wordlib.c
Normal 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
108
src/wordmac.c
Normal 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
804
src/wordole.c
Normal 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
317
src/wordtypes.h
Normal 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
209
src/wordwin.c
Normal 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
136
src/xmalloc.c
Normal 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 */
|
||||
Reference in New Issue
Block a user