Compare commits

...

3 Commits

Author SHA1 Message Date
Bram Moolenaar
17709e280a patch 8.2.2623: some tests fail when run as root
Problem:    Some tests fail when run as root.
Solution:   Use CheckNotRoot.
2021-03-19 14:38:12 +01:00
Bram Moolenaar
a555e6fcb6 patch 8.2.2622: GTK: error when starting up and -geometry is given
Problem:    GTK: error when starting up and -geometry is given. (Dominique
            Pellé)
Solution:   Use another function to get the monitor if the window has not been
            created yet. (closes #7978)
2021-03-18 22:28:57 +01:00
Bram Moolenaar
108cf0153c patch 8.2.2621: typval2type() cannot handle recursive structures
Problem:    typval2type() cannot handle recursive structures.
Solution:   Use copyID. (closes #7979)
2021-03-18 22:15:04 +01:00
14 changed files with 167 additions and 109 deletions

View File

@@ -920,7 +920,7 @@ drawBalloon(BalloonEval *beval)
screen = gtk_widget_get_screen(beval->target);
gtk_window_set_screen(GTK_WINDOW(beval->balloonShell), screen);
# endif
gui_gtk_get_screen_geom_of_win(beval->target,
gui_gtk_get_screen_geom_of_win(beval->target, 0, 0,
&screen_x, &screen_y, &screen_w, &screen_h);
# if !GTK_CHECK_VERSION(3,0,0)
gtk_widget_ensure_style(beval->balloonShell);

View File

@@ -4155,6 +4155,80 @@ mainwin_destroy_cb(GObject *object UNUSED, gpointer data UNUSED)
#endif
}
void
gui_gtk_get_screen_geom_of_win(
GtkWidget *wid,
int point_x, // x position of window if not initialized
int point_y, // y position of window if not initialized
int *screen_x,
int *screen_y,
int *width,
int *height)
{
GdkRectangle geometry;
GdkWindow *win = gtk_widget_get_window(wid);
#if GTK_CHECK_VERSION(3,22,0)
GdkDisplay *dpy = gtk_widget_get_display(wid);
GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win);
gdk_monitor_get_geometry(monitor, &geometry);
#else
GdkScreen* screen;
int monitor;
if (wid != NULL && gtk_widget_has_screen(wid))
screen = gtk_widget_get_screen(wid);
else
screen = gdk_screen_get_default();
if (win == NULL)
monitor = gdk_screen_get_monitor_at_point(screen, point_x, point_y);
else
monitor = gdk_screen_get_monitor_at_window(screen, win);
gdk_screen_get_monitor_geometry(screen, monitor, &geometry);
#endif
*screen_x = geometry.x;
*screen_y = geometry.y;
*width = geometry.width;
*height = geometry.height;
}
/*
* The screen size is used to make sure the initial window doesn't get bigger
* than the screen. This subtracts some room for menubar, toolbar and window
* decorations.
*/
static void
gui_gtk_get_screen_dimensions(
int point_x,
int point_y,
int *screen_w,
int *screen_h)
{
int x, y;
gui_gtk_get_screen_geom_of_win(gui.mainwin, point_x, point_y,
&x, &y, screen_w, screen_h);
// Subtract 'guiheadroom' from the height to allow some room for the
// window manager (task list and window title bar).
*screen_h -= p_ghr;
/*
* FIXME: dirty trick: Because the gui_get_base_height() doesn't include
* the toolbar and menubar for GTK, we subtract them from the screen
* height, so that the window size can be made to fit on the screen.
* This should be completely changed later.
*/
*screen_w -= get_menu_tool_width();
*screen_h -= get_menu_tool_height();
}
void
gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
{
gui_gtk_get_screen_dimensions(0, 0, screen_w, screen_h);
}
/*
* Bit of a hack to ensure we start GtkPlug windows with the correct window
@@ -4250,7 +4324,12 @@ gui_mch_open(void)
if (mask & (XValue | YValue))
{
int ww, hh;
#ifdef FEAT_GUI_GTK
gui_gtk_get_screen_dimensions(x, y, &ww, &hh);
#else
gui_mch_get_screen_dimensions(&ww, &hh);
#endif
hh += p_ghr + get_menu_tool_height();
ww += get_menu_tool_width();
if (mask & XNegative)
@@ -4538,64 +4617,6 @@ gui_mch_set_shellsize(int width, int height,
gui_mch_update();
}
void
gui_gtk_get_screen_geom_of_win(
GtkWidget *wid,
int *screen_x,
int *screen_y,
int *width,
int *height)
{
GdkRectangle geometry;
GdkWindow *win = gtk_widget_get_window(wid);
#if GTK_CHECK_VERSION(3,22,0)
GdkDisplay *dpy = gtk_widget_get_display(wid);
GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win);
gdk_monitor_get_geometry(monitor, &geometry);
#else
GdkScreen* screen;
int monitor;
if (wid != NULL && gtk_widget_has_screen(wid))
screen = gtk_widget_get_screen(wid);
else
screen = gdk_screen_get_default();
monitor = gdk_screen_get_monitor_at_window(screen, win);
gdk_screen_get_monitor_geometry(screen, monitor, &geometry);
#endif
*screen_x = geometry.x;
*screen_y = geometry.y;
*width = geometry.width;
*height = geometry.height;
}
/*
* The screen size is used to make sure the initial window doesn't get bigger
* than the screen. This subtracts some room for menubar, toolbar and window
* decorations.
*/
void
gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
{
int x, y;
gui_gtk_get_screen_geom_of_win(gui.mainwin, &x, &y, screen_w, screen_h);
// Subtract 'guiheadroom' from the height to allow some room for the
// window manager (task list and window title bar).
*screen_h -= p_ghr;
/*
* FIXME: dirty trick: Because the gui_get_base_height() doesn't include
* the toolbar and menubar for GTK, we subtract them from the screen
* height, so that the window size can be made to fit on the screen.
* This should be completely changed later.
*/
*screen_w -= get_menu_tool_width();
*screen_h -= get_menu_tool_height();
}
#if defined(FEAT_TITLE) || defined(PROTO)
void
gui_mch_settitle(char_u *title, char_u *icon UNUSED)

View File

@@ -207,7 +207,7 @@ im_preedit_window_set_position(void)
if (preedit_window == NULL)
return;
gui_gtk_get_screen_geom_of_win(gui.drawarea,
gui_gtk_get_screen_geom_of_win(gui.drawarea, 0, 0,
&screen_x, &screen_y, &screen_width, &screen_height);
gdk_window_get_origin(gtk_widget_get_window(gui.drawarea), &x, &y);
gtk_window_get_size(GTK_WINDOW(preedit_window), &width, &height);

View File

@@ -2052,7 +2052,7 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
{
// Check that map() does not change the type of the dict.
ga_init2(&type_list, sizeof(type_T *), 10);
type = typval2type(argvars, &type_list);
type = typval2type(argvars, get_copyID(), &type_list);
}
if (argvars[0].v_type == VAR_BLOB)
@@ -2558,7 +2558,7 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
{
// Check that map() does not change the type of the dict.
ga_init2(&type_list, sizeof(type_T *), 10);
type = typval2type(argvars, &type_list);
type = typval2type(argvars, get_copyID(), &type_list);
}
if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)

View File

@@ -18,6 +18,8 @@ void gui_gtk_set_dnd_targets(void);
int gui_mch_init(void);
void gui_mch_forked(void);
void gui_mch_new_colors(void);
void gui_gtk_get_screen_geom_of_win(GtkWidget *wid, int point_x, int point_y, int *screen_x, int *screen_y, int *width, int *height);
void gui_mch_get_screen_dimensions(int *screen_w, int *screen_h);
int gui_mch_open(void);
void gui_mch_exit(int rc);
int gui_mch_get_winpos(int *x, int *y);
@@ -26,8 +28,6 @@ int gui_mch_maximized(void);
void gui_mch_unmaximize(void);
void gui_mch_newfont(void);
void gui_mch_set_shellsize(int width, int height, int min_width, int min_height, int base_width, int base_height, int direction);
void gui_gtk_get_screen_geom_of_win(GtkWidget *wid, int *screen_x, int *screen_y, int *width, int *height);
void gui_mch_get_screen_dimensions(int *screen_w, int *screen_h);
void gui_mch_settitle(char_u *title, char_u *icon);
void gui_mch_enable_menu(int showit);
void gui_mch_show_toolbar(int showit);

View File

@@ -9,7 +9,7 @@ type_T *alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap);
type_T *get_func_type(type_T *ret_type, int argcount, garray_T *type_gap);
int func_type_add_arg_types(type_T *functype, int argcount, garray_T *type_gap);
int need_convert_to_bool(type_T *type, typval_T *tv);
type_T *typval2type(typval_T *tv, garray_T *type_gap);
type_T *typval2type(typval_T *tv, int copyID, garray_T *type_gap);
type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap);
int check_typval_arg_type(type_T *expected, typval_T *actual_tv, int arg_idx);
int check_typval_type(type_T *expected, typval_T *actual_tv, where_T where);

