A Course in BTRON MicroScript for Beginners

Chapter 3: Working with Characters and Text


Processing Characters and Text

Programming languages have supported character and text processing features ever since it became possible to process characters and text on computers. Although C language has been used to write most of the character and text processing applications that are available today, other languages have also been used. For example, a dialect of the LISP programming language, normally used for artificial intelligence applications, was used to write the famous Emacs (Editor MACroS) text editor. The BASIC programming language, which was developed at Dartmouth College in New Hampshire to enable non-science students to write computer programs, was designed with character and text processing features from the beginning.

On the BTRON software platform, most character and text processing applications are written in C language, as is the case on other computer architectures. However, characters and text can also be processed using MicroScript. In this chapter, we are going to write some simple MicroScript programs aimed at character and text processing in character segments (text fields or boxes) and the Console to illustrate that point. And then, for more advanced BTRON users, at the end of this lesson, we are going to introduce some highly detailed MicroScript scripts that allow users to get into Basic Text Editor real objects and carry out different actions.

One thing that is important to keep in mind is that there are limits to how many character segments can be crammed into the work area of a MicroScript real object. A MicroScript real object is actually a graphics window that has dimensions of 4,000 x 4,000 dots, which is almost as wide as four XGA laptop displays. While that may sound like a lot of space, in terms of non-overlapping text, the entire space couldn't hold more than a couple of dozen standard letter-size pages. In terms of words, that would probably be about 20,000 words at most. Therefore, character segments should be used for small blocks of text (something along the lines of an index card) that will be flashed on the screen. For more voluminous text (the chapters of a book, for example), it is best to embed text real objects and call them up as necessary.

Outputting Characters and Text to Character Segments

In this section of this chapter, we are going to take a look at outputting characters and text to character segments. From the point of view of the MicroScript programmer, there are five places we can output characters and text. These are:

(1)
The system message panel via the MESG statement

(2)
A character segment via the TEXT statement

(3)
The Console via the LOG statement

(4)
A text real object via the FWRITE statement

(5)
A figure (graphics) segment or figure real object using "painted text"

In the previous chapter, we were exposed to the first three. The fourth is beyond the scope of a course for absolute beginners, although we have included some samples for advanced beginners below; and the fifth is a topic for graphics processing, which is the subject of the next chapter. Because the MESG statement is not really suited to the transmission of substantial amounts of information to ordinary end users, we will concentrate on outputting character and text information in character segments and the Console by respectively using the TEXT and LOG statements.

Since we have been comparing MicroScript with the BASIC programming language in the previous chapter, let's continue on and present some simple programs that are used to introduce character and text processing in BASIC introductory programming courses. Normally, the printing of something multiple times on the screen is the first step, so let's return to our old favorite, "Hello, world!" We will use the simple character processing script below, "CharPro1," to print "Hello, world!" on the screen three times, one above the other.

Before executing the program, however, we first have to create a character segment for the output to appear in, otherwise we will get an error message (something along the lines of the segment "Output" not being defined). This is the easiest part--just press on the Stencil tool next to the Finger-for-Selecting on the Tool Panel, then click inside the graphics window. When a text frame appears, press the space bar 30 times, then press Enter about 10 times. That will give you plenty of area to work in. Next, input, do not cut and paste, the script below in the text real object that is inside the MicroScript window. Note that the "\n" below has to be changed to the 'yen' (¥) symbol plus 'n' for the script to execute properly. When you convert the Japanese text file into an ISO/IEC-8859-1-based text file, which this document is, the 'yen' symbol plus 'n' automatically become "\n." Thus we have to reverse the process when we input a MicroScript script.

MicroScript script "CharPro1"
#                 Hello, world! Three Times (1)
# 
# This script prints "Hello, world!" three times in a character
# segment designated "Output." The three lines of text appear
# simultaneously.

VERSION 3
PROLOGUE
SCENE Output
CALL Print
END

ACTION Print
  SLEEP 1000
  TEXT Output, "%s" "Hello, world!\nHello, world!\nHello, world!"
END

The reason we have slowed down the script by writing SLEEP 1000 is because the script will execute and output "Hello, world!" three times even before the window is fully opened. Thus the output will look like a graphic placed there ahead of time, rather than text being printed. However, even with the inclusion of SLEEP 1000, the execution is so fast that we cannot see the three iterations of "Hello, world!" appear consecutively. The "%s" above indicates that the output is a character string.

MicroScript script "CharPro2"
#                 Hello, world! Three Times (2)
#
# This script prints "Hello, world!" three times in a character
# segment designated "Output." The three lines of text appear
# consecutively at one second intervals. 

VERSION 3
PROLOGUE
SCENE Output
CALL Print
END

ACTION Print
  SLEEP 1000
  TEXT Output, "Hello, world!"
  SLEEP 1000
  TEXT Output, "Hello, world!\nHello, world!"
  SLEEP 1000
  TEXT Output, "Hello, world!\nHello, world!\nHello, world!"
END

In CharPro2, we have added some SLEEP time between the screen printing of the iterations of "Hello, world!," and thus we can see each iteration execute consecutively. Notice that we have to refresh each iteration above every time we print a new iteration below. This is because the TEXT statement erases everything in a character segment every time it writes something new, but you knew that from the last chapter, didn't you.

MicroScript script "CharPro3"
#                 Hello, world! Three Times (3)
#
# This script prints "Hello, world!" three times in a character
# segment designated "Output." The three lines of text appear
# consecutively at one second intervals, with the previous line
# disappearing as a new line appears below it. 

VERSION 3
PROLOGUE
SCENE Output
CALL Print 
END

ACTION Print
  SLEEP 1000
  TEXT Output, "Hello, world!"
  SLEEP 1000
  TEXT Output, "\nHello, world!"
  SLEEP 1000
  TEXT Output, "\n\nHello, world!"
END

To illustrate this point about the TEXT statement one more time, we have created CharPro3. As the script executes, the previous iteration of "Hello, world!" disappears, and a new iteration appears below it. Anyone who wants to take on a challenge should try to add procedures that reverse the processing that takes place in CharPro2 and CharPro3.

It is also possible to stream character and text data across a character segment using the TEXT statement. "CharPro4" below, while a very large script, is an example of this. The reason the program is so large is that it is not possible to place a variable between '%' and 's'. On the other hand, using the cut and paste features of modern computers, the script can be quickly and easily created and modified. An advanced programmer might say it's better to use painted text in a figure segment, or even a separate character segment with the output in it, and slide it across the screen at the same speed using the MOVE statement. True, the size of the script would be dramatically reduced, and it would also be possible to create dozens of other messages for display, although you would not use the SCENE statement in such case as that will put the character segment "Output" flush with the left of the MicroScript window. Conversely, it is extremely easy to change the character font and size using the program below--just delete the existing character segment, and then create a new one in a new font and character size.

