
/*
 * CMD3.C
 *
 *      (C)Copyright 1988 by Matthew Dillon, All Rights Reserved
 *
 *  SETFONT
 *  IGNORECASE
 *  SET
 *  SETENV
 *  UNSET
 *  UNSETENV
 *  CD
 *  SAVECONFIG
 *  FGPEN
 *  TPEN
 *  BGPEN
 *  TITLE
 *  JUSTIFY
 *  UNJUSTIFY
 *  MODIFIED
 *  UNDELINE
 */

#include "defs.h"
#include <reqtools/reqtools.h>

#define nomemory()  { memoryfail = 1; }

/*
 *  SETFONT font size
 */

void do_setfont(void)
{
    FONT *font = (FONT *)GetFont(av[1], (short)atoi(av[2]));
    ED *ep = Ep;
    if (font) {
        text_sync();
        if (ep->Font)
            CloseFont(ep->Font);
        ep->Font = font;
        SetFont(ep->Win->RPort, font);
        SetRast(ep->Win->RPort, 0);
        RefreshWindowFrame(ep->Win);
        set_window_params();
        text_redisplay();
    } else {
        title("Unable to find font");
    }
}

void do_ignorecase(void)
{
    ED *ep = Ep;

    if (av[1][0]) {
        switch(av[1][1] & 0x1F) {
        case 'n'&0x1F:
            ep->IgnoreCase = 1;
            break;
        case 'f'&0x1F:
            ep->IgnoreCase = 0;
            break;
        case 'o'&0x1F:
            ep->IgnoreCase = 1 - ep->IgnoreCase;
            break;
        }
        if (ep->IgnoreCase)
            title("Case InSensitive");
        else
            title("Case Sensitive");
    }
}

/*
 *  av[1]
 */

void do_cd(void)
{
    BPTR oldlock;
    BPTR lock;

    oldlock = CurrentDir((BPTR)Ep->dirlock);
    if (lock = Lock(av[1], SHARED_LOCK)) {
        UnLock(CurrentDir(oldlock));
        Ep->dirlock = (long)lock;
    } else {
        CurrentDir(oldlock);
        Abortcommand = 1;
        title("Unable to CD");
    }
}

/*
 *  VARIABLE SUPPORT!
 */

#define VARS    struct _VARS
VARS {
    MNODE   Node;
    char    *Name;
    char    *Str;
};

static MLIST SList = { (MNODE *)&SList.mlh_Tail, NULL, (MNODE *)&SList.mlh_Head };

void do_set(void)
{
    VARS *v;
    void do_unset();

    do_unset();
    if (v = malloc(sizeof(VARS))) {
        if (v->Name = malloc(strlen(av[1])+1)) {
            if (v->Str = malloc(strlen(av[2])+1)) {
                AddHead((LIST *)&SList, (NODE *)v);
                strcpy(v->Name, av[1]);
                strcpy(v->Str , av[2]);
                return;
            }
            free(v->Name);
        }
        free(v);
    }
    nomemory();
}

void do_setenv(void)
{
    SetDEnv(av[1], av[2]);
}

void do_unset(void)
{
    VARS *v;

    for (v = (VARS *)SList.mlh_Head; v->Node.mln_Succ; v = (VARS *)v->Node.mln_Succ) {
        if (strcmp(v->Name, av[1]) == 0) {
            Remove((NODE *)v);
            free(v);
            free(v->Name);
            free(v->Str);
            break;
        }
    }
}

void do_unsetenv(void)
{
    char *ptr = (char *)av[1];
    char *tmp = malloc(4+strlen(ptr)+1);

    if (tmp) {
        strcpy(tmp, "ENV:");
        strcat(tmp, ptr);
        mountrequest(0);
        DeleteFile(tmp);
        mountrequest(1);
        free(tmp);
    }
}

/*
 *  Search (1) internal list, (2) enviroment, (3) macros.  The variable
 *  is allocated with malloc().  NULL if not found.  ENV: need not exist.
 */

char *getvar(char *find)
{
    char *str = NULL;
    {
        VARS *v;

        for (v = (VARS *)SList.mlh_Head; v->Node.mln_Succ; v = (VARS *)v->Node.mln_Succ) {
            if (strcmp(v->Name, find) == 0) {
                if (str = malloc(strlen(v->Str)+1)) {
                    strcpy(str, v->Str);
                    return(str);
                }
            }
        }
    }

    mountrequest(0);
    str = (char *)GetDEnv(find);
    mountrequest(1);
    if (str)
        return(str);

    if ((str = keyspectomacro(find)) || (str = menutomacro(find))) {
        char *ptr = malloc(strlen(str)+1);
        if (ptr) {
            strcpy(ptr, str);
            return(ptr);
        }
    }
    return(NULL);
}

