1 /**
2  * @namespace   biewlib
3  * @file        biewlib/twin.c
4  * @brief       This file contains implementation of Text Window manager.
5  * @version     -
6  * @remark      this source file is part of Binary vIEW project (BIEW).
7  *              The Binary vIEW (BIEW) is copyright (C) 1995 Nickols_K.
8  *              All rights reserved. This software is redistributable under the
9  *              licence given in the file "Licence.en" ("Licence.ru" in russian
10  *              translation) distributed in the BIEW archive.
11  * @note        Requires POSIX compatible development system
12  *
13  * @author      Nickols_K
14  * @since       1995
15  * @note        Development, fixes and improvements
16  * @warning     Program is destroyed, from twPrintF misapplication
17  * @bug         Limitation of twPrintF using
18  * @todo        Accelerate windows interaction algorithm
19 **/
20 
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <limits.h>
26 #ifdef __GNUC__
27 #include <unistd.h>
28 #endif
29 
30 #include "biewlib/twin.h"
31 #include "biewlib/pmalloc.h"
32 
33 const char TW_SINGLE_FRAME[8] = { TWC_Sd_Sr, TWC_SH, TWC_Sl_Sd, TWC_SV, TWC_SV, TWC_Su_Sr, TWC_SH, TWC_Sl_Su };
34 const char TW_DOUBLE_FRAME[8] = { TWC_Dd_Dr, TWC_DH, TWC_Dl_Dd, TWC_DV, TWC_DV, TWC_Du_Dr, TWC_DH, TWC_Dl_Du };
35 const char TW_MEDIUM_FRAME[8] = { TWC_FL_BLK, TWC_UP_HBLK, TWC_FL_BLK, TWC_FL_BLK, TWC_FL_BLK, TWC_FL_BLK, TWC_LF_HBLK, TWC_FL_BLK };
36 const char TW_THICK_FRAME[8] = { TWC_FL_BLK, TWC_FL_BLK, TWC_FL_BLK, TWC_FL_BLK, TWC_FL_BLK, TWC_FL_BLK, TWC_FL_BLK, TWC_FL_BLK };
37 const char TW_UP3D_FRAME[8] = "\x00\x00\x00\x00\x00\x00\x00\x00";
38 const char TW_DN3D_FRAME[8] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
39 
40 #ifndef NDEBUG
41 #ifdef __TSC__
42 #pragma save , call(inline=>on) /** GPF in protmode */
43 static void winInternalError( void ) = { 0xFF, 0xFF };
44 #elif defined _MSC_VER
winInternalError(void)45 static inline void winInternalError( void ) {};
46 #else
winInternalError(void)47 static inline void winInternalError( void ) { (void)0xFFFFFFFF; };
48 #endif
test_win(TWindow * win)49 static tBool __NEAR__ __FASTCALL__ test_win(TWindow *win)
50 {
51  tBool ret;
52  ret = *((void **)(win->body.chars + win->wsize)) == win->body.chars &&
53        *((void **)(win->body.oem_pg + win->wsize)) == win->body.oem_pg &&
54        *((void **)(win->body.attrs + win->wsize)) == win->body.attrs &&
55        *((void **)(win->saved.chars + win->wsize)) == win->saved.chars &&
56        *((void **)(win->saved.oem_pg + win->wsize)) == win->saved.oem_pg &&
57        *((void **)(win->saved.attrs + win->wsize)) == win->saved.attrs ? True : False;
58  return ret;
59 }
60 #define CHECK_WINS(x) { if(!test_win(x)) winInternalError(); }
61 #else
62 #define CHECK_WINS(x)
63 #endif
64 
65 #define IFLG_VISIBLE       0x00000001UL
66 #define IFLG_ENABLED       0x00000002UL
67 #define IFLG_CURSORBEENOFF 0x80000000UL
68 
69 TWindow *active;
70 
winerr(const char * str)71 static void __NEAR__ __FASTCALL__ __NORETURN__ winerr(const char *str) { printm("\n\nInternal twin library error: %s\n",str); _exit(EXIT_FAILURE); }
72 static void __NEAR__ __FASTCALL__ wputc_oem(char ch,char oempg,char color,tBool update);
73 static void __NEAR__ __FASTCALL__ paint_internal(void);
74 
75 #define wputc(ch,color,update) wputc_oem((char)ch,(char)0,(char)color,(tBool)update)
76 
77 static TWindow *head = NULL;
78 static TWindow *cursorwin = NULL;
79 
80 static unsigned long twin_flags = 0L;
81 
82 #define __FIND_OVER(ret,win,x,y)\
83 {\
84   TWindow *iter;\
85   tAbsCoord xx,yy;\
86   iter = head;\
87   ret = NULL;\
88   xx = win->X1+x;\
89   yy = win->Y1+y;\
90   while( iter && iter != win )\
91   {\
92     if((iter->iflags & IFLG_VISIBLE) == IFLG_VISIBLE)\
93     {\
94       if((yy >= iter->Y1) && (yy < iter->Y2) &&\
95          (xx >= iter->X1) && (xx < iter->X2))\
96                        ret = iter;\
97     }\
98     iter = iter->next;\
99   }\
100 }
101 
102 #define IS_VALID_XY(win,x,y)\
103   ((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE ?\
104    (tAbsCoord)x &&\
105    (tAbsCoord)x < win->wwidth-1 &&\
106    (tAbsCoord)y &&\
107    (tAbsCoord)y < win->wheight-1 :\
108    (tAbsCoord)x < win->wwidth &&\
109    (tAbsCoord)y < win->wheight)
110 
111 #define IS_VALID_X(win,x)\
112   ((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE ?\
113    (tAbsCoord)x &&\
114    (tAbsCoord)x < win->wwidth-1:\
115    (tAbsCoord)x < win->wwidth)
116 
117 #define IS_VALID_Y(win,y)\
118   ((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE ?\
119    (tAbsCoord)y &&\
120    (tAbsCoord)y < win->wheight-1 :\
121    (tAbsCoord)y < win->wheight)
122 
isOverlapped(TWindow * win)123 static tBool __NEAR__ __FASTCALL__ isOverlapped(TWindow *win)
124 {
125   TWindow *iter;
126   tBool ret = False;
127   iter = head;
128   while( iter && iter != win )
129   {
130     if((iter->iflags & IFLG_VISIBLE) == IFLG_VISIBLE)
131     {
132       if(!((iter->Y2 <= win->Y1) || (iter->Y1 >= win->Y2) ||
133            (iter->X2 <= win->X1) || (iter->X1 >= win->X2)))
134       {
135         ret = True;
136         break;
137       }
138     }
139     iter = iter->next;
140   }
141   return ret;
142 }
143 
144 /*
145    In most cases all output is being performed into non overlapped windows.
146    We should turn on special optimization for such windows, though overlapped
147    windows will seem relatively slower. There are additional possibilities to
148    accelerate all output by computing non overlapped lines of window or parts
149    of lines, but I don't want to do such complex task.
150 */
151 #define __TOPMOST(win) (!isOverlapped(win))
152 
153 #define __ATHEAD(win)\
154 {\
155   if(head) ((TWindow *)win)->next = head;\
156   head = (TWindow *)win;\
157 }
158 
159 #define __ATWIN(win,prev)\
160 {\
161   if(!prev) __ATHEAD(win)\
162   else\
163   {\
164      ((TWindow *)win)->next = ((TWindow *)prev)->next;\
165      ((TWindow *)prev)->next = (TWindow *)win;\
166   }\
167 }
168 
169 #define __AT_POINT(iter,x,y)\
170 {\
171   iter = head;\
172   while( iter )\
173   {\
174     if((iter->iflags & IFLG_VISIBLE) == IFLG_VISIBLE)\
175     {\
176       if(((tAbsCoord)y >= iter->Y1) && ((tAbsCoord)y < iter->Y2) &&\
177          ((tAbsCoord)x >= iter->X1) && ((tAbsCoord)x < iter->X2))\
178                        break;\
179     }\
180     iter = iter->next;\
181   }\
182 }
183 
184 static int c_type = -1;
twSetCursorType(int type)185 void __FASTCALL__ twSetCursorType(int type)
186 {
187   if(type != c_type)
188   {
189     __vioSetCursorType(type);
190     c_type = type;
191   }
192 }
193 
twGetCursorType(void)194 int __FASTCALL__ twGetCursorType( void )
195 {
196   if(c_type == -1) c_type = __vioGetCursorType();
197   return c_type;
198 }
199 
twInit(const char * user_cp,unsigned long vio_flags,unsigned long twin_flgs)200 void __FASTCALL__ twInit(const char *user_cp, unsigned long vio_flags, unsigned long twin_flgs )
201 {
202   const char *nls_cp;
203   twin_flags = twin_flgs;
204   nls_cp=user_cp?user_cp:"IBM866";
205   __init_vio(nls_cp,vio_flags);
206   __init_keyboard(nls_cp);
207   if(tvioWidth > __TVIO_MAXSCREENWIDTH)
208   {
209     char outs[256];
210     twDestroy();
211     sprintf(outs,"Size of video buffer is too large: %u (max = %u)",tvioWidth,__TVIO_MAXSCREENWIDTH);
212     winerr(outs);
213   }
214   twSetCursorType(TW_CUR_OFF);
215 }
216 
twDestroy(void)217 void __FASTCALL__ twDestroy( void )
218 {
219   twSetCursorType(TW_CUR_NORM);
220   twcDestroyClassSet();
221   __term_keyboard();
222   __term_vio();
223 }
224 /*
225   Hypothesis:
226     When 16-bits color is coded then weight of component is:
227     Blue  - 4 bits
228     Green - 6 bits
229     Red   - 6 bits
230   cause of human eye more sensitivity for blue color,
231   therefore weight of colors must will:
232 
233   Blue      - 6 balls
234   Green     - 4 balls
235   Red       - 4 balls
236 
237   Brightness is 128 192 255 i.e.:
238                 2   3   4
239   Cause of programs can used multiple color conversation better use same
240   values for each color component
241 */
242 #define BR_BLUE  1
243 #define BR_GREEN 1
244 #define BR_RED   1
245 
246 static const unsigned char brightness[16] =
247 {
248         /* RGB: Name */
249     BR_RED*0+BR_GREEN*0+BR_BLUE*0, /**< 000: Black */
250     BR_RED*0+BR_GREEN*0+BR_BLUE*2, /**< 002: Blue */
251     BR_RED*0+BR_GREEN*2+BR_BLUE*0, /**< 020: Green */
252     BR_RED*0+BR_GREEN*2+BR_BLUE*2, /**< 022: Cyan */
253     BR_RED*2+BR_GREEN*0+BR_BLUE*0, /**< 200: Red */
254     BR_RED*2+BR_GREEN*0+BR_BLUE*2, /**< 202: Magenta */
255     BR_RED*2+BR_GREEN*2+BR_BLUE*0, /**< 220: Brown */
256     BR_RED*3+BR_GREEN*3+BR_BLUE*3, /**< 333: LightGray */
257     BR_RED*2+BR_GREEN*2+BR_BLUE*2, /**< 222: Gray */
258     BR_RED*0+BR_GREEN*0+BR_BLUE*4, /**< 004: LightBlue */
259     BR_RED*0+BR_GREEN*4+BR_BLUE*0, /**< 040: LightGreen */
260     BR_RED*0+BR_GREEN*4+BR_BLUE*4, /**< 044: LightCyan */
261     BR_RED*4+BR_GREEN*0+BR_BLUE*0, /**< 400: LightRed */
262     BR_RED*4+BR_GREEN*0+BR_BLUE*4, /**< 404: LightMagenta */
263     BR_RED*4+BR_GREEN*4+BR_BLUE*0, /**< 440: Yellow */
264     BR_RED*4+BR_GREEN*4+BR_BLUE*4  /**< 444: White */
265 };
266 
267 unsigned char color_map[16] =
268 {
269   0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
270 };
271 
adjustColor(Color * fore,Color * back)272 static void __NEAR__ __FASTCALL__ adjustColor(Color *fore,Color *back)
273 {
274   if(tvioNumColors < 16 || (twin_flags & TWIF_FORCEMONO))
275   {
276     unsigned char br_fore, br_back;
277     br_fore = brightness[(*fore) & 0x0F];
278     br_back = brightness[(*back) & 0x0F];
279     if(br_fore >= br_back)
280     {
281       *fore = LightGray;
282       *back = Black;
283     }
284     else
285     {
286       *fore = Black;
287       *back = LightGray;
288     }
289   }
290   (*fore) = color_map[(*fore) & 0x0F];
291   (*back) = color_map[(*back) & 0x0F];
292 }
293 
__set_color(DefColor * to,Color fore,Color back)294 static void __NEAR__ __FASTCALL__ __set_color(DefColor *to,Color fore,Color back)
295 {
296   to->user = LOGFB_TO_PHYS(fore,back);
297   adjustColor(&fore,&back);
298   to->system = LOGFB_TO_PHYS(fore,back);
299 }
300 
twSetColor(Color fore,Color back)301 ColorAttr __FASTCALL__ twSetColor(Color fore,Color back)
302 {
303   ColorAttr ret;
304   ret = active->text.user;
305   __set_color(&active->text,fore,back);
306   return ret;
307 }
308 
twSetColorAttr(ColorAttr ca)309 ColorAttr __FASTCALL__ twSetColorAttr(ColorAttr ca)
310 {
311   return twSetColor(FORE_COLOR(ca),BACK_COLOR(ca));
312 }
313 
twGetColorAttr(void)314 ColorAttr __FASTCALL__ twGetColorAttr( void ) { return active->text.user; }
315 
twGetColor(Color * fore,Color * back)316 void __FASTCALL__ twGetColor(Color *fore,Color *back)
317 {
318   ColorAttr ca = twGetColorAttr();
319   PHYS_TO_LOGFB(ca,*fore,*back);
320 }
321 
twTextColor(Color col)322 Color __FASTCALL__ twTextColor( Color col )
323 {
324   Color back,ret;
325   ColorAttr attr;
326   attr = twGetColorAttr();
327   back = BACK_COLOR(attr);
328   ret = FORE_COLOR(attr);
329   twSetColor(col, back);
330   return ret;
331 }
332 
twTextBkGnd(Color col)333 Color __FASTCALL__ twTextBkGnd( Color col )
334 {
335    Color fore,ret;
336    ColorAttr attr;
337    attr = twGetColorAttr();
338    fore = FORE_COLOR(attr);
339    ret = BACK_COLOR(attr);
340    twSetColor(fore, col);
341    return ret;
342 }
343 
twSetFrame(TWindow * win,const char * frame,Color fore,Color back)344 void __FASTCALL__ twSetFrame(TWindow *win,const char *frame,Color fore,Color back)
345 {
346   TWindow *tmp;
347   win->flags |= TWS_FRAMEABLE;
348   memcpy(win->Frame,frame,8);
349   __set_color(&win->frame,fore,back);
350   tmp = active;
351   active = win;
352   paint_internal();
353   active = tmp;
354 }
355 
twSetFrameAttr(TWindow * win,const char * frame,ColorAttr attr)356 void __FASTCALL__ twSetFrameAttr(TWindow *win,const char *frame,ColorAttr attr)
357 {
358    twSetFrame(win,frame,FORE_COLOR(attr),BACK_COLOR(attr));
359 }
360 
twGetFrameAttr(TWindow * win,char * frame,ColorAttr * attr)361 void __FASTCALL__ twGetFrameAttr(TWindow *win,char *frame,ColorAttr* attr)
362 {
363   if((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE)
364   {
365     memcpy(frame,active->Frame,8);
366     *attr = win->frame.user;
367   }
368 }
369 
twGetFrame(TWindow * win,char * frame,Color * fore,Color * back)370 void __FASTCALL__ twGetFrame(TWindow *win,char *frame,Color* fore,Color* back)
371 {
372   ColorAttr attr;
373   twGetFrameAttr(win,frame,&attr);
374   *fore = FORE_COLOR(attr);
375   *back = BACK_COLOR(attr);
376 }
377 
twSetTitle(TWindow * win,const char * title,tTitleMode mode,Color fore,Color back)378 void __FASTCALL__ twSetTitle(TWindow *win,const char *title,tTitleMode mode,Color fore,Color back)
379 {
380   TWindow *tmp;
381   unsigned slen;
382   slen = strlen(title);
383   if(win->Title) PFREE(win->Title);
384   win->Title = PMalloc(slen+1);
385   if(!win->Title) winerr("Out of memory!");
386   strcpy(win->Title,title);
387   if((win->flags & TWS_NLSOEM) == TWS_NLSOEM)
388          __nls_OemToOsdep((unsigned char *)win->Title,slen);
389   win->TitleMode = mode;
390   __set_color(&win->title,fore,back);
391   tmp = active;
392   active = win;
393   paint_internal();
394   active = tmp;
395 }
396 
twSetTitleAttr(TWindow * win,const char * title,tTitleMode mode,ColorAttr attr)397 void __FASTCALL__ twSetTitleAttr(TWindow *win,const char *title,tTitleMode mode,ColorAttr attr)
398 {
399   twSetTitle(win,title,mode,FORE_COLOR(attr),BACK_COLOR(attr));
400 }
401 
twGetTitleAttr(TWindow * win,char * title,unsigned cb_title,ColorAttr * attr)402 tTitleMode __FASTCALL__ twGetTitleAttr(TWindow *win,char *title,unsigned cb_title,ColorAttr* attr)
403 {
404   tTitleMode ret = 0;
405   if((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE && win->Title)
406   {
407     strncpy(title,win->Title,cb_title);
408     title[cb_title-1] = '\0';
409     *attr = win->title.user;
410     ret = win->TitleMode;
411   }
412   return ret;
413 }
414 
twGetTitle(TWindow * win,char * title,unsigned cb_title,Color * fore,Color * back)415 tTitleMode __FASTCALL__ twGetTitle(TWindow *win,char *title,unsigned cb_title,Color* fore,Color* back)
416 {
417   ColorAttr attr;
418   tTitleMode ret;
419   ret = twGetTitleAttr(win,title,cb_title,&attr);
420   *fore = FORE_COLOR(attr);
421   *back = BACK_COLOR(attr);
422   return ret;
423 }
424 
twSetFooter(TWindow * win,const char * footer,tTitleMode mode,Color fore,Color back)425 void __FASTCALL__ twSetFooter(TWindow *win,const char *footer,tTitleMode mode,Color fore,Color back)
426 {
427   TWindow *tmp;
428   unsigned slen;
429   slen = strlen(footer);
430   if(win->Footer) PFREE(win->Footer);
431   win->Footer = PMalloc(slen+1);
432   if(!win->Footer) winerr("Out of memory!");
433   strcpy(win->Footer,footer);
434   if((win->flags & TWS_NLSOEM) == TWS_NLSOEM)
435        __nls_OemToOsdep((unsigned char *)win->Footer,slen);
436   win->FooterMode = mode;
437   __set_color(&win->footer,fore,back);
438   tmp = active;
439   active = win;
440   paint_internal();
441   active = tmp;
442 }
443 
twSetFooterAttr(TWindow * win,const char * footer,tTitleMode mode,ColorAttr attr)444 void __FASTCALL__ twSetFooterAttr(TWindow *win,const char *footer,tTitleMode mode,ColorAttr attr)
445 {
446   twSetFooter(win,footer,mode,FORE_COLOR(attr),BACK_COLOR(attr));
447 }
448 
twGetFooterAttr(TWindow * win,char * footer,unsigned cb_footer,ColorAttr * attr)449 tTitleMode __FASTCALL__ twGetFooterAttr(TWindow *win,char *footer,unsigned cb_footer,ColorAttr* attr)
450 {
451   tTitleMode ret = 0;
452   if((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE && win->Footer)
453   {
454     strncpy(footer,win->Footer,cb_footer);
455     footer[cb_footer-1] = '\0';
456     *attr = win->footer.user;
457     ret = win->FooterMode;
458   }
459   return ret;
460 }
461 
462 
twGetFooter(TWindow * win,char * footer,unsigned cb_footer,Color * fore,Color * back)463 tTitleMode __FASTCALL__ twGetFooter(TWindow *win,char *footer,unsigned cb_footer,Color* fore,Color* back)
464 {
465   ColorAttr attr;
466   tTitleMode ret;
467   ret = twGetFooterAttr(win,footer,cb_footer,&attr);
468   *fore = FORE_COLOR(attr);
469   *back = BACK_COLOR(attr);
470   return ret;
471 }
472 
__unlistwin(TWindow * win)473 static void __NEAR__ __FASTCALL__ __unlistwin(TWindow *win)
474 {
475   if(head == win) head = win->next;
476   else
477   {
478     TWindow *iter;
479     iter = head;
480     while(iter)
481     {
482        if(iter->next) if(iter->next == win) iter->next = win->next;
483        iter = iter->next;
484     }
485   }
486 }
487 
__prevwin(TWindow * win)488 static TWindow * __NEAR__ __FASTCALL__ __prevwin(TWindow *win)
489 {
490   TWindow *ret = NULL;
491   if(head != win)
492   {
493     TWindow *iter;
494     iter = head;
495     while(iter)
496     {
497        if(iter->next) if(iter->next == win) { ret = iter; break; }
498        iter = iter->next;
499     }
500   }
501   return ret;
502 }
503 
__findcursorablewin(void)504 static TWindow * __NEAR__ __FASTCALL__ __findcursorablewin(void)
505 {
506   TWindow *iter,*ret;
507   iter = head;
508   ret = NULL;
509   while(iter)
510   {
511      if((iter->flags & TWS_CURSORABLE) == TWS_CURSORABLE) { ret = iter; break; }
512      iter = iter->next;
513   }
514   return ret;
515 }
516 
twGetWinAtPos(tAbsCoord x,tAbsCoord y)517 TWindow * __FASTCALL__ twGetWinAtPos(tAbsCoord x,tAbsCoord y)
518 {
519   TWindow *ret;
520   tAbsCoord xx,yy;
521   xx = x-1;
522   yy = y-1;
523   __AT_POINT(ret,xx,yy);
524   return ret;
525 }
526 
twCvtWinCoords(TWindow * win,tRelCoord x,tRelCoord y,tAbsCoord * xa,tAbsCoord * ya)527 void __FASTCALL__ twCvtWinCoords(TWindow *win,tRelCoord x, tRelCoord y,tAbsCoord *xa,tAbsCoord *ya)
528 {
529   if(win->flags & TWS_FRAMEABLE) { x++; y++; }
530   *xa = win->X1+x;
531   *ya = win->Y1+y;
532 }
533 
twCvtScreenCoords(TWindow * win,tAbsCoord x,tAbsCoord y,tRelCoord * xr,tRelCoord * yr)534 tBool __FASTCALL__ twCvtScreenCoords(TWindow *win,tAbsCoord x, tAbsCoord y,tRelCoord *xr,tRelCoord *yr)
535 {
536   *xr = x - win->X1;
537   *yr = y - win->Y1;
538   if(win->flags & TWS_FRAMEABLE) { (*xr)--; (*yr)--; }
539   return IS_VALID_XY(win,*xr,*yr) ? True : False;
540 }
541 
twIsPieceVisible(TWindow * win,tRelCoord x,tRelCoord y)542 tBool __FASTCALL__ twIsPieceVisible(TWindow *win,tRelCoord x, tRelCoord y)
543 {
544   TWindow *over;
545   if(win->flags & TWS_FRAMEABLE) { x++; y++; }
546   __FIND_OVER(over,win,win->X1+x,win->Y1+y);
547   return over ? True : False;
548 }
549 
iGotoXY(tRelCoord x,tRelCoord y)550 static void __NEAR__ __FASTCALL__ iGotoXY(tRelCoord x,tRelCoord y)
551 {
552   if(x && y)
553   {
554     active->cur_x = x-1;
555     active->cur_y = y-1;
556     if(active->cur_x >= active->wwidth) active->cur_x = active->wwidth-1;
557     if(active->cur_y >= active->wheight) active->cur_y = active->wheight-1;
558   }
559 }
560 
set_xy(tRelCoord x,tRelCoord y)561 static void __NEAR__ __FASTCALL__ set_xy(tRelCoord x,tRelCoord y)
562 {
563   tRelCoord width,height;
564   if(x && y)
565   {
566     x--; y--;
567     active->cur_x = x;
568     active->cur_y = y;
569     width = active->wwidth;
570     height = active->wheight;
571     if((active->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE)
572     {
573       width--;
574       height--;
575       active->cur_x++;
576       active->cur_y++;
577     }
578     if(active->cur_x > width) active->cur_x = width-1;
579     if(active->cur_y > height) active->cur_y = height-1;
580   }
581 }
582 
paint_cursor(void)583 static void __NEAR__ __FASTCALL__ paint_cursor( void )
584 {
585   TWindow * top=NULL;
586   static tAbsCoord c_x = UCHAR_MAX, c_y = UCHAR_MAX;
587   int _c_type = -1;
588   unsigned x,y;
589   int type;
590   if(cursorwin && (cursorwin->iflags & IFLG_ENABLED) == IFLG_ENABLED)
591   {
592     __FIND_OVER(top,cursorwin,cursorwin->cur_x,cursorwin->cur_y-1);
593     if(!top && (cursorwin->iflags & IFLG_VISIBLE) == IFLG_VISIBLE && cursorwin == active)
594     {
595         type = twGetCursorType();
596         if(type == TW_CUR_OFF)
597         {
598          twSetCursorType(_c_type == -1 ? TW_CUR_NORM : _c_type);
599          _c_type = _c_type == -1 ? TW_CUR_NORM : _c_type;
600         }
601         x = active->X1 + active->cur_x;
602         y = active->Y1 + active->cur_y;
603         if(!(x == c_x && y == c_y))
604         {
605           __vioSetCursorPos(x,y);
606           c_x = x;
607           c_y = y;
608         }
609     }
610     else goto hide_cursor;
611   }
612   else
613   {
614     c_x = c_y = UCHAR_MAX;
615     hide_cursor:
616     type = twGetCursorType();
617     if(type != TW_CUR_OFF)
618     {
619       _c_type = type;
620       twSetCursorType(TW_CUR_OFF);
621     }
622   }
623 }
624 
twGotoXY(tRelCoord x,tRelCoord y)625 void __FASTCALL__ twGotoXY(tRelCoord x,tRelCoord y)
626 {
627   set_xy(x,y);
628   paint_cursor();
629 }
630 
makewin(tAbsCoord x1,tAbsCoord y1,tAbsCoord width,tAbsCoord height)631 static TWindow * __NEAR__ __FASTCALL__ makewin(tAbsCoord x1, tAbsCoord y1, tAbsCoord width, tAbsCoord height)
632 {
633   TWindow *win;
634   unsigned size;
635   win = PMalloc(sizeof(TWindow));
636   if(win)
637   {
638     memset(win,0,sizeof(TWindow));
639     size = width*height;
640     win->wsize = size;
641     win->wwidth = width;
642     win->wheight = height;
643     if(!(win->body.chars = PMalloc(size*sizeof(t_vchar)
644 #ifndef NDEBUG
645                                    +sizeof(void *)
646 #endif
647       )))
648     {
649      bye0:
650       PFREE(win);
651       return NULL;
652     }
653     if(!(win->body.oem_pg = PMalloc(size*sizeof(t_vchar)
654 #ifndef NDEBUG
655                                    +sizeof(void *)
656 #endif
657       )))
658     {
659      bye1:
660       PFREE(win->body.chars);
661       goto bye0;
662     }
663     if(!(win->body.attrs = PMalloc(size*sizeof(ColorAttr)
664 #ifndef NDEBUG
665                                    +sizeof(void *)
666 #endif
667       )))
668     {
669      bye2:
670       PFREE(win->body.oem_pg);
671       goto bye1;
672     }
673     if(!(win->saved.chars = PMalloc(size*sizeof(t_vchar)
674 #ifndef NDEBUG
675                                    +sizeof(void *)
676 #endif
677       )))
678     {
679      bye3:
680       PFREE(win->body.attrs);
681       goto bye2;
682     }
683     if(!(win->saved.oem_pg = PMalloc(size*sizeof(t_vchar)
684 #ifndef NDEBUG
685                                    +sizeof(void *)
686 #endif
687       )))
688     {
689      bye4:
690       PFREE(win->saved.chars);
691       goto bye3;
692     }
693     if(!(win->saved.attrs = PMalloc(size*sizeof(ColorAttr)
694 #ifndef NDEBUG
695                                    +sizeof(void *)
696 #endif
697       )))
698     {
699       PFREE(win->saved.oem_pg);
700       goto bye4;
701     }
702 #ifndef NDEBUG
703     *((void **)(win->body.chars + size)) = win->body.chars;
704     *((void **)(win->saved.chars + size)) = win->saved.chars;
705     *((void **)(win->body.oem_pg + size)) = win->body.oem_pg;
706     *((void **)(win->saved.oem_pg + size)) = win->saved.oem_pg;
707     *((void **)(win->body.attrs + size)) = win->body.attrs;
708     *((void **)(win->saved.attrs + size)) = win->saved.attrs;
709 #endif
710     win->X1 = x1;
711     win->Y1 = y1;
712     win->X2 = x1+width;
713     win->Y2 = y1+height;
714     __ATHEAD(win);
715   }
716   return win;
717 }
718 
719 /**
720  *  Three basic functions for copying from buffer to screen:
721  *  ========================================================
722  *  updatescreencharfrombuff: low level implementation updatescreen family
723  *  updatescreenchar:  correctly copyed user record from win to screen
724  *  restorescreenchar: correctly copyed window memory from win to screen
725  */
726 
updatescreencharfrombuff(TWindow * win,tRelCoord x,tRelCoord y,tvioBuff * buff,tvioBuff * accel)727 static void __NEAR__ __FASTCALL__ updatescreencharfrombuff(TWindow *win,
728                                               tRelCoord x,
729                                               tRelCoord y,
730                                               tvioBuff *buff,
731                                               tvioBuff *accel)
732 {
733   tvioBuff it;
734   unsigned idx,aidx;
735   if((win->iflags & IFLG_VISIBLE) == IFLG_VISIBLE)
736   {
737     TWindow * top;
738     idx = y*win->wwidth+x;
739     aidx = x;
740     __FIND_OVER(top,win,x,y);
741     if(top)
742     {
743       unsigned tidx;
744       tAbsCoord tx,ty;
745       tx = win->X1 - top->X1 + x;
746       ty = win->Y1 - top->Y1 + y;
747       tidx = tx + ty*top->wwidth;
748       top->saved.chars[tidx] = buff->chars[idx];
749       top->saved.oem_pg[tidx] = buff->oem_pg[idx];
750       top->saved.attrs[tidx] = buff->attrs[idx];
751       if(accel)
752       {
753         TWindow *vis;
754         tAbsCoord xx,yy;
755         xx = x+win->X1;
756         yy = y+win->Y1;
757         __AT_POINT(vis,xx,yy);
758         tx = xx - vis->X1;
759         ty = yy - vis->Y1;
760         tidx = tx + ty*vis->wwidth;
761         accel->chars[aidx] = vis->body.chars[tidx];
762         accel->oem_pg[aidx] = vis->body.oem_pg[tidx];
763         accel->attrs[aidx] = vis->body.attrs[tidx];
764       }
765       CHECK_WINS(top);
766     }
767     else
768     {
769       tBool ms_vis;
770       tBool is_hidden = False;
771       if(accel)
772       {
773         accel->chars[aidx] = buff->chars[idx];
774         accel->oem_pg[aidx] = buff->oem_pg[idx];
775         accel->attrs[aidx] = buff->attrs[idx];
776       }
777       else
778       {
779         if((win->iflags & IFLG_ENABLED) == IFLG_ENABLED)
780         {
781           tAbsCoord outx,outy;
782           ms_vis = __MsGetState();
783           outx = (unsigned)win->X1+x;
784           outy = (unsigned)win->Y1+y;
785           if(outx+1 <= tvioWidth && outy <= tvioHeight)
786           {
787             if(ms_vis)
788             {
789                tAbsCoord mx,my;
790                __MsGetPos(&mx,&my);
791                if(mx == outx && my == outy)
792                {
793                  is_hidden = True;
794                  __MsSetState(False);
795                }
796             }
797             it.chars = &buff->chars[idx];
798             it.oem_pg = &buff->oem_pg[idx];
799             it.attrs = &buff->attrs[idx];
800             __vioWriteBuff(outx,outy,&it,1);
801             if(is_hidden) __MsSetState(True);
802           }
803           CHECK_WINS(win);
804         }
805       }
806     }
807   }
808 }
809 
810 #define updatescreenchar(win,x,y,accel)\
811    updatescreencharfrombuff((TWindow *)win,\
812                             (tRelCoord)x-1,\
813                             (tRelCoord)y-1,\
814                             &((TWindow *)win)->body,\
815                             (tvioBuff *)accel)
816 
817 #define restorescreenchar(win,x,y,accel)\
818    updatescreencharfrombuff((TWindow *)win,\
819                             (tRelCoord)x-1,\
820                             (tRelCoord)y-1,\
821                             &((TWindow *)win)->saved,\
822                             (tvioBuff *)accel)
823 /**
824  *  Three basic functions for copying from buffer to screen:
825  *  ========================================================
826  *  updatewinmemcharfromscreen: correctly copied screen to window memory
827  *  screen2win: quick implementation of copying screen to window memory
828  *  snapshot:   snap shot of screen to win body
829  */
830 
updatewinmemcharfromscreen(TWindow * win,tRelCoord x,tRelCoord y,tvioBuff * accel)831 static void __NEAR__ __FASTCALL__ updatewinmemcharfromscreen(TWindow *win,tRelCoord x,tRelCoord y,tvioBuff *accel)
832 {
833   unsigned idx,aidx;
834   tvioBuff it;
835   if((win->iflags & IFLG_VISIBLE) == IFLG_VISIBLE)
836   {
837     TWindow * top;
838     idx = y*win->wwidth+x;
839     aidx = x;
840     __FIND_OVER(top,win,x,y);
841     if(top)
842     {
843       unsigned tidx;
844       tAbsCoord tx,ty;
845       tx = win->X1 - top->X1 + x;
846       ty = win->Y1 - top->Y1 + y;
847       tidx = tx + ty*top->wwidth;
848       win->saved.chars[idx] = top->saved.chars[tidx];
849       win->saved.oem_pg[idx] = top->saved.oem_pg[tidx];
850       win->saved.attrs[idx] = top->saved.attrs[tidx];
851       top->saved.chars[tidx] = win->body.chars[idx];
852       top->saved.oem_pg[tidx] = win->body.oem_pg[idx];
853       top->saved.attrs[tidx] = win->body.attrs[idx];
854       CHECK_WINS(top);
855     }
856     else
857     {
858       tBool ms_vis;
859       tBool is_hidden = False;
860       if(accel)
861       {
862         win->saved.chars[idx] = accel->chars[aidx];
863         win->saved.oem_pg[idx] = accel->oem_pg[aidx];
864         win->saved.attrs[idx] = accel->attrs[aidx];
865       }
866       else
867       {
868         tAbsCoord inx,iny;
869         inx = (unsigned)win->X1+x;
870         iny = (unsigned)win->Y1+y;
871         if(inx+2 <= tvioWidth && iny <= tvioHeight)
872         {
873           ms_vis = __MsGetState();
874           if(ms_vis)
875           {
876              tAbsCoord mx,my;
877              __MsGetPos(&mx,&my);
878              if(mx == inx && my == iny)
879              {
880                is_hidden = True;
881                __MsSetState(False);
882              }
883           }
884           it.chars = &win->saved.chars[idx];
885           it.oem_pg = &win->saved.oem_pg[idx];
886           it.attrs = &win->saved.attrs[idx];
887           __vioReadBuff(inx,iny,&it,2);
888           if(is_hidden) __MsSetState(True);
889         }
890         CHECK_WINS(win);
891       }
892     }
893   }
894 }
895 
screen2win(TWindow * win)896 static void __NEAR__ __FASTCALL__ screen2win(TWindow *win)
897 {
898   tvioBuff it;
899   unsigned i,lwidth,idx;
900   tAbsCoord inx;
901   tBool ms_vis;
902   tBool is_hidden = False;
903   inx = win->X1;
904   lwidth = win->wwidth;
905   if(inx + lwidth > tvioWidth) lwidth = tvioWidth > inx ? tvioWidth - inx : 0;
906   if(lwidth)
907   {
908     ms_vis = __MsGetState();
909     if(ms_vis)
910     {
911       tAbsCoord mx,my;
912       __MsGetPos(&mx,&my);
913       if(mx >= inx && mx <= win->X2 && my >= win->Y1 && my <= win->Y2)
914       {
915         is_hidden = True;
916         __MsSetState(False);
917       }
918     }
919     if(win->wwidth == tvioWidth && !win->X1)
920     {
921       __vioReadBuff(0, win->Y1, &win->saved, win->wwidth*win->wheight);
922     }
923     else
924     {
925       for(i = 0;i < win->wheight;i++)
926       {
927         tAbsCoord iny;
928         iny = win->Y1+i;
929         if(iny <= tvioHeight)
930         {
931           idx = i*win->wwidth;
932           it.chars = &win->saved.chars[idx];
933           it.oem_pg = &win->saved.oem_pg[idx];
934           it.attrs = &win->saved.attrs[idx];
935           __vioReadBuff(inx,iny,&it,lwidth);
936         }
937         else break;
938       }
939     }
940     if(is_hidden) __MsSetState(True);
941   }
942   CHECK_WINS(win);
943 }
944 
twSnapShot(TWindow * win)945 void __FASTCALL__ twSnapShot(TWindow *win) /**< for snapshot */
946 {
947   tvioBuff it;
948   unsigned i,lwidth,idx;
949   tAbsCoord inx;
950   tBool ms_vis;
951   tBool is_hidden = False;
952   inx = win->X1;
953   lwidth = win->wwidth;
954   if(inx + lwidth > tvioWidth) lwidth = tvioWidth > inx ? tvioWidth - inx : 0;
955   if(lwidth)
956   {
957     ms_vis = __MsGetState();
958     if(ms_vis)
959     {
960       tAbsCoord mx,my;
961       __MsGetPos(&mx,&my);
962       if(mx >= inx && mx <= win->X2 && my >= win->Y1 && my <= win->Y2)
963       {
964         is_hidden = True;
965         __MsSetState(False);
966       }
967     }
968     for(i = 0;i < win->wheight;i++)
969     {
970       tAbsCoord iny;
971       iny = win->Y1+i;
972       if(iny <= tvioHeight)
973       {
974         idx = i*win->wwidth;
975         it.chars = &win->body.chars[idx];
976         it.oem_pg = &win->body.oem_pg[idx];
977         it.attrs = &win->body.attrs[idx];
978         __vioReadBuff(inx,iny,&it,lwidth);
979       }
980       else break;
981     }
982     if(is_hidden) __MsSetState(True);
983   }
984   CHECK_WINS(win);
985 }
986 
987 /**
988  *  Helpful functions:
989  *  ==================
990  *  savedwin2screen:  restore entire window memory to screen
991  *  updatescreen:     restore entire user record of window to screen
992  *  updatescreenpiece:restore one piece of line from user record of window to screen
993  *  updatewinmem:     update entire window memory from screen
994  */
995 
savedwin2screen(TWindow * win)996 static void __NEAR__ __FASTCALL__ savedwin2screen(TWindow *win)
997 {
998   unsigned i,j, tidx;
999   tvioBuff accel;
1000   t_vchar chars[__TVIO_MAXSCREENWIDTH];
1001   t_vchar oem_pg[__TVIO_MAXSCREENWIDTH];
1002   ColorAttr attrs[__TVIO_MAXSCREENWIDTH];
1003   tBool ms_vis, is_hidden = False, is_top;
1004   accel.chars = chars;
1005   accel.oem_pg = oem_pg;
1006   accel.attrs = attrs;
1007   if((win->iflags & IFLG_VISIBLE) == IFLG_VISIBLE)
1008   {
1009     tAbsCoord mx,my;
1010     ms_vis = __MsGetState();
1011     if(ms_vis)
1012     {
1013       __MsGetPos(&mx,&my);
1014       if(mx >= win->X1 && mx <= win->X2 && my >= win->Y1 && my <= win->Y2)
1015       {
1016         is_hidden = True;
1017         __MsSetState(False);
1018       }
1019     }
1020     is_top = __TOPMOST(win);
1021     if(is_top && win->wwidth == tvioWidth && !win->X1)
1022     {
1023       /* Special case of redrawing window interior at one call */
1024       __vioWriteBuff(0, win->Y1, &win->saved, win->wwidth*win->wheight);
1025     }
1026     else
1027     {
1028       for(i = 0;i < win->wheight;i++)
1029       {
1030         tAbsCoord outx,outy;
1031         unsigned nwidth;
1032         if(!is_top)
1033           for(j = 0;j < win->wwidth;j++) restorescreenchar(win,j+1,i+1,&accel);
1034         else
1035         {
1036            tidx = i*win->wwidth;
1037            accel.chars = &win->saved.chars[tidx];
1038            accel.attrs = &win->saved.attrs[tidx];
1039            accel.oem_pg = &win->saved.oem_pg[tidx];
1040         }
1041         outx = win->X1;
1042         outy = win->Y1+i;
1043         nwidth = win->wwidth;
1044         if(outx + nwidth > tvioWidth) nwidth = tvioWidth > outx ? tvioWidth - outx : 0;
1045         if(outy <= tvioHeight && nwidth)
1046             __vioWriteBuff(outx,outy,&accel,nwidth);
1047       }
1048     }
1049     if(is_hidden) __MsSetState(True);
1050     CHECK_WINS(win);
1051   }
1052 }
1053 
updatescreen(TWindow * win,tBool full_area)1054 static void __NEAR__ __FASTCALL__ updatescreen(TWindow *win,tBool full_area)
1055 {
1056   unsigned i,j, tidx;
1057   tAbsCoord xs,xe,ys,ye,cx,rw;
1058   unsigned aoff;
1059   tvioBuff accel,it;
1060   t_vchar chars[__TVIO_MAXSCREENWIDTH];
1061   t_vchar oem_pg[__TVIO_MAXSCREENWIDTH];
1062   ColorAttr attrs[__TVIO_MAXSCREENWIDTH];
1063   tBool ms_vis, is_hidden = False, is_top;
1064   accel.chars = chars;
1065   accel.oem_pg = oem_pg;
1066   accel.attrs = attrs;
1067   if((win->iflags & IFLG_VISIBLE) == IFLG_VISIBLE)
1068   {
1069     tAbsCoord mx,my;
1070     ms_vis = __MsGetState();
1071     if(ms_vis)
1072     {
1073       xs = win->X1;
1074       xe = win->X2;
1075       ys = win->Y1;
1076       ye = win->Y2;
1077       if((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE && (!full_area))
1078       {
1079         xs++; xe--; ys++; ye--;
1080       }
1081       __MsGetPos(&mx,&my);
1082       if(mx >= xs && mx <= xe && my >= ys && my <= ye)
1083       {
1084         is_hidden = True;
1085         __MsSetState(False);
1086       }
1087     }
1088     is_top = __TOPMOST(win);
1089     if(is_top && full_area && win->wwidth == tvioWidth && !win->X1 && (win->iflags & IFLG_ENABLED) == IFLG_ENABLED)
1090     {
1091       /* Special case of redrawing window interior at one call */
1092       __vioWriteBuff(0, win->Y1, &win->body, win->wwidth*win->wheight);
1093     }
1094     else
1095     {
1096       xs = ys = 0;
1097       xe = win->wwidth;
1098       ye = win->wheight;
1099       cx = win->X1;
1100       rw = win->wwidth;
1101       aoff = 0;
1102       if((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE && (!full_area))
1103       {
1104           xs++; xe--; ys++; ye--;
1105           cx++; rw-=2;
1106           aoff = 1;
1107       }
1108       for(i = ys;i < ye;i++)
1109       {
1110         tAbsCoord outy;
1111         if(!is_top)
1112           for(j = xs;j < xe;j++) updatescreenchar(win,j+1,i+1,&accel);
1113         if((win->iflags & IFLG_ENABLED) == IFLG_ENABLED)
1114         {
1115           outy = win->Y1+i;
1116           if(cx + rw > tvioWidth) rw = tvioWidth > cx ? tvioWidth - cx : 0;
1117           if(outy <= tvioHeight && rw)
1118           {
1119             tidx = i*win->wwidth+aoff;
1120             it.chars = is_top ? &win->body.chars[tidx] : &accel.chars[aoff];
1121             it.oem_pg = is_top ? &win->body.oem_pg[tidx] : &accel.oem_pg[aoff];
1122             it.attrs = is_top ? &win->body.attrs[tidx] : &accel.attrs[aoff];
1123             __vioWriteBuff(cx,outy,&it,rw);
1124           }
1125         }
1126       }
1127     }
1128     if(is_hidden) __MsSetState(True);
1129     CHECK_WINS(win);
1130   }
1131 }
1132 
updatescreenpiece(TWindow * win,tRelCoord stx,tRelCoord endx,tRelCoord y)1133 static void __NEAR__ __FASTCALL__ updatescreenpiece(TWindow *win,tRelCoord stx,tRelCoord endx,tRelCoord y)
1134 {
1135   unsigned i,line, tidx;
1136   tAbsCoord _stx,_endx;
1137   tvioBuff accel,it;
1138   t_vchar chars[__TVIO_MAXSCREENWIDTH];
1139   t_vchar oem_pg[__TVIO_MAXSCREENWIDTH];
1140   ColorAttr attrs[__TVIO_MAXSCREENWIDTH];
1141   tBool ms_vis, is_hidden = False, is_top;
1142   accel.chars = chars;
1143   accel.oem_pg = oem_pg;
1144   accel.attrs = attrs;
1145   if((win->iflags & IFLG_VISIBLE) == IFLG_VISIBLE)
1146   {
1147     tAbsCoord mx,my;
1148     ms_vis = __MsGetState();
1149     __MsGetPos(&mx,&my);
1150     line = win->Y1+y-1;
1151     if(ms_vis && my == line)
1152     {
1153       is_hidden = True;
1154       __MsSetState(False);
1155     }
1156     _stx = min(stx,win->wwidth);
1157     _endx = min(endx,win->wwidth);
1158     is_top = __TOPMOST(win);
1159     if(!is_top)
1160     {
1161       if(_stx < _endx)
1162         for(i = stx;i < endx;i++)
1163           updatescreenchar(win,i+1,y,&accel);
1164     }
1165     if((win->iflags & IFLG_ENABLED) == IFLG_ENABLED)
1166     {
1167       tAbsCoord outx;
1168       unsigned rw;
1169       outx = win->X1+_stx;
1170       rw = _endx - _stx;
1171       if(outx + rw > tvioWidth) rw = tvioWidth > outx ? tvioWidth - outx : 0;
1172       if(line <= tvioHeight && rw)
1173       {
1174         tidx = (y-1)*win->wwidth+_stx;
1175         it.chars = is_top ? &win->body.chars[tidx] : &accel.chars[_stx];
1176         it.oem_pg = is_top ? &win->body.oem_pg[tidx] : &accel.oem_pg[_stx];
1177         it.attrs = is_top ? &win->body.attrs[tidx] : &accel.attrs[_stx];
1178         __vioWriteBuff(outx,line,&it,rw);
1179       }
1180     }
1181     if(is_hidden) __MsSetState(True);
1182     CHECK_WINS(win);
1183   }
1184 }
1185 
updatewinmem(TWindow * win)1186 static void __NEAR__ __FASTCALL__ updatewinmem(TWindow *win)
1187 {
1188   unsigned i,j,tidx;
1189   tvioBuff accel;
1190   t_vchar chars[__TVIO_MAXSCREENWIDTH];
1191   t_vchar oem_pg[__TVIO_MAXSCREENWIDTH];
1192   ColorAttr attrs[__TVIO_MAXSCREENWIDTH];
1193   tBool ms_vis, is_hidden = False, is_top;
1194   accel.chars = chars;
1195   accel.oem_pg = oem_pg;
1196   accel.attrs = attrs;
1197   if((win->iflags & IFLG_VISIBLE) == IFLG_VISIBLE)
1198   {
1199     tAbsCoord mx,my;
1200     ms_vis = __MsGetState();
1201     if(ms_vis)
1202     {
1203       __MsGetPos(&mx,&my);
1204       if(mx >= win->X1 && mx <= win->X2 && my >= win->Y1 && my <= win->Y2)
1205       {
1206         is_hidden = True;
1207         __MsSetState(False);
1208       }
1209     }
1210     is_top = __TOPMOST(win);
1211     if(is_top && win->wwidth == tvioWidth && !win->X1)
1212     {
1213       /* Special case of redrawing window interior at one call */
1214       __vioReadBuff(0, win->Y1, &win->saved, win->wwidth*win->wheight);
1215     }
1216     else
1217     {
1218       for(i = 0;i < win->wheight;i++)
1219       {
1220         tAbsCoord inx,iny;
1221         unsigned lwidth;
1222         lwidth = win->wwidth;
1223         inx = win->X1;
1224         iny = win->Y1+i;
1225         if(inx + lwidth > tvioWidth) lwidth = tvioWidth > inx ? tvioWidth - inx : 0;
1226         if(iny <= tvioHeight && lwidth)
1227         {
1228           if(is_top)
1229           {
1230             tidx = i*win->wwidth;
1231             accel.chars = &win->saved.chars[tidx];
1232             accel.attrs = &win->saved.attrs[tidx];
1233             accel.oem_pg = &win->saved.oem_pg[tidx];
1234           }
1235           __vioReadBuff(inx,iny,&accel,lwidth);
1236         }
1237         if(!is_top)
1238           for(j = 0;j < win->wwidth;j++)
1239              updatewinmemcharfromscreen(win,j,i,&accel);
1240       }
1241     }
1242     if(is_hidden) __MsSetState(True);
1243   }
1244 }
1245 
calc_title_off(tTitleMode mode,unsigned w,unsigned slen)1246 static tRelCoord __NEAR__ __FASTCALL__ calc_title_off(tTitleMode mode,unsigned w,unsigned slen)
1247 {
1248  tRelCoord stx;
1249    switch(mode)
1250    {
1251      case TW_TMODE_LEFT:
1252                       stx = 2;
1253                       break;
1254      case TW_TMODE_CENTER:
1255                       stx = ((w - slen)>>1) + 1;
1256                       break;
1257      default:
1258      case TW_TMODE_RIGHT:
1259                       stx = w - slen;
1260                       break;
1261    }
1262    return stx;
1263 }
1264 
1265 #define DO_OEM_PG(ch) ((active->flags & TWS_NLSOEM) == TWS_NLSOEM ? NLS_IS_OEMPG(ch) ? ch : 0 : 0)
1266 
__draw_frame(tRelCoord xs,tRelCoord ys,tRelCoord xe,tRelCoord ye,const void * _frame,DefColor color)1267 static void __NEAR__ __FASTCALL__ __draw_frame( tRelCoord xs, tRelCoord ys, tRelCoord xe, tRelCoord ye,
1268                                    const void *_frame, DefColor color)
1269 {
1270  unsigned i;
1271  ColorAttr cfr,csel;
1272  tRelCoord sx,sy;
1273  char frm[8],frame[8];
1274  char up,oem_ch;
1275  ColorAttr lt = 0,gr = 0,bl = 0;
1276  sx = active->cur_x;
1277  sy = active->cur_y;
1278  cfr = color.system;
1279  up = 0;
1280  memcpy(frame,_frame,8);
1281  if(memcmp(frame,TW_UP3D_FRAME,8) == 0 ||
1282     memcmp(frame,TW_DN3D_FRAME,8) == 0)
1283  {
1284    memcpy(frame,TW_SINGLE_FRAME,8);
1285    if(tvioNumColors >= 16 && BACK_COLOR(cfr) != Black)
1286    {
1287      Color cfbk;
1288      if(memcmp(_frame,TW_UP3D_FRAME,8) == 0) up = 1;
1289      else                                    up = 2;
1290      cfbk = BACK_COLOR(cfr);
1291      lt = LOGFB_TO_PHYS(cfbk < 8 ? cfbk + 8 : White,cfbk);
1292      gr = LOGFB_TO_PHYS(cfbk == LightGray ? Gray : LightGray,cfbk);
1293      bl = LOGFB_TO_PHYS(cfbk == LightGray ? Black : Gray,cfbk);
1294    }
1295  }
1296  memcpy(frm,frame,8);
1297  if((active->flags & TWS_NLSOEM) == TWS_NLSOEM)
1298    __nls_OemToOsdep((unsigned char *)frm,sizeof(frm));
1299  iGotoXY(xs,ys);
1300  csel = up ? up == 1 ? lt : bl : cfr;
1301  oem_ch = frame[0];
1302  wputc_oem(frm[0],DO_OEM_PG(oem_ch),csel,False);
1303  for(i = xs+1;i < xe; i++)
1304  {
1305    iGotoXY(i,ys);
1306    oem_ch = frame[1];
1307    wputc_oem(frm[1],DO_OEM_PG(oem_ch),csel,False);
1308  }
1309  iGotoXY(xe,ys);
1310  oem_ch = frame[2];
1311  wputc_oem(frm[2],DO_OEM_PG(oem_ch),up ? gr : cfr,False);
1312  for(i = ys+1;i < ye;i++)
1313  {
1314    iGotoXY(xs,i);
1315    oem_ch = frame[3];
1316    wputc_oem(frm[3],DO_OEM_PG(oem_ch),csel,True);
1317  }
1318  csel = up ? up == 1 ? bl : lt : cfr;
1319  for(i = ys+1;i < ye;i++)
1320  {
1321    iGotoXY(xe,i);
1322    oem_ch = frame[4];
1323    wputc_oem(frm[4],DO_OEM_PG(oem_ch),csel,True);
1324  }
1325  iGotoXY(xs,ye);
1326  oem_ch = frame[5];
1327  wputc_oem(frm[5],DO_OEM_PG(oem_ch),up ? gr : cfr,False);
1328  for(i = xs+1;i < xe; i++)
1329  {
1330    iGotoXY(i,ye);
1331    oem_ch = frame[6];
1332    wputc_oem(frm[6],DO_OEM_PG(oem_ch),csel,False);
1333  }
1334  iGotoXY(xe,ye);
1335  oem_ch = frame[7];
1336  wputc_oem(frm[7],DO_OEM_PG(oem_ch),csel,False);
1337  active->cur_x = sx;
1338  active->cur_y = sy;
1339 
1340 }
1341 
make_frame(void)1342 static void __NEAR__ __FASTCALL__ make_frame( void )
1343 {
1344  unsigned i,w,h;
1345  tRelCoord sx,sy;
1346  w = active->wwidth;
1347  h = active->wheight;
1348  sx = active->cur_x;
1349  sy = active->cur_y;
1350  __draw_frame(1,1,w,h,active->Frame,active->frame);
1351  if(active->Title)
1352  {
1353    unsigned slen;
1354    tRelCoord stx;
1355    slen = strlen(active->Title);
1356    if(slen > w) slen = w;
1357    stx = calc_title_off(active->TitleMode,w,slen);
1358    for(i = 0;i < slen;i++)
1359    {
1360       iGotoXY(stx+i,1);
1361       wputc(active->Title[i],active->title.system,False);
1362    }
1363  }
1364  if(active->Footer)
1365  {
1366    unsigned slen;
1367    tRelCoord stx;
1368    slen = strlen(active->Footer);
1369    if(slen > w) slen = w;
1370    stx = calc_title_off(active->FooterMode,w,slen);
1371    for(i = 0;i < slen;i++)
1372    {
1373       iGotoXY(stx+i,h);
1374       wputc(active->Footer[i],active->footer.system,False);
1375    }
1376  }
1377  updatescreenpiece(active,0,active->wwidth,1);
1378  updatescreenpiece(active,0,active->wwidth,h);
1379  active->cur_x = sx;
1380  active->cur_y = sy;
1381 }
1382 
paint_internal(void)1383 static void __NEAR__ __FASTCALL__ paint_internal( void )
1384 {
1385   if((active->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE) make_frame();
1386 }
1387 
twinDrawFrame(tRelCoord x1,tRelCoord y1,tRelCoord x2,tRelCoord y2,const char * frame,Color fore,Color back)1388 void __FASTCALL__ twinDrawFrame(tRelCoord x1, tRelCoord y1, tRelCoord x2, tRelCoord y2,const char *frame,Color fore, Color back)
1389 {
1390  DefColor dcol;
1391  tRelCoord sx,sy;
1392  sx = active->cur_x;
1393  sy = active->cur_y;
1394  if(memcmp(frame,TW_UP3D_FRAME,8) == 0 ||
1395     memcmp(frame,TW_DN3D_FRAME,8) == 0) __set_color(&dcol,fore,back);
1396  else dcol = active->text;
1397  if((active->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE)
1398  {
1399    x1++; y1++; x2++; y2++;
1400  }
1401  __draw_frame(x1,y1,x2,y2,frame,dcol);
1402  updatescreenpiece(active,x1-1,x2,y1);
1403  updatescreenpiece(active,x1-1,x2,y2);
1404  active->cur_x = sx;
1405  active->cur_y = sy;
1406 }
1407 
twinDrawFrameAttr(tRelCoord x1,tRelCoord y1,tRelCoord x2,tRelCoord y2,const char * frame,ColorAttr attr)1408 void __FASTCALL__ twinDrawFrameAttr(tRelCoord x1, tRelCoord y1, tRelCoord x2, tRelCoord y2,const char *frame,ColorAttr attr)
1409 {
1410   twinDrawFrame(x1,y1,x2,y2,frame,FORE_COLOR(attr),BACK_COLOR(attr));
1411 }
1412 
twCreateWin(tAbsCoord x1,tAbsCoord y1,tAbsCoord width,tAbsCoord height,unsigned flags)1413 TWindow * __FASTCALL__ twCreateWin(tAbsCoord x1, tAbsCoord y1, tAbsCoord width, tAbsCoord height, unsigned flags)
1414 {
1415   TWindow *win;
1416   if((flags & TWS_FRAMEABLE) == TWS_FRAMEABLE) { width ++; height ++; }
1417   if((win = makewin(x1-1,y1-1,width,height)) != NULL)
1418   {
1419     win->flags = flags;
1420     win->iflags = IFLG_ENABLED;
1421     memcpy(win->Frame,TW_SINGLE_FRAME,8);
1422     memset(win->body.chars,TWC_DEF_FILLER,win->wsize);
1423     memset(win->body.oem_pg,0,win->wsize);
1424     memset(win->body.attrs,win->text.system,win->wsize);
1425     CHECK_WINS(win);
1426     __set_color(&win->text,LightGray,Black);
1427     __set_color(&win->frame,LightGray,Black);
1428     __set_color(&win->title,LightGray,Black);
1429     __set_color(&win->footer,LightGray,Black);
1430     win->cur_x = win->cur_y = 0;
1431     twUseWin(win);
1432     paint_internal();
1433     if((flags & TWS_VISIBLE) == TWS_VISIBLE) twShowWin(win);
1434   }
1435   return win;
1436 }
1437 
twCreateWinEx(tAbsCoord x1_,tAbsCoord y1_,tAbsCoord width,tAbsCoord height,unsigned flags,TWindow * parent,const char * classname)1438 TWindow *  __FASTCALL__ twCreateWinEx(tAbsCoord x1_, tAbsCoord y1_,
1439                                       tAbsCoord width, tAbsCoord height,
1440                                       unsigned flags, TWindow *parent,
1441                                       const char *classname)
1442 {
1443   TWindow *ret;
1444   UNUSED(parent);
1445   if((ret = twCreateWin(x1_, y1_, width, height, flags)) != NULL)
1446   {
1447     TwClass *cls;
1448     cls = twcFindClass(classname);
1449     if(cls)
1450     {
1451       ret->method = cls->method;
1452       ret->class_flags = cls->flags;
1453     }
1454     twinSendMessage(ret,WM_CREATE,0L,NULL);
1455   }
1456   return ret;
1457 }
1458 
1459 
twShowWin(TWindow * w)1460 void __FASTCALL__ twShowWin(TWindow* w)
1461 {
1462   twinSendMessage(w,WM_SHOW,0L,NULL);
1463   if(!(w->iflags & IFLG_VISIBLE) == IFLG_VISIBLE)
1464   {
1465     w->iflags |= IFLG_VISIBLE;
1466     __unlistwin(w);
1467     __ATHEAD(w);
1468     updatewinmem(w);
1469     updatescreen(w,True);
1470     if((w->flags & TWS_CURSORABLE) == TWS_CURSORABLE)
1471     {
1472       cursorwin = w;
1473     }
1474     paint_cursor();
1475   }
1476 }
1477 
twShowWinOnTop(TWindow * w)1478 void __FASTCALL__ twShowWinOnTop(TWindow* w)
1479 {
1480   twinSendMessage(w,WM_TOPSHOW,0L,NULL);
1481   if((w->iflags & IFLG_VISIBLE) == IFLG_VISIBLE) twHideWin(w);
1482   w->iflags |= IFLG_VISIBLE;
1483   __unlistwin(w);
1484   __ATHEAD(w);
1485   screen2win(w);
1486   updatescreen(w,True);
1487   if((w->flags & TWS_CURSORABLE) == TWS_CURSORABLE)
1488   {
1489     cursorwin = w;
1490   }
1491   paint_cursor();
1492 }
1493 
twShowWinBeneath(TWindow * w,TWindow * prev)1494 void __FASTCALL__ twShowWinBeneath(TWindow* w,TWindow *prev)
1495 {
1496   twinSendMessage(w,WM_SHOWBENEATH,0L,prev);
1497   if((w->iflags & IFLG_VISIBLE) == IFLG_VISIBLE) twHideWin(w);
1498   w->iflags |= IFLG_VISIBLE;
1499   __unlistwin(w);
1500   __ATWIN(w,prev);
1501   updatewinmem(w);
1502   updatescreen(w,True);
1503 }
1504 
twHideWin(TWindow * w)1505 void __FASTCALL__ twHideWin(TWindow *w)
1506 {
1507   twinSendMessage(w,WM_HIDE,0L,NULL);
1508   if(cursorwin == w) twSetCursorType(TW_CUR_OFF);
1509   savedwin2screen(w);
1510   w->iflags &= ~IFLG_VISIBLE;
1511 }
1512 
twDestroyWin(TWindow * win)1513 void __FASTCALL__ twDestroyWin(TWindow *win)
1514 {
1515   twinSendMessage(win,WM_DESTROY,0L,NULL);
1516   twHideWin(win);
1517   if(win->Title) PFREE(win->Title);
1518   if(win->Footer) PFREE(win->Footer);
1519   PFREE(win->body.chars);
1520   PFREE(win->body.oem_pg);
1521   PFREE(win->body.attrs);
1522   PFREE(win->saved.chars);
1523   PFREE(win->saved.oem_pg);
1524   PFREE(win->saved.attrs);
1525   if(active == win)
1526   {
1527      if(win == head)   active = win->next;
1528      else              active = __prevwin(win);
1529   }
1530   __unlistwin(win);
1531   if(cursorwin == win) cursorwin = __findcursorablewin();
1532   paint_cursor();
1533   PFREE(win);
1534 }
1535 
twGetWinPos(TWindow * win,tAbsCoord * x1,tAbsCoord * y1,tAbsCoord * x2,tAbsCoord * y2)1536 void __FASTCALL__ twGetWinPos(TWindow *win,tAbsCoord *x1,tAbsCoord *y1,tAbsCoord *x2,tAbsCoord *y2)
1537 {
1538   *x1 = win->X1+1;
1539   *y1 = win->Y1+1;
1540   *x2 = win->X2;
1541   *y2 = win->Y2;
1542   if((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE)
1543   {
1544    (*x2)--;
1545    (*y2)--;
1546   }
1547 }
1548 
twGetWinWidth(TWindow * win)1549 unsigned          __FASTCALL__ twGetWinWidth(TWindow *win)
1550 {
1551   return win->wwidth;
1552 }
1553 
twGetWinHeight(TWindow * win)1554 unsigned          __FASTCALL__ twGetWinHeight(TWindow *win)
1555 {
1556   return win->wheight;
1557 }
1558 
twGetClientWidth(TWindow * win)1559 unsigned          __FASTCALL__ twGetClientWidth(TWindow *win)
1560 {
1561   return win->flags & TWS_FRAMEABLE ? win->wwidth-2 : win->wwidth;
1562 }
1563 
twGetClientHeight(TWindow * win)1564 unsigned          __FASTCALL__ twGetClientHeight(TWindow *win)
1565 {
1566   return win->flags & TWS_FRAMEABLE ? win->wheight-2 : win->wheight;
1567 }
1568 
twMoveWin(TWindow * win,tAbsCoord dx,tAbsCoord dy)1569 void __FASTCALL__ twMoveWin(TWindow *win,tAbsCoord dx,tAbsCoord dy)
1570 {
1571   TWindow *prev;
1572   tRelCoord x,y;
1573   int vis;
1574   vis = (win->iflags & IFLG_VISIBLE) == IFLG_VISIBLE;
1575   x = twWhereX();
1576   y = twWhereY();
1577   prev = __prevwin(win);
1578   if(vis) twHideWin(win);
1579   win->X1 += dx;
1580   win->Y1 += dy;
1581   win->X2 += dx;
1582   win->Y2 += dy;
1583   if(vis) twShowWinBeneath(win,prev);
1584   twGotoXY(x,y);
1585 }
1586 
twResizeWin(TWindow * win,tAbsCoord width,tAbsCoord height)1587 void __FASTCALL__ twResizeWin(TWindow *win,tAbsCoord width,tAbsCoord height)
1588 {
1589   TWindow * tmp,*prev;
1590   tvioBuff newbody;
1591   size_t ncopy,delta,fillsize;
1592   size_t from,to,size,i,loop,start,idx;
1593   tAbsCoord oldw,oldh;
1594   tRelCoord x,y;
1595   tBool vis;
1596   x = twWhereX();
1597   y = twWhereY();
1598   vis = (win->iflags & IFLG_VISIBLE) == IFLG_VISIBLE;
1599   prev = __prevwin(win);
1600   if(vis) twHideWin(win);
1601   size = width*height;
1602   if(!(newbody.chars = PMalloc(size*sizeof(t_vchar)
1603 #ifndef NDEBUG
1604                                +sizeof(void *)
1605 #endif
1606     )))
1607   {
1608     bye0:
1609     winerr("Out of memory!");
1610   }
1611   if(!(newbody.oem_pg = PMalloc(size*sizeof(t_vchar)
1612 #ifndef NDEBUG
1613                                +sizeof(void *)
1614 #endif
1615     )))
1616   {
1617    bye1:
1618     PFREE(newbody.chars);
1619     goto bye0;
1620   }
1621   if(!(newbody.attrs = PMalloc(size*sizeof(ColorAttr)
1622 #ifndef NDEBUG
1623                                +sizeof(void *)
1624 #endif
1625     )))
1626   {
1627     PFREE(newbody.oem_pg);
1628     goto bye1;
1629   }
1630 #ifndef NDEBUG
1631   *((void **)(newbody.chars + size)) = newbody.chars;
1632   *((void **)(newbody.oem_pg + size)) = newbody.oem_pg;
1633   *((void **)(newbody.attrs + size)) = newbody.attrs;
1634 #endif
1635   oldw = win->wwidth;
1636   oldh = win->wheight;
1637   /* --- Compute copy parameters --- */
1638   to = (win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE ? 1 : 0;
1639   from = (win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE ? 1 : 0;
1640   delta = 0;
1641   if((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE) delta = 2;
1642   start = (win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE ? 1 : 0;
1643   loop = min(oldh,height);
1644   ncopy = min(width,oldw);
1645   fillsize = width-oldw;
1646   for(i = start;i < loop;i++)
1647   {
1648       memcpy(&newbody.chars[to],&win->body.chars[from],ncopy);
1649       memcpy(&newbody.oem_pg[to],&win->body.oem_pg[from],ncopy);
1650       memcpy(&newbody.attrs[to],&win->body.attrs[from],ncopy);
1651       if(oldw < width)
1652       {
1653         idx = to+ncopy-delta;
1654         memset(&newbody.chars[idx],TWC_DEF_FILLER,fillsize);
1655         memset(&newbody.oem_pg[idx],0,fillsize);
1656         memset(&newbody.attrs[idx],win->text.system,fillsize);
1657       }
1658       CHECK_WINS(win);
1659       to += width;
1660       from += oldw;
1661   }
1662   if(oldh < height)
1663   {
1664     for(;i < height;i++)
1665     {
1666        memset(&newbody.chars[to],TWC_DEF_FILLER,width);
1667        memset(&newbody.oem_pg[to],0,width);
1668        memset(&newbody.attrs[to],win->text.system,width);
1669        to += width;
1670     }
1671   }
1672   PFREE(win->saved.chars);
1673   PFREE(win->saved.oem_pg);
1674   PFREE(win->saved.attrs);
1675   win->wsize = size;
1676   win->wwidth = width;
1677   win->wheight = height;
1678   if(!(win->saved.chars = PMalloc(win->wsize*sizeof(t_vchar)
1679 #ifndef NDEBUG
1680                                +sizeof(void *)
1681 #endif
1682     )))  goto bye0;
1683   if(!(win->saved.oem_pg = PMalloc(win->wsize*sizeof(t_vchar)
1684 #ifndef NDEBUG
1685                                +sizeof(void *)
1686 #endif
1687     )))
1688   {
1689    bye2:
1690     PFREE(win->saved.chars);
1691     goto bye0;
1692   }
1693   if(!(win->saved.attrs = PMalloc(win->wsize*sizeof(ColorAttr)
1694 #ifndef NDEBUG
1695                                +sizeof(void *)
1696 #endif
1697     )))
1698   {
1699     PFREE(win->saved.oem_pg);
1700     goto bye2;
1701   }
1702   PFREE(win->body.chars);
1703   PFREE(win->body.oem_pg);
1704   PFREE(win->body.attrs);
1705 #ifndef NDEBUG
1706   *((void **)(win->saved.chars + win->wsize)) = win->saved.chars;
1707   *((void **)(win->saved.oem_pg + win->wsize)) = win->saved.oem_pg;
1708   *((void **)(win->saved.attrs + win->wsize)) = win->saved.attrs;
1709 #endif
1710   win->body = newbody;
1711   win->X2 = win->X1 + width;
1712   win->Y2 = win->Y1 + height;
1713   CHECK_WINS(win);
1714   tmp = active;
1715   active = win;
1716   paint_internal();
1717   active = tmp;
1718   if(vis) twShowWinBeneath(win,prev);
1719   twGotoXY(x,y);
1720 }
1721 
twCentredWin(TWindow * win,const TWindow * parent)1722 void __FASTCALL__ twCentredWin(TWindow * win,const TWindow *parent)
1723 {
1724   tAbsCoord ww,wh,pww,pwh;
1725   int vis = (win->iflags & IFLG_VISIBLE) == IFLG_VISIBLE;
1726   if(vis) twHideWin(win);
1727   ww = win->wwidth;
1728   wh = win->wheight;
1729   if(!parent)
1730   {
1731     pww = tvioWidth;
1732     pwh = tvioHeight;
1733   }
1734   else
1735   {
1736     pww = parent->wwidth;
1737     pwh = parent->wheight;
1738   }
1739   win->X1 = ( pww - ww )>>1;
1740   win->X2 = ( pww + ww )>>1;
1741   win->Y1 = ( pwh - wh )>>1;
1742   win->Y2 = ( pwh + wh )>>1;
1743   if(vis) twShowWin(win);
1744 }
1745 
twClearWinEx(unsigned char filler)1746 void __FASTCALL__ twClearWinEx( unsigned char filler )
1747 {
1748   size_t to,size,i,loop,start,delta,idx,fillsize;
1749   tRelCoord cx,cy;
1750   char oempg = 0;
1751   cx = active->cur_x;
1752   cy = active->cur_y;
1753   to = (active->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE ? 1 : 0;
1754   size = active->wwidth;
1755   delta = 0;
1756   if((active->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE) delta = 2;
1757   start = (active->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE ? 1 : 0;
1758   loop = active->wheight;
1759   if((active->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE) loop--;
1760   fillsize = size-delta;
1761   if((active->flags & TWS_NLSOEM) == TWS_NLSOEM)
1762   {
1763     oempg = filler;
1764     __nls_OemToOsdep(&filler,1);
1765   }
1766   for(i = start;i < loop;i++)
1767   {
1768       idx = to+i*size;
1769       memset(&active->body.chars[idx],filler,fillsize);
1770       memset(&active->body.oem_pg[idx],((active->flags & TWS_NLSOEM) == TWS_NLSOEM ? NLS_IS_OEMPG(oempg) ? oempg : 0 : 0),fillsize);
1771       memset(&active->body.attrs[idx],active->text.system,fillsize);
1772       CHECK_WINS(active);
1773       updatescreenpiece(active,0,active->wwidth,i+1);
1774   }
1775   active->cur_x = cx;
1776   active->cur_y = cy;
1777 }
1778 
twClearWin(void)1779 void __FASTCALL__ twClearWin( void )
1780 {
1781   twClearWinEx(TWC_DEF_FILLER);
1782 }
1783 
twClrEOLEx(unsigned char filler)1784 void __FASTCALL__ twClrEOLEx(unsigned char filler )
1785 {
1786   size_t size,idx;
1787   char oempg = 0;
1788   size = active->wwidth - active->cur_x;
1789   if((active->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE) size--;
1790   idx = active->cur_x + active->cur_y*active->wwidth;
1791   if((active->flags & TWS_NLSOEM) == TWS_NLSOEM)
1792   {
1793     oempg = filler;
1794     __nls_OemToOsdep(&filler,1);
1795   }
1796   memset(&active->body.chars[idx],filler,size);
1797   memset(&active->body.oem_pg[idx],((active->flags & TWS_NLSOEM) == TWS_NLSOEM ? NLS_IS_OEMPG(oempg) ? oempg : 0 : 0),size);
1798   memset(&active->body.attrs[idx],active->text.system,size);
1799   CHECK_WINS(active);
1800   updatescreenpiece(active,active->cur_x,active->wwidth,active->cur_y+1);
1801 }
1802 
twClrEOL(void)1803 void __FASTCALL__ twClrEOL( void )
1804 {
1805   twClrEOLEx(TWC_DEF_FILLER);
1806 }
1807 
twUseWin(TWindow * win)1808 TWindow * __FASTCALL__ twUseWin( TWindow * win)
1809 {
1810   TWindow *ret;
1811   ret = active;
1812   active = win;
1813   if((active->flags & TWS_CURSORABLE) == TWS_CURSORABLE)
1814   {
1815      cursorwin = win;
1816   }
1817   paint_cursor();
1818   return ret;
1819 }
1820 
twUsedWin(void)1821 TWindow * __FASTCALL__ twUsedWin( void )
1822 {
1823   return active;
1824 }
1825 
twWhereX(void)1826 tRelCoord __FASTCALL__ twWhereX( void )
1827 {
1828   return (active->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE ? active->cur_x : active->cur_x+1;
1829 }
1830 
twWhereY(void)1831 tRelCoord __FASTCALL__ twWhereY( void )
1832 {
1833   return (active->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE ? active->cur_y : active->cur_y+1;
1834 }
1835 
wputc_oem(char ch,char oempg,char color,tBool update)1836 static void __NEAR__ __FASTCALL__ wputc_oem(char ch,char oempg,char color,tBool update)
1837 {
1838   unsigned idx;
1839   idx = active->cur_x + active->cur_y*active->wwidth;
1840   active->body.chars[idx] = ch;
1841   active->body.oem_pg[idx] = oempg;
1842   active->body.attrs[idx] = color;
1843   CHECK_WINS(active);
1844   if(update) updatescreenchar(active,active->cur_x+1,active->cur_y+1,NULL);
1845 }
1846 
twPutChar(char ch)1847 void __FASTCALL__ twPutChar(char ch)
1848 {
1849   tRelCoord cx,cy;
1850   char as_oem = 0;
1851   cx = active->cur_x;
1852   cy = active->cur_y;
1853   if(IS_VALID_XY(active,cx,cy))
1854   {
1855     if((active->flags & TWS_NLSOEM) == TWS_NLSOEM)
1856     {
1857        as_oem = ch;
1858        __nls_OemToOsdep((unsigned char *)&ch,1);
1859        if(!NLS_IS_OEMPG(as_oem)) as_oem = 0;
1860        wputc_oem(ch,as_oem,active->text.system,True);
1861     }
1862     else wputc(ch,active->text.system,True);
1863     active->cur_x++;
1864   }
1865 }
1866 
twGetChar(void)1867 char __FASTCALL__ twGetChar( void )
1868 {
1869   unsigned idx;
1870   tRelCoord cx,cy;
1871   cx = active->X1 + active->cur_x;
1872   cy = active->Y1 + active->cur_y;
1873   idx = cx + cy*active->wwidth;
1874   return active->body.chars[idx];
1875 }
1876 
twPutS(const char * str)1877 int __FASTCALL__ twPutS(const char *str)
1878 {
1879   char *__nls = NULL,* __nls_ptr;
1880   const char *__oem_ptr;
1881   int freq = 0;
1882   unsigned vidx;
1883   tAbsCoord usx;
1884   tRelCoord cx,cy;
1885   char ch,as_oem;
1886   if((active->flags & TWS_NLSOEM) == TWS_NLSOEM)
1887   {
1888      unsigned len;
1889      len = strlen(str);
1890      __nls = PMalloc(len+1);
1891      if(__nls)
1892      {
1893        strcpy(__nls,str);
1894        __nls_OemToOsdep((unsigned char *)__nls,len);
1895      }
1896      else __nls = str;
1897   }
1898   else __nls = str;
1899   __nls_ptr = __nls;
1900   __oem_ptr = str;
1901   vidx = active->cur_x + active->cur_y*active->wwidth;
1902   usx = active->cur_x;
1903   while((ch=*__nls++)!=0)
1904   {
1905     as_oem=*__oem_ptr++;
1906     if(ch == '\n')
1907     {
1908         updatescreenpiece(active,usx,active->cur_x,active->cur_y+1);
1909         set_xy(1,active->cur_y+1);
1910         usx = active->cur_x;
1911         vidx = active->cur_x + active->cur_y*active->wwidth;
1912         continue;
1913     }
1914     if(ch == '\r')
1915     {
1916         set_xy(1,active->cur_y);
1917         usx = active->cur_x;
1918         vidx = active->cur_x + active->cur_y*active->wwidth;
1919         continue;
1920     }
1921     cx = active->cur_x;
1922     cy = active->cur_y;
1923     if(IS_VALID_XY(active,cx,cy))
1924     {
1925         active->body.chars[vidx] = ch;
1926         if((active->flags & TWS_NLSOEM) == TWS_NLSOEM && NLS_IS_OEMPG(as_oem))
1927              active->body.oem_pg[vidx] = as_oem;
1928 	else active->body.oem_pg[vidx] = 0;
1929         active->body.attrs[vidx++] = active->text.system;
1930         active->cur_x++;
1931         freq++;
1932     }
1933   }
1934   updatescreenpiece(active,usx,active->cur_x,active->cur_y+1);
1935   paint_cursor();
1936   if(__nls_ptr != str) PFREE(__nls_ptr);
1937   return freq;
1938 }
1939 
twPrintF(const char * fmt,...)1940 int __FASTCALL__ twPrintF(const char *fmt,...)
1941 {
1942   char *buff;
1943   int ret;
1944   va_list args;
1945   buff = PMalloc(tvioWidth*tvioHeight); /* Danger - format can be great that
1946                                          allocated buffer, but it meaningless */
1947   ret = 0;
1948   if(buff)
1949   {
1950     va_start(args,fmt);
1951     vsprintf(buff,fmt,args);
1952     va_end(args);
1953     ret = twPutS(buff);
1954     PFREE(buff);
1955   }
1956   return ret;
1957 }
1958 
twDirectWrite(tRelCoord x,tRelCoord y,const void * str,unsigned len)1959 int __FASTCALL__ twDirectWrite(tRelCoord x, tRelCoord y,const void *str,unsigned len)
1960 {
1961   unsigned i,rlen,ioff;
1962   const char *__nls = NULL,*__oem = NULL;
1963   char nlsBuff[__TVIO_MAXSCREENWIDTH];
1964   char oemBuff[__TVIO_MAXSCREENWIDTH];
1965   if(!((active->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE))
1966   {
1967     x--;  y--;
1968   }
1969   if(!IS_VALID_XY(active,x,y)) return 0;
1970   rlen = active->wwidth;
1971   if((active->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE) rlen-=1;
1972   rlen -= x;
1973   rlen = min(rlen,len);
1974   if((active->flags & TWS_NLSOEM) == TWS_NLSOEM)
1975   {
1976      memcpy(nlsBuff,str,rlen);
1977      memcpy(oemBuff,str,rlen);
1978      for(i = 0;i < rlen;i++) if(!NLS_IS_OEMPG(oemBuff[i])) oemBuff[i] = 0;
1979      __nls_OemToOsdep((unsigned char *)nlsBuff,rlen);
1980      __nls = nlsBuff;
1981      __oem = oemBuff;
1982   }
1983   else __nls = str;
1984   ioff = x+y*active->wwidth;
1985   memcpy(&active->body.chars[ioff],__nls,rlen);
1986   if(__oem) memcpy(&active->body.oem_pg[ioff],__oem,rlen);
1987   else      memset(&active->body.oem_pg[ioff],0,rlen);
1988   memset(&active->body.attrs[ioff],active->text.system,rlen);
1989   CHECK_WINS(active);
1990   updatescreenpiece(active,x,x+rlen,y+1);
1991   return rlen;
1992 }
1993 
twWriteBuffer(TWindow * win,tRelCoord x,tRelCoord y,const tvioBuff * buff,unsigned len)1994 void __FASTCALL__ twWriteBuffer(TWindow *win,tRelCoord x,tRelCoord y,const tvioBuff *buff,unsigned len)
1995 {
1996   const void *pbuff;
1997   unsigned rlen,i,loop_len;
1998   char nbuff[__TVIO_MAXSCREENWIDTH];
1999   rlen = (unsigned)x+len > win->wwidth ? win->wwidth-(unsigned)x+1 : len;
2000   if((unsigned)y <= win->wheight)
2001   {
2002     pbuff = buff->attrs;
2003     if((twin_flags & TWIF_FORCEMONO) && tvioNumColors >= 16)
2004     {
2005       memcpy(nbuff,buff->attrs,rlen);
2006       loop_len = rlen;
2007       for(i = 1;i < loop_len;i++)
2008       {
2009         Color fore,back;
2010         fore = FORE_COLOR(nbuff[i]);
2011         back = BACK_COLOR(nbuff[i]);
2012         adjustColor(&fore,&back);
2013         nbuff[i] = LOGFB_TO_PHYS(fore,back);
2014       }
2015       pbuff = nbuff;
2016     }
2017     i = (x-1)+(y-1)*win->wwidth;
2018     memcpy(&win->body.chars[i],buff->chars,rlen);
2019     memcpy(&win->body.oem_pg[i],buff->oem_pg,rlen);
2020     memcpy(&win->body.attrs[i],pbuff,rlen);
2021     CHECK_WINS(win);
2022     updatescreenpiece(win,x-1,x-1+rlen,y);
2023     paint_cursor();
2024   }
2025 }
2026 
twReadBuffer(TWindow * win,tRelCoord x,tRelCoord y,tvioBuff * buff,unsigned len)2027 void __FASTCALL__ twReadBuffer(TWindow *win,tRelCoord x,tRelCoord y,tvioBuff *buff,unsigned len)
2028 {
2029   unsigned rlen,idx;
2030   rlen = (unsigned)x+len > win->wwidth ? win->wwidth-(unsigned)x+1 : len;
2031   if((unsigned)y <= win->wheight)
2032   {
2033     idx = (x-1)+(y-1)*win->wwidth;
2034     memcpy(buff->chars,&win->body.chars[idx],rlen);
2035     memcpy(buff->oem_pg,&win->body.oem_pg[idx],rlen);
2036     memcpy(buff->attrs,&win->body.attrs[idx],rlen);
2037     CHECK_WINS(win);
2038     paint_cursor();
2039   }
2040 }
2041 
twFreezeWin(TWindow * win)2042 void __FASTCALL__ twFreezeWin(TWindow *win)
2043 {
2044   win->iflags &= ~IFLG_ENABLED;
2045 }
2046 
twRefreshLine(TWindow * win,tRelCoord y)2047 void __FASTCALL__ twRefreshLine(TWindow *win,tRelCoord y)
2048 {
2049   win->iflags |= IFLG_ENABLED;
2050   if((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE) y++;
2051   updatescreenpiece(win,0,win->wwidth,y);
2052   paint_cursor();
2053 }
2054 
twRefreshPiece(TWindow * win,tRelCoord stx,tRelCoord endx,tRelCoord y)2055 void __FASTCALL__ twRefreshPiece(TWindow *win,tRelCoord stx,tRelCoord endx,tRelCoord y)
2056 {
2057   win->iflags |= IFLG_ENABLED;
2058   if((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE) { stx++; endx++; y++; }
2059   updatescreenpiece(win,stx-1,endx-1,y);
2060   paint_cursor();
2061 }
2062 
twRefreshWin(TWindow * win)2063 void __FASTCALL__ twRefreshWin(TWindow *win)
2064 {
2065   win->iflags |= IFLG_ENABLED;
2066   updatescreen(win,(win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE ? False : True);
2067   paint_cursor();
2068 }
2069 
twRefreshFullWin(TWindow * win)2070 void __FASTCALL__ twRefreshFullWin(TWindow *win)
2071 {
2072   win->iflags |= IFLG_ENABLED;
2073   updatescreen(win,True);
2074   paint_cursor();
2075 }
2076 
twGetUsrData(TWindow * win)2077 void * __FASTCALL__ twGetUsrData(TWindow *win) { return win->usrData; }
2078 
twSetUsrData(TWindow * win,void * data)2079 void * __FASTCALL__ twSetUsrData(TWindow *win,void *data)
2080 {
2081   void *ret;
2082   ret = win->usrData;
2083   win->usrData = data;
2084   return ret;
2085 }
2086 
twRemapColor(Color color,unsigned char value)2087 void __FASTCALL__ twRemapColor(Color color,unsigned char value)
2088 {
2089   color_map[color & 0x0F] = value & 0x0F;
2090 }
2091 
twGetMappedColor(Color color)2092 unsigned char __FASTCALL__ twGetMappedColor(Color color)
2093 {
2094   return color_map[color & 0x0F];
2095 }
2096 
twScrollWinUp(TWindow * win,tRelCoord ypos,unsigned npos)2097 void __FASTCALL__ twScrollWinUp(TWindow *win,tRelCoord ypos, unsigned npos)
2098 {
2099   size_t i;
2100   tRelCoord wwidth;
2101   tvioBuff accel;
2102   t_vchar chars[__TVIO_MAXSCREENWIDTH];
2103   t_vchar oem_pg[__TVIO_MAXSCREENWIDTH];
2104   ColorAttr attrs[__TVIO_MAXSCREENWIDTH];
2105   if(!npos || !IS_VALID_Y(win,ypos)) return;
2106   accel.chars = chars;
2107   accel.oem_pg = oem_pg;
2108   accel.attrs = attrs;
2109   wwidth = win->wwidth;
2110   if((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE) wwidth-=2;
2111   for(i = npos-1;i < ypos;i++)
2112   {
2113     twReadBuffer(win,1,i+2,&accel,wwidth);
2114     twWriteBuffer(win,1,i+1,&accel,wwidth);
2115   }
2116 }
2117 
twScrollWinDn(TWindow * win,tRelCoord ypos,unsigned npos)2118 void __FASTCALL__ twScrollWinDn(TWindow *win,tRelCoord ypos, unsigned npos)
2119 {
2120   size_t i,lim;
2121   tRelCoord wwidth,wheight;
2122   tvioBuff accel;
2123   t_vchar chars[__TVIO_MAXSCREENWIDTH];
2124   t_vchar oem_pg[__TVIO_MAXSCREENWIDTH];
2125   ColorAttr attrs[__TVIO_MAXSCREENWIDTH];
2126   if(!npos || !IS_VALID_Y(win,ypos)) return;
2127   accel.chars = chars;
2128   accel.oem_pg = oem_pg;
2129   accel.attrs = attrs;
2130   lim = ypos > npos ? ypos - npos + 1 : 1;
2131   wwidth = win->wwidth;
2132   wheight = win->wheight;
2133   if((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE)
2134   {
2135     wwidth-=2;
2136     wheight-=2;
2137   }
2138   for(i = wheight;i > lim;i--)
2139   {
2140     twReadBuffer(win,1,i-npos,&accel,wwidth);
2141     twWriteBuffer(win,1,i,&accel,wwidth);
2142   }
2143 }
2144 
twScrollWinLf(TWindow * win,tRelCoord xpos,unsigned npos)2145 void __FASTCALL__ twScrollWinLf(TWindow *win,tRelCoord xpos, unsigned npos)
2146 {
2147  /** @todo Not tested!!! */
2148   size_t i,j,lim;
2149   tRelCoord wheight;
2150   tvioBuff accel;
2151   t_vchar chars[__TVIO_MAXSCREENWIDTH];
2152   t_vchar oem_pg[__TVIO_MAXSCREENWIDTH];
2153   ColorAttr attrs[__TVIO_MAXSCREENWIDTH];
2154   if(!npos || !IS_VALID_X(win,xpos)) return;
2155   accel.chars = chars;
2156   accel.oem_pg = oem_pg;
2157   accel.attrs = attrs;
2158   lim = xpos > npos ? xpos - npos : 0;
2159   wheight = win->wheight;
2160   if((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE)
2161   {
2162     wheight-=2;
2163   }
2164   for(i = lim;i < xpos;i++)
2165   {
2166     /** @todo Optimize this block */
2167     for(j = 0;j < wheight;j++)
2168     {
2169       twReadBuffer(win,i+2,j,&accel,1);
2170       twWriteBuffer(win,i+1,j,&accel,1);
2171     }
2172   }
2173 }
2174 
twScrollWinRt(TWindow * win,tRelCoord xpos,unsigned npos)2175 void __FASTCALL__ twScrollWinRt(TWindow *win,tRelCoord xpos, unsigned npos)
2176 {
2177  /** @todo Not tested!!! */
2178   size_t i,j,lim;
2179   tRelCoord wwidth,wheight;
2180   tvioBuff accel;
2181   t_vchar chars[__TVIO_MAXSCREENWIDTH];
2182   t_vchar oem_pg[__TVIO_MAXSCREENWIDTH];
2183   ColorAttr attrs[__TVIO_MAXSCREENWIDTH];
2184   if(!npos || !IS_VALID_X(win,xpos)) return;
2185   accel.chars = chars;
2186   accel.oem_pg = oem_pg;
2187   accel.attrs = attrs;
2188   lim = xpos > npos ? xpos - npos + 1 : 1;
2189   wwidth = win->wwidth;
2190   wheight = win->wheight;
2191   if((win->flags & TWS_FRAMEABLE) == TWS_FRAMEABLE)
2192   {
2193     wwidth-=2;
2194     wheight-=2;
2195   }
2196   for(i = wwidth;i > lim;i--)
2197   {
2198     /** @todo Optimize this block */
2199     for(j = 0;j < wheight;j++)
2200     {
2201       twReadBuffer(win,i-npos,j,&accel,1);
2202       twWriteBuffer(win,i,j,&accel,1);
2203     }
2204   }
2205 }
2206 
twinSendMessage(TWindow * win,unsigned event,unsigned long event_param,void * event_data)2207 long __FASTCALL__ twinSendMessage(TWindow *win,unsigned event,unsigned long event_param, void *event_data)
2208 {
2209     if(win->method) return ((twClassFunc)(win->method))(win,event,event_param,event_data);
2210     return 0L;
2211 }
2212