aboutsummaryrefslogtreecommitdiffstats
path: root/src/androidterm.c
diff options
context:
space:
mode:
authorPo Lu2022-12-31 18:04:18 +0800
committerPo Lu2022-12-31 18:04:18 +0800
commitcfbc8a5dbcd362b69b37b4e6832ae4a31834364c (patch)
treece003d03c4ae98f4e1d02186d78e5ae6e0d36e55 /src/androidterm.c
parent785095c416f9bae43d2947849282b814e2c7942e (diff)
downloademacs-cfbc8a5dbcd362b69b37b4e6832ae4a31834364c.tar.gz
emacs-cfbc8a5dbcd362b69b37b4e6832ae4a31834364c.zip
Bring up the Android operating system and its window system
* .dir-locals.el (c-mode): Add ANDROID_EXPORT noise macro. * .gitignore: Add new files to ignore. * Makefile.in: Adjust for Android. * admin/merge-gnulib: Add new warning. * configure.ac: Detect Android. Run cross-configuration for Android when appropriate. * etc/DEBUG: Document how to debug Emacs on Android. * java/AndroidManifest.xml: * java/Makefile.in: * java/README: * java/debug.sh: * java/org/gnu/emacs/EmacsActivity.java (EmacsActivity): * java/org/gnu/emacs/EmacsApplication.java (EmacsApplication): * java/org/gnu/emacs/EmacsCopyArea.java (EmacsCopyArea): * java/org/gnu/emacs/EmacsDrawLine.java (EmacsDrawLine): * java/org/gnu/emacs/EmacsDrawPoint.java (EmacsDrawPoint): * java/org/gnu/emacs/EmacsDrawRectangle.java (EmacsDrawRectangle): * java/org/gnu/emacs/EmacsDrawable.java (EmacsDrawable): * java/org/gnu/emacs/EmacsFillPolygon.java (EmacsFillPolygon): * java/org/gnu/emacs/EmacsFillRectangle.java (EmacsFillRectangle): * java/org/gnu/emacs/EmacsFontDriver.java (EmacsFontDriver): * java/org/gnu/emacs/EmacsGC.java (EmacsGC): * java/org/gnu/emacs/EmacsHandleObject.java (EmacsHandleObject): * java/org/gnu/emacs/EmacsNative.java (EmacsNative): * java/org/gnu/emacs/EmacsPaintQueue.java (EmacsPaintQueue): * java/org/gnu/emacs/EmacsPaintReq.java (EmacsPaintReq): * java/org/gnu/emacs/EmacsPixmap.java (EmacsPixmap): * java/org/gnu/emacs/EmacsSdk7FontDriver.java (EmacsSdk7FontDriver): * java/org/gnu/emacs/EmacsService.java (class Holder<T>) (EmacsService): * java/org/gnu/emacs/EmacsSurfaceView.java (EmacsSurfaceView): * java/org/gnu/emacs/EmacsThread.java (EmacsThread): * java/org/gnu/emacs/EmacsView.java (EmacsView): * java/org/gnu/emacs/EmacsWindow.java (EmacsWindow): New files and classes. * lib-src/Makefile.in (srcdir): * lib/Makefile.in (VPATH): (HAVE_NATIVE_COMP): (libgnu_a_SOURCES): (DEPFLAGS): Configure correctly for cross-compiling. * lib/faccessat.c: * lib/fpending.c (__fpending): * lib/open.c: * lib/unistd.c (_GL_UNISTD_INLINE): Temporary adjustments to gnulib. * lisp/frame.el (display-graphic-p): (display-screens): (display-pixel-height): (display-pixel-width): (display-mm-height): (display-mm-width): (display-backing-store): (display-save-under): (display-planes): (display-color-cells): (display-visual-class): Adjust for new window system `android'. * lisp/image/wallpaper.el (x-open-connection): Add declaration. * lisp/loadup.el (featurep): Load up files for Android. * lisp/net/eww.el (eww-form-submit, eww-form-file) (eww-form-checkbox, eww-form-select): Adjust faces for android. * lisp/term/android-win.el: New file. * src/Makefile.in: Add new targets emacs.so and android-emacs, then adjust for cross compilation. * src/alloc.c (cleanup_vector): Clean up Android font entities as well. (garbage_collect): Mark androidterm. * src/android-emacs.c (main): * src/android.c (ANDROID_THROW, enum android_fd_table_entry_flags) (struct android_emacs_service, struct android_emacs_pixmap) (struct android_graphics_point, struct android_event_container) (struct android_event_queue, android_run_select_thread) (android_handle_sigusr1, android_init_events, android_pending) (android_next_event, android_write_event, android_select) (android_run_debug_thread, android_user_full_name) (android_get_asset_name, android_fstat, android_fstatat) (android_file_access_p, android_hack_asset_fd, android_open) (android_close, JNICALL, android_init_emacs_service) (android_init_emacs_pixmap, android_init_graphics_point) (MAX_HANDLE, struct android_handle_entry, android_alloc_id) (android_destroy_handle, android_resolve_handle) (android_resolve_handle2, android_change_window_attributes) (android_create_window, android_set_window_background) (android_destroy_window, android_init_android_rect_class) (android_init_emacs_gc_class, android_create_gc, android_free_gc) (android_change_gc, android_set_clip_rectangles) (android_reparent_window, android_lookup_method) (android_clear_window, android_map_window, android_unmap_window) (android_resize_window, android_move_window, android_swap_buffers) (android_get_gc_values, android_set_foreground) (android_fill_rectangle, android_create_pixmap_from_bitmap_data) (android_set_clip_mask, android_set_fill_style, android_copy_area) (android_free_pixmap, android_set_background, android_fill_polygon) (android_draw_rectangle, android_draw_point, android_draw_line) (android_create_pixmap, android_set_ts_origin, android_clear_area): * src/android.h (ANDROID_EXPORT): * src/androidfns.c (android_display_info_for_name) (check_android_display_info, check_x_display_info, gamma_correct) (android_defined_color, android_decode_color) (android_implicitly_set_name, android_explicitly_set_name) (android_set_tool_bar_lines, android_change_tool_bar_height) (android_set_tab_bar_lines, android_change_tab_bar_height) (android_set_scroll_bar_default_height) (android_set_scroll_bar_default_width, android_icon_verify) (android_icon, android_make_gc, android_free_gcs) (unwind_create_frame, do_unwind_create_frame) (android_default_font_parameter, android_create_frame_window) (Fx_create_frame, Fxw_color_defined_p, Fxw_color_values) (Fxw_display_color_p, Fx_display_grayscale_p) (Fx_display_pixel_width, Fx_display_pixel_height) (Fx_display_planes, Fx_display_color_cells, Fx_display_screens) (Fx_display_mm_width, Fx_display_mm_height) (Fx_display_backing_store, Fx_display_visual_class) (Fx_display_monitor_attributes_list, Fx_frame_geometry) (Fx_frame_list_z_order, Fx_frame_restack) (Fx_mouse_absolute_pixel_position) (Fx_set_mouse_absolute_pixel_position, Fandroid_get_connection) (Fx_display_list, Fx_show_tip, Fx_hide_tip) (android_set_background_color, android_set_border_color) (android_set_cursor_color, android_set_cursor_type) (android_set_foreground_color) (android_set_child_frame_border_width) (android_set_internal_border_width, android_set_menu_bar_lines) (android_set_mouse_color, android_set_title, android_set_alpha) (android_frame_parm_handlers, syms_of_androidfns): * src/androidfont.c (struct android_emacs_font_driver) (struct android_emacs_font_spec, struct android_emacs_font_metrics) (struct android_emacs_font_object, struct android_integer) (struct androidfont_info, struct androidfont_entity) (android_init_font_driver, android_init_font_spec) (android_init_font_metrics, android_init_integer) (android_init_font_object, androidfont_get_cache) (androidfont_from_lisp, androidfont_from_java, androidfont_list) (androidfont_match, androidfont_draw, androidfont_open_font) (androidfont_close_font, androidfont_has_char) (androidfont_encode_char, androidfont_text_extents) (androidfont_list_family, androidfont_driver) (syms_of_androidfont_for_pdumper, syms_of_androidfont) (init_androidfont, android_finalize_font_entity): * src/androidgui.h (_ANDROID_GUI_H_, struct android_rectangle) (struct android_point, enum android_gc_function) (enum android_gc_value_mask, enum android_fill_style) (enum android_window_value_mask) (struct android_set_window_attributes, struct android_gc_values) (struct android_gc, enum android_swap_action, enum android_shape) (enum android_coord_mode, struct android_swap_info) (NativeRectangle, struct android_any_event) (struct android_key_event, struct android_configure_event) (union android_event): * src/androidterm.c (android_window_to_frame, android_clear_frame) (android_ring_bell, android_toggle_invisible_pointer) (android_update_begin, android_update_end, show_back_buffer) (android_flush_dirty_back_buffer_on, handle_one_android_event) (android_read_socket, android_frame_up_to_date) (android_buffer_flipping_unblocked_hook) (android_query_frame_background_color, android_parse_color) (android_alloc_nearest_color, android_query_colors) (android_mouse_position, android_get_focus_frame) (android_focus_frame, android_frame_rehighlight) (android_frame_raise_lower, android_make_frame_visible) (android_make_frame_invisible) (android_make_frame_visible_invisible, android_fullscreen_hook) (android_iconify_frame, android_set_window_size_1) (android_set_window_size, android_set_offset, android_set_alpha) (android_new_font, android_bitmap_icon, android_free_pixmap_hook) (android_free_frame_resources, android_delete_frame) (android_delete_terminal, android_scroll_run) (android_after_update_window_line, android_flip_and_flush) (android_clear_rectangle, android_reset_clip_rectangles) (android_clip_to_row, android_draw_fringe_bitmap) (android_set_cursor_gc, android_set_mouse_face_gc) (android_set_mode_line_face_gc, android_set_glyph_string_gc) (android_set_glyph_string_clipping) (android_set_glyph_string_clipping_exactly) (android_compute_glyph_string_overhangs) (android_clear_glyph_string_rect) (android_draw_glyph_string_background, android_fill_triangle) (android_make_point, android_inside_rect_p, android_clear_point) (android_draw_relief_rect, android_draw_box_rect) (HIGHLIGHT_COLOR_DARK_BOOST_LIMIT, android_setup_relief_color) (android_setup_relief_colors, android_draw_glyph_string_box) (android_draw_glyph_string_bg_rect, android_draw_image_relief) (android_draw_image_foreground, android_draw_image_foreground_1) (android_draw_image_glyph_string) (android_draw_stretch_glyph_string, android_draw_underwave) (android_draw_glyph_string_foreground) (android_draw_composite_glyph_string_foreground) (android_draw_glyphless_glyph_string_foreground) (android_draw_glyph_string, android_define_frame_cursor) (android_clear_frame_area, android_clear_under_internal_border) (android_draw_hollow_cursor, android_draw_bar_cursor) (android_draw_window_cursor, android_draw_vertical_window_border) (android_draw_window_divider, android_redisplay_interface) (frame_set_mouse_pixel_position, get_keysym_name) (android_create_terminal, android_term_init, syms_of_androidterm) (mark_androidterm): * src/androidterm.h (_ANDROID_TERM_H_, struct android_display_info) (struct android_output, FRAME_ANDROID_OUTPUT, XSCROLL_BAR): New files. * src/dired.c (file_attributes): Do not use openat on Android. * src/dispextern.h (No_Cursor): Define appropriately on Android. (struct glyph_string, struct face): Make gc field of type struct android_gc on Android. * src/dispnew.c (clear_current_matrices, clear_desired_matrices) (adjust_frame_glyphs_for_window_redisplay, free_glyphs) (update_frame, scrolling, char_ins_del_cost, update_frame_line) (init_display_interactive): Disable text terminal support completely on Android. Fix non-toolkit menus for non-X systems. * src/editfns.c (Fuser_full_name): Call android_user_full_name. * src/emacs.c (android_emacs_init): Make main this on Android. Prohibit argv sorting from exceeding end of argv. * src/epaths.in: Add path definitions for Android. * src/fileio.c (file_access_p): Call android_file_access_p. (file_name_directory): Avoid using openat on Android. (Fcopy_file): Adjust to call sys_fstat instead. (file_directory_p): (Finsert_file_contents): (write_region): Likewise. * src/filelock.c: * src/fns.c (Flocale_info): Pacify warning on Android. * src/font.c (font_make_entity_android): New function. * src/font.h: * src/frame.c (Fframep): (Fwindow_system): Handle new window system `android'. Update doc strings. (Fmake_terminal_frame): Disable on Android. (gui_display_get_resource): Disable get_string_resource_hook on Android. (syms_of_frame): New defsym `android'. * src/frame.h (GCALIGNED_STRUCT): Add new output data for Android. (ENUM_BF): Expand enumerator size. (FRAME_ANDROID_P, FRAME_WINDOW_P, MOUSE_HL_INFO): Add definitions for Android. * src/image.c (GET_PIXEL): (image_create_bitmap_from_file): (image_create_x_image_and_pixmap_1): (image_get_x_image): (slurp_file): (lookup_rgb_color): (image_to_emacs_colors): (image_from_emacs_colors): (image_pixmap_draw_cross): (image_disable_image): (MaskForeground): (gif_load): Add stubs for Android. * src/lisp.h: * src/lread.c (safe_to_load_version, maybe_swap_for_eln1, openp): * src/pdumper.c (pdumper_load): Call sys_fstat instead of fstat. * src/process.c (wait_reading_process_output): Use android_select instead of pselect. * src/scroll.c: Disable on Android. * src/sysdep.c (widen_foreground_group, reset_sys_modes) (init_signals, emacs_fstatat, sys_fstat): New function. (emacs_open, emacs_open_noquit, emacs_close): Implement differently on Android. (close_output_streams): Disable what is not required on Android. * src/term.c (OUTPUT1_IF, encode_terminal_code, string_cost) (string_cost_one_line, per_line_cost, calculate_costs) (struct fkey_table, tty_append_glyph, produce_glyphs) (tty_capable_p, Fsuspend_tty, Fresume_tty, device, init_tty) (maybe_fatal, syms_of_term): Disable text terminal support on Android. * src/termhooks.h (enum output_method): Add android output method. (GCALIGNED_STRUCT, TERMINAL_FONT_CACHE): Define for Android. * src/terminal.c (Fterminal_live_p): Implement for Android. * src/verbose.mk.in (AM_V_GLOBALS): Add JAVAC and DX. * src/xdisp.c (redisplay_internal): Disable text terminals on Android. (display_menu_bar): (display_tty_menu_item): (draw_row_with_mouse_face): (expose_frame): Make the non toolkit menu bar work on Android. * src/xfaces.c (GCGraphicsExposures): (x_create_gc): (x_free_gc): (Fx_load_color_file): Define for Android. * xcompile/Makefile.in (top_srcdir): (top_builddir): * xcompile/README: * xcompile/langinfo.h (nl_langinfo): New files.
Diffstat (limited to 'src/androidterm.c')
-rw-r--r--src/androidterm.c3161
1 files changed, 3161 insertions, 0 deletions
diff --git a/src/androidterm.c b/src/androidterm.c
new file mode 100644
index 00000000000..bb3c2a29737
--- /dev/null
+++ b/src/androidterm.c
@@ -0,0 +1,3161 @@
1/* Communication module for Android terminals.
2
3Copyright (C) 2023 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or (at
10your option) any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19
20#include <config.h>
21#include <stdio.h>
22
23#include "lisp.h"
24#include "androidterm.h"
25#include "keyboard.h"
26#include "blockinput.h"
27#include "android.h"
28#include "buffer.h"
29#include "window.h"
30
31/* This is a chain of structures for all the X displays currently in
32 use. */
33
34struct android_display_info *x_display_list;
35
36
37
38/* Android terminal interface functions. */
39
40#ifndef ANDROID_STUBIFY
41
42enum
43 {
44 ANDROID_EVENT_NORMAL,
45 ANDROID_EVENT_GOTO_OUT,
46 ANDROID_EVENT_DROP,
47 };
48
49static struct frame *
50android_window_to_frame (struct android_display_info *dpyinfo,
51 android_window wdesc)
52{
53 Lisp_Object tail, frame;
54 struct frame *f;
55
56 if (wdesc == ANDROID_NONE)
57 return NULL;
58
59 FOR_EACH_FRAME (tail, frame)
60 {
61 f = XFRAME (frame);
62
63 if (!FRAME_ANDROID_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
64 continue;
65
66 if (FRAME_ANDROID_WINDOW (f) == wdesc)
67 return f;
68 }
69
70 return NULL;
71}
72
73static void
74android_clear_frame (struct frame *f)
75{
76 /* Clearing the frame will erase any cursor, so mark them all as no
77 longer visible. */
78 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
79 android_clear_window (FRAME_ANDROID_WINDOW (f));
80}
81
82static void
83android_ring_bell (struct frame *f)
84{
85 /* TODO */
86}
87
88static void
89android_toggle_invisible_pointer (struct frame *f, bool invisible)
90{
91 /* TODO */
92}
93
94/* Start an update of frame F. This function is installed as a hook
95 for update_begin, i.e. it is called when update_begin is called.
96 This function is called prior to calls to gui_update_window_begin
97 for each window being updated. Currently, there is nothing to do
98 here because all interesting stuff is done on a window basis. */
99
100static void
101android_update_begin (struct frame *f)
102{
103 /* The frame is no longer complete, as it is in the midst of an
104 update. */
105 FRAME_ANDROID_COMPLETE_P (f) = false;
106}
107
108/* End update of frame F. This function is installed as a hook in
109 update_end. */
110
111static void
112android_update_end (struct frame *f)
113{
114 /* Mouse highlight may be displayed again. */
115 MOUSE_HL_INFO (f)->mouse_face_defer = false;
116}
117
118static void
119show_back_buffer (struct frame *f)
120{
121 struct android_swap_info swap_info;
122
123 memset (&swap_info, 0, sizeof (swap_info));
124 swap_info.swap_window = FRAME_ANDROID_WINDOW (f);
125 swap_info.swap_action = ANDROID_COPIED;
126 android_swap_buffers (&swap_info, 1);
127}
128
129/* Flip back buffers on F if it has undrawn content. */
130
131static void
132android_flush_dirty_back_buffer_on (struct frame *f)
133{
134 if (FRAME_GARBAGED_P (f)
135 || buffer_flipping_blocked_p ()
136 /* If the frame is not already up to date, do not flush buffers
137 on input, as that will result in flicker. */
138 || !FRAME_ANDROID_COMPLETE_P (f))
139 return;
140
141 show_back_buffer (f);
142}
143
144static int
145handle_one_android_event (struct android_display_info *dpyinfo,
146 union android_event *event, int *finish,
147 struct input_event *hold_quit)
148{
149 union android_event configureEvent;
150 struct frame *f, *any, *mouse_frame;
151 Mouse_HLInfo *hlinfo;
152
153 hlinfo = &dpyinfo->mouse_highlight;
154 *finish = ANDROID_EVENT_NORMAL;
155 any = android_window_to_frame (dpyinfo, event->xany.window);
156
157 switch (event->type)
158 {
159 case ANDROID_CONFIGURE_NOTIFY:
160 configureEvent = *event;
161
162 f = android_window_to_frame (dpyinfo,
163 configureEvent.xconfigure.window);
164
165 int width = configureEvent.xconfigure.width;
166 int height = configureEvent.xconfigure.height;
167
168 if (CONSP (frame_size_history))
169 frame_size_history_extra (f, build_string ("ConfigureNotify"),
170 FRAME_PIXEL_WIDTH (f),
171 FRAME_PIXEL_HEIGHT (f),
172 width, height, f->new_width,
173 f->new_height);
174
175 /* Even if the number of character rows and columns has
176 not changed, the font size may have changed, so we need
177 to check the pixel dimensions as well. */
178
179 if (width != FRAME_PIXEL_WIDTH (f)
180 || height != FRAME_PIXEL_HEIGHT (f)
181 || (f->new_size_p
182 && ((f->new_width >= 0 && width != f->new_width)
183 || (f->new_height >= 0 && height != f->new_height))))
184 {
185 change_frame_size (f, width, height, false, true, false);
186 android_clear_under_internal_border (f);
187 SET_FRAME_GARBAGED (f);
188 cancel_mouse_face (f);
189 }
190
191 goto OTHER;
192
193 case ANDROID_KEY_PRESS:
194
195 /* If mouse-highlight is an integer, input clears out
196 mouse highlighting. */
197 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
198 && (any == 0
199 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)
200 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window)))
201 {
202 mouse_frame = hlinfo->mouse_face_mouse_frame;
203
204 clear_mouse_face (hlinfo);
205 hlinfo->mouse_face_hidden = true;
206
207 if (mouse_frame)
208 android_flush_dirty_back_buffer_on (mouse_frame);
209 }
210
211 default:
212 goto OTHER;
213 }
214
215 OTHER:
216
217 return 0;
218}
219
220static int
221android_read_socket (struct terminal *terminal,
222 struct input_event *hold_quit)
223{
224 int count = 0;
225 struct android_display_info *dpyinfo;
226
227 dpyinfo = terminal->display_info.android;
228
229 block_input ();
230 while (android_pending ())
231 {
232 int finish;
233 union android_event event;
234
235 android_next_event (&event);
236 count += handle_one_android_event (dpyinfo, &event, &finish,
237 hold_quit);
238
239 if (finish == ANDROID_EVENT_GOTO_OUT)
240 break;
241 }
242 unblock_input ();
243
244 /* If the focus was just given to an auto-raising frame, raise it
245 now. */
246 if (dpyinfo->pending_autoraise_frame)
247 {
248 /* android_raise_frame (dpyinfo->pending_autoraise_frame);
249 TODO */
250 dpyinfo->pending_autoraise_frame = NULL;
251 }
252
253 return count;
254}
255
256static void
257android_frame_up_to_date (struct frame *f)
258{
259 eassert (FRAME_ANDROID_P (f));
260 block_input ();
261 FRAME_MOUSE_UPDATE (f);
262
263 if (!buffer_flipping_blocked_p ())
264 show_back_buffer (f);
265
266 /* The frame is now complete, as its contents have been drawn. */
267 FRAME_ANDROID_COMPLETE_P (f) = true;
268 unblock_input ();
269}
270
271static void
272android_buffer_flipping_unblocked_hook (struct frame *f)
273{
274 block_input ();
275 show_back_buffer (f);
276 unblock_input ();
277}
278
279static void
280android_query_frame_background_color (struct frame *f, Emacs_Color *bgcolor)
281{
282 unsigned long background;
283
284 background = FRAME_BACKGROUND_PIXEL (f);
285 bgcolor->pixel = background;
286
287 android_query_colors (f, bgcolor, 1);
288}
289
290int
291android_parse_color (struct frame *f, const char *color_name,
292 Emacs_Color *color)
293{
294 unsigned short r, g, b;
295 Lisp_Object tem, tem1;
296 unsigned long lisp_color;
297
298 if (parse_color_spec (color_name, &r, &g, &b))
299 {
300 color->red = r;
301 color->green = g;
302 color->blue = b;
303
304 return 1;
305 }
306
307 tem = x_display_list->color_map;
308 for (; CONSP (tem); tem = XCDR (tem))
309 {
310 tem1 = XCAR (tem);
311
312 if (CONSP (tem1)
313 && !xstrcasecmp (SSDATA (XCAR (tem1)), color_name))
314 {
315 lisp_color = XFIXNUM (XCDR (tem1));
316 color->red = RED_FROM_ULONG (lisp_color) * 257;
317 color->green = GREEN_FROM_ULONG (lisp_color) * 257;
318 color->blue = BLUE_FROM_ULONG (lisp_color) * 257;
319 return 1;
320 }
321 }
322
323 return 0;
324}
325
326bool
327android_alloc_nearest_color (struct frame *f, Emacs_Color *color)
328{
329 gamma_correct (f, color);
330 color->pixel = RGB_TO_ULONG (color->red / 256,
331 color->green / 256,
332 color->blue / 256);
333
334 return true;
335}
336
337void
338android_query_colors (struct frame *f, Emacs_Color *colors, int ncolors)
339{
340 int i;
341
342 for (i = 0; i < ncolors; ++i)
343 {
344 colors[i].red = RED_FROM_ULONG (colors[i].pixel) * 257;
345 colors[i].green = RED_FROM_ULONG (colors[i].pixel) * 257;
346 colors[i].blue = RED_FROM_ULONG (colors[i].pixel) * 257;
347 }
348}
349
350static void
351android_mouse_position (struct frame **fp, int insist,
352 Lisp_Object *bar_window,
353 enum scroll_bar_part *part, Lisp_Object *x,
354 Lisp_Object *y, Time *timestamp)
355{
356 /* TODO */
357}
358
359static Lisp_Object
360android_get_focus_frame (struct frame *f)
361{
362 Lisp_Object lisp_focus;
363 struct frame *focus;
364
365 focus = FRAME_DISPLAY_INFO (f)->focus_frame;
366
367 if (!focus)
368 return Qnil;
369
370 XSETFRAME (lisp_focus, focus);
371 return lisp_focus;
372}
373
374static void
375android_focus_frame (struct frame *f, bool noactivate)
376{
377 /* TODO */
378}
379
380static void
381android_frame_rehighlight (struct frame *f)
382{
383 /* TODO */
384}
385
386static void
387android_frame_raise_lower (struct frame *f, bool raise_flag)
388{
389 /* TODO */
390}
391
392void
393android_make_frame_visible (struct frame *f)
394{
395 android_map_window (FRAME_ANDROID_WINDOW (f));
396
397 SET_FRAME_VISIBLE (f, true);
398 SET_FRAME_ICONIFIED (f, false);
399}
400
401void
402android_make_frame_invisible (struct frame *f)
403{
404 android_unmap_window (FRAME_ANDROID_WINDOW (f));
405
406 SET_FRAME_VISIBLE (f, false);
407 SET_FRAME_ICONIFIED (f, false);
408}
409
410static void
411android_make_frame_visible_invisible (struct frame *f, bool visible)
412{
413 if (visible)
414 android_make_frame_visible (f);
415 else
416 android_make_frame_invisible (f);
417}
418
419static void
420android_fullscreen_hook (struct frame *f)
421{
422 /* TODO */
423}
424
425void
426android_iconify_frame (struct frame *f)
427{
428 /* TODO */
429}
430
431static void
432android_set_window_size_1 (struct frame *f, bool change_gravity,
433 int width, int height)
434{
435 if (change_gravity)
436 f->win_gravity = NorthWestGravity;
437
438 android_resize_window (FRAME_ANDROID_WINDOW (f), width,
439 height);
440
441 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
442 receive in the ConfigureNotify event; if we get what we asked
443 for, then the event won't cause the screen to become garbaged, so
444 we have to make sure to do it here. */
445 SET_FRAME_GARBAGED (f);
446}
447
448void
449android_set_window_size (struct frame *f, bool change_gravity,
450 int width, int height)
451{
452 block_input ();
453
454 android_set_window_size_1 (f, change_gravity, width, height);
455 android_clear_under_internal_border (f);
456
457 /* If cursor was outside the new size, mark it as off. */
458 mark_window_cursors_off (XWINDOW (f->root_window));
459
460 /* Clear out any recollection of where the mouse highlighting was,
461 since it might be in a place that's outside the new frame size.
462 Actually checking whether it is outside is a pain in the neck,
463 so don't try--just let the highlighting be done afresh with new size. */
464 cancel_mouse_face (f);
465
466 unblock_input ();
467
468 do_pending_window_change (false);
469}
470
471static void
472android_set_offset (struct frame *f, int xoff, int yoff,
473 int change_gravity)
474{
475 if (change_gravity > 0)
476 {
477 f->top_pos = yoff;
478 f->left_pos = xoff;
479 f->size_hint_flags &= ~ (XNegative | YNegative);
480 if (xoff < 0)
481 f->size_hint_flags |= XNegative;
482 if (yoff < 0)
483 f->size_hint_flags |= YNegative;
484 f->win_gravity = NorthWestGravity;
485 }
486
487 android_move_window (FRAME_ANDROID_WINDOW (f), xoff, yoff);
488}
489
490static void
491android_set_alpha (struct frame *f)
492{
493 /* TODO */
494}
495
496static Lisp_Object
497android_new_font (struct frame *f, Lisp_Object font_object, int fontset)
498{
499 struct font *font = XFONT_OBJECT (font_object);
500 int unit, font_ascent, font_descent;
501
502 if (fontset < 0)
503 fontset = fontset_from_font (font_object);
504 FRAME_FONTSET (f) = fontset;
505 if (FRAME_FONT (f) == font)
506 /* This font is already set in frame F. There's nothing more to
507 do. */
508 return font_object;
509
510 FRAME_FONT (f) = font;
511 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
512 FRAME_COLUMN_WIDTH (f) = font->average_width;
513 get_font_ascent_descent (font, &font_ascent, &font_descent);
514 FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
515
516 /* We could use a more elaborate calculation here. */
517 FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
518
519 /* Compute character columns occupied by scrollbar.
520
521 Don't do things differently for non-toolkit scrollbars
522 (Bug#17163). */
523 unit = FRAME_COLUMN_WIDTH (f);
524 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
525 FRAME_CONFIG_SCROLL_BAR_COLS (f)
526 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
527 else
528 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
529
530
531 /* Don't change the size of a tip frame; there's no point in doing it
532 because it's done in Fx_show_tip, and it leads to problems because
533 the tip frame has no widget. */
534 if (FRAME_ANDROID_WINDOW (f) != 0 && !FRAME_TOOLTIP_P (f))
535 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
536 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
537 false, Qfont);
538
539 return font_object;
540}
541
542static bool
543android_bitmap_icon (struct frame *f, Lisp_Object file)
544{
545 /* TODO */
546 return false;
547}
548
549static void
550android_free_pixmap_hook (struct frame *f, Emacs_Pixmap pixmap)
551{
552 android_free_pixmap (pixmap);
553}
554
555void
556android_free_frame_resources (struct frame *f)
557{
558 struct android_display_info *dpyinfo;
559 Mouse_HLInfo *hlinfo;
560
561 dpyinfo = FRAME_DISPLAY_INFO (f);
562 hlinfo = &dpyinfo->mouse_highlight;
563
564 block_input ();
565 free_frame_faces (f);
566
567 /* FRAME_ANDROID_WINDOW can be 0 if frame creation failed. */
568 if (FRAME_ANDROID_WINDOW (f))
569 android_destroy_window (FRAME_ANDROID_WINDOW (f));
570
571 android_free_gcs (f);
572
573 /* Free extra GCs allocated by android_setup_relief_colors. */
574 if (f->output_data.android->white_relief.gc)
575 {
576 android_free_gc (f->output_data.android->white_relief.gc);
577 f->output_data.android->white_relief.gc = 0;
578 }
579 if (f->output_data.android->black_relief.gc)
580 {
581 android_free_gc (f->output_data.android->black_relief.gc);
582 f->output_data.android->black_relief.gc = 0;
583 }
584
585 if (f == dpyinfo->focus_frame)
586 dpyinfo->focus_frame = 0;
587 if (f == dpyinfo->highlight_frame)
588 dpyinfo->highlight_frame = 0;
589 if (f == hlinfo->mouse_face_mouse_frame)
590 reset_mouse_highlight (hlinfo);
591
592 unblock_input ();
593}
594
595static void
596android_delete_frame (struct frame *f)
597{
598 android_free_frame_resources (f);
599 xfree (f->output_data.android);
600 f->output_data.android = NULL;
601}
602
603static void
604android_delete_terminal (struct terminal *terminal)
605{
606 error ("Cannot terminate connection to Android display server");
607}
608
609
610
611/* RIF functions. */
612
613static void
614android_scroll_run (struct window *w, struct run *run)
615{
616 struct frame *f = XFRAME (w->frame);
617 int x, y, width, height, from_y, to_y, bottom_y;
618
619 /* Get frame-relative bounding box of the text display area of W,
620 without mode lines. Include in this box the left and right
621 fringe of W. */
622 window_box (w, ANY_AREA, &x, &y, &width, &height);
623
624 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
625 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
626 bottom_y = y + height;
627
628 if (to_y < from_y)
629 {
630 /* Scrolling up. Make sure we don't copy part of the mode
631 line at the bottom. */
632 if (from_y + run->height > bottom_y)
633 height = bottom_y - from_y;
634 else
635 height = run->height;
636 }
637 else
638 {
639 /* Scrolling down. Make sure we don't copy over the mode line.
640 at the bottom. */
641 if (to_y + run->height > bottom_y)
642 height = bottom_y - to_y;
643 else
644 height = run->height;
645 }
646
647 block_input ();
648
649 /* Cursor off. Will be switched on again in gui_update_window_end. */
650 gui_clear_cursor (w);
651
652 android_copy_area (FRAME_ANDROID_WINDOW (f),
653 FRAME_ANDROID_WINDOW (f),
654 f->output_data.android->normal_gc,
655 x, from_y, width, height, x, to_y);
656
657 unblock_input ();
658}
659
660static void
661android_after_update_window_line (struct window *w, struct glyph_row *desired_row)
662{
663 eassert (w);
664
665 if (!desired_row->mode_line_p && !w->pseudo_window_p)
666 desired_row->redraw_fringe_bitmaps_p = true;
667}
668
669static void
670android_flip_and_flush (struct frame *f)
671{
672 block_input ();
673 show_back_buffer (f);
674
675 /* The frame is complete again as its contents were just
676 flushed. */
677 FRAME_ANDROID_COMPLETE_P (f) = true;
678 unblock_input ();
679}
680
681static void
682android_clear_rectangle (struct frame *f, struct android_gc *gc, int x,
683 int y, int width, int height)
684{
685 struct android_gc_values xgcv;
686
687 android_get_gc_values (gc, (ANDROID_GC_BACKGROUND
688 | ANDROID_GC_FOREGROUND),
689 &xgcv);
690 android_set_foreground (gc, xgcv.background);
691 android_fill_rectangle (FRAME_ANDROID_WINDOW (f), gc,
692 x, y, width, height);
693 android_set_foreground (gc, xgcv.foreground);
694}
695
696static void
697android_reset_clip_rectangles (struct frame *f, struct android_gc *gc)
698{
699 android_set_clip_mask (gc, ANDROID_NONE);
700}
701
702static void
703android_clip_to_row (struct window *w, struct glyph_row *row,
704 enum glyph_row_area area, struct android_gc *gc)
705{
706 struct android_rectangle clip_rect;
707 int window_x, window_y, window_width;
708
709 window_box (w, area, &window_x, &window_y, &window_width, 0);
710
711 clip_rect.x = window_x;
712 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
713 clip_rect.y = max (clip_rect.y, window_y);
714 clip_rect.width = window_width;
715 clip_rect.height = row->visible_height;
716
717 android_set_clip_rectangles (gc, 0, 0, &clip_rect, 1);
718}
719
720static void
721android_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
722 struct draw_fringe_bitmap_params *p)
723{
724 struct frame *f = XFRAME (WINDOW_FRAME (w));
725 struct android_gc *gc = f->output_data.android->normal_gc;
726 struct face *face = p->face;
727
728 /* Must clip because of partially visible lines. */
729 android_clip_to_row (w, row, ANY_AREA, gc);
730
731 if (p->bx >= 0 && !p->overlay_p)
732 {
733 /* In case the same realized face is used for fringes and for
734 something displayed in the text (e.g. face `region' on
735 mono-displays, the fill style may have been changed to
736 ANDROID_FILL_SOLID in
737 android_draw_glyph_string_background. */
738 if (face->stipple)
739 {
740 android_set_fill_style (face->gc, ANDROID_FILL_OPAQUE_STIPPLED);
741 android_fill_rectangle (FRAME_ANDROID_WINDOW (f), face->gc,
742 p->bx, p->by, p->nx, p->ny);
743 android_set_fill_style (face->gc, ANDROID_FILL_SOLID);
744
745 row->stipple_p = true;
746 }
747 else
748 {
749 android_set_background (face->gc, face->background);
750 android_clear_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
751 android_set_foreground (face->gc, face->foreground);
752 }
753 }
754
755 if (p->which)
756 {
757 android_drawable drawable;
758 char *bits;
759 android_pixmap pixmap, clipmask;
760 struct android_gc_values gcv;
761 unsigned long background, cursor_pixel;
762 int depth;
763
764 drawable = FRAME_ANDROID_WINDOW (f);
765 clipmask = ANDROID_NONE;
766 background = face->background;
767 cursor_pixel = f->output_data.android->cursor_pixel;
768 depth = FRAME_DISPLAY_INFO (f)->n_planes;
769
770 if (p->wd > 8)
771 bits = (char *) (p->bits + p->dh);
772 else
773 bits = (char *) p->bits + p->dh;
774
775 pixmap = android_create_pixmap_from_bitmap_data (bits, p->wd, p->h,
776 (p->cursor_p
777 ? (p->overlay_p
778 ? face->background
779 : cursor_pixel)
780 : face->foreground),
781 background, depth);
782
783 if (p->overlay_p)
784 {
785 clipmask = android_create_pixmap_from_bitmap_data (bits, p->wd, p->h,
786 1, 0, 0);
787
788 gcv.clip_mask = clipmask;
789 gcv.clip_x_origin = p->x;
790 gcv.clip_y_origin = p->y;
791 android_change_gc (gc, (ANDROID_GC_CLIP_MASK
792 | ANDROID_GC_CLIP_X_ORIGIN
793 | ANDROID_GC_CLIP_Y_ORIGIN),
794 &gcv);
795 }
796
797 android_copy_area (pixmap, drawable, gc, 0, 0, p->wd, p->h,
798 p->x, p->y);
799 android_free_pixmap (pixmap);
800
801 if (p->overlay_p)
802 {
803 gcv.clip_mask = ANDROID_NONE;
804 android_change_gc (gc, ANDROID_GC_CLIP_MASK, &gcv);
805 android_free_pixmap (clipmask);
806 }
807 }
808
809 android_reset_clip_rectangles (f, gc);
810}
811
812/* Set S->gc to a suitable GC for drawing glyph string S in cursor
813 face. */
814
815static void
816android_set_cursor_gc (struct glyph_string *s)
817{
818 if (s->font == FRAME_FONT (s->f)
819 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
820 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
821 && !s->cmp)
822 s->gc = s->f->output_data.android->cursor_gc;
823 else
824 {
825 /* Cursor on non-default face: must merge. */
826 struct android_gc_values xgcv;
827 unsigned long mask;
828
829 xgcv.background = s->f->output_data.android->cursor_pixel;
830 xgcv.foreground = s->face->background;
831
832 /* If the glyph would be invisible, try a different foreground. */
833 if (xgcv.foreground == xgcv.background)
834 xgcv.foreground = s->face->foreground;
835 if (xgcv.foreground == xgcv.background)
836 xgcv.foreground = s->f->output_data.android->cursor_foreground_pixel;
837 if (xgcv.foreground == xgcv.background)
838 xgcv.foreground = s->face->foreground;
839
840 /* Make sure the cursor is distinct from text in this face. */
841 if (xgcv.background == s->face->background
842 && xgcv.foreground == s->face->foreground)
843 {
844 xgcv.background = s->face->foreground;
845 xgcv.foreground = s->face->background;
846 }
847
848 mask = (ANDROID_GC_FOREGROUND | ANDROID_GC_BACKGROUND);
849
850 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
851 android_change_gc (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
852 mask, &xgcv);
853 else
854 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
855 = android_create_gc (mask, &xgcv);
856
857 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
858 }
859}
860
861
862/* Set up S->gc of glyph string S for drawing text in mouse face. */
863
864static void
865android_set_mouse_face_gc (struct glyph_string *s)
866{
867 if (s->font == s->face->font)
868 s->gc = s->face->gc;
869 else
870 {
871 /* Otherwise construct scratch_cursor_gc with values from FACE
872 except for FONT. */
873 struct android_gc_values xgcv;
874 unsigned long mask;
875
876 xgcv.background = s->face->background;
877 xgcv.foreground = s->face->foreground;
878
879 mask = (ANDROID_GC_FOREGROUND | ANDROID_GC_BACKGROUND);
880
881 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
882 android_change_gc (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
883 mask, &xgcv);
884 else
885 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
886 = android_create_gc (mask, &xgcv);
887
888 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
889 }
890
891 eassert (s->gc != 0);
892}
893
894
895/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
896 Faces to use in the mode line have already been computed when the
897 matrix was built, so there isn't much to do, here. */
898
899static void
900android_set_mode_line_face_gc (struct glyph_string *s)
901{
902 s->gc = s->face->gc;
903}
904
905/* Set S->gc of glyph string S for drawing that glyph string. Set
906 S->stippled_p to a non-zero value if the face of S has a stipple
907 pattern. */
908
909static void
910android_set_glyph_string_gc (struct glyph_string *s)
911{
912 prepare_face_for_display (s->f, s->face);
913
914 if (s->hl == DRAW_NORMAL_TEXT)
915 {
916 s->gc = s->face->gc;
917 s->stippled_p = s->face->stipple != 0;
918 }
919 else if (s->hl == DRAW_INVERSE_VIDEO)
920 {
921 android_set_mode_line_face_gc (s);
922 s->stippled_p = s->face->stipple != 0;
923 }
924 else if (s->hl == DRAW_CURSOR)
925 {
926 android_set_cursor_gc (s);
927 s->stippled_p = false;
928 }
929 else if (s->hl == DRAW_MOUSE_FACE)
930 {
931 android_set_mouse_face_gc (s);
932 s->stippled_p = s->face->stipple != 0;
933 }
934 else if (s->hl == DRAW_IMAGE_RAISED
935 || s->hl == DRAW_IMAGE_SUNKEN)
936 {
937 s->gc = s->face->gc;
938 s->stippled_p = s->face->stipple != 0;
939 }
940 else
941 emacs_abort ();
942
943 /* GC must have been set. */
944 eassert (s->gc != 0);
945}
946
947
948/* Set clipping for output of glyph string S. S may be part of a mode
949 line or menu if we don't have X toolkit support. */
950
951static void
952android_set_glyph_string_clipping (struct glyph_string *s)
953{
954 struct android_rectangle *r = s->clip;
955 int n = get_glyph_string_clip_rects (s, r, 2);
956
957 if (n > 0)
958 android_set_clip_rectangles (s->gc, 0, 0, r, n);
959 s->num_clips = n;
960}
961
962
963/* Set SRC's clipping for output of glyph string DST. This is called
964 when we are drawing DST's left_overhang or right_overhang only in
965 the area of SRC. */
966
967static void
968android_set_glyph_string_clipping_exactly (struct glyph_string *src,
969 struct glyph_string *dst)
970{
971 struct android_rectangle r;
972
973 r.x = src->x;
974 r.width = src->width;
975 r.y = src->y;
976 r.height = src->height;
977 dst->clip[0] = r;
978 dst->num_clips = 1;
979 android_set_clip_rectangles (dst->gc, 0, 0, &r, 1);
980}
981
982static void
983android_compute_glyph_string_overhangs (struct glyph_string *s)
984{
985 if (s->cmp == NULL
986 && (s->first_glyph->type == CHAR_GLYPH
987 || s->first_glyph->type == COMPOSITE_GLYPH))
988 {
989 struct font_metrics metrics;
990
991 if (s->first_glyph->type == CHAR_GLYPH)
992 {
993 struct font *font = s->font;
994 font->driver->text_extents (font, s->char2b, s->nchars, &metrics);
995 }
996 else
997 {
998 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
999
1000 composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
1001 }
1002 s->right_overhang = (metrics.rbearing > metrics.width
1003 ? metrics.rbearing - metrics.width : 0);
1004 s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
1005 }
1006 else if (s->cmp)
1007 {
1008 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1009 s->left_overhang = - s->cmp->lbearing;
1010 }
1011}
1012
1013static void
1014android_clear_glyph_string_rect (struct glyph_string *s, int x, int y,
1015 int w, int h)
1016{
1017 android_clear_rectangle (s->f, s->gc, x, y, w, h);
1018}
1019
1020static void
1021android_draw_glyph_string_background (struct glyph_string *s, bool force_p)
1022{
1023 /* Nothing to do if background has already been drawn or if it
1024 shouldn't be drawn in the first place. */
1025 if (!s->background_filled_p)
1026 {
1027 int box_line_width = max (s->face->box_horizontal_line_width, 0);
1028
1029 if (s->stippled_p)
1030 {
1031 /* Fill background with a stipple pattern. */
1032 android_set_fill_style (s->gc, ANDROID_FILL_OPAQUE_STIPPLED);
1033 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc,
1034 s->x, s->y + box_line_width,
1035 s->background_width,
1036 s->height - 2 * box_line_width);
1037 android_set_fill_style (s->gc, ANDROID_FILL_SOLID);
1038 s->background_filled_p = true;
1039 }
1040 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1041 /* When xdisp.c ignores FONT_HEIGHT, we cannot trust
1042 font dimensions, since the actual glyphs might be
1043 much smaller. So in that case we always clear the
1044 rectangle with background color. */
1045 || FONT_TOO_HIGH (s->font)
1046 || s->font_not_found_p
1047 || s->extends_to_end_of_line_p
1048 || force_p)
1049 {
1050 android_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1051 s->background_width,
1052 s->height - 2 * box_line_width);
1053 s->background_filled_p = true;
1054 }
1055 }
1056}
1057
1058static void
1059android_fill_triangle (struct frame *f, struct android_gc *gc,
1060 struct android_point point1,
1061 struct android_point point2,
1062 struct android_point point3)
1063{
1064 struct android_point abc[3];
1065
1066 abc[0] = point1;
1067 abc[1] = point2;
1068 abc[2] = point3;
1069
1070 android_fill_polygon (FRAME_ANDROID_WINDOW (f),
1071 gc, abc, 3, ANDROID_CONVEX,
1072 ANDROID_COORD_MODE_ORIGIN);
1073}
1074
1075static struct android_point
1076android_make_point (int x, int y)
1077{
1078 struct android_point pt;
1079
1080 pt.x = x;
1081 pt.y = y;
1082
1083 return pt;
1084}
1085
1086static bool
1087android_inside_rect_p (struct android_rectangle *rects, int nrects, int x,
1088 int y)
1089{
1090 int i;
1091
1092 for (i = 0; i < nrects; ++i)
1093 {
1094 if (x >= rects[i].x && y >= rects[i].y
1095 && x < rects[i].x + rects[i].width
1096 && y < rects[i].y + rects[i].height)
1097 return true;
1098 }
1099
1100 return false;
1101}
1102
1103static void
1104android_clear_point (struct frame *f, struct android_gc *gc,
1105 int x, int y)
1106{
1107 struct android_gc_values xgcv;
1108
1109 android_get_gc_values (gc, ANDROID_GC_BACKGROUND | ANDROID_GC_FOREGROUND,
1110 &xgcv);
1111 android_set_foreground (gc, xgcv.background);
1112 android_draw_point (FRAME_ANDROID_WINDOW (f), gc, x, y);
1113 android_set_foreground (gc, xgcv.foreground);
1114}
1115
1116static void
1117android_draw_relief_rect (struct frame *f, int left_x, int top_y, int right_x,
1118 int bottom_y, int hwidth, int vwidth, bool raised_p,
1119 bool top_p, bool bot_p, bool left_p, bool right_p,
1120 struct android_rectangle *clip_rect)
1121{
1122 struct android_gc *gc, *white_gc, *black_gc, *normal_gc;
1123 android_drawable drawable;
1124
1125 /* This code is more complicated than it has to be, because of two
1126 minor hacks to make the boxes look nicer: (i) if width > 1, draw
1127 the outermost line using the black relief. (ii) Omit the four
1128 corner pixels. */
1129
1130 white_gc = f->output_data.android->white_relief.gc;
1131 black_gc = f->output_data.android->black_relief.gc;
1132 normal_gc = f->output_data.android->normal_gc;
1133
1134 drawable = FRAME_ANDROID_WINDOW (f);
1135
1136 android_set_clip_rectangles (white_gc, 0, 0, clip_rect, 1);
1137 android_set_clip_rectangles (black_gc, 0, 0, clip_rect, 1);
1138
1139 if (raised_p)
1140 gc = white_gc;
1141 else
1142 gc = black_gc;
1143
1144 /* Draw lines. */
1145
1146 if (top_p)
1147 android_fill_rectangle (FRAME_ANDROID_WINDOW (f), gc, left_x, top_y,
1148 right_x - left_x + 1, hwidth);
1149
1150 if (left_p)
1151 android_fill_rectangle (FRAME_ANDROID_WINDOW (f), gc, left_x, top_y,
1152 vwidth, bottom_y - top_y + 1);
1153
1154 if (raised_p)
1155 gc = black_gc;
1156 else
1157 gc = white_gc;
1158
1159 if (bot_p)
1160 android_fill_rectangle (FRAME_ANDROID_WINDOW (f), gc, left_x,
1161 bottom_y - hwidth + 1,
1162 right_x - left_x + 1, hwidth);
1163
1164 if (right_p)
1165 android_fill_rectangle (FRAME_ANDROID_WINDOW (f), gc,
1166 right_x - vwidth + 1,
1167 top_y, vwidth, bottom_y - top_y + 1);
1168
1169 /* Draw corners. */
1170
1171 if (bot_p && left_p)
1172 android_fill_triangle (f, raised_p ? white_gc : black_gc,
1173 android_make_point (left_x, bottom_y - hwidth),
1174 android_make_point (left_x + vwidth,
1175 bottom_y - hwidth),
1176 android_make_point (left_x, bottom_y));
1177
1178 if (top_p && right_p)
1179 android_fill_triangle (f, raised_p ? white_gc : black_gc,
1180 android_make_point (right_x - vwidth, top_y),
1181 android_make_point (right_x, top_y),
1182 android_make_point (right_x - vwidth,
1183 top_y + hwidth));
1184
1185 /* Draw outer line. */
1186
1187 if (top_p && left_p && bot_p && right_p
1188 && hwidth > 1 && vwidth > 1)
1189 android_draw_rectangle (FRAME_ANDROID_WINDOW (f),
1190 black_gc, left_x, top_y,
1191 right_x - left_x, bottom_y - top_y);
1192 else
1193 {
1194 if (top_p && hwidth > 1)
1195 android_draw_line (drawable, black_gc, left_x, top_y,
1196 right_x + 1, top_y);
1197
1198 if (bot_p && hwidth > 1)
1199 android_draw_line (drawable, black_gc, left_x, bottom_y,
1200 right_x + 1, bottom_y);
1201
1202 if (left_p && vwidth > 1)
1203 android_draw_line (drawable, black_gc, left_x, top_y,
1204 left_x, bottom_y + 1);
1205
1206 if (right_p && vwidth > 1)
1207 android_draw_line (drawable, black_gc, right_x, top_y,
1208 right_x, bottom_y + 1);
1209 }
1210
1211 /* Erase corners. */
1212
1213 if (hwidth > 1 && vwidth > 1)
1214 {
1215 if (left_p && top_p && android_inside_rect_p (clip_rect, 1,
1216 left_x, top_y))
1217 android_clear_point (f, normal_gc, left_x, top_y);
1218
1219 if (left_p && bot_p && android_inside_rect_p (clip_rect, 1,
1220 left_x, bottom_y))
1221 android_clear_point (f, normal_gc, left_x, bottom_y);
1222
1223 if (right_p && top_p && android_inside_rect_p (clip_rect, 1,
1224 right_x, top_y))
1225 android_clear_point (f, normal_gc, right_x, top_y);
1226
1227 if (right_p && bot_p && android_inside_rect_p (clip_rect, 1,
1228 right_x, bottom_y))
1229 android_clear_point (f, normal_gc, right_x, bottom_y);
1230 }
1231
1232 android_reset_clip_rectangles (f, white_gc);
1233 android_reset_clip_rectangles (f, black_gc);
1234}
1235
1236static void
1237android_draw_box_rect (struct glyph_string *s,
1238 int left_x, int top_y, int right_x, int bottom_y,
1239 int hwidth, int vwidth, bool left_p, bool right_p,
1240 struct android_rectangle *clip_rect)
1241{
1242 struct android_gc_values xgcv;
1243
1244 android_get_gc_values (s->gc, ANDROID_GC_FOREGROUND, &xgcv);
1245 android_set_foreground (s->gc, s->face->box_color);
1246 android_set_clip_rectangles (s->gc, 0, 0, clip_rect, 1);
1247
1248 /* Top. */
1249 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc, left_x,
1250 left_x, right_x - left_x + 1, hwidth);
1251
1252 /* Left. */
1253 if (left_p)
1254 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc, left_x,
1255 top_y, vwidth, bottom_y - top_y + 1);
1256
1257 /* Bottom. */
1258 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc, left_x,
1259 bottom_y - hwidth + 1, right_x - left_x + 1,
1260 hwidth);
1261
1262 /* Right. */
1263 if (right_p)
1264 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc,
1265 right_x - vwidth + 1, top_y, vwidth,
1266 bottom_y - top_y + 1);
1267
1268 android_set_foreground (s->gc, xgcv.foreground);
1269 android_reset_clip_rectangles (s->f, s->gc);
1270}
1271
1272#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
1273
1274static bool
1275android_alloc_lighter_color (struct frame *f, unsigned long *pixel,
1276 double factor, int delta)
1277{
1278 Emacs_Color color, new;
1279 long bright;
1280 bool success_p;
1281
1282 /* Get RGB color values. */
1283 color.pixel = *pixel;
1284 android_query_colors (f, &color, 1);
1285
1286 /* Change RGB values by specified FACTOR. Avoid overflow! */
1287 eassert (factor >= 0);
1288 new.red = min (0xffff, factor * color.red);
1289 new.green = min (0xffff, factor * color.green);
1290 new.blue = min (0xffff, factor * color.blue);
1291
1292 /* Calculate brightness of COLOR. */
1293 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
1294
1295 /* We only boost colors that are darker than
1296 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1297 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1298 /* Make an additive adjustment to NEW, because it's dark enough so
1299 that scaling by FACTOR alone isn't enough. */
1300 {
1301 /* How far below the limit this color is (0 - 1, 1 being darker). */
1302 double dimness = 1 - (double) bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1303 /* The additive adjustment. */
1304 int min_delta = delta * dimness * factor / 2;
1305
1306 if (factor < 1)
1307 {
1308 new.red = max (0, new.red - min_delta);
1309 new.green = max (0, new.green - min_delta);
1310 new.blue = max (0, new.blue - min_delta);
1311 }
1312 else
1313 {
1314 new.red = min (0xffff, min_delta + new.red);
1315 new.green = min (0xffff, min_delta + new.green);
1316 new.blue = min (0xffff, min_delta + new.blue);
1317 }
1318 }
1319
1320 /* Try to allocate the color. */
1321 success_p = android_alloc_nearest_color (f, &new);
1322
1323 if (success_p)
1324 {
1325 if (new.pixel == *pixel)
1326 {
1327 /* If we end up with the same color as before, try adding
1328 delta to the RGB values. */
1329 new.red = min (0xffff, delta + color.red);
1330 new.green = min (0xffff, delta + color.green);
1331 new.blue = min (0xffff, delta + color.blue);
1332 success_p = android_alloc_nearest_color (f, &new);
1333 }
1334 else
1335 success_p = true;
1336
1337 *pixel = new.pixel;
1338 }
1339
1340 return success_p;
1341}
1342
1343/* Set up the foreground color for drawing relief lines of glyph
1344 string S. RELIEF is a pointer to a struct relief containing the GC
1345 with which lines will be drawn. Use a color that is FACTOR or
1346 DELTA lighter or darker than the relief's background which is found
1347 in S->f->output_data.android->relief_background. If such a color
1348 cannot be allocated, use DEFAULT_PIXEL, instead. */
1349
1350static void
1351android_setup_relief_color (struct frame *f, struct relief *relief,
1352 double factor, int delta,
1353 unsigned long default_pixel)
1354{
1355 struct android_gc_values xgcv;
1356 struct android_output *di = f->output_data.android;
1357 unsigned long mask = ANDROID_GC_FOREGROUND;
1358 unsigned long pixel;
1359 unsigned long background = di->relief_background;
1360 struct android_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1361
1362 if (relief->gc && relief->pixel != -1)
1363 relief->pixel = -1;
1364
1365 /* Allocate new color. */
1366 xgcv.foreground = default_pixel;
1367 pixel = background;
1368
1369 if (dpyinfo->n_planes != 1
1370 && android_alloc_lighter_color (f, &pixel, factor, delta))
1371 xgcv.foreground = relief->pixel = pixel;
1372
1373 if (relief->gc == 0)
1374 relief->gc = android_create_gc (mask, &xgcv);
1375 else
1376 android_change_gc (relief->gc, mask, &xgcv);
1377}
1378
1379/* Set up colors for the relief lines around glyph string S. */
1380
1381static void
1382android_setup_relief_colors (struct glyph_string *s)
1383{
1384 struct android_output *di;
1385 unsigned long color;
1386
1387 di = s->f->output_data.android;
1388
1389 if (s->face->use_box_color_for_shadows_p)
1390 color = s->face->box_color;
1391 else if (s->first_glyph->type == IMAGE_GLYPH
1392 && s->img->pixmap
1393 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1394 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1395 else
1396 {
1397 struct android_gc_values xgcv;
1398
1399 /* Get the background color of the face. */
1400 android_get_gc_values (s->gc, ANDROID_GC_BACKGROUND, &xgcv);
1401 color = xgcv.background;
1402 }
1403
1404 if (di->white_relief.gc == 0
1405 || color != di->relief_background)
1406 {
1407 di->relief_background = color;
1408 android_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1409 WHITE_PIX_DEFAULT (s->f));
1410 android_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1411 BLACK_PIX_DEFAULT (s->f));
1412 }
1413}
1414
1415static void
1416android_draw_glyph_string_box (struct glyph_string *s)
1417{
1418 int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
1419 bool raised_p, left_p, right_p;
1420 struct glyph *last_glyph;
1421 struct android_rectangle clip_rect;
1422
1423 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
1424 ? WINDOW_RIGHT_EDGE_X (s->w)
1425 : window_box_right (s->w, s->area));
1426
1427 /* The glyph that may have a right box line. For static
1428 compositions and images, the right-box flag is on the first glyph
1429 of the glyph string; for other types it's on the last glyph. */
1430 if (s->cmp || s->img)
1431 last_glyph = s->first_glyph;
1432 else if (s->first_glyph->type == COMPOSITE_GLYPH
1433 && s->first_glyph->u.cmp.automatic)
1434 {
1435 /* For automatic compositions, we need to look up the last glyph
1436 in the composition. */
1437 struct glyph *end = s->row->glyphs[s->area] + s->row->used[s->area];
1438 struct glyph *g = s->first_glyph;
1439 for (last_glyph = g++;
1440 g < end && g->u.cmp.automatic && g->u.cmp.id == s->cmp_id
1441 && g->slice.cmp.to < s->cmp_to;
1442 last_glyph = g++)
1443 ;
1444 }
1445 else
1446 last_glyph = s->first_glyph + s->nchars - 1;
1447
1448 vwidth = eabs (s->face->box_vertical_line_width);
1449 hwidth = eabs (s->face->box_horizontal_line_width);
1450 raised_p = s->face->box == FACE_RAISED_BOX;
1451 left_x = s->x;
1452 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
1453 ? last_x - 1
1454 : min (last_x, s->x + s->background_width) - 1);
1455 top_y = s->y;
1456 bottom_y = top_y + s->height - 1;
1457
1458 left_p = (s->first_glyph->left_box_line_p
1459 || (s->hl == DRAW_MOUSE_FACE
1460 && (s->prev == NULL
1461 || s->prev->hl != s->hl)));
1462 right_p = (last_glyph->right_box_line_p
1463 || (s->hl == DRAW_MOUSE_FACE
1464 && (s->next == NULL
1465 || s->next->hl != s->hl)));
1466
1467 get_glyph_string_clip_rect (s, &clip_rect);
1468
1469 if (s->face->box == FACE_SIMPLE_BOX)
1470 android_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
1471 vwidth, left_p, right_p, &clip_rect);
1472 else
1473 {
1474 android_setup_relief_colors (s);
1475 android_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
1476 vwidth, raised_p, true, true, left_p, right_p,
1477 &clip_rect);
1478 }
1479}
1480
1481static void
1482android_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y,
1483 int w, int h)
1484{
1485 if (s->stippled_p)
1486 {
1487 /* Fill background with a stipple pattern. */
1488 android_set_fill_style (s->gc, ANDROID_FILL_OPAQUE_STIPPLED);
1489 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc, x,
1490 y, w, h);
1491 android_set_fill_style (s->gc, ANDROID_FILL_SOLID);
1492 }
1493 else
1494 android_clear_glyph_string_rect (s, x, y, w, h);
1495}
1496
1497static void
1498android_draw_image_relief (struct glyph_string *s)
1499{
1500 int x1, y1, thick;
1501 bool raised_p, top_p, bot_p, left_p, right_p;
1502 int extra_x, extra_y;
1503 struct android_rectangle r;
1504 int x = s->x;
1505 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1506
1507 /* If first glyph of S has a left box line, start drawing it to the
1508 right of that line. */
1509 if (s->face->box != FACE_NO_BOX
1510 && s->first_glyph->left_box_line_p
1511 && s->slice.x == 0)
1512 x += max (s->face->box_vertical_line_width, 0);
1513
1514 /* If there is a margin around the image, adjust x- and y-position
1515 by that margin. */
1516 if (s->slice.x == 0)
1517 x += s->img->hmargin;
1518 if (s->slice.y == 0)
1519 y += s->img->vmargin;
1520
1521 if (s->hl == DRAW_IMAGE_SUNKEN
1522 || s->hl == DRAW_IMAGE_RAISED)
1523 {
1524 if (s->face->id == TAB_BAR_FACE_ID)
1525 thick = (tab_bar_button_relief < 0
1526 ? DEFAULT_TAB_BAR_BUTTON_RELIEF
1527 : min (tab_bar_button_relief, 1000000));
1528 else
1529 thick = (tool_bar_button_relief < 0
1530 ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
1531 : min (tool_bar_button_relief, 1000000));
1532 raised_p = s->hl == DRAW_IMAGE_RAISED;
1533 }
1534 else
1535 {
1536 thick = eabs (s->img->relief);
1537 raised_p = s->img->relief > 0;
1538 }
1539
1540 x1 = x + s->slice.width - 1;
1541 y1 = y + s->slice.height - 1;
1542
1543 extra_x = extra_y = 0;
1544 if (s->face->id == TAB_BAR_FACE_ID)
1545 {
1546 if (CONSP (Vtab_bar_button_margin)
1547 && FIXNUMP (XCAR (Vtab_bar_button_margin))
1548 && FIXNUMP (XCDR (Vtab_bar_button_margin)))
1549 {
1550 extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)) - thick;
1551 extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)) - thick;
1552 }
1553 else if (FIXNUMP (Vtab_bar_button_margin))
1554 extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin) - thick;
1555 }
1556
1557 if (s->face->id == TOOL_BAR_FACE_ID)
1558 {
1559 if (CONSP (Vtool_bar_button_margin)
1560 && FIXNUMP (XCAR (Vtool_bar_button_margin))
1561 && FIXNUMP (XCDR (Vtool_bar_button_margin)))
1562 {
1563 extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin));
1564 extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin));
1565 }
1566 else if (FIXNUMP (Vtool_bar_button_margin))
1567 extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin);
1568 }
1569
1570 top_p = bot_p = left_p = right_p = false;
1571
1572 if (s->slice.x == 0)
1573 x -= thick + extra_x, left_p = true;
1574 if (s->slice.y == 0)
1575 y -= thick + extra_y, top_p = true;
1576 if (s->slice.x + s->slice.width == s->img->width)
1577 x1 += thick + extra_x, right_p = true;
1578 if (s->slice.y + s->slice.height == s->img->height)
1579 y1 += thick + extra_y, bot_p = true;
1580
1581 android_setup_relief_colors (s);
1582 get_glyph_string_clip_rect (s, &r);
1583 android_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
1584 top_p, bot_p, left_p, right_p, &r);
1585}
1586
1587static void
1588android_draw_image_foreground (struct glyph_string *s)
1589{
1590 int x = s->x;
1591 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1592
1593 /* If first glyph of S has a left box line, start drawing it to the
1594 right of that line. */
1595 if (s->face->box != FACE_NO_BOX
1596 && s->first_glyph->left_box_line_p
1597 && s->slice.x == 0)
1598 x += max (s->face->box_vertical_line_width, 0);
1599
1600 /* If there is a margin around the image, adjust x- and y-position
1601 by that margin. */
1602 if (s->slice.x == 0)
1603 x += s->img->hmargin;
1604 if (s->slice.y == 0)
1605 y += s->img->vmargin;
1606
1607 if (s->img->pixmap)
1608 {
1609 if (s->img->mask)
1610 {
1611 unsigned long mask = (ANDROID_GC_CLIP_MASK
1612 | ANDROID_GC_CLIP_X_ORIGIN
1613 | ANDROID_GC_CLIP_Y_ORIGIN
1614 | ANDROID_GC_FUNCTION);
1615 struct android_gc_values xgcv;
1616 struct android_rectangle clip_rect, image_rect, r;
1617
1618 xgcv.clip_mask = s->img->mask;
1619 xgcv.clip_x_origin = x - s->slice.x;
1620 xgcv.clip_y_origin = y - s->slice.y;
1621 xgcv.function = ANDROID_GC_COPY;
1622 android_change_gc (s->gc, mask, &xgcv);
1623
1624 get_glyph_string_clip_rect (s, &clip_rect);
1625 image_rect.x = x;
1626 image_rect.y = y;
1627 image_rect.width = s->slice.width;
1628 image_rect.height = s->slice.height;
1629
1630 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
1631 android_copy_area (s->img->pixmap, FRAME_ANDROID_WINDOW (s->f),
1632 s->gc, s->slice.x + r.x - x,
1633 s->slice.y + r.y - y,
1634 r.x, r.y, r.width, r.height);
1635 }
1636 else
1637 {
1638 unsigned long mask = (ANDROID_GC_CLIP_MASK
1639 | ANDROID_GC_CLIP_X_ORIGIN
1640 | ANDROID_GC_CLIP_Y_ORIGIN
1641 | ANDROID_GC_FUNCTION);
1642 struct android_gc_values xgcv;
1643 struct android_rectangle clip_rect, image_rect, r;
1644
1645 xgcv.clip_mask = s->img->mask;
1646 xgcv.clip_x_origin = x - s->slice.x;
1647 xgcv.clip_y_origin = y - s->slice.y;
1648 xgcv.function = ANDROID_GC_COPY;
1649 android_change_gc (s->gc, mask, &xgcv);
1650
1651 get_glyph_string_clip_rect (s, &clip_rect);
1652 image_rect.x = x;
1653 image_rect.y = y;
1654 image_rect.width = s->slice.width;
1655 image_rect.height = s->slice.height;
1656
1657 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
1658 android_copy_area (s->img->pixmap,
1659 FRAME_ANDROID_WINDOW (s->f),
1660 s->gc, s->slice.x + r.x - x,
1661 s->slice.y + r.y - y,
1662 r.x, r.y, r.width, r.height);
1663
1664 /* When the image has a mask, we can expect that at
1665 least part of a mouse highlight or a block cursor will
1666 be visible. If the image doesn't have a mask, make
1667 a block cursor visible by drawing a rectangle around
1668 the image. I believe it's looking better if we do
1669 nothing here for mouse-face. */
1670 if (s->hl == DRAW_CURSOR)
1671 {
1672 int relief = eabs (s->img->relief);
1673 android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc,
1674 x - relief, y - relief,
1675 s->slice.width + relief*2 - 1,
1676 s->slice.height + relief*2 - 1);
1677 }
1678 }
1679 }
1680 else
1681 /* Draw a rectangle if image could not be loaded. */
1682 android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc, x, y,
1683 s->slice.width - 1, s->slice.height - 1);
1684}
1685
1686/* Draw the foreground of image glyph string S to PIXMAP. */
1687
1688static void
1689android_draw_image_foreground_1 (struct glyph_string *s,
1690 android_pixmap pixmap)
1691{
1692 int x = 0;
1693 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
1694
1695 /* If first glyph of S has a left box line, start drawing it to the
1696 right of that line. */
1697 if (s->face->box != FACE_NO_BOX
1698 && s->first_glyph->left_box_line_p
1699 && s->slice.x == 0)
1700 x += max (s->face->box_vertical_line_width, 0);
1701
1702 /* If there is a margin around the image, adjust x- and y-position
1703 by that margin. */
1704 if (s->slice.x == 0)
1705 x += s->img->hmargin;
1706 if (s->slice.y == 0)
1707 y += s->img->vmargin;
1708
1709 if (s->img->pixmap)
1710 {
1711 if (s->img->mask)
1712 {
1713 unsigned long mask = (ANDROID_GC_CLIP_MASK
1714 | ANDROID_GC_CLIP_X_ORIGIN
1715 | ANDROID_GC_CLIP_Y_ORIGIN
1716 | ANDROID_GC_FUNCTION);
1717 struct android_gc_values xgcv;
1718 struct android_rectangle clip_rect, image_rect, r;
1719
1720 xgcv.clip_mask = s->img->mask;
1721 xgcv.clip_x_origin = x - s->slice.x;
1722 xgcv.clip_y_origin = y - s->slice.y;
1723 xgcv.function = ANDROID_GC_COPY;
1724 android_change_gc (s->gc, mask, &xgcv);
1725
1726 get_glyph_string_clip_rect (s, &clip_rect);
1727 image_rect.x = x;
1728 image_rect.y = y;
1729 image_rect.width = s->slice.width;
1730 image_rect.height = s->slice.height;
1731
1732 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
1733 android_copy_area (s->img->pixmap, pixmap, s->gc,
1734 s->slice.x + r.x - x,
1735 s->slice.y + r.y - y,
1736 r.x, r.y, r.width, r.height);
1737
1738 android_set_clip_mask (s->gc, ANDROID_NONE);
1739 }
1740 else
1741 {
1742 android_copy_area (s->img->pixmap, pixmap, s->gc,
1743 s->slice.x, s->slice.y,
1744 s->slice.width, s->slice.height, x, y);
1745
1746 /* When the image has a mask, we can expect that at
1747 least part of a mouse highlight or a block cursor will
1748 be visible. If the image doesn't have a mask, make
1749 a block cursor visible by drawing a rectangle around
1750 the image. I believe it's looking better if we do
1751 nothing here for mouse-face. */
1752 if (s->hl == DRAW_CURSOR)
1753 {
1754 int r = eabs (s->img->relief);
1755 android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f),
1756 s->gc, x - r, y - r,
1757 s->slice.width + r*2 - 1,
1758 s->slice.height + r*2 - 1);
1759 }
1760 }
1761 }
1762 else
1763 /* Draw a rectangle if image could not be loaded. */
1764 android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc, x, y,
1765 s->slice.width - 1, s->slice.height - 1);
1766}
1767
1768static void
1769android_draw_image_glyph_string (struct glyph_string *s)
1770{
1771 int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
1772 int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
1773 int height;
1774 android_pixmap pixmap = ANDROID_NONE;
1775
1776 height = s->height;
1777 if (s->slice.y == 0)
1778 height -= box_line_vwidth;
1779 if (s->slice.y + s->slice.height >= s->img->height)
1780 height -= box_line_vwidth;
1781
1782 /* Fill background with face under the image. Do it only if row is
1783 taller than image or if image has a clip mask to reduce
1784 flickering. */
1785 s->stippled_p = s->face->stipple != 0;
1786 if (height > s->slice.height
1787 || s->img->hmargin
1788 || s->img->vmargin
1789 || s->img->mask
1790 || s->img->pixmap == 0
1791 || s->width != s->background_width)
1792 {
1793 if (s->stippled_p)
1794 s->row->stipple_p = true;
1795
1796 if (s->img->mask)
1797 {
1798 /* Create a pixmap as large as the glyph string. Fill it
1799 with the background color. Copy the image to it, using
1800 its mask. Copy the temporary pixmap to the display. */
1801 int depth = FRAME_DISPLAY_INFO (s->f)->n_planes;
1802
1803 /* Create a pixmap as large as the glyph string. */
1804 pixmap = android_create_pixmap (s->background_width,
1805 s->height, depth);
1806
1807 /* Don't clip in the following because we're working on the
1808 pixmap. */
1809 android_set_clip_mask (s->gc, ANDROID_NONE);
1810
1811 /* Fill the pixmap with the background color/stipple. */
1812 if (s->stippled_p)
1813 {
1814 /* Fill background with a stipple pattern. */
1815 android_set_fill_style (s->gc, ANDROID_FILL_OPAQUE_STIPPLED);
1816 android_set_ts_origin (s->gc, - s->x, - s->y);
1817 android_fill_rectangle (pixmap, s->gc,
1818 0, 0, s->background_width, s->height);
1819 android_set_fill_style (s->gc, ANDROID_FILL_OPAQUE_STIPPLED);
1820 android_set_ts_origin (s->gc, 0, 0);
1821 }
1822 else
1823 {
1824 struct android_gc_values xgcv;
1825
1826 android_get_gc_values (s->gc, (ANDROID_GC_FOREGROUND
1827 | ANDROID_GC_BACKGROUND),
1828 &xgcv);
1829 android_set_foreground (s->gc, xgcv.background);
1830 android_fill_rectangle (pixmap, s->gc,
1831 0, 0, s->background_width, s->height);
1832 android_set_background (s->gc, xgcv.foreground);
1833 }
1834 }
1835 else
1836 {
1837 int x = s->x;
1838 int y = s->y;
1839 int width = s->background_width;
1840
1841 if (s->first_glyph->left_box_line_p
1842 && s->slice.x == 0)
1843 {
1844 x += box_line_hwidth;
1845 width -= box_line_hwidth;
1846 }
1847
1848 if (s->slice.y == 0)
1849 y += box_line_vwidth;
1850
1851 android_draw_glyph_string_bg_rect (s, x, y, width, height);
1852 }
1853
1854 s->background_filled_p = true;
1855 }
1856
1857 /* Draw the foreground. */
1858 if (pixmap != ANDROID_NONE)
1859 {
1860 android_draw_image_foreground_1 (s, pixmap);
1861 android_set_glyph_string_clipping (s);
1862 android_copy_area (pixmap, FRAME_ANDROID_WINDOW (s->f), s->gc,
1863 0, 0, s->background_width, s->height, s->x,
1864 s->y);
1865 android_free_pixmap (pixmap);
1866 }
1867 else
1868 android_draw_image_foreground (s);
1869
1870 /* If we must draw a relief around the image, do it. */
1871 if (s->img->relief
1872 || s->hl == DRAW_IMAGE_RAISED
1873 || s->hl == DRAW_IMAGE_SUNKEN)
1874 android_draw_image_relief (s);
1875}
1876
1877static void
1878android_draw_stretch_glyph_string (struct glyph_string *s)
1879{
1880 eassert (s->first_glyph->type == STRETCH_GLYPH);
1881
1882 if (s->hl == DRAW_CURSOR && !x_stretch_cursor_p)
1883 {
1884 /* If `x-stretch-cursor' is nil, don't draw a block cursor as
1885 wide as the stretch glyph. */
1886 int width, background_width = s->background_width;
1887 int x = s->x;
1888
1889 if (!s->row->reversed_p)
1890 {
1891 int left_x = window_box_left_offset (s->w, TEXT_AREA);
1892
1893 if (x < left_x)
1894 {
1895 background_width -= left_x - x;
1896 x = left_x;
1897 }
1898 }
1899 else
1900 {
1901 /* In R2L rows, draw the cursor on the right edge of the
1902 stretch glyph. */
1903 int right_x = window_box_right (s->w, TEXT_AREA);
1904
1905 if (x + background_width > right_x)
1906 background_width -= x - right_x;
1907 x += background_width;
1908 }
1909 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
1910 if (s->row->reversed_p)
1911 x -= width;
1912
1913 /* Draw cursor. */
1914 android_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
1915
1916 /* Clear rest using the GC of the original non-cursor face. */
1917 if (width < background_width)
1918 {
1919 int y = s->y;
1920 int w = background_width - width, h = s->height;
1921 struct android_rectangle r;
1922 struct android_gc *gc;
1923
1924 if (!s->row->reversed_p)
1925 x += width;
1926 else
1927 x = s->x;
1928 if (s->row->mouse_face_p
1929 && cursor_in_mouse_face_p (s->w))
1930 {
1931 android_set_mouse_face_gc (s);
1932 gc = s->gc;
1933 }
1934 else
1935 gc = s->face->gc;
1936
1937 get_glyph_string_clip_rect (s, &r);
1938 android_set_clip_rectangles (gc, 0, 0, &r, 1);
1939
1940 if (s->face->stipple)
1941 {
1942 /* Fill background with a stipple pattern. */
1943 android_set_fill_style (gc, ANDROID_FILL_OPAQUE_STIPPLED);
1944 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f),
1945 gc, x, y, w, h);
1946 android_set_fill_style (gc, ANDROID_FILL_SOLID);
1947
1948 s->row->stipple_p = true;
1949 }
1950 else
1951 {
1952 struct android_gc_values xgcv;
1953 android_get_gc_values (gc, (ANDROID_GC_FOREGROUND
1954 | ANDROID_GC_BACKGROUND),
1955 &xgcv);
1956 android_set_foreground (gc, xgcv.background);
1957 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f),
1958 gc, x, y, w, h);
1959 android_set_foreground (gc, xgcv.foreground);
1960 }
1961
1962 android_reset_clip_rectangles (s->f, gc);
1963 }
1964 }
1965 else if (!s->background_filled_p)
1966 {
1967 int background_width = s->background_width;
1968 int x = s->x, text_left_x = window_box_left (s->w, TEXT_AREA);
1969
1970 /* Don't draw into left fringe or scrollbar area except for
1971 header line and mode line. */
1972 if (s->area == TEXT_AREA
1973 && x < text_left_x && !s->row->mode_line_p)
1974 {
1975 background_width -= text_left_x - x;
1976 x = text_left_x;
1977 }
1978
1979 if (!s->row->stipple_p)
1980 s->row->stipple_p = s->stippled_p;
1981
1982 if (background_width > 0)
1983 android_draw_glyph_string_bg_rect (s, x, s->y,
1984 background_width,
1985 s->height);
1986 }
1987
1988 s->background_filled_p = true;
1989}
1990
1991static void
1992android_draw_underwave (struct glyph_string *s, int decoration_width)
1993{
1994 int wave_height = 3, wave_length = 2;
1995 int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax;
1996 bool odd;
1997 struct android_rectangle wave_clip, string_clip, final_clip;
1998
1999 dx = wave_length;
2000 dy = wave_height - 1;
2001 x0 = s->x;
2002 y0 = s->ybase + wave_height / 2;
2003 width = decoration_width;
2004 xmax = x0 + width;
2005
2006 /* Find and set clipping rectangle */
2007
2008 wave_clip.x = x0;
2009 wave_clip.y = y0;
2010 wave_clip.width = width;
2011 wave_clip.height = wave_height;
2012 get_glyph_string_clip_rect (s, &string_clip);
2013
2014 if (!gui_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
2015 return;
2016
2017 android_set_clip_rectangles (s->gc, 0, 0, &final_clip, 1);
2018
2019 /* Draw the waves */
2020
2021 x1 = x0 - (x0 % dx);
2022 x2 = x1 + dx;
2023 odd = (x1 / dx) & 1;
2024 y1 = y2 = y0;
2025
2026 if (odd)
2027 y1 += dy;
2028 else
2029 y2 += dy;
2030
2031 if (INT_MAX - dx < xmax)
2032 emacs_abort ();
2033
2034 while (x1 <= xmax)
2035 {
2036 android_draw_line (FRAME_ANDROID_WINDOW (s->f), s->gc,
2037 x1, y1, x2, y2);
2038 x1 = x2, y1 = y2;
2039 x2 += dx, y2 = y0 + odd*dy;
2040 odd = !odd;
2041 }
2042
2043 /* Restore previous clipping rectangle(s) */
2044 android_set_clip_rectangles (s->gc, 0, 0, s->clip, s->num_clips);
2045}
2046
2047static void
2048android_draw_glyph_string_foreground (struct glyph_string *s)
2049{
2050 int i, x;
2051
2052 /* If first glyph of S has a left box line, start drawing the text
2053 of S to the right of that box line. */
2054 if (s->face->box != FACE_NO_BOX
2055 && s->first_glyph->left_box_line_p)
2056 x = s->x + max (s->face->box_vertical_line_width, 0);
2057 else
2058 x = s->x;
2059
2060 /* Draw characters of S as rectangles if S's font could not be
2061 loaded. */
2062 if (s->font_not_found_p)
2063 {
2064 for (i = 0; i < s->nchars; ++i)
2065 {
2066 struct glyph *g = s->first_glyph + i;
2067 android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f),
2068 s->gc, x, s->y,
2069 g->pixel_width - 1,
2070 s->height - 1);
2071 x += g->pixel_width;
2072 }
2073 }
2074 else
2075 {
2076 struct font *font = s->font;
2077 int boff = font->baseline_offset;
2078 int y;
2079
2080 if (font->vertical_centering)
2081 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
2082
2083 y = s->ybase - boff;
2084 if (s->for_overlaps
2085 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2086 font->driver->draw (s, 0, s->nchars, x, y, false);
2087 else
2088 font->driver->draw (s, 0, s->nchars, x, y, true);
2089 if (s->face->overstrike)
2090 font->driver->draw (s, 0, s->nchars, x + 1, y, false);
2091 }
2092}
2093
2094static void
2095android_draw_composite_glyph_string_foreground (struct glyph_string *s)
2096{
2097 int i, j, x;
2098 struct font *font = s->font;
2099
2100 /* If first glyph of S has a left box line, start drawing the text
2101 of S to the right of that box line. */
2102 if (s->face && s->face->box != FACE_NO_BOX
2103 && s->first_glyph->left_box_line_p)
2104 x = s->x + max (s->face->box_vertical_line_width, 0);
2105 else
2106 x = s->x;
2107
2108 /* S is a glyph string for a composition. S->cmp_from is the index
2109 of the first character drawn for glyphs of this composition.
2110 S->cmp_from == 0 means we are drawing the very first character of
2111 this composition. */
2112
2113 /* Draw a rectangle for the composition if the font for the very
2114 first character of the composition could not be loaded. */
2115 if (s->font_not_found_p)
2116 {
2117 if (s->cmp_from == 0)
2118 android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f),
2119 s->gc, x, s->y,
2120 s->width - 1, s->height - 1);
2121 }
2122 else if (! s->first_glyph->u.cmp.automatic)
2123 {
2124 int y = s->ybase;
2125
2126 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
2127 /* TAB in a composition means display glyphs with
2128 padding space on the left or right. */
2129 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
2130 {
2131 int xx = x + s->cmp->offsets[j * 2];
2132 int yy = y - s->cmp->offsets[j * 2 + 1];
2133
2134 font->driver->draw (s, j, j + 1, xx, yy, false);
2135 if (s->face->overstrike)
2136 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
2137 }
2138 }
2139 else
2140 {
2141 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
2142 Lisp_Object glyph;
2143 int y = s->ybase;
2144 int width = 0;
2145
2146 for (i = j = s->cmp_from; i < s->cmp_to; i++)
2147 {
2148 glyph = LGSTRING_GLYPH (gstring, i);
2149 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
2150 width += LGLYPH_WIDTH (glyph);
2151 else
2152 {
2153 int xoff, yoff, wadjust;
2154
2155 if (j < i)
2156 {
2157 font->driver->draw (s, j, i, x, y, false);
2158 if (s->face->overstrike)
2159 font->driver->draw (s, j, i, x + 1, y, false);
2160 x += width;
2161 }
2162 xoff = LGLYPH_XOFF (glyph);
2163 yoff = LGLYPH_YOFF (glyph);
2164 wadjust = LGLYPH_WADJUST (glyph);
2165 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
2166 if (s->face->overstrike)
2167 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
2168 false);
2169 x += wadjust;
2170 j = i + 1;
2171 width = 0;
2172 }
2173 }
2174 if (j < i)
2175 {
2176 font->driver->draw (s, j, i, x, y, false);
2177 if (s->face->overstrike)
2178 font->driver->draw (s, j, i, x + 1, y, false);
2179 }
2180 }
2181}
2182
2183static void
2184android_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
2185{
2186 struct glyph *glyph = s->first_glyph;
2187 unsigned char2b[8];
2188 int x, i, j;
2189
2190 /* If first glyph of S has a left box line, start drawing the text
2191 of S to the right of that box line. */
2192 if (s->face && s->face->box != FACE_NO_BOX
2193 && s->first_glyph->left_box_line_p)
2194 x = s->x + max (s->face->box_vertical_line_width, 0);
2195 else
2196 x = s->x;
2197
2198 s->char2b = char2b;
2199
2200 for (i = 0; i < s->nchars; i++, glyph++)
2201 {
2202#ifdef GCC_LINT
2203 enum { PACIFY_GCC_BUG_81401 = 1 };
2204#else
2205 enum { PACIFY_GCC_BUG_81401 = 0 };
2206#endif
2207 char buf[7 + PACIFY_GCC_BUG_81401];
2208 char *str = NULL;
2209 int len = glyph->u.glyphless.len;
2210
2211 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
2212 {
2213 if (len > 0
2214 && CHAR_TABLE_P (Vglyphless_char_display)
2215 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
2216 >= 1))
2217 {
2218 Lisp_Object acronym
2219 = (! glyph->u.glyphless.for_no_font
2220 ? CHAR_TABLE_REF (Vglyphless_char_display,
2221 glyph->u.glyphless.ch)
2222 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
2223 if (CONSP (acronym))
2224 acronym = XCAR (acronym);
2225 if (STRINGP (acronym))
2226 str = SSDATA (acronym);
2227 }
2228 }
2229 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
2230 {
2231 unsigned int ch = glyph->u.glyphless.ch;
2232 eassume (ch <= MAX_CHAR);
2233 sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
2234 str = buf;
2235 }
2236
2237 if (str)
2238 {
2239 int upper_len = (len + 1) / 2;
2240
2241 /* It is assured that all LEN characters in STR is ASCII. */
2242 for (j = 0; j < len; j++)
2243 char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
2244 s->font->driver->draw (s, 0, upper_len,
2245 x + glyph->slice.glyphless.upper_xoff,
2246 s->ybase + glyph->slice.glyphless.upper_yoff,
2247 false);
2248 s->font->driver->draw (s, upper_len, len,
2249 x + glyph->slice.glyphless.lower_xoff,
2250 s->ybase + glyph->slice.glyphless.lower_yoff,
2251 false);
2252 }
2253 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
2254 android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc,
2255 x, s->ybase - glyph->ascent,
2256 glyph->pixel_width - 1,
2257 glyph->ascent + glyph->descent - 1);
2258 x += glyph->pixel_width;
2259 }
2260
2261 /* Defend against hypothetical bad code elsewhere that uses
2262 s->char2b after this function returns. */
2263 s->char2b = NULL;
2264}
2265
2266static void
2267android_draw_glyph_string (struct glyph_string *s)
2268{
2269 bool relief_drawn_p = false;
2270
2271 /* If S draws into the background of its successors, draw the
2272 background of the successors first so that S can draw into it.
2273 This makes S->next use XDrawString instead of XDrawImageString. */
2274 if (s->next && s->right_overhang && !s->for_overlaps)
2275 {
2276 int width;
2277 struct glyph_string *next;
2278
2279 for (width = 0, next = s->next;
2280 next && width < s->right_overhang;
2281 width += next->width, next = next->next)
2282 if (next->first_glyph->type != IMAGE_GLYPH)
2283 {
2284 android_set_glyph_string_gc (next);
2285 android_set_glyph_string_clipping (next);
2286 if (next->first_glyph->type == STRETCH_GLYPH)
2287 android_draw_stretch_glyph_string (next);
2288 else
2289 android_draw_glyph_string_background (next, true);
2290 next->num_clips = 0;
2291 }
2292 }
2293
2294 /* Set up S->gc, set clipping and draw S. */
2295 android_set_glyph_string_gc (s);
2296
2297 /* Draw relief (if any) in advance for char/composition so that the
2298 glyph string can be drawn over it. */
2299 if (!s->for_overlaps
2300 && s->face->box != FACE_NO_BOX
2301 && (s->first_glyph->type == CHAR_GLYPH
2302 || s->first_glyph->type == COMPOSITE_GLYPH))
2303
2304 {
2305 android_set_glyph_string_clipping (s);
2306 android_draw_glyph_string_background (s, true);
2307 android_draw_glyph_string_box (s);
2308 android_set_glyph_string_clipping (s);
2309 relief_drawn_p = true;
2310 }
2311 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
2312 && !s->clip_tail
2313 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
2314 || (s->next && s->next->hl != s->hl && s->right_overhang)))
2315 /* We must clip just this glyph. left_overhang part has already
2316 drawn when s->prev was drawn, and right_overhang part will be
2317 drawn later when s->next is drawn. */
2318 android_set_glyph_string_clipping_exactly (s, s);
2319 else
2320 android_set_glyph_string_clipping (s);
2321
2322 switch (s->first_glyph->type)
2323 {
2324 case IMAGE_GLYPH:
2325 android_draw_image_glyph_string (s);
2326 break;
2327
2328 case XWIDGET_GLYPH:
2329 emacs_abort ();
2330 break;
2331
2332 case STRETCH_GLYPH:
2333 android_draw_stretch_glyph_string (s);
2334 break;
2335
2336 case CHAR_GLYPH:
2337 if (s->for_overlaps)
2338 s->background_filled_p = true;
2339 else
2340 android_draw_glyph_string_background (s, false);
2341 android_draw_glyph_string_foreground (s);
2342 break;
2343
2344 case COMPOSITE_GLYPH:
2345 if (s->for_overlaps || (s->cmp_from > 0
2346 && ! s->first_glyph->u.cmp.automatic))
2347 s->background_filled_p = true;
2348 else
2349 android_draw_glyph_string_background (s, true);
2350 android_draw_composite_glyph_string_foreground (s);
2351 break;
2352
2353 case GLYPHLESS_GLYPH:
2354 if (s->for_overlaps)
2355 s->background_filled_p = true;
2356 else
2357 android_draw_glyph_string_background (s, true);
2358 android_draw_glyphless_glyph_string_foreground (s);
2359 break;
2360
2361 default:
2362 emacs_abort ();
2363 }
2364
2365 if (!s->for_overlaps)
2366 {
2367 int area_x, area_y, area_width, area_height;
2368 int area_max_x, decoration_width;
2369
2370 /* Prevent the underline from overwriting surrounding areas
2371 and the fringe. */
2372 window_box (s->w, s->area, &area_x, &area_y,
2373 &area_width, &area_height);
2374 area_max_x = area_x + area_width - 1;
2375
2376 decoration_width = s->width;
2377 if (!s->row->mode_line_p
2378 && !s->row->tab_line_p
2379 && area_max_x < (s->x + decoration_width - 1))
2380 decoration_width -= (s->x + decoration_width - 1) - area_max_x;
2381
2382 /* Draw relief if not yet drawn. */
2383 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2384 android_draw_glyph_string_box (s);
2385
2386 /* Draw underline. */
2387 if (s->face->underline)
2388 {
2389 if (s->face->underline == FACE_UNDER_WAVE)
2390 {
2391 if (s->face->underline_defaulted_p)
2392 android_draw_underwave (s, decoration_width);
2393 else
2394 {
2395 struct android_gc_values xgcv;
2396 android_get_gc_values (s->gc, ANDROID_GC_FOREGROUND, &xgcv);
2397 android_set_foreground (s->gc, s->face->underline_color);
2398 android_draw_underwave (s, decoration_width);
2399 android_set_foreground (s->gc, xgcv.foreground);
2400 }
2401 }
2402 else if (s->face->underline == FACE_UNDER_LINE)
2403 {
2404 unsigned long thickness, position;
2405 int y;
2406
2407 if (s->prev
2408 && s->prev->face->underline == FACE_UNDER_LINE
2409 && (s->prev->face->underline_at_descent_line_p
2410 == s->face->underline_at_descent_line_p)
2411 && (s->prev->face->underline_pixels_above_descent_line
2412 == s->face->underline_pixels_above_descent_line))
2413 {
2414 /* We use the same underline style as the previous one. */
2415 thickness = s->prev->underline_thickness;
2416 position = s->prev->underline_position;
2417 }
2418 else
2419 {
2420 struct font *font = font_for_underline_metrics (s);
2421 unsigned long minimum_offset;
2422 bool underline_at_descent_line;
2423 bool use_underline_position_properties;
2424 Lisp_Object val = (WINDOW_BUFFER_LOCAL_VALUE
2425 (Qunderline_minimum_offset, s->w));
2426
2427 if (FIXNUMP (val))
2428 minimum_offset = max (0, XFIXNUM (val));
2429 else
2430 minimum_offset = 1;
2431
2432 val = (WINDOW_BUFFER_LOCAL_VALUE
2433 (Qx_underline_at_descent_line, s->w));
2434 underline_at_descent_line
2435 = (!(NILP (val) || BASE_EQ (val, Qunbound))
2436 || s->face->underline_at_descent_line_p);
2437
2438 val = (WINDOW_BUFFER_LOCAL_VALUE
2439 (Qx_use_underline_position_properties, s->w));
2440 use_underline_position_properties
2441 = !(NILP (val) || BASE_EQ (val, Qunbound));
2442
2443 /* Get the underline thickness. Default is 1 pixel. */
2444 if (font && font->underline_thickness > 0)
2445 thickness = font->underline_thickness;
2446 else
2447 thickness = 1;
2448 if (underline_at_descent_line)
2449 position = ((s->height - thickness)
2450 - (s->ybase - s->y)
2451 - s->face->underline_pixels_above_descent_line);
2452 else
2453 {
2454 /* Get the underline position. This is the
2455 recommended vertical offset in pixels from
2456 the baseline to the top of the underline.
2457 This is a signed value according to the
2458 specs, and its default is
2459
2460 ROUND ((maximum descent) / 2), with
2461 ROUND(x) = floor (x + 0.5) */
2462
2463 if (use_underline_position_properties
2464 && font && font->underline_position >= 0)
2465 position = font->underline_position;
2466 else if (font)
2467 position = (font->descent + 1) / 2;
2468 else
2469 position = minimum_offset;
2470 }
2471
2472 /* Ignore minimum_offset if the amount of pixels was
2473 explicitly specified. */
2474 if (!s->face->underline_pixels_above_descent_line)
2475 position = max (position, minimum_offset);
2476 }
2477 /* Check the sanity of thickness and position. We should
2478 avoid drawing underline out of the current line area. */
2479 if (s->y + s->height <= s->ybase + position)
2480 position = (s->height - 1) - (s->ybase - s->y);
2481 if (s->y + s->height < s->ybase + position + thickness)
2482 thickness = (s->y + s->height) - (s->ybase + position);
2483 s->underline_thickness = thickness;
2484 s->underline_position = position;
2485 y = s->ybase + position;
2486 if (s->face->underline_defaulted_p)
2487 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc,
2488 s->x, y, decoration_width, thickness);
2489 else
2490 {
2491 struct android_gc_values xgcv;
2492 android_get_gc_values (s->gc, ANDROID_GC_FOREGROUND, &xgcv);
2493 android_set_foreground (s->gc, s->face->underline_color);
2494 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc,
2495 s->x, y, decoration_width, thickness);
2496 android_set_foreground (s->gc, xgcv.foreground);
2497 }
2498 }
2499 }
2500 /* Draw overline. */
2501 if (s->face->overline_p)
2502 {
2503 unsigned long dy = 0, h = 1;
2504
2505 if (s->face->overline_color_defaulted_p)
2506 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f),
2507 s->gc, s->x, s->y + dy,
2508 decoration_width, h);
2509 else
2510 {
2511 struct android_gc_values xgcv;
2512 android_get_gc_values (s->gc, ANDROID_GC_FOREGROUND, &xgcv);
2513 android_set_foreground (s->gc, s->face->overline_color);
2514 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc, s->x,
2515 s->y + dy, decoration_width, h);
2516 android_set_foreground (s->gc, xgcv.foreground);
2517 }
2518 }
2519
2520 /* Draw strike-through. */
2521 if (s->face->strike_through_p)
2522 {
2523 /* Y-coordinate and height of the glyph string's first
2524 glyph. We cannot use s->y and s->height because those
2525 could be larger if there are taller display elements
2526 (e.g., characters displayed with a larger font) in the
2527 same glyph row. */
2528 int glyph_y = s->ybase - s->first_glyph->ascent;
2529 int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
2530 /* Strike-through width and offset from the glyph string's
2531 top edge. */
2532 unsigned long h = 1;
2533 unsigned long dy = (glyph_height - h) / 2;
2534
2535 if (s->face->strike_through_color_defaulted_p)
2536 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f),
2537 s->gc, s->x, glyph_y + dy,
2538 s->width, h);
2539 else
2540 {
2541 struct android_gc_values xgcv;
2542 android_get_gc_values (s->gc, ANDROID_GC_FOREGROUND, &xgcv);
2543 android_set_foreground (s->gc, s->face->strike_through_color);
2544 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc, s->x,
2545 glyph_y + dy, decoration_width, h);
2546 android_set_foreground (s->gc, xgcv.foreground);
2547 }
2548 }
2549
2550 if (s->prev)
2551 {
2552 struct glyph_string *prev;
2553
2554 for (prev = s->prev; prev; prev = prev->prev)
2555 if (prev->hl != s->hl
2556 && prev->x + prev->width + prev->right_overhang > s->x)
2557 {
2558 /* As prev was drawn while clipped to its own area, we
2559 must draw the right_overhang part using s->hl now. */
2560 enum draw_glyphs_face save = prev->hl;
2561
2562 prev->hl = s->hl;
2563 android_set_glyph_string_gc (prev);
2564 android_set_glyph_string_clipping_exactly (s, prev);
2565 if (prev->first_glyph->type == CHAR_GLYPH)
2566 android_draw_glyph_string_foreground (prev);
2567 else
2568 android_draw_composite_glyph_string_foreground (prev);
2569 android_reset_clip_rectangles (prev->f, prev->gc);
2570 prev->hl = save;
2571 prev->num_clips = 0;
2572 }
2573 }
2574
2575 if (s->next)
2576 {
2577 struct glyph_string *next;
2578
2579 for (next = s->next; next; next = next->next)
2580 if (next->hl != s->hl
2581 && next->x - next->left_overhang < s->x + s->width)
2582 {
2583 /* As next will be drawn while clipped to its own area,
2584 we must draw the left_overhang part using s->hl now. */
2585 enum draw_glyphs_face save = next->hl;
2586
2587 next->hl = s->hl;
2588 android_set_glyph_string_gc (next);
2589 android_set_glyph_string_clipping_exactly (s, next);
2590 if (next->first_glyph->type == CHAR_GLYPH)
2591 android_draw_glyph_string_foreground (next);
2592 else
2593 android_draw_composite_glyph_string_foreground (next);
2594 android_reset_clip_rectangles (next->f, next->gc);
2595 next->hl = save;
2596 next->num_clips = 0;
2597 next->clip_head = s->next;
2598 }
2599 }
2600 }
2601
2602 /* Reset clipping. */
2603 android_reset_clip_rectangles (s->f, s->gc);
2604 s->num_clips = 0;
2605
2606 /* Set the stippled flag that tells redisplay whether or not a
2607 stipple was actually draw. */
2608
2609 if (s->first_glyph->type != STRETCH_GLYPH
2610 && s->first_glyph->type != IMAGE_GLYPH
2611 && !s->row->stipple_p)
2612 s->row->stipple_p = s->stippled_p;
2613}
2614
2615static void
2616android_define_frame_cursor (struct frame *f, Emacs_Cursor cursor)
2617{
2618 /* Not supported, because cursors are not supported on Android. */
2619}
2620
2621static void
2622android_clear_frame_area (struct frame *f, int x, int y,
2623 int width, int height)
2624{
2625 android_clear_area (FRAME_ANDROID_WINDOW (f),
2626 x, y, width, height);
2627}
2628
2629void
2630android_clear_under_internal_border (struct frame *f)
2631{
2632 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
2633 {
2634 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
2635 int width = FRAME_PIXEL_WIDTH (f);
2636 int height = FRAME_PIXEL_HEIGHT (f);
2637 int margin = FRAME_TOP_MARGIN_HEIGHT (f);
2638 int face_id =
2639 (FRAME_PARENT_FRAME (f)
2640 ? (!NILP (Vface_remapping_alist)
2641 ? lookup_basic_face (NULL, f, CHILD_FRAME_BORDER_FACE_ID)
2642 : CHILD_FRAME_BORDER_FACE_ID)
2643 : (!NILP (Vface_remapping_alist)
2644 ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
2645 : INTERNAL_BORDER_FACE_ID));
2646 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
2647
2648 if (face)
2649 {
2650 unsigned long color = face->background;
2651 struct android_gc *gc = f->output_data.android->normal_gc;
2652
2653 android_set_foreground (gc, color);
2654 android_fill_rectangle (FRAME_ANDROID_WINDOW (f), gc, 0, margin,
2655 width, border);
2656 android_fill_rectangle (FRAME_ANDROID_WINDOW (f), gc, 0, 0,
2657 border, height);
2658 android_fill_rectangle (FRAME_ANDROID_WINDOW (f), gc, width - border,
2659 0, border, height);
2660 android_fill_rectangle (FRAME_ANDROID_WINDOW (f), gc, 0,
2661 height - border, width, border);
2662 android_set_foreground (gc, FRAME_FOREGROUND_PIXEL (f));
2663 }
2664 else
2665 {
2666 android_clear_area (FRAME_ANDROID_WINDOW (f), 0, 0,
2667 border, height);
2668 android_clear_area (FRAME_ANDROID_WINDOW (f), 0,
2669 margin, width, border);
2670 android_clear_area (FRAME_ANDROID_WINDOW (f), width - border,
2671 0, border, height);
2672 android_clear_area (FRAME_ANDROID_WINDOW (f), 0,
2673 height - border, width, border);
2674 }
2675 }
2676}
2677
2678static void
2679android_draw_hollow_cursor (struct window *w, struct glyph_row *row)
2680{
2681 struct frame *f = XFRAME (WINDOW_FRAME (w));
2682 struct android_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2683 int x, y, wd, h;
2684 struct android_gc_values xgcv;
2685 struct glyph *cursor_glyph;
2686 struct android_gc *gc;
2687
2688 /* Get the glyph the cursor is on. If we can't tell because
2689 the current matrix is invalid or such, give up. */
2690 cursor_glyph = get_phys_cursor_glyph (w);
2691 if (cursor_glyph == NULL)
2692 return;
2693
2694 /* Compute frame-relative coordinates for phys cursor. */
2695 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
2696 wd = w->phys_cursor_width - 1;
2697
2698 /* The foreground of cursor_gc is typically the same as the normal
2699 background color, which can cause the cursor box to be invisible. */
2700 xgcv.foreground = f->output_data.android->cursor_pixel;
2701 if (dpyinfo->scratch_cursor_gc)
2702 android_change_gc (dpyinfo->scratch_cursor_gc,
2703 ANDROID_GC_FOREGROUND, &xgcv);
2704 else
2705 dpyinfo->scratch_cursor_gc
2706 = android_create_gc (ANDROID_GC_FOREGROUND, &xgcv);
2707 gc = dpyinfo->scratch_cursor_gc;
2708
2709 /* When on R2L character, show cursor at the right edge of the
2710 glyph, unless the cursor box is as wide as the glyph or wider
2711 (the latter happens when x-stretch-cursor is non-nil). */
2712 if ((cursor_glyph->resolved_level & 1) != 0
2713 && cursor_glyph->pixel_width > wd)
2714 {
2715 x += cursor_glyph->pixel_width - wd;
2716 if (wd > 0)
2717 wd -= 1;
2718 }
2719 /* Set clipping, draw the rectangle, and reset clipping again. */
2720 android_clip_to_row (w, row, TEXT_AREA, gc);
2721 android_draw_rectangle (FRAME_ANDROID_WINDOW (f), gc, x, y, wd, h - 1);
2722 android_reset_clip_rectangles (f, gc);
2723}
2724
2725static void
2726android_draw_bar_cursor (struct window *w, struct glyph_row *row, int width,
2727 enum text_cursor_kinds kind)
2728{
2729 struct frame *f = XFRAME (w->frame);
2730 struct glyph *cursor_glyph;
2731 int cursor_start_y;
2732
2733 /* If cursor is out of bounds, don't draw garbage. This can happen
2734 in mini-buffer windows when switching between echo area glyphs
2735 and mini-buffer. */
2736 cursor_glyph = get_phys_cursor_glyph (w);
2737 if (cursor_glyph == NULL)
2738 return;
2739
2740 /* Experimental avoidance of cursor on xwidget. */
2741 if (cursor_glyph->type == XWIDGET_GLYPH)
2742 return;
2743
2744 /* If on an image, draw like a normal cursor. That's usually better
2745 visible than drawing a bar, esp. if the image is large so that
2746 the bar might not be in the window. */
2747 if (cursor_glyph->type == IMAGE_GLYPH)
2748 {
2749 struct glyph_row *r;
2750 r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
2751 draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
2752 }
2753 else
2754 {
2755 struct android_gc *gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc;
2756 unsigned long mask = ANDROID_GC_FOREGROUND | ANDROID_GC_BACKGROUND;
2757 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
2758 struct android_gc_values xgcv;
2759
2760 /* If the glyph's background equals the color we normally draw
2761 the bars cursor in, the bar cursor in its normal color is
2762 invisible. Use the glyph's foreground color instead in this
2763 case, on the assumption that the glyph's colors are chosen so
2764 that the glyph is legible. */
2765 if (face->background == f->output_data.android->cursor_pixel)
2766 xgcv.background = xgcv.foreground = face->foreground;
2767 else
2768 xgcv.background = xgcv.foreground = f->output_data.android->cursor_pixel;
2769
2770 if (gc)
2771 android_change_gc (gc, mask, &xgcv);
2772 else
2773 {
2774 gc = android_create_gc (mask, &xgcv);
2775 FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
2776 }
2777
2778 android_clip_to_row (w, row, TEXT_AREA, gc);
2779
2780 if (kind == BAR_CURSOR)
2781 {
2782 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
2783
2784 if (width < 0)
2785 width = FRAME_CURSOR_WIDTH (f);
2786 width = min (cursor_glyph->pixel_width, width);
2787
2788 w->phys_cursor_width = width;
2789
2790 /* If the character under cursor is R2L, draw the bar cursor
2791 on the right of its glyph, rather than on the left. */
2792 if ((cursor_glyph->resolved_level & 1) != 0)
2793 x += cursor_glyph->pixel_width - width;
2794
2795 android_fill_rectangle (FRAME_ANDROID_WINDOW (f), gc, x,
2796 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
2797 width, row->height);
2798 }
2799 else /* HBAR_CURSOR */
2800 {
2801 int dummy_x, dummy_y, dummy_h;
2802 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
2803
2804 if (width < 0)
2805 width = row->height;
2806
2807 width = min (row->height, width);
2808
2809 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
2810 &dummy_y, &dummy_h);
2811
2812 cursor_start_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y
2813 + row->height - width);
2814
2815 if ((cursor_glyph->resolved_level & 1) != 0
2816 && cursor_glyph->pixel_width > w->phys_cursor_width - 1)
2817 x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
2818 android_fill_rectangle (FRAME_ANDROID_WINDOW (f), gc, x,
2819 cursor_start_y,
2820 w->phys_cursor_width - 1, width);
2821 }
2822
2823 android_reset_clip_rectangles (f, gc);
2824 }
2825}
2826
2827static void
2828android_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
2829 int x, int y, enum text_cursor_kinds cursor_type,
2830 int cursor_width, bool on_p, bool active_p)
2831{
2832 if (on_p)
2833 {
2834 w->phys_cursor_type = cursor_type;
2835 w->phys_cursor_on_p = true;
2836
2837 if (glyph_row->exact_window_width_line_p
2838 && (glyph_row->reversed_p
2839 ? (w->phys_cursor.hpos < 0)
2840 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
2841 {
2842 glyph_row->cursor_in_fringe_p = true;
2843 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
2844 }
2845 else
2846 {
2847 switch (cursor_type)
2848 {
2849 case HOLLOW_BOX_CURSOR:
2850 android_draw_hollow_cursor (w, glyph_row);
2851 break;
2852
2853 case FILLED_BOX_CURSOR:
2854 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
2855 break;
2856
2857 case BAR_CURSOR:
2858 android_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
2859 break;
2860
2861 case HBAR_CURSOR:
2862 android_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
2863 break;
2864
2865 case NO_CURSOR:
2866 w->phys_cursor_width = 0;
2867 break;
2868
2869 default:
2870 emacs_abort ();
2871 }
2872 }
2873 }
2874}
2875
2876static void
2877android_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
2878{
2879 struct frame *f = XFRAME (WINDOW_FRAME (w));
2880 struct face *face;
2881
2882 face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
2883 if (face)
2884 android_set_foreground (f->output_data.android->normal_gc,
2885 face->foreground);
2886
2887 android_draw_line (FRAME_ANDROID_WINDOW (f),
2888 f->output_data.android->normal_gc,
2889 x, y0, x, y1);
2890}
2891
2892static void
2893android_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
2894{
2895 struct frame *f = XFRAME (WINDOW_FRAME (w));
2896 struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
2897 struct face *face_first
2898 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
2899 struct face *face_last
2900 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
2901 unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
2902 unsigned long color_first = (face_first
2903 ? face_first->foreground
2904 : FRAME_FOREGROUND_PIXEL (f));
2905 unsigned long color_last = (face_last
2906 ? face_last->foreground
2907 : FRAME_FOREGROUND_PIXEL (f));
2908
2909 if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
2910 /* A vertical divider, at least three pixels wide: Draw first and
2911 last pixels differently. */
2912 {
2913 android_set_foreground (f->output_data.android->normal_gc,
2914 color_first);
2915 android_fill_rectangle (FRAME_ANDROID_WINDOW (f),
2916 f->output_data.android->normal_gc,
2917 x0, y0, 1, y1 - y0);
2918 android_set_foreground (f->output_data.android->normal_gc,
2919 color);
2920 android_fill_rectangle (FRAME_ANDROID_WINDOW (f),
2921 f->output_data.android->normal_gc,
2922 x0 + 1, y0, x1 - x0 - 2, y1 - y0);
2923 android_set_foreground (f->output_data.android->normal_gc,
2924 color_last);
2925 android_fill_rectangle (FRAME_ANDROID_WINDOW (f),
2926 f->output_data.android->normal_gc,
2927 x1 - 1, y0, 1, y1 - y0);
2928 }
2929 else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
2930 /* A horizontal divider, at least three pixels high: Draw first
2931 and last pixels differently. */
2932 {
2933 android_set_foreground (f->output_data.android->normal_gc,
2934 color_first);
2935 android_fill_rectangle (FRAME_ANDROID_WINDOW (f),
2936 f->output_data.android->normal_gc,
2937 x0, y0, x1 - x0, 1);
2938 android_set_foreground (f->output_data.android->normal_gc, color);
2939 android_fill_rectangle (FRAME_ANDROID_WINDOW (f),
2940 f->output_data.android->normal_gc,
2941 x0, y0 + 1, x1 - x0, y1 - y0 - 2);
2942 android_set_foreground (f->output_data.android->normal_gc,
2943 color_last);
2944 android_fill_rectangle (FRAME_ANDROID_WINDOW (f),
2945 f->output_data.android->normal_gc,
2946 x0, y1 - 1, x1 - x0, 1);
2947 }
2948 else
2949 {
2950 /* In any other case do not draw the first and last pixels
2951 differently. */
2952 android_set_foreground (f->output_data.android->normal_gc, color);
2953 android_fill_rectangle (FRAME_ANDROID_WINDOW (f),
2954 f->output_data.android->normal_gc,
2955 x0, y0, x1 - x0, y1 - y0);
2956 }
2957}
2958
2959
2960
2961extern frame_parm_handler android_frame_parm_handlers[];
2962
2963#endif /* !ANDROID_STUBIFY */
2964
2965static struct redisplay_interface android_redisplay_interface =
2966 {
2967#ifndef ANDROID_STUBIFY
2968 android_frame_parm_handlers,
2969 gui_produce_glyphs,
2970 gui_write_glyphs,
2971 gui_insert_glyphs,
2972 gui_clear_end_of_line,
2973 android_scroll_run,
2974 android_after_update_window_line,
2975 NULL, /* update_window_begin */
2976 NULL, /* update_window_end */
2977 android_flip_and_flush,
2978 gui_clear_window_mouse_face,
2979 gui_get_glyph_overhangs,
2980 gui_fix_overlapping_area,
2981 android_draw_fringe_bitmap,
2982 NULL, /* define_fringe_bitmap */
2983 NULL, /* destroy_fringe_bitmap */
2984 android_compute_glyph_string_overhangs,
2985 android_draw_glyph_string,
2986 android_define_frame_cursor,
2987 android_clear_frame_area,
2988 android_clear_under_internal_border,
2989 android_draw_window_cursor,
2990 android_draw_vertical_window_border,
2991 android_draw_window_divider,
2992 NULL,
2993 NULL,
2994 NULL,
2995 android_default_font_parameter,
2996#endif
2997 };
2998
2999
3000
3001void
3002frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
3003{
3004 /* This cannot be implemented on Android, and as such is left
3005 blank. */
3006}
3007
3008char *
3009get_keysym_name (int keysym)
3010{
3011 return (char *) "UNKNOWN KEYSYM";
3012}
3013
3014
3015
3016/* Create a struct terminal, initialize it with the Android specific
3017 functions and make DISPLAY->TERMINAL point to it. */
3018
3019static struct terminal *
3020android_create_terminal (struct android_display_info *dpyinfo)
3021{
3022 struct terminal *terminal;
3023
3024 terminal = create_terminal (output_android,
3025 &android_redisplay_interface);
3026 terminal->display_info.android = dpyinfo;
3027 dpyinfo->terminal = terminal;
3028
3029 /* kboard is initialized in android_term_init. */
3030
3031#ifndef ANDROID_STUBIFY
3032
3033 terminal->clear_frame_hook = android_clear_frame;
3034 terminal->ring_bell_hook = android_ring_bell;
3035 terminal->toggle_invisible_pointer_hook
3036 = android_toggle_invisible_pointer;
3037 terminal->update_begin_hook = android_update_begin;
3038 terminal->update_end_hook = android_update_end;
3039 terminal->read_socket_hook = android_read_socket;
3040 terminal->frame_up_to_date_hook = android_frame_up_to_date;
3041 terminal->buffer_flipping_unblocked_hook
3042 = android_buffer_flipping_unblocked_hook;
3043 terminal->defined_color_hook = android_defined_color;
3044 terminal->query_frame_background_color
3045 = android_query_frame_background_color;
3046 terminal->query_colors = android_query_colors;
3047 terminal->mouse_position_hook = android_mouse_position;
3048 terminal->get_focus_frame = android_get_focus_frame;
3049 terminal->focus_frame_hook = android_focus_frame;
3050 terminal->frame_rehighlight_hook = android_frame_rehighlight;
3051 terminal->frame_raise_lower_hook = android_frame_raise_lower;
3052 terminal->frame_visible_invisible_hook
3053 = android_make_frame_visible_invisible;
3054 terminal->fullscreen_hook = android_fullscreen_hook;
3055 terminal->iconify_frame_hook = android_iconify_frame;
3056 terminal->set_window_size_hook = android_set_window_size;
3057 terminal->set_frame_offset_hook = android_set_offset;
3058 terminal->set_frame_alpha_hook = android_set_alpha;
3059 terminal->set_new_font_hook = android_new_font;
3060 terminal->set_bitmap_icon_hook = android_bitmap_icon;
3061 terminal->implicit_set_name_hook = android_implicitly_set_name;
3062 /* terminal->menu_show_hook = android_menu_show; XXX */
3063 terminal->change_tab_bar_height_hook = android_change_tab_bar_height;
3064 terminal->change_tool_bar_height_hook = android_change_tool_bar_height;
3065 /* terminal->set_vertical_scroll_bar_hook */
3066 /* = android_set_vertical_scroll_bar; */
3067 /* terminal->set_horizontal_scroll_bar_hook */
3068 /* = android_set_horizontal_scroll_bar; */
3069 terminal->set_scroll_bar_default_width_hook
3070 = android_set_scroll_bar_default_width;
3071 terminal->set_scroll_bar_default_height_hook
3072 = android_set_scroll_bar_default_height;
3073 /* terminal->condemn_scroll_bars_hook = android_condemn_scroll_bars; */
3074 /* terminal->redeem_scroll_bars_hook = android_redeem_scroll_bars; */
3075 /* terminal->judge_scroll_bars_hook = android_judge_scroll_bars; */
3076 terminal->free_pixmap = android_free_pixmap_hook;
3077 terminal->delete_frame_hook = android_delete_frame;
3078 terminal->delete_terminal_hook = android_delete_terminal;
3079
3080#else
3081 emacs_abort ();
3082#endif
3083
3084 return terminal;
3085}
3086
3087/* Initialize the Android terminal interface. The display connection
3088 has already been set up by the system at this point. */
3089
3090void
3091android_term_init (void)
3092{
3093 struct terminal *terminal;
3094 struct android_display_info *dpyinfo;
3095 Lisp_Object color_file, color_map;
3096
3097 dpyinfo = xzalloc (sizeof *dpyinfo);
3098 terminal = android_create_terminal (dpyinfo);
3099 terminal->kboard = allocate_kboard (Qandroid);
3100 terminal->kboard->reference_count++;
3101
3102 dpyinfo->n_planes = 24;
3103
3104 /* This function should only be called once at startup. */
3105 eassert (!x_display_list);
3106 x_display_list = dpyinfo;
3107
3108 dpyinfo->name_list_element
3109 = Fcons (build_pure_c_string ("android"), Qnil);
3110
3111 color_file = Fexpand_file_name (build_string ("rgb.txt"),
3112 Vdata_directory);
3113 color_map = Fx_load_color_file (color_file);
3114
3115 if (NILP (color_map))
3116 fatal ("Could not read %s.\n", SDATA (color_file));
3117
3118 dpyinfo->color_map = color_map;
3119
3120 /* TODO! */
3121 dpyinfo->resx = 96.0;
3122 dpyinfo->resy = 96.0;
3123
3124 /* https://lists.gnu.org/r/emacs-devel/2015-11/msg00194.html */
3125 dpyinfo->smallest_font_height = 1;
3126 dpyinfo->smallest_char_width = 1;
3127
3128 terminal->name = xstrdup ("android");
3129
3130 /* The display "connection" is now set up, and it must never go
3131 away. */
3132 terminal->reference_count = 30000;
3133}
3134
3135
3136
3137void
3138syms_of_androidterm (void)
3139{
3140 Fprovide (Qandroid, Qnil);
3141
3142 DEFVAR_BOOL ("x-use-underline-position-properties",
3143 x_use_underline_position_properties,
3144 doc: /* SKIP: real doc in xterm.c. */);
3145 x_use_underline_position_properties = true;
3146 DEFSYM (Qx_use_underline_position_properties,
3147 "x-use-underline-position-properties");
3148
3149 DEFVAR_BOOL ("x-underline-at-descent-line",
3150 x_underline_at_descent_line,
3151 doc: /* SKIP: real doc in xterm.c. */);
3152 x_underline_at_descent_line = false;
3153 DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
3154}
3155
3156void
3157mark_androidterm (void)
3158{
3159 if (x_display_list)
3160 mark_object (x_display_list->color_map);
3161}