/***********************************************************
 *
 *  display.c
 *
 *  Alles, was mit dem "Display" des "Calc" zu tun hat.
 *
 *  Peter Gober, 06-Nov-88
 *               14-Oct-88  kleine Änderung
 *
 ***********************************************************/


#include <exec/types.h>
#include <intuition/intuition.h>
#include <functions.h>
#include "calc.h"


/*
 *  Border für den Display
 */

SHORT dispbordxy[] =
{
   0, 0,
   DISPWIDTH - 1, 0,
   DISPWIDTH - 1, DISPHEIGHT - 1,
   0, DISPHEIGHT - 1,
   0, 0
};

struct Border dispbord =
{
   0, 0,                                /* LeftEdge, TopEdge */
   1, 0, JAM1,                          /* FrontPen, BackPen, DrawMode */
   5,                                   /* Count */
   dispbordxy,                          /* XY */
   NULL                                 /* NextBorder */
};


/*
 *  error(str) gibt eine Fehlermeldung aus und wartet auf das Drücken einer
 *  Taste als Bestätigung
 */

error(str)
register char *str;
{
   sprintf(dispbuf, "Fehler: %-*s", DISPCHARS-8, str);
   display();
   waitforinp();
   return(0);
}


/*
 *  display() stellt den dispbuf dar.
 */

char dispbuf[DISPCHARS+1];              /* "Bildschirmspeicher" */

struct IntuiText dispitext =
{
   1, 0, JAM2,                          /* FrontPen, BackPen, DrawMode */
   0, 0,                                /* LeftEdge, TopEdge */
   &textattr,                           /* ITextFont */
   (UBYTE *) dispbuf,                   /* IText  */
   NULL                                 /* NextText */
};

display()
{
   PrintIText(wind->RPort, &dispitext, (long) (SPCHOR+2), (long) (DISPTOP+2));
   return(0);
}


/*
 *  dispnum() stellt die Zahl x (aus process.c) dar im eingestellten Format
 */

dispnum()
{
   char buf[310];                       /* DISPCHARS+1 würde es auch tun,
                aber sprintf() scheint sich nicht immer daran zu halten ... */

   if (inpmode)
   {
      /*
       *  dispnum() wird auch von waitforinp() aufgerufen, falls das Zahlen-
       *  system gewechselt wurde; ist der Benutzer trotzdem im inpmode,
       *  diesen abbrechen
       */
      inpmode = 0;
      inpbufptr = 0;
      inpbuf[0] = '\0';
   }

   switch(zahlsys)
   {
      case SYSBIN:
         if (stack[stackptr].x > 32768 || stack[stackptr].x < -32767)
         {
            error("zu groß");
            stack[stackptr].x = 0;
         }
         int2bin((int) stack[stackptr].x, buf);
         sprintf(dispbuf, "%*s", DISPCHARS, buf);
         break;
      case SYSOKT:
         if (stack[stackptr].x > 32768 || stack[stackptr].x < -32767)
         {
            error("zu groß");
            stack[stackptr].x = 0;
         }
         sprintf(dispbuf, "%*o", DISPCHARS, (int) stack[stackptr].x);
         break;
      case SYSHEX:
         if (stack[stackptr].x > 32768 || stack[stackptr].x < -32767)
         {
            error("zu groß");
            stack[stackptr].x = 0;
         }
         sprintf(dispbuf, "%*x", DISPCHARS, (int) stack[stackptr].x);
         break;
      case SYSDEZ:
         if (anz == ANZNORM)
         {
            if (stell == -1)            /* alle Stellen */
            {
               ftoapg2(stack[stackptr].x, buf, 2);
               sprintf(dispbuf, "%*s", DISPCHARS, buf);
            }
            else
            {
               sprintf(buf,     "%*.*f", DISPCHARS, stell, stack[stackptr].x);
               sprintf(dispbuf, "%*.*e", DISPCHARS, stell, stack[stackptr].x);
               if (strlen(buf) <= strlen(dispbuf))
               {
                  char *strcpy();
                  strcpy(dispbuf, buf);
               }
            }
         }
         else if (anz == ANZWISS)
         {
            if (stell == -1)            /* alle Stellen */
            {
               ftoapg2(stack[stackptr].x, buf, 0);
               sprintf(dispbuf, "%*s", DISPCHARS, buf);
            }
            else
               sprintf(dispbuf, "%*.*e", DISPCHARS, stell, stack[stackptr].x);
         }
   }
   display();

   return(0);
}


/*
 *  int2bin() wandelt eine Integer-Zahl in ein ASCII-Binär-Äquivalent
 */

int2bin(a, buf)
register unsigned int a;
char *buf;
{
   unsigned int v = 32768;
   register char *adr;

   adr = buf;                           /* sog. "Vergleichsverfahren" */
   do
   {
      if (a >= v)
      {
         a = a - v;
         *adr++ = '1';
      }
      else
         *adr++ = '0';
      v = v / 2;
   }
   while (v > 0);

   *adr = '\0';

   adr = buf;                           /* führende Nullen abschneiden */
   while (*adr == '0' && *(adr+1) != '\0')
      adr++;
   movmem(adr, buf, (int) (adr - buf + 1));

   return(0);
}


/*
 *  ftoapg2() konvertiert eine double-float-Zahl nach ASCII und benutzt dabei
 *  alle Stellen, die da sind; 0en am Ende werden gelöscht.
 */

ftoapg2(val, buf, type)
register double val;
register char *buf;
register int type;
{
   char *strchr();
   register char *exppos, *pos;
   int only0flag;

   ftoa(val, buf, 12, type);             /* 12 Stellen, die max. Stellenzahl
                                            ist hier durch die Genauigkeit
                                            der internen Zahlendarstellung
                                            begrenzt */

   if (exppos = strchr(buf, 'e'))
   {
      /*
       *  Eine Zahl mit Exponent ist herausgekommen,
       *  unwichtige 0en nach dem . löschen
       */

      only0flag = 1;                    /* signalisiert: wir haben nur 0en */

      pos = exppos - 1;                 /* momentane Suchposition */
      while ((*pos == '0' || *pos == '.') && only0flag)
      {
         if (*pos == '.')
            only0flag = 0;              /* jetzt Stoppen, da ist der . */
         pos--;
      }

      movmem(exppos, pos + 1, strlen(buf) - (exppos - buf) + 1);
                                        /* Exponent verschieben */
   }
   else if (strchr(buf, '.'))
   {
      /*
       *  Kein Exponent, Nachkommanullen löschen
       */

      only0flag = 1;                    /* signalisiert: wir haben nur 0en */

      pos = buf + strlen(buf) - 1;      /* momentane Suchposition */
      while ((*pos == '0' || *pos == '.') && only0flag)
      {
         if (*pos == '.')
            only0flag = 0;              /* jetzt Stoppen, da ist der . */
         *pos = '\0';                   /* diese Position löschen */
         pos--;
      }
   }

   return(0);
}
