Windows NT 4.0 source code leak
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.

841 lines
24 KiB

4 years ago
  1. /*
  2. * status line handler
  3. *
  4. */
  5. /*---includes-----------------------------------------------------------*/
  6. #include "windows.h"
  7. #include "string.h"
  8. #include "gutils.h"
  9. /* --- data structures ------------------------------------------------- */
  10. #define SF_MAXLABEL 80 /* no more than 80 in an item within the bar */
  11. /* Is this adequate for long pathnames on a
  12. hi-res screen?
  13. */
  14. typedef struct statel {
  15. int type; /* SF_BUTTON or SF_STATIC */
  16. int flags; /* SF_VAR => variable width
  17. SF_LEFT=> left aligned (else right)
  18. SF_RAISE=> paint as 'raised' 3d rect
  19. SF_LOWER=> paint as lowered 3D rect
  20. SF_SZMIN=>together with SF_VAR
  21. allows minimum size for
  22. var sized item
  23. SF_SZMAX=>see SZMIN and use nouse
  24. */
  25. int id; /* control id */
  26. int width; /* width of control in chars */
  27. char text[SF_MAXLABEL+1]; /* null-term string for label */
  28. RECT rc; /* used by status.c */
  29. } STATEL, FAR * PSTATEL;
  30. typedef struct itemlist {
  31. int nitems;
  32. PSTATEL statels;
  33. int selitem; /* used by status.c */
  34. BOOL isselected; /* used by status.c */
  35. } ILIST, FAR * PILIST;
  36. /* ------------------------------------------------------------------*/
  37. /* prototypes of routines in this module */
  38. void StatusCreateTools(void);
  39. void StatusDeleteTools(void);
  40. long APIENTRY StatusWndProc(HWND, UINT, UINT, LONG);
  41. void StatusResize(HWND hWnd, PILIST pilist);
  42. int StatusCalcHeight(HWND hWnd, PSTATEL ip);
  43. int StatusCalcWidth(HWND hWnd, PSTATEL ip);
  44. PSTATEL StatusGetItem(PILIST plist, int id);
  45. void LowerRect(HDC hDC, LPRECT rcp);
  46. void RaiseRect(HDC hDC, LPRECT rcp);
  47. void StatusPaint(HWND hWnd, PILIST iplistp);
  48. void BottomRight(HDC hDC, LPRECT rcp, HPEN hpen, BOOL bCorners);
  49. void TopLeft(HDC hDC, LPRECT rcp, HPEN hpen, BOOL bCorners);
  50. void StatusButtonDown(HDC hDC, PSTATEL ip);
  51. void StatusButtonUp(HDC hDC, PSTATEL ip);
  52. void InitDC(HDC hdc);
  53. #ifdef WIN32
  54. #define _fstrncpy strncpy
  55. #endif
  56. /*--global data---------------------------------------------------------*/
  57. HPEN hpenHilight, hpenLowlight;
  58. HPEN hpenBlack, hpenNeutral;
  59. HBRUSH hbrBackground; /* pieces and board */
  60. HFONT hFont;
  61. int status_charheight, status_charwidth;
  62. /* default pt size for font (tenths of a pt) */
  63. #define DEF_PTSIZE 80
  64. /*-public functions----------------------------------------------------------*/
  65. /* StatusInit
  66. *
  67. * - create window class
  68. */
  69. BOOL
  70. StatusInit(HANDLE hInstance)
  71. {
  72. WNDCLASS wc;
  73. BOOL resp;
  74. TEXTMETRIC tm;
  75. HDC hDC;
  76. StatusCreateTools();
  77. wc.style = CS_HREDRAW|CS_VREDRAW|CS_GLOBALCLASS;
  78. wc.lpfnWndProc = (WNDPROC) StatusWndProc;
  79. wc.cbClsExtra = 0;
  80. wc.cbWndExtra = sizeof(HANDLE);
  81. wc.hInstance = hInstance;
  82. wc.hIcon = NULL;
  83. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  84. wc.hbrBackground = hbrBackground;
  85. wc.lpszClassName = (LPSTR) "gdstatusclass";
  86. wc.lpszMenuName = NULL;
  87. resp = RegisterClass(&wc);
  88. hDC = GetDC(NULL);
  89. InitDC(hDC);
  90. GetTextMetrics(hDC, &tm);
  91. status_charheight = (int)(tm.tmHeight + tm.tmExternalLeading);
  92. status_charwidth = (int)tm.tmAveCharWidth;
  93. ReleaseDC(NULL, hDC);
  94. return(resp);
  95. }
  96. /*
  97. * create and show the window
  98. */
  99. HWND APIENTRY
  100. StatusCreate(HANDLE hInst, HWND hParent, int id, LPRECT rcp, HANDLE hmem)
  101. {
  102. HWND hWnd;
  103. /* create a child window of status class */
  104. hWnd = CreateWindow("gdstatusclass",
  105. NULL,
  106. WS_CHILD | WS_VISIBLE,
  107. rcp->left,
  108. rcp->top,
  109. (rcp->right - rcp->left),
  110. (rcp->bottom - rcp->top),
  111. hParent,
  112. (HANDLE) id,
  113. hInst,
  114. (LPVOID) hmem);
  115. return(hWnd);
  116. }
  117. /* return default height of this window */
  118. int APIENTRY
  119. StatusHeight(HANDLE hmem)
  120. /* The window has a number of items which are arranged horizontally,
  121. so the window height is the maximum of the individual heights
  122. */
  123. {
  124. PILIST plist;
  125. int i;
  126. int sz;
  127. int maxsize = 0;
  128. plist = (PILIST) GlobalLock(hmem);
  129. if (plist != NULL) {
  130. for (i = 0; i<plist->nitems; i++) {
  131. sz = StatusCalcHeight(NULL, &plist->statels[i]);
  132. maxsize = max(sz, maxsize);
  133. }
  134. }
  135. GlobalUnlock(hmem);
  136. if (maxsize > 0) {
  137. return(maxsize + 4);
  138. } else {
  139. return(status_charheight + 4);
  140. }
  141. }
  142. /* alloc the plist struct and return handle to caller */
  143. HANDLE FAR PASCAL
  144. StatusAlloc(int nitems)
  145. {
  146. HANDLE hmem;
  147. PILIST pilist;
  148. LPSTR chp;
  149. hmem = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,
  150. sizeof(ILIST) + (sizeof(STATEL) * nitems));
  151. chp = GlobalLock(hmem);
  152. if (chp == NULL) {
  153. return(NULL);
  154. }
  155. pilist = (PILIST) chp;
  156. pilist->nitems = nitems;
  157. pilist->statels = (PSTATEL) &chp[sizeof(ILIST)];
  158. GlobalUnlock(hmem);
  159. return(hmem);
  160. }
  161. /* insert an item into the plist */
  162. BOOL FAR PASCAL
  163. StatusAddItem(HANDLE hmem, int itemnr, int type, int flags, int id,
  164. int width, LPSTR text)
  165. {
  166. PILIST pilist;
  167. PSTATEL pel;
  168. pilist = (PILIST) GlobalLock(hmem);
  169. if ((pilist == NULL) || (itemnr >= pilist->nitems)) {
  170. GlobalUnlock(hmem);
  171. return(FALSE);
  172. }
  173. pel = &pilist->statels[itemnr];
  174. pel->type = type;
  175. pel->flags = flags;
  176. pel->id = id;
  177. pel->width = width;
  178. if (text == NULL) {
  179. pel->text[0] = '\0';
  180. } else {
  181. lstrcpy(pel->text, text);
  182. }
  183. GlobalUnlock(hmem);
  184. return(TRUE);
  185. }
  186. /* ---- internal functions ------------------------------------------*/
  187. void
  188. InitDC(HDC hdc)
  189. {
  190. SetBkColor(hdc, RGB(192,192,192));
  191. SelectObject(hdc, hbrBackground);
  192. SelectObject(hdc, hFont);
  193. }
  194. void
  195. StatusCreateTools()
  196. {
  197. LOGFONT lf;
  198. HDC hdc;
  199. int scale;
  200. hbrBackground = CreateSolidBrush(RGB(192,192,192));
  201. hpenHilight = CreatePen(0, 1, RGB(255, 255, 255));
  202. hpenLowlight = CreatePen(0, 1, RGB(128, 128, 128));
  203. hpenNeutral = CreatePen(0, 1, RGB(192, 192, 192));
  204. hpenBlack = CreatePen(0, 1, RGB(0, 0, 0));
  205. hdc = GetDC(NULL);
  206. scale = GetDeviceCaps(hdc, LOGPIXELSY);
  207. ReleaseDC(NULL, hdc);
  208. lf.lfHeight = -MulDiv(DEF_PTSIZE, scale, 720);
  209. lf.lfWidth = 0;
  210. lf.lfEscapement = 0;
  211. lf.lfOrientation = 0;
  212. lf.lfWeight = FW_REGULAR;
  213. lf.lfItalic = 0;
  214. lf.lfUnderline = 0;
  215. lf.lfStrikeOut = 0;
  216. lf.lfCharSet = ANSI_CHARSET;
  217. lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  218. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  219. lf.lfQuality = PROOF_QUALITY;
  220. lf.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
  221. lf.lfFaceName[0] = '\0';
  222. #ifdef COMPLEX
  223. hFont = CreateFontIndirect(&lf);
  224. #else
  225. hFont = GetStockObject(SYSTEM_FONT);
  226. #endif
  227. }
  228. void
  229. StatusDeleteTools()
  230. {
  231. DeleteObject(hbrBackground);
  232. DeleteObject(hpenHilight);
  233. DeleteObject(hpenLowlight);
  234. DeleteObject(hpenBlack);
  235. DeleteObject(hpenNeutral);
  236. #ifdef COMPLEX
  237. DeleteObject(hFont);
  238. #endif
  239. }
  240. /* Main winproc for status windows
  241. *
  242. * handles create/destroy and paint requests
  243. */
  244. long FAR PASCAL
  245. StatusWndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam)
  246. {
  247. HANDLE hitems;
  248. PSTATEL ip;
  249. PILIST plist;
  250. CREATESTRUCT FAR * cp;
  251. int i;
  252. HDC hDC;
  253. RECT rc;
  254. POINT pt;
  255. switch(message) {
  256. case WM_CREATE:
  257. cp = (CREATESTRUCT FAR *) lParam;
  258. hitems = (HANDLE) (LONG) cp->lpCreateParams;
  259. SetWindowHandle(hWnd, 0, hitems);
  260. plist = (PILIST) GlobalLock(hitems);
  261. if (plist != NULL) {
  262. plist->selitem = -1;
  263. GlobalUnlock(hitems);
  264. }
  265. break;
  266. case WM_SIZE:
  267. hitems = (HANDLE) GetWindowHandle(hWnd, 0);
  268. plist = (PILIST) GlobalLock(hitems);
  269. if (plist != NULL) {
  270. StatusResize(hWnd, plist);
  271. GlobalUnlock(hitems);
  272. }
  273. break;
  274. case WM_PAINT:
  275. hitems = (HANDLE) GetWindowHandle(hWnd, 0);
  276. plist = (PILIST) GlobalLock(hitems);
  277. StatusPaint(hWnd, plist);
  278. GlobalUnlock(hitems);
  279. break;
  280. case WM_LBUTTONUP:
  281. hitems = (HANDLE) GetWindowHandle(hWnd, 0);
  282. plist = (PILIST) GlobalLock(hitems);
  283. pt.x = LOWORD(lParam);
  284. pt.y = HIWORD(lParam);
  285. if (plist == NULL) {
  286. break;
  287. }
  288. if (plist->selitem != -1) {
  289. ip = &plist->statels[plist->selitem];
  290. if (plist->isselected) {
  291. hDC = GetDC(hWnd);
  292. InitDC(hDC);
  293. StatusButtonUp(hDC, ip);
  294. ReleaseDC(hWnd, hDC);
  295. }
  296. plist->selitem = -1;
  297. ReleaseCapture();
  298. if (PtInRect(&ip->rc, pt)) {
  299. #ifdef WIN32
  300. SendMessage(GetParent(hWnd), WM_COMMAND,
  301. MAKELONG(ip->id, WM_LBUTTONUP), (LONG)hWnd);
  302. #else
  303. SendMessage(GetParent(hWnd), WM_COMMAND,
  304. ip->id, MAKELONG(hWnd, WM_LBUTTONUP));
  305. #endif
  306. }
  307. }
  308. GlobalUnlock(hitems);
  309. break;
  310. case WM_LBUTTONDOWN:
  311. hitems = (HANDLE) GetWindowHandle(hWnd, 0);
  312. plist = (PILIST) GlobalLock(hitems);
  313. if (plist == NULL) {
  314. break;
  315. }
  316. pt.x = LOWORD(lParam);
  317. pt.y = HIWORD(lParam);
  318. if (plist->selitem == -1) {
  319. for (i = 0; i< plist->nitems; i++) {
  320. ip = &plist->statels[i];
  321. if (PtInRect(&ip->rc, pt)) {
  322. if (ip->type != SF_BUTTON) {
  323. break;
  324. }
  325. plist->selitem = i;
  326. SetCapture(hWnd);
  327. plist->isselected = TRUE;
  328. hDC = GetDC(hWnd);
  329. InitDC(hDC);
  330. StatusButtonDown(hDC, ip);
  331. ReleaseDC(hWnd, hDC);
  332. break;
  333. }
  334. }
  335. }
  336. GlobalUnlock(hitems);
  337. break;
  338. case WM_MOUSEMOVE:
  339. hitems = (HANDLE) GetWindowHandle(hWnd, 0);
  340. plist = (PILIST) GlobalLock(hitems);
  341. if (plist == NULL) {
  342. break;
  343. }
  344. pt.x = LOWORD(lParam);
  345. pt.y = HIWORD(lParam);
  346. if (plist->selitem != -1) {
  347. ip = &plist->statels[plist->selitem];
  348. if (PtInRect(&ip->rc, pt)) {
  349. if (!plist->isselected) {
  350. hDC = GetDC(hWnd);
  351. InitDC(hDC);
  352. StatusButtonDown(hDC, ip);
  353. ReleaseDC(hWnd, hDC);
  354. plist->isselected = TRUE;
  355. }
  356. } else {
  357. if(plist->isselected) {
  358. hDC = GetDC(hWnd);
  359. InitDC(hDC);
  360. StatusButtonUp(hDC, ip);
  361. ReleaseDC(hWnd, hDC);
  362. plist->isselected = FALSE;
  363. }
  364. }
  365. }
  366. GlobalUnlock(hitems);
  367. break;
  368. case WM_DESTROY:
  369. hitems = (HANDLE) GetWindowHandle(hWnd, 0);
  370. GlobalUnlock(hitems);
  371. GlobalFree(hitems);
  372. SetWindowHandle(hWnd, 0, NULL);
  373. break;
  374. case SM_NEW:
  375. hitems = (HANDLE) GetWindowHandle(hWnd, 0);
  376. if (hitems != NULL) {
  377. GlobalFree(hitems);
  378. }
  379. hitems = (HANDLE) wParam;
  380. if (hitems == NULL) {
  381. SetWindowHandle(hWnd, 0, NULL);
  382. InvalidateRect(hWnd, NULL, TRUE);
  383. break;
  384. }
  385. plist = (PILIST) GlobalLock(hitems);
  386. if (plist == NULL) {
  387. SetWindowHandle(hWnd, 0, NULL);
  388. InvalidateRect(hWnd, NULL, TRUE);
  389. break;
  390. }
  391. plist->selitem = -1;
  392. StatusResize(hWnd, plist);
  393. GlobalUnlock(hitems);
  394. SetWindowHandle(hWnd, 0, hitems);
  395. InvalidateRect(hWnd, NULL, TRUE);
  396. break;
  397. case SM_SETTEXT:
  398. hitems = (HANDLE) GetWindowHandle(hWnd, 0);
  399. if (hitems == NULL) {
  400. break;
  401. }
  402. plist = (PILIST) GlobalLock(hitems);
  403. ip = StatusGetItem(plist, wParam);
  404. if (ip != NULL) {
  405. if (lParam == 0) {
  406. ip->text[0] = '\0';
  407. } else {
  408. _fstrncpy(ip->text, (LPSTR) lParam, SF_MAXLABEL);
  409. ip->text[SF_MAXLABEL] = '\0';
  410. }
  411. /* if this is a variable width field, we need to redo
  412. * all size calcs in case the field width has changed.
  413. * in that case, we need to repaint the entire window
  414. * and not just this field - so set rc to indicate the
  415. * area to be redrawn.
  416. */
  417. if (ip->flags & SF_VAR) {
  418. StatusResize(hWnd, plist);
  419. GetClientRect(hWnd, &rc);
  420. RedrawWindow(hWnd, &rc, NULL,
  421. RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW);
  422. } else {
  423. /* instead of just invalidating the window, we can
  424. * force the window to be repainted now. This is
  425. * essential for status updates during a busy
  426. * loop when no messages are being processed,
  427. * but we should still update the user on what's
  428. * happening.
  429. */
  430. RedrawWindow(hWnd, &ip->rc, NULL,
  431. RDW_INVALIDATE|RDW_NOERASE|RDW_UPDATENOW);
  432. }
  433. }
  434. GlobalUnlock(hitems);
  435. break;
  436. default:
  437. return(DefWindowProc(hWnd, message, wParam, lParam));
  438. }
  439. return 0;
  440. }
  441. /*
  442. * position the labels and buttons within the status window */
  443. void
  444. StatusResize(HWND hWnd, PILIST iplistp)
  445. {
  446. RECT rc;
  447. int curpos_right, curpos_left;
  448. int height, width;
  449. int i;
  450. PSTATEL ip;
  451. if (iplistp == NULL) {
  452. return;
  453. }
  454. GetClientRect(hWnd, &rc);
  455. curpos_left = rc.left + status_charwidth / 2;
  456. curpos_right = rc.right - (status_charwidth / 2);
  457. /* loop through all items setting their position rects.
  458. * items are flagged as being left or right. We place them
  459. * in order starting at the left and the right, with a single
  460. * char's width between each item
  461. */
  462. for (i = 0; i < iplistp->nitems; i++) {
  463. ip = &iplistp->statels[i];
  464. width = StatusCalcWidth(hWnd, ip);
  465. height = StatusCalcHeight(hWnd, ip);
  466. ip->rc.top = (rc.bottom - height) / 2;
  467. ip->rc.bottom = ip->rc.top + height;
  468. /* see if this item fits. Items that partially fit
  469. * are placed reduced in size.
  470. */
  471. if (ip->flags & SF_LEFT) {
  472. if (curpos_left+width >= curpos_right) {
  473. /* doesn't completely fit-does it partly? */
  474. if ((curpos_left + 1) >= curpos_right){
  475. /* no - this item does not fit */
  476. ip->rc.left = 0;
  477. ip->rc.right = 0;
  478. } else {
  479. /* partial fit */
  480. ip->rc.left = curpos_left;
  481. ip->rc.right = curpos_right - 1;
  482. curpos_left = curpos_right;
  483. }
  484. } else {
  485. /* complete fit */
  486. ip->rc.left = curpos_left;
  487. ip->rc.right = curpos_left + width;
  488. curpos_left += width + 1;
  489. }
  490. } else {
  491. /* same size check for right-aligned items */
  492. if (curpos_right-width <= curpos_left) {
  493. /* partial fit ? */
  494. if (curpos_right <= curpos_left+1) {
  495. ip->rc.left = 0;
  496. ip->rc.right = 0;
  497. } else {
  498. /* yes - partial fit */
  499. ip->rc.left = curpos_left + 1;
  500. ip->rc.right = curpos_right;
  501. curpos_right = curpos_left;
  502. }
  503. } else {
  504. /* complete fit */
  505. ip->rc.right = curpos_right;
  506. ip->rc.left = curpos_right - width;
  507. curpos_right -= (width + 1);
  508. }
  509. }
  510. }
  511. }
  512. void
  513. StatusPaint(HWND hWnd, PILIST iplistp)
  514. {
  515. RECT rc;
  516. HDC hDC;
  517. PAINTSTRUCT ps;
  518. int i;
  519. PSTATEL ip;
  520. HPEN hpenOld;
  521. GetClientRect(hWnd, &rc);
  522. hDC = BeginPaint(hWnd, &ps);
  523. InitDC(hDC);
  524. RaiseRect(hDC, &rc);
  525. if (iplistp == NULL) {
  526. EndPaint(hWnd, &ps);
  527. return;
  528. }
  529. for (i =0; i < iplistp->nitems; i++) {
  530. ip = &iplistp->statels[i];
  531. if (ip->rc.left == ip->rc.right) {
  532. continue;
  533. }
  534. if (ip->type == SF_STATIC) {
  535. if (ip->flags & SF_RAISE) {
  536. RaiseRect(hDC, &ip->rc);
  537. } else if (ip->flags & SF_LOWER) {
  538. LowerRect(hDC, &ip->rc);
  539. }
  540. rc = ip->rc;
  541. rc.left += (status_charwidth / 2);
  542. rc.right--;
  543. rc.top++;
  544. rc.bottom--;
  545. hpenOld = SelectObject(hDC, hpenNeutral);
  546. Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
  547. SelectObject(hDC, hpenOld);
  548. DrawText(hDC, ip->text, lstrlen(ip->text), &rc,
  549. DT_LEFT | DT_VCENTER);
  550. } else {
  551. StatusButtonUp(hDC, ip);
  552. }
  553. }
  554. EndPaint(hWnd, &ps);
  555. }
  556. void
  557. RaiseRect(HDC hDC, LPRECT rcp)
  558. {
  559. TopLeft(hDC, rcp, hpenHilight, FALSE);
  560. BottomRight(hDC, rcp, hpenLowlight, FALSE);
  561. }
  562. void
  563. LowerRect(HDC hDC, LPRECT rcp)
  564. {
  565. TopLeft(hDC, rcp, hpenLowlight, FALSE);
  566. BottomRight(hDC, rcp, hpenHilight, FALSE);
  567. }
  568. void
  569. StatusButtonUp(HDC hDC, PSTATEL ip)
  570. {
  571. RECT rc;
  572. HPEN hpenOld;
  573. rc = ip->rc;
  574. TopLeft(hDC, &rc, hpenBlack, TRUE);
  575. BottomRight(hDC, &rc, hpenBlack, FALSE);
  576. rc.top++;
  577. rc.bottom--;
  578. rc.left++;
  579. rc.right--;
  580. TopLeft(hDC, &rc, hpenHilight, FALSE);
  581. BottomRight(hDC, &rc, hpenLowlight, TRUE);
  582. rc.top++;
  583. rc.bottom--;
  584. rc.left++;
  585. rc.right--;
  586. BottomRight(hDC, &rc, hpenLowlight, TRUE);
  587. rc.bottom--;
  588. rc.right--;
  589. hpenOld = SelectObject(hDC, hpenNeutral);
  590. Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
  591. SelectObject(hDC, hpenOld);
  592. DrawText(hDC, ip->text, lstrlen(ip->text), &rc, DT_CENTER | DT_VCENTER);
  593. }
  594. void
  595. StatusButtonDown(HDC hDC, PSTATEL ip)
  596. {
  597. RECT rc;
  598. HPEN hpenOld;
  599. rc = ip->rc;
  600. TopLeft(hDC, &rc, hpenBlack, TRUE);
  601. BottomRight(hDC, &rc, hpenBlack, FALSE);
  602. rc.top++;
  603. rc.bottom--;
  604. rc.left++;
  605. rc.right--;
  606. TopLeft(hDC, &rc, hpenLowlight, TRUE);
  607. rc.top++;
  608. rc.left++;
  609. TopLeft(hDC, &rc, hpenNeutral, TRUE);
  610. rc.top++;
  611. rc.left++;
  612. TopLeft(hDC, &rc, hpenNeutral, TRUE);
  613. rc.top++;
  614. rc.left++;
  615. hpenOld = SelectObject(hDC, hpenNeutral);
  616. Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
  617. SelectObject(hDC, hpenOld);
  618. DrawText(hDC, ip->text, lstrlen(ip->text), &rc, DT_CENTER | DT_VCENTER);
  619. }
  620. void
  621. TopLeft(HDC hDC, LPRECT rcp, HPEN hpen, BOOL bCorners)
  622. {
  623. HPEN hpenOld;
  624. int x, y;
  625. hpenOld = SelectObject(hDC, hpen);
  626. x = rcp->right - 1;
  627. y = rcp->bottom;
  628. if (!bCorners) {
  629. x--;
  630. y--;
  631. }
  632. MoveToEx(hDC, x, rcp->top, NULL);
  633. LineTo(hDC, rcp->left, rcp->top);
  634. LineTo(hDC, rcp->left, y);
  635. SelectObject(hDC, hpenOld);
  636. }
  637. void
  638. BottomRight(HDC hDC, LPRECT rcp, HPEN hpen, BOOL bCorners)
  639. {
  640. HPEN hpenOld;
  641. int x, y;
  642. hpenOld = SelectObject(hDC, hpen);
  643. x = rcp->left - 1;
  644. y = rcp->top;
  645. if (!bCorners) {
  646. x++;
  647. y++;
  648. }
  649. MoveToEx(hDC, rcp->right-1, y, NULL);
  650. LineTo(hDC, rcp->right-1, rcp->bottom-1);
  651. LineTo(hDC, x, rcp->bottom-1);
  652. SelectObject(hDC, hpenOld);
  653. }
  654. PSTATEL
  655. StatusGetItem(PILIST plist, int id)
  656. {
  657. int i;
  658. if (plist == NULL) {
  659. return(NULL);
  660. }
  661. for (i = 0; i < plist->nitems; i++) {
  662. if (plist->statels[i].id == id) {
  663. return(&plist->statels[i]);
  664. }
  665. }
  666. return(NULL);
  667. }
  668. /*
  669. * calculate the width of a given field. This is the width in characters
  670. * multiplied by the average character width, plus a few units for
  671. * borders.
  672. *
  673. * if SF_VAR is set, this field size varies depending on the text, so
  674. * we use GetTextExtent for the field size. If SF_VAR is selected, the caller
  675. * can specify that the size is not to exceed the (width * avecharwidth)
  676. * size (using SF_SZMAX) or that it is not be less than it (SF_SZMIN).
  677. */
  678. int
  679. StatusCalcWidth(HWND hWnd, PSTATEL ip)
  680. {
  681. int ch_size, t_size;
  682. SIZE sz;
  683. HDC hDC;
  684. ch_size = ip->width * status_charwidth;
  685. if (ip->flags & SF_VAR) {
  686. hDC = GetDC(hWnd);
  687. InitDC(hDC);
  688. GetTextExtentPoint(hDC, ip->text, lstrlen(ip->text), &sz);
  689. ReleaseDC(hWnd, hDC);
  690. t_size = sz.cx;
  691. /*
  692. * check this size against min/max size if
  693. * requested
  694. */
  695. if (ip->flags & SF_SZMIN) {
  696. if (ch_size > t_size) {
  697. t_size = ch_size;
  698. }
  699. }
  700. if (ip->flags & SF_SZMAX) {
  701. if (ch_size < t_size) {
  702. t_size = ch_size;
  703. }
  704. }
  705. ch_size = t_size;
  706. }
  707. if (ch_size != 0) {
  708. if (ip->type == SF_BUTTON) {
  709. return(ch_size+6);
  710. } else {
  711. return(ch_size+4);
  712. }
  713. } else {
  714. return(0);
  715. }
  716. }
  717. int
  718. StatusCalcHeight(HWND hWnd, PSTATEL ip)
  719. {
  720. int size;
  721. size = status_charheight;
  722. if (ip->type == SF_BUTTON) {
  723. return(size + 6);
  724. } else {
  725. return(size + 2);
  726. }
  727. }