FreeBASIC  0.91.0
io_printbuff.c
Go to the documentation of this file.
1 /* low-level print to console function */
2 
3 #include "../fb.h"
4 #include "fb_private_console.h"
5 #include <unistd.h>
6 #include <go32.h>
7 #include <dpmi.h>
8 #include <sys/farptr.h>
9 
10 typedef struct _fb_PrintInfo {
11  unsigned short usAttr;
12 } fb_PrintInfo;
13 
14 static void fb_hHookConScroll_BIOS
15  (
17  int x1, int y1,
18  int x2, int y2,
19  int rows
20  )
21 {
22  fb_ConsoleScroll_BIOS( x1, y1, x2, y2, rows );
23  handle->Coord.Y = handle->Border.Bottom;
24 }
25 
26 static int fb_hHookConWrite_BIOS
27  (
28  fb_ConHooks *handle,
29  const void *buffer,
30  size_t length
31  )
32 {
33  fb_PrintInfo *pInfo = (fb_PrintInfo*) handle->Opaque;
34  const char *pachText = (const char *)buffer;
35  __dpmi_regs regs;
36  unsigned char uchAttr = (unsigned char) pInfo->usAttr;
37  int pos = (handle->Coord.Y << 8) | handle->Coord.X;
38 
39  while( length-- ) {
40  fb_hSetCursorPos( pos, -1 );
41  ++pos;
42  regs.h.ah = 0x09;
43  regs.h.al = *pachText++;
44  regs.h.bh = __fb_con.active;
45  regs.h.bl = uchAttr;
46  regs.x.cx = 1;
47  __dpmi_int(0x10, &regs);
48 
49  }
50 
51  return TRUE;
52 }
53 
54 static int fb_hHookConWrite_MEM
55  (
56  fb_ConHooks *handle,
57  const void *buffer,
58  size_t length
59  )
60 {
61  fb_PrintInfo *pInfo = (fb_PrintInfo*) handle->Opaque;
62  const char *pachText = (const char *)buffer;
63  unsigned short usAttr = pInfo->usAttr << 8;
64  int tmp_x = handle->Coord.X;
65  int tmp_y = handle->Coord.Y;
66  unsigned char *puchBuffer = alloca( length * 2 );
67  unsigned short *pusBuffer = (unsigned short*) puchBuffer;
68  size_t i;
69 
70  i = length;
71  pusBuffer += length;
72  while( i-- ) {
73  *--pusBuffer = usAttr + (unsigned short) (unsigned char) pachText[i];
74  }
75 
76  _movedataw( _my_ds(), (int) puchBuffer,
77  _dos_ds, __fb_con.phys_addr + (__fb_con.w << 1) * tmp_y + (tmp_x << 1),
78  length );
79 
80  return TRUE;
81 }
82 
83 unsigned long fb_hGetPageAddr( int pg, int cols, int rows )
84 {
85  unsigned long physAddr;
86  unsigned char mode = _farpeekb( _dos_ds, 0x465 );
87 
88  if( mode & 0x02 )
89  return 0;
90 
91  if( mode & 0x04 )
92  physAddr = 0xB0000;
93  else
94  physAddr = 0xB8000;
95 
96  if( pg != 0 ) {
97  if( (cols == 0) || (rows == 0) )
98  fb_ConsoleGetSize( &cols, &rows );
99 
100  int pageSize = cols * rows * (sizeof( char ) * 2);
101  if( rows == 25 )
102  pageSize += 96;
103 
104  physAddr += pg * pageSize;
105  }
106 
107  return physAddr;
108 }
109 
111  (
112  const void *buffer,
113  size_t len,
114  int mask
115  )
116 {
117  const char *pachText = (const char *) buffer;
118  int win_left, win_top, win_cols, win_rows;
119  int view_top, view_bottom;
120  fb_PrintInfo info;
121  fb_ConHooks hooks;
122 
123  /* Do we want to correct the console cursor position? */
124  if( (mask & FB_PRINT_FORCE_ADJUST)==0 ) {
125  /* No, we can check for the length to avoid unnecessary stuff ... */
126  if( len==0 )
127  return;
128  }
129 
130  FB_LOCK();
131 
132  fb_ConsoleGetSize( &win_cols, &win_rows );
133  fb_ConsoleGetView( &view_top, &view_bottom );
134  win_left = win_top = 0;
135 
136  __fb_con.w = win_cols;
137  __fb_con.h = win_rows;
138  __fb_con.phys_addr = fb_hGetPageAddr( __fb_con.active, win_cols, win_rows );
139 
140  hooks.Opaque = &info;
141  if( __fb_con.phys_addr ) {
143  hooks.Write = fb_hHookConWrite_MEM;
144  } else {
147  }
148  hooks.Border.Left = win_left;
149  hooks.Border.Top = win_top + view_top - 1;
150  hooks.Border.Right = win_left + win_cols - 1;
151  hooks.Border.Bottom = win_top + view_bottom - 1;
152 
153  info.usAttr = (unsigned short) (unsigned char) fb_ConsoleGetColorAtt();
154 
155  {
156  fb_ConsoleGetXY_BIOS( &hooks.Coord.X, &hooks.Coord.Y );
157 
158  if( __fb_con.scrollWasOff ) {
160  ++hooks.Coord.Y;
161  hooks.Coord.X = hooks.Border.Left;
162  fb_hConCheckScroll( &hooks );
163  }
164 
165  fb_ConPrintTTY( &hooks, pachText, len, TRUE );
166 
167  if( hooks.Coord.X != hooks.Border.Left
168  || hooks.Coord.Y != (hooks.Border.Bottom+1) )
169  {
170  fb_hConCheckScroll( &hooks );
171  } else {
173  hooks.Coord.X = hooks.Border.Right;
174  hooks.Coord.Y = hooks.Border.Bottom;
175  }
176  fb_ConsoleLocate_BIOS( hooks.Coord.Y, hooks.Coord.X, -1 );
177  }
178 
179  FB_UNLOCK();
180 }
181 
183  (
184  const void *buffer,
185  size_t len,
186  int mask
187  )
188 {
189  fwrite(buffer, len, 1, stdout);
190  fflush(stdout);
191 }
192 
193 void fb_ConsolePrintBufferEx( const void *buffer, size_t len, int mask )
194 {
195  static void (*fn)(const void *buffer, size_t len, int mask) = NULL;
196 
197  if( fn == NULL ) {
198  /* use cprintf() if STDOUT is the console;
199  otherwise (with shell I/O redirection) use printf() */
200  if( isatty( fileno( stdout ) ) )
202  else
204  }
205 
206  fn( buffer, len, mask );
207 }
208 
209 void fb_ConsolePrintBuffer( const char *buffer, int mask )
210 {
211  fb_ConsolePrintBufferEx( buffer, strlen( buffer ), mask );
212 }