/* canvas-type map
 *   [CV-MAP]
 *   name: <arbitrary unique name>
 *   position-itag: (position): <box-tag of an element in the main text>
 *   position-rect: (position): <rectangle (<x>+<w>,<y>+<h>) within the box-tag or the main text>
 *   disable: <whether is disabled: 1 = yes, 0 = no, or missing = enabled>
 *   img: <image file for map>
 *   homeposition: <x>,<y>
 *   velo: <moving velocitas in pixels, or missing = 1>
 *   area.<name>: (repeated for each area): <rectangle (<x>+<w>,<y>+<h>)>
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include "canvas.h"

static int type_no = 0;

struct cv_type {
  struct VG_Image *img;               /* map image */
  int x, y;                           /* start position */
  int velo;                           /* moving velocitas */
  int repw;                           /* waiting value before repeating */
  struct vgi_canvas_arrow arw_up;     /* arrow up */
  struct vgi_canvas_arrow arw_down;   /* arrow down */
  struct vgi_canvas_arrow arw_right;  /* arrow right */
  struct vgi_canvas_arrow arw_left;   /* arrow left */
  int activated;                      /* activated area (1 to maxarea) */
  int selected;                       /* selected area (1 to maxarea) */
  int maxarea;                        /* number of areas */
  struct {                            /* areas */
    char *name;                         /* name of area */
    struct VG_Rect rect;                /* rectangle */
    VG_BOOL isdisabled;                 /* whether is disabled */
  } *area;
};

void cvinit_map(struct vgi_canvas_inittype *, int);

static void * t_read_section(const struct VG_Canvas *, struct vgi_canvas_item *, const char *);
static void t_warp_mouse(struct VG_Canvas *, struct vgi_canvas_item *, int, int, int *, int *);
static void t_pre_exec(struct VG_Canvas *, struct vgi_canvas_item *);
static void t_draw(struct vgi_canvas_data *, struct vgi_canvas_item *, const char **);
static void t_destroy(struct vgi_canvas_item *);
static void t_dump(FILE *, struct vgi_canvas_item *);

static VG_BOOL canvas_map_area_disable(struct VG_Canvas *, const char *, const char *, VG_BOOL);
static const char * canvas_map_area_get_selected(struct VG_Canvas *, const char *);


void
cvinit_map(struct vgi_canvas_inittype *cvinittype, int type)
{
  if (cvinittype == NULL) { return; }

  type_no = type;

  /* cvinit */
  cvinittype->mouse_opaque = VG_FALSE;
  cvinittype->uses_cursor = VG_TRUE;
  cvinittype->read_section = t_read_section;
  cvinittype->get_itag_rect = NULL;
  cvinittype->warp_mouse = t_warp_mouse;
  cvinittype->pre_exec = t_pre_exec;
  cvinittype->draw = t_draw;
  cvinittype->destroy = t_destroy;
  cvinittype->dump = t_dump;

  /* functions */
  vg4->canvas->map_area_disable = canvas_map_area_disable;
  vg4->canvas->map_area_get_selected = canvas_map_area_get_selected;
} /* Ende cvinit_map */


