Version 15.212

This commit is contained in:
Antonio Cañas Vargas 2016-05-30 14:27:10 +02:00
parent 031dc19e13
commit 05ba149c14
8 changed files with 372 additions and 243 deletions

View File

@ -133,18 +133,25 @@
// TODO: List exam announcement as a list, like assignments. When clicking on an announcement, it will be shown alone, as now.
// TODO: Check value returned by setlocale in all calls
// TODO: Write "Tab > Action" in title of text in most frequent actions
// TODO: Fix bug in copy-paste from Briefcase to another file browser
// TODO: Fix bug: Asignatura: Arquitectura de Computadores, Crear ZIP de todos los trabajos del grupo C3
// TODO: Fix bug: se oculta el único descriptor de unas preguntas de test, y luego se renombra dicho descriptor --> el descriptor desaparece
// TODO: Fix bug: Student cant not see their test results
// TODO: Fix bug: button "Add a new question" in test should not be available for students
/*****************************************************************************/
/****************************** Public constants *****************************/
/*****************************************************************************/
#define Log_PLATFORM_VERSION "SWAD 15.211.2 (2016-05-13)"
#define Log_PLATFORM_VERSION "SWAD 15.212 (2016-05-30)"
#define CSS_FILE "swad15.210.css"
#define JS_FILE "swad15.197.js"
// Number of lines (includes comments but not blank lines) has been got with the following command:
// nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*.h sql/swad*.sql | tail -1
/*
Version 15.212: May 30, 2016 Fixed bug in edition of syllabus, reported by Raymon Moreno Colina and Javier Fernández Baldomero.
Code refactoring related to course info. (201471 lines)
Version 15.211.2: May 13, 2016 Fixed bug in test questions, reported by Nuria Torres Rosell. (201394 lines)
Version 15.211.1: May 07, 2016 Files in briefcase older than 1 year are removed automatically. (201397 lines)
Version 15.211: May 07, 2016 Code refactoring related to removing old files in briefcase.

View File

@ -860,8 +860,6 @@ void Deg_WriteBigNameCtyInsCtrDegCrs (void)
void Deg_InitCurrentCourse (void)
{
unsigned NumInfoType;
/***** If numerical course code is available, get course data *****/
if (Gbl.CurrentCrs.Crs.CrsCod > 0)
{
@ -978,17 +976,6 @@ void Deg_InitCurrentCourse (void)
sprintf (Gbl.CurrentCrs.PathURLPubl,"%s/%s/%ld",
Cfg_HTTPS_URL_SWAD_PUBLIC,Cfg_FOLDER_CRS,Gbl.CurrentCrs.Crs.CrsCod);
/***** Paths to files with URL or HTML for theory, practices, etc. of the course *****/
for (NumInfoType = 0;
NumInfoType < Inf_NUM_INFO_TYPES;
NumInfoType++)
{
sprintf (Gbl.CurrentCrs.Info.Links[NumInfoType].PathRelFileURL,"%s/%s.url",Gbl.CurrentCrs.PathPriv ,Inf_FileNamesForInfoType[NumInfoType]);
sprintf (Gbl.CurrentCrs.Info.Links[NumInfoType].PathRelFileZIP,"%s/%s.zip",Gbl.CurrentCrs.PathPriv ,Inf_FileNamesForInfoType[NumInfoType]);
sprintf (Gbl.CurrentCrs.Info.Links[NumInfoType].PathRelWebPage,"%s/%s" ,Gbl.CurrentCrs.PathRelPubl,Inf_FileNamesForInfoType[NumInfoType]);
sprintf (Gbl.CurrentCrs.Info.Links[NumInfoType].URLWebPage ,"%s/%s" ,Gbl.CurrentCrs.PathURLPubl,Inf_FileNamesForInfoType[NumInfoType]);
}
/***** If any of the course directories does not exist, create it *****/
if (!Fil_CheckIfPathExists (Gbl.CurrentCrs.PathPriv))
Fil_CreateDirIfNotExists (Gbl.CurrentCrs.PathPriv);

View File

@ -456,14 +456,6 @@ struct Globals
struct
{
Inf_InfoType_t Type;
struct
{
char URL[Cns_MAX_BYTES_URL+1]; // URL
char PathRelFileURL [PATH_MAX+1]; // Relative path to a text file of texto containing the URL
char PathRelFileZIP [PATH_MAX+1]; // Relative path to a file ZIP with the complete web page
char PathRelWebPage [PATH_MAX+1]; // Relative path to a public directory with a complete web page
char URLWebPage [PATH_MAX+1]; // URL of a web page
} Links[Inf_NUM_INFO_TYPES];
char URL[Cns_MAX_BYTES_URL+1];
bool MustBeRead[Inf_NUM_INFO_TYPES]; // Students must read info?
bool ShowMsgMustBeRead;

View File

@ -289,15 +289,28 @@ static bool Inf_GetIfIHaveReadFromForm (void);
static void Inf_SetForceReadIntoDB (bool MustBeRead);
static void Inf_SetIHaveReadIntoDB (bool IHaveRead);
static void Inf_CheckAndShowPage (void);
static void Inf_CheckAndShowURL (void);
static bool Inf_CheckPage (long CrsCod,Inf_InfoType_t InfoType);
static bool Inf_CheckAndShowPage (void);
static void Inf_BuildPathPage (long CrsCod,Inf_InfoType_t InfoType,char *PathDir);
static bool Inf_CheckURL (long CrsCod,Inf_InfoType_t InfoType);
static bool Inf_CheckAndShowURL (void);
static void Inf_BuildPathURL (long CrsCod,Inf_InfoType_t InfoType,char *PathFile);
static void Inf_ShowPage (const char *URL);
static bool Inf_CheckIfInfoAvailable (Inf_InfoSrc_t InfoSrc);
static Inf_InfoType_t Inf_AsignInfoType (void);
static void Inf_SetInfoTxtIntoDB (const char *InfoTxtHTML,const char *InfoTxtMD);
static void Inf_GetInfoTxtFromDB (char *InfoTxtHTML,char *InfoTxtMD,size_t MaxLength);
static bool Inf_CheckIfInfoTxtIsNotEmpty (long CrsCod,Inf_InfoType_t InfoType);
static void Inf_ShowPlainTxtInfo (void);
static void Inf_ShowRichTxtInfo (void);
static void Inf_GetInfoTxtFromDB (long CrsCod,Inf_InfoType_t InfoType,
char *InfoTxtHTML,char *InfoTxtMD,
size_t MaxLength);
static bool Inf_CheckPlainTxt (long CrsCod,Inf_InfoType_t InfoType);
static bool Inf_CheckAndShowPlainTxt (void);
static bool Inf_CheckRichTxt (long CrsCod,Inf_InfoType_t InfoType);
static bool Inf_CheckAndShowRichTxt (void);
/*****************************************************************************/
/******** Show course info (theory, practices, bibliography, etc.) ***********/
@ -356,7 +369,7 @@ void Inf_ShowInfo (void)
{
case Inf_LECTURES:
case Inf_PRACTICALS:
Syl_EditSyllabus ();
ShowWarningNoInfo = !Syl_CheckAndEditSyllabus ();
break;
case Inf_INTRODUCTION:
case Inf_TEACHING_GUIDE:
@ -369,18 +382,18 @@ void Inf_ShowInfo (void)
}
break;
case Inf_INFO_SRC_PLAIN_TEXT:
Inf_ShowPlainTxtInfo ();
ShowWarningNoInfo = !Inf_CheckAndShowPlainTxt ();
break;
case Inf_INFO_SRC_RICH_TEXT:
Inf_ShowRichTxtInfo ();
ShowWarningNoInfo = !Inf_CheckAndShowRichTxt ();
break;
case Inf_INFO_SRC_PAGE:
/***** Open file with web page *****/
Inf_CheckAndShowPage ();
ShowWarningNoInfo = !Inf_CheckAndShowPage ();
break;
case Inf_INFO_SRC_URL:
/***** Check if file with URL exists *****/
Inf_CheckAndShowURL ();
ShowWarningNoInfo = !Inf_CheckAndShowURL ();
break;
}
@ -713,46 +726,90 @@ void Inf_RemoveUsrFromCrsInfoRead (long UsrCod,long CrsCod)
DB_QueryDELETE (Query,"can not set that I have not read course info");
}
/*****************************************************************************/
/************************** Check if exists a page ***************************/
/*****************************************************************************/
// Return true if info available
static bool Inf_CheckPage (long CrsCod,Inf_InfoType_t InfoType)
{
char PathRelDirHTML[PATH_MAX+1];
char PathRelFileHTML[PATH_MAX+1];
// TODO !!!!!!!!!!!! If the page is hosted in server ==> it should be created a temporary public directory
// and host the page in a private directory !!!!!!!!!!!!!!!!!
/***** Build path of directory containing web page *****/
Inf_BuildPathPage (CrsCod,InfoType,PathRelDirHTML);
/***** Open file with web page *****/
/* 1. Check if index.html exists */
sprintf (PathRelFileHTML,"%s/index.html",PathRelDirHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty?
return true;
/* 2. If index.html does not exist, try index.htm */
sprintf (PathRelFileHTML,"%s/index.htm",PathRelDirHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty?
return true;
return false;
}
/*****************************************************************************/
/**************** Check if exists and show link to a page ********************/
/*****************************************************************************/
// Return true if info available
static void Inf_CheckAndShowPage (void)
static bool Inf_CheckAndShowPage (void)
{
extern const char *Txt_No_information;
const char *FileNameHTML;
char PathRelDirHTML[PATH_MAX+1];
char PathRelFileHTML[PATH_MAX+1];
char URL[PATH_MAX+1];
// TODO !!!!!!!!!!!! If the page is hosted in server ==> it should be created a temporary public directory
// and host the page in a private directory !!!!!!!!!!!!!!!!!
/***** Build path of directory containing web page *****/
Inf_BuildPathPage (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathRelDirHTML);
/***** Open file with web page *****/
/* 1. Check if index.html exists */
FileNameHTML = "index.html";
sprintf (PathRelFileHTML,"%s/%s",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage,FileNameHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML))
sprintf (PathRelFileHTML,"%s/index.html",PathRelDirHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty?
{
sprintf (URL,"%s/%s",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].URLWebPage,FileNameHTML);
sprintf (URL,"%s/%s/%ld/%s/index.html",
Cfg_HTTPS_URL_SWAD_PUBLIC,Cfg_FOLDER_CRS,Gbl.CurrentCrs.Crs.CrsCod,
Inf_FileNamesForInfoType[Gbl.CurrentCrs.Info.Type]);
Inf_ShowPage (URL);
return true;
}
else
/* 2. If index.html does not exist, try index.htm */
sprintf (PathRelFileHTML,"%s/index.htm",PathRelDirHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty?
{
/* 2. If index.html not exists, try index.htm */
FileNameHTML = "index.htm";
sprintf (PathRelFileHTML,"%s/%s",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage,FileNameHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML))
{
sprintf (URL,"%s/%s",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].URLWebPage,FileNameHTML);
Inf_ShowPage (URL);
}
else
Lay_ShowAlert (Lay_INFO,Txt_No_information);
sprintf (URL,"%s/%s/%ld/%s/index.htm",
Cfg_HTTPS_URL_SWAD_PUBLIC,Cfg_FOLDER_CRS,Gbl.CurrentCrs.Crs.CrsCod,
Inf_FileNamesForInfoType[Gbl.CurrentCrs.Info.Type]);
Inf_ShowPage (URL);
return true;
}
return false;
}
/*****************************************************************************/
/* Build path inside a course for a given a info type to store web page file */
/*****************************************************************************/
static void Inf_BuildPathPage (long CrsCod,Inf_InfoType_t InfoType,char *PathDir)
{
sprintf (PathDir,"%s/%s/%ld/%s",
Cfg_PATH_SWAD_PUBLIC,Cfg_FOLDER_CRS,CrsCod,
Inf_FileNamesForInfoType[InfoType]);
}
/*****************************************************************************/
@ -762,6 +819,7 @@ static void Inf_CheckAndShowPage (void)
int Inf_WritePageIntoHTMLBuffer (char **HTMLBuffer)
{
char PathRelDirHTML[PATH_MAX+1];
char PathRelFileHTML[PATH_MAX+1];
FILE *FileHTML;
bool FileExists = false;
@ -770,18 +828,19 @@ int Inf_WritePageIntoHTMLBuffer (char **HTMLBuffer)
/***** Initialize buffer *****/
*HTMLBuffer = NULL;
/***** Build path of directory containing web page *****/
Inf_BuildPathPage (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathRelDirHTML);
/***** Open file with web page *****/
/* 1. Check if index.html exists */
sprintf (PathRelFileHTML,"%s/index.html",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage);
if (Fil_CheckIfPathExists (PathRelFileHTML))
sprintf (PathRelFileHTML,"%s/index.html",PathRelDirHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty?
FileExists = true;
else
{
/* 2. If index.html not exists, try index.htm */
sprintf (PathRelFileHTML,"%s/index.htm",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage);
if (Fil_CheckIfPathExists (PathRelFileHTML))
sprintf (PathRelFileHTML,"%s/index.htm",PathRelDirHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty?
FileExists = true;
}
@ -825,28 +884,73 @@ int Inf_WritePageIntoHTMLBuffer (char **HTMLBuffer)
}
/*****************************************************************************/
/**************** Check if exists and show link to a page ********************/
/********************* Check if exists link to a page ************************/
/*****************************************************************************/
// Return true if info available
static void Inf_CheckAndShowURL (void)
static bool Inf_CheckURL (long CrsCod,Inf_InfoType_t InfoType)
{
extern const char *Txt_No_information;
char PathFile[PATH_MAX+1];
FILE *FileURL;
/***** Build path to file containing URL *****/
Inf_BuildPathURL (CrsCod,InfoType,PathFile);
/***** Check if file with URL exists *****/
if ((FileURL = fopen (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileURL ,"rb")))
if ((FileURL = fopen (PathFile,"rb")))
{
if (fgets (Gbl.CurrentCrs.Info.URL,Cns_MAX_BYTES_URL,FileURL) == NULL)
Gbl.CurrentCrs.Info.URL[0] = '\0';
/* File is not longer needed ==> close it */
fclose (FileURL);
if (Gbl.CurrentCrs.Info.URL[0])
Inf_ShowPage (Gbl.CurrentCrs.Info.URL);
else
Lay_ShowAlert (Lay_INFO,Txt_No_information);
return true;
}
else
Lay_ShowAlert (Lay_INFO,Txt_No_information);
return false;
}
/*****************************************************************************/
/**************** Check if exists and show link to a page ********************/
/*****************************************************************************/
// Return true if info available
static bool Inf_CheckAndShowURL (void)
{
char PathFile[PATH_MAX+1];
FILE *FileURL;
/***** Build path to file containing URL *****/
Inf_BuildPathURL (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathFile);
/***** Check if file with URL exists *****/
if ((FileURL = fopen (PathFile,"rb")))
{
if (fgets (Gbl.CurrentCrs.Info.URL,Cns_MAX_BYTES_URL,FileURL) == NULL)
Gbl.CurrentCrs.Info.URL[0] = '\0';
/* File is not longer needed ==> close it */
fclose (FileURL);
if (Gbl.CurrentCrs.Info.URL[0])
{
Inf_ShowPage (Gbl.CurrentCrs.Info.URL);
return true;
}
}
return false;
}
/*****************************************************************************/
/*** Build path inside a course for a given a info type to store URL file ****/
/*****************************************************************************/
static void Inf_BuildPathURL (long CrsCod,Inf_InfoType_t InfoType,char *PathFile)
{
sprintf (PathFile,"%s/%s/%ld/%s.url",
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_CRS,CrsCod,
Inf_FileNamesForInfoType[InfoType]);
}
/*****************************************************************************/
@ -856,13 +960,17 @@ static void Inf_CheckAndShowURL (void)
void Inf_WriteURLIntoTxtBuffer (char TxtBuffer[Cns_MAX_BYTES_URL+1])
{
char PathFile[PATH_MAX+1];
FILE *FileURL;
/***** Initialize buffer *****/
TxtBuffer[0] = '\0';
/***** Build path to file containing URL *****/
Inf_BuildPathURL (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathFile);
/***** Check if file with URL exists *****/
if ((FileURL = fopen (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileURL,"rb")))
if ((FileURL = fopen (PathFile,"rb")))
{
if (fgets (TxtBuffer,Cns_MAX_BYTES_URL,FileURL) == NULL)
TxtBuffer[0] = '\0';
@ -929,14 +1037,30 @@ void Inf_FormsToSelSendInfo (void)
extern const char *Txt_INFO_SRC_HELP[Inf_NUM_INFO_SOURCES];
Inf_InfoSrc_t InfoSrc;
Inf_InfoSrc_t InfoSrcSelected;
bool InfoAvailable[Inf_NUM_INFO_SOURCES];
bool MustBeRead;
/***** Set info type *****/
Gbl.CurrentCrs.Info.Type = Inf_AsignInfoType ();
/***** Get info source from database *****/
/***** Get current info source from database *****/
Inf_GetInfoSrcFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,&InfoSrcSelected,&MustBeRead);
/***** Check if info available *****/
for (InfoSrc = (Inf_InfoSrc_t) 0;
InfoSrc < Inf_NUM_INFO_SOURCES;
InfoSrc++)
InfoAvailable[InfoSrc] = Inf_CheckIfInfoAvailable (InfoSrc);
/***** Set info source to none
when no info available for the current source *****/
if (InfoSrcSelected != Inf_INFO_SRC_NONE &&
!InfoAvailable[InfoSrcSelected])
{
InfoSrcSelected = Inf_INFO_SRC_NONE;
Inf_SetInfoSrcIntoDB (Inf_INFO_SRC_NONE);
}
/***** Form to choice between alternatives *****/
/* Start of table */
Lay_StartRoundFrameTable (NULL,4,Txt_Source_of_information);
@ -957,8 +1081,16 @@ void Inf_FormsToSelSendInfo (void)
(unsigned) InfoSrc);
if (InfoSrc == InfoSrcSelected)
fprintf (Gbl.F.Out," checked=\"checked\"");
fprintf (Gbl.F.Out," onclick=\"document.getElementById('%s').submit();\" />",
Gbl.Form.Id);
else
{
if (InfoSrc == Inf_INFO_SRC_NONE ||
InfoAvailable[InfoSrc]) // If no info available for this source
fprintf (Gbl.F.Out," onclick=\"document.getElementById('%s').submit();\"",
Gbl.Form.Id);
else
fprintf (Gbl.F.Out," disabled=\"disabled\"");
}
fprintf (Gbl.F.Out," />");
Act_FormEnd ();
fprintf (Gbl.F.Out,"</td>");
@ -982,6 +1114,43 @@ void Inf_FormsToSelSendInfo (void)
Lay_EndRoundFrameTable ();
}
/*****************************************************************************/
/* Check if there is info available for current info type and a given source */
/*****************************************************************************/
static bool Inf_CheckIfInfoAvailable (Inf_InfoSrc_t InfoSrc)
{
switch (InfoSrc)
{
case Inf_INFO_SRC_NONE:
return false;
case Inf_INFO_SRC_EDITOR:
switch (Gbl.CurrentCrs.Info.Type)
{
case Inf_LECTURES:
case Inf_PRACTICALS:
return Syl_CheckSyllabus ();
default:
return false;
}
return false; // Not reached
case Inf_INFO_SRC_PLAIN_TEXT:
return Inf_CheckPlainTxt (Gbl.CurrentCrs.Crs.CrsCod,
Gbl.CurrentCrs.Info.Type);
case Inf_INFO_SRC_RICH_TEXT:
return Inf_CheckRichTxt (Gbl.CurrentCrs.Crs.CrsCod,
Gbl.CurrentCrs.Info.Type);
case Inf_INFO_SRC_PAGE:
return Inf_CheckPage (Gbl.CurrentCrs.Crs.CrsCod,
Gbl.CurrentCrs.Info.Type);
case Inf_INFO_SRC_URL:
return Inf_CheckURL (Gbl.CurrentCrs.Crs.CrsCod,
Gbl.CurrentCrs.Info.Type);
}
return false; // Not reached
}
/*****************************************************************************/
/****************** Form to enter in integrated editor ***********************/
/*****************************************************************************/
@ -1064,8 +1233,12 @@ void Inf_FormToSendURL (Inf_InfoSrc_t InfoSrc)
extern const char *The_ClassForm[The_NUM_THEMES];
extern const char *Txt_URL;
extern const char *Txt_Send_URL;
char PathFile[PATH_MAX+1];
FILE *FileURL;
/***** Build path to file containing URL *****/
Inf_BuildPathURL (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathFile);
/***** Start form *****/
Act_FormStart (Inf_ActionsInfo[InfoSrc][Gbl.CurrentCrs.Info.Type]);
@ -1079,7 +1252,7 @@ void Inf_FormToSendURL (Inf_InfoSrc_t InfoSrc)
"<input type=\"text\" name=\"InfoSrcURL\""
" size=\"50\" maxlength=\"256\" value=\"",
The_ClassForm[Gbl.Prefs.Theme],Txt_URL);
if ((FileURL = fopen (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileURL,"rb")) == NULL)
if ((FileURL = fopen (PathFile,"rb")) == NULL)
fprintf (Gbl.F.Out,"http://");
else
{
@ -1293,9 +1466,6 @@ void Inf_GetInfoSrcFromDB (long CrsCod,Inf_InfoType_t InfoType,
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
char PathFile[PATH_MAX+1];
FILE *File;
char URL[Cns_MAX_BYTES_URL+1];
/***** Set default values *****/
*InfoSrc = Inf_INFO_SRC_NONE;
@ -1338,13 +1508,7 @@ void Inf_GetInfoSrcFromDB (long CrsCod,Inf_InfoType_t InfoType,
{
case Inf_LECTURES:
case Inf_PRACTICALS:
/***** Check if file exists *****/
sprintf (PathFile,"%s/%s/%ld/%s/%s",
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_CRS,CrsCod,
InfoType == Inf_LECTURES ? Cfg_SYLLABUS_FOLDER_LECTURES :
Cfg_SYLLABUS_FOLDER_PRACTICALS,
Cfg_SYLLABUS_FILENAME);
if (!Fil_CheckIfPathExists (PathFile)) // Should be XML file checked for items!!!!
if (!Syl_CheckSyllabus ())
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
@ -1362,57 +1526,32 @@ void Inf_GetInfoSrcFromDB (long CrsCod,Inf_InfoType_t InfoType,
}
break;
case Inf_INFO_SRC_PLAIN_TEXT:
if (!Inf_CheckIfInfoTxtIsNotEmpty (CrsCod,InfoType))
if (!Inf_CheckPlainTxt (CrsCod,InfoType))
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
}
break;
case Inf_INFO_SRC_RICH_TEXT:
if (!Inf_CheckIfInfoTxtIsNotEmpty (CrsCod,InfoType))
if (!Inf_CheckRichTxt (CrsCod,InfoType))
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
}
break;
case Inf_INFO_SRC_PAGE:
/***** Check if file with web page exists *****/
sprintf (PathFile,"%s/%s/%ld/%s/index.html",
Cfg_PATH_SWAD_PUBLIC,Cfg_FOLDER_CRS,CrsCod,Inf_FileNamesForInfoType[InfoType]);
if (!Fil_CheckIfPathExists (PathFile))
{
// If index.html not exists, try index.htm
sprintf (PathFile,"%s/%s/%ld/%s/index.htm",
Cfg_PATH_SWAD_PUBLIC,Cfg_FOLDER_CRS,CrsCod,Inf_FileNamesForInfoType[InfoType]);
if (!Fil_CheckIfPathExists (PathFile))
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
}
}
if (!Inf_CheckPage (CrsCod,InfoType))
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
}
break;
case Inf_INFO_SRC_URL:
/***** Check if URL in file is empty or not *****/
sprintf (PathFile,"%s/%s/%ld/%s.url",
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_CRS,CrsCod,Inf_FileNamesForInfoType[InfoType]);
File = fopen (PathFile,"rb");
if (File)
{
if (fgets (URL,Cns_MAX_BYTES_URL,File) == NULL)
URL[0] = '\0';
/* File is not longer needed ==> close it */
fclose (File);
if (!URL[0])
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
}
}
else
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
}
if (!Inf_CheckURL (CrsCod,InfoType))
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
}
break;
}
}
@ -1473,7 +1612,9 @@ static void Inf_SetInfoTxtIntoDB (const char *InfoTxtHTML,const char *InfoTxtMD)
/********** Get info text for a type of course info from database ************/
/*****************************************************************************/
static void Inf_GetInfoTxtFromDB (char *InfoTxtHTML,char *InfoTxtMD,size_t MaxLength)
static void Inf_GetInfoTxtFromDB (long CrsCod,Inf_InfoType_t InfoType,
char *InfoTxtHTML,char *InfoTxtMD,
size_t MaxLength)
{
char Query[512];
MYSQL_RES *mysql_res;
@ -1484,7 +1625,7 @@ static void Inf_GetInfoTxtFromDB (char *InfoTxtHTML,char *InfoTxtMD,size_t MaxLe
(bibliography, FAQ, links or evaluation) from database *****/
sprintf (Query,"SELECT InfoTxtHTML,InfoTxtMD FROM crs_info_txt"
" WHERE CrsCod='%ld' AND InfoType='%s'",
Gbl.CurrentCrs.Crs.CrsCod,Inf_NamesInDBForInfoType[Gbl.CurrentCrs.Info.Type]);
CrsCod,Inf_NamesInDBForInfoType[InfoType]);
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get info text");
/***** The result of the query must have one row or none *****/
@ -1523,54 +1664,35 @@ static void Inf_GetInfoTxtFromDB (char *InfoTxtHTML,char *InfoTxtMD,size_t MaxLe
}
/*****************************************************************************/
/*** Check if info text for a type of course info is not empty in database ***/
/********************* Check information about the course ********************/
/*****************************************************************************/
// Return true if info available
static bool Inf_CheckIfInfoTxtIsNotEmpty (long CrsCod,Inf_InfoType_t InfoType)
static bool Inf_CheckPlainTxt (long CrsCod,Inf_InfoType_t InfoType)
{
char Query[512];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
bool Result;
char TxtHTML[Cns_MAX_BYTES_LONG_TEXT+1];
/***** Get info source for a specific type of course information
(bibliography, FAQ, links or evaluation) from database *****/
sprintf (Query,"SELECT InfoTxtHTML FROM crs_info_txt"
" WHERE CrsCod='%ld' AND InfoType='%s'",
CrsCod,Inf_NamesInDBForInfoType[InfoType]);
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get info text");
/***** Get info text from database *****/
Inf_GetInfoTxtFromDB (CrsCod,InfoType,TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT);
/***** The result of the query must have one row or none *****/
if (NumRows == 1)
{
/* Get info text */
row = mysql_fetch_row (mysql_res);
Result = (row[0][0] != '\0'); // Is text empty?
}
else
Result = false;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return Result;
return (TxtHTML[0] != '\0');
}
/*****************************************************************************/
/********************* Show information about the course *********************/
/*****************************************************************************/
// Return true if info available
static void Inf_ShowPlainTxtInfo (void)
static bool Inf_CheckAndShowPlainTxt (void)
{
extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES];
extern const char *Txt_No_information;
char TxtHTML[Cns_MAX_BYTES_LONG_TEXT+1];
bool ICanEdit = (Gbl.Usrs.Me.LoggedRole == Rol_TEACHER ||
Gbl.Usrs.Me.LoggedRole == Rol_SYS_ADM);
/***** Get info text from database *****/
Inf_GetInfoTxtFromDB (TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT);
Inf_GetInfoTxtFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,
TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT);
if (TxtHTML[0])
{
@ -1596,19 +1718,38 @@ static void Inf_ShowPlainTxtInfo (void)
/***** End frame *****/
fprintf (Gbl.F.Out,"</div>");
Lay_EndRoundFrame ();
return true;
}
else
Lay_ShowAlert (Lay_INFO,Txt_No_information);
return false;
}
/*****************************************************************************/
/********************* Show information about the course *********************/
/*****************************************************************************/
// Return true if info available
static void Inf_ShowRichTxtInfo (void)
static bool Inf_CheckRichTxt (long CrsCod,Inf_InfoType_t InfoType)
{
char TxtHTML[Cns_MAX_BYTES_LONG_TEXT+1];
char TxtMD[Cns_MAX_BYTES_LONG_TEXT+1];
/***** Get info text from database *****/
Inf_GetInfoTxtFromDB (CrsCod,InfoType,
TxtHTML,TxtMD,Cns_MAX_BYTES_LONG_TEXT);
return (TxtMD[0] != '\0');
}
/*****************************************************************************/
/********************* Show information about the course *********************/
/*****************************************************************************/
// Return true if info available
static bool Inf_CheckAndShowRichTxt (void)
{
extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES];
extern const char *Txt_No_information;
char TxtHTML[Cns_MAX_BYTES_LONG_TEXT+1];
char TxtMD[Cns_MAX_BYTES_LONG_TEXT+1];
char PathFileMD[PATH_MAX+1];
@ -1622,7 +1763,8 @@ static void Inf_ShowRichTxtInfo (void)
Gbl.Usrs.Me.LoggedRole == Rol_SYS_ADM);
/***** Get info text from database *****/
Inf_GetInfoTxtFromDB (TxtHTML,TxtMD,Cns_MAX_BYTES_LONG_TEXT);
Inf_GetInfoTxtFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,
TxtHTML,TxtMD,Cns_MAX_BYTES_LONG_TEXT);
if (TxtMD[0])
{
@ -1697,9 +1839,11 @@ static void Inf_ShowRichTxtInfo (void)
/***** End frame *****/
fprintf (Gbl.F.Out,"</div>");
Lay_EndRoundFrame ();
return true;
}
else
Lay_ShowAlert (Lay_INFO,Txt_No_information);
return false;
}
/*****************************************************************************/
@ -1720,7 +1864,8 @@ int Inf_WritePlainTextIntoHTMLBuffer (char **HTMLBuffer)
*HTMLBuffer = NULL;
/***** Get info text from database *****/
Inf_GetInfoTxtFromDB (TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT);
Inf_GetInfoTxtFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,
TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT);
if (TxtHTML[0])
{
@ -1817,7 +1962,8 @@ void Inf_EditPlainTxtInfo (void)
Lay_WriteHeaderClassPhoto (false,false,Gbl.CurrentIns.Ins.InsCod,Gbl.CurrentDeg.Deg.DegCod,Gbl.CurrentCrs.Crs.CrsCod);
/***** Get info text from database *****/
Inf_GetInfoTxtFromDB (TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT);
Inf_GetInfoTxtFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,
TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT);
/***** Edition area *****/
fprintf (Gbl.F.Out,"<div class=\"CENTER_MIDDLE\">");
@ -1855,7 +2001,8 @@ void Inf_EditRichTxtInfo (void)
Lay_WriteHeaderClassPhoto (false,false,Gbl.CurrentIns.Ins.InsCod,Gbl.CurrentDeg.Deg.DegCod,Gbl.CurrentCrs.Crs.CrsCod);
/***** Get info text from database *****/
Inf_GetInfoTxtFromDB (TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT);
Inf_GetInfoTxtFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,
TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT);
/***** Edition area *****/
fprintf (Gbl.F.Out,"<div class=\"CENTER_MIDDLE\">");
@ -1948,6 +2095,7 @@ void Inf_RecAndChangeRichTxtInfo (void)
void Inf_ReceiveURLInfo (void)
{
extern const char *Txt_The_URL_X_has_been_updated;
char PathFile[PATH_MAX+1];
FILE *FileURL;
bool URLIsOK = false;
@ -1957,8 +2105,11 @@ void Inf_ReceiveURLInfo (void)
/***** Get parameter with URL *****/
Par_GetParToText ("InfoSrcURL",Gbl.CurrentCrs.Info.URL,Cns_MAX_BYTES_URL);
/***** Build path to file containing URL *****/
Inf_BuildPathURL (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathFile);
/***** Open file with URL *****/
if ((FileURL = fopen (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileURL,"wb")) != NULL)
if ((FileURL = fopen (PathFile,"wb")) != NULL)
{
/***** Write URL *****/
fprintf (FileURL,"%s",Gbl.CurrentCrs.Info.URL);
@ -2009,10 +2160,11 @@ void Inf_ReceivePagInfo (void)
extern const char *Txt_The_file_type_should_be_HTML_or_ZIP;
struct Param *Param;
char SourceFileName[PATH_MAX+1];
char PathRelDirHTML[PATH_MAX+1];
char PathRelFileHTML[PATH_MAX+1];
char PathRelFileZIP[PATH_MAX+1];
char MIMEType[Brw_MAX_BYTES_MIME_TYPE+1];
char StrUnzip[100+PATH_MAX*2+1];
char *PathWebPage;
bool WrongType = false;
bool FileIsOK = false;
@ -2041,14 +2193,16 @@ void Inf_ReceivePagInfo (void)
}
else
{
/***** Build path of directory containing web page *****/
Inf_BuildPathPage (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,PathRelDirHTML);
/***** End the reception of the data *****/
PathWebPage = Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage;
if (Str_FileIs (SourceFileName,"html") ||
Str_FileIs (SourceFileName,"htm" )) // .html or .htm file
{
Brw_RemoveTree (PathWebPage);
Fil_CreateDirIfNotExists (PathWebPage);
sprintf (PathRelFileHTML,"%s/index.html",PathWebPage);
Brw_RemoveTree (PathRelDirHTML);
Fil_CreateDirIfNotExists (PathRelDirHTML);
sprintf (PathRelFileHTML,"%s/index.html",PathRelDirHTML);
if (Fil_EndReceptionOfFile (PathRelFileHTML,Param))
{
Lay_ShowAlert (Lay_SUCCESS,Txt_The_HTML_file_has_been_received_successfully);
@ -2059,19 +2213,23 @@ void Inf_ReceivePagInfo (void)
}
else if (Str_FileIs (SourceFileName,"zip")) // .zip file
{
Brw_RemoveTree (PathWebPage);
Fil_CreateDirIfNotExists (PathWebPage);
if (Fil_EndReceptionOfFile (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileZIP,Param))
Brw_RemoveTree (PathRelDirHTML);
Fil_CreateDirIfNotExists (PathRelDirHTML);
sprintf (PathRelFileZIP,"%s/%s.zip",
Gbl.CurrentCrs.PathPriv,
Inf_FileNamesForInfoType[Gbl.CurrentCrs.Info.Type]);
if (Fil_EndReceptionOfFile (PathRelFileZIP,Param))
{
Lay_ShowAlert (Lay_SUCCESS,Txt_The_ZIP_file_has_been_received_successfully);
/* Uncompress ZIP */
sprintf (StrUnzip,"unzip -qq -o %s -d %s",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileZIP,PathWebPage);
PathRelFileZIP,PathRelDirHTML);
if (system (StrUnzip) == 0)
{
/* Check if uploaded file is index.html or index.htm */
sprintf (PathRelFileHTML,"%s/index.html",PathWebPage);
sprintf (PathRelFileHTML,"%s/index.html",PathRelDirHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML))
{
Lay_ShowAlert (Lay_SUCCESS,Txt_The_ZIP_file_has_been_unzipped_successfully);
@ -2080,7 +2238,7 @@ void Inf_ReceivePagInfo (void)
}
else
{
sprintf (PathRelFileHTML,"%s/index.htm",PathWebPage);
sprintf (PathRelFileHTML,"%s/index.htm",PathRelDirHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML))
{
Lay_ShowAlert (Lay_SUCCESS,Txt_The_ZIP_file_has_been_unzipped_successfully);

View File

@ -173,17 +173,30 @@ void Syl_GetParamItemNumber (void)
Lay_ShowErrorAndExit ("Item is missing.");
}
/*****************************************************************************/
/********************** Check if syllabus is not empty ***********************/
/*****************************************************************************/
// Return true if info available
bool Syl_CheckSyllabus (void)
{
/***** Set syllabus type and load syllabus from XML file to memory *****/
Syl_SetSyllabusTypeAndLoadToMemory ();
/***** Start frame *****/
return (LstItemsSyllabus.NumItems != 0);
}
/*****************************************************************************/
/****************************** Edit a syllabus ******************************/
/*****************************************************************************/
// Return true if info available
void Syl_EditSyllabus (void)
bool Syl_CheckAndEditSyllabus (void)
{
extern const Act_Action_t Inf_ActionsSeeInfo[Inf_NUM_INFO_TYPES];
extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES];
extern const char *Txt_Done;
extern const char *Txt_The_syllabus_lectures_of_the_course_X_is_not_available;
extern const char *Txt_The_syllabus_practicals_of_the_course_X_is_not_available;
bool ICanEdit;
bool PutIconToEdit;
@ -194,15 +207,16 @@ void Syl_EditSyllabus (void)
Gbl.Action.Act == ActEditorSylPra)
Gbl.CurrentCrs.Syllabus.EditionIsActive = true;
/***** Start frame *****/
if (Gbl.CurrentCrs.Syllabus.EditionIsActive || LstItemsSyllabus.NumItems)
{
/***** Start frame *****/
ICanEdit = Gbl.Usrs.Me.LoggedRole == Rol_TEACHER ||
Gbl.Usrs.Me.LoggedRole == Rol_SYS_ADM;
Gbl.Usrs.Me.LoggedRole == Rol_SYS_ADM;
PutIconToEdit = ICanEdit && !Gbl.CurrentCrs.Syllabus.EditionIsActive;
Lay_StartRoundFrame (NULL,Txt_INFO_TITLE[Gbl.CurrentCrs.Info.Type],
PutIconToEdit ? Inf_PutIconToEditInfo :
NULL);
PutIconToEdit ? Inf_PutIconToEditInfo :
NULL);
fprintf (Gbl.F.Out,"<table class=\"FRAME_TABLE CELLS_PAD_1\">");
/***** Write the current syllabus *****/
@ -225,15 +239,21 @@ void Syl_EditSyllabus (void)
/***** End frame *****/
Lay_EndRoundFrame ();
return true;
}
else
{
sprintf (Gbl.Message,
Gbl.CurrentCrs.Info.Type == Inf_LECTURES ? Txt_The_syllabus_lectures_of_the_course_X_is_not_available :
Txt_The_syllabus_practicals_of_the_course_X_is_not_available,
Gbl.CurrentCrs.Crs.FullName);
Lay_ShowAlert (Lay_WARNING,Gbl.Message);
}
return false;
}
/*****************************************************************************/
/****************************** Edit a syllabus ******************************/
/*****************************************************************************/
// Return true if info available
void Syl_EditSyllabus (void)
{
(void) Syl_CheckAndEditSyllabus ();
}
/*****************************************************************************/
@ -300,12 +320,13 @@ static void Syl_SetSyllabusTypeAndLoadToMemory (void)
break;
}
/***** We are editing a syllabus with the internal editor,
so change info source to internal editor in database *****/
Inf_SetInfoSrcIntoDB (Inf_INFO_SRC_EDITOR);
/***** Load syllabus from XML file to memory *****/
Syl_LoadToMemory ();
/***** We are editing a syllabus with the internal editor,
so change info source to internal editor in database *****/
Inf_SetInfoSrcIntoDB (LstItemsSyllabus.NumItems ? Inf_INFO_SRC_EDITOR :
Inf_INFO_SRC_NONE);
}
/*****************************************************************************/
@ -420,7 +441,6 @@ static void Syl_LoadToMemory (void)
for (NumItem = 0;
NumItem < LstItemsSyllabus.NumItems - 1;
NumItem++)
{
if (LstItemsSyllabus.Lst[NumItem].Level < LstItemsSyllabus.Lst[NumItem + 1].Level)
{
LstItemsSyllabus.Lst[NumItem].HasChildren = true;
@ -428,7 +448,6 @@ static void Syl_LoadToMemory (void)
}
else
LstItemsSyllabus.Lst[NumItem].HasChildren = false;
}
LstItemsSyllabus.Lst[LstItemsSyllabus.NumItems - 1].HasChildren = false;
}
LstItemsSyllabus.NumItemsWithChildren = NumItemsWithChildren;

