home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume15 / touchup / part05 / disk_io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-06-14  |  14.5 KB  |  559 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.  
  35. #include "header.h"
  36.  
  37. #include <sys/types.h>
  38. #include <sys/dir.h>
  39. #include <sys/file.h>
  40. #include <pwd.h>
  41.  
  42. colormap_t colormap;
  43.  
  44. /*
  45.  * Let's do file completion on what we have in the file name prompt
  46.  */
  47. make_new_name(item, event)
  48. Panel_item      item;
  49. Event           *event;
  50. {
  51.   strcpy(file_name,(char*)panel_get_value(file_panel));
  52.   if (complete(file_name))
  53.       window_bell(panel);
  54.   panel_set(file_panel,PANEL_VALUE,file_name,0);
  55. }
  56.  
  57.  
  58. /* This function, written by Marc J Newberger,
  59.  * will do both login name completion and file name completion, DAM fast.
  60.  * That means as fast as the csh does it.
  61.  */
  62. int complete(template)
  63.  
  64.     char    *template;
  65.  
  66. {
  67.  
  68.     char    dirName[255];
  69.     char   *prefix;    
  70.     int     pref_len;
  71.     char   *suffix;     
  72.     char   *p, *q;
  73.     char    first;
  74.     char    nonUnique;
  75.     char    twiddleUserCompletion;
  76.  
  77.     extern  int         errno;
  78.     struct  direct     *nameEntry;
  79.     DIR                *dirChan;
  80.     struct  passwd     *pwdEntry;
  81.  
  82.     /*
  83.      *  First do a little parsing of the input. Separate the
  84.      *  prefix template from the directory if there is one.
  85.      */
  86.     twiddleUserCompletion= 0;
  87.     prefix= template+strlen(template);
  88.     while (*(--prefix) != '/' && prefix >= template);
  89.  
  90.     /*
  91.      *  See if a directory was specified:
  92.      */
  93.     if (prefix < template) {
  94.         /*
  95.          *  No /'s, could be either a username completion or
  96.          *  a completion in the current directory.
  97.          */
  98.         if (template[0] == '~') {
  99.             prefix++;
  100.             twiddleUserCompletion= 1;
  101.             }
  102.         else {
  103.             strcpy(dirName, ".");
  104.             }
  105.         }
  106.     else if (prefix == template) {
  107.         /*
  108.          *  Special case !! The directory excluding the trailing
  109.          *  '/' is zero length. It's the root:
  110.          */
  111.         strcpy(dirName, "/");
  112.         }
  113.     else {
  114.         /*
  115.          *  We're completing a file in a directory.
  116.          *  The directory may be lead by a ~<username> abbreviation.
  117.          *  If that's the case expand it.
  118.          */
  119.         if (template[0] == '~') {
  120.             /*
  121.              *  We need to do twiddle directory expansion.
  122.              *  See if it's our directory:
  123.              */
  124.             if (template[1] == '/') {
  125.                 strcpy(dirName, getenv("HOME"));
  126.         if ( &template[1] != prefix )
  127.           {
  128.                     p= dirName+strlen(dirName);
  129.                 q= &template[1];
  130.                     while (q < prefix) {
  131.                         *p= *q;
  132.                         p++, q++;
  133.                         }
  134.                     *p= 0;
  135.           }
  136.                 }
  137.             else {
  138.                 /*
  139.                  * It's someone else's. Let our fingers
  140.                  * do the walking. (Why the fuck do they call it
  141.                  * the "yellow pages" anyway. They're white pages
  142.                  * dammit !  If they were YELLOW pages, we could
  143.                  * say ypmatch "Automobile, Dealers, Retail", and
  144.                  * things like that !).
  145.                  */
  146.                 for (p= dirName, q= &template[1];
  147.                         (*p= *q) != '/';
  148.                             p++, q++);
  149.                 *p= 0;
  150.                 if (!(pwdEntry= getpwnam(dirName))) {
  151.                     return errno;
  152.                     }
  153.                 strcpy(dirName, pwdEntry->pw_dir);
  154.                 p= dirName+strlen(dirName);
  155.                 while (q < prefix) {
  156.                     *p= *q;
  157.                     p++, q++;
  158.                     }
  159.                 *p= 0;
  160.                 }
  161.             }
  162.         else {
  163.             /*
  164.              *  It's a vanilla directory. Strip it out.
  165.              */
  166.             strncpy(dirName, template, prefix-template);
  167.             dirName[prefix-template]= 0;
  168.             }
  169.         }
  170.     /*
  171.      *  Bump prefix past the '/'.
  172.      */
  173.     prefix++;
  174.  
  175.     /*
  176.      *  Get the prefix length and a pointer to the end of the
  177.      *  prefix.
  178.      */
  179.     pref_len= strlen(prefix);
  180.     suffix= template + strlen(template);
  181.  
  182.     /*
  183.      *  See whether we're doing filename or username completion:
  184.      */
  185.     if (!twiddleUserCompletion) {
  186.  
  187.         /*
  188.          *  It's filename completion. Read through the directory:
  189.          */
  190.         if ((dirChan= opendir(dirName)) == 0) {
  191.             return errno;
  192.             }
  193.  
  194.         first= 1;
  195.         nonUnique= 0;
  196.         for (;;) {
  197.             if (!(nameEntry= readdir(dirChan))) {
  198.                 break;
  199.                 }
  200.             if (!strncmp(prefix, nameEntry->d_name, pref_len)) {
  201.                 /*
  202.                  *  We have a file that matches the template.
  203.                  *  If it's the first one, we fill the completion
  204.                  *  suffix with it. Otherwise we scan and pare down
  205.                  *  the suffix.
  206.                  */
  207.                 if (first) {
  208.                     first=  0 ;
  209.                     strcpy(suffix, nameEntry->d_name+pref_len);
  210.                     }
  211.                 else {
  212.                     nonUnique= 1;
  213.                     p= suffix;
  214.                     q= nameEntry->d_name+pref_len;
  215.                     while (*p == *q) {
  216.                         ++p; ++q;
  217.                         }
  218.                     *p= 0;
  219.  
  220.                     /*
  221.                      *  A little optimization: If p == suffix, we
  222.                      *  were unable to do any extension of the name.
  223.                      *  We might as well quit here.
  224.                      */
  225.                     if (p == suffix) {
  226.                         break;
  227.                         }
  228.                     }
  229.                 }
  230.             }
  231.  
  232.         closedir(dirChan);
  233.         }
  234.     else {
  235.         /*
  236.          *  Do ~Username completion. Start by resetting the passwd file.
  237.          */
  238.         setpwent();
  239.  
  240.         first= 1;
  241.         nonUnique= 0;
  242.         for (;;) {
  243.             if (!(pwdEntry= getpwent())) {
  244.                 break;
  245.                 }
  246.             if (!strncmp(prefix, pwdEntry->pw_name, pref_len)) {
  247.                 /*
  248.                  *  We have a user that matches the template.
  249.                  *  If it's the first one, we fill the completion
  250.                  *  suffix with it. Otherwise we scan and pare down
  251.                  *  the suffix.
  252.                  */
  253.                 if (first) {
  254.                     first=  0 ;
  255.                     strcpy(suffix, pwdEntry->pw_name+pref_len);
  256.                     }
  257.                 else {
  258.                     p= suffix;
  259.                     q= pwdEntry->pw_name+pref_len;
  260.                     while (*p == *q) {
  261.                         ++p; ++q;
  262.                         }
  263.  
  264.                     /*
  265.                      *  Here there is a possibility of seeing the
  266.                      *  same username twice. For this reason, we
  267.                      *  only set nonUnique to 1 if we're shortening
  268.                      *  the suffix. This means that the new name is
  269.                      *  distinct from any name we've seen.
  270.                      */
  271.                     if (*p) {
  272.                         nonUnique= 1;
  273.                         *p= 0;
  274.                         }
  275.  
  276.                     /*
  277.                      *  A little optimization: If p == suffix, we
  278.                      *  were unable to do any extension of the name.
  279.                      *  We might as well quit here.
  280.                      */
  281.                     if (p == suffix) {
  282.                         break;
  283.                         }
  284.                     }
  285.                 }
  286.             }
  287.         }
  288.  
  289.     /*
  290.      *  If nothing matched, return a -1, if there was non-uniqueness
  291.      *  return -2.
  292.      */ 
  293.     if (first) {
  294.         return -1;
  295.         }
  296.     else if (nonUnique) {
  297.         return -2;
  298.         }
  299.     else {
  300.         return 0;
  301.         }
  302.  
  303. }
  304.  
  305.  
  306. /*
  307.  * We just got a "load" button event and we want to load in the current
  308.  * filename.
  309.  */
  310. load_file(item, event)
  311. Panel_item      item;
  312. Event           *event;
  313. {
  314. FILE *fp,*fopen();
  315. int err=0;
  316. struct rasterfile file_header;
  317. int load_area;
  318. char temp_file[MAX_FILE_NAME];
  319.  
  320.   /*
  321.    * Copy the current filename and expand the ~ if it is there
  322.    */
  323.   strcpy(temp_file,(char*)panel_get_value(file_panel));
  324.   get_full_path(temp_file,file_name);
  325.   load_area = (int)panel_get_value(load_cycle);
  326.   
  327.   fp = fopen(file_name,"r");
  328.   if (fp == NULL)
  329.     {
  330.          ERRORstr("Cannot open file: ",file_name);
  331.      fclose(fp);
  332.      return(0);
  333.     }
  334.  
  335.   /*
  336.    * Try to read the header of the raster file and check if it is color
  337.    */
  338.   err = pr_load_header(fp,&file_header);
  339.   if (file_header.ras_maplength > 3*256) err=1;
  340.   if (err)
  341.     {
  342.      ERROR("Cannot load the rasterfile header.");
  343.      fclose(fp);
  344.      return(0);
  345.     }
  346.  
  347.   if (load_area == LOAD_ALL)  
  348.     {
  349.      clear_screen();
  350.      colormap.map[0] = red;
  351.      colormap.map[1] = green;
  352.      colormap.map[2] = blue;
  353.      colormap.type = file_header.ras_maptype;
  354.      colormap.length = file_header.ras_maplength/3;
  355.     }
  356.   /*
  357.    * load in the colormap for the raster file
  358.    */
  359.   if (pr_load_colormap(fp,&file_header,&colormap))
  360.     {
  361.      ERROR("Cannot load the rasterfile colormap.");    
  362.      fclose(fp);
  363.      return(0);
  364.     }
  365.   /*
  366.    * reset the memory pixrect and load the baby in
  367.    */
  368.   MY_pr_destroy(undo_pr);
  369.   undo_pr = (struct pixrect *)pr_load_image(fp,&file_header,&colormap);
  370.  
  371.   if (undo_pr == NULL)
  372.     {
  373.          ERROR("Cannot allocate pixrect for loaded image file, not enough memory!");
  374.      fclose(fp);
  375.      return(0);
  376.     }
  377.  
  378.   fclose(fp);
  379.  
  380.  
  381.   /*
  382.    * We are loading to the main drawing area so lets set all
  383.    * the color maps
  384.    */
  385.   if (load_area == LOAD_ALL)  
  386.     {
  387.      if (file_header.ras_depth > 1)
  388.        {
  389.     my_put_colormap();
  390.     set_color();
  391.        }
  392.      else
  393.        {
  394.         set_mono();
  395.         (void)window_set(canvas,
  396.         CANVAS_WIDTH,        file_header.ras_width,
  397.         CANVAS_HEIGHT,        file_header.ras_height,
  398.         0);
  399.        }
  400.      panel_set(save_cycle,PANEL_VALUE, SAVE_ALL,0);
  401.      image_wid = file_header.ras_width;
  402.      image_hgt = file_header.ras_height;
  403.      image_depth = file_header.ras_depth;
  404.      pw_write(pw,0,0, image_wid,image_hgt, PIX_SRC, undo_pr,0,0);
  405.     }
  406.   else
  407.     {
  408.     /*
  409.      * we load the image into the cut/paste buffer
  410.      */
  411.     MY_pr_destroy(cut_buffer_pr);
  412.     cut_buffer_pr = my_mem_create(file_header.ras_width,file_header.ras_height,file_header.ras_depth);
  413.     pr_rop(cut_buffer_pr,0,0,file_header.ras_width,file_header.ras_height,
  414.             PIX_SRC,undo_pr,0,0);
  415.     MY_pr_destroy(undo_pr);
  416.     undo_pr = my_mem_create(image_wid,image_hgt,image_depth);
  417.     }
  418. }
  419.  
  420.  
  421.  
  422. /*
  423.  * Save a file out out to the current filename
  424.  *
  425.  */
  426. save_file(item, event)
  427. Panel_item      item;
  428. Event           *event;
  429. {
  430. FILE *fp,*fopen();
  431. int type = RT_STANDARD;
  432. int copy_flag = TRUE;
  433. char temp_file[MAX_FILE_NAME];
  434.  
  435.  /*
  436.   * Is the raster file to be run-length encode or not
  437.   */
  438.  if((int)panel_get_value(compress_cycle))
  439.     type = RT_BYTE_ENCODED;
  440.  else
  441.     type = RT_STANDARD;
  442.   
  443.   /*
  444.    * Copy the current filename and expand the ~ if it is there
  445.    */
  446.  strcpy(temp_file,(char*)panel_get_value(file_panel));
  447.  get_full_path(temp_file,file_name);
  448.  if (file_exist(file_name))
  449.     {
  450.          if (!confirm("Over write existing file ?"))
  451.      return(0);
  452.     }
  453.  /*
  454.   * dump standard SUN raster file with color table to disk file
  455.   */
  456.  fp = fopen(file_name,"w");
  457.   if (fp == NULL)
  458.     {
  459.      fclose(fp);
  460.          ERRORstr("Cannot write to file: ",file_name);
  461.      return(0);
  462.     }
  463.  /*
  464.   * Save the whole drawing are out to the disk file
  465.   */
  466.  if (SAVE_ALL == (int)panel_get_value(save_cycle))
  467.    {
  468.      clean_point();
  469.      clean_region();
  470.      fat_done();
  471.      save_screen();
  472.  
  473.      if (!undo_pr)
  474.     undo_pr = my_mem_create(image_wid,image_hgt,image_depth);
  475.      pr_rop(undo_pr,0,0,image_wid,image_hgt,PIX_SRC,pw->pw_prretained,0,0);
  476.      pr_dump(undo_pr,fp,&colormap,type,copy_flag);
  477.    }
  478.  else
  479.    {
  480.   /*
  481.    * just save the cut/Paste buffer out to the file
  482.    */
  483.      if (cut_buffer_pr == NULL)
  484.     {
  485.      ERROR("The Cut/Paste buffer is empty");
  486.      fclose(fp);
  487.      return(0);
  488.     }
  489.      pr_dump(cut_buffer_pr,fp,&colormap,type,copy_flag);
  490.    }
  491.  fclose(fp);
  492. }
  493.  
  494.  
  495. /*
  496.  * Check if a file exist or not
  497.  */
  498. file_exist(file_name)
  499. char *file_name;
  500. {
  501. FILE *fp;
  502.   fp = fopen(file_name,"r");
  503.   fclose(fp);
  504.   if (fp != NULL)
  505.     return(TRUE);
  506.   else
  507.     return(FALSE);
  508. }
  509.  
  510.  
  511. /*
  512.  * Take a filename with a ~ character at the begining and return
  513.  * the full path name to that file
  514.  */
  515. get_full_path(template,full_path)
  516. char template[];
  517. char full_path[];
  518. {
  519.     char   *p, *q;
  520.     struct  passwd     *pwdEntry;
  521.         /*
  522.          *  We're completing a file in a directory.
  523.          *  The directory may be lead by a ~<username> abbreviation.
  524.          *  If that's the case expand it.
  525.          */
  526.         if (template[0] == '~') {
  527.             /*
  528.              *  We need to do twiddle directory expansion.
  529.              *  See if it's our directory:
  530.              */
  531.             if (template[1] == '/') {
  532.                 strcpy(full_path, getenv("HOME"));
  533.         strcat(full_path,&template[1]);
  534.                 }
  535.             else {
  536.                 /*
  537.                  * It's someone else's. Let our fingers
  538.                  * do the walking. (Why the fuck do they call it
  539.                  * the "yellow pages" anyway. They're white pages
  540.                  * dammit !  If they were YELLOW pages, we could
  541.                  * say ypmatch "Automobile, Dealers, Retail", and
  542.                  * things like that !).
  543.                  */
  544.                 for (p= full_path, q= &template[1];
  545.                         (*p= *q) != '/';
  546.                             p++, q++);
  547.                 *p= 0;
  548.                 if (!(pwdEntry= getpwnam(full_path))) {
  549.                     return errno;
  550.                     }
  551.                 strcpy(full_path, pwdEntry->pw_dir);
  552.         strcat(full_path,q);
  553.                 }
  554.     }
  555.     else
  556.           strcpy(full_path,template);
  557. }         
  558.  
  559.