#include #include #include #include #include int lx_shape__px = -1; typedef struct shape_qpriv SHAPE_QPRIV; struct shape_qpriv { LX_CONN *xc; LX_SHAPE_PRIV *p; int there; LX_OP *queryop; int *qsupp; } ; static void done_shape_queryversion(LX_OP *op, const unsigned char *rep, void *qpv) { SHAPE_QPRIV *qp; int maj; int min; qp = qpv; do <"ret"> { if (lxxi_r_card32(rep+4) != 0) { lxxi_protoerr(lxxi_op_conn(op),"ShapeQueryVersion resposne length wrong (%u, expecting 0)",lxxi_r_card32(rep+4)); break <"ret">; } maj = lxxi_r_card16(rep+8); min = lxxi_r_card16(rep+10); if (maj != 1) { qp->p->state = SS_BADVERS; } else { /* * We normally would check minor before doing this, but we * expect 1.0, so any minor version is >= our minor version; * versions are unsigned. */ qp->p->state = SS_PRESENT; } } while (0); } static void queryversion_done(void *qpv) { SHAPE_QPRIV *qp; qp = qpv; switch (qp->p->state) { case SS_BADVERS: if (qp->qsupp) *qp->qsupp = 0; break; case SS_PRESENT: if (qp->qsupp) *qp->qsupp = 1; break; default: abort(); break; } lxxi_op_finished(qp->queryop); free(qp); } static void shape_query_done(void *qpv) { SHAPE_QPRIV *qp; qp = qpv; if (qp->there) { unsigned char req[4]; req[0] = qp->p->major; req[1] = 0; lxxi_w_card16(&req[2],1); lx_op_callback(lxxi_expect_reply(qp->xc,&req[0],4,&done_shape_queryversion,qp),&queryversion_done,qp,0); } else { qp->p->state = SS_ABSENT; if (qp->qsupp) *qp->qsupp = 0; lxxi_op_finished(qp->queryop); free(qp); } } LX_OP *lx_shape_query(LX_CONN *xc, int *supp) { LX_SHAPE_PRIV *p; SHAPE_QPRIV *qp; if (lx_shape__px < 0) lx_shape__px = lx_new_conn_private(); p = lx_get_private(xc,lx_shape__px); if (! p) { p = malloc(sizeof(LX_SHAPE_PRIV)); p->state = SS_NEW; lx_set_private(xc,lx_shape__px,p); } switch (p->state) { case SS_NEW: break; case SS_RUNNING: lxxi_bad_call(xc,"lx_shape_query"); return(0); break; case SS_PRESENT: *supp = 1; return(lxxi_predone_op(xc)); break; case SS_BADVERS: case SS_ABSENT: *supp = 0; return(lxxi_predone_op(xc)); break; default: abort(); break; } qp = malloc(sizeof(SHAPE_QPRIV)); qp->xc = xc; qp->p = p; qp->qsupp = supp; p->state = SS_RUNNING; lx_op_callback(lx_QueryExtension(xc,"SHAPE",-1,&qp->there,&p->major,&p->event,&p->error),&shape_query_done,qp,0); qp->queryop = lxxi_internal_op(xc); return(qp->queryop); }