_C PROGRAMMING COLUMN_ by Al Stevens [LISTING ONE] /* ------------- dflat.h ----------- */ #ifndef WINDOW_H #define WINDOW_H #define VERSION "Version 3 Beta" #define TRUE 1 #define FALSE 0 #include "system.h" #include "config.h" #include "rect.h" #include "menu.h" #include "keys.h" #include "commands.h" #include "config.h" #include "dialbox.h" /* ------ integer type for message parameters ----- */ typedef long PARAM; #define TE(m) m typedef enum window_class { #include "classes.h" } CLASS; typedef struct window { CLASS class; /* window class */ char *title; /* window title */ struct window *parent; /* parent window */ int (*wndproc) (struct window *, enum messages, PARAM, PARAM); /* ---------------- window dimensions ----------------- */ RECT rc; /* window coordinates (0/0 to 79/24) */ int ht, wd; /* window height and width */ RECT RestoredRC; /* restored condition rect */ /* -------------- linked list pointers ---------------- */ struct window *next; /* next window on screen */ struct window *prev; /* previous window on screen*/ struct window *nextbuilt; /* next window built */ struct window *prevbuilt; /* previous window built */ int attrib; /* Window attributes */ char *videosave; /* video save buffer */ int condition; /* Restored, Maximized, Minimized */ int restored_attrib; /* attributes when restored */ void *extension; /* -> menus, dialog box, etc*/ struct window *PrevMouse; struct window *PrevKeyboard; /* ----------------- text box fields ------------------ */ int wlines; /* number of lines of text */ int wtop; /* text line that is on the top display */ char *text; /* window text */ int textlen; /* text length */ int wleft; /* left position in window viewport */ int textwidth; /* width of longest line in textbox */ int BlkBegLine; /* beginning line of marked block */ int BlkBegCol; /* beginning column of marked block */ int BlkEndLine; /* ending line of marked block */ int BlkEndCol; /* ending column of marked block */ int HScrollBox; /* position of horizontal scroll box */ int VScrollBox; /* position of vertical scroll box */ /* ----------------- list box fields ------------------ */ int selection; /* current selection */ int AddMode; /* adding extended selections mode */ int AnchorPoint;/* anchor point for extended selections */ int SelectCount;/* count of selected items */ /* ----------------- edit box fields ------------------ */ int CurrCol; /* Current column */ int CurrLine; /* Current line */ int WndRow; /* Current window row */ int TextChanged; /* TRUE if text has changed */ char *DeletedText; /* for undo */ int DeletedLength; /* " " */ /* ---------------- dialog box fields ----------------- */ struct window *dFocus; /* control that has the focus */ int ReturnCode; /* return code from a dialog box */ } * WINDOW; #include "message.h" #include "classdef.h" #include "video.h" enum Condition { ISRESTORED, ISMINIMIZED, ISMAXIMIZED }; void LogMessages (WINDOW, MESSAGE, PARAM, PARAM); void MessageLog(WINDOW); /* ------- window methods ----------- */ #define WindowHeight(w) ((w)->ht) #define WindowWidth(w) ((w)->wd) #define BorderAdj(w) (TestAttribute(w,HASBORDER)?1:0) #define TopBorderAdj(w) ((TestAttribute(w,TITLEBAR) && \ TestAttribute(w,HASMENUBAR)) ? \ 2 : (TestAttribute(w,TITLEBAR | \ HASMENUBAR | HASBORDER) ? 1 : 0)) #define ClientWidth(w) (WindowWidth(w)-BorderAdj(w)*2) #define ClientHeight(w) (WindowHeight(w)-TopBorderAdj(w)-\ BorderAdj(w)) #define WindowRect(w) ((w)->rc) #define GetTop(w) (RectTop(WindowRect(w))) #define GetBottom(w) (RectBottom(WindowRect(w))) #define GetLeft(w) (RectLeft(WindowRect(w))) #define GetRight(w) (RectRight(WindowRect(w))) #define GetClientTop(w) (GetTop(w)+TopBorderAdj(w)) #define GetClientBottom(w) (GetBottom(w)-BorderAdj(w)) #define GetClientLeft(w) (GetLeft(w)+BorderAdj(w)) #define GetClientRight(w) (GetRight(w)-BorderAdj(w)) #define GetParent(w) ((w)->parent) #define GetTitle(w) ((w)->title) #define NextWindow(w) ((w)->next) #define PrevWindow(w) ((w)->prev) #define NextWindowBuilt(w) ((w)->nextbuilt) #define PrevWindowBuilt(w) ((w)->prevbuilt) #define GetClass(w) ((w)->class) #define GetAttribute(w) ((w)->attrib) #define AddAttribute(w,a) (GetAttribute(w) |= a) #define ClearAttribute(w,a) (GetAttribute(w) &= ~(a)) #define TestAttribute(w,a) (GetAttribute(w) & (a)) #define isVisible(w) (GetAttribute(w) & VISIBLE) #define SetVisible(w) (GetAttribute(w) |= VISIBLE) #define ClearVisible(w) (GetAttribute(w) &= ~VISIBLE) #define gotoxy(w,x,y) cursor(w->rc.lf+(x)+1,w->rc.tp+(y)+1) WINDOW CreateWindow(CLASS,char *,int,int,int,int,void*,WINDOW, int (*)(struct window *,enum messages,PARAM,PARAM),int); void AddTitle(WINDOW, char *); void InsertTitle(WINDOW, char *); void DisplayTitle(WINDOW, RECT *); void RepaintBorder(WINDOW, RECT *); void ClearWindow(WINDOW, RECT *, int); #ifdef INCLUDE_SYSTEM_MENUS void clipline(WINDOW, int, char *); #else #define clipline(w,x,c) /**/ #endif void writeline(WINDOW, char *, int, int, int); void writefull(WINDOW, char *, int); void SetNextFocus(WINDOW,int); void SetPrevFocus(WINDOW,int); void PutWindowChar(WINDOW, int, int, int); void GetVideoBuffer(WINDOW); void RestoreVideoBuffer(WINDOW); void CreatePath(char *, char *, int, int); int LineLength(char *); RECT AdjustRectangle(WINDOW, RECT); #define DisplayBorder(wnd) RepaintBorder(wnd, NULL) #define DefaultWndProc(wnd,msg,p1,p2) \ (*classdefs[FindClass(wnd->class)].wndproc)(wnd,msg,p1,p2) #define BaseWndProc(class,wnd,msg,p1,p2) \ (*classdefs[DerivedClass(class)].wndproc)(wnd,msg,p1,p2) #define NULLWND ((WINDOW) 0) struct LinkedList { WINDOW FirstWindow; WINDOW LastWindow; }; extern struct LinkedList Focus; extern struct LinkedList Built; extern WINDOW inFocus; extern WINDOW CaptureMouse; extern WINDOW CaptureKeyboard; extern int foreground, background; extern int WindowMoving; extern int WindowSizing; extern int TextMarking; extern char *Clipboard; extern WINDOW SystemMenuWnd; /* --------------- border characters ------------- */ #define FOCUS_NW '\xc9' #define FOCUS_NE '\xbb' #define FOCUS_SE '\xbc' #define FOCUS_SW '\xc8' #define FOCUS_SIDE '\xba' #define FOCUS_LINE '\xcd' #define NW '\xda' #define NE '\xbf' #define SE '\xd9' #define SW '\xc0' #define SIDE '\xb3' #define LINE '\xc4' #define LEDGE '\xc3' #define REDGE '\xb4' /* ------------- scroll bar characters ------------ */ #define UPSCROLLBOX '\x1e' #define DOWNSCROLLBOX '\x1f' #define LEFTSCROLLBOX '\x11' #define RIGHTSCROLLBOX '\x10' #define SCROLLBARCHAR 176 #define SCROLLBOXCHAR 178 #define CHECKMARK 251 /* menu item toggle */ /* ----------------- title bar characters ----------------- */ #define CONTROLBOXCHAR '\xf0' #define MAXPOINTER 24 /* maximize token */ #define MINPOINTER 25 /* minimize token */ #define RESTOREPOINTER 18 /* restore token */ /* --------------- text control characters ---------------- */ #define APPLCHAR 176 /* fills application window */ #define SHORTCUTCHAR '~' /* prefix: shortcut key display */ #define CHANGECOLOR 174 /* prefix to change colors */ #define RESETCOLOR 175 /* reset colors to default */ #define LISTSELECTOR 4 /* selected list box entry */ /* ---- standard window message processing prototypes ----- */ int ApplicationProc(WINDOW, MESSAGE, PARAM, PARAM); int NormalProc(WINDOW, MESSAGE, PARAM, PARAM); int TextBoxProc(WINDOW, MESSAGE, PARAM, PARAM); int ListBoxProc(WINDOW, MESSAGE, PARAM, PARAM); int EditBoxProc(WINDOW, MESSAGE, PARAM, PARAM); int MenuBarProc(WINDOW, MESSAGE, PARAM, PARAM); int PopDownProc(WINDOW, MESSAGE, PARAM, PARAM); int ButtonProc(WINDOW, MESSAGE, PARAM, PARAM); int DialogProc(WINDOW, MESSAGE, PARAM, PARAM); int SystemMenuProc(WINDOW, MESSAGE, PARAM, PARAM); int HelpBoxProc(WINDOW, MESSAGE, PARAM, PARAM); int MessageBoxProc(WINDOW, MESSAGE, PARAM, PARAM); /* ------------- normal box prototypes ------------- */ int isWindow(WINDOW); WINDOW inWindow(int, int); int WndForeground(WINDOW); int WndBackground(WINDOW); int FrameForeground(WINDOW); int FrameBackground(WINDOW); int SelectForeground(WINDOW); int SelectBackground(WINDOW); void SetStandardColor(WINDOW); void SetReverseColor(WINDOW); void SetClassColors(CLASS); WINDOW GetFirstChild(WINDOW); WINDOW GetNextChild(WINDOW); WINDOW GetLastChild(WINDOW); WINDOW GetPrevChild(WINDOW); #define HitControlBox(wnd, p1, p2) \ (TestAttribute(wnd, TITLEBAR) && \ TestAttribute(wnd, CONTROLBOX) && \ p1 == 2 && p2 == 0) /* -------- text box prototypes ---------- */ #define TextLine(wnd, sel) \ (wnd->text + *((int *)(wnd->extension) + sel)) void WriteTextLine(WINDOW, RECT *, int, int); void SetAnchor(WINDOW, int, int); #define BlockMarked(wnd) ( wnd->BlkBegLine || \ wnd->BlkEndLine || \ wnd->BlkBegCol || \ wnd->BlkEndCol) #define ClearBlock(wnd) wnd->BlkBegLine = wnd->BlkEndLine = \ wnd->BlkBegCol = wnd->BlkEndCol = 0; #define GetText(w) ((w)->text) void ClearTextPointers(WINDOW); void BuildTextPointers(WINDOW); /* --------- menu prototypes ---------- */ int CopyCommand(char *, char *, int, int); void PrepOptionsMenu(void *, struct Menu *); void PrepEditMenu(void *, struct Menu *); void PrepWindowMenu(void *, struct Menu *); void BuildSystemMenu(WINDOW); int isActive(MENU *, int); void ActivateCommand(MENU *,int); void DeactivateCommand(MENU *,int); int GetCommandToggle(MENU *,int); void SetCommandToggle(MENU *,int); void ClearCommandToggle(MENU *,int); void InvertCommandToggle(MENU *,int); /* ------------- list box prototypes -------------- */ int ItemSelected(WINDOW, int); /* ------------- edit box prototypes ----------- */ #ifdef INCLUDE_MULTILINE #define isMultiLine(wnd) TestAttribute(wnd, MULTILINE) #else #define isMultiLine(wnd) FALSE #endif /* --------- message box prototypes -------- */ void MessageBox(char *, char *); void ErrorMessage(char *); int TestErrorMessage(char *); int YesNoBox(char *); int MsgHeight(char *); int MsgWidth(char *); #ifdef INCLUDE_DIALOG_BOXES /* ------------- dialog box prototypes -------------- */ int DialogBox(WINDOW,DBOX *,int(*)(struct window *,enum messages,PARAM,PARAM)); int DlgOpenFile(char *, char *); int DlgSaveAs(char *); void GetDlgListText(WINDOW, char *, enum commands); int DlgDirList(WINDOW, char *, enum commands, enum commands, unsigned); int RadioButtonSetting(DBOX *, enum commands); void PushRadioButton(DBOX *, enum commands); void PutItemText(WINDOW, enum commands, char *); void GetItemText(WINDOW, enum commands, char *, int); void SetCheckBox(DBOX *, enum commands); void ClearCheckBox(DBOX *, enum commands); int CheckBoxSetting(DBOX *, enum commands); WINDOW ControlWindow(DBOX *, enum commands); CTLWINDOW *ControlBox(DBOX *, WINDOW); #endif /* ------------- help box prototypes ------------- */ void HelpFunction(void); void LoadHelpFile(void); #define swap(a,b){int x=a;a=b;b=x;} #endif [LISTING TWO] /* ---------------- config.h -------------- */ #ifndef CONFIG_H #define CONFIG_H #define DFLAT_APPLICATION "MEMOPAD" #ifdef BUILD_FULL_DFLAT #define INCLUDE_SYSTEM_MENUS #define INCLUDE_CLOCK #define INCLUDE_MULTIDOCS #define INCLUDE_SCROLLBARS #define INCLUDE_SHADOWS #define INCLUDE_DIALOG_BOXES #define INCLUDE_CLIPBOARD #define INCLUDE_MULTILINE #define INCLUDE_LOGGING #endif struct colors { /* ------------ colors ------------ */ char ApplicationFG, ApplicationBG; char NormalFG, NormalBG; char ButtonFG, ButtonBG; char ButtonSelFG, ButtonSelBG; char DialogFG, DialogBG; char ErrorBoxFG, ErrorBoxBG; char MessageBoxFG, MessageBoxBG; char HelpBoxFG, HelpBoxBG; char InFocusTitleFG, InFocusTitleBG; char TitleFG, TitleBG; char DummyFG, DummyBG; char TextBoxFG, TextBoxBG; char TextBoxSelFG, TextBoxSelBG; char TextBoxFrameFG, TextBoxFrameBG; char ListBoxFG, ListBoxBG; char ListBoxSelFG, ListBoxSelBG; char ListBoxFrameFG, ListBoxFrameBG; char EditBoxFG, EditBoxBG; char EditBoxSelFG, EditBoxSelBG; char EditBoxFrameFG, EditBoxFrameBG; char MenuBarFG, MenuBarBG; char MenuBarSelFG, MenuBarSelBG; char PopDownFG, PopDownBG; char PopDownSelFG, PopDownSelBG; char InactiveSelFG; char ShortCutFG; }; /* ----------- configuration parameters ----------- */ typedef struct config { char version[sizeof DFLAT_APPLICATION + sizeof VERSION]; char mono; /* 0=color, 1=mono, 2=reverse mono */ int InsertMode; /* Editor insert mode */ int Tabs; /* Editor tab stops */ int WordWrap; /* True to word wrap editor */ int Border; /* True for application window border */ int Title; /* True for application window title */ int Texture; /* True for textured appl window */ int ScreenLines; /* Number of screen lines (25/43/50) */ struct colors clr; /* Colors */ } CONFIG; extern CONFIG cfg; extern struct colors color, bw, reverse; int LoadConfig(void); void SaveConfig(void); #endif [LISTING THREE] /* ---------- window.c ------------- */ #include #include #include #include #include #include "dflat.h" WINDOW inFocus = NULLWND; int foreground, background; /* current video colors */ static void TopLine(WINDOW, int, RECT); /* --------- create a window ------------ */ WINDOW CreateWindow( CLASS class, /* class of this window */ char *ttl, /* title or NULL */ int left, int top, /* upper left coordinates */ int height, int width, /* dimensions */ void *extension, /* pointer to additional data */ WINDOW parent, /* parent of this window */ int (*wndproc)(struct window *,enum messages,PARAM,PARAM), int attrib) /* window attribute */ { WINDOW wnd = malloc(sizeof(struct window)); get_videomode(); if (wnd != NULLWND) { int base; /* ----- height, width = -1: fill the screen ------- */ if (height == -1) height = SCREENHEIGHT; if (width == -1) width = SCREENWIDTH; /* ----- coordinates -1, -1 = center the window ---- */ if (left == -1) wnd->rc.lf = (SCREENWIDTH-width)/2; else wnd->rc.lf = left; if (top == -1) wnd->rc.tp = (SCREENHEIGHT-height)/2; else wnd->rc.tp = top; wnd->attrib = attrib; if (ttl != NULL) AddAttribute(wnd, TITLEBAR); if (wndproc == NULL) wnd->wndproc = classdefs[FindClass(class)].wndproc; else wnd->wndproc = wndproc; /* ---- derive attributes of base classes ---- */ base = class; while (base != -1) { int tclass = FindClass(base); AddAttribute(wnd, classdefs[tclass].attrib); base = classdefs[tclass].base; } if (parent && !TestAttribute(wnd, NOCLIP)) { /* -- keep upper left within borders of parent - */ wnd->rc.lf = max(wnd->rc.lf,GetClientLeft(parent)); wnd->rc.tp = max(wnd->rc.tp,GetClientTop(parent)); } wnd->class = class; wnd->extension = extension; wnd->rc.rt = GetLeft(wnd)+width-1; wnd->rc.bt = GetTop(wnd)+height-1; wnd->ht = height; wnd->wd = width; wnd->title = NULL; if (ttl != NULL) InsertTitle(wnd, ttl); wnd->next = wnd->prev = wnd->dFocus = NULLWND; wnd->parent = parent; wnd->videosave = NULL; wnd->condition = ISRESTORED; wnd->restored_attrib = 0; wnd->RestoredRC = wnd->rc; wnd->PrevKeyboard = wnd->PrevMouse = NULL; wnd->DeletedText = NULL; SendMessage(wnd, CREATE_WINDOW, 0, 0); if (isVisible(wnd)) SendMessage(wnd, SHOW_WINDOW, 0, 0); } return wnd; } /* -------- add a title to a window --------- */ void AddTitle(WINDOW wnd, char *ttl) { InsertTitle(wnd, ttl); SendMessage(wnd, BORDER, 0, 0); } /* ----- insert a title into a window ---------- */ void InsertTitle(WINDOW wnd, char *ttl) { if ((wnd->title=realloc(wnd->title,strlen(ttl)+1)) != NULL) strcpy(wnd->title, ttl); } /* ------- write a character to a window area at x,y ------- */ void PutWindowChar(WINDOW wnd, int x, int y, int c) { int x1 = GetLeft(wnd)+x; int y1 = GetTop(wnd)+y; if (isVisible(wnd)) { if (!TestAttribute(wnd, NOCLIP)) { WINDOW wnd1 = GetParent(wnd); while (wnd1 != NULLWND) { /* --- clip character to parent's borders -- */ if (x1 < GetClientLeft(wnd1) || x1 > GetClientRight(wnd1) || y1 > GetClientBottom(wnd1) || y1 < GetClientTop(wnd1)) return; wnd1 = GetParent(wnd1); } } if (x1 < SCREENWIDTH && y1 < SCREENHEIGHT) wputch(wnd, c, x, y); } } static char line[161]; #ifdef INCLUDE_SYSTEM_MENUS /* ----- clip line if it extends below the bottom of parent window ------ */ static int clipbottom(WINDOW wnd, int y) { if (!TestAttribute(wnd, NOCLIP)) { WINDOW wnd1 = GetParent(wnd); while (wnd1 != NULLWND) { if (GetClientTop(wnd)+y > GetClientBottom(wnd1)+1) return TRUE; wnd1 = GetParent(wnd1); } } return GetTop(wnd)+y > SCREENHEIGHT; } /* -- clip portion of line that extends past right margin of parent window-- */ void clipline(WINDOW wnd, int x, char *ln) { WINDOW pwnd = GetParent(wnd); int x1 = strlen(ln); int i = 0; if (!TestAttribute(wnd, NOCLIP)) { while (pwnd != NULLWND) { x1 = GetClientRight(pwnd) - GetLeft(wnd) - x + 1; pwnd = GetParent(pwnd); } } else if (GetLeft(wnd) + x > SCREENWIDTH) x1 = SCREENWIDTH-GetLeft(wnd) - x; /* --- adjust the clipping offset for color controls --- */ if (x1 < 0) x1 = 0; while (i < x1) { if ((unsigned char) ln[i] == CHANGECOLOR) i += 3, x1 += 3; else if ((unsigned char) ln[i] == RESETCOLOR) i++, x1++; else i++; } ln[x1] = '\0'; } #else #define clipbottom(w,y) FALSE #endif /* ------ write a line to video window client area ------ */ void writeline(WINDOW wnd, char *str, int x, int y, int pad) { static char wline[120]; if (!clipbottom(wnd, y)) { char *cp; int len; int dif; memset(wline, 0, sizeof wline); len = LineLength(str); dif = strlen(str) - len; strncpy(wline, str, ClientWidth(wnd) + dif); if (pad) { cp = wline+strlen(wline); while (len++ < ClientWidth(wnd)-x) *cp++ = ' '; } clipline(wnd, x, wline); wputs(wnd, wline, x, y); } } /* -- write a line to video window (including the border) -- */ void writefull(WINDOW wnd, char *str, int y) { if (!clipbottom(wnd, y)) { strcpy(line, str); clipline(wnd, 0, line); wputs(wnd, line, 0, y); } } RECT AdjustRectangle(WINDOW wnd, RECT rc) { /* -------- adjust the rectangle ------- */ if (TestAttribute(wnd, HASBORDER)) { if (RectLeft(rc) == 0) --rc.rt; else if (RectLeft(rc) < RectRight(rc) && RectLeft(rc) < WindowWidth(wnd)+1) --rc.lf; } if (TestAttribute(wnd, HASBORDER | TITLEBAR)) { if (RectTop(rc) == 0) --rc.bt; else if (RectTop(rc) < RectBottom(rc) && RectTop(rc) < WindowHeight(wnd)+1) --rc.tp; } RectRight(rc) = max(RectLeft(rc),min(RectRight(rc),WindowWidth(wnd))); RectBottom(rc) = max(RectTop(rc),min(RectBottom(rc),WindowHeight(wnd))); return rc; } /* -------- display a window's title --------- */ void DisplayTitle(WINDOW wnd, RECT *rcc) { int tlen = min(strlen(wnd->title), WindowWidth(wnd)-2); int tend = WindowWidth(wnd)-3-BorderAdj(wnd); RECT rc; if (rcc == NULL) rc = RelativeWindowRect(wnd, WindowRect(wnd)); else rc = *rcc; rc = AdjustRectangle(wnd, rc); if (SendMessage(wnd, TITLE, LPARAM(rcc), 0)) { if (wnd == inFocus) { foreground = cfg.clr.InFocusTitleFG; background = cfg.clr.InFocusTitleBG; } else { foreground = cfg.clr.TitleFG; background = cfg.clr.TitleBG; } memset(line,' ',WindowWidth(wnd)); if (wnd->condition != ISMINIMIZED) strncpy(line + ((WindowWidth(wnd)-2 - tlen) / 2), wnd->title, tlen); if (TestAttribute(wnd, CONTROLBOX)) line[2-BorderAdj(wnd)] = CONTROLBOXCHAR; #ifdef INCLUDE_SYSTEM_MENUS if (TestAttribute(wnd, MINMAXBOX)) { switch (wnd->condition) { case ISRESTORED: line[tend+1] = MAXPOINTER; line[tend] = MINPOINTER; break; case ISMINIMIZED: line[tend+1] = MAXPOINTER; break; case ISMAXIMIZED: line[tend] = MINPOINTER; line[tend+1] = RESTOREPOINTER; break; default: break; } } #endif line[RectRight(rc)+1] = line[tend+3] = '\0'; writeline(wnd, line+RectLeft(rc), RectLeft(rc)+BorderAdj(wnd), 0, FALSE); } } #ifdef INCLUDE_SHADOWS /* --- display right border shadow character of a window --- */ static void near shadow_char(WINDOW wnd, int y) { int fg = foreground; int bg = background; int x = WindowWidth(wnd); int c = videochar(GetLeft(wnd)+x, GetTop(wnd)+y); if (TestAttribute(wnd, SHADOW) == 0) return; foreground = DARKGRAY; background = BLACK; PutWindowChar(wnd, x, y, c); foreground = fg; background = bg; } /* --- display the bottom border shadow line for a window -- */ static void near shadowline(WINDOW wnd, RECT rc) { int i; int y = GetBottom(wnd)+1; if ((TestAttribute(wnd, SHADOW)) == 0) return; if (!clipbottom(wnd, WindowHeight(wnd))) { int fg = foreground; int bg = background; for (i = 0; i < WindowWidth(wnd)+1; i++) line[i] = videochar(GetLeft(wnd)+i, y); line[i] = '\0'; foreground = DARKGRAY; background = BLACK; clipline(wnd, 1, line); line[RectRight(rc)+1] = '\0'; if (RectLeft(rc) == 0) rc.lf++; wputs(wnd, line+RectLeft(rc), RectLeft(rc),WindowHeight(wnd)); foreground = fg; background = bg; } } #endif /* ------- display a window's border ----- */ void RepaintBorder(WINDOW wnd, RECT *rcc) { int y; int lin, side, ne, nw, se, sw; RECT rc, clrc; if (!TestAttribute(wnd, HASBORDER)) return; if (rcc == NULL) { rc = RelativeWindowRect(wnd, WindowRect(wnd)); #ifdef INCLUDE_SHADOWS if (TestAttribute(wnd, SHADOW)) { rc.rt++; rc.bt++; } #endif } else rc = *rcc; clrc = AdjustRectangle(wnd, rc); if (wnd == inFocus) { lin = FOCUS_LINE; side = FOCUS_SIDE; ne = FOCUS_NE; nw = FOCUS_NW; se = FOCUS_SE; sw = FOCUS_SW; } else { lin = LINE; side = SIDE; ne = NE; nw = NW; se = SE; sw = SW; } line[WindowWidth(wnd)] = '\0'; /* ---------- window title ------------ */ if (TestAttribute(wnd, TITLEBAR)) if (RectTop(rc) == 0) if (RectLeft(rc) < WindowWidth(wnd)-BorderAdj(wnd)) DisplayTitle(wnd, &rc); foreground = FrameForeground(wnd); background = FrameBackground(wnd); /* -------- top frame corners --------- */ if (RectTop(rc) == 0) { if (RectLeft(rc) == 0) PutWindowChar(wnd, 0, 0, nw); if (RectLeft(rc) < WindowWidth(wnd)) { if (RectRight(rc) >= WindowWidth(wnd)-1) PutWindowChar(wnd, WindowWidth(wnd)-1, 0, ne); TopLine(wnd, lin, rc); } } /* ----------- window body ------------ */ for (y = RectTop(rc); y <= RectBottom(rc); y++) { int ch; if (y == 0 || y >= WindowHeight(wnd)-1) continue; if (RectLeft(rc) == 0) PutWindowChar(wnd, 0, y, side); if (RectLeft(rc) < WindowWidth(wnd) && RectRight(rc) >= WindowWidth(wnd)-1) { #ifdef INCLUDE_SCROLLBARS if (TestAttribute(wnd, VSCROLLBAR)) ch = ( y == 1 ? UPSCROLLBOX : y == WindowHeight(wnd)-2 ? DOWNSCROLLBOX : y-1 == wnd->VScrollBox ? SCROLLBOXCHAR : SCROLLBARCHAR ); else #endif ch = side; PutWindowChar(wnd, WindowWidth(wnd)-1, y, ch); } #ifdef INCLUDE_SHADOWS if (RectRight(rc) == WindowWidth(wnd)) shadow_char(wnd, y); #endif } if (RectTop(rc) <= WindowHeight(wnd)-1 && RectBottom(rc) >= WindowHeight(wnd)-1) { /* -------- bottom frame corners ---------- */ if (RectLeft(rc) == 0) PutWindowChar(wnd, 0, WindowHeight(wnd)-1, sw); if (RectLeft(rc) < WindowWidth(wnd) && RectRight(rc) >= WindowWidth(wnd)-1) PutWindowChar(wnd, WindowWidth(wnd)-1, WindowHeight(wnd)-1, se); /* ----------- bottom line ------------- */ memset(line,lin,WindowWidth(wnd)-1); #ifdef INCLUDE_SCROLLBARS if (TestAttribute(wnd, HSCROLLBAR)) { line[0] = LEFTSCROLLBOX; line[WindowWidth(wnd)-3] = RIGHTSCROLLBOX; memset(line+1, SCROLLBARCHAR, WindowWidth(wnd)-4); line[wnd->HScrollBox] = SCROLLBOXCHAR; } #endif line[WindowWidth(wnd)-2] = line[RectRight(rc)] = '\0'; if (RectLeft(rc) != RectRight(rc) || (RectLeft(rc) && RectLeft(rc) < WindowWidth(wnd)-1)) writeline(wnd, line+(RectLeft(clrc)), RectLeft(clrc)+1, WindowHeight(wnd)-1, FALSE); #ifdef INCLUDE_SHADOWS if (RectRight(rc) == WindowWidth(wnd)) shadow_char(wnd, WindowHeight(wnd)-1); #endif } #ifdef INCLUDE_SHADOWS if (RectBottom(rc) == WindowHeight(wnd)) /* ---------- bottom shadow ------------- */ shadowline(wnd, rc); #endif } static void TopLine(WINDOW wnd, int lin, RECT rc) { if (TestAttribute(wnd, TITLEBAR | HASMENUBAR)) return; if (RectLeft(rc) < RectRight(rc)) { /* ----------- top line ------------- */ memset(line,lin,WindowWidth(wnd)-1); line[RectRight(rc)] = '\0'; writeline(wnd, line+RectLeft(rc), RectLeft(rc)+1, 0, FALSE); } } /* ------ clear the data space of a window -------- */ void ClearWindow(WINDOW wnd, RECT *rcc, int clrchar) { if (isVisible(wnd)) { int y; RECT rc; if (rcc == NULL) rc = RelativeWindowRect(wnd, WindowRect(wnd)); else rc = *rcc; if (RectLeft(rc) == 0) RectLeft(rc) = BorderAdj(wnd); if (RectRight(rc) > WindowWidth(wnd)-1) RectRight(rc) = WindowWidth(wnd)-1; SetStandardColor(wnd); memset(line, clrchar, sizeof line); line[RectRight(rc)+1] = '\0'; for (y = RectTop(rc); y <= RectBottom(rc); y++) { if (y < TopBorderAdj(wnd) || y >= WindowHeight(wnd)-1) continue; writeline(wnd, line+(RectLeft(rc)), RectLeft(rc), y, FALSE); } } } /* -- adjust a window's rectangle to clip it to its parent -- */ static RECT near ClipRect(WINDOW wnd) { RECT rc; rc = wnd->rc; #ifdef INCLUDE_SHADOWS if (TestAttribute(wnd, SHADOW)) { RectBottom(rc)++; RectRight(rc)++; } #endif if (!TestAttribute(wnd, NOCLIP)) { WINDOW pwnd = GetParent(wnd); if (pwnd != NULLWND) { RectTop(rc) = max(RectTop(rc), GetClientTop(pwnd)); RectLeft(rc) = max(RectLeft(rc), GetClientLeft(pwnd)); RectRight(rc) = min(RectRight(rc), GetClientRight(pwnd)); RectBottom(rc) = min(RectBottom(rc), GetClientBottom(pwnd)); } } RectRight(rc) = min(RectRight(rc), SCREENWIDTH-1); RectBottom(rc) = min(RectBottom(rc), SCREENHEIGHT-1); RectLeft(rc) = min(RectLeft(rc), SCREENWIDTH-1); RectTop(rc) = min(RectTop(rc), SCREENHEIGHT-1); return rc; } /* -- get the video memory that is to be used by a window -- */ void GetVideoBuffer(WINDOW wnd) { RECT rc; int ht; int wd; rc = ClipRect(wnd); ht = RectBottom(rc) - RectTop(rc) + 1; wd = RectRight(rc) - RectLeft(rc) + 1; wnd->videosave = realloc(wnd->videosave, (ht * wd * 2)); get_videomode(); if (wnd->videosave != NULL) getvideo(rc, wnd->videosave); } /* --- restore the video memory that was used by a window -- */ void RestoreVideoBuffer(WINDOW wnd) { if (wnd->videosave != NULL) { RECT rc; rc = ClipRect(wnd); storevideo(rc, wnd->videosave); free(wnd->videosave); wnd->videosave = NULL; } } /* ------ compute the logical line length of a window ------ */ int LineLength(char *ln) { int len = strlen(ln); char *cp = ln; while ((cp = strchr(cp, CHANGECOLOR)) != NULL) { cp++; len -= 3; } cp = ln; while ((cp = strchr(cp, RESETCOLOR)) != NULL) { cp++; --len; } return len; }