General Notes for Logflash Conversion

          1.The break-up of the program into multiple source files is
             arbitrary.  Turbo-Pascal cannot handle more than 64K source, and
             the totality of LogFlash source is much greater.  Insert the other
             files' source into the main program "LOGFLASH.PAS" at the {$I
             filename} statements for each.

          2.Other compile directives {$I-} disables I/O checking on the
             indicated I/O procedure call.  This prevents MS-DOS from aborting
             on file I/O errors; instead it returns a status (which procedure
             FILEIO checks).

          3.File structures:

             a.  The input file is a text file editable by an outside editor.
                 It uses fixed length fields to easily enable data inspection
                 and input.  It also is flexible; it allows the same file to be
                 used for input to LogFlash2, which will test and teach affixes.

                  1)  LOGDATA.FLA  (rawfile)

                      Format: sequential text file; no random access possible.
                      80 character length.

                      Line 1:
                      chars 1-5 number words in file, excluding control rcd.
                      chars 7-21  language name (blank defaults to LOGLAN).
                      chars 22-80  comments.

                      Other lines:
                      chars 1-6 Loglan word.
                      1 space
                      chars 8-19Affixes.
                      1 space
                      chars 21-35 English word.
                      1 space
                      chars 37-76 English explanation.

                  2)  Lesson file (also sometimes called wordfile or filefile)
                    [name] + 1.FLA or NONAME1.FLA (if default).

                      Format: random access file with 1 control record and many
                      records of word data.

                      First record (control record - filefile):
                      sn        integer     session #       init 1, incremented
                                                            as we go.
                      ty        char        session-type    init C = gaining
                                                            can be M =
                                                                   B = Brush-up
                      ls        integer     last lesson#    init 12 (failure
                                                            forces next
                                                            lesson=13 (new wds)
                      ml        integer     "more lesson"   lesson number of
                                                            current lesson pile
                                                            if it has move than
                                                            250 words.  The
                                                            program updates the
                                                            file after a 250-
                                                            word partial lesson,
                                                            setting this flag.
                                                            So, if you stop and
                                                            restart it doesn't
                                                            screw up.
                      bg        integer     # new words lessons left
                      nr        integer     # records in file
                      wdcnt     array[1-14] integer         # words in each
                                                            lesson pile.
                      filelang  string[15]  language name from rawfile.
                      comments  string[59]  any comments from rawfile.
                      morecount integer     # more done     if this lesson has
                                                            ml flag set (more
                                                            words for this
                                                            lesson exist), this
                                                            tells how many parts
                                                            (@ 250 words per
                                                            part) have been
                      dummy     393 bytes   pad out record to total of 512

                      Other records (word data - wordfile):
                               (6 words are packed in a record, with this format
                               for each word.  Each word takes up 83 bytes,
                               leaving 14 spare at the end of the record (and
                               they are padded to make the record 512 bytes).

                      lg/lw     string[6]   Loglan word (Loglan word to be typed
                      en/ew     string[15]  English word (keyword to be typed
                      es1/sp1   string[12]  Affix data, or special data to go
                                                            with lg/lw
                      es2/sp2   string[40]  expanded English definition to go
                                                            with en/ew
                      fp/pii    integer     current lesson number for word.
                     sr/lr     integer     word number in file; allows random
                                           access to position directly to word
                                           for file update.
                     ym        integer     if new word pile, this is the session
                                           to introduce the word; otherwise,
                                           it's the last session # the word was
                                           tested in.

                  3) LOGWORK.FLA(Cassette file position)

                    Uses identical file record structure to #2's control record,
                    but only field sn is used.  It contains an integer value
                    which points to the word in the rawfile (see #1) which was
                    saved at the end of a previous cassette review.  The file is
                    recreated any time a new save is done.  An I/O error will
                    terminate the program if no position was ever saved.

                    Only 1 LOGWORK.FLA can exist per disk, so only 1 position
                    can be saved.  This makes sense since we will only be
                    sending one cassette per order.  It makes copying the
                    program with cassette a little less friendly an option.

          4.Much of the organization of the files and program structure is done
              to minimize I/O reads & writes of the word files.  This is slow by
              any standard, and must be written for maximal efficiency.  A
              normal session has between 10 and 12 lessons actually tested.
              This means 25 times reading the entire file (possibly more).
              Running the program with a floppy-based data file is extremely
              slow.  The packed data file itself is over 100k, so it is not a
              reasonable option to keep it in memory.

          5.For modularity, any common procedure which opens the word file will
              close the word file before returning.  This ensures that the
              processing starts at the beginning of the file and that the
              correct format for the type of record is used.

          6.The program was originally written in interactive BASIC, then
              translated to Turbo-Pascal.  We are left with a lot of two-letter
              variables and some fragmented code because of this (also some
              parenthetical references to line numbers).  We had to maintain the
              flow to be sure all loose ends were caught.  In particular, the
              procedure session (see later) was very complex, so structuring did
              not work cleanly.  It relies on null conditions, etc.  So, please
              test any rewrite, especially in this area, extremely thoroughly.

          7.At least one change is planned for the future.  When the textbook
              is complete, we will have a set of lessons where we expect certain
              words to have been introduced.  We thus will add a setup menu
              option to use the textbook-order for lessons.  A 2-digit textbook-
              lesson number will be on each line of the raw file to use in
              assigning the initial session number for the new word lesson
              (rather than a random one used in the present program).

            We may also restructure at some point to:

                a.  Separate setup from the regular program or make it a Main
                    Menu option.

                b.  Create an umbrella program for all LogFlash programs with a
                    Main Menu for setup or run of any of the LogFlash programs.

                We would like feedback on how these will affect your versions.

          8.Please test your revisions thoroughly, since we can't.  Errors will
             give LogFlash a bad name.

          9.It will be seen that LogFlash is currently designed as a generic
              language program.  While distributing a Loglan version, we are
              attempting to hold rights to distribute a slightly modified
              generic version as a tool for teaching other languages.  The
              proceeds from such a program would support Loglan.  Our Shareware
              license is specifically written to cover modifications to the code
              to preserve our marketability.  Please be considerate of our
              intent, and, in distributing your work, enclose the license in any

          10.  It should be explained that there are three learning modes in
              LogFlash: "C" = Gaining Control, "M" = Maintenance, "B" = Brush-
              up.  The user starts out in "C", and can change to "M" whenever he
              has no New Words left unseen. In "C", the Under Control words are
              not tested. In "M", neither the New Words nor the Recog2 words are
              tested.  "B" mode is meant to be a quicker form of "C", so it does
              test the New Words, but doesn't test Under Control or Recog2.

                           Notes on Data Items in Turbo-Pascal

          type STRING    maximum size is set by the type statement, so string[6]
                        has up to six bytes of character data.  As stored on a
                        file, the string is prefixed by a 1-byte binary value
                        indicating the actual length of the item, but the max
                        length is always reserved in the record.  So, even
                        though that string[6] may hold only three bytes of data,
                        on the file it takes up 7 bytes: 6 bytes for maximum
                        allowable length + 1 for the length-byte (which has a
                        value of 3).

          type CHAR   1-byte ASCII data.

          type INTEGER   2 bytes binary data (low order byte first, though this
                        shouldn't matter to you).

                               Order of Procedures In Files

          LOGFLASH.PAS (main program, which will include all the others)

            (include here LANGKEY.PAS, for receiving and processing key input)

                langline Processing of special characters for some foreign
                        languages.  Will be expanded in  Logflash2 to handle
                        screen positioning for multiple inputs per screen.

            (include here LANGIO.PAS, for handling I/O errors)

                fileioProcess MS-DOS file errors to give some understandable
                        explanation of the problem.

            (include here LANGMISC.PAS, procedures yanked out of main program
                because of space problems.  It includes mainly some common
                routines and special routines done only at certain times.)

                readchr  Get a character from the keyboard and echo it.

                upcases  Set a string to all uppercase for comparison.

                asksess  At the end of a session, ask user if he wants another

                askless  At the end of a lesson, ask user if he wants to
                        continue to the next lesson.

                endrunClean up at end of run (includes ensuring control data is
                        updated).  Normal termination.

                resetfReset all words to new word pile.  Effectively allows
                        user to start all over again like new.

                regroup  Regroup remaining New Word or Under Control words
                        (depending on session type) to mix words and even-out

                chgsess  Change session type to Maintenance/Brush-Up if no new
                        words left.

                newdone  processing when all new words are done.  Asks if user
                        wants to change to Maintenance, since all New Words have
                        been seen.

            mix     Pseudo-random mixing of the lesson words (in arr[]).

            review  Review of words at the start of New Word and Error lessons.

            recprac Practice of Recog/Recall errors for each word until it is
                    correct 6 times consecutively.

            update  Updates the wordfile at the end of each lesson.

            testreco  Test recognition (Loglan prompt, English answer)

            testreca  Test recall (English prompt, Loglan answer)

            getwds  Select words for this lesson from word file.

            getfdata  Get session control information from control record in
                    word file (called filefile when accessing control record).

            errpile Control for error word lesson.  "Error" lessons are those
                    with even numbers for the lesson number.

            goodpile  control for regular (non-error) word lesson.  Note that
                    the "Failure" pile is a regular lesson.

            session Controlling procedure for full session of lessons 1-14.

            (include here LANGFL1B.PAS, more procedures yanked out of main
                program because of size limitations.  It includes mainly some
                common routines and the set-up menu processing.)

                vocab    Review of words (from raw file) to go along with the

                setfil1  Common processing for word file creation.  It does the
                        formatting and writing of the control record for the
                        word file.

                setfil2  More common processing for word file creation.  This
                        one neatens up at the end for the last file record.

                buildwd  Control to build one word's data to lesson file
                        (wordfile) from the raw file.

                buildfil Control building of file when selecting all raw-file
                        words for the user.

                selctfil Control building of file when user is selecting
                        individual words to include.

                setup    Control setup-menu processing.  Routes to the correct

                checkftot  Check word pile counts vs a control total.  Allows
                        automatic recovery from certain abnormal terminations
                        (such as power out) where the control record may not
                        have been updated properly.  This has happened.

                initvalues initialization at start of run.

            main pgm  Present summary of piles & main menu.  Route based on
                    main menu selection.

              System Routines - you may need to supply these if you have no

          randomize Set up random number generator.

          clrscr    Clear screen

          gotoxy    Position cursor to (column,row)

          read      Read non-text file.

          write     Write non-text file or, if screen, write text without CR.

          readln    Read text line.

          writeln   Write text line with CR.

          clreol    Clear from screen position to end of line.

          (fileio)    Must be redone to handle your machine's I/O errors.  We
                    want to have a normal termination (not a bomb) when
                    possible.  We also want user-friendly error messages when
                    files are missing, etc.

          fillchar(x,y,z)  fills a data area, x, with z, for a length of y

          delay(x)    Delay x milliseconds, then continue.

          odd(x)    True if x, an integer, is odd.  False if it is not.

          upcase(x) x, a character, is made upper case.

          pos(x,y)    Function giving the starting position in string y of
                    string x.  Zero if x not contained in y.

          copy(x,y,z) Returns z characters from string x, starting at position

          length(x) Returns length of string x.

          halt      Stops program and returns to operating system.

          keypressed  Returns "true" if a key has been pressed.

          random(x) Returns a random number between 0 and x.

          sizeof(x) Returns the number of bytes reserved in memory for variable
                    x.  So, for a string[6] storing 3 bytes of data, this will
                    return "6".

          assign    Links a real file name with a file variable name to be used
                    in the program.

          rewrite   Opens a file for output.  To write a new file or overwrite
                    an existing file.

          reset     Opens a file for input & position to the beginning of the
                    file, or, for output, open an existing file.

          seek(x,y) Position random file x to record number y (first record in
                    record number zero).

          flush     Ensure that last buffer-full of data has really been written
                    out to the file.

          close     Close file.

          IOResult    Returns a value based on the type of I/O error that has

                             Detailed Structure of LOGFLASH1

          Main program (last 2 pages of LOGFLASH.PAS)

             Randomize: system routine to set up random number generator.

             Initvalues: initialize pile counts.

             Copyright screen.

             Display set-up functions.  Ask if set-up desired (Y/N).

             Y ->set-up:

                Initialization for set-up.

                Loop until set-up option 4 is chosen and processed (or
                termination requested with option "*").

                Clrscr: clear screen: system routine.

                Display set-up menu.

                Read selected option (1 char).

                Process based on selected option:

                    1 -  Vocab "REVIEW VOCABULARY":

                       Fileio called after each I/O to the files on disk.

                       Clrscr: clear screen.

                       User may have saved a tape position.  Only one such saved
                       file exists.  If a tape position was not saved, it is
                       presumed that the user has rewound the tape, so we want
                       to start at the beginning.

                       Continue from saved position (Y/N).

                           N - Skip control record and continue.

                           Y - Skip number of words already reviewed (number is
                           LOGWORK.FLA- field "sn"in, minus 1), then continue.


                       Display a logo and legend

                           Any key continues, except:

                           "*" key returns to set-up menu.

                           "1" resets to beginning of file, to go with beginning
                           of tape.

                       Loop until end of file:

                           Read a raw record (LOGDATA.FLA).

                           Position on screen to 1,5 (col,row).

                           Clear to end of line

                           Display the raw record as is; the tape will match the
                           raw file order.

                           Read a character from keyboard.

                              "*" - ask if user wants to save position.

                                  If Y, then write current position to

                              "1" - reset to beginning of rawfile.

                              Anything else - get next raw record

                       End of loop-until-end-of-file.

                    2 -  Buildfl (select all words for a user).

                       Open raw text file.

                       Read first line (control data).

                       Get # of words in file (chars 1-5 of control line).

                       Setfil1 (common processing part 1):

                           Reopen raw text file.

                           Read control line

                           Get # of words in file.


                           Get user name (up to 7 characters), with
                           default="NONAME".  Note: turn of special character
                           processing for this input to allow ":" in for
                           specifying non-current disk (e.g. A:5CHAR); otherwise
                           it tries to make an A with an umlaut.

                              Langline (accept data until ENTER is hit,
                              modifying for foreign characters).

                           Ask user for number of New Words per lesson (0-99,

                           Check for valid entry.

                           Set-up control record in Word/Lesson file (user-

                              session = 1.

                              lesson = 12 (i.e. - New Word Lesson, #13, next)

                              session type = C (Gaining Control).

                              No overflow lesson.

                              #New-Word-piles = #Words / pilesize + 1.

                              # records in Word/lesson file = #Words / 6 + 1
                              (add 1 if rounding requires incomplete final
                              record, at 6 words per record).

                              Get language name, if any, from raw file.

                              Get comments, if any, from raw file.

                           Write control record.

                           Close and then reopen file with alternate record
                           format for words.

                           Skip control record.

                       For each record in the raw file:

                           Read the raw record

                           buildwd (copy the raw data to the Word/Lesson-file
                           word-subrecord, and assign a new word lesson at

                           count subrecords, and store every 6 as one physical
                           record in the Word/Lesson file.

                       At end of file:

                           setfil2 (remainder of common processing)

                              Close the raw file.

                              Write our any incomplete word-file record, padding
                              it out first.

                              Notify user.

                    3 -  Selectfil (user-selected wordset. We may sometime get
                    rid of this).


                       Ask user how many words maximum to select (he can quit
                       before this, but can't get more).

                       setfil1 (remainder of common processing.  See option 2,

                       For each record until end of file or max words selected
                       or user asks to quit:

                           Get a raw record.

                           Display it and # words left to select.

                           Ask user if he wants this word.

                           Y - (add word as in option 2):


                              Decrement counter.

                           N - (skip word).* - (exit set-up).

                           other - (process same as N).

                    4 - Exit set-up:

                       Exits the set-up loop and  falls though end of routine,
                       thus continuing on to Main "N" answer, below.

                    * - Exits program.

                End of set-up loop.

             N - (regular menu processing).

                Ask user's name.

                Eliminate special character processing to allow ":" in name.


                Add suffix to get wordfile name [name]L.FLA or NONAMEL.FLA.

                Initialize flag ("ct" for "change type of lesson") used in
                resetf to false; this indicates that if file is reset, the type
                of lesson will be "Gaining Control".

                Getfdata (get word file control record data):

                    If the user has a bad name (i.e. file not there), the
                    program will terminate per fileio.

                    Open the lesson file for the control record (filefile).

                    Get the control record (it is first).

                    Overwrite language name if it isn't blank in control record,
                    otherwise use "LOGLAN".

                    Close lesson file.

                Checkftot (ensure lesson file integrity).

                    Check each file count for negative number of words.

                    Add all pile counts and check against control record total
                    word count.

                    If any pile has a negative count, or the total word counts
                    do not match:

                       Read the entire word file, recreating the control-record
                       word counts and total count.  Notify the user that this
                       is happening.

                Get first lesson #.

                If it is his first time through, don't ask the user if he wants
                to continue.

                Main Menu processing:

                    Repeat until an "*" entry, either from main menu or from
                    deep in lesson processing (where it always means the user
                    wants to quit).


                    Display most recent session # and lesson #, and all lesson
                    names and #'s of words in each lesson.

                    Display Main Menu - ask for choice (these procedures are
                    described elsewhere to keep the flow clearer).  Note:
                    choices 2, 3 and 4 all come back to the main menu loop;
                    others don't.

                       1 - Start lesson: session (do lessons) - see on page ###.

                       2 - Chgsess (change type of session, e.g. from Gaining-
                       Control to Maintenance) - see page ###.

                       3 - Resetf (restart at beginning).

                           Go back to initialization as if just starting in "N"
                           for answer to set-up question;, however skip the
                           prompt for the name.

                       4 - regroup (reorder word-presentation groupings) - see
                       page ###.

                       * - endrun (clean up at end) - see page ###.

                           Exit Main Menu loop.

                       other - ask again for valid entry.

                End of Main Menu loop.

          End of program.

                             Expansion of Main Menu Routines.


             Cleans up lesson numbers.

             Updates control record to ensure a proper start next time.

             Ends program.



             Do not allow session change if new words remain (return if error,
             with user msg).

             Otherwise, indicate current session type and ask which type to run

             Input selection and validate.

             If change to Brush-Up, must move all data back to "New Word" pile.
             This calls resetf.  The flag "ct" (change type) is set to true to
             indicate that we want Brush-up as the type in the control record,
             not "Gaining Control".

             Reset "ct" to false, so if resetf done again from elsewhere, it
             will go back to "Gaining Control".



             (note: this is called either from Main Menu processing or from
             chgsess, above).

             Almost identical to the set-up routine buildfl, but it doesn't need
             to read the raw data.  It updates the control record.  It asks the
             user for a pile size (average), then randomly distributes the words
             in the lesson file into "New Word" lessons with that average size.
             These are all put down in the new word pile.  The control record
             session type is changed based on whether the flag "ct" (change
             type) is true or false.

             Return to calling procedure.


             Similar to resetf, but doesn't move words in any lessons except
             "Under Control" (if session type is Maintenance) or "New Words" (if
             session type is "Gaining Control" or "Brush-Up").

             The session number and other control record data is unchanged, but
             the number of new word lessons is changed, if applicable.

             Return to Main Menu.

          Session: This is the main procedure controlling activities in a
          session, both lessons and practices.  The first thing it does is
          figure out which lesson is next.  The lesson file control area has the
          last lesson number, as well as an indicator of an overflow lesson that
          was only partially completed.  Session type (C, M or B) also affects
          lesson order.  If the user types an "*" at any of several points, the
          initial "while" clause will cause an exit to Main, which will in turn
          exit via endrun.  Otherwise this procedure loops indefinitely, running
          lesson after lesson based on the lesson determination logic in the
          first half of the procedure and the "case" statement covering each
          lesson type in the second half of the procedure.

             If an overflow lesson, do it next, otherwise increment last lesson
             by one.

             In M (Maintenance) or B (Brush-Up) mode, all Recog2 words are put
             in the Recog3 pile, so skip the Recog2 lesson (lesson #7 and its
             error lesson #8).

             If M mode, the last lesson of the session is 12 (Failure Errors).

             If C or B mode, then last lesson of the session is 14 (New Word

             If last lesson of session has been run, start new session:

                Increment session number.

                Determine first lesson of new session:

                    session 1: start with New Words (lesson #13).

                    session 2: start with Recog1 (#9).

                    session 3: start with Recog2 (#7).

                    session 4: start with Recog3 (#5).

                    session 5 and on: Basically, start with Recall1 (#3), but
                    see below.

                       In M mode, we have Under Control, but not New Word, so
                       start 2 lessons higher (one regular lesson plus its error

                       In B mode we have New Words, but lesson #7 (Recog2) is
                       skipped; therefore, if session is 3 or 4 we will be
                       starting 2 lessons higher.

                If "fs" (first entry) flag is true:

                    Don't bother asking user if he wants to start the "next"
                    session; assume he does.

                If "fs" is not true,

                    asksess: (ask user if he wants a new session)

                       Give lesson status and ask user about new session.

                       Validate response.

                If response is "N" ("no"), then endrun (clean up and end).

                Move all error word piles from previous session into the Failure
                lesson.  This entails a full read of the lesson file.  Any word
                in an even numbered lesson is moved into pile #11 (of course
                skipping any stray data in the padded portion of the last
                record, which would have a zero lesson number). "Chgflg" (Change
                Flag) is used to minimize file writes. It is set to true if any
                logical record of the physical record needs to be updated, so we
                only have to rewrite a record if "chgflg" is true.

             If first lesson of session, error lesson (even numbered lesson) or
             continuation of an incomplete lesson:

                Do not ask if user wants the lesson.  Assume he does.


                askless (ask if user wants lesson; very similar to asksess,
                which asks about a new session):

             If response is "N" ("no"), then endrun (clean up and end).

             Control lesson based on lesson number:

                #1 (Under Control pile):

                    Note: the Under Control pile has many sessions' data, but
                    the last session tested for each word is in its "ym" field.

                    Determine the oldest words (lowest "ym" field).

                       If it is a continuation lesson for Under Control (mr > 0)
                       or the oldest set of words has already been determined
                       (oldestset > 0), then there is no need to re-find the
                       oldest session number in the Under Control pile words.


                           Read through the file for all words in pile #1 (Under
                           Control), and save the lowest "ym" (session number
                           last used).

                           Incidentally, since we're going through the words
                           anyway, make sure all Recog2 (pile #7) and Recog2
                           error (pile #8) words (never used when Under Control
                           is used) have been dumped into Recog3 and Recog3
                           errors (piles #5 and 6) instead.

                           Only rewrite the record if a change was made to one
                           of its subrecords.

                    Set variable "k" (a temporary parameter) to one more than
                    the oldest session number.  This will allow the common
                    processing routine getwds to select the correct words; it
                    selects for words OLDER (i.e. with a lower session number)
                    than "k".

                #1 continued, #2 through #12, and #14:

                    If an error lesson, the word stays in this pile (same lesson
                    number) for later gathering into the failure pile (when a
                    new session starts.  Thus "np" ("next pile") is not needed.
                    "ep" ("error pile") tells the processing to leave the word
                    in this pile.  Procedure errpile is called to test error
                    words (see later explanation).

                    If a non-error lesson (odd number), we indicate with
                    variable "np" where to put successful tested words, and with
                    "ep" where to put error words.  Procedure goodpile is called
                    to test the lesson words (see later explanation).

                #13 (New Word lesson):

                    Note: This, like the Under Control lesson, is complicated by
                    having several subpiles.  At setup or resetf or regroup
                    (described earlier), a session number was assigned to each
                    word to indicate when it should be first tested as a New

                    We have a dummy check for accidental fall-though in "M"
                    ("maintenance") mode.  It should not occur.

                    Check if any new word subpiles are left.

                    If so,

                       Set "k" to the current session + 1.  This will allow the
                       common processing routine getwds to select the correct
                       words; it selects for words OLDER (i.e. with a lower
                       session number) than "k".

                       Run the lesson:

                           review, testreco, update (all described later).

                           Set ld, hm, fs and bgi as in goodpile (described

                    If no new word piles are left,

                       perform newdone - ask user whether to change to "M" mode,
                       and do so if user says "Y" (yes).

                       Pretend like we've run a lesson, setting ld, hm, fs and
                       bgi as in goodpile (described later).

                Others: Shouldn't happen, but we have a check.

          Loop back to beginning of session for next lesson or end.


             This procedure is called by session for new words, and by recprac
             from errpile in each error lesson.  It presumes the words for the
             lesson have been read in.

             Loop through the words in the lesson (in arr[]),showing a new word
             each time the user enters a character, until all displayed or "*"
             entered by user.  Blank existing fields then write data for word in
             formatted screen.

          Goodpile (Common processing for non-error word lessons):

             If not Under Control lesson (#1), set "k" so only words that have
             not been tested this session are requested from getwds.  (There
             should be no others, so this check is probably superfluous now.)

             If not a continuation lesson, reset the lesson statistics: "gt"
             (number words tested), "gs" (number correct), "sc" (percent score).
             Otherwise we want to continue accumulations.

             Getwds: get words for requested lesson pile.  Described later.

             If words found, either testreca or testreco depending on lesson

             If back from testreca or testreco with "*" last entered, abort the
             lesson, saving no data from the lesson even if partially complete.

             Set up variables for update to ensure the control record is correct
             and that session operates correctly.


                Random access is used to update each word.  It calculates a
                record number and subrecord number for each item in arr[].  Then
                seek the record update it, and rewrite it.

                We then do a read through the entire file to update our lesson
                counts.  This was put in to prevent early bugs and could
                possibly be omitted by using the totals kept by the lesson
                procedures in "gt" and "gs".

             Return to session.

          Getwds (Get words from lesson pile meeting the session criteria)

             Variables used for controlling selection of words:

                 hr = number of words to skip if "mr" flag is set (error pile

                 nw = number of words selected for this lesson (initially zero).

                 mr = overflow flag if more words than 250 for a lesson.

                 hw = counter up to hr when skipping words (error pile only).

             Since there may be more than 250 words in the lesson, this
             procedure got very complicated.  With 99-word new word lessons, we
             have seen a lesson as high as 254 words in normal use, so this
             logic is critical.  And you may need a smaller array than 250 in
             your machine.

             Initialize number of words to skip (hr) to zero.

             If there are no records for the lesson (control record word count =
             0), set all variables (hr, nw, mr, hw) to zero UNLESS this is "M"
             or "B" mode lesson #5 (Recog 3) where lesson #7 (Recog 2, which is
             skipped in these modes) has words in it; we will want to pick up
             the lesson #7 words in lesson #5.

             Write message indicating words are being read, since this takes a
             while on floppy.

             If an error pile and a continuation lesson (God help a person with
             more than 250 error words), set up "hr" so that the poor guy
             doesn't get the same words twice.

             Read all the records and all the words in each record, skipping
             blank words (may be in the last record).

             For each word:

                 Skip all words up to "hr", if any.

                 If word is in pile #7 and we're in "M" or "B" mode, handle it
                 instead as if in pile #5.

                 If not in lesson wanted, skip word.

                 If error lesson, and word not put in during current session,
                 skip word (this may be an obsolete check).

                 If non-error lesson, and word not older (i.e. less than)
                 session "k", skip word.

                 If array is full, set "mr" for next time and exit the routine.

                 Otherwise, add word to the array:

                    Extract the data.

                    Increment "nw".

             At end, ensure that the overflow flags will cause proper processing
             in session.

          Errpile (common error pile processing controller):

             Similar to Goodpile, except:

                 Recprac is called instead of testreca/testreco, to practice
                 instead of test.  A flag tells recprac whether recall or
                 recognition is required.

                 Some of the logic duplicated from the if/then/else in goodpile
                 has been simplified.

                 Update is not called, since the words remain in the error pile
                 until the end of the session (this saves a lot of file I/O).

          Recprac (Does error word practice):

             This procedure requires that a given word be typed correctly 6
             times in a row before it is dropped from the practice.  Beware of
             logic problems if modified, especially ending conditions.

             Key control variables:

                 xx = count of words to practice.

                 pii = count from 0 to 6; how many times in a row correct.

                 fd = true if at least one word needed practice (pii[word] < 6).

                 n = Index to the array for testing order.  Equals 1 if about to
                 start next pass.  Equals "nw" at the end of the pass.
                 Incremented in the loop.  This is also used as an indicator to
                 know when to mix the pile of words.

                 pisave = pii to be saved for the "until" clause, since the
                 array index changes before the end test (a Pascal artifact).

             Pack the array; this may be an artifact of earlier versions, but it
             ensures integrity and doesn't take long.

             For each word, initialize pii to 0.

             If there are errors, call review.

             If no errors, just return.

             Initialize fd to false; will be set true if item to test is found.

             Initialize n to 1.

             Loop until:

                 "*" entered, or

                 This pass through deck complete (n=nw) AND no words were
                 practiced this time through (fd is false) AND the current word
                 has been tested 6 times.  We needed all of these conditions to
                 avoid logic glitches.

                 In the loop:

                    Count number of words to be practiced this time.

                    If at least one word is left, and we are at the beginning of
                    the deck/pass, then

                        mix: shuffle nw words in arr[] pseudo-randomly by

                    If current word (n) has not been practiced 6 times

                        Set "fd" to true.


                        Build either a recall or recog test screen based on
                        recaflag (it was set by errpile based on lesson number).

                        (Screen-building notes:

                           language name found in the rawfile at setup will
                           override default "Loglan" if non-blank.

                           function langline is used.  This checks for special
                           characters and supports use of this program for
                           languages other than Loglan, allowing, for example,

                           after displaying a correct/error notice, we allow
                           user to quit with "*".  Since no update is performed,
                           he must restart the error lesson next time.)

                        If word correct, increment pii for word (one more time
                        correct).  Otherwise set pii for word to zero (start
                        collecting your six times all over again).

                    If the user has not typed "*" to exit, increment "n" or, if
                    all words done (i.e. n=nw), reset it to 1.

                    Perform "until" check to see if we're done.

             When loop done, return.

          Testreco: test recognition. Called by either goodpile or,for New
          Words, session.

             Mix: pseudo-random exchange of words to shuffle the deck.

             For each word in the pile, or until "*" response:

                 Update lesson statistics (# correct, # left, % correct).

                 Write the Loglan and request English.

                 Get user's response, using routine langline.

                 Change response to upper case and compare to English keyword.

                 If correct:

                    Write "Correct" message.

                    Increment correct count.

                    Put word in next "good pile", np.

                 If incorrect:

                    Write "incorrect" message and correct answer.

                    Put word in error pile for lesson, ep.

                 Recalculate and display scores.

                 Ask user for key to continue or "*" to exit.


             Give final score.

             Exit the routine.

          Testreca: identical to testreco except test recall for lessons called
          by goodpile.

             Display and loop the same, except we display the English keyword
             (and accompanying English further explanation) and ask for the
             Loglan (or other language) word.

          Langline: gets keys as pressed, edits (for foreign characters), writes
          to screen; finishes in .

             Note: Routine expects to get screen and line position to start at,
             and max length of the entry expected (it will beep if user tries to
             go beyond).

             Position on requested screen position and display "cursor".

             For each character entered until :

                 Get pressed character.

                 If accents to be considered (not used for file names because
                 ":" might umlaut a vowel),

                    If item is one of "accents" (/\^:@%~_), remember relative
                    position in list, for later translation.

                    Error if used in 1st position, so BEEP if there; it is
                    expected after the thing it is to accent.

                    Check the previous character entered to see if it is allowed
                    this accent.

                        if it can, replace that character by the correctly
                        accented version.

                        if not, it's an error; BEEP and stay in same place on

                 If accents are not to be considered OR entry is not an accent,
                 processing depends on just what was hit:

                    : Just write out a blank. Don't accumulate it into
                    the answer string.  This will end the loop.


                        If at beginning of line (pos=0), this is an error, so

                        Otherwise, back up 1 character on screen, erase it,
                        delete last letter accumulated into answer string.


                        If beyond the end (max allowed), this is an error, so

                        Otherwise, add item to screen line and accumulate into
                        answer string.


                 Accent:       /      \     ^       :     @  %  ~  _

                 Takes char: aeiouE aeiou aeiou aeiouAOUy aA cC nN ao

                 To make:    aeiouE aeiou aeiou aeiouAOUy aA cC nN ao