void TestMicrosoftWordChecker::TestGetVersionString()
{
	MicrosoftWordChecker offc(1,1);

	CStdString sOfficeVersion = offc.GetOfficeVersionString();

	assertMessage(sOfficeVersion != _T(""), _T("shouldn't get a null version string - I can't believe you dont have office on a dev machine"));
	assertMessage(sOfficeVersion[0] == _T('1') || sOfficeVersion[0] == _T('9'), _T("expected to find office 2k or higher on dev machine"));
}
// ######################################################################
void CenterSurroundHistogramSegmenter::computeCStemplates()
{
  itsCStemplates.clear();
  itsCSpoints.clear();

  int width  = DEFAULT_WIDTH;
  int height = DEFAULT_HEIGHT;
  int mindim = width < height ? width : height;

  // compute for each scale: .1, .2, .3 of minimum of dimension
  // max was .7 NOTE: .4 is probably better
  std::vector<float> scales;
  for(float i = 0.1F; i <= 0.3F; i+=0.1F) scales.push_back(i);

  // compute ratio: .5, .75, 1.0, 1.5, 2.0
  std::vector<float> ratios;
  //for(float i = 0.5F; i <= 2.0F; i+=0.25F) ratios.push_back(i);
  ratios.push_back(0.5F);
  ratios.push_back(0.75F);
  ratios.push_back(1.0F);
  ratios.push_back(1.5F);
  ratios.push_back(2.0F);

  // cos and sin of 45 degree 
  // for the diagonal center surround shapes
  float cang = cos(M_PI/4.0F);
  float sang = sin(M_PI/4.0F);

  // for each scale and ratios
  for(uint i = 0; i < scales.size(); i++)
    {
      int h2 = int(scales[i]*mindim)/GRID_SIZE/2;
      LDEBUG("h2[%d]: %f --> %d ", i, scales[i]*mindim, h2);

      int prevw2 = -1;
      for(uint j = 0; j < ratios.size(); j++)
        {
          // get width, height, dimensions 
          // of the center and surround rectangles
          int w2 = int(h2*ratios[j]);
          if(w2 == prevw2) continue;  prevw2 = w2;
          int w   = 2*w2 + 1;        int h   = 2*h2 + 1;
          int sw2 = 2*w2;            int sh2 = 2*h2;
          int sw  = 2*sw2 + 1;       int sh  = 2*sh2 + 1;
          LDEBUG("w2[%d]: %f --> %d",j, h2*ratios[j], w2);
          
          // compute and store the offsets as well
          int ow = w2/2; if(ow == 0) ow = 1;
          int oh = h2/2; if(oh == 0) oh = 1;
          
          // here the off sets are spaced a quarter
          // the length of each dimension
          std::vector<int> offw; 
          offw.push_back(0); offw.push_back( ow); offw.push_back(-ow);
          if(w2 != 1){ offw.push_back( w2); offw.push_back(-w2); } 

          std::vector<int> offh; 
          offh.push_back(0); offh.push_back( oh); offh.push_back(-oh);
          if(h2 != 1){ offh.push_back( h2); offh.push_back(-h2); } 

          Dims cd(w,h); Dims sd(sw,sh);
          Point2D<int> offc( -w2,  -h2);
          Point2D<int> offs(-sw2, -sh2);
          LDEBUG("Dims: c:%d %d s:%d %d: off: %d %d", 
                 w, h, sw, sh, -w2, -h2);

          for(uint ii = 0; ii < offw.size(); ii++)
            for(uint jj = 0; jj < offh.size(); jj++)
              {
                Point2D<int> pt(offw[ii], offh[jj]);

                Rectangle rc(pt+offc, cd);
                Rectangle rs(pt+offs, sd);
                itsCStemplates.push_back
                  (std::pair<Rectangle,Rectangle>(rc,rs));
              }

          // now we rotate the rectangle 45 degrees 
          // and add it to the csPoints
          int sdiag = int(sqrt(sw*sw + sh*sh)+ 0.5F) + 1;
          Point2D<int> dpt(sdiag,sdiag);

          // here we rotate the image representation of the template
          Image<float> tcimg(2*sdiag,2*sdiag,ZEROS);
          drawFilledRect(tcimg, Rectangle(dpt+offc, cd), 1.0F);
          Image<float> rtcimg = rotate(tcimg, sdiag, sdiag, M_PI/4.0F);

          Image<float> tsimg(2*sdiag,2*sdiag,ZEROS);
          drawFilledRect(tsimg, Rectangle(dpt+offs, sd), 1.0F);
          Image<float> rtsimg = rotate(tsimg, sdiag, sdiag, M_PI/4.0F);

          // only select rotated point values 
          // that are above 0.5F
          std::vector<Point2D<int> > tempC;
          for(int jj = 0; jj < rtcimg.getHeight(); jj++)
            for(int ii = 0; ii < rtcimg.getWidth(); ii++)
              {
                float val = rtcimg.getVal(ii,jj);
                if(val > 0.5F) 
                  tempC.push_back(Point2D<int>(ii,jj)-dpt);
              }

          std::vector<Point2D<int> > tempS;
          for(int jj = 0; jj < rtsimg.getHeight(); jj++)
            for(int ii = 0; ii < rtsimg.getWidth(); ii++)
              {
                float cval = rtcimg.getVal(ii,jj);
                float sval = rtsimg.getVal(ii,jj);
                if(cval < 0.5F && sval > 0.5F) 
                  tempS.push_back(Point2D<int>(ii,jj)-dpt);
              }
          
          // rotate the offset points as well
          for(uint ii = 0; ii < offw.size(); ii++)
            for(uint jj = 0; jj < offh.size(); jj++)
              {
                float rx = round( offw[ii]*cang - offh[jj]*sang);
                float ry = round( offw[ii]*sang + offh[jj]*cang);
                Point2D<int> pt(int(rx+0.0F), int(ry+0.0F));

                LDEBUG("rotated (%3d %3d) --> %5.3f %5.3f --> pt: %3d %3d", 
                       offw[ii], offh[jj], rx, ry, pt.i, pt.j);

                std::vector<Point2D<int> > rtempC;
                for(uint cc = 0; cc < tempC.size(); cc++)
                  rtempC.push_back(tempC[cc]+pt);

                std::vector<Point2D<int> > rtempS;
                for(uint ss = 0; ss < tempS.size(); ss++)
                  rtempS.push_back(tempS[ss]+pt);

                itsCSpoints.push_back
                  (std::pair<std::vector<Point2D<int> >,
                   std::vector<Point2D<int> > >(rtempC,rtempS));
              }

          // Image<float> disp(4*sdiag*GRID_SIZE, 2*sdiag*GRID_SIZE, ZEROS);
          // if(itsWin.is_invalid())
          //   itsWin.reset(new XWinManaged(disp.getDims(), 0, 0, "CSHse"));
          // else itsWin->setDims(disp.getDims());
          // inplacePaste(disp, zoomXY(tcimg,GRID_SIZE), Point2D<int>(0,0));
          // inplacePaste(disp, zoomXY(rtcimg,GRID_SIZE), 
          //              Point2D<int>(2*sdiag*GRID_SIZE,0));
          // itsWin->drawImage(disp,0,0);
          // Raster::waitForKey();          

          // inplacePaste(disp, zoomXY(tsimg,GRID_SIZE), Point2D<int>(0,0));
          // inplacePaste(disp, zoomXY(rtsimg,GRID_SIZE), 
          //              Point2D<int>(2*sdiag*GRID_SIZE,0));
          // itsWin->drawImage(disp,0,0);
          // Raster::waitForKey(); 
        }
    }

  LDEBUG("done with templates: %" ZU , itsCStemplates.size());
  LDEBUG("done with points:    %" ZU , itsCSpoints.size());
}