#include "prefs.h"

#include <exec/types.h>
#include <exec/io.h>
#ifdef LATTICE
#include <proto/asl.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/diskfont.h>
#endif
#include <dos/dosextens.h>
#include <graphics/text.h>
#include <intuition/screens.h>
#include <intuition/intuition.h>
#include <utility/tagitem.h>
#include <graphics/view.h>
#include <graphics/displayinfo.h>
#include <devices/console.h>
#include <devices/inputevent.h>
#include <exec/devices.h>
#include <libraries/asl.h>
#include <string.h>



struct Library  *IntuitionBase = NULL;
struct Library  *GfxBase = NULL;
struct Library  *DiskfontBase = NULL;
struct Library  *AslBase = NULL;
struct Screen   *screen = NULL;
struct Window   *window = NULL;
struct Window   *wintmp = NULL;
struct IOStdReq *writereq = NULL;
struct MsgPort  *writeport = NULL;
struct IOStdReq *readreq = NULL;
struct MsgPort  *readport = NULL;
struct TextAttr textAttrStd;
struct TextAttr textAttrPager;
struct TextAttr textAttrIntui;
struct TextFont *textFontStd = NULL;
struct TextFont *textFontPager = NULL;
struct TextFont *textFontIntui = NULL;
struct TextFont *oldTextFont = NULL;
struct Process  *process = NULL;
BOOL consoleOpen = FALSE;
BOOL showtitle   = FALSE;
int Win_Height = 0;
int Win_Width  = 0;
int Std_Win_Height = 0;
int Std_Win_Width  = 0;
int Pager_Win_Height = 0;
int Pager_Win_Width  = 0;
int Screen_Height = 200;
int Screen_Width  = 640;
int Screen_Interlace = 0;
int shell_count = 0;
UWORD PublicModes = 0;
char WinTitleBuffer[256];



Prototype void close_intuition(void);
Prototype BOOL IsAslOpen(void);
Prototype BOOL GetAslFRQ(char *,char *,char *);
Prototype BOOL open_intuition(void);
Prototype BOOL intui_interface(void);
Prototype void SetScreenTitle(char *);
Prototype char getch(void);
Prototype long getst(char *,long);
Prototype void flush_input(void);
Prototype void putch(char);
Prototype void putst(char *);
Prototype void putst_center(char *);
Prototype void putst_center_bold(char *);
Prototype void putstl(char *,long);
Prototype void ElmToFront(void);
Prototype void WorkbenchToFront(void);
Prototype void SetStdFont(void);
Prototype void SetPagerFont(void);
Prototype void open_shell(void);



void close_intuition(void)
{
  if (consoleOpen) CloseDevice(writereq);		consoleOpen = FALSE;
  if (readreq) DeleteExtIO(readreq);			readreq = NULL;
  if (readport) DeletePort(readport);			readport = NULL;
  if (writereq) DeleteExtIO(writereq);			writereq = NULL;
  if (writeport) DeletePort(writeport);			writeport = NULL;
  if (window) {
    SetFont(window->RPort,oldTextFont);
    if (process) process->pr_WindowPtr = wintmp;
    CloseWindow(window);
    window = NULL;
  }
  if (screen) {
    if (IntuitionBase->lib_Version<36)
      CloseScreen(screen);
    else {
      if (PubScreenName)
        PubScreenStatus(screen,PSNF_PRIVATE);
      while(!CloseScreen(screen))
        Delay(50L);
    }
    screen = NULL;
  }

  if (textFontStd)   CloseFont(textFontStd);      textFontStd   = NULL;
  if (textFontPager) CloseFont(textFontPager);    textFontPager = NULL;
  if (textFontIntui) CloseFont(textFontIntui);    textFontIntui = NULL;
  if (IntuitionBase) CloseLibrary(IntuitionBase); IntuitionBase = NULL;
  if (GfxBase)       CloseLibrary(GfxBase);       GfxBase       = NULL;
  if (DiskfontBase)  CloseLibrary(DiskfontBase);  DiskfontBase  = NULL;
  if (AslBase)       CloseLibrary(AslBase);       AslBase       = NULL;
}



