Exemplo n.º 1
0
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;
}
Exemplo n.º 2
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
}
Exemplo n.º 3
0
/*
  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" );
}
Exemplo n.º 4
0
static void itemview_rebuildAttr( UThread* ut, GItemView* ep,
                                  const UBuffer* items, int page )
{
#define MAX_ITEM_TRIS   400
#define MAX_DEC_TRIS    100
#define TRI_ATTR_BYTES  (3 * AttrCount * sizeof(GLfloat))
    DrawContext dc;
    UBlockIter bi;
    UBlockIter layout;
    UBuffer* fcBuf;
    const UCell* loStart;
    UCell* cell;
    float* attr;
    int bsize;
    int height = ep->itemHeight;
    int caOffset = items->used + DECORATION_GROUPS;


    // Reserve triangles for each item.
    ur_binReserve( &glEnv.tmpBin,
           (MAX_DEC_TRIS + (items->used * MAX_ITEM_TRIS)) * TRI_ATTR_BYTES );
    attr = glEnv.tmpBin.ptr.f;

    // Reserve first & count arrays.  fcBuf->used tracks the number of items
    // and view decorations, which is half the number of integers used for
    // both arrays.
    fcBuf = &ep->fc[ page ];
    ur_arrReserve( fcBuf, caOffset * 2 );
    fcBuf->used = 0;

    dc.attr = attr;
    dc.drawFirst = 0;
    dc.penX = 0.0;

#if 1
    // Build selected background tris.
    dc.drawCount = 0;

    if( ep->selRow > -1 )
    {
        dc.color[0] = 1.0;
        dc.color[1] = dc.color[2] = 0.0;
        dc.penY = ep->wid.area.h;

        cell = glEnv.guiStyle + CI_STYLE_AREA;
        //ur_setId(cell, UT_COORD)
        cell->coord.len = 4;
        cell->coord.n[0] = 0;
        cell->coord.n[1] = (ep->selRow + 1) * -height;
        cell->coord.n[2] = ep->itemWidth;
        cell->coord.n[3] = height;

        layout.buf = ur_buffer( ep->selectBgBlkN );
        layout.it  = layout.buf->ptr.cell;
        layout.end = layout.it + layout.buf->used;

        if( ! itemview_parse( &dc, ut, &layout, (GWidget*) ep ) )
        {
            boron_reset(ut);
            printf( "KR itemview_parse failed\n" );
        }
    }

    fcBuf->ptr.i[ fcBuf->used ] = dc.drawFirst;
    fcBuf->ptr.i[ fcBuf->used + caOffset ] = dc.drawCount;
    ++fcBuf->used;

    dc.attr = attr + MAX_DEC_TRIS * 3 * AttrCount;
    dc.drawFirst = MAX_DEC_TRIS * 3;
#endif

    dc.penY = ep->wid.area.h;


    // Setup the data item and layout iterators.
    bi.it  = items->ptr.cell;
    bi.end = bi.it + items->used;

    layout.buf = ur_buffer( ep->layoutBlkN );
    loStart    = layout.buf->ptr.cell;
    layout.end = loStart + layout.buf->used;

    ur_foreach( bi )
    {
        // Set item word to current data value.
        cell = ur_ctxCell( ur_buffer( ep->bindCtxN ), 0 );
        *cell = *bi.it;

        dc.drawCount = 0;
        dc.color[0] = 1.0;
        dc.color[1] = dc.color[2] = 0.0;
        dc.penY -= height;

        layout.it = loStart;
        if( ! itemview_parse( &dc, ut, &layout, (GWidget*) ep ) )
        {
            boron_reset(ut);
            printf( "KR itemview_parse failed\n" );
        }

        //printf( "KR fc %d,%d\n", dc.drawFirst, dc.drawCount );

        fcBuf->ptr.i[ fcBuf->used ] = dc.drawFirst;
        fcBuf->ptr.i[ fcBuf->used + caOffset ] = dc.drawCount;
        ++fcBuf->used;

        dc.drawFirst += dc.drawCount;
        //dc.drawFirst += MAX_ITEM_TRIS;
    }

    assert( fcBuf->used == caOffset );


    // Transfer vertex data to GPU.
    bsize = dc.drawFirst * TRI_ATTR_BYTES;
    if( ep->vboSize[ page ] < bsize )
    {
        ep->vboSize[ page ] = bsize;
        glBufferData( GL_ARRAY_BUFFER, bsize, attr, GL_STATIC_DRAW );
    }
    else
    {
        float* abuf = (float*) glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
        if( abuf )
        {
            memCpy( abuf, attr, bsize );
            glUnmapBuffer( GL_ARRAY_BUFFER );
        }
    }
}
Exemplo n.º 5
0
/*
  Sets res to either a shader! or a context! whose first value is a shader!.
  Returns UR_OK/UR_THROW.
*/
int ur_makeShader( UThread* ut, const char* vert, const char* frag, UCell* res )
{
#define MAX_SHADER_PARAM    16      // LIMIT: User parameters per shader.
    Shader shad;
    Shader* sh;
    UIndex bufN;
    UBuffer* buf;
    int i;
    char name[ 128 ];
    ShaderParam param[ MAX_SHADER_PARAM ];
    ShaderParam* pi;
    GLsizei length;
    GLint size;
    GLenum type;
    GLint count = 0;

    if( ! createShader( ut, &shad, vert, frag ) )
        return UR_THROW;

    glGetProgramiv( shad.program, GL_ACTIVE_UNIFORMS, &count );

    // Collect non-gl parameters.

    pi = param;
    for( i = 0; i < count; ++i )
    {
        glGetActiveUniform( shad.program, i, 128, &length, &size, &type,
                            name );
        if( name[0] == 'g' && name[1] == 'l' && name[2] == '_' )
            continue;

        pi->type     = type;
        pi->location = glGetUniformLocation( shad.program, name );
        pi->name     = ur_internAtom( ut, name, name + length );
        if( pi->name == UR_INVALID_ATOM )
            return UR_THROW;

        ++pi;
    }
    count = pi - param;

    if( count )
    {
        ShaderParam* pend;
        UBuffer* ctx;
        UCell* cval;

        // We have parameters - make context to hold shader & params.

        ctx = ur_makeContextCell( ut, count + 1, res );
        cval = ur_ctxAddWord( ctx, UR_ATOM_SHADER );

        pi = param;
        pend = param + count;
        while( pi != pend )
        {
            cval = ur_ctxAddWord( ctx, pi->name );
#if 0
            printf( "KR Shader Param %d is type %d\n",
                    (int) (pi - param), pi->type );
#endif
            switch( pi->type )
            {
                case GL_FLOAT:
                    ur_setId( cval, UT_DECIMAL );
                    ur_decimal( cval ) = 0.0;
                    break;

                case GL_FLOAT_VEC2:
                case GL_FLOAT_VEC3:
                //case GL_FLOAT_VEC4:
                    ur_setId( cval, UT_VEC3 );
                    cval->vec3.xyz[0] =
                    cval->vec3.xyz[1] =
                    cval->vec3.xyz[2] = 0.0f;
                    break;

                case GL_INT:
                    ur_setId( cval, UT_INT );
                    ur_int( cval ) = 0;
                    break;

                case GL_INT_VEC2:
                case GL_INT_VEC3:
                //case GL_INT_VEC4:
                    ur_setId( cval, UT_COORD );
                    break;

                case GL_BOOL:
                    ur_setId( cval, UT_LOGIC );
                    ur_int( cval ) = 0;
                    break;

                case GL_SAMPLER_2D:
                case GL_SAMPLER_CUBE:
#ifndef GL_ES_VERSION_2_0
                case GL_SAMPLER_1D:
                case GL_SAMPLER_3D:
                case GL_SAMPLER_1D_SHADOW:
                case GL_SAMPLER_2D_SHADOW:
#endif
                    ur_setId( cval, UT_NONE );
                    ur_texId(cval) = 0;     // Expecting texture!.
                    break;

#ifdef GL_ES_VERSION_2_0
                case GL_FLOAT_MAT4:
                    ur_setId( cval, UT_NONE );
                    break;
#endif

                default:
                    ur_setId( cval, UT_NONE );
                    break;

                /*
                GL_BOOL_VEC2:
                GL_BOOL_VEC3:
                GL_BOOL_VEC4:
                GL_FLOAT_MAT2:
                GL_FLOAT_MAT3:
                GL_FLOAT_MAT4:
                GL_SAMPLER_2D_RECT:
                GL_SAMPLER_2D_RECT_SHADOW:
                */
            }

            ++pi;
        }
        ur_ctxSort( ctx );
    }

    ur_genBuffers( ut, 1, &bufN );
    buf = ur_buffer( bufN );
    buf->type = UT_SHADER;
    buf->ptr.v = memAlloc( sizeof(Shader) +
                           sizeof(ShaderParam) * (count - 1) );

    sh = (Shader*) buf->ptr.v;
    sh->program     = shad.program;
    sh->paramCount  = count;

    if( count )
    {
        memCpy( sh->param, param, sizeof(ShaderParam) * count );

        // First context value will be set to shader!.
        res = ur_buffer( res->series.buf )->ptr.cell;
    }

    ur_setId( res, UT_SHADER );
    ur_setSeries( res, bufN, 0 );
    return UR_OK;
}
Exemplo n.º 6
0
static void ledit_render( GWidget* wp )
{
    DrawTextState ds;
    GLuint* buf;
    GLfloat* fdata;
    UBuffer* str;
    TexFont* tf;
    UCell* style = glEnv.guiStyle;
    UThread* ut  = glEnv.guiUT;
    EX_PTR;

    if( ! ep->strN )
        return;

    tf = ur_texFontV( ut, style + CI_STYLE_EDIT_FONT );
    if( tf )
    {
        str = ur_buffer( ep->strN );
        buf = vbo_bufIds( ur_buffer(ep->vboN) );

        if( flagged( NEW_CURSORX ) )
        {
            int pos;
            clrFlag( NEW_CURSORX );
            pos = txf_charAtPixel( tf, str->ptr.b, str->ptr.b + str->used,
                                   ep->newCursorX - wp->area.x - MARGIN_L );
            if( pos < 0 )
                pos = (ep->newCursorX > wp->area.x + MARGIN_L) ? str->used : 0;
            if( pos != ep->editPos )
            {
                ep->editPos = pos;
                setFlag( CHANGED );
            }
        }

#ifndef GL_ES_VERSION_2_0
        glEnableClientState( GL_TEXTURE_COORD_ARRAY );

        glBindBuffer( GL_ARRAY_BUFFER, buf[0] );

        if( flagged( CHANGED ) )
        {
            clrFlag( CHANGED );
            fdata = (float*) glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
            if( fdata )
            {
                // Cursor verticies.
                int xpos = txf_width(tf, str->ptr.b,
                                         str->ptr.b + ep->editPos );

                // FIXME: UVs require black pixels at upper-left of texture.
                fdata[0] = 0.003f;
                fdata[1] = 0.0f;  //95f;
                fdata[2] = (GLfloat) (wp->area.x + xpos + MARGIN_L);
                fdata[3] = (GLfloat) wp->area.y;

                fdata[4] = 0.003f;
                fdata[5] = 0.01f; //998f;
                fdata[6] = fdata[2];
                fdata[7] = fdata[3] + txf_lineSpacing( tf );

                //glBufferSubData(GL_ARRAY_BUFFER, 0, LEDIT_ATTR_SIZE*2, data);

                fdata += LEDIT_APV * 2;

                vbo_drawTextInit( &ds, tf, wp->area.x + MARGIN_L,
                                           wp->area.y + MARGIN_B );

                ep->drawn = 6 * vbo_drawText( &ds, fdata, fdata + 2, LEDIT_APV,
                                          str->ptr.b, str->ptr.b + str->used );
                glUnmapBuffer( GL_ARRAY_BUFFER );
            }
            //printf( "KR ledit draw\n" );
        }

        glTexCoordPointer( 2, GL_FLOAT, LEDIT_ATTR_SIZE, NULL + 0 );
        glVertexPointer  ( 2, GL_FLOAT, LEDIT_ATTR_SIZE, NULL + 8 );
        glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, buf[1] );

        glColor4f( 0.0, 0.0, 0.0, 1.0 );
        glDrawElements( GL_TRIANGLES, ep->drawn, GL_UNSIGNED_SHORT, NULL + 4 );
        if( gui_hasFocus( wp ) & GW_FOCUS_KEY )
            glDrawElements( GL_LINES, 2, GL_UNSIGNED_SHORT, 0 );

        glDisableClientState( GL_TEXTURE_COORD_ARRAY );
#endif
    }
}
Exemplo n.º 7
0
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
}
Exemplo n.º 8
0
static void ledit_dispatch( UThread* ut, GWidget* wp, const GLViewEvent* ev )
{
    EX_PTR;

    //printf( "KR ledit %d\n", ev->type );
    switch( ev->type )
    {
        case GLV_EVENT_BUTTON_DOWN:
            if( (ev->code == GLV_BUTTON_LEFT) ||
                (ev->code == GLV_BUTTON_MIDDLE) )
            {
                ledit_setState( ut, ep, LEDIT_STATE_EDIT );
                gui_setKeyFocus( wp );

                if( ev->code == GLV_BUTTON_LEFT )
                {
                    // Don't have access to font here so just notify render.
                    ep->newCursorX = ev->x;
                    setFlag( NEW_CURSORX );
                }
                else // if( ev->code == GLV_BUTTON_MIDDLE )
                {
                    ledit_paste( ut, ep );
                    setFlag( CHANGED );
                }
            }
            break;

        case GLV_EVENT_BUTTON_UP:
        case GLV_EVENT_MOTION:
            break;

        case GLV_EVENT_KEY_DOWN:
            if( ep->strN )
            {
                UBuffer* str = ur_buffer( ep->strN );

                if( ev->state & GLV_MASK_CTRL )
                {
                    if( ev->code == KEY_k )
                    {
                        // Remove from cursor to end (from Bash).
                        int len = str->used - ep->editPos;
                        if( len > 0 )
                        {
                            ur_arrErase( str, ep->editPos, len );
                            setFlag( CHANGED );
                        }
                    }
                    else if( ev->code == KEY_v )
                    {
                        ledit_paste( ut, ep );
                        setFlag( CHANGED );
                    }
                    break;
                }

                switch( ev->code )
                {
                    case KEY_Return:
                        goto activate;

                    case KEY_Left:
                        if( ep->editPos > 0 )
                        {
                            --ep->editPos;
                            setFlag( CHANGED );
                        }
                        break;

                    case KEY_Right:
                        if( ep->editPos < str->used )
                        {
                            ++ep->editPos;
                            setFlag( CHANGED );
                        }
                        break;

                    case KEY_Home:
                        ep->editPos = 0;
                        setFlag( CHANGED );
                        break;

                    case KEY_End:
                        ep->editPos = str->used;
                        setFlag( CHANGED );
                        break;

                    case KEY_Insert:
                        break;

                    case KEY_Delete:
                        if( ep->editPos < str->used )
                        {
                            ur_arrErase( str, ep->editPos, 1 );
                            setFlag( CHANGED );
                        }
                        break;

                    case KEY_Back_Space:
                        if( ep->editPos > 0 )
                        {
                            --ep->editPos;
                            ur_arrErase( str, ep->editPos, 1 );
                            setFlag( CHANGED );
                        }
                        break;

                    default:
                        if( str->used < ep->maxChars )
                        {
                            int key = KEY_ASCII(ev);
                            if( key >= ' ' )
                            {
                                if( ep->filterN )
                                {
                                    UBuffer* bin = ur_buffer( ep->filterN );
                                    if( ! _bitIsSet( bin->ptr.b, key ) )
                                        break;
                                }

                                ur_arrExpand( str, ep->editPos, 1 );
                                if( ur_strIsUcs2(str) )
                                    str->ptr.u16[ ep->editPos ] = key;
                                else
                                    str->ptr.b[ ep->editPos ] = key;
                                ++ep->editPos;
                                setFlag( CHANGED );
                            }
                            else
                            {
                                gui_ignoreEvent( ev );
                            }
                        }
                        break;
                }
            }
            break;

        case GLV_EVENT_KEY_UP:
            gui_ignoreEvent( ev );
            break;

        case GLV_EVENT_FOCUS_IN:
            break;

        case GLV_EVENT_FOCUS_OUT:
            ledit_setState( ut, ep, LEDIT_STATE_DISPLAY );
            break;
    }
    return;

activate:

    if( ep->codeN )
        gui_doBlockN( ut, ep->codeN );
}
Exemplo n.º 9
0
/*
  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;
}