void acopt_redraw(ACONTROLP ctl) {
  ACOPTDP d = (ACOPTDP) ctl->d;
  
  if (d->acheck_signature != 136) {
    return;  //-- Not Valid Signature
  }
  
  if ((d->itemn > 0) && (d->draweditemn < d->itemn)) {
    ag_ccanvas(&d->client);
    ag_canvas(&d->client, d->clientWidth, d->nextY);
    ag_rect(&d->client, 0, 0, d->clientWidth, agdp()*max(acfg()->roundsz, 4), acfg()->textbg);
    //-- Set Values
    d->scrollY     = 0;
    d->maxScrollY  = d->nextY - (ctl->h - (agdp() * max(acfg()->roundsz, 4)));
    
    if (d->maxScrollY < 0) {
      d->maxScrollY = 0;
    }
    
    //-- Draw Items
    int i;
    
    for (i = 0; i < d->itemn; i++) {
      acopt_redrawitem(ctl, i);
    }
    
    d->draweditemn = d->itemn;
  }
}
void acopt_ondraw(void * x){
  ACONTROLP   ctl= (ACONTROLP) x;
  ACOPTDP   d  = (ACOPTDP) ctl->d;
  CANVAS *    pc = &ctl->win->c;
  acopt_redraw(ctl);
  if (d->invalidDrawItem!=-1){
    d->touchedItem = d->invalidDrawItem;
    acopt_redrawitem(ctl,d->invalidDrawItem);
    d->invalidDrawItem=-1;
  }
  
  //-- Init Device Pixel Size
  int minpadding = 2;
  int agdp3 = (agdp()*minpadding);
  int agdp6 = (agdp()*(minpadding*2));
  int agdpX = agdp6;
  
  ag_draw(pc,&d->control,ctl->x,ctl->y);
  // ag_draw_ex(pc,&d->client,ctl->x+agdp3,ctl->y+1,0,d->scrollY+1,ctl->w-agdp6,ctl->h-2);
  ag_draw_ex(pc,&d->client,ctl->x+agdp(),ctl->y+1,0,d->scrollY+1,ctl->w-(agdp()*2),ctl->h-2);
  
  if (d->maxScrollY>0){
    //-- Glow
    int i;
    byte isST=(d->scrollY>0)?1:0;
    byte isSB=(d->scrollY<d->maxScrollY)?1:0;
    int add_t_y = 1;
    
    for (i=0;i<agdpX;i++){
      byte alph = 255-round((((float) (i+1))/ ((float) agdpX))*230);
      if (isST)
        ag_rectopa(pc,ctl->x,ctl->y+i+add_t_y,ctl->w,1,acfg()->textbg,alph);
      if (isSB)
        ag_rectopa(pc,ctl->x,((ctl->y+ctl->h)-(add_t_y))-(i+1),ctl->w,1,acfg()->textbg,alph);
    }
    
    //-- Scrollbar
    int newh = ctl->h - agdp6;
    float scrdif    = ((float) newh) / ((float) d->client.h);
    int  scrollbarH = round(scrdif * newh);
    int  scrollbarY = round(scrdif * d->scrollY) + agdp3;
    if (d->scrollY<0){
      scrollbarY = agdp3;
      int alp = (1.0 - (((float) abs(d->scrollY)) / (((float) ctl->h)/4))) * 255;
      if (alp<0) alp = 0;
      ag_rectopa(pc,(ctl->w-agdp()-2)+ctl->x,scrollbarY+ctl->y,agdp(),scrollbarH,acfg()->scrollbar, alp);
    }
    else if (d->scrollY>d->maxScrollY){
      scrollbarY = round(scrdif * d->maxScrollY) + agdp3;
      int alp = (1.0 - (((float) abs(d->scrollY-d->maxScrollY)) / (((float) ctl->h)/4))) * 255;
      if (alp<0) alp = 0;
      ag_rectopa(pc,(ctl->w-agdp()-2)+ctl->x,scrollbarY+ctl->y,agdp(),scrollbarH,acfg()->scrollbar, alp);
    }
    else{
      ag_rect(pc,(ctl->w-agdp()-2)+ctl->x,scrollbarY+ctl->y,agdp(),scrollbarH,acfg()->scrollbar);
    }
  }
}
void acopt_onblur(void * x){
  ACONTROLP   ctl= (ACONTROLP) x;
  ACOPTDP   d  = (ACOPTDP) ctl->d;
  d->focused=0;
  if ((d->focusedItem!=-1)&&(d->draweditemn>0)){
    acopt_redrawitem(ctl,d->focusedItem);
  }
  ctl->ondraw(ctl);
}
byte acopt_onfocus(void * x){
  ACONTROLP   ctl= (ACONTROLP) x;
  ACOPTDP   d  = (ACOPTDP) ctl->d;
  
  d->focused=1;
  
  if ((d->focusedItem==-1)&&(d->itemn>0)){
    d->focusedItem=0;
  }
  if ((d->focusedItem!=-1)&&(d->draweditemn>0)){
    acopt_redrawitem(ctl,d->focusedItem);
  }
  ctl->ondraw(ctl);
  return 1;
}
dword acopt_oninput(void * x, int action, ATEV * atev) {
  ACONTROLP ctl = (ACONTROLP) x;
  ACOPTDP d  = (ACOPTDP) ctl->d;
  dword msg = 0;
  
  switch (action) {
    case ATEV_MOUSEDN: {
        d->prevTouchY  = atev->y;
        akinetic_downhandler(&d->akin, atev->y);
        int touchpos = atev->y - ctl->y + d->scrollY;
        int i;
        
        for (i = 0; i < d->itemn; i++) {
          if ((touchpos >= d->items[i]->y) && (touchpos < d->items[i]->y + d->items[i]->h)) {
            ac_regpushwait(
              ctl, &d->prevTouchY, &d->invalidDrawItem, i
            );
            break;
          }
        }
      }
      break;
      
    case ATEV_MOUSEUP: {
        if ((d->prevTouchY != -50) && (abs(d->prevTouchY - atev->y) < agdp() * 5)) {
          d->prevTouchY = -50;
          int touchpos = atev->y - ctl->y + d->scrollY;
          int i;
          
          for (i = 0; i < d->itemn; i++) {
            if ((!d->items[i]->isTitle) && (touchpos >= d->items[i]->y) && (touchpos < d->items[i]->y + d->items[i]->h)) {
              if ((d->touchedItem != -1) && (d->touchedItem != i)) {
                int tmptouch = d->touchedItem;
                d->touchedItem = -1;
                acopt_redrawitem(ctl, tmptouch);
              }
              
              int grp = d->items[i]->group;
              
              if ((d->selectedIndexs[grp] != -1) && (d->selectedIndexs[grp] != i)) {
                int tmpsidx = d->selectedIndexs[grp];
                d->selectedIndexs[grp] = -1;
                acopt_redrawitem(ctl, tmpsidx);
              }
              
              int prevfocus               = d->focusedItem;
              d->focusedItem              = i;
              d->touchedItem              = i;
              d->selectedIndexs[grp]  = i;
              
              if ((prevfocus != -1) && (prevfocus != i)) {
                acopt_redrawitem(ctl, prevfocus);
              }
              
              acopt_redrawitem(ctl, i);
              ctl->ondraw(ctl);
              aw_draw(ctl->win);
              vibrate(30);
              break;
            }
          }
          
          if ((d->scrollY < 0) || (d->scrollY > d->maxScrollY)) {
            ac_regbounce(ctl, &d->scrollY, d->maxScrollY);
          }
        }
        else {
          if (akinetic_uphandler(&d->akin, atev->y)) {
            ac_regfling(ctl, &d->akin, &d->scrollY, d->maxScrollY);
          }
          else if ((d->scrollY < 0) || (d->scrollY > d->maxScrollY)) {
            ac_regbounce(ctl, &d->scrollY, d->maxScrollY);
          }
        }
        
        if (d->touchedItem != -1) {
          usleep(30);
          int tmptouch = d->touchedItem;
          d->touchedItem = -1;
          acopt_redrawitem(ctl, tmptouch);
          ctl->ondraw(ctl);
          msg = aw_msg(0, 1, 0, 0);
        }
      }
      break;
      
    case ATEV_MOUSEMV: {
        byte allowscroll = 1;
        
        if (atev->y != 0) {
          if (d->prevTouchY != -50) {
            if (abs(d->prevTouchY - atev->y) >= agdp() * 5) {
              d->prevTouchY = -50;
              
              if (d->touchedItem != -1) {
                int tmptouch = d->touchedItem;
                d->touchedItem = -1;
                acopt_redrawitem(ctl, tmptouch);
                ctl->ondraw(ctl);
                aw_draw(ctl->win);
              }
            }
            else {
              allowscroll = 0;
            }
          }
          
          if (allowscroll) {
            int mv = akinetic_movehandler(&d->akin, atev->y);
            
            if (mv != 0) {
              if ((d->scrollY < 0) && (mv < 0)) {
                float dumpsz = 0.6 - (0.6 * (((float) abs(d->scrollY)) / (ctl->h / 4)));
                d->scrollY += floor(mv * dumpsz);
              }
              else if ((d->scrollY > d->maxScrollY) && (mv > 0)) {
                float dumpsz = 0.6 - (0.6 * (((float) abs(d->scrollY - d->maxScrollY)) / (ctl->h / 4)));
                d->scrollY += floor(mv * dumpsz);
              }
              else {
                d->scrollY += mv;
              }
              
              if (d->scrollY < 0 - (ctl->h / 4)) {
                d->scrollY = 0 - (ctl->h / 4);
              }
              
              if (d->scrollY > d->maxScrollY + (ctl->h / 4)) {
                d->scrollY = d->maxScrollY + (ctl->h / 4);
              }
              
              msg = aw_msg(0, 1, 0, 0);
              ctl->ondraw(ctl);
            }
          }
        }
      }
      break;
      
    case ATEV_SELECT: {
        if ((d->focusedItem > -1) && (d->draweditemn > 0)) {
          if (atev->d) {
            if ((d->touchedItem != -1) && (d->touchedItem != d->focusedItem)) {
              int tmptouch = d->touchedItem;
              d->touchedItem = -1;
              acopt_redrawitem(ctl, tmptouch);
            }
            
            vibrate(30);
            d->touchedItem = d->focusedItem;
            acopt_redrawitem(ctl, d->focusedItem);
            ctl->ondraw(ctl);
            msg = aw_msg(0, 1, 0, 0);
          }
          else {
            if ((d->touchedItem != -1) && (d->touchedItem != d->focusedItem)) {
              int tmptouch = d->touchedItem;
              d->touchedItem = -1;
              acopt_redrawitem(ctl, tmptouch);
            }
            
            int grp = d->items[d->focusedItem]->group;
            
            if ((d->selectedIndexs[grp] != -1) && (d->selectedIndexs[grp] != d->focusedItem)) {
              int tmpsidx = d->selectedIndexs[grp];
              d->selectedIndexs[grp] = -1;
              acopt_redrawitem(ctl, tmpsidx);
            }
            
            d->selectedIndexs[grp] = d->focusedItem;
            d->touchedItem = -1;
            acopt_redrawitem(ctl, d->focusedItem);
            ctl->ondraw(ctl);
            msg = aw_msg(0, 1, 0, 0);
          }
        }
      }
      break;
      
    case ATEV_DOWN: {
        if ((d->focusedItem < d->itemn - 1) && (d->draweditemn > 0)) {
          int prevfocus = d->focusedItem;
          d->focusedItem++;
          
          while (d->items[d->focusedItem]->isTitle) {
            d->focusedItem++;
            
            if (d->focusedItem > d->itemn - 1) {
              d->focusedItem = prevfocus;
              return 0;
            }
          }
          
          acopt_redrawitem(ctl, prevfocus);
          acopt_redrawitem(ctl, d->focusedItem);
          ctl->ondraw(ctl);
          msg = aw_msg(0, 1, 1, 0);
          int reqY = d->items[d->focusedItem]->y - round((ctl->h / 2) - (d->items[d->focusedItem]->h / 2));
          ac_regscrollto(
            ctl,
            &d->scrollY,
            d->maxScrollY,
            reqY,
            &d->focusedItem,
            d->focusedItem
          );
        }
      }
      break;
      
    case ATEV_UP: {
        if ((d->focusedItem > 0) && (d->draweditemn > 0)) {
          int prevfocus = d->focusedItem;
          d->focusedItem--;
          
          while (d->items[d->focusedItem]->isTitle) {
            d->focusedItem--;
            
            if (d->focusedItem < 0) {
              d->focusedItem = prevfocus;
              return 0;
            }
          }
          
          acopt_redrawitem(ctl, prevfocus);
          acopt_redrawitem(ctl, d->focusedItem);
          ctl->ondraw(ctl);
          msg = aw_msg(0, 1, 1, 0);
          int reqY = d->items[d->focusedItem]->y - round((ctl->h / 2) - (d->items[d->focusedItem]->h / 2));
          ac_regscrollto(
            ctl,
            &d->scrollY,
            d->maxScrollY,
            reqY,
            &d->focusedItem,
            d->focusedItem
          );
        }
      }
      break;
  }
  
  return msg;
}