<commit_before>//===- PDB.cpp ------------------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "PDB.h"
#include "Chunks.h"
#include "Config.h"
#include "Error.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
#include "llvm/DebugInfo/MSF/ByteStream.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/ScopedPrinter.h"
#include <memory>

using namespace lld;
using namespace lld::coff;
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::support;
using namespace llvm::support::endian;

using llvm::object::coff_section;

static ExitOnError ExitOnErr;

// Returns a list of all SectionChunks.
static std::vector<coff_section> getInputSections(SymbolTable *Symtab) {
  std::vector<coff_section> V;
  for (Chunk *C : Symtab->getChunks())
    if (auto *SC = dyn_cast<SectionChunk>(C))
      V.push_back(*SC->Header);
  return V;
}

static SectionChunk *findByName(std::vector<SectionChunk *> &Sections,
                                StringRef Name) {
  for (SectionChunk *C : Sections)
    if (C->getSectionName() == Name)
      return C;
  return nullptr;
}

static ArrayRef<uint8_t> getDebugT(ObjectFile *File) {
  SectionChunk *Sec = findByName(File->getDebugChunks(), ".debug$T");
  if (!Sec)
    return {};

  // First 4 bytes are section magic.
  ArrayRef<uint8_t> Data = Sec->getContents();
  if (Data.size() < 4)
    fatal(".debug$T too short");
  if (read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC)
    fatal(".debug$T has an invalid magic");
  return Data.slice(4);
}

static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) {
  ArrayRef<uint8_t> Data = getDebugT(File);
  if (Data.empty())
    return;

  msf::ByteStream Stream(Data);
  CVTypeDumper TypeDumper(&W, false);
  if (auto EC = TypeDumper.dump(Data))
    fatal(EC, "CVTypeDumper::dump failed");
}

static void dumpDebugS(ScopedPrinter &W, ObjectFile *File) {
  SectionChunk *Sec = findByName(File->getDebugChunks(), ".debug$S");
  if (!Sec)
    return;

  msf::ByteStream Stream(Sec->getContents());
  CVSymbolArray Symbols;
  msf::StreamReader Reader(Stream);
  if (auto EC = Reader.readArray(Symbols, Reader.getLength()))
    fatal(EC, "StreamReader.readArray<CVSymbolArray> failed");

  CVTypeDumper TypeDumper(&W, false);
  CVSymbolDumper SymbolDumper(W, TypeDumper, nullptr, false);
  if (auto EC = SymbolDumper.dump(Symbols))
    fatal(EC, "CVSymbolDumper::dump failed");
}

// Dump CodeView debug info. This is for debugging.
static void dumpCodeView(SymbolTable *Symtab) {
  ScopedPrinter W(outs());

  for (ObjectFile *File : Symtab->ObjectFiles) {
    dumpDebugT(W, File);
    dumpDebugS(W, File);
  }
}

static void addTypeInfo(SymbolTable *Symtab,
                        pdb::TpiStreamBuilder &TpiBuilder) {
  for (ObjectFile *File : Symtab->ObjectFiles) {
    ArrayRef<uint8_t> Data = getDebugT(File);
    if (Data.empty())
      continue;

    msf::ByteStream Stream(Data);
    codeview::CVTypeArray Records;
    msf::StreamReader Reader(Stream);
    if (auto EC = Reader.readArray(Records, Reader.getLength()))
      fatal(EC, "Reader.readArray failed");
    for (const codeview::CVType &Rec : Records)
      TpiBuilder.addTypeRecord(Rec);
  }
}

// Creates a PDB file.
void coff::createPDB(StringRef Path, SymbolTable *Symtab,
                     ArrayRef<uint8_t> SectionTable,
                     const llvm::codeview::DebugInfo *DI) {
  if (Config->DumpPdb)
    dumpCodeView(Symtab);

  BumpPtrAllocator Alloc;
  pdb::PDBFileBuilder Builder(Alloc);
  ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize

  // Create streams in MSF for predefined streams, namely
  // PDB, TPI, DBI and IPI.
  for (int I = 0; I < (int)pdb::kSpecialStreamCount; ++I)
    ExitOnErr(Builder.getMsfBuilder().addStream(0));

  // Add an Info stream.
  auto &InfoBuilder = Builder.getInfoBuilder();
  InfoBuilder.setAge(DI->PDB70.Age);
  InfoBuilder.setGuid(
      *reinterpret_cast<const pdb::PDB_UniqueId *>(&DI->PDB70.Signature));
  // Should be the current time, but set 0 for reproducibilty.
  InfoBuilder.setSignature(0);
  InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);

  // Add an empty DPI stream.
  auto &DbiBuilder = Builder.getDbiBuilder();
  DbiBuilder.setVersionHeader(pdb::PdbDbiV110);

  // Add an empty TPI stream.
  auto &TpiBuilder = Builder.getTpiBuilder();
  TpiBuilder.setVersionHeader(pdb::PdbTpiV80);
  if (Config->DebugPdb)
    addTypeInfo(Symtab, TpiBuilder);

  // Add an empty IPI stream.
  auto &IpiBuilder = Builder.getIpiBuilder();
  IpiBuilder.setVersionHeader(pdb::PdbTpiV80);

  // Add Section Contributions.
  std::vector<pdb::SectionContrib> Contribs =
      pdb::DbiStreamBuilder::createSectionContribs(getInputSections(Symtab));
  DbiBuilder.setSectionContribs(Contribs);

  // Add Section Map stream.
  ArrayRef<object::coff_section> Sections = {
      (const object::coff_section *)SectionTable.data(),
      SectionTable.size() / sizeof(object::coff_section)};
  std::vector<pdb::SecMapEntry> SectionMap =
      pdb::DbiStreamBuilder::createSectionMap(Sections);
  DbiBuilder.setSectionMap(SectionMap);

  ExitOnErr(DbiBuilder.addModuleInfo("", "* Linker *"));

  // Add COFF section header stream.
  ExitOnErr(
      DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));

  // Write to a file.
  ExitOnErr(Builder.commit(Path));
}
<commit_msg>[CodeView] Finish decoupling TypeDatabase from TypeDumper.<commit_after>//===- PDB.cpp ------------------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "PDB.h"
#include "Chunks.h"
#include "Config.h"
#include "Error.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/MSF/ByteStream.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/ScopedPrinter.h"
#include <memory>

using namespace lld;
using namespace lld::coff;
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::support;
using namespace llvm::support::endian;

using llvm::object::coff_section;

static ExitOnError ExitOnErr;

// Returns a list of all SectionChunks.
static std::vector<coff_section> getInputSections(SymbolTable *Symtab) {
  std::vector<coff_section> V;
  for (Chunk *C : Symtab->getChunks())
    if (auto *SC = dyn_cast<SectionChunk>(C))
      V.push_back(*SC->Header);
  return V;
}

static SectionChunk *findByName(std::vector<SectionChunk *> &Sections,
                                StringRef Name) {
  for (SectionChunk *C : Sections)
    if (C->getSectionName() == Name)
      return C;
  return nullptr;
}

static ArrayRef<uint8_t> getDebugT(ObjectFile *File) {
  SectionChunk *Sec = findByName(File->getDebugChunks(), ".debug$T");
  if (!Sec)
    return {};

  // First 4 bytes are section magic.
  ArrayRef<uint8_t> Data = Sec->getContents();
  if (Data.size() < 4)
    fatal(".debug$T too short");
  if (read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC)
    fatal(".debug$T has an invalid magic");
  return Data.slice(4);
}

static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) {
  ArrayRef<uint8_t> Data = getDebugT(File);
  if (Data.empty())
    return;

  TypeDatabase TDB;
  TypeDumpVisitor TDV(TDB, &W, false);
  CVTypeDumper TypeDumper(TDB);
  if (auto EC = TypeDumper.dump(Data, TDV))
    fatal(EC, "CVTypeDumper::dump failed");
}

static void dumpDebugS(ScopedPrinter &W, ObjectFile *File) {
  SectionChunk *Sec = findByName(File->getDebugChunks(), ".debug$S");
  if (!Sec)
    return;

  msf::ByteStream Stream(Sec->getContents());
  CVSymbolArray Symbols;
  msf::StreamReader Reader(Stream);
  if (auto EC = Reader.readArray(Symbols, Reader.getLength()))
    fatal(EC, "StreamReader.readArray<CVSymbolArray> failed");

  TypeDatabase TDB;
  CVSymbolDumper SymbolDumper(W, TDB, nullptr, false);
  if (auto EC = SymbolDumper.dump(Symbols))
    fatal(EC, "CVSymbolDumper::dump failed");
}

// Dump CodeView debug info. This is for debugging.
static void dumpCodeView(SymbolTable *Symtab) {
  ScopedPrinter W(outs());

  for (ObjectFile *File : Symtab->ObjectFiles) {
    dumpDebugT(W, File);
    dumpDebugS(W, File);
  }
}

static void addTypeInfo(SymbolTable *Symtab,
                        pdb::TpiStreamBuilder &TpiBuilder) {
  for (ObjectFile *File : Symtab->ObjectFiles) {
    ArrayRef<uint8_t> Data = getDebugT(File);
    if (Data.empty())
      continue;

    msf::ByteStream Stream(Data);
    codeview::CVTypeArray Records;
    msf::StreamReader Reader(Stream);
    if (auto EC = Reader.readArray(Records, Reader.getLength()))
      fatal(EC, "Reader.readArray failed");
    for (const codeview::CVType &Rec : Records)
      TpiBuilder.addTypeRecord(Rec);
  }
}

// Creates a PDB file.
void coff::createPDB(StringRef Path, SymbolTable *Symtab,
                     ArrayRef<uint8_t> SectionTable,
                     const llvm::codeview::DebugInfo *DI) {
  if (Config->DumpPdb)
    dumpCodeView(Symtab);

  BumpPtrAllocator Alloc;
  pdb::PDBFileBuilder Builder(Alloc);
  ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize

  // Create streams in MSF for predefined streams, namely
  // PDB, TPI, DBI and IPI.
  for (int I = 0; I < (int)pdb::kSpecialStreamCount; ++I)
    ExitOnErr(Builder.getMsfBuilder().addStream(0));

  // Add an Info stream.
  auto &InfoBuilder = Builder.getInfoBuilder();
  InfoBuilder.setAge(DI->PDB70.Age);
  InfoBuilder.setGuid(
      *reinterpret_cast<const pdb::PDB_UniqueId *>(&DI->PDB70.Signature));
  // Should be the current time, but set 0 for reproducibilty.
  InfoBuilder.setSignature(0);
  InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);

  // Add an empty DPI stream.
  auto &DbiBuilder = Builder.getDbiBuilder();
  DbiBuilder.setVersionHeader(pdb::PdbDbiV110);

  // Add an empty TPI stream.
  auto &TpiBuilder = Builder.getTpiBuilder();
  TpiBuilder.setVersionHeader(pdb::PdbTpiV80);
  if (Config->DebugPdb)
    addTypeInfo(Symtab, TpiBuilder);

  // Add an empty IPI stream.
  auto &IpiBuilder = Builder.getIpiBuilder();
  IpiBuilder.setVersionHeader(pdb::PdbTpiV80);

  // Add Section Contributions.
  std::vector<pdb::SectionContrib> Contribs =
      pdb::DbiStreamBuilder::createSectionContribs(getInputSections(Symtab));
  DbiBuilder.setSectionContribs(Contribs);

  // Add Section Map stream.
  ArrayRef<object::coff_section> Sections = {
      (const object::coff_section *)SectionTable.data(),
      SectionTable.size() / sizeof(object::coff_section)};
  std::vector<pdb::SecMapEntry> SectionMap =
      pdb::DbiStreamBuilder::createSectionMap(Sections);
  DbiBuilder.setSectionMap(SectionMap);

  ExitOnErr(DbiBuilder.addModuleInfo("", "* Linker *"));

  // Add COFF section header stream.
  ExitOnErr(
      DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));

  // Write to a file.
  ExitOnErr(Builder.commit(Path));
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"
#include "obj_tool.h"

