Version19.144

This commit is contained in:
Antonio Cañas Vargas 2020-03-05 10:35:23 +01:00
parent 8f09fe9b57
commit e11203e673
6 changed files with 245 additions and 175 deletions

View File

@ -497,7 +497,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
En OpenSWAD: En OpenSWAD:
ps2pdf source.ps destination.pdf ps2pdf source.ps destination.pdf
*/ */
#define Log_PLATFORM_VERSION "SWAD 19.143.1 (2020-03-05)" #define Log_PLATFORM_VERSION "SWAD 19.144 (2020-03-05)"
#define CSS_FILE "swad19.141.6.css" #define CSS_FILE "swad19.141.6.css"
#define JS_FILE "swad19.91.1.js" #define JS_FILE "swad19.91.1.js"
/* /*
@ -524,8 +524,9 @@ Param
// TODO: Miguel Damas: al principio de los exámenes tendría que poner cuánto resta cada pregunta // TODO: Miguel Damas: al principio de los exámenes tendría que poner cuánto resta cada pregunta
// TODO: Si el alumno ha marcado "Permitir que los profesores...", entonces pedir confirmación al pulsar el botón azul, para evitar que se envíe por error antes de tiempo // TODO: Si el alumno ha marcado "Permitir que los profesores...", entonces pedir confirmación al pulsar el botón azul, para evitar que se envíe por error antes de tiempo
// TODO: Oresti Baños: cambiar ojos por candados en descriptores para prohibir/permitir y dejar los ojos para poder elegir descriptores // TODO: Oresti Baños: cambiar ojos por candados en descriptores para prohibir/permitir y dejar los ojos para poder elegir descriptores
// TODO: Hide/show items should hide/show subtrees
Version 19.144: Mar 05, 2020 Code refactoring in edition of course program.
Show hidden subtrees. (282248 lines)
Version 19.143.1: Mar 05, 2020 Code refactoring in edition of course program. (282190 lines) Version 19.143.1: Mar 05, 2020 Code refactoring in edition of course program. (282190 lines)
Version 19.143: Mar 05, 2020 Changes in edition of course program. (282214 lines) Version 19.143: Mar 05, 2020 Changes in edition of course program. (282214 lines)
Version 19.142: Mar 04, 2020 Highlighted subtree of course program. (282277 lines) Version 19.142: Mar 04, 2020 Highlighted subtree of course program. (282277 lines)

View File

@ -1330,7 +1330,7 @@ static void Brw_PutIconToContractFolder (const char *FileBrowserId,const char *R
static void Brw_PutIconShow (const char *Anchor); static void Brw_PutIconShow (const char *Anchor);
static void Brw_PutIconHide (const char *Anchor); static void Brw_PutIconHide (const char *Anchor);
static bool Brw_CheckIfAnyUpperLevelIsHidden (unsigned CurrentLevel); static bool Brw_CheckIfAnyHigherLevelIsHidden (unsigned CurrentLevel);
static void Brw_PutIconFolder (unsigned Level, static void Brw_PutIconFolder (unsigned Level,
const char *FileBrowserId,const char *RowId, const char *FileBrowserId,const char *RowId,
@ -4103,14 +4103,14 @@ static void Brw_WriteSubtitleOfFileBrowser (void)
} }
/*****************************************************************************/ /*****************************************************************************/
/************ Initialize hidden levels of download tree to false *************/ /************ Initialize hidden levels of file browser to false **************/
/*****************************************************************************/ /*****************************************************************************/
static void Brw_InitHiddenLevels (void) static void Brw_InitHiddenLevels (void)
{ {
unsigned Level; unsigned Level;
for (Level = 0; for (Level = 0;
Level <= Brw_MAX_DIR_LEVELS; Level <= Brw_MAX_DIR_LEVELS;
Level++) Level++)
Gbl.FileBrowser.HiddenLevels[Level] = false; Gbl.FileBrowser.HiddenLevels[Level] = false;
@ -5508,18 +5508,12 @@ static bool Brw_WriteRowFileBrowser (unsigned Level,const char *RowId,
return false; return false;
if (AdminDocsZone || AdminMarks) if (AdminDocsZone || AdminMarks)
{ {
if (Gbl.FileBrowser.FilFolLnk.Type == Brw_IS_FOLDER)
Gbl.FileBrowser.HiddenLevels[Level] = RowSetAsHidden;
if (RowSetAsHidden) // this row is marked as hidden if (RowSetAsHidden) // this row is marked as hidden
{
if (Gbl.FileBrowser.FilFolLnk.Type == Brw_IS_FOLDER)
Gbl.FileBrowser.HiddenLevels[Level] = true;
LightStyle = true; LightStyle = true;
}
else // this row is not marked as hidden else // this row is not marked as hidden
{ LightStyle = Brw_CheckIfAnyHigherLevelIsHidden (Level);
if (Gbl.FileBrowser.FilFolLnk.Type == Brw_IS_FOLDER)
Gbl.FileBrowser.HiddenLevels[Level] = false;
LightStyle = Brw_CheckIfAnyUpperLevelIsHidden (Level);
}
} }
} }
@ -5992,20 +5986,20 @@ static void Brw_PutIconHide (const char *Anchor)
} }
/*****************************************************************************/ /*****************************************************************************/
/**** Check if any level of folders superior to the current one is hidden ****/ /********* Check if any level higher than the current one is hidden **********/
/*****************************************************************************/ /*****************************************************************************/
static bool Brw_CheckIfAnyUpperLevelIsHidden (unsigned CurrentLevel) static bool Brw_CheckIfAnyHigherLevelIsHidden (unsigned CurrentLevel)
{ {
unsigned N; unsigned Level;
for (N = 0; for (Level = 0;
N < CurrentLevel; Level < CurrentLevel;
N++) Level++)
if (Gbl.FileBrowser.HiddenLevels[N]) if (Gbl.FileBrowser.HiddenLevels[Level]) // Hidden
return true; return true;
return false; return false; // None is hidden. All are visible.
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -297,10 +297,6 @@ void Gbl_InitializeGlobals (void)
Gbl.Search.Str[0] = '\0'; Gbl.Search.Str[0] = '\0';
Gbl.Search.LogSearch = false; Gbl.Search.LogSearch = false;
Gbl.Prg.LstIsRead = false; // List is not read
Gbl.Prg.Num = 0;
Gbl.Prg.LstItems = NULL;
Gbl.Asgs.LstIsRead = false; // List is not read Gbl.Asgs.LstIsRead = false; // List is not read
Gbl.Asgs.Num = 0; Gbl.Asgs.Num = 0;
Gbl.Asgs.LstAsgCods = NULL; Gbl.Asgs.LstAsgCods = NULL;

View File

@ -538,13 +538,6 @@ struct Globals
char TmpDir[NAME_MAX + 1]; char TmpDir[NAME_MAX + 1];
} ZIP; } ZIP;
} FileBrowser; // Struct used for a file browser } FileBrowser; // Struct used for a file browser
struct
{
bool LstIsRead; // Is the list already read from database...
// ...or it needs to be read?
unsigned Num; // Number of items
struct ProgramItemHierarchy *LstItems; // List of items
} Prg;
struct struct
{ {
bool LstIsRead; // Is the list already read from database... bool LstIsRead; // Is the list already read from database...

View File

@ -56,10 +56,31 @@ extern struct Globals Gbl;
/***************************** Private constants *****************************/ /***************************** Private constants *****************************/
/*****************************************************************************/ /*****************************************************************************/
#define Prg_MAX_CHARS_PROGRAM_ITEM_TITLE (128 - 1) // 127
#define Prg_MAX_BYTES_PROGRAM_ITEM_TITLE ((Prg_MAX_CHARS_PROGRAM_ITEM_TITLE + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047
/*****************************************************************************/ /*****************************************************************************/
/******************************* Private types *******************************/ /******************************* Private types *******************************/
/*****************************************************************************/ /*****************************************************************************/
struct ProgramItemHierarchy
{
long ItmCod;
unsigned Index;
unsigned Level;
bool Hidden;
};
struct ProgramItem
{
struct ProgramItemHierarchy Hierarchy;
unsigned NumItem;
long UsrCod;
time_t TimeUTC[Dat_NUM_START_END_TIME];
bool Open;
char Title[Prg_MAX_BYTES_PROGRAM_ITEM_TITLE + 1];
};
typedef enum typedef enum
{ {
Prg_DONT_PUT_FORM_ITEM, Prg_DONT_PUT_FORM_ITEM,
@ -87,14 +108,40 @@ struct Subtree
unsigned End; unsigned End;
}; };
struct Level
{
unsigned Number; // Numbers for each level from 1 to maximum level
bool Hidden; // If each level from 1 to maximum level is hidden
};
/*****************************************************************************/ /*****************************************************************************/
/***************************** Private variables *****************************/ /***************************** Private variables *****************************/
/*****************************************************************************/ /*****************************************************************************/
static long Prg_CurrentItmCod; // Used as parameter in contextual links static struct
{
static unsigned Prg_MaxLevel; // Maximum level of items struct
static unsigned *Prg_NumItem = NULL; // Numbers for each level from 1 to maximum level {
bool IsRead; // Is the list already read from database...
// ...or it needs to be read?
unsigned NumItems; // Number of items
struct ProgramItemHierarchy *Items; // List of items
} List;
unsigned MaxLevel; // Maximum level of items
struct Level *Levels; // Numbers and hidden for each level from 1 to maximum level
long CurrentItmCod; // Used as parameter in contextual links
} Prg_Gbl =
{
.List =
{
.IsRead = false,
.NumItems = 0,
.Items = NULL,
},
.MaxLevel = 0,
.Levels = NULL,
.CurrentItmCod = -1L
};
/*****************************************************************************/ /*****************************************************************************/
/***************************** Private prototypes ****************************/ /***************************** Private prototypes ****************************/
@ -113,14 +160,20 @@ static void Prg_ShowOneItem (unsigned NumItem,const struct ProgramItem *Item,
static void Prg_ShowItemForm (Prg_CreateOrChangeItem_t CreateOrChangeItem, static void Prg_ShowItemForm (Prg_CreateOrChangeItem_t CreateOrChangeItem,
long ParamItmCod,unsigned FormLevel); long ParamItmCod,unsigned FormLevel);
static void Prg_SetMaxItemLevel (unsigned Level);
static unsigned Prg_GetMaxItemLevel (void); static unsigned Prg_GetMaxItemLevel (void);
static void Prg_CreateNumbers (unsigned MaxLevel); static unsigned Prg_CalculateMaxItemLevel (void);
static void Prg_FreeNumbers (void); static void Prg_CreateLevels (void);
static void Prg_FreeLevels (void);
static void Prg_IncreaseNumItem (unsigned Level); static void Prg_IncreaseNumItem (unsigned Level);
static unsigned Prg_GetNumItem (unsigned Level); static unsigned Prg_GetCurrentNumberInLevel (unsigned Level);
static void Prg_WriteNumItem (unsigned Level); static void Prg_WriteNumItem (unsigned Level);
static void Prg_WriteNumNewItem (unsigned Level); static void Prg_WriteNumNewItem (unsigned Level);
static void Prg_SetHiddenLevel (unsigned Level,bool Hidden);
static bool Prg_GetHiddenLevel (unsigned Level);
static bool Prg_CheckIfAnyHigherLevelIsHidden (unsigned CurrentLevel);
static void Prg_PutFormsToRemEditOnePrgItem (unsigned NumItem, static void Prg_PutFormsToRemEditOnePrgItem (unsigned NumItem,
const struct ProgramItem *Item); const struct ProgramItem *Item);
static bool Prg_CheckIfMoveUpIsAllowed (unsigned NumItem); static bool Prg_CheckIfMoveUpIsAllowed (unsigned NumItem);
@ -207,9 +260,9 @@ static void Prg_ShowAllItems (Prg_CreateOrChangeItem_t CreateOrChangeItem,
unsigned NumItem; unsigned NumItem;
struct ProgramItem Item; struct ProgramItem Item;
/***** Create numbers *****/ /***** Create numbers and hidden levels *****/
Prg_MaxLevel = Prg_GetMaxItemLevel (); Prg_SetMaxItemLevel (Prg_CalculateMaxItemLevel ());
Prg_CreateNumbers (Prg_MaxLevel); Prg_CreateLevels ();
/***** Begin box *****/ /***** Begin box *****/
Box_BoxBegin ("100%",Txt_Course_program,Prg_PutIconsListItems, Box_BoxBegin ("100%",Txt_Course_program,Prg_PutIconsListItems,
@ -220,11 +273,11 @@ static void Prg_ShowAllItems (Prg_CreateOrChangeItem_t CreateOrChangeItem,
/***** Write all the program items *****/ /***** Write all the program items *****/
for (NumItem = 0; for (NumItem = 0;
NumItem < Gbl.Prg.Num; NumItem < Prg_Gbl.List.NumItems;
NumItem++) NumItem++)
{ {
/* Get data of this program item */ /* Get data of this program item */
Item.Hierarchy.ItmCod = Gbl.Prg.LstItems[NumItem].ItmCod; Item.Hierarchy.ItmCod = Prg_Gbl.List.Items[NumItem].ItmCod;
Prg_GetDataOfItemByCod (&Item); Prg_GetDataOfItemByCod (&Item);
/* Show item */ /* Show item */
@ -262,8 +315,8 @@ static void Prg_ShowAllItems (Prg_CreateOrChangeItem_t CreateOrChangeItem,
/***** End box *****/ /***** End box *****/
Box_BoxEnd (); Box_BoxEnd ();
/***** Free numbers *****/ /***** Free hidden levels and numbers *****/
Prg_FreeNumbers (); Prg_FreeLevels ();
} }
/*****************************************************************************/ /*****************************************************************************/
@ -331,12 +384,20 @@ static void Prg_ShowOneItem (unsigned NumItem,const struct ProgramItem *Item,
{ {
static unsigned UniqueId = 0; static unsigned UniqueId = 0;
static bool FirstTBodyOpen = false; static bool FirstTBodyOpen = false;
bool LightStyle;
char *Id; char *Id;
unsigned ColSpan; unsigned ColSpan;
unsigned NumCol; unsigned NumCol;
Dat_StartEndTime_t StartEndTime; Dat_StartEndTime_t StartEndTime;
char Txt[Cns_MAX_BYTES_TEXT + 1]; char Txt[Cns_MAX_BYTES_TEXT + 1];
/***** Check if this item should be shown as hidden *****/
Prg_SetHiddenLevel (Item->Hierarchy.Level,Item->Hierarchy.Hidden);
if (Item->Hierarchy.Hidden) // this item is marked as hidden
LightStyle = true;
else // this item is not marked as hidden
LightStyle = Prg_CheckIfAnyHigherLevelIsHidden (Item->Hierarchy.Level);
/***** Increase number of item *****/ /***** Increase number of item *****/
Prg_IncreaseNumItem (Item->Hierarchy.Level); Prg_IncreaseNumItem (Item->Hierarchy.Level);
@ -381,8 +442,8 @@ static void Prg_ShowOneItem (unsigned NumItem,const struct ProgramItem *Item,
/***** Item number *****/ /***** Item number *****/
HTM_TD_Begin ("class=\"%s RT COLOR%u\" style=\"width:%dpx;\"", HTM_TD_Begin ("class=\"%s RT COLOR%u\" style=\"width:%dpx;\"",
Item->Hierarchy.Hidden ? "ASG_TITLE_LIGHT" : LightStyle ? "ASG_TITLE_LIGHT" :
"ASG_TITLE", "ASG_TITLE",
Gbl.RowEvenOdd, Gbl.RowEvenOdd,
Item->Hierarchy.Level * Prg_WIDTH_NUM_ITEM); Item->Hierarchy.Level * Prg_WIDTH_NUM_ITEM);
Prg_WriteNumItem (Item->Hierarchy.Level); Prg_WriteNumItem (Item->Hierarchy.Level);
@ -390,7 +451,7 @@ static void Prg_ShowOneItem (unsigned NumItem,const struct ProgramItem *Item,
/***** Title and text *****/ /***** Title and text *****/
/* Begin title and text */ /* Begin title and text */
ColSpan = (Prg_MaxLevel + 2) - Item->Hierarchy.Level; ColSpan = (Prg_GetMaxItemLevel () + 2) - Item->Hierarchy.Level;
if (PrintView) if (PrintView)
HTM_TD_Begin ("colspan=\"%u\" class=\"LT\"", HTM_TD_Begin ("colspan=\"%u\" class=\"LT\"",
ColSpan); ColSpan);
@ -400,8 +461,8 @@ static void Prg_ShowOneItem (unsigned NumItem,const struct ProgramItem *Item,
/* Title */ /* Title */
HTM_DIV_Begin ("class=\"%s\"", HTM_DIV_Begin ("class=\"%s\"",
Item->Hierarchy.Hidden ? "ASG_TITLE_LIGHT" : LightStyle ? "ASG_TITLE_LIGHT" :
"ASG_TITLE"); "ASG_TITLE");
HTM_Txt (Item->Title); HTM_Txt (Item->Title);
HTM_DIV_End (); HTM_DIV_End ();
@ -410,8 +471,8 @@ static void Prg_ShowOneItem (unsigned NumItem,const struct ProgramItem *Item,
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML
Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
HTM_DIV_Begin ("class=\"PAR %s\"",Item->Hierarchy.Hidden ? "DAT_LIGHT" : HTM_DIV_Begin ("class=\"PAR %s\"",LightStyle ? "DAT_LIGHT" :
"DAT"); "DAT");
HTM_Txt (Txt); HTM_Txt (Txt);
HTM_DIV_End (); HTM_DIV_End ();
@ -430,17 +491,17 @@ static void Prg_ShowOneItem (unsigned NumItem,const struct ProgramItem *Item,
if (PrintView) if (PrintView)
HTM_TD_Begin ("id=\"%s\" class=\"%s LT\"", HTM_TD_Begin ("id=\"%s\" class=\"%s LT\"",
Id, Id,
Item->Hierarchy.Hidden ? (Item->Open ? "DATE_GREEN_LIGHT" : LightStyle ? (Item->Open ? "DATE_GREEN_LIGHT" :
"DATE_RED_LIGHT") : "DATE_RED_LIGHT") :
(Item->Open ? "DATE_GREEN" : (Item->Open ? "DATE_GREEN" :
"DATE_RED")); "DATE_RED"));
else else
HTM_TD_Begin ("id=\"%s\" class=\"%s LT COLOR%u\"", HTM_TD_Begin ("id=\"%s\" class=\"%s LT COLOR%u\"",
Id, Id,
Item->Hierarchy.Hidden ? (Item->Open ? "DATE_GREEN_LIGHT" : LightStyle ? (Item->Open ? "DATE_GREEN_LIGHT" :
"DATE_RED_LIGHT") : "DATE_RED_LIGHT") :
(Item->Open ? "DATE_GREEN" : (Item->Open ? "DATE_GREEN" :
"DATE_RED"), "DATE_RED"),
Gbl.RowEvenOdd); Gbl.RowEvenOdd);
Dat_WriteLocalDateHMSFromUTC (Id,Item->TimeUTC[StartEndTime], Dat_WriteLocalDateHMSFromUTC (Id,Item->TimeUTC[StartEndTime],
Gbl.Prefs.DateFormat,Dat_SEPARATOR_BREAK, Gbl.Prefs.DateFormat,Dat_SEPARATOR_BREAK,
@ -456,10 +517,10 @@ static void Prg_ShowOneItem (unsigned NumItem,const struct ProgramItem *Item,
if (Item->Hierarchy.Index == ToHighlight->End) // End of the highlighted subtree if (Item->Hierarchy.Index == ToHighlight->End) // End of the highlighted subtree
{ {
HTM_TBODY_End (); // Highlighted tbody end HTM_TBODY_End (); // Highlighted tbody end
if (NumItem < Gbl.Prg.Num - 1) // Not the last item if (NumItem < Prg_Gbl.List.NumItems - 1) // Not the last item
HTM_TBODY_Begin (NULL); // 3rd tbody begin HTM_TBODY_Begin (NULL); // 3rd tbody begin
} }
else if (NumItem == Gbl.Prg.Num - 1) // Last item else if (NumItem == Prg_Gbl.List.NumItems - 1) // Last item
HTM_TBODY_End (); // 3rd tbody end HTM_TBODY_End (); // 3rd tbody end
} }
@ -508,7 +569,7 @@ static void Prg_ShowItemForm (Prg_CreateOrChangeItem_t CreateOrChangeItem,
HTM_TD_End (); HTM_TD_End ();
/***** Show form to create new item as child *****/ /***** Show form to create new item as child *****/
ColSpan = (Prg_MaxLevel + 4) - FormLevel; ColSpan = (Prg_GetMaxItemLevel () + 4) - FormLevel;
HTM_TD_Begin ("colspan=\"%u\" class=\"LT COLOR%u\"", HTM_TD_Begin ("colspan=\"%u\" class=\"LT COLOR%u\"",
ColSpan,Gbl.RowEvenOdd); ColSpan,Gbl.RowEvenOdd);
HTM_ARTICLE_Begin ("item_form"); HTM_ARTICLE_Begin ("item_form");
@ -524,21 +585,34 @@ static void Prg_ShowItemForm (Prg_CreateOrChangeItem_t CreateOrChangeItem,
} }
/*****************************************************************************/ /*****************************************************************************/
/******************* Get maximum level in a course program *******************/ /************** Set and get maximum level in a course program ****************/
/*****************************************************************************/ /*****************************************************************************/
// Return 0 if no items
static void Prg_SetMaxItemLevel (unsigned Level)
{
Prg_Gbl.MaxLevel = Level;
}
static unsigned Prg_GetMaxItemLevel (void) static unsigned Prg_GetMaxItemLevel (void)
{
return Prg_Gbl.MaxLevel;
}
/*****************************************************************************/
/******** Calculate maximum level of indentation in a course program *********/
/*****************************************************************************/
static unsigned Prg_CalculateMaxItemLevel (void)
{ {
unsigned NumItem; unsigned NumItem;
unsigned MaxLevel = 0; unsigned MaxLevel = 0; // Return 0 if no items
/***** Compute maximum level of all program items *****/ /***** Compute maximum level of all program items *****/
for (NumItem = 0; for (NumItem = 0;
NumItem < Gbl.Prg.Num; NumItem < Prg_Gbl.List.NumItems;
NumItem++) NumItem++)
if (Gbl.Prg.LstItems[NumItem].Level > MaxLevel) if (Prg_Gbl.List.Items[NumItem].Level > MaxLevel)
MaxLevel = Gbl.Prg.LstItems[NumItem].Level; MaxLevel = Prg_Gbl.List.Items[NumItem].Level;
return MaxLevel; return MaxLevel;
} }
@ -547,8 +621,10 @@ static unsigned Prg_GetMaxItemLevel (void)
/********************* Allocate memory for item numbers **********************/ /********************* Allocate memory for item numbers **********************/
/*****************************************************************************/ /*****************************************************************************/
static void Prg_CreateNumbers (unsigned MaxLevel) static void Prg_CreateLevels (void)
{ {
unsigned MaxLevel = Prg_GetMaxItemLevel ();
if (MaxLevel) if (MaxLevel)
{ {
/***** Allocate memory for item numbers and initialize to 0 *****/ /***** Allocate memory for item numbers and initialize to 0 *****/
@ -564,24 +640,25 @@ static void Prg_CreateNumbers (unsigned MaxLevel)
4 1 4 1
5 0 <--- Used to create a new item 5 0 <--- Used to create a new item
*/ */
if ((Prg_NumItem = (unsigned *) calloc (1 + MaxLevel + 1,sizeof (unsigned))) == NULL) if ((Prg_Gbl.Levels = (struct Level *) calloc (1 + MaxLevel + 1,
sizeof (struct Level))) == NULL)
Lay_NotEnoughMemoryExit (); Lay_NotEnoughMemoryExit ();
} }
else else
Prg_NumItem = NULL; Prg_Gbl.Levels = NULL;
} }
/*****************************************************************************/ /*****************************************************************************/
/*********************** Free memory for item numbers ************************/ /*********************** Free memory for item numbers ************************/
/*****************************************************************************/ /*****************************************************************************/
static void Prg_FreeNumbers (void) static void Prg_FreeLevels (void)
{ {
if (Prg_MaxLevel && Prg_NumItem) if (Prg_GetMaxItemLevel () && Prg_Gbl.Levels)
{ {
/***** Free allocated memory for item numbers *****/ /***** Free allocated memory for item numbers *****/
free (Prg_NumItem); free (Prg_Gbl.Levels);
Prg_NumItem = NULL; Prg_Gbl.Levels = NULL;
} }
} }
@ -592,20 +669,20 @@ static void Prg_FreeNumbers (void)
static void Prg_IncreaseNumItem (unsigned Level) static void Prg_IncreaseNumItem (unsigned Level)
{ {
/***** Increase number for this level *****/ /***** Increase number for this level *****/
Prg_NumItem[Level]++; Prg_Gbl.Levels[Level ].Number++;
/***** Reset number for next level (children) *****/ /***** Reset number for next level (children) *****/
Prg_NumItem[Level + 1] = 0; Prg_Gbl.Levels[Level + 1].Number = 0;
} }
/*****************************************************************************/ /*****************************************************************************/
/*********************** Get number of item in a level ***********************/ /****************** Get current number of item in a level ********************/
/*****************************************************************************/ /*****************************************************************************/
static unsigned Prg_GetNumItem (unsigned Level) static unsigned Prg_GetCurrentNumberInLevel (unsigned Level)
{ {
if (Prg_NumItem) if (Prg_Gbl.Levels)
return Prg_NumItem[Level]; return Prg_Gbl.Levels[Level].Number;
return 0; return 0;
} }
@ -625,7 +702,7 @@ static void Prg_WriteNumItem (unsigned Level)
{ {
if (i > 1) if (i > 1)
HTM_Txt ("."); HTM_Txt (".");
HTM_Unsigned (Prg_GetNumItem (i)); HTM_Unsigned (Prg_GetCurrentNumberInLevel (i));
} }
} }
@ -641,12 +718,47 @@ static void Prg_WriteNumNewItem (unsigned Level)
if (i > 1) if (i > 1)
HTM_Txt ("."); HTM_Txt (".");
if (i < Level) if (i < Level)
HTM_Unsigned (Prg_GetNumItem (i)); HTM_Unsigned (Prg_GetCurrentNumberInLevel (i));
else else
HTM_Unsigned (Prg_GetNumItem (i) + 1); HTM_Unsigned (Prg_GetCurrentNumberInLevel (i) + 1);
} }
} }
/*****************************************************************************/
/********************** Set / Get if a level is hidden ***********************/
/*****************************************************************************/
static void Prg_SetHiddenLevel (unsigned Level,bool Hidden)
{
if (Prg_Gbl.Levels)
Prg_Gbl.Levels[Level].Hidden = Hidden;
}
static bool Prg_GetHiddenLevel (unsigned Level)
{
if (Prg_Gbl.Levels)
return Prg_Gbl.Levels[Level].Hidden;
return false;
}
/*****************************************************************************/
/********* Check if any level higher than the current one is hidden **********/
/*****************************************************************************/
static bool Prg_CheckIfAnyHigherLevelIsHidden (unsigned CurrentLevel)
{
unsigned Level;
for (Level = 1;
Level < CurrentLevel;
Level++)
if (Prg_GetHiddenLevel (Level)) // Hidden?
return true;
return false; // None is hidden. All are visible.
}
/*****************************************************************************/ /*****************************************************************************/
/**************** Put a link (form) to edit one program item *****************/ /**************** Put a link (form) to edit one program item *****************/
/*****************************************************************************/ /*****************************************************************************/
@ -758,8 +870,8 @@ static bool Prg_CheckIfMoveUpIsAllowed (unsigned NumItem)
/***** Move up is allowed if the item has brothers before it *****/ /***** Move up is allowed if the item has brothers before it *****/
// NumItem >= 2 // NumItem >= 2
return Gbl.Prg.LstItems[NumItem - 1].Level >= return Prg_Gbl.List.Items[NumItem - 1].Level >=
Gbl.Prg.LstItems[NumItem ].Level; Prg_Gbl.List.Items[NumItem ].Level;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -772,19 +884,19 @@ static bool Prg_CheckIfMoveDownIsAllowed (unsigned NumItem)
unsigned Level; unsigned Level;
/***** Trivial check: if item is the last one, move up is not allowed *****/ /***** Trivial check: if item is the last one, move up is not allowed *****/
if (NumItem >= Gbl.Prg.Num - 1) if (NumItem >= Prg_Gbl.List.NumItems - 1)
return false; return false;
/***** Move down is allowed if the item has brothers after it *****/ /***** Move down is allowed if the item has brothers after it *****/
// NumItem + 1 < Gbl.Prg.Num // NumItem + 1 < Prg_Gbl.List.NumItems
Level = Gbl.Prg.LstItems[NumItem].Level; Level = Prg_Gbl.List.Items[NumItem].Level;
for (i = NumItem + 1; for (i = NumItem + 1;
i < Gbl.Prg.Num; i < Prg_Gbl.List.NumItems;
i++) i++)
{ {
if (Gbl.Prg.LstItems[i].Level == Level) if (Prg_Gbl.List.Items[i].Level == Level)
return true; // Next brother found return true; // Next brother found
if (Gbl.Prg.LstItems[i].Level < Level) if (Prg_Gbl.List.Items[i].Level < Level)
return false; // Next lower level found ==> there are no more brothers return false; // Next lower level found ==> there are no more brothers
} }
return false; // End reached ==> there are no more brothers return false; // End reached ==> there are no more brothers
@ -797,7 +909,7 @@ static bool Prg_CheckIfMoveDownIsAllowed (unsigned NumItem)
static bool Prg_CheckIfMoveLeftIsAllowed (unsigned NumItem) static bool Prg_CheckIfMoveLeftIsAllowed (unsigned NumItem)
{ {
/***** Move left is allowed if the item has parent *****/ /***** Move left is allowed if the item has parent *****/
return Gbl.Prg.LstItems[NumItem].Level > 1; return Prg_Gbl.List.Items[NumItem].Level > 1;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -812,8 +924,8 @@ static bool Prg_CheckIfMoveRightIsAllowed (unsigned NumItem)
/***** Move right is allowed if the item has brothers before it *****/ /***** Move right is allowed if the item has brothers before it *****/
// NumItem >= 2 // NumItem >= 2
return Gbl.Prg.LstItems[NumItem - 1].Level >= return Prg_Gbl.List.Items[NumItem - 1].Level >=
Gbl.Prg.LstItems[NumItem ].Level; Prg_Gbl.List.Items[NumItem ].Level;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -822,12 +934,12 @@ static bool Prg_CheckIfMoveRightIsAllowed (unsigned NumItem)
static void Prg_SetCurrentItmCod (long ItmCod) static void Prg_SetCurrentItmCod (long ItmCod)
{ {
Prg_CurrentItmCod = ItmCod; Prg_Gbl.CurrentItmCod = ItmCod;
} }
static long Prg_GetCurrentItmCod (void) static long Prg_GetCurrentItmCod (void)
{ {
return Prg_CurrentItmCod; return Prg_Gbl.CurrentItmCod;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -866,7 +978,7 @@ static void Prg_GetListPrgItems (void)
unsigned long NumRows; unsigned long NumRows;
unsigned NumItem; unsigned NumItem;
if (Gbl.Prg.LstIsRead) if (Prg_Gbl.List.IsRead)
Prg_FreeListItems (); Prg_FreeListItems ();
/***** Get list of program items from database *****/ /***** Get list of program items from database *****/
@ -883,43 +995,43 @@ static void Prg_GetListPrgItems (void)
if (NumRows) // Items found... if (NumRows) // Items found...
{ {
Gbl.Prg.Num = (unsigned) NumRows; Prg_Gbl.List.NumItems = (unsigned) NumRows;
/***** Create list of program items *****/ /***** Create list of program items *****/
if ((Gbl.Prg.LstItems = if ((Prg_Gbl.List.Items =
(struct ProgramItemHierarchy *) calloc (NumRows, (struct ProgramItemHierarchy *) calloc (NumRows,
sizeof (struct ProgramItemHierarchy))) == NULL) sizeof (struct ProgramItemHierarchy))) == NULL)
Lay_NotEnoughMemoryExit (); Lay_NotEnoughMemoryExit ();
/***** Get the program items codes *****/ /***** Get the program items codes *****/
for (NumItem = 0; for (NumItem = 0;
NumItem < Gbl.Prg.Num; NumItem < Prg_Gbl.List.NumItems;
NumItem++) NumItem++)
{ {
/* Get row */ /* Get row */
row = mysql_fetch_row (mysql_res); row = mysql_fetch_row (mysql_res);
/* Get code of the program item (row[0]) */ /* Get code of the program item (row[0]) */
if ((Gbl.Prg.LstItems[NumItem].ItmCod = Str_ConvertStrCodToLongCod (row[0])) < 0) if ((Prg_Gbl.List.Items[NumItem].ItmCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Error: wrong program item code."); Lay_ShowErrorAndExit ("Error: wrong program item code.");
/* Get index of the program item (row[1]) */ /* Get index of the program item (row[1]) */
Gbl.Prg.LstItems[NumItem].Index = Str_ConvertStrToUnsigned (row[1]); Prg_Gbl.List.Items[NumItem].Index = Str_ConvertStrToUnsigned (row[1]);
/* Get level of the program item (row[2]) */ /* Get level of the program item (row[2]) */
Gbl.Prg.LstItems[NumItem].Level = Str_ConvertStrToUnsigned (row[2]); Prg_Gbl.List.Items[NumItem].Level = Str_ConvertStrToUnsigned (row[2]);
/* Get whether the program item is hidden or not (row[3]) */ /* Get whether the program item is hidden or not (row[3]) */
Gbl.Prg.LstItems[NumItem].Hidden = (row[3][0] == 'Y'); Prg_Gbl.List.Items[NumItem].Hidden = (row[3][0] == 'Y');
} }
} }
else else
Gbl.Prg.Num = 0; Prg_Gbl.List.NumItems = 0;
/***** Free structure that stores the query result *****/ /***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res); DB_FreeMySQLResult (&mysql_res);
Gbl.Prg.LstIsRead = true; Prg_Gbl.List.IsRead = true;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -1043,13 +1155,13 @@ static void Prg_ResetItem (struct ProgramItem *Item)
static void Prg_FreeListItems (void) static void Prg_FreeListItems (void)
{ {
if (Gbl.Prg.LstIsRead && Gbl.Prg.LstItems) if (Prg_Gbl.List.IsRead && Prg_Gbl.List.Items)
{ {
/***** Free memory used by the list of program items *****/ /***** Free memory used by the list of program items *****/
free (Gbl.Prg.LstItems); free (Prg_Gbl.List.Items);
Gbl.Prg.LstItems = NULL; Prg_Gbl.List.Items = NULL;
Gbl.Prg.Num = 0; Prg_Gbl.List.NumItems = 0;
Gbl.Prg.LstIsRead = false; Prg_Gbl.List.IsRead = false;
} }
} }
@ -1116,14 +1228,14 @@ static unsigned Prg_GetNumItemFromItmCod (long ItmCod)
unsigned NumItem; unsigned NumItem;
/***** List of items must be filled *****/ /***** List of items must be filled *****/
if (!Gbl.Prg.LstIsRead || Gbl.Prg.LstItems == NULL) if (!Prg_Gbl.List.IsRead || Prg_Gbl.List.Items == NULL)
Lay_ShowErrorAndExit ("Wrong list of items."); Lay_ShowErrorAndExit ("Wrong list of items.");
/***** Find item code in list *****/ /***** Find item code in list *****/
for (NumItem = 0; for (NumItem = 0;
NumItem < Gbl.Prg.Num; NumItem < Prg_Gbl.List.NumItems;
NumItem++) NumItem++)
if (Gbl.Prg.LstItems[NumItem].ItmCod == ItmCod) // Found! if (Prg_Gbl.List.Items[NumItem].ItmCod == ItmCod) // Found!
return NumItem; return NumItem;
/***** Not found *****/ /***** Not found *****/
@ -1432,19 +1544,19 @@ static int Prg_GetPrevBrother (int NumItem)
/***** Trivial check: if item is the first one, there is no previous brother *****/ /***** Trivial check: if item is the first one, there is no previous brother *****/
if (NumItem <= 0 || if (NumItem <= 0 ||
NumItem >= (int) Gbl.Prg.Num) NumItem >= (int) Prg_Gbl.List.NumItems)
return -1; return -1;
/***** Get previous brother before item *****/ /***** Get previous brother before item *****/
// 1 <= NumItem < Gbl.Prg.Num // 1 <= NumItem < Prg_Gbl.List.NumItems
Level = Gbl.Prg.LstItems[NumItem].Level; Level = Prg_Gbl.List.Items[NumItem].Level;
for (i = NumItem - 1; for (i = NumItem - 1;
i >= 0; i >= 0;
i--) i--)
{ {
if (Gbl.Prg.LstItems[i].Level == Level) if (Prg_Gbl.List.Items[i].Level == Level)
return i; // Previous brother before item found return i; // Previous brother before item found
if (Gbl.Prg.LstItems[i].Level < Level) if (Prg_Gbl.List.Items[i].Level < Level)
return -1; // Previous lower level found ==> there are no brothers before item return -1; // Previous lower level found ==> there are no brothers before item
} }
return -1; // Start reached ==> there are no brothers before item return -1; // Start reached ==> there are no brothers before item
@ -1462,19 +1574,19 @@ static int Prg_GetNextBrother (int NumItem)
/***** Trivial check: if item is the last one, there is no next brother *****/ /***** Trivial check: if item is the last one, there is no next brother *****/
if (NumItem < 0 || if (NumItem < 0 ||
NumItem >= (int) Gbl.Prg.Num - 1) NumItem >= (int) Prg_Gbl.List.NumItems - 1)
return -1; return -1;
/***** Get next brother after item *****/ /***** Get next brother after item *****/
// 0 <= NumItem < Gbl.Prg.Num - 1 // 0 <= NumItem < Prg_Gbl.List.NumItems - 1
Level = Gbl.Prg.LstItems[NumItem].Level; Level = Prg_Gbl.List.Items[NumItem].Level;
for (i = NumItem + 1; for (i = NumItem + 1;
i < (int) Gbl.Prg.Num; i < (int) Prg_Gbl.List.NumItems;
i++) i++)
{ {
if (Gbl.Prg.LstItems[i].Level == Level) if (Prg_Gbl.List.Items[i].Level == Level)
return i; // Next brother found return i; // Next brother found
if (Gbl.Prg.LstItems[i].Level < Level) if (Prg_Gbl.List.Items[i].Level < Level)
return -1; // Next lower level found ==> there are no brothers after item return -1; // Next lower level found ==> there are no brothers after item
} }
return -1; // End reached ==> there are no brothers after item return -1; // End reached ==> there are no brothers after item
@ -1564,7 +1676,7 @@ static void Prg_SetSubtreeEmpty (struct Subtree *Subtree)
{ {
/***** Range is empty *****/ /***** Range is empty *****/
Subtree->Begin = Subtree->Begin =
Subtree->End = Gbl.Prg.Num; Subtree->End = Prg_Gbl.List.NumItems;
} }
static void Prg_SetSubtreeOnlyItem (unsigned Index,struct Subtree *Subtree) static void Prg_SetSubtreeOnlyItem (unsigned Index,struct Subtree *Subtree)
@ -1577,16 +1689,16 @@ static void Prg_SetSubtreeOnlyItem (unsigned Index,struct Subtree *Subtree)
static void Prg_SetSubtreeWithAllChildren (unsigned NumItem,struct Subtree *Subtree) static void Prg_SetSubtreeWithAllChildren (unsigned NumItem,struct Subtree *Subtree)
{ {
/***** List of items must be filled *****/ /***** List of items must be filled *****/
if (!Gbl.Prg.LstIsRead || Gbl.Prg.LstItems == NULL) if (!Prg_Gbl.List.IsRead || Prg_Gbl.List.Items == NULL)
Lay_ShowErrorAndExit ("Wrong list of items."); Lay_ShowErrorAndExit ("Wrong list of items.");
/***** Number of item must be in the correct range *****/ /***** Number of item must be in the correct range *****/
if (NumItem >= Gbl.Prg.Num) if (NumItem >= Prg_Gbl.List.NumItems)
Lay_ShowErrorAndExit ("Wrong item number."); Lay_ShowErrorAndExit ("Wrong item number.");
/***** Range includes this item and all its children *****/ /***** Range includes this item and all its children *****/
Subtree->Begin = Gbl.Prg.LstItems[NumItem ].Index; Subtree->Begin = Prg_Gbl.List.Items[NumItem ].Index;
Subtree->End = Gbl.Prg.LstItems[Prg_GetLastChild (NumItem)].Index; Subtree->End = Prg_Gbl.List.Items[Prg_GetLastChild (NumItem)].Index;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -1600,20 +1712,20 @@ static unsigned Prg_GetLastChild (int NumItem)
/***** Trivial check: if item is wrong, there are no children *****/ /***** Trivial check: if item is wrong, there are no children *****/
if (NumItem < 0 || if (NumItem < 0 ||
NumItem >= (int) Gbl.Prg.Num) NumItem >= (int) Prg_Gbl.List.NumItems)
Lay_ShowErrorAndExit ("Wrong number of item."); Lay_ShowErrorAndExit ("Wrong number of item.");
/***** Get next brother after item *****/ /***** Get next brother after item *****/
// 0 <= NumItem < Gbl.Prg.Num // 0 <= NumItem < Prg_Gbl.List.NumItems
Level = Gbl.Prg.LstItems[NumItem].Level; Level = Prg_Gbl.List.Items[NumItem].Level;
for (i = NumItem + 1; for (i = NumItem + 1;
i < (int) Gbl.Prg.Num; i < (int) Prg_Gbl.List.NumItems;
i++) i++)
{ {
if (Gbl.Prg.LstItems[i].Level <= Level) if (Prg_Gbl.List.Items[i].Level <= Level)
return i - 1; // Last child found return i - 1; // Last child found
} }
return Gbl.Prg.Num - 1; // End reached ==> all items after the given item are its children return Prg_Gbl.List.NumItems - 1; // End reached ==> all items after the given item are its children
} }
/*****************************************************************************/ /*****************************************************************************/
@ -1636,8 +1748,8 @@ void Prg_RequestCreatePrgItem (void)
if (ParentItmCod > 0) if (ParentItmCod > 0)
{ {
NumItem = Prg_GetNumItemFromItmCod (ParentItmCod); NumItem = Prg_GetNumItemFromItmCod (ParentItmCod);
ItmCodBeforeForm = Gbl.Prg.LstItems[Prg_GetLastChild (NumItem)].ItmCod; ItmCodBeforeForm = Prg_Gbl.List.Items[Prg_GetLastChild (NumItem)].ItmCod;
FormLevel = Gbl.Prg.LstItems[NumItem].Level + 1; FormLevel = Prg_Gbl.List.Items[NumItem].Level + 1;
} }
else else
{ {
@ -1668,7 +1780,7 @@ void Prg_RequestChangePrgItem (void)
ItmCodBeforeForm = Prg_GetParamItmCod (); ItmCodBeforeForm = Prg_GetParamItmCod ();
if (ItmCodBeforeForm > 0) if (ItmCodBeforeForm > 0)
FormLevel = Gbl.Prg.LstItems[Prg_GetNumItemFromItmCod (ItmCodBeforeForm)].Level; FormLevel = Prg_Gbl.List.Items[Prg_GetNumItemFromItmCod (ItmCodBeforeForm)].Level;
else else
FormLevel = 0; FormLevel = 0;
@ -1947,16 +2059,16 @@ static void Prg_InsertItem (const struct ProgramItem *ParentItem,
/***** Get list of program items *****/ /***** Get list of program items *****/
Prg_GetListPrgItems (); Prg_GetListPrgItems ();
if (Gbl.Prg.Num) // There are items if (Prg_Gbl.List.NumItems) // There are items
{ {
if (ParentItem->Hierarchy.ItmCod > 0) // Parent specified if (ParentItem->Hierarchy.ItmCod > 0) // Parent specified
{ {
/***** Calculate where to insert *****/ /***** Calculate where to insert *****/
NumItemLastChild = Prg_GetLastChild (Prg_GetNumItemFromItmCod (ParentItem->Hierarchy.ItmCod)); NumItemLastChild = Prg_GetLastChild (Prg_GetNumItemFromItmCod (ParentItem->Hierarchy.ItmCod));
if (NumItemLastChild < Gbl.Prg.Num - 1) if (NumItemLastChild < Prg_Gbl.List.NumItems - 1)
{ {
/***** New program item will be inserted after last child of parent *****/ /***** New program item will be inserted after last child of parent *****/
Item->Hierarchy.Index = Gbl.Prg.LstItems[NumItemLastChild + 1].Index; Item->Hierarchy.Index = Prg_Gbl.List.Items[NumItemLastChild + 1].Index;
/***** Move down all indexes of after last child of parent *****/ /***** Move down all indexes of after last child of parent *****/
DB_QueryUPDATE ("can not move down items", DB_QueryUPDATE ("can not move down items",
@ -1969,7 +2081,7 @@ static void Prg_InsertItem (const struct ProgramItem *ParentItem,
} }
else else
/***** New program item will be inserted at the end *****/ /***** New program item will be inserted at the end *****/
Item->Hierarchy.Index = Gbl.Prg.LstItems[Gbl.Prg.Num - 1].Index + 1; Item->Hierarchy.Index = Prg_Gbl.List.Items[Prg_Gbl.List.NumItems - 1].Index + 1;
/***** Child ==> parent level + 1 *****/ /***** Child ==> parent level + 1 *****/
Item->Hierarchy.Level = ParentItem->Hierarchy.Level + 1; Item->Hierarchy.Level = ParentItem->Hierarchy.Level + 1;
@ -1977,7 +2089,7 @@ static void Prg_InsertItem (const struct ProgramItem *ParentItem,
else // No parent specified else // No parent specified
{ {
/***** New program item will be inserted at the end *****/ /***** New program item will be inserted at the end *****/
Item->Hierarchy.Index = Gbl.Prg.LstItems[Gbl.Prg.Num - 1].Index + 1; Item->Hierarchy.Index = Prg_Gbl.List.Items[Prg_Gbl.List.NumItems - 1].Index + 1;
/***** First level *****/ /***** First level *****/
Item->Hierarchy.Level = 1; Item->Hierarchy.Level = 1;

View File

@ -27,38 +27,12 @@
/********************************* Headers ***********************************/ /********************************* Headers ***********************************/
/*****************************************************************************/ /*****************************************************************************/
#include "swad_date.h" #include "swad_hierarchy.h"
#include "swad_file_browser.h"
#include "swad_notification.h"
#include "swad_user.h"
/*****************************************************************************/ /*****************************************************************************/
/************************** Public types and constants ***********************/ /************************** Public types and constants ***********************/
/*****************************************************************************/ /*****************************************************************************/
#define Prg_MAX_CHARS_PROGRAM_ITEM_TITLE (128 - 1) // 127
#define Prg_MAX_BYTES_PROGRAM_ITEM_TITLE ((Prg_MAX_CHARS_PROGRAM_ITEM_TITLE + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047
struct ProgramItemHierarchy
{
long ItmCod;
unsigned Index;
unsigned Level;
bool Hidden;
};
struct ProgramItem
{
struct ProgramItemHierarchy Hierarchy;
unsigned NumItem;
long UsrCod;
time_t TimeUTC[Dat_NUM_START_END_TIME];
bool Open;
char Title[Prg_MAX_BYTES_PROGRAM_ITEM_TITLE + 1];
};
#define Prg_ORDER_DEFAULT Dat_START_TIME
/*****************************************************************************/ /*****************************************************************************/
/***************************** Public prototypes *****************************/ /***************************** Public prototypes *****************************/
/*****************************************************************************/ /*****************************************************************************/