[comp.lang.c] Curses question

rld@drutx.ATT.COM (DucharmeBL) (04/10/88)

I am having trouble running the following section of code.  If this program is
compiled under the C compiler for System V, Release 2 it works correctly.  That
is, the test messages show up on the screen, the entering of a carriage return
causes the overlay message to print only wiping out the top message.  However,
if this segment is compiled under System V, Release 3.1 C compiler and curses
library, the carriage return after the printing of the test message is never
accepted.  Instead I must use getstr to observe the carriage return.  In
addition, when the second window is written, it also blanks out the lines under
the final three lines of msgw even though they have been cleared.  WHAT IS GOING
ON?  What changed between V-2 and V-3 in curses that would cause this problem.
In addition, how do I fix it?  I noticed that there is an overlay function in
the documentation, but I do not want to go back through a 35K line program
looking for all occurrances that will need modification.

If there are any ideas, please call or send a message to:

	Robert Ducharme
	ihnp4!drutx!rld
	(303)  538-4066

#include "curses.h"
WINDOW *msgw;

main(argc, argv, envp)
char **argv;
char **envp;
{
   char ps[20];

    /*
     * get home and options from environment
     */
    fflush(stdout);
    initscr();				/* Start up cursor package */
    msgw = newwin(4, 80, 0, 0);
    noecho();

    clearok(stdscr,TRUE);
    mvwaddstr(stdscr,0,0,"Test Message 1");
    mvwaddstr(stdscr,1,1,"Test MEssage 2");
    mvwaddstr(stdscr,2,2,"Test Message 3");
    mvwaddstr(stdscr,3,3,"Test Message 4");
    mvwaddstr(stdscr,4,4,"Test Message 5");
    wrefresh(stdscr);
    clearok(stdscr,FALSE);
    getstr(ps);
    msg("....  OVERWRITE MESSAGE  ....");
    echo();
    endwin();
}
/*
 * msg:
 *	Display a message at the top of the screen.
 */

static unsigned char msgbuf[BUFSIZ];

/*VARARGS1*/
msg(fmt, args)
char *fmt;
int args;
{
    doadd(fmt, &args);
    endmsg();
}

endmsg()
{
    /* Needed to track where we are for 5.0 (PC) curses */
    register int x, y;

    wmove(msgw, 0, 0);
    waddstr(msgw, msgbuf);
    getyx(msgw, y, x);
    wclrtobot(msgw);
    wmove(msgw, y, x);
    wrefresh(stdscr);
    clearok(msgw, FALSE);
    wrefresh(msgw);
}

doadd(fmt, args)
char *fmt;
int **args;
{
    static FILE junk;

    /*
     * Do the printf into buf
     */
    junk._flag = _IOWRT;  /* Under 3.0 IOUNK was IOSTRG */
    junk._file = _NFILE;
    junk._base = junk._ptr = &msgbuf[0];
    junk._cnt = 32767;
    _doprnt(fmt, args, &junk);
    putc('\0', &junk);
}

steffen@ihlpf.ATT.COM (Joe Steffen) (04/15/88)

I discovered a difference in curses between Release 2 and 3 that may be
related to this problem.  In Release 3, curses automatically refreshes the
window you request input from, e.g. getstr and getch refresh stdscr. 
This helps remove one source of error in writing a curses application, that
is, where do you put the refresh() calls?  In most programs, putting
refresh() just before requests for input and just after writing error
messages is the optimal solution.  Now you don't have to remember to put
them before input requests, but you must be careful what window you request
input from!  In my program, I was only using subwindows and not using
stdscr execpt to read input.  Thus in Release 3 the screen would clear
whenever the program called getch()!

Another Release 3 difference I know of is that the keypad code works and
doesn't cause your application to intermittantly receive incorrect input or
core dump like it did in release 2.

Since it took me 2 days to isolate the getch() change and 5 MONTHS to
isolate the keypad bug above I would like to see a list of Release 3 curses
changes from the person(s) who did them.  The comp centers will be
converting their mini's and maxi's to Release 3 over the next year so there
will be many tool providers discovering these Release 3 curses differences.


-- 


	Joe Steffen, AT&T Bell Labs, Naperville, IL, (312) 416-5378

wolfe@polya.Stanford.EDU (Michael R. Wolfe) (08/07/89)

  I'm trying to write an application which deals with menus.  I'd
like to be able to scroll up and down a menu, as well as scroll up
and down a file and highlight certain lines.

  I've tryed using Curses but can't see how to do it.  I can't seem to
