Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/planix-v0/sys/src/cmd/unix/drawterm/gui-osx/screen.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
// in this file, _Rect is os x Rect,
2
// _Point is os x Point
3
#undef Point
4
#define Point _Point
5
#undef Rect
6
#define Rect _Rect
7
 
8
#include <Carbon/Carbon.h>
9
#include <QuickTime/QuickTime.h> // for full screen
10
 
11
#undef Rect
12
#undef Point
13
 
14
#undef nil
15
 
16
 
17
#include "u.h"
18
#include "lib.h"
19
#include "kern/dat.h"
20
#include "kern/fns.h"
21
#include "error.h"
22
#include "user.h"
23
#include <draw.h>
24
#include <memdraw.h>
25
#include "screen.h"
26
#include "keyboard.h"
27
#include "keycodes.h"
28
 
29
#define rWindowResource  128
30
 
31
#define topLeft(r)  (((Point *) &(r))[0])
32
#define botRight(r) (((Point *) &(r))[1])
33
 
34
extern int mousequeue;
35
static int depth;
36
Boolean   gDone;
37
RgnHandle gCursorRegionHdl;
38
 
39
Memimage	*gscreen;
40
Screeninfo	screen;
41
 
42
static int readybit;
43
static Rendez	rend;
44
 
45
///
46
// menu
47
//
48
static MenuRef windMenu;
49
static MenuRef viewMenu;
50
 
51
enum {
52
	kQuitCmd = 1,
53
	kFullScreenCmd = 2,
54
};
55
 
56
static WindowGroupRef winGroup = NULL;
57
static WindowRef theWindow = NULL;
58
static CGContextRef context;
59
static CGDataProviderRef dataProviderRef;
60
static CGImageRef fullScreenImage;
61
static CGRect devRect;
62
static CGRect bounds;
63
static PasteboardRef appleclip;
64
static _Rect winRect;
65
 
66
Boolean altPressed = false;
67
Boolean button2 = false;
68
Boolean button3 = false;
69
 
70
 
71
static int
72
isready(void*a)
73
{
74
	return readybit;
75
}
76
 
77
CGContextRef QuartzContext;
78
 
79
void winproc(void *a);
80
 
81
void screeninit(void)
82
{
83
	int fmt;
84
	int dx, dy;
85
	ProcessSerialNumber psn = { 0, kCurrentProcess };
86
	TransformProcessType(&psn, kProcessTransformToForegroundApplication);
87
	SetFrontProcess(&psn);
88
 
89
	memimageinit();
90
	depth = 32; // That's all this code deals with for now
91
	screen.depth = 32;
92
	fmt = XBGR32; //XRGB32;
93
 
94
	devRect = CGDisplayBounds(CGMainDisplayID());
95
//	devRect.origin.x = 0;
96
//	devRect.origin.y = 0;
97
//	devRect.size.width = 1024;
98
//	devRect.size.height = 768;
99
	dx = devRect.size.width;
100
	dy = devRect.size.height;
101
 
102
	gscreen = allocmemimage(Rect(0,0,dx,dy), fmt);
103
	dataProviderRef = CGDataProviderCreateWithData(0, gscreen->data->bdata,
104
						dx * dy * 4, 0);
105
	fullScreenImage = CGImageCreate(dx, dy, 8, 32, dx * 4,
106
				CGColorSpaceCreateDeviceRGB(),
107
				kCGImageAlphaNoneSkipLast,
108
				dataProviderRef, 0, 0, kCGRenderingIntentDefault);
109
 
110
	kproc("osxscreen", winproc, 0);
111
	ksleep(&rend, isready, 0);
112
}
113
 
114
// No wonder Apple sells so many wide displays!
115
static OSStatus ApplicationQuitEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
116
static OSStatus MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
117
static OSStatus MainWindowCommandHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
118
 
119
void 
120
window_resized()
121
{
122
	GetWindowBounds(theWindow, kWindowContentRgn, &winRect );
123
 
124
	bounds = CGRectMake(0, 0, winRect.right-winRect.left, winRect.bottom - winRect.top);
125
}
126
 
