mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1423 lines
42 KiB
1423 lines
42 KiB
/*
|
|
Enhanced NCSA Mosaic from Spyglass
|
|
"Guitar"
|
|
|
|
Copyright 1994 Spyglass, Inc.
|
|
All Rights Reserved
|
|
|
|
Author(s):
|
|
Albert Lee [email protected]
|
|
*/
|
|
|
|
#ifdef FEATURE_IMAGE_VIEWER
|
|
|
|
#include "all.h"
|
|
|
|
DCL_WinProc(Viewer_DlgProc);
|
|
|
|
extern HPALETTE hPalGuitar;
|
|
|
|
static BOOL bInitialized = FALSE;
|
|
static struct hash_table gViewerCache;
|
|
static TCHAR Viewer_achClassName[MAX_WC_CLASSNAME];
|
|
|
|
#ifdef _GIBRALTAR
|
|
//
|
|
// Determine if the given file name has
|
|
// the given extention. The szExtent string
|
|
// is not case-sensitive.
|
|
//
|
|
BOOL
|
|
HasExtention(
|
|
char * szFile,
|
|
const char * szExtent
|
|
)
|
|
{
|
|
char * pch = strrchr(szFile, '.');
|
|
if (pch)
|
|
{
|
|
char szEx[_MAX_PATH + 1];
|
|
strcpy(szEx, pch);
|
|
return (!GTR_strcmpi(szEx, szExtent));
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#endif // _GIBRALTAR
|
|
|
|
|
|
static void SetClientWidth(HWND hwnd, int width)
|
|
{
|
|
RECT rect, clientrect;
|
|
|
|
GetWindowRect(hwnd, &rect);
|
|
GetClientRect(hwnd, &clientrect);
|
|
|
|
SetWindowPos(hwnd, NULL, 0, 0,
|
|
width + (rect.right - rect.left) - clientrect.right,
|
|
rect.bottom - rect.top,
|
|
SWP_NOMOVE | SWP_NOZORDER);
|
|
}
|
|
|
|
static void SetClientHeight(HWND hwnd, int height)
|
|
{
|
|
RECT rect, clientrect;
|
|
|
|
GetWindowRect(hwnd, &rect);
|
|
GetClientRect(hwnd, &clientrect);
|
|
|
|
SetWindowPos(hwnd, NULL, 0, 0,
|
|
rect.right - rect.left,
|
|
height + (rect.bottom - rect.top) - clientrect.bottom,
|
|
SWP_NOMOVE | SWP_NOZORDER);
|
|
}
|
|
|
|
static void CreateWindowsBitmap(HWND hwnd, struct ViewerInfo *pViewerInfo)
|
|
{
|
|
HDC hDC;
|
|
HPALETTE hOld;
|
|
|
|
hDC = GetDC(hwnd);
|
|
|
|
switch(pViewerInfo->pbmi->bmiHeader.biBitCount)
|
|
{
|
|
case 8:
|
|
if (wg.eColorMode == 8)
|
|
{
|
|
hOld = SelectPalette(hDC, hPalGuitar, FALSE);
|
|
RealizePalette(hDC);
|
|
}
|
|
|
|
pViewerInfo->hBitmap = CreateDIBitmap(hDC, (const BITMAPINFOHEADER *) pViewerInfo->pbmi,
|
|
CBM_INIT, pViewerInfo->gw, pViewerInfo->pbmi, DIB_PAL_COLORS);
|
|
|
|
if (wg.eColorMode == 8)
|
|
SelectPalette(hDC, hOld, FALSE);
|
|
break;
|
|
|
|
default:
|
|
pViewerInfo->hBitmap = CreateDIBitmap(hDC, (const BITMAPINFOHEADER *) pViewerInfo->pbmi,
|
|
CBM_INIT, pViewerInfo->gw, pViewerInfo->pbmi, DIB_RGB_COLORS);
|
|
break;
|
|
}
|
|
|
|
ReleaseDC(hwnd, hDC);
|
|
}
|
|
|
|
static void Viewer_DoImageFile(struct ViewerInfo *pvi, const char *pszURL)
|
|
{
|
|
int ndx, i, newleft, newtop, bottom, right;
|
|
void *pImage;
|
|
FILE *fp;
|
|
long imagesize, imagewidth, imageheight, transparent;
|
|
unsigned char *pDIB;
|
|
RGBQUAD colors[256];
|
|
LOGPALETTE *lp;
|
|
HPALETTE hPalette = NULL;
|
|
PBITMAPINFO pbmi = NULL;
|
|
RECT rect;
|
|
int scrollwidth, scrollheight, captionheight;
|
|
int borderheight, borderwidth, screenwidth, screenheight;
|
|
HWND hDlg;
|
|
struct Mwin *tw;
|
|
BOOL bMoveWindow;
|
|
|
|
ndx = Hash_FindOrAdd(&gViewerCache, (char *) pszURL, NULL, pvi);
|
|
|
|
// read the image file into memory
|
|
|
|
fp = fopen(pvi->fsOrig, "rb");
|
|
if (!fp)
|
|
return;
|
|
|
|
fseek(fp, 0, SEEK_END);
|
|
imagesize = ftell(fp);
|
|
|
|
pImage = GTR_MALLOC(imagesize);
|
|
if (!pImage)
|
|
{
|
|
ERR_ReportError(pvi->original_tw, SID_ERR_OUT_OF_MEMORY, NULL, NULL);
|
|
fclose(fp);
|
|
return;
|
|
}
|
|
|
|
fseek(fp, 0, SEEK_SET);
|
|
fread(pImage, 1, imagesize, fp);
|
|
fclose(fp);
|
|
|
|
// Create the bitmap
|
|
|
|
switch(pvi->format)
|
|
{
|
|
case VIEWER_GIF:
|
|
pDIB = ReadGIF(pImage, imagesize, &imagewidth, &imageheight, colors, &transparent);
|
|
if (pDIB)
|
|
{
|
|
pbmi = (BITMAPINFO *) pDIB;
|
|
|
|
lp = GTR_MALLOC(sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256);
|
|
lp->palVersion = 0x300;
|
|
lp->palNumEntries = 256;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
lp->palPalEntry[i].peRed = colors[i].rgbRed;
|
|
lp->palPalEntry[i].peGreen = colors[i].rgbGreen;
|
|
lp->palPalEntry[i].peBlue = colors[i].rgbBlue;
|
|
lp->palPalEntry[i].peFlags = 0;
|
|
}
|
|
|
|
hPalette = CreatePalette(lp);
|
|
|
|
GTR_FREE(lp);
|
|
|
|
// Dither if necessary
|
|
|
|
switch(wg.eColorMode)
|
|
{
|
|
case 8:
|
|
#if 0 /* TODO: can drop this soon. GIF code now does the dithering */
|
|
pbmi = BIT_Make_DIB_PAL_Header(imagewidth, imageheight, pDIB, hPalette, transparent);
|
|
#endif
|
|
pbmi = BIT_Make_DIB_PAL_Header_Prematched(imagewidth, imageheight, pDIB, 0);
|
|
break;
|
|
|
|
default:
|
|
pbmi = BIT_Make_DIB_RGB_Header_Screen(imagewidth, imageheight, pDIB, hPalette, transparent, 0);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VIEWER_JFIF:
|
|
|
|
switch(wg.eColorMode)
|
|
{
|
|
case 4:
|
|
pDIB = ReadJPEG_Dithered_VGA(pImage, imagesize, &imagewidth, &imageheight);
|
|
pbmi = BIT_Make_DIB_RGB_Header_VGA(imagewidth, imageheight, pDIB);
|
|
break;
|
|
|
|
case 8:
|
|
pDIB = ReadJPEG_Dithered(pImage, imagesize, &imagewidth, &imageheight);
|
|
pbmi = BIT_Make_DIB_PAL_Header_Prematched(imagewidth, imageheight, pDIB, 0);
|
|
break;
|
|
|
|
default:
|
|
pDIB = ReadJPEG_RGB(pImage, imagesize, &imagewidth, &imageheight);
|
|
pbmi = BIT_Make_DIB_RGB_Header_24BIT(imagewidth, imageheight, pDIB);
|
|
break;
|
|
}
|
|
|
|
transparent = -1; /* JPEGs are never transparent */
|
|
|
|
break;
|
|
}
|
|
|
|
GTR_FREE(pImage);
|
|
if (hPalette)
|
|
DeleteObject(hPalette);
|
|
|
|
if (!pbmi || !pDIB)
|
|
{
|
|
ERR_ReportError(pvi->original_tw, SID_ERR_INVALID_IMAGE_FORMAT, NULL, NULL);
|
|
return;
|
|
}
|
|
|
|
// Create the window
|
|
|
|
pvi->gw = pDIB;
|
|
pvi->nWidth = (short) imagewidth;
|
|
pvi->nHeight = (short) imageheight;
|
|
pvi->bInitialized = FALSE;
|
|
pvi->horz = 0;
|
|
pvi->vert = 0;
|
|
pvi->pbmi = pbmi;
|
|
pvi->transparent = transparent;
|
|
|
|
GTR_strncpy(pvi->szURL, pszURL, MAX_URL_STRING);
|
|
|
|
/* Do NOT change the initial creation size here. We create an
|
|
arbitrarily large window so that Windows can reduce the window
|
|
size if necessary. Growing the window to fit an image is
|
|
very buggy (reducing the window is not) */
|
|
|
|
#ifdef _GIBRALTAR
|
|
hDlg = CreateWindow(Viewer_achClassName, "",
|
|
WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_HSCROLL | WS_VSCROLL,
|
|
CW_USEDEFAULT, CW_USEDEFAULT, 1500, 1500, wg.hwndMainFrame, NULL,
|
|
wg.hInstance, NULL);
|
|
#else
|
|
hDlg = CreateWindow(Viewer_achClassName, "",
|
|
WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
|
|
CW_USEDEFAULT, CW_USEDEFAULT, 1500, 1500, wg.hWndHidden, NULL,
|
|
wg.hInstance, NULL);
|
|
#endif // _GIBRALTAR
|
|
|
|
if (!hDlg)
|
|
return;
|
|
pvi->hwnd = hDlg;
|
|
|
|
SetWindowLong(hDlg, 0, (LONG) pvi);
|
|
|
|
pvi->tw->hWndFrame = hDlg;
|
|
|
|
CreateWindowsBitmap(hDlg, pvi);
|
|
|
|
SetWindowText(hDlg, (char *) MB_GetWindowNameFromURL((unsigned char *) pszURL));
|
|
|
|
// Set up some variables
|
|
|
|
// Always keep around the scrollbars (it's MUCH easier that way) since it is
|
|
// consistent with the Mac image viewer implementation.
|
|
// Remember that scrollbars are always present.
|
|
|
|
scrollwidth = GetSystemMetrics(SM_CXVSCROLL);
|
|
scrollheight = GetSystemMetrics(SM_CYHSCROLL);
|
|
borderheight = GetSystemMetrics(SM_CYFRAME);
|
|
borderwidth = GetSystemMetrics(SM_CXFRAME);
|
|
captionheight = GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
|
|
screenwidth = GetSystemMetrics(SM_CXFULLSCREEN);
|
|
screenheight = GetSystemMetrics(SM_CYFULLSCREEN);
|
|
|
|
XX_DMsg(DBG_MM, ("Viewer: image width = %d\n", imagewidth));
|
|
XX_DMsg(DBG_MM, ("Viewer: image height = %d\n", imageheight));
|
|
XX_DMsg(DBG_MM, ("Viewer: scroll width = %d\n", scrollwidth));
|
|
XX_DMsg(DBG_MM, ("Viewer: scroll height = %d\n", scrollheight));
|
|
|
|
// Move the window to be cascaded from the most recently active window
|
|
|
|
tw = TW_FindTopmostWindow();
|
|
if (tw)
|
|
{
|
|
GetWindowRect(tw->hWndFrame, &rect);
|
|
newleft = rect.left + GetSystemMetrics(SM_CXSIZE) + borderwidth;
|
|
newtop = rect.top + GetSystemMetrics(SM_CYSIZE) + borderheight;
|
|
|
|
SetWindowPos(hDlg, NULL, newleft, newtop, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
|
|
}
|
|
|
|
// Resize the window to fit the image
|
|
|
|
pvi->bInitialized = TRUE;
|
|
|
|
GetClientRect(hDlg, &rect);
|
|
|
|
// Reduce the rectangle size by the scrollbar size
|
|
|
|
MapWindowPoints(hDlg, NULL, (LPPOINT) &rect, 2);
|
|
newleft = rect.left;
|
|
newtop = rect.top;
|
|
|
|
right = rect.left + imagewidth + scrollwidth + 2 * borderwidth - 1;
|
|
bottom = rect.top + imageheight + scrollheight + 2 * borderheight + captionheight - 2;
|
|
bMoveWindow = FALSE;
|
|
|
|
if (right > screenwidth)
|
|
{
|
|
newleft = max(0, newleft - (right - screenwidth));
|
|
bMoveWindow = TRUE;
|
|
}
|
|
|
|
if (bottom > screenheight)
|
|
{
|
|
newtop = max(0, newtop - (bottom - screenheight));
|
|
bMoveWindow = TRUE;
|
|
}
|
|
|
|
if (bMoveWindow)
|
|
SetWindowPos(hDlg, NULL, newleft, newtop, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
|
|
|
|
if (newleft > 0)
|
|
{
|
|
EnableScrollBar(hDlg, SB_HORZ, ESB_DISABLE_BOTH);
|
|
SetClientWidth(hDlg, imagewidth);
|
|
}
|
|
else
|
|
SetClientWidth(hDlg, screenwidth - 2 * borderwidth);
|
|
|
|
UpdateWindow(hDlg);
|
|
|
|
if (newtop > 0)
|
|
{
|
|
EnableScrollBar(hDlg, SB_VERT, ESB_DISABLE_BOTH);
|
|
SetClientHeight(hDlg, imageheight);
|
|
}
|
|
else
|
|
SetClientHeight(hDlg, screenheight - 2 * borderheight - captionheight + 2);
|
|
|
|
ShowWindow(hDlg, SW_SHOW);
|
|
}
|
|
|
|
BOOL Viewer_ShowCachedFile(const char *pszURL)
|
|
{
|
|
char *pURL;
|
|
struct ViewerInfo *pViewerInfo;
|
|
|
|
if (!bInitialized)
|
|
return FALSE;
|
|
|
|
// Check if a window with the given URL exists
|
|
|
|
if (Hash_Find(&gViewerCache, (char *) pszURL, &pURL, &pViewerInfo) != -1)
|
|
{
|
|
if (IsWindow(pViewerInfo->hwnd))
|
|
{
|
|
/* If the window exists then check its enabled status. If it is
|
|
not enabled, it means that the error dialog is up. In this
|
|
case, let the error dialog become active. */
|
|
|
|
if (IsWindowEnabled(pViewerInfo->hwnd))
|
|
TW_RestoreWindow(pViewerInfo->hwnd);
|
|
else
|
|
TW_EnableModalChild(pViewerInfo->hwnd);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void Viewer_Callback(void *param, const char *szURL, BOOL bAbort)
|
|
{
|
|
struct ViewerInfo *pvi;
|
|
|
|
pvi = (struct ViewerInfo *)param;
|
|
if (bAbort)
|
|
{
|
|
GTR_FREE(pvi->fsOrig);
|
|
GTR_FREE(pvi->tw);
|
|
GTR_FREE(pvi);
|
|
return;
|
|
}
|
|
|
|
if (pvi->original_tw->SDI_url)
|
|
GHist_Add(pvi->original_tw->SDI_url, (char *) szURL, time(NULL));
|
|
else
|
|
GHist_Add((char *) szURL, (char *) szURL, time(NULL));
|
|
|
|
switch (pvi->format)
|
|
{
|
|
case VIEWER_GIF:
|
|
case VIEWER_JFIF:
|
|
Viewer_DoImageFile(pvi, szURL);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Viewer_RegisterClass(void)
|
|
{
|
|
WNDCLASS wc;
|
|
ATOM a;
|
|
|
|
sprintf(Viewer_achClassName, "%s_Viewer", vv_Application);
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
wc.lpfnWndProc = Viewer_DlgProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = sizeof(LPVOID);
|
|
wc.hInstance = wg.hInstance;
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
|
|
#ifdef _GIBRALTAR
|
|
wc.hIcon = NULL;
|
|
#else
|
|
wc.hIcon = LoadIcon(wg.hInstance, MAKEINTRESOURCE(RES_ICO_FRAME));
|
|
#endif // _GIBRALTAR
|
|
|
|
wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1);
|
|
wc.lpszMenuName = MAKEINTRESOURCE(RES_MENU_IMAGE_VIEWER);
|
|
wc.lpszClassName = Viewer_achClassName;
|
|
|
|
a = RegisterClass(&wc);
|
|
}
|
|
|
|
HTStream *Viewer_Present(struct Mwin *tw, HTRequest *request, void *param, HTFormat input_format, HTFormat output_format, HTStream *output_stream)
|
|
{
|
|
struct ViewerInfo *pvi;
|
|
HTStream *me;
|
|
enum viewer_formats format;
|
|
char path[_MAX_PATH + 1];
|
|
|
|
if (!bInitialized)
|
|
{
|
|
Hash_Init(&gViewerCache);
|
|
Viewer_RegisterClass();
|
|
bInitialized = TRUE;
|
|
}
|
|
|
|
if (input_format == HTAtom_for("image/gif"))
|
|
format = VIEWER_GIF;
|
|
else if (input_format == HTAtom_for("image/jpeg"))
|
|
format = VIEWER_JFIF;
|
|
else
|
|
format = VIEWER_INVALID;
|
|
|
|
if (format == VIEWER_INVALID)
|
|
{
|
|
/* This shouldn't happen unless our conversions are set
|
|
incorrectly in htinit.c. */
|
|
return NULL;
|
|
}
|
|
|
|
pvi = (struct ViewerInfo *) GTR_MALLOC(sizeof(struct ViewerInfo));
|
|
memset(pvi, 0, sizeof(struct ViewerInfo));
|
|
pvi->fsOrig = GTR_MALLOC(_MAX_PATH + 1);
|
|
pvi->tw = GTR_MALLOC(sizeof(struct Mwin));
|
|
pvi->original_tw = tw;
|
|
|
|
pvi->format = format;
|
|
|
|
if (request->szLocalFileName)
|
|
{
|
|
request->savefile = NULL;
|
|
request->nosavedlg = TRUE;
|
|
strcpy(pvi->fsOrig, request->szLocalFileName);
|
|
pvi->bNoDeleteFile = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Get a temporary file name to pass to SaveLocally
|
|
|
|
path[0] = 0;
|
|
PREF_GetTempPath(_MAX_PATH, path);
|
|
GetTempFileName(path, "A", 0, pvi->fsOrig);
|
|
|
|
request->nosavedlg = TRUE;
|
|
request->savefile = pvi->fsOrig;
|
|
pvi->bNoDeleteFile = FALSE;
|
|
}
|
|
|
|
me = HTSaveWithCallback(tw, request, pvi, input_format, Viewer_Callback);
|
|
|
|
return me;
|
|
}
|
|
|
|
void Viewer_RedisplayImage(HWND hwnd, HDC hDC, struct ViewerInfo *pViewerInfo)
|
|
{
|
|
BOOL bReleaseDC = FALSE;
|
|
HPALETTE hOldPal;
|
|
RECT rect;
|
|
|
|
if (!hDC)
|
|
{
|
|
hDC = GetDC(pViewerInfo->hwnd);
|
|
bReleaseDC = TRUE;
|
|
}
|
|
|
|
rect.left = -pViewerInfo->horz;
|
|
rect.top = -pViewerInfo->vert;
|
|
rect.right = -pViewerInfo->horz + pViewerInfo->nWidth;
|
|
rect.bottom = -pViewerInfo->vert + pViewerInfo->nHeight;
|
|
|
|
switch(wg.eColorMode)
|
|
{
|
|
case 8:
|
|
hOldPal = SelectPalette(hDC, hPalGuitar, FALSE);
|
|
|
|
GTR_StretchDIBits(NULL, hDC, rect, 0,
|
|
0, 0, pViewerInfo->nWidth, pViewerInfo->nHeight,
|
|
pViewerInfo->gw, pViewerInfo->pbmi, DIB_PAL_COLORS,
|
|
SRCCOPY, pViewerInfo->transparent);
|
|
|
|
//SetDIBitsToDevice(hDC, -pViewerInfo->horz, -pViewerInfo->vert, pViewerInfo->nWidth,
|
|
// pViewerInfo->nHeight, 0, 0, 0, pViewerInfo->nHeight, pViewerInfo->gw, pViewerInfo->pbmi, DIB_PAL_COLORS);
|
|
|
|
SelectObject(hDC, hOldPal);
|
|
break;
|
|
|
|
default:
|
|
GTR_StretchDIBits(NULL, hDC, rect, 0,
|
|
0, 0, pViewerInfo->nWidth, pViewerInfo->nHeight,
|
|
pViewerInfo->gw, pViewerInfo->pbmi, DIB_RGB_COLORS,
|
|
SRCCOPY, pViewerInfo->transparent);
|
|
break;
|
|
|
|
//SetDIBitsToDevice(hDC, -pViewerInfo->horz, -pViewerInfo->vert, pViewerInfo->nWidth, pViewerInfo->nHeight,
|
|
// 0, 0, 0, pViewerInfo->nHeight, pViewerInfo->gw, pViewerInfo->pbmi, DIB_RGB_COLORS);
|
|
}
|
|
|
|
if (bReleaseDC)
|
|
ReleaseDC(pViewerInfo->hwnd, hDC);
|
|
}
|
|
|
|
void Viewer_HorzScroll(struct ViewerInfo *pViewerInfo, int code, int pos)
|
|
{
|
|
int minpos, maxpos;
|
|
RECT rect;
|
|
|
|
GetClientRect(pViewerInfo->hwnd, &rect);
|
|
GetScrollRange(pViewerInfo->hwnd, SB_HORZ, &minpos, &maxpos);
|
|
|
|
if (rect.right >= pViewerInfo->nWidth)
|
|
return;
|
|
|
|
if (wg.iWindowsMajorVersion >= 4)
|
|
maxpos = pViewerInfo->nWidth - rect.right;
|
|
|
|
switch (code)
|
|
{
|
|
case SB_LINEUP:
|
|
if (pViewerInfo->horz == minpos)
|
|
return;
|
|
pViewerInfo->horz -=
|
|
max((int) (VIEWER_LINESCROLL_AMOUNT * (pViewerInfo->nWidth - rect.right)), 1);
|
|
pViewerInfo->horz = max(pViewerInfo->horz, minpos);
|
|
SetScrollPos(pViewerInfo->hwnd, SB_HORZ, pViewerInfo->horz, TRUE);
|
|
Viewer_RedisplayImage(pViewerInfo->hwnd, NULL, pViewerInfo);
|
|
break;
|
|
|
|
case SB_LINEDOWN:
|
|
if (pViewerInfo->horz == maxpos)
|
|
return;
|
|
pViewerInfo->horz +=
|
|
max((int) (VIEWER_LINESCROLL_AMOUNT * (pViewerInfo->nWidth - rect.right)), 1);
|
|
pViewerInfo->horz = min(pViewerInfo->horz, maxpos);
|
|
SetScrollPos(pViewerInfo->hwnd, SB_HORZ, pViewerInfo->horz, TRUE);
|
|
Viewer_RedisplayImage(pViewerInfo->hwnd, NULL, pViewerInfo);
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
if (pViewerInfo->horz == minpos)
|
|
return;
|
|
pViewerInfo->horz -=
|
|
max((int) (VIEWER_PAGESCROLL_AMOUNT * (pViewerInfo->nWidth - rect.right)), 1);
|
|
pViewerInfo->horz = max(pViewerInfo->horz, minpos);
|
|
SetScrollPos(pViewerInfo->hwnd, SB_HORZ, pViewerInfo->horz, TRUE);
|
|
Viewer_RedisplayImage(pViewerInfo->hwnd, NULL, pViewerInfo);
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
if (pViewerInfo->horz == maxpos)
|
|
return;
|
|
pViewerInfo->horz +=
|
|
max((int) (VIEWER_PAGESCROLL_AMOUNT * (pViewerInfo->nWidth - rect.right)), 1);
|
|
pViewerInfo->horz = min(pViewerInfo->horz, maxpos);
|
|
SetScrollPos(pViewerInfo->hwnd, SB_HORZ, pViewerInfo->horz, TRUE);
|
|
Viewer_RedisplayImage(pViewerInfo->hwnd, NULL, pViewerInfo);
|
|
break;
|
|
|
|
case SB_THUMBPOSITION:
|
|
case SB_THUMBTRACK:
|
|
pViewerInfo->horz = pos;
|
|
SetScrollPos(pViewerInfo->hwnd, SB_HORZ, pViewerInfo->horz, TRUE);
|
|
Viewer_RedisplayImage(pViewerInfo->hwnd, NULL, pViewerInfo);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Viewer_VertScroll(struct ViewerInfo *pViewerInfo, int code, int pos)
|
|
{
|
|
int minpos, maxpos;
|
|
RECT rect;
|
|
|
|
GetClientRect(pViewerInfo->hwnd, &rect);
|
|
GetScrollRange(pViewerInfo->hwnd, SB_VERT, &minpos, &maxpos);
|
|
|
|
if (rect.bottom >= pViewerInfo->nHeight)
|
|
return;
|
|
|
|
if (wg.iWindowsMajorVersion >= 4)
|
|
maxpos = pViewerInfo->nHeight - rect.bottom;
|
|
|
|
switch (code)
|
|
{
|
|
case SB_LINEUP:
|
|
if (pViewerInfo->vert == minpos)
|
|
return;
|
|
pViewerInfo->vert -=
|
|
max((int) (VIEWER_LINESCROLL_AMOUNT * (pViewerInfo->nHeight - rect.bottom)), 1);
|
|
pViewerInfo->vert = max(pViewerInfo->vert, minpos);
|
|
SetScrollPos(pViewerInfo->hwnd, SB_VERT, pViewerInfo->vert, TRUE);
|
|
Viewer_RedisplayImage(pViewerInfo->hwnd, NULL, pViewerInfo);
|
|
break;
|
|
|
|
case SB_LINEDOWN:
|
|
if (pViewerInfo->vert == maxpos)
|
|
return;
|
|
pViewerInfo->vert +=
|
|
max((int) (VIEWER_LINESCROLL_AMOUNT * (pViewerInfo->nHeight - rect.bottom)), 1);
|
|
pViewerInfo->vert = min(pViewerInfo->vert, maxpos);
|
|
SetScrollPos(pViewerInfo->hwnd, SB_VERT, pViewerInfo->vert, TRUE);
|
|
Viewer_RedisplayImage(pViewerInfo->hwnd, NULL, pViewerInfo);
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
if (pViewerInfo->vert == minpos)
|
|
return;
|
|
pViewerInfo->vert -=
|
|
max((int) (VIEWER_PAGESCROLL_AMOUNT * (pViewerInfo->nHeight - rect.bottom)), 1);
|
|
pViewerInfo->vert = max(pViewerInfo->vert, minpos);
|
|
SetScrollPos(pViewerInfo->hwnd, SB_VERT, pViewerInfo->vert, TRUE);
|
|
Viewer_RedisplayImage(pViewerInfo->hwnd, NULL, pViewerInfo);
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
if (pViewerInfo->vert == maxpos)
|
|
return;
|
|
pViewerInfo->vert +=
|
|
max((int) (VIEWER_PAGESCROLL_AMOUNT * (pViewerInfo->nHeight - rect.bottom)), 1);
|
|
pViewerInfo->vert = min(pViewerInfo->vert, maxpos);
|
|
SetScrollPos(pViewerInfo->hwnd, SB_VERT, pViewerInfo->vert, TRUE);
|
|
Viewer_RedisplayImage(pViewerInfo->hwnd, NULL, pViewerInfo);
|
|
break;
|
|
|
|
case SB_THUMBPOSITION:
|
|
case SB_THUMBTRACK:
|
|
pViewerInfo->vert = pos;
|
|
SetScrollPos(pViewerInfo->hwnd, SB_VERT, pViewerInfo->vert, TRUE);
|
|
Viewer_RedisplayImage(pViewerInfo->hwnd, NULL, pViewerInfo);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Viewer_RestrictSize(struct ViewerInfo *pViewerInfo, LPMINMAXINFO pInfo)
|
|
{
|
|
int borderwidth, borderheight, captionheight, scrollwidth, scrollheight;
|
|
|
|
if (!pViewerInfo->bInitialized)
|
|
return;
|
|
|
|
// Do not allow the user to size the window bigger than the actual image
|
|
|
|
borderwidth = GetSystemMetrics(SM_CXFRAME);
|
|
borderheight = GetSystemMetrics(SM_CYFRAME);
|
|
captionheight = GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
|
|
scrollwidth = GetSystemMetrics(SM_CXVSCROLL);
|
|
scrollheight = GetSystemMetrics(SM_CYHSCROLL) + GetSystemMetrics(SM_CYMENU) +
|
|
GetSystemMetrics(SM_CYBORDER);
|
|
|
|
pInfo->ptMaxSize.x = pViewerInfo->nWidth + 2 * borderwidth + scrollwidth - 1;
|
|
pInfo->ptMaxSize.y = pViewerInfo->nHeight + 2 * borderheight + captionheight + scrollheight - 1;
|
|
|
|
pInfo->ptMaxSize.x = min(pInfo->ptMaxSize.x,
|
|
GetSystemMetrics(SM_CXFULLSCREEN) + 2 * borderwidth);
|
|
pInfo->ptMaxSize.y = min(pInfo->ptMaxSize.y,
|
|
GetSystemMetrics(SM_CYFULLSCREEN) + captionheight + 2 * borderheight);
|
|
|
|
pInfo->ptMaxTrackSize.x = pInfo->ptMaxSize.x;
|
|
pInfo->ptMaxTrackSize.y = pInfo->ptMaxSize.y;
|
|
pInfo->ptMinTrackSize.x = 100;
|
|
pInfo->ptMinTrackSize.y = 100;
|
|
}
|
|
|
|
void Viewer_ReadjustScrollbars(struct ViewerInfo *pViewerInfo)
|
|
{
|
|
RECT rect;
|
|
int cx, cy;
|
|
|
|
if (!pViewerInfo || !pViewerInfo->bInitialized)
|
|
return;
|
|
|
|
GetClientRect(pViewerInfo->hwnd, &rect);
|
|
|
|
// Take a look at where the scrollbar is, and adjust the display accordingly
|
|
|
|
if (pViewerInfo->nWidth - pViewerInfo->horz < rect.right)
|
|
{
|
|
// Make the image flush to the right. The thumb is all the way on the right.
|
|
|
|
pViewerInfo->horz = pViewerInfo->nWidth - rect.right;
|
|
}
|
|
|
|
if (pViewerInfo->nHeight - pViewerInfo->vert < rect.bottom)
|
|
{
|
|
// Make the image flush to the bottom. The thumb is all the way on the bottom.
|
|
|
|
pViewerInfo->vert = pViewerInfo->nHeight - rect.bottom;
|
|
}
|
|
|
|
// Adjust the scrolling range
|
|
|
|
if (pViewerInfo->nWidth <= rect.right)
|
|
{
|
|
pViewerInfo->horz = 0;
|
|
SetScrollPos(pViewerInfo->hwnd, SB_HORZ, 0, TRUE);
|
|
EnableScrollBar(pViewerInfo->hwnd, SB_HORZ, ESB_DISABLE_BOTH);
|
|
}
|
|
else
|
|
{
|
|
EnableScrollBar(pViewerInfo->hwnd, SB_HORZ, ESB_ENABLE_BOTH);
|
|
|
|
if (wg.iWindowsMajorVersion >= 4)
|
|
cy = pViewerInfo->nWidth;
|
|
else
|
|
cy = pViewerInfo->nWidth - rect.right;
|
|
|
|
GTR_SetScrollRange(pViewerInfo->hwnd, SB_HORZ, 0, cy, rect.right, TRUE);
|
|
SetScrollPos(pViewerInfo->hwnd, SB_HORZ, pViewerInfo->horz, TRUE);
|
|
}
|
|
|
|
if (pViewerInfo->nHeight <= rect.bottom)
|
|
{
|
|
pViewerInfo->vert = 0;
|
|
SetScrollPos(pViewerInfo->hwnd, SB_VERT, 0, TRUE);
|
|
EnableScrollBar(pViewerInfo->hwnd, SB_VERT, ESB_DISABLE_BOTH);
|
|
}
|
|
else
|
|
{
|
|
EnableScrollBar(pViewerInfo->hwnd, SB_VERT, ESB_ENABLE_BOTH);
|
|
|
|
if (wg.iWindowsMajorVersion >= 4)
|
|
cx = pViewerInfo->nHeight;
|
|
else
|
|
cx = pViewerInfo->nHeight - rect.bottom;
|
|
|
|
GTR_SetScrollRange(pViewerInfo->hwnd, SB_VERT, 0, cx, rect.bottom, TRUE);
|
|
SetScrollPos(pViewerInfo->hwnd, SB_VERT, pViewerInfo->vert, TRUE);
|
|
}
|
|
}
|
|
|
|
void Viewer_SaveAsBitmap(char *tempFile, struct ViewerInfo *pViewerInfo)
|
|
{
|
|
SaveAsBitmap(tempFile, &pViewerInfo->pbmi->bmiHeader, pViewerInfo->gw);
|
|
}
|
|
|
|
void Viewer_Print(struct ViewerInfo *pViewerInfo)
|
|
{
|
|
DOCINFO di;
|
|
HDC hDCPrinter;
|
|
int nHorzRes, nVertRes, nLogPixelsX, nLogPixelsY;
|
|
int cpxLeftMargin, cpxRightMargin, cpxDrawingArea; /* CountPixelsX... & CountPixelsY... */
|
|
int cpyTopMargin, cpyBottomMargin, cpyDrawingArea;
|
|
int nWidth;
|
|
int nHeight;
|
|
PBITMAPINFO pbmi;
|
|
|
|
hDCPrinter = PRINT_GetPrinterDC(pViewerInfo->tw, pViewerInfo->hwnd);
|
|
|
|
//
|
|
// Check for cancel...
|
|
//
|
|
if (hDCPrinter == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
nHorzRes = GetDeviceCaps(hDCPrinter, HORZRES);
|
|
nVertRes = GetDeviceCaps(hDCPrinter, VERTRES);
|
|
nLogPixelsX = GetDeviceCaps(hDCPrinter, LOGPIXELSX);
|
|
nLogPixelsY = GetDeviceCaps(hDCPrinter, LOGPIXELSY);
|
|
|
|
#ifdef _GIBRALTAR
|
|
//
|
|
// Our margins are 1000th of an inch
|
|
//
|
|
cpxLeftMargin = (int) (gPrefs.rtMargin.left * nLogPixelsX / 1000L);
|
|
cpxRightMargin = nHorzRes - (int) (gPrefs.rtMargin.right * nLogPixelsX / 1000L);
|
|
#else
|
|
cpxLeftMargin = (int) (gPrefs.page.marginleft * nLogPixelsX);
|
|
cpxRightMargin = nHorzRes - (int) (gPrefs.page.marginright * nLogPixelsX);
|
|
#endif // _GIBRALTAR
|
|
|
|
cpxDrawingArea = cpxRightMargin - cpxLeftMargin;
|
|
if (cpxDrawingArea < 0)
|
|
{
|
|
cpxLeftMargin = 0;
|
|
cpxRightMargin = nHorzRes;
|
|
cpxDrawingArea = nHorzRes;
|
|
}
|
|
|
|
#ifdef _GIBRALTAR
|
|
cpyTopMargin = (int) (gPrefs.rtMargin.top * nLogPixelsX / 1000L);
|
|
cpyBottomMargin = nHorzRes - (int) (gPrefs.rtMargin.bottom * nLogPixelsX / 1000L);
|
|
#else
|
|
cpyTopMargin = (int) (gPrefs.page.margintop * nLogPixelsY);
|
|
cpyBottomMargin = nVertRes - (int) (gPrefs.page.marginbottom * nLogPixelsY);
|
|
#endif // _GIBRALTAR
|
|
|
|
cpyDrawingArea = cpyBottomMargin - cpyTopMargin;
|
|
if (cpyDrawingArea < 0)
|
|
{
|
|
cpyTopMargin = 0;
|
|
cpyBottomMargin = nVertRes;
|
|
cpyDrawingArea = nVertRes;
|
|
}
|
|
|
|
/* tell the print queue manager that we're coming */
|
|
|
|
di.cbSize = sizeof(DOCINFO);
|
|
di.lpszDocName = pViewerInfo->szURL;
|
|
di.lpszOutput = NULL;
|
|
StartDoc(hDCPrinter, &di);
|
|
|
|
StartPage(hDCPrinter);
|
|
|
|
nWidth = (int) (pViewerInfo->nWidth * (nLogPixelsX / 72.0));
|
|
nHeight = (int) (pViewerInfo->nHeight * (nLogPixelsY / 72.0));
|
|
|
|
switch (wg.eColorMode)
|
|
{
|
|
case 8:
|
|
pbmi = BIT_Make_DIB_RGB_Header_Printer(pViewerInfo->nWidth, pViewerInfo->nHeight,
|
|
pViewerInfo->gw, hPalGuitar, BACKGROUND_COLOR_INDEX, 0);
|
|
if (pbmi)
|
|
{
|
|
(void) StretchDIBits(hDCPrinter, cpxLeftMargin, cpyTopMargin, nWidth, nHeight, 0, 0, pViewerInfo->nWidth, pViewerInfo->nHeight,
|
|
pViewerInfo->gw, pbmi, DIB_RGB_COLORS, SRCCOPY);
|
|
|
|
GTR_FREE(pbmi);
|
|
}
|
|
break;
|
|
default:
|
|
(void) StretchDIBits(hDCPrinter, cpxLeftMargin, cpyTopMargin, nWidth, nHeight, 0, 0, pViewerInfo->nWidth, pViewerInfo->nHeight,
|
|
pViewerInfo->gw, pViewerInfo->pbmi, DIB_RGB_COLORS, SRCCOPY);
|
|
break;
|
|
}
|
|
|
|
EndPage(hDCPrinter);
|
|
|
|
/* tell the print queue manager that we're finished */
|
|
|
|
EndDoc(hDCPrinter);
|
|
DeleteDC(hDCPrinter);
|
|
if (wg.lppdPrintDlg)
|
|
{
|
|
wg.lppdPrintDlg->hDC = NULL;
|
|
}
|
|
}
|
|
|
|
void Viewer_SaveAsOriginal(char *tempFile, struct ViewerInfo *pViewerInfo)
|
|
{
|
|
FILE *fpRead, *fpWrite;
|
|
long filesize;
|
|
char *pMem;
|
|
|
|
// Simply copy the original file to the new file name
|
|
|
|
fpRead = fopen(pViewerInfo->fsOrig, "rb");
|
|
if (!fpRead)
|
|
{
|
|
ERR_ReportError(pViewerInfo->tw, SID_ERR_COULD_NOT_SAVE_FILE_S, tempFile, NULL);
|
|
return;
|
|
}
|
|
|
|
fpWrite = fopen(tempFile, "wb");
|
|
if (!fpWrite)
|
|
{
|
|
fclose(fpRead);
|
|
ERR_ReportError(pViewerInfo->tw, SID_ERR_COULD_NOT_SAVE_FILE_S, tempFile, NULL);
|
|
return;
|
|
}
|
|
|
|
fseek(fpRead, 0, SEEK_END);
|
|
filesize = ftell(fpRead);
|
|
fseek(fpRead, 0, SEEK_SET);
|
|
|
|
pMem = GTR_MALLOC(filesize);
|
|
fread(pMem, 1, filesize, fpRead);
|
|
fwrite(pMem, 1, filesize, fpWrite);
|
|
free(pMem);
|
|
|
|
fclose(fpRead);
|
|
fclose(fpWrite);
|
|
}
|
|
|
|
BOOL Viewer_HandleMenu(struct ViewerInfo *pViewerInfo, int menuID)
|
|
{
|
|
char tempFile[_MAX_PATH + 1];
|
|
char path[_MAX_PATH + 1];
|
|
char baseFile[_MAX_PATH + 1];
|
|
char *pMem, *pExtension;
|
|
BITMAPINFO *pbmi;
|
|
int newwidth;
|
|
HANDLE hData;
|
|
int filter;
|
|
struct Mwin *tw;
|
|
|
|
#ifndef _GIBRALTAR
|
|
HWND hwnd;
|
|
#endif // _GIBRALTAR
|
|
|
|
if ((menuID >= RES_MENU_CHILD__FIRST__) && (menuID <= RES_MENU_CHILD__LAST__))
|
|
{
|
|
TW_ActivateWindowFromList(menuID, -1, NULL);
|
|
return TRUE;
|
|
}
|
|
|
|
// Return TRUE if we handled the menu here
|
|
|
|
switch(menuID)
|
|
{
|
|
|
|
#ifdef _GIBRALTAR
|
|
|
|
case RES_MENU_ITEM_PAGESETUP:
|
|
ShowPageSetup(pViewerInfo->hwnd);
|
|
return TRUE;
|
|
|
|
#endif // _GIBRALTAR
|
|
|
|
case RES_MENU_ITEM_COPY:
|
|
OpenClipboard(pViewerInfo->hwnd);
|
|
EmptyClipboard();
|
|
|
|
// We need different clipboard copying code for 8-bit and 24-bit screens.
|
|
// For 8-bit, we must pass the handle to the actual bitmap because the palette
|
|
// we use is indexed, instead of containing true RGB values. Windows can't seem to
|
|
// handle this type of DIB for the clipboard. For 24-bit, we compose the DIB and pass
|
|
// the DIB to Windows.
|
|
|
|
pbmi = pViewerInfo->pbmi;
|
|
|
|
if (wg.eColorMode == 8)
|
|
SetClipboardData(CF_BITMAP, pViewerInfo->hBitmap);
|
|
else
|
|
{
|
|
newwidth = pViewerInfo->nWidth * (pbmi->bmiHeader.biBitCount / 8);
|
|
if (newwidth % 4)
|
|
newwidth += (4 - newwidth % 4);
|
|
|
|
hData = GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD) * (pbmi->bmiHeader.biBitCount == 8) +
|
|
newwidth * pViewerInfo->nHeight);
|
|
|
|
pMem = GlobalLock(hData);
|
|
|
|
memcpy(pMem, pbmi, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD) * (pbmi->bmiHeader.biBitCount == 8));
|
|
pMem += sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD) * (pbmi->bmiHeader.biBitCount == 8);
|
|
memcpy(pMem, pViewerInfo->gw, newwidth * pViewerInfo->nHeight);
|
|
|
|
GlobalUnlock(hData);
|
|
SetClipboardData(CF_DIB, hData);
|
|
|
|
// hData is now owned by the system
|
|
}
|
|
|
|
CloseClipboard();
|
|
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_SAVEAS:
|
|
path[0] = 0;
|
|
PREF_GetTempPath(_MAX_PATH, path);
|
|
|
|
switch(pViewerInfo->format)
|
|
{
|
|
case VIEWER_GIF:
|
|
x_get_good_filename(baseFile, pViewerInfo->szURL, HTAtom_for("image/gif"));
|
|
strcpy(tempFile, baseFile);
|
|
|
|
// Lose the extension
|
|
|
|
pExtension = strchr(tempFile, '.');
|
|
if (pExtension)
|
|
*pExtension = '\0';
|
|
|
|
if ((filter = DlgSaveAs_RunDialog(pViewerInfo->hwnd, NULL, tempFile, 4, SID_DLG_SAVE_AS_TITLE)) < 0)
|
|
return TRUE;
|
|
|
|
|
|
#ifdef _GIBRALTAR
|
|
if (!HasExtention(tempFile, ".GIF")
|
|
&& !HasExtention(tempFile, ".BMP"))
|
|
{
|
|
if (filter == 1)
|
|
strcat(tempFile, ".GIF");
|
|
else if (filter == 2)
|
|
strcat(tempFile, ".BMP");
|
|
}
|
|
#else
|
|
if (!strstr(tempFile, ".GIF") && !strstr(tempFile, ".BMP"))
|
|
{
|
|
if (filter == 1)
|
|
strcat(tempFile, ".GIF");
|
|
else if (filter == 2)
|
|
strcat(tempFile, ".BMP");
|
|
}
|
|
#endif // _GIBRALTAR
|
|
|
|
break;
|
|
|
|
case VIEWER_JFIF:
|
|
x_get_good_filename(baseFile, pViewerInfo->szURL, HTAtom_for("image/jpeg"));
|
|
strcpy(tempFile, baseFile);
|
|
|
|
// Lose the extension
|
|
|
|
pExtension = strchr(tempFile, '.');
|
|
if (pExtension)
|
|
*pExtension = '\0';
|
|
|
|
if ((filter = DlgSaveAs_RunDialog(pViewerInfo->hwnd, NULL, tempFile, 5, SID_DLG_SAVE_AS_TITLE)) < 0)
|
|
return TRUE;
|
|
|
|
#ifdef _GIBRALTAR
|
|
if (!HasExtention(tempFile, ".JPG") &&
|
|
!HasExtention(tempFile, ".BMP"))
|
|
{
|
|
if (filter == 1)
|
|
strcat(tempFile, ".JPG");
|
|
else if (filter == 2)
|
|
strcat(tempFile, ".BMP");
|
|
}
|
|
#else
|
|
if (!strstr(tempFile, ".JPG") && !strstr(tempFile, ".BMP"))
|
|
{
|
|
if (filter == 1)
|
|
strcat(tempFile, ".JPG");
|
|
else if (filter == 2)
|
|
strcat(tempFile, ".BMP");
|
|
}
|
|
#endif // _GIBRALTAR
|
|
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
// Copy the temporary file to the one the user specified. If the name is the same,
|
|
// then don't copy. This is handled automatically because a file cannot be opened
|
|
// for reading only and writing only at the same time.
|
|
|
|
if (_stricmp(pViewerInfo->fsOrig, tempFile) == 0)
|
|
{
|
|
|
|
}
|
|
|
|
// If the file name ends in BMP then save the file as a bitmap
|
|
|
|
#ifdef _GIBRALTAR
|
|
if (HasExtention(tempFile, ".BMP"))
|
|
Viewer_SaveAsBitmap(tempFile, pViewerInfo);
|
|
else if (pViewerInfo->format == VIEWER_JFIF && HasExtention(tempFile, ".JPG"))
|
|
Viewer_SaveAsOriginal(tempFile, pViewerInfo);
|
|
else if (pViewerInfo->format == VIEWER_GIF && HasExtention(tempFile, ".GIF"))
|
|
Viewer_SaveAsOriginal(tempFile, pViewerInfo);
|
|
else
|
|
{
|
|
ERR_ReportError(pViewerInfo->tw, SID_ERR_COULD_NOT_SAVE_FILE_S, tempFile, NULL);
|
|
return FALSE;
|
|
}
|
|
#else
|
|
if (strstr(tempFile, ".BMP"))
|
|
Viewer_SaveAsBitmap(tempFile, pViewerInfo);
|
|
else if (pViewerInfo->format == VIEWER_JFIF && strstr(tempFile, ".JPG"))
|
|
Viewer_SaveAsOriginal(tempFile, pViewerInfo);
|
|
else if (pViewerInfo->format == VIEWER_GIF && strstr(tempFile, ".GIF"))
|
|
Viewer_SaveAsOriginal(tempFile, pViewerInfo);
|
|
else
|
|
{
|
|
ERR_ReportError(pViewerInfo->tw, SID_ERR_COULD_NOT_SAVE_FILE_S, tempFile, NULL);
|
|
return FALSE;
|
|
}
|
|
#endif // _GIBRALTAR
|
|
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_PRINT:
|
|
Viewer_Print(pViewerInfo);
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_CLOSE:
|
|
PostMessage(pViewerInfo->hwnd, WM_CLOSE, 0, 0);
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_EXIT:
|
|
PostMessage(wg.hWndHidden, WM_CLOSE, 0, 0);
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_GLOBALHISTORY:
|
|
DlgHOT_RunDialog(TRUE);
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_HOTLIST:
|
|
DlgHOT_RunDialog(FALSE);
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_ADDCURRENTTOHOTLIST:
|
|
// For an image viewer, URL and title are the same
|
|
|
|
if (!HotList_Add(pViewerInfo->szURL, pViewerInfo->szURL))
|
|
ERR_ReportError(pViewerInfo->tw, SID_ERR_HOTLIST_ALREADY_EXISTS, NULL, NULL);
|
|
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_HELPPAGE:
|
|
tw = TW_FindTopmostWindow();
|
|
OpenHelpWindow(tw->hWndFrame);
|
|
SetForegroundWindow(tw->hWndFrame);
|
|
if (IsIconic(tw->hWndFrame))
|
|
ShowWindow(tw->hWndFrame, SW_RESTORE);
|
|
return TRUE;
|
|
|
|
#ifndef _GIBRALTAR
|
|
case RES_MENU_CHILD_MOREWINDOWS:
|
|
DlgSelectWindow_RunDialog(pViewerInfo->hwnd);
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_PAGESETUP:
|
|
DlgPage_RunDialog(pViewerInfo->hwnd, &gPrefs.page);
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_ABOUTBOX:
|
|
DlgAbout_RunDialog(pViewerInfo->hwnd);
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_NEWWINDOW:
|
|
GTR_NewWindow(NULL, NULL, 0, FALSE, FALSE, NULL, NULL);
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_CASCADEWINDOWS:
|
|
TW_CascadeWindows();
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_TILEWINDOWS:
|
|
TW_TileWindows();
|
|
return TRUE;
|
|
|
|
case RES_MENU_ITEM_SWITCHWINDOW:
|
|
hwnd = TW_GetNextWindow(pViewerInfo->hwnd);
|
|
if (hwnd)
|
|
TW_RestoreWindow(hwnd);
|
|
return TRUE;
|
|
|
|
#endif // _GIBRALTAR
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void Viewer_CleanUp()
|
|
{
|
|
int count, i;
|
|
struct ViewerInfo *p;
|
|
|
|
if (!bInitialized)
|
|
return;
|
|
|
|
// Destroy all open windows
|
|
|
|
count = Hash_Count(&gViewerCache);
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
Hash_GetIndexedEntry(&gViewerCache, i, NULL, NULL, &p);
|
|
DestroyWindow(p->hwnd);
|
|
}
|
|
|
|
Hash_FreeContents(&gViewerCache);
|
|
}
|
|
|
|
HWND Viewer_GetNextWindow(BOOL bStart)
|
|
{
|
|
static int current_index = 0;
|
|
struct ViewerInfo *p;
|
|
|
|
if (bStart)
|
|
current_index = 0;
|
|
|
|
if (current_index >= Hash_Count(&gViewerCache))
|
|
return NULL;
|
|
|
|
if (!bStart)
|
|
current_index++;
|
|
|
|
if (current_index >= Hash_Count(&gViewerCache))
|
|
return NULL;
|
|
|
|
Hash_GetIndexedEntry(&gViewerCache, current_index, NULL, NULL, &p);
|
|
return (p->hwnd);
|
|
}
|
|
|
|
BOOL Viewer_IsWindow(HWND hwnd)
|
|
{
|
|
char szClass[MAX_WC_CLASSNAME];
|
|
|
|
GetClassName(hwnd, szClass, sizeof(szClass));
|
|
return (strcmp(szClass, Viewer_achClassName) == 0);
|
|
}
|
|
|
|
void Viewer_PaintIcon(struct ViewerInfo *pViewerInfo, HDC hDC)
|
|
{
|
|
HICON hIcon;
|
|
|
|
DefWindowProc(pViewerInfo->hwnd, WM_ICONERASEBKGND, (WPARAM) hDC, 0);
|
|
hIcon = LoadIcon(wg.hInstance, MAKEINTRESOURCE(RES_ICO_FRAME));
|
|
DrawIcon(hDC, 0, 0, hIcon);
|
|
}
|
|
|
|
static VOID Viewer_OnSize(HWND hWnd, UINT state, int cx, int cy)
|
|
{
|
|
struct ViewerInfo *p;
|
|
|
|
p = (struct ViewerInfo *) GetWindowLong(hWnd, 0);
|
|
|
|
if (p)
|
|
{
|
|
Viewer_ReadjustScrollbars(p);
|
|
InvalidateRect(hWnd, NULL, FALSE);
|
|
}
|
|
}
|
|
|
|
static VOID Viewer_OnCommand(HWND hWnd, int wId, HWND hWndCtl, UINT wNotifyCode)
|
|
{
|
|
struct ViewerInfo *p;
|
|
|
|
p = (struct ViewerInfo *) GetWindowLong(hWnd, 0);
|
|
if (p)
|
|
Viewer_HandleMenu(p, wId);
|
|
}
|
|
|
|
static void Viewer_OnVScroll(HWND hWnd, HWND hWndCtl, UINT code, int pos)
|
|
{
|
|
struct ViewerInfo *p;
|
|
|
|
p = (struct ViewerInfo *) GetWindowLong(hWnd, 0);
|
|
Viewer_VertScroll(p, code, pos);
|
|
}
|
|
|
|
static void Viewer_OnHScroll(HWND hWnd, HWND hWndCtl, UINT code, int pos)
|
|
{
|
|
struct ViewerInfo *p;
|
|
|
|
p = (struct ViewerInfo *) GetWindowLong(hWnd, 0);
|
|
Viewer_HorzScroll(p, code, pos);
|
|
}
|
|
|
|
static void Viewer_OnPaint(HWND hwnd)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hdc;
|
|
struct ViewerInfo *p;
|
|
|
|
p = (struct ViewerInfo *) GetWindowLong(hwnd, 0);
|
|
|
|
hdc = BeginPaint(hwnd, &ps);
|
|
|
|
if (IsIconic(hwnd))
|
|
Viewer_PaintIcon(p, hdc);
|
|
else
|
|
Viewer_RedisplayImage(hwnd, hdc, p);
|
|
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
|
|
DCL_WinProc(Viewer_DlgProc)
|
|
{
|
|
struct ViewerInfo *p;
|
|
int ndx;
|
|
HICON hIcon;
|
|
HMENU hMenu;
|
|
|
|
switch (uMsg)
|
|
{
|
|
HANDLE_MSG(hWnd, WM_SIZE, Viewer_OnSize);
|
|
HANDLE_MSG(hWnd, WM_COMMAND, Viewer_OnCommand);
|
|
HANDLE_MSG(hWnd, WM_VSCROLL, Viewer_OnVScroll);
|
|
HANDLE_MSG(hWnd, WM_HSCROLL, Viewer_OnHScroll);
|
|
HANDLE_MSG(hWnd, WM_PAINT, Viewer_OnPaint);
|
|
|
|
case WM_KEYDOWN:
|
|
switch((int) wParam)
|
|
{
|
|
case VK_LEFT:
|
|
SendMessage(hWnd, WM_HSCROLL, (WPARAM) SB_LINEUP, 0);
|
|
return 0;
|
|
case VK_RIGHT:
|
|
SendMessage(hWnd, WM_HSCROLL, (WPARAM) SB_LINEDOWN, 0);
|
|
return 0;
|
|
case VK_UP:
|
|
SendMessage(hWnd, WM_VSCROLL, (WPARAM) SB_LINEUP, 0);
|
|
return 0;
|
|
case VK_DOWN:
|
|
SendMessage(hWnd, WM_VSCROLL, (WPARAM) SB_LINEDOWN, 0);
|
|
return 0;
|
|
case VK_PRIOR:
|
|
SendMessage(hWnd, WM_VSCROLL, (WPARAM) SB_PAGEUP, 0);
|
|
return 0;
|
|
case VK_NEXT:
|
|
SendMessage(hWnd, WM_VSCROLL, (WPARAM) SB_PAGEDOWN, 0);
|
|
return 0;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
//case WM_GETMINMAXINFO:
|
|
// p = (struct ViewerInfo *) GetWindowLong(hWnd, 0);
|
|
// Viewer_RestrictSize(p, (LPMINMAXINFO) lParam);
|
|
// return FALSE;
|
|
|
|
case WM_ERASEBKGND:
|
|
if (IsIconic(hWnd))
|
|
return 0;
|
|
break;
|
|
|
|
case WM_QUERYDRAGICON:
|
|
hIcon = LoadIcon(wg.hInstance, MAKEINTRESOURCE(RES_ICO_FRAME));
|
|
return (LONG) hIcon;
|
|
|
|
case WM_INITMENU:
|
|
hMenu = GetMenu(hWnd);
|
|
TW_CreateWindowList(hWnd, hMenu, NULL);
|
|
break;
|
|
|
|
case WM_SETCURSOR:
|
|
/* If the window is currently disabled, we need to give the activation
|
|
to the window which disabled this window */
|
|
|
|
if ((!IsWindowEnabled(hWnd)) &&
|
|
((GetKeyState(VK_LBUTTON) & 0x8000) || (GetKeyState(VK_RBUTTON) & 0x8000)))
|
|
{
|
|
TW_EnableModalChild(hWnd);
|
|
}
|
|
break;
|
|
|
|
case WM_ENABLE:
|
|
if (wParam && !IsWindowEnabled(hWnd))
|
|
{
|
|
if (!TW_EnableModalChild(hWnd))
|
|
break;
|
|
else
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
DestroyWindow(hWnd);
|
|
return 0;
|
|
|
|
case WM_DESTROY:
|
|
// Remove the item from the cached list
|
|
|
|
p = (struct ViewerInfo *) GetWindowLong(hWnd, 0);
|
|
ndx = Hash_FindByData(&gViewerCache, NULL, NULL, p);
|
|
Hash_DeleteIndexedEntry(&gViewerCache, ndx);
|
|
|
|
if (p->fsOrig && !p->bNoDeleteFile)
|
|
{
|
|
remove(p->fsOrig);
|
|
}
|
|
|
|
if (p->hBitmap)
|
|
DeleteObject(p->hBitmap);
|
|
|
|
if (p->gw)
|
|
GTR_FREE(p->gw);
|
|
|
|
if (p->fsOrig)
|
|
{
|
|
GTR_FREE(p->fsOrig);
|
|
}
|
|
GTR_FREE(p->tw);
|
|
GTR_FREE(p);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
|
|
#endif
|