Commit b15325b2 authored by Steven Tamm's avatar Steven Tamm

* dispextern.h: Change HAVE_CARBON to MAC_OS.

	(struct glyph_string): Likewise.
* emacs.c (main) [MAC_OS8]: Call mac_term_init instead of
	mac_initialize.
* fileio.c (Fnext_read_file_uses_dialog_p, Fread_file_name):
	Change TARGET_API_MAC_CARBON to HAVE_CARBON.
* fns.c (vector): Change MAC_OSX to MAC_OS.
* frame.c (x_set_frame_parameters, x_report_frame_params)
	(x_set_fullscreen): Remove #ifndef HAVE_CARBON.
	(x_set_border_width, Vdefault_frame_scroll_bars): Change
	HAVE_CARBON to MAC_OS.
* image.c [MAC_OS]: Include sys/stat.h.
	[MAC_OS && !MAC_OSX]: Include sys/param.h, ImageCompression.h, and
	QuickTimeComponents.h.
* mac.c [!MAC_OSX] (mac_wait_next_event): Add extern.
	[!MAC_OSX] (select): Use mac_wait_next_event.
	[!MAC_OSX] (run_mac_command): Change EXEC_SUFFIXES to
	Vexec_suffixes.
	[!MAC_OSX] (select, run_mac_command): Change `#ifdef
	TARGET_API_MAC_CARBON' to `#if TARGET_API_MAC_CARBON'.
	(mac_clear_font_name_table): Add extern.
	(Fmac_clear_font_name_table): New defun.
	(syms_of_mac): Defsubr it.
	[MAC_OSX] (SELECT_POLLING_PERIOD_USEC): New define.
	[MAC_OSX] (select_and_poll_event): New function.
	[MAC_OSX] (sys_select): Use it.
	[MAC_OSX && SELECT_USE_CFSOCKET] (socket_callback): New function.
	[MAC_OSX && SELECT_USE_CFSOCKET]
	(SELECT_TIMEOUT_THRESHOLD_RUNLOOP, EVENT_CLASS_SOCK): New defines.
	[MAC_OSX] (sys_select) [SELECT_USE_CFSOCKET]: Use CFSocket and
	RunLoop for simultaneously monitoring two kinds of inputs, window
	events and process outputs, without periodically polling.
* macfns.c (mac_initialized): Remove extern.
	(stricmp): Put in #if 0.  All callers changed to use xstricmp in
	xfaces.c.
	(strnicmp): Decrement `n' at the end of each loop, not the
	beginning.
	(check_mac): Use the term "Mac native windows" instead of "Mac
	OS".
	(check_x_display_info, x_display_info_for_name): Sync with xfns.c.
	(mac_get_rdb_resource): New function (from w32reg.c).
	(x_get_string_resource): Use it.
	(install_window_handler): Add extern.
	(mac_window): New function.
	(Fx_create_frame): Use it instead of make_mac_frame.  Set
	parameter for Qfullscreen.  Call x_wm_set_size_hint.
	(Fx_open_connection, Fx_close_connection): New defuns.
	(syms_of_macfns): Defsubr them.
	(x_create_tip_frame) [TARGET_API_MAC_CARBON]: Add
	kWindowNoUpdatesAttribute to the window attribute.
	(x_create_tip_frame) [!TARGET_API_MAC_CARBON]: Use NewCWindow.
	(x_create_tip_frame): Don't call ShowWindow.
	(Fx_show_tip): Call ShowWindow.
	(Fx_file_dialog): Change `#ifdef TARGET_API_MAC_CARBON' to `#if
	TARGET_API_MAC_CARBON'.
	(mac_frame_parm_handlers): Set handlers for Qfullscreen.
	(syms_of_macfns) [MAC_OSX]: Initialize mac_in_use to 0.
