1 /* Haiku window system support
2    Copyright (C) 2021 Free Software Foundation, Inc.
3 
4 This file is part of GNU Emacs.
5 
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or (at
9 your option) any later version.
10 
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
18 
19 #include <config.h>
20 
21 #include "dispextern.h"
22 #include "frame.h"
23 #include "lisp.h"
24 #include "haikugui.h"
25 #include "keyboard.h"
26 #include "haikuterm.h"
27 #include "blockinput.h"
28 #include "termchar.h"
29 #include "termhooks.h"
30 #include "menu.h"
31 #include "buffer.h"
32 #include "haiku_support.h"
33 #include "thread.h"
34 #include "window.h"
35 
36 #include <math.h>
37 #include <stdlib.h>
38 
39 #ifdef USE_BE_CAIRO
40 #include <cairo.h>
41 #endif
42 
43 struct haiku_display_info *x_display_list = NULL;
44 extern frame_parm_handler haiku_frame_parm_handlers[];
45 
46 static void **fringe_bmps;
47 static int fringe_bitmap_fillptr = 0;
48 
49 static Lisp_Object rdb;
50 
51 struct unhandled_event
52 {
53   struct unhandled_event *next;
54   enum haiku_event_type type;
55   uint8_t buffer[200];
56 };
57 
58 char *
get_keysym_name(int keysym)59 get_keysym_name (int keysym)
60 {
61   static char value[16];
62   sprintf (value, "%d", keysym);
63   return value;
64 }
65 
66 static struct frame *
haiku_window_to_frame(void * window)67 haiku_window_to_frame (void *window)
68 {
69   Lisp_Object tail, tem;
70   struct frame *f;
71 
72   FOR_EACH_FRAME (tail, tem)
73     {
74       f = XFRAME (tem);
75       if (!FRAME_HAIKU_P (f))
76 	continue;
77 
78       eassert (FRAME_DISPLAY_INFO (f) == x_display_list);
79 
80       if (FRAME_HAIKU_WINDOW (f) == window)
81 	return f;
82     }
83 
84   return 0;
85 }
86 
87 static void
haiku_coords_from_parent(struct frame * f,int * x,int * y)88 haiku_coords_from_parent (struct frame *f, int *x, int *y)
89 {
90   struct frame *p = FRAME_PARENT_FRAME (f);
91   eassert (p);
92 
93   for (struct frame *parent = p; parent;
94        parent = FRAME_PARENT_FRAME (parent))
95     {
96       *x -= parent->left_pos;
97       *y -= parent->top_pos;
98     }
99 }
100 
101 static void
haiku_delete_terminal(struct terminal * terminal)102 haiku_delete_terminal (struct terminal *terminal)
103 {
104   emacs_abort ();
105 }
106 
107 static const char *
get_string_resource(void * ignored,const char * name,const char * class)108 get_string_resource (void *ignored, const char *name, const char *class)
109 {
110   if (!name)
111     return NULL;
112 
113   Lisp_Object lval = assoc_no_quit (build_string (name), rdb);
114 
115   if (!NILP (lval))
116     return SSDATA (XCDR (lval));
117 
118   return NULL;
119 }
120 
121 static void
haiku_update_size_hints(struct frame * f)122 haiku_update_size_hints (struct frame *f)
123 {
124   int base_width, base_height;
125   eassert (FRAME_HAIKU_P (f) && FRAME_HAIKU_WINDOW (f));
126 
127   base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
128   base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
129 
130   block_input ();
131   BWindow_set_size_alignment (FRAME_HAIKU_WINDOW (f),
132 			      frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f),
133 			      frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f));
134   BWindow_set_min_size (FRAME_HAIKU_WINDOW (f), base_width,
135 			base_height
136 			+ FRAME_TOOL_BAR_HEIGHT (f)
137 			+ FRAME_MENU_BAR_HEIGHT (f));
138   unblock_input ();
139 }
140 
141 static void
haiku_clip_to_string(struct glyph_string * s)142 haiku_clip_to_string (struct glyph_string *s)
143 {
144   struct haiku_rect r[2];
145   int n = get_glyph_string_clip_rects (s, (struct haiku_rect *) &r, 2);
146 
147   if (n)
148     BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), r[0].x, r[0].y,
149 		      r[0].width, r[0].height);
150   if (n > 1)
151     {
152       BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), r[1].x, r[1].y,
153 			r[1].width, r[1].height);
154     }
155 
156   s->num_clips = n;
157 }
158 
159 static void
haiku_clip_to_string_exactly(struct glyph_string * s,struct glyph_string * dst)160 haiku_clip_to_string_exactly (struct glyph_string *s, struct glyph_string *dst)
161 {
162   BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), s->x, s->y,
163 		    s->width, s->height);
164   dst->num_clips = 1;
165 }
166 
167 static void
haiku_flip_buffers(struct frame * f)168 haiku_flip_buffers (struct frame *f)
169 {
170   void *view = FRAME_OUTPUT_DATA (f)->view;
171   block_input ();
172 
173   BView_draw_lock (view);
174   FRAME_DIRTY_P (f) = 0;
175   EmacsView_flip_and_blit (view);
176   BView_draw_unlock (view);
177 
178   unblock_input ();
179 }
180 
181 static void
haiku_frame_up_to_date(struct frame * f)182 haiku_frame_up_to_date (struct frame *f)
183 {
184   block_input ();
185   FRAME_MOUSE_UPDATE (f);
186   if (FRAME_DIRTY_P (f) && !buffer_flipping_blocked_p ())
187     haiku_flip_buffers (f);
188   unblock_input ();
189 }
190 
191 static void
haiku_buffer_flipping_unblocked_hook(struct frame * f)192 haiku_buffer_flipping_unblocked_hook (struct frame *f)
193 {
194   if (FRAME_DIRTY_P (f))
195     haiku_flip_buffers (f);
196 }
197 
198 static void
haiku_clear_frame_area(struct frame * f,int x,int y,int width,int height)199 haiku_clear_frame_area (struct frame *f, int x, int y,
200 			int width, int height)
201 {
202   void *vw = FRAME_HAIKU_VIEW (f);
203   block_input ();
204   BView_draw_lock (vw);
205   BView_StartClip (vw);
206   BView_ClipToRect (vw, x, y, width, height);
207   BView_SetHighColor (vw, FRAME_BACKGROUND_PIXEL (f));
208   BView_FillRectangle (vw, x, y, width, height);
209   BView_EndClip (vw);
210   BView_draw_unlock (vw);
211   unblock_input ();
212 }
213 
214 static void
haiku_clear_frame(struct frame * f)215 haiku_clear_frame (struct frame *f)
216 {
217   void *view = FRAME_HAIKU_VIEW (f);
218   block_input ();
219   BView_draw_lock (view);
220   BView_StartClip (view);
221   BView_ClipToRect (view, 0, 0, FRAME_PIXEL_WIDTH (f) + 1,
222 		    FRAME_PIXEL_HEIGHT (f) + 1);
223   BView_SetHighColor (view, FRAME_BACKGROUND_PIXEL (f));
224   BView_FillRectangle (view, 0, 0, FRAME_PIXEL_WIDTH (f) + 1,
225 		       FRAME_PIXEL_HEIGHT (f) + 1);
226   BView_EndClip (view);
227   BView_draw_unlock (view);
228   unblock_input ();
229 }
230 
231 /* Give frame F the font FONT-OBJECT as its default font.  The return
232    value is FONT-OBJECT.  FONTSET is an ID of the fontset for the
233    frame.  If it is negative, generate a new fontset from
234    FONT-OBJECT.  */
235 
236 static Lisp_Object
haiku_new_font(struct frame * f,Lisp_Object font_object,int fontset)237 haiku_new_font (struct frame *f, Lisp_Object font_object, int fontset)
238 {
239   struct font *font = XFONT_OBJECT (font_object);
240   if (fontset < 0)
241     fontset = fontset_from_font (font_object);
242 
243   FRAME_FONTSET (f) = fontset;
244   if (FRAME_FONT (f) == font)
245     return font_object;
246 
247   FRAME_FONT (f) = font;
248   FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
249   FRAME_COLUMN_WIDTH (f) = font->average_width;
250 
251   int ascent, descent;
252   get_font_ascent_descent (font, &ascent, &descent);
253   FRAME_LINE_HEIGHT (f) = ascent + descent;
254   FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
255 
256   int unit = FRAME_COLUMN_WIDTH (f);
257   if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
258     FRAME_CONFIG_SCROLL_BAR_COLS (f)
259       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
260   else
261     FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
262 
263   if (FRAME_HAIKU_WINDOW (f))
264     {
265       adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
266 			 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f),
267 			 3, false, Qfont);
268 
269       haiku_clear_under_internal_border (f);
270     }
271   return font_object;
272 }
273 
274 static int
haiku_valid_modifier_p(Lisp_Object sym)275 haiku_valid_modifier_p (Lisp_Object sym)
276 {
277   return EQ (sym, Qcommand) || EQ (sym, Qshift)
278     || EQ (sym, Qcontrol) || EQ (sym, Qoption);
279 }
280 
281 #define MODIFIER_OR(obj, def) (haiku_valid_modifier_p (obj) ? obj : def)
282 
283 static void
haiku_add_modifier(int modifier,int toput,Lisp_Object qtem,int * modifiers)284 haiku_add_modifier (int modifier, int toput, Lisp_Object qtem, int *modifiers)
285 {
286   if ((modifier & HAIKU_MODIFIER_ALT && EQ (qtem, Qcommand))
287       || (modifier & HAIKU_MODIFIER_SHIFT && EQ (qtem, Qshift))
288       || (modifier & HAIKU_MODIFIER_CTRL && EQ (qtem, Qcontrol))
289       || (modifier & HAIKU_MODIFIER_SUPER && EQ (qtem, Qoption)))
290     *modifiers |= toput;
291 }
292 
293 static int
haiku_modifiers_to_emacs(int haiku_key)294 haiku_modifiers_to_emacs (int haiku_key)
295 {
296   int modifiers = 0;
297   haiku_add_modifier (haiku_key, shift_modifier,
298 		      MODIFIER_OR (Vhaiku_shift_keysym, Qshift), &modifiers);
299   haiku_add_modifier (haiku_key, super_modifier,
300 		      MODIFIER_OR (Vhaiku_super_keysym, Qoption), &modifiers);
301   haiku_add_modifier (haiku_key, meta_modifier,
302 		      MODIFIER_OR (Vhaiku_meta_keysym, Qcommand), &modifiers);
303   haiku_add_modifier (haiku_key, ctrl_modifier,
304 		      MODIFIER_OR (Vhaiku_control_keysym, Qcontrol), &modifiers);
305   return modifiers;
306 }
307 
308 #undef MODIFIER_OR
309 
310 static void
haiku_rehighlight(void)311 haiku_rehighlight (void)
312 {
313   eassert (x_display_list && !x_display_list->next);
314 
315   block_input ();
316 
317   struct frame *old_hl = x_display_list->highlight_frame;
318 
319   if (x_display_list->focused_frame)
320     {
321       x_display_list->highlight_frame
322 	= ((FRAMEP (FRAME_FOCUS_FRAME (x_display_list->focused_frame)))
323 	   ? XFRAME (FRAME_FOCUS_FRAME (x_display_list->focused_frame))
324 	   : x_display_list->focused_frame);
325       if (!FRAME_LIVE_P (x_display_list->highlight_frame))
326 	{
327 	  fset_focus_frame (x_display_list->focused_frame, Qnil);
328 	  x_display_list->highlight_frame = x_display_list->focused_frame;
329 	}
330     }
331   else
332     x_display_list->highlight_frame = 0;
333 
334   if (old_hl)
335     gui_update_cursor (old_hl, true);
336 
337   if (x_display_list->highlight_frame)
338     gui_update_cursor (x_display_list->highlight_frame, true);
339   unblock_input ();
340 }
341 
342 static void
haiku_frame_raise_lower(struct frame * f,bool raise_p)343 haiku_frame_raise_lower (struct frame *f, bool raise_p)
344 {
345   if (raise_p)
346     {
347       block_input ();
348       BWindow_activate (FRAME_HAIKU_WINDOW (f));
349       BWindow_sync (FRAME_HAIKU_WINDOW (f));
350       unblock_input ();
351     }
352 }
353 
354 /* Unfortunately, NOACTIVATE is not implementable on Haiku.  */
355 static void
haiku_focus_frame(struct frame * frame,bool noactivate)356 haiku_focus_frame (struct frame *frame, bool noactivate)
357 {
358   if (x_display_list->focused_frame != frame)
359     haiku_frame_raise_lower (frame, 1);
360 }
361 
362 static void
haiku_new_focus_frame(struct frame * frame)363 haiku_new_focus_frame (struct frame *frame)
364 {
365   eassert (x_display_list && !x_display_list->next);
366 
367   block_input ();
368   if (frame != x_display_list->focused_frame)
369     {
370       if (x_display_list->focused_frame &&
371 	  x_display_list->focused_frame->auto_lower)
372 	haiku_frame_raise_lower (x_display_list->focused_frame, 0);
373 
374       x_display_list->focused_frame = frame;
375 
376       if (frame && frame->auto_raise)
377 	haiku_frame_raise_lower (frame, 1);
378     }
379   unblock_input ();
380 
381   haiku_rehighlight ();
382 }
383 
384 static void
haiku_implicitly_set_name(struct frame * f,Lisp_Object arg,Lisp_Object oldval)385 haiku_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
386 {
387   haiku_set_name (f, arg, 0);
388 }
389 
390 static void
haiku_query_frame_background_color(struct frame * f,Emacs_Color * bgcolor)391 haiku_query_frame_background_color (struct frame *f, Emacs_Color *bgcolor)
392 {
393   haiku_query_color (FRAME_BACKGROUND_PIXEL (f), bgcolor);
394 }
395 
396 static bool
haiku_defined_color(struct frame * f,const char * name,Emacs_Color * color,bool alloc,bool make_index)397 haiku_defined_color (struct frame *f,
398 		     const char *name,
399 		     Emacs_Color *color,
400 		     bool alloc,
401 		     bool make_index)
402 {
403   return !haiku_get_color (name, color);
404 }
405 
406 /* Adapted from xterm `x_draw_box_rect'.  */
407 static void
haiku_draw_box_rect(struct glyph_string * s,int left_x,int top_y,int right_x,int bottom_y,int hwidth,int vwidth,bool left_p,bool right_p,struct haiku_rect * clip_rect)408 haiku_draw_box_rect (struct glyph_string *s,
409 		     int left_x, int top_y, int right_x, int bottom_y, int hwidth,
410 		     int vwidth, bool left_p, bool right_p, struct haiku_rect *clip_rect)
411 {
412   void *view = FRAME_HAIKU_VIEW (s->f);
413   struct face *face = s->face;
414 
415   BView_StartClip (view);
416   BView_SetHighColor (view, face->box_color);
417   if (clip_rect)
418     BView_ClipToRect (view, clip_rect->x, clip_rect->y, clip_rect->width,
419 		      clip_rect->height);
420   BView_FillRectangle (view, left_x, top_y, right_x - left_x + 1, hwidth);
421   if (left_p)
422     BView_FillRectangle (view, left_x, top_y, vwidth, bottom_y - top_y + 1);
423 
424   BView_FillRectangle (view, left_x, bottom_y - hwidth + 1,
425 		       right_x - left_x + 1, hwidth);
426   if (right_p)
427     BView_FillRectangle (view, right_x - vwidth + 1,
428 			 top_y, vwidth, bottom_y - top_y + 1);
429   BView_EndClip (view);
430 }
431 
432 static void
haiku_calculate_relief_colors(struct glyph_string * s,uint32_t * rgbout_w,uint32_t * rgbout_b,uint32_t * rgbout_c)433 haiku_calculate_relief_colors (struct glyph_string *s,
434 			       uint32_t *rgbout_w, uint32_t *rgbout_b,
435 			       uint32_t *rgbout_c)
436 {
437   struct face *face = s->face;
438 
439   prepare_face_for_display (s->f, s->face);
440 
441   uint32_t rgbin = face->use_box_color_for_shadows_p
442     ?  face->box_color : face->background;
443 
444   if (s->hl == DRAW_CURSOR)
445     rgbin = FRAME_CURSOR_COLOR (s->f).pixel;
446 
447   double h, cs, l;
448   rgb_color_hsl (rgbin, &h, &cs, &l);
449 
450   hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 0.6), rgbout_b);
451   hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 1.2), rgbout_w);
452   hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 1.8), rgbout_c);
453 }
454 
455 static void
haiku_draw_relief_rect(struct glyph_string * s,int left_x,int top_y,int right_x,int bottom_y,int hwidth,int vwidth,bool raised_p,bool top_p,bool bot_p,bool left_p,bool right_p,struct haiku_rect * clip_rect,bool fancy_p)456 haiku_draw_relief_rect (struct glyph_string *s,
457 			int left_x, int top_y, int right_x, int bottom_y,
458 			int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p,
459 			bool left_p, bool right_p,
460 			struct haiku_rect *clip_rect, bool fancy_p)
461 {
462   uint32_t color_white;
463   uint32_t color_black;
464   uint32_t color_corner;
465 
466   haiku_calculate_relief_colors (s, &color_white, &color_black,
467 				 &color_corner);
468 
469   void *view = FRAME_HAIKU_VIEW (s->f);
470   BView_StartClip (view);
471 
472   BView_SetHighColor (view, raised_p ? color_white : color_black);
473   if (clip_rect)
474     BView_ClipToRect (view, clip_rect->x, clip_rect->y, clip_rect->width,
475 		      clip_rect->height);
476   if (top_p)
477     BView_FillRectangle (view, left_x, top_y, right_x - left_x + 1, hwidth);
478   if (left_p)
479     BView_FillRectangle (view, left_x, top_y, vwidth, bottom_y - top_y + 1);
480   BView_SetHighColor (view, !raised_p ? color_white : color_black);
481 
482   if (bot_p)
483     BView_FillRectangle (view, left_x, bottom_y - hwidth + 1,
484 			 right_x - left_x + 1, hwidth);
485   if (right_p)
486     BView_FillRectangle (view, right_x - vwidth + 1, top_y,
487 			 vwidth, bottom_y - top_y + 1);
488 
489   /* Draw the triangle for the bottom-left corner.  */
490   if (bot_p && left_p)
491     {
492       BView_SetHighColor (view, raised_p ? color_white : color_black);
493       BView_FillTriangle (view, left_x, bottom_y - hwidth, left_x + vwidth,
494 			  bottom_y - hwidth, left_x, bottom_y);
495     }
496 
497   /* Now draw the triangle for the top-right corner.  */
498   if (top_p && right_p)
499     {
500       BView_SetHighColor (view, raised_p ? color_white : color_black);
501       BView_FillTriangle (view, right_x - vwidth, top_y,
502 			  right_x, top_y,
503 			  right_x - vwidth, top_y + hwidth);
504     }
505 
506   /* If (h/v)width is > 1, we draw the outer-most line on each side in the
507      black relief color.  */
508 
509   BView_SetHighColor (view, color_black);
510 
511   if (hwidth > 1 && top_p)
512     BView_StrokeLine (view, left_x, top_y, right_x, top_y);
513   if (hwidth > 1 && bot_p)
514     BView_StrokeLine (view, left_x, bottom_y, right_x, bottom_y);
515   if (vwidth > 1 && left_p)
516     BView_StrokeLine (view, left_x, top_y, left_x, bottom_y);
517   if (vwidth > 1 && right_p)
518     BView_StrokeLine (view, right_x, top_y, right_x, bottom_y);
519 
520   BView_SetHighColor (view, color_corner);
521 
522   /* Omit corner pixels.  */
523   if (hwidth > 1 || vwidth > 1)
524     {
525       if (left_p && top_p)
526 	BView_FillRectangle (view, left_x, top_y, 1, 1);
527       if (left_p && bot_p)
528 	BView_FillRectangle (view, left_x, bottom_y, 1, 1);
529       if (right_p && top_p)
530 	BView_FillRectangle (view, right_x, top_y, 1, 1);
531       if (right_p && bot_p)
532 	BView_FillRectangle (view, right_x, bottom_y, 1, 1);
533     }
534 
535   BView_EndClip (view);
536 }
537 
538 static void
haiku_draw_underwave(struct glyph_string * s,int width,int x)539 haiku_draw_underwave (struct glyph_string *s, int width, int x)
540 {
541   int wave_height = 3, wave_length = 2;
542   int y, dx, dy, odd, xmax;
543   dx = wave_length;
544   dy = wave_height - 1;
545   y = s->ybase - wave_height + 3;
546 
547   float ax, ay, bx, by;
548   xmax = x + width;
549 
550   void *view = FRAME_HAIKU_VIEW (s->f);
551 
552   BView_StartClip (view);
553   BView_ClipToRect (view, x, y, width, wave_height);
554   ax = x - ((int) (x) % dx) + (float) 0.5;
555   bx = ax + dx;
556   odd = (int) (ax / dx) % 2;
557   ay = by = y + 0.5;
558 
559   if (odd)
560     ay += dy;
561   else
562     by += dy;
563 
564   while (ax <= xmax)
565     {
566       BView_StrokeLine (view, ax, ay, bx, by);
567       ax = bx, ay = by;
568       bx += dx, by = y + 0.5 + odd * dy;
569       odd = !odd;
570     }
571   BView_EndClip (view);
572 }
573 
574 static void
haiku_draw_text_decoration(struct glyph_string * s,struct face * face,uint8_t dcol,int width,int x)575 haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
576 			    uint8_t dcol, int width, int x)
577 {
578   if (s->for_overlaps)
579     return;
580 
581   void *view = FRAME_HAIKU_VIEW (s->f);
582   BView_draw_lock (view);
583   BView_StartClip (view);
584 
585   if (face->underline)
586     {
587       if (s->hl == DRAW_CURSOR)
588 	BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
589       else if (!face->underline_defaulted_p)
590 	BView_SetHighColor (view, face->underline_color);
591       else
592 	BView_SetHighColor (view, dcol);
593 
594       if (face->underline == FACE_UNDER_WAVE)
595 	haiku_draw_underwave (s, width, x);
596       else if (face->underline == FACE_UNDER_LINE)
597 	{
598 	  unsigned long thickness, position;
599 	  int y;
600 
601 	  if (s->prev && s->prev && s->prev->hl == DRAW_MOUSE_FACE)
602 	    {
603 	      struct face *prev_face = s->prev->face;
604 
605 	      if (prev_face && prev_face->underline == FACE_UNDER_LINE)
606 		{
607 		  /* We use the same underline style as the previous one.  */
608 		  thickness = s->prev->underline_thickness;
609 		  position = s->prev->underline_position;
610 		}
611 	      else
612 		goto calculate_underline_metrics;
613 	    }
614 	  else
615 	    {
616 	    calculate_underline_metrics:;
617 	      struct font *font = font_for_underline_metrics (s);
618 	      unsigned long minimum_offset;
619 	      bool underline_at_descent_line;
620 	      bool use_underline_position_properties;
621 	      Lisp_Object val = (WINDOW_BUFFER_LOCAL_VALUE
622 				 (Qunderline_minimum_offset, s->w));
623 
624 	      if (FIXNUMP (val))
625 		minimum_offset = max (0, XFIXNUM (val));
626 	      else
627 		minimum_offset = 1;
628 
629 	      val = (WINDOW_BUFFER_LOCAL_VALUE
630 		     (Qx_underline_at_descent_line, s->w));
631 	      underline_at_descent_line
632 		= !(NILP (val) || EQ (val, Qunbound));
633 
634 	      val = (WINDOW_BUFFER_LOCAL_VALUE
635 		     (Qx_use_underline_position_properties, s->w));
636 	      use_underline_position_properties
637 		= !(NILP (val) || EQ (val, Qunbound));
638 
639 	      /* Get the underline thickness.  Default is 1 pixel.  */
640 	      if (font && font->underline_thickness > 0)
641 		thickness = font->underline_thickness;
642 	      else
643 		thickness = 1;
644 	      if (underline_at_descent_line)
645 		position = (s->height - thickness) - (s->ybase - s->y);
646 	      else
647 		{
648 		  /* Get the underline position.  This is the
649 		     recommended vertical offset in pixels from
650 		     the baseline to the top of the underline.
651 		     This is a signed value according to the
652 		     specs, and its default is
653 
654 		     ROUND ((maximum descent) / 2), with
655 		     ROUND(x) = floor (x + 0.5)  */
656 
657 		  if (use_underline_position_properties
658 		      && font && font->underline_position >= 0)
659 		    position = font->underline_position;
660 		  else if (font)
661 		    position = (font->descent + 1) / 2;
662 		  else
663 		    position = minimum_offset;
664 		}
665 	      position = max (position, minimum_offset);
666 	    }
667 	  /* Check the sanity of thickness and position.  We should
668 	     avoid drawing underline out of the current line area.  */
669 	  if (s->y + s->height <= s->ybase + position)
670 	    position = (s->height - 1) - (s->ybase - s->y);
671 	  if (s->y + s->height < s->ybase + position + thickness)
672 	    thickness = (s->y + s->height) - (s->ybase + position);
673 	  s->underline_thickness = thickness;
674 	  s->underline_position = position;
675 	  y = s->ybase + position;
676 
677 	  BView_FillRectangle (view, s->x, y, s->width, thickness);
678 	}
679     }
680 
681   if (face->overline_p)
682     {
683       unsigned long dy = 0, h = 1;
684       if (s->hl == DRAW_CURSOR)
685 	BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
686       else if (!face->overline_color_defaulted_p)
687 	BView_SetHighColor (view, face->overline_color);
688       else
689 	BView_SetHighColor (view, dcol);
690 
691       BView_FillRectangle (view, s->x, s->y + dy, s->width, h);
692     }
693 
694   if (face->strike_through_p)
695     {
696       /* Y-coordinate and height of the glyph string's first
697 	 glyph.  We cannot use s->y and s->height because those
698 	 could be larger if there are taller display elements
699 	 (e.g., characters displayed with a larger font) in the
700 	 same glyph row.  */
701       int glyph_y = s->ybase - s->first_glyph->ascent;
702       int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
703       /* Strike-through width and offset from the glyph string's
704 	 top edge.  */
705       unsigned long h = 1;
706       unsigned long dy = (glyph_height - h) / 2;
707 
708       if (s->hl == DRAW_CURSOR)
709 	BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
710       else if (!face->strike_through_color_defaulted_p)
711 	BView_SetHighColor (view, face->strike_through_color);
712       else
713 	BView_SetHighColor (view, dcol);
714 
715       BView_FillRectangle (view, s->x, glyph_y + dy, s->width, h);
716     }
717 
718   BView_EndClip (view);
719   BView_draw_unlock (view);
720 }
721 
722 static void
haiku_draw_string_box(struct glyph_string * s,int clip_p)723 haiku_draw_string_box (struct glyph_string *s, int clip_p)
724 {
725   int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
726   bool raised_p, left_p, right_p;
727   struct glyph *last_glyph;
728   struct haiku_rect clip_rect;
729 
730   struct face *face = s->face;
731 
732   last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
733 	    ? WINDOW_RIGHT_EDGE_X (s->w)
734 	    : window_box_right (s->w, s->area));
735 
736   /* The glyph that may have a right box line.  For static
737      compositions and images, the right-box flag is on the first glyph
738      of the glyph string; for other types it's on the last glyph.  */
739   if (s->cmp || s->img)
740     last_glyph = s->first_glyph;
741   else if (s->first_glyph->type == COMPOSITE_GLYPH
742 	   && s->first_glyph->u.cmp.automatic)
743     {
744       /* For automatic compositions, we need to look up the last glyph
745 	 in the composition.  */
746         struct glyph *end = s->row->glyphs[s->area] + s->row->used[s->area];
747 	struct glyph *g = s->first_glyph;
748 	for (last_glyph = g++;
749 	     g < end && g->u.cmp.automatic && g->u.cmp.id == s->cmp_id
750 	       && g->slice.cmp.to < s->cmp_to;
751 	     last_glyph = g++)
752 	  ;
753     }
754   else
755     last_glyph = s->first_glyph + s->nchars - 1;
756 
757   vwidth = eabs (face->box_vertical_line_width);
758   hwidth = eabs (face->box_horizontal_line_width);
759   raised_p = face->box == FACE_RAISED_BOX;
760   left_x = s->x;
761   right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
762 	     ? last_x - 1
763 	     : min (last_x, s->x + s->background_width) - 1);
764 
765   top_y = s->y;
766   bottom_y = top_y + s->height - 1;
767 
768   left_p = (s->first_glyph->left_box_line_p
769 	    || (s->hl == DRAW_MOUSE_FACE
770 		&& (s->prev == NULL
771 		    || s->prev->hl != s->hl)));
772   right_p = (last_glyph->right_box_line_p
773 	     || (s->hl == DRAW_MOUSE_FACE
774 		 && (s->next == NULL
775 		     || s->next->hl != s->hl)));
776 
777   get_glyph_string_clip_rect (s, &clip_rect);
778 
779   if (face->box == FACE_SIMPLE_BOX)
780     haiku_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
781 			 vwidth, left_p, right_p, &clip_rect);
782   else
783     haiku_draw_relief_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
784 			    vwidth, raised_p, true, true, left_p, right_p,
785 			    &clip_rect, 1);
786 
787   if (clip_p)
788     {
789       void *view = FRAME_HAIKU_VIEW (s->f);
790 
791       haiku_draw_text_decoration (s, face, face->foreground, s->width, s->x);
792       BView_ClipToInverseRect (view, left_x, top_y, right_x - left_x + 1, hwidth);
793       if (left_p)
794 	BView_ClipToInverseRect (view, left_x, top_y, vwidth, bottom_y - top_y + 1);
795       BView_ClipToInverseRect (view, left_x, bottom_y - hwidth + 1,
796 			       right_x - left_x + 1, hwidth);
797       if (right_p)
798 	BView_ClipToInverseRect (view, right_x - vwidth + 1,
799 				 top_y, vwidth, bottom_y - top_y + 1);
800     }
801 }
802 
803 static void
haiku_draw_plain_background(struct glyph_string * s,struct face * face,int box_line_hwidth,int box_line_vwidth)804 haiku_draw_plain_background (struct glyph_string *s, struct face *face,
805 			     int box_line_hwidth, int box_line_vwidth)
806 {
807   void *view = FRAME_HAIKU_VIEW (s->f);
808   BView_StartClip (view);
809   if (s->hl == DRAW_CURSOR)
810     BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel);
811   else
812     BView_SetHighColor (view, face->background_defaulted_p ?
813 			FRAME_BACKGROUND_PIXEL (s->f) :
814 		      face->background);
815 
816   BView_FillRectangle (view, s->x,
817 		       s->y + box_line_hwidth,
818 		       s->background_width,
819 		       s->height - 2 * box_line_hwidth);
820   BView_EndClip (view);
821 }
822 
823 static void
haiku_draw_stipple_background(struct glyph_string * s,struct face * face,int box_line_hwidth,int box_line_vwidth)824 haiku_draw_stipple_background (struct glyph_string *s, struct face *face,
825 			       int box_line_hwidth, int box_line_vwidth)
826 {
827 }
828 
829 static void
haiku_maybe_draw_background(struct glyph_string * s,int force_p)830 haiku_maybe_draw_background (struct glyph_string *s, int force_p)
831 {
832   if ((s->first_glyph->type != IMAGE_GLYPH) && !s->background_filled_p)
833     {
834       struct face *face = s->face;
835       int box_line_width = max (face->box_horizontal_line_width, 0);
836       int box_vline_width = max (face->box_vertical_line_width, 0);
837 
838       if (FONT_HEIGHT (s->font) < s->height - 2 * box_vline_width
839 	  || FONT_TOO_HIGH (s->font)
840           || s->font_not_found_p || s->extends_to_end_of_line_p || force_p)
841 	{
842 	  if (!face->stipple)
843 	    haiku_draw_plain_background (s, face, box_line_width,
844 					 box_vline_width);
845 	  else
846 	    haiku_draw_stipple_background (s, face, box_line_width,
847 					   box_vline_width);
848 	  s->background_filled_p = 1;
849 	}
850     }
851 }
852 
853 static void
haiku_mouse_face_colors(struct glyph_string * s,uint32_t * fg,uint32_t * bg)854 haiku_mouse_face_colors (struct glyph_string *s, uint32_t *fg,
855 			 uint32_t *bg)
856 {
857   int face_id;
858   struct face *face;
859 
860   /* What face has to be used last for the mouse face?  */
861   face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
862   face = FACE_FROM_ID_OR_NULL (s->f, face_id);
863   if (face == NULL)
864     face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
865 
866   if (s->first_glyph->type == CHAR_GLYPH)
867     face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
868   else
869     face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
870 
871   face = FACE_FROM_ID (s->f, face_id);
872   prepare_face_for_display (s->f, s->face);
873 
874   if (fg)
875     *fg = face->foreground;
876   if (bg)
877     *bg = face->background;
878 }
879 
880 static void
haiku_draw_glyph_string_foreground(struct glyph_string * s)881 haiku_draw_glyph_string_foreground (struct glyph_string *s)
882 {
883   struct face *face = s->face;
884 
885   int i, x;
886   if (face->box != FACE_NO_BOX
887       && s->first_glyph->left_box_line_p)
888     x = s->x + max (face->box_vertical_line_width, 0);
889   else
890     x = s->x;
891 
892   void *view = FRAME_HAIKU_VIEW (s->f);
893 
894   if (s->font_not_found_p)
895     {
896       BView_StartClip (view);
897       if (s->hl == DRAW_CURSOR)
898 	BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
899       else
900 	BView_SetHighColor (view, face->foreground);
901       for (i = 0; i < s->nchars; ++i)
902 	{
903 	  struct glyph *g = s->first_glyph + i;
904 	  BView_StrokeRectangle (view, x, s->y, g->pixel_width,
905 				 s->height);
906 	  x += g->pixel_width;
907 	}
908       BView_EndClip (view);
909     }
910   else
911     {
912       struct font *ft = s->font;
913       int off = ft->baseline_offset;
914       int y;
915 
916       if (ft->vertical_centering)
917 	off = VCENTER_BASELINE_OFFSET (ft, s->f) - off;
918       y = s->ybase - off;
919       if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR))
920 	ft->driver->draw (s, 0, s->nchars, x, y, false);
921       else
922 	ft->driver->draw (s, 0, s->nchars, x, y, true);
923 
924       if (face->overstrike)
925 	ft->driver->draw (s, 0, s->nchars, x + 1, y, false);
926     }
927 }
928 
929 static void
haiku_draw_glyphless_glyph_string_foreground(struct glyph_string * s)930 haiku_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
931 {
932   struct glyph *glyph = s->first_glyph;
933   unsigned char2b[8];
934   int x, i, j;
935   struct face *face = s->face;
936 
937   /* If first glyph of S has a left box line, start drawing the text
938      of S to the right of that box line.  */
939   if (face && face->box != FACE_NO_BOX
940       && s->first_glyph->left_box_line_p)
941     x = s->x + max (face->box_vertical_line_width, 0);
942   else
943     x = s->x;
944 
945   s->char2b = char2b;
946 
947   for (i = 0; i < s->nchars; i++, glyph++)
948     {
949 #ifdef GCC_LINT
950       enum { PACIFY_GCC_BUG_81401 = 1 };
951 #else
952       enum { PACIFY_GCC_BUG_81401 = 0 };
953 #endif
954       char buf[7 + PACIFY_GCC_BUG_81401];
955       char *str = NULL;
956       int len = glyph->u.glyphless.len;
957 
958       if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
959 	{
960 	  if (len > 0
961 	      && CHAR_TABLE_P (Vglyphless_char_display)
962 	      && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
963 		  >= 1))
964 	    {
965 	      Lisp_Object acronym
966 		= (! glyph->u.glyphless.for_no_font
967 		   ? CHAR_TABLE_REF (Vglyphless_char_display,
968 				     glyph->u.glyphless.ch)
969 		   : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
970 	      if (STRINGP (acronym))
971 		str = SSDATA (acronym);
972 	    }
973 	}
974       else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
975 	{
976 	  unsigned int ch = glyph->u.glyphless.ch;
977 	  eassume (ch <= MAX_CHAR);
978 	  sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
979 	  str = buf;
980 	}
981 
982       if (str)
983 	{
984 	  int upper_len = (len + 1) / 2;
985 
986 	  /* It is assured that all LEN characters in STR is ASCII.  */
987 	  for (j = 0; j < len; j++)
988             char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
989 
990 	  s->font->driver->draw (s, 0, upper_len,
991 				 x + glyph->slice.glyphless.upper_xoff,
992 				 s->ybase + glyph->slice.glyphless.upper_yoff,
993 				 false);
994 	  s->font->driver->draw (s, upper_len, len,
995 				 x + glyph->slice.glyphless.lower_xoff,
996 				 s->ybase + glyph->slice.glyphless.lower_yoff,
997 				 false);
998 	}
999       BView_StartClip (FRAME_HAIKU_VIEW (s->f));
1000       if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
1001 	BView_FillRectangle (FRAME_HAIKU_VIEW (s->f),
1002 			     x, s->ybase - glyph->ascent,
1003 			     glyph->pixel_width - 1,
1004 			     glyph->ascent + glyph->descent - 1);
1005       BView_EndClip (FRAME_HAIKU_VIEW (s->f));
1006       x += glyph->pixel_width;
1007    }
1008 }
1009 
1010 static void
haiku_draw_stretch_glyph_string(struct glyph_string * s)1011 haiku_draw_stretch_glyph_string (struct glyph_string *s)
1012 {
1013   eassert (s->first_glyph->type == STRETCH_GLYPH);
1014 
1015   struct face *face = s->face;
1016 
1017   if (s->hl == DRAW_CURSOR && !x_stretch_cursor_p)
1018     {
1019       int width, background_width = s->background_width;
1020       int x = s->x;
1021 
1022       if (!s->row->reversed_p)
1023 	{
1024 	  int left_x = window_box_left_offset (s->w, TEXT_AREA);
1025 
1026 	  if (x < left_x)
1027 	    {
1028 	      background_width -= left_x - x;
1029 	      x = left_x;
1030 	    }
1031 	}
1032       else
1033 	{
1034 	  /* In R2L rows, draw the cursor on the right edge of the
1035 	     stretch glyph.  */
1036 	  int right_x = window_box_right (s->w, TEXT_AREA);
1037 	  if (x + background_width > right_x)
1038 	    background_width -= x - right_x;
1039 	  x += background_width;
1040 	}
1041 
1042       width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
1043       if (s->row->reversed_p)
1044 	x -= width;
1045 
1046       void *view = FRAME_HAIKU_VIEW (s->f);
1047       BView_StartClip (view);
1048       BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel);
1049       BView_FillRectangle (view, x, s->y, width, s->height);
1050       BView_EndClip (view);
1051 
1052       if (width < background_width)
1053 	{
1054 	  if (!s->row->reversed_p)
1055 	    x += width;
1056 	  else
1057 	    x = s->x;
1058 
1059 	  int y = s->y;
1060 	  int w = background_width - width, h = s->height;
1061 
1062 	  if (!face->stipple)
1063 	    {
1064 	      uint32_t bkg;
1065 	      if (s->hl == DRAW_MOUSE_FACE || (s->hl == DRAW_CURSOR
1066 					       && s->row->mouse_face_p
1067 					       && cursor_in_mouse_face_p (s->w)))
1068 		  haiku_mouse_face_colors (s, NULL, &bkg);
1069 	      else
1070 		bkg = face->background;
1071 
1072 	      BView_StartClip (view);
1073 	      BView_SetHighColor (view, bkg);
1074 	      BView_FillRectangle (view, x, y, w, h);
1075 	      BView_EndClip (view);
1076 	    }
1077 	}
1078     }
1079   else if (!s->background_filled_p)
1080     {
1081       int background_width = s->background_width;
1082       int x = s->x, text_left_x = window_box_left (s->w, TEXT_AREA);
1083 
1084       /* Don't draw into left fringe or scrollbar area except for
1085          header line and mode line.  */
1086       if (s->area == TEXT_AREA
1087 	  && x < text_left_x && !s->row->mode_line_p)
1088 	{
1089 	  background_width -= text_left_x - x;
1090 	  x = text_left_x;
1091 	}
1092 
1093       if (background_width > 0)
1094 	{
1095 	  void *view = FRAME_HAIKU_VIEW (s->f);
1096 	  BView_StartClip (view);
1097 	  uint32_t bkg;
1098 	  if (s->hl == DRAW_MOUSE_FACE)
1099 	    haiku_mouse_face_colors (s, NULL, &bkg);
1100 	  else if (s->hl == DRAW_CURSOR)
1101 	    bkg = FRAME_CURSOR_COLOR (s->f).pixel;
1102 	  else
1103 	    bkg = s->face->background;
1104 
1105 	  BView_SetHighColor (view, bkg);
1106 	  BView_FillRectangle (view, x, s->y, background_width, s->height);
1107 	  BView_EndClip (view);
1108 	}
1109     }
1110   s->background_filled_p = 1;
1111 }
1112 
1113 static void
haiku_start_clip(struct glyph_string * s)1114 haiku_start_clip (struct glyph_string *s)
1115 {
1116   void *view = FRAME_HAIKU_VIEW (s->f);
1117   BView_draw_lock (view);
1118   BView_StartClip (view);
1119 }
1120 
1121 static void
haiku_end_clip(struct glyph_string * s)1122 haiku_end_clip (struct glyph_string *s)
1123 {
1124   void *view = FRAME_HAIKU_VIEW (s->f);
1125   BView_EndClip (view);
1126   BView_draw_unlock (view);
1127 }
1128 
1129 static void
haiku_clip_to_row(struct window * w,struct glyph_row * row,enum glyph_row_area area)1130 haiku_clip_to_row (struct window *w, struct glyph_row *row,
1131 		   enum glyph_row_area area)
1132 {
1133   struct frame *f = WINDOW_XFRAME (w);
1134   int window_x, window_y, window_width;
1135   int x, y, width, height;
1136 
1137   window_box (w, area, &window_x, &window_y, &window_width, 0);
1138 
1139   x = window_x;
1140   y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
1141   y = max (y, window_y);
1142   width = window_width;
1143   height = row->visible_height;
1144 
1145   BView_ClipToRect (FRAME_HAIKU_VIEW (f), x, y, width, height);
1146 }
1147 
1148 static void
haiku_update_begin(struct frame * f)1149 haiku_update_begin (struct frame *f)
1150 {
1151 }
1152 
1153 static void
haiku_update_end(struct frame * f)1154 haiku_update_end (struct frame *f)
1155 {
1156   MOUSE_HL_INFO (f)->mouse_face_defer = false;
1157   flush_frame (f);
1158 }
1159 
1160 static void
haiku_draw_composite_glyph_string_foreground(struct glyph_string * s)1161 haiku_draw_composite_glyph_string_foreground (struct glyph_string *s)
1162 {
1163   int i, j, x;
1164   struct font *font = s->font;
1165   void *view = FRAME_HAIKU_VIEW (s->f);
1166   struct face *face = s->face;
1167 
1168   /* If first glyph of S has a left box line, start drawing the text
1169      of S to the right of that box line.  */
1170   if (face && face->box != FACE_NO_BOX
1171       && s->first_glyph->left_box_line_p)
1172     x = s->x + max (face->box_vertical_line_width, 0);
1173   else
1174     x = s->x;
1175 
1176   /* S is a glyph string for a composition.  S->cmp_from is the index
1177      of the first character drawn for glyphs of this composition.
1178      S->cmp_from == 0 means we are drawing the very first character of
1179      this composition.  */
1180 
1181   /* Draw a rectangle for the composition if the font for the very
1182      first character of the composition could not be loaded.  */
1183 
1184   if (s->font_not_found_p && !s->cmp_from)
1185     {
1186       BView_StartClip (view);
1187       if (s->hl == DRAW_CURSOR)
1188 	BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
1189       else
1190 	BView_SetHighColor (view, s->face->foreground);
1191       BView_StrokeRectangle (view, s->x, s->y, s->width - 1, s->height - 1);
1192       BView_EndClip (view);
1193     }
1194   else if (!s->first_glyph->u.cmp.automatic)
1195     {
1196       int y = s->ybase;
1197 
1198       for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1199 	/* TAB in a composition means display glyphs with padding
1200 	   space on the left or right.  */
1201 	if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1202 	  {
1203 	    int xx = x + s->cmp->offsets[j * 2];
1204 	    int yy = y - s->cmp->offsets[j * 2 + 1];
1205 
1206 	    font->driver->draw (s, j, j + 1, xx, yy, false);
1207 	    if (face->overstrike)
1208 	      font->driver->draw (s, j, j + 1, xx + 1, yy, false);
1209 	  }
1210     }
1211   else
1212     {
1213       Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1214       Lisp_Object glyph;
1215       int y = s->ybase;
1216       int width = 0;
1217 
1218       for (i = j = s->cmp_from; i < s->cmp_to; i++)
1219 	{
1220 	  glyph = LGSTRING_GLYPH (gstring, i);
1221 	  if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1222 	    width += LGLYPH_WIDTH (glyph);
1223 	  else
1224 	    {
1225 	      int xoff, yoff, wadjust;
1226 
1227 	      if (j < i)
1228 		{
1229 		  font->driver->draw (s, j, i, x, y, false);
1230 		  if (s->face->overstrike)
1231 		    font->driver->draw (s, j, i, x + 1, y, false);
1232 		  x += width;
1233 		}
1234 	      xoff = LGLYPH_XOFF (glyph);
1235 	      yoff = LGLYPH_YOFF (glyph);
1236 	      wadjust = LGLYPH_WADJUST (glyph);
1237 	      font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
1238 	      if (face->overstrike)
1239 		font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
1240 				    false);
1241 	      x += wadjust;
1242 	      j = i + 1;
1243 	      width = 0;
1244 	    }
1245 	}
1246       if (j < i)
1247 	{
1248 	  font->driver->draw (s, j, i, x, y, false);
1249 	  if (face->overstrike)
1250 	    font->driver->draw (s, j, i, x + 1, y, false);
1251 	}
1252     }
1253 }
1254 
1255 static void
haiku_draw_image_relief(struct glyph_string * s)1256 haiku_draw_image_relief (struct glyph_string *s)
1257 {
1258   int x1, y1, thick;
1259   bool raised_p, top_p, bot_p, left_p, right_p;
1260   int extra_x, extra_y;
1261   struct haiku_rect r;
1262   int x = s->x;
1263   int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1264 
1265   struct face *face = s->face;
1266 
1267   /* If first glyph of S has a left box line, start drawing it to the
1268      right of that line.  */
1269   if (face->box != FACE_NO_BOX
1270       && s->first_glyph->left_box_line_p
1271       && s->slice.x == 0)
1272     x += max (face->box_vertical_line_width, 0);
1273 
1274   /* If there is a margin around the image, adjust x- and y-position
1275      by that margin.  */
1276   if (s->slice.x == 0)
1277     x += s->img->hmargin;
1278   if (s->slice.y == 0)
1279     y += s->img->vmargin;
1280 
1281   if (s->hl == DRAW_IMAGE_SUNKEN
1282       || s->hl == DRAW_IMAGE_RAISED)
1283     {
1284       if (s->face->id == TAB_BAR_FACE_ID)
1285 	thick = (tab_bar_button_relief < 0
1286 		 ? DEFAULT_TAB_BAR_BUTTON_RELIEF
1287 		 : min (tab_bar_button_relief, 1000000));
1288       else
1289 	thick = (tool_bar_button_relief < 0
1290 		 ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
1291 		 : min (tool_bar_button_relief, 1000000));
1292       raised_p = s->hl == DRAW_IMAGE_RAISED;
1293     }
1294   else
1295     {
1296       thick = eabs (s->img->relief);
1297       raised_p = s->img->relief > 0;
1298     }
1299 
1300   x1 = x + s->slice.width - 1;
1301   y1 = y + s->slice.height - 1;
1302 
1303   extra_x = extra_y = 0;
1304 
1305   if (s->face->id == TAB_BAR_FACE_ID)
1306     {
1307       if (CONSP (Vtab_bar_button_margin)
1308 	  && FIXNUMP (XCAR (Vtab_bar_button_margin))
1309 	  && FIXNUMP (XCDR (Vtab_bar_button_margin)))
1310 	{
1311 	  extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)) - thick;
1312 	  extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)) - thick;
1313 	}
1314       else if (FIXNUMP (Vtab_bar_button_margin))
1315 	extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin) - thick;
1316     }
1317 
1318   if (s->face->id == TOOL_BAR_FACE_ID)
1319     {
1320       if (CONSP (Vtool_bar_button_margin)
1321 	  && FIXNUMP (XCAR (Vtool_bar_button_margin))
1322 	  && FIXNUMP (XCDR (Vtool_bar_button_margin)))
1323 	{
1324 	  extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin));
1325 	  extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin));
1326 	}
1327       else if (FIXNUMP (Vtool_bar_button_margin))
1328 	extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin);
1329     }
1330 
1331   top_p = bot_p = left_p = right_p = 0;
1332 
1333   if (s->slice.x == 0)
1334     x -= thick + extra_x, left_p = 1;
1335   if (s->slice.y == 0)
1336     y -= thick + extra_y, top_p = 1;
1337   if (s->slice.x + s->slice.width == s->img->width)
1338     x1 += thick + extra_x, right_p = 1;
1339   if (s->slice.y + s->slice.height == s->img->height)
1340     y1 += thick + extra_y, bot_p = 1;
1341 
1342   get_glyph_string_clip_rect (s, &r);
1343   haiku_draw_relief_rect (s, x, y, x1, y1, thick, thick, raised_p,
1344 			  top_p, bot_p, left_p, right_p, &r, 0);
1345 }
1346 
1347 static void
haiku_draw_image_glyph_string(struct glyph_string * s)1348 haiku_draw_image_glyph_string (struct glyph_string *s)
1349 {
1350   struct face *face = s->face;
1351 
1352   int box_line_hwidth = max (face->box_vertical_line_width, 0);
1353   int box_line_vwidth = max (face->box_horizontal_line_width, 0);
1354 
1355   int x, y;
1356   int height, width;
1357 
1358   height = s->height;
1359   if (s->slice.y == 0)
1360     height -= box_line_vwidth;
1361   if (s->slice.y + s->slice.height >= s->img->height)
1362     height -= box_line_vwidth;
1363 
1364   width = s->background_width;
1365   x = s->x;
1366   if (s->first_glyph->left_box_line_p
1367       && s->slice.x == 0)
1368     {
1369       x += box_line_hwidth;
1370       width -= box_line_hwidth;
1371     }
1372 
1373   y = s->y;
1374   if (s->slice.y == 0)
1375     y += box_line_vwidth;
1376 
1377   void *view = FRAME_HAIKU_VIEW (s->f);
1378   void *bitmap = s->img->pixmap;
1379 
1380   s->stippled_p = face->stipple != 0;
1381 
1382   BView_draw_lock (view);
1383   BView_StartClip (view);
1384   BView_SetHighColor (view, face->background);
1385   BView_FillRectangle (view, x, y, width, height);
1386   BView_EndClip (view);
1387   BView_draw_unlock (view);
1388 
1389   if (bitmap)
1390     {
1391       struct haiku_rect nr;
1392       Emacs_Rectangle cr, ir, r;
1393 
1394       get_glyph_string_clip_rect (s, &nr);
1395       CONVERT_TO_EMACS_RECT (cr, nr);
1396       x = s->x;
1397       y = s->ybase - image_ascent (s->img, face, &s->slice);
1398 
1399       if (s->slice.x == 0)
1400 	x += s->img->hmargin;
1401       if (s->slice.y == 0)
1402 	y += s->img->vmargin;
1403 
1404       if (face->box != FACE_NO_BOX
1405 	  && s->first_glyph->left_box_line_p
1406 	  && s->slice.x == 0)
1407 	x += max (face->box_vertical_line_width, 0);
1408 
1409       ir.x = x;
1410       ir.y = y;
1411       ir.width = s->slice.width;
1412       ir.height = s->slice.height;
1413       r = ir;
1414 
1415       void *mask = s->img->mask;
1416 
1417       if (gui_intersect_rectangles (&cr, &ir, &r))
1418 	{
1419 	  BView_draw_lock (view);
1420 	  BView_StartClip (view);
1421 
1422 	  haiku_clip_to_string (s);
1423 	  if (s->img->have_be_transforms_p)
1424 	    {
1425 	      bitmap = BBitmap_transform_bitmap (bitmap,
1426 						 s->img->mask,
1427 						 face->background,
1428 						 s->img->be_rotate,
1429 						 s->img->width,
1430 						 s->img->height);
1431 	      mask = NULL;
1432 	    }
1433 
1434 	  BView_DrawBitmap (view, bitmap,
1435 			    s->slice.x + r.x - x,
1436 			    s->slice.y + r.y - y,
1437 			    r.width, r.height,
1438 			    r.x, r.y, r.width, r.height);
1439 	  if (mask)
1440 	    {
1441 	      BView_DrawMask (mask, view,
1442 			      s->slice.x + r.x - x,
1443 			      s->slice.y + r.y - y,
1444 			      r.width, r.height,
1445 			      r.x, r.y, r.width, r.height,
1446 			      face->background);
1447 	    }
1448 
1449 	  if (s->img->have_be_transforms_p)
1450 	    BBitmap_free (bitmap);
1451 	  BView_EndClip (view);
1452 	  BView_draw_unlock (view);
1453 	}
1454 
1455       if (s->hl == DRAW_CURSOR)
1456 	{
1457 	  BView_draw_lock (view);
1458 	  BView_StartClip (view);
1459 	  BView_SetPenSize (view, 1);
1460 	  BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel);
1461 	  BView_StrokeRectangle (view, r.x, r.y, r.width, r.height);
1462 	  BView_EndClip (view);
1463 	  BView_draw_unlock (view);
1464 	}
1465     }
1466 
1467   if (s->img->relief
1468       || s->hl == DRAW_IMAGE_RAISED
1469       || s->hl == DRAW_IMAGE_SUNKEN)
1470     haiku_draw_image_relief (s);
1471 }
1472 
1473 static void
haiku_draw_glyph_string(struct glyph_string * s)1474 haiku_draw_glyph_string (struct glyph_string *s)
1475 {
1476   block_input ();
1477   prepare_face_for_display (s->f, s->face);
1478 
1479   struct face *face = s->face;
1480   if (face != s->face)
1481     prepare_face_for_display (s->f, face);
1482 
1483   if (s->next && s->right_overhang && !s->for_overlaps)
1484     {
1485       int width;
1486       struct glyph_string *next;
1487 
1488       for (width = 0, next = s->next;
1489 	   next && width < s->right_overhang;
1490 	   width += next->width, next = next->next)
1491 	if (next->first_glyph->type != IMAGE_GLYPH)
1492           {
1493 	    prepare_face_for_display (s->f, s->next->face);
1494 	    haiku_start_clip (s->next);
1495 	    haiku_clip_to_string (s->next);
1496             if (next->first_glyph->type != STRETCH_GLYPH)
1497 	      haiku_maybe_draw_background (s->next, 1);
1498             else
1499 	      haiku_draw_stretch_glyph_string (s->next);
1500             next->num_clips = 0;
1501 	    haiku_end_clip (s);
1502           }
1503     }
1504 
1505   haiku_start_clip (s);
1506 
1507   int box_filled_p = 0;
1508 
1509   if (!s->for_overlaps && face->box != FACE_NO_BOX
1510       && (s->first_glyph->type == CHAR_GLYPH
1511 	  || s->first_glyph->type == COMPOSITE_GLYPH))
1512     {
1513       haiku_clip_to_string (s);
1514       haiku_maybe_draw_background (s, 1);
1515       box_filled_p = 1;
1516       haiku_draw_string_box (s, 0);
1517     }
1518   else if (!s->clip_head && !s->clip_tail &&
1519 	   ((s->prev && s->left_overhang && s->prev->hl != s->hl) ||
1520 	    (s->next && s->right_overhang && s->next->hl != s->hl)))
1521     haiku_clip_to_string_exactly (s, s);
1522   else
1523     haiku_clip_to_string (s);
1524 
1525   if (s->for_overlaps)
1526     s->background_filled_p = 1;
1527 
1528   switch (s->first_glyph->type)
1529     {
1530     case COMPOSITE_GLYPH:
1531       if (s->for_overlaps || (s->cmp_from > 0
1532 			      && ! s->first_glyph->u.cmp.automatic))
1533 	s->background_filled_p = 1;
1534       else
1535 	haiku_maybe_draw_background (s, 1);
1536       haiku_draw_composite_glyph_string_foreground (s);
1537       break;
1538     case CHAR_GLYPH:
1539       if (s->for_overlaps)
1540 	s->background_filled_p = 1;
1541       else
1542 	haiku_maybe_draw_background (s, 0);
1543       haiku_draw_glyph_string_foreground (s);
1544       break;
1545     case STRETCH_GLYPH:
1546       haiku_draw_stretch_glyph_string (s);
1547       break;
1548     case IMAGE_GLYPH:
1549       haiku_draw_image_glyph_string (s);
1550       break;
1551     case GLYPHLESS_GLYPH:
1552       if (s->for_overlaps)
1553 	s->background_filled_p = 1;
1554       else
1555 	haiku_maybe_draw_background (s, 1);
1556       haiku_draw_glyphless_glyph_string_foreground (s);
1557       break;
1558     }
1559 
1560   if (!box_filled_p && face->box != FACE_NO_BOX)
1561     haiku_draw_string_box (s, 1);
1562   else
1563     haiku_draw_text_decoration (s, face, face->foreground, s->width, s->x);
1564 
1565   if (!s->for_overlaps)
1566     {
1567       if (s->prev)
1568 	{
1569 	  struct glyph_string *prev;
1570 
1571 	  for (prev = s->prev; prev; prev = prev->prev)
1572 	    if (prev->hl != s->hl
1573 		&& prev->x + prev->width + prev->right_overhang > s->x)
1574 	      {
1575 		/* As prev was drawn while clipped to its own area, we
1576 		   must draw the right_overhang part using s->hl now.  */
1577 		enum draw_glyphs_face save = prev->hl;
1578 		struct face *save_face = prev->face;
1579 
1580 		prev->hl = s->hl;
1581 		prev->face = s->face;
1582 		haiku_start_clip (s);
1583 		haiku_clip_to_string_exactly (s, prev);
1584 		if (prev->first_glyph->type == CHAR_GLYPH)
1585 		  haiku_draw_glyph_string_foreground (prev);
1586 		else
1587 		  haiku_draw_composite_glyph_string_foreground (prev);
1588 		haiku_end_clip (s);
1589 		prev->hl = save;
1590 		prev->face = save_face;
1591 		prev->num_clips = 0;
1592 	      }
1593 	}
1594 
1595       if (s->next)
1596 	{
1597 	  struct glyph_string *next;
1598 
1599 	  for (next = s->next; next; next = next->next)
1600 	    if (next->hl != s->hl
1601 		&& next->x - next->left_overhang < s->x + s->width)
1602 	      {
1603 		/* As next will be drawn while clipped to its own area,
1604 		   we must draw the left_overhang part using s->hl now.  */
1605 		enum draw_glyphs_face save = next->hl;
1606 		struct face *save_face = next->face;
1607 
1608 		next->hl = s->hl;
1609 		next->face = s->face;
1610 		haiku_start_clip (s);
1611 		haiku_clip_to_string_exactly (s, next);
1612 		if (next->first_glyph->type == CHAR_GLYPH)
1613 		  haiku_draw_glyph_string_foreground (next);
1614 		else
1615 		  haiku_draw_composite_glyph_string_foreground (next);
1616 		haiku_end_clip (s);
1617 
1618 		next->background_filled_p = 0;
1619 		next->hl = save;
1620 		next->face = save_face;
1621 		next->clip_head = next;
1622 		next->num_clips = 0;
1623 	      }
1624 	}
1625     }
1626   s->num_clips = 0;
1627   haiku_end_clip (s);
1628   unblock_input ();
1629 }
1630 
1631 static void
haiku_after_update_window_line(struct window * w,struct glyph_row * desired_row)1632 haiku_after_update_window_line (struct window *w,
1633 				struct glyph_row *desired_row)
1634 {
1635   eassert (w);
1636   struct frame *f;
1637   int width, height;
1638 
1639   if (!desired_row->mode_line_p && !w->pseudo_window_p)
1640     desired_row->redraw_fringe_bitmaps_p = true;
1641 
1642   if (windows_or_buffers_changed
1643       && desired_row->full_width_p
1644       && (f = XFRAME (w->frame),
1645 	  width = FRAME_INTERNAL_BORDER_WIDTH (f),
1646 	  width != 0)
1647       && (height = desired_row->visible_height,
1648 	  height > 0))
1649     {
1650       int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1651       int face_id =
1652         !NILP (Vface_remapping_alist)
1653         ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
1654         : INTERNAL_BORDER_FACE_ID;
1655       struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
1656 
1657       block_input ();
1658       if (face)
1659 	{
1660 	  void *view = FRAME_HAIKU_VIEW (f);
1661 	  BView_draw_lock (view);
1662 	  BView_StartClip (view);
1663 	  BView_SetHighColor (view, face->background_defaulted_p ?
1664 			      FRAME_BACKGROUND_PIXEL (f) : face->background);
1665 	  BView_FillRectangle (view, 0, y, width, height);
1666 	  BView_FillRectangle (view, FRAME_PIXEL_WIDTH (f) - width,
1667 			       y, width, height);
1668 	  BView_EndClip (view);
1669 	  BView_draw_unlock (view);
1670 	}
1671       else
1672 	{
1673 	  haiku_clear_frame_area (f, 0, y, width, height);
1674 	  haiku_clear_frame_area (f, FRAME_PIXEL_WIDTH (f) - width,
1675 				  y, width, height);
1676 	}
1677       unblock_input ();
1678     }
1679 }
1680 
1681 static void
haiku_set_window_size(struct frame * f,bool change_gravity,int width,int height)1682 haiku_set_window_size (struct frame *f, bool change_gravity,
1683 		       int width, int height)
1684 {
1685   haiku_update_size_hints (f);
1686 
1687   if (FRAME_HAIKU_WINDOW (f))
1688     {
1689       block_input ();
1690       BWindow_resize (FRAME_HAIKU_WINDOW (f), width, height);
1691       unblock_input ();
1692     }
1693 }
1694 
1695 static void
haiku_draw_window_cursor(struct window * w,struct glyph_row * glyph_row,int x,int y,enum text_cursor_kinds cursor_type,int cursor_width,bool on_p,bool active_p)1696 haiku_draw_window_cursor (struct window *w,
1697 			  struct glyph_row *glyph_row,
1698 			  int x, int y,
1699 			  enum text_cursor_kinds cursor_type,
1700 			  int cursor_width, bool on_p, bool active_p)
1701 {
1702   struct frame *f = XFRAME (WINDOW_FRAME (w));
1703 
1704   struct glyph *phys_cursor_glyph;
1705   struct glyph *cursor_glyph;
1706 
1707   void *view = FRAME_HAIKU_VIEW (f);
1708 
1709   int fx, fy, h, cursor_height;
1710 
1711   if (!on_p)
1712     return;
1713 
1714   if (cursor_type == NO_CURSOR)
1715     {
1716       w->phys_cursor_width = 0;
1717       return;
1718     }
1719 
1720   w->phys_cursor_on_p = true;
1721   w->phys_cursor_type = cursor_type;
1722 
1723   phys_cursor_glyph = get_phys_cursor_glyph (w);
1724 
1725   if (!phys_cursor_glyph)
1726     {
1727       if (glyph_row->exact_window_width_line_p
1728           && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
1729         {
1730           glyph_row->cursor_in_fringe_p = 1;
1731           draw_fringe_bitmap (w, glyph_row, 0);
1732         }
1733       return;
1734     }
1735 
1736   get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h);
1737 
1738   if (cursor_type == BAR_CURSOR)
1739     {
1740       if (cursor_width < 1)
1741 	cursor_width = max (FRAME_CURSOR_WIDTH (f), 1);
1742       if (cursor_width < w->phys_cursor_width)
1743         w->phys_cursor_width = cursor_width;
1744     }
1745   else if (cursor_type == HBAR_CURSOR)
1746     {
1747       cursor_height = (cursor_width < 1) ? lrint (0.25 * h) : cursor_width;
1748       if (cursor_height > glyph_row->height)
1749         cursor_height = glyph_row->height;
1750       if (h > cursor_height)
1751         fy += h - cursor_height;
1752       h = cursor_height;
1753     }
1754 
1755   BView_draw_lock (view);
1756   BView_StartClip (view);
1757   BView_SetHighColor (view, FRAME_CURSOR_COLOR (f).pixel);
1758   haiku_clip_to_row (w, glyph_row, TEXT_AREA);
1759 
1760   switch (cursor_type)
1761     {
1762     default:
1763     case DEFAULT_CURSOR:
1764     case NO_CURSOR:
1765       break;
1766     case HBAR_CURSOR:
1767       BView_FillRectangle (view, fx, fy, w->phys_cursor_width, h);
1768       break;
1769     case BAR_CURSOR:
1770       cursor_glyph = get_phys_cursor_glyph (w);
1771       if (cursor_glyph->resolved_level & 1)
1772 	BView_FillRectangle (view, fx + cursor_glyph->pixel_width - w->phys_cursor_width,
1773 			     fy, w->phys_cursor_width, h);
1774       else
1775 	BView_FillRectangle (view, fx, fy, w->phys_cursor_width, h);
1776       break;
1777     case HOLLOW_BOX_CURSOR:
1778       if (phys_cursor_glyph->type != IMAGE_GLYPH)
1779 	{
1780 	  BView_SetPenSize (view, 1);
1781 	  BView_StrokeRectangle (view, fx, fy, w->phys_cursor_width, h);
1782 	}
1783       else
1784 	draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
1785       break;
1786     case FILLED_BOX_CURSOR:
1787       draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
1788     }
1789   BView_EndClip (view);
1790   BView_draw_unlock (view);
1791 }
1792 
1793 static void
haiku_show_hourglass(struct frame * f)1794 haiku_show_hourglass (struct frame *f)
1795 {
1796   if (FRAME_OUTPUT_DATA (f)->hourglass_p)
1797     return;
1798 
1799   block_input ();
1800   FRAME_OUTPUT_DATA (f)->hourglass_p = 1;
1801 
1802   if (FRAME_HAIKU_VIEW (f))
1803     BView_set_view_cursor (FRAME_HAIKU_VIEW (f),
1804 			   FRAME_OUTPUT_DATA (f)->hourglass_cursor);
1805   unblock_input ();
1806 }
1807 
1808 static void
haiku_hide_hourglass(struct frame * f)1809 haiku_hide_hourglass (struct frame *f)
1810 {
1811   if (!FRAME_OUTPUT_DATA (f)->hourglass_p)
1812     return;
1813 
1814   block_input ();
1815   FRAME_OUTPUT_DATA (f)->hourglass_p = 0;
1816 
1817   if (FRAME_HAIKU_VIEW (f))
1818     BView_set_view_cursor (FRAME_HAIKU_VIEW (f),
1819 			   FRAME_OUTPUT_DATA (f)->current_cursor);
1820   unblock_input ();
1821 }
1822 
1823 static void
haiku_compute_glyph_string_overhangs(struct glyph_string * s)1824 haiku_compute_glyph_string_overhangs (struct glyph_string *s)
1825 {
1826   if (s->cmp == NULL
1827       && (s->first_glyph->type == CHAR_GLYPH
1828 	  || s->first_glyph->type == COMPOSITE_GLYPH))
1829     {
1830       struct font_metrics metrics;
1831 
1832       if (s->first_glyph->type == CHAR_GLYPH)
1833 	{
1834 	  struct font *font = s->font;
1835 	  font->driver->text_extents (font, s->char2b, s->nchars, &metrics);
1836 	}
1837       else
1838 	{
1839 	  Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1840 
1841 	  composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
1842 	}
1843       s->right_overhang = (metrics.rbearing > metrics.width
1844 			   ? metrics.rbearing - metrics.width : 0);
1845       s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
1846     }
1847   else if (s->cmp)
1848     {
1849       s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1850       s->left_overhang = - s->cmp->lbearing;
1851     }
1852 }
1853 
1854 static void
haiku_draw_vertical_window_border(struct window * w,int x,int y_0,int y_1)1855 haiku_draw_vertical_window_border (struct window *w,
1856 				   int x, int y_0, int y_1)
1857 {
1858   struct frame *f = XFRAME (WINDOW_FRAME (w));
1859   struct face *face;
1860 
1861   face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
1862   void *view = FRAME_HAIKU_VIEW (f);
1863   BView_draw_lock (view);
1864   BView_StartClip (view);
1865   if (face)
1866     BView_SetHighColor (view, face->foreground);
1867   BView_StrokeLine (view, x, y_0, x, y_1);
1868   BView_EndClip (view);
1869   BView_draw_unlock (view);
1870 }
1871 
1872 static void
haiku_set_scroll_bar_default_width(struct frame * f)1873 haiku_set_scroll_bar_default_width (struct frame *f)
1874 {
1875   int unit = FRAME_COLUMN_WIDTH (f);
1876   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = BScrollBar_default_size (0) + 1;
1877   FRAME_CONFIG_SCROLL_BAR_COLS (f) =
1878     (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
1879 }
1880 
1881 static void
haiku_set_scroll_bar_default_height(struct frame * f)1882 haiku_set_scroll_bar_default_height (struct frame *f)
1883 {
1884   int height = FRAME_LINE_HEIGHT (f);
1885   FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = BScrollBar_default_size (1) + 1;
1886   FRAME_CONFIG_SCROLL_BAR_LINES (f) =
1887     (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + height - 1) / height;
1888 }
1889 
1890 static void
haiku_draw_window_divider(struct window * w,int x0,int x1,int y0,int y1)1891 haiku_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
1892 {
1893   struct frame *f = XFRAME (WINDOW_FRAME (w));
1894   struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
1895   struct face *face_first
1896     = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
1897   struct face *face_last
1898     = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
1899   unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
1900   unsigned long color_first = (face_first
1901 			       ? face_first->foreground
1902 			       : FRAME_FOREGROUND_PIXEL (f));
1903   unsigned long color_last = (face_last
1904 			      ? face_last->foreground
1905 			      : FRAME_FOREGROUND_PIXEL (f));
1906   void *view = FRAME_HAIKU_VIEW (f);
1907 
1908   BView_draw_lock (view);
1909   BView_StartClip (view);
1910 
1911   if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
1912     /* A vertical divider, at least three pixels wide: Draw first and
1913        last pixels differently.  */
1914     {
1915       BView_SetHighColor (view, color_first);
1916       BView_StrokeLine (view, x0, y0, x0, y1 - 1);
1917       BView_SetHighColor (view, color);
1918       BView_FillRectangle (view, x0 + 1, y0, x1 - x0 - 2, y1 - y0);
1919       BView_SetHighColor (view, color_last);
1920       BView_StrokeLine (view, x1 - 1, y0, x1 - 1, y1 - 1);
1921     }
1922   else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
1923     /* A horizontal divider, at least three pixels high: Draw first and
1924        last pixels differently.  */
1925     {
1926       BView_SetHighColor (view, color_first);
1927       BView_StrokeLine (f, x0, y0, x1 - 1, y0);
1928       BView_SetHighColor (view, color);
1929       BView_FillRectangle (view, x0, y0 + 1, x1 - x0, y1 - y0 - 2);
1930       BView_SetHighColor (view, color_last);
1931       BView_StrokeLine (view, x0, y1, x1 - 1, y1);
1932     }
1933   else
1934     {
1935       BView_SetHighColor (view, color);
1936       BView_FillRectangleAbs (view, x0, y0, x1, y1);
1937     }
1938   BView_EndClip (view);
1939   BView_draw_unlock (view);
1940 }
1941 
1942 static void
haiku_condemn_scroll_bars(struct frame * frame)1943 haiku_condemn_scroll_bars (struct frame *frame)
1944 {
1945   if (!NILP (FRAME_SCROLL_BARS (frame)))
1946     {
1947       if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
1948 	{
1949 	  /* Prepend scrollbars to already condemned ones.  */
1950 	  Lisp_Object last = FRAME_SCROLL_BARS (frame);
1951 
1952 	  while (!NILP (XSCROLL_BAR (last)->next))
1953 	    last = XSCROLL_BAR (last)->next;
1954 
1955 	  XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
1956 	  XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
1957 	}
1958 
1959       fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
1960       fset_scroll_bars (frame, Qnil);
1961     }
1962 }
1963 
1964 static void
haiku_redeem_scroll_bar(struct window * w)1965 haiku_redeem_scroll_bar (struct window *w)
1966 {
1967   struct scroll_bar *bar;
1968   Lisp_Object barobj;
1969   struct frame *f;
1970 
1971   if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
1972     {
1973       bar = XSCROLL_BAR (w->vertical_scroll_bar);
1974       /* Unlink it from the condemned list.  */
1975       f = XFRAME (WINDOW_FRAME (w));
1976       if (NILP (bar->prev))
1977 	{
1978 	  /* If the prev pointer is nil, it must be the first in one of
1979 	     the lists.  */
1980 	  if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
1981 	    /* It's not condemned.  Everything's fine.  */
1982 	    goto horizontal;
1983 	  else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
1984 		       w->vertical_scroll_bar))
1985 	    fset_condemned_scroll_bars (f, bar->next);
1986 	  else
1987 	    /* If its prev pointer is nil, it must be at the front of
1988 	       one or the other!  */
1989 	    emacs_abort ();
1990 	}
1991       else
1992 	XSCROLL_BAR (bar->prev)->next = bar->next;
1993 
1994       if (! NILP (bar->next))
1995 	XSCROLL_BAR (bar->next)->prev = bar->prev;
1996 
1997       bar->next = FRAME_SCROLL_BARS (f);
1998       bar->prev = Qnil;
1999       XSETVECTOR (barobj, bar);
2000       fset_scroll_bars (f, barobj);
2001       if (! NILP (bar->next))
2002 	XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2003     }
2004  horizontal:
2005   if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
2006     {
2007       bar = XSCROLL_BAR (w->horizontal_scroll_bar);
2008       /* Unlink it from the condemned list.  */
2009       f = XFRAME (WINDOW_FRAME (w));
2010       if (NILP (bar->prev))
2011 	{
2012 	  /* If the prev pointer is nil, it must be the first in one of
2013 	     the lists.  */
2014 	  if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
2015 	    /* It's not condemned.  Everything's fine.  */
2016 	    return;
2017 	  else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2018 		       w->horizontal_scroll_bar))
2019 	    fset_condemned_scroll_bars (f, bar->next);
2020 	  else
2021 	    /* If its prev pointer is nil, it must be at the front of
2022 	       one or the other!  */
2023 	    emacs_abort ();
2024 	}
2025       else
2026 	XSCROLL_BAR (bar->prev)->next = bar->next;
2027 
2028       if (! NILP (bar->next))
2029 	XSCROLL_BAR (bar->next)->prev = bar->prev;
2030 
2031       bar->next = FRAME_SCROLL_BARS (f);
2032       bar->prev = Qnil;
2033       XSETVECTOR (barobj, bar);
2034       fset_scroll_bars (f, barobj);
2035       if (! NILP (bar->next))
2036 	XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2037     }
2038 }
2039 
2040 static void
haiku_judge_scroll_bars(struct frame * f)2041 haiku_judge_scroll_bars (struct frame *f)
2042 {
2043   Lisp_Object bar, next;
2044 
2045   bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2046 
2047   /* Clear out the condemned list now so we won't try to process any
2048      more events on the hapless scroll bars.  */
2049   fset_condemned_scroll_bars (f, Qnil);
2050 
2051   for (; ! NILP (bar); bar = next)
2052     {
2053       struct scroll_bar *b = XSCROLL_BAR (bar);
2054 
2055       haiku_scroll_bar_remove (b);
2056 
2057       next = b->next;
2058       b->next = b->prev = Qnil;
2059     }
2060 
2061   /* Now there should be no references to the condemned scroll bars,
2062      and they should get garbage-collected.  */
2063 }
2064 
2065 static struct scroll_bar *
haiku_scroll_bar_create(struct window * w,int left,int top,int width,int height,bool horizontal_p)2066 haiku_scroll_bar_create (struct window *w, int left, int top,
2067 			 int width, int height, bool horizontal_p)
2068 {
2069   struct frame *f = XFRAME (WINDOW_FRAME (w));
2070   Lisp_Object barobj;
2071 
2072   void *sb = NULL;
2073   void *vw = FRAME_HAIKU_VIEW (f);
2074 
2075   block_input ();
2076   struct scroll_bar *bar
2077     = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER);
2078 
2079   XSETWINDOW (bar->window, w);
2080   bar->top = top;
2081   bar->left = left;
2082   bar->width = width;
2083   bar->height = height;
2084   bar->position = 0;
2085   bar->total = 0;
2086   bar->dragging = 0;
2087   bar->update = -1;
2088   bar->horizontal = horizontal_p;
2089 
2090   sb = BScrollBar_make_for_view (vw, horizontal_p,
2091 				 left, top, left + width - 1,
2092 				 top + height - 1, bar);
2093 
2094   BView_publish_scroll_bar (vw, left, top, width, height);
2095 
2096   bar->next = FRAME_SCROLL_BARS (f);
2097   bar->prev = Qnil;
2098   bar->scroll_bar = sb;
2099   XSETVECTOR (barobj, bar);
2100   fset_scroll_bars (f, barobj);
2101 
2102   if (!NILP (bar->next))
2103     XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2104 
2105   unblock_input ();
2106   return bar;
2107 }
2108 
2109 static void
haiku_set_horizontal_scroll_bar(struct window * w,int portion,int whole,int position)2110 haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int position)
2111 {
2112   eassert (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w));
2113   Lisp_Object barobj;
2114   struct scroll_bar *bar;
2115   int top, height, left, width;
2116   int window_x, window_width;
2117 
2118   /* Get window dimensions.  */
2119   window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
2120   left = window_x;
2121   width = window_width;
2122   top = WINDOW_SCROLL_BAR_AREA_Y (w);
2123   height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
2124 
2125   block_input ();
2126 
2127   if (NILP (w->horizontal_scroll_bar))
2128     {
2129       bar = haiku_scroll_bar_create (w, left, top, width, height, true);
2130       BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
2131       bar->update = position;
2132       bar->position = position;
2133       bar->total = whole;
2134     }
2135   else
2136     {
2137       bar = XSCROLL_BAR (w->horizontal_scroll_bar);
2138 
2139       if (bar->left != left || bar->top != top ||
2140 	  bar->width != width || bar->height != height)
2141 	{
2142 	  void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w));
2143 	  BView_forget_scroll_bar (view, bar->left, bar->top,
2144 				   bar->width, bar->height);
2145 	  BView_move_frame (bar->scroll_bar, left, top,
2146 			    left + width - 1, top + height - 1);
2147 	  BView_publish_scroll_bar (view, left, top, width, height);
2148 	  bar->left = left;
2149 	  bar->top = top;
2150 	  bar->width = width;
2151 	  bar->height = height;
2152 	}
2153 
2154       if (!bar->dragging)
2155 	{
2156 	  BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
2157 	  BView_invalidate (bar->scroll_bar);
2158 	}
2159     }
2160   bar->position = position;
2161   bar->total = whole;
2162   XSETVECTOR (barobj, bar);
2163   wset_horizontal_scroll_bar (w, barobj);
2164   unblock_input ();
2165 }
2166 
2167 static void
haiku_set_vertical_scroll_bar(struct window * w,int portion,int whole,int position)2168 haiku_set_vertical_scroll_bar (struct window *w,
2169 			       int portion, int whole, int position)
2170 {
2171   eassert (WINDOW_HAS_VERTICAL_SCROLL_BAR (w));
2172   Lisp_Object barobj;
2173   struct scroll_bar *bar;
2174   int top, height, left, width;
2175   int window_y, window_height;
2176 
2177   /* Get window dimensions.  */
2178   window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
2179   top = window_y;
2180   height = window_height;
2181 
2182   /* Compute the left edge and the width of the scroll bar area.  */
2183   left = WINDOW_SCROLL_BAR_AREA_X (w);
2184   width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2185   block_input ();
2186 
2187   if (NILP (w->vertical_scroll_bar))
2188     {
2189       bar = haiku_scroll_bar_create (w, left, top, width, height, false);
2190       BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
2191       bar->position = position;
2192       bar->total = whole;
2193     }
2194   else
2195     {
2196       bar = XSCROLL_BAR (w->vertical_scroll_bar);
2197 
2198       if (bar->left != left || bar->top != top ||
2199 	  bar->width != width || bar->height != height)
2200 	{
2201 	  void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w));
2202 	  BView_forget_scroll_bar (view, bar->left, bar->top,
2203 				   bar->width, bar->height);
2204 	  BView_move_frame (bar->scroll_bar, left, top,
2205 			    left + width - 1, top + height - 1);
2206 	  flush_frame (WINDOW_XFRAME (w));
2207 	  BView_publish_scroll_bar (view, left, top, width, height);
2208 	  bar->left = left;
2209 	  bar->top = top;
2210 	  bar->width = width;
2211 	  bar->height = height;
2212 	}
2213 
2214       if (!bar->dragging)
2215 	{
2216 	  BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
2217 	  bar->update = position;
2218 	  BView_invalidate (bar->scroll_bar);
2219 	}
2220     }
2221 
2222   bar->position = position;
2223   bar->total = whole;
2224 
2225   XSETVECTOR (barobj, bar);
2226   wset_vertical_scroll_bar (w, barobj);
2227   unblock_input ();
2228 }
2229 
2230 static void
haiku_draw_fringe_bitmap(struct window * w,struct glyph_row * row,struct draw_fringe_bitmap_params * p)2231 haiku_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2232 			  struct draw_fringe_bitmap_params *p)
2233 {
2234   void *view = FRAME_HAIKU_VIEW (XFRAME (WINDOW_FRAME (w)));
2235   struct face *face = p->face;
2236 
2237   BView_draw_lock (view);
2238   BView_StartClip (view);
2239 
2240   haiku_clip_to_row (w, row, ANY_AREA);
2241   if (p->bx >= 0 && !p->overlay_p)
2242     {
2243       BView_SetHighColor (view, face->background);
2244       BView_FillRectangle (view, p->bx, p->by, p->nx, p->ny);
2245     }
2246 
2247   if (p->which && p->which < fringe_bitmap_fillptr)
2248     {
2249       void *bitmap = fringe_bmps[p->which];
2250 
2251       uint32_t col;
2252 
2253       if (!p->cursor_p)
2254 	col = face->foreground;
2255       else if (p->overlay_p)
2256 	col = face->background;
2257       else
2258 	col = FRAME_CURSOR_COLOR (XFRAME (WINDOW_FRAME (w))).pixel;
2259 
2260       if (!p->overlay_p)
2261         {
2262 	  BView_SetHighColor (view, face->background);
2263 	  BView_FillRectangle (view, p->x, p->y, p->wd, p->h);
2264 	}
2265 
2266       BView_SetLowColor (view, col);
2267       BView_DrawBitmapWithEraseOp (view, bitmap, p->x, p->y, p->wd, p->h);
2268     }
2269   BView_EndClip (view);
2270   BView_draw_unlock (view);
2271 }
2272 
2273 static void
haiku_define_fringe_bitmap(int which,unsigned short * bits,int h,int wd)2274 haiku_define_fringe_bitmap (int which, unsigned short *bits,
2275 			    int h, int wd)
2276 {
2277   if (which >= fringe_bitmap_fillptr)
2278     {
2279       int i = fringe_bitmap_fillptr;
2280       fringe_bitmap_fillptr = which + 20;
2281       fringe_bmps = !i ? xmalloc (fringe_bitmap_fillptr * sizeof (void *)) :
2282 	xrealloc (fringe_bmps, fringe_bitmap_fillptr * sizeof (void *));
2283 
2284       while (i < fringe_bitmap_fillptr)
2285 	fringe_bmps[i++] = NULL;
2286     }
2287 
2288   fringe_bmps[which] = BBitmap_new (wd, h, 1);
2289   BBitmap_import_mono_bits (fringe_bmps[which], bits, wd, h);
2290 }
2291 
2292 static void
haiku_destroy_fringe_bitmap(int which)2293 haiku_destroy_fringe_bitmap (int which)
2294 {
2295   if (which >= fringe_bitmap_fillptr)
2296     return;
2297 
2298   if (fringe_bmps[which])
2299     BBitmap_free (fringe_bmps[which]);
2300   fringe_bmps[which] = NULL;
2301 }
2302 
2303 static void
haiku_scroll_run(struct window * w,struct run * run)2304 haiku_scroll_run (struct window *w, struct run *run)
2305 {
2306   struct frame *f = XFRAME (w->frame);
2307   void *view = FRAME_HAIKU_VIEW (f);
2308   int x, y, width, height, from_y, to_y, bottom_y;
2309   window_box (w, ANY_AREA, &x, &y, &width, &height);
2310 
2311   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2312   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2313   bottom_y = y + height;
2314 
2315   if (to_y < from_y)
2316     {
2317       /* Scrolling up.  Make sure we don't copy part of the mode
2318 	 line at the bottom.  */
2319       if (from_y + run->height > bottom_y)
2320 	height = bottom_y - from_y;
2321       else
2322 	height = run->height;
2323     }
2324   else
2325     {
2326       /* Scrolling down.  Make sure we don't copy over the mode line.
2327 	 at the bottom.  */
2328       if (to_y + run->height > bottom_y)
2329 	height = bottom_y - to_y;
2330       else
2331 	height = run->height;
2332     }
2333 
2334   if (!height)
2335     return;
2336 
2337   block_input ();
2338   gui_clear_cursor (w);
2339   BView_draw_lock (view);
2340 #ifdef USE_BE_CAIRO
2341   if (EmacsView_double_buffered_p (view))
2342     {
2343 #endif
2344       BView_StartClip (view);
2345       BView_CopyBits (view, x, from_y, width, height,
2346 		      x, to_y, width, height);
2347       BView_EndClip (view);
2348 #ifdef USE_BE_CAIRO
2349     }
2350   else
2351     {
2352       EmacsWindow_begin_cr_critical_section (FRAME_HAIKU_WINDOW (f));
2353       cairo_surface_t *surface = FRAME_CR_SURFACE (f);
2354       cairo_surface_t *s
2355 	= cairo_surface_create_similar (surface,
2356 					cairo_surface_get_content (surface),
2357 					width, height);
2358       cairo_t *cr = cairo_create (s);
2359       if (surface)
2360 	{
2361 	  cairo_set_source_surface (cr, surface, -x, -from_y);
2362 	  cairo_paint (cr);
2363 	  cairo_destroy (cr);
2364 
2365 	  cr = haiku_begin_cr_clip (f, NULL);
2366 	  cairo_save (cr);
2367 	  cairo_set_source_surface (cr, s, x, to_y);
2368 	  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
2369 	  cairo_rectangle (cr, x, to_y, width, height);
2370 	  cairo_fill (cr);
2371 	  cairo_restore (cr);
2372 	  cairo_surface_destroy (s);
2373 	  haiku_end_cr_clip (cr);
2374 	}
2375       EmacsWindow_end_cr_critical_section (FRAME_HAIKU_WINDOW (f));
2376     }
2377 #endif
2378   BView_draw_unlock (view);
2379 
2380   unblock_input ();
2381 }
2382 
2383 static void
haiku_mouse_position(struct frame ** fp,int insist,Lisp_Object * bar_window,enum scroll_bar_part * part,Lisp_Object * x,Lisp_Object * y,Time * timestamp)2384 haiku_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
2385 		      enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
2386 		      Time *timestamp)
2387 {
2388   if (!fp)
2389     return;
2390 
2391   block_input ();
2392   Lisp_Object frame, tail;
2393   struct frame *f1 = NULL;
2394   FOR_EACH_FRAME (tail, frame)
2395     XFRAME (frame)->mouse_moved = false;
2396 
2397   if (gui_mouse_grabbed (x_display_list) && !EQ (track_mouse, Qdropping))
2398     f1 = x_display_list->last_mouse_frame;
2399 
2400   if (!f1 || FRAME_TOOLTIP_P (f1))
2401     f1 = ((EQ (track_mouse, Qdropping) && gui_mouse_grabbed (x_display_list))
2402 	  ? x_display_list->last_mouse_frame
2403 	  : NULL);
2404 
2405   if (!f1 && insist > 0)
2406     f1 = SELECTED_FRAME ();
2407 
2408   if (!f1 || (!FRAME_HAIKU_P (f1) && (insist > 0)))
2409     FOR_EACH_FRAME (tail, frame)
2410       if (FRAME_HAIKU_P (XFRAME (frame)) &&
2411 	  !FRAME_TOOLTIP_P (XFRAME (frame)))
2412 	f1 = XFRAME (frame);
2413 
2414   if (FRAME_TOOLTIP_P (f1))
2415     f1 = NULL;
2416 
2417   if (f1 && FRAME_HAIKU_P (f1))
2418     {
2419       int sx, sy;
2420       void *view = FRAME_HAIKU_VIEW (f1);
2421       if (view)
2422 	{
2423 	  BView_get_mouse (view, &sx, &sy);
2424 
2425 	  remember_mouse_glyph (f1, sx, sy, &x_display_list->last_mouse_glyph);
2426 	  x_display_list->last_mouse_glyph_frame = f1;
2427 
2428 	  *bar_window = Qnil;
2429 	  *part = scroll_bar_above_handle;
2430 	  *fp = f1;
2431 	  *timestamp = x_display_list->last_mouse_movement_time;
2432 	  XSETINT (*x, sx);
2433 	  XSETINT (*y, sy);
2434 	}
2435     }
2436 
2437   unblock_input ();
2438 }
2439 
2440 static void
haiku_flush(struct frame * f)2441 haiku_flush (struct frame *f)
2442 {
2443   if (FRAME_VISIBLE_P (f))
2444     BWindow_Flush (FRAME_HAIKU_WINDOW (f));
2445 }
2446 
2447 static void
haiku_define_frame_cursor(struct frame * f,Emacs_Cursor cursor)2448 haiku_define_frame_cursor (struct frame *f, Emacs_Cursor cursor)
2449 {
2450   if (f->tooltip)
2451     return;
2452   block_input ();
2453   if (!f->pointer_invisible && FRAME_HAIKU_VIEW (f)
2454       && !FRAME_OUTPUT_DATA (f)->hourglass_p)
2455     BView_set_view_cursor (FRAME_HAIKU_VIEW (f), cursor);
2456   unblock_input ();
2457   FRAME_OUTPUT_DATA (f)->current_cursor = cursor;
2458 }
2459 
2460 static void
haiku_update_window_end(struct window * w,bool cursor_on_p,bool mouse_face_overwritten_p)2461 haiku_update_window_end (struct window *w, bool cursor_on_p,
2462 			 bool mouse_face_overwritten_p)
2463 {
2464 
2465 }
2466 
2467 static void
haiku_default_font_parameter(struct frame * f,Lisp_Object parms)2468 haiku_default_font_parameter (struct frame *f, Lisp_Object parms)
2469 {
2470   struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2471   Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
2472                                                 RES_TYPE_STRING);
2473   Lisp_Object font = Qnil;
2474   if (EQ (font_param, Qunbound))
2475     font_param = Qnil;
2476 
2477   if (NILP (font_param))
2478     {
2479       /* System font should take precedence over X resources.  We suggest this
2480          regardless of font-use-system-font because .emacs may not have been
2481          read yet.  */
2482       struct haiku_font_pattern ptn;
2483       ptn.specified = 0;
2484 
2485       if (f->tooltip)
2486 	BFont_populate_plain_family (&ptn);
2487       else
2488 	BFont_populate_fixed_family (&ptn);
2489 
2490       if (ptn.specified & FSPEC_FAMILY)
2491 	font = font_open_by_name (f, build_unibyte_string (ptn.family));
2492     }
2493 
2494   if (NILP (font))
2495       font = !NILP (font_param) ? font_param
2496       : gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font",
2497                              RES_TYPE_STRING);
2498 
2499   if (! FONTP (font) && ! STRINGP (font))
2500     {
2501       const char **names = (const char *[]) { "monospace-12",
2502 					      "Noto Sans Mono-12",
2503 					      "Source Code Pro-12",
2504 					      NULL };
2505       int i;
2506 
2507       for (i = 0; names[i]; i++)
2508         {
2509           font
2510             = font_open_by_name (f, build_unibyte_string (names[i]));
2511           if (!NILP (font))
2512             break;
2513         }
2514       if (NILP (font))
2515         error ("No suitable font was found");
2516     }
2517   else if (!NILP (font_param))
2518     {
2519       /* Remember the explicit font parameter, so we can re-apply it
2520          after we've applied the `default' face settings.  */
2521       AUTO_FRAME_ARG (arg, Qfont_parameter, font_param);
2522       gui_set_frame_parameters (f, arg);
2523     }
2524 
2525   gui_default_parameter (f, parms, Qfont, font, "font", "Font",
2526                          RES_TYPE_STRING);
2527 }
2528 
2529 static struct redisplay_interface haiku_redisplay_interface =
2530   {
2531     haiku_frame_parm_handlers,
2532     gui_produce_glyphs,
2533     gui_write_glyphs,
2534     gui_insert_glyphs,
2535     gui_clear_end_of_line,
2536     haiku_scroll_run,
2537     haiku_after_update_window_line,
2538     NULL,
2539     haiku_update_window_end,
2540     haiku_flush,
2541     gui_clear_window_mouse_face,
2542     gui_get_glyph_overhangs,
2543     gui_fix_overlapping_area,
2544     haiku_draw_fringe_bitmap,
2545     haiku_define_fringe_bitmap,
2546     haiku_destroy_fringe_bitmap,
2547     haiku_compute_glyph_string_overhangs,
2548     haiku_draw_glyph_string,
2549     haiku_define_frame_cursor,
2550     haiku_clear_frame_area,
2551     haiku_clear_under_internal_border,
2552     haiku_draw_window_cursor,
2553     haiku_draw_vertical_window_border,
2554     haiku_draw_window_divider,
2555     0, /* shift glyphs for insert */
2556     haiku_show_hourglass,
2557     haiku_hide_hourglass,
2558     haiku_default_font_parameter,
2559   };
2560 
2561 static void
haiku_make_fullscreen_consistent(struct frame * f)2562 haiku_make_fullscreen_consistent (struct frame *f)
2563 {
2564   Lisp_Object lval = get_frame_param (f, Qfullscreen);
2565 
2566   if (!EQ (lval, Qmaximized) && FRAME_OUTPUT_DATA (f)->zoomed_p)
2567     lval = Qmaximized;
2568   else if (EQ (lval, Qmaximized) && !FRAME_OUTPUT_DATA (f)->zoomed_p)
2569     lval = Qnil;
2570 
2571   store_frame_param (f, Qfullscreen, lval);
2572 }
2573 
2574 static void
flush_dirty_back_buffers(void)2575 flush_dirty_back_buffers (void)
2576 {
2577   block_input ();
2578   Lisp_Object tail, frame;
2579   FOR_EACH_FRAME (tail, frame)
2580     {
2581       struct frame *f = XFRAME (frame);
2582       if (FRAME_LIVE_P (f) &&
2583           FRAME_HAIKU_P (f) &&
2584           FRAME_HAIKU_WINDOW (f) &&
2585           !FRAME_GARBAGED_P (f) &&
2586           !buffer_flipping_blocked_p () &&
2587           FRAME_DIRTY_P (f))
2588         haiku_flip_buffers (f);
2589     }
2590   unblock_input ();
2591 }
2592 
2593 static int
haiku_read_socket(struct terminal * terminal,struct input_event * hold_quit)2594 haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
2595 {
2596   block_input ();
2597   int message_count = 0;
2598   static void *buf = NULL;
2599   ssize_t b_size;
2600   struct unhandled_event *unhandled_events = NULL;
2601   int button_or_motion_p;
2602   int need_flush = 0;
2603 
2604   if (!buf)
2605     buf = xmalloc (200);
2606   haiku_read_size (&b_size);
2607   while (b_size >= 0)
2608     {
2609       enum haiku_event_type type;
2610       struct input_event inev, inev2;
2611 
2612       if (b_size > 200)
2613 	emacs_abort ();
2614 
2615       EVENT_INIT (inev);
2616       EVENT_INIT (inev2);
2617       inev.kind = NO_EVENT;
2618       inev2.kind = NO_EVENT;
2619       inev.arg = Qnil;
2620       inev2.arg = Qnil;
2621 
2622       button_or_motion_p = 0;
2623 
2624       haiku_read (&type, buf, b_size);
2625 
2626       switch (type)
2627 	{
2628 	case QUIT_REQUESTED:
2629 	  {
2630 	    struct haiku_quit_requested_event *b = buf;
2631 	    struct frame *f = haiku_window_to_frame (b->window);
2632 
2633 	    if (!f)
2634 	      continue;
2635 
2636 	    inev.kind = DELETE_WINDOW_EVENT;
2637 	    XSETFRAME (inev.frame_or_window, f);
2638 	    break;
2639 	  }
2640 	case FRAME_RESIZED:
2641 	  {
2642 	    struct haiku_resize_event *b = buf;
2643 	    struct frame *f = haiku_window_to_frame (b->window);
2644 
2645 	    if (!f)
2646 	      continue;
2647 
2648 	    int width = lrint (b->px_widthf);
2649 	    int height = lrint (b->px_heightf);
2650 
2651 	    BView_draw_lock (FRAME_HAIKU_VIEW (f));
2652 	    BView_resize_to (FRAME_HAIKU_VIEW (f), width, height);
2653 	    BView_draw_unlock (FRAME_HAIKU_VIEW (f));
2654 	    if (width != FRAME_PIXEL_WIDTH (f)
2655 		|| height != FRAME_PIXEL_HEIGHT (f)
2656 		|| (f->new_size_p
2657 		    && ((f->new_width >= 0 && width != f->new_width)
2658 			|| (f->new_height >= 0 && height != f->new_height))))
2659 	      {
2660 		change_frame_size (f, width, height, false, true, false);
2661 		SET_FRAME_GARBAGED (f);
2662 		cancel_mouse_face (f);
2663 		haiku_clear_under_internal_border (f);
2664 	      }
2665 
2666 	    if (FRAME_OUTPUT_DATA (f)->pending_zoom_width != width ||
2667 		FRAME_OUTPUT_DATA (f)->pending_zoom_height != height)
2668 	      {
2669 		FRAME_OUTPUT_DATA (f)->zoomed_p = 0;
2670 		haiku_make_fullscreen_consistent (f);
2671 	      }
2672 	    else
2673 	      {
2674 		FRAME_OUTPUT_DATA (f)->zoomed_p = 1;
2675 		FRAME_OUTPUT_DATA (f)->pending_zoom_width = INT_MIN;
2676 		FRAME_OUTPUT_DATA (f)->pending_zoom_height = INT_MIN;
2677 	      }
2678 	    break;
2679 	  }
2680 	case FRAME_EXPOSED:
2681 	  {
2682 	    struct haiku_expose_event *b = buf;
2683 	    struct frame *f = haiku_window_to_frame (b->window);
2684 
2685 	    if (!f)
2686 	      continue;
2687 
2688 	    expose_frame (f, b->x, b->y, b->width, b->height);
2689 
2690 	    haiku_clear_under_internal_border (f);
2691 	    break;
2692 	  }
2693 	case KEY_DOWN:
2694 	  {
2695 	    struct haiku_key_event *b = buf;
2696 	    struct frame *f = haiku_window_to_frame (b->window);
2697 	    int non_ascii_p;
2698 	    if (!f)
2699 	      continue;
2700 
2701 	    inev.code = b->unraw_mb_char;
2702 
2703 	    BMapKey (b->kc, &non_ascii_p, &inev.code);
2704 
2705 	    if (non_ascii_p)
2706 	      inev.kind = NON_ASCII_KEYSTROKE_EVENT;
2707 	    else
2708 	      inev.kind = inev.code > 127 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT :
2709 		ASCII_KEYSTROKE_EVENT;
2710 
2711 	    inev.modifiers = haiku_modifiers_to_emacs (b->modifiers);
2712 	    XSETFRAME (inev.frame_or_window, f);
2713 	    break;
2714 	  }
2715 	case ACTIVATION:
2716 	  {
2717 	    struct haiku_activation_event *b = buf;
2718 	    struct frame *f = haiku_window_to_frame (b->window);
2719 
2720 	    if (!f)
2721 	      continue;
2722 
2723 	    if ((x_display_list->focus_event_frame != f && b->activated_p) ||
2724 		(x_display_list->focus_event_frame == f && !b->activated_p))
2725 	      {
2726 		haiku_new_focus_frame (b->activated_p ? f : NULL);
2727 		if (b->activated_p)
2728 		  x_display_list->focus_event_frame = f;
2729 		else
2730 		  x_display_list->focus_event_frame = NULL;
2731 		inev.kind = b->activated_p ? FOCUS_IN_EVENT : FOCUS_OUT_EVENT;
2732 		XSETFRAME (inev.frame_or_window, f);
2733 	      }
2734 
2735 	    break;
2736 	  }
2737 	case MOUSE_MOTION:
2738 	  {
2739 	    struct haiku_mouse_motion_event *b = buf;
2740 	    struct frame *f = haiku_window_to_frame (b->window);
2741 
2742 	    if (!f)
2743 	      continue;
2744 
2745 	    Lisp_Object frame;
2746 	    XSETFRAME (frame, f);
2747 
2748 	    x_display_list->last_mouse_movement_time = time (NULL);
2749 	    button_or_motion_p = 1;
2750 
2751 	    if (b->just_exited_p)
2752 	      {
2753 		Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
2754 		if (f == hlinfo->mouse_face_mouse_frame)
2755 		  {
2756 		    /* If we move outside the frame, then we're
2757 		       certainly no longer on any text in the frame.  */
2758 		    clear_mouse_face (hlinfo);
2759 		    hlinfo->mouse_face_mouse_frame = 0;
2760 		  }
2761 
2762 		haiku_new_focus_frame (x_display_list->focused_frame);
2763 		help_echo_string = Qnil;
2764 		gen_help_event (Qnil, frame, Qnil, Qnil, 0);
2765 	      }
2766 	    else
2767 	      {
2768 		struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2769 		struct haiku_rect r = dpyinfo->last_mouse_glyph;
2770 
2771 		dpyinfo->last_mouse_motion_x = b->x;
2772 		dpyinfo->last_mouse_motion_y = b->y;
2773 		dpyinfo->last_mouse_motion_frame = f;
2774 
2775 		previous_help_echo_string = help_echo_string;
2776 		help_echo_string = Qnil;
2777 
2778 		if (f != dpyinfo->last_mouse_glyph_frame
2779 		    || b->x < r.x || b->x >= r.x + r.width
2780 		    || b->y < r.y || b->y >= r.y + r.height)
2781 		  {
2782 		    f->mouse_moved = true;
2783 		    dpyinfo->last_mouse_scroll_bar = NULL;
2784 		    note_mouse_highlight (f, b->x, b->y);
2785 		    remember_mouse_glyph (f, b->x, b->y,
2786 					  &FRAME_DISPLAY_INFO (f)->last_mouse_glyph);
2787 		    dpyinfo->last_mouse_glyph_frame = f;
2788 		    gen_help_event (help_echo_string, frame, help_echo_window,
2789 				    help_echo_object, help_echo_pos);
2790 		  }
2791 
2792 		if (MOUSE_HL_INFO (f)->mouse_face_hidden)
2793 		  {
2794 		    MOUSE_HL_INFO (f)->mouse_face_hidden = 0;
2795 		    clear_mouse_face (MOUSE_HL_INFO (f));
2796 		  }
2797 
2798 		if (!NILP (Vmouse_autoselect_window))
2799 		  {
2800 		    static Lisp_Object last_mouse_window;
2801 		    Lisp_Object window = window_from_coordinates (f, b->x, b->y, 0, 0, 0);
2802 
2803 		    if (WINDOWP (window)
2804 			&& !EQ (window, last_mouse_window)
2805 			&& !EQ (window, selected_window)
2806 			&& (!NILP (focus_follows_mouse)
2807 				|| (EQ (XWINDOW (window)->frame,
2808 					XWINDOW (selected_window)->frame))))
2809 		      {
2810 			inev.kind = SELECT_WINDOW_EVENT;
2811 			inev.frame_or_window = window;
2812 		      }
2813 
2814 		    last_mouse_window = window;
2815 		  }
2816 	      }
2817 	    break;
2818 	  }
2819 	case BUTTON_UP:
2820 	case BUTTON_DOWN:
2821 	  {
2822 	    struct haiku_button_event *b = buf;
2823 	    struct frame *f = haiku_window_to_frame (b->window);
2824 	    Lisp_Object tab_bar_arg = Qnil;
2825 	    int tab_bar_p = 0, tool_bar_p = 0;
2826 
2827 	    if (!f)
2828 	      continue;
2829 
2830 	    struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2831 
2832 	    inev.modifiers = haiku_modifiers_to_emacs (b->modifiers);
2833 
2834 	    x_display_list->last_mouse_glyph_frame = 0;
2835 	    x_display_list->last_mouse_movement_time = time (NULL);
2836 	    button_or_motion_p = 1;
2837 
2838 	    /* Is this in the tab-bar?  */
2839 	    if (WINDOWP (f->tab_bar_window)
2840 		&& WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
2841 	      {
2842 		Lisp_Object window;
2843 		int x = b->x;
2844 		int y = b->y;
2845 
2846 		window = window_from_coordinates (f, x, y, 0, true, true);
2847 		tab_bar_p = EQ (window, f->tab_bar_window);
2848 
2849 		if (tab_bar_p)
2850 		  {
2851 		    tab_bar_arg = handle_tab_bar_click
2852 		      (f, x, y, type == BUTTON_DOWN, inev.modifiers);
2853 		    need_flush = 1;
2854 		  }
2855 	      }
2856 
2857 	    if (WINDOWP (f->tool_bar_window)
2858 		&& WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
2859 	      {
2860 		Lisp_Object window;
2861 		int x = b->x;
2862 		int y = b->y;
2863 
2864 		window = window_from_coordinates (f, x, y, 0, true, true);
2865 		tool_bar_p = EQ (window, f->tool_bar_window);
2866 
2867 		if (tool_bar_p)
2868 		  {
2869 		    handle_tool_bar_click
2870 		      (f, x, y, type == BUTTON_DOWN, inev.modifiers);
2871 		    need_flush = 1;
2872 		  }
2873 	      }
2874 
2875 	    if (type == BUTTON_UP)
2876 	      {
2877 		inev.modifiers |= up_modifier;
2878 		dpyinfo->grabbed &= ~(1 << b->btn_no);
2879 	      }
2880 	    else
2881 	      {
2882 		inev.modifiers |= down_modifier;
2883 		dpyinfo->last_mouse_frame = f;
2884 		dpyinfo->grabbed |= (1 << b->btn_no);
2885 		if (f && !tab_bar_p)
2886 		  f->last_tab_bar_item = -1;
2887 		if (f && !tool_bar_p)
2888 		  f->last_tool_bar_item = -1;
2889 	      }
2890 
2891 	    if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
2892 	      inev.kind = MOUSE_CLICK_EVENT;
2893 	    inev.arg = tab_bar_arg;
2894 	    inev.code = b->btn_no;
2895 
2896 	    f->mouse_moved = false;
2897 
2898 	    XSETINT (inev.x, b->x);
2899 	    XSETINT (inev.y, b->y);
2900 
2901 	    XSETFRAME (inev.frame_or_window, f);
2902 	    break;
2903 	  }
2904 	case ICONIFICATION:
2905 	  {
2906 	    struct haiku_iconification_event *b = buf;
2907 	    struct frame *f = haiku_window_to_frame (b->window);
2908 
2909 	    if (!f)
2910 	      continue;
2911 
2912 	    if (!b->iconified_p)
2913 	      {
2914 		SET_FRAME_VISIBLE (f, 1);
2915 		SET_FRAME_ICONIFIED (f, 0);
2916 		inev.kind = DEICONIFY_EVENT;
2917 
2918 
2919 		/* Haiku doesn't expose frames on deiconification, but
2920 		   if we are double-buffered, the previous screen
2921 		   contents should have been preserved. */
2922 		if (!EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)))
2923 		  {
2924 		    SET_FRAME_GARBAGED (f);
2925 		    expose_frame (f, 0, 0, 0, 0);
2926 		  }
2927 	      }
2928 	    else
2929 	      {
2930 		SET_FRAME_VISIBLE (f, 0);
2931 		SET_FRAME_ICONIFIED (f, 1);
2932 		inev.kind = ICONIFY_EVENT;
2933 	      }
2934 
2935 	    XSETFRAME (inev.frame_or_window, f);
2936 	    break;
2937 	  }
2938 	case MOVE_EVENT:
2939 	  {
2940 	    struct haiku_move_event *b = buf;
2941 	    struct frame *f = haiku_window_to_frame (b->window);
2942 
2943 	    if (!f)
2944 	      continue;
2945 
2946 	    if (FRAME_OUTPUT_DATA (f)->pending_zoom_x != b->x ||
2947 		FRAME_OUTPUT_DATA (f)->pending_zoom_y != b->y)
2948 	      FRAME_OUTPUT_DATA (f)->zoomed_p = 0;
2949 	    else
2950 	      {
2951 		FRAME_OUTPUT_DATA (f)->zoomed_p = 1;
2952 		FRAME_OUTPUT_DATA (f)->pending_zoom_x = INT_MIN;
2953 		FRAME_OUTPUT_DATA (f)->pending_zoom_y = INT_MIN;
2954 	      }
2955 
2956 	    if (FRAME_PARENT_FRAME (f))
2957 	      haiku_coords_from_parent (f, &b->x, &b->y);
2958 
2959 	    if (b->x != f->left_pos || b->y != f->top_pos)
2960 	      {
2961 		inev.kind = MOVE_FRAME_EVENT;
2962 
2963 		XSETINT (inev.x, b->x);
2964 		XSETINT (inev.y, b->y);
2965 
2966 		f->left_pos = b->x;
2967 		f->top_pos = b->y;
2968 
2969 		struct frame *p;
2970 
2971 		if ((p = FRAME_PARENT_FRAME (f)))
2972 		  {
2973 		    void *window = FRAME_HAIKU_WINDOW (p);
2974 		    EmacsWindow_move_weak_child (window, b->window, b->x, b->y);
2975 		  }
2976 
2977 		XSETFRAME (inev.frame_or_window, f);
2978 	      }
2979 
2980 	    haiku_make_fullscreen_consistent (f);
2981 	    break;
2982 	  }
2983 	case SCROLL_BAR_VALUE_EVENT:
2984 	  {
2985 	    struct haiku_scroll_bar_value_event *b = buf;
2986 	    struct scroll_bar *bar = b->scroll_bar;
2987 
2988 	    struct window *w = XWINDOW (bar->window);
2989 
2990 	    if (bar->update != -1)
2991 	      {
2992 		bar->update = -1;
2993 		break;
2994 	      }
2995 
2996 	    if (bar->position != b->position)
2997 	      {
2998 		inev.kind = bar->horizontal ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT :
2999 		  SCROLL_BAR_CLICK_EVENT;
3000 		inev.part = bar->horizontal ?
3001 		  scroll_bar_horizontal_handle : scroll_bar_handle;
3002 
3003 		XSETINT (inev.x, b->position);
3004 		XSETINT (inev.y, bar->total);
3005 		XSETWINDOW (inev.frame_or_window, w);
3006 	      }
3007 	    break;
3008 	  }
3009 	case SCROLL_BAR_DRAG_EVENT:
3010 	  {
3011 	    struct haiku_scroll_bar_drag_event *b = buf;
3012 	    struct scroll_bar *bar = b->scroll_bar;
3013 
3014 	    bar->dragging = b->dragging_p;
3015 	    if (!b->dragging_p && bar->horizontal)
3016 	      set_horizontal_scroll_bar (XWINDOW (bar->window));
3017 	    else if (!b->dragging_p)
3018 	      set_vertical_scroll_bar (XWINDOW (bar->window));
3019 	    break;
3020 	  }
3021 	case WHEEL_MOVE_EVENT:
3022 	  {
3023 	    struct haiku_wheel_move_event *b = buf;
3024 	    struct frame *f = haiku_window_to_frame (b->window);
3025 	    int x, y;
3026 	    static float px = 0.0f, py = 0.0f;
3027 
3028 	    if (!f)
3029 	      continue;
3030 	    BView_get_mouse (FRAME_HAIKU_VIEW (f), &x, &y);
3031 
3032 	    inev.modifiers = haiku_modifiers_to_emacs (b->modifiers);
3033 
3034 	    inev2.modifiers = inev.modifiers;
3035 
3036 	    if (signbit (px) != signbit (b->delta_x))
3037 	      px = 0;
3038 
3039 	    if (signbit (py) != signbit (b->delta_y))
3040 	      py = 0;
3041 
3042 	    px += (b->delta_x
3043 		   * powf (FRAME_PIXEL_HEIGHT (f), 2.0f / 3.0f));
3044 	    py += (b->delta_y
3045 		   * powf (FRAME_PIXEL_HEIGHT (f), 2.0f / 3.0f));
3046 
3047 	    if (fabsf (py) >= FRAME_LINE_HEIGHT (f)
3048 		|| fabsf (px) >= FRAME_COLUMN_WIDTH (f)
3049 		|| !mwheel_coalesce_scroll_events)
3050 	      {
3051 		inev.kind = (fabsf (px) > fabsf (py)
3052 			     ? HORIZ_WHEEL_EVENT
3053 			     : WHEEL_EVENT);
3054 		inev.code = 0;
3055 
3056 		XSETINT (inev.x, x);
3057 		XSETINT (inev.y, y);
3058 		inev.arg = list3 (Qnil, make_float (-px),
3059 				  make_float (-py));
3060 		XSETFRAME (inev.frame_or_window, f);
3061 
3062 		inev.modifiers |= (signbit (inev.kind == HORIZ_WHEEL_EVENT
3063 					    ? px : py)
3064 				   ? up_modifier
3065 				   : down_modifier);
3066 		py = 0.0f;
3067 		px = 0.0f;
3068 	      }
3069 
3070 	    break;
3071 	  }
3072 
3073 	case MENU_BAR_RESIZE:
3074 	  {
3075 	    struct haiku_menu_bar_resize_event *b = buf;
3076 	    struct frame *f = haiku_window_to_frame (b->window);
3077 
3078 	    if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
3079 	      continue;
3080 
3081 	    int old_height = FRAME_MENU_BAR_HEIGHT (f);
3082 
3083 	    FRAME_MENU_BAR_HEIGHT (f) = b->height + 1;
3084 	    FRAME_MENU_BAR_LINES (f) =
3085 	      (b->height + FRAME_LINE_HEIGHT (f)) / FRAME_LINE_HEIGHT (f);
3086 
3087 	    if (old_height != b->height)
3088 	      {
3089 		adjust_frame_size (f, -1, -1, 3, true, Qmenu_bar_lines);
3090 		haiku_clear_under_internal_border (f);
3091 	      }
3092 	    break;
3093 	  }
3094 	case MENU_BAR_OPEN:
3095 	case MENU_BAR_CLOSE:
3096 	  {
3097 	    struct haiku_menu_bar_state_event *b = buf;
3098 	    struct frame *f = haiku_window_to_frame (b->window);
3099 
3100 	    if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
3101 	      continue;
3102 
3103 	    if (type == MENU_BAR_OPEN)
3104 	      {
3105 		if (!FRAME_OUTPUT_DATA (f)->menu_up_to_date_p)
3106 		  {
3107 		    BView_draw_lock (FRAME_HAIKU_VIEW (f));
3108 		    /* This shouldn't be here, but nsmenu does it, so
3109 		       it should probably be safe.  */
3110 		    int was_waiting_for_input_p = waiting_for_input;
3111 		    if (waiting_for_input)
3112 		      waiting_for_input = 0;
3113 		    set_frame_menubar (f, 1);
3114 		    waiting_for_input = was_waiting_for_input_p;
3115 		    BView_draw_unlock (FRAME_HAIKU_VIEW (f));
3116 		  }
3117 		FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1;
3118 		popup_activated_p += 1;
3119 	      }
3120 	    else
3121 	      {
3122 		if (!popup_activated_p)
3123 		  emacs_abort ();
3124 		if (FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
3125 		  {
3126 		    FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 0;
3127 		    popup_activated_p -= 1;
3128 		  }
3129 	      }
3130 	    break;
3131 	  }
3132 	case MENU_BAR_SELECT_EVENT:
3133 	  {
3134 	    struct haiku_menu_bar_select_event *b = buf;
3135 	    struct frame *f = haiku_window_to_frame (b->window);
3136 
3137 	    if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
3138 	      continue;
3139 
3140 	    if (FRAME_OUTPUT_DATA (f)->menu_up_to_date_p)
3141 	      find_and_call_menu_selection (f, f->menu_bar_items_used,
3142 					    f->menu_bar_vector, b->ptr);
3143 	    break;
3144 	  }
3145 	case FILE_PANEL_EVENT:
3146 	  {
3147 	    if (!popup_activated_p)
3148 	      continue;
3149 
3150 	    struct unhandled_event *ev = xmalloc (sizeof *ev);
3151 	    ev->next = unhandled_events;
3152 	    ev->type = type;
3153 	    memcpy (&ev->buffer, buf, 200);
3154 
3155 	    unhandled_events = ev;
3156 	    break;
3157 	  }
3158 	case MENU_BAR_HELP_EVENT:
3159 	  {
3160 	    struct haiku_menu_bar_help_event *b = buf;
3161 
3162 	    if (!popup_activated_p)
3163 	      continue;
3164 
3165 	    struct frame *f = haiku_window_to_frame (b->window);
3166 	    if (!f || !FRAME_EXTERNAL_MENU_BAR (f) ||
3167 		!FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
3168 	      continue;
3169 
3170 	    run_menu_bar_help_event (f, b->mb_idx);
3171 
3172 	    break;
3173 	  }
3174 	case ZOOM_EVENT:
3175 	  {
3176 	    struct haiku_zoom_event *b = buf;
3177 
3178 	    struct frame *f = haiku_window_to_frame (b->window);
3179 
3180 	    if (!f)
3181 	      continue;
3182 
3183 	    FRAME_OUTPUT_DATA (f)->pending_zoom_height = b->height;
3184 	    FRAME_OUTPUT_DATA (f)->pending_zoom_width = b->width;
3185 	    FRAME_OUTPUT_DATA (f)->pending_zoom_x = b->x;
3186 	    FRAME_OUTPUT_DATA (f)->pending_zoom_y = b->y;
3187 
3188 	    FRAME_OUTPUT_DATA (f)->zoomed_p = 1;
3189 	    haiku_make_fullscreen_consistent (f);
3190 	    break;
3191 	  }
3192 	case REFS_EVENT:
3193 	  {
3194 	    struct haiku_refs_event *b = buf;
3195 	    struct frame *f = haiku_window_to_frame (b->window);
3196 
3197 	    if (!f)
3198 	      continue;
3199 
3200 	    inev.kind = DRAG_N_DROP_EVENT;
3201 	    inev.arg = build_string_from_utf8 (b->ref);
3202 
3203 	    XSETINT (inev.x, b->x);
3204 	    XSETINT (inev.y, b->y);
3205 	    XSETFRAME (inev.frame_or_window, f);
3206 
3207 	    /* There should be no problem with calling free here.
3208 	       free on Haiku is thread-safe.  */
3209 	    free (b->ref);
3210 	    break;
3211 	  }
3212 	case APP_QUIT_REQUESTED_EVENT:
3213 	case KEY_UP:
3214 	default:
3215 	  break;
3216 	}
3217 
3218       haiku_read_size (&b_size);
3219 
3220       if (inev.kind != NO_EVENT)
3221 	{
3222 	  if (inev.kind != HELP_EVENT)
3223 	    inev.timestamp = (button_or_motion_p
3224 			      ? x_display_list->last_mouse_movement_time
3225 			      : time (NULL));
3226 	  kbd_buffer_store_event_hold (&inev, hold_quit);
3227 	  ++message_count;
3228 	}
3229 
3230       if (inev2.kind != NO_EVENT)
3231 	{
3232 	  if (inev2.kind != HELP_EVENT)
3233 	    inev2.timestamp = (button_or_motion_p
3234 			       ? x_display_list->last_mouse_movement_time
3235 			       : time (NULL));
3236 	  kbd_buffer_store_event_hold (&inev2, hold_quit);
3237 	  ++message_count;
3238 	}
3239     }
3240 
3241   for (struct unhandled_event *ev = unhandled_events; ev;)
3242     {
3243       haiku_write_without_signal (ev->type, &ev->buffer);
3244       struct unhandled_event *old = ev;
3245       ev = old->next;
3246       xfree (old);
3247     }
3248 
3249   if (need_flush)
3250     flush_dirty_back_buffers ();
3251 
3252   unblock_input ();
3253   return message_count;
3254 }
3255 
3256 static void
haiku_frame_rehighlight(struct frame * frame)3257 haiku_frame_rehighlight (struct frame *frame)
3258 {
3259   haiku_rehighlight ();
3260 }
3261 
3262 static void
haiku_delete_window(struct frame * f)3263 haiku_delete_window (struct frame *f)
3264 {
3265   check_window_system (f);
3266   haiku_free_frame_resources (f);
3267 }
3268 
3269 static void
haiku_free_pixmap(struct frame * f,Emacs_Pixmap pixmap)3270 haiku_free_pixmap (struct frame *f, Emacs_Pixmap pixmap)
3271 {
3272   BBitmap_free (pixmap);
3273 }
3274 
3275 static void
haiku_beep(struct frame * f)3276 haiku_beep (struct frame *f)
3277 {
3278   if (visible_bell)
3279     {
3280       void *view = FRAME_HAIKU_VIEW (f);
3281       if (view)
3282 	{
3283 	  block_input ();
3284 	  BView_draw_lock (view);
3285 	  if (!EmacsView_double_buffered_p (view))
3286 	    {
3287 	      BView_SetHighColorForVisibleBell (view, FRAME_FOREGROUND_PIXEL (f));
3288 	      BView_FillRectangleForVisibleBell (view, 0, 0, FRAME_PIXEL_WIDTH (f),
3289 						 FRAME_PIXEL_HEIGHT (f));
3290 	      SET_FRAME_GARBAGED (f);
3291 	      expose_frame (f, 0, 0, 0, 0);
3292 	    }
3293 	  else
3294 	    {
3295 	      EmacsView_do_visible_bell (view, FRAME_FOREGROUND_PIXEL (f));
3296 	      haiku_flip_buffers (f);
3297 	    }
3298 	  BView_draw_unlock (view);
3299 	  unblock_input ();
3300 	}
3301     }
3302   else
3303     haiku_ring_bell ();
3304 }
3305 
3306 static void
haiku_toggle_invisible_pointer(struct frame * f,bool invisible_p)3307 haiku_toggle_invisible_pointer (struct frame *f, bool invisible_p)
3308 {
3309   void *view = FRAME_HAIKU_VIEW (f);
3310 
3311   if (view)
3312     {
3313       block_input ();
3314       BView_set_view_cursor (view, invisible_p ?
3315 			     FRAME_OUTPUT_DATA (f)->no_cursor :
3316 			     FRAME_OUTPUT_DATA (f)->current_cursor);
3317       f->pointer_invisible = invisible_p;
3318       unblock_input ();
3319     }
3320 }
3321 
3322 static void
haiku_fullscreen(struct frame * f)3323 haiku_fullscreen (struct frame *f)
3324 {
3325   if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
3326     {
3327       EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 0);
3328       BWindow_zoom (FRAME_HAIKU_WINDOW (f));
3329     }
3330   else if (f->want_fullscreen == FULLSCREEN_BOTH)
3331     EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 1);
3332   else if (f->want_fullscreen == FULLSCREEN_NONE)
3333     {
3334       EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 0);
3335       EmacsWindow_unzoom (FRAME_HAIKU_WINDOW (f));
3336     }
3337 
3338   f->want_fullscreen = FULLSCREEN_NONE;
3339 
3340   haiku_update_size_hints (f);
3341 }
3342 
3343 static struct terminal *
haiku_create_terminal(struct haiku_display_info * dpyinfo)3344 haiku_create_terminal (struct haiku_display_info *dpyinfo)
3345 {
3346   struct terminal *terminal;
3347 
3348   terminal = create_terminal (output_haiku, &haiku_redisplay_interface);
3349 
3350   terminal->display_info.haiku = dpyinfo;
3351   dpyinfo->terminal = terminal;
3352   terminal->kboard = allocate_kboard (Qhaiku);
3353 
3354   terminal->iconify_frame_hook = haiku_iconify_frame;
3355   terminal->focus_frame_hook = haiku_focus_frame;
3356   terminal->ring_bell_hook = haiku_beep;
3357   terminal->popup_dialog_hook = haiku_popup_dialog;
3358   terminal->frame_visible_invisible_hook = haiku_set_frame_visible_invisible;
3359   terminal->set_frame_offset_hook = haiku_set_offset;
3360   terminal->delete_terminal_hook = haiku_delete_terminal;
3361   terminal->get_string_resource_hook = get_string_resource;
3362   terminal->set_new_font_hook = haiku_new_font;
3363   terminal->defined_color_hook = haiku_defined_color;
3364   terminal->set_window_size_hook = haiku_set_window_size;
3365   terminal->read_socket_hook = haiku_read_socket;
3366   terminal->implicit_set_name_hook = haiku_implicitly_set_name;
3367   terminal->mouse_position_hook = haiku_mouse_position;
3368   terminal->delete_frame_hook = haiku_delete_window;
3369   terminal->frame_up_to_date_hook = haiku_frame_up_to_date;
3370   terminal->buffer_flipping_unblocked_hook = haiku_buffer_flipping_unblocked_hook;
3371   terminal->clear_frame_hook = haiku_clear_frame;
3372   terminal->change_tab_bar_height_hook = haiku_change_tab_bar_height;
3373   terminal->change_tool_bar_height_hook = haiku_change_tool_bar_height;
3374   terminal->set_vertical_scroll_bar_hook = haiku_set_vertical_scroll_bar;
3375   terminal->set_horizontal_scroll_bar_hook = haiku_set_horizontal_scroll_bar;
3376   terminal->set_scroll_bar_default_height_hook = haiku_set_scroll_bar_default_height;
3377   terminal->set_scroll_bar_default_width_hook = haiku_set_scroll_bar_default_width;
3378   terminal->judge_scroll_bars_hook = haiku_judge_scroll_bars;
3379   terminal->condemn_scroll_bars_hook = haiku_condemn_scroll_bars;
3380   terminal->redeem_scroll_bar_hook = haiku_redeem_scroll_bar;
3381   terminal->update_begin_hook = haiku_update_begin;
3382   terminal->update_end_hook = haiku_update_end;
3383   terminal->frame_rehighlight_hook = haiku_frame_rehighlight;
3384   terminal->query_frame_background_color = haiku_query_frame_background_color;
3385   terminal->free_pixmap = haiku_free_pixmap;
3386   terminal->frame_raise_lower_hook = haiku_frame_raise_lower;
3387   terminal->menu_show_hook = haiku_menu_show;
3388   terminal->toggle_invisible_pointer_hook = haiku_toggle_invisible_pointer;
3389   terminal->fullscreen_hook = haiku_fullscreen;
3390 
3391   return terminal;
3392 }
3393 
3394 struct haiku_display_info *
haiku_term_init(void)3395 haiku_term_init (void)
3396 {
3397   struct haiku_display_info *dpyinfo;
3398   struct terminal *terminal;
3399 
3400   Lisp_Object color_file, color_map;
3401 
3402   block_input ();
3403   Fset_input_interrupt_mode (Qnil);
3404 
3405   baud_rate = 19200;
3406 
3407   dpyinfo = xzalloc (sizeof *dpyinfo);
3408 
3409   haiku_io_init ();
3410 
3411   if (port_application_to_emacs < B_OK)
3412     emacs_abort ();
3413 
3414   color_file = Fexpand_file_name (build_string ("rgb.txt"),
3415 				  Fsymbol_value (intern ("data-directory")));
3416 
3417   color_map = Fx_load_color_file (color_file);
3418   if (NILP (color_map))
3419     fatal ("Could not read %s.\n", SDATA (color_file));
3420 
3421   dpyinfo->color_map = color_map;
3422 
3423   dpyinfo->display = BApplication_setup ();
3424 
3425   BScreen_res (&dpyinfo->resx, &dpyinfo->resy);
3426 
3427   dpyinfo->next = x_display_list;
3428   dpyinfo->n_planes = be_get_display_planes ();
3429   x_display_list = dpyinfo;
3430 
3431   terminal = haiku_create_terminal (dpyinfo);
3432   if (current_kboard == initial_kboard)
3433     current_kboard = terminal->kboard;
3434 
3435   terminal->kboard->reference_count++;
3436   /* Never delete haiku displays -- there can only ever be one,
3437      anyhow.  */
3438   terminal->reference_count++;
3439   terminal->name = xstrdup ("be");
3440 
3441   dpyinfo->name_list_element = Fcons (build_string ("be"), Qnil);
3442   dpyinfo->smallest_font_height = 1;
3443   dpyinfo->smallest_char_width = 1;
3444 
3445   gui_init_fringe (terminal->rif);
3446   unblock_input ();
3447 
3448   return dpyinfo;
3449 }
3450 
3451 void
put_xrm_resource(Lisp_Object name,Lisp_Object val)3452 put_xrm_resource (Lisp_Object name, Lisp_Object val)
3453 {
3454   eassert (STRINGP (name));
3455   eassert (STRINGP (val) || NILP (val));
3456 
3457   Lisp_Object lval = assoc_no_quit (name, rdb);
3458   if (!NILP (lval))
3459     Fsetcdr (lval, val);
3460   else
3461     rdb = Fcons (Fcons (name, val), rdb);
3462 }
3463 
3464 void
haiku_clear_under_internal_border(struct frame * f)3465 haiku_clear_under_internal_border (struct frame *f)
3466 {
3467   if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
3468     {
3469       int border = FRAME_INTERNAL_BORDER_WIDTH (f);
3470       int width = FRAME_PIXEL_WIDTH (f);
3471       int height = FRAME_PIXEL_HEIGHT (f);
3472       int margin = FRAME_TOP_MARGIN_HEIGHT (f);
3473       int face_id =
3474 	(FRAME_PARENT_FRAME (f)
3475 	 ? (!NILP (Vface_remapping_alist)
3476 	    ? lookup_basic_face (NULL, f, CHILD_FRAME_BORDER_FACE_ID)
3477 	    : CHILD_FRAME_BORDER_FACE_ID)
3478 	 : (!NILP (Vface_remapping_alist)
3479 	    ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
3480 	    : INTERNAL_BORDER_FACE_ID));
3481       struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
3482       void *view = FRAME_HAIKU_VIEW (f);
3483       block_input ();
3484       BView_draw_lock (view);
3485       BView_StartClip (view);
3486       BView_ClipToRect (view, 0, 0, FRAME_PIXEL_WIDTH (f),
3487 			FRAME_PIXEL_HEIGHT (f));
3488 
3489       if (face)
3490 	BView_SetHighColor (view, face->background);
3491       else
3492 	BView_SetHighColor (view, FRAME_BACKGROUND_PIXEL (f));
3493 
3494       BView_FillRectangle (view, 0, margin, width, border);
3495       BView_FillRectangle (view, 0, 0, border, height);
3496       BView_FillRectangle (view, 0, margin, width, border);
3497       BView_FillRectangle (view, width - border, 0, border, height);
3498       BView_FillRectangle (view, 0, height - border, width, border);
3499       BView_EndClip (view);
3500       BView_draw_unlock (view);
3501       unblock_input ();
3502     }
3503 }
3504 
3505 void
mark_haiku_display(void)3506 mark_haiku_display (void)
3507 {
3508   if (x_display_list)
3509     mark_object (x_display_list->color_map);
3510 }
3511 
3512 void
haiku_scroll_bar_remove(struct scroll_bar * bar)3513 haiku_scroll_bar_remove (struct scroll_bar *bar)
3514 {
3515   block_input ();
3516   void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (XWINDOW (bar->window)));
3517   BView_forget_scroll_bar (view, bar->left, bar->top, bar->width, bar->height);
3518   BScrollBar_delete (bar->scroll_bar);
3519   expose_frame (WINDOW_XFRAME (XWINDOW (bar->window)),
3520 		bar->left, bar->top, bar->width, bar->height);
3521 
3522   if (bar->horizontal)
3523     wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
3524   else
3525     wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
3526 
3527   unblock_input ();
3528 };
3529 
3530 void
haiku_set_offset(struct frame * frame,int x,int y,int change_gravity)3531 haiku_set_offset (struct frame *frame, int x, int y,
3532 		  int change_gravity)
3533 {
3534   if (change_gravity > 0)
3535     {
3536       frame->top_pos = y;
3537       frame->left_pos = x;
3538       frame->size_hint_flags &= ~ (XNegative | YNegative);
3539       if (x < 0)
3540 	frame->size_hint_flags |= XNegative;
3541       if (y < 0)
3542 	frame->size_hint_flags |= YNegative;
3543       frame->win_gravity = NorthWestGravity;
3544     }
3545 
3546   haiku_update_size_hints (frame);
3547 
3548   block_input ();
3549   if (change_gravity)
3550     BWindow_set_offset (FRAME_HAIKU_WINDOW (frame), x, y);
3551   unblock_input ();
3552 }
3553 
3554 #ifdef USE_BE_CAIRO
3555 cairo_t *
haiku_begin_cr_clip(struct frame * f,struct glyph_string * s)3556 haiku_begin_cr_clip (struct frame *f, struct glyph_string *s)
3557 {
3558   cairo_surface_t *surface = FRAME_CR_SURFACE (f);
3559   if (!surface)
3560     return NULL;
3561 
3562   cairo_t *context = cairo_create (surface);
3563   return context;
3564 }
3565 
3566 void
haiku_end_cr_clip(cairo_t * cr)3567 haiku_end_cr_clip (cairo_t *cr)
3568 {
3569   cairo_destroy (cr);
3570 }
3571 #endif
3572 
3573 void
syms_of_haikuterm(void)3574 syms_of_haikuterm (void)
3575 {
3576   DEFVAR_BOOL ("haiku-initialized", haiku_initialized,
3577      doc: /* Non-nil if the Haiku terminal backend has been initialized.  */);
3578 
3579   DEFVAR_BOOL ("x-use-underline-position-properties",
3580 	       x_use_underline_position_properties,
3581      doc: /* SKIP: real doc in xterm.c.  */);
3582   x_use_underline_position_properties = 1;
3583 
3584   DEFVAR_BOOL ("x-underline-at-descent-line",
3585 	       x_underline_at_descent_line,
3586      doc: /* SKIP: real doc in xterm.c.  */);
3587   x_underline_at_descent_line = 0;
3588 
3589   DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
3590      doc: /* SKIP: real doc in xterm.c.  */);
3591   Vx_toolkit_scroll_bars = Qt;
3592 
3593   DEFVAR_BOOL ("haiku-debug-on-fatal-error", haiku_debug_on_fatal_error,
3594      doc: /* If non-nil, Emacs will launch the system debugger upon a fatal error.  */);
3595   haiku_debug_on_fatal_error = 1;
3596 
3597   DEFSYM (Qshift, "shift");
3598   DEFSYM (Qcontrol, "control");
3599   DEFSYM (Qoption, "option");
3600   DEFSYM (Qcommand, "command");
3601 
3602   DEFVAR_LISP ("haiku-meta-keysym", Vhaiku_meta_keysym,
3603      doc: /* Which key Emacs uses as the meta modifier.
3604 This is either one of the symbols `shift', `control', `command', and
3605 `option', or nil, in which case it is treated as `command'.
3606 
3607 Setting it to any other value is equivalent to `command'.  */);
3608   Vhaiku_meta_keysym = Qnil;
3609 
3610   DEFVAR_LISP ("haiku-control-keysym", Vhaiku_control_keysym,
3611      doc: /* Which key Emacs uses as the control modifier.
3612 This is either one of the symbols `shift', `control', `command', and
3613 `option', or nil, in which case it is treated as `control'.
3614 
3615 Setting it to any other value is equivalent to `control'.  */);
3616   Vhaiku_control_keysym = Qnil;
3617 
3618   DEFVAR_LISP ("haiku-super-keysym", Vhaiku_super_keysym,
3619      doc: /* Which key Emacs uses as the super modifier.
3620 This is either one of the symbols `shift', `control', `command', and
3621 `option', or nil, in which case it is treated as `option'.
3622 
3623 Setting it to any other value is equivalent to `option'.  */);
3624   Vhaiku_super_keysym = Qnil;
3625 
3626   DEFVAR_LISP ("haiku-shift-keysym", Vhaiku_shift_keysym,
3627      doc: /* Which key Emacs uses as the shift modifier.
3628 This is either one of the symbols `shift', `control', `command', and
3629 `option', or nil, in which case it is treated as `shift'.
3630 
3631 Setting it to any other value is equivalent to `shift'.  */);
3632   Vhaiku_shift_keysym = Qnil;
3633 
3634 
3635   DEFSYM (Qx_use_underline_position_properties,
3636 	  "x-use-underline-position-properties");
3637 
3638   DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
3639 
3640   rdb = Qnil;
3641   staticpro (&rdb);
3642 
3643   Fprovide (Qhaiku, Qnil);
3644 #ifdef USE_BE_CAIRO
3645   Fprovide (intern_c_string ("cairo"), Qnil);
3646 #endif
3647 }
3648