#include <intuition/intuitionbase.h>
#include <functions.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <devices/inputevent.h>

#define CO	 (char *)&comp_opt[0] /* Addresse    */
#define LO       (char *)&link_opt[0] /*  der        */
#define WF       (char *)&work_file[0]/* Compiler-
                                      /* Varialblen  */
#define FKC      &function_key_command[0]
#define SWT      SetWindowTitles
#define PFC      SWT(ow,FKC,-1L)
#define EFC      Execute(FKC,NULL,NULL);
#define IMMER    for(;;)
#define TASTE    botschaft->Code
#define QUALI    botschaft->Qualifier
#define ART      botschaft->Class
#define RASTP    iw->RPort
#define STL      str_len(&cmd_str[0])
#define AMIGAL   0x0066  /* Hex-Werte aller */
#define AMIGAR   0x0067
#define CAPSLOCK 0x0062  /* RAW - Tasten */
#define ALTL     0x0064
#define ALTR	 0x0065
#define SHIFTL	 0x0060
#define SHIFTR	 0x0061
#define CONTROL	 0x0063
#define DEL	 0x0046
#define BACKSP	 0x0041
#define HELP	 0x005f
#define RETURN	 0x0044
#define ENTER	 0x0043
#define CURS_UP	 0x004c
#define CURS_DOWN 0x004d
#define CURS_L	 0x004f
#define CURS_R	 0x004e
#define F1	 0x0050
#define F2	 0x0051
#define F3	 0x0052
#define F4	 0x0053
#define F5	 0x0054
#define F6	 0x0055
#define F7	 0x0056
#define F8	 0x0057
#define F9	 0x0058
#define F10	 0x0059
#define INTUITION_REV 0L
#define GRAPHICS_REV  0L

struct NewWindow newwind; 
struct IntuiMessage *botschaft; /* IDCMP Daten */
struct FileHandle   *output , *save_file;
struct Window *iw,*ow; /*In-,Output */
struct IntuitionBase *IntuitionBase;   /*  BASIß     */
struct GfxBase *GfxBase;               /* ADDRESSEN  */
struct FileLock *lock, *lastlock;      /*   DER      */
struct FileInfoBlock *finfoptr, finfo; /*ROM-ROUTINEN*/

  
char empf_char,cmd_str[80]
,cmd_buf[10][80] = { {'\0'},{'\0'},{'\0'},{'\0'}
,{'\0'},{'\0'},{'\0'},{'\0'},  {'\0'},{'\0'}   };


/*  die Zeichensätze d + usa */
char *onshift,*onunshift,*trueunshift,*onshift_d,
     *onunshift_d,*onshift_usa,*onunshift_usa,
     function_key_command[80];

LONG keytyp,succ,control,alt,shift,
     redir_errors;

SHORT coun,len,zahl,cmd_ptr,cmd_count=0,old_cmd_count=0;

USHORT taste;

/* Options-Strings für das Compiler System */
char comp_opt[60],link_opt[60],work_file[20];


