Chapter 14

Doing a Presentation with BTRON MicroScript


Let's try creating a program that carries out simple a presentation using MicroScript. We will make it so that we read in text created with the Basic Text Editor.

The program "Presentation" will fulfill the following functions.

14.1 The Presentation Stage and Actors

What kind of stage and actors will we need in the program "Presentation"? First, we will need a segment into which we will substitute the character data read in from the text real object. Other than that, graphic segments that will become the switches that turn the pages are needed. Moreover, there will also be a need to prepare and put in place a virtual object segment that points to a text real object.

Translator's note: The MicroScript window above is titled "Presentation." Inside the widow, there are two virtual object segments: "Input (Text)" at the top, and "SCRIPT (Text)" at the bottom; a character segment "@Text" at the top; and two figure segments: "@Prev" on the bottom left, and "@Next" on the bottom right, which are the controls for the program Presentation.

14.2 Script of the Presentation

The script of the program "Presentation" is one that realizes the following contents.

(1)
Read in the character string from the text real object

(2)
Display the read-in character string

(3)
Display the appropriate page if the switch has been pressed

01 VERSION 2
02 DEFINE Empty_Char 0
03 DEFINE Max_Size 200000
04 VARIABLE Copy:C[Max_Size]
05 VARIABLE Page_Num:I
06
07 PROLOGUE
08  Copy[:]=Empty_Char
09  CALL Read_RealObject
10  Page_Num=0
11  CALL Display_Page
12  APPEAR Text,Prev,Next
13 END
14
15 FUNC Read_RealObject
16  LOCAL Segment:C[4]
17  LOCAL Record_Num:I, Record_Size:I
18  LOCAL Read_Location:I, Write_Location:I
19  Read_Location=0
20  Write_Location=0
21  Record_Num=0
22  REPEAT
23   FREAD Input,Record_Num,0,2,Segment,Record_Size
24   IF ($ERR!=0)
25    EXIT -1
26   ENDIF
27   IF (Segment[0]>=0xff80)
28    BREAK
29   ENDIF
30   Record_Num=Record_Num+1
31  ENDREPEAT
32  WHILE ((Read_Location<Record_Size)&&(Write_Location<Max_Size-1))
33   FREAD Input,Record_Num,Read_Location,8,Segment
34   IF (Segment[0]<0xff80)
35   Copy[Write_Location]=Segment[0]
36   Write_Location=Write_Location+1
37   Read_Location=Read_Location+2
38   CONTINUE
39  ENDIF			
40  IF (Segment[1]!=0xffff)	
41   Read_Location=Read_Location+Segment[1]+4
42   ELSE				
43    Read_Location=Read_Location+((Segment[3]<<16)+Segment[2])+8
44   ENDIF
45  ENDWHILE
46  Copy[Write_Location]=Empty_Char
47 END
48
49 FUNC Display_Page
50  LOCAL Char_Location:I,Start_Location:I,Length:I
51  Start_Location=0
52  IF (Page_Num 0)
53   Page_Num=0
54  ELSE
55   REPEAT Page_Num
56    Char_Location=asrch(Copy,Start_Location,0xc,0)
57    IF valid(Char_Location)==0
58     Page_Num=$CNT
59     BREAK
60    ENDIF
61    Start_Location=Char_Location+1
62   ENDREPEAT
63  ENDIF
64  Length=asrch(Copy,Start_Location,0xc,0)
65  IF valid(Length)
66   TEXT Text,"%s",Copy[Start_Location:Length-Start_Location-1]
67  ELSE
68   TEXT Text,"%s",Copy[Start_Location:]
69  ENDIF
70 END
71
72 ACTION Page_Return PRESS Prev
73  Page_Num=Page_Num-1
74  CALL Display_Page
75 END
76
77 ACTION Page_Forward PRESS Next
78  Page_Num=Page_Num+1
79  CALL Display_Page
80 END

We show the entire script that satisfies these. The line numbers are for the purpose of explanation, and, in actuality, they are not necessary.

This script is one example. Because you can also write another script, please try to take up the challenge.

This script is divided into the six parts below.

Reading in Character Strings from a Text Real Object

In order to read in character strings from a text real object, it is necessary to understand the structure of a text real object.

