Creative Commons License R.Muralikrishnan, MPI for Empirical Aesthetics. This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Licence.
##############################################################################
##                                                                          ##
##  KleistRead : Visual Study with Natural Reading task followed by a       ## 
##                  longish Radio Button Questionnaire                      ##
##                                                                          ##
##             Experiment Script for use with Presentation                  ##
##                       Author: R. Muralikrishnan                          ##
##                                                                          ##
##############################################################################

##############################################################################
# Scenario Description Language (SDL) Header Part
##############################################################################

# These button codes have to correspond to those set in 'Settings -> Response'
active_buttons = 3;      # There are 3 active buttons defined in 'Settings -> Response'
button_codes = 1,2,3;    # These are the codes of those buttons

response_matching = simple_matching;  # Enables features not in legacy_matching

# Only those button presses that one expects are logged; not all
response_logging = log_active;    

### NO EEG Triggers

# Default Settings for Font, FG and BG Colours etc.
default_background_color = "236,237,229"; # Colour-picked from Open-Bood-N.png #ECEDEF"232, 240, 247"; # E8 F0 F7  # An off-bluish background  # RGB codes in decimal; 000 => Black
default_font = "Verdana";
default_font_size = 24;
default_text_color = "255, 255, 255"; # White
default_text_align = align_center;

default_deltat = 0;
default_picture_duration = next_picture; /* This implies that all pictures ...
/...are shown until the next picture is shown, unless otherwise specified */

#default_all_responses = false;

#Yoga 2 Tablet: 1920 x 1200

# Blues

# 3F 7E BC      63, 126, 188 Font Colour on Highlight
# 63 97 CB      99, 151, 203
# 9C BD DE     156, 189, 222 Default Button Colour
# C2 D7 EB     194, 215, 235 
# D5 E3 F1     213, 227, 241

# E8 F0 F7     232, 240, 247 Default Background Colour

# 00 66 99     000, 102, 153  # An off-bluish tint

# Green
# ED FA CF        237, 250, 207
# 13 88 08         19, 136, 8   India Green
# 98 CF 2D

# Deep Saffron
# F4 C4 30       255, 153, 51 

# FF CC 00

##############################################################################
# Scenario Description Language (SDL) Part
##############################################################################

begin;

# ============================
# SDL Variable Declarations: -
# ============================

# ==============================
# Picture Stimuli Definitions: - Everything that is shown, including text!
# ==============================

line_graphic {
   coordinates = -600, -72, -600, 71;      
   coordinates = 600, -72, 600, 71;
   coordinates = -600, -70, 600, -70;
   coordinates = -600, 70, 600, 70;
   line_width = 4;
   line_color = 255, 255, 255;
} Lin_Border;

bitmap {filename = "Pointer-Arrow-Blue.png"; transparent_color = "0,0,0"; scale_factor = 1;} Bmp_Pointer;  #232,240,247

bitmap {filename = "MPI-Minerva-BlueBackground_Unsharp_Masked-N.png"; scale_factor = 0.4; } Bmp_Minerva;

ellipse_graphic { ellipse_width = 30; ellipse_height = 30; color = "232,240,247";} Gfx_Pointer;


array
{
	LOOP $i 40; 
		text {caption = " "; font_size = 24; background_color = "156,189,222"; width = 340; height = 50;};
	ENDLOOP;
} Txt_Array_Menu_Options;  # This constructs an SDL array of twenty Txt Picture Parts that can be dynamically added to Picture definitions.
                           # Declaring this inside the Picture definition doesn't work

array
{
	LOOP $i 40; 
		text {caption = " "; font_size = 24; font_color = "255,255,255"; background_color = "232,240,247"; width = 340; height = 50;};
	ENDLOOP;
} Txt_Array_Menu_Options_Placeholder;  # This constructs an SDL array of twenty Txt Picture Parts that can be dynamically added to Picture definitions.
                           # Declaring this inside the Picture definition doesn't work

array
{
	LOOP $i 40; 
		box {color = "255,255, 255"; width = 344; height = 54;};
	ENDLOOP;
} Box_Array_Menu_Options;  # This constructs an SDL array of twenty Txt Picture Parts that can be dynamically added to Picture definitions.
                           # Declaring this inside the Picture definition doesn't work

array
{
	LOOP $i 40; 
		box {color = "255,255, 255"; width = 344; height = 54;};
	ENDLOOP;
} Box_Array_Menu_Options_Placeholder;  # This constructs an SDL array of twenty Txt Picture Parts that can be dynamically added to Picture definitions.
                           # Declaring this inside the Picture definition doesn't work


bitmap {filename = "Next1.png"; transparent_color = "0,0,0"; scale_factor = 1;} Bmp_Continue; 
bitmap {filename = "Reconsider1.png"; transparent_color = "0,0,0"; scale_factor = 1;} Bmp_Replay; 
#bitmap {filename = "go-next.png"; transparent_color = "0,0,0"; scale_factor = 1;} Bmp_Play; 
#bitmap {filename = "go-next.png"; transparent_color = "0,0,0"; scale_factor = 1;} Bmp_Pause; 
#bitmap {filename = "go-next.png"; transparent_color = "0,0,0"; scale_factor = 1;} Bmp_Forwards; 
#bitmap {filename = "go-next.png"; transparent_color = "0,0,0"; scale_factor = 1;} Bmp_Backwards; 

bitmap {filename = "Speaker3.png"; transparent_color = "0,0,0"; scale_factor = 1;} Bmp_Audio_Playing; 


### ADDED for MusikInter2D

	bitmap {filename = "Canvas.png"; scale_factor = 1; preload = true; } Bmp_Canvas;  #White canvas with blue axes

	text { caption = "Canvas X Left Text"; font_size = 18; font_color = "63,126,188";} Txt_Canvas_X_Left;   
	text { caption = "Canvas X Right Text"; font_size = 18; font_color = "63,126,188"; } Txt_Canvas_X_Right;   
	text { caption = "Canvas Y Top Text"; font_size = 18; font_color = "63,126,188"; }  Txt_Canvas_Y_Top;   
	text { caption = "Canvas Y Bottom Text"; font_size = 18; font_color = "63,126,188"; } Txt_Canvas_Y_Bottom;   

	bitmap {filename = "Pointer-Circle-Orange.png"; transparent_color = "0,0,0"; scale_factor = 1; preload = true; } Bmp_Placeholder;

	bitmap {filename = "Slider-X-Blue.png"; transparent_color = "0,0,0"; scale_factor = 1; preload = true; } Bmp_Slider_X;

	bitmap {filename = "Slider-Y-Blue.png"; transparent_color = "0,0,0"; scale_factor = 1; preload = true; } Bmp_Slider_Y;
	
   bitmap {filename = "Highlight-Circle.png"; transparent_color = "0,0,0"; scale_factor = 1; preload = true; } Bmp_Highlight_Radio_Button;
###

array
{
	LOOP $i 100;
		ellipse_graphic { ellipse_width = 40; ellipse_height = 40; color = 255, 255, 255;};# IMPORTANT: Ensure that the ellipse width and height specified here are greater than the 
                                                                                         #            values supplied as parameters for the get_rgb_pixel_color method below.  Otherwise it
                                                                                         #            would break the code, because we'd be checking pixels that don't exist!!!
	ENDLOOP;
} Gfx_Array_Radio_Buttons;


array
{
	LOOP $i 20; 
			text {caption = " "; font = "Merriweather"; font_color = "63,126,188"; font_size = 18;};
	ENDLOOP;
} Txt_Array_Radio_Button_Left_Labels;  # This constructs an SDL array of twenty Txt Picture Parts that can be dynamically added to Picture definitions.
                                       # Declaring this inside the Picture definition doesn't work
                                       # Nesting of loops seems to be okay, but in PCL, we couldn't access Txt_x[x][y].  Apparently, only a single dimension array encompassing everything is created in PCL.
array
{
	LOOP $i 20; 
			text {caption = " "; font = "Merriweather"; font_color = "63,126,188"; font_size = 18;};
	ENDLOOP;
} Txt_Array_Radio_Button_Right_Labels;  


### ADDED for NEO Questionnaire
# To put labels on top of each radio button (i.e., in every column)
array
{
	LOOP $i 20; 
			text {caption = " "; font_color = "63,126,188"; font_size = 18; formatted_text = true; };
	ENDLOOP;
} Txt_Array_Radio_Button_Top_Labels;  

### ADDED for NEO Questionnaire
# To show a graphical legend

box {color = "255,255,255"; width = 1608; height = 38;} Box_Progress_Bar_Border;

box {color = "156,189,222"; width = 4; height = 30;} Box_Progress_Bar;

box {color = "255,255,255"; width = 1608; height = 4;} Box_Header_Line;


text {caption = " "; font_color = "63,126,188"; text_align = align_left;} Txt_Temp;


array
{
	LOOP $i 20;
		text {caption = " "; font = "Merriweather"; font_size = 16; font_color = "36, 36, 36";#"63,126,188"; 
      text_align = align_left; max_text_width = 1600;
      formatted_text = true; };
	ENDLOOP;
} Txt_Array_Questionnaire_Texts;  

text {caption = "Hello there!"; font = "Merriweather"; font_size = 18; font_color = "36, 36, 36";#"63,126,188"; 
      text_align = align_left; max_text_width = 1600;
      formatted_text = true;
} Txt_Message;

text
{
   caption = " "; 
   font = "Merriweather"; font_color = "36,36,36"; font_size = 18; 
   text_align = align_left; max_text_width = 900;
   formatted_text = true; transparent_color = "232,240,247";  # We sometimes have a box of a different colour as the background (see below)
} Txt_Description;                                            # In that case, we want the text part to be transparent (from the default background) such that the box colour comes through.

box
{
   #color = "250,252,253"; # FAFCFD A lighter tinge of E8F0F7
   color = "236,237,229"; # Colour-picked from Open-Bood-N.png #ECEDEF
   height = 1000;
   width = 2400; # Well, yes it is beyond the monitor size...so we don't have to change it for different resolutions.
} Box_Description;


picture
{

	# This empty definition is legal.  PCL Program adds text picture parts to this dynamically.

} P_User_Interface;

picture
{
        
} P_Message;

# Screen definition for the End_Thanks trial
picture 
{ 
    text {caption = "Das war's! Vielen Dank für Ihre Teilnahme."; font_color = "63,126,188";};
    x = 0;
    y = 0;
    
    line_graphic Lin_Border;
    x = 0;
    y = 0;
} P_End_Thanks;

####  Specific for presenting Auditory Stimuli   -------------------------------
# ============================
# Sound Stimuli Definitions: - 
# ============================

sound
{
    wavefile 
    { 
        filename = "";        # PCL Program below fills the file name  
      preload = false;
    } Wav_Auditory_Stimulus;
} S_Auditory_Stimulus;

####

# Screen definition for showing a message
picture
{

	bitmap { filename = "Open-Book-N.png"; scale_factor = 0.93;};
	x = 0;
	y = 0;

	box { width = 720; height = 3; color = 210, 210, 210; }; # Header rule, left
	x = -475;
	y = 540;

	box { width = 720; height = 3; color = 210, 210, 210; }; # Header rule, right
	x = 475;
	y = 540;

	box { width = 720; height = 3; color = 210, 210, 210; }; # Footer rule, left
	x = -475;
	y = -540;

	box { width = 720; height = 3; color = 210, 210, 210; }; # Footer rule, right 
	x = 475;
	y = -540;
	
   #text { caption = " "; font = "Bookman Old Style"; font_size = 28; font_color = "63,63,63"; 
   #       background_color = "255,255,255"; transparent_color = "255,255,255"; 
   #       max_text_width = 670; width = 700; height = 1000; formatted_text = true;}Txt_Message;
   #x = 475;
   #y = 0;


} P_Blank_Page;

####  Specific for presenting Visual Stimuli   --------------------------------
# Screen definition for the trial that presents Visual Stimuli (PDF page images).
picture
{

	bitmap { filename = "Open-Book-N.png"; scale_factor = 0.93;};
	x = 0;
	y = 0;

	box { width = 720; height = 3; color = 210, 210, 210; }; # Header rule, left
	x = -475;
	y = 540;

	box { width = 720; height = 3; color = 210, 210, 210; }; # Header rule, right
	x = 475;
	y = 540;

	box { width = 720; height = 3; color = 210, 210, 210; }; # Footer rule, left
	x = -475;
	y = -540;

	box { width = 720; height = 3; color = 210, 210, 210; }; # Footer rule, right 
	x = 475;
	y = -540;

	bitmap { filename = "Blank-Page.png"; transparent_color = "255,255,255";} Bmp_Visual_Stimulus_L;
	x = -475;
	y = 0;	
	
	bitmap { filename = "Blank-Page.png"; transparent_color = "255,255,255";} Bmp_Visual_Stimulus_R;
	x = 475;
	y = 0;	

   # The white background on the text page image won't be drawn, since we've defined white colour to be transparent in the BMP definitions above.

   text { caption = " "; font = "Verdana"; font_size = 11; font_color = "0,0,0"; formatted_text = true;
          background_color = "255,255,255"; transparent_color = "255,255,255"; 
          text_align = align_center;} Txt_Footer_L;
   x = -475;
   y = -570;

   
   text { caption = " "; font = "Verdana"; font_size = 11; font_color = "0,0,0"; formatted_text = true;
          background_color = "255,255,255"; transparent_color = "255,255,255"; 
          text_align = align_center;} Txt_Footer_R;
   x = 475;
   y = -570;


   text { caption = "Drücken Sie die rechte Pfeiltaste, wenn Sie den Text zu Ende gelesen haben."; font = "Verdana"; font_size = 11; font_color = "0,0,0"; formatted_text = true;
          background_color = "255,255,255"; transparent_color = "255,255,255"; 
          text_align = align_center;} Txt_Footer;
   x = 475;
   y = -520;

} P_Visual_Stimulus;

