[comp.unix.questions] Curses: Drawing Boxes -- sending control chars

russ@wpg.UUCP (Russell Lawrence) (08/26/88)

The curses box() function draws crude boxes around windows using ascii 
characters like '|' and '-' that are passed to the function as 
arguments.  By contrast, I'd like to write a better box drawing routine 
that would take advantage of box drawing graphics capabilities on some 
terminals.  Unfortunately, the terminfo definitions don't include any 
parameters that would be appropriate, and the tic(1M) program won't 
allow me to define new ones.  I figured I could get around the problem 
by concocting a small database containing the command strings for the 
various terminals we use in our office, but then I remembered that 
curses functions won't allow me to send unadulterated control characters 
to the terminal.  Can anybody suggest a work around?  
-- 
Russell Lawrence, WP Group, New Orleans (504) 456-0001
{uunet,killer}!wpg!russ

daveh@marob.MASA.COM (Dave Hammond) (08/27/88)

In article <873@wpg.UUCP> russ@wpg.UUCP (Russell Lawrence) writes:
>
>The curses box() function draws crude boxes around windows using ascii 
>characters like '|' and '-' that are passed to the function as 
>arguments.  By contrast, I'd like to write a better box drawing routine 
>that would take advantage of box drawing graphics capabilities on some 
>terminals.  Unfortunately, the terminfo definitions don't include any 
>parameters that would be appropriate, and the tic(1M) program won't 
>allow me to define new ones........................................... 

I was under the impression that terminfo-based curses allow characters
from an alternate characterset to be output (like line-drawing chars)
by or-ing them with A_ALTCHARSET.  Assuming that your terminal did graphics
by changing fonts and associating `characters' within that font with
graphics symbols, you should be able to say something like:

/* these are based on a vt100 */
#define GV 'x'
#define GH 'q'
(void) wbox(stdscr, GH | A_ALTCHARSET, GV | A_ALTCHARSET);

>............................  I figured I could get around the problem 
>by concocting a small database containing the command strings for the 
>various terminals we use in our office, but then I remembered that 
>curses functions won't allow me to send unadulterated control characters 
>to the terminal.  Can anybody suggest a work around?  

Note that the graphics capabilities GS (graphics start), GE (graphics end),
GH, GV and G1 thru G4 already exist in the /etc/termcap database.  If you're
so inclined (and your Curses doesn't already set them for you!), you could
find the appropriate strings there.

As far as curses allowing unadulterated contol characters in its output,
I believe that is version-dependent.  In many versions you must specifically
call unctrl(ch) to output the expanded string representation of control chars
(i.e. unctrl('\003') outputs `^C').

If you're gonna do this in a Curses program, but independent of Curses, you
must beware that you will get will get a box, but Curses will have no idea
that it is there and will step all over it.

If you try to output the box using Curses, you will have to send a
sequence of GS,GV,GE or GS,GH,GE for each component of the box. This
will cause Curses to think the graphics string takes as many line spaces
as there are bytes in the sequence and it will end up confused as to
where the end of the line is.

If you have access to terminfo, I suggest you use the A_ALTCHARSET
method. If not, you'll have to output the box using curses (so it knows
the thing is there), then overwrite it after EACH refresh() with your
own graphics box routine. This can make a LOT of extra terminal output.

Dave Hammond
  UUCP: {uunet|...}!masa.com!{dsix2|marob}!daveh
DOMAIN: dsix2!daveh@masa.com
------------------------------------------------------------------------------

mfp@sobeco.UUCP (Mark F. Proudman) (08/28/88)

In article <873@wpg.UUCP>, russ@wpg.UUCP (Russell Lawrence) writes:
> 
> The curses box() function draws crude boxes around windows using ascii 
> characters like '|' and '-' that are passed to the function as 
> arguments.  By contrast, I'd like to write a better box drawing routine 
> that would take advantage of box drawing graphics capabilities on some 
> terminals.  Unfortunately, the terminfo definitions don't include any 

I have just written a menu handler, to run on vt[123]xx terminals.
The attribute bits of each curses displayed character include one
#defined as A_PROTECT.  Normally useless; I changed the terminfo sgr
string so that A_PROTECT (p8 I think) invokes a change to graphics 
character set sequence.  When I want a graphic, I just addch the ascii
equivalent, with A_PROTECT on.

