Mercurial > hg > xemacs-beta
annotate src/glyphs-gtk.c @ 4952:19a72041c5ed
Mule-izing, various fixes related to char * arguments
-------------------- ChangeLog entries follow: --------------------
modules/ChangeLog addition:
2010-01-26 Ben Wing <ben@xemacs.org>
* postgresql/postgresql.c:
* postgresql/postgresql.c (CHECK_LIVE_CONNECTION):
* postgresql/postgresql.c (print_pgresult):
* postgresql/postgresql.c (Fpq_conn_defaults):
* postgresql/postgresql.c (Fpq_connectdb):
* postgresql/postgresql.c (Fpq_connect_start):
* postgresql/postgresql.c (Fpq_result_status):
* postgresql/postgresql.c (Fpq_res_status):
Mule-ize large parts of it.
2010-01-26 Ben Wing <ben@xemacs.org>
* ldap/eldap.c (print_ldap):
* ldap/eldap.c (allocate_ldap):
Use write_ascstring().
src/ChangeLog addition:
2010-01-26 Ben Wing <ben@xemacs.org>
* alloc.c:
* alloc.c (build_ascstring):
* alloc.c (build_msg_cistring):
* alloc.c (staticpro_1):
* alloc.c (staticpro_name):
* alloc.c (staticpro_nodump_1):
* alloc.c (staticpro_nodump_name):
* alloc.c (unstaticpro_nodump_1):
* alloc.c (mcpro_1):
* alloc.c (mcpro_name):
* alloc.c (object_memory_usage_stats):
* alloc.c (common_init_alloc_early):
* alloc.c (init_alloc_once_early):
* buffer.c (print_buffer):
* buffer.c (vars_of_buffer):
* buffer.c (common_init_complex_vars_of_buffer):
* buffer.c (init_initial_directory):
* bytecode.c (invalid_byte_code):
* bytecode.c (print_compiled_function):
* bytecode.c (mark_compiled_function):
* chartab.c (print_table_entry):
* chartab.c (print_char_table):
* config.h.in:
* console-gtk.c:
* console-gtk.c (gtk_device_to_console_connection):
* console-gtk.c (gtk_semi_canonicalize_console_connection):
* console-gtk.c (gtk_canonicalize_console_connection):
* console-gtk.c (gtk_semi_canonicalize_device_connection):
* console-gtk.c (gtk_canonicalize_device_connection):
* console-stream.c (stream_init_frame_1):
* console-stream.c (vars_of_console_stream):
* console-stream.c (init_console_stream):
* console-x.c (x_semi_canonicalize_console_connection):
* console-x.c (x_semi_canonicalize_device_connection):
* console-x.c (x_canonicalize_device_connection):
* console-x.h:
* data.c (eq_with_ebola_notice):
* data.c (Fsubr_interactive):
* data.c (Fnumber_to_string):
* data.c (digit_to_number):
* device-gtk.c (gtk_init_device):
* device-msw.c (print_devmode):
* device-x.c (x_event_name):
* dialog-msw.c (handle_directory_dialog_box):
* dialog-msw.c (handle_file_dialog_box):
* dialog-msw.c (vars_of_dialog_mswindows):
* doc.c (weird_doc):
* doc.c (Fsnarf_documentation):
* doc.c (vars_of_doc):
* dumper.c (pdump):
* dynarr.c:
* dynarr.c (Dynarr_realloc):
* editfns.c (Fuser_real_login_name):
* editfns.c (get_home_directory):
* elhash.c (print_hash_table_data):
* elhash.c (print_hash_table):
* emacs.c (main_1):
* emacs.c (vars_of_emacs):
* emodules.c:
* emodules.c (_emodules_list):
* emodules.c (Fload_module):
* emodules.c (Funload_module):
* emodules.c (Flist_modules):
* emodules.c (find_make_module):
* emodules.c (attempt_module_delete):
* emodules.c (emodules_load):
* emodules.c (emodules_doc_subr):
* emodules.c (emodules_doc_sym):
* emodules.c (syms_of_module):
* emodules.c (vars_of_module):
* emodules.h:
* eval.c (print_subr):
* eval.c (signal_call_debugger):
* eval.c (build_error_data):
* eval.c (signal_error):
* eval.c (maybe_signal_error):
* eval.c (signal_continuable_error):
* eval.c (maybe_signal_continuable_error):
* eval.c (signal_error_2):
* eval.c (maybe_signal_error_2):
* eval.c (signal_continuable_error_2):
* eval.c (maybe_signal_continuable_error_2):
* eval.c (signal_ferror):
* eval.c (maybe_signal_ferror):
* eval.c (signal_continuable_ferror):
* eval.c (maybe_signal_continuable_ferror):
* eval.c (signal_ferror_with_frob):
* eval.c (maybe_signal_ferror_with_frob):
* eval.c (signal_continuable_ferror_with_frob):
* eval.c (maybe_signal_continuable_ferror_with_frob):
* eval.c (syntax_error):
* eval.c (syntax_error_2):
* eval.c (maybe_syntax_error):
* eval.c (sferror):
* eval.c (sferror_2):
* eval.c (maybe_sferror):
* eval.c (invalid_argument):
* eval.c (invalid_argument_2):
* eval.c (maybe_invalid_argument):
* eval.c (invalid_constant):
* eval.c (invalid_constant_2):
* eval.c (maybe_invalid_constant):
* eval.c (invalid_operation):
* eval.c (invalid_operation_2):
* eval.c (maybe_invalid_operation):
* eval.c (invalid_change):
* eval.c (invalid_change_2):
* eval.c (maybe_invalid_change):
* eval.c (invalid_state):
* eval.c (invalid_state_2):
* eval.c (maybe_invalid_state):
* eval.c (wtaerror):
* eval.c (stack_overflow):
* eval.c (out_of_memory):
* eval.c (print_multiple_value):
* eval.c (issue_call_trapping_problems_warning):
* eval.c (backtrace_specials):
* eval.c (backtrace_unevalled_args):
* eval.c (Fbacktrace):
* eval.c (warn_when_safe):
* event-Xt.c (modwarn):
* event-Xt.c (modbarf):
* event-Xt.c (check_modifier):
* event-Xt.c (store_modifier):
* event-Xt.c (emacs_Xt_format_magic_event):
* event-Xt.c (describe_event):
* event-gtk.c (dragndrop_data_received):
* event-gtk.c (store_modifier):
* event-gtk.c (gtk_reset_modifier_mapping):
* event-msw.c (dde_eval_string):
* event-msw.c (Fdde_alloc_advise_item):
* event-msw.c (mswindows_dde_callback):
* event-msw.c (FROB):
* event-msw.c (emacs_mswindows_format_magic_event):
* event-stream.c (external_debugging_print_event):
* event-stream.c (execute_help_form):
* event-stream.c (vars_of_event_stream):
* events.c (print_event_1):
* events.c (print_event):
* events.c (event_equal):
* extents.c (print_extent_1):
* extents.c (print_extent):
* extents.c (vars_of_extents):
* faces.c (print_face):
* faces.c (complex_vars_of_faces):
* file-coding.c:
* file-coding.c (print_coding_system):
* file-coding.c (print_coding_system_in_print_method):
* file-coding.c (default_query_method):
* file-coding.c (find_coding_system):
* file-coding.c (make_coding_system_1):
* file-coding.c (chain_print):
* file-coding.c (undecided_print):
* file-coding.c (gzip_print):
* file-coding.c (vars_of_file_coding):
* file-coding.c (complex_vars_of_file_coding):
* fileio.c:
* fileio.c (report_file_type_error):
* fileio.c (report_error_with_errno):
* fileio.c (report_file_error):
* fileio.c (barf_or_query_if_file_exists):
* fileio.c (vars_of_fileio):
* floatfns.c (matherr):
* fns.c (print_bit_vector):
* fns.c (Fmapconcat):
* fns.c (add_suffix_to_symbol):
* fns.c (add_prefix_to_symbol):
* frame-gtk.c:
* frame-gtk.c (Fgtk_window_id):
* frame-x.c (def):
* frame-x.c (x_cde_transfer_callback):
* frame.c:
* frame.c (Fmake_frame):
* gc.c (show_gc_cursor_and_message):
* gc.c (vars_of_gc):
* glyphs-eimage.c (png_instantiate):
* glyphs-eimage.c (tiff_instantiate):
* glyphs-gtk.c (gtk_print_image_instance):
* glyphs-msw.c (mswindows_print_image_instance):
* glyphs-x.c (x_print_image_instance):
* glyphs-x.c (update_widget_face):
* glyphs.c (make_string_from_file):
* glyphs.c (print_image_instance):
* glyphs.c (signal_image_error):
* glyphs.c (signal_image_error_2):
* glyphs.c (signal_double_image_error):
* glyphs.c (signal_double_image_error_2):
* glyphs.c (xbm_mask_file_munging):
* glyphs.c (pixmap_to_lisp_data):
* glyphs.h:
* gui.c (gui_item_display_flush_left):
* hpplay.c (player_error_internal):
* hpplay.c (myHandler):
* intl-win32.c:
* intl-win32.c (langcode_to_lang):
* intl-win32.c (sublangcode_to_lang):
* intl-win32.c (Fmswindows_get_locale_info):
* intl-win32.c (lcid_to_locale_mule_or_no):
* intl-win32.c (mswindows_multibyte_to_unicode_print):
* intl-win32.c (complex_vars_of_intl_win32):
* keymap.c:
* keymap.c (print_keymap):
* keymap.c (ensure_meta_prefix_char_keymapp):
* keymap.c (Fkey_description):
* keymap.c (Ftext_char_description):
* lisp.h:
* lisp.h (struct):
* lisp.h (DECLARE_INLINE_HEADER):
* lread.c (Fload_internal):
* lread.c (locate_file):
* lread.c (read_escape):
* lread.c (read_raw_string):
* lread.c (read1):
* lread.c (read_list):
* lread.c (read_compiled_function):
* lread.c (init_lread):
* lrecord.h:
* marker.c (print_marker):
* marker.c (marker_equal):
* menubar-msw.c (displayable_menu_item):
* menubar-x.c (command_builder_operate_menu_accelerator):
* menubar.c (vars_of_menubar):
* minibuf.c (reinit_complex_vars_of_minibuf):
* minibuf.c (complex_vars_of_minibuf):
* mule-charset.c (Fmake_charset):
* mule-charset.c (complex_vars_of_mule_charset):
* mule-coding.c (iso2022_print):
* mule-coding.c (fixed_width_query):
* number.c (bignum_print):
* number.c (ratio_print):
* number.c (bigfloat_print):
* number.c (bigfloat_finalize):
* objects-msw.c:
* objects-msw.c (mswindows_color_to_string):
* objects-msw.c (mswindows_color_list):
* objects-tty.c:
* objects-tty.c (tty_font_list):
* objects-tty.c (tty_find_charset_font):
* objects-xlike-inc.c (xft_find_charset_font):
* objects-xlike-inc.c (endif):
* print.c:
* print.c (write_istring):
* print.c (write_ascstring):
* print.c (Fterpri):
* print.c (Fprint):
* print.c (print_error_message):
* print.c (print_vector_internal):
* print.c (print_cons):
* print.c (print_string):
* print.c (printing_unreadable_object):
* print.c (print_internal):
* print.c (print_float):
* print.c (print_symbol):
* process-nt.c (mswindows_report_winsock_error):
* process-nt.c (nt_canonicalize_host_name):
* process-unix.c (unix_canonicalize_host_name):
* process.c (print_process):
* process.c (report_process_error):
* process.c (report_network_error):
* process.c (make_process_internal):
* process.c (Fstart_process_internal):
* process.c (status_message):
* process.c (putenv_internal):
* process.c (vars_of_process):
* process.h:
* profile.c (vars_of_profile):
* rangetab.c (print_range_table):
* realpath.c (vars_of_realpath):
* redisplay.c (vars_of_redisplay):
* search.c (wordify):
* search.c (Freplace_match):
* sheap.c (sheap_adjust_h):
* sound.c (report_sound_error):
* sound.c (Fplay_sound_file):
* specifier.c (print_specifier):
* symbols.c (Fsubr_name):
* symbols.c (do_symval_forwarding):
* symbols.c (set_default_buffer_slot_variable):
* symbols.c (set_default_console_slot_variable):
* symbols.c (store_symval_forwarding):
* symbols.c (default_value):
* symbols.c (defsymbol_massage_name_1):
* symbols.c (defsymbol_massage_name_nodump):
* symbols.c (defsymbol_massage_name):
* symbols.c (defsymbol_massage_multiword_predicate_nodump):
* symbols.c (defsymbol_massage_multiword_predicate):
* symbols.c (defsymbol_nodump):
* symbols.c (defsymbol):
* symbols.c (defkeyword):
* symbols.c (defkeyword_massage_name):
* symbols.c (check_module_subr):
* symbols.c (deferror_1):
* symbols.c (deferror):
* symbols.c (deferror_massage_name):
* symbols.c (deferror_massage_name_and_message):
* symbols.c (defvar_magic):
* symeval.h:
* symeval.h (DEFVAR_SYMVAL_FWD):
* sysdep.c:
* sysdep.c (init_system_name):
* sysdll.c:
* sysdll.c (MAYBE_PREPEND_UNDERSCORE):
* sysdll.c (dll_function):
* sysdll.c (dll_variable):
* sysdll.c (dll_error):
* sysdll.c (dll_open):
* sysdll.c (dll_close):
* sysdll.c (image_for_address):
* sysdll.c (my_find_image):
* sysdll.c (search_linked_libs):
* sysdll.h:
* sysfile.h:
* sysfile.h (DEFAULT_DIRECTORY_FALLBACK):
* syswindows.h:
* tests.c (DFC_CHECK_LENGTH):
* tests.c (DFC_CHECK_CONTENT):
* tests.c (Ftest_hash_tables):
* text.c (vars_of_text):
* text.h:
* tooltalk.c (tt_opnum_string):
* tooltalk.c (tt_message_arg_ival_string):
* tooltalk.c (Ftooltalk_default_procid):
* tooltalk.c (Ftooltalk_default_session):
* tooltalk.c (init_tooltalk):
* tooltalk.c (vars_of_tooltalk):
* ui-gtk.c (Fdll_load):
* ui-gtk.c (type_to_marshaller_type):
* ui-gtk.c (Fgtk_import_function_internal):
* ui-gtk.c (emacs_gtk_object_printer):
* ui-gtk.c (emacs_gtk_boxed_printer):
* unicode.c (unicode_to_ichar):
* unicode.c (unicode_print):
* unicode.c (unicode_query):
* unicode.c (vars_of_unicode):
* unicode.c (complex_vars_of_unicode):
* win32.c:
* win32.c (mswindows_report_process_error):
* window.c (print_window):
* xemacs.def.in.in:
BASIC IDEA: Further fixing up uses of char * and CIbyte *
to reflect their actual semantics; Mule-izing some code;
redoing of the not-yet-working code to handle message translation.
Clean up code to handle message-translation (not yet working).
Create separate versions of build_msg_string() for working with
Ibyte *, CIbyte *, and Ascbyte * arguments. Assert that Ascbyte *
arguments are pure-ASCII. Make build_msg_string() be the same
as build_msg_ascstring(). Create same three versions of GETTEXT()
and DEFER_GETTEXT(). Also create build_defer_string() and
variants for the equivalent of DEFER_GETTEXT() when building a
string. Remove old CGETTEXT(). Clean up code where GETTEXT(),
DEFER_GETTEXT(), build_msg_string(), etc. was being called and
introduce some new calls to build_msg_string(), etc. Remove
GETTEXT() from calls to weird_doc() -- we assume that the
message snarfer knows about weird_doc(). Remove uses of
DEFER_GETTEXT() from error messages in sysdep.c and instead use
special comments /* @@@begin-snarf@@@ */ and /* @@@end-snarf@@@ */
that the message snarfer presumably knows about.
Create build_ascstring() and use it in many instances in place
of build_string(). The purpose of having Ascbyte * variants is
to make the code more self-documenting in terms of what sort of
semantics is expected for char * strings. In fact in the process
of looking for uses of build_string(), much improperly Mule-ized
was discovered.
Mule-ize a lot of code as described in previous paragraph,
e.g. in sysdep.c.
Make the error functions take Ascbyte * strings and fix up a
couple of places where non-pure-ASCII strings were being passed in
(file-coding.c, mule-coding.c, unicode.c). (It's debatable whether
we really need to make the error functions work this way. It
helps catch places where code is written in a way that message
translation won't work, but we may well never implement message
translation.)
Make staticpro() and friends take Ascbyte * strings instead of
raw char * strings. Create a const_Ascbyte_ptr dynarr type
to describe what's held by staticpro_names[] and friends,
create pdump descriptions for const_Ascbyte_ptr dynarrs, and
use them in place of specially-crafted staticpro descriptions.
Mule-ize certain other functions (e.g. x_event_name) by correcting
raw use of char * to Ascbyte *, Rawbyte * or another such type,
and raw use of char[] buffers to another type (usually Ascbyte[]).
Change many uses of write_c_string() to write_msg_string(),
write_ascstring(), etc.
Mule-ize emodules.c, emodules.h, sysdll.h.
Fix some un-Mule-ized code in intl-win32.c.
A comment in event-Xt.c and the limitations of the message
snarfer (make-msgfile or whatever) is presumably incorrect --
it should be smart enough to handle function calls spread over
more than one line. Clean up code in event-Xt.c that was
written awkwardly for this reason.
In config.h.in, instead of NEED_ERROR_CHECK_TYPES_INLINES,
create a more general XEMACS_DEFS_NEEDS_INLINE_DECLS to
indicate when inlined functions need to be declared in
xemacs.defs.in.in, and make use of it in xemacs.defs.in.in.
We need to do this because postgresql.c now calls qxestrdup(),
which is an inline function.
Make nconc2() and other such functions MODULE_API and put
them in xemacs.defs.in.in since postgresql.c now uses them.
Clean up indentation in lread.c and a few other places.
In text.h, document ASSERT_ASCTEXT_ASCII() and
ASSERT_ASCTEXT_ASCII_LEN(), group together the stand-in
encodings and add some more for DLL symbols, function and
variable names, etc.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Tue, 26 Jan 2010 23:22:30 -0600 |
parents | ef70ee47d287 |
children | 304aebb79cd3 |
rev | line source |
---|---|
714 | 1 /* GTK-specific Lisp objects. |
462 | 2 Copyright (C) 1993, 1994 Free Software Foundation, Inc. |
3 Copyright (C) 1995 Board of Trustees, University of Illinois. | |
4 Copyright (C) 1995 Tinker Systems | |
2959 | 5 Copyright (C) 1995, 1996, 2001, 2002, 2004, 2005 Ben Wing |
462 | 6 Copyright (C) 1995 Sun Microsystems |
7 | |
8 This file is part of XEmacs. | |
9 | |
10 XEmacs is free software; you can redistribute it and/or modify it | |
11 under the terms of the GNU General Public License as published by the | |
12 Free Software Foundation; either version 2, or (at your option) any | |
13 later version. | |
14 | |
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
18 for more details. | |
19 | |
20 You should have received a copy of the GNU General Public License | |
21 along with XEmacs; see the file COPYING. If not, write to | |
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
23 Boston, MA 02111-1307, USA. */ | |
24 | |
25 /* Synched up with: Not in FSF. */ | |
26 | |
27 /* Original author: Jamie Zawinski for 19.8 | |
28 font-truename stuff added by Jamie Zawinski for 19.10 | |
29 subwindow support added by Chuck Thompson | |
30 additional XPM support added by Chuck Thompson | |
31 initial X-Face support added by Stig | |
32 rewritten/restructured by Ben Wing for 19.12/19.13 | |
33 GIF/JPEG support added by Ben Wing for 19.14 | |
34 PNG support added by Bill Perry for 19.14 | |
35 Improved GIF/JPEG support added by Bill Perry for 19.14 | |
36 Cleanup/simplification of error handling by Ben Wing for 19.14 | |
37 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14 | |
38 GIF support changed to external GIFlib 3.1 by Jareth Hein for 21.0 | |
39 Many changes for color work and optimizations by Jareth Hein for 21.0 | |
40 Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 21.0 | |
41 TIFF code by Jareth Hein for 21.0 | |
42 GIF/JPEG/PNG/TIFF code moved to new glyph-eimage.c for 21.0 | |
43 Gtk version by William Perry for 21.1 | |
44 | |
45 TODO: | |
46 Support the GrayScale, StaticColor and StaticGray visual classes. | |
47 Convert images.el to C and stick it in here? | |
48 */ | |
49 | |
50 #include <config.h> | |
51 #include "lisp.h" | |
52 | |
53 #include "buffer.h" | |
872 | 54 #include "device-impl.h" |
55 #include "faces.h" | |
56 #include "file-coding.h" | |
57 #include "frame-impl.h" | |
58 #include "glyphs.h" | |
809 | 59 #include "gui.h" |
872 | 60 #include "imgproc.h" |
462 | 61 #include "insdel.h" |
872 | 62 #include "lstream.h" |
462 | 63 #include "opaque.h" |
872 | 64 #include "window.h" |
2168 | 65 #include "elhash.h" |
66 #include "events.h" | |
872 | 67 |
68 #include "console-gtk-impl.h" | |
69 #include "glyphs-gtk.h" | |
70 #include "objects-gtk-impl.h" | |
71 #include "ui-gtk.h" | |
462 | 72 |
73 #include "sysfile.h" | |
74 | |
75 #include <setjmp.h> | |
76 | |
2082 | 77 #if defined (HAVE_XPM) |
78 #include <X11/xpm.h> | |
79 #endif | |
80 | |
2168 | 81 /* Widget callback hash table callback slot. */ |
82 #define WIDGET_GLYPH_SLOT 0 | |
83 | |
462 | 84 DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing); |
85 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string); | |
86 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); | |
87 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit); | |
88 #ifdef HAVE_JPEG | |
89 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg); | |
90 #endif | |
91 #ifdef HAVE_TIFF | |
92 DECLARE_IMAGE_INSTANTIATOR_FORMAT (tiff); | |
93 #endif | |
94 #ifdef HAVE_PNG | |
95 DECLARE_IMAGE_INSTANTIATOR_FORMAT (png); | |
96 #endif | |
97 #ifdef HAVE_GIF | |
98 DECLARE_IMAGE_INSTANTIATOR_FORMAT (gif); | |
99 #endif | |
100 | |
101 #ifdef HAVE_XFACE | |
102 DEFINE_DEVICE_IIFORMAT (gtk, xface); | |
103 #endif | |
104 | |
105 #ifdef HAVE_XPM | |
106 DEFINE_DEVICE_IIFORMAT (gtk, xpm); | |
107 #endif | |
108 | |
109 DEFINE_DEVICE_IIFORMAT (gtk, xbm); | |
110 DEFINE_DEVICE_IIFORMAT (gtk, subwindow); | |
111 | |
112 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font); | |
113 Lisp_Object Qcursor_font; | |
114 | |
115 DEFINE_IMAGE_INSTANTIATOR_FORMAT (font); | |
116 | |
117 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect); | |
118 | |
119 #ifdef HAVE_WIDGETS | |
120 DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout); | |
121 DEFINE_DEVICE_IIFORMAT (gtk, widget); | |
122 DEFINE_DEVICE_IIFORMAT (gtk, native_layout); | |
123 DEFINE_DEVICE_IIFORMAT (gtk, button); | |
124 DEFINE_DEVICE_IIFORMAT (gtk, progress_gauge); | |
125 DEFINE_DEVICE_IIFORMAT (gtk, edit_field); | |
126 DEFINE_DEVICE_IIFORMAT (gtk, combo_box); | |
127 DEFINE_DEVICE_IIFORMAT (gtk, tab_control); | |
128 DEFINE_DEVICE_IIFORMAT (gtk, label); | |
129 #endif | |
130 | |
131 static void update_widget_face (GtkWidget *w, Lisp_Image_Instance *ii, | |
132 Lisp_Object domain); | |
133 static void cursor_font_instantiate (Lisp_Object image_instance, | |
134 Lisp_Object instantiator, | |
135 Lisp_Object pointer_fg, | |
136 Lisp_Object pointer_bg, | |
137 int dest_mask, | |
138 Lisp_Object domain); | |
139 | |
2054 | 140 static GdkCursorType cursor_name_to_index (const char *name); |
462 | 141 |
142 #ifndef BitmapSuccess | |
143 #define BitmapSuccess 0 | |
144 #define BitmapOpenFailed 1 | |
145 #define BitmapFileInvalid 2 | |
146 #define BitmapNoMemory 3 | |
147 #endif | |
148 | |
149 #include "bitmaps.h" | |
150 | |
151 DEFINE_IMAGE_INSTANTIATOR_FORMAT (gtk_resource); | |
152 Lisp_Object Qgtk_resource; | |
153 #ifdef HAVE_WIDGETS | |
154 Lisp_Object Qgtk_widget_instantiate_internal, Qgtk_widget_property_internal; | |
155 Lisp_Object Qgtk_widget_redisplay_internal, Qgtk_widget_set_style; | |
156 #endif | |
157 | |
158 | |
159 /************************************************************************/ | |
160 /* image instance methods */ | |
161 /************************************************************************/ | |
162 | |
163 /************************************************************************/ | |
164 /* convert from a series of RGB triples to an XImage formated for the */ | |
4252 | 165 /* proper display */ |
462 | 166 /************************************************************************/ |
167 static GdkImage * | |
168 convert_EImage_to_GDKImage (Lisp_Object device, int width, int height, | |
169 unsigned char *pic, unsigned long **pixtbl, | |
170 int *npixels) | |
171 { | |
172 GdkColormap *cmap; | |
173 GdkVisual *vis; | |
174 GdkImage *outimg; | |
175 int depth, byte_cnt, i, j; | |
176 int rd,gr,bl,q; | |
177 unsigned char *data, *ip, *dp = NULL; | |
178 quant_table *qtable = NULL; | |
179 union { | |
826 | 180 UINT_32_BIT val; |
462 | 181 char cp[4]; |
182 } conv; | |
183 | |
184 cmap = DEVICE_GTK_COLORMAP (XDEVICE(device)); | |
185 vis = DEVICE_GTK_VISUAL (XDEVICE(device)); | |
186 depth = DEVICE_GTK_DEPTH(XDEVICE(device)); | |
187 | |
188 if (vis->type == GDK_VISUAL_GRAYSCALE || vis->type == GDK_VISUAL_STATIC_COLOR || | |
189 vis->type == GDK_VISUAL_STATIC_GRAY) | |
190 { | |
191 /* #### Implement me!!! */ | |
192 return NULL; | |
193 } | |
194 | |
195 if (vis->type == GDK_VISUAL_PSEUDO_COLOR) | |
196 { | |
197 /* Quantize the image and get a histogram while we're at it. | |
198 Do this first to save memory */ | |
199 qtable = build_EImage_quantable(pic, width, height, 256); | |
200 if (qtable == NULL) return NULL; | |
201 } | |
202 | |
203 /* The first parameter (GdkWindow *) is allowed to be NULL if we | |
204 ** specify the depth */ | |
205 outimg = gdk_image_new (GDK_IMAGE_FASTEST, vis, width, height); | |
206 | |
207 if (!outimg) return NULL; | |
208 | |
209 byte_cnt = outimg->bpp; | |
210 | |
211 data = (unsigned char *) outimg->mem; | |
212 | |
213 if (!data) | |
214 { | |
215 gdk_image_destroy (outimg); | |
216 return NULL; | |
217 } | |
4252 | 218 |
462 | 219 if (vis->type == GDK_VISUAL_PSEUDO_COLOR) |
220 { | |
221 unsigned long pixarray[256]; | |
222 int pixcount, n; | |
223 /* use our quantize table to allocate the colors */ | |
224 pixcount = 32; | |
225 *pixtbl = xnew_array (unsigned long, pixcount); | |
226 *npixels = 0; | |
227 | |
228 /* ### should implement a sort by popularity to assure proper allocation */ | |
229 n = *npixels; | |
230 for (i = 0; i < qtable->num_active_colors; i++) | |
231 { | |
232 GdkColor color; | |
233 int res; | |
4252 | 234 |
462 | 235 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0; |
236 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0; | |
237 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0; | |
238 res = allocate_nearest_color (cmap, vis, &color); | |
239 if (res > 0 && res < 3) | |
240 { | |
241 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long); | |
242 (*pixtbl)[n] = color.pixel; | |
243 n++; | |
244 } | |
245 pixarray[i] = color.pixel; | |
246 } | |
247 *npixels = n; | |
248 ip = pic; | |
249 for (i = 0; i < height; i++) | |
250 { | |
251 dp = data + (i * outimg->bpl); | |
252 for (j = 0; j < width; j++) | |
253 { | |
254 rd = *ip++; | |
255 gr = *ip++; | |
256 bl = *ip++; | |
257 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)]; | |
258 #if WORDS_BIGENDIAN | |
259 if (outimg->byte_order == GDK_MSB_FIRST) | |
260 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q]; | |
261 else | |
262 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q]; | |
263 #else | |
264 if (outimg->byte_order == GDK_MSB_FIRST) | |
265 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q]; | |
266 else | |
267 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q]; | |
268 #endif | |
269 } | |
270 } | |
1726 | 271 xfree(qtable, quant_table *); |
462 | 272 } else { |
273 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk; | |
274 junk = vis->red_mask; | |
275 rshift = 0; | |
276 while ((junk & 0x1) == 0) | |
277 { | |
278 junk = junk >> 1; | |
279 rshift ++; | |
280 } | |
281 rbits = 0; | |
282 while (junk != 0) | |
283 { | |
284 junk = junk >> 1; | |
285 rbits++; | |
286 } | |
287 junk = vis->green_mask; | |
288 gshift = 0; | |
289 while ((junk & 0x1) == 0) | |
290 { | |
291 junk = junk >> 1; | |
292 gshift ++; | |
293 } | |
294 gbits = 0; | |
295 while (junk != 0) | |
296 { | |
297 junk = junk >> 1; | |
298 gbits++; | |
299 } | |
300 junk = vis->blue_mask; | |
301 bshift = 0; | |
302 while ((junk & 0x1) == 0) | |
303 { | |
304 junk = junk >> 1; | |
305 bshift ++; | |
306 } | |
307 bbits = 0; | |
308 while (junk != 0) | |
309 { | |
310 junk = junk >> 1; | |
311 bbits++; | |
312 } | |
313 ip = pic; | |
314 for (i = 0; i < height; i++) | |
315 { | |
316 dp = data + (i * outimg->bpl); | |
317 for (j = 0; j < width; j++) | |
318 { | |
319 if (rbits > 8) | |
320 rd = *ip++ << (rbits - 8); | |
321 else | |
322 rd = *ip++ >> (8 - rbits); | |
323 if (gbits > 8) | |
324 gr = *ip++ << (gbits - 8); | |
325 else | |
326 gr = *ip++ >> (8 - gbits); | |
327 if (bbits > 8) | |
328 bl = *ip++ << (bbits - 8); | |
329 else | |
330 bl = *ip++ >> (8 - bbits); | |
331 | |
332 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift); | |
333 #if WORDS_BIGENDIAN | |
334 if (outimg->byte_order == GDK_MSB_FIRST) | |
335 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q]; | |
336 else | |
337 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q]; | |
338 #else | |
339 if (outimg->byte_order == GDK_MSB_FIRST) | |
340 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q]; | |
341 else | |
342 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q]; | |
343 #endif | |
344 } | |
345 } | |
4252 | 346 } |
462 | 347 return outimg; |
348 } | |
349 | |
350 static void | |
351 gtk_print_image_instance (struct Lisp_Image_Instance *p, | |
352 Lisp_Object printcharfun, | |
2286 | 353 int UNUSED (escapeflag)) |
462 | 354 { |
355 switch (IMAGE_INSTANCE_TYPE (p)) | |
356 { | |
357 case IMAGE_MONO_PIXMAP: | |
358 case IMAGE_COLOR_PIXMAP: | |
359 case IMAGE_POINTER: | |
800 | 360 write_fmt_string (printcharfun, " (0x%lx", |
361 (unsigned long) IMAGE_INSTANCE_GTK_PIXMAP (p)); | |
462 | 362 if (IMAGE_INSTANCE_GTK_MASK (p)) |
800 | 363 write_fmt_string (printcharfun, "/0x%lx", |
364 (unsigned long) IMAGE_INSTANCE_GTK_MASK (p)); | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4700
diff
changeset
|
365 write_ascstring (printcharfun, ")"); |
462 | 366 break; |
2054 | 367 #ifdef HAVE_SUBWINDOWS |
462 | 368 case IMAGE_SUBWINDOW: |
369 /* #### implement me */ | |
370 #endif | |
371 default: | |
372 break; | |
373 } | |
374 } | |
375 | |
376 static void | |
377 gtk_finalize_image_instance (struct Lisp_Image_Instance *p) | |
378 { | |
379 if (!p->data) | |
380 return; | |
381 | |
382 if (DEVICE_LIVE_P (XDEVICE (p->device))) | |
383 { | |
384 if (0) | |
385 ; | |
386 #ifdef HAVE_WIDGETS | |
387 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET) | |
388 { | |
389 if (IMAGE_INSTANCE_SUBWINDOW_ID (p)) | |
390 { | |
2054 | 391 gtk_widget_destroy ((GtkWidget*) IMAGE_INSTANCE_SUBWINDOW_ID (p)); |
462 | 392 |
393 /* We can release the callbacks again. */ | |
394 /* #### FIXME! */ | |
395 /* ungcpro_popup_callbacks (...); */ | |
396 | |
397 /* IMAGE_INSTANCE_GTK_WIDGET_ID (p) = 0; */ | |
398 IMAGE_INSTANCE_GTK_CLIPWIDGET (p) = 0; | |
399 } | |
400 } | |
401 #endif | |
402 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) | |
403 { | |
2500 | 404 ABORT(); |
462 | 405 } |
406 else | |
407 { | |
408 int i; | |
409 if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p)) | |
410 disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p)); | |
411 | |
412 if (IMAGE_INSTANCE_GTK_MASK (p) && | |
413 IMAGE_INSTANCE_GTK_MASK (p) != IMAGE_INSTANCE_GTK_PIXMAP (p)) | |
414 gdk_pixmap_unref (IMAGE_INSTANCE_GTK_MASK (p)); | |
415 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0; | |
416 | |
417 if (IMAGE_INSTANCE_GTK_PIXMAP_SLICES (p)) | |
418 { | |
419 for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++) | |
420 if (IMAGE_INSTANCE_GTK_PIXMAP_SLICE (p,i)) | |
421 { | |
422 gdk_pixmap_unref (IMAGE_INSTANCE_GTK_PIXMAP_SLICE (p,i)); | |
423 IMAGE_INSTANCE_GTK_PIXMAP_SLICE (p, i) = 0; | |
424 } | |
1726 | 425 xfree (IMAGE_INSTANCE_GTK_PIXMAP_SLICES (p), GdkPixmap **); |
462 | 426 IMAGE_INSTANCE_GTK_PIXMAP_SLICES (p) = 0; |
427 } | |
428 | |
429 if (IMAGE_INSTANCE_GTK_CURSOR (p)) | |
430 { | |
431 gdk_cursor_destroy (IMAGE_INSTANCE_GTK_CURSOR (p)); | |
432 IMAGE_INSTANCE_GTK_CURSOR (p) = 0; | |
433 } | |
434 } | |
435 | |
436 #if 0 | |
437 /* #### BILL!!! */ | |
438 if (IMAGE_INSTANCE_GTK_NPIXELS (p) != 0) | |
439 { | |
440 XFreeColors (dpy, | |
441 IMAGE_INSTANCE_GTK_COLORMAP (p), | |
442 IMAGE_INSTANCE_GTK_PIXELS (p), | |
443 IMAGE_INSTANCE_GTK_NPIXELS (p), 0); | |
444 IMAGE_INSTANCE_GTK_NPIXELS (p) = 0; | |
445 } | |
446 #endif | |
447 } | |
448 | |
449 if (IMAGE_INSTANCE_TYPE (p) != IMAGE_WIDGET | |
450 && IMAGE_INSTANCE_TYPE (p) != IMAGE_SUBWINDOW | |
451 && IMAGE_INSTANCE_GTK_PIXELS (p)) | |
452 { | |
1726 | 453 xfree (IMAGE_INSTANCE_GTK_PIXELS (p), unsigned long *); |
462 | 454 IMAGE_INSTANCE_GTK_PIXELS (p) = 0; |
455 } | |
456 | |
1726 | 457 xfree (p->data, void *); |
462 | 458 p->data = 0; |
459 } | |
460 | |
461 static int | |
462 gtk_image_instance_equal (struct Lisp_Image_Instance *p1, | |
2286 | 463 struct Lisp_Image_Instance *p2, int UNUSED (depth)) |
462 | 464 { |
465 switch (IMAGE_INSTANCE_TYPE (p1)) | |
466 { | |
467 case IMAGE_MONO_PIXMAP: | |
468 case IMAGE_COLOR_PIXMAP: | |
469 case IMAGE_POINTER: | |
470 if (IMAGE_INSTANCE_GTK_COLORMAP (p1) != IMAGE_INSTANCE_GTK_COLORMAP (p2) || | |
471 IMAGE_INSTANCE_GTK_NPIXELS (p1) != IMAGE_INSTANCE_GTK_NPIXELS (p2)) | |
472 return 0; | |
2054 | 473 #ifdef HAVE_SUBWINDOWS |
462 | 474 case IMAGE_SUBWINDOW: |
475 /* #### implement me */ | |
476 #endif | |
477 break; | |
478 default: | |
479 break; | |
480 } | |
481 | |
482 return 1; | |
483 } | |
484 | |
2515 | 485 static Hashcode |
2286 | 486 gtk_image_instance_hash (struct Lisp_Image_Instance *p, int UNUSED (depth)) |
462 | 487 { |
488 switch (IMAGE_INSTANCE_TYPE (p)) | |
489 { | |
490 case IMAGE_MONO_PIXMAP: | |
491 case IMAGE_COLOR_PIXMAP: | |
492 case IMAGE_POINTER: | |
493 return IMAGE_INSTANCE_GTK_NPIXELS (p); | |
2054 | 494 #ifdef HAVE_SUBWINDOWS |
462 | 495 case IMAGE_SUBWINDOW: |
496 /* #### implement me */ | |
497 return 0; | |
498 #endif | |
499 default: | |
500 return 0; | |
501 } | |
502 } | |
503 | |
504 /* Set all the slots in an image instance structure to reasonable | |
505 default values. This is used somewhere within an instantiate | |
506 method. It is assumed that the device slot within the image | |
507 instance is already set -- this is the case when instantiate | |
508 methods are called. */ | |
509 | |
510 static void | |
511 gtk_initialize_pixmap_image_instance (struct Lisp_Image_Instance *ii, | |
512 int slices, | |
513 enum image_instance_type type) | |
514 { | |
515 ii->data = xnew_and_zero (struct gtk_image_instance_data); | |
516 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices; | |
517 IMAGE_INSTANCE_GTK_PIXMAP_SLICES (ii) = | |
518 xnew_array_and_zero (GdkPixmap *, slices); | |
519 IMAGE_INSTANCE_TYPE (ii) = type; | |
520 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil; | |
521 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil; | |
522 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil; | |
523 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil; | |
524 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil; | |
525 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil; | |
526 } | |
527 | |
528 | |
529 /************************************************************************/ | |
530 /* pixmap file functions */ | |
531 /************************************************************************/ | |
532 | |
533 /* Where bitmaps are; initialized from resource database */ | |
534 Lisp_Object Vgtk_bitmap_file_path; | |
535 | |
536 #ifndef BITMAPDIR | |
537 #define BITMAPDIR "/usr/include/X11/bitmaps" | |
538 #endif | |
539 | |
540 /* Given a pixmap filename, look through all of the "standard" places | |
541 where the file might be located. Return a full pathname if found; | |
542 otherwise, return Qnil. */ | |
543 | |
544 static Lisp_Object | |
545 gtk_locate_pixmap_file (Lisp_Object name) | |
546 { | |
547 /* This function can GC if IN_REDISPLAY is false */ | |
548 | |
549 /* Check non-absolute pathnames with a directory component relative to | |
550 the search path; that's the way Xt does it. */ | |
551 /* #### Unix-specific */ | |
826 | 552 if (string_byte (name, 0) == '/' || |
553 (string_byte (name, 0) == '.' && | |
554 (string_byte (name, 1) == '/' || | |
555 (string_byte (name, 1) == '.' && | |
556 (string_byte (name, 2) == '/'))))) | |
462 | 557 { |
558 if (!NILP (Ffile_readable_p (name))) | |
559 return name; | |
560 else | |
561 return Qnil; | |
562 } | |
563 | |
564 if (NILP (Vgtk_bitmap_file_path)) | |
565 { | |
566 Vgtk_bitmap_file_path = nconc2 (Vgtk_bitmap_file_path, | |
778 | 567 (split_external_path (BITMAPDIR))); |
462 | 568 } |
569 | |
570 { | |
571 Lisp_Object found; | |
572 if (locate_file (Vgtk_bitmap_file_path, name, Qnil, &found, R_OK) < 0) | |
573 { | |
574 Lisp_Object temp = list1 (Vdata_directory); | |
575 struct gcpro gcpro1; | |
576 | |
577 GCPRO1 (temp); | |
578 locate_file (temp, name, Qnil, &found, R_OK); | |
579 UNGCPRO; | |
580 } | |
581 | |
582 return found; | |
583 } | |
584 } | |
585 | |
586 static Lisp_Object | |
587 locate_pixmap_file (Lisp_Object name) | |
588 { | |
589 return gtk_locate_pixmap_file (name); | |
590 } | |
591 | |
592 | |
593 /************************************************************************/ | |
594 /* cursor functions */ | |
595 /************************************************************************/ | |
596 | |
597 /* Check that this server supports cursors of size WIDTH * HEIGHT. If | |
598 not, signal an error. INSTANTIATOR is only used in the error | |
599 message. */ | |
600 | |
601 static void | |
2286 | 602 check_pointer_sizes (unsigned int UNUSED (width), unsigned int UNUSED (height), |
603 Lisp_Object UNUSED (instantiator)) | |
462 | 604 { |
605 /* #### BILL!!! There is no way to call XQueryBestCursor from Gdk! */ | |
606 #if 0 | |
607 unsigned int best_width, best_height; | |
608 if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs), | |
609 width, height, &best_width, &best_height)) | |
610 /* this means that an X error of some sort occurred (we trap | |
611 these so they're not fatal). */ | |
563 | 612 gui_error ("XQueryBestCursor() failed?", instantiator); |
462 | 613 |
614 if (width > best_width || height > best_height) | |
563 | 615 signal_ferror_with_frob (Qgui_error, instantiator, |
616 "pointer too large (%dx%d): " | |
617 "server requires %dx%d or smaller", | |
618 width, height, best_width, best_height); | |
462 | 619 #endif |
620 } | |
621 | |
622 static void | |
623 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground, | |
624 Lisp_Object *background, GdkColor *xfg, GdkColor *xbg) | |
625 { | |
626 if (!NILP (*foreground) && !COLOR_INSTANCEP (*foreground)) | |
627 *foreground = | |
628 Fmake_color_instance (*foreground, device, | |
629 encode_error_behavior_flag (ERROR_ME)); | |
630 if (COLOR_INSTANCEP (*foreground)) | |
631 *xfg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (*foreground)); | |
632 else | |
633 { | |
634 xfg->pixel = 0; | |
635 xfg->red = xfg->green = xfg->blue = 0; | |
636 } | |
637 | |
638 if (!NILP (*background) && !COLOR_INSTANCEP (*background)) | |
639 *background = | |
640 Fmake_color_instance (*background, device, | |
641 encode_error_behavior_flag (ERROR_ME)); | |
642 if (COLOR_INSTANCEP (*background)) | |
643 *xbg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (*background)); | |
644 else | |
645 { | |
646 xbg->pixel = 0; | |
647 xbg->red = xbg->green = xbg->blue = ~0; | |
648 } | |
649 } | |
650 | |
651 static void | |
2286 | 652 maybe_recolor_cursor (Lisp_Object UNUSED (image_instance), |
653 Lisp_Object UNUSED (foreground), | |
654 Lisp_Object UNUSED (background)) | |
462 | 655 { |
656 #if 0 | |
657 /* #### BILL!!! */ | |
658 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance); | |
659 GdkColor xfg, xbg; | |
660 | |
661 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg); | |
662 if (!NILP (foreground) || !NILP (background)) | |
663 { | |
664 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)), | |
665 XIMAGE_INSTANCE_GTK_CURSOR (image_instance), | |
666 &xfg, &xbg); | |
667 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground; | |
668 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background; | |
669 } | |
670 #else | |
671 /* stderr_out ("Don't know how to recolor cursors in Gtk!\n"); */ | |
672 #endif | |
673 } | |
674 | |
675 | |
676 /************************************************************************/ | |
677 /* color pixmap functions */ | |
678 /************************************************************************/ | |
679 | |
2959 | 680 /* Create a pointer from a color pixmap. */ |
681 | |
682 static void | |
683 image_instance_convert_to_pointer (Lisp_Image_Instance *ii, | |
684 Lisp_Object instantiator, | |
685 Lisp_Object pointer_fg, | |
686 Lisp_Object pointer_bg) | |
687 { | |
688 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
3087 | 689 GdkPixmap *pixmap = IMAGE_INSTANCE_GTK_PIXMAP (ii); |
690 GdkPixmap *mask = (GdkPixmap *) IMAGE_INSTANCE_GTK_MASK (ii); | |
2959 | 691 GdkColor fg, bg; |
692 int xhot = 0, yhot = 0; | |
693 int w, h; | |
694 | |
695 if (INTP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii))) | |
696 xhot = XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)); | |
697 if (INTP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii))) | |
698 yhot = XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)); | |
699 w = IMAGE_INSTANCE_PIXMAP_WIDTH (ii); | |
700 h = IMAGE_INSTANCE_PIXMAP_HEIGHT (ii); | |
701 | |
702 check_pointer_sizes (w, h, instantiator); | |
703 | |
704 /* If the loaded pixmap has colors allocated (meaning it came from an | |
705 XPM file), then use those as the default colors for the cursor we | |
706 create. Otherwise, default to pointer_fg and pointer_bg. | |
707 */ | |
708 if (DEVICE_GTK_DEPTH (XDEVICE (device)) > 1) | |
709 { | |
710 warn_when_safe (Qunimplemented, Qnotice, | |
711 "GTK does not support XPM cursors...\n"); | |
712 IMAGE_INSTANCE_GTK_CURSOR (ii) = gdk_cursor_new (GDK_COFFEE_MUG); | |
713 } | |
714 else | |
715 { | |
716 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg, | |
717 &fg, &bg); | |
718 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg; | |
719 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg; | |
720 IMAGE_INSTANCE_GTK_CURSOR (ii) = | |
721 gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg, xhot, yhot); | |
722 } | |
723 } | |
724 | |
462 | 725 /* Initialize an image instance from an XImage. |
726 | |
727 DEST_MASK specifies the mask of allowed image types. | |
728 | |
729 PIXELS and NPIXELS specify an array of pixels that are used in | |
730 the image. These need to be kept around for the duration of the | |
731 image. When the image instance is freed, XFreeColors() will | |
732 automatically be called on all the pixels specified here; thus, | |
733 you should have allocated the pixels yourself using XAllocColor() | |
734 or the like. The array passed in is used directly without | |
735 being copied, so it should be heap data created with xmalloc(). | |
736 It will be freed using xfree() when the image instance is | |
737 destroyed. | |
738 | |
739 If this fails, signal an error. INSTANTIATOR is only used | |
740 in the error message. | |
741 | |
742 #### This should be able to handle conversion into `pointer'. | |
743 Use the same code as for `xpm'. */ | |
744 | |
745 static void | |
746 init_image_instance_from_gdk_image (struct Lisp_Image_Instance *ii, | |
747 GdkImage *gdk_image, | |
748 int dest_mask, | |
749 GdkColormap *cmap, | |
750 unsigned long *pixels, | |
751 int npixels, | |
752 int slices, | |
2959 | 753 Lisp_Object instantiator, |
754 Lisp_Object pointer_fg, | |
755 Lisp_Object pointer_bg) | |
462 | 756 { |
757 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
758 GdkGC *gc; | |
759 GdkWindow *d; | |
760 GdkPixmap *pixmap; | |
2959 | 761 enum image_instance_type type; |
462 | 762 |
763 if (!DEVICE_GTK_P (XDEVICE (device))) | |
563 | 764 gui_error ("Not a Gtk device", device); |
462 | 765 |
766 d = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))); | |
767 | |
2959 | 768 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) |
769 type = IMAGE_COLOR_PIXMAP; | |
770 else if (dest_mask & IMAGE_POINTER_MASK) | |
771 type = IMAGE_POINTER; | |
772 else | |
462 | 773 incompatible_image_types (instantiator, dest_mask, |
2959 | 774 IMAGE_COLOR_PIXMAP_MASK |
775 | IMAGE_POINTER_MASK); | |
462 | 776 |
777 pixmap = gdk_pixmap_new (d, gdk_image->width, gdk_image->height, gdk_image->depth); | |
778 if (!pixmap) | |
563 | 779 gui_error ("Unable to create pixmap", instantiator); |
462 | 780 |
781 gc = gdk_gc_new (pixmap); | |
782 if (!gc) | |
783 { | |
784 gdk_pixmap_unref (pixmap); | |
563 | 785 gui_error ("Unable to create GC", instantiator); |
462 | 786 } |
787 | |
788 gdk_draw_image (GDK_DRAWABLE (pixmap), gc, gdk_image, | |
789 0, 0, 0, 0, gdk_image->width, gdk_image->height); | |
790 | |
791 gdk_gc_destroy (gc); | |
792 | |
793 gtk_initialize_pixmap_image_instance (ii, slices, IMAGE_COLOR_PIXMAP); | |
794 | |
795 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = | |
796 find_keyword_in_vector (instantiator, Q_file); | |
797 | |
798 IMAGE_INSTANCE_GTK_PIXMAP (ii) = pixmap; | |
4433
1bf48c59700e
Fix old use of rvalue on lhs to placate gcc >4.0.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4252
diff
changeset
|
799 IMAGE_INSTANCE_PIXMAP_MASK (ii) = 0; |
462 | 800 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = gdk_image->width; |
801 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = gdk_image->height; | |
802 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = gdk_image->depth; | |
803 IMAGE_INSTANCE_GTK_COLORMAP (ii) = cmap; | |
804 IMAGE_INSTANCE_GTK_PIXELS (ii) = pixels; | |
805 IMAGE_INSTANCE_GTK_NPIXELS (ii) = npixels; | |
2959 | 806 |
807 if (type == IMAGE_POINTER) | |
808 image_instance_convert_to_pointer (ii, instantiator, pointer_fg, | |
809 pointer_bg); | |
462 | 810 } |
811 | |
812 #if 0 | |
813 void init_image_instance_from_gdk_pixmap (struct Lisp_Image_Instance *ii, | |
814 struct device *device, | |
815 GdkPixmap *gdk_pixmap, | |
816 int dest_mask, | |
817 Lisp_Object instantiator) | |
818 { | |
819 GdkWindow *d; | |
820 gint width, height, depth; | |
821 | |
822 if (!DEVICE_GTK_P (device)) | |
2500 | 823 ABORT (); |
462 | 824 |
825 IMAGE_INSTANCE_DEVICE (ii) = device; | |
826 IMAGE_INSTANCE_TYPE (ii) = IMAGE_COLOR_PIXMAP; | |
827 | |
828 d = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (device)); | |
829 | |
830 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK)) | |
831 incompatible_image_types (instantiator, dest_mask, | |
832 IMAGE_COLOR_PIXMAP_MASK); | |
833 | |
834 gtk_initialize_pixmap_image_instance (ii, IMAGE_COLOR_PIXMAP); | |
835 | |
836 gdk_window_get_geometry (gdk_pixmap, NULL, NULL, &width, &height, &depth); | |
837 | |
838 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil; | |
839 IMAGE_INSTANCE_GTK_PIXMAP (ii) = gdk_pixmap; | |
4629
a1dd514df5c6
Apply the 2008-03-05 change from Dominique Quatravaux in init_image_instance_from_gdk_pixmap as well even though the code is not enabled at the moment
"Ville Skyttä <scop@xemacs.org>"
parents:
4433
diff
changeset
|
840 IMAGE_INSTANCE_PIXMAP_MASK (ii) = 0; |
462 | 841 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width; |
842 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height; | |
843 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth; | |
844 IMAGE_INSTANCE_GTK_COLORMAP (ii) = gdk_window_get_colormap (gdk_pixmap); | |
845 IMAGE_INSTANCE_GTK_PIXELS (ii) = 0; | |
846 IMAGE_INSTANCE_GTK_NPIXELS (ii) = 0; | |
847 } | |
848 #endif | |
849 | |
850 static void | |
851 image_instance_add_gdk_image (Lisp_Image_Instance *ii, | |
852 GdkImage *gdk_image, | |
853 int slice, | |
854 Lisp_Object instantiator) | |
855 { | |
856 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
857 GdkWindow *d; | |
858 GdkPixmap *pixmap; | |
859 GdkGC *gc; | |
860 | |
861 d = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))); | |
862 | |
863 pixmap = gdk_pixmap_new (d, gdk_image->width, gdk_image->height, gdk_image->depth); | |
864 | |
865 if (!pixmap) | |
563 | 866 gui_error ("Unable to create pixmap", instantiator); |
462 | 867 |
868 gc = gdk_gc_new (pixmap); | |
869 | |
870 if (!gc) | |
871 { | |
872 gdk_pixmap_unref (pixmap); | |
563 | 873 gui_error ("Unable to create GC", instantiator); |
462 | 874 } |
875 | |
876 gdk_draw_image (GDK_DRAWABLE (pixmap), gc, gdk_image, 0, 0, 0, 0, | |
877 gdk_image->width, gdk_image->height); | |
878 | |
879 gdk_gc_destroy (gc); | |
880 | |
881 IMAGE_INSTANCE_GTK_PIXMAP_SLICE (ii, slice) = pixmap; | |
882 } | |
883 | |
884 static void | |
885 gtk_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii, | |
886 int width, int height, | |
887 int slices, | |
4252 | 888 unsigned char *eimage, |
462 | 889 int dest_mask, |
890 Lisp_Object instantiator, | |
2959 | 891 Lisp_Object pointer_fg, |
892 Lisp_Object pointer_bg, | |
2286 | 893 Lisp_Object UNUSED (domain)) |
462 | 894 { |
895 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
896 GdkColormap *cmap = DEVICE_GTK_COLORMAP (XDEVICE(device)); | |
897 unsigned long *pixtbl = NULL; | |
898 int npixels = 0; | |
899 int slice; | |
900 GdkImage* gdk_image; | |
901 | |
902 | |
903 for (slice = 0; slice < slices; slice++) | |
904 { | |
905 gdk_image = convert_EImage_to_GDKImage (device, width, height, eimage, | |
906 &pixtbl, &npixels); | |
907 if (!gdk_image) | |
908 { | |
1726 | 909 if (pixtbl) |
910 xfree (pixtbl, unsigned long *); | |
462 | 911 signal_image_error("EImage to GdkImage conversion failed", instantiator); |
912 } | |
913 | |
914 if (slice == 0) | |
915 /* Now create the pixmap and set up the image instance */ | |
916 init_image_instance_from_gdk_image (ii, gdk_image, dest_mask, | |
917 cmap, pixtbl, npixels, slices, | |
2959 | 918 instantiator, pointer_fg, |
919 pointer_bg); | |
462 | 920 else |
921 image_instance_add_gdk_image (ii, gdk_image, slice, instantiator); | |
922 | |
923 if (gdk_image) | |
924 { | |
925 gdk_image_destroy (gdk_image); | |
926 } | |
927 gdk_image = 0; | |
928 } | |
929 } | |
930 | |
931 /* Given inline data for a mono pixmap, create and return the | |
932 corresponding X object. */ | |
933 | |
934 static GdkPixmap * | |
935 pixmap_from_xbm_inline (Lisp_Object device, int width, int height, | |
936 /* Note that data is in ext-format! */ | |
771 | 937 const Extbyte *bits) |
462 | 938 { |
939 return (gdk_bitmap_create_from_data (GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))), | |
940 (char *) bits, width, height)); | |
941 } | |
942 | |
943 /* Given inline data for a mono pixmap, initialize the given | |
944 image instance accordingly. */ | |
945 | |
946 static void | |
947 init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii, | |
948 int width, int height, | |
949 /* Note that data is in ext-format! */ | |
771 | 950 const char *bits, |
462 | 951 Lisp_Object instantiator, |
952 Lisp_Object pointer_fg, | |
953 Lisp_Object pointer_bg, | |
954 int dest_mask, | |
955 GdkPixmap *mask, | |
2286 | 956 Lisp_Object UNUSED (mask_filename)) |
462 | 957 { |
958 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
959 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground); | |
960 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background); | |
961 GdkColor fg; | |
962 GdkColor bg; | |
963 enum image_instance_type type; | |
964 GdkWindow *draw = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))); | |
965 GdkColormap *cmap = DEVICE_GTK_COLORMAP (XDEVICE(device)); | |
966 GdkColor black; | |
967 GdkColor white; | |
968 | |
969 gdk_color_black(cmap, &black); | |
970 gdk_color_white(cmap, &white); | |
971 | |
972 if (!DEVICE_GTK_P (XDEVICE (device))) | |
563 | 973 gui_error ("Not a Gtk device", device); |
462 | 974 |
975 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) && | |
976 (dest_mask & IMAGE_COLOR_PIXMAP_MASK)) | |
977 { | |
978 if (!NILP (foreground) || !NILP (background)) | |
979 type = IMAGE_COLOR_PIXMAP; | |
980 else | |
981 type = IMAGE_MONO_PIXMAP; | |
982 } | |
983 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK) | |
984 type = IMAGE_MONO_PIXMAP; | |
985 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) | |
986 type = IMAGE_COLOR_PIXMAP; | |
987 else if (dest_mask & IMAGE_POINTER_MASK) | |
988 type = IMAGE_POINTER; | |
989 else | |
990 incompatible_image_types (instantiator, dest_mask, | |
991 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK | |
992 | IMAGE_POINTER_MASK); | |
993 | |
994 gtk_initialize_pixmap_image_instance (ii, 1, type); | |
995 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width; | |
996 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height; | |
997 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = | |
998 find_keyword_in_vector (instantiator, Q_file); | |
999 | |
1000 switch (type) | |
1001 { | |
1002 case IMAGE_MONO_PIXMAP: | |
1003 { | |
1004 IMAGE_INSTANCE_GTK_PIXMAP (ii) = | |
1005 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits); | |
1006 } | |
1007 break; | |
1008 | |
1009 case IMAGE_COLOR_PIXMAP: | |
1010 { | |
1011 gint d = DEVICE_GTK_DEPTH (XDEVICE(device)); | |
1012 | |
1013 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground)) | |
1014 foreground = | |
1015 Fmake_color_instance (foreground, device, | |
1016 encode_error_behavior_flag (ERROR_ME)); | |
1017 | |
1018 if (COLOR_INSTANCEP (foreground)) | |
1019 fg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (foreground)); | |
1020 | |
1021 if (!NILP (background) && !COLOR_INSTANCEP (background)) | |
1022 background = | |
1023 Fmake_color_instance (background, device, | |
1024 encode_error_behavior_flag (ERROR_ME)); | |
1025 | |
1026 if (COLOR_INSTANCEP (background)) | |
1027 bg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (background)); | |
1028 | |
1029 /* We used to duplicate the pixels using XAllocColor(), to protect | |
1030 against their getting freed. Just as easy to just store the | |
1031 color instances here and GC-protect them, so this doesn't | |
1032 happen. */ | |
1033 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground; | |
1034 IMAGE_INSTANCE_PIXMAP_BG (ii) = background; | |
1035 IMAGE_INSTANCE_GTK_PIXMAP (ii) = | |
1036 gdk_pixmap_create_from_data (draw, (char *) bits, width, height, d, &fg, &bg); | |
1037 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d; | |
1038 } | |
1039 break; | |
1040 | |
1041 case IMAGE_POINTER: | |
1042 { | |
1043 GdkColor fg_color, bg_color; | |
1044 GdkPixmap *source; | |
1045 | |
1046 check_pointer_sizes (width, height, instantiator); | |
1047 | |
1048 source = gdk_pixmap_create_from_data (draw, (char *) bits, width, height, 1, &black, &white); | |
1049 | |
1050 if (NILP (foreground)) | |
1051 foreground = pointer_fg; | |
1052 if (NILP (background)) | |
1053 background = pointer_bg; | |
1054 generate_cursor_fg_bg (device, &foreground, &background, | |
1055 &fg_color, &bg_color); | |
1056 | |
1057 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground; | |
1058 IMAGE_INSTANCE_PIXMAP_BG (ii) = background; | |
1059 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = | |
1060 find_keyword_in_vector (instantiator, Q_hotspot_x); | |
1061 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = | |
1062 find_keyword_in_vector (instantiator, Q_hotspot_y); | |
1063 IMAGE_INSTANCE_GTK_CURSOR (ii) = | |
1064 gdk_cursor_new_from_pixmap (source, mask, &fg_color, &bg_color, | |
1065 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ? | |
1066 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0, | |
1067 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ? | |
1068 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0); | |
1069 } | |
1070 break; | |
1071 | |
1072 default: | |
2500 | 1073 ABORT (); |
462 | 1074 } |
1075 } | |
1076 | |
1077 static void | |
1078 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, | |
1079 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
1080 int dest_mask, int width, int height, | |
1081 /* Note that data is in ext-format! */ | |
771 | 1082 const char *bits) |
462 | 1083 { |
1084 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data); | |
1085 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file); | |
1086 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
1087 GdkPixmap *mask = 0; | |
2054 | 1088 const Extbyte *gcc_may_you_rot_in_hell; |
462 | 1089 |
1090 if (!NILP (mask_data)) | |
1091 { | |
1092 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (mask_data))), | |
1093 C_STRING_ALLOCA, gcc_may_you_rot_in_hell, | |
1094 Qfile_name); | |
1095 mask = | |
1096 pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii), | |
1097 XINT (XCAR (mask_data)), | |
1098 XINT (XCAR (XCDR (mask_data))), | |
1099 gcc_may_you_rot_in_hell); | |
1100 } | |
1101 | |
1102 init_image_instance_from_xbm_inline (ii, width, height, bits, | |
1103 instantiator, pointer_fg, pointer_bg, | |
1104 dest_mask, mask, mask_file); | |
1105 } | |
1106 | |
1107 /* Instantiate method for XBM's. */ | |
1108 | |
1109 static void | |
1110 gtk_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
1111 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2286 | 1112 int dest_mask, Lisp_Object UNUSED (domain)) |
462 | 1113 { |
1114 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
771 | 1115 const char *gcc_go_home; |
462 | 1116 |
1117 assert (!NILP (data)); | |
1118 | |
1119 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (data))), | |
1120 C_STRING_ALLOCA, gcc_go_home, | |
1121 Qbinary); | |
1122 | |
1123 xbm_instantiate_1 (image_instance, instantiator, pointer_fg, | |
1124 pointer_bg, dest_mask, XINT (XCAR (data)), | |
1125 XINT (XCAR (XCDR (data))), gcc_go_home); | |
1126 } | |
1127 | |
1128 | |
1129 #ifdef HAVE_XPM | |
1130 /********************************************************************** | |
1131 * XPM * | |
1132 **********************************************************************/ | |
1133 | |
739 | 1134 struct color_symbol |
1135 { | |
2054 | 1136 Ibyte* name; |
739 | 1137 GdkColor color; |
1138 }; | |
1139 | |
1140 static struct color_symbol* | |
1141 extract_xpm_color_names (Lisp_Object device, | |
1142 Lisp_Object domain, | |
1143 Lisp_Object color_symbol_alist, | |
1144 int* nsymbols) | |
1145 { | |
1146 /* This function can GC */ | |
1147 Lisp_Object rest; | |
1148 Lisp_Object results = Qnil; | |
1149 int i, j; | |
1150 struct color_symbol *colortbl; | |
1151 struct gcpro gcpro1, gcpro2; | |
1152 | |
1153 GCPRO2 (results, device); | |
1154 | |
1155 /* We built up results to be (("name" . #<color>) ...) so that if an | |
1156 error happens we don't lose any malloc()ed data, or more importantly, | |
1157 leave any pixels allocated in the server. */ | |
1158 i = 0; | |
1159 LIST_LOOP (rest, color_symbol_alist) | |
1160 { | |
1161 Lisp_Object cons = XCAR (rest); | |
1162 Lisp_Object name = XCAR (cons); | |
1163 Lisp_Object value = XCDR (cons); | |
1164 if (NILP (value)) | |
1165 continue; | |
1166 if (STRINGP (value)) | |
1167 value = | |
1168 Fmake_color_instance | |
793 | 1169 (value, device, encode_error_behavior_flag (ERROR_ME_DEBUG_WARN)); |
739 | 1170 else |
4252 | 1171 { |
1172 assert (COLOR_SPECIFIERP (value)); | |
1173 value = Fspecifier_instance (value, domain, Qnil, Qnil); | |
1174 } | |
739 | 1175 |
1176 if (NILP (value)) | |
4252 | 1177 continue; |
739 | 1178 results = noseeum_cons (noseeum_cons (name, value), results); |
1179 i++; | |
1180 } | |
1181 UNGCPRO; /* no more evaluation */ | |
1182 | |
1183 *nsymbols=i; | |
1184 if (i == 0) return 0; | |
1185 | |
1186 colortbl = xnew_array_and_zero (struct color_symbol, i); | |
1187 | |
1188 for (j=0; j<i; j++) | |
1189 { | |
1190 Lisp_Object cons = XCAR (results); | |
4252 | 1191 colortbl[j].color = |
739 | 1192 * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (XCDR (cons))); |
1193 | |
2054 | 1194 colortbl[j].name = XSTRING_DATA (XCAR (cons)); |
1195 free_cons (cons); | |
739 | 1196 cons = results; |
1197 results = XCDR (results); | |
2054 | 1198 free_cons (cons); |
739 | 1199 } |
1200 return colortbl; | |
1201 } | |
1202 | |
462 | 1203 static void |
739 | 1204 gtk_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, |
462 | 1205 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
1206 int dest_mask, Lisp_Object domain) | |
1207 { | |
1208 /* This function can GC */ | |
1209 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
1210 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
1211 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
1212 GdkColormap *cmap; | |
1213 int depth; | |
1214 GdkVisual *visual; | |
1215 GdkPixmap *pixmap; | |
1216 GdkPixmap *mask = 0; | |
1217 GdkWindow *window = 0; | |
739 | 1218 int nsymbols = 0, i = 0; |
1219 struct color_symbol *color_symbols = NULL; | |
462 | 1220 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator, |
1221 Q_color_symbols); | |
1222 enum image_instance_type type; | |
1223 int force_mono; | |
2054 | 1224 gint w, h; |
2082 | 1225 struct gcpro gcpro1, gcpro2, gcpro3; |
2367 | 1226 const Binbyte * volatile dstring; |
462 | 1227 |
1228 if (!DEVICE_GTK_P (XDEVICE (device))) | |
563 | 1229 gui_error ("Not a Gtk device", device); |
462 | 1230 |
1231 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) | |
1232 type = IMAGE_COLOR_PIXMAP; | |
1233 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK) | |
1234 type = IMAGE_MONO_PIXMAP; | |
1235 else if (dest_mask & IMAGE_POINTER_MASK) | |
1236 type = IMAGE_POINTER; | |
1237 else | |
1238 incompatible_image_types (instantiator, dest_mask, | |
1239 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK | |
1240 | IMAGE_POINTER_MASK); | |
1241 force_mono = (type != IMAGE_COLOR_PIXMAP); | |
1242 | |
2082 | 1243 GCPRO3 (device, data, color_symbol_alist); |
771 | 1244 |
462 | 1245 window = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))); |
1246 cmap = DEVICE_GTK_COLORMAP (XDEVICE (device)); | |
1247 depth = DEVICE_GTK_DEPTH (XDEVICE (device)); | |
1248 visual = DEVICE_GTK_VISUAL (XDEVICE (device)); | |
1249 | |
1250 gtk_initialize_pixmap_image_instance (ii, 1, type); | |
1251 | |
1252 assert (!NILP (data)); | |
1253 | |
2082 | 1254 /* Extract all the entries from xpm-color-symbols */ |
771 | 1255 color_symbols = extract_xpm_color_names (device, domain, color_symbol_alist, |
1256 &nsymbols); | |
2082 | 1257 assert (!NILP (data)); |
1258 | |
1259 LISP_STRING_TO_EXTERNAL(data, dstring, Qbinary); | |
1260 | |
1261 /* | |
1262 * GTK only uses the 'c' color entry of an XPM and doesn't use the symbolic | |
1263 * color names at all. This is unfortunate because the way to change the | |
1264 * colors from lisp is by adding the symbolic names, and the new colors, to | |
1265 * the variable xpm-color-symbols. | |
1266 * | |
1267 * To get around this decode the XPM, add a 'c' entry of the desired color | |
1268 * for each matching symbolic color, recode the XPM and pass it to GTK. The | |
1269 * decode and recode stages aren't too bad because this also performs the | |
1270 * external to internal format translation, which avoids contortions like | |
1271 * writing the XPM back to disk in order to get it processed. | |
1272 */ | |
771 | 1273 { |
2082 | 1274 XpmImage image; |
1275 XpmInfo info; | |
1276 char** data; | |
1277 | |
1278 XpmCreateXpmImageFromBuffer ((char*) dstring, &image, &info); | |
1279 | |
1280 for (i = 0; i < nsymbols; i++) | |
1281 { | |
1282 unsigned j; | |
1283 | |
1284 for (j = 0; j < image.ncolors; j++) | |
1285 { | |
1286 if (image.colorTable[j].symbolic != NULL && | |
2367 | 1287 !qxestrcasecmp_ascii(color_symbols[i].name, image.colorTable[j].symbolic)) |
2082 | 1288 { |
2367 | 1289 image.colorTable[j].c_color = xnew_ascbytes (16); |
2082 | 1290 |
1291 sprintf(image.colorTable[j].c_color, "#%.4x%.4x%.4x", | |
1292 color_symbols[i].color.red, color_symbols[i].color.green, | |
1293 color_symbols[i].color.blue); | |
1294 } | |
1295 } | |
1296 } | |
1297 | |
1298 XpmCreateDataFromXpmImage (&data, &image, &info); | |
1299 | |
1300 pixmap = gdk_pixmap_create_from_xpm_d (window, &mask, NULL, | |
1301 data); | |
771 | 1302 } |
462 | 1303 |
1726 | 1304 if (color_symbols) |
1305 xfree (color_symbols, struct color_symbol *); | |
739 | 1306 |
462 | 1307 if (!pixmap) |
1308 signal_image_error ("Error reading pixmap", data); | |
1309 | |
1310 gdk_window_get_geometry (pixmap, NULL, NULL, &w, &h, &depth); | |
1311 | |
1312 IMAGE_INSTANCE_GTK_PIXMAP (ii) = pixmap; | |
3087 | 1313 IMAGE_INSTANCE_PIXMAP_MASK (ii) = mask; |
462 | 1314 IMAGE_INSTANCE_GTK_COLORMAP (ii) = cmap; |
1315 IMAGE_INSTANCE_GTK_PIXELS (ii) = 0; | |
1316 IMAGE_INSTANCE_GTK_NPIXELS (ii) = 0; | |
1317 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w; | |
1318 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h; | |
1319 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = | |
1320 find_keyword_in_vector (instantiator, Q_file); | |
1321 | |
1322 switch (type) | |
1323 { | |
1324 case IMAGE_MONO_PIXMAP: | |
1325 break; | |
1326 | |
1327 case IMAGE_COLOR_PIXMAP: | |
771 | 1328 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth; |
462 | 1329 break; |
1330 | |
1331 case IMAGE_POINTER: | |
4700
ef70ee47d287
Image instantiator pixmap hotspots are Lisp integers; make it so in GTK.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4629
diff
changeset
|
1332 /* #### Gtk does not give us access to the hotspots of a pixmap */ |
ef70ee47d287
Image instantiator pixmap hotspots are Lisp integers; make it so in GTK.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4629
diff
changeset
|
1333 |
ef70ee47d287
Image instantiator pixmap hotspots are Lisp integers; make it so in GTK.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4629
diff
changeset
|
1334 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = make_int(1); |
ef70ee47d287
Image instantiator pixmap hotspots are Lisp integers; make it so in GTK.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4629
diff
changeset
|
1335 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = make_int(1); |
3087 | 1336 |
4252 | 1337 |
2959 | 1338 image_instance_convert_to_pointer (ii, instantiator, pointer_fg, |
1339 pointer_bg); | |
462 | 1340 break; |
1341 | |
1342 default: | |
2500 | 1343 ABORT (); |
462 | 1344 } |
771 | 1345 |
1346 UNGCPRO; | |
462 | 1347 } |
1348 #endif /* HAVE_XPM */ | |
1349 | |
1350 | |
1351 #ifdef HAVE_XFACE | |
1352 | |
1353 /********************************************************************** | |
1354 * X-Face * | |
1355 **********************************************************************/ | |
1356 #if defined(EXTERN) | |
1357 /* This is about to get redefined! */ | |
1358 #undef EXTERN | |
1359 #endif | |
1360 /* We have to define SYSV32 so that compface.h includes string.h | |
1361 instead of strings.h. */ | |
1362 #define SYSV32 | |
1743 | 1363 BEGIN_C_DECLS |
462 | 1364 #include <compface.h> |
1743 | 1365 END_C_DECLS |
1366 | |
462 | 1367 /* JMP_BUF cannot be used here because if it doesn't get defined |
1368 to jmp_buf we end up with a conflicting type error with the | |
1369 definition in compface.h */ | |
1370 extern jmp_buf comp_env; | |
1371 #undef SYSV32 | |
1372 | |
1373 static void | |
1374 gtk_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
2286 | 1375 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
1376 int dest_mask, Lisp_Object UNUSED (domain)) | |
462 | 1377 { |
1378 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
1379 int i, stattis; | |
1380 char *p, *bits, *bp; | |
771 | 1381 const char * volatile emsg = 0; |
1382 const char * volatile dstring; | |
462 | 1383 |
1384 assert (!NILP (data)); | |
1385 | |
1386 LISP_STRING_TO_EXTERNAL (data, dstring, Qbinary); | |
1387 | |
1388 if ((p = strchr (dstring, ':'))) | |
1389 { | |
1390 dstring = p + 1; | |
1391 } | |
1392 | |
1393 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */ | |
1394 if (!(stattis = setjmp (comp_env))) | |
1395 { | |
1396 UnCompAll ((char *) dstring); | |
1397 UnGenFace (); | |
1398 } | |
1399 | |
1400 switch (stattis) | |
1401 { | |
1402 case -2: | |
1403 emsg = "uncompface: internal error"; | |
1404 break; | |
1405 case -1: | |
1406 emsg = "uncompface: insufficient or invalid data"; | |
1407 break; | |
1408 case 1: | |
1409 emsg = "uncompface: excess data ignored"; | |
1410 break; | |
1411 } | |
1412 | |
1413 if (emsg) | |
563 | 1414 gui_error_2 (emsg, data, Qimage); |
462 | 1415 |
851 | 1416 bp = bits = (char *) ALLOCA (PIXELS / 8); |
462 | 1417 |
1418 /* the compface library exports char F[], which uses a single byte per | |
1419 pixel to represent a 48x48 bitmap. Yuck. */ | |
1420 for (i = 0, p = F; i < (PIXELS / 8); ++i) | |
1421 { | |
1422 int n, b; | |
1423 /* reverse the bit order of each byte... */ | |
1424 for (b = n = 0; b < 8; ++b) | |
1425 { | |
1426 n |= ((*p++) << b); | |
1427 } | |
1428 *bp++ = (char) n; | |
1429 } | |
1430 | |
1431 xbm_instantiate_1 (image_instance, instantiator, pointer_fg, | |
1432 pointer_bg, dest_mask, 48, 48, bits); | |
1433 } | |
1434 | |
1435 #endif /* HAVE_XFACE */ | |
1436 | |
1437 /********************************************************************** | |
1438 * RESOURCES * | |
1439 **********************************************************************/ | |
1440 | |
1441 static void | |
1442 gtk_resource_validate (Lisp_Object instantiator) | |
1443 { | |
4252 | 1444 if ((NILP (find_keyword_in_vector (instantiator, Q_file)) |
462 | 1445 && |
4252 | 1446 NILP (find_keyword_in_vector (instantiator, Q_resource_id))) |
462 | 1447 || |
1448 NILP (find_keyword_in_vector (instantiator, Q_resource_type))) | |
563 | 1449 sferror ("Must supply :file, :resource-id and :resource-type", |
462 | 1450 instantiator); |
1451 } | |
1452 | |
1453 static Lisp_Object | |
563 | 1454 gtk_resource_normalize (Lisp_Object inst, Lisp_Object console_type, |
1455 Lisp_Object dest_mask) | |
462 | 1456 { |
563 | 1457 return shared_resource_normalize (inst, console_type, dest_mask, |
1458 Qgtk_resource); | |
462 | 1459 } |
1460 | |
1461 static int | |
1462 gtk_resource_possible_dest_types (void) | |
1463 { | |
1464 return IMAGE_POINTER_MASK | IMAGE_COLOR_PIXMAP_MASK; | |
1465 } | |
1466 | |
1467 extern guint symbol_to_enum (Lisp_Object, GtkType); | |
1468 | |
2272 | 1469 static guint resource_name_to_resource (Lisp_Object name, |
1470 enum image_instance_type type) | |
462 | 1471 { |
1472 if (type == IMAGE_POINTER) | |
1473 return (symbol_to_enum (name, GTK_TYPE_GDK_CURSOR_TYPE)); | |
1474 else | |
1475 return (0); | |
1476 } | |
1477 | |
2272 | 1478 static enum image_instance_type |
462 | 1479 resource_symbol_to_type (Lisp_Object data) |
1480 { | |
1481 if (EQ (data, Qcursor)) | |
1482 return IMAGE_POINTER; | |
1483 #if 0 | |
1484 else if (EQ (data, Qicon)) | |
1485 return IMAGE_ICON; | |
1486 else if (EQ (data, Qbitmap)) | |
1487 return IMAGE_BITMAP; | |
1488 #endif | |
1489 else | |
2054 | 1490 return IMAGE_UNKNOWN; |
462 | 1491 } |
1492 | |
1493 static void | |
1494 gtk_resource_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
2286 | 1495 Lisp_Object UNUSED (pointer_fg), |
1496 Lisp_Object UNUSED (pointer_bg), | |
1497 int UNUSED (dest_mask), Lisp_Object UNUSED (domain)) | |
462 | 1498 { |
1499 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
1500 GdkCursor *c = NULL; | |
2272 | 1501 enum image_instance_type type; |
462 | 1502 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); |
1503 Lisp_Object resource_type = find_keyword_in_vector (instantiator, Q_resource_type); | |
1504 Lisp_Object resource_id = find_keyword_in_vector (instantiator, Q_resource_id); | |
1505 | |
1506 if (!DEVICE_GTK_P (XDEVICE (device))) | |
563 | 1507 gui_error ("Not a GTK device", device); |
462 | 1508 |
1509 type = resource_symbol_to_type (resource_type); | |
1510 | |
595 | 1511 #if 0 |
1512 if (dest_mask & IMAGE_POINTER_MASK && type == IMAGE_POINTER_MASK) | |
1513 iitype = IMAGE_POINTER; | |
1514 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) | |
1515 iitype = IMAGE_COLOR_PIXMAP; | |
4252 | 1516 else |
595 | 1517 incompatible_image_types (instantiator, dest_mask, |
4252 | 1518 IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK); |
595 | 1519 #endif |
4252 | 1520 |
462 | 1521 /* mess with the keyword info we were provided with */ |
1522 gtk_initialize_pixmap_image_instance (ii, 1, type); | |
2054 | 1523 c = gdk_cursor_new ((GdkCursorType) resource_name_to_resource (resource_id, type)); |
462 | 1524 IMAGE_INSTANCE_GTK_CURSOR (ii) = c; |
1525 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = resource_id; | |
1526 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = 10; | |
1527 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = 10; | |
1528 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1; | |
1529 } | |
1530 | |
1531 static void | |
1532 check_valid_resource_symbol (Lisp_Object data) | |
1533 { | |
1534 CHECK_SYMBOL (data); | |
1535 if (!resource_symbol_to_type (data)) | |
563 | 1536 invalid_constant ("invalid resource type", data); |
462 | 1537 } |
1538 | |
1539 static void | |
1540 check_valid_resource_id (Lisp_Object data) | |
1541 { | |
1542 if (!resource_name_to_resource (data, IMAGE_POINTER) | |
1543 && | |
1544 !resource_name_to_resource (data, IMAGE_COLOR_PIXMAP) | |
1545 #if 0 | |
1546 && | |
1547 !resource_name_to_resource (data, IMAGE_BITMAP) | |
1548 #endif | |
1549 ) | |
563 | 1550 invalid_constant ("invalid resource identifier", data); |
462 | 1551 } |
1552 | |
1553 #if 0 | |
1554 void | |
1555 check_valid_string_or_int (Lisp_Object data) | |
1556 { | |
1557 if (!INTP (data)) | |
1558 CHECK_STRING (data); | |
1559 else | |
1560 CHECK_INT (data); | |
1561 } | |
1562 #endif | |
1563 | |
1564 | |
1565 /********************************************************************** | |
1566 * Autodetect * | |
1567 **********************************************************************/ | |
1568 | |
1569 static void | |
1570 autodetect_validate (Lisp_Object instantiator) | |
1571 { | |
1572 data_must_be_present (instantiator); | |
1573 } | |
1574 | |
1575 static Lisp_Object | |
1576 autodetect_normalize (Lisp_Object instantiator, | |
1577 Lisp_Object console_type, | |
2286 | 1578 Lisp_Object UNUSED (dest_mask)) |
462 | 1579 { |
1580 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data); | |
1581 Lisp_Object filename = Qnil; | |
1582 Lisp_Object data = Qnil; | |
1583 struct gcpro gcpro1, gcpro2, gcpro3; | |
1584 Lisp_Object alist = Qnil; | |
1585 | |
1586 GCPRO3 (filename, data, alist); | |
1587 | |
1588 if (NILP (file)) /* no conversion necessary */ | |
1589 RETURN_UNGCPRO (instantiator); | |
1590 | |
1591 alist = tagged_vector_to_alist (instantiator); | |
1592 | |
1593 filename = locate_pixmap_file (file); | |
1594 if (!NILP (filename)) | |
1595 { | |
1596 int xhot, yhot; | |
1597 /* #### Apparently some versions of XpmReadFileToData, which is | |
1598 called by pixmap_to_lisp_data, don't return an error value | |
1599 if the given file is not a valid XPM file. Instead, they | |
1600 just seg fault. It is definitely caused by passing a | |
1601 bitmap. To try and avoid this we check for bitmaps first. */ | |
1602 | |
1603 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1); | |
1604 | |
1605 if (!EQ (data, Qt)) | |
1606 { | |
1607 alist = remassq_no_quit (Q_data, alist); | |
1608 alist = Fcons (Fcons (Q_file, filename), | |
1609 Fcons (Fcons (Q_data, data), alist)); | |
1610 if (xhot != -1) | |
1611 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)), | |
1612 alist); | |
1613 if (yhot != -1) | |
1614 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)), | |
1615 alist); | |
1616 | |
4252 | 1617 alist = xbm_mask_file_munging (alist, filename, Qt, console_type); |
462 | 1618 |
1619 { | |
1620 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist); | |
1621 free_alist (alist); | |
1622 RETURN_UNGCPRO (result); | |
1623 } | |
1624 } | |
1625 | |
1626 #ifdef HAVE_XPM | |
1627 data = pixmap_to_lisp_data (filename, 1); | |
1628 | |
1629 if (!EQ (data, Qt)) | |
1630 { | |
1631 alist = remassq_no_quit (Q_data, alist); | |
1632 alist = Fcons (Fcons (Q_file, filename), | |
1633 Fcons (Fcons (Q_data, data), alist)); | |
1634 alist = Fcons (Fcons (Q_color_symbols, | |
1635 evaluate_xpm_color_symbols ()), | |
1636 alist); | |
1637 { | |
1638 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist); | |
1639 free_alist (alist); | |
1640 RETURN_UNGCPRO (result); | |
1641 } | |
1642 } | |
1643 #endif | |
1644 } | |
1645 | |
1646 /* If we couldn't convert it, just put it back as it is. | |
1647 We might try to further frob it later as a cursor-font | |
1648 specification. (We can't do that now because we don't know | |
1649 what dest-types it's going to be instantiated into.) */ | |
1650 { | |
1651 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist); | |
1652 free_alist (alist); | |
1653 RETURN_UNGCPRO (result); | |
1654 } | |
1655 } | |
1656 | |
1657 static int | |
1658 autodetect_possible_dest_types (void) | |
1659 { | |
1660 return | |
1661 IMAGE_MONO_PIXMAP_MASK | | |
1662 IMAGE_COLOR_PIXMAP_MASK | | |
1663 IMAGE_POINTER_MASK | | |
1664 IMAGE_TEXT_MASK; | |
1665 } | |
1666 | |
1667 static void | |
1668 autodetect_instantiate (Lisp_Object image_instance, | |
1669 Lisp_Object instantiator, | |
1670 Lisp_Object pointer_fg, | |
1671 Lisp_Object pointer_bg, | |
1672 int dest_mask, Lisp_Object domain) | |
1673 { | |
1674 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
1675 struct gcpro gcpro1, gcpro2, gcpro3; | |
1676 Lisp_Object alist = Qnil; | |
1677 Lisp_Object result = Qnil; | |
1678 int is_cursor_font = 0; | |
1679 | |
1680 GCPRO3 (data, alist, result); | |
1681 | |
1682 alist = tagged_vector_to_alist (instantiator); | |
1683 if (dest_mask & IMAGE_POINTER_MASK) | |
1684 { | |
771 | 1685 const char *name_ext; |
462 | 1686 |
1687 TO_EXTERNAL_FORMAT (LISP_STRING, data, | |
1688 C_STRING_ALLOCA, name_ext, | |
1689 Qfile_name); | |
1690 | |
1691 if (cursor_name_to_index (name_ext) != -1) | |
4252 | 1692 { |
1693 result = alist_to_tagged_vector (Qcursor_font, alist); | |
1694 is_cursor_font = 1; | |
1695 } | |
462 | 1696 } |
1697 | |
1698 if (!is_cursor_font) | |
1699 result = alist_to_tagged_vector (Qstring, alist); | |
1700 free_alist (alist); | |
1701 | |
1702 if (is_cursor_font) | |
1703 cursor_font_instantiate (image_instance, result, pointer_fg, | |
1704 pointer_bg, dest_mask, domain); | |
1705 else | |
1706 string_instantiate (image_instance, result, pointer_fg, | |
1707 pointer_bg, dest_mask, domain); | |
1708 | |
1709 UNGCPRO; | |
1710 } | |
1711 | |
1712 | |
1713 /********************************************************************** | |
1714 * Font * | |
1715 **********************************************************************/ | |
1716 | |
1717 static void | |
1718 font_validate (Lisp_Object instantiator) | |
1719 { | |
1720 data_must_be_present (instantiator); | |
1721 } | |
1722 | |
1723 static int | |
1724 font_possible_dest_types (void) | |
1725 { | |
1726 return IMAGE_POINTER_MASK; | |
1727 } | |
1728 | |
1729 static void | |
1730 font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
1731 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2286 | 1732 int dest_mask, Lisp_Object UNUSED (domain)) |
462 | 1733 { |
1734 /* This function can GC */ | |
1735 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
1736 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
1737 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
1738 GdkColor fg, bg; | |
1739 GdkFont *source, *mask; | |
2421 | 1740 char source_name[PATH_MAX_INTERNAL], mask_name[PATH_MAX_INTERNAL], dummy; |
462 | 1741 int source_char, mask_char; |
1742 int count; | |
1743 Lisp_Object foreground, background; | |
1744 | |
1745 if (!DEVICE_GTK_P (XDEVICE (device))) | |
563 | 1746 gui_error ("Not a Gtk device", device); |
462 | 1747 |
1748 if (!STRINGP (data) || | |
1749 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5)) | |
563 | 1750 invalid_argument ("Invalid font-glyph instantiator", |
462 | 1751 instantiator); |
1752 | |
1753 if (!(dest_mask & IMAGE_POINTER_MASK)) | |
1754 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK); | |
1755 | |
1756 foreground = find_keyword_in_vector (instantiator, Q_foreground); | |
1757 if (NILP (foreground)) | |
1758 foreground = pointer_fg; | |
1759 background = find_keyword_in_vector (instantiator, Q_background); | |
1760 if (NILP (background)) | |
1761 background = pointer_bg; | |
1762 | |
1763 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg); | |
1764 | |
1765 count = sscanf ((char *) XSTRING_DATA (data), | |
1766 "FONT %s %d %s %d %c", | |
1767 source_name, &source_char, | |
1768 mask_name, &mask_char, &dummy); | |
1769 /* Allow "%s %d %d" as well... */ | |
1770 if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy))) | |
1771 count = 4, mask_name[0] = 0; | |
1772 | |
1773 if (count != 2 && count != 4) | |
563 | 1774 syntax_error ("invalid cursor specification", data); |
462 | 1775 source = gdk_font_load (source_name); |
1776 if (! source) | |
563 | 1777 gui_error_2 ("couldn't load font", |
462 | 1778 build_string (source_name), |
1779 data); | |
1780 if (count == 2) | |
1781 mask = 0; | |
1782 else if (!mask_name[0]) | |
1783 mask = source; | |
1784 else | |
1785 { | |
1786 mask = gdk_font_load (mask_name); | |
1787 if (!mask) | |
1788 /* continuable */ | |
771 | 1789 Fsignal (Qgui_error, list3 (build_msg_string ("couldn't load font"), |
563 | 1790 build_string (mask_name), data)); |
462 | 1791 } |
1792 if (!mask) | |
1793 mask_char = 0; | |
1794 | |
1795 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */ | |
1796 | |
1797 gtk_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER); | |
1798 | |
1799 IMAGE_INSTANCE_GTK_CURSOR (ii) = NULL; | |
1800 | |
1801 #if 0 | |
1802 /* #### BILL!!! There is no way to call this function from Gdk */ | |
1803 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char, | |
1804 &fg, &bg); | |
1805 #endif | |
1806 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground; | |
1807 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background; | |
1808 | |
1809 gdk_font_unref (source); | |
1810 if (mask && mask != source) gdk_font_unref (mask); | |
1811 } | |
1812 | |
1813 | |
1814 /********************************************************************** | |
1815 * Cursor-Font * | |
1816 **********************************************************************/ | |
1817 | |
1818 static void | |
1819 cursor_font_validate (Lisp_Object instantiator) | |
1820 { | |
1821 data_must_be_present (instantiator); | |
1822 } | |
1823 | |
1824 static int | |
1825 cursor_font_possible_dest_types (void) | |
1826 { | |
1827 return IMAGE_POINTER_MASK; | |
1828 } | |
1829 | |
1830 static char *__downcase (const char *name) | |
1831 { | |
1832 char *converted = strdup(name); | |
1833 char *work = converted; | |
1834 | |
1835 while (*work) | |
1836 { | |
1837 *work = tolower(*work); | |
1838 work++; | |
1839 } | |
1840 return(converted); | |
1841 } | |
1842 | |
1843 /* This is basically the equivalent of XmuCursorNameToIndex */ | |
2054 | 1844 static GdkCursorType |
462 | 1845 cursor_name_to_index (const char *name) |
1846 { | |
1847 int i; | |
1848 static char *the_gdk_cursors[GDK_NUM_GLYPHS]; | |
1849 | |
1850 if (!the_gdk_cursors[GDK_BASED_ARROW_UP]) | |
1851 { | |
1852 /* Need to initialize the array */ | |
1853 /* Supposedly since this array is static it should be | |
4252 | 1854 initialized to NULLs for us, but I'm very paranoid. */ |
462 | 1855 for (i = 0; i < GDK_NUM_GLYPHS; i++) |
1856 { | |
1857 the_gdk_cursors[i] = NULL; | |
1858 } | |
1859 | |
1860 #define FROB_CURSOR(x) the_gdk_cursors[GDK_##x] = __downcase(#x) | |
1861 FROB_CURSOR(ARROW); FROB_CURSOR(BASED_ARROW_DOWN); | |
1862 FROB_CURSOR(BASED_ARROW_UP); FROB_CURSOR(BOAT); | |
1863 FROB_CURSOR(BOGOSITY); FROB_CURSOR(BOTTOM_LEFT_CORNER); | |
1864 FROB_CURSOR(BOTTOM_RIGHT_CORNER); FROB_CURSOR(BOTTOM_SIDE); | |
1865 FROB_CURSOR(BOTTOM_TEE); FROB_CURSOR(BOX_SPIRAL); | |
1866 FROB_CURSOR(CENTER_PTR); FROB_CURSOR(CIRCLE); | |
1867 FROB_CURSOR(CLOCK); FROB_CURSOR(COFFEE_MUG); | |
1868 FROB_CURSOR(CROSS); FROB_CURSOR(CROSS_REVERSE); | |
1869 FROB_CURSOR(CROSSHAIR); FROB_CURSOR(DIAMOND_CROSS); | |
1870 FROB_CURSOR(DOT); FROB_CURSOR(DOTBOX); | |
1871 FROB_CURSOR(DOUBLE_ARROW); FROB_CURSOR(DRAFT_LARGE); | |
1872 FROB_CURSOR(DRAFT_SMALL); FROB_CURSOR(DRAPED_BOX); | |
1873 FROB_CURSOR(EXCHANGE); FROB_CURSOR(FLEUR); | |
1874 FROB_CURSOR(GOBBLER); FROB_CURSOR(GUMBY); | |
1875 FROB_CURSOR(HAND1); FROB_CURSOR(HAND2); | |
1876 FROB_CURSOR(HEART); FROB_CURSOR(ICON); | |
1877 FROB_CURSOR(IRON_CROSS); FROB_CURSOR(LEFT_PTR); | |
1878 FROB_CURSOR(LEFT_SIDE); FROB_CURSOR(LEFT_TEE); | |
1879 FROB_CURSOR(LEFTBUTTON); FROB_CURSOR(LL_ANGLE); | |
1880 FROB_CURSOR(LR_ANGLE); FROB_CURSOR(MAN); | |
1881 FROB_CURSOR(MIDDLEBUTTON); FROB_CURSOR(MOUSE); | |
1882 FROB_CURSOR(PENCIL); FROB_CURSOR(PIRATE); | |
1883 FROB_CURSOR(PLUS); FROB_CURSOR(QUESTION_ARROW); | |
1884 FROB_CURSOR(RIGHT_PTR); FROB_CURSOR(RIGHT_SIDE); | |
1885 FROB_CURSOR(RIGHT_TEE); FROB_CURSOR(RIGHTBUTTON); | |
1886 FROB_CURSOR(RTL_LOGO); FROB_CURSOR(SAILBOAT); | |
1887 FROB_CURSOR(SB_DOWN_ARROW); FROB_CURSOR(SB_H_DOUBLE_ARROW); | |
1888 FROB_CURSOR(SB_LEFT_ARROW); FROB_CURSOR(SB_RIGHT_ARROW); | |
1889 FROB_CURSOR(SB_UP_ARROW); FROB_CURSOR(SB_V_DOUBLE_ARROW); | |
1890 FROB_CURSOR(SHUTTLE); FROB_CURSOR(SIZING); | |
1891 FROB_CURSOR(SPIDER); FROB_CURSOR(SPRAYCAN); | |
1892 FROB_CURSOR(STAR); FROB_CURSOR(TARGET); | |
1893 FROB_CURSOR(TCROSS); FROB_CURSOR(TOP_LEFT_ARROW); | |
1894 FROB_CURSOR(TOP_LEFT_CORNER); FROB_CURSOR(TOP_RIGHT_CORNER); | |
1895 FROB_CURSOR(TOP_SIDE); FROB_CURSOR(TOP_TEE); | |
1896 FROB_CURSOR(TREK); FROB_CURSOR(UL_ANGLE); | |
1897 FROB_CURSOR(UMBRELLA); FROB_CURSOR(UR_ANGLE); | |
1898 FROB_CURSOR(WATCH); FROB_CURSOR(XTERM); | |
1899 FROB_CURSOR(X_CURSOR); | |
1900 #undef FROB_CURSOR | |
1901 } | |
1902 | |
1903 for (i = 0; i < GDK_NUM_GLYPHS; i++) | |
1904 { | |
1905 if (!the_gdk_cursors[i]) continue; | |
1906 if (!strcmp (the_gdk_cursors[i], name)) | |
1907 { | |
2054 | 1908 return (GdkCursorType) i; |
462 | 1909 } |
1910 } | |
2054 | 1911 return (GdkCursorType) -1; |
462 | 1912 } |
1913 | |
1914 static void | |
1915 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
1916 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2286 | 1917 int dest_mask, Lisp_Object UNUSED (domain)) |
462 | 1918 { |
1919 /* This function can GC */ | |
1920 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
1921 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
1922 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
2054 | 1923 GdkCursorType i; |
771 | 1924 const char *name_ext; |
462 | 1925 Lisp_Object foreground, background; |
1926 | |
1927 if (!DEVICE_GTK_P (XDEVICE (device))) | |
563 | 1928 gui_error ("Not a Gtk device", device); |
462 | 1929 |
1930 if (!(dest_mask & IMAGE_POINTER_MASK)) | |
1931 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK); | |
1932 | |
1933 TO_EXTERNAL_FORMAT (LISP_STRING, data, | |
1934 C_STRING_ALLOCA, name_ext, | |
1935 Qfile_name); | |
1936 | |
1937 if ((i = cursor_name_to_index (name_ext)) == -1) | |
563 | 1938 invalid_argument ("Unrecognized cursor-font name", data); |
462 | 1939 |
1940 gtk_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER); | |
1941 IMAGE_INSTANCE_GTK_CURSOR (ii) = gdk_cursor_new (i); | |
1942 foreground = find_keyword_in_vector (instantiator, Q_foreground); | |
1943 if (NILP (foreground)) | |
1944 foreground = pointer_fg; | |
1945 background = find_keyword_in_vector (instantiator, Q_background); | |
1946 if (NILP (background)) | |
1947 background = pointer_bg; | |
1948 maybe_recolor_cursor (image_instance, foreground, background); | |
1949 } | |
1950 | |
1951 static int | |
1952 gtk_colorize_image_instance (Lisp_Object image_instance, | |
1953 Lisp_Object foreground, Lisp_Object background); | |
1954 | |
1955 | |
1956 /************************************************************************/ | |
1957 /* subwindow and widget support */ | |
1958 /************************************************************************/ | |
1959 | |
1960 /* unmap the image if it is a widget. This is used by redisplay via | |
1961 redisplay_unmap_subwindows */ | |
1962 static void | |
1963 gtk_unmap_subwindow (Lisp_Image_Instance *p) | |
1964 { | |
1965 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) | |
1966 { | |
1967 /* We don't support subwindows, but we do support widgets... */ | |
2500 | 1968 ABORT (); |
462 | 1969 } |
1970 else /* must be a widget */ | |
1971 { | |
1972 /* Since we are being unmapped we want the enclosing frame to | |
1973 get focus. The losing with simple scrolling but is the safest | |
1974 thing to do. */ | |
1975 if (IMAGE_INSTANCE_GTK_CLIPWIDGET (p)) | |
1976 gtk_widget_unmap (IMAGE_INSTANCE_GTK_CLIPWIDGET (p)); | |
1977 } | |
1978 } | |
1979 | |
1980 /* map the subwindow. This is used by redisplay via | |
1981 redisplay_output_subwindow */ | |
1982 static void | |
1983 gtk_map_subwindow (Lisp_Image_Instance *p, int x, int y, | |
691 | 1984 struct display_glyph_area* dga) |
462 | 1985 { |
1986 assert (dga->width > 0 && dga->height > 0); | |
1987 | |
1988 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) | |
1989 { | |
1990 /* No subwindow support... */ | |
2500 | 1991 ABORT (); |
462 | 1992 } |
1993 else /* must be a widget */ | |
1994 { | |
1995 struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p)); | |
1996 GtkWidget *wid = IMAGE_INSTANCE_GTK_CLIPWIDGET (p); | |
1997 GtkAllocation a; | |
2168 | 1998 int moving; |
462 | 1999 |
2000 if (!wid) return; | |
2001 | |
2002 a.x = x + IMAGE_INSTANCE_GTK_WIDGET_XOFFSET (p); | |
2003 a.y = y + IMAGE_INSTANCE_GTK_WIDGET_YOFFSET (p); | |
2004 a.width = dga->width; | |
2005 a.height = dga->height; | |
2006 | |
2168 | 2007 /* Is the widget cganging position? */ |
2008 moving = (a.x != wid->allocation.x) || | |
2009 (a.y != wid->allocation.y); | |
2010 | |
462 | 2011 if ((a.width != wid->allocation.width) || |
2168 | 2012 (a.height != wid->allocation.height) || |
2013 moving) | |
462 | 2014 { |
2015 gtk_widget_size_allocate (IMAGE_INSTANCE_GTK_CLIPWIDGET (p), &a); | |
2016 } | |
2017 | |
2168 | 2018 if (moving) |
462 | 2019 { |
2020 guint32 old_flags = GTK_WIDGET_FLAGS (FRAME_GTK_TEXT_WIDGET (f)); | |
2021 | |
2168 | 2022 /* GtkFixed widget queues a resize when you add a widget. |
462 | 2023 ** But only if it is visible. |
2024 ** losers. | |
2025 */ | |
2026 GTK_WIDGET_FLAGS(FRAME_GTK_TEXT_WIDGET (f)) &= ~GTK_VISIBLE; | |
2168 | 2027 |
462 | 2028 if (IMAGE_INSTANCE_GTK_ALREADY_PUT(p)) |
2029 { | |
2030 gtk_fixed_move (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)), | |
2031 wid, | |
2168 | 2032 a.x, a.y); |
462 | 2033 } |
2034 else | |
2035 { | |
2036 IMAGE_INSTANCE_GTK_ALREADY_PUT(p) = TRUE; | |
2037 gtk_fixed_put (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)), | |
2038 wid, | |
2168 | 2039 a.x, a.y); |
462 | 2040 } |
2168 | 2041 |
462 | 2042 GTK_WIDGET_FLAGS(FRAME_GTK_TEXT_WIDGET (f)) = old_flags; |
2043 } | |
691 | 2044 else |
2045 { | |
2046 if (IMAGE_INSTANCE_GTK_ALREADY_PUT(p)) | |
2047 { | |
2048 /* Do nothing... */ | |
2049 } | |
2050 else | |
2051 { | |
2052 /* Must make sure we have put the image at least once! */ | |
2053 IMAGE_INSTANCE_GTK_ALREADY_PUT(p) = TRUE; | |
2054 gtk_fixed_put (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)), | |
2055 wid, | |
2168 | 2056 a.x, a.y); |
691 | 2057 } |
2058 } | |
462 | 2059 |
2060 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p)) | |
2061 { | |
2062 gtk_widget_map (wid); | |
2063 } | |
2064 | |
2065 gtk_widget_draw (wid, NULL); | |
2066 } | |
2067 } | |
2068 | |
2069 /* when you click on a widget you may activate another widget this | |
2070 needs to be checked and all appropriate widgets updated */ | |
2071 static void | |
2072 gtk_redisplay_subwindow (Lisp_Image_Instance *p) | |
2073 { | |
2074 /* Update the subwindow size if necessary. */ | |
2075 if (IMAGE_INSTANCE_SIZE_CHANGED (p)) | |
2076 { | |
2077 #if 0 | |
2078 XResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), | |
2079 IMAGE_INSTANCE_X_SUBWINDOW_ID (p), | |
2080 IMAGE_INSTANCE_WIDTH (p), | |
2081 IMAGE_INSTANCE_HEIGHT (p)); | |
2082 #endif | |
2083 } | |
2084 } | |
2085 | |
2086 /* Update all attributes that have changed. */ | |
2087 static void | |
2088 gtk_redisplay_widget (Lisp_Image_Instance *p) | |
2089 { | |
2090 /* This function can GC if IN_REDISPLAY is false. */ | |
2091 | |
2092 if (!IMAGE_INSTANCE_GTK_CLIPWIDGET (p)) | |
2093 return; | |
2094 | |
2095 #ifdef HAVE_WIDGETS | |
2096 /* First get the items if they have changed since this is a | |
2097 structural change. As such it will nuke all added values so we | |
2098 need to update most other things after the items have changed.*/ | |
2099 gtk_widget_show_all (IMAGE_INSTANCE_GTK_CLIPWIDGET (p)); | |
2100 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)) | |
2101 { | |
2102 /* Need to update GtkArgs that might have changed... */ | |
2103 /* #### FIXME!!! */ | |
2054 | 2104 /*Lisp_Object image_instance = wrap_image_instance (p); */ |
462 | 2105 } |
2106 else | |
2107 { | |
2108 /* #### FIXME!!! */ | |
2109 /* No items changed, so do nothing, right? */ | |
2110 } | |
2111 | |
2112 /* Possibly update the colors and font */ | |
2113 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p) | |
2114 || | |
2115 /* #### This is not sufficient because it will not cope with widgets | |
2116 that are not currently visible. Once redisplay has done the | |
2117 visible ones it will clear this flag so that when new ones | |
2118 become visible they will not be updated. */ | |
2119 XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed | |
2120 || | |
2121 XFRAME (IMAGE_INSTANCE_FRAME (p))->frame_changed | |
2122 || | |
2123 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)) | |
2124 { | |
2125 /* #### Write this function BILL! */ | |
2126 update_widget_face (NULL, p, IMAGE_INSTANCE_FRAME (p)); | |
2127 } | |
2128 | |
2129 /* Possibly update the text. */ | |
2130 if (IMAGE_INSTANCE_TEXT_CHANGED (p)) | |
2131 { | |
2132 char* str; | |
2133 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p); | |
2134 LISP_STRING_TO_EXTERNAL (val, str, Qnative); | |
2135 | |
2136 /* #### Need to special case each type of GtkWidget here! */ | |
2137 } | |
2138 | |
2139 /* Possibly update the size. */ | |
2140 if (IMAGE_INSTANCE_SIZE_CHANGED (p) | |
2141 || | |
2142 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p) | |
2143 || | |
2144 IMAGE_INSTANCE_TEXT_CHANGED (p)) | |
2145 { | |
2168 | 2146 GtkRequisition r; |
2147 GtkAllocation a = IMAGE_INSTANCE_GTK_CLIPWIDGET (p)->allocation; | |
2148 | |
462 | 2149 assert (IMAGE_INSTANCE_GTK_WIDGET_ID (p) && |
2150 IMAGE_INSTANCE_GTK_CLIPWIDGET (p)) ; | |
2151 | |
2168 | 2152 a.width = r.width = IMAGE_INSTANCE_WIDTH (p); |
2153 a.height = r.height = IMAGE_INSTANCE_HEIGHT (p); | |
2154 | |
2155 /* Force the widget's preferred and actual size to what we say it shall | |
2156 be. */ | |
2157 gtk_widget_size_request (IMAGE_INSTANCE_GTK_CLIPWIDGET (p), &r); | |
2158 gtk_widget_size_allocate (IMAGE_INSTANCE_GTK_CLIPWIDGET (p), &a); | |
462 | 2159 } |
2160 | |
2161 /* Adjust offsets within the frame. */ | |
2162 if (XFRAME (IMAGE_INSTANCE_FRAME (p))->size_changed) | |
2163 { | |
2164 /* I don't think we need to do anything for Gtk here... */ | |
2165 } | |
2166 | |
2167 /* now modify the widget */ | |
2168 #endif | |
2169 } | |
2170 | |
2171 /* instantiate and gtk type subwindow */ | |
2172 static void | |
2286 | 2173 gtk_subwindow_instantiate (Lisp_Object image_instance, |
2174 Lisp_Object UNUSED (instantiator), | |
2175 Lisp_Object UNUSED (pointer_fg), | |
2176 Lisp_Object UNUSED (pointer_bg), | |
2177 int UNUSED (dest_mask), Lisp_Object UNUSED (domain)) | |
462 | 2178 { |
2179 /* This function can GC */ | |
2180 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
2181 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
2182 | |
2183 if (!DEVICE_GTK_P (XDEVICE (device))) | |
563 | 2184 gui_error ("Not a GTK device", device); |
462 | 2185 |
2186 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW; | |
2187 | |
2188 ii->data = xnew_and_zero (struct gtk_subwindow_data); | |
2189 | |
2190 /* Create a window for clipping */ | |
2191 IMAGE_INSTANCE_GTK_CLIPWINDOW (ii) = NULL; | |
2192 | |
2193 /* Now put the subwindow inside the clip window. */ | |
2194 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void *) NULL; | |
2195 } | |
2196 | |
2197 #ifdef HAVE_WIDGETS | |
2198 | |
2199 /************************************************************************/ | |
2200 /* widgets */ | |
2201 /************************************************************************/ | |
2202 static void | |
2203 update_widget_face (GtkWidget *w, Lisp_Image_Instance *ii, | |
2204 Lisp_Object domain) | |
2205 { | |
2206 if (0) | |
2207 { | |
2208 GtkStyle *style = gtk_widget_get_style (w); | |
2209 Lisp_Object pixel = Qnil; | |
2210 GdkColor *fcolor, *bcolor; | |
2211 | |
2212 style = gtk_style_copy (style); | |
4252 | 2213 |
462 | 2214 /* Update the foreground. */ |
2215 pixel = FACE_FOREGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii), domain); | |
2216 fcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (pixel)); | |
2217 | |
2218 /* Update the background. */ | |
2219 pixel = FACE_BACKGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii), domain); | |
2220 bcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (pixel)); | |
2221 | |
2222 /* Update the font */ | |
2223 /* #### FIXME!!! Need to copy the widgets style, dick with it, and | |
2224 ** set the widgets style to the new style... | |
2225 */ | |
2226 gtk_widget_set_style (w, style); | |
2227 | |
2228 /* #### Megahack - but its just getting too complicated to do this | |
2229 in the right place. */ | |
2230 #if 0 | |
2231 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qtab_control)) | |
2232 update_tab_widget_face (wv, ii, domain); | |
2233 #endif | |
2234 } | |
2235 } | |
2236 | |
2237 #if 0 | |
2238 static void | |
2239 update_tab_widget_face (GtkWidget *w, Lisp_Image_Instance *ii, | |
2240 Lisp_Object domain) | |
2241 { | |
2242 if (wv->contents) | |
2243 { | |
2244 widget_value* val = wv->contents, *cur; | |
2245 | |
2246 /* Give each child label the correct foreground color. */ | |
2247 Lisp_Object pixel = FACE_FOREGROUND | |
2248 (IMAGE_INSTANCE_WIDGET_FACE (ii), | |
2249 domain); | |
2250 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)); | |
2251 lw_add_widget_value_arg (val, XtNtabForeground, fcolor.pixel); | |
2252 wv->change = VISIBLE_CHANGE; | |
2253 val->change = VISIBLE_CHANGE; | |
2254 | |
2255 for (cur = val->next; cur; cur = cur->next) | |
2256 { | |
2257 cur->change = VISIBLE_CHANGE; | |
2258 if (cur->value) | |
2259 { | |
2260 lw_copy_widget_value_args (val, cur); | |
2261 } | |
2262 } | |
2263 } | |
2264 } | |
2265 #endif | |
2266 | |
2267 static Lisp_Object | |
2268 gtk_widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, | |
2269 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2270 Lisp_Object domain) | |
2271 { | |
2272 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
2273 Lisp_Object widget = Qnil; | |
2274 char *nm = NULL; | |
2275 GtkWidget *w = NULL; | |
2276 struct gcpro gcpro1; | |
2277 | |
2278 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET; | |
2279 | |
2280 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) | |
2281 { | |
2282 LISP_STRING_TO_EXTERNAL (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm, Qnative); | |
2283 } | |
2284 | |
2285 ii->data = xnew_and_zero (struct gtk_subwindow_data); | |
2286 | |
2287 /* Create a clipping widget */ | |
2288 IMAGE_INSTANCE_GTK_CLIPWIDGET (ii) = NULL; | |
2289 IMAGE_INSTANCE_GTK_ALREADY_PUT(ii) = FALSE; | |
2290 | |
2291 /* Create the actual widget */ | |
2292 GCPRO1 (widget); | |
2293 widget = call5 (Qgtk_widget_instantiate_internal, | |
2294 image_instance, instantiator, | |
2295 pointer_fg, pointer_bg, | |
2296 domain); | |
2297 | |
2298 if (!NILP (widget)) | |
2299 { | |
2300 CHECK_GTK_OBJECT (widget); | |
2301 w = GTK_WIDGET (XGTK_OBJECT (widget)->object); | |
2302 } | |
2303 else | |
2304 { | |
2305 stderr_out ("Lisp-level creation of widget failed... falling back\n"); | |
2306 w = gtk_label_new ("Widget Creation Failed..."); | |
2307 } | |
2308 | |
2309 UNGCPRO; | |
2310 | |
2311 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void *) w; | |
2312 | |
2313 /* #### HACK!!!! We should make this do the right thing if we | |
2314 ** really need a clip widget! | |
2315 */ | |
2316 IMAGE_INSTANCE_GTK_CLIPWIDGET (ii) = w; | |
2317 | |
2168 | 2318 /* The current theme may produce a widget of a different size that what we |
2319 expect so force reconsideration of the widget's size. */ | |
2320 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1; | |
2321 | |
462 | 2322 return (Qt); |
2323 } | |
2324 | |
2325 static void | |
2326 gtk_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
2327 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2286 | 2328 int UNUSED (dest_mask), Lisp_Object domain) |
462 | 2329 { |
2330 call_with_suspended_errors ((lisp_fn_t) gtk_widget_instantiate_1, | |
2331 Qnil, Qimage, | |
2332 ERROR_ME_WARN, 5, | |
2333 image_instance, instantiator, | |
2334 pointer_fg, | |
2335 pointer_bg, | |
2336 domain); | |
2337 } | |
2338 | |
2339 /* get properties of a control */ | |
2340 static Lisp_Object | |
2286 | 2341 gtk_widget_property (Lisp_Object UNUSED (image_instance), Lisp_Object prop) |
462 | 2342 { |
2343 /* Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); */ | |
2344 | |
2345 /* get the text from a control */ | |
2346 if (EQ (prop, Q_text)) | |
2347 { | |
2348 return Qnil; | |
2349 } | |
2350 return Qunbound; | |
2351 } | |
2352 | |
2353 #define FAKE_GTK_WIDGET_INSTANTIATOR(x) \ | |
2354 static void \ | |
2355 gtk_##x##_instantiate (Lisp_Object image_instance, \ | |
2356 Lisp_Object instantiator, \ | |
2357 Lisp_Object pointer_fg, \ | |
2358 Lisp_Object pointer_bg, \ | |
2359 int dest_mask, Lisp_Object domain) \ | |
2360 { \ | |
2361 gtk_widget_instantiate (image_instance, instantiator, pointer_fg, \ | |
2362 pointer_bg, dest_mask, domain); \ | |
2363 } | |
2364 | |
2365 FAKE_GTK_WIDGET_INSTANTIATOR(native_layout); | |
2366 FAKE_GTK_WIDGET_INSTANTIATOR(button); | |
2367 FAKE_GTK_WIDGET_INSTANTIATOR(progress_gauge); | |
2368 FAKE_GTK_WIDGET_INSTANTIATOR(edit_field); | |
2369 FAKE_GTK_WIDGET_INSTANTIATOR(combo_box); | |
2370 FAKE_GTK_WIDGET_INSTANTIATOR(label); | |
2168 | 2371 /* Note: tab_control has a custom instantiator (see below) */ |
2372 | |
2373 /* | |
2374 Ask the widget to return it's preferred size. This device method must | |
2375 defined for all widgets that also have format specific version of | |
2376 query_geometry defined in glyphs-widget.c. This is because those format | |
2377 specific versions return sizes that are appropriate for the X widgets. For | |
2378 GTK, the size of a widget can change at runtime due to the user changing | |
2379 their theme. | |
2380 | |
2381 This method can be called before the widget is instantiated. This is | |
2382 because instantiate_image_instantiator() is tying to be helpful to other | |
2383 toolkits and supply sane geometry values to them. This is not appropriate | |
2384 for GTK and can be ignored. | |
2385 | |
2386 This method can be used by all widgets. | |
2387 */ | |
2388 static void | |
2389 gtk_widget_query_geometry (Lisp_Object image_instance, | |
2390 int* width, int* height, | |
2286 | 2391 enum image_instance_geometry UNUSED (disp), |
2392 Lisp_Object UNUSED (domain)) | |
2168 | 2393 { |
2394 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); | |
2395 | |
2396 if (p->data != NULL) | |
2397 { | |
2398 GtkWidget *w = IMAGE_INSTANCE_GTK_CLIPWIDGET (p); | |
2399 GtkRequisition r; | |
2400 | |
2401 gtk_widget_size_request(w, &r); | |
2402 *height= r.height; | |
2403 *width = r.width; | |
2404 } | |
2405 } | |
2406 | |
2407 | |
2408 /* Button functions. */ | |
462 | 2409 |
2410 /* Update a button's clicked state. */ | |
2411 static void | |
2412 gtk_button_redisplay (Lisp_Object image_instance) | |
2413 { | |
2414 /* This function can GC if IN_REDISPLAY is false. */ | |
2415 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); | |
2416 GtkWidget *w = IMAGE_INSTANCE_GTK_CLIPWIDGET (p); | |
2417 | |
2418 if (GTK_WIDGET_TYPE (w) == gtk_button_get_type ()) | |
2419 { | |
2420 } | |
2421 else if (GTK_WIDGET_TYPE (w) == gtk_check_button_get_type ()) | |
2422 { | |
2423 } | |
2424 else if (GTK_WIDGET_TYPE (w) == gtk_radio_button_get_type ()) | |
2425 { | |
2426 } | |
2427 else | |
2428 { | |
2429 /* Unknown button type... */ | |
2500 | 2430 ABORT(); |
462 | 2431 } |
2432 } | |
2433 | |
2434 /* get properties of a button */ | |
2435 static Lisp_Object | |
2436 gtk_button_property (Lisp_Object image_instance, Lisp_Object prop) | |
2437 { | |
2438 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
2439 | |
2440 /* check the state of a button */ | |
2441 if (EQ (prop, Q_selected)) | |
2442 { | |
2443 if (GTK_WIDGET_HAS_FOCUS (IMAGE_INSTANCE_SUBWINDOW_ID (ii))) | |
2444 return Qt; | |
2445 else | |
2446 return Qnil; | |
2447 } | |
2448 return Qunbound; | |
2449 } | |
2450 | |
2168 | 2451 |
2452 /* Progress gauge functions. */ | |
2453 | |
462 | 2454 /* set the properties of a progress gauge */ |
2455 static void | |
2456 gtk_progress_gauge_redisplay (Lisp_Object image_instance) | |
2457 { | |
2458 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
2459 | |
2460 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)) | |
2461 { | |
2462 gfloat f; | |
2463 Lisp_Object val; | |
2464 | |
2465 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value; | |
2466 f = XFLOATINT (val); | |
2467 | |
2468 gtk_progress_set_value (GTK_PROGRESS (IMAGE_INSTANCE_SUBWINDOW_ID (ii)), | |
2469 f); | |
2470 } | |
2471 } | |
2472 | |
2168 | 2473 |
2474 /* Tab Control functions. */ | |
2475 | |
2476 /* | |
2477 Register a widget's callbacks with the frame's hashtable. The hashtable is | |
2478 weak so deregistration is handled automatically. Tab controls have per-tab | |
2479 callback list functions and the GTK callback architecture is not | |
2480 sufficiently flexible to deal with this. Instead, the functions are | |
2481 registered here and the id is passed through the callback loop. | |
2482 */ | |
2483 static int | |
2484 gtk_register_gui_item (Lisp_Object image_instance, Lisp_Object gui, | |
2485 Lisp_Object domain) | |
2486 { | |
2487 struct frame *f = XFRAME(DOMAIN_FRAME(domain)); | |
2488 int id = gui_item_id_hash(FRAME_GTK_WIDGET_CALLBACK_HASH_TABLE(f), | |
2489 gui, WIDGET_GLYPH_SLOT); | |
2490 | |
2491 Fputhash(make_int(id), image_instance, | |
2492 FRAME_GTK_WIDGET_INSTANCE_HASH_TABLE (f)); | |
2493 Fputhash(make_int(id), XGUI_ITEM (gui)->callback, | |
2494 FRAME_GTK_WIDGET_CALLBACK_HASH_TABLE (f)); | |
2495 Fputhash(make_int(id), XGUI_ITEM (gui)->callback_ex, | |
2496 FRAME_GTK_WIDGET_CALLBACK_EX_HASH_TABLE (f)); | |
2497 return id; | |
2498 } | |
2499 | |
2500 /* | |
2501 Append the given item as a tab to the notebook. Callbacks, etc are all | |
2502 setup. | |
2503 */ | |
2504 static void | |
2505 gtk_add_tab_item(Lisp_Object image_instance, | |
2506 GtkNotebook* nb, Lisp_Object item, | |
2286 | 2507 Lisp_Object domain, int UNUSED (i)) |
2168 | 2508 { |
2509 Lisp_Object name; | |
2510 int hash_id = 0; | |
2511 char *c_name = NULL; | |
2512 GtkWidget* box; | |
2513 | |
2514 if (GUI_ITEMP (item)) | |
2515 { | |
2516 Lisp_Gui_Item *pgui = XGUI_ITEM (item); | |
2517 | |
2518 if (!STRINGP (pgui->name)) | |
2519 pgui->name = eval_within_redisplay (pgui->name); | |
2520 | |
2521 if (!STRINGP (pgui->name)) { | |
2522 warn_when_safe (Qredisplay, Qwarning, | |
2523 "Name does not evaluate to string"); | |
2524 | |
2525 return; | |
2526 } | |
2527 | |
2528 hash_id = gtk_register_gui_item (image_instance, item, domain); | |
2529 name = pgui->name; | |
2530 } | |
2531 else | |
2532 { | |
2533 CHECK_STRING (item); | |
2534 name = item; | |
2535 } | |
2536 | |
2537 TO_EXTERNAL_FORMAT (LISP_STRING, name, | |
2538 C_STRING_ALLOCA, c_name, | |
2539 Qctext); | |
2540 | |
2541 /* Dummy widget that the notbook wants to display when a tab is selected. */ | |
2542 box = gtk_vbox_new (FALSE, 3); | |
2543 | |
2544 /* | |
2545 Store the per-tab callback data id in the tab. The callback functions | |
2546 themselves could have been stored in the widget but this avoids having to | |
2547 worry about the garbage collector running between here and the callback | |
2548 function. | |
2549 */ | |
2550 gtk_object_set_data(GTK_OBJECT(box), GTK_DATA_TAB_HASHCODE_IDENTIFIER, | |
2551 (gpointer) hash_id); | |
2552 | |
2553 gtk_notebook_append_page (nb, box, gtk_label_new (c_name)); | |
2554 } | |
2555 | |
2556 /* Signal handler for the switch-page signal. */ | |
2557 static void gtk_tab_control_callback(GtkNotebook *notebook, | |
2558 GtkNotebookPage *page, | |
2286 | 2559 gint UNUSED (page_num), |
2560 gpointer UNUSED (user_data)) | |
2168 | 2561 { |
2562 /* | |
2563 This callback is called for every selection, not just user selection. | |
2564 We're only interested in user selection, which occurs outside of | |
2565 redisplay. | |
2566 */ | |
2567 | |
2568 if (!in_display) | |
2569 { | |
2570 Lisp_Object image_instance, callback, callback_ex; | |
2571 Lisp_Object frame, event; | |
2572 int update_subwindows_p = 0; | |
2573 struct frame *f = gtk_widget_to_frame(GTK_WIDGET(notebook)); | |
2574 int id; | |
2575 | |
2576 if (!f) | |
2577 return; | |
2578 frame = wrap_frame (f); | |
2579 | |
2580 id = (int) gtk_object_get_data(GTK_OBJECT(page->child), | |
2581 GTK_DATA_TAB_HASHCODE_IDENTIFIER); | |
2582 image_instance = Fgethash(make_int_verify(id), | |
2583 FRAME_GTK_WIDGET_INSTANCE_HASH_TABLE(f), Qnil); | |
2584 callback = Fgethash(make_int(id), | |
2585 FRAME_GTK_WIDGET_CALLBACK_HASH_TABLE(f), Qnil); | |
2586 callback_ex = Fgethash(make_int(id), | |
2587 FRAME_GTK_WIDGET_CALLBACK_EX_HASH_TABLE(f), Qnil); | |
2588 update_subwindows_p = 1; | |
2589 | |
2590 /* It is possible for a widget action to cause it to get out of | |
2591 sync with its instantiator. Thus it is necessary to signal | |
2592 this possibility. */ | |
2593 if (IMAGE_INSTANCEP (image_instance)) | |
2594 XIMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (image_instance) = 1; | |
4252 | 2595 |
2168 | 2596 if (!NILP (callback_ex) && !UNBOUNDP (callback_ex)) |
2597 { | |
2598 event = Fmake_event (Qnil, Qnil); | |
2599 | |
2600 XSET_EVENT_TYPE (event, misc_user_event); | |
2601 XSET_EVENT_CHANNEL (event, frame); | |
2602 XSET_EVENT_MISC_USER_FUNCTION (event, Qeval); | |
2603 XSET_EVENT_MISC_USER_OBJECT (event, list4 (Qfuncall, callback_ex, image_instance, event)); | |
2604 } | |
2605 else if (NILP (callback) || UNBOUNDP (callback)) | |
2606 event = Qnil; | |
2607 else | |
2608 { | |
2609 Lisp_Object fn, arg; | |
2610 | |
2611 event = Fmake_event (Qnil, Qnil); | |
2612 | |
2613 get_gui_callback (callback, &fn, &arg); | |
2614 XSET_EVENT_TYPE (event, misc_user_event); | |
2615 XSET_EVENT_CHANNEL (event, frame); | |
2616 XSET_EVENT_MISC_USER_FUNCTION (event, fn); | |
2617 XSET_EVENT_MISC_USER_OBJECT (event, arg); | |
2618 } | |
2619 | |
2620 if (!NILP (event)) | |
2621 enqueue_dispatch_event (event); | |
2622 | |
2623 /* The result of this evaluation could cause other instances to change so | |
2624 enqueue an update callback to check this. */ | |
2625 if (update_subwindows_p && !NILP (event)) | |
2626 enqueue_magic_eval_event (update_widget_instances, frame); | |
2627 } | |
2628 } | |
2629 | |
2630 /* Create a tab_control widget. The special handling of the individual tabs | |
2631 means that the normal instantiation code cannot be used. */ | |
2632 static void | |
2633 gtk_tab_control_instantiate (Lisp_Object image_instance, | |
2634 Lisp_Object instantiator, | |
2635 Lisp_Object pointer_fg, | |
2636 Lisp_Object pointer_bg, | |
2637 int dest_mask, Lisp_Object domain) | |
2638 { | |
2639 Lisp_Object rest; | |
2640 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
2641 int i = 0; | |
2642 int selected = 0; | |
2643 GtkNotebook *nb; | |
2644 | |
2645 /* The normal instantiation is still needed. */ | |
2646 gtk_widget_instantiate (image_instance, instantiator, pointer_fg, | |
2647 pointer_bg, dest_mask, domain); | |
2648 | |
2649 nb = GTK_NOTEBOOK (IMAGE_INSTANCE_GTK_CLIPWIDGET (ii)); | |
2650 | |
2651 /* Add items to the tab, find the current selection */ | |
2652 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) | |
2653 { | |
2654 gtk_add_tab_item (image_instance, nb, XCAR (rest), domain, i); | |
2655 | |
2656 if (gui_item_selected_p (XCAR (rest))) | |
2657 selected = i; | |
2658 | |
2659 i++; | |
2660 } | |
2661 | |
2662 gtk_notebook_set_page(nb, selected); | |
2663 | |
2664 /* Call per-tab lisp callback when a tab is pressed. */ | |
2665 gtk_signal_connect (GTK_OBJECT (nb), "switch-page", | |
2666 GTK_SIGNAL_FUNC (gtk_tab_control_callback), NULL); | |
2667 } | |
2668 | |
462 | 2669 /* Set the properties of a tab control */ |
2670 static void | |
2671 gtk_tab_control_redisplay (Lisp_Object image_instance) | |
2672 { | |
2673 /* #### Convert this to GTK baby! */ | |
2674 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
2675 | |
2676 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) || | |
2677 IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii)) | |
2678 { | |
2679 /* If only the order has changed then simply select the first | |
2680 one of the pending set. This stops horrendous rebuilding - | |
2681 and hence flicker - of the tabs each time you click on | |
2682 one. */ | |
2683 if (tab_control_order_only_changed (image_instance)) | |
2684 { | |
2168 | 2685 int i = 0; |
462 | 2686 Lisp_Object rest, selected = |
2687 gui_item_list_find_selected | |
2688 (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ? | |
2689 XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) : | |
2690 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))); | |
2691 | |
2692 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) | |
2693 { | |
1913 | 2694 if (gui_item_equal_sans_selected (XCAR (rest), selected, 0)) |
462 | 2695 { |
2696 Lisp_Object old_selected =gui_item_list_find_selected | |
2697 (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))); | |
2698 | |
2699 /* Pick up the new selected item. */ | |
2700 XGUI_ITEM (old_selected)->selected = | |
2701 XGUI_ITEM (XCAR (rest))->selected; | |
2702 XGUI_ITEM (XCAR (rest))->selected = | |
2703 XGUI_ITEM (selected)->selected; | |
2704 /* We're not actually changing the items anymore. */ | |
2705 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0; | |
2706 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil; | |
2168 | 2707 |
2708 gtk_notebook_set_page(GTK_NOTEBOOK (IMAGE_INSTANCE_GTK_CLIPWIDGET (ii)), | |
2709 i); | |
462 | 2710 break; |
2711 } | |
2168 | 2712 |
2713 i++; | |
462 | 2714 } |
2715 } | |
2716 else | |
2717 { | |
2718 /* More than just the order has changed... let's get busy! */ | |
2719 GtkNotebook *nb = GTK_NOTEBOOK (IMAGE_INSTANCE_GTK_CLIPWIDGET (ii)); | |
2720 guint num_pages = g_list_length (nb->children); | |
2721 Lisp_Object rest; | |
2168 | 2722 int i; |
2723 | |
2724 /* Why is there no API to remove everything from a notebook? */ | |
462 | 2725 if (num_pages >= 0) |
2726 { | |
2727 for (i = num_pages; i >= 0; --i) | |
2728 { | |
2729 gtk_notebook_remove_page (nb, i); | |
2730 } | |
2731 } | |
2732 | |
2168 | 2733 i = 0; |
2734 | |
2735 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))) | |
462 | 2736 { |
2168 | 2737 gtk_add_tab_item(image_instance, nb, XCAR(rest), |
2738 IMAGE_INSTANCE_FRAME(ii), i); | |
462 | 2739 } |
2740 | |
2741 /* Show all the new widgets we just added... */ | |
2742 gtk_widget_show_all (GTK_WIDGET (nb)); | |
2743 } | |
2744 } | |
2745 | |
2746 /* Possibly update the face. */ | |
2747 #if 0 | |
2748 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii) | |
2749 || | |
2750 XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed | |
2751 || | |
2752 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)) | |
2753 { | |
2754 update_tab_widget_face (wv, ii, | |
2755 IMAGE_INSTANCE_FRAME (ii)); | |
2756 } | |
2757 #endif | |
2758 } | |
2759 #endif /* HAVE_WIDGETS */ | |
2760 | |
2761 | |
2762 /************************************************************************/ | |
2763 /* initialization */ | |
2764 /************************************************************************/ | |
2765 void | |
2766 syms_of_glyphs_gtk (void) | |
2767 { | |
2768 #ifdef HAVE_WIDGETS | |
563 | 2769 DEFSYMBOL (Qgtk_widget_instantiate_internal); |
2770 DEFSYMBOL (Qgtk_widget_property_internal); | |
2771 DEFSYMBOL (Qgtk_widget_redisplay_internal); | |
2772 DEFSYMBOL (Qgtk_widget_set_style); | |
462 | 2773 #endif |
2774 } | |
2775 | |
2776 void | |
2777 console_type_create_glyphs_gtk (void) | |
2778 { | |
2779 /* image methods */ | |
2780 CONSOLE_HAS_METHOD (gtk, print_image_instance); | |
2781 CONSOLE_HAS_METHOD (gtk, finalize_image_instance); | |
2782 CONSOLE_HAS_METHOD (gtk, image_instance_equal); | |
2783 CONSOLE_HAS_METHOD (gtk, image_instance_hash); | |
2784 CONSOLE_HAS_METHOD (gtk, colorize_image_instance); | |
2785 CONSOLE_HAS_METHOD (gtk, init_image_instance_from_eimage); | |
2786 CONSOLE_HAS_METHOD (gtk, locate_pixmap_file); | |
2787 CONSOLE_HAS_METHOD (gtk, unmap_subwindow); | |
2788 CONSOLE_HAS_METHOD (gtk, map_subwindow); | |
2789 CONSOLE_HAS_METHOD (gtk, redisplay_widget); | |
2790 CONSOLE_HAS_METHOD (gtk, redisplay_subwindow); | |
2791 } | |
2792 | |
2793 void | |
2794 image_instantiator_format_create_glyphs_gtk (void) | |
2795 { | |
2796 IIFORMAT_VALID_CONSOLE (gtk, nothing); | |
2797 IIFORMAT_VALID_CONSOLE (gtk, string); | |
2798 #ifdef HAVE_WIDGETS | |
2799 IIFORMAT_VALID_CONSOLE (gtk, layout); | |
2800 #endif | |
2801 IIFORMAT_VALID_CONSOLE (gtk, formatted_string); | |
2802 IIFORMAT_VALID_CONSOLE (gtk, inherit); | |
2803 #ifdef HAVE_XPM | |
2804 INITIALIZE_DEVICE_IIFORMAT (gtk, xpm); | |
2805 IIFORMAT_HAS_DEVMETHOD (gtk, xpm, instantiate); | |
2806 #endif | |
2807 #ifdef HAVE_JPEG | |
2808 IIFORMAT_VALID_CONSOLE (gtk, jpeg); | |
2809 #endif | |
2810 #ifdef HAVE_TIFF | |
2811 IIFORMAT_VALID_CONSOLE (gtk, tiff); | |
2812 #endif | |
2813 #ifdef HAVE_PNG | |
2814 IIFORMAT_VALID_CONSOLE (gtk, png); | |
2815 #endif | |
2816 #ifdef HAVE_GIF | |
2817 IIFORMAT_VALID_CONSOLE (gtk, gif); | |
2818 #endif | |
2819 | |
2820 INITIALIZE_DEVICE_IIFORMAT (gtk, subwindow); | |
2821 IIFORMAT_HAS_DEVMETHOD (gtk, subwindow, instantiate); | |
2822 | |
2823 #ifdef HAVE_WIDGETS | |
2824 /* layout widget */ | |
2825 INITIALIZE_DEVICE_IIFORMAT (gtk, native_layout); | |
2826 IIFORMAT_HAS_DEVMETHOD (gtk, native_layout, instantiate); | |
2827 | |
2828 /* button widget */ | |
2829 INITIALIZE_DEVICE_IIFORMAT (gtk, button); | |
2830 IIFORMAT_HAS_DEVMETHOD (gtk, button, property); | |
2831 IIFORMAT_HAS_DEVMETHOD (gtk, button, instantiate); | |
2832 IIFORMAT_HAS_DEVMETHOD (gtk, button, redisplay); | |
2168 | 2833 IIFORMAT_HAS_SHARED_DEVMETHOD (gtk, button, query_geometry, widget); |
462 | 2834 /* general widget methods. */ |
2835 INITIALIZE_DEVICE_IIFORMAT (gtk, widget); | |
2836 IIFORMAT_HAS_DEVMETHOD (gtk, widget, property); | |
2168 | 2837 IIFORMAT_HAS_DEVMETHOD (gtk, widget, query_geometry); |
462 | 2838 |
2839 /* progress gauge */ | |
2840 INITIALIZE_DEVICE_IIFORMAT (gtk, progress_gauge); | |
2841 IIFORMAT_HAS_DEVMETHOD (gtk, progress_gauge, redisplay); | |
2842 IIFORMAT_HAS_DEVMETHOD (gtk, progress_gauge, instantiate); | |
2168 | 2843 IIFORMAT_HAS_SHARED_DEVMETHOD (gtk, progress_gauge, query_geometry, widget); |
462 | 2844 /* text field */ |
2845 INITIALIZE_DEVICE_IIFORMAT (gtk, edit_field); | |
2846 IIFORMAT_HAS_DEVMETHOD (gtk, edit_field, instantiate); | |
2847 INITIALIZE_DEVICE_IIFORMAT (gtk, combo_box); | |
2848 IIFORMAT_HAS_DEVMETHOD (gtk, combo_box, instantiate); | |
2849 IIFORMAT_HAS_SHARED_DEVMETHOD (gtk, combo_box, redisplay, tab_control); | |
2850 /* tab control widget */ | |
2851 INITIALIZE_DEVICE_IIFORMAT (gtk, tab_control); | |
2852 IIFORMAT_HAS_DEVMETHOD (gtk, tab_control, instantiate); | |
2853 IIFORMAT_HAS_DEVMETHOD (gtk, tab_control, redisplay); | |
2168 | 2854 IIFORMAT_HAS_SHARED_DEVMETHOD (gtk, tab_control, query_geometry, widget); |
462 | 2855 /* label */ |
2856 INITIALIZE_DEVICE_IIFORMAT (gtk, label); | |
2857 IIFORMAT_HAS_DEVMETHOD (gtk, label, instantiate); | |
2858 #endif | |
2859 | |
2860 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font"); | |
2861 IIFORMAT_VALID_CONSOLE (gtk, cursor_font); | |
2862 | |
2863 IIFORMAT_HAS_METHOD (cursor_font, validate); | |
2864 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types); | |
2865 IIFORMAT_HAS_METHOD (cursor_font, instantiate); | |
2866 | |
2867 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string); | |
2868 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string); | |
2869 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string); | |
2870 | |
2871 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font"); | |
2872 IIFORMAT_VALID_CONSOLE (gtk, font); | |
2873 | |
2874 IIFORMAT_HAS_METHOD (font, validate); | |
2875 IIFORMAT_HAS_METHOD (font, possible_dest_types); | |
2876 IIFORMAT_HAS_METHOD (font, instantiate); | |
2877 | |
2878 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string); | |
2879 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string); | |
2880 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string); | |
2881 | |
2882 #ifdef HAVE_XPM | |
2883 INITIALIZE_DEVICE_IIFORMAT (gtk, xpm); | |
2884 IIFORMAT_HAS_DEVMETHOD (gtk, xpm, instantiate); | |
2885 #endif | |
2886 | |
2887 #ifdef HAVE_XFACE | |
2888 INITIALIZE_DEVICE_IIFORMAT (gtk, xface); | |
2889 IIFORMAT_HAS_DEVMETHOD (gtk, xface, instantiate); | |
2890 #endif | |
2891 | |
2892 INITIALIZE_DEVICE_IIFORMAT (gtk, xbm); | |
2893 IIFORMAT_HAS_DEVMETHOD (gtk, xbm, instantiate); | |
2894 IIFORMAT_VALID_CONSOLE (gtk, xbm); | |
2895 | |
2896 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (gtk_resource, "gtk-resource"); | |
2897 IIFORMAT_VALID_CONSOLE (gtk, gtk_resource); | |
2898 | |
2899 IIFORMAT_HAS_METHOD (gtk_resource, validate); | |
2900 IIFORMAT_HAS_METHOD (gtk_resource, normalize); | |
2901 IIFORMAT_HAS_METHOD (gtk_resource, possible_dest_types); | |
2902 IIFORMAT_HAS_METHOD (gtk_resource, instantiate); | |
2903 | |
2904 IIFORMAT_VALID_KEYWORD (gtk_resource, Q_resource_type, check_valid_resource_symbol); | |
2905 IIFORMAT_VALID_KEYWORD (gtk_resource, Q_resource_id, check_valid_resource_id); | |
2906 IIFORMAT_VALID_KEYWORD (gtk_resource, Q_file, check_valid_string); | |
2907 | |
2908 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect, "autodetect"); | |
2909 IIFORMAT_VALID_CONSOLE (gtk, autodetect); | |
2910 | |
2911 IIFORMAT_HAS_METHOD (autodetect, validate); | |
2912 IIFORMAT_HAS_METHOD (autodetect, normalize); | |
2913 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types); | |
2914 IIFORMAT_HAS_METHOD (autodetect, instantiate); | |
2915 | |
2916 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string); | |
2917 } | |
2918 | |
2919 void | |
2920 vars_of_glyphs_gtk (void) | |
2921 { | |
2922 #ifdef HAVE_XFACE | |
2923 Fprovide (Qxface); | |
2924 #endif | |
2925 | |
2926 DEFVAR_LISP ("gtk-bitmap-file-path", &Vgtk_bitmap_file_path /* | |
2927 A list of the directories in which X bitmap files may be found. | |
2928 If nil, this is initialized from the "*bitmapFilePath" resource. | |
2929 This is used by the `make-image-instance' function (however, note that if | |
2930 the environment variable XBMLANGPATH is set, it is consulted first). | |
2931 */ ); | |
2932 Vgtk_bitmap_file_path = Qnil; | |
2933 } | |
2934 | |
2935 void | |
2936 complex_vars_of_glyphs_gtk (void) | |
2937 { | |
2938 #define BUILD_GLYPH_INST(variable, name) \ | |
2939 Fadd_spec_to_specifier \ | |
2940 (GLYPH_IMAGE (XGLYPH (variable)), \ | |
2941 vector3 (Qxbm, Q_data, \ | |
2942 list3 (make_int (name##_width), \ | |
2943 make_int (name##_height), \ | |
2054 | 2944 make_ext_string ((Extbyte*) name##_bits, \ |
462 | 2945 sizeof (name##_bits), \ |
2946 Qbinary))), \ | |
2947 Qglobal, Qgtk, Qnil) | |
2948 | |
2949 BUILD_GLYPH_INST (Vtruncation_glyph, truncator); | |
2950 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer); | |
2951 BUILD_GLYPH_INST (Vxemacs_logo, xemacs); | |
2952 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll); | |
2953 | |
2954 #undef BUILD_GLYPH_INST | |
2955 } | |
2956 | |
2957 /* X specific crap */ | |
2958 #include <gdk/gdkx.h> | |
2959 /* #### Should remove all this X specific stuff when GTK/GDK matures a | |
2960 bit more and provides an abstraction for it. */ | |
2961 static int | |
2962 gtk_colorize_image_instance (Lisp_Object image_instance, | |
2963 Lisp_Object foreground, Lisp_Object background) | |
2964 { | |
2965 struct Lisp_Image_Instance *p; | |
2966 | |
2967 p = XIMAGE_INSTANCE (image_instance); | |
2968 | |
2969 switch (IMAGE_INSTANCE_TYPE (p)) | |
2970 { | |
2971 case IMAGE_MONO_PIXMAP: | |
2972 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP; | |
2973 /* Make sure there aren't two pointers to the same mask, causing | |
2974 it to get freed twice. */ | |
4433
1bf48c59700e
Fix old use of rvalue on lhs to placate gcc >4.0.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4252
diff
changeset
|
2975 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0; |
462 | 2976 break; |
2977 | |
2978 default: | |
2979 return 0; | |
2980 } | |
2981 | |
2982 { | |
2983 GdkWindow *draw = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p)))); | |
2984 GdkPixmap *new_pxmp = gdk_pixmap_new (draw, | |
2985 IMAGE_INSTANCE_PIXMAP_WIDTH (p), | |
2986 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), | |
2987 DEVICE_GTK_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p)))); | |
2988 GdkGCValues gcv; | |
2989 GdkGC *gc; | |
2990 | |
2991 gcv.foreground = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (foreground)); | |
2992 gcv.background = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (background)); | |
2054 | 2993 gc = gdk_gc_new_with_values (new_pxmp, &gcv, |
2994 (GdkGCValuesMask) (GDK_GC_BACKGROUND | GDK_GC_FOREGROUND)); | |
462 | 2995 |
2996 XCopyPlane (GDK_WINDOW_XDISPLAY (draw), | |
2997 GDK_WINDOW_XWINDOW (IMAGE_INSTANCE_GTK_PIXMAP (p)), | |
2998 GDK_WINDOW_XWINDOW (new_pxmp), | |
2999 GDK_GC_XGC (gc), 0, 0, | |
3000 IMAGE_INSTANCE_PIXMAP_WIDTH (p), | |
3001 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), | |
3002 0, 0, 1); | |
3003 | |
3004 gdk_gc_destroy (gc); | |
3005 IMAGE_INSTANCE_GTK_PIXMAP (p) = new_pxmp; | |
3006 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = DEVICE_GTK_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p))); | |
3007 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground; | |
3008 IMAGE_INSTANCE_PIXMAP_BG (p) = background; | |
3009 return 1; | |
3010 } | |
3011 } |