diff --git a/swad_classroom.c b/swad_classroom.c
new file mode 100644
index 000000000..29f28014e
--- /dev/null
+++ b/swad_classroom.c
@@ -0,0 +1,842 @@
+// swad_classroom.c: classrooms, laboratories or other classrooms where classes are taught
+
+/*
+ SWAD (Shared Workspace At a Distance),
+ is a web platform developed at the University of Granada (Spain),
+ and used to support university teaching.
+
+ This file is part of SWAD core.
+ Copyright (C) 1999-2018 Antonio Caņas Vargas
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+/*****************************************************************************/
+/********************************** Headers **********************************/
+/*****************************************************************************/
+
+#include // For NULL
+#include // For string functions
+
+#include "swad_box.h"
+#include "swad_database.h"
+#include "swad_form.h"
+#include "swad_global.h"
+#include "swad_classroom.h"
+#include "swad_table.h"
+
+/*****************************************************************************/
+/************** External global variables from others modules ****************/
+/*****************************************************************************/
+
+extern struct Globals Gbl;
+
+/*****************************************************************************/
+/***************************** Private constants *****************************/
+/*****************************************************************************/
+
+/*****************************************************************************/
+/******************************* Private types *******************************/
+/*****************************************************************************/
+
+/*****************************************************************************/
+/***************************** Private variables *****************************/
+/*****************************************************************************/
+
+/*****************************************************************************/
+/***************************** Private prototypes ****************************/
+/*****************************************************************************/
+
+static void Cla_GetParamClaOrder (void);
+static bool Cla_CheckIfICanCreateClassrooms (void);
+static void Cla_PutIconsListingClassrooms (void);
+static void Cla_PutIconToEditClassrooms (void);
+static void Cla_PutIconsEditingClassrooms (void);
+
+static void Cla_ListClassroomsForEdition (void);
+static void Cla_PutParamClaCod (long ClaCod);
+
+static void Cla_RenameClassroom (Cns_ShrtOrFullName_t ShrtOrFullName);
+static bool Cla_CheckIfClassroomNameExists (const char *FieldName,const char *Name,long ClaCod);
+static void Cla_UpdateClaNameDB (long ClaCod,const char *FieldName,const char *NewClaName);
+
+static void Cla_PutFormToCreateClassroom (void);
+static void Cla_PutHeadClassrooms (void);
+static void Cla_CreateClassroom (struct Classroom *Cla);
+
+/*****************************************************************************/
+/************************* List all the classrooms ***************************/
+/*****************************************************************************/
+
+void Cla_SeeClassrooms (void)
+ {
+ extern const char *Hlp_CENTRE_Classrooms;
+ extern const char *Txt_Classrooms;
+ extern const char *Txt_CLASSROOMS_HELP_ORDER[2];
+ extern const char *Txt_CLASSROOMS_ORDER[2];
+ extern const char *Txt_New_classroom;
+ Cla_Order_t Order;
+ unsigned NumCla;
+
+ if (Gbl.CurrentCtr.Ctr.CtrCod > 0)
+ {
+ /***** Get parameter with the type of order in the list of classrooms *****/
+ Cla_GetParamClaOrder ();
+
+ /***** Get list of classrooms *****/
+ Cla_GetListClassrooms ();
+
+ /***** Table head *****/
+ Box_StartBox (NULL,Txt_Classrooms,Cla_PutIconsListingClassrooms,
+ Hlp_CENTRE_Classrooms,Box_NOT_CLOSABLE);
+ Tbl_StartTableWideMargin (2);
+ fprintf (Gbl.F.Out,"
");
+ for (Order = Cla_ORDER_BY_CLASSROOM;
+ Order <= Cla_ORDER_BY_NUM_STDS;
+ Order++)
+ {
+ fprintf (Gbl.F.Out,"
");
+
+ /***** Write all classrooms and their nuber of students *****/
+ for (NumCla = 0;
+ NumCla < Gbl.Classrooms.Num;
+ NumCla++)
+ {
+ /* Write data of this classroom */
+ fprintf (Gbl.F.Out,"
"
+ "
"
+ "%s"
+ "
"
+ "
"
+ "%u"
+ "
"
+ "
",
+ Gbl.Classrooms.Lst[NumCla].FullName,
+ Gbl.Classrooms.Lst[NumCla].NumStds);
+ }
+
+ /***** End table *****/
+ Tbl_EndTable ();
+
+ /***** Button to create classroom *****/
+ if (Cla_CheckIfICanCreateClassrooms ())
+ {
+ Frm_StartForm (ActEdiCla);
+ Btn_PutConfirmButton (Txt_New_classroom);
+ Frm_EndForm ();
+ }
+
+ /***** End box *****/
+ Box_EndBox ();
+
+ /***** Free list of classrooms *****/
+ Cla_FreeListClassrooms ();
+ }
+ }
+
+/*****************************************************************************/
+/******** Get parameter with the type or order in list of classrooms *********/
+/*****************************************************************************/
+
+static void Cla_GetParamClaOrder (void)
+ {
+ Gbl.Classrooms.SelectedOrder = (Cla_Order_t)
+ Par_GetParToUnsignedLong ("Order",
+ 0,
+ Cla_NUM_ORDERS - 1,
+ (unsigned long) Cla_ORDER_DEFAULT);
+ }
+
+/*****************************************************************************/
+/******************** Check if I can create classrooms ***********************/
+/*****************************************************************************/
+
+static bool Cla_CheckIfICanCreateClassrooms (void)
+ {
+ return (bool) (Gbl.Usrs.Me.Role.Logged >= Rol_INS_ADM);
+ }
+
+/*****************************************************************************/
+/**************** Put contextual icons in list of classrooms *****************/
+/*****************************************************************************/
+
+static void Cla_PutIconsListingClassrooms (void)
+ {
+ /***** Put icon to edit classrooms *****/
+ if (Cla_CheckIfICanCreateClassrooms ())
+ Cla_PutIconToEditClassrooms ();
+ }
+
+/*****************************************************************************/
+/******************** Put a link (form) to edit classrooms *******************/
+/*****************************************************************************/
+
+static void Cla_PutIconToEditClassrooms (void)
+ {
+ Ico_PutContextualIconToEdit (ActEdiCla,NULL);
+ }
+
+/*****************************************************************************/
+/************************* Put forms to edit classrooms **********************/
+/*****************************************************************************/
+
+void Cla_EditClassrooms (void)
+ {
+ extern const char *Hlp_CENTRE_Classrooms_edit;
+ extern const char *Txt_Classrooms;
+
+ /***** Get list of classrooms *****/
+ Cla_GetListClassrooms ();
+
+ /***** Start box *****/
+ Box_StartBox (NULL,Txt_Classrooms,Cla_PutIconsEditingClassrooms,
+ Hlp_CENTRE_Classrooms_edit,Box_NOT_CLOSABLE);
+
+ /***** Put a form to create a new classroom *****/
+ Cla_PutFormToCreateClassroom ();
+
+ /***** Forms to edit current classrooms *****/
+ if (Gbl.Classrooms.Num)
+ Cla_ListClassroomsForEdition ();
+
+ /***** End box *****/
+ Box_EndBox ();
+
+ /***** Free list of classrooms *****/
+ Cla_FreeListClassrooms ();
+ }
+
+
+/*****************************************************************************/
+/*************** Put contextual icons in edition of classrooms ***************/
+/*****************************************************************************/
+
+static void Cla_PutIconsEditingClassrooms (void)
+ {
+ /***** Put icon to view classrooms *****/
+ Cla_PutIconToViewClassrooms ();
+ }
+
+/*****************************************************************************/
+/************************ Put icon to view classrooms ************************/
+/*****************************************************************************/
+
+void Cla_PutIconToViewClassrooms (void)
+ {
+ extern const char *Txt_Classrooms;
+
+ Lay_PutContextualLink (ActSeeCla,NULL,NULL,
+ "classroom.svg",
+ Txt_Classrooms,NULL,
+ NULL);
+ }
+
+/*****************************************************************************/
+/************************** List all the classrooms **************************/
+/*****************************************************************************/
+
+void Cla_GetListClassrooms (void)
+ {
+ char OrderBySubQuery[256];
+ MYSQL_RES *mysql_res;
+ MYSQL_ROW row;
+ unsigned long NumRows;
+ unsigned NumCla;
+ struct Classroom *Cla;
+
+ /***** Get classrooms from database *****/
+ switch (Gbl.Classrooms.SelectedOrder)
+ {
+ case Cla_ORDER_BY_CLASSROOM:
+ sprintf (OrderBySubQuery,"FullName");
+ break;
+ case Cla_ORDER_BY_NUM_STDS:
+ sprintf (OrderBySubQuery,"NumStds DESC,FullName");
+ break;
+ }
+ NumRows = DB_QuerySELECT (&mysql_res,"can not get classrooms",
+ "SELECT ClaCod,"
+ "ShortName,"
+ "FullName,"
+ "NumStds"
+ " FROM classrooms"
+ " WHERE CtrCod=%ld"
+ " ORDER BY %s",
+ Gbl.CurrentCtr.Ctr.CtrCod,
+ OrderBySubQuery);
+
+ /***** Count number of rows in result *****/
+ if (NumRows) // Classrooms found...
+ {
+ Gbl.Classrooms.Num = (unsigned) NumRows;
+
+ /***** Create list with courses in centre *****/
+ if ((Gbl.Classrooms.Lst = (struct Classroom *) calloc (NumRows,sizeof (struct Classroom))) == NULL)
+ Lay_NotEnoughMemoryExit ();
+
+ /***** Get the classrooms *****/
+ for (NumCla = 0;
+ NumCla < Gbl.Classrooms.Num;
+ NumCla++)
+ {
+ Cla = &(Gbl.Classrooms.Lst[NumCla]);
+
+ /* Get next classroom */
+ row = mysql_fetch_row (mysql_res);
+
+ /* Get classroom code (row[0]) */
+ if ((Cla->ClaCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
+ Lay_ShowErrorAndExit ("Wrong code of classroom.");
+
+ /* Get the short name of the classroom (row[1]) */
+ Str_Copy (Cla->ShrtName,row[1],
+ Cla_MAX_BYTES_CLASSROOM_SHRT_NAME);
+
+ /* Get the full name of the classroom (row[2]) */
+ Str_Copy (Cla->FullName,row[2],
+ Cla_MAX_BYTES_CLASSROOM_FULL_NAME);
+
+ /* Get number of students in this classroom (row[3]) */
+ if (sscanf (row[3],"%u",&Cla->NumStds) != 1)
+ Cla->NumStds = 0;
+ }
+ }
+ else
+ Gbl.Classrooms.Num = 0;
+
+ /***** Free structure that stores the query result *****/
+ DB_FreeMySQLResult (&mysql_res);
+ }
+
+/*****************************************************************************/
+/************************** Get classroom full name **************************/
+/*****************************************************************************/
+
+void Cla_GetDataOfClassroomByCod (struct Classroom *Cla)
+ {
+ extern const char *Txt_Classroom_unspecified;
+ extern const char *Txt_Another_classroom;
+ MYSQL_RES *mysql_res;
+ MYSQL_ROW row;
+ unsigned long NumRows;
+
+ /***** Clear data *****/
+ Cla->ShrtName[0] = '\0';
+ Cla->FullName[0] = '\0';
+ Cla->NumStds = 0;
+
+ /***** Check if classroom code is correct *****/
+ if (Cla->ClaCod < 0)
+ {
+ Str_Copy (Cla->ShrtName,Txt_Classroom_unspecified,
+ Cla_MAX_BYTES_CLASSROOM_SHRT_NAME);
+ Str_Copy (Cla->FullName,Txt_Classroom_unspecified,
+ Cla_MAX_BYTES_CLASSROOM_FULL_NAME);
+ }
+ else if (Cla->ClaCod == 0)
+ {
+ Str_Copy (Cla->ShrtName,Txt_Another_classroom,
+ Cla_MAX_BYTES_CLASSROOM_SHRT_NAME);
+ Str_Copy (Cla->FullName,Txt_Another_classroom,
+ Cla_MAX_BYTES_CLASSROOM_FULL_NAME);
+ }
+ else if (Cla->ClaCod > 0)
+ {
+ /***** Get data of a classroom from database *****/
+ NumRows = DB_QuerySELECT (&mysql_res,"can not get data of a classroom",
+ "SELECT ShortName,"
+ "FullName,"
+ "NumStds"
+ " FROM classrooms"
+ " WHERE ClaCod=%ld",
+ Cla->ClaCod);
+
+ /***** Count number of rows in result *****/
+ if (NumRows) // Classroom found...
+ {
+ /* Get row */
+ row = mysql_fetch_row (mysql_res);
+
+ /* Get the short name of the classroom (row[0]) */
+ Str_Copy (Cla->ShrtName,row[0],
+ Cla_MAX_BYTES_CLASSROOM_SHRT_NAME);
+
+ /* Get the full name of the classroom (row[1]) */
+ Str_Copy (Cla->FullName,row[1],
+ Cla_MAX_BYTES_CLASSROOM_FULL_NAME);
+
+ /* Get number of students in this classroom (row[2]) */
+ if (sscanf (row[2],"%u",&Cla->NumStds) != 1)
+ Cla->NumStds = 0;
+ }
+
+ /***** Free structure that stores the query result *****/
+ DB_FreeMySQLResult (&mysql_res);
+ }
+ }
+
+/*****************************************************************************/
+/************************** Free list of classrooms **************************/
+/*****************************************************************************/
+
+void Cla_FreeListClassrooms (void)
+ {
+ if (Gbl.Classrooms.Lst)
+ {
+ /***** Free memory used by the list of classrooms in institution *****/
+ free ((void *) Gbl.Classrooms.Lst);
+ Gbl.Classrooms.Lst = NULL;
+ Gbl.Classrooms.Num = 0;
+ }
+ }
+
+/*****************************************************************************/
+/************************* List all the classrooms ***************************/
+/*****************************************************************************/
+
+static void Cla_ListClassroomsForEdition (void)
+ {
+ unsigned NumCla;
+ struct Classroom *Cla;
+
+ /***** Write heading *****/
+ Tbl_StartTableWide (2);
+ Cla_PutHeadClassrooms ();
+
+ /***** Write all the classrooms *****/
+ for (NumCla = 0;
+ NumCla < Gbl.Classrooms.Num;
+ NumCla++)
+ {
+ Cla = &Gbl.Classrooms.Lst[NumCla];
+
+ /* Put icon to remove classroom */
+ fprintf (Gbl.F.Out,"
");
+
+ /***** Classroom short name *****/
+ fprintf (Gbl.F.Out,"
"
+ ""
+ "
",
+ Cla_MAX_CHARS_CLASSROOM_SHRT_NAME,Cla->ShrtName);
+
+ /***** Classroom full name *****/
+ fprintf (Gbl.F.Out,"
"
+ ""
+ "
",
+ Cla_MAX_CHARS_CLASSROOM_FULL_NAME,Cla->FullName);
+
+ /***** Number of students *****/
+ fprintf (Gbl.F.Out,"
"
+ "0"
+ "
"
+ "
");
+
+ /***** End table, send button and end box *****/
+ Box_EndBoxTableWithButton (Btn_CREATE_BUTTON,Txt_Create_classroom);
+
+ /***** End form *****/
+ Frm_EndForm ();
+ }
+
+/*****************************************************************************/
+/****************** Write header with fields of a classroom ******************/
+/*****************************************************************************/
+
+static void Cla_PutHeadClassrooms (void)
+ {
+ extern const char *Txt_Code;
+ extern const char *Txt_Short_name;
+ extern const char *Txt_Full_name;
+ extern const char *Txt_ROLES_PLURAL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
+
+ fprintf (Gbl.F.Out,"
"
+ "
"
+ "
"
+ "%s"
+ "
"
+ "
"
+ "%s"
+ "
"
+ "
"
+ "%s"
+ "
"
+ "
"
+ "%s"
+ "
"
+ "
",
+ Txt_Code,
+ Txt_Short_name,
+ Txt_Full_name,
+ Txt_ROLES_PLURAL_Abc[Rol_STD][Usr_SEX_UNKNOWN]);
+ }
+
+/*****************************************************************************/
+/***************** Receive form to create a new classroom ********************/
+/*****************************************************************************/
+
+void Cla_RecFormNewClassroom (void)
+ {
+ extern const char *Txt_The_classroom_X_already_exists;
+ extern const char *Txt_You_must_specify_the_short_name_and_the_full_name_of_the_new_classroom;
+ struct Classroom *Cla;
+
+ Cla = &Gbl.Classrooms.EditingCla;
+
+ /***** Get parameters from form *****/
+ /* Get classroom short name */
+ Par_GetParToText ("ShortName",Cla->ShrtName,Cla_MAX_BYTES_CLASSROOM_SHRT_NAME);
+
+ /* Get classroom full name */
+ Par_GetParToText ("FullName",Cla->FullName,Cla_MAX_BYTES_CLASSROOM_FULL_NAME);
+
+ if (Cla->ShrtName[0] && Cla->FullName[0]) // If there's a classroom name
+ {
+ /***** If name of classroom was in database... *****/
+ if (Cla_CheckIfClassroomNameExists ("ShortName",Cla->ShrtName,-1L))
+ {
+ snprintf (Gbl.Alert.Txt,sizeof (Gbl.Alert.Txt),
+ Txt_The_classroom_X_already_exists,
+ Cla->ShrtName);
+ Ale_ShowAlert (Ale_WARNING,Gbl.Alert.Txt);
+ }
+ else if (Cla_CheckIfClassroomNameExists ("FullName",Cla->FullName,-1L))
+ {
+ snprintf (Gbl.Alert.Txt,sizeof (Gbl.Alert.Txt),
+ Txt_The_classroom_X_already_exists,
+ Cla->FullName);
+ Ale_ShowAlert (Ale_WARNING,Gbl.Alert.Txt);
+ }
+ else // Add new classroom to database
+ Cla_CreateClassroom (Cla);
+ }
+ else // If there is not a classroom name
+ Ale_ShowAlert (Ale_WARNING,Txt_You_must_specify_the_short_name_and_the_full_name_of_the_new_classroom);
+
+ /***** Show the form again *****/
+ Cla_EditClassrooms ();
+ }
+
+/*****************************************************************************/
+/************************** Create a new classroom ***************************/
+/*****************************************************************************/
+
+static void Cla_CreateClassroom (struct Classroom *Cla)
+ {
+ extern const char *Txt_Created_new_classroom_X;
+
+ /***** Create a new classroom *****/
+ DB_QueryINSERT ("can not create classroom",
+ "INSERT INTO classrooms"
+ " (CtrCod,ShortName,FullName,NumStds)"
+ " VALUES"
+ " (%ld,'%s','%s',%u)",
+ Gbl.CurrentCtr.Ctr.CtrCod,
+ Cla->ShrtName,Cla->FullName,Cla->NumStds);
+
+ /***** Write success message *****/
+ snprintf (Gbl.Alert.Txt,sizeof (Gbl.Alert.Txt),
+ Txt_Created_new_classroom_X,
+ Cla->FullName);
+ Ale_ShowAlert (Ale_SUCCESS,Gbl.Alert.Txt);
+ }
diff --git a/swad_classroom.h b/swad_classroom.h
new file mode 100644
index 000000000..fcf86c7c0
--- /dev/null
+++ b/swad_classroom.h
@@ -0,0 +1,75 @@
+// swad_classroom.h: classrooms, laboratories or other classrooms where classes are taught
+
+#ifndef _SWAD_CLA
+#define _SWAD_CLA
+/*
+ SWAD (Shared Workspace At a Distance in Spanish),
+ is a web platform developed at the University of Granada (Spain),
+ and used to support university teaching.
+
+ This file is part of SWAD core.
+ Copyright (C) 1999-2018 Antonio Caņas Vargas
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+/*****************************************************************************/
+/********************************** Headers **********************************/
+/*****************************************************************************/
+
+#include "swad_string.h"
+
+/*****************************************************************************/
+/************************** Public types and constants ***********************/
+/*****************************************************************************/
+
+#define Cla_MAX_CHARS_CLASSROOM_SHRT_NAME (32 - 1) // 31
+#define Cla_MAX_BYTES_CLASSROOM_SHRT_NAME ((Cla_MAX_CHARS_CLASSROOM_SHRT_NAME + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 511
+
+#define Cla_MAX_CHARS_CLASSROOM_FULL_NAME (128 - 1) // 127
+#define Cla_MAX_BYTES_CLASSROOM_FULL_NAME ((Cla_MAX_CHARS_CLASSROOM_FULL_NAME + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047
+
+struct Classroom
+ {
+ long ClaCod;
+ long InsCod;
+ char ShrtName[Cla_MAX_BYTES_CLASSROOM_SHRT_NAME + 1];
+ char FullName[Cla_MAX_BYTES_CLASSROOM_FULL_NAME + 1];
+ unsigned NumStds;
+ };
+
+#define Cla_NUM_ORDERS 2
+typedef enum
+ {
+ Cla_ORDER_BY_CLASSROOM = 0,
+ Cla_ORDER_BY_NUM_STDS = 1,
+ } Cla_Order_t;
+#define Cla_ORDER_DEFAULT Cla_ORDER_BY_CLASSROOM
+
+/*****************************************************************************/
+/***************************** Public prototypes *****************************/
+/*****************************************************************************/
+
+void Cla_SeeClassrooms (void);
+void Cla_EditClassrooms (void);
+void Cla_PutIconToViewClassrooms (void);
+void Cla_GetListClassrooms (void);
+void Cla_FreeListClassrooms (void);
+void Cla_GetDataOfClassroomByCod (struct Classroom *Cla);
+long Cla_GetParamClaCod (void);
+void Cla_RemoveClassroom (void);
+void Cla_RenameClassroomShort (void);
+void Cla_RenameClassroomFull (void);
+void Cla_RecFormNewClassroom (void);
+
+#endif