Windows2000/private/windbg64/windbg/util.c
2020-09-30 17:12:32 +02:00

3073 lines
69 KiB
C

/*--Author:
Griffith Wm. Kadnier (v-griffk) 01-Aug-1992
Environment:
Win32, User Mode
--*/
#include "precomp.h"
#pragma hdrstop
#include "direct.h"
LRESULT SendMessageNZ (HWND,UINT,WPARAM,LPARAM);
static BOOL CompareFileName(LPSTR, LPSTR);
static BOOL CompareFileNameWithPath(LPSTR, LPSTR);
#include <ime.h>
typedef BOOL (WINAPI *LPWINNLSENABLEIME)(HWND, BOOL);
typedef LRESULT (WINAPI *LPSENDIMEMESSAGEEX)(HWND, LPARAM);
static LPWINNLSENABLEIME lpfnWINNLSEnableIME = NULL;
static LPSENDIMEMESSAGEEX lpfnSendIMEMessageEx = NULL;
static HINSTANCE hModUser32 = NULL;
HWND
MDIGetActive(
HWND hwndParent,
BOOL *lpbMaximized
)
/*++
Routine Description:
Create the command window.
Arguments:
hwndParent - The parent window to the command window. In an MDI document,
this is usually the handle to the MDI client window: g_hwndMDIClient
Return Value:
The return value is the handle to the active MDI child window.
NULL if no MDI window has been created.
--*/
{
Assert(IsWindow(hwndParent));
return (HWND)SendMessage(hwndParent,
WM_MDIGETACTIVE,
0,
(LPARAM)lpbMaximized
);
}
/*** FileExist
** Synopsis:
** bool = FileExist(szFileName)
** Entry:
** szFileName - Name of file to check for
** Returns:
** TRUE if file exists and FALSE otherwise
** Description:
** Checks to see if a file exists with the path/filename
** described by the string pointed to by 'fileName'.
*/
BOOL
FileExist(
LPSTR pszFileName
)
{
HANDLE hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile) {
return FALSE;
} else {
CloseHandle(hFile);
return TRUE;
}
} /* FileExist() */
/*** hGetBoxParent
** Synopsis:
** hwnd = hGetBoxParent()
** Entry:
** none
** Returns:
** Description:
** Gets a suitable parent window handle for an
** invocation of a message or dialog box.
** Helper function to util.c functions so declared
** near.
*/
HWND
hGetBoxParent()
{
HWND hCurWnd;
int i=0;
hCurWnd = GetFocus();
if (hCurWnd) {
while (GetWindowLong(hCurWnd, GWL_STYLE) & WS_CHILD) {
hCurWnd = GetParent(hCurWnd);
Dbg(++i < 100);
}
} else {
hCurWnd = hwndFrame;
}
return hCurWnd;
} /* hGetBoxParent() */
/*
FUNCTION: MsgBox
PURPOSE: General purpose message box routine which takes
a pointer to the message text. Provides
program title as caption.
*/
int
PASCAL
MsgBox(
HWND hwndParent,
LPSTR szText,
UINT wType
)
/*++
Routine Description:
Generial purpose message box routine which takes a pointer to a message
text and prvoides the program title for the caption of the message box.
Arguments:
hwndParament - Supplies the parent window handle for the message box
szText - Supplies a pointer to the message box text.
wType - Supplies the message box type (to specify buttons)
Return Value:
Returns the message box return code
--*/
{
int MsgBoxRet = IDOK;
if (NoPopups) {
// log the string to the command win in case testing
// or when the remote server is running
CmdLogFmt ("%s\r\n", szText);
} else {
BoxCount++;
MsgBoxRet = MessageBox(hwndParent, szText, (LPSTR)MainTitleText, wType);
BoxCount--;
}
return MsgBoxRet;
} /* MsgBox() */
/*
FUNCTION: VarMsgBox
PURPOSE: As MsgBox but takes resource id as text and performs
a vsprintf on the variable parameters.
*/
int
CDECL
VarMsgBox(
HWND hwndParent,
WORD wFormat,
UINT wType,
...)
{
char szFormat[MAX_MSG_TXT];
char szText[MAX_VAR_MSG_TXT]; // size is as big as considered necessary
va_list vargs;
// load format string from resource file
Dbg(LoadString(g_hInst, wFormat, (LPSTR)szFormat, MAX_MSG_TXT));
va_start(vargs, wType);
vsprintf(szText, szFormat, vargs);
va_end(vargs);
return MsgBox(hwndParent, szText, wType);
} /* VarMsgBox() */
/*** ErrorBox
** Synopsis:
** int = ErrorBox(wErrorFormat, ...)
** Entry:
** wErrorFormat
** ...
** Returns:
** FALSE
** Description:
** Display an error message box with an "Error" title, an OK
** button and a Exclamation Icon. First parameter is a
** reference string in the ressource file. The string
** can contain printf formatting chars, the arguments
** follow from the second parameter onwards.
*/
int
CDECL
ErrorBox(
int wErrorFormat,
...
)
{
char szErrorFormat[MAX_MSG_TXT];
char szErrorText[MAX_VAR_MSG_TXT]; // size is as big as considered necessary
va_list vargs;
// load format string from resource file
Dbg(LoadString(g_hInst, wErrorFormat, (LPSTR)szErrorFormat, MAX_MSG_TXT));
va_start(vargs, wErrorFormat);
vsprintf(szErrorText, szErrorFormat, vargs);
va_end(vargs);
MsgBox(hwndFrame, (LPSTR)szErrorText, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
return FALSE; //Keep it always FALSE please
} /* ErrorBox() */
/*** ErrorBox2
** Synopsis:
** int = ErrorBox2(hwnd, type, wErrorFormat, ...)
** Entry:
** Return:
** FALSE
** Description:
** Display an error message box with an "Error" title, an OK
** button and a Exclamation Icon. First is the window handle
** of the parent window. Second is the extra types given
** to the message box.Third parameter is a reference string
** in the ressource file. The string can contain printf
** formatting chars, the arguments follow from the fourth
** parameter onwards.
*/
int
CDECL
ErrorBox2(
HWND hwnd,
UINT type,
WORD wErrorFormat,
...
)
{
char szErrorFormat[MAX_MSG_TXT];
char szErrorText[MAX_VAR_MSG_TXT]; // size is as big as considered necessary
va_list vargs;
// load format string from resource file
Dbg(LoadString(g_hInst, wErrorFormat, (LPSTR)szErrorFormat, MAX_MSG_TXT));
// set up szErrorText from passed parameters
va_start(vargs, wErrorFormat);
vsprintf(szErrorText, szErrorFormat, vargs);
va_end(vargs);
MsgBox(hwnd, (LPSTR)szErrorText, type | MB_OK | MB_ICONINFORMATION);
return FALSE; //Keep it always FALSE please
} /* ErrorBox2() */
/*** InternalErrorBox
** Synopsis:
** int = InternalErrorBox(wDescript,...)
** Entry:
** Returns:
** FALSE
** Description:
*/
int
InternalErrorBox(
WORD wDescript
)
{
char szErrorFormat[MAX_MSG_TXT];
char szErrorText[MAX_VAR_MSG_TXT]; // size is as big as considered necessary
char szArgument[MAX_MSG_TXT];
//Load format and argument strings from resource file
Dbg(LoadString(g_hInst, ERR_Internal_Error, (LPSTR)szErrorFormat, MAX_MSG_TXT));
Dbg(LoadString(g_hInst, wDescript, (LPSTR)szArgument, MAX_MSG_TXT));
sprintf(szErrorText, szErrorFormat, (LPSTR)szArgument);
MsgBox(hwndFrame, (LPSTR)szErrorText, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
DebugBreak();
return FALSE;
} /* InternalErrorBox() */
/*** InformationBox
** Synopsis:
** void = InformationBox(wInfoFormat, ...)
** Entry:
** wInfoFormat - Resource index of format string
** ... - Additional informationto be displayed
** Returns:
** Nothing
** Description:
** Display an information message box with an "Information"
** title, an OK button and an Information Icon. First
** parameter is a reference string in the ressource file.
** The string can contain printf formatting chars, the
** arguments follow from the second parameter onwards.
*/
void
CDECL
InformationBox(
int wInfoFormat,
...
)
{
char szInfoFormat[MAX_MSG_TXT];
char szInfoText[MAX_VAR_MSG_TXT]; // size is as big as considered necessary
va_list vargs;
// load format string from resource file
Dbg(LoadString(g_hInst, wInfoFormat, (LPSTR)szInfoFormat, MAX_MSG_TXT));
// set up szInfoText from passed parameters
va_start(vargs, wInfoFormat);
vsprintf(szInfoText, szInfoFormat, vargs);
va_end(vargs);
MsgBox(hwndFrame, (LPSTR)szInfoText, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
return;
} /* InformationBox() */
/*** QuestionBox
** Synopsis:
** int = QuestionBox(wCaptionId, wMsgFormat, wType, ...)
** Entry:
** Returns:
** The result of the message box call
** Description:
** Display an query box with combination of YES, NO and
** CANCEL buttons and a question mark Icon.
** See ErrorBox for discussion.
*/
int
CDECL
QuestionBox(
WORD wMsgFormat,
UINT wType,
...
)
{
char szMsgFormat[MAX_MSG_TXT];
char szMsgText[MAX_VAR_MSG_TXT];
va_list vargs;
//Load format string from resource file
Dbg(LoadString(g_hInst, wMsgFormat, (LPSTR)szMsgFormat, MAX_MSG_TXT));
//Set up szMsgText from passed parameters
va_start(vargs, wType);
vsprintf(szMsgText, szMsgFormat, vargs);
va_end(vargs);
return MsgBox(hwndFrame, szMsgText,
wType | MB_ICONEXCLAMATION | MB_TASKMODAL);
} /* QuestionBox() */
/*
FUNCTION: QuestionBox2
PURPOSE: Display an query box with combination of YES, NO and
CANCEL buttons and a question mark Icon. The type and
the parent window are adjustable.
RETURNS: MessageBox result
*/
int
CDECL
QuestionBox2(
HWND hwnd,
WORD wMsgFormat,
UINT wType,
...
)
{
char szMsgFormat[MAX_MSG_TXT];
char szMsgText[MAX_VAR_MSG_TXT];
va_list vargs;
//Load format string from resource file
Dbg(LoadString(g_hInst, wMsgFormat, (LPSTR)szMsgFormat, MAX_MSG_TXT));
//Set up szMsgText from passed parameters
va_start(vargs, wType);
vsprintf(szMsgText, szMsgFormat, vargs);
va_end(vargs);
return MsgBox(hwnd, szMsgText, wType | MB_ICONEXCLAMATION);
} /* QuestionBox2() */
/*** FatalErrorBox
** Synopsis:
** void = FatalErrorBox(iLine, szText)
** Entry:
** iLine -
** szText -
** Returns:
** Nothing
** Description:
** This function will display an error message in a message box
** which has the title of "Error". The first paramter is an index
** of a string in the resource file and the second parameter is
** a literal which is displayed in the box.
*/
typedef struct _febargs {
LPSTR lpLine2;
WORD wLine1;
} FEBARGS;
DWORD
FatalErrorBoxThread(
LPVOID lpArgs
)
{
char text[MAX_MSG_TXT], buffer[MAX_VAR_MSG_TXT];
FEBARGS *pfa = (FEBARGS *)lpArgs;
if (pfa->wLine1 == 0) {
*text = 0;
} else {
LoadString(g_hInst, pfa->wLine1, text, MAX_MSG_TXT);
}
if (pfa->lpLine2) {
sprintf(buffer, "%s %s",text, pfa->lpLine2);
} else {
sprintf(buffer, "%s",text);
}
#if DBG
OutputDebugString(buffer);
OutputDebugString("\n\r");
#endif
strcat(buffer, "\r\nOK to ignore, CANCEL to break");
return MessageBox(NULL,
buffer,
MainTitleText,
MB_OKCANCEL | MB_ICONHAND | MB_TASKMODAL | MB_SETFOREGROUND);
} /* FatalErrorBoxThread() */
void
FatalErrorBox(
WORD wLine1,
LPSTR lpLine2
)
{
FEBARGS fa;
HANDLE hThread;
DWORD dw;
fa.wLine1 = wLine1;
fa.lpLine2 = lpLine2;
hThread = CreateThread(NULL, 0, FatalErrorBoxThread, &fa, 0, &dw);
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, &dw);
CloseHandle(hThread);
if (dw == IDCANCEL) {
DebugBreak();
}
} /* FatalErrorBox() */
/*** ShowAssert
** Synopsis:
** void = ShowAssert(szCond, iLine, szFile)
** Entry:
** szCond - tokenized form of the failed condition
** iLine - Line number for the assertion
** szFile - File for the assertion
** Returns:
** void
** Description:
** Prepare and display a Message Box with szCondition, iLine and
** szFile as fields.
*/
void
ShowAssert(
LPSTR condition,
UINT line,
LPSTR file
)
{
char text[MAX_VAR_MSG_TXT];
//Build line, show assertion and exit program
sprintf(text, "- Line:%u, File:%Fs, Condition:%Fs",
(WPARAM) line, file, condition);
if (!AutoTest) {
FatalErrorBox(ERR_Assertion_Failed, text);
} else {
char szBuffer[_MAX_PATH];
PSTR pszBuffer;
PSTR szAssertFile = "assert.qcw";
HANDLE hFile = NULL;
hFile = CreateFile(szAssertFile, GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != hFile) {
// Write the text out to the file
DWORD dwBytesWritten = 0;
Assert(WriteFile(hFile, text, strlen(text), &dwBytesWritten, NULL));
Assert(strlen(text) == dwBytesWritten);
CloseHandle(hFile);
}
CmdLogFmt( text );
exit(3);
}
} /* ShowAssert() */
/*** MakePathNameFromProg
** Synopsis:
** void = MakePathName(extension, fileName)
** Entry:
** extension - Pointer to string containing the extension to be used
** fileName - pointer to buffer for the resulting file name
** Returns:
** Nothing
** Description:
** This function will take the module name, the passed in extension
** and the current path to construct a full path name. An example of
** how this is used is in getting the ini file name.
*/
void
MakePathNameFromProg(
LPSTR extension,
LPSTR fileName
)
{
LPSTR pcFileName;
int nFileNameLen;
// Get the file name for the base module.
nFileNameLen = GetModuleFileName(g_hInst, fileName, _MAX_PATH);
pcFileName = fileName + nFileNameLen;
// Strip off any extensions found. Assume that atleast .exe exists
// M00BUG -- no extension on file name but a dot in the path.
while (pcFileName > fileName) {
pcFileName = CharPrev(fileName, pcFileName);
if (*pcFileName == '.') {
*(++pcFileName) = '\0';
break;
}
nFileNameLen -= (IsDBCSLeadByte(*pcFileName) ? 2 : 1);
}
// Make sure that the name is really an ansi string and that
// it is not too long.
OemToAnsi(fileName, fileName);
if ((nFileNameLen+lstrlen(extension)) < _MAX_PATH) {
lstrcat(fileName, extension);
} else {
ErrorBox(ERR_File_Name_Too_Long, fileName);
}
Assert(strlen(fileName) < _MAX_PATH);
} /* MakePathNameFromProg() */
/*** MakeFileNameFromProg
** Synopsis:
** void = MakeFileNameFromProg(extension, fileName)
** Entry:
** extension - Pointer to string containing the extension to be used
** fileName - pointer to buffer for the resulting file name
** Returns:
** Nothing
** Description:
** This function will take the module name, the passed in extension
** and the current path to construct a full path name. An example of
** how this is used is in getting the ini file name.
*/
void
MakeFileNameFromProg(
LPSTR extension,
LPSTR fileName
)
{
TCHAR szPath[_MAX_PATH];
TCHAR szDrive[_MAX_DRIVE];
TCHAR szDir[_MAX_DIR];
TCHAR szFName[_MAX_FNAME];
TCHAR szExt[_MAX_EXT];
int nFileNameLen;
// Get the file name for the base module.
nFileNameLen = GetModuleFileName(g_hInst, szPath, _MAX_PATH);
_splitpath(szPath, szDrive, szDir, szFName, szExt);
// Make sure that the name is really an ansi string and that
// it is not too long.
OemToAnsi(szFName, fileName);
if ((strlen(fileName)+strlen(extension)) < _MAX_FNAME) {
_fstrcat(fileName, extension);
} else {
ErrorBox(ERR_File_Name_Too_Long, fileName);
}
Assert(strlen(fileName) < _MAX_FNAME);
} /* MakePathNameFromProg() */
/*** StartDialog
** Synopsis:
** bool = StartDialog(rcDlgNb, dlgProc)
** Entry:
** rcDlgNb - Resource number of dialog to be openned
** dlgProc - Filter procedure for the dialog
** Returns:
** Result of the dialog box call
** Description:
** Loads and execute the dialog box 'rcDlgNb' (ressource
** file string number) associated with the dialog
** function 'dlgProc'
*/
BOOL
StartDialog(
int rcDlgNb,
DLGPROC dlgProc
)
{
DLGPROC lpDlgProc;
LRESULT result;
//TestRoutine();
lpDlgProc = (DLGPROC)dlgProc;
//Execute Dialog Box
DlgEnsureTitleBar();
BoxCount++;
result = DialogBox(g_hInst,
MAKEINTRESOURCE(rcDlgNb),
hGetBoxParent(),
lpDlgProc);
Assert(result != (LRESULT)-1);
BoxCount--;
return (result != 0);
} /* StartDialog() */
/*
FUNCTION: InvDlgCtlIdRect
PURPOSE: Invalidate the rectangle area of child 'ctlID' in
'hDlg' Dialog Box
*/
void
InvDlgCtlIdRect(
HWND hDlg,
int ctlID
)
{
HWND win;
Dbg(win = GetDlgItem(hDlg, ctlID));
InvalidateRect(win, (LPRECT)NULL, 1);
} /* InvDlgCtlIdRect() */
/*
FUNCTION: RemoveMnemonic
PURPOSE: Get rid of accelerator mark
*/
void
RemoveMnemonic(
LPSTR sWith,
LPSTR sWithout
)
{
int k, j = 0;
for (k = 0; k <= (int)lstrlen(sWith); k++) {
if (IsDBCSLeadByte(sWith[k]) && sWith[k+1]) {
sWithout[j++] = sWith[k++];
sWithout[j++] = sWith[k];
} else {
if (sWith[k] != '&') {
sWithout[j++] = sWith[k];
} else if (sWith[k+1] == '&') {
sWithout[j++] = sWith[k++];
}
}
}
} /* RemoveMnomonic() */
/*** fScanAnyLong
** Synopsis:
** Entry:
** Returns:
** Description:
*/
/*
FUNCTION: fScanAnyLong
PURPOSE: Converts the text form of a long value in
to the binary representation. The language
parameter specifies the expected format of the
number. If it is C then decimal, octal (leading 0)
and hex (leading 0x) are supported. If it is
Pascal then decimal and hex (leading $) are
handled. If it is AUTO then C is tried first
and Pascal if the conversion is unsuccessful.
RETURNS: TRUE if conversion is successful, FALSE if
not. To return TRUE a number must be successfully
scanned AND it must fall within the passed max and
min values.
*/
BOOL
PASCAL
fScanAnyLong(
LPSTR lpszSource,
WORD wLanguage,
long *plDest,
long lMin,
long lMax
)
{
long lLong = 0;
PSTR pszTmp;
BOOL fGotANumber = FALSE;
char szSource[80];
strncpy(szSource, lpszSource, sizeof(szSource)-1);
szSource[sizeof(szSource)-1] = '\0';
if ((wLanguage == PASCAL_LANGUAGE) || (wLanguage == AUTO_LANGUAGE)) {
// look for '$' first
// skip whitespace
pszTmp = szSource;
while (whitespace(*pszTmp)) pszTmp++;
if (*pszTmp == '$') {
pszTmp++;
lLong = strtol(pszTmp, (PSTR *)NULL, 16);
fGotANumber = TRUE;
} else if (wLanguage == PASCAL_LANGUAGE) {
// Try and read a decimal
lLong = strtol(pszTmp, (PSTR *)NULL, 10);
fGotANumber = TRUE;
}
}
if (!fGotANumber) {
lLong = strtol(szSource, (PSTR *)NULL, 0);
}
if ((lLong >= lMin) && (lLong <= lMax)) {
*plDest = lLong;
return TRUE;
}
return FALSE;
} /* fScanAnyLong() */
/*** QCQPEnumFonts
** Synopsis:
** int = QCQPEnumFonts(lf, mtr, type, data)
** Entry:
** lf
** mtr
** type
** data
** Returns:
** Description:
** Enumerates fonts faces names or font chars sizes
*/
int
CALLBACK
QCQPEnumFonts(
const LOGFONT * pLf,
const TEXTMETRIC * mtr,
DWORD fontType,
LPARAM data
)
{
#define NBOFSIZES 20
switch (LOWORD(data)) {
case 0:
//Just count the fonts, but skip the Decoratives
if (pLf->lfCharSet != SYMBOL_CHARSET
&& (pLf->lfPitchAndFamily & 0xF0) != FF_DECORATIVE) {
fontsNb++;
}
return 1;
case 1:
if (pLf->lfCharSet != SYMBOL_CHARSET
&& (pLf->lfPitchAndFamily & 0xF0) != FF_DECORATIVE) {
fonts[fontsNb] = *pLf;
fonts[fontsNb].lfWidth = 0;
fontsNb++;
}
return 1;
case 2:
//Just count the sizes for that font
if (fontType & RASTER_FONTTYPE) {
fontSizesNb++;
} else {
fontSizesNb = NBOFSIZES;
}
return 1;
case 3:
{
int i = 0;
if (fontType & RASTER_FONTTYPE) {
//Insert the new element sorted in the array
while (i < fontSizesNb && pLf->lfHeight > fontSizes[i]) {
i++;
}
if (i < fontSizesNb) {
//We don't insert the duplicates
if (pLf->lfHeight == fontSizes[i]) {
return 1;
}
//Insert element
memmove(fontSizes + i + 1, fontSizes + i,
(fontSizesNb - i) * sizeof(*fontSizes));
memmove(fontSizesPoint + i + 1, fontSizesPoint + i,
(fontSizesNb - i) * sizeof(*fontSizesPoint));
}
//Store size in pixels
fontSizes[i] = pLf->lfHeight;
//Store pixels converted into points
fontSizesPoint[i] =
(int)((72L * (pLf->lfHeight - mtr->tmInternalLeading)
+ (HIWORD((DWORD)data) / 2)) / (HIWORD((DWORD)data)));
fontSizesNb++;
} else {
int k = 6;
fontSizesNb = NBOFSIZES;
//Put a set of sizes in the array
for (i = 0 ; i < fontSizesNb; i++) {
fontSizesPoint[i] = k;
fontSizes[i] = (int)((k * (HIWORD((DWORD)data)) + 72L / 2) / 72L);
k +=2;
}
}
return 1;
}
}
// Stop enumerating
return 0;
} /* QCQPEnumFonts() */
/*** GetFontSizes
** Synopsis:
** void = GetFontSizes(hWnd, currentFont)
** Entry:
** hWnd -
** currentFont -
** Returns:
** nothing
** Description
*/
void
GetFontSizes(
HWND hWnd,
int currentFont
)
{
HDC hDC;
FONTENUMPROC EnumProc;
hDC = GetDC(hWnd);
//Dbg((LONG) (EnumProc = (FONTENUMPROC) MakeProcInstance((FARPROC)QCQPEnumFonts, g_hInst)));
EnumProc = QCQPEnumFonts;
//First query the number of sizes for this font
fontSizesNb = 0;
EnumFonts(hDC, fonts[currentFont].lfFaceName, EnumProc, 2);
//Allocates the array to store the sizes and query the sizes
if (fontSizes != NULL) {
Xfree((LPSTR)fontSizes);
Xfree((LPSTR)fontSizesPoint);
}
fontSizes = (LPINT)Xalloc(fontSizesNb * sizeof(*fontSizes));
fontSizesPoint = (LPINT)Xalloc(fontSizesNb * sizeof(*fontSizesPoint));
fontSizesNb = 0;
EnumFonts(hDC, fonts[currentFont].lfFaceName, EnumProc,
MAKELONG(3, GetDeviceCaps(hDC, LOGPIXELSY)));
//FreeProcInstance(EnumProc);
ReleaseDC(hWnd, hDC);
} /* GetFontSizes() */
/*** LoadFonts
** Synopsis:
** void = LoadFonts(hWnd)
** Entry:
** hWnd -
** Returns:
** nothing
** Description:
** Load available fonts
*/
void
LoadFonts(
HWND hWnd
)
{
HDC hDC;
FONTENUMPROC EnumProc;
hDC = GetDC(hWnd);
//Dbg((LONG) (EnumProc = (FONTENUMPROC) MakeProcInstance((FARPROC)QCQPEnumFonts, g_hInst)));
EnumProc = QCQPEnumFonts;
//First count the number of fonts
fontsNb = 0;
EnumFonts(hDC, NULL, EnumProc, 0);
//Allocates the array to store the fonts and query the fonts
if (fonts != NULL) {
Xfree((LPSTR)fonts);
}
fonts = (LPLOGFONT)Xalloc(fontsNb * sizeof(*fonts));
fontsNb = 0;
EnumFonts(hDC, NULL, EnumProc, 1);
fontCur = 0;
//FreeProcInstance(EnumProc);
ReleaseDC(hWnd, hDC);
} /* LoadFonts() */
#if defined( NEW_WINDOWING_CODE )
HWND
New_OpenDebugWindow(
WIN_TYPES winType,
BOOL bUserActivated
)
/*++
Routine Description:
Opens Cpu, Watch, Locals, Calls, or Memory Window under MDI
Handles special case for memory win's
Arguments:
winType - Supplies Type of debug window to be openned
bUserActivated - Indicates whether this action was initiated by the
user or by windbg. The value is to determine the Z order of
any windows that are opened.
Return Value:
Window handle.
NULL if an error occurs.
--*/
{
HWND hwndActivate = 0;
switch (winType) {
default:
Assert(!"Invalid window type. Ignorable error.");
break;
case WATCH_WINDOW:
if (g_DebuggerWindows.hwndWatch) {
hwndActivate = g_DebuggerWindows.hwndWatch;
} else {
}
break;
case LOCALS_WINDOW:
if (g_DebuggerWindows.hwndLocals) {
hwndActivate = g_DebuggerWindows.hwndLocals;
} else {
}
break;
case CPU_WINDOW:
if (g_DebuggerWindows.hwndCpu) {
hwndActivate = g_DebuggerWindows.hwndCpu;
} else {
}
break;
case DISASM_WINDOW:
if (!bUserActivated && GetSrcMode_StatusBar()
&& NULL == g_DebuggerWindows.hwndDisasm
&& (g_contWorkspace_WkSp.m_dopDisAsmOpts & dopNeverOpenAutomatically) ) {
return NULL;
}
if (g_DebuggerWindows.hwndDisasm) {
hwndActivate = g_DebuggerWindows.hwndDisasm;
} else {
}
break;
case CMD_WINDOW:
if (g_DebuggerWindows.hwndCmd) {
hwndActivate = g_DebuggerWindows.hwndCmd;
} else {
return NewCmd_CreateWindow(g_hwndMDIClient);
}
break;
case FLOAT_WINDOW:
if (g_DebuggerWindows.hwndFloat) {
hwndActivate = g_DebuggerWindows.hwndFloat;
} else {
}
break;
case MEMORY_WINDOW:
if (NULL == g_DebuggerWindows.hwndMemory
if (StartDialog(DLG_MEMORY, DlgMemory) != TRUE) {
MessageBeep (0);
return -1; // No Debuggee or User Cancel out.
}
}
break;
case QUICKW_WINDOW:
if (g_DebuggerWindows.hwndQuickW) {
hwndActivate = g_DebuggerWindows.hwndQuickW;
} else {
}
break;
case CALLS_WINDOW:
if (g_DebuggerWindows.hwndCalls) {
hwndActivate = g_DebuggerWindows.hwndCalls;
} else {
OpenCallsWindow(winType, NULL, -1, bUserActivated);
}
break;
}
if (hwndActivate) {
if (IsIconic(hwndActivate)) {
OpenIcon(hwndActivate);
}
ActivateMDIChild(hwndActivate, bUserActivated);
}
return hwndActivate;
}
// New_OpenDebugWindow()
#else // NEW_WINDOWING_CODE
int
OpenDebugWindow(
int winType,
BOOL bUserActivated
)
{
return OpenDebugWindowEx(winType,
NULL,
-1,
bUserActivated
);
}
int
OpenDebugWindowEx(
int winType,
LPWININFO lpWinInfo,
int nViewPreference,
BOOL bUserActivated
)
/*++
Routine Description:
Opens Cpu, Watch, Locals, Calls, or Memory Window under MDI
Handles special case for memory win's
Arguments:
winType - Supplies Type of debug window to be openned
bUserActivated - Indicates whether this action was initiated by the
lpWinInfo - window palcement preferences
nViewPreference - Prefered view position in array
user or by windbg. The value is to determine the Z order of
any windows that are opened.
Return Value:
View number on success and -1 on failures
--*/
{
HWND win = NULL;
int view = -1;
switch (winType) {
case WATCH_WIN:
case LOCALS_WIN:
case CPU_WIN:
case FLOAT_WIN:
// Let the Pane Manager handle openning the window (it will
// check for prior existance), get the view number and
// return without using the document manager.
OpenPanedWindow(winType,
lpWinInfo,
nViewPreference,
bUserActivated
);
for (view=0; view < MAX_VIEWS; view++) {
if (Views[view].Doc == -winType) {
break;
}
}
if (view == MAX_VIEWS) {
view = -1;
}
return view;
case CALLS_WIN:
OpenCallsWindow(winType,
lpWinInfo,
nViewPreference,
bUserActivated
);
for (view=0; view < MAX_VIEWS; view++) {
if (Views[view].Doc == -winType) {
break;
}
}
if (view == MAX_VIEWS) {
view = -1;
}
return view;
case DOC_WIN:
case DISASM_WIN:
case COMMAND_WIN:
win = GetDebugWindowHandle((WORD) winType);
if (DISASM_WIN == winType) {
if (!bUserActivated && GetSrcMode_StatusBar()
&& NULL == win
&& (g_contWorkspace_WkSp.m_dopDisAsmOpts & dopNeverOpenAutomatically) ) {
return -1;
}
}
break;
case MEMORY_WIN:
if (NULL == lpWinInfo) {
if (StartDialog(DLG_MEMORY, DlgMemory) != TRUE) {
MessageBeep (0);
return -1; // No Debuggee or User Cancel out.
}
}
break;
default:
//Assert(FALSE);
return -1;
}
// Open the Debug windows to standard size or to previous
// size if already opened
if (win == NULL) {
view = AddFile(MODE_CREATE,
(WORD) winType,
(LPSTR)szNull,
lpWinInfo,
NULL,
FALSE,
-1,
nViewPreference,
bUserActivated
);
} else {
HWND MDIWin = GetParent(win);
if (IsIconic(MDIWin)) {
OpenIcon(MDIWin);
}
//SendMessage(g_hwndMDIClient, WM_MDIACTIVATE, (WPARAM) MDIWin, 0L);
ActivateMDIChild(MDIWin, bUserActivated);
for (view=0; view < MAX_VIEWS; view++) {
if (Views[view].Doc < 0) {
continue;
}
if (Docs[Views[view].Doc].docType == winType) {
break;
}
}
if (view == MAX_VIEWS) {
view = -1;
}
}
return view;
}
// OpenDebugWindow()
#endif // NEW_WINDOWING_CODE
int
GotoLine(
int view,
int lineNbr,
BOOL fDebugger
)
/*++
Routine Description:
Move to the passed line in the passed view - returns
line actually hit in case of adjustment.
(NB lines are passed in range 1 => N)
Arguments:
view - Supplies the index of document window to do the goto in
lineNbr - Supplies the line number to go to
fDebugger - Supplies TRUE if debugger is doing the goto
Return Value:
lineNbr - Actual line number we went to
--*/
{
Assert( Views[view].Doc >= 0);
lineNbr = min(max(1, (int)lineNbr), (int)Docs[Views[view].Doc].NbLines) - 1;
PosXYCenter(view, 0, lineNbr, fDebugger);
return lineNbr;
} /* GotoLine() */
void
LineStatus(
int doc,
int lineNbr,
WORD state,
LINESTATUSACTION action,
BOOL positionInFirstView,
BOOL redraw
)
/*++
Routine Description:
This routine is used to change the highlighting done on a per line
basis. This include tags, current line, breakpoints, errors.
Arguments:
doc - Supplies the document index
lineNbr - Supplies the 0 based line number to be changed
state - Supplies the state to be changed.
action - Supplies the TRUE/FALSE of the state to be set
positionInFirstView - Supplies TRUE if the focues is to be changed to
the first view for the document in question
redraw - Supplies TRUE if a redraw is to be forced now
Return Value:
None.
--*/
{
LPLINEREC pl;
LPBLOCKDEF pb;
long y;
y = lineNbr = min(max(1, (int)lineNbr), (int)Docs[doc].NbLines) - 1;
if (!FirstLine (doc, &pl, &y, &pb)) {
Assert(FALSE);
return;
}
switch (action) {
case LINESTATUS_ON:
SET(pl->Status, state);
break;
case LINESTATUS_OFF:
RESET(pl->Status, state);
break;
case LINESTATUS_TOGGLE:
TOGGLE(pl->Status, state);
break;
}
CloseLine(doc, &pl, y, &pb);
if (positionInFirstView) {
PosXY(Docs[doc].FirstView, Views[Docs[doc].FirstView].X, lineNbr, TRUE);
}
if (redraw) {
InvalidateLines(Docs[doc].FirstView, lineNbr, lineNbr, FALSE);
if (! (IsIconic(GetParent(Views[Docs[doc].FirstView].hwndClient)) ||
IsZoomed(GetParent(Views[Docs[doc].FirstView].hwndClient)))) {
ShowWindow (GetParent(Views[Docs[doc].FirstView].hwndClient), SW_SHOWNORMAL); //re-activate the iconized window gaining
//current focus
}
ClearSelection (Docs[doc].FirstView);
// SendMessage (GetParent(Views[Docs[doc].FirstView].hwndClient), WM_MDIACTIVATE,0,0L);
if (positionInFirstView) {
ActivateMDIChild(Views[Docs[doc].FirstView].hwndFrame, FALSE);
}
}
} /* LineStatus() */
/*** QueryLineStatus
** Synopsis:
** bool = QueryLineStatus(doc, lineNbr, state)
** Entry:
** doc - which document to look in
** lineNbr - which line to number look at the status for
** state - which status flags we are looking at
** Returns:
** TRUE if any of the flags are set and FALSE otherwise
** Description:
** This function is used to find out if any status flags are current
** set on a line
*/
BOOL
QueryLineStatus(
int doc,
int lineNbr,
UINT state
)
{
LPLINEREC pl;
LPBLOCKDEF pb;
long y;
// If we are not looking at a valid line then no status flags
// are ever set.
if ((lineNbr < 1) || (lineNbr > Docs[doc].NbLines-1)) {
return FALSE;
}
y = lineNbr - 1;
if (!FirstLine (doc, &pl, &y, &pb)) {
Assert(FALSE);
return FALSE;
}
CloseLine(doc, &pl, y, &pb);
return (pl->Status & state) ? TRUE : FALSE;
} /* QueryLineStatus() */
/*** FindDoc
** Synopsis:
** bool = FindDoc(fileName, doc, docOnly)
** Entry:
** Returns:
** TRUE if document was found FALSE otherwise
** Description:
** Given a file Name, find doc #, if docOnly == TRUE then
** the Debug windows are not included
** Updates the location pointed to by doc with the document number
*/
BOOL FindDoc(
LPSTR fileName,
int *doc,
BOOL docOnly)
{
LPSTR SrcFile = GetFileName( fileName );
if ( SrcFile ) {
if (docOnly) {
for (*doc = 0; *doc < MAX_DOCUMENTS; (*doc)++) {
if (Docs[*doc].docType == DOC_WIN && Docs[*doc].FirstView != -1
&& _stricmp(GetFileName(Docs[*doc].szFileName), SrcFile) == 0) {
return TRUE;
}
}
}
else {
for (*doc = 0; *doc < MAX_DOCUMENTS; (*doc)++) {
if (Docs[*doc].FirstView != -1
&& _stricmp(GetFileName(Docs[*doc].szFileName), SrcFile) == 0) {
return TRUE;
}
}
}
}
return FALSE;
}
/*** FindDoc1
** Synopsis:
** bool = FindDoc1(fileName, doc, docOnly)
** Entry:
** Returns:
** TRUE if document was found FALSE otherwise
** Description:
** Given a file Name, find doc #, if docOnly == TRUE then
** the Debug windows are not included
** Updates the location pointed to by doc with the document number
*/
BOOL
FindDoc1(
LPSTR fileName,
int *doc,
BOOL docOnly
)
{
BOOL (*lpCompareFileName)(LPSTR, LPSTR);
LPSTR SrcFile = GetFileName( fileName );
if ( SrcFile ) {
#if 1
if (strlen(SrcFile) == strlen(fileName)) {
lpCompareFileName = CompareFileName;
} else {
lpCompareFileName = CompareFileNameWithPath;
SrcFile = fileName;
}
#else
lpCompareFileName = CompareFileName;
#endif
if (docOnly) {
for (*doc = 0; *doc < MAX_DOCUMENTS; (*doc)++) {
if (Docs[*doc].docType == DOC_WIN && Docs[*doc].FirstView != -1
&& (*lpCompareFileName)(Docs[*doc].szFileName, SrcFile)) {
return TRUE;
}
}
}
else {
for (*doc = 0; *doc < MAX_DOCUMENTS; (*doc)++) {
if (Docs[*doc].FirstView != -1
&& (*lpCompareFileName)(Docs[*doc].szFileName, SrcFile)) {
return TRUE;
}
}
}
}
return FALSE;
}
static
BOOL
CompareFileName(
LPSTR szName1,
LPSTR szName2
)
{
return (_stricmp(GetFileName(szName1), szName2) == 0);
}
static
BOOL
CompareFileNameWithPath(
LPSTR szName1,
LPSTR szName2
)
{
return (_stricmp(szName1, szName2) == 0);
}
char *
GetFileName(
IN char * szPath
)
/*++
Routine Description:
Returns a pointer to the filename portion of a path
Arguments:
szPath - Supplies the path
Return Value:
char * - Pointer to the filename portion of the path.
--*/
{
char *p = NULL;
if ( *szPath ) {
p = szPath + strlen(szPath );
while (p > szPath) {
p = CharPrev(szPath, p);
if (*p == '\\' || *p == '/') {
break;
}
}
if ((*p == '\\' ) || (*p == '/' )) {
p++;
}
}
return p;
}
/*
FUNCTION: ClearDocStatus
PURPOSE: Given a doc, clear all visual breakpoints, tags or
compile errors in the views in that doc.
*/
void ClearDocStatus(
int doc,
WORD state)
{
LPLINEREC pl;
LPBLOCKDEF pb;
long y;
y = 0;
if (!FirstLine(doc, &pl, &y, &pb)) {
return;
}
while (TRUE) {
if (pl->Status & state) {
pl->Status &= ~state;
InvalidateLines(Docs[doc].FirstView, y - 1, y - 1, FALSE);
}
if (y >= Docs[doc].NbLines) {
break;
} else if (!NextLine(doc, &pl, &y, &pb)) {
return;
}
}
CloseLine(doc, &pl, y, &pb);
} /* ClearDocStatus() */
/*
FUNCTION: ClearAllDocStatus
PURPOSE: Clear all visual breakpoints, tags or compile errors
that in all docs.
*/
void
ClearAllDocStatus(
WORD state
)
{
int d;
for (d = 0; d < MAX_DOCUMENTS; d++) {
if (Docs[d].FirstView != -1) {
ClearDocStatus(d, state);
}
}
} /* ClearAllDocStatus() */
/*
FUNCTION: VisibleListboxLines
PURPOSE: Return the number of visible lines in the list box
associated with the passed handle.
Note that this function assumes that each list box item
is the same height.
*/
WORD
VisibleListboxLines(
HWND hListbox
)
{
RECT ListRect; // Dims of client area of listbox
RECT ItemRect; // Dims of an item within listbox
GetClientRect(hListbox, (LPRECT)&ListRect);
Dbg(SendMessage(hListbox, LB_GETITEMRECT, 0, (LPARAM)(LPRECT)&ItemRect)!=LB_ERR);
return ((WORD)((ListRect.bottom - ListRect.top + 1) /
(ItemRect.bottom - ItemRect.top)));
} /* VisibleListboxLines() */
/*** AjustFullPathName
** Synopsis:
** void = AdjustFullPathName(fullPath, adjustedPath, len
** Entry:
** Returns:
** nothing
** Description:
** Adjust Full Path name to fit in a specified len string
** Priority rules for reduction are :
** - FileName.extension
** - Drive
** - Nth dir
** - (N-1)th dir
** - ...
** - 1st dir
*/
void
AdjustFullPathName(
PCSTR fullPath,
PSTR adjustedPath,
int len
)
{
int remain = len;
PSTR cur;
TCHAR szDrive[_MAX_DRIVE];
TCHAR szDir[_MAX_DIR];
TCHAR szFName[_MAX_FNAME];
TCHAR szExt[_MAX_EXT];
//Assert(len >= MAXFILENAMELEN);
if ((int)strlen(fullPath) <= len) {
strcpy(adjustedPath, fullPath);
return;
}
*adjustedPath = '\0';
_splitpath(fullPath, szDrive, szDir, szFName, szExt);
remain -= (strlen(szFName) + strlen(szExt));
//Try to add the drive
if (szDrive) {
if (remain >= (int)strlen(szDrive)) {
strcat(adjustedPath, szDrive);
remain -= strlen(szDrive);
} else {
//No space, try to add some "." templates
while (remain-- > 0) {
strcat(adjustedPath, ".");
}
goto rebuild;
}
}
//Extract dirs until we have no more space left
if (szDir) {
cur = szDir + strlen(szDir) - remain;
if (cur <= szDir ) {
//We have space to copy all dirs
strcat(adjustedPath, szDir);
} else if (remain < 5) {
//If we had the drive and there is a dir, better get rid
//of the drive to avoid to return a wrong pathName.
if (szDrive && strlen(szDrive) >= 2) {
strcpy(adjustedPath, "..");
}
} else {
//Add "\..\" template, if we have space left
strcat(adjustedPath, "\\...");
remain -= 4;
if (remain == 1) {
//Just space to add a "\"
strcat(adjustedPath, "\\");
} else {
//We have no space to copy all dirs, synchronize to next
//dir beginning and add it to reduced path name
cur = szDir + strlen(szDir) - remain;
while (*cur && *cur != '\\') {
if (IsDBCSLeadByte(*cur) && *(cur+1)) {
cur += 2;
} else {
cur++;
}
}
if (*cur) {
strcat(adjustedPath, cur);
} else {
strcat(adjustedPath, "\\");
}
}
}
}
rebuild:
//Rebuild FileName.extension
remain = len - strlen(adjustedPath);
strncat(adjustedPath, szFName, remain);
remain -= strlen(szFName);
if (remain > 0) {
strncat(adjustedPath, szExt, remain);
}
} /* AdjustFullPathName() */
// BUGBUG - kcarlos - dead code
#if 0
/*** ReadIni
** Synopsis:
** bool = ReadIni(hFile, lpBuffer, wBytes)
** Entry:
** Returns:
** Description:
** ReadIni to file and add to checksum
*/
BOOL
ReadIni(
int hFile,
LPSTR lpBuffer,
int wBytes
)
{
//Read File Buffer
if (_lread(hFile, lpBuffer, wBytes) != (UINT) wBytes) {
return ErrorBox2(hwndFrame, MB_TASKMODAL, ERR_Ini_File_Read, (LPSTR)iniFileName);
}
return TRUE;
} /* ReadIni() */
/*** WriteAndSum
** Synopsis:
** bool = WriteAndSum(hFile, lpBuffer, wBytes)
** Entry:
** hFile - Handle to file to do the write on
** lpBuffer - Buffer containning bytes to be written
** wBytes - count of bytes to be written
** Returns:
** TRUE on a sucessful write and FALSE on failure
** Description:
** This function will write data out to the file connected to the
** file handle and to compute a checksum on the data being written
** out. The checksum is a sum of all bytes written.
*/
BOOL
WriteAndSum(
int hFile,
LPSTR lpBuffer,
int wBytes
)
{
register int i;
//Add buffer bytes to checksum
for (i = 0; i < wBytes; i++) {
checkSum += (BYTE)lpBuffer[i];
}
//Write File Buffer
if (_lwrite(hFile, lpBuffer, wBytes) != (UINT) wBytes) {
return ErrorBox2(hwndFrame, MB_TASKMODAL, ERR_Ini_File_Write, (LPSTR)iniFileName);
}
return TRUE;
} /* WriteAndSum() */
#endif
/*** FailGlobalLock
** Synopsis:
** bool = FailGlobalLoc(h, p)
** Entry:
** Returns:
** TRUE if locked and FALSE if failed to lock
** Description:
** Try to lock a global memory handle
*/
BOOL
FailGlobalLock(
HANDLE h,
LPSTR *p
)
{
if ((*p = (PSTR) GlobalLock (h)) == 0) {
Dbg(GlobalFree (h) == NULL);
return TRUE;
}
return FALSE;
} /* FailGlobalLock() */
/*** GetCurrentText
** Synopsis:
** Entry:
** Returns:
** FALSE if there is a problem or nothing to get
** Description:
** Retrieve in view the word at cursor, or the first line
** of text if selection is active. If not NULL, beginOffset
** and endOffset return number of chars relative to cursor
** position. If a selection is active and is over several
** lines and cursor in selection is not above a word and
** lookAround is TRUE, the word at left is returned and
** 'lookAround' is TRUE, otherwise lookAround is FALSE.
*/
BOOL
GetCurrentText(
int view,
BOOL *lookAround,
LPSTR pText,
int maxSize,
LPINT xLeft,
LPINT xRight)
{
LPVIEWREC v = &Views[view];
//If selection active
if (v->BlockStatus) {
//Returns selected text
return GetSelectedText(view, lookAround, (LPSTR)pText,
maxSize, xLeft, xRight);
} else {
//No selection, send word at cursor
return GetWordAtXY(view, v->X, v->Y, FALSE, lookAround, TRUE,
(LPSTR)pText, maxSize, xLeft, xRight);
}
} /* GetCurrentText() */
/*** TimeIn100ths
** Synopsis:
** ulong = TimeIn100ths()
** Entry:
** None
** Return:
** the current time in 100ths of a second
** Description:
** This function will look at the clock and return the current time
** routined to 100ths of a second
*/
ULONG
PASCAL
TimeIn100ths()
{
#ifdef WIN32
return GetTickCount();
#else
struct _dostime_t time;
_dos_gettime(&time);
return (((((time.hour*60UL)+time.minute)*60)+time.second)*100)+time.hsecond;
#endif
} /* TimeIn100ths() */
/*
FUNCTION: StopTimeIn100ths
PURPOSE: Returns the current time + the passed delay in 100ths
of a second. NB takes into account the time period
crossing midnight.
RETURNS: See above.
*/
/*** StopTimeIn100ths
** Synopsis:
** ulong = StopTimeIn100ths( DelayIn100ths)
** Entry:
** DelayIn100ths - delay to add to current time
** Return:
** Current time plus the delay request in 100ths of a second
** Description:
** This routine will take the current system time and add the requested
** delay to it. The result in 100ths of a second will then be returned
*/
ULONG
PASCAL
StopTimeIn100ths(
ULONG DelayIn100ths
)
{
return (TimeIn100ths() + DelayIn100ths) % HUNDREDTHS_IN_A_DAY;
}
/*** ProcessQCQPMessage
** Synopsis:
** void = ProcessQCQPMessage(lpmsg)
** Entry:
** lpmsg - The message to be processed and forwarded as appropriate
** Returns:
** nothing:
** Description:
** Performs translation and dispatching of a message
** received by QCQP. Should be called by anyone that
** does a Get/Peek etc Message.
*/
void
PASCAL
ProcessQCQPMessage(
LPMSG lpMsg
)
{
//If a keyboard message is for the MDI , let the MDI client
//take care of it. Otherwise, check to see if it's a normal
//accelerator key (like F3 = find next). Otherwise, just handle
//the message as usual.
if (!TranslateMDISysAccel(g_hwndMDIClient, lpMsg) &&
!TranslateAccelerator(hwndFrame, hCurrAccTable, lpMsg)) {
TranslateMessage(lpMsg);
DispatchMessage(lpMsg);
}
} /* ProcessQCQPMessage() */
/*** AppendFilter
** Description:
** Append a filter to an existing filters string.
*/
void
AppendFilter(
WORD filterTextId,
int filterExtId,
LPSTR filterString,
int *len,
int maxLen
)
{
int size;
//Append filter text
Dbg(LoadString(g_hInst, filterTextId, (LPSTR)szTmp, MAX_MSG_TXT));
size = strlen(szTmp) + 1;
Assert(*len + size <= maxLen);
memmove(filterString + *len, szTmp, size);
*len += size;
//Append filter extension
Dbg(LoadString(g_hInst, filterExtId, (LPSTR)szTmp, MAX_MSG_TXT));
size = strlen(szTmp) + 1;
Assert(*len + size < maxLen);
memmove(filterString + *len, szTmp, size);
*len += size;
} /* AppendFilter() */
/*** InitFilterString
** Description:
** Initialize file filters for file dialog boxes.
*/
void
InitFilterString(
WORD titleId,
LPSTR filter,
int maxLen
)
{
int len = 0;
switch (titleId) {
case DLG_Browse_CrashDump_Title:
AppendFilter(TYP_File_DUMP, DEF_Ext_DUMP, filter, &len, maxLen);
break;
case DLG_Browse_Executable_Title:
AppendFilter(TYP_File_EXE, DEF_Ext_EXE, filter, &len, maxLen);
break;
case DLG_Browse_LogFile_Title:
AppendFilter(TYP_File_LOG, DEF_Ext_LOG, filter, &len, maxLen);
break;
case DLG_SaveAs_Filebox_Title:
case DLG_Open_Filebox_Title:
case DLG_Merge_Filebox_Title:
case DLG_Browse_Filebox_Title:
AppendFilter(TYP_File_SOURCE, DEF_Ext_SOURCE, filter, &len, maxLen);
AppendFilter(TYP_File_INCLUDE, DEF_Ext_INCLUDE, filter, &len, maxLen);
AppendFilter(TYP_File_ASMSRC, DEF_Ext_ASMSRC, filter, &len, maxLen);
AppendFilter(TYP_File_INC, DEF_Ext_INC, filter, &len, maxLen);
AppendFilter(TYP_File_RC, DEF_Ext_RC, filter, &len, maxLen);
AppendFilter(TYP_File_DLG, DEF_Ext_DLG, filter, &len, maxLen);
AppendFilter(TYP_File_DEF, DEF_Ext_DEF, filter, &len, maxLen);
AppendFilter(TYP_File_MAK, DEF_Ext_MAK, filter, &len, maxLen);
break ;
case DLG_Browse_DbugDll_Title:
AppendFilter(TYP_File_DLL, DEF_Ext_DLL, filter, &len, maxLen);
break;
default:
DAssert(FALSE);
break;
}
AppendFilter(TYP_File_ALL, DEF_Ext_ALL, filter, &len, maxLen);
filter[len] = '\0';
} /* InitFilterString() */
/*** GetDebugWindowHandle
** Synopsis:
** hwnd = GetDebugWindowHandle(type)
** Entry:
** type - Debug window type to get the handle for
** Returns:
** The handle for this type of debug window if one exists, otherwise
** it returns NULL
** Description:
** This function is used to obtain the window handle for the
** single instance of the debug window of class type.
*/
HWND
GetDebugWindowHandle(
WORD type
)
{
int v;
if ((type == CPU_WIN) || (type == FLOAT_WIN) || (type == WATCH_WIN) ||
(type == LOCALS_WIN) || (type == CALLS_WIN)) {
type = -type;
}
for (v = 0; v < MAX_VIEWS; v++) {
if (type < -1) {
if (Views[v].Doc == (int) type) {
return Views[v].hwndClient;
}
} else if ((Views[v].Doc != -1) &&
(Docs[Views[v].Doc].docType == type)) {
return Views[v].hwndClient;
}
}
return NULL;
} /* GetDebugWindowHandle() */
/*** SetVerticalScrollBar
** Synopsis:
** void = SetScrollBar(view, propagate)
** Entry:
** view - document to set scroll bars for
** propagate - Modify just this view or all other views on same document
** Returns:
** Nothing
** Description:
** This function is used to adjust the range of the vertical scroll bar
** for a document. It will be set according to the number of lines in
** the document. If desired then all views of the same document may have
** their scroll bars adjusted at the same time. If so then the cursor
** for the other windows will be verified as within the current line
** count.
*/
void
SetVerticalScrollBar(
int view,
BOOL propagate
)
{
int n = Docs[Views[view].Doc].NbLines - 1;
DAssert(Views[view].Doc >= 0);
// Need to work out disasmbler scroll bars later
if (view == disasmView) {
return;
}
// Only handle multiple views for DOC_WIN
if (!propagate || Docs[Views[view].Doc].docType != DOC_WIN) {
SetScrollRange(Views[view].hwndClient, SB_VERT, 0, max(n,1), TRUE);
} else {
int k = Docs[Views[view].Doc].FirstView;
LPVIEWREC v;
while (k != -1) {
v = &Views[k];
//Possibly adjust cursor position
if (v->Y > n) {
v->Y = n;
if (v->BlockYR > n) {
v->BlockYR = n;
}
if (v->BlockYL > n) {
v->BlockYL = n;
}
}
k = v->NextView;
SetScrollRange(v->hwndClient, SB_VERT, 0, max(n,1), TRUE);
}
}
} /* SetVerticalScrollBar() */
/*** AuxPrintf
** Synopsis:
** bool = AuxPrintf(iReqDebLevel, sz, ...)
** Entry:
** Returns:
** Description:
** Makes a printf style command for output on debug console
*/
#undef AuxPrintf
BOOL
AuxPrintf(
int iReqDebLevel,
LPSTR text,
...
)
{
#if !REMOVEAUXPRINTFS
char buffer[MAX_MSG_TXT];
int fdComm;
va_list vargs;
if (iReqDebLevel > iDebugLevel)
return(FALSE);
va_start(vargs, text);
vsprintf(buffer, text, vargs);
va_end(vargs);
lstrcat(buffer,"\r\n");
// By-pass OutputDebugString, otherwise we'll get notifications
// about these things when debugging (DBG_N_InfoAvail)
//!OutputDebugString(buffer);
if ((fdComm = _lopen("com1", OF_WRITE)) != -1) {
_lwrite(fdComm, buffer, strlen(buffer));
_lclose(fdComm);
}
OutputDebugString(buffer);
#endif
return FALSE;
} /* AuxPrintf() */
BOOL
FindNameOn(
PSTR pszDest,
UINT cchDest,
PCTSTR pszPaths,
PCTSTR pszFile
)
/*++
Routine Description:
This function will look in each of the directories specified in
the lszPaths variable for the relative path lszFile. If the file
if fond to exist then the resulting name will be returned in
lszDest and TRUE is returned.
Arguments:
pszDest - Supplies a buffer to place resulting name
cchDest - Supplies the number of bytes in buffer
pszPaths - Supplies a semi-colon seperated list of directories to search
pszFile - Supplies a file name to look for
Return Value:
TRUE if file was found and FALSE otherwise.
--*/
{
PCSTR psz1;
PCSTR psz2;
char ch;
char rgchT[MAX_PATH*2];
psz1 = pszPaths;
if (psz1 == NULL) {
return FALSE;
}
while (*psz1 != 0) {
psz2 = psz1;
while ((*psz2) && (*psz2 != ';')) {
psz2 = CharNext(psz2);
}
strncpy(rgchT, psz1, psz2-psz1);
rgchT[psz2-psz1] = 0;
strcat(rgchT, "\\");
strcat(rgchT, pszFile);
if (_fullpath(pszDest, rgchT, cchDest) != NULL) {
if (FileExist(pszDest)) {
return TRUE;
}
}
psz1 = psz2;
if (*psz1 == ';') {
psz1++;
}
}
return FALSE;
} /* FindNameOn() */
BOOL
SetDriveAndDir(
const TCHAR * const pszTargPath
)
{
TCHAR szTmp[_MAX_PATH] = {0};
TCHAR szDrive[_MAX_DRIVE] = {0};
TCHAR szDir[_MAX_DIR];
TCHAR szFName[_MAX_FNAME];
TCHAR szExt[_MAX_EXT];
int nDirLen;
_tsplitpath(pszTargPath, szDrive, szDir, szFName, szExt);
//Set current drive and dir
if (szDrive[0] != 0) {
if (_chdrive((int)(toupper(szDrive[0]) - 'A' + 1)) != 0) {
return ErrorBox(ERR_Change_Drive, (LPSTR)szDrive);
}
}
nDirLen = strlen(szDir);
AnsiToOem(szDir, szTmp);
if (nDirLen > 0) {
if (_tcslen(szTmp) > 1 && *CharPrev(szTmp, szTmp + nDirLen - 1) == '\\') {
szTmp[--nDirLen] = 0;
}
if (_chdir(szTmp) != 0) {
OemToAnsi(szTmp, szDir);
return ErrorBox(ERR_Change_Directory, (LPSTR)szDir);
}
}
return TRUE;
}
BOOL
GetFileTimeByName(
LPSTR FileName,
LPFILETIME lpCreationTime,
LPFILETIME lpLastAccessTime,
LPFILETIME lpLastWriteTime
)
{
BOOL Status;
HANDLE FileHandle;
FileHandle = CreateFile(
FileName,
GENERIC_READ,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0
);
if (FileHandle == INVALID_HANDLE_VALUE) {
return FALSE;
}
Status = GetFileTime(
FileHandle,
lpCreationTime,
lpLastAccessTime,
lpLastWriteTime
);
CloseHandle(FileHandle);
return Status;
}
#ifdef DEBUGGING
ULARGE_INTEGER startTime;
ULARGE_INTEGER stopTime;
void
ShowElapsedTime()
{
ULONG64 uSecs;
ULONG64 uMilliSecs;
// convert from nano (10^-9) to milli (10^-3)
uMilliSecs = (stopTime.QuadPart - startTime.QuadPart) / 1000000;
// Convert to whole seconds
uSecs = uMilliSecs / 1000;
// Calc millisecond remainder
uMilliSecs %= 1000;
AuxPrintf(1, "%u' %u''", uSecs, uMilliSecs);
}
void
StartTimer()
{
GetSystemTimeAsFileTime( (PFILETIME) &startTime );
}
void
StopTimer()
{
GetSystemTimeAsFileTime( (PFILETIME) &stopTime );
}
/*
FUNCTION: InfoBox
PURPOSE: Opens a Dialog box with a title and accepting
a printf style for text. It's for DEBUGGING USE ONLY
RETURNS: MessageBox result
*/
int
InfoBox(
LPSTR text,
...
)
{
char buffer[MAX_MSG_TXT];
va_list vargs;
va_start(vargs, text);
vsprintf(buffer, text, vargs);
va_end(vargs);
return MsgBox(GetActiveWindow(), buffer, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
}
#endif //debugging
VOID
InvalidateAllWindows()
{
SendMessageNZ( GetCpuHWND(), WU_INVALIDATE, 0, 0L);
SendMessageNZ( GetFloatHWND(), WU_INVALIDATE, 0, 0L);
SendMessageNZ( GetLocalHWND(), WU_INVALIDATE, 0, 0L);
SendMessageNZ( GetWatchHWND(), WU_INVALIDATE, 0, 0L);
SendMessageNZ( GetCallsHWND(), WU_INVALIDATE, 0, 0L);
}
/*
*/
VOID
GetDBCSCharWidth(
HDC hDC,
LPTEXTMETRIC ptm,
LPVIEWREC lpv
)
{
SIZE Size;
if (ptm->tmCharSet == SHIFTJIS_CHARSET) {
if (0 == (ptm->tmPitchAndFamily & TMPF_FIXED_PITCH)
&& ptm->tmMaxCharWidth == ptm->tmAveCharWidth * 2) {
lpv->wViewPitch = VIEW_PITCH_ALL_FIXED;
} else {
lpv->wViewPitch = VIEW_PITCH_DBCS_FIXED;
}
} else {
if (0 == (ptm->tmPitchAndFamily & TMPF_FIXED_PITCH)) {
lpv->wViewPitch = VIEW_PITCH_ALL_FIXED;
} else {
lpv->wViewPitch = VIEW_PITCH_VARIABLE;
}
}
GetTextExtentPoint((hDC), DBCS_CHAR, 2, &Size);
lpv->charWidthDBCS = Size.cx - ptm->tmOverhang;
lpv->wCharSet = ptm->tmCharSet;
}
/*
Modify UndoRedo record
*/
VOID
SetReplaceDBCSFlag(
LPDOCREC lpd,
BOOL bTwoRec
)
{
STREAMREC *pst;
if (DOC_WIN != lpd->docType) {
return;
}
//It is bad to update undo information directly...
pst = (STREAMREC *)((LPSTR)lpd->undo.pRec + lpd->undo.offset);
if (bTwoRec) {
// This is because lpd->undo.offset points the undo record
// for inserted chars. Previous record is for deleted chars.
pst = (STREAMREC *)((LPSTR)pst - pst->prevLen);
}
pst->action |= REPLACEDBCS;
}
/*
Set position of IME conversion window
*/
LRESULT
ImeMoveConvertWin(
HWND hwnd,
INT x,
INT y
)
{
HANDLE hIME;
LPIMESTRUCT lpIme;
LRESULT lrRet;
if (NULL == lpfnSendIMEMessageEx) {
return FALSE;
}
if(!(hIME = GlobalAlloc(GHND | GMEM_SHARE, (DWORD)sizeof(IMESTRUCT)))){
return FALSE;
}
if(!(lpIme = (LPIMESTRUCT)GlobalLock(hIME))){
return FALSE;
}
// Set IME_SETCONVERSIONWINDOW as a sub-function number
lpIme->fnc = IME_SETCONVERSIONWINDOW;
// if x == -1 && y == -1 then set default conversion ID
if (x == -1 && y == -1) {
lpIme->wParam = MCW_DEFAULT;
} else {
RECT rRect;
GetClientRect(hwnd, &rRect);
// Set spot conversion ID, and a position of a conversion window
lpIme->wParam = MCW_WINDOW | MCW_RECT;
lpIme->lParam1 = MAKELONG(LOWORD(x), LOWORD(y));
lpIme->lParam2 = MAKELONG(LOWORD(rRect.left), LOWORD(rRect.top));
lpIme->lParam3 = MAKELONG(LOWORD(rRect.right), LOWORD(rRect.bottom));
}
GlobalUnlock(hIME);
lrRet = (*lpfnSendIMEMessageEx)(hwnd, (LPARAM)hIME);
GlobalFree(hIME);
return lrRet;
}
/*
Send virtual key message to IME
*/
LRESULT
ImeSendVkey(
HWND hwnd,
WORD wVKey
)
{
HANDLE hIME;
LPIMESTRUCT lpIme;
LRESULT lrRet;
if (NULL == lpfnSendIMEMessageEx) {
return FALSE;
}
if(!(hIME = GlobalAlloc(GHND | GMEM_SHARE, (DWORD)sizeof(IMESTRUCT)))){
return FALSE;
}
if(!(lpIme = (LPIMESTRUCT)GlobalLock(hIME))){
return FALSE;
}
lpIme->fnc = IME_SENDVKEY;
lpIme->wParam = wVKey;
GlobalUnlock(hIME);
lrRet = (*lpfnSendIMEMessageEx)(hwnd, (LPARAM)hIME);
GlobalFree(hIME);
return lrRet;
}
/*
FUNCTION : ImeSetFont
PURPOSE : Specify the font which is used in IME conversion window
*/
BOOL
ImeSetFont(
HWND hwnd,
HFONT hFont
)
{
HANDLE hIME;
LPIMESTRUCT lpIme;
HANDLE hLF;
LPLOGFONT lpLF;
if (NULL == lpfnSendIMEMessageEx) {
return FALSE;
}
if (!(hIME = GlobalAlloc(GHND | GMEM_SHARE, (DWORD)sizeof(IMESTRUCT)))) {
return FALSE;
}
if (!(lpIme = (LPIMESTRUCT)GlobalLock(hIME))) {
return FALSE;
}
if (!(hLF = GlobalAlloc(GHND | GMEM_SHARE, sizeof(LOGFONT)))) {
GlobalUnlock(hIME);
GlobalFree(hIME);
return FALSE;
}
if (!(lpLF = (LPLOGFONT)GlobalLock(hLF))) {
GlobalFree(hLF);
GlobalUnlock(hIME);
GlobalFree(hIME);
return FALSE;
}
if (!GetObject(hFont, sizeof(LOGFONT), lpLF)) {
GlobalUnlock(hLF);
GlobalFree(hLF);
GlobalUnlock(hIME);
GlobalFree(hIME);
return FALSE;
}
GlobalUnlock(hLF);
// Set IME sub-function number
lpIme->fnc = IME_SETCONVERSIONFONTEX;
lpIme->lParam1 = (LPARAM)hLF;
GlobalUnlock(hIME);
(*lpfnSendIMEMessageEx)(hwnd, (LPARAM)hIME);
GlobalFree(hLF);
GlobalFree(hIME);
return TRUE;
}
/*
FUNCTION : ImeWINNLSEnableIME
PURPOSE :
*/
BOOL
ImeWINNLSEnableIME(
HWND hwnd,
BOOL bEnable
)
{
if (lpfnWINNLSEnableIME) {
return (*lpfnWINNLSEnableIME)(hwnd, bEnable);
} else {
return FALSE;
}
}
/*
Proccess WM_IME_REPORT:IR_STRING message
*/
BOOL
ProccessIMEString(
HWND hwnd,
LPARAM lParam
)
{
int view = GetWindowWord(hwnd, GWW_VIEW);
LPVIEWREC v = &Views[view];
LPDOCREC d = &Docs[v->Doc];
LPLINEREC pl;
LPBLOCKDEF pb;
LPTSTR lpsz;
int nLen1;
BOOL bRet;
if (!(lpsz = (PSTR) GlobalLock((HANDLE)lParam))) {
return FALSE;
}
if (!FirstLine(v->Doc, &pl, &(v->Y), &pb)) {
GlobalUnlock ((HANDLE)lParam);
return FALSE;
}
CloseLine(v->Doc, &pl, v->Y, &pb);
v->Y--;
nLen1 = lstrlen(lpsz);
if ((v->X < elLen - 1)
&& (GetOverType_StatusBar() || d->forcedOvertype) && !v->BlockStatus) {
/* if over-write mode and no text is selected */
v->BlockStatus = TRUE;
v->BlockXL = v->X;
v->BlockYL = v->Y;
v->BlockYR = v->Y;
if (v->X + nLen1 >= elLen) {
v->BlockXR = elLen - 1;
} else if (v->bDBCSOverWrite) {
int i;
for (i = 0; i < nLen1; i++) {
if (IsDBCSLeadByte(el[v->X + i])) {
i++;
}
}
if (i > nLen1) {
HGLOBAL hmemTmp;
GlobalUnlock ((HANDLE)lParam);
if (!(hmemTmp = GlobalReAlloc((HGLOBAL)lParam,
nLen1+2, GMEM_MOVEABLE | GMEM_SHARE))) {
return FALSE;
}
lParam = (LPARAM) hmemTmp;
if (!(lpsz = (LPTSTR) GlobalLock(hmemTmp))) {
return FALSE;
}
lpsz[nLen1] = ' ';
nLen1++;
}
v->BlockXR = v->X + nLen1;
} else {
int nNum1;
int nNum2;
int i;
for (i = 0, nNum1 = 0; i < nLen1; i++, nNum1++) {
if (IsDBCSLeadByte(lpsz[i])) {
i++;
}
}
for (i = 0, nNum2 = 0; nNum2 < nNum1; i++, nNum2++) {
if (IsDBCSLeadByte(el[v->X + i])) {
i++;
}
}
v->BlockXR = v->X + i;
}
}
bRet = InsertStream(view, v->X, v->Y, nLen1, lpsz, TRUE);
GlobalUnlock ((HANDLE)lParam);
if (bRet) {
SetReplaceDBCSFlag(d, v->BlockStatus ? TRUE : FALSE);
PosXY(view, v->X + nLen1, v->Y, TRUE);
}
return TRUE;
}
/*
Initialize pointers of IME APIs
*/
BOOL
ImeInit()
{
if (NULL == hModUser32) {
hModUser32 = LoadLibrary("IMM32");
}
if (NULL == hModUser32) {
#ifdef DEBUG
MessageBox(NULL, "Failed to load IMM32.DLL",
NULL, MB_APPLMODAL | MB_OK);
#endif
return FALSE;
}
if (NULL == lpfnWINNLSEnableIME) {
lpfnWINNLSEnableIME = (LPWINNLSENABLEIME) GetProcAddress(hModUser32, "ImmWINNLSEnableIME");
#ifdef DEBUG
if (NULL == lpfnWINNLSEnableIME) {
MessageBox(NULL, "Failed to get address of ImmWINNLSEnableIME",
NULL, MB_APPLMODAL | MB_OK);
}
#endif
}
if (NULL == lpfnSendIMEMessageEx) {
lpfnSendIMEMessageEx = (LPSENDIMEMESSAGEEX) GetProcAddress(hModUser32, "ImmSendIMEMessageExA");
#ifdef DEBUG
if (NULL == lpfnSendIMEMessageEx) {
MessageBox(NULL, "Failed to get address of ImmSendIMEMessageExA",
NULL, MB_APPLMODAL | MB_OK);
}
#endif
}
return TRUE;
}
/*
Terminate proccess of IME
*/
BOOL
ImeTerm()
{
if (NULL != hModUser32) {
if (FreeLibrary(hModUser32)) {
hModUser32 = NULL;
lpfnWINNLSEnableIME = NULL;
lpfnSendIMEMessageEx = NULL;
}
}
return TRUE;
}