1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-01-16 17:19:41 +00:00

(Vmac_ts_active_input_buf) [USE_MAC_TSM]: Add extern.

(fast_find_position, x_y_to_hpos_vpos, mac_ax_selected_text_range):
(mac_ax_number_of_characters): Add externs.
(mac_get_selected_range, mac_store_buffer_text_to_unicode_chars)
[USE_MAC_TSM]: Likewise.
(mac_handle_text_input_event) [MAC_OSX]:
Handle kEventTextInputOffsetToPos for no active input area case.
Handle kEventTextInputPosToOffset and kEventTextInputGetSelectedText.
(mac_handle_document_access_event)
[MAC_OS_X_VERSION_MAX_ALLOWED >= 1030]: New function.
(install_application_handler) [MAC_OSX]: Register handlers for
kEventTextInputPosToOffset and kEventTextInputGetSelectedText.
(install_application_handler) [MAC_OS_X_VERSION_MAX_ALLOWED >= 1030]:
Register mac_handle_document_access_event.
This commit is contained in:
YAMAMOTO Mitsuharu 2008-04-23 08:56:20 +00:00
parent e1adb1392e
commit 415cf4bcd1

View File

@ -118,7 +118,7 @@ extern Lisp_Object Qhi_command;
static TSMDocumentID tsm_document_id;
extern Lisp_Object Qtext_input;
extern Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
extern Lisp_Object Vmac_ts_active_input_overlay;
extern Lisp_Object Vmac_ts_active_input_overlay, Vmac_ts_active_input_buf;
extern Lisp_Object Qbefore_string;
#endif
@ -134,6 +134,14 @@ extern OSStatus mac_store_event_ref_as_apple_event P_ ((AEEventClass, AEEventID,
EventRef, UInt32,
const EventParamName *,
const EventParamType *));
extern int fast_find_position P_ ((struct window *, int, int *, int *,
int *, int *, Lisp_Object));
extern struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
int *, int *, int *, int *, int *));
extern void mac_ax_selected_text_range P_ ((struct frame *, CFRange *));
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
extern unsigned int mac_ax_number_of_characters P_ ((struct frame *));
#endif
#if USE_MAC_TSM
extern OSStatus mac_restore_keyboard_input_source P_ ((void));
@ -374,6 +382,10 @@ mac_handle_mouse_event (next_handler, event, data)
}
#if USE_MAC_TSM
extern void mac_get_selected_range P_ ((struct window *, CFRange *));
extern int mac_store_buffer_text_to_unicode_chars P_ ((struct buffer *,
int, int, UniChar *));
static pascal OSStatus
mac_handle_text_input_event (next_handler, event, data)
EventHandlerCallRef next_handler;
@ -512,43 +524,269 @@ mac_handle_text_input_event (next_handler, event, data)
case kEventTextInputOffsetToPos:
{
long byte_offset;
struct frame *f;
struct window *w;
Point p;
if (!OVERLAYP (Vmac_ts_active_input_overlay))
err = GetEventParameter (event, kEventParamTextInputSendTextOffset,
typeLongInteger, NULL, sizeof (long), NULL,
&byte_offset);
if (err != noErr)
break;
/* Strictly speaking, this is not always correct because
previous events may change some states about display. */
if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string)))
if (STRINGP (Vmac_ts_active_input_buf)
&& SBYTES (Vmac_ts_active_input_buf) != 0)
{
/* Active input area is displayed around the current point. */
f = SELECTED_FRAME ();
w = XWINDOW (f->selected_window);
}
else if (WINDOWP (echo_area_window))
{
/* Active input area is displayed in the echo area. */
w = XWINDOW (echo_area_window);
f = WINDOW_XFRAME (w);
if (!OVERLAYP (Vmac_ts_active_input_overlay))
break;
/* Strictly speaking, this is not always correct because
previous events may change some states about display. */
if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string)))
{
/* Active input area is displayed around the current point. */
f = SELECTED_FRAME ();
w = XWINDOW (f->selected_window);
}
else if (WINDOWP (echo_area_window))
{
/* Active input area is displayed in the echo area. */
w = XWINDOW (echo_area_window);
f = WINDOW_XFRAME (w);
}
else
break;
p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
+ WINDOW_LEFT_FRINGE_WIDTH (w)
+ f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f));
p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y)
+ FONT_BASE (FRAME_FONT (f))
+ f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f));
}
else
break;
{
#ifndef MAC_OSX
break;
#else /* MAC_OSX */
CFRange sel_range;
int charpos;
int hpos, vpos, x, y;
struct glyph_row *row;
struct glyph *glyph;
XFontStruct *font;
f = mac_focus_frame (&one_mac_display_info);
w = XWINDOW (f->selected_window);
mac_get_selected_range (w, &sel_range);
charpos = (BUF_BEGV (XBUFFER (w->buffer)) + sel_range.location
+ byte_offset / (long) sizeof (UniChar));
if (!fast_find_position (w, charpos, &hpos, &vpos, &x, &y, Qnil))
{
result = errOffsetInvalid;
break;
}
row = MATRIX_ROW (w->current_matrix, vpos);
glyph = row->glyphs[TEXT_AREA] + hpos;
if (glyph->type != CHAR_GLYPH || glyph->glyph_not_available_p)
break;
p.h = (WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x)
+ f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f));
p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, y)
+ row->visible_height
+ f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f));
font = FACE_FROM_ID (f, glyph->face_id)->font;
if (font)
{
Fixed point_size = Long2Fix (font->mac_fontsize);
short height = row->visible_height;
short ascent = row->ascent;
SetEventParameter (event,
kEventParamTextInputReplyPointSize,
typeFixed, sizeof (Fixed), &point_size);
SetEventParameter (event,
kEventParamTextInputReplyLineHeight,
typeShortInteger, sizeof (short), &height);
SetEventParameter (event,
kEventParamTextInputReplyLineAscent,
typeShortInteger, sizeof (short), &ascent);
if (font->mac_fontnum != -1)
{
OSStatus err1;
FMFont fm_font;
FMFontStyle style;
err1 = FMGetFontFromFontFamilyInstance (font->mac_fontnum,
font->mac_fontface,
&fm_font, &style);
if (err1 == noErr)
SetEventParameter (event, kEventParamTextInputReplyFMFont,
typeUInt32, sizeof (UInt32), &fm_font);
else
{
long qd_font = font->mac_fontnum;
SetEventParameter (event, kEventParamTextInputReplyFont,
typeLongInteger, sizeof (long),
&qd_font);
}
}
else if (font->mac_style)
{
OSStatus err1;
ATSUFontID font_id;
err1 = ATSUGetAttribute (font->mac_style, kATSUFontTag,
sizeof (ATSUFontID), &font_id,
NULL);
if (err1 == noErr)
SetEventParameter (event, kEventParamTextInputReplyFMFont,
typeUInt32, sizeof (UInt32), &font_id);
}
else
abort ();
}
#endif /* MAC_OSX */
}
p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
+ WINDOW_LEFT_FRINGE_WIDTH (w)
+ f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f));
p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y)
+ FONT_BASE (FRAME_FONT (f))
+ f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f));
err = SetEventParameter (event, kEventParamTextInputReplyPoint,
typeQDPoint, sizeof (typeQDPoint), &p);
typeQDPoint, sizeof (Point), &p);
if (err == noErr)
result = noErr;
}
break;
#ifdef MAC_OSX
case kEventTextInputPosToOffset:
{
Point point;
Boolean leading_edge_p = true;
struct frame *f;
int x, y;
Lisp_Object window;
enum window_part part;
long region_class = kTSMOutsideOfBody, byte_offset = 0;
err = GetEventParameter (event, kEventParamTextInputSendCurrentPoint,
typeQDPoint, NULL, sizeof (Point), NULL,
&point);
if (err != noErr)
break;
GetEventParameter (event, kEventParamTextInputReplyLeadingEdge,
typeBoolean, NULL, sizeof (Boolean), NULL,
&leading_edge_p);
f = mac_focus_frame (&one_mac_display_info);
x = point.h - (f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f));
y = point.v - (f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f));
window = window_from_coordinates (f, x, y, &part, 0, 0, 1);
if (WINDOWP (window) && EQ (window, f->selected_window))
{
struct window *w;
struct buffer *b;
/* Convert to window-relative pixel coordinates. */
w = XWINDOW (window);
frame_to_window_pixel_xy (w, &x, &y);
/* Are we in a window whose display is up to date?
And verify the buffer's text has not changed. */
b = XBUFFER (w->buffer);
if (part == ON_TEXT
&& EQ (w->window_end_valid, w->buffer)
&& XINT (w->last_modified) == BUF_MODIFF (b)
&& XINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
{
int hpos, vpos, area;
struct glyph *glyph;
/* Find the glyph under X/Y. */
glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, 0, 0, &area);
if (glyph != NULL && area == TEXT_AREA)
{
byte_offset = ((glyph->charpos - BUF_BEGV (b))
* sizeof (UniChar));
region_class = kTSMInsideOfBody;
}
}
}
err = SetEventParameter (event, kEventParamTextInputReplyRegionClass,
typeLongInteger, sizeof (long),
&region_class);
if (err == noErr)
err = SetEventParameter (event, kEventParamTextInputReplyTextOffset,
typeLongInteger, sizeof (long),
&byte_offset);
if (err == noErr)
result = noErr;
}
break;
case kEventTextInputGetSelectedText:
{
struct frame *f = mac_focus_frame (&one_mac_display_info);
struct window *w = XWINDOW (f->selected_window);
struct buffer *b = XBUFFER (w->buffer);
CFRange sel_range;
int start, end;
UniChar *characters, c;
if (poll_suppress_count == 0 && !NILP (Vinhibit_quit))
/* Don't try to get buffer contents as the gap might be
being altered. */
break;
mac_get_selected_range (w, &sel_range);
if (sel_range.length == 0)
{
Boolean leading_edge_p;
err = GetEventParameter (event,
kEventParamTextInputReplyLeadingEdge,
typeBoolean, NULL, sizeof (Boolean), NULL,
&leading_edge_p);
if (err != noErr)
break;
start = BUF_BEGV (b) + sel_range.location;
if (!leading_edge_p)
start--;
end = start + 1;
characters = &c;
if (start < BUF_BEGV (b) || end > BUF_ZV (b))
break;
}
else
{
start = BUF_BEGV (b) + sel_range.location;
end = start + sel_range.length;
characters = xmalloc (sel_range.length * sizeof (UniChar));
}
if (mac_store_buffer_text_to_unicode_chars (b, start, end, characters))
err = SetEventParameter (event, kEventParamTextInputReplyText,
typeUnicodeText,
sel_range.length * sizeof (UniChar),
characters);
if (characters != &c)
xfree (characters);
if (err == noErr)
result = noErr;
}
break;
#endif /* MAC_OSX */
default:
abort ();
}
@ -559,6 +797,86 @@ mac_handle_text_input_event (next_handler, event, data)
names, types);
return result;
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
static pascal OSStatus
mac_handle_document_access_event (next_handler, event, data)
EventHandlerCallRef next_handler;
EventRef event;
void *data;
{
OSStatus err, result;
struct frame *f = mac_focus_frame (&one_mac_display_info);
result = CallNextEventHandler (next_handler, event);
if (result != eventNotHandledErr)
return result;
switch (GetEventKind (event))
{
case kEventTSMDocumentAccessGetLength:
{
CFIndex count = mac_ax_number_of_characters (f);
err = SetEventParameter (event, kEventParamTSMDocAccessCharacterCount,
typeCFIndex, sizeof (CFIndex), &count);
if (err == noErr)
result = noErr;
}
break;
case kEventTSMDocumentAccessGetSelectedRange:
{
CFRange sel_range;
mac_ax_selected_text_range (f, &sel_range);
err = SetEventParameter (event,
kEventParamTSMDocAccessReplyCharacterRange,
typeCFRange, sizeof (CFRange), &sel_range);
if (err == noErr)
result = noErr;
}
break;
case kEventTSMDocumentAccessGetCharacters:
{
struct buffer *b = XBUFFER (XWINDOW (f->selected_window)->buffer);
CFRange range;
Ptr characters;
int start, end;
if (poll_suppress_count == 0 && !NILP (Vinhibit_quit))
/* Don't try to get buffer contents as the gap might be
being altered. */
break;
err = GetEventParameter (event,
kEventParamTSMDocAccessSendCharacterRange,
typeCFRange, NULL, sizeof (CFRange), NULL,
&range);
if (err == noErr)
err = GetEventParameter (event,
kEventParamTSMDocAccessSendCharactersPtr,
typePtr, NULL, sizeof (Ptr), NULL,
&characters);
if (err != noErr)
break;
start = BUF_BEGV (b) + range.location;
end = start + range.length;
if (mac_store_buffer_text_to_unicode_chars (b, start, end,
(UniChar *) characters))
result = noErr;
}
break;
default:
abort ();
}
return result;
}
#endif
#endif
OSStatus
@ -607,13 +925,32 @@ install_application_handler ()
static const EventTypeSpec specs[] =
{{kEventClassTextInput, kEventTextInputUpdateActiveInputArea},
{kEventClassTextInput, kEventTextInputUnicodeForKeyEvent},
{kEventClassTextInput, kEventTextInputOffsetToPos}};
{kEventClassTextInput, kEventTextInputOffsetToPos},
#ifdef MAC_OSX
{kEventClassTextInput, kEventTextInputPosToOffset},
{kEventClassTextInput, kEventTextInputGetSelectedText}
#endif
};
err = InstallApplicationEventHandler (NewEventHandlerUPP
(mac_handle_text_input_event),
GetEventTypeCount (specs),
specs, NULL, NULL);
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
if (err == noErr)
{
static const EventTypeSpec specs[] =
{{kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetLength},
{kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetSelectedRange},
{kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetCharacters}};
err = InstallApplicationEventHandler (mac_handle_document_access_event,
GetEventTypeCount (specs),
specs, NULL, NULL);
}
#endif
#endif
if (err == noErr)