
/*
 * EDIT.C
 */

#include "defs.h"

Prototype int  OpenEditWindow(void);
Prototype void CloseEditWindow(void);
Prototype void HandleEditGadget(IMsg *);
Prototype void HandleSliders(IMsg *);
Prototype void UpdateEWinInfo(TplRegion *);
Prototype void selectEgad(Gadget *);
Prototype void DisableEGads(TplRegion *);
Prototype void CheckSpecial(TplRegion *, long);

Prototype Window *EWin;
Prototype long   EWinMask;

Prototype long   BufSpace;
Prototype long   MaxVal;
Prototype long   DefVal;
Prototype long   SpecFlag;

Window    *EWin;
long      EWinMask;

long  BufSpace  = 0;
long  MaxVal    = 0;
long  DefVal    = 0;
long  SpecFlag  = 0;
short checked   = 0;
short disable   = 0;
long  excl      = 0;

/***********************  OpenEditWindow()  **************************/
int
OpenEditWindow()
{
  if (DDebug)
    puts("OpenEditWindow");
  Gadget *gadgets;

  if (InitGads() == NULL)
    exit(22);

  if (DDebug)
    puts("Done InitGads");

  EWin = (Window *)OpenWindowTags(NULL,
           WA_Flags,     WFLG_DRAGBAR|
                         WFLG_DEPTHGADGET|
                         WFLG_CLOSEGADGET|
                         WFLG_SIZEGADGET|
                         WFLG_SIMPLE_REFRESH|
                          /*  WFLG_REPORTMOUSE| */
                         WFLG_ACTIVATE,

           WA_IDCMP,     IDCMP_GADGETUP|
                         IDCMP_GADGETDOWN|
                         IDCMP_MOUSEMOVE|
                         IDCMP_NEWSIZE|
                         IDCMP_MENUPICK|
                          /*  IDCMP_VANILLAKEY| */
                         IDCMP_RAWKEY|
                         IDCMP_CHANGEWINDOW|
                         IDCMP_CLOSEWINDOW|
                         IDCMP_REFRESHWINDOW|
                         IDCMP_ACTIVEWINDOW,

           WA_Left,      WLEF,
           WA_Top,       WTOP,
           WA_Width,     WWID,
           WA_Height,    WHEI,
           WA_Title,     "TPL CONTROL",
           WA_MinWidth,  32,
           WA_MinHeight, 32,
           WA_MaxWidth,  -1,
           WA_MaxHeight, -1,
           WA_AutoAdjust, 1,
           WA_PubScreen, NULL,
           WA_PubScreenFallBack, 1,
           WA_Gadgets,   EGList,
           TAG_END );

  if (EWin == NULL)
    return (-1);

  EWinMask = 1 << EWin->UserPort->mp_SigBit;
  GT_RefreshWindow(EWin, NULL);

  drawborders();
  if (DDebug)
    puts("done drawborders");

  return (1);
}

/***********************  CloseEditWindow() **************************/
void
CloseEditWindow()
{
  if (EWin)
  {
    ClearMenuStrip(EWin);
    CloseWindow(EWin);
    EWin = NULL;
  }
  FreeGads();
}

