/***************************************************************************
 *                                                                         *
 *   MDLDLL.C                                                              *
 *                                                                         *
 *   Copyright (c) 1992-1997 Galacticomm, Inc.    All rights reserved.     *
 *                                                                         *
 *   This is the WGSDRAW interface module for CNF and WGSMTREE.  This      *
 *   emulates the DLL interface through bbdedt().                          *
 *                                                                         *
 *                               - S. Brinker & T. Stryker    03/24/92     *
 *                      combined - C. Robert and R. Stein     04/15/93     *
 ***************************************************************************/

#include "gcomm.h"
#include "majorbbs.h"
#include "mdlogic.h"
#include "edtoff.h"

static
CHAR *mbuf;                        /* ptr to in-memory buffer to write to  */
static
UINT buflim,                       /* max. size of in-memory buffer region */
     bufctr;                       /* counter to keep track of current size*/
INT bbdrc;                         /* return value for bbdedt()            */
static INT accmrk;                 /* accept markers? (1 or 0)             */

CHAR *ynschc[]={"Yes","No","Save",NULL};

INT bbdedt(CHAR *command,CHAR *txtbuf,UINT sizbuf);
static VOID ex2cnf(INT c);
static VOID wrapit(INT edtrc);
static INT savecnf(VOID);
static VOID mputc(INT c);
static VOID mprintf(CHAR *what);
static VOID ex2tre(INT c);

VOID
ibdraw(alwmrk)                     /* initialize WGSDRAW                   */
INT alwmrk;                        /* allow markers? (1 or 0)              */
{
     accmrk=alwmrk;
     regedtoff(bbdedt);
}

INT
bbdedt(command,txtbuf,sizbuf)      /* WGSDRAW Editor Handler interface     */
CHAR *command;                     /* editor command line (per .MDF file)  */
CHAR *txtbuf;                      /* in-place editing buffer              */
UINT sizbuf;                       /* size of buffer (includes '\0')       */
{
     CHAR *froot,fptmp[GCMAXFNM];

     froot=fileparts(GCPART_FILE,firstwd(command),fptmp,GCMAXFNM);
     if (!(sameas("WGSDRAW",froot) || sameas("BBSDRAW",froot))) {
          return(EONOTME);
     }
     if (txtbuf == NULL) {         /* WGSMTREE interface                   */
          bbdrc=EONOCHG;
          mdmtdraw(nextwd(),0,ex2tre);
          return(bbdrc);
     }
     mbuf=txtbuf;                  /* CNF interface                        */
     buflim=sizbuf;
     inimdl();
     if (markers == NULL) {
          markers=(struct marker *)alcmem(sizeof(struct marker)*MXMARK);
     }
     mdload(1,txtbuf);
     mdmain(accmrk,ex2cnf);
     return(bbdrc);
}

static VOID
ex2cnf(c)
INT c;
{
     switch (edtkey=c) {
     case ESC:
     case ALT_X:
          mdesc();
          bbdrc=EOABORT;
          break;
     case PGDN:
          wrapit(EOPGDN);
          break;
     case PGUP:
          wrapit(EOPGUP);
          break;
     case ALT_S:
          wrapit(0);
          break;
     default:
          bbdrc=EONOCHG;
          break;
     }
}

static VOID
wrapit(edtrc)
INT edtrc;
{
     if (!xmdnow() && savecnf()) {
          xmdnow();
          bbdrc=EOSAVE+edtrc;
     }
     else {
          bbdrc=EONOCHG+edtrc;
     }
}