The BTRON-specification operating system file system can include multiple records (series of data units) in one file (real object). To the records are attached record types, which are expressed with the numbers 0 to 31. In a case where we are reading and writing into a real object, it is necessary to decide which record we will make the target. We call this record the current record, and it becomes the beginning record immediately after we have opened the real object.

We call a record in which data such as text or figures have been stored the TAD main record (record type 1). TAD (TRON Application Databus) has been prescribed as data formats that are shared in common among all applications that run on top of the BTRON-specification operating system. TAD is described as a line of segments (a series of data units that comprise the record) inside the TAD main record. There are many types of segments; they are made up so that besides text and figures, things such as forms can be described.

In other words, in one real object, first the large information is classified by means of records, and then inside the TAD main record inside those, more detailed information is classified by means of segments.

Normally, segments are lined up in order inside the TAD main record. Among the segments, there are fixed length segments and variable length segments. A fixed length segment is used in expressing characters, its length is fixed at two-bytes, and it stores character data (0xff7f and below) as is. With a variable length segment, there is a segment ID (0xff80 to 0xfffe) at its beginning, and next the length of the segment (two-byte units) are described. As for segment lengths, they are divided into normal segments in the range of 0 to 65534 (0 to 0xfffe) bytes that can be expressed with two-bytes, and large segments in the range of 65536 to 4294967294 (0x10000 to 0xfffffffe) that can be expressed with four bytes.

There are a certain number of rules to the way we line up the segments inside the TAD main record. In particular, at the beginning, will exist without fail only one "management information segment," which is a variable length segment. The "management information segment" is a segment for the purpose of storing management information, such as TAD version information. After this "management information segment," segments possessing all sorts of roles are lined up, and a portion of them are fixed length segments that store character codes.

From such TAD merits, the following operations become necessary in reading in the character strings of a text real object.

A.
Finding the TAD main record that is inside the real object

B.
Finding the fixed length segments that are inside the TAD main record

For A, we investigate in order the records that are inside the real object, and we search by judging whether or not the two bytes at the beginning are a segment ID.

For B, we investigate in order the segments that are inside the TAD main record, and we search by judging whether or not the two bytes at the beginning are a character code (0xff7f or below).

Concerning the actual description, we will explain it inside the script main body.

In regard to the logical composition of a real object here, we have given the minimal explanation necessary in order to realize "Presentation." For details, please look at the BTRON1 Programming Standard Handbook, and "1B Programming Dojo," which was serialized in TRONWARE Vol. 34 and following issues.

Various Types of Definitions Required in the Script

The portion below carries out various types of declarations required in the script of the program "Presentation."

01 VERSION 2
02 DEFINE Empty_Char 0
03 DEFINE Max_Size 200000
04 VARIABLE Copy:C[Max_Size]
05 VARIABLE Page_Num:I

The VERSION statement (p. 347) on the first line is necessary in order to use the full functions of the script.

The DEFINE statements (p. 284) on the second and third lines is declaring macro names we use inside the script. In the macro name "Empty_Char," we are declaring that 0 indicates an empty character. In the macro name "Max_Size," we are declaring 200,000 as the maximum number of characters that can be read in.

The VARIABLE statements (p. 285) on the fourth and fifth lines are defining global variables. The global variable "Copy" is an array of 200,000 elements. We use this to store the character string read in from the text real object. The ": C" written immediately after the the variable name "Copy" and the ": I" written immediately after the variable name "Page_Num" specify the kind (type) of data that can be substituted in the variable. ": C" means characters, and ": I" integers. From the data types that can be substituted, we call the variable "Copy" a character-type array variable, and the variable "Page_Num" an integer-type variable. You cannot substitute other types of data into a variable for which the type has been specified.

The variable we defined in the program "Cat" did not have a data type specified. We call this kind of variable the general-purpose type, and you can substitute the values of arbitrary data types into it.

Initial Processing

The PROLOGUE (p. 288) to END (p. 295) statements are executed only once immediately after the window opens.

07 PROLOGUE
08  Copy[:]=Empty_Char
09  CALL Read_RealObject
10  Page_Num=0
11  CALL Display_Page
12  APPEAR Text,Prev,Next
13 END

The eighth line substitutes 0 (empty character) into all the elements of the character-type array variable, and then carries out the initialization of the array.

