/***************************************************************************
 *                                                                         *
 *   CATASTRO.C                                                            *
 *                                                                         *
 *   Copyright (c) 1987-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This is the GCOMM.LIB routine for handling controlled shutdown of     *
 *   a program if runtime circumstances make it impossible to continue.    *
 *   It is assumed in the use of this routine that a setjmp() call has     *
 *   taken place in the mainline, specifying the "disaster" jmp_buf.       *
 *                                                                         *
 *                                            - T. Stryker 2/3/92          *
 *   NT version                                                            *
 *                                            - Ilya Minkin 1/29/96        *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#ifdef GCDOS
#include "phasedbg.h"
#else
#include <windows.h>
#include <signal.h>
#include "excprprt.h"
#endif // GCDOS

#define FILREV "$Revision: 9 $"

jmp_buf disaster;                  /* master err-recovery longjmp save blk */
SHORT catact=0;                    /* catastro cnt, for ripple-effect stop */
static SHORT shofxs=1;             /* show catfix1() and catfix2()         */
static SHORT savex,savey;          /* saved cursor coords in case dbl-cat  */

static VOID dblcat(VOID);
static VOID catachk(VOID);
static VOID catamsg(GBOOL blink,CHAR *string);
static VOID dftrpt(CHAR *filnam);
static VOID pupwin(GBOOL blink);

VOID (*catvec)(VOID)=NULL;         /* callable vector for double catastro  */
VOID (*catrpt)(CHAR *)=dftrpt;     /* interceptable CATASTRO.TXT report vec*/

#ifdef GCDOS
VOID *catbpsav;                    /* catastro's saved BP location         */
#endif // GCDOS

static CHAR tmpbuf[1024];

VOID
catastro(                          /* catastrophe message display utility  */
CHAR *string,                      /*   conversion string                  */
...)                               /*   variable arguments                 */
{
     va_list ap;
#ifndef GCDOS
     CONTEXT thContext;
#endif // GCDOS

#ifdef GCDOS
     catbpsav=MK_FP(_SS,_BP);
#endif // GCDOS
     va_start(ap,string);
     dblcat();
     vsprintf(tmpbuf,string,ap);
     va_end(ap);
     catamsg(TRUE,tmpbuf);
#ifndef GCDOS
     gcdelay(3*1000);
     thContext.ContextFlags=CONTEXT_FULL;
     GetThreadContext(GetCurrentThread(),&thContext);
     printExcpReport(&thContext,tmpbuf,(VOID *)catastro,"GALCAT.OUT");
#endif // GCDOS
     cataexit();
}

VOID
memcata(VOID)                      /* out of memory catastro               */
{
#ifndef GCDOS
     CONTEXT thContext;
#endif // GCDOS

#ifdef GCDOS
     catbpsav=MK_FP(_SS,_BP);
#endif // GCDOS
     dblcat();
     shofxs=0;                     /* (to suppress catfix1/2 stuff)        */
     strcpy(tmpbuf,"There is not enough memory to continue.");
     catamsg(FALSE,tmpbuf);
     printf("Please either reduce your memory requirements\n");
     printf("or install more memory, and try again.\n");
     setatr(0x4E);
     printf("    << Press any key to proceed >>");
#ifndef GCDOS
     thContext.ContextFlags=CONTEXT_FULL;
     GetThreadContext(GetCurrentThread(),&thContext);
     printExcpReport(&thContext,tmpbuf,(VOID *)memcata,"GALCAT.OUT");
#endif // GCDOS
     getchc();
     savex=curcurx();
     savey=curcury();
     catachk();
     longjmp(disaster,49);
}

VOID
cataexit(VOID)                     /* catastrophe-exit utility             */
{
     savex=curcurx();
     savey=curcury();
     cursiz(GVIDLILCURS);
     catachk();
     longjmp(disaster,70);
}

static VOID
dblcat(VOID)                       /* check for double-catastrophe         */
{
     cursiz(GVIDLILCURS);
     if (++catact > 1) {
          setwin(0L,7+5,8+2,7+63,8+6,0);
          locate(savex,savey);
          setatr(0x4E);
#ifdef GCDOS
          printf("\n          YOU SHOULD REBOOT YOUR COMPUTER \n");
#else
          printf("\n          YOU SHOULD RESTART YOUR APPLICATION \n");
#endif // GCDOS
          cursact(1);
          locate(0,23);
          if (catvec != NULL) {
               (*catvec)();
          }
          exit(80);
     }
}

