<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    Glyph3D.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Toolkit. No part of this file
or its contents may be copied, reproduced or altered in any way
without the express written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
#include "Glyph3D.hh"
#include "Trans.hh"
#include "FVectors.hh"
#include "FNormals.hh"
#include "vtkMath.hh"

// Description
// Construct object with scaling on, scaling mode is by scalar value,
// scale factor = 1.0, the range is (0,1), orient geometry is on, and
// orientation is by vector.
vtkGlyph3D::vtkGlyph3D()
{
  this->Source = NULL;
  this->Scaling = 1;
  this->ScaleMode = SCALE_BY_SCALAR;
  this->ScaleFactor = 1.0;
  this->Range[0] = 0.0;
  this->Range[1] = 1.0;
  this->Orient = 1;
  this->VectorMode = USE_VECTOR;
}

vtkGlyph3D::~vtkGlyph3D()
{
}

void vtkGlyph3D::Execute()
{
  vtkPointData *pd;
  vtkScalars *inScalars;
  vtkVectors *inVectors;
  vtkNormals *inNormals, *sourceNormals;
  int numPts, numSourcePts, numSourceCells;
  int inPtId, i;
  vtkPoints *sourcePts;
  vtkCellArray *sourceCells;
  vtkFloatPoints *newPts;
  vtkFloatScalars *newScalars=NULL;
  vtkFloatVectors *newVectors=NULL;
  vtkFloatNormals *newNormals=NULL;
  float *x, *v, vNew[3];
  vtkTransform trans;
  vtkCell *cell;
  vtkIdList *cellPts;
  int npts, pts[MAX_CELL_SIZE];
  int orient, scaleSource, ptIncr, cellId;
  float scale, den;
  vtkMath math;

  vtkDebugMacro(<<"Generating glyphs");
  this->Initialize();

  pd = this->Input->GetPointData();
  inScalars = pd->GetScalars();
  inVectors = pd->GetVectors();
  inNormals = pd->GetNormals();

  numPts = this->Input->GetNumberOfPoints();
//
// Allocate storage for output PolyData
//
  sourcePts = this->Source->GetPoints();
  numSourcePts = sourcePts->GetNumberOfPoints();
  numSourceCells = this->Source->GetNumberOfCells();
  sourceNormals = this->Source->GetPointData()->GetNormals();

  newPts = new vtkFloatPoints(numPts*numSourcePts);
  if (inScalars != NULL)
    newScalars = new vtkFloatScalars(numPts*numSourcePts);
  if (inVectors != NULL || inNormals != NULL )
    newVectors = new vtkFloatVectors(numPts*numSourcePts);
  if (sourceNormals != NULL)
    newNormals = new vtkFloatNormals(numPts*numSourcePts);

  // Setting up for calls to PolyData::InsertNextCell()
  if ( (sourceCells=this->Source->GetVerts())->GetNumberOfCells() > 0 )
    {
    this->SetVerts(new vtkCellArray(numPts*sourceCells->GetSize()));
    }
  if ( (sourceCells=this->Source->GetLines())->GetNumberOfCells() > 0 )
    {
    this->SetLines(new vtkCellArray(numPts*sourceCells->GetSize()));
    }
  if ( (sourceCells=this->Source->GetPolys())->GetNumberOfCells() > 0 )
    {
    this->SetPolys(new vtkCellArray(numPts*sourceCells->GetSize()));
    }
  if ( (sourceCells=this->Source->GetStrips())->GetNumberOfCells() > 0 )
    {
    this->SetStrips(new vtkCellArray(numPts*sourceCells->GetSize()));
    }
//
// Copy (input scalars) to (output scalars) and either (input vectors or
// normals) to (output vectors). All other point attributes are copied
// from Source.
//
  pd = this->Source->GetPointData();
  this->PointData.CopyScalarsOff();
  this->PointData.CopyVectorsOff();
  this->PointData.CopyNormalsOff();
  this->PointData.CopyAllocate(pd,numPts*numSourcePts);
//
// First copy all topology (transformation independent)
//
  for (inPtId=0; inPtId < numPts; inPtId++)
    {
    ptIncr = inPtId * numSourcePts;
    for (cellId=0; cellId < numSourceCells; cellId++)
      {
      cell = this->Source->GetCell(cellId);
      cellPts = cell->GetPointIds();
      npts = cellPts->GetNumberOfIds();
      for (i=0; i < npts; i++) pts[i] = cellPts->GetId(i) + ptIncr;
      this->InsertNextCell(cell->GetCellType(),npts,pts);
      }
    }
//
// Traverse all Input points, transforming Source points and copying
// point attributes.
//
  if ( (this->VectorMode == USE_VECTOR && inVectors != NULL) ||
  (this->VectorMode == USE_NORMAL && inNormals != NULL) )
    orient = 1;
  else
    orient = 0;

  if ( this->Scaling &&
  ((this->ScaleMode == SCALE_BY_SCALAR && inScalars != NULL) ||
  (this->ScaleMode == SCALE_BY_VECTOR && (inVectors || inNormals))) )
    scaleSource = 1;
  else
    scaleSource = 0;

  for (inPtId=0; inPtId < numPts; inPtId++)
    {
    ptIncr = inPtId * numSourcePts;

    trans.Identity();

    // translate Source to Input point
    x = this->Input->GetPoint(inPtId);
    trans.Translate(x[0], x[1], x[2]);

    if ( orient )
      {
      if ( this->VectorMode == USE_NORMAL )
        v = inNormals->GetNormal(inPtId);
      else
        v = inVectors->GetVector(inPtId);
      scale = math.Norm(v);

      // Copy Input vector
      for (i=0; i < numSourcePts; i++)
        newVectors->InsertVector(ptIncr+i,v);

      if ( this->Orient )
        {
        vNew[0] = (v[0]+scale) / 2.0;
        vNew[1] = v[1] / 2.0;
        vNew[2] = v[2] / 2.0;
        trans.RotateWXYZ(180.0,vNew[0],vNew[1],vNew[2]);
        }
      }

    // determine scale factor from scalars if appropriate
    if ( inScalars != NULL )
      {
      // Copy Input scalar
      for (i=0; i < numSourcePts; i++)
        newScalars->InsertScalar(ptIncr+i,scale);

      if ( this->ScaleMode == SCALE_BY_SCALAR )
        {
        if ( (den = this->Range[1] - this->Range[0]) == 0.0 ) den = 1.0;
        scale = inScalars->GetScalar(inPtId);

        scale = (scale < this->Range[0] ? this->Range[0] :
                 (scale > this->Range[1] ? this->Range[1] : scale));
        scale = (scale - this->Range[0]) / den;

        }
      }

    // scale data if appropriate
    if ( scaleSource )
      {
      scale *= this->ScaleFactor;
      if ( scale == 0.0 ) scale = 1.0e-10;
      trans.Scale(scale,scale,scale);
      }

    // multiply points and normals by resulting matrix
    trans.MultiplyPoints(sourcePts,newPts);
    if ( sourceNormals != NULL )
      trans.MultiplyNormals(sourceNormals,newNormals);

    // Copy point data from source
    for (i=0; i < numSourcePts; i++)
      this->PointData.CopyData(pd,i,ptIncr+i);
    }
//
// Update ourselves
//
  this->SetPoints(newPts);
  this->PointData.SetScalars(newScalars);
  this->PointData.SetVectors(newVectors);
  this->PointData.SetNormals(newNormals);
  this->Squeeze();
}

// Description:
// Override update method because execution can branch two ways (Input
// and Source)
void vtkGlyph3D::Update()
{
  // make sure input is available
  if ( this->Input == NULL || this->Source == NULL )
    {
    vtkErrorMacro(<< "No input!");
    return;
    }

  // prevent chasing our tail
  if (this->Updating) return;

  this->Updating = 1;
  this->Input->Update();
  this->Source->Update();
  this->Updating = 0;

  if (this->Input->GetMTime() > this->GetMTime() ||
  this->Source->GetMTime() > this->GetMTime() ||
  this->GetMTime() > this->ExecuteTime || this->GetDataReleased() )
    {
    if ( this->StartMethod ) (*this->StartMethod)(this->StartMethodArg);
    this->Execute();
    this->ExecuteTime.Modified();
    this->SetDataReleased(0);
    if ( this->EndMethod ) (*this->EndMethod)(this->EndMethodArg);
    }

  if ( this->Input->ShouldIReleaseData() ) this->Input->ReleaseData();
  if ( this->Source->ShouldIReleaseData() ) this->Source->ReleaseData();
}

