1 /*
2  * notevil.c
3  *
4  * --------------------------------------------------------------------
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this software; see the file COPYING.LIB. If
18  * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19  * Cambridge, MA 02139, USA.
20  *
21  * --------------------------------------------------------------------
22  * ReactOS Coders Console Parade
23  *
24  * 19990411 EA
25  * 19990515 EA
26  */
27 
28 #include <windows.h>
29 #include <stdio.h>
30 #include "resource.h"
31 
32 // #define DISPLAY_COORD
33 
34 LPCWSTR app_name = L"notevil";
35 
36 HANDLE  myself;
37 HANDLE  ScreenBuffer;
38 CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo;
39 HANDLE  WaitableTimer;
40 
41 VOID
42 WriteStringAt(LPWSTR lpString,
43               COORD  xy,
44               WORD   wColor)
45 {
46     DWORD cWritten = 0;
47     WORD  wLen;
48 
49     if (!lpString || *lpString == 0) return;
50 
51     wLen = wcslen(lpString);
52 
53     /* Don't bother writing text when erasing */
54     if (wColor)
55     {
56         WriteConsoleOutputCharacterW(ScreenBuffer,
57                                      lpString,
58                                      wLen,
59                                      xy,
60                                      &cWritten);
61     }
62 
63     FillConsoleOutputAttribute(ScreenBuffer,
64                                wColor,
65                                wLen,
66                                xy,
67                                &cWritten);
68 }
69 
70 
71 #ifdef DISPLAY_COORD
72 VOID
73 WriteCoord(COORD c)
74 {
75     COORD xy = {0,0};
76     WCHAR buf[40];
77 
78     wsprintf(buf, L"x=%02d  y=%02d", c.X, c.Y);
79 
80     WriteStringAt(buf, xy,
81                   BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
82 }
83 #endif /* def DISPLAY_COORD */
84 
85 
86 VOID
87 GetNextString(LPWSTR Buffer,
88               INT    BufferSize,
89               PDWORD Index)
90 {
91     if (RES_LAST_INDEX == *Index)
92         *Index = RES_FIRST_INDEX;
93     else
94         ++*Index;
95 
96     LoadStringW(myself, *Index, Buffer, BufferSize);
97 }
98 
99 
100 VOID
101 DisplayTitle(VOID)
102 {
103     LPWSTR szTitle = L"ReactOS Coders Console Parade";
104     COORD  xy;
105 
106     xy.X = (ScreenBufferInfo.dwSize.X - wcslen(szTitle)) / 2;
107     xy.Y = ScreenBufferInfo.dwSize.Y / 2;
108 
109     WriteStringAt(szTitle, xy,
110                   FOREGROUND_GREEN | FOREGROUND_INTENSITY);
111 }
112 
113 
114 #define RES_DELAY_CHANGE 12
115 #define RES_BUFFER_SIZE  1024
116 VOID
117 MainLoop(VOID)
118 {
119     WCHAR NameString[RES_BUFFER_SIZE];
120     DWORD NameIndex  = 0;
121     INT   NameLength = 0;
122     COORD xy;
123     INT   n = RES_DELAY_CHANGE;
124     INT   dir_y  = 1;
125     INT   dir_x  = 1;
126     WORD  wColor = 1;
127 
128     xy.X = ScreenBufferInfo.dwSize.X / 2;
129     xy.Y = ScreenBufferInfo.dwSize.Y / 2;
130 
131     for ( ; 1; ++n )
132     {
133         if (n == RES_DELAY_CHANGE)
134         {
135             n = 0;
136 
137             GetNextString(NameString,
138                           RES_BUFFER_SIZE,
139                           &NameIndex);
140             NameLength = wcslen(NameString);
141 
142             wColor++;
143             if ((wColor & 0x000F) == 0)
144                 wColor = 1;
145         }
146         if (xy.X == 0)
147         {
148             if (dir_x == -1)
149                 dir_x = 1;
150         }
151         else if (xy.X >= ScreenBufferInfo.dwSize.X - NameLength - 1)
152         {
153             if (dir_x == 1)
154                 dir_x = -1;
155         }
156         xy.X += dir_x;
157 
158         if (xy.Y == 0)
159         {
160             if (dir_y == -1)
161                 dir_y = 1;
162         }
163         else if (xy.Y >= ScreenBufferInfo.dwSize.Y - 1)
164         {
165             if (dir_y == 1)
166                 dir_y = -1;
167         }
168         xy.Y += dir_y;
169 
170 #ifdef DISPLAY_COORD
171         WriteCoord(xy);
172 #endif /* def DISPLAY_COORD */
173 
174         DisplayTitle();
175         WriteStringAt(NameString, xy, wColor);
176         WaitForSingleObject(WaitableTimer, INFINITE);
177         WriteStringAt(NameString, xy, 0);
178     }
179 }
180 
181 
182 int wmain(int argc, WCHAR* argv[])
183 {
184     LARGE_INTEGER lint;
185     DWORD Written;
186     COORD Coord = { 0, 0 };
187 
188     myself = GetModuleHandle(NULL);
189 
190     GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
191                                &ScreenBufferInfo);
192     ScreenBufferInfo.dwSize.X = ScreenBufferInfo.srWindow.Right - ScreenBufferInfo.srWindow.Left + 1;
193     ScreenBufferInfo.dwSize.Y = ScreenBufferInfo.srWindow.Bottom - ScreenBufferInfo.srWindow.Top + 1;
194     ScreenBuffer = CreateConsoleScreenBuffer(GENERIC_WRITE,
195                                              0,
196                                              NULL,
197                                              CONSOLE_TEXTMODE_BUFFER,
198                                              NULL);
199     if (ScreenBuffer == INVALID_HANDLE_VALUE)
200     {
201         wprintf(L"%s: could not create a new screen buffer\n", app_name);
202         return EXIT_FAILURE;
203     }
204 
205     /* Fill buffer with black background */
206     FillConsoleOutputAttribute(ScreenBuffer,
207                                0,
208                                ScreenBufferInfo.dwSize.X * ScreenBufferInfo.dwSize.Y,
209                                Coord,
210                                &Written);
211 
212     WaitableTimer = CreateWaitableTimer(NULL, FALSE, NULL);
213     if (WaitableTimer == INVALID_HANDLE_VALUE)
214     {
215         wprintf(L"CreateWaitabletimer() failed\n");
216         return 1;
217     }
218     lint.QuadPart = -2000000;
219     if (!SetWaitableTimer(WaitableTimer, &lint, 200, NULL, NULL, FALSE))
220     {
221         wprintf(L"SetWaitableTimer() failed: 0x%lx\n", GetLastError());
222         return 2;
223     }
224     SetConsoleActiveScreenBuffer(ScreenBuffer);
225     MainLoop();
226     CloseHandle(ScreenBuffer);
227     return EXIT_SUCCESS;
228 }
229 
230 /* EOF */
231