 /*
    Przykīad ten da siė skompilowaź przy pomocy kompilatora SAS/C 6.50.
    Potrzebne sā jednak include'y w wersji 37 lub nowszej.

    Program ten rozpowszechniany jest jako Public Domain.
  */

#include <proto/exec.h>
#include <exec/memory.h>
#include <proto/dos.h>
#include <proto/asl.h>
#include <proto/intuition.h>
#include <intuition/gadgetclass.h>
#include <proto/gadtools.h>
#include <proto/graphics.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <proto/konwersja.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define OKNO_LewaKrawedz  0
#define OKNO_GornaKrawedz 11
#define OKNO_Szerokosc    534
#define OKNO_Wysokosc     225

#define GD_Zrodlowy   0
#define GD_Docelowy   1
#define GD_Wczytaj    2
#define GD_Zapisz     3
#define GD_Statystyka 4
#define GD_CRLF       5
#define GD_DodajEOF   6
#define GD_ZmianaEOL  7
#define GD_ZmianaEOF  8

#define MI_OdAutora   0
#define MI_Wyjdz      1

#define MI_Wczytaj    0
#define MI_Zapisz     1
#define MI_Statystyka 3

void StworzSrodowisko (void);
void ZamknijSrodowisko (void);
void OtworzBiblioteki (void);
void BrakBiblioteki (UBYTE *);
int PrzygotujEkran (void);
int DodajStandardy (void);
int OtworzOkno (void);
void OdswierzOkno (void);
void Renderuj (void);
void ZwolnijEkran (void);
void ZamknijOkno (void);
void UsunStandardy (void);
void ZamknijBiblioteki (void);
void WczytajPlik (void);
void ZapiszPlik (void);
void Statystyka (void);
void OdAutora (void);

void Informacja (UBYTE *);
void PiszStandard (UBYTE *, UWORD);
void PiszPlik (UBYTE *);

BOOL __stdargs __saveds FunkcjaUzytkownika1 (ULONG calosc, ULONG gotowe, APTR);
BOOL __stdargs __saveds FunkcjaUzytkownika2 (ULONG calosc, ULONG gotowe, APTR);

struct EasyStruct BrakBibliotekiES[] =
{
  sizeof (struct EasyStruct),
  NULL,
  "Konwerter",
  "%s",
  "OK"
};

UBYTE *EtykietyEOL[] =
{
  (UBYTE *) "Nie",
  (UBYTE *) "LF->CR+LF",
  (UBYTE *) "CR+LF->LF",
  NULL
};

UBYTE *EtykietyEOF[] =
{
  (UBYTE *) "Nie",
  (UBYTE *) "Dodaj",
  (UBYTE *) "Usuļ",
  NULL
};

struct NewMenu NoweMenu[] =
{
  NM_TITLE, (STRPTR) "Projekt", NULL, 0, 0L, NULL,
  NM_ITEM, (STRPTR) "Od Autora...", (STRPTR) "?", 0, 0L, NULL,
  NM_ITEM, (STRPTR) "Wyjdś", (STRPTR) "X", 0, 0L, NULL,
  NM_TITLE, (STRPTR) "Tekst", NULL, 0, 0L, NULL,
  NM_ITEM, (STRPTR) "Wczytaj...", (STRPTR) "W", 0, 0L, NULL,
  NM_ITEM, (STRPTR) "Zapisz...", (STRPTR) "Z", NM_ITEMDISABLED, 0L, NULL,
  NM_ITEM, (STRPTR) NM_BARLABEL, NULL, 0, 0L, NULL,
  NM_ITEM, (STRPTR) "Statystyka...", (STRPTR) "S", NM_ITEMDISABLED, 0L, NULL,
  NM_END, NULL, NULL, 0, 0L, NULL};

UWORD chip WaitPointer[] =
{
  0x0000, 0x0000, 0x0400, 0x07c0, 0x0000, 0x07c0, 0x0100, 0x0380,
  0x0000, 0x07e0, 0x07c0, 0x1ff8, 0x1ff0, 0x3fec, 0x3ff8, 0x7fde,
  0x3ff8, 0x7fbe, 0x7ffc, 0xff7f, 0x7efc, 0xffff, 0x7ffc, 0xffff,
  0x3ff8, 0x7ffe, 0x3ff8, 0x7ffe, 0x1ff0, 0x3ffc, 0x07c0, 0x1ff8,
  0x0000, 0x07e0, 0x0000, 0x0000
};

struct Library *AslBase = NULL;
struct Library *GadToolsBase = NULL;
struct GfxBase *GfxBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct KonBase *KonBase = NULL;
struct FileRequester *FileRequester = NULL;
struct TextFont *TextFont = NULL;
APTR VisualInfo = NULL;
struct Screen *Ekran = NULL;
struct Window *OknoProgramu = NULL;
struct Gadget *Gadzety = NULL;
struct Gadget *Gad_Zapisz, *Gad_Statystyka, *Gad_DodajEOF, *Gad_ZmianaEOL,
 *Gad_ZmianaEOF, *GadTekstowy_Plik, *GadTekstowy_StandardZrod, *GadTekstowy_StandardDoc,
 *GadTekstowy_Informacja;
struct Menu *MenuOkna = NULL;
struct TextAttr TextAttr;
struct MinList Docel_Standardy, Zrodl_Standardy;
struct BuforInfo BuforInfo =
{
  BI_WERSJA			/* Aktualna wersja struktury BuforInfo */
};

UWORD OdchylenieX, OdchylenieY;
UWORD FontX, FontY;
WORD StandardZrodlowy = -1, StandardDocelowy = -1;
UBYTE KonFlagi = NULL;
ULONG RozmiarPliku = (ULONG) NULL;
UBYTE *BuforTekstowy = (UBYTE *) NULL;