/***********************  HandleEditGadget(im)  **********************/
void
HandleEditGadget(im)
  IMsg  *im;
{
  StringInfo *si = (StringInfo *) (((Gadget *) im->IAddress)->SpecialInfo);
  short id       = ((Gadget *)im->IAddress)->GadgetID;
  long  flag     = 0;

  switch (id)
  {
  case GAD_gadgets_lv:
    if (DDebug)
      puts("GAD_gadgets_lv:");
    NewType     = im->Code;
    Menu *menu  = GMenu->NextMenu;    /*  update menu ! */

    MenuItem *item = menu->FirstItem;

    for (short i = 0; i <= 13; ++i)
    {
      if (item->Flags & CHECKED)
        item->Flags -= CHECKED;

      if (i == NewType)
        item->Flags |= CHECKED;

      item = item->NextItem;
    }
    ResetMenuStrip(EWin, GMenu);
    if (CurRegion)
      DisableEGads(CurRegion);
    else
      DisableEGads((void *)0L);
    break;

  case GAD_flags_mx:
    if (DDebug)
      printf("GAD_flags_mx: %d\n", 1L << im->Code );
    NewFlags = 1L << im->Code;
    break;

  case GAD_actions_mx:
    if (DDebug)
      puts("GAD_actions_mx:");
    DisableGadgets();
    switch (im->Code)
    {
    case ACT_NEW:
      if (DDebug)
        puts("ACT_NEW:");
      Title("Choose Place for New Gadget");
      CurState = STATE_NEWREGION;
      break;

    case ACT_COPY:
      if (DDebug)
        puts("ACT_COPY:");
      Title("Choose Gadget to Copy");
      CurState = STATE_COPYREGION;
      break;

    case ACT_MOVE:
      if (DDebug)
        puts("ACT_MOVE:");
      Title("Move to New Place");
      CurState = STATE_MOVEREGION;
      break;

    case ACT_SIZE:
      if (DDebug)
        puts("ACT_SIZE:");
      Title("Move to New Size");
      CurState = STATE_SIZEREGION;
      break;

    case ACT_EXCL:
      if (DDebug)
        puts("ACT_EXCL:");
      Title("Choose Gadget to Exclude");
      CurState = STATE_EXCLREGION;
      break;

    case ACT_DEL:
      if (DDebug)
        puts("ACT_DEL:");
      Title("Choose Gadget to Delete");
      CurState = STATE_DELREGION;
      break;

    case ACT_TEST:
      if (DDebug)
        puts("ACT_TEST:");
      Title("Test Gadgets");
      CurState = STATE_TEST;
      EnableGadgets();
      break;

    default:
      break;
    }
    break;

  case GAD_region_str:
    if (DDebug)
      puts("GAD_region_str:");
    if (CurRegion)
    {
      if (CurRegion->rg_Node.ln_Name)
        free(CurRegion->rg_Node.ln_Name);
      CurRegion->rg_Node.ln_Name = strdup(si->Buffer);
      SetCurRegion(CurRegion);
    }
    break;

  case GAD_label_str:
    if (DDebug)
      puts("GAD_label_str:");
    if (CurRegion)
    {
      if (CurRegion->rg_LabText)
        free(CurRegion->rg_LabText);
      CurRegion->rg_LabText = strdup(si->Buffer);
    }
    break;

  case GAD_default_str:
    if (DDebug)
      puts("GAD_default_str:");
    if (CurRegion)
    {
      if (CurRegion->rg_DefText)
        free(CurRegion->rg_DefText);
      CurRegion->rg_DefText = strdup(si->Buffer);
    }
    break;

  case GAD_items_str:
    if (DDebug)
      puts("GAD_items_str:");
  case GAD_items_add:
    if (DDebug)
      puts("GAD_items_add:");
    if (Buf_items_str[0] == 0)
      break;

    GT_SetGadgetAttrs(Gad_items_lv, EWin, NULL,
                      GTLV_Labels, -1,
                      TAG_END);
    MaxNode *mn;
    for (mn = GetHead(&List_items_lv); mn; mn = GetSucc(mn))
    {
      if (strcmp(Buf_items_str, mn->ln_Name) == 0)
        break;
    }
    if (mn == NULL)
    {
      AddNode(&List_items_lv, Buf_items_str, 1);
      if (CurRegion)
        GT_SetGadgetAttrs(Gad_maxval_sl, EWin, NULL,
                          GTSL_Level, ++CurRegion->rg_MaxVal,
                          TAG_END);
    }
    SortList(&List_items_lv);

    GT_SetGadgetAttrs(Gad_items_lv, EWin, NULL,
                      GTLV_Labels, &List_items_lv,
                      TAG_END);
    break;

  case GAD_items_up:
  case GAD_items_down:
    if (Buf_items_str[0] == 0)
      break;

    GT_SetGadgetAttrs(Gad_items_lv, EWin, NULL,
                      GTLV_Labels, -1,
                      TAG_END);

    SortList(&List_items_lv);

    short i = 0;
    MaxNode *mn;
    for (mn = GetHead(&List_items_lv); mn; mn = GetSucc(mn))
    {
      if (strcmp(Buf_items_str, mn->ln_Name) == 0)
      {
        Remove(mn);
        break;
      }
      ++i;
    }
    if (mn == NULL)
      break;

    if (id == GAD_items_up)
    {
      mn->ln_Pri += 2;
      --i;
    }
    else
    {
      --mn->ln_Pri;
      ++i;
    }
    Enqueue(&List_items_lv, mn);
    SortList(&List_items_lv);

    GT_SetGadgetAttrs(Gad_items_lv, EWin, NULL,
                      GTLV_Labels,    &List_items_lv,
                      GTLV_Selected,  i,
                      GTLV_Top,       ( i > 4) ? i - 4 :
                                      ((i > 3) ? i - 3 :
                                      ((i > 2) ? i - 2 :
                                      ((i > 1) ? i - 1 : 0))),
                      TAG_END);
    break;


  case GAD_items_del:
    if (DDebug)
      puts("GAD_items_del:");
    GT_SetGadgetAttrs(Gad_items_lv, EWin, NULL,
                      GTLV_Labels, -1,
                      TAG_END);
    short cnt;
    MaxNode *mn;

    for (mn = GetHead(&List_items_lv); mn; mn = GetSucc(mn))
    {
      if (strcmp(Buf_items_str, mn->ln_Name) == 0)
      {
        Remove(mn);
        free(mn->ln_Name);
        free(mn);
        if (CurRegion)
        {
          CurRegion->rg_MaxVal = (CurRegion->rg_MaxVal) ?
                                --CurRegion->rg_MaxVal  : 0;

          GT_SetGadgetAttrs(Gad_maxval_sl, EWin, NULL,
                            GTSL_Level, CurRegion->rg_MaxVal,
                            TAG_END);

          if (CurRegion->rg_DefVal > CurRegion->rg_MaxVal)
            GT_SetGadgetAttrs(Gad_defval_sl, EWin, NULL,
                              GTSL_Level, CurRegion->rg_MaxVal,
                              TAG_END);
        }
        SortList(&List_items_lv);
        break;
      }
    }

    GT_SetGadgetAttrs(Gad_items_lv, EWin, NULL,
                      GTLV_Labels, &List_items_lv,
                      TAG_END);
    break;

  case GAD_update_but: /* Update currently selected gadget from TPL CONTROL window */
    if (DDebug)
      puts("GAD_update_but:");
    if (CurRegion)
    {
      if (DDebug)
        puts("UpdateTplRegion(CurRegion)");
      UpdateTplRegion(CurRegion);
      SetCurRegion(CurRegion);
      ReMakeEverything();
      init_test();
      issaved = FALSE;
    }
    break;

  case GAD_relverify_box:
    flag = SPEC_RELVERIFY;
    break;
  case GAD_disabled_box:
    flag = SPEC_DISABLED;
    break;
  case GAD_immediate_box:
    flag = SPEC_IMMEDIATE;
    break;
  case GAD_readonly_box:
    flag = SPEC_READONLY;
    break;
  case GAD_recessed_box:
    flag = SPEC_RECESSED;
    break;
  case GAD_highlabel_box:
    flag = SPEC_HIGHLABEL;
    break;
  case GAD_vertical_box:
    flag = SPEC_VERTICAL;
    break;
  case GAD_border_box:
    flag = SPEC_BORDER;
    break;
  case GAD_checked_box:
    flag = SPEC_CHECKED;
    break;

  default:
    break;
  }

  if (flag)
  {
    if (SpecFlag & flag)
      SpecFlag -= flag;
    else
      SpecFlag |= flag;

    if (DDebug)
      printf("SpecFlag = %d\n", SpecFlag);

    if (CurRegion)
      CurRegion->rg_SpecFlags = SpecFlag;
  }
}

