Mercurial > vim
annotate src/gui.c @ 3087:3ecf9e91d88a v7.3.315
updated for version 7.3.315
Problem: Opening a window before forking causes problems for GTK.
Solution: Fork first, create the window in the child and report back to the
parent process whether it worked. If successful the parent exits,
if unsuccessful the child exits and the parent continues in the
terminal. (Tim Starling)
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Wed, 14 Sep 2011 19:04:39 +0200 |
parents | 342b17608967 |
children | 7ba2f171cdac |
rev | line source |
---|---|
7 | 1 /* vi:set ts=8 sts=4 sw=4: |
2 * | |
3 * VIM - Vi IMproved by Bram Moolenaar | |
4 * GUI/Motif support by Robert Webb | |
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 * See README.txt for an overview of the Vim source code. | |
9 */ | |
10 | |
11 #include "vim.h" | |
12 | |
13 /* Structure containing all the GUI information */ | |
14 gui_T gui; | |
15 | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
16 #if defined(FEAT_MBYTE) && !defined(FEAT_GUI_GTK) |
7 | 17 static void set_guifontwide __ARGS((char_u *font_name)); |
18 #endif | |
19 static void gui_check_pos __ARGS((void)); | |
20 static void gui_position_components __ARGS((int)); | |
21 static void gui_outstr __ARGS((char_u *, int)); | |
22 static int gui_screenchar __ARGS((int off, int flags, guicolor_T fg, guicolor_T bg, int back)); | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
23 #ifdef FEAT_GUI_GTK |
7 | 24 static int gui_screenstr __ARGS((int off, int len, int flags, guicolor_T fg, guicolor_T bg, int back)); |
25 #endif | |
26 static void gui_delete_lines __ARGS((int row, int count)); | |
27 static void gui_insert_lines __ARGS((int row, int count)); | |
28 static void fill_mouse_coord __ARGS((char_u *p, int col, int row)); | |
685 | 29 #if defined(FEAT_GUI_TABLINE) || defined(PROTO) |
30 static int gui_has_tabline __ARGS((void)); | |
31 #endif | |
7 | 32 static void gui_do_scrollbar __ARGS((win_T *wp, int which, int enable)); |
33 static colnr_T scroll_line_len __ARGS((linenr_T lnum)); | |
2409
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
34 static linenr_T gui_find_longest_lnum __ARGS((void)); |
7 | 35 static void gui_update_horiz_scrollbar __ARGS((int)); |
203 | 36 static void gui_set_fg_color __ARGS((char_u *name)); |
37 static void gui_set_bg_color __ARGS((char_u *name)); | |
7 | 38 static win_T *xy2win __ARGS((int x, int y)); |
39 | |
3087 | 40 #if defined(UNIX) && !defined(__BEOS__) && !defined(MACOS_X) \ |
41 && !defined(__APPLE__) | |
42 # define MAY_FORK | |
43 static void gui_do_fork __ARGS((void)); | |
44 | |
45 static int gui_read_child_pipe __ARGS((int fd)); | |
46 | |
47 /* Return values for gui_read_child_pipe */ | |
48 enum { | |
49 GUI_CHILD_IO_ERROR, | |
50 GUI_CHILD_OK, | |
51 GUI_CHILD_FAILED | |
52 }; | |
53 | |
54 #endif /* MAY_FORK */ | |
55 | |
56 static void gui_attempt_start __ARGS((void)); | |
57 | |
7 | 58 static int can_update_cursor = TRUE; /* can display the cursor */ |
59 | |
60 /* | |
61 * The Athena scrollbars can move the thumb to after the end of the scrollbar, | |
62 * this makes the thumb indicate the part of the text that is shown. Motif | |
63 * can't do this. | |
64 */ | |
65 #if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MAC) | |
66 # define SCROLL_PAST_END | |
67 #endif | |
68 | |
69 /* | |
70 * gui_start -- Called when user wants to start the GUI. | |
71 * | |
72 * Careful: This function can be called recursively when there is a ":gui" | |
73 * command in the .gvimrc file. Only the first call should fork, not the | |
74 * recursive call. | |
75 */ | |
76 void | |
77 gui_start() | |
78 { | |
79 char_u *old_term; | |
80 static int recursive = 0; | |
81 | |
82 old_term = vim_strsave(T_NAME); | |
83 | |
84 settmode(TMODE_COOK); /* stop RAW mode */ | |
85 if (full_screen) | |
86 cursor_on(); /* needed for ":gui" in .vimrc */ | |
87 full_screen = FALSE; | |
88 | |
3087 | 89 ++recursive; |
2923 | 90 |
7 | 91 #ifdef MAY_FORK |
3087 | 92 /* |
93 * Quit the current process and continue in the child. | |
94 * Makes "gvim file" disconnect from the shell it was started in. | |
95 * Don't do this when Vim was started with "-f" or the 'f' flag is present | |
96 * in 'guioptions'. | |
97 */ | |
98 if (gui.dofork && !vim_strchr(p_go, GO_FORG) && recursive <= 1) | |
99 { | |
100 gui_do_fork(); | |
101 } | |
102 else | |
103 #endif | |
104 { | |
105 gui_attempt_start(); | |
106 } | |
7 | 107 |
108 if (!gui.in_use) /* failed to start GUI */ | |
109 { | |
3087 | 110 /* Back to old term settings |
111 * | |
112 * FIXME: If we got here because a child process failed and flagged to | |
113 * the parent to resume, and X11 is enabled with FEAT_TITLE, this will | |
114 * hit an X11 I/O error and do a longjmp(), leaving recursive | |
115 * permanently set to 1. This is probably not as big a problem as it | |
116 * sounds, because gui_mch_init() in both gui_x11.c and gui_gtk_x11.c | |
117 * return "OK" unconditionally, so it would be very difficult to | |
118 * actually hit this case. | |
119 */ | |
120 termcapinit(old_term); | |
7 | 121 settmode(TMODE_RAW); /* restart RAW mode */ |
122 #ifdef FEAT_TITLE | |
123 set_title_defaults(); /* set 'title' and 'icon' again */ | |
124 #endif | |
125 } | |
126 | |
127 vim_free(old_term); | |
128 | |
3087 | 129 #ifdef FEAT_AUTOCMD |
130 /* If the GUI started successfully, trigger the GUIEnter event, otherwise | |
131 * the GUIFailed event. */ | |
132 gui_mch_update(); | |
133 apply_autocmds(gui.in_use ? EVENT_GUIENTER : EVENT_GUIFAILED, | |
134 NULL, NULL, FALSE, curbuf); | |
135 #endif | |
136 --recursive; | |
137 } | |
138 | |
139 /* | |
140 * Set_termname() will call gui_init() to start the GUI. | |
141 * Set the "starting" flag, to indicate that the GUI will start. | |
142 * | |
143 * We don't want to open the GUI shell until after we've read .gvimrc, | |
144 * otherwise we don't know what font we will use, and hence we don't know | |
145 * what size the shell should be. So if there are errors in the .gvimrc | |
146 * file, they will have to go to the terminal: Set full_screen to FALSE. | |
147 * full_screen will be set to TRUE again by a successful termcapinit(). | |
148 */ | |
149 static void | |
150 gui_attempt_start() | |
151 { | |
152 static int recursive = 0; | |
153 | |
154 ++recursive; | |
155 gui.starting = TRUE; | |
156 | |
157 #ifdef FEAT_GUI_GTK | |
158 gui.event_time = GDK_CURRENT_TIME; | |
159 #endif | |
160 | |
161 termcapinit((char_u *)"builtin_gui"); | |
162 gui.starting = recursive - 1; | |
163 | |
574 | 164 #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11) |
7 | 165 if (gui.in_use) |
2609 | 166 { |
167 # ifdef FEAT_EVAL | |
168 Window x11_window; | |
169 Display *x11_display; | |
170 | |
171 if (gui_get_x11_windis(&x11_window, &x11_display) == OK) | |
172 set_vim_var_nr(VV_WINDOWID, (long)x11_window); | |
173 # endif | |
174 | |
7 | 175 /* Display error messages in a dialog now. */ |
176 display_errors(); | |
2609 | 177 } |
7 | 178 #endif |
3087 | 179 --recursive; |
180 } | |
181 | |
182 #ifdef MAY_FORK | |
183 | |
184 /* for waitpid() */ | |
185 # if defined(HAVE_SYS_WAIT_H) || defined(HAVE_UNION_WAIT) | |
186 # include <sys/wait.h> | |
187 # endif | |
188 | |
189 /* | |
190 * Create a new process, by forking. In the child, start the GUI, and in | |
191 * the parent, exit. | |
192 * | |
193 * If something goes wrong, this will return with gui.in_use still set | |
194 * to FALSE, in which case the caller should continue execution without | |
195 * the GUI. | |
196 * | |
197 * If the child fails to start the GUI, then the child will exit and the | |
198 * parent will return. If the child succeeds, then the parent will exit | |
199 * and the child will return. | |
200 */ | |
201 static void | |
202 gui_do_fork() | |
203 { | |
204 #ifdef __QNXNTO__ | |
205 procmgr_daemon(0, PROCMGR_DAEMON_KEEPUMASK | PROCMGR_DAEMON_NOCHDIR | | |
206 PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL); | |
207 gui_attempt_start(); | |
208 return; | |
209 #else | |
210 int pipefd[2]; /* pipe between parent and child */ | |
211 int pipe_error; | |
212 int status; | |
213 int exit_status; | |
214 pid_t pid = -1; | |
215 FILE *parent_file; | |
216 | |
217 /* Setup a pipe between the child and the parent, so that the parent | |
218 * knows when the child has done the setsid() call and is allowed to | |
219 * exit. */ | |
220 pipe_error = (pipe(pipefd) < 0); | |
221 pid = fork(); | |
222 if (pid < 0) /* Fork error */ | |
7 | 223 { |
3087 | 224 EMSG(_("E851: Failed to create a new process for the GUI")); |
225 return; | |
226 } | |
227 else if (pid > 0) /* Parent */ | |
228 { | |
229 /* Give the child some time to do the setsid(), otherwise the | |
230 * exit() may kill the child too (when starting gvim from inside a | |
231 * gvim). */ | |
232 if (!pipe_error) | |
7 | 233 { |
3087 | 234 /* The read returns when the child closes the pipe (or when |
235 * the child dies for some reason). */ | |
236 close(pipefd[1]); | |
237 status = gui_read_child_pipe(pipefd[0]); | |
238 if (status == GUI_CHILD_FAILED) | |
7 | 239 { |
3087 | 240 /* The child failed to start the GUI, so the caller must |
241 * continue. There may be more error information written | |
242 * to stderr by the child. */ | |
243 # ifdef __NeXT__ | |
244 wait4(pid, &exit_status, 0, (struct rusage *)0); | |
245 # else | |
246 waitpid(pid, &exit_status, 0); | |
247 # endif | |
248 EMSG(_("E852: The child process failed to start the GUI")); | |
249 return; | |
7 | 250 } |
3087 | 251 else if (status == GUI_CHILD_IO_ERROR) |
252 { | |
253 pipe_error = TRUE; | |
254 } | |
255 /* else GUI_CHILD_OK: parent exit */ | |
7 | 256 } |
257 | |
3087 | 258 if (pipe_error) |
259 ui_delay(300L, TRUE); | |
260 | |
261 /* When swapping screens we may need to go to the next line, e.g., | |
262 * after a hit-enter prompt and using ":gui". */ | |
263 if (newline_on_exit) | |
264 mch_errmsg("\r\n"); | |
265 | |
266 /* | |
267 * The parent must skip the normal exit() processing, the child | |
268 * will do it. For example, GTK messes up signals when exiting. | |
269 */ | |
270 _exit(0); | |
271 } | |
272 /* Child */ | |
273 | |
7 | 274 # if defined(HAVE_SETSID) || defined(HAVE_SETPGID) |
3087 | 275 /* |
276 * Change our process group. On some systems/shells a CTRL-C in the | |
277 * shell where Vim was started would otherwise kill gvim! | |
278 */ | |
7 | 279 # if defined(HAVE_SETSID) |
3087 | 280 (void)setsid(); |
7 | 281 # else |
3087 | 282 (void)setpgid(0, 0); |
7 | 283 # endif |
284 # endif | |
3087 | 285 if (!pipe_error) |
286 close(pipefd[0]); | |
7 | 287 |
288 # if defined(FEAT_GUI_GNOME) && defined(FEAT_SESSION) | |
3087 | 289 /* Tell the session manager our new PID */ |
290 gui_mch_forked(); | |
7 | 291 # endif |
3087 | 292 |
293 if (!pipe_error) | |
294 parent_file = fdopen(pipefd[1], "w"); | |
295 else | |
296 parent_file = NULL; | |
297 | |
298 /* Try to start the GUI */ | |
299 gui_attempt_start(); | |
300 | |
301 /* Notify the parent */ | |
302 if (parent_file != NULL) | |
303 { | |
304 fputs(gui.in_use ? "ok" : "fail", parent_file); | |
305 fclose(parent_file); | |
306 } | |
307 | |
308 /* If we failed to start the GUI, exit now. */ | |
309 if (!gui.in_use) | |
310 exit(1); | |
311 #endif | |
7 | 312 } |
313 | |
314 /* | |
3087 | 315 * Read from a pipe assumed to be connected to the child process (this |
316 * function is called from the parent). | |
317 * Return GUI_CHILD_OK if the child successfully started the GUI, | |
318 * GUY_CHILD_FAILED if the child failed, or GUI_CHILD_IO_ERROR if there was | |
319 * some other error. | |
320 * | |
321 * The file descriptor will be closed before the function returns. | |
322 */ | |
323 static int | |
324 gui_read_child_pipe(int fd) | |
325 { | |
326 size_t bytes_read; | |
327 FILE *file; | |
328 char buffer[10]; | |
329 | |
330 file = fdopen(fd, "r"); | |
331 if (!file) | |
332 return GUI_CHILD_IO_ERROR; | |
333 | |
334 bytes_read = fread(buffer, sizeof(char), sizeof(buffer)-1, file); | |
335 buffer[bytes_read] = '\0'; | |
336 fclose(file); | |
337 if (strcmp(buffer, "ok") == 0) | |
338 return GUI_CHILD_OK; | |
339 return GUI_CHILD_FAILED; | |
340 } | |
341 | |
342 #endif /* MAY_FORK */ | |
343 | |
344 /* | |
7 | 345 * Call this when vim starts up, whether or not the GUI is started |
346 */ | |
347 void | |
348 gui_prepare(argc, argv) | |
349 int *argc; | |
350 char **argv; | |
351 { | |
352 gui.in_use = FALSE; /* No GUI yet (maybe later) */ | |
353 gui.starting = FALSE; /* No GUI yet (maybe later) */ | |
354 gui_mch_prepare(argc, argv); | |
355 } | |
356 | |
357 /* | |
358 * Try initializing the GUI and check if it can be started. | |
359 * Used from main() to check early if "vim -g" can start the GUI. | |
360 * Used from gui_init() to prepare for starting the GUI. | |
361 * Returns FAIL or OK. | |
362 */ | |
363 int | |
364 gui_init_check() | |
365 { | |
366 static int result = MAYBE; | |
367 | |
368 if (result != MAYBE) | |
369 { | |
370 if (result == FAIL) | |
371 EMSG(_("E229: Cannot start the GUI")); | |
372 return result; | |
373 } | |
374 | |
375 gui.shell_created = FALSE; | |
376 gui.dying = FALSE; | |
377 gui.in_focus = TRUE; /* so the guicursor setting works */ | |
378 gui.dragged_sb = SBAR_NONE; | |
379 gui.dragged_wp = NULL; | |
380 gui.pointer_hidden = FALSE; | |
381 gui.col = 0; | |
382 gui.row = 0; | |
383 gui.num_cols = Columns; | |
384 gui.num_rows = Rows; | |
385 | |
386 gui.cursor_is_valid = FALSE; | |
387 gui.scroll_region_top = 0; | |
388 gui.scroll_region_bot = Rows - 1; | |
389 gui.scroll_region_left = 0; | |
390 gui.scroll_region_right = Columns - 1; | |
391 gui.highlight_mask = HL_NORMAL; | |
392 gui.char_width = 1; | |
393 gui.char_height = 1; | |
394 gui.char_ascent = 0; | |
395 gui.border_width = 0; | |
396 | |
397 gui.norm_font = NOFONT; | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
398 #ifndef FEAT_GUI_GTK |
7 | 399 gui.bold_font = NOFONT; |
400 gui.ital_font = NOFONT; | |
401 gui.boldital_font = NOFONT; | |
402 # ifdef FEAT_XFONTSET | |
403 gui.fontset = NOFONTSET; | |
404 # endif | |
405 #endif | |
406 | |
407 #ifdef FEAT_MENU | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
408 # ifndef FEAT_GUI_GTK |
7 | 409 # ifdef FONTSET_ALWAYS |
410 gui.menu_fontset = NOFONTSET; | |
411 # else | |
412 gui.menu_font = NOFONT; | |
413 # endif | |
414 # endif | |
415 gui.menu_is_active = TRUE; /* default: include menu */ | |
416 # ifndef FEAT_GUI_GTK | |
417 gui.menu_height = MENU_DEFAULT_HEIGHT; | |
418 gui.menu_width = 0; | |
419 # endif | |
420 #endif | |
421 #if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) | |
422 gui.toolbar_height = 0; | |
423 #endif | |
424 #if defined(FEAT_FOOTER) && defined(FEAT_GUI_MOTIF) | |
425 gui.footer_height = 0; | |
426 #endif | |
427 #ifdef FEAT_BEVAL_TIP | |
428 gui.tooltip_fontset = NOFONTSET; | |
429 #endif | |
430 | |
431 gui.scrollbar_width = gui.scrollbar_height = SB_DEFAULT_WIDTH; | |
432 gui.prev_wrap = -1; | |
433 | |
434 #ifdef ALWAYS_USE_GUI | |
435 result = OK; | |
436 #else | |
437 result = gui_mch_init_check(); | |
438 #endif | |
439 return result; | |
440 } | |
441 | |
442 /* | |
443 * This is the call which starts the GUI. | |
444 */ | |
445 void | |
446 gui_init() | |
447 { | |
448 win_T *wp; | |
449 static int recursive = 0; | |
450 | |
451 /* | |
452 * It's possible to use ":gui" in a .gvimrc file. The first halve of this | |
453 * function will then be executed at the first call, the rest by the | |
454 * recursive call. This allow the shell to be opened halfway reading a | |
455 * gvimrc file. | |
456 */ | |
457 if (!recursive) | |
458 { | |
459 ++recursive; | |
460 | |
461 clip_init(TRUE); | |
462 | |
463 /* If can't initialize, don't try doing the rest */ | |
464 if (gui_init_check() == FAIL) | |
465 { | |
466 --recursive; | |
467 clip_init(FALSE); | |
468 return; | |
469 } | |
470 | |
471 /* | |
147 | 472 * Reset 'paste'. It's useful in the terminal, but not in the GUI. It |
473 * breaks the Paste toolbar button. | |
474 */ | |
475 set_option_value((char_u *)"paste", 0L, NULL, 0); | |
476 | |
477 /* | |
7 | 478 * Set up system-wide default menus. |
479 */ | |
480 #if defined(SYS_MENU_FILE) && defined(FEAT_MENU) | |
481 if (vim_strchr(p_go, GO_NOSYSMENU) == NULL) | |
482 { | |
483 sys_menu = TRUE; | |
819 | 484 do_source((char_u *)SYS_MENU_FILE, FALSE, DOSO_NONE); |
7 | 485 sys_menu = FALSE; |
486 } | |
487 #endif | |
488 | |
489 /* | |
490 * Switch on the mouse by default, unless the user changed it already. | |
491 * This can then be changed in the .gvimrc. | |
492 */ | |
493 if (!option_was_set((char_u *)"mouse")) | |
494 set_string_option_direct((char_u *)"mouse", -1, | |
694 | 495 (char_u *)"a", OPT_FREE, SID_NONE); |
7 | 496 |
497 /* | |
498 * If -U option given, use only the initializations from that file and | |
499 * nothing else. Skip all initializations for "-U NONE" or "-u NORC". | |
500 */ | |
501 if (use_gvimrc != NULL) | |
502 { | |
503 if (STRCMP(use_gvimrc, "NONE") != 0 | |
504 && STRCMP(use_gvimrc, "NORC") != 0 | |
819 | 505 && do_source(use_gvimrc, FALSE, DOSO_NONE) != OK) |
7 | 506 EMSG2(_("E230: Cannot read from \"%s\""), use_gvimrc); |
507 } | |
508 else | |
509 { | |
510 /* | |
511 * Get system wide defaults for gvim, only when file name defined. | |
512 */ | |
513 #ifdef SYS_GVIMRC_FILE | |
819 | 514 do_source((char_u *)SYS_GVIMRC_FILE, FALSE, DOSO_NONE); |
7 | 515 #endif |
516 | |
517 /* | |
518 * Try to read GUI initialization commands from the following | |
519 * places: | |
520 * - environment variable GVIMINIT | |
521 * - the user gvimrc file (~/.gvimrc) | |
522 * - the second user gvimrc file ($VIM/.gvimrc for Dos) | |
523 * - the third user gvimrc file ($VIM/.gvimrc for Amiga) | |
524 * The first that exists is used, the rest is ignored. | |
525 */ | |
526 if (process_env((char_u *)"GVIMINIT", FALSE) == FAIL | |
819 | 527 && do_source((char_u *)USR_GVIMRC_FILE, TRUE, |
528 DOSO_GVIMRC) == FAIL | |
7 | 529 #ifdef USR_GVIMRC_FILE2 |
819 | 530 && do_source((char_u *)USR_GVIMRC_FILE2, TRUE, |
531 DOSO_GVIMRC) == FAIL | |
7 | 532 #endif |
533 ) | |
534 { | |
535 #ifdef USR_GVIMRC_FILE3 | |
819 | 536 (void)do_source((char_u *)USR_GVIMRC_FILE3, TRUE, DOSO_GVIMRC); |
7 | 537 #endif |
538 } | |
539 | |
540 /* | |
541 * Read initialization commands from ".gvimrc" in current | |
542 * directory. This is only done if the 'exrc' option is set. | |
543 * Because of security reasons we disallow shell and write | |
544 * commands now, except for unix if the file is owned by the user | |
545 * or 'secure' option has been reset in environment of global | |
546 * ".gvimrc". | |
547 * Only do this if GVIMRC_FILE is not the same as USR_GVIMRC_FILE, | |
548 * USR_GVIMRC_FILE2, USR_GVIMRC_FILE3 or SYS_GVIMRC_FILE. | |
549 */ | |
550 if (p_exrc) | |
551 { | |
552 #ifdef UNIX | |
553 { | |
554 struct stat s; | |
555 | |
556 /* if ".gvimrc" file is not owned by user, set 'secure' | |
557 * mode */ | |
558 if (mch_stat(GVIMRC_FILE, &s) || s.st_uid != getuid()) | |
559 secure = p_secure; | |
560 } | |
561 #else | |
562 secure = p_secure; | |
563 #endif | |
564 | |
565 if ( fullpathcmp((char_u *)USR_GVIMRC_FILE, | |
566 (char_u *)GVIMRC_FILE, FALSE) != FPC_SAME | |
567 #ifdef SYS_GVIMRC_FILE | |
568 && fullpathcmp((char_u *)SYS_GVIMRC_FILE, | |
569 (char_u *)GVIMRC_FILE, FALSE) != FPC_SAME | |
570 #endif | |
571 #ifdef USR_GVIMRC_FILE2 | |
572 && fullpathcmp((char_u *)USR_GVIMRC_FILE2, | |
573 (char_u *)GVIMRC_FILE, FALSE) != FPC_SAME | |
574 #endif | |
575 #ifdef USR_GVIMRC_FILE3 | |
576 && fullpathcmp((char_u *)USR_GVIMRC_FILE3, | |
577 (char_u *)GVIMRC_FILE, FALSE) != FPC_SAME | |
578 #endif | |
579 ) | |
819 | 580 do_source((char_u *)GVIMRC_FILE, TRUE, DOSO_GVIMRC); |
7 | 581 |
582 if (secure == 2) | |
583 need_wait_return = TRUE; | |
584 secure = 0; | |
585 } | |
586 } | |
587 | |
588 if (need_wait_return || msg_didany) | |
589 wait_return(TRUE); | |
590 | |
591 --recursive; | |
592 } | |
593 | |
594 /* If recursive call opened the shell, return here from the first call */ | |
595 if (gui.in_use) | |
596 return; | |
597 | |
598 /* | |
599 * Create the GUI shell. | |
600 */ | |
601 gui.in_use = TRUE; /* Must be set after menus have been set up */ | |
602 if (gui_mch_init() == FAIL) | |
603 goto error; | |
604 | |
605 /* Avoid a delay for an error message that was printed in the terminal | |
606 * where Vim was started. */ | |
607 emsg_on_display = FALSE; | |
608 msg_scrolled = 0; | |
446 | 609 clear_sb_text(); |
7 | 610 need_wait_return = FALSE; |
611 msg_didany = FALSE; | |
612 | |
613 /* | |
614 * Check validity of any generic resources that may have been loaded. | |
615 */ | |
616 if (gui.border_width < 0) | |
617 gui.border_width = 0; | |
618 | |
619 /* | |
620 * Set up the fonts. First use a font specified with "-fn" or "-font". | |
621 */ | |
622 if (font_argument != NULL) | |
623 set_option_value((char_u *)"gfn", 0L, (char_u *)font_argument, 0); | |
624 if ( | |
625 #ifdef FEAT_XFONTSET | |
626 (*p_guifontset == NUL | |
627 || gui_init_font(p_guifontset, TRUE) == FAIL) && | |
628 #endif | |
629 gui_init_font(*p_guifont == NUL ? hl_get_font_name() | |
630 : p_guifont, FALSE) == FAIL) | |
631 { | |
632 EMSG(_("E665: Cannot start GUI, no valid font found")); | |
633 goto error2; | |
634 } | |
635 #ifdef FEAT_MBYTE | |
636 if (gui_get_wide_font() == FAIL) | |
637 EMSG(_("E231: 'guifontwide' invalid")); | |
638 #endif | |
639 | |
640 gui.num_cols = Columns; | |
641 gui.num_rows = Rows; | |
642 gui_reset_scroll_region(); | |
643 | |
644 /* Create initial scrollbars */ | |
645 FOR_ALL_WINDOWS(wp) | |
646 { | |
647 gui_create_scrollbar(&wp->w_scrollbars[SBAR_LEFT], SBAR_LEFT, wp); | |
648 gui_create_scrollbar(&wp->w_scrollbars[SBAR_RIGHT], SBAR_RIGHT, wp); | |
649 } | |
650 gui_create_scrollbar(&gui.bottom_sbar, SBAR_BOTTOM, NULL); | |
651 | |
652 #ifdef FEAT_MENU | |
653 gui_create_initial_menus(root_menu); | |
654 #endif | |
655 #ifdef FEAT_SUN_WORKSHOP | |
656 if (usingSunWorkShop) | |
657 workshop_init(); | |
658 #endif | |
659 #ifdef FEAT_SIGN_ICONS | |
660 sign_gui_started(); | |
661 #endif | |
662 | |
663 /* Configure the desired menu and scrollbars */ | |
664 gui_init_which_components(NULL); | |
665 | |
666 /* All components of the GUI have been created now */ | |
667 gui.shell_created = TRUE; | |
668 | |
669 #ifndef FEAT_GUI_GTK | |
670 /* Set the shell size, adjusted for the screen size. For GTK this only | |
671 * works after the shell has been opened, thus it is further down. */ | |
811 | 672 gui_set_shellsize(FALSE, TRUE, RESIZE_BOTH); |
7 | 673 #endif |
674 #if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU) | |
675 /* Need to set the size of the menubar after all the menus have been | |
676 * created. */ | |
677 gui_mch_compute_menu_height((Widget)0); | |
678 #endif | |
679 | |
680 /* | |
681 * Actually open the GUI shell. | |
682 */ | |
683 if (gui_mch_open() != FAIL) | |
684 { | |
685 #ifdef FEAT_TITLE | |
686 maketitle(); | |
687 resettitle(); | |
688 #endif | |
689 init_gui_options(); | |
690 #ifdef FEAT_ARABIC | |
691 /* Our GUI can't do bidi. */ | |
692 p_tbidi = FALSE; | |
693 #endif | |
574 | 694 #if defined(FEAT_GUI_GTK) |
7 | 695 /* Give GTK+ a chance to put all widget's into place. */ |
696 gui_mch_update(); | |
827 | 697 |
698 # ifdef FEAT_MENU | |
699 /* If there is no 'm' in 'guioptions' we need to remove the menu now. | |
700 * It was still there to make F10 work. */ | |
701 if (vim_strchr(p_go, GO_MENUS) == NULL) | |
702 { | |
703 --gui.starting; | |
704 gui_mch_enable_menu(FALSE); | |
705 ++gui.starting; | |
706 gui_mch_update(); | |
707 } | |
708 # endif | |
709 | |
7 | 710 /* Now make sure the shell fits on the screen. */ |
811 | 711 gui_set_shellsize(FALSE, TRUE, RESIZE_BOTH); |
7 | 712 #endif |
261 | 713 /* When 'lines' was set while starting up the topframe may have to be |
714 * resized. */ | |
715 win_new_shellsize(); | |
187 | 716 |
717 #ifdef FEAT_BEVAL | |
718 /* Always create the Balloon Evaluation area, but disable it when | |
719 * 'ballooneval' is off */ | |
720 # ifdef FEAT_GUI_GTK | |
721 balloonEval = gui_mch_create_beval_area(gui.drawarea, NULL, | |
722 &general_beval_cb, NULL); | |
723 # else | |
216 | 724 # if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) |
187 | 725 { |
726 extern Widget textArea; | |
727 balloonEval = gui_mch_create_beval_area(textArea, NULL, | |
216 | 728 &general_beval_cb, NULL); |
187 | 729 } |
730 # else | |
731 # ifdef FEAT_GUI_W32 | |
732 balloonEval = gui_mch_create_beval_area(NULL, NULL, | |
733 &general_beval_cb, NULL); | |
734 # endif | |
735 # endif | |
736 # endif | |
737 if (!p_beval) | |
738 gui_mch_disable_beval_area(balloonEval); | |
739 #endif | |
740 | |
7 | 741 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) |
742 if (!im_xim_isvalid_imactivate()) | |
743 EMSG(_("E599: Value of 'imactivatekey' is invalid")); | |
744 #endif | |
37 | 745 /* When 'cmdheight' was set during startup it may not have taken |
746 * effect yet. */ | |
747 if (p_ch != 1L) | |
824 | 748 command_height(); |
7 | 749 |
750 return; | |
751 } | |
752 | |
753 error2: | |
754 #ifdef FEAT_GUI_X11 | |
755 /* undo gui_mch_init() */ | |
756 gui_mch_uninit(); | |
757 #endif | |
758 | |
759 error: | |
760 gui.in_use = FALSE; | |
761 clip_init(FALSE); | |
762 } | |
763 | |
764 | |
765 void | |
766 gui_exit(rc) | |
767 int rc; | |
768 { | |
769 #ifndef __BEOS__ | |
770 /* don't free the fonts, it leads to a BUS error | |
771 * richard@whitequeen.com Jul 99 */ | |
772 free_highlight_fonts(); | |
773 #endif | |
774 gui.in_use = FALSE; | |
775 gui_mch_exit(rc); | |
776 } | |
777 | |
574 | 778 #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_MSWIN) \ |
7 | 779 || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(PROTO) |
1002 | 780 # define NEED_GUI_UPDATE_SCREEN 1 |
7 | 781 /* |
782 * Called when the GUI shell is closed by the user. If there are no changed | |
783 * files Vim exits, otherwise there will be a dialog to ask the user what to | |
784 * do. | |
785 * When this function returns, Vim should NOT exit! | |
786 */ | |
787 void | |
788 gui_shell_closed() | |
789 { | |
790 cmdmod_T save_cmdmod; | |
791 | |
792 save_cmdmod = cmdmod; | |
793 | |
794 /* Only exit when there are no changed files */ | |
795 exiting = TRUE; | |
796 # ifdef FEAT_BROWSE | |
797 cmdmod.browse = TRUE; | |
798 # endif | |
799 # if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) | |
800 cmdmod.confirm = TRUE; | |
801 # endif | |
802 /* If there are changed buffers, present the user with a dialog if | |
803 * possible, otherwise give an error message. */ | |
804 if (!check_changed_any(FALSE)) | |
805 getout(0); | |
806 | |
807 exiting = FALSE; | |
808 cmdmod = save_cmdmod; | |
1002 | 809 gui_update_screen(); /* redraw, window may show changed buffer */ |
7 | 810 } |
811 #endif | |
812 | |
813 /* | |
814 * Set the font. "font_list" is a a comma separated list of font names. The | |
815 * first font name that works is used. If none is found, use the default | |
816 * font. | |
817 * If "fontset" is TRUE, the "font_list" is used as one name for the fontset. | |
818 * Return OK when able to set the font. When it failed FAIL is returned and | |
819 * the fonts are unchanged. | |
820 */ | |
821 int | |
822 gui_init_font(font_list, fontset) | |
823 char_u *font_list; | |
1884 | 824 int fontset UNUSED; |
7 | 825 { |
826 #define FONTLEN 320 | |
827 char_u font_name[FONTLEN]; | |
828 int font_list_empty = FALSE; | |
829 int ret = FAIL; | |
830 | |
831 if (!gui.in_use) | |
832 return FAIL; | |
833 | |
834 font_name[0] = NUL; | |
835 if (*font_list == NUL) | |
836 font_list_empty = TRUE; | |
837 else | |
838 { | |
839 #ifdef FEAT_XFONTSET | |
840 /* When using a fontset, the whole list of fonts is one name. */ | |
841 if (fontset) | |
842 ret = gui_mch_init_font(font_list, TRUE); | |
843 else | |
844 #endif | |
845 while (*font_list != NUL) | |
846 { | |
847 /* Isolate one comma separated font name. */ | |
848 (void)copy_option_part(&font_list, font_name, FONTLEN, ","); | |
849 | |
850 /* Careful!!! The Win32 version of gui_mch_init_font(), when | |
851 * called with "*" will change p_guifont to the selected font | |
852 * name, which frees the old value. This makes font_list | |
853 * invalid. Thus when OK is returned here, font_list must no | |
854 * longer be used! */ | |
855 if (gui_mch_init_font(font_name, FALSE) == OK) | |
856 { | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
857 #if defined(FEAT_MBYTE) && !defined(FEAT_GUI_GTK) |
7 | 858 /* If it's a Unicode font, try setting 'guifontwide' to a |
859 * similar double-width font. */ | |
860 if ((p_guifontwide == NULL || *p_guifontwide == NUL) | |
861 && strstr((char *)font_name, "10646") != NULL) | |
862 set_guifontwide(font_name); | |
863 #endif | |
864 ret = OK; | |
865 break; | |
866 } | |
867 } | |
868 } | |
869 | |
870 if (ret != OK | |
871 && STRCMP(font_list, "*") != 0 | |
872 && (font_list_empty || gui.norm_font == NOFONT)) | |
873 { | |
874 /* | |
875 * Couldn't load any font in 'font_list', keep the current font if | |
876 * there is one. If 'font_list' is empty, or if there is no current | |
877 * font, tell gui_mch_init_font() to try to find a font we can load. | |
878 */ | |
879 ret = gui_mch_init_font(NULL, FALSE); | |
880 } | |
881 | |
882 if (ret == OK) | |
883 { | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
884 #ifndef FEAT_GUI_GTK |
7 | 885 /* Set normal font as current font */ |
886 # ifdef FEAT_XFONTSET | |
887 if (gui.fontset != NOFONTSET) | |
888 gui_mch_set_fontset(gui.fontset); | |
889 else | |
890 # endif | |
891 gui_mch_set_font(gui.norm_font); | |
892 #endif | |
893 gui_set_shellsize(FALSE, | |
894 #ifdef MSWIN | |
895 TRUE | |
896 #else | |
897 FALSE | |
898 #endif | |
811 | 899 , RESIZE_BOTH); |
7 | 900 } |
901 | |
902 return ret; | |
903 } | |
904 | |
905 #if defined(FEAT_MBYTE) || defined(PROTO) | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
906 # ifndef FEAT_GUI_GTK |
7 | 907 /* |
908 * Try setting 'guifontwide' to a font twice as wide as "name". | |
909 */ | |
910 static void | |
911 set_guifontwide(name) | |
912 char_u *name; | |
913 { | |
914 int i = 0; | |
915 char_u wide_name[FONTLEN + 10]; /* room for 2 * width and '*' */ | |
916 char_u *wp = NULL; | |
917 char_u *p; | |
918 GuiFont font; | |
919 | |
920 wp = wide_name; | |
921 for (p = name; *p != NUL; ++p) | |
922 { | |
923 *wp++ = *p; | |
924 if (*p == '-') | |
925 { | |
926 ++i; | |
927 if (i == 6) /* font type: change "--" to "-*-" */ | |
928 { | |
929 if (p[1] == '-') | |
930 *wp++ = '*'; | |
931 } | |
932 else if (i == 12) /* found the width */ | |
933 { | |
934 ++p; | |
935 i = getdigits(&p); | |
936 if (i != 0) | |
937 { | |
938 /* Double the width specification. */ | |
939 sprintf((char *)wp, "%d%s", i * 2, p); | |
940 font = gui_mch_get_font(wide_name, FALSE); | |
941 if (font != NOFONT) | |
942 { | |
37 | 943 gui_mch_free_font(gui.wide_font); |
7 | 944 gui.wide_font = font; |
945 set_string_option_direct((char_u *)"gfw", -1, | |
694 | 946 wide_name, OPT_FREE, 0); |
7 | 947 } |
948 } | |
949 break; | |
950 } | |
951 } | |
952 } | |
953 } | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
954 # endif /* !FEAT_GUI_GTK */ |
7 | 955 |
956 /* | |
957 * Get the font for 'guifontwide'. | |
958 * Return FAIL for an invalid font name. | |
959 */ | |
960 int | |
961 gui_get_wide_font() | |
962 { | |
963 GuiFont font = NOFONT; | |
964 char_u font_name[FONTLEN]; | |
965 char_u *p; | |
966 | |
967 if (!gui.in_use) /* Can't allocate font yet, assume it's OK. */ | |
968 return OK; /* Will give an error message later. */ | |
969 | |
970 if (p_guifontwide != NULL && *p_guifontwide != NUL) | |
971 { | |
972 for (p = p_guifontwide; *p != NUL; ) | |
973 { | |
974 /* Isolate one comma separated font name. */ | |
975 (void)copy_option_part(&p, font_name, FONTLEN, ","); | |
976 font = gui_mch_get_font(font_name, FALSE); | |
977 if (font != NOFONT) | |
978 break; | |
979 } | |
980 if (font == NOFONT) | |
981 return FAIL; | |
982 } | |
983 | |
984 gui_mch_free_font(gui.wide_font); | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
985 #ifdef FEAT_GUI_GTK |
7 | 986 /* Avoid unnecessary overhead if 'guifontwide' is equal to 'guifont'. */ |
987 if (font != NOFONT && gui.norm_font != NOFONT | |
988 && pango_font_description_equal(font, gui.norm_font)) | |
989 { | |
990 gui.wide_font = NOFONT; | |
991 gui_mch_free_font(font); | |
992 } | |
993 else | |
994 #endif | |
995 gui.wide_font = font; | |
996 return OK; | |
997 } | |
998 #endif | |
999 | |
1000 void | |
1001 gui_set_cursor(row, col) | |
1002 int row; | |
1003 int col; | |
1004 { | |
1005 gui.row = row; | |
1006 gui.col = col; | |
1007 } | |
1008 | |
1009 /* | |
1010 * gui_check_pos - check if the cursor is on the screen. | |
1011 */ | |
1012 static void | |
1013 gui_check_pos() | |
1014 { | |
1015 if (gui.row >= screen_Rows) | |
1016 gui.row = screen_Rows - 1; | |
1017 if (gui.col >= screen_Columns) | |
1018 gui.col = screen_Columns - 1; | |
1019 if (gui.cursor_row >= screen_Rows || gui.cursor_col >= screen_Columns) | |
1020 gui.cursor_is_valid = FALSE; | |
1021 } | |
1022 | |
1023 /* | |
1024 * Redraw the cursor if necessary or when forced. | |
1025 * Careful: The contents of ScreenLines[] must match what is on the screen, | |
1026 * otherwise this goes wrong. May need to call out_flush() first. | |
1027 */ | |
1028 void | |
1029 gui_update_cursor(force, clear_selection) | |
1030 int force; /* when TRUE, update even when not moved */ | |
1031 int clear_selection;/* clear selection under cursor */ | |
1032 { | |
1033 int cur_width = 0; | |
1034 int cur_height = 0; | |
1035 int old_hl_mask; | |
1036 int idx; | |
1037 int id; | |
1038 guicolor_T cfg, cbg, cc; /* cursor fore-/background color */ | |
1039 int cattr; /* cursor attributes */ | |
1040 int attr; | |
1041 attrentry_T *aep = NULL; | |
1042 | |
1695 | 1043 /* Don't update the cursor when halfway busy scrolling or the screen size |
1044 * doesn't match 'columns' and 'lines. ScreenLines[] isn't valid then. */ | |
1045 if (!can_update_cursor || screen_Columns != gui.num_cols | |
1046 || screen_Rows != gui.num_rows) | |
7 | 1047 return; |
1048 | |
1049 gui_check_pos(); | |
1050 if (!gui.cursor_is_valid || force | |
1051 || gui.row != gui.cursor_row || gui.col != gui.cursor_col) | |
1052 { | |
1053 gui_undraw_cursor(); | |
1054 if (gui.row < 0) | |
1055 return; | |
1056 #ifdef USE_IM_CONTROL | |
1057 if (gui.row != gui.cursor_row || gui.col != gui.cursor_col) | |
1058 im_set_position(gui.row, gui.col); | |
1059 #endif | |
1060 gui.cursor_row = gui.row; | |
1061 gui.cursor_col = gui.col; | |
1062 | |
1063 /* Only write to the screen after ScreenLines[] has been initialized */ | |
1064 if (!screen_cleared || ScreenLines == NULL) | |
1065 return; | |
1066 | |
1067 /* Clear the selection if we are about to write over it */ | |
1068 if (clear_selection) | |
1069 clip_may_clear_selection(gui.row, gui.row); | |
1070 /* Check that the cursor is inside the shell (resizing may have made | |
1071 * it invalid) */ | |
1072 if (gui.row >= screen_Rows || gui.col >= screen_Columns) | |
1073 return; | |
1074 | |
1075 gui.cursor_is_valid = TRUE; | |
1076 | |
1077 /* | |
1078 * How the cursor is drawn depends on the current mode. | |
1079 */ | |
1080 idx = get_shape_idx(FALSE); | |
1081 if (State & LANGMAP) | |
1082 id = shape_table[idx].id_lm; | |
1083 else | |
1084 id = shape_table[idx].id; | |
1085 | |
1086 /* get the colors and attributes for the cursor. Default is inverted */ | |
1087 cfg = INVALCOLOR; | |
1088 cbg = INVALCOLOR; | |
1089 cattr = HL_INVERSE; | |
1090 gui_mch_set_blinking(shape_table[idx].blinkwait, | |
1091 shape_table[idx].blinkon, | |
1092 shape_table[idx].blinkoff); | |
1093 if (id > 0) | |
1094 { | |
1095 cattr = syn_id2colors(id, &cfg, &cbg); | |
1096 #if defined(USE_IM_CONTROL) || defined(FEAT_HANGULIN) | |
1097 { | |
1098 static int iid; | |
1099 guicolor_T fg, bg; | |
1100 | |
1668 | 1101 if ( |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
1102 # if defined(FEAT_GUI_GTK) && !defined(FEAT_HANGULIN) |
1668 | 1103 preedit_get_status() |
1104 # else | |
1105 im_get_status() | |
1106 # endif | |
1107 ) | |
7 | 1108 { |
1109 iid = syn_name2id((char_u *)"CursorIM"); | |
1110 if (iid > 0) | |
1111 { | |
1112 syn_id2colors(iid, &fg, &bg); | |
1113 if (bg != INVALCOLOR) | |
1114 cbg = bg; | |
1115 if (fg != INVALCOLOR) | |
1116 cfg = fg; | |
1117 } | |
1118 } | |
1119 } | |
1120 #endif | |
1121 } | |
1122 | |
1123 /* | |
1124 * Get the attributes for the character under the cursor. | |
1125 * When no cursor color was given, use the character color. | |
1126 */ | |
1127 attr = ScreenAttrs[LineOffset[gui.row] + gui.col]; | |
1128 if (attr > HL_ALL) | |
1129 aep = syn_gui_attr2entry(attr); | |
1130 if (aep != NULL) | |
1131 { | |
1132 attr = aep->ae_attr; | |
1133 if (cfg == INVALCOLOR) | |
1134 cfg = ((attr & HL_INVERSE) ? aep->ae_u.gui.bg_color | |
1135 : aep->ae_u.gui.fg_color); | |
1136 if (cbg == INVALCOLOR) | |
1137 cbg = ((attr & HL_INVERSE) ? aep->ae_u.gui.fg_color | |
1138 : aep->ae_u.gui.bg_color); | |
1139 } | |
1140 if (cfg == INVALCOLOR) | |
1141 cfg = (attr & HL_INVERSE) ? gui.back_pixel : gui.norm_pixel; | |
1142 if (cbg == INVALCOLOR) | |
1143 cbg = (attr & HL_INVERSE) ? gui.norm_pixel : gui.back_pixel; | |
1144 | |
1145 #ifdef FEAT_XIM | |
1146 if (aep != NULL) | |
1147 { | |
1148 xim_bg_color = ((attr & HL_INVERSE) ? aep->ae_u.gui.fg_color | |
1149 : aep->ae_u.gui.bg_color); | |
1150 xim_fg_color = ((attr & HL_INVERSE) ? aep->ae_u.gui.bg_color | |
1151 : aep->ae_u.gui.fg_color); | |
1152 if (xim_bg_color == INVALCOLOR) | |
1153 xim_bg_color = (attr & HL_INVERSE) ? gui.norm_pixel | |
1154 : gui.back_pixel; | |
1155 if (xim_fg_color == INVALCOLOR) | |
1156 xim_fg_color = (attr & HL_INVERSE) ? gui.back_pixel | |
1157 : gui.norm_pixel; | |
1158 } | |
1159 else | |
1160 { | |
1161 xim_bg_color = (attr & HL_INVERSE) ? gui.norm_pixel | |
1162 : gui.back_pixel; | |
1163 xim_fg_color = (attr & HL_INVERSE) ? gui.back_pixel | |
1164 : gui.norm_pixel; | |
1165 } | |
1166 #endif | |
1167 | |
1168 attr &= ~HL_INVERSE; | |
1169 if (cattr & HL_INVERSE) | |
1170 { | |
1171 cc = cbg; | |
1172 cbg = cfg; | |
1173 cfg = cc; | |
1174 } | |
1175 cattr &= ~HL_INVERSE; | |
1176 | |
1177 /* | |
1178 * When we don't have window focus, draw a hollow cursor. | |
1179 */ | |
1180 if (!gui.in_focus) | |
1181 { | |
1182 gui_mch_draw_hollow_cursor(cbg); | |
1183 return; | |
1184 } | |
1185 | |
1186 old_hl_mask = gui.highlight_mask; | |
1187 if (shape_table[idx].shape == SHAPE_BLOCK | |
1188 #ifdef FEAT_HANGULIN | |
1189 || composing_hangul | |
1190 #endif | |
1191 ) | |
1192 { | |
1193 /* | |
1194 * Draw the text character with the cursor colors. Use the | |
1195 * character attributes plus the cursor attributes. | |
1196 */ | |
1197 gui.highlight_mask = (cattr | attr); | |
1198 #ifdef FEAT_HANGULIN | |
1199 if (composing_hangul) | |
1200 (void)gui_outstr_nowrap(composing_hangul_buffer, 2, | |
1201 GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, cfg, cbg, 0); | |
1202 else | |
1203 #endif | |
1204 (void)gui_screenchar(LineOffset[gui.row] + gui.col, | |
1205 GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, cfg, cbg, 0); | |
1206 } | |
1207 else | |
1208 { | |
1209 #if defined(FEAT_MBYTE) && defined(FEAT_RIGHTLEFT) | |
1210 int col_off = FALSE; | |
1211 #endif | |
1212 /* | |
1213 * First draw the partial cursor, then overwrite with the text | |
1214 * character, using a transparent background. | |
1215 */ | |
1216 if (shape_table[idx].shape == SHAPE_VER) | |
1217 { | |
1218 cur_height = gui.char_height; | |
1219 cur_width = (gui.char_width * shape_table[idx].percentage | |
1220 + 99) / 100; | |
1221 } | |
1222 else | |
1223 { | |
1224 cur_height = (gui.char_height * shape_table[idx].percentage | |
1225 + 99) / 100; | |
1226 cur_width = gui.char_width; | |
1227 } | |
1228 #ifdef FEAT_MBYTE | |
1378 | 1229 if (has_mbyte && (*mb_off2cells)(LineOffset[gui.row] + gui.col, |
1230 LineOffset[gui.row] + screen_Columns) > 1) | |
7 | 1231 { |
1232 /* Double wide character. */ | |
1233 if (shape_table[idx].shape != SHAPE_VER) | |
1234 cur_width += gui.char_width; | |
1235 # ifdef FEAT_RIGHTLEFT | |
1236 if (CURSOR_BAR_RIGHT) | |
1237 { | |
1238 /* gui.col points to the left halve of the character but | |
1239 * the vertical line needs to be on the right halve. | |
1240 * A double-wide horizontal line is also drawn from the | |
1241 * right halve in gui_mch_draw_part_cursor(). */ | |
1242 col_off = TRUE; | |
1243 ++gui.col; | |
1244 } | |
1245 # endif | |
1246 } | |
1247 #endif | |
1248 gui_mch_draw_part_cursor(cur_width, cur_height, cbg); | |
1249 #if defined(FEAT_MBYTE) && defined(FEAT_RIGHTLEFT) | |
1250 if (col_off) | |
1251 --gui.col; | |
1252 #endif | |
1253 | |
1254 #ifndef FEAT_GUI_MSWIN /* doesn't seem to work for MSWindows */ | |
1255 gui.highlight_mask = ScreenAttrs[LineOffset[gui.row] + gui.col]; | |
1256 (void)gui_screenchar(LineOffset[gui.row] + gui.col, | |
1257 GUI_MON_TRS_CURSOR | GUI_MON_NOCLEAR, | |
1258 (guicolor_T)0, (guicolor_T)0, 0); | |
1259 #endif | |
1260 } | |
1261 gui.highlight_mask = old_hl_mask; | |
1262 } | |
1263 } | |
1264 | |
1265 #if defined(FEAT_MENU) || defined(PROTO) | |
1266 void | |
1267 gui_position_menu() | |
1268 { | |
574 | 1269 # if !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MOTIF) |
7 | 1270 if (gui.menu_is_active && gui.in_use) |
1271 gui_mch_set_menu_pos(0, 0, gui.menu_width, gui.menu_height); | |
1272 # endif | |
1273 } | |
1274 #endif | |
1275 | |
1276 /* | |
1277 * Position the various GUI components (text area, menu). The vertical | |
1278 * scrollbars are NOT handled here. See gui_update_scrollbars(). | |
1279 */ | |
1280 static void | |
1281 gui_position_components(total_width) | |
1884 | 1282 int total_width UNUSED; |
7 | 1283 { |
1284 int text_area_x; | |
1285 int text_area_y; | |
1286 int text_area_width; | |
1287 int text_area_height; | |
1288 | |
1289 /* avoid that moving components around generates events */ | |
1290 ++hold_gui_events; | |
1291 | |
1292 text_area_x = 0; | |
1293 if (gui.which_scrollbars[SBAR_LEFT]) | |
1294 text_area_x += gui.scrollbar_width; | |
1295 | |
1296 text_area_y = 0; | |
1297 #if defined(FEAT_MENU) && !(defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON)) | |
1298 gui.menu_width = total_width; | |
1299 if (gui.menu_is_active) | |
1300 text_area_y += gui.menu_height; | |
1301 #endif | |
1302 #if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_MSWIN) | |
1303 if (vim_strchr(p_go, GO_TOOLBAR) != NULL) | |
1304 text_area_y = TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT; | |
1305 #endif | |
1306 | |
819 | 1307 # if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \ |
1378 | 1308 || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_MAC)) |
810 | 1309 if (gui_has_tabline()) |
843 | 1310 text_area_y += gui.tabline_height; |
810 | 1311 #endif |
1312 | |
7 | 1313 #if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) |
1314 if (vim_strchr(p_go, GO_TOOLBAR) != NULL) | |
1315 { | |
1316 # ifdef FEAT_GUI_ATHENA | |
1317 gui_mch_set_toolbar_pos(0, text_area_y, | |
1318 gui.menu_width, gui.toolbar_height); | |
1319 # endif | |
1320 text_area_y += gui.toolbar_height; | |
1321 } | |
1322 #endif | |
1323 | |
1324 text_area_width = gui.num_cols * gui.char_width + gui.border_offset * 2; | |
1325 text_area_height = gui.num_rows * gui.char_height + gui.border_offset * 2; | |
1326 | |
1327 gui_mch_set_text_area_pos(text_area_x, | |
1328 text_area_y, | |
1329 text_area_width, | |
1330 text_area_height | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
1331 #if defined(FEAT_XIM) && !defined(FEAT_GUI_GTK) |
7 | 1332 + xim_get_status_area_height() |
1333 #endif | |
1334 ); | |
1335 #ifdef FEAT_MENU | |
1336 gui_position_menu(); | |
1337 #endif | |
1338 if (gui.which_scrollbars[SBAR_BOTTOM]) | |
1339 gui_mch_set_scrollbar_pos(&gui.bottom_sbar, | |
1340 text_area_x, | |
1341 text_area_y + text_area_height, | |
1342 text_area_width, | |
1343 gui.scrollbar_height); | |
1344 gui.left_sbar_x = 0; | |
1345 gui.right_sbar_x = text_area_x + text_area_width; | |
1346 | |
1347 --hold_gui_events; | |
1348 } | |
1349 | |
444 | 1350 /* |
1351 * Get the width of the widgets and decorations to the side of the text area. | |
1352 */ | |
7 | 1353 int |
1354 gui_get_base_width() | |
1355 { | |
1356 int base_width; | |
1357 | |
1358 base_width = 2 * gui.border_offset; | |
1359 if (gui.which_scrollbars[SBAR_LEFT]) | |
1360 base_width += gui.scrollbar_width; | |
1361 if (gui.which_scrollbars[SBAR_RIGHT]) | |
1362 base_width += gui.scrollbar_width; | |
1363 return base_width; | |
1364 } | |
1365 | |
444 | 1366 /* |
1367 * Get the height of the widgets and decorations above and below the text area. | |
1368 */ | |
7 | 1369 int |
1370 gui_get_base_height() | |
1371 { | |
1372 int base_height; | |
1373 | |
1374 base_height = 2 * gui.border_offset; | |
1375 if (gui.which_scrollbars[SBAR_BOTTOM]) | |
1376 base_height += gui.scrollbar_height; | |
1377 #ifdef FEAT_GUI_GTK | |
1378 /* We can't take the sizes properly into account until anything is | |
1379 * realized. Therefore we recalculate all the values here just before | |
1380 * setting the size. (--mdcki) */ | |
1381 #else | |
1382 # ifdef FEAT_MENU | |
1383 if (gui.menu_is_active) | |
1384 base_height += gui.menu_height; | |
1385 # endif | |
1386 # ifdef FEAT_TOOLBAR | |
1387 if (vim_strchr(p_go, GO_TOOLBAR) != NULL) | |
1388 # if defined(FEAT_GUI_MSWIN) && defined(FEAT_TOOLBAR) | |
1389 base_height += (TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT); | |
1390 # else | |
1391 base_height += gui.toolbar_height; | |
1392 # endif | |
1393 # endif | |
819 | 1394 # if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \ |
1395 || defined(FEAT_GUI_MOTIF)) | |
810 | 1396 if (gui_has_tabline()) |
843 | 1397 base_height += gui.tabline_height; |
810 | 1398 # endif |
7 | 1399 # ifdef FEAT_FOOTER |
1400 if (vim_strchr(p_go, GO_FOOTER) != NULL) | |
1401 base_height += gui.footer_height; | |
1402 # endif | |
1403 # if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU) | |
1404 base_height += gui_mch_text_area_extra_height(); | |
1405 # endif | |
1406 #endif | |
1407 return base_height; | |
1408 } | |
1409 | |
1410 /* | |
1411 * Should be called after the GUI shell has been resized. Its arguments are | |
1412 * the new width and height of the shell in pixels. | |
1413 */ | |
1414 void | |
1415 gui_resize_shell(pixel_width, pixel_height) | |
1416 int pixel_width; | |
1417 int pixel_height; | |
1418 { | |
1419 static int busy = FALSE; | |
1420 | |
1421 if (!gui.shell_created) /* ignore when still initializing */ | |
1422 return; | |
1423 | |
1424 /* | |
1425 * Can't resize the screen while it is being redrawn. Remember the new | |
1426 * size and handle it later. | |
1427 */ | |
1428 if (updating_screen || busy) | |
1429 { | |
1430 new_pixel_width = pixel_width; | |
1431 new_pixel_height = pixel_height; | |
1432 return; | |
1433 } | |
1434 | |
1435 again: | |
1436 busy = TRUE; | |
1437 | |
1438 /* Flush pending output before redrawing */ | |
1439 out_flush(); | |
1440 | |
1441 gui.num_cols = (pixel_width - gui_get_base_width()) / gui.char_width; | |
1529 | 1442 gui.num_rows = (pixel_height - gui_get_base_height()) / gui.char_height; |
7 | 1443 |
1444 gui_position_components(pixel_width); | |
1445 | |
1446 gui_reset_scroll_region(); | |
1447 /* | |
1448 * At the "more" and ":confirm" prompt there is no redraw, put the cursor | |
1449 * at the last line here (why does it have to be one row too low?). | |
1450 */ | |
1451 if (State == ASKMORE || State == CONFIRM) | |
1452 gui.row = gui.num_rows; | |
1453 | |
1454 /* Only comparing Rows and Columns may be sufficient, but let's stay on | |
1455 * the safe side. */ | |
1456 if (gui.num_rows != screen_Rows || gui.num_cols != screen_Columns | |
1457 || gui.num_rows != Rows || gui.num_cols != Columns) | |
1458 shell_resized(); | |
1459 | |
1460 gui_update_scrollbars(TRUE); | |
1461 gui_update_cursor(FALSE, TRUE); | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
1462 #if defined(FEAT_XIM) && !defined(FEAT_GUI_GTK) |
7 | 1463 xim_set_status_area(); |
1464 #endif | |
1465 | |
1466 busy = FALSE; | |
669 | 1467 |
7 | 1468 /* |
1469 * We could have been called again while redrawing the screen. | |
1470 * Need to do it all again with the latest size then. | |
1471 */ | |
1472 if (new_pixel_height) | |
1473 { | |
1474 pixel_width = new_pixel_width; | |
1475 pixel_height = new_pixel_height; | |
1476 new_pixel_width = 0; | |
1477 new_pixel_height = 0; | |
1478 goto again; | |
1479 } | |
1480 } | |
1481 | |
1482 /* | |
1483 * Check if gui_resize_shell() must be called. | |
1484 */ | |
1485 void | |
1486 gui_may_resize_shell() | |
1487 { | |
1488 int h, w; | |
1489 | |
1490 if (new_pixel_height) | |
1491 { | |
1492 /* careful: gui_resize_shell() may postpone the resize again if we | |
1493 * were called indirectly by it */ | |
1494 w = new_pixel_width; | |
1495 h = new_pixel_height; | |
1496 new_pixel_width = 0; | |
1497 new_pixel_height = 0; | |
1498 gui_resize_shell(w, h); | |
1499 } | |
1500 } | |
1501 | |
1502 int | |
1503 gui_get_shellsize() | |
1504 { | |
1505 Rows = gui.num_rows; | |
1506 Columns = gui.num_cols; | |
1507 return OK; | |
1508 } | |
1509 | |
1510 /* | |
1511 * Set the size of the Vim shell according to Rows and Columns. | |
444 | 1512 * If "fit_to_display" is TRUE then the size may be reduced to fit the window |
1513 * on the screen. | |
7 | 1514 */ |
1515 void | |
811 | 1516 gui_set_shellsize(mustset, fit_to_display, direction) |
1884 | 1517 int mustset UNUSED; /* set by the user */ |
7 | 1518 int fit_to_display; |
811 | 1519 int direction; /* RESIZE_HOR, RESIZE_VER */ |
7 | 1520 { |
1521 int base_width; | |
1522 int base_height; | |
1523 int width; | |
1524 int height; | |
1525 int min_width; | |
1526 int min_height; | |
1527 int screen_w; | |
1528 int screen_h; | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
1529 #ifdef FEAT_GUI_GTK |
1967 | 1530 int un_maximize = mustset; |
2311
ccda151dde4e
Support completion for ":find". (Nazri Ramliy)
Bram Moolenaar <bram@vim.org>
parents:
2282
diff
changeset
|
1531 int did_adjust = 0; |
1967 | 1532 #endif |
2065
9b78bb3794ba
updated for version 7.2.350
Bram Moolenaar <bram@zimbu.org>
parents:
1967
diff
changeset
|
1533 int x = -1, y = -1; |
7 | 1534 |
1535 if (!gui.shell_created) | |
1536 return; | |
1537 | |
3014 | 1538 #if defined(MSWIN) || defined(FEAT_GUI_GTK) |
7 | 1539 /* If not setting to a user specified size and maximized, calculate the |
1540 * number of characters that fit in the maximized window. */ | |
1541 if (!mustset && gui_mch_maximized()) | |
1542 { | |
1543 gui_mch_newfont(); | |
1544 return; | |
1545 } | |
1546 #endif | |
1547 | |
1548 base_width = gui_get_base_width(); | |
1549 base_height = gui_get_base_height(); | |
2065
9b78bb3794ba
updated for version 7.2.350
Bram Moolenaar <bram@zimbu.org>
parents:
1967
diff
changeset
|
1550 if (fit_to_display) |
9b78bb3794ba
updated for version 7.2.350
Bram Moolenaar <bram@zimbu.org>
parents:
1967
diff
changeset
|
1551 /* Remember the original window position. */ |
9b78bb3794ba
updated for version 7.2.350
Bram Moolenaar <bram@zimbu.org>
parents:
1967
diff
changeset
|
1552 gui_mch_get_winpos(&x, &y); |
9b78bb3794ba
updated for version 7.2.350
Bram Moolenaar <bram@zimbu.org>
parents:
1967
diff
changeset
|
1553 |
7 | 1554 #ifdef USE_SUN_WORKSHOP |
1555 if (!mustset && usingSunWorkShop | |
1556 && workshop_get_width_height(&width, &height)) | |
1557 { | |
1558 Columns = (width - base_width + gui.char_width - 1) / gui.char_width; | |
1559 Rows = (height - base_height + gui.char_height - 1) / gui.char_height; | |
1560 } | |
1561 else | |
1562 #endif | |
1563 { | |
1564 width = Columns * gui.char_width + base_width; | |
1565 height = Rows * gui.char_height + base_height; | |
1566 } | |
1567 | |
1568 if (fit_to_display) | |
1569 { | |
1570 gui_mch_get_screen_dimensions(&screen_w, &screen_h); | |
811 | 1571 if ((direction & RESIZE_HOR) && width > screen_w) |
7 | 1572 { |
1573 Columns = (screen_w - base_width) / gui.char_width; | |
1574 if (Columns < MIN_COLUMNS) | |
1575 Columns = MIN_COLUMNS; | |
1576 width = Columns * gui.char_width + base_width; | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
1577 #ifdef FEAT_GUI_GTK |
1967 | 1578 ++did_adjust; |
1579 #endif | |
7 | 1580 } |
811 | 1581 if ((direction & RESIZE_VERT) && height > screen_h) |
7 | 1582 { |
1583 Rows = (screen_h - base_height) / gui.char_height; | |
1584 check_shellsize(); | |
1585 height = Rows * gui.char_height + base_height; | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
1586 #ifdef FEAT_GUI_GTK |
1967 | 1587 ++did_adjust; |
1588 #endif | |
7 | 1589 } |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
1590 #ifdef FEAT_GUI_GTK |
1967 | 1591 if (did_adjust == 2 || (width + gui.char_width >= screen_w |
1592 && height + gui.char_height >= screen_h)) | |
1593 /* don't unmaximize if at maximum size */ | |
1594 un_maximize = FALSE; | |
1595 #endif | |
7 | 1596 } |
1597 gui.num_cols = Columns; | |
1598 gui.num_rows = Rows; | |
1599 | |
1600 min_width = base_width + MIN_COLUMNS * gui.char_width; | |
1601 min_height = base_height + MIN_LINES * gui.char_height; | |
1967 | 1602 #ifdef FEAT_WINDOWS |
685 | 1603 min_height += tabline_height() * gui.char_height; |
1967 | 1604 #endif |
1605 | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
1606 #ifdef FEAT_GUI_GTK |
1967 | 1607 if (un_maximize) |
1608 { | |
1609 /* If the window size is smaller than the screen unmaximize the | |
1610 * window, otherwise resizing won't work. */ | |
1611 gui_mch_get_screen_dimensions(&screen_w, &screen_h); | |
1612 if ((width + gui.char_width < screen_w | |
1613 || height + gui.char_height * 2 < screen_h) | |
1614 && gui_mch_maximized()) | |
1615 gui_mch_unmaximize(); | |
1616 } | |
1617 #endif | |
7 | 1618 |
1619 gui_mch_set_shellsize(width, height, min_width, min_height, | |
811 | 1620 base_width, base_height, direction); |
2065
9b78bb3794ba
updated for version 7.2.350
Bram Moolenaar <bram@zimbu.org>
parents:
1967
diff
changeset
|
1621 |
9b78bb3794ba
updated for version 7.2.350
Bram Moolenaar <bram@zimbu.org>
parents:
1967
diff
changeset
|
1622 if (fit_to_display && x >= 0 && y >= 0) |
7 | 1623 { |
2065
9b78bb3794ba
updated for version 7.2.350
Bram Moolenaar <bram@zimbu.org>
parents:
1967
diff
changeset
|
1624 /* Some window managers put the Vim window left of/above the screen. |
9b78bb3794ba
updated for version 7.2.350
Bram Moolenaar <bram@zimbu.org>
parents:
1967
diff
changeset
|
1625 * Only change the position if it wasn't already negative before |
9b78bb3794ba
updated for version 7.2.350
Bram Moolenaar <bram@zimbu.org>
parents:
1967
diff
changeset
|
1626 * (happens on MS-Windows with a secondary monitor). */ |
7 | 1627 gui_mch_update(); |
1628 if (gui_mch_get_winpos(&x, &y) == OK && (x < 0 || y < 0)) | |
1629 gui_mch_set_winpos(x < 0 ? 0 : x, y < 0 ? 0 : y); | |
1630 } | |
1631 | |
1632 gui_position_components(width); | |
1633 gui_update_scrollbars(TRUE); | |
1634 gui_reset_scroll_region(); | |
1635 } | |
1636 | |
1637 /* | |
1638 * Called when Rows and/or Columns has changed. | |
1639 */ | |
1640 void | |
1641 gui_new_shellsize() | |
1642 { | |
1643 gui_reset_scroll_region(); | |
1644 } | |
1645 | |
1646 /* | |
1647 * Make scroll region cover whole screen. | |
1648 */ | |
1649 void | |
1650 gui_reset_scroll_region() | |
1651 { | |
1652 gui.scroll_region_top = 0; | |
1653 gui.scroll_region_bot = gui.num_rows - 1; | |
1654 gui.scroll_region_left = 0; | |
1655 gui.scroll_region_right = gui.num_cols - 1; | |
1656 } | |
1657 | |
1658 void | |
1659 gui_start_highlight(mask) | |
1660 int mask; | |
1661 { | |
1662 if (mask > HL_ALL) /* highlight code */ | |
1663 gui.highlight_mask = mask; | |
1664 else /* mask */ | |
1665 gui.highlight_mask |= mask; | |
1666 } | |
1667 | |
1668 void | |
1669 gui_stop_highlight(mask) | |
1670 int mask; | |
1671 { | |
1672 if (mask > HL_ALL) /* highlight code */ | |
1673 gui.highlight_mask = HL_NORMAL; | |
1674 else /* mask */ | |
1675 gui.highlight_mask &= ~mask; | |
1676 } | |
1677 | |
1678 /* | |
1679 * Clear a rectangular region of the screen from text pos (row1, col1) to | |
1680 * (row2, col2) inclusive. | |
1681 */ | |
1682 void | |
1683 gui_clear_block(row1, col1, row2, col2) | |
1684 int row1; | |
1685 int col1; | |
1686 int row2; | |
1687 int col2; | |
1688 { | |
1689 /* Clear the selection if we are about to write over it */ | |
1690 clip_may_clear_selection(row1, row2); | |
1691 | |
1692 gui_mch_clear_block(row1, col1, row2, col2); | |
1693 | |
1694 /* Invalidate cursor if it was in this block */ | |
1695 if ( gui.cursor_row >= row1 && gui.cursor_row <= row2 | |
1696 && gui.cursor_col >= col1 && gui.cursor_col <= col2) | |
1697 gui.cursor_is_valid = FALSE; | |
1698 } | |
1699 | |
1700 /* | |
1701 * Write code to update the cursor later. This avoids the need to flush the | |
1702 * output buffer before calling gui_update_cursor(). | |
1703 */ | |
1704 void | |
1705 gui_update_cursor_later() | |
1706 { | |
1707 OUT_STR(IF_EB("\033|s", ESC_STR "|s")); | |
1708 } | |
1709 | |
1710 void | |
1711 gui_write(s, len) | |
1712 char_u *s; | |
1713 int len; | |
1714 { | |
1715 char_u *p; | |
1716 int arg1 = 0, arg2 = 0; | |
1717 int force_cursor = FALSE; /* force cursor update */ | |
1718 int force_scrollbar = FALSE; | |
1719 static win_T *old_curwin = NULL; | |
1720 | |
1721 /* #define DEBUG_GUI_WRITE */ | |
1722 #ifdef DEBUG_GUI_WRITE | |
1723 { | |
1724 int i; | |
1725 char_u *str; | |
1726 | |
1727 printf("gui_write(%d):\n ", len); | |
1728 for (i = 0; i < len; i++) | |
1729 if (s[i] == ESC) | |
1730 { | |
1731 if (i != 0) | |
1732 printf("\n "); | |
1733 printf("<ESC>"); | |
1734 } | |
1735 else | |
1736 { | |
1737 str = transchar_byte(s[i]); | |
1738 if (str[0] && str[1]) | |
1739 printf("<%s>", (char *)str); | |
1740 else | |
1741 printf("%s", (char *)str); | |
1742 } | |
1743 printf("\n"); | |
1744 } | |
1745 #endif | |
1746 while (len) | |
1747 { | |
1748 if (s[0] == ESC && s[1] == '|') | |
1749 { | |
1750 p = s + 2; | |
1751 if (VIM_ISDIGIT(*p)) | |
1752 { | |
1753 arg1 = getdigits(&p); | |
1754 if (p > s + len) | |
1755 break; | |
1756 if (*p == ';') | |
1757 { | |
1758 ++p; | |
1759 arg2 = getdigits(&p); | |
1760 if (p > s + len) | |
1761 break; | |
1762 } | |
1763 } | |
1764 switch (*p) | |
1765 { | |
1766 case 'C': /* Clear screen */ | |
1767 clip_scroll_selection(9999); | |
1768 gui_mch_clear_all(); | |
1769 gui.cursor_is_valid = FALSE; | |
1770 force_scrollbar = TRUE; | |
1771 break; | |
1772 case 'M': /* Move cursor */ | |
1773 gui_set_cursor(arg1, arg2); | |
1774 break; | |
1775 case 's': /* force cursor (shape) update */ | |
1776 force_cursor = TRUE; | |
1777 break; | |
1778 case 'R': /* Set scroll region */ | |
1779 if (arg1 < arg2) | |
1780 { | |
1781 gui.scroll_region_top = arg1; | |
1782 gui.scroll_region_bot = arg2; | |
1783 } | |
1784 else | |
1785 { | |
1786 gui.scroll_region_top = arg2; | |
1787 gui.scroll_region_bot = arg1; | |
1788 } | |
1789 break; | |
1790 #ifdef FEAT_VERTSPLIT | |
1791 case 'V': /* Set vertical scroll region */ | |
1792 if (arg1 < arg2) | |
1793 { | |
1794 gui.scroll_region_left = arg1; | |
1795 gui.scroll_region_right = arg2; | |
1796 } | |
1797 else | |
1798 { | |
1799 gui.scroll_region_left = arg2; | |
1800 gui.scroll_region_right = arg1; | |
1801 } | |
1802 break; | |
1803 #endif | |
1804 case 'd': /* Delete line */ | |
1805 gui_delete_lines(gui.row, 1); | |
1806 break; | |
1807 case 'D': /* Delete lines */ | |
1808 gui_delete_lines(gui.row, arg1); | |
1809 break; | |
1810 case 'i': /* Insert line */ | |
1811 gui_insert_lines(gui.row, 1); | |
1812 break; | |
1813 case 'I': /* Insert lines */ | |
1814 gui_insert_lines(gui.row, arg1); | |
1815 break; | |
1816 case '$': /* Clear to end-of-line */ | |
1817 gui_clear_block(gui.row, gui.col, gui.row, | |
1818 (int)Columns - 1); | |
1819 break; | |
1820 case 'h': /* Turn on highlighting */ | |
1821 gui_start_highlight(arg1); | |
1822 break; | |
1823 case 'H': /* Turn off highlighting */ | |
1824 gui_stop_highlight(arg1); | |
1825 break; | |
1826 case 'f': /* flash the window (visual bell) */ | |
1827 gui_mch_flash(arg1 == 0 ? 20 : arg1); | |
1828 break; | |
1829 default: | |
1830 p = s + 1; /* Skip the ESC */ | |
1831 break; | |
1832 } | |
1833 len -= (int)(++p - s); | |
1834 s = p; | |
1835 } | |
1836 else if ( | |
1837 #ifdef EBCDIC | |
1838 CtrlChar(s[0]) != 0 /* Ctrl character */ | |
1839 #else | |
1840 s[0] < 0x20 /* Ctrl character */ | |
1841 #endif | |
1842 #ifdef FEAT_SIGN_ICONS | |
1843 && s[0] != SIGN_BYTE | |
1844 # ifdef FEAT_NETBEANS_INTG | |
1845 && s[0] != MULTISIGN_BYTE | |
1846 # endif | |
1847 #endif | |
1848 ) | |
1849 { | |
1850 if (s[0] == '\n') /* NL */ | |
1851 { | |
1852 gui.col = 0; | |
1853 if (gui.row < gui.scroll_region_bot) | |
1854 gui.row++; | |
1855 else | |
1856 gui_delete_lines(gui.scroll_region_top, 1); | |
1857 } | |
1858 else if (s[0] == '\r') /* CR */ | |
1859 { | |
1860 gui.col = 0; | |
1861 } | |
1862 else if (s[0] == '\b') /* Backspace */ | |
1863 { | |
1864 if (gui.col) | |
1865 --gui.col; | |
1866 } | |
1867 else if (s[0] == Ctrl_L) /* cursor-right */ | |
1868 { | |
1869 ++gui.col; | |
1870 } | |
1871 else if (s[0] == Ctrl_G) /* Beep */ | |
1872 { | |
1873 gui_mch_beep(); | |
1874 } | |
1875 /* Other Ctrl character: shouldn't happen! */ | |
1876 | |
1877 --len; /* Skip this char */ | |
1878 ++s; | |
1879 } | |
1880 else | |
1881 { | |
1882 p = s; | |
1883 while (len > 0 && ( | |
1884 #ifdef EBCDIC | |
1885 CtrlChar(*p) == 0 | |
1886 #else | |
1887 *p >= 0x20 | |
1888 #endif | |
1889 #ifdef FEAT_SIGN_ICONS | |
1890 || *p == SIGN_BYTE | |
1891 # ifdef FEAT_NETBEANS_INTG | |
1892 || *p == MULTISIGN_BYTE | |
1893 # endif | |
1894 #endif | |
1895 )) | |
1896 { | |
1897 len--; | |
1898 p++; | |
1899 } | |
1900 gui_outstr(s, (int)(p - s)); | |
1901 s = p; | |
1902 } | |
1903 } | |
1904 | |
1905 /* Postponed update of the cursor (won't work if "can_update_cursor" isn't | |
1906 * set). */ | |
1907 if (force_cursor) | |
1908 gui_update_cursor(TRUE, TRUE); | |
1909 | |
1910 /* When switching to another window the dragging must have stopped. | |
1911 * Required for GTK, dragged_sb isn't reset. */ | |
1912 if (old_curwin != curwin) | |
1913 gui.dragged_sb = SBAR_NONE; | |
1914 | |
1915 /* Update the scrollbars after clearing the screen or when switched | |
1916 * to another window. | |
1917 * Update the horizontal scrollbar always, it's difficult to check all | |
1918 * situations where it might change. */ | |
1919 if (force_scrollbar || old_curwin != curwin) | |
1920 gui_update_scrollbars(force_scrollbar); | |
1921 else | |
1922 gui_update_horiz_scrollbar(FALSE); | |
1923 old_curwin = curwin; | |
1924 | |
1925 /* | |
1926 * We need to make sure this is cleared since Athena doesn't tell us when | |
1927 * he is done dragging. Do the same for GTK. | |
1928 */ | |
574 | 1929 #if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_GTK) |
7 | 1930 gui.dragged_sb = SBAR_NONE; |
1931 #endif | |
1932 | |
1933 gui_mch_flush(); /* In case vim decides to take a nap */ | |
1934 } | |
1935 | |
1936 /* | |
1937 * When ScreenLines[] is invalid, updating the cursor should not be done, it | |
1938 * produces wrong results. Call gui_dont_update_cursor() before that code and | |
1939 * gui_can_update_cursor() afterwards. | |
1940 */ | |
1941 void | |
1942 gui_dont_update_cursor() | |
1943 { | |
1944 if (gui.in_use) | |
1945 { | |
1946 /* Undraw the cursor now, we probably can't do it after the change. */ | |
1947 gui_undraw_cursor(); | |
1948 can_update_cursor = FALSE; | |
1949 } | |
1950 } | |
1951 | |
1952 void | |
1953 gui_can_update_cursor() | |
1954 { | |
1955 can_update_cursor = TRUE; | |
1956 /* No need to update the cursor right now, there is always more output | |
1957 * after scrolling. */ | |
1958 } | |
1959 | |
1960 static void | |
1961 gui_outstr(s, len) | |
1962 char_u *s; | |
1963 int len; | |
1964 { | |
1965 int this_len; | |
1966 #ifdef FEAT_MBYTE | |
1967 int cells; | |
1968 #endif | |
1969 | |
1970 if (len == 0) | |
1971 return; | |
1972 | |
1973 if (len < 0) | |
1974 len = (int)STRLEN(s); | |
1975 | |
1976 while (len > 0) | |
1977 { | |
1978 #ifdef FEAT_MBYTE | |
1979 if (has_mbyte) | |
1980 { | |
1981 /* Find out how many chars fit in the current line. */ | |
1982 cells = 0; | |
1983 for (this_len = 0; this_len < len; ) | |
1984 { | |
1985 cells += (*mb_ptr2cells)(s + this_len); | |
1986 if (gui.col + cells > Columns) | |
1987 break; | |
474 | 1988 this_len += (*mb_ptr2len)(s + this_len); |
7 | 1989 } |
1990 if (this_len > len) | |
1991 this_len = len; /* don't include following composing char */ | |
1992 } | |
1993 else | |
1994 #endif | |
1995 if (gui.col + len > Columns) | |
1996 this_len = Columns - gui.col; | |
1997 else | |
1998 this_len = len; | |
1999 | |
2000 (void)gui_outstr_nowrap(s, this_len, | |
2001 0, (guicolor_T)0, (guicolor_T)0, 0); | |
2002 s += this_len; | |
2003 len -= this_len; | |
2004 #ifdef FEAT_MBYTE | |
2005 /* fill up for a double-width char that doesn't fit. */ | |
2006 if (len > 0 && gui.col < Columns) | |
2007 (void)gui_outstr_nowrap((char_u *)" ", 1, | |
2008 0, (guicolor_T)0, (guicolor_T)0, 0); | |
2009 #endif | |
2010 /* The cursor may wrap to the next line. */ | |
2011 if (gui.col >= Columns) | |
2012 { | |
2013 gui.col = 0; | |
2014 gui.row++; | |
2015 } | |
2016 } | |
2017 } | |
2018 | |
2019 /* | |
2020 * Output one character (may be one or two display cells). | |
2021 * Caller must check for valid "off". | |
2022 * Returns FAIL or OK, just like gui_outstr_nowrap(). | |
2023 */ | |
2024 static int | |
2025 gui_screenchar(off, flags, fg, bg, back) | |
2026 int off; /* Offset from start of screen */ | |
2027 int flags; | |
2028 guicolor_T fg, bg; /* colors for cursor */ | |
2029 int back; /* backup this many chars when using bold trick */ | |
2030 { | |
2031 #ifdef FEAT_MBYTE | |
2032 char_u buf[MB_MAXBYTES + 1]; | |
2033 | |
2034 /* Don't draw right halve of a double-width UTF-8 char. "cannot happen" */ | |
2035 if (enc_utf8 && ScreenLines[off] == 0) | |
2036 return OK; | |
2037 | |
2038 if (enc_utf8 && ScreenLinesUC[off] != 0) | |
2039 /* Draw UTF-8 multi-byte character. */ | |
2040 return gui_outstr_nowrap(buf, utfc_char2bytes(off, buf), | |
2041 flags, fg, bg, back); | |
2042 | |
2043 if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e) | |
2044 { | |
2045 buf[0] = ScreenLines[off]; | |
2046 buf[1] = ScreenLines2[off]; | |
2047 return gui_outstr_nowrap(buf, 2, flags, fg, bg, back); | |
2048 } | |
2049 | |
2050 /* Draw non-multi-byte character or DBCS character. */ | |
2051 return gui_outstr_nowrap(ScreenLines + off, | |
474 | 2052 enc_dbcs ? (*mb_ptr2len)(ScreenLines + off) : 1, |
7 | 2053 flags, fg, bg, back); |
2054 #else | |
2055 return gui_outstr_nowrap(ScreenLines + off, 1, flags, fg, bg, back); | |
2056 #endif | |
2057 } | |
2058 | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
2059 #ifdef FEAT_GUI_GTK |
7 | 2060 /* |
2061 * Output the string at the given screen position. This is used in place | |
2062 * of gui_screenchar() where possible because Pango needs as much context | |
2063 * as possible to work nicely. It's a lot faster as well. | |
2064 */ | |
2065 static int | |
2066 gui_screenstr(off, len, flags, fg, bg, back) | |
2067 int off; /* Offset from start of screen */ | |
2068 int len; /* string length in screen cells */ | |
2069 int flags; | |
2070 guicolor_T fg, bg; /* colors for cursor */ | |
2071 int back; /* backup this many chars when using bold trick */ | |
2072 { | |
2073 char_u *buf; | |
2074 int outlen = 0; | |
2075 int i; | |
2076 int retval; | |
2077 | |
2078 if (len <= 0) /* "cannot happen"? */ | |
2079 return OK; | |
2080 | |
2081 if (enc_utf8) | |
2082 { | |
2083 buf = alloc((unsigned)(len * MB_MAXBYTES + 1)); | |
2084 if (buf == NULL) | |
2085 return OK; /* not much we could do here... */ | |
2086 | |
2087 for (i = off; i < off + len; ++i) | |
2088 { | |
2089 if (ScreenLines[i] == 0) | |
2090 continue; /* skip second half of double-width char */ | |
2091 | |
2092 if (ScreenLinesUC[i] == 0) | |
2093 buf[outlen++] = ScreenLines[i]; | |
2094 else | |
2095 outlen += utfc_char2bytes(i, buf + outlen); | |
2096 } | |
2097 | |
2098 buf[outlen] = NUL; /* only to aid debugging */ | |
2099 retval = gui_outstr_nowrap(buf, outlen, flags, fg, bg, back); | |
2100 vim_free(buf); | |
2101 | |
2102 return retval; | |
2103 } | |
2104 else if (enc_dbcs == DBCS_JPNU) | |
2105 { | |
2106 buf = alloc((unsigned)(len * 2 + 1)); | |
2107 if (buf == NULL) | |
2108 return OK; /* not much we could do here... */ | |
2109 | |
2110 for (i = off; i < off + len; ++i) | |
2111 { | |
2112 buf[outlen++] = ScreenLines[i]; | |
2113 | |
2114 /* handle double-byte single-width char */ | |
2115 if (ScreenLines[i] == 0x8e) | |
2116 buf[outlen++] = ScreenLines2[i]; | |
2117 else if (MB_BYTE2LEN(ScreenLines[i]) == 2) | |
2118 buf[outlen++] = ScreenLines[++i]; | |
2119 } | |
2120 | |
2121 buf[outlen] = NUL; /* only to aid debugging */ | |
2122 retval = gui_outstr_nowrap(buf, outlen, flags, fg, bg, back); | |
2123 vim_free(buf); | |
2124 | |
2125 return retval; | |
2126 } | |
2127 else | |
2128 { | |
2129 return gui_outstr_nowrap(&ScreenLines[off], len, | |
2130 flags, fg, bg, back); | |
2131 } | |
2132 } | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
2133 #endif /* FEAT_GUI_GTK */ |
7 | 2134 |
2135 /* | |
2136 * Output the given string at the current cursor position. If the string is | |
2137 * too long to fit on the line, then it is truncated. | |
2138 * "flags": | |
2139 * GUI_MON_IS_CURSOR should only be used when this function is being called to | |
2140 * actually draw (an inverted) cursor. | |
1199 | 2141 * GUI_MON_TRS_CURSOR is used to draw the cursor text with a transparent |
7 | 2142 * background. |
2143 * GUI_MON_NOCLEAR is used to avoid clearing the selection when drawing over | |
2144 * it. | |
2145 * Returns OK, unless "back" is non-zero and using the bold trick, then return | |
2146 * FAIL (the caller should start drawing "back" chars back). | |
2147 */ | |
2148 int | |
2149 gui_outstr_nowrap(s, len, flags, fg, bg, back) | |
2150 char_u *s; | |
2151 int len; | |
2152 int flags; | |
2153 guicolor_T fg, bg; /* colors for cursor */ | |
2154 int back; /* backup this many chars when using bold trick */ | |
2155 { | |
2156 long_u highlight_mask; | |
2157 long_u hl_mask_todo; | |
2158 guicolor_T fg_color; | |
2159 guicolor_T bg_color; | |
203 | 2160 guicolor_T sp_color; |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
2161 #if !defined(MSWIN16_FASTTEXT) && !defined(FEAT_GUI_GTK) |
7 | 2162 GuiFont font = NOFONT; |
2163 # ifdef FEAT_XFONTSET | |
2164 GuiFontset fontset = NOFONTSET; | |
2165 # endif | |
2166 #endif | |
2167 attrentry_T *aep = NULL; | |
2168 int draw_flags; | |
2169 int col = gui.col; | |
2170 #ifdef FEAT_SIGN_ICONS | |
2171 int draw_sign = FALSE; | |
2172 # ifdef FEAT_NETBEANS_INTG | |
2173 int multi_sign = FALSE; | |
2174 # endif | |
2175 #endif | |
2176 | |
2177 if (len < 0) | |
2178 len = (int)STRLEN(s); | |
2179 if (len == 0) | |
2180 return OK; | |
2181 | |
2182 #ifdef FEAT_SIGN_ICONS | |
2183 if (*s == SIGN_BYTE | |
2184 # ifdef FEAT_NETBEANS_INTG | |
2185 || *s == MULTISIGN_BYTE | |
2186 # endif | |
2187 ) | |
2188 { | |
2189 # ifdef FEAT_NETBEANS_INTG | |
2190 if (*s == MULTISIGN_BYTE) | |
2191 multi_sign = TRUE; | |
2192 # endif | |
2193 /* draw spaces instead */ | |
2194 s = (char_u *)" "; | |
2195 if (len == 1 && col > 0) | |
2196 --col; | |
2197 len = 2; | |
2198 draw_sign = TRUE; | |
2199 highlight_mask = 0; | |
2200 } | |
2201 else | |
2202 #endif | |
2203 if (gui.highlight_mask > HL_ALL) | |
2204 { | |
2205 aep = syn_gui_attr2entry(gui.highlight_mask); | |
2206 if (aep == NULL) /* highlighting not set */ | |
2207 highlight_mask = 0; | |
2208 else | |
2209 highlight_mask = aep->ae_attr; | |
2210 } | |
2211 else | |
2212 highlight_mask = gui.highlight_mask; | |
2213 hl_mask_todo = highlight_mask; | |
2214 | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
2215 #if !defined(MSWIN16_FASTTEXT) && !defined(FEAT_GUI_GTK) |
7 | 2216 /* Set the font */ |
2217 if (aep != NULL && aep->ae_u.gui.font != NOFONT) | |
2218 font = aep->ae_u.gui.font; | |
2219 # ifdef FEAT_XFONTSET | |
2220 else if (aep != NULL && aep->ae_u.gui.fontset != NOFONTSET) | |
2221 fontset = aep->ae_u.gui.fontset; | |
2222 # endif | |
2223 else | |
2224 { | |
2225 # ifdef FEAT_XFONTSET | |
2226 if (gui.fontset != NOFONTSET) | |
2227 fontset = gui.fontset; | |
2228 else | |
2229 # endif | |
2230 if (hl_mask_todo & (HL_BOLD | HL_STANDOUT)) | |
2231 { | |
2232 if ((hl_mask_todo & HL_ITALIC) && gui.boldital_font != NOFONT) | |
2233 { | |
2234 font = gui.boldital_font; | |
2235 hl_mask_todo &= ~(HL_BOLD | HL_STANDOUT | HL_ITALIC); | |
2236 } | |
2237 else if (gui.bold_font != NOFONT) | |
2238 { | |
2239 font = gui.bold_font; | |
2240 hl_mask_todo &= ~(HL_BOLD | HL_STANDOUT); | |
2241 } | |
2242 else | |
2243 font = gui.norm_font; | |
2244 } | |
2245 else if ((hl_mask_todo & HL_ITALIC) && gui.ital_font != NOFONT) | |
2246 { | |
2247 font = gui.ital_font; | |
2248 hl_mask_todo &= ~HL_ITALIC; | |
2249 } | |
2250 else | |
2251 font = gui.norm_font; | |
2252 } | |
2253 # ifdef FEAT_XFONTSET | |
2254 if (fontset != NOFONTSET) | |
2255 gui_mch_set_fontset(fontset); | |
2256 else | |
2257 # endif | |
2258 gui_mch_set_font(font); | |
2259 #endif | |
2260 | |
2261 draw_flags = 0; | |
2262 | |
2263 /* Set the color */ | |
2264 bg_color = gui.back_pixel; | |
2265 if ((flags & GUI_MON_IS_CURSOR) && gui.in_focus) | |
2266 { | |
2267 draw_flags |= DRAW_CURSOR; | |
2268 fg_color = fg; | |
2269 bg_color = bg; | |
203 | 2270 sp_color = fg; |
7 | 2271 } |
2272 else if (aep != NULL) | |
2273 { | |
2274 fg_color = aep->ae_u.gui.fg_color; | |
2275 if (fg_color == INVALCOLOR) | |
2276 fg_color = gui.norm_pixel; | |
2277 bg_color = aep->ae_u.gui.bg_color; | |
2278 if (bg_color == INVALCOLOR) | |
2279 bg_color = gui.back_pixel; | |
203 | 2280 sp_color = aep->ae_u.gui.sp_color; |
2281 if (sp_color == INVALCOLOR) | |
2282 sp_color = fg_color; | |
7 | 2283 } |
2284 else | |
203 | 2285 { |
7 | 2286 fg_color = gui.norm_pixel; |
203 | 2287 sp_color = fg_color; |
2288 } | |
7 | 2289 |
2290 if (highlight_mask & (HL_INVERSE | HL_STANDOUT)) | |
2291 { | |
2823 | 2292 #if defined(AMIGA) |
7 | 2293 gui_mch_set_colors(bg_color, fg_color); |
2294 #else | |
2295 gui_mch_set_fg_color(bg_color); | |
2296 gui_mch_set_bg_color(fg_color); | |
2297 #endif | |
2298 } | |
2299 else | |
2300 { | |
2823 | 2301 #if defined(AMIGA) |
7 | 2302 gui_mch_set_colors(fg_color, bg_color); |
2303 #else | |
2304 gui_mch_set_fg_color(fg_color); | |
2305 gui_mch_set_bg_color(bg_color); | |
2306 #endif | |
2307 } | |
203 | 2308 gui_mch_set_sp_color(sp_color); |
7 | 2309 |
2310 /* Clear the selection if we are about to write over it */ | |
2311 if (!(flags & GUI_MON_NOCLEAR)) | |
2312 clip_may_clear_selection(gui.row, gui.row); | |
2313 | |
2314 | |
2315 #ifndef MSWIN16_FASTTEXT | |
2316 /* If there's no bold font, then fake it */ | |
2317 if (hl_mask_todo & (HL_BOLD | HL_STANDOUT)) | |
2318 draw_flags |= DRAW_BOLD; | |
2319 #endif | |
2320 | |
2321 /* | |
2322 * When drawing bold or italic characters the spill-over from the left | |
2323 * neighbor may be destroyed. Let the caller backup to start redrawing | |
2324 * just after a blank. | |
2325 */ | |
2326 if (back != 0 && ((draw_flags & DRAW_BOLD) || (highlight_mask & HL_ITALIC))) | |
2327 return FAIL; | |
2328 | |
2823 | 2329 #if defined(FEAT_GUI_GTK) |
7 | 2330 /* If there's no italic font, then fake it. |
2331 * For GTK2, we don't need a different font for italic style. */ | |
2332 if (hl_mask_todo & HL_ITALIC) | |
2333 draw_flags |= DRAW_ITALIC; | |
2334 | |
2335 /* Do we underline the text? */ | |
2336 if (hl_mask_todo & HL_UNDERLINE) | |
2337 draw_flags |= DRAW_UNDERL; | |
2338 #else | |
2339 /* Do we underline the text? */ | |
2340 if ((hl_mask_todo & HL_UNDERLINE) | |
2341 # ifndef MSWIN16_FASTTEXT | |
2342 || (hl_mask_todo & HL_ITALIC) | |
2343 # endif | |
2344 ) | |
2345 draw_flags |= DRAW_UNDERL; | |
2346 #endif | |
203 | 2347 /* Do we undercurl the text? */ |
2348 if (hl_mask_todo & HL_UNDERCURL) | |
2349 draw_flags |= DRAW_UNDERC; | |
7 | 2350 |
1199 | 2351 /* Do we draw transparently? */ |
7 | 2352 if (flags & GUI_MON_TRS_CURSOR) |
2353 draw_flags |= DRAW_TRANSP; | |
2354 | |
2355 /* | |
2356 * Draw the text. | |
2357 */ | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
2358 #ifdef FEAT_GUI_GTK |
7 | 2359 /* The value returned is the length in display cells */ |
2360 len = gui_gtk2_draw_string(gui.row, col, s, len, draw_flags); | |
2361 #else | |
2362 # ifdef FEAT_MBYTE | |
2363 if (enc_utf8) | |
2364 { | |
2365 int start; /* index of bytes to be drawn */ | |
2366 int cells; /* cellwidth of bytes to be drawn */ | |
2367 int thislen; /* length of bytes to be drawin */ | |
2368 int cn; /* cellwidth of current char */ | |
2369 int i; /* index of current char */ | |
2370 int c; /* current char value */ | |
2371 int cl; /* byte length of current char */ | |
2372 int comping; /* current char is composing */ | |
2373 int scol = col; /* screen column */ | |
2374 int dowide; /* use 'guifontwide' */ | |
2375 | |
2376 /* Break the string at a composing character, it has to be drawn on | |
2377 * top of the previous character. */ | |
2378 start = 0; | |
2379 cells = 0; | |
2380 for (i = 0; i < len; i += cl) | |
2381 { | |
2382 c = utf_ptr2char(s + i); | |
2383 cn = utf_char2cells(c); | |
2384 if (cn > 1 | |
2385 # ifdef FEAT_XFONTSET | |
2386 && fontset == NOFONTSET | |
2387 # endif | |
2388 && gui.wide_font != NOFONT) | |
2389 dowide = TRUE; | |
2390 else | |
2391 dowide = FALSE; | |
2392 comping = utf_iscomposing(c); | |
2393 if (!comping) /* count cells from non-composing chars */ | |
2394 cells += cn; | |
474 | 2395 cl = utf_ptr2len(s + i); |
7 | 2396 if (cl == 0) /* hit end of string */ |
2397 len = i + cl; /* len must be wrong "cannot happen" */ | |
2398 | |
2399 /* print the string so far if it's the last character or there is | |
2400 * a composing character. */ | |
2401 if (i + cl >= len || (comping && i > start) || dowide | |
2275
e4d849f4df03
Remove the old and not well supported GTK 1 code. (James Vega)
Bram Moolenaar <bram@vim.org>
parents:
2237
diff
changeset
|
2402 # if defined(FEAT_GUI_X11) |
7 | 2403 || (cn > 1 |
2404 # ifdef FEAT_XFONTSET | |
2405 /* No fontset: At least draw char after wide char at | |
2406 * right position. */ | |
2407 && fontset == NOFONTSET | |
2408 # endif | |
2409 ) | |
2410 # endif | |
2411 ) | |
2412 { | |
2413 if (comping || dowide) | |
2414 thislen = i - start; | |
2415 else | |
2416 thislen = i - start + cl; | |
2417 if (thislen > 0) | |
2418 { | |
2419 gui_mch_draw_string(gui.row, scol, s + start, thislen, | |
2420 draw_flags); | |
2421 start += thislen; | |
2422 } | |
2423 scol += cells; | |
2424 cells = 0; | |
2425 if (dowide) | |
2426 { | |
2427 gui_mch_set_font(gui.wide_font); | |
2428 gui_mch_draw_string(gui.row, scol - cn, | |
2429 s + start, cl, draw_flags); | |
2430 gui_mch_set_font(font); | |
2431 start += cl; | |
2432 } | |
2433 | |
2275
e4d849f4df03
Remove the old and not well supported GTK 1 code. (James Vega)
Bram Moolenaar <bram@vim.org>
parents:
2237
diff
changeset
|
2434 # if defined(FEAT_GUI_X11) |
11 | 2435 /* No fontset: draw a space to fill the gap after a wide char |
2436 * */ | |
7 | 2437 if (cn > 1 && (draw_flags & DRAW_TRANSP) == 0 |
2438 # ifdef FEAT_XFONTSET | |
2439 && fontset == NOFONTSET | |
2440 # endif | |
2441 && !dowide) | |
2442 gui_mch_draw_string(gui.row, scol - 1, (char_u *)" ", | |
2443 1, draw_flags); | |
2444 # endif | |
2445 } | |
2446 /* Draw a composing char on top of the previous char. */ | |
2447 if (comping) | |
2448 { | |
536 | 2449 # if (defined(__APPLE_CC__) || defined(__MRC__)) && TARGET_API_MAC_CARBON |
2450 /* Carbon ATSUI autodraws composing char over previous char */ | |
2451 gui_mch_draw_string(gui.row, scol, s + i, cl, | |
7 | 2452 draw_flags | DRAW_TRANSP); |
187 | 2453 # else |
536 | 2454 gui_mch_draw_string(gui.row, scol - cn, s + i, cl, |
187 | 2455 draw_flags | DRAW_TRANSP); |
2456 # endif | |
7 | 2457 start = i + cl; |
2458 } | |
2459 } | |
2460 /* The stuff below assumes "len" is the length in screen columns. */ | |
2461 len = scol - col; | |
2462 } | |
2463 else | |
2464 # endif | |
2465 { | |
2466 gui_mch_draw_string(gui.row, col, s, len, draw_flags); | |
2467 # ifdef FEAT_MBYTE | |
2468 if (enc_dbcs == DBCS_JPNU) | |
2469 { | |
2470 /* Get the length in display cells, this can be different from the | |
2471 * number of bytes for "euc-jp". */ | |
2338
da6ec32d8d8f
Added strwidth() and strchars() functions.
Bram Moolenaar <bram@vim.org>
parents:
2311
diff
changeset
|
2472 len = mb_string2cells(s, len); |
7 | 2473 } |
2474 # endif | |
2475 } | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
2476 #endif /* !FEAT_GUI_GTK */ |
7 | 2477 |
2478 if (!(flags & (GUI_MON_IS_CURSOR | GUI_MON_TRS_CURSOR))) | |
2479 gui.col = col + len; | |
2480 | |
2481 /* May need to invert it when it's part of the selection. */ | |
2482 if (flags & GUI_MON_NOCLEAR) | |
2483 clip_may_redraw_selection(gui.row, col, len); | |
2484 | |
2485 if (!(flags & (GUI_MON_IS_CURSOR | GUI_MON_TRS_CURSOR))) | |
2486 { | |
2487 /* Invalidate the old physical cursor position if we wrote over it */ | |
2488 if (gui.cursor_row == gui.row | |
2489 && gui.cursor_col >= col | |
2490 && gui.cursor_col < col + len) | |
2491 gui.cursor_is_valid = FALSE; | |
2492 } | |
2493 | |
2494 #ifdef FEAT_SIGN_ICONS | |
2495 if (draw_sign) | |
2496 /* Draw the sign on top of the spaces. */ | |
2497 gui_mch_drawsign(gui.row, col, gui.highlight_mask); | |
2592 | 2498 # if defined(FEAT_NETBEANS_INTG) && (defined(FEAT_GUI_X11) \ |
2209
d0ddf7ba1630
Included the patch to support netbeans in a terminal.
Bram Moolenaar <bram@vim.org>
parents:
2208
diff
changeset
|
2499 || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_W32)) |
7 | 2500 if (multi_sign) |
2501 netbeans_draw_multisign_indicator(gui.row); | |
2502 # endif | |
2503 #endif | |
2504 | |
2505 return OK; | |
2506 } | |
2507 | |
2508 /* | |
2509 * Un-draw the cursor. Actually this just redraws the character at the given | |
2510 * position. The character just before it too, for when it was in bold. | |
2511 */ | |
2512 void | |
2513 gui_undraw_cursor() | |
2514 { | |
2515 if (gui.cursor_is_valid) | |
2516 { | |
2517 #ifdef FEAT_HANGULIN | |
2518 if (composing_hangul | |
2519 && gui.col == gui.cursor_col && gui.row == gui.cursor_row) | |
2520 (void)gui_outstr_nowrap(composing_hangul_buffer, 2, | |
2521 GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, | |
2522 gui.norm_pixel, gui.back_pixel, 0); | |
2523 else | |
2524 { | |
2525 #endif | |
2526 if (gui_redraw_block(gui.cursor_row, gui.cursor_col, | |
2527 gui.cursor_row, gui.cursor_col, GUI_MON_NOCLEAR) | |
2528 && gui.cursor_col > 0) | |
2529 (void)gui_redraw_block(gui.cursor_row, gui.cursor_col - 1, | |
2530 gui.cursor_row, gui.cursor_col - 1, GUI_MON_NOCLEAR); | |
2531 #ifdef FEAT_HANGULIN | |
2532 if (composing_hangul) | |
2533 (void)gui_redraw_block(gui.cursor_row, gui.cursor_col + 1, | |
2534 gui.cursor_row, gui.cursor_col + 1, GUI_MON_NOCLEAR); | |
2535 } | |
2536 #endif | |
2537 /* Cursor_is_valid is reset when the cursor is undrawn, also reset it | |
2538 * here in case it wasn't needed to undraw it. */ | |
2539 gui.cursor_is_valid = FALSE; | |
2540 } | |
2541 } | |
2542 | |
2543 void | |
2544 gui_redraw(x, y, w, h) | |
2545 int x; | |
2546 int y; | |
2547 int w; | |
2548 int h; | |
2549 { | |
2550 int row1, col1, row2, col2; | |
2551 | |
2552 row1 = Y_2_ROW(y); | |
2553 col1 = X_2_COL(x); | |
2554 row2 = Y_2_ROW(y + h - 1); | |
2555 col2 = X_2_COL(x + w - 1); | |
2556 | |
2557 (void)gui_redraw_block(row1, col1, row2, col2, GUI_MON_NOCLEAR); | |
2558 | |
2559 /* | |
2560 * We may need to redraw the cursor, but don't take it upon us to change | |
2561 * its location after a scroll. | |
2562 * (maybe be more strict even and test col too?) | |
2563 * These things may be outside the update/clipping region and reality may | |
2564 * not reflect Vims internal ideas if these operations are clipped away. | |
2565 */ | |
2566 if (gui.row == gui.cursor_row) | |
2567 gui_update_cursor(TRUE, TRUE); | |
2568 } | |
2569 | |
2570 /* | |
2571 * Draw a rectangular block of characters, from row1 to row2 (inclusive) and | |
2572 * from col1 to col2 (inclusive). | |
2573 * Return TRUE when the character before the first drawn character has | |
2574 * different attributes (may have to be redrawn too). | |
2575 */ | |
2576 int | |
2577 gui_redraw_block(row1, col1, row2, col2, flags) | |
2578 int row1; | |
2579 int col1; | |
2580 int row2; | |
2581 int col2; | |
2582 int flags; /* flags for gui_outstr_nowrap() */ | |
2583 { | |
2584 int old_row, old_col; | |
2585 long_u old_hl_mask; | |
2586 int off; | |
203 | 2587 sattr_T first_attr; |
7 | 2588 int idx, len; |
2589 int back, nback; | |
2590 int retval = FALSE; | |
2591 #ifdef FEAT_MBYTE | |
2592 int orig_col1, orig_col2; | |
2593 #endif | |
2594 | |
2595 /* Don't try to update when ScreenLines is not valid */ | |
2596 if (!screen_cleared || ScreenLines == NULL) | |
2597 return retval; | |
2598 | |
2599 /* Don't try to draw outside the shell! */ | |
2600 /* Check everything, strange values may be caused by a big border width */ | |
2601 col1 = check_col(col1); | |
2602 col2 = check_col(col2); | |
2603 row1 = check_row(row1); | |
2604 row2 = check_row(row2); | |
2605 | |
2606 /* Remember where our cursor was */ | |
2607 old_row = gui.row; | |
2608 old_col = gui.col; | |
2609 old_hl_mask = gui.highlight_mask; | |
2610 #ifdef FEAT_MBYTE | |
2611 orig_col1 = col1; | |
2612 orig_col2 = col2; | |
2613 #endif | |
2614 | |
2615 for (gui.row = row1; gui.row <= row2; gui.row++) | |
2616 { | |
2617 #ifdef FEAT_MBYTE | |
2618 /* When only half of a double-wide character is in the block, include | |
2619 * the other half. */ | |
2620 col1 = orig_col1; | |
2621 col2 = orig_col2; | |
2622 off = LineOffset[gui.row]; | |
2623 if (enc_dbcs != 0) | |
2624 { | |
2625 if (col1 > 0) | |
2626 col1 -= dbcs_screen_head_off(ScreenLines + off, | |
2627 ScreenLines + off + col1); | |
2628 col2 += dbcs_screen_tail_off(ScreenLines + off, | |
2629 ScreenLines + off + col2); | |
2630 } | |
2631 else if (enc_utf8) | |
2632 { | |
2633 if (ScreenLines[off + col1] == 0) | |
2634 --col1; | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
2635 # ifdef FEAT_GUI_GTK |
7 | 2636 if (col2 + 1 < Columns && ScreenLines[off + col2 + 1] == 0) |
2637 ++col2; | |
2638 # endif | |
2639 } | |
2640 #endif | |
2641 gui.col = col1; | |
2642 off = LineOffset[gui.row] + gui.col; | |
2643 len = col2 - col1 + 1; | |
2644 | |
2645 /* Find how many chars back this highlighting starts, or where a space | |
2646 * is. Needed for when the bold trick is used */ | |
2647 for (back = 0; back < col1; ++back) | |
2648 if (ScreenAttrs[off - 1 - back] != ScreenAttrs[off] | |
2649 || ScreenLines[off - 1 - back] == ' ') | |
2650 break; | |
2651 retval = (col1 > 0 && ScreenAttrs[off - 1] != 0 && back == 0 | |
2652 && ScreenLines[off - 1] != ' '); | |
2653 | |
2654 /* Break it up in strings of characters with the same attributes. */ | |
2655 /* Print UTF-8 characters individually. */ | |
2656 while (len > 0) | |
2657 { | |
2658 first_attr = ScreenAttrs[off]; | |
2659 gui.highlight_mask = first_attr; | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
2660 #if defined(FEAT_MBYTE) && !defined(FEAT_GUI_GTK) |
7 | 2661 if (enc_utf8 && ScreenLinesUC[off] != 0) |
2662 { | |
2663 /* output multi-byte character separately */ | |
2664 nback = gui_screenchar(off, flags, | |
2665 (guicolor_T)0, (guicolor_T)0, back); | |
2666 if (gui.col < Columns && ScreenLines[off + 1] == 0) | |
2667 idx = 2; | |
2668 else | |
2669 idx = 1; | |
2670 } | |
2671 else if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e) | |
2672 { | |
2673 /* output double-byte, single-width character separately */ | |
2674 nback = gui_screenchar(off, flags, | |
2675 (guicolor_T)0, (guicolor_T)0, back); | |
2676 idx = 1; | |
2677 } | |
2678 else | |
2679 #endif | |
2680 { | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
2681 #ifdef FEAT_GUI_GTK |
7 | 2682 for (idx = 0; idx < len; ++idx) |
2683 { | |
2684 if (enc_utf8 && ScreenLines[off + idx] == 0) | |
2685 continue; /* skip second half of double-width char */ | |
2686 if (ScreenAttrs[off + idx] != first_attr) | |
2687 break; | |
2688 } | |
2689 /* gui_screenstr() takes care of multibyte chars */ | |
2690 nback = gui_screenstr(off, idx, flags, | |
2691 (guicolor_T)0, (guicolor_T)0, back); | |
2692 #else | |
2693 for (idx = 0; idx < len && ScreenAttrs[off + idx] == first_attr; | |
2694 idx++) | |
2695 { | |
2696 # ifdef FEAT_MBYTE | |
2697 /* Stop at a multi-byte Unicode character. */ | |
2698 if (enc_utf8 && ScreenLinesUC[off + idx] != 0) | |
2699 break; | |
2700 if (enc_dbcs == DBCS_JPNU) | |
2701 { | |
2702 /* Stop at a double-byte single-width char. */ | |
2703 if (ScreenLines[off + idx] == 0x8e) | |
2704 break; | |
474 | 2705 if (len > 1 && (*mb_ptr2len)(ScreenLines |
7 | 2706 + off + idx) == 2) |
2707 ++idx; /* skip second byte of double-byte char */ | |
2708 } | |
2709 # endif | |
2710 } | |
2711 nback = gui_outstr_nowrap(ScreenLines + off, idx, flags, | |
2712 (guicolor_T)0, (guicolor_T)0, back); | |
2713 #endif | |
2714 } | |
2715 if (nback == FAIL) | |
2716 { | |
2717 /* Must back up to start drawing where a bold or italic word | |
2718 * starts. */ | |
2719 off -= back; | |
2720 len += back; | |
2721 gui.col -= back; | |
2722 } | |
2723 else | |
2724 { | |
2725 off += idx; | |
2726 len -= idx; | |
2727 } | |
2728 back = 0; | |
2729 } | |
2730 } | |
2731 | |
2732 /* Put the cursor back where it was */ | |
2733 gui.row = old_row; | |
2734 gui.col = old_col; | |
835 | 2735 gui.highlight_mask = (int)old_hl_mask; |
7 | 2736 |
2737 return retval; | |
2738 } | |
2739 | |
2740 static void | |
2741 gui_delete_lines(row, count) | |
2742 int row; | |
2743 int count; | |
2744 { | |
2745 if (count <= 0) | |
2746 return; | |
2747 | |
2748 if (row + count > gui.scroll_region_bot) | |
2749 /* Scrolled out of region, just blank the lines out */ | |
2750 gui_clear_block(row, gui.scroll_region_left, | |
2751 gui.scroll_region_bot, gui.scroll_region_right); | |
2752 else | |
2753 { | |
2754 gui_mch_delete_lines(row, count); | |
2755 | |
2756 /* If the cursor was in the deleted lines it's now gone. If the | |
2757 * cursor was in the scrolled lines adjust its position. */ | |
2758 if (gui.cursor_row >= row | |
2759 && gui.cursor_col >= gui.scroll_region_left | |
2760 && gui.cursor_col <= gui.scroll_region_right) | |
2761 { | |
2762 if (gui.cursor_row < row + count) | |
2763 gui.cursor_is_valid = FALSE; | |
2764 else if (gui.cursor_row <= gui.scroll_region_bot) | |
2765 gui.cursor_row -= count; | |
2766 } | |
2767 } | |
2768 } | |
2769 | |
2770 static void | |
2771 gui_insert_lines(row, count) | |
2772 int row; | |
2773 int count; | |
2774 { | |
2775 if (count <= 0) | |
2776 return; | |
2777 | |
2778 if (row + count > gui.scroll_region_bot) | |
2779 /* Scrolled out of region, just blank the lines out */ | |
2780 gui_clear_block(row, gui.scroll_region_left, | |
2781 gui.scroll_region_bot, gui.scroll_region_right); | |
2782 else | |
2783 { | |
2784 gui_mch_insert_lines(row, count); | |
2785 | |
2786 if (gui.cursor_row >= gui.row | |
2787 && gui.cursor_col >= gui.scroll_region_left | |
2788 && gui.cursor_col <= gui.scroll_region_right) | |
2789 { | |
2790 if (gui.cursor_row <= gui.scroll_region_bot - count) | |
2791 gui.cursor_row += count; | |
2792 else if (gui.cursor_row <= gui.scroll_region_bot) | |
2793 gui.cursor_is_valid = FALSE; | |
2794 } | |
2795 } | |
2796 } | |
2797 | |
2798 /* | |
2799 * The main GUI input routine. Waits for a character from the keyboard. | |
2800 * wtime == -1 Wait forever. | |
2801 * wtime == 0 Don't wait. | |
2802 * wtime > 0 Wait wtime milliseconds for a character. | |
2803 * Returns OK if a character was found to be available within the given time, | |
2804 * or FAIL otherwise. | |
2805 */ | |
2806 int | |
2807 gui_wait_for_chars(wtime) | |
2808 long wtime; | |
2809 { | |
2810 int retval; | |
2811 | |
2208
495995b9ce7d
Fix: window title not updated after file dropped.
Bram Moolenaar <bram@vim.org>
parents:
2178
diff
changeset
|
2812 #ifdef FEAT_MENU |
7 | 2813 /* |
2814 * If we're going to wait a bit, update the menus and mouse shape for the | |
2815 * current State. | |
2816 */ | |
2817 if (wtime != 0) | |
2818 gui_update_menus(0); | |
2819 #endif | |
2820 | |
2821 gui_mch_update(); | |
2822 if (input_available()) /* Got char, return immediately */ | |
2823 return OK; | |
2824 if (wtime == 0) /* Don't wait for char */ | |
2825 return FAIL; | |
2826 | |
2827 /* Before waiting, flush any output to the screen. */ | |
2828 gui_mch_flush(); | |
2829 | |
2830 if (wtime > 0) | |
2831 { | |
2832 /* Blink when waiting for a character. Probably only does something | |
2833 * for showmatch() */ | |
2834 gui_mch_start_blink(); | |
2835 retval = gui_mch_wait_for_chars(wtime); | |
2836 gui_mch_stop_blink(); | |
2837 return retval; | |
2838 } | |
2839 | |
2840 /* | |
1199 | 2841 * While we are waiting indefinitely for a character, blink the cursor. |
7 | 2842 */ |
2843 gui_mch_start_blink(); | |
2844 | |
203 | 2845 retval = FAIL; |
2846 /* | |
2847 * We may want to trigger the CursorHold event. First wait for | |
2848 * 'updatetime' and if nothing is typed within that time put the | |
2849 * K_CURSORHOLD key in the input buffer. | |
2850 */ | |
2851 if (gui_mch_wait_for_chars(p_ut) == OK) | |
2852 retval = OK; | |
7 | 2853 #ifdef FEAT_AUTOCMD |
609 | 2854 else if (trigger_cursorhold()) |
7 | 2855 { |
203 | 2856 char_u buf[3]; |
2857 | |
2858 /* Put K_CURSORHOLD in the input buffer. */ | |
2859 buf[0] = CSI; | |
2860 buf[1] = KS_EXTRA; | |
2861 buf[2] = (int)KE_CURSORHOLD; | |
2862 add_to_input_buf(buf, 3); | |
2863 | |
2864 retval = OK; | |
2865 } | |
2866 #endif | |
2867 | |
2868 if (retval == FAIL) | |
2869 { | |
2870 /* Blocking wait. */ | |
368 | 2871 before_blocking(); |
7 | 2872 retval = gui_mch_wait_for_chars(-1L); |
2873 } | |
2874 | |
2875 gui_mch_stop_blink(); | |
2876 return retval; | |
2877 } | |
2878 | |
2879 /* | |
1137 | 2880 * Fill p[4] with mouse coordinates encoded for check_termcode(). |
7 | 2881 */ |
2882 static void | |
2883 fill_mouse_coord(p, col, row) | |
2884 char_u *p; | |
2885 int col; | |
2886 int row; | |
2887 { | |
2888 p[0] = (char_u)(col / 128 + ' ' + 1); | |
2889 p[1] = (char_u)(col % 128 + ' ' + 1); | |
2890 p[2] = (char_u)(row / 128 + ' ' + 1); | |
2891 p[3] = (char_u)(row % 128 + ' ' + 1); | |
2892 } | |
2893 | |
2894 /* | |
2895 * Generic mouse support function. Add a mouse event to the input buffer with | |
2896 * the given properties. | |
2897 * button --- may be any of MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT, | |
2898 * MOUSE_X1, MOUSE_X2 | |
2899 * MOUSE_DRAG, or MOUSE_RELEASE. | |
2409
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
2900 * MOUSE_4 and MOUSE_5 are used for vertical scroll wheel, |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
2901 * MOUSE_6 and MOUSE_7 for horizontal scroll wheel. |
7 | 2902 * x, y --- Coordinates of mouse in pixels. |
2903 * repeated_click --- TRUE if this click comes only a short time after a | |
2904 * previous click. | |
2905 * modifiers --- Bit field which may be any of the following modifiers | |
2906 * or'ed together: MOUSE_SHIFT | MOUSE_CTRL | MOUSE_ALT. | |
2907 * This function will ignore drag events where the mouse has not moved to a new | |
2908 * character. | |
2909 */ | |
2910 void | |
2911 gui_send_mouse_event(button, x, y, repeated_click, modifiers) | |
2912 int button; | |
2913 int x; | |
2914 int y; | |
2915 int repeated_click; | |
2916 int_u modifiers; | |
2917 { | |
2918 static int prev_row = 0, prev_col = 0; | |
2919 static int prev_button = -1; | |
2920 static int num_clicks = 1; | |
2921 char_u string[10]; | |
2922 enum key_extra button_char; | |
2923 int row, col; | |
2924 #ifdef FEAT_CLIPBOARD | |
2925 int checkfor; | |
2926 int did_clip = FALSE; | |
2927 #endif | |
2928 | |
2929 /* | |
2930 * Scrolling may happen at any time, also while a selection is present. | |
2931 */ | |
2932 switch (button) | |
2933 { | |
2934 case MOUSE_X1: | |
2935 button_char = KE_X1MOUSE; | |
2936 goto button_set; | |
2937 case MOUSE_X2: | |
2938 button_char = KE_X2MOUSE; | |
2939 goto button_set; | |
2940 case MOUSE_4: | |
2941 button_char = KE_MOUSEDOWN; | |
2942 goto button_set; | |
2943 case MOUSE_5: | |
2944 button_char = KE_MOUSEUP; | |
2409
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
2945 goto button_set; |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
2946 case MOUSE_6: |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
2947 button_char = KE_MOUSELEFT; |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
2948 goto button_set; |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
2949 case MOUSE_7: |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
2950 button_char = KE_MOUSERIGHT; |
7 | 2951 button_set: |
2952 { | |
2953 /* Don't put events in the input queue now. */ | |
2954 if (hold_gui_events) | |
2955 return; | |
2956 | |
2957 string[3] = CSI; | |
2958 string[4] = KS_EXTRA; | |
2959 string[5] = (int)button_char; | |
2960 | |
2961 /* Pass the pointer coordinates of the scroll event so that we | |
2962 * know which window to scroll. */ | |
2963 row = gui_xy2colrow(x, y, &col); | |
2964 string[6] = (char_u)(col / 128 + ' ' + 1); | |
2965 string[7] = (char_u)(col % 128 + ' ' + 1); | |
2966 string[8] = (char_u)(row / 128 + ' ' + 1); | |
2967 string[9] = (char_u)(row % 128 + ' ' + 1); | |
2968 | |
2969 if (modifiers == 0) | |
2970 add_to_input_buf(string + 3, 7); | |
2971 else | |
2972 { | |
2973 string[0] = CSI; | |
2974 string[1] = KS_MODIFIER; | |
2975 string[2] = 0; | |
2976 if (modifiers & MOUSE_SHIFT) | |
2977 string[2] |= MOD_MASK_SHIFT; | |
2978 if (modifiers & MOUSE_CTRL) | |
2979 string[2] |= MOD_MASK_CTRL; | |
2980 if (modifiers & MOUSE_ALT) | |
2981 string[2] |= MOD_MASK_ALT; | |
2982 add_to_input_buf(string, 10); | |
2983 } | |
2984 return; | |
2985 } | |
2986 } | |
2987 | |
2988 #ifdef FEAT_CLIPBOARD | |
2989 /* If a clipboard selection is in progress, handle it */ | |
2990 if (clip_star.state == SELECT_IN_PROGRESS) | |
2991 { | |
2992 clip_process_selection(button, X_2_COL(x), Y_2_ROW(y), repeated_click); | |
2993 return; | |
2994 } | |
2995 | |
2996 /* Determine which mouse settings to look for based on the current mode */ | |
2997 switch (get_real_state()) | |
2998 { | |
2999 case NORMAL_BUSY: | |
3000 case OP_PENDING: | |
3001 case NORMAL: checkfor = MOUSE_NORMAL; break; | |
3002 case VISUAL: checkfor = MOUSE_VISUAL; break; | |
788 | 3003 case SELECTMODE: checkfor = MOUSE_VISUAL; break; |
7 | 3004 case REPLACE: |
3005 case REPLACE+LANGMAP: | |
3006 #ifdef FEAT_VREPLACE | |
3007 case VREPLACE: | |
3008 case VREPLACE+LANGMAP: | |
3009 #endif | |
3010 case INSERT: | |
3011 case INSERT+LANGMAP: checkfor = MOUSE_INSERT; break; | |
3012 case ASKMORE: | |
3013 case HITRETURN: /* At the more- and hit-enter prompt pass the | |
3014 mouse event for a click on or below the | |
3015 message line. */ | |
3016 if (Y_2_ROW(y) >= msg_row) | |
3017 checkfor = MOUSE_NORMAL; | |
3018 else | |
3019 checkfor = MOUSE_RETURN; | |
3020 break; | |
3021 | |
3022 /* | |
3023 * On the command line, use the clipboard selection on all lines | |
3024 * but the command line. But not when pasting. | |
3025 */ | |
3026 case CMDLINE: | |
3027 case CMDLINE+LANGMAP: | |
3028 if (Y_2_ROW(y) < cmdline_row && button != MOUSE_MIDDLE) | |
3029 checkfor = MOUSE_NONE; | |
3030 else | |
3031 checkfor = MOUSE_COMMAND; | |
3032 break; | |
3033 | |
3034 default: | |
3035 checkfor = MOUSE_NONE; | |
3036 break; | |
3037 }; | |
3038 | |
3039 /* | |
3040 * Allow clipboard selection of text on the command line in "normal" | |
3041 * modes. Don't do this when dragging the status line, or extending a | |
3042 * Visual selection. | |
3043 */ | |
3044 if ((State == NORMAL || State == NORMAL_BUSY || (State & INSERT)) | |
3045 && Y_2_ROW(y) >= topframe->fr_height | |
995 | 3046 # ifdef FEAT_WINDOWS |
3047 + firstwin->w_winrow | |
3048 # endif | |
7 | 3049 && button != MOUSE_DRAG |
3050 # ifdef FEAT_MOUSESHAPE | |
3051 && !drag_status_line | |
3052 # ifdef FEAT_VERTSPLIT | |
3053 && !drag_sep_line | |
3054 # endif | |
3055 # endif | |
3056 ) | |
3057 checkfor = MOUSE_NONE; | |
3058 | |
3059 /* | |
3060 * Use modeless selection when holding CTRL and SHIFT pressed. | |
3061 */ | |
3062 if ((modifiers & MOUSE_CTRL) && (modifiers & MOUSE_SHIFT)) | |
3063 checkfor = MOUSE_NONEF; | |
3064 | |
3065 /* | |
3066 * In Ex mode, always use modeless selection. | |
3067 */ | |
3068 if (exmode_active) | |
3069 checkfor = MOUSE_NONE; | |
3070 | |
3071 /* | |
3072 * If the mouse settings say to not use the mouse, use the modeless | |
3073 * selection. But if Visual is active, assume that only the Visual area | |
3074 * will be selected. | |
3075 * Exception: On the command line, both the selection is used and a mouse | |
3076 * key is send. | |
3077 */ | |
3078 if (!mouse_has(checkfor) || checkfor == MOUSE_COMMAND) | |
3079 { | |
3080 #ifdef FEAT_VISUAL | |
3081 /* Don't do modeless selection in Visual mode. */ | |
3082 if (checkfor != MOUSE_NONEF && VIsual_active && (State & NORMAL)) | |
3083 return; | |
3084 #endif | |
3085 | |
3086 /* | |
3087 * When 'mousemodel' is "popup", shift-left is translated to right. | |
3088 * But not when also using Ctrl. | |
3089 */ | |
3090 if (mouse_model_popup() && button == MOUSE_LEFT | |
3091 && (modifiers & MOUSE_SHIFT) && !(modifiers & MOUSE_CTRL)) | |
3092 { | |
3093 button = MOUSE_RIGHT; | |
3094 modifiers &= ~ MOUSE_SHIFT; | |
3095 } | |
3096 | |
3097 /* If the selection is done, allow the right button to extend it. | |
3098 * If the selection is cleared, allow the right button to start it | |
3099 * from the cursor position. */ | |
3100 if (button == MOUSE_RIGHT) | |
3101 { | |
3102 if (clip_star.state == SELECT_CLEARED) | |
3103 { | |
3104 if (State & CMDLINE) | |
3105 { | |
3106 col = msg_col; | |
3107 row = msg_row; | |
3108 } | |
3109 else | |
3110 { | |
3111 col = curwin->w_wcol; | |
3112 row = curwin->w_wrow + W_WINROW(curwin); | |
3113 } | |
3114 clip_start_selection(col, row, FALSE); | |
3115 } | |
3116 clip_process_selection(button, X_2_COL(x), Y_2_ROW(y), | |
3117 repeated_click); | |
3118 did_clip = TRUE; | |
3119 } | |
3120 /* Allow the left button to start the selection */ | |
2823 | 3121 else if (button == MOUSE_LEFT) |
7 | 3122 { |
3123 clip_start_selection(X_2_COL(x), Y_2_ROW(y), repeated_click); | |
3124 did_clip = TRUE; | |
3125 } | |
3126 | |
3127 /* Always allow pasting */ | |
3128 if (button != MOUSE_MIDDLE) | |
3129 { | |
3130 if (!mouse_has(checkfor) || button == MOUSE_RELEASE) | |
3131 return; | |
3132 if (checkfor != MOUSE_COMMAND) | |
3133 button = MOUSE_LEFT; | |
3134 } | |
3135 repeated_click = FALSE; | |
3136 } | |
3137 | |
3138 if (clip_star.state != SELECT_CLEARED && !did_clip) | |
3139 clip_clear_selection(); | |
3140 #endif | |
3141 | |
3142 /* Don't put events in the input queue now. */ | |
3143 if (hold_gui_events) | |
3144 return; | |
3145 | |
3146 row = gui_xy2colrow(x, y, &col); | |
3147 | |
3148 /* | |
3149 * If we are dragging and the mouse hasn't moved far enough to be on a | |
3150 * different character, then don't send an event to vim. | |
3151 */ | |
3152 if (button == MOUSE_DRAG) | |
3153 { | |
3154 if (row == prev_row && col == prev_col) | |
3155 return; | |
3156 /* Dragging above the window, set "row" to -1 to cause a scroll. */ | |
3157 if (y < 0) | |
3158 row = -1; | |
3159 } | |
3160 | |
3161 /* | |
3162 * If topline has changed (window scrolled) since the last click, reset | |
3163 * repeated_click, because we don't want starting Visual mode when | |
3164 * clicking on a different character in the text. | |
3165 */ | |
3166 if (curwin->w_topline != gui_prev_topline | |
3167 #ifdef FEAT_DIFF | |
3168 || curwin->w_topfill != gui_prev_topfill | |
3169 #endif | |
3170 ) | |
3171 repeated_click = FALSE; | |
3172 | |
3173 string[0] = CSI; /* this sequence is recognized by check_termcode() */ | |
3174 string[1] = KS_MOUSE; | |
3175 string[2] = KE_FILLER; | |
3176 if (button != MOUSE_DRAG && button != MOUSE_RELEASE) | |
3177 { | |
3178 if (repeated_click) | |
3179 { | |
3180 /* | |
3181 * Handle multiple clicks. They only count if the mouse is still | |
3182 * pointing at the same character. | |
3183 */ | |
3184 if (button != prev_button || row != prev_row || col != prev_col) | |
3185 num_clicks = 1; | |
3186 else if (++num_clicks > 4) | |
3187 num_clicks = 1; | |
3188 } | |
3189 else | |
3190 num_clicks = 1; | |
3191 prev_button = button; | |
3192 gui_prev_topline = curwin->w_topline; | |
3193 #ifdef FEAT_DIFF | |
3194 gui_prev_topfill = curwin->w_topfill; | |
3195 #endif | |
3196 | |
3197 string[3] = (char_u)(button | 0x20); | |
3198 SET_NUM_MOUSE_CLICKS(string[3], num_clicks); | |
3199 } | |
3200 else | |
3201 string[3] = (char_u)button; | |
3202 | |
3203 string[3] |= modifiers; | |
3204 fill_mouse_coord(string + 4, col, row); | |
3205 add_to_input_buf(string, 8); | |
3206 | |
3207 if (row < 0) | |
3208 prev_row = 0; | |
3209 else | |
3210 prev_row = row; | |
3211 prev_col = col; | |
3212 | |
3213 /* | |
3214 * We need to make sure this is cleared since Athena doesn't tell us when | |
3215 * he is done dragging. Neither does GTK+ 2 -- at least for now. | |
3216 */ | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
3217 #if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_GTK) |
7 | 3218 gui.dragged_sb = SBAR_NONE; |
3219 #endif | |
3220 } | |
3221 | |
3222 /* | |
3223 * Convert x and y coordinate to column and row in text window. | |
3224 * Corrects for multi-byte character. | |
3225 * returns column in "*colp" and row as return value; | |
3226 */ | |
3227 int | |
3228 gui_xy2colrow(x, y, colp) | |
3229 int x; | |
3230 int y; | |
3231 int *colp; | |
3232 { | |
3233 int col = check_col(X_2_COL(x)); | |
3234 int row = check_row(Y_2_ROW(y)); | |
3235 | |
3236 #ifdef FEAT_MBYTE | |
3237 *colp = mb_fix_col(col, row); | |
3238 #else | |
3239 *colp = col; | |
3240 #endif | |
3241 return row; | |
3242 } | |
3243 | |
3244 #if defined(FEAT_MENU) || defined(PROTO) | |
3245 /* | |
3246 * Callback function for when a menu entry has been selected. | |
3247 */ | |
3248 void | |
3249 gui_menu_cb(menu) | |
3250 vimmenu_T *menu; | |
3251 { | |
664 | 3252 char_u bytes[sizeof(long_u)]; |
7 | 3253 |
3254 /* Don't put events in the input queue now. */ | |
3255 if (hold_gui_events) | |
3256 return; | |
3257 | |
3258 bytes[0] = CSI; | |
3259 bytes[1] = KS_MENU; | |
3260 bytes[2] = KE_FILLER; | |
664 | 3261 add_to_input_buf(bytes, 3); |
3262 add_long_to_buf((long_u)menu, bytes); | |
3263 add_to_input_buf_csi(bytes, sizeof(long_u)); | |
7 | 3264 } |
3265 #endif | |
3266 | |
811 | 3267 static int prev_which_scrollbars[3]; |
669 | 3268 |
7 | 3269 /* |
3270 * Set which components are present. | |
685 | 3271 * If "oldval" is not NULL, "oldval" is the previous value, the new value is |
7 | 3272 * in p_go. |
3273 */ | |
3274 void | |
3275 gui_init_which_components(oldval) | |
1887 | 3276 char_u *oldval UNUSED; |
7 | 3277 { |
3278 #ifdef FEAT_MENU | |
3279 static int prev_menu_is_active = -1; | |
3280 #endif | |
3281 #ifdef FEAT_TOOLBAR | |
3282 static int prev_toolbar = -1; | |
3283 int using_toolbar = FALSE; | |
3284 #endif | |
685 | 3285 #ifdef FEAT_GUI_TABLINE |
3286 int using_tabline; | |
3287 #endif | |
7 | 3288 #ifdef FEAT_FOOTER |
3289 static int prev_footer = -1; | |
3290 int using_footer = FALSE; | |
3291 #endif | |
3292 #if defined(FEAT_MENU) && !defined(WIN16) | |
3293 static int prev_tearoff = -1; | |
3294 int using_tearoff = FALSE; | |
3295 #endif | |
3296 | |
3297 char_u *p; | |
3298 int i; | |
3299 #ifdef FEAT_MENU | |
3300 int grey_old, grey_new; | |
3301 char_u *temp; | |
3302 #endif | |
3303 win_T *wp; | |
3304 int need_set_size; | |
3305 int fix_size; | |
3306 | |
3307 #ifdef FEAT_MENU | |
3308 if (oldval != NULL && gui.in_use) | |
3309 { | |
3310 /* | |
3311 * Check if the menu's go from grey to non-grey or vise versa. | |
3312 */ | |
3313 grey_old = (vim_strchr(oldval, GO_GREY) != NULL); | |
3314 grey_new = (vim_strchr(p_go, GO_GREY) != NULL); | |
3315 if (grey_old != grey_new) | |
3316 { | |
3317 temp = p_go; | |
3318 p_go = oldval; | |
3319 gui_update_menus(MENU_ALL_MODES); | |
3320 p_go = temp; | |
3321 } | |
3322 } | |
3323 gui.menu_is_active = FALSE; | |
3324 #endif | |
3325 | |
3326 for (i = 0; i < 3; i++) | |
3327 gui.which_scrollbars[i] = FALSE; | |
3328 for (p = p_go; *p; p++) | |
3329 switch (*p) | |
3330 { | |
3331 case GO_LEFT: | |
3332 gui.which_scrollbars[SBAR_LEFT] = TRUE; | |
3333 break; | |
3334 case GO_RIGHT: | |
3335 gui.which_scrollbars[SBAR_RIGHT] = TRUE; | |
3336 break; | |
3337 #ifdef FEAT_VERTSPLIT | |
3338 case GO_VLEFT: | |
3339 if (win_hasvertsplit()) | |
3340 gui.which_scrollbars[SBAR_LEFT] = TRUE; | |
3341 break; | |
3342 case GO_VRIGHT: | |
3343 if (win_hasvertsplit()) | |
3344 gui.which_scrollbars[SBAR_RIGHT] = TRUE; | |
3345 break; | |
3346 #endif | |
3347 case GO_BOT: | |
3348 gui.which_scrollbars[SBAR_BOTTOM] = TRUE; | |
3349 break; | |
3350 #ifdef FEAT_MENU | |
3351 case GO_MENUS: | |
3352 gui.menu_is_active = TRUE; | |
3353 break; | |
3354 #endif | |
3355 case GO_GREY: | |
3356 /* make menu's have grey items, ignored here */ | |
3357 break; | |
3358 #ifdef FEAT_TOOLBAR | |
3359 case GO_TOOLBAR: | |
3360 using_toolbar = TRUE; | |
3361 break; | |
3362 #endif | |
3363 #ifdef FEAT_FOOTER | |
3364 case GO_FOOTER: | |
3365 using_footer = TRUE; | |
3366 break; | |
3367 #endif | |
3368 case GO_TEAROFF: | |
3369 #if defined(FEAT_MENU) && !defined(WIN16) | |
3370 using_tearoff = TRUE; | |
3371 #endif | |
3372 break; | |
3373 default: | |
3374 /* Ignore options that are not supported */ | |
3375 break; | |
3376 } | |
685 | 3377 |
7 | 3378 if (gui.in_use) |
3379 { | |
811 | 3380 need_set_size = 0; |
7 | 3381 fix_size = FALSE; |
685 | 3382 |
3383 #ifdef FEAT_GUI_TABLINE | |
687 | 3384 /* Update the GUI tab line, it may appear or disappear. This may |
3385 * cause the non-GUI tab line to disappear or appear. */ | |
685 | 3386 using_tabline = gui_has_tabline(); |
706 | 3387 if (!gui_mch_showing_tabline() != !using_tabline) |
685 | 3388 { |
797 | 3389 /* We don't want a resize event change "Rows" here, save and |
3390 * restore it. Resizing is handled below. */ | |
3391 i = Rows; | |
685 | 3392 gui_update_tabline(); |
797 | 3393 Rows = i; |
1767 | 3394 need_set_size |= RESIZE_VERT; |
685 | 3395 if (using_tabline) |
3396 fix_size = TRUE; | |
3397 if (!gui_use_tabline()) | |
3398 redraw_tabline = TRUE; /* may draw non-GUI tab line */ | |
3399 } | |
3400 #endif | |
3401 | |
7 | 3402 for (i = 0; i < 3; i++) |
3403 { | |
811 | 3404 /* The scrollbar needs to be updated when it is shown/unshown and |
3405 * when switching tab pages. But the size only changes when it's | |
3406 * shown/unshown. Thus we need two places to remember whether a | |
3407 * scrollbar is there or not. */ | |
3408 if (gui.which_scrollbars[i] != prev_which_scrollbars[i] | |
788 | 3409 #ifdef FEAT_WINDOWS |
811 | 3410 || gui.which_scrollbars[i] |
3411 != curtab->tp_prev_which_scrollbars[i] | |
788 | 3412 #endif |
3413 ) | |
7 | 3414 { |
3415 if (i == SBAR_BOTTOM) | |
3416 gui_mch_enable_scrollbar(&gui.bottom_sbar, | |
3417 gui.which_scrollbars[i]); | |
3418 else | |
3419 { | |
3420 FOR_ALL_WINDOWS(wp) | |
3421 { | |
3422 gui_do_scrollbar(wp, i, gui.which_scrollbars[i]); | |
3423 } | |
3424 } | |
811 | 3425 if (gui.which_scrollbars[i] != prev_which_scrollbars[i]) |
3426 { | |
3427 if (i == SBAR_BOTTOM) | |
1767 | 3428 need_set_size |= RESIZE_VERT; |
811 | 3429 else |
1767 | 3430 need_set_size |= RESIZE_HOR; |
811 | 3431 if (gui.which_scrollbars[i]) |
3432 fix_size = TRUE; | |
3433 } | |
7 | 3434 } |
788 | 3435 #ifdef FEAT_WINDOWS |
811 | 3436 curtab->tp_prev_which_scrollbars[i] = gui.which_scrollbars[i]; |
788 | 3437 #endif |
811 | 3438 prev_which_scrollbars[i] = gui.which_scrollbars[i]; |
7 | 3439 } |
3440 | |
3441 #ifdef FEAT_MENU | |
3442 if (gui.menu_is_active != prev_menu_is_active) | |
3443 { | |
3444 /* We don't want a resize event change "Rows" here, save and | |
3445 * restore it. Resizing is handled below. */ | |
3446 i = Rows; | |
3447 gui_mch_enable_menu(gui.menu_is_active); | |
3448 Rows = i; | |
3449 prev_menu_is_active = gui.menu_is_active; | |
1767 | 3450 need_set_size |= RESIZE_VERT; |
7 | 3451 if (gui.menu_is_active) |
3452 fix_size = TRUE; | |
3453 } | |
3454 #endif | |
3455 | |
3456 #ifdef FEAT_TOOLBAR | |
3457 if (using_toolbar != prev_toolbar) | |
3458 { | |
3459 gui_mch_show_toolbar(using_toolbar); | |
3460 prev_toolbar = using_toolbar; | |
1767 | 3461 need_set_size |= RESIZE_VERT; |
7 | 3462 if (using_toolbar) |
3463 fix_size = TRUE; | |
3464 } | |
3465 #endif | |
3466 #ifdef FEAT_FOOTER | |
3467 if (using_footer != prev_footer) | |
3468 { | |
3469 gui_mch_enable_footer(using_footer); | |
3470 prev_footer = using_footer; | |
1767 | 3471 need_set_size |= RESIZE_VERT; |
7 | 3472 if (using_footer) |
3473 fix_size = TRUE; | |
3474 } | |
3475 #endif | |
3476 #if defined(FEAT_MENU) && !defined(WIN16) && !(defined(WIN3264) && !defined(FEAT_TEAROFF)) | |
3477 if (using_tearoff != prev_tearoff) | |
3478 { | |
3479 gui_mch_toggle_tearoffs(using_tearoff); | |
3480 prev_tearoff = using_tearoff; | |
3481 } | |
3482 #endif | |
1767 | 3483 if (need_set_size != 0) |
276 | 3484 { |
3485 #ifdef FEAT_GUI_GTK | |
1767 | 3486 long prev_Columns = Columns; |
3487 long prev_Rows = Rows; | |
276 | 3488 #endif |
7 | 3489 /* Adjust the size of the window to make the text area keep the |
3490 * same size and to avoid that part of our window is off-screen | |
3491 * and a scrollbar can't be used, for example. */ | |
811 | 3492 gui_set_shellsize(FALSE, fix_size, need_set_size); |
276 | 3493 |
3494 #ifdef FEAT_GUI_GTK | |
3495 /* GTK has the annoying habit of sending us resize events when | |
3496 * changing the window size ourselves. This mostly happens when | |
3497 * waiting for a character to arrive, quite unpredictably, and may | |
3498 * change Columns and Rows when we don't want it. Wait for a | |
3499 * character here to avoid this effect. | |
3500 * If you remove this, please test this command for resizing | |
292 | 3501 * effects (with optional left scrollbar): ":vsp|q|vsp|q|vsp|q". |
687 | 3502 * Don't do this while starting up though. |
1767 | 3503 * Don't change Rows when adding menu/toolbar/tabline. |
3504 * Don't change Columns when adding vertical toolbar. */ | |
3505 if (!gui.starting && need_set_size != (RESIZE_VERT | RESIZE_HOR)) | |
287 | 3506 (void)char_avail(); |
1767 | 3507 if ((need_set_size & RESIZE_VERT) == 0) |
3508 Rows = prev_Rows; | |
3509 if ((need_set_size & RESIZE_HOR) == 0) | |
3510 Columns = prev_Columns; | |
276 | 3511 #endif |
3512 } | |
687 | 3513 #ifdef FEAT_WINDOWS |
3514 /* When the console tabline appears or disappears the window positions | |
3515 * change. */ | |
3516 if (firstwin->w_winrow != tabline_height()) | |
3517 shell_new_rows(); /* recompute window positions and heights */ | |
3518 #endif | |
7 | 3519 } |
3520 } | |
3521 | |
685 | 3522 #if defined(FEAT_GUI_TABLINE) || defined(PROTO) |
3523 /* | |
3524 * Return TRUE if the GUI is taking care of the tabline. | |
3525 * It may still be hidden if 'showtabline' is zero. | |
3526 */ | |
3527 int | |
3528 gui_use_tabline() | |
3529 { | |
3530 return gui.in_use && vim_strchr(p_go, GO_TABLINE) != NULL; | |
3531 } | |
3532 | |
3533 /* | |
3534 * Return TRUE if the GUI is showing the tabline. | |
3535 * This uses 'showtabline'. | |
3536 */ | |
3537 static int | |
3538 gui_has_tabline() | |
3539 { | |
3540 if (!gui_use_tabline() | |
3541 || p_stal == 0 | |
3542 || (p_stal == 1 && first_tabpage->tp_next == NULL)) | |
3543 return FALSE; | |
3544 return TRUE; | |
3545 } | |
3546 | |
3547 /* | |
3548 * Update the tabline. | |
3549 * This may display/undisplay the tabline and update the labels. | |
3550 */ | |
3551 void | |
3552 gui_update_tabline() | |
3553 { | |
3554 int showit = gui_has_tabline(); | |
797 | 3555 int shown = gui_mch_showing_tabline(); |
685 | 3556 |
3557 if (!gui.starting && starting == 0) | |
3558 { | |
848 | 3559 /* Updating the tabline uses direct GUI commands, flush |
3560 * outstanding instructions first. (esp. clear screen) */ | |
3561 out_flush(); | |
3562 gui_mch_flush(); | |
3563 | |
797 | 3564 if (!showit != !shown) |
3565 gui_mch_show_tabline(showit); | |
685 | 3566 if (showit != 0) |
3567 gui_mch_update_tabline(); | |
797 | 3568 |
3569 /* When the tabs change from hidden to shown or from shown to | |
3570 * hidden the size of the text area should remain the same. */ | |
3571 if (!showit != !shown) | |
811 | 3572 gui_set_shellsize(FALSE, showit, RESIZE_VERT); |
685 | 3573 } |
3574 } | |
3575 | |
3576 /* | |
839 | 3577 * Get the label or tooltip for tab page "tp" into NameBuff[]. |
685 | 3578 */ |
3579 void | |
839 | 3580 get_tabline_label(tp, tooltip) |
685 | 3581 tabpage_T *tp; |
839 | 3582 int tooltip; /* TRUE: get tooltip */ |
685 | 3583 { |
3584 int modified = FALSE; | |
3585 char_u buf[40]; | |
3586 int wincount; | |
3587 win_T *wp; | |
857 | 3588 char_u **opt; |
839 | 3589 |
3590 /* Use 'guitablabel' or 'guitabtooltip' if it's set. */ | |
857 | 3591 opt = (tooltip ? &p_gtt : &p_gtl); |
3592 if (**opt != NUL) | |
685 | 3593 { |
687 | 3594 int use_sandbox = FALSE; |
3595 int save_called_emsg = called_emsg; | |
3596 char_u res[MAXPATHL]; | |
706 | 3597 tabpage_T *save_curtab; |
839 | 3598 char_u *opt_name = (char_u *)(tooltip ? "guitabtooltip" |
3599 : "guitablabel"); | |
687 | 3600 |
3601 called_emsg = FALSE; | |
3602 | |
3603 printer_page_num = tabpage_index(tp); | |
3604 # ifdef FEAT_EVAL | |
3605 set_vim_var_nr(VV_LNUM, printer_page_num); | |
839 | 3606 use_sandbox = was_set_insecurely(opt_name, 0); |
687 | 3607 # endif |
706 | 3608 /* It's almost as going to the tabpage, but without autocommands. */ |
3609 curtab->tp_firstwin = firstwin; | |
3610 curtab->tp_lastwin = lastwin; | |
3611 curtab->tp_curwin = curwin; | |
3612 save_curtab = curtab; | |
3613 curtab = tp; | |
3614 topframe = curtab->tp_topframe; | |
3615 firstwin = curtab->tp_firstwin; | |
3616 lastwin = curtab->tp_lastwin; | |
3617 curwin = curtab->tp_curwin; | |
3618 curbuf = curwin->w_buffer; | |
3619 | |
687 | 3620 /* Can't use NameBuff directly, build_stl_str_hl() uses it. */ |
857 | 3621 build_stl_str_hl(curwin, res, MAXPATHL, *opt, use_sandbox, |
706 | 3622 0, (int)Columns, NULL, NULL); |
687 | 3623 STRCPY(NameBuff, res); |
3624 | |
706 | 3625 /* Back to the original curtab. */ |
3626 curtab = save_curtab; | |
3627 topframe = curtab->tp_topframe; | |
3628 firstwin = curtab->tp_firstwin; | |
3629 lastwin = curtab->tp_lastwin; | |
3630 curwin = curtab->tp_curwin; | |
3631 curbuf = curwin->w_buffer; | |
3632 | |
687 | 3633 if (called_emsg) |
839 | 3634 set_string_option_direct(opt_name, -1, |
694 | 3635 (char_u *)"", OPT_FREE, SID_ERROR); |
687 | 3636 called_emsg |= save_called_emsg; |
3637 } | |
857 | 3638 |
3639 /* If 'guitablabel'/'guitabtooltip' is not set or the result is empty then | |
3640 * use a default label. */ | |
3641 if (**opt == NUL || *NameBuff == NUL) | |
687 | 3642 { |
819 | 3643 /* Get the buffer name into NameBuff[] and shorten it. */ |
687 | 3644 get_trans_bufname(tp == curtab ? curbuf : tp->tp_curwin->w_buffer); |
839 | 3645 if (!tooltip) |
3646 shorten_dir(NameBuff); | |
687 | 3647 |
3648 wp = (tp == curtab) ? firstwin : tp->tp_firstwin; | |
3649 for (wincount = 0; wp != NULL; wp = wp->w_next, ++wincount) | |
3650 if (bufIsChanged(wp->w_buffer)) | |
3651 modified = TRUE; | |
3652 if (modified || wincount > 1) | |
3653 { | |
3654 if (wincount > 1) | |
3655 vim_snprintf((char *)buf, sizeof(buf), "%d", wincount); | |
3656 else | |
3657 buf[0] = NUL; | |
3658 if (modified) | |
3659 STRCAT(buf, "+"); | |
3660 STRCAT(buf, " "); | |
1620 | 3661 STRMOVE(NameBuff + STRLEN(buf), NameBuff); |
687 | 3662 mch_memmove(NameBuff, buf, STRLEN(buf)); |
3663 } | |
685 | 3664 } |
3665 } | |
3666 | |
691 | 3667 /* |
3668 * Send the event for clicking to select tab page "nr". | |
3669 * Returns TRUE if it was done, FALSE when skipped because we are already at | |
838 | 3670 * that tab page or the cmdline window is open. |
691 | 3671 */ |
3672 int | |
3673 send_tabline_event(nr) | |
3674 int nr; | |
3675 { | |
3676 char_u string[3]; | |
3677 | |
3678 if (nr == tabpage_index(curtab)) | |
3679 return FALSE; | |
844 | 3680 |
3681 /* Don't put events in the input queue now. */ | |
3682 if (hold_gui_events | |
838 | 3683 # ifdef FEAT_CMDWIN |
844 | 3684 || cmdwin_type != 0 |
3685 # endif | |
3686 ) | |
838 | 3687 { |
3688 /* Set it back to the current tab page. */ | |
3689 gui_mch_set_curtab(tabpage_index(curtab)); | |
3690 return FALSE; | |
3691 } | |
844 | 3692 |
691 | 3693 string[0] = CSI; |
3694 string[1] = KS_TABLINE; | |
3695 string[2] = KE_FILLER; | |
3696 add_to_input_buf(string, 3); | |
3697 string[0] = nr; | |
3698 add_to_input_buf_csi(string, 1); | |
3699 return TRUE; | |
3700 } | |
3701 | |
824 | 3702 /* |
3703 * Send a tabline menu event | |
3704 */ | |
3705 void | |
3706 send_tabline_menu_event(tabidx, event) | |
3707 int tabidx; | |
3708 int event; | |
3709 { | |
3710 char_u string[3]; | |
3711 | |
844 | 3712 /* Don't put events in the input queue now. */ |
3713 if (hold_gui_events) | |
3714 return; | |
3715 | |
824 | 3716 string[0] = CSI; |
3717 string[1] = KS_TABMENU; | |
3718 string[2] = KE_FILLER; | |
3719 add_to_input_buf(string, 3); | |
3720 string[0] = tabidx; | |
3721 string[1] = (char_u)(long)event; | |
3722 add_to_input_buf_csi(string, 2); | |
3723 } | |
3724 | |
685 | 3725 #endif |
7 | 3726 |
3727 /* | |
3728 * Scrollbar stuff: | |
3729 */ | |
3730 | |
669 | 3731 #if defined(FEAT_WINDOWS) || defined(PROTO) |
3732 /* | |
3733 * Remove all scrollbars. Used before switching to another tab page. | |
3734 */ | |
3735 void | |
3736 gui_remove_scrollbars() | |
3737 { | |
3738 int i; | |
3739 win_T *wp; | |
3740 | |
3741 for (i = 0; i < 3; i++) | |
3742 { | |
3743 if (i == SBAR_BOTTOM) | |
3744 gui_mch_enable_scrollbar(&gui.bottom_sbar, FALSE); | |
3745 else | |
3746 { | |
3747 FOR_ALL_WINDOWS(wp) | |
3748 { | |
3749 gui_do_scrollbar(wp, i, FALSE); | |
3750 } | |
3751 } | |
788 | 3752 curtab->tp_prev_which_scrollbars[i] = -1; |
669 | 3753 } |
3754 } | |
3755 #endif | |
3756 | |
7 | 3757 void |
3758 gui_create_scrollbar(sb, type, wp) | |
3759 scrollbar_T *sb; | |
3760 int type; | |
3761 win_T *wp; | |
3762 { | |
3763 static int sbar_ident = 0; | |
3764 | |
3765 sb->ident = sbar_ident++; /* No check for too big, but would it happen? */ | |
3766 sb->wp = wp; | |
3767 sb->type = type; | |
3768 sb->value = 0; | |
3769 #ifdef FEAT_GUI_ATHENA | |
3770 sb->pixval = 0; | |
3771 #endif | |
3772 sb->size = 1; | |
3773 sb->max = 1; | |
3774 sb->top = 0; | |
3775 sb->height = 0; | |
3776 #ifdef FEAT_VERTSPLIT | |
3777 sb->width = 0; | |
3778 #endif | |
3779 sb->status_height = 0; | |
3780 gui_mch_create_scrollbar(sb, (wp == NULL) ? SBAR_HORIZ : SBAR_VERT); | |
3781 } | |
3782 | |
3783 /* | |
3784 * Find the scrollbar with the given index. | |
3785 */ | |
3786 scrollbar_T * | |
3787 gui_find_scrollbar(ident) | |
3788 long ident; | |
3789 { | |
3790 win_T *wp; | |
3791 | |
3792 if (gui.bottom_sbar.ident == ident) | |
3793 return &gui.bottom_sbar; | |
3794 FOR_ALL_WINDOWS(wp) | |
3795 { | |
3796 if (wp->w_scrollbars[SBAR_LEFT].ident == ident) | |
3797 return &wp->w_scrollbars[SBAR_LEFT]; | |
3798 if (wp->w_scrollbars[SBAR_RIGHT].ident == ident) | |
3799 return &wp->w_scrollbars[SBAR_RIGHT]; | |
3800 } | |
3801 return NULL; | |
3802 } | |
3803 | |
3804 /* | |
3805 * For most systems: Put a code in the input buffer for a dragged scrollbar. | |
3806 * | |
3807 * For Win32, Macintosh and GTK+ 2: | |
3808 * Scrollbars seem to grab focus and vim doesn't read the input queue until | |
3809 * you stop dragging the scrollbar. We get here each time the scrollbar is | |
3810 * dragged another pixel, but as far as the rest of vim goes, it thinks | |
3811 * we're just hanging in the call to DispatchMessage() in | |
3812 * process_message(). The DispatchMessage() call that hangs was passed a | |
3813 * mouse button click event in the scrollbar window. -- webb. | |
3814 * | |
3815 * Solution: Do the scrolling right here. But only when allowed. | |
3816 * Ignore the scrollbars while executing an external command or when there | |
3817 * are still characters to be processed. | |
3818 */ | |
3819 void | |
3820 gui_drag_scrollbar(sb, value, still_dragging) | |
3821 scrollbar_T *sb; | |
3822 long value; | |
3823 int still_dragging; | |
3824 { | |
3825 #ifdef FEAT_WINDOWS | |
3826 win_T *wp; | |
3827 #endif | |
3828 int sb_num; | |
3829 #ifdef USE_ON_FLY_SCROLL | |
3830 colnr_T old_leftcol = curwin->w_leftcol; | |
3831 # ifdef FEAT_SCROLLBIND | |
3832 linenr_T old_topline = curwin->w_topline; | |
3833 # endif | |
3834 # ifdef FEAT_DIFF | |
3835 int old_topfill = curwin->w_topfill; | |
3836 # endif | |
3837 #else | |
664 | 3838 char_u bytes[sizeof(long_u)]; |
7 | 3839 int byte_count; |
3840 #endif | |
3841 | |
3842 if (sb == NULL) | |
3843 return; | |
3844 | |
3845 /* Don't put events in the input queue now. */ | |
3846 if (hold_gui_events) | |
3847 return; | |
3848 | |
3849 #ifdef FEAT_CMDWIN | |
3850 if (cmdwin_type != 0 && sb->wp != curwin) | |
3851 return; | |
3852 #endif | |
3853 | |
3854 if (still_dragging) | |
3855 { | |
3856 if (sb->wp == NULL) | |
3857 gui.dragged_sb = SBAR_BOTTOM; | |
3858 else if (sb == &sb->wp->w_scrollbars[SBAR_LEFT]) | |
3859 gui.dragged_sb = SBAR_LEFT; | |
3860 else | |
3861 gui.dragged_sb = SBAR_RIGHT; | |
3862 gui.dragged_wp = sb->wp; | |
3863 } | |
3864 else | |
3865 { | |
3866 gui.dragged_sb = SBAR_NONE; | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
3867 #ifdef FEAT_GUI_GTK |
7 | 3868 /* Keep the "dragged_wp" value until after the scrolling, for when the |
3869 * moust button is released. GTK2 doesn't send the button-up event. */ | |
3870 gui.dragged_wp = NULL; | |
3871 #endif | |
3872 } | |
3873 | |
3874 /* Vertical sbar info is kept in the first sbar (the left one) */ | |
3875 if (sb->wp != NULL) | |
3876 sb = &sb->wp->w_scrollbars[0]; | |
3877 | |
3878 /* | |
3879 * Check validity of value | |
3880 */ | |
3881 if (value < 0) | |
3882 value = 0; | |
3883 #ifdef SCROLL_PAST_END | |
3884 else if (value > sb->max) | |
3885 value = sb->max; | |
3886 #else | |
3887 if (value > sb->max - sb->size + 1) | |
3888 value = sb->max - sb->size + 1; | |
3889 #endif | |
3890 | |
3891 sb->value = value; | |
3892 | |
3893 #ifdef USE_ON_FLY_SCROLL | |
1476 | 3894 /* When not allowed to do the scrolling right now, return. |
3895 * This also checked input_available(), but that causes the first click in | |
3896 * a scrollbar to be ignored when Vim doesn't have focus. */ | |
3897 if (dont_scroll) | |
7 | 3898 return; |
3899 #endif | |
973 | 3900 #ifdef FEAT_INS_EXPAND |
3901 /* Disallow scrolling the current window when the completion popup menu is | |
3902 * visible. */ | |
3903 if ((sb->wp == NULL || sb->wp == curwin) && pum_visible()) | |
3904 return; | |
3905 #endif | |
7 | 3906 |
3907 #ifdef FEAT_RIGHTLEFT | |
3908 if (sb->wp == NULL && curwin->w_p_rl) | |
3909 { | |
3910 value = sb->max + 1 - sb->size - value; | |
3911 if (value < 0) | |
3912 value = 0; | |
3913 } | |
3914 #endif | |
3915 | |
3916 if (sb->wp != NULL) /* vertical scrollbar */ | |
3917 { | |
3918 sb_num = 0; | |
3919 #ifdef FEAT_WINDOWS | |
3920 for (wp = firstwin; wp != sb->wp && wp != NULL; wp = wp->w_next) | |
3921 sb_num++; | |
3922 if (wp == NULL) | |
3923 return; | |
3924 #else | |
3925 if (sb->wp != curwin) | |
3926 return; | |
3927 #endif | |
3928 | |
3929 #ifdef USE_ON_FLY_SCROLL | |
3930 current_scrollbar = sb_num; | |
3931 scrollbar_value = value; | |
3932 if (State & NORMAL) | |
3933 { | |
3934 gui_do_scroll(); | |
3935 setcursor(); | |
3936 } | |
3937 else if (State & INSERT) | |
3938 { | |
3939 ins_scroll(); | |
3940 setcursor(); | |
3941 } | |
3942 else if (State & CMDLINE) | |
3943 { | |
3944 if (msg_scrolled == 0) | |
3945 { | |
3946 gui_do_scroll(); | |
3947 redrawcmdline(); | |
3948 } | |
3949 } | |
3950 # ifdef FEAT_FOLDING | |
3951 /* Value may have been changed for closed fold. */ | |
3952 sb->value = sb->wp->w_topline - 1; | |
3953 # endif | |
788 | 3954 |
3955 /* When dragging one scrollbar and there is another one at the other | |
3956 * side move the thumb of that one too. */ | |
3957 if (gui.which_scrollbars[SBAR_RIGHT] && gui.which_scrollbars[SBAR_LEFT]) | |
3958 gui_mch_set_scrollbar_thumb( | |
3959 &sb->wp->w_scrollbars[ | |
3960 sb == &sb->wp->w_scrollbars[SBAR_RIGHT] | |
3961 ? SBAR_LEFT : SBAR_RIGHT], | |
3962 sb->value, sb->size, sb->max); | |
3963 | |
7 | 3964 #else |
3965 bytes[0] = CSI; | |
3966 bytes[1] = KS_VER_SCROLLBAR; | |
3967 bytes[2] = KE_FILLER; | |
3968 bytes[3] = (char_u)sb_num; | |
3969 byte_count = 4; | |
3970 #endif | |
3971 } | |
3972 else | |
3973 { | |
3974 #ifdef USE_ON_FLY_SCROLL | |
3975 scrollbar_value = value; | |
3976 | |
3977 if (State & NORMAL) | |
2409
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
3978 gui_do_horiz_scroll(scrollbar_value, FALSE); |
7 | 3979 else if (State & INSERT) |
3980 ins_horscroll(); | |
3981 else if (State & CMDLINE) | |
3982 { | |
540 | 3983 if (msg_scrolled == 0) |
7 | 3984 { |
2409
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
3985 gui_do_horiz_scroll(scrollbar_value, FALSE); |
7 | 3986 redrawcmdline(); |
3987 } | |
3988 } | |
3989 if (old_leftcol != curwin->w_leftcol) | |
3990 { | |
3991 updateWindow(curwin); /* update window, status and cmdline */ | |
3992 setcursor(); | |
3993 } | |
3994 #else | |
3995 bytes[0] = CSI; | |
3996 bytes[1] = KS_HOR_SCROLLBAR; | |
3997 bytes[2] = KE_FILLER; | |
3998 byte_count = 3; | |
3999 #endif | |
4000 } | |
4001 | |
4002 #ifdef USE_ON_FLY_SCROLL | |
4003 # ifdef FEAT_SCROLLBIND | |
4004 /* | |
4005 * synchronize other windows, as necessary according to 'scrollbind' | |
4006 */ | |
4007 if (curwin->w_p_scb | |
4008 && ((sb->wp == NULL && curwin->w_leftcol != old_leftcol) | |
4009 || (sb->wp == curwin && (curwin->w_topline != old_topline | |
4010 # ifdef FEAT_DIFF | |
4011 || curwin->w_topfill != old_topfill | |
4012 # endif | |
4013 )))) | |
4014 { | |
4015 do_check_scrollbind(TRUE); | |
4016 /* need to update the window right here */ | |
4017 for (wp = firstwin; wp != NULL; wp = wp->w_next) | |
4018 if (wp->w_redr_type > 0) | |
4019 updateWindow(wp); | |
4020 setcursor(); | |
4021 } | |
4022 # endif | |
4023 out_flush(); | |
4024 gui_update_cursor(FALSE, TRUE); | |
4025 #else | |
664 | 4026 add_to_input_buf(bytes, byte_count); |
4027 add_long_to_buf((long_u)value, bytes); | |
4028 add_to_input_buf_csi(bytes, sizeof(long_u)); | |
7 | 4029 #endif |
4030 } | |
4031 | |
4032 /* | |
4033 * Scrollbar stuff: | |
4034 */ | |
4035 | |
2237
770485470e59
Add a few #ifdefs to exclude functions that are not used. (Domnique Pelle)
Bram Moolenaar <bram@vim.org>
parents:
2210
diff
changeset
|
4036 #if defined(FEAT_AUTOCMD) || defined(FEAT_WINDOWS) || defined(PROTO) |
1906 | 4037 /* |
4038 * Called when something in the window layout has changed. | |
4039 */ | |
4040 void | |
4041 gui_may_update_scrollbars() | |
4042 { | |
4043 if (gui.in_use && starting == 0) | |
4044 { | |
4045 out_flush(); | |
4046 gui_init_which_components(NULL); | |
4047 gui_update_scrollbars(TRUE); | |
4048 } | |
4049 need_mouse_correct = TRUE; | |
4050 } | |
2237
770485470e59
Add a few #ifdefs to exclude functions that are not used. (Domnique Pelle)
Bram Moolenaar <bram@vim.org>
parents:
2210
diff
changeset
|
4051 #endif |
1906 | 4052 |
7 | 4053 void |
4054 gui_update_scrollbars(force) | |
4055 int force; /* Force all scrollbars to get updated */ | |
4056 { | |
4057 win_T *wp; | |
4058 scrollbar_T *sb; | |
4059 long val, size, max; /* need 32 bits here */ | |
4060 int which_sb; | |
4061 int h, y; | |
4062 #ifdef FEAT_VERTSPLIT | |
4063 static win_T *prev_curwin = NULL; | |
4064 #endif | |
4065 | |
4066 /* Update the horizontal scrollbar */ | |
4067 gui_update_horiz_scrollbar(force); | |
4068 | |
4069 #ifndef WIN3264 | |
4070 /* Return straight away if there is neither a left nor right scrollbar. | |
4071 * On MS-Windows this is required anyway for scrollwheel messages. */ | |
4072 if (!gui.which_scrollbars[SBAR_LEFT] && !gui.which_scrollbars[SBAR_RIGHT]) | |
4073 return; | |
4074 #endif | |
4075 | |
4076 /* | |
4077 * Don't want to update a scrollbar while we're dragging it. But if we | |
4078 * have both a left and right scrollbar, and we drag one of them, we still | |
4079 * need to update the other one. | |
4080 */ | |
674 | 4081 if (!force && (gui.dragged_sb == SBAR_LEFT || gui.dragged_sb == SBAR_RIGHT) |
4082 && gui.which_scrollbars[SBAR_LEFT] | |
4083 && gui.which_scrollbars[SBAR_RIGHT]) | |
7 | 4084 { |
4085 /* | |
4086 * If we have two scrollbars and one of them is being dragged, just | |
4087 * copy the scrollbar position from the dragged one to the other one. | |
4088 */ | |
4089 which_sb = SBAR_LEFT + SBAR_RIGHT - gui.dragged_sb; | |
4090 if (gui.dragged_wp != NULL) | |
4091 gui_mch_set_scrollbar_thumb( | |
4092 &gui.dragged_wp->w_scrollbars[which_sb], | |
4093 gui.dragged_wp->w_scrollbars[0].value, | |
4094 gui.dragged_wp->w_scrollbars[0].size, | |
4095 gui.dragged_wp->w_scrollbars[0].max); | |
4096 } | |
4097 | |
4098 /* avoid that moving components around generates events */ | |
4099 ++hold_gui_events; | |
4100 | |
4101 for (wp = firstwin; wp != NULL; wp = W_NEXT(wp)) | |
4102 { | |
4103 if (wp->w_buffer == NULL) /* just in case */ | |
4104 continue; | |
674 | 4105 /* Skip a scrollbar that is being dragged. */ |
4106 if (!force && (gui.dragged_sb == SBAR_LEFT | |
4107 || gui.dragged_sb == SBAR_RIGHT) | |
4108 && gui.dragged_wp == wp) | |
4109 continue; | |
4110 | |
7 | 4111 #ifdef SCROLL_PAST_END |
4112 max = wp->w_buffer->b_ml.ml_line_count - 1; | |
4113 #else | |
4114 max = wp->w_buffer->b_ml.ml_line_count + wp->w_height - 2; | |
4115 #endif | |
4116 if (max < 0) /* empty buffer */ | |
4117 max = 0; | |
4118 val = wp->w_topline - 1; | |
4119 size = wp->w_height; | |
4120 #ifdef SCROLL_PAST_END | |
4121 if (val > max) /* just in case */ | |
4122 val = max; | |
4123 #else | |
4124 if (size > max + 1) /* just in case */ | |
4125 size = max + 1; | |
4126 if (val > max - size + 1) | |
4127 val = max - size + 1; | |
4128 #endif | |
4129 if (val < 0) /* minimal value is 0 */ | |
4130 val = 0; | |
4131 | |
4132 /* | |
4133 * Scrollbar at index 0 (the left one) contains all the information. | |
4134 * It would be the same info for left and right so we just store it for | |
4135 * one of them. | |
4136 */ | |
4137 sb = &wp->w_scrollbars[0]; | |
4138 | |
4139 /* | |
4140 * Note: no check for valid w_botline. If it's not valid the | |
4141 * scrollbars will be updated later anyway. | |
4142 */ | |
4143 if (size < 1 || wp->w_botline - 2 > max) | |
4144 { | |
4145 /* | |
4146 * This can happen during changing files. Just don't update the | |
4147 * scrollbar for now. | |
4148 */ | |
4149 sb->height = 0; /* Force update next time */ | |
4150 if (gui.which_scrollbars[SBAR_LEFT]) | |
4151 gui_do_scrollbar(wp, SBAR_LEFT, FALSE); | |
4152 if (gui.which_scrollbars[SBAR_RIGHT]) | |
4153 gui_do_scrollbar(wp, SBAR_RIGHT, FALSE); | |
4154 continue; | |
4155 } | |
4156 if (force || sb->height != wp->w_height | |
4157 #ifdef FEAT_WINDOWS | |
4158 || sb->top != wp->w_winrow | |
4159 || sb->status_height != wp->w_status_height | |
4160 # ifdef FEAT_VERTSPLIT | |
4161 || sb->width != wp->w_width | |
4162 || prev_curwin != curwin | |
4163 # endif | |
4164 #endif | |
4165 ) | |
4166 { | |
4167 /* Height, width or position of scrollbar has changed. For | |
4168 * vertical split: curwin changed. */ | |
4169 sb->height = wp->w_height; | |
4170 #ifdef FEAT_WINDOWS | |
4171 sb->top = wp->w_winrow; | |
4172 sb->status_height = wp->w_status_height; | |
4173 # ifdef FEAT_VERTSPLIT | |
4174 sb->width = wp->w_width; | |
4175 # endif | |
4176 #endif | |
4177 | |
4178 /* Calculate height and position in pixels */ | |
4179 h = (sb->height + sb->status_height) * gui.char_height; | |
4180 y = sb->top * gui.char_height + gui.border_offset; | |
4181 #if defined(FEAT_MENU) && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MOTIF) && !defined(FEAT_GUI_PHOTON) | |
4182 if (gui.menu_is_active) | |
4183 y += gui.menu_height; | |
4184 #endif | |
4185 | |
4186 #if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_ATHENA)) | |
4187 if (vim_strchr(p_go, GO_TOOLBAR) != NULL) | |
4188 # ifdef FEAT_GUI_ATHENA | |
4189 y += gui.toolbar_height; | |
4190 # else | |
4191 # ifdef FEAT_GUI_MSWIN | |
4192 y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT; | |
4193 # endif | |
4194 # endif | |
4195 #endif | |
4196 | |
810 | 4197 #if defined(FEAT_GUI_TABLINE) && defined(FEAT_GUI_MSWIN) |
4198 if (gui_has_tabline()) | |
843 | 4199 y += gui.tabline_height; |
810 | 4200 #endif |
4201 | |
7 | 4202 #ifdef FEAT_WINDOWS |
4203 if (wp->w_winrow == 0) | |
4204 #endif | |
4205 { | |
4206 /* Height of top scrollbar includes width of top border */ | |
4207 h += gui.border_offset; | |
4208 y -= gui.border_offset; | |
4209 } | |
4210 if (gui.which_scrollbars[SBAR_LEFT]) | |
4211 { | |
4212 gui_mch_set_scrollbar_pos(&wp->w_scrollbars[SBAR_LEFT], | |
4213 gui.left_sbar_x, y, | |
4214 gui.scrollbar_width, h); | |
4215 gui_do_scrollbar(wp, SBAR_LEFT, TRUE); | |
4216 } | |
4217 if (gui.which_scrollbars[SBAR_RIGHT]) | |
4218 { | |
4219 gui_mch_set_scrollbar_pos(&wp->w_scrollbars[SBAR_RIGHT], | |
4220 gui.right_sbar_x, y, | |
4221 gui.scrollbar_width, h); | |
4222 gui_do_scrollbar(wp, SBAR_RIGHT, TRUE); | |
4223 } | |
4224 } | |
4225 | |
4226 /* Reduce the number of calls to gui_mch_set_scrollbar_thumb() by | |
4227 * checking if the thumb moved at least a pixel. Only do this for | |
4228 * Athena, most other GUIs require the update anyway to make the | |
4229 * arrows work. */ | |
4230 #ifdef FEAT_GUI_ATHENA | |
4231 if (max == 0) | |
4232 y = 0; | |
4233 else | |
4234 y = (val * (sb->height + 2) * gui.char_height + max / 2) / max; | |
4235 if (force || sb->pixval != y || sb->size != size || sb->max != max) | |
4236 #else | |
4237 if (force || sb->value != val || sb->size != size || sb->max != max) | |
4238 #endif | |
4239 { | |
4240 /* Thumb of scrollbar has moved */ | |
4241 sb->value = val; | |
4242 #ifdef FEAT_GUI_ATHENA | |
4243 sb->pixval = y; | |
4244 #endif | |
4245 sb->size = size; | |
4246 sb->max = max; | |
674 | 4247 if (gui.which_scrollbars[SBAR_LEFT] |
4248 && (gui.dragged_sb != SBAR_LEFT || gui.dragged_wp != wp)) | |
7 | 4249 gui_mch_set_scrollbar_thumb(&wp->w_scrollbars[SBAR_LEFT], |
4250 val, size, max); | |
4251 if (gui.which_scrollbars[SBAR_RIGHT] | |
674 | 4252 && (gui.dragged_sb != SBAR_RIGHT || gui.dragged_wp != wp)) |
7 | 4253 gui_mch_set_scrollbar_thumb(&wp->w_scrollbars[SBAR_RIGHT], |
4254 val, size, max); | |
4255 } | |
4256 } | |
4257 #ifdef FEAT_VERTSPLIT | |
4258 prev_curwin = curwin; | |
4259 #endif | |
4260 --hold_gui_events; | |
4261 } | |
4262 | |
4263 /* | |
4264 * Enable or disable a scrollbar. | |
4265 * Check for scrollbars for vertically split windows which are not enabled | |
4266 * sometimes. | |
4267 */ | |
4268 static void | |
4269 gui_do_scrollbar(wp, which, enable) | |
4270 win_T *wp; | |
4271 int which; /* SBAR_LEFT or SBAR_RIGHT */ | |
4272 int enable; /* TRUE to enable scrollbar */ | |
4273 { | |
4274 #ifdef FEAT_VERTSPLIT | |
4275 int midcol = curwin->w_wincol + curwin->w_width / 2; | |
4276 int has_midcol = (wp->w_wincol <= midcol | |
4277 && wp->w_wincol + wp->w_width >= midcol); | |
4278 | |
4279 /* Only enable scrollbars that contain the middle column of the current | |
4280 * window. */ | |
4281 if (gui.which_scrollbars[SBAR_RIGHT] != gui.which_scrollbars[SBAR_LEFT]) | |
4282 { | |
4283 /* Scrollbars only on one side. Don't enable scrollbars that don't | |
4284 * contain the middle column of the current window. */ | |
4285 if (!has_midcol) | |
4286 enable = FALSE; | |
4287 } | |
4288 else | |
4289 { | |
4290 /* Scrollbars on both sides. Don't enable scrollbars that neither | |
4291 * contain the middle column of the current window nor are on the far | |
4292 * side. */ | |
4293 if (midcol > Columns / 2) | |
4294 { | |
4295 if (which == SBAR_LEFT ? wp->w_wincol != 0 : !has_midcol) | |
4296 enable = FALSE; | |
4297 } | |
4298 else | |
4299 { | |
4300 if (which == SBAR_RIGHT ? wp->w_wincol + wp->w_width != Columns | |
4301 : !has_midcol) | |
4302 enable = FALSE; | |
4303 } | |
4304 } | |
4305 #endif | |
4306 gui_mch_enable_scrollbar(&wp->w_scrollbars[which], enable); | |
4307 } | |
4308 | |
4309 /* | |
4310 * Scroll a window according to the values set in the globals current_scrollbar | |
4311 * and scrollbar_value. Return TRUE if the cursor in the current window moved | |
4312 * or FALSE otherwise. | |
4313 */ | |
4314 int | |
4315 gui_do_scroll() | |
4316 { | |
4317 win_T *wp, *save_wp; | |
4318 int i; | |
4319 long nlines; | |
4320 pos_T old_cursor; | |
4321 linenr_T old_topline; | |
4322 #ifdef FEAT_DIFF | |
4323 int old_topfill; | |
4324 #endif | |
4325 | |
4326 for (wp = firstwin, i = 0; i < current_scrollbar; wp = W_NEXT(wp), i++) | |
4327 if (wp == NULL) | |
4328 break; | |
4329 if (wp == NULL) | |
4330 /* Couldn't find window */ | |
4331 return FALSE; | |
4332 | |
4333 /* | |
4334 * Compute number of lines to scroll. If zero, nothing to do. | |
4335 */ | |
4336 nlines = (long)scrollbar_value + 1 - (long)wp->w_topline; | |
4337 if (nlines == 0) | |
4338 return FALSE; | |
4339 | |
4340 save_wp = curwin; | |
4341 old_topline = wp->w_topline; | |
4342 #ifdef FEAT_DIFF | |
4343 old_topfill = wp->w_topfill; | |
4344 #endif | |
4345 old_cursor = wp->w_cursor; | |
4346 curwin = wp; | |
4347 curbuf = wp->w_buffer; | |
4348 if (nlines < 0) | |
4349 scrolldown(-nlines, gui.dragged_wp == NULL); | |
4350 else | |
4351 scrollup(nlines, gui.dragged_wp == NULL); | |
4352 /* Reset dragged_wp after using it. "dragged_sb" will have been reset for | |
4353 * the mouse-up event already, but we still want it to behave like when | |
4354 * dragging. But not the next click in an arrow. */ | |
4355 if (gui.dragged_sb == SBAR_NONE) | |
4356 gui.dragged_wp = NULL; | |
4357 | |
4358 if (old_topline != wp->w_topline | |
4359 #ifdef FEAT_DIFF | |
4360 || old_topfill != wp->w_topfill | |
4361 #endif | |
4362 ) | |
4363 { | |
4364 if (p_so != 0) | |
4365 { | |
4366 cursor_correct(); /* fix window for 'so' */ | |
4367 update_topline(); /* avoid up/down jump */ | |
4368 } | |
4369 if (old_cursor.lnum != wp->w_cursor.lnum) | |
4370 coladvance(wp->w_curswant); | |
4371 #ifdef FEAT_SCROLLBIND | |
4372 wp->w_scbind_pos = wp->w_topline; | |
4373 #endif | |
4374 } | |
4375 | |
519 | 4376 /* Make sure wp->w_leftcol and wp->w_skipcol are correct. */ |
4377 validate_cursor(); | |
4378 | |
7 | 4379 curwin = save_wp; |
4380 curbuf = save_wp->w_buffer; | |
4381 | |
4382 /* | |
4383 * Don't call updateWindow() when nothing has changed (it will overwrite | |
4384 * the status line!). | |
4385 */ | |
4386 if (old_topline != wp->w_topline | |
519 | 4387 || wp->w_redr_type != 0 |
7 | 4388 #ifdef FEAT_DIFF |
4389 || old_topfill != wp->w_topfill | |
4390 #endif | |
4391 ) | |
4392 { | |
1434 | 4393 int type = VALID; |
4394 | |
4395 #ifdef FEAT_INS_EXPAND | |
4396 if (pum_visible()) | |
4397 { | |
4398 type = NOT_VALID; | |
4399 wp->w_lines_valid = 0; | |
4400 } | |
4401 #endif | |
4402 /* Don't set must_redraw here, it may cause the popup menu to | |
4403 * disappear when losing focus after a scrollbar drag. */ | |
4404 if (wp->w_redr_type < type) | |
4405 wp->w_redr_type = type; | |
7 | 4406 updateWindow(wp); /* update window, status line, and cmdline */ |
4407 } | |
4408 | |
973 | 4409 #ifdef FEAT_INS_EXPAND |
4410 /* May need to redraw the popup menu. */ | |
4411 if (pum_visible()) | |
4412 pum_redraw(); | |
4413 #endif | |
4414 | |
7 | 4415 return (wp == curwin && !equalpos(curwin->w_cursor, old_cursor)); |
4416 } | |
4417 | |
4418 | |
4419 /* | |
4420 * Horizontal scrollbar stuff: | |
4421 */ | |
4422 | |
4423 /* | |
4424 * Return length of line "lnum" for horizontal scrolling. | |
4425 */ | |
4426 static colnr_T | |
4427 scroll_line_len(lnum) | |
4428 linenr_T lnum; | |
4429 { | |
4430 char_u *p; | |
4431 colnr_T col; | |
4432 int w; | |
4433 | |
4434 p = ml_get(lnum); | |
4435 col = 0; | |
4436 if (*p != NUL) | |
4437 for (;;) | |
4438 { | |
4439 w = chartabsize(p, col); | |
39 | 4440 mb_ptr_adv(p); |
7 | 4441 if (*p == NUL) /* don't count the last character */ |
4442 break; | |
4443 col += w; | |
4444 } | |
4445 return col; | |
4446 } | |
4447 | |
4448 /* Remember which line is currently the longest, so that we don't have to | |
4449 * search for it when scrolling horizontally. */ | |
4450 static linenr_T longest_lnum = 0; | |
4451 | |
2409
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4452 /* |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4453 * Find longest visible line number. If this is not possible (or not desired, |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4454 * by setting 'h' in "guioptions") then the current line number is returned. |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4455 */ |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4456 static linenr_T |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4457 gui_find_longest_lnum() |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4458 { |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4459 linenr_T ret = 0; |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4460 |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4461 /* Calculate maximum for horizontal scrollbar. Check for reasonable |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4462 * line numbers, topline and botline can be invalid when displaying is |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4463 * postponed. */ |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4464 if (vim_strchr(p_go, GO_HORSCROLL) == NULL |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4465 && curwin->w_topline <= curwin->w_cursor.lnum |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4466 && curwin->w_botline > curwin->w_cursor.lnum |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4467 && curwin->w_botline <= curbuf->b_ml.ml_line_count + 1) |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4468 { |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4469 linenr_T lnum; |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4470 colnr_T n; |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4471 long max = 0; |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4472 |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4473 /* Use maximum of all visible lines. Remember the lnum of the |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4474 * longest line, closest to the cursor line. Used when scrolling |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4475 * below. */ |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4476 for (lnum = curwin->w_topline; lnum < curwin->w_botline; ++lnum) |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4477 { |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4478 n = scroll_line_len(lnum); |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4479 if (n > (colnr_T)max) |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4480 { |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4481 max = n; |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4482 ret = lnum; |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4483 } |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4484 else if (n == (colnr_T)max |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4485 && abs((int)(lnum - curwin->w_cursor.lnum)) |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4486 < abs((int)(ret - curwin->w_cursor.lnum))) |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4487 ret = lnum; |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4488 } |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4489 } |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4490 else |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4491 /* Use cursor line only. */ |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4492 ret = curwin->w_cursor.lnum; |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4493 |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4494 return ret; |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4495 } |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4496 |
7 | 4497 static void |
4498 gui_update_horiz_scrollbar(force) | |
4499 int force; | |
4500 { | |
4501 long value, size, max; /* need 32 bit ints here */ | |
4502 | |
4503 if (!gui.which_scrollbars[SBAR_BOTTOM]) | |
4504 return; | |
4505 | |
4506 if (!force && gui.dragged_sb == SBAR_BOTTOM) | |
4507 return; | |
4508 | |
4509 if (!force && curwin->w_p_wrap && gui.prev_wrap) | |
4510 return; | |
4511 | |
4512 /* | |
4513 * It is possible for the cursor to be invalid if we're in the middle of | |
4514 * something (like changing files). If so, don't do anything for now. | |
4515 */ | |
4516 if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) | |
4517 { | |
4518 gui.bottom_sbar.value = -1; | |
4519 return; | |
4520 } | |
4521 | |
4522 size = W_WIDTH(curwin); | |
4523 if (curwin->w_p_wrap) | |
4524 { | |
4525 value = 0; | |
4526 #ifdef SCROLL_PAST_END | |
4527 max = 0; | |
4528 #else | |
4529 max = W_WIDTH(curwin) - 1; | |
4530 #endif | |
4531 } | |
4532 else | |
4533 { | |
4534 value = curwin->w_leftcol; | |
4535 | |
2409
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4536 longest_lnum = gui_find_longest_lnum(); |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4537 max = scroll_line_len(longest_lnum); |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4538 |
7 | 4539 #ifdef FEAT_VIRTUALEDIT |
4540 if (virtual_active()) | |
4541 { | |
4542 /* May move the cursor even further to the right. */ | |
4543 if (curwin->w_virtcol >= (colnr_T)max) | |
4544 max = curwin->w_virtcol; | |
4545 } | |
4546 #endif | |
4547 | |
4548 #ifndef SCROLL_PAST_END | |
4549 max += W_WIDTH(curwin) - 1; | |
4550 #endif | |
4551 /* The line number isn't scrolled, thus there is less space when | |
2178
c6f1aa1e9f32
Add 'relativenumber' patch from Markus Heidelberg.
Bram Moolenaar <bram@vim.org>
parents:
2065
diff
changeset
|
4552 * 'number' or 'relativenumber' is set (also for 'foldcolumn'). */ |
7 | 4553 size -= curwin_col_off(); |
4554 #ifndef SCROLL_PAST_END | |
4555 max -= curwin_col_off(); | |
4556 #endif | |
4557 } | |
4558 | |
4559 #ifndef SCROLL_PAST_END | |
4560 if (value > max - size + 1) | |
4561 value = max - size + 1; /* limit the value to allowable range */ | |
4562 #endif | |
4563 | |
4564 #ifdef FEAT_RIGHTLEFT | |
4565 if (curwin->w_p_rl) | |
4566 { | |
4567 value = max + 1 - size - value; | |
4568 if (value < 0) | |
4569 { | |
4570 size += value; | |
4571 value = 0; | |
4572 } | |
4573 } | |
4574 #endif | |
4575 if (!force && value == gui.bottom_sbar.value && size == gui.bottom_sbar.size | |
4576 && max == gui.bottom_sbar.max) | |
4577 return; | |
4578 | |
4579 gui.bottom_sbar.value = value; | |
4580 gui.bottom_sbar.size = size; | |
4581 gui.bottom_sbar.max = max; | |
4582 gui.prev_wrap = curwin->w_p_wrap; | |
4583 | |
4584 gui_mch_set_scrollbar_thumb(&gui.bottom_sbar, value, size, max); | |
4585 } | |
4586 | |
4587 /* | |
4588 * Do a horizontal scroll. Return TRUE if the cursor moved, FALSE otherwise. | |
4589 */ | |
4590 int | |
2409
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4591 gui_do_horiz_scroll(leftcol, compute_longest_lnum) |
2416
1a9c16dd76d4
Fix compiler warnings on 64 bit systems.
Bram Moolenaar <bram@vim.org>
parents:
2409
diff
changeset
|
4592 long_u leftcol; |
2409
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4593 int compute_longest_lnum; |
7 | 4594 { |
4595 /* no wrapping, no scrolling */ | |
4596 if (curwin->w_p_wrap) | |
4597 return FALSE; | |
4598 | |
2416
1a9c16dd76d4
Fix compiler warnings on 64 bit systems.
Bram Moolenaar <bram@vim.org>
parents:
2409
diff
changeset
|
4599 if (curwin->w_leftcol == (colnr_T)leftcol) |
7 | 4600 return FALSE; |
4601 | |
2416
1a9c16dd76d4
Fix compiler warnings on 64 bit systems.
Bram Moolenaar <bram@vim.org>
parents:
2409
diff
changeset
|
4602 curwin->w_leftcol = (colnr_T)leftcol; |
7 | 4603 |
4604 /* When the line of the cursor is too short, move the cursor to the | |
2409
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4605 * longest visible line. */ |
7 | 4606 if (vim_strchr(p_go, GO_HORSCROLL) == NULL |
2409
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4607 && !virtual_active() |
2416
1a9c16dd76d4
Fix compiler warnings on 64 bit systems.
Bram Moolenaar <bram@vim.org>
parents:
2409
diff
changeset
|
4608 && (colnr_T)leftcol > scroll_line_len(curwin->w_cursor.lnum)) |
7 | 4609 { |
2409
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4610 if (compute_longest_lnum) |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4611 { |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4612 curwin->w_cursor.lnum = gui_find_longest_lnum(); |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4613 curwin->w_cursor.col = 0; |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4614 } |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4615 /* Do a sanity check on "longest_lnum", just in case. */ |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4616 else if (longest_lnum >= curwin->w_topline |
0ca06a92adfb
Add support for horizontal scroll wheel. (Bjorn Winckler)
Bram Moolenaar <bram@vim.org>
parents:
2378
diff
changeset
|
4617 && longest_lnum < curwin->w_botline) |
7 | 4618 { |
4619 curwin->w_cursor.lnum = longest_lnum; | |
4620 curwin->w_cursor.col = 0; | |
4621 } | |
4622 } | |
4623 | |
4624 return leftcol_changed(); | |
4625 } | |
4626 | |
4627 /* | |
4628 * Check that none of the colors are the same as the background color | |
4629 */ | |
4630 void | |
4631 gui_check_colors() | |
4632 { | |
4633 if (gui.norm_pixel == gui.back_pixel || gui.norm_pixel == INVALCOLOR) | |
4634 { | |
4635 gui_set_bg_color((char_u *)"White"); | |
4636 if (gui.norm_pixel == gui.back_pixel || gui.norm_pixel == INVALCOLOR) | |
4637 gui_set_fg_color((char_u *)"Black"); | |
4638 } | |
4639 } | |
4640 | |
203 | 4641 static void |
7 | 4642 gui_set_fg_color(name) |
4643 char_u *name; | |
4644 { | |
4645 gui.norm_pixel = gui_get_color(name); | |
4646 hl_set_fg_color_name(vim_strsave(name)); | |
4647 } | |
4648 | |
203 | 4649 static void |
7 | 4650 gui_set_bg_color(name) |
4651 char_u *name; | |
4652 { | |
4653 gui.back_pixel = gui_get_color(name); | |
4654 hl_set_bg_color_name(vim_strsave(name)); | |
4655 } | |
4656 | |
4657 /* | |
4658 * Allocate a color by name. | |
4659 * Returns INVALCOLOR and gives an error message when failed. | |
4660 */ | |
4661 guicolor_T | |
4662 gui_get_color(name) | |
4663 char_u *name; | |
4664 { | |
4665 guicolor_T t; | |
4666 | |
4667 if (*name == NUL) | |
4668 return INVALCOLOR; | |
4669 t = gui_mch_get_color(name); | |
11 | 4670 |
7 | 4671 if (t == INVALCOLOR |
574 | 4672 #if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) |
7 | 4673 && gui.in_use |
4674 #endif | |
4675 ) | |
4676 EMSG2(_("E254: Cannot allocate color %s"), name); | |
4677 return t; | |
4678 } | |
4679 | |
4680 /* | |
4681 * Return the grey value of a color (range 0-255). | |
4682 */ | |
4683 int | |
4684 gui_get_lightness(pixel) | |
4685 guicolor_T pixel; | |
4686 { | |
4687 long_u rgb = gui_mch_get_rgb(pixel); | |
4688 | |
835 | 4689 return (int)( (((rgb >> 16) & 0xff) * 299) |
856 | 4690 + (((rgb >> 8) & 0xff) * 587) |
4691 + ((rgb & 0xff) * 114)) / 1000; | |
7 | 4692 } |
4693 | |
4694 #if defined(FEAT_GUI_X11) || defined(PROTO) | |
4695 void | |
4696 gui_new_scrollbar_colors() | |
4697 { | |
4698 win_T *wp; | |
4699 | |
4700 /* Nothing to do if GUI hasn't started yet. */ | |
4701 if (!gui.in_use) | |
4702 return; | |
4703 | |
4704 FOR_ALL_WINDOWS(wp) | |
4705 { | |
4706 gui_mch_set_scrollbar_colors(&(wp->w_scrollbars[SBAR_LEFT])); | |
4707 gui_mch_set_scrollbar_colors(&(wp->w_scrollbars[SBAR_RIGHT])); | |
4708 } | |
4709 gui_mch_set_scrollbar_colors(&gui.bottom_sbar); | |
4710 } | |
4711 #endif | |
4712 | |
4713 /* | |
4714 * Call this when focus has changed. | |
4715 */ | |
4716 void | |
4717 gui_focus_change(in_focus) | |
4718 int in_focus; | |
4719 { | |
4720 /* | |
4721 * Skip this code to avoid drawing the cursor when debugging and switching | |
4722 * between the debugger window and gvim. | |
4723 */ | |
4724 #if 1 | |
4725 gui.in_focus = in_focus; | |
4726 out_flush(); /* make sure output has been written */ | |
4727 gui_update_cursor(TRUE, FALSE); | |
4728 | |
4729 # ifdef FEAT_XIM | |
4730 xim_set_focus(in_focus); | |
4731 # endif | |
4732 | |
1380 | 4733 /* Put events in the input queue only when allowed. |
4734 * ui_focus_change() isn't called directly, because it invokes | |
4735 * autocommands and that must not happen asynchronously. */ | |
4736 if (!hold_gui_events) | |
4737 { | |
4738 char_u bytes[3]; | |
4739 | |
4740 bytes[0] = CSI; | |
4741 bytes[1] = KS_EXTRA; | |
4742 bytes[2] = in_focus ? (int)KE_FOCUSGAINED : (int)KE_FOCUSLOST; | |
4743 add_to_input_buf(bytes, 3); | |
4744 } | |
7 | 4745 #endif |
4746 } | |
4747 | |
4748 /* | |
4749 * Called when the mouse moved (but not when dragging). | |
4750 */ | |
4751 void | |
4752 gui_mouse_moved(x, y) | |
4753 int x; | |
4754 int y; | |
4755 { | |
4756 win_T *wp; | |
894 | 4757 char_u st[8]; |
7 | 4758 |
771 | 4759 /* Ignore this while still starting up. */ |
4760 if (!gui.in_use || gui.starting) | |
4761 return; | |
4762 | |
7 | 4763 #ifdef FEAT_MOUSESHAPE |
4764 /* Get window pointer, and update mouse shape as well. */ | |
4765 wp = xy2win(x, y); | |
4766 #endif | |
4767 | |
4768 /* Only handle this when 'mousefocus' set and ... */ | |
4769 if (p_mousef | |
4770 && !hold_gui_events /* not holding events */ | |
4771 && (State & (NORMAL|INSERT))/* Normal/Visual/Insert mode */ | |
4772 && State != HITRETURN /* but not hit-return prompt */ | |
4773 && msg_scrolled == 0 /* no scrolled message */ | |
4774 && !need_mouse_correct /* not moving the pointer */ | |
4775 && gui.in_focus) /* gvim in focus */ | |
4776 { | |
4777 /* Don't move the mouse when it's left or right of the Vim window */ | |
4778 if (x < 0 || x > Columns * gui.char_width) | |
4779 return; | |
4780 #ifndef FEAT_MOUSESHAPE | |
4781 wp = xy2win(x, y); | |
4782 #endif | |
4783 if (wp == curwin || wp == NULL) | |
4784 return; /* still in the same old window, or none at all */ | |
4785 | |
859 | 4786 #ifdef FEAT_WINDOWS |
4787 /* Ignore position in the tab pages line. */ | |
4788 if (Y_2_ROW(y) < tabline_height()) | |
4789 return; | |
4790 #endif | |
4791 | |
7 | 4792 /* |
4793 * format a mouse click on status line input | |
4794 * ala gui_send_mouse_event(0, x, y, 0, 0); | |
261 | 4795 * Trick: Use a column number -1, so that get_pseudo_mouse_code() will |
4796 * generate a K_LEFTMOUSE_NM key code. | |
7 | 4797 */ |
4798 if (finish_op) | |
4799 { | |
4800 /* abort the current operator first */ | |
4801 st[0] = ESC; | |
4802 add_to_input_buf(st, 1); | |
4803 } | |
4804 st[0] = CSI; | |
4805 st[1] = KS_MOUSE; | |
4806 st[2] = KE_FILLER; | |
4807 st[3] = (char_u)MOUSE_LEFT; | |
4808 fill_mouse_coord(st + 4, | |
4809 #ifdef FEAT_VERTSPLIT | |
261 | 4810 wp->w_wincol == 0 ? -1 : wp->w_wincol + MOUSE_COLOFF, |
7 | 4811 #else |
4812 -1, | |
4813 #endif | |
4814 wp->w_height + W_WINROW(wp)); | |
4815 | |
4816 add_to_input_buf(st, 8); | |
4817 st[3] = (char_u)MOUSE_RELEASE; | |
4818 add_to_input_buf(st, 8); | |
4819 #ifdef FEAT_GUI_GTK | |
4820 /* Need to wake up the main loop */ | |
4821 if (gtk_main_level() > 0) | |
4822 gtk_main_quit(); | |
4823 #endif | |
4824 } | |
4825 } | |
4826 | |
4827 /* | |
4828 * Called when mouse should be moved to window with focus. | |
4829 */ | |
4830 void | |
4831 gui_mouse_correct() | |
4832 { | |
4833 int x, y; | |
4834 win_T *wp = NULL; | |
4835 | |
4836 need_mouse_correct = FALSE; | |
87 | 4837 |
4838 if (!(gui.in_use && p_mousef)) | |
4839 return; | |
4840 | |
4841 gui_mch_getmouse(&x, &y); | |
4842 /* Don't move the mouse when it's left or right of the Vim window */ | |
4843 if (x < 0 || x > Columns * gui.char_width) | |
4844 return; | |
877 | 4845 if (y >= 0 |
859 | 4846 # ifdef FEAT_WINDOWS |
877 | 4847 && Y_2_ROW(y) >= tabline_height() |
859 | 4848 # endif |
877 | 4849 ) |
87 | 4850 wp = xy2win(x, y); |
4851 if (wp != curwin && wp != NULL) /* If in other than current window */ | |
7 | 4852 { |
87 | 4853 validate_cline_row(); |
4854 gui_mch_setmouse((int)W_ENDCOL(curwin) * gui.char_width - 3, | |
4855 (W_WINROW(curwin) + curwin->w_wrow) * gui.char_height | |
7 | 4856 + (gui.char_height) / 2); |
4857 } | |
4858 } | |
4859 | |
4860 /* | |
4861 * Find window where the mouse pointer "y" coordinate is in. | |
4862 */ | |
4863 static win_T * | |
4864 xy2win(x, y) | |
1887 | 4865 int x UNUSED; |
4866 int y UNUSED; | |
7 | 4867 { |
4868 #ifdef FEAT_WINDOWS | |
4869 int row; | |
4870 int col; | |
4871 win_T *wp; | |
4872 | |
4873 row = Y_2_ROW(y); | |
4874 col = X_2_COL(x); | |
4875 if (row < 0 || col < 0) /* before first window */ | |
4876 return NULL; | |
4877 wp = mouse_find_win(&row, &col); | |
4878 # ifdef FEAT_MOUSESHAPE | |
4879 if (State == HITRETURN || State == ASKMORE) | |
4880 { | |
4881 if (Y_2_ROW(y) >= msg_row) | |
4882 update_mouseshape(SHAPE_IDX_MOREL); | |
4883 else | |
4884 update_mouseshape(SHAPE_IDX_MORE); | |
4885 } | |
4886 else if (row > wp->w_height) /* below status line */ | |
4887 update_mouseshape(SHAPE_IDX_CLINE); | |
4888 # ifdef FEAT_VERTSPLIT | |
4889 else if (!(State & CMDLINE) && W_VSEP_WIDTH(wp) > 0 && col == wp->w_width | |
819 | 4890 && (row != wp->w_height || !stl_connected(wp)) && msg_scrolled == 0) |
7 | 4891 update_mouseshape(SHAPE_IDX_VSEP); |
4892 # endif | |
4893 else if (!(State & CMDLINE) && W_STATUS_HEIGHT(wp) > 0 | |
819 | 4894 && row == wp->w_height && msg_scrolled == 0) |
7 | 4895 update_mouseshape(SHAPE_IDX_STATUS); |
4896 else | |
4897 update_mouseshape(-2); | |
4898 # endif | |
4899 return wp; | |
4900 #else | |
4901 return firstwin; | |
4902 #endif | |
4903 } | |
4904 | |
4905 /* | |
4906 * ":gui" and ":gvim": Change from the terminal version to the GUI version. | |
4907 * File names may be given to redefine the args list. | |
4908 */ | |
4909 void | |
4910 ex_gui(eap) | |
4911 exarg_T *eap; | |
4912 { | |
4913 char_u *arg = eap->arg; | |
4914 | |
4915 /* | |
4916 * Check for "-f" argument: foreground, don't fork. | |
4917 * Also don't fork when started with "gvim -f". | |
4918 * Do fork when using "gui -b". | |
4919 */ | |
4920 if (arg[0] == '-' | |
4921 && (arg[1] == 'f' || arg[1] == 'b') | |
4922 && (arg[2] == NUL || vim_iswhite(arg[2]))) | |
4923 { | |
4924 gui.dofork = (arg[1] == 'b'); | |
4925 eap->arg = skipwhite(eap->arg + 2); | |
4926 } | |
4927 if (!gui.in_use) | |
4928 { | |
4929 /* Clear the command. Needed for when forking+exiting, to avoid part | |
4930 * of the argument ending up after the shell prompt. */ | |
4931 msg_clr_eos_force(); | |
4932 gui_start(); | |
2209
d0ddf7ba1630
Included the patch to support netbeans in a terminal.
Bram Moolenaar <bram@vim.org>
parents:
2208
diff
changeset
|
4933 #ifdef FEAT_NETBEANS_INTG |
2210 | 4934 netbeans_gui_register(); |
2209
d0ddf7ba1630
Included the patch to support netbeans in a terminal.
Bram Moolenaar <bram@vim.org>
parents:
2208
diff
changeset
|
4935 #endif |
7 | 4936 } |
4937 if (!ends_excmd(*eap->arg)) | |
4938 ex_next(eap); | |
4939 } | |
4940 | |
4941 #if ((defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_W32) \ | |
574 | 4942 || defined(FEAT_GUI_PHOTON)) && defined(FEAT_TOOLBAR)) || defined(PROTO) |
7 | 4943 /* |
4944 * This is shared between Athena, Motif and GTK. | |
4945 */ | |
236 | 4946 static void gfp_setname __ARGS((char_u *fname, void *cookie)); |
7 | 4947 |
4948 /* | |
4949 * Callback function for do_in_runtimepath(). | |
4950 */ | |
4951 static void | |
236 | 4952 gfp_setname(fname, cookie) |
7 | 4953 char_u *fname; |
236 | 4954 void *cookie; |
7 | 4955 { |
236 | 4956 char_u *gfp_buffer = cookie; |
4957 | |
7 | 4958 if (STRLEN(fname) >= MAXPATHL) |
4959 *gfp_buffer = NUL; | |
4960 else | |
4961 STRCPY(gfp_buffer, fname); | |
4962 } | |
4963 | |
4964 /* | |
4965 * Find the path of bitmap "name" with extension "ext" in 'runtimepath'. | |
4966 * Return FAIL for failure and OK if buffer[MAXPATHL] contains the result. | |
4967 */ | |
4968 int | |
4969 gui_find_bitmap(name, buffer, ext) | |
4970 char_u *name; | |
4971 char_u *buffer; | |
4972 char *ext; | |
4973 { | |
4974 if (STRLEN(name) > MAXPATHL - 14) | |
4975 return FAIL; | |
273 | 4976 vim_snprintf((char *)buffer, MAXPATHL, "bitmaps/%s.%s", name, ext); |
236 | 4977 if (do_in_runtimepath(buffer, FALSE, gfp_setname, buffer) == FAIL |
4978 || *buffer == NUL) | |
7 | 4979 return FAIL; |
4980 return OK; | |
4981 } | |
4982 | |
2277
f42e0b5ff9e9
Change remaining HAVE_GTK2 to FEAT_GUI_GTK.
Bram Moolenaar <bram@vim.org>
parents:
2275
diff
changeset
|
4983 # if !defined(FEAT_GUI_GTK) || defined(PROTO) |
7 | 4984 /* |
4985 * Given the name of the "icon=" argument, try finding the bitmap file for the | |
4986 * icon. If it is an absolute path name, use it as it is. Otherwise append | |
4987 * "ext" and search for it in 'runtimepath'. | |
4988 * The result is put in "buffer[MAXPATHL]". If something fails "buffer" | |
4989 * contains "name". | |
4990 */ | |
4991 void | |
4992 gui_find_iconfile(name, buffer, ext) | |
4993 char_u *name; | |
4994 char_u *buffer; | |
4995 char *ext; | |
4996 { | |
4997 char_u buf[MAXPATHL + 1]; | |
4998 | |
4999 expand_env(name, buffer, MAXPATHL); | |
5000 if (!mch_isFullName(buffer) && gui_find_bitmap(buffer, buf, ext) == OK) | |
5001 STRCPY(buffer, buf); | |
5002 } | |
5003 # endif | |
5004 #endif | |
5005 | |
574 | 5006 #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11) || defined(PROTO) |
7 | 5007 void |
5008 display_errors() | |
5009 { | |
5010 char_u *p; | |
5011 | |
5012 if (isatty(2)) | |
5013 fflush(stderr); | |
5014 else if (error_ga.ga_data != NULL) | |
5015 { | |
5016 /* avoid putting up a message box with blanks only */ | |
5017 for (p = (char_u *)error_ga.ga_data; *p != NUL; ++p) | |
5018 if (!isspace(*p)) | |
5019 { | |
5020 /* Truncate a very long message, it will go off-screen. */ | |
5021 if (STRLEN(p) > 2000) | |
5022 STRCPY(p + 2000 - 14, "...(truncated)"); | |
5023 (void)do_dialog(VIM_ERROR, (char_u *)_("Error"), | |
2684 | 5024 p, (char_u *)_("&Ok"), 1, NULL, FALSE); |
7 | 5025 break; |
5026 } | |
5027 ga_clear(&error_ga); | |
5028 } | |
5029 } | |
5030 #endif | |
5031 | |
5032 #if defined(NO_CONSOLE_INPUT) || defined(PROTO) | |
5033 /* | |
5034 * Return TRUE if still starting up and there is no place to enter text. | |
5035 * For GTK and X11 we check if stderr is not a tty, which means we were | |
5036 * (probably) started from the desktop. Also check stdin, "vim >& file" does | |
5037 * allow typing on stdin. | |
5038 */ | |
5039 int | |
5040 no_console_input() | |
5041 { | |
5042 return ((!gui.in_use || gui.starting) | |
5043 # ifndef NO_CONSOLE | |
5044 && !isatty(0) && !isatty(2) | |
5045 # endif | |
5046 ); | |
5047 } | |
5048 #endif | |
5049 | |
28 | 5050 #if defined(FIND_REPLACE_DIALOG) || defined(FEAT_SUN_WORKSHOP) \ |
1002 | 5051 || defined(NEED_GUI_UPDATE_SCREEN) \ |
28 | 5052 || defined(PROTO) |
7 | 5053 /* |
5054 * Update the current window and the screen. | |
5055 */ | |
5056 void | |
5057 gui_update_screen() | |
5058 { | |
2282
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5059 #ifdef FEAT_CONCEAL |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5060 linenr_T conceal_old_cursor_line = 0; |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5061 linenr_T conceal_new_cursor_line = 0; |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5062 int conceal_update_lines = FALSE; |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5063 #endif |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5064 |
7 | 5065 update_topline(); |
5066 validate_cursor(); | |
2282
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5067 |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5068 #if defined(FEAT_AUTOCMD) || defined(FEAT_CONCEAL) |
1584 | 5069 /* Trigger CursorMoved if the cursor moved. */ |
2282
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5070 if (!finish_op && ( |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5071 # ifdef FEAT_AUTOCMD |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5072 has_cursormoved() |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5073 # endif |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5074 # if defined(FEAT_AUTOCMD) && defined(FEAT_CONCEAL) |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5075 || |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5076 # endif |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5077 # ifdef FEAT_CONCEAL |
2378
85b7dc8da5eb
Add the 'concealcursor' option to decide when the cursor line is to be
Bram Moolenaar <bram@vim.org>
parents:
2348
diff
changeset
|
5078 curwin->w_p_cole > 0 |
2282
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5079 # endif |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5080 ) |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5081 && !equalpos(last_cursormoved, curwin->w_cursor)) |
1584 | 5082 { |
2282
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5083 # ifdef FEAT_AUTOCMD |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5084 if (has_cursormoved()) |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5085 apply_autocmds(EVENT_CURSORMOVED, NULL, NULL, FALSE, curbuf); |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5086 # endif |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5087 # ifdef FEAT_CONCEAL |
2378
85b7dc8da5eb
Add the 'concealcursor' option to decide when the cursor line is to be
Bram Moolenaar <bram@vim.org>
parents:
2348
diff
changeset
|
5088 if (curwin->w_p_cole > 0) |
2282
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5089 { |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5090 conceal_old_cursor_line = last_cursormoved.lnum; |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5091 conceal_new_cursor_line = curwin->w_cursor.lnum; |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5092 conceal_update_lines = TRUE; |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5093 } |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5094 # endif |
1584 | 5095 last_cursormoved = curwin->w_cursor; |
5096 } | |
5097 #endif | |
2282
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5098 |
7 | 5099 update_screen(0); /* may need to update the screen */ |
5100 setcursor(); | |
2282
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5101 # if defined(FEAT_CONCEAL) |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5102 if (conceal_update_lines |
2378
85b7dc8da5eb
Add the 'concealcursor' option to decide when the cursor line is to be
Bram Moolenaar <bram@vim.org>
parents:
2348
diff
changeset
|
5103 && (conceal_old_cursor_line != conceal_new_cursor_line |
85b7dc8da5eb
Add the 'concealcursor' option to decide when the cursor line is to be
Bram Moolenaar <bram@vim.org>
parents:
2348
diff
changeset
|
5104 || conceal_cursor_line(curwin) |
85b7dc8da5eb
Add the 'concealcursor' option to decide when the cursor line is to be
Bram Moolenaar <bram@vim.org>
parents:
2348
diff
changeset
|
5105 || need_cursor_line_redraw)) |
2282
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5106 { |
2378
85b7dc8da5eb
Add the 'concealcursor' option to decide when the cursor line is to be
Bram Moolenaar <bram@vim.org>
parents:
2348
diff
changeset
|
5107 if (conceal_old_cursor_line != conceal_new_cursor_line) |
85b7dc8da5eb
Add the 'concealcursor' option to decide when the cursor line is to be
Bram Moolenaar <bram@vim.org>
parents:
2348
diff
changeset
|
5108 update_single_line(curwin, conceal_old_cursor_line); |
2282
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5109 update_single_line(curwin, conceal_new_cursor_line); |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5110 curwin->w_valid &= ~VALID_CROW; |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5111 } |
a888ed7ba375
Make updating text for conceal mode simpler. A few compiler warning fixes.
Bram Moolenaar <bram@vim.org>
parents:
2277
diff
changeset
|
5112 # endif |
7 | 5113 out_flush(); /* make sure output has been written */ |
5114 gui_update_cursor(TRUE, FALSE); | |
5115 gui_mch_flush(); | |
5116 } | |
5117 #endif | |
5118 | |
28 | 5119 #if defined(FIND_REPLACE_DIALOG) || defined(PROTO) |
7 | 5120 static void concat_esc __ARGS((garray_T *gap, char_u *text, int what)); |
5121 | |
5122 /* | |
5123 * Get the text to use in a find/replace dialog. Uses the last search pattern | |
5124 * if the argument is empty. | |
5125 * Returns an allocated string. | |
5126 */ | |
5127 char_u * | |
5128 get_find_dialog_text(arg, wwordp, mcasep) | |
5129 char_u *arg; | |
5130 int *wwordp; /* return: TRUE if \< \> found */ | |
5131 int *mcasep; /* return: TRUE if \C found */ | |
5132 { | |
5133 char_u *text; | |
5134 | |
5135 if (*arg == NUL) | |
5136 text = last_search_pat(); | |
5137 else | |
5138 text = arg; | |
5139 if (text != NULL) | |
5140 { | |
5141 text = vim_strsave(text); | |
5142 if (text != NULL) | |
5143 { | |
835 | 5144 int len = (int)STRLEN(text); |
7 | 5145 int i; |
5146 | |
5147 /* Remove "\V" */ | |
5148 if (len >= 2 && STRNCMP(text, "\\V", 2) == 0) | |
5149 { | |
5150 mch_memmove(text, text + 2, (size_t)(len - 1)); | |
5151 len -= 2; | |
5152 } | |
5153 | |
5154 /* Recognize "\c" and "\C" and remove. */ | |
5155 if (len >= 2 && *text == '\\' && (text[1] == 'c' || text[1] == 'C')) | |
5156 { | |
5157 *mcasep = (text[1] == 'C'); | |
5158 mch_memmove(text, text + 2, (size_t)(len - 1)); | |
5159 len -= 2; | |
5160 } | |
5161 | |
5162 /* Recognize "\<text\>" and remove. */ | |
5163 if (len >= 4 | |
5164 && STRNCMP(text, "\\<", 2) == 0 | |
5165 && STRNCMP(text + len - 2, "\\>", 2) == 0) | |
5166 { | |
5167 *wwordp = TRUE; | |
5168 mch_memmove(text, text + 2, (size_t)(len - 4)); | |
5169 text[len - 4] = NUL; | |
5170 } | |
5171 | |
5172 /* Recognize "\/" or "\?" and remove. */ | |
5173 for (i = 0; i + 1 < len; ++i) | |
5174 if (text[i] == '\\' && (text[i + 1] == '/' | |
5175 || text[i + 1] == '?')) | |
5176 { | |
5177 mch_memmove(text + i, text + i + 1, (size_t)(len - i)); | |
5178 --len; | |
5179 } | |
5180 } | |
5181 } | |
5182 return text; | |
5183 } | |
5184 | |
5185 /* | |
5186 * Concatenate "text" to grow array "gap", escaping "what" with a backslash. | |
5187 */ | |
5188 static void | |
5189 concat_esc(gap, text, what) | |
5190 garray_T *gap; | |
5191 char_u *text; | |
5192 int what; | |
5193 { | |
5194 while (*text != NUL) | |
5195 { | |
5196 #ifdef FEAT_MBYTE | |
474 | 5197 int l = (*mb_ptr2len)(text); |
819 | 5198 |
7 | 5199 if (l > 1) |
5200 { | |
5201 while (--l >= 0) | |
5202 ga_append(gap, *text++); | |
5203 continue; | |
5204 } | |
5205 #endif | |
5206 if (*text == what) | |
5207 ga_append(gap, '\\'); | |
5208 ga_append(gap, *text); | |
5209 ++text; | |
5210 } | |
5211 } | |
5212 | |
5213 /* | |
5214 * Handle the press of a button in the find-replace dialog. | |
5215 * Return TRUE when something was added to the input buffer. | |
5216 */ | |
5217 int | |
5218 gui_do_findrepl(flags, find_text, repl_text, down) | |
5219 int flags; /* one of FRD_REPLACE, FRD_FINDNEXT, etc. */ | |
5220 char_u *find_text; | |
5221 char_u *repl_text; | |
5222 int down; /* Search downwards. */ | |
5223 { | |
5224 garray_T ga; | |
5225 int i; | |
5226 int type = (flags & FRD_TYPE_MASK); | |
5227 char_u *p; | |
28 | 5228 regmatch_T regmatch; |
482 | 5229 int save_did_emsg = did_emsg; |
1943 | 5230 static int busy = FALSE; |
5231 | |
5232 /* When the screen is being updated we should not change buffers and | |
5233 * windows structures, it may cause freed memory to be used. Also don't | |
5234 * do this recursively (pressing "Find" quickly several times. */ | |
5235 if (updating_screen || busy) | |
5236 return FALSE; | |
5237 | |
5238 /* refuse replace when text cannot be changed */ | |
5239 if ((type == FRD_REPLACE || type == FRD_REPLACEALL) && text_locked()) | |
5240 return FALSE; | |
5241 | |
5242 busy = TRUE; | |
7 | 5243 |
5244 ga_init2(&ga, 1, 100); | |
28 | 5245 if (type == FRD_REPLACEALL) |
7 | 5246 ga_concat(&ga, (char_u *)"%s/"); |
5247 | |
5248 ga_concat(&ga, (char_u *)"\\V"); | |
5249 if (flags & FRD_MATCH_CASE) | |
5250 ga_concat(&ga, (char_u *)"\\C"); | |
5251 else | |
5252 ga_concat(&ga, (char_u *)"\\c"); | |
5253 if (flags & FRD_WHOLE_WORD) | |
5254 ga_concat(&ga, (char_u *)"\\<"); | |
5255 if (type == FRD_REPLACEALL || down) | |
5256 concat_esc(&ga, find_text, '/'); /* escape slashes */ | |
5257 else | |
5258 concat_esc(&ga, find_text, '?'); /* escape '?' */ | |
5259 if (flags & FRD_WHOLE_WORD) | |
5260 ga_concat(&ga, (char_u *)"\\>"); | |
5261 | |
5262 if (type == FRD_REPLACEALL) | |
5263 { | |
28 | 5264 ga_concat(&ga, (char_u *)"/"); |
694 | 5265 /* escape / and \ */ |
5266 p = vim_strsave_escaped(repl_text, (char_u *)"/\\"); | |
5267 if (p != NULL) | |
5268 ga_concat(&ga, p); | |
5269 vim_free(p); | |
28 | 5270 ga_concat(&ga, (char_u *)"/g"); |
5271 } | |
5272 ga_append(&ga, NUL); | |
5273 | |
5274 if (type == FRD_REPLACE) | |
5275 { | |
5276 /* Do the replacement when the text at the cursor matches. Thus no | |
5277 * replacement is done if the cursor was moved! */ | |
5278 regmatch.regprog = vim_regcomp(ga.ga_data, RE_MAGIC + RE_STRING); | |
5279 regmatch.rm_ic = 0; | |
5280 if (regmatch.regprog != NULL) | |
5281 { | |
5282 p = ml_get_cursor(); | |
5283 if (vim_regexec_nl(®match, p, (colnr_T)0) | |
5284 && regmatch.startp[0] == p) | |
5285 { | |
5286 /* Clear the command line to remove any old "No match" | |
5287 * error. */ | |
5288 msg_end_prompt(); | |
5289 | |
5290 if (u_save_cursor() == OK) | |
5291 { | |
5292 /* A button was pressed thus undo should be synced. */ | |
825 | 5293 u_sync(FALSE); |
28 | 5294 |
5295 del_bytes((long)(regmatch.endp[0] - regmatch.startp[0]), | |
609 | 5296 FALSE, FALSE); |
28 | 5297 ins_str(repl_text); |
5298 } | |
5299 } | |
5300 else | |
5301 MSG(_("No match at cursor, finding next")); | |
5302 vim_free(regmatch.regprog); | |
5303 } | |
5304 } | |
5305 | |
5306 if (type == FRD_REPLACEALL) | |
5307 { | |
7 | 5308 /* A button was pressed, thus undo should be synced. */ |
825 | 5309 u_sync(FALSE); |
7 | 5310 do_cmdline_cmd(ga.ga_data); |
5311 } | |
5312 else | |
5313 { | |
5314 /* Search for the next match. */ | |
5315 i = msg_scroll; | |
5316 do_search(NULL, down ? '/' : '?', ga.ga_data, 1L, | |
1521 | 5317 SEARCH_MSG + SEARCH_MARK, NULL); |
7 | 5318 msg_scroll = i; /* don't let an error message set msg_scroll */ |
5319 } | |
5320 | |
482 | 5321 /* Don't want to pass did_emsg to other code, it may cause disabling |
5322 * syntax HL if we were busy redrawing. */ | |
5323 did_emsg = save_did_emsg; | |
5324 | |
7 | 5325 if (State & (NORMAL | INSERT)) |
5326 { | |
5327 gui_update_screen(); /* update the screen */ | |
5328 msg_didout = 0; /* overwrite any message */ | |
5329 need_wait_return = FALSE; /* don't wait for return */ | |
5330 } | |
5331 | |
5332 vim_free(ga.ga_data); | |
1943 | 5333 busy = FALSE; |
7 | 5334 return (ga.ga_len > 0); |
5335 } | |
5336 | |
5337 #endif | |
5338 | |
5339 #if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \ | |
5340 || defined(FEAT_GUI_MSWIN) \ | |
5341 || defined(FEAT_GUI_MAC) \ | |
5342 || defined(PROTO) | |
5343 | |
5344 #ifdef FEAT_WINDOWS | |
5345 static void gui_wingoto_xy __ARGS((int x, int y)); | |
5346 | |
5347 /* | |
5348 * Jump to the window at specified point (x, y). | |
5349 */ | |
5350 static void | |
5351 gui_wingoto_xy(x, y) | |
5352 int x; | |
5353 int y; | |
5354 { | |
5355 int row = Y_2_ROW(y); | |
5356 int col = X_2_COL(x); | |
5357 win_T *wp; | |
5358 | |
5359 if (row >= 0 && col >= 0) | |
5360 { | |
5361 wp = mouse_find_win(&row, &col); | |
5362 if (wp != NULL && wp != curwin) | |
5363 win_goto(wp); | |
5364 } | |
5365 } | |
5366 #endif | |
5367 | |
5368 /* | |
5369 * Process file drop. Mouse cursor position, key modifiers, name of files | |
5370 * and count of files are given. Argument "fnames[count]" has full pathnames | |
5371 * of dropped files, they will be freed in this function, and caller can't use | |
5372 * fnames after call this function. | |
5373 */ | |
5374 void | |
5375 gui_handle_drop(x, y, modifiers, fnames, count) | |
1887 | 5376 int x UNUSED; |
5377 int y UNUSED; | |
7 | 5378 int_u modifiers; |
5379 char_u **fnames; | |
5380 int count; | |
5381 { | |
5382 int i; | |
5383 char_u *p; | |
1668 | 5384 static int entered = FALSE; |
5385 | |
5386 /* | |
5387 * This function is called by event handlers. Just in case we get a | |
5388 * second event before the first one is handled, ignore the second one. | |
5389 * Not sure if this can ever happen, just in case. | |
5390 */ | |
5391 if (entered) | |
5392 return; | |
5393 entered = TRUE; | |
7 | 5394 |
5395 /* | |
5396 * When the cursor is at the command line, add the file names to the | |
5397 * command line, don't edit the files. | |
5398 */ | |
5399 if (State & CMDLINE) | |
5400 { | |
5401 shorten_filenames(fnames, count); | |
5402 for (i = 0; i < count; ++i) | |
5403 { | |
5404 if (fnames[i] != NULL) | |
5405 { | |
5406 if (i > 0) | |
5407 add_to_input_buf((char_u*)" ", 1); | |
5408 | |
5409 /* We don't know what command is used thus we can't be sure | |
5410 * about which characters need to be escaped. Only escape the | |
5411 * most common ones. */ | |
5412 # ifdef BACKSLASH_IN_FILENAME | |
5413 p = vim_strsave_escaped(fnames[i], (char_u *)" \t\"|"); | |
5414 # else | |
5415 p = vim_strsave_escaped(fnames[i], (char_u *)"\\ \t\"|"); | |
5416 # endif | |
5417 if (p != NULL) | |
1364 | 5418 add_to_input_buf_csi(p, (int)STRLEN(p)); |
7 | 5419 vim_free(p); |
5420 vim_free(fnames[i]); | |
5421 } | |
5422 } | |
5423 vim_free(fnames); | |
5424 } | |
5425 else | |
5426 { | |
5427 /* Go to the window under mouse cursor, then shorten given "fnames" by | |
5428 * current window, because a window can have local current dir. */ | |
5429 # ifdef FEAT_WINDOWS | |
5430 gui_wingoto_xy(x, y); | |
5431 # endif | |
5432 shorten_filenames(fnames, count); | |
5433 | |
5434 /* If Shift held down, remember the first item. */ | |
5435 if ((modifiers & MOUSE_SHIFT) != 0) | |
5436 p = vim_strsave(fnames[0]); | |
5437 else | |
5438 p = NULL; | |
5439 | |
5440 /* Handle the drop, :edit or :split to get to the file. This also | |
5441 * frees fnames[]. Skip this if there is only one item it's a | |
5442 * directory and Shift is held down. */ | |
5443 if (count == 1 && (modifiers & MOUSE_SHIFT) != 0 | |
5444 && mch_isdir(fnames[0])) | |
5445 { | |
5446 vim_free(fnames[0]); | |
5447 vim_free(fnames); | |
5448 } | |
5449 else | |
5450 handle_drop(count, fnames, (modifiers & MOUSE_CTRL) != 0); | |
5451 | |
5452 /* If Shift held down, change to first file's directory. If the first | |
5453 * item is a directory, change to that directory (and let the explorer | |
5454 * plugin show the contents). */ | |
5455 if (p != NULL) | |
5456 { | |
5457 if (mch_isdir(p)) | |
5458 { | |
5459 if (mch_chdir((char *)p) == 0) | |
5460 shorten_fnames(TRUE); | |
5461 } | |
5462 else if (vim_chdirfile(p) == OK) | |
5463 shorten_fnames(TRUE); | |
5464 vim_free(p); | |
5465 } | |
5466 | |
5467 /* Update the screen display */ | |
5468 update_screen(NOT_VALID); | |
5469 # ifdef FEAT_MENU | |
5470 gui_update_menus(0); | |
5471 # endif | |
2208
495995b9ce7d
Fix: window title not updated after file dropped.
Bram Moolenaar <bram@vim.org>
parents:
2178
diff
changeset
|
5472 #ifdef FEAT_TITLE |
495995b9ce7d
Fix: window title not updated after file dropped.
Bram Moolenaar <bram@vim.org>
parents:
2178
diff
changeset
|
5473 maketitle(); |
495995b9ce7d
Fix: window title not updated after file dropped.
Bram Moolenaar <bram@vim.org>
parents:
2178
diff
changeset
|
5474 #endif |
7 | 5475 setcursor(); |
5476 out_flush(); | |
5477 gui_update_cursor(FALSE, FALSE); | |
5478 gui_mch_flush(); | |
5479 } | |
1668 | 5480 |
5481 entered = FALSE; | |
7 | 5482 } |
5483 #endif |