static INT
savecnf(VOID)
{
     INT ix,iy,fx,fy;
     INT savatr;
     CHAR *sp,*svescn;
     struct txtvar *vptr;

     bufctr=0;
     if (lastx == 0 && lasty == 0 && *scnbuf == ' ') {
          mputc('\0');
          changed=0;
          return(1);
     }
     if (!savwcs) {
          for (iy=0 ; iy <= lasty ; iy++) {
               if (is80lin(iy)) {
                    savwcs=1;
                    break;
               }
          }
     }
     if (savwcs) {
          mprintf("\33[0m\33[2J");
          savatr=0x07;
     }
     else {
          savatr=~(*(scnbuf+1));
     }
     for (iy=0,fy=0 ; iy < lasty+1 && bufctr < buflim ; iy++,fy++) {
          sp=scnbuf+gvscnoff(0,iy);
          if (is80lin(iy) && iy != lasty) {
               mprintf("\33[s");
          }
          for (ix=0,fx=0 ; ix < 80 && bufctr < buflim ; ix++,fx++,sp+=2) {
               if ((vptr=tvinxy(ix,iy)) != NULL) {
                    if (savatr != vptr->attr) {
                         mprintf(xlta2a(savatr,vptr->attr));
                         savatr=vptr->attr;
                    }
                    mputc(TVARCH);
                    mputc(justbl[(SHORT)vptr->just][0]);
                    mputc(vptr->length+32);
                    mprintf(vptr->name);
                    mputc(TVARCH);
                    fx=(ix+=vptr->length-1);
                    sp+=(vptr->length-1)*2;
                    if (iy == lasty && ix == lastx) {
                         break;
                    }
                    if (ix == 79) {
                         mprintf("\33[u\n");
                         savatr=~(*(scnbuf+1));
                    }
                    continue;
               }
               if ((*sp != ' ' && savatr != *(sp+1))
                 || (savatr&0x70) != (*(sp+1)&0x70)) {
                    mprintf(xlta2a(savatr,*(sp+1)));
                    savatr=*(sp+1);
               }
               if (iy != lasty && stoeol(ix,iy)) {
                    if (savatr&0x70) {
                         mprintf("\33[K");
                    }
                    mprintf("\n");
                    break;
               }
               mputc(*sp);
               if (iy == lasty && ix == lastx) {
                    if (ix == 0 && *sp == ' ') {
                         fx--;
                         mbuf--;        /* if only 1 space on last line,   */
                    }                   /* get rid of it:  |}              */
                    break;
               }
               if (ix == 79) {
                    mprintf("\33[u\n");
                    savatr=~(*(scnbuf+1));
               }
          }
     }
     if (finalx != -1) {
          if (fx == 79) {
               fx=-1;
               fy++;
          }
          if ((fy-finaly-1) != 0) {
               mprintf(spr("\33[%dA",fy-finaly-1));
          }
          finalx--;
          if ((fx-finalx) != 0) {
               mprintf(spr("\33[%d%c",abs(fx-finalx),
                  (fx-finalx < 0 ? 'C' : 'D')));
          }
          finalx++;
          if (finalc != savatr) {
               mprintf(xlta2a(savatr,finalc));
          }
     }
     mputc('\0');
     changed=0;
     if (bufctr >= buflim) {
          printf("\7");
          scn2mem(svescn=alcmem(GVIDSCNSIZ),0,GVIDSCNSIZ);
          explodeto(scntbl[COLSCN],53,17,76,22,30,11);
          cursiz(GVIDNOCURS);
          getchc();
          cursiz(GVIDLILCURS);
          mem2scn(svescn,0,GVIDSCNSIZ);
          free(svescn);
     }
     return(bufctr < buflim);
}

static
VOID
mputc(c)
INT c;
{
     if (bufctr++ < buflim) {
          *mbuf++=c;
     }
}

static
VOID
mprintf(what)
CHAR *what;
{
     while (*what != '\0' && bufctr++ < buflim) {
          *mbuf++=*what++;
     }
}

static VOID
ex2tre(c)
INT c;
{
     switch (c) {
     case ESC:
          mdesc();
          bbdrc=EOABORT;
          break;
     case ALT_X:
          if (!xmdnow()) {
               exitmd();
               bbdrc=EOABORT;
          }
          break;
     case ALT_S:
          savemd();
          xmdnow();
          bbdrc=EOSAVE;
          break;
     }
}

