Fix if/else scope in yow.c from Rudi
[sxemacs] / src / gtk-glue.c
1 GtkType GTK_TYPE_ARRAY = 0;
2 GtkType GTK_TYPE_STRING_ARRAY = 0;
3 GtkType GTK_TYPE_FLOAT_ARRAY = 0;
4 GtkType GTK_TYPE_INT_ARRAY = 0;
5 GtkType GTK_TYPE_LISTOF = 0;
6 GtkType GTK_TYPE_STRING_LIST = 0;
7 GtkType GTK_TYPE_OBJECT_LIST = 0;
8 GtkType GTK_TYPE_GDK_GC = 0;
9
10 static GtkType xemacs_type_register(gchar * name, GtkType parent)
11 {
12         GtkType type_id;
13         GtkTypeInfo info;
14
15         info.type_name = name;
16         info.object_size = 0;
17         info.class_size = 0;
18         info.class_init_func = NULL;
19         info.object_init_func = NULL;
20         info.reserved_1 = NULL;
21         info.reserved_2 = NULL;
22
23         type_id = gtk_type_unique(parent, &info);
24
25         return (type_id);
26 }
27
28 static void xemacs_init_gtk_classes(void)
29 {
30         if (!GTK_TYPE_ARRAY) {
31                 GTK_TYPE_ARRAY = xemacs_type_register("GtkArrayOf", 0);
32                 GTK_TYPE_STRING_ARRAY =
33                     xemacs_type_register("GtkArrayOfString", GTK_TYPE_ARRAY);
34                 GTK_TYPE_FLOAT_ARRAY =
35                     xemacs_type_register("GtkArrayOfFloat", GTK_TYPE_ARRAY);
36                 GTK_TYPE_INT_ARRAY =
37                     xemacs_type_register("GtkArrayOfInteger", GTK_TYPE_ARRAY);
38                 GTK_TYPE_LISTOF = xemacs_type_register("GtkListOf", 0);
39                 GTK_TYPE_STRING_LIST =
40                     xemacs_type_register("GtkListOfString", GTK_TYPE_LISTOF);
41                 GTK_TYPE_OBJECT_LIST =
42                     xemacs_type_register("GtkListOfObject", GTK_TYPE_LISTOF);
43                 GTK_TYPE_GDK_GC = xemacs_type_register("GdkGC", GTK_TYPE_BOXED);
44         }
45 }
46
47 static void xemacs_list_to_gtklist(Lisp_Object obj, GtkArg * arg)
48 {
49         CHECK_LIST(obj);
50
51         if (arg->type == GTK_TYPE_STRING_LIST) {
52                 Lisp_Object temp = obj;
53                 GList *strings = NULL;
54
55                 while (!NILP(temp)) {
56                         CHECK_STRING(XCAR(temp));
57                         temp = XCDR(temp);
58                 }
59
60                 temp = obj;
61
62                 while (!NILP(temp)) {
63                         strings =
64                             g_list_append(strings, XSTRING_DATA(XCAR(temp)));
65                         temp = XCDR(temp);
66                 }
67
68                 GTK_VALUE_POINTER(*arg) = strings;
69         } else if (arg->type == GTK_TYPE_OBJECT_LIST) {
70                 Lisp_Object temp = obj;
71                 GList *objects = NULL;
72
73                 while (!NILP(temp)) {
74                         CHECK_GTK_OBJECT(XCAR(temp));
75                         temp = XCDR(temp);
76                 }
77
78                 temp = obj;
79
80                 while (!NILP(temp)) {
81                         objects =
82                             g_list_append(objects,
83                                           XGTK_OBJECT(XCAR(temp))->object);
84                         temp = XCDR(temp);
85                 }
86
87                 GTK_VALUE_POINTER(*arg) = objects;
88         } else {
89                 abort();
90         }
91 }
92
93 static void __make_gtk_object_mapper(gpointer data, gpointer user_data)
94 {
95         Lisp_Object *rv = (Lisp_Object *) user_data;
96
97         *rv = Fcons(build_gtk_object(GTK_OBJECT(data)), *rv);
98 }
99
100 static void __make_string_mapper(gpointer data, gpointer user_data)
101 {
102         Lisp_Object *rv = (Lisp_Object *) user_data;
103
104         *rv = Fcons(build_string((char *)data), *rv);
105 }
106
107 static Lisp_Object xemacs_gtklist_to_list(GtkArg * arg)
108 {
109         Lisp_Object rval = Qnil;
110
111         if (GTK_VALUE_POINTER(*arg)) {
112                 if (arg->type == GTK_TYPE_STRING_LIST) {
113                         g_list_foreach(GTK_VALUE_POINTER(*arg),
114                                        __make_string_mapper, &rval);
115                 } else if (arg->type == GTK_TYPE_OBJECT_LIST) {
116                         g_list_foreach(GTK_VALUE_POINTER(*arg),
117                                        __make_gtk_object_mapper, &rval);
118                 } else {
119                         abort();
120                 }
121         }
122         return (rval);
123 }
124
125 static void xemacs_list_to_array(Lisp_Object obj, GtkArg * arg)
126 {
127         CHECK_LIST(obj);
128
129 #define FROB(ret_type,check_fn,extract_fn) \
130   do {                                                          \
131     Lisp_Object temp = obj;                                     \
132     int length = 0;                                             \
133     ret_type *array = NULL;                                     \
134                                                                 \
135     while (!NILP (temp))                                        \
136       {                                                         \
137         check_fn (XCAR (temp));                                 \
138         length++;                                               \
139         temp = XCDR (temp);                                     \
140       }                                                         \
141                                                                 \
142     array = xnew_array_and_zero (ret_type, length + 2);         \
143     temp = obj;                                                 \
144     length = 0;                                                 \
145                                                                 \
146     while (!NILP (temp))                                        \
147       {                                                         \
148         array[length++] = extract_fn (XCAR (temp));             \
149         temp = XCDR (temp);                                     \
150       }                                                         \
151                                                                 \
152     GTK_VALUE_POINTER(*arg) = array;                            \
153   } while (0);
154
155         if (arg->type == GTK_TYPE_STRING_ARRAY) {
156                 FROB(gchar *, CHECK_STRING, XSTRING_DATA);
157         } else if (arg->type == GTK_TYPE_FLOAT_ARRAY) {
158                 FROB(gfloat, CHECK_FLOAT, extract_float);
159         } else if (arg->type == GTK_TYPE_INT_ARRAY) {
160                 FROB(gint, CHECK_INT, XINT);
161         } else {
162                 abort();
163         }
164 #undef FROB
165 }
166
167 extern GdkGC *gtk_get_gc(struct device *d, Lisp_Object font, Lisp_Object fg,
168                          Lisp_Object bg, Lisp_Object bg_pmap,
169                          Lisp_Object lwidth);
170
171 static GdkGC *face_to_gc(Lisp_Object face)
172 {
173         Lisp_Object device = Fselected_device(Qnil);
174
175         return (gtk_get_gc(XDEVICE(device),
176                            Fspecifier_instance(Fget(face, Qfont, Qnil), device,
177                                                Qnil, Qnil),
178                            Fspecifier_instance(Fget(face, Qforeground, Qnil),
179                                                device, Qnil, Qnil),
180                            Fspecifier_instance(Fget(face, Qbackground, Qnil),
181                                                device, Qnil, Qnil),
182                            Fspecifier_instance(Fget
183                                                (face, Qbackground_pixmap, Qnil),
184                                                device, Qnil, Qnil), Qnil));
185 }
186
187 static GtkStyle *face_to_style(Lisp_Object face)
188 {
189         Lisp_Object device = Fselected_device(Qnil);
190         GtkStyle *style = gtk_style_new();
191         int i;
192
193         Lisp_Object font =
194             Fspecifier_instance(Fget(face, Qfont, Qnil), device, Qnil, Qnil);
195         Lisp_Object fg =
196             Fspecifier_instance(Fget(face, Qforeground, Qnil), device, Qnil,
197                                 Qnil);
198         Lisp_Object bg =
199             Fspecifier_instance(Fget(face, Qbackground, Qnil), device, Qnil,
200                                 Qnil);
201         Lisp_Object pm =
202             Fspecifier_instance(Fget(face, Qbackground_pixmap, Qnil), device,
203                                 Qnil, Qnil);
204
205         for (i = 0; i < 5; i++)
206                 style->fg[i] = *COLOR_INSTANCE_GTK_COLOR(XCOLOR_INSTANCE(fg));
207         for (i = 0; i < 5; i++)
208                 style->bg[i] = *COLOR_INSTANCE_GTK_COLOR(XCOLOR_INSTANCE(bg));
209
210         if (IMAGE_INSTANCEP(pm)) {
211                 for (i = 0; i < 5; i++)
212                         style->bg_pixmap[i] = XIMAGE_INSTANCE_GTK_PIXMAP(pm);
213         }
214
215         style->font = FONT_INSTANCE_GTK_FONT(XFONT_INSTANCE(font));
216
217         return (style);
218 }
219
220 extern int gtk_event_to_emacs_event(struct frame *, GdkEvent *,
221                                     struct Lisp_Event *);
222
223 static Lisp_Object gdk_event_to_emacs_event(GdkEvent * ev)
224 {
225         Lisp_Object emacs_event = Qnil;
226
227         if (ev) {
228                 emacs_event = Fmake_event(Qnil, Qnil);
229                 if (!gtk_event_to_emacs_event(NULL, ev, XEVENT(emacs_event))) {
230                         /* We need to handle a few more cases than the normal event
231                          ** loop does.  Mainly the double/triple click events.
232                          */
233                         if ((ev->type == GDK_2BUTTON_PRESS)
234                             || (ev->type == GDK_3BUTTON_PRESS)) {
235                                 struct Lisp_Event *le = XEVENT(emacs_event);
236
237                                 le->event_type = misc_user_event;
238                                 le->event.misc.button = ev->button.button;
239                                 le->event.misc.modifiers = 0;
240                                 le->event.misc.x = ev->button.x;
241                                 le->event.misc.y = ev->button.y;
242                                 if (ev->type == GDK_2BUTTON_PRESS)
243                                         le->event.misc.function =
244                                             intern("double-click");
245                                 else
246                                         le->event.misc.function =
247                                             intern("triple-click");
248                         } else {
249                                 Fdeallocate_event(emacs_event);
250                                 emacs_event = Qnil;
251                         }
252                 }
253         }
254         return (emacs_event);
255 }