FreeBASIC – configurare la console

Esiste ancora tutto un mondo di applicazioni per console (console application), alcune delle quali si permettono anche il lusso di fare a meno del mouse.

Per esempio ne (the nice editor) è un noto editor di testo per console sviluppato da Sebastiano Vigna dell’Università degli Studi di Milano.

Potrà sembrare una cosa da inguaribili nostalgici – e forse lo è – ma in questo blog trovano posto anche questo tipo di applicazioni.

Seguendo il metodo imparare facendo (learning by doing), approfondiremo passo passo le procedure per la console messe a disposizione dal compilatore FreeBASIC cercando di realizzare un semplice editor di testo per console che avrà quindi una interfaccia utente basata sul solo testo (text-based user interface). Un editor di testo che magari possa anche interagire con il compilatore FreeBASIC in modo tale che possa essere utilizzato anche come semplice IDE (Integrated Development Environment).

Il nostro piccolo progetto si chiamerà CLUMSY che in inglese suona più o meno come oggetto mal costruito. 😉

CLUMSY è ospitato su GitHub in questo repository.

Configurare la console

Come prima cosa dobbiamo informare il compilatore FreeBASIC che abbiamo intenzione di aprire una finestra grafica in modalità console. Per farlo dobbiamo impostare il valore della modalità grafica (parametro mode della istruzione screen) al valore 0 (zero).

Imposteremo poi il colore del primo piano e dello sfondo con l’istruzione color sfruttando la tavolozza dei colori di default.

Faremo uso dell’istruzione cls per pulire lo schermo e rendere attiva l’impostazione dei colori precedentemente scelta.

L’istruzione cls può essere fatta seguire da un parametro che può assumere i seguenti tre valori:

  • 0 -> pulisce l’intero schermo;
  • 1 -> pulisce l’area grafica se definita con l’istruzione view (se lo schermo è stato settato in modalità console questa istruzione non ha alcun effetto);
  • 2 -> pulisce l’area di stampa se definita con l’istruzione view print.

Se si utilizza l’istruzione cls senza alcun parametro, nel caso sia stata definita un’area grafica o di stampa, questa verra pulita, altrimenti viene pulito l’intero schermo.

Utilizzeremo poi l’istruzione width in combinazione con le istruzioni hiword e loword, per conoscere rispettivamente il numero massimo di righe e di colonne messe a disposizione di default dalla nostra finestra terminale (o prompt dei comandi in ambiente Windows).

Per posizionare il testo sfrutteremo l’istruzione locate.

Infine, per definire l’area di testo su cui andremo a scrivere utilizzaremo l’istruzione view print specificando la riga iniziale e quella finale.

''project: clumsy | pre-alpha version
''description: text editor for console
''author: Luca Evangelisti
''last update: 3th February 2020
''GitHub: https://github.com/lucaevangelisti/clumsy
''license: https://github.com/lucaevangelisti/clumsy/blob/master/LICENSE

dim as uinteger max_rows, max_cols

screen 0 ''console-mode functionality

max_rows = hiword(width) ''max number of rows
max_cols = loword(width) ''max number of columns

color 7, 0 ''text grey, background black
cls 0 ''clears the entire screen

''footer info
locate max_rows, 1
print "clumsy is a silly text editor for console"; _
      " | pre-alpha version" _
      " | ^H for Help";

''sets the printable area of the console screen
view print 1 to (max_rows - 1)

color 0, 7 ''text black, background grey
cls 2 ''clear only the text viewport

''text
print "Hello, world!";

sleep

Nel prossimo articolo vedremo come ottenere informazioni talla tastiera sfruttando la funzione getkey.

FreeBASIC – colori

In questo nuovo articolo andremo alla scoperta di come si può lavorare con i colori in FreeBASIC.

Funzione color

La prima funzione che incontriamo è la funzione color che ci permette di fare tre cose:

  • impostare il colore del primo piano (foreground)
  • impostare il colore dello sfondo (background)
  • ottenere i colori correnti del primo piano e dello sfondo

Impostare i colori del primo piano e dello sfondo

L’impostazione del colore del primo piano e dello sfondo, oltre ad avere diretto effetto sullo schermo grafico, ha effetto anche sulle figure che vengono su questo disegnate, per esempio con le funzioni line o circle, se non si specifica con queste istruzioni l’attributo relativo al loro colore.

