/* Modul 10 : Requester für Druckermenü/Requester für HALT */
/* ------------------------------------------------------- */

#include <exec/types.h>
#include <intuition/intuitionbase.h>

extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;
extern struct IntuiMessage *message;
extern BYTE ZNR,ZPG;
extern int firstNR,firstPAGE;
extern int linespP;
extern char kopftext[];
extern struct Window *Dialog;

struct Window *DWindow;

/* -----Gadget für Zeilenzahl-----*/
char zahlen3puffer[4];
char undozahlen3[4]="50";
struct IntuiText nzahlentext =
{ 1,1,JAM1,-45,-11,0,"Zeilen pro Seite",0 };
struct StringInfo PageTString =
{  zahlen3puffer,undozahlen3,0,4,0,0,0,0,0,0,NULL,0,NULL };
 
USHORT zahlenrand[] =
{ -1,-2,36,-2,36,9,-1,9,-1,-2 };

struct Border zahlenBorder =
{ 0,0,1,2,JAM1,5,zahlenrand,NULL };

struct Gadget page_gad =
  {
   NULL, 507,76,34,15,GADGHCOMP,LONGINT|STRINGCENTER|RELVERIFY,STRGADGET,
   (APTR)&zahlenBorder,0,&nzahlentext,0,(APTR)&PageTString,7,0 };

/* -----Gadget für Seitennummern-----*/
char zahlen2puffer[4];
char undoseiten[4]="0";
struct StringInfo SeitenTString =
{  zahlen2puffer,undoseiten,0,4,0,0,0,0,0,0,NULL,0,NULL };
 
struct Gadget seiten_gad =
  {
   &page_gad, 318,60,34,15,GADGHCOMP,LONGINT|STRINGCENTER|RELVERIFY,STRGADGET,
   (APTR)&zahlenBorder,0,NULL,0,(APTR)&SeitenTString,6,0 };

/* -----Gadget für Zeilennummern-----*/
char zahlen1puffer[4];
char undozeilen[4]="0";
struct StringInfo ZeilenTString =
{  zahlen1puffer,undozeilen,0,4,0,0,0,0,0,0,NULL,0,NULL };
 
struct Gadget zeilen_gad =
  {
   &seiten_gad,229,60,34,15,GADGHCOMP,LONGINT|STRINGCENTER|RELVERIFY,STRGADGET,
   (APTR)&zahlenBorder,0,NULL,0,(APTR)&ZeilenTString,5,0 };

/* --------Gadget für die Kopfzeile----------*/

struct IntuiText nkopftext =
{ 1,1,JAM1,10,-11,0,"Kopftext jeder Seite :",0 };

struct StringInfo KopfTString =  /* Fuer Texte in Text-Gadgets */
{  kopftext,NULL,0,75,0,0,0,0,0,0,NULL,0,NULL };
 
USHORT kopfrand[] =
{ -1,-2,501,-2,501,9,-1,9,-1,-2 };

struct Border kopfBorder =
{ 0,0,1,2,JAM1,5,kopfrand,NULL };

struct Gadget kopft_gad =
  {
   &zeilen_gad, 50,30,500,20,GADGHCOMP,STRINGCENTER|RELVERIFY,STRGADGET,
   (APTR)&kopfBorder,0,&nkopftext,0,(APTR)&KopfTString,4,0 };

/* --------Gadget für cancel-------- */
USHORT Standardrand[] =
{ 0,0,83,0,83,11,0,11,0,0 };
 
struct Border Standard_border =
{ -1,-1,1,0,JAM1,5,Standardrand,NULL };

struct IntuiText cancel_str =
{ 1,1,JAM1,9,1,0,"Abbrechen",0 };

struct Gadget cancel =
  {
   &kopft_gad,51,75,80,10,
   GADGHCOMP,
   GADGIMMEDIATE|RELVERIFY,
   BOOLGADGET,
   (APTR)&Standard_border,
   0,&cancel_str,0,0,3,0 };
/* -------Gadget für drucken------- */

struct IntuiText drucken_str =
{ 1,1,JAM1,9,1,0,"drucken",0 };