UBYTE *NazwaProgramu = (UBYTE *) "Konwerter 2.0 © 1999 Grzegorz Królik";

UWORD WyliczX (UWORD wartosc)
{
  return ((UWORD) ((FontX * wartosc) / 8));
}

UWORD WyliczY (UWORD wartosc)
{
  return ((UWORD) ((FontY * wartosc) / 8));
}

void WyliczFont (UWORD szerokosc, UWORD wysokosc)
{
  TextAttr.ta_Name = GfxBase->DefaultFont->tf_Message.mn_Node.ln_Name;
  TextAttr.ta_YSize = FontY = GfxBase->DefaultFont->tf_YSize;
  FontX = GfxBase->DefaultFont->tf_XSize;

  OdchylenieY = Ekran->Font->ta_YSize + Ekran->WBorTop + 1;
  OdchylenieX = Ekran->WBorLeft;

  if (szerokosc && wysokosc)
    {
      if (((WyliczX (szerokosc) + OdchylenieX + Ekran->WBorRight) > Ekran->Width) ||
	  ((WyliczY (wysokosc) + OdchylenieY + Ekran->WBorBottom) > Ekran->Height))
	TextAttr.ta_Name = (STRPTR) "topaz.font";
      FontX = FontY = TextAttr.ta_YSize = 8;
    }
}

void StworzSrodowisko (void)
{
  NewList ((struct List *) &Zrodl_Standardy);
  NewList ((struct List *) &Docel_Standardy);

  OtworzBiblioteki ();

  if (!(PrzygotujEkran ()))
    ZamknijSrodowisko ();

  if (!(DodajStandardy ()))
    ZamknijSrodowisko ();

  if (!(OtworzOkno ()))
    ZamknijSrodowisko ();
}

void ZamknijSrodowisko (void)
{
  ZamknijOkno ();
  ZwolnijEkran ();
  UsunStandardy ();
  ZamknijBiblioteki ();

  if (BuforTekstowy)
    FreeMem (BuforTekstowy, RozmiarPliku);
  exit (0);
}

void OtworzBiblioteki (void)
{
  if (!(GadToolsBase = (struct Library *) OpenLibrary ("gadtools.library", 37)))
    ZamknijSrodowisko ();

  if (!(GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 37)))
    ZamknijSrodowisko ();

  if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 37)))
    ZamknijSrodowisko ();

  if (!(AslBase = (struct Library *) OpenLibrary ("asl.library", 38)))
    BrakBiblioteki ("Wymagam asl.library V38");

  if (!(KonBase = (struct KonBase *) OpenLibrary (KONNAME, KONVERSION)))
    BrakBiblioteki ("Wymagam konwersja.library V2");

  if (!(FileRequester = (struct FileRequester *) AllocAslRequest (ASL_FileRequest, NULL)))
    ZamknijSrodowisko ();
}

void BrakBiblioteki (UBYTE * nazwa)
{
  EasyRequest (NULL, BrakBibliotekiES, NULL, nazwa);
  ZamknijSrodowisko ();
}

int PrzygotujEkran (void)
{
  if (!(Ekran = LockPubScreen ((UBYTE *) NULL)))
    return (FALSE);

  if (!(VisualInfo = GetVisualInfoA (Ekran, NULL)))
    return (FALSE);

  WyliczFont (OKNO_Szerokosc, OKNO_Wysokosc);

  if (!(TextFont = OpenFont (&TextAttr)))
    return (FALSE);

  return (TRUE);
}


int DodajStandardy (void)
{
  struct Standard *s;
  struct Node *n;

  for (s = (struct Standard *) (KonBase->kon_Standardy.mlh_Head);
       s->stan_Node.mln_Succ;
       s = (struct Standard *) (s->stan_Node.mln_Succ)
    )
    {

      /* Standard "BezPol" nie powinien raczej byź standardem śródīowym,
         dlatego nie zostanie on dodany do gadūetu "Śródīowy" */

      if (!(s->stan_Flagi & STANF_NPOL))
	{
	  if (!(n = AllocMem (sizeof (*n), MEMF_PUBLIC | MEMF_CLEAR)))
	    return (FALSE);

	  n->ln_Name = (UBYTE *) s->stan_Nazwa;

	  AddTail ((struct List *) &Zrodl_Standardy, (struct Node *) n);
	}

      if (!(n = AllocMem (sizeof (*n), MEMF_PUBLIC | MEMF_CLEAR)))
	return (FALSE);

      n->ln_Name = (UBYTE *) s->stan_Nazwa;

      AddTail ((struct List *) &Docel_Standardy, (struct Node *) n);
    }

  return (TRUE);
}