VOID
mdmtdraw(fpassd,shoid,exirou)
CHAR *fpassd;
INT shoid;
VOID (*exirou)();
{
     INT i,try1st;
     CHAR *sptr,*ptr;

     inimdl();
     if (markers == NULL) {
          markers=(struct marker *)alcmem(sizeof(struct marker)*MXMARK);
     }
     nmarks=0;
     fnmcse(fpassd);
     if ((sptr=strrchr(fpassd,'.')) == NULL) {
          try1st=IBMFIL;
     }
     else {
          switch (toupper(*(sptr+2))) {
          case 'N':
               try1st=ANSFIL;
               break;
          case 'S':
               try1st=ASCFIL;
               break;
          default:
               try1st=IBMFIL;
               break;
          }
          *sptr='\0';
     }
     if (strlen(fpassd) > 75) {
          fpassd[75]='\0';
     }
     strcpy(filnam,fpassd);
     for (i=0 ; i < 3 ; i++) {
          if (mdload(0,spr("%s.%s",fpassd,tryext[try1st][i]))) {
               break;
          }
     }
     mem2scn(scnbuf,0,GVIDSCNSIZ);
     setwin(0L,ULX,ULY,LRX,LRY,scropt);
     shwqrf();
     gcdelay(0);
     if (shoid) {
          intro();
     }
     explode(scntbl[COLSCN],28,17,51,19);
     setatr(0x1B);
     if (i == 3) {
          locate(30,18);
          printf("   No file found.");
     }
     else {
          ptr=spr("%s loaded.",(sptr=strrchr(filnam,SL)) == NULL ? filnam
                               : sptr+1);
          locate(30+(20-strlen(ptr))/2,18);
          printf("%s",ptr);
     }
     hidecursor();
     for (i=0 ; i < 350 ; i++) {
          gcdelay(10);
          if (kbhit()) {
               getchc();
               break;
          }
     }
     mdmain(accmrk,exirou);
}

VOID
exitmd(VOID)
{
     CHAR ynsans[5];

     strcpy(ynsans,"Yes");
     scn2mem(tmpbuf,0,GVIDSCNSIZ);
     explode(scntbl[ERRSCN],20,8,57,10);
     if (edtchc(51,9,ynsans,ynschc,0)) {
          switch (ynsans[0]) {
          case 'S':
               savemd();
               if (edtvalc == ESC) {
                    return;
               }
          case 'Y':
               mddone=1;
               return;
          }
     }
     rfrscn();
}

#define DOTIBM ".ibm"
#define DOTANS ".ans"
#define DOTASC ".asc"
#define DOTBIN ".bin"

VOID
savemd(VOID)
{
#define SFNSTT      1              /* save as what filename? state         */
#define SCSSTT      2              /* save with clear screen? state        */
     static CHAR sfname[40];
     CHAR *sptr;
     FILE *fp;

     explodeto(scntbl[ERRSCN],18,14,79,16,9,11);
     stzcpy(sfname,filnam,sizeof(sfname)-4);
     fnmcse(sfname);
     if ((sptr=strrchr(sfname,'.')) != NULL) {
          *sptr='\0';
     }
     if (needibm()) {
          strcat(sfname,DOTIBM);
     }
     else if (needans()) {
          strcat(sfname,DOTANS);
     }
     else {
          strcat(sfname,DOTASC);
     }
     while (edtval(30,12,sizeof(sfname),sfname,valfln,
             needupc() ? ALLCAPS : 0)) {
          if ((fp=fopen(sfname,FOPWA)) != NULL) {
               fclose(fp);
               if (strstr(sfname,DOTASC) != NULL) {
                    saveasc(sfname);
               }
               else if (strstr(sfname,DOTBIN) != NULL) {
                    savebin(sfname);
               }
               else {
                    saveans(sfname);
               }
               strcpy(filnam,sfname);
               changed=0;
               break;
          }
          printf("\7");
     }
     rfrscn();
}