int task_lightfire(TBeing *ch, cmdTypeT cmd, const char *, int pulse, TRoom *, TObj *obj)
{
  TThing *t, *t2;
  TMonster *guard;
  TTool *flintsteel=NULL;
  int found=0;

  if (ch->utilityTaskCommand(cmd) || ch->nobrainerTaskCommand(cmd))
    return FALSE;

  // basic tasky safechecking
  if (ch->isLinkdead() || (ch->in_room != ch->task->wasInRoom) || !obj){
    act("You cease your pyrotechnic activity.",
        FALSE, ch, 0, 0, TO_CHAR);
    act("$n stops trying to start a fire.",
        TRUE, ch, 0, 0, TO_ROOM);
    ch->stopTask();
    return FALSE; // returning FALSE lets command be interpreted
  }

  // make sure the thing we're trying to burn is still around
  if((obj != ch->heldInPrimHand()) && (obj != ch->heldInSecHand())){
    for (t = ch->roomp->getStuff(); t; t = t2) {
      t2 = t->nextThing;
      if(obj==dynamic_cast<TObj *>(t))
        found=1;
    }
    if(!found){
      act("You can't find $p and stop trying to light it on fire.",
          FALSE, ch, obj, 0, TO_CHAR);
      act("$n stops trying to start a fire.",
          TRUE, ch, obj, 0, TO_ROOM);
      ch->stopTask();
      return FALSE; // returning FALSE lets command be interpreted
    }
  }

  // find our tool here
  if (!(t = get_thing_char_using(ch, "flintsteel", 0, FALSE, FALSE)) ||
      !(flintsteel=dynamic_cast<TTool *>(t))){
    ch->sendTo("You need to own some flint and steel to light that.\n\r");
    ch->stopTask();
    return FALSE;
  }

  // check for guards that prevent
  for (t = ch->roomp->getStuff(); t; t = t2) {
    t2 = t->nextThing;
    guard = dynamic_cast<TMonster *>(t);
    if (!guard)
      continue;
    if (!guard->isPolice() || !guard->canSee(ch) ||
         !guard->awake())
      continue;
    guard->doSay("Hey!  Cut that out, you trying to burn the place down?");
    act("You cease your pyrotechnic activity.",
        FALSE, ch, 0, 0, TO_CHAR);
    act("$n stops trying to start a fire.",
        TRUE, ch, 0, 0, TO_ROOM);
    ch->stopTask();
    return FALSE;
  }

  if (ch->task->timeLeft < 0){
    if(material_nums[obj->getMaterial()].flammability){
      obj->setBurning(ch);

      act("You set $p on fire.",
          FALSE, ch, obj, 0, TO_CHAR);
      act("$n sets $p on fire.",
          TRUE, ch, obj, 0, TO_ROOM);
    } else {
      act("That $o doesn't seem to be flammable.",
          FALSE, ch, obj, 0, TO_CHAR);
      act("$n stops trying to start a fire.",
          TRUE, ch, 0, 0, TO_ROOM);
    }
    ch->stopTask();
    return FALSE;
  }
  switch (cmd) {
  case CMD_TASK_CONTINUE:
    // low flammability is very slow (10), wood is about 3
      ch->task->calcNextUpdate(pulse, PULSE_MOBACT *
             (10-(material_nums[obj->getMaterial()].flammability/70)));

      flintsteel->addToToolUses(-1);
      if (flintsteel->getToolUses() <= 0) {
        act("Oops, your $o has been used up.",
            FALSE, ch, flintsteel, 0, TO_CHAR);
        act("$n looks startled as $e realizes that his $o has been used up.",
            FALSE, ch, flintsteel, 0, TO_ROOM);
        ch->stopTask();
        delete flintsteel;
        return FALSE;
      }

      switch (ch->task->timeLeft) {
      case 2:
          act("You lay some thin <o>wood shavings<1> around the $o.",
              FALSE, ch, obj, 0, TO_CHAR);
          act("$n lays some thin <o>wood shavings<1> around the $o.",
              TRUE, ch, obj, 0, TO_ROOM);
          ch->task->timeLeft--;
          break;
      case 1:
          act("You strike your $o, sending <Y>sparks<1> into the <o>wood shavings<1>.",
              FALSE, ch, flintsteel, 0, TO_CHAR);
          act("$n strikes $s $o, sending <Y>sparks<1> into the <o>wood shavings<1>.",
              TRUE, ch, flintsteel, 0, TO_ROOM);
          ch->task->timeLeft--;
          break;
      case 0:
          act("You carefully fan the <r>flames<1> towards $p.",
              FALSE, ch, obj, 0, TO_CHAR);
          act("$n carefully fans the <r>flames<1> towards $p.",
              TRUE, ch, obj, 0, TO_ROOM);
          ch->task->timeLeft--;
          break;
      }
      break;
  case CMD_ABORT:
  case CMD_STOP:
      act("You cease your pyrotechnic activity.",
          FALSE, ch, 0, 0, TO_CHAR);
      act("$n stops trying to start a fire.",
          TRUE, ch, 0, 0, TO_ROOM);
      ch->stopTask();
      break;
  case CMD_TASK_FIGHTING:
      ch->sendTo("You can't properly start a fire while under attack.\n\r");
      ch->stopTask();
      break;
  default:
      if (cmd < MAX_CMD_LIST)
        warn_busy(ch);
      break;                    // eat the command
  }
  return TRUE;
}

<commit_msg>fixed crash bug when object being lit disappears<commit_after>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"
#include "obj_tool.h"

int task_lightfire(TBeing *ch, cmdTypeT cmd, const char *, int pulse, TRoom *, TObj *obj)
{
  TThing *t, *t2;
  TMonster *guard;
  TTool *flintsteel=NULL;
  int found=0;

  if (ch->utilityTaskCommand(cmd) || ch->nobrainerTaskCommand(cmd))
    return FALSE;

  // basic tasky safechecking
  if (ch->isLinkdead() || (ch->in_room != ch->task->wasInRoom) || !obj){
    act("You cease your pyrotechnic activity.",
        FALSE, ch, 0, 0, TO_CHAR);
    act("$n stops trying to start a fire.",
        TRUE, ch, 0, 0, TO_ROOM);
    ch->stopTask();
    return FALSE; // returning FALSE lets command be interpreted
  }

  // make sure the thing we're trying to burn is still around
  if((obj != ch->heldInPrimHand()) && (obj != ch->heldInSecHand())){
    for (t = ch->roomp->getStuff(); t; t = t2) {
      t2 = t->nextThing;
      if(obj==dynamic_cast<TObj *>(t))
        found=1;
    }
    if(!found){
      act("You can't find your target and stop trying to light it on fire.",
          FALSE, ch, 0, 0, TO_CHAR);
      act("$n stops trying to start a fire.",
          TRUE, ch, 0, 0, TO_ROOM);
      ch->stopTask();
      return FALSE; // returning FALSE lets command be interpreted
    }
  }

  // find our tool here
  if (!(t = get_thing_char_using(ch, "flintsteel", 0, FALSE, FALSE)) ||
      !(flintsteel=dynamic_cast<TTool *>(t))){
    ch->sendTo("You need to own some flint and steel to light that.\n\r");
    ch->stopTask();
    return FALSE;
  }

  // check for guards that prevent
  for (t = ch->roomp->getStuff(); t; t = t2) {
    t2 = t->nextThing;
    guard = dynamic_cast<TMonster *>(t);
    if (!guard)
      continue;
    if (!guard->isPolice() || !guard->canSee(ch) ||
         !guard->awake())
      continue;
    guard->doSay("Hey!  Cut that out, you trying to burn the place down?");
    act("You cease your pyrotechnic activity.",
        FALSE, ch, 0, 0, TO_CHAR);
    act("$n stops trying to start a fire.",
        TRUE, ch, 0, 0, TO_ROOM);
    ch->stopTask();
    return FALSE;
  }

  if (ch->task->timeLeft < 0){
    if(material_nums[obj->getMaterial()].flammability){
      obj->setBurning(ch);

      act("You set $p on fire.",
          FALSE, ch, obj, 0, TO_CHAR);
      act("$n sets $p on fire.",
          TRUE, ch, obj, 0, TO_ROOM);
    } else {
      act("That $o doesn't seem to be flammable.",
          FALSE, ch, obj, 0, TO_CHAR);
      act("$n stops trying to start a fire.",
          TRUE, ch, 0, 0, TO_ROOM);
    }
    ch->stopTask();
    return FALSE;
  }
  switch (cmd) {
  case CMD_TASK_CONTINUE:
    // low flammability is very slow (10), wood is about 3
      ch->task->calcNextUpdate(pulse, PULSE_MOBACT *
             (10-(material_nums[obj->getMaterial()].flammability/70)));

      flintsteel->addToToolUses(-1);
      if (flintsteel->getToolUses() <= 0) {
        act("Oops, your $o has been used up.",
            FALSE, ch, flintsteel, 0, TO_CHAR);
        act("$n looks startled as $e realizes that his $o has been used up.",
            FALSE, ch, flintsteel, 0, TO_ROOM);
        ch->stopTask();
        delete flintsteel;
        return FALSE;
      }

      switch (ch->task->timeLeft) {
      case 2:
          act("You lay some thin <o>wood shavings<1> around the $o.",
              FALSE, ch, obj, 0, TO_CHAR);
          act("$n lays some thin <o>wood shavings<1> around the $o.",
              TRUE, ch, obj, 0, TO_ROOM);
          ch->task->timeLeft--;
          break;
      case 1:
          act("You strike your $o, sending <Y>sparks<1> into the <o>wood shavings<1>.",
              FALSE, ch, flintsteel, 0, TO_CHAR);
          act("$n strikes $s $o, sending <Y>sparks<1> into the <o>wood shavings<1>.",
              TRUE, ch, flintsteel, 0, TO_ROOM);
          ch->task->timeLeft--;
          break;
      case 0:
          act("You carefully fan the <r>flames<1> towards $p.",
              FALSE, ch, obj, 0, TO_CHAR);
          act("$n carefully fans the <r>flames<1> towards $p.",
              TRUE, ch, obj, 0, TO_ROOM);
          ch->task->timeLeft--;
          break;
      }
      break;
  case CMD_ABORT:
  case CMD_STOP:
      act("You cease your pyrotechnic activity.",
          FALSE, ch, 0, 0, TO_CHAR);
      act("$n stops trying to start a fire.",
          TRUE, ch, 0, 0, TO_ROOM);
      ch->stopTask();
      break;
  case CMD_TASK_FIGHTING:
      ch->sendTo("You can't properly start a fire while under attack.\n\r");
      ch->stopTask();
      break;
  default:
      if (cmd < MAX_CMD_LIST)
        warn_busy(ch);
      break;                    // eat the command
  }
  return TRUE;
}

<|endoftext|>


<commit_before>#include "ITEMS.H"

#include "CONTROL.H"
#include "DRAW.H"
#include "OBJECTS.H"
#ifdef PC_VERSION
#include "GAME.H"
#include "INIT.H"
#else
#include "SETUP.H"
#endif
#include "SPECIFIC.H"
#include "SPECTYPES.H"
#include <stddef.h>
#include <assert.h>
#include "EFFECTS.H"
#include "MALLOC.H"
#include "EFFECT2.H"
#include "LARA.H"

int level_items;
short next_item_free;
short next_item_active;
short GlobalPulleyFrigItem;

void EffectNewRoom(short fx_num, short room_number)//42320, 42774 (F)
{
	if(InItemControlLoop)
	{
		ItemNewRooms[ItemNewRoomNo][0] = fx_num;
		ItemNewRooms[ItemNewRoomNo][1] = room_number;
		ItemNewRoomNo++;
	}
	else
	{
		struct FX_INFO* fx = &effects[fx_num];
		struct room_info* r = &room[fx->room_number];

		if (r->fx_number == fx_num)
		{
			r->fx_number = fx->next_fx;
		}
		else if(r->fx_number != -1)
		{
			short linknum;
			for (linknum = effects[r->fx_number].next_fx; linknum != -1; linknum = effects[linknum].next_fx)
			{
				if (linknum == fx_num)
				{
					effects[r->fx_number].next_fx = fx->next_fx;
					break;
				}
			}
		}

		fx->room_number = room_number;
		fx->next_fx = room[room_number].fx_number;
		room[room_number].fx_number = fx_num;
	}
}

