button.c
上传用户:xiaoan1112
上传日期:2013-04-11
资源大小:19621k
文件大小:13k
源码类别:

操作系统开发

开发平台:

Visual C++

  1. /*
  2. COW : Character Oriented Windows
  3. (COW USER DIALOG)
  4. button.c : button functions
  5. */
  6. #define COW
  7. #include <cow.h>
  8. #include <uwindow.h>
  9. #include <uevent.h>
  10. #include <vkey.h>
  11. #include <uisa.h>
  12. #include <kinput.h>
  13. #include "dialog.h"
  14. #include "event.h"
  15. #include "window.h"
  16. #include "util.h"
  17. #include "screen.h"
  18. #include "button.h"
  19. #include "_button.h"
  20. /* data for rendering */
  21. BTR btrRadioButton =
  22. {
  23. chRadioButtonOff,
  24. '?', /* must load from run-time character */
  25. chRadioButtonPrefix,
  26. chRadioButtonSuffix,
  27. '', /* no greyed radio buttons */
  28. };
  29. BTR btrCheckBox =
  30. {
  31. chCheckBoxOff,
  32. chCheckBoxOn,
  33. chCheckBoxPrefix,
  34. chCheckBoxSuffix,
  35. chCheckBoxGrey,
  36. };
  37. /* forward */
  38. STATIC VOID DrawButton(PWND);
  39. STATIC VOID DrawCheckBox(PWND, BTR *);
  40. STATIC VOID DrawPushButton(PWND);
  41. STATIC VOID DrawBracketBox(PWND, WORD);
  42. STATIC VOID DrawAccel(PWND, RX, WORD, BOOL);
  43. STATIC VOID DoButton(PWND);
  44. PRIVATE DWORD FARPUBLIC /* WndProcs are PUBLIC */
  45. ButtonWndProc(pwnd, message, wParam, lParam)
  46. /*
  47.   -- WndProc for handling button windows
  48. */
  49. PWND pwnd;
  50. WORD message, wParam;
  51. DWORD lParam;
  52. {
  53. MSP msp;
  54. BYTE fUp = FALSE;
  55. switch (message)
  56. {
  57. case WM_PAINT:
  58. DrawButton(pwnd);
  59. break;
  60. case WM_SETFOCUS:
  61. Assert((pwnd->style & WS_SUBSTYLE) != BS_GROUP);
  62. Assert(pwnd == pwndFocus);
  63. SendMessage(pwnd->pwndParent, WM_DIALOG_SETFOCUS, pwnd->id, 0L);
  64. DrawButton(pwnd);
  65. break;
  66. case WM_WANTFOCUS:
  67. switch (pwnd->style & WS_SUBSTYLE)
  68. {
  69. default:
  70. break; /* return TRUE => accept focus */
  71. case BS_GROUP:
  72. ReturnFalse:
  73. return((DWORD) FALSE); /* never accept focus */
  74. /*break*/
  75. case BS_RADIOBUTTON:
  76. /* Accept focus if button is on, or demanding it */
  77. if (BstOfWnd(pwnd) == bstOn || wParam & 1)
  78. goto ReturnTrue;
  79. else if (FFirstButton(pwnd))
  80. {
  81. REGISTER PWND pwndT = pwnd;
  82. /* first button -> are we in ninch ?? */
  83. do
  84. {
  85. pwndT = PwndButtonNext(pwndT);
  86. if (BstOfWnd(pwndT) == bstOn)
  87. goto ReturnFalse;
  88. }
  89. while (pwndT != pwnd);
  90. /* ninch state -- accept for first button */
  91. goto ReturnTrue;
  92. }
  93. else
  94. goto ReturnFalse;
  95. return (wParam);
  96. /*NOTREACHED*/
  97. }
  98. break;
  99. case WM_KILLFOCUS:
  100. Assert((pwnd->style & WS_SUBSTYLE) != BS_GROUP);
  101. SendMessage(pwnd->pwndParent,WM_DIALOG_KILLFOCUS,pwnd->id, 0L);
  102. SetFButtonDown(pwnd, FALSE);
  103. Assert(pwnd == pwndFocus);
  104. pwndFocus = NULL; /* special signal for losing focus */
  105. DrawButton(pwnd);
  106. pwndFocus = pwnd; /* restore it properly */
  107. break;
  108. case WM_MAKEACTIVE:
  109. DoButton(pwnd);
  110. break; /* return TRUE */
  111. case WM_CHAR:
  112. /* return FALSE if key ignored */
  113. UndoRepeat(wParam, lParam);
  114. switch (wParam)
  115. {
  116. default:
  117. return((DWORD) FALSE);
  118. break;
  119. case ' ':
  120. if (!FButtonDown(pwnd) && pwnd->fEnabled)
  121. {
  122. SetFButtonDown(pwnd, TRUE);
  123. DrawButton(pwnd);
  124. }
  125. break;
  126. case VK_UP:
  127. case VK_LEFT:
  128. fUp = TRUE;
  129. /* fall through */
  130. case VK_DOWN:
  131. case VK_RIGHT:
  132. switch (pwnd->style & WS_SUBSTYLE)
  133. {
  134. default:
  135. return((DWORD) FALSE);
  136. break;
  137. case BS_RADIOBUTTON:
  138. {
  139. /* move within a radio group */
  140. REGISTER PWND pwndT = pwnd;
  141. /* move if current button is on or disabled,
  142. * (i.e. stay if off and enabled)
  143. */
  144. if (BstOfWnd(pwnd) == bstOn || !pwnd->fEnabled)
  145. {
  146. /* move to next or prev */
  147. do
  148. {
  149. pwndT = PwndButtonNext(pwndT);
  150. }
  151. while (fUp &&
  152.    PwndButtonNext(pwndT) != pwnd);
  153. }
  154. /* move focus - change selection */
  155. SetFocus(pwndT);
  156. Assert(pwnd->pwndParent == pwndT->pwndParent);
  157. if (pwndT->fEnabled)
  158. DoButton(pwndT);
  159. }
  160. break;
  161. case BS_CHECKBOX:
  162. case BS_AUTOCHECKBOX:
  163. /* checkbox change */
  164. if (fUp != (BYTE) BstOfWnd(pwnd) &&
  165.     pwnd->fEnabled)
  166. DoButton(pwnd);
  167. break;
  168. }
  169. break;
  170. }
  171. break;
  172. case WM_LBUTTONUP:
  173. if (FCaptured(pwnd))
  174. ReleaseCapture();
  175. if (fButtonAction)
  176. {
  177. fButtonAction = FALSE;
  178. DoButton(pwnd);
  179. }
  180. break;
  181. case WM_KEYUP:
  182. if (FButtonDown(pwnd) && wParam == VK_SPACE)
  183. DoButton(pwnd);
  184. break;
  185. case WM_MOUSEMOVE:
  186. if (!fButtonAction)
  187. break; /* ignore first movement */
  188. case WM_LBUTTONDOWN:
  189. case WM_LBUTTONDBLCLK:
  190. fButtonAction = TRUE;
  191. if (wParam & MK_LBUTTON &&
  192.     (pwnd->style & WS_SUBSTYLE) != BS_GROUP)
  193. {
  194. /* if button down and mouse move */
  195. BOOL fWasDown = FButtonDown(pwnd);
  196. msp.lParam = lParam;
  197. SetFButtonDown(pwnd, PtInRect((PRRC) &pwnd->arcWindow,
  198.     msp.s.ax, msp.s.ay));
  199. SetFocus(pwnd); /* grab */
  200. if (FButtonDown(pwnd))
  201. {
  202. SetCapture(pwnd); /* trap all mouse events */
  203. if (fWasDown)
  204. goto ReturnTrue; /* skip draw */
  205. }
  206. else
  207. {
  208. ReleaseCapture();
  209.     /* release mouse events to other windows */
  210. /* re-post the message to proper window */
  211. RePostMouseMessage(message, wParam, lParam);
  212. }
  213. DrawButton(pwnd);
  214. }
  215. break;
  216. }
  217. ReturnTrue:
  218. return((DWORD) TRUE);
  219. }
  220. STATIC VOID
  221. DrawButton(pwnd)
  222. /*
  223.   -- draws a button (radio/push/checkbox) or groupbox
  224. */
  225. REGISTER PWND pwnd;
  226. {
  227. switch (pwnd->style & WS_SUBSTYLE)
  228. {
  229. default:
  230. AssertSz(FALSE, "Invalid Button");
  231. break;
  232. case BS_RADIOBUTTON:
  233. btrRadioButton.chOn = chRadioButtonOn; /* use run-time char */
  234. DrawCheckBox(pwnd, &btrRadioButton);
  235. break;
  236. case BS_CHECKBOX:
  237. case BS_AUTOCHECKBOX:
  238. DrawCheckBox(pwnd, &btrCheckBox);
  239. break;
  240. case BS_PUSHBUTTON:
  241. case BS_DEFPUSHBUTTON:
  242. DrawPushButton(pwnd);
  243. break;
  244. case BS_GROUP:
  245. DrawBorder(pwnd, &boxSingle, isaButton,
  246.     (char *) pwnd->szDialog);
  247. break;
  248. }
  249. }
  250. STATIC VOID
  251. DrawPushButton(pwnd)
  252. /*
  253.   -- Draw a pushbutton
  254. */
  255. REGISTER PWND pwnd;
  256. {
  257. REGISTER WORD di;
  258. WORD cch = CchRealLenSz((char *) pwnd->szDialog);
  259. BYTE drx;
  260. RX rxText;
  261. RRC rrc;
  262. GetClientRrc(pwnd, &rrc);
  263. if (cch >= (drx = rrc.rxRight - rrc.rxLeft - daxPushButton))
  264. {
  265. /* button text too big (or just right) for window */
  266. rxText = daxPushButton / 2;
  267. cch = drx;
  268. }
  269. else
  270. {
  271. rxText = (RX) (((drx - cch + 1) / 2) + daxPushButton/2);
  272. }
  273. /* set cursor position */
  274. pwnd->axCursor = pwnd->arcClipping.axLeft + rxText;
  275. #ifdef KANJI
  276. pwnd->ayCursor = pwnd->arcClipping.ayTop;
  277. #endif
  278. if (!fDrawItem)
  279. return; /* don't actually draw yet */
  280. di = FButtonDown(pwnd) ? isaButtonDown :
  281.     ((pwnd->fEnabled) ? isaPushButton : isaButtonDisabled);
  282. FillRrc(pwnd, &rrc, ' ', di);
  283. DrawAccel(pwnd, rxText, di, !FButtonDown(pwnd));
  284. if (FButtonDown(pwnd))
  285. {
  286. /* button is down -> there better be no change in status */
  287. Assert(pwndFocus != NULL);
  288. /* Assert(pwndFocus == pwnd); -> removed because if you 
  289.    redraw button on a dlmKillFocus the focus is elsewhere */
  290. }
  291. else if (pwndFocus == NULL)
  292. {
  293. /* moving off a button (or init) -> restore to default */
  294. PWND pwndT;
  295. pwndT = PwndDefaultPushButton(PwndParent(pwnd));
  296. if (pwndT == pwnd)
  297. {
  298. /* losing focus, but we are the default */
  299. di = isaDialogAccel; /* hilite this button */
  300. }
  301. else if (pwndT != NULL)
  302. {
  303. /* restore default button */
  304. Assert(pwndT->fEnabled);
  305. DrawBracketBox(pwndT, isaDialogAccel);
  306. }
  307. }
  308. else if (((pwndFocus->style & WS_TYPE) != WS_BUTTON ||
  309.      (((pwndFocus->style & WS_SUBSTYLE) != BS_PUSHBUTTON) &&
  310.       ((pwndFocus->style & WS_SUBSTYLE) != BS_DEFPUSHBUTTON))) &&
  311. (pwnd->style & WS_SUBSTYLE) == BS_DEFPUSHBUTTON)
  312. {
  313. /* focus is not a push button, but we are the default */
  314. di = isaDialogAccel; /* hilite this button */
  315. }
  316. else if (pwnd == pwndFocus)
  317. {
  318. /* we are the focus, clear old default */
  319. PWND pwndT;
  320. pwndT = PwndDefaultPushButton(PwndParent(pwnd));
  321. if ((pwndT != pwnd)&&(pwndT != NULL))
  322. {
  323. Assert(pwndT->fEnabled);
  324. DrawBracketBox(pwndT, isaPushButton);
  325. }
  326. di = isaDialogAccel; /* hilite this button */
  327. }
  328. DrawBracketBox(pwnd, di);
  329. /* cursor must be on for dialog tabbing on top line */
  330. Assert(pwnd->fCursorOn);
  331. Assert(pwnd->ayCursor = pwnd->arcClipping.ayTop);
  332. }
  333. STATIC VOID
  334. DrawBracketBox(pwnd, di)
  335. /*
  336.   -- draw brackets or box around a pushbutton
  337. */
  338. REGISTER PWND pwnd;
  339. WORD di;
  340. {
  341. #ifdef BUTTON_LARGE
  342. BOX * pbox;
  343. /* for large buttons, draw border instead */
  344. Assert(pwnd != NULL);
  345. pbox = &boxSingle;
  346. if (di == isaDialogAccel)
  347. {
  348. /* it has the focus => show as double border */
  349. pbox = &boxDouble;
  350. di = isaPushButton;
  351. }
  352. DrawBorder(pwnd, pbox, di, NULL);
  353. #else
  354. {
  355. RRC rrc;
  356. Assert(pwnd != NULL);
  357. GetClientRrc(pwnd,&rrc);
  358. CharOut(pwnd, 0, 0, '<', di);
  359. CharOut(pwnd, rrc.rxRight-1, 0, '>', di);
  360. }
  361. #endif /*BUTTON_LARGE*/
  362. }
  363. STATIC VOID
  364. DrawCheckBox(pwnd, pbtr)
  365. /*
  366.   -- draw a checkbox or radiobutton (depends on pbtr)
  367. */
  368. REGISTER PWND pwnd;
  369. REGISTER BTR *pbtr;
  370. {
  371. char ch;
  372. WORD di;
  373. di = (pwnd->fEnabled) ? isaButton : isaButtonDisabled;
  374. if ((BstOfWnd(pwnd)) == bstOff)
  375. ch = pbtr->chOff;
  376. else if (BstOfWnd(pwnd) == bstGreyed)
  377. ch = pbtr->chGrey;
  378. else
  379. ch = pbtr->chOn;
  380. BeginDraw();
  381. CharOut(pwnd, rxPrefix, 0, pbtr->chPrefix, di);
  382. CharOut(pwnd, rxButton, 0, ch, di);
  383. CharOut(pwnd, rxSuffix, 0, pbtr->chSuffix, di);
  384. DrawAccel(pwnd, rxButtonText, di, TRUE);
  385. EndDraw();
  386. pwnd->axCursor = pwnd->arcClipping.axLeft + rxButton;
  387. /* debug check that the cursor is in the correct position */
  388. Assert(pwnd->fCursorOn);
  389. Assert(pwnd->ayCursor == pwnd->arcClipping.ayTop);
  390. }
  391. STATIC VOID
  392. DrawAccel(pwnd, rx, di, fHilite)
  393. /*
  394.   -- draw text with optional accelerator in a window
  395.   -- start at rx
  396. */
  397. REGISTER PWND pwnd;
  398. RX rx;
  399. WORD di;
  400. BOOL fHilite; /* should we use isaDialogAccel ?? */
  401. {
  402. TextOut(pwnd, rx, 0, (char *) pwnd->szDialog, -1, di);
  403. if (pwnd->aclDialog == aclNil)
  404. return;
  405. if (fShowDlgAccel && pwnd->fEnabled)
  406. CharOut(pwnd, rx + IchAccel(pwnd), 0, ChAccel(pwnd),
  407.     fHilite ? isaDialogAccel : di);
  408. }
  409. WORD FARPRIVATE
  410. WButtonChecked(pwnd)
  411. /*
  412.   -- return state of button
  413.   -- note : pwnd == window of the button !!
  414.   -- for Radio/Push buttons, return TRUE if a button is "on"
  415.   -- for checkboxes, return state (0,1 or 2 for ninch)
  416. */
  417. PWND pwnd;
  418. {
  419. Assert(pwnd != NULL);
  420. return(BstOfWnd(pwnd));
  421. }
  422. VOID FARPRIVATE
  423. CheckRadioButton(pwndFirst, bnSet, fDisplay)
  424. /*
  425.   -- check a radiobutton in a group and uncheck all others in the group
  426.   -- pwndFirst is the first button in the group (usually)
  427.   -- bnSet is the button number to set (i.e. 0 based)
  428.   -- if bnSet is invalid then no button will be set
  429.   NOTE : we use the fact the uNinchRadio is -1 to get an invalid bn.
  430.   NOTE : while we are at it, we assert that the button "id"s are sequential
  431.   NOTE : if bnSet == 0, the pwndFirst does not have to be the first button
  432. in the group (and the order assertion is disabled).
  433. */
  434. REGISTER PWND pwndFirst;
  435. WORD bnSet; /* index of button to set */
  436. BOOL fDisplay; /* TRUE => redraw it */
  437.  {
  438. REGISTER PWND pwnd = pwndFirst;
  439. Debug(WORD idCheck = pwndFirst->id);
  440. Debug(BOOL fDontCheckOrder = bnSet == 0);
  441. Assert(pwndFirst != NULL);
  442. Assert(bstOff == 0 && bstOn == 1);
  443. do
  444. {
  445. BYTE bst;
  446. AssertSz((pwnd->style & WS_SUBSTYLE) == BS_RADIOBUTTON,
  447.     "Invalid Radio Group");
  448. Assert(fDontCheckOrder || pwnd->id == idCheck++);
  449. bst = (BYTE) (bnSet-- == 0);
  450. /* 1 iff matching button */
  451. if (BstOfWnd(pwnd) != bst)
  452. {
  453. SetWndBst(pwnd, bst);
  454. if (fDisplay)
  455. DrawButton(pwnd);
  456. }
  457. pwnd = PwndButtonNext(pwnd);
  458. }
  459. while (pwnd != pwndFirst);
  460. }
  461. VOID FARPRIVATE
  462. CheckDlgButton(pwnd, bst, fDisplay)
  463. /*
  464.   -- set the state of a checkbox
  465.   -- pwnd is a window pointer for a button
  466. */
  467. REGISTER PWND pwnd;
  468. WORD bst;
  469. BOOL fDisplay;
  470. {
  471. Assert(pwnd != NULL);
  472. AssertSz(bst < bstMax, "Invalid button state");
  473. SetWndBst(pwnd, bst);
  474. if (fDisplay)
  475. DrawWindow(pwnd);
  476. }
  477. STATIC VOID
  478. DoButton(pwnd)
  479. /*
  480.   -- a button has been pushed
  481. */
  482. REGISTER PWND pwnd;
  483. {
  484. SetFButtonDown(pwnd, FALSE);
  485. /* If auto then toggle the state */
  486. if (pwnd->style & BS_AUTO)
  487. {
  488. /* toggle button */
  489. Assert((pwnd->style & WS_SUBSTYLE) == BS_AUTOCHECKBOX);
  490. pwnd->wButton ^= bstOn;
  491. Assert((bstGreyed & bstOn) == 0);
  492. pwnd->wButton &= ~bstGreyed;
  493. }
  494. SendMessage(pwnd->pwndParent, WM_DIALOG, pwnd->id, 0L);
  495. DrawButton(pwnd);
  496. }
  497. PWND FARPRIVATE
  498. PwndDefaultPushButton(pwnd)
  499. /*
  500.   -- return the first default pushbutton in the dialog
  501. */
  502. REGISTER PWND pwnd;
  503. {
  504. pwnd = pwnd->pwndChild;
  505. while (pwnd)
  506. {
  507. if ((pwnd->style & WS_TYPE) == WS_BUTTON &&
  508.    (pwnd->style & WS_SUBSTYLE) == BS_DEFPUSHBUTTON)
  509.         return(pwnd);
  510. pwnd = PwndSibling(pwnd);
  511. }
  512. return NULL;
  513. }