struct Gadget drucken =
  {
   &cancel,140,75,80,10,
   GADGHCOMP,
   GADGIMMEDIATE|RELVERIFY,
   BOOLGADGET,
   (APTR)&Standard_border,
   0,&drucken_str,0,0,2,0 };
/* -------Gadget für Zeilennummern */

struct IntuiText zeilennr_str =
{ 1,1,JAM1,9,1,0,"Zeilennr.",0 };

struct Gadget zeilennr =
  {
   &drucken,229,75,80,10,
   GADGHCOMP|SELECTED,
   GADGIMMEDIATE|RELVERIFY|TOGGLESELECT,
   BOOLGADGET,
   (APTR)&Standard_border,
   0,&zeilennr_str,0,0,1,0 };
/* -------Gadget für Seitennummern */

struct IntuiText seitennr_str =
{ 1,1,JAM1,9,1,0,"Seitennr.",0 };

struct Gadget seitennr =
  {
   &zeilennr,318,75,80,10,
   GADGHCOMP|SELECTED,
   GADGIMMEDIATE|RELVERIFY|TOGGLESELECT,
   BOOLGADGET,
   (APTR)&Standard_border,
   0,&seitennr_str,0,0,0,0 };

struct NewWindow nDWindow =
  {
   0,0,640,100,2,1,
   GADGETDOWN,ACTIVATE,
   &seitennr,
   NULL,
   "Druck-Einstellungen",
   NULL,NULL,0,0,0,0,
   WBENCHSCREEN
  };

struct IntuiText fenstertext =
{ 1,1,JAM1,9,1,0,"jeweils erste Nummer :",0 };

BYTE printerreq()
{
  ULONG MessageClass;
  USHORT code;
  BYTE ende=1;
  char *z;

  z=kopftext+73; while((*z==' ')&&(z!=kopftext)) z--;
  *(z+1)=0;
  sprintf(zahlen3puffer,"%d",linespP);
  sprintf(zahlen2puffer,"%d",firstPAGE);
  sprintf(zahlen1puffer,"%d",firstNR);
  ZeilenTString.LongInt=firstNR;
  SeitenTString.LongInt=firstPAGE;
  PageTString.LongInt=linespP;
  if(!(DWindow=OpenWindow(&nDWindow)))
    return(2);

  PrintIText(DWindow->RPort,&fenstertext,42,59);

  while(ende==1)
  { Wait(1<<DWindow->UserPort->mp_SigBit);
    if(message=(struct IntuiMessage *)GetMsg(DWindow->UserPort))
    {
      MessageClass = message->Class; /* Message retten */
      code = message->Code;
      ReplyMsg(message);    /* Message beantworten */
      if(MessageClass==GADGETDOWN)
      { switch(((struct Gadget *)(message->IAddress))->GadgetID)
        {  case 0 : ZPG=!ZPG; break;/*Seitenr.*/
           case 1 : ZNR=!ZNR; break;
           case 2 : ende=2; break; /*ausdrucken*/
           case 3 : ende=0; break; /*cancel*/
           case 4 : break; /*kopftext einlesen*/
           case 5 :
           case 6 :
           case 7 : break;
        }
      }
    }
  }
  firstNR=(int)ZeilenTString.LongInt;
  firstPAGE=(int)SeitenTString.LongInt;
  linespP=(int)PageTString.LongInt;
  CloseWindow(DWindow);
  return(ende);
}

/* HALT----------------------------------------------------------- */
struct Image    v_img;
struct PropInfo v_prop;

struct Gadget v_gad =
{  NULL,342,14,20,44,GADGHCOMP,GADGIMMEDIATE|RELVERIFY,PROPGADGET,
   (APTR)&v_img,0,NULL,0,(APTR)&v_prop,0,0
};

/* --------Gadget für weiter-------- */

struct IntuiText weiter_str =
{ 1,1,JAM1,9,1,0,"weiter",0 };

