Commits (24)
  • Robert Sprowson's avatar
    Minor debug fixes · fbb7e4e0
    Robert Sprowson authored
    PSprite.c: move the trace message up before the label, so if tb is NULL there isn't a NULL pointer dereference
    guard.c: refactor assert() to not check ptr!=0 a second time
    Found by cppcheck static analysis.
    Tagged as Paint-2_23-1 since both are debug code only.
    fbb7e4e0
  • ROOL's avatar
    Add clipboard/cut and paste to sprite filer · 3be21b3b
    ROOL authored
    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'
    3be21b3b
  • ROOL's avatar
    Tool idle event and trace bug fixes · eff0967c
    ROOL authored
    Long standing disable of idle events when they are needed. Steps to recreate:
    * Create a sprite with a palette
    * Paint a little with any brush tool
    * Go to Paint > Edit palette to open the colour picker (ensuring that the menu tree, the mouse, and the colour picker are within the bounds of the sprite view being painted)
    * Collapse the menu tree and carry on painting with the brush tool
    The brush tool now only produces output on click, not drag. This is because the idle events are no longer enabled, they were lost in merely opening the picker.
    
    "oh god a sprite window's gone walkies" observed in trace during development.
    Triggered when sprwindow_delete() is called when there's only one sprite window and you close it. This is because of an earlier change which commented out
      beforeus = /*(main_sprite_window *) &*/us->sprite->windows;
    The additional addressof operation would have introduced one extra iteration to the loop that followed (with the beforeus->link variable at offset 0, it would just dereference the pointer on the first iteration). Now the case of beforeus == us is explicitly checked.
    
    Submission for the Paint bounty.
    
    Version 2.25. Tagged as 'Paint-2_25'
    eff0967c
  • ROOL's avatar
    Colour handling enhancements · 18f461a5
    ROOL authored
    Detail:
      * Artist friendly colour ordering of 256 colour palette, and option to reorder pixel data for the remapped palette
      * Full 256 colour sprites can be created (as well as 64/16 entry VIDC compatible ones)
      * Colour indicator swatch in the bottom left corner of the sprite window
      * Adjust click on colours to paint with background colour
      * Shift-select as a shortcut to Paint > Select colour
      * Shift-adjust ditto for background colour
    Admin:
      Submission for the Paint bounty.
    
    Version 2.26. Tagged as 'Paint-2_26'
    18f461a5
  • ROOL's avatar
    Zoom resize, focus, and keyboard shortcuts · 6a84fc4e
    ROOL authored
    Detail:
      * Sprite editor windows gain input focus on first click (there's an option to disable this behaviour too)
      * Zoom with Ctrl+resize window (in addition to Ctrl+Scrollwheel already implemented)
      * Key shortcuts in Sprite editor windows
    Admin:
      Submission for the Paint bounty.
    
    Version 2.27. Tagged as 'Paint-2_27'
    6a84fc4e
  • ROOL's avatar
    Colour handling fixes · b886fe56
    ROOL authored
    Detail:
      * Menus rearranged so "Advanced" is renamed "Palette options"; "Extra click for input focus" moved to the Paint menu.
      * The "Highlight background colour" menu option has been removed to simplify the interface.
      * To address all the differences of opinion around the artist-friendly palette arrangement, the default behaviour is to not show the confirmation dialogue box plus a further menu option "Rearrange user palettes" (ticked by default).
        If the latter's unticked, the remapping to artist-friendly (upon Edit palette) will never take place; if it's ticked, the remapping will always take place except when the confirmation box is enabled and the user clicks Default.
      * Greyed out palette options when there's not a full/default 256-colour palette, as appropriate.
      * Help text updated to reflect these changes.
    Admin:
      Submission for the Paint bounty.
    
    Version 2.28. Tagged as 'Paint-2_28'
    b886fe56
  • ROOL's avatar
    Fix to artist friendly remapping · e137ee5d
    ROOL authored
    Detail:
      Remapping would never occur if the confirmation box was disabled.
    Admin:
      Submission for the Paint bounty.
    
    Version 2.28. Not tagged
    e137ee5d
  • ROOL's avatar
    Fix for camera and scissor tool in 'export' mode · 05b310f2
    ROOL authored
    Detail:
      * If the source sprite has an old-style bit mask, solid pixels in the exported sprite's mask may have a different value to the source sprite's. For example 0xFF -> 0xFC.
      * The OS seems to render such intermediate mask values inconsistently.
      Applicable GCOL commands have now replaced with OS_SetColour calls (taken from another fix elsewhere in the code that dates back to Acorn).
    Admin:
      See also https://www.riscosopen.org/forum/forums/4/topics/14698
      Submission for the Paint bounty.
    
    Version 2.29. Tagged as 'Paint-2_29'
    05b310f2
  • ROOL's avatar
    Promote width variable · 6ac43b06
    ROOL authored
    Detail:
      Promoted the colour panel variables used to store dimensions based off the window furniture sizes to use ints instead of chars as they could, at least theoretically, exceed 255 OS units on a custom desktop.
    Admin:
      Submission for the Paint bounty.
    6ac43b06
  • ROOL's avatar
    Open popup menus in Style Guide approved place · 33abefef
    ROOL authored
    Detail:
      In the create sprite dialogue the menus for colour/palette didn't open in the right place. Compute the offset as the Style Guide recommends.
    Admin:
      Submission for the Paint bounty.
    33abefef
  • ROOL's avatar
    Treat 'New sprite' as dialogue window · c8a3984c
    ROOL authored
    Detail:
      Now that there a popup menus on the create sprite window, it can't be used as a menu dialogue (because the Wimp only allows one window) from a submenu arrow. Change the menu entry to add an ellipsis and open it as a plain dialogue window.
    Admin:
      Submission for the Paint bounty.
    c8a3984c
  • ROOL's avatar
    Fix for left edge adjustment · ea656225
    ROOL authored
    Detail:
      Edge Adjustment of the left edge on Adjust size was broken due to copy/paste error.
    Admin:
      Submission for the Paint bounty.
    ea656225
  • ROOL's avatar
    Reduce redraws of colour panel · 9e2713db
    ROOL authored
    Detail:
      The colour panel swatch was being redrawn unnecessarily on every open window request due to not knowing whether the furniture icons had changed size. Now, only recalculate the sizes and force a redraw on a mode change event, this eliminates the flicker when moving the sprite window around.
    Admin:
      Submission for the Paint bounty.
    9e2713db
  • ROOL's avatar
    Improve reciprocity of zooming · 8b3c9626
    ROOL authored
    Detail:
      Previously a small (eg. 100x100) sprite being
      * zoomed in until it fills the screen
      * zoom 1:1
      * zoom in again
      would lead to a large black border in width as the sprite grew, but not in height. Now ensures the width is clamped to the minimum sprite width.
    Admin:
      Submission for the Paint bounty.
    
    Version 2.30. Tagged as 'Paint-2_30'
    8b3c9626
  • ROOL's avatar
    Messages update · bdc9c4ae
    ROOL authored
    Detail:
      Move the menu entry tokens out of the !Help messages section so they don't get tokenised.
    Admin:
      Submission for the Paint bounty.
    
    Version 2.30. Not tagged
    bdc9c4ae
  • Robert Sprowson's avatar
    Fix loading palettes to all new & 256 colour old sprites · 182c9f8d
    Robert Sprowson authored
    A check (marked DF-300) rejected any attempt to load a palette into a new (ie. RISC OS 3.50+) style sprite. This is bogus because bbc_modevar() is perfectly happy to process a sprite mode word and return Log2bpp, which is all that was required. Confirmed on RISC OS 3.50 with
      SYS"OS_ReadModeVariable",&202D0169,9 TO,,log2bpp
    which gives 3 for a 256 colour 180dpi sprite.
    Ref: https://www.riscosopen.org//forum/forums/4/topics/14966
    
    Second, a logic error introduced in Paint-2_26 meant that loading from a file any 256 entry palette (old or new sprite) would result in the palette being reset to the kernel default. This is because there are 2 callers of menus_set_palette() with non-NULL palette pointers, but only 1 wants a default palette. Signal this case by passing -256 entries.
    
    Version 2.31. Tagged as 'Paint-2_31'
    182c9f8d
  • Andy Vawer's avatar
    Fix issue dragging a selection to icon bar icons · 8fbf60c5
    Andy Vawer authored
    Send Wimp message to correct destination icon rather than the iconbar window.
    
    Version 2.32. Tagged as 'Paint-2_32'
    8fbf60c5
  • ROOL's avatar
    Fix for mask errors with camera/scissor tool · 1cf50826
    ROOL authored
    Detail:
      Longstanding bug where use of the camera or scissor tool in Export mode with 'new' 1bpp mask sprites didn't work. Change to use SpriteExtend's scaled mask op.
      Ref: https://www.riscosopen.org/tracker/tickets/481
    Admin:
      Submission for Paint bounty.
    1cf50826
  • ROOL's avatar
    Add wrap option to move sprite tool · b1f2d2db
    ROOL authored
    Detail:
      Implements a wrap option to the 'Move Sprite' tool, enabled via a check box.
      Code sharing with the camera/scissor tool via copy_to_temporary_sprite() and delete_temporary_sprite().
    Admin:
      Submission for the Paint bounty.
    
    Version 2.33. Tagged as 'Paint-2_33'
    b1f2d2db
  • ROOL's avatar
    Minor fixes · 420bdd39
    ROOL authored
    Detail:
      * Fix for 2 colours being editing when the palette is in artist friendly view
      * Disabled 'Rearrange user palette' option by default to keep confusion to a minimum
      * Remove ^P shortcut for 'Edit palette' which could cause a submenu error in some situations
    Admin:
      Submission for Paint bounty.
    
    Version 2.34. Tagged as 'Paint-2_34'
    420bdd39
  • Robert Sprowson's avatar
    Add choices dialogue, don't set Paint$Options · 5ddfba1a
    Robert Sprowson authored
    Messages/Templates: Extra interactive help, new menu templates, new choices dialogue.
    PaintChoice.c/h: New source file to handle the choices dialogue, also added to Makefile.
    
    Main.c/h: Transfer ownership of initial_options to PaintChoice.c. Delete setting & parsing of Paint$Options. Export - and constify - Matches() for use elsewhere. Define MAXZOOMFACTOR and replace 999's elsewhere.
    Menus.c: Remove advanced options menu, these are now in choices.
    MenuD.h: Defines for the iconbar menu, remove advanced options menu.
    
    Version 2.35. Tagged as 'Paint-2_35'
    5ddfba1a
  • Jeffrey Lee's avatar
    Sprite compatibility report fix · ab784d97
    Jeffrey Lee authored
    As documented in PRM5A, RISC OS 3.5 doesn't support new-format sprites
    which have masks. Update the sprite info dialogue "compatibility" field
    to reflect this, reporting that the sprite is compatible with RISC OS
    3.6 instead.
    ab784d97
  • Jeffrey Lee's avatar
    Adjust USBDriver scrollwheel fix · 25c1b2b6
    Jeffrey Lee authored
    Starting with USBDriver 1.30, the scrollwheel is now handled in a
    sensible manner, so there's no longer any need to ignore four out of
    every five wheel events.
    
    Version 2.36. Tagged as 'Paint-2_36'
    25c1b2b6
  • Robert Sprowson's avatar
    Fix for NULL pointer read on drag start · 3b247281
    Robert Sprowson authored
    The call to cnp_drag_restart_dragbox() needs the window member of current_drag_op set up, but was being used before it's set.
    Since the struct is memset to 0 before use, don't bother with the static initialiser.
    
    Version 2.37. Tagged as 'Paint-2_37'
    3b247281
......@@ -83,15 +83,13 @@ DFILES = \
debug.${APP}.Sprites\
debug.${APP}.Templates
OBJS = o.colours o.main o.menus o.psprite o.sprwindow o.tools o.toolwindow \
o.AltRename o.PaintLib
OBJSZ = oz.colours oz.main oz.menus oz.psprite oz.sprwindow\
oz.tools oz.toolwindow oz.AltRename oz.PaintLib
OBJSD = od.colours od.ftrace od.guard od.main od.menus\
OBJS = o.colourpanel o.colours o.main o.menus o.psprite o.sprwindow o.tools o.toolwindow \
o.AltRename o.PaintLib o.CnPDrag o.Clipboard o.Drawfile o.PaintChoice
OBJSZ = oz.colourpanel oz.colours oz.main oz.menus oz.psprite oz.sprwindow oz.tools\
oz.toolwindow oz.AltRename oz.PaintLib oz.CnPDrag oz.Clipboard oz.Drawfile oz.PaintChoice
OBJSD = od.colourpanel od.colours od.ftrace od.guard od.main od.menus\
od.psprite od.sprwindow od.tools od.toolwindow o.m\
od.AltRename od.PaintLib
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
od.AltRename od.PaintLib od.CnPDrag od.Clipboard od.Drawfile od.PaintChoice
#
# Rule patterns
......
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.37"
Module_Version SETA 237
Module_MinorVersion SETS ""
Module_Date SETS "11 Nov 2017"
Module_ApplicationDate SETS "11-Nov-17"
Module_Date SETS "10 Aug 2020"
Module_ApplicationDate SETS "10-Aug-20"
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.37"
Module_HelpVersion SETS "2.37 (10 Aug 2020)"
END
/* (2.23)
/* (2.37)
*
* 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_MinorVersion_CMHG
#define Module_Date_CMHG 11 Nov 2017
#define Module_MajorVersion_CMHG 2.37
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 10 Aug 2020
#define Module_MajorVersion "2.23"
#define Module_Version 223
#define Module_MajorVersion "2.37"
#define Module_Version 237
#define Module_MinorVersion ""
#define Module_Date "11 Nov 2017"
#define Module_Date "10 Aug 2020"
#define Module_ApplicationDate "11-Nov-17"
#define Module_ApplicationDate "10-Aug-20"
#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.37"
#define Module_HelpVersion "2.37 (10 Aug 2020)"
#define Module_LibraryVersionInfo "2:37"
......@@ -56,7 +56,7 @@ static void altrename_renamesprite (main_sprite *sprite, char *newname)
/* rename must reset the titles of all the windows open on
the sprite */
if (sprite->colourdialogue != NULL)
{ char new_title [80];
{ char new_title [128];
colourpicker_dialogue dialogue;
dialogue.title = new_title;
......@@ -88,6 +88,17 @@ static void altrename_renamesprite (main_sprite *sprite, char *newname)
redraw_str.box.y0 = wstate.o.box.y1;
wimpt_noerr (wimp_force_redraw (&redraw_str));
}
if (sprite->bgcolourdialogue != NULL)
{ char new_title [128];
colourpicker_dialogue dialogue;
dialogue.title = new_title;
sprintf (new_title, msgs_lookup ("PntWF"), newname);
ftracef0 ("ColourPicker_UpdateDialogue: setting new bgcolour title");
wimpt_complain (os_swix3 (ColourPicker_UpdateDialogue,
colourpicker_UPDATE_TITLE, sprite->bgcolourdialogue,
&dialogue));
}
}
void altrename_delete (void)
......
/* 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.
This diff is collapsed.
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));
ptr < (draw_spristrhdr *)(*buffer + *length);
ptr = (draw_spristrhdr *)((char *)ptr + ptr->size))
{ ptr->bbox.y0 -= header->bbox.y0;
ptr->bbox.y1 -= header->bbox.y0;
}
header->bbox.y1 -= header->bbox.y0;
header->bbox.y0 = 0;
}
BOOL clipboard_to_drawfile(sprite_area *clipdata, char **buffer, int *length)
{
/* Take the clipboard data and create a simple Drawfile */
draw_box bbox = {0,0,0,0};
int fileoffset;
draw_diag drawfile;
int offset = clipdata->sproff;
int sprite;
*length = drawfile_get_clipboard_length(clipdata); /* we can precalculate this easily */
if (flex_alloc((flex_ptr)buffer, *length) == 0)
{ werr (FALSE, "PntEG"); /* out of memory */
return FALSE;
}
drawfile.data = *buffer;
drawfile.length = *length;
draw_create_diag(&drawfile, "Paint", bbox);
fileoffset = sizeof(draw_fileheader);
for (sprite = 0; sprite < clipdata->number; sprite++)
{ sprite_header *spriteptr = (sprite_header *)((char *)clipdata + offset);
offset += spriteptr->next;
drawfile_append_sprite(clipdata, spriteptr, buffer, &fileoffset);
}
/* set up a final bounding box */
drawfile_calc_bbox(buffer, length);
return TRUE;
}
BOOL selection_to_drawfile(main_window *window, char **buffer, int *length)
{
/* Take the selected sprites and create a simple Drawfile from them */
draw_box bbox = {0,0,0,0};
main_sprite *sprite;
int offset;
draw_diag drawfile;
*length = drawfile_get_selection_length(window); /* we can precalculate this easily */
if (!flex_alloc((flex_ptr)buffer, *length))
{ werr (FALSE, "PntEG"); /* out of memory */
return FALSE;
}
drawfile.data = *buffer;
drawfile.length = *length;
draw_create_diag(&drawfile, "Paint", bbox);
offset = sizeof(draw_fileheader);
for (sprite = window->data->file.sprites; sprite != NULL; sprite = sprite->link)
if (sprite->flags & MSF_SELECTED)
drawfile_append_sprite(sprite->file->spritearea, (sprite_header *)(((char *)sprite->file->spritearea) + sprite->offset), buffer, &offset);
/* set up a final bounding box */
drawfile_calc_bbox(buffer, length);
return TRUE;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.