MicroScript script "CharPro4"
#                Text Streaming Right to Left
#
# This script allows you to stream a 15 character message
# from right to left across a 30 character wide text box 
# and then make it disappear. The message here, "Next:
# Yurakucho" refers to the train station one stop south of
# Tokyo station. The script simulates the messages streamed
# across information panels in Japanese subway trains. 

VERSION 3

PROLOGUE
SCENE Output
CALL TxtStream
END

ACTION TxtStream
 TEXT Output, "%45s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%44s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%43s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%42s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%41s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%40s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%39s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%38s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%37s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%36s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%35s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%34s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%33s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%32s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%31s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%30s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%29s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%28s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%27s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%26s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%25s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%24s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%23s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%22s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%21s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%20s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%19s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%18s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%17s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%16s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%15s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%14s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%13s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%12s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%11s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%12s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%11s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%10s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%9s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%8s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%7s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%6s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%5s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%4s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%3s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%2s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%1s" "Next: Yurakucho"
 SLEEP 250
 TEXT Output, "%s" "ext: Yurakucho"
 SLEEP 250
 TEXT Output, "%s" "xt: Yurakucho"
 SLEEP 250
 TEXT Output, "%s" "t: Yurakucho"
 SLEEP 250
 TEXT Output, "%s" ": Yurakucho"
 SLEEP 250
 TEXT Output, "%s" " Yurakucho"
 SLEEP 250
 TEXT Output, "%s" "Yurakucho"
 SLEEP 250
 TEXT Output, "%s" "urakucho"
 SLEEP 250
 TEXT Output, "%s" "rakucho"
 SLEEP 250
 TEXT Output, "%s" "akucho"
 SLEEP 250
 TEXT Output, "%s" "kucho"
 SLEEP 250
 TEXT Output, "%s" "ucho"
 SLEEP 250
 TEXT Output, "%s" "cho"
 SLEEP 250
 TEXT Output, "%s" "ho"
 SLEEP 250
 TEXT Output, "%s" "o"
 SLEEP 250
 TEXT Output, "%s" " "
 SLEEP 250
END

Incidentally, any experienced programmer who thinks that MicroScript is inferior to Java or Python, which are full-featured programming languages that are designed to operate independently of the underlying operating system, should keep in mind that MicroScript has statements--the PROCESS, MSEND, and MRECV statements to be exact--that allow programmers to call up and interact with C language functions. In other words, in the BTRON architecture, MicroScript and C language complement each other and are used in conjunction with each other. Therefore, if some function is missing in MicroScript, it can easily be called up from an underlying C language function that is either a part of the operating system, or that has been ported to the BTRON software platform to fulfill a special purpose.

Inputting Characters and Text in Character Segments

As mentioned in the previous chapter, another thing that is taught to students in BASIC programming courses is how to input, process, and output text using a short program that asks a user his name and then outputs a greeting. Since this is done in direct mode in BASIC, it is not such a difficult program to create, but in MicroScript we do not have a direct mode. We just cannot open a MicroScript window and print things on the screen. So first, we have to create input and output character segments, which we will name "Input" and "Output." Having already done this in the previous chapter, that should pose no problem. However, the INPUT statement used in the previous chapter cannot be used to input unspecified characters or text into the "Input" text box. That is because:

(1)
When we input characters or text using the INPUT statement while the cursor is aligned with the left margin of the character segment, the input characters or text will disappear to the left, and the data will be lost.

(2)
When we input text using the INPUT statement while the cursor is aligned with the right margin of the character segment, the input text will appear, but when we copy it, we will simultaneously copy all the space characters before it, and they will all appear in the place where we paste the character or text data.

One way to sort of get around this is to use the script in "CharPro5," a version of which appears on p. 317 of Personal Media Corporation's "An Introduction to BTRON MicroScript." This script allows the user to insert the cursor anywhere in the "Input" text box, but unless the user has a good eye for spacing, he will probably have to type his name twice to have the first letter of his name perfectly aligned with the left margin of the "Input" text box.

MicroScript script "CharPro5"
#                    Inserting the Cursor
# 
# This script allows you to insert the cursor anywhere in a
# text box designated Input and enter text to the left of the
# cursor. 

VERSION 3
PROLOGUE
SCENE Input
CALL EnterTxt
END

ACTION EnterTxt (s, n, x, y) PRESS Input
  INPUT s, x, y
END

In the above script [1], s, n, x, and y respectively stand for the segment where the event occurred, the number of the segment where the event occurred, the x coordinate where the event occurred, and the y coordinate where the event occurred. These are the "arguments," or the values that are passed, for the procedure that has been given the name EnterTxt. Notice that arguments are given inside parentheses.

The solution, not surprisingly, is to use a different statement, the KINPUT statement, which allows us to input characters and text from the left margin without any loss of data. Those character or text data are then extracted from the "Input" text box using the .TX state name. Unlike the .V state name, which extracts only the numerical data from a character segment, the .TX state name extracts all character and text data, including space characters that a human sees as non-data, since they contain no information that a human normally processes in his brain.

Accordingly, the MicroScript equivalent to the famous BASIC program mentioned above is "CharPro6" below. You can easily confirm what has been explained here by changing the KINPUT statement to the INPUT statement. Another interesting experiment would be to change Input. TX to Input.V and put a number after your name. What happens?

MicroScript script "CharPro6"
#                      Saying Hello (1)
#
# This script asks you to input your name and then greets you 
# using your name after you press the Enter key. 

VERSION 3
PROLOGUE
SCENE Input, Output
CALL Greeting
CALL Greeting2
END

ACTION Greeting
  TEXT Input, "What's your name?"
  SLEEP 1000
  TEXT Input, " "
END

ACTION Greeting2 KEY
 KINPUT Input
 IF $KEY==0x0A
 TEXT Output, "Hi, %s, glad to meet you." Input.TX
 ENDIF
END

We can make the above script a little more user friendly for non-native speakers of English by slowing it down and giving the user explicit instructions about what to do, as shown in "CharPro7."

MicroScript script "CharPro7"
#                      Saying Hello (2)
#
# This script asks you to input your name, tells you where to
# type it, and then greets you using your name after you press
# the Enter key. The script has been slowed down compared to
# the previous one.

VERSION 3
PROLOGUE
SCENE Input, Output
CALL Greeting
CALL Greeting2
END

ACTION Greeting
  TEXT Input, "What's your name?"
  SLEEP 2000
  TEXT Input, "Type here, and press Enter."
  SLEEP 2000
  TEXT Input, " "
END

ACTION Greeting2 KEY
 KINPUT Input
 IF $KEY==0x0A
 TEXT Output, "Hi, %s, glad to meet you." Input.TX
 ENDIF
END

Outputting Characters and Text to the Console

Another place where we can output characters and text is the Console. We do this by using the LOG statement in the same manner as the MESG statement. The only difference is that we have to open the Console prior to executing a program in order to see the output. Confirm this by inputting "CharPro8," opening the Console, and executing the script.

MicroScript script "CharPro8"
#         "Hello, world!" in the Console Three Times
# 
# This script prints "Hello, world!" three times in the 
# Console. To see the output, open the Console prior to
# executing the script. 