Definire un colore con la funzione rgb

La funzione rgb permette di valorizzare distintamente i tre colori primari percepiti dal nostro occhio per sintesi additiva: rosso (red), verde (green) e blu (blue).

Nel mondo dei computer si fa largo uso del modello di colori RGB.

Vediamo un esempio:

''imposta la risoluzione dello schermo e quella grafica
screen 19, 32

''imposta il colore rosso per il primo piano e
''il colore zafferano per lo sfondo
color(rgb(255,0,0), rgb(244,196,48))

''pulisce lo schermo per rendere visibile il
''colore dello sfondo appena impostato
cls

print "Cosa sono i colori?"

sleep

Su Wikipedia è disponibile una lista dei colori molto utile per il programmatore.

Definire un colore con la tavolozza dei colori predefinita

In FreeBASIC è disponibile una tavolozza dei colori predefinita (default pallettes) che raggruppa una serie di colori visualizzabili in base alla modalità grafica scelta.

Per impostare uno di questi colori basterà specificare il relativo valore associato.

screen 12
color(1, 5) ''primo piano blu e sfondo rosa
cls
print "ciao"
sleep

In FreeBASIC è anche possibile cambiare la tavolozza dei colori attraverso l’istruzione palette, ma questa possibilità non verrà esplorata in questo articolo.

Ottenere il colore del primo piano e dello sfondo

La funzione color restituisce un valore ulong (ovvero un valore di tipo long senza però il segno) che contiene l’informazione dei valori del primo piano e dello sfondo correnti:

dim c as ulong
c = color()
print "Colori della console:"
print "primo piano:"; loword(c)
print "sfondo:"; hiword(c)

Ottenere il colore di un pixel

Oltre al colore del primo piano e dello sfondo, potremmo essere interessati a conoscere il colore di uno specifico punto dello schermo (pixel).

Per fare questo possiamo utilizzare la funzione point:

screen 12
color(1, 5) ''primo piano blu e sfondo rosa 
cls
line(10,10)-(40,10), 2 ''disegna una linea verde
locate 4,1: print "colore dello sfondo:"; point(5,5)
locate 5,1: print "colore di un pixel della linea:"; point(20,10)
sleep

Bene! Come introduzione al mondo dei colori in FreeBASIC possiamo fermarci qui.

A presto. 🙂

FreeBASIC – Grafica [2]

Nel precedente articolo abbiamo parlato della risoluzione dello schermo: ovvero di come impostare le dimensioni digitali delle nostre finestre in termini di quanti pixels si possono disegnare in orizzontale (larghezza) e di quanti in verticale (altezza).

Il rapporto tra la larghezza e l’altezza di una finestra grafica rappresenta il cosiddetto rapporto d’aspetto.

In questo nuovo articolo parleremo invece della risoluzione grafica: ovvero della qualità delle immagini che si possono disegnare a video.

Profondità di colore

In FreeBASIC per definire la qualità delle immagini occorre impostare nella istruzione screen il parametro della profondità di colore (color depth): ovvero il numero di bits utilizzati per descrivere il colore di un singolo pixel. L’unità di misura di questo parametro è quindi espressa in bpp (bits per pixel).

Questo parametro ha effetto soltanto per le modalità grafiche dalla 14 alla 21 e può assumere i valori: 8, 16 o 32 bpp.

Più bits vengono utilizzati per un singolo pixel, più la qualità dell’immagine sarà migliore.

Scheda video

Arrivati a questo punto occorre fare una precisazione:

Le caratteristiche tecniche della scheda video del nostro computer limitano le possibilità di scelta della modalità grafica in relazione alla profondità di colore da noi scelta.

Come facciamo quindi a sapere quale modalità grafica (parametro mode) possiamo scegliere con uno specifico valore di profondità di colore (parametro depth)?

L’istruzione screenlist

La risposta alla domanda che ci siamo posti più sopra ce la fornisce l’istruzione screenlist.

Vediamo nel dettaglio i passi da seguire per utilizzare al meglio questa istruzione:

  1. Nella prima chiamata alla funzione screenlist è necessario specificare il valore della profondità di colore desiderata. La funzione restituirà la più bassa risoluzione dello schermo possibile in relazione alla profondità di colore specificata.
  2. Le successive chiamate alla funzione non necessiteranno più di alcun argomento: ciascuna chiamata restituirà le possibili risoluzioni dello schermo in maniera crescente.
  3. La restituzione del valore 0 (zero) starà a significare che non ci sono risoluzioni dello schermo più grandi dell’ultima restituita.

