/* Graphical user interface functions for Mac OS.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "epaths.h"
#include "termhooks.h"
#include "coding.h"
-#include "ccl.h"
#include "systime.h"
/* #include "bitmaps/gray.xbm" */
#include <stdlib.h>
#include <string.h>
-#ifndef MAC_OSX
-#include <alloca.h>
-#endif
-
-#ifdef MAC_OSX
-#include <QuickTime/QuickTime.h>
-#else /* not MAC_OSX */
-#include <Windows.h>
-#include <Gestalt.h>
-#include <TextUtils.h>
-#endif /* not MAC_OSX */
/*extern void free_frame_menubar ();
extern double atof ();
extern int mac_initialized;
-/* Functions in macterm.c. */
-extern void x_set_window_size (struct frame *, int, int, int);
-extern void x_make_frame_visible (struct frame *);
-extern struct mac_display_info *mac_term_init (Lisp_Object, char *, char *);
-extern struct font_info *x_get_font_info (FRAME_PTR, int);
-extern struct font_info *x_load_font (struct frame *, char *, int);
-extern void x_find_ccl_program (struct font_info *);
-extern struct font_info *x_query_font (struct frame *, char *);
-extern void mac_initialize ();
-extern Pixmap XCreatePixmap (Display *, WindowPtr, unsigned int, unsigned int, unsigned int);
-extern Pixmap XCreatePixmapFromBitmapData (Display *, WindowPtr, char *, unsigned int, unsigned int, unsigned long, unsigned long, unsigned int);
-extern void XFreePixmap (Display *, Pixmap);
-extern void XSetForeground (Display *, GC, unsigned long);
-extern void mac_draw_line_to_pixmap (Display *, Pixmap, GC, int, int, int, int);
-
/* compare two strings ignoring case */
Lisp_Object,
char *, char *,
int));
+
+extern void mac_get_window_bounds P_ ((struct frame *, Rect *, Rect *));
+
/* Store the screen positions of frame F into XPTR and YPTR.
These are the positions of the containing window manager window,
not Emacs's own window. */
FRAME_PTR f;
int *xptr, *yptr;
{
- Point pt;
- GrafPtr oldport;
+ Rect inner, outer;
-#ifdef TARGET_API_MAC_CARBON
- {
- Rect r;
+ mac_get_window_bounds (f, &inner, &outer);
- GetWindowPortBounds (f->output_data.mac->mWP, &r);
- SetPt (&pt, r.left, r.top);
- }
-#else /* not TARGET_API_MAC_CARBON */
- SetPt (&pt,
- f->output_data.mac->mWP->portRect.left,
- f->output_data.mac->mWP->portRect.top);
-#endif /* not TARGET_API_MAC_CARBON */
- GetPort (&oldport);
- LocalToGlobal (&pt);
- SetPort (oldport);
-
- /* MAC has no frame pixel diff. */
- f->x_pixels_diff = 0;
- f->y_pixels_diff = 0;
-
- *xptr = pt.h;
- *yptr = pt.v;
+ f->x_pixels_diff = inner.left - outer.left;
+ f->y_pixels_diff = inner.top - outer.top;
+
+ *xptr = outer.left;
+ *yptr = outer.top;
}
\f
if (FRAME_MAC_WINDOW (f))
{
if (STRING_MULTIBYTE (name))
-#if 0 /* MAC_TODO: encoding title string */
- name = ENCODE_SYSTEM (name);
+#if TARGET_API_MAC_CARBON
+ name = ENCODE_UTF_8 (name);
#else
return;
#endif
BLOCK_INPUT;
{
+#if TARGET_API_MAC_CARBON
+ CFStringRef windowTitle =
+ CFStringCreateWithCString (NULL, SDATA (name),
+ kCFStringEncodingUTF8);
+
+ SetWindowTitleWithCFString (FRAME_MAC_WINDOW (f), windowTitle);
+ CFRelease (windowTitle);
+#else
Str255 windowTitle;
if (strlen (SDATA (name)) < 255)
{
c2pstr (windowTitle);
SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
}
+#endif
}
UNBLOCK_INPUT;
if (FRAME_MAC_WINDOW (f))
{
if (STRING_MULTIBYTE (name))
-#if 0 /* MAC_TODO: encoding title string */
- name = ENCODE_SYSTEM (name);
+#if TARGET_API_MAC_CARBON
+ name = ENCODE_UTF_8 (name);
#else
return;
#endif
BLOCK_INPUT;
{
+#if TARGET_API_MAC_CARBON
+ CFStringRef windowTitle =
+ CFStringCreateWithCString (NULL, SDATA (name),
+ kCFStringEncodingUTF8);
+
+ SetWindowTitleWithCFString (FRAME_MAC_WINDOW (f), windowTitle);
+ CFRelease (windowTitle);
+#else
Str255 windowTitle;
if (strlen (SDATA (name)) < 255)
{
c2pstr (windowTitle);
SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
}
+#endif
}
UNBLOCK_INPUT;
f->output_data.mac = (struct mac_output *) xmalloc (sizeof (struct mac_output));
bzero (f->output_data.mac, sizeof (struct mac_output));
FRAME_FONTSET (f) = -1;
- f->output_data.mac->scroll_bar_foreground_pixel = -1;
- f->output_data.mac->scroll_bar_background_pixel = -1;
record_unwind_protect (unwind_create_frame, frame);
f->icon_name
if (!NILP (parent))
{
- f->output_data.mac->parent_desc = (Window) parent;
+ f->output_data.mac->parent_desc = (Window) XFASTINT (parent);
f->output_data.mac->explicit_parent = 1;
}
else
x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
"menuBar", "MenuBar", RES_TYPE_NUMBER);
- x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
+ x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
"toolBar", "ToolBar", RES_TYPE_NUMBER);
x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
"bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
- /* MAC_TODO: specify 1 below when toolbars are implemented. */
- window_prompting = x_figure_window_size (f, parms, 0);
+#if TARGET_API_MAC_CARBON
+ f->output_data.mac->text_cursor = kThemeIBeamCursor;
+ f->output_data.mac->nontext_cursor = kThemeArrowCursor;
+ f->output_data.mac->modeline_cursor = kThemeArrowCursor;
+ f->output_data.mac->hand_cursor = kThemePointingHandCursor;
+ f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
+ f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
+#else
+ f->output_data.mac->text_cursor = GetCursor (iBeamCursor);
+ f->output_data.mac->nontext_cursor = &arrow_cursor;
+ f->output_data.mac->modeline_cursor = &arrow_cursor;
+ f->output_data.mac->hand_cursor = &arrow_cursor;
+ f->output_data.mac->hourglass_cursor = GetCursor (watchCursor);
+ f->output_data.mac->horizontal_drag_cursor = &arrow_cursor;
+#endif
+
+ /* Compute the size of the window. */
+ window_prompting = x_figure_window_size (f, parms, 1);
tem = mac_get_arg (parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
f->no_split = minibuffer_only || EQ (tem, Qt);
- /* Create the window. Add the tool-bar height to the initial frame
- height so that the user gets a text display area of the size he
- specified with -g or via the registry. Later changes of the
- tool-bar height don't change the frame size. This is done so that
- users can create tall Emacs frames without having to guess how
- tall the tool-bar will get. */
- FRAME_LINES (f) += FRAME_TOOL_BAR_LINES (f);
-
/* mac_window (f, window_prompting, minibuffer_only); */
make_mac_frame (f);
x_icon (f, parms);
-
x_make_gc (f);
/* Now consider the frame official. */
x_default_parameter (f, parms, Qcursor_type, Qbox,
"cursorType", "CursorType", RES_TYPE_SYMBOL);
x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
- "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
+ "scrollBarWidth", "ScrollBarWidth",
+ RES_TYPE_NUMBER);
/* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
Change will not be effected unless different from the current
width = FRAME_COLS (f);
height = FRAME_LINES (f);
- FRAME_LINES (f) = 0;
SET_FRAME_COLS (f, 0);
+ FRAME_LINES (f) = 0;
change_frame_size (f, height, width, 1, 0, 0);
- /* Set up faces after all frame parameters are known. */
- call1 (Qface_set_after_frame_default, frame);
-
#if 0 /* MAC_TODO: when we have window manager hints */
/* Tell the server what size and position, etc, we want, and how
badly we want them. This should be done after we have the menu
{
struct mac_display_info *dpyinfo = check_x_display_info (display);
- /* MAC_TODO: check whether this is right */
- return make_number (dpyinfo->n_planes >= 8 ? 256 : 1 << dpyinfo->n_planes - 1);
+ /* We force 24+ bit depths to 24-bit to prevent an overflow. */
+ return make_number (1 << min (dpyinfo->n_planes, 24));
}
DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
(display)
Lisp_Object display;
{
- int mac_major_version, mac_minor_version;
+ int mac_major_version;
SInt32 response;
if (Gestalt (gestaltSystemVersion, &response) != noErr)
error ("Cannot get Mac OS version");
- mac_major_version = (response >> 8) & 0xf;
- mac_minor_version = (response >> 4) & 0xf;
+ mac_major_version = (response >> 8) & 0xff;
+ /* convert BCD to int */
+ mac_major_version -= (mac_major_version >> 4) * 6;
return Fcons (make_number (mac_major_version),
- Fcons (make_number (mac_minor_version), Qnil));
+ Fcons (make_number ((response >> 4) & 0xf),
+ Fcons (make_number (response & 0xf),
+ Qnil)));
}
DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
/* MAC_TODO: this is an approximation, and only of the main display */
struct mac_display_info *dpyinfo = check_x_display_info (display);
- short h, v;
- ScreenRes (&h, &v);
-
- return make_number ((int) (v / 72.0 * 25.4));
+ return make_number ((int) (dpyinfo->height * 25.4 / dpyinfo->resy));
}
DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
/* MAC_TODO: this is an approximation, and only of the main display */
struct mac_display_info *dpyinfo = check_x_display_info (display);
- short h, v;
-
- ScreenRes (&h, &v);
- return make_number ((int) (h / 72.0 * 25.4));
+ return make_number ((int) (dpyinfo->width * 25.4 / dpyinfo->resx));
}
DEFUN ("x-display-backing-store", Fx_display_backing_store,
***********************************************************************/
static Lisp_Object x_create_tip_frame P_ ((struct mac_display_info *,
- Lisp_Object));
+ Lisp_Object, Lisp_Object));
+static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
+ Lisp_Object, int, int, int *, int *));
-/* The frame of a currently visible tooltip, or null. */
+/* The frame of a currently visible tooltip. */
Lisp_Object tip_frame;
Lisp_Object last_show_tip_args;
+/* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
+
+Lisp_Object Vx_max_tooltip_size;
+
+
+static Lisp_Object
+unwind_create_tip_frame (frame)
+ Lisp_Object frame;
+{
+ Lisp_Object deleted;
+
+ deleted = unwind_create_frame (frame);
+ if (EQ (deleted, Qt))
+ {
+ tip_window = NULL;
+ tip_frame = Qnil;
+ }
+
+ return deleted;
+}
+
+
/* Create a frame for a tooltip on the display described by DPYINFO.
- PARMS is a list of frame parameters. Value is the frame. */
+ PARMS is a list of frame parameters. TEXT is the string to
+ display in the tip frame. Value is the frame.
+
+ Note that functions called here, esp. x_default_parameter can
+ signal errors, for instance when a specified color name is
+ undefined. We have to make sure that we're in a consistent state
+ when this happens. */
static Lisp_Object
-x_create_tip_frame (dpyinfo, parms)
+x_create_tip_frame (dpyinfo, parms, text)
struct mac_display_info *dpyinfo;
- Lisp_Object parms;
+ Lisp_Object parms, text;
{
-#if 0 /* MAC_TODO : Mac version */
struct frame *f;
Lisp_Object frame, tem;
Lisp_Object name;
int count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3;
struct kboard *kb;
+ int face_change_count_before = face_change_count;
+ Lisp_Object buffer;
+ struct buffer *old_buffer;
- check_x ();
+ check_mac ();
/* Use this general default value to start with until we know if
this frame has a specified name. */
#endif
/* Get the name of the frame to use for resource lookup. */
- name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
+ name = mac_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
if (!STRINGP (name)
&& !EQ (name, Qunbound)
&& !NILP (name))
frame = Qnil;
GCPRO3 (parms, name, frame);
- tip_frame = f = make_frame (1);
+ f = make_frame (1);
XSETFRAME (frame, f);
+
+ buffer = Fget_buffer_create (build_string (" *tip*"));
+ Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
+ old_buffer = current_buffer;
+ set_buffer_internal_1 (XBUFFER (buffer));
+ current_buffer->truncate_lines = Qnil;
+ specbind (Qinhibit_read_only, Qt);
+ specbind (Qinhibit_modification_hooks, Qt);
+ Ferase_buffer ();
+ Finsert (1, &text);
+ set_buffer_internal_1 (old_buffer);
+
FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+ record_unwind_protect (unwind_create_tip_frame, frame);
- f->output_method = output_w32;
- f->output_data.w32 =
- (struct w32_output *) xmalloc (sizeof (struct w32_output));
- bzero (f->output_data.w32, sizeof (struct w32_output));
-#if 0
- f->output_data.w32->icon_bitmap = -1;
-#endif
- FRAME_FONTSET (f) = -1;
+ /* By setting the output method, we're essentially saying that
+ the frame is live, as per FRAME_LIVE_P. If we get a signal
+ from this point on, x_destroy_window might screw up reference
+ counts etc. */
+ f->output_method = output_mac;
+ f->output_data.mac =
+ (struct mac_output *) xmalloc (sizeof (struct mac_output));
+ bzero (f->output_data.mac, sizeof (struct mac_output));
+
+ FRAME_FONTSET (f) = -1;
f->icon_name = Qnil;
+#if 0 /* GLYPH_DEBUG TODO: image support. */
+ image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
+ dpyinfo_refcount = dpyinfo->reference_count;
+#endif /* GLYPH_DEBUG */
#ifdef MULTI_KBOARD
FRAME_KBOARD (f) = kb;
#endif
- f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
- f->output_data.w32->explicit_parent = 0;
+ f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
+ f->output_data.mac->explicit_parent = 0;
/* Set the name; the functions to which we pass f expect the name to
be set. */
if (EQ (name, Qunbound) || NILP (name))
{
- f->name = build_string (dpyinfo->x_id_name);
+ f->name = build_string (dpyinfo->mac_id_name);
f->explicit_name = 0;
}
else
specbind (Qx_resource_name, name);
}
- /* Extract the window parameters from the supplied values
- that are needed to determine window geometry. */
+ /* Extract the window parameters from the supplied values that are
+ needed to determine window geometry. */
{
Lisp_Object font;
- font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
+ font = mac_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
BLOCK_INPUT;
/* First, try whatever font the caller has specified. */
}
/* Try out a font which we hope has bold and italic variations. */
- if (!STRINGP (font))
- font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
- if (!STRINGP (font))
- font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
- if (! STRINGP (font))
- font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
if (! STRINGP (font))
- /* This was formerly the first thing tried, but it finds too many fonts
- and takes too long. */
- font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
+ font = x_new_font (f, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1");
/* If those didn't work, look for something which will at least work. */
if (! STRINGP (font))
- font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
+ font = x_new_font (f, "-*-monaco-*-12-*-mac-roman");
+ if (! STRINGP (font))
+ font = x_new_font (f, "-*-courier-*-10-*-mac-roman");
UNBLOCK_INPUT;
if (! STRINGP (font))
- font = build_string ("fixed");
+ error ("Cannot find any usable font");
x_default_parameter (f, parms, Qfont, font,
"font", "Font", RES_TYPE_STRING);
{
Lisp_Object value;
- value = w32_get_arg (parms, Qinternal_border_width,
+ value = mac_get_arg (parms, Qinternal_border_width,
"internalBorder", "internalBorder", RES_TYPE_NUMBER);
if (! EQ (value, Qunbound))
parms = Fcons (Fcons (Qinternal_border_width, value),
happen. */
init_frame_faces (f);
- f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
+ f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
window_prompting = x_figure_window_size (f, parms, 0);
{
- XSetWindowAttributes attrs;
- unsigned long mask;
+ Rect r;
BLOCK_INPUT;
- mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
- /* Window managers looks at the override-redirect flag to
- determine whether or net to give windows a decoration (Xlib
- 3.2.8). */
- attrs.override_redirect = True;
- attrs.save_under = True;
- attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
- /* Arrange for getting MapNotify and UnmapNotify events. */
- attrs.event_mask = StructureNotifyMask;
- tip_window
- = FRAME_W32_WINDOW (f)
- = XCreateWindow (FRAME_W32_DISPLAY (f),
- FRAME_W32_DISPLAY_INFO (f)->root_window,
- /* x, y, width, height */
- 0, 0, 1, 1,
- /* Border. */
- 1,
- CopyFromParent, InputOutput, CopyFromParent,
- mask, &attrs);
+ SetRect (&r, 0, 0, 1, 1);
+ if (CreateNewWindow (kHelpWindowClass,
+#ifdef MAC_OS_X_VERSION_10_2
+ kWindowIgnoreClicksAttribute |
+#endif
+ kWindowNoActivatesAttribute,
+ &r, &tip_window) == noErr)
+ {
+ FRAME_MAC_WINDOW (f) = tip_window;
+ SetWRefCon (tip_window, (long) f->output_data.mac);
+ /* so that update events can find this mac_output struct */
+ f->output_data.mac->mFP = f;
+ ShowWindow (tip_window);
+ }
UNBLOCK_INPUT;
}
FRAME_LINES (f). */
width = FRAME_COLS (f);
height = FRAME_LINES (f);
- FRAME_LINES (f) = 0;
SET_FRAME_COLS (f, 0);
+ FRAME_LINES (f) = 0;
change_frame_size (f, height, width, 1, 0, 0);
/* Add `tooltip' frame parameter's default value. */
Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
Qnil));
+ /* Set up faces after all frame parameters are known. This call
+ also merges in face attributes specified for new frames.
+
+ Frame parameters may be changed if .Xdefaults contains
+ specifications for the default font. For example, if there is an
+ `Emacs.default.attributeBackground: pink', the `background-color'
+ attribute of the frame get's set, which let's the internal border
+ of the tooltip frame appear in pink. Prevent this. */
+ {
+ Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
+
+ /* Set tip_frame here, so that */
+ tip_frame = frame;
+ call1 (Qface_set_after_frame_default, frame);
+
+ if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
+ Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
+ Qnil));
+ }
+
f->no_split = 1;
UNGCPRO;
/* Now that the frame is official, it counts as a reference to
its display. */
- FRAME_W32_DISPLAY_INFO (f)->reference_count++;
+ FRAME_MAC_DISPLAY_INFO (f)->reference_count++;
+
+ /* Setting attributes of faces of the tooltip frame from resources
+ and similar will increment face_change_count, which leads to the
+ clearing of all current matrices. Since this isn't necessary
+ here, avoid it by resetting face_change_count to the value it
+ had before we created the tip frame. */
+ face_change_count = face_change_count_before;
+ /* Discard the unwind_protect. */
return unbind_to (count, frame);
-#endif /* MAC_TODO */
- return Qnil;
+}
+
+
+/* Compute where to display tip frame F. PARMS is the list of frame
+ parameters for F. DX and DY are specified offsets from the current
+ location of the mouse. WIDTH and HEIGHT are the width and height
+ of the tooltip. Return coordinates relative to the root window of
+ the display in *ROOT_X, and *ROOT_Y. */
+
+static void
+compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
+ struct frame *f;
+ Lisp_Object parms, dx, dy;
+ int width, height;
+ int *root_x, *root_y;
+{
+ Lisp_Object left, top;
+
+ /* User-specified position? */
+ left = Fcdr (Fassq (Qleft, parms));
+ top = Fcdr (Fassq (Qtop, parms));
+
+ /* Move the tooltip window where the mouse pointer is. Resize and
+ show it. */
+ if (!INTEGERP (left) || !INTEGERP (top))
+ {
+ Point mouse_pos;
+
+ BLOCK_INPUT;
+ GetMouse (&mouse_pos);
+ LocalToGlobal (&mouse_pos);
+ *root_x = mouse_pos.h;
+ *root_y = mouse_pos.v;
+ UNBLOCK_INPUT;
+ }
+
+ if (INTEGERP (top))
+ *root_y = XINT (top);
+ else if (*root_y + XINT (dy) - height < 0)
+ *root_y -= XINT (dy);
+ else
+ {
+ *root_y -= height;
+ *root_y += XINT (dy);
+ }
+
+ if (INTEGERP (left))
+ *root_x = XINT (left);
+ else if (*root_x + XINT (dx) + width <= FRAME_MAC_DISPLAY_INFO (f)->width)
+ /* It fits to the right of the pointer. */
+ *root_x += XINT (dx);
+ else if (width + XINT (dx) <= *root_x)
+ /* It fits to the left of the pointer. */
+ *root_x -= width + XINT (dx);
+ else
+ /* Put it left-justified on the screen -- it ought to fit that way. */
+ *root_x = 0;
}
DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
- doc : /* Show STRING in a "tooltip" window on frame FRAME.
-A tooltip window is a small window displaying a string.
+ doc: /* Show STRING in a "tooltip" window on frame FRAME.
+A tooltip window is a small X window displaying a string.
FRAME nil or omitted means use the selected frame.
DX isn't specified). Likewise for the y-position; if a `top' frame
parameter is specified, it determines the y-position of the tooltip
window, otherwise it is displayed at the mouse position, with offset
-DY added (default is 10). */)
- (string, frame, parms, timeout, dx, dy)
+DY added (default is -10).
+
+A tooltip's maximum size is specified by `x-max-tooltip-size'.
+Text larger than the specified size is clipped. */)
+ (string, frame, parms, timeout, dx, dy)
Lisp_Object string, frame, parms, timeout, dx, dy;
{
struct frame *f;
struct window *w;
- Window root, child;
- Lisp_Object buffer, top, left;
+ int root_x, root_y;
struct buffer *old_buffer;
struct text_pos pos;
int i, width, height;
- int root_x, root_y, win_x, win_y;
- unsigned pmask;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
int old_windows_or_buffers_changed = windows_or_buffers_changed;
int count = SPECPDL_INDEX ();
call1 (Qcancel_timer, timer);
}
-#if 0 /* MAC_TODO : Mac specifics */
BLOCK_INPUT;
- compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
- XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- root_x, root_y - FRAME_PIXEL_HEIGHT (f));
+ compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f), &root_x, &root_y);
+ MoveWindow (FRAME_MAC_WINDOW (f), root_x, root_y, false);
UNBLOCK_INPUT;
-#endif /* MAC_TODO */
goto start_timer;
}
}
/* Create a frame for the tooltip, and record it in the global
variable tip_frame. */
- frame = x_create_tip_frame (FRAME_MAC_DISPLAY_INFO (f), parms);
+ frame = x_create_tip_frame (FRAME_MAC_DISPLAY_INFO (f), parms, string);
f = XFRAME (frame);
- /* Set up the frame's root window. Currently we use a size of 80
- columns x 40 lines. If someone wants to show a larger tip, he
- will loose. I don't think this is a realistic case. */
+ /* Set up the frame's root window. */
w = XWINDOW (FRAME_ROOT_WINDOW (f));
w->left_col = w->top_line = make_number (0);
- w->total_cols = make_number (80);
- w->total_lines = make_number (40);
+
+ if (CONSP (Vx_max_tooltip_size)
+ && INTEGERP (XCAR (Vx_max_tooltip_size))
+ && XINT (XCAR (Vx_max_tooltip_size)) > 0
+ && INTEGERP (XCDR (Vx_max_tooltip_size))
+ && XINT (XCDR (Vx_max_tooltip_size)) > 0)
+ {
+ w->total_cols = XCAR (Vx_max_tooltip_size);
+ w->total_lines = XCDR (Vx_max_tooltip_size);
+ }
+ else
+ {
+ w->total_cols = make_number (80);
+ w->total_lines = make_number (40);
+ }
+
+ FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
adjust_glyphs (f);
w->pseudo_window_p = 1;
/* Display the tooltip text in a temporary buffer. */
- buffer = Fget_buffer_create (build_string (" *tip*"));
- Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
old_buffer = current_buffer;
- set_buffer_internal_1 (XBUFFER (buffer));
- Ferase_buffer ();
- Finsert (1, &string);
+ set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
+ current_buffer->truncate_lines = Qnil;
clear_glyph_matrix (w->desired_matrix);
clear_glyph_matrix (w->current_matrix);
SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
/* Let the row go over the full width of the frame. */
row->full_width_p = 1;
- /* There's a glyph at the end of rows that is use to place
+ /* There's a glyph at the end of rows that is used to place
the cursor there. Don't include the width of this glyph. */
if (row->used[TEXT_AREA])
{
/* Move the tooltip window where the mouse pointer is. Resize and
show it. */
-#if 0 /* TODO : Mac specifics */
- compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
+ compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
BLOCK_INPUT;
- XQueryPointer (FRAME_W32_DISPLAY (f), FRAME_W32_DISPLAY_INFO (f)->root_window,
- &root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
- XMoveResizeWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
- root_x + 5, root_y - height - 5, width, height);
- XMapRaised (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
+ MoveWindow (FRAME_MAC_WINDOW (f), root_x, root_y, false);
+ SizeWindow (FRAME_MAC_WINDOW (f), width, height, true);
+ BringToFront (FRAME_MAC_WINDOW (f));
UNBLOCK_INPUT;
-#endif /* MAC_TODO */
/* Draw into the window. */
w->must_be_updated_p = 1;
DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
doc: /* Hide the current tooltip window, if there is any.
-Value is t is tooltip was open, nil otherwise. */)
- ()
+Value is t if tooltip was open, nil otherwise. */)
+ ()
{
int count;
Lisp_Object deleted, frame, timer;
\f
+#ifdef TARGET_API_MAC_CARBON
/***********************************************************************
File selection dialog
***********************************************************************/
-#if 0 /* MAC_TODO: can standard file dialog */
+/**
+ There is a relatively standard way to do this using applescript to run
+ a (choose file) method. However, this doesn't do "the right thing"
+ by working only if the find-file occurred during a menu or toolbar
+ click. So we must do the file dialog by hand, using the navigation
+ manager. This also has more flexibility in determining the default
+ directory and whether or not we are going to choose a file.
+ **/
+
extern Lisp_Object Qfile_name_history;
DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
doc: /* Read file name, prompting with PROMPT in directory DIR.
Use a file selection dialog.
Select DEFAULT-FILENAME in the dialog's file selection box, if
-specified. Don't let the user enter a file name in the file
-selection dialog's entry field, if MUSTMATCH is non-nil. */)
+specified. Ensure that file exists if MUSTMATCH is non-nil. */)
(prompt, dir, default_filename, mustmatch)
Lisp_Object prompt, dir, default_filename, mustmatch;
{
Lisp_Object file = Qnil;
int count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
- char filename[MAX_PATH + 1];
- char init_dir[MAX_PATH + 1];
- int use_dialog_p = 1;
+ char filename[1001];
+ int default_filter_index = 1; /* 1: All Files, 2: Directories only */
GCPRO5 (prompt, dir, default_filename, mustmatch, file);
CHECK_STRING (prompt);
/* Create the dialog with PROMPT as title, using DIR as initial
directory and using "*" as pattern. */
dir = Fexpand_file_name (dir, Qnil);
- strncpy (init_dir, SDATA (dir), MAX_PATH);
- init_dir[MAX_PATH] = '\0';
- unixtodos_filename (init_dir);
-
- if (STRINGP (default_filename))
- {
- char *file_name_only;
- char *full_path_name = SDATA (default_filename);
- unixtodos_filename (full_path_name);
-
- file_name_only = strrchr (full_path_name, '\\');
- if (!file_name_only)
- file_name_only = full_path_name;
- else
- {
- file_name_only++;
-
- /* If default_file_name is a directory, don't use the open
- file dialog, as it does not support selecting
- directories. */
- if (!(*file_name_only))
- use_dialog_p = 0;
- }
+ {
+ OSStatus status;
+ NavDialogCreationOptions options;
+ NavDialogRef dialogRef;
+ NavTypeListHandle fileTypes = NULL;
+ NavUserAction userAction;
+ CFStringRef message=NULL, client=NULL, saveName = NULL;
+
+ BLOCK_INPUT;
+ /* No need for a callback function because we are modal */
+ NavGetDefaultDialogCreationOptions(&options);
+ options.modality = kWindowModalityAppModal;
+ options.location.h = options.location.v = -1;
+ options.optionFlags = kNavDefaultNavDlogOptions;
+ options.optionFlags |= kNavAllFilesInPopup; /* All files allowed */
+ options.optionFlags |= kNavSelectAllReadableItem;
+ if (!NILP(prompt))
+ {
+ message = CFStringCreateWithCStringNoCopy(NULL, SDATA(prompt),
+ kCFStringEncodingUTF8,
+ kCFAllocatorNull);
+ options.message = message;
+ }
+ /* Don't set the application, let it use default.
+ client = CFStringCreateWithCStringNoCopy(NULL, "Emacs",
+ kCFStringEncodingMacRoman, NULL);
+ options.clientName = client;
+ */
+
+ /* Do Dired hack copied from w32fns.c */
+ if (!NILP(prompt) && strncmp (SDATA(prompt), "Dired", 5) == 0)
+ status = NavCreateChooseFolderDialog(&options, NULL, NULL, NULL,
+ &dialogRef);
+ else if (NILP (mustmatch))
+ {
+ /* This is a save dialog */
+ if (!NILP(default_filename))
+ {
+ saveName = CFStringCreateWithCString(NULL, SDATA(default_filename),
+ kCFStringEncodingUTF8);
+ options.saveFileName = saveName;
+ options.optionFlags |= kNavSelectDefaultLocation;
+ }
+ /* MAC_TODO: Find a better way to determine if this is a save
+ or load dialog than comparing dir with default_filename */
+ if (EQ(dir, default_filename))
+ {
+ status = NavCreateChooseFileDialog(&options, fileTypes,
+ NULL, NULL, NULL, NULL,
+ &dialogRef);
+ }
+ else {
+ status = NavCreatePutFileDialog(&options,
+ 'TEXT', kNavGenericSignature,
+ NULL, NULL, &dialogRef);
+ }
+ }
+ else
+ {
+ /* This is an open dialog*/
+ status = NavCreateChooseFileDialog(&options, fileTypes,
+ NULL, NULL, NULL, NULL,
+ &dialogRef);
+ }
+
+ /* Set the default location and continue*/
+ if (status == noErr) {
+ if (!NILP(dir)) {
+ FSRef defLoc;
+ AEDesc defLocAed;
+ status = FSPathMakeRef(SDATA(dir), &defLoc, NULL);
+ if (status == noErr)
+ {
+ AECreateDesc(typeFSRef, &defLoc, sizeof(FSRef), &defLocAed);
+ NavCustomControl(dialogRef, kNavCtlSetLocation, (void*) &defLocAed);
+ }
+ AEDisposeDesc(&defLocAed);
+ }
- strncpy (filename, file_name_only, MAX_PATH);
- filename[MAX_PATH] = '\0';
+ status = NavDialogRun(dialogRef);
}
- else
- filename[0] = '\0';
- if (use_dialog_p)
- {
- OPENFILENAME file_details;
- char *filename_file;
+ if (saveName) CFRelease(saveName);
+ if (client) CFRelease(client);
+ if (message) CFRelease(message);
- /* Prevent redisplay. */
- specbind (Qinhibit_redisplay, Qt);
- BLOCK_INPUT;
-
- bzero (&file_details, sizeof (file_details));
- file_details.lStructSize = sizeof (file_details);
- file_details.hwndOwner = FRAME_W32_WINDOW (f);
- file_details.lpstrFile = filename;
- file_details.nMaxFile = sizeof (filename);
- file_details.lpstrInitialDir = init_dir;
- file_details.lpstrTitle = SDATA (prompt);
- file_details.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
-
- if (!NILP (mustmatch))
- file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
-
- if (GetOpenFileName (&file_details))
- {
- dostounix_filename (filename);
- file = build_string (filename);
- }
- else
- file = Qnil;
-
- UNBLOCK_INPUT;
- file = unbind_to (count, file);
+ if (status == noErr) {
+ userAction = NavDialogGetUserAction(dialogRef);
+ switch (userAction)
+ {
+ case kNavUserActionNone:
+ case kNavUserActionCancel:
+ break; /* Treat cancel like C-g */
+ case kNavUserActionOpen:
+ case kNavUserActionChoose:
+ case kNavUserActionSaveAs:
+ {
+ NavReplyRecord reply;
+ AEDesc aed;
+ FSRef fsRef;
+ status = NavDialogGetReply(dialogRef, &reply);
+ AECoerceDesc(&reply.selection, typeFSRef, &aed);
+ AEGetDescData(&aed, (void *) &fsRef, sizeof (FSRef));
+ FSRefMakePath(&fsRef, (UInt8 *) filename, 1000);
+ AEDisposeDesc(&aed);
+ if (reply.saveFileName)
+ {
+ /* If it was a saved file, we need to add the file name */
+ int len = strlen(filename);
+ if (len && filename[len-1] != '/')
+ filename[len++] = '/';
+ CFStringGetCString(reply.saveFileName, filename+len,
+ 1000-len, kCFStringEncodingUTF8);
+ }
+ file = DECODE_FILE(build_string (filename));
+ NavDisposeReply(&reply);
+ }
+ break;
+ }
+ NavDialogDispose(dialogRef);
}
- /* Open File dialog will not allow folders to be selected, so resort
- to minibuffer completing reads for directories. */
- else
- file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
- dir, mustmatch, dir, Qfile_name_history,
- default_filename, Qnil);
+ else {
+ /* Fall back on minibuffer if there was a problem */
+ file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
+ dir, mustmatch, dir, Qfile_name_history,
+ default_filename, Qnil);
+ }
+ UNBLOCK_INPUT;
+ }
UNGCPRO;
-
+
/* Make "Cancel" equivalent to C-g. */
if (NILP (file))
Fsignal (Qquit, Qnil);
-
+
return unbind_to (count, file);
}
-#endif /* MAC_TODO */
+#endif
\f
/***********************************************************************
Initialization
staticpro (&Qsuppress_icon);
Qundefined_color = intern ("undefined-color");
staticpro (&Qundefined_color);
- /* This is the end of symbol initialization. */
+ Qcancel_timer = intern ("cancel-timer");
+ staticpro (&Qcancel_timer);
Qhyper = intern ("hyper");
staticpro (&Qhyper);
staticpro (&Qcontrol);
Qshift = intern ("shift");
staticpro (&Qshift);
+ /* This is the end of symbol initialization. */
/* Text property `display' should be nonsticky by default. */
Vtext_property_default_nonsticky
doc: /* A string indicating the foreground color of the cursor box. */);
Vx_cursor_fore_pixel = Qnil;
+ DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
+ doc: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS).
+Text larger than this is clipped. */);
+ Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
+
DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
doc: /* Non-nil if no window manager is in use.
Emacs doesn't try to figure this out; this is always nil
tip_frame = Qnil;
staticpro (&tip_frame);
-#if 0 /* MAC_TODO */
+ last_show_tip_args = Qnil;
+ staticpro (&last_show_tip_args);
+
+#if TARGET_API_MAC_CARBON
defsubr (&Sx_file_dialog);
#endif
}