Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1263 lines
38 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WMSYSERR.C
  8. * WOW16 system error box handling services
  9. *
  10. * History:
  11. *
  12. * Created 28-May-1991 by Jeff Parsons (jeffpar)
  13. * Copied from WIN31 and edited (as little as possible) for WOW16.
  14. * At this time, all we want is DrawFrame(), which the edit controls use.
  15. --*/
  16. /****************************************************************************/
  17. /* */
  18. /* WMSYSERR.C */
  19. /* */
  20. /* System error box handling routine */
  21. /* */
  22. /****************************************************************************/
  23. #include "user.h"
  24. #ifndef WOW
  25. VOID FAR PASCAL GetbackFocusFromWinOldAp(void);
  26. /* Private export from GDI for user. */
  27. HFONT FAR PASCAL GetCurLogFont(HDC);
  28. /* This array contins the state information for the three possible buttons in
  29. * a SysErrorBox.
  30. */
  31. SEBBTN rgbtn[3];
  32. /* The following arrays are used to map SEB_values to their respective
  33. * accelerator keys and text strings.
  34. */
  35. #define BTNTYPECOUNT 7
  36. static int rgStyles[BTNTYPECOUNT] =
  37. { SEB_OK, SEB_CANCEL, SEB_YES, SEB_NO, SEB_RETRY,
  38. SEB_ABORT, SEB_IGNORE };
  39. /* The following array is properly initialised by reading STR_ACCELERATORS
  40. * string at LoadWindows time, which contains the accelerator keys
  41. * corresponding to each button in the message box; Localizers must modify
  42. * this string also. Because, this array will be filled by loading a
  43. * string we must have one more space for the null terminator.
  44. */
  45. char rgAccel[BTNTYPECOUNT+1];
  46. extern WORD wDefButton;
  47. int FAR PASCAL SoftModalMessageBox(HWND, LPSTR, LPSTR, WORD);
  48. /*--------------------------------------------------------------------------*/
  49. /* */
  50. /* BltColor() - */
  51. /* */
  52. /* Modification done by SANKAR on 08-03-89: */
  53. /* The parameter hbm was used as a boolean only to determine whether to */
  54. /* use hdcBits or hdcGrey; Now hbm is replaced with hdcSrce, the source*/
  55. /* device context because, now hdcBits contains color bitmaps and */
  56. /* hdcMonoBits contains monochrome bitmaps; If hdcSrce is NULL, then */
  57. /* hdcGrey will be used, else whatever is passed thro hdcSrce will be */
  58. /* used as the source device context; */
  59. /* */
  60. /*--------------------------------------------------------------------------*/
  61. void FAR PASCAL BltColor(hdc, hbr, hdcSrce, xO, yO, cx, cy, xO1, yO1, fInvert)
  62. register HDC hdc;
  63. register HBRUSH hbr;
  64. HDC hdcSrce;
  65. int xO, yO;
  66. int cx, cy;
  67. int xO1, yO1;
  68. BOOL fInvert;
  69. {
  70. HBRUSH hbrSave;
  71. DWORD textColorSave;
  72. DWORD bkColorSave;
  73. #ifdef DEBUG
  74. if (!hdcGray && !hdcSrce) /* Only test hdcGray if it will be used */
  75. FatalExit(RIP_BADDCGRAY);
  76. #endif
  77. if (hbr == (HBRUSH)NULL)
  78. hbr = sysClrObjects.hbrWindowText;
  79. /*
  80. * Set the Text and Background colors so that bltColor handles the
  81. * background of buttons (and other bitmaps) properly.
  82. * Save the HDC's old Text and Background colors. This causes problems with
  83. * Omega (and probably other apps) when calling GrayString which uses this
  84. * routine...
  85. */
  86. textColorSave = SetTextColor(hdc, 0x00000000L);
  87. bkColorSave = SetBkColor(hdc, 0x00FFFFFFL);
  88. hbrSave = SelectObject(hdc, hbr);
  89. BitBlt(hdc, xO, yO, cx, cy, hdcSrce ? hdcSrce : hdcGray, xO1, yO1,
  90. (fInvert ? 0x00B8074AL : 0x00E20746L));
  91. SelectObject(hdc, hbrSave);
  92. /* Restore saved colors */
  93. SetTextColor(hdc, textColorSave);
  94. SetBkColor(hdc, bkColorSave);
  95. }
  96. #endif // WOW
  97. /*--------------------------------------------------------------------------*/
  98. /* */
  99. /* DrawFrame() - */
  100. /* */
  101. /*--------------------------------------------------------------------------*/
  102. #define DF_SHIFTMASK (DF_SHIFT0 | DF_SHIFT1 | DF_SHIFT2 | DF_SHIFT3)
  103. #define DF_ROPMASK (DF_PATCOPY | DF_PATINVERT)
  104. #define DF_HBRMASK ~(DF_SHIFTMASK | DF_ROPMASK)
  105. /* Command bits:
  106. * 0000 0011 - (0-3): Shift count for cxBorder and cyBorder
  107. * 0000 0100 - 0: PATCOPY, 1: PATINVERT
  108. * 1111 1000 - (0-x): Brushes as they correspond to the COLOR_*
  109. * indexes, with hbrGray thrown on last.
  110. */
  111. void USERENTRY DrawFrame(hdc, lprc, clFrame, cmd)
  112. HDC hdc;
  113. LPRECT lprc;
  114. int clFrame;
  115. int cmd;
  116. {
  117. register int x;
  118. register int y;
  119. int cx;
  120. int cy;
  121. int cxWidth;
  122. int cyWidth;
  123. int ibr;
  124. HBRUSH hbrSave;
  125. LONG rop;
  126. #ifdef WOW
  127. DWORD rgbTemp;
  128. static DWORD rgbPrev;
  129. static HBRUSH hbrPrev;
  130. #endif
  131. x = lprc->left;
  132. y = lprc->top;
  133. cxWidth = GetSystemMetrics(SM_CXBORDER) * clFrame;
  134. cyWidth = GetSystemMetrics(SM_CYBORDER) * clFrame;
  135. if (cmd == DF_ACTIVEBORDER || cmd == DF_INACTIVEBORDER)
  136. {
  137. /* We are drawing the inside colored part of a sizing border. We
  138. * subtract 1 from the width and height because we come back and draw
  139. * another frame around the inside. This avoids a lot of flicker when
  140. * redrawing a frame that already exists.
  141. */
  142. cxWidth--;
  143. cyWidth--;
  144. }
  145. cx = lprc->right - x - cxWidth;
  146. cy = lprc->bottom - y - cyWidth;
  147. rop = ((cmd & DF_ROPMASK) ? PATINVERT : PATCOPY);
  148. ibr = (cmd & DF_HBRMASK) >> 3;
  149. #ifndef WOW
  150. if (ibr == (DF_GRAY >> 3))
  151. {
  152. hbrSave = hbrGray;
  153. }
  154. else
  155. {
  156. hbrSave = ((HBRUSH *)&sysClrObjects)[ibr];
  157. }
  158. #else
  159. rgbTemp = GetSysColor(ibr);
  160. if (!(hbrSave = hbrPrev) || rgbTemp != rgbPrev) {
  161. /* Save time and space with black and white objects. */
  162. if (rgbTemp == 0L)
  163. hbrSave = GetStockObject(BLACK_BRUSH);
  164. else if (rgbTemp == 0xFFFFFFL)
  165. hbrSave = GetStockObject(WHITE_BRUSH);
  166. else
  167. hbrSave = CreateSolidBrush(rgbTemp);
  168. if (hbrPrev)
  169. DeleteObject(hbrPrev);
  170. hbrPrev = hbrSave;
  171. rgbPrev = rgbTemp;
  172. }
  173. #endif
  174. // We need to unrealize the object in order to ensure it gets realigned.
  175. //
  176. UnrealizeObject(hbrSave);
  177. hbrSave = SelectObject(hdc, hbrSave);
  178. /* Time to call the new driver supported fast draw frame stuff. */
  179. if (lprc->top >= lprc->bottom ||
  180. !FastWindowFrame(hdc, lprc, cxWidth, cyWidth, rop))
  181. {
  182. /* The driver can't do it so we have to. */
  183. PatBlt(hdc, x, y, cxWidth, cy, rop); /* Left */
  184. PatBlt(hdc, x + cxWidth, y, cx, cyWidth, rop); /* Top */
  185. PatBlt(hdc, x, y + cy, cx, cyWidth, rop); /* Bottom */
  186. PatBlt(hdc, x + cx, y + cyWidth, cxWidth, cy, rop); /* Right */
  187. }
  188. if (hbrSave)
  189. SelectObject(hdc, hbrSave);
  190. }
  191. #ifndef WOW
  192. /*--------------------------------------------------------------------------*/
  193. /* DrawPushButton() - */
  194. /* */
  195. /* lprc : The rectangle of the button */
  196. /* style : Style of the push button */
  197. /* fInvert : FALSE if pushbutton is in NORMAL state */
  198. /* TRUE if it is to be drawn in the "down" or inverse state */
  199. /* hbrBtn : The brush with which the background is to be wiped out. */
  200. /* hwnd : NULL if no text is to be drawn in the button; */
  201. /* Contains window handle, if text and focus is to be drawn; */
  202. /* */
  203. /*--------------------------------------------------------------------------*/
  204. void FAR PASCAL DrawPushButton(hdc, lprc, style, fInvert, hbrBtn, hwnd)
  205. register HDC hdc;
  206. RECT FAR *lprc;
  207. WORD style;
  208. BOOL fInvert;
  209. HBRUSH hbrBtn;
  210. HWND hwnd;
  211. {
  212. RECT rcInside;
  213. HBRUSH hbrSave;
  214. HBRUSH hbrShade = 0;
  215. HBRUSH hbrFace = 0;
  216. int iBorderWidth;
  217. int i;
  218. int dxShadow;
  219. int cxShadow;
  220. int cyShadow;
  221. if (style == LOWORD(BS_DEFPUSHBUTTON))
  222. iBorderWidth = 2;
  223. else
  224. iBorderWidth = 1;
  225. hbrSave = SelectObject(hdc, hbrBtn);
  226. CopyRect((LPRECT)&rcInside, lprc);
  227. InflateRect((LPRECT)&rcInside, -iBorderWidth*cxBorder,
  228. -iBorderWidth*cyBorder);
  229. /* Draw a frame */
  230. DrawFrame(hdc, lprc, iBorderWidth, (COLOR_WINDOWFRAME << 3));
  231. /* Notch the corners (except don't do this for scroll bar thumb (-1) or
  232. for combo box buttons (-2)) */
  233. if (style != -1 && style != -2)
  234. {
  235. /* Cut four notches at the four corners */
  236. /* Top left corner */
  237. PatBlt(hdc, lprc->left, lprc->top, cxBorder, cyBorder, PATCOPY);
  238. /* Top right corner */
  239. PatBlt(hdc, lprc->right - cxBorder, lprc->top, cxBorder, cyBorder,
  240. PATCOPY);
  241. /* bottom left corner */
  242. PatBlt(hdc, lprc->left, lprc->bottom - cyBorder, cxBorder, cyBorder,
  243. PATCOPY);
  244. /* bottom right corner */
  245. PatBlt(hdc, lprc->right - cxBorder, lprc->bottom - cyBorder, cxBorder,
  246. cyBorder, PATCOPY);
  247. }
  248. /* Draw the shades */
  249. if (sysColors.clrBtnShadow != 0x00ffffff)
  250. {
  251. hbrShade = sysClrObjects.hbrBtnShadow;
  252. if (fInvert)
  253. {
  254. /* Use shadow color */
  255. SelectObject(hdc, hbrShade);
  256. dxShadow = 1;
  257. }
  258. else
  259. {
  260. /* Use white */
  261. SelectObject(hdc, GetStockObject(WHITE_BRUSH));
  262. dxShadow = (style == -1 ? 1 : 2);
  263. }
  264. cxShadow = cxBorder * dxShadow;
  265. cyShadow = cyBorder * dxShadow;
  266. /* Draw the shadow/highlight in the left and top edges */
  267. PatBlt(hdc, rcInside.left, rcInside.top, cxShadow,
  268. (rcInside.bottom - rcInside.top), PATCOPY);
  269. PatBlt(hdc, rcInside.left, rcInside.top,
  270. (rcInside.right - rcInside.left), cyShadow, PATCOPY);
  271. if (!fInvert)
  272. {
  273. /* Use shadow color */
  274. SelectObject(hdc, hbrShade);
  275. /* Draw the shade in the bottom and right edges */
  276. rcInside.bottom -= cyBorder;
  277. rcInside.right -= cxBorder;
  278. for(i = 0; i <= dxShadow; i++)
  279. {
  280. PatBlt(hdc, rcInside.left, rcInside.bottom,
  281. rcInside.right - rcInside.left + cxBorder, cyBorder,
  282. PATCOPY);
  283. PatBlt(hdc, rcInside.right, rcInside.top, cxBorder,
  284. rcInside.bottom - rcInside.top, PATCOPY);
  285. if (i == 0)
  286. InflateRect((LPRECT)&rcInside, -cxBorder, -cyBorder);
  287. }
  288. }
  289. }
  290. else
  291. {
  292. /* Don't move text down if no shadows */
  293. fInvert = FALSE;
  294. /* The following are added as a fix for Bug #2784; Without these
  295. * two lines, cxShadow and cyShadow will be un-initialised when
  296. * running under a CGA resulting in this bug;
  297. * Bug #2784 -- 07-24-89 -- SANKAR
  298. */
  299. cxShadow = cxBorder;
  300. cyShadow = cyBorder;
  301. }
  302. /* Draw the button face color pad. If no clrBtnFace, use white to clear
  303. it. */
  304. /* if fInvert we don't subtract 1 otherwise we do because up above we
  305. do an inflate rect if not inverting for the shadow along the bottom*/
  306. rcInside.left += cxShadow - (fInvert ? 0 : cxBorder);
  307. rcInside.top += cyShadow - (fInvert ? 0 : cyBorder);
  308. if (sysColors.clrBtnFace != 0x00ffffff)
  309. hbrFace = sysClrObjects.hbrBtnFace;
  310. else
  311. hbrFace = GetStockObject(WHITE_BRUSH);
  312. SelectObject(hdc, hbrFace);
  313. PatBlt(hdc, rcInside.left, rcInside.top, rcInside.right - rcInside.left,
  314. rcInside.bottom - rcInside.top, PATCOPY);
  315. if (hbrSave)
  316. SelectObject(hdc, hbrSave);
  317. }
  318. /*
  319. *---------------------------------------------------------------------------
  320. * SEB_InitBtnInfo() -
  321. * This function fills in the button info structure (SEBBTN) for the
  322. * specified button.
  323. *---------------------------------------------------------------------------
  324. */
  325. void NEAR PASCAL SEB_InitBtnInfo(
  326. HDC hdc, /* DC to be used in dispplaying the button */
  327. unsigned int style, /* one of the SEB_* styles */
  328. int xBtn,
  329. int yBtn, /* center the button on this (x, y) pixel */
  330. int cxBtn,
  331. int cyBtn, /* make the button this size */
  332. int index) /* index of the rgbtn entry to initialize */
  333. {
  334. long Extent;
  335. int i;
  336. int temp1, temp2;
  337. #ifdef DEBUG
  338. BOOL fFound = FALSE;
  339. #endif
  340. rgbtn[index].finvert = FALSE;
  341. if ((rgbtn[index].style = style) == NULL)
  342. return;
  343. /* Calc the button text and accelerator */
  344. for (i = 0; i < MAX_MB_STRINGS; i++)
  345. {
  346. if (rgStyles[i] == (style & ~SEB_DEFBUTTON))
  347. {
  348. rgbtn[index].psztext = AllMBbtnStrings[i];
  349. rgbtn[index].chaccel = rgAccel[i];
  350. #ifdef DEBUG
  351. fFound = TRUE;
  352. #endif
  353. break;
  354. }
  355. }
  356. #ifdef DEBUG
  357. if (!fFound)
  358. {
  359. /* RIP city */
  360. return;
  361. }
  362. #endif
  363. /* Calc the button rectangle */
  364. SetRect((LPRECT)&rgbtn[index].rcbtn,
  365. (temp1 = xBtn - (cxBtn >> 1)),
  366. (temp2 = yBtn - (cyBtn >> 1)),
  367. temp1 + cxBtn,
  368. temp2 + cyBtn);
  369. /* Calc the text position */
  370. Extent = PSMGetTextExtent(hdc,
  371. (LPSTR)rgbtn[index].psztext,
  372. lstrlen((LPSTR)rgbtn[index].psztext));
  373. rgbtn[index].pttext.x = xBtn - (LOWORD(Extent) >> 1);
  374. rgbtn[index].pttext.y = yBtn - (HIWORD(Extent) >> 1);
  375. /* rgbtn[index].pttext.y = yBtn - (cySysFontAscent >> 1);*/
  376. }
  377. /*
  378. *---------------------------------------------------------------------------
  379. * SEB_DrawFocusRect() -
  380. * This function draws the Focus frame.
  381. *---------------------------------------------------------------------------
  382. */
  383. void NEAR PASCAL SEB_DrawFocusRect(HDC hdc,
  384. LPRECT lprcBtn,
  385. LPSTR lpszBtnStr,
  386. int iLen,
  387. BOOL fPressed)
  388. {
  389. DWORD dwExtents;
  390. RECT rc;
  391. dwExtents = PSMGetTextExtent(hdc, (LPSTR)lpszBtnStr, iLen);
  392. rc.left = lprcBtn->left + ((lprcBtn->right - lprcBtn->left - LOWORD(dwExtents)) >> 1) - (cxBorder << 1);
  393. rc.right = rc.left + (cxBorder << 2) + LOWORD(dwExtents);
  394. rc.top = lprcBtn->top + ((lprcBtn->bottom - lprcBtn->top - HIWORD(dwExtents)) >> 1) - cyBorder;
  395. rc.bottom = rc.top + (cyBorder << 1) + HIWORD(dwExtents) + cyBorder;
  396. if(fPressed)
  397. OffsetRect(&rc, 1, 1);
  398. /* NOTE: I know you will be tempted to use DrawFocusRect(); But this
  399. * uses PatBlt() with PATINVERT! This causes instant death in int24
  400. * SysErrBoxes! So, I am calling FrameRect() which calls PatBlt() with
  401. * PATCOPY. This works fine in int24 cases also!
  402. * --SANKAR--
  403. */
  404. FrameRect(hdc, (LPRECT)&rc, hbrGray);
  405. }
  406. /*
  407. *---------------------------------------------------------------------------
  408. * SEB_DrawButton() -
  409. * This function draws the button specified. The pbtninfo parameter is
  410. * a pointer to a structure of type SEBBTN.
  411. *---------------------------------------------------------------------------
  412. */
  413. void NEAR PASCAL SEB_DrawButton(HDC hdc, /* HDC to use for drawing */
  414. int i) /* index of the rgbtn to draw */
  415. {
  416. DWORD colorSave;
  417. int iLen;
  418. if (rgbtn[i].style == NULL)
  419. return;
  420. /* DrawPushButton() wipes out the background also */
  421. DrawPushButton(hdc,
  422. (LPRECT)&rgbtn[i].rcbtn,
  423. (WORD)((rgbtn[i].style & SEB_DEFBUTTON) ? BS_DEFPUSHBUTTON:
  424. BS_PUSHBUTTON),
  425. rgbtn[i].finvert,
  426. GetStockObject(WHITE_BRUSH),
  427. (HWND)NULL);
  428. colorSave = SetTextColor(hdc, sysColors.clrBtnText);
  429. SetBkMode(hdc, TRANSPARENT);
  430. /* Preserve the button color for vga systems */
  431. PSMTextOut(hdc,
  432. rgbtn[i].pttext.x + (rgbtn[i].finvert ? 1 : 0),
  433. rgbtn[i].pttext.y + (rgbtn[i].finvert ? 1 : 0),
  434. (LPSTR)rgbtn[i].psztext,
  435. (iLen = lstrlen((LPSTR)rgbtn[i].psztext)));
  436. /* Only the default button can have the focus frame */
  437. if(rgbtn[i].style & SEB_DEFBUTTON)
  438. SEB_DrawFocusRect(hdc,
  439. (LPRECT)&rgbtn[i].rcbtn,
  440. (LPSTR)rgbtn[i].psztext,
  441. iLen,
  442. rgbtn[i].finvert);
  443. SetTextColor(hdc, colorSave);
  444. SetBkMode(hdc, OPAQUE);
  445. }
  446. /*
  447. *---------------------------------------------------------------------------
  448. * SEB_BtnHit(pt)
  449. * Return the index of the rgbtn that the point is in. If not in any button
  450. * then return -1.
  451. *---------------------------------------------------------------------------
  452. */
  453. int NEAR SEB_BtnHit(int x, int y)
  454. {
  455. POINT pt;
  456. register int i;
  457. pt.x = x;
  458. pt.y = y;
  459. for (i = 0; i <= 2; i++)
  460. {
  461. if (rgbtn[i].style != NULL)
  462. if (PtInRect((LPRECT)&rgbtn[i].rcbtn, pt))
  463. return(i);
  464. }
  465. return(-1);
  466. }
  467. /*
  468. *---------------------------------------------------------------------------
  469. * SysErrorBox()
  470. *
  471. * This function is used to display a system error type message box. No
  472. * system resources (other than the stack) is used to display this box.
  473. * Also, it is guarenteed that all code needed to complete this function
  474. * will be memory at all times. This will allow the calling of this
  475. * funtion by the INT24 handler.
  476. *
  477. * Paramerers:
  478. * lpszText Text string of the message itself. This message is
  479. * assumed to be only one line in length and short enough
  480. * to fit in the box. The box will size itself horizontally
  481. * to center the string, but will not be sized beyond the
  482. * size of the physical screen.
  483. *
  484. * lpszCaption Text of the caption of the box. This caption will be
  485. * displayed at the top of the box, centered. The same
  486. * restrictions apply.
  487. *
  488. * Btn1
  489. * Btn2
  490. * Btn3 One of the following:
  491. * NULL No button in this position.
  492. * SEB_OK Button with "OK".
  493. * SEB_CANCEL Button with "Cancel"
  494. * SEB_YES Button with "Yes"
  495. * SEB_NO Button with "No"
  496. * SEB_RETRY Button with "Retry"
  497. * SEB_ABORT Button with "Abort"
  498. * SEB_IGNORE Button with "Ignore"
  499. *
  500. * Also, one of the parameters may have the value
  501. * SEB_DEFBUTTON
  502. * OR'ed with any of the SEB_* valued above. This draws
  503. * this button as the default button and sets the initial
  504. * "focus" to this button. Only one button should have
  505. * this style. If no buttons have this style, the first
  506. * button whose value is not NULL will be the default button.
  507. *
  508. * Return Value:
  509. * This funtion returns one of the following values:
  510. *
  511. * SEB_BTN1 Button 1 was selected
  512. * SEB_BTN2 Button 2 was selected
  513. * SEB_BTN3 Button 3 was selected
  514. *
  515. *---------------------------------------------------------------------------
  516. */
  517. /* Maximum number of lines allowed in a system error box.
  518. */
  519. #define MAXSYSERRLINES 3
  520. /* Struct allocated on stack for max lines.
  521. */
  522. typedef struct tagSysErr
  523. {
  524. int iStart;
  525. int cch;
  526. int cxText;
  527. } SYSERRSTRUCT;
  528. int USERENTRY SysErrorBox(lpszText, lpszCaption, btn1, btn2, btn3)
  529. LPSTR lpszText;
  530. LPSTR lpszCaption;
  531. unsigned int btn1, btn2, btn3;
  532. {
  533. register int cx, cy;
  534. SYSERRSTRUCT sysErr[MAXSYSERRLINES];
  535. int temp;
  536. int cchCaption;
  537. int cxText, cxCaption, cxButtons;
  538. int cxCenter, cxQuarter;
  539. int cxBtn, cyBtn;
  540. int xBtn, yBtn;
  541. int iTextLines;
  542. HDC hdc;
  543. RECT rcBox, rcTemp;
  544. HRGN hrgn;
  545. int far *pbtn;
  546. int i;
  547. MSG msg;
  548. BOOL fBtnDown;
  549. BOOL fKeyBtnDown = FALSE;
  550. int BtnReturn;
  551. int btnhit;
  552. int defbtn;
  553. HWND hwndFocusSave;
  554. BOOL fMessageBoxGlobalOld = fMessageBox;
  555. BOOL fOldHWInput;
  556. HWND hwndSysModalBoxOld;
  557. LPSTR lptemp;
  558. RECT rcInvalidDesktop; /* Keep union of invalid desktop rects */
  559. /* We have to determine if we are running Win386 in PMODE
  560. * at the time of bringing up this SysErrBox. In this case we
  561. * have to call Win386 to Set the screen focus to us so that
  562. * the user can see the SYSMODAL error message that we display;
  563. * Fix for Bug #5272 --SANKAR-- 10-12-89
  564. */
  565. if ((WinFlags & WF_WIN386) && (WinFlags & WF_PMODE))
  566. GetbackFocusFromWinOldAp();
  567. /* Set this global so that we don't over write our globals when kernel calls
  568. * this routine directly. We need to save and restore the state of the
  569. * fMessageBox flag. If SysErrorBox is called via HardSysModal, then this
  570. * flag is set and we do proper processing in the message loop. However, if
  571. * Kernel calls syserrorbox directly, then this flag wasn't being set and we
  572. * could break...
  573. */
  574. fMessageBox = TRUE;
  575. /* Save off the guy who was the old sys modal dialog box in case the int24
  576. * box is put up when a sys modal box is up.
  577. */
  578. hwndSysModalBoxOld = hwndSysModal;
  579. /* Clear this global so that if the mouse is down on an NC area we don't
  580. * drop into the move/size code when we return. If we do, it thinks the
  581. * mouse is down when it really isn't
  582. */
  583. fInt24 = TRUE;
  584. /* Initialise the Global structure */
  585. LFillStruct((LPSTR)rgbtn, 3*sizeof(SEBBTN), '\0');
  586. /* Change the hq for the desktop to be the current task hq */
  587. if (NEEDSPAINT(hwndDesktop))
  588. DecPaintCount(hwndDesktop);
  589. hwndDesktop->hq = HqCurrent();
  590. if (NEEDSPAINT(hwndDesktop))
  591. IncPaintCount(hwndDesktop);
  592. hdc = GetScreenDC();
  593. /*
  594. * Calculate the extents of the error box. Then set the rectangle that
  595. * we will use for drawing.
  596. *
  597. * The x extent of the box is the maximin of the the folowing items:
  598. * - The text for the box (padded with 3 chars on each end).
  599. * - The caption for the box (also padded).
  600. * - 3 maximum sized buttons (szCANCEL).
  601. *
  602. * The y extent is 10 times the height of the system font.
  603. *
  604. */
  605. cy = cySysFontChar * 10;
  606. /* How many lines in the box text and their extents etc?
  607. */
  608. iTextLines = 0;
  609. sysErr[0].iStart = 0;
  610. sysErr[0].cch = 0;
  611. sysErr[0].cxText = 0;
  612. lptemp=lpszText;
  613. cxText = 0; /* Max text length
  614. */
  615. while (lptemp)
  616. {
  617. if (*lptemp == '\n' || *lptemp==0)
  618. {
  619. sysErr[iTextLines].cxText = LOWORD(GetTextExtent(hdc,
  620. (LPSTR)(lpszText+sysErr[iTextLines].iStart),
  621. sysErr[iTextLines].cch));
  622. /* Keep track of length of longest line
  623. */
  624. cxText = max(sysErr[iTextLines].cxText,cxText);
  625. if (*lptemp && *(lptemp+1)!=0 && iTextLines < MAXSYSERRLINES)
  626. {
  627. /* Another line exists
  628. */
  629. iTextLines++;
  630. sysErr[iTextLines].iStart = sysErr[iTextLines-1].iStart +
  631. sysErr[iTextLines-1].cch+1;
  632. sysErr[iTextLines].cch = 0;
  633. sysErr[iTextLines].cxText = 0;
  634. lptemp++;
  635. }
  636. else
  637. break;
  638. }
  639. else
  640. {
  641. sysErr[iTextLines].cch++;
  642. lptemp++;
  643. }
  644. }
  645. cx = cxText + (6 * cxSysFontChar);
  646. /* Get the extent of the box caption
  647. */
  648. cxCaption = LOWORD(GetTextExtent(hdc,
  649. (LPSTR)lpszCaption,
  650. (cchCaption = lstrlen(lpszCaption))));
  651. temp = cxCaption + (6 * cxSysFontChar);
  652. if (cx < temp)
  653. cx = temp;
  654. /* Get the extent of 3 maximum sized buttons */
  655. cxBtn = wMaxBtnSize + (cySysFontChar << 1);
  656. cxButtons = (cxBtn + (cySysFontChar << 2)) * 3;
  657. if (cx < cxButtons)
  658. cx = cxButtons;
  659. /* Center the box on the screen. Bound to left edge if too big. */
  660. rcBox.top = (cyScreen >> 1) - (cy >> 1);
  661. rcBox.bottom = rcBox.top + cy;
  662. rcBox.left = (cxScreen >> 1) - (cx >> 1);
  663. if (rcBox.left < 0)
  664. rcBox.left = 0;
  665. rcBox.right = rcBox.left + cx;
  666. cxCenter = (rcBox.left + rcBox.right) >> 1;
  667. PatBlt(hdc, rcBox.left, rcBox.top, cx, cy, WHITENESS);
  668. rcTemp = rcBox;
  669. DrawFrame(hdc, &rcTemp, 1, DF_WINDOWFRAME);
  670. InflateRect(&rcTemp, -(cxBorder * (CLDLGFRAMEWHITE + 1)),
  671. -(cyBorder * (CLDLGFRAMEWHITE + 1)));
  672. DrawFrame(hdc, &rcTemp, CLDLGFRAME, DF_ACTIVECAPTION);
  673. TextOut(hdc,
  674. cxCenter - (cxCaption >> 1),
  675. rcBox.top + cySysFontChar,
  676. (LPSTR)lpszCaption,
  677. cchCaption);
  678. i=0;
  679. /* First line of text starts at what y offset ?
  680. */
  681. if (iTextLines == 0)
  682. temp = (cySysFontChar << 2);
  683. else
  684. temp = (cySysFontChar << 1)+(cySysFontChar * (MAXSYSERRLINES-iTextLines));
  685. while (i<=iTextLines)
  686. {
  687. TextOut(hdc,
  688. /* cxCenter - (cxText >> 1),*/
  689. cxCenter - (sysErr[i].cxText >> 1),
  690. rcBox.top + temp+(i*cySysFontChar),
  691. (LPSTR)lpszText+sysErr[i].iStart,
  692. sysErr[i].cch);
  693. i++;
  694. }
  695. pbtn = &btn1;
  696. xBtn = (cxQuarter = cx >> 2) + rcBox.left;
  697. yBtn = rcBox.bottom - (cySysFontChar << 1);
  698. cyBtn = cySysFontChar << 1;
  699. for (i=0; i <= 2; i++, pbtn--)
  700. {
  701. SEB_InitBtnInfo(hdc, *pbtn, xBtn, yBtn, cxBtn, cyBtn, i);
  702. SEB_DrawButton(hdc, i);
  703. xBtn += cxQuarter;
  704. }
  705. Capture(hwndDesktop, CLIENT_CAPTURE);
  706. SetSysModalWindow(hwndDesktop);
  707. /*hCursOld =*/ SetCursor(hCursNormal);
  708. /* Why are we doing this???? This is causing us to hit the disk to load some
  709. * cursor resource during interrupt time... davidds
  710. */
  711. /* CallOEMCursor();*/
  712. hwndFocusSave = hwndFocus;
  713. hwndFocus = hwndDesktop;
  714. fBtnDown = FALSE;
  715. BtnReturn = 0;
  716. btnhit = -1; /* -1 if not on a button, else index into rgbtn[] */
  717. defbtn = -1;
  718. for (i = 0; i <= 2; i++)
  719. if (rgbtn[i].style & SEB_DEFBUTTON)
  720. {
  721. defbtn = i;
  722. break;
  723. }
  724. /* Prevent other tasks from running because this is SysModal */
  725. if (!fEndSession)
  726. LockMyTask(TRUE);
  727. /* Insure that hardware input is enabled */
  728. fOldHWInput = EnableHardwareInput(TRUE);
  729. /* Initially, only invalidate desktop where the sys error box was.
  730. */
  731. rcInvalidDesktop = rcBox;
  732. while (BtnReturn == 0)
  733. {
  734. if (!PeekMessage((LPMSG)&msg, hwndDesktop, 0, 0, PM_REMOVE | PM_NOYIELD))
  735. continue;
  736. #ifdef NEVER
  737. ********* TranslateMessage() calls ToAscii() which refers to some tables
  738. in a LoadOnCall segment; So, this is commented out here; We can not
  739. look for WM_CHAR messages, but we still get WM_KEYDOWN messages!
  740. --Sankar, April 17, 1989--
  741. TranslateMessage((LPMSG)&msg);
  742. *********
  743. #endif
  744. if (msg.hwnd == hwndDesktop)
  745. {
  746. switch (msg.message)
  747. {
  748. case WM_LBUTTONDOWN:
  749. fBtnDown = TRUE;
  750. if ((btnhit = SEB_BtnHit(LOWORD(msg.lParam),
  751. HIWORD(msg.lParam))) != -1)
  752. {
  753. /* Move the default button to the next button.
  754. */
  755. if ((defbtn != -1) && (btnhit != defbtn))
  756. {
  757. /* Draw the current def button as not default.
  758. */
  759. rgbtn[defbtn].style &= ~SEB_DEFBUTTON;
  760. SEB_DrawButton(hdc, defbtn);
  761. /* Draw the new button as default.
  762. */
  763. defbtn = btnhit;
  764. rgbtn[btnhit].style |= SEB_DEFBUTTON;
  765. }
  766. rgbtn[btnhit].finvert = TRUE;
  767. SEB_DrawButton(hdc, btnhit);
  768. }
  769. break;
  770. case WM_LBUTTONUP:
  771. fBtnDown = FALSE;
  772. /* Was the mouse hitting on a button? If so, terminate the
  773. * loop and return the button index.
  774. */
  775. if (btnhit != -1)
  776. BtnReturn = btnhit + 1;
  777. break;
  778. case WM_MOUSEMOVE:
  779. /* Only look at mouse moves if the button is down.
  780. */
  781. if (fBtnDown)
  782. {
  783. /* Hitting on a button?
  784. */
  785. if ((i = SEB_BtnHit(LOWORD(msg.lParam), HIWORD(msg.lParam))) != -1)
  786. {
  787. /* Mouse moved and we are on a button. First test
  788. * to see if we are on the same button as before.
  789. */
  790. if ((i != btnhit) && (btnhit != -1))
  791. {
  792. rgbtn[btnhit].finvert = FALSE;
  793. SEB_DrawButton(hdc, btnhit);
  794. }
  795. /* Verify that the new button is
  796. * inverted and that btnhit is current.
  797. */
  798. btnhit = i;
  799. if (rgbtn[btnhit].finvert == FALSE)
  800. {
  801. rgbtn[btnhit].finvert = TRUE;
  802. SEB_DrawButton(hdc, btnhit);
  803. }
  804. } else {
  805. /* button down, but not hitting on a button. Check
  806. * for drag off a button.
  807. */
  808. if (btnhit != -1)
  809. {
  810. rgbtn[btnhit].finvert = FALSE;
  811. SEB_DrawButton(hdc, btnhit);
  812. btnhit = -1;
  813. }
  814. }
  815. }
  816. break;
  817. case WM_KEYUP:
  818. if(fKeyBtnDown)
  819. {
  820. switch(msg.wParam)
  821. {
  822. case VERYBIGINTEGER:
  823. /* Because this code gets moved into himem, we can't use jump
  824. * tables; This VERYBIGINTEGER prevents C6.0 from using a jump
  825. * table in the translation of Switch Statements;
  826. */
  827. break;
  828. case VK_SPACE:
  829. case VK_RETURN:
  830. /* Select the current default button and return.
  831. */
  832. if (defbtn != -1)
  833. BtnReturn = defbtn + 1;
  834. break;
  835. }
  836. }
  837. break;
  838. case WM_PAINT:
  839. GetUpdateRect(msg.hwnd, &rcTemp, FALSE);
  840. ValidateRect(msg.hwnd, NULL);
  841. UnionRect(&rcInvalidDesktop, &rcInvalidDesktop, &rcTemp);
  842. break;
  843. case WM_SYSKEYDOWN:
  844. /* Look for accelerator keys
  845. */
  846. for (i = 0; i <= 2; i++)
  847. {
  848. /* Convert to lower case and test for a match */
  849. if (((BYTE)msg.wParam | 0x20) == rgbtn[i].chaccel)
  850. {
  851. BtnReturn = i + 1;
  852. break;
  853. }
  854. }
  855. break;
  856. case WM_KEYDOWN:
  857. switch (msg.wParam)
  858. {
  859. case VK_SPACE:
  860. case VK_RETURN:
  861. /* Just keep the button pressed */
  862. /* If already pressed, ignore the rest sothat we
  863. * won't flicker horribly
  864. */
  865. if((defbtn != -1) && (!fKeyBtnDown))
  866. {
  867. fKeyBtnDown = TRUE;
  868. rgbtn[defbtn].finvert = TRUE;
  869. SEB_DrawButton(hdc, defbtn);
  870. }
  871. break;
  872. case VK_TAB:
  873. /* Move the default button to the next button.
  874. */
  875. if (defbtn != -1)
  876. {
  877. /* Draw the current def button as not default.
  878. */
  879. rgbtn[defbtn].style &= ~SEB_DEFBUTTON;
  880. SEB_DrawButton(hdc, defbtn);
  881. /* Calc the next def button. Inc defbtn, but
  882. * wrap from btn 3 to btn 1. Also, don't stop
  883. * on a button that isn't defined.
  884. */
  885. if (defbtn == 2)
  886. defbtn = 0;
  887. else
  888. ++defbtn;
  889. while (rgbtn[defbtn].style == NULL)
  890. {
  891. if (++defbtn > 2)
  892. defbtn = 0;
  893. }
  894. /* Draw the new default button as default.
  895. */
  896. rgbtn[defbtn].style |= SEB_DEFBUTTON;
  897. SEB_DrawButton(hdc, defbtn);
  898. }
  899. break;
  900. case VK_ESCAPE:
  901. /* See if there is a button with SEB_CANCEL. If there
  902. * is, return it's id.
  903. */
  904. for (i = 0; i <= 2; i++)
  905. {
  906. if ((rgbtn[i].style & ~SEB_DEFBUTTON)
  907. == SEB_CANCEL)
  908. {
  909. BtnReturn = ++i;
  910. break;
  911. }
  912. }
  913. break;
  914. }
  915. break;
  916. }
  917. }
  918. }
  919. fMessageBox=fMessageBoxGlobalOld;
  920. /* Insure that hardware input is put back the way it was */
  921. EnableHardwareInput(fOldHWInput);
  922. /* Allow other tasks to run. */
  923. LockMyTask(FALSE);
  924. /* Set sys modal box back to the guy who was up */
  925. SetSysModalWindow(hwndSysModalBoxOld);
  926. Capture(NULL, NO_CAP_CLIENT);
  927. #if 0
  928. The old cursor may have been paged out. We can't do this.
  929. SetCursor(hCursOld);
  930. #endif
  931. #if causetrouble
  932. if (iLevelCursor < 0)
  933. OEMSetCursor((LPSTR)NULL);
  934. #endif
  935. hwndFocus = hwndFocusSave;
  936. /* Set this flag indicating that another window was activate so that if we
  937. * were in menu mode when the sys error box came up, we know we should get
  938. * out because the actual mouse button/keyboard state may be different than
  939. * what the menu state thinks it is.
  940. */
  941. fActivatedWindow = TRUE;
  942. InternalReleaseDC(hdc);
  943. /* Invalidate the invalid portions of the desktop.
  944. */
  945. InvalidateRect(hwndDesktop, &rcInvalidDesktop, FALSE);
  946. hrgn = CreateRectRgn(rcInvalidDesktop.left, rcInvalidDesktop.top,
  947. rcInvalidDesktop.right,rcInvalidDesktop.bottom);
  948. InternalInvalidate(hwndDesktop, (hrgn ? hrgn : (HRGN) 1),
  949. RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
  950. if (hrgn)
  951. DeleteObject(hrgn);
  952. // RedrawScreen();
  953. return(BtnReturn);
  954. }
  955. int NEAR PASCAL HardSysModalMessageBox(LPSTR lpszText,
  956. LPSTR lpszCaption,
  957. WORD wBtnCnt,
  958. WORD wType)
  959. {
  960. WORD wBegBtn;
  961. int iCurIndex;
  962. int iCurButton;
  963. WORD iButtonNo;
  964. int iRetVal;
  965. WORD wTemp;
  966. struct
  967. {
  968. unsigned int InVal;
  969. char RetVal;
  970. }Param[3];
  971. /* If we're trying to bring up a hard sys modal message box
  972. * while another one is up, wait till the first one is through.
  973. * This protects our static save globals. I'm not actually
  974. * sure this can ever happen (at least under DOS 3).
  975. */
  976. if (fMessageBox)
  977. Yield();
  978. fMessageBox = TRUE;
  979. wBegBtn = mpTypeIich[wType]; /* Index of Begining button */
  980. Param[0].InVal = Param[1].InVal = Param[2].InVal = 0;
  981. iCurIndex = 0;
  982. for(iButtonNo = 0; iButtonNo < wBtnCnt; iButtonNo++)
  983. {
  984. iCurButton = iCurIndex;
  985. switch(wBtnCnt)
  986. {
  987. case 1: /* One button; Put it in Param[1] */
  988. Param[1].InVal = SEBbuttons[wBegBtn];
  989. Param[1].RetVal = rgReturn[wBegBtn];
  990. iCurButton = 1;
  991. break;
  992. case 2: /* 2 Buttons; Put them in Param[0] and Param[2] */
  993. Param[iCurIndex].InVal = SEBbuttons[wTemp = wBegBtn + iButtonNo];
  994. Param[iCurIndex].RetVal = rgReturn[wTemp];
  995. iCurIndex += 2;
  996. break;
  997. case 3: /* 3 Buttons; Put them in Param[0], [1] and [2] */
  998. Param[iCurIndex].InVal = SEBbuttons[wTemp = wBegBtn + iButtonNo];
  999. Param[iCurIndex].RetVal = rgReturn[wTemp];
  1000. iCurIndex++;
  1001. break;
  1002. }
  1003. /* Check for the default button */
  1004. if(wDefButton == iButtonNo)
  1005. Param[iCurButton].InVal |= SEB_DEFBUTTON;
  1006. }
  1007. iRetVal = SysErrorBox(lpszText, lpszCaption, Param[0].InVal,
  1008. Param[1].InVal, Param[2].InVal);
  1009. fMessageBox = FALSE;
  1010. return((int)Param[iRetVal - SEB_BTN1].RetVal);
  1011. }
  1012. /*--------------------------------------------------------------------------*/
  1013. /* */
  1014. /* MessageBox() - */
  1015. /* */
  1016. /*--------------------------------------------------------------------------*/
  1017. int USERENTRY MessageBox(hwndOwner, lpszText, lpszCaption, wStyle)
  1018. HWND hwndOwner;
  1019. LPSTR lpszText;
  1020. LPSTR lpszCaption;
  1021. WORD wStyle;
  1022. {
  1023. WORD wBtnCnt;
  1024. WORD wType;
  1025. WORD wIcon;
  1026. #ifdef DEBUG
  1027. if (!GetTaskQueue(GetCurrentTask()))
  1028. {
  1029. /* There is no task queue. Not put up message boxes.
  1030. */
  1031. UserFatalExitSz(RIP_MESSAGEBOXWITHNOQUEUE,
  1032. "\n\rMessageBox failed - no message queue has been initialized yet. MessageBox not allowed.",
  1033. 0);
  1034. }
  1035. #endif
  1036. /* If lpszCaption is NULL, then use "Error!" string as the caption
  1037. string */
  1038. if(!lpszCaption)
  1039. lpszCaption = (LPSTR)szERROR;
  1040. wBtnCnt = mpTypeCcmd[(wType = wStyle & MB_TYPEMASK)];
  1041. /* Set the default button value */
  1042. wDefButton = (wStyle & MB_DEFMASK) / (MB_DEFMASK & (MB_DEFMASK >> 3));
  1043. if(wDefButton >= wBtnCnt) /* Check if valid */
  1044. wDefButton = 0; /* Set the first button if error */
  1045. /* Check if this is a hard sys modal message box */
  1046. wIcon = wStyle & MB_ICONMASK;
  1047. if(((wStyle & MB_MODEMASK) == MB_SYSTEMMODAL) &&
  1048. ((wIcon == NULL) || (wIcon == MB_ICONHAND)))
  1049. {
  1050. /* It is a hard sys modal message box */
  1051. return(HardSysModalMessageBox(lpszText, lpszCaption, wBtnCnt, wType));
  1052. }
  1053. else
  1054. return(SoftModalMessageBox(hwndOwner, lpszText, lpszCaption, wStyle));
  1055. }
  1056. BOOL FAR PASCAL IsSystemFont(hdc)
  1057. register HDC hdc;
  1058. /* effects: Returns TRUE if font selected into DC is the system font else
  1059. returns false. This is called by interrupt time code so it needs to be
  1060. in the fixed code segment. */
  1061. {
  1062. return(GetCurLogFont(hdc) == GetStockObject(SYSTEM_FONT));
  1063. }
  1064. BOOL FAR PASCAL IsSysFontAndDefaultMode(hdc)
  1065. register HDC hdc;
  1066. /* effects: Returns TRUE if font selected into DC is the system font AND
  1067. the current mapping mode of the DC is MM_TEXT (Default mode); else
  1068. returns false. This is called by interrupt time code so it needs to be
  1069. in the fixed code segment. */
  1070. /* This function is the fix for Bug #8717 --02-01-90-- SANKAR */
  1071. {
  1072. return(IsSystemFont(hdc) && (GetMapMode(hdc) == MM_TEXT));
  1073. }
  1074. int USERENTRY WEP(int i)
  1075. {
  1076. return(1);
  1077. }
  1078. #endif // WOW