void do_col(void)
{
    int col;

    {
        char *ptr = av[1];

        switch(*ptr) {
        case '+':
            col = text_colno() + atoi(ptr + 1);
            if (col > 254)
                col = 254;
            break;
        case '-':
            col = text_colno() + atoi(ptr);
            if (col < 0)
                col = 0;
            break;
        default:
            col = atoi(ptr) - 1;
            break;
        }
    }
    if (col > 254 || col < 0) {
        Abortcommand = 1;
        return;
    }
    while (Clen < col)
        Current[Clen++] = ' ';
    Current[Clen] = 0;
    Ep->Column = col;
    if (Ep->Column - Ep->Topcolumn >= Columns || Ep->Column < Ep->Topcolumn)
        text_sync();
}

void do_saveconfig(void)
{
    ED *ep = Ep;
    FILE *fi;

    if (ep->iconmode == 0) {
        WIN *win = ep->Win;
        ep->Winx      = win->LeftEdge;
        ep->Winy      = win->TopEdge;
        ep->Winwidth  = win->Width;
        ep->Winheight = win->Height;
    }

    if (fi = fopen("ENVARC:dme.config", "w")) {
        fwrite(&ep->BeginConfig, (char *)&ep->EndConfig - (char *)&ep->BeginConfig, 1, fi);
        fclose(fi);
    }
}

void loadconfig(ED *ep)
{
    FILE *fi;
    char buf[10];

    if (fi = fopen("ENVARC:dme.config", "r")) {
        fread(&ep->BeginConfig, (char *)&ep->EndConfig - (char *)&ep->BeginConfig, 1, fi);
        fclose(fi);
    }
}

/* Now all color set routines redraw the text */

void do_fgpen(void)
{
    ED *ep = Ep;

    ep->FGPen = atoi(av[1]);
    text_redisplay();
}

void do_tpen(void)
{
    ED *ep = Ep;

    ep->TPen = atoi(av[1]);
    text_redisplay();
}

void do_bgpen(void)
{
    ED *ep = Ep;

    ep->BGPen = atoi(av[1]);
    text_redisplay();
}

void do_hgpen(void)
{
    ED *ep = Ep;

    ep->HGPen = atoi(av[1]);
    text_redisplay();
}

/* New: 06/94 Karl Lukas */

void do_hgbgpen(void)
{
    ED *ep = Ep;

    ep->HGBGPen = atoi(av[1]);
    text_redisplay();
}

/*
 *  Commands submitted by Markus Wenzel
 */

void do_undeline(void)
{
   do_insline();
   text_load();
   strcpy(Current, Deline);
   text_sync();
   text_displayseg(Ep->Line - Ep->Topline, 1);
}


void do_modified(void)
{
    register ED *ep = Ep;

    if (av[1][0]) {
        switch(av[1][1] & 0x1F) {
        case 'n' & 0x1F:
            ep->Modified = 1;
            break;
        case 'f' & 0x1F:
            ep->Modified = 0;
            break;
        case 'o' & 0x1F:
            ep->Modified = ep->Modified ? 0 : 1;
            break;
        }
    }
}


void do_unjustify(void)
{
    short i, j, waswhite = FALSE;
    ubyte c;


    for (i = 0; Current[i] == ' '; i++);
    for (j = i; Current[i]; i++) {
        c = Current[j] = Current[i];
        if (c != ' ' || !waswhite)
            j++;
        waswhite = (c == ' ');

    }
    Current[j] = 0;

    if (i != j) {
        text_sync();
        text_redisplaycurrline();
    }
}


void do_justify(void)
{
    ED *ep = Ep;
    short firstnb, lastnb, i, n, fill, c, sp;
    short changed = FALSE;


    switch(av[1][0]) {
    case 'c':
        break;
    case 'f':
        firstnb = firstns(Current);
        lastnb = lastns(Current);
        if (firstnb < lastnb && ep->Margin < 255) {
            n = 0;
            i = firstnb;
            while (i <= lastnb) {
                while ((c = Current[i]) && c != ' ')
                    i++;
                if (i <= lastnb) {
                    n++;
                    while (Current[i] == ' ')
                        i++;
                }
            }
            fill = ep->Margin - lastnb - 1;
            i = firstnb;
            Current[lastnb + 1] = 0;
            if (n > 0 && fill > 0)
                changed = TRUE;
            while (n > 0 && fill > 0 && Current[i]) {
                while ((c = Current[i]) && c != ' ')
                    i++;
                sp = fill / n;
                movmem(&Current[i], &Current[i + sp], strlen(&Current[i]) + 1);
                memset(&Current[i], ' ', sp);
                while (Current[i] == ' ')
                    i++;
                fill -= sp;
                n--;
            }
        }
        break;
    default:
        break;
    }

    if (changed) {
        text_sync();
        text_redisplaycurrline();
    }
}


