--- title: "Characters" id: 56287 type: "computer_media" slug: "characters" url: "http://localhost/computer_media/characters/" markdown_url: "http://localhost/computer_media/characters.md" published_at: "2024-08-04T10:49:46+00:00" modified_at: "2026-03-30T21:29:27+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/08/SCR-20240804-lbpq.png" excerpt: "Type any word up to 10 characters and watch it redrawn pixel-by-pixel as a magnified outline — a clever trick using POINT and DRAW." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Font" slug: "font" taxonomy: "genre" url: "http://localhost/type/font/" media_contents: - id: 56277 title: "Timex Sinclair Public Domain Library Tape 2001" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-2001/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Characters%20%28198x%29%28Visser%2C%20Jasper%29%28TS2068%29%28UK%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/08/SCR-20240804-lbpq.png" media_type_tags: "Font" --- # Characters This program reads a word of up to 10 characters from the user and then redraws it enlarged in a pixel-by-pixel style using PLOT and DRAW commands. It scans the top portion of the display (pixel rows 168–175) where the word is printed using INK 7, then uses POINT to detect each set pixel. For every lit pixel found, a subroutine at line 220 draws a small 3×3 square outline at a scaled position lower on the screen. The horizontal and vertical positions of the enlarged output are tracked with variables `l` and `h`, which increment by 3 for each pixel column and row respectively. *** ## Program Analysis ### Program Structure The program is organised into three logical phases: 1. **Input and validation (lines 100–140):** Initialises position counters `l` and `h`, accepts a word via `LINE` input, and rejects entries longer than 10 characters with a flashing warning. 2. **Scanning loop (lines 150–200):** Prints the word at the top of the screen, then iterates over each pixel column and row in the region where the text was rendered, using `POINT` to detect set pixels. 3. **Square-drawing subroutine (lines 220–260):** For each detected pixel, draws a 3×3 outline square at a scaled position on the lower half of the screen, but only draws each side if the neighbouring pixel is not set (creating a merged/connected appearance). ### Pixel Scanning Technique The word is printed at `AT 0,0` with `INK 7`. The outer loop (`FOR a=0 TO LEN a$*8`) iterates pixel columns — each character cell is 8 pixels wide, so this covers exactly the rendered text width. The inner loop (`FOR b=175 TO 168 STEP -1`) scans 8 pixel rows (one character row’s height) from bottom to top. `POINT (a,b)` checks whether each pixel is lit. The variable `h` tracks the vertical offset within a column (reset to 0 after each column), incrementing by 3 per pixel row. The variable `l` tracks the horizontal offset, incrementing by 3 per pixel column. This gives a 3× magnification of the original character bitmaps. ### Subroutine at Line 220 — Conditional Edge Drawing Rather than filling each magnified pixel as a solid square, the subroutine draws only the edges of each 3×3 square that border a *non-set* neighbour pixel. This creates an outline effect that merges adjacent filled pixels, similar to an isoline or connected-component boundary. Each of the four sides is tested: - Left edge: `IF POINT (a-1,b)=0 THEN DRAW 0,3` - Bottom edge: `IF POINT (a,b+1)=0 THEN DRAW 3,0` - Right edge: `IF POINT (a+1,b)=0 THEN DRAW 0,-3` - Top edge: `IF POINT (a,b-1)=0 THEN DRAW -3,0` Note that after each conditional `DRAW`, the graphics cursor position has moved only if the draw was executed. This means the `PLOT` calls at the start of lines 230–250 are essential to reposition the cursor to the correct corner of the square before testing the next edge. ### Key BASIC Idioms - `INPUT "" ; LINE a$` — The `LINE` keyword captures the whole input line including spaces without requiring quotes, a standard idiom for free-form string entry. - `PRINT AT 10,0;,,` — Using bare commas after a `PRINT AT` to overprint and clear the flash warning message with spaces. - `FLASH 1; BRIGHT 1;` — Combined attribute effects used for the error message at line 140. ### Bugs and Anomalies There is a notable positioning issue: the counters `l` and `h` are initialised at line 100 but are *not* reset if the user enters a word longer than 10 characters and is sent back to line 130 via `GO TO 130`. If the user triggers the error message after the first input, `l` and `h` remain at 0 (since no scan has occurred), so in practice this is harmless on the first attempt. However, the program stops with `STOP` at line 210 rather than looping back to allow another word, so it is a single-use program per run. The scan at line 160 uses `FOR a=0 TO LEN a$*8`, which includes one extra column beyond the text (the loop runs `LEN a$*8 + 1` iterations). This is a minor off-by-one that is functionally harmless since the extra column will always read as blank pixels. ### Variable Summary | Variable | Role | | --- | --- | | `l` | Horizontal plot position for enlarged output (increments by 3 per pixel column) | | `h` | Vertical offset within a column for enlarged output (increments by 3 per pixel row, reset per column) | | `a$` | The input word (up to 10 characters) | | `a` | Pixel column index (also reused as the outer FOR loop variable) | | `b` | Pixel row index (inner FOR loop variable, scans rows 175 down to 168) | ## Source Code ``` 1 REM "CHARACTERS" 2 REM By Jasper Visser 3 REM ZX Computing Monthly 100 LET l=0: LET h=0 130 INPUT "A word please.."; LINE a$ 140 IF LEN a$>10 THEN PRINT AT 10,0; FLASH 1; BRIGHT 1;"1 - 10 CHARACTERS !!": PAUSE 50: PRINT AT 10,0;,,: GO TO 130 150 PRINT AT 0,0; INK 7;a$ 160 FOR a=0 TO LEN a$*8 170 FOR b=175 TO 168 STEP -1 180 IF POINT (a,b)=1 THEN GO SUB 220 190 LET h=h+3: NEXT b: LET h=0: LET l=l+3: NEXT a 200 PRINT AT 0,0;,, 210 STOP 220 PLOT l,50-(h+3): IF POINT (a-1,b)=0 THEN DRAW 0,3 230 PLOT l,50-h: IF POINT (a,b+1)=0 THEN DRAW 3,0 240 PLOT l+3,50-h: IF POINT (a+1,b)=0 THEN DRAW 0,-3 250 PLOT l+3,50-(h+3): IF POINT (a,b-1)=0 THEN DRAW -3,0 260 RETURN ```