int OtworzOkno (void)
{
  struct NewGadget ng;
  struct Gadget *g;
  UWORD lewakrawedz = OKNO_LewaKrawedz, gornakrawedz = OKNO_GornaKrawedz,
    szerokosc, wysokosc;
  static UWORD WymiaryZoom[4];

  szerokosc = WyliczX (OKNO_Szerokosc);
  wysokosc = WyliczY (OKNO_Wysokosc);

  if ((lewakrawedz + szerokosc + OdchylenieX + Ekran->WBorRight) > Ekran->Width)
    lewakrawedz = Ekran->Width - szerokosc;
  if ((gornakrawedz + wysokosc + OdchylenieY + Ekran->WBorBottom) > Ekran->Height)
    gornakrawedz = Ekran->Height - wysokosc;

  if (!(g = CreateContext (&Gadzety)))
    return (FALSE);

  ng.ng_LeftEdge = OdchylenieX + WyliczX (28);
  ng.ng_TopEdge = OdchylenieY + WyliczY (22);
  ng.ng_Width = WyliczX (92);
  ng.ng_Height = WyliczY (68);
  ng.ng_GadgetText = (UBYTE *) "Śródīowy:";
  ng.ng_TextAttr = &TextAttr;
  ng.ng_GadgetID = GD_Zrodlowy;
  ng.ng_Flags = PLACETEXT_ABOVE;
  ng.ng_VisualInfo = VisualInfo;

  if (!(g = CreateGadget (LISTVIEW_KIND, g, &ng, GTLV_Labels, &Zrodl_Standardy, TAG_DONE)))
    return (FALSE);

  ng.ng_LeftEdge = OdchylenieX + WyliczX (132);
  ng.ng_GadgetText = (UBYTE *) "Docelowy:";
  ng.ng_GadgetID = GD_Docelowy;

  if (!(g = CreateGadget (LISTVIEW_KIND, g, &ng, GTLV_Labels, &Docel_Standardy, TAG_DONE)))
    return (FALSE);

  ng.ng_LeftEdge = OdchylenieX + WyliczX (304);
  ng.ng_TopEdge = OdchylenieY + WyliczY (11);
  ng.ng_Width = WyliczX (200);
  ng.ng_Height = WyliczY (14);
  ng.ng_GadgetText = (UBYTE *) "Plik:";
  ng.ng_Flags = PLACETEXT_LEFT;

  if (!(GadTekstowy_Plik = g = CreateGadget (TEXT_KIND, g, &ng, GTTX_Text, "???", GTTX_Border, TRUE, TAG_DONE)))
    return (FALSE);

  ng.ng_LeftEdge = OdchylenieX + WyliczX (345);
  ng.ng_TopEdge = OdchylenieY + WyliczY (46);
  ng.ng_Width = WyliczX (80);
  ng.ng_GadgetText = (UBYTE *) "Standard śródīowy:";
  ng.ng_Flags = PLACETEXT_ABOVE;

  if (!(GadTekstowy_StandardZrod = g = CreateGadget (TEXT_KIND, g, &ng, GTTX_Text, "???", GTTX_Border, TRUE, GTTX_Justification, GTJ_CENTER, TAG_DONE)))
    return (FALSE);

  ng.ng_TopEdge = OdchylenieY + WyliczY (77);
  ng.ng_GadgetText = (UBYTE *) "Standard Docelowy:";

  if (!(GadTekstowy_StandardDoc = g = CreateGadget (TEXT_KIND, g, &ng, GTTX_Text, "???", GTTX_Border, TRUE, GTTX_Justification, GTJ_CENTER, TAG_DONE)))
    return (FALSE);

  ng.ng_LeftEdge = OdchylenieX + WyliczX (68);
  ng.ng_TopEdge = OdchylenieY + WyliczY (103);
  ng.ng_Width = WyliczX (120);
  ng.ng_Height = WyliczY (12);
  ng.ng_GadgetText = NULL;

  if (!(g = CreateGadget (TEXT_KIND, g, &ng, GTTX_Text, "Plik tekstowy:", TAG_DONE)))
    return (FALSE);

  ng.ng_LeftEdge = OdchylenieX + WyliczX (44);
  ng.ng_TopEdge = OdchylenieY + WyliczY (117);
  ng.ng_Width = WyliczX (70);
  ng.ng_Height = WyliczY (14);
  ng.ng_GadgetText = (UBYTE *) "Wczytaj";
  ng.ng_GadgetID = GD_Wczytaj;
  ng.ng_Flags = PLACETEXT_IN;

  if (!(g = CreateGadgetA (BUTTON_KIND, g, &ng, NULL)))
    return (FALSE);

  ng.ng_LeftEdge = OdchylenieX + WyliczX (138);
  ng.ng_GadgetText = (UBYTE *) "Zapisz";
  ng.ng_GadgetID = GD_Zapisz;

  if (!(Gad_Zapisz = g = CreateGadget (BUTTON_KIND, g, &ng, GA_Disabled, TRUE, TAG_DONE)))
    return (FALSE);

  ng.ng_LeftEdge = OdchylenieX + WyliczX (79);
  ng.ng_TopEdge = OdchylenieY + WyliczY (135);
  ng.ng_Width = WyliczX (95);
  ng.ng_GadgetText = (UBYTE *) "Statystyka";
  ng.ng_GadgetID = GD_Statystyka;

  if (!(Gad_Statystyka = g = CreateGadget (BUTTON_KIND, g, &ng, GA_Disabled, TRUE, TAG_DONE)))
    return (FALSE);

  ng.ng_LeftEdge = OdchylenieX + WyliczX (265);
  ng.ng_TopEdge = OdchylenieY + WyliczY (105);
  ng.ng_Width = WyliczX (CHECKBOX_WIDTH);
  ng.ng_Height = WyliczY (CHECKBOX_HEIGHT);
  ng.ng_GadgetText = (UBYTE *) "LF <-> CR+LF";
  ng.ng_GadgetID = GD_CRLF;
  ng.ng_Flags = PLACETEXT_RIGHT;

  if (!(g = CreateGadget (CHECKBOX_KIND, g, &ng, GTCB_Scaled, TRUE, TAG_DONE)))
    return (FALSE);

  ng.ng_TopEdge = OdchylenieY + WyliczY (120);
  ng.ng_GadgetText = (UBYTE *) "Dodaj/Usuļ EOF";
  ng.ng_GadgetID = GD_DodajEOF;

  if (!(Gad_DodajEOF = g = CreateGadget (CHECKBOX_KIND, g, &ng, GA_Disabled, TRUE, GTCB_Scaled, TRUE, TAG_DONE)))
    return (FALSE);

  ng.ng_LeftEdge = OdchylenieX + WyliczX (267);
  ng.ng_TopEdge = OdchylenieY + WyliczY (137);
  ng.ng_Width = WyliczX (240);
  ng.ng_Height = WyliczY (12);
  ng.ng_GadgetText = NULL;

  if (!(g = CreateGadget (TEXT_KIND, g, &ng, GTTX_Text, "Opcje dostėpne od wersji 2.0:", TAG_DONE)))
    return (FALSE);

  ng.ng_TopEdge = OdchylenieY + WyliczY (154);
  ng.ng_Width = WyliczX (106);
  ng.ng_Height = WyliczY (13);
  ng.ng_GadgetText = (UBYTE *) "Zmiana znaku EOL";
  ng.ng_GadgetID = GD_ZmianaEOL;

  if (!(Gad_ZmianaEOL = g = CreateGadget (CYCLE_KIND, g, &ng, GTCY_Labels, &EtykietyEOL, TAG_DONE)))
    return (FALSE);

  ng.ng_TopEdge = OdchylenieY + WyliczY (171);
  ng.ng_GadgetText = (UBYTE *) "Zmiana znaku EOF";
  ng.ng_GadgetID = GD_ZmianaEOF;

  if (!(Gad_ZmianaEOF = g = CreateGadget (CYCLE_KIND, g, &ng, GTCY_Labels, &EtykietyEOF, TAG_DONE)))
    return (FALSE);

  ng.ng_LeftEdge = OdchylenieX + WyliczX (27);
  ng.ng_TopEdge = OdchylenieY + WyliczY (200);
  ng.ng_Width = WyliczX (480);
  ng.ng_Height = WyliczY (14);
  ng.ng_GadgetText = NULL;

  if (!(GadTekstowy_Informacja = g = CreateGadget (TEXT_KIND, g, &ng, GTTX_Border, TRUE, TAG_DONE)))
    return (FALSE);

  if (!(MenuOkna = CreateMenus (NoweMenu, GTMN_FrontPen, 0L, TAG_DONE)))
    return (FALSE);

  LayoutMenus (MenuOkna, VisualInfo, GTMN_NewLookMenus, TRUE, TAG_DONE);

  WymiaryZoom[0] = WymiaryZoom[1] = 0;
  WymiaryZoom[2] = TextLength (&Ekran->RastPort, NazwaProgramu, strlen (NazwaProgramu)) + 80;
  WymiaryZoom[3] = Ekran->WBorTop + Ekran->RastPort.TxHeight + 1;

  if (!(OknoProgramu = OpenWindowTags (NULL,
				       WA_Left, lewakrawedz,
				       WA_Top, gornakrawedz,
		       WA_Width, szerokosc + OdchylenieX + Ekran->WBorRight,
		      WA_Height, wysokosc + OdchylenieY + Ekran->WBorBottom,
				       WA_IDCMP, LISTVIEWIDCMP | BUTTONIDCMP | CHECKBOXIDCMP | CYCLEIDCMP | IDCMP_MENUPICK | IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_NEWSIZE,
				       WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_SMART_REFRESH | WFLG_ACTIVATE,
				       WA_Gadgets, NULL,
				       WA_Title, NazwaProgramu,
				       WA_NewLookMenus, TRUE,
				       WA_ScreenTitle, NazwaProgramu,
				       WA_PubScreen, Ekran,
				       WA_Zoom, WymiaryZoom,
				       TAG_DONE)))
    return (FALSE);

  SetMenuStrip (OknoProgramu, MenuOkna);

  SetFont (OknoProgramu->RPort, TextFont);

  OdswierzOkno ();

  return (TRUE);
}

