453 lines
10 KiB
C
453 lines
10 KiB
C
/* File: D:\WACKER\tdll\misc.c (Created: 27-Nov-1993)
|
|
*
|
|
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
|
|
* All rights reserved
|
|
*
|
|
* $Revision: 5 $
|
|
* $Date: 3/22/01 11:27a $
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#pragma hdrstop
|
|
|
|
#include "stdtyp.h"
|
|
#include "misc.h"
|
|
#include "tdll.h"
|
|
#include "htchar.h"
|
|
#include "globals.h"
|
|
#include "assert.h"
|
|
#include <term\res.h>
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* mscCenterWindowOnWindow
|
|
*
|
|
* DESCRIPTION:
|
|
* Center's first window on the second window. Assumes hwndChild is
|
|
* a direct descendant of hwndParent
|
|
*
|
|
* ARGUMENTS:
|
|
* hwndChild - window to center
|
|
* hwndParent - window to center on
|
|
*
|
|
* RETURNS:
|
|
* BOOL
|
|
*
|
|
*/
|
|
BOOL mscCenterWindowOnWindow(const HWND hwndChild, const HWND hwndParent)
|
|
{
|
|
RECT rChild, rParent;
|
|
int wChild, hChild, wParent, hParent;
|
|
int xNew, yNew;
|
|
int iMaxPos;
|
|
|
|
if (!IsWindow(hwndParent))
|
|
return FALSE;
|
|
|
|
if (!IsWindow(hwndChild))
|
|
return FALSE;
|
|
|
|
/* --- Get the Height and Width of the child window --- */
|
|
|
|
GetWindowRect(hwndChild, &rChild);
|
|
wChild = rChild.right - rChild.left;
|
|
hChild = rChild.bottom - rChild.top;
|
|
|
|
/* --- Get the Height and Width of the parent window --- */
|
|
|
|
GetWindowRect(hwndParent, &rParent);
|
|
wParent = rParent.right - rParent.left;
|
|
hParent = rParent.bottom - rParent.top;
|
|
|
|
/* --- Calculate new X position, then adjust for screen --- */
|
|
|
|
xNew = rParent.left + ((wParent - wChild) / 2);
|
|
|
|
/* --- Calculate new Y position, then adjust for screen --- */
|
|
|
|
// Let's display the dialog so that the title bar is visible.
|
|
//
|
|
iMaxPos = GetSystemMetrics(SM_CYSCREEN);
|
|
yNew = min(iMaxPos, rParent.top + ((hParent - hChild) / 2));
|
|
|
|
//mpt:3-13-98 Need to make sure dialog is not off the screen
|
|
if (yNew < 0)
|
|
{
|
|
yNew = 0;
|
|
}
|
|
|
|
if (xNew < 0)
|
|
{
|
|
xNew = 0;
|
|
}
|
|
|
|
// Set it, and return
|
|
//
|
|
return SetWindowPos(hwndChild, 0, xNew, yNew, 0, 0,
|
|
SWP_NOSIZE | SWP_NOZORDER);
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* mscStripPath
|
|
*
|
|
* DESCRIPTION:
|
|
* Strip off the path from the file name.
|
|
*
|
|
* ARGUMENTS:
|
|
* pszStr - pointer to a null terminated string.
|
|
*
|
|
* RETURNS:
|
|
* void.
|
|
*/
|
|
LPTSTR mscStripPath(LPTSTR pszStr)
|
|
{
|
|
LPTSTR pszStart, psz;
|
|
|
|
if (pszStr == 0)
|
|
return 0;
|
|
|
|
for (psz = pszStart = pszStr; *psz ; psz = StrCharNext(psz))
|
|
{
|
|
if (*psz == TEXT('\\') || *psz == TEXT(':'))
|
|
pszStart = StrCharNext(psz);
|
|
}
|
|
|
|
StrCharCopy(pszStr, pszStart);
|
|
return pszStr;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* mscStripName
|
|
*
|
|
* DESCRIPTION:
|
|
* Strip off the name of the file, leave just the path.
|
|
*
|
|
* ARGUMENTS:
|
|
* pszStr - pointer to a null terminated string.
|
|
*
|
|
* RETURNS:
|
|
* void.
|
|
*/
|
|
LPTSTR mscStripName(LPTSTR pszStr)
|
|
{
|
|
LPTSTR pszEnd, pszStart = pszStr;
|
|
|
|
if (pszStr == 0)
|
|
return 0;
|
|
|
|
for (pszEnd = pszStr; *pszStr; pszStr = StrCharNext(pszStr))
|
|
{
|
|
if (*pszStr == TEXT('\\') || *pszStr == TEXT(':'))
|
|
pszEnd = StrCharNext(pszStr);
|
|
}
|
|
|
|
*pszEnd = TEXT('\0');
|
|
return (pszStart);
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* mscStripExt
|
|
*
|
|
* DESCRIPTION:
|
|
* Strip off the file extension. The parameter string can be a full-path
|
|
* or just a file name.
|
|
*
|
|
* ARGUMENTS:
|
|
* pszStr - pointer to a null terminated string.
|
|
*
|
|
* RETURNS:
|
|
* void.
|
|
*/
|
|
LPTSTR mscStripExt(LPTSTR pszStr)
|
|
{
|
|
LPTSTR pszEnd, pszStart = pszStr;
|
|
|
|
for (pszEnd = pszStr; *pszStr; pszStr = StrCharNext(pszStr))
|
|
{
|
|
// Need to check for both '.' and '\\' because directory names
|
|
// can have extensions as well.
|
|
//
|
|
if (*pszStr == TEXT('.') || *pszStr == TEXT('\\'))
|
|
pszEnd = pszStr;
|
|
}
|
|
|
|
if (*pszEnd == TEXT('.'))
|
|
*pszEnd = TEXT('\0');
|
|
|
|
return pszStart;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* mscModifyToFit
|
|
*
|
|
* DESCRIPTION:
|
|
* If a string won't fit in a given window then chop-off as much as possible
|
|
* to be able to display a part of the string with ellipsis concatanated to
|
|
* the end of it.
|
|
*
|
|
* NOTE: I've attempted to make this code DBCS aware.
|
|
*
|
|
* ARGUMENTS:
|
|
* hwnd - control window, where the text is to be displayed.
|
|
* pszStr - pointer to the string to be displayed.
|
|
*
|
|
* RETURNS:
|
|
* lpszStr - pointer to the modified string.
|
|
*
|
|
*/
|
|
LPTSTR mscModifyToFit(HWND hwnd, LPTSTR pszStr)
|
|
{
|
|
HDC hDC;
|
|
SIZE sz;
|
|
HFONT hFontSave, hFont;
|
|
RECT rc;
|
|
TCHAR ach[512], achEllipsis[10];
|
|
int nWidth = 0, i = 0;
|
|
|
|
TCHAR_Fill(ach, TEXT('\0'), sizeof(ach) / sizeof(TCHAR));
|
|
memset(&hFont, 0, sizeof(HFONT));
|
|
memset(&hFontSave, 0, sizeof(HFONT));
|
|
memset(&rc, 0, sizeof(RECT));
|
|
|
|
GetWindowRect(hwnd, &rc);
|
|
nWidth = rc.right - rc.left;
|
|
|
|
hDC = GetDC(hwnd);
|
|
|
|
hFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0);
|
|
if (hFont)
|
|
hFontSave = SelectObject(hDC, hFont);
|
|
|
|
// TODO: I think here the string pszStr would have to be "deflated"
|
|
// before we continue. The rest of the code should stay the same.
|
|
//
|
|
GetTextExtentPoint(hDC, (LPCTSTR)pszStr, StrCharGetStrLength(pszStr), &sz);
|
|
if (sz.cx > nWidth)
|
|
{
|
|
LoadString(glblQueryDllHinst(), IDS_GNRL_ELLIPSIS,
|
|
achEllipsis, sizeof(achEllipsis) / sizeof(TCHAR));
|
|
|
|
StrCharCopy(ach, achEllipsis);
|
|
StrCharCat(ach, pszStr);
|
|
i = StrCharGetStrLength(ach);
|
|
|
|
while ((i > 0) && (sz.cx > nWidth))
|
|
{
|
|
GetTextExtentPoint(hDC, (LPCTSTR)ach, i, &sz);
|
|
i -= 1;
|
|
}
|
|
TCHAR_Fill(ach, TEXT('\0'), sizeof(ach) / sizeof(TCHAR));
|
|
StrCharCopyN(ach, pszStr, i);
|
|
StrCharCat(ach, achEllipsis);
|
|
StrCharCopy(pszStr, ach);
|
|
}
|
|
|
|
// Select the previously selected font, release DC.
|
|
//
|
|
if (hFontSave)
|
|
SelectObject(hDC, hFontSave);
|
|
ReleaseDC(hwnd, hDC);
|
|
|
|
return pszStr;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* extLoadIcon
|
|
*
|
|
* DESCRIPTION:
|
|
* Gets the icon from the hticons.dll. The extension handlers use
|
|
* this dll for icons and need to not link load anything more than
|
|
* absolutely necessary, otherwise, this function would go in the
|
|
* icon handler code.
|
|
*
|
|
* ARGUMENTS:
|
|
* id - string id of resource (can be MAKEINTRESOURCE)
|
|
*
|
|
* RETURNS:
|
|
* HICON or zero on error.
|
|
*
|
|
*/
|
|
HICON extLoadIcon(LPCSTR id)
|
|
{
|
|
static HINSTANCE hInstance;
|
|
|
|
if (hInstance == 0)
|
|
{
|
|
if ((hInstance = LoadLibrary("hticons")) == 0)
|
|
{
|
|
assert(FALSE);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return LoadIcon(hInstance, id);
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* mscCreatePath
|
|
*
|
|
* DESCRIPTION:
|
|
* Creates the given path. This function is somewhat tricky so study
|
|
* it carefully before modifying it. Despite it's simplicity, it
|
|
* accounts for all boundary conditions. - mrw
|
|
*
|
|
* ARGUMENTS:
|
|
* pszPath - path to create
|
|
*
|
|
* RETURNS:
|
|
* 0=OK,else error
|
|
*
|
|
*/
|
|
int mscCreatePath(const TCHAR *pszPath)
|
|
{
|
|
TCHAR ach[512];
|
|
TCHAR *pachTok;
|
|
|
|
if (pszPath == 0)
|
|
return -1;
|
|
|
|
StrCharCopy(ach, pszPath);
|
|
pachTok = ach;
|
|
|
|
// Basicly, we march along the string until we encounter a '\', flip
|
|
// it to a NULL and try to create the path up to that point.
|
|
// It would have been nice if CreateDirectory() could
|
|
// create sub/sub directories, but it don't. - mrw
|
|
//
|
|
while (1)
|
|
{
|
|
if ((pachTok = StrCharFindFirst(pachTok, TEXT('\\'))) == 0)
|
|
{
|
|
if (!mscIsDirectory(ach) && !CreateDirectory(ach, 0))
|
|
return -2;
|
|
|
|
break;
|
|
}
|
|
|
|
if (pachTok != ach)
|
|
{
|
|
*pachTok = TEXT('\0');
|
|
|
|
if (!mscIsDirectory(ach) && !CreateDirectory(ach, 0))
|
|
return -3;
|
|
|
|
*pachTok = TEXT('\\');
|
|
}
|
|
|
|
pachTok = StrCharNext(pachTok);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
|
* FUNCTION:
|
|
* mscIsDirectory
|
|
*
|
|
* DESCRIPTION:
|
|
* Checks to see if a string is a valid directory or not.
|
|
*
|
|
* PARAMETERS:
|
|
* pszName -- the string to test
|
|
*
|
|
* RETURNS:
|
|
* TRUE if the string is a valid directory, otherwise FALSE.
|
|
*
|
|
*/
|
|
int mscIsDirectory(LPCTSTR pszName)
|
|
{
|
|
DWORD dw;
|
|
|
|
dw = GetFileAttributes(pszName);
|
|
|
|
if ((dw != (DWORD)-1) && (dw & FILE_ATTRIBUTE_DIRECTORY))
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
|
* FUNCTION:
|
|
* mscAskWizardQuestionAgain
|
|
*
|
|
* DESCRIPTION:
|
|
* Reads a value from the Registry. This value represents how many times
|
|
* the user responded "NO" to the question: "Do you want to run the
|
|
* New Modem Wizard?". We won't ask this question any more if the
|
|
* user responded no, twice.
|
|
*
|
|
* PARAMETERS:
|
|
* None
|
|
*
|
|
* RETURNS:
|
|
* TRUE if the modem wizard question should be asked again, otherwize
|
|
* FALSE.
|
|
*
|
|
*/
|
|
int mscAskWizardQuestionAgain(void)
|
|
{
|
|
long lResult;
|
|
DWORD dwKeyValue = 0;
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
TCHAR *pszAppKey = "HYPERTERMINAL";
|
|
|
|
dwSize = sizeof(DWORD);
|
|
|
|
lResult = RegQueryValueEx(HKEY_CLASSES_ROOT, (LPTSTR)pszAppKey, 0,
|
|
&dwType, (LPBYTE)&dwKeyValue, &dwSize);
|
|
|
|
// If we are able to read a value from the registry and that value
|
|
// is 1, there is no need to ask the question again, so return
|
|
// a false value.
|
|
//
|
|
if ( (lResult == ERROR_SUCCESS) && (dwKeyValue >= 1) )
|
|
return (FALSE);
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
|
* FUNCTION:
|
|
* mscUpdateRegistryValue
|
|
*
|
|
* DESCRIPTION:
|
|
* See mscAskWizardQuestionAgain. If the user responds "NO" to this
|
|
* question, we update a counter in the registry.
|
|
*
|
|
* PARAMETERS:
|
|
* None
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*/
|
|
void mscUpdateRegistryValue(void)
|
|
{
|
|
long lResult;
|
|
DWORD dwKeyValue = 0;
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
TCHAR *pszAppKey = "HYPERTERMINAL";
|
|
|
|
dwSize = sizeof(DWORD);
|
|
|
|
lResult = RegQueryValueEx(HKEY_CLASSES_ROOT, (LPTSTR)pszAppKey, 0,
|
|
&dwType, (LPBYTE)&dwKeyValue, &dwSize);
|
|
|
|
dwKeyValue += 1;
|
|
|
|
lResult = RegSetValueEx(HKEY_CLASSES_ROOT, pszAppKey, 0,
|
|
REG_BINARY, (LPBYTE)&dwKeyValue, dwSize);
|
|
|
|
assert(lResult == ERROR_SUCCESS);
|
|
|
|
return;
|
|
}
|