/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ /* * University Copyright- Copyright (c) 1982, 1986, 1988 * The Regents of the University of California * All Rights Reserved * * University Acknowledgment- Portions of this document are derived from * software developed by the University of California, Berkeley, and its * contributors. */ /*LINTLIBRARY*/ #include #include #include #include #include "curses_inc.h" #ifdef _VR2_COMPAT_CODE extern char _endwin; #endif /* _VR2_COMPAT_CODE */ /* 1200 is put at the 0th location since 0 is probably a mistake. */ static long baud_convert[] = { 1200, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 153600, 230400, 307200, 460800, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000, 4000000 }; static char isfilter = 0; static int _chk_trm(void); static void _forget(void); /* * newscreen sets up a terminal and returns a pointer to the terminal * structure or NULL in case of an error. The parameters are: * type: terminal type * lsize, csize, tabsize: physical sizes * infptr, outfptr: input and output stdio stream file pointers */ SCREEN * newscreen(char *type, int lsize, int csize, int tabsize, FILE *outfptr, FILE *infptr) { int old_lines = LINES, old_cols = COLS, retcode; #ifndef _IOFBF char *sobuf; #endif /* _IOBUF */ WINDOW *old_curscr = curscr; SCREEN *old = SP; TERMINAL *old_term = cur_term; #ifdef DEBUG if (outf == NULL) { outf = fopen("trace", "w"); if (outf == NULL) { perror("trace"); exit(-1); } setbuf(outf, (char *)NULL); } if (outf) fprintf(outf, "NEWTERM(type=%s, outfptr=%x %d, infptr=%x %d) " "isatty(2) %d, getenv %s\n", type, outfptr, fileno(outfptr), infptr, fileno(infptr), isatty(2), getenv("TERM")); #endif /* DEBUG */ /* read in terminfo file */ if (setupterm(type, fileno(outfptr), &retcode) != 0) goto err2; /* the max length of a multi-byte character */ _csmax = (cswidth[0] > cswidth[1]+1 ? (cswidth[0] > cswidth[2]+1 ? cswidth[0] : cswidth[2]+1) : (cswidth[1] > cswidth[2] ? cswidth[1]+1 : cswidth[2]+1)); if (_csmax > CSMAX) goto err2; /* the max length of a multi-column character */ _scrmax = _curs_scrwidth[0] > _curs_scrwidth[1] ? (_curs_scrwidth[0] > _curs_scrwidth[2] ? _curs_scrwidth[0] : _curs_scrwidth[2]) : (_curs_scrwidth[1] > _curs_scrwidth[2] ? _curs_scrwidth[1] : _curs_scrwidth[2]); /* true multi-byte/multi-column case */ _mbtrue = (_csmax > 1 || _scrmax > 1); if ((curs_errno = _chk_trm()) != -1) { (void) strcpy(curs_parm_err, cur_term->_termname); goto err2; } /* use calloc because almost everything needs to be zero */ if ((SP = (SCREEN *) calloc(1, sizeof (SCREEN))) == NULL) goto err1; SP->term_file = outfptr; SP->input_file = infptr; /* * The default is echo, for upward compatibility, but we do * all echoing in curses to avoid problems with the tty driver * echoing things during critical sections. */ SP->fl_echoit = 1; /* set some fields for cur_term structure */ (void) typeahead(fileno(infptr)); (void) tinputfd(fileno(infptr)); /* * We use LINES instead of the SP variable and a local variable because * slk_init and rip_init update the LINES value and application code * may look at the value of LINES in the function called by rip_init. */ /* LINTED */ LINES = SP->lsize = lsize > 0 ? lsize : lines; /* force the output to be buffered */ #ifdef _IOFBF (void) setvbuf(outfptr, (char *)NULL, _IOFBF, 0); #else /* _IOFBF */ if ((sobuf = malloc(BUFSIZ)) == NULL) { curs_errno = CURS_BAD_MALLOC; #ifdef DEBUG strcpy(curs_parm_err, "newscreen"); #endif /* DEBUG */ } setbuf(outfptr, sobuf); #endif /* _IOFBF */ #ifdef SYSV SP->baud = baud_convert[_BRS(PROGTTYS)]; #else /* SYSV */ SP->baud = baud_convert[_BR(PROGTTY)]; #endif /* SYSV */ /* figure out how much each terminal capability costs */ _init_costs(); /* initialize the array of alternate characters */ (void) init_acs(); SP->tcap = cur_term; /* set tty settings to something reasonable for us */ #ifdef SYSV PROGTTYS.c_lflag &= ~ECHO; PROGTTYS.c_lflag |= ISIG; PROGTTYS.c_oflag &= ~(OCRNL|ONLCR); /* why would anyone set OCRNL? */ #else /* SYSV */ PROGTTY.sg_flags &= ~(RAW|ECHO|CRMOD); #endif /* SYSV */ (void) cbreak(); /* LINTED */ COLS = SP->csize = csize > 0 ? csize : columns; if (tabsize == 0) tabsize = (init_tabs == -1) ? 8 : init_tabs; /* LINTED */ SP->tsize = (short)tabsize; #ifdef DEBUG if (outf) fprintf(outf, "LINES = %d, COLS = %d\n", LINES, COLS); #endif /* DEBUG */ if ((curscr = SP->cur_scr = newwin(LINES, COLS, 0, 0)) == NULL) goto err; SP->fl_endwin = 2; #ifdef _VR2_COMPAT_CODE _endwin = FALSE; #endif /* _VR2_COMPAT_CODE */ curscr->_sync = TRUE; /* * This will tell _quick_echo(if it's ever called), whether * _quick_echo should let wrefresh handle everything. */ if (ceol_standout_glitch || (magic_cookie_glitch >= 0) || tilde_glitch || (transparent_underline && erase_overstrike)) { curscr->_flags |= _CANT_BE_IMMED; } if (!(SP->virt_scr = newwin(LINES, COLS, 0, 0))) goto err; _virtscr = SP->virt_scr; SP->virt_scr->_clear = FALSE; /* video mark map for cookie terminals */ if (ceol_standout_glitch || (magic_cookie_glitch >= 0)) { int i, nc; char **marks; if ((marks = (char **)calloc((unsigned)LINES, sizeof (char *))) == NULL) goto err; SP->_mks = marks; nc = (COLS / BITSPERBYTE) + (COLS % BITSPERBYTE ? 1 : 0); if ((*marks = (char *)calloc((unsigned)nc * LINES, sizeof (char))) == NULL) goto err; for (i = LINES - 1; i-- > 0; ++marks) *(marks + 1) = *marks + nc; } /* hash tables for lines */ if ((SP->cur_hash = (int *)calloc((unsigned)2 * LINES, sizeof (int))) == NULL) goto err; SP->virt_hash = SP->cur_hash + LINES; /* adjust the screen size if soft labels and/or ripoffline are used */ if (_slk_init) (*_slk_init)(); if (_rip_init) (*_rip_init)(); if ((SP->std_scr = newwin(LINES, COLS, 0, 0)) == NULL) { /* free all the storage allocated above and return NULL */ err: delscreen(SP); COLS = old_cols; curscr = old_curscr; LINES = old_lines; err1: SP = old; curs_errno = CURS_BAD_MALLOC; #ifdef DEBUG strcpy(curs_parm_err, "newscreen"); #endif /* DEBUG */ err2: cur_term = old_term; return (NULL); } #ifdef DEBUG if (outf) fprintf(outf, "SP %x, stdscr %x, curscr %x\n", SP, SP->std_scr, curscr); #endif /* DEBUG */ if (((SP->imode = (enter_insert_mode && exit_insert_mode)) != 0) && ((SP->dmode = (enter_delete_mode && exit_delete_mode)) != 0)) { if (strcmp(enter_insert_mode, enter_delete_mode) == 0) SP->sid_equal = TRUE; if (strcmp(exit_insert_mode, exit_delete_mode) == 0) SP->eid_equal = TRUE; } SP->ichok = (SP->imode || insert_character || parm_ich); SP->dchok = (delete_character || parm_dch); stdscr = SP->std_scr; TABSIZE = SP->tsize; return (SP); } /* * check if terminal have capabilities to do basic cursor movements and * screen clearing */ static int _chk_trm(void) { short error_num = -1; #ifdef DEBUG if (outf) fprintf(outf, "chk_trm().\n"); #endif /* DEBUG */ if (generic_type) error_num = CURS_UNKNOWN; else { if (isfilter) { _forget(); /* Only need to move left or right on current line */ if (!(cursor_left || carriage_return || column_address || parm_left_cursor)) { goto out_stupid; } } else { if ((hard_copy || over_strike) || /* some way to move up, down, left */ (!(cursor_address) && (!((cursor_up || cursor_home) && cursor_down && (cursor_left || carriage_return)))) || (!clear_screen)) { out_stupid: error_num = CURS_STUPID; } } } return (error_num); } int filter(void) { isfilter = 1; return (OK); } /* * if (for some reason) user assumes that terminal has only one line, * disable all capabilities that deal with non-horizontal cursor movement */ static void _forget(void) { row_address = cursor_address = clear_screen = parm_down_cursor = cursor_up = cursor_down = NULL; cursor_home = carriage_return; lines = 1; }