g_error widget_create(struct widget **w, handle *h, int type, struct divtree *dt, handle container, int owner) { g_error e; DBG("type %d, container %d, owner %d\n",type,container,owner); type = appmgr_widget_map(type); if (!dt) dt = DT_NIL; /* Check the type. */ if ( type > PG_WIDGETMAX ) return mkerror(PG_ERRT_BADPARAM, 20); /* Check if it's supported */ if (!widgettab[type].install) return (g_error) (long) widgettab[type].remove; #ifdef DEBUG_KEYS num_widgets++; #endif /* Allocate new widget memory and zero it out. */ e = g_malloc((void **)w, sizeof(struct widget)); errorcheck; memset(*w, 0, sizeof(struct widget)); /* Initialize the elements we can. Since this widget is unattached. */ (*w)->owner = owner; (*w)->type = type; (*w)->def = widgettab + type; (*w)->dt = dt; (*w)->container = container; /* Allocate data pointers for this widget and everythign it's subclassed from */ e = g_malloc((void**)&(*w)->subclasses, sizeof(struct widget_subclass) * ((*w)->def->subclass_num + 1)); errorcheck; /* Allocate a handle for this widget before calling install, so that it may * use the handle when setting up subwidgets. */ e = mkhandle(h,PG_TYPE_WIDGET,owner,*w); errorcheck; (*w)->h = *h; /* Initialize this instance of the widget. This install function should initialize * the widget it's subclassed from first, if any */ (*(*w)->def->install)(*w); return success; }
void textedit_build ( struct gropctxt *c, unsigned short state, struct widget *self ) { s16 w, h, tw; g_error e; w = self->in->div->r.w - theme_lookup(PGTH_O_SCROLL_V,PGTH_P_WIDTH); h = self->in->div->r.h; self->in->div->preferred.h = h; self->in->div->preferred.w = w; if (!DATA->fd){ /* FIXME: Theme lookup foreground, background colors, border */ e = textedit_set_font (self, theme_lookup (state, PGTH_P_FONT)); // errorcheck; } assert (DATA->fd); /* * The general rule is that once you create a handle you should never * delete the object it refers to, only delete the handle */ handle_free(self->owner,DATA->bit_h); e = VID(bitmap_new) (&(DATA->bit), w, h, vid->bpp); // errorcheck; /* the handle should be owned by the application not by pgserver itself */ e = mkhandle(&DATA->bit_h, PG_TYPE_BITMAP, self->owner, DATA->bit); // errorcheck; /* Size and add the bitmap itself */ e = addgropsz(c, PG_GROP_BITMAP, 0, 0, w, h); // errorcheck; c->current->param[0] = DATA->bit_h; /* Create cursor */ e = addgropsz(c,PG_GROP_RECT, 0, 0, 0, 0); // errorcheck; c->current->flags |= PG_GROPF_COLORED; DATA->cursor_grop = c->current; DATA->cursor_state = 1; DATA->cursor_grop->param[0] = VID(color_pgtohwr)(CURSORCOLOR_ON); /* Set cursor height to that of typical char */ textedit_str_size(self, NULL, 0, &tw, &DATA->cursor_grop->r.h); DATA->cursor_grop->r.x = DATA->border_h; DATA->cursor_grop->r.y = DATA->border_v; e = text_backend_build( DATA, w, h); // errorcheck; // return success; }
/* * Duplicate a handle and it's associated object. * (if it can be duplicated. Widgets, drivers, * and themes currently can't be duplicated) */ g_error handle_dup(handle *dest, int owner, handle src) { struct handlenode *n; void *newobj; g_error e; u32 sz; /* Find the handle */ n = htree_find(src); /* make sure it exists */ if (!n) return mkerror(PG_ERRT_HANDLE,26); /* Same permissions as rdhandle() */ if (owner>=0 && n->owner>=0 && n->owner != owner) return mkerror(PG_ERRT_HANDLE,27); /* Check the type */ switch (n->type & PG_TYPEMASK) { case PG_TYPE_PGSTRING: e = pgstring_dup((struct pgstring **)&newobj, (struct pgstring *) n->obj); errorcheck; e = mkhandle(dest,n->type & PG_TYPEMASK,owner,newobj); errorcheck; break; case PG_TYPE_WT: e = wt_instantiate(dest, (struct pgmemwt *) n->obj, src, owner); errorcheck; break; case PG_TYPE_ARRAY: case PG_TYPE_PALETTE: e = g_malloc(&newobj, (((u32*)n->obj)[0] + 1) * sizeof(u32)); errorcheck; e = mkhandle(dest,n->type & PG_TYPEMASK,owner,newobj); errorcheck; memcpy(newobj, n->obj, (((u32*)n->obj)[0] + 1) * sizeof(u32)); break; default: return mkerror(PG_ERRT_BADPARAM,45); /* Can't duplicate object */ } return success; }
/* Create a paragraph and divnode tied to each other */ g_error textbox_new_par_div(struct paragraph **par, struct divnode **div, struct divnode *background) { g_error e; handle hpar; struct gropctxt c; struct paragraph *old_par = *par; struct divnode *old_div = *div; /* Top-level divnode for this paragraph is used for formatting, it's * child is where the paragraph renders to. */ e = newdiv(div,background->owner); errorcheck; (*div)->flags |= DIVNODE_SPLIT_TOP; (*div)->flags &= ~DIVNODE_UNDERCONSTRUCTION; /* We want to prevent the normal groplist clearing in div_rebuild * because the only way our build function has to know the * paragraph handle is by reading the previous groplist. */ e = newdiv(&(*div)->div,background->owner); errorcheck; (*div)->div->build = &textbox_build_par_div; (*div)->div->flags |= DIVNODE_RAW_BUILD; (*div)->div->flags &= ~DIVNODE_UNDERCONSTRUCTION; /* New paragraph with associated handle */ e = paragraph_new(par, *div); errorcheck; e = mkhandle(&hpar, PG_TYPE_PARAGRAPH, -1, *par); errorcheck; (*par)->background = background; /* build the initial groplist- * one incremental paragraph divnode, one normal one. * The size and theme related params will be filled in later. */ gropctxt_init(&c,(*div)->div); addgrop(&c,PG_GROP_SETCOLOR); addgrop(&c,PG_GROP_PARAGRAPH); c.current->param[0] = hpar; addgrop(&c,PG_GROP_PARAGRAPH_INC); c.current->param[0] = hpar; c.current->flags |= PG_GROPF_INCREMENTAL; /* Relink the portion of the paragraph and divnode lists after this node */ (*par)->next = old_par; (*div)->next = old_div; return success; }
g_error cursor_new(struct cursor **crsr, handle *h, int owner) { g_error e; struct cursor *c; handle c_h; /* Allocate cursor */ e = g_malloc((void**)&c, sizeof(struct cursor)); errorcheck; memset(c,0,sizeof(struct cursor)); /* Default at the screen center */ cursor_getposition(NULL,&c->x, &c->y,NULL); /* Add to list */ c->next = cursor_list; cursor_list = c; /* Allocate the sprite */ e = cursor_set_theme(c, PGTH_O_DEFAULT); errorcheck; /* Give the cursor a handle. We always use pointers to * reference cursors internal to pgserver, but when passing * events to and from a client we must refer to the cursor * using only this handle. */ e = mkhandle(&c_h, PG_TYPE_CURSOR, owner, c); errorcheck; if (crsr) *crsr = c; if (h) *h = c_h; return success; }
/* Set the video mode using the current driver. This is the implementation * of the setmode client request */ g_error video_setmode(u16 xres,u16 yres,u16 bpp,u16 flagmode,u32 flags) { g_error e; struct divtree *tree; struct sprite *spr; u8 converting_mode,oldbpp; /* Must be done first */ if (vidwrap->exitmode) { e = VID(exitmode)(); errorcheck; } /* Default values, combine flags */ if (!xres) xres = vid->xres; if (!yres) yres = vid->yres; if (!bpp) bpp = vid->bpp; switch (flagmode) { case PG_FM_ON: flags |= vid->flags; break; case PG_FM_OFF: flags = vid->flags & (~flags); break; case PG_FM_TOGGLE: flags ^= vid->flags; break; } vid->flags = flags; /* If the new bpp is different, use modeconvert/modeunconvert */ oldbpp = vid->bpp; converting_mode = (bpp != vid->bpp); if (converting_mode) { e = bitmap_iterate((handle_iterator)vid->bitmap_modeunconvert, NULL); errorcheck; e = handle_iterate(PG_TYPE_PALETTE,(handle_iterator)array_hwrtopg, NULL); errorcheck; } /* Might want to tell the driver! */ e = (*vid->setmode) (xres,yres,bpp,flags); errorcheck; /* By default logical coordinates are also physical */ vid->lxres = vid->xres; vid->lyres = vid->yres; /* Synchronize vid->display info automatically if we're using stdbitmap */ if (vid->display && vid->bitmap_getsize==def_bitmap_getsize) { if (((struct stdbitmap *)vid->display)->rend) g_free(((struct stdbitmap *)vid->display)->rend); ((struct stdbitmap *)vid->display)->freebits = 0; ((struct stdbitmap *)vid->display)->w = vid->xres; ((struct stdbitmap *)vid->display)->h = vid->yres; ((struct stdbitmap *)vid->display)->bpp = vid->bpp; } /* Reset wrapper library (before using VID macro) */ vidwrap_static = vidlib_static; vidwrap = &vidwrap_static; { /* Generate text colors table */ u32 *tc; int i; /* Default VGA 16-color palette, copied from the Linux console */ static const u32 default_palette[] = { 0x000000, 0xaa0000, 0x00aa00, 0xaaaa00, 0x0000aa, 0xaa00aa, 0x00aaaa, 0xaaaaaa, 0x555555, 0xff5555, 0x55ff55, 0xffff55, 0x5555ff, 0xff55ff, 0x55ffff, 0xffffff, }; /* Allocate space for textcolors if we haven't already */ if (!res[PGRES_DEFAULT_TEXTCOLORS]) { u32 *ptr; e = g_malloc((void**)&ptr,sizeof(u32)*17); errorcheck; ptr[0] = 16; e = mkhandle(&res[PGRES_DEFAULT_TEXTCOLORS],PG_TYPE_PALETTE,-1,(void*)ptr); errorcheck; } e = rdhandle((void **) &tc, PG_TYPE_PALETTE, -1, res[PGRES_DEFAULT_TEXTCOLORS]); errorcheck; /* Transcribe our static palette */ memcpy(tc+1, default_palette, sizeof(default_palette)); /* If we won't be doing it anyway later, go ahead and convert these to hwrcolors */ if (!converting_mode) { e = array_pgtohwr(&tc); errorcheck; } } /* Add wrapper libraries if necessary. At compile-time, support adding * 90, 180, or 270 degrees as a hardware rotation */ #ifdef CONFIG_ROTATIONBASE_90 /***** 90 degree default */ #ifdef CONFIG_ROTATE180 if (vid->flags & PG_VID_ROTATE90) { vidwrap_rotate180(vidwrap); vid->lxres = vid->xres; vid->lyres = vid->yres; } #endif #ifdef CONFIG_ROTATE270 if (vid->flags & PG_VID_ROTATE180) { vidwrap_rotate270(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #ifdef CONFIG_ROTATE if (!(vid->flags & PG_VID_ROTATEMASK)) { vidwrap_rotate90(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #else #ifdef CONFIG_ROTATIONBASE_180 /***** 180 degree default */ #ifdef CONFIG_ROTATE if (vid->flags & PG_VID_ROTATE270) { vidwrap_rotate90(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #ifdef CONFIG_ROTATE270 if (vid->flags & PG_VID_ROTATE90) { vidwrap_rotate270(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #ifdef CONFIG_ROTATE180 if (!(vid->flags & PG_VID_ROTATEMASK)) { vidwrap_rotate180(vidwrap); vid->lxres = vid->xres; vid->lyres = vid->yres; } #endif #else #ifdef CONFIG_ROTATIONBASE_270 /***** 270 degree default */ #ifdef CONFIG_ROTATE if (vid->flags & PG_VID_ROTATE180) { vidwrap_rotate90(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #ifdef CONFIG_ROTATE180 if (vid->flags & PG_VID_ROTATE270) { vidwrap_rotate180(vidwrap); vid->lxres = vid->xres; vid->lyres = vid->yres; } #endif #ifdef CONFIG_ROTATE270 if (!(vid->flags & PG_VID_ROTATEMASK)) { vidwrap_rotate270(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #else /***** 0 degree default */ #ifdef CONFIG_ROTATE if (vid->flags & PG_VID_ROTATE90) { vidwrap_rotate90(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #ifdef CONFIG_ROTATE180 if (vid->flags & PG_VID_ROTATE180) { vidwrap_rotate180(vidwrap); vid->lxres = vid->xres; vid->lyres = vid->yres; } #endif #ifdef CONFIG_ROTATE270 if (vid->flags & PG_VID_ROTATE270) { vidwrap_rotate270(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #endif #endif #endif /* Should we ignore the base screen rotation for keyboard events? */ #ifdef CONFIG_ROTATIONBASE_NOKEYS vidwrap->coord_keyrotate = &def_coord_keyrotate; #ifdef CONFIG_ROTATE if (vid->flags & PG_VID_ROTATE90) vidwrap->coord_keyrotate = &rotate90_coord_keyrotate; #endif #ifdef CONFIG_ROTATE180 if (vid->flags & PG_VID_ROTATE180) vidwrap->coord_keyrotate = &rotate180_coord_keyrotate; #endif #ifdef CONFIG_ROTATE270 if (vid->flags & PG_VID_ROTATE270) vidwrap->coord_keyrotate = &rotate270_coord_keyrotate; #endif #endif /* CONFIG_ROTATIONBASE_NOKEYS */ /* Ignore the base screen rotation for pointing events? */ #ifdef CONFIG_ROTATIONBASE_NOPOINTING vidwrap->coord_physicalize = &def_coord_logicalize; vidwrap->coord_logicalize = &def_coord_logicalize; #ifdef CONFIG_ROTATE if (vid->flags & PG_VID_ROTATE90) { vidwrap->coord_physicalize = &rotate90_coord_physicalize; vidwrap->coord_logicalize = &rotate90_coord_logicalize; } #endif #ifdef CONFIG_ROTATE180 if (vid->flags & PG_VID_ROTATE180) { vidwrap->coord_physicalize = &rotate180_coord_logicalize; vidwrap->coord_logicalize = &rotate180_coord_logicalize; } #endif #ifdef CONFIG_ROTATE270 if (vid->flags & PG_VID_ROTATE270) { vidwrap->coord_physicalize = &rotate270_coord_physicalize; vidwrap->coord_logicalize = &rotate270_coord_logicalize; } #endif #endif /* CONFIG_ROTATIONBASE_NOPOINTING */ /* Since changing video modes pretty much obliterates all onscreen * sprites, and the previous location might be offscreen now, * reset the backbuffer on all sprites */ for (spr=spritelist;spr;spr=spr->next) spr->onscreen = 0; /* Resize the root divnodes of all divtrees in the dtstack */ if (dts) /* (if this is in early init, dtstack isn't here yet) */ for (tree=dts->top;tree;tree=tree->next) { tree->head->r.w = vid->lxres; tree->head->r.h = vid->lyres; tree->head->calc.w = vid->lxres; tree->head->calc.h = vid->lyres; tree->head->flags |= DIVNODE_NEED_RECALC | DIVNODE_FORCE_CHILD_RECALC | DIVNODE_NEED_REBUILD; tree->flags |= DIVTREE_NEED_RECALC | DIVTREE_ALL_REDRAW | DIVTREE_CLIP_POPUP; } /* Convert to the new color depth if necessary */ if (converting_mode) { e = bitmap_iterate((handle_iterator)vid->bitmap_modeconvert, NULL); errorcheck; e = handle_iterate(PG_TYPE_PALETTE,(handle_iterator)array_pgtohwr, NULL); errorcheck; } /* Done swtiching the mode, give the driver a shot at changing * things around */ e = VID(entermode)(); errorcheck; /* Reload things when increasing color depth */ if (oldbpp < bpp) { /* Reload any themes the server is responsible for */ e = reload_initial_themes(); errorcheck; /* FIXME: notify all clients that they can reload here */ } return success; }