get a window which is larger than the screen, even using pads.  Pads
seem very touchy.  For example, if I define a pad to be a certain
size, it will appear to work, but if I make it one line larger or
shorter, I'll get seqmentation faults..

  Has anyone managed to get anything like this to work?

-Mike
wolfe@polya.stanford.edu

mccaugh@s.cs.uiuc.edu (08/09/89)

 May I suggest using the "termcaps" functions (tgetent, etc.) which are
 'higher-level' (so less prone to machine-level problems) and thus more
 reliable -- and they worked for me.

nts0699@dsacg1.UUCP (Gene McManus) (08/11/89)

From article <11157@polya.Stanford.EDU>, by wolfe@polya.Stanford.EDU (Michael R. Wolfe):
> 
>   I'm trying to write an application which deals with menus.  I'd
> like to be able to scroll up and down a menu, as well as scroll up
> and down a file and highlight certain lines.
> 
>   I've tryed using Curses but can't see how to do it.  I can't seem to
> get a window which is larger than the screen, even using pads.  Pads
> seem very touchy.  For example, if I define a pad to be a certain
> size, it will appear to work, but if I make it one line larger or
> shorter, I'll get seqmentation faults..
> 
>   Has anyone managed to get anything like this to work?
> 
> -Mike
> wolfe@polya.stanford.edu

An excellent(!) book on this subject is "Advanced C Programming for
Displays" from Prentiss-Hall by Marc Roschkind (not exactly sure of
the name's spelling). Uses a project oriented approach to teach
development of virtual screens and displays using Curses, Termcap
MS-DOS and does a lot work in portability among these platforms.

Gene  (I have no affiliation with either Marc or P-H)


Gene McManus @ Defense Logistics Agency Systems Automation Center,
	       Columbus, OH 43215 (614) 238-9403,    Autovon 850-
Internet:       gmcmanus@dsacg1.dla.mil
UUCP:		{uunet!gould,cbosgd!osu-cis}!dsacg1!gmcmanus
The views expressed are my own, not those of The Agency, or Dept. of Defense

morreale@bierstadt.scd.ucar.edu (Peter Morreale) (07/18/90)

I hope this question is posted to the correct place....

I'm a fledgling C programmer who is attempting (;-) to write a 
small curses application.  The app. will be used by a small number of 
folks locally.  (This is mostly a learning exercise...)

What I'd like is some info on how to deal with cursor motion when the 
user hits a cursor key.  I intend to obtain input using getchar and need
to know how to detect when a cursor key is pressed for a couple of
different terminals.  (vt100 and xterm)

This is on Sun OS...( > 4.0)

Did I miss sumpthin in the Sun manuals?  (I have read the "Using Curses"
part several times.)

A code fragment would be wonderful...

Thanks for any insights...
-PWM
------------------------------------------------------------------
Peter W. Morreale                  email:  morreale@ncar.ucar.edu
Nat'l Center for Atmos Research    voice:  (303) 497-1293
Scientific Computing Division     
Consulting Office
------------------------------------------------------------------

gpitcher@edpmgt.UUCP (Glenn Pitcher) (08/27/90)

Question... I supposed to write a series of programs which will call each
other via the 'system' library call.  By problem is that all of these
programs use the curses library.  The code fragments below are samples of
what I've come up with and they seem to work OK yet when control is passed
back to program 'A', I can't get the screen to update correctly (even though 
the data is there).  I'm sure the problem is with the fact that both of these
programs are using curses on the same tty so, can somebody tell me how to do
it better?


Code fragments are as follows:

program 'A'
main()
{

     initscr();
     do until user exits
        {
	...draw screen...
	...get option...
	switch (option)
	   {
	   case option 1 :
	      system(...program 'B'...);
	      break;
           }
        }
     endwin();

program 'B'
main() 
{

   initscr();
   ...do various things...
   endwin();
}

Now I did think about using a variation of exec but I need to pass control back
to program 'A' when 'B' has completed.     

WHAT AM I MISSING????  ARRRGGGGG!!!!!

Thank you for your support,
-- 
Glenn Pitcher                              UUCP: {crash,ucsd}!edpmgt!gpitcher
Programmer/Analyst &                                  hp-sdd!teamnet!gpitcher
Unix Guru in training                    
EDP Management, Inc.                         * Proud member of Team.Net *
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

jetzer@studsys.mu.edu (Mike Jetzer) (08/28/90)

In article <556@edpmgt.UUCP> gpitcher@edpmgt.UUCP (Glenn Pitcher) writes:
% Question... I supposed to write a series of programs which will call each
% other via the 'system' library call.  By problem is that all of these
% programs use the curses library.  The code fragments below are samples of
% what I've come up with and they seem to work OK yet when control is passed
% back to program 'A', I can't get the screen to update correctly (even though 
% the data is there).