static void *
t_read_section(const struct VG_Canvas *cvas, struct vgi_canvas_item *cvitem, const char *dtptr)
{
  struct SML3_gummi gm1 = SML3_GUM_INITIALIZER;
  struct cv_type *cvtype;
  char ename[64], bval[256], *pval;

  if (cvas == NULL || cvitem == NULL || dtptr == NULL) { return NULL; }

  cvtype = SML3_calloc(1, sizeof(*cvtype));

  if (canvas_get_lineval(dtptr, "img", NULL, 0, NULL, 0, bval, sizeof(bval), NULL)) {
    char rfile[VGI_PATHSIZE];
    if (*bval != '/') {
      vg4->misc->strccat(rfile, sizeof(rfile), cvas->cve.dirname, "/", bval, NULL);
    } else {
      vg4->misc->strcpy(rfile, sizeof(rfile), bval + 1);
    }
    vg4_intern_fpath_with_var(rfile, sizeof(rfile), cvas->cve.hvar);
    cvtype->img = vg4_image_load_nolist(rfile);
  }

  if (cvtype->img == NULL) {
    pwarn("canvas map-section: no map image\n");
    SML3_gumdest(&gm1);
    free(cvtype);
    return NULL;
  }

  if (canvas_get_lineval(dtptr, "velo", NULL, 0, NULL, 0, bval, sizeof(bval), NULL)) {
    vg4_intern_str_with_var(&gm1, bval, cvas->cve.hvar, NULL); pval = SML3_gumgetval(&gm1);
    cvtype->velo = atoi(pval);
  }
  if (cvtype->velo <= 0) { cvtype->velo = 1; }

  if (canvas_get_lineval(dtptr, "homeposition", NULL, 0, NULL, 0, bval, sizeof(bval), NULL)) {
    char *pt1;
    vg4_intern_str_with_var(&gm1, bval, cvas->cve.hvar, NULL); pval = SML3_gumgetval(&gm1);
    if ((pt1 = strchr(pval, ',')) != NULL) {
      int w1, h1;
      vg4->image->getsize(cvtype->img, NULL, &w1, &h1);
      cvtype->x = atoi(pval);
      if (cvtype->x > 0) { cvtype->x = -cvtype->x; }
      if (cvtype->x + w1 < cvitem->rect.w) {
        cvtype->x = cvitem->rect.w - w1;
      }
      cvtype->y = atoi(pt1 + 1);
      if (cvtype->y > 0) { cvtype->y = -cvtype->y; }
      if (cvtype->y + h1 < cvitem->rect.h) {
        cvtype->y = cvitem->rect.h - h1;
      }
    }
  }

  { char *nptr;
    nptr = (char *)dtptr;
    while (canvas_get_lineval(nptr, "area", ename, sizeof(ename), NULL, 0, bval, sizeof(bval), &nptr)) {
      int uelm = cvtype->maxarea++;
      if (uelm == 0) {
        cvtype->area = SML3_malloc(sizeof(*cvtype->area));
      } else {
        cvtype->area = SML3_realloc(cvtype->area, (uelm + 1) * sizeof(*cvtype->area));
      }
      memset(&cvtype->area[uelm], 0, sizeof(*cvtype->area));
      vg4_intern_str_with_var(&gm1, bval, cvas->cve.hvar, NULL); pval = SML3_gumgetval(&gm1);
      cvtype->area[uelm].rect = vg4_intern_read_rect(pval);
      if (IS_RECT_EMPTY(&cvtype->area[uelm].rect)) {  /* remove new element */
        if (--cvtype->maxarea == 0) {
          free(cvtype->area);
          cvtype->area = NULL;
        }
      } else {
        cvtype->area[uelm].name = SML3_strdup(ename);
        cvtype->area[uelm].isdisabled = VG_FALSE;
      }
    }
  }

  SML3_gumdest(&gm1);

  return cvtype;
} /* Ende t_read_section */


static void
t_warp_mouse(struct VG_Canvas *cvas, struct vgi_canvas_item *cvitem, int xadd, int yadd, int *xm, int *ym)
{
  struct cv_type *cvtype;
  int uelm;

  if (cvas == NULL || cvitem == NULL) { return; }
  if (xm == NULL || ym == NULL) { return; }

  cvtype = (struct cv_type *)cvitem->vstrct;
  if (cvtype == NULL) { return; }

  if (cvtype->activated > 0) {
    uelm = cvtype->activated - 1;
    *xm = xadd + cvitem->rect.x + cvtype->x + cvtype->area[uelm].rect.x + cvtype->area[uelm].rect.w / 2;
    *ym = yadd + cvitem->rect.y + cvtype->y + cvtype->area[uelm].rect.y + cvtype->area[uelm].rect.h / 2;
  } else {
    *xm = xadd + cvitem->rect.x + cvitem->rect.w / 2;
    *ym = yadd + cvitem->rect.y + cvitem->rect.h / 2;
  }
} /* Ende t_warp_mouse */


