hmml_to_html.c: Complete credits [#4]

Support multiple co-hosts, guests and annotators
This commit is contained in:
Matt Mascarenhas 2017-08-18 23:46:58 +01:00
parent bcaa6d63db
commit 6e1f6a4faa
2 changed files with 282 additions and 222 deletions

View File

@ -171,12 +171,16 @@
flex-direction: column;
}
.title > .menu > .credits_container .credit {
cursor: default;
}
.title > .menu > .credits_container .credit .person {
flex-grow: 1;
text-decoration: none;
}
.title > .menu > .credits_container .credit .support {
flex-grow: 1;
text-align: right;
padding: 16px;
}
@ -409,6 +413,7 @@
/* CUSTOM PAGE STYLE */
/*
body {
background-color: #000;
font-family: sans-serif;
@ -416,6 +421,7 @@ body {
margin: 0;
padding: 0;
}
*/
/*
Open menu: ▾

View File

@ -73,7 +73,16 @@ typedef struct
} category_info;
// TODO(matt): Parse this stuff out of a config file
char *Credentials[ ][5] =
typedef struct
{
char *Username;
char *CreditedName;
char *HomepageURL;
char *SupportIcon;
char *SupportURL;
} credential_info;
credential_info Credentials[] =
{
{ "Miblo", "Matt Mascarenhas", "http://miblodelcarpio.co.uk", "cinera_icon_patreon.png", "https://patreon.com/miblo"},
{ "miotatsu", "Mio Iwakura", "http://riscy.tv/", "cinera_icon_patreon.png", "https://patreon.com/miotatsu"},
@ -81,6 +90,31 @@ char *Credentials[ ][5] =
{ "cmuratori", "Casey Muratori", "https://handmadehero.org", "cinera_icon_patreon.png", "https://patreon.com/cmuratori"},
{ "fierydrake", "Mike Tunnicliffe", "", "", ""},
{ "abnercoimbre", "Abner Coimbre", "https://handmade.network/m/abnercoimbre", "cinera_icon_patreon.png", "https://patreon.com/handmade_dev"},
{ "/y_lee", "Yunsup Lee", "https://www.linkedin.com/in/yunsup-lee-385b692b/", "", ""},
{ "/a_waterman", "Andrew Waterman", "https://www.linkedin.com/in/andrew-waterman-76805788", "", ""},
{ "debiatan", "Miguel Lechón", "http://blog.debiatan.net/", "", ""},
};
typedef struct
{
char *Medium;
char *Icon;
char *WrittenName;
} category_medium;
category_medium CategoryMedium[] =
{
// medium icon written name
{ "afk", "…" , "Away from Keyboard"}, // TODO(matt): Filter this out by default
{ "authored", "🗪", "Chat Comment"}, // TODO(matt): Conditionally handle Chat vs Guest Comments
{ "blackboard", "🖌", "Blackboard"},
{ "experience", "🍷", "Experience"},
{ "owl", "🦉", "Owl of Shame"},
{ "programming", "🖮", "Programming"}, // TODO(matt): Potentially make this configurable per project
{ "rant", "💢", "Rant"},
{ "research", "📖", "Research"},
{ "run", "🏃", "In-Game"}, // TODO(matt): Potentially make this configurable per project
{ "trivia", "🎲", "Trivia"},
};
#define EDITION EDITION_SINGLE
@ -205,6 +239,19 @@ CopyStringNoFormat(char *Dest, char *String)
return Length;
}
int
CopyStringNoFormatT(char *Dest, char *String, char Terminator)
{
int Length = 0;
while(*String != Terminator)
{
*Dest++ = *String++;
++Length;
}
*Dest = '\0';
return Length;
}
int
StringLength(char *String)
{
@ -423,118 +470,157 @@ SanitisePunctuation(char *String)
return String;
}
int
BuildCredits(buffer *CreditsMenu, buffer *HostInfo, buffer *AnnotatorInfo, bool *HasCreditsMenu, char *ImagesDir, char *Host, char *Annotator)
enum
{
// TODO(matt): Handle co-hosts and guests
bool FoundHost = FALSE;
bool FoundAnnotator = FALSE;
CreditsError_NoHost = 1 << 0,
CreditsError_NoAnnotator = 1 << 1,
CreditsError_NoCredentials = 1 << 2
} CreditsErrorCodes;
int
SearchCredentials(buffer *CreditsMenu, bool *HasCreditsMenu, char *ImagesDir, char *Person, char* Role)
{
bool Found = FALSE;
for(int CredentialIndex = 0; CredentialIndex < ArrayCount(Credentials); ++CredentialIndex)
{
if(!StringsDiffer(Host, Credentials[CredentialIndex][0]))
if(!StringsDiffer(Person, Credentials[CredentialIndex].Username))
{
FoundHost = TRUE; // TODO(matt): Check if this is actually necessary...
CopyStringToBuffer(HostInfo,
" <span class=\"credit\">\n");
if(*Credentials[CredentialIndex][2])
Found = TRUE;
if(*HasCreditsMenu == FALSE)
{
CopyStringToBuffer(HostInfo,
" <a class=\"person\" href=\"%s\" target=\"_blank\">\n"
" <div class=\"role\">Host</div>\n"
" <div class=\"name\">%s</div>\n"
" </a>\n",
Credentials[CredentialIndex][2],
Credentials[CredentialIndex][1]);
}
else
{
CopyStringToBuffer(HostInfo,
" <div class=\"person\">\n"
" <div class=\"role\">Host</div>\n"
" <div class=\"name\">%s</div>\n"
" </div>\n",
Credentials[CredentialIndex][1]);
}
if(*Credentials[CredentialIndex][4] && *Credentials[CredentialIndex][3])
{
CopyStringToBuffer(HostInfo,
" <a class=\"support\" href=\"%s\" target=\"_blank\"><img src=\"%s/%s\"></a>\n",
Credentials[CredentialIndex][4],
ImagesDir,
Credentials[CredentialIndex][3]);
}
CopyStringToBuffer(HostInfo,
" </span>\n");
}
if(!StringsDiffer(Annotator, Credentials[CredentialIndex][0]))
{
FoundAnnotator = TRUE; // TODO(matt): Check if this is actually necessary...
CopyStringToBuffer(AnnotatorInfo,
" <span class=\"credit\">\n");
if(*Credentials[CredentialIndex][2])
{
CopyStringToBuffer(AnnotatorInfo,
" <a class=\"person\" href=\"%s\" target=\"_blank\">\n"
" <div class=\"role\">Annotator</div>\n"
" <div class=\"name\">%s</div>\n"
" </a>\n",
Credentials[CredentialIndex][2],
Credentials[CredentialIndex][1]);
}
else
{
CopyStringToBuffer(AnnotatorInfo,
" <div class=\"person\">\n"
" <div class=\"role\">Annotator</div>\n"
" <div class=\"name\">%s</div>\n"
" </div>\n",
Credentials[CredentialIndex][1]);
}
if(*Credentials[CredentialIndex][4] && *Credentials[CredentialIndex][3])
{
CopyStringToBuffer(AnnotatorInfo,
" <a class=\"support\" href=\"%s\" target=\"_blank\"><img src=\"%s/%s\"></a>\n",
Credentials[CredentialIndex][4],
ImagesDir,
Credentials[CredentialIndex][3]);
}
CopyStringToBuffer(AnnotatorInfo,
" </span>\n");
}
}
if(FoundHost || FoundAnnotator)
{
CopyStringToBuffer(CreditsMenu,
CopyStringToBuffer(CreditsMenu,
" <div class=\"menu credits\">\n"
" <div class=\"mouse_catcher\"></div>\n"
" <span>Credits</span>\n"
" <div class=\"credits_container\">\n");
if(FoundHost)
{
CopyBuffer(CreditsMenu, HostInfo);
*HasCreditsMenu = TRUE;
}
CopyStringToBuffer(CreditsMenu,
" <span class=\"credit\">\n");
if(*Credentials[CredentialIndex].HomepageURL)
{
CopyStringToBuffer(CreditsMenu,
" <a class=\"person\" href=\"%s\" target=\"_blank\">\n"
" <div class=\"role\">%s</div>\n"
" <div class=\"name\">%s</div>\n"
" </a>\n",
Credentials[CredentialIndex].HomepageURL,
Role,
Credentials[CredentialIndex].CreditedName);
}
else
{
CopyStringToBuffer(CreditsMenu,
" <div class=\"person\">\n"
" <div class=\"role\">%s</div>\n"
" <div class=\"name\">%s</div>\n"
" </div>\n",
Role,
Credentials[CredentialIndex].CreditedName);
}
if(*Credentials[CredentialIndex].SupportIcon && *Credentials[CredentialIndex].SupportURL)
{
CopyStringToBuffer(CreditsMenu,
" <a class=\"support\" href=\"%s\" target=\"_blank\"><img src=\"%s/%s\"></a>\n",
Credentials[CredentialIndex].SupportURL,
ImagesDir,
Credentials[CredentialIndex].SupportIcon);
}
CopyStringToBuffer(CreditsMenu,
" </span>\n");
}
if(FoundAnnotator)
}
return Found ? 0 : CreditsError_NoCredentials;
}
int
BuildCredits(buffer *CreditsMenu, bool *HasCreditsMenu, char *ImagesDir, HMML_VideoMetaData Metadata)
// TODO(matt): Make this take the Credentials, once we are parsing them from a config
{
if(Metadata.member)
{
if(SearchCredentials(CreditsMenu, HasCreditsMenu, ImagesDir, Metadata.member, "Host"))
{
CopyBuffer(CreditsMenu, AnnotatorInfo);
printf("No credentials for %s. Please contact matt@handmadedev.org with their:\n"
" Full name\n"
" Homepage URL (optional)\n"
" Financial support info, e.g. Patreon URL (optional)\n", Metadata.member);
}
CopyStringToBuffer(CreditsMenu,
" </div>\n"
" </div>\n");
}
else
{
return 1;
if(*HasCreditsMenu == TRUE)
{
CopyStringToBuffer(CreditsMenu,
" </div>\n"
" </div>\n");
}
return CreditsError_NoHost;
}
if(Metadata.co_host_count > 0)
{
for(int i = 0; i < Metadata.co_host_count; ++i)
{
if(SearchCredentials(CreditsMenu, HasCreditsMenu, ImagesDir, Metadata.co_hosts[i], "Co-host"))
{
printf("No credentials for %s. Please contact matt@handmadedev.org with their:\n"
" Full name\n"
" Homepage URL (optional)\n"
" Financial support info, e.g. Patreon URL (optional)\n", Metadata.co_hosts[i]);
}
}
}
if(Metadata.guest_count > 0)
{
for(int i = 0; i < Metadata.guest_count; ++i)
{
if(SearchCredentials(CreditsMenu, HasCreditsMenu, ImagesDir, Metadata.guests[i], "Guest"))
{
printf("No credentials for %s. Please contact matt@handmadedev.org with their:\n"
" Full name\n"
" Homepage URL (optional)\n"
" Financial support info, e.g. Patreon URL (optional)\n", Metadata.guests[i]);
}
}
}
if(Metadata.annotator_count > 0)
{
for(int i = 0; i < Metadata.annotator_count; ++i)
{
if(SearchCredentials(CreditsMenu, HasCreditsMenu, ImagesDir, Metadata.annotators[i], "Annotator"))
{
printf("No credentials for %s. Please contact matt@handmadedev.org with their:\n"
" Full name\n"
" Homepage URL (optional)\n"
" Financial support info, e.g. Patreon URL (optional)\n", Metadata.annotators[i]);
}
}
}
else
{
if(*HasCreditsMenu == TRUE)
{
CopyStringToBuffer(CreditsMenu,
" </div>\n"
" </div>\n");
}
return CreditsError_NoAnnotator;
}
if(*HasCreditsMenu == TRUE)
{
CopyStringToBuffer(CreditsMenu,
" </div>\n"
" </div>\n");
}
*HasCreditsMenu = TRUE;
return 0;
}
@ -643,21 +729,6 @@ BuildReference(ref_info *ReferencesArray, int RefIdentifier, int UniqueRefs, HMM
return 0;
}
char *CategoryMedium[][3] =
{
// medium icon written name
{ "afk", "&#8230;" , "Away from Keyboard"}, // TODO(matt): Filter this out by default
{ "authored", "&#128490;", "Chat Comment"}, // TODO(matt): Conditionally handle Chat vs Guest Comments
{ "blackboard", "&#128396;", "Blackboard"},
{ "experience", "&#127863;", "Experience"},
{ "owl", "&#129417;", "Owl of Shame"},
{ "programming", "&#128430;", "Programming"}, // TODO(matt): Potentially make this configurable per project
{ "rant", "&#128162;", "Rant"},
{ "research", "&#128214;", "Research"},
{ "run", "&#127939;", "In-Game"}, // TODO(matt): Potentially make this configurable per project
{ "trivia", "&#127922;", "Trivia"},
};
void
BuildFilter(category_info *TopicsArray, int *UniqueTopics, category_info *MediaArray, int *UniqueMedia, char *Marker)
{
@ -666,7 +737,7 @@ BuildFilter(category_info *TopicsArray, int *UniqueTopics, category_info *MediaA
int i = 0;
for(i = 0; i < ArrayCount(CategoryMedium); ++i)
{
if(!StringsDiffer(CategoryMedium[i][0], Marker))
if(!StringsDiffer(CategoryMedium[i].Medium, Marker))
{
IsMedium = TRUE;
break;
@ -679,11 +750,11 @@ BuildFilter(category_info *TopicsArray, int *UniqueTopics, category_info *MediaA
int j = 0;
for(j = 0; j < *UniqueMedia; ++j)
{
if(!StringsDiffer(CategoryMedium[i][0], MediaArray[j].Marker))
if(!StringsDiffer(CategoryMedium[i].Medium, MediaArray[j].Marker))
{
return;
}
if((Offset = StringsDiffer(CategoryMedium[i][2], MediaArray[j].WrittenText)) < 0)
if((Offset = StringsDiffer(CategoryMedium[i].WrittenName, MediaArray[j].WrittenText)) < 0)
{
int k;
for(k = *UniqueMedia; k > j; --k)
@ -692,16 +763,16 @@ BuildFilter(category_info *TopicsArray, int *UniqueTopics, category_info *MediaA
CopyString(MediaArray[k].WrittenText, MediaArray[k-1].WrittenText);
}
CopyString(MediaArray[k].Marker, CategoryMedium[i][0]);
CopyString(MediaArray[k].WrittenText, CategoryMedium[i][2]);
CopyString(MediaArray[k].Marker, CategoryMedium[i].Medium);
CopyString(MediaArray[k].WrittenText, CategoryMedium[i].WrittenName);
break;
}
}
if(j == *UniqueMedia)
{
CopyString(MediaArray[j].Marker, CategoryMedium[i][0]);
CopyString(MediaArray[j].WrittenText, CategoryMedium[i][2]);
CopyString(MediaArray[j].Marker, CategoryMedium[i].Medium);
CopyString(MediaArray[j].WrittenText, CategoryMedium[i].WrittenName);
}
++*UniqueMedia;
@ -748,7 +819,7 @@ BuildCategories(buffer *AnnotationClass, buffer *Category, int *MarkerIndex, boo
// The code in the "annotation loop" would then have to write both the head and tail of the category stuff
for(int i = 0; i < ArrayCount(CategoryMedium); ++i)
{
if(!StringsDiffer(CategoryMedium[i][0], Marker))
if(!StringsDiffer(CategoryMedium[i].Medium, Marker))
{
CopyStringToBuffer(AnnotationClass, " %s", SanitisePunctuation(Marker));
*HasMedium = TRUE;
@ -812,70 +883,6 @@ StringToInt(char *String)
return Result;
}
size_t
CurlIntoBuffer(char *InPtr, size_t CharLength, size_t Chars, char **OutputPtr)
{
int Length = CharLength * Chars;
int i;
for(i = 0; InPtr[i] && i < Length; ++i)
{
*((*OutputPtr)++) = InPtr[i];
}
**OutputPtr = '\0';
return Length;
};
int
SearchQuotes(buffer QuoteStaging, int CacheSize, quote_info *Info, int ID)
{
QuoteStaging.Ptr = QuoteStaging.Location;
while(QuoteStaging.Ptr - QuoteStaging.Location < CacheSize)
{
char InID[4] = { 0 };
char InTime[16] = { 0 };
char *OutPtr = InID;
while(*QuoteStaging.Ptr != ',')
{
*OutPtr++ = *QuoteStaging.Ptr++;
}
*OutPtr = '\0';
if(StringToInt(InID) == ID)
{
QuoteStaging.Ptr += 1;
OutPtr = InTime;
while(*QuoteStaging.Ptr != ',')
{
*OutPtr++ = *QuoteStaging.Ptr++;
}
*OutPtr = '\0';
long int Time = StringToInt(InTime);
strftime(Info->Date, 32, "%d %B, %Y", gmtime(&Time));
QuoteStaging.Ptr += 1;
OutPtr = Info->Text;
while(*QuoteStaging.Ptr != '\n')
{
*OutPtr++ = *QuoteStaging.Ptr++;
}
*OutPtr = '\0';
FreeBuffer(&QuoteStaging);
return 0;
}
else
{
while(*QuoteStaging.Ptr != '\n')
{
++QuoteStaging.Ptr;
}
++QuoteStaging.Ptr;
}
}
return 1;
}
int
MakeDir(char *Path)
{
@ -907,6 +914,19 @@ MakeDir(char *Path)
return 0;
}
size_t
CurlIntoBuffer(char *InPtr, size_t CharLength, size_t Chars, char **OutputPtr)
{
int Length = CharLength * Chars;
int i;
for(i = 0; InPtr[i] && i < Length; ++i)
{
*((*OutputPtr)++) = InPtr[i];
}
**OutputPtr = '\0';
return Length;
};
void
CurlQuotes(buffer *QuoteStaging, char *QuotesURL)
{
@ -924,6 +944,56 @@ CurlQuotes(buffer *QuoteStaging, char *QuotesURL)
}
}
int
SearchQuotes(buffer QuoteStaging, int CacheSize, quote_info *Info, int ID)
{
QuoteStaging.Ptr = QuoteStaging.Location;
while(QuoteStaging.Ptr - QuoteStaging.Location < CacheSize)
{
char InID[4] = { 0 };
char InTime[16] = { 0 };
char *OutPtr = InID;
QuoteStaging.Ptr += CopyStringNoFormatT(OutPtr, QuoteStaging.Ptr, ',');
if(StringToInt(InID) == ID)
{
QuoteStaging.Ptr += 1;
OutPtr = InTime;
QuoteStaging.Ptr += CopyStringNoFormatT(OutPtr, QuoteStaging.Ptr, ',');
long int Time = StringToInt(InTime);
char DayString[3];
strftime(DayString, 3, "%d", gmtime(&Time));
int Day = StringToInt(DayString);
char DaySuffix[3]; if(DayString[1] == '1' && Day != 11) { CopyString(DaySuffix, "st"); }
else if(DayString[1] == '2' && Day != 12) { CopyString(DaySuffix, "nd"); }
else if(DayString[1] == '3' && Day != 13) { CopyString(DaySuffix, "rd"); }
else { CopyString(DaySuffix, "th"); }
char MonthYear[32];
strftime(MonthYear, 32, "%B, %Y", gmtime(&Time));
CopyString(Info->Date, "%d%s %s", Day, DaySuffix, MonthYear);
QuoteStaging.Ptr += 1;
OutPtr = Info->Text;
QuoteStaging.Ptr += CopyStringNoFormatT(OutPtr, QuoteStaging.Ptr, '\n');
FreeBuffer(&QuoteStaging);
return 0;
}
else
{
while(*QuoteStaging.Ptr != '\n')
{
++QuoteStaging.Ptr;
}
++QuoteStaging.Ptr;
}
}
return 1;
}
int
BuildQuote(quote_info *Info, char *Speaker, int ID, char *CacheDir)
{
@ -963,7 +1033,7 @@ BuildQuote(quote_info *Info, char *Speaker, int ID, char *CacheDir)
QuoteStaging.Size = Kilobytes(256);
if(!(QuoteStaging.Location = malloc(QuoteStaging.Size)))
{
perror("malloc");
perror("BuildQuote");
}
QuoteStaging.Ptr = QuoteStaging.Location;
@ -1016,7 +1086,7 @@ GenerateTopicColours(buffer *Colour, char *Topic, char *TopicsDir)
{
for(int i = 0; i < ArrayCount(CategoryMedium); ++i)
{
if(!StringsDiffer(Topic, CategoryMedium[i][0]))
if(!StringsDiffer(Topic, CategoryMedium[i].Medium))
{
return;
}
@ -1482,7 +1552,7 @@ main(int ArgC, char **Args)
bool ValidDefaultMedium = FALSE;
for(int i = 0; i < ArrayCount(CategoryMedium); ++i)
{
if(!StringsDiffer(DefaultMedium, CategoryMedium[i][0]))
if(!StringsDiffer(DefaultMedium, CategoryMedium[i].Medium))
{
ValidDefaultMedium = TRUE;
break;
@ -1493,7 +1563,7 @@ main(int ArgC, char **Args)
fprintf(stderr, "Specified default medium \"%s\" not available. Valid media are:\n", DefaultMedium);
for(int i = 0; i < ArrayCount(CategoryMedium); ++i)
{
fprintf(stderr, " %s\n", CategoryMedium[i][0]);
fprintf(stderr, " %s\n", CategoryMedium[i].Medium);
}
fprintf(stderr, "To have \"%s\" added to the list, contact matt@handmadedev.org\n", DefaultMedium);
return 1;
@ -1714,6 +1784,7 @@ main(int ArgC, char **Args)
// FilterMenu
// FilterTopics
// FilterMedia
// CreditsMenu
// Player
// Colour
// Annotation
@ -1735,8 +1806,6 @@ main(int ArgC, char **Args)
buffer FilterTopics;
buffer FilterMedia;
buffer CreditsMenu;
buffer HostInfo;
buffer AnnotatorInfo;
buffer Player;
buffer Colour;
@ -1803,8 +1872,6 @@ main(int ArgC, char **Args)
ClaimBuffer(&MemoryArena, &ClaimedMemory, &FilterTopics, "FilterTopics", Kilobytes(8));
ClaimBuffer(&MemoryArena, &ClaimedMemory, &FilterMedia, "FilterMedia", Kilobytes(8));
ClaimBuffer(&MemoryArena, &ClaimedMemory, &CreditsMenu, "CreditsMenu", Kilobytes(8));
ClaimBuffer(&MemoryArena, &ClaimedMemory, &HostInfo, "HostInfo", Kilobytes(1));
ClaimBuffer(&MemoryArena, &ClaimedMemory, &AnnotatorInfo, "AnnotatorInfo", Kilobytes(1));
ClaimBuffer(&MemoryArena, &ClaimedMemory, &Player, "Player", Kilobytes(256));
ClaimBuffer(&MemoryArena, &ClaimedMemory, &Colour, "Colour", 32);
@ -1840,18 +1907,22 @@ main(int ArgC, char **Args)
" <div class=\"video_container\" data-videoId=\"%s\"></div>\n"
" <div class=\"markers_container %s\">\n", HMML.metadata.id, HMML.metadata.project);
// TODO(matt): Handle multiple annotators
if(HMML.metadata.annotator_count > 0)
int CreditsErrorCode = BuildCredits(&CreditsMenu, &HasCreditsMenu, ImagesDir, HMML.metadata);
if(CreditsErrorCode)
{
BuildCredits(&CreditsMenu, &HostInfo, &AnnotatorInfo, &HasCreditsMenu, ImagesDir, HMML.metadata.member, HMML.metadata.annotators[0]);
}
else
{
fprintf(stderr, "%s: Missing annotator in [video] node\n", Args[FileIndex]);
hmml_free(&HMML);
free(MemoryArena.Location);
free(Template.Location);
return 1;
switch(CreditsErrorCode)
{
case CreditsError_NoHost:
fprintf(stderr, "%s: Missing \"member\" in the [video] node. Skipping...\n", Args[FileIndex]);
goto Cleanup;
break;
case CreditsError_NoAnnotator:
fprintf(stderr, "%s: Missing \"annotator\" in the [video] node. Skipping...\n", Args[FileIndex]);
goto Cleanup;
break;
default:
break;
}
}
#if DEBUG
@ -2216,20 +2287,6 @@ main(int ArgC, char **Args)
free(Template.Location);
return 1;
}
if(BuildQuote(&QuoteInfo,
Speaker,
Anno->quote.id,
CacheDir) == 2)
{
fprintf(stderr, "%s:%d: Failed to create quote cache at %s/quotes/%s for Quote #%s %d.\n"
"Proceeding anyway, without a cache!\n",
Args[FileIndex],
Anno->line,
CacheDir,
Speaker,
Speaker,
Anno->quote.id);
}
CopyStringToBuffer(&QuoteMenu,
" <a target=\"_blank\" class=\"ref\" href=\"https://dev.abaines.me.uk/quotes/%s/%d\">\n"
@ -2478,7 +2535,7 @@ main(int ArgC, char **Args)
int j;
for(j = 0; j < ArrayCount(CategoryMedium); ++j)
{
if(!StringsDiffer(MediaArray[i].Marker, CategoryMedium[j][0]))
if(!StringsDiffer(MediaArray[i].Marker, CategoryMedium[j].Medium))
{
break;
}
@ -2489,8 +2546,8 @@ main(int ArgC, char **Args)
" <span class=\"icon\">%s</span><span class=\"text\">%s</span>\n"
" </div>\n",
MediaArray[i].Marker,
CategoryMedium[j][1],
CategoryMedium[j][2]
CategoryMedium[j].Icon,
CategoryMedium[j].WrittenName
);
}
@ -3158,8 +3215,6 @@ main(int ArgC, char **Args)
// Annotation
// Colour
// Player
// AnnotatorInfo
// HostInfo
// CreditsMenu
// FilterMedia
// FilterTopics
@ -3170,14 +3225,13 @@ main(int ArgC, char **Args)
// Includes
// Master
Cleanup:
DeclaimBuffer(&FilterState, &ClaimedMemory);
DeclaimBuffer(&Script, &ClaimedMemory);
DeclaimBuffer(&Annotation, &ClaimedMemory);
DeclaimBuffer(&Colour, &ClaimedMemory);
DeclaimBuffer(&Player, &ClaimedMemory);
DeclaimBuffer(&AnnotatorInfo, &ClaimedMemory);
DeclaimBuffer(&HostInfo, &ClaimedMemory);
DeclaimBuffer(&CreditsMenu, &ClaimedMemory);
DeclaimBuffer(&FilterMedia, &ClaimedMemory);
DeclaimBuffer(&FilterTopics, &ClaimedMemory);