patch 9.1.0871: getcellpixels() can be further improved

Problem:  getcellpixels() can be further improved
Solution: Fix floating point exception, implement getcellpixels() in the
          UI (mikoto2000)

closes: #16059

Signed-off-by: mikoto2000 <mikoto2000@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 12f7a88..b2905da 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -61,6 +61,7 @@
 static void f_function(typval_T *argvars, typval_T *rettv);
 static void f_garbagecollect(typval_T *argvars, typval_T *rettv);
 static void f_get(typval_T *argvars, typval_T *rettv);
+static void f_getcellpixels(typval_T *argvars, typval_T *rettv);
 static void f_getchangelist(typval_T *argvars, typval_T *rettv);
 static void f_getcharpos(typval_T *argvars, typval_T *rettv);
 static void f_getcharsearch(typval_T *argvars, typval_T *rettv);
@@ -2078,13 +2079,7 @@
     {"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
-			},
+			ret_list_any,	    f_getcellpixels},
     {"getcellwidths",	0, 0, 0,	    NULL,
 			ret_list_any,	    f_getcellwidths},
     {"getchangelist",	0, 1, FEARG_1,	    arg1_buffer,
@@ -5217,6 +5212,45 @@
 }
 
 /*
+ * "getcellpixels()" function
+ */
+    static void
+f_getcellpixels(typval_T *argvars UNUSED, typval_T *rettv)
+{
+    if (rettv_list_alloc(rettv) == FAIL)
+        return;
+
+#if defined(FEAT_GUI)
+    if (gui.in_use)
+    {
+        // success pixel size and no gui.
+        list_append_number(rettv->vval.v_list, (varnumber_T)gui.char_width);
+        list_append_number(rettv->vval.v_list, (varnumber_T)gui.char_height);
+    }
+    else
+#endif
+    {
+        struct cellsize cs;
+#if defined(UNIX)
+        mch_calc_cell_size(&cs);
+#else
+        // Non-Unix CUIs are not supported, so set this to -1x-1.
+        cs.cs_xpixel = -1;
+        cs.cs_ypixel = -1;
+#endif
+
+        // failed get pixel size.
+        if (cs.cs_xpixel == -1)
+            return;
+
+        // success pixel size and no gui.
+        list_append_number(rettv->vval.v_list, (varnumber_T)cs.cs_xpixel);
+        list_append_number(rettv->vval.v_list, (varnumber_T)cs.cs_ypixel);
+    }
+
+}
+
+/*
  * "getchangelist()" function
  */
     static void
diff --git a/src/os_unix.c b/src/os_unix.c
index 80ca0ce..dc518fc 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -4348,32 +4348,6 @@
     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;
-
-    // failed get pixel size.
-    if (cs.cs_xpixel == -1)
-        return;
-
-#if defined(FEAT_GUI)
-    // gui return [].
-    if (gui.in_use)
-        return;
-#endif
-
-    // success pixel size and no gui.
-    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.
  * On failure, returns -1x-1
@@ -4391,7 +4365,7 @@
    ch_log(NULL, "ioctl(TIOCGWINSZ) %s", retval == 0 ? "success" : "failed");
 #endif
 
-   if (retval == -1)
+   if (retval == -1 || ws.ws_col == 0 || ws.ws_row == 0)
    {
        cs_out->cs_xpixel = -1;
        cs_out->cs_ypixel = -1;
diff --git a/src/os_unix.h b/src/os_unix.h
index f017d56..5ba64fd 100644
--- a/src/os_unix.h
+++ b/src/os_unix.h
@@ -489,9 +489,3 @@
 // We have three kinds of ACL support.
 #define HAVE_ACL (HAVE_POSIX_ACL || HAVE_SOLARIS_ACL || HAVE_AIX_ACL)
 
-// Defined as signed, to return -1 on error
-struct cellsize {
-    int cs_xpixel;
-    int cs_ypixel;
-};
-
diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro
index be4942d..4b1257b 100644
--- a/src/proto/os_unix.pro
+++ b/src/proto/os_unix.pro
@@ -91,6 +91,5 @@
 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/structs.h b/src/structs.h
index 19768e6..dcb8978 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -5099,3 +5099,11 @@
 
 #define KEYVALUE_ENTRY(k, v) \
     {(k), {((char_u *)v), STRLEN_LITERAL(v)}}
+
+#if defined(UNIX) || defined(MSWIN)
+// Defined as signed, to return -1 on error
+struct cellsize {
+    int cs_xpixel;
+    int cs_ypixel;
+};
+#endif
diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim
index f555621..8b2518f 100644
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -4160,10 +4160,9 @@
 endfunc
 
 
-" Test for getcellpixels()
+" Test for getcellpixels() for unix system
 " 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
+func Test_getcellpixels_for_unix()
   CheckNotMSWindows
   CheckRunVimInTerminal
 
@@ -4180,13 +4179,30 @@
   call StopVimInTerminal(buf)
 endfunc
 
+" Test for getcellpixels() for windows system
+" Windows terminal vim is not support. check return `[]`.
+func Test_getcellpixels_for_windows()
+  CheckMSWindows
+  CheckRunVimInTerminal
+
+  let buf = RunVimInTerminal('', #{rows: 6})
+
+  " write getcellpixels() result to current buffer.
+  call term_sendkeys(buf, ":redi @\"\<CR>")
+  call term_sendkeys(buf, ":echo getcellpixels()\<CR>")
+  call term_sendkeys(buf, ":redi END\<CR>")
+  call term_sendkeys(buf, "P")
+
+  call WaitForAssert({-> assert_match("\[\]", term_getline(buf, 3))}, 1000)
+
+  call StopVimInTerminal(buf)
+endfunc
+
 " Test for getcellpixels() on gVim
 func Test_getcellpixels_gui()
-  " Not yet Windows-compatible
-  CheckNotMSWindows
   if has("gui_running")
     let cellpixels = getcellpixels()
-    call assert_equal(0, len(cellpixels))
+    call assert_equal(2, len(cellpixels))
   endif
 endfunc
 
diff --git a/src/version.c b/src/version.c
index ce6c38a..dbd5fc6 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    871,
+/**/
     870,
 /**/
     869,