void vtkGlyph3D::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToPolyFilter::PrintSelf(os,indent);

  os << indent << "Source: " << this->Source << "\n";
  os << indent << "Scaling: " << (this->Scaling ? "On\n" : "Off\n");
  os << indent << "Scale Mode: " << (this->ScaleMode == SCALE_BY_SCALAR ? "Scale by scalar\n" : "Scale by vector\n");
  os << indent << "Scale Factor: " << this->ScaleFactor << "\n";
  os << indent << "Range: (" << this->Range[0] << ", " << this->Range[1] << ")\n";
  os << indent << "Orient: " << (this->Orient ? "On\n" : "Off\n");

  os << indent << "Orient Mode: " << (this->VectorMode == USE_VECTOR ? "Orient by vector\n" : "Orient by normal\n");
}

<commit_msg>fixed scalar copying bug<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    Glyph3D.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Toolkit. No part of this file
or its contents may be copied, reproduced or altered in any way
without the express written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
#include "Glyph3D.hh"
#include "Trans.hh"
#include "FVectors.hh"
#include "FNormals.hh"
#include "vtkMath.hh"

// Description
// Construct object with scaling on, scaling mode is by scalar value,
// scale factor = 1.0, the range is (0,1), orient geometry is on, and
// orientation is by vector.
vtkGlyph3D::vtkGlyph3D()
{
  this->Source = NULL;
  this->Scaling = 1;
  this->ScaleMode = SCALE_BY_SCALAR;
  this->ScaleFactor = 1.0;
  this->Range[0] = 0.0;
  this->Range[1] = 1.0;
  this->Orient = 1;
  this->VectorMode = USE_VECTOR;
}

vtkGlyph3D::~vtkGlyph3D()
{
}

void vtkGlyph3D::Execute()
{
  vtkPointData *pd;
  vtkScalars *inScalars;
  vtkVectors *inVectors;
  vtkNormals *inNormals, *sourceNormals;
  int numPts, numSourcePts, numSourceCells;
  int inPtId, i;
  vtkPoints *sourcePts;
  vtkCellArray *sourceCells;
  vtkFloatPoints *newPts;
  vtkFloatScalars *newScalars=NULL;
  vtkFloatVectors *newVectors=NULL;
  vtkFloatNormals *newNormals=NULL;
  float *x, *v, vNew[3];
  vtkTransform trans;
  vtkCell *cell;
  vtkIdList *cellPts;
  int npts, pts[MAX_CELL_SIZE];
  int orient, scaleSource, ptIncr, cellId;
  float scale, den;
  vtkMath math;

  vtkDebugMacro(<<"Generating glyphs");
  this->Initialize();

  pd = this->Input->GetPointData();
  inScalars = pd->GetScalars();
  inVectors = pd->GetVectors();
  inNormals = pd->GetNormals();

  numPts = this->Input->GetNumberOfPoints();
//
// Allocate storage for output PolyData
//
  sourcePts = this->Source->GetPoints();
  numSourcePts = sourcePts->GetNumberOfPoints();
  numSourceCells = this->Source->GetNumberOfCells();
  sourceNormals = this->Source->GetPointData()->GetNormals();

  newPts = new vtkFloatPoints(numPts*numSourcePts);
  if (inScalars != NULL)
    newScalars = new vtkFloatScalars(numPts*numSourcePts);
  if (inVectors != NULL || inNormals != NULL )
    newVectors = new vtkFloatVectors(numPts*numSourcePts);
  if (sourceNormals != NULL)
    newNormals = new vtkFloatNormals(numPts*numSourcePts);

  // Setting up for calls to PolyData::InsertNextCell()
  if ( (sourceCells=this->Source->GetVerts())->GetNumberOfCells() > 0 )
    {
    this->SetVerts(new vtkCellArray(numPts*sourceCells->GetSize()));
    }
  if ( (sourceCells=this->Source->GetLines())->GetNumberOfCells() > 0 )
    {
    this->SetLines(new vtkCellArray(numPts*sourceCells->GetSize()));
    }
  if ( (sourceCells=this->Source->GetPolys())->GetNumberOfCells() > 0 )
    {
    this->SetPolys(new vtkCellArray(numPts*sourceCells->GetSize()));
    }
  if ( (sourceCells=this->Source->GetStrips())->GetNumberOfCells() > 0 )
    {
    this->SetStrips(new vtkCellArray(numPts*sourceCells->GetSize()));
    }
//
// Copy (input scalars) to (output scalars) and either (input vectors or
// normals) to (output vectors). All other point attributes are copied
// from Source.
//
  pd = this->Source->GetPointData();
  this->PointData.CopyScalarsOff();
  this->PointData.CopyVectorsOff();
  this->PointData.CopyNormalsOff();
  this->PointData.CopyAllocate(pd,numPts*numSourcePts);
//
// First copy all topology (transformation independent)
//
  for (inPtId=0; inPtId < numPts; inPtId++)
    {
    ptIncr = inPtId * numSourcePts;
    for (cellId=0; cellId < numSourceCells; cellId++)
      {
      cell = this->Source->GetCell(cellId);
      cellPts = cell->GetPointIds();
      npts = cellPts->GetNumberOfIds();
      for (i=0; i < npts; i++) pts[i] = cellPts->GetId(i) + ptIncr;
      this->InsertNextCell(cell->GetCellType(),npts,pts);
      }
    }
//
// Traverse all Input points, transforming Source points and copying
// point attributes.
//
  if ( (this->VectorMode == USE_VECTOR && inVectors != NULL) ||
  (this->VectorMode == USE_NORMAL && inNormals != NULL) )
    orient = 1;
  else
    orient = 0;

  if ( this->Scaling &&
  ((this->ScaleMode == SCALE_BY_SCALAR && inScalars != NULL) ||
  (this->ScaleMode == SCALE_BY_VECTOR && (inVectors || inNormals))) )
    scaleSource = 1;
  else
    scaleSource = 0;

  for (inPtId=0; inPtId < numPts; inPtId++)
    {
    ptIncr = inPtId * numSourcePts;

    trans.Identity();

    // translate Source to Input point
    x = this->Input->GetPoint(inPtId);
    trans.Translate(x[0], x[1], x[2]);

    if ( orient )
      {
      if ( this->VectorMode == USE_NORMAL )
        v = inNormals->GetNormal(inPtId);
      else
        v = inVectors->GetVector(inPtId);
      scale = math.Norm(v);

      // Copy Input vector
      for (i=0; i < numSourcePts; i++)
        newVectors->InsertVector(ptIncr+i,v);

      if ( this->Orient )
        {
        vNew[0] = (v[0]+scale) / 2.0;
        vNew[1] = v[1] / 2.0;
        vNew[2] = v[2] / 2.0;
        trans.RotateWXYZ(180.0,vNew[0],vNew[1],vNew[2]);
        }
      }

    // determine scale factor from scalars if appropriate
    if ( inScalars != NULL )
      {
      // Copy Input scalar
      scale = inScalars->GetScalar(inPtId);
      if ( this->ScaleMode == SCALE_BY_SCALAR )
        {
        if ( (den = this->Range[1] - this->Range[0]) == 0.0 ) den = 1.0;

        scale = (scale < this->Range[0] ? this->Range[0] :
                 (scale > this->Range[1] ? this->Range[1] : scale));
        scale = (scale - this->Range[0]) / den;

        }

      for (i=0; i < numSourcePts; i++)
        newScalars->InsertScalar(ptIncr+i,scale);
      }

    // scale data if appropriate
    if ( scaleSource )
      {
      scale *= this->ScaleFactor;
      if ( scale == 0.0 ) scale = 1.0e-10;
      trans.Scale(scale,scale,scale);
      }

    // multiply points and normals by resulting matrix
    trans.MultiplyPoints(sourcePts,newPts);
    if ( sourceNormals != NULL )
      trans.MultiplyNormals(sourceNormals,newNormals);

    // Copy point data from source
    for (i=0; i < numSourcePts; i++)
      this->PointData.CopyData(pd,i,ptIncr+i);
    }
//
// Update ourselves
//
  this->SetPoints(newPts);
  this->PointData.SetScalars(newScalars);
  this->PointData.SetVectors(newVectors);
  this->PointData.SetNormals(newNormals);
  this->Squeeze();
}