View File

@@ -1704,9 +1704,10 @@ func Test_edit_charconvert()
endfunc
" Test for editing a file without read permission
" NOTE: if you run tests as root this will fail. Don't run tests as root!
func Test_edit_file_no_read_perm()
CheckUnix
CheckNotRoot
call writefile(['one', 'two'], 'Xfile')
call setfperm('Xfile', '-w-------')
new

View File

@@ -350,13 +350,6 @@ func Test_redir_cmd()
call assert_fails('redir > Xdir', 'E17:')
call delete('Xdir', 'd')
endif
if !has('bsd')
" Redirecting to a read-only file
call writefile([], 'Xfile')
call setfperm('Xfile', 'r--r--r--')
call assert_fails('redir! > Xfile', 'E190:')
call delete('Xfile')
endif
" Test for redirecting to a register
redir @q> | echon 'clean ' | redir END
@@ -369,6 +362,17 @@ func Test_redir_cmd()
call assert_equal('blue sky', color)
endfunc
func Test_redir_cmd_readonly()
CheckNotRoot
CheckNotBSD
" Redirecting to a read-only file
call writefile([], 'Xfile')
call setfperm('Xfile', 'r--r--r--')
call assert_fails('redir! > Xfile', 'E190:')
call delete('Xfile')
endfunc
" Test for the :filetype command
func Test_filetype_cmd()
call assert_fails('filetype abc', 'E475:')