* macgui.h [!MAC_OSX]: Don't include Controls.h.  Include
	Windows.h.
	(Window): Typedef to WindowPtr and move outside `#if
	TARGET_API_MAC_CARBON'.
	(XSizeHints): New struct.
* macterm.c (x_update_begin, x_update_end)
	[TARGET_API_MAC_CARBON]: Disable screen updates during update of a
	frame.
	(x_draw_glyph_string_background, x_draw_glyph_string_foreground)
	[MAC_OS8]: Use XDrawImageString/XDrawImageString16.
	(construct_mouse_click): Put in #if 0.
	(x_check_fullscreen, x_check_fullscreen_move): Remove decls.
	(x_scroll_bar_create, x_scroll_bar_handle_click): Change `#ifdef
	TARGET_API_MAC_CARBON' to `#if TARGET_API_MAC_CARBON'.
	(activate_scroll_bars, deactivate_scroll_bars)
	[!TARGET_API_MAC_CARBON]: Use ActivateControl/DeactivateControl.
	(x_make_frame_visible) [TARGET_API_MAC_CARBON]: Reposition window
	if the position is neither user-specified nor program-specified.
	(x_free_frame_resources): Free size_hints.
	(x_wm_set_size_hint): Allocate size_hints if needed.  Set
	size_hints.
	(mac_clear_font_name_table): New function.
	(mac_do_list_fonts): Initialize font_name_table if needed.
	(x_list_fonts): Don't initialize font_name_table.  Add BLOCK_INPUT
	around mac_do_list_fonts.
	(mac_unload_font): New function.
	(x_load_font): Add BLOCK_INPUT around XLoadQueryFont.
	(init_mac_drag_n_drop, mac_do_receive_drag): Enclose declarations
	and definitions with #if TARGET_API_MAC_CARBON.
	[USE_CARBON_EVENTS] (mac_handle_window_event): Add decl.
	(install_window_handler): Add decl.
	(do_window_update): Add BeginUpdate/EndUpdate for the tooltip
	window.  Use UpdateControls.  Get the rectangle that should be
	updated and restrict the target of expose_frame to it.
	(do_grow_window): Set minimum height/width according to
	size_hints.
	(do_grow_window) [TARGET_API_MAC_CARBON]: Use ResizeWindow.
	(do_zoom_window): Don't use x_set_window_size.
	[USE_CARBON_EVENTS] (mac_handle_window_event): New function.
	(install_window_handler): New function.
	[!USE_CARBON_EVENTS] (mouse_region): New variable.
	[!USE_CARBON_EVENTS] (mac_wait_next_event): New function.
	(XTread_socket) [USE_CARBON_EVENTS]: Move call to
	GetEventDispatcherTarget inside BLOCK_INPUT.
	(XTread_socket) [!USE_CARBON_EVENTS]: Use mac_wait_next_event.
	Update mouse_region when mouse is moved.
	(make_mac_frame): Remove.
	(make_mac_terminal_frame): Put in #ifdef MAC_OS8.  Initialize
	mouse pointer shapes.  Change values of f->left_pos and
	f->top_pos.  Don't use make_mac_frame.  Use NewCWindow.  Don't
	call ShowWindow.
	(mac_initialize_display_info) [MAC_OSX]: Create mac_id_name from
	Vinvocation_name and Vsystem_name.
	(mac_make_rdb): New function (from w32term.c).
	(mac_term_init): Use it.  Add BLOCK_INPUT.  Error if display has
	already been opened.  Don't pass argument to
	mac_initialize_display_info.  Don't set dpyinfo->height/width.
	Add entries to x_display_list and x_display_name_list.
	(x_delete_display): New function.
	(mac_initialize): Don't call mac_initialize_display_info.
	(syms_of_macterm) [!MAC_OSX]: Don't call Fprovide.
* macterm.h (check_mac): Add extern.
	(struct mac_output): New member size_hints.
	(FRAME_SIZE_HINTS): New macro.
	(mac_unload_font): Add extern.
