Petr Mrázek 2011-07-23 17:08:15 +02:00
commit 6b6eed34cc
8 changed files with 694 additions and 11 deletions

@ -104,10 +104,10 @@ namespace DFHack
{"stone pillar",PILLAR, STONE, VAR_1},
//80
{"obsidian pillar",PILLAR, OBSIDIAN, VAR_1},
{"featstone? pillar",PILLAR, FEATSTONE, VAR_1},
{"vein pillar",PILLAR, VEIN, VAR_1},
{"ice pillar",PILLAR, ICE, VAR_1},
{"obsidian pillar",PILLAR, OBSIDIAN, VAR_1,TILE_SMOOTH},
{"featstone? pillar",PILLAR, FEATSTONE, VAR_1,TILE_SMOOTH},
{"vein pillar",PILLAR, VEIN, VAR_1,TILE_SMOOTH},
{"ice pillar",PILLAR, ICE, VAR_1,TILE_SMOOTH},
{0 ,EMPTY, AIR, VAR_1},
{0 ,EMPTY, AIR, VAR_1},
{0 ,EMPTY, AIR, VAR_1},
@ -658,15 +658,44 @@ namespace DFHack
int32_t findSimilarTileType( const int32_t sourceTileType, const TileShape tshape )
{
int32_t tt, match=0;
int32_t match=0;
int value=0, matchv=0;
const TileRow *source = &tileTypeTable[sourceTileType];
//Shortcut.
//If the current tile is already a shape match, leave.
if( tshape == source->shape ) return sourceTileType;
//Cheap pseudo-entropy, by using address of the variable on the stack.
//No need for real random numbers.
static int entropy;
entropy += (int)( (void *)(&match) );
entropy ^= ((entropy & 0xFF000000)>>24) ^ ((entropy & 0x00FF0000)>>16);
#ifdef assert
assert( sourceTileType >=0 && sourceTileType < TILE_TYPE_ARRAY_LENGTH );
#endif
for(tt=0;tt<TILE_TYPE_ARRAY_LENGTH; ++tt)
//Special case for smooth pillars.
//When you want a smooth wall, no need to search for best match. Just use a pillar instead.
//Choosing the right direction would require knowing neighbors.
if( WALL==tshape && (TILE_SMOOTH==source->special || CONSTRUCTED==source->material) ){
switch( source->material ){
case CONSTRUCTED: match=495; break;
case ICE: match= 83; break;
case VEIN: match= 82; break;
case FEATSTONE: match= 81; break;
case OBSIDIAN: match= 80; break;
case STONE: match= 79; break;
}
if( match ) return match;
}
//Run through until perfect match found or hit end.
for(int32_t tt=0;tt<TILE_TYPE_ARRAY_LENGTH && value<(8|4|1); ++tt)
{
if( tshape == tileTypeTable[tt].shape )
{
@ -676,7 +705,11 @@ namespace DFHack
//Special flag match is absolutely mandatory!
if( source->special != tileTypeTable[tt].special ) continue;
value=0;
//Special case for constructions.
//Never turn a construction into a non-contruction.
if( CONSTRUCTED == source->material && CONSTRUCTED != tileTypeTable[tt].material ) continue;
value=0;
//Material is high-value match
if( tileTypeTable[tt].material == source->material ) value|=8;
//Direction is medium value match
@ -684,7 +717,7 @@ namespace DFHack
//Variant is low-value match
if( tileTypeTable[tt].variant == source->variant ) value|=1;
//Check value against last match
//Check value against last match.
if( value>matchv )
{
match=tt;
@ -692,6 +725,40 @@ namespace DFHack
}
}
}
//Post-processing for floors.
//Give raw floors variation.
//Variant matters, but does not matter for source.
//Error on the side of caution.
if( FLOOR==tshape && CONSTRUCTED!=source->material && !source->special )
{
//Trying to make a floor type with variants, so randomize the variant.
//Very picky, only handle known safe tile types.
//Some floors have 4 variants, some have 3, so the order of these matters.
switch( match ){
case 261:
//Furrowed soil got chosen by accident. Fix that.
match=352+(3&entropy);
break;
case 336: //STONE
case 340: //OBSIDIAN
case 344: //featstone
case 349: //grass
case 352: //soil
case 356: //wet soil
case 387: //dry grass
case 394: //dead grass
case 398: //grass B
case 441: //vein
match += 3&entropy;
break;
case 242: //ASHES
case 258: //ICE
match += (1&entropy) + (2&entropy);
break;
}
}
if( match ) return match;
return sourceTileType;
}