// Description:
// Override update method because execution can branch two ways (Input
// and Source)
void vtkGlyph3D::Update()
{
  // make sure input is available
  if ( this->Input == NULL || this->Source == NULL )
    {
    vtkErrorMacro(<< "No input!");
    return;
    }

  // prevent chasing our tail
  if (this->Updating) return;

  this->Updating = 1;
  this->Input->Update();
  this->Source->Update();
  this->Updating = 0;

  if (this->Input->GetMTime() > this->GetMTime() ||
  this->Source->GetMTime() > this->GetMTime() ||
  this->GetMTime() > this->ExecuteTime || this->GetDataReleased() )
    {
    if ( this->StartMethod ) (*this->StartMethod)(this->StartMethodArg);
    this->Execute();
    this->ExecuteTime.Modified();
    this->SetDataReleased(0);
    if ( this->EndMethod ) (*this->EndMethod)(this->EndMethodArg);
    }

  if ( this->Input->ShouldIReleaseData() ) this->Input->ReleaseData();
  if ( this->Source->ShouldIReleaseData() ) this->Source->ReleaseData();
}

void vtkGlyph3D::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToPolyFilter::PrintSelf(os,indent);

  os << indent << "Source: " << this->Source << "\n";
  os << indent << "Scaling: " << (this->Scaling ? "On\n" : "Off\n");
  os << indent << "Scale Mode: " << (this->ScaleMode == SCALE_BY_SCALAR ? "Scale by scalar\n" : "Scale by vector\n");
  os << indent << "Scale Factor: " << this->ScaleFactor << "\n";
  os << indent << "Range: (" << this->Range[0] << ", " << this->Range[1] << ")\n";
  os << indent << "Orient: " << (this->Orient ? "On\n" : "Off\n");

  os << indent << "Orient Mode: " << (this->VectorMode == USE_VECTOR ? "Orient by vector\n" : "Orient by normal\n");
}

<|endoftext|>


