#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>


#define IL_ZNAKOW 128
#define DL_BUFORU 20
#define DL_WEJSCIA 500

typedef  enum { FALSE=0, TRUE=1 }  Boolean;

int  nry_znakow[IL_ZNAKOW], czycyfra=FALSE, czyduza=FALSE;
char  bufor[DL_BUFORU][3][3];


void  blad(char komunikat[]) {
  printf("\n  !!!BLAD!!! %s\n\n", komunikat);
  exit(1);
}


void  inic_nry_znakow () {
  int nr;
  for (nr=0; nr<IL_ZNAKOW; nr++)  nry_znakow[nr]=0;
  nry_znakow[(int)'A'] = nry_znakow[(int)'a'] = nry_znakow[(int)'1'] =  1;
  nry_znakow[(int)'B'] = nry_znakow[(int)'b'] = nry_znakow[(int)'2'] =  3;
  nry_znakow[(int)'C'] = nry_znakow[(int)'c'] = nry_znakow[(int)'3'] =  9;
  nry_znakow[(int)'D'] = nry_znakow[(int)'d'] = nry_znakow[(int)'4'] = 25;
  nry_znakow[(int)'E'] = nry_znakow[(int)'e'] = nry_znakow[(int)'5'] = 17;
  nry_znakow[(int)'F'] = nry_znakow[(int)'f'] = nry_znakow[(int)'6'] = 11;
  nry_znakow[(int)'G'] = nry_znakow[(int)'g'] = nry_znakow[(int)'7'] = 27;
  nry_znakow[(int)'H'] = nry_znakow[(int)'h'] = nry_znakow[(int)'8'] = 19;
  nry_znakow[(int)'I'] = nry_znakow[(int)'i'] = nry_znakow[(int)'9'] = 10;
  nry_znakow[(int)'J'] = nry_znakow[(int)'j'] = nry_znakow[(int)'0'] = 26;
  nry_znakow[(int)'K'] = nry_znakow[(int)'k'] =  5;
  nry_znakow[(int)'L'] = nry_znakow[(int)'l'] =  7;
  nry_znakow[(int)'M'] = nry_znakow[(int)'m'] = 13;
  nry_znakow[(int)'N'] = nry_znakow[(int)'n'] = 29;
  nry_znakow[(int)'O'] = nry_znakow[(int)'o'] = 21;
  nry_znakow[(int)'P'] = nry_znakow[(int)'p'] = 15;
  nry_znakow[(int)'Q'] = nry_znakow[(int)'q'] = 31;
  nry_znakow[(int)'R'] = nry_znakow[(int)'r'] = 23;
  nry_znakow[(int)'S'] = nry_znakow[(int)'s'] = 14;
  nry_znakow[(int)'T'] = nry_znakow[(int)'t'] = 30;
  nry_znakow[(int)'U'] = nry_znakow[(int)'u'] = 37;
  nry_znakow[(int)'V'] = nry_znakow[(int)'v'] = 39;
  nry_znakow[(int)'W'] = nry_znakow[(int)'w'] = 58;
  nry_znakow[(int)'X'] = nry_znakow[(int)'x'] = 45;
  nry_znakow[(int)'Y'] = nry_znakow[(int)'y'] = 61;
  nry_znakow[(int)'Z'] = nry_znakow[(int)'z'] = 53;
  nry_znakow[(int)' '] =  0;
  nry_znakow[(int)'\''] = 4;
  nry_znakow[(int)'.'] = 50;
  nry_znakow[(int)','] =  2;
  nry_znakow[(int)';'] =  6;
  nry_znakow[(int)'!'] = 22;
  nry_znakow[(int)'"'] = nry_znakow[(int)'?'] = 38;
  nry_znakow[(int)'('] = nry_znakow[(int)')'] = 54;
  nry_znakow[(int)'-'] = 36;
  nry_znakow[(int)'&'] = 47;
}