INT
needibm(VOID)
{
     INT i;
     CHAR *sp;

     for (sp=scnbuf,i=0 ; i < GVIDSCNSIZ/2 ; sp+=2,i++) {
          if (*sp > 127) {
               return(1);
          }
     }
     return(0);
}

INT
needans(VOID)
{
     INT i;
     CHAR *sp;

     for (sp=scnbuf,i=0 ; i < GVIDSCNSIZ/2 ; sp+=2,i++) {
          if (*(sp+1) != 0x07 && tvinxy(i%80,i/80) == NULL) {
               return(1);
          }
     }
     return(finalx != -1);
}

VOID
savebin(savnam)
CHAR *savnam;
{
     FILE *sfp;

     if ((sfp=fopen(savnam,FOPWB)) == NULL) {
          catastro("Couldn't open %s for writing.\n",savnam);
     }
     if (fwrite(scnbuf,GVIDSCNSIZ/2,2,sfp) != 2) {
          catastro("Error writing %s\n",savnam);
     }
     fclose(sfp);
}

VOID
saveasc(savnam)
CHAR *savnam;
{
     FILE *sfp;
     CHAR *sp;
     INT ix,iy,inkm4x=-1;
     struct marker *mptr;
     struct txtvar *vptr;

     if ((sfp=fopen(savnam,FOPWB)) == NULL) {
          catastro("Couldn't open %s for writing.\n",savnam);
     }
     if (savwcs) {
          fputc(12,sfp);
     }
     for (iy=0 ; iy < 25 ; iy++) {
          sp=scnbuf+gvscnoff(0,iy);
          for (ix=0 ; ix < 80 ; ix++,sp+=2) {
               if (inkm4x == -1 && (mptr=kminxy(ix,iy)) != NULL) {
                    fputc(MARKCH,sfp);
                    fputc(mptr->select,sfp);
                    inkm4x=mptr->endx;
               }
               if ((vptr=tvinxy(ix,iy)) != NULL) {
                    fputc(TVARCH,sfp);
                    fputc(justbl[(SHORT)vptr->just][0],sfp);
                    fputc(vptr->length+32,sfp);
                    fprintf(sfp,vptr->name);
                    fputc(TVARCH,sfp);
                    ix+=vptr->length-1;
                    sp+=(vptr->length-1)*2;
                    if (inkm4x != -1 && ix >= mptr->endx
                     && (ix != 79 || mptr->startx != 0)) {
                         fputc(MARKCH,sfp);
                         inkm4x=-1;
                    }
                    if (ix == 79 && iy != 24) {
                         if (endscn(iy+1)) {
                              iy=24;
                         }
                         else {
                              fputc('\r',sfp);
                              fputc('\n',sfp);
                         }
                    }
                    continue;
               }
               if (!stoeol(ix,iy) || !(inkm4x == -1 || (mptr->startx == 0
                   && mptr->endx == 79))) {
                    fputc(*sp,sfp);
               }
               if (inkm4x != -1) {
                    if (mptr->endx == ix && (ix != 79 || mptr->startx != 0)) {
                         fputc(MARKCH,sfp);
                         inkm4x=-1;
                    }
               }
               if ((ix == 79 && iy != 24) || stoeol(ix,iy)) {
                    if (inkm4x == -1 || (mptr->startx == 0 &&
                                         mptr->endx == 79)) {
                         inkm4x=-1;
                         if (endscn(iy+1)) {
                              iy=24;
                         }
                         else {
                              fputc('\r',sfp);
                              fputc('\n',sfp);
                         }
                         if (ix != 79) {
                              break;
                         }
                    }
               }
          }
     }
     fclose(sfp);
}