<commit_before>/*
 * DIPlib 3.0 viewer
 * This file contains functionality for the status bar.
 *
 * (c)2017, Wouter Caarls
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "diplib/viewer/include_gl.h"
#include "diplib/viewer/status.h"

namespace dip { namespace viewer {

void StatusViewPort::render()
{
  auto &o = viewer()->options();

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glViewport(x_, viewer()->height()-y_-height_, width_, height_);
  glOrtho(0, width(), height(), 0, -1, 1);
  glMatrixMode(GL_MODELVIEW);

  glColor3f(.5, .5, .5);
  glBegin(GL_LINES);
    glVertex2f(0.f, 0.f);
    glVertex2f((GLfloat)width(), 0.f);
  glEnd();

  glColor3f(1., 1., 1.);
  glRasterPos2i(1, 12);

  size_t rx = 1;

  if (o.status_ != "")
  {
    viewer()->drawString(o.status_.c_str());
  }
  else
  {
    // Describe operating point
    auto op = o.operating_point_;
    auto te = (int)viewer()->image().TensorElements();
    auto opp = viewer()->image().PixelsToPhysical((FloatArray)op);

    rx += viewer()->drawString("(");
    for (dip::uint ii=0; ii < op.size(); ++ii)
    {
      rx += viewer()->drawString(std::to_string(op[ii]).c_str());
      if (viewer()->image().PixelSize(ii) != PhysicalQuantity::Pixel() || o.offset_[ii])
      {
        std::ostringstream oss;
        PhysicalQuantity p = opp[ii] + o.offset_[ii];
        p.Normalize();
        oss << "=" << p;
        rx += viewer()->drawString(oss.str().c_str());
      }

      if (ii < op.size()-1)
        rx += viewer()->drawString(", ");
    }
    rx += viewer()->drawString("): ");
    if (te > 1)
      rx += viewer()->drawString("[");

    for (int ii=0; ii < te; ++ii)
    {
      if (o.lut_ == ViewingOptions::LookupTable::RGB)
      {
        if (ii == o.color_elements_[0])
          glColor3d(0.9, 0.17, 0.);
        else if (ii == o.color_elements_[1])
          glColor3d(0.0, 0.50, 0.);
        else if (ii == o.color_elements_[2])
          glColor3d(0.1, 0.33, 1.);
        else
          glColor3f(.5, .5, .5);
      }
      else
      {
        if ((size_t)ii == o.element_)
          glColor3f(1., 1., 1.);
        else
          glColor3f(.5, .5, .5);
      }

      glRasterPos2i((GLint)rx, 12);
      rx += viewer()->drawString(std::to_string((dip::sfloat)viewer()->image().At(op)[(size_t)ii]).c_str());

      glColor3f(1., 1., 1.);
      glRasterPos2i((GLint)rx, 12);

      if (ii < te-1)
        rx += viewer()->drawString(", ");
    }
    if (te > 1)
      rx += viewer()->drawString("]");
  }
}

}} // namespace dip::viewer
<commit_msg>Fixed units display in viewer status bar<commit_after>/*
 * DIPlib 3.0 viewer
 * This file contains functionality for the status bar.
 *
 * (c)2017, Wouter Caarls
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "diplib/viewer/include_gl.h"
#include "diplib/viewer/status.h"

namespace dip { namespace viewer {

void StatusViewPort::render()
{
  auto &o = viewer()->options();

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glViewport(x_, viewer()->height()-y_-height_, width_, height_);
  glOrtho(0, width(), height(), 0, -1, 1);
  glMatrixMode(GL_MODELVIEW);

  glColor3f(.5, .5, .5);
  glBegin(GL_LINES);
    glVertex2f(0.f, 0.f);
    glVertex2f((GLfloat)width(), 0.f);
  glEnd();

  glColor3f(1., 1., 1.);
  glRasterPos2i(1, 12);

  size_t rx = 1;

  if (o.status_ != "")
  {
    viewer()->drawString(o.status_.c_str());
  }
  else
  {
    // Describe operating point
    auto op = o.operating_point_;
    auto te = (int)viewer()->image().TensorElements();
    auto opp = viewer()->image().PixelsToPhysical((FloatArray)op);

    rx += viewer()->drawString("(");
    for (dip::uint ii=0; ii < op.size(); ++ii)
    {
      rx += viewer()->drawString(std::to_string(op[ii]).c_str());
      if (viewer()->image().PixelSize(ii) != PhysicalQuantity::Pixel() || o.offset_[ii])
      {
        std::ostringstream oss;
        PhysicalQuantity p = opp[ii] + o.offset_[ii];
        p.Normalize();
        oss << "=" << p.magnitude << p.units.String();
        rx += viewer()->drawString(oss.str().c_str());
      }

      if (ii < op.size()-1)
        rx += viewer()->drawString(", ");
    }
    rx += viewer()->drawString("): ");
    if (te > 1)
      rx += viewer()->drawString("[");

    for (int ii=0; ii < te; ++ii)
    {
      if (o.lut_ == ViewingOptions::LookupTable::RGB)
      {
        if (ii == o.color_elements_[0])
          glColor3d(0.9, 0.17, 0.);
        else if (ii == o.color_elements_[1])
          glColor3d(0.0, 0.50, 0.);
        else if (ii == o.color_elements_[2])
          glColor3d(0.1, 0.33, 1.);
        else
          glColor3f(.5, .5, .5);
      }
      else
      {
        if ((size_t)ii == o.element_)
          glColor3f(1., 1., 1.);
        else
          glColor3f(.5, .5, .5);
      }

      glRasterPos2i((GLint)rx, 12);
      rx += viewer()->drawString(std::to_string((dip::sfloat)viewer()->image().At(op)[(size_t)ii]).c_str());

      glColor3f(1., 1., 1.);
      glRasterPos2i((GLint)rx, 12);

      if (ii < te-1)
        rx += viewer()->drawString(", ");
    }
    if (te > 1)
      rx += viewer()->drawString("]");
  }
}

}} // namespace dip::viewer
<|endoftext|>


<commit_before>// SciTE - Scintilla based Text Editor
/** @file LexAVE.cxx
 ** Lexer for Avenue.
 **
  ** Written by Alexey Yutkin <yutkin@geol.msu.ru>.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}
static inline bool IsEnumChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch)|| ch == '_');
}
static inline bool IsANumberChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' );
}

inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

inline bool isAveOperator(char ch) {
	if (isalnum(ch))
		return false;
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		ch == '(' || ch == ')' || ch == '=' ||
		ch == '{' || ch == '}' ||
		ch == '[' || ch == ']' || ch == ';' ||
		ch == '<' || ch == '>' || ch == ',' ||
		ch == '.'  )
		return true;
	return false;
}

static void ColouriseAveDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5];

	// Do not leak onto next line
	if (initStyle == SCE_AVE_STRINGEOL) {
		initStyle = SCE_AVE_DEFAULT;
	}

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			int currentLine = styler.GetLine(sc.currentPos);
			styler.SetLineState(currentLine, 0);
		}
		if (sc.atLineStart && (sc.state == SCE_AVE_STRING)) {
			// Prevent SCE_AVE_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_AVE_STRING);
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_AVE_OPERATOR) {
			sc.SetState(SCE_AVE_DEFAULT);
		} else if (sc.state == SCE_AVE_NUMBER) {
			if (!IsANumberChar(sc.ch)) {
				sc.SetState(SCE_AVE_DEFAULT);
			}
		} else if (sc.state == SCE_AVE_ENUM) {
			if (!IsEnumChar(sc.ch)) {
				sc.SetState(SCE_AVE_DEFAULT);
			}
		} else if (sc.state == SCE_AVE_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
				//sc.GetCurrent(s, sizeof(s));
				sc.GetCurrentLowered(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD3);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD4);
				} else if (keywords5.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD5);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD6);
				}
				sc.SetState(SCE_AVE_DEFAULT);
			}
		} else if (sc.state == SCE_AVE_COMMENT) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_AVE_DEFAULT);
			}
		} else if (sc.state == SCE_AVE_STRING) {
			 if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_AVE_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_AVE_STRINGEOL);
				sc.ForwardSetState(SCE_AVE_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_AVE_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_AVE_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_AVE_IDENTIFIER);
			} else if (sc.Match('\"')) {
				sc.SetState(SCE_AVE_STRING);
			} else if (sc.Match('\'')) {
				sc.SetState(SCE_AVE_COMMENT);
				sc.Forward();
			} else if (isAveOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_AVE_OPERATOR);
			} else if (sc.Match('#')) {
				sc.SetState(SCE_AVE_ENUM);
				sc.Forward();
			}
		}
	}
	sc.Complete();
}

static void FoldAveDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = static_cast<char>(tolower(styler[startPos]));
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	int styleNext = styler.StyleAt(startPos);
	char s[10];

	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = static_cast<char>(tolower(chNext));
		chNext = static_cast<char>(tolower(styler.SafeGetCharAt(i + 1)));
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_AVE_WORD) {
			if (ch == 't' || ch == 'f' || ch == 'w' || ch == 'e') {
				for (unsigned int j = 0; j < 6; j++) {
					if (!iswordchar(styler[i + j])) {
						break;
					}
					s[j] = static_cast<char>(tolower(styler[i + j]));
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "then") == 0) || (strcmp(s, "for") == 0) || (strcmp(s, "while") == 0)) {
					levelCurrent++;
				}
				if ((strcmp(s, "end") == 0)) {
					levelCurrent--;
				}
			}
		} else if (style == SCE_AVE_OPERATOR) {
			if (ch == '{' || ch == '(') {
				levelCurrent++;
			} else if (ch == '}' || ch == ')') {
				levelCurrent--;
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact) {
				lev |= SC_FOLDLEVELWHITEFLAG;
			}
			if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
				lev |= SC_FOLDLEVELHEADERFLAG;
			}
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch)) {
			visibleChars++;
		}
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

LexerModule lmAVE(SCLEX_AVE, ColouriseAveDoc, "ave", FoldAveDoc);

<commit_msg>Patch from Bruce Doson fixes folding of elseif.<commit_after>// SciTE - Scintilla based Text Editor
/** @file LexAVE.cxx
 ** Lexer for Avenue.
 **
  ** Written by Alexey Yutkin <yutkin@geol.msu.ru>.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}
static inline bool IsEnumChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch)|| ch == '_');
}
static inline bool IsANumberChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' );
}

inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

inline bool isAveOperator(char ch) {
	if (isalnum(ch))
		return false;
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		ch == '(' || ch == ')' || ch == '=' ||
		ch == '{' || ch == '}' ||
		ch == '[' || ch == ']' || ch == ';' ||
		ch == '<' || ch == '>' || ch == ',' ||
		ch == '.'  )
		return true;
	return false;
}

static void ColouriseAveDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5];

	// Do not leak onto next line
	if (initStyle == SCE_AVE_STRINGEOL) {
		initStyle = SCE_AVE_DEFAULT;
	}

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			int currentLine = styler.GetLine(sc.currentPos);
			styler.SetLineState(currentLine, 0);
		}
		if (sc.atLineStart && (sc.state == SCE_AVE_STRING)) {
			// Prevent SCE_AVE_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_AVE_STRING);
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_AVE_OPERATOR) {
			sc.SetState(SCE_AVE_DEFAULT);
		} else if (sc.state == SCE_AVE_NUMBER) {
			if (!IsANumberChar(sc.ch)) {
				sc.SetState(SCE_AVE_DEFAULT);
			}
		} else if (sc.state == SCE_AVE_ENUM) {
			if (!IsEnumChar(sc.ch)) {
				sc.SetState(SCE_AVE_DEFAULT);
			}
		} else if (sc.state == SCE_AVE_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
				//sc.GetCurrent(s, sizeof(s));
				sc.GetCurrentLowered(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD3);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD4);
				} else if (keywords5.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD5);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD6);
				}
				sc.SetState(SCE_AVE_DEFAULT);
			}
		} else if (sc.state == SCE_AVE_COMMENT) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_AVE_DEFAULT);
			}
		} else if (sc.state == SCE_AVE_STRING) {
			 if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_AVE_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_AVE_STRINGEOL);
				sc.ForwardSetState(SCE_AVE_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_AVE_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_AVE_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_AVE_IDENTIFIER);
			} else if (sc.Match('\"')) {
				sc.SetState(SCE_AVE_STRING);
			} else if (sc.Match('\'')) {
				sc.SetState(SCE_AVE_COMMENT);
				sc.Forward();
			} else if (isAveOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_AVE_OPERATOR);
			} else if (sc.Match('#')) {
				sc.SetState(SCE_AVE_ENUM);
				sc.Forward();
			}
		}
	}
	sc.Complete();
}

static void FoldAveDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = static_cast<char>(tolower(styler[startPos]));
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	int styleNext = styler.StyleAt(startPos);
	char s[10];

	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = static_cast<char>(tolower(chNext));
		chNext = static_cast<char>(tolower(styler.SafeGetCharAt(i + 1)));
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_AVE_WORD) {
			if (ch == 't' || ch == 'f' || ch == 'w' || ch == 'e') {
				for (unsigned int j = 0; j < 6; j++) {
					if (!iswordchar(styler[i + j])) {
						break;
					}
					s[j] = static_cast<char>(tolower(styler[i + j]));
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "then") == 0) || (strcmp(s, "for") == 0) || (strcmp(s, "while") == 0)) {
					levelCurrent++;
				}
				if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0)) {
					// Normally "elseif" and "then" will be on the same line and will cancel
					// each other out.  // As implemented, this does not support fold.at.else.
					levelCurrent--;
				}
			}
		} else if (style == SCE_AVE_OPERATOR) {
			if (ch == '{' || ch == '(') {
				levelCurrent++;
			} else if (ch == '}' || ch == ')') {
				levelCurrent--;
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact) {
				lev |= SC_FOLDLEVELWHITEFLAG;
			}
			if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
				lev |= SC_FOLDLEVELHEADERFLAG;
			}
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch)) {
			visibleChars++;
		}
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

LexerModule lmAVE(SCLEX_AVE, ColouriseAveDoc, "ave", FoldAveDoc);

<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexCSS.cxx
 ** Lexer for Cascade Style Sheets
 ** Written by Jakub Vrna
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static inline bool IsAWordChar(const unsigned int ch) {
	return (isalnum(ch) || ch == '-' || ch == '_' || ch >= 161); // _ is not in fact correct CSS word-character
}

inline bool IsCssOperator(const char ch) {
	if (!isalnum(ch) && (ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' || ch == '.' || ch == '#' || ch == '!' || ch == '@'))
		return true;
	return false;
}

static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {
	WordList &keywords = *keywordlists[0];
	WordList &pseudoClasses = *keywordlists[1];

	StyleContext sc(startPos, length, initStyle, styler);

	int lastState = -1; // before operator
	int lastStateC = -1; // before comment
	int op = ' '; // last operator

	for (; sc.More(); sc.Forward()) {
		if (sc.state == SCE_CSS_COMMENT && sc.Match('*', '/')) {
			if (lastStateC == -1) {
				// backtrack to get last state
				unsigned int i = startPos;
				for (; i > 0; i--) {
					if ((lastStateC = styler.StyleAt(i-1)) != SCE_CSS_COMMENT) {
						if (lastStateC == SCE_CSS_OPERATOR) {
							op = styler.SafeGetCharAt(i-1);
							while (--i) {
								lastState = styler.StyleAt(i-1);
								if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
									break;
							}
							if (i == 0)
								lastState = SCE_CSS_DEFAULT;
						}
						break;
					}
				}
				if (i == 0)
					lastStateC = SCE_CSS_DEFAULT;
			}
			sc.Forward();
			sc.ForwardSetState(lastStateC);
		}

		if (sc.state == SCE_CSS_COMMENT)
			continue;

		if (sc.state == SCE_CSS_DOUBLESTRING || sc.state == SCE_CSS_SINGLESTRING) {
			if (sc.ch != (sc.state == SCE_CSS_DOUBLESTRING ? '\"' : '\''))
				continue;
			unsigned int i = sc.currentPos;
			while (i && styler[i-1] == '\\')
				i--;
			if ((sc.currentPos - i) % 2 == 1)
				continue;
			sc.ForwardSetState(SCE_CSS_VALUE);
		}

		if (sc.state == SCE_CSS_OPERATOR) {
			if (op == ' ') {
				unsigned int i = startPos;
				op = styler.SafeGetCharAt(i-1);
				while (--i) {
					lastState = styler.StyleAt(i-1);
					if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
						break;
				}
			}
			switch (op) {
			case '@':
				if (lastState == SCE_CSS_DEFAULT)
					sc.SetState(SCE_CSS_DIRECTIVE);
				break;
			case '{':
				if (lastState == SCE_CSS_DIRECTIVE)
					sc.SetState(SCE_CSS_DEFAULT);
				else if (lastState == SCE_CSS_TAG)
					sc.SetState(SCE_CSS_IDENTIFIER);
				break;
			case '}':
				if (lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT || lastState == SCE_CSS_IDENTIFIER)
					sc.SetState(SCE_CSS_DEFAULT);
				break;
			case ':':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
					lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
					sc.SetState(SCE_CSS_PSEUDOCLASS);
				else if (lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_UNKNOWN_IDENTIFIER)
					sc.SetState(SCE_CSS_VALUE);
				break;
			case '.':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT)
					sc.SetState(SCE_CSS_CLASS);
				break;
			case '#':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT)
					sc.SetState(SCE_CSS_ID);
				break;
			case ',':
				if (lastState == SCE_CSS_TAG)
					sc.SetState(SCE_CSS_DEFAULT);
				break;
			case ';':
				if (lastState == SCE_CSS_DIRECTIVE)
					sc.SetState(SCE_CSS_DEFAULT);
				else if (lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT)
					sc.SetState(SCE_CSS_IDENTIFIER);
				break;
			case '!':
				if (lastState == SCE_CSS_VALUE)
					sc.SetState(SCE_CSS_IMPORTANT);
				break;
			}
		}

		if (IsAWordChar(sc.ch)) {
			if (sc.state == SCE_CSS_DEFAULT)
				sc.SetState(SCE_CSS_TAG);
			continue;
		}

		if (IsAWordChar(sc.chPrev) && (
			sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_UNKNOWN_IDENTIFIER
			|| sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS
			|| sc.state == SCE_CSS_IMPORTANT
		)) {
			char s[100];
			sc.GetCurrentLowered(s, sizeof(s));
			char *s2 = s;
			while (*s2 && !IsAWordChar(*s2))
				s2++;
			switch (sc.state) {
			case SCE_CSS_IDENTIFIER:
				if (!keywords.InList(s2))
					sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER);
				break;
			case SCE_CSS_UNKNOWN_IDENTIFIER:
				if (keywords.InList(s2))
					sc.ChangeState(SCE_CSS_IDENTIFIER);
				break;
			case SCE_CSS_PSEUDOCLASS:
				if (!pseudoClasses.InList(s2))
					sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS);
				break;
			case SCE_CSS_UNKNOWN_PSEUDOCLASS:
				if (pseudoClasses.InList(s2))
					sc.ChangeState(SCE_CSS_PSEUDOCLASS);
				break;
			case SCE_CSS_IMPORTANT:
				if (strcmp(s2, "important") != 0)
					sc.ChangeState(SCE_CSS_VALUE);
				break;
			}
		}

		if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && (sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS || sc.state == SCE_CSS_ID))
			sc.SetState(SCE_CSS_TAG);

		if (sc.Match('/', '*')) {
			lastStateC = sc.state;
			sc.SetState(SCE_CSS_COMMENT);
			sc.Forward();
		} else if (sc.state == SCE_CSS_VALUE && (sc.ch == '\"' || sc.ch == '\'')) {
			sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING));
		} else if (IsCssOperator(static_cast<char>(sc.ch))
			&& (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!')
			&& (sc.state != SCE_CSS_DIRECTIVE || sc.ch == ';' || sc.ch == '{')
		) {
			if (sc.state != SCE_CSS_OPERATOR)
				lastState = sc.state;
			sc.SetState(SCE_CSS_OPERATOR);
			op = sc.ch;
		}
	}

	sc.Complete();
}

static void FoldCSSDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool inComment = (styler.StyleAt(startPos-1) == SCE_CSS_COMMENT);
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styler.StyleAt(i);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment) {
			if (!inComment && (style == SCE_CSS_COMMENT))
				levelCurrent++;
			else if (inComment && (style != SCE_CSS_COMMENT))
				levelCurrent--;
			inComment = (style == SCE_CSS_COMMENT);
		}
		if (style == SCE_CSS_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const cssWordListDesc[] = {
	"Keywords",
	"Pseudo classes",
	0
};

LexerModule lmCss(SCLEX_CSS, ColouriseCssDoc, "css", FoldCSSDoc, cssWordListDesc);
<commit_msg>Update from Philippe with some support for CSS 2.<commit_after>// Scintilla source code edit control
/** @file LexCSS.cxx
 ** Lexer for Cascading Style Sheets
 ** Written by Jakub Vrna
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static inline bool IsAWordChar(const unsigned int ch) {
	return (isalnum(ch) || ch == '-' || ch == '_' || ch >= 161); // _ is not in fact correct CSS word-character
}

inline bool IsCssOperator(const char ch) {
	if (!isalnum(ch) &&
		(ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' ||
		 ch == '.' || ch == '#' || ch == '!' || ch == '@' ||
		 /* CSS2 */
		 ch == '*' || ch == '>' || ch == '+' || ch == '=' || ch == '~' || ch == '|' ||
		 ch == '[' || ch == ']' || ch == '(' || ch == ')')) {
		return true;
	}
	return false;
}

