mirror of
https://github.com/simon987/antiword.git
synced 2025-04-10 13:06:41 +00:00
1048 lines
26 KiB
C
1048 lines
26 KiB
C
/*
|
|
* draw.c
|
|
* Copyright (C) 1998-2005 A.J. van Os; Released under GPL
|
|
*
|
|
* Description:
|
|
* Functions to deal with the Draw format
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include "DeskLib:KeyCodes.h"
|
|
#include "DeskLib:Error.h"
|
|
#include "DeskLib:Menu.h"
|
|
#include "DeskLib:Template.h"
|
|
#include "DeskLib:Window.h"
|
|
#include "DeskLib:EventMsg.h"
|
|
#include "flexlib:flex.h"
|
|
#include "drawfile.h"
|
|
#include "antiword.h"
|
|
|
|
/* The work area must be a little bit larger than the diagram */
|
|
#define WORKAREA_EXTENSION 5
|
|
/* Diagram memory */
|
|
#define INITIAL_SIZE 32768 /* 32k */
|
|
#define EXTENSION_SIZE 4096 /* 4k */
|
|
/* Main window title */
|
|
#define WINDOW_TITLE_LEN 28
|
|
#define FILENAME_TITLE_LEN (WINDOW_TITLE_LEN - 10)
|
|
|
|
|
|
#if !defined(__GNUC__)
|
|
int
|
|
flex_alloc(flex_ptr anchor, int n)
|
|
{
|
|
void *pvTmp;
|
|
|
|
TRACE_MSG("flex_alloc");
|
|
|
|
if (anchor == NULL || n < 0) {
|
|
return 0;
|
|
}
|
|
if (n == 0) {
|
|
n = 1;
|
|
}
|
|
pvTmp = malloc(n);
|
|
if (pvTmp == NULL) {
|
|
return 0;
|
|
}
|
|
*anchor = pvTmp;
|
|
return 1;
|
|
} /* end of flex_alloc */
|
|
|
|
void
|
|
flex_free(flex_ptr anchor)
|
|
{
|
|
TRACE_MSG("flex_free");
|
|
|
|
if (anchor == NULL || *anchor == NULL) {
|
|
return;
|
|
}
|
|
free(*anchor);
|
|
*anchor = NULL;
|
|
} /* end of flex_free */
|
|
|
|
int
|
|
flex_extend(flex_ptr anchor, int newsize)
|
|
{
|
|
void *pvTmp;
|
|
|
|
TRACE_MSG("flex_extend");
|
|
|
|
if (anchor == NULL || newsize < 0) {
|
|
return 0;
|
|
}
|
|
if (newsize == 0) {
|
|
newsize = 1;
|
|
}
|
|
pvTmp = realloc(*anchor, newsize);
|
|
if (pvTmp == NULL) {
|
|
return 0;
|
|
}
|
|
*anchor = pvTmp;
|
|
return 1;
|
|
} /* end of flex_extend */
|
|
#endif /* !__GNUC__ */
|
|
|
|
/*
|
|
* vCreateMainWindow - create the Main window
|
|
*
|
|
* remark: does not return if the Main window can't be created
|
|
*/
|
|
static window_handle
|
|
tCreateMainWindow(void)
|
|
{
|
|
window_handle tMainWindow;
|
|
|
|
TRACE_MSG("tCreateMainWindow");
|
|
|
|
tMainWindow = Window_Create("MainWindow", template_TITLEMIN);
|
|
if (tMainWindow == 0) {
|
|
werr(1, "I can't find the 'MainWindow' template");
|
|
}
|
|
return tMainWindow;
|
|
} /* end of tCreateMainWindow */
|
|
|
|
/*
|
|
* vCreateScaleWindow - create the Scale view window
|
|
*
|
|
* remark: does not return if the Scale view window can't be created
|
|
*/
|
|
static window_handle
|
|
tCreateScaleWindow(void)
|
|
{
|
|
window_handle tScaleWindow;
|
|
|
|
TRACE_MSG("tCreateScaleWindow");
|
|
|
|
tScaleWindow = Window_Create("ScaleView", template_TITLEMIN);
|
|
if (tScaleWindow == 0) {
|
|
werr(1, "I can't find the 'ScaleView' template");
|
|
}
|
|
return tScaleWindow;
|
|
} /* end of tCreateScaleWindow */
|
|
|
|
/*
|
|
* 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;
|
|
options_type tOptions;
|
|
window_handle tMainWindow, tScaleWindow;
|
|
wimp_box tBox;
|
|
|
|
TRACE_MSG("pCreateDiagram");
|
|
|
|
fail(szTask == NULL || szTask[0] == '\0');
|
|
|
|
/* Create the main window */
|
|
tMainWindow = tCreateMainWindow();
|
|
|
|
/* Create the scale view window */
|
|
tScaleWindow = tCreateScaleWindow();
|
|
|
|
/* Get the necessary memory */
|
|
pDiag = xmalloc(sizeof(diagram_type));
|
|
if (flex_alloc((flex_ptr)&pDiag->tInfo.data, INITIAL_SIZE) != 1) {
|
|
werr(1, "Memory allocation failed, unable to continue");
|
|
}
|
|
|
|
/* Initialize the diagram */
|
|
vGetOptions(&tOptions);
|
|
pDiag->tMainWindow = tMainWindow;
|
|
pDiag->tScaleWindow = tScaleWindow;
|
|
pDiag->iScaleFactorCurr = tOptions.iScaleFactor;
|
|
pDiag->iScaleFactorTemp = tOptions.iScaleFactor;
|
|
pDiag->tMemorySize = INITIAL_SIZE;
|
|
tBox.min.x = 0;
|
|
tBox.min.y = -(Drawfile_ScreenToDraw(32 + 3) * 8 + 1);
|
|
tBox.max.x = Drawfile_ScreenToDraw(16) * MIN_SCREEN_WIDTH + 1;
|
|
tBox.max.y = 0;
|
|
Error_CheckFatal(Drawfile_CreateDiagram(&pDiag->tInfo,
|
|
pDiag->tMemorySize, szTask, tBox));
|
|
DBG_DEC(pDiag->tInfo.length);
|
|
pDiag->lXleft = 0;
|
|
pDiag->lYtop = 0;
|
|
strncpy(pDiag->szFilename,
|
|
szBasename(szFilename), sizeof(pDiag->szFilename) - 1);
|
|
pDiag->szFilename[sizeof(pDiag->szFilename) - 1] = '\0';
|
|
/* Return success */
|
|
return pDiag;
|
|
} /* end of pCreateDiagram */
|
|
|
|
/*
|
|
* bDestroyDiagram - remove a diagram by freeing the memory it uses
|
|
*/
|
|
BOOL
|
|
bDestroyDiagram(event_pollblock *pEvent, void *pvReference)
|
|
{
|
|
diagram_type *pDiag;
|
|
window_handle tWindow;
|
|
|
|
TRACE_MSG("bDestroyDiagram");
|
|
|
|
fail(pEvent == NULL);
|
|
fail(pvReference == NULL);
|
|
|
|
if (pEvent == NULL || pvReference == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
pDiag = (diagram_type *)pvReference;
|
|
|
|
switch (pEvent->type) {
|
|
case event_CLOSE:
|
|
tWindow = pEvent->data.openblock.window;
|
|
break;
|
|
case event_KEY:
|
|
tWindow = pEvent->data.key.caret.window;
|
|
break;
|
|
default:
|
|
DBG_DEC(pEvent->type);
|
|
return FALSE;
|
|
}
|
|
if (tWindow != pDiag->tMainWindow) {
|
|
return FALSE;
|
|
}
|
|
|
|
/* Delete the main window */
|
|
Window_Delete(pDiag->tMainWindow);
|
|
pDiag->tMainWindow = 0;
|
|
|
|
/* Delete the scale window */
|
|
Window_Delete(pDiag->tScaleWindow);
|
|
pDiag->tScaleWindow = 0;
|
|
|
|
#if defined(__GNUC__)
|
|
/*
|
|
* Remove all references to the diagram that will be free-ed
|
|
* by undoing the EventMsg_Claim's from within the Menu_Warn's
|
|
*/
|
|
while (EventMsg_ReleaseSpecific(message_MENUWARNING, window_ANY,
|
|
bSaveTextfile, pDiag))
|
|
; /* EMPTY */
|
|
while (EventMsg_ReleaseSpecific(message_MENUWARNING, window_ANY,
|
|
bSaveDrawfile, pDiag))
|
|
; /* EMPTY */
|
|
while (EventMsg_ReleaseSpecific(message_MENUWARNING, window_ANY,
|
|
bScaleOpenAction, pDiag))
|
|
; /* EMPTY */
|
|
#endif /* __GNUC__ */
|
|
|
|
/* Free the memory */
|
|
if (pDiag->tInfo.data != NULL && pDiag->tMemorySize != 0) {
|
|
flex_free((flex_ptr)&pDiag->tInfo.data);
|
|
}
|
|
/* Just to be on the save side */
|
|
pDiag->tInfo.data = NULL;
|
|
pDiag->tInfo.length = 0;
|
|
pDiag->tMemorySize = 0;
|
|
|
|
/* Destroy the diagram itself */
|
|
pDiag = xfree(pDiag);
|
|
return TRUE;
|
|
} /* end of bDestroyDiagram */
|
|
|
|
/*
|
|
* vExtendDiagramSize - make sure the diagram is big enough
|
|
*/
|
|
static void
|
|
vExtendDiagramSize(diagram_type *pDiag, size_t tSize)
|
|
{
|
|
TRACE_MSG("vExtendDiagramSize");
|
|
|
|
fail(pDiag == NULL || tSize % 4 != 0);
|
|
|
|
while (pDiag->tInfo.length + tSize > pDiag->tMemorySize) {
|
|
if (flex_extend((flex_ptr)&pDiag->tInfo.data,
|
|
pDiag->tMemorySize + EXTENSION_SIZE) != 1) {
|
|
werr(1, "Memory extend failed, unable to continue");
|
|
}
|
|
pDiag->tMemorySize += EXTENSION_SIZE;
|
|
NO_DBG_DEC(pDiag->tMemorySize);
|
|
}
|
|
TRACE_MSG("end of vExtendDiagramSize");
|
|
} /* end of vExtendDiagramSize */
|
|
|
|
/*
|
|
* vPrologue2 - prologue part 2; add a font list to a diagram
|
|
*/
|
|
void
|
|
vPrologue2(diagram_type *pDiag, int iWordVersion)
|
|
{
|
|
drawfile_object *pNew;
|
|
const font_table_type *pTmp;
|
|
char *pcTmp;
|
|
size_t tRealSize, tSize;
|
|
int iCount;
|
|
|
|
TRACE_MSG("vPrologue2");
|
|
|
|
fail(pDiag == NULL);
|
|
|
|
if (tGetFontTableLength() == 0) {
|
|
return;
|
|
}
|
|
tRealSize = offsetof(drawfile_object, data);
|
|
pTmp = NULL;
|
|
while ((pTmp = pGetNextFontTableRecord(pTmp)) != NULL) {
|
|
tRealSize += 2 + strlen(pTmp->szOurFontname);
|
|
}
|
|
DBG_DEC(tRealSize);
|
|
tSize = ROUND4(tRealSize);
|
|
vExtendDiagramSize(pDiag, tSize);
|
|
pNew = xmalloc(tSize);
|
|
memset(pNew, 0, tSize);
|
|
pNew->type = drawfile_TYPE_FONT_TABLE;
|
|
pNew->size = tSize;
|
|
pcTmp = (char *)&pNew->data.font_table.font_def[0].font_ref;
|
|
iCount = 0;
|
|
pTmp = NULL;
|
|
while ((pTmp = pGetNextFontTableRecord(pTmp)) != NULL) {
|
|
*pcTmp = ++iCount;
|
|
pcTmp++;
|
|
strcpy(pcTmp, pTmp->szOurFontname);
|
|
pcTmp += 1 + strlen(pTmp->szOurFontname);
|
|
}
|
|
Error_CheckFatal(Drawfile_AppendObject(&pDiag->tInfo,
|
|
pDiag->tMemorySize, pNew, TRUE));
|
|
pNew = xfree(pNew);
|
|
} /* end of vPrologue2 */
|
|
|
|
/*
|
|
* 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)
|
|
{
|
|
drawfile_object *pNew;
|
|
long lSizeX, lSizeY, lOffset, l20, lYMove;
|
|
size_t tRealSize, tSize;
|
|
|
|
TRACE_MSG("vSubstring2Diagram");
|
|
|
|
fail(pDiag == NULL || szString == NULL);
|
|
fail(pDiag->lXleft < 0);
|
|
fail(tStringLength != strlen(szString));
|
|
fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
|
|
fail(usMaxFontSize < MIN_FONT_SIZE || usMaxFontSize > MAX_FONT_SIZE);
|
|
fail(usFontSize > usMaxFontSize);
|
|
|
|
if (szString[0] == '\0' || tStringLength == 0) {
|
|
return;
|
|
}
|
|
|
|
if (tFontRef == 0) {
|
|
lOffset = Drawfile_ScreenToDraw(2);
|
|
l20 = Drawfile_ScreenToDraw(32 + 3);
|
|
lSizeX = Drawfile_ScreenToDraw(16);
|
|
lSizeY = Drawfile_ScreenToDraw(32);
|
|
} else {
|
|
lOffset = lToBaseLine(usMaxFontSize);
|
|
l20 = lWord2DrawUnits20(usMaxFontSize);
|
|
lSizeX = lWord2DrawUnits00(usFontSize);
|
|
lSizeY = lWord2DrawUnits00(usFontSize);
|
|
}
|
|
|
|
lYMove = 0;
|
|
|
|
/* Up for superscript */
|
|
if (bIsSuperscript(usFontstyle)) {
|
|
lYMove = lMilliPoints2DrawUnits((((long)usFontSize + 1) / 2) * 375);
|
|
}
|
|
/* Down for subscript */
|
|
if (bIsSubscript(usFontstyle)) {
|
|
lYMove = -lMilliPoints2DrawUnits((long)usFontSize * 125);
|
|
}
|
|
|
|
tRealSize = offsetof(drawfile_object, data);
|
|
tRealSize += sizeof(drawfile_text) + tStringLength;
|
|
tSize = ROUND4(tRealSize);
|
|
vExtendDiagramSize(pDiag, tSize);
|
|
pNew = xmalloc(tSize);
|
|
memset(pNew, 0, tSize);
|
|
pNew->type = drawfile_TYPE_TEXT;
|
|
pNew->size = tSize;
|
|
pNew->data.text.bbox.min.x = (int)pDiag->lXleft;
|
|
pNew->data.text.bbox.min.y = (int)(pDiag->lYtop + lYMove);
|
|
pNew->data.text.bbox.max.x = (int)(pDiag->lXleft + lStringWidth);
|
|
pNew->data.text.bbox.max.y = (int)(pDiag->lYtop + l20 + lYMove);
|
|
pNew->data.text.fill.value = (int)ulColor2Color(ucFontColor);
|
|
pNew->data.text.bg_hint.value = 0xffffff00; /* White */
|
|
pNew->data.text.style.font_ref = tFontRef;
|
|
pNew->data.text.style.reserved[0] = 0;
|
|
pNew->data.text.style.reserved[1] = 0;
|
|
pNew->data.text.style.reserved[2] = 0;
|
|
pNew->data.text.xsize = (int)lSizeX;
|
|
pNew->data.text.ysize = (int)lSizeY;
|
|
pNew->data.text.base.x = (int)pDiag->lXleft;
|
|
pNew->data.text.base.y = (int)(pDiag->lYtop + lOffset + lYMove);
|
|
strncpy(pNew->data.text.text, szString, tStringLength);
|
|
pNew->data.text.text[tStringLength] = '\0';
|
|
Error_CheckFatal(Drawfile_AppendObject(&pDiag->tInfo,
|
|
pDiag->tMemorySize, pNew, TRUE));
|
|
pNew = xfree(pNew);
|
|
/*draw_translateText(&pDiag->tInfo);*/
|
|
pDiag->lXleft += lStringWidth;
|
|
TRACE_MSG("leaving vSubstring2Diagram");
|
|
} /* end of vSubstring2Diagram */
|
|
|
|
/*
|
|
* vImage2Diagram - put an image into a diagram
|
|
*/
|
|
void
|
|
vImage2Diagram(diagram_type *pDiag, const imagedata_type *pImg,
|
|
UCHAR *pucImage, size_t tImageSize)
|
|
{
|
|
drawfile_object *pNew;
|
|
long lWidth, lHeight;
|
|
size_t tRealSize, tSize;
|
|
|
|
TRACE_MSG("vImage2Diagram");
|
|
|
|
fail(pDiag == NULL);
|
|
fail(pImg == NULL);
|
|
fail(pDiag->lXleft < 0);
|
|
fail(pImg->eImageType != imagetype_is_dib &&
|
|
pImg->eImageType != imagetype_is_jpeg);
|
|
|
|
DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
|
|
|
|
lWidth = lPoints2DrawUnits(pImg->iHorSizeScaled);
|
|
lHeight = lPoints2DrawUnits(pImg->iVerSizeScaled);
|
|
DBG_DEC(lWidth);
|
|
DBG_DEC(lHeight);
|
|
|
|
pDiag->lYtop -= lHeight;
|
|
|
|
tRealSize = offsetof(drawfile_object, data);
|
|
switch (pImg->eImageType) {
|
|
case imagetype_is_dib:
|
|
tRealSize += sizeof(drawfile_sprite) + tImageSize;
|
|
tSize = ROUND4(tRealSize);
|
|
vExtendDiagramSize(pDiag, tSize);
|
|
pNew = xmalloc(tSize);
|
|
memset(pNew, 0, tSize);
|
|
pNew->type = drawfile_TYPE_SPRITE;
|
|
pNew->size = tSize;
|
|
pNew->data.sprite.bbox.min.x = (int)pDiag->lXleft;
|
|
pNew->data.sprite.bbox.min.y = (int)pDiag->lYtop;
|
|
pNew->data.sprite.bbox.max.x = (int)(pDiag->lXleft + lWidth);
|
|
pNew->data.sprite.bbox.max.y = (int)(pDiag->lYtop + lHeight);
|
|
memcpy(&pNew->data.sprite.header, pucImage, tImageSize);
|
|
break;
|
|
case imagetype_is_jpeg:
|
|
#if defined(DEBUG)
|
|
(void)bGetJpegInfo(pucImage, tImageSize);
|
|
#endif /* DEBUG */
|
|
tRealSize += sizeof(drawfile_jpeg) + tImageSize;
|
|
tSize = ROUND4(tRealSize);
|
|
vExtendDiagramSize(pDiag, tSize);
|
|
pNew = xmalloc(tSize);
|
|
memset(pNew, 0, tSize);
|
|
pNew->type = drawfile_TYPE_JPEG;
|
|
pNew->size = tSize;
|
|
pNew->data.jpeg.bbox.min.x = (int)pDiag->lXleft;
|
|
pNew->data.jpeg.bbox.min.y = (int)pDiag->lYtop;
|
|
pNew->data.jpeg.bbox.max.x = (int)(pDiag->lXleft + lWidth);
|
|
pNew->data.jpeg.bbox.max.y = (int)(pDiag->lYtop + lHeight);
|
|
pNew->data.jpeg.width = (int)lWidth;
|
|
pNew->data.jpeg.height = (int)lHeight;
|
|
pNew->data.jpeg.xdpi = 90;
|
|
pNew->data.jpeg.ydpi = 90;
|
|
pNew->data.jpeg.trfm.entries[0][0] = 0x10000;
|
|
pNew->data.jpeg.trfm.entries[0][1] = 0;
|
|
pNew->data.jpeg.trfm.entries[1][0] = 0;
|
|
pNew->data.jpeg.trfm.entries[1][1] = 0x10000;
|
|
pNew->data.jpeg.trfm.entries[2][0] = (int)pDiag->lXleft;
|
|
pNew->data.jpeg.trfm.entries[2][1] = (int)pDiag->lYtop;
|
|
pNew->data.jpeg.len = tImageSize;
|
|
memcpy(pNew->data.jpeg.data, pucImage, tImageSize);
|
|
break;
|
|
default:
|
|
DBG_DEC(pImg->eImageType);
|
|
pNew = NULL;
|
|
break;
|
|
}
|
|
|
|
Error_CheckFatal(Drawfile_AppendObject(&pDiag->tInfo,
|
|
pDiag->tMemorySize, pNew, TRUE));
|
|
pNew = xfree(pNew);
|
|
pDiag->lXleft = 0;
|
|
} /* end of vImage2Diagram */
|
|
|
|
/*
|
|
* bAddDummyImage - add a dummy image
|
|
*
|
|
* return TRUE when successful, otherwise FALSE
|
|
*/
|
|
BOOL
|
|
bAddDummyImage(diagram_type *pDiag, const imagedata_type *pImg)
|
|
{
|
|
drawfile_object *pNew;
|
|
int *piTmp;
|
|
long lWidth, lHeight;
|
|
size_t tRealSize, tSize;
|
|
|
|
TRACE_MSG("bAddDummyImage");
|
|
|
|
fail(pDiag == NULL);
|
|
fail(pImg == NULL);
|
|
fail(pDiag->lXleft < 0);
|
|
|
|
if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
|
|
|
|
lWidth = lPoints2DrawUnits(pImg->iHorSizeScaled);
|
|
lHeight = lPoints2DrawUnits(pImg->iVerSizeScaled);
|
|
|
|
pDiag->lYtop -= lHeight;
|
|
|
|
tRealSize = offsetof(drawfile_object, data);
|
|
tRealSize += sizeof(drawfile_path) + (14 - 1) * sizeof(int);
|
|
tSize = ROUND4(tRealSize);
|
|
vExtendDiagramSize(pDiag, tSize);
|
|
pNew = xmalloc(tSize);
|
|
memset(pNew, 0, tSize);
|
|
pNew->type = drawfile_TYPE_PATH;
|
|
pNew->size = tSize;
|
|
pNew->data.path.bbox.min.x = (int)pDiag->lXleft;
|
|
pNew->data.path.bbox.min.y = (int)pDiag->lYtop;
|
|
pNew->data.path.bbox.max.x = (int)(pDiag->lXleft + lWidth);
|
|
pNew->data.path.bbox.max.y = (int)(pDiag->lYtop + lHeight);
|
|
pNew->data.path.fill.value = -1;
|
|
pNew->data.path.outline.value = 0x4d4d4d00; /* Gray 70 percent */
|
|
pNew->data.path.width = (int)lMilliPoints2DrawUnits(500);
|
|
pNew->data.path.style.flags = 0;
|
|
pNew->data.path.style.reserved = 0;
|
|
pNew->data.path.style.cap_width = 0;
|
|
pNew->data.path.style.cap_length = 0;
|
|
piTmp = pNew->data.path.path;
|
|
*piTmp++ = drawfile_PATH_MOVE_TO;
|
|
*piTmp++ = pNew->data.path.bbox.min.x;
|
|
*piTmp++ = pNew->data.path.bbox.min.y;
|
|
*piTmp++ = drawfile_PATH_LINE_TO;
|
|
*piTmp++ = pNew->data.path.bbox.min.x;
|
|
*piTmp++ = pNew->data.path.bbox.max.y;
|
|
*piTmp++ = drawfile_PATH_LINE_TO;
|
|
*piTmp++ = pNew->data.path.bbox.max.x;
|
|
*piTmp++ = pNew->data.path.bbox.max.y;
|
|
*piTmp++ = drawfile_PATH_LINE_TO;
|
|
*piTmp++ = pNew->data.path.bbox.max.x;
|
|
*piTmp++ = pNew->data.path.bbox.min.y;
|
|
*piTmp++ = drawfile_PATH_CLOSE_LINE;
|
|
*piTmp++ = drawfile_PATH_END_PATH;
|
|
|
|
Error_CheckFatal(Drawfile_AppendObject(&pDiag->tInfo,
|
|
pDiag->tMemorySize, pNew, TRUE));
|
|
pNew = xfree(pNew);
|
|
pDiag->lXleft = 0;
|
|
return TRUE;
|
|
} /* end of bAddDummyImage */
|
|
|
|
/*
|
|
* vMove2NextLine - move to the next line
|
|
*/
|
|
void
|
|
vMove2NextLine(diagram_type *pDiag, drawfile_fontref tFontRef,
|
|
USHORT usFontSize)
|
|
{
|
|
long l20;
|
|
|
|
TRACE_MSG("vMove2NextLine");
|
|
|
|
fail(pDiag == NULL);
|
|
fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
|
|
|
|
if (tFontRef == 0) {
|
|
l20 = Drawfile_ScreenToDraw(32 + 3);
|
|
} else {
|
|
l20 = lWord2DrawUnits20(usFontSize);
|
|
}
|
|
pDiag->lYtop -= l20;
|
|
} /* end of vMove2NextLine */
|
|
|
|
/*
|
|
* Create an start of paragraph (Phase 1)
|
|
*/
|
|
void
|
|
vStartOfParagraph1(diagram_type *pDiag, long lBeforeIndentation)
|
|
{
|
|
TRACE_MSG("vStartOfParagraph1");
|
|
|
|
fail(pDiag == NULL);
|
|
fail(lBeforeIndentation < 0);
|
|
|
|
pDiag->lXleft = 0;
|
|
pDiag->lYtop -= lMilliPoints2DrawUnits(lBeforeIndentation);
|
|
} /* end of vStartOfParagraph1 */
|
|
|
|
/*
|
|
* Create an start of paragraph (Phase 2)
|
|
* DUMMY function
|
|
*/
|
|
void
|
|
vStartOfParagraph2(diagram_type *pDiag)
|
|
{
|
|
TRACE_MSG("vStartOfParagraph2");
|
|
} /* end of vStartOfParagraph2 */
|
|
|
|
/*
|
|
* Create an end of paragraph
|
|
*/
|
|
void
|
|
vEndOfParagraph(diagram_type *pDiag,
|
|
drawfile_fontref tFontRef, USHORT usFontSize, long lAfterIndentation)
|
|
{
|
|
TRACE_MSG("vEndOfParagraph");
|
|
|
|
fail(pDiag == NULL);
|
|
fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
|
|
fail(lAfterIndentation < 0);
|
|
|
|
pDiag->lXleft = 0;
|
|
pDiag->lYtop -= lMilliPoints2DrawUnits(lAfterIndentation);
|
|
} /* end of vEndOfParagraph */
|
|
|
|
/*
|
|
* Create an end of page
|
|
*/
|
|
void
|
|
vEndOfPage(diagram_type *pDiag, long lAfterIndentation, BOOL bNewSection)
|
|
{
|
|
TRACE_MSG("vEndOfPage");
|
|
|
|
fail(pDiag == NULL);
|
|
fail(lAfterIndentation < 0);
|
|
|
|
pDiag->lXleft = 0;
|
|
pDiag->lYtop -= lMilliPoints2DrawUnits(lAfterIndentation);
|
|
} /* end of vEndOfPage */
|
|
|
|
/*
|
|
* vSetHeaders - set the headers
|
|
* DUMMY function
|
|
*/
|
|
void
|
|
vSetHeaders(diagram_type *pDiag, USHORT usIstd)
|
|
{
|
|
TRACE_MSG("vSetHeaders");
|
|
} /* end of vSetHeaders */
|
|
|
|
/*
|
|
* Create a start of list
|
|
* DUMMY function
|
|
*/
|
|
void
|
|
vStartOfList(diagram_type *pDiag, UCHAR ucNFC, BOOL bIsEndOfTable)
|
|
{
|
|
TRACE_MSG("vStartOfList");
|
|
} /* end of vStartOfList */
|
|
|
|
/*
|
|
* Create an end of list
|
|
* DUMMY function
|
|
*/
|
|
void
|
|
vEndOfList(diagram_type *pDiag)
|
|
{
|
|
TRACE_MSG("vEndOfList");
|
|
} /* end of vEndOfList */
|
|
|
|
/*
|
|
* Create a start of a list item
|
|
* DUMMY function
|
|
*/
|
|
void
|
|
vStartOfListItem(diagram_type *pDiag, BOOL bNoMarks)
|
|
{
|
|
TRACE_MSG("vStartOfListItem");
|
|
} /* end of vStartOfListItem */
|
|
|
|
/*
|
|
* Create an end of a table
|
|
* DUMMY function
|
|
*/
|
|
void
|
|
vEndOfTable(diagram_type *pDiag)
|
|
{
|
|
TRACE_MSG("vEndOfTable");
|
|
} /* end of vEndTable */
|
|
|
|
/*
|
|
* Add a table row
|
|
* DUMMY function
|
|
*
|
|
* Returns TRUE when conversion type is XML
|
|
*/
|
|
BOOL
|
|
bAddTableRow(diagram_type *pDiag, char **aszColTxt,
|
|
int iNbrOfColumns, const short *asColumnWidth, UCHAR ucBorderInfo)
|
|
{
|
|
TRACE_MSG("bAddTableRow");
|
|
|
|
return FALSE;
|
|
} /* end of bAddTableRow */
|
|
|
|
/*
|
|
* vForceRedraw - force a redraw of the main window
|
|
*/
|
|
static void
|
|
vForceRedraw(diagram_type *pDiag)
|
|
{
|
|
window_state tWindowState;
|
|
window_redrawblock tRedraw;
|
|
int x0, y0, x1, y1;
|
|
|
|
TRACE_MSG("vForceRedraw");
|
|
|
|
fail(pDiag == NULL);
|
|
|
|
DBG_DEC(pDiag->iScaleFactorCurr);
|
|
|
|
/* Read the size of the current diagram */
|
|
Drawfile_QueryBox(&pDiag->tInfo, &tRedraw.rect, TRUE);
|
|
/* Adjust the size of the work area */
|
|
x0 = tRedraw.rect.min.x * pDiag->iScaleFactorCurr / 100 - 1;
|
|
y0 = tRedraw.rect.min.y * pDiag->iScaleFactorCurr / 100 - 1;
|
|
x1 = tRedraw.rect.max.x * pDiag->iScaleFactorCurr / 100 + 1;
|
|
y1 = tRedraw.rect.max.y * pDiag->iScaleFactorCurr / 100 + 1;
|
|
/* Work area extension */
|
|
x0 -= WORKAREA_EXTENSION;
|
|
y0 -= WORKAREA_EXTENSION;
|
|
x1 += WORKAREA_EXTENSION;
|
|
y1 += WORKAREA_EXTENSION;
|
|
Window_SetExtent(pDiag->tMainWindow, x0, y0, x1, y1);
|
|
/* Widen the box slightly to be sure all the edges are drawn */
|
|
x0 -= 5;
|
|
y0 -= 5;
|
|
x1 += 5;
|
|
y1 += 5;
|
|
/* Force the redraw */
|
|
Window_ForceRedraw(pDiag->tMainWindow, x0, y0, x1, y1);
|
|
/* Reopen the window to show the correct size */
|
|
Error_CheckFatal(Wimp_GetWindowState(pDiag->tMainWindow, &tWindowState));
|
|
tWindowState.openblock.behind = -1;
|
|
Error_CheckFatal(Wimp_OpenWindow(&tWindowState.openblock));
|
|
} /* end of vForceRedraw */
|
|
|
|
/*
|
|
* vShowDiagram - put the diagram on the screen
|
|
*/
|
|
void
|
|
vShowDiagram(diagram_type *pDiag)
|
|
{
|
|
wimp_box tRect;
|
|
int x0, y0, x1, y1;
|
|
|
|
TRACE_MSG("vShowDiagram");
|
|
|
|
fail(pDiag == NULL);
|
|
|
|
Window_Show(pDiag->tMainWindow, open_NEARLAST);
|
|
Drawfile_QueryBox(&pDiag->tInfo, &tRect, TRUE);
|
|
/* Work area extension */
|
|
x0 = tRect.min.x - WORKAREA_EXTENSION;
|
|
y0 = tRect.min.y - WORKAREA_EXTENSION;
|
|
x1 = tRect.max.x + WORKAREA_EXTENSION;
|
|
y1 = tRect.max.y + WORKAREA_EXTENSION;
|
|
Window_SetExtent(pDiag->tMainWindow, x0, y0, x1, y1);
|
|
vForceRedraw(pDiag);
|
|
} /* end of vShowDiagram */
|
|
|
|
/*
|
|
* vMainButtonClick - handle mouse buttons clicks for the main screen
|
|
*/
|
|
void
|
|
vMainButtonClick(mouse_block *pMouse)
|
|
{
|
|
caret_block tCaret;
|
|
window_state ws;
|
|
|
|
TRACE_MSG("vMainButtonClick");
|
|
|
|
fail(pMouse == NULL);
|
|
|
|
DBG_DEC(pMouse->button.data.select);
|
|
DBG_DEC(pMouse->button.data.adjust);
|
|
DBG_DEC(pMouse->window);
|
|
DBG_DEC(pMouse->icon);
|
|
|
|
if (pMouse->window >= 0 &&
|
|
pMouse->icon == -1 &&
|
|
(pMouse->button.data.select || pMouse->button.data.adjust)) {
|
|
/* Get the input focus */
|
|
Error_CheckFatal(Wimp_GetWindowState(pMouse->window, &ws));
|
|
tCaret.window = pMouse->window;
|
|
tCaret.icon = -1;
|
|
tCaret.offset.x = pMouse->pos.x - ws.openblock.screenrect.min.x;
|
|
tCaret.offset.y = pMouse->pos.y - ws.openblock.screenrect.max.y;
|
|
tCaret.height = (int)BIT(25);
|
|
tCaret.index = 0;
|
|
Error_CheckFatal(Wimp_SetCaretPosition(&tCaret));
|
|
}
|
|
} /* end of vMainButtonClick */
|
|
|
|
/*
|
|
* bMainKeyPressed - handle pressed keys for the main window
|
|
*/
|
|
BOOL
|
|
bMainKeyPressed(event_pollblock *pEvent, void *pvReference)
|
|
{
|
|
diagram_type *pDiag;
|
|
|
|
TRACE_MSG("bMainKeyPressed");
|
|
|
|
fail(pEvent == NULL);
|
|
fail(pEvent->type != event_KEY);
|
|
fail(pvReference == NULL);
|
|
|
|
pDiag = (diagram_type *)pvReference;
|
|
|
|
fail(pEvent->data.key.caret.window != pDiag->tMainWindow);
|
|
|
|
|
|
switch (pEvent->data.key.code) {
|
|
case keycode_CTRL_F2: /* Ctrl F2 */
|
|
bDestroyDiagram(pEvent, pvReference);
|
|
break;
|
|
case keycode_F3: /* F3 */
|
|
bSaveDrawfile(pEvent, pvReference);
|
|
break;
|
|
case keycode_SHIFT_F3: /* Shift F3 */
|
|
bSaveTextfile(pEvent, pvReference);
|
|
break;
|
|
default:
|
|
DBG_DEC(pEvent->data.key.code);
|
|
Error_CheckFatal(Wimp_ProcessKey(pEvent->data.key.code));
|
|
}
|
|
return TRUE;
|
|
} /* end of bMainKeyPressed */
|
|
|
|
/*
|
|
* bRedrawMainWindow - redraw the main window
|
|
*/
|
|
BOOL
|
|
bRedrawMainWindow(event_pollblock *pEvent, void *pvReference)
|
|
{
|
|
window_redrawblock tBlock;
|
|
diagram_type *pDiag;
|
|
drawfile_info *pInfo;
|
|
double dScaleFactor;
|
|
BOOL bMore;
|
|
|
|
TRACE_MSG("bRedrawMainWindow");
|
|
|
|
fail(pEvent == NULL);
|
|
fail(pEvent->type != event_REDRAW);
|
|
fail(pvReference == NULL);
|
|
|
|
pDiag = (diagram_type *)pvReference;
|
|
|
|
fail(pDiag->tMainWindow != pEvent->data.openblock.window);
|
|
fail(pDiag->iScaleFactorCurr < MIN_SCALE_FACTOR);
|
|
fail(pDiag->iScaleFactorCurr > MAX_SCALE_FACTOR);
|
|
|
|
dScaleFactor = (double)pDiag->iScaleFactorCurr / 100.0;
|
|
pInfo = &pDiag->tInfo;
|
|
|
|
tBlock.window = pEvent->data.openblock.window;
|
|
Error_CheckFatal(Wimp_RedrawWindow(&tBlock, &bMore));
|
|
|
|
/* If there is no real diagram just go thru the motions */
|
|
while (bMore) {
|
|
if (pInfo->data != NULL && pInfo->length != 0) {
|
|
Error_CheckFatal(Drawfile_RenderDiagram(pInfo,
|
|
&tBlock, dScaleFactor));
|
|
}
|
|
Error_CheckFatal(Wimp_GetRectangle(&tBlock, &bMore));
|
|
}
|
|
return TRUE;
|
|
} /* end of bRedrawMainWindow */
|
|
|
|
/*
|
|
* bScaleOpenAction - action to be taken when the Scale view window opens
|
|
*/
|
|
BOOL
|
|
bScaleOpenAction(event_pollblock *pEvent, void *pvReference)
|
|
{
|
|
window_state tWindowState;
|
|
diagram_type *pDiag;
|
|
|
|
TRACE_MSG("bScaleOpenAction");
|
|
|
|
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] != SAVEMENU_SCALEVIEW) {
|
|
return FALSE;
|
|
}
|
|
|
|
Error_CheckFatal(Wimp_GetWindowState(pDiag->tScaleWindow,
|
|
&tWindowState));
|
|
if (tWindowState.flags.data.open) {
|
|
/* The window is already open */
|
|
return TRUE;
|
|
}
|
|
|
|
DBG_MSG("vScaleOpenAction for real");
|
|
|
|
pDiag->iScaleFactorTemp = pDiag->iScaleFactorCurr;
|
|
vUpdateWriteableNumber(pDiag->tScaleWindow,
|
|
SCALE_SCALE_WRITEABLE, pDiag->iScaleFactorTemp);
|
|
Window_Show(pDiag->tScaleWindow, open_UNDERPOINTER);
|
|
return TRUE;
|
|
} /* end of bScaleOpenAction */
|
|
|
|
/*
|
|
* vSetTitle - set the title of a window
|
|
*/
|
|
void
|
|
vSetTitle(diagram_type *pDiag)
|
|
{
|
|
char szTitle[WINDOW_TITLE_LEN];
|
|
|
|
TRACE_MSG("vSetTitle");
|
|
|
|
fail(pDiag == NULL);
|
|
fail(pDiag->szFilename[0] == '\0');
|
|
|
|
(void)sprintf(szTitle, "%.*s at %d%%",
|
|
FILENAME_TITLE_LEN,
|
|
pDiag->szFilename,
|
|
pDiag->iScaleFactorCurr % 1000);
|
|
if (strlen(pDiag->szFilename) > FILENAME_TITLE_LEN) {
|
|
szTitle[FILENAME_TITLE_LEN - 1] = OUR_ELLIPSIS;
|
|
}
|
|
|
|
Window_SetTitle(pDiag->tMainWindow, szTitle);
|
|
} /* end of vSetTitle */
|
|
|
|
/*
|
|
* vScaleButtonClick - handle a mouse button click in the Scale view window
|
|
*/
|
|
void
|
|
vScaleButtonClick(mouse_block *pMouse, diagram_type *pDiag)
|
|
{
|
|
BOOL bCloseWindow, bRedraw;
|
|
|
|
TRACE_MSG("vScaleButtonClick");
|
|
|
|
fail(pMouse == NULL || pDiag == NULL);
|
|
fail(pMouse->window != pDiag->tScaleWindow);
|
|
|
|
bCloseWindow = FALSE;
|
|
bRedraw = FALSE;
|
|
switch (pMouse->icon) {
|
|
case SCALE_CANCEL_BUTTON:
|
|
bCloseWindow = TRUE;
|
|
pDiag->iScaleFactorTemp = pDiag->iScaleFactorCurr;
|
|
break;
|
|
case SCALE_SCALE_BUTTON:
|
|
bCloseWindow = TRUE;
|
|
bRedraw = pDiag->iScaleFactorCurr != pDiag->iScaleFactorTemp;
|
|
pDiag->iScaleFactorCurr = pDiag->iScaleFactorTemp;
|
|
break;
|
|
case SCALE_50_PCT:
|
|
pDiag->iScaleFactorTemp = 50;
|
|
break;
|
|
case SCALE_75_PCT:
|
|
pDiag->iScaleFactorTemp = 75;
|
|
break;
|
|
case SCALE_100_PCT:
|
|
pDiag->iScaleFactorTemp = 100;
|
|
break;
|
|
case SCALE_150_PCT:
|
|
pDiag->iScaleFactorTemp = 150;
|
|
break;
|
|
default:
|
|
DBG_DEC(pMouse->icon);
|
|
break;
|
|
}
|
|
if (bCloseWindow) {
|
|
/* Close the scale window */
|
|
Error_CheckFatal(Wimp_CloseWindow(pMouse->window));
|
|
if (bRedraw) {
|
|
/* Redraw the main window */
|
|
vSetTitle(pDiag);
|
|
vForceRedraw(pDiag);
|
|
}
|
|
} else {
|
|
vUpdateWriteableNumber(pMouse->window,
|
|
SCALE_SCALE_WRITEABLE,
|
|
pDiag->iScaleFactorTemp);
|
|
}
|
|
} /* end of vScaleButtonClick */
|
|
|
|
/*
|
|
* bScaleKeyPressed - handle pressed keys for the scale window
|
|
*/
|
|
BOOL
|
|
bScaleKeyPressed(event_pollblock *pEvent, void *pvReference)
|
|
{
|
|
icon_block tIcon;
|
|
diagram_type *pDiag;
|
|
caret_block *pCaret;
|
|
char *pcChar;
|
|
int iTmp;
|
|
|
|
TRACE_MSG("bScaleKeyPressed");
|
|
|
|
fail(pEvent == NULL);
|
|
fail(pEvent->type != event_KEY);
|
|
fail(pvReference == NULL);
|
|
|
|
pCaret = &pEvent->data.key.caret;
|
|
pDiag = (diagram_type *)pvReference;
|
|
|
|
fail(pEvent->data.key.caret.window != pDiag->tScaleWindow);
|
|
|
|
DBG_DEC_C(pCaret->icon != SCALE_SCALE_WRITEABLE, pCaret->icon);
|
|
DBG_DEC_C(pCaret->icon == SCALE_SCALE_WRITEABLE, pEvent->data.key.code);
|
|
|
|
if (pEvent->data.key.code != '\r' ||
|
|
pCaret->icon != SCALE_SCALE_WRITEABLE) {
|
|
Error_CheckFatal(Wimp_ProcessKey(pEvent->data.key.code));
|
|
return TRUE;
|
|
}
|
|
|
|
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);
|
|
}
|
|
iTmp = (int)strtol(tIcon.data.indirecttext.buffer, &pcChar, 10);
|
|
if (*pcChar != '\0' && *pcChar != '\r') {
|
|
DBG_DEC(*pcChar);
|
|
} else if (iTmp < MIN_SCALE_FACTOR) {
|
|
pDiag->iScaleFactorTemp = MIN_SCALE_FACTOR;
|
|
} else if (iTmp > MAX_SCALE_FACTOR) {
|
|
pDiag->iScaleFactorTemp = MAX_SCALE_FACTOR;
|
|
} else {
|
|
pDiag->iScaleFactorTemp = iTmp;
|
|
}
|
|
pDiag->iScaleFactorCurr = pDiag->iScaleFactorTemp;
|
|
/* Close the scale window */
|
|
Error_CheckFatal(Wimp_CloseWindow(pCaret->window));
|
|
/* Redraw the main window */
|
|
vSetTitle(pDiag);
|
|
vForceRedraw(pDiag);
|
|
return TRUE;
|
|
} /* end of bScaleKeyPressed */
|
|
|