Scriviamo ora un semplice programma per scoprire quali risoluzioni dello schermo sono possibili con la scheda video del nostro computer in base alle tre diverse profondità di colore gestite dal FreeBASIC.

Per realizzare il nostro programma utilizzeremo due strutture di controllo:

  1. un ciclo for-next per selezionare di volta in volta le diverse profondità di colore;
  2. un ciclo do-loop per eseguire le diverse chiamate alla funzione screenlist.
'dimensiona e poi crea un array con i tre valori della
'profondità di colore disponibili in FreeBASIC
dim prof_col (1 to 3) as long
prof_col(1) = 8
prof_col(2) = 16
prof_col(3) = 32

'dimensiona una variabile per ricevere il
'risultato della chiamata alla funzione screenlist
dim risultato as long

'dimensiona una variabile stringa per la
'risoluzione dello schermo
dim risoluzione as string

'doppio ciclo per ottenere tutte le risoluzioni dello schermo
'gestite dalla scheda video del computer in base alle
'diverse profondità di colore
for i as integer = lbound(prof_col) to ubound(prof_col)
  print "Lista risoluzioni dello schermo disponibili"
  print "con la profondita' di colore "; prof_col(i)
  risultato = screenlist(prof_col(i)) 'prima chiamata
    do while risultato <> 0
      print risultato
      risultato = screenlist()
    loop
  print "---"
next i

Ecco il risultato a video:

Che dire? Ciò che abbiamo ottenuto è veramente poco soddisfacente: una serie di numeri che sembrano non dirci nulla. Perché?

La risposta ci permetterà di conoscere una tecnica che potrà tornarci utile in molte occasioni.

Lavorare con le codifiche binarie

Il risultato della funzione screenlist è codificato in un valore a 32 bit: dove i 16 bits più alti (ovvero quelli a sinistra) rappresentano la larghezza della finestra, mentre i 16 bits più bassi (ovvero quelli a destra) rappresentano l’altezza della finestra.

Il compilatore FreeBASIC ci mette a disposizione due utili funzioni per estrarre queste informazioni: l’istruzione hiword e l’istruzione loword.

Modifichiamo quindi il ciclo do-loop del nostro programma in questo modo:

do while risultato <> 0
      risoluzione = hiword(risultato) & "x" & loword(risultato)
      print risoluzione
      risultato = screenlist()
loop

Vediamo ora il nuovo risultato a video:

Molto meglio. No? 🙂

Ora non ci resta che fare un confronto con le modalità grafiche disponibili in FreeBASIC per verificare quali sono disponibili.

Modifichiamo quindi il ciclo do-loop inserendo una istruzione select case:

do while risultato <> 0
  risoluzione = hiword(risultato) & "x" & loword(risultato)
  select case risoluzione
    case "320x240"
      print hiword(risultato); "x"; loword(risultato); " -> "; "14"
    case "400x300"
      print hiword(risultato); "x"; loword(risultato); " -> "; "15"
    case "512x384"
      print hiword(risultato); "x"; loword(risultato); " -> "; "16"
    case "640x400"
      print hiword(risultato); "x"; loword(risultato); " -> "; "17"
    case "640x480"
      print hiword(risultato); "x"; loword(risultato); " -> "; "18"
    case "800x600"
      print hiword(risultato); "x"; loword(risultato); " -> "; "19"
    case "1024x768"
      print hiword(risultato); "x"; loword(risultato); " -> "; "20"
    case "1280x1024"
      print hiword(risultato); "x"; loword(risultato); " -> "; "21"
    case else
      print hiword(risultato); "x"; loword(risultato)
  end select
  risultato = screenlist()
loop

Ecco il risultato:

Ora possiamo dirci soddisfatti! 🙂

Abbiamo finalmente la lista delle risoluzioni dello schermo gestibili dalla scheda video del nostro computer con evidenziate quelle che hanno una corrispondenza con le modalità grafiche gestite dal compilatore FreeBASIC.

Nel prossimo articolo continueremo ad approfondire l’istruzione screen testando un altro dei suoi attributi: quello che gestisce le pagine video.