Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
 * Portions of this file are copyright Rebirth contributors and licensed as
3
 * described in COPYING.txt.
4
 * Portions of this file are copyright Parallax Software and licensed
5
 * according to the Parallax license below.
6
 * See COPYING.txt for license details.
7
 
8
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
9
SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
10
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
11
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
12
IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
13
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
14
FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
15
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
16
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
17
COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
18
*/
19
 
20
/*
21
 *
22
 * Windowing functions and controller.
23
 *
24
 */
25
 
26
#include <stdlib.h>
27
#include <stdio.h>
28
#include <stdarg.h>
29
 
30
#include "window.h"
31
#include "u_mem.h"
32
#include "maths.h"
33
#include "pstypes.h"
34
#include "gr.h"
35
#include "ui.h"
36
#include "key.h"
37
#include "mouse.h"
38
#include "timer.h"
39
#include "dxxerror.h"
40
#include <memory>
41
 
42
namespace dcx {
43
 
44
#define D_X             (dlg->d_x)
45
#define D_Y             (dlg->d_y)
46
#define D_WIDTH         (dlg->d_width)
47
#define D_HEIGHT        (dlg->d_height)
48
#define D_GADGET        (dlg->d_gadget)
49
#define D_TEXT_X        (dlg->d_text_x)
50
#define D_TEXT_Y        (dlg->d_text_y)
51
 
52
#ifndef __MSDOS__
53
#define _disable()
54
#define _enable()
55
#endif
56
 
57
#define BORDER_WIDTH 8
58
 
59
static void ui_dialog_draw(UI_DIALOG *dlg)
60
{
61
        int x, y, w, h;
62
        int req_w, req_h;
63
 
64
        x = D_X;
65
        y = D_Y;
66
        w = D_WIDTH;
67
        h = D_HEIGHT;
68
 
69
        req_w = w;
70
        req_h = h;
71
 
72
        if (dlg->d_flags & DF_BORDER)
73
        {
74
                req_w -= 2*BORDER_WIDTH;
75
                req_h -= 2*BORDER_WIDTH;
76
 
77
                gr_set_default_canvas();
78
                ui_draw_frame(*grd_curcanv, x, y, x + w - 1, y + h - 1);
79
        }
80
 
81
        ui_dialog_set_current_canvas(dlg);
82
 
83
        if (dlg->d_flags & DF_FILLED)
84
                ui_draw_box_out(*grd_curcanv, 0, 0, req_w-1, req_h-1);
85
 
86
        gr_set_fontcolor(*grd_curcanv, CBLACK, CWHITE);
87
}
88
 
89
 
90
// The dialog handler borrows heavily from the newmenu_handler
91
static window_event_result ui_dialog_handler(window *wind,const d_event &event, UI_DIALOG *dlg)
92
{
93
        window_event_result rval{window_event_result::ignored};
94
 
95
        if (event.type == EVENT_WINDOW_ACTIVATED ||
96
                event.type == EVENT_WINDOW_DEACTIVATED)
97
                return window_event_result::ignored;
98
 
99
        if (dlg->d_callback)
100
                if ((rval = (*dlg->d_callback)(dlg, event, dlg->d_userdata)) != window_event_result::ignored)
101
                        return rval;            // event handled
102
 
103
        switch (event.type)
104
        {
105
                case EVENT_IDLE:
106
                        timer_delay2(50);
107
                        DXX_BOOST_FALLTHROUGH;
108
                case EVENT_MOUSE_BUTTON_DOWN:
109
                case EVENT_MOUSE_BUTTON_UP:
110
                case EVENT_MOUSE_MOVED:
111
                case EVENT_KEY_COMMAND:
112
                case EVENT_KEY_RELEASE:
113
                        return ui_dialog_do_gadgets(dlg, event);
114
                case EVENT_WINDOW_DRAW:
115
                {
116
                        ui_dialog_draw(dlg);
117
                        rval = ui_dialog_do_gadgets(dlg, event);
118
                        if (rval != window_event_result::close)
119
                        {
120
                                d_event event2 = { EVENT_UI_DIALOG_DRAW };
121
                                window_send_event(*wind, event2);
122
                        }
123
                        return rval;
124
                }
125
 
126
                case EVENT_WINDOW_CLOSE:
127
                        if (rval != window_event_result::deleted)       // check if handler already deleted dialog (e.g. if UI_DIALOG was subclassed)
128
                                delete dlg;
129
                        return window_event_result::ignored;    // free the window in any case (until UI_DIALOG is subclass of window)
130
                default:
131
                        return window_event_result::ignored;
132
        }
133
}
134
 
135
UI_DIALOG::UI_DIALOG(short x, short y, short w, short h, const enum dialog_flags flags, const ui_subfunction_t<void> callback, void *const userdata, const void *const createdata) :
136
d_callback(callback), gadget(nullptr), keyboard_focus_gadget(nullptr), d_userdata(userdata), d_text_x(0), d_text_y(0), d_flags(flags)
137
{
138
        int sw, sh, req_w, req_h;
139
 
140
        auto dlg = this;
141
        sw = grd_curscreen->get_screen_width();
142
        sh = grd_curscreen->get_screen_height();
143
 
144
        //mouse_set_limits(0, 0, sw - 1, sh - 1);
145
 
146
        req_w = w;
147
        req_h = h;
148
 
149
        if (flags & DF_BORDER)
150
        {
151
                x -= BORDER_WIDTH;
152
                y -= BORDER_WIDTH;
153
                w += 2*BORDER_WIDTH;
154
                h += 2*BORDER_WIDTH;
155
        }
156
 
157
        if ( x < 0 ) x = 0;
158
        if ( (x+w-1) >= sw ) x = sw - w;
159
        if ( y < 0 ) y = 0;
160
        if ( (y+h-1) >= sh ) y = sh - h;
161
 
162
        D_X = x;
163
        D_Y = y;
164
        D_WIDTH = w;
165
        D_HEIGHT = h;
166
        selected_gadget = NULL;
167
 
168
        dlg->wind = window_create(grd_curscreen->sc_canvas,
169
                                                 x + ((flags & DF_BORDER) ? BORDER_WIDTH : 0),
170
                                                 y + ((flags & DF_BORDER) ? BORDER_WIDTH : 0),
171
                                                 req_w, req_h, ui_dialog_handler, dlg, createdata);
172
 
173
        if (!(flags & DF_MODAL))
174
                window_set_modal(dlg->wind, 0); // make this window modeless, allowing events to propogate through the window stack
175
}
176
 
177
window *ui_dialog_get_window(UI_DIALOG *dlg)
178
{
179
        return dlg->wind;
180
}
181
 
182
void ui_dialog_set_current_canvas(UI_DIALOG *dlg)
183
{
184
        gr_set_current_canvas(window_get_canvas(*dlg->wind));
185
}
186
 
187
UI_DIALOG::~UI_DIALOG()
188
{
189
        selected_gadget = NULL;
190
}
191
 
192
void ui_close_dialog( UI_DIALOG * dlg )
193
{
194
        window_close(dlg->wind);
195
}
196
 
197
#if 0
198
void restore_state()
199
{
200
        _disable();
201
        range_for (const int i, xrange(256u))
202
        {
203
                keyd_pressed[i] = SavedState[i];
204
        }
205
        _enable();
206
}
207
 
208
 
209
void ui_mega_process()
210
{
211
        int mx, my, mz;
212
        unsigned char k;
213
 
214
        event_process();
215
 
216
        switch( Record )
217
        {
218
        case 0:
219
                mouse_get_delta( &mx, &my, &mz );
220
                Mouse.new_dx = mx;
221
                Mouse.new_dy = my;
222
                Mouse.new_buttons = mouse_get_btns();
223
                last_keypress = key_inkey();
224
 
225
                if ( Mouse.new_buttons || last_keypress || Mouse.new_dx || Mouse.new_dy )       {
226
                        last_event = timer_query();
227
                }
228
 
229
                break;
230
        case 1:
231
 
232
                if (ui_event_counter==0 )
233
                {
234
                        EventBuffer[ui_event_counter].frame = 0;
235
                        EventBuffer[ui_event_counter].type = 7;
236
                        EventBuffer[ui_event_counter].data = ui_number_of_events;
237
                        ui_event_counter++;
238
                }
239
 
240
 
241
                if (ui_event_counter==1 && (RecordFlags & UI_RECORD_MOUSE) )
242
                {
243
                        Mouse.new_buttons = 0;
244
                        EventBuffer[ui_event_counter].frame = FrameCount;
245
                        EventBuffer[ui_event_counter].type = 6;
246
                        EventBuffer[ui_event_counter].data = ((Mouse.y & 0xFFFF) << 16) | (Mouse.x & 0xFFFF);
247
                        ui_event_counter++;
248
                }
249
 
250
                mouse_get_delta( &mx, &my, &mz );
251
                MouseDX = mx;
252
                MouseDY = my;
253
                MouseButtons = mouse_get_btns();
254
 
255
                Mouse.new_dx = MouseDX;
256
                Mouse.new_dy = MouseDY;
257
 
258
                if ((MouseDX != 0 || MouseDY != 0)  && (RecordFlags & UI_RECORD_MOUSE)  )
259
                {
260
                        if (ui_event_counter < ui_number_of_events-1 )
261
                        {
262
                                EventBuffer[ui_event_counter].frame = FrameCount;
263
                                EventBuffer[ui_event_counter].type = 1;
264
                                EventBuffer[ui_event_counter].data = ((MouseDY & 0xFFFF) << 16) | (MouseDX & 0xFFFF);
265
                                ui_event_counter++;
266
                        } else {
267
                                Record = 0;
268
                        }
269
 
270
                }
271
 
272
                if ( (MouseButtons != Mouse.new_buttons) && (RecordFlags & UI_RECORD_MOUSE) )
273
                {
274
                        Mouse.new_buttons = MouseButtons;
275
 
276
                        if (ui_event_counter < ui_number_of_events-1 )
277
                        {
278
                                EventBuffer[ui_event_counter].frame = FrameCount;
279
                                EventBuffer[ui_event_counter].type = 2;
280
                                EventBuffer[ui_event_counter].data = MouseButtons;
281
                                ui_event_counter++;
282
                        } else {
283
                                Record = 0;
284
                        }
285
 
286
                }
287
 
288
 
289
                if ( keyd_last_pressed && (RecordFlags & UI_RECORD_KEYS) )
290
                {
291
                        _disable();
292
                        k = keyd_last_pressed;
293
                        keyd_last_pressed= 0;
294
                        _enable();
295
 
296
                        if (ui_event_counter < ui_number_of_events-1 )
297
                        {
298
                                EventBuffer[ui_event_counter].frame = FrameCount;
299
                                EventBuffer[ui_event_counter].type = 3;
300
                                EventBuffer[ui_event_counter].data = k;
301
                                ui_event_counter++;
302
                        } else {
303
                                Record = 0;
304
                        }
305
 
306
                }
307
 
308
                if ( keyd_last_released && (RecordFlags & UI_RECORD_KEYS) )
309
                {
310
                        _disable();
311
                        k = keyd_last_released;
312
                        keyd_last_released= 0;
313
                        _enable();
314
 
315
                        if (ui_event_counter < ui_number_of_events-1 )
316
                        {
317
                                EventBuffer[ui_event_counter].frame = FrameCount;
318
                                EventBuffer[ui_event_counter].type = 4;
319
                                EventBuffer[ui_event_counter].data = k;
320
                                ui_event_counter++;
321
                        } else {
322
                                Record = 0;
323
                        }
324
                }
325
 
326
                last_keypress = key_inkey();
327
 
328
                if (last_keypress == KEY_F12 )
329
                {
330
                        ui_number_of_events = ui_event_counter;
331
                        last_keypress = 0;
332
                        Record = 0;
333
                        break;
334
                }
335
 
336
                if ((last_keypress != 0) && (RecordFlags & UI_RECORD_KEYS) )
337
                {
338
                        if (ui_event_counter < ui_number_of_events-1 )
339
                        {
340
                                EventBuffer[ui_event_counter].frame = FrameCount;
341
                                EventBuffer[ui_event_counter].type = 5;
342
                                EventBuffer[ui_event_counter].data = last_keypress;
343
                                ui_event_counter++;
344
                        } else {
345
                                Record = 0;
346
                        }
347
                }
348
 
349
                FrameCount++;
350
 
351
                break;
352
        case 2:
353
        case 3:
354
                Mouse.new_dx = 0;
355
                Mouse.new_dy = 0;
356
                Mouse.new_buttons = 0;
357
                last_keypress = 0;
358
 
359
                if ( keyd_last_pressed ) {
360
                        _disable();                    
361
                        k = keyd_last_pressed;
362
                        keyd_last_pressed = 0;
363
                        _disable();
364
                        SavedState[k] = 1;
365
                }
366
 
367
                if ( keyd_last_released )
368
                {
369
                        _disable();                    
370
                        k = keyd_last_released;
371
                        keyd_last_released = 0;
372
                        _disable();
373
                        SavedState[k] = 0;
374
                }
375
 
376
                if (key_inkey() == KEY_F12 )
377
                {
378
                        restore_state();
379
                        Record = 0;
380
                        break;
381
                }
382
 
383
                if (EventBuffer==NULL) {
384
                        restore_state();
385
                        Record = 0;
386
                        break;
387
                }
388
 
389
                while( (ui_event_counter < ui_number_of_events) && (EventBuffer[ui_event_counter].frame <= FrameCount) )
390
                {
391
                        switch ( EventBuffer[ui_event_counter].type )
392
                        {
393
                        case 1:     // Mouse moved
394
                                Mouse.new_dx = EventBuffer[ui_event_counter].data & 0xFFFF;
395
                                Mouse.new_dy = (EventBuffer[ui_event_counter].data >> 16) & 0xFFFF;
396
                                break;
397
                        case 2:     // Mouse buttons changed
398
                                Mouse.new_buttons = EventBuffer[ui_event_counter].data;
399
                                break;
400
                        case 3:     // Key moved down
401
                                keyd_pressed[ EventBuffer[ui_event_counter].data ] = 1;
402
                                break;
403
                        case 4:     // Key moved up
404
                                keyd_pressed[ EventBuffer[ui_event_counter].data ] = 0;
405
                                break;
406
                        case 5:     // Key pressed
407
                                last_keypress = EventBuffer[ui_event_counter].data;
408
                                break;
409
                        case 6:     // Initial Mouse X position
410
                                Mouse.x = EventBuffer[ui_event_counter].data & 0xFFFF;
411
                                Mouse.y = (EventBuffer[ui_event_counter].data >> 16) & 0xFFFF;
412
                                break;
413
                        case 7:
414
                                break;
415
                        }
416
                        ui_event_counter++;
417
                        if (ui_event_counter >= ui_number_of_events )
418
                        {
419
                                Record = 0;
420
                                restore_state();
421
                                //( 0, "Done playing %d events.\n", ui_number_of_events );
422
                        }
423
                }
424
 
425
                switch (Record)
426
                {
427
                case 2:
428
                        {
429
                                int next_frame;
430
 
431
                                if ( ui_event_counter < ui_number_of_events )
432
                                {
433
                                        next_frame = EventBuffer[ui_event_counter].frame;
434
 
435
                                        if ( (FrameCount+PlaybackSpeed) < next_frame )
436
                                                FrameCount = next_frame - PlaybackSpeed;
437
                                        else
438
                                                FrameCount++;
439
                                } else {
440
                                        FrameCount++;
441
                                }      
442
                        }
443
                        break;
444
 
445
                case 3:                
446
                        if ( ui_event_counter < ui_number_of_events )
447
                                FrameCount = EventBuffer[ui_event_counter].frame;
448
                        else           
449
                                FrameCount++;
450
                        break;
451
                default:               
452
                        FrameCount++;
453
                }
454
        }
455
 
456
        ui_mouse_process();
457
 
458
}
459
#endif // 0
460
 
461
void (ui_dprintf_at)( UI_DIALOG * dlg, short x, short y, const char * format, ... )
462
{
463
        char buffer[1000];
464
        va_list args;
465
 
466
        va_start(args, format );
467
        vsnprintf(buffer,sizeof(buffer),format,args);
468
        va_end(args);
469
 
470
        ui_dputs_at(dlg, x, y, buffer);
471
}
472
 
473
void ui_dputs_at( UI_DIALOG * dlg, short x, short y, const char * buffer )
474
{
475
        ui_dialog_set_current_canvas( dlg );
476
        gr_string(*grd_curcanv, *grd_curcanv->cv_font, x, y, buffer);
477
}
478
 
479
}