static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {
	WordList &keywords = *keywordlists[0];
	WordList &pseudoClasses = *keywordlists[1];
	WordList &keywords2 = *keywordlists[2];

	StyleContext sc(startPos, length, initStyle, styler);

	int lastState = -1; // before operator
	int lastStateC = -1; // before comment
	int op = ' '; // last operator

	for (; sc.More(); sc.Forward()) {
		if (sc.state == SCE_CSS_COMMENT && sc.Match('*', '/')) {
			if (lastStateC == -1) {
				// backtrack to get last state:
				// comments are like whitespace, so we must return to the previous state
				unsigned int i = startPos;
				for (; i > 0; i--) {
					if ((lastStateC = styler.StyleAt(i-1)) != SCE_CSS_COMMENT) {
						if (lastStateC == SCE_CSS_OPERATOR) {
							op = styler.SafeGetCharAt(i-1);
							while (--i) {
								lastState = styler.StyleAt(i-1);
								if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
									break;
							}
							if (i == 0)
								lastState = SCE_CSS_DEFAULT;
						}
						break;
					}
				}
				if (i == 0)
					lastStateC = SCE_CSS_DEFAULT;
			}
			sc.Forward();
			sc.ForwardSetState(lastStateC);
		}

		if (sc.state == SCE_CSS_COMMENT)
			continue;

		if (sc.state == SCE_CSS_DOUBLESTRING || sc.state == SCE_CSS_SINGLESTRING) {
			if (sc.ch != (sc.state == SCE_CSS_DOUBLESTRING ? '\"' : '\''))
				continue;
			unsigned int i = sc.currentPos;
			while (i && styler[i-1] == '\\')
				i--;
			if ((sc.currentPos - i) % 2 == 1)
				continue;
			sc.ForwardSetState(SCE_CSS_VALUE);
		}

		if (sc.state == SCE_CSS_OPERATOR) {
			if (op == ' ') {
				unsigned int i = startPos;
				op = styler.SafeGetCharAt(i-1);
				while (--i) {
					lastState = styler.StyleAt(i-1);
					if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
						break;
				}
			}
			switch (op) {
			case '@':
				if (lastState == SCE_CSS_DEFAULT)
					sc.SetState(SCE_CSS_DIRECTIVE);
				break;
			case '{':
				if (lastState == SCE_CSS_DIRECTIVE)
					sc.SetState(SCE_CSS_DEFAULT);
				else if (lastState == SCE_CSS_TAG)
					sc.SetState(SCE_CSS_IDENTIFIER);
				break;
			case '}':
				if (lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT || lastState == SCE_CSS_IDENTIFIER)
					sc.SetState(SCE_CSS_DEFAULT);
				break;
			case ':':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
					lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
					sc.SetState(SCE_CSS_PSEUDOCLASS);
				else if (lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_UNKNOWN_IDENTIFIER)
					sc.SetState(SCE_CSS_VALUE);
				break;
			case '.':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT)
					sc.SetState(SCE_CSS_CLASS);
				break;
			case '#':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT)
					sc.SetState(SCE_CSS_ID);
				break;
			case ',':
				if (lastState == SCE_CSS_TAG)
					sc.SetState(SCE_CSS_DEFAULT);
				break;
			case ';':
				if (lastState == SCE_CSS_DIRECTIVE)
					sc.SetState(SCE_CSS_DEFAULT);
				else if (lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT)
					sc.SetState(SCE_CSS_IDENTIFIER);
				break;
			case '!':
				if (lastState == SCE_CSS_VALUE)
					sc.SetState(SCE_CSS_IMPORTANT);
				break;
			}
		}

		if (IsAWordChar(sc.ch)) {
			if (sc.state == SCE_CSS_DEFAULT)
				sc.SetState(SCE_CSS_TAG);
			continue;
		}

		if (IsAWordChar(sc.chPrev) && (
			sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_UNKNOWN_IDENTIFIER
			|| sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS
			|| sc.state == SCE_CSS_IMPORTANT
		)) {
			char s[100];
			sc.GetCurrentLowered(s, sizeof(s));
			char *s2 = s;
			while (*s2 && !IsAWordChar(*s2))
				s2++;
			switch (sc.state) {
			case SCE_CSS_IDENTIFIER:
				if (!keywords.InList(s2) && !keywords2.InList(s2))
					sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER);
				break;
			case SCE_CSS_UNKNOWN_IDENTIFIER:
				if (keywords.InList(s2))
					sc.ChangeState(SCE_CSS_IDENTIFIER);
				break;
			case SCE_CSS_PSEUDOCLASS:
				if (!pseudoClasses.InList(s2))
					sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS);
				break;
			case SCE_CSS_UNKNOWN_PSEUDOCLASS:
				if (pseudoClasses.InList(s2))
					sc.ChangeState(SCE_CSS_PSEUDOCLASS);
				break;
			case SCE_CSS_IMPORTANT:
				if (strcmp(s2, "important") != 0)
					sc.ChangeState(SCE_CSS_VALUE);
				break;
			}
		}

		if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && (sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS || sc.state == SCE_CSS_ID))
			sc.SetState(SCE_CSS_TAG);

		if (sc.Match('/', '*')) {
			lastStateC = sc.state;
			sc.SetState(SCE_CSS_COMMENT);
			sc.Forward();
		} else if (sc.state == SCE_CSS_VALUE && (sc.ch == '\"' || sc.ch == '\'')) {
			sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING));
		} else if (IsCssOperator(static_cast<char>(sc.ch))
			&& (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!')
			&& (sc.state != SCE_CSS_DIRECTIVE || sc.ch == ';' || sc.ch == '{')
		) {
			if (sc.state != SCE_CSS_OPERATOR)
				lastState = sc.state;
			sc.SetState(SCE_CSS_OPERATOR);
			op = sc.ch;
		}
	}

	sc.Complete();
}

