int Widget_SetAttributeEx(LCUI_Widget w, const char *name, void *value, int value_type, void (*value_destructor)(void *)) { LCUI_WidgetAttribute attr; if (!self.available) { self.dt_attributes = DictType_StringCopyKey; self.dt_attributes.valDestructor = OnClearWidgetAttribute; self.available = TRUE; } if (!w->attributes) { w->attributes = Dict_Create(&self.dt_attributes, NULL); } attr = Dict_FetchValue(w->attributes, name); if (attr) { if (attr->value.destructor) { attr->value.destructor(attr->value.data); } } else { attr = NEW(LCUI_WidgetAttributeRec, 1); attr->name = strdup2(name); Dict_Add(w->attributes, attr->name, attr); } attr->value.data = value; attr->value.type = value_type; attr->value.destructor = value_destructor; return 0; }
const char *Widget_GetAttribute(LCUI_Widget w, const char *name) { LCUI_WidgetAttribute attr; if (!w->attributes) { return NULL; } attr = Dict_FetchValue(w->attributes, name); if (attr) { return attr->value.string; } return NULL; }
int LCUI_AddCSSParser( LCUI_StyleParser sp ) { LCUI_StyleParser new_sp; if( !sp->name || strlen( sp->name ) < 1 ) { return -1; } if( Dict_FetchValue( self.parsers, sp->name ) ) { return -2; } self.count += 1; new_sp = NEW( LCUI_StyleParserRec, 1 ); new_sp->key = sp->key; new_sp->parse = sp->parse; new_sp->name = strdup( sp->name ); Dict_Add( self.parsers, new_sp->name, new_sp ); return 0; }
/** 载入CSS代码块,用于实现CSS代码的分块载入 */ static int LCUI_LoadCSSBlock( CSSParserContext ctx, const char *str ) { size_t size = 0; LCUI_Selector s; LinkedListNode *node; ctx->ptr = str; for( ; *ctx->ptr && size < ctx->buffer_size; ++ctx->ptr, ++size ) { switch( ctx->target ) { case TARGET_SELECTOR: switch( *ctx->ptr ) { case '/': goto proc_comment; case '{': ctx->target = TARGET_KEY; ctx->css = StyleSheet(); case ',': ctx->buffer[ctx->pos] = 0; ctx->pos = 0; DEBUG_MSG("selector: %s\n", ctx->buffer); s = Selector( ctx->buffer ); if( !s ) { // 解析出错 ... break; } LinkedList_Append( &ctx->selectors, s ); break; default: ctx->buffer[ctx->pos++] = *ctx->ptr; break; } break; case TARGET_KEY: switch( *ctx->ptr ) { case '/': goto proc_comment; case ' ': case '\n': case '\r': case '\t': case ';': ctx->pos = 0; continue; case ':': break; case '}': ctx->target = TARGET_NONE; goto put_css; default: ctx->buffer[ctx->pos++] = *ctx->ptr; continue; } goto select_parser; case TARGET_VALUE: switch( *ctx->ptr ) { case '/': goto proc_comment; case '}': case ';': goto parse_value; case '\n': case '\r': case '\t': case ' ': if( ctx->pos == 0 ) { continue; } default: ctx->buffer[ctx->pos++] = *ctx->ptr; continue; } break; case TARGET_COMMENT: if( ctx->is_line_comment ) { if( *ctx->ptr == '\n' ) { ctx->target = ctx->target_bak; } break; } if( *ctx->ptr == '/' && *(ctx->ptr - 1) == '*' ) { ctx->target = ctx->target_bak; } break; case TARGET_NONE: default: switch( *ctx->ptr ) { case '/': goto proc_comment; case '\n': case '\t': case '\r': case ' ': case ',': case '{': case '\\': case '"': case '}': continue; default: break; } ctx->pos = 0; ctx->buffer[ctx->pos++] = *ctx->ptr; ctx->target = TARGET_SELECTOR; break; } continue; proc_comment: switch( *(ctx->ptr + 1) ) { case '/': ctx->is_line_comment = TRUE; break; case '*': ctx->is_line_comment = FALSE; break; default: ctx->buffer[ctx->pos++] = *ctx->ptr; continue; } if( ctx->target_bak != TARGET_COMMENT ) { ctx->target_bak = ctx->target; ctx->target = TARGET_COMMENT; } continue; put_css: DEBUG_MSG("put css\n"); /* 将记录的样式表添加至匹配到的选择器中 */ for( LinkedList_Each( node, &ctx->selectors ) ) { LCUI_PutStyleSheet( node->data, ctx->css, ctx->space ); } LinkedList_Clear( &ctx->selectors, (FuncPtr)Selector_Delete ); StyleSheet_Delete( ctx->css ); continue; select_parser: ctx->target = TARGET_VALUE; ctx->buffer[ctx->pos] = 0; ctx->pos = 0; ctx->parser = Dict_FetchValue( self.parsers, ctx->buffer ); DEBUG_MSG("select style: %s, parser: %p\n", ctx->buffer, ctx->parser); continue; parse_value: if( *ctx->ptr == ';' ) { ctx->target = TARGET_KEY; } if( !ctx->parser ) { continue; } ctx->buffer[ctx->pos] = 0; ctx->pos = 0; ctx->parser->parse( ctx->css, ctx->parser->key, ctx->buffer ); DEBUG_MSG("parse style value: %s, result: %d\n", ctx->buffer); if( *ctx->ptr == '}' ) { ctx->target = TARGET_NONE; goto put_css; } } return size; }