               CORSO DI PROGRAMMAZIONE 'C'
                       SESTA PARTE
------------------------------------------------------------

  La  puntata  scorsa  abbiamo introdotto un certo numero di
argomenti nuovi, volti alla scrittura di un primo  programma
dimostrativo  veramente  'funzionante'.  E' stato necessario
fare questo vero e proprio 'salto  di  qualita'  perche'  un
programma  Amiga,  che  giri  sotto  Intuition,  ha un certo
insieme di componenti  che  non  possono  essere  disgiunte.
Spero  che  abbiate  assimilato  i concetti base esposti nel
testo  della   puntata   precedente   ed   abbiate  studiato
attentamente  il  listato  del  programma  Micro  Paint  che
accompagnava  l'articolo.    Partendo  da  dove  ci  eravamo
lasciati  continueremo  la  spiegazione  ad  un  livello  di
dettaglio un poco piu' appprofondito. Al termine  di  questa
puntata  dovreste  essere  tranquillamente   in   grado   di
comprendere  tutti   i   dettagli   di  implementazione  del
programma  e  sperimentare  sulla  pelle del vostro computer
modifiche, ampliamenti e pateracchi.


I 'MODI' DI DISEGNO E SetDrMd().
--------------------------------

  Se  avete  provato  a  far  girare Micro Paint, oppure, se
avete  mai  provato ad utilizzare un programma di grafica su
Amiga,  avrete   certo  apprezzato  il  meccanismo  chiamato
'Rubber  Band'  (nastro  di  gomma).   Viene  cosi' chiamato
l'effetto 'elastico' che si ha quando l'utente seleziona  un
comando  come riga, cerchio, rettangolo e, piazzato il primo
punto fisso della figura geometrica, muove il cursore  sullo
schermo tirandosi dietro una versione 'gommosa' della figura
scelta.  L'oggetto si muove liberamente sullo schermo, senza
danneggiare  il  disegno sottostante, fino a quando l'utente
fissa il secondo punto significativo della figura.  A questo
punto l'immagine viene tracciata alle coordinate fissate  in
maniera  definitiva.   Alcuni  si  saranno  chiesti  come e'
possibile disegnare  sullo  schermo,  spostarsi  e  lasciare
inalterato il disegno sottostante con quella velocita'.  Una
soluzione possibile e' ovviamente quella di tenere una copia
di  riserva  della  pagina  su cui si disegna e continuare a
ripristinare il disegno prima  di  tracciare  ogni  riga  in
posizioni  diverse.   Naturalmente  esiste  una tecnica meno
ovvia,  ma   molto  piu'  efficiente.   Quando  scriviamo  o
disegnamo  su  una  pagina  grafica, andiamo a modificare lo
stato dei bit di  memoria  che  compongono  l'immagine.   Se
tracciamo  una  linea  'solida',  ponendo  ad  1  i  bit sul
percorso  della   linea,   non   c'e'  piu'  alcun  modo  di
ricostruire  lo  stato iniziale dei bit. Se, invece, andiamo
semplicemente ad invertire lo stato  dei  bit  sul  percorso
della  linea,  da 0 a 1 e da 1 a 0, possiamo, tracciando una
seconda volta la linea esattamente sugli stessi bit,  sempre
e soltanto invertendone le stato, riportarli alle condizioni
iniziali.   Chi  ha  dimestichezza  con l'aritmetica binaria
avra'  riconosciuto   un'operazione  di  COMPLEMENTO,  detto
anche,  nella  terminologia  della  logica  booleana  un OR-
ESCLUSIVO (XOR).

--Esempio: sia il seguente un pezzo di pagina grafica.   Per
semplicita'  rappresentiamo  solo  un  bit-plane. I bit sono
tutti  inizialmente   a   0   (sfondo),  tranne  quelli  che
rappresentano un rettangolo, disegnato precedentemente. 



    0000000000000000000000000000000000000000000000000
    0000000000000011111111111111111000000000000000000
    0000000000000010000000000000001000000000000000000
    0000000000000010000000000000001000000000000000000
    0000000000000010000000000000001000000000000000000
    0000000000000010000000000000001000000000000000000
    0000000000000011111111111111111000000000000000000
    0000000000000000000000000000000000000000000000000

