Sinclair QL má multitasking a okna.
Jejich používání, notabene z Basicu, ale není úplně nejpřímočařejší.
Zvlášť po příchodu myší ovládaného okenního prostředí, kde by měl uživatel okno rád nejen jako pevně definovanou oblast obrazovky, ale jako oblast, kterou může nejlépe myší posouvat či měnit její velikost.
Systém toto ovšem neřeší, ten jen poskytne okenního manažera a očekává, že záležitosti s okny si bude řešit aplikace sama.
Pokud tedy okno v Basicu nechcete mít klasicky nepohyblivé a neměnné, musíte se o jeho přesuny a změny velikosti sami starat.
Změna nastavení okna z Basicu povelem WINDOW sice počítači řekne, že bylo okno předefinováno, ale pokud to nedoprovodíte parametry pro vykreslení rámečku okna (border, dostupné v Minerva a Thor ROM), na obrazovce se to nijak graficky neprojeví, vykreslené okno zůstane tam, kde je, jeho obsah se nepřesouvá.
Do nové oblasti se sice vypisuje či vykresluje nový výstup, ale ta se automaticky předem nesmaže, pokud to neuděláte příkazem CLS.
To neplatí pro aplikace pro Pointer Environment, které se o změnu polohy a velikosti okna mohou starat samy, na jejich zavolání se pak systém, respektive manažer oken, postará o smazání staré pozice a aplikace vykreslí obsah okna na nové místo nebo v nové velikosti.
Okenní prostředí Pointer Environment počítá s programováním v assembleru, případně lze jeho služby využívat programech psaných v C, z Basicu to ale jednoduché nebylo.
Tony Tebby, autor, tedy s přišel s QPTR, knihovnou, která rozšiřuje Basic o možnost práce s okenním manažerem.
Protože je ale Tony Tebby tak trochu mimozemšťan a věci si dělá možná lepším, ale rozhodně neobvyklejším způsobem, než jak to mají jiné systémy, není to úplně jednoduše použitelné či snadno pochopitelné.
Trochu se to snažil napravit Wolfgang Lenerz svým jedenáctidílným seriálem v časopise QL Today.
(Aby se programy používající služby okenního manažera daly kompilovat kompilátorem Turbo, existuje knihovna TurboPTR, která QPTR, které je naopak kompatibilní s kompilátorem QLiberator, pro tento účel víceméně nahrazuje.)
Pro „normální lidi“ vzniklo ještě jedno rozšíření, EasyPTR, které má pomoci využívat QPTR méně mimozemským způsobem, například tím, že poskytuje WYSIWYG editor.
Pro to, abyste si pak v Basicu vytvořili okno, které se bude umět přesouvat a zavírat, pak postačí následující krátký prográmek (je pro snazší pochopení komentovaný).
(Adjektivum “krátký” může v tomto kontextu působit ironicky.)
Na obrázku vidíte tři okna vytvořená tímto prográmkem (další dvě okna patří editoru QD, jedno Basicu a jedno souborové utilitě Files).
Jistě si všimnete, že je v programu definována i jedna nepoužitá ikona.
8000 open#0,"con_": SP_JOBPAL -1,1 : initialise
8010 DR_PPOS#0,main_defn,-1,-1,m_lflg%
8020 Repeat Loop
8030   RD_PTR main_defn,it%,swnum%,event%,xrel%,yrel%,m_lflg%,0
8040   IF it%=1 : DR_UNST main_defn : CLOSE #mvch : STOP
8050   IF it%=0 : CH_WIN main_defn
8060 END REPeat loop
8070 :
8080 DEFine PROCedure                 Initialise
8090 :
8100 : REMark  Define a general-purpose moveable channel &
8110   REMark  a channel to cover the menu information window
8120 : REMark  and some useful colours.
8130 :
8140   mvch%=FOPEN(con_)    : REMark spare channel for embellishing
8150 :
8160   REMark Window Colours from chosen system palette
8170   scrollarrow=547 : between=560 : infoink=518
8180   stdink=514 : selectink=542 : selectstrip=541
8190   wndopapr=513 : wndobrdr=1024 : wndobg=533
8200   subbrdr=1219 : bgndppr=535
8210 :
8220 : REMark  Possible item type codes: retx is added to return
8230 : REMark  when hit, with (retr) or without (retn) a re-draw
8240 :
8250   text=0:sprite=2:blob=4:pattern=6
8260   retr=256:retn=-256
8270   hit$=CHR$(1):do$=CHR$(2):cancel$=CHR$(3):null$=""
8280   help$=CHR$(4):move$=CHR$(5):size$=CHR$(6)
8290 :
8300   REMark l(oose) x s(ize) l(oose) y s(ize)
8310   lxs=6*5:lys=12 : REMark size of 6 char loose items
8320   MainXsize=180 : MainYsize=84 : REMark calc values from application
8330   REMark bordsz=36
8340 :
8350 : REMark  The initialisation of the menu itself starts
8360 : REMark  here: this corresponds to a call to WM.SETUP
8370 :
8380 : REMark  The standard window attributes
8390 :
8400   RESTORE 5390
8410   DIM std_wattr%(3)
8420   RD_WATT std_wattr%
8430   DATA 0,1,scrollarrow,wndopapr
8440 :
8450 : REMark  Application sub window attributes
8460   DIM app_wattr%(3)
8470   RD_WATT app_wattr%
8480   DATA 0,1,subbrdr,bgndppr
8490 :
8500 : REMark  The standard item attributes
8510 :
8520   DIM std_iattr(3,3)
8530   RD_IATT std_iattr
8540     DATA 1,stdink
8550     DATA wndopapr,wndobrdr,0,0
8560     DATA wndopapr,stdink,0,0
8570     DATA wndobrdr,stdink,0,0
8580 :
8590   DIM alt_iattr(3,3)
8600   RD_IATT alt_iattr
8610      DATA 1,subbrdr
8620      DATA wndopapr,wndobg,0,0
8630      DATA bgndppr,stdink,0,0          : REMark paper & ink colours
8640      DATA selectstrip,selectink,0,0  : REMark selected paper & ink
8650 :
8660 : REMark  The data for the pointers
8670 :
8680   main_sprite=RD_SPRT
8690     DATA 6,5,4
8700     DATA '     www     '
8710     DATA '     waw     '
8720     DATA '     waw     '
8730     DATA '     waw     '
8740     DATA 'wwwwwa awwwww'
8750     DATA 'waaaa   aaaaw'
8760     DATA 'wwwwwa awwwww'
8770     DATA '     waw     '
8780     DATA '     waw     '
8790     DATA '     waw     '
8800     DATA '     www     ',''
8810 :
8820   move_sprite=RD_SPRT
8830     DATA 5,4,4
8840     DATA 'aaaaaaaaaa    '
8850     DATA 'awwwwwwwwa    '
8860     DATA 'awwrrrrwwa    '
8870     DATA 'awwrrrrwwaaaaa'
8880     DATA 'awwrrwwwwwwwwa'
8890     DATA 'awwwwwwwwrrwwa'
8900     DATA 'aaaaawwrrrrwwa'
8910     DATA '    awwrrrrwwa'
8920     DATA '    awwwwwwwwa'
8930     DATA '    aaaaaaaaaa',''
8940 :
8950   xout=RD_SPRT
8960     DATA 0,0,4
8970     DATA   "aaaaaaaaaaaaaa"
8980     DATA   "a            a"
8990     DATA   "a  aa    aa  a"
9000     DATA   "a  aa aa aa  a"
9010     DATA   "a    a  a    a"
9020     DATA   "a    a  a    a"
9030     DATA   "a  aa aa aa  a"
9040     DATA   "a  aa    aa  a"
9050     DATA   "a            a"
9060     DATA   "aaaaaaaaaaaaaa",""
9070 :
9080   InfoIt=RD_SPRT
9090     DATA 0,0,4
9100     DATA   "   aaaaaa   "
9110     DATA   "   aawwaa   "
9120     DATA   "    awwa    "
9130     DATA   "    awwa    "
9140     DATA   "    awwa    "
9150     DATA   "    awwa    "
9160     DATA   "    awwa    "
9170     DATA   "    awwa    "
9180     DATA   "    awwa    "
9190     DATA   "    awwa    "
9200     DATA   "   aawwaa   "
9210     DATA   "   aaaaaa   ",""
9220 :
9230 : REMark  Some loose objects
9240 :
9250   m_nlit=2:DIM m_lflg%(m_nlit-1)
9260   main_lot=RD_LOTA(alt_iattr)
9270     DATA m_nlit
9280     DATA 16,lys,4+(lxs+4)*0,4,0,0,move$,sprite+retr,move_sprite
9290     DATA lxs-12,lys,MainXsize-28,4,0,0,cancel$,sprite+retr,xout
9300 :
9310 :
9320 : REMark  The window definition itself
9330 :
9340   main_defn=RD_WDEF
9350     DATA 2,1,wndobrdr,wndopapr
9360     DATA MainXsize,MainYsize,0,0 : REMark maximum window size minus shadow
9370     DATA main_sprite,main_lot,main_iwt,main_awt
9380 :
9390 END DEFine Initialise
9400 :
9410 DEFine FuNction RD_SPRT
9420   LOCal tmp_patt$(64,64)
9430   LOCal xs,ys, xo,yo, md, l
9440   xs=0:ys=-1:READ xo,yo,md
9450   REPeat l
9460     READ x$:IF x$='' THEN EXIT l
9470     ys=ys+1:tmp_patt$(ys)=x$&FILL$(' ',32)
9480     IF LEN(x$)>xs THEN xs=LEN(x$)
9490   END REPeat l
9500   l=ALCHP(SPRSP(xs,ys+1))
9510   SPSET l,xo,yo,md,tmp_patt$(0 TO ys,1 TO xs)
9520   RETurn l
9530 END DEFine RD_SPRT
9540 :
9550 DEFine FuNction RD_WDEF
9560   LOCal lattr%(3)
9570   RD_WATT lattr%
9580   RETurn RD_WDEFA (lattr%)
9590 END DEFine RD_WDEF
9600 DEFine FuNction RD_WDEFA (lattr%)
9610   LOCal ldef%(3), lspr, lloose, linfo, lappl
9620   READ ldef%(0), ldef%(1), ldef%(2), ldef%(3)
9630   READ lspr, lloose, linf, lappl
9640   RETurn MK_WDEF (ldef%, lattr%, lspr, lloose, linf, lappl)
9650 END DEFine RD_WDEFA
9660 :
9670 DEFine FuNction RD_LOTA (lattr)
9680   LOCal nitem, cownt(3)
9690   READ  nitem: IF nitem: nitem=nitem-1: RETurn RD_LOTN
9700   RETurn 0
9710 END DEFine RD_LOTA
9720 DEFine FuNction RD_LOTN
9730   LOCal item, ltyp, a$, lsk$
9740   LOCal ldef%(nitem,6), lptr(3,nitem), lstr$(nitem,85)
9750   lsk$=''
9760   FOR item = 0 TO nitem
9770     READ ldef%(item,0), ldef%(item,1), ldef%(item,2), ldef%(item,3)
9780     READ ldef%(item,4), ldef%(item,5)
9790     READ a$: lsk$=lsk$ & a$
9800     READ ltyp
9810     ldef%(item,6)=ltyp: ltyp=(ltyp MOD 256)/2
9820     IF ltyp
9830       READ lptr(ltyp,cownt(ltyp))
9840     ELSE
9850       READ lstr$(cownt(0))
9860     END IF
9870     cownt(ltyp)=cownt(ltyp)+1
9880   END FOR item
9890   RETurn MK_LIL (lattr, ldef%(TO, 0 TO 1), ldef%(TO, 2 TO 3), ldef%(TO, 4 TO 5), lsk$, ldef%(TO, 6), lstr$, lptr(1), lptr(2), lptr(3))
9900 END DEFine RD_LOTN
9910 :
9920 DEFine PROCedure RD_IATT (lattr)
9930   LOCal i
9940   READ lattr(0,0), lattr(0,1)
9950   FOR i=1 TO 3: READ lattr(i,0), lattr(i,1), lattr(i,2), lattr(i,3)
9960 END DEFine RD_IATT
9970 :
9980 DEFine PROCedure RD_WATT (lattr%)
9990   READ lattr%(0), lattr%(1), lattr%(2), lattr%(3)
10000 END DEFine RD_WATT
