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