####

# Screen definition for getting a text input from the participant keyboard
picture
{
	text { caption = "Wer ist Ihrer Meinung nach der Autor / die Autorin des Textes?"; font = "Merriweather"; font_color = "36,36,36"; max_text_width = 1500; font_size = 18; formatted_text = true;} Txt_Instruction1;
	x = 0;
	y = 120;

	box {color = "255,255,255"; width = 410; height = 80;} Box_Keyboard_Input; # Box First, Textfield next...otherwise, box sits on top, and we won't be able to see the text input.
	left_x = -205; # Left_x and top_y used to ensure that the text is left aligned...using x,y, it would be centred!
	top_y = 25;

	text{ caption = "|"; max_text_width = 400; max_text_height = 70; font = "Merriweather"; font_size = 18; font_color = "63,126,188";  background_color = "255,255,255"; text_align = align_left;} Txt_Keyboard_Input;
	left_x = -200;
	top_y = 20;

	text { caption = "Bitte einfach eintippen und <font color='255,153,51'><b>Enter</b></font> drücken, um fortzufahren."; max_text_width = 1200; font = "Merriweather"; font_size = 18; font_color = "63,126,188"; formatted_text = true;} Txt_Instruction2;
	x = 0;
	y = -250;
 
} P_Keyboard_Input;

 

#=====================
# Trial Definitions: -
#=====================
trial
{
    trial_duration = 10;
    all_responses = false;
    
    stimulus_event
    {
        picture {};     # This is the default picture, which is nothing!
        code = "CLS";   # Comment this out to avoid seeing this in the logfile.
    };
} T_Blank_Screen;

# Definition of the Trial that acts as the main user interface, to show messages as well as to get user input.
trial
{
                          # monitor_sounds = true (default); 
                          # That is, interacting with monitor_sounds=false in T_Auditory_Stimulus,
                          # until the sound which might be playing ends, nothing should happen, and this trial doesn't end!!!
                          # Which is exactly the behaviour we want: the sound starts playing, and this trial starts showing the interface...
                          # BUT, nothing happens further until the sound ends.
    stimulus_event
    {
        picture P_User_Interface;  # No event code, since this trial will be presented in an infinite loop, and the picture parts will keep changing dynamically.
    } E_User_Interface;

} T_User_Interface;

# Definition of the Trial that logs the menu choice / radio buttons / canvas location selected by the user.
trial
{
	stimulus_event
	{
		nothing{};
		code = " ";    # PCL Program Below changes this dynamically to save user choice in the log file in a meaningful manner.
		
	} E_Log_User_Choice;
} T_Log_User_Choice;

# Definition of the Trial to show a message.
trial
{

	trial_duration = 1500;
	

    stimulus_event
    {
        picture P_Message;     # This is the default picture, which is nothing!
        code = "Message";   # Comment this out to avoid seeing this in the logfile.
    };
} T_Message;

# Definition of the Trial to play the Auditory Stimulus
trial
{
    trial_duration = stimuli_length;
    all_responses = false;
    #trial_type = specific_response;
    #terminator_button = 2;            

    #monitor_sounds = false;           # If false, then, any sound that was/has started playing when prior to/during this trial
                                       # would continue to be played even if this trial ends.
                                       # This means that, once this trial starts and the music starts playing, the control immediately
                                       # whatever is next.  In our case, the screen with multiple menu boxes shows up immediately.
                                       # However, no responses / button-clicks will be recordable until the sound ends... 
                                       # thanks only to monitor_sounds = true (default) in T_User_Interface!!!.
                                       # Which is what the behaviour that one wants here.

    stimulus_event
    {
        sound S_Auditory_Stimulus;
        code = "";                        # PCL Program sets Event code
    } E_Auditory_Stimulus;
	
} T_Auditory_Stimulus;

####


####  Specific for presenting Visual Stimuli   --------------------------------
# Definition of the Trial to present Visual Stimuli
trial
{
    trial_duration = forever;
    trial_type = specific_response;
    terminator_button = 3;            # Right-Arrow key

    stimulus_event
    {
        picture P_Visual_Stimulus;
        code = "";                       # PCL Program sets Event code
    } E_Visual_Stimulus;

} T_Visual_Stimulus;

####

# Definition of the Trial to end the session
# Operator Controlled
trial
{
    trial_duration = 4500;

    stimulus_event
    {
        picture P_End_Thanks;
        code = "End of Session!";
    };
    picture P_End_Thanks;
} T_End_Thanks;

##############################################################################
# Presentation Control Language (PCL) Program Part
##############################################################################

begin_pcl;

# Global PCL-Variables
mouse Dev_Pointer = response_manager.get_mouse(1);       # Works for either using Mouse interface or Touch interface.
                                                         # For an actual mouse, select Mouse->Use Mouse in the Response Panel settings.
                                                         # For using touch interface, select Pointing Device-> Use Mouse instead.

# When we switched to Touch Interface, the coordinates sent by the Pointer Interface was not matching the screen size.#
# Instead of relying solely upon the hand-tailored settings for minimum and maximum coordinates in the Response Devices panel,
# it's better if we ensured that these values matched the actual screen siye.  We do that here.  
# Also, the 'restricted' flag we had set in the settings (essential for a reliable touch interface) is explicitly set here.
# Set the axis position values to match the visual stimuluis location coordinate system (see Presentation Documentation -> Pointing Device Response Device)
int V_Display_Width = int(display_device.custom_width());    # Width of the display device.
int V_Display_Height = int(display_device.custom_height());
Dev_Pointer.set_min_max(1, -V_Display_Width/2, V_Display_Width/2);
Dev_Pointer.set_min_max(2, -V_Display_Height/2, V_Display_Height/2);
Dev_Pointer.set_restricted(1,true);
Dev_Pointer.set_restricted(2,true);


int V_Pointer_Position_X = Dev_Pointer.x();
int V_Pointer_Position_Y = Dev_Pointer.y();

int N_of_Responses = response_manager.total_response_count(1);

int N_of_Menubox_Columns;  # That is, number of options presented horizontally (separated on the x axis, but identical y axis).
int N_of_Menubox_Rows;     # That is, number of options presented vertically (separated on the y axis, but identical x axis).

int V_Origin_X = 0;
int V_Origin_Y = 0;

int V_Box_Width = 300; 
int V_Box_Height = 60;
int V_Box_Gap = 70;

int V_Button_Width = 30;
int V_Button_Height = 30;
int V_Button_Gap = 40;

int V_Button_Gap_Vertical = 50;  # Newly introduced in MusikInter2D to control the vertical gap between radio button rows independently from their horizontal gap

int V_L, V_R, V_T, V_B; # Left, Right, Top and Bottom Co-ordinates

int V_First_Box_Centre_X, V_First_Box_Centre_Y;   # The centre of the first menu box on screen, calculated taking into account the number of row and columns
#int V_First_Box_Left_X, V_First_Box_Top_Y;

int V_First_Button_Centre_X, V_First_Button_Centre_Y;  # The centre of the first radio button on screen, calculated taking into account the number of row and columns

array<string> A_Menu_Options[0];  # 1 D Array of Menu Options to show
array<int> A_Menu_Coordinates[0][2]; # 2 D Array of Coordinates of the Menu Options: N_of_Menu Options x 2
# i => Current Menubox Counter
# [i][1] = x coordinate (centre)
# [i][2] = y coordinate (centre)

string V_Menu_Title;
string V_Error_Message;

int V_Menu_Choice_Clicked = 0;
int V_Menu_Box_Hovered_Over = 0;
int V_Current_Box = 1;

string V_Menu_Choice_Clicked_Text;
string V_Canvas_Coordinates_Clicked;
int V_Supplementary_Menu_Choice_Clicked = 0;
#string V_Supplementary_Menu_Choice_Clicked;

int V_Last_Calculated_Centre_X;
int V_Last_Calculated_Centre_Y;
int V_Last_Created_Box;

int N_of_Menubox_Columns_Last_Row;
bool V_Last_Row_Non_Standard = false;

array<string> A_Radio_Button_Options[0][0];  # 2 D Array of point-scale extremes, such as {Agree, Disagree} or {Acceptable, Not Acceptable}. 
# i => Row Number Counter
# [i][1] = Left Label (say Agree)
# [i][2] = Right Label (say Disagree)

array<int> A_Radio_Button_Coordinates[0][2]; # 2 D Array of Coordinates of the Radio Button Options for a given x-point-scale.
# i => Current Button Counter
# [i][1] = x coordinate (centre)
# [i][2] = y coordinate (centre)

int N_of_Radio_Button_Rows;
int N_of_Radio_Button_Columns;
int V_Current_Button = 1;
int V_Radio_Button_Clicked;
int V_Radio_Button_Hovered_Over = 0;

int V_Pointer_Part_Index;

### ADDED for MusikInter2D
int V_Slider_X_Part_Index;
int V_Slider_Y_Part_Index;


bool V_Audio_Is_Playing = false;
int V_Audio_Playing_Part_Index;
bool V_Highlight_On_Hover = true;

array<int> A_Radio_Buttons_Selected[0][3];
# 2 D array of N_of_Radio_Button_Rows x 3
# i => Row Number Counter
# [i][1] == V_Button_Index_In_Current_Row ===> This is the one that the experiment will use ultimately.
# [i][2] == V_Button_Index_Absolute...that is the continuous button numbers we generated...V_Current_Button
# [i][3] == Previously Selected V_Button_Index_In_Current_Row ...
            # This is just for the sake of having a record of what was selected before, if we are interested in the first choice that participants made.
            # We don't use it to change attributes etc.

string V_Description;
int V_Hash_Index;
array<string> A_Description[0];

array<string> A_Questionnaire_Texts_Per_Page[0][2];
# This array contains L-R pairs in 2D ... as in [x][1] = left label (=Q.No.) and [x][2] = right label (=Text)
array<string> A_Questionnaire_Texts[0];
string V_Questionnaire_Texts; # We'll just include all the questionnaire texts on one line in a separate input file, get the line from the file, split it based on #, and save the elements in the array above to use later.
int V_Questionnaire_Text_X;
array<string> A_Temp[0];
# Since the split function doesn't seem to be happy with anything other than a 1D array,
# we first split the pairs into that array, and add it into the 2D array above.


int N_of_Questionnaire_Pages;
int N_of_Questions_Per_Page;
int V_Current_Questionnaire_Page;  

int V_Current_Row; # The row in which the current button is located.
int V_Button_Index_In_Current_Row;  # So this will always be 1 to N_of_columns for each row, unlike V_Current_Button, which is continuous...and equal to N_of_rows x N_co_columns.

rgb_color RGB_Current_Button_Colour;
#int V_R_Byte = RGB_Current_Button_Colour.red_byte();
#int V_G_Byte = RGB_Current_Button_Colour.green_byte();
#int V_B_Byte = RGB_Current_Button_Colour.blue_byte();      # !(V_R_Byte == 255 && V_G_Byte == 0 && V_B_Byte == 0)

rgb_color RGB_Default_Button_Colour = rgb_color(255,255,255,255);   # Default colour of radio buttons when not hovered over or clicked.
rgb_color RGB_Hovered_Button_Colour = rgb_color(19,136,8,255);   # Colour of radio buttons when hovered over, but not clicked.
rgb_color RGB_Clicked_Button_Colour = rgb_color(255,153,51,255);     # Colour of radio buttons when clicked.  

rgb_color RGB_Default_Menu_Font_Colour = rgb_color(255,255,255,255);   # Default colour of menu box text when not hovered over or clicked.
rgb_color RGB_Hovered_Menu_Font_Colour = rgb_color(63,126,188,255);   # Default colour of menu box when not hovered over or clicked.

rgb_color RGB_Default_Menu_BG_Colour = rgb_color(156,189,222,255);   # Colour of menu box text background when hovered over and / or clicked.
rgb_color RGB_Hovered_Menu_BG_Colour = rgb_color(237,250,207,255);   # Colour of menu box when hovered over and / or clicked.

rgb_color RGB_Dimmed_Menu_BG_Colour = rgb_color(232,240,247,255); # Colour of menu box text background when dimmed (while providing supplementary menu choice, for instance). 

# Fourth value in colour = Alpha; Alpha = 0 => Fully transparent; Maximum alpha 255 => Fully opaque.

bool V_Selection_Completed = true; # Flag to indicate whether at least one radio button per row has been selected.
int V_Original_Part_Count;
int V_New_Part_Count;
bool V_Present_Supplementary_Menu = true;   # Flag to indicate whether the menu boxes can be presented or not based on whether radio button selection is complete or not.


# Specific for presenting a Progress Bar
int V_Progress_Bar_Width;
int V_Progress_Bar_X = 0;

###################################################
# PCL Subroutines to accomplish various functions
###################################################

# Subroutine to construct menu boxes
# ==================================

