root/main.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pouziti
  2. inicializace_pole
  3. spocti_cetnosti
  4. nejvetsi_cetnost
  5. najdi_nejmensi
  6. najdi_koren
  7. vytvor_strom
  8. merak_cb
  9. zapis_kod
  10. nacti_kod
  11. zapis_data
  12. komprese
  13. dekomprese
  14. f_ch_b_file_set_cb
  15. quit_cb
  16. komprese_cb
  17. dekomprese_cb
  18. about_cb
  19. main

   1 #include "main.h"
   2 
   3 /**
   4  * \brief Vypis napovedy
   5  *
   6  * Vypise do terminalu zpusob pouziti programu
   7  * @param str Nazev programu - obvykle argv[0]
   8  */
   9 void pouziti(gchar *str)
  10 {
  11         g_print("Huffressor %s\n", VERZE);
  12         g_print("Pouziti:\n%s [-cdg] [-v] [-i VSTUP] [-o VYSTUP]\n", str);
  13         g_print("\t-c ....... komprese\n");
  14         g_print("\t-d ....... dekomprese\n");
  15         g_print("\t-g ....... graficke rozhrani (vychozi)\n");
  16         g_print("\t-v ....... upovidany rezim\n");
  17         //g_print("\t-V ....... debugovaci vypisy\n");  // Pri velkych souborech extremne pomale - radsi neukazovat :-)
  18         g_print("\tVSTUP .... cesta ke vstupnimu souboru\n");
  19         g_print("\tVYSTUP ... cesta k vystupnimu souboru\n");
  20 }
  21 
  22 /**
  23  * \brief Inicializace pole cetnosti a stromu
  24  *
  25  * Nastavi vychozi hodnoty promennych v poli struktur pro vytvareni stromu
  26  */
  27 void inicializace_pole(void)
  28 {
  29         gint i;
  30         gint j;
  31 
  32         for (i = 0; i < VELIKOST_POLE; i++) {
  33                 pole[i].cetnost = 0;
  34                 if (i < 256) pole[i].znak = i;
  35                 else pole[i].znak = 0;
  36                 pole[i].spoj = -1;
  37                 pole[i].vetev1 = -1;
  38                 pole[i].vetev2 = -1;
  39                 for (j = 0; j < 256; j++) {
  40                         pole[i].kod[j] = '\0';
  41                 }
  42         }
  43 }
  44 
  45 /**
  46  * \brief Nacteni cetnosti ze vstupniho souboru
  47  *
  48  * Alokuje pamet pro vstupni a vystupni buffer, zkopiruje data vstupniho
  49  * souboru a spocita cetnosti jednotlivych znaku, ktere uklada do pole.
  50  * @param file Vstupni soubor
  51  * @param data Struktura obsahujici pointery na graficke prvky
  52  * @return
  53  */
  54 guchar *spocti_cetnosti(FILE *file, ChData *data)
  55 {
  56         glong i, j;
  57         glong velikost;
  58         glong precteno;
  59         guchar *buffer;
  60 
  61         fseek(file, 0L, SEEK_END); // Konec souboru
  62         velikost = ftell(file);
  63         if (vypisy > 0) printf("Velikost vstupniho souboru: %ld\n", velikost);
  64 
  65         buffer = malloc(velikost);
  66         if (buffer == NULL) {
  67                 fprintf(stderr, "Malo RAM\n\n");
  68                 if (grafika) gtk_label_set_label(GTK_LABEL(data->label_info), "Malo RAM\n\n");
  69                 return NULL;
  70         }
  71         fseek(file, 0L, SEEK_SET);
  72         precteno = fread(buffer, sizeof(guchar), velikost, file);
  73         if (vypisy > 0) printf("Precteno: %ld\n", precteno);
  74 
  75         for (i = 0; i < precteno; i++) {
  76                 pole[buffer[i]].cetnost++; // Inkrement poctu vyskytu tohoo znaku
  77                 velikost_vstup++;
  78                 pocet_znaku++;
  79         }
  80 
  81         if (vypisy > 0) {
  82                 g_print("Tabulka cetnosti:\n");
  83                 g_print("   \t0\t1\t2\t3\t4\t5\t6\t7\n");
  84                 for (j = 0; j < 32; j++) {
  85                         g_print("%3ld", j * 8);
  86                         for (i = 0; i < 8; i++) {
  87                                 if (pole[8 * j + i].cetnost == 0)
  88                                         g_print("\t.");
  89                                 else
  90                                         g_print("\t%d", pole[8 * j + i].cetnost);
  91                         }
  92                         g_print("\t%ld\n", j * 8 + 7);
  93                 }
  94                 g_print("   \t0\t1\t2\t3\t4\t5\t6\t7\n");
  95         }
  96 
  97         return buffer;
  98 }
  99 
 100 /**
 101  * \brief Nalezeni nejvyssi cetnosti
 102  *
 103  * Prohleda pole a najde nejvyssi cetnost vyskytu
 104  * @return Nejvyssi cetnost
 105  */
 106 gint nejvetsi_cetnost()
 107 {
 108         gint i;
 109         gint cetnost = 0;
 110 
 111         for (i = 0; i < VELIKOST_POLE; i++) {
 112                 if (pole[i].cetnost > cetnost)
 113                         cetnost = pole[i].cetnost;
 114         }
 115 
 116         if (vypisy > 1) {
 117                 g_print("Maximalni cetnost: %d\n", cetnost);
 118         }
 119 
 120         return cetnost;
 121 }
 122 
 123 /**
 124  * \brief Nalezeni uzlu s nejnizsi cetnosti
 125  *
 126  * Prohleda pole a najde uzel, ktery ma nejnizsi cetnost vyskytu
 127  * @return Index uzlu s nejnizsim vyskytem
 128  */
 129 gint najdi_nejmensi()
 130 {
 131         gint i;
 132         gint nejmensi = 0;
 133         gint nejmensi_cetnost = nejvetsi_cetnost(); // Pro inicializaci nejvetsi cetnost uzlu
 134 
 135         for (i = 0; i < VELIKOST_POLE; i++) {
 136                 if (pole[i].cetnost != 0 && pole[i].cetnost <= nejmensi_cetnost && pole[i].spoj == -1) {
 137                         nejmensi = i;
 138                         nejmensi_cetnost = pole[i].cetnost;
 139                 }
 140         }
 141 
 142         return nejmensi;
 143 }
 144 
 145 /**
 146  * \brief Nalezeni korenoveho uzlu
 147  *
 148  * Prohleda pole a najde korenovy uzel, tedy uzel s nejnvyssi cetnosti vyskytu
 149  * @return Index uzlu s nejvyssim vyskytem
 150  */
 151 gint najdi_koren()
 152 {
 153         gint i;
 154         gint nejvetsi = 0;
 155         gint nejvetsi_cetnost = 0;
 156 
 157         for (i = 0; i < VELIKOST_POLE; i++) {
 158                 if (pole[i].cetnost > nejvetsi_cetnost) {
 159                         nejvetsi = i;
 160                         nejvetsi_cetnost = pole[i].cetnost;
 161                 }
 162         }
 163 
 164         return nejvetsi;
 165 }
 166 
 167 /**
 168  * \brief Vytvoreni stromu
 169  *
 170  * Prochazi pole a spojovanim uzlu vytvari strom pro kodovani nebo dekodovani
 171  * @param data Struktura obsahujici pointery na graficke prvky
 172  * @return Vraci nulu, pokud nedoslo k chybe
 173  */
 174 gint vytvor_strom(ChData *data)
 175 {
 176         gint nejmensi;
 177         gint dalsi_uzel = 256;
 178         gint i;
 179         gint j;
 180         guchar tmp[256];
 181         gint error = 0;
 182 
 183         nejmensi = najdi_nejmensi();
 184         while (pole[nejmensi].cetnost < pocet_znaku) {
 185                 pole[nejmensi].spoj = dalsi_uzel;
 186                 strcat(pole[nejmensi].kod, "1");
 187                 pole[dalsi_uzel].vetev1 = nejmensi;
 188 
 189                 nejmensi = najdi_nejmensi();
 190                 pole[nejmensi].spoj = dalsi_uzel;
 191                 strcat(pole[nejmensi].kod, "0");
 192                 pole[dalsi_uzel].vetev2 = nejmensi;
 193 
 194                 pole[dalsi_uzel].cetnost = pole[pole[dalsi_uzel].vetev1].cetnost + pole[pole[dalsi_uzel].vetev2].cetnost;
 195 
 196                 if (vypisy > 1) {
 197                         g_print("Uzel %d[%d] spojuje uzly %d[%d] a %d[%d]\n", dalsi_uzel, pole[dalsi_uzel].cetnost, pole[dalsi_uzel].vetev1, pole[pole[dalsi_uzel].vetev1].cetnost, pole[dalsi_uzel].vetev2, pole[pole[dalsi_uzel].vetev2].cetnost);
 198                 }
 199 
 200                 dalsi_uzel++;
 201                 nejmensi = najdi_nejmensi();
 202         }
 203 
 204         for (i = 0; i < 256; i++) {
 205                 if (pole[i].cetnost != 0) {
 206                         j = pole[i].spoj;
 207                         if (j < 0 || j > 512) {
 208                                 fprintf(stderr, "Kriticka chyba pri vytvareni stromu\n");
 209                                 if (grafika) gtk_label_set_label(GTK_LABEL(data->label_info), "Soubor nelze dekodovat");
 210                                 error = 1;
 211                                 break;
 212                         }
 213                         while (pole[j].spoj != -1) {
 214                                 strcpy(tmp, pole[i].kod);
 215                                 strcpy(pole[i].kod, pole[j].kod);
 216                                 strcat(pole[i].kod, tmp);
 217                                 j = pole[j].spoj;
 218                         }
 219                         if (vypisy > 1) {
 220                                 isprint(pole[i].znak);
 221                                 g_print("%c = %s\n", pole[i].znak, pole[i].kod);
 222                         }
 223                 }
 224         }
 225 
 226         return error;
 227 }
 228 
 229 /**
 230  * \brief Mereni rychlosti a prubehu
 231  *
 232  * Meri a zobrazuje rychlost komprese v MB/s a prubeh zpracovani v %
 233  * @param data Struktura obsahujici pointery na graficke prvky
 234  * @return TRUE pokud vypocet pokracuje, FALSE po ukonceni
 235  */
 236 gboolean merak_cb(gpointer data)
 237 {
 238         glong diff = pro_merak - pro_merak_posledni;
 239         gfloat speed;
 240         ChData *chdata = (ChData*) data;
 241         gchar buf[50];
 242         gfloat prubeh;
 243 
 244         pro_merak_posledni = pro_merak;
 245 
 246         prubeh = (gfloat) pro_merak / (gfloat) pro_merak_celkem * 100;
 247 
 248         if (diff == 0) {
 249                 if (grafika) gtk_label_set_label(GTK_LABEL(chdata->label_info), "Ukladam soubor");
 250                 if (grafika) gtk_statusbar_push(GTK_STATUSBAR(chdata->statusbar), gtk_statusbar_get_context_id(GTK_STATUSBAR(chdata->statusbar), "uvitani"), VERZE);
 251 
 252                 return FALSE;
 253         } else {
 254                 speed = (gfloat) diff * 1000.0 / (gfloat) TIMEOUT / 1e6;
 255                 if (vypisy > 1) g_print("%s\n", buf);
 256                 sprintf(buf, "Zpracovano: %.1f%%", prubeh);
 257                 if (grafika) gtk_label_set_label(GTK_LABEL(chdata->label_info), buf);
 258                 sprintf(buf, "Aktualni rychlost: %.3fMB/s", speed);
 259                 if (grafika) gtk_statusbar_push(GTK_STATUSBAR(chdata->statusbar), gtk_statusbar_get_context_id(GTK_STATUSBAR(chdata->statusbar), "rychlost"), buf);
 260                 return TRUE;
 261         }
 262 }
 263 
 264 /**
 265  * \brief Zapise zakodovany soubor na vystup
 266  *
 267  * Vytvori hlavicku souboru a podle kodovaciho stromu zakoduje data z bufferu.
 268  * Struktura hlavicky:\n
 269  * 1B Pocet znaku v tabulce\n
 270  * 1B znak 1\n
 271  * 4B cetnost znaku 1\n
 272  * 1B znak 2\n
 273  * 4B cetnost znaku 2\n
 274  * atd...
 275  * @param buffer_in Pointer na data pro kompresi
 276  * @param file Vystupni soubor
 277  * @param data Struktura obsahujici pointery na graficke prvky
 278  * @return 0 pokud nedojde k chybe
 279  */
 280 gint zapis_kod(guchar *buffer_in, FILE *file, ChData *data)
 281 {
 282         guchar *buffer;
 283         gint znaku_v_tabulce = 0;
 284         gint i;
 285         glong velikost_bufferu;
 286         guchar kod1[VELIKOST_BUFF];
 287         guchar kod2[VELIKOST_BUFF];
 288         guchar byte;
 289         gint j;
 290 
 291         velikost_bufferu = velikost_vstup + 256 * (sizeof(guchar) + sizeof(gint)) + 1;
 292         buffer = malloc(velikost_bufferu);
 293         if (buffer == NULL) {
 294                 fprintf(stderr, "Malo RAM\n");
 295                 if (grafika) gtk_label_set_label(GTK_LABEL(data->label_info), "Malo RAM\n");
 296                 return 1;
 297         }
 298         memset(buffer, 0, velikost_bufferu);
 299 
 300         for (i = 0; i < 256; i++) {
 301                 if (pole[i].cetnost > 0) {
 302                         buffer[znaku_v_tabulce * 5 + 1] = pole[i].znak;
 303                         buffer[znaku_v_tabulce * 5 + 2] = (guchar) ((pole[i].cetnost >> 24) & 0x000000ff);
 304                         buffer[znaku_v_tabulce * 5 + 3] = (guchar) ((pole[i].cetnost >> 16) & 0x000000ff);
 305                         buffer[znaku_v_tabulce * 5 + 4] = (guchar) ((pole[i].cetnost >> 8) & 0x000000ff);
 306                         buffer[znaku_v_tabulce * 5 + 5] = (guchar) ((pole[i].cetnost >> 0) & 0x000000ff);
 307                         znaku_v_tabulce++;
 308                 }
 309         }
 310         if (znaku_v_tabulce == 0) {
 311                 buffer[0] = 0;
 312         } else {
 313                 buffer[0] = (guchar) znaku_v_tabulce - 1;
 314         }
 315         hlavicka = znaku_v_tabulce * 5 + 1;
 316         velikost_vystup = hlavicka;
 317 
 318         pro_merak_celkem = velikost_vstup;
 319         pro_merak = 0;
 320         g_timeout_add(TIMEOUT, merak_cb, data);
 321 
 322         memset(kod1, 0, VELIKOST_BUFF);
 323         memset(kod2, 0, VELIKOST_BUFF);
 324         for (i = 0; i < velikost_vstup; i++) {
 325                 strcat(kod1, pole[buffer_in[i]].kod);
 326                 while (strlen(kod1) >= 8) {
 327                         byte = 0x00;
 328                         for (j = 0; j < 8; j++) {
 329                                 if (kod1[j] == '1') {
 330                                         byte |= 0x80 >> j;
 331                                 }
 332                         }
 333                         buffer[velikost_vystup] = byte;
 334                         velikost_vystup++;
 335                         strcpy(kod2, &kod1[8]);
 336                         strcpy(kod1, kod2);
 337                         pro_merak++;
 338                 }
 339         }
 340         if (strlen(kod1) > 0) {
 341                 byte = 0x00;
 342                 for (j = 0; j < 8; j++) {
 343                         if (kod1[j] == '1') {
 344                                 byte |= 0x80 >> j;
 345                         } else if (kod1[j] == '\0') {
 346                                 break;
 347                         }
 348                 }
 349                 buffer[velikost_vystup] = byte;
 350                 velikost_vystup++;
 351         }
 352 
 353         if (vypisy > 0) {
 354                 g_print("Velikost souboru pred kompresi: %ld\n", velikost_vstup);
 355                 g_print("Velikost souboru po kompresi: %ld\n", velikost_vystup);
 356                 g_print("Z toho hlavicka: %ld\n", hlavicka);
 357                 g_print("Relativni velikost vystupniho souboru: %f\n", (float) velikost_vystup / (float) velikost_vstup);
 358         }
 359 
 360 
 361         fwrite(buffer, sizeof(guchar), velikost_vystup, file);
 362         free(buffer);
 363 
 364         return 0;
 365 }
 366 
 367 /**
 368  * \brief Nacte zakodovany soubor
 369  *
 370  * Alokuje buffer a nacte zakodovany soubor. Z hlavicky inicializuje pole pro
 371  * kodovaci strom. Prvni faze kontroly souboru na vyskyt chyb.
 372  * @param file Vstupni soubor
 373  * @param data Struktura obsahujici pointery na graficke prvky
 374  * @return Pointer na buffer nactenych dat
 375  */
 376 guchar *nacti_kod(FILE *file, ChData *data)
 377 {
 378         guchar *buffer;
 379         glong velikost;
 380         glong precteno;
 381         gint i;
 382         gint znaku_v_tabulce;
 383 
 384         fseek(file, 0L, SEEK_END); // Konec souboru
 385         velikost = ftell(file);
 386         if (vypisy > 0) g_print("Velikost vstupniho souboru: %ld\n", velikost);
 387 
 388         buffer = malloc(velikost);
 389         if (buffer == NULL) {
 390                 fprintf(stderr, "Malo RAM\n");
 391                 if (grafika) gtk_label_set_label(GTK_LABEL(data->label_info), "Malo RAM\n");
 392                 return NULL;
 393         }
 394         fseek(file, 0L, SEEK_SET);
 395         precteno = fread(buffer, sizeof(guchar), velikost, file);
 396         if (vypisy > 0) g_print("Precteno: %ld\n", precteno);
 397         velikost_vstup = precteno;
 398 
 399         if (velikost < 2) { // Jinak rozbalujeme prazdny soubor
 400                 znaku_v_tabulce = 0;
 401         } else {
 402                 znaku_v_tabulce = buffer[0] + 1;
 403         }
 404 
 405         for (i = 0; i < znaku_v_tabulce; i++) {
 406                 if (5 * i + 5 > precteno) {
 407                         fprintf(stderr, "Soubor pravdepodobne nebyl komprimovan Huffressorem\n");
 408                         znaku_v_tabulce = 0; // Aby nic nedelal
 409                         pocet_znaku = 0; // Aby nic nedelal
 410                 }
 411                 pole[buffer[5 * i + 1]].cetnost = (((gint) buffer[5 * i + 2]) << 24) & 0xff000000;
 412                 pole[buffer[5 * i + 1]].cetnost |= (((gint) buffer[5 * i + 3]) << 16) & 0x00ff0000;
 413                 pole[buffer[5 * i + 1]].cetnost |= (((gint) buffer[5 * i + 4]) << 8) & 0x0000ff00;
 414                 pole[buffer[5 * i + 1]].cetnost |= (((gint) buffer[5 * i + 5]) << 0) & 0x000000ff;
 415                 pocet_znaku += pole[buffer[5 * i + 1]].cetnost;
 416         }
 417         hlavicka = znaku_v_tabulce * 5 + 1;
 418 
 419         if (vypisy > 0) {
 420                 g_print("Velikost hlavicky: %ld\n", hlavicka);
 421         }
 422 
 423         return buffer;
 424 }
 425 
 426 /**
 427  * \brief Zapis dekodovanych dat
 428  *
 429  * Podle binarniho stromu dekoduje vstupni buffer a zapise data do vystupniho
 430  * souboru. Druha faze kontroly chyb.
 431  * @param buffer_in Buffer zakodovanych dat
 432  * @param file Vystupni soubor
 433  * @param data Struktura obsahujici pointery na graficke prvky
 434  * @return 0 pokud nedoslo k chybe
 435  */
 436 gint zapis_data(guchar *buffer_in, FILE *file, ChData *data)
 437 {
 438         guchar byte;
 439         gint koren;
 440         guchar *buffer;
 441         glong i = 0;
 442         gint j;
 443         gint k = -1;
 444         glong pozice = hlavicka; // Prvni byte dat
 445 
 446         buffer = malloc(pocet_znaku);
 447         if (buffer == NULL) {
 448                 fprintf(stderr, "Malo RAM\n");
 449                 if (grafika) gtk_label_set_label(GTK_LABEL(data->label_info), "Malo RAM\n");
 450                 return 1;
 451         }
 452 
 453         pro_merak_celkem = pocet_znaku;
 454         pro_merak = 0;
 455         g_timeout_add(TIMEOUT, merak_cb, data);
 456 
 457         koren = najdi_koren(); // Vychozi uzel
 458         while (i < pocet_znaku) {
 459                 j = koren;
 460                 do {
 461                         if (k == -1) { // Zpracovani dalsiho bytu
 462                                 if (pozice >= velikost_vstup) {
 463                                         fprintf(stderr, "Soubor poskozen, nebo nebyl komprimovan Huffressorem\n");
 464                                         return 1;
 465                                 }
 466                                 byte = buffer_in[pozice++];
 467                                 k = 7;
 468                         }
 469                         if ((byte >> k) & 0x01) {
 470                                 j = pole[j].vetev1;
 471                                 if (vypisy > 1) printf("1");
 472                         } else {
 473                                 j = pole[j].vetev2;
 474                                 if (vypisy > 1) printf("0");
 475                         }
 476                         k--;
 477                 } while (pole[j].vetev1 != -1); // Dosli jsme ke znaku
 478                 buffer[i] = pole[j].znak;
 479                 i++;
 480                 if (vypisy > 1) printf(" = %c\n", pole[j].znak);
 481                 pro_merak++;
 482         }
 483 
 484         fwrite(buffer, sizeof(gchar), pocet_znaku, file);
 485         free(buffer);
 486 
 487         return 0;
 488 }
 489 
 490 /**
 491  * \brief Hlavni funkce komprese
 492  *
 493  * Otevre vstupni a vystupni soubory a vola funkce provadejici jednotlive kroky
 494  * komprese. Nakonec uzavira soubory a uvolnuje alokovany buffer.
 495  * @param data Struktura obsahujici pointery na graficke prvky
 496  * @return 0 pokud nedojde k chybe
 497  */
 498 gint komprese(gpointer data)
 499 {
 500         guchar *buffer_in;
 501         FILE *in;
 502         FILE *out;
 503         gchar *f_name_in = ((ChData*) data)->f_in;
 504         gchar *f_name_out = ((ChData*) data)->f_out;
 505 
 506         pocet_znaku = 0;
 507         velikost_vstup = 0;
 508         velikost_vystup = 0;
 509 
 510         in = fopen(f_name_in, "rb");
 511         if (in == NULL) {
 512                 fprintf(stderr, "Nepodarilo se otevrit %s\n", f_name_in);
 513                 return -1;
 514         }
 515         out = fopen(f_name_out, "wb");
 516         if (out == NULL) {
 517                 fprintf(stderr, "Nepodarilo se otevrit %s\n", f_name_out);
 518                 return -1;
 519         }
 520 
 521         inicializace_pole();
 522         if ((buffer_in = spocti_cetnosti(in, data)) == NULL) return 1;
 523         if (vytvor_strom(data)) {
 524                 free(buffer_in);
 525                 return 1;
 526         }
 527         if (zapis_kod(buffer_in, out, data)) {
 528                 free(buffer_in);
 529                 return 1;
 530         }
 531 
 532         free(buffer_in);
 533         fclose(in);
 534         fclose(out);
 535 
 536         if (grafika) gtk_label_set_label(GTK_LABEL(((ChData *) data)->label_info), "Uspesne dokonceno");
 537 
 538         return 0;
 539 }
 540 
 541 /**
 542  * \brief Hlavni funkce dekomprese
 543  *
 544  * Otevre vstupni a vystupni soubory a vola funkce provadejici jednotlive kroky
 545  * dekomprese. Nakonec uzavira soubory a uvolnuje alokovany buffer.
 546  * @param data Struktura obsahujici pointery na graficke prvky
 547  * @return 0 pokud nedojde k chybe
 548  */
 549 gint dekomprese(gpointer data)
 550 {
 551         guchar *buffer_in;
 552         FILE *in;
 553         FILE *out;
 554         gchar *f_name_in = ((ChData*) data)->f_in;
 555         gchar *f_name_out = ((ChData*) data)->f_out;
 556 
 557         pocet_znaku = 0;
 558         velikost_vstup = 0;
 559         velikost_vystup = 0;
 560 
 561         in = fopen(f_name_in, "rb");
 562         if (in == NULL) {
 563                 fprintf(stderr, "Nepodarilo se otevrit %s\n", f_name_in);
 564                 return -1;
 565         }
 566         out = fopen(f_name_out, "wb");
 567         if (out == NULL) {
 568                 fprintf(stderr, "Nepodarilo se otevrit %s\n", f_name_out);
 569                 return -1;
 570         }
 571 
 572         inicializace_pole();
 573         if ((buffer_in = nacti_kod(in, data)) == NULL) return 1;
 574         if (vytvor_strom(data)) {
 575                 free(buffer_in);
 576                 return 1;
 577         }
 578         if (zapis_data(buffer_in, out, data)) {
 579                 free(buffer_in);
 580                 return 1;
 581         }
 582 
 583         free(buffer_in);
 584         fclose(in);
 585         fclose(out);
 586 
 587         if (grafika) gtk_label_set_label(GTK_LABEL(((ChData *) data)->label_info), "Uspesne dokonceno");
 588 
 589         return 0;
 590 }
 591 
 592 /**
 593  * \brief Callback funkce widgetu vyber souboru
 594  *
 595  * Zpracuje nastaveny vstupni soubor, ulozi jeho nazev do struktury a podle
 596  * pripony nastavi vystupni soubor.
 597  * @param widget Pointer na tlacitko vyberu souboru
 598  * @param data Struktura obsahujici pointery na graficke prvky
 599  */
 600 G_MODULE_EXPORT void f_ch_b_file_set_cb(GtkWidget *widget, ChData *data)
 601 {
 602         gchar buf[500];
 603 
 604         data->f_in = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget));
 605         g_print("%s\n", data->f_in);
 606 
 607         if (strlen(data->f_in) > 4);
 608         if (strcmp(&(data->f_in)[strlen(data->f_in) - 4], ".hcr") == 0) {
 609                 if (vypisy > 0) g_print("Vybran zabaleny soubor\n");
 610                 strcpy(buf, data->f_in);
 611                 buf[strlen(buf) - 4] = 0; // Urizne priponu
 612                 gtk_entry_set_text(GTK_ENTRY(data->entry_vystup), buf);
 613                 if (vypisy > 0) g_print("Vystupni soubor: %s\n", buf);
 614                 strcpy(data->f_out, buf);
 615         } else {
 616                 if (vypisy > 0) g_print("Vybran neznamy soubor\n");
 617                 strcpy(buf, data->f_in);
 618                 strcat(buf, ".hcr");
 619                 gtk_entry_set_text(GTK_ENTRY(data->entry_vystup), buf);
 620                 if (vypisy > 0) g_print("Vystupni soubor: %s\n", buf);
 621                 strcpy(data->f_out, buf);
 622         }
 623 }
 624 
 625 /**
 626  * \brief Callback ukonceni programu
 627  *
 628  * Ukonci hlavni smycku GTK.
 629  * @param widget Pointer na volajici widget
 630  * @param data Struktura obsahujici pointery na graficke prvky
 631  */
 632 G_MODULE_EXPORT void quit_cb(GtkWidget *widget, ChData *data)
 633 {
 634         fprintf(stderr, "Koncim\n");
 635         gtk_main_quit();
 636 }
 637 
 638 /**
 639  * \brief Callback kliku na tlacitko komprese
 640  *
 641  * Nastavi informaci o spusteni komprese a spusti funkci komprese v novem
 642  * vlaknu.
 643  * @param widget Pointer na widget tlacitka
 644  * @param data Struktura obsahujici pointery na graficke prvky
 645  */
 646 G_MODULE_EXPORT void komprese_cb(GtkWidget *widget, ChData *data)
 647 {
 648         if (vypisy > 0) g_print("Spustena komprese\n");
 649         gtk_label_set_label(GTK_LABEL(data->label_info), "Nacitam soubor");
 650 
 651         strcpy(data->f_out, gtk_entry_get_text(GTK_ENTRY(data->entry_vystup)));
 652 
 653         if ((thread = g_thread_create((GThreadFunc) komprese, data, FALSE, &err)) == NULL) {
 654                 fprintf(stderr, "Spusteni threadu se nepovedlo: %s!\n", err->message);
 655                 g_error_free(err);
 656         }
 657 }
 658 
 659 /**
 660  * \brief Callback kliku na tlacitko dekomprese
 661  *
 662  * Nastavi informaci o spusteni dekomprese a spusti funkci dekomprese v novem
 663  * vlaknu.
 664  * @param widget Pointer na widget tlacitka
 665  * @param data Struktura obsahujici pointery na graficke prvky
 666  */
 667 G_MODULE_EXPORT void dekomprese_cb(GtkWidget *widget, ChData *data)
 668 {
 669         if (vypisy > 0) g_print("Spustena dekomprese\n");
 670         gtk_label_set_label(GTK_LABEL(data->label_info), "Nacitam soubor");
 671 
 672         strcpy(data->f_out, gtk_entry_get_text(GTK_ENTRY(data->entry_vystup)));
 673 
 674         if ((thread = g_thread_create((GThreadFunc) dekomprese, data, FALSE, &err)) == NULL) {
 675                 fprintf(stderr, "Spusteni threadu se nepovedlo: %s!\n", err->message);
 676                 g_error_free(err);
 677         }
 678 }
 679 
 680 /**
 681  * \brief Callback menu About
 682  *
 683  * Pomoci GtkBuilderu vytvori a zobrazi About dialog. Nastavi callback pro
 684  * zavreni okna (dulezite)
 685  * @param widget Pointer na volbu menu
 686  * @param data Struktura obsahujici pointery na graficke prvky
 687  */
 688 G_MODULE_EXPORT void about_cb(GtkWidget *widget, ChData *data)
 689 {
 690         GtkBuilder *builder;
 691         GtkWidget *about_dialog;
 692         GError *error = NULL;
 693 
 694         builder = gtk_builder_new();
 695         if (!gtk_builder_add_from_file(builder, ABOUT_FILE, &error)) {
 696                 g_warning("%s", error->message);
 697                 g_free(error);
 698                 return;
 699         }
 700         about_dialog = GTK_WIDGET(gtk_builder_get_object(builder, "aboutdialog"));
 701         gtk_builder_connect_signals(builder, NULL);
 702         g_signal_connect_swapped(about_dialog, "response", G_CALLBACK(gtk_widget_destroy), about_dialog); // Aby fungovalo Close
 703         g_object_unref(G_OBJECT(builder));
 704         gtk_widget_show(about_dialog);
 705 }
 706 
 707 /**
 708  * \brief Hlavni funkce
 709  *
 710  * Provede nacteni parametru prikazove radky, inicializuje nazvy souboru a podle
 711  * voleb spusti kompresi, dekompresi, zobrazi napovedu nebo nacte a zobrazi
 712  * graficke rozhrani.
 713  * @param argc Pocet retezcu v shellu pri spusteni
 714  * @param argv Pole pointeru na retezce v shellu pri spusteni
 715  * @return 0 pokud nedojde k chybe
 716  */
 717 gint main(int argc, char **argv)
 718 {
 719         ChData *data; /**< Struktura obsahujici pointery na graficke prvky */
 720         GtkBuilder *builder; /**< Struktura pro nacteni GUI z .glade souboru */
 721         GError *error = NULL; /**< Chyby pri nacitani GUI */
 722         gint akce = GRAFIKA; /**< Prepinac provedene akce */
 723         gchar f_in[1024] = {0}; /**< Retezec nazvu vstupniho souboru */
 724         gchar f_out[1024] = {0}; /**< Retezec nazvu vystupniho souboru */
 725         gint c; /**< Promenna pouzita pro zpracovani parametru shellu */
 726 
 727         opterr = 0;
 728         grafika = 1;
 729 
 730         while ((c = getopt(argc, argv, "cdghi:o:vV")) != -1) {
 731                 switch (c) {
 732                 case 'c':
 733                         akce = KOMPRESE;
 734                         grafika = 0;
 735                         break;
 736                 case 'd':
 737                         akce = DEKOMPRESE;
 738                         grafika = 0;
 739                         break;
 740                 case 'g':
 741                         akce = GRAFIKA;
 742                         grafika = 1;
 743                         break;
 744                 case 'h':
 745                         pouziti(argv[0]);
 746                         return 0;
 747                         break;
 748                 case 'i':
 749                         strcpy(f_in, optarg);
 750                         break;
 751                 case 'o':
 752                         strcpy(f_out, optarg);
 753                         break;
 754                 case 'v':
 755                         vypisy = 1;
 756                         break;
 757                 case 'V':
 758                         vypisy = 2;
 759                         break;
 760                 case '?':
 761                         if (optopt == 'i' || optopt == 'o')
 762                                 fprintf(stderr, "Parametru -%c chybi nazev souboru.\n", optopt);
 763                         else if (isprint(optopt))
 764                                 fprintf(stderr, "Neznamy parametr '-%c'.\n", optopt);
 765                         else
 766                                 fprintf(stderr, "Neznamy znak '\\x%x'.\n", optopt);
 767                         return -1;
 768                 default:
 769                         return -1;
 770                 }
 771         }
 772 
 773         if ((akce == 0 || f_in[0] == '\0' || f_out[0] == '\0') && akce != GRAFIKA) {
 774                 pouziti(argv[0]);
 775                 return 0;
 776         }
 777 
 778         data = g_slice_new(ChData);
 779         data->f_in = f_in;
 780         data->f_out = f_out;
 781 
 782         if (akce == GRAFIKA) {
 783                 gtk_init(&argc, &argv);
 784                 g_thread_init(NULL);
 785                 builder = gtk_builder_new();
 786                 if (!gtk_builder_add_from_file(builder, GUI_FILE, &error)) {
 787                         g_warning("%s", error->message);
 788                         g_free(error);
 789                         return 1;
 790                 }
 791 
 792                 data->main_window = GTK_WIDGET(gtk_builder_get_object(builder, "main_window"));
 793                 data->label_info = GTK_WIDGET(gtk_builder_get_object(builder, "label_info"));
 794                 data->f_ch_b = GTK_WIDGET(gtk_builder_get_object(builder, "f_ch_b"));
 795                 data->entry_vystup = GTK_WIDGET(gtk_builder_get_object(builder, "entry_vystup"));
 796                 data->statusbar = GTK_WIDGET(gtk_builder_get_object(builder, "statusbar"));
 797 
 798                 gtk_builder_connect_signals(builder, data);
 799                 g_object_unref(G_OBJECT(builder));
 800                 gtk_widget_show(data->main_window);
 801                 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(data->f_ch_b), f_in);
 802                 gtk_entry_set_text(GTK_ENTRY(data->entry_vystup), f_out);
 803                 gtk_statusbar_push(GTK_STATUSBAR(data->statusbar), gtk_statusbar_get_context_id(GTK_STATUSBAR(data->statusbar), "uvitani"), VERZE);
 804 
 805                 gtk_main();
 806 
 807         } else if (akce == KOMPRESE) {
 808                 if (komprese(data) != 0) {
 809                         fprintf(stderr, "Komprese se nezdarila.\n");
 810                         return -1;
 811                 }
 812 
 813         } else if (akce == DEKOMPRESE) {
 814                 if (dekomprese(data) != 0) {
 815                         fprintf(stderr, "Dekomprese se nezdarila.\n");
 816                         return -1;
 817                 }
 818         }
 819 
 820         g_slice_free(ChData, data);
 821 
 822         return 0;
 823 }

/* [<][>][^][v][top][bottom][index][help] */