BOOL IsAslOpen(void)
{
  return(AslBase!=NULL);
}



BOOL GetAslFRQ(char *dir,char *file,char *res)
{
  BOOL ret = FALSE;

  if (AslBase) {
    struct FileRequester *frq;
    struct TagItem frq_tags[5];

    frq_tags[0].ti_Tag  = ASL_Hail;
    frq_tags[0].ti_Data = (ULONG)"Select a file";
    frq_tags[1].ti_Tag  = ASL_Window;
    frq_tags[1].ti_Data = (ULONG)window;
    frq_tags[2].ti_Tag  = ASL_Dir;
    frq_tags[2].ti_Data = (ULONG)dir;
    frq_tags[3].ti_Tag  = ASL_File;
    frq_tags[3].ti_Data = (ULONG)file;
    frq_tags[4].ti_Tag  = TAG_DONE;

    if (frq = AllocAslRequest(ASL_FileRequest,frq_tags)) {
      if (ret=AslRequest(frq,NULL)) {
        strcpy(res,frq->rf_Dir);
        AddPart(res,frq->rf_File,256L);
/*
        strcpy(res,frq->rf_Dir);
        if (strlen(res)>0) {
          switch(res[strlen(res)-1]) {
          case ':': break;
          case '/': break;
          default:
            strcat(res,"/");
            break;
          }
        }
        strcat(res,frq->rf_File);
*/
      }

      FreeAslRequest(frq);
    }
  }

  return(ret);
}


void SetConBorders(void)
{
  if (UseOwnScreen) {
    if (IntuitionBase->lib_Version<36)
      sprintf(TBuffer,"%c%d%c",0x9b,screen->BarHeight+3,0x79);
    else
      sprintf(TBuffer,"%c%d%c",0x9b,screen->BarHeight+4,0x79);
  }
  else {
    if (IntuitionBase->lib_Version<36)
      sprintf(TBuffer,"%c%d%c",0x9b,window->BorderTop,0x79);
    else
      sprintf(TBuffer,"%c%d%c%c%d%c",0x9b,window->BorderTop+1,0x79,0x9b,window->BorderLeft+1,0x78);
  }
  outline();
}



void GetWinDimensions(int *width,int *height)
{
  char str[80];
  int pos=0;

  /* get window height and width */

  putst("\033c");
  SetConBorders();
  sprintf(TBuffer,"%c%c%c%c",0x9b,0x30,0x20,0x71);
  outline();
  do {
    str[pos++]=getch();
  }
  while (str[pos-1]!='r');
  pos--;  /* 'r' */
  pos--;  /* ' ' */
  str[pos]='\0';

#define isnum(x) ((x)>='0' && (x)<='9')

  do {pos--;} while (isnum(str[pos]));
  pos++;

  *width = atoi(&str[pos]);

  pos--;
  str[pos]='\0';
  do {pos--;} while (isnum(str[pos]));
  pos++;

  *height = atoi(&str[pos]);

  /*printf("Dimensions: %dx%d chars\n",*width,*height);*/
}



void SetMyFont(struct TextFont *myFont)
{
  SetFont(window->RPort,myFont);
  putst("\033c");
  SetConBorders();
}



void SetStdFont(void)
{
  SetMyFont(textFontStd);
  Win_Width  = Std_Win_Width;
  Win_Height = Std_Win_Height;
}



void SetPagerFont(void)
{
  SetMyFont(textFontPager);
  Win_Width  = Pager_Win_Width;
  Win_Height = Pager_Win_Height;
}



