NCL 304: Drawing a Screen

In the last lesson, we learned that the Display is a 32×12 grid of character positions.

We can move the cursor to any visible position:

D.CUR 10 4

and decide exactly where the next text will be written.

So far, we've mostly used that to place individual pieces of text.

Now we're going to use those positions together to build a complete screen.

Filling the Display

Before drawing a new screen, it's often useful to replace everything already on the Display.

D.FIL fills the entire Display with a repeating pattern.

Let's make that pattern obvious:

D.FIL "@"
D.BLT

The entire Display fills with @ characters.

The pattern can contain more than one character:

D.FIL "123"
D.BLT

Now the Display contains a repeating pattern:

12312312312312312312312312312312
12312312312312312312312312312312
12312312312312312312312312312312
...

D.FIL changes the Display contents, but does not move the cursor.

Most of the time, though, we aren't going to fill the Display with 123.

A particularly useful pattern is:

D.FIL " "

A Display filled with spaces is a blank Display.

The current colour

In NCL 210, we changed the appearance of text using inline style codes such as:

D.TXT "\s0BHELLO"

The B selects palette entry B, or decimal 11.

Display commands can also select palette entries directly.

D.COL changes the current Display colour:

D.COL #D.COL.PINK

NCL provides names for each of the 16 palette entries:

Integer Hex Style Code Constant Default colour
0 0 \s00 #D.COL.BLACK
1 1 \s01 #D.COL.RED
2 2 \s02 #D.COL.BLUE
3 3 \s03 #D.COL.PURPLE
4 4 \s04 #D.COL.GREEN
5 5 \s05 #D.COL.GRAY
6 6 \s06 #D.COL.MEDBLUE
7 7 \s07 #D.COL.LIGHTBLUE
8 8 \s08 #D.COL.BROWN
9 9 \s09 #D.COL.ORANGE
10 A \s0A #D.COL.LIGHTGRAY
11 B \s0B #D.COL.PINK
12 C \s0C #D.COL.LIGHTGREEN
13 D \s0D #D.COL.YELLOW
14 E \s0E #D.COL.AQUA
15 F \s0F #D.COL.WHITE

The constant is simply a readable name for the integer in the first column.

For example:

#D.COL.PINK

has the value 11, which is hexadecimal B.

It therefore selects the same palette entry as the B in:

\s0B

Palette colours

These constants refer to entries in the Display palette. The colours shown above are those of the standard palette.

Programs can change the palette, so #D.COL.PINK selects palette entry 11; it does not guarantee that entry 11 is currently pink.

Filling with a style

D.FIL uses the current Display style when it fills the Display.

We can see this easily with a visible pattern:

D.COL #D.COL.PINK
D.FIL "123"
D.BLT

The repeating 123 pattern is now pink.

What if we fill with spaces instead?

D.COL #D.COL.PINK
D.FIL " "
D.BLT

The Display looks blank.

A normal space has no visible foreground pixels, so changing its foreground colour doesn't give us a coloured background.

But we already know another style from NCL 210: inversion.

D.COL can set that at the same time:

D.COL #D.COL.PINK #D.TXT.INVERT
D.FIL " "
D.BLT

Now every space is inverted.

Instead of an empty Display, we have a solid pink one.

Try changing #D.COL.PINK to another colour from the table.

Display state sticks around

Just like registers, the Display keeps its current state until something changes it.

After:

D.COL #D.COL.PINK #D.TXT.INVERT

the current colour is still pink and the current text mode is still inverted after D.FIL finishes.

If we now start writing our interface, that text will use the same style.

So after creating our background, we'll choose the style we want for ordinary text:

D.COL #D.COL.PINK #D.TXT.INVERT
D.FIL " "

D.COL #D.COL.WHITE #D.TXT.NORMAL

We've established the background, then changed the current style for whatever we draw next.

Nothing needed to reset automatically.

We changed the Display state, so we change it again when we want something different.

Building a layout

Let's build a simple status screen.