VERSION 3

PROLOGUE
  LOG "%s" "\nHello, world!\nHello, world!\nHello, world!"
END

The advantage to using the Console for output is that everything that is output will appear there, and, moreover, the output can be selected and copied for pasting elsewhere. In "CharPro9" below, we have a program that will output "Hello, world!" five times, but it could easily be changed to 100 times, and all 100 iterations would appear in the Console.

MicroScript script "CharPro9"
#          "Hello, world!" in the Console Five Times
#
# This script prints "Hello, world!" five times in the 
# Console. To see the output, open the Console prior to
# executing the script. Since the counter is used, the 
# number of iterations can easily be increased.

VERSION 3

PROLOGUE
CALL Print_String
END

FUNC Print_String
  LOCAL A:I
   REPEAT 5
    SET A=$CNT+1
    LOG "%s" "\nHello, world!"
   ENDREPEAT
END

Notice that in this script we are calling up a function, FUNC, with the CALL statement and assigning a local variable with the LOCAL statement. This is what Personal Media Corporation recommends as a good programming practice: calling up FUNC with the CALL statement, assigning its variable with LOCAL, and limiting the ACTION statement for use with the EXECUTE statement. The reason for this recommendation is that it helps with readability when you write very long scripts. So let's base our scripts on this recommendation from now on.

As an example of a practical use of the Console, we present "CharPro10" [2], which opens a character segment named Input, prints five words into it, finds the words within it, and then outputs them in the Console. If you try to do this with a character segment as the place of output, only the last word found will be printed.

MicroScript script "CharPro10"
#                      Finding Words
# 
# The script finds words in a character segment and then
# outputs them in the Console window. The Console window
# must be opened prior to executing the program for the 
# output to be seen. 

VERSION 3
PROLOGUE
SCENE Input
CALL Print_Words
CALL Find_Words(Input.TX)
END

FUNC Print_Words
 TEXT Input, "%s" "ant, bee, cat, dog, eagle"
END

FUNC Find_Words(s:S)
  LOCAL c:C, p:I

  p = -1
  REPEAT
    c = s[$CNT]
    IF 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
      IF p == -1
        p = $CNT
      ENDIF
    ELSE
      IF p != -1
         LOG "Found %s at [%d:%d]", s[p:$CNT-p], p, $CNT-p
         p = -1
      ENDIF
      IF c == 0
        BREAK
      ENDIF
    ENDIF
  ENDREPEAT
END

In the above script, we call up two FUNC statements in succession. The first one, Print_Words, is very easy to understand; it simply prints five words into a character segment labeled "Input," which should be at least 30 characters wide for the data to be displayed. The second one, Find_Words, is a little bit more difficult to understand, but once you know what all the pieces stand for, it is not that difficult to see what it does. Before we discuss those pieces, however, let's open the Console, execute the script, and see the output results, which are as below.

Found ant at [0:3]
Found bee at [5:3]
Found cat at [10:3]
Found dog at [15:3]
Found eagle at [20:5]

The output results tell the user that the "ant, bee, cat, dog, eagle" words have been found at positions 0, 5, 10, 15, and 20, and that all of the words are three characters in length, except for the last word that is five characters in length.

Now, let's examine FUNC Find_Words. Next to the name of the procedure, we find the argument with the variable 's:S', which stands for "string of characters." Below it are two local variables, c:C and p:I, which stand for 'character' and 'position', specifically the 'word starting position'. In other words, this procedure operates on a string of characters, inside which it will find certain alphabetic characters using the local variables c:C and p:I. The variable c:C is defined inside the function as the upper case letters of the alphabet from 'A' to 'Z', and the lower case letters of the alphabet from 'a' to 'z'. The variable p:I has been given an arbitrary negative starting value, in this case -1. This means a state in which an English word has not been found. In a case where p:I does not equal -1, which is to say when a letter of the alphabet has been found, the LOG statement is activated, and the output shown above is generated. Finally, when there are no more instances of c:C, the program breaks off. It should be noted that the $CNT starts at 0 and goes on counting until the program stops executing.

Since there are three variables in this script, it is a little difficult for a beginner to understand. Accordingly, we have shown in tabular form below how the variables operate in conjunction with each other as the script executes.

Position 1st 2nd 3rd 4th 5th 6th 7th 8th 9th 10th
Data: a n t , b e e ,
p = -1 0 0 0 -1 -1 5 5 5 -1 -1
$CNT 0 1 2 3 4 5 6 7 8 9
c c c c     c c c    
s s s s s s s s s s s

In addition to carefully looking at the above table, another method that can be used to understand FUNC Find_Words better is reading it from "right to left," and not just top to bottom. When you do that, you immediately spot p = -1 and p ! = -1, and come to understand what happens as a result. As an added note, it should be pointed out that this is one of the advantages of writing functions in indented blocks of code.

Anyone who wants to take up a challenge should try to revise the script to find a particular word in a string of words.

Sending Character and Text Output to Other Programs

It is also possible to send text output from one MicroScript program to another. An example of this is included in the MicroScript samples collection in Cho Kanji V. This sample, "Message Processing Example," has one MicroScript real object, which "CharPro12" is a part of, embedded inside another MicroScript real object, of which "CharPro11" is a part. When the user presses the Tab key of the top MicroScript program, the contents of the character segment (a text box 12 full-width characters wide by six lines down) in are sent to a character segment of the same size in the bottom or embedded MicroScript program.

Although this program may be a little too difficult for the average beginner to understand, we are including it in this chapter for four reasons: (1) it is part of the samples collection, (2) just because the beginner cannot understand everything about it doesn't mean he will be unable to copy it and use it for his own purposes, (3) parts of this program have already been discussed above, and (4) reading through the explanation will acquaint the beginner with new words and concepts.

TRON Web asked Personal Media Corporation for a detailed explanation of this MicroScript sample, and here is the full translated explanation below.

Introduction to MicroScript scripts "CharPro11/12"
In this example, there are the following three parts to data
hand over. First, it would be good to firmly enter these into
one's head ahead of time.

[1] Hand over of the process ID of the sending side
microscript.

    [Sending side microscript]
       | setgnm
        ↓
    [Global name "_MAINPID"]
       | 
        ↓ getgnm
    [Receiving side microscript] mpid

[2] Hand over of text segment character strings

    [Sending side microscript]
       | MSEND
       |
       | Type 0 message (text segment character string)
       | 
        ↓ MRECV
    [Receiving side microscript]

[3] Acknowledgement

    [Sending side microscript]
        ↑ MRECV
       |
       | Type 7 message ('A' 1 character)
       |
       | MSEND
    [Receiving side microscript]

For data exchange among different processes, there are two
types: the method in which we use MSEND/MRECV 
(interprocess message communication), and the method in 
which we use setgnm/getgnm global names). Interprocess 
communication is general-purpose communication, but in a 
case where we hand over a simple numerical value (ID), there
are cases where we use a global name. What we call "first 
handing over an ID with a global name, and then afterward 
carrying out communication through interprocess communication"
is a pattern that frequently exists.

