*/ REBINT Text_Gob(void *richtext, REBSER *block) /* ** Handles all commands for the TEXT dialect as specified ** in the system/dialects/text object. ** ** This function calls the REBOL_Dialect interpreter to ** parse the dialect and build and return the command number ** (the index offset in the text object above) and a block ** of arguments. (For now, just a REBOL block, but this could ** be changed to isolate it from changes in REBOL's internals). ** ** Each arg will be of the specified datatype (given in the ** dialect) or NONE when no argument of that type was given ** and this code must determine the proper default value. ** ** If the cmd result is zero, then it is either the end of ** the block, or an error has occurred. If the error value ** is non-zero, then it was an error. ** ***********************************************************************/ { REBCNT index = 0; REBINT cmd; REBSER *args = 0; REBVAL *arg; REBCNT nargs; //font object conversion related values REBFNT* font; REBVAL* val; REBPAR offset; REBPAR space; //para object conversion related values REBPRA* para; REBPAR origin; REBPAR margin; REBPAR indent; REBPAR scroll; do { cmd = Reb_Dialect(DIALECTS_TEXT, block, &index, &args); if (cmd == 0) return 0; if (cmd < 0) { // Reb_Print("ERROR: %d, Index %d", -cmd, index); return -((REBINT)index+1); } // else // Reb_Print("TEXT: Cmd %d, Index %d, Args %m", cmd, index, args); arg = BLK_HEAD(args); nargs = SERIES_TAIL(args); // Reb_Print("Number of args: %d", nargs); switch (cmd) { case TW_TYPE_SPEC: if (IS_STRING(arg)) { rt_text(richtext, ARG_STRING(0), index); } else if (IS_TUPLE(arg)) { rt_color(richtext, ARG_TUPLE(0)); } break; case TW_ANTI_ALIAS: rt_anti_alias(richtext, ARG_OPT_LOGIC(0)); break; case TW_SCROLL: rt_scroll(richtext, ARG_PAIR(0)); break; case TW_BOLD: case TW_B: rt_bold(richtext, ARG_OPT_LOGIC(0)); break; case TW_ITALIC: case TW_I: rt_italic(richtext, ARG_OPT_LOGIC(0)); break; case TW_UNDERLINE: case TW_U: rt_underline(richtext, ARG_OPT_LOGIC(0)); break; case TW_CENTER: rt_center(richtext); break; case TW_LEFT: rt_left(richtext); break; case TW_RIGHT: rt_right(richtext); break; case TW_FONT: if (!IS_OBJECT(arg)) break; font = (REBFNT*)rt_get_font(richtext); val = BLK_HEAD(ARG_OBJECT(0))+1; if (IS_STRING(val)) { font->name = VAL_STRING(val); } // Reb_Print("font/name: %s", font->name); val++; if (IS_BLOCK(val)) { REBSER* styles = VAL_SERIES(val); REBVAL* slot = BLK_HEAD(styles); REBCNT len = SERIES_TAIL(styles) ,i; for (i = 0;i<len;i++){ if (IS_WORD(slot+i)){ set_font_styles(font, slot+i); } } } else if (IS_WORD(val)) { set_font_styles(font, val); } val++; if (IS_INTEGER(val)) { font->size = VAL_INT32(val); } // Reb_Print("font/size: %d", font->size); val++; if ((IS_TUPLE(val)) || (IS_NONE(val))) { COPY_MEM(font->color,VAL_TUPLE(val), 4); } // Reb_Print("font/color: %d.%d.%d.%d", font->color[0],font->color[1],font->color[2],font->color[3]); val++; if ((IS_PAIR(val)) || (IS_NONE(val))) { offset = VAL_PAIR(val); font->offset_x = offset.x; font->offset_y = offset.y; } // Reb_Print("font/offset: %dx%d", offset.x,offset.y); val++; if ((IS_PAIR(val)) || (IS_NONE(val))) { space = VAL_PAIR(val); font->space_x = space.x; font->space_y = space.y; } // Reb_Print("font/space: %dx%d", space.x, space.y); val++; font->shadow_x = 0; font->shadow_y = 0; if (IS_BLOCK(val)) { REBSER* ser = VAL_SERIES(val); REBVAL* slot = BLK_HEAD(ser); REBCNT len = SERIES_TAIL(ser) ,i; for (i = 0;i<len;i++){ if (IS_PAIR(slot)) { REBPAR shadow = VAL_PAIR(slot); font->shadow_x = shadow.x; font->shadow_y = shadow.y; } else if (IS_TUPLE(slot)) { COPY_MEM(font->shadow_color,VAL_TUPLE(slot), 4); } else if (IS_INTEGER(slot)) { font->shadow_blur = VAL_INT32(slot); } slot++; } } else if (IS_PAIR(val)) { REBPAR shadow = VAL_PAIR(val); font->shadow_x = shadow.x; font->shadow_y = shadow.y; } rt_font(richtext, font); break; case TW_PARA: if (!IS_OBJECT(arg)) break; para = (REBPRA*)rt_get_para(richtext); val = BLK_HEAD(ARG_OBJECT(0))+1; if (IS_PAIR(val)) { origin = VAL_PAIR(val); para->origin_x = origin.x; para->origin_y = origin.y; } // Reb_Print("para/origin: %dx%d", origin.x, origin.y); val++; if (IS_PAIR(val)) { margin = VAL_PAIR(val); para->margin_x = margin.x; para->margin_y = margin.y; } // Reb_Print("para/margin: %dx%d", margin.x, margin.y); val++; if (IS_PAIR(val)) { indent = VAL_PAIR(val); para->indent_x = indent.x; para->indent_y = indent.y; } // Reb_Print("para/indent: %dx%d", indent.x, indent.y); val++; if (IS_INTEGER(val)) { para->tabs = VAL_INT32(val); } // Reb_Print("para/tabs: %d", para->tabs); val++; if (IS_LOGIC(val)) { para->wrap = VAL_LOGIC(val); } // Reb_Print("para/wrap?: %d", para->wrap); val++; if (IS_PAIR(val)) { scroll = VAL_PAIR(val); para->scroll_x = scroll.x; para->scroll_y = scroll.y; } // Reb_Print("para/scroll: %dx%d", scroll.x, scroll.y); val++; if (IS_WORD(val)) { REBINT result = Reb_Find_Word(VAL_WORD_SYM(val), Symbol_Ids, 0); switch (result){ case SW_RIGHT: case SW_LEFT: case SW_CENTER: para->align = result; break; default: para->align = SW_LEFT; break; } } val++; if (IS_WORD(val)) { REBINT result = Reb_Find_Word(VAL_WORD_SYM(val), Symbol_Ids, 0); switch (result){ case SW_TOP: case SW_BOTTOM: case SW_MIDDLE: para->valign = result; break; default: para->valign = SW_TOP; break; } } rt_para(richtext, para); break; case TW_SIZE: rt_font_size(richtext, ARG_INTEGER(0)); break; case TW_SHADOW: rt_shadow(richtext, &ARG_PAIR(0), ARG_TUPLE(1), ARG_INTEGER(2)); break; case TW_DROP: rt_drop(richtext, ARG_OPT_INTEGER(0)); break; case TW_NEWLINE: case TW_NL: rt_newline(richtext, index); break; case TW_CARET: { REBPAR caret = {0,0}; REBPAR highlightStart = {0,0}; REBPAR highlightEnd = {0,0}; REBVAL *slot; if (!IS_OBJECT(arg)) break; val = BLK_HEAD(ARG_OBJECT(0))+1; if (IS_BLOCK(val)) { slot = BLK_HEAD(VAL_SERIES(val)); if (SERIES_TAIL(VAL_SERIES(val)) == 2 && IS_BLOCK(slot) && IS_STRING(slot+1)){ caret.x = 1 + slot->data.series.index; caret.y = 1 + (slot+1)->data.series.index;; //Reb_Print("caret %d, %d", caret.x, caret.y); } } val++; if (IS_BLOCK(val)) { slot = BLK_HEAD(VAL_SERIES(val)); if (SERIES_TAIL(VAL_SERIES(val)) == 2 && IS_BLOCK(slot) && IS_STRING(slot+1)){ highlightStart.x = 1 + slot->data.series.index; highlightStart.y = 1 + (slot+1)->data.series.index;; //Reb_Print("highlight-start %d, %d", highlightStart.x, highlightStart.y); } } val++; if (IS_BLOCK(val)) { slot = BLK_HEAD(VAL_SERIES(val)); if (SERIES_TAIL(VAL_SERIES(val)) == 2 && IS_BLOCK(slot) && IS_STRING(slot+1)){ highlightEnd.x = 1 + slot->data.series.index; highlightEnd.y = 1 + (slot+1)->data.series.index;; //Reb_Print("highlight-End %d, %d", highlightEnd.x, highlightEnd.y); } } rt_caret(richtext, &caret, &highlightStart,&highlightEnd); } break; } } while (TRUE); }
*/ RXIEXT int RXD_Text(int cmd, RXIFRM *frm, REBCEC *ctx) /* ** DRAW command dispatcher. ** ***********************************************************************/ { switch (cmd) { case CMD_TEXT_INIT_WORDS: //temp hack - will be removed later text_ext_words = RL_MAP_WORDS(RXA_SERIES(frm,1)); break; case CMD_TEXT_ANTI_ALIAS: rt_anti_alias(ctx->envr, RXA_LOGIC(frm, 1)); break; case CMD_TEXT_BOLD: rt_bold(ctx->envr, RXA_LOGIC(frm, 1)); break; case CMD_TEXT_CARET: { RXIARG val; u32 *words, *w; REBSER *obj; REBCNT type; REBXYF caret, highlightStart, highlightEnd; REBXYF *pcaret = 0, *phighlightStart = 0; obj = RXA_OBJECT(frm, 1); //Reb_Print("RXI_WORDS_OF_OBJECT() called\n"); words = RL_WORDS_OF_OBJECT(obj); //Reb_Print("RXI_WORDS_OF_OBJECT() OK\n"); w = words; while (type = RL_GET_FIELD(obj, w[0], &val)) { // RL_Print("word: %d %d %d\n", w[0],w[1], (REBYTE)w[1]); switch(RL_FIND_WORD(text_ext_words,w[0])) { case W_TEXT_CARET: if (type == RXT_BLOCK){ REBSER* block = val.series; REBINT len = RL_SERIES(block, RXI_SER_TAIL); if (len > 1){ RXIARG pos, elem; if ( RL_GET_VALUE(block, 0, &pos) == RXT_BLOCK && RL_GET_VALUE(block, 1, &elem) == RXT_STRING ){ caret.x = 1 + pos.index; caret.y = 1 + elem.index; pcaret = ⁁ } } } break; case W_TEXT_HIGHLIGHT_START: if (type == RXT_BLOCK){ REBSER* block = val.series; REBINT len = RL_SERIES(block, RXI_SER_TAIL); if (len > 1){ RXIARG pos, elem; if ( RL_GET_VALUE(block, 0, &pos) == RXT_BLOCK && RL_GET_VALUE(block, 1, &elem) == RXT_STRING ){ highlightStart.x = 1 + pos.index; highlightStart.y = 1 + elem.index; phighlightStart = &highlightStart; } } } break; case W_TEXT_HIGHLIGHT_END: if (type == RXT_BLOCK){ REBSER* block = val.series; REBINT len = RL_SERIES(block, RXI_SER_TAIL); if (len > 1){ RXIARG pos, elem; if ( RL_GET_VALUE(block, 0, &pos) == RXT_BLOCK && RL_GET_VALUE(block, 1, &elem) == RXT_STRING ){ highlightEnd.x = 1 + pos.index; highlightEnd.y = 1 + elem.index; } } } break; } w++; } OS_Free(words); rt_caret(ctx->envr, pcaret, phighlightStart, highlightEnd); } break; case CMD_TEXT_CENTER: rt_center(ctx->envr); break; case CMD_TEXT_COLOR: rt_color(ctx->envr, RXA_TUPLE(frm,1) + 1); break; case CMD_TEXT_DROP: rt_drop(ctx->envr, RXA_INT32(frm,1)); break; case CMD_TEXT_FONT: { RXIARG val; u32 *words,*w; REBSER *obj; REBCNT type; REBFNT *font = rt_get_font(ctx->envr); obj = RXA_OBJECT(frm, 1); words = RL_WORDS_OF_OBJECT(obj); w = words; while (type = RL_GET_FIELD(obj, w[0], &val)) { switch(RL_FIND_WORD(text_ext_words,w[0])) { case W_TEXT_NAME: if (type == RXT_STRING){ wchar_t* str; REBCNT gc = TRUE; if (RL_GET_STRING(val.series, 0 , (void*)&str) < 0){ size_t newSize = mbstowcs(NULL, (char*)str, 0) + 1; size_t origsize = strlen((char*)str) + 1; //note: following string will be deallocated by the rich text module wchar_t* wstr = OS_Make(newSize * sizeof( wchar_t )); mbstowcs(wstr, (char*)str, newSize); str = wstr; gc = FALSE; } font->name = str; font->name_gc = gc; } break; case W_TEXT_STYLE: switch(type) { case RXT_WORD: { u32 styleWord = RL_FIND_WORD(text_ext_words,val.int32a); if (styleWord) rt_set_font_styles(font, styleWord); } break; case RXT_BLOCK: { RXIARG styleVal; REBCNT styleType; REBCNT n; u32 styleWord; for (n = 0; styleType = RL_GET_VALUE(val.series, n, &styleVal); n++) { if (styleType == RXT_WORD) { styleWord = RL_FIND_WORD(text_ext_words,styleVal.int32a); if (styleWord) rt_set_font_styles(font, styleWord); } } } break; } break; case W_TEXT_SIZE: if (type == RXT_INTEGER) font->size = val.int64; break; case W_TEXT_COLOR: if (type == RXT_TUPLE) memcpy(font->color,val.bytes + 1 , 4); break; case W_TEXT_OFFSET: if (type == RXT_PAIR) { font->offset_x = val.pair.x; font->offset_y = val.pair.y; } break; case W_TEXT_SPACE: if (type == RXT_PAIR) { font->space_x = val.pair.x; font->space_y = val.pair.y; } break; case W_TEXT_SHADOW: switch(type) { case RXT_PAIR: { font->shadow_x = val.pair.x; font->shadow_y = val.pair.y; } break; case RXT_BLOCK: { RXIARG shadowVal; REBCNT shadowType; REBCNT n; for (n = 0; shadowType = RL_GET_VALUE(val.series, n, &shadowVal); n++) { switch (shadowType) { case RXT_PAIR: font->shadow_x = shadowVal.pair.x; font->shadow_y = shadowVal.pair.y; break; case RXT_TUPLE: memcpy(font->shadow_color,shadowVal.bytes + 1 , 4); break; case RXT_INTEGER: font->shadow_blur = shadowVal.int64; break; } } } break; } break; } w++; } OS_Free(words); rt_font(ctx->envr, font); } break; case CMD_TEXT_ITALIC: rt_italic(ctx->envr, RXA_LOGIC(frm, 1)); break; case CMD_TEXT_LEFT: rt_left(ctx->envr); break; case CMD_TEXT_NEWLINE: rt_newline(ctx->envr, ctx->index + 1); break; case CMD_TEXT_PARA: { RXIARG val; u32 *words,*w; REBSER *obj; REBCNT type; REBPRA *para = rt_get_para(ctx->envr); obj = RXA_OBJECT(frm, 1); words = RL_WORDS_OF_OBJECT(obj); w = words; while (type = RL_GET_FIELD(obj, w[0], &val)) { switch(RL_FIND_WORD(text_ext_words,w[0])) { case W_TEXT_ORIGIN: if (type == RXT_PAIR) { para->origin_x = val.pair.x; para->origin_y = val.pair.y; } break; case W_TEXT_MARGIN: if (type == RXT_PAIR) { para->margin_x = val.pair.x; para->margin_y = val.pair.y; } break; case W_TEXT_INDENT: if (type == RXT_PAIR) { para->indent_x = val.pair.x; para->indent_y = val.pair.y; } break; case W_TEXT_TABS: if (type == RXT_INTEGER) { para->tabs = val.int64; } break; case W_TEXT_WRAPQ: if (type == RXT_LOGIC) { para->wrap = val.int32a; } break; case W_TEXT_SCROLL: if (type == RXT_PAIR) { para->scroll_x = val.pair.x; para->scroll_y = val.pair.y; } break; case W_TEXT_ALIGN: if (type == RXT_WORD) { para->align = RL_FIND_WORD(text_ext_words,val.int32a); } break; case W_TEXT_VALIGN: if (type == RXT_WORD) { para->valign = RL_FIND_WORD(text_ext_words,val.int32a); } break; } w++; } OS_Free(words); rt_para(ctx->envr, para); } break; case CMD_TEXT_RIGHT: rt_right(ctx->envr); break; case CMD_TEXT_SCROLL: rt_scroll(ctx->envr, RXA_PAIR(frm, 1)); break; case CMD_TEXT_SHADOW: rt_shadow(ctx->envr, RXA_PAIR(frm, 1), RXA_TUPLE(frm,2) + 1, RXA_INT32(frm,3)); break; case CMD_TEXT_SIZE: rt_font_size(ctx->envr, RXA_INT32(frm,1)); break; case CMD_TEXT_TEXT: { REBCHR* str; REBCNT gc = TRUE; if (RL_GET_STRING(RXA_SERIES(frm, 1), 0 , (void*)&str) < 0){ size_t newSize = mbstowcs(NULL, (char*)str, 0) + 1; size_t origsize = strlen((char*)str) + 1; //note: following string will be deallocated by the rich text module wchar_t* wstr = OS_Make(newSize * sizeof( wchar_t )); mbstowcs(wstr, (char*)str, newSize); str = (REBCHR*)wstr; gc = FALSE; } rt_text(ctx->envr, str, ctx->index + 2, gc); } break; case CMD_TEXT_UNDERLINE: rt_underline(ctx->envr, RXA_LOGIC(frm, 1)); break; default: return RXR_NO_COMMAND; } return RXR_UNSET; }