% Code fragments are as follows:
[ fragmented even more]
% program 'A'
%     initscr();
%	      system(...program 'B'...);
%     endwin();

% program 'B'
%   initscr();
%   ...do various things...
%   endwin();

My curses manpage says "Programs desiring shell escapes or suspending with
control Z can call resetterm before the shell is called and fixterm after
returning from the shell."

I assume the same would apply for system() (which is, essentially, calling
a shell).

I found out from another curses question in comp.unix.questions that
curses for System V is different from curses for BSD so your mileage
may vary (although I'm on a SysV machine, whose manpage refers to
"ctrl-Z", a BSD-ism).

-- 
Mike Jetzer
"And we'll have fun, fun, fun until Daddy takes the keyboard awa-ay..."

smith@groucho (08/29/90)

In article <556@edpmgt.UUCP> gpitcher@edpmgt.UUCP (Glenn Pitcher) writes:
>
>Question... I supposed to write a series of programs which will call each
>other via the 'system' library call.  By problem is that all of these
>programs use the curses library.  The code fragments below are samples of
>what I've come up with and they seem to work OK yet when control is passed
>back to program 'A', I can't get the screen to update correctly (even though 
>the data is there).  I'm sure the problem is with the fact that both of these
>programs are using curses on the same tty so, can somebody tell me how to do
>it better?
>
>   endwin();
>}
>
>Now I did think about using a variation of exec but I need to pass control back
>to program 'A' when 'B' has completed.     
>
>WHAT AM I MISSING????  ARRRGGGGG!!!!!
>

  When program B is finished I assume you are doing a refresh in program A.  
Since you did not use the curses routines in program A to change the screen
program A has no way of knowing that the window has changed.  You can use the
touchwin command to force the window to do a total update.
                                          __        
                                         |  | My employer will disavow any 
-----------------------------            |  | knowledge of my actions. 
William Smith                            |. |  
Microelectronics Research Center         \  | 
University of Idaho                      /   \ 
Moscow, ID  83843                        |    \    
(208)885-6500                            |     \  
                                         |      ---|          
E-mail:   wsmith@groucho.mrc.uidaho.edu  |         |   
----------------------------             |         |
                                         |----------          
                                    
                                    
                                    

daveh@marob.masa.com (Dave Hammond) (08/30/90)

In article <1990Aug29.021239.8182@groucho> smith@wallaby.UUCP (William D. Smith) writes:
>In article <556@edpmgt.UUCP> gpitcher@edpmgt.UUCP (Glenn Pitcher) writes:
>>[deleted code]
>>
>>   endwin();
>>}
>>
>  When program B is finished I assume you are doing a refresh in program A.  
>Since you did not use the curses routines in program A to change the screen
>program A has no way of knowing that the window has changed.  You can use the
>touchwin command to force the window to do a total update.

Also, beware that endwin() in the sub-program will try to output a 'te'
(terminal-mode end) sequence, which may confuse the parent curses
program to the point that touchwin() and refresh() will not help (the
parent has no idea that the physical terminal setup has changed).

--
Dave Hammond
daveh@marob.masa.com
uunet!masa.com!marob!daveh

hart@blackjack.dt.navy.mil (Michael Hart) (11/20/90)

I've been trying out curses on an SGI Personal Iris.  The problem
I can't figure out is; when I quit the program, the screen doesn't
get cleared.  I get :
=====================================================
29
<blackjack \ hart >%(cursor here)
Hello, World!  Using Curses!!
30
Hello, World!  Using Curses!!
31
Hello, World!  Using Curses!!
32
Hello, World!  Using Curses!!
33
Hello, World!  Using Curses!!
34
Hello, World!  Using Curses!!
35
(etc.....)
======================================================