static void FoldCSSDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool inComment = (styler.StyleAt(startPos-1) == SCE_CSS_COMMENT);
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styler.StyleAt(i);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment) {
			if (!inComment && (style == SCE_CSS_COMMENT))
				levelCurrent++;
			else if (inComment && (style != SCE_CSS_COMMENT))
				levelCurrent--;
			inComment = (style == SCE_CSS_COMMENT);
		}
		if (style == SCE_CSS_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const cssWordListDesc[] = {
	"Keywords",
	"Pseudo classes",
	0
};

LexerModule lmCss(SCLEX_CSS, ColouriseCssDoc, "css", FoldCSSDoc, cssWordListDesc);
<|endoftext|>


<commit_before>/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 *
 *  Libmemcached Client and Server
 *
 *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *      * Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 *      * Redistributions in binary form must reproduce the above
 *  copyright notice, this list of conditions and the following disclaimer
 *  in the documentation and/or other materials provided with the
 *  distribution.
 *
 *      * The names of its contributors may not be used to endorse or
 *  promote products derived from this software without specific prior
 *  written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT +10

#include <config.h>
#include <libtest/test.hpp>

#include "tests/basic.h"
#include "tests/debug.h"
#include "tests/deprecated.h"
#include "tests/error_conditions.h"
#include "tests/exist.h"
#include "tests/ketama.h"
#include "tests/namespace.h"
#include "tests/parser.h"
#include "tests/libmemcached-1.0/dump.h"
#include "tests/libmemcached-1.0/generate.h"
#include "tests/libmemcached-1.0/haldenbrand.h"
#include "tests/libmemcached-1.0/stat.h"
#include "tests/touch.h"
#include "tests/callbacks.h"
#include "tests/pool.h"
#include "tests/print.h"
#include "tests/replication.h"
#include "tests/server_add.h"
#include "tests/virtual_buckets.h"

#include "tests/libmemcached-1.0/setup_and_teardowns.h"

#include "tests/libmemcached-1.0/mem_functions.h"

/* Collections we are running */
#include "tests/libmemcached-1.0/all_tests.h"

#include "tests/libmemcached_world.h"

void get_world(Framework *world)
{
  world->collections= collection;

  world->_create= (test_callback_create_fn*)world_create;
  world->_destroy= (test_callback_destroy_fn*)world_destroy;

  world->item._startup= (test_callback_fn*)world_test_startup;
  world->item.set_pre((test_callback_fn*)world_pre_run);
  world->item.set_flush((test_callback_fn*)world_flush);
  world->item.set_post((test_callback_fn*)world_post_run);
  world->_on_error= (test_callback_error_fn*)world_on_error;

  world->collection_startup= (test_callback_fn*)world_container_startup;
  world->collection_shutdown= (test_callback_fn*)world_container_shutdown;

  world->set_runner(&defualt_libmemcached_runner);

  world->set_socket();
}
<commit_msg>Make the number of servers we test against more flexible.<commit_after>/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 *
 *  Libmemcached Client and Server
 *
 *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *      * Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 *      * Redistributions in binary form must reproduce the above
 *  copyright notice, this list of conditions and the following disclaimer
 *  in the documentation and/or other materials provided with the
 *  distribution.
 *
 *      * The names of its contributors may not be used to endorse or
 *  promote products derived from this software without specific prior
 *  written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT +10

#include <config.h>
#include <libtest/test.hpp>

#include "tests/basic.h"
#include "tests/debug.h"
#include "tests/deprecated.h"
#include "tests/error_conditions.h"
#include "tests/exist.h"
#include "tests/ketama.h"
#include "tests/namespace.h"
#include "tests/parser.h"
#include "tests/libmemcached-1.0/dump.h"
#include "tests/libmemcached-1.0/generate.h"
#include "tests/libmemcached-1.0/haldenbrand.h"
#include "tests/libmemcached-1.0/stat.h"
#include "tests/touch.h"
#include "tests/callbacks.h"
#include "tests/pool.h"
#include "tests/print.h"
#include "tests/replication.h"
#include "tests/server_add.h"
#include "tests/virtual_buckets.h"

#include "tests/libmemcached-1.0/setup_and_teardowns.h"

#include "tests/libmemcached-1.0/mem_functions.h"

/* Collections we are running */
#include "tests/libmemcached-1.0/all_tests.h"

#include "tests/libmemcached_world.h"

void get_world(Framework *world)
{
  if (getenv("LIBMEMCACHED_SERVER_NUMBER"))
  {
    int set_count= atoi(getenv("LIBMEMCACHED_SERVER_NUMBER"));
    assert(set_count >= 0);
    world->servers().set_count(set_count);
  }
  else
  {
    world->servers().set_count(8);
  }

  world->collections= collection;

  world->_create= (test_callback_create_fn*)world_create;
  world->_destroy= (test_callback_destroy_fn*)world_destroy;

  world->item._startup= (test_callback_fn*)world_test_startup;
  world->item.set_pre((test_callback_fn*)world_pre_run);
  world->item.set_flush((test_callback_fn*)world_flush);
  world->item.set_post((test_callback_fn*)world_post_run);
  world->_on_error= (test_callback_error_fn*)world_on_error;

  world->collection_startup= (test_callback_fn*)world_container_startup;
  world->collection_shutdown= (test_callback_fn*)world_container_shutdown;

  world->set_runner(&defualt_libmemcached_runner);

  world->set_socket();
}
<|endoftext|>


<commit_before>#include "Opcodes.hpp"
#include "VMState.hpp"

// push reg
MAKE_OPCODE(0x50)
{
    state->Push(state->eax);
}
MAKE_OPCODE(0x51)
{
    state->Push(state->ecx);
}
MAKE_OPCODE(0x52)
{
    state->Push(state->edx);
}
MAKE_OPCODE(0x53)
{
    state->Push(state->ebx);
}
MAKE_OPCODE(0x54)
{
    state->Push(state->esp);
}
MAKE_OPCODE(0x55)
{
    state->Push(state->ebp);
}
MAKE_OPCODE(0x56)
{
    state->Push(state->esi);
}
MAKE_OPCODE(0x57)
{
    state->Push(state->edi);
}

// pop reg
MAKE_OPCODE(0x58)
{
    state->eax = state->Pop();
}
MAKE_OPCODE(0x59)
{
    state->ecx = state->Pop();
}
MAKE_OPCODE(0x5A)
{
    state->edx = state->Pop();
}
MAKE_OPCODE(0x5B)
{
    state->ebx = state->Pop();
}
MAKE_OPCODE(0x5C)
{
    state->esp = state->Pop();
}
MAKE_OPCODE(0x5D)
{
    state->ebp = state->Pop();
}
MAKE_OPCODE(0x5E)
{
    state->esi = state->Pop();
}
MAKE_OPCODE(0x5F)
{
    state->edi = state->Pop();
}

// mov reg, reg OR mov [reg+disp], reg
MAKE_OPCODE(0x89)
{
    ModRM mod(state->ReadIPRelative(1));

    switch (mod.mod)
    {
    case 1:
    {
        auto disp = static_cast<int32_t>(state->ReadIPRelative(2));
        Log << "[" << state->GetRegisterName(mod.reg1) << '+' << disp << "], "
                   << state->GetRegisterName(mod.reg2);
        state->Write(state->ds * 16 + (state->general[mod.reg1] + disp), state->general[mod.reg2]);
        op.insnOffset++;
        break;
    }
    case 3:
        Log << state->GetRegisterName(mod.reg1) << ", " << state->GetRegisterName(mod.reg2);
        state->general[mod.reg1] = state->general[mod.reg2];
        break;
    };
}

// mov reg8, reg8 or mov reg8, [reg]
MAKE_OPCODE(0x8A)
{
    ModRM mod(state->ReadIPRelative(1));

    switch (mod.mod)
    {
    case 0:
        Log << state->GetByteRegisterName(mod.reg2) << ", [" << state->GetRegisterCombinationName(mod.reg1) << "]";
        GetRegister8(state, mod.reg2) =
            state->Read<uint8_t>(state->ds, RegisterCombinationToMemoryAddress(state, mod.reg1));
        break;
    case 3:
        Log << state->GetByteRegisterName(mod.reg1) << ", " << state->GetByteRegisterName(mod.reg2);
        GetRegister8(state, mod.reg1) = GetRegister8(state, mod.reg2);
        break;
    };
}

// mov reg, [reg+disp]
MAKE_OPCODE(0x8B)
{
    ModRM mod(state->ReadIPRelative(1));

    if (mod.mod == 1)
    {
        auto offset = state->general[mod.reg1] + (int8_t)state->ReadIPRelative(2);
        state->general[mod.reg2] = state->Read<uint32_t>(state->ds, offset);
    }
}

// mov sreg, reg
MAKE_OPCODE(0x8E)
{
    ModRM mod(state->ReadIPRelative(1));
    if (mod.mod == 3)
    {
        Log << state->GetSegmentName(mod.reg2) << ", " << state->GetRegisterName(mod.reg1);
        state->segment[mod.reg2] = state->general[mod.reg1];
    }
}

// mov reg8, imm8
MAKE_OPCODE(0xB0)
{
    Log << "al, " << PRINT_VALUE((uint32_t)state->ReadIPRelative(1));
    GetLowerByte(state->eax) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB1)
{
    Log << "cl, " << PRINT_VALUE((uint32_t)state->ReadIPRelative(1));
    GetLowerByte(state->ecx) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB2)
{
    Log << "dl, " << PRINT_VALUE((uint32_t)state->ReadIPRelative(1));
    GetLowerByte(state->edx) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB3)
{
    Log << "bl, " << PRINT_VALUE((uint32_t)state->ReadIPRelative(1));
    GetLowerByte(state->ebx) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB4)
{
    Log << "ah, " << PRINT_VALUE((uint32_t)state->ReadIPRelative(1));
    GetUpperByte(state->eax) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB5)
{
    Log << "ch, " << PRINT_VALUE((uint32_t)state->ReadIPRelative(1));
    GetUpperByte(state->ecx) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB6)
{
    Log << "dh, " << PRINT_VALUE((uint32_t)state->ReadIPRelative(1));
    GetUpperByte(state->edx) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB7)
{
    Log << "bh, " << PRINT_VALUE((uint32_t)state->ReadIPRelative(1));
    GetUpperByte(state->ebx) = state->ReadIPRelative(1);
}

// mov reg, immediate
MAKE_OPCODE(0xB8)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->eax = value;
    Log << state->GetRegisterName(0) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xB9)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->ecx = value;
    Log << state->GetRegisterName(1) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xBA)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->edx = value;
    Log << state->GetRegisterName(2) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xBB)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->ebx = value;
    Log << state->GetRegisterName(3) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xBC)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->esp = value;
    Log << state->GetRegisterName(4) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xBD)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->ebp = value;
    Log << state->GetRegisterName(5) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xBE)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->esi = value;
    Log << state->GetRegisterName(6) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xBF)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->edi = value;
    Log << state->GetRegisterName(7) << ", " << PRINT_VALUE(value);
}

