home *** CD-ROM | disk | FTP | other *** search
/ M.u.C.S. Disc 2000 / MUCS2000.iso / anwend / qed453 / src / file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-06-13  |  14.4 KB  |  774 lines

  1. #include <errno.h>
  2. #include <stat.h>
  3. #include <time.h>
  4. #include <unistd.h>
  5.  
  6. #include "global.h"
  7. #include "aktion.h"
  8. #include "comm.h"
  9. #include "edit.h"
  10. #include "find.h"
  11. #include "icon.h"
  12. #include "memory.h"
  13. #include "olga.h"
  14. #include "options.h"
  15. #include "projekt.h"
  16. #include "rsc.h"
  17. #include "text.h"
  18. #include "window.h"
  19. #include "file.h"
  20.  
  21.  
  22. static PATH    last_path;                         /* letzter Pfad der Dateiauswahl */
  23.  
  24. /* Puffer-Länge zum Lesen/Schreiben */
  25. #define    BUFFERSIZE    4*1024L
  26.  
  27. void open_error(char *filename, int error)
  28. {
  29.     FILENAME    datei;
  30.     PATH        path;
  31.  
  32.     split_filename(filename, path, datei);
  33.     if (error == -33 && path_exists(path))    /* file not found und Pfad existiert */
  34.         snote(1, 0, NOTEXIST, datei);
  35.     else
  36.         snote(1, 0, READERR, datei);
  37. }
  38.  
  39. int load(TEXTP t_ptr, bool verbose)
  40. {
  41.     int    antw;
  42.     bool    null_byte;
  43.     
  44.     antw = load_datei(t_ptr->filename, &t_ptr->text, verbose, &null_byte);
  45.     t_ptr->cursor_line = t_ptr->text.head.nachf;
  46.     t_ptr->readonly = file_readonly(t_ptr->filename);
  47.     if (null_byte)
  48.         t_ptr->moved++;
  49.     if (antw == 0)
  50.     {
  51.         t_ptr->file_date_time = file_time(t_ptr->filename,NULL,NULL);
  52.     }
  53.     else
  54.         t_ptr->file_date_time = -1L;
  55.     return(antw);
  56. }
  57.  
  58.  
  59. int load_from_fd(int fd, char *name, RINGP t, bool verbose, bool *null_byte, long size)
  60. {
  61.     int        antw;
  62.     bool        nb = FALSE, 
  63.                 ol = FALSE;
  64.     char        *buffer, *zeile;
  65.     ZEILEP     start, next;
  66.     long        l, p, bytes;
  67.     int        n;
  68.     bool        new_line, cr = FALSE, mem = TRUE;
  69.  
  70.     /* Puffer anfordern */
  71.     buffer = (char *)malloc(BUFFERSIZE);
  72.     zeile = malloc(MAX_LINE_LEN + 2);                /* + 2 für Zeilenende */
  73.  
  74.     if (buffer == NULL || zeile == NULL)
  75.     {
  76.         note(1, 0, NOMEMORY);
  77.         return -39;
  78.     }                
  79.  
  80.     nb = FALSE;
  81.     graf_mouse(HOURGLASS, NULL);
  82.  
  83.     /* Progress-Bar */
  84.     verbose = verbose && ((size >> 10) >= transfer_size);
  85.     if (verbose)
  86.     {
  87.         char        str[40];
  88.         FILENAME    file;
  89.  
  90.         strcpy(str, rsc_string(LOADSTR));
  91.         file_name(name, file, FALSE);
  92.         strcat(str, file);
  93.         start_aktion(str, FALSE, size);
  94.         bytes = 0L;
  95.     }
  96.  
  97.  
  98.     /* Liste vorbereiten */
  99.     start = t->tail.vorg;
  100.  
  101.     /* Einlesen */
  102.     l = Fread(fd, BUFFERSIZE, buffer);
  103.  
  104.     n = 0;
  105.     new_line = FALSE;
  106.     while (mem && (l > 0))
  107.     {
  108.         p = 0;
  109.         while (mem && (p < l))
  110.         {
  111.             if (t->ending != binmode)
  112.             {
  113.                 if (buffer[p] == 0x0D)                /* CR -> Mac */
  114.                 {
  115.                     new_line = TRUE;
  116.                     p++;
  117.                     cr = TRUE;
  118.                     t->ending = apple;
  119.                 }
  120.                 else if (buffer[p] == 0x0A)        /* LF */
  121.                 {
  122.                     p++;
  123.                     if (cr)                                /* CRLF -> TOS*/
  124.                     {
  125.                         cr = FALSE;
  126.                         t->ending = tos;
  127.                     }
  128.                     else
  129.                     {
  130.                         new_line = TRUE;                /* -> Unix */
  131.                         t->ending = unix;
  132.                     }
  133.                 }
  134.                 else if (n >= t->max_line_len)    /* Überlänge */
  135.                 {
  136.                     ol = TRUE;
  137.                     new_line = TRUE;
  138.                 }
  139.                 else 
  140.                 {
  141.                     /* Nullbyte? */
  142.                     if (buffer[p] == '\0')
  143.                     {
  144.                         nb = TRUE;
  145.                         buffer[p] = ' ';                /* Durch Leerzeichen ersetzen */
  146.                     }
  147.                     zeile[n] = buffer[p];
  148.                     n++;
  149.                     p++;
  150.                 }
  151.             }
  152.             else    /* binmode */
  153.             {
  154.                 if (n >= (t->max_line_len - 1))
  155.                     new_line = TRUE;
  156.                 zeile[n] = buffer[p];
  157.                 n++;
  158.                 p++;
  159.             }
  160.             
  161.             if (new_line)
  162.             {
  163.                 zeile[n] = EOS;
  164.                 start->nachf = new_col(zeile, n);
  165.                 if (start->nachf == NULL)
  166.                     mem = FALSE;
  167.                 else
  168.                 {
  169.                     start = start->nachf;
  170.                     if (ol)
  171.                     {
  172.                         start->info |= OVERLEN;
  173.                         ol = FALSE;
  174.                     }
  175.                 }
  176.                 n = 0;
  177.                 new_line = FALSE;
  178.             }
  179.         } /* while */
  180.  
  181.         if (verbose)
  182.         {
  183.             bytes += BUFFERSIZE;
  184.             do_aktion("", bytes);
  185.         }
  186.         l = Fread(fd, BUFFERSIZE, buffer);
  187.  
  188.         /* EOF */
  189.         if (l == 0)
  190.         {
  191.             /* letzte Zeile ohne Zeilenende! */
  192.             if (n > 0)
  193.             {
  194.                 zeile[n] = EOS;
  195.                 start->nachf = new_col(zeile, n);
  196.                 if (start->nachf == NULL)
  197.                     mem = FALSE;
  198.                 else
  199.                     start = start->nachf;
  200.             }
  201.  
  202.             /* letzte Zeile hatte ZE -> ein Dummyzeile anhängen */
  203.             else if (n == 0)
  204.             {
  205.                 start->nachf = new_col(zeile, 0);
  206.                 if (start->nachf == NULL)
  207.                     mem = FALSE;
  208.                 else
  209.                     start = start->nachf;
  210.             }
  211.         }
  212.     } /* while */
  213.  
  214.     if (mem)
  215.     {
  216.         /* Ring schlie₧en */
  217.         t->tail.vorg = start;
  218.         start->nachf = &t->tail;
  219.  
  220.         /* Anzahl der Zeilen ermitteln */
  221.         start = t->head.nachf;
  222.         next = start->nachf;
  223.         for (l = 0; !IS_TAIL(start); l++)
  224.         {
  225.             next->vorg = start;
  226.             start = next;
  227.             NEXT(next);
  228.         }
  229.         t->lines = l;
  230.         if (l > 1L)
  231.             col_delete(t, t->head.nachf);
  232.  
  233.         antw = 0;
  234.     }
  235.     else
  236.     {
  237.         /* Speichermangel! Bisher gelesene Zeilen freigeben. */
  238.         next = FIRST(t);
  239.         while (next)
  240.         {
  241.             start = next;
  242.             NEXT(next);
  243.             free_col(start);
  244.         }
  245.         graf_mouse(ARROW, NULL);
  246.         note(1, 0, NOMEMORY);
  247.         antw = -39;
  248.     }
  249.  
  250.     free(buffer);
  251.     free(zeile);
  252.     
  253.     if (verbose)
  254.         end_aktion();
  255.  
  256.     graf_mouse(ARROW, NULL);
  257.  
  258.     if (null_byte != NULL)
  259.         *null_byte = nb;
  260.     return(antw);
  261. }
  262.  
  263. int load_datei(char *name, RINGP t, bool verbose, bool *null_byte)
  264. {
  265.     int    antw, fd;
  266.     long    size;
  267.     
  268.     /* grö₧e der Datei ermitteln */
  269.     size = file_size(name);
  270.     if (size >= 0L)
  271.     {
  272.         fd = (int) Fopen(name, 0);
  273.         if (fd > 0)
  274.         {
  275.             antw = load_from_fd(fd, name, t, verbose, null_byte, size);
  276.             Fclose(fd);
  277.         }
  278.         else
  279.             antw = fd;
  280.     }
  281.     else
  282.         antw = -1;
  283.     
  284.     return antw;
  285. }
  286.  
  287.  
  288. /*
  289.  * Ermittelt die anzahl der Bytes und Zeilen der übergebenen Datei.
  290.  * Wird bei der Projektverwaltung (Info) benutzt.
  291.  */
  292. int infoload(char *name, long *bytes, long *lines)
  293. {
  294.     RING    t;
  295.     int    antw = 1;
  296.  
  297.     if (file_exists(name))
  298.     {
  299.         init_textring(&t);
  300.         if (load_datei(name, &t, FALSE, NULL) == 0)
  301.         {
  302.             *bytes = textring_bytes(&t);
  303.             *lines = t.lines;
  304.             antw = 0;
  305.         }
  306.         kill_textring(&t);
  307.     }
  308.     else
  309.     {
  310.         char    s[28];
  311.         
  312.         *bytes = 0;
  313.         *lines = 0;
  314.         make_shortpath(name, s, 28);
  315.         snote(1, 0, READERR, s);
  316.     }
  317.     return antw;
  318. }
  319.  
  320.  
  321. /****************************************************************************/
  322.  
  323. long    void backup_name(char *name, char *ext)
  324. {
  325.     PATH        new;
  326.     FILENAME    new_name;
  327.     
  328.     strcpy(new, name);
  329.     strcat(new, ".");
  330.     strcat(new, ext);
  331.     file_name(new, new_name, FALSE);
  332.     if (fs_long_name(new) >= strlen(new_name))
  333.         strcpy(name, new);
  334.     else
  335.         set_extension(name, ext);
  336. }
  337.  
  338. static void restore_back_up(TEXTP t_ptr)
  339. {
  340.     if (t_ptr->loc_opt->backup)
  341.     {
  342.         PATH old;
  343.  
  344.         if (file_exists(t_ptr->filename))
  345.             Fdelete(t_ptr->filename);
  346.         strcpy(old, t_ptr->filename);
  347.         backup_name(old, t_ptr->loc_opt->backup_ext);
  348.         Frename(0, old, t_ptr->filename);
  349.     }
  350. }
  351.  
  352.  
  353. static void back_up(TEXTP t_ptr)
  354. {
  355.     PATH new;
  356.  
  357.     if (t_ptr->loc_opt->backup)
  358.     {
  359.         graf_mouse(HOURGLASS, NULL);
  360.         strcpy(new, t_ptr->filename);
  361.         backup_name(new, t_ptr->loc_opt->backup_ext);
  362.         if (file_exists(new))            /* Alte DUP-Datei löschen */
  363.             Fdelete(new);
  364.         Frename(0, t_ptr->filename, new);
  365.         graf_mouse(ARROW, NULL);
  366.     }
  367. }
  368.  
  369. int save_to_fd(int fd, char *name, RINGP t, bool verbose)
  370. {
  371.     char        end_str[3], *zeile, *buffer, *ptr;
  372.     int        e_len, z_len, antw;
  373.     long        ret, count, b, rest, text_size;
  374.     ZEILEP    lauf;
  375.  
  376.     /* Puffer anfordern */
  377.     buffer = (char *)malloc(BUFFERSIZE);
  378.     zeile = (char *)malloc(MAX_LINE_LEN + 2);
  379.  
  380.     if (buffer == NULL || zeile == NULL)
  381.     {
  382.         note(1, 0, NOMEMORY);
  383.         return -39;
  384.     }                
  385.  
  386.     graf_mouse(HOURGLASS, NULL);
  387.  
  388.     /* Progress-Bar */
  389.     text_size = textring_bytes(t);
  390.     verbose = verbose && ((text_size >> 10) >= transfer_size);
  391.     if (verbose)
  392.     {
  393.         char    str[40];
  394.         FILENAME    file;
  395.  
  396.         strcpy(str, rsc_string(SAVESTR));
  397.         file_name(name, file, FALSE);
  398.         strcat(str,file);
  399.         start_aktion(str, FALSE, text_size);
  400.         count = 0L;
  401.     }
  402.  
  403.     /* String mit Zeilenende erzeugen */
  404.     switch (t->ending)
  405.     {
  406.         case tos :
  407.             strcpy(end_str, "\r\n");
  408.             e_len = 2;
  409.             break;
  410.         case unix :
  411.             strcpy(end_str, "\n");
  412.             e_len = 1;
  413.             break;
  414.         case apple :
  415.             strcpy(end_str, "\r");
  416.             e_len = 1;
  417.             break;
  418.         default:
  419.             strcpy(end_str, "");
  420.             e_len = 0;
  421.             break;
  422.     }
  423.     
  424.     lauf = FIRST(t);
  425.     if (lauf != NULL)
  426.     {
  427.         b = 0L;
  428.         ret = 1;
  429.         ptr = buffer;
  430.         rest = BUFFERSIZE;
  431.         while ((!IS_TAIL(lauf)) && (ret > 0))
  432.         {
  433.             /* Zeile aus Text und Zeilenende zusammen setzen */
  434.             memcpy(zeile, TEXT(lauf), lauf->len);
  435.             z_len = lauf->len;
  436.  
  437.             /*
  438.              * Das Zeilenende wird nur dann angehängt, wenn lauf nicht letzte
  439.              * Zeile ist. Gab es beim Laden der Datei in der letzten Zeile
  440.              * ein ZE, gibt es die Dummyzeile. Gab es das ZE nicht, wird auch
  441.              * kein ZE angehängt!
  442.              */
  443.             if (!IS_LAST(lauf) && (e_len > 0) && !IS_OVERLEN(lauf))
  444.             {
  445.                 memcpy(zeile + lauf->len, end_str, e_len);
  446.                 z_len += e_len;
  447.             }
  448.             
  449.             /* Passt die Zeile noch in den Puffer? */
  450.             if (z_len < rest)
  451.             {
  452.                 /* komplett in den Puffer */
  453.                 memcpy(ptr, zeile, z_len);
  454.                 ptr += z_len;
  455.                 b += z_len;
  456.                 rest -= z_len;
  457.             }
  458.             else
  459.             {
  460.                 /* nur soviel kopieren, wie noch passt */
  461.                 memcpy(ptr, zeile, rest);
  462.                 ptr += rest;
  463.                 
  464.                 /* wegschreiben */
  465.                 ret = Fwrite(fd, BUFFERSIZE, buffer);
  466.                 if (verbose)
  467.                 {
  468.                     count += BUFFERSIZE;
  469.                     do_aktion("", count);
  470.                 }
  471.  
  472.                 if (ret != BUFFERSIZE)
  473.                     ret = -ENOSPC;
  474.  
  475.                 /* und den Rest in den Puffer */
  476.                 b = z_len - rest;
  477.                 ptr = buffer;
  478.                 memcpy(ptr, zeile + rest, b);
  479.                 ptr += b;
  480.                 
  481.                 rest = BUFFERSIZE - b;
  482.             }
  483.             NEXT(lauf);
  484.         }
  485.  
  486.         /* Befindet sich noch etwas im Puffer und ist kein Fehler aufgetreten? */
  487.         if ((b > 0L) && (ret > 0))
  488.         {
  489.             ret = Fwrite(fd, b, buffer);
  490.             if (verbose)
  491.             {
  492.                 count += b;
  493.                 do_aktion("", count);
  494.             }
  495.             if (ret != b)
  496.                 ret = -ENOSPC;
  497.         }
  498.         if (ret < 0)
  499.             antw = (int)ret;
  500.         else
  501.             antw = 0;
  502.     }
  503.     else
  504.         antw = 1;
  505.  
  506.     free(buffer);
  507.     free(zeile);
  508.  
  509.     if (verbose)
  510.         end_aktion();
  511.  
  512.     graf_mouse(ARROW, NULL);
  513.  
  514.     return antw;
  515. }
  516.  
  517. int save_datei(char *name, RINGP t, bool verbose)
  518. {
  519.     int    fd, antw;
  520.  
  521.     fd = (int) Fcreate(name, 0);
  522.     if (fd > 0)
  523.     {
  524.         antw = save_to_fd(fd, name, t, verbose);
  525.         Fclose(fd);
  526.         if (antw == -ENOSPC)
  527.             Fdelete(name);
  528.     }
  529.     else
  530.         antw = fd;
  531.  
  532.     return antw;
  533. }
  534.  
  535.  
  536. int save(TEXTP t_ptr)
  537. {
  538.     int            antw;
  539.     struct stat    st;
  540.     bool            not_exists;
  541.  
  542.     if (file_exists(t_ptr->filename))
  543.     {
  544.         if (file_readonly(t_ptr->filename))
  545.         {
  546.             FILENAME    file;
  547.  
  548.             t_ptr->readonly = TRUE;
  549.             file_name(t_ptr->filename, file, FALSE);
  550.             snote(1, 0, READONLY, file);
  551.             return -39;
  552.         }
  553.         else
  554.             t_ptr->readonly = FALSE;
  555.         if (t_ptr->file_date_time != -1L)
  556.         {
  557.             long date_time = file_time(t_ptr->filename, NULL, NULL);
  558.  
  559.             if (date_time != t_ptr->file_date_time)
  560.             {
  561.                 FILENAME    name;
  562.  
  563.                 file_name(t_ptr->filename, name, FALSE);
  564.                 if (snote(1, 2, MOVED2, name) == 2)
  565.                     return -1;
  566.             }
  567.         }
  568.     }
  569.     
  570.     not_exists = (stat(t_ptr->filename, &st) != 0);
  571.     
  572.     back_up(t_ptr);
  573.     antw = save_datei(t_ptr->filename, &t_ptr->text, TRUE);
  574.     if (antw == 0)
  575.     {
  576.         t_ptr->moved = 0;
  577.         t_ptr->file_date_time = file_time(t_ptr->filename, NULL, NULL);
  578.         t_ptr->asave = time(NULL);
  579.  
  580.         /* OLGA informieren */
  581.         do_olga(OLGA_UPDATE, t_ptr->filename, NULL);
  582.  
  583.         /* Attribute wieder herstellen */
  584.         if (!not_exists)
  585.         {
  586.             chmod(t_ptr->filename, (st.st_mode & 0x0000FFFF));
  587.             if (getuid() == 0)                        /* nur root darf Owner ändern */
  588.                 chown(t_ptr->filename, st.st_uid, st.st_gid);
  589.         }
  590.     }
  591.     else
  592.     {
  593.         if (antw == -ENOSPC)
  594.         {
  595.             char    tmp[20];
  596.  
  597.             make_shortpath(t_ptr->filename, tmp, 19);
  598.             snote(1, 0, NOSPACE, tmp);
  599.         }
  600.         else
  601.             note(1, 0, WRITEERR);
  602. /*        restore_back_up(t_ptr); */
  603.         t_ptr->file_date_time = -1L;
  604.     }
  605.  
  606.     return antw;
  607. }
  608.  
  609.  
  610. int save_as(TEXTP t_ptr, char *name)
  611. {
  612.     int    antw;
  613.  
  614.     if (file_exists(name))
  615.     {
  616.         if (file_readonly(name))
  617.         {
  618.             FILENAME    file;
  619.  
  620.             file_name(t_ptr->filename, file, FALSE);
  621.             snote(1, 0, READONLY, file);
  622.             return -39;
  623.         }
  624.     }
  625.     antw = save_datei(name, &t_ptr->text, TRUE);
  626.     if (antw != 0)
  627.     {
  628.         if (antw == -ENOSPC)
  629.         {
  630.             char    tmp[20];
  631.  
  632.             make_shortpath(t_ptr->filename, tmp, 19);
  633.             snote(1, 0, NOSPACE, tmp);
  634.         }
  635.         else
  636.             note(1, 0, WRITEERR);
  637. /*        restore_back_up(t_ptr);*/
  638.     }
  639.     return(antw);
  640. }
  641.  
  642.  
  643. bool    save_new(char *name, char *mask, char *title)
  644. {
  645.     PATH    new;
  646.     bool    ok = FALSE;
  647.     
  648.     if ((name[0] == EOS) || (strcmp(name, rsc_string(NAMENLOS)) == 0))
  649.         strcpy(new, last_path);
  650.     else
  651.         strcpy(new, name);
  652.     if (select_single(new, mask, title))
  653.     {
  654.         if (strcmp(name, new) != 0)        /* wirklich neuer Name? */
  655.         {
  656.             if (file_exists(new) && (note(1, 2, EXIST) == 2))
  657.                 ok = FALSE;
  658.             else
  659.             {
  660.                 strcpy(name, new);
  661.                 ok = TRUE;
  662.             }
  663.         }
  664.         else
  665.             ok = FALSE;
  666.     }
  667.     return ok;
  668. }
  669.  
  670.  
  671. /*****************************************************************************/
  672. /* Dateiauswahl                                                                                  */
  673. /*****************************************************************************/
  674. static bool    multi_bin = FALSE;
  675.  
  676. void store_path(char *path)
  677. {
  678.     PATH    p;
  679.  
  680.     split_filename(path, p, NULL);
  681.     if (strcmp(last_path, p) != 0)        /* neuer Pfad? */
  682.     {
  683.         if (path_exists(p))
  684.             strcpy(last_path, p);
  685.     }
  686. }
  687.  
  688. bool select_single(char *filename, char *mask, char *title)
  689. {
  690.     PATH        path = "";
  691.     FILENAME    name = "";
  692.     bool        ok;
  693.     
  694.     if (filename[0] != EOS)
  695.         split_filename(filename, path, name);
  696.     else
  697.         strcpy(path, last_path);
  698.  
  699.     ok = select_file(path, name, mask, title, FSCB_NULL);
  700.     if (ok && name[0] != EOS)            /* für den Fall, da₧ nur ein Verzeichnis kommt */
  701.     {
  702.         strcpy(filename, path);
  703.         strcat(filename, name);
  704.         store_path(path);
  705.     }
  706.     return ok;
  707. }
  708.  
  709.  
  710. bool select_path(char *pathname, char *title)
  711. {
  712.     PATH        path = "";
  713.     FILENAME    name = "";
  714.     bool        ok;
  715.     
  716.     if (pathname[0] != EOS)
  717.         split_filename(pathname, path, NULL);
  718.     else
  719.         strcpy(path, last_path);
  720.  
  721.     ok = select_file(path, name, "", title, FSCB_NULL);
  722.     if (ok)                            /* für den Fall, da₧ nur ein Verzeichnis kommt */
  723.     {
  724.         strcpy(pathname, path);
  725.         store_path(path);
  726.     }
  727.     return ok;
  728. }
  729.  
  730. static int open_multi(char *path, char *name)
  731. {
  732.     if (name[0] != EOS)            /* für den Fall, da₧ nur ein Verzeichnis kommt */
  733.     {
  734.         PATH    filename;
  735.         int    r;
  736.         
  737.         strcpy(filename, path);
  738.         strcat(filename, name);
  739.         if (!shift_pressed() && filematch(filename, "*.QPJ", -1))
  740.             r = load_projekt(filename);
  741.         else
  742.             r = load_edit(filename, multi_bin);
  743.         if (r > 0)
  744.             send_dhst(filename);
  745.     }
  746.     return TRUE;
  747. }
  748.  
  749. void select_multi(bool binary)
  750. {
  751.     PATH        path;
  752.     FILENAME    name = "";
  753.     char        *title;
  754.  
  755.     multi_bin = binary;
  756.     strcpy(path, last_path);
  757.  
  758.     if (binary)
  759.         title = rsc_string(LOADBINSTR);
  760.     else
  761.         title = rsc_string(LOADFILESTR);
  762.     select_file(path, name, "", title, open_multi);
  763. }
  764.  
  765. /******************************************************************************/
  766. void init_file(void)
  767. {
  768.     get_path(last_path, 0);                            /* Aktuellen Pfad holen */
  769. }
  770.  
  771. void term_file(void)
  772. {
  773. }
  774.