127
 
128
void winproc(void *a)
129
{
130
	winRect.left = 30;
131
	winRect.top = 60;
132
	winRect.bottom = (devRect.size.height * 0.75) + winRect.top;
133
	winRect.right = (devRect.size.width * 0.75) + winRect.left;
134
 
135
	ClearMenuBar();
136
	InitCursor();
137
 
138
	CreateStandardWindowMenu(0, &windMenu);
139
	InsertMenu(windMenu, 0);
140
 
141
    MenuItemIndex index;
142
	CreateNewMenu(1004, 0, &viewMenu);
143
	SetMenuTitleWithCFString(viewMenu, CFSTR("View"));
144
	AppendMenuItemTextWithCFString(viewMenu, CFSTR("Full Screen"), 0,
145
			kFullScreenCmd, &index);
146
	SetMenuItemCommandKey(viewMenu, index, 0, 'F');
147
	InsertMenu(viewMenu, GetMenuID(windMenu));
148
 
149
	DrawMenuBar();
150
	uint32_t windowAttrs = 0
151
				| kWindowCloseBoxAttribute
152
				| kWindowCollapseBoxAttribute
153
				| kWindowResizableAttribute
154
				| kWindowStandardHandlerAttribute
155
				| kWindowFullZoomAttribute
156
		;
157
 
158
	CreateNewWindow(kDocumentWindowClass, windowAttrs, &winRect, &theWindow);
159
	CreateWindowGroup(0, &winGroup);
160
	SetWindowGroup(theWindow, winGroup);
161
 
162
	SetWindowTitleWithCFString(theWindow, CFSTR("Drawterm"));
163
 
164
	if(PasteboardCreate(kPasteboardClipboard, &appleclip) != noErr)
165
		sysfatal("pasteboard create failed");
166
 
167
	const EventTypeSpec quit_events[] = {
168
		{ kEventClassApplication, kEventAppQuit }
169
	};
170
	const EventTypeSpec commands[] = {
171
		{ kEventClassWindow, kEventWindowClosed },
172
		{ kEventClassWindow, kEventWindowBoundsChanged },
173
		{ kEventClassCommand, kEventCommandProcess }
174
	};
175
	const EventTypeSpec events[] = {
176
		{ kEventClassKeyboard, kEventRawKeyDown },
177
		{ kEventClassKeyboard, kEventRawKeyModifiersChanged },
178
		{ kEventClassKeyboard, kEventRawKeyRepeat },
179
		{ kEventClassMouse, kEventMouseDown },
180
		{ kEventClassMouse, kEventMouseUp },
181
		{ kEventClassMouse, kEventMouseMoved },
182
		{ kEventClassMouse, kEventMouseDragged },
183
		{ kEventClassMouse, kEventMouseWheelMoved },
184
	};
185
 
186
	InstallApplicationEventHandler (
187
								NewEventHandlerUPP (ApplicationQuitEventHandler),
188
								GetEventTypeCount(quit_events),
189
								quit_events,
190
								NULL,
191
								NULL);
192
 
193
 	InstallApplicationEventHandler (
194
 								NewEventHandlerUPP (MainWindowEventHandler),
195
								GetEventTypeCount(events),
196
								events,
197
								NULL,
198
								NULL);
199
	InstallWindowEventHandler (
200
								theWindow,
201
								NewEventHandlerUPP (MainWindowCommandHandler),
202
								GetEventTypeCount(commands),
203
								commands,
204
								theWindow,
205
								NULL);
206
 
207
	ShowWindow(theWindow);
208
	ShowMenuBar();
209
	window_resized();
210
	SelectWindow(theWindow);
211
	terminit();
212
	// Run the event loop
213
	readybit = 1;
214
	wakeup(&rend);
215
	RunApplicationEventLoop();
216
 
217
}
218
 