sub int
	Q_Construct_Menu_Boxes
	begin
		

		if A_Menu_Options.count() > 0 then
			
			loop int V_Row = 0 until V_Row == N_of_Menubox_Rows begin
				
				loop int V_Column = 0 until V_Column == N_of_Menubox_Columns begin
					
				
					A_Menu_Coordinates[V_Current_Box][1] =  V_First_Box_Centre_X + (V_Box_Width + V_Box_Gap)*V_Column;  # x will different for different columns; for a given row, x will be identical.
					A_Menu_Coordinates[V_Current_Box][2] =  V_First_Box_Centre_Y - (V_Box_Height + V_Box_Gap)*V_Row;    # y will different for different rows; for a given column, y will be identical.
				   
				   V_Last_Calculated_Centre_Y = A_Menu_Coordinates[V_Current_Box][2]; # Useful when a last row with a non-standard number of columns need to be generated in a second step.

		         Txt_Array_Menu_Options[V_Current_Box].set_caption(A_Menu_Options[V_Current_Box]);
		         Txt_Array_Menu_Options[V_Current_Box].redraw();
		
					P_User_Interface.add_part(Box_Array_Menu_Options[V_Current_Box], A_Menu_Coordinates[V_Current_Box][1], A_Menu_Coordinates[V_Current_Box][2]); 
					P_User_Interface.add_part(Txt_Array_Menu_Options[V_Current_Box], A_Menu_Coordinates[V_Current_Box][1], A_Menu_Coordinates[V_Current_Box][2]); 
					
					# If necessary, add images to the buttons
					if A_Menu_Options[V_Current_Box] == "Weiter" then
						P_User_Interface.add_part(Bmp_Continue, A_Menu_Coordinates[V_Current_Box][1]+V_Box_Width/2-30, A_Menu_Coordinates[V_Current_Box][2]);
					end;

					if A_Menu_Options[V_Current_Box] == "Replay" then
						P_User_Interface.add_part(Bmp_Replay, A_Menu_Coordinates[V_Current_Box][1]-V_Box_Width/2+30, A_Menu_Coordinates[V_Current_Box][2]);
					end;
					
					
					V_Last_Created_Box = V_Current_Box; # Necessary to construct a non-standard row, if any.
			      
					V_Current_Box = V_Current_Box + 1; # Note that this is a continuous counter, unlike V_Column / V_Row;  
                                                  # It cannot be straightforwardly derived from either of them for a given run; 
                                                  # Its ultimate value (i.e., at the end of the nested RowxColumn loops) would correspond to A_Menu_Options.count().
					
					
					V_Column = V_Column + 1;
					
				end;
				
				V_Row = V_Row + 1;
			
			end;
		
      end;

	return 0;

end;

# Subroutine to polling the mouse and detect menu choice
# ======================================================
sub int
	Q_Poll_Device_For_Menu_Choice
	begin
		
		# Start polling the device incessantly until we have a response
		loop N_of_Responses = response_manager.total_response_count(1) until false
		begin

	####### Specific for the MusiTab Scenario			
			# If there is some auditory stimulus playing, the menu choices will show up (in the next step) but won't
			# let the user select them yet (thanks to monitor_sound = true (default) in T_User_Interface.
			# Therefore, we want to present an image of a speaker as long as the audio is still playing;
			# but once the audio ends, the speaker image should vanish, without affecting any other behaviour.
			# The following check, and the one after the presentation of T_User_Interface accomplish this.
			
			# If true, the control will get into this only the first time the infinite loop runs, 
         # for we are resetting the flag in the if check after T_User_Interface.present(), for by then the audio should have ended.
			if V_Audio_Is_Playing then

   #### ADDED for MUSIKINTER: We don't want the cursor on screen when the audio is playing				
	# ALT 1: We remove the cursor when the audio was playing. We'll add it back right after the audio is over, but before the polling loop (see below).
   #        P_User_Interface.remove_part(V_Pointer_Part_Index);
   # ALT 2: We simply reload the cursor to a blank one.  This will be automatically changed to the usual one when the polling starts.  Nothing else needs to be done.
				Bmp_Pointer.set_filename("Pointer-Blank.png");
				Bmp_Pointer.load();
				
				P_User_Interface.add_part(Bmp_Audio_Playing, 0, -500);        # Add a speaker image.
				V_Audio_Playing_Part_Index = P_User_Interface.part_count();
			end;			
	####### Specific for the MusiTab Scenario	
	
			# Show the Menu Screen
			T_User_Interface.present();
			
   ####### Specific for the MusiTab Scenario	
         if V_Audio_Playing_Part_Index != 0 then
				P_User_Interface.remove_part(V_Audio_Playing_Part_Index);     # Remove the speaker image added above.
				V_Audio_Playing_Part_Index = 0;                               
				V_Audio_Is_Playing = false;    # If we are here, that means that the audio has ended.  
                                           # Reset the flag to reflect this, so that the next run 
                                           # of the infinite loop won't run into the check above.

   #### ADDED for MUSIKINTER: We don't want the cursor on screen when the audio is playing.
   # ALT 1: We removed the cursor when the audio was playing (see above).  Now we add it back
	#			P_User_Interface.add_part(Bmp_Pointer, 0,-400);
	#			V_Pointer_Part_Index = P_User_Interface.part_count(); # Since we added the pointer as the last part, the part_count will also be the index of the last part (pointer). 
   


	
		      if response_manager.total_response_count(1) > N_of_Responses then # Participants clicked on the menu boxes when the Audio was still playing;
				# Just in case when people touch one of the buttons when the audio was still playing,
            # once the audio is over, that last location (if it happens to be a button) gets highlighted...and treated as a button selection.
            # This behaviour would have been correct usually, but for the current scenario,
            # with audio + menu, but selection enabled only after the audio ends,
            # this behaviour is not correct. Because it would almost be like priming to select that button.
            # So we make sure to update the N_of_Responses with the current count and set a flag not to highlight buttons (...reset later).
					  
                  N_of_Responses = response_manager.total_response_count(1);
				      V_Highlight_On_Hover = false;
				# Basically, this achieves two things: 1. Do not recognise the box hovered/pressed when the audio was still playing as the response
				#                                      2. Do not highlight it until the user chooses it or any other box...and then highlighting would be on as usual.
				
            end;
				# Poll device and store the current pointer position, which is the last position when the audio ends.
				# This could then be checked (see below) to reset the highlighting flag to true.
				Dev_Pointer.poll();
				V_Pointer_Position_X = Dev_Pointer.x();
				V_Pointer_Position_Y = Dev_Pointer.y();
						
         end;		

			# Check if the position of the pointer has changed from what it was when the audio ended; 
			# If so, reset the V_Highlight_On_Hover to true, so that hovering over the menuboxes from now on will highlight them.
			Dev_Pointer.poll();
			if (V_Pointer_Position_X != Dev_Pointer.x() || V_Pointer_Position_Y != Dev_Pointer.y()) then
				V_Highlight_On_Hover = true;
			end;
   ####### Specific for the MusiTab Scenario	

         # Poll device and change pointer position accordingly
			Dev_Pointer.poll();
			V_Pointer_Position_X = Dev_Pointer.x();
			V_Pointer_Position_Y = Dev_Pointer.y();
     

			#NO VISIBLE CURSOR on TOUCHSCREEN#         
         P_User_Interface.set_part_x(V_Pointer_Part_Index, V_Pointer_Position_X); # Alternativerly, the pointer's part number will be A_Menu_Options.count()*2+1 = (No.of.Txt + No.of.Box) + 1 => (No. of elements in Menu Options Array x 2) + 1
			#NO VISIBLE CURSOR on TOUCHSCREEN#         
         P_User_Interface.set_part_y(V_Pointer_Part_Index, V_Pointer_Position_Y); # Because we added the pointer as the last part, just before entering this subroutine

         # Initialise/Reset the pointer to the default
			#NO VISIBLE CURSOR on TOUCHSCREEN#         
         Bmp_Pointer.set_filename("Pointer-Arrow-Blue.png");   # Reset the pointer.  Resetting things anywhere else, either in an else case below or out of the loop below doesn't work.
			#NO VISIBLE CURSOR on TOUCHSCREEN#         
         Bmp_Pointer.load();                                    # In all other cases, some or all of the correct behaviour is lost.  So we do it here.
			
			
			# Initialise/Reset the text attributes to the default values
			Txt_Array_Menu_Options[V_Menu_Box_Hovered_Over].set_font_color(RGB_Default_Menu_Font_Colour);
			Txt_Array_Menu_Options[V_Menu_Box_Hovered_Over].set_background_color(RGB_Default_Menu_BG_Colour);
			Txt_Array_Menu_Options[V_Menu_Box_Hovered_Over].redraw();	
		    
         # Calculate the left, right, bottom and top extremes, considering we are on a menu box	
			V_L = V_Pointer_Position_X - V_Box_Width/2; 
			V_R = V_Pointer_Position_X + V_Box_Width/2;
			V_B = V_Pointer_Position_Y - V_Box_Height/2;
			V_T = V_Pointer_Position_Y + V_Box_Height/2;

         # Keep check if we are hovering over one of the menu boxes
			loop V_Current_Box = 1  until V_Current_Box > A_Menu_Options.count() begin
				
				if (V_L <= A_Menu_Coordinates[V_Current_Box][1] && 
					 V_R >= A_Menu_Coordinates[V_Current_Box][1] && 
					 V_B <= A_Menu_Coordinates[V_Current_Box][2] && 
					 V_T >= A_Menu_Coordinates[V_Current_Box][2]) then 
					
					if V_Highlight_On_Hover then
						# If so, change its attributes and the pointer
						Txt_Array_Menu_Options[V_Current_Box].set_font_color(RGB_Hovered_Menu_Font_Colour);
						Txt_Array_Menu_Options[V_Current_Box].set_background_color(RGB_Hovered_Menu_BG_Colour);
						Txt_Array_Menu_Options[V_Current_Box].redraw();
               end;

					#NO VISIBLE CURSOR on TOUCHSCREEN#               
               Bmp_Pointer.set_filename("Pointer-Hand-Orange.png");
					#NO VISIBLE CURSOR on TOUCHSCREEN#               
               Bmp_Pointer.load();
					
					# If there was a click response when inside the menubox borders, this means the user has chosen the option; return that as the result 					
					if (response_manager.total_response_count(1) > N_of_Responses) then 

						V_Menu_Choice_Clicked = V_Current_Box; 
						
						V_Selection_Completed = true;
										
						E_Log_User_Choice.set_event_code("|Menu Choice| " + A_Menu_Options[V_Menu_Choice_Clicked] + " selected. |");
						T_Log_User_Choice.present();
				
						return V_Menu_Choice_Clicked;
										
					else
						# It was just a case of hovering over the menubox, but not selecting it.  Store this information to restore attributes for the menubox later.
						V_Menu_Box_Hovered_Over = V_Current_Box;
						
					end;

				end;				
				
				V_Current_Box = V_Current_Box + 1;
				
			end;
			
			
	###### Specially for MusiTab: To enable abruptly quitting the experiment altogether (after a confirmation)
		  # In the 'Play'screen between two musical pieces, when the user clicks at a particular location on screen
		  # (not marked in any specific way, but the experimenter is aware of this location),
        # then a special value (999) is returned, which then enables asking for confirmation whether to quit or not.
        # See in the main experiment loop, where we handle this exception.  Look for the check involving 999. 
  
         if (response_manager.total_response_count(1) > N_of_Responses &&
             A_Menu_Options[1] == "Abspielen" && 
             V_Pointer_Position_X > -100 && V_Pointer_Position_X < 100 && 
             V_Pointer_Position_Y > 500) then
	          
	          return 999;
	      end;
	      


         # Update our record of the total number of responses.
			N_of_Responses = response_manager.total_response_count(1);   # This line solved the issue of selecting an option hovered over, after a click outside the buttons.        

		end;
		

	return 0;
end;

	


# Subroutine to show the menu boxes and return the user choice
# ============================================================

