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