struct Gadget weiter =
{ &v_gad,540,45,80,10,
  GADGHCOMP,
  GADGIMMEDIATE|RELVERIFY,
  BOOLGADGET,
  (APTR)&Standard_border,
  0,&weiter_str,0,0,3,0 };
/* -------Gadget für ansehen------- */

struct IntuiText ansehen_str =
{ 1,1,JAM1,9,1,0,"ansehen",0 };

struct Gadget ansehen =
{  &weiter,400,30,80,10,
   GADGHCOMP,
   GADGIMMEDIATE|RELVERIFY,
   BOOLGADGET,
   (APTR)&Standard_border,
   0,&ansehen_str,0,0,2,0 };

struct IntuiText aendern_str =
{ 1,1,JAM1,9,1,0,"ändern",0 };

struct Gadget aendern =
  {
   &ansehen,400,45,80,10,
   GADGHCOMP,
   GADGIMMEDIATE|RELVERIFY,
   BOOLGADGET,
   (APTR)&Standard_border,
   0,&aendern_str,0,0,1,0 };

struct IntuiText requp_str =
{ 0,1,JAM2,0,1,0,"/\\",0 };

struct Gadget requp =
  {
   &aendern,369,14,20,8,
   GADGHCOMP,
   GADGIMMEDIATE|RELVERIFY,
   BOOLGADGET,
   NULL,
   0,&requp_str,0,0,4,0 };

struct IntuiText reqdown_str =
{ 0,1,JAM2,0,1,0,"\\/",0 };

struct Gadget reqdown =
  {
   &requp,369,48,20,8,
   GADGHCOMP,
   GADGIMMEDIATE|RELVERIFY,
   BOOLGADGET,
   NULL,
   0,&reqdown_str,0,0,5,0 };

struct IntuiText nrleft_str =
{ 0,1,JAM2,0,1,0,"<<",0 };
struct Gadget nrleft =
  {
   &reqdown,400,13,16,8,
   GADGHCOMP,
   GADGIMMEDIATE|RELVERIFY,
   BOOLGADGET,
   NULL,
   0,&nrleft_str,0,0,6,0 };
struct IntuiText nrright_str =
{ 0,1,JAM2,0,1,0,">>",0 };
struct Gadget nrright =
  {
   &nrleft,464,13,16,8,
   GADGHCOMP,
   GADGIMMEDIATE|RELVERIFY,
   BOOLGADGET,
   NULL,
   0,&nrright_str,0,0,7,0 };

struct IntuiText loeschen_str =
{ 1,1,JAM1,9,1,0,"löschen",0 };

struct Gadget loeschen =
{  &nrright,520,30,80,10,
   GADGHCOMP,
   GADGIMMEDIATE|RELVERIFY,
   BOOLGADGET,
   (APTR)&Standard_border,
   0,&loeschen_str,0,0,8,0 };
char tleiste[80];
struct Window *BreakWindow;
struct NewWindow NewBreak =
{
  0,0,640,62,0,1,GADGETDOWN|GADGETUP,ACTIVATE,&loeschen,NULL,
  "",
  NULL,NULL,0,0,0,0,WBENCHSCREEN
};

int vzahl;
/* Struktur zur Aufnahme der Datenzeilen :*/
struct atom { int knotentyp;
              char zeichenkette[2]; };
struct paar { int knotentyp;
              WORD *CAR,*CDR; };
struct varlist { int knotentyp;
                 struct varlist *links,*rechts;
                 struct paar *eintrag;
                 struct atom *name;
                 int lokalzahl;
               };
struct reqzeile { char zeile[42]; /*36 Zeichen Name, dann 5 Zeichen Anzahl+0*/
                  struct varlist *info; /*Zeiger auf Verkettungsknoten*/
                };
struct reqzeile *reqbase;

struct IntuiText auswahltext =
   { 3,1,JAM2,9,1,0,"",0 };
