2016-11-03 21:37:29 +00:00
/*
* Mr . 4 th Dimention - Allen Webster
*
* 25.02 .2016
*
* File editing view for 4 coder
*
*/
// TOP
// Enriched Text
struct Enriched_Text {
2016-11-28 19:13:53 +00:00
String source ;
2016-11-03 21:37:29 +00:00
} ;
2017-07-10 14:51:19 +00:00
internal Enriched_Text
load_enriched_text ( char * directory , char * filename ) {
2016-11-03 21:37:29 +00:00
Enriched_Text result = { 0 } ;
char space [ 256 ] ;
String fname = make_fixed_width_string ( space ) ;
2017-07-10 15:56:57 +00:00
append ( & fname , directory ) ;
append ( & fname , " / " ) ;
append ( & fname , filename ) ;
2016-11-03 21:37:29 +00:00
terminate_with_null ( & fname ) ;
2016-11-28 19:13:53 +00:00
result . source = file_dump ( fname . str ) ;
2016-11-03 21:37:29 +00:00
return ( result ) ;
2016-11-28 19:13:53 +00:00
}
2016-11-03 21:37:29 +00:00
// Document Declaration
enum {
Doc_Root ,
Doc_Section ,
Doc_Todo ,
2017-07-14 23:34:24 +00:00
Doc_Include ,
Doc_DocList ,
Doc_DocFull ,
Doc_TableOfContents ,
Doc_PlainOldText ,
2017-07-13 21:41:44 +00:00
Doc_Version ,
Doc_BeginStyle ,
Doc_EndStyle ,
2017-07-15 01:07:00 +00:00
Doc_DocumentLink ,
2017-07-14 23:34:24 +00:00
Doc_BeginLink ,
Doc_EndLink ,
Doc_Image ,
Doc_Video ,
Doc_BeginParagraph ,
Doc_EndParagraph ,
Doc_BeginSection ,
Doc_EndSection ,
Doc_BeginList ,
Doc_EndList ,
Doc_BeginItem ,
Doc_EndItem ,
2017-07-13 05:02:21 +00:00
//
Doc_COUNT ,
2016-11-03 21:37:29 +00:00
} ;
2016-11-24 06:02:18 +00:00
struct Alternate_Name {
2016-11-10 03:18:22 +00:00
String macro ;
String public_name ;
2016-11-24 06:02:18 +00:00
} ;
2016-11-10 03:18:22 +00:00
2016-11-24 06:02:18 +00:00
struct Alternate_Names_Array {
2016-11-10 03:18:22 +00:00
Alternate_Name * names ;
2016-11-24 06:02:18 +00:00
} ;
2016-11-10 03:18:22 +00:00
enum {
AltName_Standard ,
AltName_Macro ,
AltName_Public_Name ,
} ;
2016-11-03 21:37:29 +00:00
struct Document_Item {
Document_Item * next ;
Document_Item * parent ;
2017-01-07 02:59:55 +00:00
i32 type ;
2016-11-03 21:37:29 +00:00
union {
struct {
Document_Item * first_child ;
Document_Item * last_child ;
2016-11-28 19:13:53 +00:00
String name ;
2016-11-03 21:37:29 +00:00
String id ;
2017-01-07 02:59:55 +00:00
i32 show_title ;
2016-11-28 19:13:53 +00:00
} section ;
struct {
Meta_Unit * unit ;
Alternate_Names_Array * alt_names ;
2017-01-07 02:59:55 +00:00
i32 alt_name_type ;
2016-11-28 19:13:53 +00:00
} unit_elements ;
struct {
2017-07-13 21:41:44 +00:00
String string ;
2017-07-14 23:34:24 +00:00
String string2 ;
2017-07-13 21:41:44 +00:00
} string ;
2017-07-13 05:02:21 +00:00
struct {
Enriched_Text * text ;
} enriched_text ;
2016-11-28 19:13:53 +00:00
} ;
2016-11-03 21:37:29 +00:00
} ;
2017-07-10 14:51:19 +00:00
global Document_Item null_document_item = { 0 } ;
2016-11-03 21:37:29 +00:00
2016-11-28 19:13:53 +00:00
enum {
ItemType_Document ,
ItemType_Image ,
2016-12-08 17:16:50 +00:00
ItemType_GenericFile ,
2016-11-28 19:13:53 +00:00
// never below this
ItemType_COUNT ,
} ;
2016-12-08 17:16:50 +00:00
struct Basic_Node {
Basic_Node * next ;
} ;
# define NodeGetData(node, T) ((T*) ((node)+1))
struct Basic_List {
Basic_Node * head ;
Basic_Node * tail ;
} ;
2016-11-28 19:13:53 +00:00
struct Abstract_Item {
2017-01-07 02:59:55 +00:00
i32 item_type ;
2016-11-28 19:13:53 +00:00
char * name ;
2016-11-03 21:37:29 +00:00
// Document value members
Document_Item * root_item ;
2016-11-28 19:13:53 +00:00
// TODO(allen): make these external
2016-11-03 21:37:29 +00:00
// Document building members
Document_Item * section_stack [ 16 ] ;
2017-01-07 02:59:55 +00:00
i32 section_top ;
2016-11-28 19:13:53 +00:00
// Image value members
char * source_file ;
2016-12-08 17:16:50 +00:00
char * extension ;
2016-11-28 19:13:53 +00:00
float w_h_ratio ;
float h_w_ratio ;
2016-12-08 17:16:50 +00:00
Basic_List img_instantiations ;
2016-11-28 19:13:53 +00:00
} ;
2017-07-10 14:51:19 +00:00
global Abstract_Item null_abstract_item = { 0 } ;
2016-11-28 19:13:53 +00:00
2016-12-08 17:16:50 +00:00
struct Image_Instantiation {
2017-01-07 02:59:55 +00:00
i32 w , h ;
2016-11-24 06:02:18 +00:00
} ;
struct Document_System {
2016-11-28 19:13:53 +00:00
Basic_List doc_list ;
Basic_List img_list ;
2016-12-08 17:16:50 +00:00
Basic_List file_list ;
2016-11-24 06:02:18 +00:00
} ;
2017-07-10 14:51:19 +00:00
internal Document_System
create_document_system ( ) {
2016-11-24 06:02:18 +00:00
Document_System system = { 0 } ;
return ( system ) ;
}
2017-07-10 14:51:19 +00:00
internal void *
push_item_on_list ( Basic_List * list , i32 item_size ) {
2017-01-07 02:59:55 +00:00
i32 mem_size = item_size + sizeof ( Basic_Node ) ;
2017-07-10 14:51:19 +00:00
void * mem = fm__push ( mem_size ) ;
Assert ( mem ! = 0 ) ;
2016-11-28 19:13:53 +00:00
memset ( mem , 0 , mem_size ) ;
2016-11-24 06:02:18 +00:00
2016-11-28 19:13:53 +00:00
Basic_Node * node = ( Basic_Node * ) mem ;
if ( list - > head = = 0 ) {
list - > head = node ;
list - > tail = node ;
}
else {
list - > tail - > next = node ;
list - > tail = node ;
2016-11-24 06:02:18 +00:00
}
2016-11-28 19:13:53 +00:00
void * result = ( node + 1 ) ;
return ( result ) ;
}
2017-07-10 14:51:19 +00:00
internal Abstract_Item *
2016-11-28 19:13:53 +00:00
get_item_by_name ( Basic_List list , String name ) {
Abstract_Item * result = 0 ;
for ( Basic_Node * node = list . head ;
node ! = 0 ;
node = node - > next ) {
Abstract_Item * item = NodeGetData ( node , Abstract_Item ) ;
if ( match ( item - > name , name ) ) {
result = item ;
break ;
2016-11-24 06:02:18 +00:00
}
}
return ( result ) ;
}
2017-07-10 14:51:19 +00:00
internal Abstract_Item *
2016-11-28 19:13:53 +00:00
get_item_by_name ( Basic_List list , char * name ) {
Abstract_Item * result = 0 ;
2016-11-24 06:02:18 +00:00
2016-11-28 19:13:53 +00:00
for ( Basic_Node * node = list . head ;
2016-11-24 06:02:18 +00:00
node ! = 0 ;
node = node - > next ) {
2016-11-28 19:13:53 +00:00
Abstract_Item * item = NodeGetData ( node , Abstract_Item ) ;
if ( match ( item - > name , name ) ) {
result = item ;
2016-11-24 06:02:18 +00:00
break ;
}
}
return ( result ) ;
}
2017-07-10 14:51:19 +00:00
internal Image_Instantiation *
2017-01-07 02:59:55 +00:00
get_image_instantiation ( Basic_List list , i32 w , i32 h ) {
2016-12-08 17:16:50 +00:00
Image_Instantiation * result = 0 ;
for ( Basic_Node * node = list . head ;
node ! = 0 ;
node = node - > next ) {
Image_Instantiation * instantiation = NodeGetData ( node , Image_Instantiation ) ;
if ( instantiation - > w = = w & & instantiation - > h = = h ) {
result = instantiation ;
break ;
}
}
return ( result ) ;
}
2017-07-10 14:51:19 +00:00
internal Abstract_Item *
create_item ( Basic_List * list , char * name ) {
2016-11-28 19:13:53 +00:00
Abstract_Item * lookup = get_item_by_name ( * list , name ) ;
Abstract_Item * result = 0 ;
2016-12-08 17:16:50 +00:00
if ( lookup = = 0 ) {
2017-07-10 14:51:19 +00:00
result = ( Abstract_Item * ) push_item_on_list ( list , sizeof ( Abstract_Item ) ) ;
2016-11-28 19:13:53 +00:00
}
return ( result ) ;
}
2017-07-10 14:51:19 +00:00
internal void
add_image_instantiation ( Basic_List * list , i32 w , i32 h ) {
Image_Instantiation * instantiation = ( Image_Instantiation * ) push_item_on_list ( list , sizeof ( Image_Instantiation ) ) ;
2016-12-08 17:16:50 +00:00
instantiation - > w = w ;
instantiation - > h = h ;
}
2017-07-10 14:51:19 +00:00
internal void
set_section_name ( Document_Item * item , char * name , i32 show_title ) {
2017-01-07 02:59:55 +00:00
i32 name_len = str_size ( name ) ;
2017-07-10 14:51:19 +00:00
item - > section . name = make_string_cap ( fm_push_array ( char , name_len + 1 ) , 0 , name_len + 1 ) ;
fm_align ( ) ;
2017-07-10 15:56:57 +00:00
append ( & item - > section . name , name ) ;
2016-11-28 19:13:53 +00:00
item - > section . show_title = show_title ;
2016-11-03 21:37:29 +00:00
}
2017-07-10 14:51:19 +00:00
internal void
set_section_id ( Document_Item * item , char * id ) {
2017-01-07 02:59:55 +00:00
i32 id_len = str_size ( id ) ;
2017-07-10 14:51:19 +00:00
item - > section . id = make_string_cap ( fm_push_array ( char , id_len + 1 ) , 0 , id_len + 1 ) ;
fm_align ( ) ;
2017-07-10 15:56:57 +00:00
append ( & item - > section . id , id ) ;
2016-11-03 21:37:29 +00:00
}
2017-07-10 14:51:19 +00:00
internal void
begin_document_description ( Abstract_Item * doc , char * title , i32 show_title ) {
2016-11-28 19:13:53 +00:00
* doc = null_abstract_item ;
doc - > item_type = ItemType_Document ;
2016-11-03 21:37:29 +00:00
2017-07-10 14:51:19 +00:00
doc - > root_item = fm_push_array ( Document_Item , 1 ) ;
2016-11-03 21:37:29 +00:00
* doc - > root_item = null_document_item ;
doc - > section_stack [ doc - > section_top ] = doc - > root_item ;
doc - > root_item - > type = Doc_Root ;
2017-07-10 14:51:19 +00:00
set_section_name ( doc - > root_item , title , show_title ) ;
2016-11-03 21:37:29 +00:00
}
2017-07-10 14:51:19 +00:00
internal Abstract_Item *
2016-12-08 17:16:50 +00:00
add_generic_file ( Document_System * system , char * source_file , char * extension , char * name ) {
2017-07-10 14:51:19 +00:00
Abstract_Item * item = create_item ( & system - > file_list , name ) ;
2016-12-08 17:16:50 +00:00
if ( item ) {
item - > item_type = ItemType_GenericFile ;
item - > extension = extension ;
item - > source_file = source_file ;
item - > name = name ;
}
return ( item ) ;
}
2017-07-10 14:51:19 +00:00
internal Abstract_Item *
2016-12-08 17:16:50 +00:00
add_image_description ( Document_System * system , char * source_file , char * extension , char * name ) {
2017-07-10 14:51:19 +00:00
Abstract_Item * item = create_item ( & system - > img_list , name ) ;
if ( item ! = 0 ) {
2016-11-28 19:13:53 +00:00
item - > item_type = ItemType_Image ;
2016-12-08 17:16:50 +00:00
item - > extension = extension ;
2016-11-28 19:13:53 +00:00
item - > source_file = source_file ;
item - > name = name ;
2017-01-07 02:59:55 +00:00
i32 w = 0 , h = 0 , comp = 0 ;
i32 stbi_r = stbi_info ( source_file , & w , & h , & comp ) ;
2016-12-08 17:16:50 +00:00
if ( ! stbi_r ) {
2017-07-13 05:02:21 +00:00
fprintf ( stdout , " Did not find file %s \n " , source_file ) ;
2016-12-08 17:16:50 +00:00
item - > w_h_ratio = 1.f ;
item - > h_w_ratio = 1.f ;
}
else {
2017-01-07 02:59:55 +00:00
item - > w_h_ratio = ( ( float ) w / ( float ) h ) ;
item - > h_w_ratio = ( ( float ) h / ( float ) w ) ;
2016-12-08 17:16:50 +00:00
}
2016-11-28 19:13:53 +00:00
}
return ( item ) ;
2016-11-22 18:26:58 +00:00
}
2017-07-10 14:51:19 +00:00
internal Abstract_Item *
2017-01-07 02:59:55 +00:00
begin_document_description ( Document_System * system , char * title , char * name , i32 show_title ) {
2017-07-10 14:51:19 +00:00
Abstract_Item * item = create_item ( & system - > doc_list , name ) ;
2016-11-28 19:13:53 +00:00
if ( item ) {
2017-07-10 14:51:19 +00:00
begin_document_description ( item , title , show_title ) ;
2016-11-28 19:13:53 +00:00
item - > name = name ;
2016-11-24 06:02:18 +00:00
}
2016-11-28 19:13:53 +00:00
return ( item ) ;
2016-11-24 06:02:18 +00:00
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-28 19:13:53 +00:00
end_document_description ( Abstract_Item * item ) {
Assert ( item - > section_top = = 0 ) ;
2016-11-03 21:37:29 +00:00
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-03 21:37:29 +00:00
append_child ( Document_Item * parent , Document_Item * item ) {
Assert ( parent - > type = = Doc_Root | | parent - > type = = Doc_Section ) ;
if ( parent - > section . last_child = = 0 ) {
parent - > section . first_child = item ;
}
else {
parent - > section . last_child - > next = item ;
}
parent - > section . last_child = item ;
item - > parent = parent ;
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-28 19:13:53 +00:00
begin_section ( Abstract_Item * item , char * title , char * id ) {
2017-07-13 05:02:21 +00:00
Assert ( item - > section_top + 1 < ArrayCount ( item - > section_stack ) ) ;
2016-11-03 21:37:29 +00:00
2016-11-28 19:13:53 +00:00
Document_Item * parent = item - > section_stack [ item - > section_top ] ;
2017-07-10 14:51:19 +00:00
Document_Item * section = fm_push_array ( Document_Item , 1 ) ;
2016-11-03 21:37:29 +00:00
* section = null_document_item ;
2016-11-28 19:13:53 +00:00
item - > section_stack [ + + item - > section_top ] = section ;
2016-11-03 21:37:29 +00:00
section - > type = Doc_Section ;
2017-07-10 14:51:19 +00:00
set_section_name ( section , title , 1 ) ;
if ( id ! = 0 ) {
set_section_id ( section , id ) ;
2016-11-03 21:37:29 +00:00
}
append_child ( parent , section ) ;
2016-11-28 19:13:53 +00:00
}
2016-11-03 21:37:29 +00:00
2017-07-10 14:51:19 +00:00
internal void
2016-11-28 19:13:53 +00:00
end_section ( Abstract_Item * doc ) {
2016-11-03 21:37:29 +00:00
Assert ( doc - > section_top > 0 ) ;
- - doc - > section_top ;
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-28 19:13:53 +00:00
add_todo ( Abstract_Item * doc ) {
2017-07-13 05:02:21 +00:00
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
2016-11-03 21:37:29 +00:00
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
2017-07-10 14:51:19 +00:00
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
2016-11-03 21:37:29 +00:00
* item = null_document_item ;
item - > type = Doc_Todo ;
append_child ( parent , item ) ;
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-28 19:13:53 +00:00
add_element_list ( Abstract_Item * doc , Meta_Unit * unit ) {
2017-07-13 05:02:21 +00:00
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
2016-11-03 21:37:29 +00:00
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
2017-07-10 14:51:19 +00:00
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
2016-11-03 21:37:29 +00:00
* item = null_document_item ;
2017-07-14 23:34:24 +00:00
item - > type = Doc_DocList ;
2016-11-03 21:37:29 +00:00
item - > unit_elements . unit = unit ;
append_child ( parent , item ) ;
}
2017-07-10 14:51:19 +00:00
internal void
2017-01-07 02:59:55 +00:00
add_element_list ( Abstract_Item * doc , Meta_Unit * unit , Alternate_Names_Array * alt_names , i32 alt_name_type ) {
2017-07-13 05:02:21 +00:00
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
2016-11-10 03:18:22 +00:00
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
2017-07-10 14:51:19 +00:00
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
2016-11-10 03:18:22 +00:00
* item = null_document_item ;
2017-07-14 23:34:24 +00:00
item - > type = Doc_DocList ;
2016-11-10 03:18:22 +00:00
item - > unit_elements . unit = unit ;
item - > unit_elements . alt_names = alt_names ;
item - > unit_elements . alt_name_type = alt_name_type ;
append_child ( parent , item ) ;
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-28 19:13:53 +00:00
add_full_elements ( Abstract_Item * doc , Meta_Unit * unit ) {
2017-07-13 05:02:21 +00:00
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
2016-11-03 21:37:29 +00:00
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
2017-07-10 14:51:19 +00:00
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
2016-11-03 21:37:29 +00:00
* item = null_document_item ;
2017-07-14 23:34:24 +00:00
item - > type = Doc_DocFull ;
2016-11-03 21:37:29 +00:00
item - > unit_elements . unit = unit ;
append_child ( parent , item ) ;
}
2017-07-10 14:51:19 +00:00
internal void
2017-01-07 02:59:55 +00:00
add_full_elements ( Abstract_Item * doc , Meta_Unit * unit , Alternate_Names_Array * alt_names , i32 alt_name_type ) {
2017-07-13 05:02:21 +00:00
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
2016-11-10 03:18:22 +00:00
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
2017-07-10 14:51:19 +00:00
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
2016-11-10 03:18:22 +00:00
* item = null_document_item ;
2017-07-14 23:34:24 +00:00
item - > type = Doc_DocFull ;
2016-11-10 03:18:22 +00:00
item - > unit_elements . unit = unit ;
item - > unit_elements . alt_names = alt_names ;
item - > unit_elements . alt_name_type = alt_name_type ;
append_child ( parent , item ) ;
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-28 19:13:53 +00:00
add_table_of_contents ( Abstract_Item * doc ) {
2017-07-13 05:02:21 +00:00
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
2016-11-03 21:37:29 +00:00
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
2017-07-10 14:51:19 +00:00
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
2016-11-03 21:37:29 +00:00
* item = null_document_item ;
2017-07-14 23:34:24 +00:00
item - > type = Doc_TableOfContents ;
2016-11-03 21:37:29 +00:00
append_child ( parent , item ) ;
}
2017-07-13 05:02:21 +00:00
internal void
add_plain_old_text ( Abstract_Item * doc , String text ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
2017-07-14 23:34:24 +00:00
item - > type = Doc_PlainOldText ;
2017-07-13 21:41:44 +00:00
item - > string . string = str_alloc ( text . size ) ;
copy ( & item - > string . string , text ) ;
2017-07-13 05:02:21 +00:00
append_child ( parent , item ) ;
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-28 19:13:53 +00:00
add_enriched_text ( Abstract_Item * doc , Enriched_Text * text ) {
2017-07-13 05:02:21 +00:00
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
2016-11-03 21:37:29 +00:00
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
2017-07-10 14:51:19 +00:00
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
2016-11-03 21:37:29 +00:00
* item = null_document_item ;
2017-07-14 23:34:24 +00:00
item - > type = Doc_Include ;
2017-07-13 05:02:21 +00:00
item - > enriched_text . text = text ;
2016-11-03 21:37:29 +00:00
append_child ( parent , item ) ;
}
2017-07-13 21:41:44 +00:00
internal void
add_version ( Abstract_Item * doc ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_Version ;
append_child ( parent , item ) ;
}
internal void
add_begin_style ( Abstract_Item * doc , String text ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_BeginStyle ;
item - > string . string = str_alloc ( text . size ) ;
copy ( & item - > string . string , text ) ;
append_child ( parent , item ) ;
}
internal void
add_end_style ( Abstract_Item * doc ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
2017-07-14 23:34:24 +00:00
item - > type = Doc_EndStyle ;
append_child ( parent , item ) ;
}
2017-07-15 01:07:00 +00:00
internal void
add_document_link ( Abstract_Item * doc , String text ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_DocumentLink ;
item - > string . string = str_alloc ( text . size ) ;
copy ( & item - > string . string , text ) ;
append_child ( parent , item ) ;
}
2017-07-14 23:34:24 +00:00
internal void
add_begin_link ( Abstract_Item * doc , String text ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_BeginLink ;
item - > string . string = str_alloc ( text . size ) ;
copy ( & item - > string . string , text ) ;
append_child ( parent , item ) ;
}
internal void
add_end_link ( Abstract_Item * doc ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_EndLink ;
append_child ( parent , item ) ;
}
internal void
add_image ( Abstract_Item * doc , String text , String extra_text ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_Image ;
item - > string . string = str_alloc ( text . size ) ;
copy ( & item - > string . string , text ) ;
if ( extra_text . size > 0 ) {
item - > string . string2 = str_alloc ( extra_text . size ) ;
copy ( & item - > string . string2 , extra_text ) ;
}
append_child ( parent , item ) ;
}
internal void
add_video ( Abstract_Item * doc , String text ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_Video ;
item - > string . string = str_alloc ( text . size ) ;
copy ( & item - > string . string , text ) ;
append_child ( parent , item ) ;
}
internal void
add_begin_paragraph ( Abstract_Item * doc ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_BeginParagraph ;
append_child ( parent , item ) ;
}
internal void
add_end_paragraph ( Abstract_Item * doc ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_EndParagraph ;
append_child ( parent , item ) ;
}
internal void
add_begin_section ( Abstract_Item * doc , String text ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_BeginSection ;
item - > string . string = str_alloc ( text . size ) ;
copy ( & item - > string . string , text ) ;
append_child ( parent , item ) ;
}
internal void
add_end_section ( Abstract_Item * doc ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_EndSection ;
append_child ( parent , item ) ;
}
internal void
add_begin_list ( Abstract_Item * doc ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_BeginList ;
append_child ( parent , item ) ;
}
internal void
add_end_list ( Abstract_Item * doc ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_EndList ;
append_child ( parent , item ) ;
}
internal void
add_begin_item ( Abstract_Item * doc ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_BeginItem ;
append_child ( parent , item ) ;
}
internal void
add_end_item ( Abstract_Item * doc ) {
Assert ( doc - > section_top + 1 < ArrayCount ( doc - > section_stack ) ) ;
Document_Item * parent = doc - > section_stack [ doc - > section_top ] ;
Document_Item * item = fm_push_array ( Document_Item , 1 ) ;
* item = null_document_item ;
item - > type = Doc_EndItem ;
2017-07-13 21:41:44 +00:00
append_child ( parent , item ) ;
}
2017-07-15 01:07:00 +00:00
// Document Generation from Enriched Text
enum Command_Types {
Cmd_BackSlash ,
Cmd_BeginStyle ,
Cmd_EndStyle ,
Cmd_DocumentLink ,
Cmd_BeginList ,
Cmd_EndList ,
Cmd_BeginItem ,
Cmd_EndItem ,
Cmd_BeginLink ,
Cmd_EndLink ,
Cmd_Image ,
Cmd_Video ,
Cmd_Section ,
Cmd_EndSection ,
Cmd_Version ,
// never below this
Cmd_COUNT ,
} ;
global b32 did_enriched_commands = false ;
global String enriched_commands_global_array [ Cmd_COUNT ] ;
internal String *
get_enriched_commands ( ) {
if ( ! did_enriched_commands ) {
did_enriched_commands = true ;
enriched_commands_global_array [ Cmd_BackSlash ] = make_lit_string ( " \\ " ) ;
enriched_commands_global_array [ Cmd_BeginStyle ] = make_lit_string ( " BEGIN_STYLE " ) ;
enriched_commands_global_array [ Cmd_EndStyle ] = make_lit_string ( " END_STYLE " ) ;
enriched_commands_global_array [ Cmd_DocumentLink ] = make_lit_string ( " DOC_LINK " ) ;
enriched_commands_global_array [ Cmd_BeginList ] = make_lit_string ( " BEGIN_LIST " ) ;
enriched_commands_global_array [ Cmd_EndList ] = make_lit_string ( " END_LIST " ) ;
enriched_commands_global_array [ Cmd_BeginItem ] = make_lit_string ( " BEGIN_ITEM " ) ;
enriched_commands_global_array [ Cmd_EndItem ] = make_lit_string ( " END_ITEM " ) ;
enriched_commands_global_array [ Cmd_BeginLink ] = make_lit_string ( " BEGIN_LINK " ) ;
enriched_commands_global_array [ Cmd_EndLink ] = make_lit_string ( " END_LINK " ) ;
enriched_commands_global_array [ Cmd_Image ] = make_lit_string ( " IMAGE " ) ;
enriched_commands_global_array [ Cmd_Video ] = make_lit_string ( " VIDEO " ) ;
enriched_commands_global_array [ Cmd_Section ] = make_lit_string ( " SECTION " ) ;
enriched_commands_global_array [ Cmd_EndSection ] = make_lit_string ( " END_SECTION " ) ;
enriched_commands_global_array [ Cmd_Version ] = make_lit_string ( " VERSION " ) ;
}
return ( enriched_commands_global_array ) ;
}
internal u32
get_enriched_commands_count ( ) {
return ( ArrayCount ( enriched_commands_global_array ) ) ;
}
internal b32
extract_command_body ( String l , i32 * i_in_out , i32 * body_start_out , i32 * body_end_out ) {
b32 result = false ;
i32 i = * i_in_out ;
for ( ; i < l . size ; + + i ) {
if ( ! char_is_whitespace ( l . str [ i ] ) ) {
break ;
}
}
i32 body_start = 0 , body_end = 0 ;
if ( l . str [ i ] = = ' { ' ) {
body_start = i + 1 ;
for ( + + i ; i < l . size ; + + i ) {
if ( l . str [ i ] = = ' } ' ) {
result = true ;
body_end = i ;
+ + i ;
break ;
}
}
}
if ( result ) {
* i_in_out = i ;
* body_start_out = body_start ;
* body_end_out = body_end ;
}
return ( result ) ;
}
internal b32
extract_command_body ( String l , i32 * i_in_out , String * body_text_out ) {
i32 body_start = 0 , body_end = 0 ;
b32 has_body = extract_command_body ( l , i_in_out , & body_start , & body_end ) ;
if ( has_body ) {
String body_text = substr ( l , body_start , body_end - body_start ) ;
body_text = skip_chop_whitespace ( body_text ) ;
* body_text_out = body_text ;
}
return ( has_body ) ;
}
internal Abstract_Item *
make_document_from_text ( Document_System * doc_system , char * title , char * name , Enriched_Text * text ) {
String source = text - > source ;
Abstract_Item * doc = begin_document_description ( doc_system , title , name , 0 ) ;
for ( String line = get_first_double_line ( source ) ;
line . str ;
line = get_next_double_line ( source , line ) ) {
String l = skip_chop_whitespace ( line ) ;
add_begin_paragraph ( doc ) ;
i32 start = 0 , i = 0 ;
for ( ; i < l . size ; + + i ) {
char ch = l . str [ i ] ;
if ( ch = = ' \\ ' ) {
add_plain_old_text ( doc , substr ( l , start , i - start ) ) ;
i32 command_start = i + 1 ;
i32 command_end = command_start ;
for ( ; command_end < l . size ; + + command_end ) {
if ( ! char_is_alpha_numeric ( l . str [ command_end ] ) ) {
break ;
}
}
if ( command_end = = command_start ) {
if ( command_end < l . size & & l . str [ command_end ] = = ' \\ ' ) {
+ + command_end ;
}
}
String command_string = substr ( l , command_start , command_end - command_start ) ;
String * enriched_commands = get_enriched_commands ( ) ;
u32 enriched_commands_count = get_enriched_commands_count ( ) ;
i = command_end ;
i32 match_index = 0 ;
if ( ! string_set_match ( enriched_commands , enriched_commands_count , command_string , & match_index ) ) {
match_index = - 1 ;
}
switch ( match_index ) {
case Cmd_BackSlash :
{
add_plain_old_text ( doc , make_lit_string ( " \\ " ) ) ;
} break ;
case Cmd_BeginStyle :
{
String body_text = { 0 } ;
b32 has_body = extract_command_body ( l , & i , & body_text ) ;
if ( has_body ) {
add_begin_style ( doc , body_text ) ;
}
else {
// TODO(allen):
}
} break ;
case Cmd_EndStyle :
{
add_end_style ( doc ) ;
} break ;
// TODO(allen): upgrade this bs
case Cmd_DocumentLink :
{
String body_text = { 0 } ;
b32 has_body = extract_command_body ( l , & i , & body_text ) ;
if ( has_body ) {
add_document_link ( doc , body_text ) ;
}
else {
// TODO(allen):
}
} break ;
case Cmd_BeginList :
{
add_begin_list ( doc ) ;
} break ;
case Cmd_EndList :
{
add_end_list ( doc ) ;
} break ;
case Cmd_BeginItem :
{
add_begin_item ( doc ) ;
} break ;
case Cmd_EndItem :
{
add_end_item ( doc ) ;
} break ;
case Cmd_BeginLink :
{
String body_text = { 0 } ;
b32 has_body = extract_command_body ( l , & i , & body_text ) ;
if ( has_body ) {
add_begin_link ( doc , body_text ) ;
}
else {
// TODO(allen):
}
} break ;
case Cmd_EndLink :
{
add_end_link ( doc ) ;
} break ;
case Cmd_Image :
{
String body_text = { 0 } ;
b32 has_body = extract_command_body ( l , & i , & body_text ) ;
if ( has_body ) {
String size_parameter = { 0 } ;
extract_command_body ( l , & i , & size_parameter ) ;
add_image ( doc , body_text , size_parameter ) ;
}
else {
// TODO(allen):
}
} break ;
case Cmd_Video :
{
String body_text = { 0 } ;
b32 has_body = extract_command_body ( l , & i , & body_text ) ;
if ( has_body ) {
add_video ( doc , body_text ) ;
}
else {
// TODO(allen):
}
} break ;
case Cmd_Section :
{
String body_text = { 0 } ;
b32 has_body = extract_command_body ( l , & i , & body_text ) ;
if ( has_body ) {
String extra_text = { 0 } ;
extract_command_body ( l , & i , & extra_text ) ;
add_begin_section ( doc , body_text ) ;
}
else {
// TODO(allen):
}
} break ;
case Cmd_EndSection :
{
add_end_section ( doc ) ;
} break ;
case Cmd_Version :
{
add_version ( doc ) ;
} break ;
default :
{
// TODO(allen):
} break ;
}
}
}
add_end_paragraph ( doc ) ;
}
end_document_description ( doc ) ;
return ( doc ) ;
}
2016-11-24 06:02:18 +00:00
// HTML Document Generation
2016-11-03 21:37:29 +00:00
# define HTML_BACK_COLOR "#FAFAFA"
# define HTML_TEXT_COLOR "#0D0D0D"
# define HTML_CODE_BACK "#DFDFDF"
# define HTML_EXAMPLE_BACK "#EFEFDF"
# define HTML_POP_COLOR_1 "#309030"
# define HTML_POP_BACK_1 "#E0FFD0"
# define HTML_VISITED_LINK "#A0C050"
# define HTML_POP_COLOR_2 "#005000"
# define HTML_CODE_STYLE "font-family: \"Courier New\", Courier, monospace; text-align: left;"
# define HTML_CODE_BLOCK_STYLE(back) \
" margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; " \
" background: " back " ; padding: 0.25em; "
# define HTML_DESCRIPT_SECTION_STYLE HTML_CODE_BLOCK_STYLE(HTML_CODE_BACK)
# define HTML_EXAMPLE_CODE_STYLE HTML_CODE_BLOCK_STYLE(HTML_EXAMPLE_BACK)
# define HTML_DOC_HEAD_OPEN "<div style='margin-top: 3mm; margin-bottom: 3mm; color: "HTML_POP_COLOR_1";'><b><i>"
# define HTML_DOC_HEAD_CLOSE "< / i>< / b>< / div>"
# define HTML_DOC_ITEM_HEAD_STYLE "font-weight: 600;"
# define HTML_DOC_ITEM_HEAD_INL_OPEN "<span style='"HTML_DOC_ITEM_HEAD_STYLE"'>"
# define HTML_DOC_ITEM_HEAD_INL_CLOSE "< / span>"
# define HTML_DOC_ITEM_HEAD_OPEN "<div style='"HTML_DOC_ITEM_HEAD_STYLE"'>"
# define HTML_DOC_ITEM_HEAD_CLOSE "< / div>"
# define HTML_DOC_ITEM_OPEN "<div style='margin-left: 5mm; margin-right: 5mm;'>"
# define HTML_DOC_ITEM_CLOSE "< / div>"
# define HTML_EXAMPLE_CODE_OPEN "<div style='"HTML_CODE_STYLE HTML_EXAMPLE_CODE_STYLE"'>"
# define HTML_EXAMPLE_CODE_CLOSE "< / div>"
struct Section_Counter {
2017-01-07 02:59:55 +00:00
i32 counter [ 16 ] ;
i32 nest_level ;
2017-07-14 23:34:24 +00:00
i32 list_item_counter ;
2016-11-03 21:37:29 +00:00
} ;
2017-07-10 15:56:57 +00:00
internal b32
2017-01-07 02:59:55 +00:00
doc_get_link_string ( Abstract_Item * doc , char * space , i32 capacity ) {
2016-11-24 06:02:18 +00:00
String str = make_string_cap ( space , 0 , capacity ) ;
2017-07-10 15:56:57 +00:00
append ( & str , doc - > name ) ;
append ( & str , " .html " ) ;
b32 result = terminate_with_null ( & str ) ;
2016-11-24 06:02:18 +00:00
return ( result ) ;
}
2017-07-10 15:56:57 +00:00
internal b32
2017-01-07 02:59:55 +00:00
img_get_link_string ( Abstract_Item * img , char * space , i32 capacity , i32 w , i32 h ) {
2016-11-28 19:13:53 +00:00
String str = make_string_cap ( space , 0 , capacity ) ;
2017-07-10 15:56:57 +00:00
append ( & str , img - > name ) ;
2016-12-08 17:16:50 +00:00
2017-07-10 15:56:57 +00:00
append ( & str , " _ " ) ;
2016-12-08 17:16:50 +00:00
append_int_to_str ( & str , w ) ;
2017-07-10 15:56:57 +00:00
append ( & str , " _ " ) ;
2016-12-08 17:16:50 +00:00
append_int_to_str ( & str , h ) ;
2017-07-10 15:56:57 +00:00
append ( & str , " . " ) ;
append ( & str , img - > extension ) ;
b32 result = terminate_with_null ( & str ) ;
2016-11-28 19:13:53 +00:00
return ( result ) ;
}
2017-07-10 14:51:19 +00:00
internal void
2017-01-07 02:59:55 +00:00
append_section_number_reduced ( String * out , Section_Counter * section_counter , i32 reduce ) {
i32 level = section_counter - > nest_level - reduce ;
for ( i32 i = 1 ; i < = level ; + + i ) {
2016-11-22 18:26:58 +00:00
append_int_to_str ( out , section_counter - > counter [ i ] ) ;
2016-11-10 03:18:22 +00:00
if ( i ! = level ) {
2017-07-10 15:56:57 +00:00
append ( out , " . " ) ;
2016-11-03 21:37:29 +00:00
}
}
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-22 18:26:58 +00:00
append_section_number ( String * out , Section_Counter * section_counter ) {
2016-11-10 03:18:22 +00:00
append_section_number_reduced ( out , section_counter , 0 ) ;
}
2017-07-15 01:07:00 +00:00
internal void
report_error_html_missing_body ( String * out , String command_name ) {
2016-11-10 03:18:22 +00:00
# define STR_START "<span style='color:#F00'>! Doc generator error: missing body for "
2017-07-15 01:07:00 +00:00
# define STR_SLOW " !< / span>"
append ( out , STR_START ) ;
append ( out , command_name ) ;
append ( out , STR_SLOW ) ;
fprintf ( stdout , " error: missing body for %.*s \n " , command_name . size , command_name . str ) ;
2017-07-13 05:02:21 +00:00
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-22 18:26:58 +00:00
html_render_section_header ( String * out , String section_name , String section_id , Section_Counter * section_counter ) {
if ( section_counter - > nest_level < = 1 ) {
if ( section_id . size > 0 ) {
2017-07-10 15:56:57 +00:00
append ( out , " \n <h2 id='section_ " ) ;
append ( out , section_id ) ;
append ( out , " '>§ " ) ;
2016-11-22 18:26:58 +00:00
}
else {
2017-07-10 15:56:57 +00:00
append ( out , " \n <h2>§ " ) ;
2016-11-22 18:26:58 +00:00
}
append_section_number ( out , section_counter ) ;
2017-07-10 15:56:57 +00:00
append ( out , " " ) ;
append ( out , section_name ) ;
append ( out , " </h2> " ) ;
2016-11-22 18:26:58 +00:00
}
else {
if ( section_id . size > 0 ) {
2017-07-10 15:56:57 +00:00
append ( out , " <h3 id='section_ " ) ;
append ( out , section_id ) ;
append ( out , " '>§ " ) ;
2016-11-22 18:26:58 +00:00
}
else {
2017-07-10 15:56:57 +00:00
append ( out , " <h3>§ " ) ;
2016-11-22 18:26:58 +00:00
}
append_section_number ( out , section_counter ) ;
2017-07-10 15:56:57 +00:00
append ( out , " " ) ;
append ( out , section_name ) ;
append ( out , " </h3> " ) ;
2016-11-22 18:26:58 +00:00
}
}
2016-11-28 19:13:53 +00:00
# define HTML_WIDTH 800
2017-07-13 05:02:21 +00:00
internal void
output_plain_old_text ( String * out , char * text , u32 length ) {
String l = make_string ( text , length ) ;
u32 start = 0 ;
u32 i = 0 ;
for ( ; i < length ; + + i ) {
char ch = l . str [ i ] ;
switch ( ch ) {
case ' < ' :
{
append ( out , substr ( l , start , i - start ) ) ;
append ( out , " < " ) ;
start = i + 1 ;
} break ;
case ' > ' :
{
append ( out , substr ( l , start , i - start ) ) ;
append ( out , " > " ) ;
start = i + 1 ;
} break ;
}
}
if ( start ! = i ) {
append ( out , substr ( l , start , i - start ) ) ;
}
}
2017-07-13 21:41:44 +00:00
internal void
output_begin_style ( String * out , char * name , u32 length ) {
String l = make_string ( name , length ) ;
if ( match ( l , " code " ) ) {
append ( out , " <span style=' " HTML_CODE_STYLE " '> " ) ;
}
else {
fprintf ( stdout , " error: unrecognized style \n " ) ;
}
}
internal void
output_end_style ( String * out ) {
append ( out , " </span> " ) ;
}
2017-07-15 01:07:00 +00:00
internal void
output_document_link ( String * out , char * name , u32 length ) {
String l = make_string ( name , length ) ;
append ( out , " <a href='# " ) ;
append ( out , l ) ;
append ( out , " _doc'> " ) ;
append ( out , l ) ;
append ( out , " </a> " ) ;
}
2017-07-14 23:34:24 +00:00
internal void
output_begin_link ( Document_System * doc_system , String * out , char * name , u32 length ) {
String l = make_string ( name , length ) ;
append ( out , " <a " ) ;
if ( l . str [ 0 ] = = ' ! ' ) {
append ( out , " target='_blank' " ) ;
l . str + + ;
l . size - - ;
}
append ( out , " href=' " ) ;
if ( match_part_sc ( l , " document: " ) ) {
String doc_name = substr_tail ( l , sizeof ( " document: " ) - 1 ) ;
Abstract_Item * doc_lookup = get_item_by_name ( doc_system - > doc_list , doc_name ) ;
if ( doc_lookup ) {
char space [ 256 ] ;
if ( doc_get_link_string ( doc_lookup , space , sizeof ( space ) ) ) {
append ( out , space ) ;
}
else {
NotImplemented ;
}
}
}
else {
append ( out , l ) ;
}
append ( out , " '> " ) ;
}
internal void
output_end_link ( String * out ) {
append ( out , " </a> " ) ;
}
internal void
output_image ( Document_System * doc_system , String * out , char * name , u32 length , char * name2 , u32 length2 ) {
String l = make_string ( name , length ) ;
String l2 = make_string ( name2 , length2 ) ;
i32 pixel_height = 10 ;
i32 pixel_width = HTML_WIDTH ;
if ( l2 . size > 0 ) {
if ( match_part ( l2 , " width: " ) ) {
String width_string = substr_tail ( l2 , sizeof ( " width: " ) - 1 ) ;
if ( str_is_int ( width_string ) ) {
pixel_width = str_to_int ( width_string ) ;
}
}
}
if ( match_part_sc ( l , " image: " ) ) {
String img_name = substr_tail ( l , sizeof ( " image: " ) - 1 ) ;
Abstract_Item * img_lookup = get_item_by_name ( doc_system - > img_list , img_name ) ;
if ( img_lookup ) {
pixel_height = ceil32 ( pixel_width * img_lookup - > h_w_ratio ) ;
append ( out , " <img src=' " ) ;
char space [ 256 ] ;
if ( img_get_link_string ( img_lookup , space , sizeof ( space ) , pixel_width , pixel_height ) ) {
append ( out , space ) ;
add_image_instantiation ( & img_lookup - > img_instantiations , pixel_width , pixel_height ) ;
}
else {
NotImplemented ;
}
append ( out , " ' style='width: " ) ;
append_int_to_str ( out , pixel_width ) ;
append ( out , " px; height: " ) ;
append_int_to_str ( out , pixel_height ) ;
append ( out , " px;'> " ) ;
}
}
}
internal void
output_video ( String * out , char * name , u32 length ) {
String l = make_string ( name , length ) ;
if ( match_part_sc ( l , " youtube: " ) ) {
i32 pixel_width = HTML_WIDTH ;
i32 pixel_height = ( i32 ) ( pixel_width * 0.5625f ) ;
String youtube_str = substr_tail ( l , sizeof ( " youtube: " ) - 1 ) ;
append ( out , " <iframe width=' " ) ;
append_int_to_str ( out , pixel_width ) ;
append ( out , " ' height=' " ) ;
append_int_to_str ( out , pixel_height ) ;
append ( out , " ' src=' " ) ;
append ( out , youtube_str ) ;
append ( out , " ' allowfullscreen> </iframe> " ) ;
}
else {
append ( out , " <span style='color:#F00'>! Doc generator error: unrecognized video type !</span> " ) ;
fprintf ( stdout , " error: unrecognized video type %.*s \n " , l . size , l . str ) ;
}
}
internal void
output_begin_paragraph ( String * out ) {
append ( out , " <p> " ) ;
}
internal void
output_end_paragraph ( String * out ) {
append ( out , " </p> " ) ;
}
internal void
output_begin_section ( String * out , Section_Counter * section_counter , char * name , u32 length ) {
String l = make_string ( name , length ) ;
html_render_section_header ( out , l , null_string , section_counter ) ;
+ + section_counter - > nest_level ;
section_counter - > list_item_counter = 0 ;
}
internal void
output_end_section ( String * out , Section_Counter * section_counter ) {
if ( section_counter - > nest_level > 0 ) {
- - section_counter - > nest_level ;
+ + section_counter - > counter [ section_counter - > nest_level ] ;
}
else {
append ( out , " <span style='color:#F00'>! Doc generator error: unmatched section end !</span> " ) ;
fprintf ( stdout , " error: unmatched section end \n " ) ;
}
}
internal void
output_begin_list ( String * out ) {
append ( out , " <ul style='margin-top: 5mm; margin-left: 1mm;'> " ) ;
}
internal void
output_end_list ( String * out ) {
append ( out , " </ul> " ) ;
}
internal void
output_begin_item ( String * out , Section_Counter * section_counter ) {
if ( section_counter - > list_item_counter = = 0 ) {
append ( out , " <li style='font-size: 95%; background: #EFEFDF;'> " ) ;
+ + section_counter - > list_item_counter ;
}
else {
append ( out , " <li style='font-size: 95%;'> " ) ;
section_counter - > list_item_counter = 0 ;
}
}
internal void
output_end_item ( String * out ) {
append ( out , " </li> " ) ;
}
2017-07-10 14:51:19 +00:00
internal void
write_enriched_text_html ( String * out , Enriched_Text * text , Document_System * doc_system , Section_Counter * section_counter ) {
2016-11-03 21:37:29 +00:00
String source = text - > source ;
2017-07-10 15:56:57 +00:00
append ( out , " <div> " ) ;
2016-11-03 21:37:29 +00:00
for ( String line = get_first_double_line ( source ) ;
line . str ;
2016-11-05 02:59:35 +00:00
line = get_next_double_line ( source , line ) ) {
2017-07-15 01:07:00 +00:00
String l = skip_chop_whitespace ( line ) ;
2017-07-14 23:34:24 +00:00
output_begin_paragraph ( out ) ;
2016-11-05 02:59:35 +00:00
2017-01-07 02:59:55 +00:00
i32 start = 0 , i = 0 ;
2016-11-05 02:59:35 +00:00
for ( ; i < l . size ; + + i ) {
2017-04-01 06:15:33 +00:00
char ch = l . str [ i ] ;
2017-07-13 05:02:21 +00:00
if ( ch = = ' \\ ' ) {
output_plain_old_text ( out , l . str + start , i - start ) ;
2017-07-13 21:41:44 +00:00
2017-07-13 05:02:21 +00:00
i32 command_start = i + 1 ;
i32 command_end = command_start ;
for ( ; command_end < l . size ; + + command_end ) {
if ( ! char_is_alpha_numeric ( l . str [ command_end ] ) ) {
break ;
}
}
if ( command_end = = command_start ) {
if ( command_end < l . size & & l . str [ command_end ] = = ' \\ ' ) {
+ + command_end ;
}
}
String command_string = substr ( l , command_start , command_end - command_start ) ;
2016-11-05 02:59:35 +00:00
2017-07-13 05:02:21 +00:00
String * enriched_commands = get_enriched_commands ( ) ;
u32 enriched_commands_count = get_enriched_commands_count ( ) ;
2016-11-05 02:59:35 +00:00
2017-07-13 05:02:21 +00:00
i = command_end ;
i32 match_index = 0 ;
if ( ! string_set_match ( enriched_commands , enriched_commands_count , command_string , & match_index ) ) {
match_index = - 1 ;
}
2017-07-13 21:41:44 +00:00
2017-07-13 05:02:21 +00:00
switch ( match_index ) {
case Cmd_BackSlash : append ( out , " \\ " ) ; break ;
2017-07-13 21:41:44 +00:00
2017-07-13 05:02:21 +00:00
case Cmd_BeginStyle :
{
String body_text = { 0 } ;
2017-07-15 01:07:00 +00:00
b32 has_body = extract_command_body ( l , & i , & body_text ) ;
2017-07-13 05:02:21 +00:00
if ( has_body ) {
2017-07-13 21:41:44 +00:00
output_begin_style ( out , body_text . str , body_text . size ) ;
2017-04-01 06:15:33 +00:00
}
2017-07-15 01:07:00 +00:00
else {
report_error_html_missing_body ( out , command_string ) ;
}
2017-07-13 05:02:21 +00:00
} break ;
2017-04-01 06:15:33 +00:00
2017-07-13 05:02:21 +00:00
case Cmd_EndStyle :
{
2017-07-13 21:41:44 +00:00
output_end_style ( out ) ;
2017-07-13 05:02:21 +00:00
} break ;
2017-04-01 06:15:33 +00:00
2017-07-13 05:02:21 +00:00
// TODO(allen): upgrade this bs
2017-07-15 01:07:00 +00:00
case Cmd_DocumentLink :
2017-07-13 05:02:21 +00:00
{
String body_text = { 0 } ;
2017-07-15 01:07:00 +00:00
b32 has_body = extract_command_body ( l , & i , & body_text ) ;
2017-07-13 05:02:21 +00:00
if ( has_body ) {
2017-07-15 01:07:00 +00:00
output_document_link ( out , body_text . str , body_text . size ) ;
}
else {
report_error_html_missing_body ( out , command_string ) ;
2017-07-13 05:02:21 +00:00
}
} break ;
2017-04-01 06:15:33 +00:00
2017-07-13 05:02:21 +00:00
case Cmd_BeginList :
{
2017-07-14 23:34:24 +00:00
output_begin_list ( out ) ;
2017-07-13 05:02:21 +00:00
} break ;
2017-04-01 06:15:33 +00:00
2017-07-13 05:02:21 +00:00
case Cmd_EndList :
{
2017-07-14 23:34:24 +00:00
output_end_list ( out ) ;
2017-07-13 05:02:21 +00:00
} break ;
2017-04-01 06:15:33 +00:00
2017-07-13 05:02:21 +00:00
case Cmd_BeginItem :
{
2017-07-14 23:34:24 +00:00
output_begin_item ( out , section_counter ) ;
2017-07-13 05:02:21 +00:00
} break ;
2017-04-01 06:15:33 +00:00
2017-07-13 05:02:21 +00:00
case Cmd_EndItem :
{
2017-07-14 23:34:24 +00:00
output_end_item ( out ) ;
2017-07-13 05:02:21 +00:00
} break ;
2017-04-01 06:15:33 +00:00
2017-07-13 05:02:21 +00:00
case Cmd_BeginLink :
{
String body_text = { 0 } ;
2017-07-15 01:07:00 +00:00
b32 has_body = extract_command_body ( l , & i , & body_text ) ;
2017-07-13 05:02:21 +00:00
if ( has_body ) {
2017-07-14 23:34:24 +00:00
output_begin_link ( doc_system , out , body_text . str , body_text . size ) ;
2017-07-13 05:02:21 +00:00
}
2017-07-15 01:07:00 +00:00
else {
report_error_html_missing_body ( out , command_string ) ;
}
2017-07-13 05:02:21 +00:00
} break ;
case Cmd_EndLink :
{
2017-07-14 23:34:24 +00:00
output_end_link ( out ) ;
2017-07-13 05:02:21 +00:00
} break ;
case Cmd_Image :
{
String body_text = { 0 } ;
2017-07-15 01:07:00 +00:00
b32 has_body = extract_command_body ( l , & i , & body_text ) ;
2017-07-13 05:02:21 +00:00
if ( has_body ) {
String size_parameter = { 0 } ;
2017-07-15 01:07:00 +00:00
extract_command_body ( l , & i , & size_parameter ) ;
2017-07-14 23:34:24 +00:00
output_image ( doc_system , out , body_text . str , body_text . size , size_parameter . str , size_parameter . size ) ;
2017-07-13 05:02:21 +00:00
}
2017-07-15 01:07:00 +00:00
else {
report_error_html_missing_body ( out , command_string ) ;
}
2017-07-13 05:02:21 +00:00
} break ;
case Cmd_Video :
{
String body_text = { 0 } ;
2017-07-15 01:07:00 +00:00
b32 has_body = extract_command_body ( l , & i , & body_text ) ;
2017-07-13 05:02:21 +00:00
if ( has_body ) {
2017-07-14 23:34:24 +00:00
output_video ( out , body_text . str , body_text . size ) ;
2017-04-01 06:15:33 +00:00
}
2017-07-15 01:07:00 +00:00
else {
report_error_html_missing_body ( out , command_string ) ;
}
2017-07-13 05:02:21 +00:00
} break ;
2017-04-01 06:15:33 +00:00
2017-07-13 05:02:21 +00:00
case Cmd_Section :
{
String body_text = { 0 } ;
2017-07-15 01:07:00 +00:00
b32 has_body = extract_command_body ( l , & i , & body_text ) ;
2017-07-13 05:02:21 +00:00
if ( has_body ) {
2017-07-14 23:34:24 +00:00
String extra_text = { 0 } ;
2017-07-15 01:07:00 +00:00
extract_command_body ( l , & i , & extra_text ) ;
2017-07-14 23:34:24 +00:00
output_begin_section ( out , section_counter , body_text . str , body_text . size ) ;
2017-07-13 05:02:21 +00:00
}
2017-07-15 01:07:00 +00:00
else {
report_error_html_missing_body ( out , command_string ) ;
}
2017-07-13 05:02:21 +00:00
} break ;
case Cmd_EndSection :
{
2017-07-14 23:34:24 +00:00
output_end_section ( out , section_counter ) ;
2017-07-13 05:02:21 +00:00
} break ;
2017-07-13 21:41:44 +00:00
2017-07-15 01:07:00 +00:00
case Cmd_Version :
2017-07-13 05:02:21 +00:00
{
2017-07-15 01:07:00 +00:00
append ( out , VERSION ) ;
2017-07-13 05:02:21 +00:00
} break ;
2017-07-13 21:41:44 +00:00
2017-07-13 05:02:21 +00:00
default :
{
append ( out , " <span style='color:#F00'>! Doc generator error: unrecognized command !</span> " ) ;
fprintf ( stdout , " error: unrecognized command %.*s \n " , command_string . size , command_string . str ) ;
} break ;
2016-11-05 02:59:35 +00:00
}
2017-07-13 21:41:44 +00:00
2017-07-13 05:02:21 +00:00
start = i ;
2016-11-05 02:59:35 +00:00
}
}
if ( start ! = i ) {
2017-07-13 05:02:21 +00:00
output_plain_old_text ( out , l . str + start , i - start ) ;
2016-11-05 02:59:35 +00:00
}
2017-07-14 23:34:24 +00:00
output_end_paragraph ( out ) ;
2016-11-03 21:37:29 +00:00
}
2017-07-10 15:56:57 +00:00
append ( out , " </div> " ) ;
2016-11-28 19:13:53 +00:00
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-28 19:13:53 +00:00
print_item_in_list ( String * out , String name , char * id_postfix ) {
2017-07-10 15:56:57 +00:00
append ( out , " <li><a href='# " ) ;
append ( out , name ) ;
append ( out , id_postfix ) ;
append ( out , " '> " ) ;
append ( out , name ) ;
append ( out , " </a></li> " ) ;
2016-11-28 19:13:53 +00:00
}
2017-07-10 14:51:19 +00:00
internal void
init_used_links ( Used_Links * used , i32 count ) {
used - > strs = fm_push_array ( String , count ) ;
2016-11-28 19:13:53 +00:00
used - > count = 0 ;
used - > max = count ;
}
2017-07-10 15:56:57 +00:00
internal b32
try_to_use_link ( Used_Links * used , String str ) {
b32 result = true ;
2017-01-07 02:59:55 +00:00
i32 index = 0 ;
2016-11-28 19:13:53 +00:00
if ( string_set_match ( used - > strs , used - > count , str , & index ) ) {
2017-07-10 15:56:57 +00:00
result = false ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
else {
2017-07-10 15:56:57 +00:00
Assert ( used - > count < used - > max ) ;
2016-11-28 19:13:53 +00:00
used - > strs [ used - > count + + ] = str ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
return ( result ) ;
}
2017-07-10 14:51:19 +00:00
internal void
2017-01-07 02:59:55 +00:00
print_struct_html ( String * out , Item_Node * member , i32 hide_children ) {
2016-11-28 19:13:53 +00:00
String name = member - > name ;
String type = member - > type ;
String type_postfix = member - > type_postfix ;
2017-07-10 15:56:57 +00:00
append ( out , type ) ;
2016-11-28 19:13:53 +00:00
append_s_char ( out , ' ' ) ;
2017-07-10 15:56:57 +00:00
append ( out , name ) ;
append ( out , type_postfix ) ;
2016-11-28 19:13:53 +00:00
if ( match_ss ( type , make_lit_string ( " struct " ) ) | |
match_ss ( type , make_lit_string ( " union " ) ) ) {
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
if ( hide_children ) {
2017-07-10 15:56:57 +00:00
append ( out , " { /* non-public internals */ } ; " ) ;
2016-11-10 03:18:22 +00:00
}
else {
2017-07-10 15:56:57 +00:00
append ( out , " {<br><div style='margin-left: 8mm;'> " ) ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
for ( Item_Node * member_iter = member - > first_child ;
member_iter ! = 0 ;
member_iter = member_iter - > next_sibling ) {
print_struct_html ( out , member_iter , hide_children ) ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
append ( out , " </div>};<br> " ) ;
2016-11-10 03:18:22 +00:00
}
}
2016-11-28 19:13:53 +00:00
else {
2017-07-10 15:56:57 +00:00
append ( out , " ;<br> " ) ;
2016-11-28 19:13:53 +00:00
}
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-28 19:13:53 +00:00
print_function_html ( String * out , Used_Links * used , String cpp_name , String ret , char * function_call_head , String name , Argument_Breakdown breakdown ) {
2016-11-10 03:18:22 +00:00
2017-07-10 15:56:57 +00:00
append ( out , ret ) ;
2016-11-28 19:13:53 +00:00
append_s_char ( out , ' ' ) ;
2017-07-10 15:56:57 +00:00
append ( out , function_call_head ) ;
append ( out , name ) ;
2016-11-28 19:13:53 +00:00
if ( breakdown . count = = 0 ) {
2017-07-10 15:56:57 +00:00
append ( out , " () " ) ;
2016-11-28 19:13:53 +00:00
}
else if ( breakdown . count = = 1 ) {
2017-07-10 15:56:57 +00:00
append ( out , " ( " ) ;
append ( out , breakdown . args [ 0 ] . param_string ) ;
append ( out , " ) " ) ;
2016-11-28 19:13:53 +00:00
}
else {
2017-07-10 15:56:57 +00:00
append ( out , " (<div style='margin-left: 4mm;'> " ) ;
2016-11-10 03:18:22 +00:00
2017-01-07 02:59:55 +00:00
for ( i32 j = 0 ; j < breakdown . count ; + + j ) {
2017-07-10 15:56:57 +00:00
append ( out , breakdown . args [ j ] . param_string ) ;
2016-11-28 19:13:53 +00:00
if ( j < breakdown . count - 1 ) {
append_s_char ( out , ' , ' ) ;
2016-11-10 03:18:22 +00:00
}
2017-07-10 15:56:57 +00:00
append ( out , " <br> " ) ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
append ( out , " </div>) " ) ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-28 19:13:53 +00:00
print_macro_html ( String * out , String name , Argument_Breakdown breakdown ) {
2016-11-10 03:18:22 +00:00
2017-07-10 15:56:57 +00:00
append ( out , " #define " ) ;
append ( out , name ) ;
2016-11-28 19:13:53 +00:00
if ( breakdown . count = = 0 ) {
2017-07-10 15:56:57 +00:00
append ( out , " () " ) ;
2016-11-28 19:13:53 +00:00
}
else if ( breakdown . count = = 1 ) {
append_s_char ( out , ' ( ' ) ;
2017-07-10 15:56:57 +00:00
append ( out , breakdown . args [ 0 ] . param_string ) ;
2016-11-28 19:13:53 +00:00
append_s_char ( out , ' ) ' ) ;
}
else {
2017-07-10 15:56:57 +00:00
append ( out , " (<div style='margin-left: 4mm;'> " ) ;
2016-11-10 03:18:22 +00:00
2017-01-07 02:59:55 +00:00
for ( i32 j = 0 ; j < breakdown . count ; + + j ) {
2017-07-10 15:56:57 +00:00
append ( out , breakdown . args [ j ] . param_string ) ;
2016-11-28 19:13:53 +00:00
if ( j < breakdown . count - 1 ) {
append_s_char ( out , ' , ' ) ;
2016-11-10 03:18:22 +00:00
}
2017-07-10 15:56:57 +00:00
append ( out , " <br> " ) ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
append ( out , " )</div>) " ) ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
}
enum Doc_Chunk_Type {
DocChunk_PlainText ,
DocChunk_CodeExample ,
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
DocChunk_Count
} ;
2017-07-10 14:51:19 +00:00
global String doc_chunk_headers [ ] = {
2016-11-28 19:13:53 +00:00
make_lit_string ( " " ) ,
make_lit_string ( " CODE_EXAMPLE " ) ,
} ;
2017-07-10 14:51:19 +00:00
internal String
2016-11-28 19:13:53 +00:00
get_next_doc_chunk ( String source , String prev_chunk , Doc_Chunk_Type * type ) {
String chunk = { 0 } ;
String word = { 0 } ;
2017-01-07 02:59:55 +00:00
i32 pos = source . size ;
i32 word_index = 0 ;
2016-11-28 19:13:53 +00:00
Doc_Chunk_Type t = DocChunk_PlainText ;
2016-11-10 03:18:22 +00:00
2017-01-07 02:59:55 +00:00
i32 start_pos = ( i32 ) ( prev_chunk . str - source . str ) + prev_chunk . size ;
2016-11-28 19:13:53 +00:00
String source_tail = substr_tail ( source , start_pos ) ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
Assert ( DocChunk_Count = = ArrayCount ( doc_chunk_headers ) ) ;
for ( word = get_first_word ( source_tail ) ;
word . str ;
word = get_next_word ( source_tail , word ) , + + word_index ) {
2016-11-10 03:18:22 +00:00
2017-01-07 02:59:55 +00:00
for ( i32 i = 1 ; i < DocChunk_Count ; + + i ) {
2016-11-28 19:13:53 +00:00
if ( match_ss ( word , doc_chunk_headers [ i ] ) ) {
2017-01-07 02:59:55 +00:00
pos = ( i32 ) ( word . str - source . str ) ;
2016-11-28 19:13:53 +00:00
t = ( Doc_Chunk_Type ) i ;
goto doublebreak ;
2016-11-10 03:18:22 +00:00
}
}
2016-11-28 19:13:53 +00:00
}
doublebreak : ;
* type = DocChunk_PlainText ;
if ( word_index = = 0 ) {
* type = t ;
2016-11-10 03:18:22 +00:00
2017-01-07 02:59:55 +00:00
i32 nest_level = 1 ;
i32 i = find_s_char ( source , pos , ' ( ' ) ;
2016-11-28 19:13:53 +00:00
for ( + + i ; i < source . size ; + + i ) {
if ( source . str [ i ] = = ' ( ' ) {
+ + nest_level ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
else if ( source . str [ i ] = = ' ) ' ) {
- - nest_level ;
if ( nest_level = = 0 ) {
break ;
}
2016-11-10 03:18:22 +00:00
}
}
2016-11-28 19:13:53 +00:00
pos = i + 1 ;
}
chunk = substr ( source , start_pos , pos - start_pos ) ;
2017-01-07 02:59:55 +00:00
i32 is_all_white = 1 ;
for ( i32 i = 0 ; i < chunk . size ; + + i ) {
2016-11-28 19:13:53 +00:00
if ( ! char_is_whitespace ( chunk . str [ i ] ) ) {
is_all_white = 0 ;
break ;
2016-11-10 03:18:22 +00:00
}
}
2016-11-28 19:13:53 +00:00
if ( is_all_white ) {
chunk = null_string ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
return ( chunk ) ;
}
2017-07-10 14:51:19 +00:00
internal String
2016-11-28 19:13:53 +00:00
get_first_doc_chunk ( String source , Doc_Chunk_Type * type ) {
String start_str = make_string ( source . str , 0 ) ;
String chunk = get_next_doc_chunk ( source , start_str , type ) ;
return ( chunk ) ;
}
2017-07-10 14:51:19 +00:00
internal void
print_doc_description ( String * out , String src ) {
2016-11-28 19:13:53 +00:00
Doc_Chunk_Type type ;
for ( String chunk = get_first_doc_chunk ( src , & type ) ;
chunk . str ;
chunk = get_next_doc_chunk ( src , chunk , & type ) ) {
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
switch ( type ) {
case DocChunk_PlainText :
{
for ( String line = get_first_double_line ( chunk ) ;
line . str ;
line = get_next_double_line ( chunk , line ) ) {
2017-07-10 15:56:57 +00:00
append ( out , line ) ;
append ( out , " <br><br> " ) ;
2016-11-28 19:13:53 +00:00
}
} break ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
case DocChunk_CodeExample :
{
2017-01-07 02:59:55 +00:00
i32 start = 0 ;
i32 end = chunk . size - 1 ;
2016-11-28 19:13:53 +00:00
while ( start < end & & chunk . str [ start ] ! = ' ( ' ) + + start ;
start + = 1 ;
while ( end > start & & chunk . str [ end ] ! = ' ) ' ) - - end ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
append ( out , HTML_EXAMPLE_CODE_OPEN ) ;
2016-11-28 19:13:53 +00:00
if ( start < end ) {
String code_example = substr ( chunk , start , end - start ) ;
2017-01-07 02:59:55 +00:00
i32 first_line = 1 ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
for ( String line = get_first_line ( code_example ) ;
line . str ;
line = get_next_line ( code_example , line ) ) {
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
if ( ! ( first_line & & line . size = = 0 ) ) {
2017-01-07 02:59:55 +00:00
i32 space_i = 0 ;
2016-11-28 19:13:53 +00:00
for ( ; space_i < line . size ; + + space_i ) {
if ( line . str [ space_i ] = = ' ' ) {
2017-07-10 15:56:57 +00:00
append ( out , " " ) ;
2016-11-28 19:13:53 +00:00
}
else {
break ;
2016-11-10 03:18:22 +00:00
}
}
2016-11-28 19:13:53 +00:00
String line_tail = substr_tail ( line , space_i ) ;
2017-07-10 15:56:57 +00:00
append ( out , line_tail ) ;
append ( out , " <br> " ) ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
first_line = 0 ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
}
2016-11-10 03:18:22 +00:00
2017-07-10 15:56:57 +00:00
append ( out , HTML_EXAMPLE_CODE_CLOSE ) ;
2016-11-28 19:13:53 +00:00
} break ;
2016-11-10 03:18:22 +00:00
}
}
2016-11-28 19:13:53 +00:00
}
2017-07-10 14:51:19 +00:00
internal void
print_struct_docs ( String * out , Item_Node * member ) {
2016-11-28 19:13:53 +00:00
for ( Item_Node * member_iter = member - > first_child ;
member_iter ! = 0 ;
member_iter = member_iter - > next_sibling ) {
String type = member_iter - > type ;
if ( match_ss ( type , make_lit_string ( " struct " ) ) | |
match_ss ( type , make_lit_string ( " union " ) ) ) {
2017-07-10 14:51:19 +00:00
print_struct_docs ( out , member_iter ) ;
2016-11-28 19:13:53 +00:00
}
else {
Documentation doc = { 0 } ;
2017-07-10 14:51:19 +00:00
perform_doc_parse ( member_iter - > doc_string , & doc ) ;
2016-11-10 03:18:22 +00:00
2017-07-10 15:56:57 +00:00
append ( out , " <div> " ) ;
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
append ( out , " <div style=' " HTML_CODE_STYLE " '> " HTML_DOC_ITEM_HEAD_INL_OPEN ) ;
append ( out , member_iter - > name ) ;
append ( out , HTML_DOC_ITEM_HEAD_INL_CLOSE " </div> " ) ;
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
append ( out , " <div style='margin-bottom: 6mm;'> " HTML_DOC_ITEM_OPEN ) ;
2017-07-10 14:51:19 +00:00
print_doc_description ( out , doc . main_doc ) ;
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_ITEM_CLOSE " </div> " ) ;
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
append ( out , " </div> " ) ;
2016-11-10 03:18:22 +00:00
}
}
2016-11-28 19:13:53 +00:00
}
2017-07-10 14:51:19 +00:00
internal void
2016-11-28 19:13:53 +00:00
print_see_also ( String * out , Documentation * doc ) {
2017-01-07 02:59:55 +00:00
i32 doc_see_count = doc - > see_also_count ;
2016-11-28 19:13:53 +00:00
if ( doc_see_count > 0 ) {
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_HEAD_OPEN " See Also " HTML_DOC_HEAD_CLOSE ) ;
2016-11-10 03:18:22 +00:00
2017-01-07 02:59:55 +00:00
for ( i32 j = 0 ; j < doc_see_count ; + + j ) {
2016-11-28 19:13:53 +00:00
String see_also = doc - > see_also [ j ] ;
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_ITEM_OPEN " <a href='# " ) ;
append ( out , see_also ) ;
append ( out , " _doc'> " ) ;
append ( out , see_also ) ;
append ( out , " </a> " HTML_DOC_ITEM_CLOSE ) ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
}
}
2017-07-10 14:51:19 +00:00
internal void
print_function_docs ( String * out , String name , String doc_string ) {
2016-11-28 19:13:53 +00:00
if ( doc_string . size = = 0 ) {
2017-07-10 15:56:57 +00:00
append ( out , " No documentation generated for this function. " ) ;
2017-07-13 05:02:21 +00:00
fprintf ( stdout , " warning: no documentation string for %.*s \n " , name . size , name . str ) ;
2016-11-28 19:13:53 +00:00
}
2017-07-10 14:51:19 +00:00
Temp temp = fm_begin_temp ( ) ;
2016-11-28 19:13:53 +00:00
Documentation doc = { 0 } ;
2017-07-10 14:51:19 +00:00
perform_doc_parse ( doc_string , & doc ) ;
2016-11-28 19:13:53 +00:00
2017-01-07 02:59:55 +00:00
i32 doc_param_count = doc . param_count ;
2016-11-28 19:13:53 +00:00
if ( doc_param_count > 0 ) {
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_HEAD_OPEN " Parameters " HTML_DOC_HEAD_CLOSE ) ;
2016-11-10 03:18:22 +00:00
2017-01-07 02:59:55 +00:00
for ( i32 j = 0 ; j < doc_param_count ; + + j ) {
2016-11-28 19:13:53 +00:00
String param_name = doc . param_name [ j ] ;
String param_docs = doc . param_docs [ j ] ;
2017-07-10 15:56:57 +00:00
// TODO(allen): check that param_name is actually a parameter to this function!
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
append ( out , " <div> " HTML_DOC_ITEM_HEAD_OPEN ) ;
append ( out , param_name ) ;
append ( out , HTML_DOC_ITEM_HEAD_CLOSE " <div style='margin-bottom: 6mm;'> " HTML_DOC_ITEM_OPEN ) ;
append ( out , param_docs ) ;
append ( out , HTML_DOC_ITEM_CLOSE " </div></div> " ) ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
}
String ret_doc = doc . return_doc ;
if ( ret_doc . size ! = 0 ) {
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_HEAD_OPEN " Return " HTML_DOC_HEAD_CLOSE HTML_DOC_ITEM_OPEN ) ;
append ( out , ret_doc ) ;
append ( out , HTML_DOC_ITEM_CLOSE ) ;
2016-11-28 19:13:53 +00:00
}
String main_doc = doc . main_doc ;
if ( main_doc . size ! = 0 ) {
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_HEAD_OPEN " Description " HTML_DOC_HEAD_CLOSE HTML_DOC_ITEM_OPEN ) ;
2017-07-10 14:51:19 +00:00
print_doc_description ( out , main_doc ) ;
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_ITEM_CLOSE ) ;
2016-11-28 19:13:53 +00:00
}
print_see_also ( out , & doc ) ;
2017-07-10 14:51:19 +00:00
fm_end_temp ( temp ) ;
2016-11-28 19:13:53 +00:00
}
2017-07-10 14:51:19 +00:00
internal void
print_item_html ( String * out , Used_Links * used , Item_Node * item , char * id_postfix , char * section , i32 I , Alternate_Name * alt_name , i32 alt_name_type ) {
Temp temp = fm_begin_temp ( ) ;
2016-11-28 19:13:53 +00:00
String name = item - > name ;
switch ( alt_name_type ) {
case AltName_Macro :
{
name = alt_name - > macro ;
} break ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
case AltName_Public_Name :
{
name = alt_name - > public_name ;
} break ;
}
/* NOTE(allen):
Open a div for the whole item .
Put a heading in it with the name and section .
Open a " descriptive " box for the display of the code interface .
*/
2017-07-10 15:56:57 +00:00
append ( out , " <div id=' " ) ;
append ( out , name ) ;
append ( out , id_postfix ) ;
append ( out , " ' style='margin-bottom: 1cm;'> " ) ;
2016-11-28 19:13:53 +00:00
2017-01-07 02:59:55 +00:00
i32 has_cpp_name = 0 ;
2016-11-28 19:13:53 +00:00
if ( item - > cpp_name . str ! = 0 ) {
2017-07-10 15:56:57 +00:00
if ( try_to_use_link ( used , item - > cpp_name ) ) {
append ( out , " <div id=' " ) ;
append ( out , item - > cpp_name ) ;
append ( out , id_postfix ) ;
append ( out , " '> " ) ;
2016-11-28 19:13:53 +00:00
has_cpp_name = 1 ;
2016-11-10 03:18:22 +00:00
}
}
2017-07-10 15:56:57 +00:00
append ( out , " <h4>§ " ) ;
append ( out , section ) ;
2016-11-28 19:13:53 +00:00
append_s_char ( out , ' . ' ) ;
append_int_to_str ( out , I ) ;
2017-07-10 15:56:57 +00:00
append ( out , " : " ) ;
append ( out , name ) ;
append ( out , " </h4> " ) ;
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
append ( out , " <div style=' " HTML_CODE_STYLE " " HTML_DESCRIPT_SECTION_STYLE " '> " ) ;
2016-11-28 19:13:53 +00:00
switch ( item - > t ) {
case Item_Function :
{
// NOTE(allen): Code box
print_function_html ( out , used , item - > cpp_name , item - > ret , " " , name , item - > breakdown ) ;
// NOTE(allen): Close the code box
2017-07-10 15:56:57 +00:00
append ( out , " </div> " ) ;
2016-11-28 19:13:53 +00:00
// NOTE(allen): Descriptive section
2017-07-10 14:51:19 +00:00
print_function_docs ( out , name , item - > doc_string ) ;
2016-11-28 19:13:53 +00:00
} break ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
case Item_Macro :
{
// NOTE(allen): Code box
print_macro_html ( out , name , item - > breakdown ) ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
// NOTE(allen): Close the code box
2017-07-10 15:56:57 +00:00
append ( out , " </div> " ) ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
// NOTE(allen): Descriptive section
2017-07-10 14:51:19 +00:00
print_function_docs ( out , name , item - > doc_string ) ;
2016-11-28 19:13:53 +00:00
} break ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
case Item_Typedef :
{
String type = item - > type ;
// NOTE(allen): Code box
2017-07-10 15:56:57 +00:00
append ( out , " typedef " ) ;
append ( out , type ) ;
2016-11-28 19:13:53 +00:00
append_s_char ( out , ' ' ) ;
2017-07-10 15:56:57 +00:00
append ( out , name ) ;
2016-11-28 19:13:53 +00:00
append_s_char ( out , ' ; ' ) ;
// NOTE(allen): Close the code box
2017-07-10 15:56:57 +00:00
append ( out , " </div> " ) ;
2016-11-28 19:13:53 +00:00
// NOTE(allen): Descriptive section
String doc_string = item - > doc_string ;
Documentation doc = { 0 } ;
2017-07-10 14:51:19 +00:00
perform_doc_parse ( doc_string , & doc ) ;
2016-11-28 19:13:53 +00:00
String main_doc = doc . main_doc ;
if ( main_doc . size ! = 0 ) {
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_HEAD_OPEN " Description " HTML_DOC_HEAD_CLOSE ) ;
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_ITEM_OPEN ) ;
2017-07-10 14:51:19 +00:00
print_doc_description ( out , main_doc ) ;
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_ITEM_CLOSE ) ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
else {
2017-07-13 05:02:21 +00:00
fprintf ( stdout , " warning: no documentation string for %.*s \n " , name . size , name . str ) ;
2016-11-28 19:13:53 +00:00
}
print_see_also ( out , & doc ) ;
} break ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
case Item_Enum :
{
// NOTE(allen): Code box
2017-07-10 15:56:57 +00:00
append ( out , " enum " ) ;
append ( out , name ) ;
2016-11-28 19:13:53 +00:00
append_s_char ( out , ' ; ' ) ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
// NOTE(allen): Close the code box
2017-07-10 15:56:57 +00:00
append ( out , " </div> " ) ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
// NOTE(allen): Descriptive section
String doc_string = item - > doc_string ;
Documentation doc = { 0 } ;
2017-07-10 14:51:19 +00:00
perform_doc_parse ( doc_string , & doc ) ;
2016-11-28 19:13:53 +00:00
String main_doc = doc . main_doc ;
if ( main_doc . size ! = 0 ) {
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_HEAD_OPEN " Description " HTML_DOC_HEAD_CLOSE ) ;
2016-11-10 03:18:22 +00:00
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_ITEM_OPEN ) ;
2017-07-10 14:51:19 +00:00
print_doc_description ( out , main_doc ) ;
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_ITEM_CLOSE ) ;
2016-11-28 19:13:53 +00:00
}
else {
2017-07-13 05:02:21 +00:00
fprintf ( stdout , " warning: no documentation string for %.*s \n " , name . size , name . str ) ;
2016-11-28 19:13:53 +00:00
}
if ( item - > first_child ) {
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_HEAD_OPEN " Values " HTML_DOC_HEAD_CLOSE ) ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
for ( Item_Node * member = item - > first_child ;
member ;
member = member - > next_sibling ) {
Documentation doc = { 0 } ;
2017-07-10 14:51:19 +00:00
perform_doc_parse ( member - > doc_string , & doc ) ;
2016-11-10 03:18:22 +00:00
2017-07-10 15:56:57 +00:00
append ( out , " <div> " ) ;
2016-11-28 19:13:53 +00:00
// NOTE(allen): Dafuq is this all?
2017-07-10 15:56:57 +00:00
append ( out , " <div><span style=' " HTML_CODE_STYLE " '> " HTML_DOC_ITEM_HEAD_INL_OPEN ) ;
append ( out , member - > name ) ;
append ( out , HTML_DOC_ITEM_HEAD_INL_CLOSE ) ;
2016-11-28 19:13:53 +00:00
if ( member - > value . str ) {
2017-07-10 15:56:57 +00:00
append ( out , " = " ) ;
append ( out , member - > value ) ;
2016-11-28 19:13:53 +00:00
}
2017-07-10 15:56:57 +00:00
append ( out , " </span></div> " ) ;
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
append ( out , " <div style='margin-bottom: 6mm;'> " HTML_DOC_ITEM_OPEN ) ;
2017-07-10 14:51:19 +00:00
print_doc_description ( out , doc . main_doc ) ;
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_ITEM_CLOSE " </div> " ) ;
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
append ( out , " </div> " ) ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
}
print_see_also ( out , & doc ) ;
} break ;
case Item_Struct : case Item_Union :
{
String doc_string = item - > doc_string ;
2017-01-07 02:59:55 +00:00
i32 hide_members = 0 ;
2016-11-28 19:13:53 +00:00
if ( doc_string . size = = 0 ) {
hide_members = 1 ;
}
else {
for ( String word = get_first_word ( doc_string ) ;
word . str ;
word = get_next_word ( doc_string , word ) ) {
if ( match_ss ( word , make_lit_string ( " HIDE_MEMBERS " ) ) ) {
hide_members = 1 ;
break ;
}
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
}
// NOTE(allen): Code box
print_struct_html ( out , item , hide_members ) ;
// NOTE(allen): Close the code box
2017-07-10 15:56:57 +00:00
append ( out , " </div> " ) ;
2016-11-10 03:18:22 +00:00
2016-11-28 19:13:53 +00:00
// NOTE(allen): Descriptive section
2016-11-10 03:18:22 +00:00
{
Documentation doc = { 0 } ;
2017-07-10 14:51:19 +00:00
perform_doc_parse ( doc_string , & doc ) ;
2016-11-10 03:18:22 +00:00
String main_doc = doc . main_doc ;
if ( main_doc . size ! = 0 ) {
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_HEAD_OPEN " Description " HTML_DOC_HEAD_CLOSE ) ;
2016-11-10 03:18:22 +00:00
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_ITEM_OPEN ) ;
2017-07-10 14:51:19 +00:00
print_doc_description ( out , main_doc ) ;
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_ITEM_CLOSE ) ;
2016-11-10 03:18:22 +00:00
}
else {
2017-07-13 05:02:21 +00:00
fprintf ( stdout , " warning: no documentation string for %.*s \n " , name . size , name . str ) ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
if ( ! hide_members ) {
if ( item - > first_child ) {
2017-07-10 15:56:57 +00:00
append ( out , HTML_DOC_HEAD_OPEN " Fields " HTML_DOC_HEAD_CLOSE ) ;
2017-07-10 14:51:19 +00:00
print_struct_docs ( out , item ) ;
2016-11-10 03:18:22 +00:00
}
}
print_see_also ( out , & doc ) ;
2016-11-28 19:13:53 +00:00
}
} break ;
}
if ( has_cpp_name ) {
2017-07-10 15:56:57 +00:00
append ( out , " </div> " ) ;
2016-11-10 03:18:22 +00:00
}
2016-11-28 19:13:53 +00:00
// NOTE(allen): Close the item box
2017-07-10 15:56:57 +00:00
append ( out , " </div><hr> " ) ;
2016-11-28 19:13:53 +00:00
2017-07-10 14:51:19 +00:00
fm_end_temp ( temp ) ;
2016-11-28 19:13:53 +00:00
}
2017-07-10 15:56:57 +00:00
global char * html_css =
" <style> "
" body { "
" background: " HTML_BACK_COLOR " ; "
" color: " HTML_TEXT_COLOR " ; "
" } "
// H things
" h1,h2,h3,h4 { "
" color: " HTML_POP_COLOR_1 " ; "
" margin: 0; "
" } "
" h2 { "
" margin-top: 6mm; "
" } "
" h3 { "
" margin-top: 5mm; margin-bottom: 5mm; "
" } "
" h4 { "
" font-size: 1.1em; "
" } "
// ANCHORS
" a { "
" color: " HTML_POP_COLOR_1 " ; "
" text-decoration: none; "
" } "
" a:visited { "
" color: " HTML_VISITED_LINK " ; "
" } "
" a:hover { "
" background: " HTML_POP_BACK_1 " ; "
" } "
// LIST
" ul { "
" list-style: none; "
" padding: 0; "
" margin: 0; "
" } "
" </style> " ;
2017-07-10 14:51:19 +00:00
internal void
2017-07-10 15:56:57 +00:00
doc_item_html ( String * out , Document_System * doc_system , Used_Links * used_links , Document_Item * item , Section_Counter * section_counter , b32 head ) {
2016-11-03 21:37:29 +00:00
switch ( item - > type ) {
case Doc_Root :
{
2017-07-10 15:56:57 +00:00
if ( head ) {
append ( out ,
" <html lang= \" en-US \" > "
" <head> "
" <link rel='shortcut icon' type='image/x-icon' href='4coder_icon.ico' /> "
" <title> " ) ;
append ( out , item - > section . name ) ;
append ( out , " </title> " ) ;
append ( out , html_css ) ;
append ( out ,
" </head> \n "
" <body> "
" <div style='font-family:Arial; margin: 0 auto; "
" width: " ) ;
append_int_to_str ( out , HTML_WIDTH ) ;
append ( out , " px; text-align: justify; line-height: 1.25;'> " ) ;
if ( item - > section . show_title ) {
append ( out , " <h1 style='margin-top: 5mm; margin-bottom: 5mm;'> " ) ;
append ( out , item - > section . name ) ;
append ( out , " </h1> " ) ;
}
}
else {
append ( out , " </div></body></html> " ) ;
2016-11-28 19:13:53 +00:00
}
2016-11-03 21:37:29 +00:00
} break ;
case Doc_Section :
{
2017-07-10 15:56:57 +00:00
if ( head ) {
html_render_section_header ( out , item - > section . name , item - > section . id , section_counter ) ;
}
2016-11-03 21:37:29 +00:00
} break ;
2016-11-10 03:18:22 +00:00
case Doc_Todo :
{
2017-07-10 15:56:57 +00:00
if ( head ) {
append ( out , " <div><i>Coming Soon</i><div> " ) ;
}
2016-11-10 03:18:22 +00:00
} break ;
2017-07-14 23:34:24 +00:00
case Doc_Include :
2016-11-03 21:37:29 +00:00
{
2017-07-10 15:56:57 +00:00
if ( head ) {
2017-07-14 23:34:24 +00:00
write_enriched_text_html ( out , item - > enriched_text . text , doc_system , section_counter ) ;
2017-07-10 15:56:57 +00:00
}
2016-11-03 21:37:29 +00:00
} break ;
2017-07-14 23:34:24 +00:00
case Doc_DocList :
2016-11-10 03:18:22 +00:00
{
2017-07-10 15:56:57 +00:00
if ( head ) {
append ( out , " <ul> " ) ;
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
Meta_Unit * unit = item - > unit_elements . unit ;
Alternate_Names_Array * alt_names = item - > unit_elements . alt_names ;
i32 count = unit - > set . count ;
2016-11-28 19:13:53 +00:00
2017-07-10 15:56:57 +00:00
switch ( item - > unit_elements . alt_name_type ) {
case AltName_Standard :
{
for ( i32 i = 0 ; i < count ; + + i ) {
print_item_in_list ( out , unit - > set . items [ i ] . name , " _doc " ) ;
}
} break ;
case AltName_Macro :
{
for ( i32 i = 0 ; i < count ; + + i ) {
print_item_in_list ( out , alt_names - > names [ i ] . macro , " _doc " ) ;
}
} break ;
case AltName_Public_Name :
{
for ( i32 i = 0 ; i < count ; + + i ) {
print_item_in_list ( out , alt_names - > names [ i ] . public_name , " _doc " ) ;
}
} break ;
}
append ( out , " </ul> " ) ;
2016-11-10 03:18:22 +00:00
}
} break ;
2017-07-14 23:34:24 +00:00
case Doc_DocFull :
2016-11-10 03:18:22 +00:00
{
2017-07-10 15:56:57 +00:00
if ( head ) {
Meta_Unit * unit = item - > unit_elements . unit ;
Alternate_Names_Array * alt_names = item - > unit_elements . alt_names ;
i32 count = unit - > set . count ;
char section_space [ 32 ] ;
String section_str = make_fixed_width_string ( section_space ) ;
append_section_number_reduced ( & section_str , section_counter , 1 ) ;
terminate_with_null ( & section_str ) ;
if ( alt_names ) {
i32 I = 1 ;
for ( i32 i = 0 ; i < count ; + + i , + + I ) {
print_item_html ( out , used_links , & unit - > set . items [ i ] , " _doc " , section_str . str , I , & alt_names - > names [ i ] , item - > unit_elements . alt_name_type ) ;
}
2016-11-28 19:13:53 +00:00
}
2017-07-10 15:56:57 +00:00
else {
i32 I = 1 ;
for ( i32 i = 0 ; i < count ; + + i , + + I ) {
print_item_html ( out , used_links , & unit - > set . items [ i ] , " _doc " , section_str . str , I , 0 , 0 ) ;
}
2016-11-28 19:13:53 +00:00
}
2016-11-10 03:18:22 +00:00
}
} break ;
2017-07-14 23:34:24 +00:00
case Doc_TableOfContents :
2016-11-03 21:37:29 +00:00
{
2017-07-10 15:56:57 +00:00
if ( head ) {
append ( out , " <h3 style='margin:0;'>Table of Contents</h3><ul> " ) ;
i32 i = 1 ;
for ( Document_Item * toc_item = item - > parent - > section . first_child ;
toc_item ! = 0 ;
toc_item = toc_item - > next ) {
if ( toc_item - > type = = Doc_Section ) {
if ( toc_item - > section . id . size > 0 ) {
append ( out , " <li><a href='#section_ " ) ;
append ( out , toc_item - > section . id ) ;
append ( out , " '>§ " ) ;
}
else {
append ( out , " <li>§ " ) ;
}
append_int_to_str ( out , i ) ;
append_s_char ( out , ' ' ) ;
append ( out , toc_item - > section . name ) ;
append ( out , " </a></li> " ) ;
+ + i ;
2016-11-03 21:37:29 +00:00
}
}
2017-07-10 15:56:57 +00:00
append ( out , " </ul> " ) ;
2016-11-03 21:37:29 +00:00
}
} break ;
2017-07-13 21:41:44 +00:00
2017-07-14 23:34:24 +00:00
case Doc_PlainOldText :
2017-07-13 05:02:21 +00:00
{
2017-07-14 23:34:24 +00:00
if ( head ) {
output_plain_old_text ( out , item - > string . string . str , item - > string . string . size ) ;
}
2017-07-13 21:41:44 +00:00
} break ;
2017-07-14 23:34:24 +00:00
case Doc_Version :
{
if ( head ) {
append ( out , VERSION ) ;
}
} break ;
2017-07-13 21:41:44 +00:00
case Doc_BeginStyle :
{
2017-07-14 23:34:24 +00:00
if ( head ) {
output_begin_style ( out , item - > string . string . str , item - > string . string . size ) ;
}
2017-07-13 21:41:44 +00:00
} break ;
case Doc_EndStyle :
{
2017-07-14 23:34:24 +00:00
if ( head ) {
output_end_style ( out ) ;
}
} break ;
2017-07-15 01:07:00 +00:00
case Doc_DocumentLink :
{
if ( head ) {
output_document_link ( out , item - > string . string . str , item - > string . string . size ) ;
}
} break ;
2017-07-14 23:34:24 +00:00
case Doc_BeginLink :
{
if ( head ) {
output_begin_link ( doc_system , out , item - > string . string . str , item - > string . string . size ) ;
}
} break ;
case Doc_EndLink :
{
if ( head ) {
output_end_link ( out ) ;
}
} break ;
case Doc_Image :
{
if ( head ) {
output_image ( doc_system , out , item - > string . string . str , item - > string . string . size , item - > string . string2 . str , item - > string . string2 . size ) ;
}
} break ;
case Doc_Video :
{
if ( head ) {
output_video ( out , item - > string . string . str , item - > string . string . size ) ;
}
} break ;
case Doc_BeginParagraph :
{
if ( head ) {
output_begin_paragraph ( out ) ;
}
} break ;
case Doc_EndParagraph :
{
if ( head ) {
output_end_paragraph ( out ) ;
}
} break ;
// HACK(allen): There is also a Doc_Section type item where the section is actually a parent to the children and begin/end are handled by the one item. That should be the only type.
case Doc_BeginSection :
{
if ( head ) {
output_begin_section ( out , section_counter , item - > string . string . str , item - > string . string . size ) ;
}
} break ;
case Doc_EndSection :
{
if ( head ) {
output_end_section ( out , section_counter ) ;
}
} break ;
case Doc_BeginList :
{
if ( head ) {
output_begin_list ( out ) ;
}
} break ;
case Doc_EndList :
{
if ( head ) {
output_end_list ( out ) ;
}
} break ;
case Doc_BeginItem :
{
if ( head ) {
output_begin_item ( out , section_counter ) ;
}
} break ;
case Doc_EndItem :
{
if ( head ) {
output_end_item ( out ) ;
}
2017-07-13 05:02:21 +00:00
} break ;
2016-11-03 21:37:29 +00:00
}
}
2017-07-10 14:51:19 +00:00
internal void
generate_item_html ( String * out , Document_System * doc_system , Used_Links * used_links , Document_Item * item , Section_Counter * section_counter ) {
2017-07-10 15:56:57 +00:00
doc_item_html ( out , doc_system , used_links , item , section_counter , true ) ;
2016-11-03 21:37:29 +00:00
if ( item - > type = = Doc_Root | | item - > type = = Doc_Section ) {
2017-01-07 02:59:55 +00:00
i32 level = + + section_counter - > nest_level ;
2016-11-03 21:37:29 +00:00
section_counter - > counter [ level ] = 1 ;
for ( Document_Item * m = item - > section . first_child ;
m ! = 0 ;
m = m - > next ) {
2017-07-10 14:51:19 +00:00
generate_item_html ( out , doc_system , used_links , m , section_counter ) ;
2016-11-03 21:37:29 +00:00
}
- - section_counter - > nest_level ;
+ + section_counter - > counter [ section_counter - > nest_level ] ;
}
2017-07-10 15:56:57 +00:00
doc_item_html ( out , doc_system , used_links , item , section_counter , false ) ;
2016-11-03 21:37:29 +00:00
}
2017-07-10 14:51:19 +00:00
internal void
generate_document_html ( String * out , Document_System * doc_system , Abstract_Item * doc ) {
Assert ( doc - > root_item ! = 0 ) ;
2016-11-28 19:13:53 +00:00
2016-11-10 03:18:22 +00:00
Used_Links used_links = { 0 } ;
2017-07-10 14:51:19 +00:00
init_used_links ( & used_links , 4000 ) ;
2016-11-10 03:18:22 +00:00
2016-11-03 21:37:29 +00:00
Section_Counter section_counter = { 0 } ;
section_counter . counter [ section_counter . nest_level ] = 1 ;
2017-07-10 14:51:19 +00:00
generate_item_html ( out , doc_system , & used_links , doc - > root_item , & section_counter ) ;
2016-11-03 21:37:29 +00:00
}
// BOTTOM