/* * $Id: scrnio.c,v 1.7 2005/06/21 19:53:14 andrew_belov Exp $ * --------------------------------------------------------------------------- * This module provides basic screen output routines. * */ #include "arj.h" #if CONSOLE_SET==CT_NATIVE||TARGET==OS2 #define KNOW_DIMENSIONS #endif #include #if CONSOLE_SET==CT_NATIVE #if TARGET==DOS #include #include #elif TARGET==OS2 #endif #endif DEBUGHDR(__FILE__) /* Debug information block */ /* Local variables */ #ifdef KNOW_DIMENSIONS static unsigned char w_rows=0, w_columns; #endif #if TARGET==WIN32 static HANDLE hcons; #endif #if CONSOLE_SET==CT_ANSI||CONSOLE_SET==CT_NATIVE static unsigned char curattr=7; #if CONSOLE_SET==CT_ANSI static char ansicolors[8]={30, 34, 32, 36, 31, 35, 33, 37}; static int background_touched=0; #endif #endif int scr_sentry=0; /* Queries screen dimensions, excluding window region */ #ifdef KNOW_DIMENSIONS static void get_dimensions() { #if TARGET==DOS union REGS r; r.h.ah=0x0F; int86(0x10, &r, &r); w_columns=(unsigned int)r.h.ah; w_rows=*(unsigned char FAR *)0x00000484L+1; #elif TARGET==OS2 VIOMODEINFO modedata; modedata.cb=sizeof(modedata); VioGetMode(&modedata, 0); w_columns=modedata.col; w_rows=modedata.row; #elif TARGET==WIN32 CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(hcons=GetStdHandle(STD_OUTPUT_HANDLE), &csbi); w_columns=csbi.dwSize.X; w_rows=csbi.dwSize.Y; #endif } #endif /* Positions the cursor at row y, column x (top-left screen corner is 1, 1) */ #if CONSOLE_SET!=CT_BORLAND&&CONSOLE_SET!=CT_MSGRAPH void gotoxy(int x, int y) { #if CONSOLE_SET==CT_NATIVE #if TARGET==DOS union REGS r; r.h.ah=2; r.h.bh=0; r.h.dh=(char)y-1; r.h.dl=(char)x-1; int86(0x10, &r, &r); #elif TARGET==OS2 VioSetCurPos((USHORT)y-1, (USHORT)x-1, 0); #elif TARGET==WIN32 COORD xy; if(w_rows==0) get_dimensions(); xy.X=x-1; xy.Y=y-1; SetConsoleCursorPosition(hcons, xy); #endif #elif CONSOLE_SET==CT_ANSI printf("\x1B[%u;%uH", y, x); #endif } #endif /* Refreshes the ANSI attributes */ #if CONSOLE_SET==CT_ANSI static void kick_attr() { if(!background_touched) { if(curattr%8==7) printf("\x1B[0m"); else printf("\x1B[0;%um", (unsigned int)ansicolors[curattr%8]); } else { printf("\x1B[0;%u;%um", (unsigned int)ansicolors[curattr%8], (unsigned int)(ansicolors[(curattr>>4)%8])+10); } if(curattr&8) printf("\x1B[1m"); } #else #define kick_attr() #endif /* Sets the background color to c, color index is the same as on PCs. The colors 8..15 do NOT enable blinking. */ #if CONSOLE_SET!=CT_BORLAND&&CONSOLE_SET!=CT_MSGRAPH void textbackground(int c) { curattr=(curattr%16+(c<<4))%128; kick_attr(); #if CONSOLE_SET==CT_ANSI background_touched=1; #endif } #endif /* Sets the foreground color to c, 16...31 enables blinking. */ #if CONSOLE_SET!=CT_BORLAND&&CONSOLE_SET!=CT_MSGRAPH void textcolor(int c) { curattr=(curattr&112)+((c&16)<<3)+c%16; kick_attr(); } #endif /* Sets text attributes */ #if CONSOLE_SET!=CT_BORLAND&&SFX_LEVEL>=ARJSFX void textattr(int c) { #if CONSOLE_SET==CT_MSGRAPH _settextcolor((short)((c&128)?16:0)+c%16); _setbkcolor((short)(c%128)>>4); #elif CONSOLE_SET==CT_NATIVE||CONSOLE_SET==CT_ANSI curattr=(unsigned char)c; #endif kick_attr(); } #endif /* Returns current column, 1... */ #if CONSOLE_SET!=CT_BORLAND&&CONSOLE_SET!=CT_ANSI int wherex() { #if CONSOLE_SET==CT_MSGRAPH struct rccoord coord; coord=_gettextposition(); return((int)coord.col); #elif CONSOLE_SET==CT_NATIVE #if TARGET==DOS union REGS r; r.h.ah=3; r.h.bh=0; int86(0x10, &r, &r); return((int)r.h.dl+1); #elif TARGET==OS2 USHORT x, y; VioGetCurPos(&y, &x, 0); return(x+1); #elif TARGET==WIN32 CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(hcons, &csbi); return(csbi.dwCursorPosition.X+1); #endif #endif } #endif /* Returns current row, 1... */ #if CONSOLE_SET!=CT_BORLAND&&CONSOLE_SET!=CT_ANSI int wherey() { #if CONSOLE_SET==CT_MSGRAPH struct rccoord coord; coord=_gettextposition(); return((int)coord.row); #elif CONSOLE_SET==CT_NATIVE #if TARGET==DOS union REGS r; r.h.ah=3; r.h.bh=0; int86(0x10, &r, &r); return((int)r.h.dh+1); #elif TARGET==OS2 USHORT x, y; VioGetCurPos(&y, &x, 0); return(y+1); #elif TARGET==WIN32 CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(hcons, &csbi); return(csbi.dwCursorPosition.Y+1); #endif #endif } #endif /* Returns the current text attribute */ #if SFX_LEVEL>=ARJSFX unsigned char getcurattr() { #if CONSOLE_SET==CT_BORLAND struct text_info r; gettextinfo(&r); return(r.attribute); #elif CONSOLE_SET==CT_MSGRAPH unsigned char textcolor; textcolor=(unsigned char)_gettextcolor(); return(textcolor%16+((unsigned char)_getbkcolor()<<4)+((textcolor&16)?128:0)); #elif CONSOLE_SET==CT_NATIVE||CONSOLE_SET==CT_ANSI return(curattr); #endif } #endif /* Clears the entire screen or window */ #if CONSOLE_SET!=CT_BORLAND&&CONSOLE_SET!=CT_MSGRAPH void clrscr() { #if CONSOLE_SET==CT_NATIVE #if TARGET==DOS unsigned int st_x, st_y; union REGS r; get_dimensions(); r.x.ax=0x600; r.h.bh=(unsigned char)curattr; r.x.cx=0; r.h.dh=w_rows-1; r.h.dl=w_columns-1; int86(0x10, &r, &r); gotoxy(1, 1); #elif TARGET==OS2 static BYTE cell[]={' ', 0}; int i; get_dimensions(); cell[1]=(BYTE)curattr; for(i=0; i1) column--; break; case 9: do { wputch(' '); } while((wherex()-1)%8); return; case 10: row++; column=1; break; case 13: column=1; break; default: #if TARGET==DOS r.h.ah=9; r.h.al=(unsigned char)c; r.x.bx=curattr; r.x.cx=1; int86(0x10, &r, &r); #elif TARGET==OS2 VioWrtCharStrAtt((PCH)&c, 1, row-1, column-1, &curattr, 0); #elif TARGET==WIN32 ci.Char.UnicodeChar=0; ci.Char.AsciiChar=(CHAR)c; ci.Attributes=curattr; xy.X=xy.Y=1; xysp.X=0; xysp.Y=0; sr.Left=sr.Right=column-1; sr.Top=sr.Bottom=row-1; WriteConsoleOutput(hcons, &ci, xy, xysp, &sr); #endif column++; } if(column>w_columns) { column=1; row++; } while(row>w_rows) { #if TARGET==DOS r.x.ax=0x601; r.h.bh=(unsigned char)curattr; r.x.cx=0x100; r.h.dh=w_rows-1; r.h.dl=w_columns-1; int86(0x10, &r, &r); #elif TARGET==OS2 cell[0]=' '; cell[1]=curattr; VioScrollUp(0, 0, w_rows-1, w_columns-1, 1, cell, 0); #elif TARGET==WIN32 sr.Top=1; sr.Left=0; sr.Right=w_columns-1; sr.Bottom=w_rows-1; xy.X=0; xy.Y=0; ci.Char.UnicodeChar=0x20; ci.Attributes=curattr; ScrollConsoleScreenBuffer(hcons, &sr, NULL, xy, &ci); #else #error BUG: wputch() routine not implemented #endif row--; } gotoxy(column, row); } #elif CONSOLE_SET==CT_ANSI putchar(c); #endif } #endif /* High-level functions, dropped for ANSI */ #if CONSOLE_SET!=CT_ANSI /* Borland calls this cprintf(). We call this scrprintf(). */ #if CONSOLE_SET!=CT_BORLAND&&defined(ARJDISP) void scrprintf(char *fmt, ...) { char text[1024]; va_list marker; va_start(marker, fmt); vsprintf(text, fmt, marker); va_end(marker); scr_out(text); } #endif #endif /* !CT_ANSI */ /* A general routine for outputting unformatted text onto screen */ #if defined(ARJDISP)||defined(COLOR_OUTPUT) void scr_out(char *str) { #if CONSOLE_SET==CT_BORLAND #ifdef ARJDISP char strform[]="%s"; #endif kbhit(); cprintf(strform, str); #elif CONSOLE_SET==CT_MSGRAPH /* Needs a special hack. Microsoft allows the backspace character to be passed. */ char t[128]; int i=0; int xpos; while(str[0]!='\0') { kbhit(); /* To check for Ctrl+C */ while(str[i]!='\0'&&(i0) { t[i]='\0'; str+=i; i=0; _outtext((char FAR *)t); } str++; xpos=wherex()-1; _settextposition(wherey(), max(xpos, 1)); } else { t[i]=str[i]; i++; } } t[i]='\0'; _outtext((char FAR *)t); str+=i; i=0; } if(i>0) { t[i]='\0'; _outtext((char FAR *)t); } #elif CONSOLE_SET==CT_NATIVE||CONSOLE_SET==CT_ANSI char *t_ptr; #if TARGET==DOS kbhit(); /* To check for Ctrl+C */ #endif for(t_ptr=str; *t_ptr!='\0'; t_ptr++) wputch((int)*t_ptr); #else #error scr_out() not implemented #endif } #endif /* For ANSI, we have to reset the terminal. Do it here (on other console types, it's a null macro) */ #if CONSOLE_SET==CT_ANSI void scrn_reset() { printf("\x1B[0m\n"); } #endif /* Helper routine for ARJ to know the screen height */ int query_screen_height() { #ifdef KNOW_DIMENSIONS get_dimensions(); return(w_rows); #else return(25); #endif } /* Prepares for wrapping around the right margin if the given length exceeds it */ void check_wrap(int i) { #if SFX_LEVEL>=ARJ&&defined(KNOW_DIMENSIONS)&&(defined(ARJDISP)||defined(COLOR_OUTPUT)) if(wherex()+i>w_columns) scr_out(lf); #endif }