Mail Archives: djgpp/1992/07/15/14:02:45
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 <stdlib.h>
#include <stdarg.h>
#include <pc.h>
#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;
}
- Raw text -