swad-core/swad_syllabus.c

1493 lines
52 KiB
C
Raw Normal View History

2014-12-01 23:55:08 +01:00
// swad_syllabus.c: syllabus
/*
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.
2019-01-07 21:52:19 +01:00
Copyright (C) 1999-2019 Antonio Ca<EFBFBD>as Vargas
2014-12-01 23:55:08 +01:00
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 <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
#include <unistd.h> // For SEEK_SET
#include <linux/limits.h> // For PATH_MAX
#include <linux/stddef.h> // For NULL
#include <stdsoap2.h> // For SOAP_OK and soap functions
#include <stdlib.h> // For free ()
2017-01-16 01:51:01 +01:00
#include <string.h> // For string functions
2014-12-01 23:55:08 +01:00
#include <time.h> // For time ()
2017-06-10 21:38:10 +02:00
#include "swad_box.h"
2014-12-01 23:55:08 +01:00
#include "swad_changelog.h"
#include "swad_config.h"
#include "swad_database.h"
2018-11-09 20:47:39 +01:00
#include "swad_form.h"
2014-12-01 23:55:08 +01:00
#include "swad_global.h"
#include "swad_parameter.h"
#include "swad_string.h"
2017-06-12 14:16:33 +02:00
#include "swad_table.h"
2014-12-01 23:55:08 +01:00
#include "swad_xml.h"
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
#define Syl_MAX_LEVELS_SYLLABUS 10
2017-01-16 01:51:01 +01:00
2017-03-08 03:48:23 +01:00
#define Syl_MAX_BYTES_ITEM_COD (Syl_MAX_LEVELS_SYLLABUS * (10 + 1) - 1)
2017-01-16 01:51:01 +01:00
2017-03-08 14:12:33 +01:00
#define Syl_MAX_CHARS_TEXT_ITEM (1024 - 1) // 1023
#define Syl_MAX_BYTES_TEXT_ITEM ((Syl_MAX_CHARS_TEXT_ITEM + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 16383
2014-12-01 23:55:08 +01:00
2015-09-28 18:28:29 +02:00
#define Syl_WIDTH_NUM_SYLLABUS 20
2014-12-01 23:55:08 +01:00
2017-01-28 15:58:46 +01:00
static const char *StyleSyllabus[1 + Syl_MAX_LEVELS_SYLLABUS] =
2014-12-01 23:55:08 +01:00
{
"",
"T1",
"T2",
"T3",
"T3",
"T3",
"T3",
"T3",
"T3",
"T3",
"T3",
};
/*****************************************************************************/
/******************************* Private types *******************************/
/*****************************************************************************/
struct ItemSyllabus
{
int Level;
2017-01-28 15:58:46 +01:00
int CodItem[1 + Syl_MAX_LEVELS_SYLLABUS];
2014-12-01 23:55:08 +01:00
bool HasChildren;
2017-01-28 15:58:46 +01:00
char Text[Syl_MAX_BYTES_TEXT_ITEM + 1];
2014-12-01 23:55:08 +01:00
};
/*****************************************************************************/
/***************************** Private variables *****************************/
/*****************************************************************************/
struct
{
struct ItemSyllabus *Lst; // List of items of a syllabus
unsigned NumItems; // Number of items in the list
unsigned NumItemsWithChildren; // Number of items with children
int NumLevels; // Number of levels in the list
} LstItemsSyllabus;
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
2016-05-30 15:25:21 +02:00
static void Syl_SetSyllabusTypeFromAction (void);
2017-09-10 23:24:23 +02:00
static void Syl_ShowSyllabus (bool PutIconToEdit);
2016-03-17 10:39:23 +01:00
static void Syl_ShowRowSyllabus (unsigned NumItem,
2015-10-22 14:49:48 +02:00
int Level,int *CodItem,const char *Text,bool NewItem);
2016-03-17 10:39:23 +01:00
static void Syl_WriteSyllabusIntoHTMLTmpFile (FILE *FileHTMLTmp);
static void Syl_PutFormItemSyllabus (bool NewItem,unsigned NumItem,int Level,int *CodItem,const char *Text);
2017-09-10 23:24:23 +02:00
static void Syl_PutParamNumItem (void);
2014-12-01 23:55:08 +01:00
2017-01-16 01:51:01 +01:00
static void Syl_WriteNumItem (char *StrDst,FILE *FileTgt,int Level,int *CodItem);
2014-12-28 02:42:41 +01:00
/*****************************************************************************/
2017-01-29 21:41:08 +01:00
/************* Get parameter about which syllabus I want to see **************/
2014-12-28 02:42:41 +01:00
/*****************************************************************************/
void Syl_GetParamWhichSyllabus (void)
{
/***** Get which syllabus I want to see *****/
2017-01-29 21:41:08 +01:00
Gbl.Syllabus.WhichSyllabus = (Syl_WhichSyllabus_t)
Par_GetParToUnsignedLong ("WhichSyllabus",
0,
Syl_NUM_WHICH_SYLLABUS - 1,
(unsigned long) Syl_DEFAULT_WHICH_SYLLABUS);
2014-12-28 02:42:41 +01:00
}
2014-12-27 21:09:34 +01:00
/*****************************************************************************/
/************************ Write form to select syllabus **********************/
/*****************************************************************************/
void Syl_PutFormWhichSyllabus (void)
{
extern const char *Txt_SYLLABUS_WHICH_SYLLABUS[Syl_NUM_WHICH_SYLLABUS];
Syl_WhichSyllabus_t WhichSyllabus;
/***** Form to select which forums I want to see
(all my forums or only the forums of current institution/degree/course) *****/
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActSeeSyl);
2016-12-19 00:55:24 +01:00
fprintf (Gbl.F.Out,"<div class=\"CENTER_MIDDLE\">"
"<ul class=\"LIST_LEFT\" style=\"margin:12px;\">");
2014-12-27 21:09:34 +01:00
for (WhichSyllabus = (Syl_WhichSyllabus_t) 0;
2017-04-17 19:03:21 +02:00
WhichSyllabus < For_NUM_FORUM_SETS;
2014-12-27 21:09:34 +01:00
WhichSyllabus++)
{
2015-09-02 20:23:43 +02:00
fprintf (Gbl.F.Out,"<li class=\"DAT LEFT_MIDDLE\""
" style=\"display:inline;\">"
2016-12-20 14:03:46 +01:00
"<label>"
2014-12-28 02:42:41 +01:00
"<input type=\"radio\" name=\"WhichSyllabus\" value=\"%u\"",
2014-12-27 21:09:34 +01:00
(unsigned) WhichSyllabus);
2016-05-30 15:25:21 +02:00
if (WhichSyllabus == Gbl.Syllabus.WhichSyllabus)
2014-12-27 21:09:34 +01:00
fprintf (Gbl.F.Out," checked=\"checked\"");
2015-10-22 14:49:48 +02:00
fprintf (Gbl.F.Out," onclick=\"document.getElementById('%s').submit();\" />"
2014-12-27 21:09:34 +01:00
"%s"
2016-12-20 14:03:46 +01:00
"</label>"
2014-12-27 21:09:34 +01:00
"</li>",
2016-01-14 10:31:09 +01:00
Gbl.Form.Id,Txt_SYLLABUS_WHICH_SYLLABUS[WhichSyllabus]);
2014-12-27 21:09:34 +01:00
}
2015-07-24 13:51:29 +02:00
fprintf (Gbl.F.Out,"</ul>"
"</div>");
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-27 21:09:34 +01:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-01-29 21:41:08 +01:00
/************ Get parameter item number in edition of syllabus ***************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Syl_GetParamItemNumber (void)
{
2017-01-29 21:41:08 +01:00
Gbl.Syllabus.NumItem = (unsigned)
Par_GetParToUnsignedLong ("NumI",
0,
UINT_MAX,
0);
2014-12-01 23:55:08 +01:00
}
2016-05-30 14:27:10 +02:00
/*****************************************************************************/
/********************** Check if syllabus is not empty ***********************/
/*****************************************************************************/
// Return true if info available
2016-05-30 15:25:21 +02:00
bool Syl_CheckSyllabus (long CrsCod,Inf_InfoType_t InfoType)
2016-05-30 14:27:10 +02:00
{
2016-05-30 15:25:21 +02:00
bool InfoAvailable;
2016-05-30 14:27:10 +02:00
2016-05-30 15:25:21 +02:00
/***** Set syllabus type *****/
switch (InfoType)
{
case Inf_LECTURES:
Gbl.Syllabus.WhichSyllabus = Syl_LECTURES;
break;
case Inf_PRACTICALS:
Gbl.Syllabus.WhichSyllabus = Syl_PRACTICALS;
break;
default:
return false;
}
/***** Load syllabus from XML file to memory *****/
Syl_LoadListItemsSyllabusIntoMemory (CrsCod);
/***** Number of items > 0 ==> info available *****/
InfoAvailable = (LstItemsSyllabus.NumItems != 0);
/***** Free memory used to store items *****/
Syl_FreeListItemsSyllabus ();
return InfoAvailable;
2016-05-30 14:27:10 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/****************************** Edit a syllabus ******************************/
/*****************************************************************************/
2016-05-30 14:27:10 +02:00
// Return true if info available
2014-12-01 23:55:08 +01:00
2016-05-30 14:27:10 +02:00
bool Syl_CheckAndEditSyllabus (void)
2014-12-01 23:55:08 +01:00
{
2015-08-03 21:53:34 +02:00
extern const Act_Action_t Inf_ActionsSeeInfo[Inf_NUM_INFO_TYPES];
2016-03-18 10:32:13 +01:00
extern const char *Txt_Done;
bool ICanEdit;
bool PutIconToEdit;
2014-12-01 23:55:08 +01:00
2016-05-30 15:25:21 +02:00
/***** Set syllabus type depending on current action *****/
Syl_SetSyllabusTypeFromAction ();
/***** Load syllabus from XML file to memory *****/
2019-04-04 10:45:15 +02:00
Syl_LoadListItemsSyllabusIntoMemory (Gbl.Hierarchy.Crs.CrsCod);
2014-12-01 23:55:08 +01:00
2016-01-17 15:10:54 +01:00
if (Gbl.Action.Act == ActEditorSylLec ||
Gbl.Action.Act == ActEditorSylPra)
2016-05-30 15:25:21 +02:00
Gbl.Syllabus.EditionIsActive = true;
2014-12-01 23:55:08 +01:00
2016-05-30 15:25:21 +02:00
if (Gbl.Syllabus.EditionIsActive || LstItemsSyllabus.NumItems)
2014-12-01 23:55:08 +01:00
{
2017-06-04 18:18:54 +02:00
ICanEdit = Gbl.Usrs.Me.Role.Logged == Rol_TCH ||
Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM;
2016-05-30 15:25:21 +02:00
PutIconToEdit = ICanEdit && !Gbl.Syllabus.EditionIsActive;
2017-06-12 14:16:33 +02:00
2014-12-01 23:55:08 +01:00
/***** Write the current syllabus *****/
2017-09-10 23:24:23 +02:00
Syl_ShowSyllabus (PutIconToEdit);
2014-12-01 23:55:08 +01:00
2016-05-30 15:25:21 +02:00
if (Gbl.Syllabus.EditionIsActive)
2016-03-18 10:32:13 +01:00
{
/***** Button to view *****/
2019-04-04 10:45:15 +02:00
Frm_StartForm (Inf_ActionsSeeInfo[Gbl.Crs.Info.Type]);
2017-06-11 19:02:40 +02:00
Btn_PutConfirmButton (Txt_Done);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-03-18 10:32:13 +01:00
}
2017-06-12 14:16:33 +02:00
/***** End box *****/
2017-06-10 21:38:10 +02:00
Box_EndBox ();
2016-05-30 14:27:10 +02:00
return true;
2014-12-01 23:55:08 +01:00
}
2016-05-30 14:27:10 +02:00
return false;
}
/*****************************************************************************/
/****************************** Edit a syllabus ******************************/
/*****************************************************************************/
// Return true if info available
void Syl_EditSyllabus (void)
{
(void) Syl_CheckAndEditSyllabus ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************* Set syllabus type depending on the current action *************/
/*****************************************************************************/
2016-05-30 15:25:21 +02:00
static void Syl_SetSyllabusTypeFromAction (void)
2014-12-01 23:55:08 +01:00
{
2019-04-04 10:45:15 +02:00
Gbl.Crs.Info.Type = Inf_LECTURES;
2014-12-01 23:55:08 +01:00
/***** Set the type of syllabus (lectures or practicals) *****/
2016-01-17 15:10:54 +01:00
switch (Gbl.Action.Act)
2014-12-01 23:55:08 +01:00
{
2014-12-28 02:42:41 +01:00
case ActSeeSyl:
2019-04-04 10:45:15 +02:00
Gbl.Crs.Info.Type = (Gbl.Syllabus.WhichSyllabus == Syl_LECTURES ? Inf_LECTURES :
2019-01-10 15:26:33 +01:00
Inf_PRACTICALS);
2014-12-28 02:42:41 +01:00
break;
2014-12-01 23:55:08 +01:00
case ActSeeSylLec:
2014-12-28 02:42:41 +01:00
case ActEdiSylLec:
2014-12-01 23:55:08 +01:00
case ActDelItmSylLec:
case ActUp_IteSylLec:
case ActDwnIteSylLec:
case ActRgtIteSylLec:
case ActLftIteSylLec:
case ActInsIteSylLec:
case ActModIteSylLec:
2014-12-28 02:42:41 +01:00
case ActChgFrcReaSylLec:
case ActChgHavReaSylLec:
case ActSelInfSrcSylLec:
case ActRcvURLSylLec:
case ActRcvPagSylLec:
case ActEditorSylLec:
case ActPlaTxtEdiSylLec:
case ActRchTxtEdiSylLec:
case ActRcvPlaTxtSylLec:
case ActRcvRchTxtSylLec:
2016-05-30 15:25:21 +02:00
Gbl.Syllabus.WhichSyllabus = Syl_LECTURES;
2019-04-04 10:45:15 +02:00
Gbl.Crs.Info.Type = Inf_LECTURES;
2014-12-01 23:55:08 +01:00
break;
case ActSeeSylPra:
2014-12-28 02:42:41 +01:00
case ActEdiSylPra:
2014-12-01 23:55:08 +01:00
case ActDelItmSylPra:
case ActUp_IteSylPra:
case ActDwnIteSylPra:
case ActRgtIteSylPra:
case ActLftIteSylPra:
case ActInsIteSylPra:
case ActModIteSylPra:
2014-12-28 02:42:41 +01:00
case ActChgFrcReaSylPra:
case ActChgHavReaSylPra:
case ActSelInfSrcSylPra:
case ActRcvURLSylPra:
case ActRcvPagSylPra:
case ActEditorSylPra:
case ActPlaTxtEdiSylPra:
case ActRchTxtEdiSylPra:
case ActRcvPlaTxtSylPra:
case ActRcvRchTxtSylPra:
2016-05-30 15:25:21 +02:00
Gbl.Syllabus.WhichSyllabus = Syl_PRACTICALS;
2019-04-04 10:45:15 +02:00
Gbl.Crs.Info.Type = Inf_PRACTICALS;
2014-12-01 23:55:08 +01:00
break;
default:
Lay_ShowErrorAndExit ("Wrong action.");
break;
}
}
/*****************************************************************************/
/*** Read from XML and load in memory a syllabus of lectures or practicals ***/
/*****************************************************************************/
2016-05-30 15:25:21 +02:00
void Syl_LoadListItemsSyllabusIntoMemory (long CrsCod)
2014-12-01 23:55:08 +01:00
{
2017-01-28 15:58:46 +01:00
char PathFile[PATH_MAX + 1];
2014-12-01 23:55:08 +01:00
long PostBeginList;
unsigned NumItem = 0;
int N;
2017-01-28 15:58:46 +01:00
int CodItem[1 + Syl_MAX_LEVELS_SYLLABUS]; // To make numeration
2014-12-01 23:55:08 +01:00
int Result;
unsigned NumItemsWithChildren = 0;
/* Path of the private directory for the XML file with the syllabus */
2018-10-18 02:02:32 +02:00
snprintf (Gbl.Syllabus.PathDir,sizeof (Gbl.Syllabus.PathDir),
2019-03-20 01:36:36 +01:00
"%s/%ld/%s",
Cfg_PATH_CRS_PRIVATE,CrsCod,
2018-10-18 02:02:32 +02:00
Gbl.Syllabus.WhichSyllabus == Syl_LECTURES ? Cfg_SYLLABUS_FOLDER_LECTURES :
Cfg_SYLLABUS_FOLDER_PRACTICALS);
2014-12-01 23:55:08 +01:00
/***** Open the file with the syllabus *****/
2016-05-30 15:25:21 +02:00
Syl_OpenSyllabusFile (Gbl.Syllabus.PathDir,PathFile);
2014-12-01 23:55:08 +01:00
/***** Go to the start of the list of items *****/
if (!Str_FindStrInFile (Gbl.F.XML,"<lista>",Str_NO_SKIP_HTML_COMMENTS))
Lay_ShowErrorAndExit ("Wrong syllabus format.");
/***** Save the position of the start of the list *****/
PostBeginList = ftell (Gbl.F.XML);
/***** Loop to count the number of items *****/
for (LstItemsSyllabus.NumItems = 0;
Str_FindStrInFile (Gbl.F.XML,"<item",Str_NO_SKIP_HTML_COMMENTS);
LstItemsSyllabus.NumItems++);
/***** Allocate memory for the list of items *****/
if ((LstItemsSyllabus.Lst = (struct ItemSyllabus *) calloc (LstItemsSyllabus.NumItems + 1,sizeof (struct ItemSyllabus))) == NULL)
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ();
2014-12-01 23:55:08 +01:00
/***** Return to the start of the list *****/
fseek (Gbl.F.XML,PostBeginList,SEEK_SET);
for (N = 1;
N <= Syl_MAX_LEVELS_SYLLABUS;
N++)
CodItem[N] = 0;
LstItemsSyllabus.NumLevels = 1;
/***** If the syllabus is empty ==> initialize an item to be edited *****/
if (LstItemsSyllabus.NumItems == 0)
{
/* Level of the item */
LstItemsSyllabus.Lst[0].Level = 1;
/* Code (numeraci<63>n) of the item */
CodItem[1] = 1;
for (N = 1;
N <= Syl_MAX_LEVELS_SYLLABUS;
N++)
LstItemsSyllabus.Lst[0].CodItem[N] = CodItem[N];
/* Text of the item */
LstItemsSyllabus.Lst[0].Text[0] = '\0';
}
else
/***** Loop to read and store all the items of the syllabus *****/
for (NumItem = 0;
NumItem < LstItemsSyllabus.NumItems;
NumItem++)
{
/* Go to the start of the item */
if (!Str_FindStrInFile (Gbl.F.XML,"<item",Str_NO_SKIP_HTML_COMMENTS))
Lay_ShowErrorAndExit ("Wrong syllabus format.");
/* Get the level */
LstItemsSyllabus.Lst[NumItem].Level = Syl_ReadLevelItemSyllabus ();
if (LstItemsSyllabus.Lst[NumItem].Level > LstItemsSyllabus.NumLevels)
LstItemsSyllabus.NumLevels = LstItemsSyllabus.Lst[NumItem].Level;
/* Set the code (number) of the item */
CodItem[LstItemsSyllabus.Lst[NumItem].Level]++;
for (N = LstItemsSyllabus.Lst[NumItem].Level + 1;
N <= Syl_MAX_LEVELS_SYLLABUS;
N++)
CodItem[N] = 0;
for (N = 1;
N <= Syl_MAX_LEVELS_SYLLABUS;
N++)
LstItemsSyllabus.Lst[NumItem].CodItem[N] = CodItem[N];
/* Get the text of the item */
2016-04-01 03:09:45 +02:00
Result = Str_ReadFileUntilBoundaryStr (Gbl.F.XML,LstItemsSyllabus.Lst[NumItem].Text,
"</item>",strlen ("</item>"),
(unsigned long long) Syl_MAX_BYTES_TEXT_ITEM);
2014-12-01 23:55:08 +01:00
if (Result == 0) // Str too long
{
if (!Str_FindStrInFile (Gbl.F.XML,"</item>",Str_NO_SKIP_HTML_COMMENTS)) // End the search
Lay_ShowErrorAndExit ("Wrong syllabus format.");
}
else if (Result == -1)
Lay_ShowErrorAndExit ("Wrong syllabus format.");
}
/***** Close the file with the syllabus *****/
Fil_CloseXMLFile ();
/***** Initialize other fields in the list *****/
if (LstItemsSyllabus.NumItems)
{
for (NumItem = 0;
NumItem < LstItemsSyllabus.NumItems - 1;
NumItem++)
if (LstItemsSyllabus.Lst[NumItem].Level < LstItemsSyllabus.Lst[NumItem + 1].Level)
{
LstItemsSyllabus.Lst[NumItem].HasChildren = true;
NumItemsWithChildren++;
}
else
LstItemsSyllabus.Lst[NumItem].HasChildren = false;
LstItemsSyllabus.Lst[LstItemsSyllabus.NumItems - 1].HasChildren = false;
}
LstItemsSyllabus.NumItemsWithChildren = NumItemsWithChildren;
}
/*****************************************************************************/
/*********************** Free list of items of a syllabus ********************/
/*****************************************************************************/
void Syl_FreeListItemsSyllabus (void)
{
if (LstItemsSyllabus.Lst)
{
free ((void *) LstItemsSyllabus.Lst);
LstItemsSyllabus.Lst = NULL;
2016-05-30 15:25:21 +02:00
LstItemsSyllabus.NumItems = 0;
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/************* Read the level of the current item in a syllabus **************/
/*****************************************************************************/
// XML file with the syllabus must be positioned after <item
// XML with the syllabus becomes positioned after <item nivel="x">
int Syl_ReadLevelItemSyllabus (void)
{
int Level;
2017-01-28 15:58:46 +01:00
char StrlLevel[11 + 1];
2014-12-01 23:55:08 +01:00
if (!Str_FindStrInFile (Gbl.F.XML,"nivel=\"",Str_NO_SKIP_HTML_COMMENTS))
Lay_ShowErrorAndExit ("Wrong syllabus format.");
2016-04-01 03:09:45 +02:00
if (Str_ReadFileUntilBoundaryStr (Gbl.F.XML,StrlLevel,"\"",1,
2017-01-28 15:58:46 +01:00
(unsigned long long) (11 + 1)) != 1)
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ("Wrong syllabus format.");
if (sscanf (StrlLevel,"%d",&Level) != 1)
Lay_ShowErrorAndExit ("Wrong syllabus format.");
Str_FindStrInFile (Gbl.F.XML,">",Str_NO_SKIP_HTML_COMMENTS);
if (Level < 1)
Level = 1;
else if (Level > Syl_MAX_LEVELS_SYLLABUS)
Level = Syl_MAX_LEVELS_SYLLABUS;
return Level;
}
/*****************************************************************************/
/***************** Show a syllabus of lectures or practicals *****************/
/*****************************************************************************/
2017-09-10 23:24:23 +02:00
static void Syl_ShowSyllabus (bool PutIconToEdit)
2014-12-01 23:55:08 +01:00
{
2017-09-10 23:24:23 +02:00
extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES];
extern const char *Hlp_COURSE_Syllabus_edit;
extern const char *Hlp_COURSE_Syllabus;
2014-12-01 23:55:08 +01:00
unsigned NumItem;
int i;
2016-05-30 15:25:21 +02:00
int NumButtons = Gbl.Syllabus.EditionIsActive ? 5 :
2017-09-10 23:24:23 +02:00
0;
2016-01-17 15:10:54 +01:00
bool ShowRowInsertNewItem = (Gbl.Action.Act == ActInsIteSylLec || Gbl.Action.Act == ActInsIteSylPra ||
Gbl.Action.Act == ActModIteSylLec || Gbl.Action.Act == ActModIteSylPra ||
Gbl.Action.Act == ActRgtIteSylLec || Gbl.Action.Act == ActRgtIteSylPra ||
Gbl.Action.Act == ActLftIteSylLec || Gbl.Action.Act == ActLftIteSylPra);
2014-12-01 23:55:08 +01:00
2017-09-10 23:24:23 +02:00
/***** Start box and table *****/
2019-04-04 10:45:15 +02:00
Box_StartBoxTable (NULL,Txt_INFO_TITLE[Gbl.Crs.Info.Type],
2017-09-10 23:24:23 +02:00
PutIconToEdit ? Inf_PutIconToEditInfo :
NULL,
Gbl.Syllabus.EditionIsActive ? Hlp_COURSE_Syllabus_edit :
Hlp_COURSE_Syllabus,
Box_NOT_CLOSABLE,0);
2014-12-01 23:55:08 +01:00
/***** Set width of columns of the table *****/
fprintf (Gbl.F.Out,"<colgroup>");
for (i = 0;
i < NumButtons;
i++)
fprintf (Gbl.F.Out,"<col width=\"12\" />");
for (i = 1;
i <= LstItemsSyllabus.NumLevels;
i++)
fprintf (Gbl.F.Out,"<col width=\"%d\" />",
i * Syl_WIDTH_NUM_SYLLABUS);
fprintf (Gbl.F.Out,"<col width=\"*\" />"
"</colgroup>");
2017-09-10 23:24:23 +02:00
if (LstItemsSyllabus.NumItems)
/***** Loop writing all items of the syllabus *****/
for (NumItem = 0;
NumItem < LstItemsSyllabus.NumItems;
NumItem++)
{
Syl_ShowRowSyllabus (NumItem,
LstItemsSyllabus.Lst[NumItem].Level,
LstItemsSyllabus.Lst[NumItem].CodItem,
LstItemsSyllabus.Lst[NumItem].Text,false);
if (ShowRowInsertNewItem && NumItem == Gbl.Syllabus.NumItem)
// Mostrar a new row where se puede insert a new item
Syl_ShowRowSyllabus (NumItem + 1,
LstItemsSyllabus.Lst[NumItem].Level,NULL,
"",true);
}
else if (Gbl.Syllabus.EditionIsActive)
/***** If the syllabus is empty ==>
show form to add a iten to the end *****/
Syl_ShowRowSyllabus (0,1,LstItemsSyllabus.Lst[0].CodItem,"",true);
/***** End table *****/
Tbl_EndTable ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******** Write a row (item) of a syllabus of lectures or practicals *********/
/*****************************************************************************/
2016-03-17 10:39:23 +01:00
static void Syl_ShowRowSyllabus (unsigned NumItem,
2015-10-22 14:49:48 +02:00
int Level,int *CodItem,const char *Text,bool NewItem)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Move_up_X_and_its_subsections;
extern const char *Txt_Move_up_X;
2015-07-22 18:59:44 +02:00
extern const char *Txt_Movement_not_allowed;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Move_down_X_and_its_subsections;
extern const char *Txt_Move_down_X;
extern const char *Txt_Increase_level_of_X;
extern const char *Txt_Decrease_level_of_X;
static int LastLevel = 0;
2017-01-16 01:51:01 +01:00
char StrItemCod[Syl_MAX_LEVELS_SYLLABUS * (10 + 1)];
2014-12-01 23:55:08 +01:00
struct MoveSubtrees Subtree;
Subtree.ToGetUp.Ini = Subtree.ToGetUp.End = 0;
Subtree.ToGetDown.Ini = Subtree.ToGetDown.End = 0;
Subtree.MovAllowed = false;
2017-09-10 23:24:23 +02:00
Gbl.Syllabus.ParamNumItem = NumItem; // Used as parameter in forms
2014-12-01 23:55:08 +01:00
if (!NewItem) // If the item is new (not stored in file), it has no number
Syl_WriteNumItem (StrItemCod,NULL,Level,CodItem);
/***** Start the row *****/
2019-10-04 01:35:40 +02:00
Tbl_StartRow ();
2014-12-01 23:55:08 +01:00
2016-05-30 15:25:21 +02:00
if (Gbl.Syllabus.EditionIsActive)
2014-12-01 23:55:08 +01:00
{
if (NewItem)
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td colspan=\"5\" class=\"COLOR%u\">"
2014-12-25 21:50:11 +01:00
"</td>",
2015-09-03 17:14:30 +02:00
Gbl.RowEvenOdd);
2014-12-01 23:55:08 +01:00
else
{
/***** Icon to remove the row *****/
2015-09-03 00:59:03 +02:00
fprintf (Gbl.F.Out,"<td class=\"BM%u\">",Gbl.RowEvenOdd);
2014-12-01 23:55:08 +01:00
if (LstItemsSyllabus.Lst[NumItem].HasChildren)
2017-06-11 19:13:28 +02:00
Ico_PutIconRemovalNotAllowed ();
2014-12-01 23:55:08 +01:00
else
{
2019-04-04 10:45:15 +02:00
Frm_StartForm (Gbl.Crs.Info.Type == Inf_LECTURES ? ActDelItmSylLec :
2016-03-17 10:39:23 +01:00
ActDelItmSylPra);
2017-09-10 23:24:23 +02:00
Syl_PutParamNumItem ();
2017-06-11 19:13:28 +02:00
Ico_PutIconRemove ();
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-01 23:55:08 +01:00
}
2019-10-06 12:00:55 +02:00
Tbl_EndCell ();
2014-12-01 23:55:08 +01:00
/***** Icon to get up an item *****/
Syl_CalculateUpSubtreeSyllabus (&Subtree,NumItem);
2015-09-03 00:59:03 +02:00
fprintf (Gbl.F.Out,"<td class=\"BM%u\">",Gbl.RowEvenOdd);
2014-12-01 23:55:08 +01:00
if (Subtree.MovAllowed)
{
2018-10-18 02:02:32 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
LstItemsSyllabus.Lst[NumItem].HasChildren ? Txt_Move_up_X_and_its_subsections :
Txt_Move_up_X,
StrItemCod);
2019-04-04 10:45:15 +02:00
Lay_PutContextualLinkOnlyIcon (Gbl.Crs.Info.Type == Inf_LECTURES ? ActUp_IteSylLec :
2019-01-12 03:00:59 +01:00
ActUp_IteSylPra,
NULL,Syl_PutParamNumItem,
"arrow-up.svg",
Gbl.Title);
2014-12-01 23:55:08 +01:00
}
else
2019-01-10 15:26:33 +01:00
Ico_PutIconOff ("arrow-up.svg",Txt_Movement_not_allowed);
2019-10-06 12:00:55 +02:00
Tbl_EndCell ();
2014-12-01 23:55:08 +01:00
/***** Icon to get down item *****/
Syl_CalculateDownSubtreeSyllabus (&Subtree,NumItem);
2015-09-03 00:59:03 +02:00
fprintf (Gbl.F.Out,"<td class=\"BM%u\">",Gbl.RowEvenOdd);
2014-12-01 23:55:08 +01:00
if (Subtree.MovAllowed)
{
2018-10-18 02:02:32 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
LstItemsSyllabus.Lst[NumItem].HasChildren ? Txt_Move_down_X_and_its_subsections :
Txt_Move_down_X,
StrItemCod);
2019-04-04 10:45:15 +02:00
Lay_PutContextualLinkOnlyIcon (Gbl.Crs.Info.Type == Inf_LECTURES ? ActDwnIteSylLec :
2019-01-12 03:00:59 +01:00
ActDwnIteSylPra,
NULL,Syl_PutParamNumItem,
"arrow-down.svg",
Gbl.Title);
2014-12-01 23:55:08 +01:00
}
else
2019-01-10 15:26:33 +01:00
Ico_PutIconOff ("arrow-down.svg",Txt_Movement_not_allowed);
2019-10-06 12:00:55 +02:00
Tbl_EndCell ();
2014-12-01 23:55:08 +01:00
/***** Icon to increase the level of an item *****/
2015-09-03 00:59:03 +02:00
fprintf (Gbl.F.Out,"<td class=\"BM%u\">",Gbl.RowEvenOdd);
2014-12-01 23:55:08 +01:00
if (Level > 1)
{
2018-10-18 02:02:32 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_Increase_level_of_X,
StrItemCod);
2019-04-04 10:45:15 +02:00
Lay_PutContextualLinkOnlyIcon (Gbl.Crs.Info.Type == Inf_LECTURES ? ActRgtIteSylLec :
2019-01-12 03:00:59 +01:00
ActRgtIteSylPra,
NULL,Syl_PutParamNumItem,
"arrow-left.svg",
Gbl.Title);
2014-12-01 23:55:08 +01:00
}
else
2019-01-10 15:26:33 +01:00
Ico_PutIconOff ("arrow-left.svg",Txt_Movement_not_allowed);
2019-10-06 12:00:55 +02:00
Tbl_EndCell ();
2014-12-01 23:55:08 +01:00
/***** Icon to decrease level item *****/
2015-09-03 00:59:03 +02:00
fprintf (Gbl.F.Out,"<td class=\"BM%u\">",Gbl.RowEvenOdd);
2014-12-01 23:55:08 +01:00
if (Level < LastLevel + 1 &&
Level < Syl_MAX_LEVELS_SYLLABUS)
{
2018-10-18 02:02:32 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_Decrease_level_of_X,
StrItemCod);
2019-04-04 10:45:15 +02:00
Lay_PutContextualLinkOnlyIcon (Gbl.Crs.Info.Type == Inf_LECTURES ? ActLftIteSylLec :
2019-01-12 03:00:59 +01:00
ActLftIteSylPra,
NULL,Syl_PutParamNumItem,
"arrow-right.svg",
Gbl.Title);
2014-12-01 23:55:08 +01:00
}
else
2019-01-10 15:26:33 +01:00
Ico_PutIconOff ("arrow-right.svg",Txt_Movement_not_allowed);
2019-10-06 12:00:55 +02:00
Tbl_EndCell ();
2014-12-01 23:55:08 +01:00
LastLevel = Level;
}
}
2016-05-30 15:25:21 +02:00
if (Gbl.Syllabus.EditionIsActive)
2016-03-17 10:39:23 +01:00
Syl_PutFormItemSyllabus (NewItem,NumItem,Level,CodItem,Text);
2014-12-01 23:55:08 +01:00
else
{
/***** Indent depending on the level *****/
if (Level > 1)
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td colspan=\"%d\" class=\"COLOR%u\">"
2014-12-25 21:50:11 +01:00
"</td>",
2015-09-03 17:14:30 +02:00
Level - 1,Gbl.RowEvenOdd);
2014-12-01 23:55:08 +01:00
/***** Code of the item *****/
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s RIGHT_TOP COLOR%u\""
2015-09-24 18:02:21 +02:00
" style=\"width:%dpx;\">",
2015-09-03 17:14:30 +02:00
StyleSyllabus[Level],Gbl.RowEvenOdd,
Level * Syl_WIDTH_NUM_SYLLABUS);
2014-12-01 23:55:08 +01:00
if (Level == 1)
fprintf (Gbl.F.Out,"&nbsp;");
fprintf (Gbl.F.Out,"%s&nbsp;</td>",StrItemCod);
/***** Text of the item *****/
2015-09-03 17:14:30 +02:00
fprintf (Gbl.F.Out,"<td colspan=\"%d\" class=\"%s LEFT_TOP COLOR%u\">"
2014-12-01 23:55:08 +01:00
"%s"
"</td>",
LstItemsSyllabus.NumLevels - Level + 1,
StyleSyllabus[Level],
2015-09-03 17:14:30 +02:00
Gbl.RowEvenOdd,
2014-12-01 23:55:08 +01:00
Text);
}
/***** End of the row *****/
2019-10-04 15:34:59 +02:00
Tbl_EndRow ();
2014-12-01 23:55:08 +01:00
Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd;
}
/*****************************************************************************/
2014-12-21 14:47:04 +01:00
/************** Write the syllabus into a temporary HTML file ****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
// This function is called only from web service
2016-03-17 10:39:23 +01:00
int Syl_WriteSyllabusIntoHTMLBuffer (char **HTMLBuffer)
2014-12-01 23:55:08 +01:00
{
2017-01-28 15:58:46 +01:00
char FileNameHTMLTmp[PATH_MAX + 1];
2014-12-21 14:47:04 +01:00
FILE *FileHTMLTmp;
2014-12-01 23:55:08 +01:00
size_t Length;
/***** Initialize buffer *****/
2014-12-21 14:47:04 +01:00
*HTMLBuffer = NULL;
2014-12-01 23:55:08 +01:00
/***** Load syllabus from XML file to list of items in memory *****/
2019-04-04 10:45:15 +02:00
Syl_LoadListItemsSyllabusIntoMemory (Gbl.Hierarchy.Crs.CrsCod);
2014-12-01 23:55:08 +01:00
if (LstItemsSyllabus.NumItems)
{
/***** Create a unique name for the file *****/
2018-10-18 02:02:32 +02:00
snprintf (FileNameHTMLTmp,sizeof (FileNameHTMLTmp),
2019-03-20 01:36:36 +01:00
"%s/%s_syllabus.html",
Cfg_PATH_OUT_PRIVATE,Gbl.UniqueNameEncrypted);
2014-12-01 23:55:08 +01:00
/***** Create a new temporary file for writing and reading *****/
2014-12-21 14:47:04 +01:00
if ((FileHTMLTmp = fopen (FileNameHTMLTmp,"w+b")) == NULL)
2014-12-01 23:55:08 +01:00
{
Syl_FreeListItemsSyllabus ();
return soap_receiver_fault (Gbl.soap,
"Syllabus can not be copied into buffer",
"Can not create temporary file");
}
2014-12-21 14:47:04 +01:00
/***** Write syllabus in HTML into a temporary file *****/
2016-03-17 10:39:23 +01:00
Syl_WriteSyllabusIntoHTMLTmpFile (FileHTMLTmp);
2014-12-01 23:55:08 +01:00
/***** Write syllabus from list of items in memory to text buffer *****/
/* Compute length of file */
2014-12-21 14:47:04 +01:00
Length = (size_t) ftell (FileHTMLTmp);
2014-12-01 23:55:08 +01:00
/* Allocate memory for buffer */
2017-01-28 15:58:46 +01:00
if ((*HTMLBuffer = (char *) malloc (Length + 1)) == NULL)
2014-12-01 23:55:08 +01:00
{
2014-12-21 14:47:04 +01:00
fclose (FileHTMLTmp);
unlink (FileNameHTMLTmp);
2014-12-01 23:55:08 +01:00
Syl_FreeListItemsSyllabus ();
return soap_receiver_fault (Gbl.soap,
"Syllabus can not be copied into buffer",
"Not enough memory for buffer");
}
/* Copy file content into buffer */
2014-12-21 14:47:04 +01:00
fseek (FileHTMLTmp,0L,SEEK_SET);
if (fread ((void *) *HTMLBuffer,sizeof (char),Length,FileHTMLTmp) != Length)
2014-12-01 23:55:08 +01:00
{
2014-12-21 14:47:04 +01:00
fclose (FileHTMLTmp);
unlink (FileNameHTMLTmp);
2014-12-01 23:55:08 +01:00
Syl_FreeListItemsSyllabus ();
return soap_receiver_fault (Gbl.soap,
"Syllabus can not be copied into buffer",
"Error reading file into buffer");
}
2014-12-21 14:47:04 +01:00
(*HTMLBuffer)[Length] = '\0';
2014-12-01 23:55:08 +01:00
/***** Close and remove temporary file *****/
2014-12-21 14:47:04 +01:00
fclose (FileHTMLTmp);
unlink (FileNameHTMLTmp);
2014-12-01 23:55:08 +01:00
}
/***** Free list of items *****/
Syl_FreeListItemsSyllabus ();
return SOAP_OK;
}
/*****************************************************************************/
2014-12-21 14:47:04 +01:00
/************** Write the syllabus into a temporary HTML file ****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-03-17 10:39:23 +01:00
static void Syl_WriteSyllabusIntoHTMLTmpFile (FILE *FileHTMLTmp)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES];
unsigned NumItem;
int i;
2014-12-21 14:47:04 +01:00
/***** Write start of HTML code *****/
2019-04-04 10:45:15 +02:00
Lay_StartHTMLFile (FileHTMLTmp,Txt_INFO_TITLE[Gbl.Crs.Info.Type]);
2016-10-04 01:16:52 +02:00
fprintf (FileHTMLTmp,"<body>\n"
"<table>\n");
2014-12-01 23:55:08 +01:00
/***** Set width of columns of the table *****/
2014-12-21 14:47:04 +01:00
fprintf (FileHTMLTmp,"<colgroup>\n");
2014-12-01 23:55:08 +01:00
for (i = 1;
i <= LstItemsSyllabus.NumLevels;
i++)
2014-12-21 14:47:04 +01:00
fprintf (FileHTMLTmp,"<col width=\"%d\" />\n",
2014-12-01 23:55:08 +01:00
i * Syl_WIDTH_NUM_SYLLABUS);
2014-12-21 14:47:04 +01:00
fprintf (FileHTMLTmp,"<col width=\"*\" />\n"
2016-10-04 01:16:52 +02:00
"</colgroup>\n");
2014-12-01 23:55:08 +01:00
/***** Write all items of the current syllabus into text buffer *****/
for (NumItem = 0;
NumItem < LstItemsSyllabus.NumItems;
NumItem++)
{
/***** Start the row *****/
2014-12-21 14:47:04 +01:00
fprintf (FileHTMLTmp,"<tr>");
2014-12-01 23:55:08 +01:00
/***** Indent depending on the level *****/
if (LstItemsSyllabus.Lst[NumItem].Level > 1)
2014-12-25 21:50:11 +01:00
fprintf (FileHTMLTmp,"<td colspan=\"%d\"></td>",
2014-12-01 23:55:08 +01:00
LstItemsSyllabus.Lst[NumItem].Level - 1);
/***** Code of the item *****/
2015-09-24 18:02:21 +02:00
fprintf (FileHTMLTmp,"<td class=\"%s RIGHT_TOP\" style=\"width:%dpx;\">",
2014-12-25 21:50:11 +01:00
StyleSyllabus[LstItemsSyllabus.Lst[NumItem].Level],
LstItemsSyllabus.Lst[NumItem].Level * Syl_WIDTH_NUM_SYLLABUS);
2014-12-01 23:55:08 +01:00
if (LstItemsSyllabus.Lst[NumItem].Level == 1)
2014-12-21 14:47:04 +01:00
fprintf (FileHTMLTmp,"&nbsp;");
Syl_WriteNumItem (NULL,FileHTMLTmp,
2014-12-01 23:55:08 +01:00
LstItemsSyllabus.Lst[NumItem].Level,
LstItemsSyllabus.Lst[NumItem].CodItem);
2014-12-21 14:47:04 +01:00
fprintf (FileHTMLTmp,"&nbsp;</td>");
2014-12-01 23:55:08 +01:00
/***** Text of the item *****/
2015-09-02 20:23:43 +02:00
fprintf (FileHTMLTmp,"<td colspan=\"%d\" class=\"%s LEFT_TOP\">"
2016-10-04 01:16:52 +02:00
"%s"
"</td>",
2014-12-01 23:55:08 +01:00
LstItemsSyllabus.NumLevels - LstItemsSyllabus.Lst[NumItem].Level + 1,
StyleSyllabus[LstItemsSyllabus.Lst[NumItem].Level],
LstItemsSyllabus.Lst[NumItem].Text);
/***** End of the row *****/
2014-12-21 14:47:04 +01:00
fprintf (FileHTMLTmp,"</tr>\n");
2014-12-01 23:55:08 +01:00
}
2014-12-21 14:47:04 +01:00
fprintf (FileHTMLTmp,"</table>\n"
2016-10-04 01:16:52 +02:00
"</html>\n"
"</body>\n");
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*************** Show a form to modify an item of the syllabus ***************/
/*****************************************************************************/
2016-03-17 10:39:23 +01:00
static void Syl_PutFormItemSyllabus (bool NewItem,unsigned NumItem,int Level,int *CodItem,const char *Text)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Enter_a_new_item_here;
if (Level < 1)
Level = 1;
/***** Indent depending on the level *****/
if (Level > 1)
2015-09-04 17:10:27 +02:00
fprintf (Gbl.F.Out,"<td colspan=\"%d\" class=\"COLOR%u\">"
2014-12-25 21:50:11 +01:00
"</td>",
2015-09-04 17:10:27 +02:00
Level - 1,Gbl.RowEvenOdd);
2014-12-01 23:55:08 +01:00
/***** Write the code of the item *****/
if (NewItem) // If the item is new (not stored in the file) ==> it has not a number
2015-09-24 18:02:21 +02:00
fprintf (Gbl.F.Out,"<td class=\"COLOR%u\" style=\"width:%dpx;\">"
2014-12-25 21:50:11 +01:00
"</td>",
2015-09-04 17:10:27 +02:00
Gbl.RowEvenOdd,Level * Syl_WIDTH_NUM_SYLLABUS);
2014-12-01 23:55:08 +01:00
else
{
2015-09-04 17:10:27 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s LEFT_MIDDLE COLOR%u\""
2015-09-24 18:02:21 +02:00
" style=\"width:%dpx;\">",
2015-09-04 17:10:27 +02:00
StyleSyllabus[Level],Gbl.RowEvenOdd,
Level * Syl_WIDTH_NUM_SYLLABUS);
2014-12-01 23:55:08 +01:00
if (Level == 1)
fprintf (Gbl.F.Out,"&nbsp;");
Syl_WriteNumItem (NULL,Gbl.F.Out,Level,CodItem);
fprintf (Gbl.F.Out,"&nbsp;</td>");
}
/***** Text of the item *****/
2015-10-22 14:49:48 +02:00
fprintf (Gbl.F.Out,"<td colspan=\"%d\" class=\"LEFT_MIDDLE COLOR%u\">",
2015-09-04 17:10:27 +02:00
LstItemsSyllabus.NumLevels - Level + 1,Gbl.RowEvenOdd);
2019-04-04 10:45:15 +02:00
Frm_StartForm (NewItem ? (Gbl.Crs.Info.Type == Inf_LECTURES ? ActInsIteSylLec :
2016-03-17 10:39:23 +01:00
ActInsIteSylPra) :
2019-04-04 10:45:15 +02:00
(Gbl.Crs.Info.Type == Inf_LECTURES ? ActModIteSylLec :
2016-03-17 10:39:23 +01:00
ActModIteSylPra));
2017-09-10 23:24:23 +02:00
Gbl.Syllabus.ParamNumItem = NumItem;
Syl_PutParamNumItem ();
2016-12-26 14:02:19 +01:00
fprintf (Gbl.F.Out,"<input type=\"text\" name=\"Txt\""
2017-09-10 23:24:23 +02:00
" size=\"60\" maxlength=\"%u\" value=\"%s\""
2016-12-26 14:02:19 +01:00
" placeholder=\"%s\"",
2017-03-08 03:48:23 +01:00
Syl_MAX_CHARS_TEXT_ITEM,Text,
2016-12-26 14:02:19 +01:00
Txt_Enter_a_new_item_here);
2016-03-18 10:32:13 +01:00
if (NewItem)
2016-12-26 13:09:21 +01:00
fprintf (Gbl.F.Out," autofocus=\"autofocus\"");
2016-12-26 14:02:19 +01:00
fprintf (Gbl.F.Out," onchange=\"document.getElementById('%s').submit();\" />",
2016-01-14 10:31:09 +01:00
Gbl.Form.Id);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2019-10-06 12:00:55 +02:00
Tbl_EndCell ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***** Write parameter with the number of an item in a syllabus form *********/
/*****************************************************************************/
2017-09-10 23:24:23 +02:00
static void Syl_PutParamNumItem (void)
2014-12-01 23:55:08 +01:00
{
2017-09-10 23:24:23 +02:00
Par_PutHiddenParamUnsigned ("NumI",Gbl.Syllabus.ParamNumItem);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** Write number of item in legal style ********************/
/*****************************************************************************/
2017-01-16 01:51:01 +01:00
static void Syl_WriteNumItem (char *StrDst,FILE *FileTgt,int Level,int *CodItem)
2014-12-01 23:55:08 +01:00
{
int N;
2017-01-28 15:58:46 +01:00
char InStr[1 + 10 + 1];
2014-12-01 23:55:08 +01:00
if (StrDst)
StrDst[0] = '\0';
for (N = 1;
N <= Level;
N++)
{
if (N > 1)
{
if (StrDst)
2017-01-17 03:33:05 +01:00
Str_Concat (StrDst,".",
2017-03-08 03:48:23 +01:00
Syl_MAX_BYTES_ITEM_COD);
2014-12-01 23:55:08 +01:00
if (FileTgt)
fprintf (FileTgt,".");
}
2018-10-18 02:02:32 +02:00
snprintf (InStr,sizeof (InStr),
"%d",
CodItem[N]);
2014-12-01 23:55:08 +01:00
if (StrDst)
2017-01-17 03:33:05 +01:00
Str_Concat (StrDst,InStr,
2017-03-08 03:48:23 +01:00
Syl_MAX_BYTES_ITEM_COD);
2014-12-01 23:55:08 +01:00
if (FileTgt)
fprintf (FileTgt,"%s",InStr);
}
}
/*****************************************************************************/
/********************** Remove an item from syllabus *************************/
/*****************************************************************************/
void Syl_RemoveItemSyllabus (void)
{
2017-01-16 01:51:01 +01:00
char PathFile[PATH_MAX + 1];
char PathOldFile[PATH_MAX + 1];
char PathNewFile[PATH_MAX + 1];
2014-12-01 23:55:08 +01:00
FILE *NewFile;
unsigned NumItem;
2016-05-30 15:25:21 +02:00
/***** Set syllabus type depending on current action *****/
Syl_SetSyllabusTypeFromAction ();
2014-12-01 23:55:08 +01:00
/***** Load syllabus from XML file to memory *****/
2019-04-04 10:45:15 +02:00
Syl_LoadListItemsSyllabusIntoMemory (Gbl.Hierarchy.Crs.CrsCod);
2014-12-01 23:55:08 +01:00
2016-05-30 15:25:21 +02:00
Gbl.Syllabus.EditionIsActive = true;
2014-12-01 23:55:08 +01:00
/***** Get item number *****/
Syl_GetParamItemNumber ();
/***** Create a new file to make the update *****/
Syl_BuildPathFileSyllabus (PathFile);
Fil_CreateUpdateFile (PathFile,".old",PathOldFile,PathNewFile,&NewFile);
/***** Create the new XML file *****/
Syl_WriteStartFileSyllabus (NewFile);
for (NumItem = 0;
NumItem < LstItemsSyllabus.NumItems;
NumItem++)
2016-05-30 15:25:21 +02:00
if (NumItem != Gbl.Syllabus.NumItem)
2014-12-01 23:55:08 +01:00
Syl_WriteItemFileSyllabus (NewFile,LstItemsSyllabus.Lst[NumItem].Level,LstItemsSyllabus.Lst[NumItem].Text);
Syl_WriteEndFileSyllabus (NewFile);
/***** Close the files *****/
Fil_CloseUpdateFile (PathFile,PathOldFile,PathNewFile,NewFile);
2016-05-30 15:25:21 +02:00
/***** 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);
2014-12-01 23:55:08 +01:00
/***** Show the updated syllabus to continue editing it *****/
Syl_FreeListItemsSyllabus ();
Syl_EditSyllabus ();
}
/*****************************************************************************/
/*** Get up position of an item of the syllabus of lectures or pr<70>cticals ****/
/*****************************************************************************/
void Syl_UpItemSyllabus (void)
{
Syl_ChangePlaceItemSyllabus (Syl_GET_UP);
}
/*****************************************************************************/
/** Get down position of an item of the syllabus of lectures or practicals ***/
/*****************************************************************************/
void Syl_DownItemSyllabus (void)
{
Syl_ChangePlaceItemSyllabus (Syl_GET_DOWN);
}
/*****************************************************************************/
/*************** Get up or get down a subtree of a syllabus ******************/
/*****************************************************************************/
void Syl_ChangePlaceItemSyllabus (Syl_ChangePosItem_t UpOrDownPos)
{
2017-01-28 15:58:46 +01:00
char PathFile[PATH_MAX + 1];
char PathOldFile[PATH_MAX + 1];
char PathNewFile[PATH_MAX + 1];
2014-12-01 23:55:08 +01:00
FILE *NewFile;
unsigned NumItem;
struct MoveSubtrees Subtree;
2016-05-30 15:25:21 +02:00
/***** Set syllabus type depending on current action *****/
Syl_SetSyllabusTypeFromAction ();
2014-12-01 23:55:08 +01:00
/***** Load syllabus from XML file to memory *****/
2019-04-04 10:45:15 +02:00
Syl_LoadListItemsSyllabusIntoMemory (Gbl.Hierarchy.Crs.CrsCod);
2014-12-01 23:55:08 +01:00
2016-05-30 15:25:21 +02:00
Gbl.Syllabus.EditionIsActive = true;
2014-12-01 23:55:08 +01:00
/***** Get item number *****/
Syl_GetParamItemNumber ();
Subtree.ToGetUp.Ini = Subtree.ToGetUp.End = 0;
Subtree.ToGetDown.Ini = Subtree.ToGetDown.End = 0;
Subtree.MovAllowed = false;
2016-05-30 15:25:21 +02:00
if (Gbl.Syllabus.NumItem < LstItemsSyllabus.NumItems)
2014-12-01 23:55:08 +01:00
{
/***** Create a new file where make the update *****/
Syl_BuildPathFileSyllabus (PathFile);
Fil_CreateUpdateFile (PathFile,".old",PathOldFile,PathNewFile,&NewFile);
/***** Get up or get down position *****/
switch (UpOrDownPos)
{
case Syl_GET_UP:
2016-05-30 15:25:21 +02:00
Syl_CalculateUpSubtreeSyllabus (&Subtree,Gbl.Syllabus.NumItem);
2014-12-01 23:55:08 +01:00
break;
case Syl_GET_DOWN:
2016-05-30 15:25:21 +02:00
Syl_CalculateDownSubtreeSyllabus (&Subtree,Gbl.Syllabus.NumItem);
2014-12-01 23:55:08 +01:00
break;
}
/***** Create the new XML file *****/
Syl_WriteStartFileSyllabus (NewFile);
if (Subtree.MovAllowed)
{
for (NumItem = 0;
NumItem < Subtree.ToGetDown.Ini;
NumItem++)
Syl_WriteItemFileSyllabus (NewFile,LstItemsSyllabus.Lst[NumItem].Level,LstItemsSyllabus.Lst[NumItem].Text);
for (NumItem = Subtree.ToGetUp.Ini;
NumItem <= Subtree.ToGetUp.End;
NumItem++)
Syl_WriteItemFileSyllabus (NewFile,LstItemsSyllabus.Lst[NumItem].Level,LstItemsSyllabus.Lst[NumItem].Text);
for (NumItem = Subtree.ToGetDown.Ini;
NumItem <= Subtree.ToGetDown.End;
NumItem++)
Syl_WriteItemFileSyllabus (NewFile,LstItemsSyllabus.Lst[NumItem].Level,LstItemsSyllabus.Lst[NumItem].Text);
for (NumItem = Subtree.ToGetUp.End + 1;
NumItem < LstItemsSyllabus.NumItems;
NumItem++)
Syl_WriteItemFileSyllabus (NewFile,LstItemsSyllabus.Lst[NumItem].Level,LstItemsSyllabus.Lst[NumItem].Text);
}
else
Syl_WriteAllItemsFileSyllabus (NewFile);
Syl_WriteEndFileSyllabus (NewFile);
/***** Close the files *****/
Fil_CloseUpdateFile (PathFile,PathOldFile,PathNewFile,NewFile);
}
2016-05-30 15:25:21 +02:00
/***** 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);
2014-12-01 23:55:08 +01:00
/***** Show the updated syllabus to continue editing it *****/
Syl_FreeListItemsSyllabus ();
Syl_EditSyllabus ();
}
/*****************************************************************************/
/********** Compute the limits for get up a subtree of a syllabus ************/
/*****************************************************************************/
// If return Subtree->MovAllowed = false, the limits become undefined
void Syl_CalculateUpSubtreeSyllabus (struct MoveSubtrees *Subtree,unsigned NumItem)
{
int Level = LstItemsSyllabus.Lst[NumItem].Level;
if (NumItem == 0)
Subtree->MovAllowed = false;
else // NumItem > 0
{
/***** Compute limits of the subtree to get up *****/
Subtree->ToGetUp.Ini = NumItem;
/* Search down the end of the full subtree to get up */
for (Subtree->ToGetUp.End = NumItem + 1;
Subtree->ToGetUp.End < LstItemsSyllabus.NumItems;
Subtree->ToGetUp.End++)
if (LstItemsSyllabus.Lst[Subtree->ToGetUp.End].Level <= Level)
{
Subtree->ToGetUp.End--;
break;
}
if (Subtree->ToGetUp.End == LstItemsSyllabus.NumItems)
Subtree->ToGetUp.End = LstItemsSyllabus.NumItems - 1;
/***** Compute limits of the subtree to get down *****/
Subtree->ToGetDown.End = NumItem - 1;
if (LstItemsSyllabus.Lst[Subtree->ToGetDown.End].Level < Level)
Subtree->MovAllowed = false;
else
{
Subtree->MovAllowed = true;
/* Find backwards the start of the subtree to get down */
for (Subtree->ToGetDown.Ini = Subtree->ToGetDown.End;
Subtree->ToGetDown.Ini > 0;
Subtree->ToGetDown.Ini--)
if (LstItemsSyllabus.Lst[Subtree->ToGetDown.Ini].Level <= Level)
break;
}
}
}
/*****************************************************************************/
/****** Compute the limits for the get down of a subtree of a syllabus *******/
/*****************************************************************************/
// When return Subtree->MovAllowed equal to false, the limits become undefined
void Syl_CalculateDownSubtreeSyllabus (struct MoveSubtrees *Subtree,unsigned NumItem)
{
int Level = LstItemsSyllabus.Lst[NumItem].Level;
/***** Compute limits of the subtree to get down *****/
Subtree->ToGetDown.Ini = NumItem;
/* Search down the end of the full subtree to get down */
for (Subtree->ToGetDown.End = NumItem + 1;
Subtree->ToGetDown.End < LstItemsSyllabus.NumItems;
Subtree->ToGetDown.End++)
if (LstItemsSyllabus.Lst[Subtree->ToGetDown.End].Level <= Level)
{
Subtree->ToGetDown.End--;
break;
}
if (Subtree->ToGetDown.End >= LstItemsSyllabus.NumItems - 1)
Subtree->MovAllowed = false;
else
{
/***** Compute limits of the subtree to get up *****/
Subtree->ToGetUp.Ini = Subtree->ToGetDown.End + 1;
if (LstItemsSyllabus.Lst[Subtree->ToGetUp.Ini].Level < Level)
Subtree->MovAllowed = false;
else
{
Subtree->MovAllowed = true;
/* Find downwards the end of the subtree to get up */
for (Subtree->ToGetUp.End = Subtree->ToGetUp.Ini + 1;
Subtree->ToGetUp.End < LstItemsSyllabus.NumItems;
Subtree->ToGetUp.End++)
if (LstItemsSyllabus.Lst[Subtree->ToGetUp.End].Level <= Level)
{
Subtree->ToGetUp.End--;
break;
}
if (Subtree->ToGetUp.End == LstItemsSyllabus.NumItems)
Subtree->ToGetUp.End = LstItemsSyllabus.NumItems - 1;
}
}
}
/*****************************************************************************/
/** Increase the level of an item of the syllabus of lectures or practicals **/
/*****************************************************************************/
void Syl_RightItemSyllabus (void)
{
Syl_ChangeLevelItemSyllabus (Syl_INCREASE_LEVEL);
}
/*****************************************************************************/
/** Decrease the level of an item of the syllabus of lectures or practicals **/
/*****************************************************************************/
void Syl_LeftItemSyllabus (void)
{
Syl_ChangeLevelItemSyllabus (Syl_DECREASE_LEVEL);
}
/*****************************************************************************/
/********* Increase or decrease the level of an item of a syllabus ***********/
/*****************************************************************************/
void Syl_ChangeLevelItemSyllabus (Syl_ChangeLevelItem_t IncreaseOrDecreaseLevel)
{
2017-01-28 15:58:46 +01:00
char PathFile[PATH_MAX + 1];
char PathOldFile[PATH_MAX + 1];
char PathNewFile[PATH_MAX + 1];
2014-12-01 23:55:08 +01:00
FILE *NewFile;
2016-05-30 15:25:21 +02:00
/***** Set syllabus type depending on current action *****/
Syl_SetSyllabusTypeFromAction ();
2014-12-01 23:55:08 +01:00
/***** Load syllabus from XML file to memory *****/
2019-04-04 10:45:15 +02:00
Syl_LoadListItemsSyllabusIntoMemory (Gbl.Hierarchy.Crs.CrsCod);
2014-12-01 23:55:08 +01:00
2016-05-30 15:25:21 +02:00
Gbl.Syllabus.EditionIsActive = true;
2014-12-01 23:55:08 +01:00
/***** Get item number *****/
Syl_GetParamItemNumber ();
/***** Create a new file to do the update *****/
Syl_BuildPathFileSyllabus (PathFile);
Fil_CreateUpdateFile (PathFile,".old",PathOldFile,PathNewFile,&NewFile);
/***** Increase or decrease level *****/
switch (IncreaseOrDecreaseLevel)
{
case Syl_INCREASE_LEVEL:
2016-05-30 15:25:21 +02:00
if (LstItemsSyllabus.Lst[Gbl.Syllabus.NumItem].Level > 1)
LstItemsSyllabus.Lst[Gbl.Syllabus.NumItem].Level--;
2014-12-01 23:55:08 +01:00
break;
case Syl_DECREASE_LEVEL:
2016-05-30 15:25:21 +02:00
if (LstItemsSyllabus.Lst[Gbl.Syllabus.NumItem].Level < Syl_MAX_LEVELS_SYLLABUS)
LstItemsSyllabus.Lst[Gbl.Syllabus.NumItem].Level++;
2014-12-01 23:55:08 +01:00
break;
}
/***** Create the new XML file *****/
Syl_WriteStartFileSyllabus (NewFile);
Syl_WriteAllItemsFileSyllabus (NewFile);
Syl_WriteEndFileSyllabus (NewFile);
/***** Close the files *****/
Fil_CloseUpdateFile (PathFile,PathOldFile,PathNewFile,NewFile);
2016-05-30 15:25:21 +02:00
/***** 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);
2014-12-01 23:55:08 +01:00
/***** Show the updated syllabus to continue editing it *****/
Syl_FreeListItemsSyllabus ();
Syl_EditSyllabus ();
}
/*****************************************************************************/
/************************ Insert an item in a syllabus ***********************/
/*****************************************************************************/
void Syl_InsertItemSyllabus (void)
{
2017-01-28 15:58:46 +01:00
char PathFile[PATH_MAX + 1];
char PathOldFile[PATH_MAX + 1];
char PathNewFile[PATH_MAX + 1];
2014-12-01 23:55:08 +01:00
FILE *NewFile;
unsigned NumItem;
2017-01-28 15:58:46 +01:00
char Txt[Syl_MAX_BYTES_TEXT_ITEM + 1];
2014-12-01 23:55:08 +01:00
2016-05-30 15:25:21 +02:00
/***** Set syllabus type depending on current action *****/
Syl_SetSyllabusTypeFromAction ();
2014-12-01 23:55:08 +01:00
/***** Load syllabus from XML file to memory *****/
2019-04-04 10:45:15 +02:00
Syl_LoadListItemsSyllabusIntoMemory (Gbl.Hierarchy.Crs.CrsCod);
2014-12-01 23:55:08 +01:00
2016-05-30 15:25:21 +02:00
Gbl.Syllabus.EditionIsActive = true;
2014-12-01 23:55:08 +01:00
/***** Get item number *****/
Syl_GetParamItemNumber ();
/***** Get item body *****/
Par_GetParToHTML ("Txt",Txt,Syl_MAX_BYTES_TEXT_ITEM);
/***** Create a new file to do the update *****/
Syl_BuildPathFileSyllabus (PathFile);
Fil_CreateUpdateFile (PathFile,".old",PathOldFile,PathNewFile,&NewFile);
/***** Create the new XML file *****/
Syl_WriteStartFileSyllabus (NewFile);
/* Write items before the one to be inserted */
for (NumItem = 0;
2016-05-30 15:25:21 +02:00
NumItem < Gbl.Syllabus.NumItem;
2014-12-01 23:55:08 +01:00
NumItem++)
Syl_WriteItemFileSyllabus (NewFile,LstItemsSyllabus.Lst[NumItem].Level,LstItemsSyllabus.Lst[NumItem].Text);
/* Write the item that will be inserted */
Syl_WriteItemFileSyllabus (NewFile,
NumItem ? LstItemsSyllabus.Lst[NumItem - 1].Level :
1,
Txt);
/* Write items after the one just inserted */
for (;
NumItem < LstItemsSyllabus.NumItems;
NumItem++)
Syl_WriteItemFileSyllabus (NewFile,LstItemsSyllabus.Lst[NumItem].Level,LstItemsSyllabus.Lst[NumItem].Text);
Syl_WriteEndFileSyllabus (NewFile);
/***** Close the files *****/
Fil_CloseUpdateFile (PathFile,PathOldFile,PathNewFile,NewFile);
2016-05-30 15:25:21 +02:00
/***** 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);
2014-12-01 23:55:08 +01:00
/***** Show the updated syllabus to continue editing it *****/
Syl_FreeListItemsSyllabus ();
Syl_EditSyllabus ();
}
/*****************************************************************************/
/**************** Modify and existing item of the syllabus *******************/
/*****************************************************************************/
void Syl_ModifyItemSyllabus (void)
{
2017-01-28 15:58:46 +01:00
char PathFile[PATH_MAX + 1];
char PathOldFile[PATH_MAX + 1];
char PathNewFile[PATH_MAX + 1];
2014-12-01 23:55:08 +01:00
FILE *NewFile;
2016-05-30 15:25:21 +02:00
/***** Set syllabus type depending on current action *****/
Syl_SetSyllabusTypeFromAction ();
2014-12-01 23:55:08 +01:00
/***** Load syllabus from XML file to memory *****/
2019-04-04 10:45:15 +02:00
Syl_LoadListItemsSyllabusIntoMemory (Gbl.Hierarchy.Crs.CrsCod);
2014-12-01 23:55:08 +01:00
2016-05-30 15:25:21 +02:00
Gbl.Syllabus.EditionIsActive = true;
2014-12-01 23:55:08 +01:00
/***** Get item number *****/
Syl_GetParamItemNumber ();
/***** Get item body *****/
2017-01-29 21:41:08 +01:00
Par_GetParToHTML ("Txt",LstItemsSyllabus.Lst[Gbl.Syllabus.NumItem].Text,
Syl_MAX_BYTES_TEXT_ITEM);
2014-12-01 23:55:08 +01:00
/***** Create a new file where make the update *****/
Syl_BuildPathFileSyllabus (PathFile);
Fil_CreateUpdateFile (PathFile,".old",PathOldFile,PathNewFile,&NewFile);
/***** Create the new XML file *****/
Syl_WriteStartFileSyllabus (NewFile);
Syl_WriteAllItemsFileSyllabus (NewFile);
Syl_WriteEndFileSyllabus (NewFile);
/***** Close the files *****/
Fil_CloseUpdateFile (PathFile,PathOldFile,PathNewFile,NewFile);
2016-05-30 15:25:21 +02:00
/***** 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);
2014-12-01 23:55:08 +01:00
/***** Show the updated syllabus to continue editing it *****/
Syl_FreeListItemsSyllabus ();
Syl_EditSyllabus ();
}
/*****************************************************************************/
/************ Build the path of the file XML with the syllabus ***************/
/*****************************************************************************/
void Syl_BuildPathFileSyllabus (char *PathFile)
{
2018-10-04 21:57:25 +02:00
char Path[PATH_MAX + 1 + NAME_MAX + 1];
2018-10-18 02:02:32 +02:00
snprintf (Path,sizeof (Path),
"%s/%s",
Gbl.Syllabus.PathDir,Cfg_SYLLABUS_FILENAME);
2018-10-04 21:57:25 +02:00
Str_Copy (PathFile,Path,
PATH_MAX);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Open file with the syllabus *************************/
/*****************************************************************************/
void Syl_OpenSyllabusFile (const char *PathDir,char *PathFile)
{
if (Gbl.F.XML == NULL) // If it's not open in this moment...
{
/* If the directory does not exist, create it */
Fil_CreateDirIfNotExists (PathDir);
/* Open the file for reading */
Syl_BuildPathFileSyllabus (PathFile);
if ((Gbl.F.XML = fopen (PathFile,"rb")) == NULL)
{
/* Can't open the file */
if (!Fil_CheckIfPathExists (PathDir)) // Strange error, since it is just created
Lay_ShowErrorAndExit ("Can not open syllabus file.");
else
{
/* Create a new empty syllabus */
if ((Gbl.F.XML = fopen (PathFile,"wb")) == NULL)
Lay_ShowErrorAndExit ("Can not create syllabus file.");
Syl_WriteStartFileSyllabus (Gbl.F.XML);
Syl_WriteEndFileSyllabus (Gbl.F.XML);
Fil_CloseXMLFile ();
/* Open of new the file for reading */
if ((Gbl.F.XML = fopen (PathFile,"rb")) == NULL)
Lay_ShowErrorAndExit ("Can not open syllabus file.");
}
}
}
else // Go to the start of the file
rewind (Gbl.F.XML);
}
/*****************************************************************************/
/*********************** Write a file with a syllabus ************************/
/*****************************************************************************/
void Syl_WriteStartFileSyllabus (FILE *FileSyllabus)
{
extern const char *Txt_NEW_LINE;
XML_WriteStartFile (FileSyllabus,"temario",true);
fprintf (FileSyllabus,"<lista>%s",Txt_NEW_LINE);
}
void Syl_WriteAllItemsFileSyllabus (FILE *FileSyllabus)
{
unsigned NumItem;
for (NumItem = 0;
NumItem < LstItemsSyllabus.NumItems;
NumItem++)
Syl_WriteItemFileSyllabus (FileSyllabus,LstItemsSyllabus.Lst[NumItem].Level,LstItemsSyllabus.Lst[NumItem].Text);
}
void Syl_WriteItemFileSyllabus (FILE *FileSyllabus,int Level,const char *Text)
{
extern const char *Txt_NEW_LINE;
fprintf (FileSyllabus,"<item nivel=\"%d\">%s</item>%s",Level,Text,Txt_NEW_LINE);
}
void Syl_WriteEndFileSyllabus (FILE *FileSyllabus)
{
extern const char *Txt_NEW_LINE;
fprintf (FileSyllabus,"</lista>%s",Txt_NEW_LINE);
XML_WriteEndFile (FileSyllabus,"temario");
}