static void
t_pre_exec(struct VG_Canvas *cvas, struct vgi_canvas_item *cvitem)
{
  struct cv_type *cvtype;
  struct vgi_canvas_dirs *arw_dirs;

  if (cvas == NULL || cvitem == NULL) { return; }

  cvtype = (struct cv_type *)cvitem->vstrct;
  if (cvtype == NULL) { return; }

  /* set arrow-images */
  if (cvas->cve.arrow.user_set) {
    arw_dirs = &cvas->cve.arrow.user;
  } else if (cvas->cve.ishigh) {
    arw_dirs = &cvas->cve.arrow.high;
  } else {
    arw_dirs = &cvas->cve.arrow.low;
  }
  cvtype->arw_up.img = &arw_dirs->up;
  cvtype->arw_down.img = &arw_dirs->down;
  cvtype->arw_right.img = &arw_dirs->right;
  cvtype->arw_left.img = &arw_dirs->left;

  cvtype->activated = 0;
  cvtype->selected = 0;
} /* Ende t_pre_exec */


static void
t_draw(struct vgi_canvas_data *cvdata, struct vgi_canvas_item *cvitem, const char **selname)
{
  struct cv_type *cvtype;
  int updown, leftright;

  if (cvdata == NULL || cvdata->cvas == NULL || cvitem == NULL || selname == NULL) { return; }
  if (cvitem->rimg == NULL) { return; }
  cvtype = (struct cv_type *)cvitem->vstrct;
  if (cvtype == NULL) { return; }

  /* check if shall moving up/left (-1) or down/right (1) */
  updown = leftright = 0;
  if (cvdata->hasfocus) {  /* has focus */
    if (VGI_CVKEY_NEWPRESSED(cvdata->keys.k[CV_KEY_LEFT])) {
      leftright = -1;
      cvtype->repw = VGI_CANVAS_REPWMAX;
    }
    if (VGI_CVKEY_PRESSED(cvdata->keys.k[CV_KEY_LEFT])) {
      if (cvtype->repw > 0) { cvtype->repw--; } else { leftright = -1; }
    }

    if (VGI_CVKEY_NEWPRESSED(cvdata->keys.k[CV_KEY_RIGHT])) {
      leftright = 1;
      cvtype->repw = VGI_CANVAS_REPWMAX;
    }
    if (VGI_CVKEY_PRESSED(cvdata->keys.k[CV_KEY_RIGHT])) {
      if (cvtype->repw > 0) { cvtype->repw--; } else { leftright = 1; }
    }

    if (VGI_CVKEY_NEWPRESSED(cvdata->keys.k[CV_KEY_UP])) {
      updown = -1;
      cvtype->repw = VGI_CANVAS_REPWMAX;
    }
    if (VGI_CVKEY_PRESSED(cvdata->keys.k[CV_KEY_UP])) {
      if (cvtype->repw > 0) { cvtype->repw--; } else { updown = -1; }
    }

    if (VGI_CVKEY_NEWPRESSED(cvdata->keys.k[CV_KEY_DOWN])) {
      updown = 1;
      cvtype->repw = VGI_CANVAS_REPWMAX;
    }
    if (VGI_CVKEY_PRESSED(cvdata->keys.k[CV_KEY_DOWN])) {
      if (cvtype->repw > 0) { cvtype->repw--; } else { updown = 1; }
    }
  }

  /* draw */
  { struct VG_Position posb;
    struct VG_ImagecopyAttr iattr;
    int w1, h1;
    VG_BOOL in_arrow;

    vg4->image->getsize(cvtype->img, NULL, &w1, &h1);
    VG_IMAGECOPY_ATTR_DEFAULT(&iattr);
    in_arrow = VG_FALSE;

    if (cvdata->hasfocus) {  /* has focus */
      /* move map according to keypress up, down, left and right */
      if (updown < 0) {  /* up */
        cvtype->y += cvtype->velo;
        if (cvtype->y > 0) { cvtype->y = 0; }
      } else if (updown > 0) {  /* down */
        cvtype->y -= cvtype->velo;
        if (cvtype->y + h1 < cvitem->rect.h) {
          cvtype->y = cvitem->rect.h - h1;
        }
      }
      if (leftright < 0) {  /* left */
        cvtype->x += cvtype->velo;
        if (cvtype->x > 0) { cvtype->x = 0; }
      } else if (leftright > 0) {  /* right */
        cvtype->x -= cvtype->velo;
        if (cvtype->x + w1 < cvitem->rect.w) {
          cvtype->x = cvitem->rect.w - w1;
        }
      }

      /* move map according to mouse */
      if (cvdata->cvas->cve.mouse.show) {
        int xm, ym;

        if (vg4->input->mouse_position(&xm, &ym)) {
          /* check for moving up-down */
          if (IS_IN_RECT(&cvtype->arw_up.rect, xm, ym, cvdata->xadd, cvdata->yadd)) {
            in_arrow = VG_TRUE;
            if (VGI_CVKEY_PRESSED(cvdata->keys.m_left)) {
              cvtype->y += cvtype->velo;
              if (cvtype->y > 0) { cvtype->y = 0; }
            }
          } else if (IS_IN_RECT(&cvtype->arw_down.rect, xm, ym, cvdata->xadd, cvdata->yadd)) {
            in_arrow = VG_TRUE;
            if (VGI_CVKEY_PRESSED(cvdata->keys.m_left)) {
              cvtype->y -= cvtype->velo;
              if (cvtype->y + h1 < cvitem->rect.h) {
                cvtype->y = cvitem->rect.h - h1;
              }
            }
          }

          /* check for moving left-right */
          if (IS_IN_RECT(&cvtype->arw_left.rect, xm, ym, cvdata->xadd, cvdata->yadd)) {
            in_arrow = VG_TRUE;
            if (VGI_CVKEY_PRESSED(cvdata->keys.m_left)) {
              cvtype->x += cvtype->velo;
              if (cvtype->x > 0) { cvtype->x = 0; }
            }
          } else if (IS_IN_RECT(&cvtype->arw_right.rect, xm, ym, cvdata->xadd, cvdata->yadd)) {
            in_arrow = VG_TRUE;
            if (VGI_CVKEY_PRESSED(cvdata->keys.m_left)) {
              cvtype->x -= cvtype->velo;
              if (cvtype->x + w1 < cvitem->rect.w) {
                cvtype->x = cvitem->rect.w - w1;
              }
            }
          }
        }
      }

      /* activate area according to key */
      if (VGI_CVKEY_NEWPRESSED(cvdata->keys.k[CV_KEY_SPACE])) {
        for (;;) {
          cvtype->activated++;
          if (cvtype->activated > cvtype->maxarea) {
            cvtype->activated = 0;
            break;
          }
          if (!cvtype->area[cvtype->activated - 1].isdisabled) { break; }
        }

        if (cvtype->activated > 0) {
          int uelm = cvtype->activated - 1;
          cvtype->x = cvitem->rect.w / 2 - (cvtype->area[uelm].rect.x + cvtype->area[uelm].rect.w / 2);
          if (cvtype->x > 0) {
            cvtype->x = 0;
          } else if (cvtype->x + w1 < cvitem->rect.w) {
            cvtype->x = cvitem->rect.w - w1;
          }
          cvtype->y = cvitem->rect.h / 2 - (cvtype->area[uelm].rect.y + cvtype->area[uelm].rect.h / 2);
          if (cvtype->y > 0) {
            cvtype->y = 0;
          } else if (cvtype->y + h1 < cvitem->rect.h) {
            cvtype->y = cvitem->rect.h - h1;
          }
        } else {
          cvtype->x = cvtype->y = 0;
        }

        /* warp mouse to activated area */
        { int xm, ym;
          t_warp_mouse(cvdata->cvas, cvitem, cvdata->xadd, cvdata->yadd, &xm, &ym);
          vg4->input->mouse_warp(xm, ym);
        }
      }

      /* activate/select area */
      if (!in_arrow) {
        /* area selected? */
        if (cvtype->activated > 0) {
          if (VGI_CVKEY_NEWPRESSED(cvdata->keys.k[CV_KEY_RETURN])) { cvtype->selected = cvtype->activated; }
        }

        /* activate/select area according to mouse */
        if (cvdata->cvas->cve.mouse.show) {
          int xm, ym, uelm;
          struct VG_Rect rect;

          cvtype->activated = 0;
          cvtype->selected = 0;
          if (vg4->input->mouse_position(&xm, &ym)) {
            for (uelm = 0; uelm < cvtype->maxarea; uelm++) {
              if (!cvtype->area[uelm].isdisabled) {
                rect.x = cvitem->rect.x + cvtype->area[uelm].rect.x + cvtype->x;
                rect.w = cvtype->area[uelm].rect.w;
                rect.y = cvitem->rect.y + cvtype->area[uelm].rect.y + cvtype->y;
                rect.h = cvtype->area[uelm].rect.h;
                if (IS_IN_RECT(&rect, xm, ym, cvdata->xadd, cvdata->yadd)) {
                  if (VGI_CVKEY_NEWPRESSED(cvdata->keys.k[CV_KEY_RETURN]) || VGI_CVKEY_NEWPRESSED(cvdata->keys.m_left)) {  /* area selected */
                    cvtype->selected = uelm + 1;
                  }
                  cvtype->activated = uelm + 1;
                  break;
                }
              }
            }
          }
        }
      } else {
        cvtype->selected = 0;
      }

      if (cvtype->selected > 0) { *selname = cvitem->name; }

    } else if (cvitem->isdisabled) {  /* disabled */
      iattr.pixel.pixelcolor = VG_PIXELCOLOR_GREY;
      iattr.pixel.brightness = iattr.pixel.brightness * 4 / 5;
    }

    /* draw out */
    vg4->image->clear(cvitem->rimg);
    posb.pos = VG_POS_UPPER_LEFT;
    posb.x = cvtype->x;
    posb.y = cvtype->y;
    vg4->image->copy(cvitem->rimg, cvtype->img, &posb, &iattr);
    if (!cvitem->isdisabled && cvtype->activated > 0) {  /* highlight activated area */
      struct VG_Image *imgp;
      int area_act = cvtype->activated - 1;
      VG_IMAGECOPY_ATTR_DEFAULT(&iattr);
      iattr.image.zoom_width = cvtype->area[area_act].rect.w * 130 / 100;
      iattr.image.zoom_height = cvtype->area[area_act].rect.h * 130 / 100;
      iattr.image.zoom_ispercent = VG_FALSE;
      imgp = vg4_image_clone_nolist(cvtype->img, &cvtype->area[area_act].rect, &iattr);
      if (imgp != NULL) {
        struct VG_Rect rect;
        int w2, h2;
        vg4->image->getsize(imgp, NULL, &w2, &h2);
        rect.x = rect.y = 0; rect.w = w2; rect.h = h2;
        vg4->image->draw_rect(imgp, &rect, VG_COLOR_RGB(128, 128, 128), VG_FALSE);
        posb.pos = VG_POS_CENTERED;
        posb.x = cvtype->x + cvtype->area[area_act].rect.x + cvtype->area[area_act].rect.w / 2;
        posb.y = cvtype->y + cvtype->area[area_act].rect.y + cvtype->area[area_act].rect.h / 2;
        vg4->image->copy(cvitem->rimg, imgp, &posb, NULL);
        vg4->image->destroy(imgp);
      }
    }
    posb.pos = VG_POS_UPPER_LEFT;
    posb.x = cvdata->xadd + cvitem->rect.x;
    posb.y = cvdata->yadd + cvitem->rect.y;
    vg4->window->copy(cvitem->rimg, &posb, NULL);
    if (cvdata->hasfocus) {  /* has focus */
      canvas_draw_actborder(&cvitem->rect, cvdata->xadd, cvdata->yadd);
    }

    /* draw arrow-images */
    if (cvdata->hasfocus) {  /* has focus */
      /* upper image */
      if (cvitem->rect.h >= h1) {
        CLEAR_RECT(&cvtype->arw_up.rect);
      } else if (cvtype->y < 0) {
        canvas_draw_arrow(cvdata->cvas, &cvtype->arw_up, cvitem, cvdata->keys.m_left, cvdata->xadd, cvdata->yadd, VG_FALSE, 1);
      } else {
        canvas_draw_arrow(cvdata->cvas, &cvtype->arw_up, cvitem, cvdata->keys.m_left, cvdata->xadd, cvdata->yadd, VG_TRUE, 1);
      }

      /* lower image */
      if (cvitem->rect.h >= h1) {
        CLEAR_RECT(&cvtype->arw_down.rect);
      } else if (cvtype->y + h1 > cvitem->rect.h) {
        canvas_draw_arrow(cvdata->cvas, &cvtype->arw_down, cvitem, cvdata->keys.m_left, cvdata->xadd, cvdata->yadd, VG_FALSE, 2);
      } else {
        canvas_draw_arrow(cvdata->cvas, &cvtype->arw_down, cvitem, cvdata->keys.m_left, cvdata->xadd, cvdata->yadd, VG_TRUE, 2);
      }

      /* left image */
      if (cvitem->rect.w >= w1) {
        CLEAR_RECT(&cvtype->arw_left.rect);
      } else if (cvtype->x < 0) {
        canvas_draw_arrow(cvdata->cvas, &cvtype->arw_left, cvitem, cvdata->keys.m_left, cvdata->xadd, cvdata->yadd, VG_FALSE, 3);
      } else {
        canvas_draw_arrow(cvdata->cvas, &cvtype->arw_left, cvitem, cvdata->keys.m_left, cvdata->xadd, cvdata->yadd, VG_TRUE, 3);
      }

      /* right image */
      if (cvitem->rect.w >= w1) {
        CLEAR_RECT(&cvtype->arw_right.rect);
      } else if (cvtype->x + w1 > cvitem->rect.w) {
        canvas_draw_arrow(cvdata->cvas, &cvtype->arw_right, cvitem, cvdata->keys.m_left, cvdata->xadd, cvdata->yadd, VG_FALSE, 4);
      } else {
        canvas_draw_arrow(cvdata->cvas, &cvtype->arw_right, cvitem, cvdata->keys.m_left, cvdata->xadd, cvdata->yadd, VG_TRUE, 4);
      }
    }
  }
} /* Ende t_draw */


