A step towards validation.
[super-star-trek.git] / conio.c
1 /****************************************************************************
2  * This is the implementation file for conio.h - a conio.h for Linux.       *
3  * It uses ncurses and some internal functions of Linux to simulate the     *
4  * I/O-functions.                                                           *
5  * This is copyright (c) 1996,97 by Fractor / Mental eXPlosion (MXP)        *
6  * Use and distribution is only allowed if you follow the terms of the      *
7  * GNU Library Public License Version 2.                                    *
8  * Since this work is based on ncurses please read its copyright notices as *
9  * well !                                                                   *
10  * Look into the readme to this file for further information.               *
11  * Thanx to SubZero / MXP for his little tutorial on the curses library !   *
12  * Many thanks to Mark Hahn and Rich Cochran for solving the inpw and inpd  *
13  * mega-bug !!!                                                             *
14  * Watch out for other MXP releases, too !                                  *
15  * Send bugreports to: fractor@germanymail.com                              *
16  ****************************************************************************/
17
18 #define _ISOC99_SOURCE
19 #include <stdio.h>
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/io.h>
25 #include <ncurses.h>
26 #include "conio.h" 
27
28 static attr_t txtattr,oldattr;
29 static int fgc,bgc;
30 char color_warning=1;
31 int directvideo;
32 WINDOW *conio_scr;
33
34 #ifdef SERGEEV 
35 /* Some internals... */
36 static int colortab(int a) /* convert LINUX Color code to DOS-standard */
37 {
38    switch(a) {
39       case 0 : return COLOR_BLACK;
40       case 1 : return COLOR_BLUE;
41       case 2 : return COLOR_GREEN;
42       case 3 : return COLOR_CYAN;
43       case 4 : return COLOR_RED;
44       case 5 : return COLOR_MAGENTA;
45       case 6 : return COLOR_YELLOW;
46       case 7 : return COLOR_WHITE;
47    }
48    return COLOR_BLACK;
49
50 #endif /* SERGEEV */
51
52 static void docolor (int color) /* Set DOS-like text mode colors */
53 {
54    wattrset(conio_scr,0); /* My curses-version needs this ... */
55    if ((color&128)==128) txtattr=A_BLINK; else txtattr=A_NORMAL;
56    if ((color&15)>7) txtattr|=A_STANDOUT; else txtattr|=A_NORMAL;
57    txtattr|=COLOR_PAIR((1+(color&7)+(color&112)) >> 1);
58    if (((color&127)==15) | ((color&127)==7)) txtattr=COLOR_PAIR(0);
59    if (((color&127)==127) | ((color&127)==119)) txtattr=COLOR_PAIR(8);
60    wattron(conio_scr,txtattr);
61    wattron(conio_scr,COLOR_PAIR(1+(color&7)+((color&112)>>1))); 
62 }
63
64 #ifdef SERGEEV
65 /* Call this before any call to linux conio - except the port functions ! */
66 void __attribute__((constructor)) initconio (void) /* This is needed, because ncurses needs to be initialized */
67 {
68    int x,y;
69    short pair;
70    if (atexit(doneconio)){
71       fprintf(stderr,"Unable to register doneconio(), exiting...\n");
72       exit(1);
73    }
74    initscr();
75    start_color();
76 //   attr_get(&oldattr,&pair,NULL);
77    nonl();
78    raw();
79    if (!has_colors() & (color_warning>-1))
80       fprintf(stderr,"Attention: A color terminal may be required to run this application !\n");   
81    noecho();
82    conio_scr=newwin(0,0,0,0);
83    keypad(conio_scr,TRUE);
84    meta(conio_scr,TRUE);
85    idlok(conio_scr,TRUE);
86    scrollok(conio_scr,TRUE);
87    /* Color initialization */
88    for (y=0;y<=7;y++)
89       for (x=0;x<=7;x++)
90          init_pair((8*y)+x+1, colortab(x), colortab(y));              
91    wattr_get(conio_scr,&txtattr,&pair,NULL);
92    bgc=0;
93    textcolor(7);
94    textbackground(0);
95 }
96 #endif /* SERGEEV */
97
98 /* Call this on exiting your program */
99 void doneconio (void)
100 {
101    endwin();
102 }
103
104 /* Here it starts... */
105 void _setcursortype (int cur_t)
106 {
107    curs_set(cur_t);
108    wrefresh(conio_scr);
109 }
110
111 char *cgets (char *str) /* ugly function :-( */
112 {
113    char strng[257];
114    unsigned char i=2;
115    echo();
116    strncpy(strng,str,1);
117    wgetnstr(conio_scr,&strng[2],(int) strng[0]);
118    while (strng[i]!=0) i++;
119    i=i-2;
120    strng[1]=i;
121    memcpy(str,strng,i+3);
122    noecho();
123    return(&str[2]);
124 }
125
126 void clreol (void)
127 /* clear to end of line -- can be a no-op in tty mode */
128 {
129 #ifdef SERGEEV
130    wclrtoeol(conio_scr);
131    wrefresh(conio_scr);
132 #endif /* SERGEEV */
133 }
134
135 void clrscr (void)
136 /* clear screen -- can be a no-op in tty mode */
137 {
138 #ifdef SERGEEV
139    wclear(conio_scr);
140    wmove(conio_scr,0,0);
141    wrefresh(conio_scr);
142 #endif /* SERGEEV */
143 }
144
145 int cprintf (char *format, ... )
146 {
147    int i;
148    char buffer[BUFSIZ]; /* Well, BUFSIZ is from ncurses...  */
149    va_list argp;
150    va_start(argp,format);
151    vsprintf(buffer,format,argp);
152    va_end(argp);
153
154 #ifdef SERGEEV
155    i=waddstr(conio_scr,buffer);
156    wrefresh(conio_scr);
157 #else
158    i=printf(buffer);
159 #endif /* SERGEEV */
160    return(i);
161 }
162
163 void cputs (char *str)
164 {
165    waddstr(conio_scr,str);
166    wrefresh(conio_scr);
167 }
168
169 int cscanf (const char *format, ...)
170 {
171    int i;
172    char buffer[BUFSIZ]; /* See cprintf */
173    va_list argp;
174    echo();
175    if (wgetstr(conio_scr,buffer)==ERR) return(-1);                    
176    va_start(argp,format);
177    i=vsscanf(buffer,format,argp);                         
178    va_end(argp);
179    noecho();
180    return(i);
181 }
182
183 void delline (void)
184 {
185    wdeleteln(conio_scr);
186    wrefresh(conio_scr);
187 }
188
189 int getche (void)
190 {
191    int i;
192    echo();
193    i=wgetch(conio_scr);
194    if (i==-1) i=0;
195    noecho();
196    return(i);
197 }
198
199 void gettextinfo(struct text_info *inforec)
200 {
201    short pair;
202    unsigned char xp,yp;
203    unsigned char x1,x2,y1,y2;
204    attr_t dattr,dnattr,a; /* The "d" stands for DOS */
205    getyx(conio_scr,yp,xp);
206    getbegyx(conio_scr,y1,x1);
207    getmaxyx(conio_scr,y2,x2);
208    dattr=(bgc*16)+fgc;
209    wattr_get(conio_scr,&a,&pair,NULL);
210    if (a==(a & A_BLINK)) dattr=dattr+128;
211    dnattr=oldattr;  /* Well, this cannot be right, 
212                        because we don't know the COLORPAIR values from before initconio() !*/
213    inforec->winleft=x1+1;
214    inforec->wintop=y1+1;
215    if (x1==0) x2--;
216    if (y1==0) y2--;
217    inforec->winright=x1+x2+1;
218    inforec->winbottom=y1+y2+1;
219    inforec->curx=xp+1;
220    inforec->cury=yp+1;
221    inforec->screenheight=y2+1;
222    inforec->screenwidth=x2+1;
223    inforec->currmode=3; /* This is C80 */
224    inforec->normattr=dnattr; /* Don't use this ! */
225    inforec->attribute=dattr;
226
227
228 void gotoxy (int x, int y)
229 /* address cursor -- OK for this to be a no-op in TTY mode */
230 {
231 #ifdef SERGEEV
232    y--;
233    x--;
234    wmove(conio_scr,y,x);
235    wrefresh(conio_scr);
236 #endif /* SERGEEV */
237 }
238
239 void highvideo (void)
240 {
241 #ifdef SERGEEV
242    textcolor(15); /* White */
243    textbackground(0); /* Black */
244 #endif /* SERGEEV */
245 }
246
247 void insline (void)
248
249    winsertln(conio_scr);
250    wrefresh(conio_scr);
251 }
252
253 int kbhit (void)
254 {
255    int i;
256    nodelay(conio_scr,TRUE);
257    i=wgetch(conio_scr);
258    nodelay(conio_scr,FALSE);
259    if (i==-1) i=0;
260    return(i);
261 }
262
263 void lowvideo (void)
264 {
265    textbackground(0); /* Black */
266    textcolor(8); /* Should be darkgray */
267 }
268
269 void normvideo (void)
270 {
271    wattrset(conio_scr,oldattr);
272 }
273
274 int putch (int c)
275 {
276    if (waddch(conio_scr,c)!=ERR) {
277       wrefresh(conio_scr); 
278       return(c);
279    }
280    return(0);
281 }
282                                      
283 void textattr (int attr)
284 {
285    docolor(attr);
286 }
287
288 void textbackground (int color)
289 {
290    bgc=color;
291    color=(bgc*16)+fgc;
292    docolor(color);
293 }
294
295
296 void textcolor (int color)
297 {
298 #ifdef SERGEEV
299    fgc=color;
300    color=(bgc*16)+fgc;
301    docolor(color);
302 #endif /* SERGEEV */
303 }
304  
305 void textmode (int mode)
306 {
307    /* Ignored */
308 }
309
310 int wherex (void)
311 {
312    int y;
313    int x;
314    getyx(conio_scr,y,x);
315    x++;
316    return(x);
317 }
318
319 int wherey (void)
320 {
321    int y;
322    int x;
323    getyx(conio_scr,y,x);
324    y++;
325    return(y);
326 }
327
328 void window (int left,int top,int right,int bottom)
329 {
330    int nlines,ncols;
331    delwin(conio_scr);
332    top--;
333    left--;
334    right--;
335    bottom--;
336    nlines=bottom-top;
337    ncols=right-left;
338    if (top==0) nlines++;
339    if (left==0) ncols++;
340    if ((nlines<1) | (ncols<1)) return;
341    conio_scr=newwin(nlines,ncols,top,left);   
342    keypad(conio_scr,TRUE);
343    meta(conio_scr,TRUE);
344    idlok(conio_scr,TRUE);
345    scrollok(conio_scr,TRUE);
346    wrefresh(conio_scr);
347 }
348
349 /* Linux is cool */