1 /*
2  * AcornGUI.cc
3  *
4  * Frodo's Graphical User Interface for Acorn RISC OS machines (WIMP)
5  * (C) 1997 Andreas Dehmel
6  *
7  */
8 
9 
10 
11 #include "sysdeps.h"
12 
13 #include "C64.h"
14 #include "VIC.h"
15 #include "Display.h"
16 #include "Prefs.h"
17 #include "main.h"
18 #include "ROlib.h"
19 #include "AcornGUI.h"
20 #include "Version.h"
21 
22 
23 
24 #define CUSTOM_SPRITES	"FrodoRsrc:Sprites"
25 #define TEMPLATES_FILE	"FrodoRsrc:Templates"
26 #define WIMP_SCRAP_FILE	"<Wimp$Scrap>"
27 
28 
29 #define FileType_Data		0xffd
30 #define FileType_Text		0xfff
31 #define FileType_C64File	0x064
32 #define FileType_D64File	0x164
33 
34 #define IconSpriteSize		68	// OS units of an icon sprite (for dragging)
35 #define EstimatedPrefsSize	1024	// can't say how big it'll be before saving...
36 #define EstimatedConfSize	256
37 #define EstimatedRAMSize	0x10400
38 #define EstimatedSnapSize	0x11000
39 
40 
41 
42 
43 // For the scanning of the joystick keys in the SysConfig window
44 #define IntKey_ScanFrom		3
45 // This key gets translated to 0xff, i.e. none (joystick inactive)
46 #define IntKey_Void		44
47 
48 
49 #define Key_Return		13
50 
51 
52 
53 
54 // LED number to Icon number translation:
55 char LEDtoIcon[4] = {Icon_Pane_LED0, Icon_Pane_LED1, Icon_Pane_LED2, Icon_Pane_LED3};
56 // Drive number to Icon number (Pane) translation:
57 char PDrvToIcon[4] = {Icon_Pane_Drive0, Icon_Pane_Drive1, Icon_Pane_Drive2, Icon_Pane_Drive3};
58 // Drive number to Icon number (Prefs) translation:
59 #define IconsPerDrive	4
60 char DriveToIcon[16] = {
61   Icon_Prefs_Dr8DIR,  Icon_Prefs_Dr8D64,  Icon_Prefs_Dr8T64,  Icon_Prefs_Dr8Path,
62   Icon_Prefs_Dr9DIR,  Icon_Prefs_Dr9D64,  Icon_Prefs_Dr9T64,  Icon_Prefs_Dr9Path,
63   Icon_Prefs_Dr10DIR, Icon_Prefs_Dr10D64, Icon_Prefs_Dr10T64, Icon_Prefs_Dr10Path,
64   Icon_Prefs_Dr11DIR, Icon_Prefs_Dr11D64, Icon_Prefs_Dr11T64, Icon_Prefs_Dr11Path
65 };
66 // SID type to Icon number translation:
67 char SIDtoIcon[3] = {
68   Icon_Prefs_SIDNone, Icon_Prefs_SIDDigi, Icon_Prefs_SIDCard
69 };
70 // REU type to Icon number translation:
71 char REUtoIcon[4] = {
72   Icon_Prefs_REUNone, Icon_Prefs_REU128, Icon_Prefs_REU256, Icon_Prefs_REU512
73 };
74 char KJoyToIcon[2][5] = {
75   {Icon_Conf_Joy1Up, Icon_Conf_Joy1Down, Icon_Conf_Joy1Left, Icon_Conf_Joy1Right, Icon_Conf_Joy1Fire},
76   {Icon_Conf_Joy2Up, Icon_Conf_Joy2Down, Icon_Conf_Joy2Left, Icon_Conf_Joy2Right, Icon_Conf_Joy2Fire}
77 };
78 
79 
80 
81 
82 
83 // Internal keynumbers lookup table
84 // Single characters are represented by single chars, others by pointers to strings
85 int IntKeyTable[128] = {
86   (int)"Shft", (int)"Ctrl", (int)"Alt", (int)"ShftL",
87   (int)"CtrlL", (int)"AltL", (int)"ShftR", (int)"CtrlR",
88   (int)"AltR", (int)"Slct", (int)"Menu", (int)"Adjst",
89   0, 0, 0, 0,
90   'q', '3', '4', '5',
91   (int)"F4", '8', (int)"F7", '-',
92   '6', (int)"Left", (int)"num6", (int)"num7",
93   (int)"F11", (int)"F12", (int)"F10", (int)"ScLck",
94   (int)"Prnt", 'w', 'e', 't',
95   '7', 'i', '9', '0',
96   '-', (int)"Down", (int)"num8", (int)"num9",
97   (int)"Brk", '`', '�', (int)"Del",
98   '1', '2', 'd', 'r',
99   '6', 'u', 'o', 'p',
100   '[', (int)"Up", (int)"num+", (int)"num-",
101   (int)"nmEnt", (int)"Isrt", (int)"Home", (int)"PgUp",
102   (int)"CpLck", 'a', 'x', 'f',
103   'y', 'j', 'k', '2',
104   ';', (int)"Ret", (int)"num/", 0,
105   (int)"num.", (int)"nmLck", (int)"PgDwn", '\'',
106   0, 's', 'c', 'g',
107   'h', 'n', 'l', ';',
108   ']', (int)"Del", (int)"num#", (int)"num*",
109   0, '=', (int)"Extra", 0,
110   (int)"Tab", 'z', (int)"Space", 'v',
111   'b', 'm', ',', '.',
112   '/', (int)"Copy", (int)"num0", (int)"num1",
113   (int)"num3", 0, 0, 0,
114   (int)"Esc", (int)"F1", (int)"F2", (int)"F3",
115   (int)"F5", (int)"F6", (int)"F8", (int)"F9",
116   '\\', (int)"Right", (int)"num4", (int)"num5",
117   (int)"num2", 0, 0, 0
118 };
119 
120 
121 
122 
123 
124 // The icon bar icon
125 RO_IconDesc IBarIcon = {
126   -1, 0, 0, 68, 68, 0x301a,
127 #ifdef FRODO_SC
128   "!frodosc"
129 #else
130 # ifdef FRODO_PC
131   "!frodopc"
132 # else
133   "!frodo"
134 # endif
135 #endif
136 };
137 
138 
139 
140 
141 
142 // The menus
143 
144 char *MIBTextPrefs = "Preferences...";
145 char *MIBTextConf = "Configuration...";
146 
147 
148 struct MenuIconBar {
149   RO_MenuHead head;
150   RO_MenuItem item[Menu_IBar_Items];
151 } MenuIconBar = {
152   {
153 #ifdef FRODO_SC
154   "FrodoSC",
155 #else
156 # ifdef FRODO_PC
157   "FrodoPC",
158 # else
159   "Frodo",
160 # endif
161 #endif
162   7, 2, 7, 0, Menu_IBar_Width, Menu_Height, 0},
163   {
164     {0, (RO_MenuHead*)-1, Menu_Flags, "Info"},
165     {0, (RO_MenuHead*)-1, Menu_Flags + IFlg_Indir, ""},
166     {0, (RO_MenuHead*)-1, Menu_Flags + IFlg_Indir, ""},
167     {0, (RO_MenuHead*)-1, Menu_Flags, "Sound"},
168     {MFlg_LastItem, (RO_MenuHead*)-1, Menu_Flags, "Quit"}
169   }
170 };
171 
172 struct MenuEmuWindow {
173   RO_MenuHead head;
174   RO_MenuItem item[Menu_EWind_Items];
175 } MenuEmuWindow = {
176   {
177 #ifdef FRODO_SC
178     "FrodoSC Job",
179 #else
180 # ifdef FRODO_PC
181     "FrodoPC Job",
182 # else
183     "Frodo Job",
184 # endif
185 #endif
186     7, 2, 7, 0, Menu_EWind_Width, Menu_Height, 0},
187   {
188     {0, (RO_MenuHead*)-1, Menu_Flags, "Info"},
189     {0, (RO_MenuHead*)-1, Menu_Flags, "Sound"},
190     {MFlg_Warning, (RO_MenuHead*)-1, Menu_Flags, "Save RAM"},
191     {MFlg_LastItem | MFlg_Warning, (RO_MenuHead*)-1, Menu_Flags, "Snapshot"}
192   }
193 };
194 
195 
196 
197 
198 // For less writing in LoadATemplate...
199 #define wic(base,no,off) base[RO_WINDOW_WORDS + no*RO_ICON_WORDS + off]
200 
201 // For less writing in WindowToThePrefs...
202 #define pread_opt(var,icn)	PrefsWindow->GetIconState(Icon_Prefs_##icn,AuxBlock);\
203 				prefs->##var = ((AuxBlock[IconB_Flags] & IFlg_Slct) == 0) ? false : true;
204 
205 
206 
207 //
208 // WIMP member-functions
209 //
210 
WIMP(C64 * my_c64)211 WIMP::WIMP(C64 *my_c64)
212 {
213   int x,y,i;
214   WIdata *wid;
215 
216   CMOS_DragType = ReadDragType();
217 
218   // Determine the dimensions of the icon bar sprite first.
219   if (Wimp_SpriteInfo((char*)(&IBarIcon.dat),&x,&y,&i) == NULL)
220   {
221     IBarIcon.maxx = x << OS_ReadModeVariable(i,4);
222     IBarIcon.maxy = y << OS_ReadModeVariable(i,5);
223   }
224 
225   IBicon = new Icon(0,&IBarIcon); Mask = 0x00000830;
226   LastMenu = LastClick = LastDrag = MenuType = DragType = 0;
227   UseScrap = false; EmuPaused = false; UseNULL = 0;	// one NULL client - the emulator
228   the_c64 = my_c64;
229   EmuZoom = 1;
230 
231   // Read the customized sprite area (LEDs etc)
232   if ((ReadCatalogueInfo(CUSTOM_SPRITES,AuxBlock) & 1) != 0)	// (image) file
233   {
234     int i;
235     FILE *fp;
236 
237     i = AuxBlock[2]; SpriteArea = (int*)(new char[i+16]);	// allocate space for sprite
238     fp = fopen(CUSTOM_SPRITES,"rb");
239     i = fread(SpriteArea+1,1,i,fp); SpriteArea[0] = i+4;
240     fclose(fp);
241   }
242   else
243   {
244     WimpError.errnum = 0; sprintf(WimpError.errmess,"Can't read sprites!!!");
245     Wimp_ReportError(&WimpError,1,TASKNAME);
246   }
247 
248   // Read Template and create windows
249   if (Wimp_OpenTemplate(TEMPLATES_FILE) == NULL)
250   {
251     // Load Pane first
252     LoadATemplate("EmuPane",&EmuPane);
253     LoadATemplate("EmuWindow",&EmuWindow);
254     LoadATemplate("ThePrefs",&PrefsWindow);
255     LoadATemplate("ConfigWind",&ConfigWindow);
256     LoadATemplate("InfoWindow",&InfoWindow);
257     LoadATemplate("SoundWindow",&SoundWindow);
258     LoadATemplate("SaveBox",&SaveBox);
259   }
260   else
261   {
262     Wimp_ReportError(&WimpError,1,TASKNAME);
263     WimpError.errnum = 0; sprintf(WimpError.errmess,"Error in Templates!!!");
264   }
265   Wimp_CloseTemplate();
266 
267   // Add info window to icon bar menu
268   MenuIconBar.item[Menu_IBar_Info].submenu  =
269   MenuEmuWindow.item[Menu_EWind_Info].submenu = (RO_MenuHead*)InfoWindow->MyHandle();
270   MenuIconBar.item[Menu_IBar_Sound].submenu =
271   MenuEmuWindow.item[Menu_EWind_Sound].submenu = (RO_MenuHead*)SoundWindow->MyHandle();
272   MenuEmuWindow.item[Menu_EWind_SaveRAM].submenu =
273   MenuEmuWindow.item[Menu_EWind_Snapshot].submenu = (RO_MenuHead*)SaveBox->MyHandle();
274   // I couldn't find ONE FUCKING WAY to do this in the initialisation directly and I'm
275   // REALLY PISSED OFF!
276   wid = &(MenuIconBar.item[Menu_IBar_Prefs].dat);
277   wid->ind.tit = (int*)MIBTextPrefs; wid->ind.val = NULL; wid->ind.len = sizeof(MIBTextPrefs);
278   wid = &(MenuIconBar.item[Menu_IBar_Config].dat);
279   wid->ind.tit = (int*)MIBTextConf; wid->ind.val = NULL; wid->ind.len = sizeof(MIBTextConf);
280 
281   // Write default path into config window
282   ConfigWindow->WriteIconText(Icon_Conf_ConfPath,DEFAULT_SYSCONF);
283 
284   // Set up the contents of the prefs window and init with the default prefs path
285   ThePrefsToWindow();
286   PrefsWindow->WriteIconText(Icon_Prefs_PrefPath,DEFAULT_PREFS);
287   // Grey out SID card icon -- not supported!
288   PrefsWindow->SetIconState(Icon_Prefs_SIDCard,IFlg_Grey,IFlg_Grey);
289 
290   // Open Emulator window + pane in the center of the screen and give it the input focus
291   Wimp_GetCaretPosition(&LastCaret);
292   OpenEmuWindow();
293   Wimp_SetCaretPosition(EmuWindow->MyHandle(),-1,-100,100,-1,-1); // emu window gets input focus
294 
295   // Init export files
296   sprintf(RAMFile+44,"C64_RAM"); sprintf(SnapFile+44,"FrodoSnap");
297 }
298 
299 
~WIMP(void)300 WIMP::~WIMP(void)
301 {
302   delete IBicon;
303   delete EmuWindow; delete EmuPane; delete PrefsWindow; delete ConfigWindow;
304   delete InfoWindow; delete SoundWindow; delete SaveBox;
305 }
306 
307 
LoadATemplate(char * Name,Window ** Which)308 bool WIMP::LoadATemplate(char *Name, Window **Which)
309 {
310   char *Buffer, *Indirect, *Desc;
311   int IndSize, Pos;
312   char TempName[12];
313 
314   strncpy((char*)TempName,Name,12);
315   Buffer = NULL; Pos = 0;
316   if (Wimp_LoadTemplate(&Buffer,&Indirect,0,(char*)-1,TempName,&Pos) != NULL) {return(false);}
317   Buffer = new char[(int)Buffer + 4];
318   IndSize = (int)Indirect; Indirect = new char[IndSize];
319   Pos = 0; Desc = Buffer+4;
320   Wimp_LoadTemplate(&Desc,&Indirect,Indirect+IndSize,(char*)-1,TempName,&Pos);
321   if (Which == &EmuWindow)
322   {
323     int eigen, dx, dy;
324     RO_Window *row = (RO_Window*)Buffer;
325     RORes res;
326 
327     // Center emulator window on screen
328     eigen = (res.eigx < res.eigy) ? res.eigx : res.eigy;
329     dx = (DISPLAY_X << eigen); dy = (DISPLAY_Y << eigen);
330     row->vminx = res.resx/2 - dx/2; row->vmaxx = row->vminx + dx;
331     row->vminy = res.resy/2 - dy/2; row->vmaxy = row->vminy + dy;
332     row->wminy = -dy; row->wmaxx = dx;
333     Indirect = (char*)VERSION_STRING;
334   }
335   else
336   {
337     if (Which == &EmuPane)	// EmuPane needs customized sprites
338     {
339       register RO_Window *row = (RO_Window*)Buffer;
340       register int *b = (int*)Buffer;
341 
342       // Insert sprite pointer in window and icon definitions
343       row->SpriteAreaPtr = (int)SpriteArea;
344       wic(b,Icon_Pane_LED0,RawIB_Data1) = wic(b,Icon_Pane_LED1,RawIB_Data1) =
345       wic(b,Icon_Pane_LED2,RawIB_Data1) = wic(b,Icon_Pane_LED3,RawIB_Data1) = (int)SpriteArea;
346       sprintf((char*)wic(b,Icon_Pane_Pause,RawIB_Data0),PANE_TEXT_PAUSE);
347       sprintf((char*)wic(b,Icon_Pane_Toggle,RawIB_Data0),PANE_TEXT_ZOOM2);
348     }
349     else if (Which == &SoundWindow)	// ditto
350     {
351       register RO_Window *row = (RO_Window*)Buffer;
352       register int *b = (int*)Buffer;
353       register int orr;
354 
355       row->SpriteAreaPtr = (int)SpriteArea;
356       // if sound emulation off grey out notes
357       if (ThePrefs.SIDType == SIDTYPE_NONE) {orr = IFlg_Grey;} else {orr = 0;}
358       wic(b,Icon_Sound_Notes,RawIB_Flags)=(wic(b,Icon_Sound_Notes,RawIB_Flags)&~IFlg_Grey)|orr;
359     }
360     else if (Which == &InfoWindow)	// ditto
361     {
362       register RO_Window *row = (RO_Window*)Buffer;
363 
364       row->SpriteAreaPtr = (int)SpriteArea;
365     }
366     Indirect = NULL;
367   }
368   *Which = new Window((int*)Buffer,Indirect);
369   return(true);
370 }
371 
372 
373 // All changes in position of the Emulator window have to be treated seperately
374 // to keep the pane attached to it at all times!
OpenEmuWindow(void)375 void WIMP::OpenEmuWindow(void)
376 {
377   RO_Window *wind;
378   int work[WindowB_WFlags], i;
379 
380   wind = EmuWindow->Descriptor();
381   EmuPane->GetWorkArea(&work[WindowB_VMinX]); i = work[WindowB_VMaxX] - work[WindowB_VMinX];
382   if ((work[WindowB_VMinX] = wind->vminx - EmuPaneSpace - i) < 0)
383   {
384     // if main window still on screen then keep pane on screen as well
385     if (wind->vminx >= 0) {work[WindowB_VMinX] = 0;}
386     // otherwise align pane and main window on the left
387     else {work[WindowB_VMinX] = wind->vminx;}
388   }
389   work[WindowB_VMaxX] = work[WindowB_VMinX] + i;
390   work[WindowB_VMinY] = wind->vmaxy - (work[WindowB_VMaxY]-work[WindowB_VMinY]);
391   work[WindowB_VMaxY] = wind->vmaxy;
392   work[WindowB_Handle] = EmuPane->MyHandle();
393   work[WindowB_ScrollX] = work[WindowB_ScrollY] = 0;
394   work[WindowB_Stackpos] = -1;	// open on top of stack
395   // open the pane first
396   EmuPane->open(work);
397   wind->stackpos = EmuPane->MyHandle();	// open window behind pane.
398   EmuWindow->open();
399 }
400 
401 
OpenEmuWindow(int * Where)402 void WIMP::OpenEmuWindow(int *Where)
403 {
404   int work[WindowB_WFlags], i;
405 
406   EmuPane->GetWorkArea(&work[WindowB_VMinX]); i = work[WindowB_VMaxX] - work[WindowB_VMinX];
407   if ((work[WindowB_VMinX] = Where[WindowB_VMinX] - EmuPaneSpace - i) < 0)
408   {
409     if (Where[WindowB_VMinX] >= 0) {work[WindowB_VMinX] = 0;}
410     else {work[WindowB_VMinX] = Where[WindowB_VMinX];}
411   }
412   work[WindowB_VMaxX] = work[WindowB_VMinX] + i;
413   work[WindowB_VMinY] = Where[WindowB_VMaxY] - (work[WindowB_VMaxY]-work[WindowB_VMinY]);
414   work[WindowB_VMaxY] = Where[WindowB_VMaxY];
415   work[WindowB_Handle] = EmuPane->MyHandle();
416   work[WindowB_ScrollX] = work[WindowB_ScrollY] = 0;
417   work[WindowB_Stackpos] = Where[WindowB_Stackpos];
418   // open the pane first
419   EmuPane->open(work);
420   Where[WindowB_Stackpos] = EmuPane->MyHandle();	// open window behind pane
421   EmuWindow->open(Where);
422 }
423 
424 
CloseEmuWindow(void)425 void WIMP::CloseEmuWindow(void)
426 {
427   EmuWindow->close(); EmuPane->close();
428 }
429 
430 
UpdateEmuWindow(void)431 void WIMP::UpdateEmuWindow(void)
432 {
433   C64Display *disp = the_c64->TheDisplay;
434 
435   EmuWindow->update(disp->BitmapBase(),disp);
436 }
437 
438 
439 // Write the values given in ThePrefs into the Prefs Window
ThePrefsToWindow(void)440 void WIMP::ThePrefsToWindow(void)
441 {
442   int i, j, k;
443 
444   // Update the data for each of the drives
445   for (i=0; i<4; i++)
446   {
447     switch(ThePrefs.DriveType[i])
448     {
449       case DRVTYPE_D64: j=1; break;
450       case DRVTYPE_T64: j=2; break;
451       default: j=0; break;	// otherwise type 0 = DIR
452     }
453     // unselect all but other icons
454     for (k=0; k<3; k++)
455     {
456       if (k != j) {PrefsWindow->SetIconState(DriveToIcon[i*IconsPerDrive + k],0,IFlg_Slct);}
457     }
458     // and select the correct one.
459     PrefsWindow->SetIconState(DriveToIcon[i*IconsPerDrive + j],IFlg_Slct,IFlg_Slct);
460     // Now update the path name (buffer won't change, i.e. use original data)
461     PrefsWindow->WriteIconText(DriveToIcon[i*IconsPerDrive + 3],ThePrefs.DrivePath[i]);
462   }
463   if (ThePrefs.Emul1541Proc) {i = IFlg_Slct;} else {i = 0;}
464   PrefsWindow->SetIconState(Icon_Prefs_Emul1541,i,IFlg_Slct);
465   SetLEDIcons(ThePrefs.Emul1541Proc);
466   if (ThePrefs.MapSlash) {i = IFlg_Slct;} else {i = 0;}
467   PrefsWindow->SetIconState(Icon_Prefs_MapSlash,i,IFlg_Slct);
468 
469   // SID prefs
470   switch (ThePrefs.SIDType)
471   {
472     case SIDTYPE_DIGITAL: i = 1; break;
473     case SIDTYPE_SIDCARD: i = 2; break;
474     default: i = 0; break;	// includes NONE
475   }
476   for (j=0; j<3; j++)
477   {
478     if (j != i) {PrefsWindow->SetIconState(SIDtoIcon[j],0,IFlg_Slct);}
479   }
480   PrefsWindow->SetIconState(SIDtoIcon[i],IFlg_Slct,IFlg_Slct);
481   PrefsWindow->SetIconState(Icon_Prefs_SIDFilter,(ThePrefs.SIDFilters)?IFlg_Slct:0,IFlg_Slct);
482 
483   // REU prefs
484   switch (ThePrefs.REUSize)
485   {
486     case REU_128K: i=1; break;
487     case REU_256K: i=2; break;
488     case REU_512K: i=3; break;
489     default: i=0; break;
490   }
491   for (j=0; j<4; j++)
492   {
493     if (j != i) {PrefsWindow->SetIconState(REUtoIcon[j],0,IFlg_Slct);}
494   }
495   PrefsWindow->SetIconState(REUtoIcon[i],IFlg_Slct,IFlg_Slct);
496 
497   // Skip Frames
498   PrefsWindow->WriteIconNumber(Icon_Prefs_SkipFText,ThePrefs.SkipFrames);
499 
500   // Sprites
501   PrefsWindow->SetIconState(Icon_Prefs_SprOn,(ThePrefs.SpritesOn)?IFlg_Slct:0,IFlg_Slct);
502   PrefsWindow->SetIconState(Icon_Prefs_SprColl,(ThePrefs.SpriteCollisions)?IFlg_Slct:0,IFlg_Slct);
503   // Joystick
504   PrefsWindow->SetIconState(Icon_Prefs_Joy1On,(ThePrefs.Joystick1On)?IFlg_Slct:0,IFlg_Slct);
505   PrefsWindow->SetIconState(Icon_Prefs_Joy2On,(ThePrefs.Joystick2On)?IFlg_Slct:0,IFlg_Slct);
506   PrefsWindow->SetIconState(Icon_Prefs_JoySwap,(ThePrefs.JoystickSwap)?IFlg_Slct:0,IFlg_Slct);
507 
508   // Misc
509   SetSpeedLimiter(ThePrefs.LimitSpeed);
510   PrefsWindow->SetIconState(Icon_Prefs_FastReset,(ThePrefs.FastReset)?IFlg_Slct:0,IFlg_Slct);
511   PrefsWindow->SetIconState(Icon_Prefs_CIAHack,(ThePrefs.CIAIRQHack)?IFlg_Slct:0,IFlg_Slct);
512 
513   // Cycles
514   PrefsWindow->WriteIconNumber(Icon_Prefs_CycleNorm,ThePrefs.NormalCycles);
515   PrefsWindow->WriteIconNumber(Icon_Prefs_CycleBad,ThePrefs.BadLineCycles);
516   PrefsWindow->WriteIconNumber(Icon_Prefs_CycleCIA,ThePrefs.CIACycles);
517   PrefsWindow->WriteIconNumber(Icon_Prefs_CycleFloppy,ThePrefs.FloppyCycles);
518 }
519 
520 
521 // Update ThePrefs according to the values given in the Prefs Window
WindowToThePrefs(void)522 void WIMP::WindowToThePrefs(void)
523 {
524   int i, j, k;
525   Prefs *prefs = new Prefs(ThePrefs);
526 
527   for (i=0; i<4; i++)
528   {
529     // find out which of the drive type icons is selected
530     j = -1;
531     do
532     {
533       ++j; PrefsWindow->GetIconState(DriveToIcon[i*IconsPerDrive + j],AuxBlock);
534     }
535     while ((j < 3) && ((AuxBlock[IconB_Flags] & IFlg_Slct) == 0));
536     switch (j)
537     {
538       case 1:  prefs->DriveType[i] = DRVTYPE_D64; break;
539       case 2:  prefs->DriveType[i] = DRVTYPE_T64; break;
540       default: prefs->DriveType[i] = DRVTYPE_DIR; break;
541     }
542     strcpy(prefs->DrivePath[i],PrefsWindow->ReadIconText(DriveToIcon[i*IconsPerDrive + 3]));
543   }
544   // Emulation of the 1541 processor is a special case as it also affects LED1-3
545   pread_opt(Emul1541Proc,Emul1541);
546   SetLEDIcons(prefs->Emul1541Proc);
547   pread_opt(MapSlash,MapSlash);
548 
549   // SID
550   j = -1;
551   do
552   {
553     ++j; PrefsWindow->GetIconState(SIDtoIcon[j],AuxBlock);
554   }
555   while ((j < 3) && ((AuxBlock[IconB_Flags] & IFlg_Slct) == 0));
556   switch (j)
557   {
558     case 1:  prefs->SIDType = SIDTYPE_DIGITAL; break;
559     case 2:  prefs->SIDType = SIDTYPE_SIDCARD; break;
560     default: prefs->SIDType = SIDTYPE_NONE; break;
561   }
562   pread_opt(SIDFilters,SIDFilter);
563   SoundWindow->SetIconState(Icon_Sound_Notes,(prefs->SIDType==SIDTYPE_NONE)?IFlg_Grey:0,IFlg_Grey);
564 
565   // REU
566   j = -1;
567   do
568   {
569     ++j; PrefsWindow->GetIconState(REUtoIcon[j],AuxBlock);
570   }
571   while ((j < 4) && ((AuxBlock[IconB_Flags] & IFlg_Slct) == 0));
572   switch (j)
573   {
574     case 1:  prefs->REUSize = REU_128K; break;
575     case 2:  prefs->REUSize = REU_256K; break;
576     case 3:  prefs->REUSize = REU_512K; break;
577     default: prefs->REUSize = REU_NONE; break;
578   }
579 
580   // Skip Frames
581   prefs->SkipFrames = PrefsWindow->ReadIconNumber(Icon_Prefs_SkipFText);
582 
583   // Sprites
584   pread_opt(SpritesOn,SprOn); pread_opt(SpriteCollisions,SprColl);
585 
586   // Joystick
587   pread_opt(Joystick1On,Joy1On); pread_opt(Joystick2On,Joy2On); pread_opt(JoystickSwap,JoySwap);
588 
589   // Misc
590   pread_opt(LimitSpeed,LimSpeed); pread_opt(FastReset,FastReset); pread_opt(CIAIRQHack,CIAHack);
591 
592   // Cycles
593   prefs->NormalCycles	= PrefsWindow->ReadIconNumber(Icon_Prefs_CycleNorm);
594   prefs->BadLineCycles	= PrefsWindow->ReadIconNumber(Icon_Prefs_CycleBad);
595   prefs->CIACycles	= PrefsWindow->ReadIconNumber(Icon_Prefs_CycleCIA);
596   prefs->FloppyCycles	= PrefsWindow->ReadIconNumber(Icon_Prefs_CycleFloppy);
597 
598   // Finally make the changes known to the system:
599   the_c64->NewPrefs(prefs);
600   ThePrefs = *prefs;
601   delete prefs;
602 }
603 
604 
605 // Update the SysConfig window according to the values used
SysConfToWindow(void)606 void WIMP::SysConfToWindow(void)
607 {
608   int i, j, k;
609   Joy_Keys *jk;
610   char OneChar[2], *b;
611 
612   OneChar[1] = 0;
613 
614   // Write timings
615   the_c64->ReadTimings(&i,&j,&k);
616   ConfigWindow->WriteIconNumber(Icon_Conf_PollAfter, i);
617   ConfigWindow->WriteIconNumber(Icon_Conf_SpeedAfter, j);
618   ConfigWindow->WriteIconNumber(Icon_Conf_SoundAfter, k);
619 
620   // Write joystick keys
621   for (i=0; i<2; i++)
622   {
623     jk = &(the_c64->TheDisplay->JoystickKeys[i]); NewJoyKeys[i] = *jk;
624     if ((j = jk->up) >= 128) {j = 127;}
625     j = IntKeyTable[j]; if (j < 256) {OneChar[0] = j; b = OneChar;} else {b = (char*)j;}
626     ConfigWindow->WriteIconText(KJoyToIcon[i][0], b);
627     if ((j = jk->down) >= 128) {j = 127;}
628     j = IntKeyTable[j]; if (j < 256) {OneChar[0] = j; b = OneChar;} else {b = (char*)j;}
629     ConfigWindow->WriteIconText(KJoyToIcon[i][1], b);
630     if ((j = jk->left) >= 128) {j = 127;}
631     j = IntKeyTable[j]; if (j < 256) {OneChar[0] = j; b = OneChar;} else {b = (char*)j;}
632     ConfigWindow->WriteIconText(KJoyToIcon[i][2], b);
633     if ((j = jk->right) >= 128) {j = 127;}
634     j = IntKeyTable[j]; if (j < 256) {OneChar[0] = j; b = OneChar;} else {b = (char*)j;}
635     ConfigWindow->WriteIconText(KJoyToIcon[i][3], b);
636     if ((j = jk->fire) >= 128) {j = 127;}
637     j = IntKeyTable[j]; if (j < 256) {OneChar[0] = j; b = OneChar;} else {b = (char*)j;}
638     ConfigWindow->WriteIconText(KJoyToIcon[i][4], b);
639   }
640 }
641 
642 
643 // Update SysConfig according to the values in the window
WindowToSysConf(void)644 void WIMP::WindowToSysConf(void)
645 {
646   int i, j, k;
647   Joy_Keys *jk;
648 
649   // Read timings
650   i = ConfigWindow->ReadIconNumber(Icon_Conf_PollAfter);
651   j = ConfigWindow->ReadIconNumber(Icon_Conf_SpeedAfter);
652   k = ConfigWindow->ReadIconNumber(Icon_Conf_SoundAfter);
653   the_c64->WriteTimings(i,j,k);
654 
655   // Read joystick keys
656   for (i=0; i<2; i++)
657   {
658     jk = &(the_c64->TheDisplay->JoystickKeys[i]); *jk = NewJoyKeys[i];
659   }
660 }
661 
662 
663 // Low-level keyboard scan in SysConfig Window
PollSysConfWindow(void)664 void WIMP::PollSysConfWindow(void)
665 {
666   Wimp_GetPointerInfo(Block);
667   if (Block[MouseB_Window] == ConfigWindow->MyHandle())
668   {
669     int i, j;
670 
671     for (i=0; i<2; i++)
672     {
673       for (j=0; j<5; j++)
674       {
675         if (Block[MouseB_Icon] == KJoyToIcon[i][j])
676         {
677           int key;
678 
679           // Gain caret (to window, but none of its icons!)
680           Wimp_GetCaretPosition(&LastCaret);
681           Wimp_SetCaretPosition(ConfigWindow->MyHandle(),-1,0,0,-1,-1);
682           if ((key = ScanKeys(IntKey_ScanFrom)) != 0xff)
683           {
684             char OneChar[2], *b;
685 
686             if (key == IntKey_Void) {key = 0xff;}
687             switch (j)
688             {
689               case 0: NewJoyKeys[i].up = key; break;
690               case 1: NewJoyKeys[i].down = key; break;
691               case 2: NewJoyKeys[i].left = key; break;
692               case 3: NewJoyKeys[i].right = key; break;
693               case 4: NewJoyKeys[i].fire = key; break;
694             }
695             if (key >= 128) {key = 127;}
696             key = IntKeyTable[key];
697             if (key < 256) {OneChar[0]=key; OneChar[1]=0; b=OneChar;} else {b=(char*)key;}
698             ConfigWindow->WriteIconText(KJoyToIcon[i][j], b);
699           }
700         }
701       }
702     }
703   }
704 }
705 
706 
707 // Start a drag operation on the icon <number> in the window <host>
DragIconSprite(Window * host,unsigned int number)708 void WIMP::DragIconSprite(Window *host, unsigned int number)
709 {
710   host->GetIconState(number,AuxBlock);
711   if ((AuxBlock[IconB_Flags] & IFlg_Sprite) != 0)	// it needs to have a sprite, of course
712   {
713     char spritename[16] = "\0";
714 
715     if ((AuxBlock[IconB_Flags] & IFlg_Indir) == 0)	// not indirected
716     {
717       strncpy(spritename,((char*)AuxBlock+IconB_Data0),15);
718     }
719     else
720     {
721       if ((AuxBlock[IconB_Flags] & IFlg_Text) == 0)
722       {
723         strncpy(spritename,(char*)AuxBlock[IconB_Data0],15);
724       }
725       else	// this necessitates parsing the validation string
726       {
727         register char *b, *d, *s, c;
728 
729         s = spritename;
730         if ((b = (char*)AuxBlock[IconB_Data1]) != NULL)	// pointer to val str
731         {
732           do
733           {
734             c = *b++;
735             if ((c == 's') || (c == 'S'))	// sprite command
736             {
737               c = *b++; while ((c != ';') && (c >= 32)) {*s++ = c; c = *b++;}
738               c = 0; *s++ = c;	// we can stop now
739             }
740             else if (c >= 32)	// some other command ==> skip to next.
741             {
742               c = *b++;
743               while ((c != ';') && (c >= 32)) {if (c == '\\') {b++;} c = *b++;}
744             }
745           }
746           while (c >= 32);
747         }
748       }
749     }
750     // we should now have the spritename
751     if (spritename[0] != '\0')
752     {
753       LastDrag = host->MyHandle(); LastIcon = number;
754       if (CMOS_DragType == 0)	// Drag outline
755       {
756         ROScreen *screen = the_c64->TheDisplay->screen;
757 
758         AuxBlock[DragB_Handle] = LastDrag; AuxBlock[DragB_Type] = 5;
759         Wimp_GetPointerInfo(AuxBlock + DragB_IMinX);
760         // Drag fixed sized box of this size:
761         AuxBlock[DragB_IMinX] -= IconSpriteSize/2;
762         AuxBlock[DragB_IMaxX] = AuxBlock[DragB_IMinX] + IconSpriteSize;
763         AuxBlock[DragB_IMinY] -= IconSpriteSize/2;
764         AuxBlock[DragB_IMaxY] = AuxBlock[DragB_IMinY] + IconSpriteSize;
765         // Parent box is whole screen
766         AuxBlock[DragB_BBMinX] = AuxBlock[DragB_BBMinY] = 0;
767         AuxBlock[DragB_BBMaxX] = screen->resx; AuxBlock[DragB_BBMaxY] = screen->resy;
768         Wimp_DragBox(AuxBlock);
769       }
770       else	// DragASprite
771       {
772         Wimp_GetPointerInfo(AuxBlock);
773         AuxBlock[DASB_MinX] -= IconSpriteSize/2;
774         AuxBlock[DASB_MaxX] = AuxBlock[DASB_MinX] + IconSpriteSize;
775         AuxBlock[DASB_MinY] -= IconSpriteSize/2;
776         AuxBlock[DASB_MaxY] = AuxBlock[DASB_MinY] + IconSpriteSize;
777         DragASprite_Start(0xc5,1,spritename,AuxBlock,NULL);
778       }
779     }
780   }
781 }
782 
783 
784 // Blk is a block as in MouseClick or PointerInfo
CalculateVolume(int * Blk)785 int WIMP::CalculateVolume(int *Blk)
786 {
787   int orgx, vol;
788 
789   SoundWindow->getstate(AuxBlock);
790   orgx = AuxBlock[WindowB_VMinX] - AuxBlock[WindowB_ScrollX];
791   SoundWindow->GetIconState(Icon_Sound_Volume, AuxBlock);
792   vol = (MaximumVolume*((Blk[MouseB_PosX] - orgx) - AuxBlock[IconB_MinX] - WellBorder)) / (AuxBlock[IconB_MaxX] - AuxBlock[IconB_MinX] - 2*WellBorder);
793   if (vol < 0) {vol = 0;} if (vol > MaximumVolume) {vol = MaximumVolume;}
794   return(vol);
795 }
796 
797 
798 // Check whether a filename contains a full pathname and reports an error if not.
CheckFilename(char * name)799 int WIMP::CheckFilename(char *name)
800 {
801   bool OK = false;
802   register char *b, *d, c;
803 
804   b = d = name; c = *b++;
805   while (c > 32)
806   {
807     // valid path must contain '$' or ':'
808     if ((c == '$') || (c == ':')) {OK = true; d = b;}
809     if (c == '.') {d = b;}
810     c = *b++;
811   }
812   if ((b - d) == 1) {OK = false;}	// filename mustn't end with '$', ':' or '.'
813   if (OK) {return(0);}
814 
815   WimpError.errnum = 0; sprintf(WimpError.errmess,"Bad filename %s",name);
816   Wimp_ReportError(&WimpError,1,TASKNAME);
817   return(-1);
818 }
819 
820 
SnapshotSaved(bool OK)821 void WIMP::SnapshotSaved(bool OK)
822 {
823   if (OK)
824   {
825     int *b = (int*)SnapFile;
826 
827     if (b[MsgB_Sender] != 0)
828     {
829       b[MsgB_YourRef] = b[MsgB_MyRef]; b[MsgB_Action] = Message_DataLoad;
830       Wimp_SendMessage(18,b,b[MsgB_Sender],b[6]);
831     }
832     else {Wimp_CreateMenu((int*)-1,0,0);}
833     SaveType = 0;
834   }
835 }
836 
837 
IssueSnapshotRequest(void)838 void WIMP::IssueSnapshotRequest(void)
839 {
840   if (EmuPaused)
841   {
842     EmuPane->WriteIconTextU(Icon_Pane_Pause, PANE_TEXT_PAUSE);
843     EmuPaused = false;
844   }
845   the_c64->RequestSnapshot();
846 }
847 
848 
849 // Sets the Emu pane's LEDs according to the floppy emulation state
SetLEDIcons(bool FloppyEmulation)850 void WIMP::SetLEDIcons(bool FloppyEmulation)
851 {
852   int i, eor;
853 
854   if (FloppyEmulation) {eor = IFlg_Grey;} else {eor = 0;}
855   for (i=1; i<4; i++)
856   {
857     EmuPane->SetIconState(LEDtoIcon[i],eor,IFlg_Grey);
858   }
859 }
860 
861 
862 
863 // Doesn't open window, just resizes...
SetEmuWindowSize(void)864 void WIMP::SetEmuWindowSize(void)
865 {
866   register int i;
867   register C64Display *disp = the_c64->TheDisplay;
868 
869   i = (disp->screen->eigx < disp->screen->eigy) ? disp->screen->eigx : disp->screen->eigy;
870   if (EmuZoom == 2) {i++;}
871   EmuWindow->extent(0,-(DISPLAY_Y << i),(DISPLAY_X << i),0);
872 }
873 
874 
875 
876 // switch between zoom 1 and zoom 2
ToggleEmuWindowSize(void)877 void WIMP::ToggleEmuWindowSize(void)
878 {
879   int x,y;
880 
881   // Icon in pane shows _alternative_ zoom mode
882   if (EmuZoom == 1)
883   {
884     EmuZoom = 2;
885     EmuPane->WriteIconText(Icon_Pane_Toggle,"1 x");
886   }
887   else
888   {
889     EmuZoom = 1;
890     EmuPane->WriteIconText(Icon_Pane_Toggle,"2 x");
891   }
892   SetEmuWindowSize();
893   EmuWindow->GetWorkArea(AuxBlock);
894   x = AuxBlock[2] - AuxBlock[0]; y = AuxBlock[3] - AuxBlock[1];
895   EmuWindow->getstate(AuxBlock);
896   AuxBlock[WindowB_VMaxX] = AuxBlock[WindowB_VMinX] + x;
897   AuxBlock[WindowB_VMinY] = AuxBlock[WindowB_VMaxY] - y;
898   // Open emu window alone to get the dimensions set by the WIMP
899   Wimp_OpenWindow(AuxBlock);
900   // Then open with the pane at the correct position
901   EmuWindow->getstate(AuxBlock); OpenEmuWindow(AuxBlock); UpdateEmuWindow();
902 }
903 
904 
905 
ReadEmuWindowSize(void)906 int WIMP::ReadEmuWindowSize(void)
907 {
908   return EmuZoom;
909 }
910 
911 
912 
913 // Set a new drive path for drive DrNum. MsgBlock is the DataLoad MessageBlock.
NewDriveImage(int DrNum,int * MsgBlock,bool SetNow)914 void WIMP::NewDriveImage(int DrNum, int *MsgBlock, bool SetNow)
915 {
916   int type, j = -1, map = -1;
917 
918   // determine currently selected type
919   do
920   {
921     ++j; PrefsWindow->GetIconState(DriveToIcon[DrNum*IconsPerDrive + j], AuxBlock);
922   }
923   while ((j < 3) && ((AuxBlock[6] & IFlg_Slct) == 0));
924   if (j >= 3) {j = 0;}
925   // Check the type and set the drive type accordingly
926   type = ReadCatalogueInfo(((char*)Block)+44,AuxBlock);
927   // New path is directory but DRVTYPE != DIR ==> set DIR
928   if ((type == 2) && (j != 0)) {map = 0;}
929   // New path is not directory/image but DRVTYPE == DIR ==> remap to D64
930   if (((type & 2) == 0) && (j == 0)) {map = 1;}
931   // Filetype indicated D64 image?
932   if (((type = AuxBlock[0]) & 0xfff00000) == 0xfff00000)	// typed file
933   {
934     type = (type >> 8) & 0xfff;
935     // D64 image can also be used in DIR mode (-> D64ImageFS). Only remap from T64!
936     if ((type == FileType_D64File) && (j == 2)) {map = 1;}
937   }
938   // Do we need to remap?
939   if (map >= 0)
940   {
941     PrefsWindow->SetIconState(DriveToIcon[DrNum*IconsPerDrive+j],0,IFlg_Slct);
942     PrefsWindow->SetIconState(DriveToIcon[DrNum*IconsPerDrive+map],IFlg_Slct,IFlg_Slct);
943     j = map;
944   }
945   // j is the number of the emulation mode (DIR (0), D64 (1), T64 (2))
946   PrefsWindow->WriteIconText(DriveToIcon[DrNum*IconsPerDrive+3],((char*)Block)+44);
947   // Send acknowledge message
948   Block[MsgB_YourRef] = Block[MsgB_MyRef]; Block[MsgB_Action] = Message_DataLoadAck;
949   Wimp_SendMessage(17,Block,Block[MsgB_Sender],Block[6]);
950 
951   // Set this drive path immediately?
952   if (SetNow)
953   {
954     Prefs *prefs = new Prefs(ThePrefs);
955 
956     prefs->DriveType[DrNum] = j; strcpy(prefs->DrivePath[DrNum],((char*)Block)+44);
957     the_c64->NewPrefs(prefs);
958     ThePrefs = *prefs;
959     delete prefs;
960   }
961 }
962 
963 
964 
SetSpeedLimiter(bool LimitSpeed)965 void WIMP::SetSpeedLimiter(bool LimitSpeed)
966 {
967   RO_Icon *roi;
968   char *b, c;
969 
970   PrefsWindow->SetIconState(Icon_Prefs_LimSpeed,(LimitSpeed) ? IFlg_Slct : 0, IFlg_Slct);
971   roi = EmuPane->GetIcon(Icon_Pane_Speed);
972   if ((b = (char*)roi->dat.ind.val) != NULL)
973   {
974     do
975     {
976       c = *b++;
977       if ((c == 'r') || (c == 'R'))	// boRder command?
978       {
979         if (LimitSpeed) {*b++ = '1';} else {*b++ = '2';}
980         c = 0;	// stop now
981       }
982       else if (c >= 32)	// skip to next command
983       {
984         c = *b++;
985         while ((c >= 32) && (c != ';')) {if (c == '\\') {b++;} c = *b++;}
986       }
987     }
988     while (c >= 32);
989     EmuPane->UpdateIcon(Icon_Pane_Speed);
990   }
991 }
992 
993 
994 
995 
996 
Poll(bool Paused)997 void WIMP::Poll(bool Paused)
998 {
999   int event;
1000   bool LastPause;
1001 
1002   LastPause = EmuPaused; EmuPaused = Paused;
1003 
1004   // If emulator is paused disable null events
1005   if ((!EmuPaused) || (UseNULL > 0)) {Mask &= 0xfffffffe;} else {Mask |= 1;}
1006 
1007   do
1008   {
1009     // Loop until a null event is received, then continue the emulation.
1010     // (this looks best)
1011     do
1012     {
1013       event = Wimp_Poll(Mask,Block,NULL);
1014       switch (event)
1015       {
1016         case 1: Redraw(); break;
1017         case 2: OpenWindow(); break;
1018         case 3: CloseWindow(); break;
1019         case 6: MouseClick(); break;
1020         case 7: UserDrag(); break;
1021         case 8: if ((EmuPaused) && (Block[KeyPB_Window] == EmuWindow->MyHandle()))
1022                 {
1023                   if (the_c64->TheDisplay->CheckForUnpause(!LastPause)) {EmuPaused = false;}
1024                 }
1025                 KeyPressed(); break;
1026         case 9: MenuSelection(); break;
1027         case 17:
1028         case 18: UserMessage(); break;
1029         case 19: UserMessageAck(); break;
1030         default: break;
1031       }
1032       // This is important
1033       if ((!EmuPaused) || (UseNULL > 0)) {Mask &= 0xfffffffe;} else {Mask |= 1;}
1034       LastPause = EmuPaused;
1035     }
1036     while (event != 0);
1037     if (UseNULL > 0) {PollSysConfWindow();}
1038     // This should probably become a new member-function one day...
1039     if (DragType == DRAG_VolumeWell)
1040     {
1041       Wimp_GetPointerInfo(Block);
1042       if (Block[MouseB_Icon] == Icon_Sound_Volume)	// should always be the case (BBox)!
1043       {
1044         the_c64->HostVolume = CalculateVolume(Block);
1045         SoundWindow->ForceIconRedraw(Icon_Sound_Volume);
1046       }
1047     }
1048   }
1049   while (EmuPaused);
1050 }
1051 
1052 
Redraw(void)1053 void WIMP::Redraw(void)
1054 {
1055   if (Block[RedrawB_Handle] == EmuWindow->MyHandle()) // emulator main window
1056   {
1057     C64Display *disp = the_c64->TheDisplay;
1058 
1059     EmuWindow->redraw(Block,disp->BitmapBase(),disp);
1060   }
1061   else if (Block[RedrawB_Handle] == SoundWindow->MyHandle())	// sound window
1062   {
1063     int more;
1064     int minx, miny, maxx, maxy, thresh;
1065 
1066     more = Wimp_RedrawWindow(Block);
1067     // compute screen coordinates of work (0,0)
1068     minx = Block[RedrawB_VMinX] - Block[RedrawB_ScrollX];
1069     maxy = Block[RedrawB_VMaxY] - Block[RedrawB_ScrollY];
1070     // get volume well bounding box
1071     SoundWindow->GetIconState(Icon_Sound_Volume, AuxBlock);
1072     maxx = minx + AuxBlock[IconB_MaxX] - WellBorder; minx += AuxBlock[IconB_MinX] + WellBorder;
1073     miny = maxy + AuxBlock[IconB_MinY] + WellBorder; maxy += AuxBlock[IconB_MaxY] - WellBorder;
1074     thresh = minx + (the_c64->HostVolume * (maxx - minx))/ MaximumVolume;
1075     while (more != 0)
1076     {
1077       // clip
1078       if ((minx <= Block[RedrawB_CMaxX]) && (maxx >= Block[RedrawB_CMinX]) &&
1079           (miny <= Block[RedrawB_CMaxY]) && (maxy >= Block[RedrawB_CMinY]))
1080       {
1081         if (Block[RedrawB_CMinX] < thresh)
1082         {
1083           ColourTrans_SetGCOL(0x00ff0000,0,0);	// green
1084           OS_Plot(0x04,minx,miny); OS_Plot(0x65,thresh,maxy);
1085         }
1086         if (Block[RedrawB_CMaxX] > thresh)
1087         {
1088           ColourTrans_SetGCOL(0xffffff00,0,0);	// white
1089           OS_Plot(0x04,thresh,miny); OS_Plot(0x65,maxx,maxy);
1090         }
1091       }
1092       more = Wimp_GetRectangle(Block);
1093     }
1094   }
1095   else // Dummy redraw loop
1096   {
1097     int more;
1098 
1099     more = Wimp_RedrawWindow(Block);
1100     while (more != 0)
1101     {
1102       more = Wimp_GetRectangle(Block);
1103     }
1104   }
1105 }
1106 
1107 
OpenWindow(void)1108 void WIMP::OpenWindow(void)
1109 {
1110   if (Block[WindowB_Handle] == EmuWindow->MyHandle()) {OpenEmuWindow(Block);}
1111   else if (Block[WindowB_Handle] != EmuPane->MyHandle())
1112   {
1113     Wimp_OpenWindow(Block);
1114   }
1115 }
1116 
1117 
CloseWindow(void)1118 void WIMP::CloseWindow(void)
1119 {
1120   if (Block[WindowB_Handle] == EmuWindow->MyHandle()) {CloseEmuWindow();}
1121   else if (Block[WindowB_Handle] != EmuPane->MyHandle())
1122   {
1123     if (Block[WindowB_Handle] == ConfigWindow->MyHandle()) {UseNULL--;}
1124     Wimp_CloseWindow(Block);
1125   }
1126 }
1127 
1128 
MouseClick(void)1129 void WIMP::MouseClick(void)
1130 {
1131   if ((Block[MouseB_Window] == -2) && (Block[MouseB_Icon] == IBicon->IHandle))	// Icon Bar icon
1132   {
1133     if (Block[MouseB_Buttons] == 2)	// Menu
1134     {
1135       Wimp_CreateMenu((int*)&MenuIconBar,Block[MouseB_PosX]-MenuIconBar.head.width/2,96+Menu_Height*Menu_IBar_Items);
1136       LastMenu = Menu_IBar;
1137     }
1138     else	// Some other click
1139     {
1140       if (!EmuWindow->OpenStatus(Block)) {Block[WindowB_Stackpos] = -1; OpenEmuWindow(Block);}
1141     }
1142   }
1143   else if (Block[MouseB_Window] == EmuWindow->MyHandle())	// Emulator window
1144   {
1145     if (Block[MouseB_Buttons] >= 256)	// click
1146     {
1147       Wimp_GetCaretPosition(&LastCaret);
1148       Wimp_SetCaretPosition(Block[MouseB_Window],-1,-100,100,-1,-1);	// gain input focus
1149     }
1150     if (Block[MouseB_Buttons] == 2)	// menu
1151     {
1152       Wimp_CreateMenu((int*)&MenuEmuWindow,Block[MouseB_PosX]-MenuEmuWindow.head.width/2,Block[MouseB_PosY]);
1153       LastMenu = Menu_Emulator;
1154     }
1155   }
1156   else if (Block[MouseB_Window] == EmuPane->MyHandle())	// Emulator pane
1157   {
1158     if ((Block[MouseB_Buttons] == 1) || (Block[MouseB_Buttons] == 4))
1159     {
1160       switch (Block[MouseB_Icon])
1161       {
1162         case Icon_Pane_Pause:	// Pause icon
1163           if (EmuPaused)
1164           {
1165             EmuPane->WriteIconText(Icon_Pane_Pause,PANE_TEXT_PAUSE);
1166             the_c64->Resume(); EmuPaused = false;
1167           }
1168           else
1169           {
1170             EmuPane->WriteIconText(Icon_Pane_Pause,PANE_TEXT_RESUME);
1171             the_c64->Pause(); EmuPaused = true;
1172             // Update the window now!
1173             UpdateEmuWindow();
1174           }
1175           break;
1176         case Icon_Pane_Reset: the_c64->Reset(); break;
1177         case Icon_Pane_Toggle: ToggleEmuWindowSize(); break;
1178         case Icon_Pane_Speed:
1179           ThePrefs.LimitSpeed = !ThePrefs.LimitSpeed; SetSpeedLimiter(ThePrefs.LimitSpeed);
1180           break;
1181         default: break;
1182       }
1183     }
1184   }
1185   else if (Block[MouseB_Window] == PrefsWindow->MyHandle())		// Prefs window
1186   {
1187     if ((Block[MouseB_Buttons] == 1) || (Block[MouseB_Buttons] == 4))	// normal click
1188     {
1189       register int i;
1190 
1191       switch(Block[MouseB_Icon])
1192       {
1193         case Icon_Prefs_SkipFLeft:
1194              i = PrefsWindow->ReadIconNumber(Icon_Prefs_SkipFText);
1195              if (i > 0)
1196              {
1197                PrefsWindow->WriteIconNumber(Icon_Prefs_SkipFText,--i);
1198                ThePrefs.SkipFrames = i; // instant update
1199              }
1200              break;
1201         case Icon_Prefs_SkipFRight:
1202              i = PrefsWindow->ReadIconNumber(Icon_Prefs_SkipFText);
1203              PrefsWindow->WriteIconNumber(Icon_Prefs_SkipFText,++i);
1204              ThePrefs.SkipFrames = i;	// instant update
1205              break;
1206         case Icon_Prefs_Cancel: ThePrefsToWindow(); break;	// restore current settings
1207         case Icon_Prefs_OK: WindowToThePrefs();
1208              if (Block[MouseB_Buttons] == 4) {PrefsWindow->close();}
1209              break;		// use new prefs
1210         case Icon_Prefs_Save:
1211              WindowToThePrefs();
1212              if (CheckFilename(PrefsWindow->ReadIconText(Icon_Prefs_PrefPath)) == 0)
1213              {
1214                ThePrefs.Save(PrefsWindow->ReadIconText(Icon_Prefs_PrefPath));
1215              }
1216              break;
1217         default: break;
1218       }
1219     }
1220     else if ((Block[MouseB_Buttons] == 16) || (Block[MouseB_Buttons] == 64))
1221     // drag (only the sprite)
1222     {
1223       if (Block[MouseB_Icon] == Icon_Prefs_PrefSprite)
1224       {
1225         DragIconSprite(PrefsWindow, Icon_Prefs_PrefSprite);
1226         DragType = DRAG_PrefsSprite;
1227       }
1228     }
1229   }
1230   else if (Block[MouseB_Window] == ConfigWindow->MyHandle())	// sys config window
1231   {
1232     if ((Block[MouseB_Buttons] == 1) || (Block[MouseB_Buttons] == 4))
1233     {
1234       if (Block[MouseB_Icon] == Icon_Conf_OK)
1235       {
1236         WindowToSysConf(); UseNULL--;
1237         if (Block[MouseB_Buttons] == 4) {ConfigWindow->close();}
1238       }
1239       else if (Block[MouseB_Icon] == Icon_Conf_Save)
1240       {
1241         if (CheckFilename(ConfigWindow->ReadIconText(Icon_Conf_ConfPath)) == 0)
1242         {
1243           WindowToSysConf(); UseNULL--; ConfigWindow->close();
1244           the_c64->SaveSystemConfig(ConfigWindow->ReadIconText(Icon_Conf_ConfPath));
1245         }
1246       }
1247     }
1248     else if ((Block[MouseB_Buttons] == 16) || (Block[MouseB_Buttons] == 64))
1249     {
1250       if (Block[MouseB_Icon] == Icon_Conf_ConfSprite)
1251       {
1252         DragIconSprite(ConfigWindow, Icon_Conf_ConfSprite);
1253         DragType = DRAG_ConfSprite;
1254       }
1255     }
1256   }
1257   else if (Block[MouseB_Window] == SoundWindow->MyHandle())		// sound window
1258   {
1259     if (Block[MouseB_Icon] == Icon_Sound_Volume)
1260     {
1261       if ((Block[MouseB_Buttons] == 1) || (Block[MouseB_Buttons] == 4))		// click
1262       {
1263         the_c64->HostVolume = CalculateVolume(Block); Sound_Volume(the_c64->HostVolume);
1264         SoundWindow->ForceIconRedraw(Icon_Sound_Volume);
1265       }
1266       else if ((Block[MouseB_Buttons] == 16) || (Block[MouseB_Buttons] == 64))	// drag
1267       {
1268         int orgx, orgy;
1269 
1270         SoundWindow->getstate(AuxBlock);
1271         orgx = AuxBlock[WindowB_VMinX] - AuxBlock[WindowB_ScrollX];
1272         orgy = AuxBlock[WindowB_VMaxY] - AuxBlock[WindowB_ScrollY];
1273         SoundWindow->GetIconState(Icon_Sound_Volume, &AuxBlock[DragB_BBMinX - IconB_MinX]);
1274         AuxBlock[DragB_BBMinX] += orgx; AuxBlock[DragB_BBMinY] += orgy;
1275         AuxBlock[DragB_BBMaxX] += orgx; AuxBlock[DragB_BBMaxY] += orgy;
1276         AuxBlock[DragB_Type] = 7;
1277         Wimp_DragBox(AuxBlock);
1278         DragType = DRAG_VolumeWell; UseNULL++;
1279       }
1280     }
1281   }
1282   else if (Block[MouseB_Window] == SaveBox->MyHandle())
1283   {
1284     if ((Block[MouseB_Buttons] == 1) || (Block[MouseB_Buttons] == 4))
1285     {
1286       if (Block[MouseB_Icon] == Icon_Save_OK)
1287       {
1288         if (CheckFilename(SaveBox->ReadIconText(Icon_Save_Path)) == 0)
1289         {
1290           if (SaveType == SAVE_RAM)
1291           {
1292             strcpy(RAMFile+44,SaveBox->ReadIconText(Icon_Save_Path));
1293             the_c64->SaveRAM(RAMFile+44);
1294             Wimp_CreateMenu((int*)-1,0,0);
1295             SaveType = 0;
1296           }
1297           else if (SaveType == SAVE_Snapshot)
1298           {
1299             *(((int*)SnapFile) + MsgB_Sender) = 0;
1300             strcpy(SnapFile+44,SaveBox->ReadIconText(Icon_Save_Path));
1301             IssueSnapshotRequest();
1302           }
1303         }
1304       }
1305     }
1306     else if ((Block[MouseB_Buttons] == 16) || (Block[MouseB_Buttons] == 64))
1307     {
1308       if (Block[MouseB_Icon] == Icon_Save_Sprite)
1309       {
1310         DragIconSprite(SaveBox, Icon_Save_Sprite);
1311         DragType = DRAG_SaveSprite;
1312       }
1313     }
1314   }
1315 }
1316 
1317 
1318 // A drag operation has terminated
UserDrag(void)1319 void WIMP::UserDrag(void)
1320 {
1321   char *b = NULL;
1322   int filetype, size;
1323 
1324   if ((CMOS_DragType == 0) || (DragType == DRAG_VolumeWell))
1325   {
1326     Wimp_DragBox(NULL);
1327   }
1328   else
1329   {
1330     DragASprite_Stop();
1331   }
1332 
1333   if (DragType == DRAG_VolumeWell)
1334   {
1335     UseNULL--; DragType = 0; Sound_Volume(the_c64->HostVolume);	// just set the new volume.
1336   }
1337 
1338   // Drag of the path sprite
1339   if (DragType == DRAG_PrefsSprite)
1340   {
1341     b = PrefsWindow->ReadIconText(Icon_Prefs_PrefPath); filetype = FileType_Text;
1342     size = EstimatedPrefsSize;	// can't say how large it's gonna be
1343   }
1344   else if (DragType == DRAG_ConfSprite)
1345   {
1346     b = ConfigWindow->ReadIconText(Icon_Conf_ConfPath); filetype = FileType_Text;
1347     size = EstimatedConfSize;
1348   }
1349   else if (DragType == DRAG_SaveSprite)
1350   {
1351     b = SaveBox->ReadIconText(Icon_Save_Path); filetype = FileType_Data;
1352     if (SaveType == SAVE_RAM) {size = EstimatedRAMSize;}
1353     else if (SaveType == SAVE_Snapshot) {size = EstimatedSnapSize;}
1354     else {size = 0;}
1355   }
1356 
1357   // now b should point to the path and filetype should contain the type
1358   if (b != NULL)
1359   {
1360     Wimp_GetPointerInfo(Block);
1361     // Not on background and not on my own icon bar icon
1362     if ((Block[MouseB_Window] != -1) && ((Block[MouseB_Window] != -2) || (Block[MouseB_Icon] != IBicon->IHandle)))
1363     {
1364       int handle = Block[MouseB_Window];
1365 
1366       // None of my windows
1367       if ((handle != EmuWindow->MyHandle()) && (handle != EmuPane->MyHandle()) &&
1368           (handle != PrefsWindow->MyHandle()) && (handle != ConfigWindow->MyHandle()) &&
1369           (handle != InfoWindow->MyHandle()) && (handle != SaveBox->MyHandle()))
1370       {
1371         char *d, c;
1372 
1373         d = b; c = *b++;
1374         // get pointer to leafname in d
1375         while (c > 32) {if ((c == '.') || (c == ':')) {d = b;} c = *b++;}
1376         // Build message block
1377         Block[5] = Block[MouseB_Window]; Block[6] = Block[MouseB_Icon];
1378         Block[7] = Block[MouseB_PosX]; Block[8] = Block[MouseB_PosY];
1379         Block[9] = size; Block[10] = filetype;
1380         Block[MsgB_YourRef] = 0; Block[MsgB_Action] = Message_DataSave;
1381         b = ((char*)Block) + 44; c = *d++;
1382         while (c > 32) {*b++ = c; c = *d++;}
1383         *b++ = 0; Block[MsgB_Size] = (((int)(b - (char*)Block)) + 3) & 0xfffffffc;
1384         Wimp_SendMessage(18,Block,Block[5],Block[6]);
1385       }
1386     }
1387   }
1388   else {DragType = 0;}
1389   LastDrag = 0;
1390 }
1391 
1392 
KeyPressed(void)1393 void WIMP::KeyPressed(void)
1394 {
1395   register int key = Block[KeyPB_Key];
1396 
1397   if (Block[KeyPB_Window] == EmuWindow->MyHandle())
1398   {
1399     if ((key >= 0x180) && (key <= 0x1fd)) // special keys (incl. FKeys)
1400     {
1401       key -= 0x180;
1402       if ((((key & 0x4f) >= 0x05) && ((key & 0x4f) <= 0x09)) ||	// F5 -F9 [shift|ctrl]
1403           (((key & 0x4f) >= 0x4a) && ((key & 0x4f) <= 0x4c)))	// F10-F12 [shift|ctrl]
1404       {
1405         if ((key != 0x06) && (key != 0x07) && (key != 0x08))
1406         {
1407           Wimp_ProcessKey(Block[KeyPB_Key]);
1408         }
1409       }
1410     }
1411     return;
1412   }
1413   else if (Block[KeyPB_Window] == PrefsWindow->MyHandle())
1414   {
1415     if (key == Key_Return)
1416     {
1417       WindowToThePrefs();
1418       if (Block[KeyPB_Icon] == Icon_Prefs_PrefPath)	// return pressed in path string icon?
1419       {
1420         if (CheckFilename(PrefsWindow->ReadIconText(Icon_Prefs_PrefPath)) == 0)
1421         {
1422           ThePrefs.Save(PrefsWindow->ReadIconText(Icon_Prefs_PrefPath));
1423         }
1424       }
1425       return;
1426     }
1427   }
1428   else if (Block[KeyPB_Window] == ConfigWindow->MyHandle())
1429   {
1430     if ((key == Key_Return) && (Block[KeyPB_Icon] != -1))
1431     {
1432       WindowToSysConf(); UseNULL--; ConfigWindow->close();
1433       if (Block[KeyPB_Icon] == Icon_Conf_ConfPath)	// return pressed in path string icon?
1434       {
1435         if (CheckFilename(ConfigWindow->ReadIconText(Icon_Conf_ConfPath)) == 0)
1436         {
1437           the_c64->SaveSystemConfig(ConfigWindow->ReadIconText(Icon_Conf_ConfPath));
1438         }
1439       }
1440       return;
1441     }
1442   }
1443   else if (Block[KeyPB_Window] == SaveBox->MyHandle())
1444   {
1445     if (key == Key_Return)
1446     {
1447       if (Block[KeyPB_Icon] == Icon_Save_Path)
1448       {
1449         if (CheckFilename(SaveBox->ReadIconText(Icon_Save_Path)) == 0)
1450         {
1451           if (SaveType == SAVE_RAM)
1452           {
1453             strcpy(RAMFile+44,SaveBox->ReadIconText(Icon_Save_Path));
1454             the_c64->SaveRAM(RAMFile+44);
1455             Wimp_CreateMenu((int*)-1,0,0);
1456             SaveType = 0;
1457           }
1458           else if (SaveType == SAVE_Snapshot)
1459           {
1460             *(((int*)SnapFile) + MsgB_Sender) = 0;
1461             strcpy(SnapFile+44,SaveBox->ReadIconText(Icon_Save_Path));
1462             IssueSnapshotRequest();
1463           }
1464         }
1465       }
1466       return;
1467     }
1468   }
1469   Wimp_ProcessKey(Block[KeyPB_Key]);
1470 }
1471 
1472 
MenuSelection(void)1473 void WIMP::MenuSelection(void)
1474 {
1475   int Buttons;
1476 
1477   Wimp_GetPointerInfo(AuxBlock); Buttons = AuxBlock[MouseB_Buttons];
1478 
1479   switch (LastMenu)
1480   {
1481     case Menu_IBar:
1482         if (Block[0] == Menu_IBar_Quit) {EmuPaused = false; the_c64->Quit();}
1483         else if (Block[0] == Menu_IBar_Prefs)
1484         {
1485           // Is it already open? Then don't do anything
1486           if (!PrefsWindow->OpenStatus())
1487           {
1488             int y;
1489 
1490             // Open Prefs window with top left corner in top left corner of screen
1491             PrefsWindow->getstate(AuxBlock);
1492             y = the_c64->TheDisplay->screen->resy;
1493             AuxBlock[WindowB_VMaxX] -= AuxBlock[WindowB_VMinX]; AuxBlock[WindowB_VMinX] = 0;
1494             AuxBlock[WindowB_VMinY] = y - (AuxBlock[WindowB_VMaxY] - AuxBlock[WindowB_VMinY]);
1495             AuxBlock[WindowB_VMaxY] = y;
1496             // Open Prefs window on top
1497             AuxBlock[WindowB_Stackpos] = -1;
1498             PrefsWindow->open(AuxBlock);
1499           }
1500           else
1501           {
1502             PrefsWindow->getstate(AuxBlock);
1503             AuxBlock[WindowB_Stackpos] = -1; PrefsWindow->open(AuxBlock);
1504           }
1505         }
1506         else if (Block[0] == Menu_IBar_Config)
1507         {
1508           if (!ConfigWindow->OpenStatus())
1509           {
1510             int x, y;
1511 
1512             // Update window contents
1513             SysConfToWindow();
1514             // Open config window in top right corner of screen
1515             ConfigWindow->getstate(AuxBlock);
1516             x = the_c64->TheDisplay->screen->resx; y = the_c64->TheDisplay->screen->resy;
1517             AuxBlock[WindowB_VMinX] = x - (AuxBlock[WindowB_VMaxX] - AuxBlock[WindowB_VMinX]);
1518             AuxBlock[WindowB_VMaxX] = x;
1519             AuxBlock[WindowB_VMinY] = y - (AuxBlock[WindowB_VMaxY] - AuxBlock[WindowB_VMinY]);
1520             AuxBlock[WindowB_VMaxY] = y;
1521             AuxBlock[WindowB_Stackpos] = -1;
1522             ConfigWindow->open(AuxBlock);
1523             // We need NULL-events for the low-level keyboard scan.
1524             UseNULL++;
1525           }
1526           else
1527           {
1528             ConfigWindow->getstate(AuxBlock);
1529             AuxBlock[WindowB_Stackpos] = -1; ConfigWindow->open(AuxBlock);
1530           }
1531         }
1532         if (Buttons == 1) {Wimp_CreateMenu((int*)&MenuIconBar,0,0);}
1533         break;
1534     case Menu_Emulator:
1535         if (Buttons == 1) {Wimp_CreateMenu((int*)&MenuEmuWindow,0,0);}
1536         break;
1537     default: break;
1538   }
1539 }
1540 
1541 
1542 // Handle regular messages
UserMessage(void)1543 void WIMP::UserMessage(void)
1544 {
1545   C64Display *disp = the_c64->TheDisplay;
1546   int i;
1547 
1548   switch (Block[MsgB_Action]) // Message Action
1549   {
1550     case Message_Quit:
1551     	 EmuPaused = false; the_c64->Quit(); break;
1552     case Message_ModeChange:
1553     	 disp->ModeChange(); the_c64->TheVIC->ReInitColors(); SetEmuWindowSize();
1554     	 // The window could have changed position ==> reposition pane as well!
1555     	 // we have to force the window to the screen manually
1556     	 EmuWindow->getstate(AuxBlock);
1557     	 if ((AuxBlock[WindowB_WFlags] & (1<<16)) != 0)	// is it open anyway?
1558     	 {
1559     	   i = AuxBlock[WindowB_VMaxY] - AuxBlock[WindowB_VMinY];
1560     	   if (AuxBlock[WindowB_VMaxY] > disp->screen->resy - TitleBarHeight)
1561     	   {
1562     	     AuxBlock[WindowB_VMaxY] = disp->screen->resy - TitleBarHeight;
1563       	     if ((AuxBlock[WindowB_VMinY] = AuxBlock[WindowB_VMaxY] - i) < TitleBarHeight)
1564     	     {
1565     	       AuxBlock[WindowB_VMinY] = TitleBarHeight;
1566     	     }
1567     	   }
1568     	   i = AuxBlock[WindowB_VMaxX] - AuxBlock[WindowB_VMinX];
1569     	   if (AuxBlock[WindowB_VMaxX] > disp->screen->resx - TitleBarHeight)
1570     	   {
1571     	     AuxBlock[WindowB_VMaxX] = disp->screen->resx - TitleBarHeight;
1572     	     if ((AuxBlock[WindowB_VMinX] = AuxBlock[WindowB_VMaxX] - i) < 0)
1573     	     {
1574     	       AuxBlock[WindowB_VMinX] = 0;
1575     	     }
1576     	   }
1577     	   // Don't you just love it -- you can't open the window directly, you need
1578     	   // a delay... like for instance by sending yourself an OpenWindow message...
1579     	   Wimp_SendMessage(2,AuxBlock,TaskHandle,0);
1580     	 }
1581     	 break;
1582     case Message_PaletteChange:
1583          // Updating EmuWindow is pointless since the bitmap still contains data for another mode
1584          disp->ModeChange(); the_c64->TheVIC->ReInitColors();
1585          break;
1586     case Message_DataSave:
1587          i = -1;	// indicator whether file is accepted
1588          if ((Block[5] == EmuWindow->MyHandle()) && (Block[10] == FileType_C64File)) {i=0;}
1589          else if ((Block[5] == EmuWindow->MyHandle()) && (Block[10] == FileType_Data)) {i=0;}
1590          else if ((Block[5] == PrefsWindow->MyHandle()) && (Block[10] == FileType_Text)) {i=0;}
1591          else if ((Block[5] == ConfigWindow->MyHandle()) && (Block[10] == FileType_Text)) {i=0;}
1592          if (i >= 0)
1593          {
1594            Block[9] = -1;	// file unsafe
1595            strcpy(((char*)Block)+44,WIMP_SCRAP_FILE);
1596            Block[MsgB_Size] = (48 + strlen(WIMP_SCRAP_FILE)) & 0xfffffffc;
1597            Block[MsgB_YourRef] = Block[MsgB_MyRef]; Block[MsgB_Action] = Message_DataSaveAck;
1598            Wimp_SendMessage(17,Block,Block[MsgB_Sender],Block[6]);
1599            UseScrap = true;
1600          }
1601          break;
1602     case Message_DataLoad:
1603          if (Block[5] == EmuWindow->MyHandle())	// Emulator window: load file?
1604          {
1605            if (Block[10] == FileType_C64File)	// Load only files with type &64 this way
1606            {
1607              FILE *fp;
1608 
1609              if ((fp = fopen(((char*)Block)+44,"rb")) != NULL)
1610              {
1611                uint8 lo, hi, *mem = the_c64->RAM;
1612                int length;
1613 
1614                lo = fgetc(fp); hi = fgetc(fp); length = lo + (hi<<8);
1615                length += fread(mem+length,1,0x10000-length,fp);
1616                // length is now end-address
1617                fclose(fp);
1618                mem[0xc3] = lo; mem[0xc4] = hi; // Load-address
1619                lo = length & 0xff; hi = (length >> 8) & 0xff;
1620                mem[0xae] = mem[0x2d] = mem[0x2f] = mem[0x31] = mem[0x33] = lo;
1621                mem[0xaf] = mem[0x2e] = mem[0x30] = mem[0x32] = mem[0x34] = hi;
1622                Block[MsgB_YourRef] = Block[MsgB_MyRef]; Block[MsgB_Action] = Message_DataLoadAck;
1623                Wimp_SendMessage(17,Block,Block[MsgB_Sender],Block[6]);
1624              }
1625            }
1626            else if (Block[10] == FileType_Data)
1627            {
1628              if (the_c64->LoadSnapshot(((char*)Block)+44))
1629              {
1630                Block[MsgB_YourRef] = Block[MsgB_MyRef]; Block[MsgB_Action] = Message_DataLoadAck;
1631                Wimp_SendMessage(17,Block,Block[MsgB_Sender],Block[6]);
1632              }
1633            }
1634          }
1635          else if (Block[5] == PrefsWindow->MyHandle())	// Prefs window?
1636          {
1637            if (Block[10] == FileType_Text)	// load a prefs file?
1638            {
1639              Prefs *prefs = new Prefs(ThePrefs);
1640 
1641              prefs->Load(((char*)Block)+44);
1642              the_c64->NewPrefs(prefs);
1643              ThePrefs = *prefs;
1644              delete prefs;
1645              PrefsWindow->WriteIconText(Icon_Prefs_PrefPath,((char*)Block)+44);
1646              ThePrefsToWindow();
1647              Block[MsgB_YourRef] = Block[MsgB_MyRef]; Block[MsgB_Action] = Message_DataLoadAck;
1648              Wimp_SendMessage(17,Block,Block[MsgB_Sender],Block[6]);
1649            }
1650            else		// interpret as drive path (if dragged on one of the drive path icons)
1651            {
1652              switch (Block[6])
1653              {
1654                case Icon_Prefs_Dr8Path:  i = 0; break;
1655                case Icon_Prefs_Dr9Path:  i = 1; break;
1656                case Icon_Prefs_Dr10Path: i = 2; break;
1657                case Icon_Prefs_Dr11Path: i = 3; break;
1658                default: -1; break;
1659              }
1660              if (i >= 0) {NewDriveImage(i,Block,false);}
1661            }
1662          }
1663          else if (Block[5] == ConfigWindow->MyHandle())	// load sys config file
1664          {
1665            if (Block[10] == FileType_Text)
1666            {
1667              the_c64->LoadSystemConfig(((char*)Block)+44);
1668              SysConfToWindow();
1669              ConfigWindow->WriteIconText(Icon_Conf_ConfPath,((char*)Block)+44);
1670              Block[MsgB_YourRef] = Block[MsgB_MyRef]; Block[MsgB_Action] = Message_DataLoadAck;
1671              Wimp_SendMessage(17,Block,Block[MsgB_Sender],Block[6]);
1672            }
1673          }
1674          else if (Block[5] == EmuPane->MyHandle())	// emulator pane
1675          {
1676            switch (Block[6])
1677            {
1678              case Icon_Pane_Drive0:
1679              case Icon_Pane_LED0: i = 0; break;
1680              case Icon_Pane_Drive1:
1681              case Icon_Pane_LED1: i = 1; break;
1682              case Icon_Pane_Drive2:
1683              case Icon_Pane_LED2: i = 2; break;
1684              case Icon_Pane_Drive3:
1685              case Icon_Pane_LED3: i = 3; break;
1686              default: i = -1; break;
1687            }
1688            if (i >= 0) {NewDriveImage(i,Block,true);}
1689          }
1690          // Clean up if necessary
1691          if (UseScrap) {DeleteFile(WIMP_SCRAP_FILE); UseScrap = false;}
1692          break;
1693     case Message_DataSaveAck:
1694          if (DragType == DRAG_PrefsSprite)
1695          {
1696            WindowToThePrefs();	// read window entries
1697            ThePrefs.Save(((char*)Block)+44);
1698            if (Block[9] != -1)	// we're talking to the filer ==> set new pathname
1699            {
1700              PrefsWindow->WriteIconText(Icon_Prefs_PrefPath,((char*)Block)+44);
1701            }
1702            Block[MsgB_YourRef] = Block[MsgB_MyRef]; Block[MsgB_Action] = Message_DataLoad;
1703            Wimp_SendMessage(18,Block,Block[MsgB_Sender],Block[6]);
1704          }
1705          else if (DragType == DRAG_ConfSprite)
1706          {
1707            WindowToSysConf();	// read window entries
1708            the_c64->SaveSystemConfig(((char*)Block)+44);
1709            if (Block[9] != -1)
1710            {
1711              ConfigWindow->WriteIconText(Icon_Conf_ConfPath,((char*)Block)+44);
1712            }
1713            Block[MsgB_YourRef] = Block[MsgB_MyRef]; Block[MsgB_Action] = Message_DataLoad;
1714            Wimp_SendMessage(18,Block,Block[MsgB_Sender],Block[6]);
1715          }
1716          else if (DragType == DRAG_SaveSprite)
1717          {
1718            if (SaveType == SAVE_RAM)
1719            {
1720              memcpy(RAMFile,(char*)Block,256); the_c64->SaveRAM(RAMFile+44);
1721              Block[MsgB_YourRef] = Block[MsgB_MyRef]; Block[MsgB_Action] = Message_DataLoad;
1722              Wimp_SendMessage(18,Block,Block[MsgB_Sender],Block[6]);
1723            }
1724            else if (SaveType == SAVE_Snapshot)
1725            {
1726              memcpy(SnapFile,(char*)Block,256);
1727              IssueSnapshotRequest();
1728            }
1729          }
1730          break;
1731     case Message_DataLoadAck:
1732          if (DragType == DRAG_ConfSprite)
1733          {
1734            UseNULL--; ConfigWindow->close();
1735          }
1736          if (DragType == DRAG_SaveSprite)
1737          {
1738            Wimp_CreateMenu((int*)-1,0,0);
1739          }
1740          DragType = SaveType = 0; break;
1741     case Message_MenuWarning:
1742          if (LastMenu == Menu_Emulator)
1743          {
1744            if (Block[8] == Menu_EWind_SaveRAM)
1745            {
1746              SaveType = SAVE_RAM; SaveBox->WriteIconText(Icon_Save_Path,RAMFile+44);
1747            }
1748            else if (Block[8] == Menu_EWind_Snapshot)
1749            {
1750              SaveType = SAVE_Snapshot; SaveBox->WriteIconText(Icon_Save_Path,SnapFile+44);
1751            }
1752            else {SaveType = 0;}
1753            Wimp_CreateSubMenu((int*)Block[5],Block[6],Block[7]);
1754          }
1755          break;
1756     default: break;
1757   }
1758 }
1759 
1760 
1761 // If a recorded message was not answered, i.e. something went wrong.
UserMessageAck(void)1762 void WIMP::UserMessageAck(void)
1763 {
1764   switch(Block[MsgB_Action])
1765   {
1766     case Message_DataSave:
1767          sprintf(WimpError.errmess,"Can't save data."); break;
1768     case Message_DataLoad:
1769          sprintf(WimpError.errmess,"Receiver couldn't load data."); break;
1770     default:
1771          sprintf(WimpError.errmess,"Some error occurred..."); break;
1772   }
1773   WimpError.errnum = 0; Wimp_ReportError(&WimpError,1,TASKNAME);
1774 }
1775