Start page: ARABART home
← All fifteen programs

ARABART: Editor

1991 · C:\ARABART\EDITOR.EXE

C:\ARABART\EDITOR.EXE
ARABART: Editor running in DOS

Loading EDITOR.EXE, 50 KB

Click the screen to type into the program.

A one-line Arabic typewriter. With every key you press, his library joins the whole line again, in the font, color and style you pick.

The story

Yasser wrote this small tool in Borland C++, with inline assembly for every call to ARABART. The whole program is one loop of 571 bytes: wait for a key, store it, clear the screen and ask ARABART to draw the whole line again. The keys follow the Arabic keyboard layout. On that layout, Shift with Q, W, E and R types small vowel marks that everyday Arabic leaves out. So he gave those keys a better job: they pick the font.

Drive his editor

EDITOR.EXE is a typewriter for Arabic. Every key you press becomes joined Arabic at once, in the font, color and style you pick.

This is his editor’s own logic, running on his own engine, with his own keys. Tap the black screen and type, or use the buttons. It starts where his own session ended: font 3, yellow, 3-D with a red shadow.

C:\ARABART\EDITOR.EXE
His editor: الفن العربي ٤,١٥ in yellow 3-D letters with a red shadow, at the top right of a black screen.

MEMORY
Font
3
Text
14
Shadow
4
Draw
3-D, function 8
Keys
16 of 80
Command keys: they change ARABART, and are never stored
Style keys: stored in the text, like tags
Letters and digits

His keys know the Arabic keyboard. The four keys that type rare vowel marks there, Shift+Q, W, E and R, became his font keys, 1 to 4. Shift+C and Shift+V step through the 16 screen colors for the text and its shadow. | turns 3-D on and off.

Style keys are different. ! @ # $ and * go into the text itself, like tags in HTML: everything after an @ is bold, until the next @. Command keys change ARABART’s settings and are never stored. Watch the memory window: a style key gets a cell, a command key does not.

From a key to a joined letter

His editor never stores a letter. It stores the key you pressed, and ARABART turns keys into letters every time it draws. That is why the letters reshape as you type.

Press a key, here or in the editor above, and follow its five stops.

Press a key in his editor:
ONE KEY, from your finger to the screen
1. The key
k6Bh
2. His buffer
~0g1t2k3i
3. ARABART’s table
table[k]EDh11101101
4. Joining
medialfinal
5. The screen
And ARABART draws the whole line again, from the first key, at the top right of the screen. Your letter appears already joined.

This is the Arabic-keyboard encoding at work. A whole line of Arabic is a plain string of English keys, so his C program keeps it in an ordinary 85-byte array. No Unicode, no font file, no layout engine on the C side.

Today your browser does these same steps for you: it stores the text as UTF-8, then a shaping engine picks each letter’s glyph from its neighbors. His ARABART did all of it, in 1,448 bytes of code.

The whole program is one loop

571 bytes of his C. Wait for a key, act on it, clear the screen, draw the whole line again. That is all of EDITOR.EXE.

Pick a key and follow it through his code, line by line. The picture lights the boxes that key passes through. Press keys in the editor above and the loop here traces them too.

Trace a key:
THE LOOP one pass per key
1getch()
2Esc?
3Shift+Q, W, E, R?
4Shift+C or V?
5| key?
6A command?
7Store or erase
8Copy the buffer
9cleardevice()
10INT 10h: draw
11Next key
EDITOR.EXE main(), the key loop
  1. 1D8Floop:call getch; wait for a key
  2. 1D94mov [key],al
  3. 1D97cmp [key],1Bh; Esc?
  4. 1DA1mov [i],50h; end after this
  5. 1DA6cmp [key],'Q'; Shift+Q?
  6. 1DADmov ax,3603h; pick a font
  7. 1DB1mov cx,1; font 1
  8. 1DB6int 10h; call ARABART
  9. 1DBCmov [key],0; not a letter
  10. 1DC0dec [i]; not stored
  11. 1DC3cmp [key],'W'; same, font 2
  12. 1DE0cmp [key],'E'; same, font 3
  13. 1DFDcmp [key],'R'; same, font 4
  14. 1E1Acmp [key],'C'; Shift+C?
  15. 1E20cmp [color],10h; past 16?
  16. 1E26inc [color]; next color
  17. 1E30mov ax,3601h; set colors
  18. 1E34mov cl,[color]
  19. 1E37mov ch,[shadow]
  20. 1E3Cint 10h; call ARABART
  21. 1E42mov [key],0; not stored
  22. 1E49cmp [key],'V'; same, shadow
  23. 1E78cmp [key],'|'; | key?
  24. 1E85mov [fn],3608h; 3-D
  25. 1E8Cmov [fn],3607h; plain
  26. 1E98cmp [key],0; a command?
  27. 1E9Cje 1EFAh; just redraw
  28. 1E9Ecmp [key],8; Backspace?
  29. 1EADmov es:[bx],al; buf[i] = key
  30. 1EB8mov byte es:[bx],0; erase
  31. 1EC2dec [i]; one back
  32. 1EDFmov al,es:[bx]; copy 85 bytes
  33. 1EEEmov es:[bx],al; to the draw copy
  34. 1EFAcall cleardevice; a black screen
  35. 1F08lds dx,[out]; the text
  36. 1F0Bmov cx,27Fh; x = 639
  37. 1F0Emov bx,64h; y = 100
  38. 1F11mov ax,[fn]; 3607h or 3608h
  39. 1F14int 10h; draw the line
  40. 1F1Finc [i]
  41. 1F22cmp [i],50h; 80 keys yet?
  42. 1F28jmp loop; next key
  43. 1F2Bcall closegraph; the end