void KillEffect(short fx_num)//42178, 425CC (F)
{
	if (InItemControlLoop)
	{
		ItemNewRooms[ItemNewRoomNo][0] = fx_num | 0x8000;
		ItemNewRoomNo++;
	}
	else
	{
		struct FX_INFO* fx = &effects[fx_num];

		DetatchSpark(fx_num, 128);

		if (next_fx_active == fx_num)
		{
			next_fx_active = fx->next_active;
		}
		else if (next_fx_active != -1)
		{
			short linknum;
			for (linknum = effects[next_fx_active].next_active; linknum != -1; linknum = effects[linknum].next_active)
			{
				if (linknum == fx_num)
				{
					effects[linknum].next_active = fx->next_active;
					break;
				}
			}
		}

		if (room[fx->room_number].fx_number == fx_num)
		{
			room[fx->room_number].fx_number = fx->next_fx;
		}
		else if (room[fx->room_number].fx_number != -1)
		{
			short linknum;
			for (linknum = effects[room[fx->room_number].fx_number].next_fx; linknum != -1; linknum = effects[linknum].next_fx)
			{
				if (linknum == fx_num)
				{
					effects[room[fx->room_number].fx_number].next_fx = fx->next_fx;
					break;
				}
			}
		}

		fx->next_fx = next_fx_free;
		next_fx_free = fx_num;
	}
}

short CreateEffect(short room_num)//420E0(<), 42534(<) (F)
{
	struct room_info* r;
	struct FX_INFO* fx;
	short fx_num = next_fx_free;

	if (next_fx_free != -1)
	{
		fx = &effects[next_fx_free];
		next_fx_free = fx->object_number;
		r = &room[room_num];
		fx->room_number = room_num;
		fx->next_fx = r->fx_number;
		r->fx_number = fx_num;
		fx->next_active = next_fx_active;
		next_fx_active = fx_num;
		fx->shade = GRAY555;
	}

	return fx_num;
}

void InitialiseFXArray(int allocmem)//4207C(<), 424D0(<) (F)
{
	int i;
	struct FX_INFO* fx;

	if (allocmem)
		effects = (struct FX_INFO*)game_malloc(24 * sizeof(struct FX_INFO));

	fx = effects;
	next_fx_active = -1;
	next_fx_free = 0;
	for (i = 1; i <= 24; i++)
	{
		fx->next_fx = i++;
		++fx;
	}
	fx->next_fx = -1;
}

void AddActiveItem(short item_num)//41FEC(<), 42440(<) (F)
{
	struct ITEM_INFO* item;

	item = &items[item_num];

	item->flags |= 0x20;

	if (objects[item->object_number].control == NULL)//Bug: Always zero due to incomplete level data relocation
	{
		item->status = ITEM_INACTIVE;
		return;
	}

	if (!item->active)
	{
		item->active = TRUE;
		item->next_active = next_item_active;
		next_item_active = item_num;
	}
}

void RemoveDrawnItem(short item_num)//41F48, 4239C (F)
{
	struct ITEM_INFO* item = &items[item_num];

	if (room[item->room_number].item_number == item_num)
	{
		room[item->room_number].item_number = item->next_item;
	}
	else if (room[item->room_number].item_number != -1)
	{
		short linknum;
		for (linknum = items[room[item->room_number].item_number].next_item; linknum != -1; linknum = items[linknum].next_item)
		{
			if (linknum == item_num)
			{
				items[linknum].next_item = items[item_num].next_item;
				break;
			}
		}
	}
}

void RemoveActiveItem(short item_num)//41E98, 422EC (F)
{
	if (items[item_num].active)
	{
		items[item_num].active = FALSE;

		if (next_item_active == item_num)
		{
			next_item_active = items[item_num].next_active;
		}
		else if(next_item_active != -1)
		{
			short linknum;
			for (linknum = items[next_item_active].next_active; linknum != -1; linknum = items[linknum].next_active)
			{
				if (linknum == item_num)
				{
					items[linknum].next_active = items[item_num].next_active;
					break;
				}
			}
		}
	}
}

void InitialiseItem(short item_num)//41BEC(<), 42040 (F)
{
	struct ITEM_INFO* item;
	struct room_info* r;
	struct FLOOR_INFO* floor;

	item = &items[item_num];
	item->anim_number = objects[item->object_number].anim_index;
	item->frame_number = anims[item->anim_number].frame_base;

	item->required_anim_state = 0;
	item->goal_anim_state = anims[item->anim_number].current_anim_state;
	item->current_anim_state = anims[item->anim_number].current_anim_state;

	item->pos.z_rot = 0;
	item->pos.x_rot = 0;

	item->fallspeed = 0;
	item->speed = 0;

	item->item_flags[3] = 0;
	item->item_flags[2] = 0;
	item->item_flags[1] = 0;
	item->item_flags[0] = 0;

	item->active = FALSE;
	item->status = ITEM_INACTIVE;
	item->gravity_status = FALSE;
	item->hit_status = FALSE;
	item->collidable = TRUE;
	item->looked_at = FALSE;
	item->dynamic_light = FALSE;
	item->poisoned = FALSE;
	item->ai_bits = 0;
	item->really_active = FALSE;

	item->timer = 0;

	item->hit_points = objects[item->object_number].hit_points;

	if (item->object_number == HK_ITEM ||
		item->object_number == HK_AMMO_ITEM ||
		item->object_number == CROSSBOW_ITEM ||
		item->object_number == REVOLVER_ITEM)
	{
		item->mesh_bits = 1;
	}
	else
	{
		item->mesh_bits = 0xFFFFFFFF;
	}

	item->touch_bits = 0;
	item->after_death = 0;
	item->fired_weapon = 0;
	item->data = NULL;

	if (item->flags & IFLAG_INVISIBLE)
	{
		item->flags &= ~IFLAG_INVISIBLE;
		item->status = ITEM_INVISIBLE;
	}
	else if (objects[item->object_number].intelligent)
	{
		item->status = ITEM_INVISIBLE;
	}

	if ((item->flags & IFLAG_ACTIVATION_MASK) == IFLAG_ACTIVATION_MASK)
	{
		item->flags &= ~IFLAG_ACTIVATION_MASK;
		item->flags |= IFLAG_REVERSE;
		AddActiveItem(item_num);
		item->status = ITEM_ACTIVE;
	}

	r = &room[item->room_number];

	item->next_item = r->item_number;
	r->item_number = item_num;

	floor = &r->floor[((item->pos.z_pos - r->z) / SECTOR(1)) + (((item->pos.x_pos - r->x) / SECTOR(1)) * r->x_size)];

	item->floor = floor->floor * 256;
	item->box_number = floor->box;

	if (objects[item->object_number].initialise != NULL)
	{
		objects[item->object_number].initialise(item_num);
	}

	item->il.Light[3].pad = 0;

#if PC_VERSION
	S_Warn("[InitialiseItem] - Unimplemented end of function!\n");
#endif
}

short CreateItem()//41BAC(<), 42000(<) (F)
{
	short item_num = 0;

	if (next_item_free == -1) return -1;

	item_num = next_item_free;
	items[next_item_free].flags = 0;
	next_item_free = items[next_item_free].next_item;

	return item_num;
}

void KillItem(short item_num)//41950, 41DA4 (F)
{
	if (InItemControlLoop)
	{
		ItemNewRooms[ItemNewRoomNo][0] = item_num | 0x8000;
		ItemNewRoomNo++;
	}
	else
	{
		struct ITEM_INFO* item = &items[item_num];

		DetatchSpark(item_num, 128);

		item->active = FALSE;
		item->really_active = FALSE;

		if (next_item_active == item_num)
		{
			next_item_active = item->next_active;
		}
		else if (next_item_active != -1)
		{
			short linknum;
			for (linknum = items[next_item_active].next_active; linknum != -1; linknum = items[linknum].next_active)
			{
				if (linknum == item_num)
				{
					items[linknum].next_active = item->next_active;
					break;
				}
			}
		}

		if (item->room_number != 255)
		{
			if (room[item->room_number].item_number == item_num)
			{
				room[item->room_number].item_number = item->next_item;
			}
			else if (room[item->room_number].item_number != -1)
			{
				short linknum;
				for (linknum = items[room[item->room_number].item_number].next_item; linknum != -1; linknum = items[linknum].next_item)
				{
					if (linknum == item_num)
					{
						items[room[item->room_number].item_number].next_item = item->next_item;
						break;
					}
				}
			}
		}

		if (item == lara.target)
		{
			lara.target = NULL;
		}

		if (item_num >= level_items)
		{
			item->next_item = next_item_free;
			next_item_free = item_num;
		}
		else
		{
			item->flags |= IFLAG_KILLED;
		}
	}
}

void InitialiseItemArray(int numitems)//418E8(<), 41D3C(<) (F)
{
	int i;
	struct ITEM_INFO* item;

	item = &items[level_items];
	next_item_active = -1;
	next_item_free = level_items;

	if (level_items + 1 < numitems)
	{
		for (i = level_items + 1; i < numitems; i++, item++)
		{
			item->next_item = i;
			item->active = FALSE;
		}
	}

	item->next_item = -1;
	return;
}

void ItemNewRoom(short item_num, short room_number)//7C608(<), 7E64C(<) (F)
{
	if (InItemControlLoop)
	{
		ItemNewRooms[ItemNewRoomNo][0] = item_num;
		ItemNewRooms[ItemNewRoomNo][1] = room_number;
		ItemNewRoomNo++;
	}
	else
	{
		struct ITEM_INFO* item = &items[item_num];

		if (item->room_number != 255)
		{
			struct room_info* r = &room[item->room_number];

			if (r->item_number == item_num)
			{
				r->item_number = item->next_item;
			}
			else if (r->item_number != -1)
			{
				short linknum;
				for (linknum = items[r->item_number].next_item; linknum != -1; linknum = items[linknum].next_item)
				{
					if (linknum == item_num)
					{
						items[r->item_number].next_item = item->next_item;
						break;
					}
				}
			}
		}

		item->room_number = room_number;
		item->next_item = room[room_number].item_number;
		room[room_number].item_number = item_num;
	}
}
<commit_msg>impl end of function<commit_after>#include "ITEMS.H"

#include "CONTROL.H"
#include "DRAW.H"
#include "OBJECTS.H"
#ifdef PC_VERSION
#include "GAME.H"
#include "INIT.H"
#else
#include "SETUP.H"
#endif
#include "SPECIFIC.H"
#include "SPECTYPES.H"
#include <stddef.h>
#include <assert.h>
#include "EFFECTS.H"
#include "MALLOC.H"
#include "EFFECT2.H"
#include "LARA.H"

int level_items;
short next_item_free;
short next_item_active;
short GlobalPulleyFrigItem;

void EffectNewRoom(short fx_num, short room_number)//42320, 42774 (F)
{
	if(InItemControlLoop)
	{
		ItemNewRooms[ItemNewRoomNo][0] = fx_num;
		ItemNewRooms[ItemNewRoomNo][1] = room_number;
		ItemNewRoomNo++;
	}
	else
	{
		struct FX_INFO* fx = &effects[fx_num];
		struct room_info* r = &room[fx->room_number];

		if (r->fx_number == fx_num)
		{
			r->fx_number = fx->next_fx;
		}
		else if(r->fx_number != -1)
		{
			short linknum;
			for (linknum = effects[r->fx_number].next_fx; linknum != -1; linknum = effects[linknum].next_fx)
			{
				if (linknum == fx_num)
				{
					effects[r->fx_number].next_fx = fx->next_fx;
					break;
				}
			}
		}

		fx->room_number = room_number;
		fx->next_fx = room[room_number].fx_number;
		room[room_number].fx_number = fx_num;
	}
}

void KillEffect(short fx_num)//42178, 425CC (F)
{
	if (InItemControlLoop)
	{
		ItemNewRooms[ItemNewRoomNo][0] = fx_num | 0x8000;
		ItemNewRoomNo++;
	}
	else
	{
		struct FX_INFO* fx = &effects[fx_num];

		DetatchSpark(fx_num, 128);

		if (next_fx_active == fx_num)
		{
			next_fx_active = fx->next_active;
		}
		else if (next_fx_active != -1)
		{
			short linknum;
			for (linknum = effects[next_fx_active].next_active; linknum != -1; linknum = effects[linknum].next_active)
			{
				if (linknum == fx_num)
				{
					effects[linknum].next_active = fx->next_active;
					break;
				}
			}
		}

		if (room[fx->room_number].fx_number == fx_num)
		{
			room[fx->room_number].fx_number = fx->next_fx;
		}
		else if (room[fx->room_number].fx_number != -1)
		{
			short linknum;
			for (linknum = effects[room[fx->room_number].fx_number].next_fx; linknum != -1; linknum = effects[linknum].next_fx)
			{
				if (linknum == fx_num)
				{
					effects[room[fx->room_number].fx_number].next_fx = fx->next_fx;
					break;
				}
			}
		}

		fx->next_fx = next_fx_free;
		next_fx_free = fx_num;
	}
}

