home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / sun / volume1 / touchup2.5 / part05 / disk_io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-07-12  |  17.2 KB  |  675 lines

  1.  
  2. /**************************************************************************
  3.    Touchup a bitmap graphics editor for the Sun Workstation running SunView
  4.    Copyright (c) 1988 by Raymond Kreisel
  5.    1/22/88 @ Suny Stony Brook
  6.  
  7.    This program may be redistributed without fee as long as this copyright
  8.    notice is intact.
  9.  
  10. ==> PLEASE send comments and bug reports to one of the following addresses:
  11.  
  12.        Ray Kreisel
  13.        CS Dept., SUNY at Stony Brook, Stony Brook NY 11794
  14.  
  15.        UUCP: {allegra, philabs, pyramid, research}!sbcs!rayk   
  16.        ARPA-Internet: rayk@sbcs.sunysb.edu            
  17.        CSnet: rayk@suny-sb
  18.        (If nobody is home at any of the above addresses try:
  19.         S72QKRE@TOWSONVX.BITNET                    )
  20.  
  21.  "If I get home before daylight, I just might get some sleep tonight...."
  22.  
  23. **************************************************************************/
  24. /**************************************************************************
  25.     file: disk_io.c
  26.     purpose: This file handle most of the file I/O stuff
  27.       mostly load, save and file completion
  28.  
  29.     modifications:
  30.         date:    Tue Mar 22 22:04:58 EST 1988
  31.         author:    rayk
  32.         changes:add comments
  33.  
  34.         date:    Thu Apr 21 20:14:58 EDT 1988
  35.         author:    rayk
  36.         changes:when you hit return in filename the caret moves
  37.             to textstring
  38.  
  39.         date:    Thu Apr 21 20:14:58 EDT 1988
  40.         author:    rayk
  41.         changes:when you do a load cut/paste buffer it will
  42.             automagicly bring up the cut/paste command menu
  43.  
  44.         date:    Wed Jun 1 1:22:18 EDT 1988
  45.         author:    rayk
  46.         changes:fixed bug in resize color canvases
  47.  
  48.         date:    Wed Jun 15 14:40:48 EDT 1988
  49.         author:    rayk
  50.         changes:added a check in file save to check is the
  51.             current filename is a directory
  52. **************************************************************************/
  53.  
  54. #include "header.h"
  55.  
  56. #include <sys/types.h>
  57. #include <sys/dir.h>
  58. #include <sys/file.h>
  59. #include <pwd.h>
  60. #include <sys/stat.h>
  61.  
  62. colormap_t colormap;
  63. extern  int   errno;
  64.  
  65. /*
  66.  * Let's do file completion on what we have in the file name prompt
  67.  */
  68. make_new_name(item, event)
  69. Panel_item      item;
  70. Event           *event;
  71. {
  72.         strcpy(file_name,(char*)panel_get_value(file_panel));
  73.         if (complete(file_name))
  74.             window_bell(panel);
  75.         panel_set(file_panel,PANEL_VALUE,file_name,0);
  76. }
  77.  
  78.  
  79. /* This function, written by Marc J Newberger,
  80.  * will do both login name completion and file name completion, DAM fast.
  81.  * That means as fast as the csh does it.
  82.  */
  83. int complete(template)
  84.  
  85.     char    *template;
  86.  
  87. {
  88.  
  89.     char    dirName[255];
  90.     char   *prefix;    
  91.     int     pref_len;
  92.     char   *suffix;     
  93.     char   *p, *q;
  94.     char    first;
  95.     char    nonUnique;
  96.     char    twiddleUserCompletion;
  97.  
  98.     struct  direct     *nameEntry;
  99.     DIR                *dirChan;
  100.     struct  passwd     *pwdEntry;
  101.  
  102.     /*
  103.      *  First do a little parsing of the input. Separate the
  104.      *  prefix template from the directory if there is one.
  105.      */
  106.     twiddleUserCompletion= 0;
  107.     prefix= template+strlen(template);
  108.     while (*(--prefix) != '/' && prefix >= template);
  109.  
  110.     /*
  111.      *  See if a directory was specified:
  112.      */
  113.     if (prefix < template) {
  114.         /*
  115.          *  No /'s, could be either a username completion or
  116.          *  a completion in the current directory.
  117.          */
  118.         if (template[0] == '~') {
  119.             prefix++;
  120.             twiddleUserCompletion= 1;
  121.             }
  122.         else {
  123.             strcpy(dirName, ".");
  124.             }
  125.         }
  126.     else if (prefix == template) {
  127.         /*
  128.          *  Special case !! The directory excluding the trailing
  129.          *  '/' is zero length. It's the root:
  130.          */
  131.         strcpy(dirName, "/");
  132.         }
  133.     else {
  134.         /*
  135.          *  We're completing a file in a directory.
  136.          *  The directory may be lead by a ~<username> abbreviation.
  137.          *  If that's the case expand it.
  138.          */
  139.         if (template[0] == '~') {
  140.             /*
  141.              *  We need to do twiddle directory expansion.
  142.              *  See if it's our directory:
  143.              */
  144.             if (template[1] == '/') {
  145.                 strcpy(dirName, getenv("HOME"));
  146.         if ( &template[1] != prefix )
  147.           {
  148.                     p= dirName+strlen(dirName);
  149.                 q= &template[1];
  150.                     while (q < prefix) {
  151.                         *p= *q;
  152.                         p++, q++;
  153.                         }
  154.                     *p= 0;
  155.           }
  156.                 }
  157.             else {
  158.                 /*
  159.                  * It's someone else's. Let our fingers
  160.                  * do the walking. (Why the fuck do they call it
  161.                  * the "yellow pages" anyway. They're white pages
  162.                  * dammit !  If they were YELLOW pages, we could
  163.                  * say ypmatch "Automobile, Dealers, Retail", and
  164.                  * things like that !).
  165.                  */
  166.                 for (p= dirName, q= &template[1];
  167.                         (*p= *q) != '/';
  168.                             p++, q++);
  169.                 *p= 0;
  170.                 if (!(pwdEntry= getpwnam(dirName))) {
  171.                     return errno;
  172.                     }
  173.                 strcpy(dirName, pwdEntry->pw_dir);
  174.                 p= dirName+strlen(dirName);
  175.                 while (q < prefix) {
  176.                     *p= *q;
  177.                     p++, q++;
  178.                     }
  179.                 *p= 0;
  180.                 }
  181.             }
  182.         else {
  183.             /*
  184.              *  It's a vanilla directory. Strip it out.
  185.              */
  186.             strncpy(dirName, template, prefix-template);
  187.             dirName[prefix-template]= 0;
  188.             }
  189.         }
  190.     /*
  191.      *  Bump prefix past the '/'.
  192.      */
  193.     prefix++;
  194.  
  195.     /*
  196.      *  Get the prefix length and a pointer to the end of the
  197.      *  prefix.
  198.      */
  199.     pref_len= strlen(prefix);
  200.     suffix= template + strlen(template);
  201.  
  202.     /*
  203.      *  See whether we're doing filename or username completion:
  204.      */
  205.     if (!twiddleUserCompletion) {
  206.  
  207.         /*
  208.          *  It's filename completion. Read through the directory:
  209.          */
  210.         if ((dirChan= opendir(dirName)) == 0) {
  211.             return errno;
  212.             }
  213.  
  214.         first= 1;
  215.         nonUnique= 0;
  216.         for (;;) {
  217.             if (!(nameEntry= readdir(dirChan))) {
  218.                 break;
  219.                 }
  220.             if (!strncmp(prefix, nameEntry->d_name, pref_len)) {
  221.                 /*
  222.                  *  We have a file that matches the template.
  223.                  *  If it's the first one, we fill the completion
  224.                  *  suffix with it. Otherwise we scan and pare down
  225.                  *  the suffix.
  226.                  */
  227.                 if (first) {
  228.                     first=  0 ;
  229.                     strcpy(suffix, nameEntry->d_name+pref_len);
  230.                     }
  231.                 else {
  232.                     nonUnique= 1;
  233.                     p= suffix;
  234.                     q= nameEntry->d_name+pref_len;
  235.                     while (*p == *q) {
  236.                         ++p; ++q;
  237.                         }
  238.                     *p= 0;
  239.  
  240.                     /*
  241.                      *  A little optimization: If p == suffix, we
  242.                      *  were unable to do any extension of the name.
  243.                      *  We might as well quit here.
  244.                      */
  245.                     if (p == suffix) {
  246.                         break;
  247.                         }
  248.                     }
  249.                 }
  250.             }
  251.  
  252.         closedir(dirChan);
  253.         }
  254.     else {
  255.         /*
  256.          *  Do ~Username completion. Start by resetting the passwd file.
  257.          */
  258.         setpwent();
  259.  
  260.         first= 1;
  261.         nonUnique= 0;
  262.         for (;;) {
  263.             if (!(pwdEntry= getpwent())) {
  264.                 break;
  265.                 }
  266.             if (!strncmp(prefix, pwdEntry->pw_name, pref_len)) {
  267.                 /*
  268.                  *  We have a user that matches the template.
  269.                  *  If it's the first one, we fill the completion
  270.                  *  suffix with it. Otherwise we scan and pare down
  271.                  *  the suffix.
  272.                  */
  273.                 if (first) {
  274.                     first=  0 ;
  275.                     strcpy(suffix, pwdEntry->pw_name+pref_len);
  276.                     }
  277.                 else {
  278.                     p= suffix;
  279.                     q= pwdEntry->pw_name+pref_len;
  280.                     while (*p == *q) {
  281.                         ++p; ++q;
  282.                         }
  283.  
  284.                     /*
  285.                      *  Here there is a possibility of seeing the
  286.                      *  same username twice. For this reason, we
  287.                      *  only set nonUnique to 1 if we're shortening
  288.                      *  the suffix. This means that the new name is
  289.                      *  distinct from any name we've seen.
  290.                      */
  291.                     if (*p) {
  292.                         nonUnique= 1;
  293.                         *p= 0;
  294.                         }
  295.  
  296.                     /*
  297.                      *  A little optimization: If p == suffix, we
  298.                      *  were unable to do any extension of the name.
  299.                      *  We might as well quit here.
  300.                      */
  301.                     if (p == suffix) {
  302.                         break;
  303.                         }
  304.                     }
  305.                 }
  306.             }
  307.         }
  308.  
  309.     /*
  310.      *  If nothing matched, return a -1, if there was non-uniqueness
  311.      *  return -2.
  312.      */ 
  313.     if (first) {
  314.         return -1;
  315.         }
  316.     else if (nonUnique) {
  317.         return -2;
  318.         }
  319.     else {
  320.         return 0;
  321.         }
  322.  
  323. }
  324.  
  325.  
  326. /*
  327.  * We just got a "load" button event and we want to load in the current
  328.  * filename.
  329.  */
  330. load_file()
  331. {
  332. FILE *fp,*fopen();
  333. int err=0;
  334. struct rasterfile file_header;
  335. int load_area;
  336. char temp_file[MAX_FILE_NAME];
  337. struct pixrect *temp_pr;
  338.  
  339.   /*
  340.    * Copy the current filename and expand the ~ if it is there
  341.    */
  342.   strcpy(temp_file,(char*)panel_get_value(file_panel));
  343.   get_full_path(temp_file,file_name);
  344.   load_area = (int)panel_get_value(load_cycle);
  345.   
  346.   fp = fopen(file_name,"r");
  347.   if (fp == NULL)
  348.     {
  349.          ERRORstr("Cannot open file: ",file_name);
  350.      fclose(fp);
  351.      return;
  352.     }
  353.  
  354.   /*
  355.    * Try to read the header of the raster file and check if it is color
  356.    */
  357.   err = pr_load_header(fp,&file_header);
  358.   if (file_header.ras_maplength > 3*256) err=1;
  359.   if (err)
  360.     {
  361.      ERROR("Cannot load the rasterfile header.");
  362.      fclose(fp);
  363.      return;
  364.     }
  365.  
  366.   if (load_area == LOAD_ALL)  
  367.     {
  368.      clear_screen();
  369.      colormap.map[0] = red;
  370.      colormap.map[1] = green;
  371.      colormap.map[2] = blue;
  372.      colormap.type = file_header.ras_maptype;
  373.      colormap.length = file_header.ras_maplength/3;
  374.      /*
  375.       * load in the colormap for the raster file
  376.       */
  377.      if (pr_load_colormap(fp,&file_header,&colormap))
  378.     {
  379.      ERROR("Cannot load the rasterfile colormap.");    
  380.      fclose(fp);
  381.      return;
  382.     }
  383.     }
  384.     else
  385.     {
  386.      /*
  387.       * skip the colormap for the raster file
  388.       */
  389.      if (pr_load_colormap(fp,&file_header,NULL))
  390.     {
  391.      ERROR("Cannot load the rasterfile colormap.");    
  392.      fclose(fp);
  393.      return;
  394.     }
  395.     }
  396.  
  397.   /*
  398.    * reset the memory pixrect and load the baby in
  399.    */
  400.   MY_pr_destroy(undo_pr);
  401.   undo_pr = (struct pixrect *)pr_load_image(fp,&file_header,&colormap);
  402.  
  403.   if (undo_pr == NULL)
  404.     {
  405.          ERROR("Cannot allocate pixrect for loaded image file, not enough memory!");
  406.      fclose(fp);
  407.      return;
  408.     }
  409.  
  410.   fclose(fp);
  411.  
  412.   /*
  413.    * convert 1 bit deep bitmaps to 8 bits deeps if we are on a color machine
  414.    */
  415.   if ((image_depth >1) && (undo_pr->pr_depth == 1))
  416.     {
  417.     temp_pr = my_mem_create(file_header.ras_width,file_header.ras_height,
  418.             image_depth);
  419.     pr_rop(temp_pr,0,0,file_header.ras_width,file_header.ras_height,
  420.             PIX_SRC,undo_pr,0,0);
  421.     MY_pr_destroy(undo_pr);
  422.     undo_pr = temp_pr;
  423.     }
  424.  
  425.  
  426.  
  427.   /*
  428.    * We are loading to the main drawing area so lets set all
  429.    * the color maps
  430.    */
  431.   if (load_area == LOAD_ALL)  
  432.     {
  433.      if (image_depth > 1)
  434.        {
  435.     my_put_colormap();
  436.     set_color();
  437.         /*
  438.          * new fix for color retained canvases for version 2.3
  439.          */
  440.         (void)window_set(canvas,
  441.         CANVAS_WIDTH,        file_header.ras_width,
  442.         CANVAS_HEIGHT,        file_header.ras_height,
  443.         0);
  444.        }
  445.      else
  446.        {
  447.         set_mono();
  448.         (void)window_set(canvas,
  449.         CANVAS_WIDTH,        file_header.ras_width,
  450.         CANVAS_HEIGHT,        file_header.ras_height,
  451.         0);
  452.        }
  453.      panel_set(save_cycle,PANEL_VALUE, SAVE_ALL,0);
  454.      image_wid = file_header.ras_width;
  455.      image_hgt = file_header.ras_height;
  456.      pw_write(pw,0,0, image_wid,image_hgt, PIX_SRC, undo_pr,0,0);
  457.      sprintf(temp_file,"%d",image_hgt);
  458.      panel_set(height_text,PANEL_VALUE,temp_file,0);
  459.      sprintf(temp_file,"%d",image_wid);
  460.      panel_set(width_text,PANEL_VALUE,temp_file,0);
  461.     }
  462.   else
  463.     {
  464.     /*
  465.      * we load the image into the cut/paste buffer
  466.      */
  467.     MY_pr_destroy(cut_buffer_pr);
  468.     cut_buffer_pr = my_mem_create(file_header.ras_width,file_header.ras_height,image_depth);
  469.     pr_rop(cut_buffer_pr,0,0,file_header.ras_width,file_header.ras_height,
  470.             PIX_SRC,undo_pr,0,0);
  471.     MY_pr_destroy(undo_pr);
  472.     undo_pr = my_mem_create(image_wid,image_hgt,image_depth);
  473.     panel_set(region_choice,PANEL_VALUE,MOVE,0);
  474.     panel_set(command_choice,PANEL_VALUE,SEL_REG,0);
  475.     (void)window_set(brush_panel, WIN_SHOW,FALSE, 0);
  476.     (void)window_set(region_panel, WIN_SHOW,TRUE, 0);
  477.     print_msg("Object copied to Cut/Paste buffer. Hold down the RIGHT mouse button to drag the object.");
  478.     mouse_parms();
  479.     }
  480. }
  481.  
  482.  
  483.  
  484. /*
  485.  * Save a file out to the current filename
  486.  */
  487. save_file()
  488. {
  489. FILE *fp,*fopen();
  490. int type = RT_STANDARD;
  491. int copy_flag = TRUE;
  492. char temp_file[MAX_FILE_NAME];
  493.  
  494.  hide_msg();
  495.  /*
  496.   * Is the raster file to be run-length encode or not
  497.   */
  498.  if((int)panel_get_value(compress_cycle))
  499.     type = RT_BYTE_ENCODED;
  500.  else
  501.     type = RT_STANDARD;
  502.   
  503.   /*
  504.    * Copy the current filename and expand the ~ if it is there
  505.    */
  506.  strcpy(temp_file,(char*)panel_get_value(file_panel));
  507.  get_full_path(temp_file,file_name);
  508.  
  509.  if (file_is_dir(file_name))
  510.     {
  511.          ERROR("The current filename is a directory !");
  512.      return;
  513.     }
  514.  
  515.  if (file_exist(file_name))
  516.     {
  517.          if (!confirm("Overwrite existing file ?"))
  518.      return;
  519.     }
  520.  /*
  521.   * dump standard SUN raster file with color table to disk file
  522.   */
  523.  fp = fopen(file_name,"w");
  524.   if (fp == NULL)
  525.     {
  526.      fclose(fp);
  527.          ERRORstr("Cannot write to file: ",file_name);
  528.      return;
  529.     }
  530.  /*
  531.   * Save the whole drawing area out to the disk file
  532.   */
  533.  if (SAVE_ALL == (int)panel_get_value(save_cycle))
  534.    {
  535.      clean_point();
  536.      clean_region();
  537.      fat_done();
  538.      finish_text();
  539.      save_screen();
  540.  
  541.      colormap.map[0] = red;
  542.      colormap.map[1] = green;
  543.      colormap.map[2] = blue;
  544.      if (image_depth > 1)
  545.        {
  546.          colormap.type = RMT_EQUAL_RGB;
  547.          colormap.length = 256;
  548.        }
  549.      else
  550.        {
  551.          colormap.type = RMT_NONE;
  552.          colormap.length = 0;
  553.        }
  554.  
  555.      if (!undo_pr)
  556.         undo_pr = my_mem_create(image_wid,image_hgt,image_depth);
  557.      pr_rop(undo_pr,0,0,image_wid,image_hgt,PIX_SRC,pw->pw_prretained,0,0);
  558.      pr_dump(undo_pr,fp,&colormap,type,copy_flag);
  559.    }
  560.  else
  561.    {
  562.   /*
  563.    * just save the cut/Paste buffer out to the file
  564.    */
  565.      if (cut_buffer_pr == NULL)
  566.     {
  567.      ERROR("The Cut/Paste buffer is empty");
  568.      fclose(fp);
  569.      return;
  570.     }
  571.      colormap.map[0] = red;
  572.      colormap.map[1] = green;
  573.      colormap.map[2] = blue;
  574.      if (image_depth > 1)
  575.        {
  576.          colormap.type = RMT_EQUAL_RGB;
  577.          colormap.length = 256;
  578.        }
  579.      else
  580.        {
  581.          colormap.type = RMT_NONE;
  582.          colormap.length = 0;
  583.        }
  584.      pr_dump(cut_buffer_pr,fp,&colormap,type,copy_flag);
  585.    }
  586.  fclose(fp);
  587. }
  588.  
  589.  
  590. /*
  591.  * Check if a file exist or not
  592.  */
  593. file_exist(file_name)
  594. char *file_name;
  595. {
  596. FILE *fp;
  597.   fp = fopen(file_name,"r");
  598.   fclose(fp);
  599.   if (fp != NULL)
  600.     return(TRUE);
  601.   else
  602.     return(FALSE);
  603. }
  604.  
  605.  
  606. /*
  607.  * Check if the file is a directory
  608.  */
  609. file_is_dir(file_name)
  610. char *file_name;
  611. {
  612. struct stat buf;
  613.  
  614.   if (file_exist(file_name))
  615.   {
  616.     stat(file_name,&buf);
  617.     if (buf.st_mode & S_IFDIR)
  618.     return(TRUE);
  619.     else
  620.     return(FALSE);
  621.   }
  622.   else
  623.       return(FALSE);
  624. }
  625.  
  626.  
  627. /*
  628.  * Take a filename with a ~ character at the begining and return
  629.  * the full path name to that file
  630.  */
  631. get_full_path(template,full_path)
  632. char template[];
  633. char full_path[];
  634. {
  635.     char   *p, *q;
  636.     struct  passwd     *pwdEntry;
  637.         /*
  638.          *  We're completing a file in a directory.
  639.          *  The directory may be lead by a ~<username> abbreviation.
  640.          *  If that's the case expand it.
  641.          */
  642.         if (template[0] == '~') {
  643.             /*
  644.              *  We need to do twiddle directory expansion.
  645.              *  See if it's our directory:
  646.              */
  647.             if (template[1] == '/') {
  648.                 strcpy(full_path, getenv("HOME"));
  649.         strcat(full_path,&template[1]);
  650.                 }
  651.             else {
  652.                 /*
  653.                  * It's someone else's. Let our fingers
  654.                  * do the walking. (Why the fuck do they call it
  655.                  * the "yellow pages" anyway. They're white pages
  656.                  * dammit !  If they were YELLOW pages, we could
  657.                  * say ypmatch "Automobile, Dealers, Retail", and
  658.                  * things like that !).
  659.                  */
  660.                 for (p= full_path, q= &template[1];
  661.                         (*p= *q) != '/';
  662.                             p++, q++);
  663.                 *p= 0;
  664.                 if (!(pwdEntry= getpwnam(full_path))) {
  665.                     return errno;
  666.                     }
  667.                 strcpy(full_path, pwdEntry->pw_dir);
  668.         strcat(full_path,q);
  669.                 }
  670.     }
  671.     else
  672.           strcpy(full_path,template);
  673. }         
  674.  
  675.