219
static inline int convert_key(UInt32 key, UInt32 charcode)
220
{
221
	switch(key) {
222
		case QZ_IBOOK_ENTER:
223
		case QZ_RETURN: return '\n';
224
		case QZ_ESCAPE: return 27;
225
		case QZ_BACKSPACE: return '\b';
226
		case QZ_LALT: return Kalt;
227
		case QZ_LCTRL: return Kctl;
228
		case QZ_LSHIFT: return Kshift;
229
		case QZ_F1: return KF+1;
230
		case QZ_F2: return KF+2;
231
		case QZ_F3: return KF+3;
232
		case QZ_F4: return KF+4;
233
		case QZ_F5: return KF+5;
234
		case QZ_F6: return KF+6;
235
		case QZ_F7: return KF+7;
236
		case QZ_F8: return KF+8;
237
		case QZ_F9: return KF+9;
238
		case QZ_F10: return KF+10;
239
		case QZ_F11: return KF+11;
240
		case QZ_F12: return KF+12;
241
		case QZ_INSERT: return Kins;
242
		case QZ_DELETE: return 0x7F;
243
		case QZ_HOME: return Khome;
244
		case QZ_END: return Kend;
245
		case QZ_KP_PLUS: return '+';
246
		case QZ_KP_MINUS: return '-';
247
		case QZ_TAB: return '\t';
248
		case QZ_PAGEUP: return Kpgup;
249
		case QZ_PAGEDOWN: return Kpgdown;
250
		case QZ_UP: return Kup;
251
		case QZ_DOWN: return Kdown;
252
		case QZ_LEFT: return Kleft;
253
		case QZ_RIGHT: return Kright;
254
		case QZ_KP_MULTIPLY: return '*';
255
		case QZ_KP_DIVIDE: return '/';
256
		case QZ_KP_ENTER: return '\n';
257
		case QZ_KP_PERIOD: return '.';
258
		case QZ_KP0: return '0';
259
		case QZ_KP1: return '1';
260
		case QZ_KP2: return '2';
261
		case QZ_KP3: return '3';
262
		case QZ_KP4: return '4';
263
		case QZ_KP5: return '5';
264
		case QZ_KP6: return '6';
265
		case QZ_KP7: return '7';
266
		case QZ_KP8: return '8';
267
		case QZ_KP9: return '9';
268
		default: return charcode;
269
	}
270
}
271
 
272
void
273
sendbuttons(int b, int x, int y)
274
{
275
	int i;
276
	lock(&mouse.lk);
277
	i = mouse.wi;
278
	if(mousequeue) {
279
		if(i == mouse.ri || mouse.lastb != b || mouse.trans) {
280
			mouse.wi = (i+1)%Mousequeue;
281
			if(mouse.wi == mouse.ri)
282
				mouse.ri = (mouse.ri+1)%Mousequeue;
283
			mouse.trans = mouse.lastb != b;
284
		} else {
285
			i = (i-1+Mousequeue)%Mousequeue;
286
		}
287
	} else {
288
		mouse.wi = (i+1)%Mousequeue;
289
		mouse.ri = i;
290
	}
291
	mouse.queue[i].xy.x = x;
292
	mouse.queue[i].xy.y = y;
293
	mouse.queue[i].buttons = b;
294
	mouse.queue[i].msec = ticks();
295
	mouse.lastb = b;
296
	unlock(&mouse.lk);
297
	wakeup(&mouse.r);
298
}
299
 
300
static Ptr fullScreenRestore;
301
static int amFullScreen = 0;
302
static WindowRef oldWindow = NULL;
303
 
304
static void
305
leave_full_screen()
306
{
307
	if (amFullScreen) {
308
		EndFullScreen(fullScreenRestore, 0);
309
		theWindow = oldWindow;
310
		ShowWindow(theWindow);
311
		amFullScreen = 0;
312
		window_resized();
313
		Rectangle rect =  { { 0, 0 },
314
 							{ bounds.size.width,
315
 							  bounds.size.height} };
316
		drawqlock();
317
 		flushmemscreen(rect);
318
 		drawqunlock();
319
	}
320
}
321
 
