blob: a17b4f5d03091bfc7e397035cd3d8637897e228b [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 * Photon GUI support by Julian Kinraid
5 *
6 * Do ":help uganda" in Vim to read copying and usage conditions.
7 * Do ":help credits" in Vim to see a list of people who contributed.
8 *
9 *
10 * Clipboard support is in os_qnx.c
11 * PhAttach() is called in os_qnx.c:qnx_init()
12 */
13
14#include "vim.h"
15
Bram Moolenaar734a8672019-12-02 22:49:38 +010016// cproto fails on missing include files
Bram Moolenaar82881492012-11-20 16:53:39 +010017#ifndef PROTO
18# ifdef FEAT_TOOLBAR
19# include <photon/PxImage.h>
20# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000021#endif
22
23#if !defined(__QNX__)
Bram Moolenaar734a8672019-12-02 22:49:38 +010024// Used when generating prototypes.
Bram Moolenaar071d4272004-06-13 20:20:40 +000025# define PgColor_t int
26# define PhEvent_t int
27# define PhPoint_t int
28# define PtWidget_t int
29# define Pg_BLACK 0
30# define PtCallbackF_t int
31# define PtCallbackInfo_t int
32# define PhTile_t int
33# define PtWidget_t int
34# define PhImage_t int
35#endif
36
Bram Moolenaard2221132011-07-27 14:09:09 +020037#define RGB(r, g, b) PgRGB(r, g, b)
Bram Moolenaar071d4272004-06-13 20:20:40 +000038
Bram Moolenaard2221132011-07-27 14:09:09 +020039#define EVENT_BUFFER_SIZE sizeof(PhEvent_t) + 1000
Bram Moolenaar071d4272004-06-13 20:20:40 +000040
Bram Moolenaar734a8672019-12-02 22:49:38 +010041// Some defines for gui_mch_mousehide()
Bram Moolenaar071d4272004-06-13 20:20:40 +000042#define MOUSE_HIDE TRUE
43#define MOUSE_SHOW FALSE
44
Bram Moolenaar734a8672019-12-02 22:49:38 +010045// Optional support for using a PtPanelGroup widget, needs work
Bram Moolenaar071d4272004-06-13 20:20:40 +000046#undef USE_PANEL_GROUP
47
48#ifdef USE_PANEL_GROUP
49static char *empty_title = " ";
50static char **panel_titles = NULL;
51static ushort_t num_panels = 0;
52static short pg_margin_left, pg_margin_right, pg_margin_top, pg_margin_bottom;
53#endif
54
Bram Moolenaar734a8672019-12-02 22:49:38 +010055#define GUI_PH_MARGIN 4 // Size of the bevel
Bram Moolenaar071d4272004-06-13 20:20:40 +000056
57#define GUI_PH_MOUSE_TYPE Ph_CURSOR_INSERT
58static PgColor_t gui_ph_mouse_color = Pg_BLACK;
59
60static PhPoint_t gui_ph_raw_offset;
Bram Moolenaar734a8672019-12-02 22:49:38 +010061static PtWidget_t *gui_ph_timer_cursor; // handle cursor blinking
62static PtWidget_t *gui_ph_timer_timeout; // used in gui_mch_wait_for_chars
63static short is_timeout; // Has the timeout occurred?
Bram Moolenaar071d4272004-06-13 20:20:40 +000064
65/*
66 * This is set inside the mouse callback for a right mouse
67 * button click, and used for the popup menus
68 */
69static PhPoint_t abs_mouse;
70
Bram Moolenaar734a8672019-12-02 22:49:38 +010071// Try and avoid redraws while a resize is in progress
Bram Moolenaar071d4272004-06-13 20:20:40 +000072static int is_ignore_draw = FALSE;
73
Bram Moolenaar734a8672019-12-02 22:49:38 +010074// Used for converting to/from utf-8 and other charsets
Bram Moolenaar071d4272004-06-13 20:20:40 +000075static struct PxTransCtrl *charset_translate;
76
77/*
78 * Cursor blink functions.
79 *
80 * This is a simple state machine:
81 * BLINK_NONE not blinking at all
82 * BLINK_OFF blinking, cursor is not shown
83 * BLINK_ON blinking, cursor is shown
84 */
85static enum {
86 BLINK_NONE,
87 BLINK_OFF,
88 BLINK_ON
89} blink_state = BLINK_NONE;
90
91static long_u blink_waittime = 700;
92static long_u blink_ontime = 400;
93static long_u blink_offtime = 250;
94
95static struct
96{
97 int key_sym;
98 char_u vim_code0;
99 char_u vim_code1;
100} special_keys[] =
101{
102 {Pk_Up, 'k', 'u'},
103 {Pk_Down, 'k', 'd'},
104 {Pk_Left, 'k', 'l'},
105 {Pk_Right, 'k', 'r'},
106
107 {Pk_F1, 'k', '1'},
108 {Pk_F2, 'k', '2'},
109 {Pk_F3, 'k', '3'},
110 {Pk_F4, 'k', '4'},
111 {Pk_F5, 'k', '5'},
112 {Pk_F6, 'k', '6'},
113 {Pk_F7, 'k', '7'},
114 {Pk_F8, 'k', '8'},
115 {Pk_F9, 'k', '9'},
116 {Pk_F10, 'k', ';'},
117
118 {Pk_F11, 'F', '1'},
119 {Pk_F12, 'F', '2'},
120 {Pk_F13, 'F', '3'},
121 {Pk_F14, 'F', '4'},
122 {Pk_F15, 'F', '5'},
123 {Pk_F16, 'F', '6'},
124 {Pk_F17, 'F', '7'},
125 {Pk_F18, 'F', '8'},
126 {Pk_F19, 'F', '9'},
127 {Pk_F20, 'F', 'A'},
128
129 {Pk_F21, 'F', 'B'},
130 {Pk_F22, 'F', 'C'},
131 {Pk_F23, 'F', 'D'},
132 {Pk_F24, 'F', 'E'},
133 {Pk_F25, 'F', 'F'},
134 {Pk_F26, 'F', 'G'},
135 {Pk_F27, 'F', 'H'},
136 {Pk_F28, 'F', 'I'},
137 {Pk_F29, 'F', 'J'},
138
139 {Pk_F30, 'F', 'K'},
140 {Pk_F31, 'F', 'L'},
141 {Pk_F32, 'F', 'M'},
142 {Pk_F33, 'F', 'N'},
143 {Pk_F34, 'F', 'O'},
144 {Pk_F35, 'F', 'P'},
145
146 {Pk_Help, '%', '1'},
147 {Pk_BackSpace, 'k', 'b'},
148 {Pk_Insert, 'k', 'I'},
149 {Pk_Delete, 'k', 'D'},
150 {Pk_Home, 'k', 'h'},
151 {Pk_End, '@', '7'},
152 {Pk_Prior, 'k', 'P'},
153 {Pk_Next, 'k', 'N'},
154 {Pk_Print, '%', '9'},
155
156 {Pk_KP_Add, 'K', '6'},
157 {Pk_KP_Subtract,'K', '7'},
158 {Pk_KP_Divide, 'K', '8'},
159 {Pk_KP_Multiply,'K', '9'},
160 {Pk_KP_Enter, 'K', 'A'},
161
Bram Moolenaar734a8672019-12-02 22:49:38 +0100162 {Pk_KP_0, KS_EXTRA, KE_KINS}, // Insert
163 {Pk_KP_Decimal, KS_EXTRA, KE_KDEL}, // Delete
Bram Moolenaar071d4272004-06-13 20:20:40 +0000164
Bram Moolenaar734a8672019-12-02 22:49:38 +0100165 {Pk_KP_4, 'k', 'l'}, // Left
166 {Pk_KP_6, 'k', 'r'}, // Right
167 {Pk_KP_8, 'k', 'u'}, // Up
168 {Pk_KP_2, 'k', 'd'}, // Down
Bram Moolenaar071d4272004-06-13 20:20:40 +0000169
Bram Moolenaar734a8672019-12-02 22:49:38 +0100170 {Pk_KP_7, 'K', '1'}, // Home
171 {Pk_KP_1, 'K', '4'}, // End
Bram Moolenaar071d4272004-06-13 20:20:40 +0000172
Bram Moolenaar734a8672019-12-02 22:49:38 +0100173 {Pk_KP_9, 'K', '3'}, // Page Up
174 {Pk_KP_3, 'K', '5'}, // Page Down
Bram Moolenaar071d4272004-06-13 20:20:40 +0000175
Bram Moolenaar734a8672019-12-02 22:49:38 +0100176 {Pk_KP_5, '&', '8'}, // Undo
Bram Moolenaar071d4272004-06-13 20:20:40 +0000177
Bram Moolenaar734a8672019-12-02 22:49:38 +0100178 // Keys that we want to be able to use any modifier with:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000179 {Pk_Return, CAR, NUL},
180 {Pk_space, ' ', NUL},
181 {Pk_Tab, TAB, NUL},
182 {Pk_Escape, ESC, NUL},
183 {NL, NL, NUL},
184 {CAR, CAR, NUL},
185
Bram Moolenaar734a8672019-12-02 22:49:38 +0100186 // End of list marker:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000187 {0, 0, 0}
188};
189
190
Bram Moolenaar734a8672019-12-02 22:49:38 +0100191////////////////////////////////////////////////////////////////////////////
Bram Moolenaar071d4272004-06-13 20:20:40 +0000192
193static PtCallbackF_t gui_ph_handle_timer_cursor;
194static PtCallbackF_t gui_ph_handle_timer_timeout;
195
196static PtCallbackF_t gui_ph_handle_window_cb;
197
198static PtCallbackF_t gui_ph_handle_scrollbar;
199static PtCallbackF_t gui_ph_handle_keyboard;
200static PtCallbackF_t gui_ph_handle_mouse;
201static PtCallbackF_t gui_ph_handle_pulldown_menu;
202static PtCallbackF_t gui_ph_handle_menu;
Bram Moolenaar734a8672019-12-02 22:49:38 +0100203static PtCallbackF_t gui_ph_handle_focus; // focus change of text area
Bram Moolenaar071d4272004-06-13 20:20:40 +0000204
205static PtCallbackF_t gui_ph_handle_menu_resize;
206
Bram Moolenaar734a8672019-12-02 22:49:38 +0100207// When a menu is unrealized, give focus back to vimTextArea
Bram Moolenaar071d4272004-06-13 20:20:40 +0000208static PtCallbackF_t gui_ph_handle_menu_unrealized;
209
210#ifdef USE_PANEL_GROUP
Bram Moolenaard2221132011-07-27 14:09:09 +0200211static void gui_ph_get_panelgroup_margins(short*, short*, short*, short*);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000212#endif
213
Bram Moolenaard2221132011-07-27 14:09:09 +0200214static void gui_ph_draw_start(void);
215static void gui_ph_draw_end(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000216
Bram Moolenaar734a8672019-12-02 22:49:38 +0100217// Set the text for the balloon
Bram Moolenaard2221132011-07-27 14:09:09 +0200218static PtWidget_t * gui_ph_show_tooltip(PtWidget_t *window,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000219 PtWidget_t *widget,
220 int position,
221 char *text,
222 char *font,
223 PgColor_t fill_color,
Bram Moolenaard2221132011-07-27 14:09:09 +0200224 PgColor_t text_color);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000225
Bram Moolenaar734a8672019-12-02 22:49:38 +0100226////////////////////////////////////////////////////////////////////////////
Bram Moolenaar071d4272004-06-13 20:20:40 +0000227
Bram Moolenaard2221132011-07-27 14:09:09 +0200228static PtWidget_t * gui_ph_show_tooltip(PtWidget_t *window,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000229 PtWidget_t *widget,
230 int position,
231 char *text,
232 char *font,
233 PgColor_t fill_color,
Bram Moolenaard2221132011-07-27 14:09:09 +0200234 PgColor_t text_color)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000235{
236 PtArg_t arg;
237 vimmenu_T *menu;
238 char_u *tooltip;
239
Bram Moolenaard2221132011-07-27 14:09:09 +0200240 PtSetArg(&arg, Pt_ARG_POINTER, &menu, 0);
241 PtGetResources(widget, 1, &arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000242
Bram Moolenaar734a8672019-12-02 22:49:38 +0100243 // Override the text and position
Bram Moolenaar071d4272004-06-13 20:20:40 +0000244
245 tooltip = text;
Bram Moolenaard2221132011-07-27 14:09:09 +0200246 if (menu != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000247 {
248 int index = MENU_INDEX_TIP;
Bram Moolenaard2221132011-07-27 14:09:09 +0200249 if (menu->strings[ index ] != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000250 tooltip = menu->strings[ index ];
251 }
252
Bram Moolenaard2221132011-07-27 14:09:09 +0200253 return PtInflateBalloon(
Bram Moolenaar071d4272004-06-13 20:20:40 +0000254 window,
255 widget,
Bram Moolenaar734a8672019-12-02 22:49:38 +0100256 // Don't put the balloon at the bottom,
257 // it gets drawn over by gfx done in the PtRaw
Bram Moolenaar071d4272004-06-13 20:20:40 +0000258 Pt_BALLOON_TOP,
259 tooltip,
260 font,
261 fill_color,
Bram Moolenaard2221132011-07-27 14:09:09 +0200262 text_color);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000263}
264
265 static void
Bram Moolenaard2221132011-07-27 14:09:09 +0200266gui_ph_resize_container(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000267{
268 PhArea_t area;
269
Bram Moolenaard2221132011-07-27 14:09:09 +0200270 PtWidgetArea(gui.vimWindow, &area);
271 PtWidgetPos (gui.vimContainer, &area.pos);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000272
Bram Moolenaard2221132011-07-27 14:09:09 +0200273 PtSetResource(gui.vimContainer, Pt_ARG_AREA, &area, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000274}
275
276 static int
277gui_ph_handle_menu_resize(
278 PtWidget_t *widget,
279 void *other,
Bram Moolenaard2221132011-07-27 14:09:09 +0200280 PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000281{
282 PtContainerCallback_t *sizes = info->cbdata;
283 PtWidget_t *container;
284 PhPoint_t below_menu;
285 int_u height;
286
287 height = sizes->new_dim.h;
288
Bram Moolenaar734a8672019-12-02 22:49:38 +0100289 // Because vim treats the toolbar and menubar separately,
290 // and here they're lumped together into a PtToolbarGroup,
291 // we only need either menu_height or toolbar_height set at once
Bram Moolenaard2221132011-07-27 14:09:09 +0200292 if (gui.menu_is_active)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000293 {
294 gui.menu_height = height;
295 gui.toolbar_height = 0;
296 }
297#ifdef FEAT_TOOLBAR
298 else
299 gui.toolbar_height = height;
300#endif
301
302 below_menu.x = 0;
303 below_menu.y = height;
304
305#ifdef USE_PANEL_GROUP
306 container = gui.vimPanelGroup;
307#else
308 container = gui.vimContainer;
309#endif
310
Bram Moolenaard2221132011-07-27 14:09:09 +0200311 PtSetResource(container, Pt_ARG_POS, &below_menu, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000312
313 gui_ph_resize_container();
314
315#ifdef USE_PANEL_GROUP
316 gui_ph_get_panelgroup_margins(
317 &pg_margin_top, &pg_margin_bottom,
Bram Moolenaard2221132011-07-27 14:09:09 +0200318 &pg_margin_left, &pg_margin_right);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000319#endif
Bram Moolenaard2221132011-07-27 14:09:09 +0200320 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000321}
322
323/*
324 * Pt_ARG_TIMER_REPEAT isn't used because the on & off times
325 * are different
326 */
327 static int
328gui_ph_handle_timer_cursor(
329 PtWidget_t *widget,
330 void *data,
Bram Moolenaard2221132011-07-27 14:09:09 +0200331 PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000332{
Bram Moolenaard2221132011-07-27 14:09:09 +0200333 if (blink_state == BLINK_ON)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000334 {
335 gui_undraw_cursor();
336 blink_state = BLINK_OFF;
Bram Moolenaard2221132011-07-27 14:09:09 +0200337 PtSetResource(gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL,
338 blink_offtime, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000339 }
340 else
341 {
342 gui_update_cursor(TRUE, FALSE);
343 blink_state = BLINK_ON;
Bram Moolenaard2221132011-07-27 14:09:09 +0200344 PtSetResource(gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL,
345 blink_ontime, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000346 }
Bram Moolenaard2221132011-07-27 14:09:09 +0200347 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000348}
349
350 static int
351gui_ph_handle_timer_timeout(PtWidget_t *widget, void *data, PtCallbackInfo_t *info)
352{
353 is_timeout = TRUE;
354
Bram Moolenaard2221132011-07-27 14:09:09 +0200355 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000356}
357
358 static int
Bram Moolenaard0988c52011-08-10 12:19:04 +0200359gui_ph_handle_window_cb(PtWidget_t *widget, void *data, PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000360{
361 PhWindowEvent_t *we = info->cbdata;
362 ushort_t *width, *height;
363
Bram Moolenaarebfec1c2023-01-22 21:14:53 +0000364 switch (we->event_f)
365 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000366 case Ph_WM_CLOSE:
367 gui_shell_closed();
368 break;
369
370 case Ph_WM_FOCUS:
Bram Moolenaar734a8672019-12-02 22:49:38 +0100371 // Just in case it's hidden and needs to be shown
Bram Moolenaard0988c52011-08-10 12:19:04 +0200372 gui_mch_mousehide(MOUSE_SHOW);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000373
Bram Moolenaard0988c52011-08-10 12:19:04 +0200374 if (we->event_state == Ph_WM_EVSTATE_FOCUS)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000375 {
376 gui_focus_change(TRUE);
377 gui_mch_start_blink();
378 }
379 else
380 {
381 gui_focus_change(FALSE);
Bram Moolenaar1dd45fb2018-01-31 21:10:01 +0100382 gui_mch_stop_blink(TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000383 }
384 break;
385
386 case Ph_WM_RESIZE:
Bram Moolenaard0988c52011-08-10 12:19:04 +0200387 PtGetResource(gui.vimWindow, Pt_ARG_WIDTH, &width, 0);
388 PtGetResource(gui.vimWindow, Pt_ARG_HEIGHT, &height, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000389#ifdef USE_PANEL_GROUP
390 width -= (pg_margin_left + pg_margin_right);
391 height -= (pg_margin_top + pg_margin_bottom);
392#endif
Bram Moolenaard0988c52011-08-10 12:19:04 +0200393 gui_resize_shell(*width, *height);
394 gui_set_shellsize(FALSE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000395 is_ignore_draw = FALSE;
Bram Moolenaard0988c52011-08-10 12:19:04 +0200396 PtEndFlux(gui.vimContainer);
397 PtContainerRelease(gui.vimContainer);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000398 break;
399
400 default:
401 break;
402 }
403
Bram Moolenaard2221132011-07-27 14:09:09 +0200404 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000405}
406
407 static int
Bram Moolenaard0988c52011-08-10 12:19:04 +0200408gui_ph_handle_scrollbar(PtWidget_t *widget, void *data, PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000409{
410 PtScrollbarCallback_t *scroll;
411 scrollbar_T *sb;
412 int value, dragging = FALSE;
413
414 scroll = info->cbdata;
415
416 sb = (scrollbar_T *) data;
Bram Moolenaard0988c52011-08-10 12:19:04 +0200417 if (sb != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000418 {
419 value = scroll->position;
Bram Moolenaard0988c52011-08-10 12:19:04 +0200420 switch (scroll->action)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000421 {
422 case Pt_SCROLL_DRAGGED:
423 dragging = TRUE;
424 break;
425
426 case Pt_SCROLL_SET:
Bram Moolenaar734a8672019-12-02 22:49:38 +0100427 // FIXME: return straight away here?
Bram Moolenaard2221132011-07-27 14:09:09 +0200428 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000429 break;
430 }
431
432 gui_drag_scrollbar(sb, value, dragging);
433 }
Bram Moolenaard2221132011-07-27 14:09:09 +0200434 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000435}
436
437 static int
Bram Moolenaard0988c52011-08-10 12:19:04 +0200438gui_ph_handle_keyboard(PtWidget_t *widget, void *data, PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000439{
440 PhKeyEvent_t *key;
441 unsigned char string[6];
442 int len, i;
443 int ch, modifiers;
444
Bram Moolenaard0988c52011-08-10 12:19:04 +0200445 key = PhGetData(info->event);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000446
447 ch = modifiers = len = 0;
448
Bram Moolenaard0988c52011-08-10 12:19:04 +0200449 if (p_mh)
450 gui_mch_mousehide(MOUSE_HIDE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000451
Bram Moolenaar734a8672019-12-02 22:49:38 +0100452 // We're a good lil photon program, aren't we? yes we are, yeess wee arrr
Bram Moolenaard0988c52011-08-10 12:19:04 +0200453 if (key->key_flags & Pk_KF_Compose)
Bram Moolenaard2221132011-07-27 14:09:09 +0200454 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000455
Bram Moolenaard0988c52011-08-10 12:19:04 +0200456 if ((key->key_flags & Pk_KF_Cap_Valid) &&
457 PkIsKeyDown(key->key_flags))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000458 {
459#ifdef FEAT_MENU
460 /*
461 * Only show the menu if the Alt key is down, and the Shift & Ctrl
462 * keys aren't down, as well as the other conditions
463 */
Bram Moolenaard0988c52011-08-10 12:19:04 +0200464 if (((key->key_mods & Pk_KM_Alt) &&
465 !(key->key_mods & Pk_KM_Shift) &&
466 !(key->key_mods & Pk_KM_Ctrl)) &&
Bram Moolenaar071d4272004-06-13 20:20:40 +0000467 gui.menu_is_active &&
Bram Moolenaard0988c52011-08-10 12:19:04 +0200468 (*p_wak == 'y' ||
469 (*p_wak == 'm' &&
470 gui_is_menu_shortcut(key->key_cap))))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000471 {
Bram Moolenaar734a8672019-12-02 22:49:38 +0100472 // Fallthrough and let photon look for the hotkey
Bram Moolenaard2221132011-07-27 14:09:09 +0200473 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000474 }
475#endif
476
Bram Moolenaar15d63192011-09-14 16:05:15 +0200477 for (i = 0; special_keys[i].key_sym != 0; i++)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000478 {
Bram Moolenaard0988c52011-08-10 12:19:04 +0200479 if (special_keys[i].key_sym == key->key_cap)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000480 {
481 len = 0;
Bram Moolenaard0988c52011-08-10 12:19:04 +0200482 if (special_keys[i].vim_code1 == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000483 ch = special_keys[i].vim_code0;
484 else
485 {
Bram Moolenaar734a8672019-12-02 22:49:38 +0100486 // Detect if a keypad number key has been pressed
487 // and change the key if Num Lock is on
Bram Moolenaard0988c52011-08-10 12:19:04 +0200488 if (key->key_cap >= Pk_KP_Enter && key->key_cap <= Pk_KP_9
489 && (key->key_mods & Pk_KM_Num_Lock))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000490 {
Dominique Pelleaf4a61a2021-12-27 17:21:41 +0000491 // FIXME: For now, just map the key to an ascii value
Bram Moolenaar734a8672019-12-02 22:49:38 +0100492 // (see <photon/PkKeyDef.h>)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000493 ch = key->key_cap - 0xf080;
494 }
495 else
Bram Moolenaard0988c52011-08-10 12:19:04 +0200496 ch = TO_SPECIAL(special_keys[i].vim_code0,
497 special_keys[i].vim_code1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000498 }
499 break;
500 }
501 }
502
Bram Moolenaard0988c52011-08-10 12:19:04 +0200503 if (key->key_mods & Pk_KM_Ctrl)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000504 modifiers |= MOD_MASK_CTRL;
Bram Moolenaard0988c52011-08-10 12:19:04 +0200505 if (key->key_mods & Pk_KM_Alt)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000506 modifiers |= MOD_MASK_ALT;
Bram Moolenaard0988c52011-08-10 12:19:04 +0200507 if (key->key_mods & Pk_KM_Shift)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000508 modifiers |= MOD_MASK_SHIFT;
509
Bram Moolenaar734a8672019-12-02 22:49:38 +0100510 // Is this not a special key?
Bram Moolenaard0988c52011-08-10 12:19:04 +0200511 if (special_keys[i].key_sym == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000512 {
Bram Moolenaard0988c52011-08-10 12:19:04 +0200513 ch = PhTo8859_1(key);
Bram Moolenaar13505972019-01-24 15:04:48 +0100514 if (ch == -1 || (enc_utf8 && ch > 127))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000515 {
Bram Moolenaard0988c52011-08-10 12:19:04 +0200516 len = PhKeyToMb(string, key);
517 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000518 {
519 static char buf[6];
520 int src_taken, dst_made;
Bram Moolenaard0988c52011-08-10 12:19:04 +0200521 if (enc_utf8 != TRUE)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000522 {
523 PxTranslateFromUTF(
524 charset_translate,
525 string,
526 len,
527 &src_taken,
528 buf,
529 6,
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200530 &dst_made);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000531
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200532 add_to_input_buf(buf, dst_made);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000533 }
534 else
535 {
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200536 add_to_input_buf(string, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000537 }
538
Bram Moolenaard2221132011-07-27 14:09:09 +0200539 return Pt_CONSUME;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000540 }
541 len = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000542 ch = key->key_cap;
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200543 if (ch < 0xff)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000544 {
Bram Moolenaar734a8672019-12-02 22:49:38 +0100545 // FIXME: is this the right thing to do?
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200546 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000547 {
548 modifiers &= ~MOD_MASK_CTRL;
549
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200550 if ((ch >= 'a' && ch <= 'z') ||
Bram Moolenaar071d4272004-06-13 20:20:40 +0000551 ch == '[' ||
552 ch == ']' ||
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200553 ch == '\\')
554 ch = Ctrl_chr(ch);
555 else if (ch == '2')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000556 ch = NUL;
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200557 else if (ch == '6')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000558 ch = 0x1e;
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200559 else if (ch == '-')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000560 ch = 0x1f;
561 else
562 modifiers |= MOD_MASK_CTRL;
563 }
564
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200565 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000566 {
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200567 ch = Meta(ch);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000568 modifiers &= ~MOD_MASK_ALT;
569 }
570 }
571 else
572 {
Bram Moolenaard2221132011-07-27 14:09:09 +0200573 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000574 }
575 }
576 else
577 modifiers &= ~MOD_MASK_SHIFT;
578 }
579
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200580 ch = simplify_key(ch, &modifiers);
581 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000582 {
583 string[ len++ ] = CSI;
584 string[ len++ ] = KS_MODIFIER;
585 string[ len++ ] = modifiers;
586 }
587
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200588 if (IS_SPECIAL(ch))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000589 {
590 string[ len++ ] = CSI;
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200591 string[ len++ ] = K_SECOND(ch);
592 string[ len++ ] = K_THIRD(ch);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000593 }
594 else
595 {
596 string[ len++ ] = ch;
597 }
598
Bram Moolenaar4e1d8bd2020-08-01 13:10:14 +0200599 // Check if the key interrupts.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000600 {
Bram Moolenaar4e1d8bd2020-08-01 13:10:14 +0200601 int int_ch = check_for_interrupt(ch, modifiers);
602
603 if (int_ch != NUL)
604 {
605 ch = int_ch;
606 string[0] = ch;
607 len = 1;
608 trash_input_buf();
609 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000610 }
611
612 if (len == 1 && string[0] == CSI)
613 {
Bram Moolenaar734a8672019-12-02 22:49:38 +0100614 // Turn CSI into K_CSI.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000615 string[ len++ ] = KS_EXTRA;
616 string[ len++ ] = KE_CSI;
617 }
618
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200619 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000620 {
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200621 add_to_input_buf(string, len);
Bram Moolenaard2221132011-07-27 14:09:09 +0200622 return Pt_CONSUME;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000623 }
624 }
625
Bram Moolenaard2221132011-07-27 14:09:09 +0200626 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000627}
628
629 static int
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200630gui_ph_handle_mouse(PtWidget_t *widget, void *data, PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000631{
632 PhPointerEvent_t *pointer;
633 PhRect_t *pos;
634 int button = 0, repeated_click, modifiers = 0x0;
635 short mouse_x, mouse_y;
636
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200637 pointer = PhGetData(info->event);
638 pos = PhGetRects(info->event);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000639
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200640 gui_mch_mousehide(MOUSE_SHOW);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000641
642 /*
643 * Coordinates need to be relative to the base window,
644 * not relative to the vimTextArea widget
645 */
646 mouse_x = pos->ul.x + gui.border_width;
647 mouse_y = pos->ul.y + gui.border_width;
648
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200649 if (info->event->type == Ph_EV_PTR_MOTION_NOBUTTON)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000650 {
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200651 gui_mouse_moved(mouse_x, mouse_y);
Bram Moolenaard2221132011-07-27 14:09:09 +0200652 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000653 }
654
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200655 if (pointer->key_mods & Pk_KM_Shift)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000656 modifiers |= MOUSE_SHIFT;
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200657 if (pointer->key_mods & Pk_KM_Ctrl)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000658 modifiers |= MOUSE_CTRL;
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200659 if (pointer->key_mods & Pk_KM_Alt)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000660 modifiers |= MOUSE_ALT;
661
662 /*
663 * FIXME More than one button may be involved, but for
664 * now just deal with one
665 */
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200666 if (pointer->buttons & Ph_BUTTON_SELECT)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000667 button = MOUSE_LEFT;
668
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200669 if (pointer->buttons & Ph_BUTTON_MENU)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000670 {
671 button = MOUSE_RIGHT;
Bram Moolenaar734a8672019-12-02 22:49:38 +0100672 // Need the absolute coordinates for the popup menu
Bram Moolenaar071d4272004-06-13 20:20:40 +0000673 abs_mouse.x = pointer->pos.x;
674 abs_mouse.y = pointer->pos.y;
675 }
676
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200677 if (pointer->buttons & Ph_BUTTON_ADJUST)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000678 button = MOUSE_MIDDLE;
679
Bram Moolenaar734a8672019-12-02 22:49:38 +0100680 // Catch a real release (not phantom or other releases
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200681 if (info->event->type == Ph_EV_BUT_RELEASE)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000682 button = MOUSE_RELEASE;
683
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200684 if (info->event->type & Ph_EV_PTR_MOTION_BUTTON)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000685 button = MOUSE_DRAG;
686
687#if 0
Bram Moolenaar734a8672019-12-02 22:49:38 +0100688 // Vim doesn't use button repeats
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200689 if (info->event->type & Ph_EV_BUT_REPEAT)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000690 button = MOUSE_DRAG;
691#endif
692
Bram Moolenaar734a8672019-12-02 22:49:38 +0100693 // Don't do anything if it is one of the phantom mouse release events
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200694 if ((button != MOUSE_RELEASE) ||
695 (info->event->subtype == Ph_EV_RELEASE_REAL))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000696 {
697 repeated_click = (pointer->click_count >= 2) ? TRUE : FALSE;
698
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200699 gui_send_mouse_event(button , mouse_x, mouse_y, repeated_click, modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000700 }
701
Bram Moolenaard2221132011-07-27 14:09:09 +0200702 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000703}
704
Bram Moolenaar734a8672019-12-02 22:49:38 +0100705/*
706 * Handle a focus change of the PtRaw widget
707 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000708 static int
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200709gui_ph_handle_focus(PtWidget_t *widget, void *data, PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000710{
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200711 if (info->reason == Pt_CB_LOST_FOCUS)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000712 {
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200713 PtRemoveEventHandler(gui.vimTextArea, Ph_EV_PTR_MOTION_NOBUTTON,
714 gui_ph_handle_mouse, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000715
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200716 gui_mch_mousehide(MOUSE_SHOW);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000717 }
718 else
719 {
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200720 PtAddEventHandler(gui.vimTextArea, Ph_EV_PTR_MOTION_NOBUTTON,
721 gui_ph_handle_mouse, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000722 }
Bram Moolenaard2221132011-07-27 14:09:09 +0200723 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000724}
725
726 static void
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200727gui_ph_handle_raw_draw(PtWidget_t *widget, PhTile_t *damage)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000728{
729 PhRect_t *r;
730 PhPoint_t offset;
731 PhPoint_t translation;
732
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200733 if (is_ignore_draw == TRUE)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000734 return;
735
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200736 PtSuperClassDraw(PtBasic, widget, damage);
737 PgGetTranslation(&translation);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000738 PgClearTranslation();
739
740#if 0
741 /*
Bram Moolenaarccc18222007-05-10 18:25:20 +0000742 * This causes some weird problems, with drawing being done from
Bram Moolenaar071d4272004-06-13 20:20:40 +0000743 * within this raw drawing function (rather than just simple clearing
744 * and text drawing done by gui_redraw)
745 *
746 * The main problem is when PhBlit is used, and the cursor appearing
747 * in places where it shouldn't
748 */
749 out_flush();
750#endif
751
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200752 PtWidgetOffset(widget, &offset);
753 PhTranslatePoint(&offset, PtWidgetPos(gui.vimTextArea, NULL));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000754
755#if 1
Bram Moolenaar734a8672019-12-02 22:49:38 +0100756 // Redraw individual damage regions
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200757 if (damage->next != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000758 damage = damage->next;
759
Bram Moolenaar15d63192011-09-14 16:05:15 +0200760 while (damage != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000761 {
762 r = &damage->rect;
763 gui_redraw(
764 r->ul.x - offset.x, r->ul.y - offset.y,
765 r->lr.x - r->ul.x + 1,
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200766 r->lr.y - r->ul.y + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000767 damage = damage->next;
768 }
769#else
Bram Moolenaar734a8672019-12-02 22:49:38 +0100770 // Redraw the rectangle that covers all the damaged regions
Bram Moolenaar071d4272004-06-13 20:20:40 +0000771 r = &damage->rect;
772 gui_redraw(
773 r->ul.x - offset.x, r->ul.y - offset.y,
774 r->lr.x - r->ul.x + 1,
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200775 r->lr.y - r->ul.y + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000776#endif
777
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200778 PgSetTranslation(&translation, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000779}
780
781 static int
782gui_ph_handle_pulldown_menu(
783 PtWidget_t *widget,
784 void *data,
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200785 PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000786{
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200787 if (data != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000788 {
789 vimmenu_T *menu = (vimmenu_T *) data;
790
Bram Moolenaar0d55ff12011-09-07 19:09:01 +0200791 PtPositionMenu(menu->submenu_id, NULL);
792 PtRealizeWidget(menu->submenu_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000793 }
794
Bram Moolenaard2221132011-07-27 14:09:09 +0200795 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000796}
797
Bram Moolenaar734a8672019-12-02 22:49:38 +0100798/*
799 * This is used for pulldown/popup menus and also toolbar buttons
800 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000801 static int
Bram Moolenaar15d63192011-09-14 16:05:15 +0200802gui_ph_handle_menu(PtWidget_t *widget, void *data, PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000803{
Bram Moolenaar15d63192011-09-14 16:05:15 +0200804 if (data != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000805 {
806 vimmenu_T *menu = (vimmenu_T *) data;
Bram Moolenaar15d63192011-09-14 16:05:15 +0200807 gui_menu_cb(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000808 }
Bram Moolenaard2221132011-07-27 14:09:09 +0200809 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810}
811
Bram Moolenaar734a8672019-12-02 22:49:38 +0100812/*
813 * Stop focus from disappearing into the menubar...
814 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000815 static int
816gui_ph_handle_menu_unrealized(
817 PtWidget_t *widget,
818 void *data,
Bram Moolenaar15d63192011-09-14 16:05:15 +0200819 PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820{
Bram Moolenaar15d63192011-09-14 16:05:15 +0200821 PtGiveFocus(gui.vimTextArea, NULL);
Bram Moolenaard2221132011-07-27 14:09:09 +0200822 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000823}
824
825 static int
826gui_ph_handle_window_open(
827 PtWidget_t *widget,
828 void *data,
Bram Moolenaar15d63192011-09-14 16:05:15 +0200829 PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000830{
Bram Moolenaar15d63192011-09-14 16:05:15 +0200831 gui_set_shellsize(FALSE, TRUE, RESIZE_BOTH);
Bram Moolenaard2221132011-07-27 14:09:09 +0200832 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000833}
834
Bram Moolenaar734a8672019-12-02 22:49:38 +0100835////////////////////////////////////////////////////////////////////////////
Bram Moolenaar071d4272004-06-13 20:20:40 +0000836
837#define DRAW_START gui_ph_draw_start()
838#define DRAW_END gui_ph_draw_end()
839
Bram Moolenaar734a8672019-12-02 22:49:38 +0100840/*
841 * TODO: Set a clipping rect?
842 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000843 static void
Bram Moolenaar15d63192011-09-14 16:05:15 +0200844gui_ph_draw_start(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845{
Bram Moolenaara0b19972009-07-01 14:13:18 +0000846 PhGC_t *gc;
847
848 gc = PgGetGC();
Bram Moolenaar15d63192011-09-14 16:05:15 +0200849 PgSetRegion(PtWidgetRid(PtFindDisjoint(gui.vimTextArea)));
850 PgClearClippingsCx(gc);
851 PgClearTranslationCx(gc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000852
Bram Moolenaar15d63192011-09-14 16:05:15 +0200853 PtWidgetOffset(gui.vimTextArea, &gui_ph_raw_offset);
854 PhTranslatePoint(&gui_ph_raw_offset, PtWidgetPos(gui.vimTextArea, NULL));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000855
Bram Moolenaar15d63192011-09-14 16:05:15 +0200856 PgSetTranslation(&gui_ph_raw_offset, Pg_RELATIVE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000857}
858
859 static void
Bram Moolenaar15d63192011-09-14 16:05:15 +0200860gui_ph_draw_end(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000861{
862 gui_ph_raw_offset.x = -gui_ph_raw_offset.x;
863 gui_ph_raw_offset.y = -gui_ph_raw_offset.y;
Bram Moolenaar15d63192011-09-14 16:05:15 +0200864 PgSetTranslation(&gui_ph_raw_offset, Pg_RELATIVE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000865}
866
867#ifdef USE_PANEL_GROUP
868 static vimmenu_T *
Bram Moolenaar15d63192011-09-14 16:05:15 +0200869gui_ph_find_buffer_item(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000870{
871 vimmenu_T *top_level = root_menu;
872 vimmenu_T *items = NULL;
873
Bram Moolenaar15d63192011-09-14 16:05:15 +0200874 while (top_level != NULL &&
875 (STRCMP(top_level->dname, "Buffers") != 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000876 top_level = top_level->next;
877
Bram Moolenaar15d63192011-09-14 16:05:15 +0200878 if (top_level != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000879 {
880 items = top_level->children;
881
Bram Moolenaar15d63192011-09-14 16:05:15 +0200882 while (items != NULL &&
883 (STRCMP(items->dname, name) != 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000884 items = items->next;
885 }
Bram Moolenaard2221132011-07-27 14:09:09 +0200886 return items;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000887}
888
889 static void
Bram Moolenaar15d63192011-09-14 16:05:15 +0200890gui_ph_pg_set_buffer_num(int_u buf_num)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000891{
892 int i;
893 char search[16];
894 char *mark;
895
Bram Moolenaar15d63192011-09-14 16:05:15 +0200896 if (gui.vimTextArea == NULL || buf_num == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000897 return;
898
899 search[0] = '(';
Bram Moolenaar15d63192011-09-14 16:05:15 +0200900 ultoa(buf_num, &search[1], 10);
901 STRCAT(search, ")");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000902
Bram Moolenaar15d63192011-09-14 16:05:15 +0200903 for (i = 0; i < num_panels; i++)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000904 {
Bram Moolenaar734a8672019-12-02 22:49:38 +0100905 // find the last "(" in the panel title and see if the buffer
906 // number in the title matches the one we're looking for
Bram Moolenaar15d63192011-09-14 16:05:15 +0200907 mark = STRRCHR(panel_titles[ i ], '(');
908 if (mark != NULL && STRCMP(mark, search) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000909 {
Bram Moolenaar15d63192011-09-14 16:05:15 +0200910 PtSetResource(gui.vimPanelGroup, Pt_ARG_PG_CURRENT_INDEX,
911 i, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000912 }
913 }
914}
915
916 static int
917gui_ph_handle_pg_change(
918 PtWidget_t *widget,
919 void *data,
Bram Moolenaar15d63192011-09-14 16:05:15 +0200920 PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000921{
922 vimmenu_T *menu;
923 PtPanelGroupCallback_t *panel;
924
Bram Moolenaar15d63192011-09-14 16:05:15 +0200925 if (info->event != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000926 {
927 panel = info->cbdata;
Bram Moolenaar15d63192011-09-14 16:05:15 +0200928 if (panel->new_panel != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000929 {
Bram Moolenaar15d63192011-09-14 16:05:15 +0200930 menu = gui_ph_find_buffer_item(panel->new_panel);
931 if (menu)
932 gui_menu_cb(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000933 }
934 }
Bram Moolenaard2221132011-07-27 14:09:09 +0200935 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000936}
937
938 static void
939gui_ph_get_panelgroup_margins(
940 short *top,
941 short *bottom,
942 short *left,
Bram Moolenaar15d63192011-09-14 16:05:15 +0200943 short *right)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000944{
945 unsigned short abs_raw_x, abs_raw_y, abs_panel_x, abs_panel_y;
946 const unsigned short *margin_top, *margin_bottom;
947 const unsigned short *margin_left, *margin_right;
948
Bram Moolenaar15d63192011-09-14 16:05:15 +0200949 PtGetAbsPosition(gui.vimTextArea, &abs_raw_x, &abs_raw_y);
950 PtGetAbsPosition(gui.vimPanelGroup, &abs_panel_x, &abs_panel_y);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000951
Bram Moolenaar15d63192011-09-14 16:05:15 +0200952 PtGetResource(gui.vimPanelGroup, Pt_ARG_MARGIN_RIGHT, &margin_right, 0);
953 PtGetResource(gui.vimPanelGroup, Pt_ARG_MARGIN_BOTTOM, &margin_bottom, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000954
955 abs_raw_x -= abs_panel_x;
956 abs_raw_y -= abs_panel_y;
957
958 *top = abs_raw_y;
959 *bottom = *margin_bottom;
960
961 *left = abs_raw_x;
962 *right = *margin_right;
963}
964
Bram Moolenaar734a8672019-12-02 22:49:38 +0100965/*
966 * Used for the tabs for PtPanelGroup
967 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000968 static int
Bram Moolenaar15d63192011-09-14 16:05:15 +0200969gui_ph_is_buffer_item(vimmenu_T *menu, vimmenu_T *parent)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000970{
971 char *mark;
972
Bram Moolenaar15d63192011-09-14 16:05:15 +0200973 if (STRCMP(parent->dname, "Buffers") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000974 {
Bram Moolenaar734a8672019-12-02 22:49:38 +0100975 // Look for '(' digits ')'
Bram Moolenaar15d63192011-09-14 16:05:15 +0200976 mark = vim_strchr(menu->dname, '(');
977 if (mark != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000978 {
979 mark++;
Bram Moolenaar15d63192011-09-14 16:05:15 +0200980 while (isdigit(*mark))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000981 mark++;
982
Bram Moolenaar15d63192011-09-14 16:05:15 +0200983 if (*mark == ')')
Bram Moolenaard2221132011-07-27 14:09:09 +0200984 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000985 }
986 }
Bram Moolenaard2221132011-07-27 14:09:09 +0200987 return FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000988}
989
990 static void
Bram Moolenaar15d63192011-09-14 16:05:15 +0200991gui_ph_pg_add_buffer(char *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000992{
993 char **new_titles = NULL;
994
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200995 new_titles = ALLOC_MULT(char *, (num_panels + 1));
Yegappan Lakshmanan7f8b2552023-01-08 13:44:24 +0000996 if (new_titles == NULL)
997 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000998
Yegappan Lakshmanan7f8b2552023-01-08 13:44:24 +0000999 if (num_panels > 0)
1000 memcpy(new_titles, panel_titles, num_panels * sizeof(char **));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001001
Yegappan Lakshmanan7f8b2552023-01-08 13:44:24 +00001002 new_titles[ num_panels++ ] = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001003
Yegappan Lakshmanan7f8b2552023-01-08 13:44:24 +00001004 PtSetResource(gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, new_titles,
1005 num_panels);
1006
1007 vim_free(panel_titles);
1008 panel_titles = new_titles;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001009}
1010
1011 static void
Bram Moolenaar15d63192011-09-14 16:05:15 +02001012gui_ph_pg_remove_buffer(char *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001013{
1014 int i;
1015 char **new_titles = NULL;
1016
Bram Moolenaar734a8672019-12-02 22:49:38 +01001017 // If there is only 1 panel, we just use the temporary place holder
Bram Moolenaar15d63192011-09-14 16:05:15 +02001018 if (num_panels > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001019 {
Bram Moolenaarc799fe22019-05-28 23:08:19 +02001020 new_titles = ALLOC_MULT(char *, num_panels - 1);
Bram Moolenaar15d63192011-09-14 16:05:15 +02001021 if (new_titles != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001022 {
1023 char **s = new_titles;
Bram Moolenaar734a8672019-12-02 22:49:38 +01001024 // Copy all the titles except the one we're removing
Bram Moolenaar15d63192011-09-14 16:05:15 +02001025 for (i = 0; i < num_panels; i++)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001026 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02001027 if (STRCMP(panel_titles[ i ], name) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001028 *s++ = panel_titles[ i ];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001029 }
1030 num_panels--;
1031
Bram Moolenaar15d63192011-09-14 16:05:15 +02001032 PtSetResource(gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, new_titles,
1033 num_panels);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001034
Bram Moolenaar15d63192011-09-14 16:05:15 +02001035 vim_free(panel_titles);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001036 panel_titles = new_titles;
1037 }
1038 }
1039 else
1040 {
1041 num_panels--;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001042 PtSetResource(gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, &empty_title,
1043 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001044
Bram Moolenaard23a8232018-02-10 18:45:26 +01001045 VIM_CLEAR(panel_titles);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001046 }
1047}
1048
Bram Moolenaar734a8672019-12-02 22:49:38 +01001049/*
1050 * When a buffer item is deleted from the buffer menu
1051 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001052 static int
1053gui_ph_handle_buffer_remove(
1054 PtWidget_t *widget,
1055 void *data,
Bram Moolenaar15d63192011-09-14 16:05:15 +02001056 PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001057{
1058 vimmenu_T *menu;
1059
Bram Moolenaar15d63192011-09-14 16:05:15 +02001060 if (data != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001061 {
1062 menu = (vimmenu_T *) data;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001063 gui_ph_pg_remove_buffer(menu->dname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001064 }
1065
Bram Moolenaard2221132011-07-27 14:09:09 +02001066 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001067}
1068#endif
1069
1070 static int
Bram Moolenaar15d63192011-09-14 16:05:15 +02001071gui_ph_pane_resize(PtWidget_t *widget, void *data, PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001072{
Bram Moolenaar15d63192011-09-14 16:05:15 +02001073 if (PtWidgetIsRealized(widget))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001074 {
1075 is_ignore_draw = TRUE;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001076 PtStartFlux(gui.vimContainer);
1077 PtContainerHold(gui.vimContainer);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001078 }
1079
Bram Moolenaard2221132011-07-27 14:09:09 +02001080 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001081}
1082
Bram Moolenaar734a8672019-12-02 22:49:38 +01001083////////////////////////////////////////////////////////////////////////////
Bram Moolenaar071d4272004-06-13 20:20:40 +00001084
Bram Moolenaar071d4272004-06-13 20:20:40 +00001085 void
Bram Moolenaar15d63192011-09-14 16:05:15 +02001086gui_ph_encoding_changed(int new_encoding)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001087{
Bram Moolenaar734a8672019-12-02 22:49:38 +01001088 // Default encoding is latin1
Bram Moolenaar071d4272004-06-13 20:20:40 +00001089 char *charset = "latin1";
1090 int i;
1091
1092 struct {
1093 int encoding;
1094 char *name;
1095 } charsets[] = {
1096 { DBCS_JPN, "SHIFT_JIS" },
1097 { DBCS_KOR, "csEUCKR" },
1098 { DBCS_CHT, "big5" },
1099 { DBCS_CHS, "gb" }
1100 };
1101
Bram Moolenaar15d63192011-09-14 16:05:15 +02001102 for (i = 0; i < ARRAY_LENGTH(charsets); i++)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001103 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02001104 if (new_encoding == charsets[ i ].encoding)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001105 charset = charsets[ i ].name;
1106 }
1107
Bram Moolenaar15d63192011-09-14 16:05:15 +02001108 charset_translate = PxTranslateSet(charset_translate, charset);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001109}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001110
Bram Moolenaar734a8672019-12-02 22:49:38 +01001111////////////////////////////////////////////////////////////////////////////
Bram Moolenaar071d4272004-06-13 20:20:40 +00001112
1113 void
Bram Moolenaar68c2f632016-01-30 17:24:07 +01001114gui_mch_prepare(int *argc, char **argv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001115{
Bram Moolenaar15d63192011-09-14 16:05:15 +02001116 PtInit(NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001117}
1118
1119 int
1120gui_mch_init(void)
1121{
1122 PtArg_t args[10];
1123 int flags = 0, n = 0;
1124
Bram Moolenaar734a8672019-12-02 22:49:38 +01001125 PhDim_t window_size = {100, 100}; // Arbitrary values
Bram Moolenaar071d4272004-06-13 20:20:40 +00001126 PhPoint_t pos = {0, 0};
1127
Bram Moolenaarc799fe22019-05-28 23:08:19 +02001128 gui.event_buffer = alloc(EVENT_BUFFER_SIZE);
Bram Moolenaar15d63192011-09-14 16:05:15 +02001129 if (gui.event_buffer == NULL)
Bram Moolenaard2221132011-07-27 14:09:09 +02001130 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001131
Bram Moolenaar734a8672019-12-02 22:49:38 +01001132 // Get a translation so we can convert from ISO Latin-1 to UTF
Bram Moolenaar15d63192011-09-14 16:05:15 +02001133 charset_translate = PxTranslateSet(NULL, "latin1");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001134
Bram Moolenaar734a8672019-12-02 22:49:38 +01001135 // The +2 is for the 1 pixel dark line on each side
Bram Moolenaar071d4272004-06-13 20:20:40 +00001136 gui.border_offset = gui.border_width = GUI_PH_MARGIN + 2;
1137
Bram Moolenaar734a8672019-12-02 22:49:38 +01001138 // Handle close events ourselves
Bram Moolenaar15d63192011-09-14 16:05:15 +02001139 PtSetArg(&args[ n++ ], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE);
1140 PtSetArg(&args[ n++ ], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE,
1141 Ph_WM_CLOSE | Ph_WM_RESIZE | Ph_WM_FOCUS);
1142 PtSetArg(&args[ n++ ], Pt_ARG_DIM, &window_size, 0);
1143 gui.vimWindow = PtCreateWidget(PtWindow, NULL, n, args);
1144 if (gui.vimWindow == NULL)
Bram Moolenaard2221132011-07-27 14:09:09 +02001145 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001146
Bram Moolenaar15d63192011-09-14 16:05:15 +02001147 PtAddCallback(gui.vimWindow, Pt_CB_WINDOW, gui_ph_handle_window_cb, NULL);
1148 PtAddCallback(gui.vimWindow, Pt_CB_WINDOW_OPENING,
1149 gui_ph_handle_window_open, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001150
1151 n = 0;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001152 PtSetArg(&args[ n++ ], Pt_ARG_ANCHOR_FLAGS, Pt_ANCHOR_ALL, Pt_IS_ANCHORED);
1153 PtSetArg(&args[ n++ ], Pt_ARG_DIM, &window_size, 0);
1154 PtSetArg(&args[ n++ ], Pt_ARG_POS, &pos, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001155
1156#ifdef USE_PANEL_GROUP
Bram Moolenaar734a8672019-12-02 22:49:38 +01001157 // Put in a temporary place holder title
Bram Moolenaar15d63192011-09-14 16:05:15 +02001158 PtSetArg(&args[ n++ ], Pt_ARG_PG_PANEL_TITLES, &empty_title, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001159
Bram Moolenaar15d63192011-09-14 16:05:15 +02001160 gui.vimPanelGroup = PtCreateWidget(PtPanelGroup, gui.vimWindow, n, args);
1161 if (gui.vimPanelGroup == NULL)
Bram Moolenaard2221132011-07-27 14:09:09 +02001162 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001163
Bram Moolenaar15d63192011-09-14 16:05:15 +02001164 PtAddCallback(gui.vimPanelGroup, Pt_CB_PG_PANEL_SWITCHING,
1165 gui_ph_handle_pg_change, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001166#else
Bram Moolenaar734a8672019-12-02 22:49:38 +01001167 // Turn off all edge decorations
Bram Moolenaar15d63192011-09-14 16:05:15 +02001168 PtSetArg(&args[ n++ ], Pt_ARG_BASIC_FLAGS, Pt_FALSE, Pt_ALL);
1169 PtSetArg(&args[ n++ ], Pt_ARG_BEVEL_WIDTH, 0, 0);
1170 PtSetArg(&args[ n++ ], Pt_ARG_MARGIN_WIDTH, 0, 0);
1171 PtSetArg(&args[ n++ ], Pt_ARG_MARGIN_HEIGHT, 0, 0);
1172 PtSetArg(&args[ n++ ], Pt_ARG_CONTAINER_FLAGS, Pt_TRUE, Pt_AUTO_EXTENT);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001173
Bram Moolenaar15d63192011-09-14 16:05:15 +02001174 gui.vimContainer = PtCreateWidget(PtPane, gui.vimWindow, n, args);
1175 if (gui.vimContainer == NULL)
Bram Moolenaard2221132011-07-27 14:09:09 +02001176 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001177
Bram Moolenaar15d63192011-09-14 16:05:15 +02001178 PtAddCallback(gui.vimContainer, Pt_CB_RESIZE, gui_ph_pane_resize, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001179#endif
1180
Bram Moolenaar734a8672019-12-02 22:49:38 +01001181 // Size for the text area is set in gui_mch_set_text_area_pos
Bram Moolenaar071d4272004-06-13 20:20:40 +00001182 n = 0;
1183
Bram Moolenaar15d63192011-09-14 16:05:15 +02001184 PtSetArg(&args[ n++ ], Pt_ARG_RAW_DRAW_F, gui_ph_handle_raw_draw, 1);
1185 PtSetArg(&args[ n++ ], Pt_ARG_BEVEL_WIDTH, GUI_PH_MARGIN, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001186 /*
1187 * Using focus render also causes the whole widget to be redrawn
1188 * whenever it changes focus, which is very annoying :p
1189 */
Bram Moolenaar15d63192011-09-14 16:05:15 +02001190 PtSetArg(&args[ n++ ], Pt_ARG_FLAGS, Pt_TRUE,
1191 Pt_GETS_FOCUS | Pt_HIGHLIGHTED);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001192#ifndef FEAT_MOUSESHAPE
Bram Moolenaar15d63192011-09-14 16:05:15 +02001193 PtSetArg(&args[ n++ ], Pt_ARG_CURSOR_TYPE, GUI_PH_MOUSE_TYPE, 0);
1194 PtSetArg(&args[ n++ ], Pt_ARG_CURSOR_COLOR, gui_ph_mouse_color, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001195#endif
1196
Bram Moolenaar15d63192011-09-14 16:05:15 +02001197 gui.vimTextArea = PtCreateWidget(PtRaw, Pt_DFLT_PARENT, n, args);
1198 if (gui.vimTextArea == NULL)
Bram Moolenaard2221132011-07-27 14:09:09 +02001199 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001200
Bram Moolenaar734a8672019-12-02 22:49:38 +01001201 // TODO: use PtAddEventHandlers instead?
1202 // Not using Ph_EV_BUT_REPEAT because vim wouldn't use it anyway
Bram Moolenaar15d63192011-09-14 16:05:15 +02001203 PtAddEventHandler(gui.vimTextArea,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001204 Ph_EV_BUT_PRESS | Ph_EV_BUT_RELEASE | Ph_EV_PTR_MOTION_BUTTON,
Bram Moolenaar15d63192011-09-14 16:05:15 +02001205 gui_ph_handle_mouse, NULL);
1206 PtAddEventHandler(gui.vimTextArea, Ph_EV_KEY,
1207 gui_ph_handle_keyboard, NULL);
1208 PtAddCallback(gui.vimTextArea, Pt_CB_GOT_FOCUS,
1209 gui_ph_handle_focus, NULL);
1210 PtAddCallback(gui.vimTextArea, Pt_CB_LOST_FOCUS,
1211 gui_ph_handle_focus, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001212
1213 /*
1214 * Now that the text area widget has been created, set up the colours,
Bram Moolenaar4b96df52020-01-26 22:00:26 +01001215 * which will call PtSetResource from gui_mch_new_colors
Bram Moolenaar071d4272004-06-13 20:20:40 +00001216 */
1217
1218 /*
1219 * Create the two timers, not as accurate as using the kernel timer
1220 * functions, but good enough
1221 */
Bram Moolenaar15d63192011-09-14 16:05:15 +02001222 gui_ph_timer_cursor = PtCreateWidget(PtTimer, gui.vimWindow, 0, NULL);
1223 if (gui_ph_timer_cursor == NULL)
Bram Moolenaard2221132011-07-27 14:09:09 +02001224 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001225
Bram Moolenaar15d63192011-09-14 16:05:15 +02001226 gui_ph_timer_timeout = PtCreateWidget(PtTimer, gui.vimWindow, 0, NULL);
1227 if (gui_ph_timer_timeout == NULL)
Bram Moolenaard2221132011-07-27 14:09:09 +02001228 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001229
Bram Moolenaar15d63192011-09-14 16:05:15 +02001230 PtAddCallback(gui_ph_timer_cursor, Pt_CB_TIMER_ACTIVATE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001231 gui_ph_handle_timer_cursor, NULL);
Bram Moolenaar15d63192011-09-14 16:05:15 +02001232 PtAddCallback(gui_ph_timer_timeout, Pt_CB_TIMER_ACTIVATE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001233 gui_ph_handle_timer_timeout, NULL);
1234
1235#ifdef FEAT_MENU
1236 n = 0;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001237 PtSetArg(&args[ n++ ], Pt_ARG_WIDTH, window_size.w, 0);
1238 PtSetArg(&args[ n++ ], Pt_ARG_ANCHOR_FLAGS, Pt_ANCHOR_LEFT_RIGHT,
1239 Pt_IS_ANCHORED);
1240 gui.vimToolBarGroup = PtCreateWidget(PtToolbarGroup, gui.vimWindow,
1241 n, args);
1242 if (gui.vimToolBarGroup == NULL)
Bram Moolenaard2221132011-07-27 14:09:09 +02001243 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001244
Bram Moolenaar15d63192011-09-14 16:05:15 +02001245 PtAddCallback(gui.vimToolBarGroup, Pt_CB_RESIZE,
1246 gui_ph_handle_menu_resize, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001247
1248 n = 0;
1249 flags = 0;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001250 PtSetArg(&args[ n++ ], Pt_ARG_WIDTH, window_size.w, 0);
1251 if (! vim_strchr(p_go, GO_MENUS))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001252 {
1253 flags |= Pt_DELAY_REALIZE;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001254 PtSetArg(&args[ n++ ], Pt_ARG_FLAGS, Pt_TRUE, flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001255 }
Bram Moolenaar15d63192011-09-14 16:05:15 +02001256 gui.vimMenuBar = PtCreateWidget(PtMenuBar, gui.vimToolBarGroup, n, args);
1257 if (gui.vimMenuBar == NULL)
Bram Moolenaard2221132011-07-27 14:09:09 +02001258 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001259
1260# ifdef FEAT_TOOLBAR
1261 n = 0;
1262
Bram Moolenaar15d63192011-09-14 16:05:15 +02001263 PtSetArg(&args[ n++ ], Pt_ARG_ANCHOR_FLAGS,
1264 Pt_ANCHOR_LEFT_RIGHT |Pt_TOP_ANCHORED_TOP, Pt_IS_ANCHORED);
1265 PtSetArg(&args[ n++ ], Pt_ARG_RESIZE_FLAGS, Pt_TRUE,
1266 Pt_RESIZE_Y_AS_REQUIRED);
1267 PtSetArg(&args[ n++ ], Pt_ARG_WIDTH, window_size.w, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001268
1269 flags = Pt_GETS_FOCUS;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001270 if (! vim_strchr(p_go, GO_TOOLBAR))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001271 flags |= Pt_DELAY_REALIZE;
1272
Bram Moolenaar15d63192011-09-14 16:05:15 +02001273 PtSetArg(&args[ n++ ], Pt_ARG_FLAGS, Pt_DELAY_REALIZE, flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001274
Bram Moolenaar15d63192011-09-14 16:05:15 +02001275 gui.vimToolBar = PtCreateWidget(PtToolbar, gui.vimToolBarGroup, n, args);
1276 if (gui.vimToolBar == NULL)
Bram Moolenaard2221132011-07-27 14:09:09 +02001277 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001278
1279 /*
1280 * Size for the toolbar is fetched in gui_mch_show_toolbar, after
1281 * the buttons have been added and the toolbar has resized it's height
1282 * for the buttons to fit
1283 */
1284# endif
1285
1286#endif
1287
Bram Moolenaard2221132011-07-27 14:09:09 +02001288 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001289}
1290
1291 int
1292gui_mch_init_check(void)
1293{
Bram Moolenaard2221132011-07-27 14:09:09 +02001294 return (is_photon_available == TRUE) ? OK : FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001295}
1296
1297 int
1298gui_mch_open(void)
1299{
1300 gui.norm_pixel = Pg_BLACK;
1301 gui.back_pixel = Pg_WHITE;
1302
1303 set_normal_colors();
1304
1305 gui_check_colors();
1306 gui.def_norm_pixel = gui.norm_pixel;
1307 gui.def_back_pixel = gui.back_pixel;
1308
1309 highlight_gui_started();
1310
1311 if (gui_win_x != -1 && gui_win_y != -1)
1312 gui_mch_set_winpos(gui_win_x, gui_win_y);
1313
Bram Moolenaar15d63192011-09-14 16:05:15 +02001314 return (PtRealizeWidget(gui.vimWindow) == 0) ? OK : FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001315}
1316
1317 void
1318gui_mch_exit(int rc)
1319{
Bram Moolenaar15d63192011-09-14 16:05:15 +02001320 PtDestroyWidget(gui.vimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001321
Bram Moolenaar15d63192011-09-14 16:05:15 +02001322 PxTranslateSet(charset_translate, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001323
Bram Moolenaar15d63192011-09-14 16:05:15 +02001324 vim_free(gui.event_buffer);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001325
1326#ifdef USE_PANEL_GROUPS
Bram Moolenaar15d63192011-09-14 16:05:15 +02001327 vim_free(panel_titles);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001328#endif
1329}
1330
Bram Moolenaar734a8672019-12-02 22:49:38 +01001331////////////////////////////////////////////////////////////////////////////
1332// events
Bram Moolenaar071d4272004-06-13 20:20:40 +00001333
Bram Moolenaar734a8672019-12-02 22:49:38 +01001334/*
1335 * When no events are available, photon will call this function, working is
1336 * set to FALSE, and the gui_mch_update loop will exit.
1337 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001338 static int
Bram Moolenaar15d63192011-09-14 16:05:15 +02001339exit_gui_mch_update(void *data)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001340{
1341 *(int *)data = FALSE;
Bram Moolenaard2221132011-07-27 14:09:09 +02001342 return Pt_END;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001343}
1344
1345 void
1346gui_mch_update(void)
1347{
1348 int working = TRUE;
1349
Bram Moolenaar15d63192011-09-14 16:05:15 +02001350 PtAppAddWorkProc(NULL, exit_gui_mch_update, &working);
1351 while ((working == TRUE) && !vim_is_input_buf_full())
Bram Moolenaar071d4272004-06-13 20:20:40 +00001352 PtProcessEvent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001353}
1354
1355 int
1356gui_mch_wait_for_chars(int wtime)
1357{
1358 is_timeout = FALSE;
1359
Bram Moolenaar12dfc9e2019-01-28 22:32:58 +01001360 if (wtime >= 0)
1361 PtSetResource(gui_ph_timer_timeout, Pt_ARG_TIMER_INITIAL,
1362 wtime == 0 ? 1 : wtime, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001363
Bram Moolenaar15d63192011-09-14 16:05:15 +02001364 while (1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001365 {
1366 PtProcessEvent();
Bram Moolenaar15d63192011-09-14 16:05:15 +02001367 if (input_available())
Bram Moolenaar071d4272004-06-13 20:20:40 +00001368 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02001369 PtSetResource(gui_ph_timer_timeout, Pt_ARG_TIMER_INITIAL, 0, 0);
Bram Moolenaard2221132011-07-27 14:09:09 +02001370 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001371 }
Bram Moolenaar15d63192011-09-14 16:05:15 +02001372 else if (is_timeout == TRUE)
Bram Moolenaard2221132011-07-27 14:09:09 +02001373 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001374 }
1375}
1376
Bram Moolenaar15d63192011-09-14 16:05:15 +02001377#if defined(FEAT_BROWSE) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001378/*
1379 * Put up a file requester.
1380 * Returns the selected name in allocated memory, or NULL for Cancel.
1381 * saving, select file to write
1382 * title title for the window
1383 * default_name default name (well duh!)
1384 * ext not used (extension added)
1385 * initdir initial directory, NULL for current dir
1386 * filter not used (file name filter)
1387 */
1388 char_u *
1389gui_mch_browse(
1390 int saving,
1391 char_u *title,
1392 char_u *default_name,
1393 char_u *ext,
1394 char_u *initdir,
1395 char_u *filter)
1396{
1397 PtFileSelectionInfo_t file;
1398 int flags;
1399 char_u *default_path;
1400 char_u *open_text = NULL;
1401
1402 flags = 0;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001403 memset(&file, 0, sizeof(file));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001404
Bram Moolenaar15d63192011-09-14 16:05:15 +02001405 default_path = alloc(MAXPATHL + 1 + NAME_MAX + 1);
1406 if (default_path != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001407 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02001408 if (saving == TRUE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001409 {
Bram Moolenaar734a8672019-12-02 22:49:38 +01001410 // Don't need Pt_FSR_CONFIRM_EXISTING, vim will ask anyway
Bram Moolenaar071d4272004-06-13 20:20:40 +00001411 flags |= Pt_FSR_NO_FCHECK;
1412 open_text = "&Save";
1413 }
1414
Bram Moolenaar734a8672019-12-02 22:49:38 +01001415 // combine the directory and filename into a single path
Bram Moolenaar15d63192011-09-14 16:05:15 +02001416 if (initdir == NULL || *initdir == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001417 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02001418 mch_dirname(default_path, MAXPATHL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001419 initdir = default_path;
1420 }
1421 else
1422 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02001423 STRCPY(default_path, initdir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001424 initdir = default_path;
1425 }
1426
Bram Moolenaar15d63192011-09-14 16:05:15 +02001427 if (default_name != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001428 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02001429 if (default_path[ STRLEN(default_path) - 1 ] != '/')
1430 STRCAT(default_path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001431
Bram Moolenaar15d63192011-09-14 16:05:15 +02001432 STRCAT(default_path, default_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001433 }
1434
Bram Moolenaar734a8672019-12-02 22:49:38 +01001435 // TODO: add a filter?
Bram Moolenaar071d4272004-06-13 20:20:40 +00001436 PtFileSelection(
1437 gui.vimWindow,
1438 NULL,
1439 title,
1440 default_path,
1441 NULL,
1442 open_text,
1443 NULL,
1444 NULL,
1445 &file,
Bram Moolenaar15d63192011-09-14 16:05:15 +02001446 flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001447
Bram Moolenaar15d63192011-09-14 16:05:15 +02001448 vim_free(default_path);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001449
Bram Moolenaar15d63192011-09-14 16:05:15 +02001450 if (file.ret == Pt_FSDIALOG_BTN1)
Bram Moolenaard2221132011-07-27 14:09:09 +02001451 return vim_strsave(file.path);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001452 }
Bram Moolenaard2221132011-07-27 14:09:09 +02001453 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001454}
1455#endif
1456
Bram Moolenaar15d63192011-09-14 16:05:15 +02001457#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001458static PtWidget_t *gui_ph_dialog_text = NULL;
1459
1460 static int
Bram Moolenaar15d63192011-09-14 16:05:15 +02001461gui_ph_dialog_close(int button, void *data)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001462{
1463 PtModalCtrl_t *modal_ctrl = data;
1464 char_u *dialog_text, *vim_text;
1465
Bram Moolenaar15d63192011-09-14 16:05:15 +02001466 if (gui_ph_dialog_text != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001467 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02001468 PtGetResource(gui_ph_dialog_text, Pt_ARG_TEXT_STRING, &dialog_text, 0);
1469 PtGetResource(gui_ph_dialog_text, Pt_ARG_POINTER, &vim_text, 0);
1470 STRNCPY(vim_text, dialog_text, IOSIZE - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001471 }
1472
Bram Moolenaar15d63192011-09-14 16:05:15 +02001473 PtModalUnblock(modal_ctrl, (void *) button);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001474
Bram Moolenaard2221132011-07-27 14:09:09 +02001475 return Pt_TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001476}
1477
1478 static int
Bram Moolenaar15d63192011-09-14 16:05:15 +02001479gui_ph_dialog_text_enter(PtWidget_t *widget, void *data, PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001480{
Bram Moolenaar15d63192011-09-14 16:05:15 +02001481 if (info->reason_subtype == Pt_EDIT_ACTIVATE)
1482 gui_ph_dialog_close(1, data);
Bram Moolenaard2221132011-07-27 14:09:09 +02001483 return Pt_CONTINUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001484}
1485
1486 static int
Bram Moolenaar15d63192011-09-14 16:05:15 +02001487gui_ph_dialog_esc(PtWidget_t *widget, void *data, PtCallbackInfo_t *info)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001488{
1489 PhKeyEvent_t *key;
1490
Bram Moolenaar15d63192011-09-14 16:05:15 +02001491 key = PhGetData(info->event);
1492 if ((key->key_flags & Pk_KF_Cap_Valid) && (key->key_cap == Pk_Escape))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001493 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02001494 gui_ph_dialog_close(0, data);
Bram Moolenaard2221132011-07-27 14:09:09 +02001495 return Pt_CONSUME;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001496 }
Bram Moolenaard2221132011-07-27 14:09:09 +02001497 return Pt_PROCESS;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001498}
1499
1500 int
1501gui_mch_dialog(
1502 int type,
1503 char_u *title,
1504 char_u *message,
1505 char_u *buttons,
1506 int default_button,
Bram Moolenaard2c340a2011-01-17 20:08:11 +01001507 char_u *textfield,
1508 int ex_cmd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001509{
1510 char_u *str;
1511 char_u **button_array;
1512 char_u *buttons_copy;
1513
1514 int button_count;
1515 int i, len;
1516 int dialog_result = -1;
1517
Bram Moolenaar734a8672019-12-02 22:49:38 +01001518 // FIXME: the vertical option in guioptions is blatantly ignored
1519 // FIXME: so is the type
Bram Moolenaar071d4272004-06-13 20:20:40 +00001520
1521 button_count = len = i = 0;
1522
Bram Moolenaar15d63192011-09-14 16:05:15 +02001523 if (buttons == NULL || *buttons == NUL)
Bram Moolenaard2221132011-07-27 14:09:09 +02001524 return -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001525
Bram Moolenaar734a8672019-12-02 22:49:38 +01001526 // There is one less separator than buttons, so bump up the button count
Bram Moolenaar071d4272004-06-13 20:20:40 +00001527 button_count = 1;
1528
Bram Moolenaar734a8672019-12-02 22:49:38 +01001529 // Count string length and number of separators
Bram Moolenaar15d63192011-09-14 16:05:15 +02001530 for (str = buttons; *str; str++)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001531 {
1532 len++;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001533 if (*str == DLG_BUTTON_SEP)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001534 button_count++;
1535 }
1536
Bram Moolenaar15d63192011-09-14 16:05:15 +02001537 if (title == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001538 title = "Vim";
1539
Bram Moolenaar15d63192011-09-14 16:05:15 +02001540 buttons_copy = alloc(len + 1);
Bram Moolenaarc799fe22019-05-28 23:08:19 +02001541 button_array = ALLOC_MULT(char_u *, button_count);
Bram Moolenaar15d63192011-09-14 16:05:15 +02001542 if (buttons_copy != NULL && button_array != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001543 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02001544 STRCPY(buttons_copy, buttons);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001545
1546 /*
1547 * Convert DLG_BUTTON_SEP into NUL's and fill in
1548 * button_array with the pointer to each NUL terminated string
1549 */
1550 str = buttons_copy;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001551 for (i = 0; i < button_count; i++)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001552 {
1553 button_array[ i ] = str;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001554 for (; *str; str++)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001555 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02001556 if (*str == DLG_BUTTON_SEP)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001557 {
1558 *str++ = NUL;
1559 break;
1560 }
1561 }
1562 }
1563#ifndef FEAT_GUI_TEXTDIALOG
1564 dialog_result = PtAlert(
1565 gui.vimWindow, NULL,
1566 title,
1567 NULL,
1568 message, NULL,
1569 button_count, (const char **) button_array, NULL,
Bram Moolenaar15d63192011-09-14 16:05:15 +02001570 default_button, 0, Pt_MODAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001571#else
Bram Moolenaar734a8672019-12-02 22:49:38 +01001572 // Writing the dialog ourselves lets us add extra features, like
1573 // trapping the escape key and returning 0 to vim
Bram Moolenaar071d4272004-06-13 20:20:40 +00001574 {
1575 int n;
1576 PtArg_t args[5];
1577 PtWidget_t *dialog, *pane;
1578 PtModalCtrl_t modal_ctrl;
1579 PtDialogInfo_t di;
1580
Bram Moolenaar15d63192011-09-14 16:05:15 +02001581 memset(&di, 0, sizeof(di));
1582 memset(&modal_ctrl, 0, sizeof(modal_ctrl));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001583
1584 n = 0;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001585 PtSetArg(&args[n++], Pt_ARG_GROUP_ROWS_COLS, 0, 0);
1586 PtSetArg(&args[n++], Pt_ARG_WIDTH, 350, 0);
1587 PtSetArg(&args[n++], Pt_ARG_GROUP_ORIENTATION,
1588 Pt_GROUP_VERTICAL, 0);
1589 PtSetArg(&args[n++], Pt_ARG_GROUP_FLAGS,
1590 Pt_TRUE, Pt_GROUP_NO_KEYS | Pt_GROUP_STRETCH_HORIZONTAL);
1591 PtSetArg(&args[n++], Pt_ARG_CONTAINER_FLAGS, Pt_FALSE, Pt_TRUE);
1592 pane = PtCreateWidget(PtGroup, NULL, n, args);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001593
1594 n = 0;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001595 PtSetArg(&args[n++], Pt_ARG_TEXT_STRING, message, 0);
1596 PtCreateWidget(PtLabel, pane, n, args);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001597
Bram Moolenaar15d63192011-09-14 16:05:15 +02001598 if (textfield != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001599 {
1600 n = 0;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001601 PtSetArg(&args[n++], Pt_ARG_MAX_LENGTH, IOSIZE - 1, 0);
1602 PtSetArg(&args[n++], Pt_ARG_TEXT_STRING, textfield, 0);
1603 PtSetArg(&args[n++], Pt_ARG_POINTER, textfield, 0);
1604 gui_ph_dialog_text = PtCreateWidget(PtText, pane, n, args);
1605 PtAddCallback(gui_ph_dialog_text, Pt_CB_ACTIVATE,
1606 gui_ph_dialog_text_enter, &modal_ctrl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001607 }
1608
1609 di.parent = gui.vimWindow;
1610 di.pane = pane;
1611 di.title = title;
1612 di.buttons = (const char **) button_array;
1613 di.nbtns = button_count;
1614 di.def_btn = default_button;
Bram Moolenaar734a8672019-12-02 22:49:38 +01001615 // This is just to give the dialog the close button.
1616 // We check for the Escape key ourselves and return 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00001617 di.esc_btn = button_count;
1618 di.callback = gui_ph_dialog_close;
1619 di.data = &modal_ctrl;
1620
Bram Moolenaar15d63192011-09-14 16:05:15 +02001621 dialog = PtCreateDialog(&di);
1622 PtAddFilterCallback(dialog, Ph_EV_KEY,
1623 gui_ph_dialog_esc, &modal_ctrl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001624
Bram Moolenaar15d63192011-09-14 16:05:15 +02001625 if (gui_ph_dialog_text != NULL)
1626 PtGiveFocus(gui_ph_dialog_text, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001627
Bram Moolenaar734a8672019-12-02 22:49:38 +01001628 // Open dialog, block the vim window and wait for the dialog to close
Bram Moolenaar15d63192011-09-14 16:05:15 +02001629 PtRealizeWidget(dialog);
1630 PtMakeModal(dialog, Ph_CURSOR_NOINPUT, Ph_CURSOR_DEFAULT_COLOR);
1631 dialog_result = (int) PtModalBlock(&modal_ctrl, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001632
Bram Moolenaar15d63192011-09-14 16:05:15 +02001633 PtDestroyWidget(dialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001634 gui_ph_dialog_text = NULL;
1635 }
1636#endif
1637 }
1638
Bram Moolenaar15d63192011-09-14 16:05:15 +02001639 vim_free(button_array);
1640 vim_free(buttons_copy);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001641
Bram Moolenaard2221132011-07-27 14:09:09 +02001642 return dialog_result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001643}
1644#endif
Bram Moolenaar734a8672019-12-02 22:49:38 +01001645////////////////////////////////////////////////////////////////////////////
1646// window size/position/state
Bram Moolenaar071d4272004-06-13 20:20:40 +00001647
1648 int
1649gui_mch_get_winpos(int *x, int *y)
1650{
1651 PhPoint_t *pos;
1652
Bram Moolenaar15d63192011-09-14 16:05:15 +02001653 pos = PtWidgetPos(gui.vimWindow, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001654
1655 *x = pos->x;
1656 *y = pos->y;
1657
Bram Moolenaard2221132011-07-27 14:09:09 +02001658 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001659}
1660
1661 void
1662gui_mch_set_winpos(int x, int y)
1663{
1664 PhPoint_t pos = { x, y };
1665
Bram Moolenaar15d63192011-09-14 16:05:15 +02001666 PtSetResource(gui.vimWindow, Pt_ARG_POS, &pos, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001667}
1668
1669 void
1670gui_mch_set_shellsize(int width, int height,
Bram Moolenaarafa24992006-03-27 20:58:26 +00001671 int min_width, int min_height, int base_width, int base_height,
1672 int direction)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001673{
1674 PhDim_t window_size = { width, height };
1675 PhDim_t min_size = { min_width, min_height };
1676
1677#ifdef USE_PANEL_GROUP
1678 window_size.w += pg_margin_left + pg_margin_right;
1679 window_size.h += pg_margin_top + pg_margin_bottom;
1680#endif
1681
Bram Moolenaar15d63192011-09-14 16:05:15 +02001682 PtSetResource(gui.vimWindow, Pt_ARG_MINIMUM_DIM, &min_size, 0);
1683 PtSetResource(gui.vimWindow, Pt_ARG_DIM, &window_size, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001684
Bram Moolenaar15d63192011-09-14 16:05:15 +02001685 if (! PtWidgetIsRealized(gui.vimWindow))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001686 gui_ph_resize_container();
1687}
1688
1689/*
1690 * Return the amount of screen space that hasn't been allocated (such as
1691 * by the shelf).
1692 */
1693 void
1694gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
1695{
1696 PhRect_t console;
1697
Bram Moolenaar15d63192011-09-14 16:05:15 +02001698 PhWindowQueryVisible(Ph_QUERY_WORKSPACE, 0,
1699 PhInputGroup(NULL), &console);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001700
1701 *screen_w = console.lr.x - console.ul.x + 1;
1702 *screen_h = console.lr.y - console.ul.y + 1;
1703}
1704
1705 void
1706gui_mch_iconify(void)
1707{
1708 PhWindowEvent_t event;
1709
Bram Moolenaar15d63192011-09-14 16:05:15 +02001710 memset(&event, 0, sizeof (event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001711 event.event_f = Ph_WM_HIDE;
1712 event.event_state = Ph_WM_EVSTATE_HIDE;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001713 event.rid = PtWidgetRid(gui.vimWindow);
1714 PtForwardWindowEvent(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001715}
1716
1717#if defined(FEAT_EVAL) || defined(PROTO)
1718/*
1719 * Bring the Vim window to the foreground.
1720 */
1721 void
Bram Moolenaar68c2f632016-01-30 17:24:07 +01001722gui_mch_set_foreground(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001723{
1724 PhWindowEvent_t event;
1725
Bram Moolenaar15d63192011-09-14 16:05:15 +02001726 memset(&event, 0, sizeof (event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001727 event.event_f = Ph_WM_TOFRONT;
1728 event.event_state = Ph_WM_EVSTATE_FFRONT;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001729 event.rid = PtWidgetRid(gui.vimWindow);
1730 PtForwardWindowEvent(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001731}
1732#endif
1733
1734 void
1735gui_mch_settitle(char_u *title, char_u *icon)
1736{
1737#ifdef USE_PANEL_GROUP
Bram Moolenaar15d63192011-09-14 16:05:15 +02001738 gui_ph_pg_set_buffer_num(curwin->w_buffer->b_fnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001739#endif
Bram Moolenaar15d63192011-09-14 16:05:15 +02001740 PtSetResource(gui.vimWindow, Pt_ARG_WINDOW_TITLE, title, 0);
Bram Moolenaar734a8672019-12-02 22:49:38 +01001741 // Not sure what to do with the icon text, set balloon text somehow?
Bram Moolenaar071d4272004-06-13 20:20:40 +00001742}
1743
Bram Moolenaar734a8672019-12-02 22:49:38 +01001744////////////////////////////////////////////////////////////////////////////
1745// Scrollbar
Bram Moolenaar071d4272004-06-13 20:20:40 +00001746
1747 void
1748gui_mch_set_scrollbar_thumb(scrollbar_T *sb, int val, int size, int max)
1749{
1750 int n = 0;
1751 PtArg_t args[3];
1752
Bram Moolenaar15d63192011-09-14 16:05:15 +02001753 PtSetArg(&args[ n++ ], Pt_ARG_MAXIMUM, max, 0);
1754 PtSetArg(&args[ n++ ], Pt_ARG_SLIDER_SIZE, size, 0);
1755 PtSetArg(&args[ n++ ], Pt_ARG_GAUGE_VALUE, val, 0);
1756 PtSetResources(sb->id, n, args);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001757}
1758
1759 void
1760gui_mch_set_scrollbar_pos(scrollbar_T *sb, int x, int y, int w, int h)
1761{
1762 PhArea_t area = {{ x, y }, { w, h }};
1763
Bram Moolenaar15d63192011-09-14 16:05:15 +02001764 PtSetResource(sb->id, Pt_ARG_AREA, &area, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001765}
1766
Bram Moolenaar203ec772020-07-17 20:43:43 +02001767 int
1768gui_mch_get_scrollbar_xpadding(void)
1769{
1770 // TODO: Calculate the padding for adjust scrollbar position when the
1771 // Window is maximized.
1772 return 0;
1773}
1774
1775 int
1776gui_mch_get_scrollbar_ypadding(void)
1777{
1778 // TODO: Calculate the padding for adjust scrollbar position when the
1779 // Window is maximized.
1780 return 0;
1781}
1782
Bram Moolenaar071d4272004-06-13 20:20:40 +00001783 void
1784gui_mch_create_scrollbar(scrollbar_T *sb, int orient)
1785{
1786 int n = 0;
Bram Moolenaar734a8672019-12-02 22:49:38 +01001787// int anchor_flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001788 PtArg_t args[4];
1789
1790 /*
1791 * Stop the scrollbar from being realized when the parent
1792 * is realized, so it can be explicitly realized by vim.
1793 *
1794 * Also, don't let the scrollbar get focus
1795 */
Bram Moolenaar15d63192011-09-14 16:05:15 +02001796 PtSetArg(&args[ n++ ], Pt_ARG_FLAGS, Pt_DELAY_REALIZE,
1797 Pt_DELAY_REALIZE | Pt_GETS_FOCUS);
1798 PtSetArg(&args[ n++ ], Pt_ARG_SCROLLBAR_FLAGS, Pt_SCROLLBAR_SHOW_ARROWS, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001799#if 0
Bram Moolenaar734a8672019-12-02 22:49:38 +01001800 // Don't need this anchoring for the scrollbars
Bram Moolenaar15d63192011-09-14 16:05:15 +02001801 if (orient == SBAR_HORIZ)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001802 {
1803 anchor_flags = Pt_BOTTOM_ANCHORED_BOTTOM |
1804 Pt_LEFT_ANCHORED_LEFT | Pt_RIGHT_ANCHORED_RIGHT;
1805 }
1806 else
1807 {
1808 anchor_flags = Pt_BOTTOM_ANCHORED_BOTTOM | Pt_TOP_ANCHORED_TOP;
Bram Moolenaar15d63192011-09-14 16:05:15 +02001809 if (sb->wp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001810 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02001811 if (sb == &sb->wp->w_scrollbars[ SBAR_LEFT ])
Bram Moolenaar071d4272004-06-13 20:20:40 +00001812 anchor_flags |= Pt_LEFT_ANCHORED_LEFT;
1813 else
1814 anchor_flags |= Pt_RIGHT_ANCHORED_RIGHT;
1815 }
1816 }
Bram Moolenaar15d63192011-09-14 16:05:15 +02001817 PtSetArg(&args[ n++ ], Pt_ARG_ANCHOR_FLAGS, anchor_flags, Pt_IS_ANCHORED);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001818#endif
Bram Moolenaar15d63192011-09-14 16:05:15 +02001819 PtSetArg(&args[ n++ ], Pt_ARG_ORIENTATION,
1820 (orient == SBAR_HORIZ) ? Pt_HORIZONTAL : Pt_VERTICAL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001821#ifdef USE_PANEL_GROUP
Bram Moolenaar15d63192011-09-14 16:05:15 +02001822 sb->id = PtCreateWidget(PtScrollbar, gui.vimPanelGroup, n, args);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001823#else
Bram Moolenaar15d63192011-09-14 16:05:15 +02001824 sb->id = PtCreateWidget(PtScrollbar, gui.vimContainer, n, args);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001825#endif
1826
Bram Moolenaar15d63192011-09-14 16:05:15 +02001827 PtAddCallback(sb->id, Pt_CB_SCROLLBAR_MOVE, gui_ph_handle_scrollbar, sb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001828}
1829
1830 void
1831gui_mch_enable_scrollbar(scrollbar_T *sb, int flag)
1832{
Bram Moolenaar15d63192011-09-14 16:05:15 +02001833 if (flag != 0)
1834 PtRealizeWidget(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001835 else
Bram Moolenaar15d63192011-09-14 16:05:15 +02001836 PtUnrealizeWidget(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001837}
1838
1839 void
1840gui_mch_destroy_scrollbar(scrollbar_T *sb)
1841{
Bram Moolenaar15d63192011-09-14 16:05:15 +02001842 PtDestroyWidget(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001843 sb->id = NULL;
1844}
1845
Bram Moolenaar734a8672019-12-02 22:49:38 +01001846////////////////////////////////////////////////////////////////////////////
1847// Mouse functions
Bram Moolenaar071d4272004-06-13 20:20:40 +00001848
1849#if defined(FEAT_MOUSESHAPE) || defined(PROTO)
Bram Moolenaar734a8672019-12-02 22:49:38 +01001850// The last set mouse pointer shape is remembered, to be used when it goes
1851// from hidden to not hidden.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001852static int last_shape = 0;
1853
Bram Moolenaar734a8672019-12-02 22:49:38 +01001854// Table for shape IDs. Keep in sync with the mshape_names[] table in
1855// misc2.c!
Bram Moolenaar071d4272004-06-13 20:20:40 +00001856static int mshape_ids[] =
1857{
Bram Moolenaar734a8672019-12-02 22:49:38 +01001858 Ph_CURSOR_POINTER, // arrow
1859 Ph_CURSOR_NONE, // blank
1860 Ph_CURSOR_INSERT, // beam
1861 Ph_CURSOR_DRAG_VERTICAL, // updown
1862 Ph_CURSOR_DRAG_VERTICAL, // udsizing
1863 Ph_CURSOR_DRAG_HORIZONTAL, // leftright
1864 Ph_CURSOR_DRAG_HORIZONTAL, // lrsizing
1865 Ph_CURSOR_WAIT, // busy
1866 Ph_CURSOR_DONT, // no
1867 Ph_CURSOR_CROSSHAIR, // crosshair
1868 Ph_CURSOR_FINGER, // hand1
1869 Ph_CURSOR_FINGER, // hand2
1870 Ph_CURSOR_FINGER, // pencil
1871 Ph_CURSOR_QUESTION_POINT, // question
1872 Ph_CURSOR_POINTER, // right-arrow
1873 Ph_CURSOR_POINTER, // up-arrow
1874 Ph_CURSOR_POINTER // last one
Bram Moolenaar071d4272004-06-13 20:20:40 +00001875};
1876
1877 void
Bram Moolenaar68c2f632016-01-30 17:24:07 +01001878mch_set_mouse_shape(int shape)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001879{
1880 int id;
1881
1882 if (!gui.in_use)
1883 return;
1884
1885 if (shape == MSHAPE_HIDE || gui.pointer_hidden)
Bram Moolenaar15d63192011-09-14 16:05:15 +02001886 PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_NONE,
1887 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001888 else
1889 {
1890 if (shape >= MSHAPE_NUMBERED)
1891 id = Ph_CURSOR_POINTER;
1892 else
1893 id = mshape_ids[shape];
1894
Bram Moolenaar15d63192011-09-14 16:05:15 +02001895 PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_TYPE, id, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001896 }
1897 if (shape != MSHAPE_HIDE)
1898 last_shape = shape;
1899}
1900#endif
1901
1902 void
1903gui_mch_mousehide(int hide)
1904{
Yegappan Lakshmanan7f8b2552023-01-08 13:44:24 +00001905 if (gui.pointer_hidden == hide)
1906 return;
1907
1908 gui.pointer_hidden = hide;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001909#ifdef FEAT_MOUSESHAPE
Yegappan Lakshmanan7f8b2552023-01-08 13:44:24 +00001910 if (hide)
Bram Moolenaar15d63192011-09-14 16:05:15 +02001911 PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_TYPE,
Yegappan Lakshmanan7f8b2552023-01-08 13:44:24 +00001912 Ph_CURSOR_NONE, 0);
1913 else
1914 mch_set_mouse_shape(last_shape);
1915#else
1916 PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_TYPE,
1917 (hide == MOUSE_SHOW) ? GUI_PH_MOUSE_TYPE : Ph_CURSOR_NONE,
1918 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001919#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001920}
1921
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00001922 void
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00001923gui_mch_getmouse(int *x, int *y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001924{
1925 PhCursorInfo_t info;
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00001926 short ix, iy;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001927
Bram Moolenaar734a8672019-12-02 22:49:38 +01001928 // FIXME: does this return the correct position,
1929 // with respect to the border?
Bram Moolenaar15d63192011-09-14 16:05:15 +02001930 PhQueryCursor(PhInputGroup(NULL), &info);
1931 PtGetAbsPosition(gui.vimTextArea , &ix, &iy);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001932
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00001933 *x = info.pos.x - ix;
1934 *y = info.pos.y - iy;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001935}
1936
1937 void
1938gui_mch_setmouse(int x, int y)
1939{
1940 short abs_x, abs_y;
1941
Bram Moolenaar15d63192011-09-14 16:05:15 +02001942 PtGetAbsPosition(gui.vimTextArea, &abs_x, &abs_y);
Bram Moolenaar734a8672019-12-02 22:49:38 +01001943 // Add the border offset?
Bram Moolenaar15d63192011-09-14 16:05:15 +02001944 PhMoveCursorAbs(PhInputGroup(NULL), abs_x + x, abs_y + y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001945}
1946
Bram Moolenaar734a8672019-12-02 22:49:38 +01001947////////////////////////////////////////////////////////////////////////////
1948// Colours
Bram Moolenaar071d4272004-06-13 20:20:40 +00001949
1950/*
1951 * Return the RGB value of a pixel as a long.
1952 */
Bram Moolenaar1b58cdd2016-08-22 23:04:33 +02001953 guicolor_T
Bram Moolenaar071d4272004-06-13 20:20:40 +00001954gui_mch_get_rgb(guicolor_T pixel)
1955{
Bram Moolenaar1b58cdd2016-08-22 23:04:33 +02001956 return (guicolor_T)(PgRGB(PgRedValue(pixel),
1957 PgGreenValue(pixel), PgBlueValue(pixel)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001958}
1959
1960 void
1961gui_mch_new_colors(void)
1962{
Bram Moolenaar734a8672019-12-02 22:49:38 +01001963#if 0 // Don't bother changing the cursor colour
Bram Moolenaar071d4272004-06-13 20:20:40 +00001964 short color_diff;
1965
1966 /*
1967 * If there isn't enough difference between the background colour and
1968 * the mouse pointer colour then change the mouse pointer colour
1969 */
1970 color_diff = gui_get_lightness(gui_ph_mouse_color)
1971 - gui_get_lightness(gui.back_pixel);
1972
Bram Moolenaar15d63192011-09-14 16:05:15 +02001973 if (abs(color_diff) < 64)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001974 {
1975 short r, g, b;
Bram Moolenaar734a8672019-12-02 22:49:38 +01001976 // not a great algorithm...
Bram Moolenaar15d63192011-09-14 16:05:15 +02001977 r = PgRedValue(gui_ph_mouse_color) ^ 255;
1978 g = PgGreenValue(gui_ph_mouse_color) ^ 255;
1979 b = PgBlueValue(gui_ph_mouse_color) ^ 255;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001980
1981#ifndef FEAT_MOUSESHAPE
Bram Moolenaar15d63192011-09-14 16:05:15 +02001982 gui_ph_mouse_color = PgRGB(r, g, b);
1983 PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_COLOR,
1984 gui_ph_mouse_color, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001985#endif
1986 }
1987#endif
1988
Bram Moolenaar15d63192011-09-14 16:05:15 +02001989 PtSetResource(gui.vimTextArea, Pt_ARG_FILL_COLOR, gui.back_pixel, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001990}
1991
Bram Moolenaar071d4272004-06-13 20:20:40 +00001992/*
Bram Moolenaarccc18222007-05-10 18:25:20 +00001993 * This should be split out into a separate file,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001994 * every port does basically the same thing.
1995 *
1996 * This is the gui_w32.c version (i think..)
1997 * Return INVALCOLOR when failed.
1998 */
1999
2000 guicolor_T
2001gui_mch_get_color(char_u *name)
2002{
Bram Moolenaarab302212016-04-26 20:59:29 +02002003 return gui_get_color_cmn(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002004}
2005
Bram Moolenaar26af85d2017-07-23 16:45:10 +02002006 guicolor_T
2007gui_mch_get_rgb_color(int r, int g, int b)
2008{
2009 return gui_get_rgb_color_cmn(r, g, b);
2010}
2011
Bram Moolenaar071d4272004-06-13 20:20:40 +00002012 void
2013gui_mch_set_fg_color(guicolor_T color)
2014{
Bram Moolenaar15d63192011-09-14 16:05:15 +02002015 PgSetTextColor(color);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002016}
2017
2018 void
2019gui_mch_set_bg_color(guicolor_T color)
2020{
Bram Moolenaar15d63192011-09-14 16:05:15 +02002021 PgSetFillColor(color);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002022}
2023
2024 void
Bram Moolenaare2cc9702005-03-15 22:43:58 +00002025gui_mch_set_sp_color(guicolor_T color)
2026{
2027}
2028
2029 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00002030gui_mch_invert_rectangle(int row, int col, int nr, int nc)
2031{
2032 PhRect_t rect;
2033
Bram Moolenaar15d63192011-09-14 16:05:15 +02002034 rect.ul.x = FILL_X(col);
2035 rect.ul.y = FILL_Y(row);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002036
Bram Moolenaar734a8672019-12-02 22:49:38 +01002037 // FIXME: This has an off by one pixel problem
Bram Moolenaar071d4272004-06-13 20:20:40 +00002038 rect.lr.x = rect.ul.x + nc * gui.char_width;
2039 rect.lr.y = rect.ul.y + nr * gui.char_height;
Bram Moolenaar15d63192011-09-14 16:05:15 +02002040 if (nc > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002041 rect.lr.x -= 1;
Bram Moolenaar15d63192011-09-14 16:05:15 +02002042 if (nr > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002043 rect.lr.y -= 1;
2044
2045 DRAW_START;
Bram Moolenaar15d63192011-09-14 16:05:15 +02002046 PgSetDrawMode(Pg_DrawModeDSTINVERT);
2047 PgDrawRect(&rect, Pg_DRAW_FILL);
2048 PgSetDrawMode(Pg_DrawModeSRCCOPY);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002049 DRAW_END;
2050}
2051
2052 void
2053gui_mch_clear_block(int row1, int col1, int row2, int col2)
2054{
2055 PhRect_t block = {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002056 { FILL_X(col1), FILL_Y(row1) },
2057 { FILL_X(col2 + 1) - 1, FILL_Y(row2 + 1) - 1}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002058 };
2059
2060 DRAW_START;
Bram Moolenaar15d63192011-09-14 16:05:15 +02002061 gui_mch_set_bg_color(gui.back_pixel);
2062 PgDrawRect(&block, Pg_DRAW_FILL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002063 DRAW_END;
2064}
2065
2066 void
Bram Moolenaar68c2f632016-01-30 17:24:07 +01002067gui_mch_clear_all(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002068{
2069 PhRect_t text_rect = {
2070 { gui.border_width, gui.border_width },
2071 { Columns * gui.char_width + gui.border_width - 1 ,
2072 Rows * gui.char_height + gui.border_width - 1 }
2073 };
2074
Bram Moolenaar15d63192011-09-14 16:05:15 +02002075 if (is_ignore_draw == TRUE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002076 return;
2077
2078 DRAW_START;
Bram Moolenaar15d63192011-09-14 16:05:15 +02002079 gui_mch_set_bg_color(gui.back_pixel);
2080 PgDrawRect(&text_rect, Pg_DRAW_FILL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002081 DRAW_END;
2082}
2083
2084 void
2085gui_mch_delete_lines(int row, int num_lines)
2086{
2087 PhRect_t rect;
2088 PhPoint_t delta;
2089
Bram Moolenaar15d63192011-09-14 16:05:15 +02002090 rect.ul.x = FILL_X(gui.scroll_region_left);
2091 rect.ul.y = FILL_Y(row + num_lines);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002092
Bram Moolenaar15d63192011-09-14 16:05:15 +02002093 rect.lr.x = FILL_X(gui.scroll_region_right + 1) - 1;
2094 rect.lr.y = FILL_Y(gui.scroll_region_bot + 1) - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002095
Bram Moolenaar15d63192011-09-14 16:05:15 +02002096 PtWidgetOffset(gui.vimTextArea, &gui_ph_raw_offset);
2097 PhTranslatePoint(&gui_ph_raw_offset, PtWidgetPos(gui.vimTextArea, NULL));
2098 PhTranslateRect(&rect, &gui_ph_raw_offset);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002099
2100 delta.x = 0;
2101 delta.y = -num_lines * gui.char_height;
2102
2103 PgFlush();
2104
Bram Moolenaar15d63192011-09-14 16:05:15 +02002105 PhBlit(PtWidgetRid(PtFindDisjoint(gui.vimTextArea)), &rect, &delta);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002106
2107 gui_clear_block(
2108 gui.scroll_region_bot - num_lines + 1,
2109 gui.scroll_region_left,
2110 gui.scroll_region_bot,
Bram Moolenaar15d63192011-09-14 16:05:15 +02002111 gui.scroll_region_right);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002112}
2113
2114 void
2115gui_mch_insert_lines(int row, int num_lines)
2116{
2117 PhRect_t rect;
2118 PhPoint_t delta;
2119
Bram Moolenaar15d63192011-09-14 16:05:15 +02002120 rect.ul.x = FILL_X(gui.scroll_region_left);
2121 rect.ul.y = FILL_Y(row);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002122
Bram Moolenaar15d63192011-09-14 16:05:15 +02002123 rect.lr.x = FILL_X(gui.scroll_region_right + 1) - 1;
2124 rect.lr.y = FILL_Y(gui.scroll_region_bot - num_lines + 1) - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002125
Bram Moolenaar15d63192011-09-14 16:05:15 +02002126 PtWidgetOffset(gui.vimTextArea, &gui_ph_raw_offset);
2127 PhTranslatePoint(&gui_ph_raw_offset, PtWidgetPos(gui.vimTextArea, NULL));
2128 PhTranslateRect(&rect, &gui_ph_raw_offset);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002129
2130 delta.x = 0;
2131 delta.y = num_lines * gui.char_height;
2132
2133 PgFlush();
2134
Bram Moolenaar15d63192011-09-14 16:05:15 +02002135 PhBlit(PtWidgetRid(PtFindDisjoint(gui.vimTextArea)) , &rect, &delta);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002136
Bram Moolenaar15d63192011-09-14 16:05:15 +02002137 gui_clear_block(row, gui.scroll_region_left,
2138 row + num_lines - 1, gui.scroll_region_right);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002139}
2140
2141 void
2142gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
2143{
2144 static char *utf8_buffer = NULL;
2145 static int utf8_len = 0;
2146
Bram Moolenaar15d63192011-09-14 16:05:15 +02002147 PhPoint_t pos = { TEXT_X(col), TEXT_Y(row) };
Bram Moolenaar071d4272004-06-13 20:20:40 +00002148 PhRect_t rect;
2149
Bram Moolenaar15d63192011-09-14 16:05:15 +02002150 if (is_ignore_draw == TRUE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002151 return;
2152
2153 DRAW_START;
2154
Bram Moolenaar15d63192011-09-14 16:05:15 +02002155 if (!(flags & DRAW_TRANSP))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002156 {
2157 PgDrawIRect(
Bram Moolenaar15d63192011-09-14 16:05:15 +02002158 FILL_X(col), FILL_Y(row),
2159 FILL_X(col + len) - 1, FILL_Y(row + 1) - 1,
2160 Pg_DRAW_FILL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002161 }
2162
Bram Moolenaar15d63192011-09-14 16:05:15 +02002163 if (flags & DRAW_UNDERL)
2164 PgSetUnderline(gui.norm_pixel, Pg_TRANSPARENT, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002165
Bram Moolenaar13505972019-01-24 15:04:48 +01002166 if (charset_translate != NULL && enc_utf8 == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002167 {
2168 int src_taken, dst_made;
2169
Bram Moolenaar734a8672019-12-02 22:49:38 +01002170 // Use a static buffer to avoid large amounts of de/allocations
Bram Moolenaar15d63192011-09-14 16:05:15 +02002171 if (utf8_len < len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002172 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002173 utf8_buffer = realloc(utf8_buffer, len * MB_LEN_MAX);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002174 utf8_len = len;
2175 }
2176
2177 PxTranslateToUTF(
2178 charset_translate,
2179 s,
2180 len,
2181 &src_taken,
2182 utf8_buffer,
2183 utf8_len,
Bram Moolenaar15d63192011-09-14 16:05:15 +02002184 &dst_made);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002185 s = utf8_buffer;
2186 len = dst_made;
2187 }
2188
Bram Moolenaar15d63192011-09-14 16:05:15 +02002189 PgDrawText(s, len, &pos, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002190
Bram Moolenaar15d63192011-09-14 16:05:15 +02002191 if (flags & DRAW_BOLD)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002192 {
Bram Moolenaar734a8672019-12-02 22:49:38 +01002193 // FIXME: try and only calculate these values once...
Bram Moolenaar15d63192011-09-14 16:05:15 +02002194 rect.ul.x = FILL_X(col) + 1;
2195 rect.ul.y = FILL_Y(row);
2196 rect.lr.x = FILL_X(col + len) - 1;
2197 rect.lr.y = FILL_Y(row + 1) - 1;
Bram Moolenaar734a8672019-12-02 22:49:38 +01002198 // PgSetUserClip(NULL) causes the scrollbar to not redraw...
Bram Moolenaar071d4272004-06-13 20:20:40 +00002199#if 0
2200 pos.x++;
2201
Bram Moolenaar15d63192011-09-14 16:05:15 +02002202 PgSetUserClip(&rect);
2203 PgDrawText(s, len, &pos, 0);
2204 PgSetUserClip(NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002205#else
Bram Moolenaar15d63192011-09-14 16:05:15 +02002206 rect.lr.y -= (p_linespace + 1) / 2;
Bram Moolenaar734a8672019-12-02 22:49:38 +01002207 // XXX: DrawTextArea doesn't work with phditto
Bram Moolenaar15d63192011-09-14 16:05:15 +02002208 PgDrawTextArea(s, len, &rect, Pg_TEXT_BOTTOM);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002209#endif
2210 }
2211
Bram Moolenaar15d63192011-09-14 16:05:15 +02002212 if (flags & DRAW_UNDERL)
2213 PgSetUnderline(Pg_TRANSPARENT, Pg_TRANSPARENT, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002214
2215 DRAW_END;
2216}
2217
Bram Moolenaar734a8672019-12-02 22:49:38 +01002218////////////////////////////////////////////////////////////////////////////
2219// Cursor
Bram Moolenaar071d4272004-06-13 20:20:40 +00002220
2221 void
2222gui_mch_draw_hollow_cursor(guicolor_T color)
2223{
2224 PhRect_t r;
2225
Bram Moolenaar734a8672019-12-02 22:49:38 +01002226 // FIXME: Double width characters
Bram Moolenaar071d4272004-06-13 20:20:40 +00002227
Bram Moolenaar15d63192011-09-14 16:05:15 +02002228 r.ul.x = FILL_X(gui.col);
2229 r.ul.y = FILL_Y(gui.row);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002230 r.lr.x = r.ul.x + gui.char_width - 1;
2231 r.lr.y = r.ul.y + gui.char_height - 1;
2232
2233 DRAW_START;
Bram Moolenaar15d63192011-09-14 16:05:15 +02002234 PgSetStrokeColor(color);
2235 PgDrawRect(&r, Pg_DRAW_STROKE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002236 DRAW_END;
2237}
2238
2239 void
2240gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
2241{
2242 PhRect_t r;
2243
Bram Moolenaar15d63192011-09-14 16:05:15 +02002244 r.ul.x = FILL_X(gui.col);
2245 r.ul.y = FILL_Y(gui.row) + gui.char_height - h;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002246 r.lr.x = r.ul.x + w - 1;
2247 r.lr.y = r.ul.y + h - 1;
2248
2249 DRAW_START;
Bram Moolenaar15d63192011-09-14 16:05:15 +02002250 gui_mch_set_bg_color(color);
2251 PgDrawRect(&r, Pg_DRAW_FILL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002252 DRAW_END;
2253}
2254
Bram Moolenaar703a8042016-06-04 16:24:32 +02002255 int
2256gui_mch_is_blinking(void)
2257{
2258 return blink_state != BLINK_NONE;
2259}
2260
Bram Moolenaar9d5d3c92016-07-07 16:43:02 +02002261 int
2262gui_mch_is_blink_off(void)
2263{
2264 return blink_state == BLINK_OFF;
2265}
2266
Bram Moolenaar071d4272004-06-13 20:20:40 +00002267 void
2268gui_mch_set_blinking(long wait, long on, long off)
2269{
2270 blink_waittime = wait;
2271 blink_ontime = on;
2272 blink_offtime = off;
2273}
2274
2275 void
2276gui_mch_start_blink(void)
2277{
Bram Moolenaar734a8672019-12-02 22:49:38 +01002278 // Only turn on the timer on if none of the times are zero
Bram Moolenaar15d63192011-09-14 16:05:15 +02002279 if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002280 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002281 PtSetResource(gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL,
2282 blink_waittime, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002283 blink_state = BLINK_ON;
2284 gui_update_cursor(TRUE, FALSE);
2285 }
2286}
2287
2288 void
Bram Moolenaar1dd45fb2018-01-31 21:10:01 +01002289gui_mch_stop_blink(int may_call_gui_update_cursor)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002290{
Bram Moolenaar15d63192011-09-14 16:05:15 +02002291 PtSetResource(gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL, 0, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002292
Bram Moolenaar1dd45fb2018-01-31 21:10:01 +01002293 if (blink_state == BLINK_OFF && may_call_gui_update_cursor)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002294 gui_update_cursor(TRUE, FALSE);
2295
2296 blink_state = BLINK_NONE;
2297}
2298
Bram Moolenaar734a8672019-12-02 22:49:38 +01002299////////////////////////////////////////////////////////////////////////////
2300// miscellaneous functions
Bram Moolenaar071d4272004-06-13 20:20:40 +00002301
2302 void
2303gui_mch_beep(void)
2304{
2305 PtBeep();
2306}
2307
2308 void
2309gui_mch_flash(int msec)
2310{
Bram Moolenaar15d63192011-09-14 16:05:15 +02002311 PgSetFillXORColor(Pg_BLACK, Pg_WHITE);
2312 PgSetDrawMode(Pg_DRAWMODE_XOR);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002313 gui_mch_clear_all();
2314 gui_mch_flush();
2315
Bram Moolenaar15d63192011-09-14 16:05:15 +02002316 ui_delay((long) msec, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002317
2318 gui_mch_clear_all();
Bram Moolenaar15d63192011-09-14 16:05:15 +02002319 PgSetDrawMode(Pg_DRAWMODE_OPAQUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002320 gui_mch_flush();
2321}
2322
2323 void
2324gui_mch_flush(void)
2325{
2326 PgFlush();
2327}
2328
2329 void
2330gui_mch_set_text_area_pos(int x, int y, int w, int h)
2331{
2332 PhArea_t area = {{x, y}, {w, h}};
2333
Bram Moolenaar15d63192011-09-14 16:05:15 +02002334 PtSetResource(gui.vimTextArea, Pt_ARG_AREA, &area, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002335}
2336
2337 int
2338gui_mch_haskey(char_u *name)
2339{
2340 int i;
2341
2342 for (i = 0; special_keys[i].key_sym != 0; i++)
2343 if (name[0] == special_keys[i].vim_code0 &&
2344 name[1] == special_keys[i].vim_code1)
Bram Moolenaard2221132011-07-27 14:09:09 +02002345 return OK;
2346 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002347}
2348
Bram Moolenaar734a8672019-12-02 22:49:38 +01002349////////////////////////////////////////////////////////////////////////////
2350// Menu
Bram Moolenaar071d4272004-06-13 20:20:40 +00002351
2352#ifdef FEAT_TOOLBAR
2353#include "toolbar.phi"
2354
2355static PhImage_t *gui_ph_toolbar_images[] = {
2356 &tb_new_phi,
2357 &tb_open_phi,
2358 &tb_save_phi,
2359 &tb_undo_phi,
2360 &tb_redo_phi,
2361 &tb_cut_phi,
2362 &tb_copy_phi,
2363 &tb_paste_phi,
2364 &tb_print_phi,
2365 &tb_help_phi,
2366 &tb_find_phi,
2367 &tb_save_all_phi,
2368 &tb_save_session_phi,
2369 &tb_new_session_phi,
2370 &tb_load_session_phi,
2371 &tb_macro_phi,
2372 &tb_replace_phi,
2373 &tb_close_phi,
2374 &tb_maximize_phi,
2375 &tb_minimize_phi,
2376 &tb_split_phi,
2377 &tb_shell_phi,
2378 &tb_find_prev_phi,
2379 &tb_find_next_phi,
2380 &tb_find_help_phi,
2381 &tb_make_phi,
2382 &tb_jump_phi,
2383 &tb_ctags_phi,
2384 &tb_vsplit_phi,
2385 &tb_maxwidth_phi,
2386 &tb_minwidth_phi
2387};
2388
2389static PhImage_t *
Bram Moolenaar15d63192011-09-14 16:05:15 +02002390gui_ph_toolbar_load_icon(char_u *iconfile)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002391{
2392 static PhImage_t external_icon;
2393 PhImage_t *temp_phi = NULL;
2394
Bram Moolenaar15d63192011-09-14 16:05:15 +02002395 temp_phi = PxLoadImage(iconfile, NULL);
2396 if (temp_phi != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002397 {
Bram Moolenaar734a8672019-12-02 22:49:38 +01002398 // The label widget will free the image/palette/etc. for us when
2399 // it's destroyed
Bram Moolenaar071d4272004-06-13 20:20:40 +00002400 temp_phi->flags |= Ph_RELEASE_IMAGE_ALL;
Bram Moolenaar15d63192011-09-14 16:05:15 +02002401 memcpy(&external_icon, temp_phi, sizeof(external_icon));
2402 free(temp_phi);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002403
2404 temp_phi = &external_icon;
2405 }
Bram Moolenaard2221132011-07-27 14:09:09 +02002406 return temp_phi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002407}
2408
2409/*
2410 * This returns either a builtin icon image, an external image or NULL
2411 * if it can't find either. The caller can't and doesn't need to try and
2412 * free() the returned image, and it can't store the image pointer.
2413 * (When setting the Pt_ARG_LABEL_IMAGE resource, the contents of the
2414 * PhImage_t are copied, and the original PhImage_t aren't needed anymore).
2415 */
2416static PhImage_t *
Bram Moolenaar15d63192011-09-14 16:05:15 +02002417gui_ph_toolbar_find_icon(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002418{
2419 char_u full_pathname[ MAXPATHL + 1 ];
2420 PhImage_t *icon = NULL;
2421
Bram Moolenaar15d63192011-09-14 16:05:15 +02002422 if (menu->icon_builtin == FALSE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002423 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002424 if (menu->iconfile != NULL)
Bram Moolenaar734a8672019-12-02 22:49:38 +01002425 // TODO: use gui_find_iconfile()
Bram Moolenaar15d63192011-09-14 16:05:15 +02002426 icon = gui_ph_toolbar_load_icon(menu->iconfile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002427
Bram Moolenaar734a8672019-12-02 22:49:38 +01002428 // TODO: Restrict loading to just .png? Search for any format?
Bram Moolenaar15d63192011-09-14 16:05:15 +02002429 if ((icon == NULL) &&
2430 ((gui_find_bitmap(menu->name, full_pathname, "gif") == OK) ||
2431 (gui_find_bitmap(menu->name, full_pathname, "png") == OK)))
2432 icon = gui_ph_toolbar_load_icon(full_pathname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002433
Bram Moolenaar15d63192011-09-14 16:05:15 +02002434 if (icon != NULL)
Bram Moolenaard2221132011-07-27 14:09:09 +02002435 return icon;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002436 }
2437
Bram Moolenaar15d63192011-09-14 16:05:15 +02002438 if (menu->iconidx >= 0 &&
2439 (menu->iconidx < ARRAY_LENGTH(gui_ph_toolbar_images)))
Bram Moolenaard2221132011-07-27 14:09:09 +02002440 return gui_ph_toolbar_images[menu->iconidx];
Bram Moolenaar071d4272004-06-13 20:20:40 +00002441
Bram Moolenaard2221132011-07-27 14:09:09 +02002442 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002443}
2444#endif
2445
Bram Moolenaar15d63192011-09-14 16:05:15 +02002446#if defined(FEAT_MENU) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002447 void
2448gui_mch_enable_menu(int flag)
2449{
Bram Moolenaar15d63192011-09-14 16:05:15 +02002450 if (flag != 0)
2451 PtRealizeWidget(gui.vimMenuBar);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002452 else
Bram Moolenaar15d63192011-09-14 16:05:15 +02002453 PtUnrealizeWidget(gui.vimMenuBar);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002454}
2455
2456 void
2457gui_mch_set_menu_pos(int x, int y, int w, int h)
2458{
Bram Moolenaar734a8672019-12-02 22:49:38 +01002459 // Nothing
Bram Moolenaar071d4272004-06-13 20:20:40 +00002460}
2461
Bram Moolenaar734a8672019-12-02 22:49:38 +01002462/*
2463 * Change the position of a menu button in the parent
2464 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002465 static void
Bram Moolenaar15d63192011-09-14 16:05:15 +02002466gui_ph_position_menu(PtWidget_t *widget, int priority)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002467{
2468 PtWidget_t *traverse;
2469 vimmenu_T *menu;
2470
Bram Moolenaar15d63192011-09-14 16:05:15 +02002471 traverse = PtWidgetChildBack(PtWidgetParent(widget));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002472
Bram Moolenaar734a8672019-12-02 22:49:38 +01002473 // Iterate through the list of widgets in traverse, until
2474 // we find the position we want to insert our widget into
2475 // TODO: traverse from front to back, possible speedup?
Bram Moolenaar15d63192011-09-14 16:05:15 +02002476 while (traverse != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002477 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002478 PtGetResource(traverse, Pt_ARG_POINTER, &menu, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002479
Bram Moolenaar15d63192011-09-14 16:05:15 +02002480 if (menu != NULL &&
Bram Moolenaar071d4272004-06-13 20:20:40 +00002481 priority < menu->priority &&
Bram Moolenaar15d63192011-09-14 16:05:15 +02002482 widget != traverse)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002483 {
Bram Moolenaar734a8672019-12-02 22:49:38 +01002484 // Insert the widget before the current traverse widget
Bram Moolenaar15d63192011-09-14 16:05:15 +02002485 PtWidgetInsert(widget, traverse, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002486 return;
2487 }
2488
Bram Moolenaar15d63192011-09-14 16:05:15 +02002489 traverse = PtWidgetBrotherInFront(traverse);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002490 }
2491}
2492
Bram Moolenaar734a8672019-12-02 22:49:38 +01002493/*
2494 * the index is ignored because it's not useful for our purposes
2495 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002496 void
2497gui_mch_add_menu(vimmenu_T *menu, int index)
2498{
2499 vimmenu_T *parent = menu->parent;
2500 char_u *accel_key;
2501 char_u mnemonic_str[MB_LEN_MAX];
2502 int n;
2503 PtArg_t args[5];
2504
2505 menu->submenu_id = menu->id = NULL;
2506
Bram Moolenaar15d63192011-09-14 16:05:15 +02002507 if (menu_is_menubar(menu->name))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002508 {
2509
Bram Moolenaar15d63192011-09-14 16:05:15 +02002510 accel_key = vim_strchr(menu->name, '&');
2511 if (accel_key != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002512 {
2513 mnemonic_str[0] = accel_key[1];
2514 mnemonic_str[1] = NUL;
2515 }
2516
Bram Moolenaar734a8672019-12-02 22:49:38 +01002517 // Create the menu button
Bram Moolenaar071d4272004-06-13 20:20:40 +00002518 n = 0;
Bram Moolenaar15d63192011-09-14 16:05:15 +02002519 PtSetArg(&args[ n++ ], Pt_ARG_TEXT_STRING, menu->dname, 0);
2520 PtSetArg(&args[ n++ ], Pt_ARG_ACCEL_TEXT, menu->actext, 0);
2521 if (accel_key != NULL)
2522 PtSetArg(&args[ n++ ], Pt_ARG_ACCEL_KEY, mnemonic_str, 0);
2523 PtSetArg(&args[ n++ ], Pt_ARG_POINTER, menu, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002524
Bram Moolenaar15d63192011-09-14 16:05:15 +02002525 if (parent != NULL)
2526 PtSetArg(&args[ n++ ], Pt_ARG_BUTTON_TYPE, Pt_MENU_RIGHT, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002527
Bram Moolenaar15d63192011-09-14 16:05:15 +02002528 menu->id = PtCreateWidget(PtMenuButton,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002529 (parent == NULL) ? gui.vimMenuBar : parent->submenu_id,
Bram Moolenaar15d63192011-09-14 16:05:15 +02002530 n, args);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002531
Bram Moolenaar15d63192011-09-14 16:05:15 +02002532 PtAddCallback(menu->id, Pt_CB_ARM, gui_ph_handle_pulldown_menu, menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002533
Bram Moolenaar734a8672019-12-02 22:49:38 +01002534 // Create the actual menu
Bram Moolenaar071d4272004-06-13 20:20:40 +00002535 n = 0;
Bram Moolenaar15d63192011-09-14 16:05:15 +02002536 if (parent != NULL)
2537 PtSetArg(&args[ n++ ], Pt_ARG_MENU_FLAGS, Pt_TRUE, Pt_MENU_CHILD);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002538
Bram Moolenaar15d63192011-09-14 16:05:15 +02002539 menu->submenu_id = PtCreateWidget(PtMenu, menu->id, n, args);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002540
Bram Moolenaar15d63192011-09-14 16:05:15 +02002541 if (parent == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002542 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002543 PtAddCallback(menu->submenu_id, Pt_CB_UNREALIZED,
2544 gui_ph_handle_menu_unrealized, menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002545
Bram Moolenaar15d63192011-09-14 16:05:15 +02002546 if (menu->mnemonic != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002547 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002548 PtAddHotkeyHandler(gui.vimWindow, tolower(menu->mnemonic),
2549 Pk_KM_Alt, 0, menu, gui_ph_handle_pulldown_menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002550 }
2551 }
2552
Bram Moolenaar15d63192011-09-14 16:05:15 +02002553 gui_ph_position_menu(menu->id, menu->priority);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002554
Bram Moolenaar734a8672019-12-02 22:49:38 +01002555 // Redraw menubar here instead of gui_mch_draw_menubar
Bram Moolenaar15d63192011-09-14 16:05:15 +02002556 if (gui.menu_is_active)
2557 PtRealizeWidget(menu->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002558 }
Bram Moolenaar15d63192011-09-14 16:05:15 +02002559 else if (menu_is_popup(menu->name))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002560 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002561 menu->submenu_id = PtCreateWidget(PtMenu, gui.vimWindow, 0, NULL);
2562 PtAddCallback(menu->submenu_id, Pt_CB_UNREALIZED,
2563 gui_ph_handle_menu_unrealized, menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002564 }
2565}
2566
2567 void
2568gui_mch_add_menu_item(vimmenu_T *menu, int index)
2569{
2570 vimmenu_T *parent = menu->parent;
2571 char_u *accel_key;
2572 char_u mnemonic_str[MB_LEN_MAX];
2573 int n;
2574 PtArg_t args[13];
2575
2576 n = 0;
Bram Moolenaar15d63192011-09-14 16:05:15 +02002577 PtSetArg(&args[ n++ ], Pt_ARG_POINTER, menu, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002578
2579#ifdef FEAT_TOOLBAR
Bram Moolenaar15d63192011-09-14 16:05:15 +02002580 if (menu_is_toolbar(parent->name))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002581 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002582 if (menu_is_separator(menu->name))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002583 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002584 PtSetArg(&args[ n++ ], Pt_ARG_SEP_FLAGS,
2585 Pt_SEP_VERTICAL, Pt_SEP_ORIENTATION);
2586 PtSetArg(&args[ n++ ], Pt_ARG_SEP_TYPE, Pt_ETCHED_IN, 0);
2587 PtSetArg(&args[ n++ ], Pt_ARG_ANCHOR_FLAGS,
2588 Pt_TRUE, Pt_ANCHOR_TOP_BOTTOM);
2589 PtSetArg(&args[ n++ ], Pt_ARG_WIDTH, 2, 0);
2590 menu->id = PtCreateWidget(PtSeparator, gui.vimToolBar, n, args);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002591 }
2592 else
2593 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002594 if (strstr((const char *) p_toolbar, "text") != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002595 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002596 PtSetArg(&args[ n++ ], Pt_ARG_BALLOON_POSITION,
2597 Pt_BALLOON_BOTTOM, 0);
2598 PtSetArg(&args[ n++ ], Pt_ARG_TEXT_STRING, menu->dname, 0);
2599 PtSetArg(&args[ n++ ], Pt_ARG_TEXT_FONT, "TextFont08", 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002600 }
Bram Moolenaar15d63192011-09-14 16:05:15 +02002601 if ((strstr((const char *) p_toolbar, "icons") != NULL) &&
2602 (gui_ph_toolbar_images != NULL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002603 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002604 PtSetArg(&args[ n++ ], Pt_ARG_LABEL_IMAGE,
2605 gui_ph_toolbar_find_icon(menu), 0);
2606 PtSetArg(&args[ n++ ], Pt_ARG_LABEL_TYPE, Pt_TEXT_IMAGE, 0);
2607 PtSetArg(&args[ n++ ], Pt_ARG_TEXT_IMAGE_SPACING, 0, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002608 }
Bram Moolenaar15d63192011-09-14 16:05:15 +02002609 if (strstr((const char *) p_toolbar, "tooltips") != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002610 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002611 PtSetArg(&args[ n++ ], Pt_ARG_LABEL_BALLOON,
2612 gui_ph_show_tooltip, 0);
2613 PtSetArg(&args[ n++ ], Pt_ARG_LABEL_FLAGS,
2614 Pt_TRUE, Pt_SHOW_BALLOON);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002615 }
Bram Moolenaar15d63192011-09-14 16:05:15 +02002616 PtSetArg(&args[ n++ ], Pt_ARG_MARGIN_HEIGHT, 1, 0);
2617 PtSetArg(&args[ n++ ], Pt_ARG_MARGIN_WIDTH, 1, 0);
2618 PtSetArg(&args[ n++ ], Pt_ARG_FLAGS, Pt_FALSE,
2619 Pt_HIGHLIGHTED | Pt_GETS_FOCUS);
2620 PtSetArg(&args[ n++ ], Pt_ARG_FILL_COLOR, Pg_TRANSPARENT, 0);
2621 menu->id = PtCreateWidget(PtButton, gui.vimToolBar, n, args);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002622
Bram Moolenaar15d63192011-09-14 16:05:15 +02002623 PtAddCallback(menu->id, Pt_CB_ACTIVATE, gui_ph_handle_menu, menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002624 }
Bram Moolenaar734a8672019-12-02 22:49:38 +01002625 // Update toolbar if it's open
Bram Moolenaar15d63192011-09-14 16:05:15 +02002626 if (PtWidgetIsRealized(gui.vimToolBar))
2627 PtRealizeWidget(menu->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002628 }
2629 else
2630#endif
Bram Moolenaar15d63192011-09-14 16:05:15 +02002631 if (menu_is_separator(menu->name))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002632 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002633 menu->id = PtCreateWidget(PtSeparator, parent->submenu_id, n, args);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002634 }
2635 else
2636 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002637 accel_key = vim_strchr(menu->name, '&');
2638 if (accel_key != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002639 {
2640 mnemonic_str[0] = accel_key[1];
2641 mnemonic_str[1] = NUL;
2642 }
2643
Bram Moolenaar15d63192011-09-14 16:05:15 +02002644 PtSetArg(&args[ n++ ], Pt_ARG_TEXT_STRING, menu->dname, 0);
2645 if (accel_key != NULL)
2646 PtSetArg(&args[ n++ ], Pt_ARG_ACCEL_KEY, mnemonic_str,
2647 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002648
Bram Moolenaar15d63192011-09-14 16:05:15 +02002649 PtSetArg(&args[ n++ ], Pt_ARG_ACCEL_TEXT, menu->actext, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002650
Bram Moolenaar15d63192011-09-14 16:05:15 +02002651 menu->id = PtCreateWidget(PtMenuButton, parent->submenu_id, n, args);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002652
Bram Moolenaar15d63192011-09-14 16:05:15 +02002653 PtAddCallback(menu->id, Pt_CB_ACTIVATE, gui_ph_handle_menu, menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002654
2655#ifdef USE_PANEL_GROUP
Bram Moolenaar15d63192011-09-14 16:05:15 +02002656 if (gui_ph_is_buffer_item(menu, parent) == TRUE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002657 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002658 PtAddCallback(menu->id, Pt_CB_DESTROYED,
2659 gui_ph_handle_buffer_remove, menu);
2660 gui_ph_pg_add_buffer(menu->dname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002661 }
2662#endif
2663 }
2664
Bram Moolenaar15d63192011-09-14 16:05:15 +02002665 gui_ph_position_menu(menu->id, menu->priority);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002666}
2667
2668 void
2669gui_mch_destroy_menu(vimmenu_T *menu)
2670{
Bram Moolenaar15d63192011-09-14 16:05:15 +02002671 if (menu->submenu_id != NULL)
2672 PtDestroyWidget(menu->submenu_id);
2673 if (menu->id != NULL)
2674 PtDestroyWidget(menu->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002675
2676 menu->submenu_id = NULL;
2677 menu->id = NULL;
2678}
2679
2680 void
2681gui_mch_menu_grey(vimmenu_T *menu, int grey)
2682{
2683 long flags, mask, fields;
2684
Bram Moolenaar15d63192011-09-14 16:05:15 +02002685 if (menu->id == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002686 return;
2687
Bram Moolenaar15d63192011-09-14 16:05:15 +02002688 flags = PtWidgetFlags(menu->id);
2689 if (PtWidgetIsClass(menu->id, PtMenuButton) &&
2690 PtWidgetIsClass(PtWidgetParent(menu->id), PtMenu))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002691 {
2692 fields = Pt_FALSE;
2693 mask = Pt_SELECTABLE | Pt_HIGHLIGHTED;
2694 }
2695 else
2696 {
2697 fields = Pt_TRUE;
2698 mask = Pt_BLOCKED | Pt_GHOST;
2699 }
2700
Bram Moolenaar15d63192011-09-14 16:05:15 +02002701 if (! grey)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002702 fields = ~fields;
2703
Bram Moolenaar15d63192011-09-14 16:05:15 +02002704 PtSetResource(menu->id, Pt_ARG_FLAGS, fields,
2705 mask);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002706}
2707
2708 void
2709gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
2710{
Bram Moolenaar734a8672019-12-02 22:49:38 +01002711 // TODO: [un]realize the widget?
Bram Moolenaar071d4272004-06-13 20:20:40 +00002712}
2713
2714 void
2715gui_mch_draw_menubar(void)
2716{
Bram Moolenaar734a8672019-12-02 22:49:38 +01002717 // The only time a redraw is needed is when a menu button
2718 // is added to the menubar, and that is detected and the bar
2719 // redrawn in gui_mch_add_menu_item
Bram Moolenaar071d4272004-06-13 20:20:40 +00002720}
2721
2722 void
2723gui_mch_show_popupmenu(vimmenu_T *menu)
2724{
Bram Moolenaar15d63192011-09-14 16:05:15 +02002725 PtSetResource(menu->submenu_id, Pt_ARG_POS, &abs_mouse, 0);
2726 PtRealizeWidget(menu->submenu_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002727}
2728
2729 void
2730gui_mch_toggle_tearoffs(int enable)
2731{
Bram Moolenaar734a8672019-12-02 22:49:38 +01002732 // No tearoffs yet
Bram Moolenaar071d4272004-06-13 20:20:40 +00002733}
2734
2735#endif
2736
Bram Moolenaar15d63192011-09-14 16:05:15 +02002737#if defined(FEAT_TOOLBAR) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002738 void
2739gui_mch_show_toolbar(int showit)
2740{
Bram Moolenaar15d63192011-09-14 16:05:15 +02002741 if (showit)
2742 PtRealizeWidget(gui.vimToolBar);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002743 else
Bram Moolenaar15d63192011-09-14 16:05:15 +02002744 PtUnrealizeWidget(gui.vimToolBar);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002745}
2746#endif
2747
Bram Moolenaar734a8672019-12-02 22:49:38 +01002748////////////////////////////////////////////////////////////////////////////
2749// Fonts
Bram Moolenaar071d4272004-06-13 20:20:40 +00002750
2751 static GuiFont
2752gui_ph_get_font(
2753 char_u *font_name,
2754 int_u font_flags,
2755 int_u font_size,
Bram Moolenaar734a8672019-12-02 22:49:38 +01002756 // Check whether the resulting font has the font flags and size that
2757 // was asked for
Bram Moolenaar071d4272004-06-13 20:20:40 +00002758 int_u enforce
2759 )
2760{
2761 char_u *font_tag;
2762 FontQueryInfo info;
2763 int_u style;
2764
Bram Moolenaar15d63192011-09-14 16:05:15 +02002765 font_tag = alloc(MAX_FONT_TAG);
2766 if (font_tag != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002767 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002768 if (PfGenerateFontName(font_name, font_flags, font_size,
2769 font_tag) != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002770 {
Bram Moolenaar734a8672019-12-02 22:49:38 +01002771 // Enforce some limits on the font used
Bram Moolenaar071d4272004-06-13 20:20:40 +00002772 style = PHFONT_INFO_FIXED;
2773
Bram Moolenaar15d63192011-09-14 16:05:15 +02002774 if (enforce & PF_STYLE_BOLD)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002775 style |= PHFONT_INFO_BOLD;
Bram Moolenaar15d63192011-09-14 16:05:15 +02002776 if (enforce & PF_STYLE_ANTIALIAS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002777 style |= PHFONT_INFO_ALIAS;
Bram Moolenaar15d63192011-09-14 16:05:15 +02002778 if (enforce & PF_STYLE_ITALIC)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002779 style |= PHFONT_INFO_ITALIC;
2780
Bram Moolenaar15d63192011-09-14 16:05:15 +02002781 PfQueryFontInfo(font_tag, &info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002782
Bram Moolenaar15d63192011-09-14 16:05:15 +02002783 if (info.size == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002784 font_size = 0;
2785
Bram Moolenaar734a8672019-12-02 22:49:38 +01002786 // Make sure font size matches, and that the font style
2787 // at least has the bits we're checking for
Bram Moolenaar15d63192011-09-14 16:05:15 +02002788 if (font_size == info.size &&
2789 style == (info.style & style))
Bram Moolenaard2221132011-07-27 14:09:09 +02002790 return (GuiFont)font_tag;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002791 }
Bram Moolenaar15d63192011-09-14 16:05:15 +02002792 vim_free(font_tag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002793 }
Bram Moolenaard2221132011-07-27 14:09:09 +02002794 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002795}
2796
2797/*
2798 * Split up the vim font name
2799 *
2800 * vim_font is in the form of
2801 * <name>:s<height>:a:b:i
2802 *
2803 * a = antialias
2804 * b = bold
2805 * i = italic
2806 *
2807 */
2808
2809 static int
2810gui_ph_parse_font_name(
2811 char_u *vim_font,
2812 char_u **font_name,
2813 int_u *font_flags,
Bram Moolenaar15d63192011-09-14 16:05:15 +02002814 int_u *font_size)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002815{
2816 char_u *mark;
2817 int_u name_len, size;
2818
Bram Moolenaar15d63192011-09-14 16:05:15 +02002819 mark = vim_strchr(vim_font, ':');
2820 if (mark == NULL)
2821 name_len = STRLEN(vim_font);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002822 else
Bram Moolenaar15d63192011-09-14 16:05:15 +02002823 name_len = (int_u) (mark - vim_font);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002824
Bram Moolenaar15d63192011-09-14 16:05:15 +02002825 *font_name = vim_strnsave(vim_font, name_len);
Bram Moolenaard0988c52011-08-10 12:19:04 +02002826 if (*font_name != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002827 {
Bram Moolenaard0988c52011-08-10 12:19:04 +02002828 if (mark != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002829 {
Bram Moolenaard0988c52011-08-10 12:19:04 +02002830 while (*mark != NUL && *mark++ == ':')
Bram Moolenaar071d4272004-06-13 20:20:40 +00002831 {
Bram Moolenaard0988c52011-08-10 12:19:04 +02002832 switch (tolower(*mark++))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002833 {
2834 case 'a': *font_flags |= PF_STYLE_ANTIALIAS; break;
2835 case 'b': *font_flags |= PF_STYLE_BOLD; break;
2836 case 'i': *font_flags |= PF_STYLE_ITALIC; break;
2837
2838 case 's':
Bram Moolenaar15d63192011-09-14 16:05:15 +02002839 size = getdigits(&mark);
Bram Moolenaar734a8672019-12-02 22:49:38 +01002840 // Restrict the size to some vague limits
Bram Moolenaard0988c52011-08-10 12:19:04 +02002841 if (size < 1 || size > 100)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002842 size = 8;
2843
2844 *font_size = size;
2845 break;
2846
2847 default:
2848 break;
2849 }
2850 }
2851 }
Bram Moolenaard2221132011-07-27 14:09:09 +02002852 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002853 }
Bram Moolenaard2221132011-07-27 14:09:09 +02002854 return FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002855}
2856
2857 int
2858gui_mch_init_font(char_u *vim_font_name, int fontset)
2859{
2860 char_u *font_tag;
2861 char_u *font_name = NULL;
2862 int_u font_flags = 0;
2863 int_u font_size = 12;
2864
2865 FontQueryInfo info;
2866 PhRect_t extent;
2867
Bram Moolenaard0988c52011-08-10 12:19:04 +02002868 if (vim_font_name == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002869 {
Bram Moolenaar734a8672019-12-02 22:49:38 +01002870 // Default font
Bram Moolenaara0b19972009-07-01 14:13:18 +00002871 vim_font_name = "PC Terminal";
Bram Moolenaar071d4272004-06-13 20:20:40 +00002872 }
2873
Bram Moolenaar15d63192011-09-14 16:05:15 +02002874 if (STRCMP(vim_font_name, "*") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002875 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002876 font_tag = PtFontSelection(gui.vimWindow, NULL, NULL,
2877 "pcterm12", -1, PHFONT_FIXED, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002878
Bram Moolenaard0988c52011-08-10 12:19:04 +02002879 if (font_tag == NULL)
Bram Moolenaard2221132011-07-27 14:09:09 +02002880 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002881
Bram Moolenaar15d63192011-09-14 16:05:15 +02002882 gui_mch_free_font(gui.norm_font);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002883 gui.norm_font = font_tag;
2884
Bram Moolenaar15d63192011-09-14 16:05:15 +02002885 PfQueryFontInfo(font_tag, &info);
2886 font_name = vim_strsave(info.font);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002887 }
2888 else
2889 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002890 if (gui_ph_parse_font_name(vim_font_name, &font_name, &font_flags,
2891 &font_size) == FALSE)
Bram Moolenaard2221132011-07-27 14:09:09 +02002892 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002893
Bram Moolenaar15d63192011-09-14 16:05:15 +02002894 font_tag = gui_ph_get_font(font_name, font_flags, font_size, 0);
Bram Moolenaard0988c52011-08-10 12:19:04 +02002895 if (font_tag == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002896 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002897 vim_free(font_name);
Bram Moolenaard2221132011-07-27 14:09:09 +02002898 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002899 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002900
Bram Moolenaar15d63192011-09-14 16:05:15 +02002901 gui_mch_free_font(gui.norm_font);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002902 gui.norm_font = font_tag;
2903 }
2904
Bram Moolenaar15d63192011-09-14 16:05:15 +02002905 gui_mch_free_font(gui.bold_font);
2906 gui.bold_font = gui_ph_get_font(font_name, font_flags | PF_STYLE_BOLD,
2907 font_size, PF_STYLE_BOLD);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002908
Bram Moolenaar15d63192011-09-14 16:05:15 +02002909 gui_mch_free_font(gui.ital_font);
2910 gui.ital_font = gui_ph_get_font(font_name, font_flags | PF_STYLE_ITALIC,
2911 font_size, PF_STYLE_ITALIC);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002912
Bram Moolenaar734a8672019-12-02 22:49:38 +01002913 // This extent was brought to you by the letter 'g'
Bram Moolenaar15d63192011-09-14 16:05:15 +02002914 PfExtentText(&extent, NULL, font_tag, "g", 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002915
2916 gui.char_width = extent.lr.x - extent.ul.x + 1;
2917 gui.char_height = (- extent.ul.y) + extent.lr.y + 1;
2918 gui.char_ascent = - extent.ul.y;
2919
Bram Moolenaar15d63192011-09-14 16:05:15 +02002920 vim_free(font_name);
Bram Moolenaard2221132011-07-27 14:09:09 +02002921 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002922}
2923
Bram Moolenaar02743632005-07-25 20:42:36 +00002924/*
2925 * Adjust gui.char_height (after 'linespace' was changed).
2926 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002927 int
Bram Moolenaar02743632005-07-25 20:42:36 +00002928gui_mch_adjust_charheight(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002929{
2930 FontQueryInfo info;
2931
Bram Moolenaar15d63192011-09-14 16:05:15 +02002932 PfQueryFontInfo(gui.norm_font, &info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002933
2934 gui.char_height = - info.ascender + info.descender + p_linespace;
2935 gui.char_ascent = - info.ascender + p_linespace / 2;
2936
Bram Moolenaard2221132011-07-27 14:09:09 +02002937 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002938}
2939
2940 GuiFont
2941gui_mch_get_font(char_u *vim_font_name, int report_error)
2942{
2943 char_u *font_name;
2944 char_u *font_tag;
2945 int_u font_size = 12;
2946 int_u font_flags = 0;
2947
Bram Moolenaar15d63192011-09-14 16:05:15 +02002948 if (gui_ph_parse_font_name(vim_font_name, &font_name, &font_flags,
2949 &font_size) != FALSE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002950 {
Bram Moolenaar15d63192011-09-14 16:05:15 +02002951 font_tag = gui_ph_get_font(font_name, font_flags, font_size, -1);
2952 vim_free(font_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002953
Bram Moolenaard0988c52011-08-10 12:19:04 +02002954 if (font_tag != NULL)
Bram Moolenaard2221132011-07-27 14:09:09 +02002955 return (GuiFont)font_tag;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002956 }
2957
Bram Moolenaard0988c52011-08-10 12:19:04 +02002958 if (report_error)
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00002959 semsg(e_unknown_font_str, vim_font_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002960
Bram Moolenaard2221132011-07-27 14:09:09 +02002961 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002962}
2963
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002964#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002965/*
2966 * Return the name of font "font" in allocated memory.
2967 * Don't know how to get the actual name, thus use the provided name.
2968 */
2969 char_u *
Bram Moolenaar68c2f632016-01-30 17:24:07 +01002970gui_mch_get_fontname(GuiFont font, char_u *name)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002971{
2972 if (name == NULL)
2973 return NULL;
2974 return vim_strsave(name);
2975}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002976#endif
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002977
Bram Moolenaar071d4272004-06-13 20:20:40 +00002978 void
2979gui_mch_set_font(GuiFont font)
2980{
Bram Moolenaar15d63192011-09-14 16:05:15 +02002981 PgSetFont(font);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002982}
2983
2984 void
2985gui_mch_free_font(GuiFont font)
2986{
Bram Moolenaar15d63192011-09-14 16:05:15 +02002987 vim_free(font);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002988}
2989