diff --git a/sql/swad.sql b/sql/swad.sql index d6bb1e9a4..f5eed37fc 100644 --- a/sql/swad.sql +++ b/sql/swad.sql @@ -1087,7 +1087,8 @@ CREATE TABLE IF NOT EXISTS tst_answers ( AnsInd TINYINT NOT NULL, Answer TEXT NOT NULL, Feedback TEXT NOT NULL, - Image VARCHAR(43) NOT NULL, + ImageName VARCHAR(43) NOT NULL, + ImageTitle TEXT NOT NULL, Correct ENUM('N','Y') NOT NULL, INDEX(QstCod)); -- @@ -1145,7 +1146,8 @@ CREATE TABLE IF NOT EXISTS tst_questions ( Shuffle ENUM('N','Y') NOT NULL, Stem TEXT NOT NULL, Feedback TEXT NOT NULL, - Image VARCHAR(43) NOT NULL, + ImageName VARCHAR(43) NOT NULL, + ImageTitle TEXT NOT NULL, NumHits INT NOT NULL DEFAULT 0, NumHitsNotBlank INT NOT NULL DEFAULT 0, Score DOUBLE PRECISION NOT NULL DEFAULT 0, diff --git a/swad_changelog.h b/swad_changelog.h index 34eff70c7..41cd704f6 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -131,13 +131,20 @@ /****************************** Public constants *****************************/ /*****************************************************************************/ -#define Log_PLATFORM_VERSION "SWAD 15.181 (2016-04-05)" +#define Log_PLATFORM_VERSION "SWAD 15.182 (2016-04-06)" #define CSS_FILE "swad15.178.2.css" #define JS_FILE "swad15.178.2.js" // Number of lines (includes comments but not blank lines) has been got with the following command: // nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*.h sql/swad*.sql | tail -1 /* + Version 15.182: Apr 06, 2016 Get fields title/attribution of images from form. (198610 lines) + 4 changes necessary in database: +ALTER TABLE tst_questions CHANGE COLUMN Image ImageName VARCHAR(43) NOT NULL; +ALTER TABLE tst_questions ADD COLUMN ImageTitle TEXT NOT NULL AFTER ImageName; +ALTER TABLE tst_answers CHANGE COLUMN Image ImageName VARCHAR(43) NOT NULL; +ALTER TABLE tst_answers ADD COLUMN ImageTitle TEXT NOT NULL AFTER ImageName; + Version 15.181: Apr 05, 2016 New fields in test questions with the title/attribution of images. (198515 lines) Version 15.180.7: Apr 05, 2016 Changes in layout of editor of question. (198473 lines) Version 15.180.6: Apr 05, 2016 Changes in layout of editor of question. (198490 lines) diff --git a/swad_database.c b/swad_database.c index 542581b65..8ec59a999 100644 --- a/swad_database.c +++ b/swad_database.c @@ -2290,24 +2290,26 @@ mysql> DESCRIBE timetable_tut; /***** Table tst_answers *****/ /* mysql> DESCRIBE tst_answers; -+----------+---------------+------+-----+---------+-------+ -| Field | Type | Null | Key | Default | Extra | -+----------+---------------+------+-----+---------+-------+ -| QstCod | int(11) | NO | MUL | NULL | | -| AnsInd | tinyint(4) | NO | | NULL | | -| Answer | text | NO | | NULL | | -| Feedback | text | NO | | NULL | | -| Image | varchar(43) | NO | | NULL | | -| Correct | enum('N','Y') | NO | | NULL | | -+----------+---------------+------+-----+---------+-------+ -6 rows in set (0.00 sec) ++------------+---------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++------------+---------------+------+-----+---------+-------+ +| QstCod | int(11) | NO | MUL | NULL | | +| AnsInd | tinyint(4) | NO | | NULL | | +| Answer | text | NO | | NULL | | +| Feedback | text | NO | | NULL | | +| ImageName | varchar(43) | NO | | NULL | | +| ImageTitle | text | NO | | NULL | | +| Correct | enum('N','Y') | NO | | NULL | | ++------------+---------------+------+-----+---------+-------+ +7 rows in set (0.00 sec) */ DB_CreateTable ("CREATE TABLE IF NOT EXISTS tst_answers (" "QstCod INT NOT NULL," "AnsInd TINYINT NOT NULL," "Answer TEXT NOT NULL," "Feedback TEXT NOT NULL," - "Image VARCHAR(43) NOT NULL," + "ImageName VARCHAR(43) NOT NULL," + "ImageTitle TEXT NOT NULL," "Correct ENUM('N','Y') NOT NULL," "INDEX(QstCod))"); @@ -2421,12 +2423,13 @@ mysql> DESCRIBE tst_questions; | Shuffle | enum('N','Y') | NO | | NULL | | | Stem | text | NO | | NULL | | | Feedback | text | NO | | NULL | | -| Image | varchar(43) | NO | | NULL | | +| ImageName | varchar(43) | NO | | NULL | | +| ImageTitle | text | NO | | NULL | | | NumHits | int(11) | NO | | 0 | | | NumHitsNotBlank | int(11) | NO | | 0 | | | Score | double | NO | | 0 | | +-----------------+---------------------------------------------------------------------------+------+-----+---------+----------------+ -11 rows in set (0.00 sec) +12 rows in set (0.00 sec) */ DB_CreateTable ("CREATE TABLE IF NOT EXISTS tst_questions (" "QstCod INT NOT NULL AUTO_INCREMENT," @@ -2436,7 +2439,8 @@ mysql> DESCRIBE tst_questions; "Shuffle ENUM('N','Y') NOT NULL," "Stem TEXT NOT NULL," "Feedback TEXT NOT NULL," - "Image VARCHAR(43) NOT NULL," + "ImageName VARCHAR(43) NOT NULL," + "ImageTitle TEXT NOT NULL," "NumHits INT NOT NULL DEFAULT 0," "NumHitsNotBlank INT NOT NULL DEFAULT 0," "Score DOUBLE PRECISION NOT NULL DEFAULT 0," diff --git a/swad_image.c b/swad_image.c index 27866985a..1b93be5c4 100644 --- a/swad_image.c +++ b/swad_image.c @@ -67,13 +67,54 @@ static void Img_ProcessImage (const char *FileNameImgOriginal, const char *FileNameImgProcessed, unsigned Width,unsigned Height,unsigned Quality); +/*****************************************************************************/ +/*************************** Reset image title *******************************/ +/*****************************************************************************/ + +void Img_ResetImageTitle (struct Image *Image) + { + if (Image->Title) + free ((void *) Image->Title); + Image->Title = NULL; + } + +/*****************************************************************************/ +/************ Get image title from a string and copy to struct ***************/ +/*****************************************************************************/ + +void Img_GetImageNameTitle (const char *Name,const char *Title, + struct Image *Image) + { + size_t Length; + + Img_ResetImageTitle (Image); + + if (Name[0]) + { + strncpy (Image->Name,Name,Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64); + Image->Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64] = '\0'; + + if (Image->Name[0]) // There is an image + if (Title[0]) + { + Length = strlen (Title); + if ((Image->Title = (char *) malloc (Length+1)) == NULL) + Lay_ShowErrorAndExit ("Error allocating memory for image title."); + strncpy (Image->Title,Title,Length); + Image->Title[Length] = '\0'; + } + } + else // No image in this question + Image->Name[0] = '\0'; + } + /*****************************************************************************/ /***************************** Get image from form ***************************/ /*****************************************************************************/ void Img_GetImageFromForm (unsigned NumOpt,struct Image *Image, - void (*GetImageName) (unsigned NumOpt,char *ImageName), - const char *ParamAction,const char *ParamFile, + void (*GetImageNameFromDB) (unsigned NumOpt,struct Image *Image), + const char *ParamAction,const char *ParamFile,const char *ParamTitle, unsigned Width,unsigned Height,unsigned Quality) { Image->Action = Img_GetImageActionFromForm (ParamAction); @@ -83,30 +124,34 @@ void Img_GetImageFromForm (unsigned NumOpt,struct Image *Image, case Img_ACTION_NO_IMAGE: // Do not use image (remove current image if exists) /***** Reset image name *****/ Image->Name[0] = '\0'; + Img_ResetImageTitle (Image); break; case Img_ACTION_KEEP_IMAGE: // Keep current image unchanged /***** Get image name *****/ - GetImageName (NumOpt,Image->Name); + GetImageNameFromDB (NumOpt,Image); if (Image->Name[0]) Image->Status = Img_NAME_STORED_IN_DB; break; case Img_ACTION_NEW_IMAGE: // Upload new image /***** Get new image (if present ==> process and create temporary file) *****/ - Img_GetAndProcessImageFileFromForm (Image,ParamFile,Width,Height,Quality); + Img_GetAndProcessImageFileFromForm (Image,ParamFile,ParamTitle, + Width,Height,Quality); if (Image->Status != Img_FILE_PROCESSED) // No new image received-processed successfully { /* Reset image name */ - Image->Name[0] = '\0'; Image->Status = Img_FILE_NONE; + Image->Name[0] = '\0'; + Img_ResetImageTitle (Image); } break; case Img_ACTION_CHANGE_IMAGE: // Replace old image by new image /***** Get new image (if present ==> process and create temporary file) *****/ - Img_GetAndProcessImageFileFromForm (Image,ParamFile,Width,Height,Quality); + Img_GetAndProcessImageFileFromForm (Image,ParamFile,ParamTitle, + Width,Height,Quality); if (Image->Status != Img_FILE_PROCESSED) // No new image received-processed successfully { /* Get image name */ - GetImageName (NumOpt,Image->Name); + GetImageNameFromDB (NumOpt,Image); Image->Status = (Image->Name[0] ? Img_NAME_STORED_IN_DB : Img_FILE_NONE); } @@ -137,7 +182,7 @@ Img_Action_t Img_GetImageActionFromForm (const char *ParamAction) // Return true if image is created void Img_GetAndProcessImageFileFromForm (struct Image *Image, - const char *ParamFile, + const char *ParamFile,const char *ParamTitle, unsigned Width,unsigned Height, unsigned Quality) { @@ -150,6 +195,8 @@ void Img_GetAndProcessImageFileFromForm (struct Image *Image, char FileNameImgOrig[PATH_MAX+1]; // Full name of original uploaded file char FileNameImgTmp[PATH_MAX+1]; // Full name of temporary processed file bool WrongType = false; + char Title[Cns_MAX_BYTES_TEXT+1]; + size_t Length; /***** Rest image file status *****/ Image->Status = Img_FILE_NONE; @@ -214,6 +261,17 @@ void Img_GetAndProcessImageFileFromForm (struct Image *Image, /***** Remove temporary original file *****/ unlink (FileNameImgOrig); + + /***** Get image title from form *****/ + Par_GetParToHTML (ParamTitle,Title,Cns_MAX_BYTES_TEXT); // TODO: Create a function to get only the length of a parameter + Length = strlen (Title); + if (Length > 0) + { + if ((Image->Title = (char *) malloc (Length+1)) == NULL) + Lay_ShowErrorAndExit ("Error allocating memory for image title."); + strncpy (Image->Title,Title,Length); + Image->Title[Length] = '\0'; + } } } diff --git a/swad_image.h b/swad_image.h index 68559f982..a2667d969 100644 --- a/swad_image.h +++ b/swad_image.h @@ -85,19 +85,24 @@ struct Image Img_Action_t Action; Img_FileStatus_t Status; char Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64+1]; + char *Title; // Title/attribution }; /*****************************************************************************/ /***************************** Public prototypes *****************************/ /*****************************************************************************/ +void Img_ResetImageTitle (struct Image *Image); +void Img_GetImageNameTitle (const char *Name,const char *Title, + struct Image *Image); + void Img_GetImageFromForm (unsigned NumOpt,struct Image *Image, - void (*GetImageName) (unsigned NumOpt,char *ImageName), - const char *ParamAction,const char *ParamFile, + void (*GetImageNameFromDB) (unsigned NumOpt,struct Image *Image), + const char *ParamAction,const char *ParamFile,const char *ParamTitle, unsigned Width,unsigned Height,unsigned Quality); Img_Action_t Img_GetImageActionFromForm (const char *ParamAction); void Img_GetAndProcessImageFileFromForm (struct Image *Image, - const char *ParamFile, + const char *ParamFile,const char *ParamTitle, unsigned Width,unsigned Height, unsigned Quality); diff --git a/swad_test.c b/swad_test.c index 73b1acd7e..706a350f8 100644 --- a/swad_test.c +++ b/swad_test.c @@ -220,9 +220,10 @@ static int Tst_CountNumAnswerTypesInList (void); static void Tst_PutFormEditOneQst (char *Stem,char *Feedback); static void Tst_InitImagesOfQuestion (void); +static void Tst_FreeImagesOfQuestion (void); static void Tst_GetQstDataFromDB (char *Stem,char *Feedback); -static void Tst_GetImageNameFromDB (unsigned NumOpt,char *ImageName); +static void Tst_GetImageFromDB (unsigned NumOpt,struct Image *Image); static Tst_AnswerType_t Tst_ConvertFromUnsignedStrToAnsTyp (const char *UnsignedStr); static void Tst_GetQstFromForm (char *Stem,char *Feedback); @@ -902,16 +903,17 @@ static void Tst_ShowTstResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank, /***** Get row of the result of the query *****/ row = mysql_fetch_row (mysql_res); /* - row[0] QstCod - row[1] UNIX_TIMESTAMP(EditTime) - row[2] AnsType - row[3] Shuffle - row[4] Stem - row[5] Image - row[6] Feedback - row[7] NumHits - row[8] NumHitsNotBlank - row[9] Score + row[ 0] QstCod + row[ 1] UNIX_TIMESTAMP(EditTime) + row[ 2] AnsType + row[ 3] Shuffle + row[ 4] Stem + row[ 5] Feedback + row[ 6] ImageName + row[ 7] ImageTitle + row[ 8] NumHits + row[ 9] NumHitsNotBlank + row[10] Score */ /***** Get the code of question (row[0]) *****/ @@ -966,16 +968,17 @@ static void Tst_WriteQstAndAnsExam (unsigned NumQst,long QstCod,MYSQL_ROW row, { extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES]; /* - row[0] QstCod - row[1] UNIX_TIMESTAMP(EditTime) - row[2] AnsType - row[3] Shuffle - row[4] Stem - row[5] Image - row[6] Feedback - row[7] NumHits - row[8] NumHitsNotBlank - row[9] Score + row[ 0] QstCod + row[ 1] UNIX_TIMESTAMP(EditTime) + row[ 2] AnsType + row[ 3] Shuffle + row[ 4] Stem + row[ 5] Feedback + row[ 6] ImageName + row[ 7] ImageTitle + row[ 8] NumHits + row[ 9] NumHitsNotBlank + row[10] Score */ /***** Write number of question *****/ @@ -991,15 +994,15 @@ static void Tst_WriteQstAndAnsExam (unsigned NumQst,long QstCod,MYSQL_ROW row, "", Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]); - /***** Write stem (row[4]), answers depending on shuffle (row[3]) and feedback (row[6]) *****/ + /***** Write stem (row[4]), image (row[6], row[7]), + answers depending on shuffle (row[3]) and feedback (row[5]) *****/ fprintf (Gbl.F.Out,"", Gbl.RowEvenOdd); Tst_WriteQstStem (row[4],"TEST_EXA"); - if (row[5][0]) + if (row[6][0]) { Gbl.Test.Image.Status = Img_NAME_STORED_IN_DB; - strncpy (Gbl.Test.Image.Name,row[5],Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64); - Gbl.Test.Image.Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64] = '\0'; + Img_GetImageNameTitle (row[6],row[7],&Gbl.Test.Image); Img_ShowImage (&Gbl.Test.Image,"TEST_IMG_SHOW_STEM"); } if (Gbl.Action.Act == ActSeeTst) @@ -1012,6 +1015,10 @@ static void Tst_WriteQstAndAnsExam (unsigned NumQst,long QstCod,MYSQL_ROW row, } fprintf (Gbl.F.Out,"" ""); + + /***** Free answers and images of this test question *****/ + Tst_FreeTextChoiceAnswers (); + Tst_FreeImagesOfQuestion (); } /*****************************************************************************/ @@ -2304,22 +2311,23 @@ static unsigned long Tst_GetQuestionsForEdit (MYSQL_RES **mysql_res) /***** Select questions *****/ /* Start query */ /* - row[0] QstCod - row[1] UNIX_TIMESTAMP(EditTime) - row[2] AnsType - row[3] Shuffle - row[4] Stem - row[5] Image - row[6] Feedback - row[7] NumHits - row[8] NumHitsNotBlank - row[9] Score + row[ 0] QstCod + row[ 1] UNIX_TIMESTAMP(EditTime) + row[ 2] AnsType + row[ 3] Shuffle + row[ 4] Stem + row[ 5] Feedback + row[ 6] ImageName + row[ 7] ImageTitle + row[ 8] NumHits + row[ 9] NumHitsNotBlank + row[10] Score */ sprintf (Query,"SELECT tst_questions.QstCod," "UNIX_TIMESTAMP(tst_questions.EditTime) AS F," "tst_questions.AnsType,tst_questions.Shuffle," - "tst_questions.Stem,tst_questions.Image," - "tst_questions.Feedback," + "tst_questions.Stem,tst_questions.Feedback," + "tst_questions.ImageName,tst_questions.ImageTitle," "tst_questions.NumHits,tst_questions.NumHitsNotBlank," "tst_questions.Score" " FROM tst_questions"); @@ -2441,16 +2449,17 @@ static unsigned long Tst_GetQuestionsForExam (MYSQL_RES **mysql_res) /***** Select questions without hidden tags *****/ /* - row[0] QstCod - row[1] UNIX_TIMESTAMP(EditTime) - row[2] AnsType - row[3] Shuffle - row[4] Stem - row[5] Image - row[6] Feedback - row[7] NumHits - row[8] NumHitsNotBlank - row[9] Score + row[ 0] QstCod + row[ 1] UNIX_TIMESTAMP(EditTime) + row[ 2] AnsType + row[ 3] Shuffle + row[ 4] Stem + row[ 5] Feedback + row[ 6] ImageName + row[ 7] ImageTitle + row[ 8] NumHits + row[ 9] NumHitsNotBlank + row[10] Score */ /* Start query */ // Reject questions with any tag hidden @@ -2459,8 +2468,8 @@ static unsigned long Tst_GetQuestionsForExam (MYSQL_RES **mysql_res) sprintf (Query,"SELECT DISTINCTROW tst_questions.QstCod," "UNIX_TIMESTAMP(tst_questions.EditTime)," "tst_questions.AnsType,tst_questions.Shuffle," - "tst_questions.Stem,tst_questions.Image," - "tst_questions.Feedback," + "tst_questions.Stem,tst_questions.Feedback," + "tst_questions.ImageName,tst_questions.ImageTitle," "tst_questions.NumHits,tst_questions.NumHitsNotBlank," "tst_questions.Score" " FROM tst_questions,tst_question_tags,tst_tags" @@ -2564,19 +2573,20 @@ static bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res) /***** Get data of a question from database *****/ /* - row[0] QstCod - row[1] UNIX_TIMESTAMP(EditTime) - row[2] AnsType - row[3] Shuffle - row[4] Stem - row[5] Image - row[6] Feedback - row[7] NumHits - row[8] NumHitsNotBlank - row[9] Score + row[ 0] QstCod + row[ 1] UNIX_TIMESTAMP(EditTime) + row[ 2] AnsType + row[ 3] Shuffle + row[ 4] Stem + row[ 5] Feedback + row[ 6] ImageName + row[ 7] ImageTitle + row[ 8] NumHits + row[ 9] NumHitsNotBlank + row[10] Score */ sprintf (Query,"SELECT QstCod,UNIX_TIMESTAMP(EditTime)," - "AnsType,Shuffle,Stem,Image,Feedback," + "AnsType,Shuffle,Stem,Feedback,ImageName,ImageTitle," "NumHits,NumHitsNotBlank,Score" " FROM tst_questions" " WHERE QstCod='%ld'", @@ -2684,16 +2694,17 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m row = mysql_fetch_row (mysql_res); /* - row[0] QstCod - row[1] UNIX_TIMESTAMP(EditTime) - row[2] AnsType - row[3] Shuffle - row[4] Stem - row[5] Image - row[6] Feedback - row[7] NumHits - row[8] NumHitsNotBlank - row[9] Score + row[ 0] QstCod + row[ 1] UNIX_TIMESTAMP(EditTime) + row[ 2] AnsType + row[ 3] Shuffle + row[ 4] Stem + row[ 5] Feedback + row[ 6] ImageName + row[ 7] ImageTitle + row[ 8] NumHits + row[ 9] NumHitsNotBlank + row[10] Score */ /* row[0] holds the code of the question */ if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0) @@ -2784,36 +2795,40 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m } fprintf (Gbl.F.Out,""); - /* Write the stem (row[4]), the image (row[5],vthe feedback (row[6]) and the answers */ + /* Write the stem (row[4]), the image (row[6], row[7]), + the feedback (row[5]) and the answers */ fprintf (Gbl.F.Out,"", Gbl.RowEvenOdd); Tst_WriteQstStem (row[4],"TEST_EDI"); - if (row[5][0]) + if (row[6][0]) { Gbl.Test.Image.Status = Img_NAME_STORED_IN_DB; - strncpy (Gbl.Test.Image.Name,row[5],Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64); - Gbl.Test.Image.Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64] = '\0'; + Img_GetImageNameTitle (row[6],row[7],&Gbl.Test.Image); Img_ShowImage (&Gbl.Test.Image,"TEST_IMG_EDIT_LIST_STEM"); } - Tst_WriteQstFeedback (row[6],"TEST_EDI_LIGHT"); + Tst_WriteQstFeedback (row[5],"TEST_EDI_LIGHT"); Tst_WriteAnswersOfAQstEdit (QstCod); fprintf (Gbl.F.Out,""); + /* Free answers and images of this test question */ + Tst_FreeTextChoiceAnswers (); + Tst_FreeImagesOfQuestion (); + /* Get number of hits (number of times that the question has been answered, - including blank answers) (row[7]) */ - if (sscanf (row[7],"%lu",&NumHitsThisQst) != 1) + including blank answers) (row[8]) */ + if (sscanf (row[8],"%lu",&NumHitsThisQst) != 1) Lay_ShowErrorAndExit ("Wrong number of hits to a question."); /* Get number of hits not blank (number of times that the question has been answered - with a not blank answer) (row[8]) */ - if (sscanf (row[8],"%lu",&NumHitsNotBlankThisQst) != 1) + with a not blank answer) (row[9]) */ + if (sscanf (row[9],"%lu",&NumHitsNotBlankThisQst) != 1) Lay_ShowErrorAndExit ("Wrong number of hits not blank to a question."); - /* Get the acumulated score of the question (row[9]) */ + /* Get the acumulated score of the question (row[10]) */ setlocale (LC_NUMERIC,"en_US.utf8"); // To get decimal point - if (sscanf (row[9],"%lf",&TotalScoreThisQst) != 1) + if (sscanf (row[10],"%lf",&TotalScoreThisQst) != 1) Lay_ShowErrorAndExit ("Wrong score of a question."); setlocale (LC_NUMERIC,"es_ES.utf8"); // Return to spanish system (TODO: this should be internationalized!!!!!!!) @@ -2890,7 +2905,7 @@ unsigned Tst_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res,bool Shuffle) unsigned long NumRows; /***** Get answers of a question from database *****/ - sprintf (Query,"SELECT AnsInd,Answer,Correct,Feedback,Image" + sprintf (Query,"SELECT AnsInd,Answer,Correct,Feedback,ImageName,ImageTitle" " FROM tst_answers" " WHERE QstCod='%ld' ORDER BY %s", QstCod, @@ -2989,8 +3004,7 @@ static void Tst_WriteAnswersOfAQstEdit (long QstCod) if (row[4][0]) { Gbl.Test.Answer.Options[NumOpt].Image.Status = Img_NAME_STORED_IN_DB; - strncpy (Gbl.Test.Answer.Options[NumOpt].Image.Name,row[4],Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64); - Gbl.Test.Answer.Options[NumOpt].Image.Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64] = '\0'; + Img_GetImageNameTitle (row[4],row[5],&Gbl.Test.Answer.Options[NumOpt].Image); } /* Put an icon that indicates whether the answer is correct or wrong */ @@ -3285,8 +3299,7 @@ static void Tst_WriteChoiceAnsSeeExam (unsigned NumQst,long QstCod,bool Shuffle) if (row[4][0]) { Gbl.Test.Answer.Options[NumOpt].Image.Status = Img_NAME_STORED_IN_DB; - strncpy (Gbl.Test.Answer.Options[NumOpt].Image.Name,row[4],Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64); - Gbl.Test.Answer.Options[NumOpt].Image.Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64] = '\0'; + Img_GetImageNameTitle (row[4],row[5],&Gbl.Test.Answer.Options[NumOpt].Image); } /***** Write selectors and letter of this option *****/ @@ -3319,8 +3332,9 @@ static void Tst_WriteChoiceAnsSeeExam (unsigned NumQst,long QstCod,bool Shuffle) /***** End of table *****/ fprintf (Gbl.F.Out,""); - /***** Free answers *****/ + /***** Free answers and images of this test question *****/ Tst_FreeTextChoiceAnswers (); + Tst_FreeImagesOfQuestion (); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); @@ -3354,7 +3368,7 @@ static void Tst_WriteChoiceAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res, row[1] Answer row[2] Correct row[3] Feedback - row[4] Image + row[4] ImageName */ for (NumOpt = 0; NumOpt < Gbl.Test.Answer.NumOptions; @@ -3390,8 +3404,7 @@ static void Tst_WriteChoiceAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res, if (row[4][0]) { Gbl.Test.Answer.Options[NumOpt].Image.Status = Img_NAME_STORED_IN_DB; - strncpy (Gbl.Test.Answer.Options[NumOpt].Image.Name,row[4],Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64); - Gbl.Test.Answer.Options[NumOpt].Image.Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64] = '\0'; + Img_GetImageNameTitle (row[4],row[5],&Gbl.Test.Answer.Options[NumOpt].Image); } /***** Assign correctness (row[2]) of this answer (this option) *****/ @@ -3565,8 +3578,9 @@ static void Tst_WriteChoiceAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res, /***** End of table *****/ fprintf (Gbl.F.Out,""); - /***** Free answers *****/ + /***** Free answers and images of this test question *****/ Tst_FreeTextChoiceAnswers (); + Tst_FreeImagesOfQuestion (); } /*****************************************************************************/ @@ -4451,7 +4465,7 @@ static void Tst_PutFormEditOneQst (char *Stem,char *Feedback) Stem); Tst_PutFormToEditQstImage (&Gbl.Test.Image,"TEST_IMG_EDIT_ONE_STEM", NULL,"STEM", // Title / attribution - "ImgAct","FileImg","TitImg",false); + "ImgAct","FilImg","TitImg",false); /***** Feedback *****/ fprintf (Gbl.F.Out,"