Newer
Older
glColor3f( 1, 1, 1 );
else
glColor3ubv( (GLubyte *)&st->textcmap[ p->rgba ].cooked );
cment = p->rgba;
}
sfStrDrawTJ( sl->text, p->size, &p->p, &Ttext, NULL );
if(st->usemeshes) {
struct mesh *m;
int texturing = 0;
if(additive_blend && st->alpha < 1) {
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE );
} else {
glDisable( GL_BLEND );
}
glColor4f(1, 1, 1, st->alpha);
for(m = st->staticmeshes; m != NULL; m = m->next)
specks_draw_mesh(st, m, &texturing);
for(m = CURDATATIME(meshes); m != NULL; m = m->next)
specks_draw_mesh(st, m, &texturing);
if(texturing) txbind(NULL, NULL);
}
if(st->useellipsoids) {
struct ellipsoid *e;
if(additive_blend) {
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE );
} else {
glDisable( GL_BLEND );
}
glColor4f(1, 1, 1, st->alpha);
for(e = st->staticellipsoids; e != NULL; e = e->next)
specks_draw_ellipsoid(st, e);
}
for(i = 0; i < 6; i++) /* in case clipbox was enabled when we began */
glDisable( GL_CLIP_PLANE0 + i );
glColor4ub(255,255,255,255);
glDisable( GL_BLEND );
glEnable( GL_DEPTH_TEST ); /* was already enabled */
glDepthMask( GL_TRUE );
glcheck("post-drawspecks");
void specks_draw_ellipsoid( struct stuff *st, struct ellipsoid *e )
int nu = e->nu;
int nv = e->nv;
int u, v;
float *su, *cu, *sv, *cv;
if(st->boxlevelmask == 0 || e->level >= 0 && ((1 << e->level) & st->boxlevelmask) == 0)
return;
if(nu == 0 && nv == 0) {
nu = 15;
nv = 10;
}
su = NewA( float, nu );
cu = NewA( float, nu );
sv = NewA( float, nv );
cv = NewA( float, nv );
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
for(u = 0; u < nu; u++) {
float tu = 2*M_PI*u/nu;
su[u] = sin(tu);
cu[u] = cos(tu);
}
for(v = 0; v < nv; v++) {
float tv = M_PI*v/(nv-1);
sv[v] = sin(tv);
cv[v] = cos(tv);
}
glPushMatrix();
glTranslatef( e->pos.x[0],e->pos.x[1],e->pos.x[2] );
if(e->hasori)
glMultMatrixf( &e->ori.m[0] );
glScalef( e->size.x[0], e->size.x[1], e->size.x[2] );
if(e->cindex >= 0) {
int rgba =
RGBALPHA(
RGBWHITE & st->cmap[(e->cindex < st->ncmap) ? e->cindex : st->ncmap-1].cooked,
(int)(st->alpha * 255));
glColor4ubv((GLubyte *)&rgba);
}
glLineWidth( e->linewidth > 0 ? e->linewidth : 1.0f );
case S_SOLID:
for(v = 1; v < nv; v++) {
glBegin( GL_QUAD_STRIP );
for(u = 0; u < nu; u++) {
glVertex3f( cu[u]*sv[v-1], su[u]*sv[v-1], cv[v-1] );
glVertex3f( cu[u]*sv[v], su[u]*sv[v], cv[v] );
}
glVertex3f( cu[0]*sv[v-1], su[0]*sv[v-1], cv[v-1] );
glVertex3f( cu[0]*sv[v], su[0]*sv[v], cv[v] );
glEnd();
}
break;
case S_LINE:
for(v = 1; v < nv-1; v++) {
glBegin( GL_LINE_LOOP );
for(u = 0; u < nu; u++)
glVertex3f( cu[u]*sv[v], su[u]*sv[v], cv[v] );
glEnd();
}
for(u = 0; u < nu; u++) {
glBegin( GL_LINE_STRIP );
for(v = 0; v < nv; v++)
glVertex3f( cu[u]*sv[v], su[u]*sv[v], cv[v] );
glEnd();
}
break;
case S_PLANE:
glBegin( GL_LINE_LOOP );
for(u = 0; u < nu; u++)
glVertex3f( cu[u], su[u], 0 );
glEnd();
glBegin( GL_LINE_LOOP );
for(u = 0; u < nu; u++)
glVertex3f( cu[u], 0, su[u] );
glEnd();
glBegin( GL_LINE_LOOP );
for(u = 0; u < nu; u++)
glVertex3f( 0, cu[u], su[u] );
glEnd();
break;
case S_POINT:
glPointSize( 1.0 );
glBegin( GL_POINTS );
glVertex3f( 0,0,1 );
glVertex3f( 0,0,-1 );
for(v = 1; v < nv-1; v++) {
for(u = 0; u < nu; u++)
glVertex3f( cu[u]*sv[v], su[u]*sv[v], cv[v] );
}
glEnd();
break;
void specks_draw_mesh( struct stuff *st, register struct mesh *m, int *texturing )
{
int u, v, prev, cur;
float gap, ungap;
int f, was;
int usemullions = (st->mullions > 0);
usetx = (st->usetextures && m->tx != NULL
&& m->txno >= 0 && m->txno < st->ntextures
&& st->textures[m->txno] != NULL);
glLineWidth( m->linewidth > 0 ? m->linewidth : 1.0f );
txbind( usetx ? st->textures[m->txno] : NULL, texturing );
if(m->fnorms != NULL && st->usemeshes != 2) {
static float amb[4] = { 0,0,0, 1 };
static float spec[4] = { .8,.8,.8, 1 };
glEnable( GL_LIGHTING );
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
glEnable( GL_COLOR_MATERIAL );
glShadeModel( GL_SMOOTH );
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 20. );
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, amb );
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, spec );
} else {
glDisable( GL_LIGHTING );
glDisable( GL_COLOR_MATERIAL );
if(m->cindex >= 0) {
int rgba =
RGBALPHA(
RGBWHITE & st->cmap[(m->cindex < st->ncmap) ? m->cindex : st->ncmap-1].cooked,
(int)(st->alpha * 255));
glColor4ubv((GLubyte *)&rgba);
} else if(st->coloredby == CONSTVAL) {
struct valdesc *vd = &st->vdesc[st->curdata][CONSTVAL];
glColor4f( vd->cmin, vd->cmax, vd->mean, st->alpha );
case MODEL:
if(m->objrender)
(*m->objrender)( st, m );
break;
case QUADMESH:
switch(m->style) {
case S_SOLID:
for(v = 1; v < m->nv; v++) {
prev = (v-1) * m->nu;
cur = v * m->nu;
glBegin( GL_QUAD_STRIP );
if(usetx) {
if(usetx3d) {
for(u = 0; u < m->nu; u++) {
glTexCoord3fv( &m->tx[prev+u].x[0] );
glVertex3fv( &m->pts[prev+u].x[0] );
glTexCoord3fv( &m->tx[cur+u].x[0] );
glVertex3fv( &m->pts[cur+u].x[0] );
}
for(u = 0; u < m->nu; u++) {
glTexCoord2fv( &m->tx[prev+u].x[0] );
glVertex3fv( &m->pts[prev+u].x[0] );
glTexCoord2fv( &m->tx[cur+u].x[0] );
glVertex3fv( &m->pts[cur+u].x[0] );
}
}
} else {
for(u = 0; u < m->nu; u++) {
glVertex3fv( &m->pts[prev+u].x[0] );
glVertex3fv( &m->pts[cur+u].x[0] );
}
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
case S_LINE:
for(v = 0; v < m->nv; v++) {
glBegin( GL_LINE_STRIP );
cur = v * m->nu;
for(u = 0; u < m->nu; u++)
glVertex3fv( &m->pts[cur+u].x[0] );
glEnd();
}
for(u = 0; u < m->nu; u++) {
glBegin( GL_LINE_STRIP );
for(v = 0; v < m->nv; v++)
glVertex3fv( &m->pts[v*m->nu + u].x[0] );
glEnd();
}
break;
case S_POINT:
cur = m->nu * m->nv;
glBegin( GL_POINTS );
for(u = 0; u < cur; u++)
glVertex3fv( &m->pts[u].x[0] );
glEnd();
break;
case S_PLANE:
glBegin( GL_LINE_LOOP );
for(u = 0; u < m->nu; u++)
glVertex3fv( &m->pts[u].x[0] );
for(v = 1; v < m->nv; v++)
glVertex3fv( &m->pts[v*m->nu + m->nu-1].x[0] );
cur = (m->nv-1) * m->nu;
for(u = m->nu; --u >= 0; )
glVertex3fv( &m->pts[cur+u].x[0] );
for(v = m->nv-1; --v > 0; )
glVertex3fv( &m->pts[v*m->nu].x[0] );
break;
}
break;
case POLYMESH:
gap = st->mullions;
ungap = 1 - gap;
was = 0;
for(f = 0; f < m->nfaces; f++) {
int fv0 = m->fv0[f];
int fvn = m->fvn[f];
int *fvs0 = &m->fvs[ fv0 ];
Point *pts = m->pts;
Point *txs = m->tx;
Point *vnorms = m->vnorms;
#define FVERT(i) fvs0[(i)*FVSTEP + FVS_VERT]
#define FTX(i) fvs0[(i)*FVSTEP + FVS_TX]
#define FVNORM(i) fvs0[(i)*FVSTEP + FVS_VNORM]
int usevn = unlit ? -1 : (FVNORM(0) >= 0) ? 1 : 0;
int usetex = usetx && (FTX(0) >= 0);
glNormal3fv( m->fnorms[f].x );
if(fvn == 2) {
if(was != GL_LINES) {
if(was) glEnd();
glBegin( was=GL_LINES );
}
glVertex3fv( pts[ FVERT(0) ].x );
glVertex3fv( pts[ FVERT(1) ].x );
} else if(fvn == 3) {
Point bary, *p0, *p1, *p2;
if(usemullions) {
p0 = &pts[ FVERT(0) ];
p1 = &pts[ FVERT(1) ];
p2 = &pts[ FVERT(2) ];
bary.x[0] = (p0->x[0] + p1->x[0] + p2->x[0]) * 0.3333333333f;
bary.x[1] = (p0->x[1] + p1->x[1] + p2->x[1]) * 0.3333333333f;
bary.x[2] = (p0->x[2] + p1->x[2] + p2->x[2]) * 0.3333333333f;
#define INTERP(p) p->x[0]*gap + bary.x[0]*ungap, p->x[1]*gap + bary.x[1]*ungap, p->x[2]*gap + bary.x[2]*ungap
#define TXINTERP(tx) tx->x[0]*gap + txbary[0]*ungap, tx->x[1]*gap + txbary[1]*ungap
if(was) {
was = 0;
glEnd();
}
glBegin( GL_QUAD_STRIP );
if(usetex) {
Point *tx0 = &txs[ FTX(0) ];
Point *tx1 = &txs[ FTX(1) ];
Point *tx2 = &txs[ FTX(2) ];
float txbary[2];
txbary[0] = (tx0->x[0] + tx1->x[0] + tx2->x[0]) * 0.33333333f;
txbary[1] = (tx0->x[1] + tx1->x[1] + tx2->x[1]) * 0.33333333f;
if(usevn>0) glNormal3fv( vnorms[ FVNORM(0) ].x );
glTexCoord2fv( tx0->x );
glVertex3fv( p0->x );
glTexCoord2f( TXINTERP( tx0 ) );
glVertex3f( INTERP( p0 ) );
if(usevn>0) glNormal3fv( vnorms[ FVNORM(1) ].x );
glTexCoord2fv( tx1->x );
glVertex3fv( p1->x );
glTexCoord2f( TXINTERP( tx1 ) );
glVertex3f( INTERP( p1 ) );
if(usevn>0) glNormal3fv( vnorms[ FVNORM(2) ].x );
glTexCoord2fv( tx2->x );
glVertex3fv( p2->x );
glTexCoord2f( TXINTERP( tx2 ) );
glVertex3f( INTERP( p2 ) );
if(usevn>0) glNormal3fv( vnorms[ FVNORM(0) ].x );
glTexCoord2fv( tx2->x );
glVertex3fv( p0->x );
glTexCoord2f( TXINTERP( tx0 ) );
glVertex3f( INTERP( p0 ) );
glNormal3fv( vnorms[FVNORM(0)].x );
glVertex3fv(p0->x); glVertex3f( INTERP(p0) );
glNormal3fv( vnorms[FVNORM(1)].x );
glVertex3fv(p1->x); glVertex3f( INTERP(p1) );
glNormal3fv( vnorms[FVNORM(2)].x );
glVertex3fv(p2->x); glVertex3f( INTERP(p2) );
glNormal3fv( vnorms[FVNORM(0)].x );
glVertex3fv(p0->x); glVertex3f( INTERP(p0) );
} else {
glVertex3fv(p0->x); glVertex3f( INTERP(p0) );
glVertex3fv(p1->x); glVertex3f( INTERP(p1) );
glVertex3fv(p2->x); glVertex3f( INTERP(p2) );
glVertex3fv(p0->x); glVertex3f( INTERP(p0) );
}
} else {
/* No mullions */
if(was != GL_TRIANGLES) {
if(was) glEnd();
glBegin( was=GL_TRIANGLES );
}
if(usetex) {
glNormal3fv( vnorms[FVNORM(0)].x );
glTexCoord2fv( txs[ FTX(0) ].x );
glVertex3fv( pts[ FVERT(0) ].x );
glNormal3fv( vnorms[FVNORM(1)].x );
glTexCoord2fv( txs[ FTX(1) ].x );
glVertex3fv( pts[ FVERT(1) ].x );
glNormal3fv( vnorms[FVNORM(2)].x );
glTexCoord2fv( txs[ FTX(2) ].x );
glVertex3fv( pts[ FVERT(2) ].x );
} else {
glTexCoord2fv( txs[ FTX(0) ].x );
glVertex3fv( pts[ FVERT(0) ].x );
glTexCoord2fv( txs[ FTX(1) ].x );
glVertex3fv( pts[ FVERT(1) ].x );
glTexCoord2fv( txs[ FTX(2) ].x );
glVertex3fv( pts[ FVERT(2) ].x );
}
glNormal3fv( vnorms[FVNORM(0)].x );
glVertex3fv( pts[ FVERT(0) ].x );
glNormal3fv( vnorms[FVNORM(1)].x );
glVertex3fv( pts[ FVERT(1) ].x );
glNormal3fv( vnorms[FVNORM(2)].x );
glVertex3fv( pts[ FVERT(2) ].x );
} else {
glVertex3fv( pts[ FVERT(0) ].x );
glVertex3fv( pts[ FVERT(1) ].x );
glVertex3fv( pts[ FVERT(2) ].x );
}
}
} else if(fvn == 4) {
if(was != GL_QUADS) {
if(was) glEnd();
glBegin( was=GL_QUADS );
}
if(usetex) {
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
glNormal3fv( vnorms[FVNORM(0)].x );
glTexCoord2fv( txs[FTX(0)].x );
glVertex3fv( pts[ FVERT(0) ].x );
glNormal3fv( vnorms[FVNORM(1)].x );
glTexCoord2fv( txs[FTX(1)].x );
glVertex3fv( pts[ FVERT(1) ].x );
glNormal3fv( vnorms[FVNORM(2)].x );
glTexCoord2fv( txs[FTX(2)].x );
glVertex3fv( pts[ FVERT(2) ].x );
glNormal3fv( vnorms[FVNORM(3)].x );
glTexCoord2fv( txs[FTX(3)].x );
glVertex3fv( pts[ FVERT(3) ].x );
} else {
glTexCoord2fv( txs[FTX(0)].x );
glVertex3fv( pts[ FVERT(0) ].x );
glTexCoord2fv( txs[FTX(1)].x );
glVertex3fv( pts[ FVERT(1) ].x );
glTexCoord2fv( txs[FTX(2)].x );
glVertex3fv( pts[ FVERT(2) ].x );
glTexCoord2fv( txs[FTX(3)].x );
glVertex3fv( pts[ FVERT(3) ].x );
}
} else {
glNormal3fv( vnorms[FVNORM(0)].x );
glVertex3fv( pts[ FVERT(0) ].x );
glNormal3fv( vnorms[FVNORM(1)].x );
glVertex3fv( pts[ FVERT(1) ].x );
glNormal3fv( vnorms[FVNORM(2)].x );
glVertex3fv( pts[ FVERT(2) ].x );
glNormal3fv( vnorms[FVNORM(3)].x );
glVertex3fv( pts[ FVERT(3) ].x );
} else {
glVertex3fv( pts[ FVERT(0) ].x );
glVertex3fv( pts[ FVERT(1) ].x );
glVertex3fv( pts[ FVERT(2) ].x );
glVertex3fv( pts[ FVERT(3) ].x );
}
}
if(was) {
glEnd();
was = 0;
}
glBegin( GL_TRIANGLE_STRIP );
if(usevn>0) glNormal3fv( vnorms[ FVNORM(0) ].x );
if(usetex) glTexCoord2fv( txs[ FTX(0) ].x );
glVertex3fv( pts[ FVERT(0) ].x );
fvs0 += FVSTEP;
} while(++fvn < 0);
glEnd();
if(was) {
glEnd();
was = 0;
}
glBegin( GL_POLYGON );
if(usevn>0) glNormal3fv( vnorms[ FVNORM(0) ].x );
if(usetex) glTexCoord2fv( txs[ FTX(0) ].x );
glVertex3fv( pts[ FVERT(0) ].x );
fvs0 += FVSTEP;
glEnd();
}
}
if(was) glEnd();
break;
}
if(m->fnorms != NULL) {
glDisable( GL_LIGHTING );
glDisable( GL_COLOR_MATERIAL );
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
void specks_draw_boxes( struct stuff *st, struct AMRbox *boxes, int boxlevelmask, Matrix Ttext, int oriented )
{
static short arcs[] = {
5, 4, 6, 2, 3, 1, 5, 7, 6,
-1,
7, 3,
0, 1,
0, 2,
0, 4
};
struct AMRbox *box;
int i;
float boxscale, s0, s1;
int isscaled;
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glLineWidth( st->boxlinewidth );
glEnable( GL_BLEND );
glDisable( GL_LINE_SMOOTH );
/* Scan through the array, whose end is marked with a box at level -1. */
for(box = boxes; box->level >= 0; box++) {
boxscale = (box->level < 0) ? 1.0
: st->boxscale[ box->level>=MAXBOXLEV ? MAXBOXLEV-1 : box->level ];
isscaled = (boxscale != 0 && boxscale != 1);
if(isscaled) {
s0 = .5*(1 + boxscale);
s1 = .5*(1 - boxscale);
}
if((1 << box->level) & boxlevelmask) {
int cval = RGBALPHA(st->boxcmap[
box->level<0 ? 0
: box->level>=st->boxncmap ?
st->boxncmap-1 : box->level ].cooked,
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
0xFF);
int colorme = 0;
if(oriented)
cval = orientboxcolor;
glColor4ubv( (GLubyte *)&cval );
glBegin( GL_LINE_STRIP );
for(i = 0; i < COUNT(arcs); i++) {
int vert = arcs[i];
if(vert < 0) {
glEnd();
glBegin( GL_LINES );
} else {
if(oriented) {
if(vert == 0) {
glColor4ubv( (GLubyte *)&cval );
colorme = 1;
} else if(colorme) {
glColor3f( vert&1?1:0, vert&2?1:0, vert&4?1:0 );
}
}
if(isscaled && !oriented && box->level >= 0) {
glVertex3f(
vert&1 ? s0*box->p0.x[0] + s1*box->p1.x[0]
: s1*box->p0.x[0] + s0*box->p1.x[0],
vert&2 ? s0*box->p0.x[1] + s1*box->p1.x[1]
: s1*box->p0.x[1] + s0*box->p1.x[1],
vert&4 ? s0*box->p0.x[2] + s1*box->p1.x[2]
: s1*box->p0.x[2] + s0*box->p1.x[2] );
} else {
glVertex3f(
(vert&1 ? box->p1.x : box->p0.x)[0],
(vert&2 ? box->p1.x : box->p0.x)[1],
(vert&4 ? box->p1.x : box->p0.x)[2]
);
}
}
}
glEnd();
if(st->boxlabels && st->boxlabelscale != 0) {
float sz = .16 * vdist( &box->p0, &box->p1 ) / st->textsize;
vlerp( &mid, .5, &box->p0, &box->p1 );
sfStrDrawTJ( lbl, sz, &mid, &Ttext, "c" );
}
}
}
glLineWidth( 1 );
}
int specks_partial_pick_decode( struct stuff *st, int id,
int nhits, int nents, GLuint *hitbuf,
unsigned int *bestzp, struct specklist **slp,
int *specknop, Point *pos )
{
int i, hi, ns, slno;
GLuint z0, bestz = *bestzp;
int bestslno = 0, bestspeck = -1;
struct specklist *sl, *slhead;
if(st == NULL)
return 0;
if(st->picked != NULL)
(*st->picked)(st, NULL, NULL, nhits); /* "prepare for up to nhits calls" */
slhead = st->frame_sl; /* st->sl as snapped by specks_ffn() */
if(slhead == NULL) slhead = st->sl; /* maybe there is no specks_ffn() */
if(slhead == NULL) return 0;
for(hi = 0, i = 0; hi < nhits && i < nents; hi++, i += ns + 3) {
ns = hitbuf[i];
if(ns < 1 || ns > 16)
break; /* trouble */
z0 = hitbuf[i+1];
if(id != hitbuf[i+3] || ns <= 1) continue;
if(st->usepoly>1) /* debug */
printf(ns>1?"[%x %d/%d]":"[%x %d]", z0, hitbuf[i+3],hitbuf[i+4]);
if(bestz > z0 && ns > 1 && (slno = hitbuf[i+4]) > 0) {
bestz = z0;
bestslno = slno;
bestspeck = (ns>2) ? hitbuf[i+5] : 0;
}
if(st->picked != NULL && ns > 2) {
for(sl = slhead, slno = 1; sl != NULL && slno < hitbuf[i+4]; sl = sl->next, slno++)
;
if(sl && hitbuf[i+5] < sl->nspecks)
if((*st->picked)(st, &hitbuf[i], sl, hitbuf[i+5]))
return 0;
}
}
if(st->picked != NULL) {
if((*st->picked)(st, NULL, NULL, 0))
return 0;
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
}
if(bestslno <= 0)
return 0;
for(sl = slhead, slno = 1; sl != NULL; sl = sl->next, slno++) {
if(slno == bestslno) {
if(bestspeck < 0 || bestspeck >= sl->nspecks) {
msg("Bogus pick result: sl %x bestspeck %d of 0..%d!\n",
sl, bestspeck, sl->nspecks-1);
return 0;
}
if(slp) *slp = sl;
if(specknop) *specknop = bestspeck;
if(pos) {
if(bestspeck < 0 || bestspeck >= sl->nspecks)
bestspeck = 0;
*pos = NextSpeck( sl->specks, sl, bestspeck )->p;
}
*bestzp = bestz;
return 1;
}
}
return 0;
}
int selname( struct stuff *st, char *name, int create ) {
if(name == NULL) return 0;
if(!strcmp(name, "all") || !strcmp(name, "on")) return SEL_ALL;
if(!strcmp(name, "none") || !strcmp(name, "off")) return SEL_OFF;
if(!strcmp(name, "thresh")) return SEL_THRESH;
if(!strcmp(name, "pick")) return SEL_PICK;
for(i = COUNT(st->selitems); --i >= 0; ) {
if(!strcmp(name, st->selitems[i].name))
return i+1;
if(st->selitems[i].name[0] == '\0') avail = i;
}
if(create) {
sprintf(st->selitems[avail].name, "%.15s", name);
return avail+1;
}
return 0;
}
void selinit( SelOp *sp ) {
sp->wanton = 0;
sp->use = SEL_NONE;
}
static char *selcat( struct stuff *st, char *from, int selno, int preop ) {
char *what = "";
static char s[8];
switch(selno) {
case SEL_ALL: what = "all"; break;
case SEL_THRESH: what = "thresh"; break;
case SEL_PICK: what = "pick"; break;
default:
if(selno > 0 && selno <= MAXSEL && st->selitems[selno-1].name[0] != '\0')
what = &st->selitems[selno-1].name[0];
else {
sprintf(s, "%d", selno<0||selno>MAXSEL?0:selno);
what = s;
}
}
if(preop)
*from++ = preop;
return from + sprintf(from, "%.15s ", what);
}
char *show_selexpr( struct stuff *st, SelOp *destp, SelOp *srcp )
{
char str[(MAXSELNAME + 2)*33];
char *tail = str;
static char *sstr;
static int sroom = -1;
int i;
if(destp) {
if(destp->wanted == 0) {
tail = selcat(st, tail, SEL_ALL, 0 );
} else {
for(i = SEL_THRESH; i > 0; i--) {
tail = selcat( st, tail, i,
destp->wanton & SELMASK(i) ? 0 : '-' );
} else if(destp->wanton & SELMASK(i)) {
tail = selcat( st, tail, i, '^' );
}
}
}
if(srcp)
tail += sprintf(tail, "= ");
tail = selcat( st, tail, srcp->use, 0 );
} else if(srcp->use == SEL_USE && srcp->wanted == 0) {
tail = selcat( st, tail, SEL_ALL, 0 );
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
} else {
for(i = SEL_THRESH; i > 0; i--) {
if(srcp->wanted & SELMASK(i)) {
tail = selcat( st, tail, i,
srcp->wanton & SELMASK(i) ? 0 : '-' );
} else if(srcp->wanton & SELMASK(i)) {
tail = selcat( st, tail, i, '^' );
}
}
}
}
if(tail - str > sroom) {
if(sstr) Free(sstr);
sroom = tail - str + 60;
sstr = NewN( char, sroom );
}
if(tail == str) strcpy(sstr, "null");
else {
tail[-1] = '\0';
strcpy(sstr, str);
}
return sstr;
}
enum SelToken {
SEL_ERR, /* unknown */
SEL_EOF,
SEL_WORD, /* bare word or +word */
SEL_EQUALS /* = */
};
static enum SelToken seltoken( CONST char **sp, int *leadcp, char word[MAXSELNAME] ) {
CONST char *p = *sp;
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
int k;
*leadcp = '\0';
word[0] = '\0';
while(isspace(*p)) p++;
if(*p == '\0')
return SEL_EOF;
if(*p == '-' || *p == '^' || *p == '+')
*leadcp = *p++;
if(*p == '=') {
*sp = p+1;
return SEL_EQUALS;
}
if(!(isalnum(*p) || *p == '_'))
return SEL_ERR;
word[0] = *p++;
for(k = 1; isalnum(*p) || *p == '_'; p++) {
if(k < MAXSELNAME-1) word[k++] = *p;
}
word[k] = '\0';
*sp = p;
return SEL_WORD;
void seldest2src( struct stuff *st, CONST SelOp *dest, SelOp *src ) {
selinit( src );
if(dest->use == SEL_USE) {
*src = *dest;
} else if(dest->use == SEL_DEST) {
src->wanted = ~dest->wanted | dest->wanton;
src->wanton = dest->wanton;
void selsrc2dest( struct stuff *st, CONST SelOp *src, SelOp *dest ) {
*dest = *src;
if(src->use == SEL_USE) {
dest->wanted = ~src->wanted;
dest->wanton = src->wanton & src->wanted;
dest->use = SEL_DEST;
}
}
void seldestinvert( struct stuff *st, SelOp *dest ) {
dest->wanton ^= ~dest->wanted;
}
int seldest( struct stuff *st, SelOp *dest, int selno, int selch ) {
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
SelMask mask;
if(dest == NULL)
return 0;
if(selno == SEL_ALL) {
mask = ~0;
} else if(selno <= 0 || selno > 32) {
return 0;
} else {
mask = SELMASK(selno);
}
if(dest->use != SEL_DEST) {
dest->use = SEL_DEST;
dest->wanted = ~0;
dest->wanton = 0;
}
switch(selch) {
case '^':
dest->wanted |= mask;
dest->wanton |= mask;
break;
case '-':
dest->wanted &= ~mask;
dest->wanton &= ~mask;
break;
case '+':
case '\0':
dest->wanted &= ~mask;
dest->wanton |= mask;
break;
default:
int selsrc( struct stuff *st, SelOp *src, int selno, int selch ) {
SelMask mask;
if(src == NULL)
return 0;
if(src->use == SEL_DEST) {
src->wanted = 0;
src->wanton = 0;
src->use = SEL_USE;
}
if(selno == SEL_OFF) {
src->wanted = src->wanton = mask = ~0;
src->use = SEL_NONE;
} else if(selno == SEL_ALL) {
src->wanted = src->wanton = mask = 0;
src->use = SEL_USE;
} else if(selno > 0 && selno <= 32) {
mask = SELMASK(selno);
} else {
return 0;
}
switch(selch) {
case '-':
src->wanted |= mask;
src->wanton &= ~mask;
break;
case '+':
case '\0':
src->wanted |= mask;
src->wanton |= mask;
break;
default:
return 0;
}
return 1;
}
/*
* [word [op]=] { [op]word }*
*/
int parse_selexpr( struct stuff *st, CONST char *str, SelOp *destp, SelOp *srcp, CONST char *plaint )
{
SelOp dest, src;
char wd[MAXSELNAME], w[MAXSELNAME];
CONST char *p = str;
enum SelToken tok, tok2;
int ok = 1;
int anysrc = 0, anydest = 0;
selinit(&dest); selinit(&src);
tok = seltoken( &p, &leadc, wd );
if(tok == SEL_EOF)
return 0;
/* Had better begin with a word, and with no prefix */
int destno;
if(tok != SEL_WORD) goto fail;
destno = selname( st, wd, 1 );
tok2 = seltoken( &p, &leadc2, w );
if(tok2 == SEL_ERR) goto fail;
ok = seldest( st, &dest, destno, leadc ? leadc : leadc2 );
anydest = 1;
if(!ok) goto fail;
if(tok2 == SEL_WORD) {
tok = SEL_WORD;
leadc = leadc2;
strcpy(wd, w);
} else {
tok = seltoken( &p, &leadc, wd );
}
}
while(srcp && tok == SEL_WORD) {
ok = selsrc( st, &src, selname( st, wd, 0 ), leadc );
if(!ok) goto fail;
if(src.use == SEL_NONE && src.wanted != 0 && destp) {
seldestinvert( st, &dest );
selsrc( st, &src, SEL_ALL, 0 ); /* X = off <=> -X = on */
}
anysrc = 1;
tok = seltoken( &p, &leadc, wd );
if(tok != SEL_EOF)
goto fail;
if(destp && anydest) *destp = dest;
if(srcp && anysrc) *srcp = src;
return (anydest?1:0) + (anysrc?2:0);
if(plaint)
msg("%s: um, %s", plaint, str);
return 0; /*XXX*/
}
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
CONST char *selcounts( struct stuff *st, struct specklist *sl, SelOp *selp ) {
int i;
static char counts[24];
int yes, total;
SelOp selop;
if(selp == NULL) return "";
if(selp->use == SEL_DEST)
seldest2src( st, selp, &selop );
else
selop = *selp;
for(yes = total = 0; sl != NULL; sl = sl->next) {
SelMask *sel = sl->sel;
if(sl->text != NULL || sl->nsel < sl->nspecks || sl->special != SPECKS)
continue;
total += sl->nspecks;
for(i = 0; i < sl->nspecks; i++)
if(SELECTED(sel[i], &selop))
yes++;
}
if(selop.use == SEL_NONE) yes = 0;
sprintf(counts, "%d of %d", yes, total);
return counts;
}
SpecksPickFunc specks_all_picks( struct stuff *st, SpecksPickFunc func, void *arg ) {
SpecksPickFunc was = st->picked;
st->picked = func;
st->pickinfo = arg;
return was;
}
static void addchunk( struct stuff *st, int nsp, int bytesperspeck,
float scaledby, struct speck *sp, char *text,
int outbytesperspeck )
{
struct specklist **slp, *sl = NewN( struct specklist, 1 );
memset( sl, 0, sizeof(*sl) );