/* ***** WtWin.C -- Window handler for WizTerm ***** */ #include #ifdef __TURBOC__ #include #include #endif #ifdef _MSC_VER #include #include #endif #include #include #include #include "wt.h" #include "wtwin.h" /*==========================*/ /*===== Local #defines =====*/ /*==========================*/ #define DPY_SEG 0xb800 /* segment for color video buffer */ /*=======================*/ /*===== Local types =====*/ /*=======================*/ struct crt_char { char chr; byte att; }; typedef struct crt_char t_crt_char; #if !defined(__TURBOC__) || !defined(__VIDEO) struct text_info { unsigned char winleft, wintop; unsigned char winright, winbottom; unsigned char attribute, normattr; unsigned char currmode; unsigned char screenheight; unsigned char screenwidth; unsigned char curx, cury; }; #endif typedef struct text_info t_text_info; struct win_info { t_text_info txtinf; /* window info as seen above */ byte vis; /* window visible? */ byte cursor; /* cursor visible? */ byte b4scroll; /* cursor at bottom right; */ /* next write will scroll */ t_crt_char far *winbuf; /* contains all win text */ }; typedef struct win_info t_win_info; typedef byte winnum; /* Window number, used in win map */ /*===========================*/ /*===== LOCAL VARIABLES =====*/ /*===========================*/ static winnum *winmap = NULL; /* owner window per screen pos */ static struct crt_char far *crt_buf; /* physical CRT memory buffer */ struct win_info *winctl = NULL; /* Window ctrl structure array */ struct win_info *w = NULL; /* Current window control ptr */ static winnum wn = 0; /* Current window number */ /* ***** FUNCTIONS ***** */ /* ============================================================== */ /* win_att(): Set current window attribute */ /* ============================================================== */ void win_att(byte att) { assert(w != NULL); w->txtinf.attribute = att; #if defined(__TURBOC__) textattr(w->txtinf.attribute); #endif } /* end win_att() */ /* ============================================================== */ /* win_blink(): Turn blink attribute on/off. */ /* ============================================================== */ void win_blink(int sw) { assert(w != NULL); if (sw) { w->txtinf.attribute |= BLINK; } else { w->txtinf.attribute &= ~BLINK; } } /* end win_blink() */ /* ============================================================== */ /* win_clear(): clear current window. */ /* ============================================================== */ void win_clear(void) { register int r, c; assert (w != NULL); win_att(w->txtinf.normattr); for (r=0; rtxtinf.screenheight; r++) { win_xy(0, r); for (c=0; ctxtinf.screenwidth; c++) { win_putch(' '); } } win_xy(0, 0); } /* end win_clear() */ /* ============================================================== */ /* win_cursor(): Turn cursor on/off in current window */ /* ============================================================== */ void win_cursor(int sw) { w->cursor = (byte) sw; } /* end win_cursor() */ /* ============================================================== */ /* win_fg(): Set foreground color */ /* ============================================================== */ void win_fg(enum COLORS color) { win_att((byte) (w->txtinf.attribute & 0xF0 | color & 0x0F)); } /* end win_fg() */ /* ============================================================== */ /* win_hide(): Make window contents invisible. */ /* ============================================================== */ void win_hide() { static t_win_info *win_list[WIN_NUMB]; static t_win_info **wlp; static t_win_info *wp; winnum jw; int jr, jc, jra, jca; byte *map1ptr, *mapptr; t_crt_char far *bufptr; t_crt_char far *crt1ptr, far *crtptr; /* --- Are any visible windows below the current --- */ /* --- one, and do they intersect? --- */ wlp = win_list; for (jw=(winnum)(wn-1); jw>0; jw--) { wp = &winctl[jw]; if (wp->vis && wp->txtinf.winbottom >= w->txtinf.wintop && wp->txtinf.wintop <= w->txtinf.winbottom && wp->txtinf.winright >= w->txtinf.winleft && wp->txtinf.winleft <= w->txtinf.winright) { *wlp++ = wp; } } *wlp++ = winctl; *wlp++ = NULL; /* --- For every window position to be hidden, find an --- */ /* --- intersecting lower-level window; put its number --- */ /* --- into the map for that location and copy its --- */ /* --- contents to the physical screen. --- */ /* --- set up pointers --- */ crt1ptr = &crt_buf[w->txtinf.winleft + DPY_COLS*w->txtinf.wintop]; map1ptr = &winmap[w->txtinf.winleft + DPY_COLS*w->txtinf.wintop]; for (jr=0; jrtxtinf.screenheight; jr++) { jra = jr + w->txtinf.wintop; jca = w->txtinf.winleft; crtptr = crt1ptr; mapptr = map1ptr; for (jc=0; jctxtinf.screenwidth; jc++,jca++) { if (*mapptr <= wn) { for (wlp=win_list; *wlp!=NULL; wlp++) { wp = *wlp; if (jra >= wp->txtinf.wintop && jra <= wp->txtinf.winbottom && jca >= wp->txtinf.winleft && jca <= wp->txtinf.winright) { *mapptr = (byte) (wp - winctl); bufptr = wp->winbuf + jca - wp->txtinf.winleft + (jra - wp->txtinf.wintop) * wp->txtinf.screenwidth; *crtptr = *bufptr; break; } } } mapptr++; crtptr++; } crt1ptr += DPY_COLS; map1ptr += DPY_COLS; } w->vis = 0; } /* end win_hide() */ /* ============================================================== */ /* win_init: Initialize window handler */ /* ============================================================== */ int win_init(void) { register winnum jw; register int jc; t_text_info w0; crt_buf = (t_crt_char far *) MK_FP(DPY_SEG, 0); winmap = (winnum *) calloc(DPY_ROWS * DPY_COLS, sizeof(winnum)); assert(winmap != NULL); winctl = (t_win_info *) calloc(WIN_NUMB, sizeof(struct win_info)); assert(winctl != NULL); for (jw=0; jw<=WIN_NUMB; jw++) { winctl[jw].winbuf = NULL; } #if defined(__TURBOC__) /* --- Initialize display mode --- */ textmode(C80); win_select(WIN_DOSW); gettextinfo(&w0); if (w0.currmode != C80) { fprintf(stderr, "This program requires EGA or VGA\n"); exit (1); } #else /* --- Do some default stuff not requiring library --- */ w0.winleft = 0; w0.wintop = 0; w0.winright = DPY_COLS - 1; w0.winbottom = DPY_ROWS - 1; w0.attribute = MK_ATT(WHITE, BLACK); w0.normattr = MK_ATT(WHITE, BLACK); w0.screenheight = DPY_ROWS; w0.screenwidth = DPY_COLS; w0.curx = 0; w0.cury = 0; #endif win_open(WIN_DOSW, 0, 0, DPY_COLS, DPY_ROWS, w0.normattr); for (jc=0; jc<(DPY_COLS*DPY_ROWS); jc++) { w->winbuf[jc] = crt_buf[jc]; } return 1; } /* end win_init() */ /* ================================================================= */ /* win_open(): Set up a new window with given coords in given slot. */ /* Note: Window is initially invisible! */ /* It is now legal to re-open a window. The original window should */ /* be invis, though! */ /* ================================================================= */ void win_open(int wnum, int left, int top, int cols, int rows, byte att) { assert(wnum < WIN_NUMB); win_select(wnum); if (w->winbuf != NULL) { free((t_crt_char near *) w->winbuf); } w->winbuf = (t_crt_char far *) calloc(cols*rows, sizeof(t_crt_char)); assert(w->winbuf != NULL); w->txtinf.winleft = (byte) left; w->txtinf.wintop = (byte) top; w->txtinf.winright = (byte) (left + cols - 1); w->txtinf.winbottom = (byte) (top + rows - 1); w->txtinf.attribute = att; w->txtinf.normattr = att; w->txtinf.screenheight = (byte) rows; w->txtinf.screenwidth = (byte) cols; w->vis = 0; w->cursor = 0; w->b4scroll = 0; win_clear(); } /* end win_open() */ /* ============================================================== */ /* win_putch(): Output a character to window buffer and possibly */ /* the physical screen buffer at current position; advance pos. */ /* ============================================================== */ void win_putch(char c) { struct crt_char tmp_char; int absx, absy; if (c == '\r') { /* --- Carriage return? */ win_xy(0, w->txtinf.cury); return; } if (c == '\n') { /* --- Line feed? */ if (w->txtinf.cury + 1 >= w->txtinf.screenheight) { win_scroll(); } else { win_xy(w->txtinf.curx, w->txtinf.cury + 1); } return; } if (w->b4scroll) { /* --- Scroll pending? */ win_scroll(); win_xy(0, w->txtinf.screenheight-1); } tmp_char.chr = c; tmp_char.att = w->txtinf.attribute; absx = w->txtinf.curx; absy = w->txtinf.cury; w->winbuf[absy * w->txtinf.screenwidth + absx] = tmp_char; if (w->vis) { absx += w->txtinf.winleft; absy += w->txtinf.wintop; if (winmap[xy2a(absx,absy)] == wn) { crt_buf[xy2a(absx,absy)] = tmp_char; } } /* --- advance cursor position --- */ if (w->txtinf.curx + 1 < w->txtinf.screenwidth) { win_xy(w->txtinf.curx+1, w->txtinf.cury); } else if (w->txtinf.cury + 1 < w->txtinf.screenheight) { win_xy(0, w->txtinf.cury+1); } else { w->b4scroll = 1; } } /* end win_putch() */ /* ============================================================== */ /* win_puts(): display text on current window */ /* ============================================================== */ void win_puts(char *txt) { while (*txt) { win_putch(*txt++); } } /* end win_puts() */ /* ============================================================== */ /* win_scroll(): scroll current window up one line. */ /* ============================================================== */ void win_scroll(void) { register int r, c; t_crt_char far *buf1ptr, far *bufptr; t_crt_char far *srcptr; t_crt_char far *crt1ptr, far *crtptr; winnum *map1ptr, *mapptr; struct crt_char tmp_chr; word winpos; assert (w != NULL); /* --- set up pointers --- */ buf1ptr = w->winbuf; winpos = DPY_COLS * (word) w->txtinf.wintop + w->txtinf.winleft; crt1ptr = &crt_buf[winpos]; map1ptr = &winmap[winpos]; /* --- scroll screen text up --- */ for (r=0; rtxtinf.screenheight-1; r++) { bufptr = buf1ptr; srcptr = buf1ptr + w->txtinf.screenwidth; crtptr = crt1ptr; mapptr = map1ptr; for (c=0; ctxtinf.screenwidth; c++) { *bufptr = *srcptr; if (w->vis && *mapptr == wn) { *crtptr = *srcptr; } bufptr++; srcptr++; mapptr++; crtptr++; } buf1ptr += w->txtinf.screenwidth; crt1ptr += DPY_COLS; map1ptr += DPY_COLS; } /* --- clear bottom line --- */ /* (the line begin pointers (xxx1ptr) are abused to traverse, lastime) */ tmp_chr.chr = ' '; tmp_chr.att = w->txtinf.normattr; for (c=0; ctxtinf.screenwidth; c++) { *buf1ptr = tmp_chr; if (w->vis && *map1ptr == wn) { *crt1ptr = tmp_chr; } buf1ptr++; map1ptr++; crt1ptr++; } } /* end win_scroll() */ /* ==================================================================== */ /* Select current window */ /* ==================================================================== */ void win_select(int wnum) { wn = (winnum) wnum; w = &winctl[wn]; } /* end win_select() */ /* ============================================================== */ /* win_show(): Make an invisible window visible */ /* ============================================================== */ void win_show(void) { int jr, jc; winnum *map1ptr, *mapptr; t_crt_char far *buf1ptr, far *bufptr; t_crt_char far *crt1ptr, far *crtptr; word winpos; /* --- For each position in the current window, check if --- */ /* --- it is obscured by a higher-plane window. If not, --- */ /* --- enter current window into map and copy its --- */ /* --- contents to the physical screen. --- */ /* --- set up pointers --- */ buf1ptr = w->winbuf; winpos = (word) DPY_COLS*w->txtinf.wintop + w->txtinf.winleft; crt1ptr = &crt_buf[winpos]; map1ptr = &winmap[winpos]; for (jr=0; jrtxtinf.screenheight; jr++) { bufptr = buf1ptr; crtptr = crt1ptr; mapptr = map1ptr; for (jc=0; jctxtinf.screenwidth; jc++) { if (*mapptr <= wn) { *crtptr = *bufptr; *mapptr = wn; } bufptr++; mapptr++; crtptr++; } buf1ptr += w->txtinf.screenwidth; crt1ptr += DPY_COLS; map1ptr += DPY_COLS; } w->vis = 1; } /* end win_show() */ /* ============================================================== */ /* win_x(): Position next write position to x, current y. */ /* ============================================================== */ void win_x(int x) { win_xy(x, w->txtinf.cury); } /* end win_x() */ /* ============================================================== */ /* win_xy(): Position next write position to x, y in window. */ /* ============================================================== */ void win_xy(int x, int y) { word absx, absy; assert(w != NULL); w->txtinf.curx = (byte) x; w->txtinf.cury = (byte) y; if (w->vis && w->cursor) { absx = (word) x + w->txtinf.winleft; absy = (word) y + w->txtinf.wintop; if (winmap[xy2a(absx,absy)] == wn) { _settextposition(1+absy, 1+absx); } } w->b4scroll = 0; } /* end win_xy() */ /* EOF(WtWin.C) */