sub int
	Q_Show_Menu_Boxes(array<string,1> AL_Input_Array)  # Note that we are not using pass-by reference;  That would have been array<string,1>& AL_Input_Array;  
                                                                  # Other than that, there won't be much of a difference in the code here;
                                                                  # However, we are using pass-by values, because, when calling the function, we just need to supply the values;
                                                                  # No need to declare an array, pass that, and then do an explicit resize etc.
                                                                  # The less the experimenter needs to adapt things, the better.  So, pass-by values good for us here.
	begin
		
		A_Menu_Options.assign(AL_Input_Array); # Copy contents into the global array.
		A_Menu_Coordinates.resize(A_Menu_Options.count() * 2);  # Make place to save x,y coordinates for each option...therefore * 2.

		N_of_Menubox_Columns = 5; # We specify that there can be a maximum of 3 columns in a row; anything more, and there will be more rows.  

		if N_of_Menubox_Columns > A_Menu_Options.count() then N_of_Menubox_Columns = A_Menu_Options.count(); end;  # Just in case there are only 2 or less options supplied, things should still work.

		N_of_Menubox_Rows = (A_Menu_Options.count() - 1)/N_of_Menubox_Columns + 1; # The number of rows will be based on whether there are more boxes to fit than on a single row (of n boxes);

		N_of_Menubox_Columns_Last_Row =  mod((A_Menu_Options.count() - (N_of_Menubox_Rows - 1)*N_of_Menubox_Columns), N_of_Menubox_Columns);
		
		V_Last_Row_Non_Standard = false;
	  
		if (N_of_Menubox_Rows > 1 && N_of_Menubox_Columns_Last_Row != 0) then V_Last_Row_Non_Standard = true; end; # If we have more than one row, and the last row works out to be a non-standard one, then set a flat to that effect.

		V_First_Box_Centre_X = V_Origin_X + ((V_Origin_X - V_Box_Width/2 - V_Box_Gap/2)*(N_of_Menubox_Columns - 1)); # We use the centre as the anchor.
		V_First_Box_Centre_Y = V_Origin_Y + ((V_Origin_Y + V_Box_Height/2 + V_Box_Gap/2)*(N_of_Menubox_Rows - 1));
		
		#V_First_Box_Left_X = (V_Origin_X - V_Box_Width/2) + ((V_Origin_X - V_Box_Width/2 - V_Box_Gap/2)*(N_of_Menubox_Columns - 1));  # If we want to use the top-left corner as the anchor.
		#V_First_Box_Top_Y = (V_Origin_Y + V_Box_Height/2) + ((V_Origin_Y + V_Box_Height/2 + V_Box_Gap/2)*(N_of_Menubox_Rows - 1));

		if (V_Last_Row_Non_Standard == true) then  # We have more than one row, and the last row is having a non-standard number of columns;

			V_Current_Box = 1;
			N_of_Menubox_Rows = N_of_Menubox_Rows - 1;               # We have a non-standard row to construct, which we will do in a second step.  So now, it is one less.
			Q_Construct_Menu_Boxes();                         # Construct the rows except the one with a non-standard number of columns;
			
			# Tweak parameters such that the non-standard row can be constructed.
			
			V_Current_Box = V_Last_Created_Box + 1;                  # The current box is not going to be the first, but follows the last created one.
			N_of_Menubox_Rows = 1;                                   # When we are here, it is always only one (non-standard row) we need to construct.
			N_of_Menubox_Columns = N_of_Menubox_Columns_Last_Row;    # Depends on the value set for N_of_Menubox_Columns above
			V_First_Box_Centre_X = V_Origin_X + ((V_Origin_X - V_Box_Width/2 - V_Box_Gap/2)*(N_of_Menubox_Columns - 1)); # Newly calcuated displaced X; using the standard formula though.		
			V_First_Box_Centre_Y = V_Last_Calculated_Centre_Y - (V_Box_Height + V_Box_Gap);   # V_Last_Calculated_Centre_Y stored in the previous run of Q_Construct_Menu_Boxes.
																														 # The standard formula doesn't work here though...because we need to displace the origin itself.
																														 # Changing the origin and using the formula would also not do, because in the standard formula, y is not changed if Nr=1. And here Nr=1, but not the first row. 
			Q_Construct_Menu_Boxes();
			
		else  # We have one or more rows, all with a standard number of columns; the easy option...all boxes constructed in one go.

			V_Current_Box = 1;
			Q_Construct_Menu_Boxes();

		end;

      # Add the pointer to the screen
		#NO VISIBLE CURSOR on TOUCHSCREEN#      
      P_User_Interface.add_part(Bmp_Pointer, 0,-400);
		#NO VISIBLE CURSOR on TOUCHSCREEN#      
      V_Pointer_Part_Index = P_User_Interface.part_count(); # Since we added the pointer as the last part, the part_count will also be the index of the last part (pointer). 

		# Initialise
		V_Menu_Box_Hovered_Over = 1;
			
		return Q_Poll_Device_For_Menu_Choice();

	return 0;
	
end;



# Subroutine to construct radio button rows
# =========================================

sub int
	Q_Construct_Radio_Buttons
	begin
		
		if A_Radio_Button_Options.count() > 0 then
			
			loop int V_Row = 0 until V_Row == N_of_Radio_Button_Rows begin
				
				loop int V_Column = 0 until V_Column == N_of_Radio_Button_Columns begin
					
			
					A_Radio_Button_Coordinates[V_Current_Button][1] =  V_First_Button_Centre_X + (V_Button_Width + V_Button_Gap)*V_Column;  # x will different for different columns; for a given row, x will be identical.
					A_Radio_Button_Coordinates[V_Current_Button][2] =  V_First_Button_Centre_Y - (V_Button_Height + V_Button_Gap_Vertical)*V_Row;    # y will different for different rows; for a given column, y will be identical.
				   
				   V_Last_Calculated_Centre_X = A_Radio_Button_Coordinates[V_Current_Button][1]; # Useful to put the label boxes on either side of the row of radio buttons.
				   V_Last_Calculated_Centre_Y = A_Radio_Button_Coordinates[V_Current_Button][2]; # Necessary to put buttons such as continue etc. below the row of radio buttons.
		
					P_User_Interface.add_part(Gfx_Array_Radio_Buttons[V_Current_Button], A_Radio_Button_Coordinates[V_Current_Button][1], A_Radio_Button_Coordinates[V_Current_Button][2]); 
					#P_User_Interface.add_part(Txt_Array_Menu_Options[V_Current_Box], A_Menu_Coordinates[V_Current_Box][1], A_Menu_Coordinates[V_Current_Box][2]); 

					
					#V_Last_Created_Box = V_Current_Box; # Necessary to construct a non-standard row, if any.
			      
					V_Current_Button = V_Current_Button + 1; # Note that this is a continuous counter, unlike V_Column / V_Row;  
                                                  # It cannot be straightforwardly derived from either of them for a given run; 
                                                  # Its ultimate value (i.e., at the end of the nested RowxColumn loops) would correspond to N_of_Radio_Button_Rows x N_of_Radio_Button_Columns.
					
					
					V_Column = V_Column + 1;
					
				end;
				
				
				V_Row = V_Row + 1;
                        # SPECIFIC for Q-NEO ... and by extension for scenarios that have long questions on the side	
			/**** NO TEXT LABELS for NEO Questionnaire on each row	
			
				# Add text labels for the current row of radio buttons (we do it after incrementing the row number, because the row number starts from 0).
			
			   Txt_Array_Radio_Button_Left_Labels[V_Row].set_caption(A_Radio_Button_Options[V_Row][1]);
			   Txt_Array_Radio_Button_Left_Labels[V_Row].redraw();
			   
                           Txt_Array_Radio_Button_Right_Labels[V_Row].set_caption(A_Radio_Button_Options[V_Row][2]);
			   Txt_Array_Radio_Button_Right_Labels[V_Row].redraw();			
			   
			   int V_Left_Label_X = V_First_Button_Centre_X - (V_Box_Width/2 + V_Box_Gap/2); # Default: Labels slightly apart from the buttons...good when there is no questionnaire text, but just a scale.
				#int V_Left_Label_X = V_First_Button_Centre_X - (V_Box_Width/3);               # We want the labels to be closer up to the buttons. Good when there's a text in front of the scale/button.
				#int V_Left_Label_X = V_First_Button_Centre_X - (V_Box_Width/2 + V_Box_Gap);    # We want labels quite apart from the buttons
            int V_Left_Label_Y = V_Last_Calculated_Centre_Y;
				
				int V_Right_Label_X = V_Last_Calculated_Centre_X + (V_Box_Width/2 + V_Box_Gap/2); # Default: Labels slightly apart from the buttons...good when there is no questionnaire text, but just a scale.
				#int V_Right_Label_X = V_Last_Calculated_Centre_X + (V_Box_Width/3);               # We want the labels to be closer up to the buttons. Good when there's a text in front of the scale/button.
				#int V_Right_Label_X = V_Last_Calculated_Centre_X + (V_Box_Width/2 + V_Box_Gap);    # We want labels quite apart from the buttons
				int V_Right_Label_Y = V_Last_Calculated_Centre_Y;
			
			   P_User_Interface.add_part(Txt_Array_Radio_Button_Left_Labels[V_Row], V_Left_Label_X, V_Left_Label_Y); 
			   P_User_Interface.add_part(Txt_Array_Radio_Button_Right_Labels[V_Row], V_Right_Label_X, V_Right_Label_Y); 			   
                        ****/

            # SPECIFIC for Q-NEO ... and by extension for scenarios that have long questions on the side	
	         # Instead, there's five labels right on top of the Radio Buttons, before the first row.  That's added here.
	         # If we're on row 1, we need to put a label on each of the column by calculating the coordinates
	         # using the variables V_First_Button_Centre_X, V_First_Button_Centre_X, V_Button_Wdith and V_Button_Gap
	         if V_Row == 1 then
					# First, construct an array with the labels we need on top of the first row...otherwise a loop won't be possible below.
					string V_Top_Labels = "0 1 2 3 4 5 6";
					array<string> A_Top_Labels[0];
               V_Top_Labels.split(" ", A_Top_Labels);
					
					int V_Top_Label_X;  # This will be calculated based on the width and gap variables below.
               int V_Top_Label_Y = V_First_Button_Centre_Y + 70;   # This remains the same for all the labels.]
	
					loop int V_Top_Label_Counter = 1 until V_Top_Label_Counter > A_Top_Labels.count() begin
						
						Txt_Array_Radio_Button_Top_Labels[V_Top_Label_Counter].set_caption("<b>" + A_Top_Labels[V_Top_Label_Counter] + "</b>");
						Txt_Array_Radio_Button_Top_Labels[V_Top_Label_Counter].redraw();
						
						V_Top_Label_X = V_First_Button_Centre_X + (V_Button_Width + V_Button_Gap)*(V_Top_Label_Counter - 1); 
	
						P_User_Interface.add_part(Txt_Array_Radio_Button_Top_Labels[V_Top_Label_Counter], V_Top_Label_X, V_Top_Label_Y); 
						
						V_Top_Label_Counter = V_Top_Label_Counter + 1;
						
					end;
					
				   # Present a Progress Bar
					
					P_User_Interface.add_part(Box_Progress_Bar_Border,0,-390);
					
               # These values (-900, 1700) as well as the Box_Progress_Bar_Border widths are based on the placement of the questionnaire text below.
               # Change these when that needs to be changed.

               # We do the following, because in add_part we cannot supply left_x;
               V_Progress_Bar_Width = (1600 / N_of_Questionnaire_Pages)*(V_Current_Questionnaire_Page) + 1;  # Yes, this is the main experiment loop counter!!!
					V_Progress_Bar_X = -800 + V_Progress_Bar_Width/2;
					
					Box_Progress_Bar.set_width(V_Progress_Bar_Width);			
					P_User_Interface.add_part(Box_Progress_Bar,V_Progress_Bar_X,-390);
					
					#Add a legend of the header labels, if necessary
					#Txt_Message.set_formatted_text(true);
					#Txt_Message.set_font_size(18);
					#Txt_Message.set_max_text_width(1400);
					Txt_Message.set_caption("gar nicht                                               extrem");
					Txt_Message.redraw();
					P_User_Interface.add_part(Txt_Message, (V_First_Button_Centre_X - V_Button_Gap*1.5 + Txt_Message.width()/2), V_First_Button_Centre_Y+105);
					
					P_User_Interface.add_part(Box_Header_Line, 0, V_First_Button_Centre_Y+45);
            
					
				end;
				
            # SPECIFIC for Scenarios in which there must be a question for each row of radio buttons.
            # Add the text that should appear in front of each radio button row; this is essentially the question.
            
				###Txt_Array_Questionnaire_Texts[V_Row].set_caption(A_Questionnaire_Texts[V_Row]);
				###Txt_Array_Questionnaire_Texts[V_Row].ALIGN_LEFT;
				###Txt_Array_Questionnaire_Texts[V_Row].redraw();
				
				# Since text picture parts are created in Presentation with a width just as wide as the text that they contain,
				# having left_align set doesn't make a difference to have the questionnaire left-justified...for the simple reason that
				# the text part is as big as the text, ... and therefore, it is the placement of the text picture part that would
				# actually help.  And here, because we can't use left_x in the add_part method unlike when declaring a text part in SDL as part of a picture definition,
				# we have to tweak the origin X of the text part.  To do that, we actually take a left-most point from which the text must start, and 
				# from that, we displace the X by just half the width of the text in the text part.  That way, regardless of whether we have
				# two words or 10 words in the questionnaire text, they will always appear to be left-justified...but in fact, their origin X (=centre)
				# were tweaked to accomplish this rather than the text_alignment itself.
				
				V_Questionnaire_Text_X = -800 + int(Txt_Array_Questionnaire_Texts[V_Row].width())/2;
				
				### SPECIFIC to put a 'neutral' indication in the middle radio button above the first row
				#   We just want one text part to indicate that the centre radio button in any row is neutral.
				#   We just place this text at 0, first-row's-Y.
				# V_Questionnaire_Text_X = 0;
				
				# P_User_Interface.add_part(Txt_Array_Questionnaire_Texts[V_Row], V_Questionnaire_Text_X, V_Last_Calculated_Centre_Y);
								
				
				# SPECIFIC FOR MUSIKINTER2D
				# For 'Know' and 'MusikInter2D', we do the following assignments manually BEFORE calling this procedure.
            # So just do their placements here. 
				if (Txt_Array_Questionnaire_Texts[V_Row].caption() != " ") then
					# Since there are only a maximum of two/three questionnaire radio button rows in 'KNOW' (unlike the normal radio buttons)
					# we place the questionnaire text on top of the buttons.
					P_User_Interface.add_part(Txt_Array_Questionnaire_Texts[V_Row], V_Questionnaire_Text_X, V_Last_Calculated_Centre_Y);
				end;


            ### Specific to add a Highlight Circle for the middle radio button (if there are odd number of radio buttons per row)
				#if (N_of_Radio_Button_Columns % 2 == 1) then # We have an odd number of Radio Buttons per row
				#
				#	P_User_Interface.add_part(Bmp_Highlight_Radio_Button, 0, V_Last_Calculated_Centre_Y);

				#end;
				
				#	         Txt_Array_Menu_Options[V_Current_Box].ALIGN_LEFT() .set_caption(A_Menu_Options[V_Current_Box]);
		      #   Txt_Array_Menu_Options[V_Current_Box].redraw();
		
			
			end;
		
      end;

	return 0;

end;