main()
 {
  /* Ein FileInfoBlock muß an einer durch 4 Teilbaren*/
  /* Addresse liegen (= longword boundary)           */
  /* AllocMem()  erldigt dies                        */
  finfoptr = (struct FileInfoBlock *)
     AllocMem((long)sizeof(struct FileInfoBlock),NULL);
  if(!finfoptr){ 
     printf("\nkein Speicherplatz fuer FileInfoBlock");
     ende(); 
   }         
             
  onunshift_d = 
  "[1234567890ß´\\ 0qwertzuiopü+ 123asdfghjklöä# 456<yxcvbnm,.- .789 ";
  onshift_d = 
  "]!\"§$%&/()=?`| 0QWERTZUIOPÜ* 123ASDFGHJKLÖÄ\' 456>YXCVBNM;:_ .789 ";

  onunshift_usa =
  "`1234567890-=\\ 0qwertyuiop[] 123asdfghjkl;'  456 zxcvbnm,./ .789 ";

  onshift_usa =
  "~!@#$%^&*()_+| 0QWERTYUIOP{} 123ASDFGHJKL:\"  456 ZXCVBNM<>? .789 ";

  onshift = onshift_d;
  onunshift = onunshift_d;

  
  /* Öffnen der Libraries */
  GfxBase = (struct GfxBase *)
        OpenLibrary("graphics.library",GRAPHICS_REV);
  if (GfxBase == NULL) ende();

  IntuitionBase = (struct IntuitionBase *)
        OpenLibrary("intuition.library",GRAPHICS_REV);
  if (IntuitionBase == NULL) ende();

  /* File Pointer auf den Standard-Output */
  /* hier CLI-Window */
  output = Output();

  /* Da das CLI-Window hier aktiv ist erhält man den*/
  /* Pointer darauf */
  ow = IntuitionBase->ActiveWindow; 

 /* initialisierung des Eingabewindows */
  newwind.LeftEdge = 0; 
  newwind.TopEdge  = 200;
  newwind.Width    = 640;
  newwind.Height   = 50;
  newwind.DetailPen = 0;
  newwind.BlockPen = 1; 
  newwind.Title    = (UBYTE *)"Actek C   Special Shell";
  newwind.Flags    = ACTIVATE|WINDOWDRAG
                     |WINDOWDEPTH|SIMPLE_REFRESH;
  newwind.IDCMPFlags = RAWKEY;
  newwind.Type       = WBENCHSCREEN;
  newwind.FirstGadget= NULL;
  newwind.CheckMark  = NULL;
  newwind.Screen     = NULL;
  newwind.BitMap     = NULL;
  newwind.MinWidth   = 640;
  newwind.MinHeight  = 50;
  newwind.MaxWidth   = 640;
  newwind.MaxHeight  = 50;

  if (( iw = (struct Window *)  /* Window öffnen */
          OpenWindow(&newwind)) == NULL) ende();

  curs_Pos(NULL); /* Eingabe-Cursor auf Null */

  IMMER
    {
      /* Eingabe-Window Aktiv machen */
      if(IntuitionBase->ActiveWindow != iw)
          ActivateWindow(iw);

      /* Warten auf Message vom Window (Tastendruck)*/
      Wait(1L<<iw->UserPort->mp_SigBit);
      
      /* Solange Informationen kommen werden diese  */
      /* nacheinander abgearbeitet                  */
     while(botschaft = (struct IntuiMessage *)
                        GetMsg(iw->UserPort))
	  {                 
            /* Prüfen ob RAWKEY empfangen wurde */
            if(ART != RAWKEY)break; 

 /* RAWWERT festhalten und Message freigeben */
            taste = TASTE;
            ReplyMsg(botschaft);
        
 /* Prüfen ob RAWWERT einem Buchsraben entspricht*/ 
 /* und entsprechend verzweigen */

           if(taste < 0x0041){             
	        verarbeiteASCII();
              }
            else{
                verarbeiteRAW();
              }                          
                                         
          }    /* END OF while */
                
      }     /* END OF IMMER */
    
  }     /*  END OF main() */


/**************************************************
 *
 *   TASTENVERARBEITUNG
 *
 *   hier werden alle Tasten außer Schriftzeichen 
 *   abgearbeitet entsprechend einer vorangehend
 *   betätigten <CTRL> <SHIFT> oder <ALT> Taste
 ***************************************************/
