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.

1935 lines
50 KiB

  1. /** FILE: cursors.c ********** Module Header ********************************
  2. *
  3. * Control panel applet for Cursors configuration. This file holds
  4. * everything to do with the "Cursors" dialog box in the Control Panel.
  5. *
  6. * If this applet gets incorporated into the MAIN.CPL module, look
  7. * for the define NOTINMAIN below. This marks some code that will
  8. * need to be modified.
  9. *
  10. * History:
  11. * 12:30 on Tues 23 Apr 1991 -by- Steve Cathcart [stevecat]
  12. * Took base code from Win 3.1 source
  13. * 12-22-91 DarrinM Created from MOUSE.C
  14. * 07-31-92 DarrinM Revived.
  15. * 01-04-93 ByronD Cleaned up, etc.
  16. * 03-25-93 JonPa Changed .ANI file format from RAD to RIFF
  17. * 04-29-93 JonPa Pull strings out of resource file
  18. * 05-20-93 ErikGav Added schemes
  19. *
  20. * Copyright (C) 1990-1993 Microsoft Corporation
  21. *
  22. *************************************************************************/
  23. //
  24. // Marks code that will need to be modified if this module is ever
  25. // incorporated into MAIN.CPL instead of being a separate applet.
  26. //
  27. #define NOTINMAIN
  28. //==========================================================================
  29. // Include files
  30. //==========================================================================
  31. // C Runtime
  32. #include <stddef.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <stdio.h>
  36. // Windows SDK
  37. /* cut out unnec stuff from windows.h */
  38. #define NOCLIPBOARD
  39. #define NOMETAFILE
  40. #define NOSYSCOMMANDS
  41. #define NOGDICAPMASKS
  42. #include <windows.h>
  43. // Common dialog includes.
  44. #include <dlgs.h>
  45. #include <commdlg.h>
  46. // Utility library
  47. #include <cplib.h>
  48. // Application specific
  49. #include "cursors.h"
  50. #include <winuserp.h>
  51. #ifdef NOTINMAIN
  52. #include "..\main\cphelp.h" //For the help id's.
  53. #endif //NOTINMAIN
  54. #ifndef RAD_FORMAT
  55. #include <asdf.h>
  56. #endif
  57. //==========================================================================
  58. // Local Definitions
  59. //==========================================================================
  60. #ifndef LATER
  61. // darrinm - 07/31/92
  62. // Replace with something good
  63. #define gcxAvgChar 8
  64. #endif
  65. #define CCURSORS 11
  66. #define MAX_SCHEME_NAME_LEN 32
  67. #define PM_NEWCURSOR (WM_USER + 1)
  68. #define PM_PAUSEANIMATION (WM_USER + 2)
  69. #define PM_UNPAUSEANIMATION (WM_USER + 3)
  70. #define ID_PREVIEWTIMER 1
  71. typedef struct _CURSORINFO { // curi
  72. DWORD fl;
  73. HCURSOR hcur;
  74. int ccur;
  75. int icur;
  76. char szFile[FILENAME_MAX];
  77. char szTitle[80];
  78. char szCreator[80];
  79. } CURSORINFO, *PCURSORINFO;
  80. #define CIF_FILE 0x0001
  81. #define CIF_ANICURSOR 0x0002
  82. #define CIF_MODIFIED 0x0004
  83. #define CIF_TITLE 0x0008
  84. #define CIF_CREATOR 0x0010
  85. #pragma pack(2)
  86. typedef struct tagNEWHEADER {
  87. WORD reserved;
  88. WORD rt;
  89. WORD cResources;
  90. } NEWHEADER, *LPNEWHEADER;
  91. #pragma pack()
  92. typedef struct
  93. {
  94. UINT idVisName;
  95. LPSTR idResource;
  96. LPSTR pszIniName;
  97. LPSTR pszVisName;
  98. } CURSORDESC, *PCURSORDESC;
  99. //
  100. // Structure that contains data used within a preview window. This
  101. // data is unique for each preview window, and is used to optimize
  102. // the painting.
  103. //
  104. typedef struct
  105. {
  106. HDC hdcMem;
  107. HBITMAP hbmMem;
  108. HBITMAP hbmOld;
  109. PCURSORINFO pcuri;
  110. } PREVIEWDATA, *PPREVIEWDATA;
  111. //==========================================================================
  112. // Local Data Declarations
  113. //==========================================================================
  114. extern HANDLE ghmod; // These guys are defined in INIT.C
  115. extern int gcxCursor, gcyCursor;
  116. HWND ghwndDlg, ghwndFile, ghwndFileH, ghwndTitle, ghwndTitleH;
  117. HWND ghwndCreator, ghwndCreatorH, ghwndLB, ghwndPreview;
  118. HWND ghwndSchemeCB;
  119. HBRUSH ghbrHighlight, ghbrHighlightText, ghbrWindow;
  120. COLORREF gcrHighlightText;
  121. TCHAR gszFileName[MAX_PATH];
  122. TCHAR gszFileName2[MAX_PATH];
  123. HFONT ghfontLabels;
  124. UINT gnMsgLBSelChString;
  125. UINT gnMsgFileOK;
  126. UINT wBrowseHelpMessage;
  127. LPTSTR gszFileNotFound = NULL;
  128. LPTSTR gszBrowse = NULL;
  129. LPTSTR gszFilter = NULL;
  130. TCHAR gszNoMem[256] = "No Memory";
  131. HHOOK ghhkMsgFilter; // Hook handle for message filter func.
  132. CURSORDESC gacd[] =
  133. {
  134. { IDS_ARROW, IDC_ARROW, "Arrow", NULL },
  135. { IDS_WAIT, IDC_WAIT, "Wait", NULL },
  136. { IDS_APPSTARTING, IDC_APPSTARTING, "AppStarting", NULL },
  137. { IDS_NO, IDC_NO, "No", NULL },
  138. { IDS_IBEAM, IDC_IBEAM, "IBeam", NULL },
  139. { IDS_CROSS, IDC_CROSS, "CrossHair",NULL },
  140. { IDS_SIZENS, IDC_SIZENS, "SizeNS", NULL },
  141. { IDS_SIZEWE, IDC_SIZEWE, "SizeWE", NULL },
  142. { IDS_SIZENWSE, IDC_SIZENWSE, "SizeNWSE", NULL },
  143. { IDS_SIZENESW, IDC_SIZENESW, "SizeNESW", NULL },
  144. { IDS_SIZEALL, IDC_SIZEALL, "SizeAll", NULL }
  145. };
  146. CURSORINFO acuri[CCURSORS];
  147. // registry keys
  148. char szSchemeINI[] = "Cursor Schemes";
  149. char szCurrentINI[] = "Current";
  150. char gszSchemeName[MAX_SCHEME_NAME_LEN+1];
  151. //==========================================================================
  152. // Local Function Prototypes
  153. //==========================================================================
  154. BOOL InitCursorsDlg(HWND hwnd);
  155. VOID CreateBrushes(VOID);
  156. VOID DestroyBrushes(VOID);
  157. LPTSTR GetResourceString(HINSTANCE hmod, int id);
  158. void DrawCursorListItem(DRAWITEMSTRUCT *pdis);
  159. BOOL GetCursorFromFile(CURSORINFO *pcuri);
  160. BOOL Browse(HWND hwndOwner);
  161. UINT_PTR CALLBACK OpenFileNameHookDlgProc(HWND hwnd, UINT msg, WPARAM wParam,
  162. LPARAM lParam);
  163. void CleanUpEverything(void);
  164. VOID UpdateCursorList(VOID);
  165. VOID NextFrame(HWND hwnd);
  166. BOOL ReadTag( HANDLE hf, PRTAG ptag);
  167. BOOL ReadChunk(HANDLE hf, PRTAG ptag, PVOID pv);
  168. BOOL ReadChunkN(HANDLE hf, PRTAG ptag, PVOID pv, DWORD cbMax);
  169. DWORD Skip( HANDLE hf, DWORD cbSkip);
  170. void HourGlass(BOOL fOn);
  171. DWORD FAR PASCAL MsgFilterHookFunc(INT nCode, WPARAM wParam, LPMSG lpMsg);
  172. BOOL TryToLoadCursor(HWND hwnd,int i,CURSORINFO *pcuri);
  173. BOOL LoadScheme(void);
  174. BOOL SaveScheme(void);
  175. BOOL SaveSchemeAs(void);
  176. BOOL RemoveScheme(void);
  177. BOOL InitSchemeComboBox(void);
  178. BOOL SchemeUpdate(int);
  179. LPSTR MakeFilename(LPSTR sz);
  180. INT_PTR CALLBACK SaveSchemeDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
  181. void StripBlanks (LPSTR pszString);
  182. //==========================================================================
  183. // Functions
  184. //==========================================================================
  185. #ifdef NOTINMAIN //NOTINMAIN
  186. //
  187. // This is a hack to get around the mess in CPLIB.H. It can all go away
  188. // when this applet is incorporated into MAIN.CPL.
  189. //
  190. #define wHelpMessage xwHelpMessage
  191. #define dwContext xdwContext
  192. #define szControlHlp xszControlHlp
  193. #define CPHelp xCPHelp
  194. UINT wHelpMessage; // stuff for help
  195. DWORD dwContext = 0L;
  196. char szControlHlp[] = "control.hlp";
  197. void CPHelp (HWND hWnd)
  198. {
  199. // char szBuf[80];
  200. // wsprintf (szBuf, "Help Context %ld", dwContext);
  201. WinHelp (hWnd, szControlHlp, HELP_CONTEXT, dwContext);
  202. // hWnd = hWnd;
  203. }
  204. #endif //NOTINMAIN
  205. /***************************************************************************\
  206. * InitCursorsDlg
  207. *
  208. *
  209. * History:
  210. * 12-22-91 DarrinM Created.
  211. * 04-10-93 ErikGav Added init for schemes
  212. \***************************************************************************/
  213. BOOL InitCursorsDlg(
  214. HWND hwnd)
  215. {
  216. CURSORINFO *pcuri;
  217. LOGFONT lf;
  218. int i;
  219. DWORD dwDummy;
  220. static TCHAR szBuffer[256];
  221. LPTSTR p,p2;
  222. #ifdef NOTINMAIN
  223. wHelpMessage = RegisterWindowMessage("ShellHelp");
  224. dwContext = IDH_CHILD_CURSORS;
  225. #endif //NOTINMAIN
  226. GetProfileString(szCurrentINI,szSchemeINI,"",szBuffer,sizeof(szBuffer));
  227. if (szBuffer[0] == '\0')
  228. {
  229. //
  230. // this key doesn't exist-- this is the first time
  231. // the applet has been run. Create the default
  232. // scheme sets.
  233. //
  234. LoadString(ghmod, IDS_DEFAULTSCHEME, szBuffer, sizeof(szBuffer));
  235. WriteProfileString(szCurrentINI,szSchemeINI,szBuffer);
  236. // fill in the schemes for
  237. // the listbox
  238. for (i=IDS_FIRSTSCHEME;i<=IDS_LASTSCHEME;i++)
  239. {
  240. LoadString(ghmod, i, szBuffer, sizeof(szBuffer));
  241. p = szBuffer;
  242. while (*p != '=') p = CharNext(p);
  243. p2 = CharNext(p);
  244. *p = '\0';
  245. WriteProfileString(szSchemeINI,szBuffer,p2);
  246. }
  247. }
  248. //
  249. // Register the help message from the File Open (Browse) dialog.
  250. //
  251. wBrowseHelpMessage = RegisterWindowMessage(HELPMSGSTRING);
  252. LoadAccelerators(ghmod, MAKEINTRESOURCE(CP_ACCEL));
  253. /*
  254. * Load Strings
  255. */
  256. if (gszFileNotFound == NULL) {
  257. gszFileNotFound = GetResourceString(ghmod, IDS_CUR_BADFILE);
  258. if (gszFileNotFound == NULL) {
  259. return FALSE;
  260. }
  261. }
  262. if (gszBrowse == NULL) {
  263. gszBrowse = GetResourceString(ghmod, IDS_CUR_BROWSE);
  264. if (gszBrowse == NULL) {
  265. return FALSE;
  266. }
  267. }
  268. if (gszFilter == NULL) {
  269. gszFilter = GetResourceString(ghmod, IDS_CUR_FILTER);
  270. if (gszFilter == NULL) {
  271. return FALSE;
  272. }
  273. }
  274. /*
  275. * Load description strings from the resource file
  276. */
  277. for( i = 0; i < CCURSORS; i++ ) {
  278. if (gacd[i].idVisName != 0) {
  279. gacd[i].pszVisName = GetResourceString(ghmod, gacd[i].idVisName);
  280. if (gacd[i].pszVisName != NULL) {
  281. /*
  282. * We got a buffer for the string,
  283. * clear the string id so we won't try to load it again.
  284. */
  285. gacd[i].idVisName = 0;
  286. } else {
  287. /*
  288. * Could not get the string. Use the registry name in this
  289. * emergency case.
  290. */
  291. gacd[i].pszVisName = gacd[i].pszIniName;
  292. }
  293. }
  294. }
  295. /*
  296. * As an optimization, remember the window handles of the cursor
  297. * information fields.
  298. */
  299. ghwndPreview = GetDlgItem(hwnd, ID_PREVIEW);
  300. ghwndFile = GetDlgItem(hwnd, ID_FILE);
  301. ghwndFileH = GetDlgItem(hwnd, ID_FILEH);
  302. ghwndTitle = GetDlgItem(hwnd, ID_TITLE);
  303. ghwndTitleH = GetDlgItem(hwnd, ID_TITLEH);
  304. ghwndCreator = GetDlgItem(hwnd, ID_CREATOR);
  305. ghwndCreatorH = GetDlgItem(hwnd, ID_CREATORH);
  306. ghwndLB = GetDlgItem(hwnd, ID_CURSORLIST);
  307. ghwndSchemeCB = GetDlgItem(hwnd, ID_SCHEMECOMBO);
  308. /*
  309. * Create some brushes we'll be using.
  310. */
  311. CreateBrushes();
  312. // ErikGav -
  313. // Initialize the scheme list box
  314. InitSchemeComboBox();
  315. /*
  316. * Get a nice small font for some of the controls.
  317. * LATER: How many of these fields do I really need to initialize?
  318. */
  319. memset(&lf, 0, sizeof(LOGFONT));
  320. strcpy(lf.lfFaceName, "Helv");
  321. lf.lfHeight = 8;
  322. lf.lfWeight = FW_NORMAL;
  323. lf.lfCharSet = ANSI_CHARSET;
  324. lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  325. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  326. lf.lfQuality = DEFAULT_QUALITY;
  327. ghfontLabels = CreateFontIndirect(&lf);
  328. /*
  329. * Change the font for the info fields.
  330. */
  331. SendMessage(ghwndFile, WM_SETFONT, (DWORD)ghfontLabels, FALSE);
  332. SendMessage(ghwndTitle, WM_SETFONT, (DWORD)ghfontLabels, FALSE);
  333. SendMessage(ghwndCreator, WM_SETFONT, (DWORD)ghfontLabels, FALSE);
  334. /*
  335. * Pre-clear the cursor info array.
  336. */
  337. memset(acuri, 0, sizeof(acuri));
  338. /*
  339. * Loop through all cursors checking WIN.INI to see if they've been
  340. * superceded by a 'soft' cursor. If so, get the soft cursor's filename.
  341. */
  342. for (pcuri = &acuri[0], i = 0; i < CCURSORS; i++, pcuri++) {
  343. GetProfileString("Cursors", gacd[i].pszIniName, "", pcuri->szFile,
  344. sizeof(pcuri->szFile));
  345. if ( (*(pcuri->szFile) == '\0') || !TryToLoadCursor(hwnd,i,pcuri))
  346. {
  347. /*
  348. * The cursor is either not redirected, or we could not load
  349. * the file, either way we should use the default system cursor.
  350. */
  351. pcuri->hcur = LoadCursor(NULL, gacd[i].idResource);
  352. GetCursorInfo(pcuri->hcur, NULL, 0, &dwDummy, &pcuri->ccur);
  353. if (pcuri->ccur > 1) {
  354. pcuri->fl |= CIF_ANICURSOR;
  355. }
  356. }
  357. SendMessage(ghwndLB, LB_ADDSTRING, 0, i);
  358. }
  359. /*
  360. * Select the first cursor in the list ('Arrow').
  361. */
  362. SendMessage(ghwndLB, LB_SETCURSEL, 0, 0);
  363. /*
  364. * Force an update of the preview window and the cursor details.
  365. */
  366. UpdateCursorList();
  367. gnMsgLBSelChString = RegisterWindowMessage(LBSELCHSTRING);
  368. gnMsgFileOK = RegisterWindowMessage(FILEOKSTRING);
  369. return TRUE;
  370. }
  371. /*****************************************************************************\
  372. * CreateBrushes
  373. *
  374. * Creates the brushes that are used to paint within the Cursors applet.
  375. *
  376. \*****************************************************************************/
  377. VOID
  378. CreateBrushes(
  379. VOID
  380. )
  381. {
  382. ghbrHighlight = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
  383. gcrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
  384. ghbrHighlightText = CreateSolidBrush(gcrHighlightText);
  385. ghbrWindow = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  386. }
  387. /*****************************************************************************\
  388. * DestroyBrushes
  389. *
  390. * Cleans up the brushes that were used to paint within the Cursors applet.
  391. *
  392. \*****************************************************************************/
  393. VOID
  394. DestroyBrushes(
  395. VOID
  396. )
  397. {
  398. DeleteObject(ghbrHighlight);
  399. DeleteObject(ghbrHighlightText);
  400. DeleteObject(ghbrWindow);
  401. }
  402. /*****************************************************************************\
  403. * LPTSTR GetResourceString(HINSTANCE hmod, int id);
  404. *
  405. * Gets a string out of the resouce file.
  406. *
  407. \*****************************************************************************/
  408. LPTSTR GetResourceString(HINSTANCE hmod, int id) {
  409. TCHAR szBuffer[256];
  410. LPTSTR psz;
  411. int cch;
  412. if ( (cch = LoadString(hmod, id, szBuffer, sizeof(szBuffer) /
  413. sizeof(TCHAR) )) == 0){
  414. return NULL;
  415. }
  416. psz = LocalAlloc(LPTR, cch * sizeof(TCHAR));
  417. if (psz != NULL) {
  418. int i;
  419. for( i = 0; i <= cch; i++ ) {
  420. psz[i] = (szBuffer[i] == TEXT('\1')) ?
  421. TEXT('\0') : szBuffer[i];
  422. }
  423. }
  424. return psz;
  425. }
  426. /***************************************************************************\
  427. * CursorsDlgProc
  428. *
  429. *
  430. * History:
  431. * 12-22-91 DarrinM Created.
  432. \***************************************************************************/
  433. INT_PTR CALLBACK
  434. CursorsDlgProc(
  435. HWND hwnd,
  436. UINT msg,
  437. WPARAM wParam,
  438. LPARAM lParam
  439. )
  440. {
  441. CURSORINFO *pcuri;
  442. DWORD dwDummy;
  443. HDWP hdwp;
  444. INT i;
  445. switch (msg) {
  446. case WM_INITDIALOG:
  447. ghwndDlg = hwnd;
  448. if(!InitCursorsDlg(hwnd)) {
  449. MessageBox(hwnd, gszNoMem, NULL, MB_ICONSTOP | MB_OK);
  450. EndDialog(hwnd, 0);
  451. }
  452. break;
  453. case WM_MEASUREITEM:
  454. ((MEASUREITEMSTRUCT *)lParam)->itemHeight = gcyCursor + 2;
  455. break;
  456. case WM_DRAWITEM:
  457. DrawCursorListItem((DRAWITEMSTRUCT *)lParam);
  458. break;
  459. case WM_COMMAND:
  460. switch (LOWORD(wParam)) {
  461. case ID_SCHEMECOMBO:
  462. switch (HIWORD(wParam))
  463. {
  464. case CBN_SELCHANGE:
  465. LoadScheme();
  466. break;
  467. }
  468. break;
  469. case ID_DEFAULT:
  470. /*
  471. * Throw away any fancy new cursor and replace it with the
  472. * system's original.
  473. */
  474. i = SendMessage(ghwndLB, LB_GETCURSEL, 0, 0);
  475. pcuri = &acuri[i];
  476. if (!(pcuri->fl & CIF_FILE))
  477. break;
  478. pcuri->fl = CIF_MODIFIED;
  479. if (pcuri->hcur != NULL)
  480. DestroyCursor(pcuri->hcur);
  481. pcuri->hcur = GetCursorInfo(NULL, (LPWSTR)gacd[i].idResource, 0,
  482. &dwDummy, (LPINT)&dwDummy);
  483. *pcuri->szFile = '\0';
  484. EnableWindow(GetDlgItem(hwnd, ID_SAVESCHEME), TRUE);
  485. UpdateCursorList();
  486. break;
  487. case ID_CURSORLIST:
  488. switch (HIWORD(wParam)) {
  489. case LBN_SELCHANGE:
  490. i = SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0);
  491. pcuri = &acuri[i];
  492. /*
  493. * Show a preview (including animation) in the preview window.
  494. */
  495. PreviewWndProc(ghwndPreview, PM_NEWCURSOR, 0, (LPARAM)pcuri);
  496. /*
  497. * Show/Hide and update if necessary the information text
  498. * controls that show the cursor's filename, title, and
  499. * creator.
  500. */
  501. hdwp = BeginDeferWindowPos(6);
  502. if (pcuri->fl & CIF_TITLE) {
  503. SetWindowText(ghwndTitle, pcuri->szTitle);
  504. hdwp = DeferWindowPos(hdwp, ghwndTitleH, NULL, 0, 0, 0, 0,
  505. SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE);
  506. hdwp = DeferWindowPos(hdwp, ghwndTitle, NULL, 0, 0, 0, 0,
  507. SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE);
  508. } else {
  509. hdwp = DeferWindowPos(hdwp, ghwndTitleH, NULL, 0, 0, 0, 0,
  510. SWP_HIDEWINDOW | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE);
  511. hdwp = DeferWindowPos(hdwp, ghwndTitle, NULL, 0, 0, 0, 0,
  512. SWP_HIDEWINDOW | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE);
  513. }
  514. if (pcuri->fl & CIF_CREATOR) {
  515. SetWindowText(ghwndCreator, pcuri->szCreator);
  516. hdwp = DeferWindowPos(hdwp, ghwndCreatorH, NULL, 0, 0, 0, 0,
  517. SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE);
  518. hdwp = DeferWindowPos(hdwp, ghwndCreator, NULL, 0, 0, 0, 0,
  519. SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE);
  520. } else {
  521. hdwp = DeferWindowPos(hdwp, ghwndCreatorH, NULL, 0, 0, 0, 0,
  522. SWP_HIDEWINDOW | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE);
  523. hdwp = DeferWindowPos(hdwp, ghwndCreator, NULL, 0, 0, 0, 0,
  524. SWP_HIDEWINDOW | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE);
  525. }
  526. if (pcuri->fl & CIF_FILE) {
  527. SetWindowText(ghwndFile, pcuri->szFile);
  528. hdwp = DeferWindowPos(hdwp, ghwndFileH, NULL, 0, 0, 0, 0,
  529. SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE);
  530. hdwp = DeferWindowPos(hdwp, ghwndFile, NULL, 0, 0, 0, 0,
  531. SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE);
  532. } else {
  533. hdwp = DeferWindowPos(hdwp, ghwndFileH, NULL, 0, 0, 0, 0,
  534. SWP_HIDEWINDOW | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE);
  535. hdwp = DeferWindowPos(hdwp, ghwndFile, NULL, 0, 0, 0, 0,
  536. SWP_HIDEWINDOW | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE);
  537. }
  538. EndDeferWindowPos(hdwp);
  539. //
  540. // Enable the "Set Default" button if the cursor is
  541. // from a file.
  542. //
  543. EnableWindow(GetDlgItem(hwnd, ID_DEFAULT),
  544. (pcuri->fl & CIF_FILE) ? TRUE : FALSE);
  545. break;
  546. case LBN_DBLCLK:
  547. Browse(hwnd);
  548. break;
  549. }
  550. break;
  551. case ID_BROWSE:
  552. Browse(hwnd);
  553. break;
  554. case IDD_HELP:
  555. goto DoHelp;
  556. case IDOK:
  557. /*
  558. * change cursor to hourglass
  559. */
  560. HourGlass(TRUE);
  561. // Save the modified scheme
  562. SaveScheme();
  563. /*
  564. * Save any modified cursor information to WIN.INI.
  565. */
  566. for (pcuri = &acuri[0], i = 0; i < CCURSORS; i++, pcuri++) {
  567. // if (pcuri->fl & CIF_MODIFIED) {
  568. WriteProfileString("Cursors", gacd[i].pszIniName,
  569. pcuri->fl & CIF_FILE ? pcuri->szFile : NULL);
  570. SetSystemCursor(pcuri->hcur, (DWORD)gacd[i].idResource);
  571. // }
  572. }
  573. HourGlass(FALSE);
  574. /*
  575. * Free everything.
  576. */
  577. CleanUpEverything();
  578. EndDialog(hwnd, 0L);
  579. break;
  580. case IDCANCEL:
  581. /*
  582. * Don't leave a mess.
  583. */
  584. CleanUpEverything();
  585. EndDialog(hwnd, 0L);
  586. break;
  587. case ID_SAVESCHEME:
  588. SaveSchemeAs();
  589. break;
  590. case ID_REMOVESCHEME:
  591. RemoveScheme();
  592. break;
  593. }
  594. break;
  595. case WM_SYSCOLORCHANGE:
  596. //
  597. // Recreate the brushes with the new colors.
  598. //
  599. DestroyBrushes();
  600. CreateBrushes();
  601. break;
  602. default:
  603. if (msg == wHelpMessage || msg == wBrowseHelpMessage)
  604. {
  605. DoHelp:
  606. CPHelp(hwnd);
  607. return TRUE;
  608. }
  609. else
  610. return FALSE;
  611. break;
  612. }
  613. return TRUE;
  614. }
  615. /***************************************************************************\
  616. * DrawCursorListItem
  617. *
  618. *
  619. * History:
  620. * 12-22-91 DarrinM Created.
  621. \***************************************************************************/
  622. void DrawCursorListItem(
  623. DRAWITEMSTRUCT *pdis)
  624. {
  625. CURSORINFO *pcuri;
  626. COLORREF crPrev;
  627. /*
  628. * LATER: Deal with focus rect.
  629. */
  630. if (pdis->itemAction == ODA_FOCUS)
  631. return;
  632. SetBkMode(pdis->hDC, TRANSPARENT);
  633. pcuri = &acuri[pdis->itemData];
  634. if (pdis->itemState & ODS_SELECTED) {
  635. FillRect(pdis->hDC, &pdis->rcItem, ghbrHighlight);
  636. crPrev = SetTextColor(pdis->hDC, gcrHighlightText);
  637. } else {
  638. FillRect(pdis->hDC, &pdis->rcItem, ghbrWindow);
  639. }
  640. if (pcuri->hcur != NULL) {
  641. DrawIcon(pdis->hDC, pdis->rcItem.left + 2, pdis->rcItem.top + 1,
  642. pcuri->hcur);
  643. }
  644. pdis->rcItem.left += gcxCursor + 2 + gcxAvgChar;
  645. DrawText(pdis->hDC, gacd[pdis->itemData].pszVisName,
  646. strlen(gacd[pdis->itemData].pszVisName), &pdis->rcItem,
  647. DT_SINGLELINE | DT_LEFT | DT_VCENTER);
  648. if (pdis->itemState & ODS_SELECTED) {
  649. SetTextColor(pdis->hDC, crPrev);
  650. }
  651. }
  652. /***************************************************************************\
  653. * TryToLoadCursor
  654. *
  655. *
  656. * History:
  657. * 01-28-93 JonPa Created.
  658. \***************************************************************************/
  659. BOOL TryToLoadCursor(
  660. HWND hwnd,
  661. int i,
  662. CURSORINFO *pcuri)
  663. {
  664. DWORD dwDummy;
  665. BOOL fRet = TRUE;
  666. if (!GetCursorFromFile(pcuri)) {
  667. HWND hwndControl = GetParent(hwnd);
  668. LPSTR pszText;
  669. pszText = LocalAlloc(LPTR, strlen(gszFileNotFound) +
  670. strlen(gacd[i].pszVisName) + strlen(pcuri->szFile));
  671. if (pszText == NULL)
  672. return FALSE;
  673. wsprintf(pszText, gszFileNotFound, pcuri->szFile, gacd[i].pszVisName);
  674. /* do a little multimedia action here */
  675. MessageBeep(MB_ICONEXCLAMATION);
  676. if(MessageBox(hwndControl, pszText, NULL,
  677. MB_ICONEXCLAMATION | MB_YESNO) == IDYES) {
  678. /*
  679. * Cursor file is bad or can't be found. User wants to
  680. * reset registry to use the default instead.
  681. */
  682. pcuri->fl = CIF_MODIFIED;
  683. if (pcuri->hcur != NULL)
  684. DestroyCursor(pcuri->hcur);
  685. pcuri->hcur = GetCursorInfo(NULL, (LPWSTR)gacd[i].idResource, 0,
  686. &dwDummy, (LPINT)&dwDummy);
  687. GetCursorInfo(pcuri->hcur, NULL, 0, &dwDummy, &pcuri->ccur);
  688. if (pcuri->ccur > 1) {
  689. pcuri->fl |= CIF_ANICURSOR;
  690. }
  691. } else {
  692. /* load file failed, use the default */
  693. fRet = FALSE;
  694. }
  695. LocalFree(pszText);
  696. }
  697. /* Load file worked! Display what we read */
  698. return fRet;
  699. }
  700. /***************************************************************************\
  701. * GetCursorFromFile
  702. *
  703. *
  704. * History:
  705. * 12-25-91 DarrinM Created.
  706. * 03-25-93 JonPa Rewote to use RIFF format
  707. \***************************************************************************/
  708. BOOL GetCursorFromFile(
  709. CURSORINFO *pcuri)
  710. {
  711. HANDLE hf;
  712. RTAG tag;
  713. DWORD cbRead;
  714. BOOL fBadCur = FALSE;
  715. ANIHEADER anih;
  716. pcuri->fl = 0;
  717. hf = CreateFile(MakeFilename(pcuri->szFile), GENERIC_READ, FILE_SHARE_READ, NULL,
  718. OPEN_EXISTING, 0, NULL);
  719. if (hf == INVALID_HANDLE_VALUE) {
  720. pcuri->fl |= CIF_FILE;
  721. return FALSE;
  722. }
  723. /*
  724. * Determine if this is an .ICO/.CUR file or an .ANI file.
  725. */
  726. if (ReadTag(hf, &tag) && tag.ckID == FOURCC_RIFF &&
  727. ReadFile(hf, &tag.ckID, sizeof(tag.ckID), &cbRead, NULL) &&
  728. cbRead >= sizeof(tag.ckID) && tag.ckID == FOURCC_ACON) {
  729. BOOL fNeedANI = TRUE;
  730. BOOL fNeedInfo = TRUE;
  731. /*
  732. * It's an ANICURSOR!
  733. *
  734. * Search for each chunk (LIST, anih, rate, seq, and icon).
  735. * while we search, we will assume the ani file is bad.
  736. */
  737. fBadCur = TRUE;
  738. while((fNeedANI || fNeedInfo) && ReadTag(hf, &tag)) {
  739. if( tag.ckID == FOURCC_LIST) {
  740. /* look for type INFO */
  741. DWORD cbChunk = (tag.ckSize + 1) & ~1;
  742. if (ReadFile(hf, &tag.ckID, sizeof(tag.ckID), &cbRead, NULL) &&
  743. cbRead >= sizeof(tag.ckID) && tag.ckID == FOURCC_INFO){
  744. // I think this should be here???
  745. cbChunk -= cbRead;
  746. /* now look for INAM and IART chunks */
  747. while( cbChunk >= sizeof(tag) &&
  748. ((pcuri->fl & (CIF_TITLE | CIF_CREATOR)) !=
  749. (CIF_TITLE | CIF_CREATOR))) {
  750. if (!ReadTag(hf, &tag))
  751. goto gcffExit;
  752. cbChunk -= sizeof(tag);
  753. switch( tag.ckID ) {
  754. case FOURCC_INAM:
  755. if (cbChunk < tag.ckSize ||
  756. !ReadChunkN(hf, &tag, pcuri->szTitle,
  757. sizeof(pcuri->szTitle)))
  758. goto gcffExit;
  759. pcuri->fl |= CIF_TITLE;
  760. cbChunk -= (tag.ckSize + 1) & ~1;
  761. break;
  762. case FOURCC_IART:
  763. if (cbChunk < tag.ckSize ||
  764. !ReadChunkN(hf, &tag, pcuri->szCreator,
  765. sizeof(pcuri->szCreator)))
  766. goto gcffExit;
  767. pcuri->fl |= CIF_CREATOR;
  768. cbChunk -= (tag.ckSize + 1) & ~1;
  769. break;
  770. default:
  771. cbChunk -= Skip( hf, tag.ckSize );
  772. break;
  773. }
  774. }
  775. fNeedInfo = FALSE;
  776. if (cbChunk != 0) {
  777. // This is right, isn't it?
  778. Skip( hf, cbChunk );
  779. }
  780. } else {
  781. Skip( hf, cbChunk - cbRead);
  782. }
  783. } else if (tag.ckID == FOURCC_anih) {
  784. if (!ReadChunk(hf, &tag, &anih))
  785. goto gcffExit;
  786. if (!(anih.fl & AF_ICON) || (anih.cFrames == 0))
  787. goto gcffExit;
  788. fNeedANI = FALSE;
  789. } else {
  790. Skip(hf, tag.ckSize);
  791. }
  792. }
  793. /* if we get here, it must be a real ani cursor */
  794. fBadCur = FALSE;
  795. pcuri->fl |= CIF_ANICURSOR;
  796. }
  797. gcffExit:
  798. CloseHandle(hf);
  799. if (!fBadCur) {
  800. pcuri->hcur = LoadCursorFromFile(MakeFilename(pcuri->szFile));
  801. GetCursorInfo(pcuri->hcur, NULL, 0, &cbRead, &pcuri->ccur);
  802. pcuri->fl |= CIF_FILE;
  803. }
  804. return fBadCur ? FALSE : pcuri->hcur != NULL;
  805. }
  806. /***************************************************************************\
  807. * Browse
  808. *
  809. * Browse the file system for a new cursor for the selected item.
  810. *
  811. * History:
  812. * 12-25-91 DarrinM Created.
  813. \***************************************************************************/
  814. BOOL Browse(
  815. HWND hwndOwner)
  816. {
  817. static OPENFILENAME ofn;
  818. static char szCustomFilter[80];
  819. CHAR szSystemDir[MAX_PATH];
  820. CURSORINFO curi;
  821. int i;
  822. DWORD dwContextSave;
  823. HOOKPROC lpfnMsgFilterHookFunc; // The message filter proc instance.
  824. BOOL fRet = FALSE;
  825. /*
  826. * Hook the message filter stream so that we can detect F1 keystrokes.
  827. */
  828. lpfnMsgFilterHookFunc =
  829. MakeProcInstance((HOOKPROC)MsgFilterHookFunc, ghInst);
  830. ghhkMsgFilter =
  831. SetWindowsHook(WH_MSGFILTER, lpfnMsgFilterHookFunc);
  832. ofn.lStructSize = sizeof(ofn);
  833. ofn.hwndOwner = hwndOwner;
  834. ofn.hInstance = ghmod;
  835. ofn.lpstrFilter = gszFilter;
  836. ofn.lpstrCustomFilter = szCustomFilter;
  837. ofn.nMaxCustFilter = sizeof(szCustomFilter);
  838. ofn.nFilterIndex = 1;
  839. gszFileName[0] = 0;
  840. ofn.lpstrFile = gszFileName;
  841. ofn.nMaxFile = sizeof(gszFileName);
  842. ofn.lpstrFileTitle = NULL;
  843. ofn.nMaxFileTitle = 0;
  844. GetSystemDirectory(szSystemDir, MAX_PATH);
  845. ofn.lpstrInitialDir = szSystemDir;
  846. ofn.lpstrTitle = gszBrowse;
  847. ofn.Flags = OFN_SHOWHELP | OFN_FILEMUSTEXIST |
  848. OFN_HIDEREADONLY | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK;
  849. ofn.lpstrDefExt = NULL;
  850. ofn.lpfnHook = OpenFileNameHookDlgProc;
  851. ofn.lpTemplateName = MAKEINTRESOURCE(DLG_FILEOPEN);
  852. SendDlgItemMessage(hwndOwner, ID_PREVIEW, PM_PAUSEANIMATION, 0, 0);
  853. dwContextSave = dwContext;
  854. dwContext = IDH_DLG_CURBROWSE;
  855. if (!GetOpenFileName(&ofn))
  856. {
  857. dwContext = dwContextSave;
  858. SendDlgItemMessage(hwndOwner, ID_PREVIEW, PM_UNPAUSEANIMATION, 0, 0);
  859. goto brErrExit;
  860. }
  861. dwContext = dwContextSave;
  862. strcpy(curi.szFile, gszFileName);
  863. if (!GetCursorFromFile(&curi))
  864. goto brErrExit;
  865. i = SendMessage(ghwndLB, LB_GETCURSEL, 0, 0);
  866. curi.fl |= CIF_MODIFIED;
  867. EnableWindow(GetDlgItem(ghwndDlg, ID_SAVESCHEME), TRUE);
  868. /*
  869. * Destroy the old cursor before we retain the new one.
  870. */
  871. DestroyCursor(acuri[i].hcur);
  872. acuri[i] = curi;
  873. UpdateCursorList();
  874. fRet = TRUE;
  875. brErrExit:
  876. if (ghhkMsgFilter != NULL) {
  877. UnhookWindowsHook(WH_MSGFILTER, lpfnMsgFilterHookFunc);
  878. FreeProcInstance(lpfnMsgFilterHookFunc);
  879. }
  880. return fRet;
  881. }
  882. /*****************************************************************************\
  883. * OpenFileNameHookDlgProc
  884. *
  885. * Hook function for the GetOpenFileName common dialog function.
  886. * Used to make the preview window work.
  887. *
  888. \*****************************************************************************/
  889. UINT_PTR CALLBACK
  890. OpenFileNameHookDlgProc(
  891. HWND hwnd,
  892. UINT msg,
  893. WPARAM wParam,
  894. LPARAM lParam
  895. )
  896. {
  897. static CURSORINFO curiPreview;
  898. static BOOL fInSelMode;
  899. if (msg == gnMsgLBSelChString && wParam == lst1)
  900. {
  901. fInSelMode = TRUE;
  902. PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDOK, 0),
  903. (LPARAM)GetDlgItem(hwnd, IDOK));
  904. }
  905. else if (msg == gnMsgFileOK)
  906. {
  907. if (fInSelMode)
  908. {
  909. HCURSOR hcurOld;
  910. PCURSORINFO pcuri;
  911. hcurOld = curiPreview.hcur;
  912. strcpy(curiPreview.szFile, gszFileName);
  913. if (GetCursorFromFile(&curiPreview))
  914. pcuri = &curiPreview;
  915. else
  916. pcuri = NULL;
  917. if (hcurOld)
  918. {
  919. DestroyCursor(hcurOld);
  920. }
  921. /*
  922. * Show a preview (including animation) in the preview window,
  923. * or else clear the preview window (if pcuri is NULL).
  924. */
  925. SendMessage(GetDlgItem(hwnd, ID_PREVIEW), PM_NEWCURSOR,
  926. 0, (LPARAM)pcuri);
  927. fInSelMode = FALSE;
  928. //
  929. // Do NOT close the dialog.
  930. //
  931. return 1;
  932. }
  933. else
  934. {
  935. //
  936. // OK to close the dialog.
  937. //
  938. return 0;
  939. }
  940. }
  941. else
  942. {
  943. switch (msg)
  944. {
  945. case WM_INITDIALOG:
  946. curiPreview.hcur = 0;
  947. fInSelMode = FALSE;
  948. return TRUE;
  949. case WM_DESTROY:
  950. if (curiPreview.hcur)
  951. {
  952. DestroyCursor(curiPreview.hcur);
  953. curiPreview.hcur = 0;
  954. }
  955. break;
  956. }
  957. }
  958. return FALSE;
  959. }
  960. /***************************************************************************\
  961. * CleanUpEverything
  962. *
  963. * Destroy all the outstanding cursors.
  964. *
  965. * History:
  966. * 12-25-91 DarrinM Created.
  967. \***************************************************************************/
  968. void CleanUpEverything(void)
  969. {
  970. CURSORINFO *pcuri;
  971. int i;
  972. for (pcuri = &acuri[0], i = 0; i < CCURSORS; i++, pcuri++) {
  973. if (pcuri->hcur != NULL)
  974. DestroyCursor(pcuri->hcur);
  975. }
  976. DestroyBrushes();
  977. DeleteObject(ghfontLabels);
  978. }
  979. /***************************************************************************\
  980. * UpdateCursorList
  981. *
  982. * Force the Cursor ListBox to repaint and the cursor information below the
  983. * listbox to be refreshed as well.
  984. *
  985. * History:
  986. * 12-25-91 DarrinM Created.
  987. \***************************************************************************/
  988. VOID
  989. UpdateCursorList(
  990. VOID
  991. )
  992. {
  993. InvalidateRect(ghwndLB, NULL, FALSE);
  994. SendMessage(ghwndDlg, WM_COMMAND, MAKELONG(ID_CURSORLIST, LBN_SELCHANGE),
  995. (LPARAM)ghwndLB);
  996. }
  997. /***************************************************************************\
  998. * PreviewWndProc
  999. *
  1000. *
  1001. * History:
  1002. * 08-07-92 DarrinM Created.
  1003. \***************************************************************************/
  1004. LRESULT CALLBACK
  1005. PreviewWndProc(
  1006. HWND hwnd,
  1007. UINT msg,
  1008. WPARAM wParam,
  1009. LPARAM lParam
  1010. )
  1011. {
  1012. HDC hdc;
  1013. RECT rc;
  1014. int ccur;
  1015. JIF jifRate;
  1016. HCURSOR hcur;
  1017. PAINTSTRUCT ps;
  1018. PPREVIEWDATA ppd;
  1019. switch (msg) {
  1020. case WM_CREATE:
  1021. if (!(ppd = (PPREVIEWDATA)LocalAlloc(LPTR, sizeof(PREVIEWDATA))))
  1022. return -1;
  1023. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)ppd);
  1024. /*
  1025. * Create a temp DC and bitmap to be used for buffering the
  1026. * preview rendering.
  1027. */
  1028. hdc = GetDC(hwnd);
  1029. ppd->hdcMem = CreateCompatibleDC(hdc);
  1030. ppd->hbmMem = CreateCompatibleBitmap(hdc, gcxCursor, gcyCursor);
  1031. ppd->hbmOld = SelectObject(ppd->hdcMem, ppd->hbmMem);
  1032. ppd->pcuri = NULL;
  1033. ReleaseDC(hwnd, hdc);
  1034. break;
  1035. case WM_DESTROY:
  1036. ppd = (PPREVIEWDATA)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1037. SelectObject(ppd->hdcMem, ppd->hbmOld);
  1038. DeleteObject(ppd->hbmMem);
  1039. DeleteDC(ppd->hdcMem);
  1040. LocalFree(ppd);
  1041. break;
  1042. case PM_NEWCURSOR:
  1043. KillTimer(hwnd, ID_PREVIEWTIMER);
  1044. ppd = (PPREVIEWDATA)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1045. ppd->pcuri = (PCURSORINFO)lParam;
  1046. if (ppd->pcuri)
  1047. {
  1048. if (ppd->pcuri->fl & CIF_ANICURSOR)
  1049. {
  1050. ppd->pcuri->icur = 0;
  1051. GetCursorInfo(ppd->pcuri->hcur, NULL, 0, &jifRate, &ccur);
  1052. SetTimer(hwnd, ID_PREVIEWTIMER, jifRate * 16, NULL);
  1053. }
  1054. }
  1055. InvalidateRect(hwnd, NULL, FALSE);
  1056. break;
  1057. case PM_PAUSEANIMATION:
  1058. KillTimer(hwnd, ID_PREVIEWTIMER);
  1059. break;
  1060. case PM_UNPAUSEANIMATION:
  1061. NextFrame(hwnd);
  1062. break;
  1063. case WM_TIMER:
  1064. if (wParam != ID_PREVIEWTIMER)
  1065. break;
  1066. NextFrame(hwnd);
  1067. break;
  1068. case WM_PAINT:
  1069. BeginPaint(hwnd, &ps);
  1070. ppd = (PPREVIEWDATA)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1071. if (ppd->pcuri && ppd->pcuri->hcur != NULL)
  1072. {
  1073. rc.left = rc.top = 0;
  1074. rc.right = gcxCursor;
  1075. rc.bottom = gcyCursor;
  1076. FillRect(ppd->hdcMem, &rc, ghbrWindow);
  1077. hcur = GetCursorInfo(ppd->pcuri->hcur, NULL, ppd->pcuri->icur,
  1078. &jifRate, &ccur);
  1079. DrawIcon(ppd->hdcMem, 0, 0, hcur);
  1080. BitBlt(ps.hdc, 0, 0, gcxCursor, gcyCursor, ppd->hdcMem,
  1081. 0, 0, SRCCOPY);
  1082. }
  1083. else
  1084. {
  1085. FillRect(ps.hdc, &ps.rcPaint, ghbrWindow);
  1086. }
  1087. EndPaint(hwnd, &ps);
  1088. break;
  1089. case WM_ERASEBKGND:
  1090. break;
  1091. default:
  1092. return DefWindowProc(hwnd, msg, wParam, lParam);
  1093. }
  1094. return 0;
  1095. }
  1096. /*****************************************************************************\
  1097. * NextFrame
  1098. *
  1099. * Sets up for the next frame in the preview window.
  1100. *
  1101. * Arguments:
  1102. * HWND hwnd - Dialog window handle.
  1103. *
  1104. \*****************************************************************************/
  1105. VOID
  1106. NextFrame(
  1107. HWND hwnd
  1108. )
  1109. {
  1110. INT ccur;
  1111. JIF jifRate;
  1112. PPREVIEWDATA ppd;
  1113. ppd = (PPREVIEWDATA)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1114. //
  1115. // Be sure there is a cursor specified. If not, or it is
  1116. // not an animated cursor, we are done.
  1117. //
  1118. if (!ppd->pcuri || !(ppd->pcuri->fl & CIF_ANICURSOR))
  1119. return;
  1120. if (++(ppd->pcuri->icur) >= ppd->pcuri->ccur)
  1121. ppd->pcuri->icur = 0;
  1122. /*
  1123. * Find how long this frame should be displayed (i.e. get jifRate)
  1124. */
  1125. GetCursorInfo(ppd->pcuri->hcur, NULL, ppd->pcuri->icur, &jifRate, &ccur);
  1126. SetTimer(hwnd, ID_PREVIEWTIMER, jifRate * 16, NULL);
  1127. /*
  1128. * Redraw this frame of the cursor.
  1129. */
  1130. InvalidateRect(hwnd, NULL, FALSE);
  1131. }
  1132. /***************************************************************************\
  1133. * ReadTag, ReadChunk, SkipChunk
  1134. *
  1135. * Some handy functions for reading RIFF files.
  1136. *
  1137. * History:
  1138. * 10-02-91 DarrinM Created.
  1139. * 03-25-93 Jonpa Changed to use RIFF format instead of ASDF
  1140. \***************************************************************************/
  1141. BOOL ReadTag(
  1142. HANDLE hf,
  1143. PRTAG ptag)
  1144. {
  1145. DWORD cbActual;
  1146. ptag->ckID = ptag->ckSize = 0L;
  1147. if (!ReadFile(hf, ptag, sizeof(RTAG), &cbActual, NULL) ||
  1148. (cbActual != sizeof(RTAG)))
  1149. return FALSE;
  1150. /* no need to align file pointer since RTAG is already word aligned */
  1151. return TRUE;
  1152. }
  1153. BOOL ReadChunk(
  1154. HANDLE hf,
  1155. PRTAG ptag,
  1156. PVOID pv)
  1157. {
  1158. DWORD cbActual;
  1159. if (!ReadFile(hf, pv, ptag->ckSize, &cbActual, NULL) ||
  1160. (cbActual != ptag->ckSize))
  1161. return FALSE;
  1162. /* WORD align file pointer */
  1163. if( ptag->ckSize & 1 )
  1164. SetFilePointer(hf, 1, NULL, FILE_CURRENT);
  1165. return TRUE;
  1166. }
  1167. BOOL ReadChunkN(
  1168. HANDLE hf,
  1169. PRTAG ptag,
  1170. PVOID pv,
  1171. DWORD cbMax)
  1172. {
  1173. DWORD cbActual;
  1174. DWORD cbRead = min( cbMax, ptag->ckSize );
  1175. if (!ReadFile(hf, pv, ptag->ckSize, &cbActual, NULL) ||
  1176. (cbActual != cbRead))
  1177. return FALSE;
  1178. /* WORD align file pointer */
  1179. // this is right isn't it?
  1180. cbRead = ptag->ckSize - cbActual;
  1181. if( ptag->ckSize & 1 )
  1182. cbRead++;
  1183. return SetFilePointer(hf, cbRead, NULL, FILE_CURRENT) != 0xFFFFFFFF;
  1184. }
  1185. DWORD Skip(
  1186. HANDLE hf,
  1187. DWORD cbSkip)
  1188. {
  1189. /* Round cbSize up to nearest word boundary to maintain alignment */
  1190. DWORD cb = (cbSkip + 1) & ~1;
  1191. if (SetFilePointer(hf, cb, NULL, FILE_CURRENT) == 0xFFFFFFFF)
  1192. cb = 0;
  1193. return cb;
  1194. }
  1195. /***************************************************************************\
  1196. * HourGlass
  1197. *
  1198. * Turn hourglass cursor on or off.
  1199. *
  1200. * History:
  1201. * 07-30-92 DarrinM Pulled from control\main\util.c
  1202. \***************************************************************************/
  1203. void HourGlass(BOOL fOn)
  1204. {
  1205. if (!GetSystemMetrics (SM_MOUSEPRESENT))
  1206. ShowCursor (fOn);
  1207. SetCursor (LoadCursor (NULL, fOn ? IDC_WAIT : IDC_ARROW));
  1208. }
  1209. /************************************************************************
  1210. * MsgFilterHookFunc
  1211. *
  1212. * This is the exported message filter function that is hooked into
  1213. * the message stream for detecting the pressing of the F1 key, at
  1214. * which time it calls up the appropriate help.
  1215. *
  1216. * Arguments:
  1217. *
  1218. * History:
  1219. *
  1220. ************************************************************************/
  1221. DWORD FAR PASCAL MsgFilterHookFunc(
  1222. INT nCode,
  1223. WPARAM wParam,
  1224. LPMSG lpMsg)
  1225. {
  1226. if ((nCode == MSGF_MENU || nCode == MSGF_DIALOGBOX) &&
  1227. (lpMsg->message == WM_KEYDOWN && lpMsg->wParam == VK_F1)) {
  1228. /*
  1229. * Display help.
  1230. */
  1231. CPHelp(lpMsg->hwnd);
  1232. /*
  1233. * Tell Windows to swallow this message.
  1234. */
  1235. return 1;
  1236. }
  1237. return DefHookProc(nCode, wParam, (LONG)lpMsg, &ghhkMsgFilter);
  1238. }
  1239. /***************************************************************************\
  1240. * Scheme Functions
  1241. *
  1242. * History:
  1243. * 04-10-93 ErikGav Created
  1244. \***************************************************************************/
  1245. BOOL SaveSchemeAs()
  1246. {
  1247. BOOL fSuccess=TRUE;
  1248. LRESULT lr;
  1249. // dialog proc returns TRUE & sets filename entered
  1250. // to gszSchemeName if OK clicked
  1251. if (DialogBox (ghmod, MAKEINTRESOURCE(DLG_SCHEMESAVE), ghwndDlg, SaveSchemeDlgProc))
  1252. {
  1253. lr = SendMessage(ghwndSchemeCB,CB_FINDSTRINGEXACT,0xFFFF,(LPARAM) gszSchemeName);
  1254. // if not found, add it
  1255. if (lr==CB_ERR)
  1256. {
  1257. lr = SendMessage(ghwndSchemeCB,CB_ADDSTRING,0,(LPARAM) gszSchemeName);
  1258. }
  1259. // select the name
  1260. SendMessage(ghwndSchemeCB,CB_SETCURSEL,(WPARAM) lr,0);
  1261. fSuccess=SaveScheme();
  1262. }
  1263. return fSuccess;
  1264. }
  1265. BOOL SaveScheme()
  1266. {
  1267. const BUFFER_SIZE = CCURSORS * (FILENAME_MAX+1) + 1;
  1268. char pszSchemeName[MAX_SCHEME_NAME_LEN+1];
  1269. LPSTR pszBuffer;
  1270. BOOL fSuccess=TRUE;
  1271. int i;
  1272. // allocate buffer for string
  1273. pszBuffer = (LPSTR) LocalAlloc(LMEM_FIXED,BUFFER_SIZE);
  1274. if (pszBuffer==NULL) return FALSE;
  1275. // get current scheme name
  1276. GetWindowText(ghwndSchemeCB,pszSchemeName,sizeof(pszSchemeName));
  1277. // store in registry
  1278. fSuccess = WriteProfileString(szCurrentINI,szSchemeINI,pszSchemeName);
  1279. // concatenate the filenames into a string, write it to the registry
  1280. pszBuffer[0]='\0';
  1281. for (i = 0; i < CCURSORS; i++)
  1282. {
  1283. lstrcat(pszBuffer,acuri[i].szFile);
  1284. lstrcat(pszBuffer,",");
  1285. }
  1286. pszBuffer[lstrlen(pszBuffer)-1]='\0'; // strip last comma
  1287. fSuccess &= WriteProfileString(szSchemeINI,pszSchemeName,pszBuffer);
  1288. LocalFree(pszBuffer);
  1289. if (fSuccess)
  1290. {
  1291. EnableWindow(GetDlgItem(ghwndDlg, ID_SAVESCHEME), FALSE);
  1292. }
  1293. return fSuccess;
  1294. }
  1295. BOOL LoadScheme()
  1296. {
  1297. const BUFFER_SIZE = CCURSORS * (FILENAME_MAX+1) + 1;
  1298. char pszSchemeName[MAX_SCHEME_NAME_LEN+1];
  1299. LPSTR pszBuffer;
  1300. BOOL fSuccess=TRUE;
  1301. LPSTR pszFile;
  1302. LPSTR pszNextFile;
  1303. BOOL fEOL=FALSE;
  1304. LRESULT lr;
  1305. int i=0;
  1306. // allocate buffer for cursor paths
  1307. pszBuffer = (LPSTR) LocalAlloc(LMEM_FIXED,BUFFER_SIZE);
  1308. if (pszBuffer==NULL) return FALSE;
  1309. HourGlass(TRUE);
  1310. // get current scheme name
  1311. GetWindowText(ghwndSchemeCB,pszSchemeName,sizeof(pszSchemeName));
  1312. // read cursor paths from the registry
  1313. GetProfileString(szSchemeINI,pszSchemeName,"",pszBuffer,BUFFER_SIZE);
  1314. // parse string of format "filename1,filename2,filename3..."
  1315. // into cursor info array
  1316. pszFile=pszBuffer;
  1317. do
  1318. {
  1319. pszNextFile=pszFile;
  1320. while (*pszNextFile!='\0')
  1321. {
  1322. if (*pszNextFile==',')
  1323. break;
  1324. pszNextFile=CharNext(pszNextFile);
  1325. }
  1326. if (*pszNextFile=='\0') fEOL=TRUE;
  1327. else *pszNextFile='\0';
  1328. if (lstrcmp(pszFile,acuri[i].szFile))
  1329. {
  1330. // it's different than current, update
  1331. lstrcpy(acuri[i].szFile,pszFile);
  1332. fSuccess &= SchemeUpdate(i);
  1333. }
  1334. pszFile = pszNextFile;
  1335. if (!fEOL) pszFile++; // skip '\0' and move to next path
  1336. i++;
  1337. } while (i < CCURSORS);
  1338. LocalFree(pszBuffer);
  1339. // select "Arrow" in list box
  1340. lr = SendMessage(ghwndLB, LB_GETCURSEL, 0, 0); // avoid a "flash"
  1341. if (lr!=0)
  1342. {
  1343. SendMessage(ghwndLB, LB_SETCURSEL, 0, 0);
  1344. }
  1345. // repaint
  1346. UpdateCursorList();
  1347. // disable the SAVE button
  1348. EnableWindow(GetDlgItem(ghwndDlg, ID_SAVESCHEME), FALSE);
  1349. HourGlass(FALSE);
  1350. return fSuccess;
  1351. }
  1352. // helper function --
  1353. // updates the cursor at index i
  1354. // in acuri
  1355. BOOL SchemeUpdate(int i)
  1356. {
  1357. DWORD dwDummy;
  1358. BOOL fSuccess=TRUE;
  1359. if (acuri[i].hcur != NULL)
  1360. {
  1361. DestroyCursor(acuri[i].hcur);
  1362. }
  1363. acuri[i].fl = CIF_MODIFIED;
  1364. // if "Set Default"
  1365. if (*(acuri[i].szFile) == '\0')
  1366. {
  1367. acuri[i].hcur = GetCursorInfo(NULL, (LPWSTR)gacd[i].idResource, 0, &dwDummy, (LPINT)&dwDummy);
  1368. }
  1369. else
  1370. {
  1371. fSuccess=TryToLoadCursor(ghwndDlg,i,&acuri[i]);
  1372. }
  1373. return fSuccess;
  1374. }
  1375. BOOL RemoveScheme()
  1376. {
  1377. char pszSchemeName[MAX_SCHEME_NAME_LEN+1];
  1378. LRESULT lr;
  1379. char RemoveMsg[PATHMAX];
  1380. char DialogMsg[PATHMAX];
  1381. GetWindowText(ghwndSchemeCB,pszSchemeName,sizeof(pszSchemeName));
  1382. if (*pszSchemeName=='\0')
  1383. {
  1384. return FALSE;
  1385. }
  1386. // put up a warning dialog
  1387. LoadString (ghmod, IDS_REMOVESCHEME, RemoveMsg, PATHMAX);
  1388. wsprintf(DialogMsg, RemoveMsg, (LPSTR) pszSchemeName);
  1389. // DebugBreak();
  1390. LoadString (ghmod, IDS_NAME, RemoveMsg, PATHMAX);
  1391. if (MessageBox (ghwndDlg, DialogMsg, RemoveMsg, MB_YESNO | MB_ICONEXCLAMATION) != IDYES)
  1392. return TRUE;
  1393. // delete from registry
  1394. WriteProfileString(szSchemeINI,pszSchemeName,"");
  1395. // delete from list box
  1396. lr = SendMessage(ghwndSchemeCB, CB_FINDSTRINGEXACT, 0xFFFF, (LPARAM) pszSchemeName);
  1397. SendMessage(ghwndSchemeCB, CB_DELETESTRING, (WPARAM) lr, 0);
  1398. // set new selection
  1399. SendMessage(ghwndSchemeCB, CB_SETCURSEL, 0, 0);
  1400. // Refresh everything
  1401. return LoadScheme();
  1402. }
  1403. BOOL InitSchemeComboBox()
  1404. {
  1405. const BUFFER_SIZE=4096;
  1406. LPSTR pszBuffer, pszSchemeNames;
  1407. LRESULT lr;
  1408. BOOL fSuccess=TRUE;
  1409. // allocate a buffer for the scheme names
  1410. pszBuffer = (LPSTR) LocalAlloc(LMEM_FIXED,BUFFER_SIZE);
  1411. if (pszBuffer==NULL) return FALSE;
  1412. pszSchemeNames=pszBuffer;
  1413. // copy the scheme names
  1414. GetProfileString(szSchemeINI,NULL,"",pszSchemeNames,BUFFER_SIZE);
  1415. // add each scheme name to the combo box
  1416. while (*pszSchemeNames!='\0')
  1417. {
  1418. SendMessage(ghwndSchemeCB,CB_ADDSTRING,0,(LPARAM)pszSchemeNames);
  1419. while (*pszSchemeNames!='\0')
  1420. {
  1421. pszSchemeNames=CharNext(pszSchemeNames); // skip to next string
  1422. }
  1423. pszSchemeNames++; // skip '\0' between strings
  1424. }
  1425. // determine which scheme is currently selected by the user
  1426. GetProfileString(szCurrentINI,szSchemeINI,"",pszBuffer,BUFFER_SIZE);
  1427. // try and find it in the combobox
  1428. lr = SendMessage(ghwndSchemeCB,CB_FINDSTRINGEXACT,0xFFFF,(LPARAM) pszBuffer);
  1429. // if found, select it
  1430. if (lr!=CB_ERR)
  1431. {
  1432. SendMessage(ghwndSchemeCB,CB_SETCURSEL,(WPARAM) lr,0);
  1433. fSuccess=LoadScheme();
  1434. }
  1435. else
  1436. {
  1437. // scheme was not found
  1438. // set text to nothing
  1439. SetWindowText(ghwndSchemeCB,"");
  1440. // and disable the REMOVE/SAVE buttons
  1441. EnableWindow(GetDlgItem(ghwndDlg, ID_SAVESCHEME), FALSE);
  1442. EnableWindow(GetDlgItem(ghwndDlg, ID_REMOVESCHEME), FALSE);
  1443. }
  1444. LocalFree(pszBuffer);
  1445. return fSuccess;
  1446. }
  1447. INT_PTR CALLBACK SaveSchemeDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1448. {
  1449. char szSchemeName[MAX_SCHEME_NAME_LEN+1];
  1450. switch (message)
  1451. {
  1452. case WM_INITDIALOG:
  1453. HourGlass (TRUE);
  1454. GetWindowText(ghwndSchemeCB,szSchemeName,sizeof(szSchemeName));
  1455. SetDlgItemText (hWnd, ID_SCHEMEFILENAME, szSchemeName);
  1456. SendDlgItemMessage (hWnd, ID_SCHEMEFILENAME, EM_SETSEL, 0, 32767);
  1457. SendDlgItemMessage (hWnd, ID_SCHEMEFILENAME, EM_LIMITTEXT, MAX_SCHEME_NAME_LEN, 0L);
  1458. EnableWindow (GetDlgItem (hWnd, IDOK), szSchemeName[0] != '\0');
  1459. HourGlass (FALSE);
  1460. return (TRUE);
  1461. break;
  1462. case WM_COMMAND:
  1463. switch (LOWORD (wParam))
  1464. {
  1465. case ID_SCHEMEFILENAME:
  1466. if (HIWORD (wParam) == EN_CHANGE)
  1467. {
  1468. EnableWindow (GetDlgItem (hWnd, IDOK),
  1469. GetDlgItemText (hWnd, ID_SCHEMEFILENAME, szSchemeName, 2));
  1470. }
  1471. break;
  1472. case IDD_HELP:
  1473. goto DoHelp;
  1474. case IDOK:
  1475. GetDlgItemText (hWnd, ID_SCHEMEFILENAME, szSchemeName, MAX_SCHEME_NAME_LEN);
  1476. StripBlanks (szSchemeName);
  1477. if (*szSchemeName=='/0')
  1478. {
  1479. MessageBeep(0);
  1480. break;
  1481. }
  1482. lstrcpy (gszSchemeName, szSchemeName);
  1483. // fall through...
  1484. case IDCANCEL:
  1485. EndDialog (hWnd, LOWORD (wParam) == IDOK);
  1486. return (TRUE);
  1487. }
  1488. default:
  1489. if (message == wHelpMessage)
  1490. {
  1491. DoHelp:
  1492. CPHelp (hWnd);
  1493. return TRUE;
  1494. }
  1495. else
  1496. return FALSE;
  1497. }
  1498. return (FALSE); // Didn't process a message
  1499. }
  1500. // returns Filename with a default path in system directory
  1501. // if no path is already specified
  1502. LPSTR MakeFilename(LPSTR sz)
  1503. {
  1504. if (sz[0]=='\\' || sz[1]==':')
  1505. {
  1506. return sz;
  1507. }
  1508. else
  1509. {
  1510. GetSystemDirectory(gszFileName2,sizeof(gszFileName2));
  1511. lstrcat(gszFileName2,"\\");
  1512. lstrcat(gszFileName2,sz);
  1513. return gszFileName2;
  1514. }
  1515. }
  1516. /* StripBlanks()
  1517. Strips leading and trailing blanks from a string.
  1518. Alters the memory where the string sits.
  1519. ErikGav- Stolen from \control\main\util.c
  1520. */
  1521. void StripBlanks (LPSTR pszString)
  1522. {
  1523. LPSTR pszPosn;
  1524. /* strip leading blanks */
  1525. pszPosn = pszString;
  1526. while(*pszPosn == ' ')
  1527. {
  1528. pszPosn++;
  1529. }
  1530. if (pszPosn != pszString);
  1531. strcpy (pszString, pszPosn);
  1532. /* strip trailing blanks */
  1533. if ((pszPosn=pszString + strlen (pszString)) != pszString)
  1534. {
  1535. pszPosn = CharPrev (pszString, pszPosn);
  1536. while(*pszPosn == ' ')
  1537. pszPosn = CharPrev (pszString, pszPosn);
  1538. pszPosn = CharNext (pszPosn);
  1539. *pszPosn = '\0';
  1540. }
  1541. }