Of course, your box routine  will have to know which character
position each graphic is in.  Possibly download a DEC compatible graphic
character set, if your terminals don't have one.  Or implement your
idea of a database of graphic characters:  Having stolen an attribute
bit, you won't need escape sequences in the database.  Or simply put a
lot of if's in your code (gross, non portable but effective).


Mark Proudman	uunet!attcan!sobeco!mfp
		(514) 878 9090
"It is agreed that the ice is thin here" - K&R.

clindh@Stride.COM (Christer Lindh) (08/30/88)

From article <384@marob.MASA.COM>, by daveh@marob.MASA.COM (Dave Hammond):
> I was under the impression that terminfo-based curses allow characters
> from an alternate characterset to be output (like line-drawing chars)
> by or-ing them with A_ALTCHARSET.  

That is right. What the terminfo in System 5.2 *doesn't* supply is field
where you can tell curses what character should be sent for 'Top Left
Corner' etc. System 5.3 terminfo has this, and 5.3 curses uses this
map to draw boxes with a alternate character set. It works pretty well.
This mapstring in 5.3 maps from 'vt100' characters to your terminal.

I did a a kludge using 5.2 curses, I put the ACS-table in the field
'is3' which is seldom used. I then parsed it and created a map-table
just after initscr(). I rewrote box() to use ACS characters, and
supplied all the defines curses5.3 uses (ACS_PLUS etc).  Works fine.

-- 
 clindh@stride.COM (Cybernerd)   ::      Remember when we said there is
   Stride Product Group, R&D     ::                no future ?
MicroSage Computer Systems, Inc. ::             We're there now...
    Reno, NV, (702) 322-6868     ::                              -Blank Reg

greim@sbsvax.UUCP (Michael Greim) (08/30/88)

In article <338@sobeco.UUCP>, mfp@sobeco.UUCP (Mark F. Proudman) writes:
> In article <873@wpg.UUCP>, russ@wpg.UUCP (Russell Lawrence) writes:
> > 
> > The curses box() function draws crude boxes around windows using ascii 
> > characters like '|' and '-' that are passed to the function as 
> > arguments.  By contrast, I'd like to write a better box drawing routine 
> > that would take advantage of box drawing graphics capabilities on some 
> > terminals.  Unfortunately, the terminfo definitions don't include any 
> 
> I have just written a menu handler, to run on vt[123]xx terminals.
> The attribute bits of each curses displayed character include one
> #defined as A_PROTECT.  Normally useless; I changed the terminfo sgr
> string so that A_PROTECT (p8 I think) invokes a change to graphics 
> character set sequence.  When I want a graphic, I just addch the ascii
> equivalent, with A_PROTECT on.
> 
> Of course, your box routine  will have to know which character
> position each graphic is in.  Possibly download a DEC compatible graphic
> character set, if your terminals don't have one.  Or implement your
> idea of a database of graphic characters:  Having stolen an attribute
> bit, you won't need escape sequences in the database.  Or simply put a
> lot of if's in your code (gross, non portable but effective).
> 
I have written an extension to 4.3BSD curses, which I called CURRY.
Curry uses termcap, I had no terminfo sources then. You can specify
4 attributes (reverse, blink, underline, half intens) and use characters
from 4 character sets.
I added some capabilities to termcap:
	r0-r9, ra-rf : strings to turn on attributes reverse, blink, underline
			and halfintensity and the combinations thereof.
	s0-s3 : si means switch to character set i
	SG : string of pairs (number, character); number is the character set
		number (0 - 3), character is any ASCII character.
		The positions in this string have meaning, the first entry is
		horizontal bar, the second vertical bar, the third the upper
		left corner, ...
With these I could rewrite box so that it uses the characters with
their character set attribute in SG.

I have written some demo programs which use these line drawing (semi
graphic) characters. I changed some of these to use terminfo, just
to see, how the performance might change. For this I had a problem
similar to yours.

With terminfo I would suggest, if you cannot or don't want to change
terminfo that you specified an environment variable containing
- vertical bar char
- horizontal bar char
- top left corner
...
Write a new terminfo entry using as smacs (start alternate character set) and
rmacs (end alternate character set) the sequences for "turn on semi
graphics mode" and "turn off semi graphics mode".
Then write your own routine to box a portion of the screen using the
characters from the environment variable with the A_ALTCHARSET attribute.

If you find this a kludge or too ugly, you will have to change
terminfo. But let me know, because in the near future I will do a
rewrite of Pavel Curtis pcurses and terminfo package,
while including good features from my Curry.

	-mg
