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