DMDX Help.


Prose Keyword

<Prose a, b, c, d>
<Prose option>

options:
utf8
utf8bom
cursor


    Switch to facilitate typed prose, also a clock on specifier, the first two UTF options are only valid when <Prose> is used as a parameter.  <Prose> is used in combination with branching, macros and either <ProgressiveX> or <Instruction> to gather typed text from the console.  a, b, c and d are pre-existing macro names (they should be empty before use of <prose> commences).  After <prose> has been used macros a and b are plain text suitable for emitting into the data file and macros c and d are marked up DMDX frames suitable for display in an item (they contain double quotes and frame delimiters if more than one word has been typed).  The reason there are a pair of macros for each type of data is that the first macro is the data before the cursor and the last macro the data after the cursor.  In version 6.1.6.0 of DMDX the <prose cursor> option was added that greatly improves cursor manipulation (see below).

   
<Prose>
is quite superior to either <ZillionTypedResponses> or purely macro based typing as <prose> uses Windows messages to assemble the typed text and thus knows about case and auto-repeat, neither of which is accessible with other methods.  The only keys that need to be mapped are the ones that terminate the prose typing session, all other keys are transparent as the Windows messages used to generate the typed prose are not passed through the regular DMDX input processing system (they couldn't be because there's no way ahead of time to enumerate all possible keys, a feature central to DMDX's input processing).   Instead when a Windows message comes in that affects the prose (either printable characters or editing commands) the prose handler signals that the response has been timed out and the item should branch unconditionally back to itself to display the changed prose.  Only select keys are used, excluded keys include {, } and \ (because they're reserved for the RTF syntax) and of course ; and " that are sacrosanct DMDX item delimiters.

    As of version 5.3.3.0 of DMDX there are two options that can only be used with <prose> on the parameter line and they relate to use of <prose> with DMDX's Unicode option and they affect how Unicode characters are emitted into DMDX's output data file.  The first is utf8 that makes DMDX use the UTF-8 encoding instead of whatever the active code page is on the machine and the second utf8bom that uses UTF-8 as well as making DMDX emit the UTF-8 byte order mark (BOM) at the start of the data file that some editors require in order to recognize UTF-8 being used (the BOM should be transparent but you never can tell so it's use is optional).  Note that utf8bom only affects data files started with it in effect, if you've already run a subject and saved it's data and then switch utf8bom on there will be no BOM added to the beginning of that data file.  With the addition of <safemode 3> that makes DMDX re-execute the current item when focus is shifted away from DMDX the use of Pinyin or other input method editors or keyboard accelerators (that facilitate typing Chinese and other Asian languages) should now be possible as long as you're also using the Unicode option and either of these UTF-8 options.

      In version 6.1.6.0 of DMDX the <prose cursor> option was added that should be used in the frame that displays the cursor between the two marked up macros (see examples below) and it allows DMDX to track where that frame has been drawn (using the <StoreCoords> functionality) so that HOME, END, UP and DOWN behave more like they do in a regular text editor.  Because the logic to do all of this is quite convoluted and it breaks if <inst hardmargin> isn't in use <prose cursor> will set the hardmargin mode for that item.  Also note that the frame with the <prose cursor> option in it doesn't count towards the width of the display when <inst> is wrapping things so that stuff doesn't jump around when the cursor moves from one line to another on account of the fact there's no zero width cursor available for us to use (a singular failure of Unicode if you ask me given some of the guff it's got in it) so your right margin (assuming you're not using right2left) will be over stepped by whatever the width of your cursor turns out to be every now and then.  Also note that long macro names beginning with a $ (so .$a0t. for instance) will be used internally to track where typed text is put on the screen and they are all cleared every time <prose cursor> is used -- hopefully no one was using those on account of $ being a scramble delimiter, if not, sorry about that...

    <Prose> requires a rather specific item file that gathers a single character of input, displays it and then loops back to gather the next one, only breaking out of the loop once it recognizes whatever character is going to end the input session.  For example this item file records a page of typed prose:

f1 <vm desktop> <id keyboard> <nfb> <cr> <inst hardmargin>
~3 ma++ mb++ mc++ md++ <mpr +F12> <dfm .75>;
+1 <delay 2> <inst .1,.1,.8> "Please ", "type ", "some ", "prose ", "and ", "press ", "F12 ", "when ", "done." <inst nl>, <inst nl>, ~c, "|" <prose cursor>, ~d <prose a,b,c,d> <mwb +F12,2 bu,-1> ;
2 <emit typed text is:~a~b:> "Done";

 
    Almost all elements of that item file are essential, feedback must be disabled, it must continuously run, the macros must be set empty before each use of <prose> (otherwise (a) on first use there would be messages about uninitialized macros being used and (b) because on repeated use there's no way the prose logic can set them up before the item has been parsed when the macros expand), F12 (or other similar keys) has (have) to be used to end typing because using the Enter key is part of typing prose (although if you're just gathering a single line of prose you can of course use Enter to terminate the prose) and <delay 2> is needed otherwise the display will lag behind the typing.  Note that item 1 has a + correct response indicator because <prose> is a clock on keyword.  Even the <inst nl> keywords are necessary (or at least one of them is anyway) if you're going to gather multiple lines of input with <prose cursor> as the cursor up and down movement code has to assume the typed text starts at the leftmost margin (having just tested an item without the <inst nl> in it it does in fact work, however you won't be able to use the UP key when the cursor is below text that wasn't typed).

    Note that we're using <emit> in item 2 to record the typed prose in the data file and that <emit> is currently limited to 500 characters of text so if you're anticipating having more than 500 characters of prose per item something will need to be done (either I modify DMDX to allow more characters or you use a font that's too big to allow more than 500 characters on the screen at once).  Also note the preamble on that <emit>, that's because if the first character after the emit keyword is a number <emit> will try and emit a counter of that number and when it doesn't find it DMDX will puke with a syntax error when a subject starts their prose with a number...

    Here I'm using a vertical bar as a cursor (one can use the arrow keys to move around the text), you could in fact put any character you liked between the ~c and ~d frames.  In fact one thing I experimented with was having the cursor flash by making the timeout 500 milliseconds or so and having a duplicate <prose> item following with only a space between the ~c and ~d frames however a space isn't the same width as a vertical bar and having the text move a few pixels with the cursor flashing was weird.  However if you did find a character the same width as a space it would work pretty well (you also have to remove the bu -1 from the first <prose> item).

    Note that in the past <Prose> may have been usable with <ProgressiveX> instead of <inst>, however I have my doubts as if you want to include any sort of explicatory text it blows <px>'s spacing right out of the water and I have trouble believing I changed something there, even inadvertently, question is how did I ever think it was going to work and did I actually test it or not.  Either way it sure doesn't work as of 10/23/20.  I even recommended it for remote testing (using a #keyboard input device instead of keyboard anyway), however my example (that is here) has used <inst> since as long as I can remember which makes me think I didn't in fact test the <px> example, wouldn't be the first time I'm guilty of that and it likely won't be the last either.  If you're super curious here it is however I strongly recommend you ignore it and use the <inst> example, even if you are only gathering one line of input (like my remote testing example starts off doing):

f1 <vm desktop><id keyboard> <nfb> <cr>
~3 ma++ mb++ mc++ md++ <mpr +enter> <dfm .75>;
+1 <delay 2> @-2 <x .1> "Please type some prose and press enter when done." ,
            <px .1> ~c, "|", ~d <prose a,b,c,d> <mwb +enter,2 bu,-1> ;
2 <emit typed text is:~a~b:> "Done";


    Here even though <Prose> is marking up the text as if it was to be displayed by in an instruction item our use of <ProgressiveX> gets around that and the fact that other keys (like Enter) will cause <inst> specific flags to be set is inconsequential if <inst> itself hasn't been used.  But as noted above, pretty sure that explicatory "Please type some prose and press enter when done." frame is going to bork the use of <px>.


    Note that if you are going to input multiple sections of prose you have to clear the macros between usages:

f1 <vm desktop> <id keyboard> <nfb> <cr>

  

~3 ma++ mb++ mc++ md++ <mpr +enter> <dfm .75>;

 +101 <delay 2>  <inst .1,.1,.8> "Please ", "type ", "some ", "prose ", "and ", "press ", "enter ", "when ", "done." <inst nl>, <inst nl>, ~c, "|" <prose cursor>, ~d <prose a,b,c,d> <mwb +enter,102 bu,-101> ;

~102 <emit typed text is:~a~b:>;

 

~3 ma++ mb++ mc++ md++;

 +111 <delay 2>  <inst .1,.1,.8> "Please ", "type ", "some ", "more ", "prose ", "and ", "press ", "enter ", "when ", "done." <inst nl>, <inst nl>, ~c, "|" <prose cursor>, ~d <prose a,b,c,d> <mwb +enter,112 bu,-111> ;

 112 <emit typed text is:~a~b:> "Done";



    When using <prose> with right to left fonts and <inst right2left> it is necessary to include at least one character before the macros in the right to left font you wish to have the typing rendered in.  While this is true to use any font other than the default one DMDX happens to be using it's more critical for these fonts:

f1 <vm desktop> <id keyboard> <nfb> <cr> <inst hardmargin>

0 ma++ mb++ mc++ md++ <mpr +enter> <dfm 1.5 > "Hebrew typing test";

+1 <delay 2> <inst right2left> <inst .2, .4, .9> <xyjustification RIGHTTOP> "אנא הקלד עוד ועוד כאן." <inst nl>, ~c, "|" <prose cursor>, ~d <prose a,b,c,d> <mwb +enter, 2 bu,-1> ;

2 <emit typed text is"~a~b">"סוף";


    Note that it's possible <prose> may not correctly handle East Asian characters and other Unicode/double byte code page sorts of considerations however I expect turning DMDX's Unicode option on and the <prose utf8> option will solve them.  If you are attempting to get it working there and have trouble with characters being mangled subscribe to the DMDX list serve (details here) and let me know, there's only so much testing I can do as the locale of my machine is English.  Note also that <prose> is probably not going to work with Unicode end points beyond U+FFFF even after you turn the Unicode option on, or least it might work but when back spacing over those characters they're likely to get split into two invalid UTF-16 characters and will reform again when the back spacing clears them.  No way I can test it as ALT + only works with four digit Unicode end points (ALT + 11010 is the same as ALT + 1010) and if I can't test it I'm not keen on adding the code that detects it unless someone hassles me to do so and can test it themselves.

 

DMDX Index.