* stdio
@ 2003-06-18 9:58 John T. Williams
2003-06-18 12:02 ` stdio Jan-Benedict Glaw
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: John T. Williams @ 2003-06-18 9:58 UTC (permalink / raw)
To: linux-c-programming
I am trying to figure out how to cause a character to be printed to a
specific place on the terminal
what I'm actually trying to accomplish is to make a progress bar
example:
Progress [***** ] 25%
and I want it to fill up the box with stars as my program progresses, but I
can't figure out how to just get c to write a single '*' to anywhere other
then the end of the streak
I tried lseek and got no good results.
I'd really like any advice anyone has on this.
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: stdio 2003-06-18 9:58 stdio John T. Williams @ 2003-06-18 12:02 ` Jan-Benedict Glaw 2003-06-18 12:17 ` stdio Luciano Moreira - igLnx ` (2 subsequent siblings) 3 siblings, 0 replies; 10+ messages in thread From: Jan-Benedict Glaw @ 2003-06-18 12:02 UTC (permalink / raw) To: linux-c-programming [-- Attachment #1: Type: text/plain, Size: 1402 bytes --] On Wed, 2003-06-18 05:58:42 -0400, John T. Williams <jtwilliams@vt.edu> wrote in message <011801c33580$48425aa0$e764a8c0@fesnel.noip.org>: > I am trying to figure out how to cause a character to be printed to a > specific place on the terminal > > what I'm actually trying to accomplish is to make a progress bar > > example: > > Progress [***** ] 25% > > and I want it to fill up the box with stars as my program progresses, but I > can't figure out how to just get c to write a single '*' to anywhere other > then the end of the streak > I tried lseek and got no good results. Well, what you want to do sounds quite simple, but it's really quite complicated. The basic problem is that there are thousands of different terminal types out there which need different control sequences to position the cursor (if possible at all). You would need to know all of them to be portable. Because that would be a real PITA, this functionality has been placed into some libraries. Look for libncurses (of libtermcap) to do this task... MfG, JBG -- Jan-Benedict Glaw jbglaw@lug-owl.de . +49-172-7608481 "Eine Freie Meinung in einem Freien Kopf | Gegen Zensur | Gegen Krieg fuer einen Freien Staat voll Freier Bürger" | im Internet! | im Irak! ret = do_actions((curr | FREE_SPEECH) & ~(IRAQ_WAR_2 | DRM | TCPA)); [-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: stdio 2003-06-18 9:58 stdio John T. Williams 2003-06-18 12:02 ` stdio Jan-Benedict Glaw @ 2003-06-18 12:17 ` Luciano Moreira - igLnx 2003-06-18 13:04 ` stdio Stephen Satchell 2003-06-18 18:30 ` stdio Chris Nanakos 3 siblings, 0 replies; 10+ messages in thread From: Luciano Moreira - igLnx @ 2003-06-18 12:17 UTC (permalink / raw) To: John T. Williams; +Cc: linux-c-programming Look for documentation of Curses. Its a framework that encapsulate the character sequences to keep your program portable over different terminals. Luciano John T. Williams wrote: >I am trying to figure out how to cause a character to be printed to a >specific place on the terminal > >what I'm actually trying to accomplish is to make a progress bar > >example: > >Progress [***** ] 25% > >and I want it to fill up the box with stars as my program progresses, but I >can't figure out how to just get c to write a single '*' to anywhere other >then the end of the streak >I tried lseek and got no good results. > >I'd really like any advice anyone has on this. > >- >To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in >the body of a message to majordomo@vger.kernel.org >More majordomo info at http://vger.kernel.org/majordomo-info.html > > > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: stdio 2003-06-18 9:58 stdio John T. Williams 2003-06-18 12:02 ` stdio Jan-Benedict Glaw 2003-06-18 12:17 ` stdio Luciano Moreira - igLnx @ 2003-06-18 13:04 ` Stephen Satchell 2003-06-18 17:45 ` stdio Glynn Clements 2003-06-18 18:30 ` stdio Chris Nanakos 3 siblings, 1 reply; 10+ messages in thread From: Stephen Satchell @ 2003-06-18 13:04 UTC (permalink / raw) To: John T. Williams, linux-c-programming At 05:58 AM 6/18/2003 -0400, John T. Williams wrote: >I am trying to figure out how to cause a character to be printed to a >specific place on the terminal > >what I'm actually trying to accomplish is to make a progress bar > >example: > >Progress [***** ] 25% > >and I want it to fill up the box with stars as my program progresses, but I >can't figure out how to just get c to write a single '*' to anywhere other >then the end of the streak >I tried lseek and got no good results. > >I'd really like any advice anyone has on this. The really "classic" way to do what you want to do is to rewrite the entire line each time you add a progress indicator. This is the basic idea: int i; char progress[52]; memset(progress, 0, 52); for (i = 0; i <50; i++) { fprintf(stderr, "%1.26s [%-50s]\r", "some.text", progress); progress[i] = '*'; GoDoOneFiftyithOfSomething(); } fprintf(stderr, "%1.26s [%-50s]\n", "some.text", progress); This avoids the need to use termcap or terminfo, or the curses package. It works with all non-paper terminals, but it's SLOW if you are on a real teletype and HORRIBLE on some kludge like a keypunch-cardreader/printer console. (Not likely today, but...) Hope this helps. Satch ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: stdio 2003-06-18 13:04 ` stdio Stephen Satchell @ 2003-06-18 17:45 ` Glynn Clements 0 siblings, 0 replies; 10+ messages in thread From: Glynn Clements @ 2003-06-18 17:45 UTC (permalink / raw) To: John T. Williams; +Cc: Stephen Satchell, linux-c-programming Stephen Satchell wrote: > > I am trying to figure out how to cause a character to be printed to a > > specific place on the terminal > > > > what I'm actually trying to accomplish is to make a progress bar > > > > example: > > > > Progress [***** ] 25% > > > > and I want it to fill up the box with stars as my program progresses, but I > > can't figure out how to just get c to write a single '*' to anywhere other > > then the end of the streak > > I tried lseek and got no good results. > > > > I'd really like any advice anyone has on this. > > The really "classic" way to do what you want to do is to rewrite the entire > line each time you add a progress indicator. This is the basic idea: > > int i; > char progress[52]; > > memset(progress, 0, 52); > for (i = 0; i <50; i++) > { > fprintf(stderr, "%1.26s [%-50s]\r", "some.text", progress); > progress[i] = '*'; > GoDoOneFiftyithOfSomething(); > } > fprintf(stderr, "%1.26s [%-50s]\n", "some.text", progress); > > This avoids the need to use termcap or terminfo, or the curses package. It > works with all non-paper terminals, Not quite. It doesn't work with emulators such as Emacs' shell-mode, which just dumps everything into the buffer. For correctness, you should use termcap/terminfo to check whether the terminal (as specified by $TERM) has the "cr" capability before writing '\r' to the terminal. Also, you should check whether stderr is actually a terminal (with isatty()) before doing this sort of thing; you don't want to be doing it if stderr is redirected to a file. However, using curses for this would be overkill. You only need to use curses if you need vertical positioning. -- Glynn Clements <glynn.clements@virgin.net> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: stdio 2003-06-18 9:58 stdio John T. Williams ` (2 preceding siblings ...) 2003-06-18 13:04 ` stdio Stephen Satchell @ 2003-06-18 18:30 ` Chris Nanakos 2003-06-19 7:33 ` I'm really starting to dislike stdio John T. Williams 3 siblings, 1 reply; 10+ messages in thread From: Chris Nanakos @ 2003-06-18 18:30 UTC (permalink / raw) To: John T. Williams, linux-c-programming Try this.....and make your own changes....if helps just send an e-mail!!! #This is a progress bar with iterations #A lot of implementations can exist.Try this one and tell me if its done or else i will send another one. #include <stdio.h> main() { int progress,j; progress=1; for(j=0;j<=100;j++) { if(progress(!=101) {int i; printf("\33[1;34m"); printf("\r|"); for(;i<50;i++) fprintf(stdout," "); fprintf(stdout,"%6.2f %%",(float)2.5*progress); fflush(stdout); progress++; } usleep(40000); } printf("\33[0m"); printf("\n"); return; } ^ permalink raw reply [flat|nested] 10+ messages in thread
* I'm really starting to dislike stdio 2003-06-18 18:30 ` stdio Chris Nanakos @ 2003-06-19 7:33 ` John T. Williams 2003-06-19 11:26 ` Jan-Benedict Glaw 2003-06-19 12:56 ` Andrés Roldán 0 siblings, 2 replies; 10+ messages in thread From: John T. Williams @ 2003-06-19 7:33 UTC (permalink / raw) To: linux-c-programming I really appricated the help with the progress bar. I have another problem I am trying to read in a password from the stdin, but I don't want it to display to the screen as the person types it in. I either like to mock su, and take input w/o any output, or output a * for each typed character, and I cannot figure out how to get this to work I've tried _____________________ read(1, &tmpch, 1); while(tmpch != '\n') { memset(prog, '*', stars); printf("\rPassword: %-20s ", prog ); stars++; buff[loop] = tmpch; loop++; read(1, &tmpch, 1); } read(1, &tmpch, 1); while(tmpch != '\n') { memset(prog, '*', stars); printf("\rPassword: %-20s ", prog ); stars++; buff[loop] = tmpch; loop++; read(1, &tmpch, 1); } -------------------------- I've tried ____________________ tmpch = getchar(); while(tmpch != '\n') { memset(prog, '*', stars) printf("\rPassword: %-20s ", prog ); stars++; buff[loop] = tmpch; loop++; tmpch = getchar(); } and I tried getc from the curses library. The problem with all of these is that they only actually do the read part after I've hit the <enter> key. I want it to process each character as it is typed. Anyone who has any ideas or can tell me a better way to read characters w/o displaying it to the screen and I'd be greatful. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: I'm really starting to dislike stdio 2003-06-19 7:33 ` I'm really starting to dislike stdio John T. Williams @ 2003-06-19 11:26 ` Jan-Benedict Glaw 2003-06-19 17:39 ` Glynn Clements 2003-06-19 12:56 ` Andrés Roldán 1 sibling, 1 reply; 10+ messages in thread From: Jan-Benedict Glaw @ 2003-06-19 11:26 UTC (permalink / raw) To: linux-c-programming [-- Attachment #1: Type: text/plain, Size: 2083 bytes --] On Thu, 2003-06-19 03:33:16 -0400, John T. Williams <jtwilliams@vt.edu> wrote in message <004001c33635$21f3d3a0$e764a8c0@fesnel.noip.org>: > I really appricated the help with the progress bar. > > I have another problem > > I am trying to read in a password from the stdin, but I don't want it to > display to the screen as the person types it in. > I either like to mock su, and take input w/o any output, or output a * for > each typed character, and I cannot figure out how to get this to work > and I tried getc from the curses library. > The problem with all of these is that they only actually do the read part > after I've hit the <enter> key. I want it to process each character as it > is typed. Anyone who has any ideas or can tell me a better way to read > characters w/o displaying it to the screen and I'd be greatful. Terminals are serial equipment with special characteristics:) First, a call to read() will only return after the user pressed his Enter key _until_ you fiddle with serial settings: struct termios termio; tcgetattr(STDIN_FILENO, &termio); termio.c_cc[V_MIN] = 1; /* Return after one byte */ tcsetattr(STDIN_FILENO, &termio); tcflush(STDIN_FILENO, TCIOFLUSH); (Of course, you need a second struct termios to memcpy() all the old values to be able to restore the previous state which you're expected to do.) The second part is to not let those characters appear at all. This is done with: struct termios termio; tcgetattr(STDIN_FILENO, &termio); termio_new.c_lflag &= ~ECHO; /* Clear ECHO flag */ tcsetattr(STDIN_FILENO, &termio); tcflush(STDIN_FILENO, TCIOFLUSH); (Again, you need to backup old termios settings.) Serial programming (which this is, after all) isn't 100% simple:( MfG, JBG -- Jan-Benedict Glaw jbglaw@lug-owl.de . +49-172-7608481 "Eine Freie Meinung in einem Freien Kopf | Gegen Zensur | Gegen Krieg fuer einen Freien Staat voll Freier Bürger" | im Internet! | im Irak! ret = do_actions((curr | FREE_SPEECH) & ~(IRAQ_WAR_2 | DRM | TCPA)); [-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: I'm really starting to dislike stdio 2003-06-19 11:26 ` Jan-Benedict Glaw @ 2003-06-19 17:39 ` Glynn Clements 0 siblings, 0 replies; 10+ messages in thread From: Glynn Clements @ 2003-06-19 17:39 UTC (permalink / raw) To: John T. Williams; +Cc: linux-c-programming, Jan-Benedict Glaw Jan-Benedict Glaw wrote: > > I really appricated the help with the progress bar. > > > > I have another problem > > > > I am trying to read in a password from the stdin, but I don't want it to > > display to the screen as the person types it in. > > I either like to mock su, and take input w/o any output, or output a * for > > each typed character, and I cannot figure out how to get this to work > > > and I tried getc from the curses library. > > The problem with all of these is that they only actually do the read part > > after I've hit the <enter> key. I want it to process each character as it > > is typed. Anyone who has any ideas or can tell me a better way to read > > characters w/o displaying it to the screen and I'd be greatful. > > Terminals are serial equipment with special characteristics:) First, a > call to read() will only return after the user pressed his Enter key > _until_ you fiddle with serial settings: > > struct termios termio; > tcgetattr(STDIN_FILENO, &termio); > termio.c_cc[V_MIN] = 1; /* Return after one byte */ > tcsetattr(STDIN_FILENO, &termio); > tcflush(STDIN_FILENO, TCIOFLUSH); Note: tcsetattr() takes 3 arguments. Alternatively: tcgetattr(STDIN_FILENO, &termio); termio.c_lflag &= ~ICANON; tcsetattr(STDIN_FILENO, TCSANOW, &termio); This will disable the terminal driver's line-buffering altogether. It also disables the processing of special characters (backspace, Ctrl-C, Ctrl-Z etc). For this particular situation (reading passwords), setting c_cc[V_MIN] is probably preferable, but for fully "raw" I/O you need to clear the ICANON flag. If you want to use ANSI I/O, you also need: setbuf(stdin, NULL); This will disable the line buffering within the stdio library. > (Of course, you need a second struct termios to memcpy() all the old > values to be able to restore the previous state which you're expected to > do.) If you want to be really sure about restoring the previous state, you need to install some signal handlers in case the program dies suddenly (SIGINT, SIGQUIT, etc). If you don't disable SIGTSTP (Ctrl-Z), you should restore the terminal state on SIGTSTP then re-enable the changes on SIGCONT. -- Glynn Clements <glynn.clements@virgin.net> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: I'm really starting to dislike stdio 2003-06-19 7:33 ` I'm really starting to dislike stdio John T. Williams 2003-06-19 11:26 ` Jan-Benedict Glaw @ 2003-06-19 12:56 ` Andrés Roldán 1 sibling, 0 replies; 10+ messages in thread From: Andrés Roldán @ 2003-06-19 12:56 UTC (permalink / raw) To: John T. Williams; +Cc: linux-c-programming man 3 getpass Cheers "John T. Williams" <jtwilliams@vt.edu> writes: > I really appricated the help with the progress bar. > > I have another problem > > I am trying to read in a password from the stdin, but I don't want it to > display to the screen as the person types it in. > I either like to mock su, and take input w/o any output, or output a * for > each typed character, and I cannot figure out how to get this to work > > I've tried > _____________________ > > read(1, &tmpch, 1); > > while(tmpch != '\n') { > memset(prog, '*', stars); > printf("\rPassword: %-20s ", prog ); > stars++; > > buff[loop] = tmpch; > loop++; > read(1, &tmpch, 1); > } > read(1, &tmpch, 1); > > while(tmpch != '\n') { > memset(prog, '*', stars); > printf("\rPassword: %-20s ", prog ); > stars++; > > buff[loop] = tmpch; > loop++; > read(1, &tmpch, 1); > } > -------------------------- > > I've tried > > ____________________ > > > tmpch = getchar(); > while(tmpch != '\n') { > memset(prog, '*', stars) > printf("\rPassword: %-20s ", prog ); > stars++; > > buff[loop] = tmpch; > loop++; > tmpch = getchar(); > } > > and I tried getc from the curses library. > The problem with all of these is that they only actually do the read part > after I've hit the <enter> key. I want it to process each character as it > is typed. Anyone who has any ideas or can tell me a better way to read > characters w/o displaying it to the screen and I'd be greatful. > > > - > To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Andres Roldan <aroldan@fluidsignal.com> http://people.fluidsignal.com/~aroldan CSO, Fluidsignal Group ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2003-06-19 17:39 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2003-06-18 9:58 stdio John T. Williams 2003-06-18 12:02 ` stdio Jan-Benedict Glaw 2003-06-18 12:17 ` stdio Luciano Moreira - igLnx 2003-06-18 13:04 ` stdio Stephen Satchell 2003-06-18 17:45 ` stdio Glynn Clements 2003-06-18 18:30 ` stdio Chris Nanakos 2003-06-19 7:33 ` I'm really starting to dislike stdio John T. Williams 2003-06-19 11:26 ` Jan-Benedict Glaw 2003-06-19 17:39 ` Glynn Clements 2003-06-19 12:56 ` Andrés Roldán
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).