1/*
2 * tkMacOSXXStubs.c --
3 *
4 *	This file contains most of the X calls called by Tk. Many of
5 *	these calls are just stubs and either don't make sense on the
6 *	Macintosh or thier implamentation just doesn't do anything. Other
7 *	calls will eventually be moved into other files.
8 *
9 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
10 * Copyright 2001, Apple Computer, Inc.
11 * Copyright (c) 2005-2007 Daniel A. Steffen <das@users.sourceforge.net>
12 *
13 * See the file "license.terms" for information on usage and redistribution
14 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 *
16 * RCS: @(#) $Id: tkMacOSXXStubs.c,v 1.2.2.20 2007/11/09 06:26:57 das Exp $
17 */
18
19#include "tkMacOSXPrivate.h"
20#include "tkMacOSXEvent.h"
21
22#if 0
23#include <IOKit/IOKitLib.h>
24#endif
25
26/*
27 * Because this file is still under major development Debugger statements are
28 * used through out this file. The define TCL_DEBUG will decide whether
29 * the debugger statements actually call the debugger or not.
30 */
31
32#ifndef TCL_DEBUG
33#   define Debugger()
34#endif
35
36#define ROOT_ID 10
37
38/*
39 * Declarations of static variables used in this file.
40 */
41
42static TkDisplay *gMacDisplay = NULL; /* Macintosh display. */
43static const char *macScreenName = ":0"; /* Default name of macintosh display. */
44
45/*
46 * Forward declarations of procedures used in this file.
47 */
48
49static XID MacXIdAlloc(Display *display);
50static int DefaultErrorHandler(Display* display, XErrorEvent* err_evt);
51
52/*
53 * Other declarations
54 */
55
56static int DestroyImage(XImage *image);
57static unsigned long ImageGetPixel(XImage *image, int x, int y);
58static int PutPixel(XImage *image, int x, int y, unsigned long pixel);
59#if 0
60static XImage *SubImage(XImage *image, int x, int y,
61	unsigned int width, unsigned int height);
62static int AddPixel(XImage *image, long value);
63#endif
64
65
66/*
67 *----------------------------------------------------------------------
68 *
69 * TkMacOSXDisplayChanged --
70 *
71 *	Called to set up initial screen info or when an event indicated
72 *	display (screen) change.
73 *
74 * Results:
75 *	None.
76 *
77 * Side effects:
78 *	May change info regarding the screen.
79 *
80 *----------------------------------------------------------------------
81 */
82
83void
84TkMacOSXDisplayChanged(Display *display)
85{
86    GDHandle graphicsDevice;
87    Screen *screen;
88    Rect bounds = {0, 0, 0, 0}, *maxBounds;
89
90    if (display == NULL || display->screens == NULL) {
91	return;
92    }
93    screen = display->screens;
94
95    graphicsDevice = GetMainDevice();
96    screen->root_depth	= (*(*graphicsDevice)->gdPMap)->cmpSize *
97			       (*(*graphicsDevice)->gdPMap)->cmpCount;
98    screen->height	= (*graphicsDevice)->gdRect.bottom -
99	(*graphicsDevice)->gdRect.top;
100    screen->width	= (*graphicsDevice)->gdRect.right -
101	(*graphicsDevice)->gdRect.left;
102
103    screen->mwidth	= (screen->width * 254 + 360) / 720;
104    screen->mheight	= (screen->height * 254 + 360) / 720;
105
106    maxBounds = (Rect*) screen->ext_data;
107    *maxBounds = bounds;
108    graphicsDevice = GetDeviceList();
109    while (graphicsDevice) {
110	OSStatus err;
111
112	err = ChkErr(GetAvailableWindowPositioningBounds, graphicsDevice,
113		&bounds);
114	if (err == noErr) {
115	    UnionRect(&bounds, maxBounds, maxBounds);
116	}
117	graphicsDevice = GetNextDevice(graphicsDevice);
118    }
119}
120
121/*
122 *----------------------------------------------------------------------
123 *
124 * TkpOpenDisplay --
125 *
126 *	Create the Display structure and fill it with device
127 *	specific information.
128 *
129 * Results:
130 *	Returns a Display structure on success or NULL on failure.
131 *
132 * Side effects:
133 *	Allocates a new Display structure.
134 *
135 *----------------------------------------------------------------------
136 */
137
138TkDisplay *
139TkpOpenDisplay(
140    CONST char *display_name)
141{
142    Display *display;
143    Screen *screen;
144    int fd = 0;
145    static Rect maxBounds = {0, 0, 0, 0};
146
147    if (gMacDisplay != NULL) {
148	if (strcmp(gMacDisplay->display->display_name, display_name) == 0) {
149	    return gMacDisplay;
150	} else {
151	    return NULL;
152	}
153    }
154
155    display = (Display *) ckalloc(sizeof(Display));
156    screen  = (Screen *) ckalloc(sizeof(Screen));
157    bzero(display, sizeof(Display));
158    bzero(screen, sizeof(Screen));
159
160    display->resource_alloc = MacXIdAlloc;
161    display->request	    = 0;
162    display->qlen	    = 0;
163    display->fd		    = fd;
164    display->screens	    = screen;
165    display->nscreens	    = 1;
166    display->default_screen = 0;
167    display->display_name   = (char*)macScreenName;
168
169    Gestalt(gestaltQuickdrawVersion, (long*)&display->proto_minor_version);
170    display->proto_major_version = 10;
171    display->proto_minor_version -= gestaltMacOSXQD;
172    display->vendor = "Apple";
173    Gestalt(gestaltSystemVersion, (long*)&display->release);
174
175    /*
176     * These screen bits never change
177     */
178    screen->root	= ROOT_ID;
179    screen->display	= display;
180    screen->black_pixel = 0x00000000 | PIXEL_MAGIC << 24;
181    screen->white_pixel = 0x00FFFFFF | PIXEL_MAGIC << 24;
182    screen->ext_data	= (XExtData*) &maxBounds;
183
184    screen->root_visual = (Visual *) ckalloc(sizeof(Visual));
185    screen->root_visual->visualid     = 0;
186    screen->root_visual->class	      = TrueColor;
187    screen->root_visual->red_mask     = 0x00FF0000;
188    screen->root_visual->green_mask   = 0x0000FF00;
189    screen->root_visual->blue_mask    = 0x000000FF;
190    screen->root_visual->bits_per_rgb = 24;
191    screen->root_visual->map_entries  = 256;
192
193    /*
194     * Initialize screen bits that may change
195     */
196    TkMacOSXDisplayChanged(display);
197
198    gMacDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay));
199
200    /*
201     * This is the quickest way to make sure that all the *Init
202     * flags get properly initialized
203     */
204
205    bzero(gMacDisplay, sizeof(TkDisplay));
206    gMacDisplay->display = display;
207    return gMacDisplay;
208}
209
210/*
211 *----------------------------------------------------------------------
212 *
213 * TkpCloseDisplay --
214 *
215 *	Deallocates a display structure created by TkpOpenDisplay.
216 *
217 * Results:
218 *	None.
219 *
220 * Side effects:
221 *	Frees memory.
222 *
223 *----------------------------------------------------------------------
224 */
225
226void
227TkpCloseDisplay(
228    TkDisplay *displayPtr)
229{
230    Display *display = displayPtr->display;
231    if (gMacDisplay != displayPtr) {
232	Tcl_Panic("TkpCloseDisplay: tried to call TkpCloseDisplay on bad display");
233    }
234
235    gMacDisplay = NULL;
236    if (display->screens != (Screen *) NULL) {
237	if (display->screens->root_visual != (Visual *) NULL) {
238	    ckfree((char *) display->screens->root_visual);
239	}
240	ckfree((char *) display->screens);
241    }
242    ckfree((char *) display);
243}
244
245/*
246 *----------------------------------------------------------------------
247 *
248 * TkClipCleanup --
249 *
250 *	This procedure is called to cleanup resources associated with
251 *	claiming clipboard ownership and for receiving selection get
252 *	results. This function is called in tkWindow.c. This has to be
253 *	called by the display cleanup function because we still need the
254 *	access display elements.
255 *
256 * Results:
257 *	None.
258 *
259 * Side effects:
260 *	Resources are freed - the clipboard may no longer be used.
261 *
262 *----------------------------------------------------------------------
263 */
264
265void
266TkClipCleanup(dispPtr)
267    TkDisplay *dispPtr; /* display associated with clipboard */
268{
269    /*
270     * Make sure that the local scrap is transfered to the global
271     * scrap if needed.
272     */
273
274    TkSuspendClipboard();
275
276    if (dispPtr->clipWindow != NULL) {
277	Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
278		dispPtr->applicationAtom);
279	Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
280		dispPtr->windowAtom);
281
282	Tk_DestroyWindow(dispPtr->clipWindow);
283	Tcl_Release((ClientData) dispPtr->clipWindow);
284	dispPtr->clipWindow = NULL;
285    }
286}
287
288/*
289 *----------------------------------------------------------------------
290 *
291 * MacXIdAlloc --
292 *
293 *	This procedure is invoked by Xlib as the resource allocator
294 *	for a display.
295 *
296 * Results:
297 *	The return value is an X resource identifier that isn't currently
298 *	in use.
299 *
300 * Side effects:
301 *	The identifier is removed from the stack of free identifiers,
302 *	if it was previously on the stack.
303 *
304 *----------------------------------------------------------------------
305 */
306
307static XID
308MacXIdAlloc(
309    Display *display)			/* Display for which to allocate. */
310{
311	static long int cur_id = 100;
312	/*
313	 * Some special XIds are reserved
314	 *   - this is why we start at 100
315	 */
316
317	return ++cur_id;
318}
319
320/*
321 *----------------------------------------------------------------------
322 *
323 * TkpWindowWasRecentlyDeleted --
324 *
325 *	Tries to determine whether the given window was recently deleted.
326 *	Called from the generic code error handler to attempt to deal with
327 *	async BadWindow errors under some circumstances.
328 *
329 * Results:
330 *	Always 0, we do not keep this information on the Mac, so we do not
331 *	know whether the window was destroyed.
332 *
333 * Side effects:
334 *	None.
335 *
336 *----------------------------------------------------------------------
337 */
338
339int
340TkpWindowWasRecentlyDeleted(
341    Window win,
342    TkDisplay *dispPtr)
343{
344    return 0;
345}
346
347/*
348 *----------------------------------------------------------------------
349 *
350 * DefaultErrorHandler --
351 *
352 *	This procedure is the default X error handler. Tk uses it's
353 *	own error handler so this call should never be called.
354 *
355 * Results:
356 *	None.
357 *
358 * Side effects:
359 *	This function will call panic and exit.
360 *
361 *----------------------------------------------------------------------
362 */
363
364static int
365DefaultErrorHandler(
366    Display* display,
367    XErrorEvent* err_evt)
368{
369    /*
370     * This call should never be called. Tk replaces
371     * it with its own error handler.
372     */
373    Tcl_Panic("Warning hit bogus error handler!");
374    return 0;
375}
376
377
378char *
379XGetAtomName(
380    Display * display,
381    Atom atom)
382{
383    display->request++;
384    return NULL;
385}
386
387int
388_XInitImageFuncPtrs(XImage *image)
389{
390    return 0;
391}
392
393XErrorHandler
394XSetErrorHandler(
395    XErrorHandler handler)
396{
397    return DefaultErrorHandler;
398}
399
400Window
401XRootWindow(Display *display, int screen_number)
402{
403    display->request++;
404    return ROOT_ID;
405}
406
407int
408XGetGeometry(display, d, root_return, x_return, y_return, width_return,
409	height_return, border_width_return, depth_return)
410    Display* display;
411    Drawable d;
412    Window* root_return;
413    int* x_return;
414    int* y_return;
415    unsigned int* width_return;
416    unsigned int* height_return;
417    unsigned int* border_width_return;
418    unsigned int* depth_return;
419{
420    TkWindow *winPtr = ((MacDrawable *) d)->winPtr;
421
422    display->request++;
423    *root_return = ROOT_ID;
424    if (winPtr) {
425	*x_return = Tk_X(winPtr);
426	*y_return = Tk_Y(winPtr);
427	*width_return = Tk_Width(winPtr);
428	*height_return = Tk_Height(winPtr);
429	*border_width_return = winPtr->changes.border_width;
430	*depth_return = Tk_Depth(winPtr);
431    } else {
432	Rect boundsRect;
433	CGrafPtr destPort = TkMacOSXGetDrawablePort(d);
434
435	GetPortBounds(destPort, &boundsRect);
436	*x_return = boundsRect.left;
437	*y_return =  boundsRect.top;
438	*width_return = boundsRect.right - boundsRect.left;
439	*height_return = boundsRect.bottom - boundsRect.top;
440	*border_width_return = 0;
441	*depth_return = 32;
442    }
443    return 1;
444}
445
446void
447XChangeProperty(
448    Display* display,
449    Window w,
450    Atom property,
451    Atom type,
452    int format,
453    int mode,
454    _Xconst unsigned char* data,
455    int nelements)
456{
457    Debugger();
458}
459
460void
461XSelectInput(
462    Display* display,
463    Window w,
464    long event_mask)
465{
466    Debugger();
467}
468
469void
470XBell(
471    Display* display,
472    int percent)
473{
474    SysBeep(percent);
475}
476
477#if 0
478void
479XSetWMNormalHints(
480    Display* display,
481    Window w,
482    XSizeHints* hints)
483{
484    /*
485     * Do nothing. Shouldn't even be called.
486     */
487}
488
489XSizeHints *
490XAllocSizeHints(void)
491{
492    /*
493     * Always return NULL. Tk code checks to see if NULL
494     * is returned & does nothing if it is.
495     */
496
497    return NULL;
498}
499#endif
500
501GContext
502XGContextFromGC(
503    GC gc)
504{
505    /*
506     * TODO: currently a no-op
507     */
508
509    return 0;
510}
511
512Status
513XSendEvent(
514    Display* display,
515    Window w,
516    Bool propagate,
517    long event_mask,
518    XEvent* event_send)
519{
520    Debugger();
521    return 0;
522}
523
524void
525XClearWindow(
526    Display* display,
527    Window w)
528{
529}
530
531/*
532void
533XDrawPoint(
534    Display* display,
535    Drawable d,
536    GC gc,
537    int x,
538    int y)
539{
540}
541
542void
543XDrawPoints(
544    Display* display,
545    Drawable d,
546    GC gc,
547    XPoint* points,
548    int npoints,
549    int mode)
550{
551}
552*/
553
554void
555XWarpPointer(
556    Display* display,
557    Window src_w,
558    Window dest_w,
559    int src_x,
560    int src_y,
561    unsigned int src_width,
562    unsigned int src_height,
563    int dest_x,
564    int dest_y)
565{
566}
567
568void
569XQueryColor(
570    Display* display,
571    Colormap colormap,
572    XColor* def_in_out)
573{
574    unsigned long p;
575    unsigned char r, g, b;
576    XColor *d = def_in_out;
577
578    p		= d->pixel;
579    r		= (p & 0x00FF0000) >> 16;
580    g		= (p & 0x0000FF00) >> 8;
581    b		= (p & 0x000000FF);
582    d->red	= (r << 8) | r;
583    d->green	= (g << 8) | g;
584    d->blue	= (b << 8) | b;
585    d->flags	= DoRed|DoGreen|DoBlue;
586    d->pad	= 0;
587}
588
589void
590XQueryColors(
591    Display* display,
592    Colormap colormap,
593    XColor* defs_in_out,
594    int ncolors)
595{
596    int i;
597    unsigned long p;
598    unsigned char r, g, b;
599    XColor *d = defs_in_out;
600
601    for (i = 0; i < ncolors; i++, d++) {
602	p		= d->pixel;
603	r		= (p & 0x00FF0000) >> 16;
604	g		= (p & 0x0000FF00) >> 8;
605	b		= (p & 0x000000FF);
606	d->red		= (r << 8) | r;
607	d->green	= (g << 8) | g;
608	d->blue		= (b << 8) | b;
609	d->flags	= DoRed|DoGreen|DoBlue;
610	d->pad		= 0;
611    }
612}
613
614int
615XQueryTree(display, w, root_return, parent_return, children_return,
616	nchildren_return)
617    Display* display;
618    Window w;
619    Window* root_return;
620    Window* parent_return;
621    Window** children_return;
622    unsigned int* nchildren_return;
623{
624    return 0;
625}
626
627
628int
629XGetWindowProperty(
630    Display *display,
631    Window w,
632    Atom property,
633    long long_offset,
634    long long_length,
635    Bool delete,
636    Atom req_type,
637    Atom *actual_type_return,
638    int *actual_format_return,
639    unsigned long *nitems_return,
640    unsigned long *bytes_after_return,
641    unsigned char ** prop_return)
642{
643    display->request++;
644    *actual_type_return = None;
645    *actual_format_return = *bytes_after_return = 0;
646    *nitems_return = 0;
647    return 0;
648}
649
650void
651XRefreshKeyboardMapping( XMappingEvent* x)
652{
653    /* used by tkXEvent.c */
654    Debugger();
655}
656
657void
658XSetIconName(
659    Display* display,
660    Window w,
661    const char *icon_name)
662{
663    /*
664     * This is a no-op, no icon name for Macs.
665     */
666    display->request++;
667}
668
669void
670XForceScreenSaver(
671    Display* display,
672    int mode)
673{
674    /*
675     * This function is just a no-op. It is defined to
676     * reset the screen saver. However, there is no real
677     * way to do this on a Mac. Let me know if there is!
678     */
679    display->request++;
680}
681
682void
683Tk_FreeXId(
684    Display *display,
685    XID xid)
686{
687    /* no-op function needed for stubs implementation. */
688}
689
690int
691XSync(
692    Display *display,
693    Bool flag)
694{
695    TkMacOSXFlushWindows();
696    display->request++;
697    return 0;
698}
699
700#if 0
701int
702XSetClipRectangles(
703    Display *d,
704    GC gc,
705    int clip_x_origin,
706    int clip_y_origin,
707    XRectangle* rectangles,
708    int n,
709    int ordering)
710{
711    TkRegion clipRgn = TkCreateRegion();
712
713    while (n--) {
714	XRectangle rect = *rectangles;
715
716	rect.x += clip_x_origin;
717	rect.y += clip_y_origin;
718	TkUnionRectWithRegion(&rect, clipRgn, clipRgn);
719	rectangles++;
720    }
721    TkSetRegion(d, gc, clipRgn);
722    TkDestroyRegion(clipRgn);
723    return 1;
724}
725#endif
726
727/*
728 *----------------------------------------------------------------------
729 *
730 * TkGetServerInfo --
731 *
732 *	Given a window, this procedure returns information about
733 *	the window server for that window. This procedure provides
734 *	the guts of the "winfo server" command.
735 *
736 * Results:
737 *	None.
738 *
739 * Side effects:
740 *	None.
741 *
742 *----------------------------------------------------------------------
743 */
744
745void
746TkGetServerInfo(
747    Tcl_Interp *interp,		/* The server information is returned in
748				 * this interpreter's result. */
749    Tk_Window tkwin)		/* Token for window; this selects a
750				 * particular display and server. */
751{
752    char buffer[8 + TCL_INTEGER_SPACE * 2];
753    char buffer2[TCL_INTEGER_SPACE];
754
755    sprintf(buffer, "QD%dR%x ", ProtocolVersion(Tk_Display(tkwin)),
756	    ProtocolRevision(Tk_Display(tkwin)));
757    sprintf(buffer2, " %x", VendorRelease(Tk_Display(tkwin)));
758    Tcl_AppendResult(interp, buffer, ServerVendor(Tk_Display(tkwin)),
759	    buffer2, NULL);
760}
761
762#pragma mark XImage handling
763/*
764 *----------------------------------------------------------------------
765 *
766 * XCreateImage --
767 *
768 *	Allocates storage for a new XImage.
769 *
770 * Results:
771 *	Returns a newly allocated XImage.
772 *
773 * Side effects:
774 *	None.
775 *
776 *----------------------------------------------------------------------
777 */
778
779XImage *
780XCreateImage(
781    Display* display,
782    Visual* visual,
783    unsigned int depth,
784    int format,
785    int offset,
786    char* data,
787    unsigned int width,
788    unsigned int height,
789    int bitmap_pad,
790    int bytes_per_line)
791{
792    XImage *ximage;
793
794    display->request++;
795    ximage = (XImage *) ckalloc(sizeof(XImage));
796
797    ximage->height = height;
798    ximage->width = width;
799    ximage->depth = depth;
800    ximage->xoffset = offset;
801    ximage->format = format;
802    ximage->data = data;
803
804    if (format == ZPixmap) {
805	ximage->bits_per_pixel = 32;
806	ximage->bitmap_unit = 32;
807    } else {
808	ximage->bits_per_pixel = 1;
809	ximage->bitmap_unit = 8;
810    }
811    if (bitmap_pad) {
812	ximage->bitmap_pad = bitmap_pad;
813    } else {
814	/* Use 16 byte alignment for best Quartz perfomance */
815	ximage->bitmap_pad = 128;
816    }
817    if (bytes_per_line) {
818	ximage->bytes_per_line = bytes_per_line;
819    } else {
820	ximage->bytes_per_line = ((width * ximage->bits_per_pixel +
821		(ximage->bitmap_pad - 1)) >> 3) &
822		~((ximage->bitmap_pad >> 3) - 1);
823    }
824#ifdef WORDS_BIGENDIAN
825    ximage->byte_order = MSBFirst;
826    ximage->bitmap_bit_order = MSBFirst;
827#else
828    ximage->byte_order = LSBFirst;
829    ximage->bitmap_bit_order = LSBFirst;
830#endif
831    ximage->red_mask = 0x00FF0000;
832    ximage->green_mask = 0x0000FF00;
833    ximage->blue_mask = 0x000000FF;
834    ximage->obdata = NULL;
835    ximage->f.create_image = NULL;
836    ximage->f.destroy_image = DestroyImage;
837    ximage->f.get_pixel = ImageGetPixel;
838    ximage->f.put_pixel = PutPixel;
839    ximage->f.sub_image = NULL;
840    ximage->f.add_pixel = NULL;
841
842    return ximage;
843}
844
845/*
846 *----------------------------------------------------------------------
847 *
848 * XGetImage --
849 *
850 *	This function copies data from a pixmap or window into an XImage.
851 *
852 * Results:
853 *	Returns a newly allocated image containing the data from the given
854 *	rectangle of the given drawable.
855 *
856 * Side effects:
857 *	None.
858 *
859 *----------------------------------------------------------------------
860 */
861
862XImage *
863XGetImage(
864    Display *display,
865    Drawable d,
866    int x,
867    int y,
868    unsigned int width,
869    unsigned int height,
870    unsigned long plane_mask,
871    int format)
872{
873    XImage *   imagePtr = NULL;
874    Pixmap     pixmap = (Pixmap) NULL;
875    Tk_Window  win = (Tk_Window) ((MacDrawable *) d)->winPtr;
876    GC	       gc;
877    int	       depth = 32;
878    int	       offset = 0;
879    int	       bitmap_pad = 32;
880    int	       bytes_per_line = 0;
881
882    if (TkMacOSXGetDrawablePort(d)) {
883	if (format == ZPixmap) {
884	    if (width > 0 && height > 0) {
885		/* Tk_GetPixmap fails for zero width or height */
886		pixmap = Tk_GetPixmap(display, d, width, height, depth);
887	    }
888	    if (win) {
889		XGCValues values;
890		gc = Tk_GetGC(win, 0, &values);
891	    } else {
892		gc = XCreateGC(display, pixmap, 0, NULL);
893	    }
894	    if (pixmap) {
895		XCopyArea(display, d, pixmap, gc, x, y, width, height, 0, 0);
896	    }
897	    imagePtr = XCreateImage(display, NULL, depth, format, offset,
898		(char*)TkMacOSXGetDrawablePort(pixmap),
899		width, height, bitmap_pad, bytes_per_line);
900	    /* Track Pixmap underlying the XImage in the unused obdata field *
901	     * so that we can treat XImages coming from XGetImage specially. */
902	    imagePtr->obdata = (XPointer) pixmap;
903	    if (!win) {
904		XFreeGC(display, gc);
905	    }
906	} else {
907	    TkpDisplayWarning(
908		"XGetImage: only ZPixmap types are implemented",
909		"XGetImage Failure");
910	}
911    }
912    return imagePtr;
913}
914
915/*
916 *----------------------------------------------------------------------
917 *
918 * DestroyImage --
919 *
920 *	Destroys storage associated with an image.
921 *
922 * Results:
923 *	None.
924 *
925 * Side effects:
926 *	Deallocates the image.
927 *
928 *----------------------------------------------------------------------
929 */
930
931static int
932DestroyImage(
933    XImage *image)
934{
935    if (image) {
936	if (image->obdata) {
937	    Tk_FreePixmap((Display*) gMacDisplay, (Pixmap) image->obdata);
938	} else if (image->data) {
939	    ckfree(image->data);
940	}
941	ckfree((char*) image);
942    }
943    return 0;
944}
945
946/*
947 *----------------------------------------------------------------------
948 *
949 * ImageGetPixel --
950 *
951 *	Get a single pixel from an image.
952 *
953 * Results:
954 *	Returns the 32 bit pixel value.
955 *
956 * Side effects:
957 *	None.
958 *
959 *----------------------------------------------------------------------
960 */
961
962static unsigned long
963ImageGetPixel(
964    XImage *image,
965    int x,
966    int y)
967{
968    CGrafPtr destPort, savePort;
969    Boolean portChanged;
970    RGBColor cPix;
971    unsigned long r, g, b, c;
972
973    destPort = (CGrafPtr)image->data;
974    portChanged = QDSwapPort(destPort, &savePort);
975    GetCPixel(x, y, &cPix);
976    if (image->obdata) {
977	/* Image from XGetImage, 16 bit color values */
978	r = (cPix . red) >> 8;
979	g = (cPix . green) >> 8;
980	b = (cPix . blue) >> 8;
981    } else {
982	r = cPix . red;
983	g = cPix . green;
984	b = cPix . blue;
985    }
986    c = (r<<16)|(g<<8)|(b);
987    if (portChanged) {
988	QDSwapPort(savePort, NULL);
989    }
990    return c;
991}
992
993/*
994 *----------------------------------------------------------------------
995 *
996 * PutPixel --
997 *
998 *	Set a single pixel in an image.
999 *
1000 * Results:
1001 *	None.
1002 *
1003 * Side effects:
1004 *	None.
1005 *
1006 *----------------------------------------------------------------------
1007 */
1008
1009static int
1010PutPixel(
1011    XImage *image,
1012    int x,
1013    int y,
1014    unsigned long pixel)
1015{
1016    CGrafPtr destPort, savePort;
1017    Boolean portChanged;
1018    RGBColor cPix;
1019    unsigned long r, g, b;
1020
1021    destPort = (CGrafPtr)image->data;
1022    portChanged = QDSwapPort(destPort, &savePort);
1023    r  = (pixel & image->red_mask)>>16;
1024    g  = (pixel & image->green_mask)>>8;
1025    b  = (pixel & image->blue_mask);
1026    if (image->obdata) {
1027	/* Image from XGetImage, 16 bit color values */
1028	cPix . red = r << 8;
1029	cPix . green = g << 8;
1030	cPix . blue = b << 8;
1031    } else {
1032	cPix . red = r;
1033	cPix . green = g;
1034	cPix . blue = b;
1035    }
1036    SetCPixel(x, y, &cPix);
1037    if (portChanged) {
1038	QDSwapPort(savePort, NULL);
1039    }
1040    return 0;
1041}
1042
1043#if 0
1044static XImage *
1045SubImage(
1046    XImage *image,
1047    int x,
1048    int y,
1049    unsigned int width,
1050    unsigned int height)
1051{
1052    Debugger();
1053    return NULL;
1054}
1055
1056static int
1057AddPixel(
1058    XImage *image,
1059    long value)
1060{
1061    Debugger();
1062    return 0;
1063}
1064#endif
1065
1066/*
1067 *----------------------------------------------------------------------
1068 *
1069 * XChangeWindowAttributes, XSetWindowBackground,
1070 * XSetWindowBackgroundPixmap, XSetWindowBorder, XSetWindowBorderPixmap,
1071 * XSetWindowBorderWidth, XSetWindowColormap
1072 *
1073 *	These functions are all no-ops. They all have equivilent
1074 *	Tk calls that should always be used instead.
1075 *
1076 * Results:
1077 *	None.
1078 *
1079 * Side effects:
1080 *	None.
1081 *
1082 *----------------------------------------------------------------------
1083 */
1084
1085void
1086XChangeWindowAttributes(
1087    Display* display,
1088    Window w,
1089    unsigned long value_mask,
1090    XSetWindowAttributes* attributes)
1091{
1092}
1093
1094void
1095XSetWindowBackground(
1096	Display *display,
1097	Window window,
1098	unsigned long value)
1099{
1100}
1101
1102void
1103XSetWindowBackgroundPixmap(
1104    Display* display,
1105    Window w,
1106    Pixmap background_pixmap)
1107{
1108}
1109
1110void
1111XSetWindowBorder(
1112    Display* display,
1113    Window w,
1114    unsigned long border_pixel)
1115{
1116}
1117
1118void
1119XSetWindowBorderPixmap(
1120    Display* display,
1121    Window w,
1122    Pixmap border_pixmap)
1123{
1124}
1125
1126void
1127XSetWindowBorderWidth(
1128    Display* display,
1129    Window w,
1130    unsigned int width)
1131{
1132}
1133
1134void
1135XSetWindowColormap(
1136    Display* display,
1137    Window w,
1138    Colormap colormap)
1139{
1140    Debugger();
1141}
1142
1143Status
1144XStringListToTextProperty(
1145    char** list,
1146    int count,
1147    XTextProperty* text_prop_return)
1148{
1149    Debugger();
1150    return (Status) 0;
1151}
1152void
1153XSetWMClientMachine(
1154    Display* display,
1155    Window w,
1156    XTextProperty* text_prop)
1157{
1158    Debugger();
1159}
1160XIC
1161XCreateIC(
1162    void)
1163{
1164    Debugger();
1165    return (XIC) 0;
1166}
1167
1168/*
1169 *----------------------------------------------------------------------
1170 *
1171 * TkGetDefaultScreenName --
1172 *
1173 *	Returns the name of the screen that Tk should use during
1174 *	initialization.
1175 *
1176 * Results:
1177 *	Returns a statically allocated string.
1178 *
1179 * Side effects:
1180 *	None.
1181 *
1182 *----------------------------------------------------------------------
1183 */
1184
1185CONST char *
1186TkGetDefaultScreenName(
1187    Tcl_Interp *interp,		/* Not used. */
1188    CONST char *screenName)		/* If NULL, use default string. */
1189{
1190#if 0
1191    if ((screenName == NULL) || (screenName[0] == '\0')) {
1192	screenName = macScreenName;
1193    }
1194    return screenName;
1195#endif
1196    return macScreenName;
1197}
1198#if 0
1199
1200/*
1201 *----------------------------------------------------------------------
1202 *
1203 * Tk_GetUserInactiveTime --
1204 *
1205 *	Return the number of milliseconds the user was inactive.
1206 *
1207 * Results:
1208 *	The number of milliseconds the user has been inactive,
1209 *	or -1 if querying the inactive time is not supported.
1210 *
1211 * Side effects:
1212 *	None.
1213 *----------------------------------------------------------------------
1214 */
1215
1216long
1217Tk_GetUserInactiveTime(Display *dpy)
1218{
1219    io_registry_entry_t regEntry;
1220    CFMutableDictionaryRef props = NULL;
1221    CFTypeRef timeObj;
1222    long ret = -1l;
1223    uint64_t time;
1224
1225    regEntry = IOServiceGetMatchingService(kIOMasterPortDefault,
1226	    IOServiceMatching("IOHIDSystem"));
1227
1228    if (regEntry == 0) {
1229	return -1l;
1230    }
1231
1232    IOReturn result = IORegistryEntryCreateCFProperties(regEntry, &props,
1233	    kCFAllocatorDefault, 0);
1234    IOObjectRelease(regEntry);
1235
1236    if (result != KERN_SUCCESS || props == NULL) {
1237	return -1l;
1238    }
1239
1240    timeObj = CFDictionaryGetValue(props, CFSTR("HIDIdleTime"));
1241
1242    if (timeObj) {
1243	CFTypeID type = CFGetTypeID(timeObj);
1244
1245	if (type == CFDataGetTypeID()) { /* Jaguar */
1246	    CFDataGetBytes((CFDataRef) timeObj,
1247		    CFRangeMake(0, sizeof(time)), (UInt8 *) &time);
1248	    /* Convert nanoseconds to milliseconds. */
1249	    /* ret /= kMillisecondScale; */
1250	    ret = (long)(time/kMillisecondScale);
1251	} else if (type == CFNumberGetTypeID()) { /* Panther+ */
1252	    CFNumberGetValue((CFNumberRef)timeObj,
1253		    kCFNumberSInt64Type, &time);
1254	    /* Convert nanoseconds to milliseconds. */
1255	    /* ret /= kMillisecondScale; */
1256	    ret = (long)(time/kMillisecondScale);
1257	} else {
1258	    ret = -1l;
1259	}
1260    }
1261    /* Cleanup */
1262    CFRelease(props);
1263
1264    return ret;
1265}
1266
1267/*
1268 *----------------------------------------------------------------------
1269 *
1270 * Tk_ResetUserInactiveTime --
1271 *
1272 *	Reset the user inactivity timer
1273 *
1274 * Results:
1275 *	none
1276 *
1277 * Side effects:
1278 *	The user inactivity timer of the underlaying windowing system
1279 *	is reset to zero.
1280 *
1281 *----------------------------------------------------------------------
1282 */
1283
1284void
1285Tk_ResetUserInactiveTime(Display *dpy)
1286{
1287    UpdateSystemActivity(UsrActivity);
1288}
1289#endif
1290