# Subroutine to polling the mouse and detect button choice
# ========================================================
# Calls menu box subroutines to construct menu boxes after button selection is complete

sub int
	Q_Poll_Device_For_Radio_Button_Choice
	begin
			
		A_Radio_Buttons_Selected.resize(0);
      A_Radio_Buttons_Selected.resize(A_Radio_Button_Options.count()*3);	# Because we're storing three details for each row of radio buttons.  1. V_Button_Index_In_Current_Row, 2. V_Current_Button, 3. Previously selected V_Button_Index_In_Current_Row. 
			
			
			
			
		# Start polling the device incessantly until we have selections for all rows of radio buttons
		loop N_of_Responses = response_manager.total_response_count(1) until false
		begin
			

	####### Specific for the MusiTab2D Scenario			
			# If there is some auditory stimulus playing, the radio buttons will show up (in the next step) but won't
			# let the user select them yet (thanks to monitor_sound = true (default) in T_User_Interface.
			# Therefore, we want to present an image of a speaker as long as the audio is still playing;
			# but once the audio ends, the speaker image should vanish, without affecting any other behaviour.
			# The following check, and the one after the presentation of T_User_Interface accomplish this.
			
			# If true, the control will get into this only the first time the infinite loop runs, 
         # for we are resetting the flag in the if check after T_User_Interface.present(), for by then the audio should have ended.
			if V_Audio_Is_Playing then

   #### ADDED for MUSIKINTER2D: We don't want the cursor on screen when the audio is playing				
	#    We simply reload the cursor to a blank one when the audio is playing.  This will be automatically changed to the usual one when the polling starts.  Nothing else needs to be done.
				Bmp_Pointer.set_filename("Pointer-Blank.png");
				Bmp_Pointer.load();
				
				P_User_Interface.add_part(Bmp_Audio_Playing, 0, -500);        # Add a speaker image.
				V_Audio_Playing_Part_Index = P_User_Interface.part_count();
			end;	

					
			# Show the Radio Buttons Screen
			T_User_Interface.present();

   ####### Specific for the MusiTab Scenario	
         if V_Audio_Playing_Part_Index != 0 then
				P_User_Interface.remove_part(V_Audio_Playing_Part_Index);     # Remove the speaker image added above.
				V_Audio_Playing_Part_Index = 0;                               
				V_Audio_Is_Playing = false;    # If we are here, that means that the audio has ended.  
                                           # Reset the flag to reflect this, so that the next run 
                                           # of the infinite loop won't run into the check above.
	
		      if response_manager.total_response_count(1) > N_of_Responses then # Participants clicked on the menu boxes when the Audio was still playing;
				# Just in case when people touch one of the buttons when the audio was still playing,
            # once the audio is over, that last location (if it happens to be a button) gets highlighted...and treated as a button selection.
            # This behaviour would have been correct usually, but for the current scenario,
            # with audio + menu, but selection enabled only after the audio ends,
            # this behaviour is not correct. Because it would almost be like priming to select that button.
            # So we make sure to update the N_of_Responses with the current count and set a flag not to highlight buttons (...reset later).
					  
                  N_of_Responses = response_manager.total_response_count(1);
				      #V_Highlight_On_Hover = false;
				# Basically, this achieves two things: 1. Do not recognise the box hovered/pressed when the audio was still playing as the response
				#                                      2. Do not highlight it until the user chooses it or any other box...and then highlighting would be on as usual.
				
            end;

			end;





         # Poll device and change pointer position accordingly
			Dev_Pointer.poll();
			V_Pointer_Position_X = Dev_Pointer.x();
			V_Pointer_Position_Y = Dev_Pointer.y();
		
			
			P_User_Interface.set_part_x(V_Pointer_Part_Index, V_Pointer_Position_X); # The pointer's part number will be (No.of.Txt + No.of.Box) + 1 => (No. of elements in Menu Options Array x 2) + 1
			P_User_Interface.set_part_y(V_Pointer_Part_Index, V_Pointer_Position_Y); # Because we added the pointer as the last part, just before entering this subroutine


         # Initialise/Reset the pointer to the default
			Bmp_Pointer.set_filename("Pointer-Arrow-Blue.png");#("Pointer-Blue-Orange.png");   # Reset the pointer.  Resetting things anywhere else, either in an else case below or out of the loop below doesn't work.
			Bmp_Pointer.load();                                    # In all other cases, some or all of the correct behaviour is lost.  So we do it here.
				

	      RGB_Current_Button_Colour = Gfx_Array_Radio_Buttons[V_Radio_Button_Hovered_Over].get_rgb_pixel_color(25,25); # IMPORTANT: These values must be less than the ellipse_width and heigt defined above in Gfx_Array_Radio_Buttons.
	

         # Since we're dealing with radio buttons, we should let the user keep hovering over the options to possibly reconsider their choice;
         # In that case, the button clicked on previously should remain clicked...but the other buttons should show the default behaviour of
         # changing to the default colours if it is hovered over but not clicked. 

         if RGB_Current_Button_Colour != RGB_Clicked_Button_Colour then 
				# Initialise/Reset the button attributes to the default values
				Gfx_Array_Radio_Buttons[V_Radio_Button_Hovered_Over].set_color(RGB_Default_Button_Colour);
				Gfx_Array_Radio_Buttons[V_Radio_Button_Hovered_Over].redraw();
         end;

			
         # Calculate the left, right, bottom and top extremes, considering we are on a menu box	
			V_L = V_Pointer_Position_X - V_Button_Width/2; 
			V_R = V_Pointer_Position_X + V_Button_Width/2;
			V_B = V_Pointer_Position_Y - V_Button_Height/2;
			V_T = V_Pointer_Position_Y + V_Button_Height/2;
				

         # Keep checking if we are hovering over one of the radio button
			loop V_Current_Button = 1  until V_Current_Button > A_Radio_Button_Options.count()*N_of_Radio_Button_Columns begin
				
				if (V_L <= A_Radio_Button_Coordinates[V_Current_Button][1] && 
					 V_R >= A_Radio_Button_Coordinates[V_Current_Button][1] && 
					 V_B <= A_Radio_Button_Coordinates[V_Current_Button][2] && 
					 V_T >= A_Radio_Button_Coordinates[V_Current_Button][2]) then 
					
					# If so, change its attributes and the pointer
					

					RGB_Current_Button_Colour = Gfx_Array_Radio_Buttons[V_Current_Button].get_rgb_pixel_color(25,25); # IMPORTANT: These values must be less than the ellipse_width and heigt defined above in Gfx_Array_Radio_Buttons.
					
	            if RGB_Current_Button_Colour != RGB_Clicked_Button_Colour then
						Gfx_Array_Radio_Buttons[V_Current_Button].set_color(RGB_Hovered_Button_Colour);
						Gfx_Array_Radio_Buttons[V_Current_Button].redraw();
					end;
					

					Bmp_Pointer.set_filename("Pointer-Hand-Orange.png");#("Pointer-Orange-Blue.png");
               Bmp_Pointer.load();
										
					# If there was a click response when inside the menubox borders, this means the user has chosen the option; return that as the result 					
					if (response_manager.total_response_count(1) > N_of_Responses) then 
						
						V_Radio_Button_Clicked = V_Current_Button; 
						
						V_Current_Row = ((V_Current_Button - 1)/N_of_Radio_Button_Columns) + 1; # The row in which the current button is located.
						
						V_Button_Index_In_Current_Row = V_Current_Button - (V_Current_Row - 1)*N_of_Radio_Button_Columns; # So this will always be 1 to N_of_columns for each row, unlike V_Current_Button, which is continuous...and equal to N_of_rows x N_co_columns.
						
						
                  # If a radio button was previously clicked, and it is on the same row as the current one that was just clicked, then clear the previous one.
					   if A_Radio_Buttons_Selected[V_Current_Row][2] != 0 then
						

							Gfx_Array_Radio_Buttons[A_Radio_Buttons_Selected[V_Current_Row][2]].set_color(RGB_Default_Button_Colour);
							Gfx_Array_Radio_Buttons[A_Radio_Buttons_Selected[V_Current_Row][2]].redraw();
						   
						   
                  end;					

                  Gfx_Array_Radio_Buttons[V_Current_Button].set_color(RGB_Clicked_Button_Colour);#.set_color(255,0,0,120); 
					   Gfx_Array_Radio_Buttons[V_Current_Button].redraw();
					
					   # Store the previously selected button...the one that we just cleared the attributes for; just for the record. We don't use it to change attributes etc.
					   A_Radio_Buttons_Selected[V_Current_Row][3] = A_Radio_Buttons_Selected[V_Current_Row][1];  

					   A_Radio_Buttons_Selected[V_Current_Row][1] = V_Button_Index_In_Current_Row;   # The button number on a per row basis that that experimenter will use ultimately.
					   A_Radio_Buttons_Selected[V_Current_Row][2] = V_Current_Button;                # The absolute button number, useful for the code here.
					
					   # In effect, A_Radio_Buttons_Selected[V_Current_Row][2]  is equal to  (V_Current_Row-1)*N_of_Radio_Button_Columns + A_Radio_Buttons_Selected[V_Current_Row][1];
										   
					
						
					else
						# It was just a case of hovering over the menubox, but not selecting it.  Store this information to restore attributes for the menubox later.	
						V_Radio_Button_Hovered_Over = V_Current_Button;	
						
						RGB_Current_Button_Colour = Gfx_Array_Radio_Buttons[V_Radio_Button_Hovered_Over].get_rgb_pixel_color(25,25); # IMPORTANT: These values must be less than the ellipse_width and heigt defined above in Gfx_Array_Radio_Buttons.
						
	               if RGB_Current_Button_Colour != RGB_Hovered_Button_Colour && RGB_Current_Button_Colour != RGB_Clicked_Button_Colour then  #  !((V_R_Byte == 255 && V_G_Byte == 153 && V_B_Byte == 0) || (V_R_Byte == 255 && V_G_Byte == 0 && V_B_Byte == 0) 
							Gfx_Array_Radio_Buttons[V_Radio_Button_Hovered_Over].set_color(RGB_Default_Button_Colour);
							Gfx_Array_Radio_Buttons[V_Radio_Button_Hovered_Over].redraw();
		            end;
	
					end;

				end;				
				
				V_Current_Button = V_Current_Button + 1;
				
			end;
        
         # Update our record of the total number of responses.
			N_of_Responses = response_manager.total_response_count(1);   # This line solved the issue of selecting an option hovered over, after a click outside the buttons.        

	      V_Selection_Completed = true;                                         # This needs to be set here to true every run of the loop; 
                                                                                    # It will be reset to false by the loop below, ...
                                                                                    # even if one of the rows of buttons hasn't been selected yet.

         
         loop V_Current_Row = 1 until V_Current_Row > N_of_Radio_Button_Rows 
         begin
	         
	         if A_Radio_Buttons_Selected[V_Current_Row][1] == 0 then    # This means that, there's at least one row of buttons from which a selection hasn't been made yet.
           
					V_Selection_Completed = false;                          # So reset the flag to false to reflect this reality.
						
				end;
								
				V_Current_Row = V_Current_Row + 1;
			end;

         if V_Selection_Completed then                                 # This means that, there's a selection made for each of the row.  So basically we can enable further actions,
                                                                       # ... but still providing the opportunity to reconsider selections.
				#Txt_Message.set_caption("Well done!");
            #Txt_Message.redraw();
            
            #P_User_Interface.add_part(Txt_Message, 0, -300);
            #P_User_Interface.set_part_on_top(V_Pointer_Part_Index, true);  # Just so that the pointer is still on top of everything else!!!

            V_Origin_Y = -550; # Tweak the origin, such that the menuboxes we're going to create are below the radio button boxes.  We don't want them to be relative to the buttons, otherwise we could have used the last_created_button_y on the RHS.


            P_User_Interface.remove_part(V_Pointer_Part_Index);          # Remove the pointer that we created when creating the radio buttons; For another one will be created as part of menu boxes.
				V_Original_Part_Count = P_User_Interface.part_count();       # Store the Originally existing number of parts (excluding the pointer, now that that's been removed) for use later.


				if V_Present_Supplementary_Menu then # It is the first time we show the supplementary menu; so show the replay option.
				
					V_Supplementary_Menu_Choice_Clicked = Q_Show_Menu_Boxes({"Erneut anhören", "Weiter"});
					#V_Supplementary_Menu_Choice_Clicked_Text = A_Menu_Options[V_Supplementary_Menu_Choice_Clicked];
					V_Present_Supplementary_Menu = false; # Reset the flag such that the next time, the supplementary menu won't allow to replay the stimulus.
					
				else # It is not the first time we're here; so only show the continue button.  The user can replay only once.
				
					V_Supplementary_Menu_Choice_Clicked = Q_Show_Menu_Boxes({"Weiter"});
					V_Supplementary_Menu_Choice_Clicked = 2;  # Since there was only one choice in the menu, we just overwrite the variable, just so that the code below would work without changes.
					
				end;
				
				V_Origin_Y = 0;           # The ALL IMPORTANT thing to do!!! Reset the origin to the original value.

            if V_Supplementary_Menu_Choice_Clicked == 1 then   # Participant wishes to reconsider their ratings; So the current radio button selections must be cleared, and another round of selections must be enabled.

	            V_Supplementary_Menu_Choice_Clicked = 0;        # Resetting the choice made, such that we won't land here automatically, i.e., unless the menu is presented anew and the same choice made again!!!
			
               V_New_Part_Count = P_User_Interface.part_count();
				
				   # Clear the first round of radio button selections; Also change the corresponding button attributes to the default.
				   loop V_Current_Row = 1 until V_Current_Row > N_of_Radio_Button_Rows begin
						V_Radio_Button_Clicked = A_Radio_Buttons_Selected[V_Current_Row][2];
						Gfx_Array_Radio_Buttons[V_Radio_Button_Clicked].set_color(RGB_Default_Button_Colour);
						Gfx_Array_Radio_Buttons[V_Radio_Button_Clicked].redraw();
						A_Radio_Buttons_Selected[V_Current_Row][1] = 0;
						A_Radio_Buttons_Selected[V_Current_Row][2] = 0;
						V_Current_Row = V_Current_Row + 1;
					end;

               # Remove the new picture parts (including the new pointer) created by the Q_Show_Menu_Boxes... function such that the screen looks like just after a new set of radio buttons is presented, but with the old set of buttons, of course.											
		         loop V_New_Part_Count until V_New_Part_Count <= V_Original_Part_Count
               begin
						P_User_Interface.remove_part(V_New_Part_Count);
                  V_New_Part_Count = V_New_Part_Count - 1;
               end;
               
               V_Pointer_Part_Index = 0; # We've just now removed everything that the Q_Show_Menu_Boxes... function created...including the pointer.  So reset its index accordingly.


					### SPECIFIC FOR MUSIKINTER2D
				   #   If Participant selected 'Replay', after the radio button selections are cleared,
               #   the stimulus has to play again and only then should there be a polling.
               

               T_Auditory_Stimulus.present();
               V_Audio_Is_Playing = true;

					# Add a new pointer to the screen
				   P_User_Interface.add_part(Bmp_Pointer, 0,-400);
					V_Pointer_Part_Index = P_User_Interface.part_count();  # Since we added the pointer as the last part, the part_count will also be the index of the last part (pointer).
					
            elseif  V_Supplementary_Menu_Choice_Clicked == 2 then  

               P_User_Interface.clear();


               loop V_Current_Row = 1 until V_Current_Row > N_of_Radio_Button_Rows begin
	
	               E_Log_User_Choice.set_event_code("|Radio Button| " + string(A_Radio_Buttons_Selected[V_Current_Row][1]) + " selected for " + A_Radio_Button_Options[V_Current_Row][1] + "..." + A_Radio_Button_Options[V_Current_Row][2] + ". |");
						T_Log_User_Choice.present();
						
						V_Current_Row = V_Current_Row + 1;
					end;

					return 2;
            end;

			end;
			
		end;

	return 0;
