/* config routines for PlotMap */

#include "PlotMap.h"

#define CFG_SHIRES 1          /* config window gadget ID */
#define CFG_LACE 2
#define CFG_OVERSCAN 3
#define CFG_MODE 4
#define CFG_DEPTH 5
#define CFG_LOADMAP_MIN 11
#define CFG_LOADMAP_MAX 16
#define CFG_FLOOD_FILL 20
#define CFG_SAVE 30
#define CFG_USE 31

#define MAX_MODE 1      /* PAL, NTSC */

/********** externals **********/

extern struct TextAttr myfont;
extern struct NewMenu menu_data[];
extern double act_vfactor;

extern void close_all(char *, int);

/********** Variablen, Daten **********/

static struct Window *cfg_wd;

struct Rectangle rect;
ULONG scr_displayid, scr_overscan;
static char config_filename[] = "PlotMap.config";
struct config config =              /* (default) configuration */
{
   4, FALSE, TRUE, FALSE, 0,  /* Depth, SuperHires, Lace, Overscan, mode */
   "topaz.font", 9,                 /* fontname, fontsize */
   { 0x569, 0xfff, 0x000, 0x0c0,    /* colormap */
     0xf00, 0x00f, 0x2df, 0xf00,
     0x0f0, 0xff0, 0x00f, 0xf0f,
     0x0ff, 0xf80, 0x444, 0x888 },
   TRUE, TRUE,                      /* cls before draw, flood fill flag */
   TRUE, TRUE, TRUE, 455, 10, /* coord_window, mousexy, degree, wdx, wdy */
   1.26,                            /* vfactor */
   DL_LOW,                          /* detail level */
   { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },   /* load map */
   { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },   /* plot map */
   0, 0, { 3, 3, 4, 4, 5, 6 },      /* background, ocean, map color */
   2, 1, 2,                         /* grid, gridhigh, shadow color */
   7, 8, 9, 10                      /* line, box, text, flood fill color */
};

static struct EasyStruct cfg_error_ES =
   {sizeof(struct EasyStruct), 0, "PlotMap error",
   "Can`t %s config file!", "Ok"};

static struct Gadget *scr_size_gad;
static struct TextAttr ta = {"topaz.font", 8, 0x00, 0x01};

static UBYTE *mode_str[] = {"PAL", "NTSC", NULL};
static UBYTE *depth_str[] = {"2 (_1)", "4 (_2)", "8 (_3)", "16 (_4)", NULL};
static UBYTE scr_size_txt[30];

/********** Routinen **********/

void save_config(void)
/* save configuration to config_filename */
{
   BPTR fhd;

   if (fhd = Open(&config_filename[0], MODE_NEWFILE))
   {
      if (Write(fhd, &config, sizeof(struct config)) != sizeof(struct config))
         EasyRequest(main_wd, &cfg_error_ES, NULL, "write");
      Close(fhd);
   }
   else
      EasyRequest(main_wd, &cfg_error_ES, NULL, "open");
}


static void adjust_scr_size_gad(void)
{
   int width, height;

   if (config.superhires)
   {
      if (config.interlace)
         scr_displayid = SUPERLACE_KEY;
      else
         scr_displayid = SUPER_KEY;
   }
   else
   {
      if (config.interlace)
         scr_displayid = HIRESLACE_KEY;
      else
         scr_displayid = HIRES_KEY;
   }

   if (config.mode == 1)
      scr_displayid |= NTSC_MONITOR_ID;
   else
      scr_displayid |= PAL_MONITOR_ID;

   if (config.overscan)
      scr_overscan = OSCAN_MAX;
   else
      scr_overscan = OSCAN_TEXT;

   if (!(QueryOverscan(scr_displayid, &rect, scr_overscan)))
      /* error handling */
      return;

   width = rect.MaxX - rect.MinX + 1;
   height = rect.MaxY - rect.MinY + 1;

   sprintf(scr_size_txt, "Screen size: %4d \327 %3d \327 %1d (%d)", width,
               height, config.scr_depth, width/8*height*config.scr_depth);

   GT_SetGadgetAttrs(scr_size_gad, cfg_wd, NULL,
         GTTX_Text,scr_size_txt,  TAG_DONE);
}


