@@ -98,6 +98,7 @@ rb_obj2chtype_inline(VALUE x)
98
98
99
99
static VALUE mCurses ;
100
100
static VALUE mKey ;
101
+ static VALUE cScreen ;
101
102
static VALUE cWindow ;
102
103
static VALUE cPad ;
103
104
#ifdef USE_MOUSE
@@ -220,6 +221,7 @@ check_curses_error(int error)
220
221
221
222
struct windata {
222
223
WINDOW * window ;
224
+ int is_stdscr ;
223
225
};
224
226
225
227
static VALUE window_attroff (VALUE obj , VALUE attrs );
@@ -242,7 +244,7 @@ static void
242
244
window_free (void * p )
243
245
{
244
246
struct windata * winp = p ;
245
- if (winp -> window && winp -> window != stdscr ) delwin (winp -> window );
247
+ if (winp -> window && ! winp -> is_stdscr ) delwin (winp -> window );
246
248
winp -> window = 0 ;
247
249
xfree (winp );
248
250
}
@@ -263,7 +265,7 @@ static const rb_data_type_t windata_type = {
263
265
};
264
266
265
267
static VALUE
266
- prep_window (VALUE class , WINDOW * window )
268
+ prep_window (VALUE class , WINDOW * window , int is_stdscr )
267
269
{
268
270
VALUE obj ;
269
271
struct windata * winp ;
@@ -275,6 +277,7 @@ prep_window(VALUE class, WINDOW *window)
275
277
obj = rb_obj_alloc (class );
276
278
TypedData_Get_Struct (obj , struct windata , & windata_type , winp );
277
279
winp -> window = window ;
280
+ winp -> is_stdscr = is_stdscr ;
278
281
279
282
return obj ;
280
283
}
@@ -311,7 +314,7 @@ curses_init_screen(VALUE self)
311
314
}
312
315
rb_set_end_proc (curses_finalize , 0 );
313
316
clear ();
314
- rb_stdscr = prep_window (cWindow , stdscr );
317
+ rb_stdscr = prep_window (cWindow , stdscr , 1 );
315
318
return rb_stdscr ;
316
319
}
317
320
@@ -1683,6 +1686,117 @@ curses_reset_prog_mode(VALUE obj)
1683
1686
#define curses_reset_prog_mode rb_f_notimplement
1684
1687
#endif
1685
1688
1689
+ /*-------------------------- class Screen --------------------------*/
1690
+
1691
+ struct screendata {
1692
+ SCREEN * screen ;
1693
+ VALUE stdscr ;
1694
+ };
1695
+
1696
+ NORETURN (static void no_screen (void ));
1697
+ static void
1698
+ no_screen (void )
1699
+ {
1700
+ rb_raise (rb_eRuntimeError , "no screen" );
1701
+ }
1702
+
1703
+ #define GetSCREEN (obj , screenp ) do {\
1704
+ TypedData_Get_Struct((obj), struct screendata, &screendata_type, (screenp));\
1705
+ if ((screenp)->screen == 0) no_screen();\
1706
+ } while (0)
1707
+
1708
+ static void
1709
+ screen_gc_mark (void * p )
1710
+ {
1711
+ struct screendata * screenp = p ;
1712
+
1713
+ rb_gc_mark (screenp -> stdscr );
1714
+ }
1715
+
1716
+ static void
1717
+ screen_free (void * p )
1718
+ {
1719
+ struct screendata * screenp = p ;
1720
+ if (screenp -> screen ) delscreen (screenp -> screen );
1721
+ screenp -> screen = 0 ;
1722
+ xfree (screenp );
1723
+ }
1724
+
1725
+ static size_t
1726
+ screen_memsize (const void * p )
1727
+ {
1728
+ const struct screendata * screenp = p ;
1729
+ size_t size = sizeof (* screenp );
1730
+ if (!screenp ) return 0 ;
1731
+ if (screenp -> screen ) size += CURSES_SIZEOF_SCREEN ;
1732
+ return size ;
1733
+ }
1734
+
1735
+ static const rb_data_type_t screendata_type = {
1736
+ "screendata" ,
1737
+ {screen_gc_mark , screen_free , screen_memsize ,}
1738
+ };
1739
+
1740
+ /* returns a Curses::Screen object */
1741
+ static VALUE
1742
+ screen_s_allocate (VALUE class )
1743
+ {
1744
+ struct screendata * screenp ;
1745
+
1746
+ return TypedData_Make_Struct (class , struct screendata , & screendata_type , screenp );
1747
+ }
1748
+
1749
+ /*
1750
+ * Document-method: Curses::Screen.new
1751
+ * call-seq: new(outf, inf, type=nil)
1752
+ *
1753
+ * Construct a new Curses::Screen.
1754
+ */
1755
+ static VALUE
1756
+ screen_initialize (int argc , VALUE * argv , VALUE obj )
1757
+ {
1758
+ VALUE outf , inf , type ;
1759
+ struct screendata * screenp ;
1760
+ rb_io_t * outfptr , * infptr ;
1761
+
1762
+ rb_scan_args (argc , argv , "21" , & outf , & inf , & type );
1763
+ TypedData_Get_Struct (obj , struct screendata , & screendata_type , screenp );
1764
+ if (screenp -> screen ) delscreen (screenp -> screen );
1765
+ Check_Type (outf , T_FILE );
1766
+ RB_IO_POINTER (outf , outfptr );
1767
+ rb_io_check_writable (outfptr );
1768
+ Check_Type (inf , T_FILE );
1769
+ RB_IO_POINTER (inf , infptr );
1770
+ rb_io_check_readable (infptr );
1771
+ screenp -> screen = newterm (NIL_P (type ) ? NULL : StringValueCStr (type ),
1772
+ rb_io_stdio_file (outfptr ),
1773
+ rb_io_stdio_file (infptr ));
1774
+ screenp -> stdscr = Qnil ;
1775
+
1776
+ return obj ;
1777
+ }
1778
+
1779
+ /*
1780
+ * Document-method: Curses::Screen.set_term
1781
+ * call-seq: set_term
1782
+ *
1783
+ * Set the current terminal.
1784
+ */
1785
+ static VALUE
1786
+ screen_set_term (VALUE obj )
1787
+ {
1788
+ struct screendata * screenp ;
1789
+
1790
+ GetSCREEN (obj , screenp );
1791
+ set_term (screenp -> screen );
1792
+ if (NIL_P (screenp -> stdscr )) {
1793
+ screenp -> stdscr = prep_window (cWindow , stdscr , 1 );
1794
+ }
1795
+ rb_stdscr = screenp -> stdscr ;
1796
+
1797
+ return Qnil ;
1798
+ }
1799
+
1686
1800
/*-------------------------- class Window --------------------------*/
1687
1801
1688
1802
/* returns a Curses::Window object */
@@ -1743,7 +1857,7 @@ window_subwin(VALUE obj, VALUE height, VALUE width, VALUE top, VALUE left)
1743
1857
l = NUM2INT (left );
1744
1858
GetWINDOW (obj , winp );
1745
1859
window = subwin (winp -> window , h , w , t , l );
1746
- win = prep_window (rb_obj_class (obj ), window );
1860
+ win = prep_window (rb_obj_class (obj ), window , 0 );
1747
1861
1748
1862
return win ;
1749
1863
}
@@ -1772,7 +1886,7 @@ window_derwin(VALUE obj, VALUE height, VALUE width, VALUE top, VALUE left)
1772
1886
l = NUM2INT (left );
1773
1887
GetWINDOW (obj , winp );
1774
1888
window = derwin (winp -> window , h , w , t , l );
1775
- win = prep_window (rb_obj_class (obj ), window );
1889
+ win = prep_window (rb_obj_class (obj ), window , 0 );
1776
1890
1777
1891
return win ;
1778
1892
}
@@ -3011,7 +3125,7 @@ pad_subpad(VALUE obj, VALUE height, VALUE width, VALUE begin_x, VALUE begin_y)
3011
3125
y = NUM2INT (begin_y );
3012
3126
GetWINDOW (obj , padp );
3013
3127
sub_pad = subpad (padp -> window , h , w , x , y );
3014
- pad = prep_window (rb_obj_class (obj ), sub_pad );
3128
+ pad = prep_window (rb_obj_class (obj ), sub_pad , 0 );
3015
3129
3016
3130
return pad ;
3017
3131
}
@@ -4998,6 +5112,32 @@ Init_curses(void)
4998
5112
rb_define_const (mCurses , "VERSION" , version );
4999
5113
}
5000
5114
5115
+ /*
5116
+ * Document-class: Curses::Screen
5117
+ *
5118
+ * == Description
5119
+ *
5120
+ * A Screen represents a terminal.
5121
+ * A program that outputs to more than one terminal should create a Screen
5122
+ * for each terminal instead of calling Curses.init_screen.
5123
+ *
5124
+ * == Usage
5125
+ *
5126
+ * require "curses"
5127
+ *
5128
+ * screen = Screen.new(STDOUT, STDIN, "xterm")
5129
+ * screen.set_term
5130
+ *
5131
+ * Curses.addstr("Hit any key")
5132
+ * Curses.refresh
5133
+ * Curses.getch
5134
+ * Curses.close_screen
5135
+ */
5136
+ cScreen = rb_define_class_under (mCurses , "Screen" , rb_cObject );
5137
+ rb_define_alloc_func (cScreen , screen_s_allocate );
5138
+ rb_define_method (cScreen , "initialize" , screen_initialize , -1 );
5139
+ rb_define_method (cScreen , "set_term" , screen_set_term , 0 );
5140
+
5001
5141
/*
5002
5142
* Document-class: Curses::Window
5003
5143
*
0 commit comments