short CreateEffect(short room_num)//420E0(<), 42534(<) (F)
{
	struct room_info* r;
	struct FX_INFO* fx;
	short fx_num = next_fx_free;

	if (next_fx_free != -1)
	{
		fx = &effects[next_fx_free];
		next_fx_free = fx->object_number;
		r = &room[room_num];
		fx->room_number = room_num;
		fx->next_fx = r->fx_number;
		r->fx_number = fx_num;
		fx->next_active = next_fx_active;
		next_fx_active = fx_num;
		fx->shade = GRAY555;
	}

	return fx_num;
}

void InitialiseFXArray(int allocmem)//4207C(<), 424D0(<) (F)
{
	int i;
	struct FX_INFO* fx;

	if (allocmem)
		effects = (struct FX_INFO*)game_malloc(24 * sizeof(struct FX_INFO));

	fx = effects;
	next_fx_active = -1;
	next_fx_free = 0;
	for (i = 1; i <= 24; i++)
	{
		fx->next_fx = i++;
		++fx;
	}
	fx->next_fx = -1;
}

void AddActiveItem(short item_num)//41FEC(<), 42440(<) (F)
{
	struct ITEM_INFO* item;

	item = &items[item_num];

	item->flags |= 0x20;

	if (objects[item->object_number].control == NULL)//Bug: Always zero due to incomplete level data relocation
	{
		item->status = ITEM_INACTIVE;
		return;
	}

	if (!item->active)
	{
		item->active = TRUE;
		item->next_active = next_item_active;
		next_item_active = item_num;
	}
}

void RemoveDrawnItem(short item_num)//41F48, 4239C (F)
{
	struct ITEM_INFO* item = &items[item_num];

	if (room[item->room_number].item_number == item_num)
	{
		room[item->room_number].item_number = item->next_item;
	}
	else if (room[item->room_number].item_number != -1)
	{
		short linknum;
		for (linknum = items[room[item->room_number].item_number].next_item; linknum != -1; linknum = items[linknum].next_item)
		{
			if (linknum == item_num)
			{
				items[linknum].next_item = items[item_num].next_item;
				break;
			}
		}
	}
}

void RemoveActiveItem(short item_num)//41E98, 422EC (F)
{
	if (items[item_num].active)
	{
		items[item_num].active = FALSE;

		if (next_item_active == item_num)
		{
			next_item_active = items[item_num].next_active;
		}
		else if(next_item_active != -1)
		{
			short linknum;
			for (linknum = items[next_item_active].next_active; linknum != -1; linknum = items[linknum].next_active)
			{
				if (linknum == item_num)
				{
					items[linknum].next_active = items[item_num].next_active;
					break;
				}
			}
		}
	}
}

void InitialiseItem(short item_num)//41BEC(<), 42040 (F)
{
	struct ITEM_INFO* item;
	struct room_info* r;
	struct FLOOR_INFO* floor;

	item = &items[item_num];
	item->anim_number = objects[item->object_number].anim_index;
	item->frame_number = anims[item->anim_number].frame_base;

	item->required_anim_state = 0;
	item->goal_anim_state = anims[item->anim_number].current_anim_state;
	item->current_anim_state = anims[item->anim_number].current_anim_state;

	item->pos.z_rot = 0;
	item->pos.x_rot = 0;

	item->fallspeed = 0;
	item->speed = 0;

	item->item_flags[3] = 0;
	item->item_flags[2] = 0;
	item->item_flags[1] = 0;
	item->item_flags[0] = 0;

	item->active = FALSE;
	item->status = ITEM_INACTIVE;
	item->gravity_status = FALSE;
	item->hit_status = FALSE;
	item->collidable = TRUE;
	item->looked_at = FALSE;
	item->dynamic_light = FALSE;
	item->poisoned = FALSE;
	item->ai_bits = 0;
	item->really_active = FALSE;

	item->timer = 0;

	item->hit_points = objects[item->object_number].hit_points;

	if (item->object_number == HK_ITEM ||
		item->object_number == HK_AMMO_ITEM ||
		item->object_number == CROSSBOW_ITEM ||
		item->object_number == REVOLVER_ITEM)
	{
		item->mesh_bits = 1;
	}
	else
	{
		item->mesh_bits = 0xFFFFFFFF;
	}

	item->touch_bits = 0;
	item->after_death = 0;
	item->fired_weapon = 0;
	item->data = NULL;

	if (item->flags & IFLAG_INVISIBLE)
	{
		item->flags &= ~IFLAG_INVISIBLE;
		item->status = ITEM_INVISIBLE;
	}
	else if (objects[item->object_number].intelligent)
	{
		item->status = ITEM_INVISIBLE;
	}

	if ((item->flags & IFLAG_ACTIVATION_MASK) == IFLAG_ACTIVATION_MASK)
	{
		item->flags &= ~IFLAG_ACTIVATION_MASK;
		item->flags |= IFLAG_REVERSE;
		AddActiveItem(item_num);
		item->status = ITEM_ACTIVE;
	}

	r = &room[item->room_number];

	item->next_item = r->item_number;
	r->item_number = item_num;

	floor = &r->floor[((item->pos.z_pos - r->z) / SECTOR(1)) + (((item->pos.x_pos - r->x) / SECTOR(1)) * r->x_size)];

	item->floor = floor->floor * 256;
	item->box_number = floor->box;

	if (objects[item->object_number].initialise != NULL)
	{
		objects[item->object_number].initialise(item_num);
	}

#if PSXENGINE
	item->il.Light[3].pad = 0;
#endif

#if PC_VERSION
	item->il.room_num = -1;
	item->light_room_num = -1;

	item->unk_thing = 0;

	item->num_lights_1 = 0;
	item->num_lights_2 = 0;

	item->il.room_ambient = r->ambient;

	item->ptr_lights_1 = item->lights_1;
	item->ptr_lights_2 = item->lights_2;
#endif
}

short CreateItem()//41BAC(<), 42000(<) (F)
{
	short item_num = 0;

	if (next_item_free == -1) return -1;

	item_num = next_item_free;
	items[next_item_free].flags = 0;
	next_item_free = items[next_item_free].next_item;

	return item_num;
}

void KillItem(short item_num)//41950, 41DA4 (F)
{
	if (InItemControlLoop)
	{
		ItemNewRooms[ItemNewRoomNo][0] = item_num | 0x8000;
		ItemNewRoomNo++;
	}
	else
	{
		struct ITEM_INFO* item = &items[item_num];

		DetatchSpark(item_num, 128);

		item->active = FALSE;
		item->really_active = FALSE;

		if (next_item_active == item_num)
		{
			next_item_active = item->next_active;
		}
		else if (next_item_active != -1)
		{
			short linknum;
			for (linknum = items[next_item_active].next_active; linknum != -1; linknum = items[linknum].next_active)
			{
				if (linknum == item_num)
				{
					items[linknum].next_active = item->next_active;
					break;
				}
			}
		}

		if (item->room_number != 255)
		{
			if (room[item->room_number].item_number == item_num)
			{
				room[item->room_number].item_number = item->next_item;
			}
			else if (room[item->room_number].item_number != -1)
			{
				short linknum;
				for (linknum = items[room[item->room_number].item_number].next_item; linknum != -1; linknum = items[linknum].next_item)
				{
					if (linknum == item_num)
					{
						items[room[item->room_number].item_number].next_item = item->next_item;
						break;
					}
				}
			}
		}

		if (item == lara.target)
		{
			lara.target = NULL;
		}

		if (item_num >= level_items)
		{
			item->next_item = next_item_free;
			next_item_free = item_num;
		}
		else
		{
			item->flags |= IFLAG_KILLED;
		}
	}
}

void InitialiseItemArray(int numitems)//418E8(<), 41D3C(<) (F)
{
	int i;
	struct ITEM_INFO* item;

	item = &items[level_items];
	next_item_active = -1;
	next_item_free = level_items;

	if (level_items + 1 < numitems)
	{
		for (i = level_items + 1; i < numitems; i++, item++)
		{
			item->next_item = i;
			item->active = FALSE;
		}
	}

	item->next_item = -1;
	return;
}

void ItemNewRoom(short item_num, short room_number)//7C608(<), 7E64C(<) (F)
{
	if (InItemControlLoop)
	{
		ItemNewRooms[ItemNewRoomNo][0] = item_num;
		ItemNewRooms[ItemNewRoomNo][1] = room_number;
		ItemNewRoomNo++;
	}
	else
	{
		struct ITEM_INFO* item = &items[item_num];

		if (item->room_number != 255)
		{
			struct room_info* r = &room[item->room_number];

			if (r->item_number == item_num)
			{
				r->item_number = item->next_item;
			}
			else if (r->item_number != -1)
			{
				short linknum;
				for (linknum = items[r->item_number].next_item; linknum != -1; linknum = items[linknum].next_item)
				{
					if (linknum == item_num)
					{
						items[r->item_number].next_item = item->next_item;
						break;
					}
				}
			}
		}

		item->room_number = room_number;
		item->next_item = room[room_number].item_number;
		room[room_number].item_number = item_num;
	}
}
<|endoftext|>


<commit_before>Int_t LoadLib(const TString &libName)
{
  return gSystem->Load(libName);
}
<commit_msg>AliPhysics libraries might need system libraries<commit_after>Int_t LoadLib(const TString &libName)
{
  if (libName.Contains("PWGPP") ||
      libName.Contains("PWGUDdiffractive")) {
    // Might need system-installed libraries (e.g. libzmq.so)
    gSystem->AddDynamicPath("/lib:/lib64:/usr/lib:/usr/lib64:/usr/local/lib:/usr/local/lib64:/usr/lib/x86_64-linux-gnu");
  }

  return gSystem->Load(libName);
}
<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "Copyright (c) 2012-2013 Tokutek Inc.  All rights reserved."
#ident "$Id$"

#include "backup_debug.h"
#include <stdio.h>