/***********************  HandleSliders(im);  ************************/
void
HandleSliders(IMsg *im)
{
  switch (((Gadget *)im->IAddress)->GadgetID)
  {
  case GAD_buf_space_sl:
    if (DDebug)
      puts("GAD_buf_space_sl:");
    BufSpace = im->Code;
    break;

  case GAD_defval_sl:
    if (DDebug)
      puts("GAD_defval_sl:");
    DefVal = (im->Code < MaxVal) ? im->Code : MaxVal;
    break;

  case GAD_maxval_sl:
    if (DDebug)
      puts("GAD_maxval_sl:");
    long val = im->Code;
    MaxVal   = val;

    if (DefVal > val)
      DefVal = val;

    GT_SetGadgetAttrs(Gad_defval_sl, EWin, NULL,
                      GTSL_Max,   val,
                      GTSL_Level, DefVal,
                      TAG_END);
  default:
    break;
  }
}


/***********************  UpdateEWinInfo(rg)  ************************/
void
UpdateEWinInfo(rg)
  TplRegion *rg;
{
  NewType   = rg->rg_Type;
  NewFlags  = rg->rg_Flags;
  SpecFlag  = rg->rg_SpecFlags;
  MaxVal    = rg->rg_MaxVal;
  DefVal    = rg->rg_DefVal;
  BufSpace  = rg->rg_BufSpace;

  if (DDebug)
  {
    printf("NewType   = %d\n", rg->rg_Type);
    printf("NewFlags  = %d\n", rg->rg_Flags);
    printf("SpecFlag  = %d\n", rg->rg_SpecFlags);
    printf("MaxVal    = %d\n", rg->rg_MaxVal);
    printf("DefVal    = %d\n", rg->rg_DefVal);
    printf("BufSpace  = %d\n", rg->rg_BufSpace);
  }

  GT_SetGadgetAttrs(Gad_items_lv, EWin, NULL,
                    GTLV_Labels, -1,
                    TAG_END);

  MaxNode *mn;
  while (mn = RemHead(&List_items_lv))
  {
    free(mn->ln_Name);
    free(mn);
  }
  if (rg->rg_Type == RGT_CYCLE    ||
      rg->rg_Type == RGT_LISTVIEW ||
      rg->rg_Type == RGT_MX)
  {
    for (mn = GetHead(&rg->rg_ListSet); mn; mn = GetSucc(mn))
      AddNode(&List_items_lv, mn->ln_Name, 1);
  }
  GT_SetGadgetAttrs(Gad_items_lv, EWin, NULL,
                    GTLV_Labels, &List_items_lv,
                    TAG_END);


  DisableEGads(rg);
  drawborders();
}