322
static void
323
full_screen()
324
{
325
	if (!amFullScreen) {
326
		oldWindow = theWindow;
327
		HideWindow(theWindow);
328
		BeginFullScreen(&fullScreenRestore, 0, 0, 0, &theWindow, 0, 0);
329
		amFullScreen = 1;
330
		window_resized();
331
		Rectangle rect =  { { 0, 0 },
332
 							{ bounds.size.width,
333
 							  bounds.size.height} };
334
		drawqlock();
335
 		flushmemscreen(rect);
336
 		drawqunlock();
337
	}
338
}
339
 
340
// catch quit events to handle quits from menu, Cmd+Q, applescript, and task switcher
341
static OSStatus ApplicationQuitEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
342
{
343
	exit(0);
344
//	QuitApplicationEventLoop();
345
	return noErr;
346
}
347
 
348
static OSStatus MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
349
{
350
	OSStatus result = noErr;
351
	result = CallNextEventHandler(nextHandler, event);
352
	UInt32 class = GetEventClass (event);
353
	UInt32 kind = GetEventKind (event);
354
	static uint32_t mousebuttons = 0; // bitmask of buttons currently down
355
	static uint32_t mouseX = 0; 
356
	static uint32_t mouseY = 0; 
357
 
358
	if(class == kEventClassKeyboard) {
359
		char macCharCodes;
360
		UInt32 macKeyCode;
361
		UInt32 macKeyModifiers;
362
 
363
		GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar,
364
							NULL, sizeof(macCharCodes), NULL, &macCharCodes);
365
		GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL,
366
							sizeof(macKeyCode), NULL, &macKeyCode);
367
		GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
368
							sizeof(macKeyModifiers), NULL, &macKeyModifiers);
369
        switch(kind) {
370
		case kEventRawKeyModifiersChanged:
371
			if (macKeyModifiers == (controlKey | optionKey)) leave_full_screen();
372
 
373
			switch(macKeyModifiers & (optionKey | cmdKey)) {
374
			case (optionKey | cmdKey):
375
				/* due to chording we need to handle the case when both
376
				 * modifier keys are pressed at the same time. 
377
				 * currently it's only 2-3 snarf and the 3-2 noop
378
				 */
379
				altPressed = true;
380
				if(mousebuttons & 1 || mousebuttons & 2 || mousebuttons & 4) {
381
					mousebuttons |= 2;	/* set button 2 */
382
					mousebuttons |= 4;	/* set button 3 */
383
					button2 = true;
384
					button3 = true;
385
					sendbuttons(mousebuttons, mouseX, mouseY);
386
				} 
387
				break;
388
			case optionKey:
389
				altPressed = true;
390
				if(mousebuttons & 1 || mousebuttons & 4) {
391
					mousebuttons |= 2;	/* set button 2 */
392
					button2 = true;
393
					sendbuttons(mousebuttons, mouseX, mouseY);
394
				} 
395
				break;
396
			case cmdKey:
397
				if(mousebuttons & 1 || mousebuttons & 2) {
398
					mousebuttons |= 4;	/* set button 3 */
399
					button3 = true;
400
					sendbuttons(mousebuttons, mouseX, mouseY);
401
				}
402
				break;
403
			case 0:
404
			default:
405
				if(button2 || button3) {
406
					if(button2) {
407
						mousebuttons &= ~2;	/* clear button 2 */
408
						button2 = false;
409
						altPressed = false;
410
					} 
411
					if(button3) {
412
						mousebuttons &= ~4;	/* clear button 3 */
413
						button3 = false;
414
					}
415
					sendbuttons(mousebuttons, mouseX, mouseY);
416
				}
417
				if(altPressed) {
418
					kbdputc(kbdq, Kalt);
419
					altPressed = false;
420
				} 
421
				break;
422
			}
423
			break;
424
		case kEventRawKeyDown:
425
		case kEventRawKeyRepeat:
426
			if(macKeyModifiers != cmdKey) {
427
				int key = convert_key(macKeyCode, macCharCodes);
428
				if (key != -1) kbdputc(kbdq, key);
429
			} else
430
				result = eventNotHandledErr;
431
			break;
432
		default:
433
			break;
434
		}
