Esempio n. 1
0
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
  double *OUTr, *OUTi, *data, *w, *c, *s;
  int m,n,i,j,k;
  char mode[2]; /* 2 because mxGetString appends a NULL character to terminate string */

  if(nrhs!=2)
    mexErrMsgTxt("Two input arguments required!");
  if(nlhs<1)
    mexErrMsgTxt("At least one output argument required");

  for(i=0;i<2;i++)
    if(mxIsEmpty(prhs[i])) mexErrMsgTxt("Input arguments must be nonempty.");

  m=mxGetM(prhs[0]);
  n=mxGetN(prhs[0]);

  if(mxIsDouble(prhs[0]))
    data=mxGetPr(prhs[0]);
  else
    mexErrMsgTxt("Input must be of type double.");


  if((k=mxGetM(prhs[1]))==1)
    k=mxGetN(prhs[1]);

  w=mxGetPr(prhs[1]);

  plhs[0]=mxCreateDoubleMatrix(n,k,mxCOMPLEX);
  if(plhs[0]==NULL)
    mexErrMsgTxt("Allocation of output array failed. Out of memory.");
  
  OUTr=mxGetPr(plhs[0]);
  OUTi=mxGetPi(plhs[0]);

  if((c=mxCalloc(m,sizeof(double)))==NULL)
    mexErrMsgTxt("Out of memory.");
  if((s=mxCalloc(m,sizeof(double)))==NULL)
    mexErrMsgTxt("Out of memory.");

  for(j=0;j<k;j++) {
    for(i=0;i<m;i++) {
      c[i]=cos(w[j]*(double)i); s[i]=sin(w[j]*(double)i);
    }
    for(i=0;i<n;i++)
      ftrans(m,&data[i*m],w[j],&OUTr[j*n+i],&OUTi[j*n+i],c,s);
  }
}
  void MapPainterAgg::DrawContourLabel(const Projection& projection,
                                       const MapParameter& parameter,
                                       const PathTextStyle& style,
                                       const std::string& text,
                                       size_t transStart, size_t transEnd)
  {
    double       fontSize=style.GetSize();
    double       r=style.GetTextColor().GetR();
    double       g=style.GetTextColor().GetG();
    double       b=style.GetTextColor().GetB();
    double       a=style.GetTextColor().GetA();
    std::wstring wideText(UTF8StringToWString(text));

    SetOutlineFont(projection,
                   parameter,
                   fontSize);

    //renderer_bin->color(agg::rgba(r,g,b,a));
    renderer_aa->color(agg::rgba(r,g,b,a));

    agg::path_storage path;

    double length=0;
    double xo=0;
    double yo=0;

    if (coordBuffer->buffer[transStart].GetX()<coordBuffer->buffer[transEnd].GetX()) {
      for (size_t j=transStart; j<=transEnd; j++) {
        if (j==transStart) {
          path.move_to(coordBuffer->buffer[j].GetX(),
                       coordBuffer->buffer[j].GetY());
        }
        else {
          path.line_to(coordBuffer->buffer[j].GetX(),
                       coordBuffer->buffer[j].GetY());
          length+=sqrt(pow(coordBuffer->buffer[j].GetX()-xo,2)+
                       pow(coordBuffer->buffer[j].GetY()-yo,2));
        }

        xo=coordBuffer->buffer[j].GetX();
        yo=coordBuffer->buffer[j].GetY();
      }
    }
    else {
      for (size_t j=0; j<=transEnd-transStart; j++) {
        size_t idx=transEnd-j;

        if (j==0) {
          path.move_to(coordBuffer->buffer[idx].GetX(),
                       coordBuffer->buffer[idx].GetY());
        }
        else {
          path.line_to(coordBuffer->buffer[idx].GetX(),
                       coordBuffer->buffer[idx].GetY());
          length+=sqrt(pow(coordBuffer->buffer[idx].GetX()-xo,2)+
                       pow(coordBuffer->buffer[idx].GetY()-yo,2));
        }

        xo=coordBuffer->buffer[idx].GetX();
        yo=coordBuffer->buffer[idx].GetY();
      }
    }

    double width;
    double height;

    GetTextDimension(wideText,width,height);

    if (width>length) {
      return;
    }

    /*
    typedef agg::conv_bspline<agg::path_storage> conv_bspline_type;

    conv_bspline_type bspline(path);
    bspline.interpolation_step(1.0 / path.total_vertices());*/

    agg::trans_single_path tcurve;
    tcurve.add_path(path); // bspline

    typedef agg::conv_segmentator<AggTextCurveConverter> conv_font_segm_type;
    typedef agg::conv_transform<conv_font_segm_type,
    agg::trans_single_path>                              conv_font_trans_type;

    conv_font_segm_type  fsegm(*convTextCurves);
    conv_font_trans_type ftrans(fsegm, tcurve);

    fsegm.approximation_scale(3.0);

    double x=(length-width)/2;
    double y=-height/2+fontEngine->ascender();

    for (size_t i=0; i<wideText.length(); i++) {
      const agg::glyph_cache* glyph = fontCacheManager->glyph(wideText[i]);

      if (glyph!=NULL) {
        fontCacheManager->add_kerning(&x, &y);
        fontCacheManager->init_embedded_adaptors(glyph,x,y);

        if (glyph->data_type==agg::glyph_data_outline) {
          rasterizer->reset();
          rasterizer->add_path(ftrans);
          renderer_aa->color(agg::rgba(r,g,b,a));
          agg::render_scanlines(*rasterizer,
                                *scanlineP8,
                                *renderer_aa);
        }

        // increment pen position
        x += glyph->advance_x;
        y += glyph->advance_y;
      }
    }
  }
    virtual void on_draw()
    {
        pixfmt pixf(rbuf_window());
        renderer_base rb(pixf);
        renderer_solid r(rb);
        rb.clear(agg::rgba(1, 1, 1));

        scanline_type sl;
        agg::rasterizer_scanline_aa<> ras;

        agg::simple_polygon_vertex_source path1(m_poly1.polygon(), 
                                                m_poly1.num_points(), 
                                                false, 
                                                false);

        agg::simple_polygon_vertex_source path2(m_poly2.polygon(), 
                                                m_poly2.num_points(), 
                                                false, 
                                                false);


        typedef agg::conv_bspline<agg::simple_polygon_vertex_source> conv_bspline_type;
        conv_bspline_type bspline1(path1);
        conv_bspline_type bspline2(path2);
        bspline1.interpolation_step(1.0 / m_num_points.value());
        bspline2.interpolation_step(1.0 / m_num_points.value());


        typedef agg::conv_curve<font_manager_type::path_adaptor_type>            conv_font_curve_type;
        typedef agg::conv_segmentator<conv_font_curve_type>                      conv_font_segm_type;
        typedef agg::conv_transform<conv_font_segm_type, agg::trans_double_path> conv_font_trans_type;

        agg::trans_double_path tcurve;
        conv_font_curve_type fcurves(m_fman.path_adaptor());
        conv_font_segm_type  fsegm(fcurves);
        conv_font_trans_type ftrans(fsegm, tcurve);

        tcurve.preserve_x_scale(m_preserve_x_scale.status());
        if(m_fixed_len.status()) tcurve.base_length(1140.0);
        tcurve.base_height(30.0);

        tcurve.add_paths(bspline1, bspline2);
        fsegm.approximation_scale(3.0);
        fcurves.approximation_scale(5.0);

        if(m_feng.load_font(full_file_name("timesi.ttf"), 0, agg::glyph_ren_outline))
        {
            double x = 0.0;
            double y = 3.0;
            const char* p = text;

            m_feng.hinting(false);
            m_feng.height(40);

            while(*p)
            {
                const agg::glyph_cache* glyph = m_fman.glyph(*p);
                if(glyph)
                {
                    if(x > tcurve.total_length1()) break;

                    m_fman.add_kerning(&x, &y);
                    m_fman.init_embedded_adaptors(glyph, x, y);

                    if(glyph->data_type == agg::glyph_data_outline)
                    {
                        ras.reset();
                        ras.add_path(ftrans);
                        r.color(agg::rgba8(0, 0, 0));
                        agg::render_scanlines(ras, sl, r);
                    }

                    // increment pen position
                    x += glyph->advance_x;
                    y += glyph->advance_y;
                }
                ++p;
            }
        }
        else
        {
            message("Please copy file timesi.ttf to the current directory\n"
                    "or download it from http://www.antigrain.com/timesi.zip");
        }



        typedef agg::conv_stroke<conv_bspline_type> conv_stroke_type;
        conv_stroke_type stroke1(bspline1);
        conv_stroke_type stroke2(bspline2);

        stroke1.width(2.0);
        stroke2.width(2.0);

        r.color(agg::rgba8(170, 50, 20, 100));
        ras.add_path(stroke1);
        agg::render_scanlines(ras, sl, r);

        ras.add_path(stroke2);
        agg::render_scanlines(ras, sl, r);


        //--------------------------
        // Render the "poly" tool and controls
        r.color(agg::rgba(0, 0.3, 0.5, 0.2));
        ras.add_path(m_poly1);
        agg::render_scanlines(ras, sl, r);

        ras.add_path(m_poly2);
        agg::render_scanlines(ras, sl, r);


        agg::render_ctrl(ras, sl, rb, m_fixed_len);
        agg::render_ctrl(ras, sl, rb, m_preserve_x_scale);
        agg::render_ctrl(ras, sl, rb, m_animate);
        agg::render_ctrl(ras, sl, rb, m_num_points);
        //--------------------------

    }