View File

@@ -1,5 +1,7 @@
" Tests for :help
source check.vim
func Test_help_restore_snapshot()
help
set buftype=
@@ -88,29 +90,6 @@ func Test_helptag_cmd()
call assert_equal(["help-tags\ttags\t1"], readfile('Xdir/tags'))
call delete('Xdir/tags')
" The following tests fail on FreeBSD for some reason
if has('unix') && !has('bsd')
" Read-only tags file
call mkdir('Xdir/doc', 'p')
call writefile([''], 'Xdir/doc/tags')
call writefile([], 'Xdir/doc/sample.txt')
call setfperm('Xdir/doc/tags', 'r-xr--r--')
call assert_fails('helptags Xdir/doc', 'E152:', getfperm('Xdir/doc/tags'))
let rtp = &rtp
let &rtp = 'Xdir'
helptags ALL
let &rtp = rtp
call delete('Xdir/doc/tags')
" No permission to read the help file
call setfperm('Xdir/a/doc/sample.txt', '-w-------')
call assert_fails('helptags Xdir', 'E153:', getfperm('Xdir/a/doc/sample.txt'))
call delete('Xdir/a/doc/sample.txt')
call delete('Xdir/tags')
endif
" Duplicate tags in the help file
call writefile(['*tag1*', '*tag1*', '*tag2*'], 'Xdir/a/doc/sample.txt')
call assert_fails('helptags Xdir', 'E154:')
@@ -118,4 +97,33 @@ func Test_helptag_cmd()
call delete('Xdir', 'rf')
endfunc
func Test_helptag_cmd_readonly()
CheckUnix
CheckNotRoot
" The following tests fail on FreeBSD for some reason
CheckNotBSD
" Read-only tags file
call mkdir('Xdir/doc', 'p')
call writefile([''], 'Xdir/doc/tags')
call writefile([], 'Xdir/doc/sample.txt')
call setfperm('Xdir/doc/tags', 'r-xr--r--')
call assert_fails('helptags Xdir/doc', 'E152:', getfperm('Xdir/doc/tags'))
let rtp = &rtp
let &rtp = 'Xdir'
helptags ALL
let &rtp = rtp
call delete('Xdir/doc/tags')
" No permission to read the help file
call mkdir('Xdir/b/doc', 'p')
call writefile([], 'Xdir/b/doc/sample.txt')
call setfperm('Xdir/b/doc/sample.txt', '-w-------')
call assert_fails('helptags Xdir', 'E153:', getfperm('Xdir/b/doc/sample.txt'))
call delete('Xdir', 'rf')
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -6606,6 +6606,13 @@ func Test_typename()
call assert_equal('list<number>', typename([123]))
call assert_equal('dict<number>', typename(#{key: 123}))
call assert_equal('list<dict<number>>', typename([#{key: 123}]))
let l = []
let d = #{a: 0}
let l = [d]
let l[0].e = #{b: l}
call assert_equal('list<dict<any>>', typename(l))
call assert_equal('dict<any>', typename(d))
endfunc
"-------------------------------------------------------------------------------

View File

@@ -410,6 +410,9 @@ endfunc
func Test_write_readonly_dir()
" On MS-Windows, modifying files in a read-only directory is allowed.
CheckUnix
" Root can do it too.
CheckNotRoot
call mkdir('Xdir')
call writefile(['one'], 'Xdir/Xfile1')
call setfperm('Xdir', 'r-xr--r--')

View File

@@ -750,6 +750,12 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2623,
/**/
2622,
/**/
2621,
/**/
2620,
/**/

View File

@@ -750,7 +750,7 @@ update_vim9_script_var(
if (sv != NULL)
{
if (*type == NULL)
*type = typval2type(tv, &si->sn_type_list);
*type = typval2type(tv, get_copyID(), &si->sn_type_list);
sv->sv_type = *type;
}

View File

@@ -254,7 +254,7 @@ func_type_add_arg_types(
* "type_gap" is used to temporarily create types in.
*/
static type_T *
typval2type_int(typval_T *tv, garray_T *type_gap)
typval2type_int(typval_T *tv, int copyID, garray_T *type_gap)
{
type_T *type;
type_T *member_type = &t_any;
@@ -276,11 +276,15 @@ typval2type_int(typval_T *tv, garray_T *type_gap)
return &t_list_empty;
if (l->lv_first == &range_list_item)
return &t_list_number;
if (l->lv_copyID == copyID)
// avoid recursion
return &t_list_any;
l->lv_copyID = copyID;
// Use the common type of all members.
member_type = typval2type(&l->lv_first->li_tv, type_gap);
member_type = typval2type(&l->lv_first->li_tv, copyID, type_gap);
for (li = l->lv_first->li_next; li != NULL; li = li->li_next)
common_type(typval2type(&li->li_tv, type_gap),
common_type(typval2type(&li->li_tv, copyID, type_gap),
member_type, &member_type, type_gap);
return get_list_type(member_type, type_gap);
}
@@ -289,17 +293,21 @@ typval2type_int(typval_T *tv, garray_T *type_gap)
{
dict_iterator_T iter;
typval_T *value;
dict_T *d = tv->vval.v_dict;
if (tv->vval.v_dict == NULL
|| tv->vval.v_dict->dv_hashtab.ht_used == 0)
if (d == NULL || d->dv_hashtab.ht_used == 0)
return &t_dict_empty;
if (d->dv_copyID == copyID)
// avoid recursion
return &t_dict_any;
d->dv_copyID = copyID;
// Use the common type of all values.
dict_iterate_start(tv, &iter);
dict_iterate_next(&iter, &value);
member_type = typval2type(value, type_gap);
member_type = typval2type(value, copyID, type_gap);
while (dict_iterate_next(&iter, &value) != NULL)
common_type(typval2type(value, type_gap),
common_type(typval2type(value, copyID, type_gap),
member_type, &member_type, type_gap);
return get_dict_type(member_type, type_gap);
}
@@ -372,9 +380,9 @@ need_convert_to_bool(type_T *type, typval_T *tv)
* "type_list" is used to temporarily create types in.
*/
type_T *
typval2type(typval_T *tv, garray_T *type_gap)
typval2type(typval_T *tv, int copyID, garray_T *type_gap)
{
type_T *type = typval2type_int(tv, type_gap);
type_T *type = typval2type_int(tv, copyID, type_gap);
if (type != NULL && type != &t_bool
&& (tv->v_type == VAR_NUMBER
@@ -396,7 +404,7 @@ typval2type_vimvar(typval_T *tv, garray_T *type_gap)
return &t_list_string;
if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
return &t_dict_any;
return typval2type(tv, type_gap);
return typval2type(tv, get_copyID(), type_gap);
}
int
@@ -421,7 +429,7 @@ check_typval_type(type_T *expected, typval_T *actual_tv, where_T where)
int res = FAIL;
ga_init2(&type_list, sizeof(type_T *), 10);
actual_type = typval2type(actual_tv, &type_list);
actual_type = typval2type(actual_tv, get_copyID(), &type_list);
if (actual_type != NULL)
res = check_type(expected, actual_type, TRUE, where);
clear_type_list(&type_list);
@@ -1202,7 +1210,7 @@ f_typename(typval_T *argvars, typval_T *rettv)
rettv->v_type = VAR_STRING;
ga_init2(&type_list, sizeof(type_T *), 10);
type = typval2type(argvars, &type_list);
type = typval2type(argvars, get_copyID(), &type_list);
name = type_name(type, &tofree);
if (tofree != NULL)
rettv->vval.v_string = (char_u *)tofree;