home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************\
-
- printf module
-
- part of suntar, ⌐1991 Sauro & Gabriele Speranza
-
- This program is public domain, feel free to use it or part of it for anything
-
- \*******************************************************************************/
-
- /* it's a not 100% standard version of printf: it does not support field
- length (%5d is NOT allowed) and has a new descriptor %p for Pascal strings
-
- I found no interest in supporting windows other then window 0, but
- if you place the buffer and some flags in the window struct it would be
- easy to adapt it to write to any window
- */
-
- #include "windows.h"
- #include "suntar.h"
-
- static Boolean first_time=true;
- static Boolean no_flush = false;
- static char last_char=CR;
-
- void my_flush(void);
- void printdec(long);
- void print_oct(long);
- void printhex(long,Boolean);
-
-
- void disable_autoflush()
- {
- /* the printf routine updates the screen, adjusts the scroll bars and
- scrolls the window so that the cursor is in sight, but
- a) that takes a lot of time
- b) if the printed lines are larger than the window, that may yield a lot of
- silly horizontal scrolling
- Hence, in the most critical sections of suntar updates are delayed and
- scrolls are disabled.
- */
- if(first_time){
- GrafPtr savePort;
- GetPort( &savePort );
- last_char=CR;
- new_window();
- first_time=false;
- SetPort( &my_windows[0] );
- TEAutoView (true,my_windows[0].TEH);
- SetPort( savePort );
- }
- no_flush=true;
- }
-
- void enable_autoflush()
- {
- GrafPtr savePort;
- GetPort( &savePort );
- SetPort( &my_windows[0] );
- my_flush();
-
- if( last_char==CR||last_char==LF){
- update_console();
-
- TESelView( my_windows[0].TEH);
- }
- if(curr_window==&my_windows[0]){
- SCR_BAR_AND_TEXT_IN_SYNC
- }
- /* else
- per ora la scrollbar Å comunque bianca, non importa aggiornarla, poi ci pensa
- MainEvent al momento dell'evento di attivazione
- -- the scrollbar is currently white, it will be updated by MainEvent at the
- activate event */
-
- SetPort( savePort );
- no_flush=false;
- }
-
-
- #ifndef SUNTAR
- /* suntar does not use it, preferring the more powerful prompt(), but it was
- tested and debugged, so you may use it if you need it: it's a full implementation
- ot the standard gets function, allowing all Mac-style editing tools on the
- line which is being typed */
- char * gets(buf)
- char*buf;
- {
- short io_start;
-
- /* The window was read-only: now, it' broken in two parts, the bottom
- becomes read/write, but any existing text, up to the prompt which
- probably you printf-ed just before calling gets, remains read-only;
- furthermore, the read-only portion is one line (even Paste is altered
- so that you can't paste a newline character) */
- io_start=my_windows[0].lastPrompt=(**my_windows[0].TEH).selEnd;
-
- /* wait until the user types a return or enter */
- do{
- MainEvent();
- }
- while(my_windows[0].lastPrompt!=32767);
- /* set the window as read-only again, and copy what appears after the prompt
- in the output string */
- {register char *p= buf;
- register char *q= *((**my_windows[0].TEH).hText) +io_start;
- register int i=(**my_windows[0].TEH).teLength-io_start;
- while(i--)
- *p++=*q++;
- *--p='\0'; /* il '\n' non va ritornato... */
- }
- return buf;LF
- }
- #endif
-
- void start_of_line()
- {
- /* guarantees that the last character in the window is a carriage return */
- if(last_char!=CR&&last_char!=LF)
- put_char(CR);
- }
-
- void one_empty_line()
- /* guarantees that the last two characters in the window are carriage returns */
- {
- if(last_char!=CR){
- put_char(CR);
- if(last_char!=CR) /* could be LF now... */
- put_char(CR);
- }
- }
-
-
- void prompt(buf,nbytes)
- /* come gets, ma ha un controllo di overflow e un valore iniziale
- -- similar to gets, but it has a buffer size parameter and the
- text input line has an initial value, which is selected so that one
- may delete it by typing any character
- */
- char*buf;
- {
- short io_start;
- GrafPtr savePort;
-
- io_start=(**my_windows[0].TEH).selEnd;
- if(buf[0]) printf("%s ",buf); /* the space seems superfluous, but without it the whole
- line appears selected, and that's not very pretty to be seen */
- GetPort( &savePort );
- SetPort(&my_windows[0]);
- TESetSelect((long)io_start,(**my_windows[0].TEH).selEnd-(buf[0]!=0),my_windows[0].TEH);
- update_console();
- TESelView( my_windows[0].TEH);
- SetPort(savePort);
- if(curr_window != &my_windows[0]) /* potrebbe esserci un desk accessory */
- SelectWindow(&my_windows[0]);
-
- my_windows[0].lastPrompt=io_start;
-
- do{
- MainEvent();
- if(is_abort_command()){
- GetPort( &savePort );
- SetPort(&my_windows[0]);
- TESetSelect((long)io_start,(long)32767,my_windows[0].TEH);
- TEDelete(TEH);
- my_windows[0].lastPrompt=32767; /* rimettilo readonly */
- SetPort(savePort);
- accept_abort_command();
- }
- }
- while(my_windows[0].lastPrompt!=32767);
-
- {register char *p= buf;
- register char *q= *((**my_windows[0].TEH).hText) +io_start;
- register int i=(**my_windows[0].TEH).teLength-io_start;
- if(i>nbytes) i=nbytes;
- while(i--)
- *p++=*q++;
- *--p='\0'; /* il '\n' non va ritornato... */
- }
- }
-
- #include <varargs.h>
-
- void printf(fmt,va_alist)
- char*fmt;
- va_dcl
- {
- va_list ap;
- register char*format=fmt;
- long val;
- register char*string;
- int longform;
-
-
- if(!no_flush){
- if(first_time){
- GrafPtr savePort;
- GetPort( &savePort );
- last_char=CR;
- new_window();
- first_time=false;
- SetPort( &my_windows[0] );
- TEAutoView (true,my_windows[0].TEH);
- SetPort( savePort );
- }
- }
-
- va_start(ap);
- while(*format!='\0'){
- if(*format!='%')
- put_char(*format);
- else{
- format++;
- if(longform = *format=='l')
- format++;
- switch(*format){
- case '%':
- put_char('%');
- break;
- case 'D':
- longform=1; /* e prosegui...*/
- case 'd':
- if(!longform)
- val= (long) va_arg(ap,int);
- else
- val= va_arg(ap,long);
- printdec(val);
- break;
- case 'u':
- val= (long) va_arg(ap,unsigned int); /* never used %lu... */
- printdec(val);
- break;
- case 'X':
- longform=1; /* e prosegui...*/
- case 'x':
- if(!longform)
- val= (long) va_arg(ap,int);
- else
- val= va_arg(ap,long);
- printhex(val,longform);
- break;
- case 'o':
- if(!longform)
- val= (long) va_arg(ap,int);
- else
- val= va_arg(ap,long);
- print_oct(val);
- break;
- case 'c':
- put_char( va_arg(ap,int) );
- break;
- case 's':
- string= va_arg(ap,char*);
- while(*string)
- put_char(*string++);
- break;
- case 'p':
- /* Å un formato non standard C, ma mi fa molto comodo: una stringa formato Pascal */
- string= va_arg(ap,char*);
- val= *string++;
- while(--val>=0)
- put_char(*string++);
- break;
- }
- }
- format++;
- }
- va_end(ap);
- if(!no_flush)
- enable_autoflush();
- }
-
- static void printdec(val)
- register long val;
- {
- char buf[14];
- register int i=-1;
- if(val<0){
- val= -val;
- put_char('-');
- }
- do{
- buf[++i]='0'+(int)(val%10);
- val /= 10;
- }
- while(val>0);
- while(i>=0) put_char(buf[i--]);
-
- }
-
- static void print_oct(val)
- register long val;
- {
- char buf[14];
- register int i=-1;
- do{
- buf[++i]='0'+(int)(val&7);
- val >>=3;
- }
- while(val>0);
- while(i>=0) put_char(buf[i--]);
- }
-
- static void printhex(val,longform)
- register long val;
- Boolean longform;
- {
- int digit,i=longform?28:12;
- short non_in_testa=0;
- while(i>=0){
- if(!i) non_in_testa=1;
- digit= (val>>i) & 0xF;
- if(digit!=0 || non_in_testa){
- put_char (digit<=9 ? '0'+digit : 'A'-10+digit );
- non_in_testa=1;
- }
- i-=4;
- }
- }
-
- void print_chars(p,n)
- char* p;
- int n;
- {
- if(!n) return;
- while(--n)
- put_char(*p++);
- printf("%c",*p); /* to flush the buffer and update the scrollbars */
- }
-
-
-
- #define BUFSIZE 80
-
- static char io_buf[BUFSIZE];
- static short chars_in_buffer=0;
-
- void put_char(c)
- char c;
- {
- if(c==LF) c=CR;
- if(chars_in_buffer>=BUFSIZE){
- GrafPtr savePort;
- GetPort( &savePort );
- SetPort( &my_windows[0]);
- my_flush();
- SetPort( savePort );
- }
- if(c!= CR || last_char==LF || last_char==CR )
- last_char=c;
- else
- last_char=LF; /* meaning one carriage return but not two, CR means
- at least two carriage returns */
- io_buf[chars_in_buffer]=c;
- chars_in_buffer++;
- }
-
- void update_console()
- {
- /* per uno stupido bug: il TextEdit non Å pensato per scrivere su una finestra
- che sta in background e lo scroll (almeno quello automatico) non provvede a scrollare
- anche l'update region, col che l'update successivo Å sulla posizione vecchia,
- non scrollata, del buco bianco. Unica soluzione, fare un update subito... ovviamente,
- per essere sicuri bisognerebbe chiamarla in continuazione, io mi limito a chiamarla
- quando chiudo una finestra di dialogo, quando ci sono forti probabilitê di
- provocare un update
- -- TextEdit has a bad bug: the TESelView routine does scroll the text,
- but the update region is not scrolled (that is, OffsetRgn is not called) to
- remember that the "white hole" left by an old window now closed was moved.
- Hence, when the update event arrives it updates part of the window which needn't
- an update and leaves part of the white hole.
- Only solution by now: don't call TeSelView when the update region is not empty:
- that is, either don't use TextEdit to implement the printf function (as a text
- editor it's still good, unless you type so quickly that a KeyDown event arrives
- between the window closing and the update) or do your own implementation of TESelView
- or call this function just before calling TESelView
- */
- if(!my_windows[0].used)
- return;
- else{
- RgnHandle h=((WindowPeek)&my_windows[0])->updateRgn;
- RgnPtr p;
- if(h && (p= *h) && p->rgnSize>=10)
- if( *((long*)&p->rgnBBox) != *((long*)&p->rgnBBox.bottom) ) /* this test
- is redundant, but it may avoid a relatively expensive toolbox call */
- if(!EmptyRgn (h)) UpdateWindow(&my_windows[0]);
- }
- }
-
-
- static void my_flush()
- {
- if(chars_in_buffer){
- TEAutoView (false,my_windows[0].TEH); /* otherwise, a lot of horizontal scrolling...*/
- TESetSelect((long)32767,(long)32767,my_windows[0].TEH);
- TEInsert(io_buf,(long)chars_in_buffer,my_windows[0].TEH);
- TEAutoView (true,my_windows[0].TEH);
- chars_in_buffer=0;
- }
- }