BOOL open_intuition(void)
{
  struct NewScreen newscreen;
  struct NewWindow newwindow;
  UWORD pen_array = ~0;
  WORD size_array[4];
  struct TagItem screen_tags[4];
  struct TagItem window_tags[2];
  int i;
  char *scanpnt;
  long color;

  /* initialize */
  screen_tags[0].ti_Tag  = SA_Pens;
  screen_tags[0].ti_Data = (ULONG)&pen_array;
  screen_tags[1].ti_Tag  = TAG_END;
  screen_tags[1].ti_Data = NULL;
  screen_tags[2].ti_Tag  = TAG_END;
  screen_tags[2].ti_Data = NULL;
  screen_tags[3].ti_Tag  = TAG_END;
  screen_tags[3].ti_Data = NULL;

  if (!(IntuitionBase=OpenLibrary("intuition.library",33L))) {
    fprintf(stderr,"elm: cannot open intuition.library\n");
    close_intuition();
    return(FALSE);
  }

  if (!(GfxBase=OpenLibrary("graphics.library",33L))) {
    fprintf(stderr,"elm: cannot open graphics.library\n");
    close_intuition();
    return(FALSE);
  }

  if (!(DiskfontBase=OpenLibrary("diskfont.library",33L))) {
    fprintf(stderr,"elm: cannot open diskfont.library\n");
    close_intuition();
    return(FALSE);
  }

  if (!(AslBase=OpenLibrary("asl.library",37L))) {
  /*
    fprintf(stderr,"elm: cannot open asl.library (V37)\n");
    close_intuition();
    return(FALSE);
  */
  }

/*
  textAttrIntui.ta_Name  = "topaz.font";
  textAttrIntui.ta_YSize = 8;
  textAttrIntui.ta_Style = FS_NORMAL;
  textAttrIntui.ta_Flags = FPF_ROMFONT;
*/

  textAttrIntui.ta_Name  = IntuiFontName;
  textAttrIntui.ta_YSize = IntuiFontSize;
  textAttrIntui.ta_Style = NULL;
  textAttrIntui.ta_Flags = NULL;

  if (!(textFontIntui=OpenDiskFont(&textAttrIntui))) {
    fprintf(stderr,"elm: cannot open font %s/%d\n",IntuiFontName,IntuiFontSize);
    textAttrIntui.ta_Name  = "topaz.font";
    textAttrIntui.ta_YSize = 8;
    textAttrIntui.ta_Style = FS_NORMAL;
    textAttrIntui.ta_Flags = FPF_ROMFONT;
  }

  textAttrStd.ta_Name  = StdFontName;
  textAttrStd.ta_YSize = StdFontSize;
  textAttrStd.ta_Style = NULL;
  textAttrStd.ta_Flags = NULL;

  if (!(textFontStd=OpenDiskFont(&textAttrStd))) {
    fprintf(stderr,"elm: cannot open font %s/%d\n",StdFontName,StdFontSize);
    close_intuition();
    return(FALSE);
  }

  textAttrPager.ta_Name  = PagerFontName;
  textAttrPager.ta_YSize = PagerFontSize;
  textAttrPager.ta_Style = NULL;
  textAttrPager.ta_Flags = NULL;

  if (!(textFontPager=OpenDiskFont(&textAttrPager))) {
    fprintf(stderr,"elm: cannot open font %s/%d\n",PagerFontName,PagerFontSize);
    close_intuition();
    return(FALSE);
  }

  if (UseOwnScreen) {
    newscreen.LeftEdge     = 0;
    newscreen.TopEdge      = 0;
    newscreen.Width        = Screen_Width;
    newscreen.Height       = Screen_Height;
    newscreen.Depth        = 2;
    newscreen.DetailPen    = AUTOFRONTPEN;
    newscreen.BlockPen     = AUTOBACKPEN;
    newscreen.Type         = CUSTOMSCREEN;
    newscreen.Font         = &textAttrIntui;
    newscreen.DefaultTitle = "Amiga Elm © 1991-1992 Andreas M. Kirchwitz (original Heiko W. Rupp)";
    newscreen.Gadgets      = NULL;
    newscreen.CustomBitMap = NULL;

    if (Screen_Interlace)
      newscreen.ViewModes  = HIRES|LACE;
    else
      newscreen.ViewModes  = HIRES;

    if (IntuitionBase->lib_Version<36) {
      struct Screen WBScreen;
      if (GetScreenData(&WBScreen,sizeof(struct Screen),WBENCHSCREEN,NULL)) {
        newscreen.ViewModes = WBScreen.ViewPort.Modes;
        if (Screen_Interlace)
          newscreen.ViewModes  |= LACE;
        else
          newscreen.ViewModes  &= (~LACE);
      }

      if (!(screen=OpenScreen(&newscreen))) {
        fprintf(stderr,"elm: cannot open screen\n");
        close_intuition();
        return(FALSE);
      }
    }
    else {
      long WBModeID;
      struct Screen *WBScreen;
      if (WBScreen=LockPubScreen("Workbench")) {
        WBModeID=GetVPModeID(&WBScreen->ViewPort);
        UnlockPubScreen(NULL,WBScreen);
        screen_tags[1].ti_Tag  = SA_DisplayID;
        screen_tags[1].ti_Data = WBModeID;
        if (Screen_Interlace) {
          screen_tags[1].ti_Data |= 4L;
        }
        else {
          screen_tags[1].ti_Data &= (~4L);
        }
        if (PubScreenName) {
          screen_tags[2].ti_Tag  = SA_PubName;
          screen_tags[2].ti_Data = (ULONG)PubScreenName;
        }
      }

      if (!(screen=OpenScreenTagList(&newscreen,screen_tags))) {
        fprintf(stderr,"elm: cannot open screen\n");
        fprintf(stderr,"(subliminal hint: public screen name not unique)\n");
        close_intuition();
        return(FALSE);
      }

      PublicModes = SetPubScreenModes(0);
      SetPubScreenModes(PublicModes);

      /* Are we to make our screen public? */

      if (PubScreenName)
        PubScreenStatus(screen,NULL);
/*
      else
        PubScreenStatus(screen,PSNF_PRIVATE);
*/

      /* Are we to `shanghai' Workbench windows? */

      if (ShanghaiWindows) {
        PublicModes |= SHANGHAI;
        SetPubScreenModes(PublicModes);
        /* Make this the default public screen. */
        SetDefaultPubScreen(PubScreenName);
      }
      else {
        char DefaultPubScreen[MAXPUBSCREENNAME+1];
        PublicModes &= ~SHANGHAI;
        GetDefaultPubScreen(DefaultPubScreen);
        if (LockPubScreen(DefaultPubScreen)) {
          SetDefaultPubScreen(DefaultPubScreen);
          UnlockPubScreen(DefaultPubScreen,NULL);
        }
        else
          SetDefaultPubScreen(NULL);
        SetPubScreenModes(PublicModes);
      }
    }

    if (scanpnt=ColorData) {
      for(i=0;i<(1L<<newscreen.Depth);i++) {
        color = strtol(scanpnt,&scanpnt,0);
        SetRGB4(&(screen->ViewPort),i,(color >> 8) & 0xf, (color >> 4) & 0xf, color & 0xf);
      }
    }

    /* test output for OS 1.3 -vs- OS 2.0 */

    /*
    printf("BarHeight: %d, BarVBorder: %d, BarHBorder: %d\n",
		screen->BarHeight,screen->BarVBorder,screen->BarHBorder);
    printf("MenuVBorder: %d, MenuHBorder: %d\n",
		screen->MenuVBorder,screen->MenuHBorder);
    printf("WBorTop: %d, WBorLeft: %d, WBorRight: %d, WBorBottom: %d\n",
		screen->WBorTop,screen->WBorLeft,screen->WBorRight,screen->WBorBottom);
    */

    /* end of test output */
  }

  newwindow.LeftEdge     = 0;
  newwindow.TopEdge      = 0;
  newwindow.DetailPen    = AUTOFRONTPEN;
  newwindow.BlockPen     = AUTOBACKPEN;
  newwindow.IDCMPFlags   = NULL;
  newwindow.FirstGadget  = NULL;
  newwindow.CheckMark    = NULL;
  newwindow.BitMap       = NULL;

  if (UseOwnScreen) {
    newwindow.Width      = screen->Width;
    newwindow.Height     = screen->Height;
    newwindow.Flags      = WFLG_BACKDROP|WFLG_BORDERLESS|WFLG_RMBTRAP|WFLG_NOCAREREFRESH|WFLG_ACTIVATE;
    newwindow.Screen     = screen;
    newwindow.Type       = CUSTOMSCREEN;
    newwindow.MinWidth   = screen->Width;
    newwindow.MinHeight  = screen->Height;
    newwindow.MaxWidth   = screen->Width;
    newwindow.MaxHeight  = screen->Height;
    newwindow.Title      = NULL;
  }
  else {
    newwindow.Width      = Screen_Width;
    newwindow.Height     = Screen_Height;
    if (IntuitionBase->lib_Version<36)
      newwindow.Flags    = WFLG_RMBTRAP|WFLG_NOCAREREFRESH|WFLG_ACTIVATE|WFLG_DRAGBAR|WFLG_DEPTHGADGET;
    else
      newwindow.Flags    = WFLG_RMBTRAP|WFLG_ACTIVATE|WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_SIMPLE_REFRESH;
/*      newwindow.Flags    = WFLG_RMBTRAP|WFLG_NOCAREREFRESH|WFLG_ACTIVATE|WFLG_DRAGBAR|WFLG_DEPTHGADGET;*/
/*      newwindow.Flags    = WFLG_RMBTRAP|WFLG_NOCAREREFRESH|WFLG_ACTIVATE|WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_SMART_REFRESH;*/
/*      newwindow.Flags    = WFLG_RMBTRAP|WFLG_NOCAREREFRESH|WFLG_ACTIVATE|WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_SIMPLE_REFRESH;*/
/*
	bugs:
		1. Setzt man WFLG_SIMPLE_REFRESH, geht der Inhalt verloren,
		   wenn das Elm-Window von anderen Windows ueberlagert wird.
		   (aber ohne dieses Flag geht console.device, unit 1 nicht)
		2. Setzt man WFLG_SIMPLE_REFRESH und benutzt das "Zoom"-Gadget,
		   wird beim zweiten Anklicken der Inhalt des Windows falsch
		   wiederhergestellt.  Anfaengliche Leerzeilen werden geloescht,
		   der Windowaufbau ist also ggf. verschoben um eine oder mehr
		   Zeilen.  (somit voellig unbrauchbar)
*/
    newwindow.Screen     = NULL;
    newwindow.Type       = WBENCHSCREEN;
    newwindow.MinWidth   = Screen_Width;
    newwindow.MinHeight  = Screen_Height;
    newwindow.MaxWidth   = Screen_Width;
    newwindow.MaxHeight  = Screen_Height;
    newwindow.Title      = "Amiga Elm © 1991-1992 Andreas M. Kirchwitz (original Heiko W. Rupp)";
  }

  if (IntuitionBase->lib_Version<36) {
    if (!(window=OpenWindow(&newwindow))) {
      fprintf(stderr,"elm: cannot open window\n");
      close_intuition();
      return(FALSE);
    }
  }
  else {
    struct Screen *WBScreen;
    if (WBScreen=LockPubScreen("Workbench")) {
      size_array[3] = WBScreen->BarHeight+1;
      UnlockPubScreen(NULL,WBScreen);
    }
    else {
      fprintf(stderr,"strange: cannot examine Workbench screen\n");
      size_array[3] = 13;
    }
    /* dimensions of zoomed window */
    size_array[0] = 0;
    size_array[1] = 0;
    size_array[2] = newwindow.Width;

    window_tags[0].ti_Tag  = WA_Zoom;
    window_tags[0].ti_Data = (ULONG)&size_array;
    window_tags[1].ti_Tag  = TAG_END;
    window_tags[1].ti_Data = NULL;
    if (!(window=OpenWindowTagList(&newwindow,window_tags))) {
      fprintf(stderr,"elm: cannot open window\n");
      close_intuition();
      return(FALSE);
    }
  }

  process = (struct Process *) FindTask(NULL);
  wintmp = process->pr_WindowPtr;
  process->pr_WindowPtr = (APTR) window;
  oldTextFont = window->RPort->Font;
  SetFont(window->RPort,textFontStd);

  if (!(writeport=CreatePort("Elm-Console.write",0L))) {
    fprintf(stderr,"elm: cannot open console write port\n");
    close_intuition();
    return(FALSE);
  }

  if (!(readport=CreatePort("Elm-Console.read",0L))) {
    fprintf(stderr,"elm: cannot open console read port\n");
    close_intuition();
    return(FALSE);
  }

  if (!(writereq=CreateExtIO(writeport,(long)sizeof(struct IOStdReq)))) {
    fprintf(stderr,"elm: cannot open console write request\n");
    close_intuition();
    return(FALSE);
  }

  if (!(readreq=CreateExtIO(readport,(long)sizeof(struct IOStdReq)))) {
    fprintf(stderr,"elm: cannot open console read request\n");
    close_intuition();
    return(FALSE);
  }

  writereq->io_Data = (APTR)window;
  writereq->io_Length = sizeof(struct Window);

  if (IntuitionBase->lib_Version>=36 && !UseOwnScreen) {
    if (OpenDevice("console.device",1L,writereq,0L)) {
      fprintf(stderr,"elm: cannot open console.device\n");
      close_intuition();
      clean_exit(20);
    }
  }
  else {
    if (OpenDevice("console.device",0L,writereq,0L)) {
      fprintf(stderr,"elm: cannot open console.device\n");
      close_intuition();
      clean_exit(20);
    }
  }
  consoleOpen = TRUE;

  readreq->io_Device = writereq->io_Device;
  readreq->io_Unit   = writereq->io_Unit;

  GetWinDimensions(&Std_Win_Width,&Std_Win_Height);
  SetFont(window->RPort,textFontPager);
  GetWinDimensions(&Pager_Win_Width,&Pager_Win_Height);

  if (Std_Win_Width<80 || Std_Win_Height<20) {
    fprintf(stderr,"elm: minimum standard display is 80x20 characters (you have %dx%d)\n",Std_Win_Width,Std_Win_Height);
    close_intuition();
    return(FALSE);
  }

  if (Pager_Win_Width<80 || Pager_Win_Height<20) {
    fprintf(stderr,"elm: minimum pager display is 80x20 characters (you have %dx%d)\n",Pager_Win_Width,Pager_Win_Height);
    close_intuition();
    return(FALSE);
  }

  SetStdFont();

  return(TRUE);
}



