mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-09-02 09:45:31 +00:00
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.
This commit is contained in:
parent
785095c416
commit
cfbc8a5dbc
83 changed files with 14297 additions and 217 deletions
|
@ -12,7 +12,7 @@
|
|||
(c-mode . ((c-file-style . "GNU")
|
||||
(c-noise-macro-names . ("INLINE" "NO_INLINE" "ATTRIBUTE_NO_SANITIZE_UNDEFINED"
|
||||
"UNINIT" "CALLBACK" "ALIGN_STACK" "ATTRIBUTE_MALLOC"
|
||||
"ATTRIBUTE_DEALLOC_FREE"))
|
||||
"ATTRIBUTE_DEALLOC_FREE" "ANDROID_EXPORT"))
|
||||
(electric-quote-comment . nil)
|
||||
(electric-quote-string . nil)
|
||||
(indent-tabs-mode . t)
|
||||
|
|
17
.gitignore
vendored
17
.gitignore
vendored
|
@ -52,6 +52,15 @@ src/config.h
|
|||
src/epaths.h
|
||||
src/emacs-module.h
|
||||
|
||||
# Built by recursive call to `configure'.
|
||||
*.android
|
||||
|
||||
# Built by `java'.
|
||||
java/install_temp/*
|
||||
java/*.apk*
|
||||
java/*.dex
|
||||
java/org/gnu/emacs/*.class
|
||||
|
||||
# C-level sources built by 'make'.
|
||||
lib/alloca.h
|
||||
lib/assert.h
|
||||
|
@ -81,6 +90,14 @@ src/globals.h
|
|||
src/lisp.mk
|
||||
src/verbose.mk
|
||||
|
||||
# Stuff built during cross compilation
|
||||
xcompile/lib/*
|
||||
xcompile/src/*
|
||||
xcompile/lib-src/*
|
||||
xcompile/sys/*
|
||||
xcompile/config.status
|
||||
xcompile/*.bak
|
||||
|
||||
# Lisp-level sources built by 'make'.
|
||||
*cus-load.el
|
||||
*loaddefs.el
|
||||
|
|
68
Makefile.in
68
Makefile.in
|
@ -106,15 +106,15 @@ top_builddir = @top_builddir@
|
|||
|
||||
FIND_DELETE = @FIND_DELETE@
|
||||
|
||||
HAVE_NATIVE_COMP = @HAVE_NATIVE_COMP@
|
||||
|
||||
USE_STARTUP_NOTIFICATION = @USE_STARTUP_NOTIFICATION@
|
||||
|
||||
HAVE_NATIVE_COMP = @HAVE_NATIVE_COMP@
|
||||
HAVE_BE_APP = @HAVE_BE_APP@
|
||||
|
||||
HAVE_PGTK = @HAVE_PGTK@
|
||||
HAVE_GSETTINGS = @HAVE_GSETTINGS@
|
||||
|
||||
ANDROID = @ANDROID@
|
||||
|
||||
# ==================== Where To Install Things ====================
|
||||
|
||||
# Location to install Emacs.app under GNUstep / macOS.
|
||||
|
@ -339,6 +339,10 @@ EMACS_PDMP = `./src/emacs${EXEEXT} --fingerprint`.pdmp
|
|||
# Subdirectories to make recursively.
|
||||
SUBDIR = $(NTDIR) lib lib-src src lisp
|
||||
|
||||
ifeq ($(ANDROID),yes)
|
||||
SUBDIR := $(SUBDIR) java
|
||||
endif
|
||||
|
||||
# The subdir makefiles created by config.status.
|
||||
SUBDIR_MAKEFILES_IN = @SUBDIR_MAKEFILES_IN@
|
||||
SUBDIR_MAKEFILES = $(patsubst ${srcdir}/%,%,${SUBDIR_MAKEFILES_IN:.in=})
|
||||
|
@ -467,20 +471,20 @@ epaths-force:
|
|||
esac; \
|
||||
done
|
||||
@(gamedir='${gamedir}'; \
|
||||
sed < ${srcdir}/src/epaths.in > epaths.h.$$$$ \
|
||||
-e 's;\(#.*PATH_LOADSEARCH\).*$$;\1 "${standardlisppath}";' \
|
||||
-e 's;\(#.*PATH_REL_LOADSEARCH\).*$$;\1 "${lispdirrel}";' \
|
||||
-e 's;\(#.*PATH_SITELOADSEARCH\).*$$;\1 "${locallisppath}";' \
|
||||
-e 's;\(#.*PATH_DUMPLOADSEARCH\).*$$;\1 "${buildlisppath}";' \
|
||||
-e '/^#define PATH_[^ ]*SEARCH /s/\([":]\):*/\1/g' \
|
||||
-e '/^#define PATH_[^ ]*SEARCH /s/:"/"/' \
|
||||
-e 's;\(#.*PATH_EXEC\).*$$;\1 "${archlibdir}";' \
|
||||
-e 's;\(#.*PATH_INFO\).*$$;\1 "${infodir}";' \
|
||||
-e 's;\(#.*PATH_DATA\).*$$;\1 "${etcdir}";' \
|
||||
-e 's;\(#.*PATH_BITMAPS\).*$$;\1 "${bitmapdir}";' \
|
||||
-e 's;\(#.*PATH_X_DEFAULTS\).*$$;\1 "${x_default_search_path}";' \
|
||||
-e 's;\(#.*PATH_GAME\).*$$;\1 $(PATH_GAME);' \
|
||||
-e 's;\(#.*PATH_DOC\).*$$;\1 "${etcdocdir}";') && \
|
||||
sed < ${srcdir}/src/epaths.in > epaths.h.$$$$ \
|
||||
-e 's;\(#define.*PATH_LOADSEARCH\).*$$;\1 "${standardlisppath}";' \
|
||||
-e 's;\(#define.*PATH_REL_LOADSEARCH\).*$$;\1 "${lispdirrel}";' \
|
||||
-e 's;\(#define.*PATH_SITELOADSEARCH\).*$$;\1 "${locallisppath}";' \
|
||||
-e 's;\(#define.*PATH_DUMPLOADSEARCH\).*$$;\1 "${buildlisppath}";' \
|
||||
-e '/^#define PATH_[^ ]*SEARCH /s/\([":]\):*/\1/g' \
|
||||
-e '/^#define PATH_[^ ]*SEARCH /s/:"/"/' \
|
||||
-e 's;\(#define.*PATH_EXEC\).*$$;\1 "${archlibdir}";' \
|
||||
-e 's;\(#define.*PATH_INFO\).*$$;\1 "${infodir}";' \
|
||||
-e 's;\(#define.*PATH_DATA\).*$$;\1 "${etcdir}";' \
|
||||
-e 's;\(#define.*PATH_BITMAPS\).*$$;\1 "${bitmapdir}";' \
|
||||
-e 's;\(#define.*PATH_X_DEFAULTS\).*$$;\1 "${x_default_search_path}";' \
|
||||
-e 's;\(#define.*PATH_GAME\).*$$;\1 $(PATH_GAME);' \
|
||||
-e 's;\(#define.*PATH_DOC\).*$$;\1 "${etcdocdir}";') && \
|
||||
${srcdir}/build-aux/move-if-change epaths.h.$$$$ src/epaths.h
|
||||
|
||||
# The w32 build needs a slightly different editing, and it uses
|
||||
|
@ -532,6 +536,12 @@ lisp: src
|
|||
lib lib-src lisp nt: Makefile
|
||||
$(MAKE) -C $@ all
|
||||
|
||||
java: lisp
|
||||
$(MAKE) -C $@ all
|
||||
|
||||
xcompile: src
|
||||
$(MAKE) -C $@ all
|
||||
|
||||
trampolines: src lisp
|
||||
ifeq ($(HAVE_NATIVE_COMP),yes)
|
||||
$(MAKE) -C lisp trampolines
|
||||
|
@ -561,20 +571,38 @@ blessmail: Makefile src
|
|||
# then attempts to build that file. This forces 'Makefile', 'lib/Makefile',
|
||||
# etc. to be built without running into similar recursion problems.
|
||||
MAKEFILE_NAME = Makefile
|
||||
ifeq ($(ANDROID),)
|
||||
$(MAKEFILE_NAME): config.status $(srcdir)/configure \
|
||||
$(srcdir)/lib/gnulib.mk.in \
|
||||
$(srcdir)/Makefile.in $(SUBDIR_MAKEFILES_IN) $(CONFIG_STATUS_FILES_IN)
|
||||
MAKE='$(MAKE)' ./config.status
|
||||
else
|
||||
# Note that calling config.status is insufficient on Android due to
|
||||
# the recursive calls to configure.
|
||||
|
||||
$(MAKEFILE_NAME): $(srcdir)/configure \
|
||||
$(srcdir)/lib/gnulib.mk.in \
|
||||
$(srcdir)/Makefile.in $(SUBDIR_MAKEFILES_IN) $(CONFIG_STATUS_FILES_IN)
|
||||
$(CFG) $(srcdir)/configure $(CONFIGURE_FLAGS);
|
||||
endif
|
||||
|
||||
# Don't erase these files if make is interrupted while refreshing them.
|
||||
.PRECIOUS: Makefile config.status
|
||||
|
||||
# Note that calling config.status --recheck is insufficient on Android
|
||||
# due to the recursive calls to configure.
|
||||
|
||||
ifneq ($(ANDROID),)
|
||||
config.status: ${srcdir}/configure
|
||||
if [ -x ./config.status ]; then \
|
||||
$(CFG) $(srcdir)/configure $(CONFIGURE_FLAGS)
|
||||
else
|
||||
config.status: ${srcdir}/configure
|
||||
if [ -x ./config.status ]; then \
|
||||
$(CFG) ./config.status --recheck; \
|
||||
else \
|
||||
else \
|
||||
$(CFG) $(srcdir)/configure $(CONFIGURE_FLAGS); \
|
||||
fi
|
||||
endif
|
||||
|
||||
$(srcdir)/configure: $(srcdir)/configure.ac $(srcdir)/m4/*.m4
|
||||
cd $(srcdir) && ./autogen.sh autoconf
|
||||
|
@ -999,7 +1027,7 @@ mostlyclean: $(mostlyclean_dirs:=_mostlyclean)
|
|||
### with them.
|
||||
###
|
||||
### Delete '.dvi' files here if they are not part of the distribution.
|
||||
clean_dirs = $(mostlyclean_dirs) nextstep admin/charsets admin/unidata
|
||||
clean_dirs = $(mostlyclean_dirs) java nextstep admin/charsets admin/unidata
|
||||
|
||||
$(foreach dir,$(clean_dirs),$(eval $(call submake_template,$(dir),clean)))
|
||||
|
||||
|
|
|
@ -134,3 +134,5 @@ cp -- "$gnulib_srcdir"/lib/af_alg.h \
|
|||
"$src"lib &&
|
||||
{ test -z "$src" || cd "$src"; } &&
|
||||
./autogen.sh
|
||||
|
||||
echo "Please update the block of vpath statements in lib/Makefile.in"
|
||||
|
|
524
configure.ac
524
configure.ac
|
@ -26,6 +26,16 @@ dnl Note this is parsed by (at least) make-dist and lisp/cedet/ede/emacs.el.
|
|||
AC_INIT([GNU Emacs], [30.0.50], [bug-gnu-emacs@gnu.org], [],
|
||||
[https://www.gnu.org/software/emacs/])
|
||||
|
||||
if test "$XCONFIGURE" = "android"; then
|
||||
# configure is being called recursively to configure Emacs for
|
||||
# Android!
|
||||
AC_MSG_NOTICE([called to recursively configure Emacs \
|
||||
for Android.])
|
||||
# Set CC to ANDROID_CC, and CXX to ANDROID_CXX.
|
||||
CC=$ANDROID_CC
|
||||
CXX=$ANDROID_CXX
|
||||
fi
|
||||
|
||||
dnl Set emacs_config_options to the options of 'configure', quoted for the shell,
|
||||
dnl and then quoted again for a C string. Separate options with spaces.
|
||||
dnl Add some environment variables, if they were passed via the environment
|
||||
|
@ -126,7 +136,25 @@ MAKE=$ac_cv_path_MAKE
|
|||
export MAKE
|
||||
|
||||
dnl Canonicalize the configuration name.
|
||||
if test "$XCONFIGURE" = "android"; then
|
||||
dnl Set host to whatever Android system Emacs is being configured
|
||||
dnl for. Determine this by looking at the output of ANDROID_CC.
|
||||
|
||||
AC_MSG_CHECKING([the cross-compiler's target])
|
||||
cc_target=`${CC} -v 2>&1 | sed -n 's/Target: //p'`
|
||||
case "$cc_target" in
|
||||
*android*) host_alias=$cc_target
|
||||
;;
|
||||
*) AC_MSG_ERROR([The cross compiler does not compile for Android.
|
||||
Please verify that you specified the correct compiler in the ANDROID_CC
|
||||
and ANDROID_CXX variables when you ran configure.])
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT([$host_alias])
|
||||
fi
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
AC_CANONICAL_BUILD
|
||||
|
||||
case $host in
|
||||
*-mingw*)
|
||||
|
@ -207,6 +235,13 @@ AC_ARG_WITH([all],
|
|||
[with_features=$withval],
|
||||
[with_features=yes])
|
||||
|
||||
dnl ARCH_INDEPENDENT_CONFIG_FILES(FILE...)
|
||||
dnl Like AC_CONFIG_FILES(FILE). However, do not generate this
|
||||
dnl if configure is being called recursively in preparation
|
||||
dnl for cross-compilation.
|
||||
AC_DEFUN([ARCH_INDEPENDENT_CONFIG_FILES], [
|
||||
AS_IF([test "$XCONFIGURE" != "android"], [AC_CONFIG_FILES([$1])])])
|
||||
|
||||
dnl OPTION_DEFAULT_OFF(NAME, HELP-STRING)
|
||||
dnl Create a new --with option that defaults to being disabled.
|
||||
dnl NAME is the base name of the option. The shell variable with_NAME
|
||||
|
@ -498,6 +533,7 @@ OPTION_DEFAULT_ON([threads],[don't compile with elisp threading support])
|
|||
OPTION_DEFAULT_OFF([cygwin32-native-compilation],[use native compilation on 32-bit Cygwin])
|
||||
OPTION_DEFAULT_ON([xinput2],[don't use version 2 of the X Input Extension for input])
|
||||
OPTION_DEFAULT_OFF([small-ja-dic],[generate a smaller-size Japanese dictionary])
|
||||
OPTION_DEFAULT_OFF([android],[cross-compile Android application package])
|
||||
|
||||
AC_ARG_WITH([file-notification],[AS_HELP_STRING([--with-file-notification=LIB],
|
||||
[use a file notification library (LIB one of: yes, inotify, kqueue, gfile, w32, no)])],
|
||||
|
@ -682,6 +718,237 @@ AC_ARG_ENABLE([build-details],
|
|||
[test "$enableval" = no && BUILD_DETAILS=--no-build-details])
|
||||
AC_SUBST([BUILD_DETAILS])
|
||||
|
||||
# Start Android configuration. This is done in three steps:
|
||||
|
||||
# First, the SDK tools needed to build the Android package on the host
|
||||
# are found.
|
||||
|
||||
# Then, configure is called inside itself with the NDK C and C++
|
||||
# compilers, and the Makefiles generated, along with config.h, are
|
||||
# renamed to end with .android.
|
||||
|
||||
# Finally, configure continues to configure the Emacs binary that will
|
||||
# run on the host.
|
||||
|
||||
ANDROID=
|
||||
JAVAC=
|
||||
AAPT=
|
||||
JARSIGNER=
|
||||
ZIPALIGN=
|
||||
DX=
|
||||
ANDROID_JAR=
|
||||
ANDROID_ABI=
|
||||
|
||||
# This is a list of Makefiles that have alternative versions for
|
||||
# Android.
|
||||
android_makefiles="lib/Makefile lib/gnulib.mk lib-src/Makefile src/Makefile"
|
||||
|
||||
AC_ARG_VAR([JAVAC], [Java compiler path. Used for Android.])
|
||||
AC_ARG_VAR([JARSIGNER], [Java package signer path. Used for Android.])
|
||||
AC_ARG_VAR([SDK_BULD_TOOLS], [Path to the Android SDK build tools.])
|
||||
|
||||
if test "$with_android" = "yes"; then
|
||||
AC_MSG_ERROR([Please specify the path to the Android.jar file, like so:
|
||||
|
||||
./configure --with-android=/path/to/android.jar
|
||||
|
||||
along with the path to the SDK build-tools (this is the directory with
|
||||
tools such as aapt, dx, and aidl):
|
||||
|
||||
SDK_BUILD_TOOLS=/path/to/sdk-build-tools
|
||||
|
||||
The cross-compiler should then be specified:
|
||||
|
||||
ANDROID_CC=/path/to/armv7a-linux-androideabi19-clang
|
||||
ANDROID_CXX=/path/to/armv7a-linux-androideabi19-clang++])
|
||||
elif test "$with_android" = "no" || test "$with_android" = ""; then
|
||||
ANDROID=no
|
||||
else
|
||||
AC_CHECK_PROGS([JAVAC], [javac])
|
||||
if test "$JAVAC" = ""; then
|
||||
AC_MSG_ERROR([The Java compiler required to build Emacs was not found.
|
||||
Please make sure `javac' can be found on your path, or alternatively specify
|
||||
the path to your Java compiler before configuring Emacs, like so:
|
||||
|
||||
JAVAC=/opt/jdk/bin/javac ./configure --with-android])
|
||||
fi
|
||||
AC_CHECK_PROGS([JARSIGNER], [jarsigner])
|
||||
if test "$JARSIGNER" = ""; then
|
||||
AC_MSG_ERROR([The Java package signing utility was not found.
|
||||
Please make sure `jarsigner' can be found on your path, or alternatively
|
||||
specify its location before configuring Emacs, like so:
|
||||
|
||||
JARSIGNER=/opt/jdk/bin/jarsigner ./configure --with-android])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([whether or not the Java compiler works],
|
||||
[emacs_cv_working_javac],
|
||||
AS_IF([rm -f conftest.class
|
||||
cat << EOF > conftest.java
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
||||
class conftest extends Activity
|
||||
{
|
||||
@Override
|
||||
public void
|
||||
onCreate (Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate (savedInstanceState);
|
||||
}
|
||||
}
|
||||
|
||||
EOF
|
||||
("$JAVAC" -classpath "$with_android" -target 1.7 -source 1.7 conftest.java \
|
||||
-d . >&AS_MESSAGE_LOG_FD 2>&1) && test -s conftest.class && rm -f conftest.class],
|
||||
[emacs_cv_working_javac=yes],
|
||||
[emacs_cv_working_javac=no]))
|
||||
|
||||
if test "$emacs_cv_working_javac" = "no"; then
|
||||
AC_MSG_ERROR([The Java compiler does not work, or you did not specify
|
||||
a valid path to android.jar. See config.log for more details.])
|
||||
fi
|
||||
|
||||
ANDROID_JAR="$with_android"
|
||||
|
||||
AC_PATH_PROGS([AAPT], [aapt], [], "${SDK_BUILD_TOOLS}:$PATH")
|
||||
if test "$AAPT" = ""; then
|
||||
AC_MSG_ERROR([The Android asset packaging tool was not found.
|
||||
Please verify that the path to the SDK build tools you specified is correct])
|
||||
fi
|
||||
|
||||
AC_PATH_PROGS([DX], [dx d8], [], "${SDK_BUILD_TOOLS}:$PATH")
|
||||
if test "DX" = ""; then
|
||||
AC_MSG_ERROR([The Android dexer was not found.
|
||||
Please verify that the path to the SDK build tools you specified is correct])
|
||||
fi
|
||||
|
||||
AC_PATH_PROGS([ZIPALIGN], [zipalign], [], "${SDK_BUILD_TOOLS}:$PATH")
|
||||
if test "ZIPALIGN" = ""; then
|
||||
AC_MSG_ERROR([The Android ZIP archive alignment utility was not found.
|
||||
Please verify that the path to the SDK build tools you specified is correct]);
|
||||
fi
|
||||
|
||||
dnl Now configure Emacs to generate binaries for Android. After the
|
||||
dnl configuration completes, move the generated Makefiles.
|
||||
|
||||
if test "$ANDROID_CC" = "" || test "$ANDROID_CXX" = ""; then
|
||||
AC_MSG_ERROR([Please specify the path to the Android cross-compiler
|
||||
for your machine. For example:
|
||||
|
||||
ANDROID_CC=/path/to/armv7a-linux-androideabi19-clang \\
|
||||
ANDROID_CXX=/path/to/armv7a-linux-androideabi19-clang++ \\
|
||||
./configure --with-android])
|
||||
fi
|
||||
|
||||
dnl Obtain the cross compiler's target to find out where binaries go
|
||||
dnl in the resulting package.
|
||||
|
||||
AC_MSG_CHECKING([for the kind of Android system Emacs is being built for])
|
||||
cc_target=`${ANDROID_CC} -v 2>&1 | sed -n 's/Target: //p'`
|
||||
case "$cc_target" in
|
||||
*i[3-6]86*) android_abi=x86
|
||||
;;
|
||||
*x86_64*) android_abi=x86_64
|
||||
;;
|
||||
*aarch64*) android_abi=arm64-v8a
|
||||
;;
|
||||
*arm*v7a*) android_abi=armeabi-v7a
|
||||
;;
|
||||
*mips*) android_abi=mips
|
||||
;;
|
||||
*arm*) android_abi=armeabi
|
||||
;;
|
||||
*) AC_MSG_ERROR([configure could not determine the type of Android \
|
||||
binary Emacs is being configured for. Please port this configure script \
|
||||
to your Android system, or verify that you specified the correct compiler \
|
||||
in the ANDROID_CC and ANDROID_CXX variables when you ran configure.])
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT([$android_abi])
|
||||
|
||||
ANDROID_ABI=$android_abi
|
||||
|
||||
# Save confdefs.h and config.log for now.
|
||||
mv -f confdefs.h _confdefs.h
|
||||
mv -f config.log _config.log
|
||||
|
||||
AS_IF([XCONFIGURE=android ANDROID_CC="$ANDROID_CC" \
|
||||
ANDROID_CXX="$ANDROID_CXX" $0], [], [AC_MSG_ERROR([Failed to cross-\
|
||||
configure Emacs for android.])])
|
||||
|
||||
# Now set ANDROID to yes.
|
||||
ANDROID=yes
|
||||
|
||||
for makefile in $android_makefiles; do
|
||||
AC_MSG_NOTICE([Generating $makefile.android])
|
||||
mv -f "$makefile" "$makefile.android"
|
||||
done
|
||||
|
||||
AC_MSG_NOTICE([Generating src/config.h.android])
|
||||
mv -f src/config.h src/config.h.android
|
||||
|
||||
# Move confdefs.h back now that the recursive call to configure is
|
||||
# complete.
|
||||
mv -f _confdefs.h confdefs.h
|
||||
|
||||
# Move the Android config.log to config.log.android. */
|
||||
mv -f config.log config.log.android
|
||||
|
||||
# And _config.log back.
|
||||
mv -f _config.log config.log
|
||||
fi
|
||||
|
||||
AC_SUBST([ANDROID])
|
||||
AC_SUBST([JAVAC])
|
||||
AC_SUBST([AAPT])
|
||||
AC_SUBST([DX])
|
||||
AC_SUBST([ZIPALIGN])
|
||||
AC_SUBST([ANDROID_JAR])
|
||||
AC_SUBST([ANDROID_ABI])
|
||||
|
||||
if test "$XCONFIGURE" = "android"; then
|
||||
ANDROID=yes
|
||||
|
||||
# Enable cross compiling.
|
||||
cross_compiling=yes
|
||||
fi
|
||||
|
||||
AC_SUBST([XCONFIGURE])
|
||||
|
||||
if test "$ANDROID" = "yes"; then
|
||||
# When --with-android is specified, all build options must be
|
||||
# disabled, both within the recursive invocation of configure and
|
||||
# outside.
|
||||
with_xpm=no
|
||||
with_jpeg=no
|
||||
with_tiff=no
|
||||
with_gif=no
|
||||
with_png=no
|
||||
with_rsvg=no
|
||||
with_webp=no
|
||||
with_sqlite3=no
|
||||
with_lcms2=no
|
||||
with_libsystemd=no
|
||||
with_cairo=no
|
||||
with_xml2=no
|
||||
with_imagemagick=no
|
||||
with_json=no
|
||||
with_tree_sitter=no
|
||||
with_xft=no
|
||||
with_harfbuzz=no
|
||||
with_libotf=no
|
||||
with_gpm=no
|
||||
with_dbus=no
|
||||
with_gsettings=no
|
||||
with_selinx=no
|
||||
with_gnutls=no
|
||||
with_zlib=no
|
||||
with_modules=no
|
||||
with_threads=no
|
||||
fi
|
||||
|
||||
dnl This used to use changequote, but, apart from 'changequote is evil'
|
||||
dnl per the autoconf manual, we can speed up autoconf somewhat by quoting
|
||||
dnl the great gob of text. Thus it's not processed for possible expansion.
|
||||
|
@ -705,6 +972,11 @@ dnl quotation begins
|
|||
opsys='' unported=no
|
||||
case "${canonical}" in
|
||||
|
||||
## Android
|
||||
*linux-android* )
|
||||
opsys=android
|
||||
;;
|
||||
|
||||
## GNU/Linux and similar ports
|
||||
*-*-linux* )
|
||||
opsys=gnu-linux
|
||||
|
@ -871,6 +1143,7 @@ AC_DEFUN([_AC_PROG_CC_C89], [$2])
|
|||
|
||||
dnl Sets GCC=yes if using gcc.
|
||||
AC_PROG_CC([gcc cc cl clang "$XCRUN gcc" "$XCRUN clang"])
|
||||
|
||||
if test -n "$XCRUN"; then
|
||||
AC_CHECK_PROGS([AR], [ar "$XCRUN ar"])
|
||||
test -n "$AR" && export AR
|
||||
|
@ -1123,6 +1396,12 @@ AS_IF([test $gl_gcc_warnings = no],
|
|||
nw="$nw -Wsuggest-attribute=format"
|
||||
fi
|
||||
|
||||
# If Emacs is being built for Android and many functions are
|
||||
# currently stubbed out for operation on the build machine, disable
|
||||
# -Wsuggest-attribute=noreturn.
|
||||
|
||||
nw="$nw -Wsuggest-attribute=noreturn"
|
||||
|
||||
gl_MANYWARN_ALL_GCC([ws])
|
||||
gl_MANYWARN_COMPLEMENT([ws], [$ws], [$nw])
|
||||
for w in $ws; do
|
||||
|
@ -1143,6 +1422,8 @@ AS_IF([test $gl_gcc_warnings = no],
|
|||
gl_WARN_ADD([-Wno-null-pointer-arithmetic])
|
||||
gl_WARN_ADD([-Wno-implicit-const-int-float-conversion])
|
||||
gl_WARN_ADD([-Wno-int-in-bool-context])
|
||||
gl_WARN_ADD([-Wno-shift-overflow])
|
||||
gl_WARN_ADD([-Wno-bitwise-instead-of-logical])
|
||||
fi
|
||||
|
||||
# This causes too much noise in the MinGW build
|
||||
|
@ -1265,7 +1546,7 @@ else
|
|||
AM_DEFAULT_VERBOSITY=0
|
||||
fi
|
||||
AC_SUBST([AM_DEFAULT_VERBOSITY])
|
||||
AC_CONFIG_FILES([src/verbose.mk])
|
||||
ARCH_INDEPENDENT_CONFIG_FILES([src/verbose.mk])
|
||||
|
||||
dnl Some other nice autoconf tests.
|
||||
AC_PROG_INSTALL
|
||||
|
@ -1762,7 +2043,10 @@ AC_SUBST([SYSTEM_TYPE])
|
|||
pre_PKG_CONFIG_CFLAGS=$CFLAGS
|
||||
pre_PKG_CONFIG_LIBS=$LIBS
|
||||
|
||||
PKG_PROG_PKG_CONFIG([0.9.0])
|
||||
dnl pkg-config does not work when cross-compiling for Android.
|
||||
if test "${ANDROID}" != "yes"; then
|
||||
PKG_PROG_PKG_CONFIG([0.9.0])
|
||||
fi
|
||||
|
||||
dnl EMACS_CHECK_MODULES([GSTUFF], [gtk+-2.0 >= 1.3 glib = 1.3.4])
|
||||
dnl acts like PKG_CHECK_MODULES([GSTUFF], [gtk+-2.0 >= 1.3 glib = 1.3.4],
|
||||
|
@ -1945,14 +2229,49 @@ AC_SUBST([AUTO_DEPEND])
|
|||
|
||||
window_system=none
|
||||
|
||||
ANDROID_OBJ=
|
||||
ANDROID_LIBS=
|
||||
ANDROID_CFLAGS=
|
||||
CM_OBJ="cm.o"
|
||||
|
||||
if test "${ANDROID}" = "yes"; then
|
||||
window_system=android
|
||||
no_x=yes
|
||||
ANDROID_OBJ="androidterm.o androidfns.o androidfont.o android.o"
|
||||
ANDROID_LIBS=
|
||||
CM_OBJ=
|
||||
|
||||
AC_DEFINE([HAVE_ANDROID], [1], [Define to 1 if Emacs is being built
|
||||
with Android support])
|
||||
|
||||
if test "${XCONFIGURE}" != "android"; then
|
||||
AC_DEFINE([ANDROID_STUBIFY], [1], [Define to 1 if Emacs is being built
|
||||
for Android, but all API calls need to be stubbed out])
|
||||
else
|
||||
# Emacs will be built as a shared library, and a wrapper around it
|
||||
# will also be built for the benefit of applications. This
|
||||
# requires Emacs be built as a position independent executable.
|
||||
ANDROID_CFLAGS="-fPIC -fvisibility=hidden"
|
||||
|
||||
# Link with libraries required for Android support.
|
||||
ANDROID_LIBS="-landroid -llog"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(ANDROID)
|
||||
AC_SUBST(ANDROID_OBJ)
|
||||
AC_SUBST(ANDROID_LIBS)
|
||||
AC_SUBST(ANDROID_CFLAGS)
|
||||
|
||||
if test "${with_pgtk}" = "yes"; then
|
||||
window_system=pgtk
|
||||
fi
|
||||
|
||||
|
||||
AC_PATH_X
|
||||
if test "$no_x" != yes && test "${with_pgtk}" != "yes"; then
|
||||
window_system=x11
|
||||
if test "${ANDROID}" != "yes"; then
|
||||
AC_PATH_X
|
||||
if test "$no_x" != yes && test "${with_pgtk}" != "yes"; then
|
||||
window_system=x11
|
||||
fi
|
||||
fi
|
||||
|
||||
LD_SWITCH_X_SITE_RPATH=
|
||||
|
@ -2276,7 +2595,6 @@ NTDIR=
|
|||
LIBS_ECLIENT=
|
||||
LIB_WSOCK32=
|
||||
NTLIB=
|
||||
CM_OBJ="cm.o"
|
||||
XARGS_LIMIT=
|
||||
if test "${HAVE_W32}" = "yes"; then
|
||||
AC_DEFINE([HAVE_NTGUI], [1], [Define to use native MS Windows GUI.])
|
||||
|
@ -2439,7 +2757,11 @@ dnl use the toolkit if we have gtk, or X11R5 or newer.
|
|||
haiku )
|
||||
term_header=haikuterm.h
|
||||
;;
|
||||
android )
|
||||
term_header=androidterm.h
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_SUBST([HAVE_PGTK])
|
||||
|
||||
if test "$window_system" = none && test "X$with_x" != "Xno"; then
|
||||
|
@ -2773,7 +3095,6 @@ fail;
|
|||
fi
|
||||
fi
|
||||
|
||||
|
||||
### Use -lrsvg-2 if available, unless '--with-rsvg=no' is specified.
|
||||
HAVE_RSVG=no
|
||||
if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" \
|
||||
|
@ -4202,7 +4523,7 @@ AC_SUBST([HAVE_MODULES])
|
|||
AC_SUBST([MODULES_SUFFIX])
|
||||
AC_SUBST([MODULES_SECONDARY_SUFFIX])
|
||||
|
||||
AC_CONFIG_FILES([src/emacs-module.h])
|
||||
ARCH_INDEPENDENT_CONFIG_FILES([src/emacs-module.h])
|
||||
AC_SUBST_FILE([module_env_snippet_25])
|
||||
AC_SUBST_FILE([module_env_snippet_26])
|
||||
AC_SUBST_FILE([module_env_snippet_27])
|
||||
|
@ -5003,6 +5324,40 @@ getpwent endpwent getgrent endgrent \
|
|||
renameat2 \
|
||||
cfmakeraw cfsetspeed __executable_start log2 pthread_setname_np \
|
||||
pthread_set_name_np])
|
||||
|
||||
if test "$ac_cv_func_cfmakeraw" != "yes"; then
|
||||
# On some systems (Android), cfmakeraw is inline, so AC_CHECK_FUNCS
|
||||
# cannot find it. Check if some code including termios.h and using
|
||||
# cfmakeraw builds.
|
||||
AC_CACHE_CHECK([whether cfmakeraw is inline],
|
||||
[emacs_cv_func_cfmakeraw_inline],
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <termios.h>]],
|
||||
[[&cfmakeraw;]])],
|
||||
[emacs_cv_func_cfmakeraw_inline=yes],
|
||||
[emacs_cv_func_cfmakeraw_inline=no])])
|
||||
|
||||
if test "$emacs_cv_func_cfmakeraw_inline" = "yes"; then
|
||||
# Define HAVE_CFMAKERAW again.
|
||||
AC_DEFINE([HAVE_CFMAKERAW], [1])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$ac_cv_func_cfsetspeed" != "yes"; then
|
||||
AC_CACHE_CHECK([whether cfsetspeed is inline],
|
||||
[emacs_cv_func_cfsetspeed_inline],
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <termios.h>]],
|
||||
[[&cfsetspeed;]])],
|
||||
[emacs_cv_func_cfsetspeed_inline=yes],
|
||||
[emacs_cv_func_cfsetspeed_inline=no])])
|
||||
|
||||
if test "$emacs_cv_func_cfsetspeed_inline" = "yes"; then
|
||||
# Define HAVE_CFSETSPEED again.
|
||||
AC_DEFINE([HAVE_CFSETSPEED], [1])
|
||||
fi
|
||||
fi
|
||||
|
||||
LIBS=$OLD_LIBS
|
||||
|
||||
if test "$ac_cv_func_pthread_setname_np" = "yes"; then
|
||||
|
@ -5108,7 +5463,7 @@ AC_DEFUN([tputs_link_source], [
|
|||
# than to expect to find it in ncurses.
|
||||
# Also we need tputs and friends to be able to build at all.
|
||||
AC_CACHE_CHECK([for library containing tputs], [emacs_cv_tputs_lib],
|
||||
[if test "${opsys}" = "mingw32"; then
|
||||
[if test "${opsys}" = "mingw32" || test "$opsys" = "android"; then
|
||||
emacs_cv_tputs_lib='none required'
|
||||
else
|
||||
# curses precedes termcap because of AIX (Bug#9736#35) and OpenIndiana.
|
||||
|
@ -5175,7 +5530,7 @@ fail;
|
|||
fi
|
||||
;;
|
||||
|
||||
mingw32)
|
||||
mingw32 | android)
|
||||
TERMINFO=no
|
||||
LIBS_TERMCAP=
|
||||
;;
|
||||
|
@ -5729,7 +6084,7 @@ case $opsys in
|
|||
AC_DEFINE([FIRST_PTY_LETTER], ['p'])
|
||||
;;
|
||||
|
||||
gnu-linux | gnu-kfreebsd | dragonfly | freebsd | openbsd | netbsd | darwin | nacl )
|
||||
gnu-linux | gnu-kfreebsd | dragonfly | freebsd | openbsd | netbsd | darwin | nacl | android )
|
||||
dnl if HAVE_GRANTPT
|
||||
if test "x$ac_cv_func_grantpt" = xyes; then
|
||||
AC_DEFINE([UNIX98_PTYS], [1], [Define if the system has Unix98 PTYs.])
|
||||
|
@ -6656,6 +7011,7 @@ AC_DEFINE_UNQUOTED([EMACS_CONFIG_FEATURES], ["${emacs_config_features}"],
|
|||
[Summary of some of the main features enabled by configure.])
|
||||
|
||||
AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D}
|
||||
Does Emacs use Android? ${ANDROID}
|
||||
Does Emacs use -lXpm? ${HAVE_XPM}
|
||||
Does Emacs use -ljpeg? ${HAVE_JPEG}
|
||||
Does Emacs use -ltiff? ${HAVE_TIFF}
|
||||
|
@ -6759,12 +7115,15 @@ fi
|
|||
AC_CONFIG_FILES([Makefile lib/gnulib.mk])
|
||||
|
||||
dnl config.status treats $srcdir specially, so I think this is ok...
|
||||
AC_CONFIG_FILES([$srcdir/doc/man/emacs.1])
|
||||
ARCH_INDEPENDENT_CONFIG_FILES([$srcdir/doc/man/emacs.1])
|
||||
|
||||
m4_define([subdir_makefiles],
|
||||
[lib/Makefile lib-src/Makefile oldXMenu/Makefile doc/emacs/Makefile doc/misc/Makefile doc/lispintro/Makefile doc/lispref/Makefile src/Makefile lwlib/Makefile lisp/Makefile leim/Makefile nextstep/Makefile nt/Makefile])
|
||||
SUBDIR_MAKEFILES="subdir_makefiles"
|
||||
AC_CONFIG_FILES(subdir_makefiles)
|
||||
AC_CONFIG_FILES([lib/Makefile lib-src/Makefile oldXMenu/Makefile src/Makefile
|
||||
lwlib/Makefile nextstep/Makefile nt/Makefile])
|
||||
ARCH_INDEPENDENT_CONFIG_FILES([doc/emacs/Makefile doc/misc/Makefile
|
||||
doc/lispintro/Makefile doc/lispref/Makefile
|
||||
lisp/Makefile leim/Makefile])
|
||||
|
||||
SUBDIR_MAKEFILES="lib/Makefile lib-src/Makefile oldXMenu/Makefile src/Makefile lwlib/Makefile nextstep/Makefile nt/Makefile doc/emacs/Makefile doc/misc/Makefile doc/lispintro/Makefile doc/lispref/Makefile lisp/Makefile leim/Makefile"
|
||||
|
||||
dnl The test/ directory is missing if './make-dist --no-tests' was used.
|
||||
opt_makefile=test/Makefile
|
||||
|
@ -6772,24 +7131,31 @@ if test -f "$srcdir/$opt_makefile.in"; then
|
|||
SUBDIR_MAKEFILES="$SUBDIR_MAKEFILES $opt_makefile"
|
||||
dnl Again, it's best not to use a variable. Though you can add
|
||||
dnl ", [], [opt_makefile='$opt_makefile']" and it should work.
|
||||
AC_CONFIG_FILES([test/Makefile])
|
||||
AC_CONFIG_FILES([test/manual/noverlay/Makefile])
|
||||
ARCH_INDEPENDENT_CONFIG_FILES([test/Makefile])
|
||||
ARCH_INDEPENDENT_CONFIG_FILES([test/manual/noverlay/Makefile])
|
||||
fi
|
||||
opt_makefile=test/infra/Makefile
|
||||
if test -f "$srcdir/$opt_makefile.in"; then
|
||||
SUBDIR_MAKEFILES="$SUBDIR_MAKEFILES $opt_makefile"
|
||||
dnl Again, it's best not to use a variable. Though you can add
|
||||
dnl ", [], [opt_makefile='$opt_makefile']" and it should work.
|
||||
AC_CONFIG_FILES([test/infra/Makefile])
|
||||
ARCH_INDEPENDENT_CONFIG_FILES([test/infra/Makefile])
|
||||
fi
|
||||
|
||||
if test "$ANDROID" = "yes"; then
|
||||
SUBDIR_MAKEFILES="$SUBDIR_MAKEFILES java/Makefile"
|
||||
fi
|
||||
|
||||
if test "$XCOMPILE" = "yes"; then
|
||||
SUBDIR_MAKEFILES="$SUBDIR_MAKEFILES xcompile/Makefile"
|
||||
fi
|
||||
|
||||
dnl The admin/ directory used to be excluded from tarfiles.
|
||||
if test -d $srcdir/admin; then
|
||||
SUBDIR_MAKEFILES="$SUBDIR_MAKEFILES admin/charsets/Makefile admin/unidata/Makefile admin/grammars/Makefile"
|
||||
AC_CONFIG_FILES([admin/charsets/Makefile])
|
||||
AC_CONFIG_FILES([admin/unidata/Makefile])
|
||||
AC_CONFIG_FILES([admin/grammars/Makefile])
|
||||
ARCH_INDEPENDENT_CONFIG_FILES([admin/charsets/Makefile])
|
||||
ARCH_INDEPENDENT_CONFIG_FILES([admin/unidata/Makefile])
|
||||
ARCH_INDEPENDENT_CONFIG_FILES([admin/grammars/Makefile])
|
||||
fi dnl -d admin
|
||||
|
||||
|
||||
|
@ -6800,65 +7166,75 @@ AC_SUBST([SUBDIR_MAKEFILES_IN])
|
|||
SMALL_JA_DIC=$with_small_ja_dic
|
||||
AC_SUBST([SMALL_JA_DIC])
|
||||
|
||||
dnl You might wonder (I did) why epaths.h is generated by running make,
|
||||
dnl rather than just letting configure generate it from epaths.in.
|
||||
dnl One reason is that the various paths are not fully expanded (see above);
|
||||
dnl e.g., gamedir='${localstatedir}/games/emacs'.
|
||||
dnl Secondly, the GNU Coding standards require that one should be able
|
||||
dnl to run 'make prefix=/some/where/else' and override the values set
|
||||
dnl by configure. This also explains the 'move-if-change' test and
|
||||
dnl the use of force in the 'epaths-force' rule in Makefile.in.
|
||||
AC_CONFIG_COMMANDS([src/epaths.h], [
|
||||
if test "${opsys}" = "mingw32"; then
|
||||
${MAKE-make} MAKEFILE_NAME=do-not-make-Makefile epaths-force-w32
|
||||
elif test "$HAVE_NS" = "yes" && test "$EN_NS_SELF_CONTAINED" = "yes"; then
|
||||
${MAKE-make} MAKEFILE_NAME=do-not-make-Makefile epaths-force-ns-self-contained
|
||||
else
|
||||
${MAKE-make} MAKEFILE_NAME=do-not-make-Makefile epaths-force
|
||||
fi || AC_MSG_ERROR(['src/epaths.h' could not be made.])
|
||||
], [GCC="$GCC" CPPFLAGS="$CPPFLAGS" opsys="$opsys" HAVE_NS="$HAVE_NS"
|
||||
EN_NS_SELF_CONTAINED="$EN_NS_SELF_CONTAINED"])
|
||||
dnl The following commands are run on the host system when building
|
||||
dnl Emacs.
|
||||
|
||||
dnl NB we have to cheat and use the ac_... version because abs_top_srcdir
|
||||
dnl is not yet set, sigh. Or we could use ../$srcdir/src/.gdbinit,
|
||||
dnl or a symlink?
|
||||
AC_CONFIG_COMMANDS([src/.gdbinit], [
|
||||
if test ! -f src/.gdbinit && test -f "$srcdir/src/.gdbinit"; then
|
||||
AS_ECHO(["source $ac_abs_top_srcdir/src/.gdbinit"]) > src/.gdbinit
|
||||
fi
|
||||
])
|
||||
if test "$XCONFIGURE" != "android"; then
|
||||
dnl You might wonder (I did) why epaths.h is generated by running
|
||||
dnl make, rather than just letting configure generate it from
|
||||
dnl epaths.in. One reason is that the various paths are not fully
|
||||
dnl expanded (see above); e.g.,
|
||||
dnl gamedir='${localstatedir}/games/emacs'. Secondly, the GNU
|
||||
dnl Coding standards require that one should be able to run 'make
|
||||
dnl prefix=/some/where/else' and override the values set by
|
||||
dnl configure. This also explains the 'move-if-change' test and the
|
||||
dnl use of force in the 'epaths-force' rule in Makefile.in.
|
||||
AC_CONFIG_COMMANDS([src/epaths.h], [
|
||||
if test "${opsys}" = "mingw32"; then
|
||||
${MAKE-make} MAKEFILE_NAME=do-not-make-Makefile epaths-force-w32
|
||||
elif test "$HAVE_NS" = "yes" && test "$EN_NS_SELF_CONTAINED" = "yes"; then
|
||||
${MAKE-make} MAKEFILE_NAME=do-not-make-Makefile epaths-force-ns-self-contained
|
||||
else
|
||||
${MAKE-make} MAKEFILE_NAME=do-not-make-Makefile epaths-force
|
||||
fi || AC_MSG_ERROR(['src/epaths.h' could not be made.])
|
||||
], [GCC="$GCC" CPPFLAGS="$CPPFLAGS" opsys="$opsys" HAVE_NS="$HAVE_NS"
|
||||
EN_NS_SELF_CONTAINED="$EN_NS_SELF_CONTAINED"])
|
||||
|
||||
dnl Perhaps this would be better named doc-emacs-emacsver.texi?
|
||||
dnl See comments for etc-refcards-emacsver.tex.
|
||||
dnl Since we get a doc/emacs directory generated anyway, for the Makefile,
|
||||
dnl it is not quite the same. But we are generating in $srcdir.
|
||||
AC_CONFIG_COMMANDS([doc/emacs/emacsver.texi], [
|
||||
${MAKE-make} -s --no-print-directory -C doc/emacs doc-emacsver || \
|
||||
AC_MSG_ERROR(['doc/emacs/emacsver.texi' could not be made.])
|
||||
])
|
||||
dnl NB we have to cheat and use the ac_... version because abs_top_srcdir
|
||||
dnl is not yet set, sigh. Or we could use ../$srcdir/src/.gdbinit,
|
||||
dnl or a symlink?
|
||||
AC_CONFIG_COMMANDS([src/.gdbinit], [
|
||||
if test ! -f src/.gdbinit && test -f "$srcdir/src/.gdbinit"; then
|
||||
AS_ECHO(["source $ac_abs_top_srcdir/src/.gdbinit"]) > src/.gdbinit
|
||||
fi
|
||||
])
|
||||
|
||||
dnl If we give this the more natural name, etc/refcards/emacsver.texi,
|
||||
dnl then a directory etc/refcards is created in the build directory,
|
||||
dnl which is probably harmless, but confusing (in out-of-tree builds).
|
||||
dnl (If we were to generate etc/refcards/Makefile, this might change.)
|
||||
dnl It is really $srcdir/etc/refcards/emacsver.tex that we generate.
|
||||
AC_CONFIG_COMMANDS([etc-refcards-emacsver.tex], [
|
||||
${MAKE-make} -s MAKEFILE_NAME=do-not-make-Makefile etc-emacsver || \
|
||||
AC_MSG_ERROR(['etc/refcards/emacsver.tex' could not be made.])
|
||||
])
|
||||
dnl Perhaps this would be better named doc-emacs-emacsver.texi?
|
||||
dnl See comments for etc-refcards-emacsver.tex.
|
||||
dnl Since we get a doc/emacs directory generated anyway, for the Makefile,
|
||||
dnl it is not quite the same. But we are generating in $srcdir.
|
||||
AC_CONFIG_COMMANDS([doc/emacs/emacsver.texi], [
|
||||
${MAKE-make} -s --no-print-directory -C doc/emacs doc-emacsver || \
|
||||
AC_MSG_ERROR(['doc/emacs/emacsver.texi' could not be made.])
|
||||
])
|
||||
|
||||
dnl If we give this the more natural name, etc/refcards/emacsver.texi,
|
||||
dnl then a directory etc/refcards is created in the build directory,
|
||||
dnl which is probably harmless, but confusing (in out-of-tree builds).
|
||||
dnl (If we were to generate etc/refcards/Makefile, this might change.)
|
||||
dnl It is really $srcdir/etc/refcards/emacsver.tex that we generate.
|
||||
AC_CONFIG_COMMANDS([etc-refcards-emacsver.tex], [
|
||||
${MAKE-make} -s MAKEFILE_NAME=do-not-make-Makefile etc-emacsver || \
|
||||
AC_MSG_ERROR(['etc/refcards/emacsver.tex' could not be made.])
|
||||
])
|
||||
|
||||
if test $AUTO_DEPEND = yes; then
|
||||
for dir in $AUTODEPEND_PARENTS; do
|
||||
AS_MKDIR_P([$dir/deps])
|
||||
done
|
||||
fi
|
||||
if $gl_gnulib_enabled_dynarray || $gl_gnulib_enabled_scratch_buffer; then
|
||||
AS_MKDIR_P([lib/malloc])
|
||||
if test $AUTO_DEPEND = yes; then
|
||||
AS_MKDIR_P([lib/deps/malloc])
|
||||
for dir in $AUTODEPEND_PARENTS; do
|
||||
AS_MKDIR_P([$dir/deps])
|
||||
done
|
||||
fi
|
||||
if $gl_gnulib_enabled_dynarray || $gl_gnulib_enabled_scratch_buffer; then
|
||||
AS_MKDIR_P([lib/malloc])
|
||||
if test $AUTO_DEPEND = yes; then
|
||||
AS_MKDIR_P([lib/deps/malloc])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Make java/Makefile
|
||||
ARCH_INDEPENDENT_CONFIG_FILES([java/Makefile])
|
||||
ARCH_INDEPENDENT_CONFIG_FILES([xcompile/Makefile])
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
if test ! "$with_mailutils"; then
|
||||
|
|
24
etc/DEBUG
24
etc/DEBUG
|
@ -1094,6 +1094,30 @@ Please refer to the LLDB reference on the web for more information
|
|||
about LLDB. If you already know GDB, you will also find a mapping
|
||||
from GDB commands to corresponding LLDB commands there.
|
||||
|
||||
** Debugging Emacs on Android.
|
||||
|
||||
Attaching GDB to Emacs running inside the Android application setup
|
||||
requires a special script found in the java/ directory, and a suitable
|
||||
GDB server binary to be present on the Android device, which is
|
||||
present on the free versions of Android. Connecting to the device
|
||||
also requires the `adb' (Android Debug Bridge) utility, and telling
|
||||
the Android system to resume the Emacs process after startup requires
|
||||
the Java debugger (jdb).
|
||||
|
||||
If all three of those tools are present, simply run (from the Emacs
|
||||
source directory):
|
||||
|
||||
../java/debug.sh -- [any extra arguments you wish to pass to gdb]
|
||||
|
||||
After which, upon waiting a while, the GDB prompt will show up.
|
||||
|
||||
If Emacs crashes and "JNI ERROR" shows up in the Android system log,
|
||||
then placing a breakpoint on:
|
||||
|
||||
break art::JavaVMExt::JniAbort
|
||||
|
||||
will let you find the source of the crash.
|
||||
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
|
|
54
java/AndroidManifest.xml
Normal file
54
java/AndroidManifest.xml
Normal file
|
@ -0,0 +1,54 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.gnu.emacs" android:installLocation="auto">
|
||||
|
||||
<!-- Paste in every permission in existence so Emacs can do
|
||||
anything. -->
|
||||
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.SET_WALLPAPER" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.SEND_SMS" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_MMS"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SMS"/>
|
||||
<uses-permission android:name="android.permission.READ_SMS"/>
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.TRANSMIT_IR" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
|
||||
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
<uses-sdk android:minSdkVersion="7"
|
||||
android:targetSdkVersion="28"/>
|
||||
|
||||
<application android:name="org.gnu.emacs.EmacsApplication"
|
||||
android:label="GNU Emacs"
|
||||
android:hardwareAccelerated="true"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@android:style/Theme"
|
||||
android:debuggable="true"
|
||||
android:extractNativeLibs="true">
|
||||
<activity android:name="org.gnu.emacs.EmacsActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service android:name="org.gnu.emacs.EmacsService"
|
||||
android:directBootAware="false"
|
||||
android:enabled="true"
|
||||
android:exported="false"
|
||||
android:label="GNU Emacs service"/>
|
||||
</application>
|
||||
</manifest>
|
150
java/Makefile.in
Normal file
150
java/Makefile.in
Normal file
|
@ -0,0 +1,150 @@
|
|||
### @configure_input@
|
||||
|
||||
# Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU Emacs.
|
||||
|
||||
# GNU Emacs is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# GNU Emacs is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
-include ${top_builddir}/src/verbose.mk
|
||||
|
||||
SHELL = @SHELL@
|
||||
JAVAC = @JAVAC@
|
||||
AAPT = @AAPT@
|
||||
DX = @DX@
|
||||
ZIPALIGN = @ZIPALIGN@
|
||||
JARSIGNER = @JARSIGNER@
|
||||
ANDROID_JAR = @ANDROID_JAR@
|
||||
ANDROID_ABI = @ANDROID_ABI@
|
||||
|
||||
WARN_JAVAFLAGS = -Xlint:deprecation
|
||||
JAVAFLAGS = -classpath "$(ANDROID_JAR):." -target 1.7 -source 1.7 \
|
||||
$(WARN_JAVAFLAGS)
|
||||
|
||||
SIGN_EMACS = -keystore emacs.keystore -storepass emacs1
|
||||
|
||||
JAVA_FILES = $(shell find . -type f -name *.java)
|
||||
CLASS_FILES = $(foreach file,$(JAVA_FILES),$(basename $(file)).class)
|
||||
|
||||
# How this stuff works.
|
||||
|
||||
# emacs.apk depends on emacs.apk-in, which is simply a ZIP archive
|
||||
# containing the following files:
|
||||
# lib/$(ANDROID_ABI)/libemacs.so
|
||||
# lib/$(ANDROID_ABI)/libandroid-emacs.so
|
||||
# lib/$(ANDROID_ABI)/libctags.so
|
||||
# lib/$(ANDROID_ABI)/libhexl.so
|
||||
# lib/$(ANDROID_ABI)/libmovemail.so
|
||||
# lib/$(ANDROID_ABI)/librcs2log.so
|
||||
# lib/$(ANDROID_ABI)/libebrowse.so
|
||||
# assets/info/
|
||||
# assets/etc/
|
||||
# assets/lisp/
|
||||
|
||||
.PHONY: emacs.apk-in all
|
||||
all: emacs.apk
|
||||
|
||||
# Binaries to cross-compile.
|
||||
CROSS_BINS = ../xcompile/src/android-emacs ../xcompile/lib-src/ctags \
|
||||
../xcompile/lib-src/hexl ../xcompile/lib-src/movemail \
|
||||
../xcompile/lib-src/ebrowse
|
||||
|
||||
# Libraries to cross-compile.
|
||||
CROSS_LIBS = ../xcompile/src/libemacs.so
|
||||
|
||||
.PHONY: $(CROSS_BINS) $(CROSS_LIBS)
|
||||
|
||||
../xcompile/src/android-emacs ../xcompile/src/libemacs.so:
|
||||
make -C ../xcompile src/$(notdir $@)
|
||||
|
||||
../xcompile/lib-src/hexl ../xcompile/lib-src/movemail \
|
||||
../xcompile/lib-src/ctags ../xcompile/lib-src/ebrowse &:
|
||||
make -C ../xcompile lib-src/$(notdir $@)
|
||||
|
||||
emacs.apk-in: $(CROSS_BINS) $(CROSS_LIBS) AndroidManifest.xml
|
||||
# Make the working directory for this stuff
|
||||
rm -rf install_temp
|
||||
mkdir -p install_temp/lib/$(ANDROID_ABI)
|
||||
mkdir -p install_temp/assets/etc
|
||||
mkdir -p install_temp/assets/lisp
|
||||
mkdir -p install_temp/assets/info
|
||||
# Install architecture independents to assets/etc and assets/lisp
|
||||
cp -r $(top_builddir)/lisp install_temp/assets
|
||||
cp -r $(top_builddir)/etc install_temp/assets
|
||||
# Remove undesirable files from those directories.
|
||||
for subdir in `find install_temp -type d -print`; do \
|
||||
chmod a+rx $${subdir} ; \
|
||||
rm -rf $${subdir}/.gitignore ; \
|
||||
rm -rf $${subdir}/.DS_Store ; \
|
||||
rm -rf $${subdir}/#* ; \
|
||||
rm -rf $${subdir}/.#* ; \
|
||||
rm -rf $${subdir}/*~ ; \
|
||||
rm -rf $${subdir}/*.orig ; \
|
||||
rm -rf $${subdir}/ChangeLog* ; \
|
||||
rm -rf $${subdir}/[mM]akefile*[.-]in ; \
|
||||
rm -rf $${subdir}/Makefile; \
|
||||
done
|
||||
# Install architecture dependents to lib/$(ANDROID_ABI). This
|
||||
# perculiar naming scheme is required to make Android preserve these
|
||||
# binaries upon installation.
|
||||
for file in $(CROSS_BINS); do \
|
||||
if [ -x $$file ]; then \
|
||||
filename=`basename $$file`; \
|
||||
cp -f $$file install_temp/lib/$(ANDROID_ABI)/lib$${filename}.so; \
|
||||
fi \
|
||||
done
|
||||
for file in $(CROSS_LIBS); do \
|
||||
if [ -x $$file ]; then \
|
||||
cp -f $$file install_temp/lib/$(ANDROID_ABI); \
|
||||
fi \
|
||||
done
|
||||
# Package everything.
|
||||
$(AAPT) package -I "$(ANDROID_JAR)" -F $@ -f -M AndroidManifest.xml
|
||||
pushd install_temp; $(AAPT) add ../$@ `find lib -type f`; popd
|
||||
pushd install_temp; $(AAPT) add ../$@ `find assets -type f`; popd
|
||||
rm -rf install_temp
|
||||
|
||||
.SUFFIXES: .java .class
|
||||
.java.class &:
|
||||
$(AM_V_JAVAC) $(JAVAC) $(JAVAFLAGS) $<
|
||||
|
||||
# N.B. that find must be called all over again in case javac generated
|
||||
# nested classes.
|
||||
|
||||
classes.dex: $(CLASS_FILES)
|
||||
$(AM_V_DX) $(DX) --classpath $(ANDROID_JAR) \
|
||||
$(subst $$,\$$,$(shell find . -type f -name *.class))
|
||||
|
||||
# When emacs.keystore expires, regenerate it with:
|
||||
#
|
||||
# keytool -genkey -v -keystore emacs.keystore -alias "Emacs keystore" \
|
||||
# -keyalg RSA -sigalg SHA1withRSA -keysize 2048 -validity 100000
|
||||
|
||||
.PHONY: clean maintainer-clean
|
||||
|
||||
emacs.apk: classes.dex emacs.apk-in emacs.keystore
|
||||
cp -f emacs.apk-in $@.unaligned
|
||||
$(AAPT) add $@.unaligned classes.dex
|
||||
$(JARSIGNER) $(SIGN_EMACS) $@.unaligned "Emacs keystore"
|
||||
$(ZIPALIGN) -f 4 $@.unaligned $@
|
||||
rm -f $@.unaligned
|
||||
|
||||
clean:
|
||||
rm -f emacs.apk emacs.apk-in *.dex *.unaligned *.class
|
||||
rm -rf install-temp
|
||||
find . -name '*.class' -delete
|
||||
|
||||
maintainer-clean: clean
|
6
java/README
Normal file
6
java/README
Normal file
|
@ -0,0 +1,6 @@
|
|||
This directory holds the Java sources of the port of GNU Emacs to
|
||||
Android-like systems.
|
||||
|
||||
Please keep the Java code indented with tabs and formatted according
|
||||
to the rules for C code in the GNU coding standards. Always use
|
||||
C-style comments.
|
242
java/debug.sh
Executable file
242
java/debug.sh
Executable file
|
@ -0,0 +1,242 @@
|
|||
#!/bin/bash
|
||||
### Run Emacs under GDB or JDB on Android.
|
||||
|
||||
## Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
## This file is part of GNU Emacs.
|
||||
|
||||
## GNU Emacs is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
|
||||
## GNU Emacs is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
set -m
|
||||
oldpwd=`pwd`
|
||||
cd `dirname $0`
|
||||
|
||||
devices=`adb devices | grep device | awk -- '/device\y/ { print $1 }' -`
|
||||
device=
|
||||
progname=$0
|
||||
package=org.gnu.emacs
|
||||
activity=org.gnu.emacs.EmacsActivity
|
||||
gdb_port=5039
|
||||
jdb_port=64013
|
||||
jdb=no
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
## This option specifies the serial number of a device to use.
|
||||
"--device" )
|
||||
device="$2"
|
||||
if [ -z device ]; then
|
||||
echo "You must specify an argument to --device"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
"--help" )
|
||||
echo "Usage: $progname [options] -- [gdb options]"
|
||||
echo ""
|
||||
echo " --device DEVICE run Emacs on the specified device"
|
||||
echo " --port PORT run the GDB server on a specific port"
|
||||
echo " --jdb-port PORT run the JDB server on a specific port"
|
||||
echo " --jdb run JDB instead of GDB"
|
||||
echo " --help print this message"
|
||||
echo ""
|
||||
echo "Available devices:"
|
||||
for device in $devices; do
|
||||
echo " " $device
|
||||
done
|
||||
echo ""
|
||||
exit 0
|
||||
;;
|
||||
"--jdb" )
|
||||
jdb=yes
|
||||
;;
|
||||
"--port" )
|
||||
gdb_port=$1
|
||||
;;
|
||||
"--" )
|
||||
shift
|
||||
gdbargs=$@
|
||||
break;
|
||||
;;
|
||||
* )
|
||||
echo "$progname: Unrecognized argument $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ -z $devices ]; then
|
||||
echo "No devices are available."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z $device ]; then
|
||||
device=$devices
|
||||
fi
|
||||
|
||||
if [ `wc -w <<< "$devices"` -gt 1 ] && [ -z device ]; then
|
||||
echo "Multiple devices are available. Please pick one using"
|
||||
echo "--device and try again."
|
||||
fi
|
||||
|
||||
echo "Looking for $package on device $device"
|
||||
|
||||
# Find the application data directory
|
||||
app_data_dir=`adb -s $device shell run-as $package sh -c 'pwd 2> /dev/null'`
|
||||
|
||||
if [ -z $app_data_dir ]; then
|
||||
echo "The data directory for the package $package was not found."
|
||||
echo "Is it installed?"
|
||||
fi
|
||||
|
||||
echo "Found application data directory at $app_data_dir..."
|
||||
|
||||
# Find which PIDs are associated with org.gnu.emacs
|
||||
package_uid=`adb -s $device shell run-as $package id -u`
|
||||
|
||||
if [ -z $package_uid ]; then
|
||||
echo "Failed to obtain UID of packages named $package"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# First, run ps -u $package_uid -o PID,CMD to fetch the list of
|
||||
# process IDs.
|
||||
package_pids=`adb -s $device shell run-as $package ps -u $package_uid -o PID,CMD`
|
||||
|
||||
# Next, remove lines matching "ps" itself.
|
||||
package_pids=`awk -- '{
|
||||
if (!match ($0, /(PID|ps)/))
|
||||
print $1
|
||||
}' <<< $package_pids`
|
||||
|
||||
# Finally, kill each existing process.
|
||||
for pid in $package_pids; do
|
||||
echo "Killing existing process $pid..."
|
||||
adb -s $device shell run-as $package kill -9 $pid &> /dev/null
|
||||
done
|
||||
|
||||
# Now run the main activity. This must be done as the adb user and
|
||||
# not as the package user.
|
||||
echo "Starting activity $activity and attaching debugger"
|
||||
|
||||
# Exit if the activity could not be started.
|
||||
adb -s $device shell am start -D "$package/$activity"
|
||||
if [ ! $? ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# Now look for processes matching the package again.
|
||||
package_pids=`adb -s $device shell run-as $package ps -u $package_uid -o PID,CMD`
|
||||
|
||||
# Next, remove lines matching "ps" itself.
|
||||
package_pids=`awk -- '{
|
||||
if (!match ($0, /(PID|ps)/))
|
||||
print $1
|
||||
}' <<< $package_pids`
|
||||
|
||||
pid=$package_pids
|
||||
num_pids=`wc -w <<< "$package_pids"`
|
||||
|
||||
if [ $num_pids -gt 1 ]; then
|
||||
echo "More than one process was started:"
|
||||
echo ""
|
||||
adb -s $device shell run-as $package ps -u $package_uid | awk -- '{
|
||||
if (!match ($0, /ps/))
|
||||
print $0
|
||||
}'
|
||||
echo ""
|
||||
printf "Which one do you want to attach to? "
|
||||
read pid
|
||||
elif [ -z $package_pids ]; then
|
||||
echo "No processes were found to attach to."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Start JDB to make the wait dialog disappear.
|
||||
echo "Attaching JDB to unblock the application."
|
||||
adb -s $device forward --remove-all
|
||||
adb -s $device forward "tcp:$jdb_port" "jdwp:$pid"
|
||||
|
||||
if [ ! $? ]; then
|
||||
echo "Failed to forward jdwp:$pid to $jdb_port!"
|
||||
echo "Perhaps you need to specify a different port with --port?"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
jdb_command="jdb -connect \
|
||||
com.sun.jdi.SocketAttach:hostname=localhost,port=$jdb_port"
|
||||
|
||||
if [ $jdb = "yes" ]; then
|
||||
# Just start JDB and then exit
|
||||
$jdb_command
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec 4<> /tmp/file-descriptor-stamp
|
||||
|
||||
# Now run JDB with IO redirected to file descriptor 4 in a subprocess.
|
||||
$jdb_command <&4 >&4 &
|
||||
|
||||
character=
|
||||
# Next, wait until the prompt is found.
|
||||
while read -n1 -u 4 character; do
|
||||
if [ "$character" = ">" ]; then
|
||||
echo "JDB attached successfully"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
|
||||
# Now start gdbserver on the device asynchronously.
|
||||
|
||||
echo "Attaching gdbserver to $pid on $device..."
|
||||
exec 5<> /tmp/file-descriptor-stamp
|
||||
adb -s $device shell run-as $package /system/bin/gdbserver --once \
|
||||
"+debug.$package_uid.socket" --attach $pid >&5 &
|
||||
|
||||
# Wait until gdbserver successfully runs.
|
||||
line=
|
||||
while read -u 5 line; do
|
||||
case "$line" in
|
||||
*Attached* )
|
||||
break;
|
||||
;;
|
||||
*error* | *Error* | failed )
|
||||
echo $line
|
||||
exit 1
|
||||
;;
|
||||
* )
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Send EOF to JDB to make it go away. This will also cause Android to
|
||||
# allow Emacs to continue executing.
|
||||
echo "Making JDB go away..."
|
||||
echo "exit" >&4
|
||||
read -u 4 line
|
||||
echo "JDB has gone away with $line"
|
||||
|
||||
# Forward the gdb server port here.
|
||||
adb -s $device forward "tcp:$gdb_port" \
|
||||
"localfilesystem:$app_data_dir/debug.$package_uid.socket"
|
||||
if [ ! $? ]; then
|
||||
echo "Failed to forward $app_data_dir/debug.$package_uid.socket"
|
||||
echo "to $gdb_port! Perhaps you need to specify a different port"
|
||||
echo "with --port?"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# Finally, start gdb with any extra arguments needed.
|
||||
cd "$oldpwd"
|
||||
gdb --eval-command "" --eval-command "target remote localhost:$gdb_port" $gdbargs
|
BIN
java/emacs.keystore
Normal file
BIN
java/emacs.keystore
Normal file
Binary file not shown.
146
java/org/gnu/emacs/EmacsActivity.java
Normal file
146
java/org/gnu/emacs/EmacsActivity.java
Normal file
|
@ -0,0 +1,146 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import java.lang.IllegalStateException;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.FrameLayout.LayoutParams;
|
||||
|
||||
public class EmacsActivity extends Activity
|
||||
{
|
||||
public static final String TAG = "EmacsActivity";
|
||||
|
||||
/* List of all activities that do not have an associated
|
||||
EmacsWindow. */
|
||||
public static List<EmacsActivity> availableActivities;
|
||||
|
||||
/* The currently attached EmacsWindow, or null if none. */
|
||||
private EmacsWindow window;
|
||||
|
||||
/* The frame layout associated with the activity. */
|
||||
private FrameLayout layout;
|
||||
|
||||
static
|
||||
{
|
||||
/* Set up the list of available activities. */
|
||||
availableActivities = new ArrayList<EmacsActivity> ();
|
||||
};
|
||||
|
||||
public void
|
||||
attachChild (EmacsWindow child)
|
||||
{
|
||||
if (window != null)
|
||||
throw new IllegalStateException ("trying to attach window when one"
|
||||
+ " already exists");
|
||||
|
||||
/* Record and attach the view. */
|
||||
window = child;
|
||||
layout.addView (window.view);
|
||||
|
||||
/* Remove the objects from the lists of what is available. */
|
||||
EmacsService.availableChildren.remove (child);
|
||||
availableActivities.remove (this);
|
||||
|
||||
/* Now set child->activity. */
|
||||
child.setActivity (this);
|
||||
}
|
||||
|
||||
/* Make this activity available for future windows to attach
|
||||
again. */
|
||||
|
||||
public void
|
||||
makeAvailable ()
|
||||
{
|
||||
window = null;
|
||||
|
||||
for (EmacsWindow iterWindow
|
||||
: EmacsService.availableChildren)
|
||||
{
|
||||
synchronized (iterWindow)
|
||||
{
|
||||
if (!iterWindow.isDestroyed ())
|
||||
attachChild (iterWindow);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
availableActivities.add (this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
onCreate (Bundle savedInstanceState)
|
||||
{
|
||||
FrameLayout.LayoutParams params;
|
||||
|
||||
params = new FrameLayout.LayoutParams (LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.MATCH_PARENT);
|
||||
|
||||
/* Make the frame layout. */
|
||||
layout = new FrameLayout (this);
|
||||
layout.setLayoutParams (params);
|
||||
|
||||
/* Set it as the content view. */
|
||||
setContentView (layout);
|
||||
|
||||
/* Make the activity available before starting the
|
||||
service. */
|
||||
makeAvailable ();
|
||||
|
||||
if (EmacsService.SERVICE == null)
|
||||
/* Start the Emacs service now. */
|
||||
startService (new Intent (this, EmacsService.class));
|
||||
|
||||
super.onCreate (savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
onStop ()
|
||||
{
|
||||
/* The activity is no longer visible. If there is a window
|
||||
attached, detach it. */
|
||||
|
||||
if (window != null)
|
||||
{
|
||||
layout.removeView (window.view);
|
||||
|
||||
/* Notice that the window is already available too. But do
|
||||
not call noticeAvailableChild; that might assign it to some
|
||||
other activity, which behaves badly. */
|
||||
EmacsService.availableChildren.add (window);
|
||||
window = null;
|
||||
}
|
||||
|
||||
/* Finally, remove this activity from the list of available
|
||||
activities. */
|
||||
availableActivities.remove (this);
|
||||
super.onStop ();
|
||||
}
|
||||
};
|
27
java/org/gnu/emacs/EmacsApplication.java
Normal file
27
java/org/gnu/emacs/EmacsApplication.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
public class EmacsApplication extends Application
|
||||
{
|
||||
/* This class currently does nothing. */
|
||||
};
|
131
java/org/gnu/emacs/EmacsCopyArea.java
Normal file
131
java/org/gnu/emacs/EmacsCopyArea.java
Normal file
|
@ -0,0 +1,131 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Xfermode;
|
||||
|
||||
public class EmacsCopyArea implements EmacsPaintReq
|
||||
{
|
||||
private int src_x, src_y, dest_x, dest_y, width, height;
|
||||
private EmacsDrawable destination, source;
|
||||
private EmacsGC immutableGC;
|
||||
private static Xfermode xorAlu, srcInAlu;
|
||||
|
||||
static
|
||||
{
|
||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
||||
};
|
||||
|
||||
public
|
||||
EmacsCopyArea (EmacsDrawable destination, EmacsDrawable source,
|
||||
int src_x, int src_y, int width, int height,
|
||||
int dest_x, int dest_y, EmacsGC immutableGC)
|
||||
{
|
||||
this.destination = destination;
|
||||
this.source = source;
|
||||
this.src_x = src_x;
|
||||
this.src_y = src_y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.dest_x = dest_x;
|
||||
this.dest_y = dest_y;
|
||||
this.immutableGC = immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect
|
||||
getRect ()
|
||||
{
|
||||
return new Rect (dest_x, dest_y, dest_x + width,
|
||||
dest_y + height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsDrawable
|
||||
getDrawable ()
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsGC
|
||||
getGC ()
|
||||
{
|
||||
return immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC)
|
||||
{
|
||||
int alu;
|
||||
Bitmap bitmap;
|
||||
Paint maskPaint;
|
||||
Canvas maskCanvas;
|
||||
Bitmap maskBitmap;
|
||||
Rect rect, srcRect;
|
||||
|
||||
/* TODO implement stippling. */
|
||||
if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
return;
|
||||
|
||||
alu = immutableGC.function;
|
||||
rect = getRect ();
|
||||
bitmap = source.getBitmap ();
|
||||
|
||||
if (alu == EmacsGC.GC_COPY)
|
||||
paint.setXfermode (null);
|
||||
else
|
||||
paint.setXfermode (xorAlu);
|
||||
|
||||
if (immutableGC.clip_mask == null)
|
||||
canvas.drawBitmap (bitmap, new Rect (src_x, src_y,
|
||||
src_x + width,
|
||||
src_y + height),
|
||||
rect, paint);
|
||||
else
|
||||
{
|
||||
maskPaint = new Paint ();
|
||||
srcRect = new Rect (0, 0, rect.width (),
|
||||
rect.height ());
|
||||
maskBitmap
|
||||
= immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888,
|
||||
true);
|
||||
|
||||
if (maskBitmap == null)
|
||||
return;
|
||||
|
||||
maskPaint.setXfermode (srcInAlu);
|
||||
maskCanvas = new Canvas (maskBitmap);
|
||||
maskCanvas.drawBitmap (bitmap, new Rect (src_x, src_y,
|
||||
src_x + width,
|
||||
src_y + height),
|
||||
srcRect, maskPaint);
|
||||
canvas.drawBitmap (maskBitmap, srcRect, rect, paint);
|
||||
}
|
||||
}
|
||||
}
|
137
java/org/gnu/emacs/EmacsDrawLine.java
Normal file
137
java/org/gnu/emacs/EmacsDrawLine.java
Normal file
|
@ -0,0 +1,137 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import java.lang.Math;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Xfermode;
|
||||
|
||||
public class EmacsDrawLine implements EmacsPaintReq
|
||||
{
|
||||
private int x, y, x2, y2;
|
||||
private EmacsDrawable drawable;
|
||||
private EmacsGC immutableGC;
|
||||
private static Xfermode xorAlu, srcInAlu;
|
||||
|
||||
static
|
||||
{
|
||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
||||
};
|
||||
|
||||
public
|
||||
EmacsDrawLine (EmacsDrawable drawable, int x, int y,
|
||||
int x2, int y2, EmacsGC immutableGC)
|
||||
{
|
||||
this.drawable = drawable;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.x2 = x2;
|
||||
this.y2 = y2;
|
||||
this.immutableGC = immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect
|
||||
getRect ()
|
||||
{
|
||||
return new Rect (Math.min (x, x2 + 1),
|
||||
Math.min (y, y2 + 1),
|
||||
Math.max (x2 + 1, x),
|
||||
Math.max (y2 + 1, y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsDrawable
|
||||
getDrawable ()
|
||||
{
|
||||
return drawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsGC
|
||||
getGC ()
|
||||
{
|
||||
return immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC)
|
||||
{
|
||||
int alu;
|
||||
Paint maskPaint;
|
||||
Canvas maskCanvas;
|
||||
Bitmap maskBitmap;
|
||||
Rect rect, srcRect;
|
||||
int width, height;
|
||||
|
||||
/* TODO implement stippling. */
|
||||
if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
return;
|
||||
|
||||
alu = immutableGC.function;
|
||||
rect = getRect ();
|
||||
width = rect.width ();
|
||||
height = rect.height ();
|
||||
|
||||
paint.setStyle (Paint.Style.STROKE);
|
||||
|
||||
if (alu == EmacsGC.GC_COPY)
|
||||
paint.setXfermode (null);
|
||||
else
|
||||
paint.setXfermode (xorAlu);
|
||||
|
||||
if (immutableGC.clip_mask == null)
|
||||
{
|
||||
paint.setColor (immutableGC.foreground | 0xff000000);
|
||||
canvas.drawLine ((float) x, (float) y,
|
||||
(float) x2, (float) y2,
|
||||
paint);
|
||||
}
|
||||
else
|
||||
{
|
||||
maskPaint = new Paint ();
|
||||
maskBitmap
|
||||
= immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888,
|
||||
true);
|
||||
|
||||
if (maskBitmap == null)
|
||||
return;
|
||||
|
||||
maskPaint.setXfermode (srcInAlu);
|
||||
maskPaint.setColor (immutableGC.foreground | 0xff000000);
|
||||
maskCanvas = new Canvas (maskBitmap);
|
||||
srcRect = new Rect (0, 0, maskBitmap.getWidth (),
|
||||
maskBitmap.getHeight ());
|
||||
maskCanvas.drawLine (0.0f, 0.0f, (float) Math.abs (x - x2),
|
||||
(float) Math.abs (y - y2), maskPaint);
|
||||
canvas.drawBitmap (maskBitmap, srcRect, rect, paint);
|
||||
}
|
||||
|
||||
paint.setXfermode (null);
|
||||
}
|
||||
}
|
30
java/org/gnu/emacs/EmacsDrawPoint.java
Normal file
30
java/org/gnu/emacs/EmacsDrawPoint.java
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
public class EmacsDrawPoint extends EmacsDrawRectangle
|
||||
{
|
||||
public
|
||||
EmacsDrawPoint (EmacsDrawable drawable, int x, int y,
|
||||
EmacsGC immutableGC)
|
||||
{
|
||||
super (drawable, x, y, 1, 1, immutableGC);
|
||||
}
|
||||
}
|
127
java/org/gnu/emacs/EmacsDrawRectangle.java
Normal file
127
java/org/gnu/emacs/EmacsDrawRectangle.java
Normal file
|
@ -0,0 +1,127 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Xfermode;
|
||||
|
||||
public class EmacsDrawRectangle implements EmacsPaintReq
|
||||
{
|
||||
private int x, y, width, height;
|
||||
private EmacsDrawable drawable;
|
||||
private EmacsGC immutableGC;
|
||||
private static Xfermode xorAlu, srcInAlu;
|
||||
|
||||
static
|
||||
{
|
||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
||||
};
|
||||
|
||||
public
|
||||
EmacsDrawRectangle (EmacsDrawable drawable, int x, int y,
|
||||
int width, int height,
|
||||
EmacsGC immutableGC)
|
||||
{
|
||||
this.drawable = drawable;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.immutableGC = immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect
|
||||
getRect ()
|
||||
{
|
||||
return new Rect (x, y, x + width, y + height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsDrawable
|
||||
getDrawable ()
|
||||
{
|
||||
return drawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsGC
|
||||
getGC ()
|
||||
{
|
||||
return immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC)
|
||||
{
|
||||
int alu;
|
||||
Paint maskPaint;
|
||||
Canvas maskCanvas;
|
||||
Bitmap maskBitmap;
|
||||
Rect rect, srcRect;
|
||||
|
||||
/* TODO implement stippling. */
|
||||
if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
return;
|
||||
|
||||
alu = immutableGC.function;
|
||||
rect = getRect ();
|
||||
|
||||
paint.setStyle (Paint.Style.STROKE);
|
||||
|
||||
if (alu == EmacsGC.GC_COPY)
|
||||
paint.setXfermode (null);
|
||||
else
|
||||
paint.setXfermode (xorAlu);
|
||||
|
||||
if (immutableGC.clip_mask == null)
|
||||
{
|
||||
paint.setColor (immutableGC.foreground | 0xff000000);
|
||||
canvas.drawRect (rect, paint);
|
||||
}
|
||||
else
|
||||
{
|
||||
maskPaint = new Paint ();
|
||||
maskBitmap
|
||||
= immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888,
|
||||
true);
|
||||
|
||||
if (maskBitmap == null)
|
||||
return;
|
||||
|
||||
maskPaint.setXfermode (srcInAlu);
|
||||
maskPaint.setColor (immutableGC.foreground | 0xff000000);
|
||||
maskCanvas = new Canvas (maskBitmap);
|
||||
srcRect = new Rect (0, 0, maskBitmap.getWidth (),
|
||||
maskBitmap.getHeight ());
|
||||
maskCanvas.drawRect (srcRect, maskPaint);
|
||||
canvas.drawBitmap (maskBitmap, srcRect, rect, paint);
|
||||
}
|
||||
|
||||
paint.setXfermode (null);
|
||||
}
|
||||
}
|
33
java/org/gnu/emacs/EmacsDrawable.java
Normal file
33
java/org/gnu/emacs/EmacsDrawable.java
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
|
||||
public interface EmacsDrawable
|
||||
{
|
||||
public Canvas lockCanvas ();
|
||||
public void unlockCanvas ();
|
||||
public void damageRect (Rect damageRect);
|
||||
public Bitmap getBitmap ();
|
||||
public boolean isDestroyed ();
|
||||
};
|
150
java/org/gnu/emacs/EmacsFillPolygon.java
Normal file
150
java/org/gnu/emacs/EmacsFillPolygon.java
Normal file
|
@ -0,0 +1,150 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import java.lang.Math;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Xfermode;
|
||||
|
||||
public class EmacsFillPolygon implements EmacsPaintReq
|
||||
{
|
||||
private EmacsDrawable drawable;
|
||||
private EmacsGC immutableGC;
|
||||
private Path path;
|
||||
|
||||
private static Xfermode xorAlu, srcInAlu;
|
||||
|
||||
static
|
||||
{
|
||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
||||
};
|
||||
|
||||
public
|
||||
EmacsFillPolygon (EmacsDrawable drawable, Point points[],
|
||||
EmacsGC immutableGC)
|
||||
{
|
||||
int i;
|
||||
|
||||
this.drawable = drawable;
|
||||
this.immutableGC = immutableGC;
|
||||
|
||||
/* Build the path from the given array of points. */
|
||||
path = new Path ();
|
||||
|
||||
if (points.length >= 1)
|
||||
{
|
||||
path.moveTo (points[0].x, points[0].y);
|
||||
|
||||
for (i = 1; i < points.length; ++i)
|
||||
path.lineTo (points[i].x, points[i].y);
|
||||
|
||||
path.close ();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect
|
||||
getRect ()
|
||||
{
|
||||
RectF rect;
|
||||
|
||||
rect = new RectF (0, 0, 0, 0);
|
||||
path.computeBounds (rect, true);
|
||||
|
||||
return new Rect ((int) Math.floor (rect.left),
|
||||
(int) Math.floor (rect.top),
|
||||
(int) Math.ceil (rect.right),
|
||||
(int) Math.ceil (rect.bottom));
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsDrawable
|
||||
getDrawable ()
|
||||
{
|
||||
return drawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsGC
|
||||
getGC ()
|
||||
{
|
||||
return immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC)
|
||||
{
|
||||
int alu;
|
||||
Paint maskPaint;
|
||||
Canvas maskCanvas;
|
||||
Bitmap maskBitmap;
|
||||
Rect rect;
|
||||
|
||||
/* TODO implement stippling. */
|
||||
if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
return;
|
||||
|
||||
alu = immutableGC.function;
|
||||
rect = getRect ();
|
||||
|
||||
if (alu == EmacsGC.GC_COPY)
|
||||
paint.setXfermode (null);
|
||||
else
|
||||
paint.setXfermode (xorAlu);
|
||||
|
||||
paint.setStyle (Paint.Style.FILL);
|
||||
|
||||
if (immutableGC.clip_mask == null)
|
||||
{
|
||||
paint.setColor (immutableGC.foreground | 0xff000000);
|
||||
canvas.drawPath (path, paint);
|
||||
}
|
||||
else
|
||||
{
|
||||
maskPaint = new Paint ();
|
||||
maskBitmap = immutableGC.clip_mask.bitmap;
|
||||
maskBitmap = maskBitmap.copy (Bitmap.Config.ARGB_8888,
|
||||
true);
|
||||
|
||||
if (maskBitmap == null)
|
||||
return;
|
||||
|
||||
maskPaint.setXfermode (srcInAlu);
|
||||
maskPaint.setColor (immutableGC.foreground | 0xff000000);
|
||||
maskCanvas = new Canvas (maskBitmap);
|
||||
path.offset (-rect.left, -rect.top, null);
|
||||
maskCanvas.drawPath (path, maskPaint);
|
||||
canvas.drawBitmap (maskBitmap, new Rect (0, 0, rect.width (),
|
||||
rect.height ()),
|
||||
rect, paint);
|
||||
}
|
||||
}
|
||||
}
|
129
java/org/gnu/emacs/EmacsFillRectangle.java
Normal file
129
java/org/gnu/emacs/EmacsFillRectangle.java
Normal file
|
@ -0,0 +1,129 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Xfermode;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class EmacsFillRectangle implements EmacsPaintReq
|
||||
{
|
||||
private int x, y, width, height;
|
||||
private EmacsDrawable drawable;
|
||||
private EmacsGC immutableGC;
|
||||
private static Xfermode xorAlu, srcInAlu;
|
||||
|
||||
static
|
||||
{
|
||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
||||
};
|
||||
|
||||
public
|
||||
EmacsFillRectangle (EmacsDrawable drawable, int x, int y,
|
||||
int width, int height,
|
||||
EmacsGC immutableGC)
|
||||
{
|
||||
this.drawable = drawable;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.immutableGC = immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect
|
||||
getRect ()
|
||||
{
|
||||
return new Rect (x, y, x + width, y + height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsDrawable
|
||||
getDrawable ()
|
||||
{
|
||||
return drawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsGC
|
||||
getGC ()
|
||||
{
|
||||
return immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC)
|
||||
{
|
||||
int alu;
|
||||
Paint maskPaint;
|
||||
Canvas maskCanvas;
|
||||
Bitmap maskBitmap;
|
||||
Rect rect, srcRect;
|
||||
|
||||
/* TODO implement stippling. */
|
||||
if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
return;
|
||||
|
||||
alu = immutableGC.function;
|
||||
rect = getRect ();
|
||||
|
||||
paint.setStyle (Paint.Style.FILL);
|
||||
|
||||
if (alu == EmacsGC.GC_COPY)
|
||||
paint.setXfermode (null);
|
||||
else
|
||||
paint.setXfermode (xorAlu);
|
||||
|
||||
if (immutableGC.clip_mask == null)
|
||||
{
|
||||
paint.setColor (immutableGC.foreground | 0xff000000);
|
||||
canvas.drawRect (rect, paint);
|
||||
}
|
||||
else
|
||||
{
|
||||
maskPaint = new Paint ();
|
||||
maskBitmap
|
||||
= immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888,
|
||||
true);
|
||||
|
||||
if (maskBitmap == null)
|
||||
return;
|
||||
|
||||
maskPaint.setXfermode (srcInAlu);
|
||||
maskPaint.setColor (immutableGC.foreground | 0xff000000);
|
||||
maskCanvas = new Canvas (maskBitmap);
|
||||
srcRect = new Rect (0, 0, maskBitmap.getWidth (),
|
||||
maskBitmap.getHeight ());
|
||||
maskCanvas.drawRect (srcRect, maskPaint);
|
||||
canvas.drawBitmap (maskBitmap, srcRect, rect, paint);
|
||||
}
|
||||
|
||||
paint.setXfermode (null);
|
||||
}
|
||||
}
|
150
java/org/gnu/emacs/EmacsFontDriver.java
Normal file
150
java/org/gnu/emacs/EmacsFontDriver.java
Normal file
|
@ -0,0 +1,150 @@
|
|||
/* Font backend for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class EmacsFontDriver
|
||||
{
|
||||
/* Font weights. */
|
||||
public static final int THIN = 0;
|
||||
public static final int ULTRA_LIGHT = 40;
|
||||
public static final int LIGHT = 50;
|
||||
public static final int SEMI_LIGHT = 55;
|
||||
public static final int REGULAR = 80;
|
||||
public static final int MEDIUM = 100;
|
||||
public static final int SEMI_BOLD = 180;
|
||||
public static final int BOLD = 200;
|
||||
public static final int EXTRA_BOLD = 205;
|
||||
public static final int BLACK = 210;
|
||||
public static final int ULTRA_HEAVY = 250;
|
||||
|
||||
/* Font slants. */
|
||||
public static final int REVERSE_OBLIQUE = 0;
|
||||
public static final int REVERSE_ITALIC = 10;
|
||||
public static final int NORMAL = 100;
|
||||
public static final int ITALIC = 200;
|
||||
public static final int OBLIQUE = 210;
|
||||
|
||||
/* Font widths. */
|
||||
public static final int ULTRA_CONDENSED = 50;
|
||||
public static final int EXTRA_CONDENSED = 63;
|
||||
public static final int CONDENSED = 75;
|
||||
public static final int SEMI_CONDENSED = 87;
|
||||
public static final int UNSPECIFIED = 100;
|
||||
public static final int SEMI_EXPANDED = 113;
|
||||
public static final int EXPANDED = 125;
|
||||
public static final int EXTRA_EXPANDED = 150;
|
||||
public static final int ULTRA_EXPANDED = 200;
|
||||
|
||||
/* Font spacings. */
|
||||
public static final int PROPORTIONAL = 0;
|
||||
public static final int DUAL = 90;
|
||||
public static final int MONO = 100;
|
||||
public static final int CHARCELL = 110;
|
||||
|
||||
public class FontSpec
|
||||
{
|
||||
/* The fields below mean the same as they do in enum
|
||||
font_property_index in font.h. */
|
||||
|
||||
public String foundry;
|
||||
public String family;
|
||||
public String adstyle;
|
||||
public String registry;
|
||||
public Integer width;
|
||||
public Integer weight;
|
||||
public Integer slant;
|
||||
public Integer size;
|
||||
public Integer spacing;
|
||||
public Integer avgwidth;
|
||||
|
||||
@Override
|
||||
public String
|
||||
toString ()
|
||||
{
|
||||
return ("foundry: " + foundry
|
||||
+ " family: " + family
|
||||
+ " adstyle: " + adstyle
|
||||
+ " registry: " + registry
|
||||
+ " width: " + width
|
||||
+ " weight: " + weight
|
||||
+ " slant: " + slant
|
||||
+ " spacing: " + spacing
|
||||
+ " avgwidth: " + avgwidth);
|
||||
}
|
||||
};
|
||||
|
||||
public class FontMetrics
|
||||
{
|
||||
public short lbearing;
|
||||
public short rbearing;
|
||||
public short width;
|
||||
public short ascent;
|
||||
public short descent;
|
||||
}
|
||||
|
||||
public class FontEntity extends FontSpec
|
||||
{
|
||||
/* No extra fields here. */
|
||||
};
|
||||
|
||||
public abstract class FontObject extends FontSpec
|
||||
{
|
||||
public int minWidth;
|
||||
public int maxWidth;
|
||||
public int pixelSize;
|
||||
public int height;
|
||||
public int spaceWidth;
|
||||
public int averageWidth;
|
||||
public int ascent;
|
||||
public int descent;
|
||||
public int underlineThickness;
|
||||
public int underlinePosition;
|
||||
public int baselineOffset;
|
||||
public int relativeCompose;
|
||||
public int defaultAscent;
|
||||
public int encodingCharset;
|
||||
public int repertoryCharset;
|
||||
|
||||
public
|
||||
FontObject ()
|
||||
{
|
||||
encodingCharset = -1;
|
||||
repertoryCharset = -1;
|
||||
}
|
||||
};
|
||||
|
||||
/* These mean the same as they do in struct font_driver. */
|
||||
public abstract FontEntity[] list (FontSpec fontSpec);
|
||||
public abstract FontEntity match (FontSpec fontSpec);
|
||||
public abstract String[] listFamilies ();
|
||||
public abstract FontObject openFont (FontEntity fontEntity, int pixelSize);
|
||||
public abstract int hasChar (FontSpec font, char charCode);
|
||||
public abstract void textExtents (FontObject font, int code[],
|
||||
FontMetrics fontMetrics[]);
|
||||
public abstract int encodeChar (FontObject fontObject, char charCode);
|
||||
|
||||
public static EmacsFontDriver
|
||||
createFontDriver ()
|
||||
{
|
||||
return new EmacsSdk7FontDriver ();
|
||||
}
|
||||
};
|
116
java/org/gnu/emacs/EmacsGC.java
Normal file
116
java/org/gnu/emacs/EmacsGC.java
Normal file
|
@ -0,0 +1,116 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import android.graphics.Rect;
|
||||
|
||||
/* X like graphics context structures. Keep the enums in synch with
|
||||
androidgui.h! */
|
||||
|
||||
public class EmacsGC extends EmacsHandleObject
|
||||
{
|
||||
public static final int GC_COPY = 0;
|
||||
public static final int GC_XOR = 1;
|
||||
|
||||
public static final int GC_FILL_SOLID = 0;
|
||||
public static final int GC_FILL_OPAQUE_STIPPLED = 1;
|
||||
|
||||
public int function, fill_style;
|
||||
public int foreground, background;
|
||||
public int clip_x_origin, clip_y_origin;
|
||||
public int ts_origin_x, ts_origin_y;
|
||||
public Rect clip_rects[];
|
||||
public EmacsPixmap clip_mask, stipple;
|
||||
private boolean dirty;
|
||||
private EmacsGC immutableGC;
|
||||
|
||||
/* The following fields are only set on immutable GCs. */
|
||||
|
||||
public
|
||||
EmacsGC (short handle)
|
||||
{
|
||||
/* For historical reasons the C code has an extra layer of
|
||||
indirection above this GC handle. struct android_gc is the GC
|
||||
used by Emacs code, while android_gcontext is the type of the
|
||||
handle. */
|
||||
super (handle);
|
||||
|
||||
fill_style = GC_FILL_SOLID;
|
||||
function = GC_COPY;
|
||||
foreground = 0;
|
||||
background = 0xffffffff;
|
||||
}
|
||||
|
||||
public
|
||||
EmacsGC (EmacsGC source)
|
||||
{
|
||||
super ((short) 0);
|
||||
|
||||
int i;
|
||||
|
||||
function = source.function;
|
||||
fill_style = source.fill_style;
|
||||
foreground = source.foreground;
|
||||
background = source.background;
|
||||
clip_x_origin = source.clip_x_origin;
|
||||
clip_y_origin = source.clip_y_origin;
|
||||
clip_rects = source.clip_rects;
|
||||
clip_mask = source.clip_mask;
|
||||
stipple = source.stipple;
|
||||
ts_origin_x = source.ts_origin_x;
|
||||
ts_origin_y = source.ts_origin_y;
|
||||
|
||||
/* Offset all the clip rects by ts_origin_x and ts_origin_y. */
|
||||
|
||||
if ((ts_origin_x != 0 || ts_origin_y != 0)
|
||||
&& clip_rects != null)
|
||||
{
|
||||
clip_rects = new Rect[clip_rects.length];
|
||||
|
||||
for (i = 0; i < clip_rects.length; ++i)
|
||||
{
|
||||
clip_rects[i] = new Rect (source.clip_rects[i]);
|
||||
clip_rects[i].offset (ts_origin_x,
|
||||
ts_origin_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark this GC as dirty. This means immutableGC will return a new
|
||||
copy of this GC the next time it is called. */
|
||||
|
||||
public void
|
||||
markDirty ()
|
||||
{
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public EmacsGC
|
||||
immutableGC ()
|
||||
{
|
||||
if (immutableGC == null || dirty)
|
||||
{
|
||||
immutableGC = new EmacsGC (this);
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
return immutableGC;
|
||||
};
|
||||
};
|
62
java/org/gnu/emacs/EmacsHandleObject.java
Normal file
62
java/org/gnu/emacs/EmacsHandleObject.java
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.lang.Object;
|
||||
import java.lang.IllegalStateException;
|
||||
|
||||
/* This defines something that is a so-called ``handle''. Handles
|
||||
must be created by C code, and will remain existing until
|
||||
destroyHandle is called. C code then refers to the handle by a
|
||||
number which maps into the Java object representing the handle.
|
||||
|
||||
All handle operations must be done from the Emacs thread. */
|
||||
|
||||
public abstract class EmacsHandleObject
|
||||
{
|
||||
/* Whether or not this handle has been destroyed. */
|
||||
volatile boolean destroyed;
|
||||
|
||||
/* The handle associated with this object. */
|
||||
public short handle;
|
||||
|
||||
public
|
||||
EmacsHandleObject (short handle)
|
||||
{
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
public void
|
||||
destroyHandle () throws IllegalStateException
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
destroyed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean
|
||||
isDestroyed ()
|
||||
{
|
||||
return destroyed;
|
||||
}
|
||||
};
|
72
java/org/gnu/emacs/EmacsNative.java
Normal file
72
java/org/gnu/emacs/EmacsNative.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import java.lang.System;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
|
||||
public class EmacsNative
|
||||
{
|
||||
/* Set certain parameters before initializing Emacs. This proves
|
||||
that libemacs.so is being loaded from Java code.
|
||||
|
||||
assetManager must be the asset manager associated with the
|
||||
context that is loading Emacs. It is saved and remains for the
|
||||
remainder the lifetime of the Emacs process.
|
||||
|
||||
filesDir must be the package's data storage location for the
|
||||
current Android user.
|
||||
|
||||
libDir must be the package's data storage location for native
|
||||
libraries. It is used as PATH.
|
||||
|
||||
emacsService must be the emacsService singleton. */
|
||||
public static native void setEmacsParams (AssetManager assetManager,
|
||||
String filesDir,
|
||||
String libDir,
|
||||
EmacsService emacsService);
|
||||
|
||||
/* Initialize Emacs with the argument array ARGV. Each argument
|
||||
must contain a NULL terminated string, or else the behavior is
|
||||
undefined. */
|
||||
public static native void initEmacs (String argv[]);
|
||||
|
||||
/* Abort and generate a native core dump. */
|
||||
public static native void emacsAbort ();
|
||||
|
||||
/* Send an ANDROID_CONFIGURE_NOTIFY event. */
|
||||
public static native void sendConfigureNotify (short window, long time,
|
||||
int x, int y, int width,
|
||||
int height);
|
||||
|
||||
/* Send an ANDROID_KEY_PRESS event. */
|
||||
public static native void sendKeyPress (short window, long time, int state,
|
||||
int keyCode);
|
||||
|
||||
/* Send an ANDROID_KEY_RELEASE event. */
|
||||
public static native void sendKeyRelease (short window, long time, int state,
|
||||
int keyRelease);
|
||||
|
||||
static
|
||||
{
|
||||
System.loadLibrary ("emacs");
|
||||
};
|
||||
};
|
138
java/org/gnu/emacs/EmacsPaintQueue.java
Normal file
138
java/org/gnu/emacs/EmacsPaintQueue.java
Normal file
|
@ -0,0 +1,138 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
|
||||
public class EmacsPaintQueue
|
||||
{
|
||||
/* Queue of paint operations. This is modified from the Emacs
|
||||
thread, and entire paint queues are periodically flushed to the
|
||||
application thread where it is executed. */
|
||||
private List<EmacsPaintReq> paintOperations;
|
||||
|
||||
/* Number of operations in this queue. */
|
||||
public int numRequests;
|
||||
|
||||
public
|
||||
EmacsPaintQueue ()
|
||||
{
|
||||
paintOperations = new LinkedList<EmacsPaintReq> ();
|
||||
}
|
||||
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
EmacsDrawable drawable, last;
|
||||
Canvas canvas;
|
||||
EmacsGC gc, lastGC;
|
||||
int i;
|
||||
Paint paint;
|
||||
Rect rect, offsetRect, copyRect;
|
||||
|
||||
canvas = null;
|
||||
last = null;
|
||||
gc = null;
|
||||
paint = new Paint ();
|
||||
|
||||
for (EmacsPaintReq req : paintOperations)
|
||||
{
|
||||
drawable = req.getDrawable ();
|
||||
|
||||
synchronized (req)
|
||||
{
|
||||
/* Ignore graphics requests for drawables that have been
|
||||
destroyed. */
|
||||
if (drawable.isDestroyed ())
|
||||
continue;
|
||||
}
|
||||
|
||||
canvas = drawable.lockCanvas ();
|
||||
|
||||
if (canvas == null)
|
||||
/* No canvas is currently available. */
|
||||
continue;
|
||||
|
||||
lastGC = gc;
|
||||
gc = req.getGC ();
|
||||
rect = req.getRect ();
|
||||
|
||||
if (gc.clip_rects == null)
|
||||
{
|
||||
/* No clipping is applied. Just draw and continue. */
|
||||
canvas.save ();
|
||||
req.paintTo (canvas, paint, gc);
|
||||
canvas.restore ();
|
||||
drawable.damageRect (rect);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gc.clip_rects != null && gc.clip_rects.length > 0)
|
||||
{
|
||||
canvas.save ();
|
||||
|
||||
if (gc.clip_rects.length == 1)
|
||||
{
|
||||
/* There is only a single clip rect, which is simple
|
||||
enough. */
|
||||
canvas.clipRect (gc.clip_rects[0]);
|
||||
req.paintTo (canvas, paint, gc);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There are multiple clip rects. Android doesn't let
|
||||
programs use RegionOp.UNION on the clip rectangle,
|
||||
so Emacs must iterate over each intersection and
|
||||
paint it manually. This seems inefficient but
|
||||
thankfully Emacs never seems to use more than one
|
||||
clip rect. */
|
||||
|
||||
for (i = 0; i < gc.clip_rects.length; ++i)
|
||||
{
|
||||
copyRect = new Rect (gc.clip_rects[i]);
|
||||
|
||||
if (copyRect.intersect (rect))
|
||||
{
|
||||
canvas.save ();
|
||||
canvas.clipRect (copyRect);
|
||||
req.paintTo (canvas, paint, gc);
|
||||
canvas.restore ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drawable.damageRect (rect);
|
||||
canvas.restore ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void
|
||||
appendPaintOperation (EmacsPaintReq req)
|
||||
{
|
||||
paintOperations.add (req);
|
||||
numRequests++;
|
||||
}
|
||||
};
|
33
java/org/gnu/emacs/EmacsPaintReq.java
Normal file
33
java/org/gnu/emacs/EmacsPaintReq.java
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
|
||||
public interface EmacsPaintReq
|
||||
{
|
||||
public EmacsDrawable getDrawable ();
|
||||
public EmacsGC getGC ();
|
||||
public void paintTo (Canvas canvas, Paint paint,
|
||||
EmacsGC immutableGC);
|
||||
public Rect getRect ();
|
||||
};
|
102
java/org/gnu/emacs/EmacsPixmap.java
Normal file
102
java/org/gnu/emacs/EmacsPixmap.java
Normal file
|
@ -0,0 +1,102 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
|
||||
/* Drawable backed by bitmap. */
|
||||
|
||||
public class EmacsPixmap extends EmacsHandleObject
|
||||
implements EmacsDrawable
|
||||
{
|
||||
/* The depth of the bitmap. This is not actually used, just defined
|
||||
in order to be consistent with X. */
|
||||
public int depth, width, height;
|
||||
|
||||
/* The bitmap itself. */
|
||||
public Bitmap bitmap;
|
||||
|
||||
/* The canvas used to draw to BITMAP. */
|
||||
public Canvas canvas;
|
||||
|
||||
public
|
||||
EmacsPixmap (short handle, int colors[], int width,
|
||||
int height, int depth)
|
||||
{
|
||||
super (handle);
|
||||
|
||||
if (depth != 1 && depth != 24)
|
||||
throw new IllegalArgumentException ("Invalid depth specified"
|
||||
+ " for pixmap: " + depth);
|
||||
|
||||
switch (depth)
|
||||
{
|
||||
case 1:
|
||||
bitmap = Bitmap.createBitmap (colors, width, height,
|
||||
Bitmap.Config.ALPHA_8);
|
||||
break;
|
||||
|
||||
case 24:
|
||||
bitmap = Bitmap.createBitmap (colors, width, height,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
bitmap.setHasAlpha (false);
|
||||
break;
|
||||
}
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.depth = depth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Canvas
|
||||
lockCanvas ()
|
||||
{
|
||||
if (canvas == null)
|
||||
canvas = new Canvas (bitmap);
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
unlockCanvas ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
damageRect (Rect damageRect)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap
|
||||
getBitmap ()
|
||||
{
|
||||
return bitmap;
|
||||
}
|
||||
};
|
460
java/org/gnu/emacs/EmacsSdk7FontDriver.java
Normal file
460
java/org/gnu/emacs/EmacsSdk7FontDriver.java
Normal file
|
@ -0,0 +1,460 @@
|
|||
/* Font backend for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Typeface;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class EmacsSdk7FontDriver extends EmacsFontDriver
|
||||
{
|
||||
private static final String TOFU_STRING = "\uDB3F\uDFFD";
|
||||
private static final String EM_STRING = "m";
|
||||
private static final String TAG = "EmacsSdk7FontDriver";
|
||||
|
||||
private class Sdk7Typeface
|
||||
{
|
||||
/* The typeface and paint. */
|
||||
public Typeface typeface;
|
||||
public Paint typefacePaint;
|
||||
public String familyName;
|
||||
public int slant, width, weight, spacing;
|
||||
|
||||
public
|
||||
Sdk7Typeface (String fileName, Typeface typeface)
|
||||
{
|
||||
String style, testString;
|
||||
int index, measured, i;
|
||||
float[] widths;
|
||||
|
||||
slant = NORMAL;
|
||||
weight = REGULAR;
|
||||
width = UNSPECIFIED;
|
||||
spacing = PROPORTIONAL;
|
||||
|
||||
typefacePaint = new Paint ();
|
||||
typefacePaint.setTypeface (typeface);
|
||||
|
||||
/* For the calls to measureText below. */
|
||||
typefacePaint.setTextSize (10.0f);
|
||||
|
||||
/* Parse the file name into some useful data. First, strip off
|
||||
the extension. */
|
||||
fileName = fileName.split ("\\.", 2)[0];
|
||||
|
||||
/* Next, split the file name by dashes. Everything before the
|
||||
last dash is part of the family name. */
|
||||
index = fileName.lastIndexOf ("-");
|
||||
|
||||
if (index > 0)
|
||||
{
|
||||
style = fileName.substring (index + 1, fileName.length ());
|
||||
familyName = fileName.substring (0, index);
|
||||
|
||||
/* Look for something describing the weight. */
|
||||
if (style.contains ("Thin"))
|
||||
weight = THIN;
|
||||
else if (style.contains ("UltraLight"))
|
||||
weight = ULTRA_LIGHT;
|
||||
else if (style.contains ("SemiLight"))
|
||||
weight = SEMI_LIGHT;
|
||||
else if (style.contains ("Light"))
|
||||
weight = LIGHT;
|
||||
else if (style.contains ("Medium"))
|
||||
weight = MEDIUM;
|
||||
else if (style.contains ("SemiBold"))
|
||||
weight = SEMI_BOLD;
|
||||
else if (style.contains ("ExtraBold"))
|
||||
weight = EXTRA_BOLD;
|
||||
else if (style.contains ("Bold"))
|
||||
weight = BOLD;
|
||||
else if (style.contains ("Black"))
|
||||
weight = BLACK;
|
||||
else if (style.contains ("UltraHeavy"))
|
||||
weight = ULTRA_HEAVY;
|
||||
|
||||
/* And the slant. */
|
||||
if (style.contains ("ReverseOblique"))
|
||||
slant = OBLIQUE;
|
||||
else if (style.contains ("ReverseItalic"))
|
||||
slant = REVERSE_ITALIC;
|
||||
else if (style.contains ("Italic"))
|
||||
slant = ITALIC;
|
||||
else if (style.contains ("Oblique"))
|
||||
slant = OBLIQUE;
|
||||
|
||||
/* Finally, the width. */
|
||||
if (style.contains ("UltraCondensed"))
|
||||
width = ULTRA_CONDENSED;
|
||||
else if (style.contains ("ExtraCondensed"))
|
||||
width = EXTRA_CONDENSED;
|
||||
else if (style.contains ("SemiCondensed"))
|
||||
width = SEMI_CONDENSED;
|
||||
else if (style.contains ("Condensed"))
|
||||
width = CONDENSED;
|
||||
else if (style.contains ("SemiExpanded"))
|
||||
width = SEMI_EXPANDED;
|
||||
else if (style.contains ("ExtraExpanded"))
|
||||
width = EXTRA_EXPANDED;
|
||||
else if (style.contains ("UltraExpanded"))
|
||||
width = ULTRA_EXPANDED;
|
||||
else if (style.contains ("Expanded"))
|
||||
width = EXPANDED;
|
||||
|
||||
/* Guess the spacing information. */
|
||||
testString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
widths = new float[testString.length ()];
|
||||
|
||||
measured = typefacePaint.getTextWidths (testString,
|
||||
0, testString.length (),
|
||||
widths);
|
||||
spacing = MONO;
|
||||
for (i = 0; i < measured; ++i)
|
||||
{
|
||||
if (i != 0 && widths[i - 1] != widths[i])
|
||||
/* This isn't a monospace font. */
|
||||
spacing = PROPORTIONAL;
|
||||
}
|
||||
}
|
||||
else
|
||||
familyName = fileName;
|
||||
|
||||
Log.d (TAG, "Initialized new typeface " + familyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String
|
||||
toString ()
|
||||
{
|
||||
return ("Sdk7Typeface ("
|
||||
+ String.valueOf (familyName) + ", "
|
||||
+ String.valueOf (slant) + ", "
|
||||
+ String.valueOf (width) + ", "
|
||||
+ String.valueOf (weight) + ", "
|
||||
+ String.valueOf (spacing) + ")");
|
||||
}
|
||||
};
|
||||
|
||||
private class Sdk7FontEntity extends FontEntity
|
||||
{
|
||||
/* The typeface. */
|
||||
public Sdk7Typeface typeface;
|
||||
|
||||
public
|
||||
Sdk7FontEntity (Sdk7Typeface typeface)
|
||||
{
|
||||
float width;
|
||||
|
||||
foundry = "Google";
|
||||
family = typeface.familyName;
|
||||
adstyle = null;
|
||||
weight = typeface.weight;
|
||||
slant = typeface.slant;
|
||||
spacing = typeface.spacing;
|
||||
width = typeface.width;
|
||||
|
||||
this.typeface = typeface;
|
||||
}
|
||||
};
|
||||
|
||||
private class Sdk7FontObject extends FontObject
|
||||
{
|
||||
/* The typeface. */
|
||||
public Sdk7Typeface typeface;
|
||||
|
||||
/* The text size. */
|
||||
public int pixelSize;
|
||||
|
||||
public
|
||||
Sdk7FontObject (Sdk7Typeface typeface, int pixelSize)
|
||||
{
|
||||
float totalWidth;
|
||||
String testWidth, testString;
|
||||
|
||||
this.typeface = typeface;
|
||||
this.pixelSize = pixelSize;
|
||||
|
||||
family = typeface.familyName;
|
||||
adstyle = null;
|
||||
weight = typeface.weight;
|
||||
slant = typeface.slant;
|
||||
spacing = typeface.spacing;
|
||||
width = typeface.width;
|
||||
|
||||
/* Compute the ascent and descent. */
|
||||
typeface.typefacePaint.setTextSize (pixelSize);
|
||||
ascent
|
||||
= Math.round (-typeface.typefacePaint.ascent ());
|
||||
descent
|
||||
= Math.round (typeface.typefacePaint.descent ());
|
||||
|
||||
/* Compute the average width. */
|
||||
testString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
totalWidth = typeface.typefacePaint.measureText (testString);
|
||||
|
||||
if (totalWidth > 0)
|
||||
avgwidth = Math.round (totalWidth
|
||||
/ testString.length ());
|
||||
|
||||
/* Android doesn't expose the font average width and height
|
||||
information, so this will have to do. */
|
||||
minWidth = maxWidth = avgwidth;
|
||||
|
||||
/* This is different from avgwidth in the font spec! */
|
||||
averageWidth = avgwidth;
|
||||
|
||||
/* Set the space width. */
|
||||
totalWidth = typeface.typefacePaint.measureText (" ");
|
||||
spaceWidth = Math.round (totalWidth);
|
||||
|
||||
/* Set the height and default ascent. */
|
||||
height = ascent + descent;
|
||||
defaultAscent = ascent;
|
||||
}
|
||||
};
|
||||
|
||||
private String[] fontFamilyList;
|
||||
private Sdk7Typeface[] typefaceList;
|
||||
private Sdk7Typeface fallbackTypeface;
|
||||
|
||||
public
|
||||
EmacsSdk7FontDriver ()
|
||||
{
|
||||
int i;
|
||||
File systemFontsDirectory, fontFile;
|
||||
Typeface typeface;
|
||||
|
||||
systemFontsDirectory = new File ("/system/fonts");
|
||||
|
||||
fontFamilyList = systemFontsDirectory.list ();
|
||||
typefaceList = new Sdk7Typeface[fontFamilyList.length];
|
||||
|
||||
/* It would be nice to avoid opening each and every font upon
|
||||
startup. But that doesn't seem to be possible on
|
||||
Android. */
|
||||
|
||||
for (i = 0; i < fontFamilyList.length; ++i)
|
||||
{
|
||||
fontFile = new File (systemFontsDirectory,
|
||||
fontFamilyList[i]);
|
||||
typeface = Typeface.createFromFile (fontFile);
|
||||
typefaceList[i] = new Sdk7Typeface (fontFile.getName (),
|
||||
typeface);
|
||||
}
|
||||
|
||||
fallbackTypeface = new Sdk7Typeface ("monospace",
|
||||
Typeface.MONOSPACE);
|
||||
}
|
||||
|
||||
private boolean
|
||||
checkMatch (Sdk7Typeface typeface, FontSpec fontSpec)
|
||||
{
|
||||
if (fontSpec.family != null
|
||||
&& !fontSpec.family.equals (typeface.familyName))
|
||||
return false;
|
||||
|
||||
|
||||
if (fontSpec.adstyle != null
|
||||
&& !fontSpec.adstyle.isEmpty ())
|
||||
/* return false; */;
|
||||
|
||||
if (fontSpec.slant != null
|
||||
&& !fontSpec.weight.equals (typeface.weight))
|
||||
return false;
|
||||
|
||||
if (fontSpec.spacing != null
|
||||
&& !fontSpec.spacing.equals (typeface.spacing))
|
||||
return false;
|
||||
|
||||
if (fontSpec.weight != null
|
||||
&& !fontSpec.weight.equals (typeface.weight))
|
||||
return false;
|
||||
|
||||
if (fontSpec.width != null
|
||||
&& !fontSpec.width.equals (typeface.width))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontEntity[]
|
||||
list (FontSpec fontSpec)
|
||||
{
|
||||
LinkedList<FontEntity> list;
|
||||
int i;
|
||||
|
||||
list = new LinkedList<FontEntity> ();
|
||||
|
||||
Log.d (TAG, ("Looking for fonts matching font spec: "
|
||||
+ fontSpec.toString ()));
|
||||
|
||||
for (i = 0; i < typefaceList.length; ++i)
|
||||
{
|
||||
if (checkMatch (typefaceList[i], fontSpec))
|
||||
list.add (new Sdk7FontEntity (typefaceList[i]));
|
||||
}
|
||||
|
||||
Log.d (TAG, "Found font entities: " + list.toString ());
|
||||
|
||||
return (FontEntity[]) list.toArray (new FontEntity[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontEntity
|
||||
match (FontSpec fontSpec)
|
||||
{
|
||||
FontEntity[] entities;
|
||||
int i;
|
||||
|
||||
entities = this.list (fontSpec);
|
||||
|
||||
if (entities.length == 0)
|
||||
return new Sdk7FontEntity (fallbackTypeface);
|
||||
|
||||
return entities[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[]
|
||||
listFamilies ()
|
||||
{
|
||||
return fontFamilyList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontObject
|
||||
openFont (FontEntity fontEntity, int pixelSize)
|
||||
{
|
||||
return new Sdk7FontObject (((Sdk7FontEntity) fontEntity).typeface,
|
||||
pixelSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int
|
||||
hasChar (FontSpec font, char charCode)
|
||||
{
|
||||
float missingGlyphWidth, emGlyphWidth, width;
|
||||
Rect rect1, rect2;
|
||||
Paint paint;
|
||||
Sdk7FontObject fontObject;
|
||||
|
||||
if (font instanceof Sdk7FontObject)
|
||||
{
|
||||
fontObject = (Sdk7FontObject) font;
|
||||
paint = fontObject.typeface.typefacePaint;
|
||||
}
|
||||
else
|
||||
paint = ((Sdk7FontEntity) font).typeface.typefacePaint;
|
||||
|
||||
paint.setTextSize (10);
|
||||
|
||||
if (Character.isWhitespace (charCode))
|
||||
return 1;
|
||||
|
||||
missingGlyphWidth = paint.measureText (TOFU_STRING);
|
||||
emGlyphWidth = paint.measureText (EM_STRING);
|
||||
width = paint.measureText ("" + charCode);
|
||||
|
||||
if (width == 0f)
|
||||
return 0;
|
||||
|
||||
if (width != missingGlyphWidth)
|
||||
return 1;
|
||||
|
||||
rect1 = new Rect ();
|
||||
rect2 = new Rect ();
|
||||
|
||||
paint.getTextBounds (TOFU_STRING, 0, TOFU_STRING.length (),
|
||||
rect1);
|
||||
paint.getTextBounds ("" + charCode, 0, 1, rect2);
|
||||
return rect1.equals (rect2) ? 1 : 0;
|
||||
}
|
||||
|
||||
private void
|
||||
textExtents1 (Sdk7FontObject font, int code, FontMetrics metrics,
|
||||
Paint paint, Rect bounds)
|
||||
{
|
||||
char[] text;
|
||||
float[] width;
|
||||
|
||||
text = new char[1];
|
||||
text[0] = (char) code;
|
||||
|
||||
paint.getTextBounds (text, 0, 1, bounds);
|
||||
width = new float[1];
|
||||
paint.getTextWidths (text, 0, 1, width);
|
||||
|
||||
/* bounds is the bounding box of the glyph corresponding to CODE.
|
||||
Translate these into XCharStruct values.
|
||||
|
||||
The origin is at 0, 0, and lbearing is the distance counting
|
||||
rightwards from the origin to the left most pixel in the glyph
|
||||
raster. rbearing is the distance between the origin and the
|
||||
rightmost pixel in the glyph raster. ascent is the distance
|
||||
counting upwards between the the topmost pixel in the glyph
|
||||
raster. descent is the distance (once again counting
|
||||
downwards) between the origin and the bottommost pixel in the
|
||||
glyph raster.
|
||||
|
||||
width is the distance between the origin and the origin of any
|
||||
character to the right. */
|
||||
|
||||
metrics.lbearing = (short) bounds.left;
|
||||
metrics.rbearing = (short) bounds.right;
|
||||
metrics.ascent = (short) -bounds.top;
|
||||
metrics.descent = (short) bounds.bottom;
|
||||
metrics.width = (short) Math.round (width[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
textExtents (FontObject font, int code[], FontMetrics fontMetrics[])
|
||||
{
|
||||
int i;
|
||||
Paint paintCache;
|
||||
Rect boundsCache;
|
||||
Sdk7FontObject fontObject;
|
||||
|
||||
fontObject = (Sdk7FontObject) font;
|
||||
paintCache = fontObject.typeface.typefacePaint;
|
||||
paintCache.setTextSize (fontObject.pixelSize);
|
||||
boundsCache = new Rect ();
|
||||
|
||||
for (i = 0; i < code.length; ++i)
|
||||
textExtents1 ((Sdk7FontObject) font, code[i], fontMetrics[i],
|
||||
paintCache, boundsCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int
|
||||
encodeChar (FontObject fontObject, char charCode)
|
||||
{
|
||||
return charCode;
|
||||
}
|
||||
};
|
384
java/org/gnu/emacs/EmacsService.java
Normal file
384
java/org/gnu/emacs/EmacsService.java
Normal file
|
@ -0,0 +1,384 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import java.lang.Runnable;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Point;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.AssetManager;
|
||||
import android.os.Build;
|
||||
import android.os.Looper;
|
||||
import android.os.IBinder;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
class Holder<T>
|
||||
{
|
||||
T thing;
|
||||
};
|
||||
|
||||
/* EmacsService is the service that starts the thread running Emacs
|
||||
and handles requests by that Emacs instance. */
|
||||
|
||||
public class EmacsService extends Service
|
||||
{
|
||||
public static final String TAG = "EmacsService";
|
||||
public static final int MAX_PENDING_REQUESTS = 256;
|
||||
public static volatile EmacsService SERVICE;
|
||||
|
||||
private EmacsThread thread;
|
||||
private Handler handler;
|
||||
private EmacsPaintQueue paintQueue;
|
||||
|
||||
/* List of all EmacsWindows that are available to attach to an
|
||||
activity. */
|
||||
public static List<EmacsWindow> availableChildren;
|
||||
|
||||
static
|
||||
{
|
||||
availableChildren = new ArrayList<EmacsWindow> ();
|
||||
};
|
||||
|
||||
@Override
|
||||
public int
|
||||
onStartCommand (Intent intent, int flags, int startId)
|
||||
{
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder
|
||||
onBind (Intent intent)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@TargetApi (Build.VERSION_CODES.GINGERBREAD)
|
||||
String
|
||||
getLibraryDirectory ()
|
||||
{
|
||||
int apiLevel;
|
||||
Context context;
|
||||
|
||||
context = getApplicationContext ();
|
||||
apiLevel = android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
if (apiLevel >= Build.VERSION_CODES.GINGERBREAD)
|
||||
return context.getApplicationInfo().nativeLibraryDir;
|
||||
else if (apiLevel >= Build.VERSION_CODES.DONUT)
|
||||
return context.getApplicationInfo().dataDir + "/lib";
|
||||
|
||||
return "/data/data/" + context.getPackageName() + "/lib";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
onCreate ()
|
||||
{
|
||||
AssetManager manager;
|
||||
Context app_context;
|
||||
String filesDir, libDir;
|
||||
|
||||
SERVICE = this;
|
||||
handler = new Handler (Looper.getMainLooper ());
|
||||
manager = getAssets ();
|
||||
app_context = getApplicationContext ();
|
||||
|
||||
try
|
||||
{
|
||||
/* Configure Emacs with the asset manager and other necessary
|
||||
parameters. */
|
||||
filesDir = app_context.getFilesDir ().getCanonicalPath ();
|
||||
libDir = getLibraryDirectory ();
|
||||
|
||||
Log.d (TAG, "Initializing Emacs, where filesDir = " + filesDir
|
||||
+ " and libDir = " + libDir);
|
||||
|
||||
EmacsNative.setEmacsParams (manager, filesDir, libDir,
|
||||
this);
|
||||
|
||||
/* Start the thread that runs Emacs. */
|
||||
thread = new EmacsThread (this);
|
||||
thread.start ();
|
||||
}
|
||||
catch (IOException exception)
|
||||
{
|
||||
EmacsNative.emacsAbort ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Functions from here on must only be called from the Emacs
|
||||
thread. */
|
||||
|
||||
void
|
||||
runOnUiThread (Runnable runnable)
|
||||
{
|
||||
handler.post (runnable);
|
||||
}
|
||||
|
||||
EmacsView
|
||||
getEmacsView (final EmacsWindow window)
|
||||
{
|
||||
Runnable runnable;
|
||||
final Holder<EmacsView> view;
|
||||
|
||||
view = new Holder<EmacsView> ();
|
||||
|
||||
runnable = new Runnable () {
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
view.thing = new EmacsView (window);
|
||||
notify ();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
synchronized (runnable)
|
||||
{
|
||||
runOnUiThread (runnable);
|
||||
|
||||
try
|
||||
{
|
||||
runnable.wait ();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
EmacsNative.emacsAbort ();
|
||||
}
|
||||
}
|
||||
|
||||
return view.thing;
|
||||
}
|
||||
|
||||
/* Notice that a child of the root window named WINDOW is now
|
||||
available for attachment to a specific activity. */
|
||||
|
||||
public void
|
||||
noticeAvailableChild (final EmacsWindow window)
|
||||
{
|
||||
Log.d (TAG, "A new child is available: " + window);
|
||||
|
||||
handler.post (new Runnable () {
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
for (EmacsActivity activity
|
||||
: EmacsActivity.availableActivities)
|
||||
{
|
||||
/* TODO: check if the activity matches. */
|
||||
activity.attachChild (window);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Nope, wait for an activity to become available. */
|
||||
availableChildren.add (window);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* Notice that a child of the root window named WINDOW has been
|
||||
destroyed. */
|
||||
|
||||
public void
|
||||
noticeChildDestroyed (final EmacsWindow child)
|
||||
{
|
||||
handler.post (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
availableChildren.remove (child);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* X drawing operations. These are quite primitive operations. The
|
||||
drawing queue is kept on the Emacs thread, but is periodically
|
||||
flushed to the application thread, upon buffers swaps and once it
|
||||
gets too big. */
|
||||
|
||||
|
||||
|
||||
private void
|
||||
ensurePaintQueue ()
|
||||
{
|
||||
if (paintQueue == null)
|
||||
paintQueue = new EmacsPaintQueue ();
|
||||
}
|
||||
|
||||
public void
|
||||
flushPaintQueue ()
|
||||
{
|
||||
final EmacsPaintQueue queue;
|
||||
|
||||
if (paintQueue == null)
|
||||
return;
|
||||
|
||||
if (paintQueue.numRequests < 1)
|
||||
/* No requests to flush. */
|
||||
return;
|
||||
|
||||
queue = paintQueue;
|
||||
|
||||
handler.post (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
queue.run ();
|
||||
}
|
||||
});
|
||||
|
||||
/* Clear the paint queue. */
|
||||
paintQueue = null;
|
||||
}
|
||||
|
||||
private void
|
||||
checkFlush ()
|
||||
{
|
||||
if (paintQueue != null
|
||||
&& paintQueue.numRequests > MAX_PENDING_REQUESTS)
|
||||
flushPaintQueue ();
|
||||
}
|
||||
|
||||
public void
|
||||
fillRectangle (EmacsDrawable drawable, EmacsGC gc,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
EmacsPaintReq req;
|
||||
|
||||
ensurePaintQueue ();
|
||||
|
||||
req = new EmacsFillRectangle (drawable, x, y,
|
||||
width, height,
|
||||
gc.immutableGC ());
|
||||
paintQueue.appendPaintOperation (req);
|
||||
checkFlush ();
|
||||
}
|
||||
|
||||
public void
|
||||
fillPolygon (EmacsDrawable drawable, EmacsGC gc,
|
||||
Point points[])
|
||||
{
|
||||
EmacsPaintReq req;
|
||||
|
||||
ensurePaintQueue ();
|
||||
|
||||
req = new EmacsFillPolygon (drawable, points,
|
||||
gc.immutableGC ());
|
||||
paintQueue.appendPaintOperation (req);
|
||||
checkFlush ();
|
||||
}
|
||||
|
||||
public void
|
||||
drawRectangle (EmacsDrawable drawable, EmacsGC gc,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
EmacsPaintReq req;
|
||||
|
||||
ensurePaintQueue ();
|
||||
|
||||
if (gc.clip_rects != null && gc.clip_rects.length >= 1)
|
||||
android.util.Log.d ("drawRectangle",
|
||||
gc.clip_rects[0].toString ()
|
||||
+ " " + gc.toString ());
|
||||
|
||||
req = new EmacsDrawRectangle (drawable, x, y,
|
||||
width, height,
|
||||
gc.immutableGC ());
|
||||
paintQueue.appendPaintOperation (req);
|
||||
checkFlush ();
|
||||
}
|
||||
|
||||
public void
|
||||
drawLine (EmacsDrawable drawable, EmacsGC gc,
|
||||
int x, int y, int x2, int y2)
|
||||
{
|
||||
EmacsPaintReq req;
|
||||
|
||||
ensurePaintQueue ();
|
||||
|
||||
req = new EmacsDrawLine (drawable, x, y,
|
||||
x2, y2,
|
||||
gc.immutableGC ());
|
||||
paintQueue.appendPaintOperation (req);
|
||||
checkFlush ();
|
||||
}
|
||||
|
||||
public void
|
||||
drawPoint (EmacsDrawable drawable, EmacsGC gc,
|
||||
int x, int y)
|
||||
{
|
||||
EmacsPaintReq req;
|
||||
|
||||
ensurePaintQueue ();
|
||||
|
||||
req = new EmacsDrawPoint (drawable, x, y,
|
||||
gc.immutableGC ());
|
||||
paintQueue.appendPaintOperation (req);
|
||||
checkFlush ();
|
||||
}
|
||||
|
||||
public void
|
||||
copyArea (EmacsDrawable srcDrawable, EmacsDrawable dstDrawable,
|
||||
EmacsGC gc,
|
||||
int srcX, int srcY, int width, int height, int destX,
|
||||
int destY)
|
||||
{
|
||||
EmacsPaintReq req;
|
||||
|
||||
ensurePaintQueue ();
|
||||
|
||||
req = new EmacsCopyArea (srcDrawable, dstDrawable,
|
||||
srcX, srcY, width, height, destX,
|
||||
destY, gc.immutableGC ());
|
||||
paintQueue.appendPaintOperation (req);
|
||||
checkFlush ();
|
||||
}
|
||||
|
||||
public void
|
||||
clearWindow (EmacsWindow window)
|
||||
{
|
||||
window.clearWindow ();
|
||||
}
|
||||
|
||||
public void
|
||||
clearArea (EmacsWindow window, int x, int y, int width,
|
||||
int height)
|
||||
{
|
||||
window.clearArea (x, y, width, height);
|
||||
}
|
||||
};
|
83
java/org/gnu/emacs/EmacsSurfaceView.java
Normal file
83
java/org/gnu/emacs/EmacsSurfaceView.java
Normal file
|
@ -0,0 +1,83 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import android.view.SurfaceView;
|
||||
import android.view.SurfaceHolder;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
|
||||
public class EmacsSurfaceView extends SurfaceView
|
||||
{
|
||||
private boolean created;
|
||||
|
||||
public
|
||||
EmacsSurfaceView (final EmacsView view)
|
||||
{
|
||||
super (view.getContext ());
|
||||
|
||||
getHolder ().addCallback (new SurfaceHolder.Callback () {
|
||||
@Override
|
||||
public void
|
||||
surfaceChanged (SurfaceHolder holder, int format,
|
||||
int width, int height)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
surfaceCreated (SurfaceHolder holder)
|
||||
{
|
||||
created = true;
|
||||
|
||||
/* Force a buffer swap now to get the contents of the Emacs
|
||||
view on screen. */
|
||||
view.swapBuffers ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
surfaceDestroyed (SurfaceHolder holder)
|
||||
{
|
||||
created = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean
|
||||
isCreated ()
|
||||
{
|
||||
return created;
|
||||
}
|
||||
|
||||
public Canvas
|
||||
lockCanvas (Rect damage)
|
||||
{
|
||||
return getHolder ().lockCanvas (damage);
|
||||
}
|
||||
|
||||
public void
|
||||
unlockCanvasAndPost (Canvas canvas)
|
||||
{
|
||||
getHolder ().unlockCanvasAndPost (canvas);
|
||||
}
|
||||
};
|
44
java/org/gnu/emacs/EmacsThread.java
Normal file
44
java/org/gnu/emacs/EmacsThread.java
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import java.lang.Thread;
|
||||
|
||||
public class EmacsThread extends Thread
|
||||
{
|
||||
EmacsService context;
|
||||
|
||||
public
|
||||
EmacsThread (EmacsService service)
|
||||
{
|
||||
context = service;
|
||||
}
|
||||
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
String args[];
|
||||
|
||||
args = new String[] { "android-emacs", };
|
||||
|
||||
/* Run the native code now. */
|
||||
EmacsNative.initEmacs (args);
|
||||
}
|
||||
};
|
211
java/org/gnu/emacs/EmacsView.java
Normal file
211
java/org/gnu/emacs/EmacsView.java
Normal file
|
@ -0,0 +1,211 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.ViewGroup;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.graphics.Paint;
|
||||
import android.util.Log;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
/* This is an Android view which has a back and front buffer. When
|
||||
swapBuffers is called, the back buffer is swapped to the front
|
||||
buffer, and any damage is invalidated. frontBitmap and backBitmap
|
||||
are modified and used both from the UI and the Emacs thread. As a
|
||||
result, there is a lock held during all drawing operations.
|
||||
|
||||
It is also a ViewGroup, as it also lays out children. */
|
||||
|
||||
public class EmacsView extends ViewGroup
|
||||
{
|
||||
public static final String TAG = "EmacsView";
|
||||
|
||||
/* The associated EmacsWindow. */
|
||||
public EmacsWindow window;
|
||||
|
||||
/* The buffer bitmap. */
|
||||
public Bitmap bitmap;
|
||||
|
||||
/* The associated canvases. */
|
||||
public Canvas canvas;
|
||||
|
||||
/* The damage region. */
|
||||
public Region damageRegion;
|
||||
|
||||
/* The paint. */
|
||||
public Paint paint;
|
||||
|
||||
/* The associated surface view. */
|
||||
private EmacsSurfaceView surfaceView;
|
||||
|
||||
public
|
||||
EmacsView (EmacsWindow window)
|
||||
{
|
||||
super (EmacsService.SERVICE);
|
||||
|
||||
this.window = window;
|
||||
this.damageRegion = new Region ();
|
||||
this.paint = new Paint ();
|
||||
|
||||
/* Create the surface view. */
|
||||
this.surfaceView = new EmacsSurfaceView (this);
|
||||
|
||||
setFocusable (FOCUSABLE);
|
||||
addView (this.surfaceView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void
|
||||
onMeasure (int widthMeasureSpec, int heightMeasureSpec)
|
||||
{
|
||||
Rect measurements;
|
||||
int width, height;
|
||||
|
||||
/* Return the width and height of the window regardless of what
|
||||
the parent says. */
|
||||
measurements = window.getGeometry ();
|
||||
|
||||
width = measurements.width ();
|
||||
height = measurements.height ();
|
||||
|
||||
/* Now apply any extra requirements in widthMeasureSpec and
|
||||
heightMeasureSpec. */
|
||||
|
||||
if (MeasureSpec.getMode (widthMeasureSpec) == MeasureSpec.EXACTLY)
|
||||
width = MeasureSpec.getSize (widthMeasureSpec);
|
||||
else if (MeasureSpec.getMode (widthMeasureSpec) == MeasureSpec.AT_MOST
|
||||
&& width > MeasureSpec.getSize (widthMeasureSpec))
|
||||
width = MeasureSpec.getSize (widthMeasureSpec);
|
||||
|
||||
if (MeasureSpec.getMode (heightMeasureSpec) == MeasureSpec.EXACTLY)
|
||||
height = MeasureSpec.getSize (heightMeasureSpec);
|
||||
else if (MeasureSpec.getMode (heightMeasureSpec) == MeasureSpec.AT_MOST
|
||||
&& height > MeasureSpec.getSize (heightMeasureSpec))
|
||||
height = MeasureSpec.getSize (heightMeasureSpec);
|
||||
|
||||
super.setMeasuredDimension (width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void
|
||||
onLayout (boolean changed, int left, int top, int right,
|
||||
int bottom)
|
||||
{
|
||||
int count, i;
|
||||
View child;
|
||||
Rect windowRect;
|
||||
|
||||
if (changed)
|
||||
{
|
||||
window.viewLayout (left, top, right, bottom);
|
||||
|
||||
/* Recreate the front and back buffer bitmaps. */
|
||||
bitmap
|
||||
= Bitmap.createBitmap (right - left, bottom - top,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
|
||||
/* And canvases. */
|
||||
canvas = new Canvas (bitmap);
|
||||
}
|
||||
|
||||
count = getChildCount ();
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
child = getChildAt (i);
|
||||
|
||||
if (child == surfaceView)
|
||||
/* The child is the surface view, so give it the entire
|
||||
view. */
|
||||
child.layout (left, top, right, bottom);
|
||||
else if (child.getVisibility () != GONE)
|
||||
{
|
||||
if (!(child instanceof EmacsView))
|
||||
continue;
|
||||
|
||||
/* What to do: lay out the view precisely according to its
|
||||
window rect. */
|
||||
windowRect = ((EmacsView) child).window.getGeometry ();
|
||||
child.layout (windowRect.left, windowRect.top,
|
||||
windowRect.right, windowRect.bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void
|
||||
damageRect (Rect damageRect)
|
||||
{
|
||||
damageRegion.union (damageRect);
|
||||
}
|
||||
|
||||
public void
|
||||
swapBuffers ()
|
||||
{
|
||||
Bitmap back;
|
||||
Canvas canvas;
|
||||
Rect damageRect;
|
||||
|
||||
if (damageRegion.isEmpty ())
|
||||
return;
|
||||
|
||||
if (!surfaceView.isCreated ())
|
||||
return;
|
||||
|
||||
if (bitmap == null)
|
||||
return;
|
||||
|
||||
/* Lock the canvas with the specified damage. */
|
||||
damageRect = damageRegion.getBounds ();
|
||||
canvas = surfaceView.lockCanvas (damageRect);
|
||||
|
||||
/* Return if locking the canvas failed. */
|
||||
if (canvas == null)
|
||||
return;
|
||||
|
||||
/* Copy from the back buffer to the canvas. */
|
||||
canvas.drawBitmap (bitmap, damageRect, damageRect, paint);
|
||||
|
||||
/* Unlock the canvas and clear the damage. */
|
||||
surfaceView.unlockCanvasAndPost (canvas);
|
||||
damageRegion.setEmpty ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean
|
||||
onKeyDown (int keyCode, KeyEvent event)
|
||||
{
|
||||
window.onKeyDown (keyCode, event);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean
|
||||
onKeyUp (int keyCode, KeyEvent event)
|
||||
{
|
||||
window.onKeyUp (keyCode, event);
|
||||
return true;
|
||||
}
|
||||
};
|
336
java/org/gnu/emacs/EmacsWindow.java
Normal file
336
java/org/gnu/emacs/EmacsWindow.java
Normal file
|
@ -0,0 +1,336 @@
|
|||
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import java.lang.IllegalStateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Point;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
/* This defines a window, which is a handle. Windows represent a
|
||||
rectangular subset of the screen with their own contents.
|
||||
|
||||
Windows either have a parent window, in which case their views are
|
||||
attached to the parent's view, or are "floating", in which case
|
||||
their views are attached to the parent activity (if any), else
|
||||
nothing.
|
||||
|
||||
Views are also drawables, meaning they can accept drawing
|
||||
requests. */
|
||||
|
||||
public class EmacsWindow extends EmacsHandleObject
|
||||
implements EmacsDrawable
|
||||
{
|
||||
/* The view associated with the window. */
|
||||
public EmacsView view;
|
||||
|
||||
/* The geometry of the window. */
|
||||
private Rect rect;
|
||||
|
||||
/* The parent window, or null if it is the root window. */
|
||||
private EmacsWindow parent;
|
||||
|
||||
/* List of all children in stacking order. This must be kept
|
||||
consistent! */
|
||||
private ArrayList<EmacsWindow> children;
|
||||
|
||||
/* The EmacsActivity currently attached, if it exists. */
|
||||
private EmacsActivity attached;
|
||||
|
||||
/* The window background scratch GC. foreground is always the
|
||||
window background. */
|
||||
private EmacsGC scratchGC;
|
||||
|
||||
public
|
||||
EmacsWindow (short handle, final EmacsWindow parent, int x, int y,
|
||||
int width, int height)
|
||||
{
|
||||
super (handle);
|
||||
|
||||
rect = new Rect (x, y, x + width, y + height);
|
||||
|
||||
/* Create the view from the context's UI thread. */
|
||||
view = EmacsService.SERVICE.getEmacsView (this);
|
||||
this.parent = parent;
|
||||
children = new ArrayList<EmacsWindow> ();
|
||||
|
||||
/* The window is unmapped by default. */
|
||||
view.setVisibility (View.GONE);
|
||||
|
||||
/* If parent is the root window, notice that there are new
|
||||
children available for interested activites to pick up. */
|
||||
if (parent == null)
|
||||
EmacsService.SERVICE.noticeAvailableChild (this);
|
||||
else
|
||||
{
|
||||
/* Otherwise, directly add this window as a child of that
|
||||
window's view. */
|
||||
synchronized (parent)
|
||||
{
|
||||
parent.children.add (this);
|
||||
parent.view.post (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
parent.view.addView (view);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
scratchGC = new EmacsGC ((short) 0);
|
||||
}
|
||||
|
||||
public void
|
||||
changeWindowBackground (int pixel)
|
||||
{
|
||||
/* scratchGC is used as the argument to a FillRectangles req. */
|
||||
scratchGC.foreground = pixel;
|
||||
scratchGC.markDirty ();
|
||||
}
|
||||
|
||||
public Rect
|
||||
getGeometry ()
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
/* Huh, this is it. */
|
||||
return rect;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
destroyHandle () throws IllegalStateException
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
if (!children.isEmpty ())
|
||||
throw new IllegalStateException ("Trying to destroy window with "
|
||||
+ "children!");
|
||||
}
|
||||
|
||||
/* Notice that the child has been destroyed. */
|
||||
EmacsService.SERVICE.noticeChildDestroyed (this);
|
||||
|
||||
/* Remove the view from its parent and make it invisible. */
|
||||
view.post (new Runnable () {
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
view.setVisibility (View.GONE);
|
||||
|
||||
if (view.getParent () != null)
|
||||
((ViewGroup) view.getParent ()).removeView (view);
|
||||
|
||||
if (attached != null)
|
||||
attached.makeAvailable ();
|
||||
}
|
||||
});
|
||||
|
||||
super.destroyHandle ();
|
||||
}
|
||||
|
||||
public void
|
||||
setActivity (EmacsActivity activity)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
activity = activity;
|
||||
}
|
||||
}
|
||||
|
||||
public void
|
||||
viewLayout (int left, int top, int right, int bottom)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
rect.left = left;
|
||||
rect.top = top;
|
||||
rect.right = right;
|
||||
rect.bottom = bottom;
|
||||
|
||||
EmacsNative.sendConfigureNotify (this.handle,
|
||||
System.currentTimeMillis (),
|
||||
left, top, rect.width (),
|
||||
rect.height ());
|
||||
}
|
||||
}
|
||||
|
||||
public void
|
||||
requestViewLayout ()
|
||||
{
|
||||
view.post (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
view.requestLayout ();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void
|
||||
resizeWindow (int width, int height)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
rect.right = rect.left + width;
|
||||
rect.bottom = rect.top + height;
|
||||
}
|
||||
}
|
||||
|
||||
public void
|
||||
moveWindow (int x, int y)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
synchronized (this)
|
||||
{
|
||||
width = rect.width ();
|
||||
height = rect.height ();
|
||||
|
||||
rect.left = x;
|
||||
rect.top = y;
|
||||
rect.right = x + width;
|
||||
rect.bottom = y + height;
|
||||
|
||||
requestViewLayout ();
|
||||
}
|
||||
}
|
||||
|
||||
public void
|
||||
mapWindow ()
|
||||
{
|
||||
view.post (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
view.setVisibility (View.VISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void
|
||||
unmapWindow ()
|
||||
{
|
||||
view.post (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
view.setVisibility (View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Canvas
|
||||
lockCanvas ()
|
||||
{
|
||||
if (view.canvas != null)
|
||||
return view.canvas;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
unlockCanvas ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
damageRect (Rect damageRect)
|
||||
{
|
||||
view.damageRect (damageRect);
|
||||
}
|
||||
|
||||
public void
|
||||
swapBuffers ()
|
||||
{
|
||||
/* Before calling swapBuffers, make sure to flush the paint
|
||||
queue. */
|
||||
EmacsService.SERVICE.flushPaintQueue ();
|
||||
view.post (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
view.swapBuffers ();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void
|
||||
clearWindow ()
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
EmacsService.SERVICE.fillRectangle (this, scratchGC,
|
||||
0, 0, rect.width (),
|
||||
rect.height ());
|
||||
}
|
||||
}
|
||||
|
||||
public void
|
||||
clearArea (int x, int y, int width, int height)
|
||||
{
|
||||
EmacsService.SERVICE.fillRectangle (this, scratchGC,
|
||||
x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap
|
||||
getBitmap ()
|
||||
{
|
||||
return view.bitmap;
|
||||
}
|
||||
|
||||
public void
|
||||
onKeyDown (int keyCode, KeyEvent event)
|
||||
{
|
||||
EmacsNative.sendKeyPress (this.handle,
|
||||
event.getEventTime (),
|
||||
event.getModifiers (),
|
||||
keyCode);
|
||||
}
|
||||
|
||||
public void
|
||||
onKeyUp (int keyCode, KeyEvent event)
|
||||
{
|
||||
EmacsNative.sendKeyRelease (this.handle,
|
||||
event.getEventTime (),
|
||||
event.getModifiers (),
|
||||
keyCode);
|
||||
}
|
||||
};
|
|
@ -96,6 +96,14 @@ localstatedir=@localstatedir@
|
|||
srcdir=@srcdir@
|
||||
VPATH=@srcdir@
|
||||
|
||||
# Cross-compilation setup
|
||||
|
||||
XCONFIGURE=@XCONFIGURE@
|
||||
|
||||
ifneq ($(XCONFIGURE),)
|
||||
vpath $(srcdir)
|
||||
endif
|
||||
|
||||
# The top-level source directory, also set by configure.
|
||||
top_srcdir=@top_srcdir@
|
||||
# MinGW CPPFLAGS may use this.
|
||||
|
|
137
lib/Makefile.in
137
lib/Makefile.in
|
@ -20,6 +20,130 @@
|
|||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
# This is not empty if this is a Makefile that will be copied to
|
||||
# xcompile/lib.
|
||||
XCONFIGURE = @XCONFIGURE@
|
||||
|
||||
# This is required to make sure symbol visibility is correct and
|
||||
# functions like readlinkat do not end up replacing their OS
|
||||
# counterparts.
|
||||
ANDROID_CFLAGS = @ANDROID_CFLAGS@
|
||||
|
||||
ifneq ($(XCONFIGURE),)
|
||||
|
||||
# Set vpath. Only look for C files and some headers in srcdir:
|
||||
# Headers that are generated by gnulib must be spared, or otherwise
|
||||
# the versions previously built on the host will be used, if builddir
|
||||
# is the same as srcdir. Following this is a list of files in lib/
|
||||
# that are not generated during the gnulib build process. Please keep
|
||||
# it up to date!
|
||||
|
||||
vpath _Noreturn.h $(srcdir)
|
||||
vpath acl-internal.h $(srcdir)
|
||||
vpath acl.h $(srcdir)
|
||||
vpath af_alg.h $(srcdir)
|
||||
vpath alloca.in.h $(srcdir)
|
||||
vpath allocator.h $(srcdir)
|
||||
vpath arg-nonnull.h $(srcdir)
|
||||
vpath assert.in.h $(srcdir)
|
||||
vpath attribute.h $(srcdir)
|
||||
vpath binary-io.h $(srcdir)
|
||||
vpath byteswap.in.h $(srcdir)
|
||||
vpath c++defs.h $(srcdir)
|
||||
vpath c-ctype.h $(srcdir)
|
||||
vpath c-strcase.h $(srcdir)
|
||||
vpath careadlinkat.h $(srcdir)
|
||||
vpath cdefs.h $(srcdir)
|
||||
vpath cloexec.h $(srcdir)
|
||||
vpath close-stream.h $(srcdir)
|
||||
vpath count-leading-zeros.h $(srcdir)
|
||||
vpath count-one-bits.h $(srcdir)
|
||||
vpath count-trailing-zeros.h $(srcdir)
|
||||
vpath diffseq.h $(srcdir)
|
||||
vpath dirent.h $(srcdir)
|
||||
vpath dirent.in.h $(srcdir)
|
||||
vpath dynarray.h $(srcdir)
|
||||
vpath eloop-threshold.h $(srcdir)
|
||||
vpath errno.in.h $(srcdir)
|
||||
vpath execinfo.in.h $(srcdir)
|
||||
vpath fcntl.in.h $(srcdir)
|
||||
vpath filemode.h $(srcdir)
|
||||
vpath filename.h $(srcdir)
|
||||
vpath filevercmp.h $(srcdir)
|
||||
vpath fingerprint.h $(srcdir)
|
||||
vpath flexmember.h $(srcdir)
|
||||
vpath fpending.h $(srcdir)
|
||||
vpath fsusage.h $(srcdir)
|
||||
vpath ftoastr.h $(srcdir)
|
||||
vpath getopt-cdefs.in.h $(srcdir)
|
||||
vpath getopt-core.h $(srcdir)
|
||||
vpath getopt-ext.h $(srcdir)
|
||||
vpath getopt-pfx-core.h $(srcdir)
|
||||
vpath getopt-pfx-ext.h $(srcdir)
|
||||
vpath getopt.in.h $(srcdir)
|
||||
vpath getopt_int.h $(srcdir)
|
||||
vpath gettext.h $(srcdir)
|
||||
vpath idx.h $(srcdir)
|
||||
vpath ieee754.in.h $(srcdir)
|
||||
vpath ignore-value.h $(srcdir)
|
||||
vpath intprops-internal.h $(srcdir)
|
||||
vpath intprops.h $(srcdir)
|
||||
vpath inttypes.in.h $(srcdir)
|
||||
vpath libc-config.h $(srcdir)
|
||||
vpath limits.in.h $(srcdir)
|
||||
vpath malloc/dynarray.h $(srcdir)
|
||||
vpath malloc/scratch_buffer.h $(srcdir)
|
||||
vpath md5.h $(srcdir)
|
||||
vpath min-max.h $(srcdir)
|
||||
vpath mini-gmp.h $(srcdir)
|
||||
vpath minmax.h $(srcdir)
|
||||
vpath mktime-internal.h $(srcdir)
|
||||
vpath nproc.h $(srcdir)
|
||||
vpath openat-priv.h $(srcdir)
|
||||
vpath openat.h $(srcdir)
|
||||
vpath pathmax.h $(srcdir)
|
||||
vpath regex.h $(srcdir)
|
||||
vpath regex_internal.h $(srcdir)
|
||||
vpath root-uid.h $(srcdir)
|
||||
vpath save-cwd.h $(srcdir)
|
||||
vpath scratch_buffer.h $(srcdir)
|
||||
vpath sha1.h $(srcdir)
|
||||
vpath sha256.h $(srcdir)
|
||||
vpath sha512.h $(srcdir)
|
||||
vpath sig2str.h $(srcdir)
|
||||
vpath signal.in.h $(srcdir)
|
||||
vpath stat-time.h $(srcdir)
|
||||
vpath stdalign.in.h $(srcdir)
|
||||
vpath stdckdint.in.h $(srcdir)
|
||||
vpath stddef.in.h $(srcdir)
|
||||
vpath stdint.in.h $(srcdir)
|
||||
vpath stdio-impl.h $(srcdir)
|
||||
vpath stdio.h $(srcdir)
|
||||
vpath stdio.in.h $(srcdir)
|
||||
vpath stdlib.in.h $(srcdir)
|
||||
vpath str-two-way.h $(srcdir)
|
||||
vpath strftime.h $(srcdir)
|
||||
vpath string.in.h $(srcdir)
|
||||
vpath sys_random.in.h $(srcdir)
|
||||
vpath sys_select.in.h $(srcdir)
|
||||
vpath sys_stat.in.h $(srcdir)
|
||||
vpath sys_time.in.h $(srcdir)
|
||||
vpath sys_types.in.h $(srcdir)
|
||||
vpath tempname.h $(srcdir)
|
||||
vpath time-internal.h $(srcdir)
|
||||
vpath time.in.h $(srcdir)
|
||||
vpath timespec.h $(srcdir)
|
||||
vpath u64.h $(srcdir)
|
||||
vpath unistd.in.h $(srcdir)
|
||||
vpath unlocked-io.h $(srcdir)
|
||||
vpath utimens.h $(srcdir)
|
||||
vpath verify.h $(srcdir)
|
||||
vpath vla.h $(srcdir)
|
||||
vpath warn-on-use.h $(srcdir)
|
||||
vpath xalloc-oversized.h $(srcdir)
|
||||
vpath %.c $(srcdir)
|
||||
endif
|
||||
|
||||
# Variables substituted by 'configure', and not autogenerated in gnulib.mk,
|
||||
# or needed before gnulib.mk is included.
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
|
@ -33,11 +157,11 @@ all:
|
|||
|
||||
HAVE_NATIVE_COMP = @HAVE_NATIVE_COMP@
|
||||
|
||||
ALL_CFLAGS= \
|
||||
ALL_CFLAGS = \
|
||||
$(C_SWITCH_SYSTEM) $(C_SWITCH_MACHINE) $(DEPFLAGS) \
|
||||
$(GNULIB_WARN_CFLAGS) $(WERROR_CFLAGS) $(PROFILING_CFLAGS) $(CFLAGS) \
|
||||
-I. -I../src -I$(srcdir) -I$(srcdir)/../src \
|
||||
$(if $(patsubst e-%,,$(notdir $<)),,-Demacs)
|
||||
$(if $(patsubst e-%,,$(notdir $<)),,-Demacs) $(ANDROID_CFLAGS)
|
||||
|
||||
ifeq ($(HAVE_NATIVE_COMP),yes)
|
||||
ALL_CFLAGS += -DGL_COMPILE_CRYPTO_STREAM
|
||||
|
@ -52,6 +176,12 @@ ifneq ($(SYSTEM_TYPE),windows-nt)
|
|||
libgnu_a_SOURCES += openat-die.c save-cwd.c
|
||||
endif
|
||||
|
||||
ifeq ($(XCONFIGURE),android)
|
||||
# The next line is necessary to override -I$(srcdir), which will end
|
||||
# up pulling in lots of headers from the host.
|
||||
ALL_CFLAGS += -I$(top_srcdir)/xcompile -I.
|
||||
endif
|
||||
|
||||
DEPDIR = deps
|
||||
ifeq ($(AUTO_DEPEND),yes)
|
||||
DEPFLAGS = -MMD -MF $(DEPDIR)/$*.d -MP
|
||||
|
@ -60,11 +190,14 @@ else
|
|||
DEPFLAGS =
|
||||
endif
|
||||
|
||||
# This piece of code interferes with cross compilation
|
||||
ifeq ($(XCONFIGURE),)
|
||||
.PRECIOUS: ../config.status Makefile
|
||||
../config.status: $(top_srcdir)/configure.ac $(top_srcdir)/m4/*.m4
|
||||
$(MAKE) -C .. $(notdir $@)
|
||||
Makefile: ../config.status $(srcdir)/Makefile.in
|
||||
$(MAKE) -C .. lib/$@
|
||||
endif
|
||||
|
||||
# Object modules that need not be built for Emacs.
|
||||
# Emacs does not need e-regex.o (it has its own regex-emacs.c),
|
||||
|
|
|
@ -43,7 +43,11 @@ orig_faccessat (int fd, char const *name, int mode, int flag)
|
|||
/* Write "unistd.h" here, not <unistd.h>, otherwise OSF/1 5.1 DTK cc
|
||||
eliminates this include because of the preliminary #include <unistd.h>
|
||||
above. */
|
||||
#ifdef __ANROID__
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include "unistd.h"
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ACCESS
|
||||
/* Mingw lacks access, but it also lacks real vs. effective ids, so
|
||||
|
|
|
@ -33,13 +33,15 @@
|
|||
size_t
|
||||
__fpending (FILE *fp)
|
||||
{
|
||||
#if defined __ANDROID__
|
||||
return 0;
|
||||
/* Most systems provide FILE as a struct and the necessary bitmask in
|
||||
<stdio.h>, because they need it for implementing getc() and putc() as
|
||||
fast macros. */
|
||||
#if defined _IO_EOF_SEEN || defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1
|
||||
#elif defined _IO_EOF_SEEN || defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1
|
||||
/* GNU libc, BeOS, Haiku, Linux libc5 */
|
||||
return fp->_IO_write_ptr - fp->_IO_write_base;
|
||||
#elif defined __sferror || defined __DragonFly__ || defined __ANDROID__
|
||||
#elif defined __sferror || defined __DragonFly__
|
||||
/* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin < 1.7.34, Minix 3, Android */
|
||||
return fp->_p - fp->_bf._base;
|
||||
#elif defined __EMX__ /* emx+gcc */
|
||||
|
|
|
@ -40,7 +40,11 @@ orig_open (const char *filename, int flags, mode_t mode)
|
|||
/* Specification. */
|
||||
/* Write "fcntl.h" here, not <fcntl.h>, otherwise OSF/1 5.1 DTK cc eliminates
|
||||
this include because of the preliminary #include <fcntl.h> above. */
|
||||
#ifdef __ANDROID__
|
||||
#include <fnctl.h>
|
||||
#else
|
||||
#include "fcntl.h"
|
||||
#endif
|
||||
|
||||
#include "cloexec.h"
|
||||
|
||||
|
|
|
@ -18,5 +18,5 @@
|
|||
#include <config.h>
|
||||
|
||||
#define _GL_UNISTD_INLINE _GL_EXTERN_INLINE
|
||||
#include "unistd.h"
|
||||
#include <unistd.h>
|
||||
typedef int dummy;
|
||||
|
|
|
@ -2137,7 +2137,8 @@ frames and several different fonts at once. This is true for displays
|
|||
that use a window system such as X, and false for text-only terminals.
|
||||
DISPLAY can be a display name, a frame, or nil (meaning the selected
|
||||
frame's display)."
|
||||
(not (null (memq (framep-on-display display) '(x w32 ns pgtk haiku)))))
|
||||
(not (null (memq (framep-on-display display) '(x w32 ns pgtk haiku
|
||||
android)))))
|
||||
|
||||
(defun display-images-p (&optional display)
|
||||
"Return non-nil if DISPLAY can display images.
|
||||
|
@ -2202,7 +2203,7 @@ DISPLAY should be either a frame or a display name (a string).
|
|||
If DISPLAY is omitted or nil, it defaults to the selected frame's display."
|
||||
(let ((frame-type (framep-on-display display)))
|
||||
(cond
|
||||
((memq frame-type '(x w32 ns haiku pgtk))
|
||||
((memq frame-type '(x w32 ns haiku pgtk android))
|
||||
(x-display-screens display))
|
||||
(t
|
||||
1))))
|
||||
|
@ -2222,7 +2223,7 @@ with DISPLAY. To get information for each physical monitor, use
|
|||
`display-monitor-attributes-list'."
|
||||
(let ((frame-type (framep-on-display display)))
|
||||
(cond
|
||||
((memq frame-type '(x w32 ns haiku pgtk))
|
||||
((memq frame-type '(x w32 ns haiku pgtk android))
|
||||
(x-display-pixel-height display))
|
||||
(t
|
||||
(frame-height (if (framep display) display (selected-frame)))))))
|
||||
|
@ -2242,7 +2243,7 @@ with DISPLAY. To get information for each physical monitor, use
|
|||
`display-monitor-attributes-list'."
|
||||
(let ((frame-type (framep-on-display display)))
|
||||
(cond
|
||||
((memq frame-type '(x w32 ns haiku pgtk))
|
||||
((memq frame-type '(x w32 ns haiku pgtk android))
|
||||
(x-display-pixel-width display))
|
||||
(t
|
||||
(frame-width (if (framep display) display (selected-frame)))))))
|
||||
|
@ -2280,7 +2281,7 @@ For graphical terminals, note that on \"multi-monitor\" setups this
|
|||
refers to the height in millimeters for all physical monitors
|
||||
associated with DISPLAY. To get information for each physical
|
||||
monitor, use `display-monitor-attributes-list'."
|
||||
(and (memq (framep-on-display display) '(x w32 ns haiku pgtk))
|
||||
(and (memq (framep-on-display display) '(x w32 ns haiku pgtk android))
|
||||
(or (cddr (assoc (or display (frame-parameter nil 'display))
|
||||
display-mm-dimensions-alist))
|
||||
(cddr (assoc t display-mm-dimensions-alist))
|
||||
|
@ -2301,7 +2302,7 @@ For graphical terminals, note that on \"multi-monitor\" setups this
|
|||
refers to the width in millimeters for all physical monitors
|
||||
associated with DISPLAY. To get information for each physical
|
||||
monitor, use `display-monitor-attributes-list'."
|
||||
(and (memq (framep-on-display display) '(x w32 ns haiku pgtk))
|
||||
(and (memq (framep-on-display display) '(x w32 ns haiku pgtk android))
|
||||
(or (cadr (assoc (or display (frame-parameter nil 'display))
|
||||
display-mm-dimensions-alist))
|
||||
(cadr (assoc t display-mm-dimensions-alist))
|
||||
|
@ -2319,7 +2320,7 @@ DISPLAY can be a display name or a frame.
|
|||
If DISPLAY is omitted or nil, it defaults to the selected frame's display."
|
||||
(let ((frame-type (framep-on-display display)))
|
||||
(cond
|
||||
((memq frame-type '(x w32 ns haiku pgtk))
|
||||
((memq frame-type '(x w32 ns haiku pgtk android))
|
||||
(x-display-backing-store display))
|
||||
(t
|
||||
'not-useful))))
|
||||
|
@ -2332,7 +2333,7 @@ DISPLAY can be a display name or a frame.
|
|||
If DISPLAY is omitted or nil, it defaults to the selected frame's display."
|
||||
(let ((frame-type (framep-on-display display)))
|
||||
(cond
|
||||
((memq frame-type '(x w32 ns haiku pgtk))
|
||||
((memq frame-type '(x w32 ns haiku pgtk android))
|
||||
(x-display-save-under display))
|
||||
(t
|
||||
'not-useful))))
|
||||
|
@ -2345,7 +2346,7 @@ DISPLAY can be a display name or a frame.
|
|||
If DISPLAY is omitted or nil, it defaults to the selected frame's display."
|
||||
(let ((frame-type (framep-on-display display)))
|
||||
(cond
|
||||
((memq frame-type '(x w32 ns haiku pgtk))
|
||||
((memq frame-type '(x w32 ns haiku pgtk android))
|
||||
(x-display-planes display))
|
||||
((eq frame-type 'pc)
|
||||
4)
|
||||
|
@ -2360,7 +2361,7 @@ DISPLAY can be a display name or a frame.
|
|||
If DISPLAY is omitted or nil, it defaults to the selected frame's display."
|
||||
(let ((frame-type (framep-on-display display)))
|
||||
(cond
|
||||
((memq frame-type '(x w32 ns haiku pgtk))
|
||||
((memq frame-type '(x w32 ns haiku pgtk android))
|
||||
(x-display-color-cells display))
|
||||
((eq frame-type 'pc)
|
||||
16)
|
||||
|
@ -2377,7 +2378,7 @@ DISPLAY can be a display name or a frame.
|
|||
If DISPLAY is omitted or nil, it defaults to the selected frame's display."
|
||||
(let ((frame-type (framep-on-display display)))
|
||||
(cond
|
||||
((memq frame-type '(x w32 ns haiku pgtk))
|
||||
((memq frame-type '(x w32 ns haiku pgtk android))
|
||||
(x-display-visual-class display))
|
||||
((and (memq frame-type '(pc t))
|
||||
(tty-display-color-p display))
|
||||
|
|
|
@ -432,6 +432,8 @@ See also `wallpaper-default-width'.")
|
|||
|
||||
;;; wallpaper-set
|
||||
|
||||
(declare-function x-open-connection "xfns.c")
|
||||
|
||||
(defun wallpaper--x-monitor-name ()
|
||||
"Get the monitor name for `wallpaper-set'.
|
||||
On a graphical display, try using the same monitor as the current
|
||||
|
|
|
@ -306,6 +306,11 @@
|
|||
(load "term/common-win")
|
||||
(load "term/haiku-win")))
|
||||
|
||||
(if (featurep 'android)
|
||||
(progn
|
||||
(load "term/common-win")
|
||||
(load "term/android-win")))
|
||||
|
||||
(if (or (eq system-type 'windows-nt)
|
||||
(featurep 'w32))
|
||||
(progn
|
||||
|
|
|
@ -240,7 +240,7 @@ parameter, and should return the (possibly) transformed URL."
|
|||
:version "29.1")
|
||||
|
||||
(defface eww-form-submit
|
||||
'((((type x w32 ns haiku pgtk) (class color)) ; Like default mode line
|
||||
'((((type x w32 ns haiku pgtk android) (class color)) ; Like default mode line
|
||||
:box (:line-width 2 :style released-button)
|
||||
:background "#808080" :foreground "black"))
|
||||
"Face for eww buffer buttons."
|
||||
|
@ -248,7 +248,7 @@ parameter, and should return the (possibly) transformed URL."
|
|||
:group 'eww)
|
||||
|
||||
(defface eww-form-file
|
||||
'((((type x w32 ns haiku pgtk) (class color)) ; Like default mode line
|
||||
'((((type x w32 ns haiku pgtk android) (class color)) ; Like default mode line
|
||||
:box (:line-width 2 :style released-button)
|
||||
:background "#808080" :foreground "black"))
|
||||
"Face for eww buffer buttons."
|
||||
|
@ -256,7 +256,7 @@ parameter, and should return the (possibly) transformed URL."
|
|||
:group 'eww)
|
||||
|
||||
(defface eww-form-checkbox
|
||||
'((((type x w32 ns haiku pgtk) (class color)) ; Like default mode line
|
||||
'((((type x w32 ns haiku pgtk android) (class color)) ; Like default mode line
|
||||
:box (:line-width 2 :style released-button)
|
||||
:background "lightgrey" :foreground "black"))
|
||||
"Face for eww buffer buttons."
|
||||
|
@ -264,7 +264,7 @@ parameter, and should return the (possibly) transformed URL."
|
|||
:group 'eww)
|
||||
|
||||
(defface eww-form-select
|
||||
'((((type x w32 ns haiku pgtk) (class color)) ; Like default mode line
|
||||
'((((type x w32 ns haiku pgtk android) (class color)) ; Like default mode line
|
||||
:box (:line-width 2 :style released-button)
|
||||
:background "lightgrey" :foreground "black"))
|
||||
"Face for eww buffer buttons."
|
||||
|
|
62
lisp/term/android-win.el
Normal file
62
lisp/term/android-win.el
Normal file
|
@ -0,0 +1,62 @@
|
|||
;;; x-win.el --- parse relevant switches and set up for Android -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: FSF
|
||||
;; Keywords: terminals, i18n, android
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file contains the support for initializing the Lisp side of
|
||||
;; Android windowing.
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
||||
(unless (featurep 'android)
|
||||
(error "%s: Loading android-win without having Android"
|
||||
invocation-name))
|
||||
|
||||
;; Documentation-purposes only: actually loaded in loadup.el.
|
||||
(require 'frame)
|
||||
(require 'mouse)
|
||||
(require 'fontset)
|
||||
(require 'dnd)
|
||||
|
||||
(add-to-list 'display-format-alist '(".*" . android))
|
||||
|
||||
;; Window system initialization. This is extremely simple because all
|
||||
;; initialization is done in android_term_init.
|
||||
|
||||
(cl-defmethod window-system-initialization (&context (window-system android)
|
||||
&optional _ignored)
|
||||
"Set up the window system. WINDOW-SYSTEM must be ANDROID.
|
||||
DISPLAY is ignored on Android."
|
||||
;; Just make sure the window system was initialized at startup.
|
||||
(android-get-connection))
|
||||
|
||||
(cl-defmethod frame-creation-function (params &context (window-system android))
|
||||
(x-create-frame-with-faces params))
|
||||
|
||||
(cl-defmethod handle-args-function (_ignored &context (window-system android))
|
||||
;; Nothing to do here: Android has no command line to provide
|
||||
;; arguments on.
|
||||
(ignore))
|
||||
|
||||
(provide 'android-win)
|
||||
;; android-win.el ends here.
|
|
@ -33,6 +33,16 @@ top_builddir = @top_builddir@
|
|||
# MinGW CPPFLAGS may use this.
|
||||
abs_top_srcdir=@abs_top_srcdir@
|
||||
VPATH = $(srcdir)
|
||||
|
||||
# This is not empty if this is a Makefile that will be copied to
|
||||
# xcompile/src.
|
||||
XCONFIGURE = @XCONFIGURE@
|
||||
|
||||
ifneq ($(XCONFIGURE),)
|
||||
vpath %.c := $(srcdir)
|
||||
vpath %.h := $(srcdir)
|
||||
endif
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
CFLAGS = @CFLAGS@
|
||||
|
@ -48,6 +58,7 @@ LIBOBJS = @LIBOBJS@
|
|||
|
||||
lispsource = $(top_srcdir)/lisp
|
||||
lib = ../lib
|
||||
hostlib = $(top_builddir)/lib
|
||||
libsrc = ../lib-src
|
||||
etc = ../etc
|
||||
oldXMenudir = ../oldXMenu
|
||||
|
@ -326,7 +337,7 @@ W32_RES_LINK=@W32_RES_LINK@
|
|||
## if HAVE_HARFBUZZ, hbfont.o is added regardless of the rest
|
||||
FONT_OBJ=@FONT_OBJ@
|
||||
|
||||
## Empty for MinGW, cm.o for the rest.
|
||||
## Empty for MinGW and Android, cm.o for the rest.
|
||||
CM_OBJ=@CM_OBJ@
|
||||
|
||||
LIBGPM = @LIBGPM@
|
||||
|
@ -370,6 +381,10 @@ HAIKU_CXX_OBJ = @HAIKU_CXX_OBJ@
|
|||
HAIKU_LIBS = @HAIKU_LIBS@
|
||||
HAIKU_CFLAGS = @HAIKU_CFLAGS@
|
||||
|
||||
ANDROID_OBJ = @ANDROID_OBJ@
|
||||
ANDROID_LIBS = @ANDROID_LIBS@
|
||||
ANDROID_CFLAGS = @ANDROID_CFLAGS@
|
||||
|
||||
DUMPING=@DUMPING@
|
||||
CHECK_STRUCTS = @CHECK_STRUCTS@
|
||||
HAVE_PDUMPER = @HAVE_PDUMPER@
|
||||
|
@ -411,7 +426,8 @@ EMACS_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
|
|||
$(HARFBUZZ_CFLAGS) $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
|
||||
$(LIBSYSTEMD_CFLAGS) $(JSON_CFLAGS) $(XSYNC_CFLAGS) $(TREE_SITTER_CFLAGS) \
|
||||
$(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
|
||||
$(WERROR_CFLAGS) $(HAIKU_CFLAGS) $(XCOMPOSITE_CFLAGS) $(XSHAPE_CFLAGS)
|
||||
$(WERROR_CFLAGS) $(HAIKU_CFLAGS) $(XCOMPOSITE_CFLAGS) $(XSHAPE_CFLAGS) \
|
||||
$(ANDROID_CFLAGS)
|
||||
ALL_CFLAGS = $(EMACS_CFLAGS) $(WARN_CFLAGS) $(CFLAGS)
|
||||
ALL_OBJC_CFLAGS = $(EMACS_CFLAGS) \
|
||||
$(filter-out $(NON_OBJC_CFLAGS),$(WARN_CFLAGS)) $(CFLAGS) \
|
||||
|
@ -449,7 +465,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
|
|||
$(if $(HYBRID_MALLOC),sheap.o) \
|
||||
$(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
|
||||
$(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) $(JSON_OBJ) \
|
||||
$(HAIKU_OBJ) $(PGTK_OBJ)
|
||||
$(HAIKU_OBJ) $(PGTK_OBJ) $(ANDROID_OBJ)
|
||||
doc_obj = $(base_obj) $(NS_OBJC_OBJ)
|
||||
obj = $(doc_obj) $(HAIKU_CXX_OBJ)
|
||||
|
||||
|
@ -466,7 +482,8 @@ SOME_MACHINE_OBJECTS = dosfns.o msdos.o \
|
|||
w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o \
|
||||
w16select.o widget.o xfont.o ftfont.o xftfont.o gtkutil.o \
|
||||
xsettings.o xgselect.o termcap.o hbfont.o \
|
||||
haikuterm.o haikufns.o haikumenu.o haikufont.o
|
||||
haikuterm.o haikufns.o haikumenu.o haikufont.o androidterm.o androidfns.o \
|
||||
androidfont.o
|
||||
|
||||
## gmalloc.o if !SYSTEM_MALLOC && !DOUG_LEA_MALLOC, else empty.
|
||||
GMALLOC_OBJ=@GMALLOC_OBJ@
|
||||
|
@ -569,7 +586,8 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(PGTK_LIBS) $(LIBX_BASE) $(LIBIMAGE
|
|||
$(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(GETADDRINFO_A_LIBS) $(LCMS2_LIBS) \
|
||||
$(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) $(LIBSYSTEMD_LIBS) \
|
||||
$(JSON_LIBS) $(LIBGMP) $(LIBGCCJIT_LIBS) $(XINPUT_LIBS) $(HAIKU_LIBS) \
|
||||
$(TREE_SITTER_LIBS) $(SQLITE3_LIBS) $(XCOMPOSITE_LIBS) $(XSHAPE_LIBS)
|
||||
$(TREE_SITTER_LIBS) $(SQLITE3_LIBS) $(XCOMPOSITE_LIBS) $(XSHAPE_LIBS) \
|
||||
$(ANDROID_LIBS)
|
||||
|
||||
## FORCE it so that admin/unidata can decide whether this file is
|
||||
## up-to-date. Although since charprop depends on bootstrap-emacs,
|
||||
|
@ -658,7 +676,7 @@ $(etc)/DOC: $(libsrc)/make-docfile$(EXEEXT) $(doc_obj)
|
|||
$(SOME_MACHINE_OBJECTS) $(doc_obj) > $(etc)/DOC
|
||||
|
||||
$(libsrc)/make-docfile$(EXEEXT) $(libsrc)/make-fingerprint$(EXEEXT): \
|
||||
$(lib)/libgnu.a
|
||||
$(hostlib)/libgnu.a
|
||||
$(MAKE) -C $(dir $@) $(notdir $@)
|
||||
|
||||
buildobj.h: Makefile
|
||||
|
@ -719,6 +737,27 @@ ifeq ($(DUMPING),unexec)
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(XCONFIGURE),android)
|
||||
## The Android package internally links to and communicates with a
|
||||
## shared library named `libemacs.so' at startup. This is built
|
||||
## almost the same way temacs is. But it is position independent. It
|
||||
## is not dumped here. Instead, it dumps itself the first time it
|
||||
## starts on the user's device.
|
||||
|
||||
libemacs.so: $(ALLOBJS) $(LIBEGNU_ARCHIVE) $(EMACSRES) \
|
||||
$(MAKE_PDUMPER_FINGERPRINT)
|
||||
$(AM_V_CCLD)$(CC) -o $@ $(ALL_CFLAGS) $(TEMACS_LDFLAGS) \
|
||||
$(LDFLAGS) -shared $(ALLOBJS) $(LIBEGNU_ARCHIVE) $(LIBES)
|
||||
$(AM_V_at)$(MAKE_PDUMPER_FINGERPRINT) $@
|
||||
|
||||
# There is also a binary named `android-emacs' which simply calls
|
||||
# emacs.so.
|
||||
|
||||
android-emacs: libemacs.so android-emacs.o
|
||||
$(AM_V_CCLD)$(CC) -o $@ $(ALL_CFLAGS) $(LDFLAGS) \
|
||||
-L. "-l:libemacs.so" android-emacs.o
|
||||
endif
|
||||
|
||||
## The following oldxmenu-related rules are only (possibly) used if
|
||||
## HAVE_X11 && !USE_GTK, but there is no harm in always defining them.
|
||||
$(lwlibdir)/liblw.a: $(config_h) globals.h lisp.h FORCE
|
||||
|
@ -747,6 +786,7 @@ ns-app: emacs$(EXEEXT) $(pdmp)
|
|||
.PHONY: versionclean
|
||||
|
||||
mostlyclean:
|
||||
rm -f aemacs emacs.so
|
||||
rm -f temacs$(EXEEXT) core ./*.core \#* ./*.o
|
||||
rm -f dmpstruct.h
|
||||
rm -f emacs.pdmp
|
||||
|
|
12
src/alloc.c
12
src/alloc.c
|
@ -3342,6 +3342,14 @@ cleanup_vector (struct Lisp_Vector *vector)
|
|||
drv->close_font (font);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
|
||||
/* The Android font driver needs the ability to associate extra
|
||||
information with font entities. */
|
||||
if ((vector->header.size & PSEUDOVECTOR_SIZE_MASK)
|
||||
== FONT_ENTITY_MAX)
|
||||
android_finalize_font_entity (PSEUDOVEC_STRUCT (vector, font_entity));
|
||||
#endif
|
||||
}
|
||||
else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_THREAD))
|
||||
finalize_one_thread (PSEUDOVEC_STRUCT (vector, thread_state));
|
||||
|
@ -6467,6 +6475,10 @@ garbage_collect (void)
|
|||
mark_xselect ();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
mark_androidterm ();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NS
|
||||
mark_nsterm ();
|
||||
#endif
|
||||
|
|
30
src/android-emacs.c
Normal file
30
src/android-emacs.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* Android initialization for GNU Emacs.
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
#include "android.h"
|
||||
|
||||
/* android-emacs is a wrapper around libemacs. It simply calls
|
||||
android_emacs_init with the argv and argc given to it. */
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
return android_emacs_init (argc, argv);
|
||||
}
|
2335
src/android.c
Normal file
2335
src/android.c
Normal file
File diff suppressed because it is too large
Load diff
70
src/android.h
Normal file
70
src/android.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* Android initialization for GNU Emacs.
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* On Android, Emacs is built as a shared library loaded from Java
|
||||
using the Java Native Interface. Emacs's `main' function is
|
||||
renamed `android_emacs_init', and runs with some modifications
|
||||
inside a separate thread, communicating with the Java code through
|
||||
a table of function pointers. */
|
||||
|
||||
#ifndef _ANDROID_H_
|
||||
#ifndef ANDROID_STUBIFY
|
||||
#include <jni.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
/* This must be used in every symbol declaration to export it to the
|
||||
JNI Emacs wrapper. */
|
||||
#define ANDROID_EXPORT __attribute__ ((visibility ("default")))
|
||||
|
||||
extern bool ANDROID_EXPORT android_init_gui;
|
||||
extern int ANDROID_EXPORT android_emacs_init (int, char **);
|
||||
|
||||
#ifndef ANDROID_STUBIFY
|
||||
|
||||
extern int android_select (int, fd_set *, fd_set *, fd_set *,
|
||||
struct timespec *, const sigset_t *);
|
||||
|
||||
extern bool android_file_access_p (const char *, int);
|
||||
extern int android_open (const char *, int, int);
|
||||
extern char *android_user_full_name (struct passwd *);
|
||||
extern int android_fstat (int, struct stat *);
|
||||
extern int android_fstatat (int, const char *restrict,
|
||||
struct stat *restrict, int);
|
||||
extern int android_close (int);
|
||||
|
||||
#endif
|
||||
|
||||
/* JNI functions should not be built when Emacs is stubbed out for the
|
||||
build. These should be documented in EmacsNative.java. */
|
||||
|
||||
#ifndef ANDROID_STUBIFY
|
||||
#include <jni.h>
|
||||
|
||||
extern JNIEnv *android_java_env;
|
||||
|
||||
#define ANDROID_DELETE_LOCAL_REF(ref) \
|
||||
((*android_java_env)->DeleteLocalRef (android_java_env, \
|
||||
(ref)))
|
||||
|
||||
#define NATIVE_NAME(name) Java_org_gnu_emacs_EmacsNative_##name
|
||||
|
||||
#endif
|
||||
#endif /* _ANDROID_H_ */
|
1779
src/androidfns.c
Normal file
1779
src/androidfns.c
Normal file
File diff suppressed because it is too large
Load diff
955
src/androidfont.c
Normal file
955
src/androidfont.c
Normal file
|
@ -0,0 +1,955 @@
|
|||
/* Communication module for Android terminals.
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "lisp.h"
|
||||
#include "dispextern.h"
|
||||
#include "composite.h"
|
||||
#include "blockinput.h"
|
||||
#include "charset.h"
|
||||
#include "frame.h"
|
||||
#include "window.h"
|
||||
#include "fontset.h"
|
||||
#include "androidterm.h"
|
||||
#include "character.h"
|
||||
#include "coding.h"
|
||||
#include "font.h"
|
||||
#include "termchar.h"
|
||||
#include "pdumper.h"
|
||||
#include "android.h"
|
||||
|
||||
#ifndef ANDROID_STUBIFY
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
struct android_emacs_font_driver
|
||||
{
|
||||
jclass class;
|
||||
jmethodID list;
|
||||
jmethodID match;
|
||||
jmethodID list_families;
|
||||
jmethodID open_font;
|
||||
jmethodID has_char;
|
||||
jmethodID text_extents;
|
||||
jmethodID encode_char;
|
||||
|
||||
/* Static methods. */
|
||||
jmethodID create_font_driver;
|
||||
};
|
||||
|
||||
struct android_emacs_font_spec
|
||||
{
|
||||
jclass class;
|
||||
jfieldID foundry;
|
||||
jfieldID family;
|
||||
jfieldID adstyle;
|
||||
jfieldID registry;
|
||||
jfieldID width;
|
||||
jfieldID weight;
|
||||
jfieldID slant;
|
||||
jfieldID size;
|
||||
jfieldID spacing;
|
||||
jfieldID avgwidth;
|
||||
};
|
||||
|
||||
struct android_emacs_font_metrics
|
||||
{
|
||||
jclass class;
|
||||
jfieldID lbearing;
|
||||
jfieldID rbearing;
|
||||
jfieldID width;
|
||||
jfieldID ascent;
|
||||
jfieldID descent;
|
||||
};
|
||||
|
||||
struct android_emacs_font_object
|
||||
{
|
||||
jclass class;
|
||||
jfieldID min_width;
|
||||
jfieldID max_width;
|
||||
jfieldID pixel_size;
|
||||
jfieldID height;
|
||||
jfieldID space_width;
|
||||
jfieldID average_width;
|
||||
jfieldID ascent;
|
||||
jfieldID descent;
|
||||
jfieldID underline_thickness;
|
||||
jfieldID underline_position;
|
||||
jfieldID baseline_offset;
|
||||
jfieldID relative_compose;
|
||||
jfieldID default_ascent;
|
||||
jfieldID encoding_charset;
|
||||
jfieldID repertory_charset;
|
||||
};
|
||||
|
||||
struct android_integer
|
||||
{
|
||||
jclass class;
|
||||
jmethodID constructor;
|
||||
jmethodID int_value;
|
||||
};
|
||||
|
||||
struct androidfont_info
|
||||
{
|
||||
/* The font pseudo-vector object. */
|
||||
struct font font;
|
||||
|
||||
/* The Java-side font. */
|
||||
jobject object;
|
||||
};
|
||||
|
||||
struct androidfont_entity
|
||||
{
|
||||
/* The font entity pvec. */
|
||||
struct font_entity font;
|
||||
|
||||
/* The Java-side font entity. */
|
||||
jobject object;
|
||||
};
|
||||
|
||||
/* Method and class identifiers associated with the EmacsFontDriver
|
||||
class. */
|
||||
|
||||
struct android_emacs_font_driver font_driver_class;
|
||||
|
||||
/* Field and class identifiers associated with the
|
||||
EmacsFontDriver$FontSpec class. */
|
||||
|
||||
struct android_emacs_font_spec font_spec_class;
|
||||
|
||||
/* Method and class identifiers associated with the Integer class. */
|
||||
|
||||
struct android_integer integer_class;
|
||||
|
||||
/* Field and class identifiers associated with the
|
||||
EmacsFontDriver$FontMetrics class. */
|
||||
|
||||
struct android_emacs_font_metrics font_metrics_class;
|
||||
|
||||
/* Field and class identifiers associated with the
|
||||
EmacsFontDriver$FontObject class. */
|
||||
|
||||
struct android_emacs_font_object font_object_class;
|
||||
|
||||
/* The font cache. */
|
||||
|
||||
static Lisp_Object font_cache;
|
||||
|
||||
/* The Java-side font driver. */
|
||||
|
||||
static jobject font_driver;
|
||||
|
||||
|
||||
|
||||
/* Initialize the class and method identifiers for functions in the
|
||||
EmacsFontDriver class, and place them in `font_driver_class'. */
|
||||
|
||||
static void
|
||||
android_init_font_driver (void)
|
||||
{
|
||||
jclass old;
|
||||
|
||||
font_driver_class.class
|
||||
= (*android_java_env)->FindClass (android_java_env,
|
||||
"org/gnu/emacs/EmacsFontDriver");
|
||||
eassert (font_driver_class.class);
|
||||
|
||||
old = font_driver_class.class;
|
||||
font_driver_class.class
|
||||
= (jclass) (*android_java_env)->NewGlobalRef (android_java_env,
|
||||
(jobject) old);
|
||||
ANDROID_DELETE_LOCAL_REF (old);
|
||||
|
||||
if (!font_driver_class.class)
|
||||
emacs_abort ();
|
||||
|
||||
#define FIND_METHOD(c_name, name, signature) \
|
||||
font_driver_class.c_name \
|
||||
= (*android_java_env)->GetMethodID (android_java_env, \
|
||||
font_driver_class.class, \
|
||||
name, signature); \
|
||||
eassert (font_driver_class.c_name);
|
||||
|
||||
FIND_METHOD (list, "list", "(Lorg/gnu/emacs/EmacsFontDriver$FontSpec;)"
|
||||
"[Lorg/gnu/emacs/EmacsFontDriver$FontEntity;");
|
||||
FIND_METHOD (match, "match", "(Lorg/gnu/emacs/EmacsFontDriver$FontSpec;)"
|
||||
"Lorg/gnu/emacs/EmacsFontDriver$FontEntity;");
|
||||
FIND_METHOD (list_families, "listFamilies", "()[Ljava/lang/String;");
|
||||
FIND_METHOD (open_font, "openFont", "(Lorg/gnu/emacs/EmacsFontDriver$Font"
|
||||
"Entity;I)Lorg/gnu/emacs/EmacsFontDriver$FontObject;");
|
||||
FIND_METHOD (has_char, "hasChar", "(Lorg/gnu/emacs/EmacsFontDriver$Font"
|
||||
"Spec;C)I");
|
||||
FIND_METHOD (text_extents, "textExtents", "(Lorg/gnu/emacs/EmacsFontDriver"
|
||||
"$FontObject;[I[Lorg/gnu/emacs/EmacsFontDriver$FontMetrics;)V");
|
||||
FIND_METHOD (encode_char, "encodeChar", "(Lorg/gnu/emacs/EmacsFontDriver"
|
||||
"$FontObject;C)I");
|
||||
|
||||
font_driver_class.create_font_driver
|
||||
= (*android_java_env)->GetStaticMethodID (android_java_env,
|
||||
font_driver_class.class,
|
||||
"createFontDriver",
|
||||
"()Lorg/gnu/emacs/"
|
||||
"EmacsFontDriver;");
|
||||
eassert (font_driver_class.create_font_driver);
|
||||
#undef FIND_METHOD
|
||||
}
|
||||
|
||||
/* Initialize the class and field identifiers for functions in the
|
||||
EmacsFontDriver$FontSpec class, and place them in
|
||||
`font_spec_class'. */
|
||||
|
||||
static void
|
||||
android_init_font_spec (void)
|
||||
{
|
||||
jclass old;
|
||||
|
||||
font_spec_class.class
|
||||
= (*android_java_env)->FindClass (android_java_env,
|
||||
"org/gnu/emacs/EmacsFontDriver"
|
||||
"$FontSpec");
|
||||
eassert (font_spec_class.class);
|
||||
|
||||
old = font_spec_class.class;
|
||||
font_spec_class.class
|
||||
= (jclass) (*android_java_env)->NewGlobalRef (android_java_env,
|
||||
(jobject) old);
|
||||
ANDROID_DELETE_LOCAL_REF (old);
|
||||
|
||||
if (!font_spec_class.class)
|
||||
emacs_abort ();
|
||||
|
||||
#define FIND_FIELD(c_name, name, signature) \
|
||||
font_spec_class.c_name \
|
||||
= (*android_java_env)->GetFieldID (android_java_env, \
|
||||
font_spec_class.class, \
|
||||
name, signature); \
|
||||
eassert (font_spec_class.c_name);
|
||||
|
||||
FIND_FIELD (foundry, "foundry", "Ljava/lang/String;");
|
||||
FIND_FIELD (family, "family", "Ljava/lang/String;");
|
||||
FIND_FIELD (adstyle, "adstyle", "Ljava/lang/String;");
|
||||
FIND_FIELD (registry, "registry", "Ljava/lang/String;");
|
||||
FIND_FIELD (width, "width", "Ljava/lang/Integer;");
|
||||
FIND_FIELD (weight, "weight", "Ljava/lang/Integer;");
|
||||
FIND_FIELD (slant, "slant", "Ljava/lang/Integer;");
|
||||
FIND_FIELD (size, "size", "Ljava/lang/Integer;");
|
||||
FIND_FIELD (spacing, "spacing", "Ljava/lang/Integer;");
|
||||
FIND_FIELD (avgwidth, "avgwidth", "Ljava/lang/Integer;");
|
||||
#undef FIND_FIELD
|
||||
}
|
||||
|
||||
static void
|
||||
android_init_font_metrics (void)
|
||||
{
|
||||
jclass old;
|
||||
|
||||
font_metrics_class.class
|
||||
= (*android_java_env)->FindClass (android_java_env,
|
||||
"org/gnu/emacs/EmacsFontDriver"
|
||||
"$FontMetrics");
|
||||
eassert (font_metrics_class.class);
|
||||
|
||||
old = font_metrics_class.class;
|
||||
font_metrics_class.class
|
||||
= (jclass) (*android_java_env)->NewGlobalRef (android_java_env,
|
||||
(jobject) old);
|
||||
ANDROID_DELETE_LOCAL_REF (old);
|
||||
|
||||
if (!font_metrics_class.class)
|
||||
emacs_abort ();
|
||||
|
||||
#define FIND_FIELD(c_name, name, signature) \
|
||||
font_metrics_class.c_name \
|
||||
= (*android_java_env)->GetFieldID (android_java_env, \
|
||||
font_metrics_class.class, \
|
||||
name, signature); \
|
||||
eassert (font_metrics_class.c_name);
|
||||
|
||||
FIND_FIELD (lbearing, "lbearing", "S");
|
||||
FIND_FIELD (rbearing, "rbearing", "S");
|
||||
FIND_FIELD (width, "width", "S");
|
||||
FIND_FIELD (ascent, "ascent", "S");
|
||||
FIND_FIELD (descent, "descent", "S");
|
||||
#undef FIND_FIELD
|
||||
}
|
||||
|
||||
static void
|
||||
android_init_integer (void)
|
||||
{
|
||||
jclass old;
|
||||
|
||||
integer_class.class
|
||||
= (*android_java_env)->FindClass (android_java_env,
|
||||
"java/lang/Integer");
|
||||
eassert (integer_class.class);
|
||||
|
||||
old = integer_class.class;
|
||||
integer_class.class
|
||||
= (jclass) (*android_java_env)->NewGlobalRef (android_java_env,
|
||||
(jobject) old);
|
||||
ANDROID_DELETE_LOCAL_REF (old);
|
||||
|
||||
if (!integer_class.class)
|
||||
emacs_abort ();
|
||||
|
||||
#define FIND_METHOD(c_name, name, signature) \
|
||||
integer_class.c_name \
|
||||
= (*android_java_env)->GetMethodID (android_java_env, \
|
||||
integer_class.class, \
|
||||
name, signature); \
|
||||
eassert (integer_class.c_name);
|
||||
|
||||
FIND_METHOD (constructor, "<init>", "(I)V");
|
||||
FIND_METHOD (int_value, "intValue", "()I");
|
||||
#undef FIND_METHOD
|
||||
}
|
||||
|
||||
static void
|
||||
android_init_font_object (void)
|
||||
{
|
||||
jclass old;
|
||||
|
||||
font_object_class.class
|
||||
= (*android_java_env)->FindClass (android_java_env,
|
||||
"org/gnu/emacs/EmacsFontDriver"
|
||||
"$FontObject");
|
||||
eassert (font_object_class.class);
|
||||
|
||||
old = font_object_class.class;
|
||||
font_object_class.class
|
||||
= (jclass) (*android_java_env)->NewGlobalRef (android_java_env,
|
||||
(jobject) old);
|
||||
ANDROID_DELETE_LOCAL_REF (old);
|
||||
|
||||
if (!font_object_class.class)
|
||||
emacs_abort ();
|
||||
|
||||
#define FIND_FIELD(c_name, name, signature) \
|
||||
font_object_class.c_name \
|
||||
= (*android_java_env)->GetFieldID (android_java_env, \
|
||||
font_object_class.class, \
|
||||
name, signature); \
|
||||
eassert (font_object_class.c_name);
|
||||
|
||||
FIND_FIELD (min_width, "minWidth", "I");
|
||||
FIND_FIELD (max_width, "maxWidth", "I");
|
||||
FIND_FIELD (pixel_size, "pixelSize", "I");
|
||||
FIND_FIELD (height, "height", "I");
|
||||
FIND_FIELD (space_width, "spaceWidth", "I");
|
||||
FIND_FIELD (average_width, "averageWidth", "I");
|
||||
FIND_FIELD (ascent, "ascent", "I");
|
||||
FIND_FIELD (descent, "descent", "I");
|
||||
FIND_FIELD (underline_thickness, "underlineThickness", "I");
|
||||
FIND_FIELD (underline_position, "underlinePosition", "I");
|
||||
FIND_FIELD (baseline_offset, "baselineOffset", "I");
|
||||
FIND_FIELD (relative_compose, "relativeCompose", "I");
|
||||
FIND_FIELD (default_ascent, "defaultAscent", "I");
|
||||
FIND_FIELD (encoding_charset, "encodingCharset", "I");
|
||||
FIND_FIELD (repertory_charset, "repertoryCharset", "I");
|
||||
#undef FIND_FIELD
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
androidfont_get_cache (struct frame *frame)
|
||||
{
|
||||
return font_cache;
|
||||
}
|
||||
|
||||
/* Return a local reference to an instance of EmacsFontDriver$FontSpec
|
||||
with the same values as FONT. */
|
||||
|
||||
static jobject
|
||||
androidfont_from_lisp (Lisp_Object font)
|
||||
{
|
||||
jobject spec, integer;
|
||||
jstring string;
|
||||
Lisp_Object tem;
|
||||
|
||||
spec = (*android_java_env)->AllocObject (android_java_env,
|
||||
font_spec_class.class);
|
||||
|
||||
if (!spec)
|
||||
{
|
||||
(*android_java_env)->ExceptionClear (android_java_env);
|
||||
memory_full (0);
|
||||
}
|
||||
|
||||
#define DO_SYMBOL_FIELD(field, index) \
|
||||
tem = AREF (font, index); \
|
||||
if (SYMBOLP (tem)) \
|
||||
{ \
|
||||
/* Java seems to DTRT with the Emacs string encoding, so this does \
|
||||
not matter at all. */ \
|
||||
string = (*android_java_env)->NewStringUTF (android_java_env, \
|
||||
SSDATA (SYMBOL_NAME (tem))); \
|
||||
if (!string) \
|
||||
{ \
|
||||
(*android_java_env)->ExceptionClear (android_java_env); \
|
||||
memory_full (0); \
|
||||
} \
|
||||
\
|
||||
(*android_java_env)->SetObjectField (android_java_env, spec, \
|
||||
font_spec_class.field, \
|
||||
string); \
|
||||
ANDROID_DELETE_LOCAL_REF (string); \
|
||||
} \
|
||||
|
||||
DO_SYMBOL_FIELD (foundry, FONT_FOUNDRY_INDEX);
|
||||
DO_SYMBOL_FIELD (family, FONT_FAMILY_INDEX);
|
||||
DO_SYMBOL_FIELD (adstyle, FONT_ADSTYLE_INDEX);
|
||||
DO_SYMBOL_FIELD (registry, FONT_REGISTRY_INDEX);
|
||||
|
||||
#undef DO_SYMBOL_FIELD
|
||||
|
||||
#define DO_CARDINAL_FIELD(field, value) \
|
||||
if (value != -1) \
|
||||
{ \
|
||||
integer = (*android_java_env)->NewObject (android_java_env, \
|
||||
integer_class.class, \
|
||||
integer_class.constructor, \
|
||||
(jint) value); \
|
||||
if (!integer) \
|
||||
{ \
|
||||
(*android_java_env)->ExceptionClear (android_java_env); \
|
||||
memory_full (0); \
|
||||
} \
|
||||
\
|
||||
(*android_java_env)->SetObjectField (android_java_env, spec, \
|
||||
font_spec_class.field, \
|
||||
integer); \
|
||||
ANDROID_DELETE_LOCAL_REF (integer); \
|
||||
}
|
||||
|
||||
DO_CARDINAL_FIELD (width, FONT_WIDTH_NUMERIC (font));
|
||||
DO_CARDINAL_FIELD (weight, FONT_WEIGHT_NUMERIC (font));
|
||||
DO_CARDINAL_FIELD (slant, FONT_SLANT_NUMERIC (font));
|
||||
DO_CARDINAL_FIELD (size, (FIXNUMP (AREF (font, FONT_SIZE_INDEX))
|
||||
? XFIXNUM (AREF (font, FONT_SIZE_INDEX))
|
||||
: -1));
|
||||
DO_CARDINAL_FIELD (spacing, (FIXNUMP (AREF (font, FONT_SPACING_INDEX))
|
||||
? XFIXNUM (AREF (font, FONT_SPACING_INDEX))
|
||||
: -1));
|
||||
DO_CARDINAL_FIELD (avgwidth, (FIXNUMP (AREF (font, FONT_AVGWIDTH_INDEX))
|
||||
? XFIXNUM (AREF (font, FONT_AVGWIDTH_INDEX))
|
||||
: -1));
|
||||
|
||||
#undef DO_CARDINAL_FIELD
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
static void
|
||||
androidfont_from_java (jobject spec, Lisp_Object entity)
|
||||
{
|
||||
jobject tem;
|
||||
jint value;
|
||||
const char *string;
|
||||
|
||||
#define DO_SYMBOL_FIELD(field, index) \
|
||||
tem = (*android_java_env)->GetObjectField (android_java_env, \
|
||||
spec, \
|
||||
font_spec_class.field); \
|
||||
if (tem) \
|
||||
{ \
|
||||
string = (*android_java_env)->GetStringUTFChars (android_java_env, \
|
||||
tem, NULL); \
|
||||
if (!string) \
|
||||
memory_full (0); \
|
||||
ASET (entity, index, intern (string)); \
|
||||
(*android_java_env)->ReleaseStringUTFChars (android_java_env, \
|
||||
tem, string); \
|
||||
ANDROID_DELETE_LOCAL_REF (tem); \
|
||||
}
|
||||
|
||||
DO_SYMBOL_FIELD (foundry, FONT_FOUNDRY_INDEX);
|
||||
DO_SYMBOL_FIELD (family, FONT_FAMILY_INDEX);
|
||||
DO_SYMBOL_FIELD (adstyle, FONT_ADSTYLE_INDEX);
|
||||
DO_SYMBOL_FIELD (registry, FONT_REGISTRY_INDEX);
|
||||
|
||||
#undef DO_SYMBOL_FIELD
|
||||
#define DO_CARDINAL_FIELD(field, index, is_style) \
|
||||
tem = (*android_java_env)->GetObjectField (android_java_env, \
|
||||
spec, \
|
||||
font_spec_class.field); \
|
||||
if (tem) \
|
||||
{ \
|
||||
value \
|
||||
= (*android_java_env)->CallIntMethod (android_java_env, \
|
||||
tem, \
|
||||
integer_class.int_value); \
|
||||
if (!is_style) \
|
||||
ASET (entity, index, make_fixnum (value)); \
|
||||
else \
|
||||
FONT_SET_STYLE (entity, index, make_fixnum (value)); \
|
||||
ANDROID_DELETE_LOCAL_REF (tem); \
|
||||
}
|
||||
|
||||
DO_CARDINAL_FIELD (width, FONT_WIDTH_INDEX, true);
|
||||
DO_CARDINAL_FIELD (weight, FONT_WEIGHT_INDEX, true);
|
||||
DO_CARDINAL_FIELD (slant, FONT_SLANT_INDEX, true);
|
||||
DO_CARDINAL_FIELD (size, FONT_SIZE_INDEX, false);
|
||||
DO_CARDINAL_FIELD (spacing, FONT_SPACING_INDEX, false);
|
||||
DO_CARDINAL_FIELD (avgwidth, FONT_AVGWIDTH_INDEX, false);
|
||||
#undef DO_CARDINAL_FIELD
|
||||
}
|
||||
|
||||
/* Transfer the values from FONT, which must be some kind of font
|
||||
entity, */
|
||||
|
||||
static Lisp_Object
|
||||
androidfont_list (struct frame *f, Lisp_Object font_spec)
|
||||
{
|
||||
jobject spec, array, tem;
|
||||
jarray entities;
|
||||
jsize i, size;
|
||||
Lisp_Object value, entity;
|
||||
struct androidfont_entity *info;
|
||||
|
||||
spec = androidfont_from_lisp (font_spec);
|
||||
array = (*android_java_env)->CallObjectMethod (android_java_env,
|
||||
font_driver,
|
||||
font_driver_class.list,
|
||||
spec);
|
||||
(*android_java_env)->ExceptionClear (android_java_env);
|
||||
ANDROID_DELETE_LOCAL_REF (spec);
|
||||
|
||||
if (!array)
|
||||
memory_full (0);
|
||||
|
||||
entities = (jarray) array;
|
||||
size = (*android_java_env)->GetArrayLength (android_java_env,
|
||||
entities);
|
||||
value = Qnil;
|
||||
|
||||
for (i = 0; i < size; ++i)
|
||||
{
|
||||
entity = font_make_entity_android (VECSIZE (struct androidfont_entity));
|
||||
info = (struct androidfont_entity *) XFONT_ENTITY (entity);
|
||||
|
||||
/* The type must be set correctly, or font_open_entity won't be
|
||||
able to find the right font driver. */
|
||||
ASET (entity, FONT_TYPE_INDEX, Qandroid);
|
||||
|
||||
/* Clear this now in case GC happens without it set, which can
|
||||
happen if androidfont_from_java runs out of memory. */
|
||||
info->object = NULL;
|
||||
|
||||
tem = (*android_java_env)->GetObjectArrayElement (android_java_env,
|
||||
entities, i);
|
||||
androidfont_from_java (tem, entity);
|
||||
|
||||
/* Now, make a global reference to the Java font entity. */
|
||||
info->object = (*android_java_env)->NewGlobalRef (android_java_env,
|
||||
(jobject) tem);
|
||||
(*android_java_env)->ExceptionClear (android_java_env);
|
||||
ANDROID_DELETE_LOCAL_REF (tem);
|
||||
|
||||
if (!info->object)
|
||||
memory_full (0);
|
||||
|
||||
value = Fcons (entity, value);
|
||||
}
|
||||
|
||||
ANDROID_DELETE_LOCAL_REF (entities);
|
||||
return Fnreverse (value);
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
androidfont_match (struct frame *f, Lisp_Object font_spec)
|
||||
{
|
||||
jobject spec, result;
|
||||
Lisp_Object entity;
|
||||
struct androidfont_entity *info;
|
||||
|
||||
spec = androidfont_from_lisp (font_spec);
|
||||
result = (*android_java_env)->CallObjectMethod (android_java_env,
|
||||
font_driver,
|
||||
font_driver_class.match,
|
||||
spec);
|
||||
(*android_java_env)->ExceptionClear (android_java_env);
|
||||
ANDROID_DELETE_LOCAL_REF (spec);
|
||||
|
||||
if (!result)
|
||||
memory_full (0);
|
||||
|
||||
entity = font_make_entity_android (VECSIZE (struct androidfont_entity));
|
||||
info = (struct androidfont_entity *) XFONT_ENTITY (entity);
|
||||
|
||||
/* The type must be set correctly, or font_open_entity won't be able
|
||||
to find the right font driver. */
|
||||
ASET (entity, FONT_TYPE_INDEX, Qandroid);
|
||||
|
||||
info->object = NULL;
|
||||
androidfont_from_java (result, entity);
|
||||
info->object = (*android_java_env)->NewGlobalRef (android_java_env,
|
||||
(jobject) result);
|
||||
(*android_java_env)->ExceptionClear (android_java_env);
|
||||
ANDROID_DELETE_LOCAL_REF (result);
|
||||
|
||||
if (!info->object)
|
||||
memory_full (0);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
static int
|
||||
androidfont_draw (struct glyph_string *s, int from, int to,
|
||||
int x, int y, bool with_background)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
androidfont_open_font (struct frame *f, Lisp_Object font_entity, int x)
|
||||
{
|
||||
struct androidfont_info *font_info;
|
||||
struct androidfont_entity *entity;
|
||||
struct font *font;
|
||||
Lisp_Object font_object, tem;
|
||||
jobject old;
|
||||
jint value;
|
||||
|
||||
if (x <= 0)
|
||||
{
|
||||
/* Get pixel size from frame instead. */
|
||||
tem = get_frame_param (f, Qfontsize);
|
||||
x = NILP (tem) ? 0 : XFIXNAT (tem);
|
||||
}
|
||||
|
||||
__android_log_print (ANDROID_LOG_DEBUG, __func__,
|
||||
"opening font entity %"pI"x:%d",
|
||||
(EMACS_INT) font_entity, x);
|
||||
|
||||
entity = (struct androidfont_entity *) XFONT_ENTITY (font_entity);
|
||||
|
||||
block_input ();
|
||||
font_object = font_make_object (VECSIZE (struct androidfont_info),
|
||||
font_entity, x);
|
||||
ASET (font_object, FONT_TYPE_INDEX, Qandroid);
|
||||
font_info = (struct androidfont_info *) XFONT_OBJECT (font_object);
|
||||
font = &font_info->font;
|
||||
font->driver = &androidfont_driver;
|
||||
|
||||
/* Clear font_info->object early in case GC happens later on! */
|
||||
font_info->object = NULL;
|
||||
unblock_input ();
|
||||
|
||||
font_info->object
|
||||
= (*android_java_env)->CallObjectMethod (android_java_env,
|
||||
font_driver,
|
||||
font_driver_class.open_font,
|
||||
entity->object, (jint) x);
|
||||
if (!font_info->object)
|
||||
{
|
||||
(*android_java_env)->ExceptionClear (android_java_env);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
old = font_info->object;
|
||||
font_info->object
|
||||
= (*android_java_env)->NewGlobalRef (android_java_env, old);
|
||||
(*android_java_env)->ExceptionClear (android_java_env);
|
||||
ANDROID_DELETE_LOCAL_REF (old);
|
||||
|
||||
if (!font_info->object)
|
||||
return Qnil;
|
||||
|
||||
/* Copy the font attributes from the Java object. */
|
||||
androidfont_from_java (font_info->object, font_object);
|
||||
|
||||
/* Copy font attributes inside EmacsFontDriver$FontObject. */
|
||||
#define DO_CARDINAL_FIELD(field) \
|
||||
value \
|
||||
= (*android_java_env)->GetIntField (android_java_env, \
|
||||
font_info->object, \
|
||||
font_object_class.field); \
|
||||
font->field = value;
|
||||
|
||||
DO_CARDINAL_FIELD (min_width);
|
||||
DO_CARDINAL_FIELD (max_width);
|
||||
DO_CARDINAL_FIELD (pixel_size);
|
||||
DO_CARDINAL_FIELD (height);
|
||||
DO_CARDINAL_FIELD (space_width);
|
||||
DO_CARDINAL_FIELD (average_width);
|
||||
DO_CARDINAL_FIELD (ascent);
|
||||
DO_CARDINAL_FIELD (descent);
|
||||
DO_CARDINAL_FIELD (underline_thickness);
|
||||
DO_CARDINAL_FIELD (underline_position);
|
||||
DO_CARDINAL_FIELD (baseline_offset);
|
||||
DO_CARDINAL_FIELD (relative_compose);
|
||||
DO_CARDINAL_FIELD (default_ascent);
|
||||
DO_CARDINAL_FIELD (encoding_charset);
|
||||
DO_CARDINAL_FIELD (repertory_charset);
|
||||
|
||||
#undef DO_CARDINAL_FIELD
|
||||
|
||||
/* This should eventually become unnecessary. */
|
||||
font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil);
|
||||
|
||||
return font_object;
|
||||
}
|
||||
|
||||
static void
|
||||
androidfont_close_font (struct font *font)
|
||||
{
|
||||
struct androidfont_info *info;
|
||||
|
||||
info = (struct androidfont_info *) font;
|
||||
|
||||
/* If info->object is NULL, then FONT was unsuccessfully created,
|
||||
and there is no global reference that has to be deleted. */
|
||||
|
||||
if (!info->object)
|
||||
return;
|
||||
|
||||
(*android_java_env)->DeleteGlobalRef (android_java_env,
|
||||
info->object);
|
||||
}
|
||||
|
||||
static int
|
||||
androidfont_has_char (Lisp_Object font, int c)
|
||||
{
|
||||
struct androidfont_info *info;
|
||||
struct androidfont_entity *entity;
|
||||
|
||||
if (FONT_ENTITY_P (font))
|
||||
{
|
||||
entity = (struct androidfont_entity *) XFONT_ENTITY (font);
|
||||
|
||||
return (*android_java_env)->CallIntMethod (android_java_env,
|
||||
font_driver,
|
||||
font_driver_class.has_char,
|
||||
entity->object, (jint) c);
|
||||
}
|
||||
else
|
||||
{
|
||||
info = (struct androidfont_info *) XFONT_OBJECT (font);
|
||||
|
||||
return (*android_java_env)->CallIntMethod (android_java_env,
|
||||
font_driver,
|
||||
font_driver_class.has_char,
|
||||
info->object, (jint) c);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned
|
||||
androidfont_encode_char (struct font *font, int c)
|
||||
{
|
||||
struct androidfont_info *info;
|
||||
|
||||
info = (struct androidfont_info *) font;
|
||||
|
||||
return (*android_java_env)->CallIntMethod (android_java_env,
|
||||
font_driver,
|
||||
font_driver_class.encode_char,
|
||||
info->object, (jchar) c);
|
||||
}
|
||||
|
||||
static void
|
||||
androidfont_text_extents (struct font *font, const unsigned int *code,
|
||||
int nglyphs, struct font_metrics *metrics)
|
||||
{
|
||||
struct androidfont_info *info;
|
||||
jarray codepoint_array, metrics_array;
|
||||
jobject metrics_object;
|
||||
int i;
|
||||
short value;
|
||||
|
||||
info = (struct androidfont_info *) font;
|
||||
|
||||
/* Allocate the arrays of code points and font metrics. */
|
||||
codepoint_array
|
||||
= (*android_java_env)->NewIntArray (android_java_env,
|
||||
nglyphs);
|
||||
if (!codepoint_array)
|
||||
{
|
||||
(*android_java_env)->ExceptionClear (android_java_env);
|
||||
memory_full (0);
|
||||
}
|
||||
|
||||
metrics_array
|
||||
= (*android_java_env)->NewObjectArray (android_java_env,
|
||||
nglyphs,
|
||||
font_metrics_class.class,
|
||||
NULL);
|
||||
if (!metrics_array)
|
||||
{
|
||||
(*android_java_env)->ExceptionClear (android_java_env);
|
||||
ANDROID_DELETE_LOCAL_REF (metrics_array);
|
||||
memory_full (0);
|
||||
}
|
||||
|
||||
if (sizeof (unsigned int) == sizeof (jint))
|
||||
/* Always true on every Android device. */
|
||||
(*android_java_env)->SetIntArrayRegion (android_java_env,
|
||||
codepoint_array,
|
||||
0, nglyphs,
|
||||
(jint *) code);
|
||||
else
|
||||
emacs_abort ();
|
||||
|
||||
for (i = 0; i < nglyphs; ++i)
|
||||
{
|
||||
metrics_object
|
||||
= (*android_java_env)->AllocObject (android_java_env,
|
||||
font_metrics_class.class);
|
||||
|
||||
if (!metrics_object)
|
||||
{
|
||||
(*android_java_env)->ExceptionClear (android_java_env);
|
||||
ANDROID_DELETE_LOCAL_REF (metrics_array);
|
||||
ANDROID_DELETE_LOCAL_REF (codepoint_array);
|
||||
memory_full (0);
|
||||
}
|
||||
|
||||
(*android_java_env)->SetObjectArrayElement (android_java_env,
|
||||
metrics_array, i,
|
||||
metrics_object);
|
||||
ANDROID_DELETE_LOCAL_REF (metrics_object);
|
||||
}
|
||||
|
||||
(*android_java_env)->CallVoidMethod (android_java_env,
|
||||
font_driver,
|
||||
font_driver_class.text_extents,
|
||||
info->object, codepoint_array,
|
||||
metrics_array);
|
||||
|
||||
if ((*android_java_env)->ExceptionCheck (android_java_env))
|
||||
{
|
||||
(*android_java_env)->ExceptionClear (android_java_env);
|
||||
ANDROID_DELETE_LOCAL_REF (metrics_array);
|
||||
ANDROID_DELETE_LOCAL_REF (codepoint_array);
|
||||
memory_full (0);
|
||||
}
|
||||
|
||||
for (i = 0; i < nglyphs; ++i)
|
||||
{
|
||||
metrics_object
|
||||
= (*android_java_env)->GetObjectArrayElement (android_java_env,
|
||||
metrics_array, i);
|
||||
#define DO_CARDINAL_FIELD(field) \
|
||||
value \
|
||||
= (*android_java_env)->GetShortField (android_java_env, \
|
||||
metrics_object, \
|
||||
font_metrics_class.field); \
|
||||
metrics[i].field = value;
|
||||
|
||||
DO_CARDINAL_FIELD (lbearing);
|
||||
DO_CARDINAL_FIELD (rbearing);
|
||||
DO_CARDINAL_FIELD (width);
|
||||
DO_CARDINAL_FIELD (ascent);
|
||||
DO_CARDINAL_FIELD (descent);
|
||||
|
||||
#undef DO_CARDINAL_FIELD
|
||||
|
||||
ANDROID_DELETE_LOCAL_REF (metrics_object);
|
||||
}
|
||||
|
||||
ANDROID_DELETE_LOCAL_REF (metrics_array);
|
||||
ANDROID_DELETE_LOCAL_REF (codepoint_array);
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
androidfont_list_family (struct frame *f)
|
||||
{
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
struct font_driver androidfont_driver =
|
||||
{
|
||||
.type = LISPSYM_INITIALLY (Qandroid),
|
||||
.case_sensitive = true,
|
||||
.get_cache = androidfont_get_cache,
|
||||
.list = androidfont_list,
|
||||
.match = androidfont_match,
|
||||
.draw = androidfont_draw,
|
||||
.open_font = androidfont_open_font,
|
||||
.close_font = androidfont_close_font,
|
||||
.has_char = androidfont_has_char,
|
||||
.encode_char = androidfont_encode_char,
|
||||
.text_extents = androidfont_text_extents,
|
||||
.list_family = androidfont_list_family,
|
||||
};
|
||||
|
||||
static void
|
||||
syms_of_androidfont_for_pdumper (void)
|
||||
{
|
||||
register_font_driver (&androidfont_driver, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
syms_of_androidfont (void)
|
||||
{
|
||||
DEFSYM (Qfontsize, "fontsize");
|
||||
|
||||
pdumper_do_now_and_after_load (syms_of_androidfont_for_pdumper);
|
||||
|
||||
font_cache = list (Qnil);
|
||||
staticpro (&font_cache);
|
||||
}
|
||||
|
||||
void
|
||||
init_androidfont (void)
|
||||
{
|
||||
jmethodID method;
|
||||
jobject old;
|
||||
|
||||
android_init_font_driver ();
|
||||
android_init_font_spec ();
|
||||
android_init_font_metrics ();
|
||||
android_init_font_object ();
|
||||
android_init_integer ();
|
||||
|
||||
method = font_driver_class.create_font_driver;
|
||||
|
||||
/* Initialize the font driver on the Java side. */
|
||||
font_driver
|
||||
= (*android_java_env)->CallStaticObjectMethod (android_java_env,
|
||||
font_driver_class.class,
|
||||
method);
|
||||
|
||||
if (!font_driver)
|
||||
memory_full (0);
|
||||
|
||||
old = font_driver;
|
||||
font_driver
|
||||
= (*android_java_env)->NewGlobalRef (android_java_env, font_driver);
|
||||
ANDROID_DELETE_LOCAL_REF (old);
|
||||
|
||||
if (!font_driver)
|
||||
memory_full (0);
|
||||
}
|
||||
|
||||
void
|
||||
android_finalize_font_entity (struct font_entity *entity)
|
||||
{
|
||||
struct androidfont_entity *info;
|
||||
|
||||
info = (struct androidfont_entity *) entity;
|
||||
|
||||
if (info->object)
|
||||
(*android_java_env)->DeleteGlobalRef (android_java_env,
|
||||
info->object);
|
||||
|
||||
/* Not sure if this can be called twice. */
|
||||
info->object = NULL;
|
||||
}
|
||||
|
||||
#endif
|
315
src/androidgui.h
Normal file
315
src/androidgui.h
Normal file
|
@ -0,0 +1,315 @@
|
|||
/* Android window system support.
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _ANDROID_GUI_H_
|
||||
#define _ANDROID_GUI_H_
|
||||
|
||||
struct android_char_struct
|
||||
{
|
||||
int rbearing;
|
||||
int lbearing;
|
||||
int width;
|
||||
int ascent;
|
||||
int descent;
|
||||
};
|
||||
|
||||
typedef struct android_char_struct XCharStruct;
|
||||
|
||||
typedef unsigned short android_handle;
|
||||
|
||||
typedef android_handle android_pixmap, Emacs_Pixmap;
|
||||
typedef android_handle android_window, Emacs_Window;
|
||||
typedef android_handle android_gcontext, GContext;
|
||||
typedef android_handle android_drawable, Drawable;
|
||||
|
||||
typedef unsigned int android_time;
|
||||
|
||||
struct android_rectangle
|
||||
{
|
||||
int x, y;
|
||||
unsigned width, height;
|
||||
};
|
||||
|
||||
struct android_point
|
||||
{
|
||||
int x, y;
|
||||
};
|
||||
|
||||
/* Keep this in sync with EmacsGC.java! */
|
||||
|
||||
enum android_gc_function
|
||||
{
|
||||
ANDROID_GC_COPY = 0,
|
||||
ANDROID_GC_XOR = 1,
|
||||
};
|
||||
|
||||
enum android_gc_value_mask
|
||||
{
|
||||
ANDROID_GC_FOREGROUND = (1 << 0),
|
||||
ANDROID_GC_BACKGROUND = (1 << 1),
|
||||
ANDROID_GC_FUNCTION = (1 << 2),
|
||||
ANDROID_GC_CLIP_X_ORIGIN = (1 << 3),
|
||||
ANDROID_GC_CLIP_Y_ORIGIN = (1 << 4),
|
||||
ANDROID_GC_CLIP_MASK = (1 << 5),
|
||||
ANDROID_GC_STIPPLE = (1 << 6),
|
||||
ANDROID_GC_FILL_STYLE = (1 << 7),
|
||||
ANDROID_GC_TILE_STIP_X_ORIGIN = (1 << 8),
|
||||
ANDROID_GC_TILE_STIP_Y_ORIGIN = (1 << 9),
|
||||
};
|
||||
|
||||
enum android_fill_style
|
||||
{
|
||||
ANDROID_FILL_SOLID = 0,
|
||||
ANDROID_FILL_OPAQUE_STIPPLED = 1,
|
||||
};
|
||||
|
||||
enum android_window_value_mask
|
||||
{
|
||||
ANDROID_CW_BACK_PIXEL = (1 << 1),
|
||||
};
|
||||
|
||||
struct android_set_window_attributes
|
||||
{
|
||||
/* The background pixel. */
|
||||
unsigned long background_pixel;
|
||||
};
|
||||
|
||||
struct android_gc_values
|
||||
{
|
||||
/* The foreground and background. */
|
||||
unsigned long foreground, background;
|
||||
|
||||
/* The function. */
|
||||
enum android_gc_function function;
|
||||
|
||||
/* The fill style. */
|
||||
enum android_fill_style fill_style;
|
||||
|
||||
/* The clip X and Y origin. */
|
||||
int clip_x_origin, clip_y_origin;
|
||||
|
||||
/* The clip mask image and stipple. */
|
||||
android_pixmap clip_mask, stipple;
|
||||
|
||||
/* The tile-stipple X and Y origins. */
|
||||
int ts_x_origin, ts_y_origin;
|
||||
};
|
||||
|
||||
/* X-like graphics context structure. This is implemented in
|
||||
EmacsGC.java, but a copy is kept here to avoid sending changes all
|
||||
the time. */
|
||||
|
||||
struct android_gc
|
||||
{
|
||||
/* The Java-side handle. */
|
||||
android_gcontext gcontext;
|
||||
};
|
||||
|
||||
enum android_swap_action
|
||||
{
|
||||
ANDROID_COPIED,
|
||||
};
|
||||
|
||||
enum android_shape
|
||||
{
|
||||
ANDROID_CONVEX,
|
||||
};
|
||||
|
||||
enum android_coord_mode
|
||||
{
|
||||
ANDROID_COORD_MODE_ORIGIN,
|
||||
};
|
||||
|
||||
struct android_swap_info
|
||||
{
|
||||
/* The window to swap. */
|
||||
android_window swap_window;
|
||||
|
||||
/* Unused field present only for consistency with X. */
|
||||
enum android_swap_action swap_action;
|
||||
};
|
||||
|
||||
/* Android doesn't support cursors, so define this to something
|
||||
unused. */
|
||||
typedef char Emacs_Cursor;
|
||||
|
||||
#define NativeRectangle Emacs_Rectangle
|
||||
#define CONVERT_TO_NATIVE_RECT(xr, nr) ((xr) = (nr))
|
||||
#define CONVERT_FROM_EMACS_RECT(xr, nr) ((nr) = (xr))
|
||||
|
||||
#define STORE_NATIVE_RECT(nr, rx, ry, rwidth, rheight) \
|
||||
((nr).x = (rx), (nr).y = (ry), \
|
||||
(nr).width = (rwidth), (nr).height = (rheight)) \
|
||||
|
||||
#define ForgetGravity 0
|
||||
#define NorthWestGravity 1
|
||||
#define NorthGravity 2
|
||||
#define NorthEastGravity 3
|
||||
#define WestGravity 4
|
||||
#define CenterGravity 5
|
||||
#define EastGravity 6
|
||||
#define SouthWestGravity 7
|
||||
#define SouthGravity 8
|
||||
#define SouthEastGravity 9
|
||||
#define StaticGravity 10
|
||||
|
||||
#define NoValue 0x0000
|
||||
#define XValue 0x0001
|
||||
#define YValue 0x0002
|
||||
#define WidthValue 0x0004
|
||||
#define HeightValue 0x0008
|
||||
#define AllValues 0x000F
|
||||
#define XNegative 0x0010
|
||||
#define YNegative 0x0020
|
||||
|
||||
#define USPosition (1L << 0) /* user specified x, y */
|
||||
#define USSize (1L << 1) /* user specified width, height */
|
||||
#define PPosition (1L << 2) /* program specified position */
|
||||
#define PSize (1L << 3) /* program specified size */
|
||||
#define PMinSize (1L << 4) /* program specified minimum size */
|
||||
#define PMaxSize (1L << 5) /* program specified maximum size */
|
||||
#define PResizeInc (1L << 6) /* program specified resize increments */
|
||||
#define PAspect (1L << 7) /* program specified min, max aspect ratios */
|
||||
#define PBaseSize (1L << 8) /* program specified base for incrementing */
|
||||
#define PWinGravity (1L << 9) /* program specified window gravity */
|
||||
|
||||
#ifndef ANDROID_STUBIFY
|
||||
|
||||
/* Universal NULL handle. */
|
||||
static const int ANDROID_NONE;
|
||||
|
||||
/* Keep these as conceptually close to X as possible: that makes
|
||||
synchronizing code between the ports much easier. */
|
||||
|
||||
enum android_event_type
|
||||
{
|
||||
ANDROID_KEY_PRESS,
|
||||
ANDROID_KEY_RELEASE,
|
||||
ANDROID_CONFIGURE_NOTIFY,
|
||||
};
|
||||
|
||||
struct android_any_event
|
||||
{
|
||||
enum android_event_type type;
|
||||
android_window window;
|
||||
};
|
||||
|
||||
struct android_key_event
|
||||
{
|
||||
enum android_event_type type;
|
||||
android_window window;
|
||||
android_time time;
|
||||
unsigned int state;
|
||||
unsigned int keycode;
|
||||
};
|
||||
|
||||
struct android_configure_event
|
||||
{
|
||||
enum android_event_type type;
|
||||
android_window window;
|
||||
android_time time;
|
||||
int x, y;
|
||||
int width, height;
|
||||
};
|
||||
|
||||
union android_event
|
||||
{
|
||||
enum android_event_type type;
|
||||
struct android_any_event xany;
|
||||
struct android_key_event xkey;
|
||||
struct android_configure_event xconfigure;
|
||||
};
|
||||
|
||||
extern int android_pending (void);
|
||||
extern void android_next_event (union android_event *);
|
||||
|
||||
extern android_window android_create_window (android_window, int,
|
||||
int, int, int,
|
||||
enum android_window_value_mask,
|
||||
struct
|
||||
android_set_window_attributes *);
|
||||
extern void android_change_window_attributes (android_window,
|
||||
enum android_window_value_mask,
|
||||
struct
|
||||
android_set_window_attributes *);
|
||||
extern void android_set_window_background (android_window, unsigned long);
|
||||
extern void android_destroy_window (android_window);
|
||||
extern void android_reparent_window (android_window, android_window,
|
||||
int, int);
|
||||
extern void android_set_clip_rectangles (struct android_gc *,
|
||||
int, int,
|
||||
struct android_rectangle *,
|
||||
int);
|
||||
extern void android_change_gc (struct android_gc *,
|
||||
enum android_gc_value_mask,
|
||||
struct android_gc_values *);
|
||||
|
||||
extern void android_clear_window (android_window);
|
||||
extern void android_map_window (android_window);
|
||||
extern void android_unmap_window (android_window);
|
||||
extern void android_resize_window (android_window, unsigned int,
|
||||
unsigned int);
|
||||
extern void android_move_window (android_window, int, int);
|
||||
extern void android_swap_buffers (struct android_swap_info *, int);
|
||||
extern void android_get_gc_values (struct android_gc *,
|
||||
enum android_gc_value_mask,
|
||||
struct android_gc_values *);
|
||||
extern void android_set_foreground (struct android_gc *,
|
||||
unsigned long);
|
||||
extern void android_fill_rectangle (android_drawable, struct android_gc *,
|
||||
int, int, unsigned int, unsigned int);
|
||||
extern android_pixmap android_create_pixmap_from_bitmap_data (char *,
|
||||
unsigned int,
|
||||
unsigned int,
|
||||
unsigned long,
|
||||
unsigned long,
|
||||
unsigned int);
|
||||
extern void android_set_clip_mask (struct android_gc *, android_pixmap);
|
||||
extern void android_set_fill_style (struct android_gc *,
|
||||
enum android_fill_style);
|
||||
extern void android_copy_area (android_drawable, android_drawable,
|
||||
struct android_gc *, int, int,
|
||||
unsigned int, unsigned int, int, int);
|
||||
extern void android_free_pixmap (android_drawable);
|
||||
|
||||
extern void android_set_background (struct android_gc *, unsigned long);
|
||||
extern void android_fill_polygon (android_drawable, struct android_gc *,
|
||||
struct android_point *, int,
|
||||
enum android_shape,
|
||||
enum android_coord_mode);
|
||||
extern void android_draw_rectangle (android_drawable, struct android_gc *,
|
||||
int, int, unsigned int, unsigned int);
|
||||
extern void android_draw_point (android_window, struct android_gc *,
|
||||
int, int);
|
||||
extern void android_draw_line (android_window, struct android_gc *,
|
||||
int, int, int, int);
|
||||
extern android_pixmap android_create_pixmap (unsigned int, unsigned int,
|
||||
int);
|
||||
extern void android_set_ts_origin (struct android_gc *, int, int);
|
||||
extern void android_clear_area (android_window, int, int, unsigned int,
|
||||
unsigned int);
|
||||
|
||||
#endif
|
||||
|
||||
/* X emulation stuff also needed while building stubs. */
|
||||
|
||||
extern struct android_gc *android_create_gc (enum android_gc_value_mask,
|
||||
struct android_gc_values *);
|
||||
extern void android_free_gc (struct android_gc *);
|
||||
|
||||
#endif /* _ANDROID_GUI_H_ */
|
3161
src/androidterm.c
Normal file
3161
src/androidterm.c
Normal file
File diff suppressed because it is too large
Load diff
366
src/androidterm.h
Normal file
366
src/androidterm.h
Normal file
|
@ -0,0 +1,366 @@
|
|||
/* Communication module for Android terminals.
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _ANDROID_TERM_H_
|
||||
#define _ANDROID_TERM_H_
|
||||
|
||||
#include "androidgui.h"
|
||||
#include "frame.h"
|
||||
#include "character.h"
|
||||
#include "dispextern.h"
|
||||
#include "font.h"
|
||||
|
||||
struct android_bitmap_record
|
||||
{
|
||||
/* The image backing the bitmap. */
|
||||
Emacs_Pixmap img;
|
||||
|
||||
/* The file from which it comes. */
|
||||
char *file;
|
||||
|
||||
/* The number of references to it. */
|
||||
int refcount;
|
||||
|
||||
/* The height and width. */
|
||||
int height, width;
|
||||
};
|
||||
|
||||
struct android_display_info
|
||||
{
|
||||
/* Chain of all struct android_display_info structures. */
|
||||
struct android_display_info *next;
|
||||
|
||||
/* The terminal. */
|
||||
struct terminal *terminal;
|
||||
|
||||
/* The root window. This field is unused. */
|
||||
Emacs_Window root_window;
|
||||
|
||||
/* List possibly used only for the font cache but probably used for
|
||||
something else too. */
|
||||
Lisp_Object name_list_element;
|
||||
|
||||
/* List of predefined X colors. */
|
||||
Lisp_Object color_map;
|
||||
|
||||
/* DPI of the display. */
|
||||
double resx, resy;
|
||||
|
||||
/* Scratch GC for drawing a cursor in a non-default face. */
|
||||
struct android_gc *scratch_cursor_gc;
|
||||
|
||||
/* Mouse highlight information. */
|
||||
Mouse_HLInfo mouse_highlight;
|
||||
|
||||
/* Number of planes on this screen. Always 24. */
|
||||
int n_planes;
|
||||
|
||||
/* Mask of things causing the mouse to be grabbed. */
|
||||
int grabbed;
|
||||
|
||||
/* Minimum width over all characters in all fonts in font_table. */
|
||||
int smallest_char_width;
|
||||
|
||||
/* Minimum font height over all fonts in font_table. */
|
||||
int smallest_font_height;
|
||||
|
||||
/* The number of fonts opened for this display. */
|
||||
int n_fonts;
|
||||
|
||||
/* Pointer to bitmap records. */
|
||||
struct android_bitmap_record *bitmaps;
|
||||
|
||||
/* Allocated size of bitmaps field. */
|
||||
ptrdiff_t bitmaps_size;
|
||||
|
||||
/* Last used bitmap index. */
|
||||
ptrdiff_t bitmaps_last;
|
||||
|
||||
/* The frame currently with the input focus. */
|
||||
struct frame *focus_frame;
|
||||
|
||||
/* The frame which currently has the visual highlight, and should
|
||||
get keyboard input. It points to the focus frame's selected
|
||||
window's frame, but can differ. */
|
||||
struct frame *highlight_frame;
|
||||
|
||||
/* The frame waiting to be auto-raised in android_read_socket. */
|
||||
struct frame *pending_autoraise_frame;
|
||||
|
||||
/* The frame where the mouse was the last time a button event
|
||||
happened. */
|
||||
struct frame *last_mouse_frame;
|
||||
|
||||
/* The frame where the mouse was the last time the mouse glyph
|
||||
changed. */
|
||||
struct frame *last_mouse_glyph_frame;
|
||||
|
||||
/* The frame where the mouse was the last time mouse motion
|
||||
happened. */
|
||||
struct frame *last_mouse_motion_frame;
|
||||
|
||||
/* Position where the mouse was last time we reported a motion.
|
||||
This is a position on last_mouse_motion_frame. It is used in to
|
||||
report the mouse position as well: see
|
||||
android_mouse_position. */
|
||||
int last_mouse_motion_x, last_mouse_motion_y;
|
||||
|
||||
/* Where the mouse was the last time the mouse moved. */
|
||||
Emacs_Rectangle last_mouse_glyph;
|
||||
};
|
||||
|
||||
struct android_output
|
||||
{
|
||||
/* Graphics contexts for the default font. */
|
||||
struct android_gc *normal_gc, *reverse_gc, *cursor_gc;
|
||||
|
||||
/* The window used for this frame. */
|
||||
Emacs_Window window;
|
||||
|
||||
/* Unused field. */
|
||||
Emacs_Window parent_desc;
|
||||
|
||||
/* Default ASCII font of this frame. */
|
||||
struct font *font;
|
||||
|
||||
/* The baseline offset of the default ASCII font. */
|
||||
int baseline_offset;
|
||||
|
||||
/* If a fontset is specified for this frame instead of font, this
|
||||
value contains an ID of the fontset, else -1. */
|
||||
int fontset;
|
||||
|
||||
/* Various colors. */
|
||||
unsigned long cursor_pixel;
|
||||
unsigned long cursor_foreground_pixel;
|
||||
|
||||
/* Foreground color for scroll bars. A value of -1 means use the
|
||||
default (black for non-toolkit scroll bars). */
|
||||
unsigned long scroll_bar_foreground_pixel;
|
||||
|
||||
/* Background color for scroll bars. A value of -1 means use the
|
||||
default (background color of the frame for non-toolkit scroll
|
||||
bars). */
|
||||
unsigned long scroll_bar_background_pixel;
|
||||
|
||||
/* Unused stuff (cursors). */
|
||||
Emacs_Cursor text_cursor;
|
||||
Emacs_Cursor nontext_cursor;
|
||||
Emacs_Cursor modeline_cursor;
|
||||
Emacs_Cursor hand_cursor;
|
||||
Emacs_Cursor hourglass_cursor;
|
||||
Emacs_Cursor horizontal_drag_cursor;
|
||||
Emacs_Cursor vertical_drag_cursor;
|
||||
Emacs_Cursor current_cursor;
|
||||
Emacs_Cursor left_edge_cursor;
|
||||
Emacs_Cursor top_left_corner_cursor;
|
||||
Emacs_Cursor top_edge_cursor;
|
||||
Emacs_Cursor top_right_corner_cursor;
|
||||
Emacs_Cursor right_edge_cursor;
|
||||
Emacs_Cursor bottom_right_corner_cursor;
|
||||
Emacs_Cursor bottom_edge_cursor;
|
||||
Emacs_Cursor bottom_left_corner_cursor;
|
||||
|
||||
/* This is the Emacs structure for the display this frame is on. */
|
||||
struct android_display_info *display_info;
|
||||
|
||||
/* True if this frame was ever previously visible. */
|
||||
bool_bf has_been_visible : 1;
|
||||
|
||||
/* True if this frame's alpha value is the same for both the active
|
||||
and inactive states. */
|
||||
bool_bf alpha_identical_p : 1;
|
||||
|
||||
/* Flag that indicates whether we've modified the back buffer and
|
||||
need to publish our modifications to the front buffer at a
|
||||
convenient time. */
|
||||
bool_bf need_buffer_flip : 1;
|
||||
|
||||
/* Flag that indicates whether or not the frame contents are
|
||||
complete and can be safely flushed while handling async
|
||||
input. */
|
||||
bool_bf complete : 1;
|
||||
|
||||
/* Relief GCs, colors etc. */
|
||||
struct relief {
|
||||
struct android_gc *gc;
|
||||
unsigned long pixel;
|
||||
} black_relief, white_relief;
|
||||
|
||||
/* The background for which the above relief GCs were set up.
|
||||
They are changed only when a different background is involved. */
|
||||
unsigned long relief_background;
|
||||
};
|
||||
|
||||
/* Return the Android output data for frame F. */
|
||||
#define FRAME_ANDROID_OUTPUT(f) ((f)->output_data.android)
|
||||
#define FRAME_OUTPUT_DATA(f) ((f)->output_data.android)
|
||||
|
||||
/* Return the Android window used for displaying data in frame F. */
|
||||
#define FRAME_ANDROID_WINDOW(f) ((f)->output_data.android->window)
|
||||
#define FRAME_NATIVE_WINDOW(f) ((f)->output_data.android->window)
|
||||
|
||||
/* Return the need-buffer-flip flag for frame F. */
|
||||
#define FRAME_ANDROID_NEED_BUFFER_FLIP(f) \
|
||||
((f)->output_data.android->need_buffer_flip)
|
||||
|
||||
/* Return whether or not the frame F has been completely drawn. Used
|
||||
while handling async input. */
|
||||
#define FRAME_ANDROID_COMPLETE_P(f) \
|
||||
((f)->output_data.android->complete)
|
||||
|
||||
#define FRAME_FONT(f) ((f)->output_data.android->font)
|
||||
#define FRAME_FONTSET(f) ((f)->output_data.android->fontset)
|
||||
|
||||
#define FRAME_BASELINE_OFFSET(f) \
|
||||
((f)->output_data.android->baseline_offset)
|
||||
|
||||
/* This gives the android_display_info structure for the display F is
|
||||
on. */
|
||||
#define FRAME_DISPLAY_INFO(f) ((f)->output_data.android->display_info)
|
||||
|
||||
/* Some things for X compatibility. */
|
||||
#define BLACK_PIX_DEFAULT(f) 0
|
||||
#define WHITE_PIX_DEFAULT(f) 0xffffffff
|
||||
|
||||
/* Android-specific scroll bar stuff. */
|
||||
|
||||
/* We represent scroll bars as lisp vectors. This allows us to place
|
||||
references to them in windows without worrying about whether we'll
|
||||
end up with windows referring to dead scroll bars; the garbage
|
||||
collector will free it when its time comes.
|
||||
|
||||
We use struct scroll_bar as a template for accessing fields of the
|
||||
vector. */
|
||||
|
||||
struct scroll_bar
|
||||
{
|
||||
/* These fields are shared by all vectors. */
|
||||
union vectorlike_header header;
|
||||
|
||||
/* The window we're a scroll bar for. */
|
||||
Lisp_Object window;
|
||||
|
||||
/* The next and previous in the chain of scroll bars in this frame. */
|
||||
Lisp_Object next, prev;
|
||||
|
||||
/* Fields after 'prev' are not traced by the GC. */
|
||||
|
||||
/* The X window representing this scroll bar. */
|
||||
Emacs_Window x_window;
|
||||
|
||||
/* The position and size of the scroll bar in pixels, relative to the
|
||||
frame. */
|
||||
int top, left, width, height;
|
||||
|
||||
/* The starting and ending positions of the handle, relative to the
|
||||
handle area (i.e. zero is the top position, not
|
||||
SCROLL_BAR_TOP_BORDER). If they're equal, that means the handle
|
||||
hasn't been drawn yet.
|
||||
|
||||
These are not actually the locations where the beginning and end
|
||||
are drawn; in order to keep handles from becoming invisible when
|
||||
editing large files, we establish a minimum height by always
|
||||
drawing handle bottoms VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
|
||||
where they would be normally; the bottom and top are in a
|
||||
different coordinate system. */
|
||||
int start, end;
|
||||
|
||||
/* If the scroll bar handle is currently being dragged by the user,
|
||||
this is the number of pixels from the top of the handle to the
|
||||
place where the user grabbed it. If the handle isn't currently
|
||||
being dragged, this is -1. */
|
||||
int dragging;
|
||||
|
||||
/* True if the scroll bar is horizontal. */
|
||||
bool horizontal;
|
||||
};
|
||||
|
||||
/* Turning a lisp vector value into a pointer to a struct scroll_bar. */
|
||||
#define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec))
|
||||
|
||||
|
||||
|
||||
/* This is a chain of structures for all the Android displays
|
||||
currently in use. There is only ever one, but the rest of Emacs is
|
||||
written with systems on which there can be many in mind. */
|
||||
extern struct android_display_info *x_display_list;
|
||||
|
||||
|
||||
|
||||
/* Start of function definitions. These should be a neat subset of
|
||||
the same ones in xterm.h, and come in the same order. */
|
||||
|
||||
/* From androidfns.c. */
|
||||
|
||||
extern void android_free_gcs (struct frame *);
|
||||
extern void android_default_font_parameter (struct frame *, Lisp_Object);
|
||||
|
||||
/* Defined in androidterm.c. */
|
||||
|
||||
extern void android_term_init (void);
|
||||
extern void android_set_window_size (struct frame *, bool, int, int);
|
||||
extern void android_iconify_frame (struct frame *);
|
||||
extern void android_make_frame_visible (struct frame *);
|
||||
extern void android_make_frame_invisible (struct frame *);
|
||||
extern void android_free_frame_resources (struct frame *);
|
||||
|
||||
extern int android_parse_color (struct frame *, const char *,
|
||||
Emacs_Color *);
|
||||
extern bool android_alloc_nearest_color (struct frame *, Emacs_Color *);
|
||||
extern void android_query_colors (struct frame *, Emacs_Color *, int);
|
||||
extern void android_clear_under_internal_border (struct frame *);
|
||||
|
||||
extern void syms_of_androidterm (void);
|
||||
extern void mark_androidterm (void);
|
||||
|
||||
/* Defined in androidfns.c. */
|
||||
|
||||
extern void android_change_tab_bar_height (struct frame *, int);
|
||||
extern void android_change_tool_bar_height (struct frame *, int);
|
||||
extern void android_set_scroll_bar_default_width (struct frame *);
|
||||
extern void android_set_scroll_bar_default_height (struct frame *);
|
||||
extern bool android_defined_color (struct frame *, const char *,
|
||||
Emacs_Color *, bool, bool);
|
||||
extern void android_implicitly_set_name (struct frame *, Lisp_Object,
|
||||
Lisp_Object);
|
||||
extern void android_explicitly_set_name (struct frame *, Lisp_Object,
|
||||
Lisp_Object);
|
||||
|
||||
extern void syms_of_androidfns (void);
|
||||
|
||||
/* Defined in androidfont.c. */
|
||||
|
||||
extern struct font_driver androidfont_driver;
|
||||
|
||||
extern void init_androidfont (void);
|
||||
extern void syms_of_androidfont (void);
|
||||
|
||||
extern void android_finalize_font_entity (struct font_entity *);
|
||||
|
||||
|
||||
|
||||
#define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b))
|
||||
#define RED_FROM_ULONG(color) (((color) >> 16) & 0xff)
|
||||
#define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
|
||||
#define BLUE_FROM_ULONG(color) ((color) & 0xff)
|
||||
|
||||
|
||||
|
||||
#endif /* _ANDROID_TERM_H_ */
|
|
@ -979,14 +979,15 @@ file_attributes (int fd, char const *name,
|
|||
|
||||
int err = EINVAL;
|
||||
|
||||
#if defined O_PATH && !defined HAVE_CYGWIN_O_PATH_BUG
|
||||
#if defined O_PATH && !defined HAVE_CYGWIN_O_PATH_BUG \
|
||||
&& !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
|
||||
int namefd = emacs_openat (fd, name, O_PATH | O_CLOEXEC | O_NOFOLLOW, 0);
|
||||
if (namefd < 0)
|
||||
err = errno;
|
||||
else
|
||||
{
|
||||
record_unwind_protect_int (close_file_unwind, namefd);
|
||||
if (fstat (namefd, &s) != 0)
|
||||
if (sys_fstat (namefd, &s) != 0)
|
||||
{
|
||||
err = errno;
|
||||
/* The Linux kernel before version 3.6 does not support
|
||||
|
|
|
@ -53,8 +53,15 @@ typedef struct
|
|||
unsigned short red, green, blue;
|
||||
} Emacs_Color;
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
/* Accommodate X's usage of None as a null resource ID. */
|
||||
#define No_Cursor (NULL)
|
||||
#else
|
||||
/* Android doesn't support cursors and also uses handles. */
|
||||
#define No_Cursor 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
/* XRectangle-like struct used by non-X GUI code. */
|
||||
typedef struct
|
||||
|
@ -63,6 +70,12 @@ typedef struct
|
|||
unsigned width, height;
|
||||
} Emacs_Rectangle;
|
||||
|
||||
#else
|
||||
|
||||
typedef struct android_rectangle Emacs_Rectangle;
|
||||
|
||||
#endif
|
||||
|
||||
/* XGCValues-like struct used by non-X GUI code. */
|
||||
typedef struct
|
||||
{
|
||||
|
@ -144,6 +157,13 @@ typedef Emacs_Pixmap Emacs_Pix_Container;
|
|||
typedef Emacs_Pixmap Emacs_Pix_Context;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
#include "androidgui.h"
|
||||
typedef struct android_display_info Display_Info;
|
||||
typedef Emacs_Pixmap Emacs_Pix_Container;
|
||||
typedef Emacs_Pixmap Emacs_Pix_Context;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
# include <time.h>
|
||||
# include "fontset.h"
|
||||
|
@ -1401,6 +1421,8 @@ struct glyph_string
|
|||
/* The GC to use for drawing this glyph string. */
|
||||
#if defined (HAVE_X_WINDOWS)
|
||||
GC gc;
|
||||
#elif defined HAVE_ANDROID
|
||||
struct android_gc *gc;
|
||||
#endif
|
||||
#if defined (HAVE_NTGUI)
|
||||
Emacs_GC *gc;
|
||||
|
@ -1681,6 +1703,8 @@ struct face
|
|||
drawing the characters in this face. */
|
||||
# ifdef HAVE_X_WINDOWS
|
||||
GC gc;
|
||||
# elif defined HAVE_ANDROID
|
||||
struct android_gc *gc;
|
||||
# else
|
||||
Emacs_GC *gc;
|
||||
# endif
|
||||
|
@ -3502,9 +3526,11 @@ extern void gui_clear_window_mouse_face (struct window *);
|
|||
extern void cancel_mouse_face (struct frame *);
|
||||
extern bool clear_mouse_face (Mouse_HLInfo *);
|
||||
extern bool cursor_in_mouse_face_p (struct window *w);
|
||||
#ifndef HAVE_ANDROID
|
||||
extern void tty_draw_row_with_mouse_face (struct window *, struct glyph_row *,
|
||||
int, int, enum draw_glyphs_face);
|
||||
extern void display_tty_menu_item (const char *, int, int, int, int, bool);
|
||||
#endif
|
||||
extern struct glyph *x_y_to_hpos_vpos (struct window *, int, int, int *, int *,
|
||||
int *, int *, int *);
|
||||
/* Flags passed to try_window. */
|
||||
|
@ -3566,7 +3592,7 @@ void prepare_image_for_display (struct frame *, struct image *);
|
|||
ptrdiff_t lookup_image (struct frame *, Lisp_Object, int);
|
||||
|
||||
#if defined HAVE_X_WINDOWS || defined USE_CAIRO || defined HAVE_NS \
|
||||
|| defined HAVE_HAIKU
|
||||
|| defined HAVE_HAIKU || defined HAVE_ANDROID
|
||||
#define RGB_PIXEL_COLOR unsigned long
|
||||
#endif
|
||||
|
||||
|
@ -3647,6 +3673,9 @@ void gamma_correct (struct frame *, COLORREF *);
|
|||
#ifdef HAVE_HAIKU
|
||||
void gamma_correct (struct frame *, Emacs_Color *);
|
||||
#endif
|
||||
#ifdef HAVE_ANDROID
|
||||
extern void gamma_correct (struct frame *, Emacs_Color *);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
|
||||
|
|
|
@ -43,6 +43,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include "xwidget.h"
|
||||
#include "pdumper.h"
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
#include "android.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
#include TERM_HEADER
|
||||
#endif /* HAVE_WINDOW_SYSTEM */
|
||||
|
@ -788,7 +792,7 @@ clear_current_matrices (register struct frame *f)
|
|||
if (f->current_matrix)
|
||||
clear_glyph_matrix (f->current_matrix);
|
||||
|
||||
#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
|
||||
#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
|
||||
/* Clear the matrix of the menu bar window, if such a window exists.
|
||||
The menu bar window is currently used to display menus on X when
|
||||
no toolkit support is compiled in. */
|
||||
|
@ -822,7 +826,7 @@ clear_desired_matrices (register struct frame *f)
|
|||
if (f->desired_matrix)
|
||||
clear_glyph_matrix (f->desired_matrix);
|
||||
|
||||
#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
|
||||
#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
|
||||
if (WINDOWP (f->menu_bar_window))
|
||||
clear_glyph_matrix (XWINDOW (f->menu_bar_window)->desired_matrix);
|
||||
#endif
|
||||
|
@ -1156,6 +1160,7 @@ prepare_desired_row (struct window *w, struct glyph_row *row, bool mode_line_p)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
/* Return a hash code for glyph row ROW, which may
|
||||
be from current or desired matrix of frame F. */
|
||||
|
@ -1248,6 +1253,7 @@ line_draw_cost (struct frame *f, struct glyph_matrix *matrix, int vpos)
|
|||
return len;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Return true if the glyph rows A and B have equal contents.
|
||||
MOUSE_FACE_P means compare the mouse_face_p flags of A and B, too. */
|
||||
|
@ -2160,7 +2166,7 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
|
|||
/* Allocate/reallocate window matrices. */
|
||||
allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)));
|
||||
|
||||
#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
|
||||
#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
|
||||
/* Allocate/ reallocate matrices of the dummy window used to display
|
||||
the menu bar under X when no X toolkit support is available. */
|
||||
{
|
||||
|
@ -2296,7 +2302,7 @@ free_glyphs (struct frame *f)
|
|||
if (!NILP (f->root_window))
|
||||
free_window_matrices (XWINDOW (f->root_window));
|
||||
|
||||
#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
|
||||
#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
|
||||
/* Free the dummy window for menu bars without X toolkit and its
|
||||
glyph matrices. */
|
||||
if (!NILP (f->menu_bar_window))
|
||||
|
@ -3234,7 +3240,7 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
|
|||
when pending input is detected. */
|
||||
update_begin (f);
|
||||
|
||||
#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
|
||||
#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
|
||||
/* Update the menu bar on X frames that don't have toolkit
|
||||
support. */
|
||||
if (WINDOWP (f->menu_bar_window))
|
||||
|
@ -5059,6 +5065,10 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
|
|||
static bool
|
||||
scrolling (struct frame *frame)
|
||||
{
|
||||
/* In fact this code should never be reached at all under
|
||||
Android. */
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
int unchanged_at_top, unchanged_at_bottom;
|
||||
int window_size;
|
||||
int changed_lines;
|
||||
|
@ -5149,6 +5159,7 @@ scrolling (struct frame *frame)
|
|||
free_at_end_vpos - unchanged_at_top);
|
||||
|
||||
SAFE_FREE ();
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5190,7 +5201,9 @@ count_match (struct glyph *str1, struct glyph *end1, struct glyph *str2, struct
|
|||
|
||||
/* Char insertion/deletion cost vector, from term.c */
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_TOTAL_COLS ((f))])
|
||||
#endif
|
||||
|
||||
|
||||
/* Perform a frame-based update on line VPOS in frame FRAME. */
|
||||
|
@ -5395,7 +5408,10 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
|
|||
tem = (nlen - nsp) - (olen - osp);
|
||||
if (endmatch && tem
|
||||
&& (!FRAME_CHAR_INS_DEL_OK (f)
|
||||
|| endmatch <= char_ins_del_cost (f)[tem]))
|
||||
#ifndef HAVE_ANDROID
|
||||
|| endmatch <= char_ins_del_cost (f)[tem]
|
||||
#endif
|
||||
))
|
||||
endmatch = 0;
|
||||
|
||||
/* nsp - osp is the distance to insert or delete.
|
||||
|
@ -5405,7 +5421,10 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
|
|||
|
||||
if (nsp != osp
|
||||
&& (!FRAME_CHAR_INS_DEL_OK (f)
|
||||
|| begmatch + endmatch <= char_ins_del_cost (f)[nsp - osp]))
|
||||
#ifndef HAVE_ANDROID
|
||||
|| begmatch + endmatch <= char_ins_del_cost (f)[nsp - osp]
|
||||
#endif
|
||||
))
|
||||
{
|
||||
begmatch = 0;
|
||||
endmatch = 0;
|
||||
|
@ -6528,6 +6547,15 @@ init_display_interactive (void)
|
|||
}
|
||||
#endif /* HAVE_X_WINDOWS */
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
if (!inhibit_window_system && android_init_gui)
|
||||
{
|
||||
Vinitial_window_system = Qandroid;
|
||||
android_term_init ();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NTGUI
|
||||
if (!inhibit_window_system)
|
||||
{
|
||||
|
@ -6582,6 +6610,7 @@ init_display_interactive (void)
|
|||
exit (1);
|
||||
}
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
{
|
||||
struct terminal *t;
|
||||
struct frame *f = XFRAME (selected_frame);
|
||||
|
@ -6624,6 +6653,11 @@ init_display_interactive (void)
|
|||
: Qnil));
|
||||
Fmodify_frame_parameters (selected_frame, tty_arg);
|
||||
}
|
||||
#else
|
||||
fatal ("Could not establish a connection to the Android application.\n"
|
||||
"Emacs does not work on text terminals when built to run as"
|
||||
" part of an Android application package.");
|
||||
#endif
|
||||
|
||||
{
|
||||
struct frame *sf = SELECTED_FRAME ();
|
||||
|
|
|
@ -33,6 +33,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
#include "android.h"
|
||||
#endif
|
||||
|
||||
#include "lisp.h"
|
||||
|
||||
#include <float.h>
|
||||
|
@ -1264,7 +1268,11 @@ is in general a comma-separated list. */)
|
|||
if (!pw)
|
||||
return Qnil;
|
||||
|
||||
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
|
||||
p = android_user_full_name (pw);
|
||||
#else
|
||||
p = USER_FULL_NAME;
|
||||
#endif
|
||||
/* Chop off everything after the first comma, since 'pw_gecos' is a
|
||||
comma-separated list. */
|
||||
q = strchr (p, ',');
|
||||
|
|
37
src/emacs.c
37
src/emacs.c
|
@ -33,6 +33,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include "lisp.h"
|
||||
#include "sysstdio.h"
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
#include "androidterm.h"
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWSNT
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
|
@ -137,6 +141,10 @@ extern char etext;
|
|||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
|
||||
#include "android.h"
|
||||
#endif
|
||||
|
||||
/* We don't guard this with HAVE_TREE_SITTER because treesit.o is
|
||||
always compiled (to provide treesit-available-p). */
|
||||
#include "treesit.h"
|
||||
|
@ -1123,7 +1131,7 @@ load_seccomp (const char *file)
|
|||
goto out;
|
||||
}
|
||||
struct stat stat;
|
||||
if (fstat (fd, &stat) != 0)
|
||||
if (sys_fstat (fd, &stat) != 0)
|
||||
{
|
||||
emacs_perror ("fstat");
|
||||
goto out;
|
||||
|
@ -1225,12 +1233,18 @@ maybe_load_seccomp (int argc, char **argv)
|
|||
|
||||
#endif /* SECCOMP_USABLE */
|
||||
|
||||
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
|
||||
int
|
||||
android_emacs_init (int argc, char **argv)
|
||||
#else
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
#endif
|
||||
{
|
||||
/* Variable near the bottom of the stack, and aligned appropriately
|
||||
for pointers. */
|
||||
void *stack_bottom_variable;
|
||||
int old_argc;
|
||||
|
||||
/* First, check whether we should apply a seccomp filter. This
|
||||
should come at the very beginning to allow the filter to protect
|
||||
|
@ -1425,8 +1439,10 @@ main (int argc, char **argv)
|
|||
|
||||
bool only_version = false;
|
||||
sort_args (argc, argv);
|
||||
argc = 0;
|
||||
while (argv[argc]) argc++;
|
||||
old_argc = argc, argc = 0;
|
||||
while (argv[argc]
|
||||
/* Don't allow going past argv. */
|
||||
&& argc < old_argc) argc++;
|
||||
|
||||
skip_args = 0;
|
||||
if (argmatch (argv, argc, "-version", "--version", 3, NULL, &skip_args))
|
||||
|
@ -2375,6 +2391,14 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
|
|||
#endif
|
||||
syms_of_fontset ();
|
||||
#endif /* HAVE_HAIKU */
|
||||
#ifdef HAVE_ANDROID
|
||||
syms_of_androidterm ();
|
||||
syms_of_androidfns ();
|
||||
syms_of_fontset ();
|
||||
#if !defined ANDROID_STUBIFY
|
||||
syms_of_androidfont ();
|
||||
#endif /* !ANDROID_STUBIFY */
|
||||
#endif /* HAVE_ANDROID */
|
||||
|
||||
syms_of_gnutls ();
|
||||
|
||||
|
@ -2436,6 +2460,10 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
|
|||
init_haiku_select ();
|
||||
#endif
|
||||
|
||||
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
|
||||
init_androidfont ();
|
||||
#endif
|
||||
|
||||
init_charset ();
|
||||
|
||||
/* This calls putenv and so must precede init_process_emacs. */
|
||||
|
@ -2950,7 +2978,7 @@ shut_down_emacs (int sig, Lisp_Object stuff)
|
|||
Vinhibit_redisplay = Qt;
|
||||
|
||||
/* If we are controlling the terminal, reset terminal modes. */
|
||||
#ifndef DOS_NT
|
||||
#if !defined DOS_NT && !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
|
||||
pid_t tpgrp = tcgetpgrp (STDIN_FILENO);
|
||||
if (tpgrp != -1 && tpgrp == getpgrp ())
|
||||
{
|
||||
|
@ -3469,6 +3497,7 @@ Special values:
|
|||
`windows-nt' compiled as a native W32 application.
|
||||
`cygwin' compiled using the Cygwin library.
|
||||
`haiku' compiled for a Haiku system.
|
||||
`android' compiled for Android.
|
||||
Anything else (in Emacs 26, the possibilities are: aix, berkeley-unix,
|
||||
hpux, usg-unix-v) indicates some sort of Unix system. */);
|
||||
Vsystem_type = intern_c_string (SYSTEM_TYPE);
|
||||
|
|
|
@ -18,6 +18,7 @@ GNU General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
|
||||
|
||||
/* Together with PATH_SITELOADSEARCH, this gives the default value of
|
||||
load-path, which is the search path for the Lisp function "load".
|
||||
|
@ -79,3 +80,24 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
|
||||
/* Where Emacs should look for the application default file. */
|
||||
#define PATH_X_DEFAULTS "/usr/lib/X11/%L/%T/%N%C%S:/usr/lib/X11/%l/%T/%N%C%S:/usr/lib/X11/%T/%N%C%S:/usr/lib/X11/%L/%T/%N%S:/usr/lib/X11/%l/%T/%N%S:/usr/lib/X11/%T/%N%S"
|
||||
|
||||
#else
|
||||
|
||||
/* Replace the defines above with links to files in the assets
|
||||
pseudo-directory. Preserve the extra spaces, or epaths.in will not
|
||||
be generated correctly. */
|
||||
|
||||
# define PATH_EXEC (android_lib_dir)
|
||||
# define PATH_LOADSEARCH "/assets/lisp/"
|
||||
# define PATH_SITELOADSEARCH (android_site_load_path)
|
||||
# define PATH_DUMPLOADSEARCH "/assets/lisp/"
|
||||
# define PATH_DATA "/assets/etc/"
|
||||
# define PATH_DOC "/assets/etc/"
|
||||
# define PATH_INFO "/assets/info/"
|
||||
# define PATH_GAME ""
|
||||
# define PATH_BITMAPS ""
|
||||
|
||||
extern char *android_site_load_path;
|
||||
extern char *android_lib_dir;
|
||||
|
||||
#endif
|
||||
|
|
25
src/fileio.c
25
src/fileio.c
|
@ -56,6 +56,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include "region-cache.h"
|
||||
#include "frame.h"
|
||||
|
||||
#if defined HAVE_ANDROID
|
||||
#include "android.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LINUX_FS_H
|
||||
# include <sys/ioctl.h>
|
||||
# include <linux/fs.h>
|
||||
|
@ -135,7 +139,6 @@ static dev_t timestamp_file_system;
|
|||
static Lisp_Object Vwrite_region_annotation_buffers;
|
||||
|
||||
static Lisp_Object emacs_readlinkat (int, char const *);
|
||||
static Lisp_Object file_name_directory (Lisp_Object);
|
||||
static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
|
||||
Lisp_Object *, struct coding_system *);
|
||||
static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
|
||||
|
@ -160,6 +163,12 @@ file_access_p (char const *file, int amode)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
|
||||
/* FILE may be some kind of special Android file. */
|
||||
if (android_file_access_p (file, amode))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
if (faccessat (AT_FDCWD, file, amode, AT_EACCESS) == 0)
|
||||
return true;
|
||||
|
||||
|
@ -370,7 +379,7 @@ Given a Unix syntax file name, returns a string ending in slash. */)
|
|||
/* Return the directory component of FILENAME, or nil if FILENAME does
|
||||
not contain a directory component. */
|
||||
|
||||
static Lisp_Object
|
||||
Lisp_Object
|
||||
file_name_directory (Lisp_Object filename)
|
||||
{
|
||||
char *beg = SSDATA (filename);
|
||||
|
@ -2227,7 +2236,7 @@ permissions. */)
|
|||
|
||||
record_unwind_protect_int (close_file_unwind, ifd);
|
||||
|
||||
if (fstat (ifd, &st) != 0)
|
||||
if (sys_fstat (ifd, &st) != 0)
|
||||
report_file_error ("Input file status", file);
|
||||
|
||||
if (!NILP (preserve_permissions))
|
||||
|
@ -2273,7 +2282,7 @@ permissions. */)
|
|||
if (already_exists)
|
||||
{
|
||||
struct stat out_st;
|
||||
if (fstat (ofd, &out_st) != 0)
|
||||
if (sys_fstat (ofd, &out_st) != 0)
|
||||
report_file_error ("Output file status", newname);
|
||||
if (st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
|
||||
report_file_errno ("Input and output files are the same",
|
||||
|
@ -3078,7 +3087,7 @@ file_directory_p (Lisp_Object file)
|
|||
errno = ENOTDIR; /* like the non-DOS_NT branch below does */
|
||||
return retval;
|
||||
#else
|
||||
# ifdef O_PATH
|
||||
# if defined O_PATH && !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
|
||||
/* Use O_PATH if available, as it avoids races and EOVERFLOW issues. */
|
||||
int fd = emacs_openat (AT_FDCWD, SSDATA (file),
|
||||
O_PATH | O_CLOEXEC | O_DIRECTORY, 0);
|
||||
|
@ -4002,7 +4011,7 @@ by calling `format-decode', which see. */)
|
|||
XCAR (XCAR (window_markers)));
|
||||
}
|
||||
|
||||
if (fstat (fd, &st) != 0)
|
||||
if (sys_fstat (fd, &st) != 0)
|
||||
report_file_error ("Input file status", orig_filename);
|
||||
mtime = get_stat_mtime (&st);
|
||||
|
||||
|
@ -5394,7 +5403,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
|
|||
modtime = invalid_timespec ();
|
||||
if (visiting)
|
||||
{
|
||||
if (fstat (desc, &st) == 0)
|
||||
if (sys_fstat (desc, &st) == 0)
|
||||
modtime = get_stat_mtime (&st);
|
||||
else
|
||||
ok = 0, save_errno = errno;
|
||||
|
@ -5432,7 +5441,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
|
|||
if (desc1 >= 0)
|
||||
{
|
||||
struct stat st1;
|
||||
if (fstat (desc1, &st1) == 0
|
||||
if (sys_fstat (desc1, &st1) == 0
|
||||
&& st.st_dev == st1.st_dev && st.st_ino == st1.st_ino)
|
||||
{
|
||||
/* Use the heuristic if it appears to be valid. With neither
|
||||
|
|
|
@ -120,6 +120,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
* Non-forced locks on non-MS-Windows systems that support neither
|
||||
hard nor symbolic links. */
|
||||
|
||||
/* Boot time is not available on Android. */
|
||||
|
||||
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
|
||||
#undef BOOT_TIME
|
||||
#endif
|
||||
|
||||
|
||||
/* Return the time of the last system boot. */
|
||||
|
||||
|
|
|
@ -3519,6 +3519,10 @@ The data read from the system are decoded using `locale-coding-system'. */)
|
|||
(Lisp_Object item)
|
||||
{
|
||||
char *str = NULL;
|
||||
|
||||
/* STR is apparently unused on Android. */
|
||||
((void) str);
|
||||
|
||||
#ifdef HAVE_LANGINFO_CODESET
|
||||
if (EQ (item, Qcodeset))
|
||||
{
|
||||
|
|
16
src/font.c
16
src/font.c
|
@ -180,6 +180,22 @@ font_make_entity (void)
|
|||
return font_entity;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
|
||||
Lisp_Object
|
||||
font_make_entity_android (int size)
|
||||
{
|
||||
Lisp_Object font_entity;
|
||||
struct font_entity *entity
|
||||
= ((struct font_entity *)
|
||||
allocate_pseudovector (size, FONT_ENTITY_MAX, FONT_ENTITY_MAX,
|
||||
PVEC_FONT));
|
||||
XSETFONT (font_entity, entity);
|
||||
return font_entity;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Create a font-object whose structure size is SIZE. If ENTITY is
|
||||
not nil, copy properties from ENTITY to the font-object. If
|
||||
PIXELSIZE is positive, set the `size' property to PIXELSIZE. */
|
||||
|
|
|
@ -823,6 +823,9 @@ extern Lisp_Object copy_font_spec (Lisp_Object);
|
|||
extern Lisp_Object merge_font_spec (Lisp_Object, Lisp_Object);
|
||||
|
||||
extern Lisp_Object font_make_entity (void);
|
||||
#ifdef HAVE_ANDROID
|
||||
extern Lisp_Object font_make_entity_android (int);
|
||||
#endif
|
||||
extern Lisp_Object font_make_object (int, Lisp_Object, int);
|
||||
#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) || defined (HAVE_NS)
|
||||
extern Lisp_Object font_build_object (int, Lisp_Object, Lisp_Object, double);
|
||||
|
|
30
src/frame.c
30
src/frame.c
|
@ -228,6 +228,7 @@ Value is:
|
|||
`pc' for a direct-write MS-DOS frame,
|
||||
`pgtk' for an Emacs frame running on pure GTK.
|
||||
`haiku' for an Emacs frame running in Haiku.
|
||||
`android' for an Emacs frame running in Android.
|
||||
See also `frame-live-p'. */)
|
||||
(Lisp_Object object)
|
||||
{
|
||||
|
@ -250,6 +251,8 @@ See also `frame-live-p'. */)
|
|||
return Qpgtk;
|
||||
case output_haiku:
|
||||
return Qhaiku;
|
||||
case output_android:
|
||||
return Qandroid;
|
||||
default:
|
||||
emacs_abort ();
|
||||
}
|
||||
|
@ -279,6 +282,7 @@ The value is a symbol:
|
|||
`pc' for a direct-write MS-DOS frame.
|
||||
`pgtk' for an Emacs frame using pure GTK facilities.
|
||||
`haiku' for an Emacs frame running in Haiku.
|
||||
`android' for an Emacs frame running in Android/
|
||||
|
||||
FRAME defaults to the currently selected frame.
|
||||
|
||||
|
@ -1228,6 +1232,7 @@ make_initial_frame (void)
|
|||
return f;
|
||||
}
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
static struct frame *
|
||||
make_terminal_frame (struct terminal *terminal)
|
||||
|
@ -1317,6 +1322,8 @@ get_future_frame_param (Lisp_Object parameter,
|
|||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
|
||||
1, 1, 0,
|
||||
doc: /* Create an additional terminal frame, possibly on another terminal.
|
||||
|
@ -1336,6 +1343,10 @@ Note that changing the size of one terminal frame automatically
|
|||
affects all frames on the same terminal device. */)
|
||||
(Lisp_Object parms)
|
||||
{
|
||||
#ifdef HAVE_ANDROID
|
||||
error ("Text terminals are not supported on this platform");
|
||||
return Qnil;
|
||||
#else
|
||||
struct frame *f;
|
||||
struct terminal *t = NULL;
|
||||
Lisp_Object frame;
|
||||
|
@ -1436,6 +1447,7 @@ affects all frames on the same terminal device. */)
|
|||
f->after_make_frame = true;
|
||||
|
||||
return frame;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -5303,16 +5315,23 @@ gui_display_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
|
|||
*nz++ = '.';
|
||||
lispstpcpy (nz, attribute);
|
||||
|
||||
const char *value =
|
||||
dpyinfo->terminal->get_string_resource_hook (&dpyinfo->rdb,
|
||||
name_key,
|
||||
class_key);
|
||||
SAFE_FREE();
|
||||
#ifndef HAVE_ANDROID
|
||||
const char *value
|
||||
= dpyinfo->terminal->get_string_resource_hook (&dpyinfo->rdb,
|
||||
name_key,
|
||||
class_key);
|
||||
|
||||
SAFE_FREE ();
|
||||
|
||||
if (value && *value)
|
||||
return build_string (value);
|
||||
else
|
||||
return Qnil;
|
||||
#else
|
||||
|
||||
SAFE_FREE ();
|
||||
return Qnil;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -6218,6 +6237,7 @@ syms_of_frame (void)
|
|||
DEFSYM (Qns, "ns");
|
||||
DEFSYM (Qpgtk, "pgtk");
|
||||
DEFSYM (Qhaiku, "haiku");
|
||||
DEFSYM (Qandroid, "android");
|
||||
DEFSYM (Qvisible, "visible");
|
||||
DEFSYM (Qbuffer_predicate, "buffer-predicate");
|
||||
DEFSYM (Qbuffer_list, "buffer-list");
|
||||
|
|
35
src/frame.h
35
src/frame.h
|
@ -181,7 +181,7 @@ struct frame
|
|||
most recently buried buffer is first. For last-buffer. */
|
||||
Lisp_Object buried_buffer_list;
|
||||
|
||||
#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
|
||||
#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
|
||||
/* A dummy window used to display menu bars under X when no X
|
||||
toolkit support is available. */
|
||||
Lisp_Object menu_bar_window;
|
||||
|
@ -377,7 +377,7 @@ struct frame
|
|||
/* The output method says how the contents of this frame are
|
||||
displayed. It could be using termcap, or using an X window.
|
||||
This must be the same as the terminal->type. */
|
||||
ENUM_BF (output_method) output_method : 3;
|
||||
ENUM_BF (output_method) output_method : 4;
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
/* True if this frame is a tooltip frame. */
|
||||
|
@ -586,12 +586,13 @@ struct frame
|
|||
well. */
|
||||
union output_data
|
||||
{
|
||||
struct tty_output *tty; /* From termchar.h. */
|
||||
struct x_output *x; /* From xterm.h. */
|
||||
struct w32_output *w32; /* From w32term.h. */
|
||||
struct ns_output *ns; /* From nsterm.h. */
|
||||
struct pgtk_output *pgtk; /* From pgtkterm.h. */
|
||||
struct haiku_output *haiku; /* From haikuterm.h. */
|
||||
struct tty_output *tty; /* From termchar.h. */
|
||||
struct x_output *x; /* From xterm.h. */
|
||||
struct w32_output *w32; /* From w32term.h. */
|
||||
struct ns_output *ns; /* From nsterm.h. */
|
||||
struct pgtk_output *pgtk; /* From pgtkterm.h. */
|
||||
struct haiku_output *haiku; /* From haikuterm.h. */
|
||||
struct android_output *android; /* From androidterm.h. */
|
||||
}
|
||||
output_data;
|
||||
|
||||
|
@ -713,7 +714,7 @@ fset_menu_bar_vector (struct frame *f, Lisp_Object val)
|
|||
{
|
||||
f->menu_bar_vector = val;
|
||||
}
|
||||
#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
|
||||
#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
|
||||
INLINE void
|
||||
fset_menu_bar_window (struct frame *f, Lisp_Object val)
|
||||
{
|
||||
|
@ -872,6 +873,11 @@ default_pixels_per_inch_y (void)
|
|||
#else
|
||||
#define FRAME_HAIKU_P(f) ((f)->output_method == output_haiku)
|
||||
#endif
|
||||
#ifndef HAVE_ANDROID
|
||||
#define FRAME_ANDROID_P(f) false
|
||||
#else
|
||||
#define FRAME_ANDROID_P(f) ((f)->output_method == output_android)
|
||||
#endif
|
||||
|
||||
/* FRAME_WINDOW_P tests whether the frame is a graphical window system
|
||||
frame. */
|
||||
|
@ -890,6 +896,9 @@ default_pixels_per_inch_y (void)
|
|||
#ifdef HAVE_HAIKU
|
||||
#define FRAME_WINDOW_P(f) FRAME_HAIKU_P (f)
|
||||
#endif
|
||||
#ifdef HAVE_ANDROID
|
||||
#define FRAME_WINDOW_P(f) FRAME_ANDROID_P (f)
|
||||
#endif
|
||||
#ifndef FRAME_WINDOW_P
|
||||
#define FRAME_WINDOW_P(f) ((void) (f), false)
|
||||
#endif
|
||||
|
@ -917,11 +926,17 @@ default_pixels_per_inch_y (void)
|
|||
frame F. We need to define two versions because a TTY-only build
|
||||
does not have FRAME_DISPLAY_INFO. */
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
#ifndef HAVE_ANDROID
|
||||
# define MOUSE_HL_INFO(F) \
|
||||
(FRAME_WINDOW_P(F) \
|
||||
(FRAME_WINDOW_P (F) \
|
||||
? &FRAME_DISPLAY_INFO(F)->mouse_highlight \
|
||||
: &(F)->output_data.tty->display_info->mouse_highlight)
|
||||
#else
|
||||
/* There is no "struct tty_output" on Android at all. */
|
||||
# define MOUSE_HL_INFO(F) \
|
||||
(&FRAME_DISPLAY_INFO(F)->mouse_highlight)
|
||||
#endif
|
||||
#else
|
||||
# define MOUSE_HL_INFO(F) \
|
||||
(&(F)->output_data.tty->display_info->mouse_highlight)
|
||||
#endif
|
||||
|
|
88
src/image.c
88
src/image.c
|
@ -175,6 +175,28 @@ typedef struct haiku_bitmap_record Bitmap_Record;
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
#include "androidterm.h"
|
||||
typedef struct android_bitmap_record Bitmap_Record;
|
||||
|
||||
/* TODO: implement images on Android. */
|
||||
#define GET_PIXEL(ximg, x, y) 0
|
||||
#define PUT_PIXEL(ximg, x, y, pixel) ((void) (pixel))
|
||||
#define NO_PIXMAP 0
|
||||
|
||||
#define PIX_MASK_RETAIN 0
|
||||
#define PIX_MASK_DRAW 1
|
||||
|
||||
#define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b))
|
||||
#define RED_FROM_ULONG(color) (((color) >> 16) & 0xff)
|
||||
#define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
|
||||
#define BLUE_FROM_ULONG(color) ((color) & 0xff)
|
||||
#define RED16_FROM_ULONG(color) (RED_FROM_ULONG (color) * 0x101)
|
||||
#define GREEN16_FROM_ULONG(color) (GREEN_FROM_ULONG (color) * 0x101)
|
||||
#define BLUE16_FROM_ULONG(color) (BLUE_FROM_ULONG (color) * 0x101)
|
||||
|
||||
#endif
|
||||
|
||||
static void image_disable_image (struct frame *, struct image *);
|
||||
static void image_edge_detection (struct frame *, struct image *, Lisp_Object,
|
||||
Lisp_Object);
|
||||
|
@ -831,6 +853,18 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file)
|
|||
xfree (contents);
|
||||
return id;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
#ifdef ANDROID_STUBIFY
|
||||
((void) dpyinfo);
|
||||
|
||||
/* This function should never be called when building stubs. */
|
||||
emacs_abort ();
|
||||
#else
|
||||
/* you lose, not yet implemented TODO */
|
||||
return 0;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Free bitmap B. */
|
||||
|
@ -3338,6 +3372,16 @@ image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int d
|
|||
Emacs_Pix_Container *pimg,
|
||||
Emacs_Pixmap *pixmap, Picture *picture)
|
||||
{
|
||||
#ifdef HAVE_ANDROID
|
||||
#ifdef ANDROID_STUBIFY
|
||||
/* This function should never be called when building stubs. */
|
||||
emacs_abort ();
|
||||
#else
|
||||
/* you lose, not yet implemented TODO */
|
||||
return false;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_CAIRO
|
||||
eassert (input_blocked_p ());
|
||||
|
||||
|
@ -3646,6 +3690,16 @@ image_unget_x_image_or_dc (struct image *img, bool mask_p,
|
|||
static Emacs_Pix_Container
|
||||
image_get_x_image (struct frame *f, struct image *img, bool mask_p)
|
||||
{
|
||||
#ifdef HAVE_ANDROID
|
||||
#ifdef ANDROID_STUBIFY
|
||||
/* This function should never be called when building stubs. */
|
||||
emacs_abort ();
|
||||
#else
|
||||
/* you lose, not yet implemented TODO */
|
||||
return 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined USE_CAIRO || defined (HAVE_HAIKU)
|
||||
return !mask_p ? img->pixmap : img->mask;
|
||||
#elif defined HAVE_X_WINDOWS
|
||||
|
@ -3756,7 +3810,7 @@ slurp_file (int fd, ptrdiff_t *size)
|
|||
specpdl_ref count = SPECPDL_INDEX ();
|
||||
record_unwind_protect_ptr (fclose_unwind, fp);
|
||||
|
||||
if (fstat (fileno (fp), &st) == 0
|
||||
if (sys_fstat (fileno (fp), &st) == 0
|
||||
&& 0 <= st.st_size && st.st_size < min (PTRDIFF_MAX, SIZE_MAX))
|
||||
{
|
||||
/* Report an error if we read past the purported EOF.
|
||||
|
@ -6074,7 +6128,8 @@ lookup_rgb_color (struct frame *f, int r, int g, int b)
|
|||
{
|
||||
#ifdef HAVE_NTGUI
|
||||
return PALETTERGB (r >> 8, g >> 8, b >> 8);
|
||||
#elif defined USE_CAIRO || defined HAVE_NS || defined HAVE_HAIKU
|
||||
#elif defined USE_CAIRO || defined HAVE_NS || defined HAVE_HAIKU \
|
||||
|| defined HAVE_ANDROID
|
||||
return RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
|
||||
#else
|
||||
xsignal1 (Qfile_error,
|
||||
|
@ -6147,7 +6202,8 @@ image_to_emacs_colors (struct frame *f, struct image *img, bool rgb_p)
|
|||
p = colors;
|
||||
for (y = 0; y < img->height; ++y)
|
||||
{
|
||||
#if !defined USE_CAIRO && !defined HAVE_NS && !defined HAVE_HAIKU
|
||||
#if !defined USE_CAIRO && !defined HAVE_NS && !defined HAVE_HAIKU \
|
||||
&& !defined HAVE_ANDROID
|
||||
Emacs_Color *row = p;
|
||||
for (x = 0; x < img->width; ++x, ++p)
|
||||
p->pixel = GET_PIXEL (ximg, x, y);
|
||||
|
@ -6155,7 +6211,7 @@ image_to_emacs_colors (struct frame *f, struct image *img, bool rgb_p)
|
|||
{
|
||||
FRAME_TERMINAL (f)->query_colors (f, row, img->width);
|
||||
}
|
||||
#else /* USE_CAIRO || HAVE_NS || HAVE_HAIKU */
|
||||
#else /* USE_CAIRO || HAVE_NS || HAVE_HAIKU || HAVE_ANDROID */
|
||||
for (x = 0; x < img->width; ++x, ++p)
|
||||
{
|
||||
p->pixel = GET_PIXEL (ximg, x, y);
|
||||
|
@ -6166,7 +6222,7 @@ image_to_emacs_colors (struct frame *f, struct image *img, bool rgb_p)
|
|||
p->blue = BLUE16_FROM_ULONG (p->pixel);
|
||||
}
|
||||
}
|
||||
#endif /* USE_CAIRO || HAVE_NS */
|
||||
#endif /* USE_CAIRO || HAVE_NS || HAVE_ANDROID */
|
||||
}
|
||||
|
||||
image_unget_x_image_or_dc (img, 0, ximg, prev);
|
||||
|
@ -6231,7 +6287,11 @@ image_from_emacs_colors (struct frame *f, struct image *img, Emacs_Color *colors
|
|||
Emacs_Pix_Container ximage;
|
||||
Emacs_Color *p;
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
ximage = NULL;
|
||||
#else
|
||||
ximage = 0;
|
||||
#endif
|
||||
|
||||
init_color_table ();
|
||||
|
||||
|
@ -6393,7 +6453,9 @@ image_edge_detection (struct frame *f, struct image *img,
|
|||
}
|
||||
|
||||
|
||||
#if defined HAVE_X_WINDOWS || defined USE_CAIRO || defined HAVE_HAIKU
|
||||
#if defined HAVE_X_WINDOWS || defined USE_CAIRO || defined HAVE_HAIKU \
|
||||
|| defined HAVE_ANDROID
|
||||
|
||||
static void
|
||||
image_pixmap_draw_cross (struct frame *f, Emacs_Pixmap pixmap,
|
||||
int x, int y, unsigned int width, unsigned int height,
|
||||
|
@ -6429,8 +6491,16 @@ image_pixmap_draw_cross (struct frame *f, Emacs_Pixmap pixmap,
|
|||
XFreeGC (dpy, gc);
|
||||
#elif HAVE_HAIKU
|
||||
be_draw_cross_on_pixmap (pixmap, x, y, width, height, color);
|
||||
#elif HAVE_ANDROID
|
||||
#ifdef ANDROID_STUBIFY
|
||||
/* This function should never be called when building stubs. */
|
||||
emacs_abort ();
|
||||
#else
|
||||
/* you lose, not yet implemented TODO */
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* HAVE_X_WINDOWS || USE_CAIRO || HAVE_HAIKU */
|
||||
|
||||
/* Transform image IMG on frame F so that it looks disabled. */
|
||||
|
@ -6474,7 +6544,7 @@ image_disable_image (struct frame *f, struct image *img)
|
|||
#ifndef HAVE_NTGUI
|
||||
#ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */
|
||||
|
||||
#if !defined USE_CAIRO && !defined HAVE_HAIKU
|
||||
#if !defined USE_CAIRO && !defined HAVE_HAIKU && !defined HAVE_ANDROID
|
||||
#define CrossForeground(f) BLACK_PIX_DEFAULT (f)
|
||||
#define MaskForeground(f) WHITE_PIX_DEFAULT (f)
|
||||
#else /* USE_CAIRO || HAVE_HAIKU */
|
||||
|
@ -6482,7 +6552,7 @@ image_disable_image (struct frame *f, struct image *img)
|
|||
#define MaskForeground(f) PIX_MASK_DRAW
|
||||
#endif /* USE_CAIRO || HAVE_HAIKU */
|
||||
|
||||
#if !defined USE_CAIRO && !defined HAVE_HAIKU
|
||||
#if !defined USE_CAIRO && !defined HAVE_HAIKU && !defined HAVE_ANDROID
|
||||
image_sync_to_pixmaps (f, img);
|
||||
#endif /* !USE_CAIRO && !HAVE_HAIKU */
|
||||
image_pixmap_draw_cross (f, img->pixmap, 0, 0, img->width, img->height,
|
||||
|
@ -9099,7 +9169,7 @@ gif_load (struct frame *f, struct image *img)
|
|||
`image-cache-size'. */
|
||||
struct stat st;
|
||||
FILE *fp = fopen (SSDATA (encoded_file), "rb");
|
||||
if (fstat (fileno (fp), &st) == 0)
|
||||
if (sys_fstat (fileno (fp), &st) == 0)
|
||||
byte_size = st.st_size;
|
||||
fclose (fp);
|
||||
}
|
||||
|
|
12
src/lisp.h
12
src/lisp.h
|
@ -30,6 +30,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <attribute.h>
|
||||
#include <intprops.h>
|
||||
#include <verify.h>
|
||||
|
@ -4726,6 +4730,7 @@ extern void syms_of_marker (void);
|
|||
|
||||
/* Defined in fileio.c. */
|
||||
|
||||
extern Lisp_Object file_name_directory (Lisp_Object);
|
||||
extern char *splice_dir_file (char *, char const *, char const *)
|
||||
ATTRIBUTE_RETURNS_NONNULL;
|
||||
extern bool file_name_absolute_p (const char *);
|
||||
|
@ -5063,7 +5068,12 @@ extern void init_random (void);
|
|||
extern void emacs_backtrace (int);
|
||||
extern AVOID emacs_abort (void) NO_INLINE;
|
||||
extern int emacs_fstatat (int, char const *, void *, int);
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
extern int sys_fstat (int, struct stat *);
|
||||
#endif
|
||||
#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
|
||||
extern int emacs_openat (int, char const *, int, int);
|
||||
#endif
|
||||
extern int emacs_open (const char *, int, int);
|
||||
extern int emacs_open_noquit (const char *, int, int);
|
||||
extern int emacs_pipe (int[2]);
|
||||
|
@ -5101,7 +5111,9 @@ extern Lisp_Object directory_files_internal (Lisp_Object, Lisp_Object,
|
|||
bool, Lisp_Object, Lisp_Object);
|
||||
|
||||
/* Defined in term.c. */
|
||||
#ifndef HAVE_ANDROID
|
||||
extern int *char_ins_del_vector;
|
||||
#endif
|
||||
extern void syms_of_term (void);
|
||||
extern AVOID fatal (const char *msgid, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
|
||||
|
||||
|
|
|
@ -1047,7 +1047,7 @@ safe_to_load_version (Lisp_Object file, int fd)
|
|||
|
||||
/* If the file is not regular, then we cannot safely seek it.
|
||||
Assume that it is not safe to load as a compiled file. */
|
||||
if (fstat (fd, &st) == 0 && !S_ISREG (st.st_mode))
|
||||
if (sys_fstat (fd, &st) == 0 && !S_ISREG (st.st_mode))
|
||||
return 0;
|
||||
|
||||
/* Read the first few bytes from the file, and look for a line
|
||||
|
@ -1676,7 +1676,7 @@ maybe_swap_for_eln1 (Lisp_Object src_name, Lisp_Object eln_name,
|
|||
|
||||
if (eln_fd > 0)
|
||||
{
|
||||
if (fstat (eln_fd, &eln_st) || S_ISDIR (eln_st.st_mode))
|
||||
if (sys_fstat (eln_fd, &eln_st) || S_ISDIR (eln_st.st_mode))
|
||||
emacs_close (eln_fd);
|
||||
else
|
||||
{
|
||||
|
@ -1998,7 +1998,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
|
|||
}
|
||||
else
|
||||
{
|
||||
int err = (fstat (fd, &st) != 0 ? errno
|
||||
int err = (sys_fstat (fd, &st) != 0 ? errno
|
||||
: S_ISDIR (st.st_mode) ? EISDIR : 0);
|
||||
if (err)
|
||||
{
|
||||
|
|
|
@ -5620,7 +5620,7 @@ pdumper_load (const char *dump_filename, char *argv0)
|
|||
}
|
||||
|
||||
err = PDUMPER_LOAD_FILE_NOT_FOUND;
|
||||
if (fstat (dump_fd, &stat) < 0)
|
||||
if (sys_fstat (dump_fd, &stat) < 0)
|
||||
goto out;
|
||||
|
||||
err = PDUMPER_LOAD_BAD_FILE_TYPE;
|
||||
|
|
|
@ -119,6 +119,10 @@ static struct rlimit nofile_limit;
|
|||
#include "gnutls.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
#include "android.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
#include TERM_HEADER
|
||||
#endif /* HAVE_WINDOW_SYSTEM */
|
||||
|
@ -5679,7 +5683,17 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
|
|||
timeout = short_timeout;
|
||||
#endif
|
||||
|
||||
/* Non-macOS HAVE_GLIB builds call thread_select in xgselect.c. */
|
||||
/* Android doesn't support threads and requires using a
|
||||
replacement for pselect in android.c to poll for
|
||||
events. */
|
||||
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
|
||||
nfds = android_select (max_desc + 1,
|
||||
&Available, (check_write ? &Writeok : 0),
|
||||
NULL, &timeout, NULL);
|
||||
#else
|
||||
|
||||
/* Non-macOS HAVE_GLIB builds call thread_select in
|
||||
xgselect.c. */
|
||||
#if defined HAVE_GLIB && !defined HAVE_NS
|
||||
nfds = xg_select (max_desc + 1,
|
||||
&Available, (check_write ? &Writeok : 0),
|
||||
|
@ -5695,6 +5709,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
|
|||
(check_write ? &Writeok : 0),
|
||||
NULL, &timeout, NULL);
|
||||
#endif /* !HAVE_GLIB */
|
||||
#endif /* HAVE_ANDROID && !ANDROID_STUBIFY */
|
||||
|
||||
#ifdef HAVE_GNUTLS
|
||||
/* Merge tls_available into Available. */
|
||||
|
|
|
@ -21,6 +21,11 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
|
||||
#include <config.h>
|
||||
|
||||
/* The entire file is defined out under Android, where there is no
|
||||
text terminal support of any kind. */
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
#include "lisp.h"
|
||||
#include "termchar.h"
|
||||
#include "dispextern.h"
|
||||
|
@ -984,3 +989,5 @@ do_line_insertion_deletion_costs (struct frame *frame,
|
|||
FRAME_DELETE_COST (frame), FRAME_DELETEN_COST (frame),
|
||||
coefficient);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
98
src/sysdep.c
98
src/sysdep.c
|
@ -134,6 +134,10 @@ int _cdecl _spawnlp (int, const char *, const char *, ...);
|
|||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
#include "android.h"
|
||||
#endif
|
||||
|
||||
/* Declare here, including term.h is problematic on some systems. */
|
||||
extern void tputs (const char *, int, int (*)(int));
|
||||
|
||||
|
@ -790,6 +794,7 @@ init_sigio (int fd)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
#ifndef DOS_NT
|
||||
#ifdef F_SETOWN
|
||||
static void
|
||||
|
@ -801,6 +806,7 @@ reset_sigio (int fd)
|
|||
}
|
||||
#endif /* F_SETOWN */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void
|
||||
request_sigio (void)
|
||||
|
@ -972,6 +978,8 @@ narrow_foreground_group (int fd)
|
|||
tcsetpgrp_without_stopping (fd, getpid ());
|
||||
}
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
/* Set the tty to our original foreground group. */
|
||||
static void
|
||||
widen_foreground_group (int fd)
|
||||
|
@ -979,6 +987,9 @@ widen_foreground_group (int fd)
|
|||
if (inherited_pgroup && setpgid (0, inherited_pgroup) == 0)
|
||||
tcsetpgrp_without_stopping (fd, inherited_pgroup);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Getting and setting emacs_tty structures. */
|
||||
|
||||
|
@ -1496,6 +1507,8 @@ reset_sys_modes (struct tty_display_info *tty_out)
|
|||
fflush (stdout);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
if (!tty_out->term_initted)
|
||||
return;
|
||||
|
||||
|
@ -1552,6 +1565,7 @@ reset_sys_modes (struct tty_display_info *tty_out)
|
|||
#endif
|
||||
|
||||
widen_foreground_group (fileno (tty_out->input));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_PTYS
|
||||
|
@ -1802,7 +1816,11 @@ handle_arith_signal (int sig)
|
|||
xsignal0 (Qarith_error);
|
||||
}
|
||||
|
||||
#if defined HAVE_STACK_OVERFLOW_HANDLING && !defined WINDOWSNT
|
||||
/* This does not work on Android and interferes with the system
|
||||
tombstone generation. */
|
||||
|
||||
#if defined HAVE_STACK_OVERFLOW_HANDLING && !defined WINDOWSNT \
|
||||
&& (!defined HAVE_ANDROID || defined ANDROID_STUBIFY)
|
||||
|
||||
/* Alternate stack used by SIGSEGV handler below. */
|
||||
|
||||
|
@ -1914,12 +1932,16 @@ init_sigsegv (void)
|
|||
|
||||
#else /* not HAVE_STACK_OVERFLOW_HANDLING or WINDOWSNT */
|
||||
|
||||
#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
|
||||
|
||||
static bool
|
||||
init_sigsegv (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_STACK_OVERFLOW_HANDLING && !WINDOWSNT */
|
||||
|
||||
static void
|
||||
|
@ -2020,12 +2042,17 @@ init_signals (void)
|
|||
sigaction (SIGFPE, &action, 0);
|
||||
}
|
||||
|
||||
/* SIGUSR1 and SIGUSR2 are used internally by the android_select
|
||||
function. */
|
||||
#if !defined HAVE_ANDROID
|
||||
#ifdef SIGUSR1
|
||||
add_user_signal (SIGUSR1, "sigusr1");
|
||||
#endif
|
||||
#ifdef SIGUSR2
|
||||
add_user_signal (SIGUSR2, "sigusr2");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
sigaction (SIGABRT, &thread_fatal_action, 0);
|
||||
#ifdef SIGPRE
|
||||
sigaction (SIGPRE, &thread_fatal_action, 0);
|
||||
|
@ -2051,8 +2078,10 @@ init_signals (void)
|
|||
#ifdef SIGBUS
|
||||
sigaction (SIGBUS, &thread_fatal_action, 0);
|
||||
#endif
|
||||
#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
|
||||
if (!init_sigsegv ())
|
||||
sigaction (SIGSEGV, &thread_fatal_action, 0);
|
||||
#endif
|
||||
#ifdef SIGSYS
|
||||
sigaction (SIGSYS, &thread_fatal_action, 0);
|
||||
#endif
|
||||
|
@ -2328,11 +2357,20 @@ int
|
|||
emacs_fstatat (int dirfd, char const *filename, void *st, int flags)
|
||||
{
|
||||
int r;
|
||||
while ((r = fstatat (dirfd, filename, st, flags)) != 0 && errno == EINTR)
|
||||
#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
|
||||
while ((r = fstatat (dirfd, filename, st, flags)) != 0
|
||||
&& errno == EINTR)
|
||||
maybe_quit ();
|
||||
#else
|
||||
while ((r = android_fstatat (dirfd, filename, st, flags)) != 0
|
||||
&& errno == EINTR)
|
||||
maybe_quit ();
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
|
||||
|
||||
static int
|
||||
sys_openat (int dirfd, char const *file, int oflags, int mode)
|
||||
{
|
||||
|
@ -2347,6 +2385,18 @@ sys_openat (int dirfd, char const *file, int oflags, int mode)
|
|||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
sys_fstat (int fd, struct stat *statb)
|
||||
{
|
||||
#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
|
||||
return fstat (fd, statb);
|
||||
#else
|
||||
return android_fstat (fd, statb);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Assuming the directory DIRFD, open FILE for Emacs use,
|
||||
using open flags OFLAGS and mode MODE.
|
||||
Use binary I/O on systems that care about text vs binary I/O.
|
||||
|
@ -2355,6 +2405,8 @@ sys_openat (int dirfd, char const *file, int oflags, int mode)
|
|||
Do not fail merely because the open was interrupted by a signal.
|
||||
Allow the user to quit. */
|
||||
|
||||
#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
|
||||
|
||||
int
|
||||
emacs_openat (int dirfd, char const *file, int oflags, int mode)
|
||||
{
|
||||
|
@ -2367,10 +2419,23 @@ emacs_openat (int dirfd, char const *file, int oflags, int mode)
|
|||
return fd;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
emacs_open (char const *file, int oflags, int mode)
|
||||
{
|
||||
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
|
||||
int fd;
|
||||
#endif
|
||||
|
||||
#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
|
||||
return emacs_openat (AT_FDCWD, file, oflags, mode);
|
||||
#else
|
||||
while ((fd = android_open (file, oflags, mode)) < 0 && errno == EINTR)
|
||||
maybe_quit ();
|
||||
|
||||
return fd;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Same as above, but doesn't allow the user to quit. */
|
||||
|
@ -2382,9 +2447,15 @@ emacs_open_noquit (char const *file, int oflags, int mode)
|
|||
if (! (oflags & O_TEXT))
|
||||
oflags |= O_BINARY;
|
||||
oflags |= O_CLOEXEC;
|
||||
#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
|
||||
do
|
||||
fd = open (file, oflags, mode);
|
||||
while (fd < 0 && errno == EINTR);
|
||||
#else
|
||||
do
|
||||
fd = android_open (file, oflags, mode);
|
||||
while (fd < 0 && errno == EINTR);
|
||||
#endif
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
@ -2434,6 +2505,8 @@ emacs_pipe (int fd[2])
|
|||
For the background behind this mess, please see Austin Group defect 529
|
||||
<https://austingroupbugs.net/view.php?id=529>. */
|
||||
|
||||
#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
|
||||
|
||||
#ifndef POSIX_CLOSE_RESTART
|
||||
# define POSIX_CLOSE_RESTART 1
|
||||
static int
|
||||
|
@ -2460,6 +2533,8 @@ posix_close (int fd, int flag)
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Close FD, retrying if interrupted. If successful, return 0;
|
||||
otherwise, return -1 and set errno to a non-EINTR value. Consider
|
||||
an EINPROGRESS error to be successful, as that's merely a signal
|
||||
|
@ -2472,9 +2547,17 @@ posix_close (int fd, int flag)
|
|||
int
|
||||
emacs_close (int fd)
|
||||
{
|
||||
int r;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int r = posix_close (fd, POSIX_CLOSE_RESTART);
|
||||
#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
|
||||
r = posix_close (fd, POSIX_CLOSE_RESTART);
|
||||
#else
|
||||
r = android_close (fd) == 0 || errno == EINTR ? 0 : -1;
|
||||
#define POSIX_CLOSE_RESTART 1
|
||||
#endif
|
||||
|
||||
if (r == 0)
|
||||
return r;
|
||||
if (!POSIX_CLOSE_RESTART || errno != EINTR)
|
||||
|
@ -2729,6 +2812,15 @@ errwrite (void const *buf, ptrdiff_t nbuf)
|
|||
void
|
||||
close_output_streams (void)
|
||||
{
|
||||
/* Android comes with some kind of ``file descriptor sanitizer''
|
||||
that aborts when stdout or stderr is closed. */
|
||||
|
||||
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
|
||||
fflush (stderr);
|
||||
fflush (stdout);
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (close_stream (stdout) != 0)
|
||||
{
|
||||
emacs_perror ("Write error to standard output");
|
||||
|
|
135
src/term.c
135
src/term.c
|
@ -62,6 +62,8 @@ static int been_here = -1;
|
|||
#include "w32term.h"
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
static void tty_set_scroll_region (struct frame *f, int start, int stop);
|
||||
static void turn_on_face (struct frame *, int face_id);
|
||||
static void turn_off_face (struct frame *, int face_id);
|
||||
|
@ -73,11 +75,15 @@ static void clear_tty_hooks (struct terminal *terminal);
|
|||
static void set_tty_hooks (struct terminal *terminal);
|
||||
static void dissociate_if_controlling_tty (int fd);
|
||||
static void delete_tty (struct terminal *);
|
||||
|
||||
#endif
|
||||
|
||||
static AVOID maybe_fatal (bool, struct terminal *, const char *, const char *,
|
||||
...)
|
||||
ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5);
|
||||
static AVOID vfatal (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0);
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
#define OUTPUT(tty, a) \
|
||||
emacs_tputs ((tty), a, \
|
||||
|
@ -95,6 +101,8 @@ static AVOID vfatal (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0);
|
|||
|
||||
#define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
/* Display space properties. */
|
||||
|
||||
/* Chain of all tty device parameters. */
|
||||
|
@ -117,10 +125,14 @@ enum no_color_bit
|
|||
|
||||
/* internal state */
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
/* The largest frame width in any call to calculate_costs. */
|
||||
|
||||
static int max_frame_cols;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_GPM
|
||||
|
@ -133,6 +145,8 @@ struct tty_display_info *gpm_tty = NULL;
|
|||
static int last_mouse_x, last_mouse_y;
|
||||
#endif /* HAVE_GPM */
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
/* Ring the bell on a tty. */
|
||||
|
||||
static void
|
||||
|
@ -718,7 +732,20 @@ encode_terminal_code (struct glyph *src, int src_len,
|
|||
return (encode_terminal_dst);
|
||||
}
|
||||
|
||||
#else /* !HAVE_ANDROID */
|
||||
|
||||
unsigned char *
|
||||
encode_terminal_code (struct glyph *src, int src_len,
|
||||
struct coding_system *coding)
|
||||
{
|
||||
/* Text terminals are simply not supported on Android. */
|
||||
coding->produced = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* HAVE_ANDROID */
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
/* An implementation of write_glyphs for termcap frames. */
|
||||
|
||||
|
@ -1046,8 +1073,10 @@ int
|
|||
string_cost (const char *str)
|
||||
{
|
||||
cost = 0;
|
||||
#ifndef HAVE_ANDROID
|
||||
if (str)
|
||||
tputs (str, 0, evalcost);
|
||||
#endif
|
||||
return cost;
|
||||
}
|
||||
|
||||
|
@ -1058,8 +1087,10 @@ static int
|
|||
string_cost_one_line (const char *str)
|
||||
{
|
||||
cost = 0;
|
||||
#ifndef HAVE_ANDROID
|
||||
if (str)
|
||||
tputs (str, 1, evalcost);
|
||||
#endif
|
||||
return cost;
|
||||
}
|
||||
|
||||
|
@ -1070,11 +1101,13 @@ int
|
|||
per_line_cost (const char *str)
|
||||
{
|
||||
cost = 0;
|
||||
#ifndef HAVE_ANDROID
|
||||
if (str)
|
||||
tputs (str, 0, evalcost);
|
||||
cost = - cost;
|
||||
if (str)
|
||||
tputs (str, 10, evalcost);
|
||||
#endif
|
||||
return cost;
|
||||
}
|
||||
|
||||
|
@ -1147,11 +1180,14 @@ calculate_ins_del_char_costs (struct frame *f)
|
|||
*p++ = (ins_startup_cost += ins_cost_per_char);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
calculate_costs (struct frame *frame)
|
||||
{
|
||||
FRAME_COST_BAUD_RATE (frame) = baud_rate;
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
if (FRAME_TERMCAP_P (frame))
|
||||
{
|
||||
struct tty_display_info *tty = FRAME_TTY (frame);
|
||||
|
@ -1206,13 +1242,15 @@ calculate_costs (struct frame *frame)
|
|||
|
||||
cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
struct fkey_table {
|
||||
struct fkey_table
|
||||
{
|
||||
const char *cap, *name;
|
||||
};
|
||||
|
||||
#ifndef DOS_NT
|
||||
#if !defined DOS_NT && !defined HAVE_ANDROID
|
||||
/* Termcap capability names that correspond directly to X keysyms.
|
||||
Some of these (marked "terminfo") aren't supplied by old-style
|
||||
(Berkeley) termcap entries. They're listed in X keysym order;
|
||||
|
@ -1443,6 +1481,9 @@ term_get_fkeys_1 (void)
|
|||
#endif /* not DOS_NT */
|
||||
|
||||
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
/***********************************************************************
|
||||
Character Display Information
|
||||
***********************************************************************/
|
||||
|
@ -1519,14 +1560,17 @@ append_glyph (struct it *it)
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* For external use. */
|
||||
void
|
||||
tty_append_glyph (struct it *it)
|
||||
{
|
||||
#ifndef HAVE_ANDROID
|
||||
append_glyph (it);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Produce glyphs for the display element described by IT. *IT
|
||||
specifies what we want to produce a glyph for (character, image, ...),
|
||||
and where in the glyph matrix we currently are (glyph row and hpos).
|
||||
|
@ -1549,6 +1593,7 @@ tty_append_glyph (struct it *it)
|
|||
void
|
||||
produce_glyphs (struct it *it)
|
||||
{
|
||||
#ifndef HAVE_ANDROID
|
||||
/* If a hook is installed, let it do the work. */
|
||||
|
||||
/* Nothing but characters are supported on terminal frames. */
|
||||
|
@ -1661,8 +1706,11 @@ produce_glyphs (struct it *it)
|
|||
it->current_x += it->pixel_width;
|
||||
it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
|
||||
it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
/* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
|
||||
Called from produce_composite_glyph for terminal frames if
|
||||
IT->glyph_row != NULL. IT->face_id contains the character's
|
||||
|
@ -2020,6 +2068,7 @@ turn_off_face (struct frame *f, int face_id)
|
|||
OUTPUT1_IF (tty, tty->TS_orig_pair);
|
||||
}
|
||||
|
||||
#endif /* !HAVE_ANDROID */
|
||||
|
||||
/* Return true if the terminal on frame F supports all of the
|
||||
capabilities in CAPS simultaneously. */
|
||||
|
@ -2027,8 +2076,9 @@ turn_off_face (struct frame *f, int face_id)
|
|||
bool
|
||||
tty_capable_p (struct tty_display_info *tty, unsigned int caps)
|
||||
{
|
||||
#ifndef HAVE_ANDROID
|
||||
#define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
|
||||
if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
|
||||
if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P (tty, NC_bit))) \
|
||||
return 0;
|
||||
|
||||
TTY_CAPABLE_P_TRY (tty,
|
||||
|
@ -2048,6 +2098,9 @@ tty_capable_p (struct tty_display_info *tty, unsigned int caps)
|
|||
|
||||
/* We can do it! */
|
||||
return 1;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return non-zero if the terminal is capable to display colors. */
|
||||
|
@ -2081,7 +2134,7 @@ TERMINAL does not refer to a text terminal. */)
|
|||
return make_fixnum (t ? t->display_info.tty->TN_max_colors : 0);
|
||||
}
|
||||
|
||||
#ifndef DOS_NT
|
||||
#if !defined DOS_NT && !defined HAVE_ANDROID
|
||||
|
||||
/* Declare here rather than in the function, as in the rest of Emacs,
|
||||
to work around an HPUX compiler bug (?). See
|
||||
|
@ -2186,7 +2239,7 @@ set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
|
|||
}
|
||||
}
|
||||
|
||||
#endif /* !DOS_NT */
|
||||
#endif /* !DOS_NT && !HAVE_ANDROID */
|
||||
|
||||
char *
|
||||
tty_type_name (Lisp_Object terminal)
|
||||
|
@ -2278,6 +2331,7 @@ suspended.
|
|||
A suspended tty may be resumed by calling `resume-tty' on it. */)
|
||||
(Lisp_Object tty)
|
||||
{
|
||||
#ifndef HAVE_ANDROID
|
||||
struct terminal *t = decode_tty_terminal (tty);
|
||||
FILE *f;
|
||||
|
||||
|
@ -2314,6 +2368,10 @@ A suspended tty may be resumed by calling `resume-tty' on it. */)
|
|||
|
||||
/* Clear display hooks to prevent further output. */
|
||||
clear_tty_hooks (t);
|
||||
#else
|
||||
/* This will always signal on Android. */
|
||||
decode_tty_terminal (tty);
|
||||
#endif
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
@ -2337,9 +2395,12 @@ TTY may be a terminal object, a frame, or nil (meaning the selected
|
|||
frame's terminal). */)
|
||||
(Lisp_Object tty)
|
||||
{
|
||||
struct terminal *t = decode_tty_terminal (tty);
|
||||
#ifndef HAVE_ANDROID
|
||||
struct terminal *t;
|
||||
int fd;
|
||||
|
||||
t = decode_tty_terminal (tty);
|
||||
|
||||
if (!t)
|
||||
error ("Attempt to resume a non-text terminal device");
|
||||
|
||||
|
@ -2396,10 +2457,15 @@ frame's terminal). */)
|
|||
}
|
||||
|
||||
set_tty_hooks (t);
|
||||
#else
|
||||
decode_tty_terminal (tty);
|
||||
#endif
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
DEFUN ("tty--set-output-buffer-size", Ftty__set_output_buffer_size,
|
||||
Stty__set_output_buffer_size, 1, 2, 0, doc:
|
||||
/* Set the output buffer size for a TTY.
|
||||
|
@ -2438,12 +2504,14 @@ A value of zero means TTY uses the system's default value. */)
|
|||
error ("Not a tty terminal");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
Mouse
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef DOS_NT
|
||||
#if !defined DOS_NT && !defined HAVE_ANDROID
|
||||
|
||||
/* Implementation of draw_row_with_mouse_face for TTY/GPM and macOS. */
|
||||
void
|
||||
|
@ -2713,7 +2781,7 @@ DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
|
|||
Menus
|
||||
***********************************************************************/
|
||||
|
||||
#if !defined (MSDOS)
|
||||
#if !defined (MSDOS) && !defined HAVE_ANDROID
|
||||
|
||||
/* TTY menu implementation and main ideas are borrowed from msdos.c.
|
||||
|
||||
|
@ -3813,10 +3881,12 @@ tty_menu_show (struct frame *f, int x, int y, int menuflags,
|
|||
return SAFE_FREE_UNBIND_TO (specpdl_count, entry);
|
||||
}
|
||||
|
||||
#endif /* !MSDOS */
|
||||
#endif /* !MSDOS && !defined HAVE_ANDROID */
|
||||
|
||||
|
||||
#ifndef MSDOS
|
||||
|
||||
#if !defined MSDOS && !defined HAVE_ANDROID
|
||||
|
||||
/***********************************************************************
|
||||
Initialization
|
||||
***********************************************************************/
|
||||
|
@ -3846,7 +3916,7 @@ tty_free_frame_resources (struct frame *f)
|
|||
xfree (f->output_data.tty);
|
||||
}
|
||||
|
||||
#else /* MSDOS */
|
||||
#elif defined MSDOS
|
||||
|
||||
/* Delete frame F's face cache. */
|
||||
|
||||
|
@ -3856,8 +3926,13 @@ tty_free_frame_resources (struct frame *f)
|
|||
eassert (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
|
||||
free_frame_faces (f);
|
||||
}
|
||||
#endif /* MSDOS */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
/* Reset the hooks in TERMINAL. */
|
||||
|
||||
static void
|
||||
|
@ -3952,6 +4027,8 @@ dissociate_if_controlling_tty (int fd)
|
|||
}
|
||||
}
|
||||
|
||||
#endif /* !HAVE_ANDROID */
|
||||
|
||||
/* Create a termcap display on the tty device with the given name and
|
||||
type.
|
||||
|
||||
|
@ -3961,11 +4038,23 @@ dissociate_if_controlling_tty (int fd)
|
|||
|
||||
TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
|
||||
|
||||
If MUST_SUCCEED is true, then all errors are fatal. */
|
||||
If MUST_SUCCEED is true, then all errors are fatal. This function
|
||||
always signals on Android, where text terminals are prohibited by
|
||||
system policy (and the required libraries are usually not
|
||||
available.) */
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
_Noreturn
|
||||
#endif
|
||||
|
||||
struct terminal *
|
||||
init_tty (const char *name, const char *terminal_type, bool must_succeed)
|
||||
{
|
||||
#ifdef HAVE_ANDROID
|
||||
maybe_fatal (must_succeed, 0, "Text terminals are not supported"
|
||||
" under Android", "Text terminals are not supported"
|
||||
" under Android");
|
||||
#else
|
||||
struct tty_display_info *tty = NULL;
|
||||
struct terminal *terminal = NULL;
|
||||
#ifndef DOS_NT
|
||||
|
@ -4447,6 +4536,7 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\
|
|||
init_sys_modes (tty);
|
||||
|
||||
return terminal;
|
||||
#endif /* !HAVE_ANDROID */
|
||||
}
|
||||
|
||||
|
||||
|
@ -4471,8 +4561,13 @@ maybe_fatal (bool must_succeed, struct terminal *terminal,
|
|||
{
|
||||
va_list ap;
|
||||
va_start (ap, str2);
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
if (terminal)
|
||||
delete_tty (terminal);
|
||||
#else
|
||||
eassert (terminal == NULL);
|
||||
#endif
|
||||
|
||||
if (must_succeed)
|
||||
vfatal (str2, ap);
|
||||
|
@ -4490,6 +4585,8 @@ fatal (const char *str, ...)
|
|||
|
||||
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
/* Delete the given tty terminal, closing all frames on it. */
|
||||
|
||||
static void
|
||||
|
@ -4547,6 +4644,8 @@ delete_tty (struct terminal *terminal)
|
|||
xfree (tty);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
syms_of_term (void)
|
||||
{
|
||||
|
@ -4594,21 +4693,25 @@ trigger redisplay. */);
|
|||
defsubr (&Stty_top_frame);
|
||||
defsubr (&Ssuspend_tty);
|
||||
defsubr (&Sresume_tty);
|
||||
#ifndef HAVE_ANDROID
|
||||
defsubr (&Stty__set_output_buffer_size);
|
||||
defsubr (&Stty__output_buffer_size);
|
||||
#endif /* !HAVE_ANDROID */
|
||||
#ifdef HAVE_GPM
|
||||
defsubr (&Sgpm_mouse_start);
|
||||
defsubr (&Sgpm_mouse_stop);
|
||||
#endif /* HAVE_GPM */
|
||||
|
||||
#ifndef DOS_NT
|
||||
#if !defined DOS_NT && !defined HAVE_ANDROID
|
||||
default_orig_pair = NULL;
|
||||
default_set_foreground = NULL;
|
||||
default_set_background = NULL;
|
||||
#endif /* !DOS_NT */
|
||||
#endif /* !DOS_NT && !HAVE_ANDROID */
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
encode_terminal_src = NULL;
|
||||
encode_terminal_dst = NULL;
|
||||
#endif
|
||||
|
||||
DEFSYM (Qtty_mode_set_strings, "tty-mode-set-strings");
|
||||
DEFSYM (Qtty_mode_reset_strings, "tty-mode-reset-strings");
|
||||
|
|
|
@ -63,7 +63,8 @@ enum output_method
|
|||
output_w32,
|
||||
output_ns,
|
||||
output_pgtk,
|
||||
output_haiku
|
||||
output_haiku,
|
||||
output_android,
|
||||
};
|
||||
|
||||
/* Input queue declarations and hooks. */
|
||||
|
@ -516,12 +517,13 @@ struct terminal
|
|||
/* Device-type dependent data shared amongst all frames on this terminal. */
|
||||
union display_info
|
||||
{
|
||||
struct tty_display_info *tty; /* termchar.h */
|
||||
struct x_display_info *x; /* xterm.h */
|
||||
struct w32_display_info *w32; /* w32term.h */
|
||||
struct ns_display_info *ns; /* nsterm.h */
|
||||
struct pgtk_display_info *pgtk; /* pgtkterm.h */
|
||||
struct haiku_display_info *haiku; /* haikuterm.h */
|
||||
struct tty_display_info *tty; /* termchar.h */
|
||||
struct x_display_info *x; /* xterm.h */
|
||||
struct w32_display_info *w32; /* w32term.h */
|
||||
struct ns_display_info *ns; /* nsterm.h */
|
||||
struct pgtk_display_info *pgtk; /* pgtkterm.h */
|
||||
struct haiku_display_info *haiku; /* haikuterm.h */
|
||||
struct android_display_info *android; /* androidterm.h */
|
||||
} display_info;
|
||||
|
||||
|
||||
|
@ -595,7 +597,8 @@ struct terminal
|
|||
BGCOLOR. */
|
||||
void (*query_frame_background_color) (struct frame *f, Emacs_Color *bgcolor);
|
||||
|
||||
#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (HAVE_PGTK)
|
||||
#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (HAVE_PGTK) \
|
||||
|| defined (HAVE_ANDROID)
|
||||
/* On frame F, translate pixel colors to RGB values for the NCOLORS
|
||||
colors in COLORS. Use cached information, if available. */
|
||||
|
||||
|
@ -930,6 +933,9 @@ extern struct terminal *terminal_list;
|
|||
#elif defined (HAVE_HAIKU)
|
||||
#define TERMINAL_FONT_CACHE(t) \
|
||||
(t->type == output_haiku ? t->display_info.haiku->name_list_element : Qnil)
|
||||
#elif defined (HAVE_ANDROID)
|
||||
#define TERMINAL_FONT_CACHE(t) \
|
||||
(t->type == output_android ? t->display_info.android->name_list_element : Qnil)
|
||||
#endif
|
||||
|
||||
extern struct terminal *decode_live_terminal (Lisp_Object);
|
||||
|
|
|
@ -451,6 +451,8 @@ return values. */)
|
|||
return Qpgtk;
|
||||
case output_haiku:
|
||||
return Qhaiku;
|
||||
case output_android:
|
||||
return Qandroid;
|
||||
default:
|
||||
emacs_abort ();
|
||||
}
|
||||
|
|
|
@ -32,6 +32,10 @@ AM_V_GEN =
|
|||
AM_V_GLOBALS =
|
||||
AM_V_NO_PD =
|
||||
AM_V_RC =
|
||||
AM_V_JAVAC =
|
||||
AM_V_DX =
|
||||
AM_V_AAPT =
|
||||
AM_V_ZIPALIGN =
|
||||
else
|
||||
|
||||
# Whether $(info ...) works. This is to work around a bug in GNU Make
|
||||
|
@ -76,4 +80,8 @@ AM_V_GEN = @$(info $ GEN $@)
|
|||
AM_V_GLOBALS = @$(info $ GEN globals.h)
|
||||
AM_V_NO_PD = --no-print-directory
|
||||
AM_V_RC = @$(info $ RC $@)
|
||||
|
||||
# These are used for the Android port.
|
||||
AM_V_JAVAC = @$(info $ JAVAC $@)
|
||||
AM_V_DX = @$(info $ DX $@)
|
||||
endif
|
||||
|
|
26
src/xdisp.c
26
src/xdisp.c
|
@ -16415,7 +16415,7 @@ redisplay_internal (void)
|
|||
display area, displaying a different frame means redisplay
|
||||
the whole thing. */
|
||||
SET_FRAME_GARBAGED (sf);
|
||||
#ifndef DOS_NT
|
||||
#if !defined DOS_NT && !defined HAVE_ANDROID
|
||||
set_tty_color_mode (FRAME_TTY (sf), sf);
|
||||
#endif
|
||||
FRAME_TTY (sf)->previous_frame = sf;
|
||||
|
@ -26320,7 +26320,7 @@ display_menu_bar (struct window *w)
|
|||
init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
|
||||
it.first_visible_x = 0;
|
||||
it.last_visible_x = FRAME_PIXEL_WIDTH (f);
|
||||
#elif defined (HAVE_X_WINDOWS) /* X without toolkit. */
|
||||
#elif defined (HAVE_X_WINDOWS) || defined (HAVE_ANDROID)
|
||||
struct window *menu_window = NULL;
|
||||
struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
|
||||
|
||||
|
@ -26390,7 +26390,11 @@ display_menu_bar (struct window *w)
|
|||
it.glyph_row->truncated_on_left_p = false;
|
||||
it.glyph_row->truncated_on_right_p = false;
|
||||
|
||||
#if defined (HAVE_X_WINDOWS) && !defined (USE_X_TOOLKIT) && !defined (USE_GTK)
|
||||
/* This will break the moment someone tries to add another window
|
||||
system that uses the no toolkit menu bar. Oh well. At least
|
||||
there will be an error, meaning he will correct the ifdef inside
|
||||
which `face' is defined. */
|
||||
#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
|
||||
/* Make a 3D menu bar have a shadow at its right end. */
|
||||
extend_face_to_end_of_line (&it);
|
||||
if (face->box != FACE_NO_BOX)
|
||||
|
@ -26431,6 +26435,11 @@ display_menu_bar (struct window *w)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* This code is never used on Android where there are only GUI and
|
||||
initial frames. */
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
|
||||
/* Deep copy of a glyph row, including the glyphs. */
|
||||
static void
|
||||
deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
|
||||
|
@ -26551,6 +26560,9 @@ display_tty_menu_item (const char *item_text, int width, int face_id,
|
|||
row->full_width_p = saved_width;
|
||||
row->reversed_p = saved_reversed;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
Mode Line
|
||||
|
@ -33432,7 +33444,9 @@ draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ANDROID
|
||||
tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Display the active region described by mouse_face_* according to DRAW. */
|
||||
|
@ -36104,14 +36118,10 @@ expose_frame (struct frame *f, int x, int y, int w, int h)
|
|||
|= expose_window (XWINDOW (f->tool_bar_window), &r);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_X_WINDOWS
|
||||
#ifndef MSDOS
|
||||
#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
|
||||
#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
|
||||
if (WINDOWP (f->menu_bar_window))
|
||||
mouse_face_overwritten_p
|
||||
|= expose_window (XWINDOW (f->menu_bar_window), &r);
|
||||
#endif /* not USE_X_TOOLKIT and not USE_GTK */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Some window managers support a focus-follows-mouse style with
|
||||
|
|
59
src/xfaces.c
59
src/xfaces.c
|
@ -254,6 +254,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#ifdef HAVE_HAIKU
|
||||
#define GCGraphicsExposures 0
|
||||
#endif /* HAVE_HAIKU */
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
#define GCGraphicsExposures 0
|
||||
#endif /* HAVE_ANDROID */
|
||||
#endif /* HAVE_WINDOW_SYSTEM */
|
||||
|
||||
#include "buffer.h"
|
||||
|
@ -607,6 +611,39 @@ x_free_gc (struct frame *f, Emacs_GC *gc)
|
|||
}
|
||||
#endif /* HAVE_NS */
|
||||
|
||||
#ifdef HAVE_ANDROID
|
||||
|
||||
/* Android real GCs. */
|
||||
|
||||
static struct android_gc *
|
||||
x_create_gc (struct frame *f, unsigned long value_mask,
|
||||
Emacs_GC *xgcv)
|
||||
{
|
||||
struct android_gc_values gcv;
|
||||
unsigned long mask;
|
||||
|
||||
gcv.foreground = xgcv->foreground;
|
||||
gcv.background = xgcv->background;
|
||||
|
||||
mask = 0;
|
||||
|
||||
if (value_mask & GCForeground)
|
||||
mask |= ANDROID_GC_FOREGROUND;
|
||||
|
||||
if (value_mask & GCBackground)
|
||||
mask |= ANDROID_GC_BACKGROUND;
|
||||
|
||||
return android_create_gc (mask, &gcv);
|
||||
}
|
||||
|
||||
static void
|
||||
x_free_gc (struct frame *f, struct android_gc *gc)
|
||||
{
|
||||
android_free_gc (gc);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/***********************************************************************
|
||||
Frames and faces
|
||||
***********************************************************************/
|
||||
|
@ -6951,19 +6988,21 @@ where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
|
|||
int num;
|
||||
|
||||
while (fgets (buf, sizeof (buf), fp) != NULL)
|
||||
if (sscanf (buf, "%d %d %d %n", &red, &green, &blue, &num) == 3)
|
||||
{
|
||||
{
|
||||
if (sscanf (buf, "%d %d %d %n", &red, &green, &blue, &num) == 3)
|
||||
{
|
||||
#ifdef HAVE_NTGUI
|
||||
int color = RGB (red, green, blue);
|
||||
int color = RGB (red, green, blue);
|
||||
#else
|
||||
int color = (red << 16) | (green << 8) | blue;
|
||||
int color = (red << 16) | (green << 8) | blue;
|
||||
#endif
|
||||
char *name = buf + num;
|
||||
ptrdiff_t len = strlen (name);
|
||||
len -= 0 < len && name[len - 1] == '\n';
|
||||
cmap = Fcons (Fcons (make_string (name, len), make_fixnum (color)),
|
||||
cmap);
|
||||
}
|
||||
char *name = buf + num;
|
||||
ptrdiff_t len = strlen (name);
|
||||
len -= 0 < len && name[len - 1] == '\n';
|
||||
cmap = Fcons (Fcons (make_string (name, len), make_fixnum (color)),
|
||||
cmap);
|
||||
}
|
||||
}
|
||||
fclose (fp);
|
||||
}
|
||||
unblock_input ();
|
||||
|
|
209
xcompile/Makefile.in
Normal file
209
xcompile/Makefile.in
Normal file
|
@ -0,0 +1,209 @@
|
|||
### @configure_input@
|
||||
|
||||
# Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU Emacs.
|
||||
|
||||
# GNU Emacs is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# GNU Emacs is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
# Cross-compiling Emacs for Android.
|
||||
|
||||
# The cross compiled binaries are built by having ``variant''
|
||||
# Makefiles generated at configure-time. First,
|
||||
# $(top_builddir)/src/Makefile.android,
|
||||
# $(top_builddir)/lib/Makefile.android,
|
||||
# $(top_builddir)/lib/gnulib.mk.android and
|
||||
# $(top_builddir)/lib-src/Makefile.android are copied to their usual
|
||||
# locations in this directory.
|
||||
|
||||
# Finally, the following commands are executed in order, to produce
|
||||
# libgnu.a, various binaries in lib-src, and src/aemacs:
|
||||
# make -C lib libgnu.a
|
||||
# make -C lib-src src/aemacs
|
||||
# make -C src aemacs
|
||||
|
||||
# This is possibly the ugliest Makefile ever written!
|
||||
|
||||
LIB_SRCDIR = $(realpath $(top_srcdir)/lib)
|
||||
LIB_TOP_SRCDIR = $(realpath $(top_srcdir))
|
||||
|
||||
SRC_SRCDIR = $(realpath $(top_srcdir)/src)
|
||||
SRC_TOP_SRCDIR = $(realpath $(top_srcdir))
|
||||
|
||||
LIB_SRC_SRCDIR = $(realpath $(top_srcdir)/lib-src)
|
||||
LIB_SRC_TOP_SRCDIR = $(realpath $(top_src))
|
||||
|
||||
# This is a list of binaries to build and install in lib-src.
|
||||
|
||||
LIBSRC_BINARIES = lib-src/etags lib-src/ctags lib-src/emacsclient \
|
||||
lib-src/ebrowse lib-src/hexl lib-src/movemail
|
||||
|
||||
CLEAN_SUBDIRS=lib src lib-src
|
||||
|
||||
.PHONY: all
|
||||
all: lib/libgnu.a src/libemacs.so src/android-emacs $(LIBSRC_BINARIES)
|
||||
|
||||
# This Makefile relies on builddir and top_builddir being relative
|
||||
# paths in *.android.
|
||||
|
||||
# This file is used to trick lib/gnulib.mk, it is not actually useful.
|
||||
config.status:
|
||||
touch config.status
|
||||
|
||||
src/verbose.mk: verbose.mk.android
|
||||
mkdir -p src
|
||||
cp -f verbose.mk.android src/verbose.mk
|
||||
|
||||
UGLY_HOST_HEADERS = dirent.h stdlib.h sys/random.h limits.h \
|
||||
string.h signal.h time.h inttypes.h assert.h \
|
||||
stdint.h unistd.h stdlib.h sys/types.h sys/time.h \
|
||||
sys/stat.h getopt.h fcntl.h sys/select.h alloca.h \
|
||||
stdio.h sys/random.h
|
||||
|
||||
# Gnulib, make-fingerprint and make-docfile must be built before
|
||||
# entering any of the rules below, or they will get the Android
|
||||
# versions of many headers.
|
||||
|
||||
.PHONY: $(top_builddir)/lib/libgnu.a
|
||||
$(top_builddir)/lib/libgnu.a:
|
||||
+ make -C $(top_builddir)/lib libgnu.a
|
||||
|
||||
.PHONY: $(top_builddir)/lib-src/make-fingerprint
|
||||
$(top_builddir)/lib-src/make-fingerprint:
|
||||
make -C $(top_builddir)/lib-src make-fingerprint
|
||||
|
||||
.PHONY: $(top_builddir)/lib-src/make-docfile
|
||||
$(top_builddir)/lib-src/make-docfile:
|
||||
make -C $(top_builddir)/lib-src make-docfile
|
||||
|
||||
PRE_BUILD_DEPS=$(top_builddir)/lib/libgnu.a \
|
||||
$(top_builddir)/lib-src/make-fingerprint \
|
||||
$(top_builddir)/lib-src/make-docfile
|
||||
|
||||
.PHONY: lib/libgnu.a
|
||||
lib/libgnu.a: src/verbose.mk config.status $(PRE_BUILD_DEPS)
|
||||
mkdir -p lib/deps lib/deps/malloc
|
||||
# Temporarily move config.h to config.h.bak and config.h.android to
|
||||
# config.h
|
||||
cp -f -p $(top_builddir)/src/config.h.android lib/config.h
|
||||
# And the Makefiles.
|
||||
cp -f -p $(top_builddir)/lib/gnulib.mk.android lib/gnulib.mk
|
||||
cp -f -p $(top_builddir)/lib/Makefile.android lib/Makefile
|
||||
# Next, move srcdir and top_srcdir in the Makefiles copied.
|
||||
sed -i 's/srcdir =.*$$/srcdir = $(subst /,\/,$(LIB_SRCDIR))/g' lib/Makefile
|
||||
sed -i 's/top_srcdir =.*$$/top_srcdir = $(subst /,\/,$(LIB_TOP_SRCDIR))/g' \
|
||||
lib/Makefile
|
||||
sed -i 's/srcdir =.*$$/srcdir = $(subst /,\/,$(LIB_SRCDIR))/g' lib/gnulib.mk
|
||||
# Ugly hack: hide some troublesome headers in $(top_builddir)/lib
|
||||
# while building lib. Otherwise, they will end up overriding the
|
||||
# system headers used on Android through #include_next and cause
|
||||
# trouble.
|
||||
mkdir -p sys
|
||||
for ugly_header in $(UGLY_HOST_HEADERS); do \
|
||||
if [ -e "$(top_builddir)/lib/$$ugly_header" ]; then \
|
||||
mv -f $(top_builddir)/lib/$$ugly_header $$ugly_header.bak; \
|
||||
fi \
|
||||
done
|
||||
# And make libgnu.a. Restore config.h if it fails.
|
||||
-make -C lib libgnu.a
|
||||
# Move the hiden headers back
|
||||
for ugly_header in $(UGLY_HOST_HEADERS); do \
|
||||
if [ -e "$$ugly_header.bak" ]; then \
|
||||
mv -f $$ugly_header.bak $(top_builddir)/lib/$$ugly_header; \
|
||||
fi \
|
||||
done
|
||||
|
||||
src/Makefile src/config.h &: $(top_builddir)/src/config.h.android \
|
||||
$(top_builddir)/src/Makefile.android $(PRE_BUILD_DEPS)
|
||||
mkdir -p src src/deps
|
||||
# Copy config.h to src/
|
||||
cp -f -p $(top_builddir)/src/config.h.android src/config.h
|
||||
# And the Makefile.
|
||||
cp -f -p $(top_builddir)/src/Makefile.android src/Makefile
|
||||
# Next, edit srcdir and top_srcdir to the right location.
|
||||
sed -i 's/srcdir =.*$$/srcdir = $(subst /,\/,$(SRC_SRCDIR))/g' src/Makefile
|
||||
sed -i 's/top_srcdir =.*$$/top_srcdir = $(subst /,\/,$(LIB_TOP_SRCDIR))/g' \
|
||||
src/Makefile
|
||||
# Edit references to ../admin/unidata to read ../../admin/unidata.
|
||||
sed -i 's/\.\.\/admin\/unidata/..\/..\/admin\/unidata/g' src/Makefile
|
||||
sed -i 's/\.\.\/admin\/charsets/..\/..\/admin\/charsets/g' src/Makefile
|
||||
# Next, edit libsrc to the location at top_srcdir! It is important
|
||||
# that src/Makefile uses the binaries there, instead of any
|
||||
# cross-compiled binaries at ./lib-src.
|
||||
sed -i 's/libsrc =.*$$/libsrc = \.\.\/\.\.\/lib-src/g' src/Makefile
|
||||
|
||||
.PHONY: src/android-emacs src/libemacs.so
|
||||
src/android-emacs src/libemacs.so &: src/Makefile src/config.h \
|
||||
src/verbose.mk lib/libgnu.a $(PRE_BUILD_DEPS)
|
||||
# Ugly hack: hide some troublesome headers in $(top_builddir)/lib
|
||||
# while building lib. Otherwise, they will end up overriding the
|
||||
# system headers used on Android through #include_next and cause
|
||||
# trouble.
|
||||
mkdir -p sys
|
||||
for ugly_header in $(UGLY_HOST_HEADERS); do \
|
||||
if [ -e "$(top_builddir)/lib/$$ugly_header" ]; then \
|
||||
mv -f $(top_builddir)/lib/$$ugly_header $$ugly_header.bak; \
|
||||
fi \
|
||||
done
|
||||
# Finally, go into src and make
|
||||
+make -C src android-emacs libemacs.so
|
||||
# Move the hidden headers back
|
||||
for ugly_header in $(UGLY_HOST_HEADERS); do \
|
||||
if [ -e "$$ugly_header.bak" ]; then \
|
||||
mv -f $$ugly_header.bak $(top_builddir)/lib/$$ugly_header; \
|
||||
fi \
|
||||
done
|
||||
|
||||
lib-src/Makefile: $(top_builddir)/lib-src/Makefile.android
|
||||
mkdir -p lib-src
|
||||
cp -f -p $< $@
|
||||
|
||||
.PHONY: $(LIBSRC_BINARIES)
|
||||
$(LIBSRC_BINARIES) &: src/verbose.mk $(top_builddir)/$@ lib/libgnu.a \
|
||||
src/config.h lib-src/Makefile $(PRE_BUILD_DEPS)
|
||||
mkdir -p src lib-src
|
||||
# Next, edit srcdir and top_srcdir to the right location.
|
||||
sed -i 's/srcdir=.*$$/srcdir = $(subst /,\/,$(LIB_SRC_SRCDIR))/g' \
|
||||
lib-src/Makefile
|
||||
sed -i 's/top_srcdir=.*$$/top_srcdir = $(subst /,\/,$(LIB_SRC_TOP_SRCDIR))/g' \
|
||||
lib-src/Makefile
|
||||
# Edit out SCRIPTS, it interferes with the build.
|
||||
sed -i 's/^SCRIPTS=.*$$/SCRIPTS=/g' lib-src/Makefile
|
||||
# Ugly hack: hide some troublesome headers in $(top_builddir)/lib
|
||||
# while building lib. Otherwise, they will end up overriding the
|
||||
# system headers used on Android through #include_next and cause
|
||||
# trouble.
|
||||
mkdir -p sys
|
||||
for ugly_header in $(UGLY_HOST_HEADERS); do \
|
||||
if [ -e "$(top_builddir)/lib/$$ugly_header" ]; then \
|
||||
mv -f $(top_builddir)/lib/$$ugly_header $$ugly_header.bak; \
|
||||
fi \
|
||||
done
|
||||
# Finally, go into lib-src and make everything being built
|
||||
+make -C lib-src $(foreach bin,$(LIBSRC_BINARIES),$(notdir $(bin)))
|
||||
# Move the hidden headers back
|
||||
for ugly_header in $(UGLY_HOST_HEADERS); do \
|
||||
if [ -e "$$ugly_header.bak" ]; then \
|
||||
mv -f $$ugly_header.bak $(top_builddir)/lib/$$ugly_header; \
|
||||
fi \
|
||||
done
|
||||
|
||||
.PHONY: clean maintainer-clean
|
||||
clean:
|
||||
rm -rf $(CLEAN_SUBDIRS) *.bak sys
|
||||
|
||||
maintainer-clean: clean
|
7
xcompile/README
Normal file
7
xcompile/README
Normal file
|
@ -0,0 +1,7 @@
|
|||
This directory holds Makefiles and other required assets to build an
|
||||
Emacs binary independently for another toolchain, which is currently
|
||||
required when building for Android.
|
||||
|
||||
The files here are extremely ugly, and contain rules that cannot be
|
||||
interrupted without leaving the build tree in an unsafe state. At
|
||||
some point that should be fixed!
|
20
xcompile/langinfo.h
Normal file
20
xcompile/langinfo.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/* Replacement langinfo.h file for building GNU Emacs on Android.
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#define nl_langinfo(ignore) "ASCII"
|
Loading…
Reference in a new issue