1 /* Public Domain Curses */
2 
3 #include <curspriv.h>
4 
5 /*man-start**************************************************************
6 
7 initscr
8 -------
9 
10 ### Synopsis
11 
12     WINDOW *initscr(void);
13     WINDOW *Xinitscr(int argc, char *argv[]);
14     int endwin(void);
15     bool isendwin(void);
16     SCREEN *newterm(const char *type, FILE *outfd, FILE *infd);
17     SCREEN *set_term(SCREEN *new);
18     void delscreen(SCREEN *sp);
19 
20     int resize_term(int nlines, int ncols);
21     bool is_termresized(void);
22     const char *curses_version(void);
23 
24 ### Description
25 
26    initscr() should be the first curses routine called.  It will
27    initialize all curses data structures, and arrange that the
28    first call to refresh() will clear the screen.  In case of
29    error, initscr() will write a message to standard error and end
30    the program.
31 
32    endwin() should be called before exiting or escaping from curses
33    mode temporarily.  It will restore tty modes, move the cursor to
34    the lower left corner of the screen and reset the terminal into
35    the proper non-visual mode.  To resume curses after a temporary
36    escape, call refresh() or doupdate().
37 
38    isendwin() returns TRUE if endwin() has been called without a
39    subsequent refresh, unless SP is NULL.
40 
41    In some implementations of curses, newterm() allows the use of
42    multiple terminals. Here, it's just an alternative interface for
43    initscr(). It always returns SP, or NULL.
44 
45    delscreen() frees the memory allocated by newterm() or
46    initscr(), since it's not freed by endwin(). This function is
47    usually not needed. In PDCurses, the parameter must be the
48    value of SP, and delscreen() sets SP to NULL.
49 
50    set_term() does nothing meaningful in PDCurses, but is included
51    for compatibility with other curses implementations.
52 
53    resize_term() is effectively two functions: When called with
54    nonzero values for nlines and ncols, it attempts to resize the
55    screen to the given size. When called with (0, 0), it merely
56    adjusts the internal structures to match the current size after
57    the screen is resized by the user. On the currently supported
58    platforms, this functionality is mutually exclusive: X11 allows
59    user resizing, while DOS, OS/2 and Win32 allow programmatic
60    resizing. If you want to support user resizing, you should check
61    for getch() returning KEY_RESIZE, and/or call is_termresized()
62    at appropriate times; if either condition occurs, call
63    resize_term(0, 0). Then, with either user or programmatic
64    resizing, you'll have to resize any windows you've created, as
65    appropriate; resize_term() only handles stdscr and curscr.
66 
67    is_termresized() returns TRUE if the curses screen has been
68    resized by the user, and a call to resize_term() is needed.
69    Checking for KEY_RESIZE is generally preferable, unless you're
70    not handling the keyboard.
71 
72    curses_version() returns a string describing the version of
73    PDCurses.
74 
75 ### Return Value
76 
77    All functions return NULL on error, except endwin(), which
78    returns ERR on error.
79 
80 ### Portability
81                              X/Open    BSD    SYS V
82     initscr                     Y       Y       Y
83     endwin                      Y       Y       Y
84     isendwin                    Y       -      3.0
85     newterm                     Y       -       Y
86     set_term                    Y       -       Y
87     delscreen                   Y       -      4.0
88     resize_term                 -       -       -
89     is_termresized              -       -       -
90     curses_version              -       -       -
91 
92 **man-end****************************************************************/
93 
94 #include <stdlib.h>
95 
96 char ttytype[128];
97 
98 #define PDC_STR( x) #x
99 #define PDC_str( x) PDC_STR( x)
100 
101 static const char *_curses_notice =
102       "PDCurses " PDC_str(PDC_VER_MAJOR) "."
103                   PDC_str(PDC_VER_MINOR) "."
104                   PDC_str(PDC_VER_CHANGE) " - Public Domain "
105                   PDC_str(PDC_VER_YEAR) "-"
106                   PDC_str(PDC_VER_MONTH) "-"
107                   PDC_str(PDC_VER_DAY);
108 
109 SCREEN *SP = (SCREEN*)NULL;           /* curses variables */
110 WINDOW *curscr = (WINDOW *)NULL;      /* the current screen image */
111 WINDOW *stdscr = (WINDOW *)NULL;      /* the default screen window */
112 WINDOW *pdc_lastscr = (WINDOW *)NULL; /* the last screen image */
113 
114 int LINES = 0;                        /* current terminal height */
115 int COLS = 0;                         /* current terminal width */
116 int TABSIZE = 8;
117 
118 MOUSE_STATUS Mouse_status, pdc_mouse_status;
119 
120 extern RIPPEDOFFLINE linesripped[5];
121 extern char linesrippedoff;
122 
Xinitscr(int argc,char * argv[])123 WINDOW *Xinitscr(int argc, char *argv[])
124 {
125     int i;
126 
127     PDC_LOG(("Xinitscr() - called\n"));
128 
129     if (SP && SP->alive)
130         return NULL;
131 
132     if (PDC_scr_open(argc, argv) == ERR)
133     {
134         fprintf(stderr, "initscr(): Unable to create SP\n");
135         exit(8);
136     }
137 
138     SP->autocr = TRUE;       /* cr -> lf by default */
139     SP->raw_out = FALSE;     /* tty I/O modes */
140     SP->raw_inp = FALSE;     /* tty I/O modes */
141     SP->cbreak = TRUE;
142     SP->save_key_modifiers = FALSE;
143     SP->return_key_modifiers = FALSE;
144     SP->echo = TRUE;
145     SP->visibility = 1;
146     SP->resized = FALSE;
147     SP->_trap_mbe = 0L;
148     SP->_map_mbe_to_key = 0L;
149     SP->linesrippedoff = 0;
150     SP->linesrippedoffontop = 0;
151     SP->delaytenths = 0;
152     SP->line_color = -1;
153 
154     SP->orig_cursor = PDC_get_cursor_mode();
155 
156     LINES = SP->lines;
157     COLS = SP->cols;
158 
159     if (LINES < 2 || COLS < 2)
160     {
161         fprintf(stderr, "initscr(): LINES=%d COLS=%d: too small.\n",
162                 LINES, COLS);
163         exit(4);
164     }
165 
166     if ((curscr = newwin(LINES, COLS, 0, 0)) == (WINDOW *)NULL)
167     {
168         fprintf(stderr, "initscr(): Unable to create curscr.\n");
169         exit(2);
170     }
171 
172     if ((pdc_lastscr = newwin(LINES, COLS, 0, 0)) == (WINDOW *)NULL)
173     {
174         fprintf(stderr, "initscr(): Unable to create pdc_lastscr.\n");
175         exit(2);
176     }
177 
178     wattrset(pdc_lastscr, (chtype)(-1));
179     werase(pdc_lastscr);
180 
181     PDC_slk_initialize();
182     LINES -= SP->slklines;
183 
184     /* We have to sort out ripped off lines here, and reduce the height
185        of stdscr by the number of lines ripped off */
186 
187     for (i = 0; i < linesrippedoff; i++)
188     {
189         if (linesripped[i].line < 0)
190             (*linesripped[i].init)(newwin(1, COLS, LINES - 1, 0), COLS);
191         else
192             (*linesripped[i].init)(newwin(1, COLS,
193                                    SP->linesrippedoffontop++, 0), COLS);
194 
195         SP->linesrippedoff++;
196         LINES--;
197     }
198 
199     linesrippedoff = 0;
200 
201     if (!(stdscr = newwin(LINES, COLS, SP->linesrippedoffontop, 0)))
202     {
203         fprintf(stderr, "initscr(): Unable to create stdscr.\n");
204         exit(1);
205     }
206 
207     wclrtobot(stdscr);
208 
209     /* If preserving the existing screen, don't allow a screen clear */
210 
211     if (SP->_preserve)
212     {
213         untouchwin(curscr);
214         untouchwin(stdscr);
215         stdscr->_clear = FALSE;
216         curscr->_clear = FALSE;
217     }
218     else
219         curscr->_clear = TRUE;
220 
221     PDC_init_atrtab();  /* set up default colors */
222 
223     MOUSE_X_POS = MOUSE_Y_POS = -1;
224     BUTTON_STATUS(1) = BUTTON_RELEASED;
225     BUTTON_STATUS(2) = BUTTON_RELEASED;
226     BUTTON_STATUS(3) = BUTTON_RELEASED;
227     Mouse_status.changes = 0;
228 
229     SP->alive = TRUE;
230 
231     def_shell_mode();
232 
233     longname( );   /* to ensure that ttytype is initialized */
234 
235     return stdscr;
236 }
237 
initscr(void)238 WINDOW *initscr(void)
239 {
240     PDC_LOG(("initscr() - called\n"));
241 
242     return Xinitscr(0, NULL);
243 }
244 
endwin(void)245 int endwin(void)
246 {
247     PDC_LOG(("endwin() - called\n"));
248 
249     /* Allow temporary exit from curses using endwin() */
250 
251     def_prog_mode();
252     PDC_scr_close();
253 
254     SP->alive = FALSE;
255 
256     return OK;
257 }
258 
isendwin(void)259 bool isendwin(void)
260 {
261     PDC_LOG(("isendwin() - called\n"));
262 
263     return SP ? !(SP->alive) : FALSE;
264 }
265 
newterm(const char * type,FILE * outfd,FILE * infd)266 SCREEN *newterm(const char *type, FILE *outfd, FILE *infd)
267 {
268     PDC_LOG(("newterm() - called\n"));
269 
270     return Xinitscr(0, NULL) ? SP : NULL;
271 }
272 
set_term(SCREEN * new)273 SCREEN *set_term(SCREEN *new)
274 {
275     PDC_LOG(("set_term() - called\n"));
276 
277     /* We only support one screen */
278 
279     return (new == SP) ? SP : NULL;
280 }
281 
delscreen(SCREEN * sp)282 void delscreen(SCREEN *sp)
283 {
284     PDC_LOG(("delscreen() - called\n"));
285 
286     if (sp != SP)
287         return;
288 
289     PDC_slk_free();     /* free the soft label keys, if needed */
290 
291     delwin(stdscr);
292     delwin(curscr);
293     delwin(pdc_lastscr);
294     stdscr = (WINDOW *)NULL;
295     curscr = (WINDOW *)NULL;
296     pdc_lastscr = (WINDOW *)NULL;
297 
298     SP->alive = FALSE;
299 
300     PDC_scr_free();     /* free SP and pdc_atrtab */
301 
302     SP = (SCREEN *)NULL;
303 }
304 
resize_term(int nlines,int ncols)305 int resize_term(int nlines, int ncols)
306 {
307     PDC_LOG(("resize_term() - called: nlines %d\n", nlines));
308 
309     if( PDC_resize_screen(nlines, ncols) == ERR)
310         return ERR;
311 
312     if (!stdscr)
313         return OK;
314 
315     SP->lines = PDC_get_rows();
316     LINES = SP->lines - SP->linesrippedoff - SP->slklines;
317     SP->cols = COLS = PDC_get_columns();
318 
319     if (wresize(curscr, SP->lines, SP->cols) == ERR ||
320         wresize(stdscr, LINES, COLS) == ERR ||
321         wresize(pdc_lastscr, SP->lines, SP->cols) == ERR)
322         return ERR;
323 
324     werase(pdc_lastscr);
325     curscr->_clear = TRUE;
326 
327     if (SP->slk_winptr)
328     {
329         if (wresize(SP->slk_winptr, SP->slklines, COLS) == ERR)
330             return ERR;
331 
332         wmove(SP->slk_winptr, 0, 0);
333         wclrtobot(SP->slk_winptr);
334         PDC_slk_initialize();
335         slk_noutrefresh();
336     }
337 
338     touchwin(stdscr);
339     wnoutrefresh(stdscr);
340 
341     return OK;
342 }
343 
is_termresized(void)344 bool is_termresized(void)
345 {
346     PDC_LOG(("is_termresized() - called\n"));
347 
348     return SP->resized;
349 }
350 
curses_version(void)351 const char *curses_version(void)
352 {
353     return _curses_notice;
354 }
355