Compare commits

...

11 Commits

Author SHA1 Message Date
5df95ea9ef patch 8.0.1325: more tests are not run
Problem:    More tests are not run.
Solution:   Add targets to the list of tests. (Yegappan Lakshmanan)
2017-11-20 22:08:10 +01:00
bb160a188a patch 8.0.1324: some xterm sends different mouse move codes
Problem:    Some xterm sends different mouse move codes.
Solution:   Also accept 0x80 as a move event.
2017-11-20 21:52:24 +01:00
73675fbc48 patch 8.0.1323: mouse events in a terminal window may cause endless loop
Problem:    Mouse events in a terminal window may cause endless loop.
Solution:   Adjust position computation.  Don't stuff a mouse event when
            coming from normal_cmd().
2017-11-20 21:49:19 +01:00
5bbef31949 patch 8.0.1322: textformat test isn't run
Problem:    Textformat test isn't run. (Yegappan Lakshmanan)
Solution:   Add target to the list of tests.
2017-11-19 20:38:05 +01:00
40e280d949 patch 8.0.1321: can't build huge version with Athena
Problem:    Can't build huge version with Athena. (Mark Kelly)
Solution:   Move including beval.h to before structs.h. Include beval.pro like
            other proto files.
2017-11-19 20:34:59 +01:00
7221fce8b3 patch 8.0.1320: popup test fails on GUI-only build
Problem:    Popup test fails on GUI-only build.
Solution:   Don't test balloon_split() when it's not available.
2017-11-19 20:32:49 +01:00
669a828cdc patch 8.0.1319: can't build GUI on MS-Windows
Problem:    Can't build GUI on MS-Windows.
Solution:   Don't define the balloon_split() function in a GUI-only build.
2017-11-19 20:13:05 +01:00
246fe03d15 patch 8.0.1318: terminal balloon only shows one line
Problem:    Terminal balloon only shows one line.
Solution:   Split into several lines in a clever way.  Add balloon_split().
            Make balloon_show() accept a list in the terminal.
2017-11-19 19:56:27 +01:00
e518226713 patch 8.0.1317: accessing freed memory in term_wait()
Problem:    Accessing freed memory in term_wait(). (Dominique Pelle)
Solution:   Check that the buffer still exists.
2017-11-19 15:05:44 +01:00
44c2bffde7 patch 8.0.1316: build still still fails on Mac
Problem:    Build still still fails on Mac. (chdiza)
Solution:   Remove another bogus typedef.
2017-11-18 23:23:01 +01:00
e86ee877c1 patch 8.0.1315: build still fails on Mac
Problem:    Build still fails on Mac. (chdiza)
Solution:   Remove bogus typedef.
2017-11-18 23:09:37 +01:00
18 changed files with 343 additions and 42 deletions

View File

@ -2032,6 +2032,7 @@ asin({expr}) Float arc sine of {expr}
atan({expr}) Float arc tangent of {expr}
atan2({expr1}, {expr2}) Float arc tangent of {expr1} / {expr2}
balloon_show({msg}) none show {msg} inside the balloon
balloon_split({msg}) List split {msg} as used for a balloon
browse({save}, {title}, {initdir}, {default})
String put up a file requester
browsedir({title}, {initdir}) String put up a directory requester
@ -2682,8 +2683,12 @@ atan2({expr1}, {expr2}) *atan2()*
< 2.356194
{only available when compiled with the |+float| feature}
balloon_show({msg}) *balloon_show()*
Show {msg} inside the balloon.
balloon_show({expr}) *balloon_show()*
Show {expr} inside the balloon. For the GUI {expr} is used as
a string. For a terminal {expr} can be a list, which contains
the lines of the balloon. If {expr} is not a list it will be
split with |balloon_split()|.
Example: >
func GetBalloonContent()
" initiate getting the content
@ -2703,7 +2708,16 @@ balloon_show({msg}) *balloon_show()*
When showing a balloon is not possible nothing happens, no
error message.
{only available when compiled with the +balloon_eval feature}
{only available when compiled with the +balloon_eval or
+balloon_eval_term feature}
balloon_split({msg}) *balloon_split()*
Split {msg} into lines to be displayed in a balloon. The
splits are made for the current window size and optimize to
show debugger output.
Returns a |List| with the split lines.
{only available when compiled with the +balloon_eval_term
feature}
*browse()*
browse({save}, {title}, {initdir}, {default})