end;

	




# Subroutine to show radio buttons and record the user choice
# ===========================================================


sub int
	Q_Show_Radio_Buttons(array<string,2> AL_Input_Array)  # Note that we are not using pass-by reference;  That would have been array<string,1>& AL_Input_Array;  
                                                                  # Other than that, there won't be much of a difference in the code here;
                                                                  # However, we are using pass-by values, because, when calling the function, we just need to supply the values;
                                                                  # No need to declare an array, pass that, and then do an explicit resize etc.
                                                                  # The less the experimenter needs to adapt things, the better.  So, pass-by values good for us here.
	begin

	   N_of_Radio_Button_Rows = AL_Input_Array.count();
	   N_of_Radio_Button_Columns = 7;
	
		
		A_Radio_Button_Options.assign(AL_Input_Array); # Copy contents into the global array.
		A_Radio_Button_Coordinates.resize(A_Radio_Button_Options.count() * N_of_Radio_Button_Rows * N_of_Radio_Button_Columns * 2);  # Make place to save x,y coordinates for each point-scale and for each column within it...therefore N_of_Rows * N_of_Columns * 2.

	
		V_First_Button_Centre_X = V_Origin_X + ((V_Origin_X - V_Button_Width/2 - V_Button_Gap/2)*(N_of_Radio_Button_Columns - 1)); # We use the centre as the anchor.
		V_First_Button_Centre_Y = V_Origin_Y + ((V_Origin_Y + V_Button_Height/2 + V_Button_Gap_Vertical/2)*(N_of_Radio_Button_Rows - 1));
		

			V_Current_Button = 1;
			Q_Construct_Radio_Buttons();


      # Add the pointer to the screen
		P_User_Interface.add_part(Bmp_Pointer, 0,-400);
		V_Pointer_Part_Index = P_User_Interface.part_count();  # Since we added the pointer as the last part, the part_count will also be the index of the last part (pointer).

		  
		# Initialise
		V_Radio_Button_Hovered_Over = 1;
		
		Q_Poll_Device_For_Radio_Button_Choice();
		


	return 0;
	
end;


# Subroutine to show radio buttons and record the user choice -- Pass-By-Reference
# ===========================================================


sub int                                                       # Different from the pass-by value version above.
	Q_Show_Radio_Buttons_PBR(array<string,2>& AL_Input_Array)  # This sub-routine uses PASS-BY-REFERENCE;  That's why the ampersand in array<string,2>& ...;
                                                              # Other than that, there isn't be much of a difference in the code here from the pass-by-value version above;

	begin

	   N_of_Radio_Button_Rows = AL_Input_Array.count();
	   N_of_Radio_Button_Columns = 7;


		A_Radio_Button_Options.assign(AL_Input_Array); # Copy contents into the global array.
		A_Radio_Button_Coordinates.resize(A_Radio_Button_Options.count() * N_of_Radio_Button_Rows * N_of_Radio_Button_Columns * 2);  # Make place to save x,y coordinates for each point-scale and for each column within it...therefore N_of_Rows * N_of_Columns * 2.


      #Txt_Message.set_caption(string(N_of_Radio_Button_Rows) + " " + string(AL_Input_Array.count()) + " " + string(A_Radio_Button_Options.count()));
      #Txt_Message.redraw();
      #P_User_Interface.add_part(Txt_Message, 0 ,-500);

		V_First_Button_Centre_X = V_Origin_X + ((V_Origin_X - V_Button_Width/2 - V_Button_Gap/2)*(N_of_Radio_Button_Columns - 1)); # We use the centre as the anchor.
		V_First_Button_Centre_Y = V_Origin_Y + ((V_Origin_Y + V_Button_Height/2 + V_Button_Gap_Vertical/2)*(N_of_Radio_Button_Rows - 1));


			V_Current_Button = 1;
			Q_Construct_Radio_Buttons();


      # Add the pointer to the screen
		P_User_Interface.add_part(Bmp_Pointer, 0,-400);
		V_Pointer_Part_Index = P_User_Interface.part_count();  # Since we added the pointer as the last part, the part_count will also be the index of the last part (pointer).


		# Initialise
		V_Radio_Button_Hovered_Over = 1;

		Q_Poll_Device_For_Radio_Button_Choice();



	return 0;

end;


# Subroutine to show the 2D Canvas and poll the mouse for response
# ================================================================
sub string
	Q_Show_Canvas_And_Poll_Device
	begin
		
		# Show the 2D Canvas with its text labels on either sides of the axes

		P_User_Interface.add_part(Bmp_Canvas, 0, 0);

		P_User_Interface.add_part(Txt_Canvas_X_Left, -520, 0);
		P_User_Interface.add_part(Txt_Canvas_X_Right, 510, 0);
		
		P_User_Interface.add_part(Txt_Canvas_Y_Top, 0, 380);
		P_User_Interface.add_part(Txt_Canvas_Y_Bottom, 0, -380);


      # Restrict the mouse co-ordinates to the area of the canvas.  Will be reset later.

		Dev_Pointer.set_min_max(1, -342, 342);
		Dev_Pointer.set_min_max(2, -342, 342);	
		
		# Start polling the device incessantly until we have a response
		loop N_of_Responses = response_manager.total_response_count(1) until false
		begin

	   ####### Specific for the MusiTab Scenario			
			# If there is some auditory stimulus playing, the menu choices will show up (in the next step) but won't
			# let the user select them yet (thanks to monitor_sound = true (default) in T_User_Interface.
			# Therefore, we want to present an image of a speaker as long as the audio is still playing;
			# but once the audio ends, the speaker image should vanish, without affecting any other behaviour.
			# The following check, and the one after the presentation of T_User_Interface accomplish this.
			
			# If true, the control will get into this only the first time the infinite loop runs, 
         # for we are resetting the flag in the if check after T_User_Interface.present(), for by then the audio should have ended.
			if V_Audio_Is_Playing then

         #### MODIFIED for MUSIKINTER2D: We don't want the cursor on screen when the audio is playing				
            # We reload the cursor to a blank one.  A green circle will be added as the pointer when the polling starts, which will then be removed before returning from this function.  
				# We load a green circle as the pointer on the canvas
				# Before returning from this function, this will be removed.
				
				#Bmp_Pointer.set_filename("Pointer-Blank.png");
				#Bmp_Pointer.load();

			   Bmp_Pointer.set_filename("Pointer-Circle-Green.png");
				Bmp_Pointer.load();
				
				P_User_Interface.add_part(Bmp_Pointer, 0, 0);
				V_Pointer_Part_Index = P_User_Interface.part_count(); # Since we added the pointer as the last part, the part_count will also be the index of the last part (pointer). 
            P_User_Interface.set_part_on_top(V_Pointer_Part_Index, true);  

				P_User_Interface.add_part(Bmp_Slider_X, 0, 0);
				V_Slider_X_Part_Index = P_User_Interface.part_count();
				
            P_User_Interface.add_part(Bmp_Slider_Y, 0, 0);
            V_Slider_Y_Part_Index = P_User_Interface.part_count();		

			
				P_User_Interface.add_part(Bmp_Audio_Playing, 0, -500);        # Add a speaker image.
				V_Audio_Playing_Part_Index = P_User_Interface.part_count();		
				
			end;			
	
			# Show the Menu Screen
			T_User_Interface.present();
			
         if V_Audio_Playing_Part_Index != 0 then
				P_User_Interface.remove_part(V_Audio_Playing_Part_Index);     # Remove the speaker image added above.
				V_Audio_Playing_Part_Index = 0;                               
				V_Audio_Is_Playing = false;    # If we are here, that means that the audio has ended.  
                                           # Reset the flag to reflect this, so that the next run 
                                           # of the infinite loop won't run into the check above.

				#### MODIFIED FOR MUSIKINTER2D
				# We removed the cursor when the audio was playing (see above).  Now we add it back
				# We load a green circle as the pointer on the canvas
				# Before returning from this function, this will be removed.
