Date: Wed, 15 Jul 92 19:24:36 +0100 From: buers AT dg1 DOT chemie DOT uni-konstanz DOT de (Dieter Buerssner) To: djgpp AT sun DOT soe DOT clarkson DOT edu Cc: dj AT ctron DOT com Subject: fixed gppconio.c I had some problems with the conio-library in djgpp. The VIDADDR macro did not work. Also characters with the high bit set (like the German "Umlaute") did not work. I also tried to speed up the functions a little bit. The original version was much slower than the corresponding Turbo-C version. Now they are comparable in speed. Here is my version. I tried some programs, which were originally written for Turbo-C, they all work now without modification of the sources (exept for the call of gppconio_init and the different name of the header file). The context diff is larger than the whole file, therefore I'm sending the file here. Try it out. Comments welcome. Dieter /********************************************************************** * * NAME: gppconio.c * * DESCRIPTION: simulate Borland text video funcs for GNU C++ * * copyright (c) 1991 J. Alan Eldridge * * M O D I F I C A T I O N H I S T O R Y * * when who what * ------------------------------------------------------------------- * 10/27/91 J. Alan Eldridge created * 01/06/92 D. Buerssner make it work with extended characters * (buers AT dg1 DOT chemie DOT uni-konstanz DOT de) speed-up of cputs * some missing brackets in VIDADDR * don't need scrollwindow anymore *********************************************************************/ #include #include #include #include "gppconio.h" #define DBGGTINFO 0 static struct text_info txinfo; #define VIDADDR(r,c) (ScreenPrimary + ((r) * txinfo.screenwidth) + (c)) int puttext(int c, int r, int c2, int r2, void *buf) { int c0; short *pvch = (short *)buf; r--, r2--, c--, c2--; for (c0 = c; r <= r2; r++) for (c = c0; c <= c2; c++) *VIDADDR(r,c) = *pvch++; return 1; } int gettext(int c, int r, int c2, int r2, void *buf) { int c0; short *pvch = (short *)buf; r--, r2--, c--, c2--; for (c0 = c; r <= r2; r++) { for (c = c0; c <= c2; c++) *pvch++ = *VIDADDR(r,c); } return 1; } void gotoxy(int col, int row) { ScreenSetCursor(row + txinfo.wintop - 2, col + txinfo.winleft - 2); } int wherex(void) { int row, col; ScreenGetCursor(&row, &col); return col - txinfo.winleft + 2; } int wherey(void) { int row, col; ScreenGetCursor(&row, &col); return row - txinfo.wintop + 2; } void textmode(int unused_mode) { } void textattr(int attr) { txinfo.attribute=ScreenAttrib = (unsigned char)attr; } void textcolor(int color) { ScreenAttrib &= 0xf0; txinfo.attribute=(ScreenAttrib |= (color & 0x0f)); } void textbackground(int color) { ScreenAttrib &= 0x0f; txinfo.attribute=(ScreenAttrib |= ((color & 0x0f) << 4)); } void highvideo(void) { txinfo.attribute=(ScreenAttrib |= 0x08); } void lowvideo(void) { txinfo.attribute=(ScreenAttrib &= 0x07); } void normvideo(void) { txinfo.attribute = ScreenAttrib = txinfo.normattr; } void _setcursortype(int unused_type) { } static void getwincursor(int *row, int *col) { ScreenGetCursor(row, col); *col += txinfo.winleft - 1; *row += txinfo.wintop - 1; } void clreol(void) { short image[ 256 ]; short val = ' ' | (ScreenAttrib << 8); int c, row, col, ncols; getwincursor(&row, &col); ncols = txinfo.winright - col; for (c = 0; c < ncols; c++) image[ c ] = val; puttext(col + 1, row + 1, txinfo.winright, row + 1, image); } static void fillrow(int row, int left, int right, int fill) { int col; for (col = left; col <= right; col++) *VIDADDR(row, col) = fill; } void clrscr(void) { int row, col; int c = ' ' | (ScreenAttrib << 8); for (row=txinfo.wintop-1; row < txinfo.winbottom; row++) for (col=txinfo.winleft-1; col < txinfo.winright; col++) *VIDADDR(row,col) = c; } int putch(int c) { int row, col; ScreenGetCursor(&row, &col); /* first, handle the character */ if (c == '\n') { row++; } else if (c == '\r') { col = txinfo.winleft - 1; } else { short val = c | (ScreenAttrib << 8); /* puttext(col + 1, row + 1, col + 1, row + 1, &val); */ *VIDADDR(row,col) = val; col++; } /* now, readjust the window */ if (col >= txinfo.winright) { col = txinfo.winleft - 1; row++; } if (row >= txinfo.winbottom) { /* scrollwin(0, txinfo.winbottom - txinfo.wintop, 1); */ ScreenSetCursor(txinfo.wintop-1,0); delline(); row--; } ScreenSetCursor(row, col); return c; } int getche(void) { int c = getch(); if (!c || c == 0xE0) c = getch(); return putch(c); } void insline(void) { int row, col, left, right, nbytes, bot, fill; ScreenGetCursor(&row, &col); left = txinfo.winleft - 1; right = txinfo.winright - 1; nbytes = (right-left+1)*2; bot = txinfo.winbottom-1; fill = ' ' | (ScreenAttrib << 8); while(bot > row+1) { memcpy(VIDADDR(bot,left), VIDADDR(bot-1,left), nbytes); bot--; } if (row < txinfo.winbottom -1) { fillrow(row+1,left,right,fill); } } void delline(void) { int row, col, left, right, nbytes, bot, fill; ScreenGetCursor(&row, &col); left = txinfo.winleft - 1; right = txinfo.winright - 1; nbytes = (right-left+1)*2; bot = txinfo.winbottom-1; fill = ' ' | (ScreenAttrib << 8); while(row < bot) { memcpy(VIDADDR(row,left), VIDADDR(row+1,left), nbytes); row++; } fillrow(bot,left,right,fill); } void window(int left, int top, int right, int bottom) { if (top < 1 || left < 1 || right > txinfo.screenwidth || bottom > txinfo.screenheight) return; txinfo.wintop = top; txinfo.winleft = left; txinfo.winright = right; txinfo.winbottom = bottom; } int cputs(const char *s) { int row, col,c; const unsigned char *ss = (const unsigned char *)s; short *viaddr; short sa = ScreenAttrib << 8; ScreenGetCursor(&row, &col); viaddr = (short *)VIDADDR(row,col); /* * Instead of just calling putch; we do everything by hand here, * This is much faster. We don't move the cursor after each character, * only after the whole string is written, because ScreenSetCursor * needs to long. You won't recognize the differenc. */ while (c = *ss++) { /* first, handle the character */ if (c == '\n') { row++; viaddr += txinfo.screenwidth; } else if (c == '\r') { col = txinfo.winleft - 1; viaddr = (short *)VIDADDR(row,col); } else { *viaddr++ = c | sa; col++; } /* now, readjust the window */ if (col >= txinfo.winright) { col = txinfo.winleft - 1; row++; viaddr = (short *)VIDADDR(row,col); } if (row >= txinfo.winbottom) { ScreenSetCursor(txinfo.wintop-1,0); /* goto first line in window */ delline(); /* and delete it */ row--; viaddr -= txinfo.screenwidth; } } ScreenSetCursor(row, col); return(*(--ss)); } int cprintf(const char *fmt, ...) { int cnt; char buf[ 2048 ]; va_list ap; va_start(ap, fmt); cnt = vsprintf(buf, fmt, ap); va_end(ap); cputs(buf); return cnt; } int movetext(int left, int top, int right, int bottom, int dleft, int dtop) { char *buf = malloc((right - left + 1) * (bottom - top + 1) * 2); if (!buf) return 0; gettext(left, top, right, bottom, buf); puttext(dleft, dtop, dleft + right - left, dtop + bottom - top, buf); free(buf); return 1; } static void _gettextinfo(struct text_info *t) { int row, col; t->winleft = t->wintop = 1; t->winright = t->screenwidth = ScreenCols(); t->winbottom = t->screenheight = ScreenRows(); t->normattr = 0x07; t->currmode = ScreenMode(); ScreenGetCursor(&row, &col); t->curx = col; t->cury = row; #if DBGGTINFO printf("left=%2d,right=%2d,top=%2d,bottom=%2d\n",t->winleft, t->winright,t->wintop,t->winbottom); printf("scrht=%2d,scrwid=%2d,norm=%2x,mode=%2d,x=%2d,y=%2d\n", t->screenheight, t->screenwidth, t->normattr, t->currmode, t->curx, t->cury); #endif } void gettextinfo(struct text_info *t) { *t = txinfo; #if DBGGTINFO printf("left=%2d,right=%2d,top=%2d,bottom=%2d\n",t->winleft, t->winright,t->wintop,t->winbottom); printf("scrht=%2d,scrwid=%2d,norm=%2x,mode=%2d,x=%2d,y=%2d\n", t->screenheight, t->screenwidth, t->normattr, t->currmode, t->curx, t->cury); #endif } extern int _gppconio_init; void gppconio_init(void) { _gettextinfo(&txinfo); _gppconio_init = 1; }