Revision 5fafdf24 cocoa.m
b/cocoa.m | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* QEMU Cocoa display driver |
3 |
*
|
|
3 |
* |
|
4 | 4 |
* Copyright (c) 2005 Pierre d'Herbemont |
5 | 5 |
* many code/inspiration from SDL 1.2 code (LGPL) |
6 |
*
|
|
6 |
* |
|
7 | 7 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
8 | 8 |
* of this software and associated documentation files (the "Software"), to deal |
9 | 9 |
* in the Software without restriction, including without limitation the rights |
... | ... | |
23 | 23 |
* THE SOFTWARE. |
24 | 24 |
*/ |
25 | 25 |
/* |
26 |
Todo : x miniaturize window
|
|
26 |
Todo : x miniaturize window |
|
27 | 27 |
x center the window |
28 | 28 |
- save window position |
29 | 29 |
- handle keyboard event |
... | ... | |
84 | 84 |
MacSetRectRgn (temp, x, y, |
85 | 85 |
x + w, y + h); |
86 | 86 |
MacUnionRgn (dirty, temp, dirty); |
87 |
|
|
87 |
|
|
88 | 88 |
/* Flush the dirty region */ |
89 | 89 |
QDFlushPortBuffer ( [ qd_view qdPort ], dirty ); |
90 | 90 |
DisposeRgn (dirty); |
... | ... | |
102 | 102 |
static void *screen_pixels; |
103 | 103 |
static int screen_pitch; |
104 | 104 |
NSRect contentRect; |
105 |
|
|
105 |
|
|
106 | 106 |
//printf("resizing to %d %d\n", w, h); |
107 |
|
|
107 |
|
|
108 | 108 |
contentRect = NSMakeRect (0, 0, w, h); |
109 | 109 |
if(window) |
110 | 110 |
{ |
... | ... | |
119 | 119 |
fprintf(stderr, "(cocoa) can't create window\n"); |
120 | 120 |
exit(1); |
121 | 121 |
} |
122 |
|
|
122 |
|
|
123 | 123 |
if(qd_view) |
124 | 124 |
[qd_view release]; |
125 |
|
|
125 |
|
|
126 | 126 |
qd_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ]; |
127 |
|
|
127 |
|
|
128 | 128 |
if(!qd_view) |
129 | 129 |
{ |
130 | 130 |
fprintf(stderr, "(cocoa) can't create qd_view\n"); |
131 | 131 |
exit(1); |
132 | 132 |
} |
133 |
|
|
133 |
|
|
134 | 134 |
[ window setAcceptsMouseMovedEvents:YES ]; |
135 | 135 |
[ window setTitle:@"Qemu" ]; |
136 | 136 |
[ window setReleasedWhenClosed:NO ]; |
137 |
|
|
137 |
|
|
138 | 138 |
/* Set screen to black */ |
139 | 139 |
[ window setBackgroundColor: [NSColor blackColor] ]; |
140 |
|
|
140 |
|
|
141 | 141 |
/* set window position */ |
142 | 142 |
[ window center ]; |
143 |
|
|
143 |
|
|
144 | 144 |
[ qd_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; |
145 | 145 |
[ [ window contentView ] addSubview:qd_view ]; |
146 | 146 |
[ qd_view release ]; |
147 | 147 |
[ window makeKeyAndOrderFront:nil ]; |
148 |
|
|
148 |
|
|
149 | 149 |
/* Careful here, the window seems to have to be onscreen to do that */ |
150 | 150 |
LockPortBits ( [ qd_view qdPort ] ); |
151 | 151 |
screen_pixels = GetPixBaseAddr ( GetPortPixMap ( [ qd_view qdPort ] ) ); |
152 | 152 |
screen_pitch = GetPixRowBytes ( GetPortPixMap ( [ qd_view qdPort ] ) ); |
153 | 153 |
UnlockPortBits ( [ qd_view qdPort ] ); |
154 |
{
|
|
155 |
int vOffset = [ window frame ].size.height -
|
|
154 |
{ |
|
155 |
int vOffset = [ window frame ].size.height - |
|
156 | 156 |
[ qd_view frame ].size.height - [ qd_view frame ].origin.y; |
157 |
|
|
157 |
|
|
158 | 158 |
int hOffset = [ qd_view frame ].origin.x; |
159 |
|
|
159 |
|
|
160 | 160 |
screen_pixels += (vOffset * screen_pitch) + hOffset * (device_bpp/8); |
161 | 161 |
} |
162 | 162 |
ds->data = screen_pixels; |
... | ... | |
310 | 310 |
208,// 125 0x7D 0xd0 E0,50 D ARROW QZ_DOWN |
311 | 311 |
200,// 126 0x7E 0xc8 E0,48 U ARROW QZ_UP |
312 | 312 |
/* completed according to http://www.libsdl.org/cgi/cvsweb.cgi/SDL12/src/video/quartz/SDL_QuartzKeys.h?rev=1.6&content-type=text/x-cvsweb-markup */ |
313 |
|
|
313 |
|
|
314 | 314 |
/* Aditional 104 Key XP-Keyboard Scancodes from http://www.computer-engineering.org/ps2keyboard/scancodes1.html */ |
315 | 315 |
/* |
316 |
219 // 0xdb e0,5b L GUI
|
|
317 |
220 // 0xdc e0,5c R GUI
|
|
318 |
221 // 0xdd e0,5d APPS
|
|
319 |
// E0,2A,E0,37 PRNT SCRN
|
|
320 |
// E1,1D,45,E1,9D,C5 PAUSE
|
|
321 |
83 // 0x53 0x53 KP .
|
|
322 |
// ACPI Scan Codes
|
|
323 |
222 // 0xde E0, 5E Power
|
|
324 |
223 // 0xdf E0, 5F Sleep
|
|
325 |
227 // 0xe3 E0, 63 Wake
|
|
326 |
// Windows Multimedia Scan Codes
|
|
327 |
153 // 0x99 E0, 19 Next Track
|
|
328 |
144 // 0x90 E0, 10 Previous Track
|
|
329 |
164 // 0xa4 E0, 24 Stop
|
|
330 |
162 // 0xa2 E0, 22 Play/Pause
|
|
331 |
160 // 0xa0 E0, 20 Mute
|
|
332 |
176 // 0xb0 E0, 30 Volume Up
|
|
333 |
174 // 0xae E0, 2E Volume Down
|
|
334 |
237 // 0xed E0, 6D Media Select
|
|
335 |
236 // 0xec E0, 6C E-Mail
|
|
336 |
161 // 0xa1 E0, 21 Calculator
|
|
337 |
235 // 0xeb E0, 6B My Computer
|
|
338 |
229 // 0xe5 E0, 65 WWW Search
|
|
339 |
178 // 0xb2 E0, 32 WWW Home
|
|
340 |
234 // 0xea E0, 6A WWW Back
|
|
341 |
233 // 0xe9 E0, 69 WWW Forward
|
|
342 |
232 // 0xe8 E0, 68 WWW Stop
|
|
343 |
231 // 0xe7 E0, 67 WWW Refresh
|
|
344 |
230 // 0xe6 E0, 66 WWW Favorites
|
|
316 |
219 // 0xdb e0,5b L GUI |
|
317 |
220 // 0xdc e0,5c R GUI |
|
318 |
221 // 0xdd e0,5d APPS |
|
319 |
// E0,2A,E0,37 PRNT SCRN |
|
320 |
// E1,1D,45,E1,9D,C5 PAUSE |
|
321 |
83 // 0x53 0x53 KP . |
|
322 |
// ACPI Scan Codes |
|
323 |
222 // 0xde E0, 5E Power |
|
324 |
223 // 0xdf E0, 5F Sleep |
|
325 |
227 // 0xe3 E0, 63 Wake |
|
326 |
// Windows Multimedia Scan Codes |
|
327 |
153 // 0x99 E0, 19 Next Track |
|
328 |
144 // 0x90 E0, 10 Previous Track |
|
329 |
164 // 0xa4 E0, 24 Stop |
|
330 |
162 // 0xa2 E0, 22 Play/Pause |
|
331 |
160 // 0xa0 E0, 20 Mute |
|
332 |
176 // 0xb0 E0, 30 Volume Up |
|
333 |
174 // 0xae E0, 2E Volume Down |
|
334 |
237 // 0xed E0, 6D Media Select |
|
335 |
236 // 0xec E0, 6C E-Mail |
|
336 |
161 // 0xa1 E0, 21 Calculator |
|
337 |
235 // 0xeb E0, 6B My Computer |
|
338 |
229 // 0xe5 E0, 65 WWW Search |
|
339 |
178 // 0xb2 E0, 32 WWW Home |
|
340 |
234 // 0xea E0, 6A WWW Back |
|
341 |
233 // 0xe9 E0, 69 WWW Forward |
|
342 |
232 // 0xe8 E0, 68 WWW Stop |
|
343 |
231 // 0xe7 E0, 67 WWW Refresh |
|
344 |
230 // 0xe6 E0, 66 WWW Favorites |
|
345 | 345 |
*/ |
346 | 346 |
}; |
347 | 347 |
|
... | ... | |
366 | 366 |
NSDate *distantPast; |
367 | 367 |
NSEvent *event; |
368 | 368 |
NSAutoreleasePool *pool; |
369 |
|
|
369 |
|
|
370 | 370 |
pool = [ [ NSAutoreleasePool alloc ] init ]; |
371 | 371 |
distantPast = [ NSDate distantPast ]; |
372 |
|
|
372 |
|
|
373 | 373 |
vga_hw_update(); |
374 | 374 |
|
375 | 375 |
do { |
... | ... | |
415 | 415 |
|
416 | 416 |
case NSKeyDown: |
417 | 417 |
{ |
418 |
int keycode = cocoa_keycode_to_qemu([event keyCode]);
|
|
419 |
|
|
418 |
int keycode = cocoa_keycode_to_qemu([event keyCode]); |
|
419 |
|
|
420 | 420 |
/* handle command Key Combos */ |
421 | 421 |
if ([event modifierFlags] & NSCommandKeyMask) { |
422 | 422 |
switch ([event keyCode]) { |
... | ... | |
427 | 427 |
return; |
428 | 428 |
} |
429 | 429 |
} |
430 |
|
|
430 |
|
|
431 | 431 |
/* handle control + alt Key Combos */ |
432 | 432 |
if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) { |
433 | 433 |
switch (keycode) { |
... | ... | |
482 | 482 |
} |
483 | 483 |
} |
484 | 484 |
break; |
485 |
|
|
485 |
|
|
486 | 486 |
case NSKeyUp: |
487 | 487 |
{ |
488 |
int keycode = cocoa_keycode_to_qemu([event keyCode]);
|
|
488 |
int keycode = cocoa_keycode_to_qemu([event keyCode]); |
|
489 | 489 |
if (is_graphic_console()) { |
490 | 490 |
if (keycode & 0x80) |
491 | 491 |
kbd_put_keycode(0xe0); |
... | ... | |
493 | 493 |
} |
494 | 494 |
} |
495 | 495 |
break; |
496 |
|
|
496 |
|
|
497 | 497 |
case NSMouseMoved: |
498 | 498 |
if (grab) { |
499 | 499 |
int dx = [event deltaX]; |
... | ... | |
503 | 503 |
kbd_mouse_event(dx, dy, dz, buttons); |
504 | 504 |
} |
505 | 505 |
break; |
506 |
|
|
506 |
|
|
507 | 507 |
case NSLeftMouseDown: |
508 | 508 |
if (grab) { |
509 | 509 |
int buttons = 0; |
510 |
|
|
510 |
|
|
511 | 511 |
/* leftclick+command simulates rightclick */ |
512 | 512 |
if ([event modifierFlags] & NSCommandKeyMask) { |
513 | 513 |
buttons |= MOUSE_EVENT_RBUTTON; |
... | ... | |
519 | 519 |
[NSApp sendEvent: event]; |
520 | 520 |
} |
521 | 521 |
break; |
522 |
|
|
522 |
|
|
523 | 523 |
case NSLeftMouseDragged: |
524 | 524 |
if (grab) { |
525 | 525 |
int dx = [event deltaX]; |
... | ... | |
534 | 534 |
kbd_mouse_event(dx, dy, dz, buttons); |
535 | 535 |
} |
536 | 536 |
break; |
537 |
|
|
537 |
|
|
538 | 538 |
case NSLeftMouseUp: |
539 | 539 |
if (grab) { |
540 | 540 |
kbd_mouse_event(0, 0, 0, 0); |
... | ... | |
546 | 546 |
//[NSApp sendEvent: event]; |
547 | 547 |
} |
548 | 548 |
break; |
549 |
|
|
549 |
|
|
550 | 550 |
case NSRightMouseDown: |
551 | 551 |
if (grab) { |
552 | 552 |
int buttons = 0; |
553 |
|
|
553 |
|
|
554 | 554 |
buttons |= MOUSE_EVENT_RBUTTON; |
555 | 555 |
kbd_mouse_event(0, 0, 0, buttons); |
556 | 556 |
} else { |
557 | 557 |
[NSApp sendEvent: event]; |
558 | 558 |
} |
559 | 559 |
break; |
560 |
|
|
560 |
|
|
561 | 561 |
case NSRightMouseDragged: |
562 | 562 |
if (grab) { |
563 | 563 |
int dx = [event deltaX]; |
... | ... | |
568 | 568 |
kbd_mouse_event(dx, dy, dz, buttons); |
569 | 569 |
} |
570 | 570 |
break; |
571 |
|
|
571 |
|
|
572 | 572 |
case NSRightMouseUp: |
573 | 573 |
if (grab) { |
574 | 574 |
kbd_mouse_event(0, 0, 0, 0); |
... | ... | |
576 | 576 |
[NSApp sendEvent: event]; |
577 | 577 |
} |
578 | 578 |
break; |
579 |
|
|
579 |
|
|
580 | 580 |
case NSOtherMouseDragged: |
581 | 581 |
if (grab) { |
582 | 582 |
int dx = [event deltaX]; |
... | ... | |
587 | 587 |
kbd_mouse_event(dx, dy, dz, buttons); |
588 | 588 |
} |
589 | 589 |
break; |
590 |
|
|
590 |
|
|
591 | 591 |
case NSOtherMouseDown: |
592 | 592 |
if (grab) { |
593 | 593 |
int buttons = 0; |
... | ... | |
597 | 597 |
[NSApp sendEvent:event]; |
598 | 598 |
} |
599 | 599 |
break; |
600 |
|
|
600 |
|
|
601 | 601 |
case NSOtherMouseUp: |
602 | 602 |
if (grab) { |
603 | 603 |
kbd_mouse_event(0, 0, 0, 0); |
... | ... | |
605 | 605 |
[NSApp sendEvent: event]; |
606 | 606 |
} |
607 | 607 |
break; |
608 |
|
|
608 |
|
|
609 | 609 |
case NSScrollWheel: |
610 | 610 |
if (grab) { |
611 | 611 |
int dz = [event deltaY]; |
612 | 612 |
kbd_mouse_event(0, 0, -dz, 0); |
613 | 613 |
} |
614 | 614 |
break; |
615 |
|
|
615 |
|
|
616 | 616 |
default: [NSApp sendEvent:event]; |
617 | 617 |
} |
618 | 618 |
} |
... | ... | |
625 | 625 |
------------------------------------------------------ |
626 | 626 |
*/ |
627 | 627 |
|
628 |
static void cocoa_cleanup(void)
|
|
628 |
static void cocoa_cleanup(void) |
|
629 | 629 |
{ |
630 | 630 |
|
631 | 631 |
} |
... | ... | |
641 | 641 |
ds->dpy_update = cocoa_update; |
642 | 642 |
ds->dpy_resize = cocoa_resize; |
643 | 643 |
ds->dpy_refresh = cocoa_refresh; |
644 |
|
|
644 |
|
|
645 | 645 |
cocoa_resize(ds, 640, 400); |
646 |
|
|
646 |
|
|
647 | 647 |
atexit(cocoa_cleanup); |
648 | 648 |
} |
649 | 649 |
|
... | ... | |
661 | 661 |
------------------------------------------------------ |
662 | 662 |
*/ |
663 | 663 |
static void QZ_SetPortAlphaOpaque () |
664 |
{
|
|
664 |
{ |
|
665 | 665 |
/* Assume 32 bit if( bpp == 32 )*/ |
666 | 666 |
if ( 1 ) { |
667 |
|
|
667 |
|
|
668 | 668 |
uint32_t *pixels = (uint32_t*) current_ds.data; |
669 | 669 |
uint32_t rowPixels = current_ds.linesize / 4; |
670 | 670 |
uint32_t i, j; |
671 |
|
|
671 |
|
|
672 | 672 |
for (i = 0; i < current_ds.height; i++) |
673 | 673 |
for (j = 0; j < current_ds.width; j++) { |
674 |
|
|
674 |
|
|
675 | 675 |
pixels[ (i * rowPixels) + j ] |= 0xFF000000; |
676 | 676 |
} |
677 | 677 |
} |
... | ... | |
680 | 680 |
@implementation QemuWindow |
681 | 681 |
- (void)miniaturize:(id)sender |
682 | 682 |
{ |
683 |
|
|
683 |
|
|
684 | 684 |
/* make the alpha channel opaque so anim won't have holes in it */ |
685 | 685 |
QZ_SetPortAlphaOpaque (); |
686 |
|
|
686 |
|
|
687 | 687 |
[ super miniaturize:sender ]; |
688 |
|
|
688 |
|
|
689 | 689 |
} |
690 | 690 |
- (void)display |
691 |
{
|
|
692 |
/*
|
|
691 |
{ |
|
692 |
/* |
|
693 | 693 |
This method fires just before the window deminaturizes from the Dock. |
694 |
|
|
694 |
|
|
695 | 695 |
We'll save the current visible surface, let the window manager redraw any |
696 |
UI elements, and restore the SDL surface. This way, no expose event
|
|
696 |
UI elements, and restore the SDL surface. This way, no expose event |
|
697 | 697 |
is required, and the deminiaturize works perfectly. |
698 | 698 |
*/ |
699 |
|
|
699 |
|
|
700 | 700 |
/* make sure pixels are fully opaque */ |
701 | 701 |
QZ_SetPortAlphaOpaque (); |
702 |
|
|
702 |
|
|
703 | 703 |
/* save current visible SDL surface */ |
704 | 704 |
[ self cacheImageInRect:[ qd_view frame ] ]; |
705 |
|
|
705 |
|
|
706 | 706 |
/* let the window manager redraw controls, border, etc */ |
707 | 707 |
[ super display ]; |
708 |
|
|
708 |
|
|
709 | 709 |
/* restore visible SDL surface */ |
710 | 710 |
[ self restoreCachedImage ]; |
711 | 711 |
} |
... | ... | |
742 | 742 |
if( gArgc <= 1 || strncmp (gArgv[1], "-psn", 4) == 0) |
743 | 743 |
{ |
744 | 744 |
NSOpenPanel *op = [[NSOpenPanel alloc] init]; |
745 |
|
|
745 |
|
|
746 | 746 |
cocoa_resize(¤t_ds, 640, 400); |
747 |
|
|
747 |
|
|
748 | 748 |
[op setPrompt:@"Boot image"]; |
749 |
|
|
749 |
|
|
750 | 750 |
[op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"]; |
751 |
|
|
751 |
|
|
752 | 752 |
[op beginSheetForDirectory:nil file:nil types:[NSArray arrayWithObjects:@"img",@"iso",@"dmg",@"qcow",@"cow",@"cloop",@"vmdk",nil] |
753 | 753 |
modalForWindow:window modalDelegate:self |
754 | 754 |
didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; |
... | ... | |
774 | 774 |
{ |
775 | 775 |
exit(0); |
776 | 776 |
} |
777 |
|
|
777 |
|
|
778 | 778 |
if(returnCode == NSOKButton) |
779 | 779 |
{ |
780 | 780 |
char *bin = "qemu"; |
781 | 781 |
char *img = (char*)[ [ sheet filename ] cString]; |
782 |
|
|
782 |
|
|
783 | 783 |
char **argv = (char**)malloc( sizeof(char*)*3 ); |
784 |
|
|
784 |
|
|
785 | 785 |
asprintf(&argv[0], "%s", bin); |
786 | 786 |
asprintf(&argv[1], "-hda"); |
787 | 787 |
asprintf(&argv[2], "%s", img); |
788 |
|
|
788 |
|
|
789 | 789 |
printf("Using argc %d argv %s -hda %s\n", 3, bin, img); |
790 |
|
|
790 |
|
|
791 | 791 |
[self startEmulationWithArgc:3 argv:(char**)argv]; |
792 | 792 |
} |
793 | 793 |
} |
... | ... | |
827 | 827 |
NSMenuItem *menuItem; |
828 | 828 |
NSString *title; |
829 | 829 |
NSString *appName; |
830 |
|
|
830 |
|
|
831 | 831 |
appName = @"Qemu"; |
832 | 832 |
appleMenu = [[NSMenu alloc] initWithTitle:@""]; |
833 |
|
|
833 |
|
|
834 | 834 |
/* Add menu items */ |
835 | 835 |
title = [@"About " stringByAppendingString:appName]; |
836 | 836 |
[appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; |
... | ... | |
850 | 850 |
title = [@"Quit " stringByAppendingString:appName]; |
851 | 851 |
[appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; |
852 | 852 |
|
853 |
|
|
853 |
|
|
854 | 854 |
/* Put menu into the menubar */ |
855 | 855 |
menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; |
856 | 856 |
[menuItem setSubmenu:appleMenu]; |
... | ... | |
872 | 872 |
NSMenuItem *menuItem; |
873 | 873 |
|
874 | 874 |
windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; |
875 |
|
|
875 |
|
|
876 | 876 |
/* "Minimize" item */ |
877 | 877 |
menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; |
878 | 878 |
[windowMenu addItem:menuItem]; |
879 | 879 |
[menuItem release]; |
880 |
|
|
880 |
|
|
881 | 881 |
/* Put menu into the menubar */ |
882 | 882 |
windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; |
883 | 883 |
[windowMenuItem setSubmenu:windowMenu]; |
884 | 884 |
[[NSApp mainMenu] addItem:windowMenuItem]; |
885 |
|
|
885 |
|
|
886 | 886 |
/* Tell the application object that this is now the window menu */ |
887 | 887 |
[NSApp setWindowsMenu:windowMenu]; |
888 | 888 |
|
... | ... | |
896 | 896 |
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
897 | 897 |
QemuCocoaGUIController *gui_controller; |
898 | 898 |
CPSProcessSerNum PSN; |
899 |
|
|
899 |
|
|
900 | 900 |
[NSApplication sharedApplication]; |
901 |
|
|
901 |
|
|
902 | 902 |
if (!CPSGetCurrentProcess(&PSN)) |
903 | 903 |
if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) |
904 | 904 |
if (!CPSSetFrontProcess(&PSN)) |
905 | 905 |
[NSApplication sharedApplication]; |
906 |
|
|
906 |
|
|
907 | 907 |
/* Set up the menubar */ |
908 | 908 |
[NSApp setMainMenu:[[NSMenu alloc] init]]; |
909 | 909 |
setApplicationMenu(); |
... | ... | |
912 | 912 |
/* Create SDLMain and make it the app delegate */ |
913 | 913 |
gui_controller = [[QemuCocoaGUIController alloc] init]; |
914 | 914 |
[NSApp setDelegate:gui_controller]; |
915 |
|
|
915 |
|
|
916 | 916 |
/* Start the main event loop */ |
917 | 917 |
[NSApp run]; |
918 |
|
|
918 |
|
|
919 | 919 |
[gui_controller release]; |
920 | 920 |
[pool release]; |
921 | 921 |
} |
Also available in: Unified diff