Exemple #1
0
void scroll_to_divnode(struct divnode *div) {
  s16 dx = 0,dy = 0;
  struct divnode *ds = div->divscroll;
  struct widget *w;

  if (!ds)
    return;

  /* If the divnode is larger or equal size to the scrolled
   * container, no need to scroll it in.
   * This fixes some confusing scroll behavior when focusing the textbox widget.
   */
  if ( (div->r.x <= ds->calc.x && (div->r.x + div->r.w) > (ds->calc.x + ds->calc.w)) ||
       (div->r.y <= ds->calc.y && (div->r.y + div->r.h) > (ds->calc.y + ds->calc.h)) )
    return;

  /* Figure out how much to scroll, if any. */

  if (div->r.x < ds->calc.x)
    dx = div->r.x - ds->calc.x;
  else if ( (div->r.x + div->r.w) > (ds->calc.x + ds->calc.w) )
    dx = (div->r.x + div->r.w) - (ds->calc.x + ds->calc.w);
  if (div->r.y < ds->calc.y)
    dy = div->r.y - ds->calc.y;
  else if ( (div->r.y + div->r.h) > (ds->calc.y + ds->calc.h) )
    dy = (div->r.y + div->r.h) - (ds->calc.y + ds->calc.h);

  /* No scrolling? */
  if (!(dx || dy))
    return;

  /* Get a pointer to the scroll bar */
  if (!iserror(rdhandle((void **)&w,PG_TYPE_WIDGET,-1,
			ds->owner->scrollbind)) && w) {
    
    if (dx)
      widget_set(w,PG_WP_SCROLL_X,widget_get(w,PG_WP_SCROLL_X) + dx);    
    if (dy)
      widget_set(w,PG_WP_SCROLL_Y,widget_get(w,PG_WP_SCROLL_Y) + dy);
    
    update(NULL,1);
  }
}
Exemple #2
0
void themeify_panelbar(struct widget *self,bool force) {
  int hz = widget_get(self,PG_WP_SIDE) & (PG_S_TOP | PG_S_BOTTOM);

  /* Apply the current state  */

  if (DATA->on)
    div_setstate(DATA->panelbar,hz ? PGTH_O_PANELBAR_H_ON : PGTH_O_PANELBAR_V_ON,force);
  else if (DATA->over)
    div_setstate(DATA->panelbar,hz ? PGTH_O_PANELBAR_H_HILIGHT : PGTH_O_PANELBAR_V_HILIGHT,force);
  else
    div_setstate(DATA->panelbar,hz ? PGTH_O_PANELBAR_H : PGTH_O_PANELBAR_V,force);
}
Exemple #3
0
glob panel_get(struct widget *self,int property) {
  struct widget *w;
  g_error e;

  switch (property) {

  case PG_WP_THOBJ:
    return DATA->bg->state;

  case PG_WP_TEXT:
    e = rdhandle((void **) &w, PG_TYPE_WIDGET, self->owner, DATA->hlabel);
    errorcheck;
    return widget_get(w,property);

  case PG_WP_IMAGE:
    e = rdhandle((void **) &w, PG_TYPE_WIDGET, self->owner, DATA->hlabel);
    errorcheck;
    return widget_get(w,property);

  case PG_WP_PANELBAR:
    return DATA->hbar;

  case PG_WP_PANELBAR_LABEL:
    return DATA->hlabel;

  case PG_WP_PANELBAR_CLOSE:
    return DATA->hclose;

  case PG_WP_PANELBAR_ROTATE:
    return DATA->hrotate;

  case PG_WP_PANELBAR_ZOOM:
    return DATA->hzoom;

  case PG_WP_MARGIN:
    return DATA->margin;

  }
  return widget_base_get(self,property);
}
Exemple #4
0
glob tabpage_get(struct widget *self,int property) {
  struct widget *w;

  /* Redirect applicable properties to the tab */ 
  if (is_tab_property(property))
    if (!iserror(rdhandle((void**)&w, PG_TYPE_WIDGET, self->owner, DATA->htab)) && w)
      return widget_get(w, property);

  /* Redirect applicable properties to the tab bar */ 
  if (is_tab_bar_property(property))
    if (!iserror(rdhandle((void**)&w, PG_TYPE_WIDGET, self->owner, DATA->htab_bar)) && w)
      return widget_get(w, property);

  switch (property) {

  case PG_WP_TAB:
    return DATA->htab;

  case PG_WP_TAB_BAR:
    return DATA->htab_bar;

  }
  return WIDGET_PARENT->get(self,property);
}
Exemple #5
0
int panel_rotate_callback(int event, struct widget *from, s32 param, int owner, const u8 *data) {
  struct widget *p;
  p = from->callback_owner;
  if (p && event==PG_WE_ACTIVATE) {

    switch (widget_get(p,PG_WP_SIDE)) {
    case PG_S_TOP:    widget_set(p,PG_WP_SIDE,PG_S_RIGHT);  break;
    case PG_S_RIGHT:  widget_set(p,PG_WP_SIDE,PG_S_BOTTOM); break;
    case PG_S_BOTTOM: widget_set(p,PG_WP_SIDE,PG_S_LEFT);   break;
    case PG_S_LEFT:   widget_set(p,PG_WP_SIDE,PG_S_TOP);    break; 
    }

    update(NULL,1);
  }
  return 1; /* Absorb event */
}
Exemple #6
0
void panel_resize(struct widget *self) {
  struct widget *bar = NULL;
  rdhandle((void **) &bar, PG_TYPE_WIDGET, self->owner, DATA->hbar);

  if (DATA->margin_override)
    DATA->bg->split = DATA->margin;
  else
    DATA->bg->split = theme_lookup(DATA->bg->state,PGTH_P_MARGIN);
  self->in->div->split = theme_lookup(DATA->bg->state,PGTH_P_BORDER_SIZE);

  /* The minimum setting on the panelbar needs to leave room for the margin
   * on both sides, and the panelbar width itself.
   */
  if (bar)
    widget_set(bar, PG_WP_MINIMUM, widget_get(bar, PG_WP_SIZE) + 
	       (self->in->div->split << 1));
}
Exemple #7
0
void cursor_widgetunder(struct cursor *crsr) {
  int x,y;
  struct divnode *div;
  struct divtree *dt;

  cursor_getposition(crsr, &x, &y, &dt);
  div = dt->head;

  /* If there are popups and they're all in the nontoolbar area,
   * we can pass toolbar's events through to the bottom layer in the dtstack
   */
  if (popup_toolbar_passthrough()) {
    struct divnode *ntb = appmgr_nontoolbar_area();
    if (ntb) {
      if (x < ntb->r.x ||
	  y < ntb->r.y ||
	  x >= ntb->r.x+ntb->r.w ||
	  y >= ntb->r.y+ntb->r.h) {
	
	/* Get a widget from the bottom layer, with the toolbars */
	div = dts->root->head;
      }
    }
  }
 
  /* recursively determine the widget/divnode under the cursor */
  crsr->ctx.div_under = NULL;
  crsr->ctx.deepest_div = NULL;
  r_cursor_widgetunder(crsr,div,x,y);

  /* Save the widget associated with the divnode we're under */
  if (crsr->ctx.div_under) {
    crsr->ctx.widget_under = hlookup(crsr->ctx.div_under->owner,NULL);

    /* Also change the cursor theme */
    cursor_set_theme(crsr, widget_get(crsr->ctx.div_under->owner,PG_WP_THOBJ));
  }
  else {
    crsr->ctx.widget_under = 0;

    /* Default cursor theme */
    cursor_set_theme(crsr, PGTH_O_DEFAULT);
  }
}
Exemple #8
0
/* Sends a trigger to all of a widget's children */
void r_send_trigger(struct widget *w, s32 type,
		    union trigparam *param, int *stop,int forward) {
  struct widget *bar;
  
  if (!w || (*stop) > 0)
    return;
  send_trigger(w,type,param);
  
  /* Also traverse the panelbar if there is one */
  if (!iserror(rdhandle((void**)&bar, PG_TYPE_WIDGET, w->owner, 
			widget_get(w,PG_WP_PANELBAR))) && bar) {
    r_send_trigger(bar, type, param, stop,0);
    if ((*stop) > 0)
      return;
  }
  
  r_send_trigger(widget_traverse(w,PG_TRAVERSE_CHILDREN,0),type,param,stop,1);
  if (forward)
    r_send_trigger(widget_traverse(w,PG_TRAVERSE_FORWARD,1),type,param,stop,1);
}
Exemple #9
0
g_error widget_base_set(struct widget *w, int property, glob data) {
  char *str;
  struct divnode *maindiv = w->in->div ? w->in->div : w->in;

  switch (property) {
    
    /* Set the size, assuming initial split at w->in.
     * Calls resize handler if it exists, and sets the
     * appropriate flags.
     */
  case PG_WP_SIDE:
    if (!VALID_SIDE(data)) return mkerror(PG_ERRT_BADPARAM,2);
    w->in->flags &= SIDEMASK;
    w->in->flags |= ((sidet)data) | DIVNODE_NEED_RECALC;
    resizewidget(w);
    w->dt->flags |= DIVTREE_NEED_RECALC;
    redraw_bg(w);

    if (w->auto_orientation) {
      /* Set orientation on all child widgets */

      struct widget *p;
      p = widget_traverse(w, PG_TRAVERSE_CHILDREN, 0);
      while (p) {
	switch (data) {

	case PG_S_LEFT:
	case PG_S_RIGHT:
	   
	  if (w->auto_orientation & PG_AUTO_DIRECTION)
	    widget_set(p, PG_WP_DIRECTION, PG_DIR_VERTICAL);

	  if (w->auto_orientation & PG_AUTO_SIDE)
	    switch (widget_get(p, PG_WP_SIDE)) {
		
	    case PG_S_LEFT:
	      widget_set(p, PG_WP_SIDE, PG_S_TOP);
	      break;
		
	    case PG_S_RIGHT:
	      widget_set(p, PG_WP_SIDE, PG_S_BOTTOM);
	      break;
		
	    }
	  break;

	case PG_S_TOP:
	case PG_S_BOTTOM:

	  if (w->auto_orientation & PG_AUTO_DIRECTION)
	    widget_set(p, PG_WP_DIRECTION, PG_DIR_HORIZONTAL);

	  if (w->auto_orientation & PG_AUTO_SIDE)
	    switch (widget_get(p, PG_WP_SIDE)) {
		
	    case PG_S_TOP:
	      widget_set(p, PG_WP_SIDE, PG_S_LEFT);
	      break;
		
	    case PG_S_BOTTOM:
	      widget_set(p, PG_WP_SIDE, PG_S_RIGHT);
	      break;
		
	    }
	  break;

	}
	p = widget_traverse(p, PG_TRAVERSE_FORWARD,1);
      }
    }
    break;

  case PG_WP_SIZE:
    if (data<0) {
      /* Automatic sizing */
      w->in->flags |= DIVNODE_SIZE_AUTOSPLIT;
      w->dt->flags |= DIVTREE_NEED_RESIZE;
    }
    else {
      w->in->split = data;
      w->in->flags &= ~DIVNODE_SIZE_AUTOSPLIT;     /* No auto resizing */
    }
    w->in->flags |= DIVNODE_NEED_RECALC;
    w->dt->flags |= DIVTREE_NEED_RECALC;
    redraw_bg(w);
    break;

  case PG_WP_SIZEMODE:
    w->in->flags &= ~DIVNODE_SIZE_AUTOSPLIT;     /* No auto resizing */
    w->in->flags &= ~PG_SZMODEMASK;
    w->in->flags |= data & PG_SZMODEMASK;
    redraw_bg(w);
    break;
      
  case PG_WP_SCROLL_X:
    if (data > w->in->child.w - w->in->r.w)
      data = w->in->child.w - w->in->r.w;
    if (data < 0)
      data = 0;
    if (maindiv->translation.x != -data) {
      maindiv->translation.x = -data;
      maindiv->flags |= DIVNODE_SCROLL_ONLY | DIVNODE_NEED_RECALC;
      w->dt->flags |= DIVTREE_NEED_REDRAW;
      hotspot_free();
    }
    maindiv->flags |= DIVNODE_DIVSCROLL | DIVNODE_EXTEND_WIDTH;
    break;

  case PG_WP_SCROLL_Y:
    if (data > w->in->child.h - w->in->r.h)
      data = w->in->child.h - w->in->r.h;
    if (data < 0)
      data = 0;
    if (maindiv->translation.y != -data) {
      maindiv->translation.y = -data;
      maindiv->flags |= DIVNODE_SCROLL_ONLY | DIVNODE_NEED_RECALC;
      w->dt->flags |= DIVTREE_NEED_REDRAW;
      hotspot_free();
    }
    maindiv->flags |= DIVNODE_DIVSCROLL | DIVNODE_EXTEND_HEIGHT;
    break;

  case PG_WP_NAME:
    if (iserror(rdhandle((void **)&str,PG_TYPE_PGSTRING,-1,data))) 
      return mkerror(PG_ERRT_HANDLE,18);
    w->name = handle_canonicalize((handle) data);
    break;

  case PG_WP_PUBLICBOX:
    w->publicbox = data;
    break;

  case PG_WP_BIND:
    w->scrollbind = data;
    break;

  case PG_WP_THOBJ:
    maindiv->state = data;
    resizewidget(w);
    w->in->flags |= DIVNODE_NEED_RECALC;
    w->dt->flags |= DIVTREE_NEED_RECALC;
    break;

  case PG_WP_TRIGGERMASK:
    w->trigger_mask = data;
    break;
     
  case PG_WP_HILIGHTED:
    {
      struct widget *p;
      
      //
      // Pass the message onto the other sub widgets
      //
      p = widget_traverse(w, PG_TRAVERSE_CHILDREN, 0);
      while (p) {
	widget_set(p, PG_WP_HILIGHTED, data);
	p = widget_traverse(p, PG_TRAVERSE_FORWARD,1);
      }
    }
    break;

  case PG_WP_AUTO_ORIENTATION:
    w->auto_orientation = data;
    break;

  default:
    return mkerror(PG_ERRT_BADPARAM,6);   /* Unknown property */
  }
  return success;
}
Exemple #10
0
void panelbar_trigger_solid(struct widget *self,s32 type,union trigparam *param) {
  bool force = 0;
  struct widget *boundwidget;
  int s;

  switch (type) {

  case PG_TRIGGER_ENTER:
    DATA->over = 1;
    break;
  case PG_TRIGGER_LEAVE:
    DATA->over=0;
    break;

  case PG_TRIGGER_DOWN:
    if (param->mouse.chbtn != 1) return;

    /* If we're bound to another widget (we should be) save its current size */
    if (!iserror(rdhandle((void**)&boundwidget,PG_TYPE_WIDGET,self->owner,
			  DATA->bindto)) && boundwidget) {
      DATA->oldsize = widget_get(boundwidget,PG_WP_SIZE);

      /* To make things easier during dragging,
       * get the effective split to equal the split
       */
      widget_set(boundwidget, PG_WP_SIZEMODE, PG_SZMODE_PIXEL);
      widget_set(boundwidget, PG_WP_SIZE,
		 panel_effective_split(boundwidget->in));	 
    }

    DATA->on = 1;
    DATA->x = param->mouse.x;
    DATA->y = param->mouse.y;
    DATA->draglen = 0;
    break;

  case PG_TRIGGER_UP:
  case PG_TRIGGER_RELEASE:
    if (!DATA->on) return;
    if (!(param->mouse.chbtn & 1)) return;

    if (!iserror(rdhandle((void**)&boundwidget,PG_TYPE_WIDGET,self->owner,
			  DATA->bindto)) && boundwidget) {

      if (DATA->draglen < MINDRAGLEN) {
	/* This was a click, not a drag */
	DATA->over = 0;
	
	widget_set(boundwidget,PG_WP_SIZEMODE,PG_SZMODE_PIXEL);
	if (DATA->oldsize > DATA->minimum)
	  /* Roll up the panel */
	  widget_set(boundwidget,PG_WP_SIZE,DATA->minimum);
	else
	  /* Unroll the panel */
	  widget_set(boundwidget,PG_WP_SIZE,DATA->unrolled);

	update(NULL,1);
      }
      else {
	s = panel_effective_split(boundwidget->in);

	/* Save this as the new unrolled split,
	 * Unless the user manually rolled up the panel */
	if ((s-DATA->minimum) > MAXROLLUP) 
	  DATA->unrolled = s;
	else
	  s = DATA->minimum;
      }
    }

    DATA->on = 0;
    break;

  case PG_TRIGGER_MOVE:
  case PG_TRIGGER_DRAG:
     if (!DATA->on) return;
     if (panel_throttle(self))
       return;
     
     if (!iserror(rdhandle((void**)&boundwidget,PG_TYPE_WIDGET,self->owner,
			   DATA->bindto)) && boundwidget) {
     
       s = panel_calcsplit(self,param->mouse.x,param->mouse.y,
			   widget_get(boundwidget,PG_WP_SIDE));
       DATA->draglen += abs(s);
       
       if (s) {
	 s += boundwidget->in->split;

	 /* FIXME: This isn't quite right, in solid dragging mode the panelbar
	  * can get out of sync with the cursor when this s < DATA->minimum code
	  * comes into effect.
	  */
	 if (s < DATA->minimum)
	   s = DATA->minimum;
	 else {
	   DATA->x = param->mouse.x;
	   DATA->y = param->mouse.y;
	 }

	 widget_set(boundwidget, PG_WP_SIZE,s);
	 update(NULL,1);
       }
     }
     return;
  }

  themeify_panelbar(self,force);
}
Exemple #11
0
void panelbar_trigger_sprite(struct widget *self,s32 type,union trigparam *param) {
  bool force = 0;
  struct widget *boundwidget;
  int s;

  switch (type) {

  case PG_TRIGGER_ENTER:
    DATA->over = 1;
    break;

  case PG_TRIGGER_LEAVE:
    /* If we're dragging, the mouse didn't REALLY leave */
    if (DATA->on) return;
    DATA->over=0;
    break;

  case PG_TRIGGER_DOWN:
    if (param->mouse.chbtn != 1) return;

    /* If we're bound to another widget (we should be) save its current size */
    if (!iserror(rdhandle((void**)&boundwidget,PG_TYPE_WIDGET,self->owner,
			  DATA->bindto)) && boundwidget) {
      DATA->oldsize = widget_get(boundwidget,PG_WP_SIZE);

      /* If we're not rolled up, save this as the unrolled split */
      if (DATA->oldsize > DATA->minimum)
	DATA->unrolled = DATA->oldsize;
    }

    DATA->on = 1;
    DATA->x = param->mouse.x;
    DATA->y = param->mouse.y;
    DATA->draglen = 0;
     
    /* Update the screen now, so we have an up-to-date picture
       of the panelbar stored in DATA->s */
    themeify_panelbar(self,1);

    VID(sprite_hideall) ();   /* This line combined with the zero flag on */
    update(NULL,0);             /*  the next gets a clean spriteless grab */

    /* In case there was no release trigger (bug in input driver) */
    if (DATA->s) {
       free_sprite(DATA->s);
       DATA->s = NULL;
    }
    if (DATA->sbit) {
       VID(bitmap_free) (DATA->sbit);
       DATA->sbit = NULL;
    }
     
    /* Allocate the new sprite */
    if(iserror(new_sprite(&DATA->s,self->dt,DATA->panelbar->r.w,DATA->panelbar->r.h))) {
       DATA->s = NULL;
       return;
    }
    if (iserror(VID(bitmap_new) (&DATA->sbit,DATA->panelbar->r.w,DATA->panelbar->r.h,vid->bpp))) {
       free_sprite(DATA->s);
       DATA->s = NULL;
       DATA->sbit = NULL;
       return;
    }
    DATA->s->bitmap = &DATA->sbit;
    
    /* Grab a bitmap of the panelbar to use as the sprite */
    VID(blit) (DATA->sbit,0,0,DATA->panelbar->r.w,DATA->panelbar->r.h,
	       self->dt->display,DATA->s->x = DATA->panelbar->r.x,DATA->s->y = DATA->panelbar->r.y,
	       PG_LGOP_NONE);

    /* Clip the sprite to the travel allowed by boundwidget's parent */
    if (!iserror(rdhandle((void**)&boundwidget,PG_TYPE_WIDGET,self->owner,
			  DATA->bindto)) && boundwidget) {
      DATA->s->clip_to = boundwidget->in;
    }

    return;

  case PG_TRIGGER_UP:
  case PG_TRIGGER_RELEASE:
    if (!DATA->on) return;
    if (!(param->mouse.chbtn & 1)) return;

    if (!iserror(rdhandle((void**)&boundwidget,PG_TYPE_WIDGET,self->owner,
			  DATA->bindto)) && boundwidget) {

      s = panel_calcsplit(self,param->mouse.x,param->mouse.y,
			  widget_get(boundwidget,PG_WP_SIDE));
      
      if (DATA->draglen < MINDRAGLEN) {
	/* This was a click, not a drag */
	DATA->over = 0;
	
	widget_set(boundwidget,PG_WP_SIZEMODE,PG_SZMODE_PIXEL);
	if (DATA->oldsize > DATA->minimum)
	  /* Roll up the panel */
	  widget_set(boundwidget,PG_WP_SIZE,DATA->minimum);
	else
	  /* Unroll the panel */
	  widget_set(boundwidget,PG_WP_SIZE,DATA->unrolled);
      }
      else {
	s += panel_effective_split(boundwidget->in);

	/* Save this as the new unrolled split,
	 * Unless the user manually rolled up the panel */
	if ((s-DATA->minimum) > MAXROLLUP) 
	  DATA->unrolled = s;
	else
	  s = DATA->minimum;
	
	widget_set(boundwidget,PG_WP_SIZEMODE,PG_SZMODE_PIXEL);
	widget_set(boundwidget,PG_WP_SIZE,s);

	DATA->over = 1;
      }
    }

    VID(bitmap_free) (DATA->sbit);
    free_sprite(DATA->s);
    DATA->s = NULL;
    DATA->sbit = NULL;
    force = 1;           /* Definitely draw the new position */
     
    DATA->on = 0;
    break;

  case PG_TRIGGER_MOVE:
  case PG_TRIGGER_DRAG:
    if (!DATA->on) return;
     /* Ok, button 1 is dragging through our widget... */
     
    if (panel_throttle(self))
      return;
     
     /* Race condition prevention?
      * Without this, sometimes segfaults because DATA->s is NULL.
      * Possibly events_pending() triggered another event? */
     if (!DATA->s) return;
      
     /* Determine where to blit the bar to... */
     switch (self->in->flags & (~SIDEMASK)) {
     case PG_S_TOP:
     case PG_S_BOTTOM:
       DATA->s->x = DATA->panelbar->r.x;
       DATA->draglen += abs(param->mouse.y - DATA->y + DATA->panelbar->r.y - DATA->s->y);
       DATA->s->y = param->mouse.y - DATA->y + DATA->panelbar->r.y;
       break;
     case PG_S_LEFT:
     case PG_S_RIGHT:
       DATA->s->y = DATA->panelbar->r.y;
       DATA->draglen += abs(param->mouse.x - DATA->x + DATA->panelbar->r.x - DATA->s->x);
       DATA->s->x = param->mouse.x - DATA->x + DATA->panelbar->r.x;
       break;
     }

    /* Reposition sprite */
    VID(sprite_update) (DATA->s);
    return;
  }

  themeify_panelbar(self,force);
}
Exemple #12
0
/* Fillstyle interpreter- generates/refreshes a gropnode list */
g_error exec_fillstyle_inner(struct gropctxt *ctx,u16 state,
			     u16 property) {
  g_error e;
  u32 fssize;  /* Fillstyle size */
  unsigned char *fs;  /* Pointer to the actual fillstyle data */
  unsigned char *p,*plimit;
  unsigned char op;
  int r,g,b;          /* For color arithmetic */
  struct widget *w;
  int stackframe = fsstkpos-4;

  /* Look up the fillstyle */
  e = rdhandle((void**)&fs,PG_TYPE_FILLSTYLE,-1,theme_lookup(state,property));
  errorcheck;

  if (!fs) {
    
    /* When our best just isn't good enough... */
    if (property == PGTH_P_BACKDROP || property == PGTH_P_BORDER_FILL)
      return success;

    /* The default fillstyle, if no theme is loaded or no 
       theme has defined the property*/

    addgrop(ctx,PG_GROP_SETCOLOR);
    ctx->current->param[0] = VID(color_pgtohwr) (0x000000);
    
    switch (state) {

    case PGTH_O_BUTTON_ON:      /* 2 borders */
      addgropsz(ctx,PG_GROP_FRAME,ctx->r.x,ctx->r.y,ctx->r.w,ctx->r.h);
      ctx->r.x += 1; ctx->r.y += 1; ctx->r.w -= 2; ctx->r.h -= 2;
    default:                    /* 1 border */
      addgropsz(ctx,PG_GROP_FRAME,ctx->r.x,ctx->r.y,ctx->r.w,ctx->r.h);
      ctx->r.x += 1; ctx->r.y += 1; ctx->r.w -= 2; ctx->r.h -= 2;
    case PGTH_O_LABEL_SCROLL:   /* No border */
      addgrop(ctx,PG_GROP_SETCOLOR);
      ctx->current->param[0] = VID(color_pgtohwr) (theme_lookup(state,PGTH_P_BGCOLOR));
      addgropsz(ctx,PG_GROP_RECT,ctx->r.x,ctx->r.y,ctx->r.w,ctx->r.h);      
    }
    return success;
  }

  /* Process the opcodes */
  fssize = *(((u32 *)fs)++);
  p = fs;
  plimit = fs+fssize;
  while (p<plimit) {
    op = *(p++);
    
    /* These must occur in MSB to LSB order! (see constants.h) */
    if (op & PGTH_OPSIMPLE_GROP) {
      /* 1-byte gropnode */
      e = fsgrop(ctx,op & (PGTH_OPSIMPLE_GROP-1));
      errorcheck;
    }
    else if (op & PGTH_OPSIMPLE_LITERAL) {
      /* 1-byte literal */
      fsstack[fsstkpos++] = op & (PGTH_OPSIMPLE_LITERAL-1);
    }
    else if (op & PGTH_OPSIMPLE_CMDCODE) {
      /* Command code */
      switch (op) {

      case PGTH_OPCMD_LONGLITERAL:
	if ((plimit-p)<4)
	  return mkerror(PG_ERRT_BADPARAM,91);  /* Truncated opcode */
	 fsstack[fsstkpos++] = NEXTLONG;
	 p += 4;
	 break;

      case PGTH_OPCMD_LONGGROP:
	if ((plimit-p)<2)
	  return mkerror(PG_ERRT_BADPARAM,91);  /* Truncated opcode */
	e = fsgrop(ctx,NEXTSHORT);
	p += 2;
	errorcheck;
	break;

      case PGTH_OPCMD_LONGGET:
	if (plimit<=p)
	  return mkerror(PG_ERRT_BADPARAM,91);  /* Truncated opcode */
	e = fsget(*(p++)+stackframe);
	errorcheck;
	break;

      case PGTH_OPCMD_LONGSET:
	if (plimit<=p)
	  return mkerror(PG_ERRT_BADPARAM,91);  /* Truncated opcode */
	e = fsset(*(p++)+stackframe);
	errorcheck;
	break;

      case PGTH_OPCMD_PROPERTY:
	if ((plimit-p)<4)
	  return mkerror(PG_ERRT_BADPARAM,91);  /* Truncated opcode */
	fsa = NEXTSHORT;
	p += 2;
	fsb = NEXTSHORT;
	p += 2;
	fsstack[fsstkpos++] = theme_lookup(fsa,fsb);

#ifdef CONFIG_ANIMATION
	/* If it depends on time or randomness, turn on the animated flag in the divnode */
	if ((fsb==PGTH_P_TICKS || fsb==PGTH_P_RANDOM) && ctx->owner)
	  ctx->owner->flags |= DIVNODE_ANIMATED;
#endif
	break;

      case PGTH_OPCMD_LOCALPROP:
	if ((plimit-p)<2)
	  return mkerror(PG_ERRT_BADPARAM,91);  /* Truncated opcode */
	 fsa = NEXTSHORT;
	 p += 2;
#ifdef DEBUG_THEME
	 printf("Local theme lookup, property %d\n",(int)fsa);
#endif
	 fsstack[fsstkpos++] = theme_lookup(state,fsa);

#ifdef CONFIG_ANIMATION
	/* If it depends on time or randomness, turn on the animated flag in the divnode */
	if ((fsa==PGTH_P_TICKS || fsa==PGTH_P_RANDOM) && ctx->owner)
	  ctx->owner->flags |= DIVNODE_ANIMATED;
#endif
	break;

      case PGTH_OPCMD_PLUS:
	e = fspopargs();
	errorcheck;
	fsstack[fsstkpos++] = fsa + fsb;
	break;

      case PGTH_OPCMD_MINUS:
	e = fspopargs();
	errorcheck;
	fsstack[fsstkpos++] = fsa -  fsb;
	break;

      case PGTH_OPCMD_MULTIPLY:
	e = fspopargs();
	errorcheck;
	fsstack[fsstkpos++] = fsa * fsb;
	break;

      case PGTH_OPCMD_SHIFTL:
	e = fspopargs();
	errorcheck;
	fsstack[fsstkpos++] = fsa << fsb; 
	break;
	
      case PGTH_OPCMD_SHIFTR:
	e = fspopargs();
	errorcheck;
	fsstack[fsstkpos++] = fsa >> fsb;
	break;

      case PGTH_OPCMD_OR:
	e = fspopargs();
	errorcheck;
	fsstack[fsstkpos++] = fsa | fsb;
	break;

      case PGTH_OPCMD_AND:
	e = fspopargs();
	errorcheck;
	fsstack[fsstkpos++] = fsa & fsb;
	break;

      case PGTH_OPCMD_EQ:
	e = fspopargs();
	errorcheck;
	fsstack[fsstkpos++] = fsa == fsb;
	break;

      case PGTH_OPCMD_LT:
	e = fspopargs();
	errorcheck;
	fsstack[fsstkpos++] = fsa < fsb;
	break;

      case PGTH_OPCMD_GT:
	e = fspopargs();
	errorcheck;
	fsstack[fsstkpos++] = fsa > fsb;
	break;

      case PGTH_OPCMD_LOGICAL_OR:
	e = fspopargs();
	errorcheck;
	fsstack[fsstkpos++] = fsa || fsb;
	break;

      case PGTH_OPCMD_LOGICAL_AND:
	e = fspopargs();
	errorcheck;
	fsstack[fsstkpos++] = fsa && fsb;
	break;

      case PGTH_OPCMD_LOGICAL_NOT:
	fsstack[fsstkpos-1] = !fsstack[fsstkpos-1];
	break;

      case PGTH_OPCMD_DIVIDE:   
	e = fspopargs();
	errorcheck;
	if (fsb)
	  fsstack[fsstkpos++] = fsa / fsb; 
	else
	  fsstack[fsstkpos++] = 0xFFFFFFFF;   /* limit of fsa/fsb as fsb approaches 0 */
	break;

      case PGTH_OPCMD_COLORADD:
	e = fspopargs();
	errorcheck;
	r = getred(fsa);
	g = getgreen(fsa);
	b = getblue(fsa);
	r += getred(fsb);
	g += getgreen(fsb);
	b += getblue(fsb);
	if (r>255) r = 255;
	if (g>255) g = 255;
	if (b>255) b = 255;
	fsstack[fsstkpos++] = mkcolor(r,g,b);
	break;

      case PGTH_OPCMD_COLORSUB:
	e = fspopargs();
	errorcheck;
	r = getred(fsa);
	g = getgreen(fsa);
	b = getblue(fsa);
	r -= getred(fsb);
	g -= getgreen(fsb);
	b -= getblue(fsb);
	if (r<0) r = 0;
	if (g<0) g = 0;
	if (b<0) b = 0;
	fsstack[fsstkpos++] = mkcolor(r,g,b);
	break;

      case PGTH_OPCMD_COLORDIV:
	e = fspopargs();
	errorcheck;
	r = getred(fsa);
	g = getgreen(fsa);
	b = getblue(fsa);
	r = getred(fsb) ? (r/getred(fsb)) : 0xFF;     /* Avoid divide by zero */
	g = getgreen(fsb) ? (g/getgreen(fsb)) : 0xFF; 
	b = getred(fsb) ? (b/getblue(fsb)) : 0xFF;
     	fsstack[fsstkpos++] = mkcolor(r,g,b);
	break;

      case PGTH_OPCMD_COLORMULT:
	e = fspopargs();
	errorcheck;
	r = getred(fsa);
	g = getgreen(fsa);
	b = getblue(fsa);
	r *= getred(fsb);
	g *= getgreen(fsb);
	b *= getblue(fsb);
	if (r>255) r = 255;
	if (g>255) g = 255;
	if (b>255) b = 255;
	fsstack[fsstkpos++] = mkcolor(r,g,b);
	break;

      case PGTH_OPCMD_QUESTIONCOLON:
	if (fsstkpos<3)
	  return mkerror(PG_ERRT_BADPARAM,88);  /* Stack underflow */
	fsstkpos -= 2;
	fsstack[fsstkpos-1] = fsstack[fsstkpos+1] ? 
	  fsstack[fsstkpos] : fsstack[fsstkpos-1];
	break;

      case PGTH_OPCMD_WIDGET:
	if (ctx->owner && ctx->owner->owner)
	  fsstack[fsstkpos++] = hlookup(ctx->owner->owner,NULL);
	else
	  fsstack[fsstkpos++] = 0;
	break;
	
      case PGTH_OPCMD_TRAVERSEWGT:
	if (fsstkpos<3)
	  return mkerror(PG_ERRT_BADPARAM,88);  /* Stack underflow */
	fsstkpos -= 2;
	e = rdhandle((void**)&w, PG_TYPE_WIDGET, -1, fsstack[fsstkpos+1]);
	errorcheck;
	if (w)
	  fsstack[fsstkpos-1] = hlookup(widget_traverse(w,fsstack[fsstkpos],fsstack[fsstkpos-1]),NULL);
	else
	  fsstack[fsstkpos-1] = 0;
	break;

      case PGTH_OPCMD_GETWIDGET:
	e = fspopargs();
	errorcheck;
	e = rdhandle((void**)&w, PG_TYPE_WIDGET, -1, fsa);
	errorcheck;
	if (w) 
	  fsstack[fsstkpos++] = widget_get(w,fsb);
	else
	  fsstack[fsstkpos++] = 0;
	break;

      case PGTH_OPCMD_CALL:
	if ((plimit-p)<4)
	  return mkerror(PG_ERRT_BADPARAM,91);  /* Truncated opcode */
	fsa = NEXTSHORT;
	p += 2;
	fsb = NEXTSHORT;
	p += 2;
	e = exec_fillstyle_inner(ctx,fsa,fsb);
	errorcheck;
	break;

      case PGTH_OPCMD_LOCALCALL:
	if ((plimit-p)<2)
	  return mkerror(PG_ERRT_BADPARAM,91);  /* Truncated opcode */
	fsb = NEXTSHORT;
	p += 2;
	e = exec_fillstyle_inner(ctx,state,fsb);
	errorcheck;
	break;

      case PGTH_OPCMD_EXTENDED:
	/* extended command */
	op = *(p++);
	switch (op) {

	case PGTH_EXCMD_SKIP_IF:
	  if (!fsstack[--fsstkpos]) {
	    --fsstkpos;
	    break;
	  }
	  /* else proceed to EXCMD_SKIP */

	case PGTH_EXCMD_SKIP:
	  p += (s32)fsstack[--fsstkpos];
	  break;

	}
	break;

      }
    }
    else if (op & PGTH_OPSIMPLE_GET) {
      /* 1-byte get */
      e = fsget((op & (PGTH_OPSIMPLE_GET-1)) + stackframe);
      errorcheck;
    }
    else {
      /* 1-byte set */
      e = fsset(op + stackframe);
      errorcheck;
    }

#ifdef DEBUG_THEME
    /* trace */
    printf("FILLSTYLE --- Op: 0x%02X Stk:",op);
    for (fsa=0;fsa<fsstkpos;fsa++)
      printf(" %d",(int)fsstack[fsa]);
    printf("\n"); 
#endif
    
    /* check for stack over/underflow */
    if (fsstkpos<0)
      return mkerror(PG_ERRT_BADPARAM,88);  /* Stack underflow */
    if (fsstkpos>=FSSTACKSIZE)
      return mkerror(PG_ERRT_BADPARAM,89);  /* Stack overflow */
  }
Exemple #13
0
/* Called when our tab button is selected or deselected */
static int tabpage_tab_callback(int event, struct widget *from, s32 param, int owner, const u8 *data) {
  tabpage_show_hide(from->callback_owner, widget_get(from, PG_WP_ON));
  post_event(PG_WE_ACTIVATE,from->callback_owner,0,0,NULL);
}
Exemple #14
0
/* This is called whenever the widget is attached, after the attaching
 * process is complete. We use this as a hook for managing the tab and tab_bar.
 */
g_error tabpage_post_attach(struct widget *self, struct widget *parent, int rship) {
  struct widget *tab, *tab_bar, *parent_tab;
  g_error e;
  handle existing_bar = 0;

  /* Dereference handles */
  e = rdhandle((void**)&tab, PG_TYPE_WIDGET, self->owner, DATA->htab);
  errorcheck;
  e = rdhandle((void**)&tab_bar, PG_TYPE_WIDGET, self->owner, DATA->htab_bar);
  errorcheck;

  /* Detach our tab. It will be reattached later if necessary */
  e = widget_derive(&tab, &DATA->htab, tab->type, NULL, 0, 0, self->owner);
  errorcheck;

  /* If we already have a tab bar but it's empty, delete it */
  if (DATA->htab_bar && !widget_traverse(tab_bar, PG_TRAVERSE_CHILDREN, 0)) {
    handle_free(self->owner, DATA->htab_bar);
    DATA->htab_bar = 0;
  }

  /* Are we being attached rather than detached? */
  if (parent) {

    /* If we're attaching before or after another tab page, share its tab bar */
    if (parent->type==PG_WIDGET_TABPAGE &&
	(rship==PG_DERIVE_BEFORE || rship==PG_DERIVE_AFTER)) {
      struct widget *self = parent;
      existing_bar = DATA->htab_bar;
    }
    DATA->htab_bar = existing_bar;

    /* Otherwise, create a new tab bar */
    if (!DATA->htab_bar) {
      tab_bar = NULL;
      e = widget_derive(&tab_bar, &DATA->htab_bar, PG_WIDGET_TOOLBAR,
			self, self->h, PG_DERIVE_BEFORE, self->owner);
      errorcheck;
      e = widget_set(tab_bar, PG_WP_THOBJ, PGTH_O_TAB_BAR);
      errorcheck;
      tab_bar->auto_orientation = PG_AUTO_SIDE;
    }

    /* If we're attaching on an existing bar, attach the tab in the same
     * relative order as the tab pages themselves.
     */
    parent_tab = NULL;
    rdhandle((void**)&parent_tab, PG_TYPE_WIDGET, self->owner, widget_get(parent, PG_WP_TAB));
    if (existing_bar && parent_tab) {
      e = widget_derive(&tab, &DATA->htab, tab->type,
			parent_tab, parent_tab->h, rship, self->owner);
      errorcheck;
    }
    /* Otherwise just put it in our tab bar directly */
    else {
      e = widget_derive(&tab, &DATA->htab, tab->type,
			tab_bar, tab_bar->h, PG_DERIVE_INSIDE, self->owner);
      errorcheck;
    }      
		
    /* If we were here first, make ourselves active */
    if (!existing_bar) {
      e = widget_set(self, PG_WP_ON, 1);
      errorcheck;
    }
  }

  return success;
}