219 lines
4.1 KiB
C
219 lines
4.1 KiB
C
/* $NetBSD: gs.c,v 1.2 2011/09/16 16:13:41 joerg Exp $ */
|
|
|
|
/*-
|
|
* Copyright (c) 2000
|
|
* Sven Verdoolaege. All rights reserved.
|
|
*
|
|
* See the LICENSE file for redistribution information.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/queue.h>
|
|
|
|
#include <bitstring.h>
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "../common/common.h"
|
|
#include "../perl_api/extern.h"
|
|
|
|
__dead static void perr __P((char *, char *));
|
|
|
|
/*
|
|
* gs_init --
|
|
* Create and partially initialize the GS structure.
|
|
* PUBLIC: GS * gs_init __P((char*));
|
|
*/
|
|
GS *
|
|
gs_init(char *name)
|
|
{
|
|
GS *gp;
|
|
char *p;
|
|
|
|
/* Figure out what our name is. */
|
|
if ((p = strrchr(name, '/')) != NULL)
|
|
name = p + 1;
|
|
|
|
/* Allocate the global structure. */
|
|
CALLOC_NOMSG(NULL, gp, GS *, 1, sizeof(GS));
|
|
if (gp == NULL)
|
|
perr(name, NULL);
|
|
|
|
gp->progname = name;
|
|
|
|
/* Common global structure initialization. */
|
|
/* others will need to be copied from main.c */
|
|
CIRCLEQ_INIT(&gp->dq);
|
|
|
|
CIRCLEQ_INIT(&gp->hq);
|
|
gp->noprint = DEFAULT_NOPRINT;
|
|
|
|
/* Structures shared by screens so stored in the GS structure. */
|
|
CIRCLEQ_INIT(&gp->frefq);
|
|
CIRCLEQ_INIT(&gp->exfq);
|
|
LIST_INIT(&gp->seqq);
|
|
|
|
thread_init(gp);
|
|
|
|
return (gp);
|
|
}
|
|
|
|
/*
|
|
* gs_new_win
|
|
* Create new window
|
|
* PUBLIC: WIN * gs_new_win __P((GS *gp));
|
|
*/
|
|
|
|
WIN *
|
|
gs_new_win(GS *gp)
|
|
{
|
|
WIN *wp;
|
|
|
|
CALLOC_NOMSG(NULL, wp, WIN *, 1, sizeof(*wp));
|
|
if (!wp)
|
|
return NULL;
|
|
|
|
/* Common global structure initialization. */
|
|
LIST_INIT(&wp->ecq);
|
|
LIST_INSERT_HEAD(&wp->ecq, &wp->excmd, q);
|
|
|
|
CIRCLEQ_INSERT_TAIL(&gp->dq, wp, q);
|
|
CIRCLEQ_INIT(&wp->scrq);
|
|
|
|
CIRCLEQ_INIT(&wp->dcb_store.textq);
|
|
LIST_INIT(&wp->cutq);
|
|
|
|
wp->gp = gp;
|
|
|
|
return wp;
|
|
}
|
|
|
|
/*
|
|
* win_end --
|
|
* Remove window.
|
|
*
|
|
* PUBLIC: int win_end __P((WIN *wp));
|
|
*/
|
|
int
|
|
win_end(WIN *wp)
|
|
{
|
|
SCR *sp;
|
|
|
|
CIRCLEQ_REMOVE(&wp->gp->dq, wp, q);
|
|
|
|
if (wp->ccl_sp != NULL) {
|
|
(void)file_end(wp->ccl_sp, NULL, 1);
|
|
(void)screen_end(wp->ccl_sp);
|
|
}
|
|
while ((sp = wp->scrq.cqh_first) != (void *)&wp->scrq)
|
|
(void)screen_end(sp);
|
|
|
|
/* Free key input queue. */
|
|
if (wp->i_event != NULL)
|
|
free(wp->i_event);
|
|
|
|
/* Free cut buffers. */
|
|
cut_close(wp);
|
|
|
|
/* Free default buffer storage. */
|
|
(void)text_lfree(&wp->dcb_store.textq);
|
|
|
|
#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
|
|
/* Free any temporary space. */
|
|
if (wp->tmp_bp != NULL)
|
|
free(wp->tmp_bp);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* gs_end --
|
|
* End the program, discarding screens and most of the global area.
|
|
*
|
|
* PUBLIC: void gs_end __P((GS *));
|
|
*/
|
|
void
|
|
gs_end(GS *gp)
|
|
{
|
|
MSGS *mp;
|
|
SCR *sp;
|
|
WIN *wp;
|
|
|
|
/* If there are any remaining screens, kill them off. */
|
|
while ((wp = gp->dq.cqh_first) != (void *)&gp->dq)
|
|
(void)win_end(wp);
|
|
while ((sp = gp->hq.cqh_first) != (void *)&gp->hq)
|
|
(void)screen_end(sp);
|
|
|
|
#ifdef HAVE_PERL_INTERP
|
|
perl_end(gp);
|
|
#endif
|
|
|
|
#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
|
|
{ FREF *frp;
|
|
/* Free FREF's. */
|
|
while ((frp = gp->frefq.cqh_first) != (FREF *)&gp->frefq) {
|
|
CIRCLEQ_REMOVE(&gp->frefq, frp, q);
|
|
if (frp->name != NULL)
|
|
free(frp->name);
|
|
if (frp->tname != NULL)
|
|
free(frp->tname);
|
|
free(frp);
|
|
}
|
|
}
|
|
|
|
/* Free map sequences. */
|
|
seq_close(gp);
|
|
|
|
/* Close message catalogs. */
|
|
msg_close(gp);
|
|
#endif
|
|
|
|
/* Ring the bell if scheduled. */
|
|
if (F_ISSET(gp, G_BELLSCHED))
|
|
(void)fprintf(stderr, "\07"); /* \a */
|
|
|
|
/*
|
|
* Flush any remaining messages. If a message is here, it's almost
|
|
* certainly the message about the event that killed us (although
|
|
* it's possible that the user is sourcing a file that exits from the
|
|
* editor).
|
|
*/
|
|
while ((mp = gp->msgq.lh_first) != NULL) {
|
|
(void)fprintf(stderr, "%s%.*s",
|
|
mp->mtype == M_ERR ? "ex/vi: " : "", (int)mp->len, mp->buf);
|
|
LIST_REMOVE(mp, q);
|
|
#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
|
|
free(mp->buf);
|
|
free(mp);
|
|
#endif
|
|
}
|
|
|
|
#if defined(TRACE)
|
|
/* Close tracing file descriptor. */
|
|
vtrace_end();
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
* perr --
|
|
* Print system error.
|
|
*/
|
|
static void
|
|
perr(char *name, char *msg)
|
|
{
|
|
(void)fprintf(stderr, "%s:", name);
|
|
if (msg != NULL)
|
|
(void)fprintf(stderr, "%s:", msg);
|
|
(void)fprintf(stderr, "%s\n", strerror(errno));
|
|
exit(1);
|
|
}
|