diff options
-rw-r--r-- | minetest.vcproj | 2 | ||||
-rw-r--r-- | src/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/debug.h | 4 | ||||
-rw-r--r-- | src/inventory.h | 35 | ||||
-rw-r--r-- | src/main.cpp | 27 | ||||
-rw-r--r-- | src/mapblock.cpp | 21 | ||||
-rw-r--r-- | src/mapnode.cpp | 65 | ||||
-rw-r--r-- | src/mapnode.h | 25 | ||||
-rw-r--r-- | src/materials.cpp | 6 | ||||
-rw-r--r-- | src/porting.h | 2 | ||||
-rw-r--r-- | src/socket.h | 8 | ||||
-rw-r--r-- | src/tile.cpp | 105 | ||||
-rw-r--r-- | src/tile.h | 7 | ||||
-rw-r--r-- | src/utility.h | 20 |
14 files changed, 253 insertions, 78 deletions
diff --git a/minetest.vcproj b/minetest.vcproj index 8d49d2cdf..8973c9a2c 100644 --- a/minetest.vcproj +++ b/minetest.vcproj @@ -57,6 +57,7 @@ />
<Tool
Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib"
AdditionalLibraryDirectories=""..\irrlicht\irrlicht-1.7.1\lib\Win32-visualstudio";..\zlib125dll\dll32"
IgnoreAllDefaultLibraries="false"
GenerateDebugInformation="true"
@@ -136,6 +137,7 @@ />
<Tool
Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib"
AdditionalLibraryDirectories=""..\irrlicht\irrlicht-1.7.1\lib\Win32-visualstudio";..\zlib125dll\dll32"
IgnoreDefaultLibraryNames="libcmtd.dll"
GenerateDebugInformation="false"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4d2ba0d29..f44b0930f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,9 +10,11 @@ add_definitions ( -DUSE_CMAKE_CONFIG_H ) if(WIN32) # Windows - if(MSVC) + if(MSVC) # MSVC Specifics # Surpress some useless warnings add_definitions ( /D "_CRT_SECURE_NO_DEPRECATE" /W1 ) + else() # Probably MinGW = GCC + set(PLATFORM_LIBS ws2_32.lib) endif() # Zlib stuff set(ZLIB_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../../zlib/zlib-1.2.5" diff --git a/src/debug.h b/src/debug.h index 092bb03a8..5cc1e6c4d 100644 --- a/src/debug.h +++ b/src/debug.h @@ -33,7 +33,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include <windows.h> - #include <eh.h> + #ifdef _MSC_VER + #include <eh.h> + #endif #else #endif diff --git a/src/inventory.h b/src/inventory.h index ca07bf46d..9155eb025 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -122,8 +122,7 @@ public: #ifndef SERVER video::ITexture * getImage() { - //TODO - //return g_irrlicht->getTexture(content_features(m_content).inventory_texture); + return content_features(m_content).inventory_texture; return NULL; } #endif @@ -249,6 +248,9 @@ public: #ifndef SERVER video::ITexture * getImage() { + if(g_texturesource == NULL) + return NULL; + std::string name; if(m_subname == "Stick") @@ -262,8 +264,7 @@ public: // Get such a texture //return g_irrlicht->getTexture(name); - //TODO - return NULL; + return g_texturesource->getTextureRaw(name); } #endif std::string getText() @@ -329,6 +330,9 @@ public: #ifndef SERVER video::ITexture * getImage() { + if(g_texturesource == NULL) + return NULL; + std::string basename; if(m_toolname == "WPick") basename = "tool_wpick.png"; @@ -348,31 +352,14 @@ public: float value_f = (float)toolprogress / (float)maxprogress; std::ostringstream os; - os<<"[progressbar"<<value_f; + os<<basename<<"^[progressbar"<<value_f; + + return g_texturesource->getTextureRaw(os.str()); /*TextureSpec spec; spec.addTid(g_irrlicht->getTextureId(basename)); spec.addTid(g_irrlicht->getTextureId(os.str())); return g_irrlicht->getTexture(spec);*/ - //TODO - return NULL; - - /*// Make texture name for the new texture with a progress bar - float value_f = (float)toolprogress / (float)maxprogress; - std::ostringstream os; - os<<basename<<"[[mod:progressbar"<<value_f; - return g_irrlicht->getTexture(os.str());*/ - - /*// Make texture name for the new texture with a progress bar - std::ostringstream os; - os<<basename<<"-toolprogress-"<<toolprogress; - std::string finalname = os.str(); - - float value_f = (float)toolprogress / (float)maxprogress; - - // Get such a texture - TextureMod *mod = new ProgressBarTextureMod(value_f); - return g_irrlicht->getTexture(TextureSpec(finalname, basename, mod));*/ } #endif std::string getText() diff --git a/src/main.cpp b/src/main.cpp index 1a576b28d..105acedf7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -267,9 +267,15 @@ Doing now (most important at the top): # maybe done
* not done
-=== Stuff being done
+=== Immediate stuff
* Combine meshes to bigger ones in ClientMap and set them EHM_STATIC
+=== Making it more portable
+* MinGW: Switch away from swprintf; mingw has a bad version of it.
+ Use snprintf + narrow_to_wide or (w)ostringstream
+* Some MSVC: std::sto* are defined without a namespace and collide
+ with the ones in utility.h
+
=== Stuff to do before release
* Save the new mapgen stuff
- map/meta.txt, which should contain only plain text, something like this:
@@ -331,12 +337,12 @@ Doing now (most important at the top): #endif
#ifdef _MSC_VER
-#pragma comment(lib, "Irrlicht.lib")
-//#pragma comment(lib, "jthread.lib")
-#pragma comment(lib, "zlibwapi.lib")
-#pragma comment(lib, "Shell32.lib")
-// This would get rid of the console window
-//#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
+ #pragma comment(lib, "Irrlicht.lib")
+ //#pragma comment(lib, "jthread.lib")
+ #pragma comment(lib, "zlibwapi.lib")
+ #pragma comment(lib, "Shell32.lib")
+ // This would get rid of the console window
+ //#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
#include <iostream>
@@ -1548,9 +1554,8 @@ int main(int argc, char *argv[]) These are needed for unit tests at least.
*/
- IIrrlichtWrapper irrlicht_dummy;
-
- init_mapnode(&irrlicht_dummy);
+ // Initial call with g_texturesource not set.
+ init_mapnode();
/*
Run unit tests
@@ -1716,7 +1721,7 @@ int main(int argc, char *argv[]) */
init_content_inventory_texture_paths();
- init_mapnode(g_irrlicht);
+ init_mapnode(); // Second call with g_texturesource set
init_mineral(g_irrlicht);
/*
diff --git a/src/mapblock.cpp b/src/mapblock.cpp index e66d4dd8f..e0b8965b4 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -341,20 +341,21 @@ TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir, Get texture id, translate it to name, append stuff to name, get texture id */ + // Get original texture name u32 orig_id = spec.texture.id; std::string orig_name = g_texturesource->getTextureName(orig_id); + // Create new texture name std::ostringstream os; os<<orig_name<<"^[crack"<<mod.param; - //os<<orig_name<<"^[progressbar0.5"; - //os<<"mese.png"; + // Get new texture u32 new_id = g_texturesource->getTextureId(os.str()); - dstream<<"MapBlock::getNodeTile(): Switching from " + /*dstream<<"MapBlock::getNodeTile(): Switching from " <<orig_name<<" to "<<os.str()<<" (" - <<orig_id<<" to "<<new_id<<")"<<std::endl; + <<orig_id<<" to "<<new_id<<")"<<std::endl;*/ spec.texture = g_texturesource->getTexture(new_id); } @@ -864,20 +865,20 @@ void MapBlock::updateMesh(u32 daynight_ratio) //material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - //TODO - /*if(dir == v3s16(0,-1,0)) + + if(dir == v3s16(0,-1,0)) material.setTexture(0, - g_irrlicht->getTexture("torch_on_floor.png")); + g_texturesource->getTextureRaw("torch_on_floor.png")); else if(dir == v3s16(0,1,0)) material.setTexture(0, - g_irrlicht->getTexture("torch_on_ceiling.png")); + g_texturesource->getTextureRaw("torch_on_ceiling.png")); // For backwards compatibility else if(dir == v3s16(0,0,0)) material.setTexture(0, - g_irrlicht->getTexture("torch_on_floor.png")); + g_texturesource->getTextureRaw("torch_on_floor.png")); else material.setTexture(0, - g_irrlicht->getTexture("torch.png"));*/ + g_texturesource->getTextureRaw("torch.png")); u16 indices[] = {0,1,2,2,3,0}; // Add to mesh collector diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 06d1be8a3..747c5aefb 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -44,6 +44,39 @@ void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha) tiles[i].alpha = alpha; tiles[i].material_type = MATERIAL_ALPHA_VERTEX; } + + if(inventory_texture == NULL) + setInventoryTexture(name); +} + +void ContentFeatures::setInventoryTexture(std::string imgname) +{ + if(g_texturesource == NULL) + return; + + imgname += "^[forcesingle"; + + inventory_texture = g_texturesource->getTextureRaw(imgname); +} + +void ContentFeatures::setInventoryTextureCube(std::string top, + std::string left, std::string right) +{ + if(g_texturesource == NULL) + return; + + str_replace_char(top, '^', '&'); + str_replace_char(left, '^', '&'); + str_replace_char(right, '^', '&'); + + std::string imgname_full; + imgname_full += "[inventorycube{"; + imgname_full += top; + imgname_full += "{"; + imgname_full += left; + imgname_full += "{"; + imgname_full += right; + inventory_texture = g_texturesource->getTextureRaw(imgname_full); } struct ContentFeatures g_content_features[256]; @@ -53,8 +86,24 @@ ContentFeatures & content_features(u8 i) return g_content_features[i]; } -void init_mapnode(IIrrlichtWrapper *irrlicht) +/* + See mapnode.h for description. +*/ +void init_mapnode() { + if(g_texturesource == NULL) + { + dstream<<"INFO: Initial run of init_mapnode with " + "g_texturesource=NULL. If this segfaults, " + "there is a bug with something not checking for " + "the NULL value."<<std::endl; + } + else + { + dstream<<"INFO: Full run of init_mapnode with " + "g_texturesource!=NULL"<<std::endl; + } + // Read some settings bool new_style_water = g_settings.getBool("new_style_water"); bool new_style_leaves = g_settings.getBool("new_style_leaves"); @@ -88,6 +137,7 @@ void init_mapnode(IIrrlichtWrapper *irrlicht) i = CONTENT_STONE; f = &g_content_features[i]; f->setAllTextures("stone.png"); + f->setInventoryTextureCube("stone.png", "stone.png", "stone.png"); f->param_type = CPT_MINERAL; f->is_ground_content = true; @@ -96,13 +146,11 @@ void init_mapnode(IIrrlichtWrapper *irrlicht) f->setAllTextures("mud.png^grass_side.png"); f->setTexture(0, "grass.png"); f->setTexture(1, "mud.png"); - //f->setInventoryTexture(irrlicht->getTextureId("grass.png")); f->param_type = CPT_MINERAL; f->is_ground_content = true; i = CONTENT_GRASS_FOOTSTEPS; f = &g_content_features[i]; - //f->setInventoryTexture(irrlicht->getTextureId("grass_footsteps.png")); f->setAllTextures("mud.png^grass_side.png"); f->setTexture(0, "grass_footsteps.png"); f->setTexture(1, "mud.png"); @@ -126,7 +174,6 @@ void init_mapnode(IIrrlichtWrapper *irrlicht) f->setAllTextures("tree.png"); f->setTexture(0, "tree_top.png"); f->setTexture(1, "tree_top.png"); - //f->setInventoryTexture(irrlicht->getTextureId("tree_top.png")); f->param_type = CPT_MINERAL; f->is_ground_content = true; @@ -148,26 +195,21 @@ void init_mapnode(IIrrlichtWrapper *irrlicht) i = CONTENT_COALSTONE; f = &g_content_features[i]; //f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL); - /*f->setAllTextures(TextureSpec(irrlicht->getTextureId("coal.png"), - irrlicht->getTextureId("mineral_coal.png")));*/ f->setAllTextures("stone.png^mineral_coal.png"); f->is_ground_content = true; i = CONTENT_WOOD; f = &g_content_features[i]; - //f->setAllTextures(irrlicht->getTextureId("wood.png")); f->setAllTextures("wood.png"); f->is_ground_content = true; i = CONTENT_MESE; f = &g_content_features[i]; - //f->setAllTextures(irrlicht->getTextureId("mese.png")); f->setAllTextures("mese.png"); f->is_ground_content = true; i = CONTENT_CLOUD; f = &g_content_features[i]; - //f->setAllTextures(irrlicht->getTextureId("cloud.png")); f->setAllTextures("cloud.png"); f->is_ground_content = true; @@ -184,7 +226,7 @@ void init_mapnode(IIrrlichtWrapper *irrlicht) i = CONTENT_WATER; f = &g_content_features[i]; - //f->setInventoryTexture(irrlicht->getTextureId("water.png")); + f->setInventoryTextureCube("water.png", "water.png", "water.png"); f->param_type = CPT_LIGHT; f->light_propagates = true; f->solidness = 0; // Drawn separately, makes no faces @@ -196,7 +238,7 @@ void init_mapnode(IIrrlichtWrapper *irrlicht) i = CONTENT_WATERSOURCE; f = &g_content_features[i]; - //f->setInventoryTexture(irrlicht->getTextureId("water.png")); + f->setInventoryTexture("water.png"); if(new_style_water) { f->solidness = 0; // drawn separately, makes no faces @@ -224,6 +266,7 @@ void init_mapnode(IIrrlichtWrapper *irrlicht) i = CONTENT_TORCH; f = &g_content_features[i]; + f->setInventoryTexture("torch_on_floor.png"); f->param_type = CPT_LIGHT; f->light_propagates = true; f->solidness = 0; // drawn separately, makes no faces diff --git a/src/mapnode.h b/src/mapnode.h index 3de170598..37a0b3aa6 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -33,9 +33,15 @@ with this program; if not, write to the Free Software Foundation, Inc., Initializes all kind of stuff in here. Many things depend on this. - irrlicht: Used for getting texture ids. + This accesses g_texturesource; if it is non-NULL, textures are set. + + Client first calls this with g_texturesource=NULL to run some + unit tests and stuff, then it runs this again with g_texturesource + defined to get the textures. + + Server only calls this once with g_texturesource=NULL. */ -void init_mapnode(IIrrlichtWrapper *irrlicht); +void init_mapnode(); // Initializes g_content_inventory_texture_paths void init_content_inventory_texture_paths(); @@ -137,6 +143,7 @@ struct ContentFeatures //std::string inventory_image_path; //TextureSpec inventory_texture; //u32 inventory_texture_id; + video::ITexture *inventory_texture; bool is_ground_content; //TODO: Remove, use walkable instead bool light_propagates; @@ -155,6 +162,7 @@ struct ContentFeatures { translate_to = NULL; param_type = CPT_NONE; + inventory_texture = NULL; is_ground_content = false; light_propagates = false; sunlight_propagates = false; @@ -212,15 +220,10 @@ struct ContentFeatures } } - /*void setInventoryTexture(const TextureSpec &spec) - { - inventory_texture = spec; - }*/ - - /*void setInventoryImage(std::string imgname) - { - inventory_image_path = porting::getDataPath(imgname.c_str()); - }*/ + void setInventoryTexture(std::string imgname); + + void setInventoryTextureCube(std::string top, + std::string left, std::string right); }; /* diff --git a/src/materials.cpp b/src/materials.cpp index 7f1ba18bd..00d212c63 100644 --- a/src/materials.cpp +++ b/src/materials.cpp @@ -33,7 +33,7 @@ void initializeMaterialProperties() setStoneLikeDiggingProperties(CONTENT_STONE, 1.0); g_material_properties[CONTENT_GRASS].setDiggingProperties("", - DiggingProperties(true, 0.5, 0)); + DiggingProperties(true, 0.4, 0)); g_material_properties[CONTENT_TORCH].setDiggingProperties("", DiggingProperties(true, 0.0, 0)); @@ -42,7 +42,7 @@ void initializeMaterialProperties() DiggingProperties(true, 1.5, 0)); g_material_properties[CONTENT_LEAVES].setDiggingProperties("", - DiggingProperties(true, 0.5, 0)); + DiggingProperties(true, 0.35, 0)); g_material_properties[CONTENT_GRASS_FOOTSTEPS].setDiggingProperties("", DiggingProperties(true, 0.5, 0)); @@ -50,7 +50,7 @@ void initializeMaterialProperties() setStoneLikeDiggingProperties(CONTENT_MESE, 0.5); g_material_properties[CONTENT_MUD].setDiggingProperties("", - DiggingProperties(true, 0.5, 0)); + DiggingProperties(true, 0.4, 0)); setStoneLikeDiggingProperties(CONTENT_COALSTONE, 1.5); diff --git a/src/porting.h b/src/porting.h index 71891de39..441a57d77 100644 --- a/src/porting.h +++ b/src/porting.h @@ -30,7 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "debug.h" #include "constants.h" -#ifdef _WIN32 +#ifdef _MSC_VER #define SWPRINTF_CHARSTRING L"%S" #else #define SWPRINTF_CHARSTRING L"%s" diff --git a/src/socket.h b/src/socket.h index a56715d99..10bcdefee 100644 --- a/src/socket.h +++ b/src/socket.h @@ -22,10 +22,16 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN + // Without this some of the network functions are not found on mingw + #ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0501 + #endif #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h> - #pragma comment(lib, "wsock32.lib") + #ifdef _MSC_VER + #pragma comment(lib, "wsock32.lib") + #endif typedef SOCKET socket_t; typedef int socklen_t; #else diff --git a/src/tile.cpp b/src/tile.cpp index 7b19b3651..415830a87 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -626,8 +626,23 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, dstream<<"INFO: getTextureIdDirect(): generating special " <<"modification \""<<part_of_name<<"\"" <<std::endl; + + /* + This is the simplest of all; it just adds stuff to the + name so that a separate texture is created. - if(part_of_name.substr(0,6) == "[crack") + It is used to make textures for stuff that doesn't want + to implement getting the texture from a bigger texture + atlas. + */ + if(part_of_name == "[forcesingle") + { + } + /* + [crackN + Adds a cracking texture + */ + else if(part_of_name.substr(0,6) == "[crack") { if(baseimg == NULL) { @@ -671,9 +686,12 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, crackimage->drop(); } } + /* + [combine:WxH:X,Y=filename:X,Y=filename2 + Creates a bigger texture from an amount of smaller ones + */ else if(part_of_name.substr(0,8) == "[combine") { - // "[combine:16x128:0,0=stone.png:0,16=grass.png" Strfnd sf(part_of_name); sf.next(":"); u32 w0 = stoi(sf.next("x")); @@ -713,6 +731,10 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, } } } + /* + [progressbarN + Adds a progress bar, 0.0 <= N <= 1.0 + */ else if(part_of_name.substr(0,12) == "[progressbar") { if(baseimg == NULL) @@ -726,8 +748,13 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, float value = stof(part_of_name.substr(12)); make_progressbar(value, baseimg); } - // "[noalpha:filename.png" - // Use an image without it's alpha channel + /* + "[noalpha:filename.png" + Use an image without it's alpha channel. + Used for the leaves texture when in old leaves mode, so + that the transparent parts don't look completely black + when simple alpha channel is used for rendering. + */ else if(part_of_name.substr(0,8) == "[noalpha") { if(baseimg != NULL) @@ -771,6 +798,76 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, image->drop(); } } + /* + [inventorycube{topimage{leftimage{rightimage + In every subimage, replace ^ with &. + Create an "inventory cube". + NOTE: This should be used only on its own. + Example (a grass block (not actually used in game): + "[inventorycube{grass.png{mud.png&grass_side.png{mud.png&grass_side.png" + */ + else if(part_of_name.substr(0,14) == "[inventorycube") + { + if(baseimg != NULL) + { + dstream<<"WARNING: getTextureIdDirect(): baseimg!=NULL " + <<"for part_of_name="<<part_of_name + <<", cancelling."<<std::endl; + return false; + } + + // This is just a placeholder + + str_replace_char(part_of_name, '&', '^'); + Strfnd sf(part_of_name); + sf.next("{"); + std::string imagename_top = sf.next("{"); + std::string imagename_left = sf.next("{"); + std::string imagename_right = sf.next("{"); + + baseimg = generate_image_from_scratch( + imagename_top, driver); + + //TODO +#if 0 + if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false) + { + dstream<<"WARNING: getTextureIdDirect(): EVDF_RENDER_TO_TARGET" + " not supported"<<std::endl; + return false; + } + + u32 w0 = 16; + u32 h0 = 16; + dstream<<"INFO: inventorycube w="<<w0<<" h="<<h0<<std::endl; + core::dimension2d<u32> dim(w0,h0); + + //baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); + + video::IImage *img_top = generate_image_from_scratch( + imagename_top, driver); + video::IImage *img_left = generate_image_from_scratch( + imagename_left, driver); + video::IImage *img_right = generate_image_from_scratch( + imagename_right, driver); + + // Render target texture + video::ITexture *rtt = NULL; + std::string rtt_name = part_of_name + "_RTT"; + + rtt = driver->addRenderTargetTexture(dim, rtt_name.c_str()); + assert(rtt); + + + + img_top->drop(); + img_left->drop(); + img_right->drop(); + + //TODO + assert(0); +#endif + } else { dstream<<"WARNING: getTextureIdDirect(): Invalid " diff --git a/src/tile.h b/src/tile.h index b846b467b..2a342313d 100644 --- a/src/tile.h +++ b/src/tile.h @@ -192,6 +192,13 @@ public: { return getTexture(getTextureId(name)); } + + // Gets a separate texture + video::ITexture* getTextureRaw(const std::string &name) + { + AtlasPointer ap = getTexture(name); + return ap.atlas; + } private: /* diff --git a/src/utility.h b/src/utility.h index 7d8102b62..deaa78d90 100644 --- a/src/utility.h +++ b/src/utility.h @@ -716,6 +716,26 @@ inline std::string ftos(float f) return o.str(); } +inline void str_replace(std::string & str, std::string const & pattern, + std::string const & replacement) +{ + std::string::size_type start = str.find(pattern, 0); + while(start != str.npos) + { + str.replace(start, pattern.size(), replacement); + start = str.find(pattern, start+replacement.size()); + } +} + +inline void str_replace_char(std::string & str, char from, char to) +{ + for(unsigned int i=0; i<str.size(); i++) + { + if(str[i] == from) + str[i] = to; + } +} + /* A base class for simple background thread implementation */ |