namespace HotBackup {

// TODO: Set each flag with getenv...
int BACKUP_TRACE_FLAGS = 0x0F;
int BACKUP_WARN_FLAGS = 0x0F;
int BACKUP_ERROR_FLAGS = 0x0F;

void CopyTrace(const char *s, const char *arg)
{
    if(BACKUP_TRACE_FLAGS & COPY_FLAG) {
        printf("TRACE: <COPY> %s %s\n", s, arg);
    }
}

void CopyWarn(const char *s, const char *arg)
{
    if(BACKUP_WARN_FLAGS & COPY_FLAG) {
        printf("WARN: <COPY> %s %s\n", s, arg);
    }
}

void CopyError(const char *s, const char *arg)
{
    if(BACKUP_ERROR_FLAGS & COPY_FLAG) {
        printf("ERROR: <COPY> %s %s\n", s, arg);
    }
}

void CaptureTrace(const char *s, const char *arg)
{
    if(BACKUP_TRACE_FLAGS & CAPUTRE_FLAG) {
        printf("TRACE: <CAPTURE> %s %s\n", s, arg);
    }
}

void CaptureTrace(const char *s, const int arg)
{
    if(BACKUP_TRACE_FLAGS & CAPUTRE_FLAG) {
        printf("TRACE: <CAPTURE> %s %d\n", s, arg);
    }
}

void CaptureWarn(const char *s, const char *arg)
{
    if(BACKUP_WARN_FLAGS & CAPUTRE_FLAG) {
        printf("WARN: <CAPTURE> %s %s\n", s, arg);
    }
}

void CaptureError(const char *s, const char *arg)
{
    if(BACKUP_ERROR_FLAGS & CAPUTRE_FLAG) {
        printf("ERROR: <CAPTURE> %s %s\n", s, arg);
    }
}

void CaptureError(const char *s, const int arg)
{
    if(BACKUP_ERROR_FLAGS & CAPUTRE_FLAG) {
        printf("ERROR: <CAPTURE> %s %d\n", s, arg);
    }
}

void InterposeTrace(const char *s, const char *arg)
{
    if(BACKUP_TRACE_FLAGS & INTERPOSE_FLAG) {
        printf("TRACE: <INTERPOSE> %s %s\n", s, arg);
    }
}

void InterposeTrace(const char *s, const int arg)
{
    if(BACKUP_TRACE_FLAGS & INTERPOSE_FLAG) {
        printf("TRACE: <INTERPOSE> %s %d\n", s, arg);
    }
}

void InterposeWarn(const char *s, const char *arg)
{
    if(BACKUP_WARN_FLAGS & INTERPOSE_FLAG) {
        printf("WARN: <INTERPOSE> %s %s\n", s, arg);
    }
}

void InterposeError(const char *s, const char *arg)
{
    if(BACKUP_ERROR_FLAGS & INTERPOSE_FLAG) {
        printf("ERROR: <INTERPOSE> %s %s\n", s, arg);
    }
}

static int PAUSE_POINTS = 0x00;

bool should_pause(int flag)
{
    bool result = false;
    switch (flag) {
        case COPIER_BEFORE_READ:
            result = COPIER_BEFORE_READ & PAUSE_POINTS;
            break;
        case COPIER_AFTER_READ_BEFORE_WRITE:
            result = COPIER_AFTER_READ_BEFORE_WRITE & PAUSE_POINTS;
            break;
        case COPIER_AFTER_WRITE:
            result = COPIER_AFTER_WRITE & PAUSE_POINTS;
            break;
        case MANAGER_IN_PREPARE:
            result = MANAGER_IN_PREPARE;
            break;
        case MANAGER_IN_DISABLE:
            result = MANAGER_IN_DISABLE;
            break;
        default:
            break;
    }

    return result;
}

void toggle_pause_point(int flag)
{
    PAUSE_POINTS = PAUSE_POINTS ^ flag;
}

} // End of namespace.

<commit_msg>Fixes #6510.  Add helgrind anotatoin to {{{PAUSE_POINT}}}.<commit_after>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "Copyright (c) 2012-2013 Tokutek Inc.  All rights reserved."
#ident "$Id$"

#include "backup_debug.h"
#include <stdio.h>
#include <valgrind/helgrind.h>

namespace HotBackup {

// TODO: Set each flag with getenv...
int BACKUP_TRACE_FLAGS = 0x0F;
int BACKUP_WARN_FLAGS = 0x0F;
int BACKUP_ERROR_FLAGS = 0x0F;

void CopyTrace(const char *s, const char *arg)
{
    if(BACKUP_TRACE_FLAGS & COPY_FLAG) {
        printf("TRACE: <COPY> %s %s\n", s, arg);
    }
}

void CopyWarn(const char *s, const char *arg)
{
    if(BACKUP_WARN_FLAGS & COPY_FLAG) {
        printf("WARN: <COPY> %s %s\n", s, arg);
    }
}

void CopyError(const char *s, const char *arg)
{
    if(BACKUP_ERROR_FLAGS & COPY_FLAG) {
        printf("ERROR: <COPY> %s %s\n", s, arg);
    }
}

void CaptureTrace(const char *s, const char *arg)
{
    if(BACKUP_TRACE_FLAGS & CAPUTRE_FLAG) {
        printf("TRACE: <CAPTURE> %s %s\n", s, arg);
    }
}

void CaptureTrace(const char *s, const int arg)
{
    if(BACKUP_TRACE_FLAGS & CAPUTRE_FLAG) {
        printf("TRACE: <CAPTURE> %s %d\n", s, arg);
    }
}

void CaptureWarn(const char *s, const char *arg)
{
    if(BACKUP_WARN_FLAGS & CAPUTRE_FLAG) {
        printf("WARN: <CAPTURE> %s %s\n", s, arg);
    }
}

void CaptureError(const char *s, const char *arg)
{
    if(BACKUP_ERROR_FLAGS & CAPUTRE_FLAG) {
        printf("ERROR: <CAPTURE> %s %s\n", s, arg);
    }
}

void CaptureError(const char *s, const int arg)
{
    if(BACKUP_ERROR_FLAGS & CAPUTRE_FLAG) {
        printf("ERROR: <CAPTURE> %s %d\n", s, arg);
    }
}

void InterposeTrace(const char *s, const char *arg)
{
    if(BACKUP_TRACE_FLAGS & INTERPOSE_FLAG) {
        printf("TRACE: <INTERPOSE> %s %s\n", s, arg);
    }
}

void InterposeTrace(const char *s, const int arg)
{
    if(BACKUP_TRACE_FLAGS & INTERPOSE_FLAG) {
        printf("TRACE: <INTERPOSE> %s %d\n", s, arg);
    }
}

void InterposeWarn(const char *s, const char *arg)
{
    if(BACKUP_WARN_FLAGS & INTERPOSE_FLAG) {
        printf("WARN: <INTERPOSE> %s %s\n", s, arg);
    }
}

void InterposeError(const char *s, const char *arg)
{
    if(BACKUP_ERROR_FLAGS & INTERPOSE_FLAG) {
        printf("ERROR: <INTERPOSE> %s %s\n", s, arg);
    }
}

static int PAUSE_POINTS = 0x00;

bool should_pause(int flag)
{
    bool result = false;
    switch (flag) {
        case COPIER_BEFORE_READ:
            result = COPIER_BEFORE_READ & PAUSE_POINTS;
            break;
        case COPIER_AFTER_READ_BEFORE_WRITE:
            result = COPIER_AFTER_READ_BEFORE_WRITE & PAUSE_POINTS;
            break;
        case COPIER_AFTER_WRITE:
            result = COPIER_AFTER_WRITE & PAUSE_POINTS;
            break;
        case MANAGER_IN_PREPARE:
            result = MANAGER_IN_PREPARE;
            break;
        case MANAGER_IN_DISABLE:
            result = MANAGER_IN_DISABLE;
            break;
        default:
            break;
    }

    return result;
}

void toggle_pause_point(int flag)
{
    VALGRIND_HG_DISABLE_CHECKING(&PAUSE_POINTS, sizeof(PAUSE_POINTS));
    PAUSE_POINTS = PAUSE_POINTS ^ flag;
}

} // End of namespace.

<|endoftext|>


<commit_before># pragma once
# include <Siv3D.hpp>
# include "AscChoiceManager.hpp"
# include "AscMessageManager.hpp"
# include "AscSpriteManager.hpp"

namespace asc
{
	using namespace s3d;

	using Commnad = std::pair<int32, String>;

	class Novel
	{
	private:

		bool m_isUpdating;

		int32 m_currentLine;

		Array<Commnad> m_commands;

		ChoiceManager m_choiceManager;

		MessageManager m_messageManager;

		SpriteManager m_spriteManager;

		void clearManager()
		{
			m_messageManager.clear();
			m_spriteManager.clear();
			m_choiceManager.clear();
		}

		void execute()
		{
			switch (m_commands[m_currentLine].first)
			{
			// Point
			case 0:
				m_isUpdating = false;
				return;

			// Text
			case 1:
				m_messageManager.setText(m_commands[m_currentLine].second);
				m_messageManager.start();
				break;

			// Name
			case 2:
				m_messageManager.setName(m_commands[m_currentLine].second);
				break;

			// AddSprite
			case 3:
				m_spriteManager.add<Sprite>(m_commands[m_currentLine].second);
				break;

			// AddFixedSprite
			case 4:
				m_spriteManager.add<FixedSprite>(m_commands[m_currentLine].second);
				break;

			// Choice
			case 5:
				m_choiceManager.start(m_commands[m_currentLine].second);
				break;

			default:
				break;
			}

			m_currentLine++;
		}

	public:

		Novel() :
			m_isUpdating(false),
			m_currentLine(0)
		{
			m_commands.push_back({ 0, L"1"});
			m_commands.push_back({ 3, L"1,character1,0,0,640,720" });
			m_commands.push_back({ 3, L"3,character3,480,180,320,360" });
			m_commands.push_back({ 1, L"Characters" });
			m_commands.push_back({ 0, L"2" });
			m_commands.push_back({ 1, L"Only Text" });
			m_commands.push_back({ 0, L"3" });
			m_commands.push_back({ 1, L"Show Character?" });
			m_commands.push_back({ 5, L"1,Yes,2,No" });
			m_commands.push_back({ 0, L"4" });
			m_commands.push_back({ 1, L"Jump 2" });
			m_commands.push_back({ 7, L"2" });
			m_commands.push_back({ 0, L"-1" });
		}

		virtual ~Novel() = default;

		bool start(int32 seekPoint)
		{
			const auto size = m_commands.size() - 1;
			for (auto i = 0u; i < size; i++)
			{
				const auto index = (m_currentLine + i) % m_commands.size();

				const auto command = m_commands[index];
				if (
					command.first == 0 &&
					Parse<int32>(command.second) == seekPoint
				)
				{
					clearManager();
					m_currentLine = index + 1;
					m_isUpdating = true;

					return true;
				}
			}

			return false;
		}

		void update()
		{
			while (
				m_isUpdating &&
				!m_messageManager.isUpdating() &&
				!m_choiceManager.isUpdating()
			)
			{
				execute();
			}

			m_messageManager.update();
			m_choiceManager.update();
		}

		bool isUpdating() const
		{
			return m_isUpdating;
		}

		void draw() const
		{
			m_spriteManager.draw();
			m_messageManager.draw();
			m_choiceManager.draw();
		}
	};
}<commit_msg>Implement Jump.<commit_after># pragma once
# include <Siv3D.hpp>
# include "AscChoiceManager.hpp"
# include "AscMessageManager.hpp"
# include "AscSpriteManager.hpp"

namespace asc
{
	using namespace s3d;

	using Commnad = std::pair<int32, String>;

	class Novel
	{
	private:

		bool m_isUpdating;

		int32 m_currentLine;

		Array<Commnad> m_commands;

		ChoiceManager m_choiceManager;

		MessageManager m_messageManager;

		SpriteManager m_spriteManager;

		void clearManager()
		{
			m_messageManager.clear();
			m_spriteManager.clear();
			m_choiceManager.clear();
		}

		void execute()
		{
			switch (m_commands[m_currentLine].first)
			{
			// Point
			case 0:
				m_isUpdating = false;
				return;

			// Text
			case 1:
				m_messageManager.setText(m_commands[m_currentLine].second);
				m_messageManager.start();
				break;

			// Name
			case 2:
				m_messageManager.setName(m_commands[m_currentLine].second);
				break;

			// AddSprite
			case 3:
				m_spriteManager.add<Sprite>(m_commands[m_currentLine].second);
				break;

			// AddFixedSprite
			case 4:
				m_spriteManager.add<FixedSprite>(m_commands[m_currentLine].second);
				break;

			// Choice
			case 5:
				m_choiceManager.start(m_commands[m_currentLine].second);
				break;

			// Jump
			case 7:
				start(Parse<int32>(m_commands[m_currentLine].second));
				return;

			default:
				break;
			}

			m_currentLine++;
		}

	public:

		Novel() :
			m_isUpdating(false),
			m_currentLine(0)
		{
			m_commands.push_back({ 0, L"1"});
			m_commands.push_back({ 3, L"1,character1,0,0,640,720" });
			m_commands.push_back({ 3, L"3,character3,480,180,320,360" });
			m_commands.push_back({ 1, L"Characters" });
			m_commands.push_back({ 0, L"2" });
			m_commands.push_back({ 1, L"Only Text" });
			m_commands.push_back({ 0, L"3" });
			m_commands.push_back({ 1, L"Show Character?" });
			m_commands.push_back({ 5, L"1,Yes,2,No" });
			m_commands.push_back({ 0, L"4" });
			m_commands.push_back({ 1, L"Jump 2" });
			m_commands.push_back({ 7, L"2" });
			m_commands.push_back({ 0, L"-1" });
		}

		virtual ~Novel() = default;