void  czysc_buf() {
  int poz;
  for (poz=0; poz<DL_BUFORU; poz++) {
    bufor[poz][0][0] = 
    bufor[poz][1][0] = 
    bufor[poz][2][0] = '|';
    bufor[poz][0][1] = bufor[poz][0][2] = 
    bufor[poz][1][1] = bufor[poz][1][2] = 
    bufor[poz][2][1] = bufor[poz][2][2] = ' ';
  }
}


char  znak(int nr) {
  int  ascii;

  if (nr==32) { // przelacznik na duze
    czyduza=TRUE;
    return '\0';
  }

  if (nr==60) { // przelacznik na liczby
    czycyfra=TRUE;
    return '\0';
  }

  if (nr==0) { // spacja
    czycyfra=FALSE; czyduza=FALSE;
    return ' ';
  }

  if (nr==50) { // kropka
    czyduza=FALSE;
    return '.';
  }

  if (czycyfra) { // cyfra
    ascii=(int)'0';
    while (ascii <= '9' && nry_znakow[ascii] != nr)
      ascii++;
    if (ascii <= (int)'9') {
      czyduza=FALSE;
      return (char)ascii;
    }
  }

  if (czyduza) { // duza litera
    ascii=(int)'A';
    while (ascii <= 'Z' && nry_znakow[ascii] != nr)
      ascii++;
    if (ascii <= (int)'Z') {
      czycyfra=FALSE; czyduza = FALSE;
      return (char)ascii;
    }
  }

    // mala litera
  ascii=(int)'a';
  while (ascii <= 'z' && nry_znakow[ascii] != nr)
    ascii++;
  if (ascii <= (int)'z') {
    czycyfra=FALSE; czyduza = FALSE;
    return (char)ascii;
  }

    // inny znak z listy
  ascii=(int)' ';
  while (ascii < IL_ZNAKOW && nry_znakow[ascii] != nr)
    ascii++;
  if (ascii < IL_ZNAKOW) {
    czycyfra=FALSE; czyduza = FALSE;
    return (char)ascii;
  }

    // znak spoza listy
  return (char)(nr-128);
}


void  napisz_zn(int znak_nr, int poz) {
  char komunikat[100];
  if (poz<0 || DL_BUFORU<=poz) {
    sprintf(komunikat, "zla pozycja w wierszu: %i", poz);
    blad(komunikat);
  }
  else
    if (znak_nr<0 || 64<=znak_nr) {
      sprintf(komunikat, "zly numer znaku: %i", znak_nr);
      blad(komunikat);
    }
    else {
      bufor[poz][0][0] = bufor[poz][1][0] = bufor[poz][2][0] = '|';
      bufor[poz][0][1] = (znak_nr % 2 == 0 ? ' ' : '*'); znak_nr /= 2;
      bufor[poz][1][1] = (znak_nr % 2 == 0 ? ' ' : '*'); znak_nr /= 2;
      bufor[poz][2][1] = (znak_nr % 2 == 0 ? ' ' : '*'); znak_nr /= 2;
      bufor[poz][0][2] = (znak_nr % 2 == 0 ? ' ' : '*'); znak_nr /= 2;
      bufor[poz][1][2] = (znak_nr % 2 == 0 ? ' ' : '*'); znak_nr /= 2;
      bufor[poz][2][2] = (znak_nr % 2 == 0 ? ' ' : '*'); znak_nr /= 2;
    }
}


void  wydruk_buf() {
  int poz;
  printf("  ");
  for (poz=0; poz<DL_BUFORU; poz++)
    printf(" --");
  printf("\n  ");
  for (poz=0; poz<DL_BUFORU; poz++)
    printf("%c%c%c", bufor[poz][0][0], bufor[poz][0][1], bufor[poz][0][2]);
  printf("|\n  ");
  for (poz=0; poz<DL_BUFORU; poz++)
    printf("%c%c%c", bufor[poz][1][0], bufor[poz][1][1], bufor[poz][1][2]);
  printf("|\n  ");
  for (poz=0; poz<DL_BUFORU; poz++)
    printf("%c%c%c", bufor[poz][2][0], bufor[poz][2][1], bufor[poz][2][2]);
  printf("|\n  ");
  for (poz=0; poz<DL_BUFORU; poz++)
    printf(" --");
  printf("\n");
  czysc_buf();
}


