diff --git a/cinera/cinera.c b/cinera/cinera.c index 475c16f..1dfe024 100644 --- a/cinera/cinera.c +++ b/cinera/cinera.c @@ -23,7 +23,7 @@ typedef struct version CINERA_APP_VERSION = { .Major = 0, .Minor = 10, - .Patch = 30 + .Patch = 31 }; #define __USE_XOPEN2K8 // NOTE(matt): O_NOFOLLOW @@ -8350,16 +8350,70 @@ BuildTimestampClass(buffer *TimestampClass, _memory_book(category_info) *LocalTo CopyStringToBuffer(TimestampClass, "\""); } -void -BuildCategoryIcons(buffer *CategoryIcons, _memory_book(category_info) *LocalTopics, _memory_book(category_info) *LocalMedia, string DefaultMedium, bool *RequiresCineraJS) +bool +IsWhitespace(char C) { - bool CategoriesSpan = FALSE; + return (C == ' ' || C == '\t' || C == '\n'); +} + +bool +ContainsWhitespace(string S) +{ + bool Result = FALSE; + for(int i = 0; i < S.Length; ++i) + { + if(IsWhitespace(S.Base[i])) + { + Result = TRUE; + break; + } + } + return Result; +} + +void +ConsumeWhitespace(buffer *B) +{ + while(B->Ptr - B->Location < B->Size && IsWhitespace(*B->Ptr)) + { + ++B->Ptr; + } +} + +void +PushCategorySearchEntry(buffer *SearchEntry, HMML_Timestamp *Timestamp, category_info *Category, bool Underway) +{ + if(Underway || Timestamp->text[0]) + { + CopyStringToBuffer(SearchEntry, " "); + } + if(!Underway) + { + CopyStringToBuffer(SearchEntry, "["); + } + + CopyStringToBuffer(SearchEntry, ":"); + bool NeedsQuoting = ContainsWhitespace(Category->Marker); + if(NeedsQuoting) + { + CopyStringToBuffer(SearchEntry, "\""); + } + CopyStringToBufferNoFormat(SearchEntry, Category->Marker); + if(NeedsQuoting) + { + CopyStringToBuffer(SearchEntry, "\""); + } +} + +void +BuildCategoryIcons(buffer *SearchEntry, buffer *CategoryIcons, _memory_book(category_info) *LocalTopics, _memory_book(category_info) *LocalMedia, string DefaultMedium, bool *RequiresCineraJS, HMML_Timestamp *Timestamp) +{ + bool Underway = FALSE; category_info *FirstLocalTopic = GetPlaceInBook(LocalTopics, 0); category_info *FirstLocalMedium = GetPlaceInBook(LocalMedia, 0); if(!(LocalTopics->ItemCount == 1 && StringsMatch(FirstLocalTopic->Marker, Wrap0("nullTopic")) - && LocalMedia->ItemCount == 1 && StringsMatch(DefaultMedium, FirstLocalMedium->Marker))) + && LocalMedia->ItemCount == 1 && StringsMatch(FirstLocalMedium->Marker, DefaultMedium))) { - CategoriesSpan = TRUE; CopyStringToBuffer(CategoryIcons, ""); } @@ -8368,6 +8422,14 @@ BuildCategoryIcons(buffer *CategoryIcons, _memory_book(category_info) *LocalTopi for(int i = 0; i < LocalTopics->ItemCount; ++i) { category_info *This = GetPlaceInBook(LocalTopics, i); + + // .index + if(SearchEntry) + { + PushCategorySearchEntry(SearchEntry, Timestamp, This, Underway); + } + + // .html // NOTE(matt): Stack-string char SanitisedMarker[This->Marker.Length + 1]; CopyString(SanitisedMarker, sizeof(SanitisedMarker), "%.*s", (int)This->Marker.Length, This->Marker.Base); @@ -8385,14 +8447,24 @@ BuildCategoryIcons(buffer *CategoryIcons, _memory_book(category_info) *LocalTopi } CopyStringToBuffer(CategoryIcons, ">"); + + Underway = TRUE; } } - if(!(LocalMedia->ItemCount == 1 && StringsMatch(DefaultMedium, FirstLocalMedium->Marker))) + if(!(LocalMedia->ItemCount == 1 && StringsMatch(FirstLocalMedium->Marker, DefaultMedium))) { for(int i = 0; i < LocalMedia->ItemCount; ++i) { category_info *This = GetPlaceInBook(LocalMedia, i); + + // .index + if(SearchEntry) + { + PushCategorySearchEntry(SearchEntry, Timestamp, This, Underway); + } + + // .html // NOTE(matt): Stack-string char SanitisedMarker[This->Marker.Length + 1]; CopyString(SanitisedMarker, sizeof(SanitisedMarker), "%.*s", (int)This->Marker.Length, This->Marker.Base); @@ -8409,11 +8481,20 @@ BuildCategoryIcons(buffer *CategoryIcons, _memory_book(category_info) *LocalTopi CopyStringToBuffer(CategoryIcons, ""); } + + Underway = TRUE; } } - if(CategoriesSpan) + if(Underway) { + // .index + if(SearchEntry) + { + CopyStringToBuffer(SearchEntry, "]"); + } + + // .html CopyStringToBuffer(CategoryIcons, ""); } } @@ -9220,21 +9301,6 @@ StripSurroundingSlashes(char *String) // NOTE(matt): For relative paths return Ptr; } -bool -IsWhitespace(char C) -{ - return (C == ' ' || C == '\t' || C == '\n'); -} - -void -ConsumeWhitespace(buffer *B) -{ - while(B->Ptr - B->Location < B->Size && IsWhitespace(*B->Ptr)) - { - ++B->Ptr; - } -} - string StripPWDIndicators(string Path) { @@ -10862,6 +10928,483 @@ TimecodeIs(v4 Timecode, int Hours, int Minutes, int Seconds, int Milliseconds) return Timecode.Hours == Hours && Timecode.Minutes == Minutes && Timecode.Seconds == Seconds && Timecode.Milliseconds == Milliseconds; } +void +ProcessTimestampCoda(buffer *SearchEntry, index_buffers *IndexBuffers) +{ + // .index + CopyStringToBuffer(SearchEntry, "\"\n"); + + // .html + CopyStringToBuffer(&IndexBuffers->Master, "\n" + " \n" + " \n"); +} + +rc +ProcessTimestampCategories(neighbourhood *N, + buffer *SearchEntry, index_buffers *IndexBuffers, + medium *DefaultMedium, + bool *HasFilterMenu, + bool *RequiresCineraJS, + _memory_book(category_info) *Topics, _memory_book(category_info) *LocalTopics, + _memory_book(category_info) *Media, _memory_book(category_info) *LocalMedia, + HMML_Timestamp *Timestamp, v4 Timecode, + int *MarkerIndex, bool HasQuote, bool HasReference) +{ + rc Result = RC_SUCCESS; + + while(*MarkerIndex < Timestamp->marker_count) + { + hsl_colour TopicColour = {}; + Result = GenerateTopicColours(N, Wrap0(Timestamp->markers[*MarkerIndex].marker), &TopicColour); + if(Result == RC_SUCCESS) + { + if(!*HasFilterMenu) + { + *HasFilterMenu = TRUE; + } + InsertCategory(Topics, LocalTopics, Media, LocalMedia, Wrap0(Timestamp->markers[*MarkerIndex].marker), &TopicColour); + ++*MarkerIndex; + } + else + { + break; + } + } + + if(Result == RC_SUCCESS) + { + if(LocalTopics->ItemCount == 0) + { + hsl_colour TopicColour = {}; + Result = GenerateTopicColours(N, Wrap0("nullTopic"), &TopicColour); + if(Result == RC_SUCCESS) + { + InsertCategory(Topics, LocalTopics, Media, LocalMedia, Wrap0("nullTopic"), &TopicColour); + } + } + + if(Result == RC_SUCCESS) + { + if(LocalMedia->ItemCount == 0) + { + InsertCategory(Topics, LocalTopics, Media, LocalMedia, DefaultMedium->ID, NULL); + } + + BuildTimestampClass(&IndexBuffers->Class, LocalTopics, LocalMedia, DefaultMedium->ID); + CopyLandmarkedBuffer(&IndexBuffers->Header, &IndexBuffers->Class, 0, PAGE_PLAYER); + + if(HasQuote || HasReference) + { + CopyStringToBuffer(&IndexBuffers->Data, "\""); + CopyLandmarkedBuffer(&IndexBuffers->Header, &IndexBuffers->Data, 0, PAGE_PLAYER); + } + CopyStringToBuffer(&IndexBuffers->Header, ">\n"); + + CopyLandmarkedBuffer(&IndexBuffers->Master, &IndexBuffers->Header, 0, PAGE_PLAYER); + CopyStringToBuffer(&IndexBuffers->Master, + "