static void
t_destroy(struct vgi_canvas_item *cvitem)
{
  struct cv_type *cvtype;
  int uelm;

  if (cvitem == NULL) { return; }
  cvtype = (struct cv_type *)cvitem->vstrct;
  if (cvtype == NULL) { return; }

  if (cvtype->img != NULL) { vg4->image->destroy(cvtype->img); }
  for (uelm = 0; uelm < cvtype->maxarea; uelm++) {
    if (cvtype->area[uelm].name != NULL) { free(cvtype->area[uelm].name); }
  }
  if (cvtype->maxarea > 0) { free(cvtype->area); }

  free(cvtype);
} /* Ende t_destroy */


static void
t_dump(FILE *outfp, struct vgi_canvas_item *cvitem)
{
  struct cv_type *cvtype;
  const char *namptr;
  int uelm;

  if (outfp == NULL || cvitem == NULL) { return; }
  cvtype = (struct cv_type *)cvitem->vstrct;
  if (cvtype == NULL) { return; }

  fprintf(outfp, "    type=map\n");
  namptr = vg4->image->getname(cvtype->img);
  fprintf(outfp, "    img=%s\n", namptr);
  fprintf(outfp, "    x,y=%d,%d\n", cvtype->x, cvtype->y);
  fprintf(outfp, "    velo=%d\n", cvtype->velo);
  fprintf(outfp, "    activated=%d\n", cvtype->activated);
  fprintf(outfp, "    selected=%d\n", cvtype->selected);
  fprintf(outfp, "    areas=%d:\n", cvtype->maxarea);
  for (uelm = 0; uelm < cvtype->maxarea; uelm++) {
    fprintf(outfp, "    - [%d]\n", uelm + 1);
    fprintf(outfp, "      name=%s\n", cvtype->area[uelm].name);
    fprintf(outfp, "      rect={%d+%d,%d+%d}\n",
            cvtype->area[uelm].rect.x,
            cvtype->area[uelm].rect.w,
            cvtype->area[uelm].rect.y, 
            cvtype->area[uelm].rect.h);
    fprintf(outfp, "      is-disabled=%s\n", (cvtype->area[uelm].isdisabled ? "yes" : "no"));
  }
} /* Ende t_dump */


