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.

407 lines
10 KiB

  1. /*****************************************************************************
  2. *
  3. * diqvint.c
  4. *
  5. * VList plug-in that does integers.
  6. *
  7. *****************************************************************************/
  8. #include "diquick.h"
  9. #pragma BEGIN_CONST_DATA
  10. /*****************************************************************************
  11. *
  12. * VLISTINT
  13. *
  14. * INT-specific goo.
  15. *
  16. *****************************************************************************/
  17. typedef struct VLISTINT {
  18. VLISTITEM item;
  19. DIPROPDWORD dipdw;
  20. int iMin;
  21. int iMax;
  22. int iRadix;
  23. /*
  24. * If non-NULL, then this is a read/write control.
  25. */
  26. PROPUPDATEPROC Update;
  27. PV pvRef1;
  28. PV pvRef2;
  29. } VLISTINT, *PVLISTINT;
  30. #ifndef UDM_SETRANGE32
  31. #define UDM_SETRANGE32 (WM_USER + 111)
  32. #define UDM_GETRANGE32 (WM_USER + 112)
  33. #endif
  34. /*****************************************************************************
  35. *
  36. * Some helper functions for UpDown controls since they're kind
  37. * of broken.
  38. *
  39. *****************************************************************************/
  40. /*****************************************************************************
  41. *
  42. * UpDown_SetRange
  43. *
  44. * This is an evil hack to set the range of an UpDown control to a
  45. * 32-bit value, because older versions didn't support
  46. * UDM_SETRANGE32.
  47. *
  48. *****************************************************************************/
  49. void EXTERNAL
  50. UpDown_SetRange(HWND hwndUD, int min, int max)
  51. {
  52. int iTest;
  53. /*
  54. * We detect whether UDM_SETRANGE32 is supported by first sending it,
  55. * then using UDM_GETRANGE32 to see if it worked.
  56. */
  57. SendMessage(hwndUD, UDM_SETRANGE32, (WPARAM)min, (LPARAM)max);
  58. iTest = max + 1; /* Make sure it's different */
  59. SendMessage(hwndUD, UDM_GETRANGE32, 0, (LPARAM)&iTest);
  60. /*
  61. * If UDM_GETRANGE32 failed to return the correct value,
  62. * then try it the old way, but first pin the pin/max values.
  63. */
  64. if (iTest != max) {
  65. if (max > UD_MAXVAL) max = UD_MAXVAL;
  66. if (min < UD_MINVAL) min = UD_MINVAL;
  67. SendMessage(hwndUD, UDM_SETRANGE, 0, MAKELPARAM(max, min));
  68. }
  69. }
  70. /*****************************************************************************
  71. *
  72. * UpDown_SetPos
  73. *
  74. * Set the value in the edit control part of the sub-dialog.
  75. * We have to do it ourselves because there is no UDM_SETPOS32
  76. * message.
  77. *
  78. *****************************************************************************/
  79. void EXTERNAL
  80. UpDown_SetPos(HWND hwndUD, int iRadix, int iValue)
  81. {
  82. TCHAR tsz[128];
  83. SendMessage(hwndUD, UDM_SETBASE, iRadix, 0L);
  84. /*
  85. * Bug in UDM_SETPOS means that we cannot use it on values
  86. * greater than 65535.
  87. */
  88. if (iRadix == 10) {
  89. wsprintf(tsz, TEXT("%d") , iValue);
  90. } else {
  91. wsprintf(tsz, TEXT("0x%08x"), iValue);
  92. }
  93. SetWindowText(GetWindow(hwndUD, GW_HWNDPREV), tsz);
  94. }
  95. /*****************************************************************************
  96. *
  97. * VInt_AToI
  98. *
  99. * Convert a string to an integer, allowing decimal or hex.
  100. *
  101. *****************************************************************************/
  102. BOOL INTERNAL
  103. VInt_AToI(LPCTSTR ptsz, PINT pi)
  104. {
  105. int iVal;
  106. BOOL fSign = FALSE;
  107. UINT uiRadix;
  108. /*
  109. * Skip leading whitespace.
  110. */
  111. while (*ptsz == TEXT(' ')) {
  112. ptsz++;
  113. }
  114. /*
  115. * See if there is a leading negative sign.
  116. */
  117. if (*ptsz == TEXT('-')) {
  118. fSign = TRUE;
  119. ptsz++;
  120. }
  121. iVal = 0;
  122. if (ptsz[0] == TEXT('0') &&
  123. (ptsz[1] == TEXT('x') || ptsz[1] == TEXT('X'))) {
  124. uiRadix = 16;
  125. ptsz += 2;
  126. } else {
  127. uiRadix = 10;
  128. }
  129. for (;;) {
  130. UINT uiVal;
  131. if ((UINT)(*ptsz - TEXT('0')) < 10) {
  132. uiVal = (UINT)(*ptsz - TEXT('0'));
  133. } else if ((UINT)(*ptsz - TEXT('A')) < 6) {
  134. uiVal = (UINT)(*ptsz - TEXT('A')) + 10;
  135. } else if ((UINT)(*ptsz - TEXT('a')) < 6) {
  136. uiVal = (UINT)(*ptsz - TEXT('a')) + 10;
  137. } else if (*ptsz == TEXT(' ') || *ptsz == TEXT(',')) {
  138. continue; /* Ignore spaces and commas */
  139. } else if (*ptsz == TEXT('\0')) {
  140. *pi = fSign ? -iVal : iVal;
  141. return TRUE;
  142. } else {
  143. return FALSE;
  144. }
  145. if (uiVal < uiRadix) {
  146. iVal = iVal * uiRadix + uiVal;
  147. } else {
  148. return FALSE;
  149. }
  150. ptsz++;
  151. }
  152. }
  153. /*****************************************************************************
  154. *
  155. * UpDown_GetPos
  156. *
  157. * Get the value in the edit control part of the sub-dialog.
  158. * We have to do it ourselves because there is no UDM_GETPOS32
  159. * message.
  160. *
  161. *****************************************************************************/
  162. BOOL EXTERNAL
  163. UpDown_GetPos(HWND hwndUD, LPINT pi)
  164. {
  165. TCHAR tsz[CCHMAXINT];
  166. GetWindowText(GetWindow(hwndUD, GW_HWNDPREV), tsz, cA(tsz));
  167. return VInt_AToI(tsz, pi);
  168. }
  169. /*****************************************************************************
  170. *
  171. * VInt_PreDisplay
  172. *
  173. * Set the edit control text and let the dialog know who it is in
  174. * charge of.
  175. *
  176. *****************************************************************************/
  177. void INTERNAL
  178. VInt_PreDisplay(HWND hdlg, PV pv)
  179. {
  180. PVLISTINT pvint = pv;
  181. HWND hwndUD = GetDlgItem(hdlg, IDC_VINT_UD);
  182. HWND hwndEdit;
  183. ShowWindow(hwndUD, pvint->Update ? SW_SHOW : SW_HIDE);
  184. ShowWindow(GetDlgItem(hdlg, IDC_VINT_APPLY),
  185. pvint->Update ? SW_SHOW : SW_HIDE);
  186. UpDown_SetRange(hwndUD, pvint->iMin, pvint->iMax);
  187. UpDown_SetPos(hwndUD, pvint->iRadix, pvint->dipdw.dwData);
  188. hwndEdit = GetDlgItem(hdlg, IDC_VINT_EDIT);
  189. Edit_SetReadOnly(hwndEdit, !pvint->Update);
  190. CheckRadioButton(hdlg, IDC_VINT_DEC, IDC_VINT_HEX,
  191. pvint->iRadix == 10 ? IDC_VINT_DEC : IDC_VINT_HEX);
  192. SetDialogPtr(hdlg, pvint);
  193. }
  194. /*****************************************************************************
  195. *
  196. * VInt_Destroy
  197. *
  198. * Nothing to clean up.
  199. *
  200. *****************************************************************************/
  201. void INTERNAL
  202. VInt_Destroy(PV pv)
  203. {
  204. PVLISTINT pvint = pv;
  205. }
  206. /*****************************************************************************
  207. *
  208. * VInt_OnInitDialog
  209. *
  210. * Limit the strings to CCHMAXINT characters.
  211. *
  212. *****************************************************************************/
  213. BOOL INTERNAL
  214. VInt_OnInitDialog(HWND hdlg)
  215. {
  216. HWND hwndEdit = GetDlgItem(hdlg, IDC_VINT_EDIT);
  217. Edit_LimitText(hwndEdit, CCHMAXINT);
  218. return TRUE;
  219. }
  220. /*****************************************************************************
  221. *
  222. * VInt_OnApply
  223. *
  224. * Let the owner know.
  225. *
  226. *****************************************************************************/
  227. void INTERNAL
  228. VInt_OnApply(HWND hdlg, PVLISTINT pvint)
  229. {
  230. HRESULT hres;
  231. hres = pvint->Update(&pvint->dipdw.diph, pvint->pvRef1, pvint->pvRef2);
  232. if (FAILED(hres)) {
  233. MessageBoxV(hdlg, IDS_ERR_HRESULT, hres);
  234. }
  235. }
  236. /*****************************************************************************
  237. *
  238. * VInt_SetRadix
  239. *
  240. * Set a new radix by reading the old value, changing the radix,
  241. * and writing out the new value.
  242. *
  243. *****************************************************************************/
  244. void INTERNAL
  245. VInt_SetRadix(HWND hwndUD, PVLISTINT pvint, int iRadix)
  246. {
  247. UpDown_GetPos(hwndUD, &pvint->dipdw.dwData);
  248. pvint->iRadix = iRadix;
  249. UpDown_SetPos(hwndUD, pvint->iRadix, pvint->dipdw.dwData);
  250. }
  251. /*****************************************************************************
  252. *
  253. * VInt_OnCommand
  254. *
  255. * If they changed the radix, then change it.
  256. *
  257. * If they pressed Apply, then apply it.
  258. *
  259. *****************************************************************************/
  260. BOOL INTERNAL
  261. VInt_OnCommand(HWND hdlg, int id, UINT codeNotify)
  262. {
  263. PVLISTINT pvint = GetDialogPtr(hdlg);
  264. HWND hwndUD = GetDlgItem(hdlg, IDC_VINT_UD);
  265. switch (id) {
  266. case IDC_VINT_DEC:
  267. VInt_SetRadix(hwndUD, pvint, 10);
  268. return TRUE;
  269. case IDC_VINT_HEX:
  270. VInt_SetRadix(hwndUD, pvint, 16);
  271. return TRUE;
  272. case IDC_VINT_APPLY:
  273. UpDown_GetPos(hwndUD, &pvint->dipdw.dwData);
  274. VInt_OnApply(hdlg, pvint);
  275. return TRUE;
  276. }
  277. return FALSE;
  278. }
  279. /*****************************************************************************
  280. *
  281. * VInt_DlgProc
  282. *
  283. * Nothing really happens here. The real work is done externally.
  284. *
  285. *****************************************************************************/
  286. INT_PTR CALLBACK
  287. VInt_DlgProc(HWND hdlg, UINT wm, WPARAM wp, LPARAM lp)
  288. {
  289. switch (wm) {
  290. case WM_INITDIALOG:
  291. return VInt_OnInitDialog(hdlg);
  292. case WM_COMMAND:
  293. return VInt_OnCommand(hdlg,
  294. (int)GET_WM_COMMAND_ID(wp, lp),
  295. (UINT)GET_WM_COMMAND_CMD(wp, lp));
  296. }
  297. return FALSE;
  298. }
  299. /*****************************************************************************
  300. *
  301. * c_vvtblInt
  302. *
  303. * Our vtbl.
  304. *
  305. *****************************************************************************/
  306. const VLISTVTBL c_vvtblInt = {
  307. VInt_PreDisplay,
  308. VInt_Destroy,
  309. IDD_VAL_INT,
  310. VInt_DlgProc,
  311. };
  312. /*****************************************************************************
  313. *
  314. * VInt_Create
  315. *
  316. * Make a vlist item that tracks an integer.
  317. *
  318. * The LPDIPROPDWORD gets copied and handed to the Update procedure.
  319. * The Update procedure can use the non-dwData fields of the
  320. * DIPROPDWORD to stash extra reference data.
  321. *
  322. *****************************************************************************/
  323. PVLISTITEM EXTERNAL
  324. VInt_Create(LPDIPROPDWORD pdipdw, int iMin, int iMax, int iRadix,
  325. PROPUPDATEPROC Update, PV pvRef1, PV pvRef2)
  326. {
  327. PVLISTINT pvint = LocalAlloc(LPTR, cbX(VLISTINT));
  328. if (pvint) {
  329. pvint->item.pvtbl = &c_vvtblInt;
  330. pvint->dipdw = *pdipdw;
  331. pvint->iMin = iMin;
  332. pvint->iMax = iMax;
  333. pvint->iRadix = iRadix;
  334. pvint->Update = Update;
  335. pvint->pvRef1 = pvRef1;
  336. pvint->pvRef2 = pvRef2;
  337. }
  338. return (PV)pvint;
  339. }