435
	}
436
	else if(class == kEventClassMouse) {
437
		_Point mousePos;
438
 
439
		GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
440
							0, sizeof mousePos, 0, &mousePos);
441
 
442
		switch (kind) {
443
			case kEventMouseWheelMoved:
444
			{
445
			    int32_t wheeldelta;
446
				GetEventParameter(event,kEventParamMouseWheelDelta,typeSInt32,
447
									0,sizeof(wheeldelta), 0, &wheeldelta);
448
				mouseX = mousePos.h - winRect.left;
449
				mouseY = mousePos.v - winRect.top;
450
				sendbuttons(wheeldelta>0 ? 8 : 16, mouseX, mouseY);
451
				break;
452
			}
453
			case kEventMouseUp:
454
			case kEventMouseDown:
455
			{
456
				uint32_t buttons;
457
				uint32_t modifiers;
458
				GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 
459
									0, sizeof(modifiers), 0, &modifiers);
460
				GetEventParameter(event, kEventParamMouseChord, typeUInt32, 
461
									0, sizeof buttons, 0, &buttons);
462
				/* simulate other buttons via alt/apple key. like x11 */
463
				if(modifiers & optionKey) {
464
					mousebuttons = ((buttons & 1) ? 2 : 0);
465
					altPressed = false;
466
				} else if(modifiers & cmdKey)
467
					mousebuttons = ((buttons & 1) ? 4 : 0);
468
				else
469
					mousebuttons = (buttons & 1);
470
 
471
				mousebuttons |= ((buttons & 2)<<1);
472
				mousebuttons |= ((buttons & 4)>>1);
473
 
474
			} /* Fallthrough */
475
			case kEventMouseMoved:
476
			case kEventMouseDragged:
477
				mouseX = mousePos.h - winRect.left;
478
				mouseY = mousePos.v - winRect.top;
479
				sendbuttons(mousebuttons, mouseX, mouseY);
480
				break;
481
			default:
482
				result = eventNotHandledErr;
483
				break;
484
		}
485
	}
486
	return result;
487
}
488
 
489
 
490
//default window command handler (from menus)
491
static OSStatus MainWindowCommandHandler(EventHandlerCallRef nextHandler,
492
					EventRef event, void *userData)
493
{
494
	OSStatus result = noErr;
495
	UInt32 class = GetEventClass (event);
496
	UInt32 kind = GetEventKind (event);
497
 
498
	result = CallNextEventHandler(nextHandler, event);
499
 
500
	if(class == kEventClassCommand)
501
	{
502
		HICommand theHICommand;
503
		GetEventParameter( event, kEventParamDirectObject, typeHICommand,
504
							NULL, sizeof( HICommand ), NULL, &theHICommand );
505
 
506
		switch ( theHICommand.commandID )
507
		{
508
			case kHICommandQuit:
509
				exit(0);
510
				break;
511
 
512
			case kFullScreenCmd:
513
				full_screen();
514
				break;
515
 
516
			default:
517
				result = eventNotHandledErr;
518
				break;
519
		}
520
	}
521
	else if(class == kEventClassWindow)
522
	{
523
		WindowRef     window;
524
		_Rect          rectPort = {0,0,0,0};
525
 
526
		GetEventParameter(event, kEventParamDirectObject, typeWindowRef,
527
							NULL, sizeof(WindowRef), NULL, &window);
528
 
529
		if(window)
530
		{
531
			GetPortBounds(GetWindowPort(window), &rectPort);
532
		}
533
 
534
		switch (kind)
535
		{
536
			case kEventWindowClosed:
537
				// send a quit carbon event instead of directly calling cleanexit 
538
				// so that all quits are done in ApplicationQuitEventHandler
539
				{
540
				EventRef quitEvent;
541
				CreateEvent(NULL,
542
							kEventClassApplication,
543
							kEventAppQuit,
544
							0,
545
							kEventAttributeNone,
546
							&quitEvent);
547
				EventTargetRef target;
548
				target = GetApplicationEventTarget();
549
				SendEventToEventTarget(quitEvent, target);
550
				}
551
 				break;
552
 
553
			//resize window
554
			case kEventWindowBoundsChanged:
555
				window_resized();
556
				Rectangle rect =  { { 0, 0 },
557
 									{ bounds.size.width,
558
 									  bounds.size.height} };
559
				drawqlock();
560
 				flushmemscreen(rect);
561
 				drawqunlock();
562
				break;
563
 
564
			default:
565
				result = eventNotHandledErr;
566
				break;
567
		}
568
	}
569
 
570
	return result;
571
}
572
 