static void config_window(void)
/* open window on WB to set screen resolution/size/depth, font, etc. */
{
   struct Screen *scr;
   struct Gadget *gad, *gad_list = NULL;
   struct Gadget *shires_gad, *lace_gad, *overscan_gad, *mode_gad;
   struct Gadget *color_gad, *coastlines_gad, *islands_gad, *countries_gad;
   struct Gadget *states_gad, *lakes_gad, *rivers_gad, *flood_gad;
   struct NewGadget new_gad;
   APTR cfg_vinfo;
   int gad_left, gad_top;

   BOOL cfg_ende = FALSE;
   struct IntuiMessage *msg;
   ULONG class;
   UWORD code;

   if (!(scr = LockPubScreen(NULL)))            /* Vorbereitungen */
      close_all("Can`t lock screen", 20);
   if (!(cfg_vinfo = GetVisualInfo(scr, TAG_DONE)))
   {
      UnlockPubScreen(NULL, scr);
      close_all("Can`t get visual info", 20);
   }

   /*** Gadgets initialisieren ***/

   gad = CreateContext(&gad_list);

   gad_left = scr->WBorLeft + INTERWIDTH;
   gad_top = scr->WBorTop + scr->Font->ta_YSize + 1 + INTERHEIGHT;

   new_gad.ng_LeftEdge = gad_left;
   new_gad.ng_TopEdge = gad_top;
   new_gad.ng_Width = 0;            /* ignored by CHECKBOX_KIND */
   new_gad.ng_Height = 11;          /* init. for following gadgets */
   new_gad.ng_GadgetText = "Super_Hires";
   new_gad.ng_GadgetID = CFG_SHIRES;
   new_gad.ng_TextAttr = &ta;
   new_gad.ng_Flags = PLACETEXT_RIGHT;
   new_gad.ng_VisualInfo = cfg_vinfo;
   new_gad.ng_UserData = NULL;
   shires_gad = gad = CreateGadget(CHECKBOX_KIND, gad, &new_gad,
            GT_Underscore,'_',  GTCB_Checked,config.superhires,  TAG_DONE);

   new_gad.ng_TopEdge += 12;
   new_gad.ng_GadgetText = "Inter_lace";
   new_gad.ng_GadgetID = CFG_LACE;
   lace_gad = gad = CreateGadget(CHECKBOX_KIND, gad, &new_gad,
            GT_Underscore,'_',  GTCB_Checked,config.interlace,  TAG_DONE);

   new_gad.ng_TopEdge += 12;
   new_gad.ng_GadgetText = "_Overscan";
   new_gad.ng_GadgetID = CFG_OVERSCAN;
   overscan_gad = gad = CreateGadget(CHECKBOX_KIND, gad, &new_gad,
            GT_Underscore,'_',  GTCB_Checked,config.overscan,  TAG_DONE);

   new_gad.ng_TopEdge += 12;
   new_gad.ng_Width = 80;
   new_gad.ng_GadgetText = "_Mode";
   new_gad.ng_GadgetID = CFG_MODE;
   mode_gad = gad = CreateGadget(CYCLE_KIND, gad, &new_gad,
            GT_Underscore,'_',  GTCY_Labels,mode_str,
            GTCY_Active,config.mode,  TAG_DONE);

   new_gad.ng_LeftEdge += 145;
   new_gad.ng_TopEdge = gad_top;
   new_gad.ng_Width = 0;
   new_gad.ng_GadgetText = "Colors:";
   new_gad.ng_GadgetID = 0;
   gad = CreateGadget(TEXT_KIND, gad, &new_gad,  TAG_DONE);

   new_gad.ng_LeftEdge += 65;
   new_gad.ng_TopEdge += 1;
   new_gad.ng_GadgetText = NULL;       /* obsolete, but better */
   new_gad.ng_GadgetID = CFG_DEPTH;
   color_gad = gad = CreateGadget(MX_KIND, gad, &new_gad,
            GT_Underscore,'_',  GTMX_Labels,depth_str,
            GTMX_Active,config.scr_depth-1,  GTMX_Spacing,2,  TAG_DONE);

   new_gad.ng_LeftEdge = gad_left;
   new_gad.ng_TopEdge += 36+15;
   new_gad.ng_Width = 36*8 + 8;
   new_gad.ng_GadgetID = 0;
   scr_size_gad = gad = CreateGadget(TEXT_KIND, gad, &new_gad,
            GTTX_Text,scr_size_txt,  GTTX_Border,TRUE,  TAG_DONE);

   new_gad.ng_TopEdge += 17;
   new_gad.ng_Width = 0;
   new_gad.ng_GadgetText = "Load map:";
   gad = CreateGadget(TEXT_KIND, gad, &new_gad,  TAG_DONE);

   new_gad.ng_LeftEdge += 10;
   new_gad.ng_TopEdge += 12;
   new_gad.ng_GadgetText = "_Coastlines (449802)";
   new_gad.ng_GadgetID = CFG_LOADMAP_MIN+0;
   coastlines_gad = gad = CreateGadget(CHECKBOX_KIND, gad, &new_gad,
            GT_Underscore,'_',  GTCB_Checked,config.loadmap[0],  TAG_DONE);

   new_gad.ng_TopEdge += 12;
   new_gad.ng_GadgetText = "_Islands (211026)";
   new_gad.ng_GadgetID = CFG_LOADMAP_MIN+1;
   islands_gad = gad = CreateGadget(CHECKBOX_KIND, gad, &new_gad,
            GT_Underscore,'_',  GTCB_Checked,config.loadmap[1],  TAG_DONE);

   new_gad.ng_TopEdge += 12;
   new_gad.ng_GadgetText = "Cou_ntries (134154)";
   new_gad.ng_GadgetID = CFG_LOADMAP_MIN+2;
   countries_gad = gad = CreateGadget(CHECKBOX_KIND, gad, &new_gad,
            GT_Underscore,'_',  GTCB_Checked,config.loadmap[2],  TAG_DONE);

   new_gad.ng_LeftEdge += 200;
   new_gad.ng_TopEdge -= 24;
   new_gad.ng_GadgetText = "S_tates (13554)";
   new_gad.ng_GadgetID = CFG_LOADMAP_MIN+3;
   states_gad = gad = CreateGadget(CHECKBOX_KIND, gad, &new_gad,
            GT_Underscore,'_',  GTCB_Checked,config.loadmap[3],  TAG_DONE);

   new_gad.ng_TopEdge += 12;
   new_gad.ng_GadgetText = "L_akes (90708)";
   new_gad.ng_GadgetID = CFG_LOADMAP_MIN+4;
   lakes_gad = gad = CreateGadget(CHECKBOX_KIND, gad, &new_gad,
            GT_Underscore,'_',  GTCB_Checked,config.loadmap[4],  TAG_DONE);

   new_gad.ng_TopEdge += 12;
   new_gad.ng_GadgetText = "_Rivers (169164)";
   new_gad.ng_GadgetID = CFG_LOADMAP_MIN+5;
   rivers_gad = gad = CreateGadget(CHECKBOX_KIND, gad, &new_gad,
            GT_Underscore,'_',  GTCB_Checked,config.loadmap[5],  TAG_DONE);

   new_gad.ng_LeftEdge = gad_left;
   new_gad.ng_TopEdge += 18;
   new_gad.ng_GadgetText = "_Flood fill option";
   new_gad.ng_GadgetID = CFG_FLOOD_FILL;
   flood_gad = gad = CreateGadget(CHECKBOX_KIND, gad, &new_gad,
            GT_Underscore,'_',  GTCB_Checked,config.flood_fill,  TAG_DONE);

   new_gad.ng_LeftEdge = gad_left + 20;
   new_gad.ng_TopEdge += 20;
   new_gad.ng_Width = 80;
   new_gad.ng_Height = 13;
   new_gad.ng_Flags = PLACETEXT_IN;
   new_gad.ng_GadgetText = "_Save";
   new_gad.ng_GadgetID = CFG_SAVE;
   gad = CreateGadget(BUTTON_KIND, gad, &new_gad,  GT_Underscore,'_',
            TAG_DONE);

   new_gad.ng_LeftEdge += 110;
   new_gad.ng_GadgetText = "_Use";
   new_gad.ng_GadgetID = CFG_USE;
   gad = CreateGadget(BUTTON_KIND, gad, &new_gad,  GT_Underscore,'_',
            TAG_DONE);

   if (!gad)            /* it is possible to check for errors after all */
   {                    /* gadgets have been created */
      FreeGadgets(gad_list);
      FreeVisualInfo(cfg_vinfo);
      UnlockPubScreen(NULL, scr);
      close_all("Can`t create gadget", 20);
   }

   if (!(cfg_wd = OpenWindowTags(NULL,
            WA_Left,20,  WA_Top,15,
            WA_IDCMP, BUTTONIDCMP | CHECKBOXIDCMP | MXIDCMP | CYCLEIDCMP |
               IDCMP_VANILLAKEY | IDCMP_REFRESHWINDOW,
            WA_Flags, WFLG_SIMPLE_REFRESH | WFLG_RMBTRAP | WFLG_ACTIVATE |
               WFLG_DRAGBAR | WFLG_DEPTHGADGET,
            WA_Title, "PlotMap configuration",
            WA_Gadgets, gad_list,  WA_AutoAdjust,TRUE,
            WA_InnerWidth,375,  WA_InnerHeight,165,  TAG_DONE)))
   {
      FreeGadgets(gad_list);
      FreeVisualInfo(cfg_vinfo);
      UnlockPubScreen(NULL, scr);
      close_all("Can`t open window", 20);
   }

   UnlockPubScreen(NULL, scr);            /* ein Wd. ist offen */
   GT_RefreshWindow(cfg_wd, NULL);
   adjust_scr_size_gad();

   while (!cfg_ende)
   {
      WaitPort(cfg_wd->UserPort);
      while (!cfg_ende && (msg = GT_GetIMsg(cfg_wd->UserPort)))
      {
         class = msg->Class;
         code = msg->Code;
         gad = (struct Gadget *)(msg->IAddress);
         GT_ReplyIMsg(msg);

         switch (class)
         {
            case IDCMP_GADGETDOWN:
               switch (gad->GadgetID)
               {
                  case CFG_DEPTH:
                     config.scr_depth = code+1;
                     adjust_scr_size_gad();
                     break;
               }
               break;
            case IDCMP_GADGETUP:
               switch (gad->GadgetID)
               {
                  case CFG_SHIRES:
                     config.superhires ^= TRUE;
                     adjust_scr_size_gad();
                     break;
                  case CFG_LACE:
                     config.interlace ^= TRUE;
                     adjust_scr_size_gad();
                     break;
                  case CFG_OVERSCAN:
                     config.overscan ^= TRUE;
                     adjust_scr_size_gad();
                     break;
                  case CFG_MODE:
                     config.mode = code;
                     adjust_scr_size_gad();
                     break;
                  case CFG_LOADMAP_MIN+0:
                  case CFG_LOADMAP_MIN+1:
                  case CFG_LOADMAP_MIN+2:
                  case CFG_LOADMAP_MIN+3:
                  case CFG_LOADMAP_MIN+4:
                  case CFG_LOADMAP_MIN+5:
                     config.loadmap[gad->GadgetID - CFG_LOADMAP_MIN] ^= TRUE;
                     break;
                  case CFG_FLOOD_FILL:
                     config.flood_fill ^= TRUE;
                     break;
                  case CFG_SAVE:          /* no break, SAVE + USE */
                     save_config();
                  case CFG_USE:
                     cfg_ende = TRUE;
                     break;
               } /* switch (gad_id) */
               break;
            case IDCMP_VANILLAKEY:
               switch (code)
               {
                  case 'h':
                  case 'H':
                     config.superhires ^= TRUE;
                     GT_SetGadgetAttrs(shires_gad, cfg_wd, NULL,
                           GTCB_Checked, config.superhires, TAG_DONE);
                     adjust_scr_size_gad();
                     break;
                  case 'l':
                  case 'L':
                     config.interlace ^= TRUE;
                     GT_SetGadgetAttrs(lace_gad, cfg_wd, NULL,
                           GTCB_Checked, config.interlace, TAG_DONE);
                     adjust_scr_size_gad();
                     break;
                  case 'o':
                  case 'O':
                     config.overscan ^= TRUE;
                     GT_SetGadgetAttrs(overscan_gad, cfg_wd, NULL,
                           GTCB_Checked, config.overscan, TAG_DONE);
                     adjust_scr_size_gad();
                     break;
                  case 'm':
                     config.mode++;
                     if (config.mode > MAX_MODE)
                        config.mode = 0;
                     GT_SetGadgetAttrs(mode_gad, cfg_wd, NULL,
                           GTCY_Active, config.mode, TAG_DONE);
                     adjust_scr_size_gad();
                     break;
                  case 'M':
                     config.mode--;
                     if (config.mode < 0)
                        config.mode = MAX_MODE;
                     GT_SetGadgetAttrs(mode_gad, cfg_wd, NULL,
                           GTCY_Active, config.mode, TAG_DONE);
                     adjust_scr_size_gad();
                     break;
                  case '1':
                  case '2':
                  case '3':
                  case '4':
                     config.scr_depth = code - '0';
                     adjust_scr_size_gad();
                     GT_SetGadgetAttrs(color_gad, cfg_wd, NULL,
                           GTMX_Active,config.scr_depth-1, TAG_DONE);
                     break;
                  case 'c':
                  case 'C':
                     config.loadmap[0] ^= TRUE;
                     GT_SetGadgetAttrs(coastlines_gad, cfg_wd, NULL,
                           GTCB_Checked, config.loadmap[0], TAG_DONE);
                     break;
                  case 'i':
                  case 'I':
                     config.loadmap[1] ^= TRUE;
                     GT_SetGadgetAttrs(islands_gad, cfg_wd, NULL,
                           GTCB_Checked, config.loadmap[1], TAG_DONE);
                     break;
                  case 'n':
                  case 'N':
                     config.loadmap[2] ^= TRUE;
                     GT_SetGadgetAttrs(countries_gad, cfg_wd, NULL,
                           GTCB_Checked, config.loadmap[2], TAG_DONE);
                     break;
                  case 't':
                  case 'T':
                     config.loadmap[3] ^= TRUE;
                     GT_SetGadgetAttrs(states_gad, cfg_wd, NULL,
                           GTCB_Checked, config.loadmap[3], TAG_DONE);
                     break;
                  case 'a':
                  case 'A':
                     config.loadmap[4] ^= TRUE;
                     GT_SetGadgetAttrs(lakes_gad, cfg_wd, NULL,
                           GTCB_Checked, config.loadmap[4], TAG_DONE);
                     break;
                  case 'r':
                  case 'R':
                     config.loadmap[5] ^= TRUE;
                     GT_SetGadgetAttrs(rivers_gad, cfg_wd, NULL,
                           GTCB_Checked, config.loadmap[5], TAG_DONE);
                     break;
                  case 'f':
                  case 'F':
                     config.flood_fill ^= TRUE;
                     GT_SetGadgetAttrs(flood_gad, cfg_wd, NULL,
                           GTCB_Checked, config.flood_fill, TAG_DONE);
                     break;
                  case 's':
                  case 'S':
                     save_config();       /* no break; save + use */
                  case 'u':
                  case 'U':
                     cfg_ende = TRUE;
                     break;
               }
               break;
            case IDCMP_REFRESHWINDOW:
               GT_BeginRefresh(cfg_wd);
               GT_EndRefresh(cfg_wd, TRUE);
               break;
         } /* switch (class) */
      } /* while (GT_GetIMsg()) */
   } /* while (!cfg_ende) */

   CloseWindow(cfg_wd);
   FreeGadgets(gad_list);
   FreeVisualInfo(cfg_vinfo);
}


