root/trunk/txlib/txwiop.c

Revision 7, 76.2 kB (checked in by jvw, 3 years ago)

Made O_BINARY default for Linux files (CR/LF in logfiles)
Fixed Radio-repaint bug caused by a (x == TRUE) compare

Line 
1//
2//                     TxWin, Textmode Windowing Library
3//
4//   Original code Copyright (c) 1995-2005 Fsys Software and Jan van Wijk
5//
6// ==========================================================================
7//
8// This file contains Original Code and/or Modifications of Original Code as
9// defined in and that are subject to the GNU Lesser General Public License.
10// You may not use this file except in compliance with the License.
11// BY USING THIS FILE YOU AGREE TO ALL TERMS AND CONDITIONS OF THE LICENSE.
12// A copy of the License is provided with the Original Code and Modifications,
13// and is also available at http://www.dfsee.com/txwin/lgpl.htm
14//
15// This library is free software; you can redistribute it and/or modify
16// it under the terms of the GNU Lesser General Public License as published
17// by the Free Software Foundation; either version 2.1 of the License,
18// or (at your option) any later version.
19//
20// This library is distributed in the hope that it will be useful,
21// but WITHOUT ANY WARRANTY; without even the implied warranty of
22// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23// See the GNU Lesser General Public License for more details.
24//
25// You should have received a copy of the GNU Lesser General Public License
26// along with this library; (lgpl.htm) if not, write to the Free Software
27// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28//
29// Questions on TxWin licensing can be directed to: txwin@fsys.nl
30//
31// ==========================================================================
32//
33// TX Basic text I/O primitives
34//
35// Author: J. van Wijk
36//
37// JvW  25-05-1999 Initial version, split off from ANSILOG.C
38// JvW  22-08-2001 Added ReadCellStr & fixed WriteCellStr bug (garbage char)
39// JvW  08-09-2001 Combined all functions from txw32con and txw32ans
40// JvW  28-05-2002 Added DOS32 support (DOS4G/W or causeway or compatibles)
41// JvW  07-06-2002 Speedup using selective direct video-memory access
42// JvW  10-03-2004 Added Linux code and initializaton/termination API
43
44#include <txlib.h>
45#include <txwpriv.h>                            // private window interface
46
47#if defined (WIN32)
48
49#define TX32CON_MAXERR  16
50
51typedef enum tx_color_value
52{
53   Black,     Blue,          Green,       Cyan,
54   Red,       Magenta,       Brown,       Light_Gray,
55   Dark_Gray, Light_Blue,    Light_Green, Light_Cyan,
56   Light_Red, Light_Magenta, Yellow,      White
57} TX_COLOR_VALUE;
58
59static HANDLE virtualScrBuf = NULL;
60
61static void TxWntSetFgCol
62(
63   TX_COLOR_VALUE      color                    // IN    color value
64);
65
66static void TxWntSetBgCol
67(
68   TX_COLOR_VALUE      color                    // IN    color value
69);
70
71// set background and foreground color for NT console
72static void txNtSet_color
73(
74   WORD                color                    // IN    combined color value
75);
76
77
78// get the size of display area, horizontal
79static int  TxWntSx
80(
81   void
82);
83
84// get the size of display area, vertical
85static int  TxWntSy
86(
87   void
88);
89
90// get the position of the cursor, horizontal
91static int  TxWntCx
92(
93   void
94);
95
96// get the position of the cursor, vertical
97static int  TxWntCy
98(
99   void
100);
101
102// set the position of the cursor
103static void TxWntGo
104(
105   int                 x,                       // IN    horizontal position
106   int                 y                        // IN    horizontal position
107);
108
109// clear the screen
110static void TxWntClearScreen
111(
112   void
113);
114
115// clear to end of line
116static void TxWntClrToEndOfLine
117(
118   void
119);
120
121// write a single character to the console
122static void TxWntWriteChar
123(
124   char                ch                       // IN    character to write
125);
126
127//- write string to console, limit to length (clipping)
128static void TxWntWriteString
129(
130   char               *str,                     // IN    string pointer
131   short               length                   // IN    length to write
132);
133
134// get the current status of the output buffer
135static int TxWntGetScrInfo
136(
137   HANDLE                      buffer,
138   PCONSOLE_SCREEN_BUFFER_INFO info
139);
140
141#elif defined (LINUX)                           // Linux console/xterm
142#include <sys/ioctl.h>
143#include <sys/time.h>
144
145typedef struct tx_screen
146{
147   short               cols;                    // screen width in characters
148   short               rows;                    // screen length in lines
149   TXCELL             *buffer;                  // screen buffer
150} TX_SCREEN;
151
152
153//- WARNING: Edit the two tables below in codepage-437 for readability!
154//- character translation table, for alternate-set and controlchar replacement
155//- Codepage-437 capable version (drawing characters) like Linux console
156static char chTransConsole[256] =
157{
158    //-   1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
159    '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', // 00
160    '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', // 10
161      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 20
162      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 30
163      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 40
164      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 50
165      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 60
166      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, '^', // 70
167    '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', // 80
168    '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', // 90
169      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, '®', '¯', // A0
170    '°', '±', '²', '³', 'Ž', '¹', '¹', '»', '»', '¹', 'º', '»', 'Œ', 'Œ', 'Œ', '¿', // B0
171    'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Ì', 'Ì', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Á', // C0
172    'Ê', 'Ë', 'Ë', 'È', 'È', 'É', 'É', 'Î', 'Î', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß', // D0
173      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // E0
174      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 'x',   0,   0,   0, // F0
175};
176
177#if defined (USEWINDOWING)
178//- character translation table, for alternate-set and controlchar replacement
179//- Generic terminal version (no drawing characters) like X-terminal or VT220
180static char chTransGeneric[256] =
181{
182    //-   1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
183    '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', // 00
184    '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', // 10
185      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 20
186      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 30
187      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 40
188      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 50
189      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 60
190      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, '^', // 70
191    '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', // 80
192    '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', // 90
193      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 171, 187, // A0
194     97,  97,  97, 120, 117, 117, 117, 107, 107, 117, 166, 107, 106, 106, 106, 107, // B0
195    109, 118, 119, 116, 113, 110, 116, 116, 109, 108, 118, 119, 116, '=', 110, 118, // C0
196    118, 119, 119, 109, 109, 108, 108, 110, 110, 106, 108,  97, 113, 120, 120, 113, // D0
197      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // E0
198      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 'x',   0,   0,   0, // F0
199};
200
201//- terminal dependent definitions and escape-sequences
202//- Note: All terminals are supposed to understand the ANSI sequenses for colors
203
204static TXTT      txlTermCap_eA  = "";           // Terminal initialize ??
205
206static short     virtualCurCol;                   // cursor pos on virtual screen
207static short     virtualCurRow;
208static BOOL      cursorVisible  = FALSE;          // cursor should be visible
209static BOOL      cursorInsert   = FALSE;          // cursor shape insert mode
210
211#endif                                          // USEWINDOWING
212
213static TXLTERM   txlTerminal    = TXLT_CONSOLE;   // default linux console
214static char     *txlTransTable  = chTransConsole; // actual translate table
215static BOOL      txl16ColorsBg  = TRUE;           // allow 16 colors background
216static TXTT      txlTermCap_ae  = "";             // Switch to standard  charset
217static TXTT      txlTermCap_as  = "";             // Switch to alternate charset
218static short     displayCurCol;                   // cursor pos on display device
219static short     displayCurRow;
220static BYTE      currentColor   =  0;             // current color value
221static BOOL      alternateChr   = FALSE;          // alternate set in use now
222static TX_SCREEN virtualScreen  = {80, 25, NULL}; // updated by application
223static TX_SCREEN displayScreen  = {80, 25, NULL}; // as shown on display
224
225
226//- initialize Linux display
227static ULONG TxLinInitializeDisplay
228(
229   void
230);
231
232//- Restore Linux console to initial status
233static void TxLinTerminateDisplay
234(
235   void
236);
237
238// set cursor position, update visibility if moving off/on screen
239static void TxLinSetCursorPos
240(
241   short               row,
242   short               col
243);
244
245// make cursor invisible
246static void TxLinHideCursor
247(
248   void
249);
250
251// make cursor visible
252static void TxLinShowCursor
253(
254   void
255);
256
257// Draw characters to the actual display terminal for specified fragment
258static void TxLinUpdateFragment
259(
260   short               start,
261   short               end
262);
263
264// refresh specified area in display-buffer from virtual one
265static void TxLinUpdateArea
266(
267   short               refresh_start,           // start offset in virtual
268   short               refresh_end              // end offset
269);
270
271// refresh multiple lines on display
272static void TxLinUpdateLines
273(
274   short               first,                   // IN    first line to refresh
275   short               last                     // IN    last line to refresh
276);
277
278// Get console/window display size
279static void TxLinGetScreenSize
280(
281   short              *cols,
282   short              *rows
283);
284
285// Set global screen buffers to specified size
286static ULONG TxLinAllocScrBuffers
287(
288   short               cols,                    // IN    number of columns
289   short               rows                     // IN    number of rows
290);
291
292// Set cursor position on display device
293static void TxLinSetDevCursorPos
294(
295   short               col,
296   short               row
297);
298
299// Make cursor invisible on display device
300static void TxLinHideDevCursor
301(
302   void
303);
304
305// Make cursor visible on display device
306static void TxLinShowDevCursor
307(
308   void
309);
310
311#define TXX_VIDEO  ((BYTE *) virtualScreen.buffer)
312
313#elif defined (DOS32)                           // extended DOS
314
315#define VideoInt10()   int386( TXDX_VIDEO, &regs, &regs)
316
317#define TXX_VIDEO  ((BYTE *)  0xb8000)          // Video memory start
318
319#else                                           // OS/2 VIO subsystem
320
321typedef struct txviostate
322{
323   USHORT        length;                        // length of struct = 6
324   USHORT        request;                       // request type = 3
325   USHORT        bright;                        // 0 = blink; 1 = bright
326}  TXVIOSTATE;                                  // end of struct txviostate
327#endif
328
329
330/*****************************************************************************/
331// Initialize low level screen/terminal handling
332/*****************************************************************************/
333ULONG TxScreenInitialize
334(
335   void
336)
337{
338   ULONG               rc = NO_ERROR;           // function return
339
340   #if defined (LINUX)
341      rc = TxLinInitializeDisplay();
342   #endif
343
344   return (rc);
345}                                               // end 'TxScreenInitialize'
346/*---------------------------------------------------------------------------*/
347
348/*****************************************************************************/
349// Terminate low level screen/terminal handling
350/*****************************************************************************/
351ULONG TxScreenTerminate
352(
353   void
354)
355{
356   ULONG               rc = NO_ERROR;           // function return
357
358   #if defined (LINUX)
359      TxLinTerminateDisplay();
360   #elif defined (WIN32)
361      txNtSet_color((WORD) TX_Default);
362   #endif
363
364   return (rc);
365}                                               // end 'TxScreenTerminate'
366/*---------------------------------------------------------------------------*/
367
368
369
370/*****************************************************************************/
371// Return number of columns on the screen
372/*****************************************************************************/
373short  TxScreenCols                             // RET   current screen columns
374(
375   void
376)
377{
378   short               col = 80;
379
380   #if defined (WIN32)
381      col = (short ) TxWntSx();
382   #elif defined (DOS32)
383      col = TxxBiosWord(TXX_CRT_COLS);          // get from BIOS data area
384   #elif defined (LINUX)
385      col = virtualScreen.cols;
386   #else
387      VIOMODEINFO   vio;
388
389      vio.cb = sizeof(VIOMODEINFO);
390
391      if (VioGetMode(&vio, 0) == NO_ERROR)      // get current screenmode
392      {
393         col = vio.col;
394      }
395   #endif
396   return( col);
397}                                               // end 'TxScreenCols'
398/*---------------------------------------------------------------------------*/
399
400#if defined (USEWINDOWING) || defined (DOS32)
401/*****************************************************************************/
402// Return current cursor column, 0 = left
403/*****************************************************************************/
404short  TxCursorCol                              // RET   current cursor column
405(
406   void
407)
408{
409   USHORT              col = 1;
410
411   #if defined (WIN32)
412      col = (USHORT) TxWntCx();
413   #elif defined (DOS32)
414      union  REGS      regs;
415
416      TxxClearReg( regs);
417      regs.h.bh = 0x00;                         // first page of text-video mem
418      TxxVideoInt( regs, TXDX_VIDEO_GETCURSOR);
419
420      col = (USHORT) regs.h.dl;
421   #elif defined (LINUX)
422      col = (USHORT) virtualCurCol;
423   #else
424      USHORT           row;
425
426      VioGetCurPos( &row, &col, 0);
427   #endif
428   return((short) col);
429}                                               // end 'TxCursorCol'
430/*---------------------------------------------------------------------------*/
431#endif
432
433#if defined (USEWINDOWING)
434/*****************************************************************************/
435// Return number of lines on the screen
436/*****************************************************************************/
437short  TxScreenRows                             // RET   current screen rows
438(
439   void
440)
441{
442   short               row = 25;
443
444   #if defined (WIN32)
445      row = (short ) TxWntSy();
446   #elif defined (DOS32)
447      row = (USHORT) TxxBiosChar(TXX_CRT_ROWS) +1; // get from BIOS data area
448   #elif defined (LINUX)
449      row = virtualScreen.rows;
450   #else
451      VIOMODEINFO   vio;
452
453      vio.cb = sizeof(VIOMODEINFO);
454
455      if (VioGetMode(&vio, 0) == NO_ERROR)      // get current screenmode
456      {
457         row = vio.row;
458      }
459   #endif
460   return( row);
461}                                               // end 'TxScreenRows'
462/*---------------------------------------------------------------------------*/
463
464
465/*****************************************************************************/
466// Return current cursor row, 0 = top
467/*****************************************************************************/
468short  TxCursorRow                              // RET   current cursor row
469(
470   void
471)
472{
473   USHORT              row = 1;
474
475   #if defined (WIN32)
476      row = (USHORT) TxWntCy();
477   #elif defined (DOS32)
478      union  REGS      regs;
479
480      TxxClearReg( regs);
481      regs.h.bh = 0x00;                         // first page of text-video mem
482      TxxVideoInt( regs, TXDX_VIDEO_GETCURSOR);
483
484      row = (USHORT) regs.h.dh;
485   #elif defined (LINUX)
486      row = (USHORT) virtualCurRow;
487   #else
488      USHORT           col;
489
490      VioGetCurPos( &row, &col, 0);
491   #endif
492   return((short) row);
493}                                               // end 'TxCursorRow'
494/*---------------------------------------------------------------------------*/
495
496/*****************************************************************************/
497// Set new cursor position row and column
498/*****************************************************************************/
499void TxSetCursorPos
500(
501   short               row,                     // IN    destination row
502   short               col                      // IN    destination column
503)
504{
505   #if defined (WIN32)
506      TxWntGo((int) col, (int) row);
507   #elif defined (DOS32)
508      union  REGS      regs;
509
510      TxxClearReg( regs);
511      regs.h.bh = 0x00;                         // first page of text-video mem
512      regs.h.dh = (BYTE) row;
513      regs.h.dl = (BYTE) col;
514      TxxVideoInt( regs, TXDX_VIDEO_SETCURSOR);
515   #elif defined (LINUX)
516      TxLinSetCursorPos( row, col);
517   #else
518      VioSetCurPos((USHORT) row, (USHORT) col, 0);
519   #endif
520   return;
521}                                               // end 'TxSetCursorPos'
522/*---------------------------------------------------------------------------*/
523
524/*****************************************************************************/
525// Set new cursor visibility and style
526/*****************************************************************************/
527void TxSetCursorStyle
528(
529   BOOL                visible,                 // IN    cursor visible
530   BOOL                insert                   // IN    insert style
531)
532{
533   #if defined (WIN32)
534      CONSOLE_CURSOR_INFO   cinfo;
535
536          cinfo.dwSize   = (insert) ? 50 : 10;
537          cinfo.bVisible = visible;
538
539      SetConsoleCursorInfo( virtualScrBuf, &cinfo);
540   #elif defined (DOS32)
541      union  REGS      regs;
542
543      TxxClearReg( regs);
544      if (visible)
545      {
546         regs.h.ch = (insert)  ? (BYTE) 4 : (BYTE) 6;
547         regs.h.cl = 7;
548      }
549      else
550      {
551         regs.h.ch = 0x20;
552      }
553      TxxVideoInt( regs, TXDX_VIDEO_SETCSHAPE);
554   #elif defined (LINUX)
555      //- to be refined, set cursor shape for insert (ioctl ?)
556      //- use TermCap ve (normal) vs (insert) and vi (hidden) escape strings
557      if (visible)
558      {
559         TxLinShowCursor();
560      }
561      else
562      {
563         TxLinHideCursor();
564      }
565      cursorInsert = insert;
566   #else
567      VIOCURSORINFO    ci;
568
569      VioGetCurType( &ci, 0);                   // get current cursor style
570
571      ci.attr   = (USHORT) ((visible) ?   1 :  -1);
572      ci.yStart = (USHORT) ((insert)  ? -50 : -90);
573      ci.cEnd   = (USHORT) (-100);
574
575      VioSetCurType( &ci, 0);                   // set current cursor style
576   #endif
577   return;
578}                                               // end 'TxSetCursorStyle'
579/*---------------------------------------------------------------------------*/
580#endif
581
582/*****************************************************************************/
583// Set blinking/bright-background mode for fullscreen sessions (VGA)
584/*****************************************************************************/
585void TxSetBrightBgMode
586(
587   BOOL                bright                   // IN    use bright background
588)
589{
590   #if   defined (WIN32)                        // no setting needed (no FS)
591   #elif defined (DOS32)
592      union  REGS      regs;
593
594      TxxClearReg( regs);
595      regs.h.al = 0x03;                         // set bright/blinking
596      regs.h.bl = (BYTE) ((bright) ? 0 : 1);
597      TxxVideoInt( regs, TXDX_VIDEO_SETSTATUS);
598   #elif defined (LINUX)
599      //- to be refined
600   #else                                        // use VioSetState INTENSITY
601      TXVIOSTATE       viostate;
602
603      viostate.length  = 6;                     // length of struct
604      viostate.request = 2;                     // request type
605      viostate.bright  = (bright) ? 1 : 0;      // 0 = blink; 1 = bright
606
607      VioSetState( &viostate, 0);               // set bright/blink state
608   #endif
609   return;
610}                                               // end 'TxSetBrightBgMode'
611/*---------------------------------------------------------------------------*/
612
613#if defined (USEWINDOWING)
614/*****************************************************************************/
615// Draw a character-string at specified position, clip to optional clip-rect
616/*****************************************************************************/
617void txwScrDrawCharString
618(
619   short               row,                     // IN    destination row
620   short               col,                     // IN    destination column
621   TXRECT             *clip,                    // IN    opt clip-rectangle
622   char               *str                      // IN    string to draw
623)
624{
625   short               length;                  // length visible string
626   short               start;                   // start-offset visible string
627
628   TXSCREEN_BEGIN_UPDATE();
629   length = txwCalculateStringClip( row, col, (short) strlen(str), clip, &start);
630   if (length > 0)
631   {
632      short         srow = TxCursorRow();
633      short         scol = TxCursorCol();
634
635      #if defined (WIN32)
636         COORD         dpos;
637         ULONG         todo = (ULONG) length;
638         ULONG         done;
639
640         dpos.X = col + start;
641         dpos.Y = row;
642
643         WriteConsoleOutputCharacter( virtualScrBuf,
644                            (LPCTSTR) (str + start), todo, dpos, &done);
645
646      #elif defined (DEV32)                     // OS/2 VIO subsystem
647         memcpy( txVbuf, str + start, length);
648         txVbuf[ length] = 0;
649
650         VioWrtCharStr( txVbuf, length, row, col + start, 0);
651
652      #else                                     // DOS or LINUX memory mapped
653         short         i;
654         BYTE         *first = TXX_VIDEO;
655
656         first += ((row * TxScreenCols()) +col +start) *2;
657
658         for (i = 0; i < length; i++)           // itterate over visible string
659         {
660            *first = str[ start + i];           // write the character
661            first++;                            // move to attribute byte
662            first++;                            // move to next character
663         }
664      #endif
665      TxSetCursorPos( srow, scol);              // restore cursor position
666   }
667   TXSCREEN_ENDOF_UPDATE();
668   return;
669}                                               // end 'txwScrDrawCharString'
670/*---------------------------------------------------------------------------*/
671
672
673/*****************************************************************************/
674// Draw a character-string at position in specified color, using clip-rect
675/*****************************************************************************/
676void txwScrDrawCharStrCol
677(
678   short               row,                     // IN    destination row
679   short               col,                     // IN    destination column
680   TXRECT             *clip,                    // IN    opt clip-rectangle
681   char               *str,                     // IN    string to draw
682   BYTE                color                    // IN    color attribute
683)
684{
685   short               length;                  // length visible string
686   short               start;                   // start-offset visible string
687
688   TXSCREEN_BEGIN_UPDATE();
689   length = txwCalculateStringClip( row, col, (short