Back to index

tetex-bin  3.0
lib_set_term.c
Go to the documentation of this file.
00001 /****************************************************************************
00002  * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc.              *
00003  *                                                                          *
00004  * Permission is hereby granted, free of charge, to any person obtaining a  *
00005  * copy of this software and associated documentation files (the            *
00006  * "Software"), to deal in the Software without restriction, including      *
00007  * without limitation the rights to use, copy, modify, merge, publish,      *
00008  * distribute, distribute with modifications, sublicense, and/or sell       *
00009  * copies of the Software, and to permit persons to whom the Software is    *
00010  * furnished to do so, subject to the following conditions:                 *
00011  *                                                                          *
00012  * The above copyright notice and this permission notice shall be included  *
00013  * in all copies or substantial portions of the Software.                   *
00014  *                                                                          *
00015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
00016  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
00017  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
00018  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
00019  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
00020  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
00021  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
00022  *                                                                          *
00023  * Except as contained in this notice, the name(s) of the above copyright   *
00024  * holders shall not be used in advertising or otherwise to promote the     *
00025  * sale, use or other dealings in this Software without prior written       *
00026  * authorization.                                                           *
00027  ****************************************************************************/
00028 
00029 /****************************************************************************
00030  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
00031  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
00032  *     and: Thomas E. Dickey                        1996-on                 *
00033  ****************************************************************************/
00034 
00035 /*
00036 **     lib_set_term.c
00037 **
00038 **     The routine set_term().
00039 **
00040 */
00041 
00042 #include <curses.priv.h>
00043 
00044 #include <term.h>           /* cur_term */
00045 #include <tic.h>
00046 
00047 MODULE_ID("$Id: lib_set_term.c,v 1.82 2004/04/24 20:17:39 tom Exp $")
00048 
00049 NCURSES_EXPORT(SCREEN *)
00050 set_term(SCREEN * screenp)
00051 {
00052     SCREEN *oldSP;
00053 
00054     T((T_CALLED("set_term(%p)"), screenp));
00055 
00056     oldSP = SP;
00057     _nc_set_screen(screenp);
00058 
00059     set_curterm(SP->_term);
00060     curscr = SP->_curscr;
00061     newscr = SP->_newscr;
00062     stdscr = SP->_stdscr;
00063     COLORS = SP->_color_count;
00064     COLOR_PAIRS = SP->_pair_count;
00065 
00066     T((T_RETURN("%p"), oldSP));
00067     return (oldSP);
00068 }
00069 
00070 static void
00071 _nc_free_keytry(struct tries *kt)
00072 {
00073     if (kt != 0) {
00074        _nc_free_keytry(kt->child);
00075        _nc_free_keytry(kt->sibling);
00076        free(kt);
00077     }
00078 }
00079 
00080 /*
00081  * Free the storage associated with the given SCREEN sp.
00082  */
00083 NCURSES_EXPORT(void)
00084 delscreen(SCREEN * sp)
00085 {
00086     SCREEN **scan = &_nc_screen_chain;
00087     int i;
00088 
00089     T((T_CALLED("delscreen(%p)"), sp));
00090 
00091     while (*scan) {
00092        if (*scan == sp) {
00093            *scan = sp->_next_screen;
00094            break;
00095        }
00096        scan = &(*scan)->_next_screen;
00097     }
00098 
00099     (void) _nc_freewin(sp->_curscr);
00100     (void) _nc_freewin(sp->_newscr);
00101     (void) _nc_freewin(sp->_stdscr);
00102 
00103     if (sp->_slk != 0) {
00104        if (sp->_slk->ent != 0) {
00105            for (i = 0; i < sp->_slk->labcnt; ++i) {
00106               FreeIfNeeded(sp->_slk->ent[i].ent_text);
00107               FreeIfNeeded(sp->_slk->ent[i].form_text);
00108            }
00109            free(sp->_slk->ent);
00110        }
00111        free(sp->_slk);
00112        sp->_slk = 0;
00113     }
00114 
00115     _nc_free_keytry(sp->_keytry);
00116     sp->_keytry = 0;
00117 
00118     _nc_free_keytry(sp->_key_ok);
00119     sp->_key_ok = 0;
00120 
00121     FreeIfNeeded(sp->_color_table);
00122     FreeIfNeeded(sp->_color_pairs);
00123 
00124     FreeIfNeeded(sp->oldhash);
00125     FreeIfNeeded(sp->newhash);
00126     FreeIfNeeded(sp->hashtab);
00127 
00128     del_curterm(sp->_term);
00129 
00130     /*
00131      * If the associated output stream has been closed, we can discard the
00132      * set-buffer.  Limit the error check to EBADF, since fflush may fail
00133      * for other reasons than trying to operate upon a closed stream.
00134      */
00135     if (sp->_ofp != 0
00136        && sp->_setbuf != 0
00137        && fflush(sp->_ofp) != 0
00138        && errno == EBADF) {
00139        free(sp->_setbuf);
00140     }
00141 
00142     free(sp);
00143 
00144     /*
00145      * If this was the current screen, reset everything that the
00146      * application might try to use (except cur_term, which may have
00147      * multiple references in different screens).
00148      */
00149     if (sp == SP) {
00150        curscr = 0;
00151        newscr = 0;
00152        stdscr = 0;
00153        COLORS = 0;
00154        COLOR_PAIRS = 0;
00155        _nc_set_screen(0);
00156     }
00157     returnVoid;
00158 }
00159 
00160 static ripoff_t rippedoff[5];
00161 static ripoff_t *rsp = rippedoff;
00162 #define N_RIPS SIZEOF(SP->_rippedoff)
00163 
00164 static bool
00165 no_mouse_event(SCREEN * sp GCC_UNUSED)
00166 {
00167     return FALSE;
00168 }
00169 
00170 static bool
00171 no_mouse_inline(SCREEN * sp GCC_UNUSED)
00172 {
00173     return FALSE;
00174 }
00175 
00176 static bool
00177 no_mouse_parse(int code GCC_UNUSED)
00178 {
00179     return TRUE;
00180 }
00181 
00182 static void
00183 no_mouse_resume(SCREEN * sp GCC_UNUSED)
00184 {
00185 }
00186 
00187 static void
00188 no_mouse_wrap(SCREEN * sp GCC_UNUSED)
00189 {
00190 }
00191 
00192 #if NCURSES_EXT_FUNCS && USE_COLORFGBG
00193 static char *
00194 extract_fgbg(char *src, int *result)
00195 {
00196     char *dst = 0;
00197     long value = strtol(src, &dst, 0);
00198 
00199     if (dst == 0) {
00200        dst = src;
00201     } else if (value >= 0) {
00202        *result = value;
00203     }
00204     while (*dst != 0 && *dst != ';')
00205        dst++;
00206     if (*dst == ';')
00207        dst++;
00208     return dst;
00209 }
00210 #endif
00211 
00212 NCURSES_EXPORT(int)
00213 _nc_setupscreen(short slines, short const scolumns, FILE *output)
00214 /* OS-independent screen initializations */
00215 {
00216     int bottom_stolen = 0;
00217     int i;
00218 
00219     T((T_CALLED("_nc_setupscreen(%d, %d, %p)"), slines, scolumns, output));
00220     assert(SP == 0);        /* has been reset in newterm() ! */
00221     if (!_nc_alloc_screen())
00222        returnCode(ERR);
00223 
00224     SP->_next_screen = _nc_screen_chain;
00225     _nc_screen_chain = SP;
00226 
00227 #ifdef __DJGPP__
00228     T(("setting output mode to binary"));
00229     fflush(output);
00230     setmode(output, O_BINARY);
00231 #endif
00232     _nc_set_buffer(output, TRUE);
00233     SP->_term = cur_term;
00234     SP->_lines = slines;
00235     SP->_lines_avail = slines;
00236     SP->_columns = scolumns;
00237     SP->_cursrow = -1;
00238     SP->_curscol = -1;
00239     SP->_nl = TRUE;
00240     SP->_raw = FALSE;
00241     SP->_cbreak = 0;
00242     SP->_echo = TRUE;
00243     SP->_fifohead = -1;
00244     SP->_endwin = TRUE;
00245     SP->_ofp = output;
00246     SP->_cursor = -1;              /* cannot know real cursor shape */
00247 
00248 #if NCURSES_NO_PADDING
00249     SP->_no_padding = getenv("NCURSES_NO_PADDING") != 0;
00250     TR(TRACE_CHARPUT | TRACE_MOVE, ("padding will%s be used",
00251                                 SP->_no_padding ? " not" : ""));
00252 #endif
00253 
00254 #if NCURSES_EXT_FUNCS
00255     SP->_default_color = FALSE;
00256     SP->_has_sgr_39_49 = FALSE;
00257 
00258     /*
00259      * Set our assumption of the terminal's default foreground and background
00260      * colors.  The curs_color man-page states that we can assume that the
00261      * background is black.  The origin of this assumption appears to be
00262      * terminals that displayed colored text, but no colored backgrounds, e.g.,
00263      * the first colored terminals around 1980.  More recent ones with better
00264      * technology can display not only colored backgrounds, but all
00265      * combinations.  So a terminal might be something other than "white" on
00266      * black (green/black looks monochrome too), but black on white or even
00267      * on ivory.
00268      *
00269      * White-on-black is the simplest thing to use for monochrome.  Almost
00270      * all applications that use color paint both text and background, so
00271      * the distinction is moot.  But a few do not - which is why we leave this
00272      * configurable (a better solution is to use assume_default_colors() for
00273      * the rare applications that do require that sort of appearance, since
00274      * is appears that more users expect to be able to make a white-on-black
00275      * or black-on-white display under control of the application than not).
00276      */
00277 #ifdef USE_ASSUMED_COLOR
00278     SP->_default_fg = COLOR_WHITE;
00279     SP->_default_bg = COLOR_BLACK;
00280 #else
00281     SP->_default_fg = C_MASK;
00282     SP->_default_bg = C_MASK;
00283 #endif
00284 
00285     /*
00286      * Allow those assumed/default color assumptions to be overridden at
00287      * runtime:
00288      */
00289     if (getenv("NCURSES_ASSUMED_COLORS") != 0) {
00290        char *p = getenv("NCURSES_ASSUMED_COLORS");
00291        int fg, bg;
00292        char sep1, sep2;
00293        int count = sscanf(p, "%d%c%d%c", &fg, &sep1, &bg, &sep2);
00294        if (count >= 1) {
00295            SP->_default_fg = (fg >= 0 && fg < max_colors) ? fg : C_MASK;
00296            if (count >= 3) {
00297               SP->_default_bg = (bg >= 0 && bg < max_colors) ? bg : C_MASK;
00298            }
00299            TR(TRACE_CHARPUT | TRACE_MOVE,
00300               ("from environment assumed fg=%d, bg=%d",
00301               SP->_default_fg,
00302               SP->_default_bg));
00303        }
00304     }
00305 #if USE_COLORFGBG
00306     /*
00307      * If rxvt's $COLORFGBG variable is set, use it to specify the assumed
00308      * default colors.  Note that rxvt (mis)uses bold colors, equating a bold
00309      * color to that value plus 8.  We'll only use the non-bold color for now -
00310      * decide later if it is worth having default attributes as well.
00311      */
00312     if (getenv("COLORFGBG") != 0) {
00313        char *p = getenv("COLORFGBG");
00314        TR(TRACE_CHARPUT | TRACE_MOVE, ("decoding COLORFGBG %s", p));
00315        p = extract_fgbg(p, &(SP->_default_fg));
00316        p = extract_fgbg(p, &(SP->_default_bg));
00317        if (*p)                     /* assume rxvt was compiled with xpm support */
00318            p = extract_fgbg(p, &(SP->_default_bg));
00319        TR(TRACE_CHARPUT | TRACE_MOVE, ("decoded fg=%d, bg=%d",
00320                                    SP->_default_fg, SP->_default_bg));
00321        if (SP->_default_fg >= max_colors) {
00322            if (set_a_foreground != ABSENT_STRING
00323               && !strcmp(set_a_foreground, "\033[3%p1%dm")) {
00324               set_a_foreground = "\033[3%?%p1%{8}%>%t9%e%p1%d%;m";
00325            } else {
00326               SP->_default_fg %= max_colors;
00327            }
00328        }
00329        if (SP->_default_bg >= max_colors) {
00330            if (set_a_background != ABSENT_STRING
00331               && !strcmp(set_a_background, "\033[4%p1%dm")) {
00332               set_a_background = "\033[4%?%p1%{8}%>%t9%e%p1%d%;m";
00333            } else {
00334               SP->_default_bg %= max_colors;
00335            }
00336        }
00337     }
00338 #endif
00339 #endif /* NCURSES_EXT_FUNCS */
00340 
00341     SP->_maxclick = DEFAULT_MAXCLICK;
00342     SP->_mouse_event = no_mouse_event;
00343     SP->_mouse_inline = no_mouse_inline;
00344     SP->_mouse_parse = no_mouse_parse;
00345     SP->_mouse_resume = no_mouse_resume;
00346     SP->_mouse_wrap = no_mouse_wrap;
00347     SP->_mouse_fd = -1;
00348 
00349     /* initialize the panel hooks */
00350     SP->_panelHook.top_panel = (struct panel *) 0;
00351     SP->_panelHook.bottom_panel = (struct panel *) 0;
00352     SP->_panelHook.stdscr_pseudo_panel = (struct panel *) 0;
00353 
00354     /*
00355      * If we've no magic cookie support, we suppress attributes that xmc
00356      * would affect, i.e., the attributes that affect the rendition of a
00357      * space.  Note that this impacts the alternate character set mapping
00358      * as well.
00359      */
00360     if (magic_cookie_glitch > 0) {
00361 
00362        SP->_xmc_triggers = termattrs() & (
00363                                          A_ALTCHARSET |
00364                                          A_BLINK |
00365                                          A_BOLD |
00366                                          A_REVERSE |
00367                                          A_STANDOUT |
00368                                          A_UNDERLINE
00369            );
00370        SP->_xmc_suppress = SP->_xmc_triggers & (chtype) ~(A_BOLD);
00371 
00372        T(("magic cookie attributes %s", _traceattr(SP->_xmc_suppress)));
00373 #if USE_XMC_SUPPORT
00374        /*
00375         * To keep this simple, suppress all of the optimization hooks
00376         * except for clear_screen and the cursor addressing.
00377         */
00378        clr_eol = 0;
00379        clr_eos = 0;
00380        set_attributes = 0;
00381 #else
00382        magic_cookie_glitch = ABSENT_NUMERIC;
00383        acs_chars = 0;
00384 #endif
00385     }
00386 
00387     /* initialize normal acs before wide, since we use mapping in the latter */
00388     _nc_init_acs();
00389 #if USE_WIDEC_SUPPORT
00390     _nc_init_wacs();
00391 
00392     SP->_screen_acs_fix = (_nc_unicode_locale() && _nc_locale_breaks_acs());
00393     {
00394        char *env = _nc_get_locale();
00395        SP->_legacy_coding = ((env == 0)
00396                           || !strcmp(env, "C")
00397                           || !strcmp(env, "POSIX"));
00398     }
00399 #endif
00400 
00401     _nc_idcok = TRUE;
00402     _nc_idlok = FALSE;
00403 
00404     _nc_windows = 0;        /* no windows yet */
00405 
00406     SP->oldhash = 0;
00407     SP->newhash = 0;
00408 
00409     T(("creating newscr"));
00410     if ((newscr = newwin(slines, scolumns, 0, 0)) == 0)
00411        returnCode(ERR);
00412 
00413     T(("creating curscr"));
00414     if ((curscr = newwin(slines, scolumns, 0, 0)) == 0)
00415        returnCode(ERR);
00416 
00417     SP->_newscr = newscr;
00418     SP->_curscr = curscr;
00419 #if USE_SIZECHANGE
00420     SP->_resize = resizeterm;
00421 #endif
00422 
00423     newscr->_clear = TRUE;
00424     curscr->_clear = FALSE;
00425 
00426     def_shell_mode();
00427     def_prog_mode();
00428 
00429     for (i = 0, rsp = rippedoff; rsp->line && (i < (int) N_RIPS); rsp++, i++) {
00430        T(("ripping off line %d at %s", i, rsp->line < 0 ? "bottom" : "top"));
00431        SP->_rippedoff[i] = rippedoff[i];
00432        if (rsp->hook) {
00433            int count = (rsp->line < 0) ? -rsp->line : rsp->line;
00434 
00435            SP->_rippedoff[i].w = newwin(count,
00436                                     scolumns,
00437                                     ((rsp->line < 0)
00438                                      ? SP->_lines_avail - count
00439                                      : 0),
00440                                     0);
00441            if (SP->_rippedoff[i].w != 0)
00442               SP->_rippedoff[i].hook(SP->_rippedoff[i].w, scolumns);
00443            else
00444               returnCode(ERR);
00445            if (rsp->line < 0)
00446               bottom_stolen += count;
00447            else
00448               SP->_topstolen += count;
00449            SP->_lines_avail -= count;
00450        }
00451        rsp->line = 0;
00452     }
00453     SP->_rip_count = i;
00454     /* reset the stack */
00455     rsp = rippedoff;
00456 
00457     T(("creating stdscr"));
00458     assert((SP->_lines_avail + SP->_topstolen + bottom_stolen) == slines);
00459     if ((stdscr = newwin(LINES = SP->_lines_avail, scolumns, 0, 0)) == 0)
00460        returnCode(ERR);
00461     SP->_stdscr = stdscr;
00462 
00463     returnCode(OK);
00464 }
00465 
00466 /* The internal implementation interprets line as the number of
00467    lines to rip off from the top or bottom.
00468    */
00469 NCURSES_EXPORT(int)
00470 _nc_ripoffline(int line, int (*init) (WINDOW *, int))
00471 {
00472     T((T_CALLED("_nc_ripoffline(%d, %p)"), line, init));
00473 
00474     if (line != 0) {
00475 
00476        if (rsp >= rippedoff + N_RIPS)
00477            returnCode(ERR);
00478 
00479        rsp->line = line;
00480        rsp->hook = init;
00481        rsp->w = 0;
00482        rsp++;
00483     }
00484 
00485     returnCode(OK);
00486 }
00487 
00488 NCURSES_EXPORT(int)
00489 ripoffline(int line, int (*init) (WINDOW *, int))
00490 {
00491     T((T_CALLED("ripoffline(%d,%p)"), line, init));
00492 
00493     if (line == 0)
00494        returnCode(OK);
00495 
00496     returnCode(_nc_ripoffline((line < 0) ? -1 : 1, init));
00497 }