diff --git a/common/lc_bricklink.cpp b/common/lc_bricklink.cpp index 98b09b2c..059ec7bc 100644 --- a/common/lc_bricklink.cpp +++ b/common/lc_bricklink.cpp @@ -2,6 +2,7 @@ #include "lc_file.h" #include "lc_library.h" #include "lc_mainwindow.h" +#include "lc_string.h" #include "pieceinf.h" static QJsonDocument lcLoadBrickLinkMapping() @@ -84,7 +85,7 @@ void lcExportBrickLink(const QString& SaveFileName, const lcPartsList& PartsList for (const auto& ColorIt : PartIt.second) { char FileName[LC_PIECE_NAME_LEN]; - strcpy(FileName, Info->mFileName); + lcstrcpy(FileName, Info->mFileName); char* Ext = strchr(FileName, '.'); if (Ext) *Ext = 0; diff --git a/common/lc_category.cpp b/common/lc_category.cpp index d862c68a..192ecb3f 100644 --- a/common/lc_category.cpp +++ b/common/lc_category.cpp @@ -1,6 +1,6 @@ #include "lc_global.h" #include "lc_category.h" -#include "lc_file.h" +#include "lc_string.h" #include "lc_profile.h" std::vector gCategories; @@ -261,7 +261,7 @@ bool lcMatchCategory(const char* PieceName, const char* Expression) if (!Word[0]) return false; - const char* Result = strcasestr(PieceName, Word); + const char* Result = lcstrcasestr(PieceName, Word); if (!Result) return false; diff --git a/common/lc_colors.cpp b/common/lc_colors.cpp index 3b77be85..262c5d21 100644 --- a/common/lc_colors.cpp +++ b/common/lc_colors.cpp @@ -3,6 +3,7 @@ #include "lc_file.h" #include "lc_library.h" #include "lc_application.h" +#include "lc_string.h" #include std::vector gColorList; @@ -79,7 +80,7 @@ static std::vector lcParseColorFile(lcFile& File) continue; GetToken(Ptr, Token); - strupr(Token); + lcstrupr(Token); if (strcmp(Token, "!COLOUR")) continue; @@ -107,7 +108,7 @@ static std::vector lcParseColorFile(lcFile& File) for (GetToken(Ptr, Token); Token[0]; GetToken(Ptr, Token)) { - strupr(Token); + lcstrupr(Token); if (!strcmp(Token, "CODE")) { @@ -258,8 +259,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle) MainColor.Edge[1] = 0.2f; MainColor.Edge[2] = 0.2f; MainColor.Edge[3] = 1.0f; - strcpy(MainColor.Name, "Main Color"); - strcpy(MainColor.SafeName, "Main_Color"); + lcstrcpy(MainColor.Name, "Main Color"); + lcstrcpy(MainColor.SafeName, "Main_Color"); Colors.push_back(MainColor); } @@ -281,8 +282,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle) EdgeColor.Edge[1] = 0.2f; EdgeColor.Edge[2] = 0.2f; EdgeColor.Edge[3] = 1.0f; - strcpy(EdgeColor.Name, "Edge Color"); - strcpy(EdgeColor.SafeName, "Edge_Color"); + lcstrcpy(EdgeColor.Name, "Edge Color"); + lcstrcpy(EdgeColor.SafeName, "Edge_Color"); Colors.push_back(EdgeColor); } @@ -299,8 +300,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle) StudCylinderColor.Group = LC_NUM_COLORGROUPS; StudCylinderColor.Value = lcVector4FromColor(Preferences.mStudCylinderColor); StudCylinderColor.Edge = lcVector4FromColor(Preferences.mPartEdgeColor); - strcpy(StudCylinderColor.Name, "Stud Cylinder Color"); - strcpy(StudCylinderColor.SafeName, "Stud_Cylinder_Color"); + lcstrcpy(StudCylinderColor.Name, "Stud Cylinder Color"); + lcstrcpy(StudCylinderColor.SafeName, "Stud_Cylinder_Color"); Colors.push_back(StudCylinderColor); } @@ -322,8 +323,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle) NoColor.Edge[1] = 0.2f; NoColor.Edge[2] = 0.2f; NoColor.Edge[3] = 1.0f; - strcpy(NoColor.Name, "No Color"); - strcpy(NoColor.SafeName, "No_Color"); + lcstrcpy(NoColor.Name, "No Color"); + lcstrcpy(NoColor.SafeName, "No_Color"); Colors.push_back(NoColor); } diff --git a/common/lc_filter.cpp b/common/lc_filter.cpp index e9656c1f..a008a820 100644 --- a/common/lc_filter.cpp +++ b/common/lc_filter.cpp @@ -1,5 +1,6 @@ #include "lc_global.h" #include "lc_filter.h" +#include "lc_string.h" lcFilter::lcFilter(const std::string_view FilterString) { @@ -80,7 +81,7 @@ bool lcFilter::Match(const char* String) const for (const FilterPart& FilterPart : mFilterParts) { - bool Match = FilterPart.Wildcard ? FastWildCompare(String, FilterPart.String.c_str()) : strcasestr(String, FilterPart.String.c_str()) != nullptr; + bool Match = FilterPart.Wildcard ? FastWildCompare(String, FilterPart.String.c_str()) : lcstrcasestr(String, FilterPart.String.c_str()) != nullptr; switch (FilterPart.Op) { diff --git a/common/lc_global.h b/common/lc_global.h index 9146f242..c9a7d227 100644 --- a/common/lc_global.h +++ b/common/lc_global.h @@ -67,12 +67,6 @@ class QPrinter; typedef quint32 lcStep; #define LC_STEP_MAX 0xffffffff -#ifdef Q_OS_WIN -char* strcasestr(const char *s, const char *find); -#else -char* strupr(char* string); -#endif - // Version number. #define LC_VERSION_MAJOR 25 #define LC_VERSION_MINOR 9 diff --git a/common/lc_library.cpp b/common/lc_library.cpp index 8f1b161c..fdf20d64 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -16,8 +16,7 @@ #include "project.h" #include "lc_profile.h" #include "lc_meshloader.h" -#include -#include +#include "lc_string.h" #include #include @@ -129,8 +128,8 @@ void lcPiecesLibrary::RenamePiece(PieceInfo* Info, const char* NewName) Info->m_strDescription[sizeof(Info->m_strDescription) - 1] = 0; char PieceName[LC_PIECE_NAME_LEN]; - strcpy(PieceName, Info->mFileName); - strupr(PieceName); + lcstrcpy(PieceName, Info->mFileName); + lcstrupr(PieceName); mPieces[PieceName] = Info; } @@ -761,7 +760,7 @@ void lcPiecesLibrary::ReadDirectoryDescriptions(const QFileInfoList (&FileLists) if (FileTime == CachedFileTime) { - strcpy(Info->m_strDescription, Description); + lcstrcpy(Info->m_strDescription, Description); return; } } @@ -769,7 +768,7 @@ void lcPiecesLibrary::ReadDirectoryDescriptions(const QFileInfoList (&FileLists) if (!PieceFile.Open(QIODevice::ReadOnly) || !PieceFile.ReadLine(Line, sizeof(Line))) { - strcpy(Info->m_strDescription, "Unknown"); + lcstrcpy(Info->m_strDescription, "Unknown"); return; } @@ -1668,9 +1667,9 @@ bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive) if (strncmp(Primitive->mName, "8/", 2)) // todo: this is currently the only place that uses mName so use mFileName instead. this should also be done for the loose file libraries. { char Name[LC_PIECE_NAME_LEN]; - strcpy(Name, "8/"); + lcstrcpy(Name, "8/"); strcat(Name, Primitive->mName); - strupr(Name); + lcstrupr(Name); LowPrimitive = FindPrimitive(Name); // todo: low primitives don't work with studlogo, because the low stud gets added as shared } @@ -1769,7 +1768,7 @@ void lcPiecesLibrary::GetCategoryEntries(const char* CategoryKeywords, bool Grou // Find the parent of this patterned piece. char ParentName[LC_PIECE_NAME_LEN]; - strcpy(ParentName, Info->mFileName); + lcstrcpy(ParentName, Info->mFileName); *strchr(ParentName, 'P') = '\0'; strcat(ParentName, ".dat"); diff --git a/common/lc_meshloader.cpp b/common/lc_meshloader.cpp index 0b64d388..d4b53ca3 100644 --- a/common/lc_meshloader.cpp +++ b/common/lc_meshloader.cpp @@ -5,6 +5,7 @@ #include "lc_library.h" #include "lc_application.h" #include "lc_texture.h" +#include "lc_string.h" static void lcCheckTexCoordsWrap(const lcVector4& Plane2, const lcVector3 (&Positions)[3], lcVector2 (&TexCoords)[3]) { @@ -589,7 +590,7 @@ lcMeshLoaderMaterial* lcLibraryMeshData::GetTexturedMaterial(quint32 ColorCode, Material->Points[2] = TextureMap.Points[2]; Material->Angles[0] = TextureMap.Angles[0]; Material->Angles[1] = TextureMap.Angles[1]; - strcpy(Material->Name, TextureMap.Name); + lcstrcpy(Material->Name, TextureMap.Name); return Material; } @@ -831,7 +832,7 @@ lcMesh* lcLibraryMeshData::CreateMesh() FinalSection.PrimitiveType = Section->mPrimitiveType; FinalSection.Color = Section->mMaterial->Color; - strcpy(FinalSection.Name, Section->mMaterial->Name); + lcstrcpy(FinalSection.Name, Section->mMaterial->Name); }; for (const std::unique_ptr& Section : mData[LC_MESHDATA_SHARED].mSections) @@ -1370,7 +1371,7 @@ bool lcMeshLoader::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform sscanf(Line, "%d %i %f %f %f %f %f %f %f %f %f %f %f %f %s", &LineType, &Dummy, &fm[0], &fm[1], &fm[2], &fm[3], &fm[4], &fm[5], &fm[6], &fm[7], &fm[8], &fm[9], &fm[10], &fm[11], OriginalFileName); char FileName[LC_MAXPATH]; - strcpy(FileName, OriginalFileName); + lcstrcpy(FileName, OriginalFileName); char* Ch; for (Ch = FileName; *Ch; Ch++) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 712ce667..a8180a24 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -23,6 +23,7 @@ #include "lc_qutils.h" #include "lc_lxf.h" #include "lc_previewwidget.h" +#include "lc_string.h" #include void lcModelProperties::LoadDefaults() @@ -4992,7 +4993,7 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) if (Params.FindInfo && Params.FindInfo != Piece->mPieceInfo) return false; - if (!Params.FindString.isEmpty() && !strcasestr(Piece->mPieceInfo->m_strDescription, Params.FindString.toLatin1())) + if (!Params.FindString.isEmpty() && !lcstrcasestr(Piece->mPieceInfo->m_strDescription, Params.FindString.toLatin1())) return false; return (lcGetColorCode(Params.FindColorIndex) == LC_COLOR_NOCOLOR) || (Piece->GetColorIndex() == Params.FindColorIndex); diff --git a/qt/system.cpp b/common/lc_string.cpp similarity index 53% rename from qt/system.cpp rename to common/lc_string.cpp index d201c97b..dcc8546e 100644 --- a/qt/system.cpp +++ b/common/lc_string.cpp @@ -1,11 +1,10 @@ #include "lc_global.h" +#include "lc_string.h" -#ifdef Q_OS_WIN - -char* strcasestr(const char* s, const char* find) +char* lcstrcasestr(const char* s, const char* find) { char c, sc; - + if ((c = *find++) != 0) { c = tolower((unsigned char)c); @@ -23,14 +22,30 @@ char* strcasestr(const char* s, const char* find) return ((char *)s); } -#else - -char* strupr(char* string) +char* lcstrupr(char* string) { for (char* c = string; *c; c++) *c = toupper(*c); - + return string; } -#endif +size_t lcstrcpy(char* dest, const char* source, size_t count) +{ + if (count == 0) + return 0; + + for (size_t i = 0; i < count; i++) + { + dest[i] = source[i]; + + if (source[i] == '\0') + { + return i; + } + } + + dest[--count] = '\0'; + + return count; +} diff --git a/common/lc_string.h b/common/lc_string.h new file mode 100644 index 00000000..3d4cdbdd --- /dev/null +++ b/common/lc_string.h @@ -0,0 +1,11 @@ +#pragma once + +char* lcstrcasestr(const char* s, const char* find); +char* lcstrupr(char* string); +size_t lcstrcpy(char* dest, const char* source, size_t count); + +template +size_t lcstrcpy(char (&dest)[size], const char* source) +{ + return lcstrcpy(dest, source, size); +} diff --git a/common/lc_texture.cpp b/common/lc_texture.cpp index 1f61a9c1..819e53e5 100644 --- a/common/lc_texture.cpp +++ b/common/lc_texture.cpp @@ -4,6 +4,7 @@ #include "lc_library.h" #include "image.h" #include "lc_glextensions.h" +#include "lc_string.h" lcTexture* gGridTexture; @@ -18,7 +19,7 @@ lcTexture* lcLoadTexture(const QString& FileName, int Flags) } else { - strcpy(Texture->mName, QFileInfo(FileName).baseName().toLatin1()); + lcstrcpy(Texture->mName, QFileInfo(FileName).baseName().toLatin1()); Texture->SetTemporary(true); } diff --git a/common/project.cpp b/common/project.cpp index ac0770c9..44545a42 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -1,7 +1,6 @@ #include "lc_global.h" #include "lc_math.h" #include "lc_mesh.h" -#include #include "pieceinf.h" #include "camera.h" #include "project.h" @@ -18,6 +17,7 @@ #include "lc_qimagedialog.h" #include "lc_modellistdialog.h" #include "lc_bricklink.h" +#include "lc_string.h" lcHTMLExportOptions::lcHTMLExportOptions(const Project* Project) { @@ -2413,7 +2413,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) if (!ModelPart.Mesh) { std::pair& Entry = PieceTable[ModelPart.Info]; - strcpy(Entry.first, "lc_"); + lcstrcpy(Entry.first, "lc_"); strncat(Entry.first, Name, sizeof(Entry.first) - 1); Entry.first[sizeof(Entry.first) - 1] = 0; } diff --git a/leocad.pro b/leocad.pro index adabb7da..15cf65d3 100644 --- a/leocad.pro +++ b/leocad.pro @@ -219,6 +219,7 @@ SOURCES += \ common/lc_propertieswidget.cpp \ common/lc_scene.cpp \ common/lc_shortcuts.cpp \ + common/lc_string.cpp \ common/lc_stringcache.cpp \ common/lc_synth.cpp \ common/lc_texture.cpp \ @@ -230,7 +231,6 @@ SOURCES += \ common/lc_viewsphere.cpp \ common/lc_viewwidget.cpp \ common/lc_zipfile.cpp \ - qt/system.cpp \ qt/qtmain.cpp \ qt/lc_qeditgroupsdialog.cpp \ qt/lc_qselectdialog.cpp \ @@ -298,6 +298,7 @@ HEADERS += \ common/lc_propertieswidget.h \ common/lc_scene.h \ common/lc_shortcuts.h \ + common/lc_string.h \ common/lc_stringcache.h \ common/lc_synth.h \ common/lc_texture.h \ diff --git a/qt/lc_qutils.cpp b/qt/lc_qutils.cpp index 4130876b..fe003e7d 100644 --- a/qt/lc_qutils.cpp +++ b/qt/lc_qutils.cpp @@ -4,8 +4,7 @@ #include "lc_library.h" #include "lc_model.h" #include "pieceinf.h" -#include "lc_partselectionwidget.h" -#include "lc_mainwindow.h" +#include "lc_string.h" #ifdef Q_OS_WIN #include @@ -238,7 +237,7 @@ std::vector lcPieceIdStringModel::GetFilteredRows(const QString& FilterTex { const PieceInfo* Info = mSortedPieces[PieceInfoIndex]; - FilteredRows[PieceInfoIndex] = (strcasestr(Info->m_strDescription, Text.c_str()) || strcasestr(Info->mFileName, Text.c_str())); + FilteredRows[PieceInfoIndex] = (lcstrcasestr(Info->m_strDescription, Text.c_str()) || lcstrcasestr(Info->mFileName, Text.c_str())); } return FilteredRows;