diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..708558b
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,20 @@
+Copyright (c) 1997-2020 Marco Olivo
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6d25a44
--- /dev/null
+++ b/README.md
@@ -0,0 +1,113 @@
+# Grafico, a program for drawing math functions
+
+This repo contains an old retro-computing program I wrote back in 1997 for MS-DOS. Its aim was to get a math function in input and draw it, also calculating and plotting first-degree and second-degree derived functions.
+
+It was written in Turbo Pascal 6, and you can find the [source code here](/src) with the main code being [this file](/src/grafico.pas). The original [compile.bat](/compile.bat) was the file used to compile it all, and required the `tcp.exe` file which is the Turbo Pascal 6 compiler for MS-DOS.
+
+I cannot provide it (I am not sure it is still under copyright), however I do not think anyone will try to compile this program anymore.
+To compile it maybe you can use Free Pascal:
+
+```bash
+sudo apt-get install fp-compiler fp-ide
+```
+
+See also
+
+However I haven't tried it myself (being Grafico more than 20 years old).
+
+Theoretically, it could be run under Linux with `dosbox`:
+
+```bash
+sudo apt-get install dosbox
+dosbox grafico.exe
+```
+
+However, I personally didn't succeed: the program runs in graphical mode, and I received lots of gibberish on the screen. If you manage to make it run, please let me know how.
+
+## Original instructions (italian)
+
+Grafico è un programma che ho ideato nel dicembre del 1997 ed ho sviluppato nel corso dei primi mesi del 1998. Sebbene il suo nome sia tutt'altro che originale, questo programma è in grado di compiere diverse operazioni riguardo lo studio di funzioni matematiche. Alla fine di aprile 1999 sono state aggiunte alcune nuove funzionalità per quanto riguarda le funzioni supportate dal programma.
+
+In breve, ecco le caratteristiche principali del programma in questione:
+
+* possibilità di studiare una qualunque funzione matematica (razionale, irrazionale, fratta, goniometrica, logaritmica, ...)
+* possibilità di visualizzarne la sua derivata prima con in più alcuni punti particolarmente significativi ricavabili da essa; la derivata seconda non è stata implementata, ma è possibile inserire una breve funzione anche per essa tramite semplici formule di calcolo numerico
+* possibilità di visualizzare il grafico di rotazione della curva attorno all'asse delle ascisse (un problema che si trova spesso durante la discussione di volumi tramite integrali; a questo proposito anche qui non è stato implementato il calcolo dell'integrale della curva, ma il metodo è piuttosto facile, dato che è sufficiente utilizzare qualche formula del calcolo numerico)
+* possibilità di caricare e salvare un file contenente un massimo di 16 funzioni, richiamabili molto facilmente per una rapida consultazione
+* possibilità di cambiare la scala di visualizzazione da numeri interi a radianti (l'ideale per le funzioni goniometriche)
+* possibilità di scorrere il grafico della curva, di ingrandire e di rimpicciolire parti di essa, di aumentare o diminuire la risoluzione della curva (modificando la distanza tra i punti) e possibilità di visualizzare il dominio della curva
+* possibilità di estrapolare punti dal grafico, al fine di visualizzarne l'ordinata
+
+Le funzioni matematiche base supportate sono numerose. Esempi:
+
+* abs(x)
+* ln(x)
+* sen(x)
+* cos(x)
+* tag(x)
+* cotag(x)
+* arcsen(x)
+* arccos(x)
+* arctag(x)
+* arccotag(x)
+* sqr(x)
+* sqrt(x)
+* x^3
+* e^x
+* (1/2)^x
+* (x-1)/(x+4)
+* asinh(x)
+* acosh(x)
+* atanh(x)
+* sinh(x)
+* cosh(x)
+* tanh(x)
+* sgn(x)
+* int(x)
+
+oltre a tutte le possibili combinazioni delle stesse, come ad esempio:
+
+* 4\*cos(x)+2\*cos(2\*x)-1
+* cos(x)/(sin(x)-1)
+* (x^3)\*(e^(-x))
+* (1-abs(e^(2\*x)-1))^(1/2)
+* arctag(1/abs(x))
+* x/(x^3-1)
+* 2\*x+log(x)
+* 2\*arctag(x)-x
+* (x^2+x)^(1/3)
+* x+(1-x^2)^(1/2)
+* 1/(1+x)+1/(1-abs(x))
+* x/(x^2+1)
+* abs(x^3-x^2)+x^3
+* ln(x/(x^2-4))
+* x+tag(x)
+* (x-2)*(e^x-1)
+* (1+x)/(abs(1-x))
+* (1+x)/(1-abs(x))
+* (1+abs(x))/(1-abs(x))
+* (x^2-4)/(x+1)
+* (x^3)/abs(x^2-1)
+* sqrt(4-x^2)
+* sqrt((1-abs(x))/(1+abs(x)))
+* sqrt((1-x)/(1+x))
+* 3\*((sen(x))^2)-3\*((sen(x))^3)
+* ((cos(x))^2)/(1+2\*sen(x))
+* (abs(x))^x
+* 2^(x+1/x)
+* (e^(tag(x))-1)/(e^(tag(x))+1)
+* sqrt(1-e^x)
+* arctag((e^x+1)/(e^x-1))
+* 25\*(x^3)\*(x-1)^2
+
+## Screenshot
+
+La figura qui sotto mostra una sovrapposizione di schermate del programma (quella in alto a sinistra è uno studio di funzione in verde con la derivata prima in viola e l'asse Y fuori dal dominio evidenziato in blu e quella in basso a destra è la rotazione di una curva attorno all'asse delle X):
+
+![Screenshot del programma](/images/grafico.jpg)
+
+## Riconoscimenti
+
+QUESTO PROGRAMMA E' STATO PUBBLICATO SULLA RIVISTA ITALIANA PCFLOPPY+PCMAGAZINE (EDITA DA JACKSON INFORMATICA) NEL MESE DI MAGGIO 1999 NELLO SPAZIO DEDICATO AI PROGRAMMATORI ITALIANI. DESIDERO RINGRAZIARE TUTTI COLORO CHE MI HANNO AIUTATO, IN UN MODO O NELL'ALTRO. UN GRAZIE SPECIALE A SILVIO D'ANGELO E ROBERTO FULIGNI, CHE MI HANNO AIUTATO ED INCORAGGIATO NELLA PRIMA VERSIONE DEL PROGRAMMA.
+
+![Articolo su PC Magazine maggio 1999](/images/articolo.jpg)
diff --git a/build/grafico.exe b/build/grafico.exe
new file mode 100644
index 0000000..56dee3e
Binary files /dev/null and b/build/grafico.exe differ
diff --git a/compile.bat b/compile.bat
new file mode 100644
index 0000000..ddb1601
--- /dev/null
+++ b/compile.bat
@@ -0,0 +1,5 @@
+rem Compilazione di grafico.pas tramite Turbo Pascal
+cls
+cd src
+tpc grafico.pas
+make -f grafico.mak
diff --git a/images/articolo.jpg b/images/articolo.jpg
new file mode 100644
index 0000000..68ef6d9
Binary files /dev/null and b/images/articolo.jpg differ
diff --git a/images/grafico.jpg b/images/grafico.jpg
new file mode 100644
index 0000000..7164892
Binary files /dev/null and b/images/grafico.jpg differ
diff --git a/images/logopcf.gif b/images/logopcf.gif
new file mode 100644
index 0000000..2a6b8cb
Binary files /dev/null and b/images/logopcf.gif differ
diff --git a/src/att.bgi b/src/att.bgi
new file mode 100644
index 0000000..fa25e1c
Binary files /dev/null and b/src/att.bgi differ
diff --git a/src/att.obj b/src/att.obj
new file mode 100644
index 0000000..6ed6f3e
Binary files /dev/null and b/src/att.obj differ
diff --git a/src/bgidriv.pas b/src/bgidriv.pas
new file mode 100644
index 0000000..097208d
--- /dev/null
+++ b/src/bgidriv.pas
@@ -0,0 +1,35 @@
+
+{ Copyright (c) 1985, 1990 by Borland International, Inc. }
+
+unit BGIDriv;
+{ Sample unit to accompany BGILINK.PAS. This unit links the BGI graphics
+ driver into a single TPU file. This makes it easy to link the driver files
+ directly into an .EXE file. See BGILINK.PAS for more information.
+}
+interface
+
+procedure ATTDriverProc;
+procedure CgaDriverProc;
+procedure EgaVgaDriverProc;
+procedure HercDriverProc;
+procedure PC3270DriverProc;
+
+implementation
+
+procedure ATTDriverProc; external;
+{$L ATT.OBJ }
+
+procedure CgaDriverProc; external;
+{$L CGA.OBJ }
+
+procedure EgaVgaDriverProc; external;
+{$L EGAVGA.OBJ }
+
+procedure HercDriverProc; external;
+{$L HERC.OBJ }
+
+procedure PC3270DriverProc; external;
+{$L PC3270.OBJ }
+
+end.
+
\ No newline at end of file
diff --git a/src/bgidriv.tpu b/src/bgidriv.tpu
new file mode 100644
index 0000000..ffc583e
Binary files /dev/null and b/src/bgidriv.tpu differ
diff --git a/src/bgifont.pas b/src/bgifont.pas
new file mode 100644
index 0000000..3968fdd
--- /dev/null
+++ b/src/bgifont.pas
@@ -0,0 +1,31 @@
+
+{ Copyright (c) 1985, 1990 by Borland International, Inc. }
+
+unit BGIFont;
+{ Sample unit to accompany BGILINK.PAS. This unit links all the BGI graphics
+ fonts into a single TPU file. This makes it easy to incorporate the font
+ files directly into an .EXE file. See BGILINK.PAS for more information.
+}
+interface
+
+procedure GothicFontProc;
+procedure SansSerifFontProc;
+procedure SmallFontProc;
+procedure TriplexFontProc;
+
+implementation
+
+procedure GothicFontProc; external;
+{$L GOTH.OBJ }
+
+procedure SansSerifFontProc; external;
+{$L SANS.OBJ }
+
+procedure SmallFontProc; external;
+{$L LITT.OBJ }
+
+procedure TriplexFontProc; external;
+{$L TRIP.OBJ }
+
+end.
+
\ No newline at end of file
diff --git a/src/bgifont.tpu b/src/bgifont.tpu
new file mode 100644
index 0000000..bddb195
Binary files /dev/null and b/src/bgifont.tpu differ
diff --git a/src/binobj.exe b/src/binobj.exe
new file mode 100644
index 0000000..5d46a2e
Binary files /dev/null and b/src/binobj.exe differ
diff --git a/src/bold.chr b/src/bold.chr
new file mode 100644
index 0000000..8af2bc2
Binary files /dev/null and b/src/bold.chr differ
diff --git a/src/cga.bgi b/src/cga.bgi
new file mode 100644
index 0000000..0c3cb66
Binary files /dev/null and b/src/cga.bgi differ
diff --git a/src/cga.obj b/src/cga.obj
new file mode 100644
index 0000000..747498c
Binary files /dev/null and b/src/cga.obj differ
diff --git a/src/egavga.bgi b/src/egavga.bgi
new file mode 100644
index 0000000..1771336
Binary files /dev/null and b/src/egavga.bgi differ
diff --git a/src/egavga.obj b/src/egavga.obj
new file mode 100644
index 0000000..492b11f
Binary files /dev/null and b/src/egavga.obj differ
diff --git a/src/euro.chr b/src/euro.chr
new file mode 100644
index 0000000..bb1f9ec
Binary files /dev/null and b/src/euro.chr differ
diff --git a/src/goth.chr b/src/goth.chr
new file mode 100644
index 0000000..75f9a7e
Binary files /dev/null and b/src/goth.chr differ
diff --git a/src/goth.obj b/src/goth.obj
new file mode 100644
index 0000000..8c5a195
Binary files /dev/null and b/src/goth.obj differ
diff --git a/src/grafico.mak b/src/grafico.mak
new file mode 100644
index 0000000..93aef88
--- /dev/null
+++ b/src/grafico.mak
@@ -0,0 +1,31 @@
+# Build program that uses BGIFONT.TPU and BGIDRIV.TPU
+grafico.exe: bgidriv.tpu bgifont.tpu
+ tpc grafico /m
+
+# Build unit with all fonts linked in
+bgifont.tpu: bgifont.pas goth.obj litt.obj sans.obj trip.obj
+ tpc bgifont
+goth.obj: goth.chr
+ binobj goth.chr goth GothicFontProc
+litt.obj: litt.chr
+ binobj litt.chr litt SmallFontProc
+sans.obj: sans.chr
+ binobj sans.chr sans SansSerifFontProc
+trip.obj: trip.chr
+ binobj trip.chr trip TriplexFontProc
+
+
+# Build unit with all drivers linked in
+bgidriv.tpu: bgidriv.pas cga.obj egavga.obj herc.obj pc3270.obj att.obj
+ tpc bgidriv
+cga.obj: cga.bgi
+ binobj cga.bgi cga CGADriverProc
+egavga.obj: egavga.bgi
+ binobj egavga.bgi egavga EGAVGADriverProc
+herc.obj: herc.bgi
+ binobj herc.bgi herc HercDriverProc
+pc3270.obj: pc3270.bgi
+ binobj pc3270.bgi pc3270 PC3270DriverProc
+att.obj: att.bgi
+ binobj att.bgi att ATTDriverProc
+
\ No newline at end of file
diff --git a/src/grafico.pas b/src/grafico.pas
new file mode 100644
index 0000000..c3c6e03
--- /dev/null
+++ b/src/grafico.pas
@@ -0,0 +1,3793 @@
+(*Programma per l'analisi di una funzione matematica - Marco Olivo, 1998*)
+(*Versione 4.0*)
+
+(*Questo programma ? liberamente distribuibile e modificabile, a patto che rimanga
+il mio nome nei crediti e a patto che non venga utilizzato per scopi di lucro e/o commerciali*)
+(*Contiene parti Copyright (c) 1985, 1990 by Borland International, Inc.*)
+
+(*In nessun caso sar? responsabile per i danni (inclusi, senza limitazioni, il danno per
+perdita mancato guadagno, interruzione dell'attivit?, perdita di informazioni o altre perdite
+economiche) derivanti dall'uso del prodotto "Grafico", anche nel caso io sia stato avvertito
+dalla possibilit? di danni.*)
+
+(*Per la compilazione utilizzare il comando:
+ make -fgrafico.mak
+*)
+
+(*Impostiamo alcune "Switch directives"; la prima ({$A+}) serve per velocizzare
+l'esecuzione del programma sulle CPU 80x86; la seconda ({$G-}) per far funzionare il programma
+anche sugli 8086; la terza ({$N+}) e la quarta ({$E+}) servono per rendere il programma
+portabile su macchine senza il coprocessore numerico 8087 e la quinta ({$S-}) per non permettere al
+programma di dare eventuali errori di "stack overflow"*)
+{$A+,G-,N+,E+,S-}
+
+program Analizza_Funzione;
+
+(********************************************************************
+* Dichiarazione "uses"
+********************************************************************)
+
+uses Crt,
+ Graph,
+ BGIDriv,
+ BGIFont;
+
+(********************************************************************
+* Dichiarazione "type"
+********************************************************************)
+
+type
+ coordxy=record
+ x,y:Integer;
+end;
+
+(********************************************************************
+* Variabili globali del programma
+********************************************************************)
+
+var
+ vertici:array[1..4] of coordxy; (*Array per il riempimento della grafica 3D*)
+ funzione:string; (*Variabile temporanea per la nostra funzione*)
+ numero,array_funzione:array[1..100] of string; (*Variabili per valutare l'equazione*)
+ lista_funzioni:array[1..16] of string; (*Contiene le ultime 16 funzioni*)
+ array_x,array_y:array[1..500] of real; (*Arrays per la rotazione della curva*)
+ num_valori:Integer; (*Per il conteggio dei valori presenti negli array sopra*)
+ numero_funzioni:Integer; (*Numero di funzioni correntemente salvate*)
+ funzione_corrente:Integer; (*Numero della funzione correntemente selezionata*)
+ lunghezza:Integer; (*Lunghezza della nostra funzione*)
+ decrementa:Integer; (*Variabile per l'analisi dei dati immessi*)
+ i,oparen,cparen:Integer; (*Variabili per l'analisi dei dati immessi*)
+ OrigMode:Integer; (*Contiene modalit? di testo iniziale*)
+ grDriver:Integer; (*Per la grafica*)
+ grMode:Integer; (*Per la grafica*)
+ ErrCode:Integer; (*Per la grafica*)
+ AsseXx1, AsseXy1, AsseXx2, AsseXy2, AsseYx1, AsseYy1, AsseYx2, AsseYy2:Integer; (*Posizioni degli assi cartesiani*)
+ risoluzione,scala:Integer; (*Fattori per la precisione del grafico*)
+ lunghezza_funzione:Integer; (*Variabile temporanea*)
+ PuntiSx,PuntiDx:Integer; (*Punti principali tracciati a sinistra ed a destra dell'origine*)
+ Linee:Boolean; (*Grafico per linee o per punti?*)
+ Limita:Boolean; (*Per la limitazione del dominio*)
+ x_precedente,y_precedente:Longint; (*Per unire il punto precedente del grafico con quello corrente con una linea*)
+ sx,dx:extended; (*Se il dominio ? limitato, allora queste variabili contengono limitazione*)
+ Disegna,Errore:Boolean; (*Per disegnare correttamente la funzione quando ci sono errori*)
+ Grafico_Rotazione:Boolean; (*Grafico (True) o rotazione (False)?*)
+ Griglia:Boolean; (*Per la griglia*)
+ FuoriDominio:Boolean; (*Per il dominio*)
+ FileDelleFunzioni:string; (*Nome del file che contiene la lista delle funzioni*)
+ errore_da,errore_a:extended; (*Per il dominio*)
+ Dominio:Boolean; (*Dobbiamo disegnare il dominio?*)
+ h:real; (*Incremento tra due valori consecutivi di X*)
+ path:string; (*Percorso BGI*)
+ InizializzatoX,InizializzatoY:Boolean; (*Per vedere se abbiamo inizializzato correttamente
+ le posizioni degli assi*)
+ Radianti:Boolean; (*Punti sul grafico in interi od in radianti?*)
+ DisegnaDerivata:Boolean; (*Dobbiamo disegnare la derivata della funzione?*)
+
+(********************************************************************
+* Prototipi di funzioni e procedure di tutto il programma
+********************************************************************)
+
+function Power(x:extended;y:extended):extended; forward;
+function sinh(x:extended):extended; forward;
+function cosh(x:extended):extended; forward;
+function tanh(x:extended):extended; forward;
+function sgn(x:extended):extended; forward;
+function asinh(x:extended):extended; forward;
+function acosh(x:extended):extended; forward;
+function atanh(x:extended):extended; forward;
+function ArcSen(x:extended):extended; forward;
+function ArcCos(x:extended):extended; forward;
+function ArcCotan(x:extended):extended; forward;
+function ControllaSintassi:Boolean; forward;
+function TrovaPrimoTermine(pos:Integer):Integer; forward;
+function TrovaSecondoTermine(pos:Integer):Integer; forward;
+procedure CalcolaPrecedenze; forward;
+procedure AnalizzaDati; forward;
+function CalcolaParentesi(da,a:Integer):extended; forward;
+procedure Scrivi(valore:extended;da,a:Integer); forward;
+function CalcolaValore(da,a:Integer):extended; forward;
+procedure LeggiFunzione; forward;
+procedure Abort(Msg:string); forward;
+procedure DisegnaTitolo(titolo:string); forward;
+procedure DisegnaMascherinaInformazioni; forward;
+procedure DisegnaMascherinaTasti; forward;
+procedure DisegnaGriglia; forward;
+procedure DisegnaAssi; forward;
+procedure DisegnaAssiSussidiari; forward;
+procedure DisegnaNumeri; forward;
+procedure DisegnaValore(x,y:Longint;color:Integer); forward;
+procedure Sostituisci(x:real); forward;
+procedure DisegnaDominio; forward;
+procedure DisegnaGrafico(flag:Boolean); forward;
+procedure DisegnaMascherinaRotazione; forward;
+procedure VisualizzaGrafico; forward;
+procedure Grafico; forward;
+procedure Rotazione; forward;
+procedure Derivata; forward;
+procedure RuotaCurva; forward;
+function ReadChar:Char; forward;
+procedure Beep; forward;
+procedure SchermataDiBenvenuto; forward;
+procedure Messaggio(testo:string); forward;
+procedure MenuPrincipale; forward;
+procedure InserisciFunzione(espressione:string); forward;
+procedure EstrapolaPunti; forward;
+procedure LimitaDominio; forward;
+procedure Informazioni_Guida; forward;
+function Conferma(testo:string):Boolean; forward;
+function ConfermaUscita:Boolean; forward;
+procedure ImpostaValoriDiDefault; forward;
+procedure ImpostaDefault; forward;
+function FileExists(FileName:string):Boolean; forward;
+procedure CaricaListaFunzioni(FileName:string); forward;
+procedure SalvaListaFunzioni(FileName:string); forward;
+procedure MostraListaFunzioni; forward;
+procedure SelezionaFunzione(da_selezionare,precedente:Integer); forward;
+procedure ChiediNomeFile; forward;
+procedure FinestraPrincipale; forward;
+
+(********************************************************************
+* Funzioni e procedure per il calcolo dei valori della funzione
+********************************************************************)
+
+function Power(x:extended;y:extended):extended;
+begin
+ if (x=0) AND (y=0) then
+ begin
+ Power:=0;
+ Errore:=True;
+ Disegna:=False;
+ end
+ else if (x>0) then
+ Power:=Exp(y*ln(x))
+ else if (x<0) then
+ begin
+ if ((1/y)>1) then
+ begin
+ if (Odd(Round(1/y))) then
+ Power:=-Exp(y*ln(-x))
+ else if (NOT (Odd(Round(1/y)))) then
+ begin
+ if (y>1) then
+ Power:=Exp(y*ln(-x))
+ else if (y<1) then
+ begin
+ Power:=0;
+ Errore:=True;
+ end
+ else if (y=1) then
+ Power:=x;
+ end;
+ end
+ else
+ begin
+ if (Odd(Round(y))) then
+ Power:=-Exp(y*ln(-x))
+ else if (NOT (Odd(Round(y)))) then
+ begin
+ if (y>1) then
+ Power:=Exp(y*ln(-x))
+ else if (y<1) then
+ begin
+ Power:=0;
+ Errore:=True;
+ end
+ else if (y=1) then
+ Power:=x;
+ end;
+ end;
+ end
+ else if (x=0) AND (y>0) then
+ Power:=0
+ else if (x=0) AND (y<0) then
+ begin
+ Errore:=True;
+ Power:=0;
+ end
+ else
+ Power:=1;
+end;
+(*******************************************************************)
+
+function sinh(x:extended):extended;
+begin
+ sinh:=(exp(x)-exp(-x))/2;
+end;
+(*******************************************************************)
+
+function cosh(x:extended):extended;
+begin
+ cosh:=(exp(x)+exp(-x))/2;
+end;
+(*******************************************************************)
+
+function tanh(x:extended):extended;
+begin
+ tanh:=(exp(2*x)-1)/(exp(2*x)+1)
+end;
+(*******************************************************************)
+
+function sgn(x:extended):extended;
+begin
+ if (x>0) then
+ sgn:=1
+ else if (x<0) then
+ sgn:=-1
+ else (*x=0*)
+ sgn:=0;
+end;
+(*******************************************************************)
+
+function asinh(x:extended):extended;
+begin
+ asinh:=ln(x+sqrt(sqr(x)+1));
+end;
+(*******************************************************************)
+
+function acosh(x:extended):extended;
+begin
+ if (x>=1) then
+ acosh:=ln(x+sqrt(sqr(x)-1))
+ else
+ begin
+ acosh:=0;
+ Errore:=True;
+ end;
+end;
+(*******************************************************************)
+
+function atanh(x:extended):extended;
+begin
+ if (x>-1) AND (x<1) then
+ atanh:=ln(sqrt((1+x)/(1-x)))
+ else
+ begin
+ atanh:=0;
+ Errore:=True;
+ end;
+end;
+(*******************************************************************)
+
+function ArcSen(x:extended):extended;
+begin
+ if (x>-1) AND (x<1) then
+ ArcSen:=ArcTan(x/sqrt(1-sqr(x)))
+ else
+ begin
+ ArcSen:=0;
+ Errore:=True;
+ end;
+end;
+(*******************************************************************)
+
+function ArcCos(x:extended):extended;
+begin
+ if (x>-1) AND (x<1) then
+ ArcCos:=Pi/2-ArcTan(x/sqrt(1-sqr(x)))
+ else
+ begin
+ ArcCos:=0;
+ Errore:=True;
+ end;
+end;
+(*******************************************************************)
+
+function ArcCotan(x:extended):extended;
+begin
+ ArcCotan:=Pi/2-ArcTan(x);
+end;
+(*******************************************************************)
+
+function ControllaSintassi:Boolean;
+var
+ k,i:Integer;
+ posizione_parentesi:Integer;
+ testo:string;
+begin
+ ControllaSintassi:=True;
+ if (oparen<>cparen) then
+ begin
+ Messaggio('Errore di sintassi: parentesi aperte e chiuse in numero diverso');
+ ControllaSintassi:=False;
+ end;
+ for i:=1 to lunghezza do
+ begin
+ if (array_funzione[i]<>'(') AND (array_funzione[i]<>')') AND (array_funzione[i]<>'+') AND (array_funzione[i]<>'-')
+ AND (array_funzione[i]<>'*') AND (array_funzione[i]<>'^') AND (array_funzione[i]<>'/')
+ AND (array_funzione[i]<>'SIN') AND (array_funzione[i]<>'COS') AND (array_funzione[i]<>'TAN') AND
+ (array_funzione[i]<>'ATAN') AND (array_funzione[i]<>'COTAN') AND
+ (array_funzione[i]<>'LOG') AND (array_funzione[i]<>'ABS') AND (array_funzione[i]<>'SQR') AND
+ (array_funzione[i]<>'SQRT') AND (array_funzione[i]<>'X') AND (array_funzione[i]<>'ARCSIN')
+ AND (array_funzione[i]<>'ARCCOS') AND (array_funzione[i]<>'ARCCOTAN') AND (array_funzione[i]<>'SINH')
+ AND (array_funzione[i]<>'ASINH') AND (array_funzione[i]<>'COSH') AND (array_funzione[i]<>'ACOSH')
+ AND (array_funzione[i]<>'TANH') AND (array_funzione[i]<>'ATANH') AND (array_funzione[i]<>'SGN') AND
+ (array_funzione[i]<>'INT')then
+ begin
+ if (array_funzione[i][1]='0') OR (array_funzione[i][1]='1')
+ OR (array_funzione[i][1]='2') OR (array_funzione[i][1]='3')
+ OR (array_funzione[i][1]='4') OR (array_funzione[i][1]='5')
+ OR (array_funzione[i][1]='6') OR (array_funzione[i][1]='7')
+ OR (array_funzione[i][1]='8') OR (array_funzione[i][1]='9') then
+ begin
+ for k:=2 to Length(array_funzione[i]) do
+ begin
+ if (array_funzione[i][k]<>'0') AND (array_funzione[i][k]<>'1')
+ AND (array_funzione[i][k]<>'2') AND (array_funzione[i][k]<>'3')
+ AND (array_funzione[i][k]<>'4') AND (array_funzione[i][k]<>'5')
+ AND (array_funzione[i][k]<>'6') AND (array_funzione[i][k]<>'7')
+ AND (array_funzione[i][k]<>'8') AND (array_funzione[i][k]<>'9') then
+ begin
+ Messaggio('Errore di sintassi: carattere non valido');
+ ControllaSintassi:=False;
+ end;
+ end;
+ end
+ else if (array_funzione[i]='E') then
+ begin
+ Str(Exp(1.0),array_funzione[i]); (*Sostituiamo "e" con il suo valore,
+ dal momento che non lo abbiamo fatto prima
+ per poter controllare la sintassi*)
+ end
+ else
+ begin
+ Messaggio('Errore di sintassi: carattere non valido');
+ ControllaSintassi:=False;
+ end;
+ end;
+ end;
+ for i:=1 to lunghezza do
+ begin
+ if (array_funzione[i]='(') then
+ begin
+ if (array_funzione[i+1]=')') then
+ begin
+ Messaggio('Errore di sintassi: nessun argomento nella parentesi');
+ ControllaSintassi:=False;
+ end;
+ end;
+ end;
+ oparen:=0;
+ cparen:=0;
+ for i:=1 to lunghezza do
+ begin
+ if (array_funzione[i]='(') then
+ Inc(oparen)
+ else if (array_funzione[i]=')') then
+ Inc(cparen);
+ if cparen>oparen then
+ begin
+ Messaggio('Errore di sintassi: parentesi chiusa prima di parentesi aperta');
+ ControllaSintassi:=False;
+ end;
+ end;
+ for i:=1 to lunghezza do
+ begin
+ if (array_funzione[i]='SIN') OR (array_funzione[i]='COS') OR (array_funzione[i]='TAN') OR
+ (array_funzione[i]='ATAN') OR (array_funzione[i]='COTAN') OR
+ (array_funzione[i]='LOG') OR (array_funzione[i]='ABS') OR (array_funzione[i]='SQR') OR
+ (array_funzione[i]='SQRT') OR (array_funzione[i]='ARCSIN') OR (array_funzione[i]='ARCCOS') OR
+ (array_funzione[i]='ARCCOTAN') OR (array_funzione[i]='SINH') OR (array_funzione[i]='ASINH') OR
+ (array_funzione[i]='COSH') OR (array_funzione[i]='ACOSH') OR (array_funzione[i]='TANH') OR
+ (array_funzione[i]='ATANH') OR (array_funzione[i]='SGN') OR (array_funzione[i]='INT') then
+ begin
+ if (array_funzione[i+1]<>'(') then
+ begin
+ testo:=Concat('Errore di sintassi: nessun argomento di ',array_funzione[i]);
+ Messaggio(testo);
+ ControllaSintassi:=False;
+ end;
+ end;
+ end;
+end;
+(*******************************************************************)
+
+function TrovaPrimoTermine(pos:Integer):Integer;
+var
+ i:Integer;
+ paren:Integer;
+begin
+ paren:=0;
+ for i:=pos downto 1 do
+ begin
+ (*Se la posizione dell'array ? un numero oppure una parentesi, l'abbiamo trovato e
+ ritorniamo la posizione; non ammettiamo errori, dato che abbiamo gi? controllato la
+ sintassi precedentemente*)
+ if (array_funzione[i]<>')') AND (array_funzione[i]<>'+') AND (array_funzione[i]<>'-') AND
+ (array_funzione[i]<>'*') AND (array_funzione[i]<>'^') AND (array_funzione[i]<>'/') AND (paren=0) then
+ begin
+ TrovaPrimoTermine:=i;
+ i:=1; (*Usciamo dal ciclo*)
+ end
+ else if (array_funzione[i]=')') then
+ inc(paren)
+ else if (array_funzione[i]='(') AND (paren>0) then
+ begin
+ dec(paren);
+ if (paren=0) then
+ begin
+ TrovaPrimoTermine:=i;
+ i:=1;
+ end;
+ end;
+ end;
+end;
+(*******************************************************************)
+
+function TrovaSecondoTermine(pos:Integer):Integer;
+var
+ i:Integer;
+ paren:Integer;
+begin
+ paren:=0;
+ for i:=pos to lunghezza do
+ begin
+ (*Se la posizione dell'array ? un numero oppure una parentesi, l'abbiamo trovato e
+ ritorniamo la posizione; non ammettiamo errori, dato che abbiamo gi? controllato la
+ sintassi precedentemente*)
+ if (array_funzione[i]<>'(') AND (array_funzione[i]<>'+') AND (array_funzione[i]<>'-')
+ AND (array_funzione[i]<>'*') AND (array_funzione[i]<>'^') AND (array_funzione[i]<>'/')
+ AND (array_funzione[i]<>'SIN') AND (array_funzione[i]<>'COS') AND (array_funzione[i]<>'TAN') AND
+ (array_funzione[i]<>'ATAN') AND (array_funzione[i]<>'COTAN') AND
+ (array_funzione[i]<>'LOG') AND (array_funzione[i]<>'ABS') AND (array_funzione[i]<>'SQR')
+ AND (array_funzione[i]<>'SQRT') AND (array_funzione[i]<>'ARCSIN') AND (array_funzione[i]<>'ARCCOS')
+ AND (array_funzione[i]<>'ARCCOTAN') AND (array_funzione[i]<>'SINH') AND (array_funzione[i]<>'ASINH')
+ AND (array_funzione[i]<>'COSH') AND (array_funzione[i]<>'ACOSH') AND (array_funzione[i]<>'TANH')
+ AND (array_funzione[i]<>'ATANH') AND (array_funzione[i]<>'SGN') AND (array_funzione[i]<>'INT')
+ AND (paren=0) then
+ begin
+ TrovaSecondoTermine:=i;
+ i:=lunghezza; (*Usciamo dal ciclo*)
+ end
+ else if (array_funzione[i]='(') then
+ inc(paren)
+ else if (array_funzione[i]=')') AND (paren>0) then
+ begin
+ dec(paren);
+ if (paren=0) then
+ begin
+ TrovaSecondoTermine:=i-1;
+ i:=lunghezza;
+ end;
+ end;
+ end;
+end;
+(*******************************************************************)
+
+procedure CalcolaPrecedenze;
+var
+ n,f:Integer;
+ primo_termine,secondo_termine:Integer;
+begin
+ for f:=1 to 100 do
+ begin
+ if (array_funzione[f]='SIN') OR (array_funzione[f]='COS') OR
+ (array_funzione[f]='TAN') OR (array_funzione[f]='ATAN') OR
+ (array_funzione[f]='LOG') OR (array_funzione[f]='COTAN') OR
+ (array_funzione[f]='ABS') OR (array_funzione[f]='SQR') OR
+ (array_funzione[f]='SQRT') OR (array_funzione[f]='ARCSIN') OR
+ (array_funzione[f]='ARCCOS') OR (array_funzione[f]='ARCCOTAN') OR
+ (array_funzione[f]='SINH') OR (array_funzione[f]='ASINH') OR
+ (array_funzione[f]='COSH') OR (array_funzione[f]='ACOSH') OR
+ (array_funzione[f]='TANH') OR (array_funzione[f]='ATANH') OR (array_funzione[f]='INT') OR
+ (array_funzione[f]='SGN') then
+ begin
+ primo_termine:=f;
+ secondo_termine:=TrovaSecondoTermine(f);
+ for n:=lunghezza+1 downto primo_termine do
+ array_funzione[n]:=array_funzione[n-1];
+ array_funzione[primo_termine]:='(';
+ inc(lunghezza);
+ for n:=lunghezza+1 downto secondo_termine+2 do
+ array_funzione[n]:=array_funzione[n-1];
+ array_funzione[secondo_termine+2]:=')';
+ inc(lunghezza);
+ inc(f); (*Evitiamo ripetizioni*)
+ end;
+ end;
+ for f:=1 to 100 do
+ begin
+ if (array_funzione[f]='^') then
+ begin
+ primo_termine:=TrovaPrimoTermine(f);
+ secondo_termine:=TrovaSecondoTermine(f);
+ for n:=lunghezza+1 downto primo_termine do
+ array_funzione[n]:=array_funzione[n-1];
+ array_funzione[primo_termine]:='(';
+ inc(lunghezza);
+ for n:=lunghezza+1 downto secondo_termine+2 do
+ array_funzione[n]:=array_funzione[n-1];
+ array_funzione[secondo_termine+2]:=')';
+ inc(lunghezza);
+ inc(f); (*Evitiamo ripetizioni*)
+ end;
+ end;
+ for f:=1 to 100 do
+ begin
+ if (array_funzione[f]='*') then
+ begin
+ primo_termine:=TrovaPrimoTermine(f);
+ secondo_termine:=TrovaSecondoTermine(f);
+ for n:=lunghezza+1 downto primo_termine do
+ array_funzione[n]:=array_funzione[n-1];
+ array_funzione[primo_termine]:='(';
+ inc(lunghezza);
+ for n:=lunghezza+1 downto secondo_termine+2 do
+ array_funzione[n]:=array_funzione[n-1];
+ array_funzione[secondo_termine+2]:=')';
+ inc(lunghezza);
+ inc(f); (*Evitiamo ripetizioni*)
+ end
+ else if (array_funzione[f]='/') then
+ begin
+ primo_termine:=TrovaPrimoTermine(f);
+ secondo_termine:=TrovaSecondoTermine(f);
+ for n:=lunghezza+1 downto primo_termine do
+ array_funzione[n]:=array_funzione[n-1];
+ array_funzione[primo_termine]:='(';
+ inc(lunghezza);
+ for n:=lunghezza+1 downto secondo_termine+2 do
+ array_funzione[n]:=array_funzione[n-1];
+ array_funzione[secondo_termine+2]:=')';
+ inc(lunghezza);
+ inc(f); (*Evitiamo ripetizioni*)
+ end;
+ end;
+ (*Non ci interessano altri casi*)
+end;
+(*******************************************************************)
+
+procedure AnalizzaDati;
+var
+ n,k,i:Integer;
+ IsNumber:Boolean;
+begin
+ IsNumber:=False;
+ decrementa:=0;
+ for i:=1 to lunghezza do
+ begin
+ if (array_funzione[i]='0') OR (array_funzione[i]='1') OR (array_funzione[i]='2') OR
+ (array_funzione[i]='3') OR (array_funzione[i]='4') OR (array_funzione[i]='5') OR
+ (array_funzione[i]='6') OR (array_funzione[i]='7') OR (array_funzione[i]='8') OR
+ (array_funzione[i]='9') then
+ begin
+ if (IsNumber=False) then
+ IsNumber:=True
+ else (*Accorpiamo la stringa*)
+ begin
+ array_funzione[i-1]:=Concat(array_funzione[i-1], array_funzione[i]);
+ for k:=i to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa);
+ dec(i);
+ end;
+ end
+ else if (array_funzione[i]='X') then
+ IsNumber:=False
+ else if (array_funzione[i]='+') OR (array_funzione[i]='-') OR (array_funzione[i]='*') OR
+ (array_funzione[i]='/') OR (array_funzione[i]='^') then
+ IsNumber:=False
+ else
+ begin
+ IsNumber:=False;
+ if (array_funzione[i]='S') AND (array_funzione[i+1]='I') AND
+ (array_funzione[i+2]='N') AND (array_funzione[i+3]='H') then
+ begin
+ array_funzione[i]:='SINH';
+ for n:=1 to 3 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,3);
+ dec(i,3);
+ end
+ else if (array_funzione[i]='C') AND (array_funzione[i+1]='O') AND
+ (array_funzione[i+2]='S') AND (array_funzione[i+3]='H') then
+ begin
+ array_funzione[i]:='COSH';
+ for n:=1 to 3 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,3);
+ dec(i,3);
+ end
+ else if (array_funzione[i]='T') AND (array_funzione[i+1]='A') AND
+ (array_funzione[i+2]='N') AND (array_funzione[i+3]='H') then
+ begin
+ array_funzione[i]:='TANH';
+ for n:=1 to 3 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,3);
+ dec(i,3);
+ end
+ else if (array_funzione[i]='A') AND (array_funzione[i+1]='S') AND
+ (array_funzione[i+2]='I') AND (array_funzione[i+3]='N') AND
+ (array_funzione[i+4]='H')then
+ begin
+ array_funzione[i]:='ASINH';
+ for n:=1 to 4 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,4);
+ dec(i,4);
+ end
+ else if (array_funzione[i]='A') AND (array_funzione[i+1]='C') AND
+ (array_funzione[i+2]='O') AND (array_funzione[i+3]='S') AND
+ (array_funzione[i+4]='H')then
+ begin
+ array_funzione[i]:='ACOSH';
+ for n:=1 to 4 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,4);
+ dec(i,4);
+ end
+ else if (array_funzione[i]='A') AND (array_funzione[i+1]='T') AND
+ (array_funzione[i+2]='A') AND (array_funzione[i+3]='N') AND
+ (array_funzione[i+4]='H')then
+ begin
+ array_funzione[i]:='ATANH';
+ for n:=1 to 4 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,4);
+ dec(i,4);
+ end
+ else if (array_funzione[i]='S') AND ((array_funzione[i+1]='I') OR (array_funzione[i+1]='E')) AND
+ (array_funzione[i+2]='N') then
+ begin
+ array_funzione[i]:='SIN';
+ for n:=1 to 2 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,2);
+ dec(i,2);
+ end
+ else if (array_funzione[i]='C') AND (array_funzione[i+1]='O') AND (array_funzione[i+2]='S') then
+ begin
+ array_funzione[i]:='COS';
+ for n:=1 to 2 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,2);
+ dec(i,2);
+ end
+ else if (array_funzione[i]='L') AND (array_funzione[i+1]='O') AND (array_funzione[i+2]='G') then
+ begin
+ array_funzione[i]:='LOG';
+ for n:=1 to 2 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,2);
+ dec(i,2);
+ end
+ else if (array_funzione[i]='S') AND (array_funzione[i+1]='G') AND (array_funzione[i+2]='N') then
+ begin
+ array_funzione[i]:='SGN';
+ for n:=1 to 2 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,2);
+ dec(i,2);
+ end
+ else if (array_funzione[i]='L') AND (array_funzione[i+1]='N') then
+ begin
+ array_funzione[i]:='LOG';
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa);
+ dec(i,2);
+ end
+ else if (array_funzione[i]='A') AND (array_funzione[i+1]='B') AND (array_funzione[i+2]='S') then
+ begin
+ array_funzione[i]:='ABS';
+ for n:=1 to 2 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,2);
+ dec(i,2);
+ end
+ else if (array_funzione[i]='C') AND (array_funzione[i+1]='O') AND
+ (array_funzione[i+2]='T') AND (array_funzione[i+3]='G') then
+ begin
+ array_funzione[i]:='COTAN';
+ for n:=1 to 3 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,3);
+ dec(i,3);
+ end
+ else if (array_funzione[i]='C') AND (array_funzione[i+1]='O') AND
+ (array_funzione[i+2]='T') AND (array_funzione[i+3]='A') AND
+ ((array_funzione[i+4]='G') OR (array_funzione[i+4]='N')) then
+ begin
+ array_funzione[i]:='COTAN';
+ for n:=1 to 4 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,4);
+ dec(i,4);
+ end
+ else if (array_funzione[i]='T') AND (array_funzione[i+1]='A') AND
+ ((array_funzione[i+2]='G') OR (array_funzione[i+2]='N')) then
+ begin
+ array_funzione[i]:='TAN';
+ for n:=1 to 2 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,2);
+ dec(i,2);
+ end
+ else if (array_funzione[i]='T') AND (array_funzione[i+1]='G') then
+ begin
+ array_funzione[i]:='TAN';
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa);
+ dec(i,2);
+ end
+ else if (array_funzione[i]='A') AND (array_funzione[i+1]='R') AND
+ (array_funzione[i+2]='C') AND (array_funzione[i+3]='T') AND
+ (array_funzione[i+4]='A') AND ((array_funzione[i+5]='G') OR (array_funzione[i+5]='N')) then
+ begin
+ array_funzione[i]:='ATAN';
+ for n:=1 to 5 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,5);
+ dec(i,5);
+ end
+ else if (array_funzione[i]='A') AND (array_funzione[i+1]='R') AND
+ (array_funzione[i+2]='C') AND (array_funzione[i+3]='T') AND
+ (array_funzione[i+4]='G') then
+ begin
+ array_funzione[i]:='ATAN';
+ for n:=1 to 4 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,4);
+ dec(i,4);
+ end
+ else if (array_funzione[i]='A') AND (array_funzione[i+1]='T') AND
+ (array_funzione[i+2]='A') AND ((array_funzione[i+3]='G') OR
+ (array_funzione[i+3]='N')) then
+ begin
+ array_funzione[i]:='ATAN';
+ for n:=1 to 3 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,3);
+ dec(i,3);
+ end
+ else if (array_funzione[i]='S') AND (array_funzione[i+1]='Q') AND
+ (array_funzione[i+2]='R') AND (array_funzione[i+3]='T') then
+ begin
+ array_funzione[i]:='SQRT';
+ for n:=1 to 3 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,3);
+ dec(i,3);
+ end
+ else if (array_funzione[i]='S') AND (array_funzione[i+1]='Q') AND (array_funzione[i+2]='R') then
+ begin
+ array_funzione[i]:='SQR';
+ for n:=1 to 2 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,2);
+ dec(i,2);
+ end
+ else if (array_funzione[i]='A') AND (array_funzione[i+1]='R') AND
+ (array_funzione[i+2]='C') AND (array_funzione[i+3]='S') AND
+ ((array_funzione[i+4]='E') OR (array_funzione[i+4]='I')) AND (array_funzione[i+5]='N') then
+ begin
+ array_funzione[i]:='ARCSIN';
+ for n:=1 to 5 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,5);
+ dec(i,5);
+ end
+ else if (array_funzione[i]='A') AND (array_funzione[i+1]='R') AND
+ (array_funzione[i+2]='C') AND (array_funzione[i+3]='C') AND
+ (array_funzione[i+4]='O') AND (array_funzione[i+5]='S') then
+ begin
+ array_funzione[i]:='ARCCOS';
+ for n:=1 to 5 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,5);
+ dec(i,5);
+ end
+ else if (array_funzione[i]='A') AND (array_funzione[i+1]='R') AND
+ (array_funzione[i+2]='C') AND (array_funzione[i+3]='C') AND
+ (array_funzione[i+4]='O') AND (array_funzione[i+5]='T') AND (array_funzione[i+6]='G') then
+ begin
+ array_funzione[i]:='ARCCOTAN';
+ for n:=1 to 6 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,6);
+ dec(i,6);
+ end
+ else if (array_funzione[i]='I') AND (array_funzione[i+1]='N') AND
+ (array_funzione[i+2]='T') then
+ begin
+ array_funzione[i]:='INT';
+ for n:=1 to 2 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,2);
+ dec(i,2);
+ end
+ else if (array_funzione[i]='A') AND (array_funzione[i+1]='R') AND
+ (array_funzione[i+2]='C') AND (array_funzione[i+3]='C') AND
+ (array_funzione[i+4]='O') AND (array_funzione[i+5]='T') AND (array_funzione[i+6]='A')
+ AND ((array_funzione[i+7]='G') OR (array_funzione[i+7]='N')) then
+ begin
+ array_funzione[i]:='ARCCOTAN';
+ for n:=1 to 7 do
+ for k:=i+1 to lunghezza do
+ array_funzione[k]:=array_funzione[k+1];
+ inc(decrementa,7);
+ dec(i,7);
+ end;
+ end;
+ end;
+ dec(lunghezza,decrementa);
+end;
+(*******************************************************************)
+
+function CalcolaParentesi(da,a:Integer):extended;
+var
+ result:extended;
+ i:Integer;
+ sign:string;
+ number:extended;
+ code:Integer;
+begin
+ result:=0;
+ sign:='';
+ (*Calcoliamo il valore dell'espressione*)
+ for i:=da to a do
+ begin
+ Val(numero[i],number,code);
+ if (code=0) then
+ begin
+ if (sign='+') then
+ result:=result+number
+ else if (sign='-') then
+ result:=result-number
+ else if (sign='*') then
+ result:=result*number
+ else if (sign='/') then
+ begin
+ if number<>0 then
+ result:=result/number
+ else
+ Errore:=True;
+ end
+ else if (sign='^') then
+ result:=Power(result,number)
+ else if (sign='SIN') then
+ result:=sin(number)
+ else if (sign='COS') then
+ result:=cos(number)
+ else if (sign='LOG') then
+ begin
+ if number>0 then
+ result:=ln(number)
+ else
+ Errore:=True;
+ end
+ else if (sign='TAN') then
+ begin
+ if cos(number)<>0 then
+ result:=sin(number)/cos(number)
+ else
+ Errore:=True;
+ end
+ else if (sign='COTAN') then
+ begin
+ if sin(number)<>0 then
+ result:=cos(number)/sin(number)
+ else
+ Errore:=True;
+ end
+ else if (sign='SINH') then
+ begin
+ result:=sinh(number);
+ end
+ else if (sign='COSH') then
+ begin
+ result:=cosh(number);
+ end
+ else if (sign='TANH') then
+ begin
+ result:=tanh(number);
+ end
+ else if (sign='INT') then
+ begin
+ result:=Int(number);
+ end
+ else if (sign='SGN') then
+ begin
+ result:=sgn(number);
+ end
+ else if (sign='ASINH') then
+ begin
+ result:=asinh(number);
+ end
+ else if (sign='ACOSH') then
+ begin
+ result:=acosh(number);
+ end
+ else if (sign='ATANH') then
+ begin
+ result:=atanh(number);
+ end
+ else if (sign='ATAN') then
+ result:=arctan(number)
+ else if (sign='ABS') then
+ result:=Abs(number)
+ else if (sign='SQR') then
+ result:=Power(number,2)
+ else if (sign='SQRT') then
+ result:=Power(number,1/2)
+ else if (sign='ARCSIN') then
+ result:=ArcSen(number)
+ else if (sign='ARCCOS') then
+ result:=ArcCos(number)
+ else if (sign='ARCCOTAN') then
+ result:=ArcCotan(number)
+ else
+ result:=number;
+ end;
+ sign:=numero[i];
+ end;
+ CalcolaParentesi:=result;
+end;
+(*******************************************************************)
+
+procedure Scrivi(valore:extended;da,a:Integer);
+var
+ i:Integer;
+begin
+ Str(valore,numero[da]);
+ for i:=da+1 to 100 do
+ numero[i]:=numero[i+a-da];
+end;
+(*******************************************************************)
+
+function CalcolaValore(da,a:Integer):extended;
+var
+ i,k:Integer;
+ number,code:Integer;
+ inizio,fine:Integer;
+ risultato:extended;
+ paren:Integer;
+ IsParen:Boolean;
+begin
+ risultato:=0;
+ paren:=0;
+ IsParen:=True;
+
+ (*Togliere il commento alle righe seguenti per mettere in grado il programma
+ di valutare espressioni senza incognite (diventa una sorta di calcolatrice scientifica)*)
+(* for i:=1 to 100 do
+ numero[i]:=array_funzione[i];*)
+
+ (*Calcoliamo tutte le parentesi*)
+ for i:=1 to lunghezza do
+ begin
+ if (numero[i]='(') then
+ begin
+ paren:=1;
+ IsParen:=True;
+ inizio:=i+1;
+ for k:=i+1 to lunghezza do
+ begin
+ if (numero[k]=')') then
+ begin
+ fine:=k-1;
+ k:=lunghezza;
+ end
+ else if (numero[k]='(') then
+ begin
+ inc(paren);
+ inizio:=k+1;
+ end;
+ end;
+ risultato:=CalcolaParentesi(inizio,fine);
+ Scrivi(risultato,inizio-1,fine+1);
+ dec(lunghezza,fine-inizio+2);
+ end
+ else
+ IsParen:=False;
+
+ if (IsParen=True) then
+ i:=1;
+ end;
+
+ (*Fa le varie operazioni, ormai soltanto tra numeri*)
+ CalcolaValore:=CalcolaParentesi(1,lunghezza);
+end;
+(*******************************************************************)
+
+procedure LeggiFunzione;
+var
+ token:string;
+ i:Integer;
+begin
+ oparen:=0;
+ cparen:=0;
+ for i:=1 to 100 do
+ begin
+ array_funzione[i]:='';
+ end;
+
+ for i:=1 to lunghezza do
+ begin
+ token:=Copy(funzione, i, 1);
+
+ (*Analizza la funzione*)
+ if token='(' then
+ begin
+ inc(oparen);
+ array_funzione[i]:='(';
+ end
+ else if token=')' then
+ begin
+ inc(cparen);
+ array_funzione[i]:=')';
+ end
+ else if token='+' then array_funzione[i]:='+'
+ else if token='-' then array_funzione[i]:='-'
+ else if token='*' then array_funzione[i]:='*'
+ else if token='/' then array_funzione[i]:='/'
+ else if token='^' then array_funzione[i]:='^'
+ else if (token='0') OR (token='1') OR (token='2') OR (token='3') OR
+ (token='4') OR (token='5') OR (token='6') OR (token='7') OR
+ (token='8') OR (token='9') then array_funzione[i]:=token
+ else if (token='x') OR (token='X') then array_funzione[i]:='X'
+ else
+ array_funzione[i]:=token;
+ end;
+ AnalizzaDati;
+end;
+
+(********************************************************************
+* Funzioni e procedure per il grafico della funzione
+********************************************************************)
+
+procedure Abort(Msg:string);
+begin
+ (*E' occorso un errore molto grave*)
+ Writeln(Msg,': ',GraphErrorMsg(GraphResult));
+ Halt(1);
+end;
+
+procedure DisegnaTitolo(titolo:string);
+begin
+ SetViewPort(5,5,GetMaxX-5,25,ClipOn);
+ ClearViewPort;
+ SetViewPort(0,0,GetMaxX,GetMaxY,ClipOn);
+ (*Creiamo la nostra mascherina del titolo*)
+ SetColor(DarkGray);
+ SetBkColor(Black);
+ Line(5,5,GetMaxX-5,5);
+ Line(5,5,5,25);
+ Line(5,25,GetMaxX-5,25);
+ Line(GetMaxX-5,5,GetMaxX-5,25);
+ SetColor(Yellow);
+ titolo:=Concat(titolo,funzione);
+ SetTextStyle(DefaultFont,HorizDir,1);
+ SetTextJustify(CenterText,CenterText);
+ OutTextXY(GetMaxX div 2,15,titolo);
+end;
+(*******************************************************************)
+
+procedure DisegnaMascherinaInformazioni;
+var
+ i:Integer;
+ testo:string;
+begin
+ (*Impostiamo l'area di disegno*)
+ SetViewPort(5,GetMaxY-50,GetMaxX-5,GetMaxY-40,ClipOn);
+ ClearViewPort;
+ SetViewPort(0,0,GetMaxX,GetMaxY,ClipOn);
+
+ (*Iniziamo a disegnare*)
+ SetColor(DarkGray);
+ SetBkColor(Black);
+ Line(5,GetMaxY-50,GetMaxX-5,GetMaxY-50);
+ Line(5,GetMaxY-50,5,GetMaxY-40);
+ Line(5,GetMaxY-40,GetMaxX-5,GetMaxY-40);
+ Line(GetMaxX-5,GetMaxY-50,GetMaxX-5,GetMaxY-40);
+ SetColor(LightGreen);
+ SetTextStyle(DefaultFont,HorizDir,1);
+ SetTextJustify(LeftText,TopText);
+ if (Linee=True) then
+ testo:='Linee'
+ else
+ testo:='Punti';
+ OutTextXY(7,GetMaxY-48,testo);
+ SetColor(DarkGray);
+ Line(8+TextWidth(testo),GetMaxY-50,8+TextWidth(testo),GetMaxY-40);
+ SetColor(LightBlue);
+ if Dominio then
+ OutTextXY(9+TextWidth(testo),GetMaxY-48,'Dominio');
+ SetColor(DarkGray);
+ Line(10+TextWidth(testo)+TextWidth('Dominio'),GetMaxY-50,10+TextWidth(testo)+TextWidth('Dominio'),GetMaxY-40);
+ Str(scala*5/2:4:0,testo);
+ testo:=Concat(testo,'%');
+ SetColor(Red);
+ OutTextXY(GetMaxX-TextWidth(testo)-5,GetMaxY-48,testo);
+ SetColor(DarkGray);
+ Line(12+TextWidth('Linee')+TextWidth('Dominio')+TextWidth('Radianti'),GetMaxY-50,
+ 12+TextWidth('Linee')+TextWidth('Dominio')+
+ TextWidth('Radianti'),GetMaxY-40);
+ Line(14+TextWidth('Linee')+TextWidth('Dominio')+TextWidth('Radianti')+TextWidth('Derivata'),GetMaxY-50,
+ 14+TextWidth('Linee')+
+ TextWidth('Dominio')+TextWidth('Radianti')+TextWidth('Derivata'),GetMaxY-40);
+ Line(16+TextWidth('Linee')+TextWidth('Dominio')+TextWidth('Radianti')+TextWidth('Derivata')+TextWidth('Griglia'),
+ GetMaxY-50,
+ 16+TextWidth('Linee')+TextWidth('Dominio')+TextWidth('Radianti')+TextWidth('Derivata')+TextWidth('Griglia'),
+ GetMaxY-40);
+ SetColor(Yellow);
+ if Radianti then
+ OutTextXY(12+TextWidth('Linee')+TextWidth('Dominio'),GetMaxY-48,'Radianti');
+ SetColor(LightMagenta);
+ if DisegnaDerivata then
+ OutTextXY(14+TextWidth('Linee')+TextWidth('Dominio')+TextWidth('Radianti'),GetMaxY-48,'Derivata');
+ SetColor(Red);
+ if Griglia then
+ OutTextXY(16+TextWidth('Linee')+TextWidth('Dominio')+TextWidth('Radianti')+TextWidth('Derivata'),GetMaxY-48,'Griglia');
+ SetColor(Cyan);
+ i:=18+TextWidth('Linee')+TextWidth('Dominio')+TextWidth('Radianti')+TextWidth('Derivata')+TextWidth('Griglia');
+ while (i=GetMaxX-6 then
+ begin
+ row:=AsseYx1;
+ while row>0 do
+ begin
+ col:=AsseXy1;
+ while col0 do
+ begin
+ col:=AsseXy1;
+ while col0 do
+ begin
+ col:=AsseXy1;
+ while col>0 do
+ begin
+ PutPixel(Round(row),Round(col),Red);
+ col:=col-fattore*scala/2;
+ end;
+ row:=row-fattore*scala/2;
+ end;
+ row:=AsseYx1;
+ while row>0 do
+ begin
+ col:=AsseXy1;
+ while col>0 do
+ begin
+ PutPixel(Round(row),Round(col),Red);
+ col:=col-fattore*scala/2;
+ end;
+ row:=row-fattore*scala/2;
+ end;
+ end
+ else
+ begin
+ row:=AsseYx1;
+ while row0 do
+ begin
+ col:=AsseXy1;
+ while col0 do
+ begin
+ PutPixel(Round(row),Round(col),Red);
+ col:=col-fattore*scala/2;
+ end;
+ row:=row+fattore*scala/2;
+ end;
+ row:=AsseYx1;
+ while row>0 do
+ begin
+ col:=AsseXy1;
+ while col>0 do
+ begin
+ PutPixel(Round(row),Round(col),Red);
+ col:=col-fattore*scala/2;
+ end;
+ row:=row-fattore*scala/2;
+ end;
+ end;
+end;
+(*******************************************************************)
+
+procedure DisegnaAssi;
+var
+ i:real;
+ fattore:real;
+begin
+ SetViewPort(22,30,GetMaxX-5,GetMaxY-72,ClipOn);
+ ClearViewPort;
+ SetViewPort(0,0,GetMaxX,GetMaxY,ClipOn);
+
+ if NOT Radianti then
+ fattore:=1
+ else
+ fattore:=Pi;
+
+ (*Creiamo la zona del grafico*)
+ SetColor(DarkGray);
+ SetBkColor(Black);
+ Line(23,30,GetMaxX-5,30);
+ Line(23,30,23,GetMaxY-75);
+ Line(23,GetMaxY-75,GetMaxX-5,GetMaxY-75);
+ Line(GetMaxX-5,30,GetMaxX-5,GetMaxY-75);
+
+ SetViewPort(24,31,GetMaxX-6,GetMaxY-75,ClipOn);
+
+ (*Assi cartesiani*)
+ SetColor(White);
+ Line(AsseYx1,AsseYy1,AsseYx2,AsseYy2);
+ Line(AsseXx1,AsseXy1,AsseXx2,AsseXy2);
+
+ SetColor(Brown);
+ SetLineStyle(SolidLn,1,NormWidth);
+
+ (*Costruiamo la nostra griglia sull'asse delle X*)
+ i:=AsseYx1;
+ while (i0) do
+ begin
+ Line(Round(i),AsseXy1+3,Round(i),AsseXy1-3);
+ i:=i-fattore*scala;
+ end;
+ i:=AsseYx1;
+ while (i>0) do
+ begin
+ Line(Round(i),AsseXy1+2,Round(i),AsseXy1-2);
+ i:=i-fattore*scala/2;
+ end;
+ i:=AsseYx1;
+ while (i>0) do
+ begin
+ Line(Round(i),AsseXy1+1,Round(i),AsseXy1-1);
+ i:=i-fattore*scala/4;
+ end;
+
+ (*Costruiamo la nostra griglia sull'asse delle Y*)
+ i:=AsseXy1;
+ while (i0) do
+ begin
+ Line(AsseYx1+3,Round(i),AsseYx1-3,Round(i));
+ i:=i-fattore*scala;
+ end;
+ i:=AsseXy1;
+ while (i>0) do
+ begin
+ Line(AsseYx1-2,Round(i),AsseYx1+2,Round(i));
+ i:=i-fattore*scala/2;
+ end;
+ i:=AsseXy1;
+ while (i>0) do
+ begin
+ Line(AsseYx1+1,Round(i),AsseYx1-1,Round(i));
+ i:=i-fattore*scala/4;
+ end;
+ if Griglia then
+ DisegnaGriglia;
+ DisegnaAssiSussidiari;
+end;
+(*******************************************************************)
+
+procedure DisegnaAssiSussidiari;
+var
+ i:real;
+ fattore:real;
+begin
+ (*Inizializzazione variabili*)
+ PuntiSx:=0;
+ PuntiDx:=0;
+ if NOT Radianti then
+ fattore:=1
+ else
+ fattore:=Pi;
+
+ SetViewPort(5,30,21,GetMaxY-56,ClipOn);
+ ClearViewPort;
+ SetViewPort(0,0,GetMaxX,GetMaxY,ClipOn);
+
+ SetColor(DarkGray);
+ Line(5,30,5,GetMaxY-75);
+ Line(5,30,19,30);
+ Line(19,30,19,GetMaxY-75);
+ Line(5,GetMaxY-75,19,GetMaxY-75);
+
+ SetViewPort(22,GetMaxY-72,GetMaxX-6,GetMaxY-56,ClipOn);
+ ClearViewPort;
+ SetViewPort(0,0,GetMaxX,GetMaxY,ClipOn);
+
+ Line(23,GetMaxY-72,GetMaxX-5,GetMaxY-72);
+ Line(23,GetMaxY-72,23,GetMaxY-56);
+ Line(23,GetMaxY-56,GetMaxX-5,GetMaxY-56);
+ Line(GetMaxX-5,GetMaxY-72,GetMaxX-5,GetMaxY-56);
+
+ SetColor(Brown);
+ SetLineStyle(SolidLn,1,NormWidth);
+
+ (*Costruiamo la nostra griglia sull'asse delle X*)
+ SetViewPort(23,0,GetMaxX-6,GetMaxY,ClipOn);
+ i:=AsseYx1;
+ while (i0) do
+ begin
+ Line(Round(i),GetMaxY-64,Round(i),GetMaxY-57);
+ i:=i-fattore*scala;
+ Inc(PuntiSx);
+ end;
+ i:=AsseYx1;
+ while (i>0) do
+ begin
+ Line(Round(i),GetMaxY-62,Round(i),GetMaxY-57);
+ i:=i-fattore*scala/2;
+ end;
+ i:=AsseYx1;
+ while (i>0) do
+ begin
+ Line(Round(i),GetMaxY-60,Round(i),GetMaxY-57);
+ i:=i-fattore*scala/4;
+ end;
+
+ (*Costruiamo la nostra griglia sull'asse delle Y*)
+ SetViewPort(5,30,21,GetMaxY-76,ClipOn);
+ i:=AsseXy1;
+ while (i0) do
+ begin
+ Line(1,Round(i),7,Round(i));
+ i:=i-fattore*scala;
+ end;
+ i:=AsseXy1;
+ while (i>0) do
+ begin
+ Line(1,Round(i),5,Round(i));
+ i:=i-fattore*scala/2;
+ end;
+ i:=AsseXy1;
+ while (i>0) do
+ begin
+ Line(1,Round(i),3,Round(i));
+ i:=i-fattore*scala/4;
+ end;
+ PuntiSx:=PuntiSx*3;
+ PuntiDx:=PuntiDx*3;
+ SetViewPort(0,0,GetMaxX,GetMaxY,ClipOn);
+end;
+(*******************************************************************)
+
+procedure DisegnaNumeri;
+var
+ numero:real;
+ pos:Integer;
+ testo:string;
+ aumento:Integer;
+ posRad:real;
+begin
+ SetViewPort(23,31,GetMaxX-6,GetMaxY-75,ClipOn);
+
+ SetColor(Yellow);
+ SetTextStyle(SmallFont,HorizDir,2);
+ SetTextJustify(LeftText,TopText);
+
+ if NOT Radianti then
+ begin
+ aumento:=2;
+ (*Prima parte: asse delle X*)
+ numero:=0;
+ pos:=AsseYx1+6;
+ while (pos6) do
+ begin
+ Str(numero:4:2,testo);
+ if (pos-scala>6) then
+ OutTextXY(pos-scala,AsseXy1+5,testo);
+ Dec(pos,scala*aumento);
+ numero:=numero-aumento;
+ end;
+ (*Seconda parte: asse delle Y*)
+ numero:=aumento;
+ pos:=AsseXy1+3;
+ while (pos>31) do
+ begin
+ Str(numero:4:2,testo);
+ if (TextHeight(testo)+pos-aumento*scala>31) then
+ OutTextXY(AsseYx1-TextWidth(testo)-5,pos-aumento*scala-TextHeight(testo)-5,testo);
+ Dec(pos,scala*aumento);
+ numero:=numero+aumento;
+ end;
+ numero:=aumento;
+ pos:=AsseXy1-3;
+ while (pos6) do
+ begin
+ Str(numero:4:1,testo);
+ testo:=Concat(testo,'?');
+ if (Round(posRad)-scala>6) then
+ OutTextXY(Round(posRad)-scala,AsseXy1+5,testo);
+ posRad:=posRad-scala*Pi;
+ numero:=numero-aumento;
+ end;
+ (*Seconda parte: asse delle Y*)
+ numero:=aumento;
+ posRad:=AsseXy1+3-scala*2;
+ while (posRad>31) do
+ begin
+ Str(numero:4:1,testo);
+ testo:=Concat(testo,'?');
+ if (TextHeight(testo)+Round(posRad)-aumento*scala>31) then
+ OutTextXY(AsseYx1-TextWidth(testo)-5,Round(posRad)-aumento*scala-TextHeight(testo)-5,testo);
+ posRad:=posRad-scala*Pi;
+ numero:=numero+aumento;
+ end;
+ numero:=aumento;
+ posRad:=AsseXy1-3+scala*2;
+ while (posRad-32768) AND
+ (-y+AsseXy1<32767) AND (-y+AsseXy1>-32768) then
+ begin
+ if Disegna then
+ Line(x_precedente+AsseYx1,-y_precedente+AsseXy1,x+AsseYx1,-y+AsseXy1)
+ else
+ Disegna:=True;
+ (*Salviamo i nostri valori correnti*)
+ x_precedente:=x;
+ y_precedente:=y;
+ end;
+ end
+ else
+ begin
+ if (x+AsseYx1<32767) AND (x+AsseYx1>-32768) AND
+ (-y+AsseXy1<32767) AND (-y+AsseXy1>-32768) then
+ PutPixel(x+AsseYx1,-y+AsseXy1,color);
+ end;
+end;
+(*******************************************************************)
+
+procedure Sostituisci(x:real);
+var
+ z:Integer;
+ temp: array[1..100] of string;
+begin
+ for z:=1 to 100 do
+ begin
+ numero[z]:='';
+ temp[z]:=array_funzione[z];
+ array_funzione[z]:='';
+ end;
+ for z:=1 to 100 do
+ begin
+ array_funzione[z]:=temp[z];
+ end;
+
+ (*Copiamo il nostro array in un nuovo array*)
+ for z:=1 to lunghezza_funzione do
+ begin
+ numero[z]:=array_funzione[z];
+ if (numero[z]='X') then
+ Str(x,numero[z]);
+ end;
+end;
+(*******************************************************************)
+
+procedure DisegnaDominio;
+var
+ col,row:Integer;
+begin
+ if (Round(errore_da*scala)+AsseYx1<32767) AND (Round(errore_da*scala)+AsseYx1>-32768) AND
+ (Round(errore_a*scala)+AsseYx1<32767) AND (Round(errore_a*scala)+AsseYx1>-32768) then
+ begin
+ SetColor(LightBlue);
+ Line(Round(errore_da*scala)+AsseYx1,0,Round(errore_da*scala)+AsseYx1,GetMaxY-56);
+ Line(Round(errore_a*scala)+AsseYx1,0,Round(errore_a*scala)+AsseYx1,GetMaxY-56);
+ col:=Round(errore_da*scala)+AsseYx1;
+ if errore_da>errore_a then
+ while col>Round(errore_a*scala)+AsseYx1 do
+ begin
+ row:=0;
+ while row-PuntiSx) do
+ begin
+ Sostituisci(x);
+ lunghezza:=lunghezza_funzione;
+ Errore:=False;
+ y:=CalcolaValore(1,lunghezza);
+ if (y*scala<2147483647.0) AND (y*scala>-2147483648.0) AND NOT Errore then
+ begin
+ if Limita then
+ begin
+ if (x*scalasx*scala) AND flag then
+ DisegnaValore(Round(x*scala),Round(y*scala),LightGreen);
+ end
+ else if NOT Limita AND flag then
+ DisegnaValore(Round(x*scala),Round(y*scala),LightGreen);
+ if (k=4) AND ((Limita AND (x*scalasx*scala)) OR
+ NOT Limita) then
+ begin
+ array_x[num_valori]:=x*scala;
+ if y<0 then
+ y:=-y;
+ array_y[num_valori]:=y*scala;
+ k:=1;
+ Inc(num_valori);
+ end
+ else if k<>4 then
+ Inc(k);
+ end;
+ if Errore then
+ begin
+ if NOT NonNelDominio then
+ begin
+ Disegna:=False;
+ FuoriDominio:=True;
+ errore_da:=x;
+ errore_a:=x;
+ NonNelDominio:=True;
+ end
+ else
+ begin
+ errore_a:=x;
+ end;
+ end
+ else
+ begin
+ if NonNelDominio AND Dominio then
+ DisegnaDominio;
+ FuoriDominio:=False;
+ NonNelDominio:=False;
+ end;
+ x:=x-h;
+ end;
+ if Dominio AND FuoriDominio then
+ DisegnaDominio;
+ (*... e dal centro a destra*)
+ x_precedente:=0;
+ y_precedente:=0;
+ Disegna:=False;
+ FuoriDominio:=False;
+ NonNelDominio:=False;
+ x:=0;
+ while (x-2147483648.0) AND NOT Errore then
+ begin
+ if Limita then
+ begin
+ if (x*scalasx*scala) AND flag then
+ DisegnaValore(Round(x*scala),Round(y*scala),LightGreen);
+ end
+ else if NOT Limita AND flag then
+ DisegnaValore(Round(x*scala),Round(y*scala),LightGreen);
+ if (k=4) AND ((Limita AND (x*scalasx*scala)) OR
+ NOT Limita) then
+ begin
+ array_x[num_valori]:=x*scala;
+ if y<0 then
+ y:=-y;
+ array_y[num_valori]:=y*scala;
+ k:=1;
+ Inc(num_valori);
+ end
+ else if k<>4 then
+ Inc(k);
+ end;
+ if Errore then
+ begin
+ if NOT NonNelDominio then
+ begin
+ Disegna:=False;
+ FuoriDominio:=True;
+ errore_da:=x;
+ errore_a:=x;
+ NonNelDominio:=True;
+ end
+ else
+ begin
+ errore_a:=x;
+ end;
+ end
+ else
+ begin
+ if NonNelDominio AND Dominio then
+ DisegnaDominio;
+ FuoriDominio:=False;
+ NonNelDominio:=False;
+ end;
+ x:=x+h;
+ end;
+ if Dominio AND FuoriDominio then
+ DisegnaDominio;
+
+ lunghezza:=lunghezza_funzione;
+ for z:=1 to 100 do
+ begin
+ numero[z]:='';
+ temp[z]:=array_funzione[z];
+ array_funzione[z]:='';
+ end;
+ for z:=1 to 100 do
+ begin
+ array_funzione[z]:=temp[z];
+ end;
+ x_precedente:=0;
+ y_precedente:=0;
+ Disegna:=False;
+end;
+(*******************************************************************)
+
+procedure DisegnaMascherinaRotazione;
+begin
+ SetViewPort(5,GetMaxY-35,GetMaxX-5,GetMaxY,ClipOn);
+ ClearViewPort;
+ SetViewPort(0,0,GetMaxX,GetMaxY,ClipOn);
+ SetColor(DarkGray);
+ SetBkColor(Black);
+ Line(5,GetMaxY-35,GetMaxX-5,GetMaxY-35);
+ Line(5,GetMaxY-35,5,GetMaxY-5);
+ Line(GetMaxX-5,GetMaxY-35,GetMaxX-5,GetMaxY-5);
+ Line(5,GetMaxY-5,GetMaxX-5,GetMaxY-5);
+ SetColor(White);
+ SetTextStyle(SmallFont,HorizDir,4);
+ SetTextJustify(LeftText,TopText);
+ OutTextXY(15,GetMaxY-35,'F1/F2 - Zoom +/-');
+ OutTextXY(15,GetMaxY-20,'F3 - Punti/Linee');
+ OutTextXY(160,GetMaxY-35,'F5/F6 - Risoluzione +/-');
+ OutTextXY(160,GetMaxY-20,'F10 - Griglia');
+ OutTextXY(325,GetMaxY-35,'INVIO - Grafico');
+ OutTextXY(325,GetMaxY-20,'ESC - Esci');
+end;
+(*******************************************************************)
+
+procedure VisualizzaGrafico;
+var
+ c:Char;
+ LowMode,HiMode:Integer;
+begin
+ repeat
+ (*Registrazione dei drivers grafici*)
+ if RegisterBGIdriver(@CGADriverProc)<0 then
+ Abort('CGA');
+ if RegisterBGIdriver(@EGAVGADriverProc)<0 then
+ Abort('EGA/VGA');
+ if RegisterBGIdriver(@HercDriverProc)<0 then
+ Abort('Herc');
+ if RegisterBGIdriver(@ATTDriverProc)<0 then
+ Abort('AT&T');
+ if RegisterBGIdriver(@PC3270DriverProc)<0 then
+ Abort('PC 3270');
+
+ (*Registrazione dei font*)
+ if RegisterBGIfont(@GothicFontProc)<0 then
+ Abort('Gothic');
+ if RegisterBGIfont(@SansSerifFontProc)<0 then
+ Abort('SansSerif');
+ if RegisterBGIfont(@SmallFontProc)<0 then
+ Abort('Small');
+ if RegisterBGIfont(@TriplexFontProc)<0 then
+ Abort('Triplex');
+
+ grDriver:=Detect;
+ InitGraph(grDriver,grMode,path);
+ ErrCode:=GraphResult;
+ if ErrCode<>grOK then
+ begin
+ if ErrCode=grFileNotFound then
+ begin
+ (*Creiamo la nostra finestra*)
+ Window(1,1,80,25);
+ TextBackground(Black);
+ TextColor(LightGray);
+ ClrScr;
+ Writeln('Errore grafico: ', GraphErrorMsg(ErrCode));
+ Writeln;
+ Writeln('Se non si desidera immettere il percorso dei drivers ora, premere Esc');
+ c:=ReadChar;
+ if ord(c)<>27 then
+ begin
+ Writeln('Inserire il percorso dei drivers BGI:');
+ WriteLn;
+ Readln(path);
+ end
+ else
+ ErrCode:=grOK;
+ end
+ else
+ begin
+ Writeln('Errore grafico: ', GraphErrorMsg(ErrCode));
+ Delay(5000);
+ Halt(1);
+ end;
+ end;
+ until ErrCode=grOK;
+
+ (*Impostiamo alcune caratteristiche della modalit? grafica*)
+ GetModeRange(grDriver,LowMode,HiMode);
+ SetGraphMode(HiMode);
+
+ if ord(c)<>27 then
+ begin
+ if Grafico_Rotazione then
+ Grafico
+ else
+ Rotazione;
+ end;
+ CloseGraph;
+end;
+(*******************************************************************)
+
+procedure Grafico;
+var
+ ch:Char;
+ done:Boolean;
+begin
+ if NOT InizializzatoX then
+ begin
+ AsseXx1:=0;
+ AsseXy1:=GetMaxY div 2;
+ AsseXx2:=GetMaxX;
+ AsseXy2:=GetMaxY div 2;
+ InizializzatoX:=True;
+ end;
+ if NOT InizializzatoY then
+ begin
+ AsseYx1:=GetMaxX div 2;
+ AsseYy1:=0;
+ AsseYx2:=GetMaxX div 2;
+ AsseYy2:=GetMaxY;
+ InizializzatoY:=True;
+ end;
+ DisegnaAssi;
+ DisegnaNumeri;
+ DisegnaMascherinaInformazioni;
+ DisegnaMascherinaTasti;
+ DisegnaTitolo('Grafico di Y=');
+ DisegnaGrafico(True);
+ Derivata;
+ done:=False;
+ repeat
+ ch:=ReadChar;
+ case ch of
+ #13: (*CR*)
+ begin
+ done:=True;
+ (*Richiamo della procedura*)
+ Rotazione;
+ end;
+ #27: (*ESC*)
+ done:=True;
+ #59: (*F1*)
+ begin
+ if scala<640 then
+ begin
+ scala:=scala*2;
+ DisegnaMascherinaInformazioni;
+ DisegnaAssi;
+ DisegnaNumeri;
+ DisegnaGrafico(True);
+ Derivata;
+ end
+ else
+ Beep;
+ end;
+ #60: (*F2*)
+ begin
+ if scala>20 then
+ begin
+ scala:=scala div 2;
+ DisegnaMascherinaInformazioni;
+ DisegnaAssi;
+ DisegnaNumeri;
+ DisegnaGrafico(True);
+ Derivata;
+ end
+ else
+ Beep;
+ end;
+ #61: (*F3*)
+ begin
+ Linee:=NOT Linee;
+ DisegnaMascherinaInformazioni;
+ if NOT Linee then
+ begin
+ DisegnaAssi;
+ DisegnaNumeri;
+ end;
+ DisegnaGrafico(True);
+ Derivata;
+ end;
+ #62: (*F4*)
+ begin
+ Radianti:=NOT Radianti;
+ DisegnaMascherinaInformazioni;
+ DisegnaAssi;
+ DisegnaNumeri;
+ DisegnaGrafico(True);
+ Derivata;
+ end;
+ #63: (*F5*)
+ begin
+ if risoluzione>1 then
+ begin
+ risoluzione:=risoluzione div 2;
+ DisegnaMascherinaInformazioni;
+ DisegnaAssi;
+ DisegnaNumeri;
+ DisegnaGrafico(True);
+ Derivata;
+ end
+ else
+ Beep;
+ end;
+ #64: (*F6*)
+ begin
+ if risoluzione-2147483648.0) AND (Round(y*scala)=0)) then
+ begin
+ Disegna:=False;
+ Errore:=False;
+ Sostituisci(x);
+ lunghezza:=lunghezza_funzione;
+ y:=CalcolaValore(1,lunghezza);
+ if NOT Errore then
+ begin
+ PutPixel(AsseYx1+Round(x*scala),AsseXy1-Round(y*scala),White);
+ PutPixel(AsseYx1+Round(x*scala)-1,AsseXy1-Round(y*scala)-1,White);
+ PutPixel(AsseYx1+Round(x*scala),AsseXy1-Round(y*scala)-1,White);
+ PutPixel(AsseYx1+Round(x*scala)-1,AsseXy1-Round(y*scala),White);
+ end;
+ end
+ else if (y*scala<2147483647.0) AND (y*scala>-2147483648.0) AND NOT Errore then
+ begin
+ if Limita then
+ begin
+ if (x*scalasx*scala) then
+ DisegnaValore(Round(x*scala),Round(y*scala),LightMagenta);
+ end
+ else if NOT Limita then
+ DisegnaValore(Round(x*scala),Round(y*scala),LightMagenta)
+ end
+ else if Errore then
+ Disegna:=False;
+ end
+ else
+ Disegna:=False;
+ x:=x+h;
+ end;
+
+ (*... e dal centro a sinistra*)
+ Disegna:=False;
+ x_precedente:=0;
+ y_precedente:=0;
+ x:=0;
+ while x>-PuntiSx do
+ begin
+ Disegna:=False;
+ Errore:=False;
+ Sostituisci(x+0.01);
+ lunghezza:=lunghezza_funzione;
+ y1:=CalcolaValore(1,lunghezza);
+ if Errore then
+ begin
+ Errore:=False;
+ Sostituisci(x);
+ lunghezza:=lunghezza_funzione;
+ y:=CalcolaValore(1,lunghezza);
+ if NOT Errore then
+ begin
+ PutPixel(AsseYx1+Round(x*scala),AsseXy1-Round(y*scala),White);
+ PutPixel(AsseYx1+Round(x*scala)-1,AsseXy1-Round(y*scala)-1,White);
+ PutPixel(AsseYx1+Round(x*scala),AsseXy1-Round(y*scala)-1,White);
+ PutPixel(AsseYx1+Round(x*scala)-1,AsseXy1-Round(y*scala),White);
+ end;
+ end
+ else if NOT Errore then
+ begin
+ Sostituisci(x-0.01);
+ lunghezza:=lunghezza_funzione;
+ y2:=CalcolaValore(1,lunghezza);
+ y:=(y1-y2)/0.02;
+ if (Errore) OR ((y*scala<2147483647.0) AND (y*scala>-2147483648.0) AND (Round(y*scala)=0)) then
+ begin
+ Disegna:=False;
+ Errore:=False;
+ Sostituisci(x);
+ lunghezza:=lunghezza_funzione;
+ y:=CalcolaValore(1,lunghezza);
+ if NOT Errore then
+ begin
+ PutPixel(AsseYx1+Round(x*scala),AsseXy1-Round(y*scala),White);
+ PutPixel(AsseYx1+Round(x*scala)-1,AsseXy1-Round(y*scala)-1,White);
+ PutPixel(AsseYx1+Round(x*scala),AsseXy1-Round(y*scala)-1,White);
+ PutPixel(AsseYx1+Round(x*scala)-1,AsseXy1-Round(y*scala),White);
+ end;
+ end
+ else if (y*scala<2147483647.0) AND (y*scala>-2147483648.0) AND NOT Errore then
+ begin
+ if Limita then
+ begin
+ if (x*scalasx*scala) then
+ DisegnaValore(Round(x*scala),Round(y*scala),LightMagenta);
+ end
+ else if NOT Limita then
+ DisegnaValore(Round(x*scala),Round(y*scala),LightMagenta)
+ end
+ else if Errore then
+ Disegna:=False;
+ end
+ else
+ Disegna:=False;
+ x:=x-h;
+ end;
+
+ lunghezza:=lunghezza_funzione;
+ for z:=1 to 100 do
+ begin
+ numero[z]:='';
+ temp[z]:=array_funzione[z];
+ array_funzione[z]:='';
+ end;
+ for z:=1 to 100 do
+ begin
+ array_funzione[z]:=temp[z];
+ end;
+ x_precedente:=0;
+ y_precedente:=0;
+ (*Ripristiniamo i valori salvati*)
+ Linee:=old_linee;
+ end;
+end;
+(*******************************************************************)
+
+procedure RuotaCurva;
+var
+ theta,alpha,n,i,k:Integer;
+ x_succ1,y_succ1,x_succ2,y_succ2,x_prec,y_prec,x,y:extended;
+ sin_look,cos_look:array[1..360] of real;
+ temp:real;
+ Congiungi:Boolean;
+begin
+ (*Preparazione delle SIN e COS lookup tables*)
+ for i:=1 to 360 do
+ begin
+ sin_look[i]:=sin(i*Pi/180);
+ cos_look[i]:=cos(i*Pi/180);
+ end;
+
+ (*Inizializzazione di alcune variabili*)
+ alpha:=330;
+ theta:=1;
+ x_prec:=0;
+ y_prec:=0;
+ Congiungi:=False;
+
+ (*Impostiamo il colore ed il tipo di fill*)
+ SetColor(Yellow);
+ SetFillStyle(SolidFill,LightBlue);
+
+ (*Impostiamo la zona di schermo in cui disegneremo*)
+ SetViewPort(24,31,GetMaxX-6,GetMaxY-76,ClipOn);
+
+ (*Ordiniamo i nostri arrays di valori (in base alla x, ordine crescente)*)
+ for i:=1 to num_valori-1 do
+ begin
+ for k:=i+1 to num_valori-1 do
+ if array_x[i]>array_x[k] then
+ begin
+ temp:=array_x[i];
+ array_x[i]:=array_x[k];
+ array_x[k]:=temp;
+ temp:=array_y[i];
+ array_y[i]:=array_y[k];
+ array_y[k]:=temp;
+ end;
+ end;
+
+ (*Controllo sui valori immagazzinati*)
+ k:=num_valori-1;
+ for i:=1 to k do
+ begin
+ if (AsseXy1-array_y[i]<0) OR (AsseXy1-array_y[i]>GetMaxY)
+ OR (AsseYx1-array_x[i]<0) OR (AsseYx1-array_x[i]>GetMaxX) then
+ begin
+ for n:=i to k do
+ begin
+ array_x[n]:=array_x[n+1];
+ array_y[n]:=array_y[n+1];
+ end;
+ Dec(num_valori);
+ Dec(i);
+ end;
+ end;
+
+ (*Avevamo incrementato di un valore in pi? la variabile "num_valori" durante il salvataggio dei punti*)
+ Dec(num_valori);
+
+ (*Ciclo per il calcolo ed il disegno dei punti sullo schermo*)
+ while alpha>=180 do
+ begin
+ for i:=1 to num_valori do
+ begin
+ x:=array_x[i]-array_y[i]*sin_look[alpha]*sin_look[theta];
+ y:=array_y[i]*cos_look[alpha]-array_y[i]*sin_look[alpha]*cos_look[theta];
+ if (AsseXy1-Round(y)>-32768) AND (AsseXy1-Round(y)<32767) then
+ begin
+ if NOT Linee then
+ begin
+ PutPixel(AsseYx1+Round(x),AsseXy1-Round(y),Yellow);
+ end
+ else
+ begin
+ if Congiungi then
+ begin
+ if (AsseXy1-Round(y_prec)>-32768) AND (AsseXy1-Round(y_prec)<32767) then
+ begin
+ vertici[1].x:=AsseYx1+Round(x);
+ vertici[1].y:=AsseXy1-Round(y);
+ vertici[2].x:=AsseYx1+Round(x_prec);
+ vertici[2].y:=AsseXy1-Round(y_prec);
+ if (i>0) then
+ begin
+ x_succ1:=array_x[i]-array_y[i]*sin_look[alpha-5]*sin_look[theta];
+ y_succ1:=array_y[i]*cos_look[alpha-5]-array_y[i]*sin_look[alpha-5]
+ *cos_look[theta];
+ x_succ2:=array_x[i-1]-array_y[i-1]*sin_look[alpha-5]
+ *sin_look[theta];
+ y_succ2:=array_y[i-1]*cos_look[alpha-5]-array_y[i-1]
+ *sin_look[alpha-5]*cos_look[theta];
+ if (x_succ1>-32768) AND (x_succ1<32767) AND (y_succ1>-32768) AND
+ (y_succ1<32767) AND (x_succ2>-32768)
+ AND (x_succ2<32767) AND (y_succ2>-32768) AND (y_succ2<32767)
+ then
+ begin
+ vertici[3].x:=AsseYx1+Round(x_succ2);
+ vertici[3].y:=AsseXy1-Round(y_succ2);
+ vertici[4].x:=AsseYx1+Round(x_succ1);
+ vertici[4].y:=AsseXy1-Round(y_succ1);
+ FillPoly(4,vertici);
+ end;
+ end;
+ end
+ else
+ Congiungi:=False;
+ end
+ else
+ Congiungi:=True;
+ end;
+ end;
+ x_prec:=x;
+ y_prec:=y;
+ end;
+ Dec(alpha,5);
+ Congiungi:=False;
+ end;
+end;
+
+(********************************************************************
+* Funzioni e procedure per le finestre del programma
+********************************************************************)
+
+function ReadChar:Char;
+var
+ ch:Char;
+begin
+ ch:=ReadKey;
+ if ch=#0 then
+ ch:=ReadKey;
+ ReadChar:=ch;
+end;
+(*******************************************************************)
+
+procedure Beep;
+begin
+ NoSound;
+ Sound(2000);
+ Delay(150);
+ NoSound;
+end;
+(*******************************************************************)
+
+procedure SchermataDiBenvenuto;
+var
+ c:Char;
+begin
+ (*Creiamo la nostra finestra*)
+ Window(1,1,80,25);
+ TextBackground(Black);
+ TextColor(LightBlue);
+ ClrScr;
+ Writeln(' ANALIZZATORE DI FUNZIONI MATEMATICHE - 4');
+ Writeln(' di Marco Olivo, 1998,1999');
+ Writeln;
+ Writeln;
+ TextColor(Yellow);
+ Writeln(' Questo programma ? in grado di tracciare il grafico approssimato di una');
+ Writeln(' qualsiasi funzione. Queste sono le funzioni permesse dal programma:');
+ Writeln;
+ TextColor(White);
+ Writeln(' arcsen/arcsin(x) ????????> arco-seno di x');
+ Writeln(' arccos(x) ????????> arco-coseno di x');
+ Writeln(' arccotg/arccotag/arccotan(x) ????????> arco-cotangente di x');
+ Writeln(' sen/sin(x) ????????> seno di x');
+ Writeln(' cos(x) ????????> coseno di x');
+ Writeln(' tan/tag/tg(x) ????????> tangente di x');
+ Writeln(' arctan/arctag/atag/atan ????????> arco-tangente di x');
+ Writeln(' cotan/cotag/cotg(x) ????????> cotangente di x');
+ Writeln(' log/ln(x) ????????> logaritmo naturale di x');
+ Writeln(' a^x,e^x ????????> elevamento ad esponente x');
+ Writeln(' abs,sgn(x) ????????> valore assoluto, segno di x');
+ Writeln(' sqr,sqrt(x) ????????> quadrato, radice quadrata');
+ Writeln(' sinh,cosh,tanh(x) ????????> sin, cos, tan iperbolici');
+ Writeln(' asinh,acosh,atanh(x) ????????> asin, acos, atan iperbolici');
+ Writeln(' int(x) ????????> parte intera di x');
+ Writeln;
+ TextColor(LightCyan+Blink);
+ Writeln(' Premere un tasto per iniziare il programma');
+ Beep;
+ c:=ReadKey;
+end;
+(*******************************************************************)
+
+procedure Messaggio(testo:string);
+var
+ lunghezza_messaggio:Integer;
+ k:Integer;
+begin
+ TextColor(Yellow);
+ TextBackground(Blue);
+ Window(2,24,79,25);
+ GotoXY(1,1);
+ Write(' ');
+ lunghezza_messaggio:=Length(testo);
+ if (lunghezza_messaggio<=75) then
+ begin
+ Write(testo);
+ for k:=1+lunghezza_messaggio to 77 do
+ Write(' ');
+ end;
+end;
+(*******************************************************************)
+
+procedure MenuPrincipale;
+begin
+ TextBackground(Black);
+ TextColor(Yellow);
+ Window(1,1,80,25);
+ GotoXY(25,4);
+ Write('Men? principale');
+
+ (*Creiamo la nostra finestra*)
+ Window(4,5,58,21);
+ TextBackground(Black);
+ ClrScr;
+ (*Scriviamo nella nostra finestra*)
+ TextColor(LightGreen);
+ GotoXY(12,17);
+ Write('Freccia Su/Gi?: cambiamento funzione');
+ TextColor(White);
+ GotoXY(10,2);
+ Write('nserimento della funzione');
+ GotoXY(10,4);
+ Write('isualizzazione del grafico della funzione');
+ GotoXY(10,5);
+ Write('strapolazione dei punti dal grafico');
+ GotoXY(10,6);
+ Write('imitazione del dominio');
+ GotoXY(10,7);
+ Write('otazione della curva');
+ GotoXY(9,9);
+ Write('Informazioni/ uida');
+ GotoXY(9,10);
+ Write('V lori di default');
+ GotoXY(10,12);
+ Write('alvare lista funzioni');
+ GotoXY(10,13);
+ Write('aricare lista funzioni');
+ GotoXY(10,15);
+ Write('scita');
+ TextColor(LightRed);
+ GotoXY(9,2);
+ Write('I');
+ GotoXY(9,4);
+ Write('V');
+ GotoXY(9,5);
+ Write('E');
+ GotoXY(9,6);
+ Write('L');
+ GotoXY(9,7);
+ Write('R');
+ GotoXY(22,9);
+ Write('g');
+ GotoXY(10,10);
+ Write('a');
+ GotoXY(9,12);
+ Write('S');
+ GotoXY(9,13);
+ Write('C');
+ GotoXY(9,15);
+ Write('U');
+end;
+(*******************************************************************)
+
+procedure InserisciFunzione(espressione:string);
+var
+ i:Integer;
+ posizione:Integer;
+ ch:Char;
+ done:Boolean;
+ funzione_inserita,tasto:string;
+begin
+ TextBackground(Black);
+ TextColor(Yellow);
+ Window(1,1,80,25);
+ GotoXY(22,4);
+ Write('Inserimento funzione');
+
+ (*Creiamo la nostra finestra*)
+ Window(4,5,58,21);
+ TextBackground(Black);
+ ClrScr;
+ TextColor(White);
+ (*Richiediamo la funzione*)
+ Writeln;
+ Writeln('Immettere la funzione y=f(x) da valutare:');
+ Writeln;
+ TextColor(LightGray);
+ Writeln('y=');
+ TextColor(LightGreen);
+ GotoXY(15,16);
+ Writeln('Freccia Su/Gi?: cambiamento funzione');
+ GotoXY(25,17);
+ Write('Esc: esci');
+ TextColor(LightGray);
+ GotoXY(3,4);
+ funzione:='';
+ funzione_inserita:=espressione;
+ if espressione<>'' then
+ Write(espressione)
+ else
+ begin
+ Write(lista_funzioni[funzione_corrente]);
+ funzione_inserita:=lista_funzioni[funzione_corrente];
+ end;
+ posizione:=Length(funzione_inserita)+2;
+ done:=False;
+ GotoXY(1+posizione,4);
+
+ repeat
+ ch:=ReadChar;
+ case ch of
+ #8: (*BS*)
+ begin
+ if posizione>2 then
+ begin
+ tasto:='';
+ for i:=1 to (posizione-3) do
+ tasto:=Concat(tasto,funzione_inserita[i]);
+ funzione_inserita:=tasto;
+ (*Creiamo la nostra finestra*)
+ Window(4,5,58,21);
+ TextColor(LightGray);
+ TextBackground(Black);
+ GotoXY(posizione,4);
+ Write(' ');
+ Dec(posizione);
+ GotoXY(1+posizione,4);
+ end;
+ if posizione=2 then
+ funzione_inserita:='';
+ end;
+ #13: (*CR*)
+ done:=True;
+ #27: (*ESC*)
+ begin
+ done:=True;
+ funzione_inserita:='';
+ end;
+ #72: (*Freccia in alto*)
+ begin
+ if funzione_corrente>1 then
+ begin
+ SelezionaFunzione(funzione_corrente-1,funzione_corrente);
+ Dec(funzione_corrente);
+ if lista_funzioni[funzione_corrente]<>'' then
+ Messaggio(lista_funzioni[funzione_corrente])
+ else
+ Messaggio('Consultare la guida in linea per maggiori informazioni sul programma');
+ (*Creiamo la nostra finestra*)
+ Window(4,5,58,21);
+ TextColor(LightGray);
+ TextBackground(Black);
+ for i:=3 to 57 do
+ begin
+ GotoXY(i,4);
+ Write(' ');
+ end;
+ GotoXY(3,4);
+ Write(lista_funzioni[funzione_corrente]);
+ funzione_inserita:=lista_funzioni[funzione_corrente];
+ posizione:=Length(funzione_inserita)+2;
+ GotoXY(1+posizione,4);
+ end
+ else
+ Beep;
+ end;
+ #75,#77: (*Freccia a sinistra, freccia a destra*)
+ Beep;
+ #80: (*Freccia in basso*)
+ begin
+ if funzione_corrente<16 then
+ begin
+ SelezionaFunzione(funzione_corrente+1,funzione_corrente);
+ Inc(funzione_corrente);
+ if lista_funzioni[funzione_corrente]<>'' then
+ Messaggio(lista_funzioni[funzione_corrente])
+ else
+ Messaggio('Consultare la guida in linea per maggiori informazioni sul programma');
+ (*Creiamo la nostra finestra*)
+ Window(4,5,58,21);
+ TextColor(LightGray);
+ TextBackground(Black);
+ for i:=3 to 57 do
+ begin
+ GotoXY(i,4);
+ Write(' ');
+ end;
+ GotoXY(3,4);
+ Write(lista_funzioni[funzione_corrente]);
+ funzione_inserita:=lista_funzioni[funzione_corrente];
+ posizione:=Length(funzione_inserita)+2;
+ GotoXY(1+posizione,4);
+ end
+ else
+ Beep;
+ end;
+ else
+ case ch of
+ 'A'..'Z','a'..'z','0'..'9','+', '-', '*', '/','^','(',')':
+ begin
+ if posizione<54 then
+ begin
+ tasto:=ch;
+ funzione_inserita:=Concat(funzione_inserita,tasto);
+ Inc(posizione);
+ (*Creiamo la nostra finestra*)
+ Window(4,5,58,21);
+ TextColor(LightGray);
+ TextBackground(Black);
+ GotoXY(posizione,4);
+ Write(tasto);
+ end
+ else
+ Beep;
+ end;
+ else
+ Beep;
+ end;
+ end;
+ until done;
+ if funzione_inserita='' then
+ funzione_inserita:=lista_funzioni[funzione_corrente];
+ lunghezza:=Length(funzione_inserita);
+ funzione:=funzione_inserita;
+ if lunghezza>0 then
+ begin
+ (*Facciamo di modo che la nostra stringa sia tutta in maiuscolo*)
+ for i:=1 to lunghezza do
+ funzione[i]:=UpCase(funzione_inserita[i]);
+ LeggiFunzione;
+ if (ControllaSintassi=True) then
+ begin
+ CalcolaPrecedenze;
+ (*Scriviamo la funzione nel nostro array delle ultime 16 funzioni*)
+ lista_funzioni[funzione_corrente]:=funzione_inserita;
+ if numero_funzioni'' then
+ begin
+ Val(ascissa,number,code);
+ if code=0 then
+ begin
+ lunghezza_funzione:=lunghezza;
+ Sostituisci(number);
+ TextColor(Red);
+ Writeln;
+ Errore:=False;
+ lunghezza_funzione:=lunghezza;
+ valore:=CalcolaValore(1,lunghezza);
+ if NOT Errore then
+ Writeln('L''ordinata del punto scelto ?: ',valore:8:8)
+ else
+ Writeln('Il valore scelto non appartiene al dominio');
+ lunghezza:=lunghezza_funzione;
+ end
+ else
+ begin
+ TextColor(Yellow+Blink);
+ TextBackground(Red);
+ Writeln;
+ Writeln(' Errore: il valore inserito non ? un numero reale ');
+ end;
+ c:=ReadKey;
+ end;
+end;
+(*******************************************************************)
+
+procedure LimitaDominio;
+var
+ margine_dx,margine_sx:string;
+ code1,code2:Integer;
+ c:Char;
+begin
+ TextBackground(Black);
+ TextColor(Yellow);
+ Window(1,1,80,25);
+ GotoXY(20,4);
+ Write('Limitazione del dominio');
+
+ (*Creiamo la nostra finestra*)
+ Window(4,5,58,21);
+ TextBackground(Black);
+ ClrScr;
+ TextColor(White);
+ if Conferma('Si ? proprio sicuri di voler limitare il dominio?') then
+ begin
+ ClrScr;
+ Writeln;
+ Writeln('Inserire l''estremo sinistro:');
+ Writeln;
+ TextColor(LightGray);
+ Readln(margine_sx);
+ Writeln;
+ TextColor(White);
+ Writeln('Inserire l''estremo destro:');
+ Writeln;
+ TextColor(LightGray);
+ Readln(margine_dx);
+ Val(margine_sx,sx,code1);
+ Val(margine_dx,dx,code2);
+ if (code1=0) AND (code2=0) then
+ begin
+ if sx>dx then
+ begin
+ TextColor(Yellow+Blink);
+ TextBackground(Red);
+ Writeln;
+ Writeln(' Errore: il margine SX ? maggiore del margine DX ');
+ Limita:=False;
+ c:=ReadKey;
+ end
+ else
+ Limita:=True;
+ end
+ else
+ begin
+ TextColor(Yellow+Blink);
+ TextBackground(Red);
+ Writeln;
+ Writeln(' Errore: il valore non ? reale ');
+ Limita:=False;
+ c:=ReadKey;
+ end;
+ end
+ else
+ Limita:=False;
+end;
+(*******************************************************************)
+
+procedure Informazioni_Guida;
+begin
+ SchermataDiBenvenuto;
+end;
+(*******************************************************************)
+
+function Conferma(testo:string):Boolean;
+var
+ ch:Char;
+ done,scelta:Boolean;
+begin
+ (*Creiamo la nostra finestra*)
+ Window(4,5,58,21);
+ TextBackground(Black);
+ ClrScr;
+ TextColor(LightGray);
+ (*Scriviamo nella nostra finestra*)
+ Writeln;
+ Writeln(testo);
+ TextBackground(Red);
+ TextColor(Black);
+ GotoXY(18,6);
+ Write(' S? ');
+ TextBackground(Black);
+ TextColor(White);
+ GotoXY(32,6);
+ Write(' No ');
+ done:=False;
+ scelta:=True;
+ repeat
+ ch:=ReadChar;
+ case ch of
+ #13: (*CR*)
+ begin
+ done:=True;
+ scelta:=scelta;
+ end;
+ #27: (*ESC*)
+ begin
+ done:=True;
+ scelta:=False;
+ end;
+ 's','S':
+ begin
+ done:=True;
+ scelta:=True;
+ end;
+ 'n','N':
+ begin
+ done:=True;
+ scelta:=False;
+ end;
+ #75: (*Freccia a sinistra*)
+ begin
+ scelta:=True;
+ TextBackground(Red);
+ TextColor(Black);
+ GotoXY(18,6);
+ Write(' S? ');
+ TextBackground(Black);
+ TextColor(White);
+ GotoXY(32,6);
+ Write(' No ');
+ end;
+ #77: (*Freccia a destra*)
+ begin
+ scelta:=False;
+ TextBackground(Black);
+ TextColor(White);
+ GotoXY(18,6);
+ Write(' S? ');
+ TextBackground(Red);
+ TextColor(Black);
+ GotoXY(32,6);
+ Write(' No ');
+ end;
+ else
+ Beep;
+ end;
+ until done;
+ Conferma:=scelta;
+end;
+(*******************************************************************)
+
+function ConfermaUscita:Boolean;
+begin
+ if (Conferma('Si ? proprio sicuri di voler uscire dal programma?')=True) then
+ ConfermaUscita:=True
+ else
+ ConfermaUscita:=False;
+end;
+(*******************************************************************)
+
+procedure ImpostaValoriDiDefault;
+begin
+ (*Assegnazione dei valori standard delle posizioni degli assi*)
+ AsseXx1:=0;
+ AsseXy1:=GetMaxY div 2;
+ AsseXx2:=GetMaxX;
+ AsseXy2:=GetMaxY div 2;
+ AsseYx1:=GetMaxX div 2;
+ AsseYy1:=0;
+ AsseYx2:=GetMaxX div 2;
+ AsseYy2:=GetMaxY;
+
+ risoluzione:=1; (*Vicinanza dei punti del grafico*)
+ scala:=40; (*Scala del grafico (100%)*)
+ Linee:=False; (*Grafico a punti o linee (punti)*)
+ Dominio:=True; (*Disegnamo il dominio*)
+ Radianti:=False; (*Numeri interi sul grafico*)
+ Limita:=False; (*Dominio non limitato*)
+ DisegnaDerivata:=False; (*Non disegnamo la derivata*)
+ path:='a:\'; (*Directory dei drivers BGI*)
+ Grafico_Rotazione:=True; (*Visualizziamo il grafico e non la rotazione*)
+ Griglia:=True; (*Visualizziamo la griglia*)
+end;
+(*******************************************************************)
+
+procedure ImpostaDefault;
+begin
+ TextBackground(Black);
+ TextColor(Yellow);
+ Window(1,1,80,25);
+ GotoXY(20,4);
+ Write('Impostazione valori di default');
+
+ if (Conferma('Con questa operazione si elimineranno tutti i settaggi correnti. Continuare?')=True) then
+ begin
+ (*Imposta i valori di default*)
+ ImpostaValoriDiDefault;
+ end;
+end;
+(*******************************************************************)
+
+function FileExists(FileName:string):Boolean;
+var
+ f:file;
+begin
+ (*"Input/Output Checking Switch": attiva la generazione di codice che
+ controlla i risultati delle chiamate a procedure di I/O*)
+ {$I-}
+ Assign(f, FileName);
+ Reset(f);
+ Close(f);
+ (*"Input/Output Checking Switch": (ri)attiva la generazione di codice che
+ controlla i risultati delle chiamate a procedure di I/O*)
+ {$I+}
+ FileExists:=(IOResult=0) AND (FileName<>'');
+end;
+(*******************************************************************)
+
+procedure CaricaListaFunzioni(FileName:string);
+var
+ f:Text;
+ i:Integer;
+ str:string;
+begin
+ i:=1;
+ TextColor(LightRed);
+ if FileExists(FileName) then
+ begin
+ for i:=1 to 16 do
+ lista_funzioni[i]:='';
+ funzione_corrente:=1;
+ numero_funzioni:=0;
+ Assign(f,FileName);
+ Reset(f);
+ Readln(f,str);
+ lista_funzioni[funzione_corrente]:=str;
+ Inc(funzione_corrente);
+ Inc(numero_funzioni);
+ while NOT Eof(f) do
+ begin
+ Readln(f,str);
+ if (funzione_corrente<17) AND (numero_funzioni<17) then
+ begin
+ lista_funzioni[funzione_corrente]:=str;
+ Inc(funzione_corrente);
+ Inc(numero_funzioni);
+ end;
+ end;
+ Close(f);
+ end
+ else
+ FileDelleFunzioni:='';
+end;
+(*******************************************************************)
+
+procedure SalvaListaFunzioni(FileName:string);
+var
+ f:Text;
+ i:Integer;
+begin
+ Assign(f,FileName);
+ Rewrite(f);
+ for i:=1 to numero_funzioni do
+ if lista_funzioni[i]<>'' then
+ Writeln(f,lista_funzioni[i]);
+ Close(f);
+end;
+
+(*******************************************************************)
+
+procedure MostraListaFunzioni;
+var
+ n,k,i:Integer;
+begin
+ (*Creiamo la nostra finestra*)
+ Window(63,5,77,22);
+ TextBackground(Black);
+ TextColor(LightGray);
+ ClrScr;
+ for i:=5 to 20 do
+ begin
+ GotoXY(68,i);
+ TextColor(White);
+ Write('y=?(x):');
+ TextColor(DarkGray);
+ GotoXY(73,i);
+ Write(' -------');
+ end;
+ i:=1;
+ TextColor(LightCyan);
+ while (i'') then
+ begin
+ GotoXY(9,i);
+ Write(lista_funzioni[i]);
+ for k:=Length(lista_funzioni[i]) to 6 do
+ begin
+ GotoXY(9+k,i);
+ Write(' ');
+ end;
+ end
+ else if (Length(lista_funzioni[i])>=8) AND (lista_funzioni[i]<>'') then
+ begin
+ for k:=1 to 7 do
+ begin
+ GotoXY(8+k,i);
+ Write(lista_funzioni[i][k]);
+ end;
+ end;
+ Inc(i);
+ end;
+end;
+(*******************************************************************)
+
+procedure SelezionaFunzione(da_selezionare,precedente:Integer);
+var
+ k:Integer;
+begin
+ (*Creiamo la nostra finestra*)
+ Window(1,1,80,25);
+ TextBackground(Black);
+ TextColor(White);
+ (*Togliamo la vecchia selezione...*)
+ GotoXY(63,precedente+4);
+ Write('y=?(x):');
+ TextColor(DarkGray);
+ GotoXY(70,precedente+4);
+ Write(' -------');
+ TextColor(LightCyan);
+ if (Length(lista_funzioni[precedente])<8) AND (lista_funzioni[precedente]<>'') then
+ begin
+ GotoXY(71,precedente+4);
+ Write(lista_funzioni[precedente]);
+ for k:=Length(lista_funzioni[precedente]) to 6 do
+ begin
+ GotoXY(71+k,precedente+4);
+ Write(' ');
+ end;
+ end
+ else if (Length(lista_funzioni[precedente])>=8) AND (lista_funzioni[precedente]<>'') then
+ begin
+ for k:=1 to 7 do
+ begin
+ GotoXY(70+k,precedente+4);
+ Write(lista_funzioni[precedente][k]);
+ end;
+ end;
+ (*... e mostriamo la nuova*)
+ TextBackground(Red);
+ TextColor(White);
+ GotoXY(63,da_selezionare+4);
+ Write('y=?(x):');
+ TextColor(DarkGray);
+ GotoXY(70,da_selezionare+4);
+ Write(' -------');
+ TextColor(Yellow);
+ if (Length(lista_funzioni[da_selezionare])<8) AND (lista_funzioni[da_selezionare]<>'') then
+ begin
+ GotoXY(71,da_selezionare+4);
+ Write(lista_funzioni[da_selezionare]);
+ for k:=Length(lista_funzioni[da_selezionare]) to 6 do
+ begin
+ GotoXY(71+k,da_selezionare+4);
+ Write(' ');
+ end;
+ end
+ else if (Length(lista_funzioni[da_selezionare])>=8) AND (lista_funzioni[da_selezionare]<>'') then
+ begin
+ for k:=1 to 7 do
+ begin
+ GotoXY(70+k,da_selezionare+4);
+ Write(lista_funzioni[da_selezionare][k]);
+ end;
+ end;
+end;
+(*******************************************************************)
+
+procedure ChiediNomeFile;
+var
+ done:Boolean;
+ ch:Char;
+ posizione:Integer;
+ tasto,precedente:string;
+begin
+ TextBackground(Black);
+ TextColor(Yellow);
+ Window(1,1,80,25);
+ GotoXY(21,4);
+ Write('File delle funzioni');
+
+ (*Creiamo la nostra finestra*)
+ Window(4,5,58,21);
+ TextBackground(Black);
+ ClrScr;
+ TextColor(White);
+ Writeln;
+ Writeln('Inserire il nome ed il percorso completo del file:');
+ Writeln;
+ TextColor(LightGreen);
+ GotoXY(25,17);
+ Write('Esc: esci');
+ TextColor(LightGray);
+ GotoXY(1,4);
+ done:=False;
+ Write(FileDelleFunzioni);
+ posizione:=Length(FileDelleFunzioni);
+ GotoXY(1+posizione,4);
+ precedente:=FileDelleFunzioni;
+ repeat
+ ch:=ReadChar;
+ case ch of
+ #8:
+ begin
+ if posizione>0 then
+ begin
+ tasto:='';
+ for i:=1 to (posizione-1) do
+ tasto:=Concat(tasto,FileDelleFunzioni[i]);
+ FileDelleFunzioni:=tasto;
+ (*Creiamo la nostra finestra*)
+ Window(4,5,58,21);
+ TextColor(LightGray);
+ TextBackground(Black);
+ GotoXY(posizione,4);
+ Write(' ');
+ Dec(posizione);
+ GotoXY(1+posizione,4);
+ end;
+ if posizione=0 then
+ FileDelleFunzioni:='';
+ end;
+ #13:
+ done:=True;
+ #27:
+ begin
+ done:=True;
+ FileDelleFunzioni:=precedente;
+ end;
+ #72:
+ Beep;
+ #75,#77:
+ Beep;
+ #80:
+ Beep;
+ else
+ begin
+ if posizione<54 then
+ begin
+ tasto:=ch;
+ Delete(FileDelleFunzioni,posizione+1,1);
+ Insert(tasto,FileDelleFunzioni,posizione+1);
+ Inc(posizione);
+ (*Creiamo la nostra finestra*)
+ Window(4,5,58,21);
+ TextColor(LightGray);
+ TextBackground(Black);
+ GotoXY(posizione,4);
+ Write(tasto);
+ end
+ else
+ Beep;
+ end;
+ end;
+ until done;
+end;
+(*******************************************************************)
+
+procedure FinestraPrincipale;
+var
+ ch:Char;
+ done:Boolean;
+begin
+ (*Creiamo la nostra finestra*)
+ Window(1,1,80,25);
+ TextBackground(Black);
+ ClrScr;
+ TextColor(LightBlue);
+ Writeln(' ANALIZZATORE DI FUNZIONI MATEMATICHE - 4');
+ Writeln(' di Marco Olivo, 1998,1999');
+ Writeln;
+ TextColor(DarkGray);
+ Writeln(' ????????????????????????????????????????????????????????????????????????????');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ? ?? ?');
+ Writeln(' ????????????????????????????????????????????????????????????????????????????');
+ Messaggio('Consultare la guida in linea per maggiori informazioni sul programma');
+ MenuPrincipale;
+ MostraListaFunzioni;
+ SelezionaFunzione(funzione_corrente,funzione_corrente);
+ if lista_funzioni[funzione_corrente]<>'' then
+ Messaggio(lista_funzioni[funzione_corrente]);
+ done:=False;
+ repeat
+ ch:=ReadChar;
+ case ch of
+ 'i','I':
+ begin
+ done:=True;
+ InserisciFunzione('');
+ FinestraPrincipale;
+ end;
+ 'v','V':
+ begin
+ done:=True;
+ if lunghezza>0 then
+ begin
+ Grafico_Rotazione:=True;
+ VisualizzaGrafico;
+ end
+ else
+ Beep;
+ FinestraPrincipale;
+ end;
+ 'e','E':
+ begin
+ done:=True;
+ if lunghezza>0 then
+ EstrapolaPunti
+ else
+ Beep;
+ FinestraPrincipale;
+ end;
+ 'l','L':
+ begin
+ done:=True;
+ LimitaDominio;
+ FinestraPrincipale;
+ end;
+ 'r','R':
+ begin
+ done:=True;
+ if lunghezza>0 then
+ begin
+ Grafico_Rotazione:=False;
+ VisualizzaGrafico;
+ end
+ else
+ Beep;
+ FinestraPrincipale;
+ end;
+ 'g','G':
+ begin
+ done:=True;
+ Informazioni_Guida;
+ FinestraPrincipale;
+ end;
+ 'a','A':
+ begin
+ done:=True;
+ ImpostaDefault;
+ FinestraPrincipale;
+ end;
+ #72: (*Freccia in alto*)
+ begin
+ if funzione_corrente>1 then
+ begin
+ SelezionaFunzione(funzione_corrente-1,funzione_corrente);
+ Dec(funzione_corrente);
+ if lista_funzioni[funzione_corrente]<>'' then
+ Messaggio(lista_funzioni[funzione_corrente])
+ else
+ Messaggio('Consultare la guida in linea per maggiori informazioni sul programma');
+ funzione:=lista_funzioni[funzione_corrente];
+ lunghezza:=Length(funzione);
+ (*Facciamo di modo che la nostra stringa sia tutta in maiuscolo*)
+ for i:=1 to lunghezza do
+ funzione[i]:=UpCase(funzione[i]);
+ LeggiFunzione;
+ if (ControllaSintassi=True) then
+ begin
+ CalcolaPrecedenze;
+ if numero_funzioni'' then
+ Messaggio(lista_funzioni[funzione_corrente])
+ else
+ Messaggio('Consultare la guida in linea per maggiori informazioni sul programma');
+ funzione:=lista_funzioni[funzione_corrente];
+ lunghezza:=Length(funzione);
+ (*Facciamo di modo che la nostra stringa sia tutta in maiuscolo*)
+ for i:=1 to lunghezza do
+ funzione[i]:=UpCase(funzione[i]);
+ LeggiFunzione;
+ if (ControllaSintassi=True) then
+ begin
+ CalcolaPrecedenze;
+ if numero_funzioni'' then
+ Messaggio(lista_funzioni[funzione_corrente]);
+ funzione:=lista_funzioni[funzione_corrente];
+ lunghezza:=Length(funzione);
+ (*Facciamo di modo che la nostra stringa sia tutta in maiuscolo*)
+ for i:=1 to lunghezza do
+ funzione[i]:=UpCase(funzione[i]);
+ LeggiFunzione;
+ if (ControllaSintassi=True) then
+ begin
+ CalcolaPrecedenze;
+ if numero_funzioni