verarbeiteRAW()

 {
  switch(TASTE)
   {
     case HELP:
             Write(output,"\n\r\n\rKommandospeicher :\n\r\n\r",26L);
             for(coun=0;coun<10;coun++)
              { 
		Write(output,&cmd_buf[coun][0],
                           (long)str_len(&cmd_buf[coun][0]));
                Write(output,"\n\r",2L);
              }
             break;

     case SHIFTL:
     case SHIFTR:
            shift = TRUE;
	    break;
     case ALTL:
     case ALTR:
            alt = TRUE;
            break;
        
     case CONTROL:
            control = TRUE;
            break;


     case BACKSP:
            if(shift){
               shift = FALSE;
               while(cmd_str[cmd_ptr-1] != 32){
                  --cmd_ptr;
                  if(cmd_ptr < 0){
                     cmd_ptr = 0;
                     break;
                   }
                  del_String_Char();
                }
             }  
            else
             { --cmd_ptr;
               if(cmd_ptr < 0)cmd_ptr = 0;
                        del_String_Char();
             }    
            zeige_String();
            curs_Pos((long)cmd_ptr);
            break;

        case DEL:
            if(shift)
             { shift = FALSE;
               while(cmd_str[cmd_ptr] != 32
                     && cmd_str[cmd_ptr] != 0)
                               del_String_Char();
             }    
            else del_String_Char();
            zeige_String();       		    
            break;

        case ENTER:
        case RETURN:
            cmd_count = old_cmd_count;
            str_copy
                 (&cmd_buf[cmd_count][0],&cmd_str[0]);
            if(++cmd_count > 9)cmd_count = 0;
            old_cmd_count = cmd_count;
            SetWindowTitles(ow,&cmd_str[0],-1L);

            commando(&cmd_str[0]);

            ActivateWindow(iw);
            curs_Pos(0L);
            cmd_ptr = 0;
            clear_inp();
            cmd_str[0] = '\0';
            break;
    
        case CURS_UP:
            if(--cmd_count < 0)cmd_count = 9;
            str_copy
                 (&cmd_str[0],&cmd_buf[cmd_count][0]);
            zeige_String();
            curs_Pos((long)(cmd_ptr = 0));
            break;


        case CURS_DOWN:
            if(++cmd_count > 9)cmd_count = 0;
            str_copy
                (& cmd_str[0],& cmd_buf[cmd_count][0]);
            zeige_String();
            curs_Pos((long)(cmd_ptr = 0));
            break;


        case CURS_L:
            if(shift)
             { shift = FALSE;
               cmd_ptr = 0;
             }
            else
             { if(alt)
                { alt = FALSE;
                  while(cmd_str[--cmd_ptr] != 32 
                                    && cmd_ptr>= 0);
                }
               else
                { --cmd_ptr;
                  if(cmd_ptr < 0)cmd_ptr = 0;
                }
             } 
            curs_Pos((long)cmd_ptr);
            break;

        case CURS_R:
            if(shift)
             { shift = FALSE;
               cmd_ptr = STL;
             }
	   else
            { if(alt)
               { alt = FALSE;
                 while(cmd_str[++cmd_ptr] != 32 
                             && cmd_ptr <= STL );
               }
              else
               {
                 ++cmd_ptr;
                 if(cmd_ptr > STL)cmd_ptr = STL;
               }
            }
           curs_Pos((long)cmd_ptr);          
           break;

        case F1:
                if(alt)
                 { alt = FALSE;
                   Write(output,"ALT     F1",10L);
                   ende();
		   break;
                  }

                if(shift)
                  { shift = FALSE;
                    Write(output,"SHIFT   F1",10L);
                    break;
                  }

                if(control)
                 { control = FALSE;
                   if(keytyp )
                    {  keytyp = FALSE;
                       onshift = onshift_usa;
                       onunshift = onunshift_usa;
                    }
                   else 
                    { keytyp = TRUE;
                      onshift = onshift_d;
                      onunshift = onunshift_d;
                    }
                 }
                else
                 { str_copy(FKC,"RUN EM \0");
                   str_cat(FKC,WF);
                   str_cat(FKC,".c\0");
                   PFC;
                   commando(FKC);   
                 } 
                 break;

        case F2:
                if(alt)
                  {
                  }

                if(shift)
                  {
                  }

                if(control)
                  {
                  }
                else
                  {
                    str_copy(FKC,"CC \0");
                    if(redir_errors)
                      str_cat(FKC,"> PAR: -B \0");
                    str_cat(FKC,CO);
                    str_cat(FKC," \0");
                    str_cat(FKC,WF);
                    str_cat(FKC,".c\0");
                    PFC;
                    commando(FKC);
                    str_copy(FKC,"LN \0");
                    str_cat(FKC,WF);
                    str_cat(FKC,".o \0");
                    str_cat(FKC,LO);
                    PFC;
                    commando (FKC);
                  } 
                 break;

        case F3:
                if(alt)
                  {
                  }

                if(shift)
                  {
                  }

                if(control)
                  {
                  }
                else
                  {
                    str_copy(FKC,WF);
                    PFC;
                    EFC;
                  } 
                 break;

        case F4:
                if(alt)
                  {
                  }

                if(shift)
                  {
                  }

                if(control)
                  {
                  }
                else
                  {
                    str_copy(FKC,"type > PAR: \0");
                    str_cat(FKC,WF);
                    str_cat(FKC,".c\0");
                    PFC;
                    EFC;
                  } 
                 break;

        case F5:
                if(alt)
                  {
                  }

                if(shift)
                  {
                  }

                if(control)
                  {
                  }
                else
                  {
                    neue_Option(CO,"EDIERE COMPILER OPTION\0");
                    zeigeInfo();                 
                  } 
                 break;

        case F6:
                if(alt)
                  {
                  }

                if(shift)
                  {
                  }

                if(control)
                  {
                  }
                else
                  {
                    neue_Option(LO,"EDIERE LINKER OPTION\0");
                    zeigeInfo();
                  } 
                 break;

        case F7:
                if(alt)
                  {
                  }

                if(shift)
                  {
                  }

                if(control)
                  {
                  }
                else
                  {
                    if(redir_errors)
                      redir_errors = FALSE;
                    else redir_errors  = TRUE;
                    zeigeInfo();
                  } 
                 break;

        case F8:
                if(alt)
                  {
                  }

                if(shift)
                  {
                  }

                if(control)
                  {
                  }
                else
                  {
                    str_copy(FKC,"Optionen Speichern\0");
                    PFC;
                    save_file = 
                       Open("s:optionen",MODE_NEWFILE);
                    Write(save_file,WF,str_len(WF));
                    Write(save_file,CO,str_len(WF));
                    Write(save_file,LO,str_len(WF));
                    Close(save_file);
                  } 
                 break;

        case F9:
                if(alt)
                  {
                  }

                if(shift)
                  {
                  }

                if(control)
                  {
                  }
                else
                  {
                    neue_Option(WF,"NEUER ARBEITSFILE ?\0");
                    zeigeInfo();
                  } 
                 break;

       } /* End of switch(taste) */
 } /* End of verarbeiteRAW()  */