There are eight kinds of message types that we can use, 0 
through 7. There are no rules in particular as to which 
number among types 0 through 7 we should use, but as long as
agreement has been obtained between the programmer creating the
sending side and the programmer creating the receiving side,
then it doesn't matter what we use. Here, they have decided to
to use type 0 in the handing over of the character strings of a
character segment, and to use type 7 for acknowledgement. Types
1 through 6 are not being used in particular.

In contrast to the sending side specifying a number from types
0 through 7, the receiving side specifies with a mask. On this
occasion, in a case where we receive message type 7, we specify
10000000 as a mask by counting in binary from the low end and
making the seventh bit 1, in other words, 0x80 in hexadecimal,
or 128 in decimal. (We count 0th, 1st, . . . , in order from
the lowest end of the binary numbers.) 

In a case where we receive message type 0, we specify 00000001
as a mask by counting in binary from the low end and making the
zeroth bit 1, in other words, 0x01 in hexadecimal, or 1 in 
decimal.  

Something that has been purposely made into a specification 
that specifies a mask is a specification that has taken into 
consideration receiving several different types of messages. 
For example, in a case where you would like to receive both 
message type 7 and message type 2, you specify 10000100 as a 
mask by counting from the low end in binary and making the 2nd 
and 7th bits 1, in other words, by specifying 0x84 in 
hexadecimal, or 132 in decimal.

Now, we will explain the actual microscripts line by line.

[Note: below each MicroScript script is a second version of the
same script fully annotated.]

MicroScript script "CharPro11"
#              Message Processing Example (Send)
#
# This script is part of the Cho Kanji samples collection. It
# transmits the contents of a character segment to the
# character segment of another MicroScript program embedded
# inside it when the Tab key is pressed.
# The contents of the sample's character segment read:
# "When you press the Tab key after inputting some suitable 
# characters, they are transmitted as a message."
# Note: the backward slash has to be converted to the yen sign.
#
VERSION 2
#
DEFINE TAB 9
DEFINE SMTYP 0
DEFINE RMMSK 0x80
DEFINE LOG COMMENT
#
VARIABLE msg:C[256]
VARIABLE spid:I,dmy:I
VARIABLE rpid:I,mtyp:I,msz:I
#
#
PROLOGUE
SCENE BG,TX
$MMASK=RMMSK
dmy=setgnm("_MAINPID",$PID)
VOPEN Mesg_Proc_Ex
spid=Mesg_Proc_Ex.PID
LOG "pid=%d spid=%d dmy=%d",\
	$PID,spid,dmy
KINPUT TX
END
#
#
EPILOGUE
VCLOSE
END
#
#
ACTION tx(s:S,n:I,x:I,y:I)\
			CLICK TX
KINPUT s,x,y
END
#
#
ACTION key(k:I) KEY
IF k==TAB
 msg[:]=TX.TX[:],0
 msz=(TX.TL+1)*2
 MSEND spid,SMTYP,msz,msg
 LOG "MSEND pid=%d msz=%d[%d]",\
		spid,msz,$ERR
  MRECV RMMSK,rpid,mtyp,msz,msg
  MESG "--pid=%d,ty=%d,sz=%d",\
		rpid,mtyp,msz
ENDIF
END

MicroScript script "CharPro11" (Annotated by Personal Media Corporation)
#              Message Processing Example (Send)
#
# This is the microscript on the sending side. Every time the
# Tab key is pressed it carries out processing in which "it
# performs transmission of the character segment contents, and
# then receives acknowledgement." 
#
VERSION 2
# This operates even as VERSION 2, but because the current
# MicroScript in Cho Kanji V is made up as VERSION 3, we 
# request that you use it as VERSION 3, if you don't mind.
#
DEFINE TAB 9
# 9 is Tab in TRON Code. In ASCII code it is the same 9, but,
# as we will explain later, C type is TRON Code. 
DEFINE SMTYP 0
# Send Message Type; the sending message type is 0.
DEFINE RMMSK 0x80
# Recv Message Mask is 0x80. This is 0x80 in hexadecimal, in
# other words, 10000000 in binary. This expresses the
# receiving of message type 7.
DEFINE LOG COMMENT
# The LOG statement is a statement that outputs messages to
# the Console utility, but because we are making the LOG
# statement invalid here, we have made it so that we replace
# LOG in COMMENT. 
# Usually, we employ a method of use in which we use the LOG
# statement for debugging use up to the point where the
# program is running normally, and then once we can confirm
# that the program is running normally, we make it invalid by
# replacing LOG with COMMENT. To return the LOG statement to
# valid, please make "DEFINE LOG COMMENT" into "# DEFINE LOG
# COMMENT."
VARIABLE msg:C[256]
# Secure the message region as an array of 256 characters. 
# With this you can reach a message of up to 256 characters 
# maximum. However, as will be described later, because 0 
# is attached at the end of the message, it becomes up to
# a maximum of 255 characters if we do not include the 0 at
# the end.
VARIABLE spid:I,dmy:I
# spid is send process ID, and dmy is dummy.
VARIABLE rpid:I,mtyp:I,msz:I
# rpid is receive process ID, mtyp is message type, and msz is
# message size.
#
#
PROLOGUE
# From PROLOGUE up to END we describe the initialization that
# will be executed first at the time MicroScript is started up.
SCENE BG,TX
# Display segments BG and TX.
$MMASK=RMMSK
# Set the receiving mask to 0x80.
dmy=setgnm("_MAINPID",$PID)
# The self (sending side microscript) process ID ($PID) is
# stored in the global name of the name "_MAINPID". setgnm
# means set global name.
#
# _MAINPID probably means main process ID. The naming seems
# based on thinking in which the sending side microscript
# is main, and the receiving side microscript is sub.
# The return value of setgnm is stored in dmy.
# The return value of setgnm expresses whether or not storing
# into the global name has succeeded; because nothing in
# particular outside of display with the LOG statement is used
# after this, it seems the programmer has made it into a
# variable with the name of dmy (dummy).
VOPEN Mesg_Proc_Ex
# This starts up the sending side microscript. 
spid=Mesg_Proc_Ex.PID
# This obtains the now started up sending side microscript's
# process ID, and stores it in spid. 
LOG "pid=%d spid=%d dmy=%d",\
	$PID,spid,dmy
# This expresses the values of $PID, spid, and dmy for the
# purpose of debugging.
KINPUT TX
# This puts the character segment TX to input status. 
END
#
#
EPILOGUE
# From EPILOGUE to END, we describe the termination processing
# that will be executed when the microscript is terminated.
VCLOSE
# When the (sending side) self terminates, the receiving side
# microscript also closes together with it.
END
#
#
ACTION tx(s:S,n:I,x:I,y:I)\
			CLICK TX
