// swad_HTML.c: tables, divs
/*
SWAD (Shared Workspace At a Distance),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
Copyright (C) 1999-2024 Antonio Caņas Vargas
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
#define _GNU_SOURCE // For vasprintf
#include // For va_start, va_end
#include // For vasprintf
#include // For free
#include "swad_alert.h"
#include "swad_error.h"
#include "swad_global.h"
#include "swad_HTML.h"
/*****************************************************************************/
/**************************** Private constants ******************************/
/*****************************************************************************/
static const char *ClassAlign[HTM_NUM_HEAD_ALIGN] =
{
[HTM_HEAD_LEFT ] = "LT",
[HTM_HEAD_CENTER] = "CT",
[HTM_HEAD_RIGHT ] = "RT",
};
/*****************************************************************************/
/************************* Private global variables **************************/
/*****************************************************************************/
static unsigned HTM_TABLE_NestingLevel = 0;
static unsigned HTM_TR_NestingLevel = 0;
static unsigned HTM_TH_NestingLevel = 0;
static unsigned HTM_TD_NestingLevel = 0;
static unsigned HTM_DIV_NestingLevel = 0;
static unsigned HTM_SPAN_NestingLevel = 0;
static unsigned HTM_OL_NestingLevel = 0;
static unsigned HTM_UL_NestingLevel = 0;
static unsigned HTM_LI_NestingLevel = 0;
static unsigned HTM_DL_NestingLevel = 0;
static unsigned HTM_DT_NestingLevel = 0;
static unsigned HTM_DD_NestingLevel = 0;
static unsigned HTM_A_NestingLevel = 0;
static unsigned HTM_SCRIPT_NestingLevel = 0;
static unsigned HTM_FIELDSET_NestingLevel = 0;
static unsigned HTM_LABEL_NestingLevel = 0;
static unsigned HTM_BUTTON_NestingLevel = 0;
static unsigned HTM_TEXTAREA_NestingLevel = 0;
static unsigned HTM_SELECT_NestingLevel = 0;
static unsigned HTM_OPTGROUP_NestingLevel = 0;
static unsigned HTM_STRONG_NestingLevel = 0;
static unsigned HTM_EM_NestingLevel = 0;
static unsigned HTM_U_NestingLevel = 0;
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static void HTM_PutAttributes (HTM_Attributes_t Attributes,
const char *FuncsOnChange); // if not null ==> must include ending ";"
/*****************************************************************************/
/******************************* Begin/end title *****************************/
/*****************************************************************************/
void HTM_TITLE_Begin (void)
{
HTM_Txt ("");
}
void HTM_TITLE_End (void)
{
HTM_Txt ("\n");
}
/*****************************************************************************/
/******************************* Begin/end table *****************************/
/*****************************************************************************/
void HTM_TABLE_Begin (const char *fmt,...)
{
va_list ap;
int NumBytesPrinted;
char *Class;
HTM_Txt ("
",
CellPadding); // CellPadding must be 0, 1, 2, 5, 10, 20
else
HTM_Txt ("
");
HTM_TABLE_NestingLevel++;
}
void HTM_TABLE_End (void)
{
if (HTM_TABLE_NestingLevel == 0) // No TABLE open
Ale_ShowAlert (Ale_ERROR,"Trying to close unopened TABLE.");
HTM_Txt ("
");
HTM_TR_NestingLevel++;
}
void HTM_TR_End (void)
{
if (HTM_TR_NestingLevel == 0) // No TR open
Ale_ShowAlert (Ale_ERROR,"Trying to close unopened TR.");
HTM_Txt ("
");
HTM_TR_NestingLevel--;
}
/*****************************************************************************/
/***************************** Table heading cells ***************************/
/*****************************************************************************/
void HTM_TH (const char *Title,HTM_HeadAlign HeadAlign)
{
HTM_TH_Span (Title,HeadAlign,1,1,NULL);
}
void HTM_TH_Begin (HTM_HeadAlign HeadAlign)
{
HTM_TH_Span_Begin (HeadAlign,1,1,NULL);
}
void HTM_TH_Span (const char *Title,HTM_HeadAlign HeadAlign,
unsigned RowSpan,unsigned ColSpan,
const char *ClassFmt,...)
{
va_list ap;
int NumBytesPrinted;
char *Attr = NULL;
if (ClassFmt)
if (ClassFmt[0])
{
va_start (ap,ClassFmt);
NumBytesPrinted = vasprintf (&Attr,ClassFmt,ap);
va_end (ap);
if (NumBytesPrinted < 0) // -1 if no memory or any other error
Err_NotEnoughMemoryExit ();
}
if (RowSpan > 1 && ColSpan > 1)
{
if (Attr)
HTM_TxtF ("
",
The_GetSuffix (),ClassAlign[HeadAlign]);
}
if (ClassFmt)
if (ClassFmt[0])
free (Attr);
HTM_TH_NestingLevel++;
}
void HTM_TH_End (void)
{
if (HTM_TH_NestingLevel == 0) // No TH open
Ale_ShowAlert (Ale_ERROR,"Trying to close unopened TR.");
HTM_Txt ("
");
HTM_TD_NestingLevel++;
}
void HTM_TD_End (void)
{
if (HTM_TD_NestingLevel == 0) // No TD open
Ale_ShowAlert (Ale_ERROR,"Trying to close unopened TD.");
HTM_Txt ("
");
HTM_DIV_NestingLevel++;
}
void HTM_DIV_End (void)
{
if (HTM_DIV_NestingLevel == 0) // No DIV open
Ale_ShowAlert (Ale_ERROR,"Trying to close unopened DIV.");
HTM_Txt ("
");
HTM_UL_NestingLevel++;
}
void HTM_UL_End (void)
{
if (HTM_UL_NestingLevel == 0) // No UL open
Ale_ShowAlert (Ale_ERROR,"Trying to close unopened UL.");
HTM_Txt ("
");
HTM_LI_NestingLevel++;
}
void HTM_LI_End (void)
{
if (HTM_LI_NestingLevel == 0) // No LI open
Ale_ShowAlert (Ale_ERROR,"Trying to close unopened LI.");
HTM_Txt ("
");
HTM_DL_NestingLevel++;
}
void HTM_DL_End (void)
{
if (HTM_DL_NestingLevel == 0) // No DL open
Ale_ShowAlert (Ale_ERROR,"Trying to close unopened DL.");
HTM_Txt ("
");
HTM_DT_NestingLevel++;
}
void HTM_DT_End (void)
{
if (HTM_DL_NestingLevel == 0) // No DT open
Ale_ShowAlert (Ale_ERROR,"Trying to close unopened DT.");
HTM_Txt ("
");
HTM_DD_NestingLevel++;
}
void HTM_DD_End (void)
{
if (HTM_DD_NestingLevel == 0) // No DD open
Ale_ShowAlert (Ale_ERROR,"Trying to close unopened DD.");
HTM_Txt ("