View File

@ -127,9 +127,11 @@ func s:StartDebug(cmd)
call win_gotoid(s:gdbwin)
" Enable showing a balloon with eval info
if has("balloon_eval")
set ballooneval
if has("balloon_eval") || has("balloon_eval_term")
set balloonexpr=TermDebugBalloonExpr()
if has("balloon_eval")
set ballooneval
endif
if has("balloon_eval_term")
set balloonevalterm
endif
@ -158,9 +160,11 @@ func s:EndDebug(job, status)
let &columns = s:save_columns
endif
if has("balloon_eval")
set noballooneval
if has("balloon_eval") || has("balloon_eval_term")
set balloonexpr=
if has("balloon_eval")
set noballooneval
endif
if has("balloon_eval_term")
set noballoonevalterm
endif
@ -366,6 +370,7 @@ func s:HandleError(msg)
if a:msg =~ 'No symbol .* in current context'
\ || a:msg =~ 'Cannot access memory at address '
\ || a:msg =~ 'Attempt to use a type name as an expression'
\ || a:msg =~ 'A syntax error in expression,'
" Result of s:SendEval() failed, ignore.
return
endif

View File

@ -134,19 +134,20 @@ get_beval_info(
}
/*
* Show a balloon with "mesg".
* Show a balloon with "mesg" or "list".
*/
void
post_balloon(BalloonEval *beval UNUSED, char_u *mesg)
post_balloon(BalloonEval *beval UNUSED, char_u *mesg, list_T *list)
{
# ifdef FEAT_BEVAL_TERM
# ifdef FEAT_GUI
if (!gui.in_use)
# endif
ui_post_balloon(mesg);
ui_post_balloon(mesg, list);
# endif
# ifdef FEAT_BEVAL_GUI
if (gui.in_use)
/* GUI can't handle a list */
gui_mch_post_balloon(beval, mesg);
# endif
}
@ -257,7 +258,7 @@ general_beval_cb(BalloonEval *beval, int state UNUSED)
set_vim_var_string(VV_BEVAL_TEXT, NULL, -1);
if (result != NULL && result[0] != NUL)
{
post_balloon(beval, result);
post_balloon(beval, result, NULL);
recursive = FALSE;
return;
}

View File

@ -78,7 +78,6 @@ typedef struct BalloonEvalStruct
#define EVAL_OFFSET_X 15 /* displacement of beval topleft corner from pointer */
#define EVAL_OFFSET_Y 10
#include "beval.pro"
#ifdef FEAT_BEVAL_GUI
# include "gui_beval.pro"
#endif

View File