# From this ACTION up to END is executed when the TX segment
# has been clicked.  
KINPUT s,x,y
# Once the TX segment has been clicked, this puts it to input
# status. 
END
#
#
ACTION key(k:I) KEY
# From this ACTION up to END is executed when a key has been
# pressed. 
IF k==TAB
# If the key that has been pressed is the Tab key
# msg[:]=TX.TX[:],0
# The character string that has been input into TX segment is
# substituted into msg.
# TX.TX means the character string that has been input into the
# text segment, 
# [:] means the entirety of the character string,
# and ,0 means attach a null character at the end of the 
# message. 
# A null character at the end of a character string is 0 in
# TRON Code.
# A null character is a special character that expresses the
# end of a character string. Because it is completely separate
# from the numerical character '0', please be careful. 
# http://en.wikipedia.org/wiki/Null_character
 msz=(TX.TL+1)*2
# msz (message size) is two times the number of characters
# that have been substituted into the TX segment (TL= text
# length) +1. 
# The +1 is the portion of the null character that is attached
# at the end off the message. 
# Because one character is two bytes in TRON Code, the message
# size is made double. 
# Because one character is one byte in ASCII code, but one
# character is two bytes in TRON Code, please be careful.
 MSEND spid,SMTYP,msz,msg
# This is message type SMTYP (=0) for the process ID spid, and
# it sends the message msg of the length msz.
# MSEND means message send.
 LOG "MSEND pid=%d msz=%d[%d]",\
		spid,msz,$ERR
# This displays spid, msg, $ERR for the purpose of debugging.
# $ERR is for the purpose of confirming whether or not an error
# has occurred in the MSEND statement.
  MRECV RMMSK,rpid,mtyp,msz,msg
# This receives the message with the message mask RMMSK 
# (=0x80).
# MRECV means message receive. 
# The process ID of the sending source of the received message,
# the received message type, the received message length, and 
# the received message contents are overwritten in rpid, mtyp,
# msz, and msg. Because a timeout is not specified, it will 
# wait forever until a message is received. 
# As described later, one letter, 'A', will be received.
  MESG "--pid=%d,ty=%d,sz=%d",\
		rpid,mtyp,msz
# This displays rpid, mtyp, and msz for the purpose of 
# debugging. 
ENDIF
END

 MicroScript script "CharPro12"
#             Message Operation Example (Receive)
#
# This script is part of a MicroScript program that is
# embedded inside the MicroScript program that the above
# script is a part of. It receives the message the above
# script transmits when the Tab key is pressed. 
#
VERSION 2
#
DEFINE SMTYP 7
DEFINE RMMSK 1
DEFINE LOG COMMENT
#
VARIABLE msg:C[256]
VARIABLE rpid:I,mtyp:I,msz:I
VARIABLE mpid:I
#
#
PROLOGUE
SCENE BG,TX
$MMASK=RMMSK
mpid=getgnm("_MAINPID")
LOG "MainPid=%d",mpid
EXECUTE recv()
END
#
#
FUNC recv()
REPEAT
 MRECV RMMSK,rpid,mtyp,msz,\
		msg:10
 IF $ERR!=0
  MESG "MRECV TIMEOUT"
 ELSEIF rpid != mpid
  MESG "ILLEGAL PID=%d",rpid
 ELSE
  MESG "++pid=%d,ty=%d,sz=%d",\
		rpid,mtyp,msz
  TEXT TX,"%s",msg
  SLEEP 2000
  msg[0]='A'
  MSEND rpid,SMTYP,2,msg
 ENDIF
ENDREPEAT
END

 MicroScript script "CharPro12" (Annotated by Personal Media Corporation)
#             Message Processing Example (Receive)
#
# This is the microscript on the receiving side. It infinitely
# repeats processing in which it displays in a character
# segment and returns an acknowledgement if a message is
# received. 
#
VERSION 2
# This operates even as VERSION 2, but because the current
# MicroScript in Cho Kanji V is made up as VERSION 3, we 
# request that you use it as VERSION 3, if you don't mind.
#
DEFINE SMTYP 7
# Send Message Type; the sending message type is 7.
DEFINE RMMSK 1
# Recv Message Mask is 1. This is a decimal number, 1 in
# hexadecimal is 0x01, and 00000001 in binary. Counting from 
# the low end, because the 0th bit is 1, this expresses the
# receiving of message type 0.
DEFINE LOG COMMENT
# The LOG statement is a statement that outputs messages to
# the Console utility, but because we are making the LOG
# statement invalid here, we have made it so that we replace
# LOG in COMMENT. 
# Usually, we employ a method of use in which we use the LOG
# statement for debugging use up to the point where the
# program is running normally, and then once we can confirm
# that the program is running normally, we make it invalid by
# replacing LOG with COMMENT. To return the LOG statement to
# valid, please make "DEFINE LOG COMMENT" into "# DEFINE LOG
# COMMENT."
VARIABLE msg:C[256]
# Secure the message region as an array of 256 characters. 
# With this you can reach a message of up to 256 characters 
# maximum. However, as will be described later, because 0 
# is attached at the end of the message, it becomes up to
# a maximum of 255 characters if we do not include the 0 at
# the end.
VARIABLE rpid:I,mtyp:I,msz:I
# rpid is receive process ID, mtyp is message type, and msz is
# message size.
VARIABLE mpid:I
# mpid is main process ID (the process ID of the sending side
# microscript). 
#
#
PROLOGUE
# From PROLOGUE up to END we describe the initialization that
# will be executed first at the time MicroScript is started up.
SCENE BG,TX
# Display segments BG and TX.
$MMASK=RMMSK
# Set the receiving mask to 1.
mpid=getgnm("_MAINPID")
# This obtains the process ID ($PID) of the sending side
# microscript from the global name of the name "_MAINPID," and
# stores it in mpid. 
# getgnm means get global name.
LOG "MainPid=%d",mpid
# This displays mpid for the purpose of debugging.
EXECUTE recv()
# This executes the function named recv(). 
END
#
#
FUNC recv()
# This defines the function named recv(which means receive).
REPEAT
# REPEAT-END is an endless loop.
 MRECV RMMSK,rpid,mtyp,msz,\
		msg:10
# This receives the message in the message mask RMMSK (=-1).
# The process ID of the sending source of the received message,
# the received message type, the received message length, and 
# the received message contents are overwritten in rpid, mtyp,
# msz, and msg. Because 10 seconds has been specified as the 
# timeout, it will wait a maximum of 10 seconds up to which
# the message can be received. 
 IF $ERR!=0
# In a case where $ERR is not 0, a timeout message for the
# MRECV statement is started up.
  MESG "MRECV TIMEOUT"
# "MRECV TIMEOUT" is is displayed in the system message panel
# (the line at the very bottom of the Cho Kanji V screen).
 ELSEIF rpid != mpid
  MESG "ILLEGAL PID=%d",rpid
# In a case where rpid is different from mpid, another process,
# in other words something different from the sending source
# microscript, becomes the sending source. This displays that
# process ID in the system message panel.
 ELSE
  MESG "++pid=%d,ty=%d,sz=%d",\
		rpid,mtyp,msz
# This displays rpid, mtyp, msz in the system message panel.
  TEXT TX,"%s",msg
