(fwd) patch: Linux console BIG cursor & contents saving/restoring

William Burrow (aa126@fan1.fan.nb.ca)
Mon, 10 Feb 1997 12:16:12 -0400 (AST)


---------- Forwarded message ----------
From: Sergey_Korshunoff@p5.f434.n5020.z2.fidonet.org
Subject: patch: Linux console BIG cursor & contents saving/restoring
Date: 29 Jan 1997 19:39:30 GMT
Message-ID: <4s10ti$non@at40.seyko.msk.su>

Hello! There is a linux-2.0.18 console patch for big cursor and
screen contents saving support. Sorry for posting to news group
but I can not send it to mail list (broken e-mail link). It is
not so big.

Escape sequence for big cursor on/off I choose like for
AT&T 610; 80 column; 98key keyboard
AT&T 620; 80 column; 98key keyboard
AT&T 730 windowing terminal

Normal cursor \E[?25h\E[?12l ( \E[?12l added )
Big cursor \E[?25h\E[?12h ( \E[?12h added )
Invisble cursor \E[?25l ( not changed )

Save contents is like for xterm - \E[?47h for save console contents
and \E[?47l for restoring.

You need to change console type from "linux" to "linux2"
in /etc/inittab like

1:1234:respawn:/sbin/getty tty1 VC linux2
2:234:respawn:/sbin/getty tty2 VC linux2

or set "TERM=linux2" in /etc/profile.

"vi", "crisp", SLang curses based games now restore contents on exit
without recompilation. NCURSES 1.9.9e has bug wich don't allow application
to get strings for "smcup", "rmcup" (this may be my fault, but I
can not make ncurses return non zero for this values). If You recompile
"wpe" with TERMCAP or modify it not to search terminfo but use default ones,
then "wpe" will allow You to see user program screen when debuging
on console.

There is no big cursor patch for tga.c (only vga.c). You are welcome
to write one.

Cost for console contents saving -- there may be two screen buffers
for virtual console if curses based program don't switch back on exit.
But
for t in $SCREENS
do
echo -n -e "\\033[?47l" > /dev/$t
done

bash script would free all screen saver buffers in this case. As I
say -- ncurses 1.9.9e based programs can't use this feature,
and Slang curses library is safe.

No kernel memory wasted when You don't run curses based programs.

Regards,
Sergey Ya. Korshunoff p5.f434.n5020.z2.fidonet.org

PS: this work even on telnet sessions. Midnight Commander can
throw away SUID "cons.saver" and don't more say

Not an xterm or Linux console
the panels cannot be toggled.

But MC has strange detection of color terminals. You need
add enviroment variable COLORTERM or call as "mc -c"
to get colors back with linux2.

PPS: no cursor visibility is saved by save cursor sequence.
I added \E[?25h to xterm rmcup sequence.

+-----0<-----------------------------0<----------------------
# new termcap entry for linux console with big cursor and
# screen contents saving support.

linux2:\
:vi=\E[?25l:ve=\E[?25h\E[?12l:vs=\E[?25h\E[?12h:\
:ti=\E7\E[?47h:te=\E[2J\E[?47l\E8\E[?25h:\
:tc=linux:

+-----0<-----------------------------0<----------------------
# new terminfo entry for linux console with big cursor and
# screen contents saving support.

linux2|linux with big cursor and console contents saving support,
cnorm=\E[?25h\E[?12l, cvvis=\E[?25;12h,
smcup=\E7\E[?47h, rmcup=\E[2J\E[?47l\E8\E[?25h, use=linux,
+-----0<-----------------------------0<----------------------
--- drivers/char/console.c.old Mon Sep 2 09:41:25 1996
+++ drivers/char/console.c Wed Jan 29 05:17:05 1997
@@ -124,8 +124,12 @@
static struct termios *console_termios[MAX_NR_CONSOLES];
static struct termios *console_termios_locked[MAX_NR_CONSOLES];
unsigned short *vc_scrbuf[MAX_NR_CONSOLES];
+unsigned short *vc_saved_buf[MAX_NR_CONSOLES];
struct vc vc_cons [MAX_NR_CONSOLES];

+#define SAVED_SIZE (2*vc_saved_buf[currcons][0]*vc_saved_buf[currcons][1]+4)
+
+
static void con_setsize(unsigned long rows, unsigned long cols);
static void vc_init(unsigned int console, unsigned long rows,
unsigned long cols, int do_clear);
@@ -139,6 +143,7 @@
static void gotoxy(int currcons, int new_x, int new_y);
static void save_cur(int currcons);
extern void set_cursor(int currcons);
+extern void resize_cursor(int currcons);
extern void hide_cursor(void);
static void reset_terminal(int currcons, int do_clear);
extern void reset_vc(unsigned int new_console);
@@ -153,6 +158,8 @@
extern unsigned long con_type_init(unsigned long, const char **);
extern int set_get_cmap(unsigned char *, int);
extern int set_get_font(unsigned char *, int, int);
+static void save_screen_buffer(int currcons);
+static void restore_screen_buffer(int currcons);

/* Description of the hardware situation */
unsigned char video_type; /* Type of display being used */
@@ -330,6 +337,7 @@
p += sizeof(struct vc_data);
vt_cons[i] = (struct vt_struct *) p;
vc_scrbuf[i] = (unsigned short *) q;
+ vc_saved_buf[i] = (unsigned short *) 0;
vc_cons[i].d->vc_kmalloced = 1;
vc_cons[i].d->vc_screenbuf_size = video_screen_size;
vc_init (i, video_num_lines, video_num_columns, 1);
@@ -427,12 +435,12 @@
top = 0;
bottom = video_num_lines;
gotoxy(currcons, x, y);
- save_cur(currcons);
}

set_scrmem(fg_console, 0);
set_origin(fg_console);
set_cursor(fg_console);
+ resize_cursor(fg_console);

return 0;
}
@@ -442,6 +450,10 @@
if (vc_cons_allocated(currcons)) {
if (kmalloced)
kfree_s(vc_scrbuf[currcons], screenbuf_size);
+ if (vc_saved_buf[currcons]) {
+ kfree_s(vc_saved_buf[currcons], SAVED_SIZE );
+ vc_saved_buf[currcons] = 0;
+ }
if (currcons >= MIN_NR_CONSOLES)
kfree_s(vc_cons[currcons].d, structsize);
vc_cons[currcons].d = 0;
@@ -1096,10 +1108,18 @@
case 9:
report_mouse = on_off ? 1 : 0;
break;
+ case 12: /* Cursor size */
+ big_cursor = on_off;
+ resize_cursor(currcons);
+ break;
case 25: /* Cursor on/off */
deccm = on_off;
set_cursor(currcons);
break;
+ case 47:
+ if( on_off ) save_screen_buffer(currcons);
+ else restore_screen_buffer(currcons);
+ break;
case 1000:
report_mouse = on_off ? 2 : 0;
break;
@@ -1255,6 +1275,7 @@
{
saved_x = x;
saved_y = y;
+ s_big_cursor = big_cursor;
s_intensity = intensity;
s_underline = underline;
s_blink = blink;
@@ -1279,6 +1300,9 @@
translate = set_translate(charset ? G1_charset : G0_charset);
update_attr(currcons);
need_wrap = 0;
+
+ big_cursor = s_big_cursor;
+ resize_cursor(currcons);
}

enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
@@ -1307,6 +1331,7 @@
decom = 0;
decawm = 1;
deccm = 1;
+ big_cursor = 0;
decim = 0;

set_kbd(decarm);
@@ -2051,6 +2076,7 @@
vt_cons[currcons] = (struct vt_struct *) kmem_start;
kmem_start += sizeof(struct vt_struct);
vc_scrbuf[currcons] = (unsigned short *) kmem_start;
+ vc_saved_buf[currcons] = 0;
kmem_start += video_screen_size;
kmalloced = 0;
screenbuf_size = video_screen_size;
@@ -2238,6 +2264,7 @@
set_scrmem(fg_console, 0);
set_origin(fg_console);
set_cursor(fg_console);
+ resize_cursor(fg_console);
set_leds();
compute_shiftstate();
lock = 0;
@@ -2317,3 +2344,64 @@
{
return set_get_font (arg,0,video_mode_512ch);
}
+
+void save_screen_buffer(int currcons)
+{
+ unsigned long columns;
+ unsigned long lines;
+
+ unsigned short *src;
+ unsigned short *dst;
+
+ columns = video_num_columns;
+ lines = video_num_lines;
+
+ if (vc_saved_buf[currcons])
+ kfree_s(vc_saved_buf[currcons], SAVED_SIZE );
+ vc_saved_buf[currcons] = (unsigned short *) kmalloc(2 * columns * lines + 4, GFP_KERNEL);
+ if (!vc_saved_buf[currcons])
+ return;
+ vc_saved_buf[currcons][0] = columns;
+ vc_saved_buf[currcons][1] = lines;
+
+ dst = &vc_saved_buf[currcons][2];
+ src = (unsigned short *)origin;
+
+ memcpyw( dst, src, 2 * columns * lines);
+}
+
+void restore_screen_buffer(int currcons)
+{
+ unsigned long columns, col;
+ unsigned long lines, lin, l;
+ unsigned short *src;
+ unsigned short *dst;
+
+ if (!vc_saved_buf[currcons])
+ return;
+
+ if (currcons == fg_console && vcmode == KD_GRAPHICS) {
+ kfree_s(vc_saved_buf[currcons], SAVED_SIZE );
+ vc_saved_buf[currcons] = 0;
+ return;
+ }
+
+ columns = vc_saved_buf[currcons][0];
+ lines = vc_saved_buf[currcons][1];
+
+ col = MIN(columns,video_num_columns);
+ lin = MIN(lines,video_num_lines);
+
+ src = &vc_saved_buf[currcons][2];
+ dst = (unsigned short *)origin;
+
+ for (l=0; l<lin; l++) {
+ memcpyw(dst, src, 2 * col);
+ src += columns;
+ dst += video_num_columns;
+ }
+
+ kfree_s(vc_saved_buf[currcons], SAVED_SIZE );
+ vc_saved_buf[currcons] = 0;
+}
+
--- drivers/char/console_struct.h.old Tue Nov 21 09:34:54 1995
+++ drivers/char/console_struct.h Tue Jan 28 15:12:57 1997
@@ -37,6 +37,8 @@
unsigned long vc_deccm : 1; /* Cursor Visible */
unsigned long vc_decim : 1; /* Insert Mode */
unsigned long vc_deccolm : 1; /* 80/132 Column Mode */
+ unsigned long vc_big_cursor : 1; /* Cursor size */
+ unsigned long vc_s_big_cursor : 1; /* Saved cursor size */
/* attribute flags */
unsigned long vc_intensity : 2; /* 0=half-bright, 1=normal, 2=bold */
unsigned long vc_underline : 1;
@@ -85,6 +87,7 @@
#define bottom (vc_cons[currcons].d->vc_bottom)
#define x (vc_cons[currcons].d->vc_x)
#define y (vc_cons[currcons].d->vc_y)
+#define big_cursor (vc_cons[currcons].d->vc_big_cursor)
#define vc_state (vc_cons[currcons].d->vc_state)
#define npar (vc_cons[currcons].d->vc_npar)
#define par (vc_cons[currcons].d->vc_par)
@@ -92,6 +95,7 @@
#define attr (vc_cons[currcons].d->vc_attr)
#define saved_x (vc_cons[currcons].d->vc_saved_x)
#define saved_y (vc_cons[currcons].d->vc_saved_y)
+#define s_big_cursor (vc_cons[currcons].d->vc_s_big_cursor)
#define translate (vc_cons[currcons].d->vc_translate)
#define G0_charset (vc_cons[currcons].d->vc_G0_charset)
#define G1_charset (vc_cons[currcons].d->vc_G1_charset)
@@ -139,3 +143,5 @@

#define vcmode (vt_cons[currcons]->vc_mode)
#define structsize (sizeof(struct vc_data) + sizeof(struct vt_struct))
+
+
--- drivers/char/vga.c.old Tue May 7 08:50:53 1996
+++ drivers/char/vga.c Tue Jan 28 10:22:01 1997
@@ -116,6 +116,41 @@
outb_p(0xff&((video_mem_term-video_mem_base)>>1), video_port_val);
}

+
+void
+resize_cursor(int currcons)
+{
+ unsigned long flags;
+ unsigned fsr;
+ unsigned curs, cure;
+
+ if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
+ return;
+
+ save_flags(flags); cli();
+ outb_p( 0x09, video_port_reg ); /* Font size register */
+ fsr = inb_p(video_port_val);
+ outb_p( 0x0a, video_port_reg ); /* Cursor start */
+ curs = inb_p(video_port_val);
+ outb_p( 0x0b, video_port_reg ); /* Cursor end */
+ cure = inb_p(video_port_val);
+ restore_flags(flags);
+
+ fsr = fsr & 0x1f;
+
+ if (big_cursor) curs = (curs & 0xc0);
+ else curs = (curs & 0xc0) + fsr - (fsr < 9 ? 1 : 2);
+
+ cure = (cure & 0xe0) + fsr - (fsr < 9 ? 0 : 1);
+
+ cli();
+ outb_p( 0x0a, video_port_reg ); /* Cursor start */
+ outb_p( curs, video_port_val );
+ outb_p( 0x0b, video_port_reg ); /* Cursor end */
+ outb_p( cure, video_port_val );
+ restore_flags(flags);
+}
+
void
set_cursor(int currcons)
{
@@ -125,6 +160,7 @@
return;
if (__real_origin != __origin)
__set_origin(__real_origin);
+
save_flags(flags); cli();
if (deccm) {
outb_p(14, video_port_reg);
@@ -509,8 +545,11 @@
ovr = (ovr & 0xbd) + /* Overflow register */
((maxscan & 0x100) >> 7) +
((maxscan & 0x200) >> 3);
+
fsr = (fsr & 0xe0) + (fontheight-1); /* Font size register */
- curs = (curs & 0xc0) + fontheight - (fontheight < 10 ? 2 : 3);
+
+ if( (curs & 0xc0) != curs )
+ curs = (curs & 0xc0) + fontheight - (fontheight < 10 ? 2 : 3);
cure = (cure & 0xe0) + fontheight - (fontheight < 10 ? 1 : 2);

cli();
+-----0<-----------------------------0<----------------------

--
--
William Burrow  --  Fredericton Area Network, New Brunswick, Canada
Copyright 1997 William Burrow  
This line left intentionally blank.
And the one below it.