/*
				Bmp_Pointer.set_filename("Pointer-Circle-Green.png");
				Bmp_Pointer.load();
				
				P_User_Interface.add_part(Bmp_Pointer, 0, 0);
				V_Pointer_Part_Index = P_User_Interface.part_count(); # Since we added the pointer as the last part, the part_count will also be the index of the last part (pointer). 
            P_User_Interface.set_part_on_top(V_Pointer_Part_Index, true);  


				P_User_Interface.add_part(Bmp_Slider_X, 0, 0);
				V_Slider_X_Part_Index = P_User_Interface.part_count();
				
            P_User_Interface.add_part(Bmp_Slider_Y, 0, 0);
            V_Slider_Y_Part_Index = P_User_Interface.part_count();
*/
		      if response_manager.total_response_count(1) > N_of_Responses then # Participants clicked on the menu boxes when the Audio was still playing;
				# Just in case when people touch the canvas when the audio was still playing,
            # once the audio is over, that last location (if it happens to be on the canvas) would get the Orange placeholder
            # ...and treated as a response selection.
            # This behaviour would have been correct usually, but for the current scenario,
            # with audio + canvas, but selection enabled only after the audio ends,
            # this behaviour is not correct. Because it would almost be like priming to select that location on the canvas.
            # So we make sure to update the N_of_Responses with the current count.  No flags necessary here unlike menu boxes.
					  
                  N_of_Responses = response_manager.total_response_count(1);

				# Basically, this achieves two things: 1. Do not recognise any canvas presses when the audio was still playing as the response
				#                                      2. Do not put the orange placeholder until the user chooses a location after the audio ends.
				
            end;
				# Poll device and store the current pointer position, which is the last position when the audio ends.
				# This could then be checked (see below) to reset the highlighting flag to true.
				Dev_Pointer.poll();
				V_Pointer_Position_X = Dev_Pointer.x();
				V_Pointer_Position_Y = Dev_Pointer.y();
						
         end;		

   ####### Specific for the MusiTab Scenario	

         # Poll device and change pointer position accordingly
			Dev_Pointer.poll();
			V_Pointer_Position_X = Dev_Pointer.x();
			V_Pointer_Position_Y = Dev_Pointer.y();
     

			#NO VISIBLE CURSOR on TOUCHSCREEN#     
         P_User_Interface.set_part_x(V_Pointer_Part_Index, V_Pointer_Position_X); # Alternativerly, the pointer's part number will be A_Menu_Options.count()*2+1 = (No.of.Txt + No.of.Box) + 1 => (No. of elements in Menu Options Array x 2) + 1
			#NO VISIBLE CURSOR on TOUCHSCREEN#         
         P_User_Interface.set_part_y(V_Pointer_Part_Index, V_Pointer_Position_Y); # Because we added the pointer as the last part, just before entering this subroutine
			   
			
			# Set Slider-X's position on the x-axis based on the current mouse pointer position
			# No change of y-position (0) for Slider-X!!!
         P_User_Interface.set_part_x(V_Slider_X_Part_Index, V_Pointer_Position_X);
			
			# Set Slider-Y's position on the y-axis based on the current mouse pointer position
			# No change of x-position (0) for Slider-Y!!!			
			P_User_Interface.set_part_y(V_Slider_Y_Part_Index, V_Pointer_Position_Y);
			
			
			
			
         # As soon as we have a response inside the canvas area, 
         # we'll mark that location with an Orange Circle,
         # remove the Green Circle pointer we added,
         # reset the mouse co-ordinate restrictions, and
         # return from the infinite look and in turn return from the function
				
				if (V_Pointer_Position_X <= 350 && 
					 V_Pointer_Position_X >= -350 && 
					 V_Pointer_Position_Y <= 350 && 
					 V_Pointer_Position_Y >= -350 &&
                response_manager.total_response_count(1) > N_of_Responses) then 
					
                  # If there was a click response when inside the canvas area, this means the user has chosen that as their response.
                  # Put an orange placeholder, unrestrict the mouse movements beyond the borders of the canvas and return.
						P_User_Interface.add_part(Bmp_Placeholder, V_Pointer_Position_X, V_Pointer_Position_Y);
						
						Bmp_Slider_X.set_filename("Slider-X-Green.png");
						Bmp_Slider_X.load();
						
						Bmp_Slider_Y.set_filename("Slider-Y-Green.png");
						Bmp_Slider_Y.load();
						
						# LOGGING DONE OUTSIDE THIS FUNCTION!!!
						# We just return the Canvas Coordinates Clicked ... see below.
						# REMEMBER TO DO IT EVERYTIME THIS FUNCTION IS CALLED!!!
						
						V_Canvas_Coordinates_Clicked = "X: " + string(V_Pointer_Position_X) + " Y: " + string(V_Pointer_Position_Y);

						V_Selection_Completed = true;
						
						
						# Reset mouse coordinate restriction beyond the canvas area to the entire display area
						
						Dev_Pointer.set_min_max(1, -V_Display_Width/2, V_Display_Width/2);
						Dev_Pointer.set_min_max(2, -V_Display_Height/2, V_Display_Height/2);

                  # Remove the extra Green Circle pointer we added above. 
                  # If this is not done, there would be two copies of the mouse pointer, one wherever the mouse moves, and 
                  # another at the point marked on the canvas, over and above the orange circle (actually below it)!
                  P_User_Interface.remove_part(V_Pointer_Part_Index);






                  # Extra fancy things: Change the font colour of the text corresponding to the selected quadrant

                  # + + First Quadrant
                  # - + Second
                  # - - Third
                  # + - Fourth

                  if (V_Pointer_Position_X > 0) then
	
							Txt_Canvas_X_Right.set_font_color(RGB_Clicked_Button_Colour);
							Txt_Canvas_X_Right.redraw();
							
							Txt_Canvas_X_Left.set_font_color(RGB_Default_Button_Colour);
							Txt_Canvas_X_Left.redraw();
							
                  elseif (V_Pointer_Position_X < 0) then

							Txt_Canvas_X_Right.set_font_color(RGB_Default_Button_Colour);
							Txt_Canvas_X_Right.redraw();
	
							Txt_Canvas_X_Left.set_font_color(RGB_Clicked_Button_Colour);
							Txt_Canvas_X_Left.redraw();
							
						end;
							
                  if (V_Pointer_Position_Y > 0) then
	
							Txt_Canvas_Y_Top.set_font_color(RGB_Clicked_Button_Colour);
							Txt_Canvas_Y_Top.redraw();
							
							Txt_Canvas_Y_Bottom.set_font_color(RGB_Default_Button_Colour);
							Txt_Canvas_Y_Bottom.redraw();												
							
                  elseif (V_Pointer_Position_Y < 0) then

							Txt_Canvas_Y_Top.set_font_color(RGB_Default_Button_Colour);
							Txt_Canvas_Y_Top.redraw();
	
							Txt_Canvas_Y_Bottom.set_font_color(RGB_Clicked_Button_Colour);
							Txt_Canvas_Y_Bottom.redraw();							
							
                  end;


						return V_Canvas_Coordinates_Clicked;

				end;				
				
         # Update our record of the total number of responses.
			N_of_Responses = response_manager.total_response_count(1);   # This line solved the issue of selecting an option hovered over, after a click outside the buttons.        

		end;
		
	return V_Canvas_Coordinates_Clicked;
end;


# Subroutine to clear previous menu and button choices; Resizes arrays; Resets Txt and Gfx (SDL Array) Attributes to their default
# ================================================================================================================================

sub
	Q_Clear_Previous_Button_And_Menu_Choices
	begin
		
		V_Menu_Box_Hovered_Over = 0;
		
		A_Menu_Options.resize(0);
		A_Menu_Coordinates.resize(0);

		loop V_Current_Box = 1 until V_Current_Box > 40   # This should be equal to the number of Txt elements created in the SDL part above
		begin
			 
			
			 Txt_Array_Menu_Options[V_Current_Box].set_font_color(RGB_Default_Menu_Font_Colour);
			 Txt_Array_Menu_Options[V_Current_Box].set_background_color(RGB_Default_Menu_BG_Colour);
			 Txt_Array_Menu_Options[V_Current_Box].redraw();
			
			V_Current_Box = V_Current_Box + 1;
		end;
		
		
		V_Radio_Button_Hovered_Over = 0;
		
		A_Radio_Button_Options.resize(0);
		A_Radio_Button_Coordinates.resize(0);
		A_Radio_Buttons_Selected.resize(0);
			
		V_Current_Button = N_of_Radio_Button_Rows * N_of_Radio_Button_Columns;
	
		loop V_Current_Button = 1 until V_Current_Button > 100   # This should be equal to the number of Gfx elements created in the SDL part above
		begin
			
			Gfx_Array_Radio_Buttons[V_Current_Button].set_color(RGB_Default_Button_Colour);
			Gfx_Array_Radio_Buttons[V_Current_Button].redraw();		
						
			V_Current_Button = V_Current_Button + 1;
		end;
			
		
end;

# Subroutine to clear previous menu and button choices; Resizes arrays; Resets Txt and Gfx (SDL Array) Attributes to their default
# ================================================================================================================================

sub
	Q_Hide_Unselected_Menu_Choices
	begin
		
		P_User_Interface.clear();
		
		loop V_Current_Box = 1 until V_Current_Box > A_Menu_Options.count()   # This should be equal to the number of Txt elements created in the SDL part above
      begin
			
			P_User_Interface.add_part(Box_Array_Menu_Options_Placeholder[V_Current_Box], A_Menu_Coordinates[V_Current_Box][1], A_Menu_Coordinates[V_Current_Box][2]);

			Txt_Array_Menu_Options_Placeholder[V_Current_Box].set_caption(A_Menu_Options[V_Current_Box]);
			Txt_Array_Menu_Options_Placeholder[V_Current_Box].set_font_color(RGB_Default_Menu_Font_Colour);
			Txt_Array_Menu_Options_Placeholder[V_Current_Box].set_background_color(RGB_Dimmed_Menu_BG_Colour);
			
			if V_Current_Box == V_Menu_Choice_Clicked then
				Txt_Array_Menu_Options_Placeholder[V_Current_Box].set_font_color(RGB_Hovered_Menu_Font_Colour);
				Txt_Array_Menu_Options_Placeholder[V_Current_Box].set_background_color(RGB_Hovered_Menu_BG_Colour);
			end;
			
			Txt_Array_Menu_Options_Placeholder[V_Current_Box].redraw();
			
			P_User_Interface.add_part(Txt_Array_Menu_Options_Placeholder[V_Current_Box], A_Menu_Coordinates[V_Current_Box][1], A_Menu_Coordinates[V_Current_Box][2]);

			V_Current_Box = V_Current_Box + 1;
			
		end;

  
		
		
		/*
		
		Txt_Menu_Placeholder.set_caption(V_Menu_Choice_Clicked_Text);
		Txt_Menu_Placeholder.redraw();
		
		
		
		P_User_Interface.add_part(Box_Menu_Placeholder, A_Menu_Coordinates[V_Menu_Choice_Clicked][1], A_Menu_Coordinates[V_Menu_Choice_Clicked][2]);
		P_User_Interface.add_part(Txt_Menu_Placeholder, A_Menu_Coordinates[V_Menu_Choice_Clicked][1], A_Menu_Coordinates[V_Menu_Choice_Clicked][2]);
		*/
		
end;


# Subroutine to show on-screen instructions/description; Replaces # with \n in the Description text, displays it with a Continue button  
# ======================================================================================================================================

sub 
	Q_Show_Description
	begin
	 
		# Replace # characters in the input line with line-feed / newline characters.
		V_Hash_Index = V_Description.find("#");			  
		loop until V_Hash_Index == 0 begin
			V_Description.set_char(V_Hash_Index, 10); # 10 -> LF
			V_Hash_Index = V_Description.find("#");
		end;

		Txt_Description.set_caption(V_Description);
		Txt_Description.redraw();
		P_User_Interface.add_part(Box_Description, 0, 0);
		P_User_Interface.add_part(Txt_Description, 0, 0);      



		#V_Origin_Y = -550;				# Because we have the polled position of the mouse,
												# if one of the menu choices after the 'play' screen partially coincides in its co-ordinates
												# with the 'Play' button's co-ordinates, that menu choice becomes highlighted ... as though prompting
												# the user to choose that option.  So we decided to place the Play button way below, so that
												# such coincidences are avoided in most cases.  We tried resetting the V_...Position_X and Y variables,
												# but that didn't do, because the device is continuously polled when the menu choices are available...
												# and they are updated with the correct (=for us problematic) co-ordinates again.
												# So we'll have to do with this rough and dirty but working solution.

		Q_Show_Menu_Boxes({"Weiter"}); 

		P_User_Interface.clear();
		Q_Clear_Previous_Button_And_Menu_Choices();
		V_Origin_Y = 0;

end;


###################################################
# Experiment Execution Begins Here!!!
###################################################

preset string V_Group;   # Prompt the group at the beginning!!!    Participant Group can be A or B in KleistRead.
preset string V_Version; # Prompt the version at the beginning!!!  Version can be anything from 1 to 50 in KleistRead. 

# Based on the input for V_Group, we use the variable V_Group later construct filenames to display.
# So adapt V_Group appropriately to reflect suffixes for the filenames for each group.
if (V_Group == "O" || V_Group == "o") then
	V_Group = "Original";
elseif (V_Group == "M" || V_Group == "m") then
	V_Group = "Modified";
end;

int N_of_Trials = 6;                                 # Number of Experimental Trials per Session.  
int N_of_Blocks = 1;
int N_of_Trials_per_Block = N_of_Trials/N_of_Blocks;

N_of_Questionnaire_Pages = 3;
N_of_Questions_Per_Page = 9;

int N_of_Practice_Trials = 1;

input_file F_Session_List = new input_file;
F_Session_List.open("Session_List_KleistRead.txt");

# Variables specific for Auditory Stimuli
#string V_Auditory_Stimuli_per_Block;
#array<string> A_Auditory_Stimuli_per_Block[0];
#string V_Auditory_Stimulus;
#int V_Auditory_Stimulus_Duration;

# Variables specific for Visual Stimuli
string V_Visual_Stimuli_per_Block;
array<string> A_Visual_Stimuli_per_Block[0];
string V_Visual_Stimulus;

 			
input_file F_Questionnaire_Texts = new input_file;
F_Questionnaire_Texts.open("Session_List_KleistRead-Questionnaire.txt");

# There are 27 questions, which we read all at once into an array, which we could then shuffle for every trial;
# The input line would be something like: Qxx-Bla Bla Bla.  We split that based on "-" and save the contents into a 2D array,
# the size of which will/should be exactly equal to the number of questions per page.  This way, the log file would be
# more informative...rather than a dummy 1..1, 2..2 etc. See below.  
loop int j = 1 until j > N_of_Questionnaire_Pages*N_of_Questions_Per_Page begin;
    A_Questionnaire_Texts.add(F_Questionnaire_Texts.get_line());
    j = j + 1;
end;

#string V_Visual_Stimulus_With_PageCount;
#array<string> A_Visual_Stimulus_With_PageCount[0]; # We split the Itemx_n combination and store here (see below)
int V_N_of_Single_Pages;

bool V_Last_Single_Page_Blank = false;
string V_Visual_Stimulus_L;
string V_Visual_Stimulus_R;


stimulus_data D_Stimulus_Data = stimulus_manager.last_stimulus_data();
int D_Last_Response = response_manager.last_response();


system_keyboard.set_delimiter('\n');    # Defines the escape character that will get the control out of the get_input() function.
                                        # \n => Enter. \t => Tab...Pressing this button will get us out of the keyboard mode.
                                        # We've set it to Tab, because that is not as easy to type as enter (because there's no going back) / tab (because it is too dangerously close to ESC).

system_keyboard.set_inactivity_time_out(600000); # 600 second inactivity timeout for keyboard input
 
system_keyboard.set_case_mode(3); # 1 => CASE_LOWER; 2 => CASE_UPPER; 3 => CASE_SHIFT; 4=> CASE_SHIFT_CAPS;



# Scenario-specific Subroutine to run one experimental trial 
# ==========================================================
# Specific for KleistRead

