diff --git a/swad_action.c b/swad_action.c
index df31826a8..b240e8a5e 100644
--- a/swad_action.c
+++ b/swad_action.c
@@ -408,8 +408,8 @@ const struct Act_Actions Act_Actions[Act_NUM_ACTIONS] =
[ActShoPrgItm ] = {1830,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_ShowPrgItem ,NULL},
[ActUp_PrgItm ] = {1831,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_MoveUpPrgItem ,NULL},
[ActDwnPrgItm ] = {1832,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_MoveDownPrgItem ,NULL},
- [ActRgtPrgItm ] = {1833,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_MoveRightPrgItem ,NULL},
[ActLftPrgItm ] = {1834,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_MoveLeftPrgItem ,NULL},
+ [ActRgtPrgItm ] = {1833,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_MoveRightPrgItem ,NULL},
[ActEdiTchGui ] = { 785,-1,TabUnk,ActSeeTchGui ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Inf_FormsToSelSendInfo ,NULL},
diff --git a/swad_action.h b/swad_action.h
index eab49fe0d..834363111 100644
--- a/swad_action.h
+++ b/swad_action.h
@@ -394,8 +394,8 @@ typedef signed int Act_Action_t; // Must be a signed type, because -1 is used to
#define ActShoPrgItm (ActChgCrsSta + 23)
#define ActUp_PrgItm (ActChgCrsSta + 24)
#define ActDwnPrgItm (ActChgCrsSta + 25)
-#define ActRgtPrgItm (ActChgCrsSta + 26)
-#define ActLftPrgItm (ActChgCrsSta + 27)
+#define ActLftPrgItm (ActChgCrsSta + 26)
+#define ActRgtPrgItm (ActChgCrsSta + 27)
#define ActEdiTchGui (ActChgCrsSta + 28)
#define ActSeeSylLec (ActChgCrsSta + 29)
#define ActSeeSylPra (ActChgCrsSta + 30)
diff --git a/swad_changelog.h b/swad_changelog.h
index 83c0f2bce..41556ced5 100644
--- a/swad_changelog.h
+++ b/swad_changelog.h
@@ -497,7 +497,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
En OpenSWAD:
ps2pdf source.ps destination.pdf
*/
-#define Log_PLATFORM_VERSION "SWAD 19.138.1 (2020-02-29)"
+#define Log_PLATFORM_VERSION "SWAD 19.139 (2020-03-02)"
#define CSS_FILE "swad19.136.css"
#define JS_FILE "swad19.91.1.js"
/*
@@ -523,7 +523,7 @@ Param
// TODO: Miguel Damas: por defecto, marcar "Permitir que los profesores..." en los test (que ya esté marcado en lugar de desmarcado)
// 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
- Version 19.138.2: Feb 29, 2020 Check if arrows are correct (move up is wring). (? lines)
+ Version 19.139: Mar 02, 2020 Changes in course program. (282252 lines)
Version 19.138.1: Feb 29, 2020 Fixed bugs in course program. (282252 lines)
Version 19.138: Feb 29, 2020 Move subtrees up and down in course program. (282230 lines)
Version 19.137: Feb 29, 2020 Removed pagination in course program. (282305 lines)
diff --git a/swad_global.c b/swad_global.c
index 63632d6d1..fbf899c8a 100644
--- a/swad_global.c
+++ b/swad_global.c
@@ -299,7 +299,7 @@ void Gbl_InitializeGlobals (void)
Gbl.Prg.LstIsRead = false; // List is not read
Gbl.Prg.Num = 0;
- Gbl.Prg.LstItmCods = NULL;
+ Gbl.Prg.LstItems = NULL;
Gbl.Asgs.LstIsRead = false; // List is not read
Gbl.Asgs.Num = 0;
diff --git a/swad_global.h b/swad_global.h
index eef10b58a..5eb2f79a8 100644
--- a/swad_global.h
+++ b/swad_global.h
@@ -540,13 +540,15 @@ struct Globals
} 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
- long *LstItmCods; // List of items codes
+ 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
{
- bool LstIsRead; // Is the list already read from database, or it needs to be read?
+ bool LstIsRead; // Is the list already read from database...
+ // ...or it needs to be read?
unsigned Num; // Number of assignments
long *LstAsgCods; // List of assigment codes
Dat_StartEndTime_t SelectedOrder;
diff --git a/swad_program.c b/swad_program.c
index 134fa991c..7543d11b6 100644
--- a/swad_program.c
+++ b/swad_program.c
@@ -79,40 +79,44 @@ static bool Prg_CheckIfICanCreateItems (void);
static void Prg_PutIconsListItems (void);
static void Prg_PutIconToCreateNewItem (void);
static void Prg_PutButtonToCreateNewItem (void);
-static void Prg_ShowOneItem (long ItmCod,unsigned MaxIndex,bool PrintView);
+static void Prg_ShowOneItem (unsigned NumItem,bool PrintView);
static void Prg_CreateNumbers (unsigned MaxLevel);
static void Prg_FreeNumbers (void);
+static void Prg_IncreaseNumItem (unsigned Level);
+static unsigned Prg_GetNumItem (unsigned Level);
static void Prg_WriteNumItem (unsigned Level);
-static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item,
- unsigned MaxIndex,
- const char *Anchor);
+static void Prg_PutFormsToRemEditOnePrgItem (unsigned NumItem,const char *Anchor);
+static bool Prg_CheckIfMoveUpIsAllowed (unsigned NumItem);
+static bool Prg_CheckIfMoveDownIsAllowed (unsigned NumItem);
+static bool Prg_CheckIfMoveLeftIsAllowed (unsigned NumItem);
+static bool Prg_CheckIfMoveRightIsAllowed (unsigned NumItem);
static void Prg_SetCurrentItmCod (long ItmCod);
static long Prg_GetCurrentItmCod (void);
static void Prg_PutParams (void);
+static void Prg_GetListPrgItems (void);
static void Prg_GetDataOfItem (struct ProgramItem *Item,
MYSQL_RES **mysql_res,
unsigned long NumRows);
static void Prg_ResetItem (struct ProgramItem *Item);
static void Prg_GetPrgItemTxtFromDB (long ItmCod,char Txt[Cns_MAX_BYTES_TEXT + 1]);
static void Prg_PutParamItmCod (long ItmCod);
+static long Prg_GetParamItmCod (void);
+
+static unsigned Prg_GetNumItemFromItmCod (unsigned ItmCod);
static unsigned Prg_GetMaxItemLevel (void);
static unsigned Prg_GetMaxItemIndex (void);
-static unsigned Prg_GetPrevIndex (unsigned Index);
-static unsigned Prg_GetParentIndex (unsigned Index,unsigned Level);
-static unsigned Prg_GetNextLowerIndex (unsigned Index,unsigned Level);
-static unsigned Prg_GetPrevBrotherIndex (unsigned Index,unsigned Level);
-static unsigned Prg_GetNextBrotherIndex (unsigned Index,unsigned Level);
-static unsigned Prg_GetLastChildIndex (unsigned Index,unsigned Level);
+static int Prg_GetPrevBrother (int NumItem);
+static int Prg_GetNextBrother (int NumItem);
+static int Prg_GetLastChild (int NumItem);
-static void Prg_ExchangeItems (int TopBegin,int TopEnd,
- int BottomBegin,int BottomEnd);
-static void Prg_MoveItemAndChildrenLeft (const struct ProgramItem *Item);
-static void Prg_MoveItemAndChildrenRight (const struct ProgramItem *Item);
+static void Prg_ExchangeItems (int NumItemTop,int NumItemBottom);
+static void Prg_MoveItemAndChildrenLeft (unsigned NumItem);
+static void Prg_MoveItemAndChildrenRight (unsigned NumItem);
static bool Prg_CheckIfSimilarPrgItemExists (const char *Field,const char *Value,long ItmCod);
static void Prg_ShowLstGrpsToEditPrgItem (long ItmCod);
@@ -176,11 +180,10 @@ static void Prg_ShowAllItems (void)
HTM_TABLE_BeginWideMarginPadding (2);
/***** Write all the program items *****/
- for (NumItem = 1;
- NumItem <= Gbl.Prg.Num;
+ for (NumItem = 0;
+ NumItem < Gbl.Prg.Num;
NumItem++)
- Prg_ShowOneItem (Gbl.Prg.LstItmCods[NumItem - 1],
- Gbl.Prg.Num,
+ Prg_ShowOneItem (NumItem,
false); // Not print view
/***** End table *****/
@@ -262,7 +265,7 @@ static void Prg_PutButtonToCreateNewItem (void)
#define Prg_WIDTH_NUM_ITEM 20
-static void Prg_ShowOneItem (long ItmCod,unsigned MaxIndex,bool PrintView)
+static void Prg_ShowOneItem (unsigned NumItem,bool PrintView)
{
char *Anchor = NULL;
static unsigned UniqueId = 0;
@@ -273,11 +276,12 @@ static void Prg_ShowOneItem (long ItmCod,unsigned MaxIndex,bool PrintView)
char Txt[Cns_MAX_BYTES_TEXT + 1];
/***** Get data of this program item *****/
- Item.ItmCod = ItmCod;
+ Item.Hierarchy.ItmCod = Gbl.Prg.LstItems[NumItem].ItmCod;
Prg_GetDataOfItemByCod (&Item);
+ Prg_IncreaseNumItem (Item.Hierarchy.Level);
/***** Set anchor string *****/
- Frm_SetAnchorStr (Item.ItmCod,&Anchor);
+ Frm_SetAnchorStr (Item.Hierarchy.ItmCod,&Anchor);
/***** Start row *****/
HTM_TR_Begin (NULL);
@@ -286,15 +290,15 @@ static void Prg_ShowOneItem (long ItmCod,unsigned MaxIndex,bool PrintView)
if (!PrintView)
{
HTM_TD_Begin ("class=\"PRG_COL1 LT COLOR%u\"",Gbl.RowEvenOdd);
- Prg_PutFormsToRemEditOnePrgItem (&Item,MaxIndex,Anchor);
+ Prg_PutFormsToRemEditOnePrgItem (NumItem,Anchor);
HTM_TD_End ();
}
/***** Indent depending on the level *****/
- if (Item.Level > 1)
+ if (Item.Hierarchy.Level > 1)
{
HTM_TD_Begin ("colspan=\"%u\" class=\"COLOR%u\"",
- Item.Level - 1,Gbl.RowEvenOdd);
+ Item.Hierarchy.Level - 1,Gbl.RowEvenOdd);
HTM_TD_End ();
}
@@ -303,13 +307,13 @@ static void Prg_ShowOneItem (long ItmCod,unsigned MaxIndex,bool PrintView)
Item.Hidden ? "ASG_TITLE_LIGHT" :
"ASG_TITLE",
Gbl.RowEvenOdd,
- Item.Level * Prg_WIDTH_NUM_ITEM);
- Prg_WriteNumItem (Item.Level);
+ Item.Hierarchy.Level * Prg_WIDTH_NUM_ITEM);
+ Prg_WriteNumItem (Item.Hierarchy.Level);
HTM_TD_End ();
/***** Title, groups and text *****/
/* Begin title, groups and text */
- ColSpan = Prg_MaxLevel - Item.Level + 1;
+ ColSpan = Prg_MaxLevel - Item.Hierarchy.Level + 1;
if (PrintView)
HTM_TD_Begin ("colspan=\"%u\" class=\"LT\"",
ColSpan);
@@ -330,7 +334,7 @@ static void Prg_ShowOneItem (long ItmCod,unsigned MaxIndex,bool PrintView)
Prg_GetAndWriteNamesOfGrpsAssociatedToItem (&Item);
/* Text */
- Prg_GetPrgItemTxtFromDB (Item.ItmCod,Txt);
+ Prg_GetPrgItemTxtFromDB (Item.Hierarchy.ItmCod,Txt);
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML
Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
@@ -408,6 +412,31 @@ static void Prg_FreeNumbers (void)
}
}
+/*****************************************************************************/
+/**************************** Increase number of item ************************/
+/*****************************************************************************/
+
+static void Prg_IncreaseNumItem (unsigned Level)
+ {
+ /***** Increase number for this level *****/
+ Prg_NumItem[Level]++;
+
+ /***** Reset number for next level (children) *****/
+ Prg_NumItem[Level + 1] = 0;
+ }
+
+/*****************************************************************************/
+/*********************** Get number of item in a level ***********************/
+/*****************************************************************************/
+
+static unsigned Prg_GetNumItem (unsigned Level)
+ {
+ if (Prg_NumItem)
+ return Prg_NumItem[Level];
+
+ return 0;
+ }
+
/*****************************************************************************/
/******************** Write number of item in legal style ********************/
/*****************************************************************************/
@@ -416,45 +445,36 @@ static void Prg_WriteNumItem (unsigned Level)
{
unsigned i;
- /***** Increase number for this level *****/
- Prg_NumItem[Level]++;
-
- /***** Write number *****/
- HTM_Unsigned (Prg_NumItem[1]);
+ /***** Write number in legal style *****/
+ HTM_Unsigned (Prg_GetNumItem (1));
for (i = 2;
i <= Level;
i++)
{
HTM_Txt (".");
- HTM_Unsigned (Prg_NumItem[i]);
+ HTM_Unsigned (Prg_GetNumItem (i));
}
-
- /***** Reset number for next level (children) *****/
- Prg_NumItem[Level + 1] = 0;
}
/*****************************************************************************/
/**************** Put a link (form) to edit one program item *****************/
/*****************************************************************************/
-static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item,
- unsigned MaxIndex,
- const char *Anchor)
+static void Prg_PutFormsToRemEditOnePrgItem (unsigned NumItem,const char *Anchor)
{
extern const char *Txt_Move_up_X;
extern const char *Txt_Move_down_X;
extern const char *Txt_Increase_level_of_X;
extern const char *Txt_Decrease_level_of_X;
extern const char *Txt_Movement_not_allowed;
- static unsigned PrevLevel = 0;
char StrItemIndex[Cns_MAX_DECIMAL_DIGITS_UINT + 1];
- Prg_SetCurrentItmCod (Item->ItmCod); // Used as parameter in contextual links
+ Prg_SetCurrentItmCod (Gbl.Prg.LstItems[NumItem].ItmCod); // Used as parameter in contextual links
/***** Initialize item index string *****/
snprintf (StrItemIndex,sizeof (StrItemIndex),
"%u",
- Item->Index);
+ Gbl.Prg.LstItems[NumItem].Index);
switch (Gbl.Usrs.Me.Role.Logged)
{
@@ -464,7 +484,7 @@ static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item,
Ico_PutContextualIconToRemove (ActReqRemPrgItm,Prg_PutParams);
/***** Put form to hide/show program item *****/
- if (Item->Hidden)
+ if (Gbl.Prg.LstItems[NumItem].Hidden)
Ico_PutContextualIconToUnhide (ActShoPrgItm,Anchor,Prg_PutParams);
else
Ico_PutContextualIconToHide (ActHidPrgItm,Anchor,Prg_PutParams);
@@ -475,7 +495,7 @@ static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item,
HTM_BR ();
/***** Put icon to move up the item *****/
- if (Item->Index > 1)
+ if (Prg_CheckIfMoveUpIsAllowed (NumItem))
{
Lay_PutContextualLinkOnlyIcon (ActUp_PrgItm,NULL,Prg_PutParams,
"arrow-up.svg",
@@ -487,7 +507,7 @@ static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item,
Ico_PutIconOff ("arrow-up.svg",Txt_Movement_not_allowed);
/***** Put icon to move down the item *****/
- if (Item->Index < MaxIndex)
+ if (Prg_CheckIfMoveDownIsAllowed (NumItem))
{
Lay_PutContextualLinkOnlyIcon (ActDwnPrgItm,NULL,Prg_PutParams,
"arrow-down.svg",
@@ -501,7 +521,7 @@ static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item,
HTM_BR ();
/***** Icon to move left item (increase level) *****/
- if (Item->Level > 1)
+ if (Prg_CheckIfMoveLeftIsAllowed (NumItem))
{
Lay_PutContextualLinkOnlyIcon (ActLftPrgItm,NULL,Prg_PutParams,
"arrow-left.svg",
@@ -513,7 +533,7 @@ static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item,
Ico_PutIconOff ("arrow-left.svg",Txt_Movement_not_allowed);
/***** Icon to move right item (indent, decrease level) *****/
- if (Item->Level <= PrevLevel)
+ if (Prg_CheckIfMoveRightIsAllowed (NumItem))
{
Lay_PutContextualLinkOnlyIcon (ActRgtPrgItm,NULL,Prg_PutParams,
"arrow-right.svg",
@@ -523,8 +543,6 @@ static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item,
}
else
Ico_PutIconOff ("arrow-right.svg",Txt_Movement_not_allowed);
-
- PrevLevel = Item->Level;
break;
case Rol_STD:
case Rol_NET:
@@ -534,6 +552,76 @@ static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item,
}
}
+/*****************************************************************************/
+/*********************** Check if item can be moved up ***********************/
+/*****************************************************************************/
+
+static bool Prg_CheckIfMoveUpIsAllowed (unsigned NumItem)
+ {
+ /***** Trivial check: if item is the first one, move up is not allowed *****/
+ if (NumItem == 0)
+ return false;
+
+ /***** Move up is allowed if the item has brothers before it *****/
+ // NumItem >= 2
+ return Gbl.Prg.LstItems[NumItem - 1].Level >=
+ Gbl.Prg.LstItems[NumItem ].Level;
+ }
+
+/*****************************************************************************/
+/********************** Check if item can be moved down **********************/
+/*****************************************************************************/
+
+static bool Prg_CheckIfMoveDownIsAllowed (unsigned NumItem)
+ {
+ unsigned i;
+ unsigned Level;
+
+ /***** Trivial check: if item is the last one, move up is not allowed *****/
+ if (NumItem >= Gbl.Prg.Num - 1)
+ return false;
+
+ /***** Move down is allowed if the item has brothers after it *****/
+ // NumItem + 1 < Gbl.Prg.Num
+ Level = Gbl.Prg.LstItems[NumItem].Level;
+ for (i = NumItem + 1;
+ i < Gbl.Prg.Num;
+ i++)
+ {
+ if (Gbl.Prg.LstItems[i].Level == Level)
+ return true; // Next brother found
+ if (Gbl.Prg.LstItems[i].Level < Level)
+ return false; // Next lower level found ==> there are no more brothers
+ }
+ return false; // End reached ==> there are no more brothers
+ }
+
+/*****************************************************************************/
+/******************* Check if item can be moved to the left ******************/
+/*****************************************************************************/
+
+static bool Prg_CheckIfMoveLeftIsAllowed (unsigned NumItem)
+ {
+ /***** Move left is allowed if the item has parent *****/
+ return Gbl.Prg.LstItems[NumItem].Level > 1;
+ }
+
+/*****************************************************************************/
+/****************** Check if item can be moved to the right ******************/
+/*****************************************************************************/
+
+static bool Prg_CheckIfMoveRightIsAllowed (unsigned NumItem)
+ {
+ /***** If item is the first, move right is not allowed *****/
+ if (NumItem == 0)
+ return false;
+
+ /***** Move right is allowed if the item has brothers before it *****/
+ // NumItem >= 2
+ return Gbl.Prg.LstItems[NumItem - 1].Level >=
+ Gbl.Prg.LstItems[NumItem ].Level;
+ }
+
/*****************************************************************************/
/**************** Access to variables used to pass parameter *****************/
/*****************************************************************************/
@@ -565,7 +653,7 @@ static void Prg_PutParams (void)
/*********************** List all the program items **************************/
/*****************************************************************************/
-void Prg_GetListPrgItems (void)
+static void Prg_GetListPrgItems (void)
{
static const char *HiddenSubQuery[Rol_NUM_ROLES] =
{
@@ -591,7 +679,10 @@ void Prg_GetListPrgItems (void)
/***** Get list of program items from database *****/
if (Gbl.Crs.Grps.WhichGrps == Grp_MY_GROUPS)
NumRows = DB_QuerySELECT (&mysql_res,"can not get program items",
- "SELECT ItmCod"
+ "SELECT ItmCod," // row[0]
+ "ItmInd," // row[1]
+ "Level," // row[2]
+ "Hidden" // row[3]
" FROM prg_items"
" WHERE CrsCod=%ld%s"
" AND "
@@ -606,7 +697,10 @@ void Prg_GetListPrgItems (void)
Gbl.Usrs.Me.UsrDat.UsrCod);
else // Gbl.Crs.Grps.WhichGrps == Grp_ALL_GROUPS
NumRows = DB_QuerySELECT (&mysql_res,"can not get program items",
- "SELECT ItmCod"
+ "SELECT ItmCod," // row[0]
+ "ItmInd," // row[1]
+ "Level," // row[2]
+ "Hidden" // row[3]
" FROM prg_items"
" WHERE CrsCod=%ld%s"
" ORDER BY ItmInd",
@@ -618,7 +712,9 @@ void Prg_GetListPrgItems (void)
Gbl.Prg.Num = (unsigned) NumRows;
/***** Create list of program items *****/
- if ((Gbl.Prg.LstItmCods = (long *) calloc (NumRows,sizeof (long))) == NULL)
+ if ((Gbl.Prg.LstItems =
+ (struct ProgramItemHierarchy *) calloc (NumRows,
+ sizeof (struct ProgramItemHierarchy))) == NULL)
Lay_NotEnoughMemoryExit ();
/***** Get the program items codes *****/
@@ -626,10 +722,21 @@ void Prg_GetListPrgItems (void)
NumItem < Gbl.Prg.Num;
NumItem++)
{
- /* Get next program item code */
+ /* Get row */
row = mysql_fetch_row (mysql_res);
- if ((Gbl.Prg.LstItmCods[NumItem] = Str_ConvertStrCodToLongCod (row[0])) < 0)
+
+ /* Get code of the program item (row[0]) */
+ if ((Gbl.Prg.LstItems[NumItem].ItmCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Error: wrong program item code.");
+
+ /* Get index of the program item (row[1]) */
+ Gbl.Prg.LstItems[NumItem].Index = Str_ConvertStrToUnsigned (row[1]);
+
+ /* Get level of the program item (row[2]) */
+ Gbl.Prg.LstItems[NumItem].Level = Str_ConvertStrToUnsigned (row[2]);
+
+ /* Get whether the program item is hidden or not (row[3]) */
+ Gbl.Prg.LstItems[NumItem].Hidden = (row[3][0] == 'Y');
}
}
else
@@ -650,7 +757,7 @@ void Prg_GetDataOfItemByCod (struct ProgramItem *Item)
MYSQL_RES *mysql_res;
unsigned long NumRows;
- if (Item->ItmCod > 0)
+ if (Item->Hierarchy.ItmCod > 0)
{
/***** Build query *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get program item data",
@@ -666,7 +773,7 @@ void Prg_GetDataOfItemByCod (struct ProgramItem *Item)
" FROM prg_items"
" WHERE ItmCod=%ld"
" AND CrsCod=%ld", // Extra check
- Item->ItmCod,Gbl.Hierarchy.Crs.CrsCod);
+ Item->Hierarchy.ItmCod,Gbl.Hierarchy.Crs.CrsCod);
/***** Get data of program item *****/
Prg_GetDataOfItem (Item,&mysql_res,NumRows);
@@ -707,13 +814,13 @@ static void Prg_GetDataOfItem (struct ProgramItem *Item,
*/
/* Get code of the program item (row[0]) */
- Item->ItmCod = Str_ConvertStrCodToLongCod (row[0]);
+ Item->Hierarchy.ItmCod = Str_ConvertStrCodToLongCod (row[0]);
/* Get index of the program item (row[1]) */
- Item->Index = Str_ConvertStrToUnsigned (row[1]);
+ Item->Hierarchy.Index = Str_ConvertStrToUnsigned (row[1]);
/* Get level of the program item (row[2]) */
- Item->Level = Str_ConvertStrToUnsigned (row[2]);
+ Item->Hierarchy.Level = Str_ConvertStrToUnsigned (row[2]);
/* Get whether the program item is hidden or not (row[3]) */
Item->Hidden = (row[3][0] == 'Y');
@@ -735,7 +842,7 @@ static void Prg_GetDataOfItem (struct ProgramItem *Item,
Prg_MAX_BYTES_PROGRAM_ITEM_TITLE);
/* Can I do this program item? */
- Item->IBelongToCrsOrGrps = Prg_CheckIfIBelongToCrsOrGrpsThisItem (Item->ItmCod);
+ Item->IBelongToCrsOrGrps = Prg_CheckIfIBelongToCrsOrGrpsThisItem (Item->Hierarchy.ItmCod);
}
/***** Free structure that stores the query result *****/
@@ -748,9 +855,9 @@ static void Prg_GetDataOfItem (struct ProgramItem *Item,
static void Prg_ResetItem (struct ProgramItem *Item)
{
- Item->ItmCod = -1L;
- Item->Index = 0;
- Item->Level = 1;
+ Item->Hierarchy.ItmCod = -1L;
+ Item->Hierarchy.Index = 0;
+ Item->Hierarchy.Level = 1;
Item->Hidden = false;
Item->UsrCod = -1L;
Item->TimeUTC[Dat_START_TIME] =
@@ -766,11 +873,11 @@ static void Prg_ResetItem (struct ProgramItem *Item)
void Prg_FreeListItems (void)
{
- if (Gbl.Prg.LstIsRead && Gbl.Prg.LstItmCods)
+ if (Gbl.Prg.LstIsRead && Gbl.Prg.LstItems)
{
/***** Free memory used by the list of program items *****/
- free (Gbl.Prg.LstItmCods);
- Gbl.Prg.LstItmCods = NULL;
+ free (Gbl.Prg.LstItems);
+ Gbl.Prg.LstItems = NULL;
Gbl.Prg.Num = 0;
Gbl.Prg.LstIsRead = false;
}
@@ -824,12 +931,30 @@ static void Prg_PutParamItmCod (long ItmCod)
/***************** Get parameter with code of program item *******************/
/*****************************************************************************/
-long Prg_GetParamItmCod (void)
+static long Prg_GetParamItmCod (void)
{
/***** Get code of program item *****/
return Par_GetParToLong ("ItmCod");
}
+/*****************************************************************************/
+/**************** Get number of item in list from item code ******************/
+/*****************************************************************************/
+
+static unsigned Prg_GetNumItemFromItmCod (unsigned ItmCod)
+ {
+ unsigned NumItem;
+
+ for (NumItem = 0;
+ NumItem < Gbl.Prg.Num;
+ NumItem++)
+ if (Gbl.Prg.LstItems[NumItem].ItmCod == ItmCod)
+ return NumItem;
+
+ Lay_ShowErrorAndExit ("Wrong item code.");
+ return 0; // Not reached
+ }
+
/*****************************************************************************/
/************* Ask for confirmation of removing a program item ***************/
/*****************************************************************************/
@@ -844,14 +969,14 @@ void Prg_ReqRemPrgItem (void)
Grp_GetParamWhichGrps ();
/***** Get program item code *****/
- if ((Item.ItmCod = Prg_GetParamItmCod ()) == -1L)
+ if ((Item.Hierarchy.ItmCod = Prg_GetParamItmCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of program item is missing.");
/***** Get data of the program item from database *****/
Prg_GetDataOfItemByCod (&Item);
/***** Show question and button to remove the program item *****/
- Prg_SetCurrentItmCod (Item.ItmCod);
+ Prg_SetCurrentItmCod (Item.Hierarchy.ItmCod);
Ale_ShowAlertAndButton (ActRemPrgItm,NULL,NULL,Prg_PutParams,
Btn_REMOVE_BUTTON,Txt_Remove_item,
Ale_QUESTION,Txt_Do_you_really_want_to_remove_the_item_X,
@@ -871,19 +996,19 @@ void Prg_RemovePrgItem (void)
struct ProgramItem Item;
/***** Get program item code *****/
- if ((Item.ItmCod = Prg_GetParamItmCod ()) == -1L)
+ if ((Item.Hierarchy.ItmCod = Prg_GetParamItmCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of program item is missing.");
/***** Get data of the program item from database *****/
Prg_GetDataOfItemByCod (&Item); // Inside this function, the course is checked to be the current one
/***** Remove all the groups of this program item *****/
- Prg_RemoveAllTheGrpsAssociatedToAnItem (Item.ItmCod);
+ Prg_RemoveAllTheGrpsAssociatedToAnItem (Item.Hierarchy.ItmCod);
/***** Remove program item *****/
DB_QueryDELETE ("can not remove program item",
"DELETE FROM prg_items WHERE ItmCod=%ld AND CrsCod=%ld",
- Item.ItmCod,Gbl.Hierarchy.Crs.CrsCod);
+ Item.Hierarchy.ItmCod,Gbl.Hierarchy.Crs.CrsCod);
/***** Write message to show the change made *****/
Ale_ShowAlert (Ale_SUCCESS,Txt_Item_X_removed,Item.Title);
@@ -901,7 +1026,7 @@ void Prg_HidePrgItem (void)
struct ProgramItem Item;
/***** Get program item code *****/
- if ((Item.ItmCod = Prg_GetParamItmCod ()) == -1L)
+ if ((Item.Hierarchy.ItmCod = Prg_GetParamItmCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of program item is missing.");
/***** Get data of the program item from database *****/
@@ -912,7 +1037,7 @@ void Prg_HidePrgItem (void)
"UPDATE prg_items SET Hidden='Y'"
" WHERE ItmCod=%ld"
" AND CrsCod=%ld", // Extra check
- Item.ItmCod,Gbl.Hierarchy.Crs.CrsCod);
+ Item.Hierarchy.ItmCod,Gbl.Hierarchy.Crs.CrsCod);
/***** Show program items again *****/
Prg_SeeCourseProgram ();
@@ -927,7 +1052,7 @@ void Prg_ShowPrgItem (void)
struct ProgramItem Item;
/***** Get program item code *****/
- if ((Item.ItmCod = Prg_GetParamItmCod ()) == -1L)
+ if ((Item.Hierarchy.ItmCod = Prg_GetParamItmCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of program item is missing.");
/***** Get data of the program item from database *****/
@@ -938,7 +1063,7 @@ void Prg_ShowPrgItem (void)
"UPDATE prg_items SET Hidden='N'"
" WHERE ItmCod=%ld"
" AND CrsCod=%ld", // Extra check
- Item.ItmCod,Gbl.Hierarchy.Crs.CrsCod);
+ Item.Hierarchy.ItmCod,Gbl.Hierarchy.Crs.CrsCod);
/***** Show program items again *****/
Prg_SeeCourseProgram ();
@@ -950,30 +1075,27 @@ void Prg_ShowPrgItem (void)
void Prg_MoveUpPrgItem (void)
{
- struct ProgramItem Item;
- struct
- {
- unsigned Begin;
- unsigned End;
- } Prev, This;
+ extern const char *Txt_Movement_not_allowed;
+ long ItmCod;
+ unsigned NumItem;
/***** Get program item code *****/
- if ((Item.ItmCod = Prg_GetParamItmCod ()) == -1L)
+ if ((ItmCod = Prg_GetParamItmCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of program item is missing.");
- /***** Get data of the program item from database *****/
- Prg_GetDataOfItemByCod (&Item);
+ /***** Get list of program items *****/
+ Prg_GetListPrgItems ();
+ NumItem = Prg_GetNumItemFromItmCod (ItmCod);
- /***** Move up item *****/
- /* Indexes of items to be exchanged */
- Prev.Begin = Prg_GetPrevBrotherIndex (Item.Index,Item.Level);
- Prev.End = Prg_GetPrevIndex (Item.Index);
- This.Begin = Item.Index;
- This.End = Prg_GetLastChildIndex (Item.Index,Item.Level);
+ if (Prg_CheckIfMoveUpIsAllowed (NumItem))
+ /***** Move up item *****/
+ /* Exchange subtrees */
+ Prg_ExchangeItems (Prg_GetPrevBrother (NumItem),NumItem);
+ else
+ Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed);
- /* Exchange items */
- Prg_ExchangeItems ((int) Prev.Begin,(int) Prev.End,
- (int) This.Begin,(int) This.End);
+ /***** Free list of program items *****/
+ Prg_FreeListItems ();
/***** Show program items again *****/
Prg_SeeCourseProgram ();
@@ -986,59 +1108,26 @@ void Prg_MoveUpPrgItem (void)
void Prg_MoveDownPrgItem (void)
{
extern const char *Txt_Movement_not_allowed;
- struct ProgramItem Item;
- struct
- {
- unsigned Begin;
- unsigned End;
- } This, Next;
+ long ItmCod;
+ unsigned NumItem;
/***** Get program item code *****/
- if ((Item.ItmCod = Prg_GetParamItmCod ()) == -1L)
+ if ((ItmCod = Prg_GetParamItmCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of program item is missing.");
- /***** Get data of the program item from database *****/
- Prg_GetDataOfItemByCod (&Item);
+ /***** Get list of program items *****/
+ Prg_GetListPrgItems ();
+ NumItem = Prg_GetNumItemFromItmCod (ItmCod);
- /***** Move down item *****/
- /* Indexes of items to be exchanged */
- This.Begin = Item.Index;
- This.End = Prg_GetLastChildIndex (Item.Index,Item.Level);
- Next.Begin = Prg_GetNextBrotherIndex (Item.Index,Item.Level);
- Next.End = Prg_GetLastChildIndex (Next.Begin,Item.Level);
+ if (Prg_CheckIfMoveDownIsAllowed (NumItem))
+ /***** Move down item *****/
+ /* Exchange subtrees */
+ Prg_ExchangeItems (NumItem,Prg_GetNextBrother (NumItem));
+ else
+ Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed);
- Ale_ShowAlert (Ale_INFO,"This.Begin = %u
"
- "This.End = %u
"
- "Next.Begin = %u
"
- "Next.End = %u",
- This.Begin,This.End,Next.Begin,Next.End);
-
- /* Exchange items */
- Prg_ExchangeItems (This.Begin,This.End,
- Next.Begin,Next.End);
-
- /***** Show program items again *****/
- Prg_SeeCourseProgram ();
- }
-
-/*****************************************************************************/
-/**** Move right (increase level) position of an item in a course program ****/
-/*****************************************************************************/
-
-void Prg_MoveRightPrgItem (void)
- {
- struct ProgramItem Item;
-
- /***** Get program item code *****/
- if ((Item.ItmCod = Prg_GetParamItmCod ()) == -1L)
- Lay_ShowErrorAndExit ("Code of program item is missing.");
-
- /***** Get data of the program item from database *****/
- Prg_GetDataOfItemByCod (&Item);
-
- /***** Move right item (increase level) *****/
- /* Move item and its children to right */
- Prg_MoveItemAndChildrenRight (&Item);
+ /***** Free list of program items *****/
+ Prg_FreeListItems ();
/***** Show program items again *****/
Prg_SeeCourseProgram ();
@@ -1050,18 +1139,51 @@ void Prg_MoveRightPrgItem (void)
void Prg_MoveLeftPrgItem (void)
{
- struct ProgramItem Item;
+ long ItmCod;
+ unsigned NumItem;
/***** Get program item code *****/
- if ((Item.ItmCod = Prg_GetParamItmCod ()) == -1L)
+ if ((ItmCod = Prg_GetParamItmCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of program item is missing.");
- /***** Get data of the program item from database *****/
- Prg_GetDataOfItemByCod (&Item);
+ /***** Get list of program items *****/
+ Prg_GetListPrgItems ();
+ NumItem = Prg_GetNumItemFromItmCod (ItmCod);
/***** Move left item (decrease level) *****/
/* Move item and its children to left */
- Prg_MoveItemAndChildrenLeft (&Item);
+ Prg_MoveItemAndChildrenLeft (NumItem);
+
+ /***** Free list of program items *****/
+ Prg_FreeListItems ();
+
+ /***** Show program items again *****/
+ Prg_SeeCourseProgram ();
+ }
+
+/*****************************************************************************/
+/**** Move right (increase level) position of an item in a course program ****/
+/*****************************************************************************/
+
+void Prg_MoveRightPrgItem (void)
+ {
+ long ItmCod;
+ unsigned NumItem;
+
+ /***** Get program item code *****/
+ if ((ItmCod = Prg_GetParamItmCod ()) == -1L)
+ Lay_ShowErrorAndExit ("Code of program item is missing.");
+
+ /***** Get list of program items *****/
+ Prg_GetListPrgItems ();
+ NumItem = Prg_GetNumItemFromItmCod (ItmCod);
+
+ /***** Move right item (increase level) *****/
+ /* Move item and its children to right */
+ Prg_MoveItemAndChildrenRight (NumItem);
+
+ /***** Free list of program items *****/
+ Prg_FreeListItems ();
/***** Show program items again *****/
Prg_SeeCourseProgram ();
@@ -1074,23 +1196,15 @@ void Prg_MoveLeftPrgItem (void)
static unsigned Prg_GetMaxItemLevel (void)
{
- MYSQL_RES *mysql_res;
- MYSQL_ROW row;
+ unsigned NumItem;
unsigned MaxLevel = 0;
- /***** Get maximum item index in a course program from database *****/
- DB_QuerySELECT (&mysql_res,"can not get last item index",
- "SELECT MAX(Level)"
- " FROM prg_items"
- " WHERE CrsCod=%ld",
- Gbl.Hierarchy.Crs.CrsCod);
- row = mysql_fetch_row (mysql_res);
- if (row[0]) // There are items
- if (sscanf (row[0],"%u",&MaxLevel) != 1)
- Lay_ShowErrorAndExit ("Error when getting maximum item level.");
-
- /***** Free structure that stores the query result *****/
- DB_FreeMySQLResult (&mysql_res);
+ /***** Compute maximum level of all program items *****/
+ for (NumItem = 0;
+ NumItem < Gbl.Prg.Num;
+ NumItem++)
+ if (Gbl.Prg.LstItems[NumItem].Level > MaxLevel)
+ MaxLevel = Gbl.Prg.LstItems[NumItem].Level;
return MaxLevel;
}
@@ -1125,206 +1239,63 @@ static unsigned Prg_GetMaxItemIndex (void)
}
/*****************************************************************************/
-/******** Get previous item index to a given index in current course *********/
+/******** Get previous brother item to a given item in current course ********/
/*****************************************************************************/
-// Return 0 if no previous item
+// Return -1 if no previous brother
-static unsigned Prg_GetPrevIndex (unsigned Index)
+static int Prg_GetPrevBrother (int NumItem)
{
- MYSQL_RES *mysql_res;
- MYSQL_ROW row;
- unsigned PrevIndex = 0;
+ unsigned Level;
+ int i;
- if (Index)
+ /***** Trivial check: if item is the first one, there is no previous brother *****/
+ if (NumItem <= 0 ||
+ NumItem >= (int) Gbl.Prg.Num)
+ return -1;
+
+ /***** Get previous brother before item *****/
+ // 1 <= NumItem < Gbl.Prg.Num
+ Level = Gbl.Prg.LstItems[NumItem].Level;
+ for (i = NumItem - 1;
+ i >= 0;
+ i--)
{
- /***** Get previous item index in a course from database *****/
- if (!DB_QuerySELECT (&mysql_res,"can not get previous item index",
- "SELECT MAX(ItmInd)" // row[0]
- " FROM prg_items"
- " WHERE CrsCod=%ld"
- " AND ItmInd<%u",
- Gbl.Hierarchy.Crs.CrsCod,Index))
- Lay_ShowErrorAndExit ("Error: previous item index not found.");
-
- /***** Get previous item index (row[0]) *****/
- row = mysql_fetch_row (mysql_res);
- if (row)
- if (row[0])
- if (sscanf (row[0],"%u",&PrevIndex) != 1)
- Lay_ShowErrorAndExit ("Error when getting previous item index.");
-
- /***** Free structure that stores the query result *****/
- DB_FreeMySQLResult (&mysql_res);
+ if (Gbl.Prg.LstItems[i].Level == Level)
+ return i; // Previous brother before item found
+ if (Gbl.Prg.LstItems[i].Level < Level)
+ return -1; // Previous lower level found ==> there are no brothers before item
}
-
- return PrevIndex;
+ return -1; // Start reached ==> there are no brothers before item
}
/*****************************************************************************/
-/************ Get parent index to a given index in current course ************/
+/********** Get next brother item to a given item in current course **********/
/*****************************************************************************/
-// Return 0 if no parent item
+// Return -1 if no next brother
-static unsigned Prg_GetParentIndex (unsigned Index,unsigned Level)
+static int Prg_GetNextBrother (int NumItem)
{
- MYSQL_RES *mysql_res;
- MYSQL_ROW row;
- unsigned ParentIndex = 0;
+ unsigned Level;
+ int i;
- if (Index)
- if (Level > 1)
- {
- /***** Get parent item index in a course from database *****/
- if (!DB_QuerySELECT (&mysql_res,"can not get parent item index",
- "SELECT MAX(ItmInd)" // row[0]
- " FROM prg_items"
- " WHERE CrsCod=%ld"
- " AND ItmInd<%u AND Level=%u",
- Gbl.Hierarchy.Crs.CrsCod,Index,Level - 1))
- Lay_ShowErrorAndExit ("Error: parent item index not found.");
+ /***** Trivial check: if item is the last one, there is no next brother *****/
+ if (NumItem < 0 ||
+ NumItem >= (int) Gbl.Prg.Num - 1)
+ return -1;
- /***** Get previous item index (row[0]) *****/
- row = mysql_fetch_row (mysql_res);
- if (row)
- if (row[0])
- if (sscanf (row[0],"%u",&ParentIndex) != 1)
- Lay_ShowErrorAndExit ("Error when getting parent item index.");
-
- /***** Free structure that stores the query result *****/
- DB_FreeMySQLResult (&mysql_res);
- }
-
- return ParentIndex;
- }
-
-/*****************************************************************************/
-/**** Get next index with lower level than a given index in current course ***/
-/*****************************************************************************/
-// Return 0 if no next lower item
-
-static unsigned Prg_GetNextLowerIndex (unsigned Index,unsigned Level)
- {
- MYSQL_RES *mysql_res;
- MYSQL_ROW row;
- unsigned NextLowerIndex = 0;
-
- if (Index)
+ /***** Get next brother after item *****/
+ // 0 <= NumItem < Gbl.Prg.Num - 1
+ Level = Gbl.Prg.LstItems[NumItem].Level;
+ for (i = NumItem + 1;
+ i < (int) Gbl.Prg.Num;
+ i++)
{
- /***** Get next item index in a course from database *****/
- if (!DB_QuerySELECT (&mysql_res,"can not get next brother item index",
- "SELECT MIN(ItmInd)" // row[0]
- " FROM prg_items"
- " WHERE CrsCod=%ld"
- " AND ItmInd>%u AND Level>%u",
- Gbl.Hierarchy.Crs.CrsCod,Index,Level))
- Lay_ShowErrorAndExit ("Error: next brother item index not found.");
-
- /***** Get previous item index (row[0]) *****/
- row = mysql_fetch_row (mysql_res);
- if (row)
- if (row[0])
- if (sscanf (row[0],"%u",&NextLowerIndex) != 1)
- Lay_ShowErrorAndExit ("Error when getting next brother item index.");
-
- /***** Free structure that stores the query result *****/
- DB_FreeMySQLResult (&mysql_res);
+ if (Gbl.Prg.LstItems[i].Level == Level)
+ return i; // Next brother found
+ if (Gbl.Prg.LstItems[i].Level < Level)
+ return -1; // Next lower level found ==> there are no brothers after item
}
-
- return NextLowerIndex;
- }
-
-/*****************************************************************************/
-/******* Get previous brother index to a given index in current course *******/
-/*****************************************************************************/
-// Return 0 if no previous brother
-
-static unsigned Prg_GetPrevBrotherIndex (unsigned Index,unsigned Level)
- {
- MYSQL_RES *mysql_res;
- MYSQL_ROW row;
- unsigned ParentIndex;
- unsigned PrevBrotherIndex = 0;
-
- if (Index)
- {
- ParentIndex = Prg_GetParentIndex (Index,Level);
-
- /***** Get previous brother item index in a course from database *****/
- if (!DB_QuerySELECT (&mysql_res,"can not get previous brother item index",
- "SELECT MAX(ItmInd)" // row[0]
- " FROM prg_items"
- " WHERE CrsCod=%ld"
- " AND ItmInd>%u AND ItmInd<%u AND Level=%u",
- Gbl.Hierarchy.Crs.CrsCod,
- ParentIndex,Index,Level))
- Lay_ShowErrorAndExit ("Error: previous brother item index not found.");
-
- /***** Get previous item index (row[0]) *****/
- row = mysql_fetch_row (mysql_res);
- if (row)
- if (row[0])
- if (sscanf (row[0],"%u",&PrevBrotherIndex) != 1)
- Lay_ShowErrorAndExit ("Error when getting previous brother item index.");
-
- /***** Free structure that stores the query result *****/
- DB_FreeMySQLResult (&mysql_res);
- }
-
- return PrevBrotherIndex;
- }
-
-/*****************************************************************************/
-/********* Get next brother index to a given index in current course *********/
-/*****************************************************************************/
-// Return 0 if no next brother
-
-static unsigned Prg_GetNextBrotherIndex (unsigned Index,unsigned Level)
- {
- MYSQL_RES *mysql_res;
- MYSQL_ROW row;
- unsigned NextLowerIndex;
- unsigned NextBrotherIndex = 0;
-
- if (Index)
- {
- NextLowerIndex = Prg_GetNextLowerIndex (Index,Level);
-
- /***** Get next brother item index in a course from database *****/
- if (NextLowerIndex)
- {
- if (!DB_QuerySELECT (&mysql_res,"can not get next brother item index",
- "SELECT MIN(ItmInd)" // row[0]
- " FROM prg_items"
- " WHERE CrsCod=%ld"
- " AND ItmInd>%u AND ItmInd<%u AND Level=%u",
- Gbl.Hierarchy.Crs.CrsCod,
- Index,NextLowerIndex,Level))
- Lay_ShowErrorAndExit ("Error: next brother item index not found.");
- }
- else
- {
- if (!DB_QuerySELECT (&mysql_res,"can not get next brother item index",
- "SELECT MIN(ItmInd)" // row[0]
- " FROM prg_items"
- " WHERE CrsCod=%ld"
- " AND ItmInd>%u AND Level=%u",
- Gbl.Hierarchy.Crs.CrsCod,
- Index,Level))
- Lay_ShowErrorAndExit ("Error: next brother item index not found.");
- }
-
- /***** Get previous item index (row[0]) *****/
- row = mysql_fetch_row (mysql_res);
- if (row)
- if (row[0])
- if (sscanf (row[0],"%u",&NextBrotherIndex) != 1)
- Lay_ShowErrorAndExit ("Error when getting next brother item index.");
-
- /***** Free structure that stores the query result *****/
- DB_FreeMySQLResult (&mysql_res);
- }
-
- return NextBrotherIndex;
+ return -1; // End reached ==> there are no brothers after item
}
/*****************************************************************************/
@@ -1332,49 +1303,53 @@ static unsigned Prg_GetNextBrotherIndex (unsigned Index,unsigned Level)
/*****************************************************************************/
// Return the same index if no children
-static unsigned Prg_GetLastChildIndex (unsigned Index,unsigned Level)
+static int Prg_GetLastChild (int NumItem)
{
- unsigned NextBrother;
- unsigned NextLower;
+ unsigned Level;
+ int i;
- NextBrother = Prg_GetNextBrotherIndex (Index,Level);
- if (NextBrother)
- return Prg_GetPrevIndex (NextBrother);
+ /***** Trivial check: if item is wrong, there are no children *****/
+ if (NumItem < 0 ||
+ NumItem >= (int) Gbl.Prg.Num)
+ return -1;
- // Last brother, no more brothers
- NextLower = Prg_GetNextLowerIndex (Index,Level);
- if (NextLower)
- return Prg_GetPrevIndex (NextLower);
-
- // Last item, no more items
- return Index;
+ /***** Get next brother after item *****/
+ // 0 <= NumItem < Gbl.Prg.Num
+ Level = Gbl.Prg.LstItems[NumItem].Level;
+ for (i = NumItem + 1;
+ i < (int) Gbl.Prg.Num;
+ i++)
+ {
+ if (Gbl.Prg.LstItems[i].Level <= Level)
+ return i - 1; // Last child found
+ }
+ return Gbl.Prg.Num - 1; // End reached ==> all items after the given item are its children
}
/*****************************************************************************/
/**************** Move item and its children to left or right ****************/
/*****************************************************************************/
-static void Prg_MoveItemAndChildrenLeft (const struct ProgramItem *Item)
+static void Prg_MoveItemAndChildrenLeft (unsigned NumItem)
{
extern const char *Txt_Movement_not_allowed;
- struct
+ unsigned BeginIndex;
+ unsigned EndIndex;
+
+ if (Prg_CheckIfMoveLeftIsAllowed (NumItem))
{
- unsigned Begin;
- unsigned End;
- } This;
+ /* Indexes of items */
+ BeginIndex = Gbl.Prg.LstItems[NumItem].Index;
+ EndIndex = Gbl.Prg.LstItems[Prg_GetLastChild (NumItem)].Index;
- /* Indexes of items */
- This.Begin = Item->Index;
- This.End = Prg_GetLastChildIndex (Item->Index,Item->Level);
-
- if (Item->Level) // Only if no first level
/* Move item and its children to left or right */
DB_QueryUPDATE ("can not move items",
"UPDATE prg_items SET Level=Level-1"
" WHERE CrsCod=%ld"
" AND ItmInd>=%u AND ItmInd<=%u",
Gbl.Hierarchy.Crs.CrsCod,
- This.Begin,This.End);
+ BeginIndex,EndIndex);
+ }
else
Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed);
}
@@ -1383,29 +1358,26 @@ static void Prg_MoveItemAndChildrenLeft (const struct ProgramItem *Item)
/**************** Move item and its children to left or right ****************/
/*****************************************************************************/
-static void Prg_MoveItemAndChildrenRight (const struct ProgramItem *Item)
+static void Prg_MoveItemAndChildrenRight (unsigned NumItem)
{
extern const char *Txt_Movement_not_allowed;
- struct
+ unsigned BeginIndex;
+ unsigned EndIndex;
+
+ if (Prg_CheckIfMoveRightIsAllowed (NumItem))
{
- unsigned Begin;
- unsigned End;
- } Prev, This;
+ /* Indexes of items */
+ BeginIndex = Gbl.Prg.LstItems[NumItem].Index;
+ EndIndex = Gbl.Prg.LstItems[Prg_GetLastChild (NumItem)].Index;
- /* Indexes of items */
- Prev.Begin = Prg_GetPrevBrotherIndex (Item->Index,Item->Level);
- Prev.End = Prg_GetLastChildIndex (Prev.Begin,Item->Level);
- This.Begin = Item->Index;
- This.End = Prg_GetLastChildIndex (Item->Index,Item->Level);
-
- if (Prev.Begin) // Only if previous brother exists
/* Move item and its children to left or right */
DB_QueryUPDATE ("can not move items",
"UPDATE prg_items SET Level=Level+1"
" WHERE CrsCod=%ld"
" AND ItmInd>=%u AND ItmInd<=%u",
Gbl.Hierarchy.Crs.CrsCod,
- This.Begin,This.End);
+ BeginIndex,EndIndex);
+ }
else
Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed);
}
@@ -1414,15 +1386,35 @@ static void Prg_MoveItemAndChildrenRight (const struct ProgramItem *Item)
/****** Exchange the order of two consecutive items in a course program ******/
/*****************************************************************************/
-static void Prg_ExchangeItems (int TopBegin,int TopEnd,
- int BottomBegin,int BottomEnd)
+static void Prg_ExchangeItems (int NumItemTop,int NumItemBottom)
{
extern const char *Txt_Movement_not_allowed;
- int DiffBegin = BottomBegin - TopBegin;
- int DiffEnd = BottomEnd - TopEnd;
-
- if (TopBegin && BottomBegin)
+ struct
{
+ unsigned Begin;
+ unsigned End;
+ } TopIndex, BottomIndex, Diff;
+
+ if (NumItemTop >= 0 &&
+ NumItemBottom >= 0)
+ {
+ TopIndex.Begin = Gbl.Prg.LstItems[NumItemTop ].Index;
+ TopIndex.End = Gbl.Prg.LstItems[Prg_GetLastChild (NumItemTop )].Index;
+ BottomIndex.Begin = Gbl.Prg.LstItems[NumItemBottom ].Index;
+ BottomIndex.End = Gbl.Prg.LstItems[Prg_GetLastChild (NumItemBottom)].Index;
+ Diff.Begin = BottomIndex.Begin - TopIndex.Begin;
+ Diff.End = BottomIndex.End - TopIndex.End;
+
+ Ale_ShowAlert (Ale_INFO,"TopIndex.Begin = %u
"
+ "TopIndex.End = %u
"
+ "BottomIndex.Begin = %u
"
+ "BottomIndex.End = %u",
+ TopIndex.Begin,
+ TopIndex.End,
+ BottomIndex.Begin,
+ BottomIndex.End);
+
+
/***** Lock table to make the move atomic *****/
DB_Query ("can not lock tables to move program item",
"LOCK TABLES prg_items WRITE");
@@ -1433,48 +1425,52 @@ static void Prg_ExchangeItems (int TopBegin,int TopEnd,
// ...this implementation works even with non continuous indexes
/*
Example:
- TopBegin = 5
- = 10
- TopEnd = 17
- BottomBegin = 28
- BottomEnd = 49
+ TopIndex.Begin = 5
+ = 10
+ TopIndex.End = 17
+ BottomIndex.Begin = 28
+ BottomIndex.End = 49
- DiffBegin = 28 - 5 = 23;
- DiffEnd = 49 - 17 = 32;
+ Diff.Begin = 28 - 5 = 23;
+ Diff.End = 49 - 17 = 32;
- Step 1 Step 2 Step 3 (Equivalent to)
- +------+------+ +------+------+ +------+------+ +------+------+ +------+------+
- |ItmInd|ItmCod| |ItmInd|ItmCod| |ItmInd|ItmCod| |ItmInd|ItmCod| |ItmInd|ItmCod|
- +------+------+ +------+------+ +------+------+ +------+------+ +------+------+
- TopBegin: 5| 218|-->|--> -5| 218|-->|--> 37| 218| | 37| 218| | 5| 221|
- | 10| 219|-->|-->-10| 219|-->|--> 42| 219| | 42| 219| | 26| 222|
- TopEnd: 17| 220|-->|-->-17| 220|-->|--> 49| 220| | 49| 220| | 37| 218|
- BottomBegin: 28| 221|-->|-->-28| 221| | -28| 221|-->|--> 5| 221| | 42| 219|
- BottomEnd: 49| 222|-->|-->-49| 222| | -49| 222|-->|--> 26| 222| | 49| 220|
- +------+------+ +------+------+ +------+------+ +------+------+ +------+------+
+ Step 1 Step 2 Step 3 (Equivalent to)
+ +------+------+ +------+------+ +------+------+ +------+------+ +------+------+
+ |ItmInd|ItmCod| |ItmInd|ItmCod| |ItmInd|ItmCod| |ItmInd|ItmCod| |ItmInd|ItmCod|
+ +------+------+ +------+------+ +------+------+ +------+------+ +------+------+
+TopIndex.Begin: 5| 218|-->|--> -5| 218|-->|--> 37| 218| | 37| 218| | 5| 221|
+ | 10| 219|-->|-->-10| 219|-->|--> 42| 219| | 42| 219| | 26| 222|
+TopIndex.End: | 17| 220|-->|-->-17| 220|-->|--> 49| 220| | 49| 220| | 37| 218|
+BottomIndex.Begin: 28| 221|-->|-->-28| 221| | -28| 221|-->|--> 5| 221| | 42| 219|
+BottomIndex.End: 49| 222|-->|-->-49| 222| | -49| 222|-->|--> 26| 222| | 49| 220|
+ +------+------+ +------+------+ +------+------+ +------+------+ +------+------+
*/
/* Step 1: Change all indexes involved to negative,
necessary to preserve unique index (CrsCod,ItmInd) */
DB_QueryUPDATE ("can not exchange indexes of items",
"UPDATE prg_items SET ItmInd=-ItmInd"
- " WHERE CrsCod=%ld AND ItmInd>=%d AND ItmInd<=%d",
- Gbl.Hierarchy.Crs.CrsCod,TopBegin,BottomEnd);
+ " WHERE CrsCod=%ld"
+ " AND ItmInd>=%u AND ItmInd<=%u",
+ Gbl.Hierarchy.Crs.CrsCod,
+ TopIndex.Begin,BottomIndex.End);
/* Step 2: Increase top indexes */
DB_QueryUPDATE ("can not exchange indexes of items",
- "UPDATE prg_items SET ItmInd=-ItmInd+%d"
- " WHERE CrsCod=%ld AND ItmInd>=%d AND ItmInd<=%d",
- DiffEnd,
+ "UPDATE prg_items SET ItmInd=-ItmInd+%u"
+ " WHERE CrsCod=%ld"
+ " AND ItmInd>=-%u AND ItmInd<=-%u",
+ Diff.End,
Gbl.Hierarchy.Crs.CrsCod,
- -TopEnd,-TopBegin); // All indexes in top part
+ TopIndex.End,TopIndex.Begin); // All indexes in top part
/* Step 3: Decrease bottom indexes */
DB_QueryUPDATE ("can not exchange indexes of items",
- "UPDATE prg_items SET ItmInd=-ItmInd-%d"
- " WHERE CrsCod=%ld AND ItmInd>=%d AND ItmInd<=%d",
- DiffBegin,
+ "UPDATE prg_items SET ItmInd=-ItmInd-%u"
+ " WHERE CrsCod=%ld"
+ " AND ItmInd>=-%u AND ItmInd<=-%u",
+ Diff.Begin,
Gbl.Hierarchy.Crs.CrsCod,
- -BottomEnd,-BottomBegin); // All indexes in bottom part
+ BottomIndex.End,BottomIndex.Begin); // All indexes in bottom part
/***** Unlock table *****/
Gbl.DB.LockedTables = false; // Set to false before the following unlock...
@@ -1528,7 +1524,7 @@ void Prg_RequestCreatOrEditPrgItem (void)
Grp_GetParamWhichGrps ();
/***** Get the code of the program item *****/
- ItsANewItem = ((Item.ItmCod = Prg_GetParamItmCod ()) == -1L);
+ ItsANewItem = ((Item.Hierarchy.ItmCod = Prg_GetParamItmCod ()) == -1L);
/***** Get from the database the data of the program item *****/
if (ItsANewItem)
@@ -1545,7 +1541,7 @@ void Prg_RequestCreatOrEditPrgItem (void)
Prg_GetDataOfItemByCod (&Item);
/* Get text of the program item from database */
- Prg_GetPrgItemTxtFromDB (Item.ItmCod,Txt);
+ Prg_GetPrgItemTxtFromDB (Item.Hierarchy.ItmCod,Txt);
}
/***** Begin form *****/
@@ -1557,7 +1553,7 @@ void Prg_RequestCreatOrEditPrgItem (void)
else
{
Frm_StartForm (ActChgPrgItm);
- Prg_SetCurrentItmCod (Item.ItmCod);
+ Prg_SetCurrentItmCod (Item.Hierarchy.ItmCod);
}
Prg_PutParams ();
@@ -1611,7 +1607,7 @@ void Prg_RequestCreatOrEditPrgItem (void)
HTM_TR_End ();
/***** Groups *****/
- Prg_ShowLstGrpsToEditPrgItem (Item.ItmCod);
+ Prg_ShowLstGrpsToEditPrgItem (Item.Hierarchy.ItmCod);
/***** End table, send button and end box *****/
if (ItsANewItem)
@@ -1706,8 +1702,8 @@ void Prg_RecFormPrgItem (void)
char Description[Cns_MAX_BYTES_TEXT + 1];
/***** Get the code of the program item *****/
- NewItem.ItmCod = Prg_GetParamItmCod ();
- ItsANewItem = (NewItem.ItmCod < 0);
+ NewItem.Hierarchy.ItmCod = Prg_GetParamItmCod ();
+ ItsANewItem = (NewItem.Hierarchy.ItmCod < 0);
if (ItsANewItem)
/***** Reset old (current, not existing) program item data *****/
@@ -1715,7 +1711,7 @@ void Prg_RecFormPrgItem (void)
else
{
/***** Get data of the old (current) program item from database *****/
- OldItem.ItmCod = NewItem.ItmCod;
+ OldItem.Hierarchy.ItmCod = NewItem.Hierarchy.ItmCod;
Prg_GetDataOfItemByCod (&OldItem);
}
@@ -1739,7 +1735,7 @@ void Prg_RecFormPrgItem (void)
if (NewItem.Title[0]) // If there's a program item title
{
/* If title of program item was in database... */
- if (Prg_CheckIfSimilarPrgItemExists ("Title",NewItem.Title,NewItem.ItmCod))
+ if (Prg_CheckIfSimilarPrgItemExists ("Title",NewItem.Title,NewItem.Hierarchy.ItmCod))
{
NewItemIsCorrect = false;
@@ -1803,15 +1799,15 @@ static void Prg_CreatePrgItem (struct ProgramItem *Item,const char *Txt)
MaxIndex = Prg_GetMaxItemIndex ();
/***** Create a new program item *****/
- Item->Index = MaxIndex + 1;
- Item->ItmCod =
+ Item->Hierarchy.Index = MaxIndex + 1;
+ Item->Hierarchy.ItmCod =
DB_QueryINSERTandReturnCode ("can not create new program item",
"INSERT INTO prg_items"
" (ItmInd,CrsCod,UsrCod,StartTime,EndTime,Title,Txt)"
" VALUES"
" (%u,%ld,%ld,FROM_UNIXTIME(%ld),FROM_UNIXTIME(%ld),"
"'%s','%s')",
- Item->Index,
+ Item->Hierarchy.Index,
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
Item->TimeUTC[Dat_START_TIME],
@@ -1827,7 +1823,7 @@ static void Prg_CreatePrgItem (struct ProgramItem *Item,const char *Txt)
/***** Create groups *****/
if (Gbl.Crs.Grps.LstGrpsSel.NumGrps)
- Prg_CreateGrps (Item->ItmCod);
+ Prg_CreateGrps (Item->Hierarchy.ItmCod);
}
/*****************************************************************************/
@@ -1848,15 +1844,15 @@ static void Prg_UpdatePrgItem (struct ProgramItem *Item,const char *Txt)
Item->TimeUTC[Dat_END_TIME ],
Item->Title,
Txt,
- Item->ItmCod,Gbl.Hierarchy.Crs.CrsCod);
+ Item->Hierarchy.ItmCod,Gbl.Hierarchy.Crs.CrsCod);
/***** Update groups *****/
/* Remove old groups */
- Prg_RemoveAllTheGrpsAssociatedToAnItem (Item->ItmCod);
+ Prg_RemoveAllTheGrpsAssociatedToAnItem (Item->Hierarchy.ItmCod);
/* Create new groups */
if (Gbl.Crs.Grps.LstGrpsSel.NumGrps)
- Prg_CreateGrps (Item->ItmCod);
+ Prg_CreateGrps (Item->Hierarchy.ItmCod);
}
/*****************************************************************************/
@@ -1974,7 +1970,7 @@ static void Prg_GetAndWriteNamesOfGrpsAssociatedToItem (struct ProgramItem *Item
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod"
" ORDER BY crs_grp_types.GrpTypName,"
"crs_grp.GrpName",
- Item->ItmCod);
+ Item->Hierarchy.ItmCod);
/***** Write heading *****/
HTM_DIV_Begin ("class=\"%s\"",Item->Hidden ? "ASG_GRP_LIGHT" :
diff --git a/swad_program.h b/swad_program.h
index 0074eb8d6..47bf2cfe9 100644
--- a/swad_program.h
+++ b/swad_program.h
@@ -39,12 +39,18 @@
#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 ProgramItem
+struct ProgramItemHierarchy
{
long ItmCod;
unsigned Index;
unsigned Level;
bool Hidden;
+ };
+
+struct ProgramItem
+ {
+ struct ProgramItemHierarchy Hierarchy;
+ bool Hidden;
long UsrCod;
time_t TimeUTC[Dat_NUM_START_END_TIME];
bool Open;
@@ -64,7 +70,6 @@ struct ProgramItem
void Prg_SeeCourseProgram (void);
void Prg_RequestCreatOrEditPrgItem (void);
-void Prg_GetListPrgItems (void);
void Prg_GetDataOfItemByCod (struct ProgramItem *PrgItem);
void Prg_FreeListItems (void);
@@ -77,8 +82,8 @@ void Prg_ShowPrgItem (void);
void Prg_MoveUpPrgItem (void);
void Prg_MoveDownPrgItem (void);
-void Prg_MoveRightPrgItem (void);
void Prg_MoveLeftPrgItem (void);
+void Prg_MoveRightPrgItem (void);
void Prg_RecFormPrgItem (void);
bool Prg_CheckIfItemIsAssociatedToGrp (long PrgItmCod,long GrpCod);
diff --git a/swad_text_action.c b/swad_text_action.c
index 5fcea68b1..0c3a0da8b 100644
--- a/swad_text_action.c
+++ b/swad_text_action.c
@@ -4997,15 +4997,15 @@ const char *Txt_Actions[Act_NUM_ACTIONS] =
"" // Precisa de tradução
#endif
,
- [ActRgtPrgItm] =
+ [ActLftPrgItm] =
#if L==1 // ca
"" // Necessita traducció
#elif L==2 // de
"" // Need Übersetzung
#elif L==3 // en
- "Move right program item"
+ "Move left program item"
#elif L==4 // es
- "Mover a la derecha ítem del programa"
+ "Mover a la izquierda ítem del programa"
#elif L==5 // fr
"" // Besoin de traduction
#elif L==6 // gn
@@ -5018,15 +5018,15 @@ const char *Txt_Actions[Act_NUM_ACTIONS] =
"" // Precisa de tradução
#endif
,
- [ActLftPrgItm] =
+ [ActRgtPrgItm] =
#if L==1 // ca
"" // Necessita traducció
#elif L==2 // de
"" // Need Übersetzung
#elif L==3 // en
- "Move left program item"
+ "Move right program item"
#elif L==4 // es
- "Mover a la izquierda ítem del programa"
+ "Mover a la derecha ítem del programa"
#elif L==5 // fr
"" // Besoin de traduction
#elif L==6 // gn