add level component saving functions which use PhysicsFS (didn't commit properly...
[btb/d2x.git] / ui / window.c
1 /* $Id: window.c,v 1.10 2005-02-26 10:13:51 chris Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 #ifdef RCS
16 static char rcsid[] = "$Id: window.c,v 1.10 2005-02-26 10:13:51 chris Exp $";
17 #endif
18
19 #ifdef HAVE_CONFIG_H
20 #include "conf.h"
21 #endif
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26 #ifdef __MSDOS__
27  #include <dos.h>
28 #else
29  #define _disable()
30  #define _enable()
31 #endif
32
33 #include "u_mem.h"
34 #include "fix.h"
35 #include "pstypes.h"
36 #include "gr.h"
37 #include "ui.h"
38 #include "key.h"
39 #include "timer.h"
40
41 #include "mono.h"
42 #include "mouse.h"
43
44
45 #define W_BACKGROUND    (wnd->background )
46 #define W_X             (wnd->x)
47 #define W_Y             (wnd->y)
48 #define W_WIDTH         (wnd->width)
49 #define W_HEIGHT        (wnd->height)
50 #define W_OLDCANVAS     (wnd->oldcanvas)
51 #define W_CANVAS        (wnd->canvas)
52 #define W_GADGET        (wnd->gadget)
53 #define W_TEXT_X        (wnd->text_x)
54 #define W_TEXT_Y        (wnd->text_y)
55 #define W_NEXT          (wnd->next)
56 #define W_PREV          (wnd->prev)
57
58
59 UI_WINDOW * CurWindow = NULL;
60 UI_WINDOW * FirstWindow = NULL;
61 UI_WINDOW * LastWindow = NULL;
62
63 int last_keypress = 0;
64
65 #define BORDER_WIDTH 8
66
67 static unsigned int FrameCount = 0;
68 unsigned int ui_event_counter = 0;
69 unsigned int ui_number_of_events = 0;
70 static UI_EVENT *   EventBuffer = NULL;
71 static int          Record = 0;
72 static int          RecordFlags = 0;
73
74 static short MouseDX=0, MouseDY=0, MouseButtons=0;
75
76 static unsigned char SavedState[256];
77
78 static int PlaybackSpeed = 1;
79
80 extern void ui_draw_frame( short x1, short y1, short x2, short y2 );
81
82 // 1=1x faster, 2=2x faster, etc
83 void ui_set_playback_speed( int speed )
84 {
85         PlaybackSpeed = speed;
86 }
87
88 int ui_record_events( int NumberOfEvents, UI_EVENT * buffer, int Flags )
89 {
90         if ( Record > 0 || buffer==NULL ) return 1;
91
92         RecordFlags = Flags;
93         EventBuffer = buffer;
94         ui_event_counter = 0;
95         FrameCount = 0;
96         ui_number_of_events = NumberOfEvents;
97         Record = 1;
98         return 0;
99 }
100
101 int ui_play_events_realtime( int NumberOfEvents, UI_EVENT * buffer )
102 {       int i;
103         if ( buffer == NULL ) return 1;
104
105         EventBuffer = buffer;
106         FrameCount = 0;
107         ui_event_counter = 0;
108         ui_number_of_events = NumberOfEvents;
109         Record = 2;
110         _disable();
111         keyd_last_released= 0;
112         keyd_last_pressed= 0;
113         for (i=0; i<256; i++ )
114                 SavedState[i] = keyd_pressed[i];
115         _enable();
116         key_flush();
117         return 0;
118 }
119
120 int ui_play_events_fast( int NumberOfEvents, UI_EVENT * buffer )
121 {
122         int i;
123         if ( buffer == NULL ) return 1;
124
125         EventBuffer = buffer;
126         FrameCount = 0;
127         ui_event_counter = 0;
128         ui_number_of_events = NumberOfEvents;
129         Record = 3;
130         _disable();
131         keyd_last_released= 0;
132         keyd_last_pressed= 0;
133
134         //mprintf( 0, "Before: ", i );
135         for (i=0; i<256; i++ )
136         {
137                 //if (keyd_pressed[i]) mprintf( 0, "%d ", i );
138                 SavedState[i] = keyd_pressed[i];
139         }
140         //mprintf( 0, "\n" );
141         _enable();
142         key_flush();
143         return 0;
144 }
145
146 // Returns:  0=Normal, 1=Recording, 2=Playback normal, 3=Playback fast
147 int ui_recorder_status()
148 {
149         return Record;
150 }
151
152 void add_window_to_end( UI_WINDOW * wnd )
153 {
154         if (LastWindow) {
155                 W_PREV = LastWindow;
156                 LastWindow->next = wnd;
157         }
158         LastWindow = wnd;
159         if (!FirstWindow)
160                 FirstWindow = wnd;
161 }
162
163 void add_window_to_beg( UI_WINDOW * wnd )
164 {
165         if (FirstWindow) {
166                 W_NEXT = FirstWindow;
167                 FirstWindow->prev = wnd;
168         }
169         FirstWindow = wnd;
170         if (!LastWindow)
171                 LastWindow = wnd;
172 }
173
174 // Add w1 after w2
175 void add_window_after( UI_WINDOW * w1, UI_WINDOW * w2 )
176 {
177         w1->prev = w2;
178         w1->next = w2->next;
179         w2->next = w1;
180         if (w1->next == NULL )
181                 LastWindow = w1;
182         else
183                 w1->next->prev = w1;
184 }
185
186 void close_all()
187 {
188         UI_WINDOW *sav, *wnd = LastWindow;
189
190         while(wnd)
191         {
192                 sav = W_PREV;
193                 ui_close_window(wnd);
194                 wnd = sav;
195         }
196 }
197
198 void remove_window( UI_WINDOW * wnd )
199 {
200         if (W_NEXT)
201                 W_NEXT->prev = W_PREV;
202         if (W_PREV)
203                 W_PREV->next = W_NEXT;
204         if (FirstWindow == wnd )
205                 FirstWindow = W_NEXT;
206         if (LastWindow == wnd )
207                 LastWindow = W_PREV;
208         W_NEXT = W_PREV = NULL;
209 }
210
211
212
213 UI_WINDOW * ui_open_window( short x, short y, short w, short h, int flags )
214 {
215         UI_WINDOW * wnd;
216         int sw, sh, req_w, req_h;
217
218         wnd = (UI_WINDOW *) d_malloc(sizeof(UI_WINDOW));
219         if (wnd==NULL) exit(1);
220
221         W_NEXT = NULL;
222         W_PREV = NULL;
223
224         add_window_to_end( wnd );
225
226         sw = grd_curscreen->sc_w;
227         sh = grd_curscreen->sc_h;
228
229         //mouse_set_limits(0, 0, sw - 1, sh - 1);
230
231         req_w = w;
232         req_h = h;
233
234         if (flags & WIN_BORDER)
235         {
236                 x -= BORDER_WIDTH;
237                 y -= BORDER_WIDTH;
238                 w += 2*BORDER_WIDTH;
239                 h += 2*BORDER_WIDTH;
240         }
241
242         if ( x < 0 ) x = 0;
243         if ( (x+w-1) >= sw ) x = sw - w;
244         if ( y < 0 ) y = 0;
245         if ( (y+h-1) >= sh ) y = sh - h;
246
247         W_X = x;
248         W_Y = y;
249         W_WIDTH = w;
250         W_HEIGHT = h;
251         W_OLDCANVAS = grd_curcanv;
252         W_GADGET = NULL;
253         wnd->keyboard_focus_gadget = NULL;
254
255         ui_mouse_hide();
256
257         if (flags & WIN_SAVE_BG)
258         {
259                 W_BACKGROUND = gr_create_bitmap( w, h );
260                 gr_bm_ubitblt(w, h, 0, 0, x, y, &(grd_curscreen->sc_canvas.cv_bitmap), W_BACKGROUND );
261         }
262         else
263                 W_BACKGROUND = NULL;
264
265         if (flags & WIN_BORDER)
266         {
267                 W_CANVAS = gr_create_sub_canvas( &(grd_curscreen->sc_canvas), x+BORDER_WIDTH, y+BORDER_WIDTH, req_w, req_h );
268                 gr_set_current_canvas( NULL );
269                 ui_draw_frame( x, y, x+w-1, y+h-1 );
270         }
271         else
272                 W_CANVAS = gr_create_sub_canvas( &(grd_curscreen->sc_canvas), x, y, req_w, req_h );
273
274         gr_set_current_canvas( W_CANVAS );
275
276         if (flags & WIN_FILLED)
277                 ui_draw_box_out( 0, 0, req_w-1, req_h-1 );
278
279         gr_set_fontcolor( CBLACK, CWHITE );
280
281         selected_gadget = NULL;
282
283         W_TEXT_X = 0;
284         W_TEXT_Y = 0;
285
286         return wnd;
287
288 }
289
290 void ui_close_window( UI_WINDOW * wnd )
291 {
292
293         ui_mouse_hide();
294
295         ui_gadget_delete_all( wnd );
296
297         if (W_BACKGROUND)
298         {
299                 gr_bm_ubitblt(W_WIDTH, W_HEIGHT, W_X, W_Y, 0, 0, W_BACKGROUND, &(grd_curscreen->sc_canvas.cv_bitmap));
300                 gr_free_bitmap( W_BACKGROUND );
301         } else
302         {
303                 gr_set_current_canvas( NULL );
304                 gr_setcolor( CBLACK );
305                 gr_rect( W_X, W_Y, W_X+W_WIDTH-1, W_Y+W_HEIGHT-1 );
306         }
307
308         gr_free_sub_canvas( W_CANVAS );
309
310         gr_set_current_canvas( W_OLDCANVAS );
311
312         selected_gadget = NULL;
313
314         remove_window( wnd );
315
316         if (CurWindow==wnd)
317                 CurWindow = NULL;
318
319         d_free( wnd );
320
321         ui_mouse_show();
322 }
323
324 void restore_state()
325 {
326         int i;
327         _disable();
328         //mprintf( 0, "After: " );
329         for (i=0; i<256; i++ )
330         {
331                 //if (SavedState[i]) mprintf( 0, "%d ", i );
332                 keyd_pressed[i] = SavedState[i];
333         }
334         //mprintf( 0, "\n" );
335         _enable();
336 }
337
338
339 int last_event = 0;
340
341 void ui_reset_idle_seconds()
342 {
343         last_event = timer_get_fixed_seconds();
344 }
345
346 int ui_get_idle_seconds()
347 {
348         return (timer_get_fixed_seconds() - last_event)/F1_0;
349 }
350
351 void ui_mega_process()
352 {
353         int mx, my;
354         unsigned char k;
355         
356         switch( Record )
357         {
358         case 0:
359                 mouse_get_delta( &mx, &my );
360                 Mouse.new_dx = mx;
361                 Mouse.new_dy = my;
362                 Mouse.new_buttons = mouse_get_btns();
363                 last_keypress = key_inkey();
364
365                 if ( Mouse.new_buttons || last_keypress || Mouse.new_dx || Mouse.new_dy )       {
366                         last_event = TICKER;
367                 }
368
369                 break;
370         case 1:
371
372                 if (ui_event_counter==0 )
373                 {
374                         EventBuffer[ui_event_counter].frame = 0;
375                         EventBuffer[ui_event_counter].type = 7;
376                         EventBuffer[ui_event_counter].data = ui_number_of_events;
377                         ui_event_counter++;
378                 }
379
380
381                 if (ui_event_counter==1 && (RecordFlags & UI_RECORD_MOUSE) )
382                 {
383                         Mouse.new_buttons = 0;
384                         EventBuffer[ui_event_counter].frame = FrameCount;
385                         EventBuffer[ui_event_counter].type = 6;
386                         EventBuffer[ui_event_counter].data = ((Mouse.y & 0xFFFF) << 16) | (Mouse.x & 0xFFFF);
387                         ui_event_counter++;
388                 }
389
390                 mouse_get_delta( &mx, &my );
391                 MouseDX = mx;
392                 MouseDY = my;
393                 MouseButtons = mouse_get_btns();
394
395                 Mouse.new_dx = MouseDX;
396                 Mouse.new_dy = MouseDY;
397
398                 if ((MouseDX != 0 || MouseDY != 0)  && (RecordFlags & UI_RECORD_MOUSE)  )
399                 {
400                         if (ui_event_counter < ui_number_of_events-1 )
401                         {
402                                 EventBuffer[ui_event_counter].frame = FrameCount;
403                                 EventBuffer[ui_event_counter].type = 1;
404                                 EventBuffer[ui_event_counter].data = ((MouseDY & 0xFFFF) << 16) | (MouseDX & 0xFFFF);
405                                 ui_event_counter++;
406                                 //mprintf( 0, "EVENT:%d, Mouse moved %d,%d\n", ui_event_counter, MouseDX, MouseDY );
407                         } else {
408                                 Record = 0;
409                         }
410
411                 }
412
413                 if ( (MouseButtons != Mouse.new_buttons) && (RecordFlags & UI_RECORD_MOUSE) )
414                 {
415                         Mouse.new_buttons = MouseButtons;
416
417                         if (ui_event_counter < ui_number_of_events-1 )
418                         {
419                                 EventBuffer[ui_event_counter].frame = FrameCount;
420                                 EventBuffer[ui_event_counter].type = 2;
421                                 EventBuffer[ui_event_counter].data = MouseButtons;
422                                 ui_event_counter++;
423                                 //mprintf( 0, "EVENT:%d, Mouse buttons changed %d\n", ui_event_counter, MouseButtons );
424                         } else {
425                                 Record = 0;
426                         }
427
428                 }
429
430
431                 if ( keyd_last_pressed && (RecordFlags & UI_RECORD_KEYS) )
432                 {
433                         _disable();
434                         k = keyd_last_pressed;
435                         keyd_last_pressed= 0;
436                         _enable();
437
438                         if (ui_event_counter < ui_number_of_events-1 )
439                         {
440                                 EventBuffer[ui_event_counter].frame = FrameCount;
441                                 EventBuffer[ui_event_counter].type = 3;
442                                 EventBuffer[ui_event_counter].data = k;
443                                 ui_event_counter++;
444                                 //mprintf( 0, "EVENT:%d, Key %d pressed\n", ui_event_counter, k );
445                         } else {
446                                 Record = 0;
447                         }
448
449                 }
450
451                 if ( keyd_last_released && (RecordFlags & UI_RECORD_KEYS) )
452                 {
453                         _disable();
454                         k = keyd_last_released;
455                         keyd_last_released= 0;
456                         _enable();
457
458                         if (ui_event_counter < ui_number_of_events-1 )
459                         {
460                                 EventBuffer[ui_event_counter].frame = FrameCount;
461                                 EventBuffer[ui_event_counter].type = 4;
462                                 EventBuffer[ui_event_counter].data = k;
463                                 ui_event_counter++;
464                                 //mprintf( 0, "EVENT:%d, Key %d released\n", ui_event_counter, k );
465                         } else {
466                                 Record = 0;
467                         }
468                 }
469
470                 last_keypress = key_inkey();
471
472                 if (last_keypress == KEY_F12 )
473                 {
474                         ui_number_of_events = ui_event_counter;
475                         last_keypress = 0;
476                         Record = 0;
477                         break;
478                 }
479
480                 if ((last_keypress != 0) && (RecordFlags & UI_RECORD_KEYS) )
481                 {
482                         if (ui_event_counter < ui_number_of_events-1 )
483                         {
484                                 EventBuffer[ui_event_counter].frame = FrameCount;
485                                 EventBuffer[ui_event_counter].type = 5;
486                                 EventBuffer[ui_event_counter].data = last_keypress;
487                                 ui_event_counter++;
488                                 //mprintf( 0, "EVENT:%d, Keypressed %d\n", ui_event_counter, last_keypress );
489                         } else {
490                                 Record = 0;
491                         }
492                 }
493
494                 FrameCount++;
495
496                 break;
497         case 2:
498         case 3:
499                 Mouse.new_dx = 0;
500                 Mouse.new_dy = 0;
501                 Mouse.new_buttons = 0;
502                 last_keypress = 0;
503
504                 if ( keyd_last_pressed ) {
505                         _disable();                     
506                         k = keyd_last_pressed;
507                         keyd_last_pressed = 0;
508                         _disable();
509                         SavedState[k] = 1;
510                 }
511
512                 if ( keyd_last_released ) 
513                 {
514                         _disable();                     
515                         k = keyd_last_released;
516                         keyd_last_released = 0;
517                         _disable();
518                         SavedState[k] = 0;
519                 }
520                 
521                 if (key_inkey() == KEY_F12 )
522                 {
523                         //mprintf( 0, "Playing stopped.\n" );
524                         restore_state();
525                         Record = 0;
526                         break;
527                 }
528
529                 if (EventBuffer==NULL) {
530                         restore_state();
531                         Record = 0;
532                         break;
533                 }
534
535                 while( (ui_event_counter < ui_number_of_events) && (EventBuffer[ui_event_counter].frame <= FrameCount) )
536                 {
537                         switch ( EventBuffer[ui_event_counter].type )
538                         {
539                         case 1:     // Mouse moved
540                                 Mouse.new_dx = EventBuffer[ui_event_counter].data & 0xFFFF;
541                                 Mouse.new_dy = (EventBuffer[ui_event_counter].data >> 16) & 0xFFFF;
542                                 break;
543                         case 2:     // Mouse buttons changed
544                                 Mouse.new_buttons = EventBuffer[ui_event_counter].data;
545                                 break;
546                         case 3:     // Key moved down
547                                 keyd_pressed[ EventBuffer[ui_event_counter].data ] = 1;
548                                 break;
549                         case 4:     // Key moved up
550                                 keyd_pressed[ EventBuffer[ui_event_counter].data ] = 0;
551                                 break;
552                         case 5:     // Key pressed
553                                 last_keypress = EventBuffer[ui_event_counter].data;
554                                 break;
555                         case 6:     // Initial Mouse X position
556                                 Mouse.x = EventBuffer[ui_event_counter].data & 0xFFFF;
557                                 Mouse.y = (EventBuffer[ui_event_counter].data >> 16) & 0xFFFF;
558                                 break;
559                         case 7:
560                                 break;
561                         }
562                         ui_event_counter++;
563                         if (ui_event_counter >= ui_number_of_events )
564                         {
565                                 Record = 0;
566                                 restore_state();
567                                 //( 0, "Done playing %d events.\n", ui_number_of_events );
568                         }
569                 }
570
571                 switch (Record)
572                 {
573                 case 2:
574                         {
575                                 int next_frame;
576                         
577                                 if ( ui_event_counter < ui_number_of_events )
578                                 {
579                                         next_frame = EventBuffer[ui_event_counter].frame;
580                                         
581                                         if ( (FrameCount+PlaybackSpeed) < next_frame )
582                                                 FrameCount = next_frame - PlaybackSpeed;
583                                         else
584                                                 FrameCount++;
585                                 } else {
586                                         FrameCount++;
587                                 }       
588                         }
589                         break;
590
591                 case 3:                 
592                         if ( ui_event_counter < ui_number_of_events ) 
593                                 FrameCount = EventBuffer[ui_event_counter].frame;
594                         else            
595                                 FrameCount++;
596                         break;
597                 default:                
598                         FrameCount++;
599                 }
600         }
601
602         ui_mouse_process();
603
604 }
605
606 void ui_wprintf( UI_WINDOW * wnd, char * format, ... )
607 {
608         char buffer[1000];
609         va_list args;
610
611         va_start(args, format );
612         vsprintf(buffer,format,args);
613
614         gr_set_current_canvas( W_CANVAS );
615
616         ui_mouse_hide();
617         W_TEXT_X = gr_string( W_TEXT_X, W_TEXT_Y, buffer );
618         ui_mouse_show();
619 }
620
621 void ui_wprintf_at( UI_WINDOW * wnd, short x, short y, char * format, ... )
622 {
623         char buffer[1000];
624         va_list args;
625
626         va_start(args, format );
627         vsprintf(buffer,format,args);
628
629         gr_set_current_canvas( W_CANVAS );
630
631         ui_mouse_hide();
632         gr_string( x, y, buffer );
633         ui_mouse_show();
634
635 }