home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / desklib / examples / DeskLib / Examples / Widget5 / !Widget5 / c / SpriteWin < prev    next >
Encoding:
Text File  |  1995-05-10  |  36.5 KB  |  1,248 lines

  1. /************************************************************************
  2.  *                                                                      *
  3.  *        File: SpriteWin.c                                             *
  4.  *                                                                      *
  5.  *     Purpose: Store 256 grey level arbitrary sized images in 6 'image *
  6.  *              banks' and display them in a window using a pixel       *
  7.  *              colour translation table to map the grey levels to the  *
  8.  *              screen palette if required.                             *
  9.  *                                                                      *
  10.  ************************************************************************/
  11.  
  12. #include "DeskLib:WimpSWIs.h"          /* Low-level WIMP commands         */
  13. #include "DeskLib:Window.h"            /* Window handling automation      */
  14. #include "DeskLib:Core.h"              /* usefull core functions          */
  15. #include "DeskLib:Error.h"             /* Error despatcher                */
  16. #include "DeskLib:Event.h"             /* Event despatcher                */
  17. #include "DeskLib:EventMsg.h"          /* Wimp Message event dispatcher   */
  18. #include "DeskLib:File.h"              /* Low level file handling         */
  19. #include "DeskLib:Msgs.h"              /* Message translation code        */
  20. #include "DeskLib:Resource.h"          /* Handles finding resource files  */
  21. #include "DeskLib:Sound.h"             /* Beep!                           */
  22. #include "DeskLib:Template.h"          /* Template loading and caching    */
  23. #include "DeskLib:Icon.h"              /* Icon handling automation        */
  24. #include "DeskLib:Menu.h"              /* Menu create & show support      */
  25. #include "DeskLib:Screen.h"            /* Caching screen info             */
  26. #include "DeskLib:Sprite.h"            /* Sprite handling routines        */
  27. #include "DeskLib:File.h"              /* OS file IO                      */
  28. #include "DeskLib:KeyCodes.h"          /* Codes for wimp returned keys    */
  29.  
  30. #include "Dialog2:Dialog2.h"           /* windows on menus made easy      */
  31.  
  32. #include "HackLib:flex.h"              /* Flexable malloc                 */
  33.  
  34. #include "Pane.h"                      /* Panes with less pain            */
  35.  
  36. #include "ATrans.h"                    /* My load/save library            */
  37.  
  38. #include "kernel.h"                    /* clib kernel functions           */
  39. #include "MySWIs.h"                    /* SWI no defs                     */
  40. #include "SpriteWin.h"
  41. #include "Misc.h"
  42. #include "LoadSave.h"
  43. #include "ProcessWin.h"
  44. #include "GraphWin.h"
  45. #include "Widget5.h"
  46. #include "Configure.h"
  47.  
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51.  
  52. /* debug window */
  53. extern window_handle db;
  54.  
  55. /* size of palette in sprite */
  56. #define sizeof_PALETTE 2048
  57.  
  58. /* some common sprite details */
  59. #define Mode 21 /* 256 colours */
  60. #define Colours 256
  61. #define SpriteName "widget5pic"
  62.  
  63. #define image_OFFSET 2108
  64.  
  65. /* array to hold 256 grey level palette */
  66. static palette_entry GreyscalePalette[Colours];
  67.  
  68. /* array to hold image bank info */
  69. static spritewin_block *imageblock[number_IMAGES];
  70.  
  71. extern int *imageblockadd = (int *) &imageblock[0];
  72.  
  73. /* menu for image bank window */
  74. static menu_ptr imagewindowmenu = NULL;
  75. static menu_ptr savemenu = NULL;
  76. static menu_ptr processmenu = NULL;
  77. static menu_ptr graphmenu = NULL;
  78.  
  79. static currentimageno = 0; /* it's sad isn't it! */
  80.  
  81. #define imagewindowmenu_IMAGEINFO 0
  82. #define imagewindowmenu_SAVE      1
  83. #define imagewindowmenu_PROCESS   2
  84. #define imagewindowmenu_GRAPH     3
  85. #define imagewindowmenu_ZOOM      4
  86.  
  87. /* zoom window */
  88. static dialog2_block *zoomwindow;
  89. /* max and min scalefactors for zoom window */
  90. #define scale_MAX 50
  91. #define scale_MIN 1
  92.  
  93. /* save windows */
  94. #define savemenu_SPRITE  0
  95. #define savemenu_WIDGET5 1
  96. #define savemenu_WIDGET4 2
  97. static dialog2_block *save;
  98. static dialog2_block *savewidget5;
  99.  
  100. /* image info window */
  101. static dialog2_block *imageinfo;
  102.  
  103. static BOOL Redraw(event_pollblock *event, void *reference);
  104. static BOOL Click(event_pollblock *event, void *reference);
  105. static BOOL Click_zoomwindow(event_pollblock *event, void *reference);
  106. static BOOL Click_savesprite(event_pollblock *event, void *reference);
  107. static BOOL Click_savewidget4(event_pollblock *event, void *reference);
  108. static BOOL Click_savewidget5(event_pollblock *event, void *reference);
  109. static BOOL Key_savesprite(event_pollblock *event, void *reference);
  110. static BOOL Key_savewidget4(event_pollblock *event, void *reference);
  111. static BOOL Key_savewidget5(event_pollblock *event, void *reference);
  112. static BOOL Key_zoomwindow(event_pollblock *event, void *reference);
  113. static BOOL BuildPixTransTable(event_pollblock *event, void *reference);
  114. static BOOL ModeChange(event_pollblock *event, void *reference);
  115. static BOOL CloseWindow(event_pollblock *event, void *reference);
  116. static BOOL Menuwarn(event_pollblock *event, void *reference);
  117. static BOOL MenuChoice(event_pollblock *event, void *reference);
  118. void build_pixtranstable(spritewin_block *block);
  119. void NotEnoughMem(void);
  120. void DragToSave(void);
  121. void scale_image(int multiplier, int divisor, spritewin_block *block);
  122. void update_screenscale(spritewin_block *block);
  123.  
  124. /******************************************************************************
  125.  *                            extern routines                                 *
  126.  ******************************************************************************/
  127.  
  128. extern void SpriteWin_Init(void)
  129. {
  130.  /*
  131.   * initialisation to be done on startup
  132.   */
  133.   int colour;
  134.   int imageno;
  135.   char menudescription[260];
  136.   char menutitle[15];
  137.  
  138.  /*
  139.   * initialise 256 level greyscale sprite palette
  140.   */
  141.   for(colour = 0; colour < Colours; colour++){
  142.  
  143.       GreyscalePalette[colour].data.gcol = 0;
  144.       GreyscalePalette[colour].data.red = colour;
  145.       GreyscalePalette[colour].data.green = colour;
  146.       GreyscalePalette[colour].data.blue = colour;
  147.  
  148.   }
  149.  
  150.  /*
  151.   * initialise image blocks so that all images are unused
  152.   */
  153.   for(imageno = 0; imageno < number_IMAGES; imageno++)
  154.      imageblock[imageno] = NULL;
  155.  
  156.  /*
  157.   * build menus
  158.   */
  159.   Msgs_Lookup("title.image", menutitle, 15);
  160.   Msgs_Lookup("menu.image", menudescription, 260);
  161.   imagewindowmenu = Menu_New(menutitle, menudescription);
  162.  
  163.   Msgs_Lookup("title.save", menutitle, 15);
  164.   Msgs_Lookup("menu.save", menudescription, 260);
  165.   savemenu = Menu_New(menutitle, menudescription);
  166.   Menu_MakeWarn(imagewindowmenu, imagewindowmenu_SAVE, !fullversion);
  167.   if(fullversion)
  168.      Menu_AddSubMenu(imagewindowmenu, imagewindowmenu_SAVE, savemenu);
  169.  
  170.   Msgs_Lookup("title.process", menutitle, 15);
  171.   Msgs_Lookup("menu.process", menudescription, 260);
  172.   processmenu = Menu_New(menutitle, menudescription);
  173.   Menu_AddSubMenu(imagewindowmenu, imagewindowmenu_PROCESS, processmenu);
  174.  
  175.   Msgs_Lookup("title.graph", menutitle, 15);
  176.   Msgs_Lookup("menu.graph", menudescription, 260);
  177.   graphmenu = Menu_New(menutitle, menudescription);
  178.   Menu_AddSubMenu(imagewindowmenu, imagewindowmenu_GRAPH, graphmenu);
  179.  
  180.   Event_Claim(event_MENU, event_ANY, event_ANY, MenuChoice, NULL);
  181.  
  182.  /*
  183.   * initialise dialog box structs
  184.   */
  185.   save = Dialog2_CreateDialogBlock( "Save", 42, 42, NULL, NULL, NULL);
  186.   if(fullversion)
  187.      savewidget5 = Dialog2_CreateDialogBlock( "SaveWidget5", 42, 42, NULL, NULL, NULL);
  188.   imageinfo = Dialog2_CreateDialogBlock( "ImageInfo", 42, 42, NULL, NULL, NULL);
  189.   zoomwindow = Dialog2_CreateDialogBlock( "Zoom", 42, 42, NULL, NULL, NULL);
  190.   EventMsg_Claim(message_MENUWARNING, event_ANY, Menuwarn, NULL);
  191.  
  192. }
  193.  
  194. /******************************************************************************/
  195.  
  196. extern void SpriteWin_InitBlock(spritewin_block *block, int imageno)
  197. {
  198.  
  199.   block->imageno = imageno; /* used for reference only */
  200.   block->spritearea = NULL;
  201.   block->size.x = 0;
  202.   block->size.y = 0;
  203.  
  204. }
  205.  
  206. /******************************************************************************/
  207.  
  208. extern BOOL SpriteWin_FreeImage(int imageno)
  209. {
  210.  /*
  211.   * returns TRUE if the image is free
  212.   */
  213.   return(imageblock[imageno] == NULL);
  214. }
  215.  
  216. /******************************************************************************/
  217.  
  218. extern BOOL SpriteWin_SameSize(wimp_point *res, int imageno)
  219. {
  220.  /*
  221.   * returns TRUE if image is same size as 'res'
  222.   */
  223.   return( (imageblock[imageno]->size.x == res->x) &&
  224.           (imageblock[imageno]->size.y == res->y) );
  225. }
  226.  
  227. /******************************************************************************/
  228.  
  229. extern BOOL SpriteWin_Identical(int image1, int image2)
  230. {
  231.  /*
  232.   * returns TRUE if both images are the same size
  233.   */
  234.   return( (imageblock[image1]->size.x == imageblock[image2]->size.x) &&
  235.           (imageblock[image1]->size.y == imageblock[image2]->size.y) );
  236.  
  237. }
  238.  
  239. /******************************************************************************/
  240.  
  241. extern wimp_point *SpriteWin_GetSize(int imageno)
  242. {
  243.  /*
  244.   * returns the size of the image 'imageno'
  245.   */
  246.  
  247.   return( &imageblock[imageno]->size );
  248. }
  249.  
  250. /******************************************************************************/
  251.  
  252. extern int SpriteWin_GetPixel(wimp_point *pos, int imageno)
  253. {
  254.  /*
  255.   * returns the grey level value of the pixel at 'pos' in image bank 'imageno'
  256.   */
  257.   return(((char *)imageblock[imageno]->spritearea)[image_OFFSET +
  258.                                   pos->x + (pos->y * imageblock[imageno]->linebytes)]);
  259.  /*
  260.   return (Sprite_ReadPixel(imageblock[imageno].spritearea, SpriteName, pos));
  261.   */
  262. }
  263.  
  264. /******************************************************************************/
  265.  
  266. extern void SpriteWin_PutPixel(wimp_point *pos, int pixel, int imageno)
  267. {
  268.  /*
  269.   * sets the grey level of the pixel at 'pos' to 'pixel' in image bank 'imageno'
  270.   */
  271.  
  272.   ((char *)imageblock[imageno]->spritearea)[image_OFFSET +
  273.                            pos->x + (pos->y * imageblock[imageno]->linebytes)] = pixel;
  274.   
  275.  /*
  276.   Sprite_WritePixel(imageblock[imageno].spritearea, SpriteName, pos, pixel, 0);
  277.   */
  278. }
  279.  
  280. /******************************************************************************/
  281.  
  282. extern spritewin_block *SpriteWin_GetImageBlock(int imageno)
  283. {
  284.  /*
  285.   * returns a pointer to the spritewin_block for image bank 'imageno'
  286.   */
  287.  
  288.   return(imageblock[imageno]);
  289. }
  290.  
  291. /******************************************************************************/
  292.  
  293. extern BOOL SpriteWin_AddImageBlock(spritewin_block *block, int imageno)
  294. {
  295.  /*
  296.   * adds the image bank info block 'block' to the list of image banks
  297.   * returns FALSE if bank in use
  298.   */
  299.  
  300.   if(imageblock[imageno] != NULL)
  301.      return(FALSE);
  302.  
  303.   imageblock[imageno] = block;
  304.   block->imageno = imageno;
  305.  
  306.   return(TRUE);
  307.  
  308. }
  309.  
  310. /******************************************************************************/
  311.  
  312. extern void SpriteWin_RefreshWin(int imageno)
  313. {
  314.  /*
  315.   * refreshes the window of the image bank 'imageno'
  316.   */
  317.   window_state windowstate;
  318.  
  319.   if(imageblock[imageno] == NULL)
  320.      return;
  321.  
  322.  /*
  323.   * refresh window (the sad way)
  324.   */
  325.   Wimp_GetWindowState(imageblock[imageno]->window, &windowstate);
  326.   Wimp_CloseWindow(imageblock[imageno]->window);
  327.   Wimp_OpenWindow(&windowstate.openblock);
  328.  
  329. }
  330.  
  331. /******************************************************************************/
  332.  
  333. extern void SpriteWin_RemoveImageBlock(int imageno)
  334. {
  335.  /*
  336.   * removes the image bank info block 'block' from the list of image banks
  337.   */
  338.  
  339.   imageblock[imageno] = NULL;
  340.  
  341. }
  342.  
  343. /******************************************************************************/
  344.  
  345. extern void SpriteWin_CloseSaveWidget5(void)
  346. {
  347.   Dialog2_CloseDialog(savewidget5);
  348. }
  349.  
  350. /******************************************************************************/
  351.  
  352. extern void SpriteWin_CloseSave(void)
  353. {
  354.   Dialog2_CloseDialog(save);
  355. }
  356.  
  357. /******************************************************************************
  358.  *                                open handlers                               *
  359.  ******************************************************************************/
  360.  
  361. extern BOOL SpriteWin_Create(wimp_point *res, int imageno)
  362. {
  363.  /*
  364.   * creates image at size 'res' in image bank 'imageno' and displays the window
  365.   * exits quietly if the image bank is already used
  366.   */
  367.   spritewin_block *block;
  368.  
  369.  /*
  370.   * return if bank in use
  371.   */
  372.   if(imageblock[imageno] != NULL)
  373.      return(FALSE);
  374.  
  375.  /*
  376.   * allocate memory for image bank info block
  377.   * return FALSE if fails
  378.   */
  379.   block = malloc(sizeof(spritewin_block));
  380.   if(block == NULL){
  381.      NotEnoughMem();
  382.      return(FALSE);
  383.   }
  384.   SpriteWin_InitBlock(block, imageno);
  385.  
  386.  /*
  387.   * add image bank info block to list
  388.   */
  389.   SpriteWin_AddImageBlock(block, imageno);
  390.   
  391.  /*
  392.   * create image but if fails the deallocate memory for image bank info block
  393.   */
  394.   if( !SpriteWin_CreateImage(block, res) ){
  395.      SpriteWin_RemoveImageBlock(imageno);
  396.      free(block);
  397.      return(FALSE);
  398.   }
  399.  
  400.   SpriteWin_CreateWindow(block);
  401.  
  402.   return(TRUE);
  403. }
  404.  
  405. /******************************************************************************/
  406.  
  407. extern BOOL SpriteWin_CreateImage(spritewin_block *block, wimp_point *res)
  408. {
  409.  /*
  410.   * creates image in image bank info block 'block'
  411.   * returns FALSE if fails
  412.   */
  413.   int size;
  414.   sprite_header *header;
  415.   palette_entry *palette;
  416.   int colour;
  417.   char *image;
  418.   int imagesize;
  419.  
  420.  /*
  421.   * return if image already used
  422.   */
  423.   if(block->spritearea != NULL)
  424.      return(FALSE);
  425.  
  426.  /*
  427.   * work out the memory required for the sprite area
  428.   * total memory is 'size' bytes for sprite area
  429.   * 'imagesize' is size of image pixel data in bytes
  430.   */
  431.   size = Sprite_MemorySize(res->x, res->y, Mode, sprite_HASNOMASKPAL);
  432.   imagesize = size - sizeof(sprite_header);
  433.   size += sizeof(sprite_areainfo); /* add sprite area header size */
  434.   size += sizeof_PALETTE; /* add 256 colour palette size */
  435.  
  436.  /*
  437.   * allocate memory for sprite area
  438.   */
  439.   flex_alloc((flex_ptr) &block->spritearea, size);
  440.   if(block->spritearea == NULL){
  441.      NotEnoughMem();
  442.      return(FALSE);
  443.   }
  444.  
  445.  /*
  446.   * initialise sprite area header for no sprites
  447.   */
  448.   (block->spritearea)->areasize = size;
  449.   (block->spritearea)->numsprites = 0;
  450.   (block->spritearea)->firstoffset = 16;
  451.   (block->spritearea)->freeoffset = 16;
  452.  
  453.  /*
  454.   * create blank sprite with no palette in sprite area
  455.   */
  456.   Sprite_Create(block->spritearea, SpriteName, sprite_HASNOMASKPAL, res->x, res->y, Mode);
  457.  
  458.  /*
  459.   * 'header' points to start of sprite header
  460.   * 'palette' points to start of sprite palette
  461.   * 'image' points to start of image pixel data
  462.   */
  463.   header = (void *) ((char *)block->spritearea + (block->spritearea)->firstoffset);
  464.   palette = (void *) ((char *)header + sizeof(sprite_header));
  465.   image = (void *) ((char *)palette + sizeof_PALETTE);
  466.  
  467.  /*
  468.   * insert 256 entry palette into sprite
  469.   */
  470.   memmove(image, image - sizeof_PALETTE, imagesize);
  471.  
  472.   header->imageoffset += sizeof_PALETTE;
  473.   header->maskoffset += sizeof_PALETTE;
  474.   header->offset_next += sizeof_PALETTE;
  475.   block->spritearea->freeoffset += sizeof_PALETTE;
  476.  
  477.  /*
  478.   * set palette to 256 level greyscale
  479.   */
  480.   for(colour = 0; colour < Colours; colour++){
  481.  
  482.       palette->value = GreyscalePalette[colour].value;
  483.       palette++;
  484.       palette->value = GreyscalePalette[colour].value;
  485.       palette++;
  486.   }
  487.  
  488.  /*
  489.   * initialise rest of image bank info block
  490.   * scale is set to 1:1
  491.   * plot position in window and set so that image is lined up with edges
  492.   */
  493.   block->scale.multiply.x = 1;
  494.   block->scale.multiply.y = 1;
  495.   block->scale.divide.x = 1;
  496.   block->scale.divide.y = 1;
  497.   update_screenscale(block);
  498.   block->plotcoord.x = 0;
  499.   block->plotcoord.y = -(res->y * 2);
  500.   block->size = *res;
  501.   block->header =  (char *) header - (char *) block->spritearea;
  502.   block->image =  (char *) image - (char *) block->spritearea;
  503.   block->linebytes = (header->width + 1) * 4;
  504.  
  505.   return(TRUE);
  506. }
  507.  
  508. /******************************************************************************/
  509.  
  510. extern void SpriteWin_CreateWindow(spritewin_block *block)
  511. {
  512.  /*
  513.   * create window for image bank info block 'block'
  514.   */
  515.   window_info windowinfo;
  516.   wimp_box newworkarea;
  517.   char windowtitle[10];
  518.  
  519.  /*
  520.   * create window, set size
  521.   */
  522.   block->window = Window_Create("Image", template_TITLEMIN);
  523.   Window_GetInfo(block->window, &windowinfo);
  524.   newworkarea = windowinfo.block.workarearect;
  525.   newworkarea.min.y = 0 - (block->size.y * 2);
  526.   newworkarea.max.x = block->size.x * 2;
  527.   Wimp_SetExtent(block->window, &newworkarea);
  528.  
  529.  /*
  530.   * set window title to be "Image X" where X is the image bank number
  531.   */
  532.   sprintf(windowtitle, "Image %i", block->imageno);
  533.   Window_SetTitle(block->window, windowtitle);
  534.  
  535.  /*
  536.   * initialise pixel translation table for current screen palette
  537.   */
  538.   build_pixtranstable(block);
  539.  
  540.  /*
  541.   * install event handlers and display window
  542.   */
  543.   Event_Claim(event_REDRAW, block->window, event_ANY, Redraw, block);
  544.   Event_Claim(event_CLOSE, block->window, event_ANY, CloseWindow, block);
  545.   Event_Claim(event_CLICK, block->window, event_ANY, Click, block);
  546.   EventMsg_Claim(message_PALETTECHANGE, block->window, BuildPixTransTable, block);
  547.   EventMsg_Claim(message_MODECHANGE, block->window, BuildPixTransTable, block);
  548.   EventMsg_Claim(message_MODECHANGE, block->window, ModeChange, block);
  549.   Window_Show(block->window, open_WHEREVER);
  550.  
  551. }
  552.  
  553. /******************************************************************************
  554.  *                               close handlers                               *
  555.  ******************************************************************************/
  556.  
  557. static BOOL CloseWindow(event_pollblock *event, void *reference)
  558. {
  559.  /*
  560.   * called when window is closed to delete the window, free the memory used to
  561.   * store the image and set the image bank as unused
  562.   */
  563.   spritewin_block *block = reference;
  564.  
  565.   Window_Delete(block->window);
  566.  
  567.   SpriteWin_RemoveImageBlock(block->imageno);
  568.  
  569.   flex_free((flex_ptr) &block->spritearea);
  570.  
  571.   free(block);
  572.   
  573.   return(TRUE);
  574. }
  575.  
  576. /******************************************************************************
  577.  *                              Click handlers                                *
  578.  ******************************************************************************/
  579.  
  580. static BOOL Click(event_pollblock *event, void *reference)
  581. {
  582.   spritewin_block *block = reference;
  583.   char menutitle[10];
  584.  
  585.   currentimageno = block->imageno;
  586.  
  587.   if(event->data.mouse.button.data.menu){
  588.     /*
  589.      * set menu title to reflect image number of image bank
  590.      */
  591.      sprintf(menutitle, "Image %i", block->imageno);
  592.      strncpy(imagewindowmenu->title, menutitle, wimp_MAXNAME);
  593.  
  594.     /*
  595.      * release old menuwarn event handler
  596.      */
  597.      EventMsg_Release(message_MENUWARNING, event_ANY, Menuwarn);
  598.  
  599.     /*
  600.      * install new menuwarn event handler with correct pointer to image bank info block
  601.      */
  602.      EventMsg_Claim(message_MENUWARNING, event_ANY, Menuwarn, block);
  603.  
  604.     /*
  605.      * grey out save widget4 if it is not a 256x256 or 512x512 image
  606.      */
  607.      if( ((block->size.x == 256) && (block->size.y == 256)) ||
  608.          ((block->size.x == 512) && (block->size.y == 512)) )
  609.         Menu_SetFlags(savemenu, savemenu_WIDGET4, 0, 0); /* not shaded */
  610.      else
  611.         Menu_SetFlags(savemenu, savemenu_WIDGET4, 0, 1); /* shaded */
  612.  
  613.      Menu_Show(imagewindowmenu, event->data.mouse.pos.x,event->data.mouse.pos.y);
  614.   }
  615.  
  616.  
  617. /*
  618.   if(event->data.mouse.button.data.select)
  619.  
  620.   if(event->data.mouse.button.data.adjust)
  621. */
  622.  
  623.   return(TRUE);
  624. }
  625.  
  626. /******************************************************************************/
  627.  
  628. static BOOL Click_zoomwindow(event_pollblock *event, void *reference)
  629. {
  630.   spritewin_block *block = reference;
  631.  
  632.   switch(event->data.mouse.icon)
  633.   {
  634.     case 0: /* up multiplier */
  635.        if(event->data.mouse.button.data.select)
  636.           inc_icon(zoomwindow->window, 4, scale_MAX);
  637.        if(event->data.mouse.button.data.adjust)
  638.           dec_icon(zoomwindow->window, 4, scale_MIN);
  639.        break;
  640.  
  641.     case 1: /* down multiplier */
  642.        if(event->data.mouse.button.data.select)
  643.           dec_icon(zoomwindow->window, 4, scale_MIN);
  644.        if(event->data.mouse.button.data.adjust)
  645.           inc_icon(zoomwindow->window, 4, scale_MAX);
  646.        break;
  647.  
  648.     case 2: /* up divisor */
  649.        if(event->data.mouse.button.data.select)
  650.           inc_icon(zoomwindow->window, 5, scale_MAX);
  651.        if(event->data.mouse.button.data.adjust)
  652.           dec_icon(zoomwindow->window, 5, scale_MIN);
  653.        break;
  654.  
  655.     case 3: /* down divisor */
  656.        if(event->data.mouse.button.data.select)
  657.           dec_icon(zoomwindow->window, 5, scale_MIN);
  658.        if(event->data.mouse.button.data.adjust)
  659.           inc_icon(zoomwindow->window, 5, scale_MAX);
  660.        break;
  661.   }
  662.  
  663.   if((event->data.mouse.icon >= 0) && (event->data.mouse.icon <= 3))
  664.        scale_image(Icon_GetInteger(zoomwindow->window, 4),
  665.                    Icon_GetInteger(zoomwindow->window, 5), block);
  666.      
  667.   return(TRUE);
  668. }
  669.  
  670. /******************************************************************************/
  671.  
  672. static BOOL Click_savesprite(event_pollblock *event, void *reference)
  673. {
  674.   spritewin_block *block = reference;
  675.  
  676.   switch(event->data.mouse.icon)
  677.   {
  678.     case 0: /* file icon */
  679.       if(event->data.mouse.button.value == button_DRAGSELECT){
  680.          LoadSave_SetSaveBank(block->imageno, 256);
  681.          ATrans_startdrag(Icon_GetTextPtr(save->window, 1),
  682.                           filetype_SPRITE, 1024, save->window, 0, usericonsprites);
  683.          }
  684.       break;
  685.   
  686.     case 2: /* save */
  687.       if(strchr(Icon_GetTextPtr(save->window, 1), '.') == 0)
  688.          DragToSave();
  689.       else{
  690.          LoadSave_SetSaveBank(block->imageno, 256);
  691.          LoadSave_savefile(Icon_GetTextPtr(save->window, 1), filetype_SPRITE, TRUE);
  692.         if(!event->data.mouse.button.data.adjust)
  693.            Dialog2_CloseDialog(save);
  694.       }
  695.       break;
  696.  
  697.     case 3: /* cancel */
  698.       Dialog2_CloseDialog(save);
  699.       break;
  700.   }
  701.  
  702.      
  703.   return(TRUE);
  704. }
  705.  
  706. /******************************************************************************/
  707.  
  708. static BOOL Click_savewidget4(event_pollblock *event, void *reference)
  709. {
  710.   spritewin_block *block = reference;
  711.  
  712.   switch(event->data.mouse.icon)
  713.   {
  714.     case 0: /* file icon */
  715.       if(event->data.mouse.button.value == button_DRAGSELECT){
  716.          LoadSave_SetSaveBank(block->imageno, 256);
  717.          ATrans_startdrag(Icon_GetTextPtr(save->window, 1),
  718.                           filetype_WIDGET4, 1024, save->window, 0, usericonsprites);
  719.          }
  720.       break;
  721.   
  722.     case 2: /* save */
  723.       if(strchr(Icon_GetTextPtr(save->window, 1), '.') == 0)
  724.          DragToSave();
  725.       else{
  726.          LoadSave_SetSaveBank(block->imageno, 256);
  727.          LoadSave_savefile(Icon_GetTextPtr(save->window, 1), filetype_WIDGET4, TRUE);
  728.         if(!event->data.mouse.button.data.adjust)
  729.            Dialog2_CloseDialog(save);
  730.       }
  731.       break;
  732.  
  733.     case 3: /* cancel */
  734.       Dialog2_CloseDialog(save);
  735.       break;
  736.   }
  737.  
  738.      
  739.   return(TRUE);
  740. }
  741.  
  742. /******************************************************************************/
  743.  
  744. static BOOL Click_savewidget5(event_pollblock *event, void *reference)
  745. {
  746.   spritewin_block *block = reference;
  747.   int numbergreys = 1;
  748.  
  749.   switch(event->data.mouse.icon)
  750.   {
  751.     case 0: /* file icon */
  752.       if(event->data.mouse.button.value == button_DRAGSELECT){
  753.          if(Icon_GetSelect(savewidget5->window, 4))
  754.             numbergreys = 128;
  755.          if(Icon_GetSelect(savewidget5->window, 5))
  756.             numbergreys = 256;
  757.          LoadSave_SetSaveBank(block->imageno, numbergreys);
  758.          ATrans_startdrag(Icon_GetTextPtr(savewidget5->window, 1),
  759.                           filetype_WIDGET5, 1024, savewidget5->window, 0,usericonsprites);
  760.          }
  761.       break;
  762.   
  763.     case 2: /* save */
  764.       if(strchr(Icon_GetTextPtr(savewidget5->window, 1), '.') == 0)
  765.          DragToSave();
  766.       else{
  767.          if(Icon_GetSelect(savewidget5->window, 4))
  768.             numbergreys = 128;
  769.          if(Icon_GetSelect(savewidget5->window, 5))
  770.             numbergreys = 256;
  771.          LoadSave_SetSaveBank(block->imageno, numbergreys);
  772.          LoadSave_savefile(Icon_GetTextPtr(savewidget5->window, 1),filetype_WIDGET5,TRUE);
  773.          if(!event->data.mouse.button.data.adjust)
  774.             Dialog2_CloseDialog(savewidget5);
  775.       }
  776.       break;
  777.  
  778.     case 3: /* cancel */
  779.       Dialog2_CloseDialog(savewidget5);
  780.       break;
  781.  
  782.     case 4: case 5:
  783.       Icon_Select(savewidget5->window, event->data.mouse.icon);
  784.       break;
  785.  
  786.   }
  787.      
  788.   return(TRUE);
  789. }
  790.  
  791. /******************************************************************************
  792.  *                             keypress handlers                              *
  793.  ******************************************************************************/
  794.  
  795. static BOOL Key_zoomwindow(event_pollblock *event, void *reference)
  796. {
  797.   spritewin_block *block = reference;
  798.  
  799.   if(event->data.key.caret.icon == 5){
  800.  
  801.      if(event->data.key.code == keycode_RETURN){
  802.  
  803.         scale_image(Icon_GetInteger(zoomwindow->window, 4),
  804.                     Icon_GetInteger(zoomwindow->window, 5), block);
  805.  
  806.      }
  807.  
  808.   }
  809.  
  810.   return(TRUE);
  811.  
  812. }
  813.  
  814. /******************************************************************************/
  815.  
  816. static BOOL Key_savesprite(event_pollblock *event, void *reference)
  817. {
  818.   spritewin_block *block = reference;
  819.  
  820.   if(event->data.key.caret.icon == 1){
  821.  
  822.      if(event->data.key.code == keycode_RETURN){
  823.  
  824.         if(strchr(Icon_GetTextPtr(save->window, 1), '.') == 0)
  825.            DragToSave();
  826.         else{
  827.            LoadSave_SetSaveBank(block->imageno, 256);
  828.            LoadSave_savefile(Icon_GetTextPtr(save->window, 1), filetype_SPRITE, TRUE);
  829.            Dialog2_CloseDialog(save);
  830.         }
  831.  
  832.      }
  833.  
  834.   }
  835.  
  836.   return(TRUE);
  837.  
  838. }
  839.  
  840. /******************************************************************************/
  841.  
  842. static BOOL Key_savewidget5(event_pollblock *event, void *reference)
  843. {
  844.   spritewin_block *block = reference;
  845.   int numbergreys;
  846.  
  847.   if(event->data.key.caret.icon == 1){
  848.  
  849.      if(event->data.key.code == keycode_RETURN){
  850.  
  851.         if(strchr(Icon_GetTextPtr(savewidget5->window, 1), '.') == 0)
  852.            DragToSave();
  853.         else{
  854.            if(Icon_GetSelect(savewidget5->window, 4))
  855.               numbergreys = 128;
  856.            if(Icon_GetSelect(savewidget5->window, 5))
  857.               numbergreys = 256;
  858.            LoadSave_SetSaveBank(block->imageno, numbergreys);
  859.          LoadSave_savefile(Icon_GetTextPtr(savewidget5->window, 1),filetype_WIDGET5,TRUE);
  860.            Dialog2_CloseDialog(savewidget5);
  861.         }
  862.  
  863.      }
  864.  
  865.   }
  866.  
  867.   return(TRUE);
  868.  
  869. }
  870.  
  871. /******************************************************************************/
  872.  
  873. static BOOL Key_savewidget4(event_pollblock *event, void *reference)
  874. {
  875.   spritewin_block *block = reference;
  876.  
  877.   if(event->data.key.caret.icon == 1){
  878.  
  879.      if(event->data.key.code == keycode_RETURN){
  880.  
  881.         if(strchr(Icon_GetTextPtr(save->window, 1), '.') == 0)
  882.            DragToSave();
  883.         else{
  884.            LoadSave_SetSaveBank(block->imageno, 256);
  885.            LoadSave_savefile(Icon_GetTextPtr(save->window, 1), filetype_WIDGET4, TRUE);
  886.            Dialog2_CloseDialog(save);
  887.         }
  888.  
  889.         Icon_SetCaret(zoomwindow->window, 4);
  890.      }
  891.  
  892.   }
  893.  
  894.   return(TRUE);
  895.  
  896. }
  897.  
  898. /******************************************************************************
  899.  *                            MenuWarn handlers                               *
  900.  ******************************************************************************/
  901.  
  902. static BOOL Menuwarn(event_pollblock *event, void *reference)
  903. {
  904.   spritewin_block *block = reference;
  905.  
  906.   if(menu_currentopen != imagewindowmenu)
  907.      return(FALSE);
  908.  
  909.   switch(event->data.message.data.menuwarn.selection[0])
  910.   {
  911.  
  912.     case imagewindowmenu_IMAGEINFO:
  913.       Dialog2_OpenDialogMenuLeaf(event, imageinfo);
  914.       Icon_SetInteger(imageinfo->window, 3, block->size.x);
  915.       Icon_SetInteger(imageinfo->window, 4, block->size.y);
  916.       Icon_printf(imageinfo->window, 5, "%i K",
  917.                           flex_size((flex_ptr) &block->spritearea) / 1024);
  918.       return(TRUE);
  919.       break;
  920.  
  921.     case imagewindowmenu_SAVE:
  922.  
  923.       if(fullversion){
  924.  
  925.          switch(event->data.message.data.menuwarn.selection[1])
  926.          {
  927.            case savemenu_SPRITE:
  928.              Dialog2_OpenDialogMenuLeaf(event, save);
  929.              Icon_SetText(save->window, 1, "Sprite");
  930.              Icon_SetFileType(save->window, 0, filetype_SPRITE);
  931.              Event_Claim(event_CLICK, save->window, event_ANY, Click_savesprite, block);
  932.              Event_Claim(event_KEY, save->window, event_ANY, Key_savesprite, block);
  933.              return(TRUE);
  934.              break;
  935.                                                                     
  936.            case savemenu_WIDGET5:
  937.              Dialog2_OpenDialogMenuLeaf(event, savewidget5);
  938.              Icon_Select(savewidget5->window, 5); /* default to 256 colours */
  939.            Event_Claim(event_CLICK,savewidget5->window,event_ANY,Click_savewidget5,block);
  940.              Event_Claim(event_KEY, savewidget5->window, event_ANY,Key_savewidget5,block);
  941.              return(TRUE);
  942.              break;
  943.  
  944.            case savemenu_WIDGET4:
  945.              Dialog2_OpenDialogMenuLeaf(event, save);
  946.              Icon_SetText(save->window, 1, "Widget4");
  947.              Icon_SetFileType(save->window, 0, filetype_WIDGET4);
  948.              Event_Claim(event_CLICK, save->window, event_ANY, Click_savewidget4, block);
  949.              Event_Claim(event_KEY, save->window, event_ANY, Key_savewidget4, block);
  950.              return(TRUE);
  951.              break;
  952.          }
  953.       }
  954.  
  955.       else{ /* just open savesprite instead of save type menu */
  956.          Dialog2_OpenDialogMenuLeaf(event, save);
  957.          Icon_SetText(save->window, 1, "Sprite");
  958.          Icon_SetFileType(save->window, 0, filetype_SPRITE);
  959.          Event_Claim(event_CLICK, save->window, event_ANY, Click_savesprite, block);
  960.          Event_Claim(event_KEY, save->window, event_ANY, Key_savesprite, block);
  961.          return(TRUE);
  962.       }
  963.       break;
  964.  
  965.     case imagewindowmenu_ZOOM:
  966.       Dialog2_OpenDialogMenuLeaf(event, zoomwindow);
  967.       Event_Claim(event_CLICK, zoomwindow->window, event_ANY, Click_zoomwindow, block);
  968.       Event_Claim(event_KEY, zoomwindow->window, event_ANY, Key_zoomwindow, block);
  969.       Icon_SetInteger(zoomwindow->window, 4, block->scale.multiply.x);
  970.       Icon_SetInteger(zoomwindow->window, 5, block->scale.divide.x);
  971.       Icon_SetCaret(zoomwindow->window, 4);
  972.       return(TRUE);
  973.       break;
  974.       
  975.   }
  976.  
  977.   return(FALSE);
  978. }
  979.  
  980. /******************************************************************************
  981.  *                           menu choice handlers                             *
  982.  ******************************************************************************/
  983.  
  984. static BOOL MenuChoice(event_pollblock *event, void *reference)
  985. {
  986.   mouse_block ptr;
  987.  
  988.   if (menu_currentopen != imagewindowmenu) /* Only respond to the imagewindowmenu */
  989.     return(FALSE);
  990.  
  991.  
  992.   switch(event->data.selection[0])
  993.   {
  994.      case imagewindowmenu_PROCESS:
  995.         if(event->data.selection[1] != -1)
  996.            ProcessWin_Start(event->data.selection[1], currentimageno);
  997.         break;
  998.  
  999.      case imagewindowmenu_GRAPH:
  1000.         if(event->data.selection[1] != -1)
  1001.            GraphWin_Start(event->data.selection[1], currentimageno);
  1002.         break;
  1003.  
  1004.   }
  1005.  
  1006.   Wimp_GetPointerInfo(&ptr);               /* If ADJUST was used to select, */
  1007.   if (ptr.button.data.adjust)              /* then we keep the menu open.   */
  1008.     Menu_ShowLast();
  1009.  
  1010.   return(TRUE);
  1011. }
  1012.  
  1013. /******************************************************************************
  1014.  *                        palette change handlers                             *
  1015.  ******************************************************************************/
  1016.  
  1017. static BOOL BuildPixTransTable(event_pollblock *event, void *reference)
  1018. {
  1019.   /*
  1020.    * called on palette change to recalculate pixel translation table
  1021.    */
  1022.  
  1023.    build_pixtranstable((spritewin_block *)reference);
  1024.  
  1025.    return(FALSE);
  1026. }
  1027.  
  1028. /******************************************************************************/
  1029.  
  1030. void build_pixtranstable(spritewin_block *block)
  1031. {
  1032.  /*
  1033.   * calculates pixel translation table for current screen palette
  1034.   * code taken from PRMs Vol. 1 Page 834
  1035.   */
  1036.   sprite_header *header;
  1037.   palette_entry *palette;
  1038.   int q;
  1039.   _kernel_swi_regs r;
  1040.  
  1041.   header = (void *) ((char *)block->spritearea + (block->spritearea)->firstoffset);
  1042.  
  1043.   if(header->imageoffset == 44){
  1044.  
  1045.      palette = 0;
  1046.   }
  1047.   else{
  1048.  
  1049.      palette = (palette_entry *)&GreyscalePalette;
  1050.   }
  1051.  
  1052.   for(q = 0; q < 256; q++){
  1053.  
  1054.      block->pixtransbuffer[q] = q;
  1055.  
  1056.   }
  1057.  
  1058.   if(header->imageoffset == 44 + 2048){
  1059.  
  1060.      for(q = 0; q < 256; q++){
  1061.  
  1062.          r.r[0] = (int)GreyscalePalette[q].value;
  1063.          Error_Check((os_error *)
  1064.                  _kernel_swi( SWI_XOS_Bit | SWI_ColourTrans_ReturnColourNumber, &r, &r ));
  1065.          block->pixtransbuffer[q] = r.r[0];
  1066.      }
  1067.   }
  1068.   else{
  1069.  
  1070.      r.r[0] = Mode;
  1071.      r.r[1] = (int)palette;
  1072.      r.r[2] = -1;
  1073.      r.r[3] = -1;
  1074.      r.r[4] = (int)&block->pixtransbuffer;
  1075.      Error_Check((os_error *)
  1076.                  _kernel_swi( SWI_XOS_Bit | SWI_ColourTrans_SelectTable, &r, &r ));
  1077.   }
  1078.  
  1079.   block->pixtranstable = (char *)-1;
  1080.   for(q = 0; q < 256; q++){
  1081.  
  1082.       if(block->pixtransbuffer[q] != q)
  1083.          block->pixtranstable = (char *)&block->pixtransbuffer;
  1084.   }
  1085.      
  1086. }
  1087.  
  1088. /******************************************************************************
  1089.  *                          mode change handlers                              *
  1090.  ******************************************************************************/
  1091.  
  1092. static BOOL ModeChange(event_pollblock *event, void *reference)
  1093. {
  1094.   spritewin_block *block = reference;
  1095.  
  1096.   update_screenscale(block);
  1097.  
  1098.   return(FALSE);
  1099. }
  1100.  
  1101. /******************************************************************************
  1102.  *                            redraw handlers                                 *
  1103.  ******************************************************************************/
  1104.  
  1105. static BOOL Redraw(event_pollblock *event, void *reference)
  1106. {
  1107.  /*
  1108.   * called to redraw the image window
  1109.   */
  1110.   window_redrawblock redraw;
  1111.   BOOL more;
  1112.   spritewin_block *block = reference;
  1113.   _kernel_swi_regs r;
  1114.  
  1115.   redraw.window = event->data.openblock.window;
  1116.   Wimp_RedrawWindow(&redraw, &more);
  1117.  
  1118.   while (more)
  1119.   {
  1120.  
  1121.     r.r[0] = 52 + 256;
  1122.     r.r[1] = (int)block->spritearea;
  1123.     r.r[2] = (int)SpriteName;
  1124.     r.r[3] = (block->plotcoord.x - redraw.scroll.x) + redraw.rect.min.x;
  1125.     r.r[4] = (block->plotcoord.y - redraw.scroll.y) + redraw.rect.max.y;
  1126.     r.r[5] = 0;
  1127.     r.r[6] = (int)&block->screenscale;
  1128.     r.r[7] = (int)block->pixtranstable;
  1129.     
  1130.     Error_Check((os_error *)
  1131.               _kernel_swi( SWI_XOS_Bit | SWI_OS_SpriteOp , &r, &r ));
  1132.                                                         
  1133.     Wimp_GetRectangle(&redraw, &more);
  1134.   }
  1135.  
  1136.   return(TRUE);
  1137. }
  1138.  
  1139. /******************************************************************************
  1140.  *                             misc routines                                  *
  1141.  ******************************************************************************/
  1142.  
  1143. void NotEnoughMem(void)
  1144. {
  1145.   char err_msg[128];
  1146.  
  1147.   Msgs_Lookup("err.nomemspr", err_msg, 127);
  1148.   Error_Report(1,err_msg);
  1149.  
  1150. }
  1151.  
  1152. /******************************************************************************/
  1153.  
  1154. void DragToSave(void)
  1155. {
  1156.   char msg[128];
  1157.  
  1158.   Msgs_Lookup("msg.noleaf", msg, 127);
  1159.   Error_Report(1,msg);
  1160.  
  1161. }
  1162.  
  1163. /******************************************************************************/
  1164.  
  1165. void scale_image(int multiplier, int divisor, spritewin_block *block)
  1166. {
  1167.   window_info windowinfo;
  1168.   wimp_box newworkarea;
  1169.   window_state windowstate;
  1170.   
  1171.  /*
  1172.   * change scaleing factors for image
  1173.   */
  1174.   block->scale.multiply.x = multiplier;
  1175.   block->scale.multiply.y = multiplier;
  1176.   block->scale.divide.x = divisor;
  1177.   block->scale.divide.y = divisor;
  1178.   update_screenscale(block);
  1179.  
  1180.  /*
  1181.   * change window area to reflect new image size
  1182.   */
  1183.   Window_GetInfo(block->window, &windowinfo);
  1184.   newworkarea = windowinfo.block.workarearect;
  1185.   newworkarea.min.y = 0 - ( (block->size.y * 2 * multiplier) / divisor );
  1186.   newworkarea.max.x = (block->size.x * 2 * multiplier ) / divisor;
  1187.   Wimp_SetExtent(block->window, &newworkarea);
  1188.  
  1189.  /*
  1190.   * change plot position in window to reflect new image size
  1191.   */
  1192.   block->plotcoord.x = 0;
  1193.   block->plotcoord.y = -( (block->size.y * 2 * multiplier) / divisor );
  1194.  
  1195.  /*
  1196.   * refresh image and window size (the sad way)
  1197.   */
  1198.   Wimp_GetWindowState(block->window, &windowstate);
  1199.   Wimp_CloseWindow(block->window);
  1200.   Wimp_OpenWindow(&windowstate.openblock);
  1201.   
  1202. }
  1203.  
  1204. /******************************************************************************/
  1205.  
  1206. void update_screenscale(spritewin_block *block)
  1207. {
  1208.   Screen_CacheModeInfo();
  1209.  
  1210.   switch(screen_eig.x)
  1211.   {
  1212.     case 0:
  1213.       block->screenscale.multiply.x = block->scale.multiply.x * 2;
  1214.       block->screenscale.divide.x = block->scale.divide.x;
  1215.       break;
  1216.  
  1217.     case 1:
  1218.       block->screenscale.multiply.x = block->scale.multiply.x;
  1219.       block->screenscale.divide.x = block->scale.divide.x;
  1220.       break;
  1221.  
  1222.     case 2:
  1223.       block->screenscale.multiply.x = block->scale.multiply.x;
  1224.       block->screenscale.divide.x = block->scale.divide.x * 2;
  1225.       break;
  1226.   }
  1227.  
  1228.   switch(screen_eig.y)
  1229.   {
  1230.     case 0:
  1231.       block->screenscale.multiply.y = block->scale.multiply.y * 2;
  1232.       block->screenscale.divide.y = block->scale.divide.y;
  1233.       break;
  1234.  
  1235.     case 1:
  1236.       block->screenscale.multiply.y = block->scale.multiply.y;
  1237.       block->screenscale.divide.y = block->scale.divide.y;
  1238.       break;
  1239.  
  1240.     case 2:
  1241.       block->screenscale.multiply.y = block->scale.multiply.y;
  1242.       block->screenscale.divide.y = block->scale.divide.y * 2;
  1243.       break;
  1244.   }
  1245.  
  1246. }
  1247.  
  1248.