static VOID
catachk(VOID)                      /* check that longjmp(disaster) is poss */
{
#ifdef GCDOS
     if (disaster[0].j_sp == 0) {
#else
     if (disaster[0].j_esp == 0) {
#endif // GCDOS
          if (catact == 0) {
               pupwin(TRUE);
          }
          printf("\n\nUnexpected exit, no recovery method supplied...\n");
          locate(0,23);
          if (catvec != NULL) {
               (*catvec)();
          }
          exit(90);
     }
}

static VOID
catamsg(                           /* catastro. msg w/ catfix1(),catfix2() */
GBOOL blink,                       /*   make window border blink?          */
CHAR *string)                      /*   printf()-style control string      */
{
#ifdef GCDOS
     FILE *fp;
#endif // GCDOS
     CHAR *cp1,*cp2;
     CHAR *catfix1(VOID);
     CHAR *catfix2(VOID);

     pupwin(blink);
     printf("%s %s\n",ncedat(today()),nctime(now()));
     printf(string);
     printf("\n");
     savex=curcurx();
     savey=curcury();
#ifdef GCDOS
     if ((fp=fopen("GALCAT.OUT",FOPAA)) == NULL) {
          printf("(Can't open GALCAT.OUT)\n");
     }
     else {
          fprintf(fp,"\n%s %s ",ncedat(today()),nctime(now()));
          fprintf(fp,"%s",string);
          fprintf(fp,"\n");
          fclose(fp);
     }
#endif // GCDOS
     if (catact == 1 && shofxs) {
          cp1=catfix1();
          cp2=catfix2();
          if (*cp1 != '\0' || *cp2 != '\0') {
               printf("%s,%s\7\n",cp1,cp2);
          }
#ifdef GCDOS
          if ((fp=fopen("GALCAT.OUT",FOPAA)) == NULL) {
               printf("(Can't re-open GALCAT.OUT)\n");
          }
          else {
               if (*cp1 != '\0' || *cp2 != '\0') {
                    fprintf(fp,"%s,%s\n",cp1,cp2);
               }
          }
#endif // GCDOS
          savex=curcurx();
          savey=curcury();
#ifdef GCDOS
          fflush(fp);
          rptphs(fp);
          fclose(fp);
          setatr(curatr.attrib|=0x80);
          printf("                One moment please...");
          (*catrpt)("GALCAT.OUT");
          setatr(curatr.attrib&=~0x80);
          printf("\r                                    \r");
          savex=curcurx();
          savey=curcury();
#endif // GCDOS
     }
}

static VOID
dftrpt(                            /* default (*catrpt)() routine          */
CHAR *filnam)                      /*   does nothing                       */
{
     (VOID)filnam;
}

static VOID
pupwin(                            /* put up the catastro window           */
GBOOL blink)                       /*   border blinkage                    */
{
     static USHORT catawin[]={
          0x0DEDB,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,
          0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,
          0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,
          0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,
          0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,
          0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,
          0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,
          0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,0x0DEDF,
          0x0DEDF,0x0DEDF,0x0DEDB,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x0DEDB,0x0DE20,0x04EDB,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,
          0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,
          0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,
          0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,
          0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,
          0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,
          0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,
          0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,0x04EDF,
          0x04EDB,0x0DE20,0x0DEDB,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x0DEDB,0x0DE20,0x04EDB,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04EDB,0x0DE20,0x0DEDB,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x0DEDB,0x0DE20,0x04EDB,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04EDB,0x0DE20,0x0DEDB,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x0DEDB,0x0DE20,0x04EDB,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04EDB,0x0DE20,0x0DEDB,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x0DEDB,0x0DE20,0x04EDB,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04EDB,0x0DE20,0x0DEDB,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x0DEDB,0x0DE20,0x04EDB,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,0x04F20,
          0x04EDB,0x0DE20,0x0DEDB,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x0DEDB,0x0DE20,0x04EDB,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,
          0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,
          0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,
          0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,
          0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,
          0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,
          0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,
          0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,0x04EDC,
          0x04EDB,0x0DE20,0x0DEDB,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,0x00720,
          0x0DEDB,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,
          0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,
          0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,
          0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,
          0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,
          0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,
          0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,
          0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,0x0DEDC,
          0x0DEDC,0x0DEDC,0x0DEDB
     };
     SHORT i;

     for (i=0 ; i < nelems(catawin) ; i++) {
          if (!color) {
               catawin[i]&=0x8FFF;
               catawin[i]|=0x0F00;
          }
          if (!blink) {
               catawin[i]&=0x7FFF;
          }
          cvtDataIP(&catawin[i],sizeof(USHORT),sizeof(USHORT),shortFDA,
                    CVTPACKED,CVTSERVER,CHAN_NUL);
     }
     explodeto((CHAR *)catawin,0,0,66,8,7,8);
     setwin(0L,7+5,8+2,7+63,8+6,0);
     locate(7+5,8+2);
     setatr(0x4F);
}
