diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 67f447d7db..1c7814fe61 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1,4 +1,4 @@ -*builtin.txt* For Vim version 9.1. Last change: 2024 Nov 10 +*builtin.txt* For Vim version 9.1. Last change: 2024 Nov 11 VIM REFERENCE MANUAL by Bram Moolenaar @@ -222,6 +222,7 @@ getbufline({buf}, {lnum} [, {end}]) getbufoneline({buf}, {lnum}) String line {lnum} of buffer {buf} getbufvar({buf}, {varname} [, {def}]) any variable {varname} in buffer {buf} +getcellpixels() List get character cell pixel size getcellwidths() List get character cell width overrides getchangelist([{buf}]) List list of change list items getchar([{expr}]) Number or String @@ -3786,6 +3787,15 @@ getbufvar({buf}, {varname} [, {def}]) *getbufvar()* Return type: any, depending on {varname} +getcellpixels() *getcellpixels()* + Returns a |List| of terminal cell pixel size. + List format is [xpixels, ypixels]. + Only works on Unix. For gVim and on other systems, + returns [-1, -1]. + + Return type: list + + getcellwidths() *getcellwidths()* Returns a |List| of cell widths of character ranges overridden by |setcellwidths()|. The format is equal to the argument of diff --git a/runtime/doc/tags b/runtime/doc/tags index 00d65eb12b..f7ca8d2e8d 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -7838,6 +7838,7 @@ getbufinfo() builtin.txt /*getbufinfo()* getbufline() builtin.txt /*getbufline()* getbufoneline() builtin.txt /*getbufoneline()* getbufvar() builtin.txt /*getbufvar()* +getcellpixels() builtin.txt /*getcellpixels()* getcellwidths() builtin.txt /*getcellwidths()* getchangelist() builtin.txt /*getchangelist()* getchar() builtin.txt /*getchar()* diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index af67429ece..36907d249c 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -1,4 +1,4 @@ -*usr_41.txt* For Vim version 9.1. Last change: 2024 Oct 05 +*usr_41.txt* For Vim version 9.1. Last change: 2024 Nov 11 VIM USER MANUAL - by Bram Moolenaar @@ -778,6 +778,7 @@ String manipulation: *string-functions* strdisplaywidth() size of string when displayed, deals with tabs setcellwidths() set character cell width overrides getcellwidths() get character cell width overrides + getcellpixels() get character cell pixel size reverse() reverse the order of characters in a string substitute() substitute a pattern match with a string submatch() get a specific match in ":s" and substitute() @@ -1394,6 +1395,7 @@ Various: *various-functions* did_filetype() check if a FileType autocommand was used diff() diff two Lists of strings eventhandler() check if invoked by an event handler + getcellpixels() get List of cell pixel size getpid() get process ID of Vim getscriptinfo() get list of sourced vim scripts getimstatus() check if IME status is active diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index daba9848c9..ac0700ed79 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -1,4 +1,4 @@ -*version9.txt* For Vim version 9.1. Last change: 2024 Nov 06 +*version9.txt* For Vim version 9.1. Last change: 2024 Nov 11 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41621,6 +41621,7 @@ Functions: ~ |foreach()| apply function to List items |getcmdcomplpat()| Shell command line completion |getcmdprompt()| get prompt for input()/confirm() +|getcellpixels()| get List of terminal cell pixel size |getregion()| get a region of text from a buffer |getregionpos()| get a list of positions for a region |id()| get unique identifier for a Dict, List, Object, diff --git a/src/evalfunc.c b/src/evalfunc.c index 2d886682d5..04967efc32 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -2077,6 +2077,14 @@ static funcentry_T global_functions[] = ret_string, f_getbufoneline}, {"getbufvar", 2, 3, FEARG_1, arg3_buffer_string_any, ret_any, f_getbufvar}, + {"getcellpixels", 0, 0, 0, NULL, + ret_list_any, +#if (defined(UNIX) || defined(VMS)) && (defined(FEAT_EVAL) || defined(PROTO)) + f_getcellpixels +#else + NULL +#endif + }, {"getcellwidths", 0, 0, 0, NULL, ret_list_any, f_getcellwidths}, {"getchangelist", 0, 1, FEARG_1, arg1_buffer, diff --git a/src/os_unix.c b/src/os_unix.c index 0aa6f3ca13..c69798d7d5 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4348,6 +4348,68 @@ mch_get_shellsize(void) return OK; } +#if defined(FEAT_EVAL) || defined(PROTO) + void +f_getcellpixels(typval_T *argvars UNUSED, typval_T *rettv) +{ + struct cellsize cs; + mch_calc_cell_size(&cs); + + if (rettv_list_alloc(rettv) == FAIL) + return; + + list_append_number(rettv->vval.v_list, (varnumber_T)cs.cs_xpixel); + list_append_number(rettv->vval.v_list, (varnumber_T)cs.cs_ypixel); +} +#endif + +/* + * Try to get the current terminal cell size. + * If faile get cell size, fallback 5x10 pixel. + */ + void +mch_calc_cell_size(struct cellsize *cs_out) +{ +#if defined(FEAT_GUI) + if (!gui.in_use) + { +#endif + // get current tty size. + struct winsize ws; + int fd = 1; + int retval = -1; + retval = ioctl(fd, TIOCGWINSZ, &ws); +# ifdef FEAT_EVAL + ch_log(NULL, "ioctl(TIOCGWINSZ) %s", retval == 0 ? "success" : "failed"); +# endif + if (retval == -1) + { + cs_out->cs_xpixel = -1; + cs_out->cs_ypixel = -1; + return; + } + + // calculate parent tty's pixel per cell. + int x_cell_size = ws.ws_xpixel / ws.ws_col; + int y_cell_size = ws.ws_ypixel / ws.ws_row; + + // calculate current tty's pixel + cs_out->cs_xpixel = x_cell_size; + cs_out->cs_ypixel = y_cell_size; + +# ifdef FEAT_EVAL + ch_log(NULL, "Got cell pixel size with TIOCGWINSZ: %d x %d", x_cell_size, y_cell_size); +# endif +#if defined(FEAT_GUI) + } + else + { + cs_out->cs_xpixel = -1; + cs_out->cs_ypixel = -1; + } +#endif +} + #if defined(FEAT_TERMINAL) || defined(PROTO) /* * Report the windows size "rows" and "cols" to tty "fd". @@ -4367,8 +4429,13 @@ mch_report_winsize(int fd, int rows, int cols) ws.ws_col = cols; ws.ws_row = rows; - ws.ws_xpixel = cols * 5; - ws.ws_ypixel = rows * 10; + + // calcurate and set tty pixel size + struct cellsize cs; + mch_calc_cell_size(&cs); + ws.ws_xpixel = cols * cs.cs_xpixel; + ws.ws_ypixel = rows * cs.cs_ypixel; + retval = ioctl(tty_fd, TIOCSWINSZ, &ws); ch_log(NULL, "ioctl(TIOCSWINSZ) %s", retval == 0 ? "success" : "failed"); # elif defined(TIOCSSIZE) diff --git a/src/os_unix.h b/src/os_unix.h index 99184abe6c..fac2c0fd99 100644 --- a/src/os_unix.h +++ b/src/os_unix.h @@ -488,3 +488,9 @@ int mch_rename(const char *src, const char *dest); // We have three kinds of ACL support. #define HAVE_ACL (HAVE_POSIX_ACL || HAVE_SOLARIS_ACL || HAVE_AIX_ACL) + +struct cellsize { + unsigned int cs_xpixel; + unsigned int cs_ypixel; +}; + diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro index d9dc8d9d54..be4942d291 100644 --- a/src/proto/os_unix.pro +++ b/src/proto/os_unix.pro @@ -91,4 +91,6 @@ void xsmp_close(void); void stop_timeout(void); volatile sig_atomic_t *start_timeout(long msec); void delete_timer(void); +void f_getcellpixels(typval_T *argvars UNUSED, typval_T *rettv); +void mch_calc_cell_size(struct cellsize *cs_out); /* vim: set ft=c : */ diff --git a/src/testdir/test_utf8.vim b/src/testdir/test_utf8.vim index 991a095380..d820e3517d 100644 --- a/src/testdir/test_utf8.vim +++ b/src/testdir/test_utf8.vim @@ -273,6 +273,14 @@ func Test_setcellwidths() bwipe! endfunc +" Pixel size of a cell is terminal-dependent, so in the test, only the list and size 2 are checked. +func Test_getcellpixels() + " Not yet Windows-compatible + CheckNotMSWindows + let cellpixels = getcellpixels() + call assert_equal(2, len(cellpixels)) +endfunc + func Test_getcellwidths() call setcellwidths([]) call assert_equal([], getcellwidths()) diff --git a/src/version.c b/src/version.c index 4e5864f09f..5337b1ad25 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 854, /**/ 853, /**/