1 /***********************************************************************************
2   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3 
4   (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5                              Jerremy Koot (jkoot@snes9x.com)
6 
7   (c) Copyright 2002 - 2004  Matthew Kendora
8 
9   (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10 
11   (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12 
13   (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14 
15   (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16                              Kris Bleakley (codeviolation@hotmail.com)
17 
18   (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19                              Nach (n-a-c-h@users.sourceforge.net),
20 
21   (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22 
23   (c) Copyright 2006 - 2007  nitsuja
24 
25   (c) Copyright 2009 - 2016  BearOso,
26                              OV2
27 
28 
29   BS-X C emulator code
30   (c) Copyright 2005 - 2006  Dreamer Nom,
31                              zones
32 
33   C4 x86 assembler and some C emulation code
34   (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35                              Nach,
36                              zsKnight (zsknight@zsnes.com)
37 
38   C4 C++ code
39   (c) Copyright 2003 - 2006  Brad Jorsch,
40                              Nach
41 
42   DSP-1 emulator code
43   (c) Copyright 1998 - 2006  _Demo_,
44                              Andreas Naive (andreasnaive@gmail.com),
45                              Gary Henderson,
46                              Ivar (ivar@snes9x.com),
47                              John Weidman,
48                              Kris Bleakley,
49                              Matthew Kendora,
50                              Nach,
51                              neviksti (neviksti@hotmail.com)
52 
53   DSP-2 emulator code
54   (c) Copyright 2003         John Weidman,
55                              Kris Bleakley,
56                              Lord Nightmare (lord_nightmare@users.sourceforge.net),
57                              Matthew Kendora,
58                              neviksti
59 
60   DSP-3 emulator code
61   (c) Copyright 2003 - 2006  John Weidman,
62                              Kris Bleakley,
63                              Lancer,
64                              z80 gaiden
65 
66   DSP-4 emulator code
67   (c) Copyright 2004 - 2006  Dreamer Nom,
68                              John Weidman,
69                              Kris Bleakley,
70                              Nach,
71                              z80 gaiden
72 
73   OBC1 emulator code
74   (c) Copyright 2001 - 2004  zsKnight,
75                              pagefault (pagefault@zsnes.com),
76                              Kris Bleakley
77                              Ported from x86 assembler to C by sanmaiwashi
78 
79   SPC7110 and RTC C++ emulator code used in 1.39-1.51
80   (c) Copyright 2002         Matthew Kendora with research by
81                              zsKnight,
82                              John Weidman,
83                              Dark Force
84 
85   SPC7110 and RTC C++ emulator code used in 1.52+
86   (c) Copyright 2009         byuu,
87                              neviksti
88 
89   S-DD1 C emulator code
90   (c) Copyright 2003         Brad Jorsch with research by
91                              Andreas Naive,
92                              John Weidman
93 
94   S-RTC C emulator code
95   (c) Copyright 2001 - 2006  byuu,
96                              John Weidman
97 
98   ST010 C++ emulator code
99   (c) Copyright 2003         Feather,
100                              John Weidman,
101                              Kris Bleakley,
102                              Matthew Kendora
103 
104   Super FX x86 assembler emulator code
105   (c) Copyright 1998 - 2003  _Demo_,
106                              pagefault,
107                              zsKnight
108 
109   Super FX C emulator code
110   (c) Copyright 1997 - 1999  Ivar,
111                              Gary Henderson,
112                              John Weidman
113 
114   Sound emulator code used in 1.5-1.51
115   (c) Copyright 1998 - 2003  Brad Martin
116   (c) Copyright 1998 - 2006  Charles Bilyue'
117 
118   Sound emulator code used in 1.52+
119   (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120 
121   S-SMP emulator code used in 1.54+
122   (c) Copyright 2016         byuu
123 
124   SH assembler code partly based on x86 assembler code
125   (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
126 
127   2xSaI filter
128   (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
129 
130   HQ2x, HQ3x, HQ4x filters
131   (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
132 
133   NTSC filter
134   (c) Copyright 2006 - 2007  Shay Green
135 
136   GTK+ GUI code
137   (c) Copyright 2004 - 2016  BearOso
138 
139   Win32 GUI code
140   (c) Copyright 2003 - 2006  blip,
141                              funkyass,
142                              Matthew Kendora,
143                              Nach,
144                              nitsuja
145   (c) Copyright 2009 - 2016  OV2
146 
147   Mac OS GUI code
148   (c) Copyright 1998 - 2001  John Stiles
149   (c) Copyright 2001 - 2011  zones
150 
151 
152   Specific ports contains the works of other authors. See headers in
153   individual files.
154 
155 
156   Snes9x homepage: http://www.snes9x.com/
157 
158   Permission to use, copy, modify and/or distribute Snes9x in both binary
159   and source form, for non-commercial purposes, is hereby granted without
160   fee, providing that this license information and copyright notice appear
161   with all copies and any derived work.
162 
163   This software is provided 'as-is', without any express or implied
164   warranty. In no event shall the authors be held liable for any damages
165   arising from the use of this software or it's derivatives.
166 
167   Snes9x is freeware for PERSONAL USE only. Commercial users should
168   seek permission of the copyright holders first. Commercial use includes,
169   but is not limited to, charging money for Snes9x or software derived from
170   Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
171   using Snes9x as a promotion for your commercial product.
172 
173   The copyright holders request that bug fixes and improvements to the code
174   should be forwarded to them so everyone can benefit from the modifications
175   in future versions.
176 
177   Super NES and Super Nintendo Entertainment System are trademarks of
178   Nintendo Co., Limited and its subsidiary companies.
179  ***********************************************************************************/
180 
181 /***********************************************************************************
182   SNES9X for Mac OS (c) Copyright John Stiles
183 
184   Snes9x for Mac OS X
185 
186   (c) Copyright 2001 - 2011  zones
187   (c) Copyright 2002 - 2005  107
188   (c) Copyright 2002         PB1400c
189   (c) Copyright 2004         Alexander and Sander
190   (c) Copyright 2004 - 2005  Steven Seeger
191   (c) Copyright 2005         Ryan Vogt
192  ***********************************************************************************/
193 
194 
195 #include "port.h"
196 
197 #include "mac-prefix.h"
198 #include "mac-dialog.h"
199 #include "mac-gworld.h"
200 #include "mac-os.h"
201 #include "mac-keyboard.h"
202 
203 #define kmUpArrowKey	0x7E
204 #define kmDownArrowKey	0x7D
205 #define kmRightArrowKey	0x7C
206 #define kmLeftArrowKey	0x7B
207 #define kmReturnKey		0x24
208 #define kmTabKey		0x30
209 #define kmShiftKey		0x38
210 #define kmControlKey	0x3B
211 #define kmOptionKey		0x3A
212 #define kmCommandKey	0x37
213 #define kmXKey			0x07
214 #define kmZKey			0x06
215 #define kmKP2Key		0x54
216 #define kmKP4Key		0x56
217 #define kmKP5Key		0x57
218 #define kmKP6Key		0x58
219 #define kmKP8Key		0x5B
220 #define kmKPEnterKey	0x4C
221 #define kmKPPlusKey		0x45
222 #define kmKP0Key		0x52
223 #define kmKPPeriodKey	0x41
224 #define kmHomeKey		0x73
225 #define kmPageUpKey		0x74
226 #define kmEndKey		0x77
227 #define kmPageDownKey	0x79
228 #define kmBackslashKey	0x2A
229 #define km1Key			0x12
230 #define km0Key			0x1D
231 #define kmIKey			0x22
232 #define kmJKey			0x26
233 #define kmKKey			0x28
234 #define kmLKey			0x25
235 #define kmTildeKey		0x32
236 #define	kmRKey			0x0F
237 #define	kmBKey			0x0B
238 #define	kmNKey			0x2D
239 #define	kmMKey			0x2E
240 #define	kmSpaceKey		0x31
241 #define kmSlashKey		0x2C
242 #define	kmPeriodKey		0x2F
243 #define	kmQKey			0x0C
244 #define	kmWKey			0x0D
245 #define	kmEscKey		0x35
246 #define	kmCommaKey		0x2B
247 
248 #define kIconSize		16
249 #define kKeySize		24
250 #define KS				kKeySize
251 
252 uint8	keyCode[kKeys] =
253 {
254 	kmUpArrowKey,
255 	kmDownArrowKey,
256 	kmLeftArrowKey,
257 	kmRightArrowKey,
258 	kmShiftKey,
259 	kmOptionKey,
260 	kmControlKey,
261 	kmCommandKey,
262 	kmZKey,
263 	kmXKey,
264 	kmReturnKey,
265 	kmTabKey,
266 
267 	kmKP8Key,
268 	kmKP2Key,
269 	kmKP4Key,
270 	kmKP6Key,
271 	kmPageDownKey,
272 	kmPageUpKey,
273 	kmEndKey,
274 	kmHomeKey,
275 	kmKP0Key,
276 	kmKPPeriodKey,
277 	kmKPEnterKey,
278 	kmKPPlusKey,
279 
280 	kmBackslashKey,
281 	km1Key,
282 	km0Key,
283 	kmTildeKey,
284 	kmRKey,
285 	kmBKey,
286 	kmNKey,
287 	kmMKey,
288 	kmSpaceKey,
289 	kmSlashKey,
290 	kmPeriodKey,
291 	kmQKey,
292 	kmWKey,
293 	kmEscKey,
294 	kmCommaKey
295 };
296 
297 typedef struct
298 {
299 	int			keyWidth, keyHeight;
300 	uint8		scancode;
301   	const char	*keyLabel;
302 }	KeyboardLayout;
303 
304 typedef struct
305 {
306 	HIViewRef	view;
307 }	CustomViewData;
308 
309 static CGImageRef		iconTableImage;
310 static CGImageRef		keyLayoutImage;
311 static CGImageRef		iconPlaceImage;
312 static Ptr				iconTableCGWld;
313 static Ptr				keyLayoutWorld;
314 static Ptr				iconPlaceWorld;
315 
316 static CGRect			keyRect[0x80][2];
317 static uint8			defaultKeys[kKeys];
318 
319 static HIObjectClassRef	theClass;
320 static HIViewRef		customView;
321 static HIPoint			mousePos;
322 static float			ofsx, ofsy;
323 static int				dragKey;
324 static CGPoint			dragKeyOfs;
325 static CGRect			dragKeyRect;
326 static volatile Boolean	keyInDrag;
327 
328 static const int		kKeyLayoutWidth  = kKeySize * 23 + 1,
329 						kKeyLayoutHeight = kKeySize *  7 + 1;
330 
331 static KeyboardLayout	keys[] =
332 {
333 	{ KS,         KS,     0x35, "esc"    },
334 	{ KS,         KS,     0x00, NULL     },
335 	{ KS,         KS,     0x7a, "F1"     },
336 	{ KS,         KS,     0x78, "F2"     },
337 	{ KS,         KS,     0x63, "F3"     },
338 	{ KS,         KS,     0x76, "F4"     },
339 	{ KS / 2,     KS,     0x00, NULL     },
340 	{ KS,         KS,     0x60, "F5"     },
341 	{ KS,         KS,     0x61, "F6"     },
342 	{ KS,         KS,     0x62, "F7"     },
343 	{ KS,         KS,     0x64, "F8"     },
344 	{ KS / 2,     KS,     0x00, NULL     },
345 	{ KS,         KS,     0x65, "F9"     },
346 	{ KS,         KS,     0x6d, "F10"    },
347 	{ KS,         KS,     0x67, "F11"    },
348 	{ KS,         KS,     0x6f, "F12"    },
349 	{ KS / 2,     KS,     0x00, NULL     },
350 	{ KS,         KS,     0x69, "F13"    },
351 	{ KS,         KS,     0x6b, "F14"    },
352 	{ KS,         KS,     0x71, "F15"    },
353 	{ 0,          0,      0x00, NULL     },
354 
355 	{ 0,          0,      0x00, NULL     },
356 
357 	{ KS,         KS,     0x32, "`"      },
358 	{ KS,         KS,     0x12, "1"      },
359 	{ KS,         KS,     0x13, "2"      },
360 	{ KS,         KS,     0x14, "3"      },
361 	{ KS,         KS,     0x15, "4"      },
362 	{ KS,         KS,     0x17, "5"      },
363 	{ KS,         KS,     0x16, "6"      },
364 	{ KS,         KS,     0x1a, "7"      },
365 	{ KS,         KS,     0x1c, "8"      },
366 	{ KS,         KS,     0x19, "9"      },
367 	{ KS,         KS,     0x1d, "0"      },
368 	{ KS,         KS,     0x1b, "-"      },
369 	{ KS,         KS,     0x18, "="      },
370 	{ KS * 2,     KS,     0x33, "delete" },
371 	{ KS / 2,     KS,     0x00, NULL     },
372 	{ KS,         KS,     0x72, "ins"    },
373 	{ KS,         KS,     0x73, "hom"    },
374 	{ KS,         KS,     0x74, "pgu"    },
375 	{ KS / 2,     KS,     0x00, NULL     },
376 	{ KS,         KS,     0x47, "clr"    },
377 	{ KS,         KS,     0x51, "="      },
378 	{ KS,         KS,     0x4b, "/"      },
379 	{ KS,         KS,     0x43, "*"      },
380 	{ 0,          0,      0x00, NULL     },
381 
382 	{ KS * 3 / 2, KS,     0x30, "tab"    },
383 	{ KS,         KS,     0x0c, "Q"      },
384 	{ KS,         KS,     0x0d, "W"      },
385 	{ KS,         KS,     0x0e, "E"      },
386 	{ KS,         KS,     0x0f, "R"      },
387 	{ KS,         KS,     0x11, "T"      },
388 	{ KS,         KS,     0x10, "Y"      },
389 	{ KS,         KS,     0x20, "U"      },
390 	{ KS,         KS,     0x22, "I"      },
391 	{ KS,         KS,     0x1f, "O"      },
392 	{ KS,         KS,     0x23, "P"      },
393 	{ KS,         KS,     0x21, "["      },
394 	{ KS,         KS,     0x1e, "]"      },
395 	{ KS * 3 / 2, KS,     0x2a, "\\"     },
396 	{ KS / 2,     KS,     0x00, NULL     },
397 	{ KS,         KS,     0x75, "del"    },
398 	{ KS,         KS,     0x77, "end"    },
399 	{ KS,         KS,     0x79, "pgd"    },
400 	{ KS / 2,     KS,     0x00, NULL     },
401 	{ KS,         KS,     0x59, "7"      },
402 	{ KS,         KS,     0x5b, "8"      },
403 	{ KS,         KS,     0x5c, "9"      },
404 	{ KS,         KS,     0x4e, "-"      },
405 	{ 0,          0,      0x00, NULL     },
406 
407 	{ KS * 2,     KS,     0x39, "caps"   },
408 	{ KS,         KS,     0x00, "A"      },
409 	{ KS,         KS,     0x01, "S"      },
410 	{ KS,         KS,     0x02, "D"      },
411 	{ KS,         KS,     0x03, "F"      },
412 	{ KS,         KS,     0x05, "G"      },
413 	{ KS,         KS,     0x04, "H"      },
414 	{ KS,         KS,     0x26, "J"      },
415 	{ KS,         KS,     0x28, "K"      },
416 	{ KS,         KS,     0x25, "L"      },
417 	{ KS,         KS,     0x29, ";"      },
418 	{ KS,         KS,     0x27, "\xd3"   },
419 	{ KS * 2,     KS,     0x24, "return" },
420 	{ KS * 4,     KS,     0x00, NULL     },
421 	{ KS,         KS,     0x56, "4"      },
422 	{ KS,         KS,     0x57, "5"      },
423 	{ KS,         KS,     0x58, "6"      },
424 	{ KS,         KS,     0x45, "+"      },
425 	{ 0,          0,      0x00, NULL     },
426 
427 	{ KS * 5 / 2, KS,     0x38, "shift"  },
428 	{ KS,         KS,     0x06, "Z"      },
429 	{ KS,         KS,     0x07, "X"      },
430 	{ KS,         KS,     0x08, "C"      },
431 	{ KS,         KS,     0x09, "V"      },
432 	{ KS,         KS,     0x0b, "B"      },
433 	{ KS,         KS,     0x2d, "N"      },
434 	{ KS,         KS,     0x2e, "M"      },
435 	{ KS,         KS,     0x2b, ","      },
436 	{ KS,         KS,     0x2f, "."      },
437 	{ KS,         KS,     0x2c, "/"      },
438 	{ KS * 5 / 2, KS,     0x38, "shift"  },
439 	{ KS * 3 / 2, KS,     0x00, NULL     },
440 	{ KS,         KS,     0x7e, "up"     },
441 	{ KS * 3 / 2, KS,     0x00, NULL     },
442 	{ KS,         KS,     0x53, "1"      },
443 	{ KS,         KS,     0x54, "2"      },
444 	{ KS,         KS,     0x55, "3"      },
445 	{ KS,         KS * 2, 0x4c, "ent"    },
446 	{ 0,          0,      0x00, NULL     },
447 
448 	{ KS * 3 / 2, KS,     0x3b, "ctrl"   },
449 	{ KS * 3 / 2, KS,     0x3a, "opt"    },
450 	{ KS * 3 / 2, KS,     0x37, "cmd"    },
451 	{ KS * 6,     KS,     0x31, "   "    },
452 	{ KS * 3 / 2, KS,     0x37, "cmd"    },
453 	{ KS * 3 / 2, KS,     0x3a, "opt"    },
454 	{ KS * 3 / 2, KS,     0x3b, "ctrl"   },
455 	{ KS / 2,     KS,     0x00, NULL     },
456 	{ KS,         KS,     0x7b, "lt"     },
457 	{ KS,         KS,     0x7d, "dn"     },
458 	{ KS,         KS,     0x7c, "rt"     },
459 	{ KS / 2,     KS,     0x00, NULL     },
460 	{ KS * 2,     KS,     0x52, "0"      },
461 	{ KS,         KS,     0x41, "."      },
462 	{ 0,          0,      0x00, NULL     }
463 };
464 
465 static void CreateIconTableImage (void);
466 static void ReleaseIconTableImage (void);
467 static void CreateKeyLayoutImage (void);
468 static void ReleaseKeyLayoutImage (void);
469 static void CreateIconPlaceImage (void);
470 static void UpdateIconPlaceImage (void);
471 static void ReleaseIconPlaceImage (void);
472 static void DrawPlacedIcon (CGContextRef, int);
473 static void DrawDraggedIcon (CGContextRef, int, CGPoint *);
474 static Boolean KeyCodeInUse (int);
475 static int FindHitKey (HIPoint, CGRect *, CGPoint *);
476 static pascal OSStatus KeyWindowEventHandler (EventHandlerCallRef, EventRef, void *);
477 static pascal OSStatus KeyLegendEventHandler (EventHandlerCallRef, EventRef, void *);
478 static pascal OSStatus KeyLayoutEventHandler (EventHandlerCallRef, EventRef, void *);
479 
480 #define	kCustomLayoutViewClassID	CFSTR("com.snes9x.macos.snes9x.keylayout")
481 
482 
ConfigureKeyboard(void)483 void ConfigureKeyboard (void)
484 {
485 	OSStatus	err;
486 	IBNibRef	nibRef;
487 
488 	err = CreateNibReference(kMacS9XCFString, &nibRef);
489 	if (err == noErr)
490 	{
491 		WindowRef	tWindowRef;
492 
493 		err = CreateWindowFromNib(nibRef, CFSTR("Keyboard"), &tWindowRef);
494 		if (err == noErr)
495 		{
496 			EventHandlerRef	wref, iref1, iref2;
497 			EventHandlerUPP	wUPP, iUPP;
498 			EventTypeSpec	wEvents[] = { { kEventClassWindow,   kEventWindowClose         },
499 										  { kEventClassCommand,  kEventCommandProcess      },
500 										  { kEventClassCommand,  kEventCommandUpdateStatus } },
501 							cEvents[] = { { kEventClassHIObject, kEventHIObjectConstruct   },
502 										  { kEventClassHIObject, kEventHIObjectDestruct    },
503 										  { kEventClassHIObject, kEventHIObjectInitialize  },
504 										  { kEventClassControl,  kEventControlDraw         },
505 										  { kEventClassControl,  kEventControlHitTest      },
506 										  { kEventClassControl,  kEventControlTrack        } },
507 							iEvents[] = { { kEventClassControl,  kEventControlDraw         } };
508 			HIObjectRef		hiObject;
509 			HIViewRef		contentView, image1, image2;
510 			HIViewID		cid;
511 			HIRect			frame;
512 			Rect			winBounds;
513 
514 			UpdateIconPlaceImage();
515 
516 			keyInDrag = false;
517 			dragKey = -1;
518 			dragKeyOfs = CGPointMake(0.0f, 0.0f);
519 			dragKeyRect = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f);
520 			mousePos = CGPointMake(0.0f, 0.0f);
521 
522 			err = noErr;
523 			if (theClass == NULL)
524 				err = HIObjectRegisterSubclass(kCustomLayoutViewClassID, kHIViewClassID, 0, KeyLayoutEventHandler, GetEventTypeCount(cEvents), cEvents, NULL, &theClass);
525 
526 			if (err == noErr)
527 			{
528 				err = HIObjectCreate(kCustomLayoutViewClassID, NULL, &hiObject);
529 				if (err == noErr)
530 				{
531 					GetWindowBounds(tWindowRef, kWindowContentRgn, &winBounds);
532 
533 					frame.origin.x = 2.0f;
534 					frame.origin.y = 2.0f;
535 					frame.size.width  = (float) (winBounds.right - winBounds.left) - 4.0f;
536 					frame.size.height = (float) kKeyLayoutHeight + 36.0f;
537 
538 					ofsx = (float) (((int) frame.size.width  - kKeyLayoutWidth ) >> 1) + 1.0f;
539 					ofsy = (float) (((int) frame.size.height - kKeyLayoutHeight) >> 1) + 1.0f;
540 
541 					customView = (HIViewRef) hiObject;
542 
543 					HIViewFindByID(HIViewGetRoot(tWindowRef), kHIViewWindowContentID, &contentView);
544 					HIViewAddSubview(contentView, customView);
545 					HIViewSetFrame(customView, &frame);
546 					HIViewSetVisible(customView, true);
547 
548 					cid.signature = 'Lgnd';
549 					cid.id = 0;
550 					HIViewFindByID(contentView, cid, &image1);
551 					cid.id = 1;
552 					HIViewFindByID(contentView, cid, &image2);
553 					iUPP = NewEventHandlerUPP(KeyLegendEventHandler);
554 					err = InstallControlEventHandler(image1, iUPP, GetEventTypeCount(iEvents), iEvents, (void *) image1, &iref1);
555 					err = InstallControlEventHandler(image2, iUPP, GetEventTypeCount(iEvents), iEvents, (void *) image2, &iref2);
556 
557 					wUPP = NewEventHandlerUPP(KeyWindowEventHandler);
558 					err = InstallWindowEventHandler(tWindowRef, wUPP, GetEventTypeCount(wEvents), wEvents, (void *) tWindowRef, &wref);
559 
560 					MoveWindowPosition(tWindowRef, kWindowKeyConfig, false);
561 					ShowWindow(tWindowRef);
562 					err = RunAppModalLoopForWindow(tWindowRef);
563 					HideWindow(tWindowRef);
564 					SaveWindowPosition(tWindowRef, kWindowKeyConfig);
565 
566 					err = RemoveEventHandler(iref2);
567 					err = RemoveEventHandler(iref1);
568 					DisposeEventHandlerUPP(iUPP);
569 
570 					err = RemoveEventHandler(wref);
571 					DisposeEventHandlerUPP(wUPP);
572 				}
573 			}
574 
575 			CFRelease(tWindowRef);
576 		}
577 
578 		DisposeNibReference(nibRef);
579 	}
580 }
581 
CreateIconTableImage(void)582 static void CreateIconTableImage (void)
583 {
584 	CGContextRef		ctx;
585 	CGDataProviderRef	prov;
586 	CGColorSpaceRef		color;
587 	CGRect				rct;
588 
589 	rct = CGRectMake(0.0f, 0.0f, (float) kIconSize, (float) kIconSize);
590 
591 	iconTableCGWld = (Ptr) malloc(kIconSize * kKeys * (kIconSize + 1) * 4);
592 	if (!iconTableCGWld)
593 		QuitWithFatalError(0, "keyboard 08");
594 
595 	ctx = NULL;
596 
597 	color = CGColorSpaceCreateDeviceRGB();
598 	if (color)
599 	{
600 		ctx = CGBitmapContextCreate(iconTableCGWld, kIconSize * kKeys, kIconSize, 8, kIconSize * kKeys * 4, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrderDefault : 0));
601 		CGColorSpaceRelease(color);
602 	}
603 
604 	if (!ctx)
605 		QuitWithFatalError(0, "keyboard 09");
606 
607 	CGContextTranslateCTM(ctx, 0.0f, (float) kIconSize);
608 	CGContextScaleCTM(ctx, 1.0f, -1.0f);
609 
610 	// SNES pads
611 	for (int i = macPadIconIndex; i < macPadIconIndex + 12 * 2; i++)
612 	{
613 		if (systemVersion >= 0x1040)
614 			CGContextDrawImage(ctx, rct, macIconImage[i]);
615 	#ifdef MAC_PANTHER_SUPPORT
616 		else
617 			PlotIconRefInContext(ctx, &rct, kAlignNone, kTransformNone, NULL, kPlotIconRefNormalFlags, macIconRef[i]);
618 	#endif
619 		rct = CGRectOffset(rct, kIconSize, 0);
620 	}
621 
622 	// Function buttons
623 	for (int i = macFunctionIconIndex; i < macFunctionIconIndex + 17; i++)
624 	{
625 		if (systemVersion >= 0x1040)
626 			CGContextDrawImage(ctx, rct, macIconImage[i]);
627 	#ifdef MAC_PANTHER_SUPPORT
628 		else
629 			PlotIconRefInContext(ctx, &rct, kAlignNone, kTransformNone, NULL, kPlotIconRefNormalFlags, macIconRef[i]);
630 	#endif
631 		rct = CGRectOffset(rct, kIconSize, 0);
632 	}
633 
634 	CGContextRelease(ctx);
635 
636 	iconTableImage = NULL;
637 
638 	prov = CGDataProviderCreateWithData(NULL, iconTableCGWld, kIconSize * kKeys * kIconSize * 4, NULL);
639 	if (prov)
640 	{
641 		color = CGColorSpaceCreateDeviceRGB();
642 		if (color)
643 		{
644 			iconTableImage = CGImageCreate(kIconSize * kKeys, kIconSize, 8, 32, kIconSize * kKeys * 4, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrderDefault : 0), prov, NULL, 0, kCGRenderingIntentDefault);
645 			CGColorSpaceRelease(color);
646 		}
647 
648 		CGDataProviderRelease(prov);
649 	}
650 
651 	if (!iconTableImage)
652 		QuitWithFatalError(0, "keyboard 10");
653 }
654 
ReleaseIconTableImage(void)655 static void ReleaseIconTableImage (void)
656 {
657 	CGImageRelease(iconTableImage);
658 	free(iconTableCGWld);
659 }
660 
CreateKeyLayoutImage(void)661 static void CreateKeyLayoutImage (void)
662 {
663 	CGContextRef		ctx;
664 	CGDataProviderRef	prov;
665 	CGColorSpaceRef		color;
666 	CGAffineTransform	flipMatrix;
667 	CGRect				rct, r;
668 	int					index, scancode;
669 
670 	rct = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f);
671 	for (int i = 0; i < 0x80; i++)
672 		keyRect[i][0] = keyRect[i][1] = rct;
673 
674 	keyLayoutWorld = (Ptr) malloc(kKeyLayoutWidth * (kKeyLayoutHeight + 1) * 4);
675 	if (!keyLayoutWorld)
676 		QuitWithFatalError(0, "keyboard 02");
677 
678 	ctx = NULL;
679 
680 	color = CGColorSpaceCreateDeviceRGB();
681 	if (color)
682 	{
683 		ctx = CGBitmapContextCreate(keyLayoutWorld, kKeyLayoutWidth, kKeyLayoutHeight, 8, kKeyLayoutWidth * 4, color, kCGImageAlphaPremultipliedFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrderDefault : 0));
684 		CGColorSpaceRelease(color);
685 	}
686 
687 	if (!ctx)
688 		QuitWithFatalError(0, "keyboard 04");
689 
690 	CGContextSetLineJoin(ctx, kCGLineJoinMiter);
691 
692 	flipMatrix = CGAffineTransformMake(1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
693 	CGContextSelectFont(ctx, "Helvetica", 10.0f, kCGEncodingMacRoman);
694 	CGContextSetTextDrawingMode(ctx, kCGTextFill);
695 	CGContextSetTextMatrix(ctx, flipMatrix);
696 
697 	rct = CGRectMake(0.0f, 0.0f, (float) kKeyLayoutWidth, (float) kKeyLayoutHeight);
698 	CGContextClearRect(ctx, rct);
699 
700 	index = 0;
701 	rct = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f);
702 
703 	for (int i = 0; i < 7; i++)
704 	{
705 		while (keys[index].keyWidth)
706 		{
707 			rct.size.width = (float) keys[index].keyWidth;
708 
709 			if (keys[index].keyLabel)
710 			{
711 				rct.size.height = (float) keys[index].keyHeight;
712 				scancode = keys[index].scancode;
713 
714 				if (keyRect[scancode][0].size.height < 1.0)
715 					keyRect[scancode][0] = rct;
716 				else
717 					keyRect[scancode][1] = rct;
718 
719 				r = rct;
720 
721 				r.origin.x += 1.0f;
722 				r.origin.y += 1.0f;
723 				r.size.width  -= 1.0f;
724 				r.size.height -= 1.0f;
725 
726 				CGContextSetRGBStrokeColor(ctx, 0.1f, 0.1f, 0.1f, 1.0f);
727 				CGContextStrokeRect(ctx, r);
728 
729 				float	h, p;
730 
731 				CGRectInset(r, 2.0f, 2.0f);
732 				h = r.size.height;
733 				for (float f = h; f >= 1.0f; f -= 1.0f)
734 				{
735 					p = (155.0f + (h - f)) / 180.0f;
736 					CGContextSetRGBFillColor(ctx, p, p, p, 1.0f);
737 					CGContextFillRect(ctx, r);
738 					r.size.height -= 1.0f;
739 				}
740 
741 				CGContextSetRGBFillColor(ctx, 0.1f, 0.1f, 0.1f, 1.0f);
742 				CGContextShowTextAtPoint(ctx, rct.origin.x + 3.0f, rct.origin.y + rct.size.height - 3.0f, keys[index].keyLabel, strlen(keys[index].keyLabel));
743 			}
744 
745 			rct.origin.x += rct.size.width;
746 			index++;
747 		}
748 
749 		rct.origin.y += kKeySize;
750 		rct.origin.x  = rct.size.width = 0;
751 		index++;
752 	}
753 
754 	CGContextRelease(ctx);
755 
756 	keyLayoutImage = NULL;
757 
758 	prov = CGDataProviderCreateWithData(NULL, keyLayoutWorld, kKeyLayoutWidth * kKeyLayoutHeight * 4, NULL);
759 	if (prov)
760 	{
761 		color = CGColorSpaceCreateDeviceRGB();
762 		if (color)
763 		{
764 			keyLayoutImage = CGImageCreate(kKeyLayoutWidth, kKeyLayoutHeight, 8, 32, kKeyLayoutWidth * 4, color, kCGImageAlphaPremultipliedFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrderDefault : 0), prov, NULL, 0, kCGRenderingIntentDefault);
765 			CGColorSpaceRelease(color);
766 		}
767 
768 		CGDataProviderRelease(prov);
769 	}
770 
771 	if (!keyLayoutImage)
772 		QuitWithFatalError(0, "keyboard 05");
773 }
774 
ReleaseKeyLayoutImage(void)775 static void ReleaseKeyLayoutImage (void)
776 {
777 	CGImageRelease(keyLayoutImage);
778 	free(keyLayoutWorld);
779 }
780 
CreateIconPlaceImage(void)781 static void CreateIconPlaceImage (void)
782 {
783 	iconPlaceWorld = (Ptr) malloc(kKeyLayoutWidth * (kKeyLayoutHeight + 1) * 4);
784 	if (!iconPlaceWorld)
785 		QuitWithFatalError(0, "keyboard 06");
786 
787 	iconPlaceImage = NULL;
788 
789 	UpdateIconPlaceImage();
790 }
791 
UpdateIconPlaceImage(void)792 static void UpdateIconPlaceImage (void)
793 {
794 	CGContextRef		ctx;
795 	CGDataProviderRef	prov;
796 	CGColorSpaceRef		color;
797 	CGRect				rct;
798 
799 	if (iconPlaceImage)
800 		CGImageRelease(iconPlaceImage);
801 
802 	iconPlaceImage = NULL;
803 
804 	color = CGColorSpaceCreateDeviceRGB();
805 	if (color)
806 	{
807 		ctx = CGBitmapContextCreate(iconPlaceWorld, kKeyLayoutWidth, kKeyLayoutHeight, 8, kKeyLayoutWidth * 4, color, kCGImageAlphaPremultipliedFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrderDefault : 0));
808 		if (ctx)
809 		{
810 			rct = CGRectMake(0.0f, 0.0f, (float) kKeyLayoutWidth, (float) kKeyLayoutHeight);
811 			CGContextDrawImage(ctx, rct, keyLayoutImage);
812 
813 			for (int i = 0; i < kKeys; i++)
814 				DrawPlacedIcon(ctx, i);
815 
816 			CGContextRelease(ctx);
817 		}
818 
819 		prov = CGDataProviderCreateWithData(NULL, iconPlaceWorld, kKeyLayoutWidth * kKeyLayoutHeight * 4, NULL);
820 		if (prov)
821 		{
822 			iconPlaceImage = CGImageCreate(kKeyLayoutWidth, kKeyLayoutHeight, 8, 32, kKeyLayoutWidth * 4, color, kCGImageAlphaPremultipliedFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrderDefault : 0), prov, NULL, 0, kCGRenderingIntentDefault);
823 			CGDataProviderRelease(prov);
824 		}
825 
826 		CGColorSpaceRelease(color);
827 	}
828 
829 	if (!iconPlaceImage)
830 		QuitWithFatalError(0, "keyboard 07");
831 }
832 
ReleaseIconPlaceImage(void)833 static void ReleaseIconPlaceImage (void)
834 {
835 	CGImageRelease(iconPlaceImage);
836 	free(iconPlaceWorld);
837 }
838 
InitKeyboard(void)839 void InitKeyboard (void)
840 {
841 	theClass = NULL;
842 
843 	memcpy(defaultKeys, keyCode, sizeof(keyCode));
844 
845 	CreateIconTableImage();
846 	CreateKeyLayoutImage();
847 	CreateIconPlaceImage();
848 }
849 
DeinitKeyboard(void)850 void DeinitKeyboard (void)
851 {
852 	ReleaseIconPlaceImage();
853 	ReleaseKeyLayoutImage();
854 	ReleaseIconTableImage();
855 }
856 
DrawPlacedIcon(CGContextRef ctx,int which)857 static void DrawPlacedIcon (CGContextRef ctx, int which)
858 {
859 	CGRect	keyBounds, srcRect, dstRect;
860 
861 	CGContextSaveGState(ctx);
862 
863 	CGContextSetRGBFillColor(ctx, 0.40f, 0.40f, 0.65f, 0.5f);
864 
865 	for (int each = 0; each <= 1; each++)
866 	{
867 		keyBounds = keyRect[keyCode[which]][each];
868 
869 		if (keyBounds.size.height > 1.0f)
870 		{
871 			keyBounds.origin.x += 1.0f;
872 			keyBounds.origin.y += 1.0f;
873 			keyBounds.size.width  -= 1.0f;
874 			keyBounds.size.height -= 1.0f;
875 
876 			CGContextFillRect(ctx, keyBounds);
877 
878 			keyBounds.origin.x -= 1.0f;
879 			keyBounds.origin.y -= 1.0f;
880 			keyBounds.size.width  += 1.0f;
881 			keyBounds.size.height += 1.0f;
882 
883 			srcRect.origin.x = (float) (which * kIconSize);
884 			srcRect.origin.y = 0.0f;
885 			srcRect.size.width  = (float) kIconSize;
886 			srcRect.size.height = (float) kIconSize;
887 
888 			dstRect.origin.x = keyBounds.origin.x + (keyBounds.size.width  - kIconSize) / 2.0f;
889 			dstRect.origin.y = keyBounds.origin.y + (keyBounds.size.height - kIconSize) / 2.0f;
890 			dstRect.size.width  = (float) kIconSize;
891 			dstRect.size.height = (float) kIconSize;
892 
893 			DrawSubCGImage(ctx, iconTableImage, srcRect, dstRect);
894 		}
895 	}
896 
897 	CGContextRestoreGState(ctx);
898 }
899 
DrawDraggedIcon(CGContextRef ctx,int which,CGPoint * offset)900 static void DrawDraggedIcon (CGContextRef ctx, int which, CGPoint *offset)
901 {
902 	CGRect	srcRect, dstRect;
903 
904 	CGContextSaveGState(ctx);
905 
906 	srcRect.origin.x = (float) (which * kIconSize);
907 	srcRect.origin.y = 0.0f;
908 	srcRect.size.width  = (float) kIconSize;
909 	srcRect.size.height = (float) kIconSize;
910 
911 	dstRect.origin.x = mousePos.x + offset->x;
912 	dstRect.origin.y = mousePos.y + offset->y;
913 	dstRect.size.width  = (float) kIconSize;
914 	dstRect.size.height = (float) kIconSize;
915 
916 	CGContextSetAlpha(ctx, 0.5f);
917 	DrawSubCGImage(ctx, iconTableImage, srcRect, dstRect);
918 
919 	CGContextRestoreGState(ctx);
920 }
921 
KeyCodeInUse(int code)922 static Boolean KeyCodeInUse (int code)
923 {
924 	for (int i = 0; i < kKeys; i++)
925 		if (keyCode[i] == code)
926 			return (true);
927 
928 	return (false);
929 }
930 
FindHitKey(HIPoint where,CGRect * keybounds,CGPoint * offset)931 static int FindHitKey (HIPoint where, CGRect *keybounds, CGPoint *offset)
932 {
933 	int	hit;
934 
935 	hit = -1;
936 	*offset = CGPointMake(0.0f, 0.0f);
937 	*keybounds = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f);
938 
939 	for (int which = 0; which < kKeys; which++)
940 	{
941 		for (int each = 0; each <= 1; each++)
942 		{
943 			if (CGRectContainsPoint(keyRect[keyCode[which]][each], where))
944 			{
945 				hit = which;
946 
947 				*keybounds = keyRect[keyCode[which]][each];
948 				offset->x = keybounds->origin.x + (keybounds->size.width  - kIconSize) / 2.0f - where.x + 18.0f;
949 				offset->y = keybounds->origin.y + (keybounds->size.height - kIconSize) / 2.0f - where.y + 18.0f;
950 			}
951 		}
952 	}
953 
954 	return (hit);
955 }
956 
KeyWindowEventHandler(EventHandlerCallRef inHandlerRef,EventRef inEvent,void * inUserData)957 static pascal OSStatus KeyWindowEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData)
958 {
959 	OSStatus	err, result = eventNotHandledErr;
960 	WindowRef	tWindowRef = (WindowRef) inUserData;
961 
962 	switch (GetEventClass(inEvent))
963 	{
964 		case kEventClassWindow:
965 			switch (GetEventKind(inEvent))
966 			{
967 				case kEventWindowClose:
968 					QuitAppModalLoopForWindow(tWindowRef);
969 					result = noErr;
970 			}
971 
972 			break;
973 
974 		case kEventClassCommand:
975 			switch (GetEventKind(inEvent))
976 			{
977 				HICommand	tHICommand;
978 
979 				case kEventCommandUpdateStatus:
980 					err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand);
981 					if (err == noErr && tHICommand.commandID == 'clos')
982 					{
983 						UpdateMenuCommandStatus(true);
984 						result = noErr;
985 					}
986 
987 					break;
988 
989 				case kEventCommandProcess:
990 					err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand);
991 					if (err == noErr)
992 					{
993 						if (tHICommand.commandID == 'DFLT')
994 						{
995 							memcpy(keyCode, defaultKeys, sizeof(keyCode));
996 							UpdateIconPlaceImage();
997 							HIViewSetNeedsDisplay(customView, true);
998 							result = noErr;
999 						}
1000 					}
1001 			}
1002 	}
1003 
1004 	return (result);
1005 }
1006 
KeyLegendEventHandler(EventHandlerCallRef inHandlerRef,EventRef inEvent,void * inUserData)1007 static pascal OSStatus KeyLegendEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData)
1008 {
1009     OSStatus	err, result = eventNotHandledErr;
1010 	HIViewRef	view = (HIViewRef) inUserData;
1011 
1012 	switch (GetEventClass(inEvent))
1013 	{
1014 		case kEventClassControl:
1015 			switch (GetEventKind(inEvent))
1016 			{
1017 				case kEventControlDraw:
1018 					CGContextRef	ctx;
1019 
1020 					err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(CGContextRef), NULL, &ctx);
1021 					if (err == noErr)
1022 					{
1023 						HIViewID	cid;
1024 						HIRect		bounds;
1025 
1026 						GetControlID(view, &cid);
1027 						HIViewGetBounds(view, &bounds);
1028 						CGContextTranslateCTM(ctx, 0, bounds.size.height);
1029 						CGContextScaleCTM(ctx, 1.0f, -1.0f);
1030 						CGContextDrawImage(ctx, CGRectMake(0, 0, kIconSize, kIconSize), macIconImage[macLegendIconIndex + cid.id]);
1031 
1032 						result = noErr;
1033 					}
1034 			}
1035 	}
1036 
1037 	return (result);
1038 }
1039 
KeyLayoutEventHandler(EventHandlerCallRef inHandlerRef,EventRef inEvent,void * inUserData)1040 static pascal OSStatus KeyLayoutEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData)
1041 {
1042 	OSStatus		err, result = eventNotHandledErr;
1043 	CustomViewData	*data = (CustomViewData *) inUserData;
1044 
1045 	switch (GetEventClass(inEvent))
1046 	{
1047 		case kEventClassHIObject:
1048 			switch (GetEventKind(inEvent))
1049 			{
1050 				case kEventHIObjectConstruct:
1051 					data = (CustomViewData *) calloc(1, sizeof(CustomViewData));
1052 					if (data)
1053 					{
1054 						HIViewRef	epView;
1055 
1056 						err = GetEventParameter(inEvent, kEventParamHIObjectInstance, typeHIObjectRef, NULL, sizeof(epView), NULL, &epView);
1057 						if (err == noErr)
1058 						{
1059 							data->view = epView;
1060 							result = SetEventParameter(inEvent, kEventParamHIObjectInstance, typeVoidPtr, sizeof(data), &data);
1061 						}
1062 					}
1063 
1064 					break;
1065 
1066 				case kEventHIObjectDestruct:
1067 					if (data)
1068 						free(data);
1069 
1070 					result = noErr;
1071 					break;
1072 
1073 				case kEventHIObjectInitialize:
1074 					result = CallNextEventHandler(inHandlerRef, inEvent);
1075 			}
1076 
1077 			break;
1078 
1079 		case kEventClassControl:
1080 			switch (GetEventKind(inEvent))
1081 			{
1082 				case kEventControlDraw:
1083 					CGContextRef	ctx;
1084 
1085 					err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(ctx), NULL, &ctx);
1086 					if (err == noErr)
1087 					{
1088 						HIRect	bounds, srcRect, dstRect;
1089 
1090 						HIViewGetBounds(customView, &bounds);
1091 						srcRect = CGRectMake(0, 0, kKeyLayoutWidth, kKeyLayoutHeight);
1092 
1093 						dstRect.origin.x = (float) (((int) bounds.size.width  - kKeyLayoutWidth ) >> 1);
1094 						dstRect.origin.y = (float) (((int) bounds.size.height - kKeyLayoutHeight) >> 1);
1095 						dstRect.size.width  = (float) kKeyLayoutWidth;
1096 						dstRect.size.height = (float) kKeyLayoutHeight;
1097 
1098 						DrawSubCGImage(ctx, iconPlaceImage, srcRect, dstRect);
1099 						if (keyInDrag && (dragKey != -1))
1100 							DrawDraggedIcon(ctx, dragKey, &dragKeyOfs);
1101 					}
1102 
1103 					result = noErr;
1104 					break;
1105 
1106 				case kEventControlHitTest:
1107 					ControlPartCode	part;
1108 
1109 					part = kControlButtonPart;
1110 					result = SetEventParameter(inEvent, kEventParamControlPart, typeControlPartCode, sizeof(part), &part);
1111 
1112 					break;
1113 
1114       			case kEventControlTrack:
1115                     MouseTrackingResult	trackResult;
1116 					WindowRef			window;
1117 					HIViewRef			contentView;
1118 					HIPoint				hipt;
1119 
1120  					dragKey = -1;
1121 					dragKeyOfs = CGPointMake(0.0f, 0.0f);
1122 					dragKeyRect = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f);
1123 					mousePos = CGPointMake(0.0f, 0.0f);
1124 					trackResult = kMouseTrackingMouseDown;
1125 
1126 					window = GetControlOwner(customView);
1127 					HIViewFindByID(HIViewGetRoot(window), kHIViewWindowContentID, &contentView);
1128 
1129 				#ifdef MAC_TIGER_PANTHER_SUPPORT
1130 					CGrafPtr	oldPort;
1131 					Point		qdpt;
1132 					Boolean		portChanged = false;
1133 
1134 					if (systemVersion < 0x1050)
1135 						portChanged = QDSwapPort(GetWindowPort(window), &oldPort);
1136 				#endif
1137 
1138 					err = GetEventParameter(inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(hipt), NULL, &hipt);
1139 					if (err == noErr)
1140 					{
1141 						hipt.x -= ofsx;
1142 						hipt.y -= ofsy;
1143 
1144 						dragKey = FindHitKey(hipt, &dragKeyRect, &dragKeyOfs);
1145 						if (dragKey != -1)
1146 						{
1147 							keyInDrag = true;
1148 
1149 							while (trackResult != kMouseTrackingMouseUp)
1150 							{
1151 								if (CGPointEqualToPoint(mousePos, hipt) == 0)
1152 								{
1153 									mousePos = hipt;
1154 									HIViewSetNeedsDisplay(customView, true);
1155 								}
1156 
1157 								if (systemVersion >= 0x1050)
1158 								{
1159 									err = HIViewTrackMouseLocation(customView, 0, kEventDurationForever, 0, NULL, &hipt, NULL, NULL, &trackResult);
1160 									hipt.x -= ofsx;
1161 									hipt.y -= ofsy;
1162 								}
1163 							#ifdef MAC_TIGER_PANTHER_SUPPORT
1164 								else
1165 								{
1166 									TrackMouseLocation(NULL, &qdpt, &trackResult);
1167 									hipt.x = qdpt.h - ofsx;
1168 									hipt.y = qdpt.v - ofsy;
1169 									HIViewConvertPoint(&hipt, contentView, customView);
1170 								}
1171 							#endif
1172 							}
1173 
1174 							keyInDrag = false;
1175 
1176 							for (int code = 0; code < 0x80; code++)
1177 							{
1178 								for (int each = 0; each <= 1; each++)
1179 								{
1180 									if (CGRectContainsPoint(keyRect[code][each], mousePos))
1181 									{
1182 										if (!KeyCodeInUse(code))
1183 										{
1184 											keyCode[dragKey] = code;
1185 											UpdateIconPlaceImage();
1186 										}
1187 									}
1188 								}
1189 							}
1190 
1191 							HIViewSetNeedsDisplay(customView, true);
1192 						}
1193 					}
1194 
1195 				#ifdef MAC_TIGER_PANTHER_SUPPORT
1196 					if (systemVersion < 0x1050)
1197 					{
1198 						if (portChanged)
1199 							QDSwapPort(oldPort, NULL);
1200 					}
1201 				#endif
1202 
1203 					result = noErr;
1204 			}
1205 	}
1206 
1207 	return (result);
1208 }
1209