void OdswierzOkno (void)
{
  Renderuj ();

  OknoProgramu->Flags &= ~WFLG_RMBTRAP;

  AddGList (OknoProgramu, Gadzety, -1, -1, NULL);
  RefreshGList (Gadzety, OknoProgramu, NULL, -1);

  GT_RefreshWindow (OknoProgramu, NULL);
}

void Renderuj (void)
{
  static UWORD wzorzec[] =
  {
    0xaaaa, 0x5555
  };

  SetAPen (OknoProgramu->RPort, 2);

  SetAfPt (OknoProgramu->RPort, wzorzec, 1);

  RectFill (OknoProgramu->RPort, OdchylenieX, OdchylenieY, OknoProgramu->Width - OdchylenieX, OknoProgramu->Height - OknoProgramu->BorderBottom - 1);

  SetAfPt (OknoProgramu->RPort, NULL, 0);

  SetAPen (OknoProgramu->RPort, 0);

  RectFill (OknoProgramu->RPort, OdchylenieX + WyliczX (14), OdchylenieY + WyliczY (6), OdchylenieX + WyliczX (14) + WyliczX (224) - 1, OdchylenieY + WyliczY (6) + WyliczY (90) - 1);
  RectFill (OknoProgramu->RPort, OdchylenieX + WyliczX (251), OdchylenieY + WyliczY (6), OdchylenieX + WyliczX (251) + WyliczX (269) - 1, OdchylenieY + WyliczY (6) + WyliczY (90) - 1);
  RectFill (OknoProgramu->RPort, OdchylenieX + WyliczX (14), OdchylenieY + WyliczY (101), OdchylenieX + WyliczX (14) + WyliczX (224) - 1, OdchylenieY + WyliczY (101) + WyliczY (54) - 1);
  RectFill (OknoProgramu->RPort, OdchylenieX + WyliczX (251), OdchylenieY + WyliczY (101), OdchylenieX + WyliczX (251) + WyliczX (269) - 1, OdchylenieY + WyliczY (101) + WyliczY (89) - 1);
  RectFill (OknoProgramu->RPort, OdchylenieX + WyliczX (14), OdchylenieY + WyliczY (160), OdchylenieX + WyliczX (14) + WyliczX (224) - 1, OdchylenieY + WyliczY (160) + WyliczY (30) - 1);
  RectFill (OknoProgramu->RPort, OdchylenieX + WyliczX (14), OdchylenieY + WyliczY (195), OdchylenieX + WyliczX (14) + WyliczX (506) - 1, OdchylenieY + WyliczY (195) + WyliczY (24) - 1);

  DrawBevelBox (OknoProgramu->RPort, OdchylenieX + WyliczX (14), OdchylenieY + WyliczY (6), WyliczX (224), WyliczY (90), GT_VisualInfo, VisualInfo, GTBB_Recessed, TRUE, TAG_DONE);
  DrawBevelBox (OknoProgramu->RPort, OdchylenieX + WyliczX (251), OdchylenieY + WyliczY (6), WyliczX (269), WyliczY (90), GT_VisualInfo, VisualInfo, GTBB_Recessed, TRUE, TAG_DONE);
  DrawBevelBox (OknoProgramu->RPort, OdchylenieX + WyliczX (14), OdchylenieY + WyliczY (101), WyliczX (224), WyliczY (54), GT_VisualInfo, VisualInfo, GTBB_Recessed, TRUE, TAG_DONE);
  DrawBevelBox (OknoProgramu->RPort, OdchylenieX + WyliczX (251), OdchylenieY + WyliczY (101), WyliczX (269), WyliczY (89), GT_VisualInfo, VisualInfo, GTBB_Recessed, TRUE, TAG_DONE);
  DrawBevelBox (OknoProgramu->RPort, OdchylenieX + WyliczX (14), OdchylenieY + WyliczY (160), WyliczX (224), WyliczY (30), GT_VisualInfo, VisualInfo, GTBB_Recessed, TRUE, TAG_DONE);
  DrawBevelBox (OknoProgramu->RPort, OdchylenieX + WyliczX (14), OdchylenieY + WyliczY (195), WyliczX (506), WyliczY (24), GT_VisualInfo, VisualInfo, GTBB_Recessed, TRUE, TAG_DONE);
}