void inkarnation(nr)
int nr;
{  char puffer[8];
   sprintf(puffer,"%5d",nr);
   auswahltext.IText=puffer;
   auswahltext.DrawMode=JAM2;
   PrintIText(BreakWindow->RPort,&auswahltext,410,13);
}
void auffuellen(position)
int position;
{  int i;
   position-=2;
   for(i=0;i<5;i++)
   { if((position < 0)||(position>vzahl))
       auswahltext.IText="                                         ";
     else
       auswahltext.IText=(reqbase+position)->zeile;
     if(i!=2) auswahltext.DrawMode=JAM2; else auswahltext.DrawMode=JAM2|INVERSVID;
     PrintIText(BreakWindow->RPort,&auswahltext,0,15+i*8);
     position++;
   }
   inkarnation((reqbase+position-3)->info->lokalzahl);
}

extern struct varlist *symbolliste;

void getvzahl(zeiger) /*ermittelt rekursiv die Anzahl der Symbolnahmen*/
struct varlist *zeiger;
{ if(zeiger)
  {  vzahl++; getvzahl(zeiger->links); getvzahl(zeiger->rechts); }
}

struct reqzeile *aufbau;
void datagen(zeiger) /*füllt das Gadget mit den Namen auf*/
struct varlist *zeiger;
{ char *z1,*z2;
  int i;
  if(zeiger)
  {  datagen(zeiger->links); /*inorder*/
     i=0; z1=aufbau->zeile;
     z2=zeiger->name->zeichenkette;
     while((*z2)&&(i<36)) { *z1++=*z2++; i++; }
     while(i++<36) *z1++=' '; /*mit Space auffüllen*/
     sprintf(z1,"%5d",zeiger->lokalzahl);
     aufbau->info=zeiger; /* Variablenverkettung */
     aufbau++;
     datagen(zeiger->rechts);
  }
}
struct paarheap { struct paarheap *last,*next;
                  struct paar inhalt;
                };