/*  Umformung der Schriftzeichen in ASCII-Werte und 
    diese an den String anhängen.
    Edierfunktionen erfolge über die RAW-Tasten.
    Dazu wird die Position im String cmd_ptr    
     festgehalten     */

verarbeiteASCII()


  {
    if(!shift)
      {
        empf_char = *(onunshift+TASTE);
      } 

     if(shift)
      {
        empf_char = *(onshift+TASTE);
	shift = FALSE;
      }
    
    zahl = STL;
    
    while(zahl >= cmd_ptr)
      {
        cmd_str[(zahl+1)] = cmd_str[zahl];
        zahl--;
      }
    cmd_str[cmd_ptr] = empf_char;
    ++cmd_ptr;

    zeige_String();
    curs_Pos((long)cmd_ptr);
  } 

/* Zeichen auf dem cmd_ptr wird gelöscht
   und dahinterstehende vorgezogen       */
del_String_Char()
  {
    SHORT loop;
    
    for(loop = cmd_ptr;cmd_str[loop];++loop)
      {
        cmd_str[loop] = cmd_str[loop +1];
      }
  }

/* diese Funktion setzt den Cursor */
curs_Pos(neupos)

  LONG neupos;

  {
    SetAPen(RASTP,0L);
    Move(RASTP,2L,22L);
    Draw(RASTP,638L,22L);

    SetAPen(RASTP,1L);
    Move(RASTP,neupos*8L+2L,22L);
    Draw(RASTP,neupos*8L+10L,22L);
  }