@ -120,6 +120,7 @@ namespace DFHack
uint32_t origin;
};
/**
* mineral vein object - bitmap with a material type
* \ingroup grp_maps
@ -135,6 +136,26 @@ namespace DFHack
uint32_t flags;
/// this is NOT part of the DF vein, but an address of the vein as seen by DFhack.
uint32_t address_of;
//zilpin: Functions to more conveniently check the assignment flags of the vein.
//Coordinates are given in tile within the block.
//Important to make these inline.
inline int getassignment( DFCoord xy ){
return getassignment(xy.x,xy.y);
}
inline int getassignment( int x, int y ){
return (assignment[y] & (1 << x));
}
inline void setassignment( DFCoord xy, int bit ){
return setassignment(xy.x,xy.y, bit);
}
inline void setassignment( int x, int y, int bit ){
if(bit)
assignment[y] |= (1 << x);
else
assignment[y] &= 0xFFFF ^ (1 << x);
}
};
/**
@ -652,7 +673,10 @@ namespace DFHack
std::vector<t_grassvein>* grass = 0,
std::vector<t_worldconstruction>* constructions = 0
);
/// read all plants in this block
/// write a single vein back to the address it was retreived from
bool Maps::WriteVein(t_vein *vein);
/// read all plants in this block
bool ReadVegetation(uint32_t x, uint32_t y, uint32_t z, std::vector<dfh_plant>* plants);
private:
struct Private;

@ -1043,6 +1043,23 @@ bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector <t_vein>* veins,
return true;
}
/*
Write the vein retreived using ReadVeins back to the address it was taken from.
*/
bool Maps::WriteVein(t_vein *vein)
{
if(!vein) return false;
Process* p = d->owner;
//Write each part individually.
p->writeDWord(vein->address_of + 4 , vein->type );
p->write( vein->address_of + 8 , 32 , (uint8_t *)vein->assignment );
p->writeDWord(vein->address_of + 40 , vein->flags );
return true;
}
/*
__int16 __userpurge GetGeologicalRegion<ax>(__int16 block_X<cx>, int X<ebx>, __int16 block_Y<di>, int block_addr<esi>, int Y)
{

@ -70,6 +70,23 @@ DFHACK_TOOL(dfprinttiletypes printtiletypes.cpp)
# Will have many options in the future.
DFHACK_TOOL(dfhellhole hellhole.cpp)
# drawtile
# Author: zilpin
# Arbitrary tile drawing at the cursor.
# Does not fix tiles above/below for consistency (e.g. ramps).
DFHACK_TOOL(dfdrawtile drawtile.cpp)
# veinswap
# Author: zilpin
# Randomly swap a percentage of the specified vein material with another material.
# Or, set the material of a vein under the cursor.
DFHACK_TOOL(dfveinswap veinswap.cpp)
# lumberjack
# Author: zilpin
# Designate all trees of the given type which can be reached from the cursor.
DFHACK_TOOL(dflumberjack lumberjack.cpp)
# dfcreaturemanager
# Author: raoulxq
# - Display creatures (overview & detail)

@ -0,0 +1,315 @@
//
#include <iostream>
#include <vector>
#include <map>
#include <cstdlib>
#include <limits>
using namespace std;
#include <conio.h>
#include <DFHack.h>
#include <dfhack/DFTileTypes.h>
//Avoid including Windows.h because it causes name clashes
extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long milliseconds);
//Trim
#define WHITESPACE " \t\r\n"
inline string trimr(const string & s, const string & t = WHITESPACE)
{
string d (s);
string::size_type i (d.find_last_not_of (t));
if (i == string::npos)
return "";
else
return d.erase (d.find_last_not_of (t) + 1) ;
}
inline string triml(const string & s, const string & t = WHITESPACE)
{
string d (s);
return d.erase (0, s.find_first_not_of (t)) ;
}
inline string trim(const string & s, const string & t = WHITESPACE)
{
string d (s);
return triml(trimr(d, t), t);
}
void printtiletype( int i ){
printf("%s\n%4i ; %-13s ; %-11s ; %c ; %-12s ; %s\n",
( DFHack::tileTypeTable[i].name ? DFHack::tileTypeTable[i].name : "[invalid tile]" ),
i,
( DFHack::tileTypeTable[i].name ? DFHack::TileShapeString[ DFHack::tileTypeTable[i].shape ] : "" ),
( DFHack::tileTypeTable[i].name ? DFHack::TileMaterialString[ DFHack::tileTypeTable[i].material ] : "" ),
( DFHack::tileTypeTable[i].variant ? '0'+ DFHack::tileTypeTable[i].variant : ' ' ),
( DFHack::tileTypeTable[i].special ? DFHack::TileSpecialString[ DFHack::tileTypeTable[i].special ] : "" ),
( DFHack::tileTypeTable[i].direction.whole ? DFHack::tileTypeTable[i].direction.getStr() : "" ),
0
);
}
int main (void)
{
int32_t x,y,z,tx,ty;
//DFHack::designations40d designations;
DFHack::tiletypes40d tiles;
//DFHack::t_temperatures temp1,temp2;
uint32_t x_max,y_max,z_max;
int32_t oldT, newT;
int count, dirty;
//Brush defaults
DFHack::TileShape BrushClass = DFHack::WALL;
DFHack::TileMaterial BrushMat = DFHack::tilematerial_invalid;
int BrushType = -1;
DFHack::ContextManager DFMgr("Memory.xml");
DFHack::Context *DF;
DFHack::Maps * Maps;
DFHack::Gui * Gui;
try
{
DF=DFMgr.getSingleContext();
DF->Attach();
Maps = DF->getMaps();
Maps->Start();
Maps->getSize(x_max,y_max,z_max);
Gui = DF->getGui();
}
catch (exception& e)
{
cerr << e.what() << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
}
bool end = false;
cout << "Welcome to the Tile Drawing tool.\nType 'help' or ? for a list of available commands, 'q' to quit" << endl;
string mode = "wall";
string command = "";
while(!end)
{
DF->Resume();
cout << endl << ":";
getline(cin, command);
int ch = command[0];
if(command.length()<=0) ch=0;
if( ((int)command.find("help")) >=0 ) ch='?'; //under windows, find was casting unsigned!
switch(ch)
{
case '?':
cout << "Modes:" << endl
<< "O - draw Open Space" << endl
<< "M - draw material only (shape unchanged)" << endl
<< "m number - use Material value entered" << endl
<< "r - use Rock/stone material" << endl
<< "l - use Soil material" << endl
<< "v - use Vein material" << endl
<< "H - draw tile shape only (material unchanged)" << endl
<< "h number - draw Tile Shape value entered" << endl
<< "w - draw Wall tiles" << endl
<< "f - draw Floor tiles" << endl
<< "t number - draw exact tile type entered" << endl
<< "Commands:" << endl
<< "p - print tile shapes and materials, and current brush" << endl
<< "P - print all tile types" << endl
<< "q - quit" << endl
<< "help OR ? - print this list of commands" << endl
<< "d - being drawing" << endl
<< endl
<< "Usage:\nChoose a mode (default is walls), then enter 'd' to being drawing.\nMove the cursor in DF wherever you want to draw.\nPress any key to pause drawing." << endl;
break;
case 'p':
//Classes
printf("\nTile Type Classes:\n");
for(int i=0;i<DFHack::tileshape_count;++i)
{
printf("%4i ; %s\n", i, DFHack::TileShapeString[i] ,0 );
}
//Materials
printf("\nTile Type Materials:\n");
for(int i=0;i<DFHack::tilematerial_count;++i)
{
printf("%4i ; %s\n", i, DFHack::TileMaterialString[i] ,0 );
}
//fall through...
case 10:
case 13:
case 0:
//Print current cursor & brush settings.
cout << "\nCurrent Brush:\n";
cout << "tile = ";
if(BrushClass<0) cout<<"(not drawing)"; else cout<<DFHack::TileShapeString[BrushClass]; cout << endl;
cout << "mat = ";
if(BrushMat<0) cout<<"(not drawing)"; else cout<<DFHack::TileMaterialString[BrushMat]; cout << endl;
cout << "type = ";
if(BrushType<0){
cout<<"(not drawing)";
}else{
printtiletype(BrushType);
}
break;
case 'P':
cout << "\nAll Valid Tile Types:\n";
for(int i=0;i<TILE_TYPE_ARRAY_LENGTH;++i)
{
if( DFHack::tileTypeTable[i].name )
printtiletype(i);
}
case 'w':
BrushType=-1;
BrushClass = DFHack::WALL;
cout << "Tile brush shape set to Wall." << endl;
break;
case 'f':
BrushType=-1;
BrushClass = DFHack::FLOOR;
cout << "Tile brush shape set to Floor." << endl;
break;
case 'h':
BrushType=-1;
BrushClass = (DFHack::TileShape)atol( command.c_str()+1 );
cout << "Tile brush shape set to " << BrushClass << endl;
break;
case 'M':
BrushClass = DFHack::tileshape_invalid;
cout << "Tile brush will not draw tile shape." << endl;
break;
case 'r':
BrushType=-1;
BrushMat = DFHack::STONE;
cout << "Tile brush material set to Rock." << endl;
break;
case 'l':
BrushType=-1;
BrushMat = DFHack::SOIL;
cout << "Tile brush material set to Soil." << endl;
break;
case 'v':
BrushType=-1;
BrushMat = DFHack::VEIN;
cout << "Tile brush material set to Vein." << endl;
break;
case 'm':
BrushType=-1;
BrushMat = (DFHack::TileMaterial)atol( command.c_str()+1 );
cout << "Tile brush material set to " << BrushMat << endl;
break;
case 'H':
BrushMat = DFHack::tilematerial_invalid;
cout << "Tile brush will not draw material." << endl;
break;
case 'O':
BrushType=-1;
BrushClass = DFHack::EMPTY;
BrushMat = DFHack::AIR;
cout << "Tile brush will draw Open Space." << endl;
break;
case 't':
BrushClass = DFHack::tileshape_invalid ;
BrushMat = DFHack::tilematerial_invalid;
BrushType = atol( command.c_str()+1 );
cout << "Tile brush type set to:" << endl;
printtiletype(BrushType);
break;
case 'q':
end = true;
cout << "Bye!" << endl;
break;
case 'd':
{
count=0;
cout << "Beginning to draw at cursor." << endl << "Press any key to stop drawing." << endl;
//DF->Suspend();
kbhit(); //throw away, just to be sure.
for(;;)
{
if(!Maps->Start())
{
cout << "Can't see any DF map loaded." << endl;
break;
}
if(!Gui->getCursorCoords(x,y,z))
{
cout << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl;
break;
}
//cout << "cursor coords: " << x << "/" << y << "/" << z << endl;
tx=x%16; ty=y%16;
if(!Maps->isValidBlock(x/16,y/16,z))
{
cout << "Invalid block." << endl;
break;
}
//Read the tiles.
dirty=0;
Maps->ReadTileTypes((x/16),(y/16),z, &tiles);
oldT = tiles[tx][ty];
newT = -1;
if( 0<BrushType ){
//Explicit tile type set. Trust the user.
newT = BrushType;
}else if( 0==BrushMat && 0==BrushClass ){
//Special case, Empty Air.
newT = 32;
}else if( BrushMat>=0 && BrushClass>=0 && ( BrushClass != DFHack::tileTypeTable[oldT].shape || BrushMat != DFHack::tileTypeTable[oldT].material) ){
//Set tile material and class
newT = DFHack::findTileType(BrushClass,BrushMat, DFHack::tileTypeTable[oldT].variant , DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction );
if(newT<0) newT = DFHack::findTileType(BrushClass,BrushMat, DFHack::tilevariant_invalid, DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction );
if(newT<0) newT = DFHack::findTileType(BrushClass,BrushMat, DFHack::tilevariant_invalid , DFHack::tileTypeTable[oldT].special , (uint32_t)0 );
}else if( BrushMat<0 && BrushClass>=0 && BrushClass != DFHack::tileTypeTable[oldT].shape ){
//Set current tile class only, as accurately as can be expected
newT = DFHack::findSimilarTileType(oldT,BrushClass);
}else if( BrushClass<0 && BrushMat>=0 && BrushMat != DFHack::tileTypeTable[oldT].material ){
//Set current tile material only
newT = DFHack::findTileType(DFHack::tileTypeTable[oldT].shape,BrushMat, DFHack::tileTypeTable[oldT].variant , DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction );
if(newT<0) newT = DFHack::findTileType(DFHack::tileTypeTable[oldT].shape,BrushMat, DFHack::tilevariant_invalid , DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction );
if(newT<0) newT = DFHack::findTileType(DFHack::tileTypeTable[oldT].shape,BrushMat, DFHack::tilevariant_invalid , DFHack::tileTypeTable[oldT].special , (uint32_t)0 );
}
//If no change, skip it (couldn't find a good tile type, or already what we want)
if ( newT > 0 && oldT != newT ){
//Set new tile type
tiles[tx][ty] = newT;
dirty=-1;
}
//If anything was changed, write it all.
if (dirty)
{
//Maps->WriteDesignations(x/16,y/16,z/16, &designations);
Maps->WriteTileTypes(x/16,y/16,z, &tiles);
printf("(%4d,%4d,%4d)",x,y,z);
++count;
}
Maps->Finish();
Sleep(10);
if( kbhit() ) break;
}
cin.clear();
cout << endl << count << " tiles were drawn." << endl << "Drawing halted. Entering command mode." << endl;
}
continue;
break;
default:
cout << "Unknown command: " << command << endl;
}
}
DF->Detach();
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();
#endif
return 0;
}

@ -0,0 +1,5 @@
int main (int numargs, const char ** args)
{
return 0;
}

@ -0,0 +1,229 @@
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <map>
#include <cstdlib>
#include <limits>
using namespace std;
#include <conio.h>
#include <DFHack.h>
#include <dfhack/DFTileTypes.h>
#include <dfhack/extra/MapExtras.h>
//Globals
DFHack::Context *DF;
DFHack::Maps *maps;
DFHack::Gui *gui;
DFHack::Materials *mats;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int main (void)
{
int32_t
cx,cy,z, //cursor coords
tx,ty, //tile coords within block
bx,by; //block coords
//DFHack::designations40d designations;
//DFHack::tiletypes40d tiles;
//DFHack::t_temperatures temp1,temp2;
uint32_t x_max,y_max,z_max;
DFHack::ContextManager DFMgr("Memory.xml");
try
{
DF=DFMgr.getSingleContext();
DF->Attach();
maps = DF->getMaps();
maps->Start();
maps->getSize(x_max,y_max,z_max);
gui = DF->getGui();
mats = DF->getMaterials();
mats->ReadAllMaterials();
if(!mats->ReadInorganicMaterials())
{
printf("Error: Could not load materials!\n");
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
}
}
catch (exception& e)
{
cerr << e.what() << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
}
bool end = false;
cout << "Welcome to the Vein Swap tool.\nType 'help' or ? for a list of available commands, 'q' to quit" << endl;
string mode = "";
string command = "";
while(!end)
{
DF->Resume();
cout << endl << ":";
getline(cin, command);
int ch = command[0];
if(command.length()<=0) ch=0;
if( ((int)command.find("help")) >=0 ) ch='?'; //under windows, find was casting unsigned!
//Process user command.
switch(ch)
{
case 'h':
case '?':
cout << "" << endl
<< "Commands:" << endl
<< "p - print vein at cursor" << endl
<< "m - print all inorganic material types" << endl
<< "r MatTo - replace the vein at cursor with MatTo" << endl
<< "R Percent MatFrom MatTo - replace Percent of MatFrom veins with MatTo veins" << endl
<< "help OR ? - print this list of commands" << endl
<< "q - quit" << endl
<< endl
<< "Usage:\n\t" << endl;
break;
case 'p':
case 10:
case 13:
case 0:
{
//Print current cursor
mats->ReadAllMaterials();
if(!maps->Start())
{
cout << "Can't see any DF map loaded." << endl;
break;
}
if(!gui->getCursorCoords(cx,cy,z))
{
cout << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl;
break;
}
//cout << "cursor coords: " << x << "/" << y << "/" << z << endl;
tx=cx%16; ty=cy%16;
bx=cx/16; by=cy/16;
DFHack::DFCoord xyz(cx,cy,z);
printf("Cursor[%d,%d,%d] Block(%d,%d) Tile(%d,%d)\n", cx,cy,z, bx,by, tx,ty );
if(!maps->isValidBlock(bx,by,z))
{
cout << "Invalid block." << endl;
break;
}
vector<DFHack::t_vein> veinVector;
int found=0;
maps->ReadVeins(bx,by,z,&veinVector);
printf("Veins in block (%d):\n",veinVector.size());
for(unsigned long i=0;i<veinVector.size();++i){
found = veinVector[i].getassignment(tx,ty);
printf("\t%c %4d %s\n",
(found ? '*' : ' '),
veinVector[i].type,
mats->inorganic[veinVector[i].type].id
);
}
printf("Cursor is%s in vein.\n", (found?"":" not") );
maps->Finish();
DF->Resume();
}
break;
case 'v':
break;
case 'm':
break;
case 'R':
break;
case 'q':
end = true;
cout << "Bye!" << endl;
break;
case 'r':
DF->Suspend();
do{
//Process parameters
long matto = atol( command.c_str()+1 );
if( matto < 0 || matto >= (long)mats->inorganic.size() ){
cout << "Invalid material: " << matto << endl;
break;
}
if(!maps->Start())
{
cout << "Can't see any DF map loaded." << endl;
break;
}
if(!gui->getCursorCoords(cx,cy,z))
{
cout << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl;
break;
}
tx=cx%16; ty=cy%16;
bx=cx/16; by=cy/16;
printf("Cursor[%d,%d,%d] Block(%d,%d) Tile(%d,%d)\n", cx,cy,z, bx,by, tx,ty );
if(!maps->isValidBlock(bx,by,z))
{
cout << "Invalid block." << endl;
break;
}
//MapExtras::MapCache MC(maps);
//MapExtras::Block B(maps,DFHack::DFCoord(bx,by,z));
vector<DFHack::t_vein> veinVector;
int v=-1; //the vector pointed to by the cursor
mats->ReadAllMaterials();
maps->ReadVeins(bx,by,z,&veinVector);
for(unsigned long i=0 ; v<0 && i<veinVector.size() ; ++i){
if( veinVector[i].getassignment(tx,ty) )
v=i;
}
printf("Replacing %d %s with %d %s...\n", veinVector[v].type, mats->inorganic[veinVector[v].type].id, matto, mats->inorganic[matto].id );
printf("%X\n",veinVector[v].vtable);
vector<DFHack::t_vein> veinTable;
veinVector[v].type = matto;
maps->WriteVein( &veinVector[v] );
maps->Finish();
cout << endl << "Finished." << endl;
}while(0);
DF->Resume();
break;
default:
cout << "Unknown command: " << command << endl;
}//end switch
}//end while
DF->Detach();
//#ifndef LINUX_BUILD
//cout << "Done. Press any key to continue" << endl;
//cin.ignore();
//#endif
return 0;
}

@ -13,14 +13,23 @@ using namespace std;
#include <dfhack/extra/MapExtras.h>
#include <dfhack/extra/termutil.h>
//zilpin: These two functions were giving me compile errors in VS2008, so I cheated with the C style loop below, just to get it to build.
//Original code is commented out.
void tolower(std::string &str)
{
std::transform(str.begin(), str.end(), str.begin(), std::bind2nd(std::ptr_fun(&std::tolower<char>), std::locale("")));
//The C++ way...
//std::transform(str.begin(), str.end(), str.begin(), std::bind2nd(std::ptr_fun(&std::tolower<char> ), std::locale("")));
//The C way...
for(char *c=(char *)str.c_str(); *c; ++c)
*c = tolower(*c);
}
void toupper(std::string &str)
{
std::transform(str.begin(), str.end(), str.begin(), std::bind2nd(std::ptr_fun(&std::toupper<char>), std::locale("")));
//std::transform(str.begin(), str.end(), str.begin(), std::bind2nd(std::ptr_fun(&std::toupper<char>), std::locale("")));
for(char *c=(char *)str.c_str(); *c; ++c)
*c = toupper(*c);
}
int toint(const std::string &str, int failValue = 0)