		bool start(int32 seekPoint)
		{
			const auto size = m_commands.size() - 1;
			for (auto i = 0u; i < size; i++)
			{
				const auto index = (m_currentLine + i) % m_commands.size();

				const auto command = m_commands[index];
				if (
					command.first == 0 &&
					Parse<int32>(command.second) == seekPoint
				)
				{
					clearManager();
					m_currentLine = index + 1;
					m_isUpdating = true;

					return true;
				}
			}

			return false;
		}

		void update()
		{
			while (
				m_isUpdating &&
				!m_messageManager.isUpdating() &&
				!m_choiceManager.isUpdating()
			)
			{
				execute();
			}

			m_messageManager.update();
			m_choiceManager.update();
		}

		bool isUpdating() const
		{
			return m_isUpdating;
		}

		void draw() const
		{
			m_spriteManager.draw();
			m_messageManager.draw();
			m_choiceManager.draw();
		}
	};
}<|endoftext|>


<commit_before>// Copyright AudioKit. All Rights Reserved. Revision History at http://github.com/AudioKit/AudioKit/

#pragma once

#import <AVFoundation/AVFoundation.h>
#import "AKInterop.h"

typedef NS_ENUM(AUParameterAddress, AKSequencerEngineParameter) {
    AKSequencerEngineParameterTempo,
    AKSequencerEngineParameterLength,
    AKSequencerEngineParameterMaximumPlayCount,
    AKSequencerEngineParameterPosition,
    AKSequencerEngineParameterLoopEnabled
};

AK_API AKDSPRef createAKSequencerEngineDSP(void);

#ifndef __cplusplus

void sequencerEngineAddMIDIEvent(AKDSPRef dsp, uint8_t status, uint8_t data1, uint8_t data2, double beat);
void sequencerEngineAddMIDINote(AKDSPRef dsp, uint8_t noteNumber, uint8_t velocity, double beat, double duration);
void sequencerEngineRemoveMIDIEvent(AKDSPRef dsp, double beat);
void sequencerEngineRemoveMIDINote(AKDSPRef dsp, double beat);
void sequencerEngineRemoveSpecificMIDINote(AKDSPRef dsp, double beat, uint8_t noteNumber);
void sequencerEngineRemoveAllInstancesOf(AKDSPRef dsp, uint8_t noteNumber);

void sequencerEngineStopPlayingNotes(AKDSPRef dsp);
void sequencerEngineClear(AKDSPRef dsp);

void sequencerEngineSetAUTarget(AKDSPRef dsp, AudioUnit audioUnit);

#else

#include "AKDSPBase.hpp"
#include <vector>
#include <stdio.h>

#define NOTEON 0x90
#define NOTEOFF 0x80

class AKSequencerEngineDSP : public AKDSPBase {

    struct MIDIEvent {
        uint8_t status;
        uint8_t data1;
        uint8_t data2;
        double beat;
    };

    struct MIDINote {
        struct MIDIEvent noteOn;
        struct MIDIEvent noteOff;
    };

public:

    AKSequencerEngineDSP() {}

    void setTargetAU(AudioUnit target) {
        targetAU = target;
    }

    void seekTo(double position) {
        positionInSamples = beatToSamples(position);
    }

    void setTempo(double newValue) {
        double lastPosition = currentPositionInBeats(); // 1) save where we are before we manipulate time
        tempo = newValue;                               // 2) manipulate time
        seekTo(lastPosition);                           // 3) go back to where we were before time manipulation
    }

    void setStartPoint(float value) {
        startPoint = value;
    }

    void addPlayingNote(MIDINote note, int offset) {
        if (note.noteOn.data2 > 0) {
            sendMidiData(note.noteOn.status, note.noteOn.data1, note.noteOn.data2, offset, note.noteOn.beat);
            playingNotes.push_back(note);
        } else {
            sendMidiData(note.noteOff.status, note.noteOff.data1, note.noteOff.data2, offset, note.noteOn.beat);
        }
    }

    void stopPlayingNote(MIDINote note, int offset, int index) {
        sendMidiData(note.noteOff.status, note.noteOff.data1, note.noteOff.data2, offset, note.noteOff.beat);
        playingNotes.erase(playingNotes.begin() + index);
    }

    void setParameter(AUParameterAddress address, AUValue value, bool immediate) override {
        switch (address) {
            case AKSequencerEngineParameterTempo:
                setTempo(value);
                break;
            case AKSequencerEngineParameterLength:
                length = value;
                break;
            case AKSequencerEngineParameterMaximumPlayCount:
                maximumPlayCount = value;
                break;
            case AKSequencerEngineParameterPosition:
                seekTo(value);
                break;
            case AKSequencerEngineParameterLoopEnabled:
                loopEnabled = value > 0.5f;
                break;
        }
    }

    AUValue getParameter(AUParameterAddress address) override {
        switch (address) {
            case AKSequencerEngineParameterTempo:
                return tempo;
            case AKSequencerEngineParameterLength:
                return length;
            case AKSequencerEngineParameterMaximumPlayCount:
                return maximumPlayCount;
                break;
            case AKSequencerEngineParameterPosition:
                return currentPositionInBeats();
                break;
            case AKSequencerEngineParameterLoopEnabled:
                return loopEnabled ? 1.f : 0.f;
            default:
                return 0.f;
        }
    }

    void process(AUAudioFrameCount frameCount, AUAudioFrameCount bufferOffset) override {
        if (isStarted) {
            if (positionInSamples >= lengthInSamples()){
                if (!loopEnabled) { //stop if played enough
                    stop();
                    return;
                }
            }
            long currentStartSample = positionModulo();
            long currentEndSample = currentStartSample + frameCount;
            for (int i = 0; i < events.size(); i++) {
                // go through every event
                int triggerTime = beatToSamples(events[i].beat);
                if (currentStartSample <= triggerTime && triggerTime < currentEndSample) {
                    // this event is supposed to trigger between currentStartSample and currentEndSample
                    int offset = (int)(triggerTime - currentStartSample);
                    sendMidiData(events[i].status, events[i].data1, events[i].data2,
                                 offset, events[i].beat);
                } else if (currentEndSample > lengthInSamples() && loopEnabled) {
                    // this buffer extends beyond the length of the loop and looping is on
                    int loopRestartInBuffer = (int)(lengthInSamples() - currentStartSample);
                    int samplesOfBufferForNewLoop = frameCount - loopRestartInBuffer;
                    if (triggerTime < samplesOfBufferForNewLoop) {
                        // this event would trigger early enough in the next loop that it should happen in this buffer
                        // ie. this buffer contains events from the previous loop, and the next loop
                        int offset = (int)triggerTime + loopRestartInBuffer;
                        sendMidiData(events[i].status, events[i].data1, events[i].data2,
                                     offset, events[i].beat);
                    }
                }
            }

            // Check the playing notes for note offs
            int i = 0;
            while (i < playingNotes.size()) {
                int triggerTime = beatToSamples(playingNotes[i].noteOff.beat);
                if (currentStartSample <= triggerTime && triggerTime < currentEndSample) {
                    int offset = (int)(triggerTime - currentStartSample);
                    stopPlayingNote(playingNotes[i], offset, i);
                    continue;
                }

                if (currentEndSample > lengthInSamples() && loopEnabled) {
                    int loopRestartInBuffer = (int)(lengthInSamples() - currentStartSample);
                    int samplesOfBufferForNewLoop = frameCount - loopRestartInBuffer;
                    if (triggerTime < samplesOfBufferForNewLoop) {
                        int offset = (int)triggerTime + loopRestartInBuffer;
                        stopPlayingNote(playingNotes[i], offset, i);
                        continue;
                    }
                }
                i++;
            }

            // Check scheduled notes for note ons
            for (int i = 0; i < notes.size(); i++) {
                int triggerTime = beatToSamples(notes[i].noteOn.beat);
                if (currentStartSample <= triggerTime && triggerTime < currentEndSample) {
                    int offset = (int)(triggerTime - currentStartSample);
                    addPlayingNote(notes[i], offset);
                } else if (currentEndSample > lengthInSamples() && loopEnabled) {
                    int loopRestartInBuffer = (int)(lengthInSamples() - currentStartSample);
                    int samplesOfBufferForNewLoop = frameCount - loopRestartInBuffer;
                    if (triggerTime < samplesOfBufferForNewLoop) {
                        int offset = (int)triggerTime + loopRestartInBuffer;
                        addPlayingNote(notes[i], offset);
                    }
                }
            }

            positionInSamples += frameCount;
        }
        framesCounted += frameCount;
    }

    void removeNoteAt(double beat) {
        for (int i = 0; i < notes.size(); i++) {
            MIDINote note = notes[i];
            if (note.noteOn.beat == beat) {
                notes.erase(notes.begin()+i);
            }
        }
    }

    void removeNoteAt(uint8_t noteToRemove, double beat) {

        for (int i = 0; i < notes.size(); i++) {
            MIDINote note = notes[i];
            if (note.noteOn.beat == beat && note.noteOn.data1 == noteToRemove) {
                notes.erase(notes.begin()+i);
            }
        }
    }

    void removeAllInstancesOf(uint8_t noteToRemove) {

         for (auto itr1 = notes.rbegin(); itr1 < notes.rend(); itr1++) {
             if (itr1->noteOn.data1 == noteToRemove) {
                   notes.erase((itr1 + 1).base());
               }
           }
    }

    void removeEventAt(double beat) {
        for (int i = 0; i < events.size(); i++) {
            MIDIEvent event = events[i];
            if (event.beat == beat) {
                events.erase(events.begin()+i);
            }
        }
    }

    void addMIDIEvent(uint8_t status, uint8_t data1, uint8_t data2, double beat) {
        MIDIEvent newEvent;
        newEvent.status = status;
        newEvent.data1 = data1;
        newEvent.data2 = data2;
        newEvent.beat = beat;
        events.push_back(newEvent);
    }

    void addMIDINote(uint8_t number, uint8_t velocity, double beat, double duration) {
        MIDINote newNote;

        newNote.noteOn.status = NOTEON;
        newNote.noteOn.data1 = number;
        newNote.noteOn.data2 = velocity;
        newNote.noteOn.beat = beat;

        newNote.noteOff.status = NOTEOFF;
        newNote.noteOff.data1 = number;
        newNote.noteOff.data2 = velocity;
        newNote.noteOff.beat = beat + duration;

        notes.push_back(newNote);
    }

    void clear() {
        notes.clear();
        events.clear();
    }

    void stopPlayingNotes() {
        while (playingNotes.size() > 0) {
            stopPlayingNote(playingNotes[0], 0, 0);
        }
    }

    void sendMidiData(UInt8 status, UInt8 data1, UInt8 data2, double offset, double time) {
//        printf("%p: sending: %i %i %i at offset %f (%f beats)\n", &midiEndpoint, status, data1, data2, offset, time);
        if (midiPort == 0 || midiEndpoint == 0) {
            MusicDeviceMIDIEvent(targetAU, status, data1, data2, offset);
        } else {
            MIDIPacketList packetList;
            packetList.numPackets = 1;
            MIDIPacket* firstPacket = &packetList.packet[0];
            firstPacket->length = 3;
            firstPacket->data[0] = status;
            firstPacket->data[1] = data1;
            firstPacket->data[2] = data2;
            firstPacket->timeStamp = offset;
            MIDISend(midiPort, midiEndpoint, &packetList);
        }
    }

    long lengthInSamples() {
        return beatToSamples(length);
    }

    int beatToSamples(double beat) {
        return (int)(beat / tempo * 60 * sampleRate);
    }

    long positionModulo() {
        long length = lengthInSamples();
        if (positionInSamples == 0 || length == 0) {
            return 0;
        } else if (positionInSamples < 0) {
            return positionInSamples;
        } else {
            return positionInSamples % length;
        }
    }

    double currentPositionInBeats() {
        return (double)positionModulo() / sampleRate * (tempo / 60);
    }

    bool validTriggerTime(double beat) {
        return true;
    }

private:

    float startPoint = 0;
    AudioUnit targetAU;
    UInt64 framesCounted = 0;
    long positionInSamples = 0;

public:
    MIDIPortRef midiPort;
    MIDIEndpointRef midiEndpoint;
    std::vector<MIDIEvent> events;
    std::vector<MIDINote> notes;
    std::vector<MIDINote> playingNotes;
    int maximumPlayCount = 0;
    double length = 4.0;
    double tempo = 120.0;
    bool loopEnabled = true;
    uint numberOfLoops = 0;
};