* xdisp.c (expose_window, expose_frame): Remove kludges for Mac.
* xfaces.c (clear_font_table) [MAC_OS]: call mac_unload_font.
parent 22933cbf
2004-12-27 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
* dispextern.h: Change HAVE_CARBON to MAC_OS.
(struct glyph_string): Likewise.
* emacs.c (main) [MAC_OS8]: Call mac_term_init instead of
mac_initialize.
* fileio.c (Fnext_read_file_uses_dialog_p, Fread_file_name):
Change TARGET_API_MAC_CARBON to HAVE_CARBON.
* fns.c (vector): Change MAC_OSX to MAC_OS.
* frame.c (x_set_frame_parameters, x_report_frame_params)
(x_set_fullscreen): Remove #ifndef HAVE_CARBON.
(x_set_border_width, Vdefault_frame_scroll_bars): Change
HAVE_CARBON to MAC_OS.
* image.c [MAC_OS]: Include sys/stat.h.
[MAC_OS && !MAC_OSX]: Include sys/param.h, ImageCompression.h, and
QuickTimeComponents.h.
* mac.c [!MAC_OSX] (mac_wait_next_event): Add extern.
[!MAC_OSX] (select): Use mac_wait_next_event.
[!MAC_OSX] (run_mac_command): Change EXEC_SUFFIXES to
Vexec_suffixes.
[!MAC_OSX] (select, run_mac_command): Change `#ifdef
TARGET_API_MAC_CARBON' to `#if TARGET_API_MAC_CARBON'.
(mac_clear_font_name_table): Add extern.
(Fmac_clear_font_name_table): New defun.
(syms_of_mac): Defsubr it.
[MAC_OSX] (SELECT_POLLING_PERIOD_USEC): New define.
[MAC_OSX] (select_and_poll_event): New function.
[MAC_OSX] (sys_select): Use it.
[MAC_OSX && SELECT_USE_CFSOCKET] (socket_callback): New function.
[MAC_OSX && SELECT_USE_CFSOCKET]
(SELECT_TIMEOUT_THRESHOLD_RUNLOOP, EVENT_CLASS_SOCK): New defines.
[MAC_OSX] (sys_select) [SELECT_USE_CFSOCKET]: Use CFSocket and
RunLoop for simultaneously monitoring two kinds of inputs, window
events and process outputs, without periodically polling.
* macfns.c (mac_initialized): Remove extern.
(stricmp): Put in #if 0. All callers changed to use xstricmp in
xfaces.c.
(strnicmp): Decrement `n' at the end of each loop, not the
beginning.
(check_mac): Use the term "Mac native windows" instead of "Mac
OS".
(check_x_display_info, x_display_info_for_name): Sync with xfns.c.
(mac_get_rdb_resource): New function (from w32reg.c).
(x_get_string_resource): Use it.
(install_window_handler): Add extern.
(mac_window): New function.
(Fx_create_frame): Use it instead of make_mac_frame. Set
parameter for Qfullscreen. Call x_wm_set_size_hint.
(Fx_open_connection, Fx_close_connection): New defuns.
(syms_of_macfns): Defsubr them.
(x_create_tip_frame) [TARGET_API_MAC_CARBON]: Add
kWindowNoUpdatesAttribute to the window attribute.
(x_create_tip_frame) [!TARGET_API_MAC_CARBON]: Use NewCWindow.
(x_create_tip_frame): Don't call ShowWindow.
(Fx_show_tip): Call ShowWindow.
(Fx_file_dialog): Change `#ifdef TARGET_API_MAC_CARBON' to `#if
TARGET_API_MAC_CARBON'.
(mac_frame_parm_handlers): Set handlers for Qfullscreen.
(syms_of_macfns) [MAC_OSX]: Initialize mac_in_use to 0.
* macgui.h [!MAC_OSX]: Don't include Controls.h. Include
Windows.h.
(Window): Typedef to WindowPtr and move outside `#if
TARGET_API_MAC_CARBON'.
(XSizeHints): New struct.
* macterm.c (x_update_begin, x_update_end)
[TARGET_API_MAC_CARBON]: Disable screen updates during update of a
frame.
(x_draw_glyph_string_background, x_draw_glyph_string_foreground)
[MAC_OS8]: Use XDrawImageString/XDrawImageString16.
(construct_mouse_click): Put in #if 0.
(x_check_fullscreen, x_check_fullscreen_move): Remove decls.
(x_scroll_bar_create, x_scroll_bar_handle_click): Change `#ifdef
TARGET_API_MAC_CARBON' to `#if TARGET_API_MAC_CARBON'.
(activate_scroll_bars, deactivate_scroll_bars)
[!TARGET_API_MAC_CARBON]: Use ActivateControl/DeactivateControl.
(x_make_frame_visible) [TARGET_API_MAC_CARBON]: Reposition window
if the position is neither user-specified nor program-specified.
(x_free_frame_resources): Free size_hints.
(x_wm_set_size_hint): Allocate size_hints if needed. Set
size_hints.
(mac_clear_font_name_table): New function.
(mac_do_list_fonts): Initialize font_name_table if needed.
(x_list_fonts): Don't initialize font_name_table. Add BLOCK_INPUT
around mac_do_list_fonts.
(mac_unload_font): New function.
(x_load_font): Add BLOCK_INPUT around XLoadQueryFont.
(init_mac_drag_n_drop, mac_do_receive_drag): Enclose declarations
and definitions with #if TARGET_API_MAC_CARBON.
[USE_CARBON_EVENTS] (mac_handle_window_event): Add decl.
(install_window_handler): Add decl.
(do_window_update): Add BeginUpdate/EndUpdate for the tooltip
window. Use UpdateControls. Get the rectangle that should be
updated and restrict the target of expose_frame to it.
(do_grow_window): Set minimum height/width according to
size_hints.
(do_grow_window) [TARGET_API_MAC_CARBON]: Use ResizeWindow.
(do_zoom_window): Don't use x_set_window_size.
[USE_CARBON_EVENTS] (mac_handle_window_event): New function.
(install_window_handler): New function.
[!USE_CARBON_EVENTS] (mouse_region): New variable.
[!USE_CARBON_EVENTS] (mac_wait_next_event): New function.
(XTread_socket) [USE_CARBON_EVENTS]: Move call to
GetEventDispatcherTarget inside BLOCK_INPUT.
(XTread_socket) [!USE_CARBON_EVENTS]: Use mac_wait_next_event.
Update mouse_region when mouse is moved.
(make_mac_frame): Remove.
(make_mac_terminal_frame): Put in #ifdef MAC_OS8. Initialize
mouse pointer shapes. Change values of f->left_pos and
f->top_pos. Don't use make_mac_frame. Use NewCWindow. Don't
call ShowWindow.
(mac_initialize_display_info) [MAC_OSX]: Create mac_id_name from
Vinvocation_name and Vsystem_name.
(mac_make_rdb): New function (from w32term.c).
(mac_term_init): Use it. Add BLOCK_INPUT. Error if display has
already been opened. Don't pass argument to
mac_initialize_display_info. Don't set dpyinfo->height/width.
Add entries to x_display_list and x_display_name_list.
(x_delete_display): New function.
(mac_initialize): Don't call mac_initialize_display_info.
(syms_of_macterm) [!MAC_OSX]: Don't call Fprovide.
* macterm.h (check_mac): Add extern.
(struct mac_output): New member size_hints.
(FRAME_SIZE_HINTS): New macro.
(mac_unload_font): Add extern.
* xdisp.c (expose_window, expose_frame): Remove kludges for Mac.
* xfaces.c (clear_font_table) [MAC_OS]: call mac_unload_font.
2004-12-27 Richard M. Stallman <rms@gnu.org>
* buffer.c (Fbuffer_disable_undo): Deleted (moved to simple.el).
......
......@@ -62,7 +62,7 @@ typedef XImage *XImagePtr;
typedef HDC XImagePtr_or_DC;
#endif
#ifdef HAVE_CARBON
#ifdef MAC_OS
#include "macgui.h"
typedef struct mac_display_info Display_Info;
/* Mac equivalent of XImage. */
......@@ -1171,7 +1171,7 @@ struct glyph_string
unsigned for_overlaps_p : 1;
/* The GC to use for drawing this glyph string. */
#if defined(HAVE_X_WINDOWS) || defined(HAVE_CARBON)
#if defined(HAVE_X_WINDOWS) || defined(MAC_OS)
GC gc;
#endif
#if defined(HAVE_NTGUI)
......
......@@ -1306,7 +1306,7 @@ main (argc, argv
creates a full-fledge output_mac type frame. This does not
work correctly before syms_of_textprop, syms_of_macfns,
syms_of_ccl, syms_of_fontset, syms_of_xterm, syms_of_search,
syms_of_frame, mac_initialize, and init_keyboard have already
syms_of_frame, mac_term_init, and init_keyboard have already
been called. */
syms_of_textprop ();
syms_of_macfns ();
......@@ -1318,7 +1318,7 @@ main (argc, argv
syms_of_search ();
syms_of_frame ();
mac_initialize ();
mac_term_init (build_string ("Mac"), NULL, NULL);
init_keyboard ();
#endif
......
......@@ -6188,7 +6188,7 @@ The return value is only relevant for a call to `read-file-name' that happens
before any other event (mouse or keypress) is handeled. */)
()
{
#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) || defined (TARGET_API_MAC_CARBON)
#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) || defined (HAVE_CARBON)
if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
&& use_dialog_box
&& use_file_dialog
......@@ -6329,7 +6329,7 @@ and `read-file-name-function'. */)
GCPRO2 (insdef, default_filename);
#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) || defined (TARGET_API_MAC_CARBON)
#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) || defined (HAVE_CARBON)
if (! NILP (Fnext_read_file_uses_dialog_p ()))
{
/* If DIR contains a file name, split it. */
......
......@@ -26,8 +26,8 @@ Boston, MA 02111-1307, USA. */
#endif
#include <time.h>
#ifndef MAC_OSX
/* On Mac OS X, defining this conflicts with precompiled headers. */
#ifndef MAC_OS
/* On Mac OS, defining this conflicts with precompiled headers. */
/* Note on some machines this defines `vector' as a typedef,
so make sure we don't use that name in this file. */
......
......@@ -2815,8 +2815,6 @@ x_set_frame_parameters (f, alist)
XSETINT (icon_top, 0);
}
#ifndef HAVE_CARBON
/* MAC_TODO: fullscreen */
if (FRAME_VISIBLE_P (f) && fullscreen_is_being_set)
{
/* If the frame is visible already and the fullscreen parameter is
......@@ -2832,7 +2830,6 @@ x_set_frame_parameters (f, alist)
if (new_top != f->top_pos || new_left != f->left_pos)
x_set_offset (f, new_left, new_top, 1);
}
#endif
/* Don't set these parameters unless they've been explicitly
specified. The window might be mapped or resized while we're in
......@@ -2993,14 +2990,11 @@ x_report_frame_params (f, alistptr)
store_in_alist (alistptr, Qdisplay,
XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
#ifndef HAVE_CARBON
/* A Mac Window is identified by a struct, not an integer. */
if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
tem = Qnil;
else
XSETFASTINT (tem, FRAME_X_OUTPUT (f)->parent_desc);
store_in_alist (alistptr, Qparent_id, tem);
#endif
}
......@@ -3012,7 +3006,6 @@ x_set_fullscreen (f, new_value, old_value)
struct frame *f;
Lisp_Object new_value, old_value;
{
#ifndef HAVE_CARBON
if (NILP (new_value))
f->want_fullscreen = FULLSCREEN_NONE;
else if (EQ (new_value, Qfullboth))
......@@ -3021,7 +3014,6 @@ x_set_fullscreen (f, new_value, old_value)
f->want_fullscreen = FULLSCREEN_WIDTH;
else if (EQ (new_value, Qfullheight))
f->want_fullscreen = FULLSCREEN_HEIGHT;
#endif
}
......@@ -3141,7 +3133,7 @@ x_set_border_width (f, arg, oldval)
if (XINT (arg) == f->border_width)
return;
#ifndef HAVE_CARBON
#ifndef MAC_OS
if (FRAME_X_WINDOW (f) != 0)
error ("Cannot change the border width of a window");
#endif /* MAC_TODO */
......@@ -4052,7 +4044,7 @@ Setting this variable does not affect existing frames, only new ones. */);
DEFVAR_LISP ("default-frame-scroll-bars", &Vdefault_frame_scroll_bars,
doc: /* Default position of scroll bars on this window-system. */);
#ifdef HAVE_WINDOW_SYSTEM
#if defined(HAVE_NTGUI) || defined(HAVE_CARBON)
#if defined(HAVE_NTGUI) || defined(MAC_OS)
/* MS-Windows has scroll bars on the right by default. */
Vdefault_frame_scroll_bars = Qright;
#else
......
......@@ -83,16 +83,19 @@ typedef struct w32_bitmap_record Bitmap_Record;
#ifdef MAC_OS
#include "macterm.h"
#include <sys/stat.h>
#ifndef MAC_OSX
#include <alloca.h>
#include <sys/param.h>
#endif
#ifdef MAC_OSX
#include <sys/stat.h>
#include <QuickTime/QuickTime.h>
#else /* not MAC_OSX */
#include <Windows.h>
#include <Gestalt.h>
#include <TextUtils.h>
#include <ImageCompression.h>
#include <QuickTimeComponents.h>
#endif /* not MAC_OSX */
/* MAC_TODO : Color tables on Mac. */
......
......@@ -845,6 +845,8 @@ check_alarm ()
}
extern Boolean mac_wait_next_event (EventRecord *, UInt32, Boolean);
int
select (n, rfds, wfds, efds, timeout)
int n;
......@@ -853,49 +855,24 @@ select (n, rfds, wfds, efds, timeout)
SELECT_TYPE *efds;
struct timeval *timeout;
{
#ifdef TARGET_API_MAC_CARBON
#if TARGET_API_MAC_CARBON
return 1;
#else /* not TARGET_API_MAC_CARBON */
EMACS_TIME end_time, now;
EventRecord e;
UInt32 sleep_time = EMACS_SECS (*timeout) * 60 +
((EMACS_USECS (*timeout) * 60) / 1000000);
/* Can only handle wait for keyboard input. */
if (n > 1 || wfds || efds)
return -1;
EMACS_GET_TIME (end_time);
EMACS_ADD_TIME (end_time, end_time, *timeout);
do
{
/* Also return true if an event other than a keyDown has
occurred. This causes kbd_buffer_get_event in keyboard.c to
call read_avail_input which in turn calls XTread_socket to
poll for these events. Otherwise these never get processed
except but a very slow poll timer. */
if (FD_ISSET (0, rfds) && EventAvail (everyEvent, &e))
return 1;
/* Also check movement of the mouse. */
{
Point mouse_pos;
static Point old_mouse_pos = {-1, -1};
GetMouse (&mouse_pos);
if (!EqualPt (mouse_pos, old_mouse_pos))
{
old_mouse_pos = mouse_pos;
return 1;
}
}
WaitNextEvent (0, &e, 1UL, NULL); /* Accept no event; wait 1
tic. by T.I. */
EMACS_GET_TIME (now);
EMACS_SUB_TIME (now, end_time, now);
}
while (!EMACS_TIME_NEG_P (now));
/* Also return true if an event other than a keyDown has occurred.
This causes kbd_buffer_get_event in keyboard.c to call
read_avail_input which in turn calls XTread_socket to poll for
these events. Otherwise these never get processed except but a
very slow poll timer. */
if (FD_ISSET (0, rfds) && mac_wait_next_event (&e, sleep_time, false))
return 1;
return 0;
#endif /* not TARGET_API_MAC_CARBON */
......@@ -1996,7 +1973,7 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
const char *workdir;
const char *infn, *outfn, *errfn;
{
#ifdef TARGET_API_MAC_CARBON
#if TARGET_API_MAC_CARBON
return -1;
#else /* not TARGET_API_MAC_CARBON */
char macappname[MAXPATHLEN+1], macworkdir[MAXPATHLEN+1];
......@@ -2081,7 +2058,7 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
strcat (t, newargv[0]);
#endif /* 0 */
Lisp_Object path;
openp (Vexec_path, build_string (newargv[0]), EXEC_SUFFIXES, &path,
openp (Vexec_path, build_string (newargv[0]), Vexec_suffixes, &path,
make_number (X_OK));
if (NILP (path))
......@@ -2793,17 +2770,98 @@ and t is the same as `SECONDARY'. */)
return Qnil;
}
extern void mac_clear_font_name_table P_ ((void));
DEFUN ("mac-clear-font-name-table", Fmac_clear_font_name_table, Smac_clear_font_name_table, 0, 0, 0,
doc: /* Clear the font name table. */)
()
{
check_mac ();
mac_clear_font_name_table ();
return Qnil;
}
#ifdef MAC_OSX
#undef select
extern int inhibit_window_system;
extern int noninteractive;
/* When Emacs is started from the Finder, SELECT always immediately
returns as if input is present when file descriptor 0 is polled for
input. Strangely, when Emacs is run as a GUI application from the
command line, it blocks in the same situation. This `wrapper' of
the system call SELECT corrects this discrepancy. */
/* Unlike in X11, window events in Carbon do not come from sockets.
So we cannot simply use `select' to monitor two kinds of inputs:
window events and process outputs. We emulate such functionality
by regarding fd 0 as the window event channel and simultaneously
monitoring both kinds of input channels. It is implemented by
dividing into some cases:
1. The window event channel is not involved.
-> Use `select'.
2. Sockets are not involved.
-> Use ReceiveNextEvent.
3. [If SELECT_USE_CFSOCKET is defined]
Only the window event channel and socket read channels are
involved, and timeout is not too short (greater than
SELECT_TIMEOUT_THRESHHOLD_RUNLOOP seconds).
-> Create CFSocket for each socket and add it into the current
event RunLoop so that an `ready-to-read' event can be posted
to the event queue that is also used for window events. Then
ReceiveNextEvent can wait for both kinds of inputs.
4. Otherwise.
-> Periodically poll the window input channel while repeatedly
executing `select' with a short timeout
(SELECT_POLLING_PERIOD_USEC microseconds). */
#define SELECT_POLLING_PERIOD_USEC 20000
#ifdef SELECT_USE_CFSOCKET
#define SELECT_TIMEOUT_THRESHOLD_RUNLOOP 0.2
#define EVENT_CLASS_SOCK 'Sock'
static void
socket_callback (s, type, address, data, info)
CFSocketRef s;
CFSocketCallBackType type;
CFDataRef address;
const void *data;
void *info;
{
EventRef event;
CreateEvent (NULL, EVENT_CLASS_SOCK, 0, 0, kEventAttributeNone, &event);
PostEventToQueue (GetCurrentEventQueue (), event, kEventPriorityStandard);
ReleaseEvent (event);
}
#endif /* SELECT_USE_CFSOCKET */
static int
select_and_poll_event (n, rfds, wfds, efds, timeout)
int n;
SELECT_TYPE *rfds;
SELECT_TYPE *wfds;
SELECT_TYPE *efds;
struct timeval *timeout;
{
int r;
OSErr err;
r = select (n, rfds, wfds, efds, timeout);
if (r != -1)
{
BLOCK_INPUT;
err = ReceiveNextEvent (0, NULL, kEventDurationNoWait,
kEventLeaveInQueue, NULL);
UNBLOCK_INPUT;
if (err == noErr)
{
FD_SET (0, rfds);
r++;
}
}
return r;
}
#ifndef MAC_OS_X_VERSION_10_2
#undef SELECT_INVALIDATE_CFSOCKET
#endif
int
sys_select (n, rfds, wfds, efds, timeout)
int n;
......@@ -2813,91 +2871,182 @@ sys_select (n, rfds, wfds, efds, timeout)
struct timeval *timeout;
{
OSErr err;
EMACS_TIME end_time, now, remaining_time;
int i, r;
EMACS_TIME select_timeout;
if (inhibit_window_system || noninteractive
|| rfds == NULL || !FD_ISSET (0, rfds))
return select (n, rfds, wfds, efds, timeout);
FD_CLR (0, rfds);
if (wfds == NULL && efds == NULL)
{
int i;
int nsocks = 0;
SELECT_TYPE orfds = *rfds;
EventTimeout timeout_sec =
(timeout
? (EMACS_SECS (*timeout) * kEventDurationSecond
+ EMACS_USECS (*timeout) * kEventDurationMicrosecond)
: kEventDurationForever);
for (i = 1; i < n; i++)
if (FD_ISSET (i, rfds))
break;
if (i == n)
{
EventTimeout timeout_sec =
(timeout
? (EMACS_SECS (*timeout) * kEventDurationSecond
+ EMACS_USECS (*timeout) * kEventDurationMicrosecond)
: kEventDurationForever);
nsocks++;
if (nsocks == 0)
{
BLOCK_INPUT;
err = ReceiveNextEvent (0, NULL, timeout_sec,
kEventLeaveInQueue, NULL);
UNBLOCK_INPUT;
if (err == noErr)
{
FD_ZERO (rfds);
FD_SET (0, rfds);
return 1;
}
else
return 0;
}
}
if (timeout)
{
remaining_time = *timeout;
EMACS_GET_TIME (now);
EMACS_ADD_TIME (end_time, now, remaining_time);
}
FD_CLR (0, rfds);
do
{
EMACS_TIME select_timeout;
SELECT_TYPE orfds = *rfds;
int r;
/* Avoid initial overhead of RunLoop setup for the case that
some input is already available. */
EMACS_SET_SECS_USECS (select_timeout, 0, 0);
r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout);
if (r != 0 || timeout_sec == 0.0)
return r;
EMACS_SET_SECS_USECS (select_timeout, 0, 20000);
*rfds = orfds;
if (timeout && EMACS_TIME_LT (remaining_time, select_timeout))
select_timeout = remaining_time;
#ifdef SELECT_USE_CFSOCKET
if (timeout_sec > 0 && timeout_sec <= SELECT_TIMEOUT_THRESHOLD_RUNLOOP)
goto poll_periodically;
r = select (n, &orfds, wfds, efds, &select_timeout);
BLOCK_INPUT;
err = ReceiveNextEvent (0, NULL, kEventDurationNoWait,
kEventLeaveInQueue, NULL);
UNBLOCK_INPUT;
if (r > 0)
{
*rfds = orfds;
if (err == noErr)
{
CFRunLoopRef runloop =
(CFRunLoopRef) GetCFRunLoopFromEventLoop (GetCurrentEventLoop ());
EventTypeSpec specs[] = {{EVENT_CLASS_SOCK, 0}};
#ifdef SELECT_INVALIDATE_CFSOCKET
CFSocketRef *shead, *s;
#else
CFRunLoopSourceRef *shead, *s;
#endif
BLOCK_INPUT;
#ifdef SELECT_INVALIDATE_CFSOCKET
shead = xmalloc (sizeof (CFSocketRef) * nsocks);
#else
shead = xmalloc (sizeof (CFRunLoopSourceRef) * nsocks);
#endif
s = shead;
for (i = 1; i < n; i++)
if (FD_ISSET (i, rfds))
{
FD_SET (0, rfds);
r++;
CFSocketRef socket =
CFSocketCreateWithNative (NULL, i, kCFSocketReadCallBack,
socket_callback, NULL);
CFRunLoopSourceRef source =
CFSocketCreateRunLoopSource (NULL, socket, 0);
#ifdef SELECT_INVALIDATE_CFSOCKET
CFSocketSetSocketFlags (socket, 0);
#endif
CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode);
#ifdef SELECT_INVALIDATE_CFSOCKET
CFRelease (source);
*s = socket;
#else
CFRelease (socket);
*s = source;
#endif
s++;
}
return r;
}
else if (err == noErr)
{
FD_ZERO (rfds);
FD_SET (0, rfds);
return 1;
}
if (timeout)
{
EMACS_GET_TIME (now);
EMACS_SUB_TIME (remaining_time, end_time, now);
}
err = ReceiveNextEvent (0, NULL, timeout_sec, kEventLeaveInQueue, NULL);
do
{
--s;
#ifdef SELECT_INVALIDATE_CFSOCKET
CFSocketInvalidate (*s);
#else
CFRunLoopRemoveSource (runloop, *s, kCFRunLoopDefaultMode);
#endif
CFRelease (*s);
}
while (s != shead);
xfree (shead);
if (err)
{
FD_ZERO (rfds);
r = 0;
}
else
{
FlushEventsMatchingListFromQueue (GetCurrentEventQueue (),
GetEventTypeCount (specs),
specs);
EMACS_SET_SECS_USECS (select_timeout, 0, 0);
r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout);
}
UNBLOCK_INPUT;
return r;
}
#endif /* SELECT_USE_CFSOCKET */
}
while (!timeout || EMACS_TIME_LT (now, end_time));
return 0;
poll_periodically:
{
EMACS_TIME end_time, now, remaining_time;
SELECT_TYPE orfds = *rfds, owfds, oefds;