# This displays the received message contents in the segment
# TX.
  SLEEP 2000
# This waits 2,000 milliseconds, in other words two seconds.
  msg[0]='A'
# This creates a message made up of one character, 'A'.
  MSEND rpid,SMTYP,2,msg
# This sends the SMTYP (type 7) message for the rpid (in other
# words the sending source microscript).
# The message length is two bytes. This is because the one
# character 'A' in TRON Code is is two bytes.
# It seems as if they are using 'A' as the beginning character
# of an acknowledgement that says it was possible to receive
# the message. 
# http://en.wikipedia.org/wiki/Acknowledgement_(data_networks)
 ENDIF
ENDREPEAT
END

Review and Further Explanation

Now, before going on to the next chapter, let's review the things that we have learn in this introductory MicroScript lesson.

(1)
MicroScript can output characters and text in five places: (1) the system message panel, (2) character segments, (3) the Console, (4) text real objects, and (5) figure (graphics) segments. This is done by respectively using the MESG statement, the TEXT statement, the LOG statement, the FWRITE statement, and painted text.

(2)
The TEXT statement, which is used to print characters and text into character segments, erases everything in a character segment every time it prints something new. To keep the things already in a character segment from disappearing, they have to be continually added to the new data that will be printed in the character segment each time the TEXT statement is executed.

(3)
The INPUT statement is difficult to use for the inputting of characters or text into text boxes, and thus it should used only for numerical data entry. When creating a script that will allow end users to input characters and text into a text box, please use the KINPUT statement

(4)
The LOG statement is used to print characters and text in the Console. The advantage to using this is that the data above do not have to be refreshed as new data are written below, which makes it an ideal place for outputting lists. When the LOG statement is used in a script, the Console has to be opened prior to execution of the program for the data to be seen.

(5)
In order to make your scripts more readable, it is best to use the CALL statement with the FUNC statement, and the EXECUTE statement with the ACTION statement. The LOCAL statement is used with the FUNC statement to assign local variables.

(6)
Using the MSEND and MRECV statements, it is possible to create MicroScript programs that transmit data to other MicroScript programs. There is also a PROCESS statement that allows a programmer to call up functionality from programs written in C language.

(7)
The setgnm () and getgnm () functions, which set and get global names, are also used when two independent MicroScript scripts communicate with each other and exchange data.

(8)
The $MMASK system variable, which is used in conjunction with the MRECV statement, is used to determine whether a message received is of the proper type.

(9)
The LOG statement mentioned above is also used in debugging MicroScript scripts during the development stage. Once the program is working normally and its script or scripts are fully debugged, the LOG statement is disabled.

(10)
The CLICK statement, which is used in conjunction with the ACTION statement, defines a procedure that starts up when a specified segment is clicked on.

Some Scripts for Working with Text Real Objects

As mentioned at the beginning of this chapter, opening text real objects and doing things inside them are difficult things for beginners to do, unless you happen to be a beginner who is already a highly experienced programmer. With that type of MicroScript beginner in mind, we are giving the two scripts and their explanatory documentation below that were downloaded from Mr. Shin Moriyama's Web site. Both of these scripts have VERSION 2 written at the beginning of them, so they are very old scripts. It might be best to correct to VERSION 3, which might allow you to overcome some of the limitations mentioned in the explanatory documentation.

The first script, "Simple Editor," allows you to write things into a character segment labeled Text that will then appear in text real object labeled "Target" (yes, this script will allow you to input "Hello, world!" into text real object).

The second script, "Line Break → Tab," turns line breaks preloaded into a text real object into Tab marks. You have to fill the text real object will some data beforehand for this script to work.

Explanation

This is a MicroScript library that carries out the input and output of characters vis-a-vis TAD-format real objects.

It includes three functions:

  • Real object → character array
  • Character array → real object
  • Replacing of characters in an arbitrary location in a real object

