/* line-edit word!/string! <max-chars> */ static GWidget* ledit_make( UThread* ut, UBlockIter* bi, const GWidgetClass* wclass ) { LineEdit* ep; const UCell* arg[2]; int maxChars = 32; if( ! gui_parseArgs( ut, bi, wclass, ledit_args, arg ) ) return 0; if( ur_isShared( arg[0]->series.buf ) ) { ur_error( ut, UR_ERR_SCRIPT, "line-edit cannot modify shared string" ); return 0; } if( arg[1] ) maxChars = ur_int(arg[1]); ep = (LineEdit*) gui_allocWidget( sizeof(LineEdit), wclass ); ep->wid.flags |= CHANGED; //ep->state = LEDIT_STATE_DISPLAY; ep->strN = arg[0]->series.buf; ep->maxChars = maxChars; ep->vboN = ledit_vbo( ut, maxChars ); return (GWidget*) ep; }
static int thread_write( UThread* ut, UBuffer* port, const UCell* data ) { UBuffer* buf; ThreadExt* ext = (ThreadExt*) port->ptr.v; ThreadQueue* queue; int type = ur_type(data); if( ur_isSeriesType(type) && ! ur_isShared( data->series.buf ) ) { buf = ur_bufferSerM( data ); if( ! buf ) return UR_THROW; if( ur_isBlockType(type) ) { UCell* it = buf->ptr.cell; UCell* end = it + buf->used; while( it != end ) { type = ur_type(it); if( ur_isWordType(type) ) { if( ur_binding(it) == UR_BIND_THREAD ) ur_unbind(it); } else if( ur_isSeriesType(type) ) { return ur_error( ut, UR_ERR_INTERNAL, "Cannot write block containing series to thread port" ); } ++it; } } } else buf = 0; queue = (port->SIDE == SIDE_A) ? &ext->A : &ext->B; mutexLock( queue->mutex ); if( queue->END_OPEN ) { thread_queue( &queue->buf, data, buf ); condSignal( queue->cond ); writeEvent( queue ); } mutexUnlock( queue->mutex ); return UR_OK; }
static UIndex thread_dequeue( UBuffer* qbuf, UIndex it, UCell* dest, UBuffer* transitBuf ) { *dest = qbuf->ptr.cell[ it ]; ++it; if( ur_isSeriesType(ur_type(dest)) && ! ur_isShared( dest->series.buf ) ) { memCpy( transitBuf, qbuf->ptr.cell + it, sizeof(UBuffer) ); ++it; } if( it == qbuf->used ) it = qbuf->used = 0; return it; }
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; }
/* 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" ); }