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