Andando a tracciare una linea invertendo i bit otteniamo:

    0000111000000000000000000000000000000000000000000
    0000000111000011111111111111111000000000000000000
    0000000000111010000000000000001000000000000000000
    0000000000000101000000000000001000000000000000000
    0000000000000010111000000000001000000000000000000
    0000000000000010000111000000001000000000000000000
    0000000000000011111111000111111000000000000000000
    0000000000000000000000000111000000000000000000000



  Questa  linea  sara'  visibile sullo schermo, anche se non
con i colori  corretti  che  la  linea  definitiva  dovrebbe
avere.  Notate pero' che, tracciando una nuova linea, sempre
in  modo  'inverti  i bit' alla stessa posizione, annulliamo
completamente l'effetto della linea precedente.  In  pratica
ricostruiamo  l'immagine  originale,  velocemente e senza la
necessita' di tenerne una copia. Naturalmente,  nel  momento
in  cui  avremo  deciso la posizione definitiva della linea,
cancelleremo l'ultima linea temporanea e tracceremo la linea
'vera' con una strisciata  di  1  attraverso  il  bit-plane,
cancellando per sempre il disegno sottostante.

  Ovviamente  non  e'  necessario scendere a questi dettagli
nello scrivere un programma. Il sistema di Amiga, attraverso
l'uso del Blitter, puo' fare tutto questo  per  noi.  Esiste
una  chiamata  alla  Graphics.library,  denominata SetDrMd()
(che sta per Set Draw Mode,  imposta  il  'modo'  usato  per
disegnare),  che  ci  permette  di decidere, con un semplice
comando, come saranno modificati i bit della pagina  grafica
quando   chiameremo    una   qualsiasi   funzione   grafica.


  La sintassi della chiamata a SetDrMd e'

 SetDrMd (puntatore_a_struttura_RastPort, modo_desiderato);

  Se  andate  ad  esaminare  una  funzione  come linea() nel
MicroPaint, vedrete come questa funzione e'  utilizzata  per
creare  l'effetto  'elastico'  fino  a  quando  l'utente non
rilascia il pulsante sinistro del mouse.

  Quando  il pulsante viene premuto, fissando cosi' il primo
punto  della   linea,   le   coordinate  del  punto  vengono
memorizzate e il modo grafico viene impostato con:

                 SetDrMd (RP,COMPLEMENT);

che sceglie il modo a 'inversione di bit'. Di qui in avanti,
ogni volta che l'utente muove il mouse  tenendo  premuto  il
pulsante  (si  entra in linea() con un comando MUOVI), viene
dapprima annullata la linea alla posizione  precedente,  poi
viene  tracciata  la  linea  nella  nuova  posizione. Questa
tecnica ripristina ad ogni passo lo  sfondo  che  era  stato
sovrascritto  e  crea  l'effetto  'elastico'  che  vedete in
schermo. Quando l'utente rilascia il pulsante (si  entra  in
linea()  con  il comando TERMINA), viene cancellata l'ultima
linea ed il modo grafico viene modificato con la chiamata:

                    SetDrMd (RP,JAM1);

che  ripristina   il   modo   standard,   non  cancellabile,
utilizzato  per   tracciare   la   linea   alle   coordinate
definitive. Il modo JAM1 'martella' il  colore  della  penna
primaria  APen nello sfondo. I modi grafici disponibili sono
definiti in <graphics/rastport.h>. Accanto  a  COMPLEMENT  e
JAM1,  che  sono quelli di uso piu' frequente, segnalo JAM2,
che, oltre a disegnare con la APen,  riempie  il  resto  del
rettangolo  'danneggiato' dal comando con il colore definito
dalla  penna  di  sfondo  BPen.  Questo  modo,  insieme  con
INVERSEVID,  serve  ad  esempio  per  scrivere in 'negativo'
utilizzando la gia' nota funzione  Text().  In  alternativa,
una  combinazione  di  modi  grafici puo' essere inserita in
qualsiasi definizione di una struttura IntuiText,  come  nel
caso  delle  voci  dei  menu. I due modi vanno combinati con
l'istruzione OR booleano, come in:
             SetDrMd (RP, JAM2 | INVERSEVID);
  Ricordo che i colori delle due penne vengono  settati  con
le chiamate alle funzioni corrispondenti:

SetAPen (RastPort, numero_del_colore);
SetBPen (RastPort, numero_del_colore);

  Potete vedere, esaminando la sorgente del MicroPaint, come
la  stessa   identica   tecnica  sia  stata  utilizzata  per
realizzare  tutti  i comandi grafici implementati, tranne il
disegno a mano libera per il quale non avrebbe avuto  senso.


FUNZIONI GRAFICHE EXTRA.
------------------------

  Nel MicroPaint ho introdotto un piccolo numero di funzioni