#endif
<commit_msg>Cleanup.<commit_after>// Copyright AudioKit. All Rights Reserved. Revision History at http://github.com/AudioKit/AudioKit/

#pragma once

#import <AVFoundation/AVFoundation.h>
#import "AKInterop.h"

typedef NS_ENUM(AUParameterAddress, AKSequencerEngineParameter) {
    AKSequencerEngineParameterTempo,
    AKSequencerEngineParameterLength,
    AKSequencerEngineParameterMaximumPlayCount,
    AKSequencerEngineParameterPosition,
    AKSequencerEngineParameterLoopEnabled
};

AK_API AKDSPRef createAKSequencerEngineDSP(void);

AK_API void sequencerEngineAddMIDIEvent(AKDSPRef dsp, uint8_t status, uint8_t data1, uint8_t data2, double beat);
AK_API void sequencerEngineAddMIDINote(AKDSPRef dsp, uint8_t noteNumber, uint8_t velocity, double beat, double duration);
AK_API void sequencerEngineRemoveMIDIEvent(AKDSPRef dsp, double beat);
AK_API void sequencerEngineRemoveMIDINote(AKDSPRef dsp, double beat);
AK_API void sequencerEngineRemoveSpecificMIDINote(AKDSPRef dsp, double beat, uint8_t noteNumber);
AK_API void sequencerEngineRemoveAllInstancesOf(AKDSPRef dsp, uint8_t noteNumber);

AK_API void sequencerEngineStopPlayingNotes(AKDSPRef dsp);
AK_API void sequencerEngineClear(AKDSPRef dsp);

AK_API void sequencerEngineSetAUTarget(AKDSPRef dsp, AudioUnit audioUnit);

#ifdef __cplusplus

#include "AKDSPBase.hpp"
#include <vector>
#include <stdio.h>

#define NOTEON 0x90
#define NOTEOFF 0x80

class AKSequencerEngineDSP : public AKDSPBase {

    struct MIDIEvent {
        uint8_t status;
        uint8_t data1;
        uint8_t data2;
        double beat;
    };

    struct MIDINote {
        struct MIDIEvent noteOn;
        struct MIDIEvent noteOff;
    };

public:

    AKSequencerEngineDSP() {}

    void setTargetAU(AudioUnit target) {
        targetAU = target;
    }

    void seekTo(double position) {
        positionInSamples = beatToSamples(position);
    }

    void setTempo(double newValue) {
        double lastPosition = currentPositionInBeats(); // 1) save where we are before we manipulate time
        tempo = newValue;                               // 2) manipulate time
        seekTo(lastPosition);                           // 3) go back to where we were before time manipulation
    }

    void setStartPoint(float value) {
        startPoint = value;
    }

    void addPlayingNote(MIDINote note, int offset) {
        if (note.noteOn.data2 > 0) {
            sendMidiData(note.noteOn.status, note.noteOn.data1, note.noteOn.data2, offset, note.noteOn.beat);
            playingNotes.push_back(note);
        } else {
            sendMidiData(note.noteOff.status, note.noteOff.data1, note.noteOff.data2, offset, note.noteOn.beat);
        }
    }

    void stopPlayingNote(MIDINote note, int offset, int index) {
        sendMidiData(note.noteOff.status, note.noteOff.data1, note.noteOff.data2, offset, note.noteOff.beat);
        playingNotes.erase(playingNotes.begin() + index);
    }

    void setParameter(AUParameterAddress address, AUValue value, bool immediate) override {
        switch (address) {
            case AKSequencerEngineParameterTempo:
                setTempo(value);
                break;
            case AKSequencerEngineParameterLength:
                length = value;
                break;
            case AKSequencerEngineParameterMaximumPlayCount:
                maximumPlayCount = value;
                break;
            case AKSequencerEngineParameterPosition:
                seekTo(value);
                break;
            case AKSequencerEngineParameterLoopEnabled:
                loopEnabled = value > 0.5f;
                break;
        }
    }

    AUValue getParameter(AUParameterAddress address) override {
        switch (address) {
            case AKSequencerEngineParameterTempo:
                return tempo;
            case AKSequencerEngineParameterLength:
                return length;
            case AKSequencerEngineParameterMaximumPlayCount:
                return maximumPlayCount;
                break;
            case AKSequencerEngineParameterPosition:
                return currentPositionInBeats();
                break;
            case AKSequencerEngineParameterLoopEnabled:
                return loopEnabled ? 1.f : 0.f;
            default:
                return 0.f;
        }
    }

    void process(AUAudioFrameCount frameCount, AUAudioFrameCount bufferOffset) override {
        if (isStarted) {
            if (positionInSamples >= lengthInSamples()){
                if (!loopEnabled) { //stop if played enough
                    stop();
                    return;
                }
            }
            long currentStartSample = positionModulo();
            long currentEndSample = currentStartSample + frameCount;
            for (int i = 0; i < events.size(); i++) {
                // go through every event
                int triggerTime = beatToSamples(events[i].beat);
                if (currentStartSample <= triggerTime && triggerTime < currentEndSample) {
                    // this event is supposed to trigger between currentStartSample and currentEndSample
                    int offset = (int)(triggerTime - currentStartSample);
                    sendMidiData(events[i].status, events[i].data1, events[i].data2,
                                 offset, events[i].beat);
                } else if (currentEndSample > lengthInSamples() && loopEnabled) {
                    // this buffer extends beyond the length of the loop and looping is on
                    int loopRestartInBuffer = (int)(lengthInSamples() - currentStartSample);
                    int samplesOfBufferForNewLoop = frameCount - loopRestartInBuffer;
                    if (triggerTime < samplesOfBufferForNewLoop) {
                        // this event would trigger early enough in the next loop that it should happen in this buffer
                        // ie. this buffer contains events from the previous loop, and the next loop
                        int offset = (int)triggerTime + loopRestartInBuffer;
                        sendMidiData(events[i].status, events[i].data1, events[i].data2,
                                     offset, events[i].beat);
                    }
                }
            }

            // Check the playing notes for note offs
            int i = 0;
            while (i < playingNotes.size()) {
                int triggerTime = beatToSamples(playingNotes[i].noteOff.beat);
                if (currentStartSample <= triggerTime && triggerTime < currentEndSample) {
                    int offset = (int)(triggerTime - currentStartSample);
                    stopPlayingNote(playingNotes[i], offset, i);
                    continue;
                }

                if (currentEndSample > lengthInSamples() && loopEnabled) {
                    int loopRestartInBuffer = (int)(lengthInSamples() - currentStartSample);
                    int samplesOfBufferForNewLoop = frameCount - loopRestartInBuffer;
                    if (triggerTime < samplesOfBufferForNewLoop) {
                        int offset = (int)triggerTime + loopRestartInBuffer;
                        stopPlayingNote(playingNotes[i], offset, i);
                        continue;
                    }
                }
                i++;
            }

            // Check scheduled notes for note ons
            for (int i = 0; i < notes.size(); i++) {
                int triggerTime = beatToSamples(notes[i].noteOn.beat);
                if (currentStartSample <= triggerTime && triggerTime < currentEndSample) {
                    int offset = (int)(triggerTime - currentStartSample);
                    addPlayingNote(notes[i], offset);
                } else if (currentEndSample > lengthInSamples() && loopEnabled) {
                    int loopRestartInBuffer = (int)(lengthInSamples() - currentStartSample);
                    int samplesOfBufferForNewLoop = frameCount - loopRestartInBuffer;
                    if (triggerTime < samplesOfBufferForNewLoop) {
                        int offset = (int)triggerTime + loopRestartInBuffer;
                        addPlayingNote(notes[i], offset);
                    }
                }
            }

            positionInSamples += frameCount;
        }
        framesCounted += frameCount;
    }

    void removeNoteAt(double beat) {
        for (int i = 0; i < notes.size(); i++) {
            MIDINote note = notes[i];
            if (note.noteOn.beat == beat) {
                notes.erase(notes.begin()+i);
            }
        }
    }

    void removeNoteAt(uint8_t noteToRemove, double beat) {

        for (int i = 0; i < notes.size(); i++) {
            MIDINote note = notes[i];
            if (note.noteOn.beat == beat && note.noteOn.data1 == noteToRemove) {
                notes.erase(notes.begin()+i);
            }
        }
    }

    void removeAllInstancesOf(uint8_t noteToRemove) {

         for (auto itr1 = notes.rbegin(); itr1 < notes.rend(); itr1++) {
             if (itr1->noteOn.data1 == noteToRemove) {
                   notes.erase((itr1 + 1).base());
               }
           }
    }

    void removeEventAt(double beat) {
        for (int i = 0; i < events.size(); i++) {
            MIDIEvent event = events[i];
            if (event.beat == beat) {
                events.erase(events.begin()+i);
            }
        }
    }

    void addMIDIEvent(uint8_t status, uint8_t data1, uint8_t data2, double beat) {
        MIDIEvent newEvent;
        newEvent.status = status;
        newEvent.data1 = data1;
        newEvent.data2 = data2;
        newEvent.beat = beat;
        events.push_back(newEvent);
    }

    void addMIDINote(uint8_t number, uint8_t velocity, double beat, double duration) {
        MIDINote newNote;

        newNote.noteOn.status = NOTEON;
        newNote.noteOn.data1 = number;
        newNote.noteOn.data2 = velocity;
        newNote.noteOn.beat = beat;

        newNote.noteOff.status = NOTEOFF;
        newNote.noteOff.data1 = number;
        newNote.noteOff.data2 = velocity;
        newNote.noteOff.beat = beat + duration;

        notes.push_back(newNote);
    }

    void clear() {
        notes.clear();
        events.clear();
    }

    void stopPlayingNotes() {
        while (playingNotes.size() > 0) {
            stopPlayingNote(playingNotes[0], 0, 0);
        }
    }

    void sendMidiData(UInt8 status, UInt8 data1, UInt8 data2, double offset, double time) {
//        printf("%p: sending: %i %i %i at offset %f (%f beats)\n", &midiEndpoint, status, data1, data2, offset, time);
        if (midiPort == 0 || midiEndpoint == 0) {
            MusicDeviceMIDIEvent(targetAU, status, data1, data2, offset);
        } else {
            MIDIPacketList packetList;
            packetList.numPackets = 1;
            MIDIPacket* firstPacket = &packetList.packet[0];
            firstPacket->length = 3;
            firstPacket->data[0] = status;
            firstPacket->data[1] = data1;
            firstPacket->data[2] = data2;
            firstPacket->timeStamp = offset;
            MIDISend(midiPort, midiEndpoint, &packetList);
        }
    }

    long lengthInSamples() {
        return beatToSamples(length);
    }

    int beatToSamples(double beat) {
        return (int)(beat / tempo * 60 * sampleRate);
    }

    long positionModulo() {
        long length = lengthInSamples();
        if (positionInSamples == 0 || length == 0) {
            return 0;
        } else if (positionInSamples < 0) {
            return positionInSamples;
        } else {
            return positionInSamples % length;
        }
    }

    double currentPositionInBeats() {
        return (double)positionModulo() / sampleRate * (tempo / 60);
    }

    bool validTriggerTime(double beat) {
        return true;
    }

private:

    float startPoint = 0;
    AudioUnit targetAU;
    UInt64 framesCounted = 0;
    long positionInSamples = 0;

public:
    MIDIPortRef midiPort;
    MIDIEndpointRef midiEndpoint;
    std::vector<MIDIEvent> events;
    std::vector<MIDINote> notes;
    std::vector<MIDINote> playingNotes;
    int maximumPlayCount = 0;
    double length = 4.0;
    double tempo = 120.0;
    bool loopEnabled = true;
    uint numberOfLoops = 0;
};

#endif
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -emit-llvm %s -o -  | FileCheck %s

