1 : ////////////////////////////////////////////////////////////////// 2 : // ScrSave 3 : // 4 : // C program shell for screen saver application 5 : // Flying Pig 6 : // 1.00 (29 Aug 2006) 7 : ////////////////////////////////////////////////////////////////// 8 : 9 : ////////////////////////////////////////////////////////////////// 10 : // Includes 11 : 12 : #include "oslib/osmodule.h" 13 : #include "oslib/messagetrans.h" 14 : #include "oslib/wimp.h" 15 : #include "oslib/colourtrans.h" 16 : 17 : #include "ScrSave.h" 18 : #include "Bristle.h" 19 : 20 : #include 21 : #include 22 : #include 23 : #include 24 : #include 25 : #include 26 : #include 27 : 28 : #if defined _DEBUG 29 : #include 30 : #endif 31 : 32 : ////////////////////////////////////////////////////////////////// 33 : // Defines 34 : 35 : ////////////////////////////////////////////////////////////////// 36 : // Structures 37 : 38 : ////////////////////////////////////////////////////////////////// 39 : // Global variables 40 : 41 : static char gpcTemp[256]; 42 : static char *gpcMessages; 43 : static wimp_w gwhMain; 44 : static wimp_t gnTaskHandle; 45 : static char gacFontRef[255]; 46 : static int gnScreenWidth; 47 : static int gnScreenHeight; 48 : static os_t gnMonotonicTime; 49 : static int gnTimeInc; 50 : static os_t gnAnimationTime; 51 : 52 : static unsigned long gulPollWord; 53 : static unsigned long gulPollFlags = FLAGS_INIT; 54 : 55 : ////////////////////////////////////////////////////////////////// 56 : // Local function prototypes 57 : 58 : ////////////////////////////////////////////////////////////////// 59 : // Main application 60 : 61 : ////////////////////////////////////////////////////////////////// 62 : // Main program 63 : int main (int argc, char **argv) { 64 : wimp_block cBlock; 65 : wimp_version_no nVersion; 66 : int nCount; 67 : wimp_event_no nEvent; 68 : wimp_MESSAGE_LIST(2) sMessages = {{0u}}; 69 : wimp_message_list *psUserMessages = (wimp_message_list*)&sMessages; 70 : os_t nMonotonicTime = 0; 71 : wimp_draw sRedraw; 72 : 73 : // Initialise general variables 74 : gnTimeInc = 2; // Update window time (centiseconds) 75 : 76 : // Load Messages file 77 : gpcMessages = osmodule_alloc (17 + sizeof(MESSAGES)); 78 : strcpy(gpcMessages + 16, MESSAGES); 79 : 80 : messagetrans_open_file ((messagetrans_control_block*)gpcMessages, 81 : gpcMessages + 16, 0); 82 : 83 : // Initialise task 84 : gnTaskHandle = wimp_initialise (wimp_VERSION_RO3, Tag ("Tsk"), 85 : psUserMessages, & nVersion); 86 : 87 : // Load templates 88 : for (nCount = 0; nCount < 256; nCount++) { 89 : gacFontRef[nCount] = 0; 90 : } 91 : wimp_open_template (TEMPLATES); 92 : gwhMain = LoadTemplate ("Main"); 93 : 94 : // Close templates 95 : wimp_close_template (); 96 : 97 : // Check the command line arguments 98 : gulPollWord = 0u; 99 : if (argc >= 2) { 100 : // Read in the pollword in base 10 101 : gulPollWord = strtoul (argv[1], NULL, 10); 102 : } 103 : if ((argc < 2) || (gulPollWord == 0) || (gulPollWord == ULONG_MAX)) { 104 : // If there's a problem, we're not sticking around 105 : Quit (); 106 : } 107 : 108 : // Open main window 109 : OpenWindowScreenFull (gwhMain); 110 : 111 : // Initialise the animation 112 : InitAnimation (gnScreenWidth, gnScreenHeight); 113 : 114 : // Set up initial poll flags 115 : gulPollFlags |= (1 << 23); // High priority pollword (only for first call) 116 : gulPollFlags |= (1 << 22); // 'R3 is pointer to pollword' flag 117 : 118 : xos_read_monotonic_time (& gnMonotonicTime); 119 : gnAnimationTime = gnMonotonicTime; 120 : 121 : // Main polling loop 122 : ////////////////////////////////////////////////////////////////// 123 : do { 124 : nEvent = wimp_poll_idle (gulPollFlags, & cBlock, gnMonotonicTime, 125 : (int *)gulPollWord); 126 : xos_read_monotonic_time (& nMonotonicTime); 127 : if (nMonotonicTime >= gnMonotonicTime) { 128 : gnMonotonicTime = nMonotonicTime + gnTimeInc; 129 : } 130 : gulPollFlags &= ~(1 << 23); // Clear high priority pollword flag 131 : switch (nEvent) { 132 : case 0: // Null 133 : sRedraw.w = gwhMain; 134 : sRedraw.box.x0 = 0; 135 : sRedraw.box.x1 = gnScreenWidth; 136 : sRedraw.box.y0 = -gnScreenHeight; 137 : sRedraw.box.y1 = 0; 138 : AnimateScreenSaver ((float)(nMonotonicTime - gnAnimationTime), 139 : & sRedraw); 140 : gnAnimationTime = nMonotonicTime; 141 : break; 142 : case 1: // Redraw window 143 : RedrawWindow (& cBlock); 144 : break; 145 : case 2: // Open window 146 : OpenWindow (& cBlock); 147 : break; 148 : case 3: // Closewindow 149 : CloseWindow (& cBlock); 150 : break; 151 : case 4: // Pointer leaving window 152 : PointerLeavingWindow (& cBlock); 153 : break; 154 : case 5: // Pointer entering window 155 : PointerEnteringWindow (& cBlock); 156 : break; 157 : case 6: // Mouse click 158 : break; 159 : case 7: // User drag box 160 : break; 161 : case 8: // Keys 162 : break; 163 : case 9: // Menu select 164 : break; 165 : case 10: // Scroll request 166 : break; 167 : case 11: // Lose caret 168 : break; 169 : case 12: // Gain caret 170 : break; 171 : case 13: // Pollword non-zero (quit the screen saver) 172 : PollWordNonZero (); 173 : break; 174 : case 17: // Receive message 175 : case 18: 176 : Receive (& cBlock); 177 : break; 178 : case 19: // UserMessage Acknowledge 179 : break; 180 : default: // Default 181 : break; 182 : } 183 : } while TRUE; 184 : 185 : ////////////////////////////////////////////////////////////////// 186 : 187 : return 0; 188 : } 189 : 190 : ////////////////////////////////////////////////////////////////// 191 : // Poll 16,17: Message received 192 : void Receive (wimp_block *pcBlock) { 193 : switch (pcBlock->message.action) { 194 : case message_QUIT: 195 : Quit (); 196 : break; 197 : } 198 : } 199 : 200 : ////////////////////////////////////////////////////////////////// 201 : // Quit task 202 : void Quit (void) { 203 : int nCount; 204 : int nRemove; 205 : 206 : // Restore the mouse pointer 207 : wimp_set_pointer_shape (1, (void *)-1, 0, 0, 0, 0); 208 : 209 : // Free the fonts 210 : for (nCount = 0; nCount < 256; nCount++) { 211 : if (gacFontRef[nCount]) { 212 : for (nRemove = 0; nRemove < gacFontRef[nCount]; nRemove++) { 213 : xfont_lose_font ((font_f)nCount); 214 : } 215 : } 216 : } 217 : 218 : // Unset ScrSaver$Running 219 : xos_set_var_val ("ScrSaver$Running", "", -1, 0, os_VARTYPE_STRING, 220 : NULL, NULL); 221 : 222 : // Close the program 223 : wimp_close_down (gnTaskHandle); 224 : } 225 : 226 : ////////////////////////////////////////////////////////////////// 227 : // Poll 1: Redraw window 228 : void RedrawWindow (wimp_block *pcBlock) { 229 : wimp_draw sRedraw; 230 : bool boMore = TRUE; 231 : 232 : sRedraw = pcBlock->redraw; 233 : wimp_redraw_window (& sRedraw); 234 : while (boMore) { 235 : if (sRedraw.w == gwhMain) { 236 : // Redraw the screen saver, clearing first 237 : DrawScreenSaver (& sRedraw, ANIMDRAW_CLEAR); 238 : } 239 : boMore = wimp_get_rectangle (& sRedraw); 240 : } 241 : } 242 : 243 : ////////////////////////////////////////////////////////////////// 244 : // Poll 2: Open window given window block 245 : void OpenWindow (wimp_block *pcBlock) { 246 : xwimp_open_window (& pcBlock->open); 247 : } 248 : 249 : ////////////////////////////////////////////////////////////////// 250 : // Poll 4: Pointer leaving window 251 : void PointerLeavingWindow (wimp_block *pcBlock) { 252 : if (pcBlock->leaving.w == gwhMain) { 253 : // Restore the mouse pointer 254 : wimp_set_pointer_shape (1, (void *)-1, 0, 0, 0, 0); 255 : } 256 : } 257 : 258 : ////////////////////////////////////////////////////////////////// 259 : // Poll 5: Pointer entering window 260 : void PointerEnteringWindow (wimp_block *pcBlock) { 261 : if (pcBlock->entering.w == gwhMain) { 262 : // Hide the mouse pointer 263 : wimp_set_pointer_shape (0, (void *)-1, 0, 0, 0, 0); 264 : } 265 : } 266 : 267 : ////////////////////////////////////////////////////////////////// 268 : // Poll 13: Poll word non zero; time to quit the screen saver 269 : void PollWordNonZero (void) { 270 : gulPollFlags &= ~(1 << 22); // Clear 'R3 is pointer to pollword' flag 271 : Quit (); 272 : } 273 : 274 : ////////////////////////////////////////////////////////////////// 275 : // Open a window full screen 276 : void OpenWindowScreenFull (wimp_w whWindow) { 277 : int nHeight; 278 : int nWidth; 279 : int nEigFactor; 280 : int nSize; 281 : int nPosition; 282 : wimp_window_state sState; 283 : os_box sSize; 284 : 285 : sState.w = whWindow; 286 : xwimp_get_window_state (& sState); 287 : 288 : nWidth = sState.visible.x1 - sState.visible.x0; 289 : nHeight = sState.visible.y1 - sState.visible.y0; 290 : 291 : xos_read_mode_variable (os_CURRENT_MODE, os_MODEVAR_XEIG_FACTOR, 292 : & nEigFactor, NULL); 293 : xos_read_mode_variable (os_CURRENT_MODE, os_MODEVAR_XWIND_LIMIT, 294 : & nSize, NULL); 295 : gnScreenWidth = (nSize + 1) << nEigFactor; 296 : nPosition = (gnScreenWidth - nWidth) / 2; 297 : 298 : xos_read_mode_variable (os_CURRENT_MODE, os_MODEVAR_YEIG_FACTOR, 299 : & nEigFactor, NULL); 300 : xos_read_mode_variable (os_CURRENT_MODE, os_MODEVAR_YWIND_LIMIT, 301 : & nSize, NULL); 302 : gnScreenHeight = (nSize + 1) << nEigFactor; 303 : nPosition = (gnScreenHeight - nHeight) / 2; 304 : 305 : sSize.x0 = 0; 306 : sSize.x1 = gnScreenWidth; 307 : sSize.y0 = -gnScreenHeight; 308 : sSize.y1 = 0; 309 : xwimp_set_extent (whWindow, & sSize); 310 : 311 : sState.visible.x0 = 0; 312 : sState.visible.x1 = gnScreenWidth; 313 : sState.visible.y0 = 0; 314 : sState.visible.y1 = gnScreenHeight; 315 : 316 : sState.next = wimp_TOP; // Open at the top of the window stack 317 : sState.flags |= wimp_WINDOW_FOREGROUND_WINDOW; // Foreground window 318 : 319 : xwimp_open_window ((wimp_open *)& sState); 320 : } 321 : 322 : ////////////////////////////////////////////////////////////////// 323 : // Poll 3: Close a window 324 : void CloseWindow (wimp_block *pcBlock) { 325 : wimp_close_window (pcBlock->close.w); 326 : } 327 : 328 : ////////////////////////////////////////////////////////////////// 329 : // Create window from Templates file 330 : wimp_w LoadTemplate (char *szWindowTitle) { 331 : wimp_window *pcWindow; 332 : char * pcIndirected; 333 : int nWindowSize; 334 : int nIndirectedSize; 335 : char szTitle[12]; 336 : wimp_w whWindow; 337 : 338 : wimp_load_template (0, NULL, NULL, NULL, szWindowTitle, 0, 339 : & nWindowSize, & nIndirectedSize); 340 : 341 : pcWindow = (wimp_window*)malloc (nWindowSize); 342 : pcIndirected = malloc (nIndirectedSize); 343 : strncpy (szTitle, szWindowTitle, 12); 344 : 345 : wimp_load_template (pcWindow, pcIndirected, pcIndirected + nIndirectedSize, 346 : gacFontRef, szWindowTitle, 0, NULL, NULL); 347 : 348 : // All of our windows are going to be foreground windows 349 : pcWindow->next = wimp_TOP; 350 : pcWindow->flags |= wimp_WINDOW_FOREGROUND_WINDOW; 351 : 352 : whWindow = wimp_create_window (pcWindow); 353 : 354 : free((void *)pcWindow); 355 : 356 : return whWindow; 357 : } 358 : 359 : ////////////////////////////////////////////////////////////////// 360 : // Obtain string from Messages file 361 : char * Tag (char * szTag) { 362 : messagetrans_lookup ((messagetrans_control_block*)gpcMessages, 363 : szTag, gpcTemp, 256, 0, 0, 0, 0, NULL); 364 : 365 : return gpcTemp; 366 : } 367 : 368 : #if defined _DEBUG 369 : ////////////////////////////////////////////////////////////////// 370 : // Report a debug message 371 : void Report (char *szMessage) { 372 : _kernel_swi_regs sRegs; 373 : 374 : sRegs.r[0] = (int)szMessage; 375 : _kernel_swi (Report_Text0, & sRegs, & sRegs); 376 : } 377 : 378 : ////////////////////////////////////////////////////////////////// 379 : // Report a debug message with variable 380 : void ReportVar (char *szFormat, int nVariable) { 381 : _kernel_swi_regs sRegs; 382 : char szReport[255]; 383 : 384 : sprintf (szReport, szFormat, nVariable); 385 : sRegs.r[0] = (int)szReport; 386 : _kernel_swi (Report_Text0, & sRegs, & sRegs); 387 : } 388 : #endif // _DEBUG 389 : 390 : ////////////////////////////////////////////////////////////////// 391 : // Set the poll idle delay between each animation update 392 : void SetAnimationDelay (int nCentiseconds) { 393 : gnTimeInc = nCentiseconds; 394 : } 395 : 396 :