Commit 3be21b3b authored by ROOL's avatar ROOL 🤖

Add clipboard/cut and paste to sprite filer

Detail:
  * Sprite filer window can now gain input focus
  * Change sprite/selection menu to add clipboard operations
  * Change 'Copy' to 'Copy as' to keep original copy with rename option
  * Add clipboard copy/paste/cut functionality
  * Add key bindings for clipboard bits
  * Remove existing drag of selection and replace with drag and drop protocol data export
  * Add drag and drop data import
Admin:
  Submission for Clipboard Support bounty.

Version 2.24. Tagged as 'Paint-2_24'
parent fbb7e4e0
......@@ -84,12 +84,12 @@ DFILES = \
debug.${APP}.Templates
OBJS = o.colours o.main o.menus o.psprite o.sprwindow o.tools o.toolwindow \
o.AltRename o.PaintLib
o.AltRename o.PaintLib o.CnPDrag o.Clipboard o.Drawfile
OBJSZ = oz.colours oz.main oz.menus oz.psprite oz.sprwindow\
oz.tools oz.toolwindow oz.AltRename oz.PaintLib
oz.tools oz.toolwindow oz.AltRename oz.PaintLib oz.CnPDrag oz.Clipboard oz.Drawfile
OBJSD = od.colours od.ftrace od.guard od.main od.menus\
od.psprite od.sprwindow od.tools od.toolwindow o.m\
od.AltRename od.PaintLib
od.AltRename od.PaintLib od.CnPDrag od.Clipboard od.Drawfile
ASMS = s.colours s.main s.menus s.psprite s.sprwindow s.tools s.toolwindow
INCS = i.colours i.main i.menus i.psprite i.sprwindow i.tools i.toolwindow
......
No preview for this file type
;
; This file is automatically maintained by srccommit, do not edit manually.
; Last processed by srccommit version: 1.1.
;
GBLS Module_MajorVersion
GBLA Module_Version
......@@ -10,14 +9,12 @@
GBLS Module_ApplicationDate
GBLS Module_HelpVersion
GBLS Module_ComponentName
GBLS Module_ComponentPath
Module_MajorVersion SETS "2.23"
Module_Version SETA 223
Module_MajorVersion SETS "2.24"
Module_Version SETA 224
Module_MinorVersion SETS ""
Module_Date SETS "11 Nov 2017"
Module_ApplicationDate SETS "11-Nov-17"
Module_Date SETS "08 Jun 2019"
Module_ApplicationDate SETS "08-Jun-19"
Module_ComponentName SETS "Paint"
Module_ComponentPath SETS "castle/RiscOS/Sources/Apps/Paint"
Module_FullVersion SETS "2.23"
Module_HelpVersion SETS "2.23 (11 Nov 2017)"
Module_FullVersion SETS "2.24"
Module_HelpVersion SETS "2.24 (08 Jun 2019)"
END
/* (2.23)
/* (2.24)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 2.23
#define Module_MajorVersion_CMHG 2.24
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 11 Nov 2017
#define Module_Date_CMHG 08 Jun 2019
#define Module_MajorVersion "2.23"
#define Module_Version 223
#define Module_MajorVersion "2.24"
#define Module_Version 224
#define Module_MinorVersion ""
#define Module_Date "11 Nov 2017"
#define Module_Date "08 Jun 2019"
#define Module_ApplicationDate "11-Nov-17"
#define Module_ApplicationDate "08-Jun-19"
#define Module_ComponentName "Paint"
#define Module_ComponentPath "castle/RiscOS/Sources/Apps/Paint"
#define Module_FullVersion "2.23"
#define Module_HelpVersion "2.23 (11 Nov 2017)"
#define Module_LibraryVersionInfo "2:23"
#define Module_FullVersion "2.24"
#define Module_HelpVersion "2.24 (08 Jun 2019)"
#define Module_LibraryVersionInfo "2:24"
/* Copyright 2019 RISC OS Open Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Global/FileTypes.h"
#include "Global/Sprite.h"
#include "Interface/HighFSI.h"
#include "event.h"
#include "flex.h"
#include "msgs.h"
#include "os.h"
#include "werr.h"
#include "wimp.h"
#include "wimpt.h"
#include "xferrecv.h"
#include "help.h"
#include "swis.h"
#include "ftrace.h"
#include "guard.h"
#include "main.h"
#include "Menus.h"
#include "MenuD.h"
#include "PSprite.h"
#include "Clipboard.h"
#include "Drawfile.h"
/*Globals: current clipboard data if we have ownership*/
static sprite_area *clipdata = NULL;
static BOOL paint_owns_clipboard = FALSE;
BOOL paint_clipboard_openup(const char *name, int *handle)
{ os_regset blk;
blk.r[0] = 0x87; /*OpenOut, Ignore file$path, give err if a dir.!*/
blk.r[1] = (int)name;
if (wimpt_complain(os_find(&blk))) return FALSE;
if (blk.r[0] == 0)
{ /*In case the FileSwitch bug returns a 0 handle.*/
werr (FALSE, "PntE4",name);
return FALSE;
}
*handle = blk.r[0];
return TRUE;
}
BOOL paint_clipboard_close(const char *name, int *handle, int filetype)
{ os_regset blk;
blk.r[0] = 0; blk.r[1] = *handle;
if (wimpt_complain (os_find (&blk))) return FALSE;
os_filestr osf;
memset(&osf,0,sizeof(os_filestr));
/*Set filetype*/
osf.action = OSFile_SetType;
osf.name = (char *)name;
osf.loadaddr = filetype;
if (wimpt_complain(os_file(&osf))) return FALSE;
return TRUE;
}
BOOL paint_clipboard_write_bytes(int handle, const char *buffer, int buffer_length)
{ os_regset blk;
blk.r[0] = OSGBPB_WriteAtPTR;
blk.r[1] = handle;
blk.r[2] = (int)buffer;
blk.r[3] = buffer_length;
while (blk.r[3] > 0)
{ /*ensure we transfer all data if possible*/
if (wimpt_complain(os_swix(OS_GBPB,&blk))) return FALSE;
}
return TRUE;
}
void paint_clipboard_export_ramxfer_do(wimp_eventstr *ev, char *export_buffer, int export_length)
{ int export_offset = 0;
BOOL abort = FALSE, messaged = FALSE;
while (export_offset <= export_length && abort == FALSE)
{ /*Send the requested amount of data (or less if necessary)*/
int xfer_amount = ev->data.msg.data.ramfetch.nbytes;
wimp_msgstr msg;
if (xfer_amount > (export_length-export_offset)) xfer_amount = export_length - export_offset; /*not too much though*/
if (xfer_amount) wimp_transferblock(wimpt_task(), export_buffer + export_offset, ev->data.msg.hdr.task, ev->data.msg.data.ramfetch.addr, xfer_amount);
memset(&msg, 0, sizeof(wimp_msgstr));
msg.hdr.size = sizeof(wimp_msghdr) + sizeof(wimp_msgramtransmit);
msg.hdr.your_ref = ev->data.msg.hdr.my_ref;
msg.hdr.action = wimp_MRAMTRANSMIT;
msg.data.ramtransmit.addr = ev->data.msg.data.ramfetch.addr;
msg.data.ramtransmit.nbyteswritten = xfer_amount;
export_offset += xfer_amount;
wimp_sendmessage(xfer_amount == 0 ? wimp_ESEND : wimp_ESENDWANTACK, &msg,ev->data.msg.hdr.task);
if (xfer_amount == 0) abort=TRUE;
while (!messaged && !abort)
{ wimpt_poll(event_getmask(), ev);
switch (ev->e)
{ case wimp_EACK:
/*Bounced message; abort*/
abort = TRUE;
break;
case wimp_ESENDWANTACK:
case wimp_ESEND:
/*we can send more stuff*/
if (ev->data.msg.hdr.action != wimp_MRAMFETCH) abort = TRUE;
else messaged = TRUE;
break;
}
}
}
}
void paint_clipboard_release(void)
{ /*Another task has claimed the clipboard*/
paint_owns_clipboard = FALSE;
if (clipdata != NULL)
{ flex_free((flex_ptr)&clipdata);
clipdata = NULL;
}
}
void paint_clipboard_claim(int claimtype)
{ /*Claimtype is as per the Wimp Message*/
if (!paint_owns_clipboard)
{ wimp_msgstr msg;
memset(&msg, 0, sizeof(wimp_msgstr));
msg.hdr.size = 24;
msg.hdr.action = wimp_MCLAIMENTITY;
msg.data.claimentity.flags = claimtype;
wimp_sendmessage(wimp_ESEND, &msg, 0);
if ((claimtype & wimp_MCLAIMENTITY_flags_clipboard) != 0)
paint_owns_clipboard = TRUE;
}
}
static BOOL paint_clipboard_send_datarequest(wimp_eventstr *e)
{ /*Request from other tasks*/
wimp_msgstr msg;
int *types;
memset(&msg, 0, sizeof(wimp_msgstr));
msg.hdr.size = 20 + ((3-1) * sizeof(int)) + sizeof(wimp_msghdr);
msg.hdr.action = wimp_MDATAREQUEST;
msg.data.datarequest.w = 0;
msg.data.datarequest.h = &clipdata;
msg.data.datarequest.x = 0;
msg.data.datarequest.y = 0;
msg.data.datarequest.flags = wimp_MDATAREQUEST_flags_clipboard;
types = &msg.data.datarequest.types[0];
types[0] = FileType_Sprite;
types[1] = FileType_JPEG;
types[2] = wimp_MDATAREQUEST_types_end;
wimp_sendmessage(wimp_ESENDWANTACK, &msg, 0);
/*We either get back a datasave or a bounce*/
while (1)
{ wimpt_poll(event_getmask(), e);
switch (e->e)
{ case wimp_EACK:
if (e->data.msg.hdr.action == wimp_MDATAREQUEST)
{ /*Bounced message - no data on clipboard to paste*/
return FALSE;
}
break;
case wimp_ESEND:
case wimp_ESENDWANTACK:
if (e->data.msg.hdr.action == wimp_MDATASAVE)
/*Check the filetypes supported*/
return (e->data.msg.data.datasave.type == FileType_Sprite ||
e->data.msg.data.datasave.type == FileType_JPEG);
break;
}
}
return FALSE;
}
BOOL paint_clipboard_check_paste(void)
{ wimp_eventstr e;
/*See if there's anything on the clipboard for pasting*/
if (paint_owns_clipboard) return TRUE; /*Quick check*/
return paint_clipboard_send_datarequest(&e);
}
BOOL paint_clipboard_get_selection(main_window *window,void *buffer,selbuffer_type type)
{ char *ptr;
main_sprite *sprite;
int size = main_selection_file_size(window);
char **rawdata=(char **)buffer;
/* see if we can allocate it */
/* +4 bytes as we have an area rather than a file */
if (!flex_alloc((flex_ptr)rawdata, size + (type == SELBUFFER_SPRITEAREA ? 4:0)))
{ /* out of space */
werr (FALSE, "PntEG");
return FALSE;
}
if (type == SELBUFFER_SPRITEAREA)
{ sprite_area *spr = *((sprite_area **)buffer);
spr->size = size + 4;
spr->number = window->selection.count;
spr->sproff = sizeof (sprite_area);
spr->freeoff = size + 4;
ptr = *rawdata + spr->sproff;
}
else
{ struct fileheader
{ int number;
int sproff;
int freeoff;
} **header = (struct fileheader **)buffer;
(*header)->number = window->selection.count;
(*header)->sproff = sizeof(sprite_area);
(*header)->freeoff = size + 4;
ptr = *rawdata + (*header)->sproff - 4;
}
for (sprite = window->data->file.sprites; sprite != NULL; sprite = sprite->link)
{ if (sprite->flags & MSF_SELECTED)
{ sprite_header *header = psprite_address (sprite);
memcpy (ptr, header, header->next);
ptr += header->next;
}
}
return TRUE;
}
BOOL paint_clipboard_set_data_from_selection(main_window *window)
{ /* Transfer data from a selection to the clipboard */
if (!window || (window->selection.count==0)) return FALSE; /* Nothing to do */
/* Clear any existing area first */
if (clipdata) {
flex_free((flex_ptr)&clipdata);
clipdata = NULL;
}
if (!paint_clipboard_get_selection(window, &clipdata, SELBUFFER_SPRITEAREA)) return FALSE;
/* Data set up, so send out our clipboard claim */
paint_clipboard_claim(wimp_MCLAIMENTITY_flags_clipboard);
return TRUE;
}
void paint_clipboard_paste(main_window *window)
{ /*Paste clipboard data into sprite file*/
wimp_eventstr e;
/*We either just do an internal copy, or pull from external clipboard task*/
if (paint_owns_clipboard)
{ /* Internal action */
/* Transfer data to ramfetch_buffer for import */
if (!flex_alloc((flex_ptr)&ramfetch_buffer,clipdata->size - 4))
{ werr (FALSE, "PntEG");
return;
}
memcpy(ramfetch_buffer, (char *)clipdata + 4, clipdata->size - 4);
}
else
{ /* Request from external clipboard task*/
if (!paint_clipboard_send_datarequest(&e)) return; /*Message was bounced, oddly*/
/* Acquire the data */
if (!ramtransfer_file(&e.data.msg.data.datasave)) return; /* Failed to acquire data */
}
/* Delete any currently selected sprites */
if (window->selection.count != 0)
{ char hit[2];
hit [0] = m_Sprite;
hit [1] = m_Sprite_Delete;
menus_file_handler(window, hit);
}
Load_File(window, (char *)-1, 1, 0);
}
void paint_clipboard_claimed(wimp_eventstr *e)
{ /* Claimed... */
if (e->data.msg.hdr.task == wimpt_task()) return; /* Was us! */
paint_clipboard_release();
}
void paint_clipboard_send_dataload(wimp_eventstr *ev, int buffer_length)
{ wimp_msgstr msg;
memset(&msg, 0, sizeof(wimp_msgstr));
msg.hdr.action = wimp_MDATALOAD;
msg.hdr.size = (msg.data.dataload.name - (char *)&msg + 1 + strlen(ev->data.msg.data.dataload.name) + 3) &~ 3;
msg.hdr.your_ref = ev->data.msg.hdr.my_ref;
msg.data.dataload.w = ev->data.msg.data.datasaveok.w; /* target window */
msg.data.dataload.i = ev->data.msg.data.datasaveok.i; /* target icon */
msg.data.dataload.x = ev->data.msg.data.datasaveok.x; /* target coords in target window work area */
msg.data.dataload.y = ev->data.msg.data.datasaveok.y;
msg.data.dataload.size = buffer_length;
msg.data.dataload.type = ev->data.msg.data.datasaveok.type; /* type of file */
strcpy(msg.data.dataload.name, ev->data.msg.data.dataload.name);
wimp_sendmessage(wimp_ESENDWANTACK, &msg, ev->data.msg.hdr.task); /*Return to destination task*/
}
static void paint_clipboard_export_file(wimp_eventstr *ev, char *data, int length, int filetype)
{ /*Export data to file and then issue DATALOAD*/
int handle;
BOOL success = FALSE;
if (!paint_clipboard_openup(ev->data.msg.data.datasaveok.name, &handle))
return; /*Error already reported; bail out*/
success = paint_clipboard_write_bytes(handle, data, length);
if (success)
success = paint_clipboard_close(ev->data.msg.data.datasaveok.name, &handle, filetype);
else
{ /*Don't change success - want to keep it as FALSE */
paint_clipboard_close(ev->data.msg.data.datasaveok.name, &handle, filetype);
}
if (success) paint_clipboard_send_dataload(ev, length);
}
BOOL paint_clipboard_list_has_type(int *listptr, int filetype)
{ /*Check the list to see if it has a particular filetype or not*/
int i;
for (i = 0; i < (256 - 24 - sizeof(wimp_msghdr))/4 && *(listptr+i) != wimp_MDATAREQUEST_types_end; i++)
{
if (*(listptr + i) == filetype)
return TRUE;
}
return FALSE;
}
void paint_clipboard_rx_datarequest(wimp_eventstr *e)
{ wimp_msgstr msg;
int output_type;
char *draw_buffer = NULL;
int draw_length = 0;
/*Can we service this?*/
if (!paint_owns_clipboard) return; /*We don't have anything to shout about*/
if (e->data.msg.data.datarequest.flags != wimp_MDATAREQUEST_flags_clipboard)
return; /*Unknown flags, bail out*/
/*Send a datasave with a matching mask*/
memset(&msg, 0, sizeof(wimp_msgstr));
msg.hdr.your_ref = e->data.msg.hdr.my_ref;
msg.hdr.action = wimp_MDATASAVE;
msg.data.datasave.w = e->data.msg.data.datarequest.w;
msg.data.datasave.i = (int)e->data.msg.data.datarequest.h;
msg.data.datasave.x = e->data.msg.data.datarequest.x;
msg.data.datasave.y = e->data.msg.data.datarequest.y;
/* At the moment we only export Sprites or a Drawfile. In future we'll likely need
to alter this to export PNG on request too. */
/* determine export options */
if (clipdata->number > 1 && paint_clipboard_list_has_type(&e->data.msg.data.datarequest.types[0],FileType_Draw))
{ output_type = FileType_Draw;
if (!clipboard_to_drawfile(clipdata, &draw_buffer, &draw_length)) return;
msg.data.datasave.estsize = draw_length;
}
else
{ output_type = FileType_Sprite;
msg.data.datasave.estsize = clipdata->size - 4;
}
msg.data.datasave.type = output_type;
strcpy(msg.data.datasave.leaf, msgs_lookup("PntG6"));
msg.hdr.size = (msg.data.datasave.leaf - (char *)&msg + 1 + strlen(msg.data.datasave.leaf) + 3) &~ 3;
wimp_sendmessage(wimp_ESENDWANTACK, &msg, e->data.msg.hdr.task);
/*See if we get a reply...*/
wimp_eventstr ev;
BOOL complete = FALSE;
while (!complete)
{ wimpt_poll(event_getmask(), &ev);
switch (ev.e)
{ case wimp_EACK:
if (ev.data.msg.hdr.action == wimp_MDATASAVE)
{ /*Bounced message - no data on clipboard to paste, just bail out*/
complete = TRUE;
}
break;
case wimp_ESEND:
case wimp_ESENDWANTACK:
switch (ev.data.msg.hdr.action)
{ case wimp_MDATASAVEOK: /*File xfer*/
if (output_type == FileType_Sprite)
paint_clipboard_export_file(&ev, ((char *)clipdata) + 4, clipdata->size - 4, output_type);
else
paint_clipboard_export_file(&ev, draw_buffer, draw_length, output_type);
complete = TRUE;
break;
case wimp_MRAMFETCH: /*Memory xfer*/
if (output_type == FileType_Sprite)
paint_clipboard_export_ramxfer_do(&ev, ((char *)clipdata) + 4, clipdata->size - 4);
else
paint_clipboard_export_ramxfer_do(&ev, draw_buffer, draw_length);
complete = TRUE;
break;
}
break;
}
}
if (draw_buffer) flex_free((flex_ptr)&draw_buffer);
}
This diff is collapsed.
/* Copyright 2019 RISC OS Open Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include "bbc.h"
#include "flex.h"
#include "werr.h"
#include "drawftypes.h"
#include "drawfdiag.h"
#include "drawfobj.h"
#include "sprite.h"
#include "main.h"
#include "Drawfile.h"
/* default settings for our layout */
#define XMIN 0
#define XMAX 675
#define GRID 75
#define SCALE 512
#define TOP 1000
static int drawfile_get_selection_length(main_window *window)
{
/* returns the required length for a drawfile export */
int size = sizeof(draw_fileheader);
/* iterate the selection and find the individual sprite lengths */
main_sprite *sprite;
sprite_header *entry;
for (sprite = window->data->file.sprites; sprite != NULL; sprite = sprite->link)
{ if (sprite->flags & MSF_SELECTED)
{ entry = (sprite_header *) ((char *)sprite->file->spritearea + sprite->offset);
size += sizeof(draw_spristrhdr) + sizeof(draw_spristr) + entry->next;
}
}
return size;
}
static int drawfile_get_clipboard_length(sprite_area *clipdata)
{
/* returns the required length for a drawfile export */
int size = sizeof(draw_fileheader);
int offset = clipdata->sproff;
int sprite;
for (sprite = 0; sprite < clipdata->number; sprite++)
{ sprite_header *spriteptr = (sprite_header *)((char *)clipdata + offset);
offset += spriteptr->next;
size += sizeof(draw_spristrhdr) + sizeof(draw_spristr) + spriteptr->next;
}
return size;
}
static BOOL drawfile_sprite_fits(char **buffer, int *end_offset, int width, int height, int x, int y)
{
/* see if the bounding box intersects an existing one... */
int xmax = width + x;
int ymax = height + y;
draw_spristrhdr *ptr;
for (ptr = (draw_spristrhdr *)(*buffer + sizeof(draw_fileheader));
ptr < (draw_spristrhdr *)(*buffer + *end_offset);
ptr = (draw_spristrhdr *)((char *)ptr + ptr->size))
if (!(ptr->bbox.x0 > xmax || ptr->bbox.x1 < x || ptr->bbox.y1 < y || ptr->bbox.y0 > ymax)) return FALSE;
return TRUE;
}
static void drawfile_find_gap(sprite_area *area, sprite_header *sprite, char **buffer, int *end_offset, draw_box *bbox)
{
/* Find a hole to position the sprite in */
/* We'll create as many rows as needed */
main_scaling_block mode;
int y = (TOP + GRID) * SCALE;
int x;
BOOL found = FALSE;
/* find sprite */
sprite_info info;
sprite_id id;
id.s.addr = (sprite_ptr) sprite;
id.tag = sprite_id_addr;
sprite_readsize(area, &id, &info);
/* work out scale factor for the sprite */
mode.scale_xmul = 1 << bbc_modevar (info.mode, bbc_XEigFactor);
mode.scale_xdiv = 2;
mode.scale_ymul = 1 << bbc_modevar (info.mode, bbc_YEigFactor);
mode.scale_ydiv = 2;
/* work out the bounding box for this sprite from its size and the scale factors */
bbox->x0 = 0;
bbox->y0 = 0;
bbox->x1 = (info.width * SCALE * mode.scale_xmul) / mode.scale_xdiv;
bbox->y1 = (info.height * SCALE * mode.scale_ymul) / mode.scale_ydiv;
while (!found)
{ y -= (GRID * SCALE);
for (x = XMIN * SCALE; x < XMAX * SCALE; x += GRID * SCALE)
if (drawfile_sprite_fits(buffer, end_offset, bbox->x1, bbox->y1, x, y))
{ found = TRUE;
bbox->x0 += x;
bbox->x1 += x;
bbox->y0 += y;
bbox->y1 += y;
break;
}
}
}
static BOOL drawfile_append_sprite(sprite_area *area, sprite_header *sprheader, char **buffer, int *offset)
{
/* Append sprite to drawfile */
draw_box bbox;
draw_spristrhdr *hdrptr;
draw_spristr *dataptr;
/* find a convenient location to place sprite in the output document */
drawfile_find_gap(area, sprheader, buffer, offset, &bbox);
/* append to the Drawfile. Memory has already been allocated */
/* generate our object */
hdrptr = (draw_spristrhdr *) (*buffer + *offset);
dataptr = (draw_spristr *) (hdrptr+1); /* +1 as pointer will add size of struct for us */
/* fill header */
hdrptr->tag = draw_OBJSPRITE;
hdrptr->size = sizeof(draw_spristrhdr) + sizeof(draw_spristr) + sprheader->next;
hdrptr->bbox = bbox;
/* copy in sprite */
memcpy(dataptr, sprheader, sprheader->next);
/* update offset for the next one */
*offset = *offset + hdrptr->size;
return TRUE;
}
static void drawfile_calc_bbox(char **buffer,int *length)
{
/* sort out the file bounding box from the individual components */
draw_fileheader *header = (draw_fileheader *)*buffer;
draw_spristrhdr *ptr;
header->bbox.y1 = header->bbox.x1 = 0;
header->bbox.y0 = header->bbox.x0 = 0x7fffffff;
/* iterate each object in the drawfile */
for (ptr = (draw_spristrhdr *)(*buffer + sizeof(draw_fileheader));
ptr < (draw_spristrhdr *)(*buffer + *length);
ptr = (draw_spristrhdr *)((char *)ptr + ptr->size))
{ if (header->bbox.x0 > ptr->bbox.x0) header->bbox.x0 = ptr->bbox.x0;
if (header->bbox.y0 > ptr->bbox.y0) header->bbox.y0 = ptr->bbox.y0;
if (header->bbox.x1 < ptr->bbox.x1) header->bbox.x1 = ptr->bbox.x1;
if (header->bbox.y1 < ptr->bbox.y1) header->bbox.y1 = ptr->bbox.y1;
}
/* and now move everything down the page */
for (ptr = (draw_spristrhdr *)(*buffer + sizeof(draw_fileheader));