windows-nt/Source/XPSP1/NT/base/mvdm/wow16/user/wmsyserr.c
2020-09-26 16:20:57 +08:00

1264 lines
38 KiB
C

/*++
*
* WOW v1.0
*
* Copyright (c) 1991, Microsoft Corporation
*
* WMSYSERR.C
* WOW16 system error box handling services
*
* History:
*
* Created 28-May-1991 by Jeff Parsons (jeffpar)
* Copied from WIN31 and edited (as little as possible) for WOW16.
* At this time, all we want is DrawFrame(), which the edit controls use.
--*/
/****************************************************************************/
/* */
/* WMSYSERR.C */
/* */
/* System error box handling routine */
/* */
/****************************************************************************/
#include "user.h"
#ifndef WOW
VOID FAR PASCAL GetbackFocusFromWinOldAp(void);
/* Private export from GDI for user. */
HFONT FAR PASCAL GetCurLogFont(HDC);
/* This array contins the state information for the three possible buttons in
* a SysErrorBox.
*/
SEBBTN rgbtn[3];
/* The following arrays are used to map SEB_values to their respective
* accelerator keys and text strings.
*/
#define BTNTYPECOUNT 7
static int rgStyles[BTNTYPECOUNT] =
{ SEB_OK, SEB_CANCEL, SEB_YES, SEB_NO, SEB_RETRY,
SEB_ABORT, SEB_IGNORE };
/* The following array is properly initialised by reading STR_ACCELERATORS
* string at LoadWindows time, which contains the accelerator keys
* corresponding to each button in the message box; Localizers must modify
* this string also. Because, this array will be filled by loading a
* string we must have one more space for the null terminator.
*/
char rgAccel[BTNTYPECOUNT+1];
extern WORD wDefButton;
int FAR PASCAL SoftModalMessageBox(HWND, LPSTR, LPSTR, WORD);
/*--------------------------------------------------------------------------*/
/* */
/* BltColor() - */
/* */
/* Modification done by SANKAR on 08-03-89: */
/* The parameter hbm was used as a boolean only to determine whether to */
/* use hdcBits or hdcGrey; Now hbm is replaced with hdcSrce, the source*/
/* device context because, now hdcBits contains color bitmaps and */
/* hdcMonoBits contains monochrome bitmaps; If hdcSrce is NULL, then */
/* hdcGrey will be used, else whatever is passed thro hdcSrce will be */
/* used as the source device context; */
/* */
/*--------------------------------------------------------------------------*/
void FAR PASCAL BltColor(hdc, hbr, hdcSrce, xO, yO, cx, cy, xO1, yO1, fInvert)
register HDC hdc;
register HBRUSH hbr;
HDC hdcSrce;
int xO, yO;
int cx, cy;
int xO1, yO1;
BOOL fInvert;
{
HBRUSH hbrSave;
DWORD textColorSave;
DWORD bkColorSave;
#ifdef DEBUG
if (!hdcGray && !hdcSrce) /* Only test hdcGray if it will be used */
FatalExit(RIP_BADDCGRAY);
#endif
if (hbr == (HBRUSH)NULL)
hbr = sysClrObjects.hbrWindowText;
/*
* Set the Text and Background colors so that bltColor handles the
* background of buttons (and other bitmaps) properly.
* Save the HDC's old Text and Background colors. This causes problems with
* Omega (and probably other apps) when calling GrayString which uses this
* routine...
*/
textColorSave = SetTextColor(hdc, 0x00000000L);
bkColorSave = SetBkColor(hdc, 0x00FFFFFFL);
hbrSave = SelectObject(hdc, hbr);
BitBlt(hdc, xO, yO, cx, cy, hdcSrce ? hdcSrce : hdcGray, xO1, yO1,
(fInvert ? 0x00B8074AL : 0x00E20746L));
SelectObject(hdc, hbrSave);
/* Restore saved colors */
SetTextColor(hdc, textColorSave);
SetBkColor(hdc, bkColorSave);
}
#endif // WOW
/*--------------------------------------------------------------------------*/
/* */
/* DrawFrame() - */
/* */
/*--------------------------------------------------------------------------*/
#define DF_SHIFTMASK (DF_SHIFT0 | DF_SHIFT1 | DF_SHIFT2 | DF_SHIFT3)
#define DF_ROPMASK (DF_PATCOPY | DF_PATINVERT)
#define DF_HBRMASK ~(DF_SHIFTMASK | DF_ROPMASK)
/* Command bits:
* 0000 0011 - (0-3): Shift count for cxBorder and cyBorder
* 0000 0100 - 0: PATCOPY, 1: PATINVERT
* 1111 1000 - (0-x): Brushes as they correspond to the COLOR_*
* indexes, with hbrGray thrown on last.
*/
void USERENTRY DrawFrame(hdc, lprc, clFrame, cmd)
HDC hdc;
LPRECT lprc;
int clFrame;
int cmd;
{
register int x;
register int y;
int cx;
int cy;
int cxWidth;
int cyWidth;
int ibr;
HBRUSH hbrSave;
LONG rop;
#ifdef WOW
DWORD rgbTemp;
static DWORD rgbPrev;
static HBRUSH hbrPrev;
#endif
x = lprc->left;
y = lprc->top;
cxWidth = GetSystemMetrics(SM_CXBORDER) * clFrame;
cyWidth = GetSystemMetrics(SM_CYBORDER) * clFrame;
if (cmd == DF_ACTIVEBORDER || cmd == DF_INACTIVEBORDER)
{
/* We are drawing the inside colored part of a sizing border. We
* subtract 1 from the width and height because we come back and draw
* another frame around the inside. This avoids a lot of flicker when
* redrawing a frame that already exists.
*/
cxWidth--;
cyWidth--;
}
cx = lprc->right - x - cxWidth;
cy = lprc->bottom - y - cyWidth;
rop = ((cmd & DF_ROPMASK) ? PATINVERT : PATCOPY);
ibr = (cmd & DF_HBRMASK) >> 3;
#ifndef WOW
if (ibr == (DF_GRAY >> 3))
{
hbrSave = hbrGray;
}
else
{
hbrSave = ((HBRUSH *)&sysClrObjects)[ibr];
}
#else
rgbTemp = GetSysColor(ibr);
if (!(hbrSave = hbrPrev) || rgbTemp != rgbPrev) {
/* Save time and space with black and white objects. */
if (rgbTemp == 0L)
hbrSave = GetStockObject(BLACK_BRUSH);
else if (rgbTemp == 0xFFFFFFL)
hbrSave = GetStockObject(WHITE_BRUSH);
else
hbrSave = CreateSolidBrush(rgbTemp);
if (hbrPrev)
DeleteObject(hbrPrev);
hbrPrev = hbrSave;
rgbPrev = rgbTemp;
}
#endif
// We need to unrealize the object in order to ensure it gets realigned.
//
UnrealizeObject(hbrSave);
hbrSave = SelectObject(hdc, hbrSave);
/* Time to call the new driver supported fast draw frame stuff. */
if (lprc->top >= lprc->bottom ||
!FastWindowFrame(hdc, lprc, cxWidth, cyWidth, rop))
{
/* The driver can't do it so we have to. */
PatBlt(hdc, x, y, cxWidth, cy, rop); /* Left */
PatBlt(hdc, x + cxWidth, y, cx, cyWidth, rop); /* Top */
PatBlt(hdc, x, y + cy, cx, cyWidth, rop); /* Bottom */
PatBlt(hdc, x + cx, y + cyWidth, cxWidth, cy, rop); /* Right */
}
if (hbrSave)
SelectObject(hdc, hbrSave);
}
#ifndef WOW
/*--------------------------------------------------------------------------*/
/* DrawPushButton() - */
/* */
/* lprc : The rectangle of the button */
/* style : Style of the push button */
/* fInvert : FALSE if pushbutton is in NORMAL state */
/* TRUE if it is to be drawn in the "down" or inverse state */
/* hbrBtn : The brush with which the background is to be wiped out. */
/* hwnd : NULL if no text is to be drawn in the button; */
/* Contains window handle, if text and focus is to be drawn; */
/* */
/*--------------------------------------------------------------------------*/
void FAR PASCAL DrawPushButton(hdc, lprc, style, fInvert, hbrBtn, hwnd)
register HDC hdc;
RECT FAR *lprc;
WORD style;
BOOL fInvert;
HBRUSH hbrBtn;
HWND hwnd;
{
RECT rcInside;
HBRUSH hbrSave;
HBRUSH hbrShade = 0;
HBRUSH hbrFace = 0;
int iBorderWidth;
int i;
int dxShadow;
int cxShadow;
int cyShadow;
if (style == LOWORD(BS_DEFPUSHBUTTON))
iBorderWidth = 2;
else
iBorderWidth = 1;
hbrSave = SelectObject(hdc, hbrBtn);
CopyRect((LPRECT)&rcInside, lprc);
InflateRect((LPRECT)&rcInside, -iBorderWidth*cxBorder,
-iBorderWidth*cyBorder);
/* Draw a frame */
DrawFrame(hdc, lprc, iBorderWidth, (COLOR_WINDOWFRAME << 3));
/* Notch the corners (except don't do this for scroll bar thumb (-1) or
for combo box buttons (-2)) */
if (style != -1 && style != -2)
{
/* Cut four notches at the four corners */
/* Top left corner */
PatBlt(hdc, lprc->left, lprc->top, cxBorder, cyBorder, PATCOPY);
/* Top right corner */
PatBlt(hdc, lprc->right - cxBorder, lprc->top, cxBorder, cyBorder,
PATCOPY);
/* bottom left corner */
PatBlt(hdc, lprc->left, lprc->bottom - cyBorder, cxBorder, cyBorder,
PATCOPY);
/* bottom right corner */
PatBlt(hdc, lprc->right - cxBorder, lprc->bottom - cyBorder, cxBorder,
cyBorder, PATCOPY);
}
/* Draw the shades */
if (sysColors.clrBtnShadow != 0x00ffffff)
{
hbrShade = sysClrObjects.hbrBtnShadow;
if (fInvert)
{
/* Use shadow color */
SelectObject(hdc, hbrShade);
dxShadow = 1;
}
else
{
/* Use white */
SelectObject(hdc, GetStockObject(WHITE_BRUSH));
dxShadow = (style == -1 ? 1 : 2);
}
cxShadow = cxBorder * dxShadow;
cyShadow = cyBorder * dxShadow;
/* Draw the shadow/highlight in the left and top edges */
PatBlt(hdc, rcInside.left, rcInside.top, cxShadow,
(rcInside.bottom - rcInside.top), PATCOPY);
PatBlt(hdc, rcInside.left, rcInside.top,
(rcInside.right - rcInside.left), cyShadow, PATCOPY);
if (!fInvert)
{
/* Use shadow color */
SelectObject(hdc, hbrShade);
/* Draw the shade in the bottom and right edges */
rcInside.bottom -= cyBorder;
rcInside.right -= cxBorder;
for(i = 0; i <= dxShadow; i++)
{
PatBlt(hdc, rcInside.left, rcInside.bottom,
rcInside.right - rcInside.left + cxBorder, cyBorder,
PATCOPY);
PatBlt(hdc, rcInside.right, rcInside.top, cxBorder,
rcInside.bottom - rcInside.top, PATCOPY);
if (i == 0)
InflateRect((LPRECT)&rcInside, -cxBorder, -cyBorder);
}
}
}
else
{
/* Don't move text down if no shadows */
fInvert = FALSE;
/* The following are added as a fix for Bug #2784; Without these
* two lines, cxShadow and cyShadow will be un-initialised when
* running under a CGA resulting in this bug;
* Bug #2784 -- 07-24-89 -- SANKAR
*/
cxShadow = cxBorder;
cyShadow = cyBorder;
}
/* Draw the button face color pad. If no clrBtnFace, use white to clear
it. */
/* if fInvert we don't subtract 1 otherwise we do because up above we
do an inflate rect if not inverting for the shadow along the bottom*/
rcInside.left += cxShadow - (fInvert ? 0 : cxBorder);
rcInside.top += cyShadow - (fInvert ? 0 : cyBorder);
if (sysColors.clrBtnFace != 0x00ffffff)
hbrFace = sysClrObjects.hbrBtnFace;
else
hbrFace = GetStockObject(WHITE_BRUSH);
SelectObject(hdc, hbrFace);
PatBlt(hdc, rcInside.left, rcInside.top, rcInside.right - rcInside.left,
rcInside.bottom - rcInside.top, PATCOPY);
if (hbrSave)
SelectObject(hdc, hbrSave);
}
/*
*---------------------------------------------------------------------------
* SEB_InitBtnInfo() -
* This function fills in the button info structure (SEBBTN) for the
* specified button.
*---------------------------------------------------------------------------
*/
void NEAR PASCAL SEB_InitBtnInfo(
HDC hdc, /* DC to be used in dispplaying the button */
unsigned int style, /* one of the SEB_* styles */
int xBtn,
int yBtn, /* center the button on this (x, y) pixel */
int cxBtn,
int cyBtn, /* make the button this size */
int index) /* index of the rgbtn entry to initialize */
{
long Extent;
int i;
int temp1, temp2;
#ifdef DEBUG
BOOL fFound = FALSE;
#endif
rgbtn[index].finvert = FALSE;
if ((rgbtn[index].style = style) == NULL)
return;
/* Calc the button text and accelerator */
for (i = 0; i < MAX_MB_STRINGS; i++)
{
if (rgStyles[i] == (style & ~SEB_DEFBUTTON))
{
rgbtn[index].psztext = AllMBbtnStrings[i];
rgbtn[index].chaccel = rgAccel[i];
#ifdef DEBUG
fFound = TRUE;
#endif
break;
}
}
#ifdef DEBUG
if (!fFound)
{
/* RIP city */
return;
}
#endif
/* Calc the button rectangle */
SetRect((LPRECT)&rgbtn[index].rcbtn,
(temp1 = xBtn - (cxBtn >> 1)),
(temp2 = yBtn - (cyBtn >> 1)),
temp1 + cxBtn,
temp2 + cyBtn);
/* Calc the text position */
Extent = PSMGetTextExtent(hdc,
(LPSTR)rgbtn[index].psztext,
lstrlen((LPSTR)rgbtn[index].psztext));
rgbtn[index].pttext.x = xBtn - (LOWORD(Extent) >> 1);
rgbtn[index].pttext.y = yBtn - (HIWORD(Extent) >> 1);
/* rgbtn[index].pttext.y = yBtn - (cySysFontAscent >> 1);*/
}
/*
*---------------------------------------------------------------------------
* SEB_DrawFocusRect() -
* This function draws the Focus frame.
*---------------------------------------------------------------------------
*/
void NEAR PASCAL SEB_DrawFocusRect(HDC hdc,
LPRECT lprcBtn,
LPSTR lpszBtnStr,
int iLen,
BOOL fPressed)
{
DWORD dwExtents;
RECT rc;
dwExtents = PSMGetTextExtent(hdc, (LPSTR)lpszBtnStr, iLen);
rc.left = lprcBtn->left + ((lprcBtn->right - lprcBtn->left - LOWORD(dwExtents)) >> 1) - (cxBorder << 1);
rc.right = rc.left + (cxBorder << 2) + LOWORD(dwExtents);
rc.top = lprcBtn->top + ((lprcBtn->bottom - lprcBtn->top - HIWORD(dwExtents)) >> 1) - cyBorder;
rc.bottom = rc.top + (cyBorder << 1) + HIWORD(dwExtents) + cyBorder;
if(fPressed)
OffsetRect(&rc, 1, 1);
/* NOTE: I know you will be tempted to use DrawFocusRect(); But this
* uses PatBlt() with PATINVERT! This causes instant death in int24
* SysErrBoxes! So, I am calling FrameRect() which calls PatBlt() with
* PATCOPY. This works fine in int24 cases also!
* --SANKAR--
*/
FrameRect(hdc, (LPRECT)&rc, hbrGray);
}
/*
*---------------------------------------------------------------------------
* SEB_DrawButton() -
* This function draws the button specified. The pbtninfo parameter is
* a pointer to a structure of type SEBBTN.
*---------------------------------------------------------------------------
*/
void NEAR PASCAL SEB_DrawButton(HDC hdc, /* HDC to use for drawing */
int i) /* index of the rgbtn to draw */
{
DWORD colorSave;
int iLen;
if (rgbtn[i].style == NULL)
return;
/* DrawPushButton() wipes out the background also */
DrawPushButton(hdc,
(LPRECT)&rgbtn[i].rcbtn,
(WORD)((rgbtn[i].style & SEB_DEFBUTTON) ? BS_DEFPUSHBUTTON:
BS_PUSHBUTTON),
rgbtn[i].finvert,
GetStockObject(WHITE_BRUSH),
(HWND)NULL);
colorSave = SetTextColor(hdc, sysColors.clrBtnText);
SetBkMode(hdc, TRANSPARENT);
/* Preserve the button color for vga systems */
PSMTextOut(hdc,
rgbtn[i].pttext.x + (rgbtn[i].finvert ? 1 : 0),
rgbtn[i].pttext.y + (rgbtn[i].finvert ? 1 : 0),
(LPSTR)rgbtn[i].psztext,
(iLen = lstrlen((LPSTR)rgbtn[i].psztext)));
/* Only the default button can have the focus frame */
if(rgbtn[i].style & SEB_DEFBUTTON)
SEB_DrawFocusRect(hdc,
(LPRECT)&rgbtn[i].rcbtn,
(LPSTR)rgbtn[i].psztext,
iLen,
rgbtn[i].finvert);
SetTextColor(hdc, colorSave);
SetBkMode(hdc, OPAQUE);
}
/*
*---------------------------------------------------------------------------
* SEB_BtnHit(pt)
* Return the index of the rgbtn that the point is in. If not in any button
* then return -1.
*---------------------------------------------------------------------------
*/
int NEAR SEB_BtnHit(int x, int y)
{
POINT pt;
register int i;
pt.x = x;
pt.y = y;
for (i = 0; i <= 2; i++)
{
if (rgbtn[i].style != NULL)
if (PtInRect((LPRECT)&rgbtn[i].rcbtn, pt))
return(i);
}
return(-1);
}
/*
*---------------------------------------------------------------------------
* SysErrorBox()
*
* This function is used to display a system error type message box. No
* system resources (other than the stack) is used to display this box.
* Also, it is guarenteed that all code needed to complete this function
* will be memory at all times. This will allow the calling of this
* funtion by the INT24 handler.
*
* Paramerers:
* lpszText Text string of the message itself. This message is
* assumed to be only one line in length and short enough
* to fit in the box. The box will size itself horizontally
* to center the string, but will not be sized beyond the
* size of the physical screen.
*
* lpszCaption Text of the caption of the box. This caption will be
* displayed at the top of the box, centered. The same
* restrictions apply.
*
* Btn1
* Btn2
* Btn3 One of the following:
* NULL No button in this position.
* SEB_OK Button with "OK".
* SEB_CANCEL Button with "Cancel"
* SEB_YES Button with "Yes"
* SEB_NO Button with "No"
* SEB_RETRY Button with "Retry"
* SEB_ABORT Button with "Abort"
* SEB_IGNORE Button with "Ignore"
*
* Also, one of the parameters may have the value
* SEB_DEFBUTTON
* OR'ed with any of the SEB_* valued above. This draws
* this button as the default button and sets the initial
* "focus" to this button. Only one button should have
* this style. If no buttons have this style, the first
* button whose value is not NULL will be the default button.
*
* Return Value:
* This funtion returns one of the following values:
*
* SEB_BTN1 Button 1 was selected
* SEB_BTN2 Button 2 was selected
* SEB_BTN3 Button 3 was selected
*
*---------------------------------------------------------------------------
*/
/* Maximum number of lines allowed in a system error box.
*/
#define MAXSYSERRLINES 3
/* Struct allocated on stack for max lines.
*/
typedef struct tagSysErr
{
int iStart;
int cch;
int cxText;
} SYSERRSTRUCT;
int USERENTRY SysErrorBox(lpszText, lpszCaption, btn1, btn2, btn3)
LPSTR lpszText;
LPSTR lpszCaption;
unsigned int btn1, btn2, btn3;
{
register int cx, cy;
SYSERRSTRUCT sysErr[MAXSYSERRLINES];
int temp;
int cchCaption;
int cxText, cxCaption, cxButtons;
int cxCenter, cxQuarter;
int cxBtn, cyBtn;
int xBtn, yBtn;
int iTextLines;
HDC hdc;
RECT rcBox, rcTemp;
HRGN hrgn;
int far *pbtn;
int i;
MSG msg;
BOOL fBtnDown;
BOOL fKeyBtnDown = FALSE;
int BtnReturn;
int btnhit;
int defbtn;
HWND hwndFocusSave;
BOOL fMessageBoxGlobalOld = fMessageBox;
BOOL fOldHWInput;
HWND hwndSysModalBoxOld;
LPSTR lptemp;
RECT rcInvalidDesktop; /* Keep union of invalid desktop rects */
/* We have to determine if we are running Win386 in PMODE
* at the time of bringing up this SysErrBox. In this case we
* have to call Win386 to Set the screen focus to us so that
* the user can see the SYSMODAL error message that we display;
* Fix for Bug #5272 --SANKAR-- 10-12-89
*/
if ((WinFlags & WF_WIN386) && (WinFlags & WF_PMODE))
GetbackFocusFromWinOldAp();
/* Set this global so that we don't over write our globals when kernel calls
* this routine directly. We need to save and restore the state of the
* fMessageBox flag. If SysErrorBox is called via HardSysModal, then this
* flag is set and we do proper processing in the message loop. However, if
* Kernel calls syserrorbox directly, then this flag wasn't being set and we
* could break...
*/
fMessageBox = TRUE;
/* Save off the guy who was the old sys modal dialog box in case the int24
* box is put up when a sys modal box is up.
*/
hwndSysModalBoxOld = hwndSysModal;
/* Clear this global so that if the mouse is down on an NC area we don't
* drop into the move/size code when we return. If we do, it thinks the
* mouse is down when it really isn't
*/
fInt24 = TRUE;
/* Initialise the Global structure */
LFillStruct((LPSTR)rgbtn, 3*sizeof(SEBBTN), '\0');
/* Change the hq for the desktop to be the current task hq */
if (NEEDSPAINT(hwndDesktop))
DecPaintCount(hwndDesktop);
hwndDesktop->hq = HqCurrent();
if (NEEDSPAINT(hwndDesktop))
IncPaintCount(hwndDesktop);
hdc = GetScreenDC();
/*
* Calculate the extents of the error box. Then set the rectangle that
* we will use for drawing.
*
* The x extent of the box is the maximin of the the folowing items:
* - The text for the box (padded with 3 chars on each end).
* - The caption for the box (also padded).
* - 3 maximum sized buttons (szCANCEL).
*
* The y extent is 10 times the height of the system font.
*
*/
cy = cySysFontChar * 10;
/* How many lines in the box text and their extents etc?
*/
iTextLines = 0;
sysErr[0].iStart = 0;
sysErr[0].cch = 0;
sysErr[0].cxText = 0;
lptemp=lpszText;
cxText = 0; /* Max text length
*/
while (lptemp)
{
if (*lptemp == '\n' || *lptemp==0)
{
sysErr[iTextLines].cxText = LOWORD(GetTextExtent(hdc,
(LPSTR)(lpszText+sysErr[iTextLines].iStart),
sysErr[iTextLines].cch));
/* Keep track of length of longest line
*/
cxText = max(sysErr[iTextLines].cxText,cxText);
if (*lptemp && *(lptemp+1)!=0 && iTextLines < MAXSYSERRLINES)
{
/* Another line exists
*/
iTextLines++;
sysErr[iTextLines].iStart = sysErr[iTextLines-1].iStart +
sysErr[iTextLines-1].cch+1;
sysErr[iTextLines].cch = 0;
sysErr[iTextLines].cxText = 0;
lptemp++;
}
else
break;
}
else
{
sysErr[iTextLines].cch++;
lptemp++;
}
}
cx = cxText + (6 * cxSysFontChar);
/* Get the extent of the box caption
*/
cxCaption = LOWORD(GetTextExtent(hdc,
(LPSTR)lpszCaption,
(cchCaption = lstrlen(lpszCaption))));
temp = cxCaption + (6 * cxSysFontChar);
if (cx < temp)
cx = temp;
/* Get the extent of 3 maximum sized buttons */
cxBtn = wMaxBtnSize + (cySysFontChar << 1);
cxButtons = (cxBtn + (cySysFontChar << 2)) * 3;
if (cx < cxButtons)
cx = cxButtons;
/* Center the box on the screen. Bound to left edge if too big. */
rcBox.top = (cyScreen >> 1) - (cy >> 1);
rcBox.bottom = rcBox.top + cy;
rcBox.left = (cxScreen >> 1) - (cx >> 1);
if (rcBox.left < 0)
rcBox.left = 0;
rcBox.right = rcBox.left + cx;
cxCenter = (rcBox.left + rcBox.right) >> 1;
PatBlt(hdc, rcBox.left, rcBox.top, cx, cy, WHITENESS);
rcTemp = rcBox;
DrawFrame(hdc, &rcTemp, 1, DF_WINDOWFRAME);
InflateRect(&rcTemp, -(cxBorder * (CLDLGFRAMEWHITE + 1)),
-(cyBorder * (CLDLGFRAMEWHITE + 1)));
DrawFrame(hdc, &rcTemp, CLDLGFRAME, DF_ACTIVECAPTION);
TextOut(hdc,
cxCenter - (cxCaption >> 1),
rcBox.top + cySysFontChar,
(LPSTR)lpszCaption,
cchCaption);
i=0;
/* First line of text starts at what y offset ?
*/
if (iTextLines == 0)
temp = (cySysFontChar << 2);
else
temp = (cySysFontChar << 1)+(cySysFontChar * (MAXSYSERRLINES-iTextLines));
while (i<=iTextLines)
{
TextOut(hdc,
/* cxCenter - (cxText >> 1),*/
cxCenter - (sysErr[i].cxText >> 1),
rcBox.top + temp+(i*cySysFontChar),
(LPSTR)lpszText+sysErr[i].iStart,
sysErr[i].cch);
i++;
}
pbtn = &btn1;
xBtn = (cxQuarter = cx >> 2) + rcBox.left;
yBtn = rcBox.bottom - (cySysFontChar << 1);
cyBtn = cySysFontChar << 1;
for (i=0; i <= 2; i++, pbtn--)
{
SEB_InitBtnInfo(hdc, *pbtn, xBtn, yBtn, cxBtn, cyBtn, i);
SEB_DrawButton(hdc, i);
xBtn += cxQuarter;
}
Capture(hwndDesktop, CLIENT_CAPTURE);
SetSysModalWindow(hwndDesktop);
/*hCursOld =*/ SetCursor(hCursNormal);
/* Why are we doing this???? This is causing us to hit the disk to load some
* cursor resource during interrupt time... davidds
*/
/* CallOEMCursor();*/
hwndFocusSave = hwndFocus;
hwndFocus = hwndDesktop;
fBtnDown = FALSE;
BtnReturn = 0;
btnhit = -1; /* -1 if not on a button, else index into rgbtn[] */
defbtn = -1;
for (i = 0; i <= 2; i++)
if (rgbtn[i].style & SEB_DEFBUTTON)
{
defbtn = i;
break;
}
/* Prevent other tasks from running because this is SysModal */
if (!fEndSession)
LockMyTask(TRUE);
/* Insure that hardware input is enabled */
fOldHWInput = EnableHardwareInput(TRUE);
/* Initially, only invalidate desktop where the sys error box was.
*/
rcInvalidDesktop = rcBox;
while (BtnReturn == 0)
{
if (!PeekMessage((LPMSG)&msg, hwndDesktop, 0, 0, PM_REMOVE | PM_NOYIELD))
continue;
#ifdef NEVER
********* TranslateMessage() calls ToAscii() which refers to some tables
in a LoadOnCall segment; So, this is commented out here; We can not
look for WM_CHAR messages, but we still get WM_KEYDOWN messages!
--Sankar, April 17, 1989--
TranslateMessage((LPMSG)&msg);
*********
#endif
if (msg.hwnd == hwndDesktop)
{
switch (msg.message)
{
case WM_LBUTTONDOWN:
fBtnDown = TRUE;
if ((btnhit = SEB_BtnHit(LOWORD(msg.lParam),
HIWORD(msg.lParam))) != -1)
{
/* Move the default button to the next button.
*/
if ((defbtn != -1) && (btnhit != defbtn))
{
/* Draw the current def button as not default.
*/
rgbtn[defbtn].style &= ~SEB_DEFBUTTON;
SEB_DrawButton(hdc, defbtn);
/* Draw the new button as default.
*/
defbtn = btnhit;
rgbtn[btnhit].style |= SEB_DEFBUTTON;
}
rgbtn[btnhit].finvert = TRUE;
SEB_DrawButton(hdc, btnhit);
}
break;
case WM_LBUTTONUP:
fBtnDown = FALSE;
/* Was the mouse hitting on a button? If so, terminate the
* loop and return the button index.
*/
if (btnhit != -1)
BtnReturn = btnhit + 1;
break;
case WM_MOUSEMOVE:
/* Only look at mouse moves if the button is down.
*/
if (fBtnDown)
{
/* Hitting on a button?
*/
if ((i = SEB_BtnHit(LOWORD(msg.lParam), HIWORD(msg.lParam))) != -1)
{
/* Mouse moved and we are on a button. First test
* to see if we are on the same button as before.
*/
if ((i != btnhit) && (btnhit != -1))
{
rgbtn[btnhit].finvert = FALSE;
SEB_DrawButton(hdc, btnhit);
}
/* Verify that the new button is
* inverted and that btnhit is current.
*/
btnhit = i;
if (rgbtn[btnhit].finvert == FALSE)
{
rgbtn[btnhit].finvert = TRUE;
SEB_DrawButton(hdc, btnhit);
}
} else {
/* button down, but not hitting on a button. Check
* for drag off a button.
*/
if (btnhit != -1)
{
rgbtn[btnhit].finvert = FALSE;
SEB_DrawButton(hdc, btnhit);
btnhit = -1;
}
}
}
break;
case WM_KEYUP:
if(fKeyBtnDown)
{
switch(msg.wParam)
{
case VERYBIGINTEGER:
/* Because this code gets moved into himem, we can't use jump
* tables; This VERYBIGINTEGER prevents C6.0 from using a jump
* table in the translation of Switch Statements;
*/
break;
case VK_SPACE:
case VK_RETURN:
/* Select the current default button and return.
*/
if (defbtn != -1)
BtnReturn = defbtn + 1;
break;
}
}
break;
case WM_PAINT:
GetUpdateRect(msg.hwnd, &rcTemp, FALSE);
ValidateRect(msg.hwnd, NULL);
UnionRect(&rcInvalidDesktop, &rcInvalidDesktop, &rcTemp);
break;
case WM_SYSKEYDOWN:
/* Look for accelerator keys
*/
for (i = 0; i <= 2; i++)
{
/* Convert to lower case and test for a match */
if (((BYTE)msg.wParam | 0x20) == rgbtn[i].chaccel)
{
BtnReturn = i + 1;
break;
}
}
break;
case WM_KEYDOWN:
switch (msg.wParam)
{
case VK_SPACE:
case VK_RETURN:
/* Just keep the button pressed */
/* If already pressed, ignore the rest sothat we
* won't flicker horribly
*/
if((defbtn != -1) && (!fKeyBtnDown))
{
fKeyBtnDown = TRUE;
rgbtn[defbtn].finvert = TRUE;
SEB_DrawButton(hdc, defbtn);
}
break;
case VK_TAB:
/* Move the default button to the next button.
*/
if (defbtn != -1)
{
/* Draw the current def button as not default.
*/
rgbtn[defbtn].style &= ~SEB_DEFBUTTON;
SEB_DrawButton(hdc, defbtn);
/* Calc the next def button. Inc defbtn, but
* wrap from btn 3 to btn 1. Also, don't stop
* on a button that isn't defined.
*/
if (defbtn == 2)
defbtn = 0;
else
++defbtn;
while (rgbtn[defbtn].style == NULL)
{
if (++defbtn > 2)
defbtn = 0;
}
/* Draw the new default button as default.
*/
rgbtn[defbtn].style |= SEB_DEFBUTTON;
SEB_DrawButton(hdc, defbtn);
}
break;
case VK_ESCAPE:
/* See if there is a button with SEB_CANCEL. If there
* is, return it's id.
*/
for (i = 0; i <= 2; i++)
{
if ((rgbtn[i].style & ~SEB_DEFBUTTON)
== SEB_CANCEL)
{
BtnReturn = ++i;
break;
}
}
break;
}
break;
}
}
}
fMessageBox=fMessageBoxGlobalOld;
/* Insure that hardware input is put back the way it was */
EnableHardwareInput(fOldHWInput);
/* Allow other tasks to run. */
LockMyTask(FALSE);
/* Set sys modal box back to the guy who was up */
SetSysModalWindow(hwndSysModalBoxOld);
Capture(NULL, NO_CAP_CLIENT);
#if 0
The old cursor may have been paged out. We can't do this.
SetCursor(hCursOld);
#endif
#if causetrouble
if (iLevelCursor < 0)
OEMSetCursor((LPSTR)NULL);
#endif
hwndFocus = hwndFocusSave;
/* Set this flag indicating that another window was activate so that if we
* were in menu mode when the sys error box came up, we know we should get
* out because the actual mouse button/keyboard state may be different than
* what the menu state thinks it is.
*/
fActivatedWindow = TRUE;
InternalReleaseDC(hdc);
/* Invalidate the invalid portions of the desktop.
*/
InvalidateRect(hwndDesktop, &rcInvalidDesktop, FALSE);
hrgn = CreateRectRgn(rcInvalidDesktop.left, rcInvalidDesktop.top,
rcInvalidDesktop.right,rcInvalidDesktop.bottom);
InternalInvalidate(hwndDesktop, (hrgn ? hrgn : (HRGN) 1),
RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
if (hrgn)
DeleteObject(hrgn);
// RedrawScreen();
return(BtnReturn);
}
int NEAR PASCAL HardSysModalMessageBox(LPSTR lpszText,
LPSTR lpszCaption,
WORD wBtnCnt,
WORD wType)
{
WORD wBegBtn;
int iCurIndex;
int iCurButton;
WORD iButtonNo;
int iRetVal;
WORD wTemp;
struct
{
unsigned int InVal;
char RetVal;
}Param[3];
/* If we're trying to bring up a hard sys modal message box
* while another one is up, wait till the first one is through.
* This protects our static save globals. I'm not actually
* sure this can ever happen (at least under DOS 3).
*/
if (fMessageBox)
Yield();
fMessageBox = TRUE;
wBegBtn = mpTypeIich[wType]; /* Index of Begining button */
Param[0].InVal = Param[1].InVal = Param[2].InVal = 0;
iCurIndex = 0;
for(iButtonNo = 0; iButtonNo < wBtnCnt; iButtonNo++)
{
iCurButton = iCurIndex;
switch(wBtnCnt)
{
case 1: /* One button; Put it in Param[1] */
Param[1].InVal = SEBbuttons[wBegBtn];
Param[1].RetVal = rgReturn[wBegBtn];
iCurButton = 1;
break;
case 2: /* 2 Buttons; Put them in Param[0] and Param[2] */
Param[iCurIndex].InVal = SEBbuttons[wTemp = wBegBtn + iButtonNo];
Param[iCurIndex].RetVal = rgReturn[wTemp];
iCurIndex += 2;
break;
case 3: /* 3 Buttons; Put them in Param[0], [1] and [2] */
Param[iCurIndex].InVal = SEBbuttons[wTemp = wBegBtn + iButtonNo];
Param[iCurIndex].RetVal = rgReturn[wTemp];
iCurIndex++;
break;
}
/* Check for the default button */
if(wDefButton == iButtonNo)
Param[iCurButton].InVal |= SEB_DEFBUTTON;
}
iRetVal = SysErrorBox(lpszText, lpszCaption, Param[0].InVal,
Param[1].InVal, Param[2].InVal);
fMessageBox = FALSE;
return((int)Param[iRetVal - SEB_BTN1].RetVal);
}
/*--------------------------------------------------------------------------*/
/* */
/* MessageBox() - */
/* */
/*--------------------------------------------------------------------------*/
int USERENTRY MessageBox(hwndOwner, lpszText, lpszCaption, wStyle)
HWND hwndOwner;
LPSTR lpszText;
LPSTR lpszCaption;
WORD wStyle;
{
WORD wBtnCnt;
WORD wType;
WORD wIcon;
#ifdef DEBUG
if (!GetTaskQueue(GetCurrentTask()))
{
/* There is no task queue. Not put up message boxes.
*/
UserFatalExitSz(RIP_MESSAGEBOXWITHNOQUEUE,
"\n\rMessageBox failed - no message queue has been initialized yet. MessageBox not allowed.",
0);
}
#endif
/* If lpszCaption is NULL, then use "Error!" string as the caption
string */
if(!lpszCaption)
lpszCaption = (LPSTR)szERROR;
wBtnCnt = mpTypeCcmd[(wType = wStyle & MB_TYPEMASK)];
/* Set the default button value */
wDefButton = (wStyle & MB_DEFMASK) / (MB_DEFMASK & (MB_DEFMASK >> 3));
if(wDefButton >= wBtnCnt) /* Check if valid */
wDefButton = 0; /* Set the first button if error */
/* Check if this is a hard sys modal message box */
wIcon = wStyle & MB_ICONMASK;
if(((wStyle & MB_MODEMASK) == MB_SYSTEMMODAL) &&
((wIcon == NULL) || (wIcon == MB_ICONHAND)))
{
/* It is a hard sys modal message box */
return(HardSysModalMessageBox(lpszText, lpszCaption, wBtnCnt, wType));
}
else
return(SoftModalMessageBox(hwndOwner, lpszText, lpszCaption, wStyle));
}
BOOL FAR PASCAL IsSystemFont(hdc)
register HDC hdc;
/* effects: Returns TRUE if font selected into DC is the system font else
returns false. This is called by interrupt time code so it needs to be
in the fixed code segment. */
{
return(GetCurLogFont(hdc) == GetStockObject(SYSTEM_FONT));
}
BOOL FAR PASCAL IsSysFontAndDefaultMode(hdc)
register HDC hdc;
/* effects: Returns TRUE if font selected into DC is the system font AND
the current mapping mode of the DC is MM_TEXT (Default mode); else
returns false. This is called by interrupt time code so it needs to be
in the fixed code segment. */
/* This function is the fix for Bug #8717 --02-01-90-- SANKAR */
{
return(IsSystemFont(hdc) && (GetMapMode(hdc) == MM_TEXT));
}
int USERENTRY WEP(int i)
{
return(1);
}
#endif // WOW