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.

706 lines
26 KiB

  1. /*************************************************
  2. * movelst.c *
  3. * *
  4. * Copyright (C) 1995-1999 Microsoft Inc. *
  5. * *
  6. *************************************************/
  7. #include <windows.h> // required for all Windows applications
  8. #include <windowsx.h>
  9. #include <stdlib.h>
  10. #include <memory.h>
  11. #include <tchar.h>
  12. #include <htmlhelp.h>
  13. #include "rc.h"
  14. #include "movelst.h"
  15. #include "lctool.h"
  16. #define HELPNAME _TEXT("LCTOOL.CHM")
  17. //Bug #19911
  18. //#define SEQHELPKEY _TEXT("���ܦr������")
  19. #define ID_TIMER 100
  20. #define LINE_WIDTH 1
  21. // style flags for the DrawIndicator() function
  22. #define DI_TOPERASED 0x0001 // erasing a line drawn on the top of the list
  23. #define DI_BOTTOMERASED 0x0002 // erasing a line drawn on the bottom of the list
  24. #define DI_ERASEICON 0x0004 // erasing the icon
  25. static UINT idTimer; // the id for the timer used in scrolling the list
  26. static HFONT hFont; // a new font for the list box
  27. static HCURSOR hCurDrag; // a cursor to indicate dragging
  28. static int nHtItem; // the height of an individual item in the list box
  29. static BOOL bNoIntegralHeight; // does the list box have the LBS_NOINTEGRALHEIGHT style flag
  30. static HWND ghDlg; // handle to the main window
  31. static HWND ghList; // handle to the list box
  32. static HBRUSH ghBrush; // handle to the brush with the color of the windows background
  33. static UINT iCurrentAddr;
  34. void DrawIndicator(HDC hDC, int nYpos, int nWidth, WORD wFlags);
  35. WNDPROC lpfnOldListProc, LstProc;
  36. BOOL lcRemoveDup( TCHAR *szBuf );
  37. void lcOrgEditWindow();
  38. BOOL lcDisp2Seq(
  39. HWND hDlg,
  40. UINT iAddr,
  41. TCHAR *szDispBuf)
  42. {
  43. UINT i,j,len;
  44. #ifdef UNICODE
  45. TCHAR szPhrase[SEGMENT_SIZE * 2];
  46. #else
  47. UCHAR szPhrase[SEGMENT_SIZE * 2];
  48. #endif
  49. int nRet;
  50. // remove duplicate phrase
  51. if(lcRemoveDup(szDispBuf) && iAddr < MAX_LINE){
  52. SendMessage(hwndPhrase[iAddr],WM_SETTEXT,0,
  53. (LPARAM)(LPCTSTR)szDispBuf);
  54. }
  55. len=lstrlen(szDispBuf)+1;
  56. if((szDispBuf[len-1] == _TEXT(' ')) && (len > 1)) {
  57. szDispBuf[len-1]=0;
  58. len--;
  59. }
  60. if(len >= MAX_CHAR_NUM) { //tang must fix
  61. szDispBuf[MAX_CHAR_NUM-1]=0;
  62. #ifndef UNICODE
  63. if(is_DBCS_1st(szDispBuf, MAX_CHAR_NUM-2))
  64. szDispBuf[MAX_CHAR_NUM-2]=' ';
  65. #endif
  66. len=MAX_CHAR_NUM;
  67. }
  68. i = 0;
  69. j = 0;
  70. for(;;) {
  71. if (i == len - 1) {
  72. if (i - j + 1 > 0) {
  73. lstrcpyn(szPhrase, &szDispBuf[j], i - j + 1);
  74. SendDlgItemMessage(hDlg,IDD_SOURCELIST,
  75. LB_ADDSTRING,
  76. 0,
  77. (LPARAM)(LPSTR)szPhrase);
  78. }
  79. break;
  80. }
  81. if (szDispBuf[i] == ' ') {
  82. lstrcpyn(szPhrase, &szDispBuf[j], i - j + 1);
  83. nRet = (int)SendDlgItemMessage(hDlg,
  84. IDD_SOURCELIST,
  85. LB_ADDSTRING,
  86. 0,
  87. (LPARAM)(LPSTR)szPhrase);
  88. j = i + 1;
  89. }
  90. i++;
  91. }
  92. return TRUE;
  93. }
  94. BOOL lcSeq2Disp(
  95. HWND hDlg,
  96. UINT iAddr,
  97. TCHAR *szDispBuf)
  98. {
  99. WORD nCount;
  100. TCHAR szPhrase[SEGMENT_SIZE * 2];
  101. int nRet;
  102. WORD i;
  103. nCount = (int)SendDlgItemMessage(hDlg,IDD_SOURCELIST, LB_GETCOUNT,
  104. 0, 0);
  105. if (nCount == LB_ERR)
  106. return FALSE;
  107. *szDispBuf = 0;
  108. for(i = 0; i < nCount; i++) {
  109. nRet = (int)SendDlgItemMessage(hDlg,
  110. IDD_SOURCELIST,
  111. LB_GETTEXT,
  112. (WPARAM)i,
  113. (LPARAM)(LPSTR)szPhrase);
  114. if (nRet == LB_ERR)
  115. return FALSE;
  116. lstrcat(szDispBuf, szPhrase);
  117. lstrcat(szDispBuf, _TEXT(" "));
  118. }
  119. SendMessage(hwndPhrase[iAddr],WM_SETTEXT,0,
  120. (LPARAM)(LPCTSTR)szDispBuf);
  121. SendMessage(hwndPhrase[iAddr], EM_SETMODIFY, TRUE, 0);
  122. return TRUE;
  123. }
  124. void lcChangeSequence(
  125. HWND hwnd)
  126. {
  127. int is_OK;
  128. BOOL is_WORD;
  129. iCurrentAddr=lcGetEditFocus(GetFocus(), &is_WORD);
  130. is_OK=(INT)DialogBox(hInst,
  131. _TEXT("SEQDIALOG"),
  132. hwndMain,
  133. (DLGPROC)ActualDlgProc);
  134. if (is_WORD)
  135. SetFocus(hwndWord[iCurrentAddr]);
  136. else
  137. SetFocus(hwndPhrase[iCurrentAddr]);
  138. if (is_OK) {
  139. bSaveFile = TRUE;
  140. lcSaveEditText(iDisp_Top, 0);
  141. lcOrgEditWindow();
  142. }
  143. }
  144. LRESULT CALLBACK ClassDlgProc(HWND hDlg, UINT message, WPARAM wParam , LPARAM lParam)
  145. {
  146. return DefDlgProc(hDlg, message, wParam, lParam);
  147. }
  148. LRESULT CALLBACK ActualDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  149. {
  150. TCHAR szStr[MAX_CHAR_NUM];
  151. BOOL bRet;
  152. switch (message)
  153. {
  154. case WM_INITDIALOG:
  155. {
  156. LOGFONT lf;
  157. HMENU hSysMenu; // handle to the system menu
  158. HDC hdc; // a dc to find out the number of pixels per logcal inch
  159. LOGBRUSH lb;
  160. lb.lbStyle = BS_SOLID;
  161. lb.lbColor = GetSysColor(COLOR_WINDOW);
  162. lb.lbHatch = 0;
  163. ghBrush = CreateBrushIndirect(&lb);
  164. hSysMenu = GetSystemMenu(hDlg, FALSE);
  165. // disable the "maximize" option in the system menu
  166. EnableMenuItem(hSysMenu, 4, MF_GRAYED|MF_DISABLED|MF_BYPOSITION);
  167. // disable the "size" option of the system menu
  168. EnableMenuItem(hSysMenu, 2, MF_GRAYED|MF_DISABLED|MF_BYPOSITION);
  169. SendMessage(hwndPhrase[iCurrentAddr], WM_GETTEXT, MAX_CHAR_NUM-1, (LPARAM)szStr);
  170. lcDisp2Seq(hDlg, iCurrentAddr, szStr);
  171. ghList = GetDlgItem(hDlg, IDD_SOURCELIST);
  172. LstProc = MakeProcInstance(NewListProc,hInst);
  173. lpfnOldListProc = (WNDPROC)SetWindowLongPtr(ghList,
  174. GWLP_WNDPROC,
  175. (LONG_PTR)LstProc);
  176. // check to see if it has integral height
  177. bNoIntegralHeight = FALSE;
  178. hdc = GetDC(hDlg);
  179. memset(&lf, 0, sizeof(lf));
  180. lf.lfHeight = -MulDiv(9, 96, 72);
  181. lstrcpy(lf.lfFaceName, _TEXT("MS Sans Serif"));
  182. hFont = CreateFontIndirect(&lf);
  183. ReleaseDC(hDlg, hdc);
  184. SendMessage(ghList, WM_SETFONT, (WPARAM)hFont, (LPARAM)FALSE);
  185. // the drag cursor
  186. hCurDrag = LoadCursor(hInst, _TEXT("IDC_DRAG"));
  187. return FALSE; // didn't set the focus
  188. }
  189. break;
  190. case WM_COMMAND:
  191. switch (wParam)
  192. {
  193. case IDCANCEL:
  194. EndDialog(hDlg, FALSE);
  195. break;
  196. case IDOK:
  197. bRet = lcSeq2Disp(hDlg, iCurrentAddr, szStr);
  198. EndDialog(hDlg, bRet);
  199. break;
  200. case ID_HELP:
  201. LoadString(hInst, IDS_CHANGEWORDORDER, szStr, sizeof(szStr)/sizeof(TCHAR));
  202. // WinHelp(hDlg, HELPNAME, HELP_PARTIALKEY, (DWORD)szStr);
  203. HtmlHelp(hDlg, HELPNAME, HH_DISPLAY_TOPIC, 0L);
  204. break;
  205. }
  206. return TRUE;
  207. case WM_DESTROY: // clean up
  208. {
  209. DeleteObject(ghBrush);
  210. DeleteObject(hFont);
  211. DestroyCursor(hCurDrag);
  212. }
  213. break;
  214. default:
  215. return FALSE; // we didn't do anyting
  216. } // end switch message
  217. return TRUE; // we did the processing
  218. }
  219. LRESULT CALLBACK NewListProc(HWND hwndList,
  220. UINT message,
  221. WPARAM wParam,
  222. LPARAM lParam)
  223. {
  224. static BOOL bTracking = FALSE;
  225. static BOOL bDrag = FALSE;
  226. static HCURSOR hCursorOld = NULL;
  227. switch (message)
  228. {
  229. case WM_CANCELMODE:
  230. // WM_CANCELMODE is sent to the window that has captured the mouse before
  231. // a message box or modal dialog is displayed. If we were dragging the item
  232. // cancel the drag.
  233. bTracking = FALSE;
  234. ReleaseCapture();
  235. if (bDrag)
  236. SetCursor(hCursorOld);
  237. break;
  238. case WM_LBUTTONDOWN:
  239. {
  240. // Was the list box item dragged into the destination?
  241. BOOL bDragSuccess = FALSE;
  242. MSG msg;
  243. POINTS pts;
  244. POINTS points;
  245. POINT pt;
  246. POINT point;
  247. RECT rectIsDrag; // Rectangle to determine if dragging has started.
  248. int nOldPos;
  249. int nOldY = -1; // the last place that we drew on
  250. HDC hdc; // dc to draw on
  251. div_t divt; // get remainder a quotient with "div"
  252. int nCount;
  253. div_t divVis;
  254. // space for scroll bar - starts off at 1 so we don't overwrite the border
  255. int dxScroll = 1;
  256. RECT rect;
  257. int nVisible; // the number of items visible
  258. int idTimer; // id for the timer
  259. int nNewPos; // the new position
  260. int nTopIndex; // the top index
  261. GetWindowRect(hwndList, &rect);
  262. // Pass the WM_LBUTTONDOWN to the list box window procedure. Then
  263. // fake a WM_LBUTTONUP so that we can track the drag.
  264. CallWindowProc(lpfnOldListProc, hwndList, message, wParam, lParam);
  265. // the number of items in the list box
  266. nCount = (int)SendMessage(hwndList, LB_GETCOUNT,0,0L);
  267. if (nCount == 0 ) // don't do anything to and empty list box
  268. return 0;
  269. // fake the WM_LBUTTONUP
  270. CallWindowProc(lpfnOldListProc, hwndList, WM_LBUTTONUP, wParam, lParam);
  271. // get a dc to draw on
  272. hdc = GetDC(hwndList);
  273. // the height of each item
  274. nHtItem = (int)SendMessage(hwndList, LB_GETITEMHEIGHT,0,0L);
  275. // the current item
  276. nOldPos = (int)SendMessage(hwndList, LB_GETCURSEL,0,0L);
  277. divVis = div((rect.bottom - rect.top), nHtItem);
  278. // the number of visible items
  279. nVisible = divVis.quot;
  280. // some items are invisible - there must be scroll bars - we don't want
  281. // to draw on them
  282. if (nVisible < nCount)
  283. dxScroll = GetSystemMetrics(SM_CXVSCROLL) + 1;
  284. idTimer = 0;
  285. idTimer = (UINT)SetTimer(hwndList, ID_TIMER,100,NULL);
  286. // Create a tiny rectangle to determine if item was dragged or merely clicked on.
  287. // If the user moves outside this rectangle we assume that the dragging has
  288. // started.
  289. points = MAKEPOINTS(lParam);
  290. point.x = points.x; point.y = points.y;
  291. SetRect(&rectIsDrag, point.x, point.y - nHtItem / 2,
  292. point.x, point.y + nHtItem / 2);
  293. bTracking = TRUE;
  294. SetCapture(hwndList);
  295. // Drag loop
  296. while (bTracking)
  297. {
  298. // Retrieve mouse, keyboard, and timer messages. We retrieve keyboard
  299. // messages so that the system queue is not filled by keyboard messages
  300. // during the drag (This can happen if the user madly types while dragging!)
  301. // If none of these messages are available we wait. Both PeekMessage()
  302. // and Waitmessage() will yield to other apps.
  303. while (!PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)
  304. && !PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)
  305. && !PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE))
  306. WaitMessage();
  307. switch(msg.message)
  308. {
  309. case WM_MOUSEMOVE:
  310. {
  311. pts = MAKEPOINTS(msg.lParam);
  312. pt.x = pts.x; pt.y = pts.y;
  313. if (!bDrag)
  314. {
  315. // Check if the user has moved out of the Drag rect.
  316. // in the vertical direction. This indicates that
  317. // the drag has started.
  318. if ( (pt.y > rectIsDrag.bottom) ||
  319. (pt.y < rectIsDrag.top)) // !PtInRect(&rectIsDrag,pt))
  320. {
  321. hCursorOld = SetCursor(hCurDrag);
  322. bDrag = TRUE; // Drag has started
  323. }
  324. }
  325. if (bDrag)
  326. {
  327. SetCursor(hCurDrag);
  328. // if we are above or below the list box, then we are scrolling it, and
  329. // we shouldn't be drawing here
  330. ClientToScreen(hwndList, &pt);
  331. if ((pt.y >= rect.top) && (pt.y <= rect.bottom))
  332. {
  333. // convert the point back to client coordinates
  334. ScreenToClient(hwndList, &pt);
  335. divt = div(pt.y,nHtItem);
  336. // if we are half way to the item
  337. // AND it is a new item
  338. // AND we are not past the end of the list..
  339. if ( divt.rem < nHtItem / 2 &&
  340. (nOldY != nHtItem * divt.quot) &&
  341. (divt.quot < nCount + 1))
  342. {
  343. if (nOldY != -1)
  344. {
  345. // erase the old one
  346. DrawIndicator(hdc, nOldY,(rect.right - rect.left) - dxScroll, DI_ERASEICON);
  347. }
  348. nOldY = nHtItem * divt.quot;
  349. DrawIndicator(hdc, nOldY,(rect.right - rect.left) - dxScroll, 0);
  350. }
  351. } // end if in the list box window
  352. } // end if bDrag
  353. }
  354. break;
  355. case WM_TIMER:
  356. {
  357. POINT pt;
  358. GetCursorPos(&pt);
  359. nTopIndex = (int)SendMessage(hwndList, LB_GETTOPINDEX,0,0L);;
  360. if (pt.y < rect.top) // scroll up
  361. {
  362. if (nTopIndex > 0)
  363. {
  364. nTopIndex--;
  365. SendMessage(hwndList, LB_SETTOPINDEX, nTopIndex,0L);
  366. // when you scroll up, the line always stays on the top index
  367. // erase the one we've moved down
  368. DrawIndicator(hdc, nHtItem,(rect.right - rect.left) - dxScroll, DI_TOPERASED|DI_ERASEICON);
  369. // draw the new one
  370. DrawIndicator(hdc, 0,(rect.right - rect.left) - dxScroll, 0);
  371. // the new one was drawn at y = 0
  372. nOldY = 0;
  373. }
  374. }
  375. else if (pt.y > rect.bottom) // scroll down
  376. {
  377. // if the number of visible items (ie seen in the list box)
  378. // plus the number above the list is less than the total number
  379. // of items, then we need to scroll down
  380. if (nVisible + nTopIndex < nCount)
  381. {
  382. if (nOldY - nTopIndex != nVisible)
  383. {
  384. // if them move below the list REALLY REALLY FAST, then
  385. // the last line will not be on the bottom - so we want to reset the last
  386. // line to be the bottom
  387. // erase the old line
  388. DrawIndicator(hdc, nOldY,(rect.right - rect.left) - dxScroll, DI_ERASEICON);
  389. // reset the index
  390. divt.quot = nVisible;
  391. nOldY = divt.quot * nHtItem;
  392. // draw the new line
  393. DrawIndicator(hdc, nOldY,(rect.right - rect.left) - dxScroll, 0);
  394. }
  395. // scroll up
  396. nTopIndex++;
  397. SendMessage(hwndList, LB_SETTOPINDEX, nTopIndex,0L);
  398. // erase the line that has moved up..
  399. DrawIndicator(hdc, nOldY - nHtItem,(rect.right - rect.left) - dxScroll, DI_BOTTOMERASED|DI_ERASEICON);
  400. // draw the new one
  401. DrawIndicator(hdc, nOldY,(rect.right - rect.left) - dxScroll, 0);
  402. }
  403. }
  404. }
  405. break;
  406. case WM_LBUTTONUP:
  407. // End of Drag
  408. nTopIndex = (int)SendMessage(hwndList, LB_GETTOPINDEX, 0, 0L);
  409. if (bDrag)
  410. {
  411. // get rid of any line we've drawn - the position of the line
  412. // divided by the height of the itme is where our new index
  413. // is going to be
  414. DrawIndicator(hdc, nOldY,(rect.right - rect.left) - dxScroll, DI_ERASEICON);
  415. nNewPos = (nOldY / nHtItem) + nTopIndex;
  416. // the old position can't equal the new one
  417. if (nNewPos != nOldPos)
  418. bDragSuccess = TRUE;
  419. }
  420. bTracking = FALSE;
  421. break;
  422. default:
  423. // Process the keyboard messages
  424. TranslateMessage(&msg);
  425. DispatchMessage(&msg);
  426. break;
  427. }
  428. }// end while bTracking
  429. ReleaseCapture();
  430. if (bDrag)
  431. {
  432. SetCursor(hCursorOld);
  433. // move the item
  434. if (bDragSuccess)
  435. {
  436. int nIndex;
  437. char s[256];
  438. // we need to store the top index, because deleting and adding a new
  439. // string will change it, and we want to be able to see the item that
  440. // we have moved
  441. nTopIndex = (int)SendMessage(hwndList, LB_GETTOPINDEX,0,0L);
  442. // stop most of the blinking..
  443. SendMessage(hwndList, WM_SETREDRAW, FALSE,0L);
  444. // get the text of the item - limited to 256 chars!
  445. SendMessage(hwndList, LB_GETTEXT, nOldPos, (LPARAM)(LPSTR)s);
  446. /*------------------------------------------------------------------------
  447. | strategy: given ABCD and moving to BCAD do the following:
  448. |
  449. | 1. delete A -- giving BCD
  450. | 2. insert A -- giving BCAD
  451. | 3. hilite A
  452. | 4. set the top index so A is visible
  453. -------------------------------------------------------------------------*/
  454. // delete the original string
  455. SendMessage(hwndList, LB_DELETESTRING, nOldPos, 0L);
  456. // if we've moved DOWN the list subtract one from the new index
  457. // (because we've deleted a string but if we are moving UP the list,
  458. // we don't subtract anything (the deleted item is below the new item,
  459. // so our new index hasn't changed
  460. if (nNewPos > nOldPos)
  461. nNewPos--;
  462. // put it in the new pos
  463. nIndex = (int)SendMessage(hwndList,
  464. LB_INSERTSTRING,
  465. nNewPos,
  466. (LPARAM)(LPSTR)s);
  467. SendMessage(hwndList, LB_SETCURSEL, nIndex, 0L);
  468. SendMessage(hwndList, LB_SETTOPINDEX, nTopIndex,0L);
  469. SendMessage(hwndList, WM_SETREDRAW, TRUE,0L);
  470. } // end if bDragSuccess
  471. } // end if bDrag
  472. bDrag = FALSE;
  473. ReleaseDC(hwndList, hdc);
  474. KillTimer(hwndList, idTimer);
  475. }
  476. break;
  477. default:
  478. return CallWindowProc(lpfnOldListProc, hwndList, message, wParam, lParam);
  479. }
  480. return 0;
  481. }
  482. LRESULT CALLBACK AboutDlgProc (HWND hDlg, UINT message,
  483. WPARAM wParam, LPARAM lParam)
  484. {
  485. switch (message)
  486. {
  487. case WM_INITDIALOG:
  488. return (TRUE);
  489. case WM_COMMAND:
  490. if (wParam == IDOK)
  491. {
  492. EndDialog(hDlg, TRUE);
  493. return (TRUE);
  494. }
  495. break;
  496. }
  497. return (FALSE);
  498. }
  499. void DrawIndicator(HDC hDC, int nYpos, int nWidth, WORD wFlags)
  500. {
  501. // draw a horizontal line
  502. int nTop, nHeight;
  503. HICON hIcon;
  504. HRGN hClipRgn; // the clipping region
  505. RECT rect;
  506. // we don't want the clip anything when we are drawing
  507. // the icon outside the list box
  508. SelectClipRgn(hDC, NULL);
  509. if (wFlags & DI_ERASEICON)
  510. {
  511. rect.left = -33;
  512. rect.right = -1;
  513. rect.top = nYpos -16;
  514. rect.bottom = nYpos + 16;
  515. // ghBrush is created in WM_INITDIALOG
  516. FillRect(hDC, &rect, ghBrush);
  517. }
  518. else
  519. {
  520. hIcon = LoadIcon(hInst, _TEXT("IDI_ARROW"));
  521. if (hIcon)
  522. {
  523. DrawIcon(hDC,-33,nYpos - 16,hIcon);
  524. DestroyIcon(hIcon);
  525. }
  526. }
  527. // create a clipping region for drawing the lines in the list box
  528. GetWindowRect(ghList, &rect);
  529. hClipRgn = CreateRectRgn(0,0, rect.right - rect.left, rect.bottom - rect.top);
  530. if ( hClipRgn )
  531. {
  532. SelectClipRgn(hDC, hClipRgn);
  533. // we can delete it emmdiately because SelectClipRgn makes a COPY of the region
  534. DeleteObject(hClipRgn);
  535. }
  536. /****************************************************
  537. erasing something drawn on top
  538. the top is drawn like
  539. ______ |_____|
  540. | | instead of | |
  541. so we want to NOT draw the two vertical lines
  542. above the horzontal
  543. *****************************************************/
  544. // if (nYpos = 0) wFlags |= DI_TOPERASED;
  545. if (wFlags & DI_TOPERASED)
  546. {
  547. nTop = nYpos;
  548. nHeight = nHtItem / 4;
  549. }
  550. /****************************************************
  551. erasing something originally drawn on the bottom
  552. if the list box is NOT LBS_NOINTEGRALHEIGHT, then
  553. the botton line will be on the border of the list
  554. box, so we don't want to draw the horizontal line at
  555. all, ie we draw
  556. | | |_____|
  557. instead of | |
  558. *****************************************************/
  559. else if (wFlags & DI_BOTTOMERASED && !bNoIntegralHeight)
  560. {
  561. nTop = nYpos - nHtItem / 4;
  562. nHeight = nHtItem / 4;
  563. }
  564. else
  565. {
  566. nTop = nYpos - nHtItem / 4;
  567. nHeight = nHtItem / 2;
  568. }
  569. if (!(wFlags & DI_BOTTOMERASED && !bNoIntegralHeight)) // see above comment
  570. {
  571. PatBlt(hDC,
  572. LINE_WIDTH,
  573. nYpos,
  574. nWidth - 2 * LINE_WIDTH,
  575. LINE_WIDTH,
  576. PATINVERT);
  577. }
  578. PatBlt(hDC,
  579. 0,
  580. nTop,
  581. LINE_WIDTH,
  582. nHeight ,
  583. PATINVERT);
  584. PatBlt(hDC,
  585. nWidth - LINE_WIDTH,
  586. nTop,
  587. LINE_WIDTH,
  588. nHeight,
  589. PATINVERT);
  590. }