home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1989 / 08 / praxis / upn.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1989-05-16  |  13.0 KB  |  338 lines

  1. (* ------------------------------------------------------ *)
  2. (*                     UPN.PAS                            *)
  3. (*             (c) 1989 C.Ohr & TOOLBOX                   *)
  4. (* ------------------------------------------------------ *)
  5. PROGRAM UPNCalc;
  6. {$I-,V-}
  7. {$M 2000, 0, 100}
  8.  
  9. USES CRT, TSR, { s. TOOLBOX 4'89 bzw. PASCAL 5'88 }  DOS;
  10.  
  11. CONST
  12.   ErsatzX = 50;
  13.   ErsatzY =  3;      { Defaultwerte für Bildschirmposition }
  14.   HotKey  = $6600;                      { Hotkey : Ctrl-F9 }
  15.  
  16. VAR
  17.   regs : Registers;
  18.  
  19. {$F+}                               { Far-Modell wegen TSR }
  20.  
  21. TYPE
  22.   pElement = ^Element;          { Zeiger auf Kellerelement }
  23.   Element  = RECORD             { Kellerelement y1->y2 ... }
  24.                fig  : REAL;
  25.                next : pElement;
  26.              END;
  27.   string14 = STRING[14];
  28.   ScrType  = ARRAY[0..3999] OF BYTE;          { Bildschirm }
  29.  
  30. CONST
  31.   ndef  = 'Not defined!';  { Meldung, wenn Keller leer ist }
  32.   Liste = 1;
  33.   Float = 2;
  34.   Input = 3;                                 { Fehlercodes }
  35.   MaxM  = 9;
  36.  
  37. VAR
  38.   EPtr   : pElement;      { Zeiger auf erstes Datenelement }
  39.   Screen : ScrType ABSOLUTE $B800:$0000;
  40.                                  { Bildschirmspeicher :    }
  41.                                  { $B000:.. fuer Monochrom }
  42.                                  { $B800:.. fuer CGA       }
  43.   Buffer : ScrType;          { Buffer für Bildschirminhalt }
  44.   m : ARRAY[0..MaxM] OF REAL;         { Konstantenspeicher }
  45.   OldX, OldY,
  46.   OldWMin,OldWMax : WORD;    { Alte Cursorposition/Fenster }
  47.   SoftKey         : WORD;          { Scan-Code fuer Hotkey }
  48.   XPos, YPos      : BYTE;            { Neue Cursorposition }
  49.   ch              : CHAR;
  50.   zahl            : string14;             { Eingabe-String }
  51.   x, h            : REAL;
  52.   i, error        : INTEGER;
  53.   EFlag           : BOOLEAN;    { Flag für Darstellungsart }
  54.  
  55.   PROCEDURE Init;                { Programm initialisieren }
  56.   BEGIN
  57.     OldX := WhereX;
  58.     OldY := WhereY;           { Alte Cursorposition retten }
  59.     OldWMin := WindMin;
  60.     OldWMax := WindMax;              { Alte Fenster retten }
  61.     Zahl := '';                   { Eingabestring loeschen }
  62.     x := 0.0;                        { x-Register loeschen }
  63.     FOR i := 0 TO MaxM DO m[i] := 0.0;
  64.     EPtr := NIL;         { Keller leer -> Zeiger ins Blaue }
  65.     EFlag := TRUE;           { Darstellung: Zehnerpotenzen }
  66.     Move(Screen,Buffer,
  67.          SizeOf(Buffer))         { Alten Bildschirm retten }
  68.   END;
  69.  
  70.   PROCEDURE BWrite(s : STRING);
  71.                   { Schreibprozedur für den Taschenrechner }
  72.   BEGIN
  73.     FOR i := 1 TO Length(s) DO BEGIN
  74.       IF s[i] = '#' THEN BEGIN  { Falls dem Zeichen        }
  75.                                 { ein '#' vorgestellt ist, }
  76.         Inc(i);                 { das nächste Zeichen      }
  77.         TextColor(White);       { heller schreiben.        }
  78.       END ELSE
  79.         TextColor(LightGray);   { ...ansonsten normal      }
  80.       Write(s[i]);
  81.     END;
  82.   END;
  83.  
  84.   PROCEDURE Swap(VAR x, y : REAL);
  85.                               { Zwei Variablen vertauschen }
  86.   BEGIN
  87.     h := x;  x := y;  y := h;
  88.   END;
  89.  
  90.   PROCEDURE DrawCalc;                   { Rechner ausgeben }
  91.   BEGIN
  92.     TextColor(Magenta);
  93.     TextBackGround(Black);
  94.     Window(XPos, YPos, XPos+19, YPos+11);
  95.     ClrScr;
  96.     Write ('▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄');
  97.     Write ('▌x:                ▐');
  98.     Write ('▌y:                ▐');
  99.     Write ('▌Z:                ▐');
  100.     Write ('▓▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▓');
  101.     BWrite('▒ L#n  E#x  L#og  Rp#V ▒');
  102.     BWrite('▒ #Pi  R#d  #Int  C#hS ▒');
  103.     BWrite('▒ x'+Chr(16)+'#Z En#g #Y^X  #* #/ ▒');
  104.     BWrite('▒ S#mx #Wm  #Rm   #+ #- ▒');
  105.     BWrite('▒ #Sxy #Ex #. #'+Chr(17)+'#┘ #C #Ac ▒');
  106.     BWrite('▒ C#ly #'+Chr(17)+'#- #Kill #Quit ▒');
  107.     Window(XPos, YPos+11, XPos+19, YPos+12);
  108.                           { Fenster vergrößern, sonst wird }
  109.                           { beim letzten Zeichen gescrollt }
  110.     Write('▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀');
  111.     Window(XPos+3, YPos+1, XPos+18, YPos+3);
  112.     TextColor(LightMagenta)
  113.   END;
  114.  
  115.   PROCEDURE WriteStr(s : STRING; y : BYTE);
  116.   BEGIN
  117.     GotoXY(1, y);  Write(' ', s);
  118.     ClrEoL;
  119.   END;
  120.  
  121.   PROCEDURE WriteR(x : REAL; y : BYTE);
  122.   BEGIN
  123.     GotoXY(1, y);
  124.     IF EFlag THEN Write(x:15)
  125.              ELSE Write(x:15:15);
  126.     ClrEoL;
  127.   END;
  128.  
  129.   PROCEDURE Push(x : REAL);
  130.   VAR
  131.     NPtr : pElement;
  132.   BEGIN
  133.     New(NPtr);               { Speicherplatz bereitstellen }
  134.     NPtr^.fig := x;                     { x-Wert eintragen }
  135.     NPtr^.next:=EPtr;  {  Next-Zeiger auf das alte 1.Elem. }
  136.     EPtr := NPtr;      { Zeiger auf das 1.Elem. neu setzen }
  137.   END;
  138.  
  139.   FUNCTION Pop : REAL;      { Holt den Inhalt des obersten }
  140.   VAR                       { Kellerelements               }
  141.     OPtr : pElement;
  142.   BEGIN
  143.     Pop  := EPtr^.fig;                     { Wert auslesen }
  144.     OPtr := EPtr;                          { Zeiger retten }
  145.     EPtr := EPtr^.Next;      { Erstes Element 'ausklinken' }
  146.     Dispose(OPtr);           { ...und löschen.             }
  147.   END;
  148.  
  149.   PROCEDURE Err(nr : BYTE);         { Fehler <nr> ausgeben }
  150.   BEGIN
  151.     CASE nr OF
  152.       Liste : WriteStr(#7 + 'List Error! ',2);
  153.       Float : WriteStr(#7 + ndef,1);
  154.                               { z.B. bei 1/0 oder Ln(-3)...}
  155.       Input : WriteStr(#7 + 'Input Error! ',3)
  156.     END;
  157.     Delay(1000);
  158.   END;
  159.  
  160.   PROCEDURE TestX;              { String in Zahl umwandeln }
  161.   BEGIN
  162.     Val(Zahl, x, error);
  163.     IF error <> 0 THEN Err(Input);
  164.   END;
  165.  
  166.   FUNCTION InputNr(s : STRING) : BYTE;
  167.                         { Nummer des m-Speichers eingeben. }
  168.   VAR TempB : BYTE;
  169.   BEGIN
  170.     WriteStr(s, 3);     { String ausgeben,                 }
  171.     REPEAT              { auf Eingabe einer Ziffer warten  }
  172.       ch := ReadKey
  173.     UNTIL (ch >= '0') AND (ch <= '9');
  174.     Write(ch);          { ... anzeigen ...                 }
  175.     Delay(100);
  176.     Val(ch, TempB, error);             { ...und umwandeln. }
  177.     InputNr := TempB;
  178.   END;
  179.  
  180.   FUNCTION PotenzXY(x, y : REAL) : REAL;
  181.   BEGIN
  182.     error := 0;
  183.     IF x > 0.0 THEN PotenzXY := Exp(y * Ln(x))
  184.     ELSE
  185.     IF x = 0.0 THEN
  186.       IF y > 0.0 THEN PotenzXY := 0.0
  187.                  ELSE error := 1
  188.     ELSE                                       { Basis < 0 }
  189.       IF y = Trunc(y) THEN      { Exponent ist ganzzahlig: }
  190.         IF Odd(Trunc(y)) THEN                { gerade oder }
  191.           PotenzXY := -Exp(y * Ln(-x))
  192.         ELSE PotenzXY := Exp(y * Ln(-x))    { ...ungerade! }
  193.       ELSE
  194.         IF (1/y = Round(1/y)) AND (Odd(Round(1/y))) THEN
  195.           PotenzXY:=-Exp(y*Ln(-x))
  196.                        { Exponent ist Kehrwert einer unge- }
  197.                        { raden Zahl: eigentlich nicht de-  }
  198.                        { finiert, die meisten TR lassen    }
  199.                        { die Rechnung aber zu! }
  200.         ELSE error := 1   { ...sonst aber wirklich Fehler! }
  201.   END;
  202.  
  203.   PROCEDURE Execute;                          { Rechnungen }
  204.   BEGIN
  205.     REPEAT
  206.       REPEAT
  207.          ch := UpCase(ReadKey)
  208.  { Zur Vergrößerung der Anzahl an 'Funktions'-Tasten kann  }
  209.  { auch zw. Groß- und Kleinschreibung differenziert werden.}
  210.       UNTIL ch <> '';            { Auf eine Eingabe warten }
  211.       CASE ch OF            { und die jetzt unterscheiden: }
  212.         '0'..'9',
  213.         'E','.',
  214.         '_'     : IF ch <> '_' THEN zahl := zahl + ch
  215.                                ELSE zahl := zahl + '-';
  216.  { Zur Unterscheidung mit dem normalen Minuszeichen wird   }
  217.  { hier der Underline '_' zur Vorzeichenwahl verwendet.    }
  218.         'A'     : BEGIN
  219.                      WHILE EPtr <> NIL DO x := Pop;
  220.                      x := 0.0;
  221.                      Zahl := '';          { Alles loeschen }
  222.                   END;
  223.         'C'     : x := 0.0;          { x-Register loeschen }
  224.         'D'     : x := Round(x);                  { Runden }
  225.         'G'     : EFlag := NOT EFlag;   { Real-Darstellung }
  226.         'H'     : x := -x;             { Vorzeichenwechsel }
  227.         'I'     : x := Int(x);           { Integerfunktion }
  228.         'K'     : Zahl := '';     { Eingabestring loeschen }
  229.         'L'     : IF EPtr <> NIL THEN h := Pop
  230.                                  ELSE Err(Liste);
  231.                                     { y1-Register loeschen }
  232.         'M'     : BEGIN                   { x <--> m[0..9] }
  233.                     Swap(x, m[InputNr('Swap x with m')]);
  234.                     WriteStr('M swapped!', 1);
  235.                     Delay(300);
  236.                   END;
  237.         'N'     : IF x > 0.0 THEN x := Ln(x)
  238.                              ELSE Err(Float);
  239.                                  { Natürlicher Logarithmus }
  240.         'O'     : IF x > 0.0 THEN x := Ln(x)/Ln(10)
  241.                              ELSE Err(Float);
  242.                                  { Zehnerlogarithmus       }
  243.         'P'     : Str(Pi:10:8, Zahl);                 { PI }
  244.         'R'     : BEGIN                    { x <-- m[0..9] }
  245.                     x := m[InputNr('Read from m')];
  246.                     WriteStr('M read!', 1);
  247.                     Delay(300);
  248.                   END;
  249.         'S'     : IF EPtr <> NIL THEN Swap(x, EPtr^.fig)
  250.                                  ELSE Err(Liste);
  251.                                                { x <--> y1 }
  252.         'V'     : IF x <> 0.0 THEN x := 1/x
  253.                               ELSE Err(Float);  { Kehrwert }
  254.         'W'     : BEGIN                    { x --> m[0..9] }
  255.                     m[InputNr('Store x in m')] := x;
  256.                     WriteStr('M stored!', 1);
  257.                     Delay(300);
  258.                   END;
  259.         'X'     : x := Exp(x);                { e-Funktion }
  260.         'Z'     : Str(x:14, Zahl); { x in String umwandeln }
  261.         '+','-','Y',          { Verknüpfungen zw. x und y1 }
  262.         '*','/' : IF EPtr <> NIL THEN BEGIN
  263.                                         { Operand (y1) da? }
  264.                     error := 0;
  265.                     IF Zahl <> '' THEN TestX;  { umwandeln }
  266.                       IF error = 0 THEN
  267.                       CASE ch OF
  268.                         '+': x := Pop + x;   { und rechnen }
  269.                         '-': x := Pop - x;
  270.                         '*': x := Pop * x;
  271.                         '/': IF x <> 0.0 THEN x := Pop/x
  272.                                          ELSE Err(Float);
  273.                         'Y': BEGIN
  274.                                x := PotenzXY(Pop, x);
  275.                                IF error <> 0 THEN Err(Float)
  276.                              END;
  277.                       END;
  278.                       IF EPtr = NIL THEN Push(x);
  279.                       Zahl := ''; { Eingabe-String löschen }
  280.                    END ELSE Err(Liste);     { sonst Fehler }
  281.         #8       : IF Length(Zahl) > 0 THEN
  282.                      Zahl:= Copy(Zahl,1,Pred(Length(Zahl)));
  283.                                  { Letztes Zeichen löschen }
  284.         #13      : BEGIN                         { Eingabe }
  285.                      TestX;
  286.                      IF error = 0 THEN Push(x);
  287.                                   {  Zahl gültig -> Keller }
  288.                      Zahl := '';  { Eingabe-String löschen }
  289.                    END;
  290.       END;
  291.       WriteR(x, 1);                       { Werte ausgeben }
  292.       IF EPtr <> NIL THEN WriteR(EPtr^.fig, 2)
  293.                      ELSE WriteStr(ndef, 2);
  294.       WriteStr(Zahl, 3);
  295.     UNTIL ch = 'Q';           { und wiederholen bis 'QUIT' }
  296.   END;
  297.  
  298.   PROCEDURE upn;                    { Urspr. Hauptprogramm }
  299.   BEGIN
  300.     Init;
  301.     DrawCalc;                    { Taschenrechner ausgeben }
  302.     WriteR(x, 1);
  303.     WriteStr(ndef, 2);              { erste Werte ausgeben }
  304.     GotoXY(2, 3);
  305.     Execute;                          { ...und los geht's! }
  306.     Move(Buffer, Screen, SizeOf(Screen));
  307.     Window(Succ(Lo(OldWMin)), Succ(Hi(OldWMin)),
  308.            Succ(Lo(OldWMax)), Succ(Hi(OldWMax)));
  309.                            { Alten Bildschirm restaurieren }
  310.     GotoXY(OldX, OldY);    { Alte Cursorposition ansteuern }
  311.   END;
  312.  
  313. {$F-}                                    { Ende Far-Modell }
  314.  
  315. BEGIN                            { Beginn UPN-Installation }
  316.   IF ParamCount > 1 THEN BEGIN      { Eingabe der Position }
  317.     Val(ParamStr(1), XPos, error);
  318.     Val(ParamStr(2), YPos, error);
  319.     IF (XPos < 1) OR (XPos > 60) OR (YPos < 1)
  320.                   OR (YPos > 13) OR (error <> 0) THEN BEGIN
  321.       XPos := ErsatzX;
  322.       YPos := ErsatzY;  { Default bei unvollständiger oder }
  323.                         { unsinniger Eingabe }
  324.     END;
  325.     IF ParamCount > 2 THEN BEGIN  { Eingabe des Scan-Codes }
  326.       Val(ParamStr(3), SoftKey, error);
  327.       IF error <> 0 THEN SoftKey := HotKey;
  328.     END ELSE SoftKey := HotKey;  { oder Default einsetzen. }
  329.   END ELSE BEGIN
  330.     XPos := ErsatzX;
  331.     YPos := ErsatzY;                                { s.o. }
  332.     SoftKey := HotKey;
  333.   END;
  334.   MakeResident(@upn, SoftKey)
  335.                            { Programm im Speicher behalten }
  336. END.                       { Voila! Viel Spass mit UPN !!  }
  337. (* ------------------------------------------------------ *)
  338. (*                  Ende von UPN.PAS                      *)