Esempio n. 4
0
MStatus HesperisCmd::attachSelected(const Vector3F & offsetV)
{
	MGlobal::displayInfo(MString(" attach to grow mesh ") + m_growMeshName);
	MSelectionList selList;
    MGlobal::getActiveSelectionList(selList);
    
	MItSelectionList iter( selList );
	
	MDagPath apath;		
	iter.getDagPath( apath );
		
	MObject otrans = apath.node();
	if(!otrans.hasFn(MFn::kTransform)) {
		MGlobal::displayWarning("must select a transform/group to attach to grow mesh");
		return MS::kFailure;
	}
	
	ASearchHelper searcher;
	MDagPath meshGrp;
	if(!searcher.dagByFullName(m_growMeshName.asChar(), meshGrp)) {
		MGlobal::displayWarning(MString("cannot find grow mesh by name ")+m_growMeshName);
		return MS::kFailure;
	}
	MObject ogrow = meshGrp.node();
	if(!ogrow.hasFn(MFn::kTransform)) {
		MGlobal::displayWarning("-gm must be a transform/group");
		return MS::kFailure;
	}
	
	MStatus stat;
    MDGModifier modif;
	MDagModifier dmodif;
	MObject hestranslate = modif.createNode("hesperisTranslateNode", &stat);
	modif.doIt();
    
    if(hestranslate.isNull()) {
		MGlobal::displayWarning("cannot create hes translate node");
		return MS::kFailure;
	}
	
	MFnDependencyNode fhest(hestranslate);
	MFnDependencyNode fgrow(ogrow);
	
	modif.connect(fgrow.findPlug("boundingBoxMinX", true), fhest.findPlug("bBoxMinX", true));
	modif.connect(fgrow.findPlug("boundingBoxMinY", true), fhest.findPlug("bBoxMinY", true));
	modif.connect(fgrow.findPlug("boundingBoxMinZ", true), fhest.findPlug("bBoxMinZ", true));
	modif.connect(fgrow.findPlug("boundingBoxMaxX", true), fhest.findPlug("bBoxMaxX", true));
	modif.connect(fgrow.findPlug("boundingBoxMaxY", true), fhest.findPlug("bBoxMaxY", true));
	modif.connect(fgrow.findPlug("boundingBoxMaxZ", true), fhest.findPlug("bBoxMaxZ", true));
	
	MPlug psrcwpmat = fgrow.findPlug("parentMatrix", true, &stat);
	if(!stat) MGlobal::displayInfo("cannot find plug worldParentMatrix");
	modif.connect(psrcwpmat, fhest.findPlug("inParentMatrix", true));
	modif.doIt();
	
    MFnDependencyNode ftrans(otrans);

	dmodif.connect(fhest.findPlug("outTranslateX", true), ftrans.findPlug("translateX", true));
	dmodif.connect(fhest.findPlug("outTranslateY", true), ftrans.findPlug("translateY", true));
	dmodif.connect(fhest.findPlug("outTranslateZ", true), ftrans.findPlug("translateZ", true));
	stat = dmodif.doIt();
	if(!stat) MGlobal::displayInfo(MString("cannot make some connections to ")+ftrans.name());
    
    fhest.findPlug("offsetX").setValue((double)-offsetV.x);
    fhest.findPlug("offsetY").setValue((double)-offsetV.y);
    fhest.findPlug("offsetZ").setValue((double)-offsetV.z);
    return MS::kSuccess;
}
Esempio n. 5
0
    virtual void on_draw()
    {
        pixfmt pixf(rbuf_window());
        renderer_base rb(pixf);
        renderer_solid r(rb);
        rb.clear(agg::rgba(1, 1, 1));

        scanline_type sl;
        agg::rasterizer_scanline_aa<> ras;

        m_poly.close(m_close.status());
        agg::simple_polygon_vertex_source path(m_poly.polygon(), 
                                               m_poly.num_points(), 
                                               false, 
                                               m_close.status());

        typedef agg::conv_bspline<agg::simple_polygon_vertex_source> conv_bspline_type;
        conv_bspline_type bspline(path);
        bspline.interpolation_step(1.0 / m_num_points.value());

        agg::trans_single_path tcurve;
        tcurve.add_path(bspline);
        tcurve.preserve_x_scale(m_preserve_x_scale.status());
        if(m_fixed_len.status()) tcurve.base_length(1120);

        typedef agg::conv_curve<font_manager_type::path_adaptor_type>             conv_font_curve_type;
        typedef agg::conv_segmentator<conv_font_curve_type>                      conv_font_segm_type;
        typedef agg::conv_transform<conv_font_segm_type, agg::trans_single_path> conv_font_trans_type;
        conv_font_curve_type fcurves(m_fman.path_adaptor());

        conv_font_segm_type  fsegm(fcurves);
        conv_font_trans_type ftrans(fsegm, tcurve);
        fsegm.approximation_scale(3.0);
        fcurves.approximation_scale(2.0);

        m_feng.height(40.0);
        //m_feng.italic(true);

        if(m_feng.create_font("Times New Roman", agg::glyph_ren_outline))
        {
            double x = 0.0;
            double y = 3.0;
            const char* p = text;

            while(*p)
            {
                const agg::glyph_cache* glyph = m_fman.glyph(*p);
                if(glyph)
                {
                    if(x > tcurve.total_length()) break;

                    m_fman.add_kerning(&x, &y);
                    m_fman.init_embedded_adaptors(glyph, x, y);

                    if(glyph->data_type == agg::glyph_data_outline)
                    {
                        ras.reset();
                        ras.add_path(ftrans);
                        r.color(agg::rgba8(0, 0, 0));
                        agg::render_scanlines(ras, sl, r);
                    }

                    // increment pen position
                    x += glyph->advance_x;
                    y += glyph->advance_y;
                }
                ++p;
            }

        }



        typedef agg::conv_stroke<conv_bspline_type> conv_stroke_type;
        conv_stroke_type stroke(bspline);

        stroke.width(2.0);

        r.color(agg::rgba8(170, 50, 20, 100));
        ras.add_path(stroke);
        agg::render_scanlines(ras, sl, r);

        //--------------------------
        // Render the "poly" tool and controls
        r.color(agg::rgba(0, 0.3, 0.5, 0.3));
        ras.add_path(m_poly);
        agg::render_scanlines(ras, sl, r);

        agg::render_ctrl(ras, sl, rb, m_close);
        agg::render_ctrl(ras, sl, rb, m_preserve_x_scale);
        agg::render_ctrl(ras, sl, rb, m_fixed_len);
        agg::render_ctrl(ras, sl, rb, m_animate);
        agg::render_ctrl(ras, sl, rb, m_num_points);
        //--------------------------

    }
