hmml_to_html.c: Sort the filter media [#21]

This commit is contained in:
Matt Mascarenhas 2017-05-24 22:56:36 +01:00
parent f4352572b9
commit 2d9af4ee93
1 changed files with 154 additions and 110 deletions

View File

@ -17,6 +17,9 @@ typedef unsigned int bool;
#include <stdlib.h> // NOTE(matt): calloc, malloc, free #include <stdlib.h> // NOTE(matt): calloc, malloc, free
#include "hmmlib.h" #include "hmmlib.h"
#define Kilobytes(Bytes) Bytes << 10
#define Megabytes(Bytes) Bytes << 20
typedef struct typedef struct
{ {
char *Location; char *Location;
@ -53,8 +56,8 @@ typedef struct
typedef struct typedef struct
{ {
char Category[32]; char Marker[32];
bool IsMedium; char WrittenText[32];
} category_info; } category_info;
#define ArrayCount(A) sizeof(A)/sizeof(*(A)) #define ArrayCount(A) sizeof(A)/sizeof(*(A))
@ -127,7 +130,7 @@ CopyBuffer(buffer *Dest, buffer *Src)
{ {
if(Dest->Ptr - Dest->Location >= Dest->Size) if(Dest->Ptr - Dest->Location >= Dest->Size)
{ {
printf("Too big! Too big!\n"); fprintf(stderr, "CopyBuffer: %s cannot accommodate %s\n", Dest->ID, Src->ID);
__asm__("int3"); __asm__("int3");
} }
@ -150,14 +153,6 @@ __attribute__ ((format (printf, 2, 3)))
void void
CopyStringToBuffer(buffer *Dest, char *Format, ...) CopyStringToBuffer(buffer *Dest, char *Format, ...)
{ {
// TODO(matt):
{
if(Dest->Ptr - Dest->Location >= Dest->Size)
{
printf("Too big! Too big!\n");
__asm__("int3");
}
}
va_list Args; va_list Args;
va_start(Args, Format); va_start(Args, Format);
int Length = vsprintf(Dest->Ptr, Format, Args); int Length = vsprintf(Dest->Ptr, Format, Args);
@ -166,7 +161,7 @@ CopyStringToBuffer(buffer *Dest, char *Format, ...)
{ {
if(Length + (Dest->Ptr - Dest->Location) >= Dest->Size) if(Length + (Dest->Ptr - Dest->Location) >= Dest->Size)
{ {
printf("Too big! Too big!\n"); fprintf(stderr, "CopyStringToBuffer: %s cannot accommodate %d-character string\n", Dest->ID, Length);
__asm__("int3"); __asm__("int3");
} }
} }
@ -378,46 +373,84 @@ char *CategoryMedium[][3] =
}; };
void void
BuildFilter(category_info *CategoriesArray, int *UniqueCategories, char *Marker) BuildFilter(category_info *TopicsArray, int *UniqueTopics, category_info *MediaArray, int *UniqueMedia, char *Marker)
{ {
int Offset = 0; int Offset;
int i = 0; bool IsMedium = FALSE;
for(i = 0; i < *UniqueCategories; ++i)
{
if(!StringsDiffer(Marker, CategoriesArray[i].Category))
{
return;
}
if((Offset = StringsDiffer(Marker, CategoriesArray[i].Category)) < 0)
{
int j;
for(j = *UniqueCategories; j > i; --j)
{
CopyString(CategoriesArray[j].Category, CategoriesArray[j-1].Category);
CategoriesArray[j].IsMedium = CategoriesArray[j-1].IsMedium;
}
CopyString(CategoriesArray[j].Category, Marker); int i = 0;
CategoriesArray[j].IsMedium = FALSE; for(i = 0; i < ArrayCount(CategoryMedium); ++i)
{
if(!StringsDiffer(CategoryMedium[i][0], Marker))
{
IsMedium = TRUE;
break; break;
} }
} }
// This really ought to sort by the Alternative Text if(IsMedium)
if(i == *UniqueCategories)
{ {
CopyString(CategoriesArray[i].Category, Marker); int j = 0;
} for(j = 0; j < *UniqueMedia; ++j)
++*UniqueCategories;
for(int k = 0; k < ArrayCount(CategoryMedium); ++k)
{
if(!StringsDiffer(CategoryMedium[k][0], Marker))
{ {
CategoriesArray[i].IsMedium = TRUE; if(!StringsDiffer(CategoryMedium[i][0], MediaArray[j].Marker))
{
return;
}
if((Offset = StringsDiffer(CategoryMedium[i][2], MediaArray[j].WrittenText)) < 0)
{
int k;
for(k = *UniqueMedia; k > j; --k)
{
CopyString(MediaArray[k].Marker, MediaArray[k-1].Marker);
CopyString(MediaArray[k].WrittenText, MediaArray[k-1].WrittenText);
}
CopyString(MediaArray[k].Marker, CategoryMedium[i][0]);
CopyString(MediaArray[k].WrittenText, CategoryMedium[i][2]);
break;
}
} }
if(j == *UniqueMedia)
{
CopyString(MediaArray[j].Marker, CategoryMedium[i][0]);
CopyString(MediaArray[j].WrittenText, CategoryMedium[i][2]);
}
++*UniqueMedia;
return;
}
else
{
int i = 0;
for(i = 0; i < *UniqueTopics; ++i)
{
if(!StringsDiffer(Marker, TopicsArray[i].Marker))
{
return;
}
if((Offset = StringsDiffer(Marker, TopicsArray[i].Marker)) < 0)
{
int j;
for(j = *UniqueTopics; j > i; --j)
{
CopyString(TopicsArray[j].Marker, TopicsArray[j-1].Marker);
}
CopyString(TopicsArray[j].Marker, Marker);
break;
}
}
// This really ought to sort by the Alternative Text
if(i == *UniqueTopics)
{
CopyString(TopicsArray[i].Marker, Marker);
}
++*UniqueTopics;
} }
} }
@ -889,7 +922,7 @@ main(int ArgC, char **Args)
// NOTE(matt): Init MemoryArena // NOTE(matt): Init MemoryArena
char *MemoryArena; char *MemoryArena;
int ArenaSize = 1024 * 1024 * 4; int ArenaSize = Megabytes(4);
if(!(MemoryArena = calloc(ArenaSize, 1))) if(!(MemoryArena = calloc(ArenaSize, 1)))
{ {
perror(Args[0]); perror(Args[0]);
@ -953,7 +986,7 @@ main(int ArgC, char **Args)
} }
#if CONFIG #if CONFIG
ClaimBuffer(MemoryArena, &ClaimedMemory, &Config, "Config", 1024); ClaimBuffer(MemoryArena, &ClaimedMemory, &Config, "Config", Kilobytes(1));
#endif #endif
HMML_Output HMML = hmml_parse_file(InFile); HMML_Output HMML = hmml_parse_file(InFile);
@ -974,23 +1007,24 @@ main(int ArgC, char **Args)
// Annotation // Annotation
// FilterState // FilterState
ClaimBuffer(MemoryArena, &ClaimedMemory, &Master, "Master", 1024 * 512); ClaimBuffer(MemoryArena, &ClaimedMemory, &Master, "Master", Kilobytes(512));
ClaimBuffer(MemoryArena, &ClaimedMemory, &Title, "Title", 1024 * 16); ClaimBuffer(MemoryArena, &ClaimedMemory, &Title, "Title", Kilobytes(16));
ClaimBuffer(MemoryArena, &ClaimedMemory, &QuoteMenu, "QuoteMenu", 1024 * 16); ClaimBuffer(MemoryArena, &ClaimedMemory, &QuoteMenu, "QuoteMenu", Kilobytes(16));
ClaimBuffer(MemoryArena, &ClaimedMemory, &ReferenceMenu, "ReferenceMenu", 1024 * 16); ClaimBuffer(MemoryArena, &ClaimedMemory, &ReferenceMenu, "ReferenceMenu", Kilobytes(16));
ClaimBuffer(MemoryArena, &ClaimedMemory, &FilterMenu, "FilterMenu", 1024 * 16); ClaimBuffer(MemoryArena, &ClaimedMemory, &FilterMenu, "FilterMenu", Kilobytes(16));
ClaimBuffer(MemoryArena, &ClaimedMemory, &FilterTopics, "FilterTopics", 1024 * 8); ClaimBuffer(MemoryArena, &ClaimedMemory, &FilterTopics, "FilterTopics", Kilobytes(8));
ClaimBuffer(MemoryArena, &ClaimedMemory, &FilterMedia, "FilterMedia", 1024 * 8); ClaimBuffer(MemoryArena, &ClaimedMemory, &FilterMedia, "FilterMedia", Kilobytes(8));
ClaimBuffer(MemoryArena, &ClaimedMemory, &Player, "Player", 1024 * 256); ClaimBuffer(MemoryArena, &ClaimedMemory, &Player, "Player", Kilobytes(256));
ClaimBuffer(MemoryArena, &ClaimedMemory, &Colour, "Colour", 32); ClaimBuffer(MemoryArena, &ClaimedMemory, &Colour, "Colour", 32);
ClaimBuffer(MemoryArena, &ClaimedMemory, &Annotation, "Annotation", 1024 * 8); ClaimBuffer(MemoryArena, &ClaimedMemory, &Annotation, "Annotation", Kilobytes(8));
ClaimBuffer(MemoryArena, &ClaimedMemory, &FilterState, "FilterState", 1024 * 4); ClaimBuffer(MemoryArena, &ClaimedMemory, &FilterState, "FilterState", Kilobytes(4));
ref_info ReferencesArray[200] = { 0 }; ref_info ReferencesArray[200] = { 0 };
category_info CategoriesArray[64] = { 0 }; category_info TopicsArray[56] = { 0 };
category_info MediaArray[8] = { 0 };
bool HasQuoteMenu = FALSE; bool HasQuoteMenu = FALSE;
bool HasReferenceMenu = FALSE; bool HasReferenceMenu = FALSE;
@ -999,7 +1033,8 @@ main(int ArgC, char **Args)
int QuoteIdentifier = 0x3b1; int QuoteIdentifier = 0x3b1;
int RefIdentifier = 1; int RefIdentifier = 1;
int UniqueRefs = 0; int UniqueRefs = 0;
int UniqueCategories = 0; int UniqueTopics = 0;
int UniqueMedia = 0;
CopyStringToBuffer(&Title, CopyStringToBuffer(&Title,
" <div class=\"title %s\">\n" " <div class=\"title %s\">\n"
@ -1036,8 +1071,8 @@ main(int ArgC, char **Args)
ClaimBuffer(MemoryArena, &ClaimedMemory, &AnnotationHeader, "AnnotationHeader", 512); ClaimBuffer(MemoryArena, &ClaimedMemory, &AnnotationHeader, "AnnotationHeader", 512);
ClaimBuffer(MemoryArena, &ClaimedMemory, &AnnotationClass, "AnnotationClass", 256); ClaimBuffer(MemoryArena, &ClaimedMemory, &AnnotationClass, "AnnotationClass", 256);
ClaimBuffer(MemoryArena, &ClaimedMemory, &AnnotationData, "AnnotationData", 128); ClaimBuffer(MemoryArena, &ClaimedMemory, &AnnotationData, "AnnotationData", 256);
ClaimBuffer(MemoryArena, &ClaimedMemory, &Text, "Text", 1024 * 4); ClaimBuffer(MemoryArena, &ClaimedMemory, &Text, "Text", Kilobytes(4));
ClaimBuffer(MemoryArena, &ClaimedMemory, &Category, "Category", 256); ClaimBuffer(MemoryArena, &ClaimedMemory, &Category, "Category", 256);
CopyStringToBuffer(&AnnotationHeader, CopyStringToBuffer(&AnnotationHeader,
@ -1053,7 +1088,7 @@ TimecodeToSeconds(Anno->time));
{ {
HasFilterMenu = TRUE; HasFilterMenu = TRUE;
} }
BuildFilter(CategoriesArray, &UniqueCategories, "authored"); BuildFilter(TopicsArray, &UniqueTopics, MediaArray, &UniqueMedia, "authored");
CopyStringToBuffer(&AnnotationClass, " authored"); CopyStringToBuffer(&AnnotationClass, " authored");
CopyStringToBuffer(&Text, CopyStringToBuffer(&Text,
"<span class=\"author\" style=\"color: %s;\">%s</span> ", "<span class=\"author\" style=\"color: %s;\">%s</span> ",
@ -1104,7 +1139,7 @@ Readable);
{ {
HasFilterMenu = TRUE; HasFilterMenu = TRUE;
} }
BuildFilter(CategoriesArray, &UniqueCategories, Anno->markers[MarkerIndex].marker); BuildFilter(TopicsArray, &UniqueTopics, MediaArray, &UniqueMedia, Anno->markers[MarkerIndex].marker);
BuildCategories(&AnnotationClass, &Category, &MarkerIndex, &HasCategory, &HasMedium, Anno->markers[MarkerIndex].marker); BuildCategories(&AnnotationClass, &Category, &MarkerIndex, &HasCategory, &HasMedium, Anno->markers[MarkerIndex].marker);
} }
} }
@ -1216,7 +1251,14 @@ AppendedIdentifier:
} }
} }
CopyStringToBuffer(&Text, "<sup>%d</sup>", RefIdentifier); if(RefIndex > 1 && Anno->references[RefIndex].offset == Anno->references[RefIndex-1].offset)
{
CopyStringToBuffer(&Text, "<sup>,%d</sup>", RefIdentifier);
}
else
{
CopyStringToBuffer(&Text, "<sup>%d</sup>", RefIdentifier);
}
++RefIndex; ++RefIndex;
++RefIdentifier; ++RefIdentifier;
@ -1302,14 +1344,14 @@ Anno->time);
} }
if(Anno->markers[MarkerIndex].marker) if(Anno->markers[MarkerIndex].marker)
{ {
BuildFilter(CategoriesArray, &UniqueCategories, Anno->markers[MarkerIndex].marker); BuildFilter(TopicsArray, &UniqueTopics, MediaArray, &UniqueMedia, Anno->markers[MarkerIndex].marker);
} }
BuildCategories(&AnnotationClass, &Category, &MarkerIndex, &HasCategory, &HasMedium, Anno->markers[MarkerIndex].marker); BuildCategories(&AnnotationClass, &Category, &MarkerIndex, &HasCategory, &HasMedium, Anno->markers[MarkerIndex].marker);
} }
if(!HasMedium) if(!HasMedium)
{ {
BuildFilter(CategoriesArray, &UniqueCategories, "default"); BuildFilter(TopicsArray, &UniqueTopics, MediaArray, &UniqueMedia, "default");
BuildCategories(&AnnotationClass, &Category, &MarkerIndex, &HasCategory, &HasMedium, "default"); BuildCategories(&AnnotationClass, &Category, &MarkerIndex, &HasCategory, &HasMedium, "default");
} }
@ -1442,10 +1484,15 @@ ReferencesArray[i].Identifier[j].Timecode);
if(HasFilterMenu) if(HasFilterMenu)
{ {
CopyStringToBuffer(&FilterState, "var filterState = {\n"); CopyStringToBuffer(&FilterState, "var filterState = {\n");
for(int i = 0; i < UniqueCategories; ++i) for(int i = 0; i < UniqueTopics; ++i)
{ {
CopyStringToBuffer(&FilterState, "\"%s\":\t{ \"type\": \"%s\",\t\"off\": false },\n", CopyStringToBuffer(&FilterState, "\"%s\":\t{ \"type\": \"%s\",\t\"off\": false },\n",
CategoriesArray[i].Category, CategoriesArray[i].IsMedium ? "medium" : "topic"); TopicsArray[i].Marker, "topic");
}
for(int i = 0; i < UniqueMedia; ++i)
{
CopyStringToBuffer(&FilterState, "\"%s\":\t{ \"type\": \"%s\",\t\"off\": false },\n",
MediaArray[i].Marker, "medium");
} }
CopyStringToBuffer(&FilterState, "};\n" CopyStringToBuffer(&FilterState, "};\n"
"\n"); "\n");
@ -1461,59 +1508,53 @@ ReferencesArray[i].Identifier[j].Timecode);
bool HasTopic = FALSE; bool HasTopic = FALSE;
bool HasMedium = FALSE; bool HasMedium = FALSE;
for(int i = 0; i < UniqueCategories; ++i) for(int i = 0; i < UniqueTopics; ++i)
{ {
if(CategoriesArray[i].IsMedium) if(!HasTopic)
{ {
if(!HasMedium) CopyStringToBuffer(&FilterMenu,
{
CopyStringToBuffer(&FilterMedia,
" <div class=\"filter_media\">\n"
" <div class=\"filter_title\">Media</div>\n");
HasMedium = TRUE;
}
int j;
for(j = 0; j < ArrayCount(CategoryMedium); ++j)
{
if(!StringsDiffer(CategoriesArray[i].Category, CategoryMedium[j][0]))
{
break;
}
}
CopyStringToBuffer(&FilterMedia,
" <div class=\"filter_content %s\">\n"
" <span class=\"icon\">%s</span><span class=\"text\">%s</span>\n"
" </div>\n",
CategoriesArray[i].Category,
CategoryMedium[j][1],
CategoryMedium[j][2]
);
/*
</div>
*/
}
else
{
if(!HasTopic)
{
CopyStringToBuffer(&FilterMenu,
" <div class=\"filter_topics\">\n" " <div class=\"filter_topics\">\n"
" <div class=\"filter_title\">Topics</div>\n"); " <div class=\"filter_title\">Topics</div>\n");
HasTopic = TRUE; HasTopic = TRUE;
} }
CopyStringToBuffer(&FilterTopics, CopyStringToBuffer(&FilterTopics,
" <div class=\"filter_content %s\">\n" " <div class=\"filter_content %s\">\n"
" <span class=\"icon category %s\"></span><span class=\"text\">%s</span>\n" " <span class=\"icon category %s\"></span><span class=\"text\">%s</span>\n"
" </div>\n", " </div>\n",
CategoriesArray[i].Category, TopicsArray[i].Marker,
CategoriesArray[i].Category, TopicsArray[i].Marker,
CategoriesArray[i].Category); TopicsArray[i].Marker);
}
for(int i = 0; i < UniqueMedia; ++i)
{
if(!HasMedium)
{
CopyStringToBuffer(&FilterMedia,
" <div class=\"filter_media\">\n"
" <div class=\"filter_title\">Media</div>\n");
HasMedium = TRUE;
} }
int j;
for(j = 0; j < ArrayCount(CategoryMedium); ++j)
{
if(!StringsDiffer(MediaArray[i].Marker, CategoryMedium[j][0]))
{
break;
}
}
CopyStringToBuffer(&FilterMedia,
" <div class=\"filter_content %s\">\n"
" <span class=\"icon\">%s</span><span class=\"text\">%s</span>\n"
" </div>\n",
MediaArray[i].Marker,
CategoryMedium[j][1],
CategoryMedium[j][2]
);
} }
if(HasTopic) if(HasTopic)
@ -1561,6 +1602,7 @@ HMML.metadata.annotator);
"<html>\n" "<html>\n"
" <head>\n" " <head>\n"
" <meta charset=\"UTF-8\">\n" " <meta charset=\"UTF-8\">\n"
" <title>%s</title>\n" // TODO(matt): Add the name of the project
"\n" "\n"
" <!-- Load the player -->\n" " <!-- Load the player -->\n"
" <script type=\"text/javascript\" src=\"player.js\"></script>\n" " <script type=\"text/javascript\" src=\"player.js\"></script>\n"
@ -1568,7 +1610,9 @@ HMML.metadata.annotator);
" <link rel=\"stylesheet\" type=\"text/css\" href=\"%s.css\">\n" " <link rel=\"stylesheet\" type=\"text/css\" href=\"%s.css\">\n"
" <link rel=\"stylesheet\" type=\"text/css\" href=\"topics.css\">\n" " <link rel=\"stylesheet\" type=\"text/css\" href=\"topics.css\">\n"
" </head>\n" " </head>\n"
" <body>\n", HMML.metadata.project); " <body>\n",
HMML.metadata.title,
HMML.metadata.project);
//NOTE(matt): Here is where we do all our CopyBuffer() calls //NOTE(matt): Here is where we do all our CopyBuffer() calls
CopyBuffer(&Master, &Title); CopyBuffer(&Master, &Title);