grafiche  che  non  avevamo ancora utilizzato. Per ognuna di
esse diamo una breve descrizione.

Funzione:
             Draw (puntatore_a_RastPort,x,y);

NB: D'ora in avanti abbreviero' puntatore_a_RastPort con RP.
In C questo significa sempre: struct RastPort *RP;

  Traccia  una   linea,   con   colore   e   modo    grafico
selezionato,dalla posizione corrente della penna al punto di
coordinate x,y. Pertanto, per tracciare una  linea  tra  due
arbitrari punti P1 (x1,y1) e P2 (x2,y2) scriveremo:

Move (RP,x1,y1);    /* porta la penna in P1 */
Draw (RP,x2,y2);    /* traccia una linea fino a P2 */

Funzione:
                RectFill (RP,x1,y1,x2,y2);

  Traccia un rettangolo pieno, nel  colore  e  modo  grafico
correnti,  tra  i  punti  P1  (x1,y1) e P2 (x2,y2). P1 e' il
vertice superiore sinistro del rettangolo, P2 e' il  vertice
inferiore  destro.  Se provate ad invertire l'ordine dei due
punti il Blitter si mette a blittare a casaccio  in  memoria
e,  da  quel  momento,  avete in media un paio di secondi di
tempo prima di assistere ad uno dei crash  di  sistema  piu'
rovinosi  della  storia. Per questa ragione si e' introdotta
nela funzione  rettangolo()  del  MicroPaint,  una  semplice
limitazione sulle coordinate di P2, che deve sempre trovarsi
sotto P1 ed alla sua destra.

Funzione:
               DrawEllipse (RP,x,y,rx,ry);

  Traccia  un'ellisse  vuota  con colore e modo selezionati,
avente per centro il punto  P  di  coordinate  x,y  e  raggi
orizzontale  e  verticale  rx,ry.  Questa  funzione  e',  se
confrontata con il resto  della  graphics  library,  di  una
lentezza  sconcertante...  La  ragione  e' che essa serve di
base per altre funzioni del sistema.  Esegue  una  marea  di
calcoli preparatori necessari per la realizzazione di queste
funzioni, consentendo di risparmiare codice e quindi memoria
a  scapito della velocita'. Gli stessi autori del sistema di
Amiga  consigliano,   per  applicazioni  piu'  esigenti,  di
scriversi  una  routine  ad  hoc.   Questa   funzione   puo'
naturalmente essere utilizzata per tracciare dei cerchi.  In
<graphics/gfxmacros.h>  e'  comunque  definita  la  seguente
macro:

                  DrawCircle (RP,x,y,r)

  Essa  consente   di   disegnare  un  cerchio  passando  le
coordinate  del centro x,y ed il raggio r. In realta' questa
chiamata viene sostituita da una chiamata a DrawEllipse,  in
cui  r viene utilizzato come raggio orizzontale e verticale.
Ecco infatti la definizione della macro nel file gfxmacros.h

 #define DrawCircle(rp,cx,cy,r) DrawEllipse(rp,cx,cy,r,r);

Funzione:
                   WritePixel (RP,x,y);

  Questa funzione semplicemente scrive un punto nel colore e
modo  selezionato  alle  coordinate  x,y specificate...tutto
qui! Potrebbe interessarvi sapere che  esiste  una  funzione
complementare:
               colore = ReadPixel (RP,x,y);

che  invece  ritorna  il  numero  del  colore del punto alle
coordinate x,y. Sembra una funzione 'buffa',  ma  si  rivela
spesso estremamente utile.
NUOVI EVENTI SOTTO INTUITION
----------------------------

  Nella  puntata  scorsa   abbiamo   introdotto   abbastanza
dettagliatamente  il  protocollo  di  attesa,  decodifica  e
gestione  degli  eventi  sotto  intuition.   Abbiamo   visto
specificatamente  un'applicazione  di  questa  tecnica  alla
gestione dei menu a discesa.

  Prima di esaminare tutti gli altri eventi  utilizzati  nel
nostro  MicroPaint,  vorrei  che prestaste ancora un poco di
attenzione  alle   istruzioni  necessarie  per  ottenere  la
trasmissione di un evento.
  Alcuni  eventi,  come MOUSEBUTTONS, che rileva pressione e