@ -61,6 +61,9 @@ static void f_atan2(typval_T *argvars, typval_T *rettv);
#endif
#ifdef FEAT_BEVAL
static void f_balloon_show(typval_T *argvars, typval_T *rettv);
# if defined(FEAT_BEVAL_TERM)
static void f_balloon_split(typval_T *argvars, typval_T *rettv);
# endif
#endif
static void f_browse(typval_T *argvars, typval_T *rettv);
static void f_browsedir(typval_T *argvars, typval_T *rettv);
@ -494,6 +497,9 @@ static struct fst
#endif
#ifdef FEAT_BEVAL
{"balloon_show", 1, 1, f_balloon_show},
# if defined(FEAT_BEVAL_TERM)
{"balloon_split", 1, 1, f_balloon_split},
# endif
#endif
{"browse", 4, 4, f_browse},
{"browsedir", 2, 2, f_browsedir},
@ -1410,8 +1416,40 @@ f_atan2(typval_T *argvars, typval_T *rettv)
f_balloon_show(typval_T *argvars, typval_T *rettv UNUSED)
{
if (balloonEval != NULL)
post_balloon(balloonEval, get_tv_string_chk(&argvars[0]));
{
if (argvars[0].v_type == VAR_LIST
# ifdef FEAT_GUI
&& !gui.in_use
# endif
)
post_balloon(balloonEval, NULL, argvars[0].vval.v_list);
else
post_balloon(balloonEval, get_tv_string_chk(&argvars[0]), NULL);
}
}
# if defined(FEAT_BEVAL_TERM)
static void
f_balloon_split(typval_T *argvars, typval_T *rettv UNUSED)
{
if (rettv_list_alloc(rettv) == OK)
{
char_u *msg = get_tv_string_chk(&argvars[0]);
if (msg != NULL)
{
pumitem_T *array;
int size = split_message(msg, &array);
int i;
/* Skip the first and last item, they are always empty. */
for (i = 1; i < size - 1; ++i)
list_append_string(rettv->vval.v_list, array[i].pum_text, -1);
vim_free(array);
}
}
}
# endif
#endif
/*

View File

@ -4633,7 +4633,9 @@ nv_mousescroll(cmdarg_T *cap)
{
# ifdef FEAT_TERMINAL
if (term_use_loop())
send_keys_to_term(curbuf->b_term, cap->cmdchar, TRUE);
/* This window is a terminal window, send the mouse event there.
* Set "typed" to FALSE to avoid an endless loop. */
send_keys_to_term(curbuf->b_term, cap->cmdchar, FALSE);
else
# endif
if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))

View File

@ -14,7 +14,6 @@
*/
#define NO_X11_INCLUDES
typedef int BalloonEval; /* used in header files */
#include "vim.h"

View File

@ -14,7 +14,6 @@
/* Avoid a conflict for the definition of Boolean between Mac header files and
* X11 header files. */
#define NO_X11_INCLUDES
#define BalloonEval int /* used in header files */
#include "vim.h"
#import <AppKit/AppKit.h>

View File