573
void
574
flushmemscreen(Rectangle r)
575
{
576
	// sanity check.  Trips from the initial "terminal"
577
    if (r.max.x < r.min.x || r.max.y < r.min.y) return;
578
 
579
	screenload(r, gscreen->depth, byteaddr(gscreen, ZP), ZP,
580
		gscreen->width*sizeof(ulong));
581
}
582
 
583
uchar*
584
attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen, void **X)
585
{
586
	*r = gscreen->r;
587
	*chan = gscreen->chan;
588
	*depth = gscreen->depth;
589
	*width = gscreen->width;
590
	*softscreen = 1;
591
 
592
	return gscreen->data->bdata;
593
}
594
 
595
// PAL - no palette handling.  Don't intend to either.
596
void
597
getcolor(ulong i, ulong *r, ulong *g, ulong *b)
598
{
599
 
600
// PAL: Certainly wrong to return a grayscale.
601
	 *r = i;
602
	 *g = i;
603
	 *b = i;
604
}
605
 
606
void
607
setcolor(ulong index, ulong red, ulong green, ulong blue)
608
{
609
	assert(0);
610
}
611
 
612
 
613
static char snarf[3*SnarfSize+1];
614
static Rune rsnarf[SnarfSize+1];
615
 
616
char*
617
clipread(void)
618
{
619
	CFDataRef cfdata;
620
	OSStatus err = noErr;
621
	ItemCount nItems;
622
 
623
	// Wow.  This is ridiculously complicated.
624
	PasteboardSynchronize(appleclip);
625
	if((err = PasteboardGetItemCount(appleclip, &nItems)) != noErr) {
626
		fprint(2, "apple pasteboard GetItemCount failed - Error %d\n", err);
627
		return 0;
628
	}
629
 
630
	uint32_t i;
631
	// Yes, based at 1.  Silly API.
632
	for(i = 1; i <= nItems; ++i) {
633
		PasteboardItemID itemID;
634
		CFArrayRef flavorTypeArray;
635
		CFIndex flavorCount;
636
 
637
		if((err = PasteboardGetItemIdentifier(appleclip, i, &itemID)) != noErr){
638
			fprint(2, "Can't get pasteboard item identifier: %d\n", err);
639
			return 0;
640
		}
641
 
642
		if((err = PasteboardCopyItemFlavors(appleclip, itemID, &flavorTypeArray))!=noErr){
643
			fprint(2, "Can't copy pasteboard item flavors: %d\n", err);
644
			return 0;
645
		}
646
 
647
		flavorCount = CFArrayGetCount(flavorTypeArray);
648
		CFIndex flavorIndex;
649
		for(flavorIndex = 0; flavorIndex < flavorCount; ++flavorIndex){
650
			CFStringRef flavorType;
651
			flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex);
652
			if (UTTypeConformsTo(flavorType, CFSTR("public.utf16-plain-text"))){
653
				if((err = PasteboardCopyItemFlavorData(appleclip, itemID,
654
					CFSTR("public.utf16-plain-text"), &cfdata)) != noErr){
655
					fprint(2, "apple pasteboard CopyItem failed - Error %d\n", err);
656
					return 0;
657
				}
658
				CFIndex length = CFDataGetLength(cfdata);
659
				if (length > sizeof rsnarf) length = sizeof rsnarf;
660
				CFDataGetBytes(cfdata, CFRangeMake(0, length), (uint8_t *)rsnarf);
661
				snprint(snarf, sizeof snarf, "%.*S", length/sizeof(Rune), rsnarf);
662
				char *s = snarf;
663
				while (*s) {
664
					if (*s == '\r') *s = '\n';
665
					s++;
666
				}
667
				CFRelease(cfdata);
668
				return strdup(snarf);
669
			}
670
		}
671
	}
