1 /*
2  *  Copyright 2003 J Brown
3  *  Copyright 2006 Eric Kohl
4  *  Copyright 2007 Marc Piulachs (marc.piulachs@codexchange.net)
5  *  Copyright 2015 Daniel Reimer
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21 
22 #include <windows.h>
23 #include <tchar.h>
24 #include <scrnsave.h>
25 #include "resource.h"
26 
27 #define RANDOM( min, max ) ((rand() % (int)(((max)+1) - (min))) + (min))
28 
29 #define MAX_LOADSTRING 100
30 #define MAX_STARS 1000
31 
32 #define APPNAME            _T("Starfield")
33 #define APP_TIMER          1
34 #define APP_TIMER_INTERVAL 20
35 
36 #define MAX_STARS 1000
37 
38 // Details of each individual star
39 typedef struct star
40 {
41     int m_nXPos, m_nYPos, m_nZPos;
42     int m_nOldX, m_nOldY;
43 } STAR;
44 
45 STAR *stars;
46 
47 int m_nTotStars;
48 int m_nCenterX, m_nCenterY;
49 
50 void DrawStarField (HDC pDC)
51 {
52     int nX, nY;
53     int i;
54     for (i = 0; i < m_nTotStars; i++)
55     {
56         // Clear last position of this star
57         SetPixel (
58             pDC,
59             stars[i].m_nOldX,
60             stars[i].m_nOldY,
61             RGB (0, 0, 0));
62 
63         nX = (int)((((long)stars[i].m_nXPos << 7) / (long)stars[i].m_nZPos) + m_nCenterX);
64         nY = (int)((((long)stars[i].m_nYPos << 7) / (long)stars[i].m_nZPos) + m_nCenterY);
65 
66         // Draw star
67         SetPixel (
68             pDC,
69             nX,
70             nY,
71             RGB (255, 255, 255));
72 
73         // Remember current position for clearing later
74         stars[i].m_nOldX = nX;
75         stars[i].m_nOldY = nY;
76     }
77 }
78 
79 BOOL SetUpStars (int nNumStars)
80 {
81     int i;
82     if (nNumStars > MAX_STARS)
83     {
84         MessageBox (0,
85             _T("Too many stars! Aborting!"),
86             _T("Error"),
87             MB_OK | MB_ICONWARNING);
88         return FALSE;
89     }
90 
91     if (stars)
92         free (stars);
93 
94     m_nTotStars = nNumStars;
95 
96     stars = (STAR*)malloc(nNumStars * sizeof(STAR));
97 
98     if (!stars)
99     {
100         MessageBox (0,
101             _T("Unable to allocate memory! Aborting!"),
102             _T("Error"),
103             MB_OK | MB_ICONWARNING);
104         return FALSE;
105     }
106 
107     for (i = 0; i < m_nTotStars; i++)
108     {
109         do
110         {
111             stars[i].m_nXPos = RANDOM (-320, 320);
112             stars[i].m_nYPos = RANDOM (-200, 200);
113             stars[i].m_nZPos = i+1;
114             stars[i].m_nOldX = -1;
115             stars[i].m_nOldY = -1;
116         } while ((stars[i].m_nXPos == 0) || (stars[i].m_nYPos == 0));
117     }
118     return TRUE;
119 }
120 
121 void MoveStarField (int nXofs, int nYofs, int nZofs)
122 {
123     int i;
124     for (i = 0; i < m_nTotStars; i++)
125     {
126         stars[i].m_nXPos += nXofs;
127         stars[i].m_nYPos += nYofs;
128         stars[i].m_nZPos += nZofs;
129 
130         if (stars[i].m_nZPos > m_nTotStars)
131             stars[i].m_nZPos -= m_nTotStars;
132         if (stars[i].m_nZPos < 1)
133             stars[i].m_nZPos += m_nTotStars;
134     }
135 }
136 
137 void SetDimensions (int nWidth, int nHeight)
138 {
139     m_nCenterX = nWidth / 2;
140     m_nCenterY = nHeight / 2;
141 }
142 
143 LRESULT WINAPI ScreenSaverProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
144 {
145     static HDC pDC;
146 
147     switch (msg)
148     {
149         case WM_CREATE:
150         {
151             SetTimer (
152                 hwnd,
153                 APP_TIMER,
154                 APP_TIMER_INTERVAL,
155                 NULL);
156         }
157         break;
158         case WM_PAINT:
159         {
160             PAINTSTRUCT    PtStr;
161             HDC pDC = BeginPaint (hwnd, &PtStr);
162             DrawStarField (pDC);
163             EndPaint (hwnd, &PtStr);
164             SetUpStars(250);
165             return (0);
166         }
167         break;
168         case WM_TIMER:
169         {
170             if (wParam == APP_TIMER)
171             {
172                 MoveStarField (0, 0, -3);
173                 pDC = GetDC(hwnd);
174                 DrawStarField (pDC);
175                 ReleaseDC(hwnd, pDC);
176             }
177         }
178         break;
179         case WM_SIZE:
180         {
181             // Change the center point of the starfield
182             SetDimensions (
183                 LOWORD(lParam),
184                 HIWORD(lParam));
185         }
186         break;
187         case WM_DESTROY:
188         {
189             KillTimer (hwnd, APP_TIMER);
190             free(stars);
191             ShowCursor(TRUE);
192             PostQuitMessage (0);
193             return 0;
194         }
195         break;
196         default:
197             return DefScreenSaverProc(hwnd, msg, wParam, lParam);
198     }
199     return 0;
200 }
201 
202 BOOL WINAPI ScreenSaverConfigureDialog(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
203 {
204     return FALSE;
205 }
206 
207 BOOL WINAPI RegisterDialogClasses(HANDLE hmodule)
208 {
209     TCHAR szTitle[256];
210     TCHAR szText[256];
211 
212     LoadString(hmodule,
213             IDS_TITLE,
214             szTitle,
215             256);
216 
217     LoadString(hmodule,
218             IDS_TEXT,
219             szText,
220             256);
221 
222     MessageBox(0,
223             szText,
224             szTitle,
225             MB_OK | MB_ICONWARNING);
226     return FALSE;
227 }