const Shader* shaderContext( UThread* ut, const UCell* cell, const UBuffer** blkPtr ) { const UBuffer* ctx; if( ur_is(cell, UT_CONTEXT) ) { ctx = ur_bufferSer( cell ); cell = ur_ctxCell( ctx, 0 ); if( ! cell ) return 0; } else { ctx = 0; } if( ur_is(cell, UT_SHADER) ) { const Shader* sh = (const Shader*) ur_bufferSer( cell )->ptr.v; if( blkPtr ) *blkPtr = ctx; return sh; } return 0; }
void setUniform( UThread* ut, UCell* path, UCell* val ) { if( ur_is(path, UT_SELECT) ) { UCell* cval; Shader* sh; ShaderParam* pi; ShaderParam* pend; cval = ur_buffer( ctx->ctx.valBlk )->ptr.cell; if( cval && ur_is(cval, UT_SHADER) ) { sh = (Shader*) ur_resPtr( cval->series.n )->ptr; pi = sh->param; pend = sh->param + sh->paramCount; while( pi != pend ) { if( pi->name == sel ) { switch( pi->type ) { case GL_INT: case GL_BOOL: glUniform1i( pi->location, ur_int(val) ); break; } return; } ++pi; } } } }
static int getString( UThread* ut, const UCell* cell, QString& str ) { if( ur_is(cell, UT_WORD) || ur_is(cell, UT_GETWORD) ) { if( ! (cell = ur_wordCell( ut, cell )) ) return UR_THROW; } cellToQString( cell, str ); return UR_OK; }
/* "tcp://host:port" "tcp://:port" "udp://host:port" "udp://:port" */ static int socket_open( UThread* ut, const UPortDevice* pdev, const UCell* from, int opt, UCell* res ) { NodeServ ns; SocketExt* ext; int socket; int nowait = opt & UR_PORT_NOWAIT; //int port = 0; //int hostPort = 0; //UCell* initAddr = 0; if( ! ur_is(from, UT_STRING) ) return ur_error( ut, UR_ERR_TYPE, "socket open expected string" ); ext = (SocketExt*) memAlloc( sizeof(SocketExt) ); ext->addrlen = 0; #ifdef _WIN32 ext->event = WSA_INVALID_EVENT; #endif //if( ur_is(from, UT_STRING) ) { stringToNodeServ( ut, from, &ns ); if( ! makeSockAddr( ut, ext, &ns ) ) goto fail; } #if 0 else if( ur_is(from, UT_BLOCK) )
static void slider_setValue( GSlider* ep, const UCell* cell ) { struct Value* da = &ep->data; float n; if( ur_is(cell, UT_INT) ) n = (float) ur_int(cell); else if( ur_is(cell, UT_DECIMAL) ) n = (float) ur_decimal(cell); else n = 0.0; if( n < da->min ) n = da->min; else if( n > da->max ) n = da->max; da->val = n; }
/* Do block, ignore result, and show any error in QMessageBox. */ void boron_doBlockQt( UThread* ut, const UCell* blkC ) { if( ! boron_doVoid( ut, blkC ) ) { UCell* ex = boron_exception( ut ); if( ur_is(ex, UT_ERROR) ) { QString msg; cellToQString( ex, msg ); QMessageBox::warning( 0, "Script Error", msg, QMessageBox::Ok, QMessageBox::NoButton ); ur_blkPop( ur_errorBlock(ut) ); //boron_reset( ut ); } else if( ur_is(ex, UT_WORD) ) { if( ur_atom(ex) == UR_ATOM_QUIT ) qApp->quit(); } } }
static int tabWidgetBlock( UThread* ut, QTabWidget* tab, const UCell* blkC ) { UBlockIter bi; const UCell* label = 0; ur_blkSlice( ut, &bi, blkC ); ur_foreach( bi ) { if( ur_is(bi.it, UT_STRING) ) { label = bi.it; } else if( ur_is(bi.it, UT_WORD) ) { const UCell* val = ur_wordCell( ut, bi.it ); if( ! val ) return UR_THROW; if( label && ur_is(val, UT_BLOCK) ) { if( ! tabBlock( ut, tab, val, label ) ) return UR_THROW; label = 0; } } else if( ur_is(bi.it, UT_BLOCK) ) { if( label ) { if( ! tabBlock( ut, tab, bi.it, label ) ) return UR_THROW; label = 0; } } } return UR_OK; }
static GWidget* slider_make( UThread* ut, UBlockIter* bi, const GWidgetClass* wclass ) { GSlider* ep; const UCell* arg[4]; if( ! gui_parseArgs( ut, bi, wclass, slider_args, arg ) ) return 0; ep = (GSlider*) gui_allocWidget( sizeof(GSlider), wclass ); ep->state = BTN_STATE_UP; // Optional orientaion. if( arg[0] ) { const char* word = ur_atomCStr( ut, arg[0]->word.atom ); ep->orient = (word[0] == 'h') ? HORIZONTAL : VERTICAL; } else if( wclass == &wclass_scrollbar ) { ep->orient = VERTICAL; } if( ur_is(arg[1], UT_COORD) ) { ep->data.val = ep->data.min = (float) arg[1]->coord.n[0]; ep->data.max = (float) arg[1]->coord.n[1]; ep->data.vsize = (float) arg[1]->coord.n[2]; ep->dataType = UT_INT; } else { ep->data.val = ep->data.min = arg[1]->vec3.xyz[0]; ep->data.max = arg[1]->vec3.xyz[1]; ep->data.vsize = arg[1]->vec3.xyz[2]; ep->dataType = UT_DECIMAL; } slider_setValue( ep, arg[2] ); // Optional action block. if( arg[3] ) ep->actionN = arg[3]->series.buf; return (GWidget*) ep; }
static void slider_sizeHint( GWidget* wp, GSizeHint* size ) { UCell* rc; EX_PTR; int isSlider = (wp->wclass != &wclass_scrollbar); rc = glEnv.guiStyle + (isSlider ? CI_STYLE_SLIDER_SIZE : CI_STYLE_SCROLL_SIZE); if( ur_is(rc, UT_COORD) ) { size->minW = rc->coord.n[0]; size->minH = rc->coord.n[1]; } else { size->minW = 20; size->minH = 20; } if( ep->orient == HORIZONTAL ) { size->minW = 100; size->maxW = GW_MAX_DIM; size->maxH = size->minH; size->weightX = 2; size->weightY = 1; size->policyX = GW_EXPANDING; size->policyY = GW_FIXED; } else { size->minH = 100; size->maxW = size->minW; size->maxH = GW_MAX_DIM; size->weightX = 1; size->weightY = 2; size->policyX = GW_FIXED; size->policyY = GW_EXPANDING; } }
static void ledit_sizeHint( GWidget* wp, GSizeHint* size ) { UCell* rc; TexFont* tf; UCell* style = glEnv.guiStyle; UThread* ut = glEnv.guiUT; EX_PTR; rc = style + CI_STYLE_BUTTON_SIZE; if( ur_is(rc, UT_COORD) ) { size->minW = rc->coord.n[0]; size->minH = rc->coord.n[1]; size->maxW = rc->coord.n[2]; } else { size->minW = 32; size->minH = 20; size->maxW = 100; } size->maxH = size->minH; size->weightX = 2; size->weightY = 1; size->policyX = GW_EXPANDING; size->policyY = GW_FIXED; tf = ur_texFontV( ut, style + CI_STYLE_EDIT_FONT ); if( tf ) { TexFontGlyph* glyph = txf_glyph( tf, 'W' ); int width = ep->maxChars * (glyph ? glyph->width : 9); if( width > size->minW ) size->minW += width; if( size->maxW < size->minW ) size->maxW = size->minW; } }
/* Updates DrawContext attr & drawCount. Return UR_OK/UR_THROW. */ int itemview_parse( DrawContext* dc, UThread* ut, UBlockIter* bi, GWidget* wp ) { const UCell* arg[3]; UAtom atom; int opcode; float x, y; while( bi->it != bi->end ) { if( ur_is(bi->it, UT_WORD) ) { atom = ur_atom( bi->it ); opcode = ur_atomsSearch( glEnv.drawOpTable, DOP_COUNT, atom ); switch( opcode ) { case DOP_IMAGE: { QuadDim qd; int16_t rect[4]; const int16_t* coord; FETCH_ARGS( iv_args_image ); //printf( "KR IV image\n" ); coord = arg[0]->coord.n; rect[0] = coord[0] + dc->penX; rect[1] = coord[1] + dc->penY; rect[2] = coord[2]; rect[3] = coord[3]; quad_init( &qd, rect, arg[1]->coord.n, arg[2]->coord.n ); quad_emitVT( &qd, dc->attr, dc->attr + 3, AttrCount ); vbo_setVec3( dc->attr + 5, AttrCount, 6, dc->color ); dc->attr += 6 * AttrCount; dc->drawCount += 6; } break; case DOP_COLOR: FETCH_ARGS( iv_args_color ); dc->color[0] = (GLfloat) ur_int( arg[0] ); break; case DOP_FONT: FETCH_ARGS( iv_args_font ); dc->fontN = ur_fontTF( arg[0] ); break; case DOP_TEXT: FETCH_ARGS( iv_args_text ); x = dc->penX + (float) arg[0]->coord.n[0]; y = dc->penY + (float) arg[0]->coord.n[1]; { DrawTextState dts; UBinaryIter si; int glyphCount; //printf( "KR IV text\n" ); dp_toString( ut, arg[1], &si ); vbo_drawTextInit( &dts, (TexFont*) ur_buffer( dc->fontN )->ptr.v, x, y ); dts.emitTris = 1; glyphCount = vbo_drawText( &dts, dc->attr + 3, dc->attr, AttrCount, si.it, si.end ); glyphCount *= 6; vbo_setVec3( dc->attr + 5, AttrCount, glyphCount, dc->color ); /* while( si.it != si.end ) putchar( *si.it++ ); putchar( '\n' ); */ dc->attr += glyphCount * AttrCount; dc->drawCount += glyphCount; } break; default: goto invalid_op; } } else { goto invalid_op; } } return UR_OK; invalid_op: return ur_error( ut, UR_ERR_SCRIPT, "Invalid item-view instruction" ); }
/* "tcps://host:port" "tcps://:port" "udps://host:port" "udps://:port" */ static int ssl_open( UThread* ut, const UPortDevice* pdev, const UCell* from, int opt, UCell* res ) { NodeServ ns; SSLExt* ext; int ok; //int nowait = opt & UR_PORT_NOWAIT; mbedtls_net_context* nc; mbedtls_ssl_context* sc; mbedtls_ssl_config* conf; const char* pers = "ssl_client1"; (void) opt; if( ! ur_is(from, UT_STRING) ) return ur_error( ut, UR_ERR_TYPE, "socket open expected string" ); ext = (SSLExt*) memAlloc( sizeof(SSLExt) ); ext->se.addrlen = 0; #ifdef _WIN32 ext->se.event = WSA_INVALID_EVENT; #endif //if( ur_is(from, UT_STRING) ) { stringToNodeServ( ut, from, &ns ); if( ! makeSockAddr( ut, &ext->se, &ns ) ) goto fail; } if( ! ns.service ) { ur_error( ut, UR_ERR_SCRIPT, "Socket port requires hostname and/or port" ); goto fail; } if( ! boron_requestAccess( ut, "Open socket %s", ns.service ) ) goto fail; ssl_init( ext ); nc = &ext->nc; sc = &ext->sc; conf = &ext->conf; ok = mbedtls_ctr_drbg_seed( &ext->ctr_drbg, mbedtls_entropy_func, &ext->entropy, (const unsigned char*) pers, strlen(pers) ); if( ok != 0 ) { ssl_error( ut, "mbedtls_ctr_drbg_seed", ok ); goto failSSL; } ok = mbedtls_net_connect( nc, ns.node, ns.service, (ns.socktype == SOCK_DGRAM) ? MBEDTLS_NET_PROTO_UDP : MBEDTLS_NET_PROTO_TCP ); if( ok != 0 ) { ssl_error( ut, "mbedtls_net_connect", ok ); goto failSSL; } ok = mbedtls_ssl_config_defaults( conf, MBEDTLS_SSL_IS_CLIENT, (ns.socktype == SOCK_DGRAM) ? MBEDTLS_SSL_TRANSPORT_DATAGRAM : MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ); if( ok != 0 ) { ssl_error( ut, "mbedtls_ssl_config_defaults", ok ); goto failSSL; } mbedtls_ssl_conf_authmode( conf, MBEDTLS_SSL_VERIFY_NONE ); //mbedtls_ssl_conf_ca_chain( conf, cacert, NULL ); mbedtls_ssl_conf_rng( conf, mbedtls_ctr_drbg_random, &ext->ctr_drbg ); mbedtls_ssl_conf_dbg( conf, ssl_debug, stdout ); ok = mbedtls_ssl_setup( sc, conf ); if( ok != 0 ) { ssl_error( ut, "mbedtls_ssl_setup", ok ); goto failSSL; } ok = mbedtls_ssl_set_hostname( sc, "Boron TLS Server 1" ); if( ok != 0 ) { ssl_error( ut, "mbedtls_ssl_set_hostname", ok ); goto failSSL; } mbedtls_ssl_set_bio( sc, nc, mbedtls_net_send, mbedtls_net_recv, NULL ); while( (ok = mbedtls_ssl_handshake( sc )) != 0 ) { if( ok != MBEDTLS_ERR_SSL_WANT_READ && ok != MBEDTLS_ERR_SSL_WANT_WRITE ) { ssl_error( ut, "mbedtls_ssl_handshake", ok ); goto failSSL; } } { UBuffer* pbuf; pbuf = boron_makePort( ut, pdev, ext, res ); pbuf->TCP = (ns.socktype == SOCK_STREAM) ? 1 : 0; pbuf->FD = nc->fd; //printf( "KR socket_open %d %d\n", pbuf->FD, pbuf->TCP ); } return UR_OK; failSSL: ssl_free( ext ); fail: memFree( ext ); return UR_THROW; }
/* Returns zero if matching rule not found or exception occured. */ static const UCell* _parseBin( UThread* ut, BinaryParser* pe, const UCell* rit, const UCell* rend, UIndex* spos ) { const UCell* set = 0; const UCell* tval; uint32_t bitCount; uint32_t field; UBuffer* ibin = ur_buffer( pe->inputBufN ); uint8_t* in = ibin->ptr.b + *spos; uint8_t* inEnd = ibin->ptr.b + pe->inputEnd; match: while( rit != rend ) { switch( ur_type(rit) ) { case UT_INT: bitCount = ur_int(rit); if( bitCount < 1 || bitCount > 32 ) { ur_error( PARSE_ERR, "bit-field size must be 1 to 32" ); goto parse_err; } if( bitCount > 24 ) { uint32_t high; in = pullBits( pe, bitCount - 16, in, inEnd, &high ); if( ! in ) goto failed; in = pullBits( pe, 16, in, inEnd, &field ); if( ! in ) goto failed; field |= high << 16; } else { in = pullBits( pe, bitCount, in, inEnd, &field ); if( ! in ) goto failed; } goto set_field; case UT_WORD: switch( ur_atom(rit) ) { case UR_ATOM_U8: if( in == inEnd ) goto failed; field = *in++; goto set_field; case UR_ATOM_U16: if( (inEnd - in) < 2 ) goto failed; if( pe->bigEndian ) field = (in[0] << 8) | in[1]; else field = (in[1] << 8) | in[0]; in += 2; goto set_field; case UR_ATOM_U32: if( (inEnd - in) < 4 ) goto failed; if( pe->bigEndian ) field = (in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3]; else field = (in[3] << 24) | (in[2] << 16) | (in[1] << 8) | in[0]; in += 4; goto set_field; case UR_ATOM_SKIP: ++rit; ++in; break; #if 0 case UR_ATOM_MARK: break; case UR_ATOM_PLACE: ++rit; if( (rit != rend) && ur_is(rit, UT_WORD) ) { tval = ur_wordCell( ut, rit++ ); CHECK_WORD(tval); if( ur_is(tval, UT_BINARY) ) { pos = tval->series.it; break; } } ur_error( PARSE_ERR, "place expected series word" ); goto parse_err; #endif case UR_ATOM_COPY: // copy dest size // word! int!/word! ++rit; if( (rit != rend) && ur_is(rit, UT_WORD) ) { UCell* res = ur_wordCellM( ut, rit ); CHECK_WORD(res); if( ++rit != rend ) { tval = rit++; if( ur_is(tval, UT_WORD) ) { tval = ur_wordCell( ut, tval ); CHECK_WORD(tval); } if( ur_is(tval, UT_INT) ) { UBuffer* cb; int size = ur_int(tval); cb = ur_makeBinaryCell( ut, size, res ); cb->used = size; memCpy( cb->ptr.b, in, size ); in += size; break; } } ur_error( PARSE_ERR, "copy expected int! count" ); goto parse_err; } ur_error( PARSE_ERR, "copy expected word! destination" ); goto parse_err; case UR_ATOM_BIG_ENDIAN: ++rit; pe->bigEndian = 1; break; case UR_ATOM_LITTLE_ENDIAN: ++rit; pe->bigEndian = 0; break; default: tval = ur_wordCell( ut, rit ); CHECK_WORD(tval); if( ur_is(tval, UT_CHAR) ) goto match_char; else if( ur_is(tval, UT_STRING) ) goto match_string; else if( ur_is(tval, UT_BLOCK) ) goto match_block; /* else if( ur_is(tval, UT_BITSET) ) goto match_bitset; */ else { ur_error( PARSE_ERR, "parse expected char!/string!/block!" ); goto parse_err; } break; } break; case UT_SETWORD: set = rit++; while( (rit != rend) && ur_is(rit, UT_SETWORD) ) ++rit; break; #if 0 case UT_GETWORD: break; case UT_INT: repMin = ur_int(rit); ++rit; if( rit == rend ) return 0; if( ur_is(rit, UT_INT) ) { repMax = ur_int(rit); ++rit; } else { repMax = repMin; } goto repeat; #endif case UT_CHAR: match_char: if( *in != ur_int(rit) ) goto failed; ++in; ++rit; break; case UT_BLOCK: tval = rit; match_block: { UBlockIter bi; UIndex pos = in - ibin->ptr.b; UIndex rblkN = tval->series.buf; ur_blkSlice( ut, &bi, tval ); tval = _parseBin( ut, pe, bi.it, bi.end, &pos ); ibin = ur_buffer( pe->inputBufN ); if( ! tval ) { if( pe->exception == PARSE_EX_ERROR ) { ur_appendTrace( ut, rblkN, 0 ); return 0; } if( pe->exception == PARSE_EX_BREAK ) pe->exception = PARSE_EX_NONE; else goto failed; } in = ibin->ptr.b + pos; inEnd = ibin->ptr.b + pe->inputEnd; ++rit; } break; case UT_PAREN: { UIndex pos = in - ibin->ptr.b; if( UR_OK != pe->eval( ut, rit ) ) goto parse_err; /* Re-acquire pointer & check if input modified. */ ibin = ur_buffer( pe->inputBufN ); if( pe->sliced ) { // We have no way to track changes to the end of a slice, // so just make sure we remain in valid memery. if( ibin->used < pe->inputEnd ) pe->inputEnd = ibin->used; } else { // Not sliced, track input end. if( ibin->used != pe->inputEnd ) pe->inputEnd = ibin->used; } in = ibin->ptr.b + pos; inEnd = ibin->ptr.b + pe->inputEnd; ++rit; } break; case UT_STRING: tval = rit; match_string: { UBinaryIter bi; int size; ur_binSlice( ut, &bi, tval ); if( ur_strIsUcs2(bi.buf) ) goto bad_enc; size = bi.end - bi.it; if( size > (inEnd - in) ) goto failed; if( match_pattern_8(in, inEnd, bi.it, bi.end) == bi.end ) { in += size; ++rit; } else goto failed; } break; #if 0 case UT_BITSET: tval = rit; match_bitset: if( pos >= pe->inputEnd ) goto failed; { const UBuffer* bin = ur_bufferSer( tval ); int c = istr->ptr.c[ pos ]; if( bitIsSet( bin->ptr.b, c ) ) { ++rit; ++pos; } else goto failed; } break; #endif default: ur_error( PARSE_ERR, "invalid parse value" ); //orDatatypeName( ur_type(rit) ) ); goto parse_err; } } //complete: *spos = in - ibin->ptr.b; return rit; set_field: if( set ) { UCell* val; while( set != rit ) { val = ur_wordCellM( ut, set++ ); CHECK_WORD(val); ur_setId(val, UT_INT); ur_int(val) = field; } set = 0; } ++rit; goto match; failed: *spos = in - ibin->ptr.b; return 0; bad_enc: ur_error( ut, UR_ERR_INTERNAL, "parse binary does not handle UCS2 strings" ); //goto parse_err; parse_err: pe->exception = PARSE_EX_ERROR; return 0; }
static void slider_layout( GWidget* wp ) { UCell* rc; UCell* area; UCell* style = glEnv.guiStyle; UThread* ut = glEnv.guiUT; EX_PTR; int isSlider = (wp->wclass != &wclass_scrollbar); int horiz = (ep->orient == HORIZONTAL); int majorD = horiz ? wp->area.w : wp->area.h; if( ! gDPC ) return; // Set slider knob length. if( isSlider ) { rc = style + CI_STYLE_SLIDER_SIZE; ep->knobLen = rc->coord.n[0]; } else { struct Value* da = &ep->data; ep->knobLen = (int16_t) (da->vsize * majorD / (da->max - da->min + da->vsize)); } ep->td = slider_knobTrans( ep, (float) (majorD - ep->knobLen), ep->data.max - ep->data.min ); // Set draw list variables. area = style + CI_STYLE_AREA; gui_initRectCoord( area, wp, UR_ATOM_RECT ); // Compile draw lists. rc = style + (isSlider ? CI_STYLE_SLIDER_GROOVE : CI_STYLE_SCROLL_BAR); if( ur_is(rc, UT_BLOCK) ) ur_compileDP( ut, rc, 1 ); rc = style + (isSlider ? CI_STYLE_SLIDER : CI_STYLE_SCROLL_KNOB); //(horiz ? CI_STYLE_SLIDER_H : CI_STYLE_SLIDER_V); if( ur_is(rc, UT_BLOCK) ) { float tx, ty; if( horiz ) { tx = (float) ep->td; ty = 0.0f; area->coord.n[2] = ep->knobLen; // Area width. } else { tx = 0.0f; #ifdef YTOP ty = (float) ep->td; #else ty = (float) (wp->area.h - ep->knobLen - ep->td); #endif area->coord.n[3] = ep->knobLen; // Area height. } ep->dpTrans = dp_beginTransXY( gDPC, tx, ty ); ur_compileDP( ut, rc, 1 ); dp_endTransXY( gDPC ); } }
/* Recursively evaluate math expression. \param cell Cell to evaluate. \param res Result. \return UR_OK or UR_THROW. */ int calc_eval( UThread* ut, UCell* cell, double* res ) { switch( ur_type(cell) ) { case UT_WORD: { const UCell* val = ur_wordCell( ut, cell ); if( ! val ) return UR_THROW; if( ur_is(val, UT_DECIMAL) ) *res = ur_decimal(val); else if( ur_is(val, UT_INT) || ur_is(val, UT_CHAR) ) *res = (double) ur_int(val); else { return ur_error( ut, UR_ERR_SCRIPT, "Invalid word '%s", ur_wordCStr( cell ) ); } } break; case UT_DECIMAL: *res = ur_decimal(cell); break; case UT_INT: case UT_CHAR: *res = (double) ur_int(cell); break; case UT_BLOCK: case UT_PAREN: { UBlockIterM bi; double num = 0.0; double right; #define RIGHT_VAL \ if( ++bi.it == bi.end ) \ return ur_error( ut, UR_ERR_SCRIPT, "Expected operator r-value" ); \ if( ! calc_eval( ut, bi.it, &right ) ) \ return UR_THROW; if( ! ur_blkSliceM( ut, &bi, cell ) ) return UR_THROW; ur_foreach( bi ) { if( ur_is(bi.it, UT_WORD) ) { switch( ur_atom(bi.it) ) { case UR_ATOM_PLUS: RIGHT_VAL num += right; break; case UR_ATOM_MINUS: RIGHT_VAL num -= right; break; case UR_ATOM_ASTERISK: RIGHT_VAL num *= right; break; case UR_ATOM_SLASH: RIGHT_VAL num /= right; break; default: if( ! calc_eval( ut, bi.it, &num ) ) return UR_THROW; } } else if( ur_is(bi.it, UT_SETWORD) ) { cell = ur_wordCellM( ut, bi.it ); if( ! cell ) return UR_THROW; ur_setId( cell, UT_DECIMAL ); ur_decimal(cell) = num; } else { if( ! calc_eval( ut, bi.it, &num ) ) return UR_THROW; } } *res = num; } break; default: *res = 0.0; break; } return UR_OK; }
static GWidget* itemview_make( UThread* ut, UBlockIter* bi, const GWidgetClass* wclass ) { GItemView* ep; UIndex itemBlkN; const UCell* arg[3]; //int ok; if( ! gui_parseArgs( ut, bi, wclass, itemview_args, arg ) ) return 0; ep = (GItemView*) gui_allocWidget( sizeof(GItemView), wclass ); assert( sizeof(GLint) == sizeof(GLsizei) ); ur_arrInit( ep->fc + 0, sizeof(GLint), 0 ); ur_arrInit( ep->fc + 1, sizeof(GLint), 0 ); glGenBuffers( 2, ep->vbo ); ep->vboSize[0] = ep->vboSize[1] = 0; ep->use_color = -1; ep->selCol = -1; ep->selRow = -1; ep->itemCount = 0; ep->itemWidth = 0; ep->itemHeight = 0; ep->scrollY = 0; ep->modVbo = 0; ep->updateMethod = IV_UPDATE_2; ep->layoutBlkN = UR_INVALID_BUF; ep->selectBgBlkN = UR_INVALID_BUF; ep->bindCtxN = UR_INVALID_BUF; ep->actionBlkN = UR_INVALID_BUF; itemBlkN = arg[0]->series.buf; if( ur_isShared( itemBlkN ) ) ep->dataBlkN = UR_INVALID_BUF; else ep->dataBlkN = itemBlkN; // Optional action block. if( arg[2] ) ep->actionBlkN = arg[2]->series.buf; //-------------------------------------------- // Parse layout block [size coord! item block! selected block!] { UBlockIterM bi; UBuffer* ctx; if( ur_blkSliceM( ut, &bi, arg[1] ) != UR_OK ) goto fail; if( (bi.end - bi.it) < 3 ) goto bad_layout; ctx = gui_styleContext( ut ); if( ctx ) ur_bind( ut, bi.buf, ctx, UR_BIND_THREAD ); if( ur_is(bi.it, UT_COORD) ) { // Fixed layout. static char itemStr[] = "item"; UBuffer* blk; if( ! ur_is(bi.it + 1, UT_BLOCK) || ! ur_is(bi.it + 2, UT_BLOCK) ) goto bad_layout; ep->itemWidth = bi.it->coord.n[0]; ep->itemHeight = bi.it->coord.n[1]; //printf( "KR item dim %d,%d\n", ep->itemWidth, ep->itemHeight ); ++bi.it; ep->layoutBlkN = bi.it->series.buf; ep->bindCtxN = ur_makeContext( ut, 1 ); // gc! ctx = ur_buffer( ep->bindCtxN ); ur_ctxAppendWord( ctx, ur_intern( ut, itemStr, 4 ) ); if( ! (blk = ur_bufferSerM( bi.it )) ) goto fail; ur_bind( ut, blk, ctx, UR_BIND_THREAD ); ++bi.it; ep->selectBgBlkN = bi.it->series.buf; } #ifdef ITEMVIEW_BOX_LAYOUT else { // Automatic layout. glEnv.guiParsingItemView = 1; ok = gui_makeWidgets( ut, arg[1], &ep->wid, 0 ); glEnv.guiParsingItemView = 0; if( ! ok ) goto fail; //ep->wid.child->flags |= GW_HIDDEN; } #endif } return (GWidget*) ep; bad_layout: ur_error( ut, UR_ERR_SCRIPT, "Invalid item-view layout" ); fail: itemview_free( (GWidget*) ep ); return 0; }
static void itemview_layout( GWidget* wp ) { UCell* rc; /* UCell* it; UBuffer* blk; int row, rowCount; int col, colCount; int itemY; */ UCell* style = glEnv.guiStyle; UThread* ut = glEnv.guiUT; //UIndex strN = 0; EX_PTR; /* DPCompiler* save; DPCompiler dpc; */ #ifdef ITEM_HEADER if( ep->headerBlkN <= 0 ) return; #endif if( ep->dataBlkN <= 0 ) return; itemview_calcItemHeight( ut, ep ); //itemY = wp->area.y + wp->area.h - ep->itemHeight; if( ep->use_color == -1 ) { rc = style + CI_STYLE_WIDGET_SH; if( ur_is(rc, UT_CONTEXT) ) { const Shader* shad = shaderContext( ut, rc, 0 ); if( shad ) { ep->use_color = glGetUniformLocation( shad->program, "use_color" ); //printf( "KR use_color %d\n", ep->use_color ); } } } #if 0 // Compile draw list for visible items. save = ur_beginDP( &dpc ); if( save ) dpc.shaderProg = save->shaderProg; // Header blk = ur_buffer( ep->headerBlkN ); it = blk->ptr.cell; colCount = ep->colCount = blk->used; for( col = 0; col < colCount; ++col, ++it ) { rc = style + CI_STYLE_LABEL; if( ur_is(it, UT_STRING) ) { *rc = *it; } rc = style + CI_STYLE_AREA; rc->coord.len = 4; rc->coord.n[0] = wp->area.x + (col * MIN_COLW); rc->coord.n[1] = itemY; rc->coord.n[2] = MIN_COLW; rc->coord.n[3] = ep->itemHeight; rc = style + CI_STYLE_LIST_HEADER; if( ur_is(rc, UT_BLOCK) ) ur_compileDP( ut, rc, 1 ); } itemY -= ep->itemHeight; // Items blk = ur_buffer( ep->dataBlkN ); it = blk->ptr.cell; rowCount = blk->used / colCount; for( row = 0; row < rowCount; ++row ) { for( col = 0; col < colCount; ++col, ++it ) { rc = style + CI_STYLE_LABEL; if( ur_is(it, UT_STRING) ) { *rc = *it; } else { UBuffer* str; if( ! strN ) strN = ur_makeString( ut, UR_ENC_LATIN1, 32 ); ur_initSeries( rc, UT_STRING, strN ); str = ur_buffer( strN ); str->used = 0; ur_toStr( ut, it, str, 0 ); } rc = style + CI_STYLE_AREA; rc->coord.len = 4; rc->coord.n[0] = wp->area.x + (col * MIN_COLW); rc->coord.n[1] = itemY; rc->coord.n[2] = MIN_COLW; rc->coord.n[3] = ep->itemHeight; rc = style + ((row == ep->selRow) ? CI_STYLE_LIST_ITEM_SELECTED : CI_STYLE_LIST_ITEM); if( ur_is(rc, UT_BLOCK) ) ur_compileDP( ut, rc, 1 ); } itemY -= ep->itemHeight; } ur_endDP( ut, ur_buffer(ep->dp[0]), save ); #endif }
static void ledit_layout( GWidget* wp ) { UCell* style = glEnv.guiStyle; UThread* ut = glEnv.guiUT; UCell* rc; EX_PTR; // Set draw list variables. rc = style + CI_STYLE_LABEL; ur_setId( rc, UT_STRING ); ur_setSeries( rc, ep->strN, 0 ); rc = style + CI_STYLE_AREA; gui_initRectCoord( rc, wp, UR_ATOM_RECT ); // Compile draw lists. if( ! gDPC ) return; // Make sure the tgeo vertex buffers are bound before the switch. // Otherwise only the first case would emit the code to do it. // NOTE: This assumes the button draw programs actually use tgeo. dp_tgeoInit( gDPC ); ep->dpSwitch = dp_beginSwitch( gDPC, 2 ); rc = style + CI_STYLE_EDITOR; if( ur_is(rc, UT_BLOCK) ) ur_compileDP( ut, rc, 1 ); dp_endCase( gDPC, ep->dpSwitch ); rc = style + CI_STYLE_EDITOR_ACTIVE; if( ur_is(rc, UT_BLOCK) ) ur_compileDP( ut, rc, 1 ); dp_endCase( gDPC, ep->dpSwitch ); dp_endSwitch( gDPC, ep->dpSwitch, ep->state ); setFlag( CHANGED ); #if 0 rc = style + CI_STYLE_EDITOR_CURSOR; if( ur_is(rc, UT_BLOCK) ) { DPCompiler dc; DPCompiler* save; save = gx_beginDP( &dc ); if( save ) dc.shaderProg = save->shaderProg; ur_compileDP( ut, rc, 1 ); gx_endDP( ur_buffer( ep->textResN ), save ); //dp_compile( &dc, ut, rc->series.n ); } #endif }
int main( int argc, char** argv ) { char cmd[ 2048 ]; BoronApp app( argc, argv ); UThread* ut; UBuffer rstr; int fileN = 0; int ret = 0; { UEnvParameters param; ut = boron_makeEnv( boron_envParam(¶m) ); } if( ! ut ) { printf( "boron_makeEnv failed\n" ); return -1; } ur_freezeEnv( ut ); boron_initQt( ut ); if( argc > 1 ) { int i; char* arg; for( i = 1; i < argc; ++i ) { arg = argv[i]; if( arg[0] == '-' ) { switch( arg[1] ) { case 's': //ur_disable( env, UR_ENV_SECURE ); break; case 'h': usage( argv[0] ); return 0; } } else { fileN = i; break; } } } ur_strInit( &rstr, UR_ENC_UTF8, 0 ); #ifdef _WIN32 { WORD wsver; WSADATA wsdata; wsver = MAKEWORD( 2, 2 ); WSAStartup( wsver, &wsdata ); } #endif if( fileN ) { char* pos; pos = cmd; cmd[ sizeof(cmd) - 1 ] = -1; // Create args block for any command line parameters. if( (argc - fileN) > 1 ) { int i; pos = str_copy( pos, "args: [" ); for( i = fileN + 1; i < argc; ++i ) { *pos++ = '"'; pos = str_copy( pos, argv[i] ); *pos++ = '"'; *pos++ = ' '; } *pos++ = ']'; } else { pos = str_copy( pos, "args: none " ); } pos = str_copy( pos, "do load {" ); pos = str_copy( pos, argv[fileN] ); *pos++ = '}'; assert( cmd[ sizeof(cmd) - 1 ] == -1 && "cmd buffer overflow" ); if( ! boron_evalUtf8( ut, cmd, pos - cmd ) ) { UCell* ex = ur_exception( ut ); if( ur_is(ex, UT_ERROR) ) { OPEN_CONSOLE reportError( ut, ex, &rstr ); goto prompt; } else if( ur_is(ex, UT_WORD) ) { switch( ur_atom(ex) ) { case UR_ATOM_QUIT: goto quit; case UR_ATOM_HALT: goto prompt; break; } } } } else { OPEN_CONSOLE printf( APPNAME " %s (%s)\n", UR_VERSION_STR, __DATE__ ); prompt: while( 1 ) { printf( ")> " ); fflush( stdout ); /* Required on Windows. */ fgets( cmd, sizeof(cmd), stdin ); #if 0 { char* cp = cmd; while( *cp != '\n' ) printf( " %d", (int) *cp++ ); printf( "\n" ); } #endif if( cmd[0] == ESC ) { // Up 27 91 65 // Down 27 91 66 printf( "\n" ); } else if( cmd[0] != '\n' ) { #if 0 if( cmd[0] == 'q' ) goto quit; #endif UCell* val = boron_evalUtf8( ut, cmd, -1 ); if( val ) { if( ur_is(val, UT_UNSET) || ur_is(val, UT_CONTEXT) ) goto prompt; rstr.used = 0; ur_toStr( ut, val, &rstr, 0 ); if( rstr.ptr.c ) { ur_strTermNull( &rstr ); if( rstr.used > PRINT_MAX ) { char* cp = str_copy( rstr.ptr.c + PRINT_MAX - 4, "..." ); *cp = '\0'; } printf( "== %s\n", rstr.ptr.c ); } } else { UCell* ex = ur_exception( ut ); if( ur_is(ex, UT_ERROR) ) { reportError( ut, ex, &rstr ); } else if( ur_is(ex, UT_WORD) ) { switch( ur_atom(ex) ) { case UR_ATOM_QUIT: goto quit; case UR_ATOM_HALT: printf( "**halt\n" ); break; default: printf( "**unhandled excepetion %s\n", ur_atomCStr(ut,ur_atom(ex)) ); break; } } boron_reset( ut ); } } } } quit: ur_strFree( &rstr ); boron_freeQt(); boron_freeEnv( ut ); #ifdef _WIN32 WSACleanup(); #endif return ret; }
/* Returns zero if matching rule not found or exception occured. */ static const UCell* _parseBlock( UThread* ut, BlockParser* pe, const UCell* rit, const UCell* rend, UIndex* spos ) { const UCell* tval; int32_t repMin; int32_t repMax; UAtom atom; const UBuffer* iblk = pe->blk; UIndex pos = *spos; match: while( rit != rend ) { switch( ur_type(rit) ) { case UT_WORD: atom = ur_atom(rit); if( atom < UT_BI_COUNT ) { // Datatype if( pos >= pe->inputEnd ) goto failed; tval = iblk->ptr.cell + pos; if( ur_type(tval) != atom ) { /* if( atom == UT_NUMBER ) { if( ur_is(tval,UT_INT) || ur_is(tval,UT_DECIMAL) ) goto type_matched; } */ goto failed; } //type_matched: ++rit; ++pos; } else switch( atom ) { case UR_ATOM_OPT: ++rit; repMin = 0; repMax = 1; goto repeat; case UR_ATOM_ANY: ++rit; repMin = 0; repMax = 0x7fffffff; goto repeat; case UR_ATOM_SOME: ++rit; repMin = 1; repMax = 0x7fffffff; goto repeat; case UR_ATOM_BREAK: pe->exception = PARSE_EX_BREAK; *spos = pos; return 0; case UR_ATOM_BAR: goto complete; case UR_ATOM_TO: case UR_ATOM_THRU: { const UCell* ci; const UCell* ce; UAtom ratom = ur_atom(rit); ++rit; if( rit == rend ) return 0; ci = iblk->ptr.cell + pos; ce = iblk->ptr.cell + pe->inputEnd; if( ur_is(rit, UT_WORD) ) { if( ur_atom(rit) < UT_BI_COUNT ) { atom = ur_atom(rit); while( ci != ce ) { if( ur_type(ci) == atom ) break; ++ci; } if( ci == ce ) goto failed; pos = ci - iblk->ptr.cell; if( ratom == UR_ATOM_THRU ) ++pos; ++rit; break; } else { tval = ur_wordCell( ut, rit ); CHECK_WORD( tval ) } } else { tval = rit; } if( ur_is(tval, UT_BLOCK) ) { // TODO: If block then all values must match. BLK_RULE_ERROR( "to/thru block! not implemented" ); } else { while( ci != ce ) { if( ur_equal(ut, ci, tval) ) break; ++ci; } if( ci == ce ) goto failed; pos = ci - iblk->ptr.cell; if( ratom == UR_ATOM_THRU ) ++pos; } ++rit; } break; case UR_ATOM_INTO: ++rit; if( rit == rend || ! ur_is(rit, UT_BLOCK) ) { BLK_RULE_ERROR( "parse into expected block" ); } tval = iblk->ptr.cell + pos; if( ! ur_is(tval, UT_BLOCK) ) goto failed; if( ur_isShared( tval->series.buf ) ) goto failed; { BlockParser ip; UBlockIter bi; UIndex parsePos = 0; ip.eval = pe->eval; ip.blk = ur_bufferSer( tval ); ip.inputBuf = tval->series.buf; ip.inputEnd = ip.blk->used; ip.sliced = 0; ip.exception = PARSE_EX_NONE; ur_blkSlice( ut, &bi, rit ); tval = _parseBlock( ut, &ip, bi.it, bi.end, &parsePos ); iblk = _acquireInput( ut, pe ); if( ! tval ) { if( ip.exception == PARSE_EX_ERROR ) { pe->exception = PARSE_EX_ERROR; ur_appendTrace( ut, rit->series.buf, 0 ); return 0; } if( ip.exception != PARSE_EX_BREAK ) goto failed; } } ++rit; ++pos; break; case UR_ATOM_SKIP: repMin = 1; skip: if( (pos + repMin) > pe->inputEnd ) goto failed; pos += repMin; ++rit; break; case UR_ATOM_SET: ++rit; if( rit == rend ) goto unexpected_end; if( ! ur_is(rit, UT_WORD) ) { BLK_RULE_ERROR( "parse set expected word" ); } { UCell* cell = ur_wordCellM( ut, rit ); CHECK_WORD( cell ) *cell = iblk->ptr.cell[ pos ]; } ++rit; break; case UR_ATOM_PLACE: ++rit; if( (rit != rend) && ur_is(rit, UT_WORD) ) { tval = ur_wordCell( ut, rit++ ); CHECK_WORD( tval ) if( ur_is(tval, UT_BLOCK) ) { pos = tval->series.it; break; } } BLK_RULE_ERROR( "place expected series word" ); //case UR_ATOM_COPY: default: { tval = ur_wordCell( ut, rit ); CHECK_WORD( tval ) if( ur_is(tval, UT_BLOCK) ) { goto match_block; } else { BLK_RULE_ERROR( "parse expected block" ); } } break; } break; case UT_SETWORD: { UCell* cell = ur_wordCellM( ut, rit ); CHECK_WORD( cell ) ++rit; ur_setId( cell, UT_BLOCK ); ur_setSlice( cell, pe->inputBuf, pos, pe->inputEnd ); } break; case UT_GETWORD: { UCell* cell = ur_wordCellM( ut, rit ); CHECK_WORD( cell ) ++rit; if( ur_is(cell, UT_BLOCK) && (cell->series.buf == pe->inputBuf) ) cell->series.end = pos; } break; case UT_LITWORD: if( pos >= pe->inputEnd ) goto failed; tval = iblk->ptr.cell + pos; if( (ur_is(tval, UT_WORD) || ur_is(tval, UT_LITWORD)) && (ur_atom(tval) == ur_atom(rit)) ) { ++rit; ++pos; } else goto failed; break; case UT_INT: repMin = ur_int(rit); ++rit; if( rit == rend ) return 0; if( ur_is(rit, UT_INT) ) { repMax = ur_int(rit); ++rit; } else if( ur_is(rit, UT_WORD) && ur_atom(rit) == UR_ATOM_SKIP ) { goto skip; } else { repMax = repMin; } goto repeat; case UT_DATATYPE: if( pos >= pe->inputEnd ) goto failed; if( ! ur_isDatatype( iblk->ptr.cell + pos, rit ) ) goto failed; ++rit; ++pos; break; case UT_CHAR: case UT_BINARY: case UT_STRING: case UT_FILE: if( pos >= pe->inputEnd ) goto failed; if( ! ur_equal( ut, iblk->ptr.cell + pos, rit ) ) goto failed; ++rit; ++pos; break; case UT_BLOCK: tval = rit; match_block: { UBlockIter bi; UIndex rblkN = tval->series.buf; ur_blkSlice( ut, &bi, tval ); tval = _parseBlock( ut, pe, bi.it, bi.end, &pos ); iblk = pe->blk; if( ! tval ) { if( pe->exception == PARSE_EX_ERROR ) { ur_appendTrace( ut, rblkN, 0 ); return 0; } if( pe->exception == PARSE_EX_BREAK ) pe->exception = PARSE_EX_NONE; else goto failed; } } ++rit; break; case UT_PAREN: if( UR_OK != pe->eval( ut, rit ) ) goto parse_err; iblk = _acquireInput( ut, pe ); ++rit; break; default: BLK_RULE_ERROR( "invalid parse value" ); }
/* Layout Language \return Layout pointer or zero if error generated. */ QLayout* ur_qtLayout( UThread* ut, LayoutInfo& parent, const UCell* blkC ) { CBParser cbp; UBlockIter bi; LayoutInfo lo; const UCell* val; const UCell* setWord = 0; QWidget* wid = 0; int match; ur_blkSlice( ut, &bi, blkC ); cbp_beginParse( ut, &cbp, bi.it, bi.end, qEnv.layoutRules ); while( (match = cbp_matchRule( &cbp )) > -1 ) { switch( match ) { case LD_HBOX: case LD_VBOX: { wid = 0; lo.grid = 0; lo.box = new QBoxLayout( (match == LD_HBOX) ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom ); if( parent.layout() ) parent.addLayout( lo.box ); val = cbp.values + 1; //TODO: Handle error. ur_qtLayout( ut, lo, val ); } break; case LD_LABEL: { QString txt; if( ! getString( ut, cbp.values + 1, txt ) ) return 0; MAKE_WIDGET( SLabel ) pw->setText( txt ); } break; case LD_BUTTON: { MAKE_WIDGET( SButton ) pw->setText( qstring( cbp.values + 1 ) ); pw->setBlock( cbp.values + 2 ); } break; case LD_CHECKBOX: { MAKE_WIDGET( SCheck ) pw->setText( qstring( cbp.values + 1 ) ); } break; case LD_SPIN_BOX: { MAKE_WIDGET( SSpinBox ) pw->setRange( ur_int( cbp.values + 1 ), ur_int( cbp.values + 2 ) ); } break; case LD_COMBO: { MAKE_WIDGET( SCombo ) val = cbp.values + 1; if( ur_is(val, UT_GETWORD) ) { if( ! (val = ur_wordCell( ut, val )) ) return 0; } if( ur_is(val, UT_BLOCK) ) { UBlockIter bi2; ur_blkSlice( ut, &bi2, val ); ur_foreach( bi2 ) { if( ur_is(bi2.it, UT_STRING) ) pw->addItem( qstring( bi2.it ) ); } } else { pw->addItem( qstring( val ) ); } } break; case LD_SPACER: if( ! parent.box ) goto no_layout; parent.box->addStretch( 1 ); break; case LD_SPACE: if( ! parent.box ) goto no_layout; val = cbp.values + 1; parent.box->addSpacing( ur_int(val) ); break; case LD_TAB: { MAKE_WIDGET( STabWidget ) if( ! tabWidgetBlock( ut, pw, cbp.values + 1 ) ) return 0; } break; case LD_TIP: if( wid ) wid->setToolTip( qstring(cbp.values + 1) ); break; case LD_TITLE: if( qEnv.curWidget ) { QString str; if( ! getString( ut, cbp.values + 1, str ) ) return 0; qEnv.curWidget->setWindowTitle( str ); } break; case LD_RESIZE: if( qEnv.curWidget ) { val = cbp.values + 1; qEnv.curWidget->resize( val->coord.n[0], val->coord.n[1] ); } break; case LD_LINE_EDIT_STR: case LD_LINE_EDIT: { MAKE_WIDGET( SLineEdit ) if( match == LD_LINE_EDIT_STR ) pw->setText( qstring( cbp.values + 1 ) ); } break; case LD_LIST: { const UCell* hdr = cbp.values + 1; if( ur_is(hdr, UT_GETWORD) ) { if( ! (hdr = ur_wordCell( ut, hdr )) ) return 0; } val = cbp.values + 2; if( ur_is(val, UT_GETWORD) ) { if( ! (val = ur_wordCell( ut, val )) ) return 0; } MAKE_WIDGET( STreeView ) pw->setRootIsDecorated( false ); pw->setModel( new UTreeModel( pw, hdr, val ) ); } break; case LD_TEXT_EDIT_STR: case LD_TEXT_EDIT: { MAKE_WIDGET( STextEdit ) if( match == LD_TEXT_EDIT_STR ) { QString str; if( ! getString( ut, cbp.values + 1, str ) ) return 0; if( str[0] == '<' ) pw->setHtml( str ); else pw->setPlainText( str ); } } break; case LD_GROUP: case LD_GROUP_CHECKABLE: { MAKE_WIDGET( SGroup ) val = cbp.values + 1; if( match == LD_GROUP_CHECKABLE ) { const UCell* enabled; if( ! (enabled = ur_wordCell( ut, val )) ) return 0; pw->setCheckable( true ); pw->setChecked( ur_isTrue( enabled ) ); ++val; } pw->setTitle( qstring( val ) ); ++val; LayoutInfo lo2; QLayout* lr2 = ur_qtLayout(ut, lo2, val); if( ! lr2 ) return 0; pw->setLayout( lr2 ); } break; case LD_READ_ONLY: if( wid ) { QTextEdit* tedit = qobject_cast<QTextEdit*>( wid ); if( tedit ) tedit->setReadOnly( true ); } break; case LD_ON_EVENT: if( qEnv.curWidget ) { SWidget* sw = qobject_cast<SWidget*>( qEnv.curWidget ); if( sw ) sw->setEventBlock( cbp.values + 1 ); } break; case LD_STRING: if( wid ) { SCombo* combo = qobject_cast<SCombo*>( wid ); if( combo ) { combo->addItem( qstring( cbp.values ) ); break; } QTextEdit* texted = qobject_cast<QTextEdit*>( wid ); if( texted ) { QString str; cellToQString( cbp.values, str ); if( str[0] == '<' ) texted->setHtml( str ); else texted->setPlainText( str ); } } break; case LD_BLOCK: if( wid ) { SCombo* combo = qobject_cast<SCombo*>( wid ); if( combo ) { combo->setBlock( cbp.values ); break; } STreeView* tree = qobject_cast<STreeView*>( wid ); if( tree ) { tree->setBlock( cbp.values ); break; } } break; case LD_SET_WORD: setWord = cbp.values; break; case LD_GRID: val = cbp.values + 1; wid = 0; lo.box = 0; lo.grid = new QGridLayout; lo.columns = ur_int(val); lo.colN = 0; lo.rowN = 0; if( parent.layout() ) parent.addLayout( lo.grid ); ++val; //TODO: Handle error. ur_qtLayout( ut, lo, val ); break; case LD_PROGRESS: { MAKE_WIDGET( SProgress ) pw->setRange( 0, ur_int(cbp.values+1) ); } break; case LD_WEIGHT: if( parent.box && wid ) { parent.box->setStretchFactor(wid, ur_int(cbp.values+1)); } break; } }
/** Returns rule number of matched rule or -1 if no match was found. cbp->values points to the current position in the input block, or is set to zero when the end of input is reached. */ int cbp_matchRule( CBParser* cbp ) { const UCell* rit; const UCell* rend; const UCell* sit = cbp->_inputPos; const UCell* send = cbp->_inputEnd; int ruleN = 0; if( sit == send ) { cbp->values = 0; return -1; } cbp->values = sit; if( ! cbp->_rules ) return -1; rit = cbp->_rules; rend = cbp->_rulesEnd; next: if( ur_is(rit, UT_LITWORD) ) { if( ur_is(sit, UT_WORD) && (ur_atom(rit) == ur_atom(sit)) ) goto value_matched; } else if( ur_is(rit, UT_WORD) ) { UAtom atom = ur_atom(rit); if( atom < UT_BI_COUNT ) { if( atom == ur_type(sit) ) goto value_matched; } else if( atom == UR_ATOM_BAR ) goto rule_matched; } else if( ur_is(rit, UT_DATATYPE) ) { if( ur_isDatatype( sit, rit ) ) goto value_matched; } next_rule: sit = cbp->_inputPos; do { if( ur_is(rit, UT_WORD) && (ur_atom(rit) == UR_ATOM_BAR) ) { ++ruleN; if( ++rit == rend ) goto fail; goto next; } ++rit; } while( rit != rend ); fail: cbp->_inputPos = send; return -1; value_matched: ++rit; ++sit; if( rit == rend ) goto rule_matched; if( sit == send ) { if( ur_is(rit, UT_WORD) && (ur_atom(rit) == UR_ATOM_BAR) ) goto rule_matched; goto next_rule; } goto next; rule_matched: cbp->_inputPos = sit; return ruleN; }