This is something that was registered in SPMC(DL10 #7) in @nifty.

Even I myself have modified these and used them on several occasions; because they are very useful functions, I am reproducing them, taking advantage of the distribution free condition of the author.

Supplementary Explanation

The

real object read-in
real-object write-in
real-object character conversion

that are included in each script real object make up the character input/output library.

I do not have experience using anything other than the former two, however.

FCLOSE

In a case where the file to be made the target of the processing is on an external memory device (ATA memory card, MO disk, etc.), because it will become impossible to detach it midway through, it is best, I think, to additionally write "FCLOSE" at the end of the script (one line before "END").

slen

slen has been used in real object "write-in."

Because slen will return an error in a case where "Copy" is buried in all the characters, the function will not operate normally (slen specification).

For example, I think it's better to make it in the manner of

Character_Array [Character_Array_Maximum_Length-1] = 0

and process beforehand "Copy" so that at least a 0 is entered at the end of the array.

 

Concerning Character Arrays

The library uses the local variable "Copy" as an argument.

Because the maximum number of elements for a local variable is 4,096, it cannot cope with long texts.

In the case of a program that will handle long texts, it is necessary to stop pulling in the array with an argument, and cope by writing into and reading out of a global variable.

__________

Shin Moriyama

File Access Library Reproduction

File Access Library

This library is something for carrying out the input and output of characters vis-a-vis TAD-type real objects using MicroScript (R2.100). The use of the library (scripts) recorded here is completely free, including commercial use, and you can utilize it, distribute it, make modifications to it, and so on, without obtaining consent, etc., from the author.

The library is three functions that are in the latter half of each sample script. There are functions for real object → character array, replacing of characters in an arbitrary location in a real object, and character array → real object. All are made up so that input/output can be carried out while maintaining the original TAD structure.

As an exception, in the case of "character array → real object," when you reduce the size 64 kilobytes or more, an error panel will appear when you read in that real object with the text editor. Because the reduction of the record size is not possible with the current version of MicroScript, in a case where an empty region has been made in the end, everything having been made into text termination segments is the cause. As for the Basic Text Editor, in a case where the text termination segment is a large segment, it looks like it will display an error panel; accordingly, in a case where a text termination segment of 64 kilobytes or greater ends up being created, it will come about that an error panel will be displayed when you open the Basic Text Editor. If you save with the Basic Text Editor, things will become normal.

Furthermore, because the possibility in which you can destroy the contents of an accessed real object due to a program bug can be conceived, please be careful.

  • Input/output of character strings

When you start up [Simple Editor (Figure)], the editing of [Target (Text)] is possible in the window. When you terminate, the editing will be saved. Furthermore, fusen, embedded figures, and the like will be deleted, and even the final line break will be deleted.

  • Replacement of Character units

In the previous section "Input/output of character strings," information on fusen and the like get completely lost. With these systems, you can replace characters while leaving fusen and embedded figures as is.

When you start up [Line Break → Tab (Figure)], you terminate after replacing in all the tabs the line change characters inside [Target (Text)].

Simple Editor (Figure)
VERSION 2

DEFINE TNULL 0
DEFINE Max_Size 10000
VARIABLE Copy0:C[Max_Size]

PROLOGUE
SET Copy0[0:Max_Size]=TNULL
CALL Read_RealObject(Target, Copy0, Max_Size)
SET Copy0[slen(Copy0):Max_Size-slen(Copy0)]='\n'
TEXT Text, "%s", Copy0
APPEAR Text
KINPUT Text
END

EPILOGUE
LOCAL Location:I, End_Location:I
 Location=0
 End_Location=0
WHILE ((Location <Text.TL) && (Location <Max_Size-1))
  Copy0[Location]=Text.TX[Location]
 IF (Copy0[Location]!='\n')
  End_Location=Location
 ENDIF
  Location=Location+1
ENDWHILE
  Copy0[End_Location+1]=TNULL
CALL Write_RealObject(Target,Copy0)
END

# This opens the real object shown in "RealObject," and then 
# reads in only characters up to the maximum "Copy_Size" 
# characters in the character array shown in "Copy."

FUNC Read_RealObject(RealObject:S,Copy:C[],Copy_Size:I)
LOCAL Segment:C[4]
LOCAL Record_Num:I, Record_Size:I
LOCAL Read_Location:I, Write_Location:I
  Read_Location=0
  Write_Location=0
  Record_Num=0
  Copy[0]=TNULL
REPEAT
 FREAD RealObject, Record_Num, 0, 2, Segment, Record_Size
 IF ($ERR!=0)
  EXIT $ERR
 ENDIF
 IF (Segment[0]>=0xff80)
  BREAK
 ENDIF
  Record_Num=Record_Num+1
ENDREPEAT

# MESG "Record_Num:%d Record_Size:%d", Record_Num,Record_Size

WHILE ((Read_Location<Record_Size) && (Write_Location<Copy_Size-1))
 FREAD RealObject, Record_Num, Read_Location, 8, Segment
 IF (Segment[0]<0xff80)	# Case of a character segment
  Copy[Write_Location]=Segment[0]
  Write_Location=Write_Location+1
  Read_Location=Read_Location+2
  CONTINUE
 ENDIF			# Case of a variable-length segment
 IF (Segment[1]!=0xffff)	# Normal segment
  Read_Location=Read_Location+Segment[1]+4
 ELSE				# Large segment
  Read_Location=Read_Location+((Segment[3]<<16)+Segment[2])+8
 ENDIF
ENDWHILE
  Copy[Write_Location]=TNULL
END

# This opens the real object shown in "RealObject," and then
# replaces in "Char" one character that is in "CharLocation" (0~).

FUNC RealObject_CharReplace(RealObject:S, Char:C, CharLocation:I)
LOCAL Segment:C[4]
LOCAL Record_Num:I, Record_Size:I
LOCAL Read_Location:I, Write_Location:I
  Read_Location=0
  Write_Location=0
  Record_Num=0
REPEAT
 FREAD RealObject, Record_Num, 0, 2, Segment, Record_Size
 IF ($ERR!=0)
  EXIT $ERR
 ENDIF
 IF (Segment[0]>=0xff80)
  BREAK
 ENDIF
   Record_Num=Record_Num+1
ENDREPEAT
WHILE (Read_Location<Record_Size)
 FREAD RealObject, Record_Num, Read_Location, 8, Segment
 IF (Segment[0]<0xff80)	# Case of a character segment
    Write_Location=Write_Location+1
  IF (Write_Location>CharLocation)
    Segment[0]=Char
   FWRITE RealObject, Record_Num, Read_Location, 2, Segment
   EXIT 0
  ENDIF
   Read_Location=Read_Location+2
  CONTINUE
 ENDIF			# Case of a variable-length segment
 IF (Segment[1]!=0xffff)	# Normal segment
   Read_Location=Read_Location+Segment[1]+4
 ELSE				# Large segment
   Read_Location=Read_Location+((Segment[3]<<16)+Segment[2])+8
 ENDIF
ENDWHILE
END

# This opens the real object shown in "RealObject," and then 
# writes out in the format of a text real object the character
# array shown in "Copy." The contents of the original real 
# object are completely replaced with the with the contents
# of "Copy."

FUNC Write_RealObject(RealObject:S, Copy:C[])
LOCAL Segment:C[4]
LOCAL Management_Info_Segment:C[5]
LOCAL Text_Start_Segment:C[14]
LOCAL Text_End_Segment:C[4]
SET Management_Info_Segment[0:5]=0xffe0, 6, 0, 2, 0x120
SET Text_Start_Segment[0:14]=0xffe1, 24, 0, 0, 0, 0, \
	0, 0, 0, 0, 0, 0, 0x21, 0
SET Text_End_Segment[0:2]=0xffe2,0
LOCAL Record_Num:I, Record_Size:I
LOCAL Write_Location:I
    Write_Location=0
    Record_Num=0
REPEAT
 FREAD RealObject, Record_Num, 0, 2, Segment, Record_Size
 IF ($ERR!=0)
  EXIT $ERR
 ENDIF
 IF (Segment[0]>=0xff80)
  BREAK
 ENDIF
    Record_Num=Record_Num+1
ENDREPEAT
FWRITE RealObject, Record_Num, Write_Location, 10, Management_Info_Segment
  Write_Location=Write_Location+10
FWRITE RealObject, Record_Num, Write_Location, 28, Text_Start_Segment
  Write_Location=Write_Location+28
FWRITE RealObject,Record_Num,Write_Location,slen(Copy)*2, Copy
  Write_Location=Write_Location+slen(Copy)*2
IF (Write_Location+4>=Record_Size)
  Text_End_Segment[1]=0
 FWRITE RealObject, Record_Num, Write_Location,4, Text_End_Segment
ELSEIF (Record_Size-Write_Location-4<65535)
  Text_End_Segment[1]=Record_Size-Write_Location-4
 FWRITE RealObject, Record_Num, Write_Location, 4, Text_End_Segment
ELSE
  Text_End_Segment[1]=0xffff
  Text_End_Segment[2]=(Record_Size-Write_Location-8)&0xffff
  Text_End_Segment[3]=(Record_Size-Write_Location-8)>>16
 FWRITE RealObject, Record_Num, Write_Location, 8, Text_End_Segment
ENDIF
END
#eoo

Line Break → Tab (Figure)
VERSION 2

DEFINE TNULL 0
DEFINE Max_Size 10000
VARIABLE Copy0:C[Max_Size]

PROLOGUE
LOCAL Location:I
SET Copy0[0:Max_Size]=TNULL
CALL Read_RealObject(Target, Copy0, Max_Size)

# TEXT Text,"%s",Copy0
# APPEAR Text

  Location=0
WHILE (Location<slen(Copy0))
 IF (Copy0[Location]=='\n')
  CALL RealObject_Replace(Target, '\t', Location)
 ENDIF
  Location=Location+1
ENDWHILE
FINISH
END

# This opens the real object shown in "RealObject," and then 
# reads in only characters up to the maximum "Copy_Size" 
# characters in the character array shown in "Copy."

FUNC Read_RealObject(RealObject:S, Copy:C[], Copy_Size:I)
LOCAL Segment:C[4]
LOCAL Record_Num:I, Record_Size:I
LOCAL Read_Location:I, Write_Location:I
  Read_Location=0
  Write_Location=0
  Record_Num=0
  Copy[0]=TNULL
REPEAT
 FREAD RealObject, Record_Num, 0, 2, Segment, Record_Size
 IF ($ERR!=0)
  EXIT $ERR
 ENDIF
 IF (Segment[0]>=0xff80)
  BREAK
 ENDIF
  Record_Num=Record_Num+1
ENDREPEAT

# MESG "Record_Num:%d Record_Size:%d", Record_Num, Record_Size

WHILE ((Read_Location<Record_Size) && (Write_Location<Copy_Size-1))
 FREAD RealObject,Record_Num, Read_Location, 8, Segment
 IF (Segment[0]<0xff80)	#Case of a character Segment
  Copy[Write_Location]=Segment[0]
  Write_Location=Write_Location+1
  Read_Location=Read_Location+2
  CONTINUE
 ENDIF			# Case of a variable-length segment
 IF (Segment[1]!=0xffff)	# Normal segment
  Read_Location=Read_Location+Segment[1]+4
 ELSE				# Large Segment
  Read_Location=Read_Location+((Segment[3]<<16)+Segment[2])+8
 ENDIF
ENDWHILE
  Copy[Write_Location]=TNULL
END

# This opens the real object shown in "RealObject," and then 
# replaces in "Char" one character that is in "CharLocation" (0~).

FUNC RealObject_Replace(RealObject:S, Char:C, CharLocation:I)
LOCAL Segment:C[4]
LOCAL Record_Num:I, Record_Size:I
LOCAL Read_Location:I, Write_Location:I
  Read_Location=0
  Write_Location=0
  Record_Num=0
REPEAT
 FREAD RealObject,Record_Num, 0, 2, Segment, Record_Size
 IF ($ERR!=0)
  EXIT $ERR
 ENDIF
 IF (Segment[0]>=0xff80)
  BREAK
 ENDIF
   Record_Num=Record_Num+1
ENDREPEAT
WHILE (Read_Location<Record_Size)
 FREAD RealObject, Record_Num, Read_Location, 8, Segment
 IF (Segment[0]<0xff80)	# Case of a character segment
  Write_Location=Write_Location+1
  IF (Write_Location>CharLocation)
   Segment[0]=Char
   FWRITE RealObject, Record_Num, Read_Location, 2, Segment
   EXIT 0
  ENDIF
   Read_Location=Read_Location+2
  CONTINUE
 ENDIF			# Case of a variable-length segment
 IF (Segment[1]!=0xffff)	# Normal segment
  Read_Location=Read_Location+Segment[1]+4
 ELSE				# Large segment
  Read_Location=Read_Location+((Segment[3]<<16)+Segment[2])+8
 ENDIF
ENDWHILE
END

# This opens the real object shown in "RealObject," and then 
# writes out in the format of a text real object the character
# array shown in "Copy." The contents of the original real 
# object are completely replaced with the with the contents 
# of "Copy."

FUNC RealObjectWrite_(RealObject:S,Copy:C[])
LOCAL Segment:C[4]
LOCAL Management_Info_Segment:C[5]
LOCAL Text_Start_Segment:C[14]
LOCAL Text_End_Segment:C[4]
SET Management_Info_Segment[0:5]=0xffe0, 6, 0, 2, 0x120
SET Text_Start_Segment[0:14]=0xffe1, 24, 0, 0, 0, 0, \
	0, 0, 0, 0, 0, 0, 0x21,0
SET Text_End_Segment[0:2]=0xffe2,0
LOCAL Record_Num:I, Record_Size:I
LOCAL Write_Location:I
  Write_Location=0
  Record_Num=0
REPEAT
 FREAD RealObject, Record_Num, 0, 2, Segment, Record_Size
 IF ($ERR!=0)
  EXIT $ERR
 ENDIF
 IF (Segment[0]>=0xff80)
  BREAK
 ENDIF
  Record_Num=Record_Num+1
ENDREPEAT
FWRITE RealObject, Record_Num, Write_Location, 10, Management_Info_Segment
  Write_Location=Write_Location+10
FWRITE RealObject, Record_Num, Write_Location, 28, Text_Start_Segment
  Write_Location=Write_Location+28
FWRITE RealObject,Record_Num, Write_Location, slen(Copy)*2, Copy
  Write_Location=Write_Location+slen(Copy)*2
IF (Write_Location+4>=Record_Size)
 Text_End_Segment[1]=0
 FWRITE RealObject, Record_Num, Write_Location, 4, Text_End_Segment
ELSEIF (Record_Size-Write_Location-4<65535)
 Text_End_Segment[1]=Record_Size-Write_Location-4
 FWRITE RealObject, Record_Num,Write_Location,4,Text_End_Segment
ELSE
 Text_End_Segment[1]=0xffff
 Text_End_Segment[2]=(Record_Size-Write_Location-8)&0xffff
 Text_End_Segment[3]=(Record_Size-Write_Location-8)>>16
 FWRITE RealObject, Record_Num, Write_Location, 8, Text_End_Segment
ENDIF
END
#eoo

____________________

[1] The Cho Kanji V samples collection includes a program that is based on "CharPro5" above. We have listed this sample below as "CharPro5a." This program consists of a background (bg), and two input boxes (N1 and N2), which are 17 full-width characters wide (you can change to half-width if you want to limit yourself to English language input) and six lines down. When the user presses the Tab key, the contents of the first box are printed in the second box.

MicroScript script "CharPro5a"
#                   Text Transfer Example
#
# This script is part of the Cho Kanji samples collection. It
# is based on CharPro5 above. The explanation in the N1 text
# box reads: "When you press the Tab key, the same thing as 
# the contents input here will be displayed below."
# Note: the backward slash has to be converted to the yen sign.

VERSION 2
#
DEFINE TAB 9
#
PROLOGUE
 SCENE bg, N1, N2
END
#
ACTION input (s:S, n:I, x:I, y:I)\
                    CLICK N1
 KINPUT s, x, y
END
#
ACTION key(k:I) KEY
 IF k==TAB
  TEXT N2, "%s", N1.TX
 ENDIF
END

In the above script, 9 is the number of the Tab key in the ASCII character set, and also in TRON Code. Note that s, n, x, and y arguments now have data type specifications next to them. CLICK indicates that the input procedure will start up when the character segment N1 is clicked. The second procedure, key, starts up if there is a key event in which the Tab key is pressed. When that happens, the character segment N2 is filled with the text contents of the character segment N1.

[2] Mr. Daishin Nakamura of Personal Media Corporation kindly wrote this program especially for TRON Web. He also wrote the explanations of CharPro11 and CharPro12. His help has been invaluable in the creation of this MicroScript course for beginners.


Copyright © 2012 Sakamura Laboratory, University Museum, University of Tokyo