/***********************  selectEgad  **************************/
void
selectEgad(Gadget *gadget)
{
  if ((gadget->GadgetType & GTYP_BOOLGADGET) &&
     !(gadget->Flags      & SELECTED))
  {
    short gad_pos   = RemoveGadget(EWin, gadget);
    gadget->Flags  += SELECTED;
    AddGadget(EWin, gadget, gad_pos);
    RefreshGList(gadget, EWin, NULL, 1);

    long mx;
    if (mx = gadget->MutualExclude)
    {
      for (short i = 1; i < ALLGADS; ++i)
      {
        if (gadget->GadgetID == i)
          continue;

        Gadget *gad = Egadlist[i];
        if ((gad->GadgetType & GTYP_BOOLGADGET) &&
            (gad->Flags      & SELECTED) &&
            (mx & (1L << i)))
        {
          gad_pos      = RemoveGadget(EWin, gad);
          gad->Flags  -= SELECTED;
          AddGadget(EWin, gad, gad_pos);
          RefreshGList(gad, EWin, NULL, 1);
        }
      }
    }
  }
}


/***********************  DisableEGads()  ****************************/
void
DisableEGads(rg)
  TplRegion *rg;
{
  if (DDebug)
    return;

  excl = SPEC_EXCL;

  switch(NewType)
  {
    case RGT_BUTTON:
    case RGT_CHECKBOX:
      excl -= SPEC_CHECKED  |
              SPEC_DISABLED |
              SPEC_HIGHLABEL;
      break;

    case RGT_CYCLE:
      excl -= SPEC_DISABLED |
              SPEC_HIGHLABEL|
              SPEC_ITEM     |
              SPEC_BUFSPACE |
              SPEC_DEFVAL   ;
      break;

    case RGT_STRING:
      excl -= SPEC_DISABLED |
              SPEC_HIGHLABEL|
              SPEC_BUFSPACE |
              SPEC_DEFAULT  ;
      break;

    case RGT_INTEGER:
      excl -= SPEC_DISABLED |
              SPEC_HIGHLABEL|
              SPEC_BUFSPACE |
              SPEC_DEFVAL   ;
      break;

    case RGT_LISTVIEW:
      excl -= SPEC_READONLY |
              SPEC_HIGHLABEL|
              SPEC_BUFSPACE |
              SPEC_ITEM     |
              SPEC_DEFVAL   ;
      break;

    case RGT_NUMBER:
      excl -= SPEC_HIGHLABEL|
              SPEC_BORDER   |
              SPEC_DEFVAL   ;
      break;

    case RGT_TEXT:
      excl -= SPEC_HIGHLABEL|
              SPEC_BORDER   |
              SPEC_DEFAULT  ;
      break;

    case RGT_MX:
      excl -= SPEC_HIGHLABEL|
              SPEC_ITEM     |
              SPEC_BUFSPACE |
              SPEC_DEFVAL   ;
      break;

    case RGT_SLIDER:
    case RGT_SCROLLER:
      excl -= SPEC_HIGHLABEL|
              SPEC_VERTICAL |
              SPEC_DISABLED |
              SPEC_RELVERIFY|
              SPEC_IMMEDIATE|
              SPEC_BUFSPACE |
              SPEC_MAXVAL   |
              SPEC_DEFVAL   ;
      break;

    case RGT_BEVELBOX:
      excl -= SPEC_RECESSED;
      break;

    case RGT_PALETTE:
      excl -= SPEC_HIGHLABEL|
              SPEC_DISABLED |
              SPEC_BUFSPACE |
              SPEC_MAXVAL   |
              SPEC_DEFVAL   ;

    default:
      break;
  }

  Forbid();

  GT_SetGadgetAttrs(Gad_buf_space_sl, EWin, NULL,
                    GTSL_Level,   BufSpace,
                    GA_Disabled, (excl & SPEC_BUFSPACE)   ? TRUE : FALSE,
                    TAG_END);

  GT_SetGadgetAttrs(Gad_maxval_sl, EWin, NULL,
                    GTSL_Level,   MaxVal,
                    GA_Disabled, (excl & SPEC_MAXVAL)     ? TRUE : FALSE,
                    TAG_END);

  GT_SetGadgetAttrs(Gad_defval_sl, EWin, NULL,
                    GTSL_Max,     MaxVal,
                    GTSL_Level,   DefVal,
                    GA_Disabled, (excl & SPEC_DEFVAL)     ? TRUE : FALSE,
                    TAG_END);

  GT_SetGadgetAttrs(Gad_gadgets_lv, EWin, NULL,
                    GTLV_Selected,  NewType,
                    TAG_END);

  short flag =  (NewFlags &  1) ? 0 :
                (NewFlags &  2) ? 1 :
                (NewFlags &  4) ? 2 :
                (NewFlags &  8) ? 3 :
                (NewFlags & 16) ? 4 : -1;

  if (flag >= 0)
    GT_SetGadgetAttrs(Gad_flags_mx, EWin, NULL,
                      GTMX_Active, flag,
                      TAG_END);

  GT_SetGadgetAttrs(Gad_region_str, EWin, NULL,
                    GTST_String, (rg) ?
                                ((rg->rg_Node.ln_Name[0]) ?
                                  rg->rg_Node.ln_Name     : "") : "",
                    TAG_END);

  GT_SetGadgetAttrs(Gad_label_str, EWin, NULL,
                    GTST_String, (rg) ?
                                ((rg->rg_LabText[0]) ?
                                  rg->rg_LabText     : "") : "",
                    TAG_END);

  GT_SetGadgetAttrs(Gad_default_str, EWin, NULL,
                    GTST_String, (rg) ?
                                ((rg->rg_DefText[0]) ?
                                  rg->rg_DefText     : "") : "",
                    GA_Disabled, (excl & SPEC_DEFAULT)    ? TRUE : FALSE,
                    TAG_END);


  disable = (excl & SPEC_ITEM);

  GT_SetGadgetAttrs(Gad_items_add, EWin, NULL,
                    GA_Disabled, disable,
                    TAG_END);

  GT_SetGadgetAttrs(Gad_items_del, EWin, NULL,
                    GA_Disabled, disable,
                    TAG_END);

  GT_SetGadgetAttrs(Gad_items_up, EWin, NULL,
                    GA_Disabled, disable,
                    TAG_END);

  GT_SetGadgetAttrs(Gad_items_down, EWin, NULL,
                    GA_Disabled, disable,
                    TAG_END);

  GT_SetGadgetAttrs(Gad_items_str, EWin, NULL,
                    GA_Disabled, disable,
                    TAG_END);

  CheckSpecial(rg, SPEC_DISABLED);

  GT_SetGadgetAttrs(Gad_disabled_box, EWin, NULL,
                    GTCB_Checked, checked,
                    GA_Disabled,  disable,
                    TAG_END);

  CheckSpecial(rg, SPEC_CHECKED);

  GT_SetGadgetAttrs(Gad_checked_box, EWin, NULL,
                    GTCB_Checked, checked,
                    GA_Disabled,  disable,
                    TAG_END);

  CheckSpecial(rg, SPEC_BORDER);

  GT_SetGadgetAttrs(Gad_border_box, EWin, NULL,
                    GTCB_Checked, checked,
                    GA_Disabled,  disable,
                    TAG_END);

  CheckSpecial(rg, SPEC_VERTICAL);

  GT_SetGadgetAttrs(Gad_vertical_box, EWin, NULL,
                    GTCB_Checked, checked,
                    GA_Disabled,  disable,
                    TAG_END);

  CheckSpecial(rg, SPEC_HIGHLABEL);

  GT_SetGadgetAttrs(Gad_highlabel_box, EWin, NULL,
                    GTCB_Checked, checked,
                    GA_Disabled,  disable,
                    TAG_END);

  CheckSpecial(rg, SPEC_RECESSED);

  GT_SetGadgetAttrs(Gad_recessed_box, EWin, NULL,
                    GTCB_Checked, checked,
                    GA_Disabled,  disable,
                    TAG_END);

  CheckSpecial(rg, SPEC_READONLY);

  GT_SetGadgetAttrs(Gad_readonly_box, EWin, NULL,
                    GTCB_Checked, checked,
                    GA_Disabled,  disable,
                    TAG_END);

  CheckSpecial(rg, SPEC_IMMEDIATE);

  GT_SetGadgetAttrs(Gad_immediate_box, EWin, NULL,
                    GTCB_Checked, checked,
                    GA_Disabled,  disable,
                    TAG_END);

  CheckSpecial(rg, SPEC_RELVERIFY);

  GT_SetGadgetAttrs(Gad_relverify_box, EWin, NULL,
                    GTCB_Checked, checked,
                    GA_Disabled,  disable,
                    TAG_END);

  checked = 0;
  disable = 0;

  GT_RefreshWindow(EWin, NULL);

  Permit();
}


/***********************  CheckSpecial(rg, special) **********************/
void
CheckSpecial(rg, special)
  TplRegion *rg;
  long special;
{
  checked = (SpecFlag & special);
  disable = (excl     & special);

  if (checked && disable)
  {
    SpecFlag -= special;
    checked   = FALSE;
    return;
  }
  if (rg && !checked && !disable)
  {
    if (rg->rg_SpecFlags & special)
    {
      SpecFlag |= special;
      checked   = TRUE;
    }
  }
}
