Windowing in my eyes is quite simple. You draw a square on the screen. Then you pass in content or call a program that uses that window as it's boundaries. This means that the windowing system needs to set the boundaries but the content needs to manage itself.
I wrote a quick test to draw the square and I can already see the shape of the code that will be required to draw the content. I don't think it will be difficult as I already have a base to work with in the form of EVA.
The core issue is that because BASIC is single threaded and you don't have a way of doing background jobs, this means that I need to do a form of cooperative multitasking.
If application A is running in a window and I want to launch application B, then A needs to give control back to the main program so that I can launch B. With Pick A would run and finish first then give control back to the main program, then I can launch B.
I would need to write A in such a way that it returns control back, one option is to write a state machine so that processing can be picked up every 5ms. A would do some work, return and then get called again if it didn't finish.
The windowing system I'm envisioning is almost an operating system on top of Pick which is a goal of mine at some point. Though I could build the windowing system and ignore the multitasking portion for now.
Just for clarity, the opposite of cooperative multitasking is preemptive multitasking which is what most operating systems use. They full save the application state whenever they want and switch to another application without asking. They then load everything back and the program runs as if it never stopped in the first place. I don't think this is possible in Pick. It looks like various version of DOS were able to build windowing systems with cooperative multitasking and if it was good enough for them, I'm sure it's good enough for me.
To have a real windowing system, I think I need to handle mouse input. Luckily there is a way to get mouse data in a terminal. You can trigger an ansi escape code that will then capture the mouse movement and button presses as escape codes that you can then process.
I wrote a quick test program in BASIC and it works beautifully. Integrating this into my test drawing program is next.
*
EQU ESCAPE.CODE TO CHAR(27)
*
START.MOUSE = ESCAPE.CODE : '[?1003h'
STOP.MOUSE = ESCAPE.CODE : '[?1003l'
*
PRINT START.MOUSE
*
X = ''
*
LOOP
X = KEYIN()
UNTIL X = 'Q' DO
PRINT X : ' - ' : SEQ(X)
REPEAT
*
PRINT STOP.MOUSE
*
* END OF PROGRAM
*
END
*
While this idea kicks around my head, I think adding graphics might be a fun side adventure. This would mean that my windowing system isn't going to work with all terminals but at least with kitty and other terminals that support the kitty graphics protocol, I can show images directly in the terminal. This is also done through escape codes but these are specifically made for kitty. There is a push to make these standard so it may be that they get adopted more widely in the future.
#!/bin/bash
transmit_png() {
data=$(base64 "$1")
data="${data//[[:space:]]}"
builtin local pos=0
builtin local chunk_size=4096
while [ $pos -lt ${#data} ]; do
builtin printf "\e_G"
[ $pos = "0" ] && printf "a=T,f=100,"
builtin local chunk="${data:$pos:$chunk_size}"
pos=$(($pos+$chunk_size))
[ $pos -lt ${#data} ] && builtin printf "m=1"
[ ${#chunk} -gt 0 ] && builtin printf ";%s" "${chunk}"
builtin printf "\e\\"
done
}
transmit_png "$1"
Save this as send-png and then use it to show an image in the kitty terminal.
The goal is to create a TUI framework that I can build applications in. I think a good test would be to implement the 7 GUI test programs though I haven't done them before so I'm not too sure if it'll be relevant.
It will be a good goal though as I think if I could build even a few of those programs, I should be able to build the things I want.
The great thing is because I'm writing this for myself, it doesn't have to be that great. Just good enough to use.