The prog is supposed to print Hello, World!  Using Curses!!, then
a repetition count on the next line.  (Needed the rep count, because
the PI was so fast, I couldn't tell if the thing running or not!).

Anyway, the prog quits with a ctl-C, and is supposed to clear the
screen.  I've tried werase(stdscr), wclear(stdscr), and with & without
a wrefresh(stdscr).  Am I being brain-dead, or is something funky
with curses on SGI?

=================prog below====================

/**************************************************
	Author:		Michael G. Hart
	Program Name:	cur1.c
	Date:			19 November 90
	Purpose:		test out curses functions
	Compile:		cc cur1.c -lc_s -lcurses -o cur1
***************************************************/

#include <curses.h>

/**************************************************

	main function here

***************************************************/

main()
{
	char *theStr = "Hello, World!  Using Curses!!\n";
	chtype theInput;
	int repCtr = 0;

/*	some curses initialization items first 
	init the curses code
	call character mode for input (cbreak)
	set noecho
	set to clear input buffer on an interrupt intrflus
*/
	initscr();
	cbreak();
	noecho();
	intrflush();
	nodelay(stdscr,TRUE);
	scrollok(stdscr,TRUE);

	theInput = wgetch(stdscr);
	while ( theInput != KEY_END) {
		addstr(theStr);
		repCtr++;
		wprintw(stdscr,"%d \n",repCtr);
		theInput = wgetch(stdscr);
	}
	wclear(stdscr);
	wrefresh(stdscr);
	endwin();
}
=================end prog======================

thanx!!!

--
-------------------------------------------------------------------------------
Michael G. Hart   hart@blackjack.dt.navy.mil /  mhart@oasys.dt.navy.mil
	I don't know what I want to be when I grow up!
DISCLAIMER: the usual!

rwhite@nusdecs.uucp (0257014-Robert White(140)) (11/22/90)

In article <hart.659105063@blackjack> hart@blackjack.dt.navy.mil (Michael Hart) writes:
>I've been trying out curses on an SGI Personal Iris.  The problem
>	Compile:		cc cur1.c -lc_s -lcurses -o cur1

	While I don't beleive that it is a problem in your current
example, you should remember that the libraries are scanned in the
order they occur on the cc command line (in ?most? implementations) so
if you use the shared c library (-lc_s) is *MUST* be the last library
spesified!  If you don't do this you may discover many strange things
happening durring compilation or runtime (depending on numerous
things).

(e.g.) if your program calls a routine x and curses calls a routine y
and x and y are from the standard c library and both depend on the
same global data item you will have name colision because the y will
come from the c library and x will come from the shared library and
the data item will be included twice by the same name with an
impossible linkage [sic]

	These linkage problems *may* already be occuring in your
example because of the possiblity thay you may be getting stdio
routines piecemeal from the tro libraries.  Don't *know* this to be
the case, but it could happen.

> [Some Code]

	It *looked* ok at a quick read.  The only thing that really
jumped out at me was that if you use the strange-key definitions you
really *should* call keypad(win,TRUE) on the window you wgetch() your
input from (stdscr in the example).

	An other possibility is that the control-C combo may be setup
to signal(2) your program.  If you have ^C setup as interrupt or quit
your system would abort the program instead of using your branching
logic to exit.  This could cause the symptoms you describe.  The best
way to test this is to check for a known-not-to-be-special character
like the space bar; or put some indicative code after the loop (e.g. a
printf("Normal Exit\n"); after the endwin() call.

Disclaimer:  Just a few guesses that might help, not dogma (woff ;-)

*******************************************************************
Robert White           |   Not some church, and not the state,
Network Administrator  |      Not some dark capricious fate.
National University    |   Who you are, and when you lose,
crash!nusdecs!rwhite   |      Comes only from the things you chose.
(619) 563-7140 (voice) |                             -- me.
*******************************************************************

bowen@wanda.SGI.COM (Jerre Bowen) (11/27/90)

Michael Hart writes:
> 
> Anyway, the prog quits with a ctl-C, and is supposed to clear the
> screen.  I've tried werase(stdscr), wclear(stdscr), and with & without
> a wrefresh(stdscr).  Am I being brain-dead, or is something funky
> with curses on SGI?
> 
> #include <curses.h>
> 
> main()
> {
> 	char *theStr = "Hello, World!  Using Curses!!\n";
> 	chtype theInput;
> 	int repCtr = 0;
> 
> /*	some curses initialization items first 
> 	init the curses code
> 	call character mode for input (cbreak)
> 	set noecho
> 	set to clear input buffer on an interrupt intrflus
> */
> 	initscr();
> 	cbreak();
> 	noecho();
> 	intrflush();
> 	nodelay(stdscr,TRUE);
> 	scrollok(stdscr,TRUE);
> 
> 	theInput = wgetch(stdscr);
> 	while ( theInput != KEY_END) {
> 		addstr(theStr);
> 		repCtr++;
> 		wprintw(stdscr,"%d \n",repCtr);
> 		theInput = wgetch(stdscr);
> 	}
> 	wclear(stdscr);
> 	wrefresh(stdscr);
> 	endwin();
> }

> Michael G. Hart   hart@blackjack.dt.navy.mil /  mhart@oasys.dt.navy.mil
> 

	cbreak() mode delivers characters to the program one by one, but
interrupt characters still cause signals to be sent the program, so when
you <ctrl>-c the program (as you say above if I understand correctly)
the process is terminated unnaturally via a SIGINT and therefore never
hits the wclear() and etc.  You must catch SIGINT (using sigset(), for
example) if you intend to use <ctrl>-c as the termination sequence.  I
think there are other bugs in this program, however, just glancing at
the curses man page--initscr() needs some parameters and I don't think
using KEY_END is legit without first initializing the keypad.


	Jerre Bowen
	bowen@sgi.com

hagins@dg-rtp.dg.com (Jody Hagins) (11/28/90)

In article <1990Nov26.222916.11634@odin.corp.sgi.com>,
bowen@wanda.SGI.COM (Jerre Bowen) writes:
|> 
|> Michael Hart writes:
|> > 
|> > Anyway, the prog quits with a ctl-C, and is supposed to clear the
|> > screen.  I've tried werase(stdscr), wclear(stdscr), and with &
without
|> > a wrefresh(stdscr).  Am I being brain-dead, or is something funky
|> > with curses on SGI?
|> > 
|> > #include <curses.h>
|> > 
|> > main()
|> > {
|> > 	char *theStr = "Hello, World!  Using Curses!!\n";
|> > 	chtype theInput;
|> > 	int repCtr = 0;
|> > 
|> > /*	some curses initialization items first 
|> > 	init the curses code
|> > 	call character mode for input (cbreak)
|> > 	set noecho
|> > 	set to clear input buffer on an interrupt intrflus
|> > */
|> > 	initscr();
|> > 	cbreak();
|> > 	noecho();
|> > 	intrflush();
|> > 	nodelay(stdscr,TRUE);
|> > 	scrollok(stdscr,TRUE);
|> > 
|> > 	theInput = wgetch(stdscr);
|> > 	while ( theInput != KEY_END) {
|> > 		addstr(theStr);
|> > 		repCtr++;
|> > 		wprintw(stdscr,"%d \n",repCtr);
|> > 		theInput = wgetch(stdscr);
|> > 	}
|> > 	wclear(stdscr);
|> > 	wrefresh(stdscr);
|> > 	endwin();
|> > }
|> 
|> > Michael G. Hart   hart@blackjack.dt.navy.mil / 
mhart@oasys.dt.navy.mil
|> > 
|> 
|> 	cbreak() mode delivers characters to the program one by one, but
|> interrupt characters still cause signals to be sent the program, so
when
|> you <ctrl>-c the program (as you say above if I understand
correctly)
|> the process is terminated unnaturally via a SIGINT and therefore
never
|> hits the wclear() and etc.  You must catch SIGINT (using sigset(),
for
|> example) if you intend to use <ctrl>-c as the termination sequence. 
I
|> think there are other bugs in this program, however, just glancing
at
|> the curses man page--initscr() needs some parameters and I don't
think
|> using KEY_END is legit without first initializing the keypad.
|> 
|> 
|> 	Jerre Bowen
|> 	bowen@sgi.com



I believe that going into raw mode will interrupt the ctrl-c 
(and all other keys) and send them straight to the program
for processing.


--

Jody Hagins             
hagins@dg-rtp.dg.com    
Data General Corp.      
62 Alexander Dr.        
RTP, N.C.  27709        
(919) 248-6035          

TIM@ENH.Prime.COM (12/04/90)

The wrefresh() and wclear() routines simply clear your virtual screen. Upon
exitting your program (prior to the call the endwin()), call refresh() and
clear() to clear your physical screen. I know this will help, because I did the
same thing a few months ago to myself. :-)

/*   Tim Cantin  --  Phone: (508) 620-2800 x3101  --  FAX: (508) 879-9098   **
** Prime Computer Inc. 10-13, 500 Old Conn Path, Framingham, MA 01701 (USA) **
**     TIM@ENH.Prime.COM || {primerd, cvbnet, uunet}!ENH.Prime.COM!TIM      **
** 1% of Americans retire independently wealthy; the other 99% are working, **
**            financially dependent, or dead. WHAT WILL YOU BE?             */
#include "stddisclaimer.h"