// mov [reg], imm8
MAKE_OPCODE(0xC6)
{
    ModRM mod(state->ReadIPRelative(1));

    switch (mod.mod)
    {
    case 0:
        Log << "[" << state->general[mod.reg1] << "], " << PRINT_VALUE((uint32_t)state->ReadIPRelative(2))
                   << std::endl;
        state->Write(state->general[mod.reg1], state->ReadIPRelative(2));
        break;
    case 3:
        Log << state->general[mod.reg1] << ", " << PRINT_VALUE((uint32_t)state->ReadIPRelative(2));
        state->general[mod.reg1] = state->ReadIPRelative(2);
        break;
    };
}

// mov [reg+disp], imm16/32
MAKE_OPCODE(0xC7)
{
    ModRM mod(state->ReadIPRelative(1));
    ModRM sib(state->ReadIPRelative(2));

    uint8_t displacement = 0;
    if (mod.mod == 1)
    {
        displacement = state->ReadIPRelative(3);
        op.insnOffset++;
    }

    uint32_t memAddress = state->general[sib.reg1] + static_cast<int32_t>(displacement);
    auto offset = op.GetOffset(state) - (state->CR0.protectedMode ? 4 : 2);
    auto immediate = state->ReadImmediate(offset);

    if (state->CR0.protectedMode)
        state->Write<uint32_t>(memAddress, immediate);
    else
        state->Write<uint16_t>(memAddress, immediate);
}<commit_msg>General cleanup in Memory.cpp<commit_after>#include "Opcodes.hpp"
#include "VMState.hpp"

