Start page: ARABART home
← All fifteen programs

ARABART: Demo

1991 · C:\ARABART\DEMO.EXE

C:\ARABART\DEMO.EXE
ARABART: Demo running in DOS

Loading DEMO.EXE, 50 KB

Click the screen to type into the program.

The showcase for his Arabic engine: one line of Arabic in four fonts and twelve colors, stretched, then all of it again in italic.

The story

Borland C and its graphics library could not write a single word of Arabic. ARABART gives them Arabic with one call. It is a small program that stays in memory once it starts, like a background service on your laptop, and any program can ask it to draw. The text goes in as the English keys of an Arabic keyboard. The library joins the letters in five hand-drawn fonts, with bold, italic, underline, double size and 3-D. The demo itself is a loop of a dozen lines of C that talks to ARABART through five tiny functions. It works out every position from the text itself, never from numbers typed in by hand. Three programs in this archive call ARABART: this demo, the editor and The Brave Sun.

One line, a hundred and twenty times

DEMO.EXE shows off everything ARABART can do with one short line: الفن العربي ٤,١٥, “Arabic Art 4.15”. A loop of a dozen lines of C draws it again and again, until four screens are full.

Here is that loop, rebuilt in your browser on his own engine. Press Run and watch it fill the screen line by line, the way his PC did. Step back and forth to see each call.

C:\ARABART\DEMO.EXE screen 1 of 4
Screen 1 of his demo: الفن العربي ٤,١٥ in three columns, fonts 1 to 3, each line in a new color.

main() what it just did
ar_font(3);
ar_color(15);
ar_text(261, 374, s1);
y += ar_height(s1);
The last line of screen 1: font 3, in white.

No position on these screens is typed in by hand. Before each line, his loop asks ARABART how tall the font is and moves down by exactly that much. After twelve lines it asks how wide the line came out and starts the next column that far to the left. Turn on Show the measuring to see it.

That is why the columns fit so snugly, whatever the font. A browser does the same today when it sizes a box to fit its text.

Put your words in his demo

Type any Arabic below. His demo loop picks up your line and draws it on all four screens, in every font and color.

YOUR LINE ARABART, 640×480

الفن العربي ٤,١٥

Options
Font

Font 5 has its own big letters only for الشمس, The Sun. Other letters come from font 1.

