/* $NetBSD: screen.c,v 1.8 2014/01/26 21:43:45 christos Exp $ */
/*-
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
* Copyright (c) 1993, 1994, 1995, 1996
* Keith Bostic. All rights reserved.
*
* See the LICENSE file for redistribution information.
*/
if (ex_screen_copy(orig, sp)) /* Ex. */
goto err;
if (v_screen_copy(orig, sp)) /* Vi. */
goto err;
sp->cl_private = 0; /* XXX */
conv_init(orig, sp); /* XXX */
*spp = sp;
return (0);
err: screen_fini(sp);
return (1);
}
static int
screen_end1(SCR *sp, int init)
{
int rval;
/* If multiply referenced, just decrement the count and return. */
if (--sp->refcnt != 0)
return (0);
/*
* Remove the screen from the displayed queue.
*
* If a created screen failed during initialization, it may not
* be linked into the chain.
*
* XXX screen_end can be called multiple times, abuse the tqe_prev pointer
* to signal wether the tailq node is on-list.
*/
if (init && sp->q.tqe_prev) {
TAILQ_REMOVE(&sp->wp->scrq, sp, q);
sp->q.tqe_prev = NULL;
}
/* The screen is no longer real. */
F_CLR(sp, SC_SCR_EX | SC_SCR_VI);
rval = 0;
#ifdef HAVE_PERL_INTERP
if (perl_screen_end(sp)) /* End perl. */
rval = 1;
#endif
if (v_screen_end(sp)) /* End vi. */
rval = 1;
if (ex_screen_end(sp)) /* End ex. */
rval = 1;
/* Free file names. */
{ char **ap;
if (!F_ISSET(sp, SC_ARGNOFREE) && sp->argv != NULL) {
for (ap = sp->argv; *ap != NULL; ++ap)
free(*ap);
free(sp->argv);
}
}
/* Free any text input. */
if (!TAILQ_EMPTY(&sp->tiq))
text_lfree(&sp->tiq);
/* Free up search information. */
if (sp->re != NULL)
free(sp->re);
if (F_ISSET(sp, SC_RE_SEARCH))
regfree(&sp->re_c);
if (sp->subre != NULL)
free(sp->subre);
if (F_ISSET(sp, SC_RE_SUBST))
regfree(&sp->subre_c);
if (sp->repl != NULL)
free(sp->repl);
if (sp->newl != NULL)
free(sp->newl);
/* Free all the options */
opts_free(sp);
/* Free the screen itself. */
free(sp);
return (rval);
}
/*
* screen_fini --
* Release a screen, that has not been chained to the screen queues.
*
* PUBLIC: int screen_fini __P((SCR *));
*/
int
screen_fini(SCR *sp)
{
return screen_end1(sp, 0);
}
/*
* screen_end --
* Release a screen, that has been chained to the screen queues.
*
* PUBLIC: int screen_end __P((SCR *));
*/
int
screen_end(SCR *sp)
{
return screen_end1(sp, 1);
}
/*
* screen_next --
* Return the next screen in the queue.
*
* PUBLIC: SCR *screen_next __P((SCR *));
*/
SCR *
screen_next(SCR *sp)
{
GS *gp;
WIN *wp;
SCR *next;
/* Try the display queue, without returning the current screen. */
gp = sp->gp;
wp = sp->wp;
TAILQ_FOREACH(next, &wp->scrq, q)
if (next != sp)
break;
if (next != NULL)
return (next);
/* Try the hidden queue; if found, move screen to the display queue. */
if ((next = TAILQ_FIRST(&gp->hq)) != NULL) {
TAILQ_REMOVE(&gp->hq, next, q);
TAILQ_INSERT_HEAD(&wp->scrq, next, q);
next->wp = sp->wp;
return (next);
}
return (NULL);
}