BOOL intui_interface(void)
{
  return(window!=NULL);
}



void SetScreenTitle(char *text)
{
  strcpy(WinTitleBuffer,text);
  if (UseOwnScreen) {
    SetWindowTitles(window,(UBYTE *)~0,WinTitleBuffer);
    ShowTitle(screen,TRUE);
  }
  else
    SetWindowTitles(window,WinTitleBuffer,(UBYTE *)~0);
}



void ElmToFront(void)
{
  if (UseOwnScreen)
    ScreenToFront(screen);
  else
    WBenchToFront();
    
  ActivateWindow(window);
}



void WorkbenchToFront(void)
{
  if (WBToFront)
    WBenchToFront();
}



void flush_input(void)
{
  if (UseCmdClearKludge && IntuitionBase->lib_Version>=36) {
    char *pnt;
    pnt = (char *)readreq->io_Unit;
    *(long *)((char *)pnt + 374) = 0L;
  }
  else {
    readreq->io_Command = CMD_CLEAR;
    DoIO(readreq);
  }
}



char getch(void)
{
  char ch = '\0';
  readreq->io_Command = CMD_READ;
  readreq->io_Data    = (APTR)&ch;
  readreq->io_Length  = 1;
  DoIO(readreq);
  return(ch);
}



long getst(char *buffer,long limit)
{
  register long len = 0L;
  char ch;

  while ((ch=getch())!='\r') {
    if (ch=='\b') {
      if (len>0) {
        putst("\b \b");
        len--;
      }
    }
    else if (ch==0x1b || ch==0x9b) {
    }
    else {
      if (len<limit)
        putch( buffer[len++] = ch );
    }
  }

  buffer[len] = '\0';

  return(len);
}