View File

@ -69,7 +69,11 @@ void Syl_GetParamWhichSyllabus (void);
void Syl_PutFormWhichSyllabus (void);
void Syl_GetParamItemNumber (void);
bool Syl_CheckSyllabus (void);
bool Syl_CheckAndEditSyllabus (void);
void Syl_EditSyllabus (void);
void Syl_FreeListItemsSyllabus (void);
int Syl_ReadLevelItemSyllabus (void);
int Syl_WriteSyllabusIntoHTMLBuffer (char **HTMLBuffer);

View File

@ -1403,7 +1403,6 @@ void Tst_RenameTag (void)
/***** Get old and new tags from the form *****/
Par_GetParToText ("OldTagTxt",OldTagTxt,Tst_MAX_BYTES_TAG);
Par_GetParToText ("NewTagTxt",NewTagTxt,Tst_MAX_BYTES_TAG);
/***** Check that the new tag is not empty *****/
@ -1415,12 +1414,16 @@ void Tst_RenameTag (void)
}
else
{
/***** Check if the old tag is equal to the new one (this happens when user press INTRO without changing anything in the form) *****/
/***** Check if the old tag is equal to the new one
(this happens when user press INTRO
without changing anything in the form) *****/
if (strcmp (OldTagTxt,NewTagTxt)) // The tag text has changed
{
/***** Check if the new tag text is equal to any of the tag texts present in the database *****/
/***** Check if the new tag text is equal
to any of the current tag texts present in the database *****/
if ((ExistingNewTagCod = Tst_GetTagCodFromTagTxt (NewTagTxt)) > 0) // The new tag was already in database
{
// TODO: Fix Bug: when renaming unique tag "examen" to "Examen", tag is removed!
/***** Complex update made to not repeat tags *****/
/* Step 1. Get tag code of the old tag */
if ((OldTagCod = Tst_GetTagCodFromTagTxt (OldTagTxt)) < 0)
@ -1468,7 +1471,8 @@ void Tst_RenameTag (void)
{
/***** Simple update replacing each instance of the old tag by the new tag *****/
sprintf (Query,"UPDATE tst_tags SET TagTxt='%s',ChangeTime=NOW()"
" WHERE tst_tags.CrsCod='%ld' AND tst_tags.TagTxt='%s'",
" WHERE tst_tags.CrsCod='%ld'"
" AND tst_tags.TagTxt='%s'",
NewTagTxt,Gbl.CurrentCrs.Crs.CrsCod,OldTagTxt);
DB_QueryUPDATE (Query,"can not update tag");
}

View File

@ -44544,48 +44544,6 @@ const char *Txt_The_survey_has_been_modified =
"O inqu&eacute;rito foi modificado.";
#endif
const char *Txt_The_syllabus_lectures_of_the_course_X_is_not_available = // Warning: it is very important to include %s in the following sentences
#if L==1
"El programa de teor&iacute;a de la asignatura <strong>%s</strong> no est&aacute; disponible."; // Necessita traduccio
#elif L==2
"The syllabus (lectures) of the course <strong>%s</strong> is not available."; // Need Übersetzung
#elif L==3
"The syllabus (lectures) of the course <strong>%s</strong> is not available.";
#elif L==4
"El programa de teor&iacute;a de la asignatura <strong>%s</strong> no est&aacute; disponible.";
#elif L==5
"The syllabus (lectures) of the course <strong>%s</strong> is not available."; // Besoin de traduction
#elif L==6
"El programa de teor&iacute;a de la asignatura <strong>%s</strong> no est&aacute; disponible."; // Okoteve traducción
#elif L==7
"Il programma di teoria del corso <strong>%s</strong> non &egrave; disponibile.";
#elif L==8
"The syllabus (lectures) of the course <strong>%s</strong> is not available."; // Potrzebujesz tlumaczenie
#elif L==9
"The syllabus (lectures) of the course <strong>%s</strong> is not available."; // Necessita de tradução
#endif
const char *Txt_The_syllabus_practicals_of_the_course_X_is_not_available = // Warning: it is very important to include %s in the following sentences
#if L==1
"El programa de pr&aacute;cticas de la asignatura <strong>%s</strong> no est&aacute; disponible."; // Necessita traduccio
#elif L==2
"The syllabus (practicals) of the course <strong>%s</strong> is not available."; // Need Übersetzung
#elif L==3
"The syllabus (practicals) of the course <strong>%s</strong> is not available.";
#elif L==4
"El programa de pr&aacute;cticas de la asignatura <strong>%s</strong> no est&aacute; disponible.";
#elif L==5
"The syllabus (practicals) of the course <strong>%s</strong> is not available."; // Besoin de traduction
#elif L==6
"El programa de pr&aacute;cticas de la asignatura <strong>%s</strong> no est&aacute; disponible."; // Okoteve traducción
#elif L==7
"Il programma della pratica <strong>%s</strong> non &egrave; disponibile.";
#elif L==8
"The syllabus (practicals) of the course <strong>%s</strong> is not available."; // Potrzebujesz tlumaczenie
#elif L==9
"The syllabus (practicals) of the course <strong>%s</strong> is not available."; // Necessita de tradução
#endif
const char *Txt_The_tag_X_has_been_renamed_as_Y = // Warning: it is very important to include two %s in the following sentences
#if L==1
"El descriptor <strong>%s</strong> ha pasado a denominarse <strong>%s</strong>."; // Necessita traduccio