On this page:
Fun  Pad:   the Word Processor for Dummies!
8.15

Lab 4 Structures, Unions, and Templates🔗

lab!

Purpose: The purpose of this lab is to give you some hands-on experience with various complex data types, including structured data and unions, as well as combinations of these. The emphasis will be on data design: doing so in a way that helps make the program more logical. We will also stress carefully following the recipe, especially the templates.

FunPad: the Word Processor for Dummies!🔗

For this lab, you will be designing a baby word processor: a program that lets you enter text, as well as perform some rudimentary editing: adding and deleting characters anywhere in the input buffer. You will be building the program in stages:

Exercise 1 Understanding Existing Code:

Grab the provided starter code from here: lab4-starter.rkt. Study the code with your partner. There is no data definition to speak of: the world state is a simple string representing the current contents of the input buffer. Study the big-bang program and event handlers. Note that the on-key handler uses a helper to do the tricky editing.

Exercise 2 Practice with Structures:

You will now upgrade the provided code to create a better word processor: one where the user can enter or delete text anywhere in the buffer, instead of just at the end, by manipulating a cursor, which they will do by using the cursor keys. In order to support this, you will need to update your world state design to include the concept of a current cursor position, in addition to the text in the input buffer.

You must then update the function implementations, and design additional functions, in order to support these expanded operations. You need to be able to display where the cursor is currently located, and correctly handle simple input and deletion requests. If the user hits any normal character key, that character should be inserted just BEFORE the character position. So, if the current string is "Hello there", and the cursor position is 4–so, over the "o" (numbering positions starting from 0 to align with the way indices work in the substring function), then if the user types the "X" character, you should end up with "HellXo there" in the input buffer, with the cursor right after the newly-inserted "X" (i.e., still over the "o").

If, back in the same original situation–string is "Hello there", cursor at 4–the user had hit BACKSPACE (the on-key handler will be called with the key event "\b"), you should delete the character just before the cursor, ending up with the string "Helo there", and the cursor at 3, i.e., once again, over the "o" character (the cursor seems to really like the "o" :-) )

Also, you must be able to correctly handle the edge case of the user attempting to delete characters before the beginning of the text, i.e., hitting BACKSPACE when the cursor is already at the very beginning (the correct behavior is to ignore the request). You must also handle the user trying to add text beyond the end (this should be allowed, but it’s slightly tricky–see HINTS below).

What information will you need in your world state? It will clearly be complex enough that you will want to design a structured data type to hold the information. Think about what changes, and what remains the same. (Examples: the frame size can remain fixed, but obviously the input buffer will change as the user types; what else changes and needs to be kept track of?

Some Random Hints:
  • Note that the cursor can be positioned over any of the characters in the string in the input buffer, but it must also be positionable beyond the last character: else, the user would not be able to insert text at the end of the buffer. You must support this.

  • to indicate the current cursor position, you can simply draw the character the cursor is positioned at in red, while the rest of the text is black. This is easy except for two cases: first, what to do if the cursor is over a space, since rendering a red space will not actually draw anything visible in red? In that case, you can print a red "_" (underscore). Second, what should you do when the cursor is beyond the end of the buffer (see previous note)?; in that case, you can display a "#" in red after the last character of real text in the input buffer. Note: if the cursor is not at the end, you should not display the "#".

  • For displaying the input text, just use a text image (actually, several sequential text images, in order to do the coloring suggested in the previous hint), inside a box wide enough to hold about 80 characters. Your editor only needs to work on a single input line.

  • Don’t worry about handling uppercase letters: handling the SHIFT key is hard. Just don’t try to enter any uppercase letters. (If you do accidentally hit the SHIFT key, you will get a weird character in your input string–just kill the program and start over.)

Exercise 3 Practice with Unions:

For this part, you are going to evolve your design from the previous exercise into a more "app-like" program. You will make your world program modal: like what we did with the moon program in class when it had a "start" phase, a "moving moon" phase, and a "done" phase. For this exercise, when the program begins, it should display an initial splash screen that announces "FunPad!!!" (short for "Fundies Notepad"–get it??), with the message "(Hit any key to continue)" on a separate line below.

Then, when the user hits a key (any key), your program should transition over to its editing mode, which will be pretty much what you designed for the previous exercise above. The only changes are: in addition to displaying the input buffer (including cursor position), below the text entry window, your display should include a message that says "Hit ENTER to finish editing".

When the user hits the "ENTER" key (will show up as a "\n" in the key event), you should transition to the third and final mode of your program (see next paragraph), where you pretend to save the file.

In the third mode, you will display a pretend save screen: the program should display the final edited string in a box, with a message below that saying: "Saved to file". Your program should stay in this mode, ignoring any input. No stop-when handler or final exit screen is needed.

To support this modal behavior, you should re-design the world state as a union of three possible types: the first just needs to encode that you’re in the start mode; the second needs to encode both the string being edited as well as any other information you will need to implement proper editing; the third world state type needs to also contain the string (so it can display it), but doesn’t need the additional information about the cursor position.