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.

1384 lines
34 KiB

  1. /*
  2. SSBEZIER.C
  3. Bezier screensaver.
  4. History:
  5. 10/14/91 kentd Wrote for Windows NT. Hacked from WinBez.
  6. */
  7. #include <windows.h>
  8. #include <commctrl.h>
  9. #include <scrnsave.h>
  10. #include "bezdlg.h"
  11. #include "strings.h"
  12. #include "uniconv.h"
  13. #include "stdlib.h"
  14. #undef OVERFLOW
  15. #undef UNDERFLOW
  16. #include "math.h"
  17. #define INT int
  18. #if !defined(_ALPHA_)
  19. // floating point always initialized on ALPHA and ALPHA64
  20. VOID _fltused(VOID) {}
  21. #endif
  22. // routines from bez.c
  23. VOID vInitPoints();
  24. VOID vRedraw();
  25. VOID vNextBez();
  26. LONG GetDlgItemLong(HWND hDlg, WORD wID, BOOL *pfTranslated, BOOL fSigned);
  27. VOID GetIniEntries(VOID);
  28. VOID vInitPalette(HDC);
  29. VOID vNewColor(VOID);
  30. LONG GetPrivateProfileLong(LPTSTR pszApp, LPTSTR pszKey, LONG lDefault);
  31. typedef struct _STR
  32. {
  33. PSZ psz;
  34. SIZE sz;
  35. SHORT c;
  36. BYTE f;
  37. } STR;
  38. typedef struct _inst
  39. {
  40. ULONG i;
  41. POINT pt;
  42. POINT ptVel;
  43. LONG c;
  44. } INST, *PINST;
  45. typedef struct _WINDOW {
  46. HWND hwnd;
  47. HDC hdc;
  48. HANDLE hWait;
  49. int xsize;
  50. int ysize;
  51. HPALETTE hpalette;
  52. // frame data
  53. HBITMAP hbitmap;
  54. HDC hdcBitmap;
  55. PBYTE pdata;
  56. RECT rcBlt;
  57. RECT rcDraw;
  58. int xDelta;
  59. int yDelta;
  60. // text data
  61. HBITMAP hbitmapText;
  62. HDC hdcText;
  63. PBYTE pdataText;
  64. } WINDOW, *PWINDOW;
  65. PWINDOW gpwindow;
  66. BOOL fRepaint = TRUE;
  67. //
  68. // Length is the number of beziers in each loop
  69. // Width is the number of times each bezier loop is drawn
  70. //
  71. #define MINLENGTH 1
  72. #define MAXLENGTH 10
  73. #define DEF_LENGTH 4
  74. #define MINWIDTH 1
  75. #define MAXWIDTH 100
  76. #define DEF_WIDTH 30
  77. #define MINVEL 2
  78. #define DEFVEL 10
  79. #define MAXVEL 20
  80. #define MAX(a, b) (((a) >= (b)) ? (a) : (b))
  81. #define NEWVEL (ulRandom() % (MAXVEL / 2 - MINVEL) + MINVEL)
  82. HDC ghdc;
  83. HPEN ghpenBez;
  84. HPEN ghpenErase;
  85. HBRUSH ghbrushBack;
  86. DWORD glSeed;
  87. LONG gcxScreen;
  88. LONG gcyScreen;
  89. LONG gczScreen;
  90. LONG gcPoints;
  91. HDC hdcBM;
  92. HBITMAP hbm;
  93. PINST ainst;
  94. BOOL gbPointsDrawn;
  95. LONG giVelMax = DEFVEL;
  96. LONG gcBez = DEF_WIDTH;
  97. LONG gcRingLen = DEF_LENGTH;
  98. STR *astr = NULL;
  99. BOOL bInit = FALSE;
  100. int cstr = 0;
  101. ULONG ic = 0;
  102. BYTE gf = 0xff;
  103. BOOL gbCopy = TRUE;
  104. BOOL gbPalette = FALSE;
  105. HPALETTE ghpal = 0;
  106. HPALETTE ghpalOld = 0;
  107. #define NUM_PALETTE_ENTRIES 10
  108. #define FADE_RESOLUTION 24
  109. #define MAX_TICKS_WIMPY 1000
  110. #define MAX_TICKS_COOL 100
  111. PALETTEENTRY gapal[NUM_PALETTE_ENTRIES * FADE_RESOLUTION];
  112. PALETTEENTRY gapalDefault[NUM_PALETTE_ENTRIES + 1] =
  113. { {255, 0, 0}, {128, 0, 0},
  114. {0, 128, 0}, {128, 128, 0},
  115. {0, 0, 128}, {128, 0, 128},
  116. {0, 128, 128}, {128, 128, 128},
  117. {192, 192, 192}, {255, 0, 0},
  118. {0, 0, 0} };
  119. LONG gipal;
  120. LONG gcpal;
  121. LONG gcTicker;
  122. LONG gcMaxTicks;
  123. // Structures:
  124. typedef struct _BAND {
  125. POINT apt[2];
  126. } BAND;
  127. typedef struct _BEZ {
  128. BAND band[MAXLENGTH];
  129. BOOL bDrawn;
  130. } BEZ, *PBEZ;
  131. BEZ bezbuf[MAXWIDTH];
  132. PBEZ gpBez;
  133. POINT aPts[MAXLENGTH * 3 + 1];
  134. POINT aVel[MAXLENGTH][2];
  135. TCHAR szLineSpeed [] = TEXT("LineSpeed"); // .INI Line Speed key
  136. TCHAR szNumBez [] = TEXT("Width"); // .INI Width key
  137. TCHAR szNumRings [] = TEXT("Length"); // .INI Length key
  138. BOOL Init(HWND);
  139. BYTE mask = 0;
  140. //
  141. // Help IDs
  142. //
  143. DWORD aBezDlgHelpIds[] = {
  144. 65535, ((DWORD) -1),
  145. ID_LENGTH_LABEL, IDH_DISPLAY_SCREENSAVER_BEZIERS_LENGTH,
  146. ID_LENGTH, IDH_DISPLAY_SCREENSAVER_BEZIERS_LENGTH,
  147. ID_LENGTHARROW, IDH_DISPLAY_SCREENSAVER_BEZIERS_LENGTH,
  148. ID_WIDTH_LABEL, IDH_DISPLAY_SCREENSAVER_BEZIERS_WIDTH,
  149. ID_WIDTH, IDH_DISPLAY_SCREENSAVER_BEZIERS_WIDTH,
  150. ID_WIDTHARROW, IDH_DISPLAY_SCREENSAVER_BEZIERS_WIDTH,
  151. ID_VELOCITY, IDH_DISPLAY_SCREENSAVER_BEZIERS_SPEED,
  152. ID_VELOCITY_SLOW, IDH_DISPLAY_SCREENSAVER_BEZIERS_SPEED,
  153. ID_VELOCITY_FAST, IDH_DISPLAY_SCREENSAVER_BEZIERS_SPEED,
  154. 0,0
  155. };
  156. /* This is the main window procedure to be used when the screen saver is
  157. activated in a screen saver mode ( as opposed to configure mode ). This
  158. function must be declared as an EXPORT in the EXPORTS section of the
  159. DEFinition file... */
  160. LRESULT ScreenSaverProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  161. {
  162. static UINT_PTR wTimer;
  163. TCHAR szTemp[20]; // Temporary string buffer
  164. int i;
  165. BYTE bit;
  166. switch (message)
  167. {
  168. case WM_CREATE:
  169. GetIniEntries ();
  170. glSeed = GetCurrentTime (); // random number generator
  171. ghdc = GetDC(hWnd);
  172. gcxScreen = ((LPCREATESTRUCT)lParam)->cx;
  173. gcyScreen = ((LPCREATESTRUCT)lParam)->cy;
  174. vInitPoints();
  175. if (gczScreen & (1 << 14)) {
  176. Init(hWnd);
  177. } else {
  178. ghbrushBack = GetStockObject(BLACK_BRUSH);
  179. ghpenBez = CreatePen(PS_SOLID, 0, 0xff);
  180. ghpenErase = CreatePen(PS_SOLID, 0, 0);
  181. SelectObject(ghdc,ghpenBez);
  182. SelectObject(ghdc,ghbrushBack);
  183. vInitPalette(ghdc);
  184. wTimer = SetTimer (hWnd, 1, 1, NULL);
  185. }
  186. break;
  187. case WM_SIZE:
  188. gcxScreen = LOWORD(lParam);
  189. gcyScreen = HIWORD(lParam);
  190. break;
  191. case WM_PALETTECHANGED:
  192. RealizePalette(ghdc);
  193. break;
  194. case WM_QUERYNEWPALETTE:
  195. if (ghpal != 0)
  196. {
  197. SelectPalette(ghdc, ghpal, FALSE);
  198. RealizePalette(ghdc);
  199. InvalidateRect(hWnd, NULL, TRUE);
  200. return(TRUE);
  201. }
  202. else
  203. return(FALSE);
  204. case WM_PAINT:
  205. if (gczScreen & (1 << 14)) {
  206. PAINTSTRUCT paint;
  207. BeginPaint(hWnd, &paint);
  208. EndPaint(hWnd, &paint);
  209. fRepaint = TRUE;
  210. } else {
  211. vRedraw();
  212. }
  213. break;
  214. case WM_TIMER:
  215. if (gczScreen & (1 << 14)) {
  216. SetEvent(gpwindow->hWait);
  217. } else {
  218. vNextBez();
  219. }
  220. break;
  221. case WM_DESTROY:
  222. if (wTimer)
  223. KillTimer (hWnd, wTimer);
  224. if (ghpal != 0)
  225. {
  226. SelectPalette(ghdc, ghpalOld, FALSE);
  227. DeleteObject(ghpal);
  228. }
  229. ReleaseDC(hWnd, ghdc);
  230. break;
  231. }
  232. return (DefScreenSaverProc (hWnd, message, wParam, lParam));
  233. }
  234. //***************************************************************************
  235. BOOL ScreenSaverConfigureDialog (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  236. {
  237. BOOL fError; // Error flag
  238. UINT wTemp;
  239. TCHAR szTemp[20]; // Temporary string buffer
  240. char szTemp2[20]; // Temporary string buffer
  241. WORD nCtlId;
  242. int nVal, nOldVal;
  243. LONG *plState = (LONG *) szTemp2; // State buffer
  244. static HWND hVelocity, // window handle of Speed scrollbar
  245. hIDOK, // window handle of OK button
  246. hSetPassword, // window handle of SetPassword button
  247. hNumBeziers, // window handle of NumBezier EditControl
  248. hNumRings; // window handle of NumBezier EditControl
  249. switch (message)
  250. {
  251. case WM_INITDIALOG:
  252. GetIniEntries (); // Get initial values
  253. hVelocity = GetDlgItem (hDlg, ID_VELOCITY);
  254. hIDOK = GetDlgItem (hDlg, IDOK);
  255. hNumBeziers = GetDlgItem (hDlg, ID_WIDTH);
  256. hNumRings = GetDlgItem (hDlg, ID_LENGTH);
  257. SendMessage (hNumBeziers, EM_LIMITTEXT, 3, 0);
  258. SendMessage (hNumRings, EM_LIMITTEXT, 3, 0);
  259. SetScrollRange (hVelocity, SB_CTL, MINVEL, MAXVEL, FALSE);
  260. SetScrollPos (hVelocity, SB_CTL, giVelMax, TRUE);
  261. SetDlgItemInt (hDlg, ID_WIDTH, gcBez, FALSE);
  262. SetDlgItemInt (hDlg, ID_LENGTH, gcRingLen, FALSE);
  263. SendDlgItemMessage( hDlg, ID_LENGTHARROW, UDM_SETRANGE, 0, MAKELONG(MAXLENGTH, MINLENGTH));
  264. SendDlgItemMessage( hDlg, ID_WIDTHARROW, UDM_SETRANGE, 0, MAKELONG(MAXWIDTH, MINWIDTH));
  265. wsprintf (szTemp, TEXT("%d"), gcBez);
  266. WritePrivateProfileString (szAppName, szNumBez, szTemp, szIniFile);
  267. return TRUE;
  268. case WM_HSCROLL:
  269. switch (LOWORD(wParam))
  270. {
  271. case SB_PAGEUP:
  272. --giVelMax;
  273. break;
  274. case SB_LINEUP:
  275. --giVelMax;
  276. break;
  277. case SB_PAGEDOWN:
  278. ++giVelMax;
  279. break;
  280. case SB_LINEDOWN:
  281. ++giVelMax;
  282. break;
  283. case SB_THUMBPOSITION:
  284. giVelMax = HIWORD (wParam);
  285. break;
  286. case SB_BOTTOM:
  287. giVelMax = MAXVEL;
  288. break;
  289. case SB_TOP:
  290. giVelMax = MINVEL;
  291. break;
  292. case SB_THUMBTRACK:
  293. case SB_ENDSCROLL:
  294. return TRUE;
  295. break;
  296. }
  297. if ((int)giVelMax <= MINVEL)
  298. giVelMax = MINVEL;
  299. if ((int)giVelMax >= MAXVEL)
  300. giVelMax = MAXVEL;
  301. SetScrollPos ((HWND) lParam, SB_CTL, giVelMax, TRUE);
  302. break;
  303. case WM_COMMAND:
  304. switch (LOWORD(wParam))
  305. {
  306. case ID_LENGTH:
  307. if (HIWORD(wParam) == EN_UPDATE)
  308. {
  309. wTemp = GetDlgItemInt (hDlg, ID_LENGTH, &fError, FALSE);
  310. fError = ((wTemp <= MAXLENGTH) && (wTemp >= MINLENGTH));
  311. EnableWindow (GetDlgItem (hDlg, ID_LENGTHARROW), fError);
  312. EnableWindow (GetDlgItem (hDlg, IDOK), fError);
  313. }
  314. break;
  315. case ID_WIDTH:
  316. if (HIWORD(wParam) == EN_UPDATE)
  317. {
  318. wTemp = GetDlgItemInt (hDlg, ID_WIDTH, &fError, FALSE);
  319. fError = ((wTemp <= MAXWIDTH) && (wTemp >= MINWIDTH));
  320. EnableWindow (GetDlgItem (hDlg, ID_WIDTHARROW), fError);
  321. EnableWindow (GetDlgItem (hDlg, IDOK), fError);
  322. }
  323. break;
  324. case IDOK:
  325. wTemp = GetDlgItemInt (hDlg, ID_WIDTH, &fError, FALSE);
  326. wTemp |= GetPrivateProfileInt (szAppName, szNumBez, DEF_WIDTH, szIniFile) & (1 << 14);
  327. wsprintf (szTemp, TEXT("%d"), wTemp);
  328. WritePrivateProfileString (szAppName, szNumBez, szTemp, szIniFile);
  329. wTemp = GetDlgItemInt (hDlg, ID_LENGTH, &fError, FALSE);
  330. wsprintf (szTemp, TEXT("%d"), wTemp);
  331. WritePrivateProfileString (szAppName, szNumRings, szTemp, szIniFile);
  332. wsprintf (szTemp, TEXT("%d"), giVelMax);
  333. WritePrivateProfileString (szAppName, szLineSpeed, szTemp, szIniFile);
  334. case IDCANCEL:
  335. EndDialog (hDlg, LOWORD(wParam) == IDOK);
  336. return TRUE;
  337. }
  338. break;
  339. case WM_HELP: // F1
  340. WinHelp(
  341. (HWND) ((LPHELPINFO) lParam)->hItemHandle,
  342. szHelpFile,
  343. HELP_WM_HELP,
  344. (ULONG_PTR) (LPSTR) aBezDlgHelpIds
  345. );
  346. break;
  347. case WM_CONTEXTMENU: // right mouse click
  348. WinHelp(
  349. (HWND) wParam,
  350. szHelpFile,
  351. HELP_CONTEXTMENU,
  352. (ULONG_PTR) (LPSTR) aBezDlgHelpIds
  353. );
  354. break;
  355. default:
  356. break;
  357. }
  358. return FALSE;
  359. }
  360. /* This procedure is called right before the dialog box above is created in
  361. order to register any child windows that are custom controls. If no
  362. custom controls need to be registered, then simply return TRUE.
  363. Otherwise, register the child controls however is convenient... */
  364. BOOL RegisterDialogClasses (HANDLE hInst)
  365. {
  366. InitCommonControls();
  367. return TRUE;
  368. }
  369. LONG GetDlgItemLong (HWND hDlg, WORD wID, BOOL *pfTranslated, BOOL fSigned)
  370. {
  371. TCHAR szTemp[20];
  372. LPTSTR pszTemp;
  373. LONG lTemp = 0l;
  374. BOOL fNegative;
  375. if (!GetDlgItemText (hDlg, wID, szTemp, CharSizeOf(szTemp)))
  376. goto GetDlgItemLongError;
  377. szTemp[19] = TEXT('\0');
  378. pszTemp = szTemp;
  379. while (*pszTemp == TEXT(' ') || *pszTemp == TEXT('\t'))
  380. pszTemp++;
  381. if ((!fSigned && *pszTemp == TEXT('-')) || !*pszTemp)
  382. goto GetDlgItemLongError;
  383. fNegative = (*pszTemp == TEXT('-')) ? TRUE : FALSE;
  384. while (*pszTemp >= TEXT('0') && *pszTemp <= TEXT('9'))
  385. lTemp = lTemp * 10l + (LONG)(*(pszTemp++) - TEXT('0'));
  386. if (*pszTemp)
  387. goto GetDlgItemLongError;
  388. if (fNegative)
  389. lTemp *= -1;
  390. *pfTranslated = TRUE;
  391. return lTemp;
  392. GetDlgItemLongError:
  393. *pfTranslated = FALSE;
  394. return 0l;
  395. }
  396. LONG GetPrivateProfileLong (LPTSTR pszApp, LPTSTR pszKey, LONG lDefault)
  397. {
  398. LONG lTemp = 0l;
  399. TCHAR szTemp[20];
  400. LPTSTR pszTemp;
  401. if (!GetPrivateProfileString (pszApp, pszKey, TEXT(""), szTemp, CharSizeOf(szTemp), szIniFile))
  402. goto GetProfileLongError;
  403. szTemp[19] = TEXT('\0');
  404. pszTemp = szTemp;
  405. while (*pszTemp >= TEXT('0') && *pszTemp <= TEXT('9'))
  406. lTemp = lTemp * 10l + (LONG)(*(pszTemp++) - TEXT('0'));
  407. if (*pszTemp)
  408. goto GetProfileLongError;
  409. return lTemp;
  410. GetProfileLongError:
  411. return lDefault;
  412. }
  413. VOID GetIniEntries (VOID)
  414. {
  415. LoadString (hMainInstance, idsName, szName, TITLEBARNAMELEN);
  416. LoadString (hMainInstance, idsAppName, szAppName, APPNAMEBUFFERLEN);
  417. //Load Common Strings from stringtable...
  418. LoadString (hMainInstance, idsIniFile, szIniFile, MAXFILELEN);
  419. LoadString (hMainInstance, idsScreenSaver, szScreenSaver, 22);
  420. LoadString (hMainInstance, idsHelpFile, szHelpFile, MAXFILELEN);
  421. LoadString (hMainInstance, idsNoHelpMemory, szNoHelpMemory, BUFFLEN);
  422. giVelMax = GetPrivateProfileInt (szAppName, szLineSpeed, DEFVEL, szIniFile);
  423. if (giVelMax > MAXVEL || giVelMax < MINVEL)
  424. giVelMax = DEFVEL;
  425. gcBez = GetPrivateProfileInt (szAppName, szNumBez, DEF_WIDTH, szIniFile);
  426. gcBez = (gczScreen = gcBez) & ~(1 << 14);
  427. if (gcBez > MAXWIDTH)
  428. gcBez = MAXWIDTH;
  429. if (gcBez < MINWIDTH)
  430. gcBez = MINWIDTH;
  431. gcRingLen = GetPrivateProfileInt (szAppName, szNumRings, DEF_LENGTH, szIniFile);
  432. if (gcRingLen > MAXLENGTH)
  433. gcRingLen = MAXLENGTH;
  434. if (gcRingLen < MINLENGTH)
  435. gcRingLen = MINLENGTH;
  436. }
  437. /************************************************************************
  438. * Bezier code
  439. *
  440. * Created: 19-Oct-1990 10:18:45
  441. * Author: Paul Butzi
  442. *
  443. * Copyright (c) 1990 Microsoft Corporation
  444. *
  445. * Generates random lines
  446. * Hacked from arcs.c
  447. \**************************************************************************/
  448. DWORD ulRandom()
  449. {
  450. glSeed *= 69069;
  451. glSeed++;
  452. return(glSeed);
  453. }
  454. VOID vCLS()
  455. {
  456. PatBlt(ghdc, 0, 0, gcxScreen, gcyScreen, PATCOPY);
  457. }
  458. int iNewVel(INT i)
  459. {
  460. if ((gcRingLen != 1) || (i == 1) || (i == 2))
  461. return(ulRandom() % (giVelMax + 1 / 3) + MINVEL);
  462. else
  463. return(ulRandom() % giVelMax + MINVEL);
  464. }
  465. VOID vInitPoints()
  466. {
  467. INT ii;
  468. for (ii = 0; ii < MAXLENGTH; ii++)
  469. {
  470. bezbuf[0].band[ii].apt[0].x = gcxScreen ? ulRandom() % gcxScreen : 0;
  471. bezbuf[0].band[ii].apt[0].y = gcyScreen ? ulRandom() % gcyScreen : 0;
  472. bezbuf[0].band[ii].apt[1].x = gcxScreen ? ulRandom() % gcxScreen : 0;
  473. bezbuf[0].band[ii].apt[1].y = gcyScreen ? ulRandom() % gcyScreen : 0;
  474. aVel[ii][0].x = iNewVel(ii) * ((ulRandom() & 0x10) ? 1 : -1);
  475. aVel[ii][0].y = iNewVel(ii) * ((ulRandom() & 0x10) ? 1 : -1);
  476. aVel[ii][1].x = iNewVel(ii) * ((ulRandom() & 0x11) ? 1 : -1);
  477. aVel[ii][1].y = iNewVel(ii) * ((ulRandom() & 0x10) ? 1 : -1);
  478. }
  479. gpBez = bezbuf;
  480. }
  481. VOID vRedraw()
  482. {
  483. INT j;
  484. for ( j = 0; j < gcBez; j += 1 )
  485. {
  486. bezbuf[j].bDrawn = FALSE;
  487. }
  488. vCLS();
  489. gpBez = bezbuf;
  490. gbPointsDrawn = FALSE;
  491. }
  492. /******************************Public*Routine******************************\
  493. * VOID vDrawBand(pbez)
  494. *
  495. * History:
  496. * 14-Oct-1991 -by- J. Andrew Goossen [andrewgo]
  497. * Wrote it.
  498. \**************************************************************************/
  499. VOID vDrawBand(PBEZ pbez)
  500. {
  501. INT ii;
  502. INT iNext;
  503. PPOINT ppt;
  504. // If only drawing one Bezier, special case it:
  505. if (gcRingLen == 1)
  506. {
  507. aPts[0] = pbez->band[0].apt[0];
  508. aPts[1] = pbez->band[0].apt[1];
  509. aPts[2] = pbez->band[1].apt[0];
  510. aPts[3] = pbez->band[1].apt[1];
  511. }
  512. else
  513. {
  514. // Do the elastic band effect, with 2nd order continuity:
  515. aPts[0].x = (pbez->band[0].apt[0].x + pbez->band[0].apt[1].x) >> 1;
  516. aPts[0].y = (pbez->band[0].apt[0].y + pbez->band[0].apt[1].y) >> 1;
  517. ppt = &aPts[1];
  518. for (ii = 0; ii < gcRingLen; ii++)
  519. {
  520. iNext = (ii + 1) % gcRingLen;
  521. *ppt++ = pbez->band[ii].apt[1];
  522. *ppt++ = pbez->band[iNext].apt[0];
  523. ppt->x = (pbez->band[iNext].apt[0].x + pbez->band[iNext].apt[1].x) >> 1;
  524. ppt->y = (pbez->band[iNext].apt[0].y + pbez->band[iNext].apt[1].y) >> 1;
  525. ppt++;
  526. }
  527. }
  528. PolyBezier(ghdc, aPts, gcRingLen * 3 + 1);
  529. }
  530. /******************************Public*Routine******************************\
  531. * VOID vNextBez()
  532. *
  533. \**************************************************************************/
  534. VOID vNextBez()
  535. {
  536. INT ii;
  537. INT jj;
  538. PBEZ obp = gpBez++;
  539. if ( gpBez >= &bezbuf[gcBez] )
  540. gpBez = bezbuf;
  541. // If bezier on screen, erase by redrawing:
  542. if (gpBez->bDrawn)
  543. {
  544. if (gbCopy)
  545. SelectObject(ghdc, ghpenErase);
  546. vDrawBand(gpBez);
  547. }
  548. // Adjust points:
  549. for (ii = 0; ii < MAX(gcRingLen, 2); ii++)
  550. {
  551. for (jj = 0; jj < 2; jj++)
  552. {
  553. register INT x, y;
  554. x = obp->band[ii].apt[jj].x;
  555. y = obp->band[ii].apt[jj].y;
  556. x += aVel[ii][jj].x;
  557. y += aVel[ii][jj].y;
  558. if ( x >= gcxScreen )
  559. {
  560. x = gcxScreen - ((x - gcxScreen) + 1);
  561. aVel[ii][jj].x = - iNewVel(ii);
  562. }
  563. if ( x < 0 )
  564. {
  565. x = - x;
  566. aVel[ii][jj].x = iNewVel(ii);
  567. }
  568. if ( y >= gcyScreen )
  569. {
  570. y = gcyScreen - ((y - gcyScreen) + 1);
  571. aVel[ii][jj].y = - iNewVel(ii);
  572. }
  573. if ( y < 0 )
  574. {
  575. y = - y;
  576. aVel[ii][jj].y = iNewVel(ii);
  577. }
  578. gpBez->band[ii].apt[jj].x = x;
  579. gpBez->band[ii].apt[jj].y = y;
  580. }
  581. }
  582. vNewColor();
  583. if (gbCopy)
  584. SelectObject(ghdc, ghpenBez);
  585. vDrawBand(gpBez);
  586. gpBez->bDrawn = TRUE;
  587. }
  588. ULONG iGet()
  589. {
  590. static int i = 0;
  591. int j;
  592. if (++i >= cstr)
  593. i = 1;
  594. j = i;
  595. while (astr[i].f == gf) {i = (i % (cstr - 1)) + 1; if (i == j) gf = ~gf;}
  596. astr[i].f = ~astr[i].f;
  597. return(i);
  598. }
  599. VOID vInitPalette(HDC hdc)
  600. {
  601. LOGPALETTE lp;
  602. HPALETTE hpalOld = 0;
  603. PALETTEENTRY *ppal;
  604. LONG cBitsPerPel;
  605. LONG i;
  606. LONG j;
  607. cBitsPerPel = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
  608. gbPalette = (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) > 0;
  609. if (gbPalette)
  610. {
  611. // Try and realize a palette with one palette entry reserved:
  612. lp.palVersion = 0x300;
  613. lp.palNumEntries = 1;
  614. lp.palPalEntry[0].peFlags = PC_RESERVED;
  615. ghpal = CreatePalette(&lp);
  616. if (ghpal != 0)
  617. {
  618. ghpalOld = SelectPalette(hdc, ghpal, FALSE);
  619. RealizePalette(ghdc);
  620. }
  621. }
  622. if (!gbPalette && cBitsPerPel <= 4)
  623. {
  624. // If on a wimpy device, simply cycle through the 'dark' colors of
  625. // its palette, skipping black because it's boring:
  626. gcpal = GetSystemPaletteEntries(hdc, 1, NUM_PALETTE_ENTRIES, &gapal[0]);
  627. if (gcpal == 0)
  628. {
  629. // Worst comes to worst, always use a white pen:
  630. gcpal = 1;
  631. gapal[0].peRed = 255;
  632. gapal[0].peGreen = 255;
  633. gapal[0].peBlue = 255;
  634. gapal[0].peFlags = 0;
  635. }
  636. gipal = 8 % gcpal; // Start with red
  637. gcMaxTicks = MAX_TICKS_WIMPY;
  638. gcTicker = 0;
  639. return;
  640. }
  641. // At this point, we either have a palette managed or high color device.
  642. ppal = &gapal[0];
  643. for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
  644. {
  645. for (j = 0; j < FADE_RESOLUTION; j++)
  646. {
  647. ppal->peRed = (BYTE)(gapalDefault[i].peRed +
  648. (j * (gapalDefault[i + 1].peRed - gapalDefault[i].peRed))
  649. / FADE_RESOLUTION);
  650. ppal->peGreen = (BYTE)(gapalDefault[i].peGreen +
  651. (j * (gapalDefault[i + 1].peGreen - gapalDefault[i].peGreen))
  652. / FADE_RESOLUTION);
  653. ppal->peBlue = (BYTE)(gapalDefault[i].peBlue +
  654. (j * (gapalDefault[i + 1].peBlue - gapalDefault[i].peBlue))
  655. / FADE_RESOLUTION);
  656. ppal->peFlags = PC_RESERVED;
  657. ppal++;
  658. }
  659. }
  660. gcpal = (NUM_PALETTE_ENTRIES - 1) * FADE_RESOLUTION;
  661. gipal = 0;
  662. gcMaxTicks = MAX_TICKS_COOL;
  663. gcTicker = 0;
  664. if (gbPalette)
  665. {
  666. // Create a pen that maps to logical palette index zero:
  667. SelectObject(hdc, GetStockObject(BLACK_PEN));
  668. DeleteObject(ghpenBez);
  669. ghpenBez = CreatePen(0, 0, PALETTEINDEX(0));
  670. SelectObject(hdc, ghpenBez);
  671. }
  672. return;
  673. }
  674. VOID vNewColor(VOID)
  675. {
  676. HPEN hpen;
  677. if (--gcTicker <= 0)
  678. {
  679. if (gbPalette)
  680. {
  681. AnimatePalette(ghpal, 0, 1, &gapal[gipal]);
  682. }
  683. else
  684. {
  685. if (gbCopy)
  686. {
  687. hpen = CreatePen(0, 0, RGB(gapal[gipal].peRed,
  688. gapal[gipal].peGreen,
  689. gapal[gipal].peBlue));
  690. SelectObject(ghdc, hpen);
  691. DeleteObject(ghpenBez);
  692. ghpenBez = hpen;
  693. }
  694. }
  695. gcTicker = gcMaxTicks;
  696. if (--gipal < 0)
  697. gipal = gcpal - 1;
  698. }
  699. return;
  700. }
  701. /****************************************************************************/
  702. typedef struct _DOT {
  703. int xm, ym, zm;
  704. int xn, yn, zn;
  705. int color;
  706. } DOT, *PDOT;
  707. typedef struct _LIST *PLIST;
  708. typedef struct _LIST {
  709. PLIST pnext;
  710. PLIST plistComplete;
  711. PSZ psz;
  712. } LIST;
  713. #define MAXFIXED (65536)
  714. #define AXISSIZE 150
  715. #define XSIZE (gcxScreen)
  716. #define YSIZE (gcyScreen)
  717. #define XSIZE2 (XSIZE / 2)
  718. #define YSIZE2 (YSIZE / 2)
  719. #define SCANSIZE ((8 * XSIZE + 31) & ~31) / 8
  720. #define PI (3.141529)
  721. #define MAXANGLE (360 * 10)
  722. /****************************************************************************/
  723. int *icos;
  724. int *isin;
  725. /****************************************************************************/
  726. void ClearRect(
  727. PBYTE pstart,
  728. PRECT prc)
  729. {
  730. PBYTE pdst;
  731. int length, y;
  732. pdst = pstart + SCANSIZE * prc->top + prc->left;
  733. length = prc->right - prc->left;
  734. for (y = prc->top; y < prc->bottom; y++) {
  735. memset(pdst, 0, length);
  736. pdst += SCANSIZE;
  737. }
  738. }
  739. /****************************************************************************/
  740. void UnionRects(
  741. PRECT prcDest,
  742. PRECT prc)
  743. {
  744. if (prc->left < prcDest->left) prcDest->left = prc->left;
  745. if (prc->right > prcDest->right) prcDest->right = prc->right;
  746. if (prc->top < prcDest->top) prcDest->top = prc->top;
  747. if (prc->bottom > prcDest->bottom) prcDest->bottom = prc->bottom;
  748. }
  749. /****************************************************************************/
  750. __inline int WrapPlus(
  751. int deg,
  752. int range)
  753. {
  754. return deg >= range
  755. ? deg - range
  756. : deg;
  757. }
  758. __inline int WrapMinus(
  759. int deg,
  760. int range)
  761. {
  762. return deg < 0
  763. ? deg + range
  764. : deg;
  765. }
  766. __inline int Bound(
  767. int deg,
  768. int range)
  769. {
  770. return WrapMinus(WrapPlus(deg, range), range);
  771. }
  772. /****************************************************************************/
  773. int RandomInt(
  774. int min,
  775. int max)
  776. {
  777. int dx = max - min;
  778. int mask = 1;
  779. int value;
  780. while (mask < dx) {
  781. mask = (mask << 1) + 1;
  782. }
  783. while ((value = (rand() & mask) + min) > max) ;
  784. return value;
  785. }
  786. /****************************************************************************/
  787. #define NUMDOTS 1500
  788. PDOT adot;
  789. void InitDrawShaded(
  790. PWINDOW pwindow)
  791. {
  792. int d0, d1;
  793. int c0, c1, s0, s1;
  794. int i;
  795. int x, y, z;
  796. pwindow->rcDraw.left = 0;
  797. pwindow->rcDraw.right = 0;
  798. pwindow->rcDraw.top = 0;
  799. pwindow->rcDraw.bottom = 0;
  800. for (i = 0; i < NUMDOTS; i++) {
  801. PDOT pdot = adot + i;
  802. pdot->xm = 1 * AXISSIZE / 4;
  803. pdot->ym = 0;
  804. pdot->zm = 0;
  805. d0 = RandomInt(0, MAXANGLE / 2);
  806. d1 = RandomInt(0, MAXANGLE - 1);
  807. c0 = icos[d0];
  808. s0 = isin[d0];
  809. c1 = icos[d1];
  810. s1 = isin[d1];
  811. x = (pdot->zm * s0 + pdot->xm * c0) / MAXFIXED;
  812. z = (pdot->zm * c0 - pdot->xm * s0) / MAXFIXED;
  813. y = (z * s1 + pdot->ym * c1) / MAXFIXED;
  814. z = (z * c1 - pdot->ym * s1) / MAXFIXED;
  815. pdot->xm = x;
  816. pdot->ym = y;
  817. pdot->zm = z;
  818. pdot->xn = 0;
  819. pdot->yn = 0;
  820. pdot->zn = 0;
  821. }
  822. }
  823. /****************************************************************************/
  824. #define DELTA0 47
  825. #define DELTA1 30
  826. #define DELTA2 40
  827. void DrawFrameShaded(
  828. PWINDOW pwindow)
  829. {
  830. static int deg0 = 0, deg1 = 0, deg2 = 0, deg3 = 0;
  831. int i, j;
  832. int c0, c1, sizetext;
  833. int s0, s1, sizeball;
  834. int x, y, z;
  835. int xs, ys, zs;
  836. PBYTE pdata = pwindow->pdata;
  837. BYTE color;
  838. int d0, d1, d2;
  839. PRECT prc = &(pwindow->rcDraw);
  840. ClearRect(pwindow->pdata, &(pwindow->rcDraw));
  841. pwindow->rcBlt = pwindow->rcDraw;
  842. prc->left = XSIZE;
  843. prc->right = 0;
  844. prc->top = YSIZE;
  845. prc->bottom = 0;
  846. //
  847. // draw this frame
  848. //
  849. for (j = 0; j < 1; j++) {
  850. d0 = WrapPlus(deg0 + j * DELTA0, MAXANGLE);
  851. d0 = Bound((icos[d0] * MAXANGLE / 2) / MAXFIXED, MAXANGLE);
  852. c0 = icos[d0];
  853. s0 = isin[d0];
  854. d1 = WrapPlus(deg1 + j * DELTA1, MAXANGLE);
  855. c1 = icos[d1];
  856. s1 = isin[d1];
  857. d2 = WrapPlus(deg2 + MAXANGLE * 3 / 4, MAXANGLE);
  858. sizeball = (icos[d2] + MAXFIXED) / 2;
  859. sizetext = (isin[d2] + MAXFIXED) / 2;
  860. color = 245;
  861. /*
  862. * rotate verticies
  863. */
  864. for (i = 0; i < NUMDOTS; i++) {
  865. PDOT pdot = adot + i;
  866. PBYTE pbyte;
  867. xs = pdot->xm;
  868. ys = pdot->ym;
  869. zs = pdot->zm;
  870. x = (zs * s0 + xs * c0) / MAXFIXED;
  871. z = (zs * c0 - xs * s0) / MAXFIXED;
  872. y = (z * s1 + ys * c1) / MAXFIXED;
  873. z = (z * c1 - ys * s1) / MAXFIXED;
  874. x = (x * sizeball + pdot->xn * sizetext) / MAXFIXED;
  875. y = (y * sizeball + pdot->yn * sizetext) / MAXFIXED;
  876. z = (z * sizeball + pdot->zn * sizetext) / MAXFIXED;
  877. x += XSIZE2;
  878. y += YSIZE2;
  879. if (x < 0) x = 0;
  880. if (x > XSIZE - 2) x = XSIZE - 2;
  881. if (y < 0) y = 0;
  882. if (y > YSIZE - 2) y = YSIZE - 2;
  883. if (x < prc->left) prc->left = x;
  884. if (x+2 > prc->right) prc->right = x+2;
  885. if (y < prc->top) prc->top = y;
  886. if (y+2 > prc->bottom) prc->bottom = y+2;
  887. pbyte = pdata + x + y * SCANSIZE;
  888. pbyte[0] = color;
  889. pbyte[1] = color;
  890. pbyte[SCANSIZE] = color;
  891. pbyte[SCANSIZE + 1] = color;
  892. }
  893. }
  894. //
  895. // next frame
  896. //
  897. deg0 = WrapPlus(deg0 + DELTA0, MAXANGLE);
  898. deg1 = WrapPlus(deg1 + DELTA1, MAXANGLE);
  899. deg2 -= DELTA2;
  900. if (deg2 < 0) {
  901. deg2 += MAXANGLE;
  902. }
  903. UnionRects(&(pwindow->rcBlt), &(pwindow->rcDraw));
  904. pwindow->xDelta = pwindow->rcBlt.left;
  905. pwindow->yDelta = pwindow->rcBlt.top;
  906. }
  907. /****************************************************************************/
  908. void InitDrawingThread(
  909. PWINDOW pwindow)
  910. {
  911. int i;
  912. for (i = 0; i < MAXANGLE; i++) {
  913. double rad = i * (2.0 * PI / MAXANGLE);
  914. icos[i] = (int)(cos(rad) * MAXFIXED);
  915. isin[i] = (int)(sin(rad) * MAXFIXED);
  916. }
  917. }
  918. /****************************************************************************/
  919. void BltThread(
  920. PWINDOW pwindow)
  921. {
  922. PRECT prc = &(pwindow->rcBlt);
  923. GdiSetBatchLimit(1);
  924. InitDrawingThread(pwindow);
  925. InitDrawShaded(pwindow);
  926. while (TRUE) {
  927. if (fRepaint) {
  928. RECT rc;
  929. rc.left = 0;
  930. rc.right = pwindow->xsize;
  931. rc.top = 0;
  932. rc.bottom = pwindow->ysize;
  933. FillRect(pwindow->hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
  934. fRepaint = FALSE;
  935. }
  936. DrawFrameShaded(pwindow);
  937. BitBlt(
  938. pwindow->hdc,
  939. prc->left, prc->top,
  940. prc->right - prc->left, prc->bottom - prc->top,
  941. pwindow->hdcBitmap,
  942. pwindow->xDelta,
  943. pwindow->yDelta, SRCCOPY);
  944. WaitForSingleObject(pwindow->hWait, INFINITE);
  945. }
  946. }
  947. /****************************************************************************/
  948. void vCleanSystemPalette(HDC hdc)
  949. {
  950. HPALETTE hpal,hpalOld;
  951. DWORD aTemp[257];
  952. LPLOGPALETTE lpLogPal;
  953. UCHAR iTemp;
  954. lpLogPal = (LPLOGPALETTE) aTemp;
  955. lpLogPal->palVersion = 0x300;
  956. lpLogPal->palNumEntries = 256;
  957. for (iTemp = 0; iTemp < 256; iTemp++)
  958. {
  959. lpLogPal->palPalEntry[iTemp].peRed = 0;
  960. lpLogPal->palPalEntry[iTemp].peGreen = 0;
  961. lpLogPal->palPalEntry[iTemp].peBlue = iTemp;
  962. lpLogPal->palPalEntry[iTemp].peFlags = PC_RESERVED;
  963. }
  964. hpal = CreatePalette(lpLogPal);
  965. hpalOld = SelectPalette(hdc, hpal, 0);
  966. RealizePalette(hdc);
  967. SelectPalette(hdc, hpalOld, 0);
  968. DeleteObject(hpal);
  969. }
  970. /****************************************************************************/
  971. BOOL InitDibSection(
  972. PWINDOW pwindow,
  973. RGBQUAD* ppal,
  974. BOOL fSystemPalette)
  975. {
  976. LPLOGPALETTE plp = (LPLOGPALETTE)LocalAlloc(LPTR, sizeof(LOGPALETTE) + 4 * 256);
  977. LPBITMAPINFO pbmi = (LPBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + 4 * 256);
  978. int i;
  979. UCHAR iTemp;
  980. PUSHORT pw;
  981. LOGFONT lf;
  982. HFONT hfont;
  983. if(plp == NULL || pbmi == NULL)
  984. {
  985. return FALSE;
  986. }
  987. plp->palVersion = 0x300;
  988. plp->palNumEntries = 256;
  989. if (fSystemPalette) {
  990. GetPaletteEntries((HPALETTE)GetStockObject(DEFAULT_PALETTE),
  991. 0, 1, plp->palPalEntry);
  992. GetPaletteEntries((HPALETTE)GetStockObject(DEFAULT_PALETTE),
  993. 255, 1, &plp->palPalEntry[255]);
  994. for (i = 1; i < 254; i++) {
  995. plp->palPalEntry[i].peRed = ppal[i].rgbRed;
  996. plp->palPalEntry[i].peGreen = ppal[i].rgbGreen;
  997. plp->palPalEntry[i].peBlue = ppal[i].rgbBlue;
  998. plp->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
  999. }
  1000. SetSystemPaletteUse(pwindow->hdc, SYSPAL_NOSTATIC);
  1001. } else {
  1002. GetPaletteEntries((HPALETTE)GetStockObject(DEFAULT_PALETTE),
  1003. 0, 10, plp->palPalEntry);
  1004. GetPaletteEntries((HPALETTE)GetStockObject(DEFAULT_PALETTE),
  1005. 246, 10, &plp->palPalEntry[255]);
  1006. for (i = 10; i < 246; i++) {
  1007. plp->palPalEntry[i].peRed = ppal[i].rgbRed;
  1008. plp->palPalEntry[i].peGreen = ppal[i].rgbGreen;
  1009. plp->palPalEntry[i].peBlue = ppal[i].rgbBlue;
  1010. plp->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
  1011. }
  1012. }
  1013. pwindow->hpalette = CreatePalette(plp);
  1014. vCleanSystemPalette(pwindow->hdc);
  1015. SelectPalette(pwindow->hdc, pwindow->hpalette, FALSE);
  1016. RealizePalette(pwindow->hdc);
  1017. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  1018. pbmi->bmiHeader.biWidth = XSIZE;
  1019. pbmi->bmiHeader.biHeight = -YSIZE;
  1020. pbmi->bmiHeader.biPlanes = 1;
  1021. pbmi->bmiHeader.biBitCount = 8;
  1022. pbmi->bmiHeader.biCompression = BI_RGB;
  1023. pbmi->bmiHeader.biSizeImage = 0;
  1024. pbmi->bmiHeader.biXPelsPerMeter = 0;
  1025. pbmi->bmiHeader.biYPelsPerMeter = 0;
  1026. pbmi->bmiHeader.biClrUsed = 0;
  1027. pbmi->bmiHeader.biClrImportant = 0;
  1028. pw = (PUSHORT)(pbmi->bmiColors);
  1029. for (iTemp=0; iTemp<256; iTemp++) {
  1030. pw[iTemp] = iTemp;
  1031. }
  1032. pwindow->hbitmap = CreateDIBSection(
  1033. pwindow->hdc, pbmi, DIB_PAL_COLORS,
  1034. (PVOID*)&(pwindow->pdata), 0, 0);
  1035. pwindow->hdcBitmap = CreateCompatibleDC(pwindow->hdc);
  1036. SelectObject(pwindow->hdcBitmap, pwindow->hbitmap);
  1037. lf.lfHeight = 30;
  1038. lf.lfWidth = 0;
  1039. lf.lfEscapement = 0;
  1040. lf.lfOrientation = 0;
  1041. lf.lfWeight = 400;
  1042. lf.lfItalic = FALSE;
  1043. lf.lfUnderline = FALSE;
  1044. lf.lfStrikeOut = FALSE;
  1045. lf.lfCharSet = ANSI_CHARSET;
  1046. lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  1047. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  1048. lf.lfQuality = DEFAULT_QUALITY;
  1049. lf.lfPitchAndFamily = VARIABLE_PITCH | FF_DONTCARE;
  1050. lstrcpy(lf.lfFaceName, TEXT("Arial"));
  1051. hfont = CreateFontIndirect(&lf);
  1052. pwindow->hbitmapText = CreateDIBSection(
  1053. pwindow->hdc, pbmi, DIB_PAL_COLORS,
  1054. (PVOID*)&(pwindow->pdataText), 0, 0);
  1055. pwindow->hdcText = CreateCompatibleDC(pwindow->hdcText);
  1056. SelectObject(pwindow->hdcText, pwindow->hbitmapText);
  1057. SelectObject(pwindow->hdcText, hfont);
  1058. return TRUE;
  1059. }
  1060. /****************************************************************************/
  1061. BOOL Init(
  1062. HWND hwnd)
  1063. {
  1064. int i;
  1065. RGBQUAD apal[256];
  1066. DWORD tid;
  1067. srand(GetTickCount());
  1068. adot = (PDOT) LocalAlloc(LPTR, sizeof(DOT) * NUMDOTS);
  1069. isin = (int *) LocalAlloc(LPTR, sizeof(int) * MAXANGLE);
  1070. icos = (int *) LocalAlloc(LPTR, sizeof(int) * MAXANGLE);
  1071. gpwindow = (PWINDOW) LocalAlloc(LPTR, sizeof(WINDOW));
  1072. if(adot == NULL || isin == NULL || icos == NULL || gpwindow == NULL)
  1073. return FALSE;
  1074. gpwindow->hwnd = hwnd;
  1075. gpwindow->xsize = gcxScreen;
  1076. gpwindow->ysize = gcyScreen;
  1077. gpwindow->hdc = ghdc;
  1078. SetBkColor(gpwindow->hdc, 0);
  1079. SetTextColor(gpwindow->hdc, RGB(0xff, 0xff, 0xff));
  1080. gpwindow->hWait = CreateEvent(NULL, FALSE, FALSE, NULL);
  1081. SetTimer(gpwindow->hwnd, 1, 1000 / 20, NULL);
  1082. for (i = 0; i < 236; i++) {
  1083. apal[i + 10].rgbRed = (i * 255) / 235;
  1084. apal[i + 10].rgbGreen = (i * 255) / 235;
  1085. apal[i + 10].rgbBlue = (i * 255) / 235;
  1086. }
  1087. if(!InitDibSection(gpwindow, apal, FALSE))
  1088. return FALSE;
  1089. CreateThread(
  1090. NULL,
  1091. 0,
  1092. (LPTHREAD_START_ROUTINE)BltThread,
  1093. gpwindow,
  1094. 0,
  1095. &tid);
  1096. return TRUE;
  1097. }