void  druk_wiersz(char nap[]) {
  int  poz=0, i;
  for (i=0; i<strlen(nap); i++) {
    if ('0'<=nap[i] && nap[i]<='9') {
      if (!czycyfra) { // zmiana na liczby
	napisz_zn(60, poz); poz++; czycyfra=TRUE;
      }
      napisz_zn(nry_znakow[(int)nap[i]], poz);
    }
    else
      if ('A'<=nap[i] && nap[i]<='Z') { // na duze litery
	napisz_zn(32, poz); poz++;
	napisz_zn(nry_znakow[(int)nap[i]], poz);
      }
      else
	if (nap[i]=='.')
	  napisz_zn(nry_znakow[(int)nap[i]], poz);
	else
	  if ((int)nap[i]<0)
	    napisz_zn((int)nap[i]+128, poz);
	  else {
	    napisz_zn(nry_znakow[(int)nap[i]], poz);
	    czycyfra=FALSE;
	  }
    poz++;
    if (poz == DL_BUFORU) {
      wydruk_buf();
      poz=0;
    }
  }
  if (poz>0)  wydruk_buf();
}


void  wczyt_wiersz(char ww[]) {
  int poz=0;  char zn;
  zn = getchar();
  while (isgraph(zn) || zn==' ') {
    ww[poz]=zn; poz++;
    zn = getchar();
  }
  ww[poz]='\0';
}


void  dodruk(char nap[]) {
  int i;
  printf("\n  ");
  for (i=0; i<strlen(nap); i++)
    if ((int)nap[i]<0)
      printf("#%-2i", (int)nap[i]+128);
    else
      printf(" %1c ", nap[i]);
  printf("\n"); 
}


int  main () {
  char  odp, zn;
  char wiersz[DL_WEJSCIA];
  int  nr_zn, poz, c0, c1, c2;
  inic_nry_znakow(); czysc_buf();

  do {
    printf("\n  (C) -- czytac Braille\'a?");
    printf("\n  (P) -- pisac Braillem\'a?");
    printf("\n  (Z) -- zakonczyc?\n  ");
    scanf("%c", &odp); getchar();

    if (odp=='p' || odp=='P') {
      printf("  Podaj zwykly napis, zakoncz ENTERem:\n\n  ");
      wczyt_wiersz(wiersz);
      druk_wiersz(wiersz);
    }
    else

      if (odp=='c' || odp=='C') {
        printf("  Podaj ciag kodow Braille'a, zakoncz liczba ujemna:\n\n  ");
	poz=0;
	scanf("%i", &nr_zn); getchar();
	c0 = nr_zn%10; c1 = (nr_zn/10)%10; c2 = ((nr_zn/10)/10)%10;
	nr_zn = (c2*8+c1)*8+c0;
        strcpy(wiersz, "");
	while (nr_zn>=0) {
          zn=znak(nr_zn);
	  if (zn != '\0') {
	    wiersz[poz]=zn;
	    napisz_zn(nr_zn, poz);
	    poz++;
	    if (poz==DL_BUFORU) {
	      wiersz[poz]='\0'; poz=0;
	      dodruk(wiersz); druk_wiersz(wiersz);
	      strcpy(wiersz, "");
	    }
	  }
	  scanf("%i", &nr_zn); getchar();
	  c0 = nr_zn%10; c1 = (nr_zn/10)%10; c2 = ((nr_zn/10)/10)%10;
	  nr_zn = (c2*8+c1)*8+c0;
	}
        wiersz[poz]='\0';
        dodruk(wiersz); druk_wiersz(wiersz);
      }

  } while (odp!='z' && odp!='Z');

  printf("\n  Dziekuje.\n\n");

  return 0;
}
