home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_11_08 / weber / loadsave.c < prev    next >
Text File  |  1993-03-13  |  13KB  |  335 lines

  1. /***************************************************************
  2.  * file: LOADSAVE.C
  3.  * purpose: dialog box routine for getting a file name from the
  4.  *          user.  Has the expected listbox, editbox and file system
  5.  *          smarts.  Written for the simple gui system; GUI.C, MENU.C
  6.  *          and DIALOG.C
  7.  * system: Flash graphics library in Zortech 3.0
  8.  *          MSDOS dependencies in _dos_findfirst, _dos_findnext, path/file names
  9.  *          and wildcard usage.
  10.  * contains:
  11.  *      short loadsave(char *search,char *choice,unsigned short status);
  12.  *      short loadsave_add_button(BUTTON *button,short (*message_handler)(MESSAGE *));
  13.  *      short loadsave_button_location(BUTTON *button,short *loc_x,short *loc_y);
  14.  * copyright: 1992 by David Weber.  All rights reserved.
  15.  *  This software can be used for any purpose as object, library or executable.
  16.  *  It cannot be sold for profit as source code.
  17.  * history:
  18.  *  01-13-92 - initial code
  19.  *  01-31-93 - this code is now obsolete, see the CPP gui package
  20.  **************************************************************/
  21.  
  22. #define MSDOS 1
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <dos.h>
  28. #include <io.h>
  29. #include "gui.h"
  30. #include "loadsave.h"
  31.  
  32.  
  33. /* local data */
  34. static char edit_string[FILENAME_MAX+1];
  35. static char search_string[FILENAME_MAX+1];
  36. static BUTTON *extra_button[LOADSAVE_MAX_BUTTONS];
  37. static short (*extra_message[LOADSAVE_MAX_BUTTONS])(MESSAGE *);
  38. static short extra_button_count = 0;
  39.  
  40.  
  41. /* local prototypes */
  42. static short first_dir(char *filename);
  43. static short next_dir(char *filename);
  44. static void setup_wildcards(char *dest,char *source);
  45. static void merge_path_filename(char *path,char *filename);
  46. static short check_wildcard_or_directory(char *path);
  47.  
  48.  
  49. /* dialog box data */
  50.  
  51. /* dialog ids */
  52. #define D_LS_OK 23991
  53. #define D_LS_CANCEL 23992
  54. #define D_LS_LISTBOX 23993
  55. #define D_LS_EDITBOX 23994
  56.  
  57. /* dialog dimensions */
  58. #define D_LS_WIDTH (38*DIALOG_UNITS)
  59. #define D_LS_HEIGHT (15*DIALOG_UNITS)
  60.  
  61. /* listbox dimensions in text cells */
  62. #define LISTBOX_WIDTH 12    /* MSDOS filename width */
  63. #define LISTBOX_HEIGHT 8
  64.  
  65. /* editbox width in text cells */
  66. #define EDITBOX_SCREEN_WIDTH 33         /* displayed width */
  67. #define EDITBOX_EDIT_WIDTH FILENAME_MAX /* editable width */
  68.  
  69. /* dialog box #1 */
  70. static TEXT dialog_ls_text1 = {"",14*DIALOG_UNITS,13*DIALOG_UNITS+DIALOG_UNITS/2,DIALOG_ACTIVE};
  71. static EDITBOX dialog_ls_editbox = {D_LS_EDITBOX,2*DIALOG_UNITS,11*DIALOG_UNITS+DIALOG_UNITS/2,EDITBOX_SCREEN_WIDTH*DIALOG_UNITS,EDITBOX_EDIT_WIDTH,edit_string,DIALOG_ACTIVE};
  72. static LISTBOX dialog_ls_listbox = {D_LS_LISTBOX,2*DIALOG_UNITS,3*DIALOG_UNITS,LISTBOX_WIDTH*DIALOG_UNITS,LISTBOX_HEIGHT*DIALOG_UNITS,first_dir,next_dir,DIALOG_ACTIVE};
  73. static BUTTON dialog_ls_ok = {D_LS_OK,"Ok",F10,D_LS_WIDTH-5*DIALOG_UNITS,DIALOG_UNITS,DIALOG_ACTIVE};
  74. static BUTTON dialog_ls_cancel = {D_LS_CANCEL,"Cancel",ESC,3*DIALOG_UNITS,DIALOG_UNITS,DIALOG_ACTIVE};
  75. static DIALOG_ITEM dialog_ls[] =
  76.     {
  77.     {DIALOG_TEXT,&dialog_ls_text1},
  78.     {DIALOG_EDITBOX,&dialog_ls_editbox},
  79.     {DIALOG_LISTBOX,&dialog_ls_listbox},
  80.     {DIALOG_BUTTON,&dialog_ls_cancel},
  81.     {DIALOG_BUTTON,&dialog_ls_ok}
  82.     };
  83.  
  84.  
  85.  
  86. /************************************************
  87.  * function: short loadsave(char *search,char *choice,unsigned short status)
  88.  *      get a file name from the user with all the usual gui goodies.  loadsave
  89.  *      does not open/read or create/write the file, it justs gets a name
  90.  * parameters: search string for list box directory list.  If the search string
  91.  *             is a path and filename it should contain appropriate wild cards.
  92.  *             If it is a directory then loadsave will temporarily append the
  93.  *             wildcards.
  94.  *             choice string for holding the user's selection.
  95.  *             status is either LOADSAVE_LOAD if opening a file or
  96.  *             LOADSAVE_SAVE if saving one.  Also the bit flag LOADSAVE_VERIFY
  97.  *             will verify the files existence before opening it (LOAD) or
  98.  *             verify overwriting an existing file (SAVE).
  99.  * returns: 1 if there is a valid file name in choice, 0 if error or escaped
  100.  ************************************************/
  101. short loadsave(char *search,char *choice,unsigned short status)
  102.     {
  103.     MESSAGE message;
  104.     short i,button_count;
  105.  
  106.     setup_wildcards(search_string,search);  /* set up edit/list strings */
  107.     strcpy(edit_string,search_string);
  108.     if (status & LOADSAVE_LOAD)             /* load or save? */
  109.         dialog_ls_text1.name = "Open File";
  110.     else
  111.         dialog_ls_text1.name = "Save File";
  112.     if (!dialog_open(dialog_ls,sizeof(dialog_ls)/sizeof(DIALOG_ITEM),-1,-1,D_LS_WIDTH,D_LS_HEIGHT))
  113.         {
  114.         extra_button_count = 0;
  115.         return 0;
  116.         }
  117.     for (i = 0 ; i < extra_button_count ; i++)
  118.         if (!dialog_add_item(DIALOG_BUTTON,extra_button[i],dialog_ls))
  119.             {
  120.             extra_button_count = 0;
  121.             return 0;
  122.             }
  123.     button_count = extra_button_count;
  124.     extra_button_count = 0;
  125.     for (;;)        /* loop on messages */
  126.         {
  127.         message_get(&message);
  128.         for (i = 0 ; i < button_count ; i++)    /* check extra buttons */
  129.             if (message.id == extra_button[i]->id)
  130.                 if (!(*extra_message[i])(&message))
  131.                     {
  132.                     dialog_close(dialog_ls);
  133.                     return 0;
  134.                     }
  135.         switch (message.id)                     /* check standard buttons */
  136.             {
  137.             case D_LS_LISTBOX:                      /* put listbox selection into editbox */
  138.                 merge_path_filename(edit_string,message.data.ptr_data);
  139.                 editbox_initialize(&dialog_ls_editbox);
  140.                 break;
  141.             case D_LS_OK:                           /* user said accept it */
  142.             case D_LS_EDITBOX:
  143.                 if (message.id == D_LS_EDITBOX && message.data.short_data.x != EDITBOX_ACCEPT)
  144.                     break;
  145.                 if (check_wildcard_or_directory(edit_string))
  146.                     {                               /* new fodder for list box */
  147.                     strcpy(search,edit_string);
  148.                     setup_wildcards(search_string,search);
  149.                     strcpy(edit_string,search_string);
  150.                     editbox_initialize(&dialog_ls_editbox);
  151.                     listbox_initialize(&dialog_ls_listbox);
  152.                     break;
  153.                     }
  154.                 if (status & LOADSAVE_VERIFY)       /* verify? */
  155.                     {
  156.                     if (status & LOADSAVE_LOAD)
  157.                         {
  158.                         if (access(edit_string,F_OK) != 0)
  159.                             {
  160.                             message_box("File does not exist");
  161.                             break;
  162.                             }
  163.                         }
  164.                     else
  165.                         {
  166.                         if (access(edit_string,F_OK) == 0)
  167.                             {
  168.                             if (yn_box("File exists.  Overwrite it") == 0)
  169.                                 break;
  170.                             }
  171.                         }
  172.                     }
  173.                 dialog_close(dialog_ls);
  174.                 strcpy(choice,edit_string);
  175.                 return 1;
  176.             case D_LS_CANCEL:                       /* user said outta here */
  177.                 dialog_close(dialog_ls);
  178.                 return 0;
  179.             default:                                /* check if error */
  180.                 if (error_box(message.id))
  181.                     {
  182.                     dialog_close(dialog_ls);
  183.                     return 0;
  184.                     }
  185.                 break;
  186.             }
  187.         }
  188.     }
  189.  
  190.  
  191. /* get first filename from search_string, returns 1 if OK or 0 if no such critter */
  192. /* MSDOS dependent */
  193. static struct find_t find_file;
  194. static short first_dir(char *filename)
  195.     {
  196.     if (_dos_findfirst(search_string,FA_NORMAL,&find_file) != 0)
  197.         return 0;
  198.     strncpy(filename,find_file.name,LISTBOX_WIDTH);
  199.     filename[LISTBOX_WIDTH] = 0;
  200.     strlwr(filename);
  201.     return 1;
  202.     }
  203.  
  204.  
  205. /* get next filename, returns 1 if OK or 0 if no such critter */
  206. /* MSDOS dependent */
  207. static short next_dir(char *filename)
  208.     {
  209.     if (_dos_findnext(&find_file) != 0)
  210.         return 0;
  211.     strncpy(filename,find_file.name,LISTBOX_WIDTH);
  212.     filename[LISTBOX_WIDTH] = 0;
  213.     strlwr(filename);
  214.     return 1;
  215.     }
  216.  
  217.  
  218. /* set up wildcards appropriately, this is MSDOS dependent */
  219. static struct find_t temp_file;
  220. static void setup_wildcards(char *dest,char *source)
  221.     {
  222.     char *p;
  223.  
  224.     strcpy(dest,source);                            /* load source string */
  225.     strlwr(dest);                                   /* make it lowercase pretty */
  226.     p = dest + strlen(dest) - 1;
  227.     if (*p == ':')                                  /* drive only? */
  228.         strcat(dest,".\\*.*");
  229.     else if (*p == '\\')                            /* path only? */
  230.         strcat(dest,"*.*");
  231.     else if (*p == '.')                             /* current directory or filename.ext */
  232.         if (strchr(".:\\",*(p-1)) != NULL || p == dest)
  233.             strcat(dest,"\\*.*");
  234.     if (strpbrk(dest,"?*") == NULL)                 /* wildcards? */
  235.         {
  236.         if (_dos_findfirst(dest,FA_DIREC,&temp_file) == 0)  /* directory? */
  237.             if (temp_file.attrib & FA_DIREC)
  238.                 strcat(dest,"\\*.*");
  239.         }
  240.     }
  241.  
  242.  
  243. /* merge the filename into the path accounting for wildcards and other obscenities */
  244. /* MSDOS dependent */
  245. static void merge_path_filename(char *path,char *filename)
  246.     {
  247.     char *p;
  248.  
  249.     p = path + strlen(path) - 1;
  250.     if (*p == '\\')                 /* strip trailing backslash, if any */
  251.         *p = 0;
  252.     for ( ; p >= path ; p--)        /* find out where to cut off path */
  253.         if (*p == '\\' || *p == ':')
  254.             {                       /* directory break in path string */
  255.             p++;
  256.             strcpy(p,filename);
  257.             return;
  258.             }
  259.     strcpy(path,filename);          /* replace path with filename */
  260.     }
  261.  
  262.  
  263. /* see if path refers to a wildcard or a directory */
  264. static short check_wildcard_or_directory(char *path)
  265.     {
  266.     char *p;
  267.  
  268.     for (p = path+strlen(path)-1 ; p >= path ; p--) /* strip trailing blanks */
  269.         if (*p == ' ')
  270.             *p = 0;
  271.         else
  272.             break;
  273.     if (p <= path)                          /* blank path, use default directory */
  274.         return 1;
  275.     if (*p == ':' || (*p == '\\' && *(p-1) == ':')) /* just a drive? */
  276.         return 1;
  277.     if (*p == '\\')                         /* strip trailing backslash, if any */
  278.         *p = 0;
  279.     if (strpbrk(path,"?*") != NULL)         /* wildcards? */
  280.         return 1;
  281.     if (_dos_findfirst(path,FA_DIREC,&temp_file) == 0)
  282.         if (temp_file.attrib & FA_DIREC)    /* directory? */
  283.             return 1;
  284.     return 0;
  285.     }
  286.  
  287.  
  288. /************************************************
  289.  * function: short loadsave_add_button(BUTTON *button,short (*message_handler)(MESSAGE *))
  290.  *      adds a button to the next loadsave call.  If the button
  291.  *      is pressed the button id will be sent out as a message to the handler.
  292.  *      The handler should return 1 if OK or 0 if loadsave() is to be aborted
  293.  *      Note: this is a one shot function and should be called before
  294.  *      each invocation of loadsave()
  295.  * parameters: pointer to button to add and function pointer of message handler
  296.  * returns: 1 if button added or 0 if failed
  297.  ************************************************/
  298. short loadsave_add_button(BUTTON *button,short (*message_handler)(MESSAGE *))
  299.     {
  300.     if (extra_button_count >= LOADSAVE_MAX_BUTTONS)
  301.         return 0;
  302.     extra_button[extra_button_count] = button;
  303.     extra_message[extra_button_count] = message_handler;
  304.     button->loc_x = D_LS_WIDTH-(2+strlen(button->name))*DIALOG_UNITS;
  305.     button->loc_y = (9-(2*extra_button_count))*DIALOG_UNITS+DIALOG_UNITS/2;
  306.     extra_button_count++;
  307.     return 1;
  308.     }
  309.  
  310.  
  311. /************************************************
  312.  * function: short loadsave_button_location(BUTTON *button,short *loc_x,short *loc_y)
  313.  *      get screen location of an extra button
  314.  * parameters: pointer to added button, storage for x and y location in DIALOG_UNITS
  315.  *      from lower left screen corner.  loc_x and loc_y are suitable for passing
  316.  *      to dialog_open().
  317.  * returns:
  318.  *      1 if valid coordinates or 0 if failed
  319.  ************************************************/
  320. short loadsave_button_location(BUTTON *button,short *loc_x,short *loc_y)
  321.     {
  322.     short i;
  323.  
  324.     for (i = 0 ; i < LOADSAVE_MAX_BUTTONS ; i++)
  325.         if (extra_button[i] == button)
  326.             {
  327.             *loc_x = (fg.displaybox[FG_X2]-fg.displaybox[FG_X1])/2 - (D_LS_WIDTH*gui_char_width)/(2*DIALOG_UNITS);
  328.             *loc_x = (*loc_x/gui_char_width)*DIALOG_UNITS + button->loc_x;
  329.             *loc_y = (fg.displaybox[FG_Y2]-fg.displaybox[FG_Y1])/2 - (D_LS_HEIGHT*gui_char_height)/(2*DIALOG_UNITS);
  330.             *loc_y = (*loc_y/gui_char_height)*DIALOG_UNITS + button->loc_y;
  331.             return 1;
  332.             }
  333.     return 0;
  334.     }
  335.