We want it to contain a title and three fields:

     NCS/e SYSTEM STATUS


   NAME:       TERMINAL 1

   STATUS:     READY

   MODE:       LOCAL

        PRESS ANY KEY

Instead of producing this as one long string, we can think about where each part belongs.

For example:

Text X Y
NCS/e SYSTEM STATUS 5 1
NAME: 3 4
TERMINAL 1 15 4
STATUS: 3 6
READY 15 6
MODE: 3 8
LOCAL 15 8
PRESS ANY KEY 8 10

Notice what we've done with the fields.

The labels all begin at X position 3.

Their values all begin at X position 15.

That gives the screen columns.

Now we can translate the layout directly into NCL:

D.COL #D.COL.BLUE #D.TXT.INVERT
D.FIL " "

D.COL #D.COL.WHITE #D.TXT.NORMAL

D.CUR 5 1
D.TXT "NCS/e SYSTEM STATUS"

D.CUR 3 4
D.TXT "NAME:"

D.CUR 15 4
D.TXT "TERMINAL 1"

D.CUR 3 6
D.TXT "STATUS:"

D.CUR 15 6
D.TXT "READY"

D.CUR 3 8
D.TXT "MODE:"

D.CUR 15 8
D.TXT "LOCAL"

D.CUR 8 10
D.TXT "PRESS ANY KEY"

D.BLT

SYS.AKEY s0

There aren't many new ideas in this program.

We're mostly combining things we already know:

  • D.COL chooses the style we're drawing with;
  • D.FIL establishes the background;
  • D.CUR chooses a position;
  • D.TXT changes the Display contents at that position;
  • D.BLT shows the completed result;
  • SYS.AKEY waits for a key.

The important difference is how we're using them together.

We're no longer asking only:

What text should I write next?

We're also asking:

Where does this part of the screen belong?

Drawing before showing

Notice that we didn't do this:

D.COL #D.COL.BLUE #D.TXT.INVERT
D.FIL " "
D.BLT

and then refresh again after every individual piece of text.

Instead, we prepared everything first:

D.FIL " "

D.CUR 5 1
D.TXT "NCS/e SYSTEM STATUS"

D.CUR 3 4
D.TXT "NAME:"

-- More of the screen...

None of those changes need to be shown individually.

Only when the complete screen is ready do we use:

D.BLT

The physical Display then refreshes with the completed layout.

This is one of the reasons D.TXT is useful when drawing a screen.

We can make many changes to the Display state and show them together.

A screen has structure

Our little status screen already has structure.

It has:

  • a title;
  • a group of labels;
  • a group of values;
  • a prompt at the bottom.

And each part has an assigned place.

That makes the layout easier to change.

If we decide that the values should begin farther to the right, we can change their X coordinates.

If the title should be lower, we can change its Y coordinate.

The text itself doesn't need to change.

This is also where fixed-width strings become useful.

If a particular field has a known amount of space available, the string operations we learned in NCL 206 and used again in NCL 211 can prepare text that fits that space.

The Display decides where the field goes.

Our string operations can decide what fits inside it.

Try it

Change the status screen.

First, give it a different background:

D.COL #D.COL.PINK #D.TXT.INVERT
D.FIL " "

Your serious computer terminal is now salmon pink.

Then try changing the contents and positions.

You could:

  • change TERMINAL 1 to another name;
  • change READY to another status;
  • move the title;
  • move the labels and values into different columns;
  • add another field;
  • use a different foreground colour;
  • place a message in one of the unused rows.

Try to decide where each piece belongs before writing its D.CUR.

You can even make a small table like the one above first, then translate those positions into NCL.

The goal isn't to make the prettiest interface yet.

It's to start thinking of the Display as a complete layout rather than a stream of text.


We can now establish a background, position fields deliberately, prepare an entire screen in Display state, and reveal it with one D.BLT.

But our status screen has a problem.

Suppose:

STATUS:     READY

needs to become:

STATUS:     BUSY

We could build the entire screen again.

But only one small part actually changed.

In NCL 305: Updating the Screen, we'll learn how to update the parts of a screen that need to change.