void ZwolnijEkran (void)
{
  if (TextFont)
    CloseFont (TextFont);

  if (VisualInfo)
    FreeVisualInfo (VisualInfo);

  if (Ekran)
    UnlockPubScreen (NULL, Ekran);
}

void ZamknijOkno (void)
{
  if (MenuOkna)
    {
      ClearMenuStrip (OknoProgramu);
      FreeMenus (MenuOkna);
    }

  if (OknoProgramu)
    CloseWindow (OknoProgramu);

  if (Gadzety)
    FreeGadgets (Gadzety);
}

void UsunStandardy (void)
{
  struct Node *n;

  while (n = (struct Node *) RemTail ((struct List *) &Zrodl_Standardy))
    FreeMem (n, sizeof (*n));

  while (n = (struct Node *) RemTail ((struct List *) &Docel_Standardy))
    FreeMem (n, sizeof (*n));
}

void ZamknijBiblioteki (void)
{
  if (FileRequester)
    FreeAslRequest ((struct FileRequester *) FileRequester);

  if (KonBase)
    CloseLibrary ((struct Library *) KonBase);
  if (IntuitionBase)
    CloseLibrary ((struct Library *) IntuitionBase);
  if (GfxBase)
    CloseLibrary ((struct Library *) GfxBase);
  if (GadToolsBase)
    CloseLibrary ((struct Library *) GadToolsBase);
  if (AslBase)
    CloseLibrary ((struct Library *) AslBase);
}

