home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / utilities / m / multimod / !MultiMod / c / support < prev    next >
Encoding:
Text File  |  1992-11-16  |  14.9 KB  |  496 lines

  1. /* support.c */
  2.  
  3. #include "all.h"
  4.  
  5. procs multi = PROCS;
  6. menu current_menu = 0;
  7.  
  8. /* This procedure generates a menu when the middle button is clicked over a
  9.  * collection window.  It uses the mouse co-ordinates and the display mode to
  10.  * calculate which file icon it is over and generates a menu for that icon
  11.  */
  12.  
  13. menu maker(void *handle)
  14. {
  15.         char menubuf[512];
  16.         char delete[64];
  17.         int h = (int) handle;
  18.  
  19.         if ((current_menu && !event_is_menu_being_recreated()) || !current_menu)
  20.                 {
  21.                 if (current_menu) menu_dispose(¤t_menu,0);
  22.                 current_menu = (menu) 0;
  23.                 data[h]->cm  = matchbox(h);
  24.  
  25.                 if (data[h]->cm == -1)
  26.                         sprintf(delete,"~Remove");
  27.                 else
  28.                 {
  29.                    char *filename = data[h]->m[data[h]->cm].leaf;
  30.                    sprintf(delete,"Remove '%s'\0",filename);
  31.                 }
  32.                 sprintf(menubuf,"Display,>Save,>Save Group,%s,Quit",delete);
  33.         }
  34.  
  35.         if (!event_is_menu_being_recreated())
  36.         {
  37.                 current_menu = menu_new("Multi Module",menubuf);
  38.                 menu_submenu(current_menu,1,disp_menu);
  39.         }
  40.         setflags(h);
  41.         return current_menu;
  42. }
  43.  
  44. /* This routine makes room for a new file.  It uses flex_alloc to claim space
  45.  * for the data it requires.  It also creates a new window and puts the handle
  46.  * into the structure.  The structure is initialised to zero except for the
  47.  * window handle and the other standard data that must be defined.
  48.  */
  49.  
  50. int allocate_untitled_window(char *v) /* returns index */
  51. {
  52.         wimp_w new;
  53.  
  54.         if (example_create_window("modules",&new))
  55.         {
  56.                 int i;
  57.                 for (i = 0 ; i < MaxFiles ; i++)
  58.                         if (!using[i]) {
  59.                                 if (flex_alloc((flex_ptr)&data[i],
  60.                                         sizeof(single_file_info)))
  61.                                 {
  62.                                         blank_data(data[i]);
  63.                                         data[i]->entries = 0;
  64.                                         data[i]->w       = new;
  65.                                         data[i]->cm      = -1;
  66.                                         data[i]->disp    = display_fullinfo;
  67.                                         data[i]->changed = FALSE;
  68.                                         data[i]->next    = 0;
  69.                                         data[i]->sort    = sorting_alpha;
  70.                                         using[i]         = TRUE;
  71.                                         data_handler(i,new);
  72.                                         sprintf(data[i]->filename,"<Untitled>\0");
  73.                                         setflags(i);
  74.                                         initial_position(i,data[i]->w);
  75.                                         resize_window(i);
  76.                                         return i;
  77.                                 }
  78.                                 else
  79.                                 {
  80.                                         wimp_delete_wind(new);
  81.                                         werr(0,"Cannot create file -- Out of memory");
  82.                                         return -1;
  83.                                 } }
  84.         }
  85.         return -1;
  86. }
  87.  
  88. /* This routine is the same as above except that it sets the title of the window
  89.  * as well
  90.  */
  91.  
  92. int allocate_named_window(char *v)
  93. {
  94.         int index;
  95.         char buffer[270];
  96.         wimp_wstate state;
  97.  
  98.         if ((index = allocate_untitled_window((char *)-1)) == -1) return -1;
  99.         sprintf(buffer,"Multi Module: %.250s\0",v);
  100.         win_settitle(data[index]->w,buffer);
  101.  
  102.         if (wimpt_complain(wimp_get_wind_state(data[index]->w , &state)) == 0)
  103.         {
  104.                 state.o.behind = -1;          /* Make sure window is opened in front */
  105.                 wimpt_noerr(wimp_open_wind(&state.o));
  106.         }
  107.  
  108.         return index;
  109. }
  110.  
  111. int open_file(int mode, char *name)   /* Open a file (RISC_OS style) */
  112. {
  113.         os_regset r;
  114.  
  115.         r.r[0] = mode;
  116.         r.r[1] = (int) name;
  117.         os_find(&r);
  118.         return r.r[0];
  119. }
  120.  
  121. void close_file(int file)               /* Close a file (RISC_OS style) */
  122. {
  123.         os_regset r;
  124.  
  125.         r.r[0] = 0;
  126.         r.r[1] = file;
  127.         os_find(&r);
  128. }
  129.  
  130. /* This routine performs a generic OS_GBPB call.  The particular call wanted
  131.  * is passed in the reason parameter which corresponds directly to those used
  132.  * by RISC OS.
  133.  */
  134.  
  135. int call_args(int reason, int file, int misc)
  136. {
  137.         os_regset r;
  138.         r.r[0] = reason;
  139.         r.r[1] = file;
  140.         r.r[2] = misc;
  141.         os_args(&r);
  142.         return r.r[2];
  143. }
  144.  
  145. /* These procedures call OS_GBPB to set file extents, read and set file pointers */
  146.  
  147. void file_extent(int file, int extent) { (void) call_args(3,file,extent); }
  148. void set_pointer(int file,int ptr)     { (void) call_args(1,file,ptr);    }
  149. int  get_pointer(int file)             { return call_args(0,file,0     ); }
  150.  
  151. /* This procedure creates an empty file with type 0xff8 (Absolute) */
  152.  
  153. void create_file(char *name)
  154. {
  155.         os_filestr o;
  156.  
  157.         o.action   = 11;
  158.         o.name     = name;
  159.         o.loadaddr = 0xff8;
  160.         o.start    = o.end = 0;
  161.         os_file(&o);
  162. }
  163.  
  164. void putw(int file, int size)
  165. {
  166.         gbpb(file,&size,4,-1);
  167. }
  168.  
  169. /* This procedure generates an absolute file containing all the modules in the
  170.  * current collection.  It refuses to save an empty collection and prompts for
  171.  * clearance to save a collection with one item only
  172.  */
  173.  
  174. #define OneModQuery "File contains only one module. Continue anyway?"
  175.  
  176. BOOL save_to_absolute(char *name, void *handle)
  177. {
  178.         int i;                  /* For looping around the modules */
  179.         int h = (int) handle;   /* Internal file handle for program */
  180.         SFI d = data[h];        /* Pointer to data for internal file */
  181.         SMI m;                  /* Pointer to a module information  */
  182.         int f;                  /* File handle */
  183.         int result;             /* Result of writing to a file */
  184.  
  185.         if (d->entries == 0)
  186.         {
  187.                 werr(0,"No modules in collection");
  188.                 return FALSE;
  189.         }
  190.         else if (d->entries == 1)
  191.                 if (dboxquery(OneModQuery) != dboxquery_YES) return FALSE;
  192.  
  193.  
  194.         create_file(name);
  195.         if ((f = open_file(0xc0 , name)) == 0) return FALSE;
  196.         file_extent(f,AUXSIZE + sumsizes(h));
  197.         set_pointer(f,AUXSIZE);
  198.  
  199.         for (i = 0 , m=&d->m[0]; i < d->entries; i++, m++)
  200.         {
  201.                 int ptr;
  202.  
  203.                 set_pointer(f,ptr = align(get_pointer(f)));
  204.                 code.info[i].module_start = ptr + 0x8004;
  205.                 code.info[i].module_size  = m->size;
  206.  
  207.                 putw(f,m->size);
  208.  
  209.                 if (!outfile(f, m->filename, m->size))
  210.                 {
  211.                         werr(0,"File '%s' not included in output",m->filename);
  212.                         code.info[i].module_start = 0;
  213.                         set_pointer(f,ptr);
  214.                 }
  215.         }
  216.  
  217.         code.module_count = d->entries;
  218.         sprintf(code.id,"Multi Module version %-26.26s\0",example_Version_String);
  219.         set_pointer(f,0);
  220.         result = gbpb(f,(void *)&code, AUXSIZE, 0);
  221.         close_file(f);
  222.  
  223.         return result != -1;
  224. }
  225.  
  226. /* This functions transfers a given file (name) into the file dest.  The
  227.  * expected size of the file is given in (size).  If this does not match
  228.  * then an error is generated.  Really this should be a time stamp.
  229.  */
  230.  
  231. #define NotAModule "%s is not a module"
  232. #define Modified   "%s modified since addition to collection"
  233.  
  234. BOOL outfile(int dest, char *name, int size)
  235. {
  236.         int       sz;  /* For holding the size of the file   */
  237.         int       src; /* The RISC OS file handle for source */
  238.  
  239.         if ((sz = filesize(name)) != size)
  240.           return werr(0, sz == -2 ? NotAModule : Modified , name) , FALSE;
  241.  
  242.         if ((src = open_file(0x40 , name)) == 0) return FALSE;
  243.         copyb(src,dest);
  244.         close_file(src);
  245.         return TRUE;
  246. }
  247.  
  248. /* This function is responsible for resizing a window so that all the icons
  249.  * just fit in the window.  It uses the multi procedures to call the correct
  250.  * sizing functions for the particular display mode in use
  251.  */
  252.  
  253. #define MAXIMUM_Y0 (-44)
  254.  
  255. void resize_window(int handle)
  256. {
  257.         wimp_wstate    state;
  258.         wimp_box      *box = &state.o.box;
  259.         SFI            d   = data[handle];
  260.  
  261.         wimp_redrawstr r;
  262.  
  263.         wimp_get_wind_state(d->w,&state);
  264.  
  265.         r.w = d->w;
  266.         r.box.x0 = 0;
  267.         r.box.y1 = 0;
  268.  
  269.         if (multi[d->disp].setextent(handle,&r.box),state.flags & wimp_WOPEN)
  270.         {
  271.                 if (box->y0 < r.box.y0) box->y0 = r.box.y0;
  272.                 if (box->x1 > r.box.x1) box->x1 = r.box.x1;
  273.                 wimp_close_wind(state.o.w);
  274.         }
  275.         wimp_set_extent(&r);
  276.         organise_icons(handle);
  277.         if (state.flags & wimp_WOPEN) wimp_open_wind(&state.o);
  278. }
  279.  
  280. /* These three functions calculate the work area extent for the display modes */
  281.  
  282. void large_ext(int handle, wimp_box *box)
  283. {
  284.         box->x1 = LARGE_ICONSWIDTH * LARGE_ICONSPERROW;
  285.         box->y0 = -44 - LARGE_ICONSHEIGHT * (1+((data[handle]->entries-1) / LARGE_ICONSPERROW));
  286. }
  287.  
  288. void small_ext(int handle, wimp_box *box)
  289. {
  290.         box->x1 = SMALL_ICONSWIDTH * SMALL_ICONSPERROW;
  291.         box->y0 = -48 - SMALL_ICONSHEIGHT * (1+((data[handle]->entries-1) / SMALL_ICONSPERROW));
  292. }
  293.  
  294. void finfo_ext(int handle, wimp_box *box)
  295. {
  296.         box->x1 = larger(smaller(WIDTH,16*(35+longest(handle))),900);
  297.         box->y0 = smaller(MAXIMUM_Y0 - (data[handle]->entries * LineGap),MAXIMUM_Y0)-4;
  298. }
  299.  
  300. /* This procedure organises the title bar and the contents icon (#0) for a window
  301.  * It works out the size of the modules in the collection and displays this 
  302.  * at the top of the window.
  303.  */
  304.  
  305. void organise_icons(int handle)
  306. {
  307.         wimp_w w = data[handle]->w;
  308.         int    e = data[handle]->entries;
  309.         char   c[20];
  310.  
  311.         wimp_icon wi;
  312.  
  313.         size_string(sumsizes(handle),c);
  314.  
  315.         wimp_get_icon_info(w,0,&wi);
  316.         sprintf(wi.data.indirecttext.buffer,
  317.                 " Number of Modules: %3d   Size of Modules: %.12s",e,c);
  318.         wimp_set_icon_state(w,0,0,0);
  319.         resort(handle);
  320.         force_redraw(handle);
  321. }
  322.  
  323. /* Unsigned char, case-insenstive version of strcmp (same entry/exit conditions) */
  324.  
  325. int strcmpic(unsigned char *a,unsigned char *b)
  326. {
  327.         int ans;
  328.  
  329.         while (*a && *b) if ((ans = tolower(*a++) - tolower(*b++))) return ans;
  330.         return *a - *b;
  331. }
  332.  
  333. /* This array of functions required to do the comparisons for qsort */
  334.  
  335. static int sort_0(const void *a, const void *b)
  336. { return ((SMI)a)->order - ((SMI)b)->order; }
  337.  
  338. static int sort_1(const void *a, const void *b)
  339. { return strcmpic((unsigned char *)((SMI)a)->leaf,(unsigned char *)((SMI)b)->leaf); }
  340.  
  341. static int sort_2(const void *a, const void *b)
  342. { return ((SMI)a)->size - ((SMI)b)->size; }
  343.  
  344. static int sort_3(const void *a ,const void *b)
  345. { return -sort_2(a,b); }
  346.  
  347. typedef int (*comparison)(const void *,const void *);
  348. static comparison sorters[8] = { 0 , 0 , 0 , 0 , sort_0 , sort_1 , sort_2 , sort_3 };
  349.  
  350. void resort(int handle)
  351. {
  352.         SFI d = data[handle];
  353.         comparison comp = sorters[d->sort];
  354.  
  355.         qsort((void *)(d->m), d->entries, sizeof(single_module_info), comp);
  356. }
  357.  
  358. /* This procedure adds small offsets to the window position so that opening
  359.  * several new windows doesn't result in them all being exactly on top of
  360.  * one another
  361.  */
  362.  
  363. void initial_position(int handle, wimp_w w)
  364. {
  365.         wimp_wstate state;
  366.         int xoffset = (handle / 4) * 64;
  367.         int yoffset = -(handle % 4) * 24;
  368.  
  369.         wimp_get_wind_state(w,&state);
  370.         state.o.box.x0 += xoffset;
  371.         state.o.box.x1 += xoffset;
  372.         state.o.box.y0 += yoffset;
  373.         state.o.box.y1 += yoffset;
  374.         wimp_open_wind(&state.o);
  375.         wimp_close_wind(w);
  376. }
  377.  
  378. /* This function attempts to load a given file. */
  379.  
  380. #define NotMultiFile "This is not a Multi Module collection file"
  381. #define WrongVersion "This file was saved by a different version of Multi Module"
  382. #define CouldntLoad  "Load aborted because file is not a valid collection"
  383. #define CantOpen     "Unable to load %s because file will not open",filename
  384. #define NoMoreRoom   "Too many collections already open"
  385.  
  386. #define LoadFail(R,W)  werr(0,R),destroy_data(W),FALSE
  387. #define LoadFailW(R,W) werr(0,R),wimp_delete_wind(d->w),destroy_data(W),FALSE
  388.  
  389. int check_headers(int handle)
  390. {
  391.         SFI d = data[handle];
  392.  
  393.         if (strncmp(IDENT, d->ident, 8)) return LoadFailW(NotMultiFile,handle);
  394.         if (d->version != VERSION_NUMBER) return LoadFailW(WrongVersion,handle);
  395.         return TRUE;
  396. }
  397.  
  398. BOOL load_file(char *filename)
  399. {
  400.         int handle;
  401.         SFI d;
  402.         int file;
  403.         int i;
  404.         wimp_wstate state;
  405.         wimp_w temp;
  406.  
  407.         if ((i = editing(filename)) != -1)
  408.         {
  409.                 wimp_get_wind_state(data[i]->w,&state);
  410.                 state.o.behind = -1;
  411.                 wimp_open_wind(&state.o);
  412.                 return FALSE;
  413.         }
  414.  
  415.         if ((handle = allocate_untitled_window(filename)) == -1)
  416.                 return werr(0,NoMoreRoom),FALSE;
  417.  
  418.         d = data[handle];
  419.         temp = d->w;
  420.  
  421.         if ((file = open_file(0x40,filename)) == 0) LoadFailW(CantOpen,handle);
  422.  
  423.         i = readb(file,d,sizeof(single_file_info),-1);
  424.         close_file(file);
  425.  
  426.         d->w = temp;
  427.  
  428.         if (i == -1) return LoadFailW(CouldntLoad,handle);
  429.         if (!check_headers(handle)) return FALSE;
  430.  
  431.         strncpy(d->filename, filename ,256);
  432.  
  433.         mark_unchanged(handle);
  434.         resize_window(handle);
  435.         wimp_get_wind_state(d->w,&state);
  436.         state.o.behind = -1;
  437.         wimp_open_wind(&state.o);
  438.         return TRUE;
  439. }
  440.  
  441. /* Returns -1 if file is not already being edited.  Returns handle of file if it is */
  442.  
  443. int editing(char *name)
  444. {
  445.         int i;
  446.  
  447.         for (i = 0; i<MaxFiles; i++) if (using[i])
  448.                 if (strcmp(data[i]->filename,name) == 0) return i;
  449.  
  450.         return -1;
  451. }
  452.  
  453. #define InsertFail "Failed to insert due to lack of memory (or too many MultiMod windows open)"
  454.  
  455. BOOL insert_file(int handle,char *filename)
  456. {
  457.         int temp;
  458.         int file;
  459.         int i;
  460.         SFI d;
  461.  
  462.         if ((temp = allocate_untitled_window("<Temporary File>")) == -1)
  463.                 return LoadFail(InsertFail,temp);
  464.         else
  465.         {
  466.         wimp_w w = data[temp]->w;
  467.  
  468.         if ((file = open_file(0x40,filename)) == 0) return LoadFailW(CantOpen,temp);
  469.  
  470.         d = data[temp];
  471.         i = readb(file,d,sizeof(single_file_info),-1);
  472.         d->w = w;
  473.         close_file(file);
  474.  
  475.         if (i == -1) return LoadFail(CouldntLoad,temp);
  476.         if (!check_headers(temp)) return FALSE;
  477.  
  478.         wimp_delete_wind(w);
  479.         (void) copy_contents(temp,handle);
  480.         destroy_data(temp);
  481.         }
  482.         return TRUE;
  483. }
  484.  
  485. BOOL copy_contents(int src,int dest)
  486. {
  487.         SFI from = data[src];
  488.         SMI msrc = &from->m[0];
  489.         int loop ;
  490.  
  491.         for ( loop = 0; loop < from->entries; loop++,msrc++)
  492.                 add_module(dest,msrc->filename);
  493.  
  494.         return TRUE;
  495. }
  496.