-- 
UUCP:  ...!uunet!unido!sbsvax!greim   | Michael T. Greim
       or greim@sbsvax.UUCP           | Universitaet des Saarlandes
CSNET: greim%sbsvax.uucp@Germany.CSnet| FB 10 - Informatik (Dept. of CS)
ARPA:  greim%sbsvax.uucp@uunet.UU.NET | Bau 36, Im Stadtwald 15
voice: +49 681 302 2434               | D-6600 Saarbruecken 11, West Germany

# include <disclaimers/std.h>

domo@riddle.UUCP (Dominic Dunlop) (09/05/88)

In article <873@wpg.UUCP> russ@wpg.UUCP (Russell Lawrence) writes:
>
>The curses box() function draws crude boxes around windows using ascii 
>characters like '|' and '-' that are passed to the function as 
>arguments.  By contrast, I'd like to write a better box drawing routine 
>that would take advantage of box drawing graphics capabilities on some 
>terminals.  Unfortunately, the terminfo definitions don't include any 
>parameters that would be appropriate, and the tic(1M) program won't 
>allow me to define new ones.

Er... Oh, yes it does.  Oh, yes it will.  If you look in the _UNIX System V
Programmer's Guide_ (AT&T select code 307-225, or available at bookstores
in the Prentice-Hall edition), chapter 10, _Curses/terminfo_, you will find
a section called ``Using Advanced curses Features'' which describes the use
of ACS_* characters from an alternate character set to draw boxes.  There's
even an example program, which uses the box() function to do the job: box()
will use the ACS characters in preference to `+' and `-', provided that the
necessary characters are defined.  The definition is a little baroque:
Moving to _UNIX System V Programmer's Reference Manual_ (select code
307-226, or from Prentice Hall), section TERMINFO(4), you (eventually) find
a section called ``Line Graphics''.  This discusses the ``acsc'' (alternate
character set characters) capability, a single string containing your
terminal's half of a mapping between the VT100's alternate character set
and your terminal's alternate character set.  So, if you feed tic a
terminal description containing an acsc=... capability, you should get
prettier boxes when you use the curses box() function.  Admittedly, this is
all theory: I've never had to do it myself in anger -- although I've spent
plenty of time persuading applications authors that they should be doing
it, rather than...

>I figured I could get around the problem 
>by concocting a small database containing the command strings for the 
>various terminals we use in our office...

Please, please, don't do this.  Maintaining non-standard extensions to
curses, termcap and terminfo has been one of the banes of my life.  Every
(supply your own adjective) application does it differently.  No more
unnecessary diversity, please.  (Even if I don't get to maintain it.)
-- 
Dominic Dunlop
domo@sphinx.co.uk  domo@riddle.uucp

chris@cetia.UUCP (Chris Bertin) (09/12/88)

In article <806@riddle.UUCP>, domo@riddle.UUCP (Dominic Dunlop) writes:
> ... So, if you feed tic a
> terminal description containing an acsc=... capability, you should get
> prettier boxes when you use the curses box() function.  Admittedly, this is
> all theory: I've never had to do it myself in anger -- although I've spent
> plenty of time persuading applications authors that they should be doing
> it, rather than...
> 

There is only one problem with this new alternate character stuff: the
semi-graphics '|' and '-' will be used only if you draw your box with
'|' and '-' (or NULLS) but the corners will always be done using the
semi-graphics, even if you try to erase the box using spaces
(box(win, ' ', ' ')).

Chris
-- 
Chris Bertin	| CETIA
		| 150, Av Marcelin Berthelot, Z.I. Toulon-Est
+33(94)212005	| 83088 Toulon Cedex, France
Ext: 239	| inria!cetia

hansen@pegasus.UUCP (Tony L. Hansen) (09/28/88)

< There is only one problem with this new alternate character stuff: the
< semi-graphics '|' and '-' will be used only if you draw your box with '|'
< and '-' (or NULLS) but the corners will always be done using the
< semi-graphics, even if you try to erase the box using spaces (box(win,
< ' ', ' ')).

It was for this reason that the border() and wborder() functions were added
to the curses library in System V release 3.1. These functions allow you to
specify the characters to be used for all four sides and all four corners.

Here is the function prototype for wborder(). (border() just calls wborder()
with stdscr.)

wborder(WINDOW *win,
	chtype leftside, chtype rightside, chtype topside, chtype bottomside,
	chtype topleft, chtype topright, chtype bottomleft, chtype bottomright)

					Tony Hansen
				att!pegasus!hansen, attmail!tony