void titelfree() /*Darstellung des Speicherstatus in der Titelzeile*/
{ ULONG *lauf;
  extern ULONG *truedynber,anzSeg;
  extern int PSecZahl,PZahl;
  struct paarheap *h;
  extern struct paarheap *BesetztPaar;
  int merke=0,k[4];
  lauf=truedynber;k[0]=k[1]=k[2]=k[3]=0;
  while(*lauf!=0xfffffffe)
  {  if((*lauf)&1L)
     {  if(!((*lauf)&0x80000000L))
          k[(*(lauf+1))-1L]++;
     }
     else merke+=((*lauf)-((ULONG)lauf)-4L);
     lauf=(*lauf)&0x7ffffffeL;
  }
  h=BesetztPaar;
  while(h)
  {  k[h->inhalt.knotentyp-1]++;
     h=h->next;
  }
  sprintf(tleiste,"     (Knoten:%5d/%5d/%4d//%6d reserviert:%7d frei:%7d)",
  k[0]+k[3],k[1],k[2],k[0]+k[1]+k[2]+k[3],(anzSeg+1)*32768+PSecZahl*30000,
  merke+PSecZahl*30000-PZahl*20);
  SetWindowTitles(BreakWindow,tleiste,-1);
}
BYTE testnull(pos) /*testet, ob es eine entspr. globale Var. gibt*/
int pos;
{ int i=0;
  struct paar *lauf;
  lauf=(reqbase+pos)->info->eintrag;
  while(lauf) { lauf=lauf->CDR; i++; }
  if(i==(reqbase+pos)->info->lokalzahl)
    return(0);
  return(1);
}
struct paar *mla; /*gibt vorletzten Eintrag an*/
struct paar *aktinhalt(pos,nr) /*ermittelt den Inhalt der aktuellen Inkarnation*/
int pos; /*Nr des ausgawählten Symbols*/
int nr; /*Nr der gewünschten Inkarnation*/
{ int i,gesamt;
  struct paar *lauf;
  gesamt=(reqbase+pos)->info->lokalzahl-nr;
  lauf=(reqbase+pos)->info->eintrag;
  for(i=0;i<gesamt;i++) {mla=lauf; lauf=lauf->CDR;}
  return(lauf);
}
extern void fehler();
BYTE breakmenu()
{ extern void output(),nprint(),delete();
  extern char *newcon(),*textpointer;
  extern BYTE menuflag;
  extern struct paar *input();
  extern BYTE datflag,bildaus;
  extern void lineup(),linedown(),setpage(),delsymbol();
  struct paar *hilf,*help,*evaluate();
  char *hzeig;
  ULONG MessageClass;
  USHORT code;
  int i,merke=0,nr;
  BYTE flag=1,me,mf;
  v_prop.Flags = FREEVERT|AUTOKNOB;
  v_prop.VertBody = 0xFFFF;
  v_prop.VertPot = 0;
  if(!(BreakWindow = (struct Window *)OpenWindow(&NewBreak) ))
  { fehler(8,0L); return(0); }
  titelfree();
  SetAPen(BreakWindow->RPort,1);
  Move(BreakWindow->RPort,0,14);Draw(BreakWindow->RPort,342,14);
  Move(BreakWindow->RPort,0,57);Draw(BreakWindow->RPort,342,57);
  vzahl=0;                        /*Anzahl der Symbolnamen*/
  getvzahl(symbolliste); vzahl--;
  if(vzahl<0) /*keine Variablen !*/
  { CloseWindow(BreakWindow); return(0); }
  if(!(reqbase=AllocMem(sizeof(struct reqzeile)*(vzahl+1),1L)))
  { CloseWindow(BreakWindow); fehler(8,0L); return(0); }
  aufbau=reqbase;
  datagen(symbolliste);
  if(vzahl) v_prop.VertBody = 0xFFFF/(vzahl+4)*5;
  RefreshGadgets(&v_gad,BreakWindow,0);
  auffuellen(0);
  nr=reqbase->info->lokalzahl;
  while(flag)
  { if(message = (struct IntuiMessage *)GetMsg(BreakWindow->UserPort))
    { MessageClass = message->Class; /* Message retten */
      code = message->Code;
      ReplyMsg(message);    /* Message beantworten */
      if(MessageClass==GADGETDOWN)
      {  if(!vzahl) merke=0;
         else merke=v_prop.VertPot/(0xffff/vzahl);
         switch(((struct Gadget *)message->IAddress)->GadgetID)
         { case 0 : if(!vzahl) break;
                    auffuellen(merke);
                    do
                    { if(merke!=v_prop.VertPot/(0xffff/vzahl))
                      {  merke=v_prop.VertPot/(0xffff/vzahl);
                         auffuellen(merke);
                      }
                      if(message=(struct IntuiMessage*)GetMsg(BreakWindow->UserPort))
                      {  MessageClass=message->Class; ReplyMsg(message); }
                    }while(MessageClass!=GADGETUP);
                    if(merke!=v_prop.VertPot/(0xffff/vzahl))
                      auffuellen(v_prop.VertPot/(0xffff/vzahl));
                    nr=(reqbase+merke)->info->lokalzahl;
                    break;
           case 1 : nprint("\nBitte neuen Wert für");
                    me=datflag; datflag=1; mf=bildaus; bildaus=1;
                    output((reqbase+merke)->info->name);nprint("eingeben :");
                    ActivateWindow(Dialog);datflag=me; bildaus=mf;
                    hzeig=textpointer; /*Position im Quelltext retten*/
                    hilf=evaluate(input(newcon()));
                    textpointer=hzeig;
                    if(hilf!=-1L)
                    { help=aktinhalt(merke,nr);
                      delete(help->CAR);
                      help->CAR=hilf;
                    }
                    ActivateWindow(BreakWindow);
                    titelfree();
                    break;
           case 2 : me=datflag; mf=bildaus; bildaus=datflag=1;
                    output((reqbase+merke)->info->name);nprint(":=");
                    output(aktinhalt(merke,nr)->CAR);
                    datflag=me; bildaus=mf; nprint("\n"); break;
           case 3 : flag=0; break;
           case 4 : if((!vzahl)||(merke<=0)) break;
                    v_prop.VertPot=0xffff/vzahl*(--merke);
                    auffuellen(merke);
                    nr=(reqbase+merke)->info->lokalzahl;
                    RefreshGadgets(&v_gad,BreakWindow,0);break;
           case 5 : if((!vzahl)||(merke>=vzahl)) break;
                    v_prop.VertPot=0xffff/vzahl*(++merke);
                    auffuellen(merke);
                    nr=(reqbase+merke)->info->lokalzahl;
                    RefreshGadgets(&v_gad,BreakWindow,0);break;
           case 6 : if(nr==0) break;
                    if(nr==1) if(!testnull(merke)) break;
                    inkarnation(--nr); break;
           case 7 : if(nr>=(reqbase+merke)->info->lokalzahl) break;
                    inkarnation(++nr);break;
           case 8 : if(nr>0) {nprint("lokale Variablen dürfen nicht gelöscht werden !\n");break;}
                    if((reqbase+merke)->info->lokalzahl>0) /*Name bleibt bestehen*/
                    {  hilf=aktinhalt(merke,0);
                       delete(hilf->CAR);
                       mla->CDR=0L;  /*s.o.*/
                       dispose(hilf);
                       inkarnation(++nr);
                    }
                    else
                    {  delsymbol((reqbase+merke)->info->name);
                       /*Achtung : der Name wird zweimal hintereinander*/
                       /* gelöscht, dispose nicht ändern !*/
                       if(--vzahl<0) {flag=0; break;} /*nichts übrig*/
                       aufbau=reqbase;
                       datagen(symbolliste);
                       if(--merke<0) merke=0;
                       auffuellen(merke);
                       nr=(reqbase+merke)->info->lokalzahl;
                       if(vzahl) v_prop.VertBody = 0xFFFF/(vzahl+4)*5;
                       else v_prop.VertBody=0xFFFF;
                       if(!vzahl) v_prop.VertPot=0;
                       else v_prop.VertPot=0xffff/vzahl*merke;
                       RefreshGadgets(&v_gad,BreakWindow,0);
                    }
                    titelfree();break;
         }
      }
    }
    if(message = (struct IntuiMessage *)GetMsg(Dialog->UserPort))
    { MessageClass = message->Class; /* Message retten */
      code = message->Code;
      ReplyMsg(message);    /* Message beantworten */
      if(MessageClass==GADGETUP)
      {  switch(((struct Gadget*)message->IAddress)->GadgetID)
         { case 1 : lineup(); break;
           case 2 : linedown(); break;
           case 3 : setpage(); break;
         }
      }
    }
  }
  FreeMem(reqbase,sizeof(struct reqzeile)*(vzahl+1));
  CloseWindow(BreakWindow);
  return(1);
}
/* Gadgets der unteren Dialogleiste */

