Make project navigation menus use the right theme

It was just a typo. HMMLToBuffers() passed the global config pointer,
rather than the passed in one, to GenerateNavigation().

Also switch the entire config over to use memory_book style allocation.
This saves us from having to offset pointers when memory gets realloc'd.
This commit is contained in:
Matt Mascarenhas 2020-05-25 00:26:13 +01:00
parent 8aa67a386a
commit bc6f21f71d
2 changed files with 727 additions and 734 deletions

View File

@ -23,7 +23,7 @@ typedef struct
version CINERA_APP_VERSION = { version CINERA_APP_VERSION = {
.Major = 0, .Major = 0,
.Minor = 7, .Minor = 7,
.Patch = 11 .Patch = 12
}; };
#include <stdarg.h> // NOTE(matt): varargs #include <stdarg.h> // NOTE(matt): varargs
@ -462,15 +462,28 @@ typedef enum
MBT_NONE, MBT_NONE,
MBT_ASSET, MBT_ASSET,
MBT_CONFIG_IDENTIFIER_ID,
MBT_CONFIG_BOOL_PAIR,
MBT_CONFIG_INT_PAIR,
MBT_CONFIG_PAIR,
MBT_CONFIG_STRING_ASSOCIATION,
MBT_CONFIG_TYPE_FIELD,
MBT_CONFIG_TYPE_SPEC,
MBT_MEDIUM, MBT_MEDIUM,
MBT_NAVIGATION_BUFFER, MBT_NAVIGATION_BUFFER,
MBT_PERSON, MBT_PERSON,
MBT_PERSON_PTR,
MBT_PROJECT, MBT_PROJECT,
MBT_PROJECT_PTR,
MBT_RESOLUTION_ERROR,
MBT_STRING, MBT_STRING,
MBT_STRING_PTR,
MBT_SUPPORT, MBT_SUPPORT,
MBT_TAG_OFFSET, MBT_TAG_OFFSET,
MBT_TOKEN, MBT_TOKEN,
MBT_TOKENS, MBT_TOKENS,
MBT_VARIANT,
MBT_VARIANT_STRING,
} memory_book_type; } memory_book_type;
typedef struct typedef struct
@ -493,6 +506,12 @@ InitBook(memory_book *M, uint64_t DataWidthInBytes, uint64_t ItemsPerPage, memor
M->DataWidthInBytes = DataWidthInBytes; M->DataWidthInBytes = DataWidthInBytes;
} }
void
InitBookOfPointers(memory_book *M, uint64_t ItemsPerPage, memory_book_type Type)
{
InitBook(M, sizeof(uintptr_t), ItemsPerPage, Type);
}
memory_page * memory_page *
AddPage(memory_book *M) AddPage(memory_book *M)
{ {
@ -538,9 +557,13 @@ void
FreeAndReinitialiseBook(memory_book *M) FreeAndReinitialiseBook(memory_book *M)
{ {
int PageSize = M->PageSize; int PageSize = M->PageSize;
int DataWidthInBytes = M->DataWidthInBytes;
int Type = M->Type; int Type = M->Type;
FreeBook(M); FreeBook(M);
M->PageSize = PageSize; M->PageSize = PageSize;
M->DataWidthInBytes = DataWidthInBytes;
M->Type = Type; M->Type = Type;
} }
@ -634,6 +657,12 @@ GetPlaceInBook(memory_book *M, int Index)
return Result; return Result;
} }
void *
MakeSpaceInBook(memory_book *M)
{
return GetPlaceInBook(M, M->ItemCount++);
}
string string
ExtendStringInBook(memory_book *M, string S) ExtendStringInBook(memory_book *M, string S)
{ {
@ -723,14 +752,27 @@ PrintBook(memory_book *M)
} break; } break;
case MBT_NONE: Assert(0); break; case MBT_NONE: Assert(0); break;
case MBT_ASSET: Assert(0); break; case MBT_ASSET: Assert(0); break;
case MBT_CONFIG_IDENTIFIER_ID: Assert(0); break;
case MBT_CONFIG_BOOL_PAIR: Assert(0); break;
case MBT_CONFIG_INT_PAIR: Assert(0); break;
case MBT_CONFIG_PAIR: Assert(0); break;
case MBT_CONFIG_STRING_ASSOCIATION: Assert(0); break;
case MBT_CONFIG_TYPE_FIELD: Assert(0); break;
case MBT_CONFIG_TYPE_SPEC: Assert(0); break;
case MBT_MEDIUM: Assert(0); break; case MBT_MEDIUM: Assert(0); break;
case MBT_NAVIGATION_BUFFER: Assert(0); break; case MBT_NAVIGATION_BUFFER: Assert(0); break;
case MBT_PERSON: Assert(0); break; case MBT_PERSON: Assert(0); break;
case MBT_PERSON_PTR: Assert(0); break;
case MBT_PROJECT: Assert(0); break; case MBT_PROJECT: Assert(0); break;
case MBT_PROJECT_PTR: Assert(0); break;
case MBT_RESOLUTION_ERROR: Assert(0); break;
case MBT_STRING_PTR: Assert(0); break;
case MBT_SUPPORT: Assert(0); break; case MBT_SUPPORT: Assert(0); break;
case MBT_TAG_OFFSET: Assert(0); break; case MBT_TAG_OFFSET: Assert(0); break;
case MBT_TOKEN: Assert(0); break; case MBT_TOKEN: Assert(0); break;
case MBT_TOKENS: Assert(0); break; case MBT_TOKENS: Assert(0); break;
case MBT_VARIANT: Assert(0); break;
case MBT_VARIANT_STRING: Assert(0); break;
} }
} }
@ -2639,11 +2681,13 @@ FreeTemplateNavBuffers(template *T)
void void
ClearTemplateMetadata(template *Template) ClearTemplateMetadata(template *Template)
{ {
Template->Metadata.Validity = 0;
Template->Metadata.Type = TEMPLATE_NULL;
Template->Metadata.RequiresCineraJS = FALSE;
FreeTemplateNavBuffers(Template); FreeTemplateNavBuffers(Template);
FreeBook(&Template->Metadata.NavBuffer); FreeBook(&Template->Metadata.NavBuffer);
FreeBook(&Template->Metadata.Tags);
template_metadata Zero = {};
Template->Metadata = Zero;
} }
void void
@ -2666,7 +2710,6 @@ void
FreeTemplate(template *Template) FreeTemplate(template *Template)
{ {
FreeFile(&Template->File); FreeFile(&Template->File);
FreeBook(&Template->Metadata.Tags);
ClearTemplateMetadata(Template); ClearTemplateMetadata(Template);
} }
@ -3710,12 +3753,11 @@ GetDirectoryPath(char *Filepath)
void void
PushTemplateTag(template *Template, int Offset, template_tag_code TagCode, asset *Asset, navigation_buffer *NavBuffer) PushTemplateTag(template *Template, int Offset, template_tag_code TagCode, asset *Asset, navigation_buffer *NavBuffer)
{ {
tag_offset *This = GetPlaceInBook(&Template->Metadata.Tags, Template->Metadata.Tags.ItemCount); tag_offset *This = MakeSpaceInBook(&Template->Metadata.Tags);
This->Offset = Offset; This->Offset = Offset;
This->TagCode = TagCode; This->TagCode = TagCode;
This->Asset = Asset; This->Asset = Asset;
This->Nav = NavBuffer; This->Nav = NavBuffer;
++Template->Metadata.Tags.ItemCount;
} }
void void
@ -6202,10 +6244,8 @@ FreeCredentials(speakers *S)
void void
WaitForInput() WaitForInput()
{ {
#if 0
fprintf(stderr, "Press Enter to continue...\n"); fprintf(stderr, "Press Enter to continue...\n");
getchar(); getchar();
#endif
} }
void void
@ -6990,17 +7030,6 @@ GenerateTopicColours(neighbourhood *N, string Topic)
} }
} }
/*
* NOTE(matt);
*
* Documentation structure:
*
* section
*
* option <argument>
* description
*/
void void
ResetConfigIdentifierDescriptionDisplayedBools(void) ResetConfigIdentifierDescriptionDisplayedBools(void)
{ {
@ -7065,7 +7094,7 @@ set base_dir at the root scope (i.e. not within a project scope) then the base_d
scope, then the owner will also be set in all child project scopes. Naturally we may need this setting to vary, while also wanting the concision of writing it once. The \ scope, then the owner will also be set in all child project scopes. Naturally we may need this setting to vary, while also wanting the concision of writing it once. The \
base_dir is a prime example of this. To facilitate this variance, we may use variables, notably the $lineage variable, as described below. A variable written in a setting at the root \ base_dir is a prime example of this. To facilitate this variance, we may use variables, notably the $lineage variable, as described below. A variable written in a setting at the root \
scope, which is absorbed by a project, only gets resolved as if it had been written in the project scope.")); scope, which is absorbed by a project, only gets resolved as if it had been written in the project scope."));
config_type_specs TypeSpecs = InitTypeSpecs(); memory_book TypeSpecs = InitTypeSpecs();
PrintTypeSpecs(&TypeSpecs, IndentationLevel); PrintTypeSpecs(&TypeSpecs, IndentationLevel);
//FreeTypeSpecs(&TypeSpecs); //FreeTypeSpecs(&TypeSpecs);
EndSection(&IndentationLevel); EndSection(&IndentationLevel);
@ -7638,10 +7667,9 @@ PushNavBufferUniquely(template *Template, navigation_spec Spec)
navigation_buffer *Result = GetNavBufferFromTemplate(Template, Spec); navigation_buffer *Result = GetNavBufferFromTemplate(Template, Spec);
if(!Result) if(!Result)
{ {
Result = GetPlaceInBook(&Template->Metadata.NavBuffer, Template->Metadata.NavBuffer.ItemCount); Result = MakeSpaceInBook(&Template->Metadata.NavBuffer);
Result->Spec = Spec; Result->Spec = Spec;
Result->Buffer.ID = BID_NAVIGATION; Result->Buffer.ID = BID_NAVIGATION;
++Template->Metadata.NavBuffer.ItemCount;
} }
return Result; return Result;
} }
@ -7980,14 +8008,8 @@ ConstructPlayerURL(buffer *PlayerURL, db_header_project *P, string EntryOutput)
medium * medium *
MediumExists(string Medium) MediumExists(string Medium)
{ {
medium *ParsedMedium = GetMediumFromProject(CurrentProject, Medium); medium *Result = GetMediumFromProject(CurrentProject, Medium);
if(ParsedMedium) if(!Result)
{
return ParsedMedium;
}
fprintf(stderr, "Specified default medium \"%.*s\" not available. Valid media are:\n", (int)Medium.Length, Medium.Base);
for(int i = 0; i < CurrentProject->Medium.ItemCount; ++i)
{ {
typography Typography = typography Typography =
{ {
@ -8002,6 +8024,10 @@ MediumExists(string Medium)
.Delimiter = ": ", .Delimiter = ": ",
.Separator = "", .Separator = "",
}; };
fprintf(stderr, "Specified default medium \"%.*s\" not available. Valid media are:\n", (int)Medium.Length, Medium.Base);
for(int i = 0; i < CurrentProject->Medium.ItemCount; ++i)
{
medium *This = GetPlaceInBook(&CurrentProject->Medium, i); medium *This = GetPlaceInBook(&CurrentProject->Medium, i);
PrintMedium(&Typography, This, ": ", 2, TRUE); PrintMedium(&Typography, This, ": ", 2, TRUE);
} }
@ -8011,7 +8037,8 @@ MediumExists(string Medium)
" name = \"Name of Medium\";\n" " name = \"Name of Medium\";\n"
" icon = \"&#129514;\";\n" " icon = \"&#129514;\";\n"
" }\n", (int)Medium.Length, Medium.Base); " }\n", (int)Medium.Length, Medium.Base);
return 0; }
return Result;
} }
typedef struct typedef struct
@ -10452,12 +10479,10 @@ BuffersToHTML(config *C, project *Project, buffers *CollationBuffers, template *
Template->File.Buffer.Ptr = Template->File.Buffer.Location; Template->File.Buffer.Ptr = Template->File.Buffer.Location;
for(int i = 0; i < Template->Metadata.Tags.ItemCount; ++i) for(int i = 0; i < Template->Metadata.Tags.ItemCount; ++i)
{ {
int j = 0;
tag_offset *Tag = GetPlaceInBook(&Template->Metadata.Tags, i); tag_offset *Tag = GetPlaceInBook(&Template->Metadata.Tags, i);
while(Tag->Offset > j) for(int j = 0; Tag->Offset > j; ++j)
{ {
*Master.Ptr++ = *Template->File.Buffer.Ptr++; *Master.Ptr++ = *Template->File.Buffer.Ptr++;
++j;
} }
// TODO(matt): Make this whole template stuff context-aware, so it can determine whether or not to HTML-encode // TODO(matt): Make this whole template stuff context-aware, so it can determine whether or not to HTML-encode
@ -10546,7 +10571,7 @@ BuffersToHTML(config *C, project *Project, buffers *CollationBuffers, template *
{ {
if(!Tag->Nav->Buffer.Location) if(!Tag->Nav->Buffer.Location)
{ {
GenerateNavigation(Config, Project, Tag->Nav); GenerateNavigation(C, Project, Tag->Nav);
} }
// TODO(matt): If we add project icons to the nav - and, frankly, we will want project art at some // TODO(matt): If we add project icons to the nav - and, frankly, we will want project art at some
@ -12565,85 +12590,75 @@ AtLeastNProjectsHavePublicEntries(uint8_t N)
return FALSE; return FALSE;
} }
// TODO(matt): Replace with a memory_book
typedef struct
{
string *S;
uint64_t Count;
} strings;
void void
PushUniqueStringsRecursively(strings *UniqueThemes, db_header_project *P) PushUniqueStringsRecursively(memory_book *UniqueThemes, project *P)
{ {
bool FoundMatch = FALSE; bool FoundMatch = FALSE;
string Theme = Wrap0i(P->Theme, sizeof(P->Theme)); for(int i = 0; i < UniqueThemes->ItemCount; ++i)
for(int i = 0; i < UniqueThemes->Count; ++i)
{ {
if(StringsMatch(UniqueThemes->S[i], Theme)) string **This = GetPlaceInBook(UniqueThemes, i);
if(StringsMatch(P->Theme, **This))
{ {
FoundMatch = TRUE; FoundMatch = TRUE;
} }
} }
if(!FoundMatch && Theme.Length > 0) if(!FoundMatch && P->Theme.Length > 0)
{ {
UniqueThemes->S = Fit(UniqueThemes->S, sizeof(*UniqueThemes->S), UniqueThemes->Count, 4, FALSE); string **This = MakeSpaceInBook(UniqueThemes);
UniqueThemes->S[UniqueThemes->Count] = Theme; *This = &P->Theme;
++UniqueThemes->Count;
} }
db_header_project *Child = LocateFirstChildProject(P); for(int i = 0; i < P->Child.ItemCount; ++i)
for(int i = 0; i < P->ChildCount; ++i)
{ {
project *Child = GetPlaceInBook(&P->Child, i);
PushUniqueStringsRecursively(UniqueThemes, Child); PushUniqueStringsRecursively(UniqueThemes, Child);
Child = SkipProject(Child);
} }
} }
void void
PushUniqueString(strings *UniqueThemes, string GlobalTheme) PushUniqueString(memory_book *UniqueThemes, string *GlobalTheme)
{ {
bool FoundMatch = FALSE; bool FoundMatch = FALSE;
for(int i = 0; i < UniqueThemes->Count; ++i) for(int i = 0; i < UniqueThemes->ItemCount; ++i)
{ {
if(StringsMatch(UniqueThemes->S[i], GlobalTheme)) string **This = GetPlaceInBook(UniqueThemes, i);
if(StringsMatch(*GlobalTheme, **This))
{ {
FoundMatch = TRUE; FoundMatch = TRUE;
} }
} }
if(!FoundMatch && GlobalTheme.Length > 0) if(!FoundMatch && GlobalTheme->Length > 0)
{ {
UniqueThemes->S = Fit(UniqueThemes->S, sizeof(*UniqueThemes->S), UniqueThemes->Count, 4, FALSE); string **This = MakeSpaceInBook(UniqueThemes);
UniqueThemes->S[UniqueThemes->Count] = GlobalTheme; *This = GlobalTheme;
++UniqueThemes->Count;
} }
} }
void void
GenerateThemeLinks(buffer *IncludesSearch, db_header_project *P) GenerateThemeLinks(buffer *IncludesSearch, project *P)
{ {
strings UniqueThemes = {}; memory_book UniqueThemes = {};
InitBookOfPointers(&UniqueThemes, 4, MBT_STRING_PTR);
if(P) if(P)
{ {
PushUniqueStringsRecursively(&UniqueThemes, P); PushUniqueStringsRecursively(&UniqueThemes, P);
} }
else else
{ {
PushUniqueString(&UniqueThemes, Config->GlobalTheme); PushUniqueString(&UniqueThemes, &Config->GlobalTheme);
db_block_projects *ProjectsBlock = DB.Metadata.Signposts.ProjectsBlock.Ptr ? DB.Metadata.Signposts.ProjectsBlock.Ptr : LocateBlock(B_PROJ); for(int i = 0; i < Config->Project.ItemCount; ++i)
P = LocateFirstChildProjectOfBlock(ProjectsBlock);
for(int i = 0; i < ProjectsBlock->Count; ++i)
{ {
P = GetPlaceInBook(&Config->Project, i);
PushUniqueStringsRecursively(&UniqueThemes, P); PushUniqueStringsRecursively(&UniqueThemes, P);
P = SkipProjectAndChildren(P);
} }
} }
for(int i = 0; i < UniqueThemes.Count; ++i) for(int i = 0; i < UniqueThemes.ItemCount; ++i)
{ {
string ThemeID = UniqueThemes.S[i]; string **This = GetPlaceInBook(&UniqueThemes, i);
string ThemeFilename = MakeString("sls", "cinera__", &ThemeID, ".css"); string ThemeFilename = MakeString("sls", "cinera__", *This, ".css");
asset *CSSTheme = GetAsset(ThemeFilename, ASSET_CSS); asset *CSSTheme = GetAsset(ThemeFilename, ASSET_CSS);
FreeString(&ThemeFilename); FreeString(&ThemeFilename);
buffer URL; buffer URL;
@ -12658,7 +12673,7 @@ GenerateThemeLinks(buffer *IncludesSearch, db_header_project *P)
"\">"); "\">");
} }
FreeAndResetCount(UniqueThemes.S, UniqueThemes.Count); FreeBook(&UniqueThemes);
} }
int int
@ -12711,7 +12726,7 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P
"\">"); "\">");
// TODO(matt): Switch the CollationBuffers->IncludesSearch to be allocated rather than claimed // TODO(matt): Switch the CollationBuffers->IncludesSearch to be allocated rather than claimed
GenerateThemeLinks(&CollationBuffers->IncludesSearch, StoredP); GenerateThemeLinks(&CollationBuffers->IncludesSearch, P);
asset *CSSTopics = GetAsset(Wrap0(BuiltinAssets[ASSET_CSS_TOPICS].Filename), ASSET_CSS); asset *CSSTopics = GetAsset(Wrap0(BuiltinAssets[ASSET_CSS_TOPICS].Filename), ASSET_CSS);
ConstructResolvedAssetURL(&URL, CSSTopics, PAGE_SEARCH); ConstructResolvedAssetURL(&URL, CSSTopics, PAGE_SEARCH);
@ -14877,8 +14892,7 @@ InitAll(neighbourhood *Neighbourhood, buffers *CollationBuffers, template *Bespo
for(int i = 0; i < Assets.ItemCount; ++i) for(int i = 0; i < Assets.ItemCount; ++i)
{ {
asset *This = GetPlaceInBook(&Assets, i); UpdateAssetInDB(GetPlaceInBook(&Assets, i));
UpdateAssetInDB(This);
} }
DeleteStaleAssets(); DeleteStaleAssets();
//PrintAssetsBlock(0); //PrintAssetsBlock(0);

File diff suppressed because it is too large Load Diff