void WczytajPlik (void)
{
  struct Requester requester;
  UBYTE nazwa_pliku[255];
  BPTR plik;
  ULONG nowy_rozmiar_pliku;

  InitRequester (&requester);
  requester.Flags = NOISYREQ;

  Request (&requester, OknoProgramu);
  SetPointer (OknoProgramu, WaitPointer, 16, 16, -6, 0);

  if (AslRequestTags ((struct FileRequester *) FileRequester,
		      ASLFR_Window, OknoProgramu,
		      ASLFR_TitleText, (STRPTR) "Wybierz plik do konwersji",
		      ASLFR_PositiveText, (STRPTR) "Wczytaj",
		      ASLFR_NegativeText, (STRPTR) "Zaniechaj",
		      TAG_DONE))
    {

      strcpy (nazwa_pliku, FileRequester->rf_Dir);
      AddPart (nazwa_pliku, FileRequester->rf_File, 255);

      Informacja ("Īadujė plik...");

      if (plik = Open (nazwa_pliku, MODE_OLDFILE))
	{

	  Seek (plik, NULL, OFFSET_END);
	  nowy_rozmiar_pliku = Seek (plik, NULL, OFFSET_BEGINNING);

	  if (nowy_rozmiar_pliku)
	    {

	      if (BuforTekstowy)
		FreeMem (BuforTekstowy, RozmiarPliku);

	      OffMenu (OknoProgramu, FULLMENUNUM (1, MI_Zapisz, NOSUB));
	      OffMenu (OknoProgramu, FULLMENUNUM (1, MI_Statystyka, NOSUB));
	      GT_SetGadgetAttrs (Gad_Zapisz, OknoProgramu, NULL, GA_Disabled, TRUE, TAG_DONE);
	      GT_SetGadgetAttrs (Gad_Statystyka, OknoProgramu, NULL, GA_Disabled, TRUE, TAG_DONE);

	      RozmiarPliku = nowy_rozmiar_pliku;

	      if (BuforTekstowy = AllocMem (RozmiarPliku, MEMF_PUBLIC))
		{
		  if ((Read (plik, BuforTekstowy, RozmiarPliku)) == RozmiarPliku)
		    {
		      if (AnalizujBufor (BuforTekstowy, RozmiarPliku, &BuforInfo, FunkcjaUzytkownika2, NULL) == KONBLAD_ANALIZA_PRZERWANA)
			{
			  Informacja ("Analiza zostaīa przerwana");
			  FreeMem (BuforTekstowy, RozmiarPliku);
			  BuforTekstowy = (UBYTE *) NULL;
			}
		      else
			{
			  PiszPlik (FilePart (nazwa_pliku));

			  if ((StandardZrodlowy = BuforInfo.bi_StanNumer) >= 0)
			    {
			      PiszStandard (BuforInfo.bi_StanNazwa, GD_Zrodlowy);
			      Informacja ("Standard zostaī rozpoznany");
			    }
			  else
			    {
			      PiszStandard ("???", GD_Zrodlowy);
			      Informacja ("Standard nie zostaī rozpoznany!");
			    }

			  OnMenu (OknoProgramu, FULLMENUNUM (1, MI_Zapisz, NOSUB));
			  OnMenu (OknoProgramu, FULLMENUNUM (1, MI_Statystyka, NOSUB));
			  GT_SetGadgetAttrs (Gad_Zapisz, OknoProgramu, NULL, GA_Disabled, FALSE, TAG_DONE);
			  GT_SetGadgetAttrs (Gad_Statystyka, OknoProgramu, NULL, GA_Disabled, FALSE, TAG_DONE);
			}
		    }
		  else
		    {
		      Informacja ("Bīād podczas odczytu pliku!");
		      FreeMem (BuforTekstowy, RozmiarPliku);
		      BuforTekstowy = (UBYTE *) NULL;
		    }
		}
	      else
		Informacja ("Brak pamiėci!");
	    }
	  else
	    Informacja ("Plik śródīowy jest pusty!");

	  Close (plik);
	}
      else
	Informacja ("Bīād otwarcia pliku śródīowego!");
    }

  ClearPointer (OknoProgramu);
  EndRequest (&requester, OknoProgramu);
}

void ZapiszPlik (void)
{
  struct Requester requester;
  UBYTE nazwa_pliku[255];
  UBYTE *nowy_bufor_tekstowy;
  BPTR plik;
  ULONG nowy_rozmiar_pliku;
  LONG wynik;

  if (StandardZrodlowy < 0)
    {
      Informacja ("Wybierz standard śródīowy!!!");
      return;
    }

  if (StandardDocelowy < 0)
    {
      Informacja ("Wybierz standard docelowy!!!");
      return;
    }

  InitRequester (&requester);
  requester.Flags = NOISYREQ;

  Request (&requester, OknoProgramu);
  SetPointer (OknoProgramu, WaitPointer, 16, 16, -6, 0);

  if (AslRequestTags ((struct FileRequester *) FileRequester,
		      ASLFR_Window, OknoProgramu,
		      ASLFR_TitleText, (UBYTE *) "Zapisz plik jako",
		      ASLFR_PositiveText, "Zapisz",
		      ASLFR_NegativeText, "Zaniechaj",
		      TAG_DONE))
    {

      strcpy (nazwa_pliku, FileRequester->fr_Drawer);
      AddPart (nazwa_pliku, FileRequester->fr_File, 255);

      if (plik = Open (nazwa_pliku, MODE_NEWFILE))
	{

	  wynik = Konwertuj (BuforTekstowy, RozmiarPliku, &nowy_bufor_tekstowy, &nowy_rozmiar_pliku, MEMF_PUBLIC, StandardZrodlowy, StandardDocelowy, KonFlagi, FunkcjaUzytkownika1, NULL);

	  if (wynik == KONBLAD_OK)
	    {
	      if ((Write (plik, nowy_bufor_tekstowy, nowy_rozmiar_pliku)) == nowy_rozmiar_pliku)
		{
		  Close (plik);
		  FreeMem (nowy_bufor_tekstowy, nowy_rozmiar_pliku);
		  Informacja ("Zapisaīem plik");
		}
	      else
		Informacja ("Bīād podczas zapisu pliku!");
	    }
	  else if (wynik == KONBLAD_BRAK_PAMIECI)
	    {
	      Informacja ("Brak pamiėci!");

	      FreeMem (BuforTekstowy, RozmiarPliku);
	      BuforTekstowy = (UBYTE *) NULL;
	    }
	  else if (wynik == KONBLAD_KONWERSJA_PRZERWANA)
	    Informacja ("Konwersja przerwana");

	  if (wynik != KONBLAD_KONWERSJA_PRZERWANA)
	    {
	      PiszPlik ("???");
	      PiszStandard ("???", GD_Zrodlowy);

	      OffMenu (OknoProgramu, FULLMENUNUM (1, MI_Zapisz, NOSUB));
	      OffMenu (OknoProgramu, FULLMENUNUM (1, MI_Statystyka, NOSUB));
	      GT_SetGadgetAttrs (Gad_Zapisz, OknoProgramu, NULL, GA_Disabled, TRUE, TAG_DONE);
	      GT_SetGadgetAttrs (Gad_Statystyka, OknoProgramu, NULL, GA_Disabled, TRUE, TAG_DONE);
	    }
	  else if (wynik != KONBLAD_OK)
	    {
	      Close (plik);
	      DeleteFile (nazwa_pliku);
	    }
	}
      else
	Informacja ("Bīād otwarcia pliku docelowego!");
    }

  ClearPointer (OknoProgramu);
  EndRequest (&requester, OknoProgramu);
}

