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.

1486 lines
24 KiB

  1. #ifdef PM
  2. #define CSTD_WITH_OS2
  3. #include <cstd.h>
  4. #define INCL_WIN
  5. #define INCL_DOS
  6. #include <os2.h>
  7. #endif
  8. #ifdef WIN
  9. #include <windows.h>
  10. #include <port1632.h>
  11. #endif
  12. #include "std.h"
  13. #include "scrsave.h"
  14. #ifdef PM
  15. #define prioNormal PRTYC_REGULAR
  16. #define prioIdle PRTYC_IDLETIME
  17. INT _acrtused = 0; // 'cause this is a DLL
  18. #endif
  19. #ifdef WIN
  20. #define prioNormal 0
  21. #define prioIdle 1
  22. #endif
  23. HWND hwndHook;
  24. BOOL fDelayAction;
  25. // Timer identifiers...
  26. #define tidSecond 1
  27. #define tidAnimate 2
  28. #ifdef WIN
  29. HHOOK lpfnSysMsgHookNext;
  30. #endif
  31. #ifdef PM
  32. MRESULT APIENTRY WinProcBlanker(HWND, USHORT, MPARAM, MPARAM);
  33. #endif
  34. VOID APIENTRY ScrChooseRandomServer(void);
  35. F FSendSsm(INT, LPVOID, LONG_PTR, LONG_PTR);
  36. BOOL FDosModeHwnd(HWND hwnd);
  37. VOID BlankScreen(F);
  38. VOID BlankMouse(F);
  39. VOID QuarterSecond(void);
  40. VOID EverySecond(void);
  41. VOID DelayAction(void);
  42. void MoveHwndToFront(HWND hwnd);
  43. void ShowMouse(F fShow);
  44. void GetMousePos(LPPOINT ppt);
  45. void InvalHwnd(HWND hwnd);
  46. void EraseScreen(void);
  47. void MoveHwndToBack(HWND hwnd);
  48. void ShowHwnd(HWND hwnd, F fShow);
  49. void SetPrio(INT prio);
  50. VOID CopyPszToPsz(PSZ, PSZ);
  51. INT CchLenPsz(PSZ);
  52. VOID APIENTRY TermScrSave(void);
  53. void StopTimer(INT tid);
  54. void ReleaseCvs( HWND hwnd, CVS cvs);
  55. F FAnyMouseDown(void);
  56. CVS CvsFromHwnd(HWND);
  57. F FStartTimer(INT, INT);
  58. typedef struct _ssb
  59. {
  60. #ifdef PM
  61. struct _ssb FAR * pssbNext;
  62. #endif
  63. #ifdef WIN
  64. HANDLE hssbNext;
  65. HMODULE hdll;
  66. #endif
  67. SCRSAVEPROC lpfnSaver;
  68. CHAR szName [2];
  69. } SSB;
  70. #define cbSSBBase (sizeof (SSB) - 2)
  71. #ifdef PM
  72. SSB FAR * pssbList = NULL;
  73. SSB FAR * pssbCur = NULL;
  74. #endif
  75. #ifdef WIN
  76. HANDLE hssbList = NULL;
  77. HANDLE hssbCur = NULL;
  78. #endif
  79. INT cssbRegistered = 0;
  80. #ifdef PM
  81. SSB FAR * PssbFindSz(PSZ);
  82. #endif
  83. #ifdef WIN
  84. HANDLE HssbFindSz(PSZ);
  85. #endif
  86. SCRSAVEPROC lpfnSaver;
  87. HWND hwnd;
  88. HWND hwndClient;
  89. HWND hwndApp;
  90. CVS cvs;
  91. HAB hab; // NOTE: really an hInstance in Windows!
  92. #ifdef WIN
  93. BOOL fWin30 = TRUE;
  94. #endif
  95. UINT wmScrSave; // REVIEW: for win 3.1
  96. #ifdef PM
  97. SEL selHeap;
  98. HHEAP hheap;
  99. #endif
  100. POINT ptMouseOld;
  101. INT dxScreen, dyScreen;
  102. INT csecTilReblank = 0;
  103. INT csecIgnoreDelay = 0;
  104. INT csecTilBlank = 0;
  105. F fMouseHidden = fFalse;
  106. F fScreenHidden = fFalse;
  107. INT csecTimeout = 60 * 5; /* 5 minutes */
  108. F fNoBlackout = fFalse;
  109. F fRandServer = fFalse;
  110. F fBlankPtr = fTrue;
  111. F fBackground = fFalse;
  112. F fInited = fFalse;
  113. INT csecTilMouseBlank = 5;
  114. INT csecMouseTimeout = 5;
  115. #ifdef WIN
  116. #ifdef WIN32
  117. INT APIENTRY LibMain(HANDLE hInst, ULONG ul_reason_being_called, LPVOID lpReserved) {
  118. UNREFERENCED_PARAMETER(ul_reason_being_called);
  119. UNREFERENCED_PARAMETER(lpReserved);
  120. UNREFERENCED_PARAMETER(hInst);
  121. #else
  122. int LibMain(HMODULE hModule, WORD wDataSeg, WORD cbHeap, WORD sz) {
  123. if (cbHeap != 0)
  124. (VOID)MUnlockData(0);
  125. UNREFERENCED_PARAMETER(sz);
  126. UNREFERENCED_PARAMETER(cbheap);
  127. UNREFERENCED_PARAMETER(wDataSeg);
  128. UNREFERENCED_PARAMETER(hModule);
  129. #endif /* WIN32 */
  130. return 1;
  131. }
  132. VOID APIENTRY WEP(INT fSysShutdown)
  133. {
  134. UNREFERENCED_PARAMETER(fSysShutdown);
  135. }
  136. #endif
  137. #ifdef PM
  138. VOID SetPssbCur(SSB FAR * pssb)
  139. #endif
  140. #ifdef WIN
  141. VOID SetHssbCur(HANDLE hssb)
  142. #endif
  143. {
  144. if (fScreenHidden || fBackground)
  145. FSendSsm(SSM_UNBLANK, cvs, 0L, 0L);
  146. #ifdef PM
  147. pssbCur = pssb;
  148. #endif
  149. #ifdef WIN
  150. hssbCur = hssb;
  151. #endif
  152. if (fScreenHidden)
  153. {
  154. InvalHwnd(hwnd);
  155. fNoBlackout = FSendSsm(SSM_BLANK, cvs, 0L, 0L);
  156. }
  157. else if (fBackground)
  158. {
  159. if (!FSendSsm(SSM_BLANK, cvs, 0L, 0L))
  160. {
  161. EraseScreen();
  162. }
  163. }
  164. }
  165. F FSendSsm(ssm, l1, l2, l3)
  166. INT ssm;
  167. LPVOID l1;
  168. LONG_PTR l2, l3;
  169. {
  170. #ifdef PM
  171. if (pssbCur == NULL)
  172. return fFalse;
  173. return (*pssbCur->lpfnSaver)(ssm, l1, l2, l3);
  174. #endif
  175. #ifdef WIN
  176. SCRSAVEPROC lpfn;
  177. if (hssbCur == NULL)
  178. return fFalse;
  179. lpfn = ((SSB *) LocalLock(hssbCur))->lpfnSaver;
  180. LocalUnlock(hssbCur);
  181. return (*lpfn)(ssm, l1, l2, l3);
  182. #endif
  183. }
  184. #ifdef PM
  185. APIENTRY BlankerHook(HAB hab, PQMSG pqmsg)
  186. {
  187. if (hwnd == NULL)
  188. return;
  189. switch (pqmsg->msg)
  190. {
  191. case WM_MOUSEMOVE:
  192. if (fMouseHidden)
  193. {
  194. POINT pt;
  195. GetCursorPos(&pt);
  196. if (pt.x != ptMouseOld.x || pt.y != ptMouseOld.y)
  197. BlankMouse(fFalse);
  198. }
  199. break;
  200. case WM_BUTTON1DOWN:
  201. case WM_BUTTON2DOWN:
  202. case WM_BUTTON3DOWN:
  203. case WM_VIOCHAR:
  204. case WM_CHAR:
  205. WinSendMsg(hwnd, WM_USER, (MPARAM) 0, (MPARAM) 0);
  206. break;
  207. }
  208. }
  209. #endif
  210. #ifdef WIN
  211. LRESULT APIENTRY BlankerHook(INT nCode, WPARAM wParam, LPARAM lParam)
  212. {
  213. if (csecTilBlank != csecTimeout && csecIgnoreDelay == 0)
  214. fDelayAction = TRUE;
  215. return DefHookProc(nCode, wParam, lParam,
  216. &lpfnSysMsgHookNext);
  217. }
  218. #endif
  219. #ifdef WIN_JOURNAL
  220. VOID APIENTRY BlankerHook(msgf, wParam, lParam)
  221. LONG lParam;
  222. {
  223. if (msgf >= 0)
  224. {
  225. LPEVENTMSGMSG lpevmsg;
  226. lpevmsg = (LPEVENTMSGMSG) lParam;
  227. switch (lpevmsg->message)
  228. {
  229. static POINT pt;
  230. case WM_LBUTTONDOWN:
  231. case WM_MBUTTONDOWN:
  232. case WM_RBUTTONDOWN:
  233. BlankMouse(FALSE);
  234. goto LDelay;
  235. case WM_MOUSEMOVE:
  236. GetMousePos(&pt);
  237. if (pt.x == ptMouseOld.x && pt.y == ptMouseOld.y)
  238. break;
  239. ptMouseOld = pt;
  240. if (fMouseHidden)
  241. BlankMouse(FALSE);
  242. if (csecIgnoreDelay > 0)
  243. break;
  244. /* FALL THROUGH */
  245. case WM_KEYDOWN:
  246. case WM_SYSKEYDOWN:
  247. LDelay:
  248. PostMessage(hwnd, WM_USER, 0, 0);
  249. break;
  250. }
  251. }
  252. DefHookProc(msgf, wParam, lParam,
  253. &lpfnSysMsgHookNext);
  254. }
  255. #endif
  256. BOOL FSetHwndHook(HAB hab, HWND hwnd)
  257. {
  258. #ifdef PM
  259. HMODULE hmodule;
  260. DosGetModHandle("sos", &hmodule);
  261. hwndHook = hwnd;
  262. return (hwnd != NULL ? WinSetHook : WinReleaseHook)
  263. (hab, NULL, HK_JOURNALRECORD, BlankerHook, hmodule);
  264. #endif
  265. #ifdef WIN
  266. lpfnSysMsgHookNext = SetWindowsHook(/*WH_JOURNALRECORD*/WH_KEYBOARD, &BlankerHook);
  267. return TRUE;
  268. UNREFERENCED_PARAMETER(hab);
  269. UNREFERENCED_PARAMETER(hwnd);
  270. #endif
  271. }
  272. VOID APIENTRY ScrBlank(SHORT fBlank)
  273. {
  274. BlankScreen(fBlank);
  275. csecTilBlank = 0;
  276. }
  277. VOID APIENTRY ScrSetTimeout(INT csec)
  278. {
  279. if ((csecTimeout = csec) == 0)
  280. csecTimeout = 60 * 5;
  281. }
  282. INT APIENTRY ScrGetTimeout()
  283. {
  284. return csecTimeout;
  285. }
  286. VOID APIENTRY ScrSetIgnore(SHORT csec)
  287. {
  288. csecIgnoreDelay = csec;
  289. }
  290. VOID APIENTRY ScrEnablePtrBlank(INT fEnable)
  291. {
  292. fBlankPtr = fEnable;
  293. }
  294. INT APIENTRY ScrQueryPtrBlank()
  295. {
  296. return fBlankPtr;
  297. }
  298. VOID APIENTRY ScrSetBackground(SHORT fOn)
  299. {
  300. if (!fBackground == !fOn)
  301. return;
  302. fBackground = fOn;
  303. if (fOn && !fScreenHidden)
  304. {
  305. if (cvs == NULL) // if it's not NULL, something bad happend
  306. {
  307. MoveHwndToBack(hwnd);
  308. ShowHwnd(hwnd, fTrue);
  309. if ((cvs = CvsFromHwnd(hwnd)) != NULL)
  310. {
  311. if (!FSendSsm(SSM_BLANK, cvs, 0L, 0L))
  312. {
  313. EraseScreen();
  314. FStartTimer(tidAnimate, 0);
  315. SetPrio(prioIdle);
  316. }
  317. }
  318. }
  319. }
  320. else if (!fOn && !fScreenHidden)
  321. {
  322. if (cvs != NULL)
  323. {
  324. FSendSsm(SSM_UNBLANK, cvs, 0L, 0L);
  325. ReleaseCvs(hwndClient, cvs);
  326. cvs = NULL;
  327. }
  328. StopTimer(tidAnimate);
  329. ShowHwnd(hwnd, fFalse);
  330. SetPrio(prioNormal);
  331. }
  332. }
  333. INT APIENTRY ScrQueryBackground()
  334. {
  335. return fBackground;
  336. }
  337. #ifdef PM
  338. INIT APIENTRY FInitScrSave(HAB habExe)
  339. {
  340. ULONG flFrameFlags = 0;
  341. if (hab != NULL)
  342. return fFalse;
  343. hab = habExe;
  344. if (DosAllocSeg(256, &selHeap, SEG_NONSHARED) != 0)
  345. return fFalse;
  346. if ((hheap = WinCreateHeap(selHeap, 256, 256, 0, 0, 0)) == NULL)
  347. {
  348. DosFreeSeg(selHeap);
  349. return fFalse;
  350. }
  351. if (!WinRegisterClass(hab, "sos", WinProcBlanker, 0L, NULL))
  352. {
  353. WinDestroyHeap(hheap);
  354. return fFalse;
  355. }
  356. // REVIEW: I should probably be using WinCreateWindow, but I couldn't get
  357. // it to work...
  358. if ((hwnd = WinCreateStdWindow(HWND_DESKTOP, WS_VISIBLE,
  359. &flFrameFlags, "sos", NULL, 0L, NULL, 1, &hwndClient)) == NULL)
  360. {
  361. WinDestroyHeap(hheap);
  362. return fFalse;
  363. }
  364. dxScreen = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
  365. dyScreen = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
  366. // This timer ticks every second and is used for various things
  367. while (!WinStartTimer(hab, hwndClient, tidSecond, 1000))
  368. {
  369. if (WinMessageBox(HWND_DESKTOP, hwnd,
  370. "Too many clocks or timers!", "Screen Saver", 0,
  371. MB_ICONEXCLAMATION | MB_RETRYCANCEL) == MBID_CANCEL)
  372. {
  373. return fFalse;
  374. }
  375. }
  376. if (!FSetHwndHook(hab, hwndClient))
  377. {
  378. WinDestroyWindow(hwnd);
  379. WinDestroyHeap(hheap);
  380. return fFalse;
  381. }
  382. DelayAction();
  383. fInited = fTrue;
  384. return fTrue;
  385. }
  386. VOID APIENTRY TermScrSave()
  387. {
  388. if (!fInited)
  389. return;
  390. BlankScreen(fFalse);
  391. FSetHwndHook(hab, NULL);
  392. WinDestroyWindow(hwnd);
  393. WinDestroyHeap(hheap);
  394. DosFreeSeg(selHeap);
  395. hab = NULL;
  396. fInited = fFalse;
  397. }
  398. MRESULT APIENTRY WinProcBlanker(HWND hwnd, USHORT wm, MPARAM mp1, MPARAM mp2)
  399. {
  400. switch (wm)
  401. {
  402. default:
  403. return WinDefWindowProc(hwnd, wm, mp1, mp2);
  404. case WM_BUTTON2DOWN:
  405. return WinSendMsg(HWND_DESKTOP, wm, mp1, mp2);
  406. case WM_TIMER:
  407. if (SHORT1FROMMP(mp1) == tidSecond)
  408. {
  409. EverySecond();
  410. }
  411. else if (cvs != NULL)
  412. {
  413. FSendSsm(SSM_ANIMATE, cvs, 0L, 0L);
  414. }
  415. break;
  416. case WM_CREATE:
  417. WinQueryPointerPos(HWND_DESKTOP, &ptMouseOld);
  418. break;
  419. case WM_PAINT:
  420. // BLOCK
  421. {
  422. CVS cvs;
  423. RECTL rectl;
  424. cvs = WinBeginPaint(hwnd, NULL, &rectl);
  425. if (!fNoBlackout)
  426. WinFillRect(cvs, &rectl, CLR_BLACK);
  427. WinEndPaint(cvs);
  428. }
  429. break;
  430. case WM_MOUSEMOVE:
  431. // BLOCK
  432. {
  433. PT pt;
  434. // WM_MOUSEMOVE does not mean the mouse has moved
  435. WinQueryPointerPos(HWND_DESKTOP, &pt);
  436. if (pt.x == ptMouseOld.x && pt.y == ptMouseOld.y)
  437. {
  438. break;
  439. }
  440. csecTilMouseBlank = csecMouseTimeout;
  441. }
  442. // FALL THROUGH
  443. case WM_USER:
  444. // Sent by the hook when the user does something...
  445. if (csecIgnoreDelay == 0)
  446. DelayAction();
  447. break;
  448. }
  449. return (MRESULT) 0;
  450. }
  451. #endif
  452. #ifdef WIN
  453. LRESULT APIENTRY WinProcBlanker(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)
  454. {
  455. DWORD pos;
  456. switch (wm)
  457. {
  458. case WM_PAINT:
  459. {
  460. CVS cvs;
  461. PAINTSTRUCT paint;
  462. cvs = BeginPaint(hwnd, &paint);
  463. if (!fNoBlackout)
  464. EraseScreen();
  465. EndPaint(hwnd, &paint);
  466. }
  467. break;
  468. case WM_MOUSEMOVE:
  469. pos = GetMessagePos();
  470. if (ptMouseOld.x == LOWORD(pos) &&
  471. ptMouseOld.y == HIWORD(pos))
  472. break;
  473. csecTilMouseBlank = csecMouseTimeout;
  474. /* FALL THROUGH */
  475. case WM_KEYDOWN:
  476. case WM_SYSKEYDOWN:
  477. case WM_LBUTTONDOWN:
  478. case WM_MBUTTONDOWN:
  479. case WM_RBUTTONDOWN:
  480. case WM_USER:
  481. if (csecIgnoreDelay == 0)
  482. DelayAction();
  483. break;
  484. case WM_TIMER:
  485. if (wParam == tidSecond)
  486. {
  487. static INT iqsec;
  488. iqsec += 1;
  489. if (iqsec == 4)
  490. {
  491. iqsec = 0;
  492. EverySecond();
  493. }
  494. QuarterSecond();
  495. }
  496. else if (cvs != NULL)
  497. {
  498. // Ignore events for a bit after blanking to allow
  499. // for key-up, mouse jiggle, etc...
  500. if (csecIgnoreDelay > 0)
  501. csecIgnoreDelay -= 1;
  502. BlankMouse(TRUE);
  503. FSendSsm(SSM_ANIMATE, cvs, 0L, 0L);
  504. }
  505. break;
  506. default:
  507. return DefWindowProc(hwnd, wm, wParam, lParam);
  508. }
  509. return 0;
  510. }
  511. BOOL APIENTRY FInitScrSave(HAB habExe, HWND hwndUI) /* NOTE: hab is hInstance for Win */
  512. {
  513. WNDCLASS wndclass;
  514. if (fInited)
  515. {
  516. #ifdef DEBUG
  517. MessageBox(NULL, "Already initialized!", "IdleWild", MB_OK);
  518. #endif
  519. return FALSE;
  520. }
  521. fWin30 = (GETMAJORVERSION(GetVersion()) == 0x0003);
  522. hwndApp = hwndUI;
  523. wmScrSave = RegisterWindowMessage("SCRSAVE"); // REVIEW: for win 3.1
  524. dxScreen = GetSystemMetrics(SM_CXSCREEN);
  525. dyScreen = GetSystemMetrics(SM_CYSCREEN);
  526. wndclass.style = 0;
  527. wndclass.lpfnWndProc = WinProcBlanker;
  528. wndclass.cbClsExtra = 0;
  529. wndclass.cbWndExtra = 0;
  530. wndclass.hInstance = hab;
  531. wndclass.hIcon = NULL;
  532. wndclass.hCursor = NULL;
  533. wndclass.hbrBackground = NULL;
  534. wndclass.lpszMenuName = (LPSTR) 0;
  535. wndclass.lpszClassName = "IWBKG";
  536. if (!RegisterClass(&wndclass))
  537. {
  538. #ifdef DEBUG
  539. MessageBox(NULL, "Cannot register IWBKG class!", "IdleWild", MB_OK);
  540. #endif
  541. return fFalse;
  542. }
  543. if ((hwnd = hwndClient = CreateWindow("IWBKG", NULL, WS_POPUP,
  544. -2, 0, 1, 1, NULL, NULL, hab, NULL)) == hNil)
  545. {
  546. MessageBox(NULL, "Cannot create a window!",
  547. "IdleWild", MB_OK);
  548. return fFalse;
  549. }
  550. while (!SetTimer(hwnd, tidSecond, 250, hNil))
  551. {
  552. if (MessageBox(hwnd, "Too many clocks or timers!",
  553. "IdleWild", MB_RETRYCANCEL) == IDCANCEL)
  554. {
  555. return FALSE;
  556. }
  557. }
  558. ShowWindow(hwnd, SW_HIDE);
  559. SetWindowPos(hwnd, NULL, 0, 0, dxScreen, dyScreen,
  560. SWP_NOACTIVATE | SWP_NOZORDER);
  561. if (fWin30 && !FSetHwndHook(hab, hwnd))
  562. {
  563. #ifdef DEBUG
  564. MessageBox(NULL, "Cannot set hook!", "IdleWild", MB_OK);
  565. #endif
  566. return FALSE;
  567. }
  568. DelayAction();
  569. fInited = fTrue;
  570. UNREFERENCED_PARAMETER(habExe);
  571. return TRUE;
  572. }
  573. VOID APIENTRY TermScrSave()
  574. {
  575. HANDLE hssb, hssbNext;
  576. SSB * pssb;
  577. if (!fInited)
  578. return;
  579. BlankScreen(FALSE);
  580. if (fWin30)
  581. UnhookWindowsHook(WH_KEYBOARD, BlankerHook);
  582. DestroyWindow(hwnd);
  583. UnregisterClass("IWBKG", hab);
  584. for (hssb = hssbList; hssb != NULL; hssb = hssbNext)
  585. {
  586. pssb = (SSB *) LocalLock(hssb);
  587. FreeLibrary(pssb->hdll);
  588. hssbNext = pssb->hssbNext;
  589. LocalUnlock(hssb);
  590. LocalFree(hssb);
  591. }
  592. hwnd = NULL;
  593. hab = NULL;
  594. fInited = fFalse;
  595. }
  596. #endif
  597. VOID QuarterSecond()
  598. {
  599. static POINT pt;
  600. if (fDelayAction)
  601. {
  602. fDelayAction = FALSE;
  603. if (csecIgnoreDelay == 0)
  604. DelayAction();
  605. }
  606. GetMousePos(&pt);
  607. // Check for mouse movement...
  608. if (pt.x != ptMouseOld.x || pt.y != ptMouseOld.y)
  609. {
  610. BlankMouse(FALSE);
  611. if (csecIgnoreDelay == 0)
  612. DelayAction();
  613. }
  614. if (pt.x == dxScreen - 1)
  615. {
  616. #ifdef PM
  617. if (pt.y == dyScreen - 1)
  618. #endif
  619. #ifdef WIN
  620. if (pt.y == 0)
  621. #endif
  622. {
  623. // Blank the screen if mouse is moved to the
  624. // upper-right corner...
  625. BlankScreen(fTrue);
  626. csecTilBlank = 0;
  627. }
  628. #ifdef PM
  629. else if (pt.y == 0)
  630. #endif
  631. #ifdef WIN
  632. else if (pt.y == dyScreen - 1)
  633. #endif
  634. {
  635. // Disable the blanker when the mouse is in
  636. // the lower-right corner...
  637. BlankScreen(fFalse);
  638. csecTilBlank = csecTimeout;
  639. }
  640. }
  641. ptMouseOld = pt;
  642. }
  643. VOID EverySecond()
  644. {
  645. // Take care of mouse blanking...
  646. if (fBlankPtr && csecTilMouseBlank > 0 && !FAnyMouseDown())
  647. {
  648. csecTilMouseBlank -= 1;
  649. if (csecTilMouseBlank == 0)
  650. BlankMouse(TRUE);
  651. }
  652. // Countdown screen blank timer or send second message to blanker...
  653. if (fWin30 && csecTilBlank > 0)
  654. {
  655. csecTilBlank -= 1;
  656. if (csecTilBlank == 0)
  657. BlankScreen(fTrue);
  658. }
  659. if (fScreenHidden || fBackground)
  660. {
  661. if (fScreenHidden)
  662. MoveHwndToFront(hwnd);
  663. else
  664. MoveHwndToBack(hwnd);
  665. if (csecTilReblank > 0 && --csecTilReblank == 0)
  666. ScrChooseRandomServer();
  667. FSendSsm(SSM_SECOND, 0L, 0L, 0L);
  668. }
  669. }
  670. VOID DelayAction()
  671. {
  672. csecTilBlank = csecTimeout;
  673. if (fScreenHidden)
  674. {
  675. if (!fBackground)
  676. {
  677. // It *should* be safe to stop the timer even if
  678. // it was never started.
  679. StopTimer(tidAnimate);
  680. }
  681. BlankScreen(fFalse);
  682. }
  683. GetMousePos(&ptMouseOld);
  684. }
  685. VOID BlankMouse(F fBlank)
  686. {
  687. if (!fBlank)
  688. csecTilMouseBlank = csecMouseTimeout;
  689. if (!fBlank == !fMouseHidden)
  690. return;
  691. fMouseHidden = fBlank;
  692. ShowMouse(!fBlank);
  693. }
  694. VOID BlankScreen(F fBlank)
  695. {
  696. #ifdef WIN
  697. if (fBlank)
  698. {
  699. HWND hwnd;
  700. hwnd = GetActiveWindow();
  701. if (FDosModeHwnd(hwnd) /*&& !IsIconic(hwnd)*/ ||
  702. FindWindow("CbtComm", NULL))
  703. {
  704. DelayAction();
  705. return;
  706. }
  707. }
  708. #endif
  709. BlankMouse(fBlank);
  710. if (!fBlank == !fScreenHidden)
  711. return;
  712. if (fBlank)
  713. {
  714. PostMessage((HWND)0xffff, wmScrSave, 1, 0); // REVIEW: for win 3.1
  715. MoveHwndToFront(hwnd);
  716. ShowHwnd(hwnd, fTrue);
  717. GetMousePos(&ptMouseOld);
  718. // If we can't get a canvas, there will be no animation...
  719. if (cvs == NULL && (cvs = CvsFromHwnd(hwndClient)) == NULL)
  720. return;
  721. SetPrio(prioIdle);
  722. if (fRandServer)
  723. ScrChooseRandomServer();
  724. fScreenHidden = fTrue;
  725. fNoBlackout = FSendSsm(SSM_BLANK, cvs, 0L, 0L);
  726. // Starting that timer might fail, in which case there will
  727. // be no animation, but the screen will still be blank...
  728. if (!FStartTimer(tidAnimate, 0))
  729. fNoBlackout = fFalse;
  730. csecIgnoreDelay = 4;
  731. }
  732. else
  733. {
  734. PostMessage((HWND)0xffff, wmScrSave, 0, 0); // REVIEW: for win 3.1
  735. FSendSsm(SSM_UNBLANK, cvs, 0L, 0L);
  736. fScreenHidden = fFalse;
  737. if (fBackground)
  738. {
  739. MoveHwndToBack(hwnd);
  740. /* ShowHwnd(hwnd, fTrue); /* already shown */
  741. }
  742. else
  743. {
  744. SetPrio(prioNormal);
  745. ShowHwnd(hwnd, fFalse);
  746. if (cvs != NULL)
  747. {
  748. ReleaseCvs(hwndClient, cvs);
  749. cvs = NULL;
  750. }
  751. }
  752. }
  753. }
  754. BOOL APIENTRY ScrSetServer(PSZ szName)
  755. {
  756. #ifdef PM
  757. SSB FAR * pssb;
  758. #endif
  759. #ifdef WIN
  760. HANDLE hssb;
  761. #endif
  762. csecTilReblank = 0; // Disable random re-blanker for now...
  763. // Random
  764. if (szName == NULL)
  765. {
  766. fRandServer = fTrue;
  767. return fTrue;
  768. }
  769. // Blackness
  770. if (szName[0] == '\0')
  771. {
  772. #ifdef PM
  773. SetPssbCur(NULL);
  774. #endif
  775. #ifdef WIN
  776. SetHssbCur(NULL);
  777. #endif
  778. fRandServer = fFalse;
  779. return fTrue;
  780. }
  781. // Named server
  782. #ifdef PM
  783. if ((pssb = PssbFindSz(szName)) == NULL)
  784. return fFalse;
  785. SetPssbCur(pssb);
  786. #endif
  787. #ifdef WIN
  788. if ((hssb = HssbFindSz(szName)) == NULL)
  789. return FALSE;
  790. SetHssbCur(hssb);
  791. #endif
  792. fRandServer = fFalse;
  793. return fTrue;
  794. }
  795. SHORT FCompPszPsz(PSZ psz1, PSZ psz2)
  796. {
  797. CHAR FAR * lpch1, FAR * lpch2;
  798. lpch1 = psz1;
  799. lpch2 = psz2;
  800. while (*lpch1 == *lpch2 && *lpch1 != '\0')
  801. {
  802. lpch1 += 1;
  803. lpch2 += 1;
  804. }
  805. return *lpch1 == '\0' && *lpch2 == '\0';
  806. }
  807. #ifdef PM
  808. SSB FAR * PssbFindSz(PSZ sz)
  809. {
  810. SSB FAR * pssb;
  811. for (pssb = pssbList; pssb != NULL; pssb = pssb->pssbNext)
  812. {
  813. if (FCompPszPsz(pssb->szName, sz))
  814. return pssb;
  815. }
  816. return NULL;
  817. }
  818. #endif
  819. #ifdef WIN
  820. HANDLE HssbFindSz(PSZ sz)
  821. {
  822. HANDLE hssb, hssbNext;
  823. SSB * pssb;
  824. for (hssb = hssbList; hssb != NULL; hssb = hssbNext)
  825. {
  826. F fSame;
  827. pssb = (SSB *) LocalLock(hssb);
  828. fSame = FCompPszPsz(pssb->szName, sz);
  829. hssbNext = pssb->hssbNext;
  830. LocalUnlock(hssb);
  831. if (fSame)
  832. return hssb;
  833. }
  834. return NULL;
  835. }
  836. #endif
  837. #ifdef PM
  838. SSB FAR * PssbIssb(issb)
  839. INT issb;
  840. {
  841. SSB FAR * pssb;
  842. for (pssb = pssbList; pssb != NULL && issb-- > 0;
  843. pssb = pssb->pssbNext)
  844. ;
  845. return pssb;
  846. }
  847. #endif
  848. #ifdef WIN
  849. HANDLE HssbIssb(issb)
  850. INT issb;
  851. {
  852. HANDLE hssb, hssbNext;
  853. SSB * pssb;
  854. for (hssb = hssbList; hssb != NULL && issb-- > 0; hssb = hssbNext)
  855. {
  856. pssb = (SSB *) LocalLock(hssb);
  857. hssbNext = pssb->hssbNext;
  858. LocalUnlock(hssb);
  859. }
  860. return hssb;
  861. }
  862. #endif
  863. VOID APIENTRY ScrChooseRandomServer()
  864. {
  865. csecTilReblank = csecTimeout * 4; // REVIEW: make an option?
  866. #ifdef PM
  867. SetPssbCur(PssbIssb(WRand(cssbRegistered)));
  868. #endif
  869. #ifdef WIN
  870. SetHssbCur(HssbIssb(WRand(cssbRegistered)));
  871. #endif
  872. }
  873. SHORT APIENTRY ScrLoadServer(PSZ szDllName)
  874. {
  875. #ifdef PM
  876. NPBYTE npb;
  877. SSB FAR * pssb;
  878. HMODULE hmod;
  879. SCRSAVEPROC lpfnSaver;
  880. CHAR szFailure [80];
  881. CHAR szName [80];
  882. CHAR szDesc [256];
  883. if (DosLoadModule(szFailure, sizeof (szFailure), szDllName, &hmod) != 0)
  884. return fFalse;
  885. if (DosGetProcAddr(hmod, "SCRSAVEPROC", &lpfnSaver) != 0)
  886. {
  887. DosFreeModule(hmod);
  888. return fFalse;
  889. }
  890. CopyPszToPsz(szDllName, szName);
  891. (*lpfnSaver)(SSM_OPEN, szName,
  892. (LONG_PTR) szDesc, ((LONG) dyScreen << 16) + dxScreen);
  893. if ((npb = WinAllocMem(hheap,
  894. cbSSBBase + CchLenPsz(szName) + 1)) == NULL)
  895. {
  896. DosFreeModule(hmod);
  897. return fFalse;
  898. }
  899. pssb = (SSB FAR *) MAKEP(selHeap, npb);
  900. pssb->lpfnSaver = lpfnSaver;
  901. pssb->pssbNext = pssbList;
  902. CopyPszToPsz(szName, pssb->szName);
  903. pssbList = pssb;
  904. cssbRegistered += 1;
  905. SetPssbCur(pssb);
  906. return fTrue;
  907. #endif
  908. #ifdef WIN
  909. HMODULE hdll;
  910. HANDLE hssb;
  911. SSB * pssb;
  912. SCRSAVEPROC lpfnSaver;
  913. CHAR szName [80];
  914. CHAR szDesc [256];
  915. if ((hdll = MLoadLibrary(szDllName)) == NULL)
  916. {
  917. #ifdef DEBUG
  918. MessageBox(NULL, szDllName, "IdleWild cannot load:", MB_OK);
  919. #endif
  920. return FALSE;
  921. }
  922. if ((lpfnSaver = (SCRSAVEPROC)GetProcAddress(hdll, "SCRSAVEPROC")) == NULL)
  923. {
  924. MessageBox(NULL, "Invalid module!", "IdleWild", MB_OK);
  925. FreeLibrary(hdll);
  926. return FALSE;
  927. }
  928. CopyPszToPsz(szDllName, szName);
  929. szDesc[0] = '\0';
  930. (*lpfnSaver)(SSM_OPEN, szName,
  931. (LONG_PTR) szDesc, ((LONG) dyScreen << 16) + dxScreen);
  932. hssb = LocalAlloc(LMEM_MOVEABLE, cbSSBBase + CchLenPsz(szName) + 1 +
  933. CchLenPsz(szDesc) + 1);
  934. if (hssb == NULL)
  935. {
  936. MessageBox(NULL, "Not enough memory!", "IdleWild", MB_OK);
  937. FreeLibrary(hdll);
  938. return FALSE;
  939. }
  940. pssb = (SSB *) LocalLock(hssb);
  941. pssb->lpfnSaver = lpfnSaver;
  942. pssb->hdll = hdll;
  943. pssb->hssbNext = hssbList;
  944. CopyPszToPsz(szName, pssb->szName);
  945. CopyPszToPsz(szDesc, pssb->szName + CchLenPsz(szName) + 1);
  946. LocalUnlock(hssb);
  947. hssbList = hssb;
  948. cssbRegistered += 1;
  949. SetHssbCur(hssb);
  950. return TRUE;
  951. #endif
  952. }
  953. VOID APIENTRY ScrQueryServerDesc(PSZ szBuf)
  954. {
  955. #ifdef PM
  956. if (fRandServer || pssbCur == NULL)
  957. szBuf[0] = '\0';
  958. else
  959. {
  960. CopyPszToPsz(pssbCur->szName + CchLenPsz(pssbCur->szName) + 1,
  961. szBuf);
  962. }
  963. #endif
  964. #ifdef WIN
  965. if (fRandServer || hssbCur == NULL)
  966. szBuf[0] = '\0';
  967. else
  968. {
  969. SSB * pssb;
  970. pssb = (SSB *) LocalLock(hssbCur);
  971. CopyPszToPsz(pssb->szName + CchLenPsz(pssb->szName) + 1,
  972. szBuf);
  973. LocalUnlock(hssbCur);
  974. }
  975. #endif
  976. }
  977. VOID APIENTRY ScrQueryServerName(PSZ szBuf)
  978. {
  979. #ifdef PM
  980. if (pssbCur == NULL)
  981. szBuf[0] = '\0';
  982. else
  983. CopyPszToPsz(pssbCur->szName, szBuf);
  984. #endif
  985. #ifdef WIN
  986. if (hssbCur == NULL)
  987. szBuf[0] = '\0';
  988. else
  989. {
  990. SSB * pssb;
  991. pssb = (SSB *) LocalLock(hssbCur);
  992. CopyPszToPsz(pssb->szName, szBuf);
  993. LocalUnlock(hssbCur);
  994. }
  995. #endif
  996. }
  997. VOID CopyPszToPsz(PSZ pszFrom, PSZ pszTo)
  998. {
  999. CHAR FAR * lpchFrom, FAR * lpchTo;
  1000. lpchFrom = pszFrom;
  1001. lpchTo = pszTo;
  1002. while ((*lpchTo++ = *lpchFrom++) != '\0')
  1003. ;
  1004. }
  1005. INT CchLenPsz(PSZ psz)
  1006. {
  1007. CHAR FAR * pch;
  1008. for (pch = psz; *pch != '\0'; pch += 1)
  1009. ;
  1010. return (INT) (pch - psz);
  1011. }
  1012. void GetMousePos(ppt)
  1013. LPPOINT ppt;
  1014. {
  1015. #ifdef PM
  1016. WinQueryPointerPos(HWND_DESKTOP, ppt);
  1017. #endif
  1018. #ifdef WIN
  1019. GetCursorPos(ppt);
  1020. #endif
  1021. }
  1022. F FStartTimer(tid, ms)
  1023. INT tid, ms;
  1024. {
  1025. #ifdef PM
  1026. return WinStartTimer(hab, hwndClient, tid, ms);
  1027. #endif
  1028. #ifdef WIN
  1029. return (F)SetTimer(hwndClient, tid, ms, NULL);
  1030. #endif
  1031. }
  1032. void StopTimer(INT tid)
  1033. {
  1034. #ifdef PM
  1035. WinStopTimer(hab, hwndClient, tid);
  1036. #endif
  1037. #ifdef WIN
  1038. KillTimer(hwndClient, tid);
  1039. #endif
  1040. }
  1041. void ShowHwnd(hwnd, fShow)
  1042. HWND hwnd;
  1043. F fShow;
  1044. {
  1045. #ifdef PM
  1046. WinShowWindow(hwnd, fShow);
  1047. #endif
  1048. #ifdef WIN
  1049. ShowWindow(hwnd, fShow ? SW_SHOW : SW_HIDE);
  1050. #endif
  1051. }
  1052. void MoveHwndToFront(hwnd)
  1053. HWND hwnd;
  1054. {
  1055. #ifdef PM
  1056. WinSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER);
  1057. #endif
  1058. #ifdef WIN
  1059. SetWindowPos(hwnd, (HWND) 0, 0, 0, 0, 0,
  1060. SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  1061. #endif
  1062. }
  1063. void MoveHwndToBack(hwnd)
  1064. HWND hwnd;
  1065. {
  1066. #ifdef PM
  1067. WinSetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_ZORDER);
  1068. #endif
  1069. #ifdef WIN
  1070. SetWindowPos(hwnd, (HWND) 1, 0, 0, 0, 0,
  1071. SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  1072. #endif
  1073. }
  1074. CVS CvsFromHwnd(hwnd)
  1075. HWND hwnd;
  1076. {
  1077. #ifdef PM
  1078. return WinGetPS(hwnd);
  1079. #endif
  1080. #ifdef WIN
  1081. return GetDC(hwnd);
  1082. #endif
  1083. }
  1084. void ReleaseCvs(hwnd, cvs)
  1085. HWND hwnd;
  1086. CVS cvs;
  1087. {
  1088. #ifdef PM
  1089. WinReleasePS(cvs);
  1090. #endif
  1091. #ifdef WIN
  1092. ReleaseDC(hwnd, cvs);
  1093. #endif
  1094. }
  1095. void InvalHwnd(hwnd)
  1096. HWND hwnd;
  1097. {
  1098. #ifdef PM
  1099. WinInvalidateRect(hwnd, NULL, TRUE);
  1100. #endif
  1101. #ifdef WIN
  1102. InvalidateRect(hwnd, NULL, FALSE);
  1103. #endif
  1104. }
  1105. void EraseScreen()
  1106. {
  1107. #ifdef PM
  1108. RECTL rectl;
  1109. rectl.xLeft = 0;
  1110. rectl.yBottom = 0;
  1111. rectl.xRight = dxScreen;
  1112. rectl.yTop = dyScreen;
  1113. WinFillRect(cvs, &rectl, CLR_BLACK);
  1114. #endif
  1115. #ifdef WIN
  1116. PatBlt(cvs, 0, 0, dxScreen, dyScreen, BLACKNESS);
  1117. #endif
  1118. }
  1119. void SetPrio(INT prio)
  1120. {
  1121. #ifdef PM
  1122. DosSetPrty(PRTYS_PROCESS, prio, 0, 0);
  1123. #else
  1124. UNREFERENCED_PARAMETER(prio);
  1125. #endif
  1126. }
  1127. F FAnyMouseDown()
  1128. {
  1129. #ifdef PM
  1130. return (WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000) != 0 ||
  1131. (WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000) != 0 ||
  1132. (WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000) != 0;
  1133. #endif
  1134. #ifdef WIN
  1135. return (GetKeyState(VK_LBUTTON) & 0x8000) != 0 ||
  1136. (GetKeyState(VK_MBUTTON) & 0x8000) != 0 ||
  1137. (GetKeyState(VK_RBUTTON) & 0x8000) != 0;
  1138. #endif
  1139. }
  1140. void ShowMouse(fShow)
  1141. F fShow;
  1142. {
  1143. #ifdef PM
  1144. WinShowPointer(HWND_DESKTOP, fShow);
  1145. #endif
  1146. #ifdef WIN
  1147. ShowCursor(fShow);
  1148. #endif
  1149. }
  1150. #ifdef WIN
  1151. VOID APIENTRY ScrInvokeDlg(HANDLE hInst, HWND hwnd)
  1152. {
  1153. FSendSsm(SSM_DIALOG, hInst, (LONG_PTR) hwnd, 0L);
  1154. }
  1155. #endif
  1156. #ifdef WIN
  1157. BOOL FDosModeHwnd(HWND hwnd)
  1158. {
  1159. #ifdef YUCKY
  1160. extern BOOL APIENTRY IsWinOldAppTask(HANDLE);
  1161. if (GETMAJORVERSION(GetVersion()) == 0x0003)
  1162. #endif
  1163. return FALSE;
  1164. #ifdef YUCKY
  1165. return IsWinOldAppTask(GetWindowTask(hwnd));
  1166. #endif
  1167. #ifdef YUCKY
  1168. HMENU hmenu;
  1169. INT iItem, cItems;
  1170. BOOL fFoundPopup;
  1171. hmenu = GetSystemMenu(hwnd, FALSE);
  1172. cItems = GetMenuItemCount(hmenu);
  1173. fFoundPopup = FALSE;
  1174. for (iItem = 0; iItem < cItems; iItem += 1)
  1175. {
  1176. if (GetSubMenu(hmenu, iItem) != NULL)
  1177. {
  1178. fFoundPopup = TRUE;
  1179. break;
  1180. }
  1181. }
  1182. return fFoundPopup;
  1183. #endif
  1184. UNREFERENCED_PARAMETER(hwnd);
  1185. }
  1186. #endif
  1187. INT APIENTRY RestoreEnumProc(HWND hwnd, LPARAM lParam)
  1188. {
  1189. UpdateWindow(hwnd);
  1190. UNREFERENCED_PARAMETER(lParam);
  1191. return TRUE;
  1192. }
  1193. VOID APIENTRY ScrRestoreScreen()
  1194. {
  1195. ShowHwnd(hwnd, fFalse);
  1196. EnumWindows(RestoreEnumProc, 0);
  1197. ShowHwnd(hwnd, fTrue);
  1198. }