@@ -297,6 +297,19 @@ static inline unsigned short *screenpos(const struct vc_data *vc, int offset,
297297 return p ;
298298}
299299
300+ static inline unsigned short * screenpos_utf8 (const struct vc_data * vc , int offset , bool viewed )
301+ {
302+ unsigned short * p ;
303+
304+ if (!viewed )
305+ p = (unsigned short * )(vc -> vc_origin + offset + vc -> vc_screenbuf_size );
306+ else if (!vc -> vc_sw -> con_screen_pos )
307+ p = (unsigned short * )(vc -> vc_visible_origin + offset + vc -> vc_screenbuf_size );
308+ else
309+ p = vc -> vc_sw -> con_screen_pos (vc , - offset - 1 );
310+ return p ;
311+ }
312+
300313/* Called from the keyboard irq path.. */
301314static inline void scrolldelta (int lines )
302315{
@@ -583,6 +596,11 @@ static void con_scroll(struct vc_data *vc, unsigned int top,
583596 }
584597 scr_memmovew (dst , src , (rows - nr ) * vc -> vc_size_row );
585598 scr_memsetw (clear , vc -> vc_video_erase_char , vc -> vc_size_row * nr );
599+
600+ dst += (vc -> vc_screenbuf_size >> 1 );
601+ src += (vc -> vc_screenbuf_size >> 1 );
602+ scr_memmovew (dst , src , (rows - nr ) * vc -> vc_size_row );
603+ scr_memsetw (clear , 0 , vc -> vc_size_row * nr );
586604}
587605
588606static void do_update_region (struct vc_data * vc , unsigned long start , int count )
@@ -751,14 +769,16 @@ void complement_pos(struct vc_data *vc, int offset)
751769 static int old_offset = -1 ;
752770 static unsigned short old ;
753771 static unsigned short oldx , oldy ;
772+ static unsigned short * p_ext = NULL ;
773+ static unsigned short old_ext = 0 ;
754774
755775 WARN_CONSOLE_UNLOCKED ();
756776
757777 if (old_offset != -1 && old_offset >= 0 &&
758778 old_offset < vc -> vc_screenbuf_size ) {
759779 scr_writew (old , screenpos (vc , old_offset , true));
760780 if (con_should_update (vc ))
761- vc -> vc_sw -> con_putc (vc , old , oldy , oldx );
781+ vc -> vc_sw -> con_putc (vc , ( old_ext << 16 )| old , oldy , oldx );
762782 notify_update (vc );
763783 }
764784
@@ -769,13 +789,15 @@ void complement_pos(struct vc_data *vc, int offset)
769789 unsigned short new ;
770790 unsigned short * p ;
771791 p = screenpos (vc , offset , true);
792+ p_ext = screenpos_utf8 (vc , offset , true);
772793 old = scr_readw (p );
794+ old_ext = scr_readw (p_ext );
773795 new = old ^ vc -> vc_complement_mask ;
774796 scr_writew (new , p );
775797 if (con_should_update (vc )) {
776798 oldx = (offset >> 1 ) % vc -> vc_cols ;
777799 oldy = (offset >> 1 ) / vc -> vc_cols ;
778- vc -> vc_sw -> con_putc (vc , new , oldy , oldx );
800+ vc -> vc_sw -> con_putc (vc , ( old_ext << 16 )| new , oldy , oldx );
779801 }
780802 notify_update (vc );
781803 }
@@ -1088,7 +1110,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
10881110 vc -> vc_screenbuf_size > KMALLOC_MAX_SIZE || !vc -> vc_screenbuf_size )
10891111 goto err_free ;
10901112 err = - ENOMEM ;
1091- vc -> vc_screenbuf = kzalloc (vc -> vc_screenbuf_size , GFP_KERNEL );
1113+ vc -> vc_screenbuf = kzalloc (vc -> vc_screenbuf_size * 2 , GFP_KERNEL );
10921114 if (!vc -> vc_screenbuf )
10931115 goto err_free ;
10941116
@@ -1141,7 +1163,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
11411163{
11421164 unsigned long old_origin , new_origin , new_scr_end , rlth , rrem , err = 0 ;
11431165 unsigned long end ;
1144- unsigned int old_rows , old_row_size , first_copied_row ;
1166+ unsigned int old_rows , old_row_size , first_copied_row , old_screen_size ;
11451167 unsigned int new_cols , new_rows , new_row_size , new_screen_size ;
11461168 unsigned int user ;
11471169 unsigned short * oldscreen , * newscreen ;
@@ -1185,7 +1207,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
11851207
11861208 if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size )
11871209 return - EINVAL ;
1188- newscreen = kzalloc (new_screen_size , GFP_USER );
1210+ newscreen = kzalloc (new_screen_size * 2 , GFP_USER );
11891211 if (!newscreen )
11901212 return - ENOMEM ;
11911213
@@ -1202,6 +1224,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
12021224
12031225 old_rows = vc -> vc_rows ;
12041226 old_row_size = vc -> vc_size_row ;
1227+ old_screen_size = vc -> vc_screenbuf_size ;
12051228
12061229 err = resize_screen (vc , new_cols , new_rows , user );
12071230 if (err ) {
@@ -1250,15 +1273,23 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
12501273 while (old_origin < end ) {
12511274 scr_memcpyw ((unsigned short * ) new_origin ,
12521275 (unsigned short * ) old_origin , rlth );
1253- if (rrem )
1276+ scr_memcpyw ((unsigned short * ) new_origin + (new_screen_size >> 1 ),
1277+ (unsigned short * ) old_origin + (old_screen_size >> 1 ), rlth );
1278+ if (rrem ){
12541279 scr_memsetw ((void * )(new_origin + rlth ),
12551280 vc -> vc_video_erase_char , rrem );
1281+ scr_memsetw ((void * )(new_origin + rlth + (new_screen_size )),
1282+ 0x00 , rrem );
1283+ }
12561284 old_origin += old_row_size ;
12571285 new_origin += new_row_size ;
12581286 }
1259- if (new_scr_end > new_origin )
1287+ if (new_scr_end > new_origin ){
12601288 scr_memsetw ((void * )new_origin , vc -> vc_video_erase_char ,
12611289 new_scr_end - new_origin );
1290+ scr_memsetw ((void * )new_origin + (new_screen_size ), 0x00 ,
1291+ new_scr_end - new_origin );
1292+ }
12621293 oldscreen = vc -> vc_screenbuf ;
12631294 vc -> vc_screenbuf = newscreen ;
12641295 vc -> vc_screenbuf_size = new_screen_size ;
@@ -2744,11 +2775,16 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c,
27442775 u16 himask = vc -> vc_hi_font_mask , charmask = himask ? 0x1ff : 0xff ;
27452776 u8 width = 1 ;
27462777 bool inverse = false;
2778+ int is_utf8 = 0 ;
2779+ int tc_1 = 0xfe ;
2780+ uint32_t utf8_c = c ;
27472781
27482782 if (vc -> vc_utf && !vc -> vc_disp_ctrl ) {
27492783 if (is_double_width (c ))
27502784 width = 2 ;
27512785 }
2786+ if (utf8_c > 0x7f )
2787+ is_utf8 = 1 ;
27522788
27532789 /* Now try to find out how to display it */
27542790 tc = conv_uni_to_pc (vc , tc );
@@ -2787,6 +2823,10 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c,
27872823 }
27882824
27892825 next_c = c ;
2826+ if (is_utf8 == 1 ){
2827+ tc = 0xff ;
2828+ next_c = 0xff ;
2829+ }
27902830 while (1 ) {
27912831 if (vc -> vc_need_wrap || vc -> vc_decim )
27922832 con_flush (vc , draw );
@@ -2805,6 +2845,10 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c,
28052845
28062846 scr_writew (tc , (u16 * )vc -> vc_pos );
28072847
2848+ if (is_utf8 == 1 ) {
2849+ scr_writew (utf8_c , (u16 * ) vc -> vc_pos + (vc -> vc_screenbuf_size >> 1 ));
2850+ }
2851+
28082852 if (con_should_update (vc ) && draw -> x < 0 ) {
28092853 draw -> x = vc -> state .x ;
28102854 draw -> from = vc -> vc_pos ;
@@ -2821,10 +2865,10 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c,
28212865 break ;
28222866
28232867 /* A space is printed in the second column */
2824- tc = conv_uni_to_pc (vc , ' ' );
2868+ tc = conv_uni_to_pc (vc , tc_1 );
28252869 if (tc < 0 )
2826- tc = ' ' ;
2827- next_c = ' ' ;
2870+ tc = tc_1 ;
2871+ next_c = tc_1 ;
28282872 }
28292873 notify_write (vc , c );
28302874
@@ -3472,7 +3516,7 @@ static int __init con_init(void)
34723516 tty_port_init (& vc -> port );
34733517 visual_init (vc , currcons , 1 );
34743518 /* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */
3475- vc -> vc_screenbuf = kzalloc (vc -> vc_screenbuf_size , GFP_NOWAIT );
3519+ vc -> vc_screenbuf = kzalloc (vc -> vc_screenbuf_size * 2 , GFP_NOWAIT );
34763520 vc_init (vc , vc -> vc_rows , vc -> vc_cols ,
34773521 currcons || !vc -> vc_sw -> con_save_screen );
34783522 }
@@ -4599,8 +4643,6 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op)
45994643 return - EINVAL ;
46004644 if (!op -> data )
46014645 return - EINVAL ;
4602- if (op -> charcount > max_font_glyphs )
4603- return - EINVAL ;
46044646 if (op -> width <= 0 || op -> width > max_font_width || !op -> height ||
46054647 op -> height > max_font_height )
46064648 return - EINVAL ;
@@ -4694,9 +4736,15 @@ u16 screen_glyph(const struct vc_data *vc, int offset)
46944736 u16 w = scr_readw (screenpos (vc , offset , true));
46954737 u16 c = w & 0xff ;
46964738
4739+ u16 c_utf8 = scr_readw (screenpos_utf8 (vc , offset , true));
4740+
4741+ if ( (c == 0xff || c == 0xfe ) && c_utf8 != 0 ){
4742+ return c_utf8 ;
4743+ }else {
46974744 if (w & vc -> vc_hi_font_mask )
46984745 c |= 0x100 ;
46994746 return c ;
4747+ }
47004748}
47014749EXPORT_SYMBOL_GPL (screen_glyph );
47024750
@@ -4707,7 +4755,7 @@ u32 screen_glyph_unicode(const struct vc_data *vc, int n)
47074755 if (uni_lines )
47084756 return uni_lines [n / vc -> vc_cols ][n % vc -> vc_cols ];
47094757
4710- return inverse_translate ( vc , screen_glyph (vc , n * 2 ), true );
4758+ return screen_glyph (vc , n * 2 );
47114759}
47124760EXPORT_SYMBOL_GPL (screen_glyph_unicode );
47134761
0 commit comments