void Statystyka ()
{
  struct Requester requester;

  static struct EasyStruct statystyka_requester[] =
  {
    sizeof (struct EasyStruct),
    0,
    "Statystyka",
    " Numer Standardu        : %ld\n"
    " Nazwa Standardu        : %s\n"
    " Znak Koļca Linii (EOL) : %s\n"
    " Znak Koļca Pliku (EOF) : %s\n"
    " Iloōź Polskich Liter   : %ld\n"
    " Iloōź Znaków Binarnych : %ld",
    "OK",
  };

  ULONG DaneStatystyczne[6];

  DaneStatystyczne[0] = BuforInfo.bi_StanNumer;
  DaneStatystyczne[1] = (ULONG) BuforInfo.bi_StanNazwa;

  switch (BuforInfo.bi_RodzajEOL)
    {
    case BIEOLF_AMIGA:
      DaneStatystyczne[2] = (ULONG) "AMIGA";
      break;

    case BIEOLF_IBMPC:
      DaneStatystyczne[2] = (ULONG) "IBM PC";
      break;

    case BIEOLF_AMIGA | BIEOLF_IBMPC:
      DaneStatystyczne[2] = (ULONG) "AMIGA i IBM PC";
      break;

    default:
      DaneStatystyczne[2] = (ULONG) "BRAK";
    }

  DaneStatystyczne[3] = BuforInfo.bi_ZnakEOF ? (ULONG) "TAK" : (ULONG) "BRAK";
  DaneStatystyczne[4] = BuforInfo.bi_IloscPolLit;
  DaneStatystyczne[5] = BuforInfo.bi_IloscBinarnych;

  InitRequester (&requester);
  Request (&requester, OknoProgramu);
  SetPointer (OknoProgramu, WaitPointer, 16, 16, -6, 0);

  EasyRequestArgs (OknoProgramu, statystyka_requester, NULL, DaneStatystyczne);

  ClearPointer (OknoProgramu);
  EndRequest (&requester, OknoProgramu);
}

void OdAutora ()
{
  struct Requester requester;

  static struct EasyStruct infotekst[] =
  {
    sizeof (struct EasyStruct),
    0,
    "Od Autora...",

    "Konwerter 2.0\n"
    "Copyright © 1998-1999 Grzegorz Królik\n\n"

    "Konwerter  jest  programem demonstracyjnym\n"
    "sīuūācym   do  zaprezentowania  moūliwoōci\n"
    "biblioteki 'konwersja.library' w wersji 2.\n\n"

    "Jest   on   nieodīācznā   czėōciā  pakietu\n"
    "developerskiego  'Konwersja Library' i nie\n"
    "powinien byź rozpowszechniany osobno.\n\n"

    "Program   ten   oraz   jego  kod  śródīowy\n"
    "(doīāczony  do  pakietu)  sā Public Domain\n"
    "i  mogā  zostaź wykorzystane i dostosowane\n"
    "do wīasnych potrzeb.",

    "OK",};

  InitRequester (&requester);
  Request (&requester, OknoProgramu);
  SetPointer (OknoProgramu, WaitPointer, 16, 16, -6, 0);

  EasyRequestArgs (OknoProgramu, infotekst, NULL, NULL);

  ClearPointer (OknoProgramu);
  EndRequest (&requester, OknoProgramu);
}

void Informacja (UBYTE * tekst)
{
  GT_SetGadgetAttrs (GadTekstowy_Informacja, OknoProgramu, NULL, GTTX_Text, tekst, TAG_DONE);
}

void PiszStandard (UBYTE * tekst, UWORD gad)
{
  if (gad == GD_Zrodlowy)
    GT_SetGadgetAttrs (GadTekstowy_StandardZrod, OknoProgramu, NULL, GTTX_Text, tekst, TAG_DONE);
  else
    GT_SetGadgetAttrs (GadTekstowy_StandardDoc, OknoProgramu, NULL, GTTX_Text, tekst, TAG_DONE);
}

void PiszPlik (UBYTE * tekst)
{
  GT_SetGadgetAttrs (GadTekstowy_Plik, OknoProgramu, NULL, GTTX_Text, tekst, TAG_DONE);
}

 /* Funkcja uūytkownika dla funkcji Konwertuj() */

BOOL __stdargs __saveds FunkcjaUzytkownika1 (ULONG calosc, ULONG gotowe, APTR atrapa)
{
  struct IntuiMessage *msg;
  UBYTE bufortekstowy[40];

  while (msg = GT_GetIMsg (OknoProgramu->UserPort))
    {
      if (msg->Code == 27)
	return (FALSE);
    }

  sprintf ((UBYTE *) bufortekstowy, "Konwertujė wczytany zbiór - %d%%", ((gotowe * 100) / calosc));

  Informacja ((UBYTE *) bufortekstowy);

  return (TRUE);
}

 /* Funkcja uūytkownika dla funkcji AnalizujBufor(). Jest dokīadnie taka sama
    jak ta dla Konwertuj() */