namespace Common {
enum RenderMode {
  kRenderEGA,
  kRenderCGA
};
class C;
class A {
  A();
  C *_vm;
  unsigned char _highlightColorTableVGA[];
  static const unsigned char b[];
};
class B {
public:
  Common::RenderMode _configRenderMode;
};
class C : public B {};
A::A() {
  0 == Common::kRenderCGA || _vm->_configRenderMode == Common::kRenderEGA
      ? b
      : _highlightColorTableVGA;
// Make sure the PHI value is casted correctly to the PHI type
// CHECK: %cond-lvalue = phi [0 x i8]* [ bitcast ([1 x i8]* @_ZN6Common1A1bE to [0 x i8]*), %cond.true ], [ %_highlightColorTableVGA, %cond.false ]
}
const unsigned char A::b[] = { 0 };
}
<commit_msg>Fix pr19841.cpp on release mode<commit_after>// RUN: %clang_cc1 -emit-llvm %s -o -  | FileCheck %s

namespace Common {
enum RenderMode {
  kRenderEGA,
  kRenderCGA
};
class C;
class A {
  A();
  C *_vm;
  unsigned char _highlightColorTableVGA[];
  static const unsigned char b[];
};
class B {
public:
  Common::RenderMode _configRenderMode;
};
class C : public B {};
A::A() {
  0 == Common::kRenderCGA || _vm->_configRenderMode == Common::kRenderEGA
      ? b
      : _highlightColorTableVGA;
// Make sure the PHI value is casted correctly to the PHI type
// CHECK: %{{.*}} = phi [0 x i8]* [ bitcast ([1 x i8]* @_ZN6Common1A1bE to [0 x i8]*), %cond.true ], [ %{{.*}}, %cond.false ]
}
const unsigned char A::b[] = { 0 };
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: canvascustomsprite.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: obo $ $Date: 2007-07-17 14:25:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_canvas.hxx"

#include <canvas/debug.hxx>
#include <canvas/verbosetrace.hxx>

#include <rtl/math.hxx>

#include <vcl/outdev.hxx>
#include <vcl/bitmap.hxx>
#include <vcl/alpha.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/canvastools.hxx>

#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/tools/canvastools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/numeric/ftools.hxx>

#include <canvas/canvastools.hxx>

#include "canvascustomsprite.hxx"

using namespace ::com::sun::star;

namespace vclcanvas
{

    CanvasCustomSprite::CanvasCustomSprite( const geometry::RealSize2D& rSpriteSize,
                                            const SpriteCanvasRef&      rSpriteCanvas,
                                            bool                        bShowSpriteBounds ) :
        mpSpriteCanvas( rSpriteCanvas )
    {
        ENSURE_AND_THROW( rSpriteCanvas.get() &&
                          rSpriteCanvas->getOutDev(),
                          "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );

        // setup back buffer
        // -----------------

        const ::Size aSize(
            static_cast<sal_Int32>( ::std::max( 1.0,
                                                ceil( rSpriteSize.Width ))),  // round up to nearest int,
                                                                              // enforce sprite to have at
                                                                               // least (1,1) pixel size
            static_cast<sal_Int32>( ::std::max( 1.0,
                                                ceil( rSpriteSize.Height ))) );

        // create content backbuffer in screen depth
        BackBufferSharedPtr pBackBuffer( new BackBuffer( *rSpriteCanvas->getOutDev() ) );
        pBackBuffer->setSize( aSize );

        // create mask backbuffer, with one bit color depth
        BackBufferSharedPtr pBackBufferMask( new BackBuffer( *rSpriteCanvas->getOutDev(),
                                                             true ) );
        pBackBufferMask->setSize( aSize );

        // TODO(F1): Implement alpha vdev (could prolly enable
        // antialiasing again, then)

        // disable font antialiasing (causes ugly shadows otherwise)
        pBackBuffer->getVirDev().SetAntialiasing( ANTIALIASING_DISABLE_TEXT );
        pBackBufferMask->getVirDev().SetAntialiasing( ANTIALIASING_DISABLE_TEXT );

        // set mask vdev drawmode, such that everything is painted
        // black. That leaves us with a binary image, white for
        // background, black for painted content
        pBackBufferMask->getVirDev().SetDrawMode( DRAWMODE_BLACKLINE | DRAWMODE_BLACKFILL | DRAWMODE_BLACKTEXT |
                                                  DRAWMODE_BLACKGRADIENT | DRAWMODE_BLACKBITMAP );

        // setup canvas helper
        // -------------------

        // always render into back buffer, don't preserve state (it's
        // our private VDev, after all), have notion of alpha
        maCanvasHelper.init( *rSpriteCanvas.get(),
                             pBackBuffer,
                             false,
                             true );
        maCanvasHelper.setBackgroundOutDev( pBackBufferMask );

        // setup sprite helper
        // -------------------

        maSpriteHelper.init( rSpriteSize,
                             rSpriteCanvas,
                             pBackBuffer,
                             pBackBufferMask,
                             bShowSpriteBounds );

        // clear sprite to 100% transparent
        maCanvasHelper.clear();
    }

    void SAL_CALL CanvasCustomSprite::disposing()
    {
        tools::LocalGuard aGuard;

        mpSpriteCanvas.clear();

        // forward to parent
        CanvasCustomSpriteBaseT::disposing();
    }

#define IMPLEMENTATION_NAME "VCLCanvas.CanvasCustomSprite"
#define SERVICE_NAME "com.sun.star.rendering.CanvasCustomSprite"

    ::rtl::OUString SAL_CALL CanvasCustomSprite::getImplementationName() throw( uno::RuntimeException )
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
    }

    sal_Bool SAL_CALL CanvasCustomSprite::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
    {
        return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
    }

    uno::Sequence< ::rtl::OUString > SAL_CALL CanvasCustomSprite::getSupportedServiceNames()  throw( uno::RuntimeException )
    {
        uno::Sequence< ::rtl::OUString > aRet(1);
        aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );

        return aRet;
    }

    // Sprite
    void CanvasCustomSprite::redraw( OutputDevice& rOutDev,
                                     bool          bBufferedUpdate ) const
    {
        tools::LocalGuard aGuard;

        redraw( rOutDev, maSpriteHelper.getPosPixel(), bBufferedUpdate );
    }

    void CanvasCustomSprite::redraw( OutputDevice&              rOutDev,
                                     const ::basegfx::B2DPoint& rOrigOutputPos,
                                     bool                       bBufferedUpdate ) const
    {
        tools::LocalGuard aGuard;

        maSpriteHelper.redraw( rOutDev,
                               rOrigOutputPos,
                               mbSurfaceDirty,
                               bBufferedUpdate );

        mbSurfaceDirty = false;
    }

    bool CanvasCustomSprite::repaint( const GraphicObjectSharedPtr& rGrf,
                                      const ::Point&                rPt,
                                      const ::Size&                 rSz,
                                      const GraphicAttr&            rAttr ) const
    {
        tools::LocalGuard aGuard;

        mbSurfaceDirty = true;

        return maCanvasHelper.repaint( rGrf, rPt, rSz, rAttr );
    }

}
<commit_msg>INTEGRATION: CWS thbpp9_SRC680 (1.12.28); FILE MERGED 2007/10/17 21:14:36 thb 1.12.28.1: #i82485# Carry clips along, also for XCachedPrimitive repaints<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: canvascustomsprite.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-01 14:41:02 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_canvas.hxx"

#include <canvas/debug.hxx>
#include <canvas/verbosetrace.hxx>

#include <rtl/math.hxx>

#include <vcl/outdev.hxx>
#include <vcl/bitmap.hxx>
#include <vcl/alpha.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/canvastools.hxx>

#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/tools/canvastools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/numeric/ftools.hxx>

#include <canvas/canvastools.hxx>

#include "canvascustomsprite.hxx"

using namespace ::com::sun::star;

namespace vclcanvas
{

    CanvasCustomSprite::CanvasCustomSprite( const geometry::RealSize2D& rSpriteSize,
                                            const SpriteCanvasRef&      rSpriteCanvas,
                                            bool                        bShowSpriteBounds ) :
        mpSpriteCanvas( rSpriteCanvas )
    {
        ENSURE_AND_THROW( rSpriteCanvas.get() &&
                          rSpriteCanvas->getOutDev(),
                          "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );

        // setup back buffer
        // -----------------

        const ::Size aSize(
            static_cast<sal_Int32>( ::std::max( 1.0,
                                                ceil( rSpriteSize.Width ))),  // round up to nearest int,
                                                                              // enforce sprite to have at
                                                                               // least (1,1) pixel size
            static_cast<sal_Int32>( ::std::max( 1.0,
                                                ceil( rSpriteSize.Height ))) );

        // create content backbuffer in screen depth
        BackBufferSharedPtr pBackBuffer( new BackBuffer( *rSpriteCanvas->getOutDev() ) );
        pBackBuffer->setSize( aSize );

        // create mask backbuffer, with one bit color depth
        BackBufferSharedPtr pBackBufferMask( new BackBuffer( *rSpriteCanvas->getOutDev(),
                                                             true ) );
        pBackBufferMask->setSize( aSize );

        // TODO(F1): Implement alpha vdev (could prolly enable
        // antialiasing again, then)

        // disable font antialiasing (causes ugly shadows otherwise)
        pBackBuffer->getVirDev().SetAntialiasing( ANTIALIASING_DISABLE_TEXT );
        pBackBufferMask->getVirDev().SetAntialiasing( ANTIALIASING_DISABLE_TEXT );

        // set mask vdev drawmode, such that everything is painted
        // black. That leaves us with a binary image, white for
        // background, black for painted content
        pBackBufferMask->getVirDev().SetDrawMode( DRAWMODE_BLACKLINE | DRAWMODE_BLACKFILL | DRAWMODE_BLACKTEXT |
                                                  DRAWMODE_BLACKGRADIENT | DRAWMODE_BLACKBITMAP );

        // setup canvas helper
        // -------------------

        // always render into back buffer, don't preserve state (it's
        // our private VDev, after all), have notion of alpha
        maCanvasHelper.init( *rSpriteCanvas.get(),
                             pBackBuffer,
                             false,
                             true );
        maCanvasHelper.setBackgroundOutDev( pBackBufferMask );

        // setup sprite helper
        // -------------------

        maSpriteHelper.init( rSpriteSize,
                             rSpriteCanvas,
                             pBackBuffer,
                             pBackBufferMask,
                             bShowSpriteBounds );

        // clear sprite to 100% transparent
        maCanvasHelper.clear();
    }

    void SAL_CALL CanvasCustomSprite::disposing()
    {
        tools::LocalGuard aGuard;

        mpSpriteCanvas.clear();

        // forward to parent
        CanvasCustomSpriteBaseT::disposing();
    }

#define IMPLEMENTATION_NAME "VCLCanvas.CanvasCustomSprite"
#define SERVICE_NAME "com.sun.star.rendering.CanvasCustomSprite"

    ::rtl::OUString SAL_CALL CanvasCustomSprite::getImplementationName() throw( uno::RuntimeException )
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
    }

    sal_Bool SAL_CALL CanvasCustomSprite::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
    {
        return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
    }

    uno::Sequence< ::rtl::OUString > SAL_CALL CanvasCustomSprite::getSupportedServiceNames()  throw( uno::RuntimeException )
    {
        uno::Sequence< ::rtl::OUString > aRet(1);
        aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );

        return aRet;
    }

    // Sprite
    void CanvasCustomSprite::redraw( OutputDevice& rOutDev,
                                     bool          bBufferedUpdate ) const
    {
        tools::LocalGuard aGuard;

        redraw( rOutDev, maSpriteHelper.getPosPixel(), bBufferedUpdate );
    }

    void CanvasCustomSprite::redraw( OutputDevice&              rOutDev,
                                     const ::basegfx::B2DPoint& rOrigOutputPos,
                                     bool                       bBufferedUpdate ) const
    {
        tools::LocalGuard aGuard;

        maSpriteHelper.redraw( rOutDev,
                               rOrigOutputPos,
                               mbSurfaceDirty,
                               bBufferedUpdate );

        mbSurfaceDirty = false;
    }

    bool CanvasCustomSprite::repaint( const GraphicObjectSharedPtr& rGrf,
                                      const rendering::ViewState&   viewState,
                                      const rendering::RenderState& renderState,
                                      const ::Point&                rPt,
                                      const ::Size&                 rSz,
                                      const GraphicAttr&            rAttr ) const
    {
        tools::LocalGuard aGuard;

        mbSurfaceDirty = true;

        return maCanvasHelper.repaint( rGrf, viewState, renderState, rPt, rSz, rAttr );
    }

}
<|endoftext|>