The CALL statement (p. 302) on the ninth line sequentially executes the procedure "Read_RealObject." The procedure "Read_RealObject" is defined in the FUNC statement (p. 295) on the 15th line. Because it is sequential execution, the procedure for initial processing use on the call-up side is suspended until the procedure "Read_RealObject" on the called-up side terminates. We will explain the contents of the procedure "Read_RealObject" later.

The 10th line substitutes 0 into the global variable "Page_Num" as the initial value.

The CALL statement on the 11th line sequentially executes the procedure "Display_Page." The procedure "Display_Page" is defined in the FUNC statement on the 49th line. We will explain the contents of the procedure "Display_Page" later.

The APPEAR statement (p. 311) on the 12th line displays the character segment "Text," and the figure segments "Prev" and "Next."

Translator's note: The text inside the MicroScript window titled "Presentation" reads: "Let's try creating a program that carries out presentations using MicroScript."

Procedure that Reads in the Real Object

The procedure "Read_RealObject" (15th to 47th lines) reads in a character string from the text real object "Input."

15 FUNC Read_RealObject
16  LOCAL Segment:C[4]
17  LOCAL Record_Num:I, Record_Size:I
18  LOCAL Read_Location:I, Write_Location:I
19  Read_Location=0
20  Write_Location=0
21  Record_Num=0

The LOCAL statements (p. 286) on the 16th to 18th lines define local variables we use inside the procedure.

In the 19th to 21st lines, we substitute 0 as the initial value into the local variables.

22  REPEAT
23   FREAD Input,Record_Num,0,2,Segment,Record_Size
24   IF ($ERR!=0)
25    EXIT -1
26   ENDIF
27   IF (Segment[0]>=0xff80)
28    BREAK
29   ENDIF
30   Record_Num=Record_Num+1
31  ENDREPEAT

In the REPEAT to ENDREPEAT statements (p. 300) of the 22nd to the 31st lines lies the operation in which we look for a record in which the beginning starts with the segment ID (0xff80 or greater).

The FREAD statement (p. 330) on the 23rd line opens the real object "Input," reads in two-byte segments from an offset byte number of 0 in the record specified in the variable "Record_Num," and then stores them in the array variable "Record_Size." The overall size of the read-in record is stored in the variable "Record_Size."

The IF statement (p. 298) on the 24th line checks whether or not an error occurred when reading in the real object. In a case where an error has occurred, a value other than 0 will be stored will be stored in the system variable $ERR.

The EXIT statement (p. 304) on the 25th line terminates the procedure "Read_RealObject," and then returns -1.

The IF statement on the 27th line investigates the data (data at the beginning of the record) stored in element number 0 of the array variable "Segment," and if it's a segment ID (0xff80 or greater), it terminates the REPEAT statement (28th line BREAK statement [p. 305]).

If the data at the beginning of the record is a segment ID, it adds 1 to the record number on the 30th line, and makes it so that we can investigate the next record. And then, it repeats the processing from the 22nd line one more time.

With this REPEAT statement, if a segment ID record is discovered at the beginning, processing moves to what is next after the ENDREPEAT statement on the 31st line, and it executes the WHILE statement (p. 302) on the 32nd line. In a case where the target record could not be found or some sort of error has occurred during read-in, the WHILE statement on the 32nd will not be executed, because the procedure "Read_RealObject" will terminate.

32  WHILE ((Read_Location<Record_Size)&&(Write_Location<Max_Size-1))
33   FREAD Input,Record_Num,Read_Location,8,Segment
34   IF (Segment[0]<0xff80)
35   Copy[Write_Location]=Segment[0]
36   Write_Location=Write_Location+1
37   Read_Location=Read_Location+2
38   CONTINUE
39  ENDIF			
40  IF (Segment[1]!=0xffff)	
41   Read_Location=Read_Location+Segment[1]+4
42   ELSE				
43    Read_Location=Read_Location+((Segment[3]<<16)+Segment[2])+8
44   ENDIF
45  ENDWHILE
46  Copy[Write_Location]=Empty_Char
47 END

Among the WHILE to ENDWHILE statements on the 32nd to 45th lines, there is an operation in which we store the read-in character string in the character-type array variable "Copy[]."

The conditional expression on the 32nd line repeats the process up to the end of the read-in record (Read_Location<Record_Size), and also up until the element of the array variable "Copy[]" disappears (Write_Location<Max_Size-1).