BOOL __stdargs __saveds FunkcjaUzytkownika2 (ULONG calosc, ULONG gotowe, APTR atrapa)
{
  struct IntuiMessage *msg;
  UBYTE bufortekstowy[40];

  while (msg = GT_GetIMsg (OknoProgramu->UserPort))
    {
      if (msg->Code == 27)
	return (FALSE);
    }

  sprintf ((UBYTE *) bufortekstowy, "Analizujė wczytany zbiór - %d%%", ((gotowe * 100) / calosc));

  Informacja ((UBYTE *) bufortekstowy);

  return (TRUE);
}

main ()
{
  struct IntuiMessage *msg;
  LONG klasa;
  UWORD kod;
  struct Gadget *g;
  ULONG stancrlf = TRUE;
  UWORD stanzoom = FALSE;
  WORD numer;
  struct Node *n;

  StworzSrodowisko ();

  for (;;)
    {
      WaitPort (OknoProgramu->UserPort);
      while (msg = GT_GetIMsg (OknoProgramu->UserPort))
	{
	  klasa = msg->Class;
	  kod = msg->Code;
	  g = (struct Gadget *) msg->IAddress;
	  GT_ReplyIMsg (msg);

	  switch (klasa)
	    {
	    case IDCMP_CLOSEWINDOW:
	      ZamknijSrodowisko ();

	    case IDCMP_NEWSIZE:
	      if (stanzoom = !stanzoom)
		{
		  OknoProgramu->Flags |= WFLG_RMBTRAP;
		  RemoveGList (OknoProgramu, Gadzety, -1);
		}
	      else
		OdswierzOkno ();
	      break;

	    case IDCMP_GADGETUP:
	      switch (g->GadgetID)
		{
		case GD_Zrodlowy:
		  /*
		     Poniūsza  pėtla  wyszukuje  prawidīowy numer wybranego
		     standardu  śródīowego.  Procedurka  ta jest konieczna,
		     poniewaū   gadūet   wyboru  standardu  śródīowego  nie
		     zawiera  standardu  "BezPol"  (który  nie powinien byź
		     uūywany  jako  standard  śródīowy) i numery standardów
		     pomiėdzy gadūetami "Śródīowy" i "Docelowy" bėdā siė od
		     siebie róūniīy.
		   */

		  for (n = (struct Node *) Zrodl_Standardy.mlh_Head, numer = 0; numer != kod; n = n->ln_Succ, numer++)
		    ;

		  StandardZrodlowy = PobierzNumer (n->ln_Name);
		  PiszStandard (n->ln_Name, GD_Zrodlowy);
		  break;

		case GD_Docelowy:
		  StandardDocelowy = kod;
		  PiszStandard (PobierzNazwe (StandardDocelowy), GD_Docelowy);
		  break;

		case GD_Wczytaj:
		  WczytajPlik ();
		  break;

		case GD_Zapisz:
		  ZapiszPlik ();
		  break;

		case GD_Statystyka:
		  Statystyka ();
		  break;

		case GD_CRLF:
		  KonFlagi ^= KONWF_ZMIENNL;
		  stancrlf = !stancrlf;
		  GT_SetGadgetAttrs (Gad_DodajEOF, OknoProgramu, NULL, GA_Disabled, stancrlf, TAG_END);
		  GT_SetGadgetAttrs (Gad_ZmianaEOL, OknoProgramu, NULL, GA_Disabled, !stancrlf, TAG_END);
		  GT_SetGadgetAttrs (Gad_ZmianaEOF, OknoProgramu, NULL, GA_Disabled, !stancrlf, TAG_END);
		  break;

		case GD_DodajEOF:
		  KonFlagi ^= KONWF_DODAJEOF;
		  break;

		case GD_ZmianaEOL:
		  switch (kod)
		    {
		    case 1:

		      /* Naleūy wyczyōciź opcje dotyczāce tylko zmiany znaku
		         EOL */

		      KonFlagi &= ~(KONWF_WSTAW_CR | KONWF_USUN_CR);
		      KonFlagi |= KONWF_WSTAW_CR;
		      break;

		    case 2:

		      /* Naleūy wyczyōciź opcje dotyczāce tylko zmiany znaku
		         EOF */

		      KonFlagi &= ~(KONWF_WSTAW_CR | KONWF_USUN_CR);
		      KonFlagi |= KONWF_USUN_CR;
		      break;

		    default:
		      KonFlagi &= ~(KONWF_WSTAW_CR | KONWF_USUN_CR);
		    }
		  break;

		case GD_ZmianaEOF:
		  switch (kod)
		    {
		    case 1:
		      KonFlagi &= ~(KONWF_WSTAW_EOF | KONWF_USUN_EOF);
		      KonFlagi |= KONWF_WSTAW_EOF;
		      break;

		    case 2:
		      KonFlagi &= ~(KONWF_WSTAW_EOF | KONWF_USUN_EOF);
		      KonFlagi |= KONWF_USUN_EOF;
		      break;

		    default:
		      KonFlagi &= ~(KONWF_WSTAW_EOF | KONWF_USUN_EOF);
		    }
		}
	      break;

	    case IDCMP_MENUPICK:
	      if (kod != MENUNULL)	/* Nie wybrano menu! */
		switch (kod)
		  {
		  case FULLMENUNUM (0, MI_OdAutora, NOSUB):
		    OdAutora ();
		    break;

		  case FULLMENUNUM (0, MI_Wyjdz, NOSUB):
		    ZamknijSrodowisko ();

		  case FULLMENUNUM (1, MI_Wczytaj, NOSUB):
		    WczytajPlik ();
		    break;

		  case FULLMENUNUM (1, MI_Zapisz, NOSUB):
		    ZapiszPlik ();
		    break;

		  case FULLMENUNUM (1, MI_Statystyka, NOSUB):
		    Statystyka ();
		  }
	    }
	}
    }
}
