Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

2054 lines
49 KiB

/*
Enhanced NCSA Mosaic from Spyglass
"Guitar"
Copyright 1994 Spyglass, Inc.
All Rights Reserved
Author(s):
Eric W. Sink [email protected]
Jim Seidman [email protected]
*/
#include "all.h"
extern TCHAR Frame_achClassName[MAX_WC_CLASSNAME];
static char szStringBuffer[256]; /* Used to get strings from string table */
#define MAX_DEBUG_MESSAGE_SIZE 64*1024 /* arbitrary */
//#if defined(XX_DEBUG) && defined(GTR_MEM_STATS)
#ifdef _DEBUG
static struct {
int cMalloc;
int cCalloc;
int cRealloc;
int cFree;
int nBytes;
int nMaxBytes;
} gMemStats;
#ifdef GTR_FAKE_LOW_MEMORY
#define GTR_ARTIFICIAL_MEMORY_LIMIT (1*1024*1024)
#endif
void * GTR_DebugMalloc(char *szFile, int iLine, size_t iSize)
{
void *p;
#ifdef GTR_FAKE_LOW_MEMORY
if ((gMemStats.nBytes + iSize) > GTR_ARTIFICIAL_MEMORY_LIMIT)
{
XX_DMsg(DBG_MEM, ("INTENTIONAL FAILURE: malloc %d bytes (0x%x) at %s:%d\n", iSize, (unsigned long) p, szFile, iLine));
return NULL;
}
#endif
gMemStats.cMalloc++;
gMemStats.nBytes += iSize;
if (gMemStats.nBytes > gMemStats.nMaxBytes)
{
gMemStats.nMaxBytes = gMemStats.nBytes;
}
p = malloc(iSize);
XX_DMsg(DBG_MEM, ("malloc %d bytes (0x%x) at %s:%d (totals %d/%d)\n", iSize, (unsigned long) p, szFile, iLine,
gMemStats.cMalloc, gMemStats.nBytes));
return p;
}
void * GTR_DebugCalloc(char *szFile, int iLine, size_t iNum, size_t iSize)
{
void *p;
#ifdef GTR_FAKE_LOW_MEMORY
if ((gMemStats.nBytes + (iNum * iSize))> GTR_ARTIFICIAL_MEMORY_LIMIT)
{
XX_DMsg(DBG_MEM, ("INTENTIONAL FAILURE: calloc %d*%d bytes (0x%x) at %s:%d\n", iNum, iSize, (unsigned long) p, szFile, iLine));
return NULL;
}
#endif
gMemStats.cCalloc++;
gMemStats.nBytes += (iNum * iSize);
if (gMemStats.nBytes > gMemStats.nMaxBytes)
{
gMemStats.nMaxBytes = gMemStats.nBytes;
}
p = calloc(iNum, iSize);
XX_DMsg(DBG_MEM, ("calloc %d*%d bytes (0x%x) at %s:%d (totals %d/%d)\n", iNum, iSize, (unsigned long) p, szFile, iLine,
gMemStats.cCalloc, gMemStats.nBytes));
return p;
}
void * GTR_DebugRealloc(char *szFile, int iLine, void *pMem, size_t iSize)
{
void *p;
size_t siz;
siz = _msize(pMem);
#ifdef GTR_FAKE_LOW_MEMORY
if ((gMemStats.nBytes + iSize - siz) > GTR_ARTIFICIAL_MEMORY_LIMIT)
{
XX_DMsg(DBG_MEM, ("INTENTIONAL FAILURE: realloc 0x%x to %d (0x%x) at %s:%d\n", pMem, iSize, (unsigned long) p, szFile, iLine));
return NULL;
}
#endif
gMemStats.cRealloc++;
gMemStats.nBytes -= siz;
gMemStats.nBytes += iSize;
if (gMemStats.nBytes > gMemStats.nMaxBytes)
{
gMemStats.nMaxBytes = gMemStats.nBytes;
}
p = realloc(pMem, iSize);
XX_DMsg(DBG_MEM, ("REALLOC 0x%x to %d (0x%x) at %s:%d\n", pMem, iSize, (unsigned long) p, szFile, iLine));
return p;
}
void GTR_DebugFree(char *szFile, int iLine, void *pMem)
{
size_t siz;
XX_Assert((pMem), ("GTR_DebugFree: Trying to free a NULL block\n"));
siz = _msize(pMem);
XX_Assert((siz != 0), ("GTR_DebugFree: Encountered a block of size 0\n"));
memset(pMem, 0xbe, siz);
gMemStats.cFree++;
gMemStats.nBytes -= siz;
XX_DMsg(DBG_MEM, ("free 0x%x at %s:%d (total %d)\n", pMem, szFile, iLine,
gMemStats.cFree));
free(pMem);
}
void GTR_MemStats(void)
{
XX_DMsg(DBG_MEM, ("Memory Statistics\n"));
XX_DMsg(DBG_MEM, (" cAlloc = %d\n", gMemStats.cMalloc + gMemStats.cCalloc));
XX_DMsg(DBG_MEM, (" cMalloc = %d\n", gMemStats.cMalloc));
XX_DMsg(DBG_MEM, (" cCalloc = %d\n", gMemStats.cCalloc));
XX_DMsg(DBG_MEM, (" cRealloc = %d\n", gMemStats.cRealloc));
XX_DMsg(DBG_MEM, (" cFree = %d\n\n", gMemStats.cFree));
XX_DMsg(DBG_MEM, (" nBytes = %d\n", gMemStats.nBytes));
XX_DMsg(DBG_MEM, (" nMaxBytes= %d\n", gMemStats.nMaxBytes));
}
// build fix: added local declaration (a-BWill)
void XX_DebugMessage(unsigned char * msg, ...);
unsigned char * XX_FormatMessage(unsigned char * fmt, ...)
{
static unsigned char static_buf[MAX_DEBUG_MESSAGE_SIZE];
va_list val;
va_start(val,fmt);
vsprintf(static_buf,fmt,val);
va_end(val);
return (static_buf);
}
void XX_AssertionFailure(unsigned char * filename, int linenumber,
unsigned char * condition, unsigned char * user_message)
{
static char buf[MAX_DEBUG_MESSAGE_SIZE];
sprintf(buf,"%s:%04d Assertion [%s] failed. [%s]\n",
filename,linenumber,condition,user_message);
(void)MessageBox(NULL,buf,"XX_DEBUG",MB_OK|MB_ICONSTOP);
XX_DebugMessage(buf);
return;
}
/* XX_DebugMessage() -- generate printf-style message on the appropriate
debug device. (Caller should test debug category.) */
void XX_DebugMessage(unsigned char * msg, ...)
{
return;
/*
static unsigned char buf[MAX_DEBUG_MESSAGE_SIZE];
va_list val;
va_start(val,msg);
vsprintf(buf,msg,val);
va_end(val);
OutputDebugString(buf);
*/
}
#endif /* XX_DEBUG && GTR_MEM_STATS */
BOOL TW_SetWindowTitle(struct Mwin *tw, const char *s)
{
#ifndef FEATURE_KIOSK_MODE
return SetWindowText(tw->hWndFrame, s);
#endif
}
int ExecuteCommand(char *cmd)
{
char drive[_MAX_DRIVE + 1];
char dir[_MAX_DIR + 1];
char fname[_MAX_FNAME + 1];
char ext[_MAX_EXT + 1];
char workdir[_MAX_PATH + 1];
BOOL bOK;
STARTUPINFO si;
PROCESS_INFORMATION pi;
char *p;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.wShowWindow = SW_SHOW;
memset(&pi, 0, sizeof(pi));
strcpy(workdir, cmd);
p = workdir;
while (*p && !isspace((unsigned char)*p))
{
p++;
}
if (isspace((unsigned char)*p))
{
*p = 0;
}
_splitpath(workdir, drive, dir, fname, ext);
strcpy(workdir, drive);
strcat(workdir, dir);
bOK = CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, workdir[0] ? workdir : NULL, &si, &pi);
if (bOK)
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
else
{
char buf[_MAX_PATH + 512];
sprintf(buf, GTR_GetString(SID_ERR_COULD_NOT_EXECUTE_COMMAND_D_S), GetLastError(), cmd);
ERR_ReportError(NULL, SID_ERR_SIMPLY_SHOW_ARGUMENTS_S_S, buf, NULL);
return -1;
}
}
void TW_GetWindowWrapRect(struct Mwin *tw, RECT * rWrap)
{
RECT r;
int cx;
int cy;
GetWindowRect(tw->win, &r);
cx = r.right - r.left;
cy = r.bottom - r.top;
cx -= GetSystemMetrics(SM_CXHSCROLL);
rWrap->left = 0;
rWrap->top = 0;
rWrap->right = cx;
rWrap->bottom = cy;
}
/*
This function simply scrolls the document to the
given element. The return value specifies whether
or not the scroll was "truncated" - i.e. the local
anchor didn't make it to the top of the screen.
*/
BOOL TW_ScrollToElement(struct Mwin *tw, int ndx)
{
int newofft;
BOOL bResult;
if (tw->w3doc->cy)
{
if (ndx)
{
/* TODO we can subtract tw->w3doc->pStyles->top_margin like the Mac version
as soon as we stop setting iFirstVisibleElement in the draw routine. */
newofft = tw->w3doc->aElements[ndx].r.top;
}
else
{
newofft = 0;
}
if (newofft > tw->w3doc->cy)
{
newofft = tw->w3doc->cy;
bResult = FALSE;
}
else
{
bResult = TRUE;
}
if (newofft < 0)
{
newofft = 0;
}
if (newofft != tw->offt || tw->offl)
{
tw->offt = newofft;
tw->offl = 0;
SetScrollPos(tw->win, SB_VERT, tw->offt / tw->w3doc->yscale, TRUE);
SetScrollPos(tw->win, SB_HORZ, tw->offl, TRUE);
TW_adjust_all_child_windows(tw);
}
#if 0 /* see comment above */
tw->w3doc->iFirstVisibleElement = ndx;
#endif
}
else
{
bResult = FALSE;
}
TW_InvalidateDocument(tw);
return bResult;
}
/*
helper function to enable Win95 proportional scrollbars.
*/
void GTR_SetScrollRange(HWND hWnd, int fnBar, int nMinPos, int nMaxPos, int nPageSize, BOOL fRedraw)
{
#if (WINVER >= 0x0400)
if (wg.iWindowsMajorVersion >= 4)
{
// this structure needed to update the scrollbar page range
SCROLLINFO info;
info.cbSize = sizeof(SCROLLINFO);
info.fMask = SIF_PAGE|SIF_RANGE;
info.nMin = nMinPos;
info.nMax = nMaxPos;
info.nPage = nPageSize;
SetScrollInfo(hWnd, fnBar, &info, fRedraw);
}
else
#endif // WINVER
{
SetScrollRange(hWnd, fnBar, nMinPos, nMaxPos, fRedraw);
}
}
void TW_SetScrollBars(struct Mwin *tw)
{
RECT rWnd;
int cx, cy;
rWnd = tw->w3doc->rWindow;
tw->w3doc->cy = tw->w3doc->ybound - (rWnd.bottom - rWnd.top) + tw->w3doc->pStyles->top_margin;
if (tw->w3doc->cy < 0)
{
tw->w3doc->cy = 0;
}
if (wg.iWindowsMajorVersion >= 4)
{
if (tw->w3doc->ybound > 0)
cy = tw->w3doc->ybound + tw->w3doc->pStyles->top_margin;
else
cy = 0;
}
else
cy = tw->w3doc->cy;
tw->w3doc->yscale = (int) (ceil(cy / 32767.0));
if (tw->w3doc->yscale == 0)
tw->w3doc->yscale = 1;
GTR_SetScrollRange(tw->win, SB_VERT, 0, cy / tw->w3doc->yscale, (rWnd.bottom - rWnd.top) / tw->w3doc->yscale, FALSE);
/*
Be aware that at this point, we may have just sent a WM_SIZE
message to ourselves if the scroll bar visibility changed.
*/
if (tw->offt > tw->w3doc->cy)
{
tw->offt = tw->w3doc->cy;
}
SetScrollPos(tw->win, SB_VERT, tw->offt / tw->w3doc->yscale, TRUE);
/*
Horizontal
*/
tw->w3doc->cx = tw->w3doc->xbound - (rWnd.right - rWnd.left);
if (tw->w3doc->cx < 0)
{
tw->w3doc->cx = 0;
}
if (wg.iWindowsMajorVersion >= 4)
cx = tw->w3doc->xbound;
else
cx = tw->w3doc->cx;
GTR_SetScrollRange(tw->win, SB_HORZ, 0, cx, rWnd.right - rWnd.left, FALSE);
/*
Be aware that at this point, we may have just sent a WM_SIZE
message to ourselves if the scroll bar visibility changed.
*/
if (tw->offl > tw->w3doc->cx)
{
tw->offl = tw->w3doc->cx;
}
SetScrollPos(tw->win, SB_HORZ, tw->offl, TRUE);
TW_adjust_all_child_windows(tw);
}
void TW_InvalidateDocument( struct Mwin *tw )
{
XX_DMsg(DBG_DRAW, ("TW_InvalidateDocument\n"));
InvalidateRect(tw->win, NULL, TRUE);
TBar_UpdateTBar(tw);
TW_ForceHitTest(tw);
}
void TW_UpdateTBar(struct Mwin *tw )
{
TBar_UpdateTBar(tw);
TW_ForceHitTest(tw);
}
void TW_UpdateRect( struct Mwin *tw, RECT *r )
{
XX_DMsg(DBG_DRAW, ("TW_UpdateRect: %d,%d %d,%d\n", r->left, r->top, r->right, r->bottom));
InvalidateRect(tw->win, r, TRUE);
}
COLORREF GTR_MakeCOLORREF(int r, int g, int b)
{
return PALETTERGB(r,g,b);
}
void DOS_EnforceEndingSlash(char *dir)
{
int len;
len = strlen(dir);
if (dir[len-1] != '\\')
{
dir[len] = '\\';
dir[len+1] = 0;
}
}
void DOS_MakeShortFilename(char *dest, char *src)
{
char *pBase;
char *p;
char *q;
int i;
pBase = src;
i = 0;
while ((pBase[i] != '.') && (i < 8))
{
dest[i] = pBase[i];
i++;
}
dest[i++] = '.';
p = dest + i;
q = strrchr(pBase, '.');
if (q)
{
q++;
strcpy(p, q);
if (strlen(p) > 3)
{
p[3] = 0;
}
}
}
void TW_ForceHitTest(struct Mwin * tw)
{
/* the following looks a bit strange, but we need it to force
the cursor back to the icon appropriate for what the mouse
is positioned over. this cleans up the hourglass effect
forced by wc_... on a WM_SETCURSOR. (the first mouse
movement following our ending the wait would clear
the hourglass -- this is for the patient user who's not
fidgeting...) */
if (tw && tw->hWndFrame)
{
POINT pt;
GetCursorPos(&pt);
SetCursorPos(pt.x, pt.y);
}
// SendMessage(tw->hWndFrame, WM_SETCURSOR, 0, 0);
}
BOOL TW_EnableModalChild(HWND hDlg)
{
HWND hwnd;
BOOL bTriedHistory = FALSE, bTriedHotlist = FALSE;
/* Enable a 'modal' child dialog of the given dialog. This is useful when
the user clicks on a dialog currently disabled because its child dialog has
disabled it. In this case, we want the activation to go to the child dialog. */
hwnd = GetTopWindow(NULL);
while (TRUE)
{
/* Find the modal child of the given window */
while (hwnd && GetParent(hwnd) != hDlg)
hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
if (hwnd)
{
/* If the modal child is enabled, then bring it to the foreground. Otherwise,
find the modal child of this child and check that dialog */
if (IsWindowEnabled(hwnd))
{
SetForegroundWindow(hwnd);
return TRUE;
}
else
{
hDlg = hwnd;
hwnd = GetTopWindow(NULL);
}
}
else
{
/* Try history and hotlist dialogs since those can have modal dialogs too */
if (bTriedHistory && bTriedHotlist)
{
/* This should NEVER happen */
return FALSE;
}
hwnd = GetTopWindow(NULL);
if (bTriedHistory)
{
bTriedHotlist = TRUE;
hDlg = DlgHOT_GetHistoryWindow();
}
else
{
bTriedHistory = TRUE;
hDlg = DlgHOT_GetHotlistWindow();
}
}
}
return FALSE; /* There was no child window to activate */
}
/* This function returns the topmost Mosaic window in the Z-order list */
struct Mwin *TW_FindTopmostWindow(void)
{
char szClassName[32];
HWND hwnd;
struct Mwin *tw;
hwnd = GetTopWindow(NULL);
while (hwnd)
{
GetClassName(hwnd, szClassName, sizeof(szClassName));
if (_stricmp(Frame_achClassName, szClassName) == 0)
break;
hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
}
if (!hwnd)
return NULL; /* This should never happen */
tw = GetPrivateData(hwnd);
return tw;
}
/* This function is used only by TW_AddToWindowMenu */
static char *TW_GetMenuWithMnemonic(char *pMenu, int mnemonic)
{
char *pBuffer;
/* Given a text string, return a string with the mnemonic in front. */
pBuffer = GTR_MALLOC(strlen(pMenu) + 10);
sprintf(pBuffer, "&%d ", mnemonic);
strcat(pBuffer, pMenu);
return pBuffer;
}
/*
TW_CreateWindowList
This function adds menu items to the Window menu or a listbox.
Note: possible cases:
only hwnd & hMenu are valid: Called from a document or img view/sound player
only hListbox valid : Called from the Select Window dialog
only hMenu valid : Called from baby window
*/
void TW_CreateWindowList(HWND hwnd, HMENU hMenu, HWND hListbox)
{
char szClassName[32];
struct Mwin *tw, *twTop;
int count, length, i;
char *pBuffer, *pText;
HMENU hMenuSub;
HWND hDialog;
count = 0;
if (hMenu)
{
if (hwnd)
{
hMenuSub = MB_GetWindowsPad(hMenu);
if (!hMenuSub)
return;
/* delete old items from the windows menu pad */
for (i = RES_MENU_CHILD__FIRST__; i <= RES_MENU_CHILD__LAST__; i++)
DeleteMenu(hMenuSub, i, MF_BYCOMMAND);
DeleteMenu(hMenuSub, RES_MENU_CHILD_MOREWINDOWS, MF_BYCOMMAND);
}
else
hMenuSub = hMenu;
}
/* Check to see what kind of window is requesting */
if (hwnd)
{
GetClassName(hwnd, szClassName, sizeof(szClassName));
if (_stricmp(Frame_achClassName, szClassName) == 0)
{
/* The window calling this function is a frame window */
twTop = GetPrivateData(hwnd);
}
else
{
/* An image viewer or sound player window is requesting */
twTop = NULL;
}
}
else
twTop = NULL;
/* Add the first item in the window (currently active window) */
if (twTop && hwnd)
{
/* Add the document window as the first window in the list */
count++;
if (hMenu)
{
pBuffer = TW_GetMenuWithMnemonic(MB_GetWindowName(twTop), count);
InsertMenu(hMenuSub, 0xffffffff, MF_BYPOSITION | MF_STRING | MF_ENABLED | MF_CHECKED,
RES_MENU_CHILD__FIRST__, pBuffer);
GTR_FREE(pBuffer);
}
else
{
SendMessage(hListbox, LB_INSERTSTRING, (WPARAM) -1, (LPARAM) MB_GetWindowName(twTop));
}
}
else if (hwnd)
{
/* Add the image window or sound player window as the first window */
count++;
length = GetWindowTextLength(hwnd);
pText = GTR_MALLOC(length + 1);
GetWindowText(hwnd, pText, length + 1);
if (hMenu)
{
pBuffer = TW_GetMenuWithMnemonic(pText, count);
InsertMenu(hMenuSub, 0xffffffff, MF_BYPOSITION | MF_STRING | MF_ENABLED | MF_CHECKED,
RES_MENU_CHILD__FIRST__, pBuffer);
GTR_FREE(pBuffer);
}
else
{
SendMessage(hListbox, LB_INSERTSTRING, (WPARAM) -1, (LPARAM) pText);
}
GTR_FREE(pText);
}
/* Now go through the Mlist structure and add the windows */
tw = Mlist;
while (tw)
{
if (tw != twTop)
{
count++;
if (hMenu)
{
if (count - 1 + RES_MENU_CHILD__FIRST__ > RES_MENU_CHILD__LAST__)
{
InsertMenu(hMenuSub, 0xffffffff, MF_BYPOSITION | MF_STRING,
RES_MENU_CHILD_MOREWINDOWS, RES_MENU_LABEL_MOREWINDOWS);
return;
}
pBuffer = TW_GetMenuWithMnemonic(MB_GetWindowName(tw), count);
InsertMenu(hMenuSub, 0xffffffff, MF_BYPOSITION | MF_STRING | MF_ENABLED,
RES_MENU_CHILD__FIRST__ + count - 1, pBuffer);
GTR_FREE(pBuffer);
}
else
{
SendMessage(hListbox, LB_INSERTSTRING, (WPARAM) -1, (LPARAM) MB_GetWindowName(tw));
}
}
tw = tw->next;
}
/* Now add the image viewer windows */
#ifdef FEATURE_IMAGE_VIEWER
hDialog = Viewer_GetNextWindow(TRUE); /* Return the first viewer dialog */
while (hDialog)
{
if (hDialog != hwnd)
{
count++;
if (hMenu)
{
if (count - 1 + RES_MENU_CHILD__FIRST__ > RES_MENU_CHILD__LAST__)
{
InsertMenu(hMenuSub, 0xffffffff, MF_BYPOSITION | MF_STRING,
RES_MENU_CHILD_MOREWINDOWS, RES_MENU_LABEL_MOREWINDOWS);
return;
}
}
length = GetWindowTextLength(hDialog);
pText = GTR_MALLOC(length + 1);
GetWindowText(hDialog, pText, length + 1);
if (hMenu)
{
pBuffer = TW_GetMenuWithMnemonic(pText, count);
InsertMenu(hMenuSub, 0xffffffff, MF_BYPOSITION | MF_STRING | MF_ENABLED,
RES_MENU_CHILD__FIRST__ + count - 1, pBuffer);
GTR_FREE(pBuffer);
}
else
{
SendMessage(hListbox, LB_INSERTSTRING, (WPARAM) -1, (LPARAM) pText);
}
GTR_FREE(pText);
}
hDialog = Viewer_GetNextWindow(FALSE); /* Get next window */
}
#endif
/* Now add the sound player windows */
#ifdef FEATURE_SOUND_PLAYER
hDialog = SoundPlayer_GetNextWindow(TRUE); /* Return the first sound player dialog */
while (hDialog)
{
if (hDialog != hwnd)
{
count++;
if (hMenu)
{
if (count - 1 + RES_MENU_CHILD__FIRST__ > RES_MENU_CHILD__LAST__)
{
InsertMenu(hMenuSub, 0xffffffff, MF_BYPOSITION | MF_STRING,
RES_MENU_CHILD_MOREWINDOWS, RES_MENU_LABEL_MOREWINDOWS);
return;
}
}
length = GetWindowTextLength(hDialog);
pText = GTR_MALLOC(length + 1);
GetWindowText(hDialog, pText, length + 1);
if (hMenu)
{
pBuffer = TW_GetMenuWithMnemonic(pText, count);
InsertMenu(hMenuSub, 0xffffffff, MF_BYPOSITION | MF_STRING | MF_ENABLED,
RES_MENU_CHILD__FIRST__ + count - 1, pBuffer);
GTR_FREE(pBuffer);
}
else
{
SendMessage(hListbox, LB_INSERTSTRING, (WPARAM) -1, (LPARAM) pText);
}
GTR_FREE(pText);
}
hDialog = SoundPlayer_GetNextWindow(FALSE); /* Get next window */
}
#endif
}
/*
TW_ActivateWindowFromList
Activate the selected window from the Window list or listbox
Only ONE of menuID or listRow must be specified. (-1 == not used)
For menu items: menuID = valid, listRow = -1 , hSelectWindow = NULL
For list items: menuID = -1 , listRow = valid, hSelectWindow = dlg_selw window handle
For baby menu : menuID = listRow = valid, hSelectWindow = NULL
*/
void TW_ActivateWindowFromList(int menuID, int listRow, HWND hSelectWindow)
{
int document_count, count;
struct Mwin *tw, *twTop;
char szClassName[32];
BOOL document_selected;
HWND hDialog, hParent;
/* See if this is from the baby window */
if (menuID == listRow)
{
/* From the baby window. Only the first menu item will not be processed by
the code below, so handle the first menu item case here */
listRow = menuID - RES_MENU_CHILD__FIRST__;
if (listRow == 0)
{
twTop = Mlist;
TW_RestoreWindow(twTop->hWndFrame);
return;
}
twTop = NULL;
menuID = -1;
listRow++;
}
else if (menuID > -1)
{
/* Trying to activate a window from the window menu */
listRow = menuID - RES_MENU_CHILD__FIRST__;
if (listRow == 0)
return;
hParent = GetForegroundWindow();
GetClassName(hParent, szClassName, sizeof(szClassName));
if (_stricmp(Frame_achClassName, szClassName) == 0)
twTop = GetPrivateData(hParent); /* Top menu item is Mosaic document */
else
twTop = NULL; /* Top menu item is image/sound player */
}
else
{
/* Trying to activate a window from the window list (dlg_selw) */
if (listRow == 0)
return; /* Top menu item is the current window which will become active anyway */
/* Figure out whether the top menu item is Mosaic document or image/sound player */
hParent = GetParent(hSelectWindow);
GetClassName(hParent, szClassName, sizeof(szClassName));
if (_stricmp(Frame_achClassName, szClassName) == 0)
twTop = GetPrivateData(GetParent(hSelectWindow)); /* Top menu item is Mosaic document */
else
twTop = NULL; /* Top menu item is image/sound player */
}
/* Get the number of Mosaic document windows */
document_count = 0;
tw = Mlist;
while (tw)
{
document_count++;
tw = tw->next;
}
/* Figure out if the user selected a Mosaic document window or image/sound player */
if (twTop) /* Top menu item is a Mosaic document */
{
if (listRow < document_count)
document_selected = TRUE;
else
document_selected = FALSE;
}
else /* Top menu item is NOT a Mosaic document */
{
if (listRow - 1 < document_count)
document_selected = TRUE;
else
document_selected = FALSE;
}
/* Now find the right window to activate */
if (document_selected)
{
count = 1; /* skip the first row */
tw = Mlist;
while (tw)
{
if (tw != twTop)
{
if (count == listRow)
{
BringWindowToTop(tw->hWndFrame);
if (IsIconic(tw->hWndFrame))
ShowWindow(tw->hWndFrame, SW_RESTORE);
return;
}
count++;
}
tw = tw->next;
}
}
else
{
#ifdef FEATURE_IMAGE_VIEWER
/* Image viewer / sound player selected */
hDialog = Viewer_GetNextWindow(TRUE);
count = document_count;
if (!twTop)
count++;
while (hDialog)
{
if (hDialog != hParent)
{
if (count == listRow)
{
BringWindowToTop(hDialog);
if (IsIconic(hDialog))
ShowWindow(hDialog, SW_RESTORE);
return;
}
count++;
}
hDialog = Viewer_GetNextWindow(FALSE);
}
#endif
#ifdef FEATURE_SOUND_PLAYER
hDialog = SoundPlayer_GetNextWindow(TRUE);
while (hDialog)
{
if (hDialog != hParent)
{
if (count == listRow)
{
BringWindowToTop(hDialog);
if (IsIconic(hDialog))
ShowWindow(hDialog, SW_RESTORE);
return;
}
count++;
}
hDialog = SoundPlayer_GetNextWindow(FALSE);
}
#endif
}
return;
}
/*
TW_IsMosaicWindow
Returns TRUE if the specified window is a document window, image viewer,
or sound player window.
This function is necessary because all windows and dialogs within Mosaic
do not have parents (they have owners, however).
*/
BOOL TW_IsMosaicWindow(HWND hwnd)
{
char szClassName[32];
if (hwnd == wg.hWndHidden)
return FALSE;
GetClassName(hwnd, szClassName, sizeof(szClassName));
if (_stricmp(Frame_achClassName, szClassName) == 0)
return TRUE;
#ifdef FEATURE_IMAGE_VIEWER
if (Viewer_IsWindow(hwnd))
return TRUE;
#endif
#ifdef FEATURE_SOUND_PLAYER
if (SoundPlayer_IsWindow(hwnd))
return TRUE;
#endif
return FALSE;
}
/*
TW_CascadeWindows
Cascade all windows created by Mosaic
*/
/* This structure is used in building a reverse Z-order list for cascading & tiling */
struct ZOrderList
{
HWND hwnd;
struct ZOrderList *next;
};
void TW_CascadeWindows(void)
{
int screenheight, screenwidth;
int y_increment, x_increment;
int windowheight, windowwidth;
HWND hwnd;
int current;
struct ZOrderList *pList, *pItem, *pNext;
screenheight = GetSystemMetrics(SM_CYFULLSCREEN);
screenwidth = GetSystemMetrics(SM_CXFULLSCREEN);
/* Subtract from screen height the space reserved for minimized icons */
screenheight -= GetSystemMetrics(SM_CYICONSPACING);
/* We cascade up to eight windows before recycling, so figure out how
wide and high each window should be. */
x_increment = GetSystemMetrics(SM_CXSIZE) + GetSystemMetrics(SM_CXFRAME);
y_increment = GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYFRAME);
windowheight = screenheight - 7 * y_increment;
windowwidth = screenwidth - 7 * x_increment;
/* Ok, now go through the Z-order list in reverse order and cascade all windows
which belong to Mosaic */
pList = NULL;
hwnd = GetTopWindow(NULL);
while (hwnd)
{
if (TW_IsMosaicWindow(hwnd))
{
pItem = GTR_MALLOC(sizeof(struct ZOrderList));
pItem->hwnd = hwnd;
if (pList)
pItem->next = pList;
else
pItem->next = NULL;
pList = pItem;
}
hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
}
current = 0;
pItem = pList;
while (pItem)
{
if (!IsIconic(pItem->hwnd))
{
#ifdef FEATURE_SOUND_PLAYER
/* Sound Player dialogs must not be resized since they don't have sizeable borders */
if (SoundPlayer_IsWindow(pItem->hwnd))
{
SetWindowPos(pItem->hwnd, NULL, current * x_increment, current * y_increment,
0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
else
#endif
{
SetWindowPos(pItem->hwnd, NULL, current * x_increment, current * y_increment,
windowwidth, windowheight, SWP_NOZORDER);
}
current++;
if (current == 8)
current = 0;
}
pItem = pItem->next;
}
/* Clean up */
pItem = pList;
while (pItem)
{
pNext = pItem->next;
GTR_FREE(pItem);
pItem = pNext;
}
}
/*
TW_TileWindows
Tile all windows created by Mosaic
*/
void TW_TileWindows(void)
{
int screenheight, screenwidth;
int minimumheight, minimumwidth;
int maximumwindows;
HWND hwnd;
int current;
struct ZOrderList *pList, *pItem, *pNext;
int totalwindows, windows_per_row, windows_per_column, windows_left;
struct Mwin *tw;
int x, y, xpos, ypos, width, height;
/* We tile up to a maximum of three windows across, and n windows down,
limited by the minimum window size */
screenheight = GetSystemMetrics(SM_CYFULLSCREEN);
screenwidth = GetSystemMetrics(SM_CXFULLSCREEN);
minimumheight = GetSystemMetrics(SM_CYMIN);
minimumwidth = screenwidth / 3;
/* Subtract from screen height the space reserved for minimized icons */
screenheight -= GetSystemMetrics(SM_CYICONSPACING);
maximumwindows = 3 * (screenheight / minimumheight);
/* Get the total number of windows which are NOT iconized */
totalwindows = 0;
tw = Mlist;
while (tw)
{
if (!IsIconic(tw->hWndFrame))
totalwindows++;
tw = tw->next;
}
#ifdef FEATURE_IMAGE_VIEWER
hwnd = Viewer_GetNextWindow(TRUE);
while (hwnd)
{
if (!IsIconic(hwnd))
totalwindows++;
hwnd = Viewer_GetNextWindow(FALSE);
}
#endif
#ifdef FEATURE_SOUND_PLAYER
hwnd = SoundPlayer_GetNextWindow(TRUE);
while (hwnd)
{
if (!IsIconic(hwnd))
totalwindows++;
hwnd = SoundPlayer_GetNextWindow(FALSE);
}
#endif
/* Calculate some values */
if (totalwindows == 1)
{
windows_per_row = 1;
windows_per_column = 1;
}
else if (totalwindows == 2)
{
windows_per_row = 2;
windows_per_column = 1;
}
else if (totalwindows < maximumwindows)
{
windows_per_row = 3;
windows_per_column = totalwindows / 3;
}
else
{
windows_per_row = 3;
windows_per_column = screenheight / minimumheight;
}
/* Now build a reverse Z-order list */
pList = NULL;
hwnd = GetTopWindow(NULL);
while (hwnd)
{
if (TW_IsMosaicWindow(hwnd) && !IsIconic(hwnd))
{
pItem = GTR_MALLOC(sizeof(struct ZOrderList));
pItem->hwnd = hwnd;
if (pList)
pItem->next = pList;
else
pItem->next = NULL;
pList = pItem;
}
hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
}
/* Now tile the windows */
current = 0;
pItem = pList;
if (totalwindows < maximumwindows)
{
for (x = 0; x < windows_per_row; x++)
{
if (x == 2)
{
/* Last column - we may have less or more than windows_per_column because
the total number of windows may not be evenly divisible by 3 */
windows_left = totalwindows - 2 * windows_per_column;
}
else
windows_left = windows_per_column;
for (y = 0; y < windows_left; y++)
{
width = screenwidth / windows_per_row;
height = screenheight / windows_left;
xpos = x * width;
ypos = y * height;
#ifdef FEATURE_SOUND_PLAYER
if (SoundPlayer_IsWindow(pItem->hwnd))
SetWindowPos(pItem->hwnd, NULL, xpos, ypos, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
else
#endif
SetWindowPos(pItem->hwnd, NULL, xpos, ypos, width, height, SWP_NOZORDER);
pItem = pItem->next;
}
}
}
else
{
/* There are too many windows to show all at once, so overlap as needed */
width = screenwidth / windows_per_row;
height = screenheight / windows_per_column;
DoMore:
for (x = 0; x < windows_per_row; x++)
{
for (y = 0; y < windows_per_column; y++)
{
xpos = x * width;
ypos = y * height;
#ifdef FEATURE_SOUND_PLAYER
if (SoundPlayer_IsWindow(pItem->hwnd))
SetWindowPos(pItem->hwnd, NULL, xpos, ypos, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
else
#endif
SetWindowPos(pItem->hwnd, NULL, xpos, ypos, width, height, SWP_NOZORDER);
/* We are finished when there are no more windows to tile */
pItem = pItem->next;
if (!pItem)
goto Finished;
}
}
/* We have finished tiling the maximum number that can fit. There are still more
windows, so start tiling again from the beginning. */
goto DoMore;
}
/* Clean up */
Finished:
pItem = pList;
while (pItem)
{
pNext = pItem->next;
GTR_FREE(pItem);
pItem = pNext;
}
}
void TW_RestoreWindow(HWND hwnd)
{
if (IsWindow(hwnd))
{
SetForegroundWindow(hwnd);
if (IsIconic(hwnd))
ShowWindow(hwnd, SW_RESTORE);
}
}
HWND TW_GetNextWindow(HWND hwnd)
{
struct Mwin *tw = Mlist;
BOOL bFound = FALSE;
HWND hwndNext;
while (tw)
{
if (bFound)
return (tw->hWndFrame);
if (tw->hWndFrame == hwnd)
bFound = TRUE;
tw = tw->next;
}
#ifdef FEATURE_IMAGE_VIEWER
hwndNext = Viewer_GetNextWindow(TRUE);
while (hwndNext)
{
if (bFound)
return (hwndNext);
if (hwndNext == hwnd)
bFound = TRUE;
hwndNext = Viewer_GetNextWindow(FALSE);
}
#endif
#ifdef FEATURE_SOUND_PLAYER
hwndNext = SoundPlayer_GetNextWindow(TRUE);
while (hwndNext)
{
if (bFound)
return hwndNext;
if (hwndNext == hwnd)
bFound = TRUE;
hwndNext = SoundPlayer_GetNextWindow(FALSE);
}
#endif
return Mlist->hWndFrame;
}
void GTR_RefreshHistory()
{
if (DlgHOT_IsHistoryRunning())
{
DlgHOT_RefreshHistory();
}
}
void TW_EnableButton(HWND hwnd, BOOL bEnabled)
{
SendMessage(hwnd, WM_DO_ENABLE_BUTTON, (WPARAM) bEnabled, 0);
}
#ifdef FEATURE_TIME_BOMB
static void x_GetCookieFileName(char *filename)
{
char *p;
PREF_GetPrefsDirectory(filename);
strcat(filename, vv_IniFileName);
p = strrchr(filename, '.');
if (p)
{
*p = 0;
}
strcat(filename, ".NST");
}
BOOL GTR_CheckTimeBombCookie(char *correct_cookie)
{
char filename[_MAX_PATH+1];
FILE *fp;
int len;
char *p;
BOOL bResult;
x_GetCookieFileName(filename);
fp = fopen(filename, "rb");
if (!fp)
{
return FALSE;
}
/* get the length of the data */
if (0 == fseek(fp, 0, SEEK_END))
{
len = ftell(fp);
if (len < 0)
{
len = 0;
}
fseek(fp, 0, SEEK_SET);
}
p = GTR_MALLOC(len);
if (!p)
{
return FALSE;
}
fread(p, 1, len, fp);
fclose(fp);
if (strstr(p, correct_cookie))
{
bResult = TRUE;
}
else
{
bResult = FALSE;
}
GTR_FREE(p);
return bResult;
}
time_t GTR_GetTimeBombDate(void)
{
char dte[32+1];
time_t time_start;
time_start = 0;
GetPrivateProfileString("DemoMode", "Date", "", dte, 32, AppIniFile);
if (dte[0])
{
sscanf(dte, "%u", &time_start);
}
return time_start;
}
void GTR_SetTimeBombDate(time_t time_start)
{
char dte[32+1];
sprintf(dte, "%u", time_start);
WritePrivateProfileString("DemoMode", "Date", dte, AppIniFile);
}
#endif
char *GTR_GetString(int stringID)
{
LoadString(wg.hInstance, stringID, szStringBuffer, sizeof(szStringBuffer));
return (szStringBuffer);
}
char *GTR_GetStringAbsolute(int stringID, char *buffer, int bufsize)
{
/* Clear the buffers. This is necessary because some strings have embedded NULLs. */
memset(buffer, 0, bufsize);
memset(szStringBuffer, 0, sizeof(szStringBuffer));
/* Copy the specified size or the size of the string buffer, whichever is less */
LoadString(wg.hInstance, stringID, szStringBuffer, sizeof(szStringBuffer));
memcpy(buffer, szStringBuffer, min(bufsize, sizeof(szStringBuffer)));
return (buffer);
}
/* ------------------------------------------------------------------------ */
/*
FONT HANDLING CODE
The following code manages the font handling for Mosaic. It keeps
track of a cache of fonts. trying to minimize the number of fonts
which actually get created.
*/
struct hash_table *gFontCache;
int FONT_AddToCache(char *fids, struct GTRFont *pFont)
{
if (!gFontCache)
{
gFontCache = Hash_Create();
}
XX_DMsg(DBG_FONT, ("Adding %s to font cache\n", fids));
XX_DMsg(DBG_FONT, ("Font Cache will now contain %d items\n", Hash_Count(gFontCache)));
return Hash_AddAndReturnIndex(gFontCache, fids, NULL, pFont);
}
static int point_size_array[] =
{
/*
The following are point sizes for logical font
sizes 1 thru 7.
*/
9,
10,
12,
14,
18,
24,
36,
/*
The following correspond to logical font sizes
8 thru 13, which are used for H1 thru H6, respectively
*/
24,
20,
18,
16,
14,
14
};
/*
This function takes a logical font size (which may have come
from a FONT tag, or from a header tag, or simply just defaults),
and comes up with a proper font size in points. I don't consider
this function shareable, because it doesn't make much sense on
UNIX where scalable fonts can't always be counted upon.
*/
int GTR_MapLogicalFontSize(int logical_font_size, int base_point_size)
{
int siz;
float size_factor;
/*
Basically, the idea here is to use the array of 'nice'
sizes above, and then adjust off that for the amount
that the base point size differs from the array's
base point size.
*/
if (logical_font_size < 1)
{
logical_font_size = 1;
}
siz = point_size_array[logical_font_size - 1];
/*
Assuming that Normal (user text size 2) corresponds to a base point size of 9,
like that contained in point_size_array, then siz now contains the point
size corresponding to the logical font size, based on Normal.
Now, we need to adjust up or down based on the percentage difference between
our base_point_size and the Normal base_point_size.
*/
size_factor = base_point_size / ((float) point_size_array[0]);
siz = (int) (siz * size_factor);
return siz;
}
/*
The font cache must be flushed anytime the user changes either the face or
base point size. This function is also used at program exit.
*/
void FONT_FlushCache(void)
{
int i;
int count;
struct GTRFont *pFont;
if (!gFontCache)
{
return;
}
count = Hash_Count(gFontCache);
for (i=0; i<count; i++)
{
Hash_GetIndexedEntry(gFontCache, i, NULL, NULL, (void **) &pFont);
if (pFont && pFont->hFont)
{
DeleteObject(pFont->hFont);
GTR_FREE(pFont);
}
}
Hash_Destroy(gFontCache);
gFontCache = NULL;
}
/*
This is the function which actually creates the font
*/
int GTR_GetProperFont(struct GTR_Font_Request *pfr, int base_point_size, HTAtom atomCharSet, unsigned int nLogPixelsY)
{
char font_identifier_string[255 + 1];
int actual_point_size;
struct GTRFont *pFont;
int ndx;
XX_DMsg(DBG_FONT, ("GTR_GetProperFont: base_point_size=%d logical_font_size=%d flags=%x\n",
base_point_size, pfr->logical_font_size, pfr->flags));
/*
First calculate the actual point size of this font
*/
if (pfr->flags & FONTBIT_MONOSPACE)
{
/*
We force monospace text to be one logical font size smaller. It looks better.
*/
actual_point_size = GTR_MapLogicalFontSize(pfr->logical_font_size - 1, base_point_size);
}
else
{
actual_point_size = GTR_MapLogicalFontSize(pfr->logical_font_size, base_point_size);
}
/*
Now, build a font identifer string to associate with this font for
the font cache.
*/
if (pfr->flags & FONTBIT_MONOSPACE)
{
strcpy(font_identifier_string, gPrefs.szMonospaceFontName);
}
else if (pfr->flags & FONTBIT_HEADER)
{
strcpy(font_identifier_string, gPrefs.szHeaderFontName);
}
else
{
strcpy(font_identifier_string, gPrefs.szMainFontName);
}
sprintf(font_identifier_string + strlen(font_identifier_string),
",%x,%d,%d,%s",
pfr->flags, actual_point_size, nLogPixelsY, HTAtom_name(atomCharSet));
XX_DMsg(DBG_FONT, ("GTR_GetProperFont: string is %s\n", font_identifier_string));
if (!gFontCache)
{
gFontCache = Hash_Create();
}
ndx = Hash_Find(gFontCache, font_identifier_string, NULL, NULL);
if (ndx < 0)
{
pFont = GTR_CALLOC(1, sizeof(struct GTRFont));
if (pFont)
{
HDC hdc;
HFONT oldFont;
hdc = GetDC(NULL);
/* fill in logical font structure with all default/sane values.
then parse the string supplied and override individual fields
as necessary. */
pFont->lf.lfHeight = 0;
pFont->lf.lfWidth = 0;
pFont->lf.lfEscapement = 0;
pFont->lf.lfOrientation = 0;
pFont->lf.lfWeight = FW_NORMAL;
pFont->lf.lfItalic = FALSE;
pFont->lf.lfUnderline = FALSE;
pFont->lf.lfStrikeOut = FALSE;
pFont->lf.lfCharSet = ANSI_CHARSET;
pFont->lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
pFont->lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
pFont->lf.lfQuality = DEFAULT_QUALITY;
pFont->lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
pFont->lf.lfFaceName[0] = '\0';
if (pfr->flags & FONTBIT_MONOSPACE)
{
strcpy(pFont->lf.lfFaceName, gPrefs.szMonospaceFontName);
}
else if (pfr->flags & FONTBIT_HEADER)
{
strcpy(pFont->lf.lfFaceName, gPrefs.szHeaderFontName);
}
else
{
strcpy(pFont->lf.lfFaceName, gPrefs.szMainFontName);
}
if (pfr->flags & FONTBIT_BOLD)
{
pFont->lf.lfWeight = FW_BOLD;
}
else
{
pFont->lf.lfWeight = FW_NORMAL;
}
pFont->lf.lfHeight = -MulDiv(actual_point_size,
nLogPixelsY, 72);
if (pfr->flags & FONTBIT_ITALIC)
{
pFont->lf.lfItalic = TRUE;
}
if (pfr->flags & FONTBIT_UNDERLINE)
{
pFont->lf.lfUnderline = TRUE;
}
if (pfr->flags & FONTBIT_STRIKEOUT)
{
pFont->lf.lfStrikeOut = TRUE;
}
if (atomCharSet == HTAtom_for("x-sjis"))
{
pFont->lf.lfCharSet = SHIFTJIS_CHARSET;
}
pFont->hFont = CreateFontIndirect(&pFont->lf);
oldFont = SelectObject(hdc, pFont->hFont);
GetTextMetrics(hdc, &pFont->tm);
SelectObject(hdc, oldFont);
ReleaseDC(NULL, hdc);
ndx = FONT_AddToCache(font_identifier_string, pFont);
}
}
else
{
XX_DMsg(DBG_FONT, ("Found %s in cache at index %d\n",
font_identifier_string, ndx));
}
return ndx;
}
struct GTRFont *GTR_GetNormalFont(struct _www *pdoc)
{
struct GTR_Font_Request fr;
int base_point_size;
int ndx;
struct GTRFont *pFont;
HTAtom atomCharSet;
unsigned int nLogPixelsY;
if (pdoc)
{
base_point_size = pdoc->base_point_size;
atomCharSet = pdoc->atomCharSet;
nLogPixelsY = pdoc->nLogPixelsY;
}
else
{
base_point_size = GTR_GetCurrentBasePointSize(gPrefs.iUserTextSize);
atomCharSet = GTR_GetDefaultCharset();
{
HDC hdc;
hdc = GetDC(NULL);
nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
ReleaseDC(NULL, hdc);
}
}
fr.logical_font_size = BASE_LOGICAL_FONT_SIZE;
fr.flags = 0;
ndx = GTR_GetProperFont(&fr, base_point_size, atomCharSet, nLogPixelsY);
Hash_GetIndexedEntry(gFontCache, ndx, NULL, NULL, (void **) &pFont);
return pFont;
}
/*
This is the main function for determining what the right font is for
a given element. It's used during reformatting, display, and also during
font measurements for selections. The API for this function is shared,
but the implementation of it is essentially platform-specific.
*/
struct GTRFont *GTR_GetElementFont(struct _www *pdoc, struct _element *pel)
{
struct GTR_Font_Request fr;
int ndx;
struct GTRFont *pFont;
char *fids;
if (pel->type != ELE_TEXT)
{
return GTR_GetNormalFont(pdoc);
}
if (!gFontCache || (pel->portion.text.cached_font_index < 0))
{
/*
Given the inputs
pel->font_request
pel->lFlags & ELEFLAG_ANCHOR
pdoc->base_point_size
pdoc->atomCharSet;
*/
fr = pel->portion.text.font_request;
if (gPrefs.bUnderlineLinks && (pel->lFlags & ELEFLAG_ANCHOR))
{
fr.flags |= FONTBIT_UNDERLINE;
}
ndx = GTR_GetProperFont(&fr, pdoc->base_point_size, pdoc->atomCharSet, pdoc->nLogPixelsY);
XX_Assert((ndx < Hash_Count(gFontCache)), ("Font cache index out of range"));
pel->portion.text.cached_font_index = ndx;
}
pFont = NULL;
fids = NULL;
Hash_GetIndexedEntry(gFontCache, pel->portion.text.cached_font_index, &fids, NULL, (void **) &pFont);
XX_Assert((pFont && pFont->hFont), ("Invalid font being returned"));
return pFont;
}
struct GTRFont *GTR_GetMonospaceFont(struct _www *pdoc)
{
struct GTR_Font_Request fr;
int base_point_size;
int ndx;
struct GTRFont *pFont;
HTAtom atomCharSet;
unsigned int nLogPixelsY;
if (pdoc)
{
base_point_size = pdoc->base_point_size;
atomCharSet = pdoc->atomCharSet;
nLogPixelsY = pdoc->nLogPixelsY;
}
else
{
base_point_size = GTR_GetCurrentBasePointSize(gPrefs.iUserTextSize);
atomCharSet = GTR_GetDefaultCharset();
{
HDC hdc;
hdc = GetDC(NULL);
nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
ReleaseDC(NULL, hdc);
}
}
fr.logical_font_size = BASE_LOGICAL_FONT_SIZE;
fr.flags = FONTBIT_MONOSPACE;
ndx = GTR_GetProperFont(&fr, base_point_size, atomCharSet, nLogPixelsY);
Hash_GetIndexedEntry(gFontCache, ndx, NULL, NULL, (void **) &pFont);
return pFont;
}
BOOL Dir_IsDirectory (CONST char *pszLocalname)
{
DWORD dw;
dw = GetFileAttributes(pszLocalname);
if (dw == 0xffffffff)
{
return FALSE;
}
if (dw & FILE_ATTRIBUTE_DIRECTORY)
{
return TRUE;
}
return FALSE;
}
struct my_dir_state
{
HANDLE h;
WIN32_FIND_DATA wfd;
BOOL bJustOpened;
};
void * Dir_OpenDirectory (char *pszLocalname)
{
char pattern[MAX_PATH + 1];
struct my_dir_state *mds;
strcpy(pattern, pszLocalname);
DOS_EnforceEndingSlash(pattern);
strcat(pattern, "*");
mds = GTR_CALLOC(1, sizeof(*mds));
if (mds)
{
mds->h = FindFirstFile(pattern, &mds->wfd);
if (mds->h == INVALID_HANDLE_VALUE)
{
GTR_FREE(mds);
return NULL;
}
mds->bJustOpened = TRUE;
}
return mds;
}
BOOL Dir_NextEntry (void *dirp, HT_DirEntry *dir_ent)
{
struct my_dir_state *mds = dirp;
if (mds->bJustOpened)
{
mds->bJustOpened = FALSE;
}
else
{
if (!FindNextFile(mds->h, &mds->wfd))
{
return FALSE;
}
}
if (dir_ent && mds->wfd.cFileName[0])
{
strcpy(dir_ent->name, mds->wfd.cFileName);
dir_ent->size = mds->wfd.nFileSizeLow;
dir_ent->type = 0;
if (mds->wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
dir_ent->type |= HTDIR_DIR;
}
else
{
dir_ent->type |= HTDIR_FILE;
}
return TRUE;
}
else
{
return FALSE;
}
}
void Dir_CloseDirectory (void *dirp)
{
struct my_dir_state *mds = dirp;
FindClose(mds->h);
GTR_FREE(mds);
}