@ -766,9 +766,147 @@ static int balloon_arraysize;
static int balloon_mouse_row = 0;
static int balloon_mouse_col = 0;
#define BALLOON_MIN_WIDTH 40
#define BALLOON_MIN_WIDTH 50
#define BALLOON_MIN_HEIGHT 10
typedef struct {
char_u *start;
int bytelen;
int cells;
int indent;
} balpart_T;
/*
* Split a string into parts to display in the balloon.
* Aimed at output from gdb. Attempts to split at white space, preserve quoted
* strings and make a struct look good.
* Resulting array is stored in "array" and returns the size of the array.
*/
int
split_message(char_u *mesg, pumitem_T **array)
{
garray_T ga;
char_u *p;
balpart_T *item;
int quoted = FALSE;
int height;
int line;
int item_idx;
int indent = 0;
int max_cells = 0;
int max_height = Rows / 2 - 2;
int long_item_count = 0;
int split_long_items = FALSE;
ga_init2(&ga, sizeof(balpart_T), 20);
p = mesg;
while (*p != NUL)
{
if (ga_grow(&ga, 1) == FAIL)
goto failed;
item = ((balpart_T *)ga.ga_data) + ga.ga_len;
item->start = p;
item->indent = indent;
item->cells = indent * 2;
++ga.ga_len;
while (*p != NUL)
{
if (*p == '"')
quoted = !quoted;
else if (*p == '\\' && p[1] != NUL)
++p;
else if (!quoted)
{
if ((*p == ',' && p[1] == ' ') || *p == '{' || *p == '}')
{
/* Looks like a good point to break. */
if (*p == '{')
++indent;
else if (*p == '}' && indent > 0)
--indent;
++item->cells;
p = skipwhite(p + 1);
break;
}
}
item->cells += ptr2cells(p);
p += MB_PTR2LEN(p);
}
item->bytelen = p - item->start;
if (item->cells > max_cells)
max_cells = item->cells;
long_item_count += item->cells / BALLOON_MIN_WIDTH;
}
height = 2 + ga.ga_len;
/* If there are long items and the height is below the limit: split lines */
if (long_item_count > 0 && height + long_item_count <= max_height)
{
split_long_items = TRUE;
height += long_item_count;
}
/* Limit to half the window height, it has to fit above or below the mouse
* position. */
if (height > max_height)
height = max_height;
*array = (pumitem_T *)alloc_clear((unsigned)sizeof(pumitem_T) * height);
if (*array == NULL)
goto failed;
/* Add an empty line above and below, looks better. */
(*array)->pum_text = vim_strsave((char_u *)"");
(*array + height - 1)->pum_text = vim_strsave((char_u *)"");
for (line = 1, item_idx = 0; line < height - 1; ++item_idx)
{
int skip;
int thislen;
int copylen;
int ind;
int cells;
item = ((balpart_T *)ga.ga_data) + item_idx;
for (skip = 0; skip < item->bytelen; skip += thislen)
{
if (split_long_items && item->cells >= BALLOON_MIN_WIDTH)
{
cells = item->indent * 2;
for (p = item->start + skip; p < item->start + item->bytelen;
p += MB_PTR2LEN(p))
if ((cells += ptr2cells(p)) > BALLOON_MIN_WIDTH)
break;
thislen = p - (item->start + skip);
}
else
thislen = item->bytelen;
/* put indent at the start */
p = alloc(thislen + item->indent * 2 + 1);
for (ind = 0; ind < item->indent * 2; ++ind)
p[ind] = ' ';
/* exclude spaces at the end of the string */
for (copylen = thislen; copylen > 0; --copylen)
if (item->start[skip + copylen - 1] != ' ')
break;
vim_strncpy(p + ind, item->start + skip, copylen);
(*array)[line].pum_text = p;
item->indent = 0; /* wrapped line has no indent */
++line;
}
}
ga_clear(&ga);
return height;
failed:
ga_clear(&ga);
return 0;
}
void
ui_remove_balloon(void)
{
@ -786,28 +924,42 @@ ui_remove_balloon(void)
* Terminal version of a balloon, uses the popup menu code.
*/
void
ui_post_balloon(char_u *mesg)
ui_post_balloon(char_u *mesg, list_T *list)
{
ui_remove_balloon();
/* TODO: split the text in multiple lines. */
balloon_arraysize = 3;
balloon_array = (pumitem_T *)alloc_clear(
(unsigned)sizeof(pumitem_T) * balloon_arraysize);
if (balloon_array != NULL)
if (mesg == NULL && list == NULL)
return;
if (list != NULL)
{
/* Add an empty line above and below, looks better. */
balloon_array[0].pum_text = vim_strsave((char_u *)"");
balloon_array[1].pum_text = vim_strsave(mesg);
balloon_array[2].pum_text = vim_strsave((char_u *)"");
listitem_T *li;
int idx;
balloon_arraysize = list->lv_len;
balloon_array = (pumitem_T *)alloc_clear(
(unsigned)sizeof(pumitem_T) * list->lv_len);
if (balloon_array == NULL)
return;
for (idx = 0, li = list->lv_first; li != NULL; li = li->li_next, ++idx)
{
char_u *text = get_tv_string_chk(&li->li_tv);
balloon_array[idx].pum_text = vim_strsave(
text == NULL ? (char_u *)"" : text);
}
}
else
balloon_arraysize = split_message(mesg, &balloon_array);
if (balloon_arraysize > 0)
{
pum_array = balloon_array;
pum_size = balloon_arraysize;
pum_compute_size();
pum_scrollbar = 0;
pum_height = balloon_arraysize;
if (Rows - mouse_row > BALLOON_MIN_HEIGHT)
if (Rows - mouse_row > pum_size)
{
/* Enough space below the mouse row. */
pum_row = mouse_row + 1;
@ -817,7 +969,7 @@ ui_post_balloon(char_u *mesg)
else
{
/* Show above the mouse row, reduce height if it does not fit. */
pum_row = mouse_row - 1 - pum_size;
pum_row = mouse_row - pum_size;
if (pum_row < 0)
{
pum_height += pum_row;

View File

@ -201,7 +201,9 @@ void qsort(void *base, size_t elm_count, size_t elm_size, int (*cmp)(const void
/* Ugly solution for "BalloonEval" not being defined while it's used in some
* .pro files. */
# ifndef FEAT_BEVAL
# ifdef FEAT_BEVAL
# include "beval.pro"
# else
# define BalloonEval int
# endif

View File

@ -1,6 +1,6 @@
/* beval.c */
int get_beval_info(BalloonEval *beval, int getword, win_T **winp, linenr_T *lnump, char_u **textp, int *colp);
void post_balloon(BalloonEval *beval, char_u *mesg);
void post_balloon(BalloonEval *beval, char_u *mesg, list_T *list);
int can_use_beval(void);
void general_beval_cb(BalloonEval *beval, int state);
/* vim: set ft=c : */

View File

@ -5,7 +5,8 @@ void pum_undisplay(void);
void pum_clear(void);
int pum_visible(void);
int pum_get_height(void);
int split_message(char_u *mesg, pumitem_T **array);
void ui_remove_balloon(void);
void ui_post_balloon(char_u *mesg);
void ui_post_balloon(char_u *mesg, list_T *list);
void ui_may_remove_balloon(void);
/* vim: set ft=c : */

View File

@ -4980,6 +4980,8 @@ check_termcode(
* add 0x08 for ALT
* add 0x10 for CTRL
* add 0x20 for mouse drag (0x40 is drag with left button)
* add 0x40 for mouse move (0x80 is move, 0x81 too)
* 0x43 (drag + release) is also move
* c == column + ' ' + 1 == column + 33
* r == row + ' ' + 1 == row + 33
*
@ -5121,9 +5123,15 @@ check_termcode(
# endif
)
{
/* Keep the mouse_code before it's changed, so that we
* remember that it was a mouse wheel click. */
wheel_code = mouse_code;
# if defined(UNIX) && defined(FEAT_MOUSE_TTY)
if (use_xterm_mouse() > 1 && mouse_code >= 0x80)
/* mouse-move event, using MOUSE_DRAG works */
mouse_code = MOUSE_DRAG;
else
# endif
/* Keep the mouse_code before it's changed, so that we
* remember that it was a mouse wheel click. */
wheel_code = mouse_code;
}
# ifdef FEAT_MOUSE_XTERM
else if (held_button == MOUSE_RELEASE

View File

@ -1302,9 +1302,9 @@ send_keys_to_term(term_T *term, int c, int typed)
case K_MOUSELEFT:
case K_MOUSERIGHT:
if (mouse_row < W_WINROW(curwin)
|| mouse_row >= (W_WINROW(curwin) + curwin->w_height)
|| mouse_row > (W_WINROW(curwin) + curwin->w_height)
|| mouse_col < curwin->w_wincol
|| mouse_col >= W_ENDCOL(curwin)
|| mouse_col > W_ENDCOL(curwin)
|| dragging_outside)
{
/* click or scroll outside the current window */
@ -3227,6 +3227,10 @@ f_term_wait(typval_T *argvars, typval_T *rettv UNUSED)
{
mch_check_messages();
parse_queued_messages();
if (!buf_valid(buf))
/* If the terminal is closed when the channel is closed the
* buffer disappears. */
break;
ui_delay(10L, FALSE);
}
mch_check_messages();

View File

@ -78,11 +78,13 @@ NEW_TESTS = test_arabic.res \
test_cdo.res \
test_channel.res \
test_charsearch.res \
test_charsearch_utf8.res \
test_cindent.res \
test_clientserver.res \
test_close_count.res \
test_cmdline.res \
test_command_count.res \
test_comparators.res \
test_crypt.res \
test_cscope.res \
test_curswant.res \
@ -91,13 +93,18 @@ NEW_TESTS = test_arabic.res \
test_display.res \
test_edit.res \
test_erasebackword.res \
test_escaped_glob.res \
test_exec_while_if.res \
test_exists.res \
test_exists_autocmd.res \
test_expr_utf8.res \
test_farsi.res \
test_file_size.res \
test_find_complete.res \
test_fixeol.res \
test_fnameescape.res \
test_fold.res \
test_getcwd.res \
test_getvar.res \
test_gf.res \
test_gn.res \
@ -115,6 +122,7 @@ NEW_TESTS = test_arabic.res \
test_job_fails.res \
test_json.res \
test_langmap.res \
test_largefile.res \
test_let.res \
test_lineending.res \
test_listchars.res \
@ -124,8 +132,10 @@ NEW_TESTS = test_arabic.res \
test_lua.res \
test_makeencoding.res \
test_man.res \
test_maparg.res \
test_marks.res \
test_matchadd_conceal.res \
test_matchadd_conceal_utf8.res \
test_mksession.res \
test_mksession_utf8.res \
test_nested_function.res \
@ -136,6 +146,7 @@ NEW_TESTS = test_arabic.res \
test_packadd.res \
test_paste.res \
test_perl.res \
test_plus_arg_edit.res \
test_preview.res \
test_profile.res \
test_python2.res \
@ -144,13 +155,17 @@ NEW_TESTS = test_arabic.res \
test_pyx3.res \
test_quickfix.res \
test_quotestar.res \
test_retab.res \
test_regex_char_classes.res \
test_regexp_latin.res \
test_regexp_utf8.res \
test_registers.res \
test_retab.res \
test_ruby.res \
test_scrollbind.res \
test_search.res \
test_signs.res \
test_smartindent.res \
test_source_utf8.res \
test_spell.res \
test_startup.res \
test_startup_utf8.res \
@ -163,10 +178,13 @@ NEW_TESTS = test_arabic.res \
test_tcl.res \
test_terminal.res \
test_terminal_fail.res \
test_textformat.res \
test_textobjects.res \
test_undo.res \
test_usercommands.res \
test_user_func.res \
test_usercommands.res \
test_utf8.res \
test_utf8_comparisons.res \
test_viminfo.res \
test_vimscript.res \
test_visual.res \

View File

@ -703,4 +703,40 @@ func Test_popup_and_preview_autocommand()
bw!
endfunc
func Test_balloon_split()
if !exists('*balloon_split')
return
endif
call assert_equal([
\ 'one two three four one two three four one two thre',
\ 'e four',
\ ], balloon_split(
\ 'one two three four one two three four one two three four'))
call assert_equal([
\ 'struct = {',
\ ' one = 1,',
\ ' two = 2,',
\ ' three = 3}',
\ ], balloon_split(
\ 'struct = {one = 1, two = 2, three = 3}'))
call assert_equal([
\ 'struct = {',
\ ' one = 1,',
\ ' nested = {',
\ ' n1 = "yes",',
\ ' n2 = "no"}',
\ ' two = 2}',
\ ], balloon_split(
\ 'struct = {one = 1, nested = {n1 = "yes", n2 = "no"} two = 2}'))
call assert_equal([
\ 'struct = 0x234 {',
\ ' long = 2343 "\\"some long string that will be wr',
\ 'apped in two\\"",',
\ ' next = 123}',
\ ], balloon_split(
\ 'struct = 0x234 {long = 2343 "\\"some long string that will be wrapped in two\\"", next = 123}'))
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -771,6 +771,28 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1325,
/**/
1324,
/**/
1323,
/**/
1322,
/**/
1321,
/**/
1320,
/**/
1319,
/**/
1318,
/**/
1317,
/**/
1316,
/**/
1315,
/**/
1314,
/**/

View File

@ -1809,14 +1809,15 @@ typedef int sock_T;
/* Include option.h before structs.h, because the number of window-local and
* buffer-local options is used there. */
#include "option.h" /* options and default values */
#include "option.h" /* options and default values */
#include "beval.h" /* BalloonEval */
/* Note that gui.h is included by structs.h */
#include "structs.h" /* file that defines many structures */
#include "structs.h" /* defines many structures */
#include "alloc.h"
#include "beval.h"
/* Values for "do_profiling". */
#define PROF_NONE 0 /* profiling not started */