diff --git a/swad_form.c b/swad_form.c
new file mode 100644
index 00000000..179701a4
--- /dev/null
+++ b/swad_form.c
@@ -0,0 +1,294 @@
+// swad_form.c: forms to go to actions
+
+/*
+ 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 "swad_form.h"
+#include "swad_global.h"
+
+
+/*****************************************************************************/
+/************** External global variables from others modules ****************/
+/*****************************************************************************/
+
+extern struct Globals Gbl;
+
+/*****************************************************************************/
+/************************ Internal global variables **************************/
+/*****************************************************************************/
+
+/*****************************************************************************/
+/**************************** Private prototypes *****************************/
+/*****************************************************************************/
+
+static void Frm_StartFormInternal (Act_Action_t NextAction,bool PutParameterLocationIfNoSesion,
+ const char *Id,const char *Anchor,const char *OnSubmit);
+
+/*****************************************************************************/
+/******************************** Start a form *******************************/
+/*****************************************************************************/
+
+void Frm_StartFormGoTo (Act_Action_t NextAction)
+ {
+ Gbl.Form.Num++; // Initialized to -1. The first time it is incremented, it will be equal to 0
+ snprintf (Gbl.Form.Id,sizeof (Gbl.Form.Id),
+ "form_%d",
+ Gbl.Form.Num);
+ Frm_StartFormInternal (NextAction,false,Gbl.Form.Id,NULL,NULL); // Do not put now parameter location
+ }
+
+void Frm_StartForm (Act_Action_t NextAction)
+ {
+ Frm_StartFormAnchorOnSubmit (NextAction,NULL,NULL);
+ }
+
+void Frm_StartFormAnchor (Act_Action_t NextAction,const char *Anchor)
+ {
+ Frm_StartFormAnchorOnSubmit (NextAction,Anchor,NULL);
+ }
+
+void Frm_StartFormOnSubmit (Act_Action_t NextAction,const char *OnSubmit)
+ {
+ Frm_StartFormAnchorOnSubmit (NextAction,NULL,OnSubmit);
+ }
+
+void Frm_StartFormAnchorOnSubmit (Act_Action_t NextAction,const char *Anchor,const char *OnSubmit)
+ {
+ Gbl.Form.Num++; // Initialized to -1. The first time it is incremented, it will be equal to 0
+ snprintf (Gbl.Form.Id,sizeof (Gbl.Form.Id),
+ "form_%d",
+ Gbl.Form.Num);
+ Frm_StartFormInternal (NextAction,true,Gbl.Form.Id,Anchor,OnSubmit); // Do put now parameter location (if no open session)
+ }
+
+void Frm_StartFormUnique (Act_Action_t NextAction)
+ {
+ Frm_StartFormUniqueAnchor (NextAction,NULL);
+ }
+
+void Frm_StartFormUniqueAnchor (Act_Action_t NextAction,const char *Anchor)
+ {
+ Gbl.Form.Num++; // Initialized to -1. The first time it is incremented, it will be equal to 0
+ snprintf (Gbl.Form.UniqueId,sizeof (Gbl.Form.UniqueId),
+ "form_%s_%d",
+ Gbl.UniqueNameEncrypted,Gbl.Form.Num);
+ Frm_StartFormInternal (NextAction,true,Gbl.Form.UniqueId,Anchor,NULL); // Do put now parameter location (if no open session)
+ }
+
+void Frm_StartFormId (Act_Action_t NextAction,const char *Id)
+ {
+ Gbl.Form.Num++; // Initialized to -1. The first time it is incremented, it will be equal to 0
+ Frm_StartFormInternal (NextAction,true,Id,NULL,NULL); // Do put now parameter location (if no open session)
+ }
+
+// Id can not be NULL
+static void Frm_StartFormInternal (Act_Action_t NextAction,bool PutParameterLocationIfNoSesion,
+ const char *Id,const char *Anchor,const char *OnSubmit)
+ {
+ extern const char *Txt_STR_LANG_ID[1 + Txt_NUM_LANGUAGES];
+ char ParamsStr[Frm_MAX_BYTES_PARAMS_STR + 1];
+
+ if (!Gbl.Form.Inside)
+ {
+ /* Start form */
+ fprintf (Gbl.F.Out,"
");
+ Gbl.Form.Inside = false;
+ }
+ }
+
+/*****************************************************************************/
+/******************* Anchor directive used to send a form ********************/
+/*****************************************************************************/
+// Requires an extern
+
+void Frm_LinkFormSubmit (const char *Title,const char *LinkStyle,
+ const char *OnSubmit)
+ {
+ Frm_LinkFormSubmitId (Title,LinkStyle,Gbl.Form.Id,OnSubmit);
+ }
+
+void Frm_LinkFormSubmitUnique (const char *Title,const char *LinkStyle)
+ {
+ Frm_LinkFormSubmitId (Title,LinkStyle,Gbl.Form.UniqueId,NULL);
+ }
+
+// Title can be NULL
+// LinkStyle can be NULL
+// Id can not be NULL
+// OnSubmit can be NULL
+
+void Frm_LinkFormSubmitId (const char *Title,const char *LinkStyle,
+ const char *Id,const char *OnSubmit)
+ {
+ fprintf (Gbl.F.Out,"",
+ Id);
+ }
+
+void Frm_LinkFormSubmitAnimated (const char *Title,const char *LinkStyle,
+ const char *OnSubmit)
+ {
+ fprintf (Gbl.F.Out,"",
+ Gbl.Form.Num,
+ Gbl.Form.Id);
+ }
+
+/*****************************************************************************/
+/***************************** Get unique Id *********************************/
+/*****************************************************************************/
+
+void Frm_SetUniqueId (char UniqueId[Frm_MAX_BYTES_ID + 1])
+ {
+ static unsigned CountForThisExecution = 0;
+
+ /***** Create Id. The id must be unique,
+ the page content may be updated via AJAX.
+ So, Id uses:
+ - a name for this execution (Gbl.UniqueNameEncrypted)
+ - a number for each element in this execution (CountForThisExecution) *****/
+ snprintf (UniqueId,Frm_MAX_BYTES_ID + 1,
+ "id_%s_%u",
+ Gbl.UniqueNameEncrypted,
+ ++CountForThisExecution);
+ }
diff --git a/swad_form.h b/swad_form.h
new file mode 100644
index 00000000..96424ef4
--- /dev/null
+++ b/swad_form.h
@@ -0,0 +1,75 @@
+// swad_form.h: forms to go to actions
+
+#ifndef _SWAD_FRM
+#define _SWAD_FRM
+/*
+ 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 "swad_action.h"
+#include "swad_constant.h"
+#include "swad_cryptography.h"
+
+/*****************************************************************************/
+/****************************** Public constants *****************************/
+/*****************************************************************************/
+
+#define Frm_MAX_BYTES_ID (32 + Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64 + 10)
+
+#define Frm_MAX_BYTES_PARAM_ACTION 256
+#define Frm_MAX_BYTES_PARAM_SESSION (256 + Cns_BYTES_SESSION_ID)
+#define Frm_MAX_BYTES_PARAM_LOCATION 256
+#define Frm_MAX_BYTES_PARAMS_STR (Frm_MAX_BYTES_PARAM_ACTION + Frm_MAX_BYTES_PARAM_SESSION + Frm_MAX_BYTES_PARAM_LOCATION)
+
+/*****************************************************************************/
+/******************************** Public types *******************************/
+/*****************************************************************************/
+
+/*****************************************************************************/
+/***************************** Public prototypes *****************************/
+/*****************************************************************************/
+
+void Frm_StartFormGoTo (Act_Action_t NextAction);
+void Frm_StartForm (Act_Action_t NextAction);
+void Frm_StartFormOnSubmit (Act_Action_t NextAction,const char *OnSubmit);
+void Frm_StartFormAnchorOnSubmit (Act_Action_t NextAction,const char *Anchor,const char *OnSubmit);
+void Frm_StartFormUnique (Act_Action_t NextAction);
+void Frm_StartFormAnchor (Act_Action_t NextAction,const char *Anchor);
+void Frm_StartFormUniqueAnchor (Act_Action_t NextAction,const char *Anchor);
+void Frm_StartFormId (Act_Action_t NextAction,const char *Id);
+void Frm_SetParamsForm (char ParamsStr[Frm_MAX_BYTES_PARAMS_STR],Act_Action_t NextAction,
+ bool PutParameterLocationIfNoSesion);
+void Frm_EndForm (void);
+void Frm_LinkFormSubmit (const char *Title,const char *LinkStyle,
+ const char *OnSubmit);
+void Frm_LinkFormSubmitUnique (const char *Title,const char *LinkStyle);
+void Frm_LinkFormSubmitId (const char *Title,const char *LinkStyle,
+ const char *Id,const char *OnSubmit);
+void Frm_LinkFormSubmitAnimated (const char *Title,const char *LinkStyle,
+ const char *OnSubmit);
+
+void Frm_SetUniqueId (char UniqueId[Frm_MAX_BYTES_ID + 1]);
+
+#endif
+