From 1cf703e34601b5a7657b4be4bf9b9ccfbe39517e Mon Sep 17 00:00:00 2001 From: Matt Mascarenhas Date: Tue, 30 Aug 2022 19:15:44 +0100 Subject: [PATCH] cinera: Fully handle auto-numbering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Renumber affected entries when inserting / deleting an entry of an auto-numbered project • Prohibit an entry from sharing an "output" with another entry • Prohibit an entry's "output" from containing a slash • Fix entry HTML deletion to use OutputLocation, not BaseFilename --- cinera/cinera.c | 488 +++++++++++++++++++++++++++++++----------------- 1 file changed, 315 insertions(+), 173 deletions(-) diff --git a/cinera/cinera.c b/cinera/cinera.c index fa23d8d..2beceb5 100644 --- a/cinera/cinera.c +++ b/cinera/cinera.c @@ -23,7 +23,7 @@ typedef struct version CINERA_APP_VERSION = { .Major = 0, .Minor = 10, - .Patch = 11 + .Patch = 12 }; #include // NOTE(matt): varargs @@ -949,6 +949,22 @@ StringsMatchSized(string A, int Size, string B) return FALSE; } +bool +StringContains(string S, string Substring) +{ + bool Result = FALSE; + string Test = S; + for(int64_t i = 0; i <= S.Length - Substring.Length; ++i, ++Test.Base, --Test.Length) + { + if(StringsMatchSized(Test, Substring.Length, Substring)) + { + Result = TRUE; + break; + } + } + return Result; +} + bool StringsMatchCaseInsensitive(string A, string B) { @@ -1003,6 +1019,7 @@ ExtensionMatches(string Path, extension_id Extension) // NOTE(matt): Extension i return Result; } +// NOTE(matt): For use with 0-terminated strings string Wrap0(char *String) { @@ -1012,8 +1029,11 @@ Wrap0(char *String) return Result; } +// NOTE(matt): For use with implicitly 0-terminated strings, i.e. fixed-size char arrays that may either be full of data, +// or filled after their data with 0s +#define Wrap0i(S) Wrap0i_(S, sizeof(S)) string -Wrap0i(char *S, uint64_t MaxSize) +Wrap0i_(char *S, uint64_t MaxSize) { string Result = {}; Result.Base = S; @@ -2015,6 +2035,24 @@ IndexingErrorSizing(string *Filename, uint64_t LineNumber, char *Key, string Rec fprintf(stderr, "\n"); } +void +IndexingErrorClash(string *Filename, uint64_t LineNumber, severity Severity, char *Key, string Received, string ExistingEntryBaseFilename) +{ + ErrorFilenameAndLineNumber(Filename, LineNumber, Severity, ED_INDEXING); + fprintf(stderr, "%s value %s%.*s%s clashes with that of existing entry: ", Key, ColourStrings[CS_MAGENTA_BOLD], (int)Received.Length, Received.Base, ColourStrings[CS_END]); + PrintStringC(CS_MAGENTA, ExistingEntryBaseFilename); + fprintf(stderr, "\n"); +} + +void +IndexingErrorInvalidSubstring(string *Filename, uint64_t LineNumber, char *Key, string Received, string InvalidSubstring) +{ + ErrorFilenameAndLineNumber(Filename, LineNumber, S_ERROR, ED_INDEXING); + fprintf(stderr, "%s value %s%.*s%s contains invalid substring: ", Key, ColourStrings[CS_MAGENTA_BOLD], (int)Received.Length, Received.Base, ColourStrings[CS_END]); + PrintStringC(CS_MAGENTA, InvalidSubstring); + fprintf(stderr, "\n"); +} + void IndexingErrorCustomSizing(string *Filename, uint64_t LineNumber, int CustomIndex, string Received) { @@ -4723,7 +4761,7 @@ PrintAsset(db_asset *A, uint16_t *Index) fprintf(stderr, "[%4u]", *Index); Colourise(CS_END); } - string FilenameL = Wrap0i(A->Filename, sizeof(A->Filename)); + string FilenameL = Wrap0i(A->Filename); fprintf(stderr, " %s asset: %.*s [%8x]\n", AssetTypeNames[A->Type], (int)FilenameL.Length, FilenameL.Base, A->Hash); @@ -5067,17 +5105,22 @@ LocateFirstEntry(db_header_project *P) } db_entry * -LocateEntry(db_project_index DBProjectIndex, int32_t EntryIndex) +LocateEntryOfProject(db_header_project *Project, int32_t EntryIndex) { - db_header_project *Project = LocateProject(DBProjectIndex); + db_entry *Result = 0; if(Project && EntryIndex < Project->EntryCount) { char *Ptr = (char *)Project; Ptr += sizeof(db_header_project) + sizeof(db_entry) * EntryIndex; - db_entry *Result = (db_entry *)Ptr; - return Result; + Result = (db_entry *)Ptr; } - return 0; + return Result; +} + +db_entry * +LocateEntry(db_project_index DBProjectIndex, int32_t EntryIndex) +{ + return LocateEntryOfProject(LocateProject(DBProjectIndex), EntryIndex); } void @@ -5197,7 +5240,7 @@ rc ReadGlobalSearchPageIntoBuffer(file *File) { db_block_projects *ProjectsBlock = DB.Metadata.Signposts.ProjectsBlock.Ptr ? DB.Metadata.Signposts.ProjectsBlock.Ptr : LocateBlock(B_PROJ); - string SearchLocationL = Wrap0i(ProjectsBlock->GlobalSearchDir, sizeof(ProjectsBlock->GlobalSearchDir)); + string SearchLocationL = Wrap0i(ProjectsBlock->GlobalSearchDir); File->Path = ConstructHTMLIndexFilePath(0, &SearchLocationL, 0); return ReadFileIntoBuffer(File); } @@ -5229,9 +5272,9 @@ SnipeChecksumIntoHTML(db_asset *Asset, asset_hash Checksum) db_entry *Entry = LocateEntry(Landmark->Project, Landmark->EntryIndex); if(Entry) { - string BaseDir = Wrap0i(P->BaseDir, sizeof(P->BaseDir)); - string PlayerLocation = Wrap0i(P->PlayerLocation, sizeof(P->PlayerLocation)); - string OutputLocation = Wrap0i(Entry->OutputLocation, sizeof(Entry->OutputLocation)); + string BaseDir = Wrap0i(P->BaseDir); + string PlayerLocation = Wrap0i(P->PlayerLocation); + string OutputLocation = Wrap0i(Entry->OutputLocation); FileReadRC = ReadPlayerPageIntoBuffer(&HTML, BaseDir, PlayerLocation, OutputLocation); } else @@ -5251,8 +5294,8 @@ SnipeChecksumIntoHTML(db_asset *Asset, asset_hash Checksum) { if(P) { - string BaseDir = Wrap0i(P->BaseDir, sizeof(P->BaseDir)); - string SearchLocation = Wrap0i(P->SearchLocation, sizeof(P->SearchLocation)); + string BaseDir = Wrap0i(P->BaseDir); + string SearchLocation = Wrap0i(P->SearchLocation); FileReadRC = ReadSearchPageIntoBuffer(&HTML, &BaseDir, &SearchLocation); } else @@ -5461,7 +5504,7 @@ WriteFilenameThenTargetPathIntoBook(memory_book *M, string Path, watch_type Type if(IsSymlink(OriginalPath0)) { int PathLength = readlink(OriginalPath0, ResolvedSymlinkPath, 4096); - FullPath = Wrap0i(ResolvedSymlinkPath, PathLength); + FullPath = Wrap0i_(ResolvedSymlinkPath, PathLength); } else { @@ -5717,8 +5760,8 @@ LocateAsset(db_block_assets *Block, asset *Asset, int *Index) for(int i = 0; i < Block->Count; ++i) { db_asset *StoredAsset = (db_asset *)Ptr; - string FilenameInDB = Wrap0i(StoredAsset->Filename, sizeof(StoredAsset->Filename)); - string FilenameInMemory = Wrap0i(Asset->Filename, sizeof(Asset->Filename)); + string FilenameInDB = Wrap0i(StoredAsset->Filename); + string FilenameInMemory = Wrap0i(Asset->Filename); if(StringsMatch(FilenameInDB, FilenameInMemory) && StoredAsset->Type == Asset->Type) { *Index = i; @@ -5789,7 +5832,7 @@ UpdateAssetInDB(asset *Asset) Ptr += sizeof(*Asset); file AssetFile = {}; - AssetFile.Path = ConstructAssetPath(&AssetFile, Wrap0i(StoredAsset->Filename, sizeof(StoredAsset->Filename)), StoredAsset->Type); + AssetFile.Path = ConstructAssetPath(&AssetFile, Wrap0i(StoredAsset->Filename), StoredAsset->Type); ResolvePath(&AssetFile.Path); string MessageEditType = MakeString("sss", ColourStrings[CS_ONGOING], "Updating", ColourStrings[CS_END]); @@ -5840,7 +5883,7 @@ UpdateAssetInDB(asset *Asset) StoredAsset.Height = Asset->Dimensions.Height; StoredAsset.Associated = Asset->Associated; - ClearCopyStringNoFormat(StoredAsset.Filename, sizeof(StoredAsset.Filename), Wrap0i(Asset->Filename, sizeof(Asset->Filename))); + ClearCopyStringNoFormat(StoredAsset.Filename, sizeof(StoredAsset.Filename), Wrap0i(Asset->Filename)); fwrite(&StoredAsset, sizeof(StoredAsset), 1, DB.Metadata.File.Handle); AccumulateFileEditSize(&DB.Metadata, sizeof(StoredAsset)); @@ -5928,7 +5971,7 @@ UpdateAsset(asset *Asset, bool Defer) { int32_t AssetIndexInDB = SAI_UNSET; file File = {}; - File.Path = ConstructAssetPath(&File, Wrap0i(Asset->Filename, sizeof(Asset->Filename)), Asset->Type); + File.Path = ConstructAssetPath(&File, Wrap0i(Asset->Filename), Asset->Type); ReadFileIntoBuffer(&File); if(File.Buffer.Location) @@ -6094,7 +6137,7 @@ InitAssets(void) for(int i = 0; i < AssetsBlock->Count; ++i) { - PushAsset(Wrap0i(Asset->Filename, sizeof(Asset->Filename)), Asset->Type, Asset->Variants, Asset->Associated); + PushAsset(Wrap0i(Asset->Filename), Asset->Type, Asset->Variants, Asset->Associated); Asset = SkipAsset(Asset); } } @@ -6105,7 +6148,7 @@ ConstructResolvedAssetURL(buffer *Buffer, asset *Asset, page_type PageType) { ClaimBuffer(Buffer, BID_URL_ASSET, (MAX_ROOT_URL_LENGTH + 1 + MAX_RELATIVE_ASSET_LOCATION_LENGTH + 1) * 2); ConstructURLPrefix(Buffer, Asset->Type, PageType); - CopyStringToBufferHTMLPercentEncoded(Buffer, Wrap0i(Asset->Filename, sizeof(Asset->Filename))); + CopyStringToBufferHTMLPercentEncoded(Buffer, Wrap0i(Asset->Filename)); string BufferL = {}; BufferL.Base = Buffer->Location; BufferL.Length = Buffer->Ptr - Buffer->Location; @@ -6121,7 +6164,7 @@ InitialString(memory_book *Abbreviations, string Src) { ResetPen(Abbreviations); string Result = {}; - string Char = Wrap0i(Src.Base, 1); + string Char = Wrap0i_(Src.Base, 1); Result = ExtendStringInBook(Abbreviations, Char); for(int i = 1; i < Src.Length; ++i) @@ -6129,7 +6172,7 @@ InitialString(memory_book *Abbreviations, string Src) if(Src.Base[i] == ' ' && i < Src.Length) { ++i; - Char = Wrap0i(Src.Base + i, 1); + Char = Wrap0i_(Src.Base + i, 1); Result = ExtendStringInBook(Abbreviations, Char); } } @@ -6160,11 +6203,11 @@ InitialAndGetFinalString(memory_book *Abbreviations, string Src) ++FinalStringBase; } - string FinalString = Wrap0i(Src.Base + FinalStringBase, Src.Length - FinalStringBase); + string FinalString = Wrap0i_(Src.Base + FinalStringBase, Src.Length - FinalStringBase); if(FinalStringBase > 0) { - string Initial = Wrap0i(Src.Base, 1); + string Initial = Wrap0i_(Src.Base, 1); Result = ExtendStringInBook(Abbreviations, Initial); Result = ExtendStringInBook(Abbreviations, Wrap0(". ")); @@ -6173,7 +6216,7 @@ InitialAndGetFinalString(memory_book *Abbreviations, string Src) if(Src.Base[i] == ' ' && i + 1 < FinalStringBase) { ++i; - string Initial = Wrap0i(Src.Base + i, 1); + string Initial = Wrap0i_(Src.Base + i, 1); Result = ExtendStringInBook(Abbreviations, Initial); Result = ExtendStringInBook(Abbreviations, Wrap0(". ")); } @@ -6269,7 +6312,7 @@ GetAsset(string Filename, asset_type AssetType) for(int i = 0; i < Assets.ItemCount; ++i) { asset *This = GetPlaceInBook(&Assets, i); - if(StringsMatch(Filename, Wrap0i(This->Filename, sizeof(This->Filename))) + if(StringsMatch(Filename, Wrap0i(This->Filename)) && AssetType == This->Type) { Result = This; @@ -6400,7 +6443,7 @@ SyncAssetAssociation(string Path, uint64_t Variants, db_project_index Index, ass if(OldIndex >= 0 && OldIndex != NewIndex) { db_asset *OldAssetInDB = LocateAssetByIndex(OldIndex); - asset *OldAsset = GetAsset(Wrap0i(OldAssetInDB->Filename, sizeof(OldAssetInDB->Filename)), OldAssetInDB->Type); + asset *OldAsset = GetAsset(Wrap0i(OldAssetInDB->Filename), OldAssetInDB->Type); ConfirmAssociations(OldAsset, OldAssetInDB, OldIndex); //DeleteStaleAssets(); // TODO(matt): Maybe do this later? } @@ -7380,7 +7423,7 @@ BuildQuote(memory_book *Strings, quote_info *Info, string Speaker, int ID, bool } else { - MakeDir(Wrap0i(QuoteCacheDir, sizeof(QuoteCacheDir))); + MakeDir(Wrap0i(QuoteCacheDir)); QuoteCache = fopen(QuoteCachePath, "a+"); if(QuoteCache) { @@ -8550,8 +8593,8 @@ void ConstructPlayerURL(buffer *PlayerURL, db_header_project *P, string EntryOutput) { RewindBuffer(PlayerURL); - string BaseURL = Wrap0i(P->BaseURL, sizeof(P->BaseURL)); - string PlayerLocation = Wrap0i(P->PlayerLocation, sizeof(P->PlayerLocation)); + string BaseURL = Wrap0i(P->BaseURL); + string PlayerLocation = Wrap0i(P->PlayerLocation); if(BaseURL.Length > 0) { CopyStringToBuffer(PlayerURL, "%.*s/", (int)BaseURL.Length, BaseURL.Base); @@ -8890,14 +8933,14 @@ PrintAssetIndex(int32_t Index) void * PrintProjectAndChildren(db_header_project *P, typography T) { - string ID = Wrap0i(P->ID, sizeof(P->ID)); - string Title = Wrap0i(P->Title, sizeof(P->Title)); - string BaseDir = Wrap0i(P->BaseDir, sizeof(P->BaseDir)); - string BaseURL = Wrap0i(P->BaseURL, sizeof(P->BaseURL)); - string SearchLocation = Wrap0i(P->SearchLocation, sizeof(P->SearchLocation)); - string PlayerLocation = Wrap0i(P->PlayerLocation, sizeof(P->PlayerLocation)); - string Theme = Wrap0i(P->Theme, sizeof(P->Theme)); - string Unit = Wrap0i(P->Unit, sizeof(P->Unit)); + string ID = Wrap0i(P->ID); + string Title = Wrap0i(P->Title); + string BaseDir = Wrap0i(P->BaseDir); + string BaseURL = Wrap0i(P->BaseURL); + string SearchLocation = Wrap0i(P->SearchLocation); + string PlayerLocation = Wrap0i(P->PlayerLocation); + string Theme = Wrap0i(P->Theme); + string Unit = Wrap0i(P->Unit); fprintf(stderr, "\n"); PrintC(CS_YELLOW_BOLD, "\nID"); fprintf(stderr, ": "); PrintStringC(CS_GREEN_BOLD, ID); @@ -8925,10 +8968,10 @@ PrintProjectAndChildren(db_header_project *P, typography T) { db_entry *E = (db_entry *)Ptr; - string EntryHMMLBaseFilename = Wrap0i(E->HMMLBaseFilename, sizeof(E->HMMLBaseFilename)); - string EntryOutputLocation = Wrap0i(E->OutputLocation, sizeof(E->OutputLocation)); - string EntryTitle = Wrap0i(E->Title, sizeof(E->Title)); - string Number = Wrap0i(E->Number, sizeof(E->Number)); + string EntryHMMLBaseFilename = Wrap0i(E->HMMLBaseFilename); + string EntryOutputLocation = Wrap0i(E->OutputLocation); + string EntryTitle = Wrap0i(E->Title); + string Number = Wrap0i(E->Number); fprintf(stderr, "\n" "%s%s%s%s%s ", T.UpperLeftCorner, @@ -9599,13 +9642,13 @@ FreeReferences(_memory_book(ref_info) *References) bool HMMLBaseFilenameIs(neighbourhood *N, char *ID) { - return StringsMatch(Wrap0i(N->WorkingThis.HMMLBaseFilename, sizeof(N->WorkingThis.HMMLBaseFilename)), Wrap0(ID)); + return StringsMatch(Wrap0i(N->WorkingThis.HMMLBaseFilename), Wrap0(ID)); } bool HMMLOutputLocationIs(neighbourhood *N, char *OutputLocation) { - return StringsMatch(Wrap0i(N->WorkingThis.OutputLocation, sizeof(N->WorkingThis.OutputLocation)), Wrap0(OutputLocation)); + return StringsMatch(Wrap0i(N->WorkingThis.OutputLocation), Wrap0(OutputLocation)); } bool @@ -10075,6 +10118,7 @@ typedef struct typedef struct { typed_value Value; + int DigitsInHighestNumber; uint64_t ZeroPadding; } numbering_info; @@ -10093,6 +10137,7 @@ GetEntryNumbering(project *P, string HMMLBaseFilename, string SpecifiedNumber, u Result.Value.int64_t = ThisNumber; if(P->Numbering.Auto.ZeroPadded) { + Result.DigitsInHighestNumber = DigitsInInt(&HighestNumber); Result.ZeroPadding = DigitsInInt(&HighestNumber) - DigitsInInt(&ThisNumber); } } break; @@ -10131,6 +10176,27 @@ CopyProjectEndStringToBuffer(buffer *B, string ProjectTitle) "
You have arrived at the (current) end of %.*s
\n", (int)ProjectTitle.Length, ProjectTitle.Base); } +db_entry * +FieldClashes_String(db_header_project *Header, uint32_t FieldOffset, uint32_t FieldSize, string NewHMMLBaseFilename, string NewString) +{ + db_entry *Result = 0; + db_entry *Test = LocateFirstEntry(Header); + for(int i = 0; i < Header->EntryCount; ++i, ++Test) + { + char *Ptr = (char *)Test; + Ptr += FieldOffset; + if(StringsMatch(NewString, Wrap0i_(Ptr, FieldSize))) + { + if(StringsDiffer(NewHMMLBaseFilename, Wrap0i(Test->HMMLBaseFilename))) + { + Result = Test; + } + break; + } + } + return Result; +} + rc HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseFilename, neighbourhood *N, uint64_t EntryCount) { @@ -10292,22 +10358,22 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF Result = RC_ERROR_HMML; } - if(!HMML.metadata.number) + if(CurrentProject->Numbering.Method == NM_HMML_SPECIFIED) { - if(CurrentProject->Numbering.Method == NM_HMML_SPECIFIED) + if(!HMML.metadata.number) { IndexingError(FilepathL, 0, S_ERROR, "No number set in the [video] node", 0); Result = RC_ERROR_HMML; } - } - else if(StringLength(HMML.metadata.number) > sizeof(N->WorkingThis.Number)) - { - IndexingErrorSizing(&FilepathL, 0, "number", Wrap0(HMML.metadata.number), MAX_NUMBER_LENGTH); - Result = RC_ERROR_HMML; - } - else - { - ClearCopyStringNoFormat(N->WorkingThis.Number, sizeof(N->WorkingThis.Number), Wrap0(HMML.metadata.number)); + else if(StringLength(HMML.metadata.number) > sizeof(N->WorkingThis.Number)) + { + IndexingErrorSizing(&FilepathL, 0, "number", Wrap0(HMML.metadata.number), MAX_NUMBER_LENGTH); + Result = RC_ERROR_HMML; + } + else + { + ClearCopyStringNoFormat(N->WorkingThis.Number, sizeof(N->WorkingThis.Number), Wrap0(HMML.metadata.number)); + } } string OutputLocation = {}; @@ -10320,11 +10386,39 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF IndexingErrorSizing(&FilepathL, 0, "output", Wrap0(HMML.metadata.output), MAX_ENTRY_OUTPUT_LENGTH); Result = RC_ERROR_HMML; } + else if(StringContains(Wrap0(HMML.metadata.output), Wrap0("/"))) + { + IndexingErrorInvalidSubstring(&FilepathL, 0, "output", Wrap0(HMML.metadata.output), Wrap0("/")); + Result = RC_ERROR_HMML; + } else { OutputLocation = Wrap0(HMML.metadata.output); } + if(Result == RC_SUCCESS) // Clash Tests + { + db_entry *ClashTest = FieldClashes_String(N->Project, offsetof(db_entry, OutputLocation), sizeof(N->WorkingThis.OutputLocation), BaseFilename, OutputLocation); + if(ClashTest) + { + // NOTE(matt): This clash is fatal because letting it go through would make the encroaching entry's + // HTML file overwrite that of an existing entry + IndexingErrorClash(&FilepathL, 0, S_ERROR, "output", OutputLocation, Wrap0i(ClashTest->HMMLBaseFilename)); + Result = RC_ERROR_HMML; + } + + if(CurrentProject->Numbering.Method == NM_HMML_SPECIFIED) + { + ClashTest = FieldClashes_String(N->Project, offsetof(db_entry, Number), sizeof(N->WorkingThis.Number), BaseFilename, Wrap0i(N->WorkingThis.Number)); + if(ClashTest) + { + // NOTE(matt): This clash is nonfatal because the number has no purpose other than to be + // displayed beside the entry's title on the search page + IndexingErrorClash(&FilepathL, 0, S_WARNING, "number", Wrap0i(N->WorkingThis.Number), Wrap0i(ClashTest->HMMLBaseFilename)); + } + } + } + string ProjectTitle = BestTitleForHTML(CurrentProject); // TODO(matt): Handle the art and art_variants once .hmml supports them @@ -10380,14 +10474,14 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF buffer URLPlayer = {}; ClaimBuffer(&URLPlayer, BID_URL_PLAYER, MAX_BASE_URL_LENGTH + SLASH + MAX_RELATIVE_PAGE_LOCATION_LENGTH + SLASH + sizeof(N->WorkingThis.OutputLocation)); - ConstructPlayerURL(&URLPlayer, N->Project, Wrap0i(N->WorkingThis.OutputLocation, sizeof(N->WorkingThis.OutputLocation))); + ConstructPlayerURL(&URLPlayer, N->Project, Wrap0i(N->WorkingThis.OutputLocation)); CopyString(CollationBuffers->URLPlayer, sizeof(CollationBuffers->URLPlayer), "%s", URLPlayer.Location); DeclaimBuffer(&URLPlayer); if(N->This) { - string OldOutputLocation = Wrap0i(N->This->OutputLocation, sizeof(N->This->OutputLocation)); - string NewOutputLocation = Wrap0i(N->WorkingThis.OutputLocation, sizeof(N->WorkingThis.OutputLocation)); + string OldOutputLocation = Wrap0i(N->This->OutputLocation); + string NewOutputLocation = Wrap0i(N->WorkingThis.OutputLocation); if(StringsDiffer(OldOutputLocation, NewOutputLocation)) { DeletePlayerPageFromFilesystem(CurrentProject->BaseDir, CurrentProject->PlayerLocation, OldOutputLocation, FALSE, TRUE); @@ -10471,7 +10565,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF // TODO(matt): Once we have a more rigorous notion of "Day Numbers", perhaps also use them here buffer PreviousPlayerURL = {}; ClaimBuffer(&PreviousPlayerURL, BID_PREVIOUS_PLAYER_URL, MAX_BASE_URL_LENGTH + 1 + MAX_RELATIVE_PAGE_LOCATION_LENGTH + 1 + MAX_BASE_FILENAME_LENGTH); - ConstructPlayerURL(&PreviousPlayerURL, N->Project, Wrap0i(N->Prev->OutputLocation, sizeof(N->Prev->OutputLocation))); + ConstructPlayerURL(&PreviousPlayerURL, N->Project, Wrap0i(N->Prev->OutputLocation)); CopyStringToBuffer(&PlayerBuffers.Main, "
Previous: '%s'
\n", PreviousPlayerURL.Location, @@ -10496,7 +10590,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF { CopyStringToBuffer(&CollationBuffers->SearchEntry, "location: \"%.*s\"\n", (int)OutputLocation.Length, OutputLocation.Base); CopyStringToBuffer(&CollationBuffers->SearchEntry, "number: \""); - numbering_info Number = GetEntryNumbering(CurrentProject, BaseFilename, Wrap0i(N->WorkingThis.Number, sizeof(N->WorkingThis.Number)), N->ThisIndex, EntryCount); + numbering_info Number = GetEntryNumbering(CurrentProject, BaseFilename, Wrap0i(N->WorkingThis.Number), N->ThisIndex, EntryCount); switch(Number.Value.Type) { case PT_STRING: @@ -10505,11 +10599,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF } break; case PT_INT64: { - for(int i = 0; i < Number.ZeroPadding; ++i) - { - CopyStringToBuffer(&CollationBuffers->SearchEntry, "0"); - } - CopyStringToBuffer(&CollationBuffers->SearchEntry, "%li", Number.Value.int64_t); + CopyStringToBuffer(&CollationBuffers->SearchEntry, "%0*li", Number.DigitsInHighestNumber, Number.Value.int64_t); } break; default: break; } @@ -10893,7 +10983,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF // TODO(matt): Once we have a more rigorous notion of "Day Numbers", perhaps also use them here buffer NextPlayerURL = {}; ClaimBuffer(&NextPlayerURL, BID_NEXT_PLAYER_URL, MAX_BASE_URL_LENGTH + 1 + MAX_RELATIVE_PAGE_LOCATION_LENGTH + 1 + MAX_BASE_FILENAME_LENGTH); - ConstructPlayerURL(&NextPlayerURL, N->Project, Wrap0i(N->Next->OutputLocation, sizeof(N->Next->OutputLocation))); + ConstructPlayerURL(&NextPlayerURL, N->Project, Wrap0i(N->Next->OutputLocation)); CopyStringToBuffer(&PlayerBuffers.Main, "
Next: '%s'
\n", NextPlayerURL.Location, @@ -11497,13 +11587,13 @@ BuffersToHTML(config *C, project *Project, buffers *CollationBuffers, template * case TAG_PROJECT_ID: CopyStringToBufferNoFormat(&Master, Project->ID); break; // NOTE(matt): Not HTML-safe case TAG_PROJECT_LINEAGE: CopyStringToBufferHTMLSafe(&Master, Project->WrittenLineage); break; case TAG_PROJECT_PLAIN: CopyStringToBufferHTMLSafe(&Master, Project->Title); break; - case TAG_SEARCH_URL: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->URLSearch, sizeof(CollationBuffers->URLSearch))); break; // NOTE(matt): Not HTML-safe + case TAG_SEARCH_URL: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->URLSearch)); break; // NOTE(matt): Not HTML-safe case TAG_THEME: CopyStringToBufferNoFormat(&Master, Project->Theme); break; // NOTE(matt): Not HTML-safe - case TAG_TITLE: CopyStringToBufferHTMLSafe(&Master, Wrap0i(CollationBuffers->Title, sizeof(CollationBuffers->Title))); break; + case TAG_TITLE: CopyStringToBufferHTMLSafe(&Master, Wrap0i(CollationBuffers->Title)); break; case TAG_URL: if(PageType == PAGE_PLAYER) { - CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->URLPlayer, sizeof(CollationBuffers->URLPlayer))); + CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->URLPlayer)); } else { @@ -11513,11 +11603,11 @@ BuffersToHTML(config *C, project *Project, buffers *CollationBuffers, template * } else { - CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->URLSearch, sizeof(CollationBuffers->URLSearch))); + CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->URLSearch)); } } break; - case TAG_VIDEO_ID: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->VideoID, sizeof(CollationBuffers->VideoID))); break; + case TAG_VIDEO_ID: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->VideoID)); break; case TAG_VOD_PLATFORM: CopyStringToBufferNoFormat(&Master, Wrap0(VODPlatformStrings[CollationBuffers->VODPlatform])); break; case TAG_SEARCH: { @@ -11591,22 +11681,22 @@ BuffersToHTML(config *C, project *Project, buffers *CollationBuffers, template * // point - we'll need to correctly offset its landmarks here CopyLandmarkedBuffer(&Master, &Tag->Nav->Buffer, 0, PageType); } break; - case TAG_CUSTOM0: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom0, sizeof(CollationBuffers->Custom0))); break; - case TAG_CUSTOM1: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom1, sizeof(CollationBuffers->Custom1))); break; - case TAG_CUSTOM2: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom2, sizeof(CollationBuffers->Custom2))); break; - case TAG_CUSTOM3: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom3, sizeof(CollationBuffers->Custom3))); break; - case TAG_CUSTOM4: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom4, sizeof(CollationBuffers->Custom4))); break; - case TAG_CUSTOM5: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom5, sizeof(CollationBuffers->Custom5))); break; - case TAG_CUSTOM6: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom6, sizeof(CollationBuffers->Custom6))); break; - case TAG_CUSTOM7: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom7, sizeof(CollationBuffers->Custom7))); break; - case TAG_CUSTOM8: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom8, sizeof(CollationBuffers->Custom8))); break; - case TAG_CUSTOM9: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom9, sizeof(CollationBuffers->Custom9))); break; - case TAG_CUSTOM10: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom10, sizeof(CollationBuffers->Custom10))); break; - case TAG_CUSTOM11: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom11, sizeof(CollationBuffers->Custom11))); break; - case TAG_CUSTOM12: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom12, sizeof(CollationBuffers->Custom12))); break; - case TAG_CUSTOM13: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom13, sizeof(CollationBuffers->Custom13))); break; - case TAG_CUSTOM14: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom14, sizeof(CollationBuffers->Custom14))); break; - case TAG_CUSTOM15: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom15, sizeof(CollationBuffers->Custom15))); break; + case TAG_CUSTOM0: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom0)); break; + case TAG_CUSTOM1: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom1)); break; + case TAG_CUSTOM2: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom2)); break; + case TAG_CUSTOM3: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom3)); break; + case TAG_CUSTOM4: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom4)); break; + case TAG_CUSTOM5: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom5)); break; + case TAG_CUSTOM6: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom6)); break; + case TAG_CUSTOM7: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom7)); break; + case TAG_CUSTOM8: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom8)); break; + case TAG_CUSTOM9: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom9)); break; + case TAG_CUSTOM10: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom10)); break; + case TAG_CUSTOM11: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom11)); break; + case TAG_CUSTOM12: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom12)); break; + case TAG_CUSTOM13: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom13)); break; + case TAG_CUSTOM14: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom14)); break; + case TAG_CUSTOM15: CopyStringToBufferNoFormat(&Master, Wrap0i(CollationBuffers->Custom15)); break; case TEMPLATE_TAG_COUNT: break; } DepartComment(&Template->File.Buffer); @@ -11727,7 +11817,7 @@ BinarySearchForMetadataEntry(db_header_project *Header, db_entry **Entry, string db_entry *FirstEntry = (db_entry *)Ptr; int Lower = 0; db_entry *LowerEntry = FirstEntry + Lower; - if(StringsDiffer(SearchTerm, Wrap0i(LowerEntry->HMMLBaseFilename, sizeof(LowerEntry->HMMLBaseFilename))) < 0 ) { return -1; } + if(StringsDiffer(SearchTerm, Wrap0i(LowerEntry->HMMLBaseFilename)) < 0 ) { return -1; } int Upper = Header->EntryCount - 1; int Pivot = Upper - ((Upper - Lower) >> 1); @@ -11739,11 +11829,11 @@ BinarySearchForMetadataEntry(db_header_project *Header, db_entry **Entry, string PivotEntry = FirstEntry + Pivot; UpperEntry = FirstEntry + Upper; - if(!StringsDiffer(SearchTerm, Wrap0i(LowerEntry->HMMLBaseFilename, sizeof(LowerEntry->HMMLBaseFilename)))) { *Entry = LowerEntry; return Lower; } - if(!StringsDiffer(SearchTerm, Wrap0i(PivotEntry->HMMLBaseFilename, sizeof(PivotEntry->HMMLBaseFilename)))) { *Entry = PivotEntry; return Pivot; } - if(!StringsDiffer(SearchTerm, Wrap0i(UpperEntry->HMMLBaseFilename, sizeof(UpperEntry->HMMLBaseFilename)))) { *Entry = UpperEntry; return Upper; } + if(!StringsDiffer(SearchTerm, Wrap0i(LowerEntry->HMMLBaseFilename))) { *Entry = LowerEntry; return Lower; } + if(!StringsDiffer(SearchTerm, Wrap0i(PivotEntry->HMMLBaseFilename))) { *Entry = PivotEntry; return Pivot; } + if(!StringsDiffer(SearchTerm, Wrap0i(UpperEntry->HMMLBaseFilename))) { *Entry = UpperEntry; return Upper; } - if(StringsDiffer(SearchTerm, Wrap0i(PivotEntry->HMMLBaseFilename, sizeof(PivotEntry->HMMLBaseFilename))) < 0) { Upper = Pivot; } + if(StringsDiffer(SearchTerm, Wrap0i(PivotEntry->HMMLBaseFilename)) < 0) { Upper = Pivot; } else { Lower = Pivot; } Pivot = Upper - ((Upper - Lower) >> 1); } while(Upper > Pivot); @@ -11881,9 +11971,9 @@ InitNeighbourhood(neighbourhood *N) _exit(1); } - if(StringsDiffer(CurrentProject->ID, Wrap0i(N->Project->ID, sizeof(N->Project->ID)))) + if(StringsDiffer(CurrentProject->ID, Wrap0i(N->Project->ID))) { - string StoredID = Wrap0i(N->Project->ID, sizeof(N->Project->ID)); + string StoredID = Wrap0i(N->Project->ID); Colourise(CS_ERROR); fprintf(stderr, "Project in DB located by ProjectIndex (%.*s) does not match the project got from the config (%.*s)\n", (int)StoredID.Length, StoredID.Base, (int)CurrentProject->ID.Length, CurrentProject->ID.Base); Colourise(CS_END); @@ -12117,6 +12207,48 @@ GetNeighbourhood(neighbourhood *N, edit_type_id EditType) DB.Metadata.Signposts.Next.Ptr = N->Next; } +void +RenumberEntries(neighbourhood *N, db_header_project *P, int64_t IndexOfFirstEntryToRenumber) +{ + db_entry *Entry = LocateEntryOfProject(P, IndexOfFirstEntryToRenumber); + int EntryOffset = AccumulateDBEntryInsertionOffset(P, IndexOfFirstEntryToRenumber); + char *Cursor = DB.File.Buffer.Location; + DB.File.Buffer.Ptr = DB.File.Buffer.Location + EntryOffset; + + if(!(DB.File.Handle = fopen(DB.File.Path, "w"))) { return; } + Cursor += fwrite(Cursor, 1, EntryOffset, DB.File.Handle); + + for(int i = IndexOfFirstEntryToRenumber; i < P->EntryCount; ++i) + { + char *Start = Cursor; + int OldSize = Entry->Size; + + SeekBufferForString(&DB.File.Buffer, "\nnumber: \"", C_SEEK_FORWARDS, C_SEEK_AFTER); + Cursor += fwrite(Cursor, 1, DB.File.Buffer.Ptr - Cursor, DB.File.Handle); + + SeekBufferForString(&DB.File.Buffer, "\"\n", C_SEEK_FORWARDS, C_SEEK_START); + int NumberLength = DB.File.Buffer.Ptr - Cursor; + Cursor = DB.File.Buffer.Ptr; + + string Blank = {}; + numbering_info NumberingInfo = GetEntryNumbering(CurrentProject, Blank, Blank, i, P->EntryCount); + + int NewNumberLength = fprintf(DB.File.Handle, "%0*li", NumberingInfo.DigitsInHighestNumber, NumberingInfo.Value.int64_t); + Entry->Size += NewNumberLength - NumberLength; + + Cursor += fwrite(Cursor, 1, OldSize - (Cursor - Start), DB.File.Handle); + ++Entry; + } + + Cursor += fwrite(Cursor, 1, DB.File.Buffer.Size - (Cursor - DB.File.Buffer.Location), DB.File.Handle); + CycleFile(&DB.File); + + if(!(DB.Metadata.File.Handle = fopen(DB.Metadata.File.Path, "w"))) { return; } + fwrite(DB.Metadata.File.Buffer.Location, 1, DB.Metadata.File.Buffer.Size, DB.Metadata.File.Handle); + CycleSignpostedFile(&DB.Metadata); + UpdateNeighbourhoodPointers(N, &DB.Metadata.Signposts); +} + db_entry * InsertIntoDB(neighbourhood *N, buffers *CollationBuffers, template *BespokeTemplate, string BaseFilename, bool RecheckingPrivacy, bool *Reinserting) { @@ -12145,7 +12277,7 @@ InsertIntoDB(neighbourhood *N, buffers *CollationBuffers, template *BespokeTempl if(N->ThisIndex == -1) { ++N->ThisIndex; } // NOTE(matt): BinarySearchForMetadataEntry returns -1 if search term precedes the set db_entry *Test = FirstEntry + N->ThisIndex; //N->WorkingThis = *(FirstEntry + N->ThisIndex); - if(StringsDiffer(BaseFilename, Wrap0i(Test->HMMLBaseFilename, sizeof(Test->HMMLBaseFilename))) < 0) + if(StringsDiffer(BaseFilename, Wrap0i(Test->HMMLBaseFilename)) < 0) { // Insert EditType = EDIT_INSERTION; @@ -12175,7 +12307,7 @@ InsertIntoDB(neighbourhood *N, buffers *CollationBuffers, template *BespokeTempl ClearCopyStringNoFormat(N->WorkingThis.HMMLBaseFilename, sizeof(N->WorkingThis.HMMLBaseFilename), BaseFilename); - if(!VideoIsPrivate) { ClearCopyStringNoFormat(N->WorkingThis.Title, sizeof(N->WorkingThis.Title), Wrap0i(CollationBuffers->Title, sizeof(CollationBuffers->Title))); } + if(!VideoIsPrivate) { ClearCopyStringNoFormat(N->WorkingThis.Title, sizeof(N->WorkingThis.Title), Wrap0i(CollationBuffers->Title)); } if(!DB.File.Buffer.Location) { @@ -12229,15 +12361,19 @@ InsertIntoDB(neighbourhood *N, buffers *CollationBuffers, template *BespokeTempl CycleSignpostedFile(&DB.Metadata); UpdateNeighbourhoodPointers(N, &DB.Metadata.Signposts); - char *EntryInDB = DB.Metadata.File.Buffer.Location + BytesIntoFile; - N->This = (db_entry *)EntryInDB; + DB.Metadata.Signposts.This.Ptr = DB.Metadata.File.Buffer.Location + BytesIntoFile; + N->This = DB.Metadata.Signposts.This.Ptr; if(!(DB.File.Handle = fopen(DB.File.Path, "w"))) { return 0; } fwrite(DB.File.Buffer.Location, EntryInsertionStart, 1, DB.File.Handle); fwrite(CollationBuffers->SearchEntry.Location, N->This->Size, 1, DB.File.Handle); fwrite(DB.File.Buffer.Location + EntryInsertionStart, DB.File.Buffer.Size - EntryInsertionStart, 1, DB.File.Handle); - CycleFile(&DB.File); + + if(CurrentProject->Numbering.Method == NM_AUTO) + { + RenumberEntries(N, N->Project, N->ThisIndex + 1); + } } if(!VideoIsPrivate || !RecheckingPrivacy) @@ -12566,7 +12702,7 @@ AddLandmarks(neighbourhood *N, project *P, edit_type_id EditType) asset *AssetInMemory = GetPlaceInBook(&Assets, i); // TODO(matt): Exhaustively test BinarySearchForMetadataLandmark() and figure out why ProcessPrevLandmarks() / // ProcessNextLandmarks() are apparently failing to write out all the existing landmarks - if(!StringsDiffer(Wrap0i(Asset->Filename, sizeof(Asset->Filename)), Wrap0i(AssetInMemory->Filename, sizeof(AssetInMemory->Filename))) && Asset->Type == AssetInMemory->Type) + if(!StringsDiffer(Wrap0i(Asset->Filename), Wrap0i(AssetInMemory->Filename)) && Asset->Type == AssetInMemory->Type) { AssetInMemory->Known = TRUE; landmark_range ProjectRange = DetermineProjectLandmarksRange(Asset, P->Index); @@ -12956,7 +13092,7 @@ rc InsertNeighbourLink(db_header_project *P, db_entry *From, db_entry *To, enum8(link_directions) LinkDirection, bool FromHasOneNeighbour) { rc Result = RC_SUCCESS; - MEM_TEST_TOP("InsertNeighbourLink()"); file HTML = {}; ReadPlayerPageIntoBuffer(&HTML, Wrap0i(P->BaseDir, sizeof(P->BaseDir)), Wrap0i(P->PlayerLocation, sizeof(P->PlayerLocation)), Wrap0i(From->OutputLocation, sizeof(From->OutputLocation))); + MEM_TEST_TOP("InsertNeighbourLink()"); file HTML = {}; ReadPlayerPageIntoBuffer(&HTML, Wrap0i(P->BaseDir), Wrap0i(P->PlayerLocation), Wrap0i(From->OutputLocation)); if(HTML.Buffer.Location) { if(!(HTML.Handle = fopen(HTML.Path, "w"))) { Result = RC_ERROR_FILE; }; @@ -12970,7 +13106,7 @@ InsertNeighbourLink(db_header_project *P, db_entry *From, db_entry *To, enum8(li if(To) { ClaimBuffer(&ToPlayerURL, BID_TO_PLAYER_URL, MAX_BASE_URL_LENGTH + 1 + MAX_RELATIVE_PAGE_LOCATION_LENGTH + 1 + MAX_BASE_FILENAME_LENGTH); - ConstructPlayerURL(&ToPlayerURL, P, Wrap0i(To->OutputLocation, sizeof(To->OutputLocation))); + ConstructPlayerURL(&ToPlayerURL, P, Wrap0i(To->OutputLocation)); } string ProjectTitle = BestTitleForHTML(CurrentProject); @@ -13097,7 +13233,7 @@ DeleteNeighbourLinks(neighbourhood *N) } file HTML = {}; - ReadPlayerPageIntoBuffer(&HTML, Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir)), Wrap0i(N->Project->PlayerLocation, sizeof(N->Project->PlayerLocation)), Wrap0i(Entry->OutputLocation, sizeof(Entry->OutputLocation))); + ReadPlayerPageIntoBuffer(&HTML, Wrap0i(N->Project->BaseDir), Wrap0i(N->Project->PlayerLocation), Wrap0i(Entry->OutputLocation)); if(HTML.Buffer.Location) { if(!(HTML.Handle = fopen(HTML.Path, "w"))) { FreeFile(&HTML); return RC_ERROR_FILE; }; @@ -13173,7 +13309,7 @@ MarkNextAsFirst(neighbourhood *N) { // TODO(matt): We added some untested logic in here. If things related to the prev / next links fail, we screwed up here file HTML = {}; - ReadPlayerPageIntoBuffer(&HTML, Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir)), Wrap0i(N->Project->PlayerLocation, sizeof(N->Project->PlayerLocation)), Wrap0i(N->Next->OutputLocation, sizeof(N->Next->OutputLocation))); + ReadPlayerPageIntoBuffer(&HTML, Wrap0i(N->Project->BaseDir), Wrap0i(N->Project->PlayerLocation), Wrap0i(N->Next->OutputLocation)); if(HTML.Buffer.Location) { buffer Link; @@ -13210,7 +13346,7 @@ void MarkPrevAsFinal(neighbourhood *N) { file HTML = {}; - ReadPlayerPageIntoBuffer(&HTML, Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir)), Wrap0i(N->Project->PlayerLocation, sizeof(N->Project->PlayerLocation)), Wrap0i(N->Prev->OutputLocation, sizeof(N->Prev->OutputLocation))); + ReadPlayerPageIntoBuffer(&HTML, Wrap0i(N->Project->BaseDir), Wrap0i(N->Project->PlayerLocation), Wrap0i(N->Prev->OutputLocation)); if(HTML.Buffer.Location) { @@ -13366,7 +13502,7 @@ LinkNeighbours(neighbourhood *N, enum8(link_types) LinkType) } rc -DeleteFromDB(neighbourhood *N, string BaseFilename) +DeleteFromDB(neighbourhood *N, string BaseFilename, db_entry *Deceased) { ResetNeighbourhood(N); // TODO(matt): LogError() @@ -13380,6 +13516,8 @@ DeleteFromDB(neighbourhood *N, string BaseFilename) if(Entry) { + *Deceased = *Entry; + int DeleteFileFrom = AccumulateDBEntryInsertionOffset(N->Project, EntryIndex); int DeleteFileTo = DeleteFileFrom + Entry->Size; N->This = Entry; @@ -13390,7 +13528,7 @@ DeleteFromDB(neighbourhood *N, string BaseFilename) --NewEntryCount; if(NewEntryCount == 0) { - DeleteSearchPageFromFilesystem(Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir)), Wrap0i(N->Project->SearchLocation, sizeof(N->Project->SearchLocation)), Wrap0i(N->Project->ID, sizeof(N->Project->ID))); + DeleteSearchPageFromFilesystem(Wrap0i(N->Project->BaseDir), Wrap0i(N->Project->SearchLocation), Wrap0i(N->Project->ID)); DeleteLandmarksForSearch(CurrentProject->Index); UpdateNeighbourhoodPointers(N, &DB.Metadata.Signposts); } @@ -13423,6 +13561,11 @@ DeleteFromDB(neighbourhood *N, string BaseFilename) fwrite(DB.File.Buffer.Location, DeleteFileFrom, 1, DB.File.Handle); fwrite(DB.File.Buffer.Location + DeleteFileTo, DB.File.Buffer.Size - DeleteFileTo, 1, DB.File.Handle); CycleFile(&DB.File); + + if(CurrentProject->Numbering.Method == NM_AUTO) + { + RenumberEntries(N, N->Project, N->PreDeletionThisIndex); + } } LogError(LOG_INFORMATIONAL, "Deleted %.*s/%.*s", (int)CurrentProject->Lineage.Length, CurrentProject->Lineage.Base, (int)BaseFilename.Length, BaseFilename.Base); @@ -13514,7 +13657,7 @@ GenerateIndexOfProjectAndChildren(buffer *Index, db_header_project *StoredP, pro OpenNode(Index, &Index->IndentLevel, NODE_A, 0); AppendStringToBuffer(Index, Wrap0(" href=\"")); - ConstructPlayerURL(&PlayerURL, StoredP, Wrap0i(Entry->OutputLocation, sizeof(Entry->OutputLocation))); + ConstructPlayerURL(&PlayerURL, StoredP, Wrap0i(Entry->OutputLocation)); AppendBuffer(Index, &PlayerURL); AppendStringToBuffer(Index, Wrap0("\">")); @@ -13523,7 +13666,7 @@ GenerateIndexOfProjectAndChildren(buffer *Index, db_header_project *StoredP, pro AppendStringToBuffer(Index, P->Numbering.Unit); AppendStringToBuffer(Index, Wrap0(" ")); - numbering_info Number = GetEntryNumbering(P, Wrap0i(Entry->HMMLBaseFilename, sizeof(Entry->HMMLBaseFilename)), Wrap0i(Entry->Number, sizeof(Entry->Number)), i, StoredP->EntryCount); + numbering_info Number = GetEntryNumbering(P, Wrap0i(Entry->HMMLBaseFilename), Wrap0i(Entry->Number), i, StoredP->EntryCount); switch(Number.Value.Type) { case PT_STRING: @@ -13544,7 +13687,7 @@ GenerateIndexOfProjectAndChildren(buffer *Index, db_header_project *StoredP, pro AppendStringToBuffer(Index, Wrap0(": ")); } - AppendStringToBufferHTMLSafe(Index, Wrap0i(Entry->Title, sizeof(Entry->Title))); + AppendStringToBufferHTMLSafe(Index, Wrap0i(Entry->Title)); CloseNode(Index, &Index->IndentLevel, NODE_A); CloseNode(Index, &Index->IndentLevel, NODE_DIV); } @@ -13900,7 +14043,7 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P AppendStringToBuffer(B, Wrap0(" src=\"")); asset *FilterImage = GetAsset(Wrap0(BuiltinAssets[ASSET_IMG_FILTER].Filename), ASSET_IMG); ConstructResolvedAssetURL(&URL, FilterImage, PAGE_SEARCH); - AppendStringToBuffer(B, Wrap0i(URL.Location, URL.Ptr - URL.Location)); + AppendStringToBuffer(B, Wrap0i_(URL.Location, URL.Ptr - URL.Location)); DeclaimBuffer(&URL); PushAssetLandmark(B, FilterImage, PAGE_SEARCH, TRUE); AppendStringToBuffer(B, Wrap0("\">")); @@ -14181,8 +14324,8 @@ int GeneratePlayerPage(neighbourhood *N, buffers *CollationBuffers, template *PlayerTemplate, string OutputLocation, bool Reinserting) { MEM_TEST_TOP("GeneratePlayerPage()"); - string BaseDir = Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir)); - string PlayerLocation = Wrap0i(N->Project->PlayerLocation, sizeof(N->Project->PlayerLocation)); + string BaseDir = Wrap0i(N->Project->BaseDir); + string PlayerLocation = Wrap0i(N->Project->PlayerLocation); char *PlayerPath = ConstructDirectoryPath(&BaseDir, &PlayerLocation, &OutputLocation); DIR *OutputDirectoryHandle; @@ -14208,7 +14351,7 @@ GeneratePlayerPage(neighbourhood *N, buffers *CollationBuffers, template *Player SearchInTemplate = TRUE; // TODO(matt): Fully determine whether UpdateNeighbourhoodPointers() must happen here UpdateNeighbourhoodPointers(N, &DB.Metadata.Signposts); - SearchToBuffer(CollationBuffers, N->Project, CurrentProject, Wrap0i(N->Project->Theme, sizeof(N->Project->Theme)), PlayerTemplate->Metadata.RequiresCineraJS); + SearchToBuffer(CollationBuffers, N->Project, CurrentProject, Wrap0i(N->Project->Theme), PlayerTemplate->Metadata.RequiresCineraJS); break; } } @@ -14233,8 +14376,8 @@ rc GenerateSearchPage(neighbourhood *N, buffers *CollationBuffers, db_header_project *StoredP, project *P) { MEM_TEST_TOP("GenerateSearchPage()"); - string BaseDir = Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir)); - string SearchLocation = Wrap0i(N->Project->SearchLocation, sizeof(N->Project->SearchLocation)); + string BaseDir = Wrap0i(N->Project->BaseDir); + string SearchLocation = Wrap0i(N->Project->SearchLocation); char *SearchPath = ConstructDirectoryPath(&BaseDir, &SearchLocation, 0); DIR *OutputDirectoryHandle; @@ -14252,7 +14395,7 @@ GenerateSearchPage(neighbourhood *N, buffers *CollationBuffers, db_header_projec ExtendString0(&SearchPath, Wrap0("/index.html")); // TODO(matt): We used to do UpdateNeighbourhoodPointers() here. If something goes awry near here, reinstate that call switch(SearchToBuffer(CollationBuffers, StoredP, P, - Wrap0i(StoredP->Theme, sizeof(StoredP->Theme)), P->SearchTemplate.Metadata.RequiresCineraJS)) + Wrap0i(StoredP->Theme), P->SearchTemplate.Metadata.RequiresCineraJS)) { case RC_SUCCESS: { @@ -14280,7 +14423,7 @@ GenerateGlobalSearchPage(neighbourhood *N, buffers *CollationBuffers) { MEM_TEST_TOP("GenerateGlobalSearchPage()"); db_block_projects *ProjectsBlock = DB.Metadata.Signposts.ProjectsBlock.Ptr; - string SearchLocationL = Wrap0i(ProjectsBlock->GlobalSearchDir, sizeof(ProjectsBlock->GlobalSearchDir)); + string SearchLocationL = Wrap0i(ProjectsBlock->GlobalSearchDir); char *SearchPath = MakeString0("l", &SearchLocationL); DIR *OutputDirectoryHandle; @@ -14357,26 +14500,25 @@ GenerateSearchPages(neighbourhood *N, buffers *CollationBuffers) return RC_SUCCESS; } -int +rc DeleteEntry(neighbourhood *N, string BaseFilename) { - // TODO(matt): DeleteFromDB() may reasonably use this BaseFilename to locate the Entry. But, we'll need to return the - // Entry->Output to pass to DeletePlayerPageFromFilesystem() - // db_entry5 + rc Result = RC_NOOP; // TODO(matt): Fix deletion of the final entry in a project - if(DeleteFromDB(N, BaseFilename) == RC_SUCCESS) + db_entry Deceased = {}; + if(DeleteFromDB(N, BaseFilename, &Deceased) == RC_SUCCESS) { LinkNeighbours(N, LINK_EXCLUDE); - string BaseDir = Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir)); - string PlayerLocation = Wrap0i(N->Project->PlayerLocation, sizeof(N->Project->PlayerLocation)); - DeletePlayerPageFromFilesystem(BaseDir, PlayerLocation, BaseFilename, FALSE, TRUE); + string BaseDir = Wrap0i(N->Project->BaseDir); + string PlayerLocation = Wrap0i(N->Project->PlayerLocation); + DeletePlayerPageFromFilesystem(BaseDir, PlayerLocation, Wrap0i(Deceased.OutputLocation), FALSE, TRUE); UpdateLandmarksForNeighbourhood(N, EDIT_DELETION); - return RC_SUCCESS; + Result = RC_SUCCESS; } - return RC_NOOP; + return Result; } rc @@ -14394,14 +14536,14 @@ InsertEntry(neighbourhood *N, buffers *CollationBuffers, template *BespokeTempla if(BespokeTemplate->File.Buffer.Location) { /* */ MEM_TEST_MID("InsertEntry()"); - /* +MEM (inferred) */ GeneratePlayerPage(N, CollationBuffers, BespokeTemplate, Wrap0i(Entry->OutputLocation, sizeof(Entry->OutputLocation)), Reinserting); + /* +MEM (inferred) */ GeneratePlayerPage(N, CollationBuffers, BespokeTemplate, Wrap0i(Entry->OutputLocation), Reinserting); /* */ MEM_TEST_MID("InsertEntry()"); FreeTemplate(BespokeTemplate); } else { /* */ MEM_TEST_MID("InsertEntry()"); - /* +MEM */ GeneratePlayerPage(N, CollationBuffers, &CurrentProject->PlayerTemplate, Wrap0i(Entry->OutputLocation, sizeof(Entry->OutputLocation)), Reinserting); + /* +MEM */ GeneratePlayerPage(N, CollationBuffers, &CurrentProject->PlayerTemplate, Wrap0i(Entry->OutputLocation), Reinserting); /* */ MEM_TEST_MID("InsertEntry()"); } } @@ -14457,7 +14599,7 @@ RecheckPrivacyRecursively(project *P, neighbourhood *N, buffers *CollationBuffer for(int i = 0; i < PrivateEntryIndex; ++i) { - Inserted = (InsertEntry(N, CollationBuffers, BespokeTemplate, Wrap0i(PrivateEntries[i].HMMLBaseFilename, sizeof(PrivateEntries[i].HMMLBaseFilename)), TRUE) == RC_SUCCESS); + Inserted = (InsertEntry(N, CollationBuffers, BespokeTemplate, Wrap0i(PrivateEntries[i].HMMLBaseFilename), TRUE) == RC_SUCCESS); } if(Inserted) @@ -14618,16 +14760,16 @@ DeleteDeadDBEntries(neighbourhood *N, bool *Modified) // TODO(matt): Here is where the relocation happens. This could be wrong - if(StringsDiffer(CurrentProject->BaseDir, Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir))) || - StringsDiffer(CurrentProject->PlayerLocation, Wrap0i(N->Project->PlayerLocation, sizeof(N->Project->PlayerLocation)))) + if(StringsDiffer(CurrentProject->BaseDir, Wrap0i(N->Project->BaseDir)) || + StringsDiffer(CurrentProject->PlayerLocation, Wrap0i(N->Project->PlayerLocation))) { - string OldBaseDir = Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir)); - string OldPlayerLocation = Wrap0i(N->Project->PlayerLocation, sizeof(N->Project->PlayerLocation)); + string OldBaseDir = Wrap0i(N->Project->BaseDir); + string OldPlayerLocation = Wrap0i(N->Project->PlayerLocation); char *OldPlayerDirectory = ConstructDirectoryPath(&OldBaseDir, &OldPlayerLocation, 0); db_header_project NewProjectHeader = *N->Project; ClearCopyStringNoFormat(NewProjectHeader.BaseDir, sizeof(NewProjectHeader.BaseDir), CurrentProject->BaseDir); - string NewBaseDir = Wrap0i(NewProjectHeader.BaseDir, sizeof(NewProjectHeader.BaseDir)); + string NewBaseDir = Wrap0i(NewProjectHeader.BaseDir); char *NewPlayerDirectory = ConstructDirectoryPath(&NewBaseDir, &CurrentProject->PlayerLocation, 0); printf("%sRelocating Player Page%s from %s to %s%s\n", @@ -14639,14 +14781,14 @@ DeleteDeadDBEntries(neighbourhood *N, bool *Modified) for(int EntryIndex = 0; EntryIndex < N->Project->EntryCount; ++EntryIndex) { db_entry *This = FirstEntry + EntryIndex; - string BaseDir = Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir)); - string PlayerLocation = Wrap0i(N->Project->PlayerLocation, sizeof(N->Project->PlayerLocation)); - DeletePlayerPageFromFilesystem(BaseDir, PlayerLocation, Wrap0i(This->OutputLocation, sizeof(This->OutputLocation)), TRUE, TRUE); + string BaseDir = Wrap0i(N->Project->BaseDir); + string PlayerLocation = Wrap0i(N->Project->PlayerLocation); + DeletePlayerPageFromFilesystem(BaseDir, PlayerLocation, Wrap0i(This->OutputLocation), TRUE, TRUE); } if(OldPlayerLocation.Length > 0) { - RemoveChildDirectories(Wrap0(OldPlayerDirectory), Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir))); + RemoveChildDirectories(Wrap0(OldPlayerDirectory), Wrap0i(N->Project->BaseDir)); } Free(OldPlayerDirectory); @@ -14654,18 +14796,18 @@ DeleteDeadDBEntries(neighbourhood *N, bool *Modified) HasNewPlayerLocation = TRUE; } - if(StringsDiffer(CurrentProject->BaseDir, Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir))) || - StringsDiffer(CurrentProject->SearchLocation, Wrap0i(N->Project->SearchLocation, sizeof(N->Project->SearchLocation)))) + if(StringsDiffer(CurrentProject->BaseDir, Wrap0i(N->Project->BaseDir)) || + StringsDiffer(CurrentProject->SearchLocation, Wrap0i(N->Project->SearchLocation))) { - string OldBaseDir = Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir)); - string OldSearchLocation = Wrap0i(N->Project->SearchLocation, sizeof(N->Project->SearchLocation)); + string OldBaseDir = Wrap0i(N->Project->BaseDir); + string OldSearchLocation = Wrap0i(N->Project->SearchLocation); char *OldSearchDirectory = ConstructDirectoryPath(&OldBaseDir, &OldSearchLocation, 0); db_header_project NewProjectHeader = *N->Project; ClearCopyStringNoFormat(NewProjectHeader.BaseDir, sizeof(NewProjectHeader.BaseDir), CurrentProject->BaseDir); ClearCopyStringNoFormat(NewProjectHeader.SearchLocation, sizeof(NewProjectHeader.SearchLocation), CurrentProject->SearchLocation); - string NewBaseDir = Wrap0i(NewProjectHeader.BaseDir, sizeof(NewProjectHeader.BaseDir)); - string NewSearchLocation = Wrap0i(NewProjectHeader.SearchLocation, sizeof(NewProjectHeader.SearchLocation)); + string NewBaseDir = Wrap0i(NewProjectHeader.BaseDir); + string NewSearchLocation = Wrap0i(NewProjectHeader.SearchLocation); char *NewSearchDirectory = ConstructDirectoryPath(&NewBaseDir, &NewSearchLocation, 0); MakeDir(Wrap0(NewSearchDirectory)); @@ -14679,8 +14821,8 @@ DeleteDeadDBEntries(neighbourhood *N, bool *Modified) Free(OldSearchPagePath); Free(NewSearchPagePath); - char *OldSearchIndexPath = ConstructIndexFilePath(OldBaseDir, OldSearchLocation, Wrap0i(N->Project->ID, sizeof(N->Project->ID))); - char *NewSearchIndexPath = ConstructIndexFilePath(NewBaseDir, NewSearchLocation, Wrap0i(N->Project->ID, sizeof(N->Project->ID))); + char *OldSearchIndexPath = ConstructIndexFilePath(OldBaseDir, OldSearchLocation, Wrap0i(N->Project->ID)); + char *NewSearchIndexPath = ConstructIndexFilePath(NewBaseDir, NewSearchLocation, Wrap0i(N->Project->ID)); rename(OldSearchIndexPath, NewSearchIndexPath); Free(OldSearchIndexPath); Free(NewSearchIndexPath); @@ -14693,7 +14835,7 @@ DeleteDeadDBEntries(neighbourhood *N, bool *Modified) if(OldSearchLocation.Length > 0) { - RemoveChildDirectories(Wrap0(OldSearchDirectory), Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir))); + RemoveChildDirectories(Wrap0(OldSearchDirectory), Wrap0i(N->Project->BaseDir)); } remove(OldSearchDirectory); @@ -14702,7 +14844,7 @@ DeleteDeadDBEntries(neighbourhood *N, bool *Modified) HasNewSearchLocation = TRUE; } - if(StringsDiffer(CurrentProject->BaseDir, Wrap0i(N->Project->BaseDir, sizeof(N->Project->BaseDir)))) + if(StringsDiffer(CurrentProject->BaseDir, Wrap0i(N->Project->BaseDir))) { ClearCopyStringNoFormat(N->Project->BaseDir, sizeof(N->Project->BaseDir), CurrentProject->BaseDir); DB.Metadata.File.Handle = fopen(DB.Metadata.File.Path, "w"); @@ -14712,7 +14854,7 @@ DeleteDeadDBEntries(neighbourhood *N, bool *Modified) *Modified = TRUE; } - if(StringsDiffer(CurrentProject->BaseURL, Wrap0i(N->Project->BaseURL, sizeof(N->Project->BaseURL)))) + if(StringsDiffer(CurrentProject->BaseURL, Wrap0i(N->Project->BaseURL))) { ClearCopyStringNoFormat(N->Project->BaseURL, sizeof(N->Project->BaseURL), CurrentProject->BaseURL); DB.Metadata.File.Handle = fopen(DB.Metadata.File.Path, "w"); @@ -14738,7 +14880,7 @@ DeleteDeadDBEntries(neighbourhood *N, bool *Modified) for(int EntryIndex = 0; EntryIndex < N->Project->EntryCount; ++EntryIndex) { db_entry *This = FirstEntry + EntryIndex; - CopyStringNoFormat(Entries[EntryIndex].ID, sizeof(Entries[EntryIndex].ID), Wrap0i(This->HMMLBaseFilename, sizeof(This->HMMLBaseFilename))); + CopyStringNoFormat(Entries[EntryIndex].ID, sizeof(Entries[EntryIndex].ID), Wrap0i(This->HMMLBaseFilename)); Entries[EntryIndex].Present = FALSE; } @@ -14797,7 +14939,7 @@ SyncDBWithInput(neighbourhood *N, buffers *CollationBuffers, template *BespokeTe } bool Modified = FALSE; - if(StringsDiffer(CurrentProject->Title, Wrap0i(N->Project->Title, sizeof(N->Project->Title)))) + if(StringsDiffer(CurrentProject->Title, Wrap0i(N->Project->Title))) { ClearCopyStringNoFormat(N->Project->Title, sizeof(N->Project->Title), CurrentProject->Title); DB.Metadata.File.Handle = fopen(DB.Metadata.File.Path, "w"); @@ -14807,7 +14949,7 @@ SyncDBWithInput(neighbourhood *N, buffers *CollationBuffers, template *BespokeTe Modified = TRUE; } - if(StringsDiffer(CurrentProject->Theme, Wrap0i(N->Project->Theme, sizeof(N->Project->Theme)))) + if(StringsDiffer(CurrentProject->Theme, Wrap0i(N->Project->Theme))) { ClearCopyStringNoFormat(N->Project->Theme, sizeof(N->Project->Theme), CurrentProject->Theme); DB.Metadata.File.Handle = fopen(DB.Metadata.File.Path, "w"); @@ -14817,7 +14959,7 @@ SyncDBWithInput(neighbourhood *N, buffers *CollationBuffers, template *BespokeTe Modified = TRUE; } - if(StringsDiffer(CurrentProject->Numbering.Unit, Wrap0i(N->Project->Unit, sizeof(N->Project->Unit)))) + if(StringsDiffer(CurrentProject->Numbering.Unit, Wrap0i(N->Project->Unit))) { ClearCopyStringNoFormat(N->Project->Unit, sizeof(N->Project->Unit), CurrentProject->Numbering.Unit); DB.Metadata.File.Handle = fopen(DB.Metadata.File.Path, "w"); @@ -15311,7 +15453,7 @@ InsertProjectIntoDB(project_generations *G, db_header_project **Parent, db_heade bool ConfiguredAndStoredProjectIDsMatch(project *ConfiguredP, db_header_project *StoredP) { - return StringsMatch(ConfiguredP->ID, Wrap0i(StoredP->ID, sizeof(StoredP->ID))); + return StringsMatch(ConfiguredP->ID, Wrap0i(StoredP->ID)); } void @@ -15420,16 +15562,16 @@ DeleteHTMLFilesOfProject(db_header_project *Project) char *Ptr = (char *)Project; Ptr += sizeof(db_header_project) + sizeof(db_entry) * Project->EntryCount; - string BaseDir = Wrap0i(Project->BaseDir, sizeof(Project->BaseDir)); - string PlayerLocation = Wrap0i(Project->PlayerLocation, sizeof(Project->PlayerLocation)); + string BaseDir = Wrap0i(Project->BaseDir); + string PlayerLocation = Wrap0i(Project->PlayerLocation); db_entry *Entry = LocateFirstEntry(Project); for(int i = 0; i < Project->EntryCount; ++i, ++Entry) { - DeletePlayerPageFromFilesystem(BaseDir, PlayerLocation, Wrap0i(Entry->OutputLocation, sizeof(Entry->OutputLocation)), FALSE, FALSE); + DeletePlayerPageFromFilesystem(BaseDir, PlayerLocation, Wrap0i(Entry->OutputLocation), FALSE, FALSE); } - DeleteSearchPageFromFilesystem(BaseDir, PlayerLocation, Wrap0i(Project->ID, sizeof(Project->ID))); + DeleteSearchPageFromFilesystem(BaseDir, PlayerLocation, Wrap0i(Project->ID)); return Ptr; } @@ -15442,9 +15584,9 @@ DeleteHTMLFilesOfProjectAndChildren(db_header_project *Project) { Ptr = DeleteHTMLFilesOfProjectAndChildren(Ptr); } - string BaseDir = Wrap0i(Project->BaseDir, sizeof(Project->BaseDir)); - string SearchLocation = Wrap0i(Project->SearchLocation, sizeof(Project->SearchLocation)); - DeleteSearchPageFromFilesystem(BaseDir, SearchLocation, Wrap0i(Project->ID, sizeof(Project->ID))); + string BaseDir = Wrap0i(Project->BaseDir); + string SearchLocation = Wrap0i(Project->SearchLocation); + DeleteSearchPageFromFilesystem(BaseDir, SearchLocation, Wrap0i(Project->ID)); return Ptr; } @@ -15754,9 +15896,9 @@ SyncProjects_TopLevel(project_generations *G, project *C, db_block_projects **SP if((*SChild)->ChildCount == 0 && (*SChild)->EntryCount == 0) { - string BaseDir = Wrap0i((*SChild)->BaseDir, sizeof((*SChild)->BaseDir)); - string SearchLocation = Wrap0i((*SChild)->SearchLocation, sizeof((*SChild)->SearchLocation)); - string ProjectID = Wrap0i((*SChild)->ID, sizeof((*SChild)->ID)); + string BaseDir = Wrap0i((*SChild)->BaseDir); + string SearchLocation = Wrap0i((*SChild)->SearchLocation); + string ProjectID = Wrap0i((*SChild)->ID); DeleteSearchPageFromFilesystem(BaseDir, SearchLocation, ProjectID); DeleteLandmarksForSearch(C->Index); DeleteStaleAssets(); @@ -15811,9 +15953,9 @@ SyncProjects(project_generations *G, project *C, db_header_project **SParent, db if((*SChild)->ChildCount == 0 && (*SChild)->EntryCount == 0) { - string BaseDir = Wrap0i((*SChild)->BaseDir, sizeof((*SChild)->BaseDir)); - string SearchLocation = Wrap0i((*SChild)->SearchLocation, sizeof((*SChild)->SearchLocation)); - string ProjectID = Wrap0i((*SChild)->ID, sizeof((*SChild)->ID)); + string BaseDir = Wrap0i((*SChild)->BaseDir); + string SearchLocation = Wrap0i((*SChild)->SearchLocation); + string ProjectID = Wrap0i((*SChild)->ID); DeleteSearchPageFromFilesystem(BaseDir, SearchLocation, ProjectID); DeleteLandmarksForSearch(C->Index); @@ -15888,8 +16030,8 @@ SyncGlobalPagesWithInput(neighbourhood *N, buffers *CollationBuffers) { MEM_TEST_TOP("SyncGlobalPagesWithInput"); db_block_projects *ProjectsBlock = DB.Metadata.Signposts.ProjectsBlock.Ptr; - string StoredGlobalSearchDir = Wrap0i(ProjectsBlock->GlobalSearchDir, sizeof(ProjectsBlock->GlobalSearchDir)); - string StoredGlobalSearchURL = Wrap0i(ProjectsBlock->GlobalSearchURL, sizeof(ProjectsBlock->GlobalSearchURL)); + string StoredGlobalSearchDir = Wrap0i(ProjectsBlock->GlobalSearchDir); + string StoredGlobalSearchURL = Wrap0i(ProjectsBlock->GlobalSearchURL); char *StoredGlobalSearchDir0 = MakeString0("l", &StoredGlobalSearchDir); if(StringsDiffer(StoredGlobalSearchDir, Config->GlobalSearchDir)) {