void do_title(void)
{
    static ubyte wtitle[256];

    strncpy(wtitle, av[1], 255);
    wtitle[255] = 0;
    title(wtitle);
}

void do_space(void)
{
    ED *ep = Ep;
    int insmode = ep->Insertmode;

    ep->Insertmode = 1;
    text_write(" ");
    ep->Insertmode = insmode;
}

/* MMW 1.42 */
void do_sizewindow(void)
{
    WIN *win = Ep->Win;
    struct NewWindow nw;
    int mdx, mdy;

    GeometryToNW(av[1], &nw);

    if (nw.LeftEdge + nw.Width <= win->WScreen->Width &&
        nw.TopEdge + nw.Height <= win->WScreen->Height &&
        nw.Width >= win->MinWidth &&
        nw.Height >= win->MinHeight) {

        mdx = nw.LeftEdge - win->LeftEdge;
        mdy = nw.TopEdge - win->TopEdge;
        if (mdx > 0)
            mdx = 0;
        if (mdy > 0)
            mdy = 0;

        MoveWindow(win, mdx, mdy);
        SizeWindow(win, nw.Width - win->Width, nw.Height - win->Height);
        MoveWindow(win, nw.LeftEdge - win->LeftEdge, nw.TopEdge - win->TopEdge);
    }
}


void do_reqparcol(void)
{
   struct TagItem taglist[3];
   ULONG number = Ep->WWCol;

   if (! ReqToolsBase)
   {
      title("No reqtools.library");
      return;
   }
   taglist[0].ti_Tag = RTGL_Min;
   taglist[0].ti_Data = 0;
   taglist[1].ti_Tag = RTGL_Max;
   taglist[1].ti_Data = Ep->Margin - 1;
   taglist[2].ti_Tag = TAG_DONE;
   taglist[2].ti_Data = 0;

   if (rtGetLongA(&number, "Left margin", NULL, taglist))
      Ep->WWCol = number;
}

void do_reqmargin(void)
{
   TagItem taglist[3];
   ULONG number = Ep->Margin;

   if (! ReqToolsBase)
   {
      title("No reqtools.library");
      return;
   }
   taglist[0].ti_Tag = RTGL_Min;
   taglist[0].ti_Data = Ep->WWCol + 1;
   taglist[1].ti_Tag = RTGL_Max;
   taglist[1].ti_Data = 255;
   taglist[2].ti_Tag = TAG_DONE;
   taglist[2].ti_Data = 0;

   if (rtGetLongA(&number, "Right margin", NULL, taglist))
      Ep->Margin = number;
}

void do_reqgoto(void)
{
   TagItem taglist[3];
   ULONG number = Ep->Line + 1;
   char buf[10];
   if (! ReqToolsBase)
   {
      title("No reqtools.library");
      return;
   }
   taglist[0].ti_Tag = RTGL_Min;
   taglist[0].ti_Data = 0;
   taglist[1].ti_Tag = RTGL_Max;
   taglist[1].ti_Data = Ep->Lines - 1;
   taglist[2].ti_Tag = TAG_DONE;
   taglist[2].ti_Data = 0;

   if (rtGetLongA(&number, "Goto line", NULL, taglist))
   {
      sprintf(buf, "%ld", number);
      av[1] = buf;
      do_goto();
   }
}

void do_reqtabstop(void)
{
   TagItem taglist[3];
   ULONG number = Ep->Tabstop;

   if (! ReqToolsBase)
   {
      title("No reqtools.library");
      return;
   }
   taglist[0].ti_Tag = RTGL_Min;
   taglist[0].ti_Data = 1;
   taglist[1].ti_Tag = RTGL_Max;
   taglist[1].ti_Data = 255;
   taglist[2].ti_Tag = TAG_DONE;
   taglist[2].ti_Data = 0;

   if (rtGetLongA(&number, "Set tabwidth", NULL, taglist))
      Ep->Tabstop = number;
}