il  rilascio   del   tasto   sinistro   del   mouse,  devono
semplicemente  essere specificati nel campo IDCMPFlags della
struttura NewWindow. Altri eventi richiedono invece  che  la
finestra  abbia delle caratteristiche particolari, che vanno
specificate nel campo Flags della struttura  NewWindow.   Ad
esempio,  non  ha  senso   chiedere   di   ricevere   eventi
CLOSEWINDOW (chiusura della finestra) se la finestra non  ha
il  flag  WINDOWCLOSE  ('voglio  il  gadget  di  chiusura').
  Ricordiamo quindi che, se un evento ha a che fare con  una
ben  determinata  caratteristica della finestra, la suddetta
caratteristica e l'evento corrispondente  vanno  specificati
entrambi, rispettivamente nei campi Flags e IDCMPFlags nella
struttura  di  tipo  NewWindow   usata   per   definire   le
caratteristiche della finestra. Questa osservazione  non  e'
del  tutto  banale.  Per alcuni eventi la corrispondenza tra
flag ed evento si presta a generare un  po'  di  confusione.
Ad  esempio non si comprende perche', per ricevere eventi di
tipo MOUSEMOVE, che indicano  un  movimento  del  mouse,  si
debba  anche  settare  il  flag  REPORTMOUSE nel campo Flags
della struttura NewWindow. E' inoltre possibile e  frequente
confondersi  tra  un  flag ed il corrispondente evento, come
nel caso delle coppie:

                 flag        evento
               ---------------------------
                 WINOWSIZING NEWSIZE
                 WINDOWCLOSE CLOSEWINDOW

  Basta  ricordare  che il Flag in genere inizia con WINDOW,
mentre l'evento inizia con il nome dell'azione.
  Detto questo, passiamo in rassegna gli  eventi  utilizzati
nel MicroPaint ed alcuni extra che possono esservi utili:

- CLOSEWINDOW

  Qualcuno  a  caso  ha clickato il gadget di chiusura della
finestra. Quando questo evento arriva,  e'  ora  di  fare  i
bagagli  e  chiudere  bottega.  Intuition  NON   chiude   la
finestra. Questo ci consente, prima  di  smammare,  di  fare
pulizia, mostrare un messaggio pubblicitario oppure gridare
'NO..NO...  non voglio morire!!   Finito  lo  show  DOBBIAMO
chiudere  la  finestra  esplicitamente,  con  CloseWindow().
Questo evento puo' essere ricevuto solo se la finestra ha il
gadget di chiusura (Flag WINDOWCLOSE).

- MOUSEBUTTONS

  Questo evento rileva e segnala  che  l'utente  ha  premuto
oppure  rilasciato un pulsante del mouse. Normalmente questo
si riferisce al pulsante  SINISTRO,  dato  che  il  pulsante
destro  serve  ad  Intuition per mostrare i menu a discesa e
leggere la nostra selezione. Nel caso in  cui,  per  qualche
strano motivo, si volesse ricevere anche gli eventi relativi
al  pulsante  destro  del mouse, si deve specificare il flag
RMBTRAP (right-mouse-button-trap). Questo flag va in  struct
NewWindow.Flags,  NON   IDCMPFlags,   in   quanto   e'   una
'preferenza',  e  non  direttamente  un  evento.  Se   state
leggendo anche il pulsante destro  del  mouse  l'utente  non
sara'  piu' direttamente in grado di selezionare i menu. Per
sapere esattamente cosa  e'  successo  dovete  esaminare  il
campo Code del messaggio ricevuto. E' possibile leggervi:

  SELECTUP       Tasto sinistro rilasciato
  SELECTDOWN     Tasto sinistro abbassato
  MENUUP         Tasto destro rilasciato
  MENUDOWN       Tasto destro abbassato

- MOUSEMOVE

  Questo  evento  segnala  che  e' avvenuto un movimento del