sub 
	Q_Run_Experimental_Trial__KleistRead(string VL_Experiment_Part, int VL_Current_Trial)
	begin


	   V_Visual_Stimulus = A_Visual_Stimuli_per_Block[VL_Current_Trial] + "-" + V_Group;  # Construct the file name ... Eg:- T1-Modified
	
		V_Origin_Y = -400;	
			
		if (VL_Experiment_Part != "Practice") then	
			# Get the right description text for the current stimulus using the text number encoded in the name (T1 T2 etc.);
			# Notice that we are not depending on the trial number, but the actual stimulus number encoded in its name.  
			# That way, we display the correct description pertaining to each stimulus.
			# split it using _ as the delimiter, and use only the text in the second part (the first part is dummy, for our reference).	
			A_Description[int(V_Visual_Stimulus.substring(2,1))].split("_", A_Temp); 
			V_Description = A_Temp[2];
			
			Q_Show_Description();

		end;
		
		
		P_User_Interface.clear();
		Q_Clear_Previous_Button_And_Menu_Choices();
		V_Origin_Y = 0;


	########## Presenting Text Pages -- Begin

	 T_Blank_Screen.present();
	
			if (V_N_of_Single_Pages % 2 > 0) then # The story has odd number of single pages; so the last single page must be blank.
				V_Last_Single_Page_Blank = true;
				#V_N_of_Facing_Pages = (V_N_of_Single_Pages+1)/2;
			else
				V_Last_Single_Page_Blank = false;
				#V_N_of_Facing_Pages = V_N_of_Single_Pages/2;
			end;



        # Do filename and event-code assignments valid during this exp-trial;
        # Load wavefile and bitmap stimuli that are needed for this trial;
        /*# We do this before launching the experimental trial so as to keep
          # as minimal intereference as possible in trial timings.  You see,
          # these things consume processor time, however small they are!
        */

		  E_Visual_Stimulus.set_event_code(V_Visual_Stimulus);


        # Present the pages of Stimulus Text in a staggered loop, such that the participant can browse through the
        # pages back and forth.
        #============
        # Loop 2.1: -
        #============   			
			loop int V_Current_Single_Page = 1
			until V_Current_Single_Page > V_N_of_Single_Pages # Staggered loop!!! That is, the loop counter is
			begin                                    # sometimes incremented by 2, sometimes decremented by 2 and sometimes neither. 
				                                      # This allows going backwards (unless first page) or forwards (unless last page)
				                                      # as many times as the participant wants.
				

				
				V_Visual_Stimulus_L =  V_Visual_Stimulus + "-" + string(V_Current_Single_Page) +".png";

				if (V_Last_Single_Page_Blank && V_Current_Single_Page == V_N_of_Single_Pages) then
					V_Visual_Stimulus_R = "Blank-Page.png";
            else
					V_Visual_Stimulus_R =  V_Visual_Stimulus + "-" + string(V_Current_Single_Page+1) +".png";
            end;
				
			 
				
				/*****************  Visual Stimulus Presentation Begins  ***********************/
			
				# Put the current word on the picture and redraw the text part in it.
				Bmp_Visual_Stimulus_L.set_filename(V_Visual_Stimulus_L);
				Bmp_Visual_Stimulus_L.load();

				Bmp_Visual_Stimulus_R.set_filename(V_Visual_Stimulus_R);
				Bmp_Visual_Stimulus_R.load();
				
            Txt_Footer_L.set_caption("<b>" + string(V_Current_Single_Page) + "</b>");
            Txt_Footer_L.redraw();

            if (V_Visual_Stimulus_R != "Blank-Page.png") then
					Txt_Footer_R.set_caption("<b>" + string(V_Current_Single_Page+1) + "</b>");
					Txt_Footer_R.redraw();
				else
					Txt_Footer_R.set_caption(" ");
					Txt_Footer_R.redraw();
				end;
				
				# Present the trial that will show the changed text on screen for x ms.
				T_Visual_Stimulus.present();


				/*****************  Visual Stimulus Presentation Ends  *************************/

			   # Get the last button pressed, and either go backwards or forwards accordingly.
			   D_Last_Response = response_manager.last_response();
					
			   if (D_Last_Response == 2) then
					# Go backwards one set of facing pages
					if (V_Current_Single_Page == 1) then
						# We're on the first page; so going backwards not possible
						# So just don't change the Visual_Stimuli and run the loop again with the same page number.
					else
						V_Current_Single_Page = V_Current_Single_Page - 2;
					end;
						
			   elseif (D_Last_Response == 3) then
				
				   #if (V_Current_Single_Page == V_N_of_Single_Pages || V_Current_Single_Page+1 == V_N_of_Single_Pages) then
					   # We're on the last page; so going forwards is not possible
					   # So just don't change the Visual_Stimuli and run the loop again with the same page number.
					#else
						# Go forwards to the next set of facing pages.
						V_Current_Single_Page = V_Current_Single_Page + 2; 
					#end;
				end;
 
		  #=============
		  # End Loop 2.2
		  #=============
		  end; /*** End Loop 2.2 for Facing Pages ***/

	########## Presenting Text Pages -- End

		V_Description = "Nun folgen einige Fragen.";
		V_Origin_Y = -250;
		Q_Show_Description();
			
		P_User_Interface.clear();
		Q_Clear_Previous_Button_And_Menu_Choices();	
			
		V_Selection_Completed = false;
		V_Present_Supplementary_Menu = false;  # Changed for SpliceUp!!!  No replay.
		V_Supplementary_Menu_Choice_Clicked = 0;

      # Shuffle the list of questions
      A_Questionnaire_Texts.shuffle();

		loop V_Current_Questionnaire_Page = 1 until V_Current_Questionnaire_Page > N_of_Questionnaire_Pages begin


			A_Questionnaire_Texts_Per_Page.resize(0); # This is the array that will be passed to the _PBR procedure below.
			                                    # This must contain exactly the number of questions that should be 
			                                    # displayed on a single page.  Not the whole list of questions.
			                                    # Because, unlike the _PBV procedure, _PBR takes the whole array 
			                                    # that's passed to it, and works out to construct as many radio button rows
			                                    # as there are 2D elements in the array.		
			
			
			# Construct the 2D array to pass to the _PBR procedure.
			# Further, loop over the number of text questions, to assign Txt_... here itself
			loop int V_Current_Question = 1 until V_Current_Question > N_of_Questions_Per_Page begin

				A_Questionnaire_Texts[V_Current_Question + (V_Current_Questionnaire_Page-1)*N_of_Questions_Per_Page].split("_", A_Temp);
				A_Questionnaire_Texts_Per_Page.add(A_Temp);	
				# REF: http://www.neurobs.com/menu_support/menu_forums/view_thread?id=6827
				# So basically, we add the 1D array containing two elements as a single element to the 2D array.

				Txt_Array_Questionnaire_Texts[V_Current_Question].set_caption(A_Questionnaire_Texts_Per_Page[V_Current_Question][2]);
				Txt_Array_Questionnaire_Texts[V_Current_Question].redraw();			          

				V_Current_Question = V_Current_Question + 1;
         end;

			V_Origin_X = 82;  # Tweak the Origin X, so that we have space for the questionnaire text.   

			V_Present_Supplementary_Menu = false;
					
			# We are using the pass-by reference here!!!  The logfile would be much more useful that way for KleistRead.
			# The number of questions is determined by the number of 2D elements in the array being passed.

	      Q_Show_Radio_Buttons_PBR(A_Questionnaire_Texts_Per_Page);  # Notice that the Pass-By-Reference version is called here!!!
			P_User_Interface.clear();
			Q_Clear_Previous_Button_And_Menu_Choices();
			
			V_Origin_X = 0;   # Reset the Origin X, just in case.

			V_Current_Questionnaire_Page = V_Current_Questionnaire_Page + 1;
		end;

		Txt_Array_Questionnaire_Texts[1].set_caption("Kannten Sie den eben gelesenen Text schon?");
		Txt_Array_Questionnaire_Texts[1].redraw();
		#V_Questionnaire_Text_X = -690 + int(Txt_Array_Questionnaire_Texts[1].width())/2; # See way above for explanation of why we're doing it this way...keyword: left-alignment with no option to provide left_x in add_part...look for V_Questionnaire_Text_X.
 	   P_User_Interface.add_part(Txt_Array_Questionnaire_Texts[1], 0, 0);

      V_Origin_Y = -100;

		Q_Show_Menu_Boxes({"Ja","Nein"});
		P_User_Interface.clear();
		Q_Clear_Previous_Button_And_Menu_Choices();

      V_Origin_Y = -200;

		Txt_Array_Questionnaire_Texts[1].set_caption("Haben Sie eine Vermutung, wer der Autor / die Autorin des Textes sein könnte?");
		Txt_Array_Questionnaire_Texts[1].redraw();
		#V_Questionnaire_Text_X = -690 + int(Txt_Array_Questionnaire_Texts[1].width())/2; # See way above for explanation of why we're doing it this way...keyword: left-alignment with no option to provide left_x in add_part...look for V_Questionnaire_Text_X.
 	   P_User_Interface.add_part(Txt_Array_Questionnaire_Texts[1], 0, 0);
		Q_Show_Menu_Boxes({"Ja","Nein"});
		P_User_Interface.clear();
		Q_Clear_Previous_Button_And_Menu_Choices();
		
      V_Origin_Y = 0;

		if (V_Menu_Choice_Clicked == 1) then # If user clicked yes, let them enter text; else do nothing.
			system_keyboard.get_input(P_Keyboard_Input, Txt_Keyboard_Input); # Notice that the system_keyboard built-in function takes care to blend in and blend out the picture specified.
		end;

		T_Blank_Screen.present();
		Q_Clear_Previous_Button_And_Menu_Choices();
		
		
end;





#========================
# Main Experiment Loop: -
#========================

# Read and display the instructions description from the session list
V_Description = F_Session_List.get_line();

V_Origin_Y = -550;
# Show the description screen
Q_Show_Description();

###########   Practice Begins

# Read and display the instructions description from the session list
V_Description = F_Session_List.get_line();

V_Origin_Y = -450;
# Show the description screen
Q_Show_Description();

# Read the list of stimuli to present in the Practice part
V_Visual_Stimuli_per_Block = F_Session_List.get_line();
A_Visual_Stimuli_per_Block.resize(0); # Empty the array
V_Visual_Stimuli_per_Block.split(" ",A_Visual_Stimuli_per_Block); # Split the input line based on 'space' 
																						# and save the output as individual elements in an array.
																						
V_N_of_Single_Pages = 1; # The practice trial in KleistRead is 1 page long.

#==========
# Loop 0: -
#==========
loop    /*** Begin Loop 0 for Practice Trials ***/
  int V_Current_Trial = 1

until
  V_Current_Trial > N_of_Practice_Trials

begin

	Q_Run_Experimental_Trial__KleistRead("Practice", V_Current_Trial);
		
	# Go to the Next Trial        
	V_Current_Trial = V_Current_Trial + 1;

#===========
# End Loop 0 
#===========
end; /*** End Loop 0 for Practice Trials ***/

###########  Practice Complete

# Read the instructions description from the session list and display it
V_Description = F_Session_List.get_line();

V_Origin_Y = -550;
# Show the description screen
Q_Show_Description();

###########  Main Experiment Begins

# Read all the description texts for the critical stimuli from the session list and store tehm in an array.
# The first part of the description contains a sort of header to avoid confusion, which will be discarded when 
# the array is actually used when running the trial.  See Q_Run_Experimental_Trial__KleistRead.
loop int k = 1 until k > N_of_Trials begin;
    A_Description.add(F_Session_List.get_line());
    k = k + 1;
end;

# Read the list of stimuli to present in the Main part

# KleistRead has 6 texts that need to be presented in a conditional randomised manner
# Further, it is a between-subjects design, in which an identical quasi-randomised sequence of stimuli
# need to be presented to 2 different participants, each from groups 1 or 2.
# The possible sequences are listed in the Session List. Each line is a  quasi-randomised sequence of stimuli.
# Based on the version number, we read so many lines, save and present ONLY the last sequence read
loop int i = 1 until i > int(V_Version) begin;
    
	# Notice that the variable WILL BE OVERWRITTEN every time a line is read 
	# This is deliberately so, because we don't need all of the listed sequences, 
   # but only the sequence that corresponds to the Version number provided...
   # ... which would be the last read sequence, because we use V_Version as the loop control variable.
	V_Visual_Stimuli_per_Block = F_Session_List.get_line();   # Eg: T1 T3 T5 T6 T4 T2 
																			               # This is the list of all the stimuli
																			               # to presented in the given sequence for a given participant.
	A_Visual_Stimuli_per_Block.resize(0); # Empty the array
	V_Visual_Stimuli_per_Block.split(" ",A_Visual_Stimuli_per_Block); # Split the input line based on 'space' 
																							# and save the output as individual elements in an array.

	# No shuffling any more...what we read-in was already the quasi-randomised sequence of stimuli!
	
    i = i + 1;
end;

V_N_of_Single_Pages = 2; # All critical texts in KleistRead are 2 pages long.

#==========
# Loop 1: -
#==========
loop    /*** Begin Loop 1 for Blocks ***/
  int V_Current_Block = 1

until
  V_Current_Block > N_of_Blocks

begin
	
	#============
	# Loop 1.1: -
	#============
	loop    /*** Begin Loop 1.1 for Trials ***/
	  int V_Current_Trial = 1

	until
	  V_Current_Trial > N_of_Trials_per_Block

	begin

		Q_Run_Experimental_Trial__KleistRead("MainPart", V_Current_Trial);

		# Go to the Next Trial        
		V_Current_Trial = V_Current_Trial + 1;

	#=============
	# End Loop 1.1 
	#=============
	end; /*** End Loop 1.1 for Trials ***/

	# Go to the Next Block        
	V_Current_Block = V_Current_Block + 1;
	
#===========
# End Loop 1 
#===========
end; /*** End Loop 1 for Blocks ***/

###########  Main Experiment Complete


# Close all the open files
F_Session_List.close();
F_Questionnaire_Texts.close();

# Finish off the session!!!
T_End_Thanks.present();