From 7d4188e060f8b242498374bb71931ce643684fb1 Mon Sep 17 00:00:00 2001 From: Shugo Maeda Date: Fri, 6 Mar 2026 14:53:47 +0900 Subject: [PATCH 1/2] Add Window#attr_set and Window#attr_get These wrap wattr_set() and wattr_get() respectively, exposing the full extended color pair number (> 255) that attrset/color_set cannot represent. attr_set(attrs, pair) sets both attributes and color pair; attr_get returns [attrs, pair] as a 2-element Array. Both are guarded by HAVE_WATTR_SET / HAVE_WATTR_GET and fall back to rb_f_notimplement when unavailable. Co-Authored-By: Claude Sonnet 4.6 --- ext/curses/curses.c | 60 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/ext/curses/curses.c b/ext/curses/curses.c index e7eea6b9..1b31125d 100644 --- a/ext/curses/curses.c +++ b/ext/curses/curses.c @@ -2951,6 +2951,64 @@ window_attrset(VALUE obj, VALUE attrs) #endif } +/* + * Document-method: Curses::Window.attr_set + * call-seq: attr_set(attrs, pair) + * + * Sets the current attributes and color pair of the given window. + * Unlike Curses::Window.attrset, this method accepts an extended color + * pair number (> 255) when the ncurses extended colors API is available. + * + * Returns +true+ on success, +false+ on failure. + * + * see also system manual curs_attr(3) + */ +#ifdef HAVE_WATTR_SET +static VALUE +window_attr_set(VALUE obj, VALUE attrs, VALUE pair) +{ + struct windata *winp; + + GetWINDOW(obj, winp); + return (wattr_set(winp->window, NUM2ULONG(attrs), NUM2INT(pair), NULL) == OK) ? Qtrue : Qfalse; +} +#else +#define window_attr_set rb_f_notimplement +#endif + +/* + * Document-method: Curses::Window.attr_get + * call-seq: attr_get => [attrs, pair] + * + * Returns a 2-element Array of the current attributes and color pair + * of the given window. The color pair number may exceed 255 when the + * ncurses extended colors API is available. + * + * Returns +nil+ on failure. + * + * see also system manual curs_attr(3) + */ +#ifdef HAVE_WATTR_GET +static VALUE +window_attr_get(VALUE obj) +{ + struct windata *winp; + attr_t attrs; +#ifdef NCURSES_PAIRS_T + NCURSES_PAIRS_T pair; +#else + short pair; +#endif + + GetWINDOW(obj, winp); + if (wattr_get(winp->window, &attrs, &pair, NULL) == ERR) + return Qnil; + return rb_ary_new3(2, ULONG2NUM(attrs), INT2FIX(pair)); +} +#else +#define window_attr_get rb_f_notimplement +#endif + /* * Document-method: Curses::Window.bkgdset * call-seq: bkgdset(ch) @@ -5319,6 +5377,8 @@ Init_curses(void) rb_define_method(cWindow, "attroff", window_attroff, 1); rb_define_method(cWindow, "attron", window_attron, 1); rb_define_method(cWindow, "attrset", window_attrset, 1); + rb_define_method(cWindow, "attr_set", window_attr_set, 2); + rb_define_method(cWindow, "attr_get", window_attr_get, 0); rb_define_method(cWindow, "bkgdset", window_bkgdset, 1); rb_define_method(cWindow, "bkgd", window_bkgd, 1); rb_define_method(cWindow, "getbkgd", window_getbkgd, 0); From fdf92d133c1002363f41b959ca286f522bc01e53 Mon Sep 17 00:00:00 2001 From: Shugo Maeda Date: Fri, 6 Mar 2026 15:03:32 +0900 Subject: [PATCH 2/2] Fix type conversion macros in Window#attr_set and Window#attr_get - attr_set: NUM2ULONG -> NUM2UINT to match attr_t (unsigned int) - attr_get: ULONG2NUM -> UINT2NUM for attr_t; INT2FIX -> INT2NUM for pair number to safely handle extended pair values on all platforms Co-Authored-By: Claude Sonnet 4.6 --- ext/curses/curses.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/curses/curses.c b/ext/curses/curses.c index 1b31125d..265f6e1a 100644 --- a/ext/curses/curses.c +++ b/ext/curses/curses.c @@ -2970,7 +2970,7 @@ window_attr_set(VALUE obj, VALUE attrs, VALUE pair) struct windata *winp; GetWINDOW(obj, winp); - return (wattr_set(winp->window, NUM2ULONG(attrs), NUM2INT(pair), NULL) == OK) ? Qtrue : Qfalse; + return (wattr_set(winp->window, NUM2UINT(attrs), NUM2INT(pair), NULL) == OK) ? Qtrue : Qfalse; } #else #define window_attr_set rb_f_notimplement @@ -3003,7 +3003,7 @@ window_attr_get(VALUE obj) GetWINDOW(obj, winp); if (wattr_get(winp->window, &attrs, &pair, NULL) == ERR) return Qnil; - return rb_ary_new3(2, ULONG2NUM(attrs), INT2FIX(pair)); + return rb_ary_new3(2, UINT2NUM(attrs), INT2NUM(pair)); } #else #define window_attr_get rb_f_notimplement