QB64 Phoenix Edition
Confusing Chr$ explanation - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: QB64 Rising (https://qb64phoenix.com/forum/forumdisplay.php?fid=1)
+--- Forum: Code and Stuff (https://qb64phoenix.com/forum/forumdisplay.php?fid=3)
+---- Forum: Help Me! (https://qb64phoenix.com/forum/forumdisplay.php?fid=10)
+---- Thread: Confusing Chr$ explanation (/showthread.php?tid=1820)

Pages: 1 2 3 4 5


RE: Confusing Chr$ explanation - RhoSigma - 07-09-2023

(07-09-2023, 07:43 AM)Space_Ghost Wrote: My guess is the ALT codes with leading zeros are not part of the QB64pe compilation options.....but someone with much more knowledge can chime in to confirm or not.

Cheers.

You should have noticed that QB64pe works with codepage 437, the copyright sign is simply not available in that set of chars. You may try whatever you want, it won't give you that sign with PRINT CHR$(169).

You have to use a unicode capable custom font, MAPUNICODE the copyright sign's unicode codepoint to any ASCII char of your choice and then PRINT that remapped char.

On the other hand you may use UPRINTSTRING with the respective codepoint directly, but that requires a graphic screen (text SCREEN 0 is not supported) and of course a suitable unicode custom font too.


RE: Confusing Chr$ explanation - SagaraS - 07-09-2023

(07-09-2023, 04:22 AM)PhilOfPerth Wrote: I'm able to see characters for all the Alt values, but I'm unable to produce the Copyright (and some others). The Alt table says it should be Alt 0169,
but Alt + 0169 only produces the ┌ symbol (or something very similar).
When I enter  Alt + 0169  here, on the Forum, I get the © ok. Why not in my program?
The copyright character does not exist in the DOS ASCII character set of code page 437.

All characters from 128 to 255 are different characters than what you have in Windows + those of other countries.

e.g.:
Code page 437 = English https://de.wikipedia.org/wiki/Codepage_437
Character 169 / &HA9
MS DOS characters: ⌐
MS WIN Character: ©

Code page 850 = Western European https://de.wikipedia.org/wiki/Codepage_850
Character 169 / &HA9
MS DOS characters: ®
MS WIN Character: ©

You must use a Unicode set for that.

Create the following file
CP850.CSV
Code: (Select All)
' Microsoft_pc_cp850
199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
201,230,198,244,246,242,251,249,255,214,220,248,163,216,215,402
225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
9617,9618,9619,9474,9508,193,194,192,169,9571,9553,9559,9565,162,165,9488
9492,9524,9516,9500,9472,9532,227,195,9562,9556,9577,9574,9568,9552,9580,164
240,208,202,203,200,**305**,205,206,207,9496,9484,9608,9604,166,204,9600
211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
173,177,8215,190,182,167,247,184,176,168,183,185,179,178,9632,160

The character numbered 305 in the table (which is bracketed with asterisks) is the euro character. Simply remove the stars to have the euro sign in the set.

Then you can use the following in QB64:
Code: (Select All)

SCREEN 0
_FONT _LOADFONT("C:\Windows\Fonts\Cour.ttf", 20, "MONOSPACE") 'select monospace font
FileName$ = "CP850.CSV" '              <<<<<<< Enter Unicode CSV data text file name you created here!**
f = FREEFILE
OPEN FileName$ FOR INPUT AS #f
INPUT #f, CodePage$ '                  read code page ID on first line of file
IF NOT EOF(f) THEN PRINT CodePage$ '    display code page number

FOR ascii = 128 TO 255 '                assign unicode values to ascii 128 to 255 only
  IF EOF(f) THEN EXIT FOR
  INPUT #f, unicode&
  IF unicode& = 0 THEN unicode& = 9744 'make undefined characters look like a box
  _MAPUNICODE unicode& TO ascii '      replace ascii with unicode value
NEXT
CLOSE #f

FOR code = 128 TO 255
  PRINT code; CHR$(code); '            display unicode characters
NEXT

END

And this would be your output:
Character 169 is now ®
[Image: cp850h7dyd.png]

Here a QB64 code for the complete table

Code: (Select All)
' instructs the compiler to require variable declaration
OPTION _EXPLICIT

' Control function off to set all characters
_CONTROLCHR OFF

' dimension variables
DIM winX AS _UNSIGNED INTEGER
DIM winY AS _UNSIGNED INTEGER
DIM i AS _UNSIGNED _BYTE
DIM x AS _UNSIGNED _BYTE
DIM y AS _UNSIGNED _BYTE
DIM selx AS _UNSIGNED _BYTE
DIM sely AS _UNSIGNED _BYTE
DIM keyin AS STRING

' variables for codepages
DIM Filename AS STRING
DIM CodePage AS STRING
DIM ASCII AS _UNSIGNED _BYTE
DIM UNICODE AS _UNSIGNED LONG
DIM F AS _UNSIGNED _BYTE

' Load codepage 850 from UNICODE
_FONT _LOADFONT("C:\Windows\Fonts\Cour.ttf", 20, "MONOSPACE") 'select monospace font
Filename = "CP850.CSV" '              <<<<<<< Enter Unicode CSV data text file name you created here!**
F = FREEFILE
OPEN Filename FOR INPUT AS #F
INPUT #F, CodePage '                  read code page ID on first line of file
IF NOT EOF(F) THEN PRINT CodePage '    display code page number

FOR ASCII = 128 TO 255 '                assign unicode values to ascii 128 to 255 only
  IF EOF(F) THEN EXIT FOR
  INPUT #F, UNICODE
  IF UNICODE = 0 THEN UNICODE = 9744 'make undefined characters look like a box
  _MAPUNICODE UNICODE TO ASCII '      replace ascii with unicode value
NEXT
CLOSE #F

' Create window area with colors
COLOR 4, 7
winX = 14
winY = 4
FOR y = winY + 0 TO winY + 16
  FOR x = winX + 0 TO winX + 16 * 3
    LOCATE y, x: PRINT SPACE$(2);
  NEXT x
NEXT y

' Create table info
FOR i = 0 TO 15
  LOCATE winY, winX + (i * 3) + 3: PRINT "0" + HEX$(i);
  LOCATE winY + i + 1, winX: PRINT HEX$(i) + "0";
NEXT i

' Create ASCII characters
' Init values for the table of ASCII chars
COLOR 0, 7
winX = winX + 1
winY = winY + 1

DO
  ' Output of all ASCII characters in the table
  x = 0
  y = winY
  FOR i = 0 TO 255
    IF selx = x AND sely = y - winY THEN COLOR 7, 2 ELSE COLOR 0, 7
    LOCATE y, winX + (x * 3) + 3: PRINT CHR$(i);
    x = x + 1
    IF x = 16 THEN
      x = 0
      y = y + 1
    END IF
  NEXT i

  ' Output of decimal and hex value of current char
  COLOR 0, 7
  LOCATE winY + 16, winX - 1: PRINT SPACE$(25);
  LOCATE winY + 16, winX - 1: PRINT "ASCII:  DEC(" + LTRIM$(STR$(sely * 16 + selx)) + ")  HEX(" + HEX$(sely * 16 + selx) + ")";

  ' Key Input
  DO
    keyin = INKEY$
  LOOP WHILE keyin = ""

  ' Arrowkeys to select the current char
  IF keyin = CHR$(0) + CHR$(77) THEN IF selx >= 15 THEN selx = 0 ELSE selx = selx + 1
  IF keyin = CHR$(0) + CHR$(75) THEN IF selx <= 0 THEN selx = 15 ELSE selx = selx - 1
  IF keyin = CHR$(0) + CHR$(80) THEN IF sely >= 15 THEN sely = 0 ELSE sely = sely + 1
  IF keyin = CHR$(0) + CHR$(72) THEN IF sely <= 0 THEN sely = 15 ELSE sely = sely - 1

  ' ESC to end the program
LOOP WHILE keyin <> CHR$(27)

Output is this:
[Image: cp850_2s4fg9.png]


When you use the DOSBox you must change the keyboard + character set.
KEYB gr 850   <- It's for german keyboard layout + codepage 850

Then have the same result in the DOSBox with the characters:
[Image: qb_0053ofcm.png]

In both cases you then have your copyright char in the set.
Character 169 - ®
Character 184 - ©



If you are looking for a suitable DOS TrueType font on the Internet, you can also make the characters look original. (QB64)
e.g.: https://archive.org/details/ultimate_oldschool_pc_font_pack_v1.0

The output then looks like this:
("PxPlus_IBM_VGA9.ttf", 16, "MONOSPACE")
[Image: cp850_31kdmi.png]


RE: Confusing Chr$ explanation - SagaraS - 07-09-2023

Another possibility would be to use a raster font. But the whole thing doesn't work in Screen 0 mode.

http://orangetide.com/fonts/DOS/

The File "cp850.f16" on this site is that what you search. F16 stand for 8x16 raster font.
Screen mode must use 8x16 fonts. e.g.: Screen 11 or 12
Screen Mode 12 would be similar to Screen 0

or much better is
Code: (Select All)
SCREEN _NEWIMAGE(640, 400, 256) ' <- Screen 0 Resolution
WIDTH 80, 25 '                    <-- Colums and Rows from Screen 0


Here a picture of my raster font editor with this font.
[Image: cp850_r1qycyh.png]


You can load this raster font into an array and have the array indexed. As a CHR$ replacement.
Example:

Sorry for the font comments.
Originally I used the whole thing for 8x8 raster fonts.
Just modified it for 8x16.

Code: (Select All)
REDIM SHARED FontMEM(0) AS _UNSIGNED _BYTE '  Font Memory for 8x8 raster fonts. 1024 or 2048 Bytes

SCREEN 12

CALL LoadFNT("cp850.f16")

' instructs the compiler to require variable declaration
OPTION _EXPLICIT

' Control function off to set all characters
_CONTROLCHR OFF

' dimension variables
DIM winX AS _UNSIGNED INTEGER
DIM winY AS _UNSIGNED INTEGER
DIM i AS _UNSIGNED _BYTE
DIM x AS _UNSIGNED _BYTE
DIM y AS _UNSIGNED _BYTE
DIM selx AS _UNSIGNED _BYTE
DIM sely AS _UNSIGNED _BYTE
DIM keyin AS STRING
DIM col1 AS _UNSIGNED _BYTE
DIM col2 AS _UNSIGNED _BYTE

' Create window area with colors
COLOR 4, 7
winX = 14
winY = 4
FOR y = winY + 0 TO winY + 16
  FOR x = winX + 0 TO winX + 16 * 3
    LOCATE y, x: PRINT SPACE$(2);
  NEXT x
NEXT y

' Create table info
FOR i = 0 TO 15
  LOCATE winY, winX + (i * 3) + 3: PRINT "0" + HEX$(i);
  LOCATE winY + i + 1, winX: PRINT HEX$(i) + "0";
NEXT i

' Create ASCII characters
' Init values for the table of ASCII chars
COLOR 0, 7
winX = winX + 1
winY = winY + 1

DO
  ' Output of all ASCII characters in the table
  x = 0
  y = winY
  FOR i = 0 TO 255
    'IF selx = x AND sely = y - winY THEN COLOR 7, 2 ELSE COLOR 0, 7
    'LOCATE y, winX + (x * 3) + 3: PRINT CHR$(i);
    IF selx = x AND sely = y - winY THEN col1 = 7: col2 = 2 ELSE col1 = 0: col2 = 7
    FPRINT winX + (x * 3) + 3, y, CHR$(i), col1, col2
    x = x + 1
    IF x = 16 THEN
      x = 0
      y = y + 1
    END IF
  NEXT i

  ' Output of decimal and hex value of current char
  COLOR 0, 7
  LOCATE winY + 16, winX - 1: PRINT SPACE$(25);
  LOCATE winY + 16, winX - 1: PRINT "ASCII:  DEC(" + LTRIM$(STR$(sely * 16 + selx)) + ")  HEX(" + HEX$(sely * 16 + selx) + ")";

  ' Key Input
  DO
    keyin = INKEY$
  LOOP WHILE keyin = ""

  ' Arrowkeys to select the current char
  IF keyin = CHR$(0) + CHR$(77) THEN IF selx >= 15 THEN selx = 0 ELSE selx = selx + 1
  IF keyin = CHR$(0) + CHR$(75) THEN IF selx <= 0 THEN selx = 15 ELSE selx = selx - 1
  IF keyin = CHR$(0) + CHR$(80) THEN IF sely >= 15 THEN sely = 0 ELSE sely = sely + 1
  IF keyin = CHR$(0) + CHR$(72) THEN IF sely <= 0 THEN sely = 15 ELSE sely = sely - 1

  ' ESC to end the program
LOOP WHILE keyin <> CHR$(27)


SUB LoadFNT (file AS STRING)
  ' Loading 8x8 Raster Font in the Font Memory
  ' If File > 1024 then Font Memory = 2048 Byte else 1024 Byte
  OPEN file FOR BINARY ACCESS READ AS #1
  IF LOF(1) > 2048 THEN
    REDIM FontMEM(4095) AS _UNSIGNED _BYTE
  ELSE
    REDIM FontMEM(2047) AS _UNSIGNED _BYTE
  END IF
  GET #1, , FontMEM()
  CLOSE #1
END SUB

SUB FPRINT (x AS _UNSIGNED INTEGER, y AS _UNSIGNED INTEGER, Text AS STRING, col1 AS _UNSIGNED _BYTE, col2 AS _UNSIGNED _BYTE)
  ' The same as the PRINT funtion in QB64
  ' but it use the own Font
  DIM px AS _UNSIGNED INTEGER
  DIM py AS _UNSIGNED INTEGER
  DIM i AS _UNSIGNED INTEGER
  DIM lowBase AS _UNSIGNED _BYTE
  DIM idx AS _UNSIGNED LONG

  px = (x - 1) * 8
  py = (y - 1) * 16

  IF UBOUND(FontMEM) <= 2047 THEN lowBase = 1

  FOR i = 1 TO LEN(Text)
    idx = ASC(MID$(Text, i, 1))
    CALL FONTprint(idx, lowBase, px, py, col1, col2)
    px = px + 8
  NEXT i
END SUB

SUB FONTprint (idx AS _UNSIGNED _BYTE, lowBase AS _UNSIGNED _BYTE, px AS _UNSIGNED INTEGER, py AS _UNSIGNED INTEGER, col1 AS _UNSIGNED _BYTE, col2 AS _UNSIGNED _BYTE)
  DIM t AS _UNSIGNED _BYTE
  DIM dx AS _UNSIGNED INTEGER
  DIM dy AS _UNSIGNED INTEGER
  DIM dcol AS _UNSIGNED _BYTE

  ' Critical Error FIX, when PX > 320 or PY >200
  IF px >= 640 THEN
    px = px - 8
    EXIT SUB
  END IF
  IF py >= 400 THEN
    py = py - 16
    EXIT SUB
  END IF

  ' Draw Font
  IF idx > 127 AND lowBase = 1 THEN ' If Font idx > 127 and the Fontfile < 1024 then print empty CHAR
    FOR dy = 0 TO 15
      FOR dx = 0 TO 7
        PSET (px + dx, py + dy), col2
      NEXT dx
    NEXT dy
  ELSE '                              else draw Font idx from the FONT Memory
    FOR dy = 0 TO 15
      t = &H80
      FOR dx = 0 TO 7
        IF (FontMEM(idx * 16 + (dy)) AND t) / t = 1 THEN dcol = col1 ELSE dcol = col2
        PSET (px + dx, py + dy), dcol
        t = t / 2
      NEXT dx
    NEXT dy
  END IF
END SUB

Your output will then be as follows:
[Image: cp850_r266c23.png]


A raster font is much more accurate and faithful than TrueType fonts.


Here's another raster font as proof. "scrwl~~~.f16"
[Image: cp850_r3h4e8i.png]


RE: Confusing Chr$ explanation - TempodiBasic - 07-09-2023

(07-08-2023, 10:44 PM)mnrvovrfc Wrote:
(07-08-2023, 09:30 PM)TempodiBasic Wrote: your same code without an unuseful pause (sleep 1) and an unuseful clearscreen (CLS) plus a better output settings (;" "Wink for PRINT statement you get this output

I was going to point that out earlier but perhaps Phil wanted to see each character alone. A better idea was to switch to a graphics screen and find a way to cause a character to dominate the screen, by printing it much larger.

Code: (Select All)

DIM AS LONG thiscr, charscr
DIM AS INTEGER wx, hy, tx, ty, scale, i, j
wx = 8
hy = 14
tx = 100
ty = 100
scale = 10

SCREEN 12
thiscr = _COPYIMAGE(0)
SCREEN thiscr
_TITLE "Press [ESC] to quit."
charscr = _NEWIMAGE(wx, hy, 12)
COLOR 15
FOR i = 129 TO 255
    _DEST charscr
    LOCATE 1, 1
    PRINT CHR$(i);
    _PUTIMAGE (tx, ty)-(tx + wx * scale - 1, ty + hy * scale - 1), charscr, thiscr, (0, 0)-(wx - 1, hy - 1)
    FOR j = 1 TO 10
        _DELAY 0.1
        IF _KEYDOWN(27) THEN EXIT FOR
    NEXT
    CLS
    IF _KEYDOWN(27) THEN EXIT FOR
NEXT
_DEST 0
SYSTEM

Hi
thanks to remember me that the goal can be watching a single couple ASCII number + ASCII code in a row.
I have misunderstood the goal of the code posted by PhilOfPerth.

@mnrvovfrc
I have tried to run your code but I am in trouble.
The code runs, but the output is a little window that is blank all the time while its caption is "Press [Esc] to quit".
I have REMmed "System" too thinking that the program runs quickly and I am not able to see the output, but nothing to do.
Also increasing _delay to 1.0  or adding a _limit 5 nothing to do, I get only that blank window.
What must I do to see your output?


RE: Confusing Chr$ explanation - TempodiBasic - 07-09-2023

(07-09-2023, 04:22 AM)PhilOfPerth Wrote: I'm able to see characters for all the Alt values, but I'm unable to produce the Copyright (and some others). The Alt table says it should be Alt 0169,
but Alt + 0169 only produces the ┌ symbol (or something very similar).
When I enter  Alt + 0169  here, on the Forum, I get the © ok. Why not in my program?
The answer is in your same question! Being clearer,  QB64pe is a QB45 clone, it is standing on ASCII table, while the forum page is a webpage that uses Unicode Table. 
So 0169 in ASCII (0- 255) is equal to 169 and in the ASCII table of the IDE and of the compiler is this character  ┌
while 0169 in Unicode table (0196 = 00A9) is the copyright simbol  ©
Now I do the eco of Space_ghost, SagarS and RhoSigma
you can use  ASCII Table  external characters by using _MapUnicode to substitute an unused character with that we need.
I learnt this tip from the community when I wanted to localize to my language the input/output of keywords of QB64.
please think how is in trouble the hangman game when I must guess "papà" and not "papa"  (Dad and not the Pope) without "à" in input/output.


RE: Confusing Chr$ explanation - TempodiBasic - 07-09-2023

Hi mnrvovrfc
Solved the issue with your code
I change the foreground color and I got the characters!


RE: Confusing Chr$ explanation - PhilOfPerth - 07-10-2023

(07-09-2023, 03:48 PM)TempodiBasic Wrote:
(07-09-2023, 04:22 AM)PhilOfPerth Wrote: I'm able to see characters for all the Alt values, but I'm unable to produce the Copyright (and some others). The Alt table says it should be Alt 0169,
but Alt + 0169 only produces the ┌ symbol (or something very similar).
When I enter  Alt + 0169  here, on the Forum, I get the © ok. Why not in my program?
The answer is in your same question! Being clearer,  QB64pe is a QB45 clone, it is standing on ASCII table, while the forum page is a webpage that uses Unicode Table. 
So 0169 in ASCII (0- 255) is equal to 169 and in the ASCII table of the IDE and of the compiler is this character  ┌
while 0169 in Unicode table (0196 = 00A9) is the copyright simbol  ©
Now I do the eco of Space_ghost, SagarS and RhoSigma
you can use  ASCII Table  external characters by using _MapUnicode to substitute an unused character with that we need.
I learnt this tip from the community when I wanted to localize to my language the input/output of keywords of QB64.
please think how is in trouble the hangman game when I must guess "papà" and not "papa"  (Dad and not the Pope) without "à" in input/output.

Thanks TempodiBasic; I get it now (almost)!
With the info you gave me, I was able to write the small snippet below, and this produces the Copyright and RegisteredTM symbols, 
and any others I need from the Unicode table. 
It seems I need to set the font specifically first - in my case to a Monospace font. Is this correct? I thought the default font would have worked.
Code: (Select All)
Screen 9
f& = _LoadFont("C:\WINDOWS\fonts\courbd.ttf", 32, "monospace")
_Font f& '

Dim CopyRt As Long, RegTM As Long
CopyRt = 169: RegTM = 174
_MapUnicode CopyRt To 199: _MapUnicode RegTM To 200
Print Chr$(199), Chr$(200)



RE: Confusing Chr$ explanation - SagaraS - 07-10-2023

The problem by using TrueType Fonts is that all Fonts scaled by vector size of the font.
It's not so cool.
Then in Screen 9, for example, you no longer have 80 rows and 25 lines for the characters by a size of 32.

Screen 9 have a 8x14 Font. You must need to change the ttf font size to 14. Then you have the 80x25 text field from screen mode.

By a size of 28, you have 40x12,5 text field.

So be careful!

It would be perfect if you set your TTF fonts to the appropriate screen mode for an optimal result.

Screen 1, 2, 7, 8, 13 = Size 8 for a 8x8 Font Set
Screen 9, 10 = Size 14 for a 8x14 Font Set
Screen 11, 12 = Size 16 for a 8x16 Font Set


RE: Confusing Chr$ explanation - mnrvovrfc - 07-10-2023

(07-10-2023, 11:23 AM)SagaraS Wrote: The problem by using TrueType Fonts is that all Fonts scaled by vector size of the font.
It's not so cool.

The problem is that the user will then want to see that much larger than SCREEN 9, like in a 4k screen. This is where raster fonts are totally undesireable nowadays, and vector-type fonts are absolute. This was demonstrated distinctly by the program I posted on this thread.

Also one will need a different raster font file for each size, which could be annoying although the combined sizes could be smaller than a single OTF or TTF file.

QB64 was designed in a way where SCREEN 0 was to remain more limited than using a graphics screen. That's why it could only employ monospaced fonts and there are niggles about it with _CONTROLCHAR and with code pages and more. QB64PE v3.7 was giving us a promise with _UPRINTSTRING and related functions but sadly this still doesn't give us "everything" that could be seen from the Character Map application with a "loaded" OpenType or TrueType font.


RE: Confusing Chr$ explanation - mnrvovrfc - 07-11-2023

What Phil is going through here represents a crossroads for QB64.

What is QB64? It's an emulation of Microsoft QuickBASIC and QBasic, right? When QBasic was released (as part of MS-DOS v5), the norm were 16-bit single-CPU computers with VGA, I think 1024x768 with many colors (not that much different from today at least with budget laptops). The system requirements were very restricted. Things depended a lot on how MS-DOS limited available memory. M$ were just trying to sell it in the U.S.A. and Canada primarily and therefore they helped created a "standard" character set which became the CP437, and the set that is seen in the QB64 IDE now, in "Tools/ASCII Chart". At that time it wasn't "let's make it easier for Asians to use our programming system!" It was "let's give the hobbyists a quick and dirty tool". Although there were a few markets in Europe and Latin America, I gather, which provided the alternative character sets.

Now with modern web browsers being able to display all sorts of things, which should have been done only with graphics commands on QBasic, confusion results because QB64 has been trying so hard to remain compatible with QuickBASIC and QBasic, but it means it cannot be compatible with the modern web browsers. Then the CP437 doesn't go far enough. There's the push to be more considerate with people having other writing systems. Also the "geeks" for Linux being full of terminal graphics tricks much beyond "neofetch" and that "Matrix" movie thing. Cannot tell them, you need a graphics screen to do that, cannot do it on a text screen. Then programming in QB64 seems to be a bit of an anachronism. Programming in Python for the Linux terminal seems to become more attractive because "everybody" seems to be doing it. It should bother me but I'm happy to have this best of both worlds which is not perfect, which is like an old dog but good to have around.

I discovered a "flappybird" clone for Linux done with Python, entirely in text mode in the terminal. It's terrible. The player has to crush the spacebar to get two points or so in that game LOL.

In another thread there was an observation about "local" constants and how it should be sensible to allow "local" user-defined type (UDT) definitions.

For that and for the CHR$() "confusion", have to change QB64 so it supports object-oriented programming and Unicode. Or use another programming system that could help that.