// swad_place.c: places /* 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-2017 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 calloc #include // For string functions #include "swad_constant.h" #include "swad_database.h" #include "swad_global.h" #include "swad_parameter.h" #include "swad_place.h" #include "swad_text.h" /*****************************************************************************/ /************** External global variables from others modules ****************/ /*****************************************************************************/ extern struct Globals Gbl; /*****************************************************************************/ /***************************** Private constants *****************************/ /*****************************************************************************/ /*****************************************************************************/ /******************************* Private types *******************************/ /*****************************************************************************/ /*****************************************************************************/ /***************************** Private variables *****************************/ /*****************************************************************************/ /*****************************************************************************/ /***************************** Private prototypes ****************************/ /*****************************************************************************/ static void Plc_GetParamPlcOrder (void); static void Plc_PutIconToEditPlaces (void); static void Plc_PutIconToViewPlacesWhenEditing (void); static void Plc_ListPlacesForEdition (void); static void Plc_PutParamPlcCod (long PlcCod); static void Plc_RenamePlace (Cns_ShrtOrFullName_t ShrtOrFullName); static bool Plc_CheckIfPlaceNameExists (const char *FieldName,const char *Name,long PlcCod); static void Plc_UpdatePlcNameDB (long PlcCod,const char *FieldName,const char *NewPlcName); static void Plc_PutFormToCreatePlace (void); static void Plc_PutHeadPlaces (void); static void Plc_CreatePlace (struct Place *Plc); /*****************************************************************************/ /********************** Put link (form) to view places ***********************/ /*****************************************************************************/ void Plc_PutIconToViewPlaces (void) { extern const char *Txt_Places; Lay_PutContextualLink (ActSeePlc,NULL,NULL, "mapmarker64x64.png", Txt_Places,NULL, NULL); } /*****************************************************************************/ /*************************** List all the places *****************************/ /*****************************************************************************/ void Plc_SeePlaces (void) { extern const char *Hlp_INSTITUTION_Places; extern const char *Txt_Places; extern const char *Txt_PLACES_HELP_ORDER[2]; extern const char *Txt_PLACES_ORDER[2]; extern const char *Txt_Other_places; extern const char *Txt_Place_unspecified; extern const char *Txt_New_place; Plc_Order_t Order; unsigned NumPlc; unsigned NumCtrsWithPlc = 0; unsigned NumCtrsInOtherPlcs; bool ICanEdit; if (Gbl.CurrentIns.Ins.InsCod > 0) { ICanEdit = (Gbl.Usrs.Me.LoggedRole >= Rol_INS_ADM); /***** Get parameter with the type of order in the list of places *****/ Plc_GetParamPlcOrder (); /***** Get list of places *****/ Plc_GetListPlaces (); /***** Table head *****/ Lay_StartRoundFrame (NULL,Txt_Places, ICanEdit ? Plc_PutIconToEditPlaces : NULL, Hlp_INSTITUTION_Places); Lay_StartTableWideMargin (2); fprintf (Gbl.F.Out,""); for (Order = Plc_ORDER_BY_PLACE; Order <= Plc_ORDER_BY_NUM_CTRS; Order++) { fprintf (Gbl.F.Out,""); Act_FormStart (ActSeePlc); Par_PutHiddenParamUnsigned ("Order",(unsigned) Order); Act_LinkFormSubmit (Txt_PLACES_HELP_ORDER[Order],"TIT_TBL",NULL); if (Order == Gbl.Plcs.SelectedOrder) fprintf (Gbl.F.Out,""); fprintf (Gbl.F.Out,"%s",Txt_PLACES_ORDER[Order]); if (Order == Gbl.Plcs.SelectedOrder) fprintf (Gbl.F.Out,""); fprintf (Gbl.F.Out,""); Act_FormEnd (); fprintf (Gbl.F.Out,""); } fprintf (Gbl.F.Out,""); /***** Write all places and their nuber of centres *****/ for (NumPlc = 0; NumPlc < Gbl.Plcs.Num; NumPlc++) { /* Write data of this place */ fprintf (Gbl.F.Out,"" "" "%s" "" "" "%u" "" "", Gbl.Plcs.Lst[NumPlc].FullName, Gbl.Plcs.Lst[NumPlc].NumCtrs); NumCtrsWithPlc += Gbl.Plcs.Lst[NumPlc].NumCtrs; } /***** Separation row *****/ fprintf (Gbl.F.Out,"" "" " " "" ""); /***** Write centres (of the current institution) with other place *****/ NumCtrsInOtherPlcs = Ctr_GetNumCtrsInPlc (0); fprintf (Gbl.F.Out,"" "" "%s" "" "" "%u" "" "", Txt_Other_places,NumCtrsInOtherPlcs); NumCtrsWithPlc += NumCtrsInOtherPlcs; /***** Write centres (of the current institution) with no place *****/ fprintf (Gbl.F.Out,"" "" "%s" "" "" "%u" "" "", Txt_Place_unspecified, Ctr_GetNumCtrsInIns (Gbl.CurrentIns.Ins.InsCod) - NumCtrsWithPlc); /***** End table *****/ Lay_EndTable (); /***** Button to create place *****/ if (ICanEdit) { Act_FormStart (ActEdiPlc); Lay_PutConfirmButton (Txt_New_place); Act_FormEnd (); } /***** End frame *****/ Lay_EndRoundFrame (); /***** Free list of places *****/ Plc_FreeListPlaces (); } } /*****************************************************************************/ /********** Get parameter with the type or order in list of places ***********/ /*****************************************************************************/ static void Plc_GetParamPlcOrder (void) { Gbl.Plcs.SelectedOrder = (Plc_Order_t) Par_GetParToUnsignedLong ("Order", 0, Plc_NUM_ORDERS - 1, (unsigned long) Plc_ORDER_DEFAULT); } /*****************************************************************************/ /********************** Put a link (form) to edit places *********************/ /*****************************************************************************/ static void Plc_PutIconToEditPlaces (void) { Lay_PutContextualIconToEdit (ActEdiPlc,NULL); } /*****************************************************************************/ /*************************** Put forms to edit places ************************/ /*****************************************************************************/ void Plc_EditPlaces (void) { extern const char *Hlp_INSTITUTION_Places_edit; extern const char *Txt_Places; /***** Get list of places *****/ Plc_GetListPlaces (); /***** Start frame *****/ Lay_StartRoundFrame (NULL,Txt_Places,Plc_PutIconToViewPlacesWhenEditing, Hlp_INSTITUTION_Places_edit); /***** Put a form to create a new place *****/ Plc_PutFormToCreatePlace (); /***** Forms to edit current places *****/ if (Gbl.Plcs.Num) Plc_ListPlacesForEdition (); /***** End frame *****/ Lay_EndRoundFrame (); /***** Free list of places *****/ Plc_FreeListPlaces (); } /*****************************************************************************/ /**************** Put contextual icons in edition of places *****************/ /*****************************************************************************/ static void Plc_PutIconToViewPlacesWhenEditing (void) { Lay_PutContextualIconToView (ActSeePlc,NULL); } /*****************************************************************************/ /**************************** List all the places ****************************/ /*****************************************************************************/ void Plc_GetListPlaces (void) { char OrderBySubQuery[256]; char Query[1024]; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned long NumRows; unsigned NumPlc; struct Place *Plc; /***** Get places from database *****/ switch (Gbl.Plcs.SelectedOrder) { case Plc_ORDER_BY_PLACE: sprintf (OrderBySubQuery,"FullName"); break; case Plc_ORDER_BY_NUM_CTRS: sprintf (OrderBySubQuery,"NumCtrs DESC,FullName"); break; } sprintf (Query,"(SELECT places.PlcCod,places.ShortName,places.FullName,COUNT(*) AS NumCtrs" " FROM places,centres" " WHERE places.InsCod=%ld" " AND places.PlcCod=centres.PlcCod" " AND centres.InsCod=%ld" " GROUP BY places.PlcCod)" " UNION " "(SELECT PlcCod,ShortName,FullName,0 AS NumCtrs" " FROM places" " WHERE InsCod=%ld" " AND PlcCod NOT IN" " (SELECT DISTINCT PlcCod FROM centres WHERE InsCod=%ld))" " ORDER BY %s", Gbl.CurrentIns.Ins.InsCod, Gbl.CurrentIns.Ins.InsCod, Gbl.CurrentIns.Ins.InsCod, Gbl.CurrentIns.Ins.InsCod, OrderBySubQuery); NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get places"); /***** Count number of rows in result *****/ if (NumRows) // Places found... { Gbl.Plcs.Num = (unsigned) NumRows; /***** Create list with courses in centre *****/ if ((Gbl.Plcs.Lst = (struct Place *) calloc (NumRows,sizeof (struct Place))) == NULL) Lay_ShowErrorAndExit ("Not enough memory to store places."); /***** Get the places *****/ for (NumPlc = 0; NumPlc < Gbl.Plcs.Num; NumPlc++) { Plc = &(Gbl.Plcs.Lst[NumPlc]); /* Get next place */ row = mysql_fetch_row (mysql_res); /* Get place code (row[0]) */ if ((Plc->PlcCod = Str_ConvertStrCodToLongCod (row[0])) < 0) Lay_ShowErrorAndExit ("Wrong code of place."); /* Get the short name of the place (row[1]) */ Str_Copy (Plc->ShrtName,row[1], Plc_MAX_BYTES_PLACE_SHRT_NAME); /* Get the full name of the place (row[2]) */ Str_Copy (Plc->FullName,row[2], Plc_MAX_BYTES_PLACE_FULL_NAME); /* Get number of centres in this place (row[3]) */ if (sscanf (row[3],"%u",&Plc->NumCtrs) != 1) Plc->NumCtrs = 0; } } else Gbl.Plcs.Num = 0; /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } /*****************************************************************************/ /**************************** Get place full name ****************************/ /*****************************************************************************/ void Plc_GetDataOfPlaceByCod (struct Place *Plc) { extern const char *Txt_Place_unspecified; extern const char *Txt_Another_place; char Query[1024]; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned long NumRows; /***** Clear data *****/ Plc->ShrtName[0] = '\0'; Plc->FullName[0] = '\0'; Plc->NumCtrs = 0; /***** Check if place code is correct *****/ if (Plc->PlcCod < 0) { Str_Copy (Plc->ShrtName,Txt_Place_unspecified, Plc_MAX_BYTES_PLACE_SHRT_NAME); Str_Copy (Plc->FullName,Txt_Place_unspecified, Plc_MAX_BYTES_PLACE_FULL_NAME); } else if (Plc->PlcCod == 0) { Str_Copy (Plc->ShrtName,Txt_Another_place, Plc_MAX_BYTES_PLACE_SHRT_NAME); Str_Copy (Plc->FullName,Txt_Another_place, Plc_MAX_BYTES_PLACE_FULL_NAME); } else if (Plc->PlcCod > 0) { /***** Get data of a place from database *****/ sprintf (Query,"(SELECT places.ShortName,places.FullName,COUNT(*)" " FROM places,centres" " WHERE places.PlcCod=%ld" " AND places.PlcCod=centres.PlcCod" " AND centres.PlcCod=%ld" " GROUP BY places.PlcCod)" " UNION " "(SELECT ShortName,FullName,0" " FROM places" " WHERE PlcCod=%ld" " AND PlcCod NOT IN" " (SELECT DISTINCT PlcCod FROM centres))", Plc->PlcCod, Plc->PlcCod, Plc->PlcCod); NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get data of a place"); /***** Count number of rows in result *****/ if (NumRows) // Place found... { /* Get row */ row = mysql_fetch_row (mysql_res); /* Get the short name of the place (row[0]) */ Str_Copy (Plc->ShrtName,row[0], Plc_MAX_BYTES_PLACE_SHRT_NAME); /* Get the full name of the place (row[1]) */ Str_Copy (Plc->FullName,row[1], Plc_MAX_BYTES_PLACE_FULL_NAME); /* Get number of centres in this place (row[2]) */ if (sscanf (row[2],"%u",&Plc->NumCtrs) != 1) Plc->NumCtrs = 0; } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } } /*****************************************************************************/ /**************************** Free list of places ****************************/ /*****************************************************************************/ void Plc_FreeListPlaces (void) { if (Gbl.Plcs.Lst) { /***** Free memory used by the list of places in institution *****/ free ((void *) Gbl.Plcs.Lst); Gbl.Plcs.Lst = NULL; Gbl.Plcs.Num = 0; } } /*****************************************************************************/ /*************************** List all the places *****************************/ /*****************************************************************************/ static void Plc_ListPlacesForEdition (void) { unsigned NumPlc; struct Place *Plc; /***** Write heading *****/ Lay_StartTableWide (2); Plc_PutHeadPlaces (); /***** Write all the places *****/ for (NumPlc = 0; NumPlc < Gbl.Plcs.Num; NumPlc++) { Plc = &Gbl.Plcs.Lst[NumPlc]; /* Put icon to remove place */ fprintf (Gbl.F.Out,"" ""); if (Plc->NumCtrs) // Place has centres ==> deletion forbidden Lay_PutIconRemovalNotAllowed (); else { Act_FormStart (ActRemPlc); Plc_PutParamPlcCod (Plc->PlcCod); Lay_PutIconRemove (); Act_FormEnd (); } fprintf (Gbl.F.Out,""); /* Place code */ fprintf (Gbl.F.Out,"" "%ld" "", Plc->PlcCod); /* Place short name */ fprintf (Gbl.F.Out,""); Act_FormStart (ActRenPlcSho); Plc_PutParamPlcCod (Plc->PlcCod); fprintf (Gbl.F.Out,"", Plc_MAX_CHARS_PLACE_SHRT_NAME,Plc->ShrtName,Gbl.Form.Id); Act_FormEnd (); fprintf (Gbl.F.Out,""); /* Place full name */ fprintf (Gbl.F.Out,""); Act_FormStart (ActRenPlcFul); Plc_PutParamPlcCod (Plc->PlcCod); fprintf (Gbl.F.Out,"", Plc_MAX_CHARS_PLACE_FULL_NAME,Plc->FullName,Gbl.Form.Id); Act_FormEnd (); fprintf (Gbl.F.Out,""); /* Number of centres */ fprintf (Gbl.F.Out,"" "%u" "" "", Plc->NumCtrs); } /***** End table *****/ Lay_EndTable (); } /*****************************************************************************/ /******************** Write parameter with code of place *********************/ /*****************************************************************************/ static void Plc_PutParamPlcCod (long PlcCod) { Par_PutHiddenParamLong ("PlcCod",PlcCod); } /*****************************************************************************/ /********************* Get parameter with code of place **********************/ /*****************************************************************************/ long Plc_GetParamPlcCod (void) { /***** Get code of place *****/ return Par_GetParToLong ("PlcCod"); } /*****************************************************************************/ /******************************* Remove a place ******************************/ /*****************************************************************************/ void Plc_RemovePlace (void) { extern const char *Txt_To_remove_a_place_you_must_first_remove_all_centres_of_that_place; extern const char *Txt_Place_X_removed; char Query[128]; struct Place Plc; /***** Get place code *****/ if ((Plc.PlcCod = Plc_GetParamPlcCod ()) == -1L) Lay_ShowErrorAndExit ("Code of place is missing."); /***** Get data of the place from database *****/ Plc_GetDataOfPlaceByCod (&Plc); /***** Check if this place has centres *****/ if (Plc.NumCtrs) // Place has centres ==> don't remove Ale_ShowAlert (Ale_WARNING,Txt_To_remove_a_place_you_must_first_remove_all_centres_of_that_place); else // Place has no centres ==> remove it { /***** Remove place *****/ sprintf (Query,"DELETE FROM places WHERE PlcCod=%ld", Plc.PlcCod); DB_QueryDELETE (Query,"can not remove a place"); /***** Write message to show the change made *****/ sprintf (Gbl.Alert.Txt,Txt_Place_X_removed, Plc.FullName); Ale_ShowAlert (Ale_SUCCESS,Gbl.Alert.Txt); } /***** Show the form again *****/ Plc_EditPlaces (); } /*****************************************************************************/ /********************* Change the short name of a place **********************/ /*****************************************************************************/ void Plc_RenamePlaceShort (void) { Plc_RenamePlace (Cns_SHRT_NAME); } /*****************************************************************************/ /********************* Change the full name of a place ***********************/ /*****************************************************************************/ void Plc_RenamePlaceFull (void) { Plc_RenamePlace (Cns_FULL_NAME); } /*****************************************************************************/ /************************ Change the name of a place *************************/ /*****************************************************************************/ static void Plc_RenamePlace (Cns_ShrtOrFullName_t ShrtOrFullName) { extern const char *Txt_You_can_not_leave_the_name_of_the_place_X_empty; extern const char *Txt_The_place_X_already_exists; extern const char *Txt_The_place_X_has_been_renamed_as_Y; extern const char *Txt_The_name_of_the_place_X_has_not_changed; struct Place *Plc; const char *ParamName = NULL; // Initialized to avoid warning const char *FieldName = NULL; // Initialized to avoid warning unsigned MaxBytes = 0; // Initialized to avoid warning char *CurrentPlcName = NULL; // Initialized to avoid warning char NewPlcName[Plc_MAX_BYTES_PLACE_FULL_NAME + 1]; Plc = &Gbl.Plcs.EditingPlc; switch (ShrtOrFullName) { case Cns_SHRT_NAME: ParamName = "ShortName"; FieldName = "ShortName"; MaxBytes = Plc_MAX_BYTES_PLACE_SHRT_NAME; CurrentPlcName = Plc->ShrtName; break; case Cns_FULL_NAME: ParamName = "FullName"; FieldName = "FullName"; MaxBytes = Plc_MAX_BYTES_PLACE_FULL_NAME; CurrentPlcName = Plc->FullName; break; } /***** Get parameters from form *****/ /* Get the code of the place */ if ((Plc->PlcCod = Plc_GetParamPlcCod ()) == -1L) Lay_ShowErrorAndExit ("Code of place is missing."); /* Get the new name for the place */ Par_GetParToText (ParamName,NewPlcName,MaxBytes); /***** Get from the database the old names of the place *****/ Plc_GetDataOfPlaceByCod (Plc); /***** Check if new name is empty *****/ if (!NewPlcName[0]) { sprintf (Gbl.Alert.Txt,Txt_You_can_not_leave_the_name_of_the_place_X_empty, CurrentPlcName); Ale_ShowAlert (Ale_WARNING,Gbl.Alert.Txt); } else { /***** Check if old and new names are the same (this happens when user press enter with no changes in the form) *****/ if (strcmp (CurrentPlcName,NewPlcName)) // Different names { /***** If place was in database... *****/ if (Plc_CheckIfPlaceNameExists (ParamName,NewPlcName,Plc->PlcCod)) { sprintf (Gbl.Alert.Txt,Txt_The_place_X_already_exists, NewPlcName); Ale_ShowAlert (Ale_WARNING,Gbl.Alert.Txt); } else { /* Update the table changing old name by new name */ Plc_UpdatePlcNameDB (Plc->PlcCod,FieldName,NewPlcName); /* Write message to show the change made */ sprintf (Gbl.Alert.Txt,Txt_The_place_X_has_been_renamed_as_Y, CurrentPlcName,NewPlcName); Ale_ShowAlert (Ale_SUCCESS,Gbl.Alert.Txt); } } else // The same name { sprintf (Gbl.Alert.Txt,Txt_The_name_of_the_place_X_has_not_changed, CurrentPlcName); Ale_ShowAlert (Ale_INFO,Gbl.Alert.Txt); } } /***** Show the form again *****/ Str_Copy (CurrentPlcName,NewPlcName, MaxBytes); Plc_EditPlaces (); } /*****************************************************************************/ /********************** Check if the name of place exists ********************/ /*****************************************************************************/ static bool Plc_CheckIfPlaceNameExists (const char *FieldName,const char *Name,long PlcCod) { char Query[256 + Plc_MAX_BYTES_PLACE_FULL_NAME]; /***** Get number of places with a name from database *****/ sprintf (Query,"SELECT COUNT(*) FROM places" " WHERE InsCod=%ld AND %s='%s' AND PlcCod<>%ld", Gbl.CurrentIns.Ins.InsCod,FieldName,Name,PlcCod); return (DB_QueryCOUNT (Query,"can not check if the name of a place already existed") != 0); } /*****************************************************************************/ /****************** Update place name in table of places *********************/ /*****************************************************************************/ static void Plc_UpdatePlcNameDB (long PlcCod,const char *FieldName,const char *NewPlcName) { char Query[128 + Plc_MAX_BYTES_PLACE_FULL_NAME]; /***** Update place changing old name by new name */ sprintf (Query,"UPDATE places SET %s='%s' WHERE PlcCod=%ld", FieldName,NewPlcName,PlcCod); DB_QueryUPDATE (Query,"can not update the name of a place"); } /*****************************************************************************/ /********************* Put a form to create a new place **********************/ /*****************************************************************************/ static void Plc_PutFormToCreatePlace (void) { extern const char *Txt_New_place; extern const char *Txt_Create_place; struct Place *Plc; /***** Place data *****/ Plc = &Gbl.Plcs.EditingPlc; /***** Start form *****/ Act_FormStart (ActNewPlc); /***** Start frame *****/ Lay_StartRoundFrameTable (NULL,Txt_New_place,NULL,NULL,2); /***** Write heading *****/ Plc_PutHeadPlaces (); /***** Column to remove place, disabled here *****/ fprintf (Gbl.F.Out,"" ""); /***** Place code *****/ fprintf (Gbl.F.Out,""); /***** Place short name *****/ fprintf (Gbl.F.Out,"" "" "", Plc_MAX_CHARS_PLACE_SHRT_NAME,Plc->ShrtName); /***** Place full name *****/ fprintf (Gbl.F.Out,"" "" "", Plc_MAX_CHARS_PLACE_FULL_NAME,Plc->FullName); /***** Number of centres *****/ fprintf (Gbl.F.Out,"" "0" "" ""); /***** Send button and end frame *****/ Lay_EndRoundFrameTableWithButton (Lay_CREATE_BUTTON,Txt_Create_place); /***** End formn *****/ Act_FormEnd (); } /*****************************************************************************/ /******************** Write header with fields of a place ********************/ /*****************************************************************************/ static void Plc_PutHeadPlaces (void) { extern const char *Txt_Code; extern const char *Txt_Short_name; extern const char *Txt_Full_name; extern const char *Txt_Centres; fprintf (Gbl.F.Out,"" "" "" "%s" "" "" "%s" "" "" "%s" "" "" "%s" "" "", Txt_Code, Txt_Short_name, Txt_Full_name, Txt_Centres); } /*****************************************************************************/ /******************* Receive form to create a new place **********************/ /*****************************************************************************/ void Plc_RecFormNewPlace (void) { extern const char *Txt_The_place_X_already_exists; extern const char *Txt_You_must_specify_the_short_name_and_the_full_name_of_the_new_place; struct Place *Plc; Plc = &Gbl.Plcs.EditingPlc; /***** Get parameters from form *****/ /* Get place short name */ Par_GetParToText ("ShortName",Plc->ShrtName,Plc_MAX_BYTES_PLACE_SHRT_NAME); /* Get place full name */ Par_GetParToText ("FullName",Plc->FullName,Plc_MAX_BYTES_PLACE_FULL_NAME); if (Plc->ShrtName[0] && Plc->FullName[0]) // If there's a place name { /***** If name of place was in database... *****/ if (Plc_CheckIfPlaceNameExists ("ShortName",Plc->ShrtName,-1L)) { sprintf (Gbl.Alert.Txt,Txt_The_place_X_already_exists, Plc->ShrtName); Ale_ShowAlert (Ale_WARNING,Gbl.Alert.Txt); } else if (Plc_CheckIfPlaceNameExists ("FullName",Plc->FullName,-1L)) { sprintf (Gbl.Alert.Txt,Txt_The_place_X_already_exists, Plc->FullName); Ale_ShowAlert (Ale_WARNING,Gbl.Alert.Txt); } else // Add new place to database Plc_CreatePlace (Plc); } else // If there is not a place name Ale_ShowAlert (Ale_WARNING,Txt_You_must_specify_the_short_name_and_the_full_name_of_the_new_place); /***** Show the form again *****/ Plc_EditPlaces (); } /*****************************************************************************/ /**************************** Create a new place *****************************/ /*****************************************************************************/ static void Plc_CreatePlace (struct Place *Plc) { extern const char *Txt_Created_new_place_X; char Query[256 + Plc_MAX_BYTES_PLACE_SHRT_NAME + Plc_MAX_BYTES_PLACE_FULL_NAME]; /***** Create a new place *****/ sprintf (Query,"INSERT INTO places" " (InsCod,ShortName,FullName)" " VALUES" " (%ld,'%s','%s')", Gbl.CurrentIns.Ins.InsCod,Plc->ShrtName,Plc->FullName); DB_QueryINSERT (Query,"can not create place"); /***** Write success message *****/ sprintf (Gbl.Alert.Txt,Txt_Created_new_place_X, Plc->FullName); Ale_ShowAlert (Ale_SUCCESS,Gbl.Alert.Txt); }