void putch(char ch)
{
  writereq->io_Command = CMD_WRITE;
  writereq->io_Data    = (APTR)&ch;
  writereq->io_Length  = 1;
  DoIO(writereq);
}



void putst(char *buffer)
{
  writereq->io_Command = CMD_WRITE;
  writereq->io_Data    = (APTR)buffer;
  writereq->io_Length  = strlen(buffer);
  DoIO(writereq);
}



void putst_center(char *buffer)
{
  int i,pos;
  char *cbuf;

  if (cbuf=malloc(Win_Width+1)) {   /* null terminator */
    for(pos=0,i=strlen(buffer)+1;i<Win_Width;i+=2,pos++)
      cbuf[pos] = ' ';
    cbuf[pos] = '\0';

    writereq->io_Command = CMD_WRITE;
    writereq->io_Data    = (APTR)cbuf;
    writereq->io_Length  = strlen(cbuf);
    DoIO(writereq);
    free(cbuf);
  }

  writereq->io_Command = CMD_WRITE;
  writereq->io_Data    = (APTR)buffer;
  writereq->io_Length  = strlen(buffer);
  DoIO(writereq);
}



void putst_center_bold(char *buffer)
{
  int i,pos;
  char *cbuf;

  if (cbuf=malloc(Win_Width+5)) {   /* null terminator + bold face on */
    for(pos=0,i=strlen(buffer)+1;i<Win_Width;i+=2,pos++)
      cbuf[pos] = ' ';
    cbuf[pos] = '\0';
    strcat(cbuf,"\033[1m");

    writereq->io_Command = CMD_WRITE;
    writereq->io_Data    = (APTR)cbuf;
    writereq->io_Length  = strlen(cbuf);
    DoIO(writereq);
    free(cbuf);
  }

  writereq->io_Command = CMD_WRITE;
  writereq->io_Data    = (APTR)buffer;
  writereq->io_Length  = strlen(buffer);
  DoIO(writereq);

  putst("\033[m");
}