void get_config(void)
/* load and set configuration */
{
   int i;
   BPTR fhd;
   struct config cfg;            /* temp. buffer */

   if (fhd = Open(&config_filename[0], MODE_OLDFILE))
   {
      if (Read(fhd, &cfg, sizeof(struct config)) == sizeof(struct config))
         CopyMem(&cfg, &config, sizeof(struct config));
      else
         DisplayBeep(NULL);

      Close(fhd);
   }
   else
      DisplayBeep(NULL);                  /* configfile not found */

   config_window();                       /* get config from user */

   myfont.ta_Name = config.fontname;
   myfont.ta_YSize = config.fontsize;
   act_vfactor = config.vfac;

   /* set menu (CHECKED, etc.) according to configuration */
   if (config.cls_before_draw) menu_data[16].nm_Flags |= CHECKED;
   if (config.coord_window)   menu_data[18].nm_Flags |= CHECKED;
   if (config.coord_mousexy)  menu_data[19].nm_Flags |= CHECKED;
   if (config.coord_degree)   menu_data[20].nm_Flags |= CHECKED;
   menu_data[29+config.detail_level].nm_Flags |= CHECKED;

   menu_data[43+config.bg_color].nm_Flags |= CHECKED;
   menu_data[60+config.ocean_color].nm_Flags |= CHECKED;
   for (i = 0; i < NUM_MAPS; i++)               /* init menus */
   {
      if (config.plotmap[i])
         menu_data[22+i].nm_Flags |= CHECKED;
      menu_data[78 + i*17 + config.mapcolor[i]].nm_Flags |= CHECKED;
   } /* for (i) */

   menu_data[181+config.grid_color].nm_Flags |= CHECKED;
   menu_data[198+config.gridhigh_color].nm_Flags |= CHECKED;
   menu_data[215+config.shadow_color].nm_Flags |= CHECKED;
   menu_data[233+config.line_color].nm_Flags |= CHECKED;
   menu_data[250+config.box_color].nm_Flags |= CHECKED;
   menu_data[267+config.text_color].nm_Flags |= CHECKED;
   menu_data[284+config.flood_color].nm_Flags |= CHECKED;
}