672
	return 0;
673
}
674
 
675
int
676
clipwrite(char *snarf)
677
{
678
	CFDataRef cfdata;
679
	PasteboardSyncFlags flags;
680
 
681
	runesnprint(rsnarf, nelem(rsnarf), "%s", snarf);
682
	if(PasteboardClear(appleclip) != noErr){
683
		fprint(2, "apple pasteboard clear failed\n");
684
		return 0;
685
	}
686
	flags = PasteboardSynchronize(appleclip);
687
	if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){
688
		fprint(2, "apple pasteboard cannot assert ownership\n");
689
		return 0;
690
	}
691
	cfdata = CFDataCreate(kCFAllocatorDefault, 
692
		(uchar*)rsnarf, runestrlen(rsnarf)*2);
693
	if(cfdata == nil){
694
		fprint(2, "apple pasteboard cfdatacreate failed\n");
695
		return 0;
696
	}
697
	if(PasteboardPutItemFlavor(appleclip, (PasteboardItemID)1,
698
		CFSTR("public.utf16-plain-text"), cfdata, 0) != noErr){
699
		fprint(2, "apple pasteboard putitem failed\n");
700
		CFRelease(cfdata);
701
		return 0;
702
	}
703
	CFRelease(cfdata);
704
	return 1;
705
}
706
 
707
 
708
void
709
mouseset(Point xy)
710
{
711
	CGPoint pnt;
712
	pnt.x = xy.x + winRect.left;
713
	pnt.y = xy.y + winRect.top;
714
	CGWarpMouseCursorPosition(pnt);
715
}
716
 
717
void
718
screenload(Rectangle r, int depth, uchar *p, Point pt, int step)
719
{
720
	CGRect rbounds;
721
	rbounds.size.width = r.max.x - r.min.x;
722
	rbounds.size.height = r.max.y - r.min.y;
723
	rbounds.origin.x = r.min.x;
724
	rbounds.origin.y = r.min.y;
725
 
726
	if(depth != gscreen->depth)
727
		panic("screenload: bad ldepth");
728
 
729
	QDBeginCGContext( GetWindowPort(theWindow), &context);
730
 
731
	// The sub-image is relative to our whole screen image.
732
	CGImageRef subimg = CGImageCreateWithImageInRect(fullScreenImage, rbounds);
733
 
734
	// Drawing the sub-image is relative to the window.
735
	rbounds.origin.y = winRect.bottom - winRect.top - r.min.y - rbounds.size.height;
736
	CGContextDrawImage(context, rbounds, subimg);
737
	CGContextFlush(context);
738
	CGImageRelease(subimg);
739
	QDEndCGContext( GetWindowPort(theWindow), &context);
740
 
741
}
742
 
743
// PAL: these don't work.
744
// SetCursor and InitCursor are marked as deprecated in 10.4, and I can't for the
745
// life of me find out what has replaced them.
746
void
747
setcursor(void)
748
{
749
    Cursor crsr;
750
    int i;
751
 
752
	for(i=0; i<16; i++){
753
		crsr.data[i] = ((ushort*)cursor.set)[i];
754
		crsr.mask[i] = crsr.data[i] | ((ushort*)cursor.clr)[i];
755
	}
756
	crsr.hotSpot.h = -cursor.offset.x;
757
	crsr.hotSpot.v = -cursor.offset.y;
758
	SetCursor(&crsr);
759
}
760
 
761
void
762
cursorarrow(void)
763
{
764
	InitCursor();
765
}