@@ -766,6 +766,21 @@ console_beep(VALUE io)
766
766
return io ;
767
767
}
768
768
769
+ static int
770
+ mode_in_range (VALUE val , int high , const char * modename )
771
+ {
772
+ int mode ;
773
+ if (NIL_P (val )) return 0 ;
774
+ if (!RB_INTEGER_TYPE_P (val )) {
775
+ wrong_value :
776
+ rb_raise (rb_eArgError , "wrong %s mode: %" PRIsVALUE , modename , val );
777
+ }
778
+ if ((mode = NUM2INT (val )) < 0 || mode > high ) {
779
+ goto wrong_value ;
780
+ }
781
+ return mode ;
782
+ }
783
+
769
784
#if defined _WIN32
770
785
static VALUE
771
786
console_goto (VALUE io , VALUE x , VALUE y )
@@ -839,6 +854,87 @@ console_goto_column(VALUE io, VALUE val)
839
854
}
840
855
return io ;
841
856
}
857
+
858
+ static void
859
+ constat_clear (HANDLE handle , WORD attr , DWORD len , COORD pos )
860
+ {
861
+ DWORD written ;
862
+
863
+ FillConsoleOutputAttribute (handle , attr , len , pos , & written );
864
+ FillConsoleOutputCharacterW (handle , L' ' , len , pos , & written );
865
+ }
866
+
867
+ static VALUE
868
+ console_erase_line (VALUE io , VALUE val )
869
+ {
870
+ rb_io_t * fptr ;
871
+ HANDLE h ;
872
+ rb_console_size_t ws ;
873
+ COORD * pos = & ws .dwCursorPosition ;
874
+ DWORD written , w ;
875
+ int mode = mode_in_range (val , 2 , "line erase" );
876
+
877
+ GetOpenFile (io , fptr );
878
+ h = (HANDLE )rb_w32_get_osfhandle (GetWriteFD (fptr ));
879
+ if (!GetConsoleScreenBufferInfo (h , & ws )) {
880
+ rb_syserr_fail (LAST_ERROR , 0 );
881
+ }
882
+ w = winsize_col (& ws );
883
+ switch (mode ) {
884
+ case 0 : /* after cursor */
885
+ w -= pos -> X ;
886
+ break ;
887
+ case 1 : /* before *and* cursor */
888
+ w = pos -> X + 1 ;
889
+ pos -> X = 0 ;
890
+ break ;
891
+ case 2 : /* entire line */
892
+ pos -> X = 0 ;
893
+ break ;
894
+ }
895
+ constat_clear (h , ws .wAttributes , w , * pos );
896
+ return io ;
897
+ }
898
+
899
+ static VALUE
900
+ console_erase_screen (VALUE io , VALUE val )
901
+ {
902
+ rb_io_t * fptr ;
903
+ HANDLE h ;
904
+ rb_console_size_t ws ;
905
+ COORD * pos = & ws .dwCursorPosition ;
906
+ DWORD written , w ;
907
+ int mode = mode_in_range (val , 3 , "screen erase" );
908
+
909
+ GetOpenFile (io , fptr );
910
+ h = (HANDLE )rb_w32_get_osfhandle (GetWriteFD (fptr ));
911
+ if (!GetConsoleScreenBufferInfo (h , & ws )) {
912
+ rb_syserr_fail (LAST_ERROR , 0 );
913
+ }
914
+ w = winsize_col (& ws );
915
+ switch (mode ) {
916
+ case 0 : /* erase after cursor */
917
+ w = (w * (ws .srWindow .Bottom - pos -> Y + 1 ) - pos -> X );
918
+ break ;
919
+ case 1 : /* erase before *and* cursor */
920
+ w = (w * (pos -> Y - ws .srWindow .Top ) + pos -> X + 1 );
921
+ pos -> X = 0 ;
922
+ pos -> Y = ws .srWindow .Top ;
923
+ break ;
924
+ case 2 : /* erase entire screen */
925
+ w = (w * winsize_row (& ws ));
926
+ pos -> X = 0 ;
927
+ pos -> Y = ws .srWindow .Top ;
928
+ break ;
929
+ case 3 : /* erase entire screen */
930
+ w = (w * ws .dwSize .Y );
931
+ pos -> X = 0 ;
932
+ pos -> Y = 0 ;
933
+ break ;
934
+ }
935
+ constat_clear (h , ws .wAttributes , w , * pos );
936
+ return io ;
937
+ }
842
938
#include "win32_vk.inc"
843
939
844
940
static VALUE
@@ -949,6 +1045,22 @@ console_goto_column(VALUE io, VALUE val)
949
1045
rb_io_write (io , rb_sprintf ("\x1b[%dG" , NUM2UINT (val )+ 1 ));
950
1046
return io ;
951
1047
}
1048
+
1049
+ static VALUE
1050
+ console_erase_line (VALUE io , VALUE val )
1051
+ {
1052
+ int mode = mode_in_range (val , 2 , "line erase" );
1053
+ rb_io_write (io , rb_sprintf ("\x1b[%dK" , mode ));
1054
+ return io ;
1055
+ }
1056
+
1057
+ static VALUE
1058
+ console_erase_screen (VALUE io , VALUE val )
1059
+ {
1060
+ int mode = mode_in_range (val , 3 , "screen erase" );
1061
+ rb_io_write (io , rb_sprintf ("\x1b[%dJ" , mode ));
1062
+ return io ;
1063
+ }
952
1064
# define console_key_pressed_p rb_f_notimplement
953
1065
#endif
954
1066
@@ -1221,6 +1333,9 @@ InitVM_console(void)
1221
1333
rb_define_method (rb_cIO , "cursor_left" , console_cursor_left , 1 );
1222
1334
rb_define_method (rb_cIO , "cursor_right" , console_cursor_right , 1 );
1223
1335
rb_define_method (rb_cIO , "goto_column" , console_goto_column , 1 );
1336
+ rb_define_method (rb_cIO , "erase_line" , console_erase_line , 1 );
1337
+ rb_define_method (rb_cIO , "erase_screen" , console_erase_screen , 1 );
1338
+ rb_define_method (rb_cIO , "clear_screen" , console_clear_screen , 0 );
1224
1339
rb_define_method (rb_cIO , "pressed?" , console_key_pressed_p , 1 );
1225
1340
#if ENABLE_IO_GETPASS
1226
1341
rb_define_method (rb_cIO , "getpass" , console_getpass , -1 );
0 commit comments