swad-core/swad_syllabus.c

1468 lines
51 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.
Copyright (C) 1999-2023 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 ***********************************/
/*****************************************************************************/
#define _GNU_SOURCE // For asprintf
2014-12-01 23:55:08 +01:00
#include <linux/limits.h> // For PATH_MAX
2019-12-29 12:39:00 +01:00
#include <stddef.h> // For NULL
#include <stdio.h> // For asprintf
2014-12-01 23:55:08 +01:00
#include <stdlib.h> // For free ()
2019-12-29 12:39:00 +01:00
#include <stdsoap2.h> // For SOAP_OK and soap functions
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 ()
#include <unistd.h> // For SEEK_SET
2014-12-01 23:55:08 +01:00
#include "swad_action_list.h"
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"
#include "swad_error.h"
2018-11-09 20:47:39 +01:00
#include "swad_form.h"
2020-04-14 17:15:17 +02:00
#include "swad_forum.h"
2014-12-01 23:55:08 +01:00
#include "swad_global.h"
2019-10-23 19:05:05 +02:00
#include "swad_HTML.h"
#include "swad_info_database.h"
2014-12-01 23:55:08 +01:00
#include "swad_parameter.h"
#include "swad_string.h"
#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
static const char *ClassSyllabus[1 + Syl_MAX_LEVELS_SYLLABUS] =
2014-12-01 23:55:08 +01:00
{
2019-12-15 20:02:34 +01:00
[ 0] = "",
[ 1] = "SYL1",
[ 2] = "SYL2",
[ 3] = "SYL3",
[ 4] = "SYL3",
[ 5] = "SYL3",
[ 6] = "SYL3",
[ 7] = "SYL3",
[ 8] = "SYL3",
[ 9] = "SYL3",
[10] = "SYL3",
2014-12-01 23:55:08 +01:00
};
/*****************************************************************************/
/******************************* 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 *****************************/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
struct LstItemsSyllabus Syl_LstItemsSyllabus;
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static void Syl_PutFormWhichSyllabus (Syl_WhichSyllabus_t SyllabusSelected);
static unsigned Syl_GetParItemNumber (void);
2020-04-12 02:47:32 +02:00
static void Syl_SetSyllabusTypeFromAction (struct Syl_Syllabus *Syllabus);
static void Syl_ShowSyllabus (struct Syl_Syllabus *Syllabus);
2020-04-12 02:47:32 +02:00
static void Syl_ShowRowSyllabus (struct Syl_Syllabus *Syllabus,unsigned NumItem,
2015-10-22 14:49:48 +02:00
int Level,int *CodItem,const char *Text,bool NewItem);
2020-04-12 02:47:32 +02:00
static void Syl_PutFormItemSyllabus (struct Syl_Syllabus *Syllabus,
bool NewItem,unsigned NumItem,int Level,int *CodItem,const char *Text);
static void Syl_PutParNumItem (void *ParNumItem);
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);
2020-04-12 02:47:32 +02:00
static void Syl_ChangePlaceItemSyllabus (Syl_ChangePosItem_t UpOrDownPos);
static void Syl_ChangeLevelItemSyllabus (Syl_ChangeLevelItem_t IncreaseOrDecreaseLevel);
static void Syl_OpenSyllabusFile (const struct Syl_Syllabus *Syllabus,
char PathFile[PATH_MAX + 1],
FILE **XML);
static void Syl_CloseXMLFile (FILE **XML);
2020-04-12 02:47:32 +02:00
/*****************************************************************************/
/************************** Reset syllabus context ***************************/
/*****************************************************************************/
void Syl_ResetSyllabus (struct Syl_Syllabus *Syllabus)
{
Syllabus->PathDir[0] = '\0';
Syllabus->NumItem = 0;
Syllabus->ViewType = Vie_VIEW;
2020-04-12 02:47:32 +02:00
Syllabus->WhichSyllabus = Syl_DEFAULT_WHICH_SYLLABUS;
}
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
/*****************************************************************************/
Syl_WhichSyllabus_t Syl_GetParWhichSyllabus (void)
2014-12-28 02:42:41 +01:00
{
/***** Get which syllabus I want to see *****/
2020-04-12 02:47:32 +02:00
return (Syl_WhichSyllabus_t)
Par_GetParUnsignedLong ("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 **********************/
/*****************************************************************************/
static void Syl_PutFormWhichSyllabus (Syl_WhichSyllabus_t SyllabusSelected)
2014-12-27 21:09:34 +01:00
{
extern const char *Txt_SYLLABUS_WHICH_SYLLABUS[Syl_NUM_WHICH_SYLLABUS];
2020-04-12 02:47:32 +02:00
Syl_WhichSyllabus_t WhichSyl;
2014-12-27 21:09:34 +01:00
2019-10-16 00:06:02 +02:00
/***** Form to select which syllabus I want to see (lectures/practicals) *****/
Frm_BeginForm (ActSeeSyl);
HTM_DIV_Begin ("class=\"SEL_BELOW_TITLE DAT_%s\"",The_GetSuffix ());
HTM_UL_Begin (NULL);
2014-12-27 21:09:34 +01:00
for (WhichSyl = (Syl_WhichSyllabus_t) 0;
WhichSyl <= (Syl_WhichSyllabus_t) (For_NUM_FORUM_SETS - 1);
WhichSyl++)
{
HTM_LI_Begin (NULL);
HTM_LABEL_Begin (NULL);
HTM_INPUT_RADIO ("WhichSyllabus",HTM_SUBMIT_ON_CLICK,
"value=\"%u\"%s",
(unsigned) WhichSyl,
WhichSyl == SyllabusSelected ? " checked=\"checked\"" :
"");
HTM_Txt (Txt_SYLLABUS_WHICH_SYLLABUS[WhichSyl]);
HTM_LABEL_End ();
HTM_LI_End ();
}
HTM_UL_End ();
HTM_DIV_End ();
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
/*****************************************************************************/
static unsigned Syl_GetParItemNumber (void)
2014-12-01 23:55:08 +01:00
{
return (unsigned) Par_GetParUnsignedLong ("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
2020-04-12 02:47:32 +02:00
bool Syl_CheckSyllabus (struct Syl_Syllabus *Syllabus,long CrsCod)
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
/***** Load syllabus from XML file to memory *****/
2020-04-12 02:47:32 +02:00
Syl_LoadListItemsSyllabusIntoMemory (Syllabus,CrsCod);
2016-05-30 15:25:21 +02:00
/***** Number of items > 0 ==> info available *****/
2020-02-24 19:31:55 +01:00
InfoAvailable = (Syl_LstItemsSyllabus.NumItems != 0);
2016-05-30 15:25:21 +02:00
/***** 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
/*****************************************************************************/
2020-04-13 12:04:49 +02:00
/************** Load syllabus from file to memoruy and edit it ***************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-05-30 14:27:10 +02:00
// Return true if info available
2014-12-01 23:55:08 +01:00
2020-04-12 02:47:32 +02:00
bool Syl_CheckAndEditSyllabus (struct Syl_Syllabus *Syllabus)
2014-12-01 23:55:08 +01:00
{
2016-05-30 15:25:21 +02:00
/***** Set syllabus type depending on current action *****/
2020-04-12 02:47:32 +02:00
Syl_SetSyllabusTypeFromAction (Syllabus);
2016-05-30 15:25:21 +02:00
/***** Load syllabus from XML file to memory *****/
Syl_LoadListItemsSyllabusIntoMemory (Syllabus,Gbl.Hierarchy.Node[Hie_CRS].HieCod);
2014-12-01 23:55:08 +01:00
2020-04-13 12:04:49 +02:00
switch (Gbl.Action.Act)
{
case ActEditorSylLec: case ActEditorSylPra:
case ActDelItmSylLec: case ActDelItmSylPra:
case ActUp_IteSylLec: case ActUp_IteSylPra:
case ActDwnIteSylLec: case ActDwnIteSylPra:
case ActRgtIteSylLec: case ActRgtIteSylPra:
case ActLftIteSylLec: case ActLftIteSylPra:
case ActInsIteSylLec: case ActInsIteSylPra:
case ActModIteSylLec: case ActModIteSylPra:
Syllabus->ViewType = Vie_EDIT;
2020-04-13 12:04:49 +02:00
break;
default:
Syllabus->ViewType = Vie_VIEW;
2020-04-13 12:04:49 +02:00
break;
}
2014-12-01 23:55:08 +01:00
if (Syllabus->ViewType == Vie_EDIT ||
Syl_LstItemsSyllabus.NumItems)
2014-12-01 23:55:08 +01:00
{
/***** Write the current syllabus *****/
Syl_ShowSyllabus (Syllabus);
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)
{
2020-04-12 02:47:32 +02:00
struct Syl_Syllabus Syllabus;
/***** Reset syllabus context *****/
Syl_ResetSyllabus (&Syllabus);
/***** Edit syllabus *****/
2020-04-19 02:39:20 +02:00
Syl_CheckAndEditSyllabus (&Syllabus);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************* Set syllabus type depending on the current action *************/
/*****************************************************************************/
2020-04-12 02:47:32 +02:00
static void Syl_SetSyllabusTypeFromAction (struct Syl_Syllabus *Syllabus)
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:
2020-04-12 02:47:32 +02:00
Gbl.Crs.Info.Type = (Syllabus->WhichSyllabus == Syl_LECTURES ? Inf_LECTURES :
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:
2020-04-12 02:47:32 +02:00
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:
2020-04-12 02:47:32 +02:00
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:
Err_WrongActionExit ();
2014-12-01 23:55:08 +01:00
break;
}
}
/*****************************************************************************/
/*** Read from XML and load in memory a syllabus of lectures or practicals ***/
/*****************************************************************************/
2020-04-12 02:47:32 +02:00
void Syl_LoadListItemsSyllabusIntoMemory (struct Syl_Syllabus *Syllabus,
long CrsCod)
2014-12-01 23:55:08 +01:00
{
2017-01-28 15:58:46 +01:00
char PathFile[PATH_MAX + 1];
FILE *XML = NULL; // XML file for syllabus
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 */
snprintf (Syllabus->PathDir,sizeof (Syllabus->PathDir),"%s/%ld/%s",
2019-03-20 01:36:36 +01:00
Cfg_PATH_CRS_PRIVATE,CrsCod,
2020-04-12 02:47:32 +02:00
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 *****/
Syl_OpenSyllabusFile (Syllabus,PathFile,&XML);
2014-12-01 23:55:08 +01:00
/***** Go to the start of the list of items *****/
if (!Str_FindStrInFile (XML,"<lista>",Str_NO_SKIP_HTML_COMMENTS))
Err_WrongSyllabusFormatExit ();
2014-12-01 23:55:08 +01:00
/***** Save the position of the start of the list *****/
PostBeginList = ftell (XML);
2014-12-01 23:55:08 +01:00
/***** Loop to count the number of items *****/
2020-02-24 19:31:55 +01:00
for (Syl_LstItemsSyllabus.NumItems = 0;
Str_FindStrInFile (XML,"<item",Str_NO_SKIP_HTML_COMMENTS);
2020-02-24 19:31:55 +01:00
Syl_LstItemsSyllabus.NumItems++);
2014-12-01 23:55:08 +01:00
/***** Allocate memory for the list of items *****/
if ((Syl_LstItemsSyllabus.Lst = calloc (Syl_LstItemsSyllabus.NumItems + 1,
sizeof (*Syl_LstItemsSyllabus.Lst))) == NULL)
Err_NotEnoughMemoryExit ();
2014-12-01 23:55:08 +01:00
/***** Return to the start of the list *****/
fseek (XML,PostBeginList,SEEK_SET);
2014-12-01 23:55:08 +01:00
2020-02-27 00:19:55 +01:00
for (N = 1;
2014-12-01 23:55:08 +01:00
N <= Syl_MAX_LEVELS_SYLLABUS;
N++)
CodItem[N] = 0;
2020-02-24 19:31:55 +01:00
Syl_LstItemsSyllabus.NumLevels = 1;
2014-12-01 23:55:08 +01:00
/***** If the syllabus is empty ==> initialize an item to be edited *****/
2020-02-24 19:31:55 +01:00
if (Syl_LstItemsSyllabus.NumItems == 0)
2014-12-01 23:55:08 +01:00
{
/* Level of the item */
2020-02-24 19:31:55 +01:00
Syl_LstItemsSyllabus.Lst[0].Level = 1;
2014-12-01 23:55:08 +01:00
2020-02-27 23:44:21 +01:00
/* Code (numeration) of the item */
2014-12-01 23:55:08 +01:00
CodItem[1] = 1;
for (N = 1;
N <= Syl_MAX_LEVELS_SYLLABUS;
N++)
2020-02-24 19:31:55 +01:00
Syl_LstItemsSyllabus.Lst[0].CodItem[N] = CodItem[N];
2014-12-01 23:55:08 +01:00
/* Text of the item */
2020-02-24 19:31:55 +01:00
Syl_LstItemsSyllabus.Lst[0].Text[0] = '\0';
2014-12-01 23:55:08 +01:00
}
else
/***** Loop to read and store all items of the syllabus *****/
2014-12-01 23:55:08 +01:00
for (NumItem = 0;
2020-02-24 19:31:55 +01:00
NumItem < Syl_LstItemsSyllabus.NumItems;
2014-12-01 23:55:08 +01:00
NumItem++)
{
/* Go to the start of the item */
if (!Str_FindStrInFile (XML,"<item",Str_NO_SKIP_HTML_COMMENTS))
Err_WrongSyllabusFormatExit ();
2014-12-01 23:55:08 +01:00
/* Get the level */
Syl_LstItemsSyllabus.Lst[NumItem].Level = Syl_ReadLevelItemSyllabus (XML);
2020-02-24 19:31:55 +01:00
if (Syl_LstItemsSyllabus.Lst[NumItem].Level > Syl_LstItemsSyllabus.NumLevels)
Syl_LstItemsSyllabus.NumLevels = Syl_LstItemsSyllabus.Lst[NumItem].Level;
2014-12-01 23:55:08 +01:00
/* Set the code (number) of the item */
2020-02-24 19:31:55 +01:00
CodItem[Syl_LstItemsSyllabus.Lst[NumItem].Level]++;
for (N = Syl_LstItemsSyllabus.Lst[NumItem].Level + 1;
2014-12-01 23:55:08 +01:00
N <= Syl_MAX_LEVELS_SYLLABUS;
N++)
CodItem[N] = 0;
for (N = 1;
2014-12-01 23:55:08 +01:00
N <= Syl_MAX_LEVELS_SYLLABUS;
N++)
2020-02-24 19:31:55 +01:00
Syl_LstItemsSyllabus.Lst[NumItem].CodItem[N] = CodItem[N];
2014-12-01 23:55:08 +01:00
/* Get the text of the item */
Result = Str_ReadFileUntilBoundaryStr (XML,Syl_LstItemsSyllabus.Lst[NumItem].Text,
2016-04-01 03:09:45 +02:00
"</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 (XML,"</item>",Str_NO_SKIP_HTML_COMMENTS)) // End the search
Err_WrongSyllabusFormatExit ();
2014-12-01 23:55:08 +01:00
}
else if (Result == -1)
Err_WrongSyllabusFormatExit ();
2014-12-01 23:55:08 +01:00
}
/***** Close the file with the syllabus *****/
Syl_CloseXMLFile (&XML);
2014-12-01 23:55:08 +01:00
/***** Initialize other fields in the list *****/
2020-02-24 19:31:55 +01:00
if (Syl_LstItemsSyllabus.NumItems)
2014-12-01 23:55:08 +01:00
{
for (NumItem = 0;
2020-02-24 19:31:55 +01:00
NumItem < Syl_LstItemsSyllabus.NumItems - 1;
2014-12-01 23:55:08 +01:00
NumItem++)
2020-02-24 19:31:55 +01:00
if (Syl_LstItemsSyllabus.Lst[NumItem].Level < Syl_LstItemsSyllabus.Lst[NumItem + 1].Level)
2014-12-01 23:55:08 +01:00
{
2020-02-24 19:31:55 +01:00
Syl_LstItemsSyllabus.Lst[NumItem].HasChildren = true;
2014-12-01 23:55:08 +01:00
NumItemsWithChildren++;
}
else
2020-02-24 19:31:55 +01:00
Syl_LstItemsSyllabus.Lst[NumItem].HasChildren = false;
Syl_LstItemsSyllabus.Lst[Syl_LstItemsSyllabus.NumItems - 1].HasChildren = false;
2014-12-01 23:55:08 +01:00
}
2020-02-24 19:31:55 +01:00
Syl_LstItemsSyllabus.NumItemsWithChildren = NumItemsWithChildren;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Free list of items of a syllabus ********************/
/*****************************************************************************/
void Syl_FreeListItemsSyllabus (void)
{
2020-02-24 19:31:55 +01:00
if (Syl_LstItemsSyllabus.Lst)
2014-12-01 23:55:08 +01:00
{
2020-02-24 19:31:55 +01:00
free (Syl_LstItemsSyllabus.Lst);
Syl_LstItemsSyllabus.Lst = NULL;
Syl_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 (FILE *XML)
2014-12-01 23:55:08 +01:00
{
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 (XML,"nivel=\"",Str_NO_SKIP_HTML_COMMENTS))
Err_WrongSyllabusFormatExit ();
if (Str_ReadFileUntilBoundaryStr (XML,StrlLevel,"\"",1,
2017-01-28 15:58:46 +01:00
(unsigned long long) (11 + 1)) != 1)
Err_WrongSyllabusFormatExit ();
2014-12-01 23:55:08 +01:00
if (sscanf (StrlLevel,"%d",&Level) != 1)
Err_WrongSyllabusFormatExit ();
Str_FindStrInFile (XML,">",Str_NO_SKIP_HTML_COMMENTS);
2014-12-01 23:55:08 +01:00
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 *****************/
/*****************************************************************************/
static void Syl_ShowSyllabus (struct Syl_Syllabus *Syllabus)
2014-12-01 23:55:08 +01:00
{
extern const Act_Action_t Inf_ActionsSeeInfo[Inf_NUM_TYPES];
extern const char *Txt_INFO_TITLE[Inf_NUM_TYPES];
2017-09-10 23:24:23 +02:00
extern const char *Hlp_COURSE_Syllabus_edit;
extern const char *Hlp_COURSE_Syllabus;
extern const char *Txt_Done;
2014-12-01 23:55:08 +01:00
unsigned NumItem;
int Col;
static const char **HelpLink[Vie_NUM_VIEW_TYPES] =
{
[Vie_VIEW] = &Hlp_COURSE_Syllabus,
[Vie_EDIT] = &Hlp_COURSE_Syllabus_edit,
};
static int NumButtons[Vie_NUM_VIEW_TYPES] =
{
[Vie_VIEW] = 0,
[Vie_EDIT] = 5,
};
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);
bool ICanEdit = Gbl.Usrs.Me.Role.Logged == Rol_TCH ||
Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM;
bool PutIconToEdit = Syllabus->ViewType == Vie_VIEW && ICanEdit;
2014-12-01 23:55:08 +01:00
/***** Begin box *****/
Box_BoxBegin (NULL,Txt_INFO_TITLE[Gbl.Crs.Info.Type],
PutIconToEdit ? Inf_PutIconToEditInfo :
NULL,
PutIconToEdit ? &Gbl.Crs.Info.Type :
NULL,
*HelpLink[Syllabus->ViewType],Box_NOT_CLOSABLE);
/****** Form to select syllabus *****/
Syl_PutFormWhichSyllabus (Syllabus->WhichSyllabus);
/***** Begin table *****/
HTM_TABLE_BeginWide ();
/***** Set width of columns of the table *****/
HTM_Txt ("<colgroup>");
for (Col = 0;
Col < NumButtons[Syllabus->ViewType];
Col++)
HTM_Txt ("<col width=\"12\" />");
for (Col = 1;
Col <= Syl_LstItemsSyllabus.NumLevels;
Col++)
HTM_TxtF ("<col width=\"%d\" />",Col * Syl_WIDTH_NUM_SYLLABUS);
HTM_Txt ("<col width=\"*\" />");
HTM_Txt ("</colgroup>");
if (Syl_LstItemsSyllabus.NumItems)
/***** Loop writing all items of the syllabus *****/
for (NumItem = 0;
NumItem < Syl_LstItemsSyllabus.NumItems;
NumItem++)
{
Syl_ShowRowSyllabus (Syllabus,NumItem,
Syl_LstItemsSyllabus.Lst[NumItem].Level,
Syl_LstItemsSyllabus.Lst[NumItem].CodItem,
Syl_LstItemsSyllabus.Lst[NumItem].Text,false);
if (ShowRowInsertNewItem && NumItem == Syllabus->NumItem)
// Mostrar a new row where se puede insert a new item
Syl_ShowRowSyllabus (Syllabus,NumItem + 1,
Syl_LstItemsSyllabus.Lst[NumItem].Level,NULL,
"",true);
}
else if (Syllabus->ViewType == Vie_EDIT)
/***** If the syllabus is empty ==>
show form to add a iten to the end *****/
Syl_ShowRowSyllabus (Syllabus,0,
1,Syl_LstItemsSyllabus.Lst[0].CodItem,"",true);
2017-09-10 23:24:23 +02:00
/***** End table *****/
HTM_TABLE_End ();
/***** Button to view *****/
if (Syllabus->ViewType == Vie_EDIT)
{
Frm_BeginForm (Inf_ActionsSeeInfo[Gbl.Crs.Info.Type]);
Btn_PutConfirmButton (Txt_Done);
Frm_EndForm ();
}
/***** End box *****/
Box_BoxEnd ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******** Write a row (item) of a syllabus of lectures or practicals *********/
/*****************************************************************************/
2020-04-12 02:47:32 +02:00
static void Syl_ShowRowSyllabus (struct Syl_Syllabus *Syllabus,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
{
2015-07-22 18:59:44 +02:00
extern const char *Txt_Movement_not_allowed;
2014-12-01 23:55:08 +01:00
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;
Syllabus->ParNumItem = NumItem; // Used as parameter in forms
2017-09-10 23:24:23 +02:00
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);
/***** Begin the row *****/
2019-10-23 19:05:05 +02:00
HTM_TR_Begin (NULL);
2014-12-01 23:55:08 +01:00
switch (Syllabus->ViewType)
{
case Vie_VIEW:
/***** Indent depending on the level *****/
if (Level > 1)
{
HTM_TD_Begin ("colspan=\"%d\" class=\"%s\"",
Level - 1,The_GetColorRows ());
HTM_TD_End ();
}
/***** Code of the item *****/
HTM_TD_Begin ("class=\"RT %s_%s %s\" style=\"width:%dpx;\"",
ClassSyllabus[Level],The_GetSuffix (),
The_GetColorRows (),
Level * Syl_WIDTH_NUM_SYLLABUS);
if (Level == 1)
HTM_NBSP ();
HTM_TxtF ("%s&nbsp;",StrItemCod);
HTM_TD_End ();
/***** Text of the item *****/
HTM_TD_Begin ("colspan=\"%d\" class=\"LT %s_%s %s\"",
Syl_LstItemsSyllabus.NumLevels - Level + 1,
ClassSyllabus[Level],The_GetSuffix (),
The_GetColorRows ());
HTM_Txt (Text);
HTM_TD_End ();
break;
case Vie_EDIT:
if (NewItem)
{
HTM_TD_Begin ("colspan=\"5\" class=\"%s\"",
The_GetColorRows ());
HTM_TD_End ();
}
else
{
/***** Icon to remove the row *****/
HTM_TD_Begin ("class=\"BM %s\"",The_GetColorRows ());
if (Syl_LstItemsSyllabus.Lst[NumItem].HasChildren)
Ico_PutIconRemovalNotAllowed ();
else
Ico_PutContextualIconToRemove (Gbl.Crs.Info.Type == Inf_LECTURES ? ActDelItmSylLec :
ActDelItmSylPra,NULL,
Syl_PutParNumItem,&Syllabus->ParNumItem);
HTM_TD_End ();
/***** Icon to get up an item *****/
Syl_CalculateUpSubtreeSyllabus (&Subtree,NumItem);
HTM_TD_Begin ("class=\"BM %s\"",The_GetColorRows ());
if (Subtree.MovAllowed)
Lay_PutContextualLinkOnlyIcon (Gbl.Crs.Info.Type == Inf_LECTURES ? ActUp_IteSylLec :
ActUp_IteSylPra,
NULL,
Syl_PutParNumItem,&Syllabus->ParNumItem,
"arrow-up.svg",Ico_BLACK);
else
Ico_PutIconOff ("arrow-up.svg",Ico_BLACK,
Txt_Movement_not_allowed);
HTM_TD_End ();
/***** Icon to get down item *****/
Syl_CalculateDownSubtreeSyllabus (&Subtree,NumItem);
HTM_TD_Begin ("class=\"BM %s\"",The_GetColorRows ());
if (Subtree.MovAllowed)
Lay_PutContextualLinkOnlyIcon (Gbl.Crs.Info.Type == Inf_LECTURES ? ActDwnIteSylLec :
ActDwnIteSylPra,
NULL,
Syl_PutParNumItem,&Syllabus->ParNumItem,
"arrow-down.svg",Ico_BLACK);
else
Ico_PutIconOff ("arrow-down.svg",Ico_BLACK,
Txt_Movement_not_allowed);
HTM_TD_End ();
/***** Icon to increase the level of an item *****/
HTM_TD_Begin ("class=\"BM %s\"",The_GetColorRows ());
if (Level > 1)
Lay_PutContextualLinkOnlyIcon (Gbl.Crs.Info.Type == Inf_LECTURES ? ActRgtIteSylLec :
ActRgtIteSylPra,
NULL,
Syl_PutParNumItem,&Syllabus->ParNumItem,
"arrow-left.svg",Ico_BLACK);
else
Ico_PutIconOff ("arrow-left.svg",Ico_BLACK,
Txt_Movement_not_allowed);
HTM_TD_End ();
/***** Icon to decrease level item *****/
HTM_TD_Begin ("class=\"BM %s\"",The_GetColorRows ());
if (Level < LastLevel + 1 &&
Level < Syl_MAX_LEVELS_SYLLABUS)
Lay_PutContextualLinkOnlyIcon (Gbl.Crs.Info.Type == Inf_LECTURES ? ActLftIteSylLec :
ActLftIteSylPra,
NULL,
Syl_PutParNumItem,&Syllabus->ParNumItem,
"arrow-right.svg",Ico_BLACK);
else
Ico_PutIconOff ("arrow-right.svg",Ico_BLACK,
Txt_Movement_not_allowed);
HTM_TD_End ();
LastLevel = Level;
}
2014-12-01 23:55:08 +01:00