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 = {
.Major = 0,
.Minor = 7,
.Patch = 11
.Patch = 12
};
#include <stdarg.h> // NOTE(matt): varargs
@ -462,15 +462,28 @@ typedef enum
MBT_NONE,
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_NAVIGATION_BUFFER,
MBT_PERSON,
MBT_PERSON_PTR,
MBT_PROJECT,
MBT_PROJECT_PTR,
MBT_RESOLUTION_ERROR,
MBT_STRING,
MBT_STRING_PTR,
MBT_SUPPORT,
MBT_TAG_OFFSET,
MBT_TOKEN,
MBT_TOKENS,
MBT_VARIANT,
MBT_VARIANT_STRING,
} memory_book_type;
typedef struct
@ -493,6 +506,12 @@ InitBook(memory_book *M, uint64_t DataWidthInBytes, uint64_t ItemsPerPage, memor
M->DataWidthInBytes = DataWidthInBytes;
}
void
InitBookOfPointers(memory_book *M, uint64_t ItemsPerPage, memory_book_type Type)
{
InitBook(M, sizeof(uintptr_t), ItemsPerPage, Type);
}
memory_page *
AddPage(memory_book *M)
{
@ -538,9 +557,13 @@ void
FreeAndReinitialiseBook(memory_book *M)
{
int PageSize = M->PageSize;
int DataWidthInBytes = M->DataWidthInBytes;
int Type = M->Type;
FreeBook(M);
M->PageSize = PageSize;
M->DataWidthInBytes = DataWidthInBytes;
M->Type = Type;
}
@ -634,6 +657,12 @@ GetPlaceInBook(memory_book *M, int Index)
return Result;
}
void *
MakeSpaceInBook(memory_book *M)
{
return GetPlaceInBook(M, M->ItemCount++);
}
string
ExtendStringInBook(memory_book *M, string S)
{
@ -723,14 +752,27 @@ PrintBook(memory_book *M)
} break;
case MBT_NONE: 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_NAVIGATION_BUFFER: 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_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_TAG_OFFSET: Assert(0); break;
case MBT_TOKEN: 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
ClearTemplateMetadata(template *Template)
{
Template->Metadata.Validity = 0;
Template->Metadata.Type = TEMPLATE_NULL;
Template->Metadata.RequiresCineraJS = FALSE;
FreeTemplateNavBuffers(Template);
FreeBook(&Template->Metadata.NavBuffer);
FreeBook(&Template->Metadata.Tags);
template_metadata Zero = {};
Template->Metadata = Zero;
}
void
@ -2666,7 +2710,6 @@ void
FreeTemplate(template *Template)
{
FreeFile(&Template->File);
FreeBook(&Template->Metadata.Tags);
ClearTemplateMetadata(Template);
}
@ -3710,12 +3753,11 @@ GetDirectoryPath(char *Filepath)
void
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->TagCode = TagCode;
This->Asset = Asset;
This->Nav = NavBuffer;
++Template->Metadata.Tags.ItemCount;
}
void
@ -6202,10 +6244,8 @@ FreeCredentials(speakers *S)
void
WaitForInput()
{
#if 0
fprintf(stderr, "Press Enter to continue...\n");
getchar();
#endif
}
void
@ -6990,17 +7030,6 @@ GenerateTopicColours(neighbourhood *N, string Topic)
}
}
/*
* NOTE(matt);
*
* Documentation structure:
*
* section
*
* option <argument>
* description
*/
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 \
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."));
config_type_specs TypeSpecs = InitTypeSpecs();
memory_book TypeSpecs = InitTypeSpecs();
PrintTypeSpecs(&TypeSpecs, IndentationLevel);
//FreeTypeSpecs(&TypeSpecs);
EndSection(&IndentationLevel);
@ -7638,10 +7667,9 @@ PushNavBufferUniquely(template *Template, navigation_spec Spec)
navigation_buffer *Result = GetNavBufferFromTemplate(Template, Spec);
if(!Result)
{
Result = GetPlaceInBook(&Template->Metadata.NavBuffer, Template->Metadata.NavBuffer.ItemCount);
Result = MakeSpaceInBook(&Template->Metadata.NavBuffer);
Result->Spec = Spec;
Result->Buffer.ID = BID_NAVIGATION;
++Template->Metadata.NavBuffer.ItemCount;
}
return Result;
}
@ -7980,14 +8008,8 @@ ConstructPlayerURL(buffer *PlayerURL, db_header_project *P, string EntryOutput)
medium *
MediumExists(string Medium)
{
medium *ParsedMedium = GetMediumFromProject(CurrentProject, Medium);
if(ParsedMedium)
{
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)
medium *Result = GetMediumFromProject(CurrentProject, Medium);
if(!Result)
{
typography Typography =
{
@ -8002,16 +8024,21 @@ MediumExists(string Medium)
.Delimiter = ": ",
.Separator = "",
};
medium *This = GetPlaceInBook(&CurrentProject->Medium, i);
PrintMedium(&Typography, This, ": ", 2, TRUE);
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);
PrintMedium(&Typography, This, ": ", 2, TRUE);
}
fprintf(stderr, "Perhaps you'd like to add a new medium to your config file, e.g.:\n"
" medium = \"%.*s\"\n"
" {\n"
" name = \"Name of Medium\";\n"
" icon = \"&#129514;\";\n"
" }\n", (int)Medium.Length, Medium.Base);
}
fprintf(stderr, "Perhaps you'd like to add a new medium to your config file, e.g.:\n"
" medium = \"%.*s\"\n"
" {\n"
" name = \"Name of Medium\";\n"
" icon = \"&#129514;\";\n"
" }\n", (int)Medium.Length, Medium.Base);
return 0;
return Result;
}
typedef struct
@ -10452,12 +10479,10 @@ BuffersToHTML(config *C, project *Project, buffers *CollationBuffers, template *
Template->File.Buffer.Ptr = Template->File.Buffer.Location;
for(int i = 0; i < Template->Metadata.Tags.ItemCount; ++i)
{
int j = 0;
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++;
++j;
}
// 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)
{
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
@ -12565,85 +12590,75 @@ AtLeastNProjectsHavePublicEntries(uint8_t N)
return FALSE;
}
// TODO(matt): Replace with a memory_book
typedef struct
{
string *S;
uint64_t Count;
} strings;
void
PushUniqueStringsRecursively(strings *UniqueThemes, db_header_project *P)
PushUniqueStringsRecursively(memory_book *UniqueThemes, project *P)
{
bool FoundMatch = FALSE;
string Theme = Wrap0i(P->Theme, sizeof(P->Theme));
for(int i = 0; i < UniqueThemes->Count; ++i)
for(int i = 0; i < UniqueThemes->ItemCount; ++i)
{
if(StringsMatch(UniqueThemes->S[i], Theme))
string **This = GetPlaceInBook(UniqueThemes, i);
if(StringsMatch(P->Theme, **This))
{
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);
UniqueThemes->S[UniqueThemes->Count] = Theme;
++UniqueThemes->Count;
string **This = MakeSpaceInBook(UniqueThemes);
*This = &P->Theme;
}
db_header_project *Child = LocateFirstChildProject(P);
for(int i = 0; i < P->ChildCount; ++i)
for(int i = 0; i < P->Child.ItemCount; ++i)
{
project *Child = GetPlaceInBook(&P->Child, i);
PushUniqueStringsRecursively(UniqueThemes, Child);
Child = SkipProject(Child);
}
}
void
PushUniqueString(strings *UniqueThemes, string GlobalTheme)
PushUniqueString(memory_book *UniqueThemes, string *GlobalTheme)
{
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;
}
}
if(!FoundMatch && GlobalTheme.Length > 0)
if(!FoundMatch && GlobalTheme->Length > 0)
{
UniqueThemes->S = Fit(UniqueThemes->S, sizeof(*UniqueThemes->S), UniqueThemes->Count, 4, FALSE);
UniqueThemes->S[UniqueThemes->Count] = GlobalTheme;
++UniqueThemes->Count;
string **This = MakeSpaceInBook(UniqueThemes);
*This = GlobalTheme;
}
}
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)
{
PushUniqueStringsRecursively(&UniqueThemes, P);
}
else
{
PushUniqueString(&UniqueThemes, Config->GlobalTheme);
db_block_projects *ProjectsBlock = DB.Metadata.Signposts.ProjectsBlock.Ptr ? DB.Metadata.Signposts.ProjectsBlock.Ptr : LocateBlock(B_PROJ);
P = LocateFirstChildProjectOfBlock(ProjectsBlock);
for(int i = 0; i < ProjectsBlock->Count; ++i)
PushUniqueString(&UniqueThemes, &Config->GlobalTheme);
for(int i = 0; i < Config->Project.ItemCount; ++i)
{
P = GetPlaceInBook(&Config->Project, i);
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 ThemeFilename = MakeString("sls", "cinera__", &ThemeID, ".css");
string **This = GetPlaceInBook(&UniqueThemes, i);
string ThemeFilename = MakeString("sls", "cinera__", *This, ".css");
asset *CSSTheme = GetAsset(ThemeFilename, ASSET_CSS);
FreeString(&ThemeFilename);
buffer URL;
@ -12658,7 +12673,7 @@ GenerateThemeLinks(buffer *IncludesSearch, db_header_project *P)
"\">");
}
FreeAndResetCount(UniqueThemes.S, UniqueThemes.Count);
FreeBook(&UniqueThemes);
}
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
GenerateThemeLinks(&CollationBuffers->IncludesSearch, StoredP);
GenerateThemeLinks(&CollationBuffers->IncludesSearch, P);
asset *CSSTopics = GetAsset(Wrap0(BuiltinAssets[ASSET_CSS_TOPICS].Filename), ASSET_CSS);
ConstructResolvedAssetURL(&URL, CSSTopics, PAGE_SEARCH);
@ -14877,8 +14892,7 @@ InitAll(neighbourhood *Neighbourhood, buffers *CollationBuffers, template *Bespo
for(int i = 0; i < Assets.ItemCount; ++i)
{
asset *This = GetPlaceInBook(&Assets, i);
UpdateAssetInDB(This);
UpdateAssetInDB(GetPlaceInBook(&Assets, i));
}
DeleteStaleAssets();
//PrintAssetsBlock(0);

File diff suppressed because it is too large Load Diff