// swad_layout.c: page layout /* 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 exit, system, malloc, calloc, free, etc #include // For string functions #include "swad_action.h" #include "swad_calendar.h" #include "swad_changelog.h" #include "swad_config.h" #include "swad_connected.h" #include "swad_database.h" #include "swad_exam.h" #include "swad_follow.h" #include "swad_global.h" #include "swad_help.h" #include "swad_hierarchy.h" #include "swad_language.h" #include "swad_logo.h" #include "swad_MFU.h" #include "swad_notice.h" #include "swad_notification.h" #include "swad_parameter.h" #include "swad_preference.h" #include "swad_social.h" #include "swad_tab.h" #include "swad_theme.h" #include "swad_web_service.h" /*****************************************************************************/ /************** External global variables from others modules ****************/ /*****************************************************************************/ extern struct Globals Gbl; /*****************************************************************************/ /****************************** Public constants *****************************/ /*****************************************************************************/ /*****************************************************************************/ /***************************** Private constants *****************************/ /*****************************************************************************/ /*****************************************************************************/ /******************************* Private types *******************************/ /*****************************************************************************/ /*****************************************************************************/ /***************************** Private prototypes ****************************/ /*****************************************************************************/ static void Lay_WriteEndOfPage (void); static void Lay_WritePageTitle (void); static void Lay_WriteRedirToMyLangOnLogIn (void); static void Lay_WriteRedirToMyLangOnViewUsrAgd (void); static void Lay_WriteScripts (void); static void Lay_WriteScriptMathJax (void); static void Lay_WriteScriptInit (void); static void Lay_WriteScriptParamsAJAX (void); static void Lay_WriteScriptCustomDropzone (void); static void Lay_WritePageTopHeading (void); static void Lay_WriteBreadcrumb (void); static void Lay_WriteTitleAction (void); static void Lay_ShowLeftColumn (void); static void Lay_ShowRightColumn (void); static void Lay_StartRoundFrameInternal (const char *Width,const char *Title, void (*FunctionToDrawContextualIcons) (void), const char *HelpLink, const char *ClassFrame); static void Lay_WriteAboutZone (void); static void Lay_WriteFootFromHTMLFile (void); static void Lay_HelpTextEditor (const char *Text,const char *InlineMath,const char *Equation); /*****************************************************************************/ /*********************** Write the start of the page *************************/ /*****************************************************************************/ void Lay_WriteStartOfPage (void) { extern struct Act_Actions Act_Actions[Act_NUM_ACTIONS]; extern const char *Txt_STR_LANG_ID[1 + Txt_NUM_LANGUAGES]; extern const unsigned Txt_Current_CGI_SWAD_Language; extern const char *The_TabOnBgColors[The_NUM_THEMES]; extern const char *Txt_NEW_YEAR_GREETING; const char *LayoutMainZone[Mnu_NUM_MENUS] = { "main_horizontal", // Mnu_MENU_HORIZONTAL "main_vertical", // Mnu_MENU_VERTICAL }; /***** If, when this function is called, the head is being written or the head is already written ==> don't do anything *****/ if (Gbl.Layout.WritingHTMLStart || Gbl.Layout.HTMLStartWritten) return; /***** Compute connected users to be displayed in right columns *****/ Con_ComputeConnectedUsrsBelongingToCurrentCrs (); /***** Send head width the file type for the HTTP protocol *****/ if (Gbl.Action.UsesAJAX) // Don't generate a full HTML page, only the content of a DIV or similar { fprintf (Gbl.F.Out,"Content-Type: text/html; charset=windows-1252\r\n\r\n"); Gbl.Layout.WritingHTMLStart = false; Gbl.Layout.HTMLStartWritten = Gbl.Layout.DivsEndWritten = true; return; } /***** If serving a web service ==> don't do anything *****/ if (Gbl.WebService.IsWebService) { Gbl.Layout.WritingHTMLStart = false; Gbl.Layout.HTMLStartWritten = Gbl.Layout.DivsEndWritten = true; return; } Gbl.Layout.WritingHTMLStart = true; /***** Write header to standard output to avoid timeout *****/ // Two \r\n are necessary fprintf (stdout,"Content-type: text/html; charset=windows-1252\r\n\r\n" "\n"); /***** Write start of HTML code *****/ // WARNING: It is necessary to comment the line 'AddDefaultCharset UTF8' // in httpd.conf to enable meta tag fprintf (Gbl.F.Out,"\n" "\n" "\n" "\n" "\n" "\n" "\n", Txt_STR_LANG_ID[Gbl.Prefs.Language], Cfg_PLATFORM_SHORT_NAME); /* Viewport (used for responsive design) */ fprintf (Gbl.F.Out,"\n"); /* Title */ Lay_WritePageTitle (); /* Canonical URL */ fprintf (Gbl.F.Out,"\n", Cfg_URL_SWAD_CGI); /* Favicon */ fprintf (Gbl.F.Out,"\n" "\n", Gbl.Prefs.IconsURL, Gbl.Prefs.IconsURL); /* Style sheet for SWAD */ fprintf (Gbl.F.Out,"\n", Cfg_URL_SWAD_PUBLIC,CSS_FILE); /* Style sheet for Dropzone.js (http://www.dropzonejs.com/) */ // The public directory dropzone must hold: // dropzone.js // css/dropzone.css // images/spritemap@2x.png // images/spritemap.png switch (Gbl.Action.Act) { case ActFrmCreDocIns: // Brw_ADMI_DOCUM_INS case ActFrmCreShaIns: // Brw_ADMI_SHARE_INS case ActFrmCreDocCtr: // Brw_ADMI_DOCUM_CTR case ActFrmCreShaCtr: // Brw_ADMI_SHARE_CTR case ActFrmCreDocDeg: // Brw_ADMI_DOCUM_DEG case ActFrmCreShaDeg: // Brw_ADMI_SHARE_DEG case ActFrmCreDocCrs: // Brw_ADMI_DOCUM_CRS case ActFrmCreDocGrp: // Brw_ADMI_DOCUM_GRP case ActFrmCreTchCrs: // Brw_ADMI_TEACH_CRS case ActFrmCreTchGrp: // Brw_ADMI_TEACH_GRP case ActFrmCreShaCrs: // Brw_ADMI_SHARE_CRS case ActFrmCreShaGrp: // Brw_ADMI_SHARE_GRP case ActFrmCreAsgUsr: // Brw_ADMI_ASSIG_USR case ActFrmCreAsgCrs: // Brw_ADMI_ASSIG_CRS case ActFrmCreWrkUsr: // Brw_ADMI_WORKS_USR case ActFrmCreWrkCrs: // Brw_ADMI_WORKS_CRS case ActFrmCreMrkCrs: // Brw_ADMI_MARKS_CRS case ActFrmCreMrkGrp: // Brw_ADMI_MARKS_GRP case ActFrmCreBrf: // Brw_ADMI_BRIEF_USR fprintf (Gbl.F.Out,"\n", Cfg_URL_SWAD_PUBLIC); break; default: break; } /* Redirect to correct language */ if (Gbl.Usrs.Me.Logged && // I am logged Gbl.Usrs.Me.UsrDat.Prefs.Language != Txt_Current_CGI_SWAD_Language) // My language != current language { if (Gbl.Action.Act == ActLogIn || // Regular log in Gbl.Action.Act == ActLogInNew) // Log in when checking account Lay_WriteRedirToMyLangOnLogIn (); else if (Gbl.Action.Act == ActLogInUsrAgd) // Log in to view another user's public agenda Lay_WriteRedirToMyLangOnViewUsrAgd (); } /* Write initial scripts depending on the action */ Lay_WriteScripts (); fprintf (Gbl.F.Out,"\n"); /***** HTML body *****/ if (Act_Actions[Gbl.Action.Act].BrowserWindow == Act_THIS_WINDOW) fprintf (Gbl.F.Out,"\n" "
" "\"\"" "
" "
" "
", Gbl.Prefs.IconsURL); else { fprintf (Gbl.F.Out,"\n"); Gbl.Layout.WritingHTMLStart = false; Gbl.Layout.HTMLStartWritten = Gbl.Layout.DivsEndWritten = true; return; } /***** Start of box that contains the whole page except the foot *****/ fprintf (Gbl.F.Out,"
"); /***** Header of layout *****/ Lay_WritePageTopHeading (); /***** 3rd. row (tabs) *****/ Tab_DrawTabs (); /***** 4th row: main zone *****/ fprintf (Gbl.F.Out,"
"); /* Left column */ if (Gbl.Prefs.SideCols & Lay_SHOW_LEFT_COLUMN) // Left column visible { fprintf (Gbl.F.Out,""); } /* Right column */ // Right column is written before central column // but it must be drawn at right using "position:absolute; right:0". // The reason to write right column before central column // is that central column may hold a lot of content drawn slowly. if (Gbl.Prefs.SideCols & Lay_SHOW_RIGHT_COLUMN) // Right column visible { fprintf (Gbl.F.Out,""); } /* Central (main) column */ switch (Gbl.Prefs.SideCols) { case 0: fprintf (Gbl.F.Out,"
"); break; case Lay_SHOW_LEFT_COLUMN: fprintf (Gbl.F.Out,"
"); break; case Lay_SHOW_RIGHT_COLUMN: fprintf (Gbl.F.Out,"
"); break; case (Lay_SHOW_LEFT_COLUMN | Lay_SHOW_RIGHT_COLUMN): fprintf (Gbl.F.Out,"
"); break; } fprintf (Gbl.F.Out,"
", The_TabOnBgColors[Gbl.Prefs.Theme]); /* Layout with horizontal or vertical menu */ fprintf (Gbl.F.Out,"
",LayoutMainZone[Gbl.Prefs.Menu]); /* Menu */ Mnu_WriteMenuThisTab (); /* Start of canvas: main zone for actions output */ fprintf (Gbl.F.Out,"
"); /* If it is mandatory to read any information about course */ if (Gbl.CurrentCrs.Info.ShowMsgMustBeRead) Inf_WriteMsgYouMustReadInfo (); /* Write title of the current action */ if (Gbl.Prefs.Menu == Mnu_MENU_VERTICAL && Act_Actions[Act_Actions[Gbl.Action.Act].SuperAction].IndexInMenu >= 0) Lay_WriteTitleAction (); Gbl.Layout.WritingHTMLStart = false; Gbl.Layout.HTMLStartWritten = true; /* Write new year greeting */ if (Gbl.Action.Act == ActLogIn || Gbl.Action.Act == ActLogInNew || Gbl.Action.Act == ActLogInLan) if (Gbl.Now.Date.Month == 1 && Gbl.Now.Date.Day == 1) { fprintf (Gbl.F.Out,"
"); fprintf (Gbl.F.Out,Txt_NEW_YEAR_GREETING,Gbl.Now.Date.Year); fprintf (Gbl.F.Out,"
"); } /* Write message indicating number of clicks allowed before sending my photo */ Usr_InformAboutNumClicksBeforePhoto (); } /*****************************************************************************/ /************************ Write the end of the page **************************/ /*****************************************************************************/ static void Lay_WriteEndOfPage (void) { extern struct Act_Actions Act_Actions[Act_NUM_ACTIONS]; if (!Gbl.Layout.DivsEndWritten) { /***** End of central part of main zone *****/ fprintf (Gbl.F.Out,"
" // Canvas (main zone to output content of the current action) "
" // Layout with horizontal or vertical menu "
"); // main_zone_central_container /***** Write page footer *****/ if (Act_Actions[Gbl.Action.Act].BrowserWindow == Act_THIS_WINDOW) Lay_WriteFootFromHTMLFile (); /***** End of main zone and page *****/ fprintf (Gbl.F.Out,"
" // main_zone_central "
" // main_zone "
\n"); // whole_page_* (box that contains the whole page except the foot) Gbl.Layout.DivsEndWritten = true; } } /*****************************************************************************/ /************************* Write the title of the page ***********************/ /*****************************************************************************/ static void Lay_WritePageTitle (void) { extern const char *Txt_TAGLINE; fprintf (Gbl.F.Out,""); if (Gbl.Params.GetMethod && Gbl.CurrentDeg.Deg.DegCod > 0) { fprintf (Gbl.F.Out,"%s > %s", Cfg_PLATFORM_SHORT_NAME, Gbl.CurrentDeg.Deg.ShrtName); if (Gbl.CurrentCrs.Crs.CrsCod > 0) fprintf (Gbl.F.Out," > %s", Gbl.CurrentCrs.Crs.ShrtName); } else fprintf (Gbl.F.Out,"%s: %s", Cfg_PLATFORM_SHORT_NAME,Txt_TAGLINE); fprintf (Gbl.F.Out,"\n"); } /*****************************************************************************/ /************* Write script and meta to redirect to my language **************/ /*****************************************************************************/ static void Lay_WriteRedirToMyLangOnLogIn (void) { extern struct Act_Actions Act_Actions[Act_NUM_ACTIONS]; extern const char *Txt_STR_LANG_ID[1 + Txt_NUM_LANGUAGES]; fprintf (Gbl.F.Out,"", Cfg_URL_SWAD_CGI, Txt_STR_LANG_ID[Gbl.Usrs.Me.UsrDat.Prefs.Language], Act_Actions[ActLogInLan].ActCod, Gbl.Session.Id); } static void Lay_WriteRedirToMyLangOnViewUsrAgd (void) { extern struct Act_Actions Act_Actions[Act_NUM_ACTIONS]; extern const char *Txt_STR_LANG_ID[1 + Txt_NUM_LANGUAGES]; fprintf (Gbl.F.Out,"", Cfg_URL_SWAD_CGI, Txt_STR_LANG_ID[Gbl.Usrs.Me.UsrDat.Prefs.Language], Act_Actions[ActLogInUsrAgdLan].ActCod, Gbl.Session.Id, Gbl.Usrs.Other.UsrDat.Nickname); } /*****************************************************************************/ /************ Write some scripts depending on the current action *************/ /*****************************************************************************/ static void Lay_WriteScripts (void) { extern struct Act_Actions Act_Actions[Act_NUM_ACTIONS]; extern const char *Txt_DAYS_CAPS[7]; extern const char *Txt_DAYS_SMALL[7]; extern const char *Txt_Exam_of_X; unsigned DayOfWeek; /* 0, 1, 2, 3, 4, 5, 6 */ unsigned NumHld; unsigned NumExamAnnouncement; // Number of exam announcement /***** General scripts for swad *****/ fprintf (Gbl.F.Out,"\n", Cfg_URL_SWAD_PUBLIC,JS_FILE); /***** Script for MathJax *****/ Lay_WriteScriptMathJax (); /***** Scripts used only in main window *****/ if (Act_Actions[Gbl.Action.Act].BrowserWindow == Act_THIS_WINDOW) { Lay_WriteScriptInit (); Lay_WriteScriptParamsAJAX (); } /***** Prepare script to draw months *****/ if ((Gbl.Prefs.SideCols & Lay_SHOW_LEFT_COLUMN) || // Left column visible Gbl.Action.Act == ActSeeCalIns || Gbl.Action.Act == ActPrnCalIns || Gbl.Action.Act == ActSeeCalCtr || Gbl.Action.Act == ActPrnCalCtr || Gbl.Action.Act == ActSeeCalDeg || Gbl.Action.Act == ActPrnCalDeg || Gbl.Action.Act == ActSeeCalCrs || Gbl.Action.Act == ActPrnCalCrs) { /***** Get list of holidays *****/ if (!Gbl.Hlds.LstIsRead) { Gbl.Hlds.SelectedOrder = Hld_ORDER_BY_START_DATE; Hld_GetListHolidays (); } /***** Create list of calls for examination *****/ Exa_CreateListDatesOfExamAnnouncements (); /***** Write script to initialize variables used to draw months *****/ fprintf (Gbl.F.Out,"\n"); /***** Free list of dates of exam announcements *****/ Exa_FreeListExamAnnouncements (); } /***** Scripts depending on action *****/ switch (Gbl.Action.Act) { /***** Script to print world map *****/ case ActSeeCty: Cty_WriteScriptGoogleGeochart (); break; /***** Script for uploading files using Dropzone.js (http://www.dropzonejs.com/) *****/ // The public directory dropzone must hold: // dropzone.js // css/dropzone.css // images/spritemap@2x.png // images/spritemap.png case ActFrmCreDocIns: // Brw_ADMI_DOCUM_INS case ActFrmCreShaIns: // Brw_ADMI_SHARE_INS case ActFrmCreDocCtr: // Brw_ADMI_DOCUM_CTR case ActFrmCreShaCtr: // Brw_ADMI_SHARE_CTR case ActFrmCreDocDeg: // Brw_ADMI_DOCUM_DEG case ActFrmCreShaDeg: // Brw_ADMI_SHARE_DEG case ActFrmCreDocCrs: // Brw_ADMI_DOCUM_CRS case ActFrmCreDocGrp: // Brw_ADMI_DOCUM_GRP case ActFrmCreTchCrs: // Brw_ADMI_TEACH_CRS case ActFrmCreTchGrp: // Brw_ADMI_TEACH_GRP case ActFrmCreShaCrs: // Brw_ADMI_SHARE_CRS case ActFrmCreShaGrp: // Brw_ADMI_SHARE_GRP case ActFrmCreAsgUsr: // Brw_ADMI_ASSIG_USR case ActFrmCreAsgCrs: // Brw_ADMI_ASSIG_CRS case ActFrmCreWrkUsr: // Brw_ADMI_WORKS_USR case ActFrmCreWrkCrs: // Brw_ADMI_WORKS_CRS case ActFrmCreMrkCrs: // Brw_ADMI_MARKS_CRS case ActFrmCreMrkGrp: // Brw_ADMI_MARKS_GRP case ActFrmCreBrf: // Brw_ADMI_BRIEF_USR // Use charset="windows-1252" to force error messages in windows-1252 (default is UTF-8) fprintf (Gbl.F.Out,"\n", Cfg_URL_SWAD_PUBLIC); Lay_WriteScriptCustomDropzone (); break; case ActReqAccGbl: case ActSeeAccGbl: case ActReqAccCrs: case ActSeeAccCrs: case ActSeeAllStaCrs: fprintf (Gbl.F.Out,"\n", Cfg_URL_SWAD_PUBLIC); break; default: break; } /***** Script for Google Analytics *****/ fprintf (Gbl.F.Out,"%s",Cfg_GOOGLE_ANALYTICS); } // Change page title //function changeTitle(title) { // document.title = title; //} /*****************************************************************************/ /************ Write some scripts depending on the current action *************/ /*****************************************************************************/ static void Lay_WriteScriptMathJax (void) { // MathJax configuration /* fprintf (Gbl.F.Out,""); */ #ifdef Cfg_MATHJAX_LOCAL // Use the local copy of MathJax fprintf (Gbl.F.Out,"\n", Cfg_URL_SWAD_PUBLIC); #else // Use the MathJax Content Delivery Network (CDN) fprintf (Gbl.F.Out,"\n"); #endif } /*****************************************************************************/ /******* Write script with init function executed after loading page *********/ /*****************************************************************************/ static void Lay_WriteScriptInit (void) { extern const char *Txt_STR_LANG_ID[1 + Txt_NUM_LANGUAGES]; fprintf (Gbl.F.Out,"\n"); } /*****************************************************************************/ /************** Write script to set parameters needed by AJAX ****************/ /*****************************************************************************/ static void Lay_WriteScriptParamsAJAX (void) { extern struct Act_Actions Act_Actions[Act_NUM_ACTIONS]; /***** Start script *****/ fprintf (Gbl.F.Out,"\n", Gbl.Session.Id, Gbl.CurrentCrs.Crs.CrsCod); } /*****************************************************************************/ /******* Write script to customize upload of files using Dropzone.js *********/ /*****************************************************************************/ // More info: http://www.dropzonejs.com/ static void Lay_WriteScriptCustomDropzone (void) { // "myAwesomeDropzone" is the camelized version of the HTML element's ID // Add a line "forceFallback: true,\n" to test classic upload fprintf (Gbl.F.Out,"\n", (unsigned long) (Fil_MAX_FILE_SIZE / (1024ULL * 1024ULL) - 1)); } /*****************************************************************************/ /************************ Write top heading of the page **********************/ /*****************************************************************************/ static void Lay_WritePageTopHeading (void) { extern const char *The_ClassHead[The_NUM_THEMES]; extern const char *The_ClassTagline[The_NUM_THEMES]; extern const char *Txt_System; extern const char *Txt_TAGLINE; extern const char *Txt_TAGLINE_BR; const char *ClassHeadRow1[The_NUM_THEMES] = { "HEAD_ROW_1_WHITE", // The_THEME_WHITE "HEAD_ROW_1_GREY", // The_THEME_GREY "HEAD_ROW_1_BLUE", // The_THEME_BLUE "HEAD_ROW_1_YELLOW", // The_THEME_YELLOW }; const char *ClassHeadRow2[The_NUM_THEMES] = { "HEAD_ROW_2_WHITE", // The_THEME_WHITE "HEAD_ROW_2_GREY", // The_THEME_GREY "HEAD_ROW_2_BLUE", // The_THEME_BLUE "HEAD_ROW_2_YELLOW", // The_THEME_YELLOW }; /***** Start header *****/ fprintf (Gbl.F.Out,"
"); /***** 1st. row *****/ /* Start of 1st. row */ fprintf (Gbl.F.Out,"
", ClassHeadRow1[Gbl.Prefs.Theme]); /* 1st. row, 1st. column: logo, tagline and search */ fprintf (Gbl.F.Out,"
"); /* Start form to go to home page */ Act_FormGoToStart (ActMnu); Par_PutHiddenParamUnsigned ("NxtTab",(unsigned) TabSys); fprintf (Gbl.F.Out,"
"); Act_LinkFormSubmit (Txt_System,NULL,NULL); fprintf (Gbl.F.Out,"\"%s\"" "", // head_row_1_logo_small Gbl.Prefs.IconsURL,Cfg_PLATFORM_LOGO_SMALL_FILENAME, Cfg_PLATFORM_SHORT_NAME,Cfg_PLATFORM_FULL_NAME, Cfg_PLATFORM_LOGO_SMALL_WIDTH,Cfg_PLATFORM_LOGO_SMALL_HEIGHT); fprintf (Gbl.F.Out,"
" "
"); Act_LinkFormSubmit (Txt_System,NULL,NULL); fprintf (Gbl.F.Out,"\"%s\"" "", // head_row_1_logo_big Gbl.Prefs.IconsURL,Cfg_PLATFORM_LOGO_BIG_FILENAME, Cfg_PLATFORM_SHORT_NAME,Cfg_PLATFORM_FULL_NAME, Cfg_PLATFORM_LOGO_BIG_WIDTH,Cfg_PLATFORM_LOGO_BIG_HEIGHT); fprintf (Gbl.F.Out,"
" "
"); Act_LinkFormSubmit (Txt_TAGLINE,The_ClassTagline[Gbl.Prefs.Theme],NULL); fprintf (Gbl.F.Out,"%s" "" "
", // head_row_1_tagline Txt_TAGLINE_BR); /* End form to go to home page */ Act_FormEnd (); Sch_PutFormToSearchInPageTopHeading (); fprintf (Gbl.F.Out,"
"); // head_row_1_left /* 1st. row, 3rd. column: logged user or language selection, and link to open/close session */ fprintf (Gbl.F.Out,"
", The_ClassHead[Gbl.Prefs.Theme]); if (Gbl.Usrs.Me.Logged) Usr_WriteLoggedUsrHead (); else Lan_PutSelectorToSelectLanguage (); fprintf (Gbl.F.Out,"
"); if (Gbl.Usrs.Me.Logged) Usr_PutFormLogOut (); else Usr_PutFormLogIn (); fprintf (Gbl.F.Out,"
" // login_box "
"); // head_row_1_right /* End of 1st. row */ fprintf (Gbl.F.Out,"
"); // head_row_1 /***** 2nd. row *****/ /* Start of second row */ fprintf (Gbl.F.Out,"
", ClassHeadRow2[Gbl.Prefs.Theme]); /* 2nd. row, 1st. column Clock with hour:minute (server hour is shown) */ fprintf (Gbl.F.Out,"
"); Dat_ShowClientLocalTime (); fprintf (Gbl.F.Out,"
"); // End of first column /* 2nd. row, 2nd. column: degree and course */ fprintf (Gbl.F.Out,"
"); Lay_WriteBreadcrumb (); Hie_WriteBigNameCtyInsCtrDegCrs (); fprintf (Gbl.F.Out,"
"); /* 2nd. row, 3rd. column */ fprintf (Gbl.F.Out,"
"); // Used for AJAX based refresh if (Gbl.Usrs.Me.Logged) Ntf_WriteNumberOfNewNtfs (); fprintf (Gbl.F.Out,"
"); // Used for AJAX based refresh /* End of 2nd. row */ fprintf (Gbl.F.Out,"
"); /***** End header *****/ fprintf (Gbl.F.Out,"
"); } /*****************************************************************************/ /*********** Write breadcrumb with the path to the current location **********/ /*****************************************************************************/ static void Lay_WriteBreadcrumb (void) { fprintf (Gbl.F.Out,""); } /*****************************************************************************/ /*********** Write icon and title associated to the current action ***********/ /*****************************************************************************/ static void Lay_WriteTitleAction (void) { extern struct Act_Actions Act_Actions[Act_NUM_ACTIONS]; extern const char *The_ClassTitleAction[The_NUM_THEMES]; extern const char *The_ClassSubtitleAction[The_NUM_THEMES]; extern const char *Txt_TABS_TXT[Tab_NUM_TABS]; Act_Action_t SuperAction = Act_Actions[Gbl.Action.Act].SuperAction; /***** Container start *****/ fprintf (Gbl.F.Out,"
", Gbl.Prefs.PathIconSet,Cfg_ICON_ACTION, Act_Actions[SuperAction].Icon); /***** Title *****/ fprintf (Gbl.F.Out,"
%s > %s
", The_ClassTitleAction[Gbl.Prefs.Theme], Txt_TABS_TXT[Act_Actions[SuperAction].Tab], Act_GetTitleAction (Gbl.Action.Act)); /***** Subtitle *****/ fprintf (Gbl.F.Out,"
%s
", The_ClassSubtitleAction[Gbl.Prefs.Theme], Act_GetSubtitleAction (Gbl.Action.Act)); /***** Container end *****/ fprintf (Gbl.F.Out,"
"); } /*****************************************************************************/ /***************************** Show left column ******************************/ /*****************************************************************************/ static void Lay_ShowLeftColumn (void) { struct MFU_ListMFUActions ListMFUActions; fprintf (Gbl.F.Out,"
"); fprintf (Gbl.F.Out,"
"); if (Gbl.Usrs.Me.Logged) { /***** Most frequently used actions *****/ MFU_AllocateMFUActions (&ListMFUActions,6); MFU_GetMFUActions (&ListMFUActions,6); MFU_WriteSmallMFUActions (&ListMFUActions); MFU_FreeMFUActions (&ListMFUActions); } else /***** Institutional links *****/ Lnk_WriteMenuWithInstitutionalLinks (); fprintf (Gbl.F.Out,"
"); /***** Month *****/ fprintf (Gbl.F.Out,"
"); Cal_DrawCurrentMonth (); fprintf (Gbl.F.Out,"
"); /***** Notices (yellow notes) *****/ if (Gbl.CurrentCrs.Crs.CrsCod > 0) { fprintf (Gbl.F.Out,"
"); Not_ShowNotices (Not_LIST_BRIEF_NOTICES); fprintf (Gbl.F.Out,"
"); } fprintf (Gbl.F.Out,"
"); } /*****************************************************************************/ /**************************** Show right column ******************************/ /*****************************************************************************/ static void Lay_ShowRightColumn (void) { extern const char *Txt_If_you_have_an_Android_device_try_SWADroid; /***** Banners *****/ Ban_WriteMenuWithBanners (); /***** Number of connected users in the whole platform *****/ if (Gbl.Usrs.Me.LoggedRole == Rol_SYS_ADM) { fprintf (Gbl.F.Out,"
"); Con_ShowGlobalConnectedUsrs (); fprintf (Gbl.F.Out,"
"); // Used for AJAX based refresh } /***** Number of connected users in the current course *****/ if (Gbl.CurrentCrs.Crs.CrsCod > 0) // There is a course selected { fprintf (Gbl.F.Out,"
"); Gbl.Scope.Current = Sco_SCOPE_CRS; Con_ShowConnectedUsrsBelongingToCurrentCrs (); fprintf (Gbl.F.Out,"
"); // Used for AJAX based refresh } else if (Gbl.Usrs.Me.Logged) // I am logged { /***** Suggest one user to follow *****/ fprintf (Gbl.F.Out,"
"); Fol_SuggestUsrsToFollowMainZoneOnRightColumn (); fprintf (Gbl.F.Out,"
"); } if (!Gbl.Usrs.Me.Logged) /***** SWADroid advertisement *****/ fprintf (Gbl.F.Out,"
" "" "\"SWADroid\"" "" "
", Txt_If_you_have_an_Android_device_try_SWADroid, Gbl.Prefs.IconsURL); } /*****************************************************************************/ /***** Show contextual icons to remove, edit, view, hide, unhide, print ******/ /*****************************************************************************/ void Lay_PutContextualIconToRemove (Act_Action_t NextAction,void (*FuncParams) ()) { extern const char *Txt_Remove; Lay_PutContextualLink (NextAction,NULL,FuncParams, "remove-on64x64.png", Txt_Remove,NULL, NULL); } void Lay_PutContextualIconToEdit (Act_Action_t NextAction,void (*FuncParams) ()) { extern const char *Txt_Edit; Lay_PutContextualLink (NextAction,NULL,FuncParams, "edit64x64.png", Txt_Edit,NULL, NULL); } void Lay_PutContextualIconToView (Act_Action_t NextAction,void (*FuncParams) ()) { extern const char *Txt_View; Lay_PutContextualLink (NextAction,NULL,FuncParams, "eye-on64x64.png", Txt_View,NULL, NULL); } void Lay_PutContextualIconToHide (Act_Action_t NextAction,void (*FuncParams) ()) { extern const char *Txt_Hide; Lay_PutContextualLink (NextAction,NULL,FuncParams, "eye-on64x64.png", Txt_Hide,NULL, NULL); } void Lay_PutContextualIconToUnhide (Act_Action_t NextAction,void (*FuncParams) ()) { extern const char *Txt_Show; Lay_PutContextualLink (NextAction,NULL,FuncParams, "eye-slash-on64x64.png", Txt_Show,NULL, NULL); } void Lay_PutContextualIconToPrint (Act_Action_t NextAction,void (*FuncParams) ()) { extern const char *Txt_Print; Lay_PutContextualLink (NextAction,NULL,FuncParams, "print64x64.png", Txt_Print,NULL, NULL); } /*****************************************************************************/ /**************** Show an icon with a link in contextual menu ****************/ /*****************************************************************************/ void Lay_PutContextualLink (Act_Action_t NextAction,const char *Anchor, void (*FuncParams) (), const char *Icon, const char *Title,const char *Text, const char *OnSubmit) { extern const char *The_ClassFormBold[The_NUM_THEMES]; /***** Separator *****/ if (Text) fprintf (Gbl.F.Out," "); // This space is necessary to enable // jumping to the next line on narrow screens /***** Start form *****/ Act_FormStartAnchor (NextAction,Anchor); if (FuncParams) FuncParams (); /***** Put icon with link *****/ Lay_PutIconLink (Icon,Title,Text, Text ? The_ClassFormBold[Gbl.Prefs.Theme] : NULL, OnSubmit); /***** End form *****/ Act_FormEnd (); /***** Separator *****/ if (Text) fprintf (Gbl.F.Out," "); // This space is necessary to enable // jumping to the next line on narrow screens } /*****************************************************************************/ /******************** Show a checkbox in contextual menu *********************/ /*****************************************************************************/ void Lay_PutContextualCheckbox (Act_Action_t NextAction, void (*FuncParams) (), const char *CheckboxName,bool Checked, const char *Title,const char *Text) { extern const char *The_ClassFormBold[The_NUM_THEMES]; /***** Separator *****/ if (Text) fprintf (Gbl.F.Out," "); // This space is necessary to enable // jumping to the next line on narrow screens /***** Start form *****/ Act_FormStart (NextAction); if (FuncParams) FuncParams (); /***** Start container and label *****/ fprintf (Gbl.F.Out,"
" "" "
"); /***** End form *****/ Act_FormEnd (); /***** Separator *****/ if (Text) fprintf (Gbl.F.Out," "); // This space is necessary to enable // jumping to the next line on narrow screens } /*****************************************************************************/ /****************** Show an icon with a link (without text) ******************/ /*****************************************************************************/ void Lay_PutIconLink (const char *Icon,const char *Title,const char *Text, const char *LinkStyle,const char *OnSubmit) { Act_LinkFormSubmit (Title,LinkStyle,OnSubmit); Lay_PutIconWithText (Icon,Title,Text); fprintf (Gbl.F.Out,""); } /*****************************************************************************/ /**************** Put a icon with a text to submit a form ********************/ /*****************************************************************************/ void Lay_PutIconWithText (const char *Icon,const char *Alt,const char *Text) { /***** Print icon and optional text *****/ fprintf (Gbl.F.Out,"
" "\"%s\"", Gbl.Prefs.IconsURL,Icon, Alt,Text ? Text : Alt); if (Text) if (Text[0]) fprintf (Gbl.F.Out," %s",Text); fprintf (Gbl.F.Out,"
"); } /*****************************************************************************/ /********** Put a icon to submit a form. **********/ /********** When clicked, the icon will be replaced by an animation **********/ /*****************************************************************************/ void Lay_PutCalculateIcon (const char *Alt) { fprintf (Gbl.F.Out,"
" "\"%s\"" "\"%s\"" // Animated icon hidden "
" "", Gbl.Form.Num,Gbl.Prefs.IconsURL,Alt,Alt, Gbl.Form.Num,Gbl.Prefs.IconsURL,Alt,Alt); } /*****************************************************************************/ /********** Put a icon with a text to submit a form. **********/ /********** When clicked, the icon will be replaced by an animation **********/ /*****************************************************************************/ void Lay_PutCalculateIconWithText (const char *Alt,const char *Text) { fprintf (Gbl.F.Out,"
" "\"%s\"" "\"%s\"" // Animated icon hidden " %s" "
" "", Gbl.Form.Num,Gbl.Prefs.IconsURL,Alt,Text, Gbl.Form.Num,Gbl.Prefs.IconsURL,Alt,Text, Text); } /*****************************************************************************/ /******** Put a disabled icon indicating that removal is not allowed *********/ /*****************************************************************************/ void Lay_PutIconRemovalNotAllowed (void) { extern const char *Txt_Removal_not_allowed; fprintf (Gbl.F.Out,"\"%s\"", Gbl.Prefs.IconsURL, Txt_Removal_not_allowed, Txt_Removal_not_allowed); } void Lay_PutIconBRemovalNotAllowed (void) { extern const char *Txt_Removal_not_allowed; fprintf (Gbl.F.Out,"\"%s\"", Gbl.Prefs.IconsURL, Txt_Removal_not_allowed, Txt_Removal_not_allowed); } /*****************************************************************************/ /******** Put an icon indicating that removal is not allowed *********/ /*****************************************************************************/ void Lay_PutIconRemove (void) { extern const char *Txt_Remove; fprintf (Gbl.F.Out,"", Gbl.Prefs.IconsURL, Txt_Remove, Txt_Remove); } /*****************************************************************************/ /********************** Put a button to submit a form ************************/ /*****************************************************************************/ void Lay_PutButton (Lay_Button_t Button,const char *TxtButton) { if (TxtButton) if (TxtButton[0]) switch (Button) { case Lay_NO_BUTTON: break; case Lay_CREATE_BUTTON: Lay_PutCreateButton (TxtButton); break; case Lay_CONFIRM_BUTTON: Lay_PutConfirmButton (TxtButton); break; case Lay_REMOVE_BUTTON: Lay_PutRemoveButton (TxtButton); break; } } void Lay_PutCreateButton (const char *TxtButton) { fprintf (Gbl.F.Out,"
" "" "
", TxtButton); } void Lay_PutCreateButtonInline (const char *TxtButton) { fprintf (Gbl.F.Out,"", TxtButton); } void Lay_PutConfirmButton (const char *TxtButton) { fprintf (Gbl.F.Out,"
" "" "
", TxtButton); } void Lay_PutConfirmButtonInline (const char *TxtButton) { fprintf (Gbl.F.Out,"", TxtButton); } void Lay_PutRemoveButton (const char *TxtButton) { fprintf (Gbl.F.Out,"
" "" "
", TxtButton); } void Lay_PutRemoveButtonInline (const char *TxtButton) { fprintf (Gbl.F.Out,"", TxtButton); } /*****************************************************************************/ /****************** Start and end a table with rounded frame *****************/ /*****************************************************************************/ // CellPadding must be 0, 1, 2, 4 or 8 void Lay_StartRoundFrameTable (const char *Width,const char *Title, void (*FunctionToDrawContextualIcons) (void), const char *HelpLink, unsigned CellPadding) // CellPadding must be 0, 1, 2, 5 or 10 { Lay_StartRoundFrame (Width,Title,FunctionToDrawContextualIcons,HelpLink); Lay_StartTableWide (CellPadding); } void Lay_StartRoundFrameTableShadow (const char *Width,const char *Title, void (*FunctionToDrawContextualIcons) (void), const char *HelpLink, unsigned CellPadding) // CellPadding must be 0, 1, 2, 5 or 10 { Lay_StartRoundFrameShadow (Width,Title,FunctionToDrawContextualIcons,HelpLink); Lay_StartTableWide (CellPadding); } void Lay_StartRoundFrame (const char *Width,const char *Title, void (*FunctionToDrawContextualIcons) (void), const char *HelpLink) { Lay_StartRoundFrameInternal (Width,Title, FunctionToDrawContextualIcons, HelpLink, "FRAME"); } void Lay_StartRoundFrameShadow (const char *Width,const char *Title, void (*FunctionToDrawContextualIcons) (void), const char *HelpLink) { Lay_StartRoundFrameInternal (Width,Title, FunctionToDrawContextualIcons, HelpLink, "FRAME_SHADOW"); } static void Lay_StartRoundFrameInternal (const char *Width,const char *Title, void (*FunctionToDrawContextualIcons) (void), const char *HelpLink, const char *ClassFrame) { extern const char *Txt_Help; fprintf (Gbl.F.Out,"
" "
"); fprintf (Gbl.F.Out,"
"); if (FunctionToDrawContextualIcons) { fprintf (Gbl.F.Out,"
"); FunctionToDrawContextualIcons (); fprintf (Gbl.F.Out,"
"); } if (HelpLink) fprintf (Gbl.F.Out,"", Hlp_WIKI,HelpLink, Gbl.Prefs.IconsURL, Txt_Help,Txt_Help); fprintf (Gbl.F.Out,"
"); if (Title) fprintf (Gbl.F.Out,"
" "%s" "
", Gbl.Layout.FrameNested ? "FRAME_TITLE_SMALL" : "FRAME_TITLE_BIG", Title); Gbl.Layout.FrameNested++; } void Lay_EndRoundFrameTable (void) { Lay_EndTable (); Lay_EndRoundFrame (); } void Lay_EndRoundFrameTableWithButton (Lay_Button_t Button,const char *TxtButton) { Lay_EndTable (); Lay_EndRoundFrameWithButton (Button,TxtButton); } void Lay_EndRoundFrameWithButton (Lay_Button_t Button,const char *TxtButton) { Lay_PutButton (Button,TxtButton); Lay_EndRoundFrame (); } void Lay_EndRoundFrame (void) { Gbl.Layout.FrameNested--; fprintf (Gbl.F.Out,"
" "
"); } void Lay_StartTable (unsigned CellPadding) { fprintf (Gbl.F.Out,""); } void Lay_StartTableCenter (unsigned CellPadding) { fprintf (Gbl.F.Out,""); } void Lay_StartTableWide (unsigned CellPadding) { fprintf (Gbl.F.Out,"
"); } void Lay_StartTableWideMargin (unsigned CellPadding) { fprintf (Gbl.F.Out,"
"); } void Lay_EndTable (void) { fprintf (Gbl.F.Out,"
"); } /*****************************************************************************/ /******* Write error message, close files, remove lock file, and exit ********/ /*****************************************************************************/ void Lay_ShowErrorAndExit (const char *Txt) { extern struct Act_Actions Act_Actions[Act_NUM_ACTIONS]; /***** Unlock tables if locked *****/ if (Gbl.DB.LockedTables) { Gbl.DB.LockedTables = false; mysql_query (&Gbl.mysql,"UNLOCK TABLES"); } if (!Gbl.WebService.IsWebService) { /****** If start of page is not written yet, do it now ******/ if (!Gbl.Layout.HTMLStartWritten) Lay_WriteStartOfPage (); /***** Write possible error message *****/ if (Txt) Ale_ShowAlert (Ale_ERROR,Txt); /***** Finish the page, except and *****/ Lay_WriteEndOfPage (); } /***** Free memory and close all the open files *****/ Gbl_Cleanup (); /***** Page is generated (except and ). Compute time to generate page *****/ if (!Gbl.Action.IsAJAXAutoRefresh) Sta_ComputeTimeToGeneratePage (); if (Gbl.WebService.IsWebService) // Serving a plugin request { /***** Log access *****/ Gbl.TimeSendInMicroseconds = 0L; Sta_LogAccess (Txt); } else { /***** Send page. The HTML output is now in Gbl.F.Out file ==> ==> copy it to standard output *****/ rewind (Gbl.F.Out); Fil_FastCopyOfOpenFiles (Gbl.F.Out,stdout); Fil_CloseAndRemoveFileForHTMLOutput (); if (!Gbl.Action.IsAJAXAutoRefresh) { /***** Compute time to send page *****/ Sta_ComputeTimeToSendPage (); /***** Log access *****/ Sta_LogAccess (Txt); /***** End the output *****/ if (!Gbl.Layout.HTMLEndWritten) { // Here Gbl.F.Out is stdout if (Act_Actions[Gbl.Action.Act].BrowserWindow == Act_THIS_WINDOW) Lay_WriteAboutZone (); fprintf (Gbl.F.Out,"\n" "\n"); Gbl.Layout.HTMLEndWritten = true; } } } /***** Close database connection *****/ DB_CloseDBConnection (); /***** Exit *****/ if (Gbl.WebService.IsWebService) Svc_Exit (Txt); exit (0); } /*****************************************************************************/ /***************** Write about zone at the end of the page *******************/ /*****************************************************************************/ static void Lay_WriteAboutZone (void) { extern const char *Txt_About_X; extern const char *Txt_Questions_and_problems; /***** Start about zone *****/ fprintf (Gbl.F.Out,"
"); /***** Institution and centre hosting the platform *****/ fprintf (Gbl.F.Out,"" "\"%s\"" "
%s
" "
", Cfg_ABOUT_URL, Gbl.Prefs.IconsURL,Cfg_ABOUT_LOGO, Cfg_ABOUT_NAME,Cfg_ABOUT_NAME, Cfg_ABOUT_LOGO_WIDTH,Cfg_ABOUT_LOGO_HEIGHT, Cfg_ABOUT_NAME); /***** Questions and problems *****/ fprintf (Gbl.F.Out,"
" "%s: " "%s" "
", Txt_Questions_and_problems, Cfg_PLATFORM_RESPONSIBLE_EMAIL,Cfg_PLATFORM_RESPONSIBLE_EMAIL); /***** About and time to generate and send page *****/ fprintf (Gbl.F.Out,"
"); /* About */ fprintf (Gbl.F.Out,"", Cfg_ABOUT_SWAD_URL); fprintf (Gbl.F.Out,Txt_About_X,Log_PLATFORM_VERSION); fprintf (Gbl.F.Out,"" "     "); /* Time to generate and send page */ Sta_WriteTimeToGenerateAndSendPage (); fprintf (Gbl.F.Out,"
"); /***** End about zone *****/ fprintf (Gbl.F.Out,"
"); // about_zone } /*****************************************************************************/ /*********** Refresh notifications and connected users via AJAX **************/ /*****************************************************************************/ void Lay_RefreshNotifsAndConnected (void) { unsigned NumUsr; bool ShowConnected = (Gbl.Prefs.SideCols & Lay_SHOW_RIGHT_COLUMN) && Gbl.CurrentCrs.Crs.CrsCod > 0; // Right column visible && There is a course selected // Sometimes, someone must do this work, so who best than processes that refresh via AJAX? if (!(Gbl.PID % 11)) // Do this only one of 11 times ( 11 is prime) Ntf_SendPendingNotifByEMailToAllUsrs (); // Send pending notifications by email else if (!(Gbl.PID % 1013)) // Do this only one of 1013 times (1013 is prime) Brw_RemoveExpiredExpandedFolders (); // Remove old expanded folders (from all users) else if (!(Gbl.PID % 1019)) // Do this only one of 1019 times (1019 is prime) Pre_RemoveOldPrefsFromIP (); // Remove old preferences from IP else if (!(Gbl.PID % 1021)) // Do this only one of 1021 times (1021 is prime) Sta_RemoveOldEntriesRecentLog (); // Remove old entries in recent log table, it's a slow query // Send, before the HTML, the refresh time fprintf (Gbl.F.Out,"%lu|",Gbl.Usrs.Connected.TimeToRefreshInMs); if (Gbl.Usrs.Me.Logged) Ntf_WriteNumberOfNewNtfs (); fprintf (Gbl.F.Out,"|"); Con_ShowGlobalConnectedUsrs (); fprintf (Gbl.F.Out,"|"); if (ShowConnected) { Gbl.Scope.Current = Sco_SCOPE_CRS; Con_ShowConnectedUsrsBelongingToCurrentCrs (); } fprintf (Gbl.F.Out,"|"); if (ShowConnected) fprintf (Gbl.F.Out,"%u",Gbl.Usrs.Connected.NumUsrsToList); fprintf (Gbl.F.Out,"|"); if (ShowConnected) for (NumUsr = 0; NumUsr < Gbl.Usrs.Connected.NumUsrsToList; NumUsr++) fprintf (Gbl.F.Out,"%ld|",Gbl.Usrs.Connected.Lst[NumUsr].TimeDiff); /***** All the output is made, so don't write anymore *****/ Gbl.Layout.DivsEndWritten = Gbl.Layout.HTMLEndWritten = true; } /*****************************************************************************/ /**************** Refresh last clicks in realtime via AJAX *******************/ /*****************************************************************************/ void Lay_RefreshLastClicks (void) { if (Gbl.Session.IsOpen) // If session has been closed, do not write anything { /***** Send, before the HTML, the refresh time *****/ fprintf (Gbl.F.Out,"%lu|",Cfg_TIME_TO_REFRESH_LAST_CLICKS); /***** Get and show last clicks *****/ Con_GetAndShowLastClicks (); } /***** All the output is made, so don't write anymore *****/ Gbl.Layout.DivsEndWritten = Gbl.Layout.HTMLEndWritten = true; } /*****************************************************************************/ /************************ Write the end of the page **************************/ /*****************************************************************************/ static void Lay_WriteFootFromHTMLFile (void) { FILE *FileHTML; /***** Open file with the HTML page for the chat *****/ if ((FileHTML = fopen (Cfg_PATH_AND_FILE_REL_HTML_PRIVATE,"rb"))) { fprintf (Gbl.F.Out,"
"); /***** Copy HTML to output file *****/ Fil_FastCopyOfOpenFiles (FileHTML,Gbl.F.Out); fclose (FileHTML); fprintf (Gbl.F.Out,"
"); } } /*****************************************************************************/ /****** Write header and footer of the class photo or academic calendar ******/ /*****************************************************************************/ void Lay_WriteHeaderClassPhoto (bool PrintView,bool DrawingClassPhoto, long InsCod,long DegCod,long CrsCod) { struct Instit Ins; struct Degree Deg; struct Course Crs; /***** Get data of institution *****/ Ins.InsCod = InsCod; Ins_GetDataOfInstitutionByCod (&Ins,Ins_GET_BASIC_DATA); /***** Get data of degree *****/ Deg.DegCod = DegCod; Deg_GetDataOfDegreeByCod (&Deg); /***** Get data of course *****/ Crs.CrsCod = CrsCod; Crs_GetDataOfCourseByCod (&Crs); /***** Table start *****/ fprintf (Gbl.F.Out,"" ""); /***** First column: institution logo *****/ fprintf (Gbl.F.Out,""); /***** Second column: class photo title *****/ fprintf (Gbl.F.Out,""); /***** Third column: degree logo *****/ fprintf (Gbl.F.Out,""); /***** End table *****/ fprintf (Gbl.F.Out,"" "
"); if (InsCod > 0) { if (!PrintView) fprintf (Gbl.F.Out,"",Ins.WWW); Log_DrawLogo (Sco_SCOPE_INS,Ins.InsCod,Ins.ShrtName,40,NULL,true); if (!PrintView) fprintf (Gbl.F.Out,""); } fprintf (Gbl.F.Out,""); if (InsCod > 0) { if (!PrintView) fprintf (Gbl.F.Out,"", Ins.WWW); fprintf (Gbl.F.Out,"%s",Ins.FullName); if (!PrintView) fprintf (Gbl.F.Out,""); } if (DegCod > 0) { if (Ins.InsCod > 0) fprintf (Gbl.F.Out," - "); if (!PrintView) fprintf (Gbl.F.Out,"", Deg.WWW); fprintf (Gbl.F.Out,"%s",Deg.FullName); if (!PrintView) fprintf (Gbl.F.Out,""); } fprintf (Gbl.F.Out,"
"); if (CrsCod > 0) { fprintf (Gbl.F.Out,"%s",Crs.FullName); if (DrawingClassPhoto && !Gbl.Usrs.ClassPhoto.AllGroups) { fprintf (Gbl.F.Out,"
"); Grp_WriteNamesOfSelectedGrps (); } } fprintf (Gbl.F.Out,"
"); if (DegCod > 0) { if (!PrintView) fprintf (Gbl.F.Out,"", Deg.WWW); Log_DrawLogo (Sco_SCOPE_DEG,Deg.DegCod,Deg.ShrtName,40,NULL,true); if (!PrintView) fprintf (Gbl.F.Out,""); } fprintf (Gbl.F.Out,"
"); } /*****************************************************************************/ /**************** Show advertisement about mobile version ********************/ /*****************************************************************************/ #define Lay_SHOW_ADVERTISEMENT_ONE_TIME_OF_X 5 // n ==> show advertisement 1/n of the times void Lay_AdvertisementMobile (void) { extern const char *Txt_Stay_connected_with_SWADroid; if (!(rand () % Lay_SHOW_ADVERTISEMENT_ONE_TIME_OF_X)) { fprintf (Gbl.F.Out,"
"); /***** Table start *****/ Lay_StartRoundFrameTable (NULL,NULL,NULL,NULL,8); /***** Show advertisement *****/ fprintf (Gbl.F.Out,"" "" "" "%s

" "\"SWADroid\"" "
" "" "", Txt_Stay_connected_with_SWADroid, Gbl.Prefs.IconsURL, Txt_Stay_connected_with_SWADroid); /***** End table *****/ Lay_EndRoundFrameTable (); fprintf (Gbl.F.Out,"
"); } } /*****************************************************************************/ /*********************** Indent forum or chat title **************************/ /*****************************************************************************/ // IsLastItemInLevel[] is a vector with at least 1 + Level booleans void Lay_IndentDependingOnLevel (unsigned Level,bool IsLastItemInLevel[]) { unsigned i; /***** Indent (from 1 to Level-1) *****/ for (i = 1; i < Level; i++) fprintf (Gbl.F.Out,"\"\"", Gbl.Prefs.IconsURL, IsLastItemInLevel[i] ? "tr" : "subleft"); /***** Level *****/ if (Level) fprintf (Gbl.F.Out,"\"\"", Gbl.Prefs.IconsURL, IsLastItemInLevel[Level] ? "subend" : "submid"); } /*****************************************************************************/ /************************** Help for the text editor *************************/ /*****************************************************************************/ void Lay_HelpPlainEditor (void) { extern const char *Txt_TEXT_plain; Lay_HelpTextEditor (Txt_TEXT_plain, "\\(LaTeX\\)", "$$LaTeX$$ \\[LaTeX\\]"); } void Lay_HelpRichEditor (void) { Lay_HelpTextEditor ("Markdown+Pandoc", "$LaTeX$", "$$LaTeX$$"); } static void Lay_HelpTextEditor (const char *Text,const char *InlineMath,const char *Equation) { extern const char *Txt_Text; extern const char *Txt_Inline_math; extern const char *Txt_Equation_centered; fprintf (Gbl.F.Out,"
" "%s: %s" " " "%s: %s" " " "%s: %s" "
", Txt_Text,Text, Txt_Inline_math,InlineMath, Txt_Equation_centered,Equation); } /*****************************************************************************/ /************************** Help for the text editor *************************/ /*****************************************************************************/ void Lay_StartHTMLFile (FILE *File,const char *Title) { extern const char *Txt_STR_LANG_ID[1 + Txt_NUM_LANGUAGES]; fprintf (File,"\n" "\n" "\n" "\n" "%s\n" "\n", Txt_STR_LANG_ID[Gbl.Prefs.Language], // Language Title); // Page title }