USHORT leistenrand[] =
{ 0,0,198,0,198,11,0,11,0,0 };
struct Border leistenborder =
{ 0,0,1,2,JAM1,5,leistenrand,NULL };
extern struct Gadget d_gad;
struct IntuiText leiste3txt =
{ 1,0,JAM2,5,2,0," Dialog -> PRT:",0 };
struct Gadget leiste3 =
  {
   &d_gad,440,243,196,10,
   GADGHCOMP,
   GADGIMMEDIATE|RELVERIFY,
   BOOLGADGET,
   (APTR)&leistenborder,
   0,&leiste3txt,0,0,6,0 };

struct IntuiText leiste2txt =
{ 1,0,JAM2,5,2,0," Funktionsaufrufe zeigen",0 };
struct Gadget leiste2 =
  {
   &leiste3,221,243,196,10,
   GADGHCOMP,
   GADGIMMEDIATE|RELVERIFY,
   BOOLGADGET,
   (APTR)&leistenborder,
   0,&leiste2txt,0,0,5,0 };

struct IntuiText leiste1txt =
{ 1,0,JAM2,5,2,0," nur 'princ'-Ausgaben",0 };
struct Gadget leiste1 =
  {
   &leiste2,2,243,196,10,
   GADGHCOMP,
   GADGIMMEDIATE|RELVERIFY,
   BOOLGADGET,
   (APTR)&leistenborder,
   0,&leiste1txt,0,0,4,0 };
