home *** CD-ROM | disk | FTP | other *** search
- /* support.c */
-
- #include "all.h"
-
- procs multi = PROCS;
- menu current_menu = 0;
-
- /* This procedure generates a menu when the middle button is clicked over a
- * collection window. It uses the mouse co-ordinates and the display mode to
- * calculate which file icon it is over and generates a menu for that icon
- */
-
- menu maker(void *handle)
- {
- char menubuf[512];
- char delete[64];
- int h = (int) handle;
-
- if ((current_menu && !event_is_menu_being_recreated()) || !current_menu)
- {
- if (current_menu) menu_dispose(¤t_menu,0);
- current_menu = (menu) 0;
- data[h]->cm = matchbox(h);
-
- if (data[h]->cm == -1)
- sprintf(delete,"~Remove");
- else
- {
- char *filename = data[h]->m[data[h]->cm].leaf;
- sprintf(delete,"Remove '%s'\0",filename);
- }
- sprintf(menubuf,"Display,>Save,>Save Group,%s,Quit",delete);
- }
-
- if (!event_is_menu_being_recreated())
- {
- current_menu = menu_new("Multi Module",menubuf);
- menu_submenu(current_menu,1,disp_menu);
- }
- setflags(h);
- return current_menu;
- }
-
- /* This routine makes room for a new file. It uses flex_alloc to claim space
- * for the data it requires. It also creates a new window and puts the handle
- * into the structure. The structure is initialised to zero except for the
- * window handle and the other standard data that must be defined.
- */
-
- int allocate_untitled_window(char *v) /* returns index */
- {
- wimp_w new;
-
- if (example_create_window("modules",&new))
- {
- int i;
- for (i = 0 ; i < MaxFiles ; i++)
- if (!using[i]) {
- if (flex_alloc((flex_ptr)&data[i],
- sizeof(single_file_info)))
- {
- blank_data(data[i]);
- data[i]->entries = 0;
- data[i]->w = new;
- data[i]->cm = -1;
- data[i]->disp = display_fullinfo;
- data[i]->changed = FALSE;
- data[i]->next = 0;
- data[i]->sort = sorting_alpha;
- using[i] = TRUE;
- data_handler(i,new);
- sprintf(data[i]->filename,"<Untitled>\0");
- setflags(i);
- initial_position(i,data[i]->w);
- resize_window(i);
- return i;
- }
- else
- {
- wimp_delete_wind(new);
- werr(0,"Cannot create file -- Out of memory");
- return -1;
- } }
- }
- return -1;
- }
-
- /* This routine is the same as above except that it sets the title of the window
- * as well
- */
-
- int allocate_named_window(char *v)
- {
- int index;
- char buffer[270];
- wimp_wstate state;
-
- if ((index = allocate_untitled_window((char *)-1)) == -1) return -1;
- sprintf(buffer,"Multi Module: %.250s\0",v);
- win_settitle(data[index]->w,buffer);
-
- if (wimpt_complain(wimp_get_wind_state(data[index]->w , &state)) == 0)
- {
- state.o.behind = -1; /* Make sure window is opened in front */
- wimpt_noerr(wimp_open_wind(&state.o));
- }
-
- return index;
- }
-
- int open_file(int mode, char *name) /* Open a file (RISC_OS style) */
- {
- os_regset r;
-
- r.r[0] = mode;
- r.r[1] = (int) name;
- os_find(&r);
- return r.r[0];
- }
-
- void close_file(int file) /* Close a file (RISC_OS style) */
- {
- os_regset r;
-
- r.r[0] = 0;
- r.r[1] = file;
- os_find(&r);
- }
-
- /* This routine performs a generic OS_GBPB call. The particular call wanted
- * is passed in the reason parameter which corresponds directly to those used
- * by RISC OS.
- */
-
- int call_args(int reason, int file, int misc)
- {
- os_regset r;
- r.r[0] = reason;
- r.r[1] = file;
- r.r[2] = misc;
- os_args(&r);
- return r.r[2];
- }
-
- /* These procedures call OS_GBPB to set file extents, read and set file pointers */
-
- void file_extent(int file, int extent) { (void) call_args(3,file,extent); }
- void set_pointer(int file,int ptr) { (void) call_args(1,file,ptr); }
- int get_pointer(int file) { return call_args(0,file,0 ); }
-
- /* This procedure creates an empty file with type 0xff8 (Absolute) */
-
- void create_file(char *name)
- {
- os_filestr o;
-
- o.action = 11;
- o.name = name;
- o.loadaddr = 0xff8;
- o.start = o.end = 0;
- os_file(&o);
- }
-
- void putw(int file, int size)
- {
- gbpb(file,&size,4,-1);
- }
-
- /* This procedure generates an absolute file containing all the modules in the
- * current collection. It refuses to save an empty collection and prompts for
- * clearance to save a collection with one item only
- */
-
- #define OneModQuery "File contains only one module. Continue anyway?"
-
- BOOL save_to_absolute(char *name, void *handle)
- {
- int i; /* For looping around the modules */
- int h = (int) handle; /* Internal file handle for program */
- SFI d = data[h]; /* Pointer to data for internal file */
- SMI m; /* Pointer to a module information */
- int f; /* File handle */
- int result; /* Result of writing to a file */
-
- if (d->entries == 0)
- {
- werr(0,"No modules in collection");
- return FALSE;
- }
- else if (d->entries == 1)
- if (dboxquery(OneModQuery) != dboxquery_YES) return FALSE;
-
-
- create_file(name);
- if ((f = open_file(0xc0 , name)) == 0) return FALSE;
- file_extent(f,AUXSIZE + sumsizes(h));
- set_pointer(f,AUXSIZE);
-
- for (i = 0 , m=&d->m[0]; i < d->entries; i++, m++)
- {
- int ptr;
-
- set_pointer(f,ptr = align(get_pointer(f)));
- code.info[i].module_start = ptr + 0x8004;
- code.info[i].module_size = m->size;
-
- putw(f,m->size);
-
- if (!outfile(f, m->filename, m->size))
- {
- werr(0,"File '%s' not included in output",m->filename);
- code.info[i].module_start = 0;
- set_pointer(f,ptr);
- }
- }
-
- code.module_count = d->entries;
- sprintf(code.id,"Multi Module version %-26.26s\0",example_Version_String);
- set_pointer(f,0);
- result = gbpb(f,(void *)&code, AUXSIZE, 0);
- close_file(f);
-
- return result != -1;
- }
-
- /* This functions transfers a given file (name) into the file dest. The
- * expected size of the file is given in (size). If this does not match
- * then an error is generated. Really this should be a time stamp.
- */
-
- #define NotAModule "%s is not a module"
- #define Modified "%s modified since addition to collection"
-
- BOOL outfile(int dest, char *name, int size)
- {
- int sz; /* For holding the size of the file */
- int src; /* The RISC OS file handle for source */
-
- if ((sz = filesize(name)) != size)
- return werr(0, sz == -2 ? NotAModule : Modified , name) , FALSE;
-
- if ((src = open_file(0x40 , name)) == 0) return FALSE;
- copyb(src,dest);
- close_file(src);
- return TRUE;
- }
-
- /* This function is responsible for resizing a window so that all the icons
- * just fit in the window. It uses the multi procedures to call the correct
- * sizing functions for the particular display mode in use
- */
-
- #define MAXIMUM_Y0 (-44)
-
- void resize_window(int handle)
- {
- wimp_wstate state;
- wimp_box *box = &state.o.box;
- SFI d = data[handle];
-
- wimp_redrawstr r;
-
- wimp_get_wind_state(d->w,&state);
-
- r.w = d->w;
- r.box.x0 = 0;
- r.box.y1 = 0;
-
- if (multi[d->disp].setextent(handle,&r.box),state.flags & wimp_WOPEN)
- {
- if (box->y0 < r.box.y0) box->y0 = r.box.y0;
- if (box->x1 > r.box.x1) box->x1 = r.box.x1;
- wimp_close_wind(state.o.w);
- }
- wimp_set_extent(&r);
- organise_icons(handle);
- if (state.flags & wimp_WOPEN) wimp_open_wind(&state.o);
- }
-
- /* These three functions calculate the work area extent for the display modes */
-
- void large_ext(int handle, wimp_box *box)
- {
- box->x1 = LARGE_ICONSWIDTH * LARGE_ICONSPERROW;
- box->y0 = -44 - LARGE_ICONSHEIGHT * (1+((data[handle]->entries-1) / LARGE_ICONSPERROW));
- }
-
- void small_ext(int handle, wimp_box *box)
- {
- box->x1 = SMALL_ICONSWIDTH * SMALL_ICONSPERROW;
- box->y0 = -48 - SMALL_ICONSHEIGHT * (1+((data[handle]->entries-1) / SMALL_ICONSPERROW));
- }
-
- void finfo_ext(int handle, wimp_box *box)
- {
- box->x1 = larger(smaller(WIDTH,16*(35+longest(handle))),900);
- box->y0 = smaller(MAXIMUM_Y0 - (data[handle]->entries * LineGap),MAXIMUM_Y0)-4;
- }
-
- /* This procedure organises the title bar and the contents icon (#0) for a window
- * It works out the size of the modules in the collection and displays this
- * at the top of the window.
- */
-
- void organise_icons(int handle)
- {
- wimp_w w = data[handle]->w;
- int e = data[handle]->entries;
- char c[20];
-
- wimp_icon wi;
-
- size_string(sumsizes(handle),c);
-
- wimp_get_icon_info(w,0,&wi);
- sprintf(wi.data.indirecttext.buffer,
- " Number of Modules: %3d Size of Modules: %.12s",e,c);
- wimp_set_icon_state(w,0,0,0);
- resort(handle);
- force_redraw(handle);
- }
-
- /* Unsigned char, case-insenstive version of strcmp (same entry/exit conditions) */
-
- int strcmpic(unsigned char *a,unsigned char *b)
- {
- int ans;
-
- while (*a && *b) if ((ans = tolower(*a++) - tolower(*b++))) return ans;
- return *a - *b;
- }
-
- /* This array of functions required to do the comparisons for qsort */
-
- static int sort_0(const void *a, const void *b)
- { return ((SMI)a)->order - ((SMI)b)->order; }
-
- static int sort_1(const void *a, const void *b)
- { return strcmpic((unsigned char *)((SMI)a)->leaf,(unsigned char *)((SMI)b)->leaf); }
-
- static int sort_2(const void *a, const void *b)
- { return ((SMI)a)->size - ((SMI)b)->size; }
-
- static int sort_3(const void *a ,const void *b)
- { return -sort_2(a,b); }
-
- typedef int (*comparison)(const void *,const void *);
- static comparison sorters[8] = { 0 , 0 , 0 , 0 , sort_0 , sort_1 , sort_2 , sort_3 };
-
- void resort(int handle)
- {
- SFI d = data[handle];
- comparison comp = sorters[d->sort];
-
- qsort((void *)(d->m), d->entries, sizeof(single_module_info), comp);
- }
-
- /* This procedure adds small offsets to the window position so that opening
- * several new windows doesn't result in them all being exactly on top of
- * one another
- */
-
- void initial_position(int handle, wimp_w w)
- {
- wimp_wstate state;
- int xoffset = (handle / 4) * 64;
- int yoffset = -(handle % 4) * 24;
-
- wimp_get_wind_state(w,&state);
- state.o.box.x0 += xoffset;
- state.o.box.x1 += xoffset;
- state.o.box.y0 += yoffset;
- state.o.box.y1 += yoffset;
- wimp_open_wind(&state.o);
- wimp_close_wind(w);
- }
-
- /* This function attempts to load a given file. */
-
- #define NotMultiFile "This is not a Multi Module collection file"
- #define WrongVersion "This file was saved by a different version of Multi Module"
- #define CouldntLoad "Load aborted because file is not a valid collection"
- #define CantOpen "Unable to load %s because file will not open",filename
- #define NoMoreRoom "Too many collections already open"
-
- #define LoadFail(R,W) werr(0,R),destroy_data(W),FALSE
- #define LoadFailW(R,W) werr(0,R),wimp_delete_wind(d->w),destroy_data(W),FALSE
-
- int check_headers(int handle)
- {
- SFI d = data[handle];
-
- if (strncmp(IDENT, d->ident, 8)) return LoadFailW(NotMultiFile,handle);
- if (d->version != VERSION_NUMBER) return LoadFailW(WrongVersion,handle);
- return TRUE;
- }
-
- BOOL load_file(char *filename)
- {
- int handle;
- SFI d;
- int file;
- int i;
- wimp_wstate state;
- wimp_w temp;
-
- if ((i = editing(filename)) != -1)
- {
- wimp_get_wind_state(data[i]->w,&state);
- state.o.behind = -1;
- wimp_open_wind(&state.o);
- return FALSE;
- }
-
- if ((handle = allocate_untitled_window(filename)) == -1)
- return werr(0,NoMoreRoom),FALSE;
-
- d = data[handle];
- temp = d->w;
-
- if ((file = open_file(0x40,filename)) == 0) LoadFailW(CantOpen,handle);
-
- i = readb(file,d,sizeof(single_file_info),-1);
- close_file(file);
-
- d->w = temp;
-
- if (i == -1) return LoadFailW(CouldntLoad,handle);
- if (!check_headers(handle)) return FALSE;
-
- strncpy(d->filename, filename ,256);
-
- mark_unchanged(handle);
- resize_window(handle);
- wimp_get_wind_state(d->w,&state);
- state.o.behind = -1;
- wimp_open_wind(&state.o);
- return TRUE;
- }
-
- /* Returns -1 if file is not already being edited. Returns handle of file if it is */
-
- int editing(char *name)
- {
- int i;
-
- for (i = 0; i<MaxFiles; i++) if (using[i])
- if (strcmp(data[i]->filename,name) == 0) return i;
-
- return -1;
- }
-
- #define InsertFail "Failed to insert due to lack of memory (or too many MultiMod windows open)"
-
- BOOL insert_file(int handle,char *filename)
- {
- int temp;
- int file;
- int i;
- SFI d;
-
- if ((temp = allocate_untitled_window("<Temporary File>")) == -1)
- return LoadFail(InsertFail,temp);
- else
- {
- wimp_w w = data[temp]->w;
-
- if ((file = open_file(0x40,filename)) == 0) return LoadFailW(CantOpen,temp);
-
- d = data[temp];
- i = readb(file,d,sizeof(single_file_info),-1);
- d->w = w;
- close_file(file);
-
- if (i == -1) return LoadFail(CouldntLoad,temp);
- if (!check_headers(temp)) return FALSE;
-
- wimp_delete_wind(w);
- (void) copy_contents(temp,handle);
- destroy_data(temp);
- }
- return TRUE;
- }
-
- BOOL copy_contents(int src,int dest)
- {
- SFI from = data[src];
- SMI msrc = &from->m[0];
- int loop ;
-
- for ( loop = 0; loop < from->entries; loop++,msrc++)
- add_module(dest,msrc->filename);
-
- return TRUE;
- }
-