home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
swCHIP 1991 January
/
swCHIP_95-1.bin
/
utility
/
gsview13
/
src
/
gvpm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-09
|
59KB
|
1,967 lines
/* Copyright (C) 1993, 1994, 1995, Russell Lang. All rights reserved.
This file is part of GSview.
This program is distributed with NO WARRANTY OF ANY KIND. No author
or distributor accepts any responsibility for the consequences of using it,
or for whether it serves any particular purpose or works at all, unless he
or she says so in writing. Refer to the GSview Free Public Licence
(the "Licence") for full details.
Every copy of GSview must include a copy of the Licence, normally in a
plain ASCII text file named LICENCE. The Licence grants you the right
to copy, modify and redistribute GSview, but only under certain conditions
described in the Licence. Among other things, the Licence requires that
the copyright notice and this notice be preserved on all copies.
*/
/* gvpm.c */
/* Main routines for PM GSview */
#define INCL_WINSTDDRAG
#include "gvpm.h"
#ifdef __EMX__
#include "sys/ioctl.h"
#endif
#include "gvphelp.h" /* generated by doc2ipf.c */
char szAppName[MAXSTR] = "PM GSview";
char szHelpTopic[MAXSTR];
char szWait[MAXSTR];
char szExePath[MAXSTR];
char szHelpFile[MAXSTR];
char szFindText[MAXSTR];
char szIniFile[MAXSTR];
char szMMini[MAXSTR];
char previous_filename[MAXSTR];
const char szScratch[] = "gv"; /* temporary filename prefix */
HAB hab; /* Anchor Block */
HELPINIT hi_help;
ULONG os_version;
HWND hwnd_frame;
HWND hwnd_bmp;
HWND hwnd_status;
HWND hwnd_button;
HWND hwnd_help;
HWND hwnd_modeless; /* any modeless dialog box */
HWND hptr_crosshair;
HACCEL haccel;
POINTL buttonbar;
POINTL statusbar;
POINTL info_file;
POINTL info_page;
POINTL scroll_pos;
RECTL info_coord;
BOOL waiting;
TID queue_tid;
TID term_tid;
#define SB_TOP 20
#define SB_BOTTOM 21
GVIEW gsview; /* GSview structure */
PSFILE psfile; /* Postscript file structure */
BMAP bitmap; /* Bitmap structure */
PROG gsprog; /* Ghostscript program structure */
PROG pdfconv; /* Ghostscript running PDF converter */
OPTIONS option; /* GSview options (saved in INI file) */
DISPLAY display; /* Display parameters */
PRINTER printer; /* Printer GS parameters */
PSDOC *doc;
int page_extra; /* extra pages to skip */
int page_skip = 5; /* number of pages to skip in IDM_NEXTSKIP or IDM_PREVSKIP */
BOOL changed_version = FALSE; /* to warn user to update Ghostscript Command */
BOOL zoom = FALSE; /* true if display zoomed */
BOOL debug = FALSE; /* /D command line option used */
struct page_list_s page_list;
struct sound_s sound[NUMSOUND] = {
{"SoundOutputPage", IDS_SNDPAGE, ""},
{"SoundNoPage", IDS_SNDNOPAGE, BEEP},
{"SoundNoNumbering", IDS_SNDNONUMBER, ""},
{"SoundNotOpen", IDS_SNDNOTOPEN, ""},
{"SoundError", IDS_SNDERROR, BEEP},
{"SoundTimeout", IDS_SNDTIMEOUT, ""},
{"SoundStart", IDS_SNDSTART, ""},
{"SoundExit", IDS_SNDEXIT, ""},
};
PFN_MciPlayFile pfnMciPlayFile;
/* button bar */
struct button *buttonhead, *buttontail;
BOOL button_down;
struct button *button_current;
struct button *button_info;
POINTL button_shift;
POINTL button_size;
MRESULT EXPENTRY ClientWndProc(HWND, ULONG, MPARAM, MPARAM);
MRESULT EXPENTRY FrameWndProc(HWND, ULONG, MPARAM, MPARAM);
MRESULT EXPENTRY StatusWndProc(HWND, ULONG, MPARAM, MPARAM);
MRESULT EXPENTRY ButtonWndProc(HWND, ULONG, MPARAM, MPARAM);
PFNWP OldFrameWndProc;
BOOL scan_bitmap(BMAP *pbm);
HBITMAP make_bitmap(BMAP *, ULONG, ULONG, ULONG, ULONG, ULONG);
void cursorpos_paint(HPS hps);
void map_pt_to_pixel(float *x, float *y);
MRESULT DragOver(PDRAGINFO);
MRESULT Drop(PDRAGINFO);
void
update_scroll_bars(void)
{
/* Cause update of scroll bars etc. */
SWP swp;
WinQueryWindowPos(hwnd_bmp, &swp);
WinSendMsg(hwnd_bmp, WM_SIZE, MPFROM2SHORT(swp.cx, swp.cy), MPFROM2SHORT(swp.cx, swp.cy));
}
/* temporary until status line created */
void
update_title(void)
{
char buf[256];
char *state;
char page[256];
char *progname = "PM GSview";
if (display.page)
state = "PAGE";
else if (display.sync)
state = "SYNC";
else
state = "OTHER";
if (psfile.name[0]) {
if (doc != (PSDOC *)NULL) {
int n = map_page(psfile.pagenum - 1);
if (doc->pages)
sprintf(page, "'%s' %d of %d", doc->pages[n].label ? doc->pages[n].label : " ",psfile.pagenum, doc->numpages);
else
sprintf(page, "'' %d of %d", psfile.pagenum, doc->numpages);
sprintf(buf, "%s - %s - %s - %s", progname,
psfile.name, page, state);
}
else {
sprintf(buf, "%s - %s - %d -%s", progname,
psfile.name, psfile.pagenum, state);
}
}
else {
sprintf(buf, "%s - No File", progname);
}
WinSetWindowText(hwnd_frame, buf);
}
/* display thread */
/* abort if display.abort TRUE */
void
display_thread(void *arg)
{
do_output();
/* avoid bug in gs 2.9.4 */
{int i;
for (i=0; i<80; i++)
fputs("\r\n",gsprog.input);
}
fflush(gsprog.input);
dfclose();
display.busy = FALSE;
display.abort = FALSE;
display.do_endfile = FALSE;
display.do_resize = FALSE;
display.do_display = FALSE;
if (!gsprog.valid) {
/* WinPostMsg(hwnd_bmp, WM_GSCLOSE, MPFROMLONG(0), MPFROMLONG(0)); */
gs_close();
}
DosPostEventSem(display.done);
}
#ifdef NOTUSED
/* not used */
/* copy psfile.file to GS */
/* abort copy if display.abort TRUE */
void
copy_thread(void *arg)
{
#define COPY_BUF_SIZE 4096
char *buffer;
int count;
if ((buffer = malloc(COPY_BUF_SIZE)) != (char *)NULL) {
while ( !display.abort &&
(count = fread(buffer, 1, COPY_BUF_SIZE, psfile.file)) != 0 )
fwrite(buffer, 1, count, gsprog.input);
free(buffer);
}
fclose(psfile.file);
/* fputs("quit\n", gsprog.input); */
fflush(gsprog.input);
display.busy = FALSE;
display.abort = FALSE;
DosPostEventSem(display.done);
}
#endif
/* Queue thread */
/* This thread waits for queue messages from gsos2.exe */
/* This thread must NOT call C library functions */
VOID APIENTRY queue_thread(ULONG unused)
{
REQUESTDATA Request;
ULONG DataLength;
PVOID DataAddress;
BYTE ElemPriority;
unused = unused; /* to shut up warning */
while ( !DosReadQueue(gsview.queue, &Request, &DataLength, &DataAddress,
0, DCWW_WAIT, &ElemPriority, (HEV)NULL) ) {
switch(Request.ulData) {
case GS_UPDATING:
WinPostMsg(hwnd_bmp, WM_GSUPDATING, MPFROMLONG(0), MPFROMLONG(0));
break;
case GS_SYNC:
WinPostMsg(hwnd_bmp, WM_GSSYNC, MPFROMLONG(0), MPFROMLONG(0));
break;
case GS_PAGE:
WinPostMsg(hwnd_bmp, WM_GSPAGE, MPFROMLONG(0), MPFROMLONG(0));
break;
case GS_CLOSE:
WinPostMsg(hwnd_bmp, WM_GSCLOSE, MPFROMLONG(0), MPFROMLONG(0));
break;
case GS_ERROR:
WinPostMsg(hwnd_bmp, WM_GSERROR, MPFROMLONG(0), MPFROMLONG(0));
break;
case GS_PALCHANGE:
WinPostMsg(hwnd_bmp, WM_GSPALCHANGE, MPFROMLONG(0), MPFROMLONG(0));
break;
case GS_BEGIN:
WinPostMsg(hwnd_bmp, WM_GSBEGIN, MPFROMLONG(0), MPFROMLONG(0));
break;
case GS_END:
WinPostMsg(hwnd_bmp, WM_GSEND, MPFROMLONG(0), MPFROMLONG(0));
break;
}
}
}
/* termination queue thread */
/* This thread waits for termination messages */
/* This thread must NOT call C library functions */
VOID APIENTRY term_thread(ULONG unused)
{
REQUESTDATA Request;
ULONG DataLength;
PVOID DataAddress;
BYTE ElemPriority;
WORD *pword;
unused = unused; /* to shut up warning */
while ( !DosReadQueue(gsview.term_queue, &Request, &DataLength, &DataAddress,
0, DCWW_WAIT, &ElemPriority, (HEV)NULL) ) {
pword = DataAddress;
/* should really build a list of programs and search the list */
if (*pword == gsprog.session_id) {
WinPostMsg(hwnd_bmp, WM_GSCLOSE, MPFROMLONG(0), MPFROMSHORT(pword[1]));
}
else if (*pword == printer.prog.session_id) {
WinPostMsg(hwnd_bmp, WM_GSPRNEXIT, MPFROMP(&printer), MPFROMSHORT(pword[1]));
}
DosFreeMem(DataAddress);
}
term_tid = 0;
}
void
exit_func(void)
{
DosCloseEventSem(gsview.next_event);
DosCloseMutexSem(gsview.bmp_mutex);
DosCloseQueue(gsview.queue);
if (bitmap.pbmi)
DosFreeMem((PVOID)bitmap.pbmi);
if (gsprog.valid) {
stop_pgm(&gsprog);
}
if (printer.prog.valid) {
/* clean up after printer */
stop_pgm(&printer.prog);
if ((printer.cfname[0] != '\0') && !debug)
unlink(printer.cfname);
printer.cfname[0] = '\0';
if ((printer.fname[0] != '\0') && !debug)
unlink(printer.fname);
printer.fname[0] = '\0';
}
if (psfile.ispdf && psfile.name[0] && psfile.pdftemp[0])
unlink(psfile.pdftemp); /* remove temporary DSC file */
if (option.settings)
write_profile();
DosCloseQueue(gsview.term_queue);
}
int
main(int argc, char *argv[])
{
HMQ hand_mq; /* message queue */
QMSG q_mess; /* queue message */
ULONG flFlags; /* Window frame definition */
APIRET rc = 0;
SWP swp;
hab = WinInitialize(0); /* Get the Anchor Block */
hand_mq = WinCreateMsgQueue(hab, 0); /* start a queue */
if (argc > 4) {
rc = 1;
error_message("Usage: gvpm [/D] [/F] [/P] [/S[port]] [filename]");
}
rc = gsview_init(argc, argv);
atexit(exit_func);
if (!rc) {
WinShowWindow(hwnd_frame, TRUE);
haccel = WinQueryAccelTable(hab, hwnd_frame);
/* create help window */
hi_help.cb = sizeof(HELPINIT);
hi_help.ulReturnCode = 0;
hi_help.pszTutorialName = NULL;
hi_help.phtHelpTable = NULL;
hi_help.hmodAccelActionBarModule = 0;
hi_help.idAccelTable = 0;
hi_help.idActionBar = 0;
hi_help.pszHelpWindowTitle=(PSZ)"PM GSview Help";
hi_help.hmodHelpTableModule = 0;
hi_help.fShowPanelId = 0;
hi_help.pszHelpLibraryName = (PSZ)szHelpFile;
hwnd_help = WinCreateHelpInstance(hab, &hi_help);
if (!hwnd_help)
message_box("main: help not available", 0);
else
if (hi_help.ulReturnCode)
message_box("main: help terminated due to error", 0);
if (hwnd_help)
WinAssociateHelpInstance(hwnd_help, hwnd_frame);
}
play_sound(SOUND_START);
/* message loop */
while (!rc && WinGetMsg(hab, &q_mess, 0L, 0, 0))
WinDispatchMsg(hab, &q_mess);
play_sound(SOUND_EXIT);
/* Shut down the application window and queue */
DosKillThread(queue_tid);
DosKillThread(term_tid);
term_tid = 0;
if (hwnd_help)
WinDestroyHelpInstance(hwnd_help);
WinDestroyWindow(hwnd_frame);
WinDestroyMsgQueue(hand_mq);
WinTerminate(hab);
return rc;
}
#define MAX_PAL_SIZE 256
void
make_palette(BMAP *pbm)
{
ULONG tbl[MAX_PAL_SIZE];
PRGB2 palptr = (PRGB2) ((PBYTE)(pbm->pbmi) + pbm->pbmi->cbFix);
RGB *old_palptr = (RGB *)palptr;
int palcount = pbm->palimportant;
int i;
BOOL old_bmp = (pbm->pbmi->cbFix == sizeof(BITMAPINFOHEADER));
if (old_bmp) {
for (i=0; i<palcount; i++) {
tbl[i] = (old_palptr->bRed<<16) + (old_palptr->bGreen<<8) + (old_palptr->bBlue);
palptr++;
}
}
else {
for (i=0; i<palcount; i++) {
tbl[i] = (palptr->bRed<<16) + (palptr->bGreen<<8) + (palptr->bBlue);
palptr++;
}
}
if (display.hpal_exists)
GpiDeletePalette(display.hpal);
display.hpal = GpiCreatePalette(hab, 0L, LCOLF_CONSECRGB, palcount, tbl);
display.hpal_exists = TRUE;
}
/* scan bitmap */
/* update bitmap structure */
/* return value is TRUE if bitmap dimension has changed */
BOOL
scan_bitmap(BMAP *pbm)
{
PBITMAPINFO2 pbmi = pbm->pbmi;
PBITMAPINFO old_pbmi = (PBITMAPINFO)pbmi;
BOOL old_bmp = (pbmi->cbFix == sizeof(BITMAPINFOHEADER));
if (old_bmp) {
/* it is a BITMAPINFO */
switch(old_pbmi->cBitCount) {
case 24:
pbm->palsize = 0;
break;
case 8:
pbm->palsize = 256;
break;
case 4:
pbm->palsize = 16;
break;
case 1:
pbm->palsize = 2;
break;
default:
pbm->valid = FALSE;
error_message("scan_bitmap: wrong number of bits"); /* panic */
return FALSE;
}
pbm->palimportant = pbm->palsize;
pbm->palsize = pbm->palsize * sizeof(RGB);
pbm->bits = (PBYTE)old_pbmi + old_pbmi->cbFix + pbm->palsize;
pbm->width = old_pbmi->cx;
pbm->height = old_pbmi->cy;
pbm->planes = old_pbmi->cPlanes;
pbm->depth = old_pbmi->cBitCount;
}
else {
/* it is a BITMAPINFO2 */
switch(pbmi->cBitCount) {
case 24:
pbm->palsize = 0;
break;
case 8:
pbm->palsize = 256;
break;
case 4:
pbm->palsize = 16;
break;
case 1:
pbm->palsize = 2;
break;
default:
pbm->valid = FALSE;
error_message("scan_bitmap: wrong number of bits"); /* panic */
return FALSE;
}
if ( (pbmi->cbFix > (&(pbmi->cclrUsed) - &(pbmi->cbFix)))
&& (pbmi->cclrUsed != 0) && (pbmi->cBitCount != 24) )
pbm->palsize = pbmi->cclrUsed;
pbm->palimportant = pbm->palsize;
if ( (pbmi->cbFix > (&(pbmi->cclrImportant) - &(pbmi->cbFix)))
&& (pbmi->cclrImportant != 0) && (pbmi->cBitCount != 24) )
pbm->palimportant = pbmi->cclrImportant;
pbm->palsize = pbm->palsize * sizeof(RGB2);
pbm->bits = (PBYTE)pbmi + pbmi->cbFix + pbm->palsize;
pbm->width = pbmi->cx;
pbm->height = pbmi->cy;
pbm->planes = pbmi->cPlanes;
pbm->depth = pbmi->cBitCount;
}
if ((pbm->palsize != pbm->old_palsize) || (pbm->palimportant != pbm->old_palimportant)) {
if ( (pbm->depth == 8) && display.hasPalMan )
make_palette(pbm);
pbm->old_palimportant = pbm->palimportant;
}
if ( (pbm->width == pbm->old_width) &&
(pbm->height == pbm->old_height) &&
(pbm->planes == pbm->old_planes) &&
(pbm->depth == pbm->old_depth) &&
(pbm->palsize == pbm->old_palsize) &&
(pbm->old_bmp == old_bmp) )
return FALSE;
/* bitmap has changed */
pbm->old_width = pbm->width;
pbm->old_height = pbm->height;
pbm->old_planes = pbm->planes;
pbm->old_depth = pbm->depth;
pbm->old_palsize = pbm->palsize;
pbm->old_bmp = old_bmp;
return TRUE;
}
/* copy bitmap to the clipboard */
void
copy_clipboard(void)
{
HBITMAP hbmp;
if (!bitmap.valid) {
gserror(0, "Cannot copy to clipboard:\nNo Bitmap displayed", MB_ICONEXCLAMATION, SOUND_ERROR);
return;
}
if (WinOpenClipbrd(hab)) {
/* get bmp mutex to stop gs.exe changing bitmap while we copy it */
if (DosRequestMutexSem(gsview.bmp_mutex, 10000) == ERROR_TIMEOUT)
message_box("copy_clipboard: mutex timeout", 0);
if (scan_bitmap(&bitmap)) {
/* bitmap has changed */
update_scroll_bars();
}
hbmp = make_bitmap(&bitmap, 0, 0, bitmap.width, bitmap.height, bitmap.depth);
if (hbmp) {
WinEmptyClipbrd(hab);
WinSetClipbrdData(hab, (ULONG)hbmp, CF_BITMAP, CFI_HANDLE);
}
DosReleaseMutexSem(gsview.bmp_mutex);
WinCloseClipbrd(hab);
}
}
HBITMAP
make_bitmap(BMAP *pbm, ULONG left, ULONG bottom, ULONG right, ULONG top, ULONG depth)
{
HDC hdcMem = DEV_ERROR;
HPS hps = GPI_ERROR;
HBITMAP hbmp = GPI_ERROR, hbmr = HBM_ERROR;
SIZEL sizePS;
BITMAPINFOHEADER2 bmih;
if ( (left == right) || (bottom == top) )
return (HBITMAP)NULL;
if (right > pbm->width)
right = pbm->width;
if (left > pbm->width)
left = 0;
if (top > pbm->height)
top = pbm->height;
if (bottom > pbm->height)
bottom = 0;
memset(&bmih, 0, sizeof(bmih));
bmih.cbFix = sizeof(BITMAPINFOHEADER2);
bmih.cx = right - left;
bmih.cy = top - bottom;
bmih.cPlanes = 1;
bmih.cBitCount = depth;
/* create memory DC compatible with screen */
hdcMem = DevOpenDC(hab, OD_MEMORY, "*", 0L, NULL, NULLHANDLE);
sizePS.cx = right - left;
sizePS.cy = top - bottom;
if (hdcMem != DEV_ERROR)
hps = GpiCreatePS(hab, hdcMem, &sizePS,
PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC );
if (hps != GPI_ERROR)
hbmp = GpiCreateBitmap(hps, &bmih, 0L, NULL, NULL);
if (hbmp != GPI_ERROR)
hbmr = GpiSetBitmap(hps, hbmp);
if (hbmr != HBM_ERROR) {
LONG rc;
ERRORID eid;
POINTL apts[4];
/* target is inclusive */
apts[0].x = 0;
apts[0].y = 0;
apts[1].x = right - left - 1;
apts[1].y = top - bottom - 1;
/* source is not inclusive of top & right borders */
apts[2].x = left;
apts[2].y = bottom;
apts[3].x = right;
apts[3].y = top;
rc = 0;
eid = WinGetLastError(hab);
rc = GpiDrawBits(hps, pbm->bits, pbm->pbmi, 4, apts,
(bitmap.depth != 1) ? ROP_SRCCOPY : ROP_NOTSRCCOPY, 0);
if (rc==0) {
char buf[256];
eid = WinGetLastError(hab);
sprintf(buf,"make_bitmap: GpiDrawBits rc = %08x, eid = %08x",rc, eid);
message_box(buf, 0);
}
}
if (hbmr != HBM_ERROR)
GpiSetBitmap(hps, (ULONG)0);
if (hps != GPI_ERROR)
GpiDestroyPS(hps);
if (hdcMem != DEV_ERROR)
DevCloseDC(hdcMem);
if ( (hbmr == HBM_ERROR) || (hdcMem == DEV_ERROR) ||
(hbmp == GPI_ERROR) || (hps == GPI_ERROR) ) {
if (hbmp != GPI_ERROR)
GpiDeleteBitmap(hbmp);
return 0;
}
return hbmp;
}
MRESULT
paint_bitmap(HPS ps, PRECTL prect, int scrollx, int scrolly)
{
POINTL apts[4];
RECTL rect;
int wx, wy;
int ewx = 0; /* empty area at right */
int ewy = 0; /* empty area at top */
if (WinIsRectEmpty(hab, prect))
return 0;
/* source is not inclusive of top & right borders */
wx = prect->xRight - prect->xLeft; /* update width */
wy = prect->yTop - prect->yBottom; /* update height */
if (prect->xLeft < display.offset.x)
apts[2].x = 0;
else
apts[2].x = (prect->xLeft-display.offset.x) + scrollx;
if (prect->yBottom < display.offset.y)
apts[2].y = 0;
else
apts[2].y = (prect->yBottom-display.offset.y) + scrolly;
if (apts[2].x > bitmap.width)
apts[2].x = bitmap.width;
if (apts[2].x + wx > bitmap.width) {
wx = bitmap.width - apts[2].x;
}
apts[3].x = apts[2].x + wx;
if (apts[2].y > bitmap.height)
apts[2].y = bitmap.height;
if (apts[2].y + wy > bitmap.height) {
wy = bitmap.height - apts[2].y;
}
apts[3].y = apts[2].y + wy;
/* target is inclusive */
#ifdef NOTUSED
apts[0].x = prect->xLeft;
apts[0].y = prect->yBottom;
apts[1].x = prect->xLeft + wx - 1;
apts[1].y = prect->yBottom + wy - 1;
#else
if (prect->xLeft < display.offset.x)
apts[0].x = display.offset.x;
else
apts[0].x = prect->xLeft;
if (prect->yBottom < display.offset.y)
apts[0].y = display.offset.y;
else
apts[0].y = prect->yBottom;
apts[1].x = apts[0].x + wx - 1;
apts[1].y = apts[0].y + wy - 1;
#endif
#ifdef NOTUSED
if ( (display.bitcount == 4) /* standard VGA is buggy */
|| ( (os_version==201100) && (display.bitcount==8) && (bitmap.depth==1)) /* S3 and ATI GU are buggy */
) {
/* slow code to dodge OS/2 bugs */
/* this code double buffers the bitmap and works on a standard VGA
* but didn't work on an ATI Ultra Graphics Pro in 8514 emulation
*/
/* This won't work for version 2.11, S3 or ATI GU, 8bit/pixel display, 8bit/pixel bitmap */
HBITMAP hbmp;
/* create a bitmap */
hbmp = make_bitmap(&bitmap, apts[2].x, apts[2].y, apts[3].x, apts[3].y, bitmap.depth);
/* Draw it to the display */
if (hbmp) {
WinDrawBitmap(ps, hbmp, NULL, &apts[0], CLR_BLACK, CLR_WHITE, DBM_NORMAL);
GpiDeleteBitmap(hbmp);
}
}
else {
#endif
/* fast code which doesn't always work */
/* This code works on the Trident SVGA and 8514 in 256 color mode,
* but GpiDrawBits fails with a SYS3175 on the standard VGA.
*/
/* This won't work for version 2.11, S3 or ATI GU, 8bit/pixel display, 1bit/pixel bitmap */
GpiDrawBits(ps, bitmap.bits, bitmap.pbmi, 4, apts,
(bitmap.depth != 1) ? ROP_SRCCOPY : ROP_NOTSRCCOPY, 0);
#ifdef NOTUSED
}
#endif
/* Fill areas around page */
if (prect->yBottom < display.offset.y) { /* bottom centre */
rect.yBottom = prect->yBottom;
rect.yTop = display.offset.y;
rect.xLeft = apts[0].x;
rect.xRight = rect.xLeft + wx;
WinFillRect(ps, &rect, SYSCLR_BUTTONMIDDLE);
}
if (prect->yTop > bitmap.height + display.offset.y) { /* bottom centre */
rect.yBottom = bitmap.height + display.offset.y;
rect.yTop = prect->yTop;
rect.xLeft = apts[0].x;
rect.xRight = rect.xLeft + wx;
WinFillRect(ps, &rect, SYSCLR_BUTTONMIDDLE);
}
if (prect->xLeft < display.offset.x) { /* left */
rect.yBottom = prect->yBottom;
rect.yTop = prect->yTop;
rect.xLeft = prect->xLeft;
rect.xRight = display.offset.x;
WinFillRect(ps, &rect, SYSCLR_BUTTONMIDDLE);
}
if (prect->xRight > bitmap.width + display.offset.x) { /* right */
rect.yBottom = prect->yBottom;
rect.yTop = prect->yTop;
rect.xLeft = bitmap.width + display.offset.x;
rect.xRight = prect->xRight;
WinFillRect(ps, &rect, SYSCLR_BUTTONMIDDLE);
}
/* draw bounding box */
if ((doc != (PSDOC *)NULL) && option.show_bbox) {
POINTL pt;
float x, y;
/* map bounding box to device coordinates */
x = doc->boundingbox[LLX];
y = doc->boundingbox[LLY];
map_pt_to_pixel(&x, &y);
rect.xLeft = (int)x;
rect.yBottom = (int)y;
x = doc->boundingbox[URX];
y = doc->boundingbox[URY];
map_pt_to_pixel(&x, &y);
rect.xRight = (int)x;
rect.yTop = (int)y;
/* draw it inverted */
GpiSetColor(ps, CLR_TRUE);
GpiSetLineType(ps, LINETYPE_SHORTDASH);
GpiSetMix(ps, FM_XOR);
pt.x = rect.xLeft; pt.y = rect.yBottom;
GpiMove(ps, &pt);
pt.x = rect.xRight; /* might be better to use GpiPolyLine */
GpiLine(ps, &pt);
pt.y = rect.yTop;
GpiLine(ps, &pt);
pt.x = rect.xLeft;
GpiLine(ps, &pt);
pt.y = rect.yBottom;
GpiLine(ps, &pt);
GpiSetLineType(ps, LINETYPE_DEFAULT);
GpiSetMix(ps, FM_DEFAULT);
GpiSetColor(ps, CLR_TRUE);
}
return 0;
}
/* enable or disable a menu item */
void
enable_menu_item(int menuid, int itemid, BOOL enabled)
{
HWND hwndMenu;
MENUITEM mi;
hwndMenu = WinWindowFromID(hwnd_frame, FID_MENU);
WinSendMsg(hwndMenu, MM_QUERYITEM,
MPFROM2SHORT(menuid, TRUE), MPFROMP(&mi));
WinSendMsg(mi.hwndSubMenu, MM_SETITEMATTR, MPFROMLONG(itemid),
MPFROM2SHORT(MIA_DISABLED, enabled ? 0 : MIA_DISABLED));
}
/* This is the window function */
MRESULT EXPENTRY ClientWndProc(HWND hwnd, ULONG mess,
MPARAM mp1, MPARAM mp2)
{
char buf[256];
static int cxClient, cyClient;
static int cxAdjust, cyAdjust;
static int nHscrollMax, nHscrollPos;
static int nVscrollMax, nVscrollPos;
int nHscrollInc;
int nVscrollInc;
HWND hwndScroll;
HPS hps;
RECTL rect;
ULONG ulclr;
switch(mess) {
case WM_CREATE:
break;
case WM_ERASEBACKGROUND:
/* by returning TRUE, the Presentation Manager automatically clears
* the window each time the window is resized or moved.
*/
if (!bitmap.valid)
return (MRESULT)TRUE;
break;
case WM_GSUPDATING:
/* this used to do the same as WM_GSBEGIN */
/* if we don't know the bitmap pointer, get it now */
if (!bitmap.valid) {
APIRET rc;
char name[256];
memset(&bitmap, 0, sizeof(bitmap));
sprintf(name, SHARED_NAME, gsview.id);
rc = DosGetNamedSharedMem((PVOID *)&bitmap.pbmi, name, PAG_READ);
if (rc) {
sprintf(buf, "Failed to open: bmp shared memory \"%s\" rc = %d", name, rc);
error_message(buf);
}
else
bitmap.valid = TRUE;
}
return 0;
case WM_GSBEGIN:
display.page = FALSE;
display.sync = FALSE;
display.end = FALSE;
load_string(IDS_WAITDRAW, szWait, sizeof(szWait));
info_wait(TRUE);
if (!gsprog.valid) {
/* someone has killed GS */
WinSendMsg(hwnd_bmp, WM_GSCLOSE, MPFROMLONG(0), MPFROMLONG(0));
return 0;
}
/* if we don't know the bitmap pointer, get it now */
if (!bitmap.valid) {
APIRET rc;
char name[256];
memset(&bitmap, 0, sizeof(bitmap));
sprintf(name, SHARED_NAME, gsview.id);
rc = DosGetNamedSharedMem((PVOID *)&bitmap.pbmi, name, PAG_READ);
if (rc) {
sprintf(buf, "Failed to open: bmp shared memory \"%s\" rc = %d", name, rc);
error_message(buf);
}
else
bitmap.valid = TRUE;
}
/* should set update timer here */
return 0;
case WM_GSSYNC:
display.page = FALSE;
display.sync = TRUE;
/* don't clear display.end since this stops us noticing end of non DSC document
display.end = FALSE;
*/
if (!WinInvalidateRect(hwnd_bmp, (PRECTL)NULL, TRUE))
error_message("error invalidating rect");
if (!WinUpdateWindow(hwnd_bmp))
error_message("error updating window");
/*
if (!display.busy)
info_wait(FALSE);
*/
return 0;
case WM_GSPAGE:
play_sound(SOUND_PAGE);
display.page = TRUE;
display.sync = FALSE;
display.end = FALSE;
if (!WinInvalidateRect(hwnd_bmp, (PRECTL)NULL, TRUE))
error_message("error invalidating rect");
if (!WinUpdateWindow(hwnd_bmp))
error_message("error updating window");
info_wait(FALSE);
return 0;
case WM_GSCLOSE:
display.page = FALSE;
display.sync = FALSE;
bitmap.valid = FALSE;
/* mark bitmap as unused */
if (DosRequestMutexSem(gsview.bmp_mutex, 10000) == ERROR_TIMEOUT)
message_box("ClientWndProc: WM_CLOSE: mutex timeout", 0);
DosEnterCritSec();
if (bitmap.pbmi)
DosFreeMem((PVOID)bitmap.pbmi);
memset(&bitmap, 0, sizeof(bitmap));
DosExitCritSec();
DosReleaseMutexSem(gsview.bmp_mutex);
update_scroll_bars();
if (display.busy) {
int i, n;
char buf[2048];
gsprog.valid = FALSE; /* don't kill gsprog.input while display thread using it */
display.abort = TRUE;
#ifdef __EMX__
/* flush pipe - not working */
n = -1;
while ( display.busy && n ) {
i = ioctl(0, FIONREAD, &n);
if (n)
read(0, buf, n > sizeof(buf) ? sizeof(buf) : n);
if (gsprog.input)
fflush(gsprog.input);
DosSleep(0); /* switch to next thread */
}
#endif
}
else
cleanup_pgm(&gsprog);
info_wait(FALSE);
return 0;
case WM_GSERROR:
display.page = FALSE;
display.sync = FALSE;
display.end = FALSE;
if (display.busy)
display.abort = TRUE;
info_wait(FALSE);
message_box("Ghostscript Error\rSee Ghostscript window for more details", 0);
DosPostEventSem(gsview.next_event);
if (!display.busy)
cleanup_pgm(&gsprog);
return 0;
case WM_GSPALCHANGE:
/* do nothing yet */
return 0;
case WM_GSEND:
display.page = FALSE;
display.sync = FALSE;
display.end = TRUE;
if (!WinInvalidateRect(hwnd_bmp, (PRECTL)NULL, TRUE))
error_message("error invalidating rect");
if (!WinUpdateWindow(hwnd_bmp))
error_message("error updating window");
if (!display.busy)
info_wait(FALSE);
return 0;
case WM_GSPRNEXIT:
{ PRINTER *prn = (PRINTER *)mp1;
cleanup_pgm(&prn->prog);
if ((prn->cfname[0] != '\0') && !debug)
unlink(prn->cfname);
prn->cfname[0] = '\0';
if ((prn->fname[0] != '\0') && !debug)
unlink(prn->fname);
prn->fname[0] = '\0';
}
return 0;
case WM_INITMENU:
enable_menu_item(IDM_EDITMENU, IDM_COPYCLIP, bitmap.valid);
enable_menu_item(IDM_EDITMENU, IDM_PASTETO, bitmap.valid);
enable_menu_item(IDM_EDITMENU, IDM_ADDEPSMENU, bitmap.valid
&& (doc != (PSDOC *)NULL) && doc->epsf);
enable_menu_item(IDM_EDITMENU, IDM_EXTEPSMENU,
(psfile.preview == IDS_EPST) || (psfile.preview == IDS_EPSW));
WinSetAccelTable(hab, NULLHANDLE, hwnd_frame); /* disable keyboard accelerators */
break;
case WM_MENUEND:
WinSetAccelTable(hab, haccel, hwnd_frame); /* reenable keyboard accelerators */
break;
case WM_COMMAND:
if (LONGFROMMP(mp1) == IDM_DROP) {
char *cmd = (char *)mp2;
if ((cmd[0] == '-') || (cmd[0] == '/')) {
switch (toupper(cmd[1])) {
case 'P':
gsview_selectfile(cmd+2);
gsview_print(FALSE);
break;
case 'F':
gsview_selectfile(cmd+2);
gsview_print(TRUE);
break;
case 'S':
if (cmd[2] != ' ') {
char *fname;
/* skip over port name */
for (fname=cmd+2; *fname && *fname!=' '; fname++)
/* nothing */ ;
/* skip blanks until file name */
if (*fname) {
*fname++ = '\0'; /* place null after port name */
for (; *fname==' '; fname++)
/* nothing */ ;
}
if (*fname) {
/* found both filename and port */
gsview_spool(fname, cmd+2);
break;
}
}
gsview_spool(cmd+2, (char *)NULL);
break;
default:
gserror(IDS_BADCLI, cmd, MB_ICONEXCLAMATION, SOUND_ERROR);
}
}
else {
FILE *f;
/* only display file if it exists */
/* because starting GSview from Desktop menu sets cmd to d:\Desktop */
if ( (f=fopen(cmd,"rb")) != (FILE *)NULL ) {
fclose(f);
gsview_displayfile(cmd);
}
}
free(cmd);
}
else {
if (waiting) {
switch(LONGFROMMP(mp1)) {
case IDM_INFO:
case IDM_SAVEDIR:
case IDM_SETTINGS:
case IDM_SAVESETTINGS:
case IDM_SOUNDS:
case IDM_HELPCONTENT:
case IDM_HELPSEARCH:
case IDM_ABOUT:
case IDM_EXIT:
/* these are safe to use when busy */
break;
default:
play_sound(SOUND_ERROR);
return 0; /* Command not permitted now */
}
}
if (LONGFROMMP(mp1) == IDM_PSTOEPS) {
if (psfile.name[0] == '\0') /* need open file */
WinSendMsg(hwnd, WM_COMMAND, MPFROMSHORT(IDM_OPEN), MPFROM2SHORT(CMDSRC_OTHER,FALSE));
}
gsview_command(LONGFROMMP(mp1));
}
if (display.do_endfile || display.do_resize || display.do_display) {
if (display.busy && (display.do_display || display.do_resize)) {
play_sound(SOUND_ERROR);
break;
}
load_string(IDS_WAIT, szWait, sizeof(szWait));
info_wait(TRUE);
if (!gs_open()) {
info_wait(FALSE);
return FALSE;
}
if (display.busy) {
play_sound(SOUND_ERROR);
if (!gsprog.valid) {
message_box("Problem with gs. Exit and restart PM GSview", 0);
info_wait(FALSE);
}
}
else {
ULONG count;
dfreopen();
display.busy = TRUE;
DosResetEventSem(display.done, &count);
#ifdef NOTHREAD
/* for debugging run it in thread 1 */
display_thread(NULL);
#else
#ifdef __BORLANDC__
display.id = _beginthread(display_thread, 16384, NULL);
#else
display.id = _beginthread(display_thread, NULL, 16384, NULL);
#endif
if (display.id == -1) {
info_wait(FALSE);
message_box("_beginthread() output thread failed", 0);
display.busy = FALSE;
display.abort = FALSE;
display.do_endfile = FALSE;
display.do_resize = FALSE;
display.do_display = FALSE;
play_sound(SOUND_ERROR);
}
#endif
}
}
else
info_wait(FALSE);
break;
case WM_REALIZEPALETTE:
if ((bitmap.depth == 8) && display.hasPalMan && display.hpal_exists) {
hps = WinGetPS(hwnd);
GpiSelectPalette(hps, display.hpal);
if (WinRealizePalette(hwnd, hps, &ulclr) > 0)
WinInvalidateRect(hwnd, NULL, FALSE);
GpiSelectPalette(hps, (HPAL)NULL);
WinReleasePS(hps);
return 0;
}
break; /* use default processing */
case WM_PAINT:
if (!bitmap.valid) {
hps = WinBeginPaint(hwnd, (ULONG)0, &rect);
WinFillRect(hps, &rect, CLR_BACKGROUND);
WinEndPaint(hwnd);
return 0;
}
/* Refresh the window each time the WM_PAINT message is received */
/* get bmp mutex to stop gs.exe changing bitmap while we paint */
if (DosRequestMutexSem(gsview.bmp_mutex, 10000) == ERROR_TIMEOUT)
message_box("ClientWndProc: WM_PAINT: mutex timeout", 0);
if (scan_bitmap(&bitmap))
update_scroll_bars(); /* bitmap has changed */
if (!bitmap.valid) {
DosReleaseMutexSem(gsview.bmp_mutex);
hps = WinBeginPaint(hwnd, (ULONG)0, &rect);
WinFillRect(hps, &rect, CLR_BACKGROUND);
WinEndPaint(hwnd);
return 0;
}
hps = WinBeginPaint(hwnd, (HPS)NULL, &rect);
if ((bitmap.depth == 8) && display.hasPalMan && display.hpal_exists) {
GpiSelectPalette(hps, display.hpal);
WinRealizePalette(hwnd, hps, &ulclr);
paint_bitmap(hps, &rect, nHscrollPos, nVscrollMax - nVscrollPos);
GpiSelectPalette(hps, (HPAL)NULL);
}
else
paint_bitmap(hps, &rect, nHscrollPos, nVscrollMax - nVscrollPos);
WinEndPaint(hwnd);
DosReleaseMutexSem(gsview.bmp_mutex);
return 0;
case WM_MOVE:
/* don't interrogate the window location immediately since */
/* it causes the Diamond Stealth VL24 with IBM S3 drivers */
/* to corrupt the display */
DosSleep(50);
if (hwnd_frame) {
SWP swp;
WinQueryWindowPos(WinQueryWindow(hwnd, QW_PARENT), &swp);
if (!(swp.fl & SWP_MINIMIZE)) {
if (!(swp.fl & SWP_MAXIMIZE)) {
option.img_origin.x = swp.x;
option.img_origin.y = swp.y;
}
option.img_max = ((swp.fl & SWP_MAXIMIZE) != 0);
}
}
break;
case WM_SIZE:
cyClient = SHORT2FROMMP(mp2);
cxClient = SHORT1FROMMP(mp2);
cyAdjust = min(bitmap.height, cyClient) - cyClient;
cyClient += cyAdjust;
nVscrollMax = max(0, bitmap.height - cyClient);
nVscrollPos = min(nVscrollPos, nVscrollMax);
scroll_pos.y = nVscrollMax - nVscrollPos;
if (!bitmap.valid)
cyClient = cyAdjust = nVscrollMax = nVscrollPos;
hwndScroll = WinWindowFromID(WinQueryWindow(hwnd, QW_PARENT), FID_VERTSCROLL);
WinSendMsg(hwndScroll, SBM_SETSCROLLBAR, MPFROMLONG(nVscrollPos),
MPFROM2SHORT(0, nVscrollMax));
if (bitmap.valid)
WinSendMsg(hwndScroll, SBM_SETTHUMBSIZE, MPFROM2SHORT(cyClient, bitmap.height),
MPFROMLONG(0));
else
WinSendMsg(hwndScroll, SBM_SETTHUMBSIZE, MPFROM2SHORT(1, 1),
MPFROMLONG(0));
cxAdjust = min(bitmap.width, cxClient) - cxClient;
cxClient += cxAdjust;
nHscrollMax = max(0, bitmap.width - cxClient);
nHscrollPos = min(nHscrollPos, nHscrollMax);
scroll_pos.x = nHscrollPos;
if (!bitmap.valid)
cxClient = cxAdjust = nHscrollMax = nHscrollPos;
hwndScroll = WinWindowFromID(WinQueryWindow(hwnd, QW_PARENT), FID_HORZSCROLL);
WinSendMsg(hwndScroll, SBM_SETSCROLLBAR, MPFROMLONG(nHscrollPos),
MPFROM2SHORT(0, nHscrollMax));
if (bitmap.valid)
WinSendMsg(hwndScroll, SBM_SETTHUMBSIZE, MPFROM2SHORT(cxClient, bitmap.width),
MPFROMLONG(0));
else
WinSendMsg(hwndScroll, SBM_SETTHUMBSIZE, MPFROM2SHORT(1, 1),
MPFROMLONG(0));
if ( option.fit_page && (cxAdjust!=0 || cyAdjust!=0) ) {
SWP swp;
/* don't interrogate the window location immediately since */
/* it causes the Diamond Stealth VL24 with IBM S3 drivers */
/* to corrupt the display */
DosSleep(50);
WinQueryWindowPos(WinQueryWindow(hwnd, QW_PARENT), &swp);
WinSetWindowPos(WinQueryWindow(hwnd, QW_PARENT), 0,
swp.x, swp.y - cyAdjust,
swp.cx + cxAdjust, swp.cy + cyAdjust, SWP_SIZE | SWP_MOVE);
cxAdjust = cyAdjust = 0;
}
display.offset.x = -cxAdjust/2;
display.offset.y = -cyAdjust/2;
if (hwnd_frame) {
SWP swp;
WinQueryWindowPos(WinQueryWindow(hwnd, QW_PARENT), &swp);
if (!(swp.fl & SWP_MINIMIZE)) {
if (!(swp.fl & SWP_MAXIMIZE)) {
option.img_size.x = swp.cx;
option.img_size.y = swp.cy;
}
option.img_max = ((swp.fl & SWP_MAXIMIZE) != 0);
}
}
break;
case WM_VSCROLL:
switch(SHORT2FROMMP(mp2)) {
case SB_LINEUP:
nVscrollInc = -cyClient/16;
break;
case SB_LINEDOWN:
nVscrollInc = cyClient/16;
break;
case SB_PAGEUP:
nVscrollInc = min(-1,-cyClient);
break;
case SB_PAGEDOWN:
nVscrollInc = max(1,cyClient);
break;
#ifdef NOTUSED
case SB_SLIDERTRACK:
/* only do this for fast redraw modes */
/* these are 8bit/pixel and 1bit/pixel */
if ( (bitmap.depth == 1) ||
((bitmap.depth == 8) && display.hasPalMan && display.hpal_exists) ) {
nVscrollInc = SHORT1FROMMP(mp2) - nVscrollPos;
}
else
nVscrollInc = 0;
#endif
case SB_SLIDERPOSITION:
nVscrollInc = SHORT1FROMMP(mp2) - nVscrollPos;
break;
case SB_TOP:
nVscrollInc = -nVscrollPos;
break;
case SB_BOTTOM:
nVscrollInc = nVscrollMax - nVscrollPos;
break;
default:
nVscrollInc = 0;
}
if ((nVscrollInc = max(-nVscrollPos,
min(nVscrollInc, nVscrollMax - nVscrollPos)))!=0) {
LONG lComplexity;
hwndScroll = WinWindowFromID(WinQueryWindow(hwnd, QW_PARENT), FID_VERTSCROLL);
nVscrollPos += nVscrollInc;
scroll_pos.y = nVscrollMax - nVscrollPos;
lComplexity = WinScrollWindow(hwnd, 0, nVscrollInc, (PRECTL)NULL, (PRECTL)NULL,
(HRGN)NULLHANDLE, (PRECTL)&rect, 0);
WinSendMsg(hwndScroll, SBM_SETPOS, MPFROMLONG(nVscrollPos), 0);
if (lComplexity != RGN_RECT) {
WinInvalidateRect(hwnd, (PRECTL)NULL, FALSE);
WinUpdateWindow(hwnd);
}
else {
/* redraw exposed area */
hps = WinGetPS(hwnd);
if ((bitmap.depth == 8) && display.hasPalMan && display.hpal_exists) {
GpiSelectPalette(hps, display.hpal);
WinRealizePalette(hwnd, hps, &ulclr);
paint_bitmap(hps, &rect, nHscrollPos, nVscrollMax - nVscrollPos);
GpiSelectPalette(hps, (HPAL)NULL);
}
else
paint_bitmap(hps, &rect, nHscrollPos, nVscrollMax - nVscrollPos);
WinReleasePS(hps);
}
}
break;
case WM_HSCROLL:
switch(SHORT2FROMMP(mp2)) {
case SB_LINELEFT:
nHscrollInc = -cxClient/16;
break;
case SB_LINERIGHT:
nHscrollInc = cyClient/16;
break;
case SB_PAGELEFT:
nHscrollInc = min(-1,-cxClient);
break;
case SB_PAGERIGHT:
nHscrollInc = max(1,cxClient);
break;
#ifdef NOTUSED
case SB_SLIDERTRACK:
/* only do this for fast redraw modes */
/* these are 8bit/pixel and 1bit/pixel */
if ( (bitmap.depth == 1) ||
((bitmap.depth == 8) && display.hasPalMan && display.hpal_exists) ) {
nHscrollInc = SHORT1FROMMP(mp2) - nHscrollPos;
}
else
nHscrollInc = 0;
#endif
case SB_SLIDERPOSITION:
nHscrollInc = SHORT1FROMMP(mp2) - nHscrollPos;
break;
default:
nHscrollInc = 0;
}
if ((nHscrollInc = max(-nHscrollPos,
min(nHscrollInc, nHscrollMax - nHscrollPos)))!=0) {
LONG lComplexity;
hwndScroll = WinWindowFromID(WinQueryWindow(hwnd, QW_PARENT), FID_HORZSCROLL);
nHscrollPos += nHscrollInc;
scroll_pos.x = nHscrollPos;
lComplexity = WinScrollWindow(hwnd, -nHscrollInc, 0, (PRECTL)NULL, (PRECTL)NULL,
(HRGN)NULLHANDLE, (PRECTL)&rect, 0);
/* need to send next message BEFORE redrawing, otherwise S3 driver screws up */
WinSendMsg(hwndScroll, SBM_SETPOS, MPFROMLONG(nHscrollPos), 0);
if (lComplexity != RGN_RECT) {
WinInvalidateRect(hwnd, (PRECTL)NULL, FALSE);
WinUpdateWindow(hwnd);
}
else {
/* redraw exposed area */
hps = WinGetPS(hwnd);
if ((bitmap.depth == 8) && display.hasPalMan && display.hpal_exists) {
GpiSelectPalette(hps, display.hpal);
WinRealizePalette(hwnd, hps, &ulclr);
paint_bitmap(hps, &rect, nHscrollPos, nVscrollMax - nVscrollPos);
GpiSelectPalette(hps, (HPAL)NULL);
}
else
paint_bitmap(hps, &rect, nHscrollPos, nVscrollMax - nVscrollPos);
WinReleasePS(hps);
}
}
break;
case WM_CHAR: /* process keystrokes here */
/* Process only key presses, not key releases */
if (SHORT1FROMMP(mp1) & KC_KEYUP)
break;
if (SHORT1FROMMP(mp1) & KC_VIRTUALKEY) {
USHORT vkey = SHORT2FROMMP(mp2);
switch(vkey) {
case VK_HOME:
WinSendMsg(hwnd, WM_VSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_TOP));
break;
case VK_END:
WinSendMsg(hwnd, WM_VSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_BOTTOM));
break;
case VK_UP:
WinSendMsg(hwnd, WM_VSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_LINEUP));
break;
case VK_DOWN:
WinSendMsg(hwnd, WM_VSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_LINEDOWN));
break;
case VK_PAGEUP:
if (SHORT1FROMMP(mp1) & KC_CTRL)
WinSendMsg(hwnd, WM_HSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_PAGELEFT));
else
WinSendMsg(hwnd, WM_VSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_PAGEUP));
break;
case VK_PAGEDOWN:
if (SHORT1FROMMP(mp1) & KC_CTRL)
WinSendMsg(hwnd, WM_HSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_PAGERIGHT));
else
WinSendMsg(hwnd, WM_VSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_PAGEDOWN));
break;
case VK_LEFT:
if (SHORT1FROMMP(mp1) & KC_CTRL)
WinSendMsg(hwnd, WM_HSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_PAGELEFT));
else
WinSendMsg(hwnd, WM_HSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_LINELEFT));
break;
case VK_RIGHT:
if (SHORT1FROMMP(mp1) & KC_CTRL)
WinSendMsg(hwnd, WM_HSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_PAGERIGHT));
else
WinSendMsg(hwnd, WM_HSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_LINERIGHT));
break;
}
}
case WM_BUTTON1DOWN:
if (hwnd_modeless)
WinPostMsg(hwnd_modeless, WM_COMMAND, MPFROMSHORT(BB_CLICK), MPFROMLONG(0));
break;
case WM_BUTTON2DOWN:
{ float x, y;
if (get_cursorpos(&x, &y)) {
zoom = !zoom;
display.zoom_xoffset = x;
display.zoom_yoffset = y;
x = (scroll_pos.x+cxClient/2)*72.0/option.xdpi;
y = (scroll_pos.y+cyClient/2)*72.0/option.ydpi;
transform_point(&x, &y);
x *= option.xdpi/72.0;
y *= option.ydpi/72.0;
display.zoom_xoffset -= (int)(x*72.0/option.zoom_xdpi);
display.zoom_yoffset -= (int)(y*72.0/option.zoom_ydpi);
}
else {
zoom = FALSE;
}
WinPostMsg(hwnd_bmp, WM_COMMAND, (MPARAM)IDM_ZOOM, MPFROMLONG(0));
}
break;
case WM_MOUSEMOVE:
/* track cursor and display coordinates */
hps = WinGetPS(hwnd_status);
WinFillRect(hps, &info_coord, SYSCLR_BUTTONMIDDLE);
cursorpos_paint(hps);
WinReleasePS(hps);
if (waiting)
WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE));
else {
if (!bitmap.valid)
break;
WinSetPointer(HWND_DESKTOP, hptr_crosshair);
}
return (MRESULT)TRUE; /* cursor has been changed */
case WM_CLOSE:
if (printer.prog.valid) {
load_string(IDS_PRINTBUSY, buf, sizeof(buf));
if (message_box(buf, MB_YESNO | MB_ICONQUESTION) != IDYES)
return (MRESULT)0;
}
break;
case DM_DRAGOVER:
return DragOver((PDRAGINFO)mp1);
case DM_DROP:
return Drop((PDRAGINFO)mp1);
}
/* All messages not handled by the ClientWndProc must be passed */
/* along to the Presentation Manager for default processing */
return WinDefWindowProc(hwnd, mess, mp1, mp2);
}
/* map from a coordinate in points, to a coordinate in pixels */
/* This is the opposite of the transform part of get_cursorpos */
/* Used when showing bbox */
void
map_pt_to_pixel(float *x, float *y)
{
if (zoom) {
/* WARNING - this doesn't cope with EPS Clip */
*x = (*x - display.zoom_xoffset) * option.zoom_xdpi / 72.0;
*y = (*y - display.zoom_yoffset) * option.zoom_ydpi / 72.0;
*x = (*x * 72.0 / option.xdpi);
*y = (*y * 72.0 / option.ydpi);
itransform_point(x, y);
*x = (*x * option.xdpi / 72.0) - scroll_pos.x + display.offset.x;
*y = (*y * option.ydpi / 72.0) - scroll_pos.y + display.offset.y;
}
else {
*x = *x - (display.epsf_clipped ? doc->boundingbox[LLX] : 0);
*y = *y - (display.epsf_clipped ? doc->boundingbox[LLY] : 0);
itransform_point(x, y);
*x = *x * option.xdpi/72.0
- scroll_pos.x + display.offset.x;
*y = *y * option.ydpi/72.0
- scroll_pos.y + display.offset.y;
}
}
/* return coordinates in pts from origin of page */
/* For Portrait, this is the bottom left */
/* For rotated pages, this is NOT the bottom left */
BOOL
get_cursorpos(float *x, float *y)
{
RECTL rect;
POINTL pt;
if (!bitmap.valid)
return FALSE;
if (!WinQueryPointerPos(HWND_DESKTOP, &pt))
return FALSE;
WinMapWindowPoints(HWND_DESKTOP, hwnd_bmp, &pt, 1);
WinQueryWindowRect(hwnd_bmp, &rect);
if (!WinPtInRect(hab, &rect, &pt))
return FALSE;
*x = scroll_pos.x+pt.x-display.offset.x;
*y = scroll_pos.y+pt.y-display.offset.y;
transform_cursorpos(x, y);
return TRUE;
}
void
cursorpos_paint(HPS hps)
{
float x, y;
POINTL pt;
char buf[64];
if (get_cursorpos(&x, &y)) {
switch(option.unit) {
case IDM_UNITPT:
sprintf(buf,"%.0f, %.0fpt", x, y);
break;
case IDM_UNITMM:
sprintf(buf,"%.0f, %.0fmm", x/72*25.4, y/72*25.4);
break;
case IDM_UNITINCH:
sprintf(buf,"%.1f, %.1fin", x/72, y/72);
break;
}
GpiSetTextAlignment(hps, TA_RIGHT, TA_NORMAL_VERT);
pt.x = info_coord.xRight - 1;
pt.y = info_page.y;
GpiCharStringAt(hps, &pt, strlen(buf), buf);
}
}
void
info_paint(HWND hwnd)
{
HPS ps;
RECTL rect;
POINTL pt;
int i;
char *p;
char buf[MAXSTR];
char fmt[MAXSTR];
ps = WinBeginPaint(hwnd, (ULONG)0, &rect);
/* draw background */
WinFillRect(ps, &rect, SYSCLR_BUTTONMIDDLE);
GpiSetColor(ps, SYSCLR_BUTTONDARK);
pt.x = 0; pt.y = 0;
GpiMove(ps, &pt);
pt.x = statusbar.x - 1;
GpiLine(ps, &pt);
pt.y = statusbar.y - 1;
GpiLine(ps, &pt);
GpiSetColor(ps, SYSCLR_BUTTONLIGHT);
pt.x = 0;
GpiLine(ps, &pt);
pt.y = 0;
GpiLine(ps, &pt);
GpiSetColor(ps, SYSCLR_BUTTONDEFAULT);
/* write file information */
if (psfile.name[0] != '\0') {
i = load_string(IDS_FILE, buf, sizeof(buf));
if ( (p = strrchr(psfile.name, '\\')) == (char *)NULL )
p = psfile.name;
else
p++;
strcat(buf, p);
GpiCharStringAt(ps, &info_file, strlen(buf), buf);
if (waiting) {
/*
i = load_string(IDS_WAIT, buf, sizeof(buf));
GpiCharStringAt(ps, &info_page, strlen(buf), buf);
*/
GpiCharStringAt(ps, &info_page, strlen(szWait), szWait);
}
else {
if (doc!=(PSDOC *)NULL) {
int n = map_page(psfile.pagenum - 1);
i = load_string(IDS_PAGEINFO, fmt, sizeof(fmt));
if (doc->pages)
sprintf(buf, fmt, doc->pages[n].label ? doc->pages[n].label : " ",psfile.pagenum, doc->numpages);
else
sprintf(buf, fmt, " " ,psfile.pagenum, doc->numpages);
if (zoom)
strcat(buf, " Zoomed");
GpiCharStringAt(ps, &info_page, strlen(buf), buf);
}
else {
if (is_pipe_done())
i = load_string(IDS_NOMORE, buf, sizeof(buf));
else {
i = load_string(IDS_PAGE, buf, sizeof(buf));
sprintf(buf+i, "%d", psfile.pagenum);
}
GpiCharStringAt(ps, &info_page, strlen(buf), buf);
}
/* show coordinate */
cursorpos_paint(ps);
}
}
else {
i = load_string(IDS_NOFILE, buf, sizeof(buf));
GpiCharStringAt(ps, &info_file, strlen(buf), buf);
if (waiting) {
/*
i = load_string(IDS_WAIT, buf, sizeof(buf));
GpiCharStringAt(ps, &info_page, strlen(buf), buf);
*/
GpiCharStringAt(ps, &info_page, strlen(szWait), szWait);
}
}
WinEndPaint(hwnd);
}
/* Status Bar Window Proc */
MRESULT EXPENTRY StatusWndProc(HWND hwnd, ULONG mess,
MPARAM mp1, MPARAM mp2)
{
HPS ps;
RECTL rect;
POINTL pt;
switch (mess) {
case WM_CREATE:
{
FONTMETRICS fm;
POINTL char_size;
ps = WinGetPS(hwnd);
GpiQueryFontMetrics(ps, sizeof(FONTMETRICS), &fm);
char_size.y = fm.lMaxAscender + fm.lMaxDescender + fm.lExternalLeading + 2;
char_size.x = fm.lAveCharWidth;
statusbar.y = char_size.y + 2;
info_file.x = 2;
info_file.y = fm.lMaxDescender + 3;
info_coord.xLeft = 23 * char_size.x;
info_coord.xRight = 38 * char_size.x;
info_coord.yTop = char_size.y - 1;
info_coord.yBottom = 1;
info_page.x = 40 * char_size.x + 2;
info_page.y = fm.lMaxDescender + 3;
/*
WinFillRect(ps, SYSCLR_BUTTONMIDDLE);
*/
WinReleasePS(ps);
}
break;
case WM_PAINT:
info_paint(hwnd);
return 0;
}
return WinDefWindowProc(hwnd, mess, mp1, mp2);
}
void
shade_button(HPS hps, struct button *bp, BOOL down)
{
POINTL pt;
/* draw button shading */
if (down)
GpiSetColor(hps, SYSCLR_BUTTONLIGHT);
else
GpiSetColor(hps, SYSCLR_BUTTONDARK);
pt.x = bp->rect.xLeft;
pt.y = bp->rect.yBottom;
GpiMove(hps, &pt);
pt.x = bp->rect.xRight - 1;
GpiLine(hps, &pt);
pt.y = bp->rect.yTop - 1;
GpiLine(hps, &pt);
if (down)
GpiSetColor(hps, SYSCLR_BUTTONDARK);
else
GpiSetColor(hps, SYSCLR_BUTTONLIGHT);
pt.x = bp->rect.xLeft;
GpiLine(hps, &pt);
pt.y = bp->rect.yBottom;
GpiLine(hps, &pt);
GpiSetColor(hps, SYSCLR_BUTTONDEFAULT);
}
void
size_buttons(PPOINTL ppt)
{
struct button *bp;
int i = 0;
if (option.button_show) {
for (bp = buttonhead; bp != (struct button *)NULL; bp = bp->next) {
bp->rect.xLeft = i * button_shift.x;
bp->rect.yBottom = ppt->y - button_size.y - i * button_shift.y;
bp->rect.xRight = bp->rect.xLeft + button_size.x;
bp->rect.yTop = bp->rect.yBottom + button_size.y;
i++;
}
}
}
/* Button Bar Window Proc */
MRESULT EXPENTRY ButtonWndProc(HWND hwnd, ULONG mess,
MPARAM mp1, MPARAM mp2)
{
HPS hps;
RECTL rect;
POINTL pt;
struct button *bp;
switch (mess) {
case WM_SIZE:
/* reposition buttons */
pt.x = SHORT1FROMMP(mp2);
pt.y = SHORT2FROMMP(mp2);
size_buttons(&pt);
WinInvalidateRect(hwnd, (PRECTL)NULL, FALSE);
break;
case WM_BUTTON1DOWN:
pt.x = SHORT1FROMMP(mp1);
pt.y = SHORT2FROMMP(mp1);
for (bp = buttonhead; bp != (struct button *)NULL; bp = bp->next) {
if (WinPtInRect(hab, &(bp->rect), &pt)) {
button_current = bp;
button_down = TRUE;
hps = WinGetPS(hwnd);
shade_button(hps, bp, TRUE);
WinReleasePS(hps);
WinSetCapture(HWND_DESKTOP, hwnd);
break;
}
}
break;
case WM_BUTTON1UP:
pt.x = SHORT1FROMMP(mp1);
pt.y = SHORT2FROMMP(mp1);
bp = button_current;
if (bp != (struct button *)NULL) {
hps = WinGetPS(hwnd);
shade_button(hps, bp, FALSE);
WinReleasePS(hps);
if (WinPtInRect(hab, &(bp->rect), &pt)) {
WinPostMsg(hwnd_bmp, WM_COMMAND, MPFROMSHORT(bp->id), MPFROMLONG(0));
}
}
WinSetCapture(HWND_DESKTOP, NULLHANDLE);
WinInvalidateRect(hwnd_status, NULL, FALSE);
WinUpdateWindow(hwnd_status);
button_info = NULL;
button_current = NULL;
button_down = FALSE;
break;
case WM_MOUSEMOVE:
pt.x = SHORT1FROMMP(mp1);
pt.y = SHORT2FROMMP(mp1);
bp = button_current;
if (bp != (struct button *)NULL) {
if (button_down && !WinPtInRect(hab, &(bp->rect), &pt)) {
button_down = FALSE;
hps = WinGetPS(hwnd);
shade_button(hps, bp, FALSE);
WinReleasePS(hps);
}
else if (!button_down && WinPtInRect(hab, &(bp->rect), &pt)) {
button_down = TRUE;
hps = WinGetPS(hwnd);
shade_button(hps, bp, TRUE);
WinReleasePS(hps);
}
}
else {
/* track cursor and display button function */
char buf[64];
/* find button */
for (bp = buttonhead; bp != (struct button *)NULL; bp = bp->next) {
if (WinPtInRect(hab, &(bp->rect), &pt)) {
break;
}
}
if (bp != button_info) {
button_info = bp;
if (bp != (struct button *)NULL) {
if (WinQueryCapture(HWND_DESKTOP) != hwnd)
WinSetCapture(HWND_DESKTOP, hwnd); /* track all mouse movements */
/* erase page area of status bar */
hps = WinGetPS(hwnd_status);
rect.xLeft = info_file.x;
rect.xRight = statusbar.x - 1;
rect.yBottom = info_coord.yBottom;
rect.yTop = info_coord.yTop;
WinFillRect(hps, &rect, SYSCLR_BUTTONMIDDLE);
load_string(bp->id, buf, sizeof(buf));
GpiCharStringAt(hps, &info_file, strlen(buf), buf);
WinReleasePS(hps);
}
else {
WinSetCapture(HWND_DESKTOP, NULLHANDLE); /* release capture */
/* put statusbar back to normal */
WinInvalidateRect(hwnd_status, NULL, FALSE);
WinUpdateWindow(hwnd_status);
}
}
}
break;
case WM_PAINT:
hps = WinBeginPaint(hwnd, (ULONG)0, &rect);
/* draw background */
WinFillRect(hps, &rect, SYSCLR_BUTTONMIDDLE);
GpiSetColor(hps, SYSCLR_BUTTONDARK);
pt.x = buttonbar.x - 1; pt.y = 0;
GpiMove(hps, &pt);
pt.y = buttonbar.y - 1;
GpiLine(hps, &pt);
GpiSetColor(hps, SYSCLR_BUTTONLIGHT);
pt.x = 0;
GpiLine(hps, &pt);
pt.y = 0;
GpiLine(hps, &pt);
GpiSetColor(hps, SYSCLR_BUTTONDEFAULT);
for (bp = buttonhead; bp != (struct button *)NULL; bp = bp->next) {
if (bp->hbitmap) {
/* draw bitmap */
pt.x = bp->rect.xLeft;
pt.y = bp->rect.yBottom;
WinDrawBitmap(hps, bp->hbitmap, NULL, &pt, 0, 0, DBM_NORMAL);
}
else {
/* draw button text */
pt.x = (bp->rect.xLeft + bp->rect.xRight)/2;
pt.y = (bp->rect.yBottom + bp->rect.yTop)/2;
GpiSetTextAlignment(hps, TA_CENTER, TA_HALF);
GpiCharStringAt(hps, &pt, strlen(bp->str), bp->str);
}
shade_button(hps, bp, FALSE);
}
WinEndPaint(hwnd);
return 0;
}
return WinDefWindowProc(hwnd, mess, mp1, mp2);
}
/* subclassed Frame Window Procedure */
MRESULT EXPENTRY FrameWndProc(HWND hwnd, ULONG mess,
MPARAM mp1, MPARAM mp2)
{
MRESULT mr;
int sCount;
PSWP pswpNew, pswpClient, pswp;
switch(mess) {
case WM_HELP:
/* HM_DISPLAY_HELP is unreliable for HM_PANELNAME so we lookup */
/* the id ourselves and use HM_RESOURCEID */
{
HELPIDX *hidx;
for (hidx = helpidx; hidx->id != 0; hidx++) {
if (strcmp(hidx->name, szHelpTopic)==0) {
WinSendMsg(hwnd_help, HM_DISPLAY_HELP, MPFROMSHORT(hidx->id), MPFROMSHORT(HM_RESOURCEID));
continue;
}
}
}
return 0;
case WM_CALCFRAMERECT:
mr = (*OldFrameWndProc)(hwnd, mess, mp1, mp2);
/* calculate position of client rectangle */
if (mr && mp2) {
((PRECTL)mp1)->yTop -= statusbar.y;
if (option.button_show)
((PRECTL)mp1)->xLeft += buttonbar.x;
}
return mr;
case WM_FORMATFRAME:
/* reformat frame to make room for status bar */
mr = (*OldFrameWndProc)(hwnd, mess, mp1, mp2);
sCount = (int)mr;
pswp = (PSWP)mp1;
pswpClient = (PSWP)mp1 + sCount - 1;
pswpNew = pswpClient + 1;
*pswpNew = *pswpClient;
pswpNew->hwnd = WinWindowFromID(hwnd, ID_STATUSBAR);
pswpNew->cy = statusbar.y;
pswpClient->cy -= pswpNew->cy;
pswpNew->y = pswpClient->y + pswpClient->cy;
pswp[FID_VERTSCROLL - FID_SYSMENU].cy -= pswpNew->cy;
pswpNew->x = pswp[FID_MENU - FID_SYSMENU].x;
pswpNew->cx = pswp[FID_MENU - FID_SYSMENU].cx;
statusbar.x = pswpNew->cx;
sCount++;
/* reformat frame to make room for button bar */
pswpNew++;
*pswpNew = *pswpClient;
pswpNew->hwnd = WinWindowFromID(hwnd, ID_BUTTONBAR);
pswpNew->x = pswpClient->x;
pswpNew->cx = buttonbar.x;
pswpNew->y = pswpClient->y;
pswpNew->cy = pswpClient->cy;
buttonbar.y = pswpNew->cy;
pswpNew->fl &= ~(SWP_SHOW | SWP_HIDE);
sCount++;
if (option.button_show) {
pswpClient->x += buttonbar.x;
pswpClient->cx -= buttonbar.x;
pswpNew->fl |= SWP_SHOW;
/* following is a kludge because ButtonWndProc is receiving WM_SIZE
messages in reverse order to WM_FORMATFRAME here! */
WinPostMsg(hwnd_button, WM_SIZE,
MPFROM2SHORT(pswpNew->cx, pswpNew->cy),
MPFROM2SHORT(pswpNew->cx, pswpNew->cy));
}
else {
pswpNew->fl |= SWP_HIDE;
}
return (MRESULT)sCount;
case WM_QUERYFRAMECTLCOUNT:
mr = (*OldFrameWndProc)(hwnd, mess, mp1, mp2);
sCount = (int)mr;
sCount+=2;
return (MRESULT)sCount;
}
return (*OldFrameWndProc)(hwnd, mess, mp1, mp2);
}
MRESULT
DragOver(PDRAGINFO pDragInfo)
{
int cItems, i;
PDRAGITEM pditem;
USHORT usDrop, usDefaultOp;
char dtype[256];
char drmf[256];
if (!DrgAccessDraginfo(pDragInfo))
return MRFROM2SHORT(DOR_NODROPOP, 0);
switch(pDragInfo->usOperation) {
case DO_DEFAULT:
case DO_COPY:
usDrop = DOR_DROP;
usDefaultOp = DO_COPY;
break;
default:
case DO_UNKNOWN:
case DO_MOVE:
DrgFreeDraginfo(pDragInfo);
return MRFROM2SHORT(DOR_NODROPOP, 0);
}
cItems = DrgQueryDragitemCount(pDragInfo);
for (i=0; i<cItems; i++) {
pditem = DrgQueryDragitemPtr(pDragInfo, i);
DrgQueryStrName(pditem->hstrType, sizeof(dtype)-1, dtype);
DrgQueryStrName(pditem->hstrRMF, sizeof(drmf)-1, drmf);
if (pditem->fsSupportedOps & DO_COPYABLE) {
if ( DrgVerifyRMF(pditem, "DRM_OS2FILE", "DRF_TEXT") )
usDrop = DOR_DROP;
else
usDrop = DOR_NEVERDROP;
}
else {
usDrop = DOR_NODROPOP;
}
}
DrgFreeDraginfo(pDragInfo);
return MRFROM2SHORT(usDrop, usDefaultOp);
}
MRESULT
Drop(PDRAGINFO pDragInfo)
{
int cItems, i;
DRAGITEM dragitem;
USHORT usDrop, usDefaultOp;
char dirname[MAXSTR];
char filename[MAXSTR];
char *dragname;
int length;
HPS hps;
POINTL pt;
if (!DrgAccessDraginfo(pDragInfo))
return MRFROM2SHORT(DOR_NODROPOP, 0);
cItems = DrgQueryDragitemCount(pDragInfo);
for (i=0; i<cItems; i++) {
DrgQueryDragitem(pDragInfo, sizeof(dragitem), &dragitem, i);
length = DrgQueryStrName(dragitem.hstrContainerName, sizeof(dirname), dirname);
length += DrgQueryStrName(dragitem.hstrSourceName, sizeof(filename), filename);
dragname = malloc(length+1);
strcpy(dragname, dirname);
strcat(dragname, filename);
WinPostMsg(hwnd_bmp, WM_COMMAND, (MPARAM)IDM_DROP, MPFROMP(dragname)); /* mp2 is not strictly correct */
}
DrgDeleteDraginfoStrHandles(pDragInfo);
DrgFreeDraginfo(pDragInfo);
return (MRESULT)0;
}