The FREAD statement on the 33rd line opens the real object "Input," and where the beginning is the record of a segment ID, reads in 8-byte segments from the offset byte number specified in the variable "Read_Location," and then stores them in the array variable "Segment[]."

The IF statement on the 34th line describes the processing that will be carried out in a case where the read-in data are character codes (less than 0xff80).

The 35th line substitutes the character data read into the array variable "Segment[0]" into the element number specified in the variable Read_Location" of the array variable "Segment[]."

The 36th line adds one to the variable "Write_Location," and then advances the element number where we will write in next by one.

The 37th line adds two to the variable "Read_Location," and then advances the offset byte number where we will read in next by two bytes. This is because the character data are made up into two-byte units.

In the CONTINUE statement on the 38th line, there is the operation that forcibly advances the repetition to the next instance. As such time, processing up to the ENDWHILE statement on the 45th line is ignored, and the operation is repeated again from the WHILE statement on the 32nd line.

The IF statement on the 40th line describes processing that will be carried out in a case where the read-in data are outside character codes (greater than 0xff80). In concrete terms, it skips over variable length segments. The conditional expression distinguishes whether something is a normal segment or a large segment with a segment length greater than 65,536 bytes.

The 41st line, in the case of a normal segment, by advancing the read-in location to the extent of a value in which we have added four bytes (segment ID + segment length) to the length of a segment (the value stored in Segment[1]), skips over variable length segments.

The 43rd line, in the case of a large segment, by advancing the read-in location to the extent of a value in which we have added eight bytes (segment ID + large segment specification + segment length [four bytes]) to the length of a segment (the value of the expression "(Segment[3]<<16)+Segment[2]"), skips over variable length segments. For quasi-TAD [Note 12:], we can search for the segment length by adding the value of Segment[2], because we do a 16-bit shift operation on the value of "Segment[3]."

The 46th line substitutes an empty character (0) immediately after we have stored the character string of the array variable "Copy[]," and displays the end of the character string.

Procedure that Displays the Page

The procedure "Display_Page" (49th to 70th lines) displays the read-in character string inside a window.

49 FUNC Display_Page
50  LOCAL Char_Location:I,Start_Location:I,Length:I
51  Start_Location=0
52  IF (Page_Num 0)
53   Page_Num=0
54  ELSE
55   REPEAT Page_Num
56    Char_Location=asrch(Copy,Start_Location,0xc,0)
57    IF valid(Char_Location)==0
58     Page_Num=$CNT
59     BREAK
60    ENDIF
61    Start_Location=Char_Location+1
62   ENDREPEAT
63  ENDIF

The IF statement on the 52nd line performs the operation that determines the character string data of the page we will display. The beginning of the character string we will display is shown in the variable "Start_Location." The conditional expression divides cases on whether we are displaying the beginning page (page number 0) or whether we are displaying a page other than the beginning (page number other than 0).

The 53rd line, in the case that we are displaying the beginning page (the case immediately after the script starts, and also when we display the beginning page after turning the previous page), substitutes 0 in the variable "Page_Num."

The REPEAT to ENDREPEAT statements on the 55th to 62nd lines are processing for a case in which we display a page other than the beginning. There is an operation in which we look for a character string that corresponds to the page number stored in the variable "Page_Num." For example, what we display on the second page are the character strings from the next character of first new page characters up to the new page after that among the character strings stored in the character-type array variable "Copy[]."

The function asrch() (p. 354) on the 56th line searches for the element (0) from the element number specified in the variable Start_Location of the array variable Copy[] up to the end, and it returns the number of the element in which "0xc" (new page character) has been stored. If "0xc" is not found, it returns an illegal value. The value returned from the function asrch() is stored in the variable Char_Location.

The function valid() (p. 349) of the IF statement on the 57th line returns 0 in a case where the argument is an illegal value. By means of this, if the value of the value of the variable "Char_Location" is illegal, it substitutes into the variable "Page_Num" the number of repeat times ($CNT) of the REPEAT statement on the 55th line, and escapes from the REPEAT statement by means of the BREAK statement on the 59th line. This is because it has judged that the current character string is the character string of the last page, because the new page character has not been found.

The 61st line substitutes the value of the expression "Char_Location+1" in the value of the variable "Start_Location," and it makes is so that the location where we begin to search next comes to the next of the new page characters.

