示例#1
0
*/	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);
}
示例#2
0
文件: api.c 项目: taohonker/Ovito
/* allocate and initialize a scene with default parameters */
SceneHandle rt_newscene(void) {
  scenedef * scene;
  SceneHandle voidscene;
  apicolor bgcolor = rt_color(0.0, 0.0, 0.0);
  apicolor ambcolor = rt_color(1.0, 1.0, 1.0);

  scene = (scenedef *) malloc(sizeof(scenedef));
  memset(scene, 0, sizeof(scenedef));             /* clear all valuas to 0  */

  voidscene = (SceneHandle) scene;

  rt_outputfile(voidscene, "/tmp/outfile.tga");   /* default output file    */
  rt_crop_disable(voidscene);                     /* disable cropping */
  rt_outputformat(voidscene, RT_FORMAT_TARGA);    /* default iamge format   */
  rt_resolution(voidscene, 512, 512);             /* 512x512 resolution     */
  rt_verbose(voidscene, 0);                       /* verbose messages off   */

  rt_image_gamma(voidscene, 2.2f);                /* set default gamma */
  rt_image_clamp(voidscene);                      /* clamp image colors */

#if 1
  rt_rawimage_rgb96f(voidscene, NULL);            /* raw image output off   */
#else
  rt_rawimage_rgb24(voidscene, NULL);             /* raw image output off   */
#endif

  rt_boundmode(voidscene, RT_BOUNDING_ENABLED);   /* spatial subdivision on */
  rt_boundthresh(voidscene, BOUNDTHRESH);         /* default threshold      */
  rt_camera_setup(voidscene, 1.0, 1.0, 0, 6,
                  rt_vector(0.0, 0.0, 0.0),
                  rt_vector(0.0, 0.0, 1.0),
                  rt_vector(0.0, 1.0, 0.0));
  rt_camera_dof(voidscene, 1.0, 0.0);
  rt_shadermode(voidscene, RT_SHADER_AUTO);
  rt_rescale_lights(voidscene, 1.0);
  rt_phong_shader(voidscene, RT_SHADER_BLINN);

  rt_background(voidscene, bgcolor);
  rt_background_sky_sphere(voidscene, rt_vector(0.0, 1.0, 0.0), 0.3, 0, 
                           rt_color(0.0, 0.0, 0.0), rt_color(0.0, 0.0, 0.5));
  rt_background_mode(voidscene, RT_BACKGROUND_TEXTURE_SOLID);

  rt_ambient_occlusion(voidscene, 0, ambcolor);    /* disable AO by default  */
  rt_fog_rendering_mode(voidscene, RT_FOG_NORMAL); /* radial fog by default  */
  rt_fog_mode(voidscene, RT_FOG_NONE);             /* disable fog by default */
  rt_fog_parms(voidscene, bgcolor, 0.0, 1.0, 1.0);

  /* use max positive integer for max transparent surface limit by default */
  rt_trans_max_surfaces(voidscene,((((int)1) << ((sizeof(int) * 8) - 2))-1)*2);

  rt_trans_mode(voidscene, RT_TRANS_ORIG);         /* set transparency mode  */
  rt_normal_fixup_mode(voidscene, 0);              /* disable normal fixup   */
  rt_shadow_filtering(voidscene, 1);               /* shadow filtering on    */

  scene->objgroup.boundedobj = NULL;
  scene->objgroup.unboundedobj = NULL;
  scene->objgroup.numobjects = 0;

  scene->texlist = NULL;
  scene->lightlist = NULL;
  scene->cliplist = NULL;
  scene->numlights = 0;
  scene->scenecheck = 1;
  scene->parbuf = NULL;
  scene->threads = NULL;
  scene->threadparms = NULL;
  scene->flags = RT_SHADE_NOFLAGS;
 
  rt_set_numthreads(voidscene, -1);         /* auto determine num threads */ 

  /* number of distributed memory nodes, fills in array of node/cpu info */
  scene->nodes = rt_getcpuinfo(&scene->cpuinfo);
  scene->mynode = rt_mynode();

  return scene;
}
示例#3
0
*/	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 = &caret;
                                }
                            }
                        }
                        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;
}