// push reg
MAKE_OPCODE(0x50)
{
    state->Push(state->eax);
}
MAKE_OPCODE(0x51)
{
    state->Push(state->ecx);
}
MAKE_OPCODE(0x52)
{
    state->Push(state->edx);
}
MAKE_OPCODE(0x53)
{
    state->Push(state->ebx);
}
MAKE_OPCODE(0x54)
{
    state->Push(state->esp);
}
MAKE_OPCODE(0x55)
{
    state->Push(state->ebp);
}
MAKE_OPCODE(0x56)
{
    state->Push(state->esi);
}
MAKE_OPCODE(0x57)
{
    state->Push(state->edi);
}

// pop reg
MAKE_OPCODE(0x58)
{
    state->eax = state->Pop();
}
MAKE_OPCODE(0x59)
{
    state->ecx = state->Pop();
}
MAKE_OPCODE(0x5A)
{
    state->edx = state->Pop();
}
MAKE_OPCODE(0x5B)
{
    state->ebx = state->Pop();
}
MAKE_OPCODE(0x5C)
{
    state->esp = state->Pop();
}
MAKE_OPCODE(0x5D)
{
    state->ebp = state->Pop();
}
MAKE_OPCODE(0x5E)
{
    state->esi = state->Pop();
}
MAKE_OPCODE(0x5F)
{
    state->edi = state->Pop();
}

// mov reg, reg OR mov [reg+disp], reg
MAKE_OPCODE(0x89)
{
    ModRM mod(state->ReadIPRelative(1));

    switch (mod.mod)
    {
    case 1:
    {
        auto disp = static_cast<int32_t>(state->ReadIPRelative(2));
        Log << "[" << state->GetRegisterName(mod.reg1) << '+' << disp << "], "
                   << state->GetRegisterName(mod.reg2);
        state->Write(state->ds * 16 + (state->general[mod.reg1] + disp), state->general[mod.reg2]);
        op.insnOffset++;
        break;
    }
    case 3:
        Log << state->GetRegisterName(mod.reg1) << ", " << state->GetRegisterName(mod.reg2);
        state->general[mod.reg1] = state->general[mod.reg2];
        break;
    };
}

// mov reg8, reg8 or mov reg8, [reg]
MAKE_OPCODE(0x8A)
{
    ModRM mod(state->ReadIPRelative(1));

    switch (mod.mod)
    {
    case 0:
        Log << state->GetByteRegisterName(mod.reg2) << ", [" << state->GetRegisterCombinationName(mod.reg1) << "]";
        GetRegister8(state, mod.reg2) =
            state->Read<uint8_t>(state->ds, RegisterCombinationToMemoryAddress(state, mod.reg1));
        break;
    case 3:
        Log << state->GetByteRegisterName(mod.reg1) << ", " << state->GetByteRegisterName(mod.reg2);
        GetRegister8(state, mod.reg1) = GetRegister8(state, mod.reg2);
        break;
    };
}

// mov reg, [reg+disp]
MAKE_OPCODE(0x8B)
{
    ModRM mod(state->ReadIPRelative(1));

    if (mod.mod == 1)
    {
        auto offset = state->general[mod.reg1] + (int8_t)state->ReadIPRelative(2);
        state->general[mod.reg2] = state->Read<uint32_t>(state->ds, offset);
    }
}

// mov sreg, reg
MAKE_OPCODE(0x8E)
{
    ModRM mod(state->ReadIPRelative(1));
    if (mod.mod == 3)
    {
        Log << state->GetSegmentName(mod.reg2) << ", " << state->GetRegisterName(mod.reg1);
        state->segment[mod.reg2] = state->general[mod.reg1];
    }
}

// mov reg8, imm8
MAKE_OPCODE(0xB0)
{
    Log << "al, " << PRINT_VALUE(static_cast<uint32_t>(state->ReadIPRelative(1)));
    GetLowerByte(state->eax) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB1)
{
    Log << "cl, " << PRINT_VALUE(static_cast<uint32_t>(state->ReadIPRelative(1)));
    GetLowerByte(state->ecx) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB2)
{
    Log << "dl, " << PRINT_VALUE(static_cast<uint32_t>(state->ReadIPRelative(1)));
    GetLowerByte(state->edx) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB3)
{
    Log << "bl, " << PRINT_VALUE(static_cast<uint32_t>(state->ReadIPRelative(1)));
    GetLowerByte(state->ebx) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB4)
{
    Log << "ah, " << PRINT_VALUE(static_cast<uint32_t>(state->ReadIPRelative(1)));
    GetUpperByte(state->eax) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB5)
{
    Log << "ch, " << PRINT_VALUE(static_cast<uint32_t>(state->ReadIPRelative(1)));
    GetUpperByte(state->ecx) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB6)
{
    Log << "dh, " << PRINT_VALUE(static_cast<uint32_t>(state->ReadIPRelative(1)));
    GetUpperByte(state->edx) = state->ReadIPRelative(1);
}
MAKE_OPCODE(0xB7)
{
    Log << "bh, " << PRINT_VALUE(static_cast<uint32_t>(state->ReadIPRelative(1)));
    GetUpperByte(state->ebx) = state->ReadIPRelative(1);
}

// mov reg, immediate
MAKE_OPCODE(0xB8)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->eax = value;
    Log << state->GetRegisterName(0) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xB9)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->ecx = value;
    Log << state->GetRegisterName(1) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xBA)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->edx = value;
    Log << state->GetRegisterName(2) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xBB)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->ebx = value;
    Log << state->GetRegisterName(3) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xBC)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->esp = value;
    Log << state->GetRegisterName(4) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xBD)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->ebp = value;
    Log << state->GetRegisterName(5) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xBE)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->esi = value;
    Log << state->GetRegisterName(6) << ", " << PRINT_VALUE(value);
}

MAKE_OPCODE(0xBF)
{
    auto value = state->ReadImmediate(state->eip + 1);
    state->edi = value;
    Log << state->GetRegisterName(7) << ", " << PRINT_VALUE(value);
}

// mov [reg], imm8
MAKE_OPCODE(0xC6)
{
    ModRM mod(state->ReadIPRelative(1));

    auto immediate = state->ReadIPRelative(2);

    switch (mod.mod)
    {
    case 0:
        Log << "[" << state->general[mod.reg1] << "], "
                   << PRINT_VALUE(static_cast<uint32_t>(immediate))
                   << std::endl;

        state->Write(state->general[mod.reg1], immediate);
        break;
    case 3:
        Log << state->general[mod.reg1] << ", "
            << PRINT_VALUE(static_cast<uint32_t>(immediate))
            << std::endl;

        state->general[mod.reg1] = immediate;
        break;
    };
}

// mov [reg+disp], imm16/32
MAKE_OPCODE(0xC7)
{
    ModRM mod(state->ReadIPRelative(1));
    ModRM sib(state->ReadIPRelative(2));

    uint8_t displacement = 0;
    if (mod.mod == 1)
    {
        displacement = state->ReadIPRelative(3);
        op.insnOffset++;
    }

    uint32_t memAddress = state->general[sib.reg1] + static_cast<int32_t>(displacement);
    auto offset = op.GetOffset(state) - (state->CR0.protectedMode ? 4 : 2);
    auto immediate = state->ReadImmediate(offset);

    if (state->CR0.protectedMode)
        state->Write<uint32_t>(memAddress, immediate);
    else
        state->Write<uint16_t>(memAddress, immediate);
}<|endoftext|>