Text color
Shadow color
Effect
Style, from the first letter
Screen
Join bits, the line you are typing

    Stored as his programs stored it: #~gtk ~guvfd 51<4#

    On an English keyboard, press the key where each letter sits on an Arabic keyboard: g is ل, h is ا. Shift+3 types #, his underline key, as in the line he chose. For screens 2 and 4 the demo stretches each word at its middle join, just as he stretched his.

    Five tiny functions

    His demo is written in C. ARABART is a separate program, already waiting in memory. Between them sit five small functions he wrote, each a few lines long.

    Each function fills in a few numbers, the way you fill in a request, and rings ARABART through the PC’s built-in video service, INT 10h. The rest of the demo never deals with any of that. It just calls ar_font(1) or ar_text(x, y, s). Today we call this an SDK: friendly functions over an API. Step through one line of screen 1 below, from the C down to the call and back.

    ONE CALL, end to end
    main()his demo, in C
    ar_font(1)his binding
    INT 10hthe video service
    ARABARTwaiting in memory
    Sent nothing yet Back nothing yet
    VGA the top right corner
    DEMO.EXE his ARABART binding
    1. 206Bpush bp; ar_color(c)
    2. 2079push ax; save registers
    3. 207Dmov ax,3601h; colors
    4. 2080mov cx,[bp+6]; the color
    5. 2083int 10h; call ARABART
    6. 2085pop dx; restore them
    7. 208Aretf
    8. 208Bpush bp; ar_font(f)
    9. 2099push ax; save registers
    10. 209Dmov ax,3603h; pick a font
    11. 20A0mov cx,[bp+6]; the font
    12. 20A3int 10h; call ARABART
    13. 20A5pop dx; restore
    14. 20AAretf
    15. 20ABenter 2,0; ar_width(s)
    16. 20BFlds dx,[bp+6]; the text
    17. 20C2mov ax,3605h; measure
    18. 20C5int 10h; call ARABART
    19. 20C8mov [bp-2],cx; the width
    20. 20CFmov ax,[bp-2]; return it
    21. 20D6enter 4,0; ar_height(s)
    22. 20ECmov ax,3604h; font info
    23. 20EFint 10h; call ARABART
    24. 20F1mov [bp-2],dx; h = height
    25. 20F8les bx,[bp+6]; the text
    26. 2103next:cmp byte [bp-3],24h; a $?
    27. 2107jne 2114h
    28. 210Fimul dx; h * 2
    29. 2114inc si; next key
    30. 211Ecmp byte [bp-3],0; the end?
    31. 2122jne next
    32. 2124mov ax,[bp-2]; return h
    33. 212Cpush bp; ar_text(x, y, s)
    34. 2141call 20D6h; ar_height(s)
    35. 2146add [bp+8],ax; y += h
    36. 214Emov cx,[bp+6]; x, right edge
    37. 2151mov bx,[bp+8]; y, line bottom
    38. 2154lds dx,[bp+0Ah]; the text
    39. 2157mov ax,3607h; draw
    40. 215Aint 10h; call ARABART
    41. 2162retf
    The same in C
    1. for (font = 1; font <= 3; font++) {
    2. for (y = 0, c = 1; c < 13; c++) {
    3. ar_font(font);
    4. ar_color(c + 3);// 4 to 15
    5. ar_text(x, y, s1);
    6. y += ar_height(s1);
    7. }
    8. x -= ar_width(s1);// next column
    9. }
    10. void ar_color(int c) {
    11. _AX = 0x3601; _CX = c;
    12. geninterrupt(0x10);
    13. }
    14. void ar_font(int f) {
    15. _AX = 0x3603; _CX = f;
    16. geninterrupt(0x10);
    17. }
    18. int ar_width(char far *s) {
    19. _DS = FP_SEG(s); _DX = FP_OFF(s);
    20. _AX = 0x3605; geninterrupt(0x10);
    21. return _CX;
    22. }
    23. int ar_height(char far *s) {
    24. _AX = 0x3604; geninterrupt(0x10);
    25. int h = _DX;
    26. for (; *s; s++)
    27. if (*s == '$') h *= 2;
    28. return h;
    29. }
    30. void ar_text(int x, int y, char far *s) {
    31. y += ar_height(s);// top to bottom
    32. _CX = x; _BX = y;
    33. _DS = FP_SEG(s); _DX = FP_OFF(s);
    34. _AX = 0x3607; geninterrupt(0x10);
    35. }
    Watches
    x
    630 the right edge of this column
    y
    0 the top of the next line
    Help

    His demo starts a column in font 1, with its right edge at x = 630.

    His binding, and an SDK today
    1991 to 19932026Why it is the same idea
    ar_font(1), ar_text(x, y, s) sdk.setFont(1), sdk.drawText(…) A friendly name in your own language, over a numbered request.
    int 10h, request 36h One HTTP call to a service One door into code that someone else runs.
    A second number picks the job: 1 colors, 3 font, 7 draw The route: /colors, /font, /draw A number, or a path, says what you want.
    The values ride in the processor’s own scratch slots The JSON body of the request The arguments travel in a fixed, agreed shape.
    ar_text adds the line height to y An SDK that converts units for you The caller thinks in its own terms. The binding speaks the service’s.
    For engineers: main() and the binding, as compiled
    DEMO.EXE · main (image offset 2163h)
    2187 call SCOPY (28 bytes, DS:0092) ; string 1 onto the stack
    2198 call SCOPY (34 bytes, DS:00AE) ; string 2, with the stretch
    21BC call initgraph ; Borland graphics, driver 0: detect the card
    2209 mov word [bp-0Ah],276h ; x = 630
    221C push [bp-0Ch] / call ar_font
    2224 mov ax,si / add ax,3 / push ax / call ar_color ; colors 4 to 15
    2239 call ar_text ; x, y, s1
    2245 call ar_height / add di,ax ; y += height
    2258 call ar_width / sub [bp-0Ah],ax ; x -= width
    226E call getch / call cleardevice ; a key, then the next screen
    22D3 mov byte [bp-28h],21h ; pass 2: ! at byte 0 of s1
    22DB mov byte [bp-16h],20h / mov byte [bp-14h],23h ; the closing # moves two keys on
    2300 cmp word [bp-8],1 / jg 2309h ; two passes, four screens
    Image offsets in the unpacked DEMO.EXE; the file adds a 300h-byte header. SCOPY is Borland’s helper that copies a block of bytes.

    The binding sits at 206Bh to 2162h: ar_color 206Bh, ar_font 208Bh, ar_width 20ABh, ar_height 20D6h and ar_text 212Ch. Each one is a far C function with Borland’s stack check, and each saves every register it touches, so ARABART can use them freely. The demo is built with Borland C++ and its graphics library, the same tools as The Brave Sun, which talks to ARABART through this same binding. See the binding in Every Byte.

    The whole line is one C string

    No font file, no markup language. The line, its underline and its version number are 27 keys in an ordinary C string, typed on an English keyboard.

    ARABART reads the string from the right, the way Arabic reads. Pick any key to see what it becomes. Then switch to screen 3: for the italic screens his demo changes just three bytes of the same string and runs the same loop again.

    THE STRING, one key per byte
    Key 3, ~: his table turns it into 30h, the letter ا, and it never joins. Here it keeps that shape: isolated.
    His first string: a space, # underline on, the line, # underline off, then eight spaces.

    Look at the number. Arabic runs right to left, and numbers run left to right. ARABART lays every key down from right to left. So he typed the version backwards, 51<4, and it comes out reading ٤,١٥, in the Arabic-Indic digits used in Egypt.

    Every key here is the Arabic-keyboard encoding at work: ~gtk are the keys under ا, ل, ف and ن. The final yeh is drawn without dots, ى, the way Egyptian writers write it. And the J key gives the kashida, the stroke a calligrapher uses to stretch a word.

    Every Byte of DEMO.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\DEMO.EXE