ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/AmigaOS/video_amiga.cpp
Revision: 1.8
Committed: 2000-07-22T18:25:48Z (24 years, 4 months ago) by cebix
Branch: MAIN
Changes since 1.7: +32 -1 lines
Log Message:
- Amiga mouse pointer is hidden inside windowed displays

File Contents

# Content
1 /*
2 * video_amiga.cpp - Video/graphics emulation, AmigaOS specific stuff
3 *
4 * Basilisk II (C) 1997-2000 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <exec/types.h>
22 #include <intuition/intuition.h>
23 #include <graphics/rastport.h>
24 #include <graphics/gfx.h>
25 #include <cybergraphics/cybergraphics.h>
26 #include <dos/dostags.h>
27 #include <devices/timer.h>
28 #include <proto/exec.h>
29 #include <proto/dos.h>
30 #include <proto/intuition.h>
31 #include <proto/graphics.h>
32 #include <proto/Picasso96.h>
33 #include <proto/cybergraphics.h>
34
35 #include "sysdeps.h"
36 #include "main.h"
37 #include "adb.h"
38 #include "prefs.h"
39 #include "user_strings.h"
40 #include "video.h"
41
42 #define DEBUG 0
43 #include "debug.h"
44
45
46 // Display types
47 enum {
48 DISPLAY_WINDOW,
49 DISPLAY_PIP,
50 DISPLAY_SCREEN_P96,
51 DISPLAY_SCREEN_CGFX
52 };
53
54 // Global variables
55 static int32 frame_skip;
56 static int display_type = DISPLAY_WINDOW; // See enum above
57 static struct Screen *the_screen = NULL;
58 static struct Window *the_win = NULL;
59 static struct BitMap *the_bitmap = NULL;
60 static UWORD *null_pointer = NULL; // Blank mouse pointer data
61 static UWORD *current_pointer = (UWORD *)-1; // Currently visible mouse pointer data
62 static LONG black_pen = -1, white_pen = -1;
63 static struct Process *periodic_proc = NULL; // Periodic process
64
65 extern struct Task *MainTask; // Pointer to main task (from main_amiga.cpp)
66
67
68 // Amiga -> Mac raw keycode translation table
69 static const uint8 keycode2mac[0x80] = {
70 0x0a, 0x12, 0x13, 0x14, 0x15, 0x17, 0x16, 0x1a, // ` 1 2 3 4 5 6 7
71 0x1c, 0x19, 0x1d, 0x1b, 0x18, 0x2a, 0xff, 0x52, // 8 9 0 - = \ inv 0
72 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x10, 0x20, 0x22, // Q W E R T Y U I
73 0x1f, 0x23, 0x21, 0x1e, 0xff, 0x53, 0x54, 0x55, // O P [ ] inv 1 2 3
74 0x00, 0x01, 0x02, 0x03, 0x05, 0x04, 0x26, 0x28, // A S D F G H J K
75 0x25, 0x29, 0x27, 0x2a, 0xff, 0x56, 0x57, 0x58, // L ; ' # inv 4 5 6
76 0x32, 0x06, 0x07, 0x08, 0x09, 0x0b, 0x2d, 0x2e, // < Z X C V B N M
77 0x2b, 0x2f, 0x2c, 0xff, 0x41, 0x59, 0x5b, 0x5c, // , . / inv . 7 8 9
78 0x31, 0x33, 0x30, 0x4c, 0x24, 0x35, 0x75, 0xff, // SPC BSP TAB ENT RET ESC DEL inv
79 0xff, 0xff, 0x4e, 0xff, 0x3e, 0x3d, 0x3c, 0x3b, // inv inv - inv CUP CDN CRT CLF
80 0x7a, 0x78, 0x63, 0x76, 0x60, 0x61, 0x62, 0x64, // F1 F2 F3 F4 F5 F6 F7 F8
81 0x65, 0x6d, 0x47, 0x51, 0x4b, 0x43, 0x45, 0x72, // F9 F10 ( ) / * + HLP
82 0x38, 0x38, 0x39, 0x36, 0x3a, 0x3a, 0x37, 0x37, // SHL SHR CAP CTL ALL ALR AML AMR
83 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv
84 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv
85 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv
86 };
87
88
89 // Prototypes
90 static void periodic_func(void);
91
92
93 /*
94 * Initialization
95 */
96
97 // Open window
98 static bool init_window(int width, int height)
99 {
100 // Set absolute mouse mode
101 ADBSetRelMouseMode(false);
102
103 // Open window
104 the_win = OpenWindowTags(NULL,
105 WA_Left, 0, WA_Top, 0,
106 WA_InnerWidth, width, WA_InnerHeight, height,
107 WA_SimpleRefresh, TRUE,
108 WA_NoCareRefresh, TRUE,
109 WA_Activate, TRUE,
110 WA_RMBTrap, TRUE,
111 WA_ReportMouse, TRUE,
112 WA_DragBar, TRUE,
113 WA_DepthGadget, TRUE,
114 WA_SizeGadget, FALSE,
115 WA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
116 TAG_END
117 );
118 if (the_win == NULL) {
119 ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
120 return false;
121 }
122
123 // Create bitmap ("height + 2" for safety)
124 the_bitmap = AllocBitMap(width, height + 2, 1, BMF_CLEAR, NULL);
125 if (the_bitmap == NULL) {
126 ErrorAlert(GetString(STR_NO_MEM_ERR));
127 return false;
128 }
129
130 // Set VideoMonitor
131 VideoMonitor.mac_frame_base = (uint32)the_bitmap->Planes[0];
132 VideoMonitor.bytes_per_row = the_bitmap->BytesPerRow;
133 VideoMonitor.x = width;
134 VideoMonitor.y = height;
135 VideoMonitor.mode = VMODE_1BIT;
136
137 // Set FgPen and BgPen
138 black_pen = ObtainBestPenA(the_win->WScreen->ViewPort.ColorMap, 0, 0, 0, NULL);
139 white_pen = ObtainBestPenA(the_win->WScreen->ViewPort.ColorMap, 0xffffffff, 0xffffffff, 0xffffffff, NULL);
140 SetAPen(the_win->RPort, black_pen);
141 SetBPen(the_win->RPort, white_pen);
142 SetDrMd(the_win->RPort, JAM2);
143 return true;
144 }
145
146 // Open PIP (requires Picasso96)
147 static bool init_pip(int width, int height)
148 {
149 // Set absolute mouse mode
150 ADBSetRelMouseMode(false);
151
152 // Open window
153 ULONG error = 0;
154 the_win = p96PIP_OpenTags(
155 P96PIP_SourceFormat, RGBFB_R5G5B5,
156 P96PIP_SourceWidth, width,
157 P96PIP_SourceHeight, height,
158 P96PIP_ErrorCode, (ULONG)&error,
159 WA_Left, 0, WA_Top, 0,
160 WA_InnerWidth, width, WA_InnerHeight, height,
161 WA_SimpleRefresh, TRUE,
162 WA_NoCareRefresh, TRUE,
163 WA_Activate, TRUE,
164 WA_RMBTrap, TRUE,
165 WA_ReportMouse, TRUE,
166 WA_DragBar, TRUE,
167 WA_DepthGadget, TRUE,
168 WA_SizeGadget, FALSE,
169 WA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
170 WA_PubScreenName, (ULONG)"Workbench",
171 TAG_END
172 );
173 if (the_win == NULL || error) {
174 ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
175 return false;
176 }
177
178 // Find bitmap
179 p96PIP_GetTags(the_win, P96PIP_SourceBitMap, (ULONG)&the_bitmap, TAG_END);
180
181 // Set VideoMonitor
182 VideoMonitor.mac_frame_base = p96GetBitMapAttr(the_bitmap, P96BMA_MEMORY);
183 VideoMonitor.bytes_per_row = p96GetBitMapAttr(the_bitmap, P96BMA_BYTESPERROW);
184 VideoMonitor.x = width;
185 VideoMonitor.y = height;
186 VideoMonitor.mode = VMODE_16BIT;
187 return true;
188 }
189
190 // Open Picasso96 screen
191 static bool init_screen_p96(ULONG mode_id)
192 {
193 // Set relative mouse mode
194 ADBSetRelMouseMode(true);
195
196 // Check if the mode is one we can handle
197 uint32 depth = p96GetModeIDAttr(mode_id, P96IDA_DEPTH);
198 uint32 format = p96GetModeIDAttr(mode_id, P96IDA_RGBFORMAT);
199
200 switch (depth) {
201 case 8:
202 VideoMonitor.mode = VMODE_8BIT;
203 break;
204 case 15:
205 case 16:
206 if (format != RGBFB_R5G5B5) {
207 ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
208 return false;
209 }
210 VideoMonitor.mode = VMODE_16BIT;
211 break;
212 case 24:
213 case 32:
214 if (format != RGBFB_A8R8G8B8) {
215 ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
216 return false;
217 }
218 VideoMonitor.mode = VMODE_32BIT;
219 break;
220 default:
221 ErrorAlert(GetString(STR_WRONG_SCREEN_DEPTH_ERR));
222 return false;
223 }
224
225 // Yes, get width and height
226 uint32 width = p96GetModeIDAttr(mode_id, P96IDA_WIDTH);
227 uint32 height = p96GetModeIDAttr(mode_id, P96IDA_HEIGHT);
228
229 VideoMonitor.x = width;
230 VideoMonitor.y = height;
231
232 // Open screen
233 the_screen = p96OpenScreenTags(
234 P96SA_DisplayID, mode_id,
235 P96SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
236 P96SA_Quiet, TRUE,
237 P96SA_NoMemory, TRUE,
238 P96SA_NoSprite, TRUE,
239 P96SA_Exclusive, TRUE,
240 TAG_END
241 );
242 if (the_screen == NULL) {
243 ErrorAlert(GetString(STR_OPEN_SCREEN_ERR));
244 return false;
245 }
246
247 // Open window
248 the_win = OpenWindowTags(NULL,
249 WA_Left, 0, WA_Top, 0,
250 WA_Width, width, WA_Height, height,
251 WA_NoCareRefresh, TRUE,
252 WA_Borderless, TRUE,
253 WA_Activate, TRUE,
254 WA_RMBTrap, TRUE,
255 WA_ReportMouse, TRUE,
256 WA_CustomScreen, (ULONG)the_screen,
257 TAG_END
258 );
259 if (the_win == NULL) {
260 ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
261 return false;
262 }
263
264 // Set VideoMonitor
265 ScreenToFront(the_screen);
266 VideoMonitor.mac_frame_base = p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_MEMORY);
267 VideoMonitor.bytes_per_row = p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_BYTESPERROW);
268 return true;
269 }
270
271 // Open CyberGraphX screen
272 static bool init_screen_cgfx(ULONG mode_id)
273 {
274 // Set relative mouse mode
275 ADBSetRelMouseMode(true);
276
277 // Check if the mode is one we can handle
278 uint32 depth = GetCyberIDAttr(CYBRIDATTR_DEPTH, mode_id);
279 uint32 format = GetCyberIDAttr(CYBRIDATTR_PIXFMT, mode_id);
280
281 switch (depth) {
282 case 8:
283 VideoMonitor.mode = VMODE_8BIT;
284 break;
285 case 15:
286 case 16:
287 if (format != PIXFMT_RGB16) {
288 ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
289 return false;
290 }
291 VideoMonitor.mode = VMODE_16BIT;
292 break;
293 case 24:
294 case 32:
295 if (format != PIXFMT_ARGB32) {
296 ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
297 return false;
298 }
299 VideoMonitor.mode = VMODE_32BIT;
300 break;
301 default:
302 ErrorAlert(GetString(STR_WRONG_SCREEN_DEPTH_ERR));
303 return false;
304 }
305
306 // Yes, get width and height
307 uint32 width = GetCyberIDAttr(CYBRIDATTR_WIDTH, mode_id);
308 uint32 height = GetCyberIDAttr(CYBRIDATTR_HEIGHT, mode_id);
309
310 VideoMonitor.x = width;
311 VideoMonitor.y = height;
312
313 // Open screen
314 the_screen = OpenScreenTags(NULL,
315 SA_DisplayID, mode_id,
316 SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
317 SA_Quiet, TRUE,
318 SA_Exclusive, TRUE,
319 TAG_END
320 );
321 if (the_screen == NULL) {
322 ErrorAlert(GetString(STR_OPEN_SCREEN_ERR));
323 return false;
324 }
325
326 // Open window
327 the_win = OpenWindowTags(NULL,
328 WA_Left, 0, WA_Top, 0,
329 WA_Width, width, WA_Height, height,
330 WA_NoCareRefresh, TRUE,
331 WA_Borderless, TRUE,
332 WA_Activate, TRUE,
333 WA_RMBTrap, TRUE,
334 WA_ReportMouse, TRUE,
335 WA_CustomScreen, (ULONG)the_screen,
336 TAG_END
337 );
338 if (the_win == NULL) {
339 ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
340 return false;
341 }
342
343 // Set VideoMonitor
344 ScreenToFront(the_screen);
345 static UWORD ptr[] = { 0, 0, 0, 0 };
346 SetPointer(the_win, ptr, 0, 0, 0, 0); // Hide mouse pointer
347 APTR handle = LockBitMapTags(the_screen->RastPort.BitMap,
348 LBMI_BASEADDRESS, (ULONG)&VideoMonitor.mac_frame_base,
349 TAG_END);
350 UnLockBitMap(handle);
351 VideoMonitor.bytes_per_row = GetCyberMapAttr(the_screen->RastPort.BitMap, CYBRMATTR_XMOD);
352 return true;
353 }
354
355 bool VideoInit(bool classic)
356 {
357 // Allocate blank mouse pointer data
358 null_pointer = (UWORD *)AllocMem(12, MEMF_PUBLIC | MEMF_CHIP | MEMF_CLEAR);
359 if (null_pointer == NULL) {
360 ErrorAlert(GetString(STR_NO_MEM_ERR));
361 return false;
362 }
363
364 // Read frame skip prefs
365 frame_skip = PrefsFindInt32("frameskip");
366 if (frame_skip == 0)
367 frame_skip = 1;
368
369 // Get screen mode from preferences
370 const char *mode_str;
371 if (classic)
372 mode_str = "win/512/342";
373 else
374 mode_str = PrefsFindString("screen");
375
376 // Determine type and mode
377 display_type = DISPLAY_WINDOW;
378 int width = 512, height = 384;
379 ULONG mode_id = 0;
380 if (mode_str) {
381 if (sscanf(mode_str, "win/%d/%d", &width, &height) == 2)
382 display_type = DISPLAY_WINDOW;
383 else if (sscanf(mode_str, "pip/%d/%d", &width, &height) == 2 && P96Base)
384 display_type = DISPLAY_PIP;
385 else if (sscanf(mode_str, "scr/%08lx", &mode_id) == 1 && (CyberGfxBase || P96Base)) {
386 if (P96Base && p96GetModeIDAttr(mode_id, P96IDA_ISP96))
387 display_type = DISPLAY_SCREEN_P96;
388 else if (CyberGfxBase && IsCyberModeID(mode_id))
389 display_type = DISPLAY_SCREEN_CGFX;
390 else {
391 ErrorAlert(GetString(STR_NO_P96_MODE_ERR));
392 return false;
393 }
394 }
395 }
396
397 // Open display
398 switch (display_type) {
399 case DISPLAY_WINDOW:
400 if (!init_window(width, height))
401 return false;
402 break;
403
404 case DISPLAY_PIP:
405 if (!init_pip(width, height))
406 return false;
407 break;
408
409 case DISPLAY_SCREEN_P96:
410 if (!init_screen_p96(mode_id))
411 return false;
412 break;
413
414 case DISPLAY_SCREEN_CGFX:
415 if (!init_screen_cgfx(mode_id))
416 return false;
417 break;
418 }
419
420 // Start periodic process
421 periodic_proc = CreateNewProcTags(
422 NP_Entry, (ULONG)periodic_func,
423 NP_Name, (ULONG)"Basilisk II IDCMP Handler",
424 NP_Priority, 0,
425 TAG_END
426 );
427 if (periodic_proc == NULL) {
428 ErrorAlert(GetString(STR_NO_MEM_ERR));
429 return false;
430 }
431 return true;
432 }
433
434
435 /*
436 * Deinitialization
437 */
438
439 void VideoExit(void)
440 {
441 // Stop periodic process
442 if (periodic_proc) {
443 SetSignal(0, SIGF_SINGLE);
444 Signal(&periodic_proc->pr_Task, SIGBREAKF_CTRL_C);
445 Wait(SIGF_SINGLE);
446 }
447
448 switch (display_type) {
449
450 case DISPLAY_WINDOW:
451
452 // Window mode, free bitmap
453 if (the_bitmap) {
454 WaitBlit();
455 FreeBitMap(the_bitmap);
456 }
457
458 // Free pens and close window
459 if (the_win) {
460 ReleasePen(the_win->WScreen->ViewPort.ColorMap, black_pen);
461 ReleasePen(the_win->WScreen->ViewPort.ColorMap, white_pen);
462
463 CloseWindow(the_win);
464 }
465 break;
466
467 case DISPLAY_PIP:
468
469 // Close PIP
470 if (the_win)
471 p96PIP_Close(the_win);
472 break;
473
474 case DISPLAY_SCREEN_P96:
475
476 // Close window
477 if (the_win)
478 CloseWindow(the_win);
479
480 // Close screen
481 if (the_screen) {
482 p96CloseScreen(the_screen);
483 the_screen = NULL;
484 }
485 break;
486
487 case DISPLAY_SCREEN_CGFX:
488
489 // Close window
490 if (the_win)
491 CloseWindow(the_win);
492
493 // Close screen
494 if (the_screen) {
495 CloseScreen(the_screen);
496 the_screen = NULL;
497 }
498 break;
499 }
500
501 // Free mouse pointer
502 if (null_pointer) {
503 FreeMem(null_pointer, 12);
504 null_pointer = NULL;
505 }
506 }
507
508
509 /*
510 * Set palette
511 */
512
513 void video_set_palette(uint8 *pal)
514 {
515 if (display_type == DISPLAY_SCREEN_P96 || display_type == DISPLAY_SCREEN_CGFX) {
516
517 // Convert palette to 32 bits
518 ULONG table[2 + 256 * 3];
519 table[0] = 256 << 16;
520 table[256 * 3 + 1] = 0;
521 for (int i=0; i<256; i++) {
522 table[i*3+1] = pal[i*3] * 0x01010101;
523 table[i*3+2] = pal[i*3+1] * 0x01010101;
524 table[i*3+3] = pal[i*3+2] * 0x01010101;
525 }
526
527 // And load it
528 LoadRGB32(&the_screen->ViewPort, table);
529 }
530 }
531
532
533 /*
534 * Video message handling (not neccessary under AmigaOS, handled by periodic_func())
535 */
536
537 void VideoInterrupt(void)
538 {
539 }
540
541
542 /*
543 * Process for window refresh and message handling
544 */
545
546 static __saveds void periodic_func(void)
547 {
548 struct MsgPort *timer_port = NULL;
549 struct timerequest *timer_io = NULL;
550 struct IntuiMessage *msg;
551 ULONG win_mask = 0, timer_mask = 0;
552
553 // Create message port for window and attach it
554 struct MsgPort *win_port = CreateMsgPort();
555 if (win_port) {
556 win_mask = 1 << win_port->mp_SigBit;
557 the_win->UserPort = win_port;
558 ModifyIDCMP(the_win, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY | ((display_type == DISPLAY_SCREEN_P96 || display_type == DISPLAY_SCREEN_CGFX) ? IDCMP_DELTAMOVE : 0));
559 }
560
561 // Start 60Hz timer for window refresh
562 if (display_type == DISPLAY_WINDOW) {
563 timer_port = CreateMsgPort();
564 if (timer_port) {
565 timer_io = (struct timerequest *)CreateIORequest(timer_port, sizeof(struct timerequest));
566 if (timer_io) {
567 if (!OpenDevice((UBYTE *)TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timer_io, 0)) {
568 timer_mask = 1 << timer_port->mp_SigBit;
569 timer_io->tr_node.io_Command = TR_ADDREQUEST;
570 timer_io->tr_time.tv_secs = 0;
571 timer_io->tr_time.tv_micro = 16667 * frame_skip;
572 SendIO((struct IORequest *)timer_io);
573 }
574 }
575 }
576 }
577
578 // Main loop
579 for (;;) {
580
581 // Wait for timer and/or window (CTRL_C is used for quitting the task)
582 ULONG sig = Wait(win_mask | timer_mask | SIGBREAKF_CTRL_C);
583
584 if (sig & SIGBREAKF_CTRL_C)
585 break;
586
587 if (sig & timer_mask) {
588
589 // Timer tick, update display
590 BltTemplate(the_bitmap->Planes[0], 0, the_bitmap->BytesPerRow, the_win->RPort,
591 the_win->BorderLeft, the_win->BorderTop, VideoMonitor.x, VideoMonitor.y);
592
593 // Restart timer
594 timer_io->tr_node.io_Command = TR_ADDREQUEST;
595 timer_io->tr_time.tv_secs = 0;
596 timer_io->tr_time.tv_micro = 16667 * frame_skip;
597 SendIO((struct IORequest *)timer_io);
598 }
599
600 if (sig & win_mask) {
601
602 // Handle window messages
603 while (msg = (struct IntuiMessage *)GetMsg(win_port)) {
604
605 // Get data from message and reply
606 ULONG cl = msg->Class;
607 UWORD code = msg->Code;
608 UWORD qualifier = msg->Qualifier;
609 WORD mx = msg->MouseX;
610 WORD my = msg->MouseY;
611 ReplyMsg((struct Message *)msg);
612
613 // Handle message according to class
614 switch (cl) {
615 case IDCMP_MOUSEMOVE:
616 if (display_type == DISPLAY_SCREEN_P96 || display_type == DISPLAY_SCREEN_CGFX)
617 ADBMouseMoved(mx, my);
618 else {
619 ADBMouseMoved(mx - the_win->BorderLeft, my - the_win->BorderTop);
620 if (mx < the_win->BorderLeft
621 || my < the_win->BorderTop
622 || mx >= the_win->BorderLeft + VideoMonitor.x
623 || my >= the_win->BorderTop + VideoMonitor.y) {
624 if (current_pointer) {
625 ClearPointer(the_win);
626 current_pointer = NULL;
627 }
628 } else {
629 if (current_pointer != null_pointer) {
630 // Hide mouse pointer inside window
631 SetPointer(the_win, null_pointer, 1, 16, 0, 0);
632 current_pointer = null_pointer;
633 }
634 }
635 }
636 break;
637
638 case IDCMP_MOUSEBUTTONS:
639 if (code == SELECTDOWN)
640 ADBMouseDown(0);
641 else if (code == SELECTUP)
642 ADBMouseUp(0);
643 else if (code == MENUDOWN)
644 ADBMouseDown(1);
645 else if (code == MENUUP)
646 ADBMouseUp(1);
647 else if (code == MIDDLEDOWN)
648 ADBMouseDown(2);
649 else if (code == MIDDLEUP)
650 ADBMouseUp(2);
651 break;
652
653 case IDCMP_RAWKEY:
654 if (qualifier & IEQUALIFIER_REPEAT) // Keyboard repeat is done by MacOS
655 break;
656 if (code & IECODE_UP_PREFIX)
657 ADBKeyUp(keycode2mac[code & 0x7f]);
658 else
659 ADBKeyDown(keycode2mac[code & 0x7f]);
660 break;
661 }
662 }
663 }
664 }
665
666 // Stop timer
667 if (timer_io) {
668 if (!CheckIO((struct IORequest *)timer_io))
669 AbortIO((struct IORequest *)timer_io);
670 WaitIO((struct IORequest *)timer_io);
671 CloseDevice((struct IORequest *)timer_io);
672 DeleteIORequest(timer_io);
673 }
674 if (timer_port)
675 DeleteMsgPort(timer_port);
676
677 // Remove port from window and delete it
678 Forbid();
679 msg = (struct IntuiMessage *)win_port->mp_MsgList.lh_Head;
680 struct Node *succ;
681 while (succ = msg->ExecMessage.mn_Node.ln_Succ) {
682 if (msg->IDCMPWindow == the_win) {
683 Remove((struct Node *)msg);
684 ReplyMsg((struct Message *)msg);
685 }
686 msg = (struct IntuiMessage *)succ;
687 }
688 the_win->UserPort = NULL;
689 ModifyIDCMP(the_win, 0);
690 Permit();
691 DeleteMsgPort(win_port);
692
693 // Main task asked for termination, send signal
694 Forbid();
695 Signal(MainTask, SIGF_SINGLE);
696 }