mouse. Per ricevere i movimenti  del  mouse  si  deve  ANCHE
porre  il  flag  REPORTMOUSE nel campo Flags della struttura
NewWindow. Si richiede un poco di attenzione nella  gestione
di  questo  evento.  Infatti, se l'utente e' un poco nervoso
con  il   mouse,  Intuition  puo'  tranquillamente  spedirci
centinaia  di  eventi  di  questo  genere nello spazio di un
battito di  ciglia.  Se  non  si  rispetta  STRETTAMENTE  il
protocollo  di gestione e risposta ai messaggi presentato, o
si impiega troppo tempo nell'esecuzione di  un  comando  (ad
esempio  perche'  si  sta ridisegnando una schermata) questi
messaggi  possono  letteralmente  intasare  la  porta  della
nostra   finestra    (..il   gioco   di   parole   non   era
intenzionale!).  Se non si riesce a  convincere  l'utente  a
smetterla,  puo'  accadere  che il sistema si 'sieda' per il
sovraccarico, o che al limite vada in crash per mancanza  di
memoria  (Intuition  non sa piu' dove infilarci i messaggi a
cui continuiamo a non rispondere). Morale: state  attenti  a
quello  che  fate. Se smettete di controllare la porta della
finestra (e dagli!) per fare qualcosa che pensate vi  occupi
piu'  di  poche manciate di istruzioni, e' meglio segnalarlo
ad  Intuition   'spegnendo'   l'IDCMPFlag   MOUSEMOVE,   con
l'istruzione  ModifyIDCMP(),  come spiegato poco piu' sotto.
La cosa interessante di questo evento e' la possibilita'  di
leggere  le  coordinate del mouse, continuamente aggiornate,
nei campi MouseX, MouseY del messaggio.  Questo  meccanismo,
insieme  con  la lettura dello stato dei pulsanti del mouse,
e' alla base di tutto il sistema di disegno del MicroPaint e
della  totalita'  dei  programmi  di  grafica  esistenti  ed
operanti sotto Intuition.

- DELTAMOVE

  Una  possibilita' extra e' quella di ricevere, anziche' le
coordinate  assolute   della   posizione   del   mouse,   lo
spostamento nelle  direzioni  x,y  relativo  alla  posizione
dell'ultimo  messaggio  ricevuto.  L'evento   DELTAMOVE   fa
esattamente questo. Valgono tutte le  considerazioni  e  gli
avvertimenti fatti per l'evento MOUSEMOVE.

- MENUPICK

  Di questo evento abbiamo spiegato praticamente tutto nella
puntata  precedente,  avendone  fatto  cavia  per  la nostra
dissertazione  sul  protocollo  di  gestione  degli  eventi.
Ricordiamo  solo che eventi MENUPICK hanno senso quando alla
finestra si sia attaccato con SetMenuStrip() un menu, e  che
tutte  le  informazioni  relative  alla selezione effettuata
sono leggibili nel campo codice  del  messaggio,  attraverso
delle  comode  macros che sono state illustrate nella nostra
ultima chiaccherata.

- NEWSIZE

  Questo evento ci avverte quando l'utente ha ridimensionato
la  nostra   finestra.   Potremo   decidere  ad  esempio  di
ridisegnarne  la  grafica  che  e'  andata  quasi certamente
distrutta.

- DISKINSERTED - DISKREMOVED

  Come dicono i nomi, questi eventi segnalano l'introduzione
o la rimozione di un disco da un drive.

- INTUITICKS

  Gli  eventi  intuiticks  sono  dei  semplici  messaggi  di
temporizzazione  che  Intuition,  ci  manda ad intervalli di
circa 1/50 di secondo. Ne parlo  perche'  qualcuno  potrebbe
avere  la  malaugurata tentazione di provare ad utilizzarli.
In due parole: LASCIATELI PERDERE.
  Gia' il buon Mr.Mical, sul manuale di  Intuition,  avverte
che  la  temporizzazione e' imprecisa. Nella realta' essa e'
MOLTO imprecisa. Secondariamente, per evitare la tendenza di
questi messaggi ad accumularsi alla porta,  Intuition  cessa
di  trasmetterli   se   non   riceve   entro   il   fatidico
cinquantesimo di secondo successivo la nostra risposta.   E'
maledettamente  facile,  anche  usando tutta la nostra buona
volonta' di  programmatori,  rispondere  in  ritardo  ad  un
INTUITICK.  Da  quel  momento  in   avanti   Intuition   non
trasmettera' piu' eventi INTUITICK e, se stiamo aspettando i
suoi messaggi per sincronizzarci, resteremo ad  aspettare  e
sperare fino al prossimo, spazientito reboot.

  Ho  accennato alla possibilita' di modificare l'insieme di
eventi dei quali essere avvertiti  da  Intuition.   Si  puo'
farlo con una semplice chiamata del tipo:

ModifyIDCMP (puntatore_a_Window, Nuovo_insieme_IDCMPFlags);
/* fa parte della intuition.library */

  Il  nuovo  insieme  di  IDCMP  flags  SOSTITUISCE   quello
specificato nel campo IDCMPFlags della struttura  NewWindow,
o  qualsiasi  insieme preesistente nel caso siano state gia'
apportate delle modifiche con questa  chiamata.   Se  volete
accendere  o  spegnere  un  singolo  evento,  qui di seguito
riportiamo le chiamate principali, che  costituiscono  anche
una  buona  ginnastica sugli operatori in logica binaria del
linguaggio C:

-Per aggiungere un evento a quelli correntemente installati:

 ModifyIDCMP(finestra,(finestra->IDCMPFlags|nuovo_evento));

dove  <finestra>  e'  un  puntatore  alla  struttura  Window
ritornato da  OpenWindow,  e  nuovo_evento  e'  l'evento  da
aggiungere  a  quelli  esistenti.  Inutile  dire  che dovete
essere pronti a maneggiare anche questo evento. Il segno '|'
(la barretta che si trova, sulla mia tastiera USA, sopra  il
'\'  e di fianco all '=') sta per OR logico tra DUE MASCHERE
DI BIT, nel senso proprio  della  logica  binaria.   Non  va
confuso  con  il segno || (doppia barretta) che e' invece un
OR in logica  'umana'  (ex:  se  a=b  OR  c=d).   La  stessa
confusione  e'  offerta dal C per i segni '&' (AND in logica
binaria) e '&&' (AND in logica 'umana').
-Per eliminare un evento:

 ModifyIDCMP (finestra, (finestra->IDCMPFlags & ~evento));

  Questo e' un poco piu' complesso da spiegare.  Attenzione:
Ogni evento corrisponde ad un bit 'acceso' (1) in  una  LONG
(32  bit). Al nome di un evento, come definito in Intuition/
Intuition.h, corrisponde un bit a 1 in  una  LONG  di  tutti
zeri. Ad esempio (da intuition.h):

#define MENUPICK 0x00000100L

  L'operazione  ~evento  (NOT  in logica binaria) inverte lo
stato di tutti i bit di evento, quindi significa "tutti  gli
eventi possibili tranne 'nuovo_evento'".

--Esempio: ~MENUPICK = 0xffffeffL (in notazione esadecimale)
cioe': = 111111.......1 0 1....11111 (in binario)

  Il  primo zero in 0x non ha valore, indica solo che questo
e' un numero esadecimale.

  Il valore ottentuto serve da 'maschera' per  filtrare  gli
eventi  gia'  attivi,  contenuti  nel campo IDCMPFlags della
struttura Window.  L'operazione  '&'  (AND  binario)  lascia
passare  tutti  i  bit  degli eventi preesistenti (che nella
maschera  sono   ad  1),  tranne  quello  corrispondente  ad
'evento' (che nella maschera e' stato azzerato). Quindi alla
funzione  viene  passato  un  nuovo  insieme  di bit/eventi,
identica a quella preesistente nella finestra, mancante solo
del bit corrispondente ad 'evento'.

-Per invertire lo stato di un evento:

 ModifyIDCMP (finestra, (finestra->IDCMPFlags ^evento));

  Quest'ultima espressione prende  l'insieme  di  bit/eventi
preesistente  ed inverte (utilizzando l'operatore binario OR
ESCLUSIVO  '^'  lo  stato  del bit corrispondente all'evento
desiderato.  Come risultato, se l'evento era acceso,  questa
operazione  lo spegne. Se, invece, era spento, lo attiva.  I
bit  relativi  agli  altri  eventi   rimangono   inalterati.


  Bene, ora sapete sulla gestione degli eventi tutto  quello
che  e'  necessario  per la scrittura di qualche programmino
utile,  partendo   magari  dalla  sorgente  dell'esempio  ed
aggiungendo   qualche    funzione.   Nel   nostro   prossimo
appuntamento  ci   occuperemo  dell'ultimo  dei  cavalli  di
battaglia  di  Intuition:  i  Gadgets.  Preparatevi  ad  una
puntata very mega tosta! Avremo qualche altro evento  ed  un
programma  sempre  piu' completo. Nel frattempo coccolate il
vostro Amiga e  non  disperatevi  troppo  se,  programmando,
scrivete  ancora  piu'  bugs che istruzioni corrette. Avremo
presto uno 'special' dedicato ai bugs ed  agli  errori  piu'
comuni  e  difficili da localizzare. Sara' un campo di prova
per  affinare   le   vostre   capacita'   nell'arte    della
derattizzazione. Potrete rimediare ai peccati che avete gia'
commesso  ed imparerete come evitare di commettere i peccati
che hanno gia' portato tanti altri programmatori alla soglia
dell'esaurimento nervoso.....(..yuk!..)
  See ya soon !
                                            Andy Zanna