void putstl(char *buffer,long length)
{
  writereq->io_Command = CMD_WRITE;
  writereq->io_Data    = (APTR)buffer;
  writereq->io_Length  = length;
  DoIO(writereq);
}



void open_shell(void)
{
  struct Window *sh_win;
  struct TagItem window_tags[2];
  struct NewWindow newwindow;
  WORD size_array[4];
  char exec[256];
  int magic_offset = 20;

  shell_count++;

  newwindow.LeftEdge    = magic_offset;
  newwindow.TopEdge     = (shell_count%2)?(magic_offset):(screen->Height/2+magic_offset/2);
  newwindow.DetailPen   = AUTOFRONTPEN;
  newwindow.BlockPen    = AUTOBACKPEN;
  newwindow.IDCMPFlags  = NULL;
  newwindow.FirstGadget = NULL;
  newwindow.CheckMark   = NULL;
  newwindow.BitMap      = NULL;
  newwindow.Width       = screen->Width-2*magic_offset;
  newwindow.Height      = screen->Height/2-2*magic_offset+magic_offset/2;
  newwindow.Flags       = WFLG_NOCAREREFRESH|WFLG_ACTIVATE|WFLG_SIZEGADGET|
                          WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|
                          WFLG_SIZEBBOTTOM;
  newwindow.Screen      = screen;
  newwindow.Type        = CUSTOMSCREEN;
  newwindow.MinWidth    = screen->Width/2;
  newwindow.MinHeight   = /* 2* */(screen->BarHeight+1);
  newwindow.MaxWidth    = screen->Width;
  newwindow.MaxHeight   = screen->Height;
  newwindow.Title       = NULL;

  /* dimensions of zoomed window */
  size_array[0] = (shell_count%2)?(0):(screen->Width/2);
  size_array[1] = screen->BarHeight+1;
  size_array[2] = screen->Width/2;
  size_array[3] = screen->BarHeight+1;

  window_tags[0].ti_Tag  = WA_Zoom;
  window_tags[0].ti_Data = (ULONG)&size_array;
  window_tags[1].ti_Tag  = TAG_END;
  window_tags[1].ti_Data = NULL;

  if (IntuitionBase->lib_Version>=36 && screen) {
    if (sh_win=OpenWindowTagList(&newwindow,window_tags)) {
      sprintf(exec,"newshell \"con:////AmigaElm Shell/WINDOW0x%lx\"",sh_win);
      Execute(exec,NULL,NULL);
    }
  }
}

