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 Control can be M = Maintenance B = Brush-up ls integer last lesson# init 12 (failure error) 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 done. dummy 393 bytes pad out record to total of 512 bytes. 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). Word-subrecord: lg/lw string[6] Loglan word (Loglan word to be typed in) en/ew string[15] English word (keyword to be typed in) 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 distributions. 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 session. 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 lessons. 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 cassette. 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 procedure. 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 equivalent 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 bytes. 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 y. 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 occurred. 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. Clrscr 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 LOGWORK.FLA. "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. Clrscrn. 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, default=40). Check for valid entry. Set-up control record in Word/Lesson file (user- nameL.FLA). 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 random). 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). clrscr 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, buildfl). 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): buildwd. 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. Langline. 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). clrscr. 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. Endrun: Cleans up lesson numbers. Updates control record to ensure a proper start next time. Ends program. Chgsess: Clrscr 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 next. 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". Return. Resetf: (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. Regroup: 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 Errors) 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 lesson). 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. Otherwise: 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. Otherwise: 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 Word. 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 later). 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. Review: 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 number. 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. Update: 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 only). 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 exchanges. If current word (n) has not been practiced 6 times correctly: Set "fd" to true. clrscr. 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, umlauts. 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. clrscr. 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 screen. 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 BEEP. Otherwise, back up 1 character on screen, erase it, delete last letter accumulated into answer string. other: If beyond the end (max allowed), this is an error, so BEEP. Otherwise, add item to screen line and accumulate into answer string. Note: Accent: / \ ^ : @ % ~ _ Takes char: aeiouE aeiou aeiou aeiouAOUy aA cC nN ao To make: aeiouE aeiou aeiou aeiouAOUy aA cC nN ao