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