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