screen.c revision 19304
119304Speter/*- 219304Speter * Copyright (c) 1993, 1994 319304Speter * The Regents of the University of California. All rights reserved. 419304Speter * Copyright (c) 1993, 1994, 1995, 1996 519304Speter * Keith Bostic. All rights reserved. 619304Speter * 719304Speter * See the LICENSE file for redistribution information. 819304Speter */ 919304Speter 1019304Speter#include "config.h" 1119304Speter 1219304Speter#ifndef lint 1319304Speterstatic const char sccsid[] = "@(#)screen.c 10.15 (Berkeley) 9/15/96"; 1419304Speter#endif /* not lint */ 1519304Speter 1619304Speter#include <sys/types.h> 1719304Speter#include <sys/queue.h> 1819304Speter#include <sys/time.h> 1919304Speter 2019304Speter#include <bitstring.h> 2119304Speter#include <errno.h> 2219304Speter#include <limits.h> 2319304Speter#include <stdio.h> 2419304Speter#include <stdlib.h> 2519304Speter#include <string.h> 2619304Speter#include <unistd.h> 2719304Speter 2819304Speter#include "common.h" 2919304Speter#include "../vi/vi.h" 3019304Speter 3119304Speter/* 3219304Speter * screen_init -- 3319304Speter * Do the default initialization of an SCR structure. 3419304Speter * 3519304Speter * PUBLIC: int screen_init __P((GS *, SCR *, SCR **)); 3619304Speter */ 3719304Speterint 3819304Speterscreen_init(gp, orig, spp) 3919304Speter GS *gp; 4019304Speter SCR *orig, **spp; 4119304Speter{ 4219304Speter SCR *sp; 4319304Speter size_t len; 4419304Speter 4519304Speter *spp = NULL; 4619304Speter CALLOC_RET(orig, sp, SCR *, 1, sizeof(SCR)); 4719304Speter *spp = sp; 4819304Speter 4919304Speter/* INITIALIZED AT SCREEN CREATE. */ 5019304Speter sp->id = ++gp->id; 5119304Speter sp->refcnt = 1; 5219304Speter 5319304Speter sp->gp = gp; /* All ref the GS structure. */ 5419304Speter 5519304Speter sp->ccnt = 2; /* Anything > 1 */ 5619304Speter 5719304Speter /* 5819304Speter * XXX 5919304Speter * sp->defscroll is initialized by the opts_init() code because 6019304Speter * we don't have the option information yet. 6119304Speter */ 6219304Speter 6319304Speter CIRCLEQ_INIT(&sp->tiq); 6419304Speter 6519304Speter/* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */ 6619304Speter if (orig == NULL) { 6719304Speter sp->searchdir = NOTSET; 6819304Speter } else { 6919304Speter /* Alternate file name. */ 7019304Speter if (orig->alt_name != NULL && 7119304Speter (sp->alt_name = strdup(orig->alt_name)) == NULL) 7219304Speter goto mem; 7319304Speter 7419304Speter /* Last executed at buffer. */ 7519304Speter if (F_ISSET(orig, SC_AT_SET)) { 7619304Speter F_SET(sp, SC_AT_SET); 7719304Speter sp->at_lbuf = orig->at_lbuf; 7819304Speter } 7919304Speter 8019304Speter /* Retain searching/substitution information. */ 8119304Speter sp->searchdir = orig->searchdir == NOTSET ? NOTSET : FORWARD; 8219304Speter if (orig->re != NULL && (sp->re = 8319304Speter v_strdup(sp, orig->re, orig->re_len)) == NULL) 8419304Speter goto mem; 8519304Speter sp->re_len = orig->re_len; 8619304Speter if (orig->subre != NULL && (sp->subre = 8719304Speter v_strdup(sp, orig->subre, orig->subre_len)) == NULL) 8819304Speter goto mem; 8919304Speter sp->subre_len = orig->subre_len; 9019304Speter if (orig->repl != NULL && (sp->repl = 9119304Speter v_strdup(sp, orig->repl, orig->repl_len)) == NULL) 9219304Speter goto mem; 9319304Speter sp->repl_len = orig->repl_len; 9419304Speter if (orig->newl_len) { 9519304Speter len = orig->newl_len * sizeof(size_t); 9619304Speter MALLOC(sp, sp->newl, size_t *, len); 9719304Speter if (sp->newl == NULL) { 9819304Spetermem: msgq(orig, M_SYSERR, NULL); 9919304Speter goto err; 10019304Speter } 10119304Speter sp->newl_len = orig->newl_len; 10219304Speter sp->newl_cnt = orig->newl_cnt; 10319304Speter memcpy(sp->newl, orig->newl, len); 10419304Speter } 10519304Speter 10619304Speter if (opts_copy(orig, sp)) 10719304Speter goto err; 10819304Speter 10919304Speter F_SET(sp, F_ISSET(orig, SC_EX | SC_VI)); 11019304Speter } 11119304Speter 11219304Speter if (ex_screen_copy(orig, sp)) /* Ex. */ 11319304Speter goto err; 11419304Speter if (v_screen_copy(orig, sp)) /* Vi. */ 11519304Speter goto err; 11619304Speter 11719304Speter *spp = sp; 11819304Speter return (0); 11919304Speter 12019304Spetererr: screen_end(sp); 12119304Speter return (1); 12219304Speter} 12319304Speter 12419304Speter/* 12519304Speter * screen_end -- 12619304Speter * Release a screen, no matter what had (and had not) been 12719304Speter * initialized. 12819304Speter * 12919304Speter * PUBLIC: int screen_end __P((SCR *)); 13019304Speter */ 13119304Speterint 13219304Speterscreen_end(sp) 13319304Speter SCR *sp; 13419304Speter{ 13519304Speter int rval; 13619304Speter 13719304Speter /* If multiply referenced, just decrement the count and return. */ 13819304Speter if (--sp->refcnt != 0) 13919304Speter return (0); 14019304Speter 14119304Speter /* 14219304Speter * Remove the screen from the displayed queue. 14319304Speter * 14419304Speter * If a created screen failed during initialization, it may not 14519304Speter * be linked into the chain. 14619304Speter */ 14719304Speter if (sp->q.cqe_next != NULL) 14819304Speter CIRCLEQ_REMOVE(&sp->gp->dq, sp, q); 14919304Speter 15019304Speter /* The screen is no longer real. */ 15119304Speter F_CLR(sp, SC_SCR_EX | SC_SCR_VI); 15219304Speter 15319304Speter rval = 0; 15419304Speter#ifdef HAVE_PERL_INTERP 15519304Speter if (perl_screen_end(sp)) /* End perl. */ 15619304Speter rval = 1; 15719304Speter#endif 15819304Speter if (v_screen_end(sp)) /* End vi. */ 15919304Speter rval = 1; 16019304Speter if (ex_screen_end(sp)) /* End ex. */ 16119304Speter rval = 1; 16219304Speter 16319304Speter /* Free file names. */ 16419304Speter { char **ap; 16519304Speter if (!F_ISSET(sp, SC_ARGNOFREE) && sp->argv != NULL) { 16619304Speter for (ap = sp->argv; *ap != NULL; ++ap) 16719304Speter free(*ap); 16819304Speter free(sp->argv); 16919304Speter } 17019304Speter } 17119304Speter 17219304Speter /* Free any text input. */ 17319304Speter if (sp->tiq.cqh_first != NULL) 17419304Speter text_lfree(&sp->tiq); 17519304Speter 17619304Speter /* Free alternate file name. */ 17719304Speter if (sp->alt_name != NULL) 17819304Speter free(sp->alt_name); 17919304Speter 18019304Speter /* Free up search information. */ 18119304Speter if (sp->re != NULL) 18219304Speter free(sp->re); 18319304Speter if (F_ISSET(sp, SC_RE_SEARCH)) 18419304Speter regfree(&sp->re_c); 18519304Speter if (sp->subre != NULL) 18619304Speter free(sp->subre); 18719304Speter if (F_ISSET(sp, SC_RE_SUBST)) 18819304Speter regfree(&sp->subre_c); 18919304Speter if (sp->repl != NULL) 19019304Speter free(sp->repl); 19119304Speter if (sp->newl != NULL) 19219304Speter free(sp->newl); 19319304Speter 19419304Speter /* Free all the options */ 19519304Speter opts_free(sp); 19619304Speter 19719304Speter /* Free the screen itself. */ 19819304Speter free(sp); 19919304Speter 20019304Speter return (rval); 20119304Speter} 20219304Speter 20319304Speter/* 20419304Speter * screen_next -- 20519304Speter * Return the next screen in the queue. 20619304Speter * 20719304Speter * PUBLIC: SCR *screen_next __P((SCR *)); 20819304Speter */ 20919304SpeterSCR * 21019304Speterscreen_next(sp) 21119304Speter SCR *sp; 21219304Speter{ 21319304Speter GS *gp; 21419304Speter SCR *next; 21519304Speter 21619304Speter /* Try the display queue, without returning the current screen. */ 21719304Speter gp = sp->gp; 21819304Speter for (next = gp->dq.cqh_first; 21919304Speter next != (void *)&gp->dq; next = next->q.cqe_next) 22019304Speter if (next != sp) 22119304Speter break; 22219304Speter if (next != (void *)&gp->dq) 22319304Speter return (next); 22419304Speter 22519304Speter /* Try the hidden queue; if found, move screen to the display queue. */ 22619304Speter if (gp->hq.cqh_first != (void *)&gp->hq) { 22719304Speter next = gp->hq.cqh_first; 22819304Speter CIRCLEQ_REMOVE(&gp->hq, next, q); 22919304Speter CIRCLEQ_INSERT_HEAD(&gp->dq, next, q); 23019304Speter return (next); 23119304Speter } 23219304Speter return (NULL); 23319304Speter} 234