Esempio n. 6
0
int
pchar(register tchar i)
{
	register int j;
	static int hx = 0;	/* records if have seen HX */
	static int xon = 0;	/* records if have seen XON */
	static int drawfcn = 0;	/* records if have seen DRAWFCN */

	if (hx) {
		hx = 0;
		j = absmot(i);
		if (isnmot(i)) {
			if (j > dip->blss)
				dip->blss = j;
		} else {
			if (j > dip->alss)
				dip->alss = j;
			ralss = dip->alss;
		}
		return 1;
	}
	if (ismot(i)) {
		pchar1(i); 
		return 1;
	}
	switch (j = cbits(i)) {
	case 0:
	case IMP:
	case RIGHT:
	case LEFT:
		if (xflag) {
			i = j = FILLER;	/* avoid kerning in output routine */
			goto dfl;
		}
		return 1;
	case HX:
		hx = 1;
		if (xflag) {
			i = j = FILLER;	/* avoid kerning in output routine */
			goto dfl;
		}
		return 1;
	case XON:
		xon = 1;
		goto dfl;
	case XOFF:
		xon = 0;
		goto dfl;
	case DRAWFCN:
		drawfcn = !drawfcn;
		goto dfl;
	case PRESC:
		if (dip == &d[0])
			j = eschar;	/* fall through */
	default:
	dfl:
#ifndef NROFF
		if (html) {
			if (!xflag || !isdi(i)) {
				setcbits(i, j >= NCHARS ? j :
				    tflg ? trnttab[j] : trtab[j]);
				if (xon == 0 && drawfcn == 0 && i < NCHARS)
					setcbits(i, ftrans(fbits(i),
					    cbits(i)));
			}
		} else
#endif
		if (!xflag || !isdi(i)) {
			setcbits(i, tflg ? trnttab[j] : trtab[j]);
			if (xon == 0 && drawfcn == 0)
				setcbits(i, ftrans(fbits(i), cbits(i)));
		}
	}
#ifdef	NROFF
	if (xon && xflag)
		return 1;
#endif	/* NROFF */
	pchar1(i);
	return 1;
}
Esempio n. 7
0
int 
sweep (
    int opcode,							/* The operation to perform. */
    char *file1,							/* The search/source file. */
    char *file2,							/* The scratch file.  (Required.) */
    int recsep,							/* Record seperator. */
    int fldsep,							/* Field seperator. */
    int maxlen,							/* Maximum length of record. */
    char *fmatch[],						/* Fields to match. */
    char *usrbuf,						/* User's copy of matching record. */
    char *usrmatch[],					/* Pointers to arguments. */
    int (*chop)(char *, int, char **),			/* Routine to seperate the fields. */
    int (*compare)(char **, char **, int)		/* Routine to compare records. */
)
{
	char	**arg = NULL,						/* Pointers to the fields. */
			*realrec = NULL,				/* A copy of what was actually read. */
			*hackrec = NULL;				/* A place to keep the fields. */

	int		cmpstat,					/* Comparison status. */
			retcode,					/* Return code. */
			action = 0,					/* Record of what we have done. */
			rectype,					/* FIXED or VARIED record size. */
			i, j;						/* Looping variable. */

	FILE	*fp1, *fp2 = NULL;					/* Pointers to file1 and file2. */

	TR("Sweep: opcode=%d file1=(%s) file2=(%s)\n", opcode, file1, file2);
	TR(".. recsep=(%c) fldsep=(%c) maxlen=%d ", recsep, fldsep, maxlen);
	TR("usrbuf=%d usrmatch=%d chop=%d\n", usrbuf, usrmatch, chop);
	TR(".. usrbuf=(%s) compare=%d\n", usrbuf, compare, EMPTY);
#ifdef TRACE
	TR(".. fmatch ..\n", EMPTY, EMPTY, EMPTY);
	for (i = 0; fmatch[i] != EMPTY; i++)
		TR("%d (%s)\n", i, fmatch[i], EMPTY);
#endif

	if ((fp1 = fopen (file1, READ)) == NULL) {
		if (opcode == PUTNOW || (opcode & INSERT) > 0) {
			if ((fp1 = fopen (file1, APP)) == NULL)
				return (NOSOURCE);
			if (fclose (fp1) == ERROR)
				return (NOSOURCE);
			if ((fp1 = fopen (file1, READ)) == NULL)
				return (NOSOURCE);
			TR("Sweep: made a blank file1\n", EMPTY, EMPTY, EMPTY);
			opcode = PUTNOW;			/* Since buffers are unneeded. */
			}
		else
			return (NOSOURCE);
		}

	if ((opcode & VERIFY) == 0) {
		if ((fp2 = fopen (file2, READ)) != NULL) {
			if (fclose (fp2) == ERROR || unlink (file2) == ERROR) {
				if (fclose (fp1) == ERROR)
					return (RECURSE + LIVEDEST);
				return (LIVEDEST);
				}
			}
		if ((fp2 = fopen (file2, APP)) == NULL) {
			if (fclose (fp1) == ERROR)
				return (RECURSE + NODEST);
			return (NODEST);
			}
		action += OFILE2;				/* Flag file2 as open. */
		}

	action += OFILE1;					/* Flag file1 as open. */

	TR("Sweep: file1%s open\n", ((action & OFILE2) > 0) ? " and file2" : "",
	  EMPTY, EMPTY);

	if (opcode == PUTNOW)
		goto begin;						/* Because we need no allocations. */

	/* At this point, we begin allocating the three areas that  this routine
	 * needs.  realrec will contain a copy of what was really read.  hackrec
	 * will provide space to store its individual fields.  arg will  provide
	 * space for the pointers the those fields.  The general scheme used for
	 * allocation and use of these areas is as follows:
	 *
	 *			Given:	usrbuf		--			usrbuf		--
	 *					usrmatch	usrmatch	--			--
	 *			---------------------------------------------------
	 *			arg		usrmatch/1	usrmatch/2	ALLOC3		ALLOC3
	 *			---------------------------------------------------
	 *			realrec	ALLOC1		ALLOC1		usrbuf/3	ALLOC1
	 *			---------------------------------------------------
	 *			hackrec	usrbuf/4	ALLOC2		ALLOC2		ALLOC2
	 *			---------------------------------------------------
	 *
	 * Note 1: On DELETE this  array will hold pointers to the actual fields
	 *  of the DELETED record.  On INSERT and REPLACE, it will hold pointers
	 *  into usrbuf which will be MEANINGLESS.  On VERIFY, it will also hold
	 *	pointers, but they are to the matched record.  On PUTNOW, this array
	 *	is unaffected.
	 *
	 * Note 2: On all operations, the pointers in this array will be useless
	 *	upon return.
	 *
	 * Note 3: On DELETE and VERIFY, this array will hold the actual  record
	 *	deleted or matched.  On INSERT or REPLACE, this record will hold the
	 *	actual  record  inserted  or  replaced (and is not used internally).
	 *	PUTNOW has no effect.
	 *
	 * Note 4: On DELETE and VERIFY, this array will hold the actual  record
	 *	deleted or matched.  On INSERT and REPLACE, this array will hold the
	 *	actual record inserted or replaced (in which case, the specification
	 *	of usrmatch will put only junk into that array, as in note 1).  This
	 *	area is not used internally for an INSERT or REPLACE.  This array is
	 *	not affected by PUTNOW.
	 */

	if (maxlen <= 0) {
		retcode = BADSIZE;
		goto bye;
		}

	retcode = NOSPACE;					/* All errors will be for this. */

	if (usrbuf == EMPTY) {				/* We must allocate a buffer. */
		TR("Sweep: no usrbuf\n", EMPTY, EMPTY, EMPTY);
		if ((realrec = (char *) malloc ((unsigned) maxlen)) == EMPTY)
			goto bye;
		action += ALLOC1;				/* A buffer was allocated. */
		TR("Sweep: allocated (1) realrec=%d\n", realrec, EMPTY, EMPTY);
		if ((hackrec = (char *) malloc ((unsigned) maxlen)) == EMPTY)
			goto bye;
		action += ALLOC2;
		TR("Sweep: allocated (2) hackrec=%d\n", hackrec, EMPTY, EMPTY);
		if (usrmatch == (char**) NULL) { /* User provided no field pointers. */
			j = (maxlen / 2 + 1) * sizeof (char*);
			if ((arg = (char**) malloc ((unsigned) j)) == (char**) NULL)
				goto bye;
			action += ALLOC3;			/* Pointer space was allocated. */
			TR("Sweep: allocated (3) arg=%d\n", arg, EMPTY, EMPTY);
			}
		else
			arg = usrmatch;
		}
	
	else {								/* A usrbuf area was specified */
		TR("Sweep: usrbuf given\n", EMPTY, EMPTY, EMPTY);
		if (usrmatch == (char**) NULL) {
			TR("Sweep: no usrmatch\n", EMPTY, EMPTY, EMPTY);
			if ((opcode & REPLACE) > 0 || (opcode & INSERT) > 0) {
				/* Alas, we cannot use the area. */
				if ((realrec = (char *) malloc ((unsigned) maxlen)) == EMPTY)
					goto bye;
				action += ALLOC1;
				TR("Sweep: allocated (4) realrec=%d\n", realrec, EMPTY, EMPTY);
				}
			else
				realrec = usrbuf;
			if ((hackrec = (char *) malloc ((unsigned) maxlen)) == EMPTY)
				goto bye;
			action += ALLOC2;
			TR("Sweep: allocated (5) hackrec=%d\n", hackrec, EMPTY, EMPTY);
			j = (maxlen / 2 + 1) * sizeof (char*);
			if ((arg = (char**) malloc ((unsigned) j)) == (char**) NULL)
				goto bye;
			action += ALLOC3;
			TR("Sweep: allocated (6) arg=%d\n", arg, EMPTY, EMPTY);
			}
		else {							/* We have usrbuf and usrmatch. */
			if ((opcode & REPLACE) > 0 || (opcode & INSERT) > 0) {
				if ((hackrec = (char *) malloc ((unsigned) maxlen)) == EMPTY)
					goto bye;
				action += ALLOC2;
				TR("Sweep: allocated (7) hackrec=%d\n", hackrec, EMPTY, EMPTY);
				}
			else
				hackrec = usrbuf;
			arg = usrmatch;
			if ((realrec = (char *) malloc ((unsigned) maxlen)) == EMPTY)
				goto bye;
			action += ALLOC1;
			TR("Sweep: allocated (8) realrec=%d\n", realrec, EMPTY, EMPTY);
			}
		}

begin:

	if (opcode == PUTNOW) {				/* Insert a message at beginning. */
		if ((action & OFILE2) > 0) {
			fprintf (fp2, "%s%c", usrbuf, recsep);
			retcode = DONE;
			goto bye;
			}
		else {
			retcode = NOTPUT;
			goto bye;
			}
		}

	if (recsep == 0)
		rectype = FIXED;
	else
		rectype = VARIED;

	while ((i = getrec (fp1, realrec, recsep, rectype, maxlen)) == DONE) {

		/* Copy the buffer */
		strncpy (hackrec, realrec, (unsigned) maxlen);

		/* Seperate the command into arguments. */
		if (chop == (int (*)(char *, int, char **)) NULL)
			i = argchop (hackrec, fldsep, arg);
		else
			i = (*chop) (hackrec, fldsep, arg);
		if (i != DONE)
			break;						/* Something funny in record. */

		/* Now, determine the alphabetic status of this record. */
		if (compare == (int (*)(char **, char **, int)) NULL)
			cmpstat = rec_cmp (arg, fmatch, recsep);
		else
			cmpstat = (*compare) (arg, fmatch, recsep);

		/* Now, decide to continue or not. */
		if ((opcode & SEQUENTIAL) == 0 && cmpstat != SAME)
			continue;
			/* We continue if the search is not sequential and the record
			 * did not match. */

		if (cmpstat == SAME) {
			TR("Sweep: Enter SAME section\n", EMPTY, EMPTY, EMPTY);
			if ((opcode & INSERT) > 0)
				retcode = NOTNEW;
			else if ((opcode & VERIFY) > 0)
				retcode = FOUND;
			else {
				if ((opcode & REPLACE) > 0 && usrbuf != EMPTY)
					fprintf (fp2, "%s%c", usrbuf, recsep);
					/* And if this was a DELETE, nothing is printed. */
				retcode = DONE;
				}
			goto bye;
			}

		else if (cmpstat == BEFORE) {
			TR("Sweep: Enter BEFORE section\n", EMPTY, EMPTY, EMPTY);
			/* Put the record into the "scratch" file. */
			if ((opcode & VERIFY) == 0)
				fprintf (fp2, "%s%c", realrec, recsep);
			}

		else {							/* cmpstat == AFTER. */
			TR("Sweep: enter AFTER section\n", EMPTY, EMPTY, EMPTY);
			/* Match goes (or should have come) before this one. */
			if (opcode == SEQINSERT) {
				if (usrbuf != EMPTY)
					fprintf (fp2, "%s%c", usrbuf, recsep);
				/* Put in the INSERTed one, then replace the old one. */
				fprintf (fp2, "%s%c", realrec, recsep);
				retcode = DONE;
				}
			else
				/* We never get here on non-sequential searches. */
				retcode = NOTFOUND;
			goto bye;
			}
		}								/* End of while loop. */
	TR("Sweep: end of record loop\n", EMPTY, EMPTY, EMPTY);

	if (i != FILE1EOF) {
		TR("Sweep: funny death\n", EMPTY, EMPTY, EMPTY);
		retcode = i;					/* So user knows about bad data. */
		goto bye;
		}

	if (fclose (fp1) == ERROR)
		retcode = NOCLOSE;
	action -= OFILE1;

	if (((opcode & VERIFY) | (opcode & REPLACE) | (opcode & DELETE)) > 0) {
		TR("Sweep: not there\n", EMPTY, EMPTY, EMPTY);
		if ((opcode & VERIFY) == 0) {
			if (fclose (fp2) == ERROR)
				retcode = RESETERR;
			action -= OFILE2;
			if (unlink (file2) == ERROR) {
				retcode = RESETERR;		/* Should never happen? */
				goto bye;
				}
			}
		retcode = NOTFOUND;
		goto bye;
		}

	if ((opcode & INSERT) > 0) {
		TR("Sweep: insert tail record\n", EMPTY, EMPTY, EMPTY);
		if (usrbuf != EMPTY)
			fprintf (fp2, "%s%c", usrbuf, recsep);
		retcode = DONE;
		}
	else
		retcode = ABEND;				/* Should never happen? */

bye:

	TR("Sweep: closing retcode=%d action=%d\n", retcode, action, EMPTY);
	if (retcode == DONE) {				/* Successful on a file update. */
		if ((action & OFILE1) > 0 && (action & OFILE2) > 0)
			retcode = copyrest (fp1, fp2, EMPTY, BUFSIZE);
		}

	if ((action & OFILE1) > 0) {
		if (fclose (fp1) == ERROR)
			retcode = NOCLOSE;
		TR("Sweep: file1 closed\n", EMPTY, EMPTY, EMPTY);
		}
	if ((action & OFILE2) > 0) {
		if (fclose (fp2) == ERROR)
			retcode = NOCLOSE;
		TR("Sweep: file2 closed\n", EMPTY, EMPTY, EMPTY);
		}

	/* With the files closed, we now replace file1 with file2 (if needed). */
	if (retcode == DONE) {
		if ((retcode = ftrans (MOVE, file2, file1, EMPTY, BUFSIZE)) != DONE)
			retcode += RECURSE;
		TR("Sweep: final transfer\n", EMPTY, EMPTY, EMPTY);
		}
	if ((action & ALLOC1) > 0) {
		TR("Sweep: free realrec\n", EMPTY, EMPTY, EMPTY);
		free (realrec);
		}
	if ((action & ALLOC2) > 0) {
		TR("Sweep: free hackrec\n", EMPTY, EMPTY, EMPTY);
		free (hackrec);
		}
	if ((action & ALLOC3) > 0) {
		TR("Sweep: free arg\n", EMPTY, EMPTY, EMPTY);
		free ((char*) arg);
		}
	return (retcode);
}