/* Ausstieg aus dem Programm.  Freigeben aller
   geöffneten Bestandteile an das System     */
 ende()
  {
    if(finfoptr)FreeMem(finfoptr,(long)sizeof(struct FileInfoBlock));
    if(iw)CloseWindow(iw);
    if(GfxBase)CloseLibrary(GfxBase);
    if(IntuitionBase)CloseLibrary(IntuitionBase);
    Exit(TRUE);
  }

/* Darstellung des Befehlsstrings im Eingabefenster */
zeige_String()
  {
    clear_inp();
    Move(RASTP,2L,20L);
    Text(RASTP,&cmd_str[0],(long)(STL));
  }

/* Löschen der Eingabezeile */
clear_inp()
  { 
                     
    Move(RASTP,2L,20L);
    Text(RASTP,"                                                         ",57L);
   }

/* Bestimmung der Stringlänge   */
str_len(s)

  char *s;

  {
    char *cp = s;

    while(*cp++);
    return(cp-s-1);
  }

/* String kopieren von Quelle nach Ziel    */
str_copy(ziel,quelle)

  char *ziel, *quelle;

  {
    while ((*ziel++ = *quelle++) != '\0');
  }

/* String zweiter an erster anhängen */
str_cat(erster,zweiter)

  char *erster, *zweiter;

  {
    SHORT loop;

    while(*erster != '\0')
        erster++;

    while((*(erster++) = *(zweiter++)) != '\0');
  }

/* Ausführung eines Kommandos nach einem <RETURN>  */
commando(unchecked)

  char *unchecked;

  {
    char *name,*argv[3],*pos1,*pos2;
    char commandoname[20],argument[40];
    
    pos1 = name = &commandoname[0];
    pos2 = argv[1] = &argument[0];
    argv[2] = NULL;

    /* Aktivieren des Ausgabewindows */
    ActivateWindow(ow);

    Write(output,"\n\r\n\r",4L);
    /* Überflüssige Leerstellen beseitigen */
    while( *unchecked == 32 )unchecked++;
    while( *unchecked != 32 && *unchecked != 0 )
       *pos1++ = *unchecked++;
    *pos1 = 0;

    /* RUN und Output-Redirection wird durch
       Execute() realisiert                    */
    if(str_cmp("run\0",name) || *(unchecked+1)=='<'
       || *(unchecked+1) == '?' || *(unchecked+1)=='>')
            return(Execute(&cmd_str[0],NULL,NULL));
    
    /* nochmals Leerstellen beseitigen und 
       Argument bestimmen */          
    if(*unchecked)
      while( *unchecked == 32 )unchecked++;
      while( *pos2++ = *unchecked++ );
    *pos2 = 0;

    fexecv(name,argv);

  }

/* Vergleiche Strings*/
str_cmp(str1,str2)

  char *str1,*str2;
  
   {
    while( *str1++ == *str2++ )
      {
        if(*str1 == 0 && *str2 == 0)return(1);
      }
    return(0);
  }

/* gibt Variablen des Compiler Systems aus */
zeigeInfo()

  {
    LONG loop;
    for(loop=2;loop<=624;loop+=8){
       Move(RASTP,loop,29L);
       Text(RASTP," ",1L);
       Move(RASTP,loop,38L);
       Text(RASTP," ",1L);
     }
     
    Move(RASTP,2L,29L);
    Text(RASTP,"source file : ",14L);

    Move(RASTP,320L,29L);
    Text(RASTP,"compiler option : ",18L);    

    Move(RASTP,2L,38L);
    Text(RASTP,"linker option : ",16L);

    Move(RASTP,130L,29L);
    Text(RASTP,WF,(long)str_len(WF));  

    Move(RASTP,464L,29L);
    Text(RASTP,CO,(long)str_len(CO)); 

    Move(RASTP,130L,38L);
    Text(RASTP,LO,(long)str_len(LO));

    Move(RASTP,320L,46L);
    if(redir_errors)Text(RASTP,"CC > PAR:",8L);
    else            Text(RASTP,"CC > *   ",8L);

  }