/* canvas_map_area_disable:
 * disable or enable area of a map
 * @param cvas     canvas
 * @param iname    name of map
 * @param ename    name of area to disable/enable
 * @param disable  whether to disable
 * @return  whether it was previous disabled
 */
static VG_BOOL
canvas_map_area_disable(struct VG_Canvas *cvas, const char *iname, const char *ename, VG_BOOL disable)
{
  struct vgi_canvas_item *cvitem;
  struct cv_type *cvtype;
  int uelm;
  VG_BOOL wasdisabled;

  if (cvas == NULL || iname == NULL || *iname == '\0' || ename == NULL || *ename == '\0') { return VG_TRUE; }

  cvitem = cvtype_get_item(cvas, iname, type_no);
  if (cvitem == NULL) { return VG_TRUE; }
  cvtype = (struct cv_type *)cvitem->vstrct;
  if (cvtype == NULL) { return VG_TRUE; }

  wasdisabled = VG_TRUE;

  for (uelm = 0; uelm < cvtype->maxarea; uelm++) {
    if (strcmp(ename, cvtype->area[uelm].name) == 0) {
      wasdisabled = cvtype->area[uelm].isdisabled;
      cvtype->area[uelm].isdisabled = disable;
      break;
    }
  }

  return wasdisabled;
} /* Ende canvas_map_area_disable */


/* canvas_map_area_get_selected:
 * get selected area of map
 * @param cvas     canvas
 * @param iname    name of map
 * @return   name of selected area of map, or NULL = none
 */
static const char *
canvas_map_area_get_selected(struct VG_Canvas *cvas, const char *iname)
{
  struct vgi_canvas_item *cvitem;
  struct cv_type *cvtype;
  const char *ename;
  int item_no;

  if (cvas == NULL || iname == NULL || *iname == '\0') { return NULL; }

  cvitem = cvtype_get_item(cvas, iname, type_no);
  if (cvitem == NULL) { return NULL; }
  cvtype = (struct cv_type *)cvitem->vstrct;
  if (cvtype == NULL) { return NULL; }

  ename = NULL;
  item_no = cvtype->selected;
  if (item_no > 0) { ename = cvtype->area[item_no - 1].name; }

  return ename;
} /* Ende canvas_map_area_get_selected */