64  Length=asrch(Copy,Start_Location,0xc,0)
65  IF valid(Length)
66   TEXT Text,"%s",Copy[Start_Location:Length-Start_Location-1]
67  ELSE
68   TEXT Text,"%s",Copy[Start_Location:]
69  ENDIF
70 END

The function asrch() on the 64th line, in the same manner as the 56th line, searches for the element (0) from the element number specified in the variable Start_Location of the array variable Copy[] up to the end, and it returns the number of the element in which "0xc" (new page character) has been stored. If "0xc" cannot be found, it returns an illegal value. The value returned from the function asrch() is stored in the variable "Length."

On the 65th line, from the evaluation results of the function valid() in the IF statement, we do dividing into cases of whether to display on the last page, or to display on a page other than that.

The TEXT statement (p. 316) on the 66th line sets the specified character string in a character segment.

TEXT Character_Segment, Form_Character_String, Expression

The character string set in the character segment is specified in the "expression." Form character string specifies the form when we output the character string. The form character string "%s" outputs as a character string.

In a case where the variable "Length" is not illegal, it is executed in (expression "valid(Length)" returns 1). In the character segment "Text," from the location that the variable "Start_Location" inside the array "Copy" specifies, we display a character string to the extent of the element number that the result (up to immediately before "0xc") of the expression "Length-Start_Location-1" specifies.

The TEXT statement on the 68th line is executed in a case where the variable "Length" is an illegal value (the expression "valid(Length)" returns 0). In the character segment "Text," from the location that the variable "Start_Location" inside the array "Copy" specifies, we display up to the end (the 0 that shows the end of the character string).

Procedure that Turns the Pages

This turns the pages, and displays the next page or the previous page. We respectively prepare procedures that start up in events where we press the figure segments "Prev" and "Next."

72 ACTION Page_Return PRESS Prev
73  Page_Num=Page_Num-1
74  CALL Display_Page
75 END

The procedure "Page_Return" on 72nd to 75th lines is a procedure that starts up when the figure segment "Prev" is pressed.

The 73rd line subtracts 1 from the value of the variable "Page_Num," and it makes it so that we show one page previous.

The procedure sequentially starts up the procedure "Display_Page" in the CALL statement on the 74th line, and then carries out display of the actual page.

77 ACTION Page_Forward PRESS Next
78  Page_Num=Page_Num+1
79  CALL Display_Page
80 END

The procedure "Page_Forward" on the 77th to 80th lines is a procedure that starts up when the actor segment "Next" is pressed.

The 78th line adds 1 to the value of the variable "Page_Num," and it makes it so that we show one page to the rear.

The procedure sequentially starts up the procedure "Display_Page" in the CALL statement on the 79th line, and then carries out display of the actual page.

Expansion of the Program "Presentation"

We will introduce proposals for expanding the program "Presentation." Please finish an original presentation by devising all sorts of schemes.

Changing the Character Segment to Be Displayed

The read-in character string has been displayed by being set in the character segment "Text" based on the TEXT statement. For the size and number of character we will use at this time, the settings of this character segment "Text" are used. In other words, we can change the size and number of characters that will be displayed inside the page by just changing the character segment "Text."

As for a character string that can be set as a character segment, the maximum is 1,024 characters. You cannot mix full-width and half-width characters.

Displaying Page Numbers

We know the current page number by referencing the variable "Page_Num." However, because the value of the variable "Page_Num" begins from 0, it is necessary to add 1 in making it the page number. For example, we prepare the following character segment.

Translator's note: Next to the SCRIPT (Text) virtual object is a new segment: "-1- @Num." To the left are the two control buttons: @Prev on the left, and @Next on the right.

On top of that, we add the description below to the script.

  • Revision of the 12th line
 
APPEAR Text, Num, Prev, Next
  # Display the character segment "Num."
  • Insert between the 69th and 70th lines
 
TEXT Num, "-%d-", Page_Num+1
  Set the page number in the character segment "Num."

Also, with the switches that turn the pages, it would be thoughtful to make it so that you display only the Next switch when you are on the first page, and only the Prev switch when you are on the last page. Please try devising that.

____________________

Note 12: What we call quasi-TAD is a standard of TAD data organization that possesses a little endian data format in which the lower byte comes first. For details, please look at "Appendix 2: The TAD Specification" in BTRON1 Programming Standard Handbook.


Copyright © 1999 Personal Media Corporation

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