The same in C
  1. for (i = 0; i < 80; i++) {
  2. key = getch();
  3. if (key == 27) key = 0, i = 80;// Esc
  4. if (key == 'Q') font(1), key = 0, i--;
  5. if (key == 'W') font(2), key = 0, i--;
  6. if (key == 'E') font(3), key = 0, i--;
  7. if (key == 'R') font(4), key = 0, i--;
  8. if (key == 'C') {
  9. color = color > 16 ? 1 : color + 1;
  10. colors(color, shadow); key = 0; i--;
  11. }
  12. if (key == 'V') { /* same, shadow */ }
  13. if (key == '|') {
  14. fn = fn == 0x3607 ? 0x3608 : 0x3607;
  15. key = 0; i--;
  16. }
  17. if (key != 0) {
  18. if (key != 8) buf[i] = key;
  19. else { buf[i] = 0; i--;
  20. buf[i] = 0; i--; }
  21. memcpy(out, buf, 85);
  22. }
  23. cleardevice();
  24. arabart(fn, 639, 100, out);// draw
  25. }
  26. closegraph();
Watches
key
6Bh “k”
i
3 keys typed so far
clr
14 yellow
fn
3608h draw in 3-D
Help

His loop waits here until you press a key. You press k.

Drawing everything again after every key keeps the program tiny and always right. The screen is always made from the text, so it can never drift out of step with it. Modern interfaces are built on the same idea: React renders the view from the data on every change.

His editor, and the same ideas today
1991 to 19932026Why it is the same idea
Clear the screen and draw the whole line after every key React rendering the view from state The picture always comes from the data, so it cannot drift.
One getch() loop reads letters and commands One keydown handler that checks for shortcuts before it inserts text One stream of keys; the code decides which ones are commands.
Style keys stored in the text, commands sent to ARABART Markdown’s **bold** in the text, a font menu in the app Some styling travels with the text. Some belongs to the program showing it.
ARABART keeps its font and colors between programs A background service that keeps its own state Run the editor again and it starts in the colors you left it in.
For engineers: the start of main() and the draw call
EDITOR.EXE · main (image offset 1CFDh)
1D13 mov word [bp-8],3607h ; fn: plain text to start
1D18 mov byte [bp-9],1 / mov byte [bp-0Ah],1 ; color and shadow counters
1D2E call initgraph ; Borland graphics: detect the card
1D49 mov ax,3600h / int 10h ; is ARABART in memory?
1D4E cmp ax,5944h / je 1D5Dh ; it answers 5944h
1D7A mov byte es:[bx],0 / inc word [bp-16h] ; clear 85 bytes of buffer
1EFF push si / push di / push bp / push es / push ds ; save nine registers
1F04 push dx / push cx / push bx / push ax
1F08 lds dx,[bp-12h] / mov cx,27Fh / mov bx,64h ; text, x = 639, y = 100
1F11 mov ax,[bp-8] / int 10h ; draw: 3607h or 3608h
Image offsets in the unpacked EDITOR.EXE; the file adds a 2A0h-byte header. The names in the stepper above are ours: his variables live on the stack, the key at [bp-13h], i at [bp-18h], the colors at [bp-9] and [bp-0Ah], the draw function at [bp-8].

Every call to ARABART is a small block of inline assembly inside his C: save the registers, load AX and CX, int 10h, restore. Before the draw call he saves nine registers, so ARABART is free to use any of them. The buffer starts at DS:0093 and the copy ARABART reads at DS:00EF. The editor is built with Borland C++ and its graphics library. See main() in Every Byte.

Every Byte of EDITOR.EXE

Each square is one byte of the program in memory, colored by what it is. Tap a part to open it in the full map, down to the single instruction.

C:\ARABART\EDITOR.EXE