UBYTE puffer1[40],puffer2[40];

SHORT xy_pt2[] = { -2,-2,-2,9,322,9,322,-2,-2,-2 };
SHORT xy_pt1[] = { 0,0,0,10,60,10,60,0,0,0 };

struct Border rahmen =
      { 0,0,1,0,JAM1,5,(SHORT *)&xy_pt1[0],NULL };

struct Border str_rahmen =
      { 0,0,1,0,JAM1,5,(SHORT *)&xy_pt2[0],NULL };

struct StringInfo option_str =
      {(UBYTE *)&puffer1[0],(UBYTE *)&puffer2[0],0,40,0,
       NULL,NULL,NULL,NULL,NULL,NULL,NULL };

struct IntuiText ok_txt = {(UBYTE)1,(UBYTE)0,JAM1,2,2,
                          NULL,(UBYTE *)"  OK!  \0",NULL };

struct IntuiText cancel_txt = {(UBYTE)1,(UBYTE)0,JAM1,2,2,
                           NULL,(UBYTE *)"CANCEL!\0",NULL };

struct Gadget option_gad =
      { NULL,10,12,320,9,SELECTED,TOGGLESELECT,
        STRGADGET,(APTR)&str_rahmen,NULL,NULL,0,(APTR)
        &option_str,NULL,NULL };

struct Gadget ok_gad =
      { &option_gad,10,25,60,10,GADGHNONE,GADGIMMEDIATE
        |RELVERIFY,BOOLGADGET,(APTR)&rahmen,NULL,&ok_txt,
        NULL,NULL,2,NULL };

struct Gadget cancel_gad =
      { &ok_gad,270,25,60,10,GADGHNONE,GADGIMMEDIATE
        |RELVERIFY,BOOLGADGET,(APTR)&rahmen,NULL,
        &cancel_txt,NULL,NULL,1,NULL };

neue_Option(option,text)

  char *option, *text;

  {
    struct Window *gadwindow;
    struct Gadget *empf_gad;
 
    newwind.LeftEdge = 150;  
    newwind.TopEdge  = 100;
    newwind.Width    = 340;
    newwind.Height   = 50;
    newwind.DetailPen = 0;
    newwind.BlockPen = 1; 
    newwind.Title    = (UBYTE *)text;
    newwind.Flags    = ACTIVATE|SIMPLE_REFRESH;
    newwind.IDCMPFlags = MOUSEBUTTONS|GADGETDOWN;
    newwind.Type       = WBENCHSCREEN;
    newwind.FirstGadget= &cancel_gad;
    newwind.CheckMark  = NULL;
    newwind.Screen     = NULL;
    newwind.BitMap     = NULL;
    newwind.MinWidth   = 200;
    newwind.MinHeight  = 25;
    newwind.MaxWidth   = 640;
    newwind.MaxHeight  = 150;
      
    str_copy(&puffer1[0],option);
    str_copy(&puffer2[0],option);
 	 
    if (( gadwindow = (struct Window *)
          OpenWindow(&newwind)) == NULL) ende();

    OnGadget(&option_gad,gadwindow,NULL);    

    IMMER
      {
	Wait(1L<<gadwindow->UserPort->mp_SigBit);

	while(botschaft = (struct IntuiMessage *)GetMsg(gadwindow->UserPort))
	  {
            if(ART == GADGETDOWN)
              {
                empf_gad = (struct Gadget *)botschaft->IAddress;
                switch(empf_gad->GadgetID)
                  {
                    case 2:
                            str_copy(option,puffer1);
                    case 1:
                            CloseWindow(gadwindow);
                            puffer1[0]=puffer2[0]=0;
                            return;
                    default:
                            break;
                  }
              }
             ReplyMsg(botschaft);

          }    /* END OF while */
                
      }     /* END OF IMMER */
    
  }


