home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / gamesuite_1 / GameSuite / Sources / FSPConv / c / !FSPConv
Encoding:
Text File  |  1995-08-24  |  57.1 KB  |  2,498 lines

  1. /* FSPConv Application */
  2. /* A. Southgate 1993 */
  3. /* Originally Compiled with Norcroft C 3.00 */
  4. /* There's a bit of a bodge going on here.
  5. The upshot is that horizontal locking is dodgy unless either all or none
  6. of the h-lock toggles are set */
  7.  
  8.  
  9. #include "wimp.h"
  10. #include "wimpt.h"
  11. #include "win.h"
  12. #include "baricon.h"
  13. #include "event.h"
  14. #include "res.h"
  15. #include "resspr.h"
  16. #include "template.h"
  17. #include "os.h"
  18. #include "dbox.h"
  19. #include "dboxquery.h"
  20. #include "menu.h"
  21. #include "flex.h"
  22. #include "heap.h"
  23. #include "werr.h"
  24. #include "visdelay.h"
  25. #include "xfersend.h"
  26. #include "xferrecv.h"
  27. #include "colourtran.h"
  28. #include "coords.h"
  29. #include "bbc.h"
  30. #include <stdlib.h>
  31. #include <string.h>
  32.  
  33.  
  34.  
  35. #define Prog_name "FSPConv"
  36. #define Prog_spr_name "!FSPConv"
  37. #define Version_string "2.12 (25th April 1995)"
  38. #define Wimp_sprite_area 1
  39.  
  40. #define XOS_File 0x20008
  41. #define XOS_SpriteOp 0x2002e
  42. #define XWimp_StartTask 0x600de
  43. #define XWimp_DecodeMenu 0x600d5
  44. #define Sprite_filetype 0x0ff9
  45. #define FastSpr_filetype 0x0113
  46. #define FSPConv_max_name 255
  47. #define FSPConv_null_name "Null"
  48. #define Max_frame 16
  49. #define Fastspr_filetype 0x113
  50.  
  51. #define ModeVars_LineLength 6
  52. #define Modevars_Log2BPP 9
  53.  
  54. /* Menu Items */
  55.  
  56. #define Bar_menu_info 0
  57. #define Bar_menu_transp 1
  58. #define Bar_menu_convert 2
  59. #define Bar_menu_help 3
  60. #define Bar_menu_quit 4
  61. #define Sprite_menu_convert 0
  62. #define Sprite_menu_fake 1
  63. #define Sprite_menu_discard 2
  64. #define Sprite_menu_help 3
  65.  
  66.  
  67. #define Isprite_number 6
  68. #define Isprite_frame 10
  69. #define Isprite_xsize 13
  70. #define Isprite_ysize 14
  71. #define Isprite_mode 15
  72. #define Isprite_xcent 17
  73. #define Isprite_ycent 21
  74. #define Isprite_sprite 0
  75. #define Isprite_name 29
  76. #define Isprite_type 31
  77. #define Isprite_typemenu 32
  78. #define Isprite_preshift 33
  79. #define Isprite_pre0 34
  80. #define Isprite_pre1 35
  81. #define Isprite_pre2 36
  82. #define Isprite_pre3 37
  83. #define Isprite_premenu 38
  84. #define Isprite_all 39
  85. #define Isprite_hlock 40
  86. #define Isprite_none 41
  87. #define Isprite_str 42
  88. #define Isprite_stm 43
  89.  
  90. #define Ispeed_preludetime 2
  91. #define Ispeed_stmtime 3
  92. #define Ispeed_strtime 4
  93. #define Ispeed_strbtime 5
  94. #define Ispeed_toaltime 6
  95. #define Ispeed_stmopt 7
  96. #define Ispeed_stropt 8
  97. #define Ispeed_unclipped 9
  98. #define Ispeed_rightclip 10
  99. #define Ispeed_leftclip 11
  100. #define Ispeed_bothclip 12
  101. #define Ispeed_cancel 13
  102. #define Ispeed_calculate 14
  103.  
  104. #define Iconvert_fileicon 4
  105. #define Iconvert_filename 6
  106. #define Iconvert_filetype 9
  107. #define Iconvert_sourcesize 11
  108. #define Iconvert_outputsize 14
  109. #define Iconvert_cancel 10
  110. #define Iconvert_convert 8
  111. #define Iconvert_message 15
  112. #define Iconvert_getlength 16
  113.  
  114. #define Itransp_transp 1
  115.  
  116. #define Ifake_fake 1
  117. #define Ifake_use  2
  118.  
  119. #define Centre_menu_centre 0
  120. #define Centre_menu_left 1
  121. #define Centre_menu_right 2
  122. #define Centre_menu_top 3
  123. #define Centre_menu_bottom 4
  124. #define Centre_menu_topleft 5
  125. #define Centre_menu_topright 6
  126. #define Centre_menu_bottomleft 7
  127. #define Centre_menu_bottomright 8
  128. #define Centre_menu_all 9
  129. #define Centre_menu_help 10
  130.  
  131. #define Type_menu_fsp1 0
  132. #define Type_menu_fsp2 1
  133. #define Type_menu_help 2
  134.  
  135. #define Preshift_menu_all 0
  136. #define Preshift_menu_none 1
  137. #define Preshift_menu_just0 2
  138. #define Preshift_menu_0and2 3
  139. #define Preshift_menu_appall 4
  140. #define Preshift_menu_help 5
  141. #define Preshift_menu_hlock 6 /* Not a real menu item */
  142.  
  143. #define Smask_0 1
  144. #define Smask_1 2
  145. #define Smask_2 4
  146. #define Smask_3 8
  147. #define Smask_stm 16
  148. #define Smask_str 32
  149.  
  150.  
  151.  
  152. typedef enum {
  153.   M_iconbar,
  154.   M_sprite_number,
  155.   M_sprite_frame,
  156.   M_sprite_centre,
  157.   M_sprite_preshift,
  158.   M_sprite_type,
  159.   M_sprite_normal
  160. } Menu_type;
  161.  
  162. typedef struct {
  163.   char  id[4];
  164.   int   res1;
  165.   int   basemode;
  166.   int   number;
  167. } FSP1_header;
  168.  
  169. typedef struct {
  170.   char  id[4];
  171.   int   number;
  172.   int   basemode;
  173. } FSP2_header;
  174.  
  175. typedef struct {
  176.   int   entry[1];
  177. } FSP2_offset;
  178.  
  179. typedef struct {
  180.   char  xsize[1];
  181.   char  ysize[1];
  182.   char  xofs[1];
  183.   char  yofs[1];
  184. } FSP1_entry;
  185. #define Sizeof_FSP1_entry 4
  186.  
  187. typedef struct {
  188.   short ysize;  /* Reversed because of how short works */
  189.   short xsize;
  190.   short yofs;
  191.   short xofs;
  192.   int   stmofs;
  193.   int   strofs;
  194.   int   strbofs;
  195.   int   advofs;
  196.   int   data[1];
  197. } FSP2_entry;
  198. #define Sizeof_FSP2_entry 24
  199.  
  200.  
  201. typedef struct {
  202.   FSP1_header   header;
  203.   FSP1_entry    entry[1];
  204. } FSP1_file;
  205.  
  206. typedef struct {
  207.   FSP2_header   header;
  208.   FSP2_offset   ofs;
  209.   FSP2_entry    entry[1];
  210. } FSP2_file;
  211.  
  212. typedef struct {
  213.   int   width;
  214.   int   height;
  215.   int   bwidth;
  216.   int   rbytes;
  217.   int   hbytes;
  218. } Conv_det;
  219.  
  220. typedef struct {
  221.   BOOL          loaded;
  222.   BOOL          saved;
  223.   int           size;
  224.   int           number;
  225.   int           last_number;
  226.   int           last_frame;
  227.   int           frame;
  228.   int           no_frames;
  229.   sprite_area   *area;
  230.   sprite_id     id;
  231.   char          name[12];
  232.   char          filename[FSPConv_max_name];
  233. } Conv_sprites;
  234.  
  235. typedef struct {
  236.   int           number;
  237.   int           total;
  238.   int           max;
  239. } Conv_info_header;
  240.  
  241. typedef struct {
  242.   int           number;
  243.   int           frames;
  244.   int           xcent[Max_frame];
  245.   int           ycent[Max_frame];
  246.   int           type;
  247. } Conv_info_entry;
  248.  
  249. /* Change info_size if you alter this */
  250.  
  251. typedef struct {
  252.   Conv_info_header      header;
  253.   Conv_info_entry       entry[1];
  254. } Conv_info;
  255.  
  256. /*  Globals  */
  257. static Conv_sprites conv_sprites;
  258. static Conv_info *conv_info=0;
  259. static wimp_w sprite_whandle;
  260. static dbox sprite_dbox;
  261. static dbox convert_dbox;
  262. static char save_filename[255];
  263. static sprite_pixtrans trans[256];
  264. static menu bar_menu,
  265.             sprite_menu,
  266.             sprite_number_menu,
  267.             sprite_frame_menu,
  268.             sprite_centre_menu,
  269.             sprite_preshift_menu,
  270.             sprite_type_menu;
  271.  
  272. static Menu_type menu_type;
  273.  
  274. static int transp = 0;
  275. static int fsp_type = 1;
  276. static int lastcentre = 9;
  277.  
  278. static int      fsp_ofs;
  279. static int      anim_ofs;
  280. static int      spr_ofs;
  281. static char     *fsp_area_ptr;
  282. static char     **fsp_area = &fsp_area_ptr;
  283.  
  284. static int      fsp_area_size = 0;
  285. static int      conv_no =-1;
  286. static int     fakemode=13;
  287. static BOOL    fake_use=FALSE;
  288. static BOOL     convert_dbox_open = FALSE;
  289. static BOOL     conv_info_valid = FALSE;
  290. static BOOL     convert_getlength;
  291.  
  292. static char *typestr1 = "FSP1";
  293. static char *typestr2 = "FSP2";
  294. static char *typestr3 = "FSP?";
  295.  
  296. static int sequence_length[17] =
  297. {0,1,2,4,4,8,8,8,8,16,16,16,16,16,16,16,16};
  298.  
  299. static char sequence[17][16] =
  300. {
  301.  {0},
  302.  {0},
  303.  {0,1},
  304.  {0,1,2,1},
  305.  {0,1,2,3},
  306.  {0,1,2,3,4,3,2,1},
  307.  {0,1,2,3,4,5,5,5},
  308.  {0,1,2,3,4,5,6,6},
  309.  {0,1,2,3,4,5,6,7},
  310.  {0,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1},
  311.  {0,1,2,3,4,5,6,7,8,9,9,9,9,9,9,9},
  312.  {0,1,2,3,4,5,6,7,8,9,10,10,10,10,10,10},
  313.  {0,1,2,3,4,5,6,7,8,9,10,11,11,11,11,11},
  314.  {0,1,2,3,4,5,6,7,8,9,10,11,12,12,12,12},
  315.  {0,1,2,3,4,5,6,7,8,9,10,11,12,13,13,13},
  316.  {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,14},
  317.  {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
  318. };
  319.  
  320. /* -----Coding -----*/
  321.  
  322. static void quad_align(int *ptr, int value)
  323. {
  324.   int inc, i;
  325.   inc = 12 - ((value) & 15);
  326.   for (i=0; i<inc; i+=4)
  327.     *(int *)&(*fsp_area)[value + i] = 0x00120969;
  328.   *ptr += inc;
  329. }
  330.  
  331. static void start_task(char *filename)
  332. {
  333.   wimpt_complain(os_swi1(XWimp_StartTask, (int) filename));
  334. }
  335.  
  336. static void limit(int *ptr, int lowlim, int highlim)
  337. {
  338.   if (*ptr < lowlim) *ptr=lowlim;
  339.   if (*ptr > highlim) *ptr=highlim;
  340. }
  341.  
  342.  
  343. static void read_trans(int mode)
  344. {
  345.   wimpt_checkmode();
  346.   wimpt_complain(colourtran_select_table(mode, 0, -1,
  347.                     (wimp_paletteword *)-1, trans));
  348. }
  349.  
  350. static int scan_conv_info(int n)
  351. {
  352.   int i;
  353.   if (!conv_info_valid) return -1;
  354.   for (i=0; i<conv_info->header.number; i++)
  355.     if (conv_info->entry[i].number == n) return i;
  356.   return -1;
  357. }
  358.  
  359. static sprite_id * current_id(Conv_sprites *s)
  360. {
  361.   int e;
  362.  
  363. /* return pronto if details already correct */
  364.  
  365.   if (s->number == s->last_number && s->frame == s->last_frame) return &s->id;
  366.  
  367.   if (conv_info_valid && (e=scan_conv_info(s->number), e != -1))
  368.   {
  369.  
  370.     if (conv_info->entry[e].frames > 1)
  371.       sprintf(s->name,"%d_%d",s->number, s->frame);
  372.     else
  373.       sprintf(s->name,"%d",s->number);
  374.   }
  375.   else
  376.   {
  377.       sprintf(s->name,"%d",s->number);
  378.   }
  379.  
  380.   s->id.s.name=s->name;
  381.   s->id.tag=sprite_id_name;
  382.   s->last_frame=s->frame;
  383.   s->last_number=s->number;
  384.   return &s->id;
  385. }
  386.  
  387. static sprite_id * conv_id(Conv_sprites *s, Conv_info_entry *e, int f)
  388. {
  389.   if (e->frames > 1)
  390.     sprintf(s->name,"%d_%d",e->number, (int) sequence[e->frames][f]);
  391.   else
  392.     sprintf(s->name,"%d",e->number);
  393.  
  394.   s->id.s.name=s->name;
  395.   s->id.tag=sprite_id_name;
  396.   return &s->id;
  397. }
  398.  
  399. static void redraw_sprite_window(Conv_sprites *d)
  400. {
  401.   wimp_redrawstr r;
  402.   coords_cvtstr *c;
  403.   sprite_info sinfo;
  404.   int x,y,div;
  405.   BOOL more = TRUE;
  406.   sprite_factors factors;
  407.   sprite_pixtrans pixtrans[256];
  408.   wimp_icon icon;
  409.  
  410. /* Set pointer for coords */
  411.  
  412.   c=(coords_cvtstr *) &r.box;
  413.   r.w = sprite_whandle;
  414.   wimpt_noerr(wimp_redraw_wind(&r, &more));
  415.   if (d->loaded && (sprite_select(d->area, current_id(d)) == 0))
  416.   {
  417. /* Plot a sprite */
  418. /* Get icon infomation */
  419.  
  420.     wimpt_noerr(wimp_get_icon_info(sprite_whandle, Isprite_sprite, &icon));
  421.     x=16+coords_x_toscreen(icon.box.x0, c);
  422.     y=16+coords_y_toscreen(icon.box.y0, c);
  423.     wimpt_noerr(sprite_readsize(d->area, current_id(d), &sinfo));
  424.  
  425.  
  426.     read_trans(sinfo.mode);
  427.     wimpt_noerr(wimp_readpixtrans(d->area, current_id(d), &factors, pixtrans));
  428.  
  429.     factors.xmag = abs(icon.box.x1-icon.box.x0-32)/wimpt_dx();
  430.     factors.ymag = abs(icon.box.y1-icon.box.y0-32)/wimpt_dy();
  431.  
  432.     if (sinfo.width>sinfo.height)
  433.     {
  434.       div=sinfo.width;
  435.     }
  436.     else
  437.     {
  438.       div=sinfo.height;
  439.     }
  440.     factors.xdiv=div;
  441.     factors.ydiv=div;
  442.  
  443.     while (more)
  444.     {
  445.       wimpt_noerr(sprite_put_scaled(conv_sprites.area, &conv_sprites.id, 0,x, y, &factors, trans));
  446.  
  447.       wimp_get_rectangle(&r, &more);
  448.     }
  449.   }
  450.   else
  451.   {
  452.     while (more)
  453.     {
  454.       wimp_get_rectangle(&r, &more);
  455.     }
  456.   }
  457. }
  458. /*
  459.  
  460. static BOOL create_window(char *name, wimp_w *handle)
  461. {
  462.   wimp_wind *window;
  463.  
  464.   window = template_syshandle(name);
  465.  
  466.   if (window == 0) return FALSE;
  467.   return (wimpt_complain(wimp_create_wind(window, handle)) == 0);
  468. }
  469.  
  470.  
  471. static void open_window(wimp_w whandle)
  472. {
  473.   wimp_wstate state;
  474.   if (wimpt_complain(wimp_get_wind_state(whandle, &state)) == 0)
  475.   {
  476.     state.o.behind = -1;
  477.     wimpt_noerr(wimp_open_wind(&state.o));
  478.   }
  479. }
  480.  
  481. static void redraw_window(wimp_w w)
  482. {
  483.   wimp_redrawstr r;
  484.   r.w=w;
  485.   wimpt_complain(wimp_getwindowoutline(&r));
  486.   r.w=-1;
  487.   wimpt_complain(wimp_force_redraw(&r));
  488. }
  489. */
  490. static void sprites_dispose(Conv_sprites *s)
  491. {
  492.   if (s->loaded)
  493.   {
  494.     /* Free old memory */
  495.     flex_free((flex_ptr) &s->area);
  496.     s->size = 0;
  497.   }
  498.  
  499.   /* Cancel loaded flag and clear name */
  500.   s->loaded = FALSE;
  501.   if (conv_info_valid) flex_free((flex_ptr) &conv_info);
  502.  
  503.   conv_info_valid = FALSE;
  504.   s->last_number=-1;
  505.   win_settitle(sprite_whandle, "No Sprites");
  506. }
  507.  
  508. static char *type_string(void)
  509. {
  510.   switch (fsp_type)
  511.   {
  512.     case 1:
  513.       return typestr1;
  514.  
  515.     case 2:
  516.       return typestr2;
  517.  
  518.     default:
  519.       return typestr3;
  520.   }
  521. }
  522.  
  523.  
  524. static void fillin_sprite_window(dbox d, Conv_sprites *s)
  525. {
  526.   int e, type;
  527.   current_id(s);
  528.   dbox_setnumeric(d,Isprite_number,s->number);
  529.   dbox_setfield(d, Isprite_name, s->name);
  530.   dbox_setfield(d, Isprite_type, type_string());
  531.   if (fsp_type == 1)
  532.   {
  533.     dbox_fadefield(d, Isprite_pre0);
  534.     dbox_fadefield(d, Isprite_pre1);
  535.     dbox_fadefield(d, Isprite_pre2);
  536.     dbox_fadefield(d, Isprite_pre3);
  537.     dbox_fadefield(d, Isprite_str);
  538.     dbox_fadefield(d, Isprite_stm);
  539.   }
  540.   else
  541.   {
  542.     dbox_unfadefield(d, Isprite_pre0);
  543.     dbox_unfadefield(d, Isprite_pre1);
  544.     dbox_unfadefield(d, Isprite_pre2);
  545.     dbox_unfadefield(d, Isprite_pre3);
  546.     dbox_unfadefield(d, Isprite_str);
  547.     dbox_unfadefield(d, Isprite_stm);
  548.   }
  549.  
  550.   e=scan_conv_info(s->number);
  551.   if (s->loaded && e != -1 && (sprite_select(s->area, current_id(s)) == 0))
  552.   {
  553.     sprite_info sinfo;
  554.     sprite_readsize(s->area, current_id(s), &sinfo);
  555.     dbox_setnumeric(d,Isprite_xsize,sinfo.width);
  556.     dbox_setnumeric(d,Isprite_ysize,sinfo.height);
  557.     dbox_setnumeric(d,Isprite_mode,sinfo.mode);
  558.  
  559.     dbox_setnumeric(d,Isprite_xcent,conv_info->entry[e].xcent[s->frame]);
  560.     dbox_setnumeric(d,Isprite_ycent,conv_info->entry[e].ycent[s->frame]);
  561.     if (conv_info->entry[e].frames > 1)
  562.     {
  563.       dbox_setnumeric(d,Isprite_frame,s->frame);
  564.       dbox_unfadefield(d, Isprite_frame);
  565.     }
  566.     else
  567.     {
  568.       dbox_setfield(d,Isprite_frame,"-");
  569.       dbox_fadefield(d, Isprite_frame);
  570.     }
  571.     if (fsp_type == 1)
  572.      type = 0;
  573.        else
  574.      type = conv_info->entry[e].type;
  575.  
  576.     dbox_setnumeric(d, Isprite_pre0, (type & Smask_0));
  577.     dbox_setnumeric(d, Isprite_pre1, (type & Smask_1));
  578.     dbox_setnumeric(d, Isprite_pre2, (type & Smask_2));
  579.     dbox_setnumeric(d, Isprite_pre3, (type & Smask_3));
  580.     dbox_setnumeric(d, Isprite_str, (type & Smask_str));
  581.     dbox_setnumeric(d, Isprite_stm, (type & Smask_stm));
  582.  
  583.   }
  584.   else
  585.   {
  586.     dbox_setfield(d,Isprite_frame,"-");
  587.     dbox_setfield(d,Isprite_xsize,"-");
  588.     dbox_setfield(d,Isprite_ysize,"-");
  589.     dbox_setfield(d,Isprite_mode,"-");
  590.     dbox_setfield(d,Isprite_xcent,"-");
  591.     dbox_setfield(d,Isprite_ycent,"-");
  592.   }
  593. }
  594.  
  595. static void remake_sprite_window(Conv_sprites *s)
  596. {
  597.   wimp_icon icon;
  598.   wimp_redrawstr r;
  599.  
  600.   fillin_sprite_window(sprite_dbox, s);
  601.  
  602. /* Get icon infomation */
  603.  
  604.   r.w = sprite_whandle;
  605.   wimpt_complain(wimp_get_icon_info(sprite_whandle, Isprite_sprite, &icon));
  606.   r.box.x0=icon.box.x0;
  607.   r.box.y0=icon.box.y0;
  608.   r.box.x1=icon.box.x1;
  609.   r.box.y1=icon.box.y1;
  610.   wimpt_complain(wimp_force_redraw(&r));
  611. }
  612.  
  613. static void sprite_read_details(dbox d, Conv_sprites *s, int e)
  614. {
  615.   int type;
  616.   if (e != -1)
  617.   {
  618.     conv_info->entry[e].xcent[s->frame]=dbox_getnumeric(d, Isprite_xcent);
  619.     conv_info->entry[e].ycent[s->frame]=dbox_getnumeric(d, Isprite_ycent);
  620.     limit(&conv_info->entry[e].xcent[s->frame], 0, 255);
  621.     limit(&conv_info->entry[e].ycent[s->frame], 0, 255);
  622.     if (fsp_type == 2)
  623.     {
  624.       type = (Smask_0 * dbox_getnumeric(d, Isprite_pre0))
  625.            + (Smask_1 * dbox_getnumeric(d, Isprite_pre1))
  626.            + (Smask_2 * dbox_getnumeric(d, Isprite_pre2))
  627.            + (Smask_3 * dbox_getnumeric(d, Isprite_pre3))
  628.            + (Smask_str * dbox_getnumeric(d, Isprite_str))
  629.            + (Smask_stm * dbox_getnumeric(d, Isprite_stm))
  630.            ;
  631.       conv_info->entry[e].type=type;
  632.     }
  633.   }
  634. }
  635.  
  636. static void sprite_readfields(dbox d, Conv_sprites *s)
  637. {
  638.   int e, last_number, last_frame;
  639.   last_number=s->number;
  640.   last_frame=s->frame;
  641.   e=scan_conv_info(s->number);
  642.   if (e != -1)
  643.   {
  644.     sprite_read_details(d, s, e);
  645.   }
  646.   s->number=dbox_getnumeric(d, Isprite_number);
  647.   e=scan_conv_info(s->number);
  648.   if (e == -1)
  649.   {
  650.     remake_sprite_window(s);
  651.     return;
  652.   }
  653.   s->frame=dbox_getnumeric(d,Isprite_frame);
  654.  
  655.   if (last_number != s->number || last_frame != s->frame)
  656.   {
  657.     if (e != -1)
  658.     {
  659.       limit(&s->frame, 0, conv_info->entry[e].frames-1);
  660.       limit(&s->frame, 0, Max_frame);
  661.     }
  662.     remake_sprite_window(s);
  663.   }
  664. }
  665.  
  666. static void swap_sprite_info(int i, int j)
  667. {
  668.   Conv_info_entry temp;
  669.   memcpy(&temp, &conv_info->entry[i], sizeof(Conv_info_entry));
  670.   memcpy(&conv_info->entry[i], &conv_info->entry[j], sizeof(Conv_info_entry));
  671.   memcpy(&conv_info->entry[j], &temp, sizeof(Conv_info_entry));
  672. }
  673.  
  674. static void sort_sprite_info(void)
  675. {
  676.   int i;
  677.   for (i=conv_info->header.number-1; i>=1; i--)
  678.   {
  679.     if (conv_info->entry[i].number<conv_info->entry[i-1].number)
  680.     {
  681.       swap_sprite_info(i, i-1);
  682.       i=conv_info->header.number;
  683.     }
  684.   }
  685. }
  686.  
  687. static void read_sprite_info(Conv_sprites *s)
  688. {
  689.   int i, e, n, number, frame, info_size;
  690.   sprite_area sarea;
  691.   sprite_info sinfo;
  692.   sprite_id id;
  693.   char name[12];
  694.   e=0;
  695.   if (s->loaded)
  696.   {
  697.     visdelay_begin();
  698.     if (conv_info_valid) flex_free((flex_ptr) &conv_info);
  699.     conv_info_valid = FALSE;
  700.  
  701.     wimpt_complain(sprite_area_readinfo(s->area, &sarea));
  702.     info_size=sizeof(Conv_info_header)+sizeof(Conv_info_entry) * (sarea.number);
  703.     if (flex_alloc((flex_ptr) &conv_info, info_size) == 0)
  704.     {
  705.       visdelay_end();
  706.       werr(0, "Not enough memory for FSPConv");
  707.       sprites_dispose(s);
  708.       return;
  709.     }
  710.     conv_info->header.number=e;
  711.     conv_info->header.max=0;
  712.     conv_info_valid=TRUE;
  713.     for (i=0; i<sarea.number; i++)
  714.     {
  715.       conv_info->entry[i].number = -1;
  716.       conv_info->entry[i].frames = 0;
  717.     }
  718.     for (i=1; i<=sarea.number; i++)
  719.     {
  720.       wimpt_complain(os_swi6(XOS_SpriteOp, 256+13, (int) s->area, (int) name, 12, i, 0));
  721.  
  722.       switch (sscanf(name, "%d_%d", &number, &frame))
  723.       {
  724.         case 1:
  725.           frame=0;
  726.           break;
  727.         case 2:
  728.           break;
  729.         default:
  730.           number=-1;
  731.           frame=0;
  732.           break;
  733.       }
  734.       if (frame > 15)
  735.       {
  736.         werr(0, "This version of FSPConv cannot cope with more than 16 animation frames");
  737.         sprites_dispose(s);
  738.         return;
  739.       }
  740.       if (number != -1)
  741.       {
  742.         if (number > conv_info->header.max)
  743.           conv_info->header.max = number;
  744.         conv_info->header.number = e;
  745.         if (n = scan_conv_info(number), n < 0)
  746.         {
  747.           n=e;
  748.           id.s.name=name;
  749.           id.tag=sprite_id_name;
  750.           wimpt_complain(sprite_readsize(s->area, &id, &sinfo));
  751.           conv_info->entry[n].number=number;
  752.           conv_info->entry[n].type=Smask_0+Smask_1+Smask_2+Smask_3+Smask_stm+Smask_str;
  753.           conv_info->entry[n].frames = 1;
  754.           e++;
  755.         }
  756.         id.s.name=name;
  757.         id.tag=sprite_id_name;
  758.         wimpt_complain(sprite_readsize(s->area, &id, &sinfo));
  759.         if (conv_info->entry[n].frames < frame+1)
  760.             conv_info->entry[n].frames=frame+1;
  761.         conv_info->entry[n].xcent[frame]=sinfo.width/2;
  762.         conv_info->entry[n].ycent[frame]=sinfo.height/2;
  763.       }
  764.     }
  765.     conv_info->header.number = e;
  766.     sort_sprite_info();
  767.     visdelay_end();
  768.     s->number = conv_info->entry[0].number;
  769.     s->frame = 0;
  770.     remake_sprite_window(s);
  771.   }
  772. }
  773.  
  774. static void conv_info_total(void)
  775. {
  776.   int i, t;
  777.   t=0;
  778.   for (i=0; i<conv_info->header.number; i++)
  779.   {
  780.     t += 4 * sequence_length[conv_info->entry[i].frames];
  781.   }
  782.   conv_info->header.total = t;
  783. }
  784.  
  785. /****************************** SAVE FUNCTIONS ****************************/
  786.  
  787.  
  788. static void fillin_save_filename(char *filename)
  789. {
  790.   dbox_setfield(convert_dbox, Iconvert_filename, filename);
  791. }
  792.  
  793. static BOOL save_do_save(char *filename, void *handle)
  794. {
  795.   handle=handle;
  796.   strncpy(save_filename, filename, 255);
  797.   fillin_save_filename(save_filename);
  798.   return TRUE;
  799. }
  800.  
  801.  
  802. static void open_textfile(char *filename)
  803. {
  804.   wimp_msgstr msg;
  805.   msg.hdr.size=256;
  806.   msg.hdr.your_ref = 0;
  807.   msg.hdr.action = wimp_MDATAOPEN;
  808.   msg.data.dataopen.w = sprite_whandle;
  809.   msg.data.dataopen.i = 0;
  810.   msg.data.dataopen.x = 0;
  811.   msg.data.dataopen.y = 0;
  812.   msg.data.dataopen.size = 0;
  813.   msg.data.dataopen.type = 0xfff;
  814.   strncpy(msg.data.dataopen.name, filename, 212);
  815.   wimpt_complain(wimp_sendmessage(wimp_ESENDWANTACK, &msg, 0));
  816. }
  817.  
  818. static void out_of_memory(void)
  819. {
  820.   werr(0, "Not enough memory to perform conversion");
  821. }
  822.  
  823.  
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830. /********************** CONVERSION FUNCTIONS  ******************************/
  831.  
  832. static void discard_fsp_area(void)
  833. {
  834.   if (fsp_area_size != 0)
  835.   {
  836.     flex_free((flex_ptr) fsp_area);
  837.     *fsp_area = 0;
  838.     fsp_area_size = 0;
  839.   }
  840. }
  841. static BOOL extend_if_needed(char **area, int *size, int offset)
  842. {
  843.   if ((*size - offset) < 0x1000) /* arbitrary limit */
  844.   {
  845.     *size += 0x4000;
  846.     if (flex_extend((flex_ptr) area, *size) == 0) return FALSE;
  847.   }
  848.   return TRUE;
  849. }
  850.  
  851. static void convert_link(void)
  852. {
  853.   event_setmask(wimp_EMPTRENTER | wimp_EMPTRLEAVE);
  854. }
  855.  
  856. static void convert_unlink(void)
  857. {
  858.   event_setmask(wimp_EMNULL | wimp_EMPTRENTER | wimp_EMPTRLEAVE);
  859. }
  860.  
  861. static void convert_error(void)
  862. {
  863.   convert_unlink();
  864.   discard_fsp_area();
  865.   remove(save_filename);
  866.   conv_sprites.number=conv_info->entry[0].number;
  867.   conv_sprites.last_number=-1;
  868.   conv_sprites.frame=0;
  869.   remake_sprite_window(&conv_sprites);
  870. }
  871.  
  872.  
  873. static void convert_message(char *message)
  874. {
  875.   if (convert_dbox_open)
  876.     dbox_setfield(convert_dbox, Iconvert_message, message);
  877. }
  878.  
  879. static void convert_size(int size)
  880. {
  881.   if (convert_dbox_open)
  882.     dbox_setnumeric(convert_dbox, Iconvert_outputsize, size);
  883. }
  884.  
  885. static void sprite_getdetails(sprite_id *id, Conv_det *det)
  886. {
  887.   int mode;
  888.   sprite_header *h;
  889.   h = (sprite_header *) id->s.addr;
  890.   if (fake_use) mode = fakemode;
  891.     else mode=h->mode;
  892.   det->width = h->width;
  893.   det->height = h->height;
  894.   det->bwidth=(32*h->width+(h->rbit+1))/8; /* eight for bytes */
  895.   det->rbytes=4*(h->width+1);
  896.   det->hbytes=bbc_modevar(mode, ModeVars_LineLength);
  897. }
  898.  
  899. static BOOL copy_sprite(sprite_id *id, void **sprc)
  900. {
  901.   int size;
  902.   sprite_header *h;
  903.   h= (sprite_header *) id->s.addr;
  904.   size =  4*(h->width + 1)*(h->height + 1);
  905.   if (flex_alloc(sprc, size) == 0)
  906.   {
  907.     out_of_memory();
  908.     return FALSE;
  909.   }
  910.   memcpy(*sprc, (char *) &h->next + h->image, size);
  911.   return TRUE;
  912. }
  913.  
  914.  
  915. static BOOL fsp1_make_file_header(void)
  916. {
  917.   FSP1_header h;
  918.   strncpy(h.id, "FSP1", 4);
  919.   h.res1 = 0;
  920.   h.basemode = 0;
  921.   h.number = conv_info->header.max + 1;
  922.   memcpy(*fsp_area, &h, sizeof(FSP1_header));
  923.   fsp_ofs += sizeof(FSP1_header);
  924.   spr_ofs = fsp_ofs + 4 * (conv_info->header.max + 1);
  925.   if (!extend_if_needed(fsp_area, &fsp_area_size, spr_ofs)) return FALSE;
  926.   memset(&(*fsp_area)[fsp_ofs], 0, spr_ofs - fsp_ofs);
  927.   return TRUE;
  928. }
  929.  
  930. static BOOL fsp2_make_file_header(void)
  931. {
  932.   FSP2_header h;
  933.   strncpy(h.id, "FSP2", 4);
  934.   h.number = conv_info->header.max + 1;
  935.   h.basemode = 0;
  936.   memcpy(*fsp_area, &h, sizeof(FSP2_header));
  937.   fsp_ofs += sizeof(FSP2_header);
  938.   conv_info_total();
  939.   anim_ofs = fsp_ofs + 4 * (conv_info->header.max+1);
  940.   spr_ofs = anim_ofs + 4 * conv_info->header.total;
  941.   if (!extend_if_needed(fsp_area, &fsp_area_size, spr_ofs)) return FALSE;
  942.   memset(&(*fsp_area)[fsp_ofs], 0, spr_ofs - fsp_ofs);
  943.   return TRUE;
  944. }
  945.  
  946.  
  947.  
  948. static BOOL convert_make_file_header(void)
  949. {
  950.   if (fsp_type == 1) return fsp1_make_file_header();
  951.   if (fsp_type == 2) return fsp2_make_file_header();
  952.   return FALSE;
  953. }
  954.  
  955. static int build_stm_block(void **sprc, Conv_det *det, int shift, int base, BOOL *fours, BOOL *eights)
  956. {
  957.   int x,y,g,h,col,local_ofs,start;
  958.   BOOL any = FALSE;
  959.   char **read;
  960.   *eights = TRUE;
  961.   *fours = TRUE;
  962.   read = (char **) sprc;
  963.   start=4-shift;
  964.   if (shift==0) start=0;
  965.   local_ofs = 4*(det->height+2); /*size of vert table*/
  966.   quad_align(&local_ofs, spr_ofs + local_ofs);
  967.   for (y=0; y<=det->height; y++)
  968.   {
  969.     *(int *)&(*fsp_area)[spr_ofs + 4*y] = local_ofs + base;
  970.     for (x=start; x<det->bwidth; x+=4)
  971.     {
  972.  
  973.       for (g=0; g<7*4 && g+x<det->bwidth; g++)
  974.       {
  975.         col=(*read)[y*det->rbytes + x + g];
  976.         if (col == transp) break;
  977.         (*fsp_area)[spr_ofs + local_ofs + 4 + g] = col;
  978.       }
  979.       h=0;
  980.       if (g >= 3*4) h = 3*4;
  981.       if (g == 7*4) h = 7*4;
  982.       if (h == 3*4) *eights = FALSE;
  983.       if (h == 7*4) *fours = FALSE;
  984.       if (h > 0)
  985.       {
  986.         any = TRUE;
  987.         col=((x + y*det->hbytes)<<8) +(h/4)+1;
  988.         *(int *)&(*fsp_area)[spr_ofs + local_ofs] = col;
  989.         local_ofs += 4+h;
  990.         for (h--;h>=0;h--)
  991.           (*read)[y*det->rbytes + x + h] = transp;
  992.       }
  993.     }
  994.     if (!extend_if_needed(fsp_area, &fsp_area_size, spr_ofs+local_ofs)) return 0;
  995.   }
  996.   *(int *)&(*fsp_area)[spr_ofs + 4*y] = local_ofs + base;
  997.   if (!any) local_ofs = 0;
  998.   return local_ofs;
  999. }
  1000.  
  1001. static int build_str_block(void **sprc, Conv_det *det, int shift, int base)
  1002. {
  1003.   int x,y,g,col,local_ofs,start;
  1004.   BOOL any = FALSE;
  1005.   char **read;
  1006.   read = (char **) sprc;
  1007.   start=4-shift;
  1008.   if (shift==0) start=0;
  1009.   local_ofs = 4*(det->height+2); /*size of vert table*/
  1010.   quad_align(&local_ofs, spr_ofs + local_ofs);
  1011.   for (y=0; y<=det->height; y++)
  1012.   {
  1013.     *(int *)&(*fsp_area)[spr_ofs + 4*y] = local_ofs + base;
  1014.     for (x=start; x<det->bwidth; x+=4)
  1015.     {
  1016.  
  1017.       for (g=0; g<4 && g+x<det->bwidth; g++)
  1018.       {
  1019.         col=(*read)[y*det->rbytes + x + g];
  1020.         if (col == transp) break;
  1021.         (*fsp_area)[spr_ofs + local_ofs + 4 + g] = col;
  1022.       }
  1023.       if (g == 4)
  1024.       {
  1025.         any = TRUE;
  1026.         col=((x + y*det->hbytes)<<8) +(g/4)+1;
  1027.         *(int *)&(*fsp_area)[spr_ofs + local_ofs] = col;
  1028.         local_ofs += 4+g;
  1029.         for (g--;g>=0;g--)
  1030.           (*read)[y*det->rbytes + x + g] = transp;
  1031.       }
  1032.  
  1033.     }
  1034.     if (!extend_if_needed(fsp_area, &fsp_area_size, spr_ofs+local_ofs)) return 0;
  1035.   }
  1036.   *(int *)&(*fsp_area)[spr_ofs + 4*y] = local_ofs + base;
  1037.   if (!any) local_ofs = 0;
  1038.   return local_ofs;
  1039. }
  1040.  
  1041.  
  1042. static int build_strb_block(void **sprc, Conv_det *det, int shift, int base)
  1043. {
  1044.   int x,y,col,local_ofs;
  1045.   char **read;
  1046.   read = (char **) sprc;
  1047.   shift = shift;
  1048.   local_ofs = 4*(det->height+2); /*size of vert table*/
  1049.   for (y=0; y<=det->height; y++)
  1050.   {
  1051.     *(int *)&(*fsp_area)[spr_ofs + 4*y] = local_ofs + base;
  1052.     for (x=0; x<det->bwidth; x++)
  1053.     {
  1054.       col=(*read)[y*det->rbytes + x];
  1055.       if (col != transp)
  1056.       {
  1057.         col+=(x + y*det->hbytes)<<8;
  1058.         *(int *)&(*fsp_area)[spr_ofs + local_ofs] = col;
  1059.         local_ofs+=4;
  1060.       }
  1061.     }
  1062.     if (!extend_if_needed(fsp_area, &fsp_area_size, spr_ofs+local_ofs)) return 0;
  1063.   }
  1064.   *(int *)&(*fsp_area)[spr_ofs + 4*y] = local_ofs + base;
  1065.   if (local_ofs == 4*(det->height+2)) local_ofs = 0;
  1066.   return local_ofs;
  1067. }
  1068.  
  1069. /* -- Write data or line table to file */
  1070.  
  1071. static int fsp1_convert_data(sprite_id *id, sprite_info *i, Conv_info_entry *e)
  1072. {
  1073.   int length;
  1074.   FSP1_entry fsp;
  1075.   Conv_det det;
  1076.   void *sprc;
  1077.   *(int *)&(*fsp_area)[fsp_ofs + 4*e->number] = spr_ofs;
  1078.   if (!copy_sprite(id, &sprc)) return 0;
  1079.   fsp.xsize[0]=i->width;
  1080.   fsp.ysize[0]=i->height;
  1081.   fsp.xofs[0]=e->xcent[0];
  1082.   fsp.yofs[0]=e->ycent[0];
  1083.  
  1084.   memcpy(&(*fsp_area)[spr_ofs], &fsp, Sizeof_FSP1_entry);
  1085.   spr_ofs += Sizeof_FSP1_entry;
  1086.   sprite_getdetails(id, &det);
  1087.   length = build_strb_block(&sprc, &det, 0, 4);
  1088.   spr_ofs+=length;
  1089.   flex_free(&sprc);
  1090.   return length;
  1091. }
  1092.  
  1093. static int fsp2_convert_single(sprite_id *id, sprite_info *i, Conv_info_entry *e, int shift, int frame, BOOL *flag)
  1094. {
  1095.   int temp_spr_ofs, length;
  1096.   BOOL fours,eights;
  1097.  
  1098.   FSP2_entry fsp;
  1099.   Conv_det det;
  1100.   void *sprc;
  1101.   temp_spr_ofs = spr_ofs;
  1102.   if (!copy_sprite(id, &sprc)) return 0;
  1103.   wimpt_complain(sprite_readsize(conv_sprites.area, id, i));
  1104.   sprite_getdetails(id, &det);
  1105.   fsp.xsize     =i->width;
  1106.   fsp.ysize     =i->height;
  1107.   fsp.xofs      =e->xcent[frame];
  1108.   fsp.yofs      =e->ycent[frame];
  1109.   fsp.stmofs    =0;
  1110.   fsp.strofs    =0;
  1111.   fsp.strbofs   =0;
  1112.   fsp.advofs    =0;
  1113.   spr_ofs += Sizeof_FSP2_entry;
  1114.   if ((e->type & Smask_stm) == Smask_stm)
  1115.   {
  1116.     length = build_stm_block(&sprc, &det, shift, 0, &fours, &eights);
  1117.     if (length == 0) fsp.stmofs = 0;
  1118.     else
  1119.     {
  1120.       fsp.stmofs = (spr_ofs - temp_spr_ofs) << 8 ;
  1121.       if (fours) fsp.stmofs+=4;
  1122.       if (eights) fsp.stmofs+=8;
  1123.     }
  1124.     spr_ofs += length;
  1125.   }
  1126.  
  1127.   if ((e->type & Smask_str) == Smask_str)
  1128.   {
  1129.     length = build_str_block(&sprc, &det, shift, 0);
  1130.     if (length == 0) fsp.strofs = 0;
  1131.     else fsp.strofs = (spr_ofs - temp_spr_ofs) << 8;
  1132.     spr_ofs += length;
  1133.   }
  1134.  
  1135.   length = build_strb_block(&sprc, &det, shift, 0);
  1136.   if (length == 0) fsp.strbofs = 0;
  1137.   else fsp.strbofs = (spr_ofs - temp_spr_ofs) << 8;
  1138.   spr_ofs += length;
  1139.  
  1140.   if (fsp.stmofs == 0 && fsp.strofs == 0)
  1141.     *flag = TRUE;
  1142.   else
  1143.     *flag = FALSE;
  1144.  
  1145.   flex_free(&sprc);
  1146.   memcpy(&(*fsp_area)[temp_spr_ofs], &fsp, Sizeof_FSP2_entry);
  1147.   return spr_ofs - temp_spr_ofs;
  1148. }
  1149.  
  1150. static int fsp2_block_convert(sprite_id *id, sprite_info *inf, Conv_info_entry *e, int *length)
  1151. {
  1152.   int i, j, shift, prev_shift, sp_no, anim_base, def_ofs = 0xdead0b0d;
  1153.   sprite_ptr s_ptr;
  1154.   BOOL flag[4], downgrade = TRUE;
  1155.   *length = 0;
  1156.   if ((e->type & (Smask_0 + Smask_1 + Smask_2 + Smask_3)) == 0)
  1157.     e->type = e->type | Smask_0;
  1158.   if ((e->type & (Smask_str + Smask_stm)) == 0)
  1159.   {
  1160.     e->type = Smask_0;
  1161.     downgrade = FALSE;
  1162.   }
  1163.   *(int *)&(*fsp_area)[fsp_ofs + 4*e->number] = (anim_ofs<<8)+(sequence_length[e->frames]-1);
  1164.   anim_base = anim_ofs;
  1165.   for (i=0; i<sequence_length[e->frames]; i++)
  1166.   {
  1167.     sp_no = sequence[e->frames][i];
  1168.     if (sp_no < i)
  1169.     {
  1170.       memcpy(&(*fsp_area)[anim_ofs], &(*fsp_area)[anim_base + 16*sp_no], 16);
  1171.     }
  1172.     else
  1173.     {
  1174.       if(wimpt_complain(sprite_select_rp(conv_sprites.area, conv_id(&conv_sprites, e, sp_no), &s_ptr)) != 0) s_ptr = 0;
  1175.       if (s_ptr == 0)
  1176.       {
  1177.         werr(0, "Sprite named %s does not exist", conv_sprites.name);
  1178.         *length = 0;
  1179.         return FALSE;
  1180.       }
  1181.       id->s.addr=s_ptr;
  1182.       id->tag=sprite_id_addr;
  1183.       wimpt_complain(sprite_removewastage(conv_sprites.area, id));
  1184.       def_ofs = 0;
  1185.       prev_shift = 0;
  1186.       for (j=0; j<4; j++)
  1187.       {
  1188.         flag[j] = TRUE;
  1189.         if ((e->type & 1<<j) != 0)
  1190.         {
  1191.           shift = (j - e->xcent[i]) & 3;
  1192.           /* if ((shift > j) && (e->type != Smask_0)) shift |= 4;*/
  1193.           /* release h-locking if STRB only */
  1194.           def_ofs = (spr_ofs<<8) + shift;
  1195.           if (e->type == Smask_0) def_ofs |= 8;
  1196.           *(int *)&(*fsp_area)[anim_ofs+j*4] = def_ofs;
  1197.           *length+=fsp2_convert_single(id, inf, e, shift & 3, i, &flag[j]);
  1198.         }
  1199.         else
  1200.           *(int *)&(*fsp_area)[anim_ofs+j*4] = def_ofs;
  1201.       }
  1202.     if (!(flag[0] && flag[1] && flag[2] && flag[3]))
  1203.       downgrade = FALSE;
  1204.     }
  1205.     for (j=3; j>=0; j--)
  1206.     {
  1207.       if (*(int *)&(*fsp_area)[anim_ofs+j*4] == 0)
  1208.         *(int *)&(*fsp_area)[anim_ofs+j*4] = def_ofs;
  1209.       else
  1210.         def_ofs = *(int *)&(*fsp_area)[anim_ofs+j*4];
  1211.     }
  1212.     anim_ofs+=16;
  1213.   }
  1214.   return downgrade;
  1215. }
  1216.  
  1217. static int fsp2_convert_data(sprite_id *id, sprite_info *inf, Conv_info_entry *e)
  1218. {
  1219.   int length = 0;
  1220.   int temp_spr_ofs, temp_anim_ofs;
  1221.   temp_spr_ofs = spr_ofs;
  1222.   temp_anim_ofs = anim_ofs;
  1223.   if (fsp2_block_convert(id, inf, e, &length))
  1224.   {
  1225.     e->type = Smask_0;
  1226.     spr_ofs = temp_spr_ofs;
  1227.     anim_ofs = temp_anim_ofs;
  1228.     if (fsp2_block_convert(id, inf, e, &length))
  1229.       werr(1, "Internal Inconsistency - FSPConv must leave the Desktop");
  1230.   }
  1231.   return length;
  1232. }
  1233.  
  1234.  
  1235. /****- sprite data to file entry point ****/
  1236.  
  1237. static BOOL fsp_convert(sprite_id *id,Conv_info_entry *e)
  1238. {
  1239.   int length = 0;
  1240.   sprite_info i;
  1241.  
  1242.   wimpt_complain(sprite_readsize(conv_sprites.area, id, &i));
  1243.  
  1244.   if (fsp_type == 1) length = fsp1_convert_data(id, &i, e);
  1245.   if (fsp_type == 2) length = fsp2_convert_data(id, &i, e);
  1246.   if (length == 0) return FALSE;
  1247.   convert_size(spr_ofs);
  1248.   return TRUE;
  1249. }
  1250.  
  1251. /****- CONVERT SPRITES TO FILE ENTRY POINT -****/
  1252.  
  1253. static BOOL sprite_convert(Conv_sprites *s, Conv_info_entry *e, int i)
  1254. {
  1255.   char message[128];
  1256.   sprite_ptr s_ptr;
  1257.   sprite_id id;
  1258.  
  1259.   sprintf(message, "Converting sprite %d out of %d", i+1, conv_info->header.number);
  1260.   convert_message(message);
  1261.  
  1262.   wimpt_complain(sprite_select_rp(s->area, conv_id(s, e, 1), &s_ptr));
  1263.   if (s_ptr == 0)
  1264.   {
  1265.     werr(0, "Cannot get pointer for sprite named %s", s->name);
  1266.     return FALSE;
  1267.   }
  1268.  
  1269.   id.s.addr=s_ptr;
  1270.   id.tag=sprite_id_addr;
  1271.   wimpt_complain(sprite_removewastage(s->area, &id));
  1272.  
  1273.   if (!fsp_convert(&id, e)) return FALSE;
  1274.   return TRUE;
  1275. }
  1276.  
  1277. static BOOL convert_open()
  1278. {
  1279.   fsp_area_size = 0x4000; /* Get a default size flex block */
  1280.   if (flex_alloc((flex_ptr) fsp_area, fsp_area_size) == 0)
  1281.   {
  1282.     *fsp_area = NULL;
  1283.     fsp_area_size = 0;
  1284.     werr(0, "Not enough memory to perform conversion");
  1285.     convert_error();
  1286.     return FALSE;
  1287.   }
  1288.   fsp_ofs = 0;
  1289.   conv_no=0;
  1290.   convert_link();
  1291.   return TRUE;
  1292. }
  1293.  
  1294. static void set_filetype(char *filename, int type)
  1295. {
  1296.   wimpt_complain(os_swi4(XOS_File,18,(int) filename,type,0));
  1297. }
  1298.  
  1299. static BOOL convert_write()
  1300. {
  1301.   FILE *f;
  1302.   if (!convert_getlength)
  1303.   {
  1304.  
  1305.     if (f = fopen (save_filename, "w"), f == 0)
  1306.     {
  1307.       werr(0, "Cannot open file for write access");
  1308.       convert_error();
  1309.       return FALSE;
  1310.     }
  1311.     if (fwrite(*fsp_area, 1, spr_ofs, f) != spr_ofs)
  1312.     {
  1313.       fclose(f);
  1314.       werr(0, "Disc full");
  1315.       convert_error();
  1316.       return FALSE;
  1317.     }
  1318.     fclose(f);
  1319.   set_filetype(save_filename, FastSpr_filetype);
  1320.   }
  1321.   discard_fsp_area();
  1322.   conv_no=-1;
  1323.   convert_size(spr_ofs);
  1324.   conv_sprites.number=conv_info->entry[0].number;
  1325.   conv_sprites.last_number=-1;
  1326.   conv_sprites.frame=0;
  1327.   remake_sprite_window(&conv_sprites);
  1328.   return TRUE;
  1329. }
  1330.  
  1331. static void convert_event(void)
  1332. {
  1333.   if (conv_no == -1)
  1334.   {
  1335.     werr(0, "Conversion event received when no conversion requested");
  1336.     convert_unlink();
  1337.     return;
  1338.   }
  1339.   if (conv_no == -2)
  1340.   {
  1341.     convert_error();
  1342.     return;
  1343.   }
  1344.   if (conv_no == 0)
  1345.   {
  1346.     if (!convert_make_file_header())
  1347.     {
  1348.       convert_error();
  1349.       return;
  1350.     }
  1351.   }
  1352.   if(!sprite_convert(&conv_sprites, &conv_info->entry[conv_no], conv_no))
  1353.   {
  1354.     werr(0, "Conversion of sprite named %d failed", conv_info->entry[conv_no].number);
  1355.     convert_error();
  1356.     return;
  1357.   }
  1358.   conv_no++;
  1359.   if (conv_no >= conv_info->header.number)
  1360.   {
  1361.     if (!convert_write())
  1362.     {
  1363.       convert_message("Conversion OK - write to disc failed");
  1364.       convert_error();
  1365.       return;
  1366.     }
  1367.     convert_unlink();
  1368.     if (convert_getlength)
  1369.       convert_message("Length calculation successful");
  1370.     else
  1371.       convert_message("Conversion successful");
  1372.   }
  1373. }
  1374.  
  1375. static BOOL do_conversion(Conv_info *c)
  1376. {
  1377.   if (!conv_info_valid || c->header.number == 0)
  1378.   {
  1379.     werr(0, "There are no sprites to convert");
  1380.     return FALSE;
  1381.   }
  1382.   return convert_open();
  1383. }
  1384.  
  1385. static int filesize_sprite(sprite_area *sa)
  1386. {
  1387.   sprite_area result;
  1388.   sprite_area_readinfo(sa, &result);
  1389.   return result.size;
  1390. }
  1391.  
  1392. static BOOL save_raw_event_handler(dbox d, void *v, void *handle)
  1393. {
  1394.   wimp_eventstr *e;
  1395.   e = (wimp_eventstr *) v;
  1396.   switch (e->e)
  1397.   {
  1398.     case wimp_EBUT:
  1399.       if (e->data.but.m.bbits == wimp_BDRAGLEFT)
  1400.       {
  1401.         dbox_getfield(d, Iconvert_filename, save_filename, 255);
  1402.         xfersend(Fastspr_filetype, save_filename, 0, save_do_save, 0, 0, e, handle);
  1403.         fillin_save_filename(save_filename);
  1404.         return TRUE;
  1405.       }
  1406.       else
  1407.       return FALSE;
  1408.  
  1409.     case wimp_ECLOSE:
  1410.       conv_no=-2; /* signal a cancel */
  1411.       return FALSE;
  1412.  
  1413.     default:
  1414.       break;
  1415.  
  1416.   }
  1417.   return FALSE;
  1418. }
  1419.  
  1420. static void convert_event_handler(dbox d, void *handle)
  1421. {
  1422.   BOOL persist;
  1423.   dbox_field f;
  1424.   handle=handle;
  1425.   f=dbox_get(d);
  1426.   persist=dbox_persist();
  1427.   convert_getlength = FALSE;
  1428.   switch (f)
  1429.   {
  1430.     case Iconvert_cancel:
  1431.       conv_no=-2;
  1432.       persist=FALSE;
  1433.       break;
  1434.  
  1435.     case Iconvert_getlength:
  1436.       convert_getlength = TRUE; /* drops through */
  1437.     case Iconvert_convert:
  1438.     case 0:
  1439.       if (!conv_sprites.loaded) break;
  1440.  
  1441.       sprite_readfields(sprite_dbox, &conv_sprites);
  1442.       dbox_getfield(d, Iconvert_filename, save_filename, 255);
  1443.       dbox_setnumeric(d, Iconvert_convert, 1);
  1444.       do_conversion(conv_info);
  1445.       dbox_setnumeric(d, Iconvert_convert, 0);
  1446.       persist = TRUE;
  1447.       break;
  1448.  
  1449.  
  1450.  
  1451.  
  1452.  
  1453.     default:
  1454.       break;
  1455.   }
  1456.   if (!persist)
  1457.   {
  1458.     dbox_dispose(&d);
  1459.     convert_dbox_open = FALSE;
  1460.   }
  1461. }
  1462.  
  1463.  
  1464. static BOOL begin_conversion(Conv_sprites *s)
  1465. {
  1466.   s=s;
  1467.  
  1468.   if (convert_dbox_open)
  1469.   {
  1470.     dbox_dispose(&convert_dbox);
  1471.   }
  1472.   if (convert_dbox = dbox_new("Convert"), convert_dbox != NULL)
  1473.   {
  1474.     convert_dbox_open = TRUE;
  1475.     dbox_raw_eventhandler(convert_dbox, save_raw_event_handler, 0);
  1476.     dbox_eventhandler(convert_dbox, convert_event_handler, 0);
  1477.     dbox_setfield(convert_dbox, Iconvert_filename, save_filename);
  1478.     dbox_setfield(convert_dbox, Iconvert_filetype, type_string());
  1479.     dbox_setnumeric(convert_dbox, Iconvert_sourcesize, filesize_sprite(s->area));
  1480.     if (conv_sprites.loaded)
  1481.     {
  1482.       if (conv_info->header.number == 0)
  1483.         convert_message("No sprites to convert.  Are they named correctly?");
  1484.       else
  1485.         if (fake_use)
  1486.         {
  1487.           char message[128];
  1488.           sprintf(message,"Ready to Convert...  Faking Mode %d", fakemode);
  1489.           convert_message(message);
  1490.         }
  1491.         else
  1492.         convert_message("Ready to Convert...");
  1493.     }
  1494.     else
  1495.       convert_message("No sprite file is loaded");
  1496.   dbox_showstatic(convert_dbox);
  1497.  
  1498.   }
  1499.   return TRUE;
  1500. }
  1501.  
  1502.  
  1503. /****************************** LOAD FUNCTIONS ****************************/
  1504.  
  1505.  
  1506.  
  1507. /*--- Load checks: determines if the file type is valid, and if so deletes
  1508.       the old file, then claims memory as necessary. ---*/
  1509. static BOOL FSPConv_load_check(int filetype, Conv_sprites *d, int size)
  1510. {
  1511.   int areasize;
  1512.  
  1513.   /* Check validity of file type */
  1514.   if (filetype != Sprite_filetype)
  1515.   {
  1516.     werr(0, "You can only load sprite files");
  1517.     return FALSE;
  1518.   }
  1519.  
  1520.   /* Remove any old file */
  1521.   sprites_dispose(d);
  1522.  
  1523.   /* Allocate new memory */
  1524.   areasize = size+sizeof(sprite_area);
  1525.   if (flex_alloc((flex_ptr) &d->area, areasize))
  1526.   {
  1527.   /* Initialise sprite area */
  1528.  
  1529.     sprite_area_initialise(d->area, areasize);
  1530.     return TRUE;
  1531.   }
  1532.   else
  1533.   {
  1534.     werr(0, "There is not enough free memory to load that file.");
  1535.     return FALSE;
  1536.   }
  1537. }
  1538.  
  1539. /*--- Handle loading errors. ---*/
  1540. static void FSPConv_load_error(Conv_sprites *d)
  1541. {
  1542.   sprites_dispose(d);
  1543.   strcpy(d->filename, FSPConv_null_name);
  1544.   werr(0,"Sprite load has failed");
  1545. }
  1546.  
  1547. /*--- Complete the loading process. ---*/
  1548. static void FSPConv_load_finish(Conv_sprites *d, int size)
  1549. {
  1550.   int i;
  1551.   d->size     = size;
  1552.   d->loaded   = TRUE;
  1553.   d->saved    = TRUE;
  1554.   for (i=strlen(d->filename); i>0; i--)
  1555.     if (d->filename[i]=='.') break;
  1556.  
  1557.   strncpy(save_filename, d->filename, i+1);
  1558.   save_filename[i+1]='\0';
  1559.   strcat(save_filename, "FSP");
  1560.   strcat(save_filename, &d->filename[i+1]);
  1561.  
  1562.   win_settitle(sprite_whandle, d->filename);
  1563.   if (convert_dbox_open)
  1564.     dbox_setfield(convert_dbox, Iconvert_filename, save_filename);
  1565.  
  1566.   read_sprite_info(d);
  1567.   /* Redraw the diagram */
  1568.  
  1569.   remake_sprite_window(d);
  1570.   begin_conversion(d);
  1571. }
  1572.  
  1573.  
  1574. /*--- Read the size of a file. Return 0 if not a file. ---*/
  1575. static int FSPConv_filesize(char *filename)
  1576. {
  1577.   os_filestr file;
  1578.  
  1579.   /* Read the size of the file */
  1580.   file.action = 5;    /* Get catalogue info */
  1581.   file.name   = filename;
  1582.   if (wimpt_complain(os_file(&file)) != 0) return 0;
  1583.  
  1584.   switch (file.action)
  1585.   {
  1586.     case 0: werr(0, "File not found");              return 0;
  1587.     case 2: werr(0, "You cannot load a directory"); return 0;
  1588.   }
  1589.  
  1590.   return file.start;
  1591. }
  1592.  
  1593.  
  1594. /*--- Load from a file. ---*/
  1595. static void load_file(Conv_sprites *d)
  1596. {
  1597.   char      *filename;
  1598.   int       size;
  1599.  
  1600.   /* Fetch the type and name of the file */
  1601.   int filetype = xferrecv_checkinsert(&filename);
  1602.  
  1603.   /* Check the name and make a permanent copy */
  1604.   if (strlen(filename) > FSPConv_max_name)
  1605.   {
  1606.     werr(0, "File name is too long");
  1607.   }
  1608.   else
  1609.   {
  1610.     strcpy(d->filename, filename);
  1611.  
  1612.     /* Get size of file (and check it is a file) */
  1613.     size = FSPConv_filesize(d->filename);
  1614.  
  1615.     /* Check file type, get rid of old memory and allocate new */
  1616.     if (size > 0 && FSPConv_load_check(filetype, d, size))
  1617.     {
  1618.       visdelay_begin();
  1619.  
  1620.       if (wimpt_complain(sprite_area_load(d->area, d->filename)) == 0)
  1621.         FSPConv_load_finish(d, size);
  1622.           else
  1623.         FSPConv_load_error(d);
  1624.  
  1625.       visdelay_end();
  1626.     }
  1627.     else
  1628.     {
  1629.       werr(0,"Failed to load file");
  1630.     }
  1631.   }
  1632.  
  1633.   /* Indicate load is completed */
  1634.   xferrecv_insertfileok();
  1635. }
  1636.  
  1637. /**************** --- Sprite handling *********************/
  1638.  
  1639. static menu make_number_menu(void)
  1640. {
  1641.   int i, m;
  1642.   menu next_menu = NULL;
  1643.   char extendstr[12];
  1644.   if (sprite_number_menu != NULL)
  1645.     menu_dispose(&sprite_number_menu, 1);
  1646.   sprite_number_menu = menu_new("Number","");
  1647.   if (conv_info_valid)
  1648.   {
  1649.     if (conv_info->header.number < 20)
  1650.     {
  1651.       for (i=0; i<conv_info->header.number; i++)
  1652.       {
  1653.         sprintf(extendstr, "%d",conv_info->entry[i].number);
  1654.         menu_extend(sprite_number_menu, extendstr);
  1655.       }
  1656.     }
  1657.     else
  1658.     {
  1659.       m=0;
  1660.       for (i=0;i<conv_info->header.number; i++)
  1661.       {
  1662.         if (conv_info->entry[i].number >= m || next_menu == NULL)
  1663.         {
  1664.           if (next_menu != NULL)
  1665.             menu_submenu(sprite_number_menu, m/10, next_menu);
  1666.           m=(conv_info->entry[i].number/10)*10;
  1667.           sprintf(extendstr, "%d-%d",m,m+9);
  1668.           menu_extend(sprite_number_menu, extendstr);
  1669.           next_menu = menu_new(extendstr, "");
  1670.           m+=10;
  1671.         }
  1672.         sprintf(extendstr, "%d",conv_info->entry[i].number);
  1673.         menu_extend(next_menu, extendstr);
  1674.       }
  1675.       menu_submenu(sprite_number_menu, m/10, next_menu);
  1676.     }
  1677.   }
  1678.   menu_extend(sprite_number_menu, "|Help");
  1679.   return sprite_number_menu;
  1680. }
  1681.  
  1682. static menu make_frame_menu(void)
  1683. {
  1684.   int i,e=-1;
  1685.   char extendstr[12];
  1686.   if (sprite_frame_menu != NULL)
  1687.     menu_dispose(&sprite_frame_menu, 0);
  1688.   sprite_frame_menu = menu_new("Frame","");
  1689.   e = scan_conv_info(conv_sprites.number);
  1690.   if (e != -1 && conv_info->entry[e].frames <= 256)
  1691.   {
  1692.     for (i=0; i<conv_info->entry[e].frames; i++)
  1693.     {
  1694.       sprintf(extendstr, "%d",i);
  1695.       menu_extend(sprite_frame_menu, extendstr);
  1696.     }
  1697.   }
  1698.   menu_extend(sprite_frame_menu, "|Help");
  1699.   return sprite_frame_menu;
  1700. }
  1701.  
  1702. static void open_menu(menu menu, wimp_mousestr *mouse)
  1703. {
  1704.   wimpt_complain(wimp_create_menu(menu_syshandle(menu), mouse->x-96, mouse->y));
  1705. }
  1706.  
  1707. static void open_popup_menu(menu menu, wimp_mousestr *mouse)
  1708. {
  1709.   wimpt_complain(wimp_create_menu(menu_syshandle(menu), mouse->x+24, mouse->y));
  1710. }
  1711.  
  1712. static void open_sprite_menu(wimp_mousestr *mouse)
  1713. {
  1714.   switch (mouse->i)
  1715.   {
  1716.     case Isprite_number+2:
  1717.       open_popup_menu(make_number_menu(), mouse);
  1718.       menu_type=M_sprite_number;
  1719.       break;
  1720.  
  1721.     case Isprite_frame+2:
  1722.       open_popup_menu(make_frame_menu(), mouse);
  1723.       menu_type=M_sprite_frame;
  1724.       break;
  1725.  
  1726.     case Isprite_xcent+2:
  1727.       open_popup_menu(sprite_centre_menu, mouse);
  1728.       menu_type=M_sprite_centre;
  1729.       break;
  1730.  
  1731.     case Isprite_premenu:
  1732.       open_popup_menu(sprite_preshift_menu, mouse);
  1733.       menu_type=M_sprite_preshift;
  1734.       break;
  1735.  
  1736.     case Isprite_typemenu:
  1737.       open_popup_menu(sprite_type_menu, mouse);
  1738.       menu_type=M_sprite_type;
  1739.       break;
  1740.  
  1741.     default:
  1742.       open_menu(sprite_menu, mouse);
  1743.       menu_type=M_sprite_normal;
  1744.       break;
  1745.   }
  1746. }
  1747.  
  1748. static void check_incdec(dbox d, int f, int g)
  1749. {
  1750.   int x,i;
  1751.   wimp_mousestr mouse;
  1752.   wimpt_complain(wimp_get_point_info(&mouse));
  1753.   if (mouse.bbits == wimp_BLEFT)
  1754.     i=1;
  1755.   else
  1756.     i=-1;
  1757.  
  1758.   if (f == g-1)
  1759.   {
  1760.     x=dbox_getnumeric(d, g) - i;
  1761.     dbox_setnumeric(d, g, x);
  1762.   }
  1763.   if (f == g+1)
  1764.   {
  1765.     x=dbox_getnumeric(d, g) + i;
  1766.     dbox_setnumeric(d, g, x);
  1767.   }
  1768.   if ((f == g+2) && (i == 1))
  1769.   {
  1770.     open_sprite_menu(&mouse);
  1771.   }
  1772. }
  1773.  
  1774. static void check_number_incdec(dbox d, int f, int g)
  1775. {
  1776.   int x,i,e;
  1777.   wimp_mousestr mouse;
  1778.   wimpt_complain(wimp_get_point_info(&mouse));
  1779.   if (mouse.bbits == wimp_BLEFT)
  1780.     i=1;
  1781.   else
  1782.     i=-1;
  1783.  
  1784.   if (f == g-1)
  1785.   {
  1786.     e = scan_conv_info(conv_sprites.number);
  1787.     if (e != -1 && e != 0)
  1788.     {
  1789.       x=conv_info->entry[e-1].number;
  1790.       dbox_setnumeric(d, g, x);
  1791.     }
  1792.   }
  1793.   if (f == g+1)
  1794.   {
  1795.     e = scan_conv_info(conv_sprites.number);
  1796.     if (e != -1 && e+1 < conv_info->header.number)
  1797.     {
  1798.       x=conv_info->entry[e+1].number;
  1799.       dbox_setnumeric(d, g, x);
  1800.     }
  1801.   }
  1802.   if ((f == g+2) && (i == 1))
  1803.   {
  1804.     open_sprite_menu(&mouse);
  1805.   }
  1806. }
  1807.  
  1808. static void info_about_program(void)
  1809. {
  1810.   dbox d;
  1811.   if (d = dbox_new("Proginfo"), d != NULL)
  1812.   {
  1813.     dbox_setfield(d,4,Prog_name);
  1814.     dbox_setfield(d,7,Version_string);
  1815.     dbox_show(d);
  1816.     dbox_fillin(d);
  1817.     dbox_dispose(&d);
  1818.   }
  1819. }
  1820.  
  1821. static void open_transp_dbox(void)
  1822. {
  1823.   dbox d;
  1824.   if (d = dbox_new("Transp"), d != NULL)
  1825.   {
  1826.     dbox_setnumeric(d,Itransp_transp,transp);
  1827.     dbox_show(d);
  1828.     dbox_fillin(d);
  1829.     transp = dbox_getnumeric(d,Itransp_transp);
  1830.     if (transp<0 || transp>255)
  1831.     {
  1832.       werr(0, "The transparent colour should range from 0 to 255");
  1833.     }
  1834.     dbox_dispose(&d);
  1835.   }
  1836. }
  1837.  
  1838. static void open_fake_dbox(void)
  1839. {
  1840.   dbox d;
  1841.   if (d = dbox_new("FakeMode"), d != NULL)
  1842.   {
  1843.     dbox_setnumeric(d,Ifake_fake,fakemode);
  1844.     dbox_setnumeric(d,Ifake_use,fake_use);
  1845.     dbox_show(d);
  1846.     dbox_fillin(d);
  1847.     fakemode = dbox_getnumeric(d,Ifake_fake);
  1848.     fake_use = dbox_getnumeric(d,Ifake_use);
  1849.     if (fakemode<0 || fakemode>255)
  1850.     {
  1851.       werr(0, "The fake mode should range from 0 to 255");
  1852.     }
  1853.     dbox_dispose(&d);
  1854.   }
  1855. }
  1856.  
  1857. static void decode_bar_menu(void *hitlist)
  1858. {
  1859.   int *hitno;
  1860.   hitno = (int *) hitlist;
  1861.  
  1862.   switch(hitno[0])
  1863.   {
  1864.     case Bar_menu_info:
  1865.       info_about_program();
  1866.       break;
  1867.  
  1868.     case Bar_menu_transp:
  1869.       open_transp_dbox();
  1870.       break;
  1871.  
  1872.     case Bar_menu_convert:
  1873.       begin_conversion(&conv_sprites);
  1874.       break;
  1875.  
  1876.     case Bar_menu_help:
  1877.       open_textfile("FSPConv:Help.General");
  1878.       break;
  1879.  
  1880.     case Bar_menu_quit:
  1881.       exit(0);
  1882.  
  1883.     default:
  1884.       break;
  1885.   }
  1886. }
  1887.  
  1888. static void decode_number_menu(void *hitlist)
  1889. {
  1890.   int args,first,last,value;
  1891.   char buffer[256];
  1892.   wimpt_complain(wimp_decode_menu(menu_syshandle(sprite_number_menu),
  1893.     hitlist, buffer));
  1894.   args=sscanf(buffer,"%d-%d.%d",&first,&last,&value);
  1895.   switch (args)
  1896.   {
  1897.     case 0:
  1898.       open_textfile("FSPConv:Help.NumberMenu");
  1899.       break;
  1900.  
  1901.     case 1:
  1902.     case 2:
  1903.       dbox_setnumeric(sprite_dbox, Isprite_number, first);
  1904.       sprite_readfields(sprite_dbox, &conv_sprites);
  1905.       break;
  1906.  
  1907.  
  1908.     case 3:
  1909.       dbox_setnumeric(sprite_dbox, Isprite_number, value);
  1910.       sprite_readfields(sprite_dbox, &conv_sprites);
  1911.       break;
  1912.  
  1913.     default:
  1914.       break;
  1915.   }
  1916. }
  1917.  
  1918. static void decode_frame_menu(void *hitlist)
  1919. {
  1920.   int args,value;
  1921.   char buffer[256];
  1922.   wimpt_complain(wimp_decode_menu(menu_syshandle(sprite_frame_menu),
  1923.     hitlist, buffer));
  1924.   args=sscanf(buffer,"%d",&value);
  1925.   switch (args)
  1926.   {
  1927.     case 0:
  1928.       open_textfile("FSPConv:Help.FrameMenu");
  1929.       break;
  1930.  
  1931.     case 1:
  1932.       dbox_setnumeric(sprite_dbox, Isprite_frame, value);
  1933.       sprite_readfields(sprite_dbox, &conv_sprites);
  1934.       break;
  1935.   }
  1936. }
  1937.  
  1938. static void centre_menu_all(void)
  1939. {
  1940.   int i,j,x,y,num,frame;
  1941.   sprite_info sinfo;
  1942.   num=conv_sprites.number;
  1943.   frame=conv_sprites.frame;
  1944.   for (i=0; i<=conv_info->header.number; i++)
  1945.   {
  1946.     for (j=0; j< conv_info->entry[i].frames; j++)
  1947.     {
  1948.       conv_sprites.number=conv_info->entry[i].number;
  1949.       conv_sprites.frame=j;
  1950.       wimpt_complain(sprite_readsize(conv_sprites.area, current_id(&conv_sprites), &sinfo));
  1951.       x=0;
  1952.       y=0;
  1953.       switch (lastcentre)
  1954.       {
  1955.         case Centre_menu_centre:
  1956.           x=sinfo.width/2;
  1957.           y=sinfo.height/2;
  1958.           break;
  1959.     
  1960.         case Centre_menu_left:
  1961.           x=0;
  1962.           y=sinfo.height/2;
  1963.           break;
  1964.     
  1965.         case Centre_menu_right:
  1966.           x=sinfo.width-1;
  1967.           y=sinfo.height/2;
  1968.           break;
  1969.     
  1970.         case Centre_menu_top:
  1971.           x=sinfo.width/2;
  1972.           y=0;
  1973.           break;
  1974.     
  1975.         case Centre_menu_bottom:
  1976.           x=sinfo.width/2;
  1977.           y=sinfo.height-1;
  1978.           break;
  1979.     
  1980.         case Centre_menu_topleft:
  1981.           x=0;
  1982.           y=0;
  1983.           break;
  1984.     
  1985.         case Centre_menu_topright:
  1986.           x=sinfo.width-1;
  1987.           y=0;
  1988.           break;
  1989.     
  1990.         case Centre_menu_bottomleft:
  1991.           x=0;
  1992.           y=sinfo.height-1;
  1993.           break;
  1994.     
  1995.         case Centre_menu_bottomright:
  1996.           x=sinfo.width-1;
  1997.           y=sinfo.height-1;
  1998.           break;
  1999.       }
  2000.     conv_info->entry[i].xcent[conv_sprites.frame] = x;
  2001.     conv_info->entry[i].ycent[conv_sprites.frame] = y;
  2002.     }
  2003.   }
  2004.   conv_sprites.number=num;
  2005.   conv_sprites.frame=frame;
  2006.   remake_sprite_window(&conv_sprites);
  2007. }
  2008.     
  2009.  
  2010. static void decode_centre_menu(void *hitlist)
  2011. {
  2012.   int *hitno;
  2013.   int hit;
  2014.   sprite_info sinfo;
  2015.   int x, y, e;
  2016.   hitno = (int *) hitlist;
  2017.   hit=hitno[0];
  2018.   e=scan_conv_info(conv_sprites.number);
  2019.   if (e == -1)
  2020.   {
  2021.     x=0;
  2022.     y=0;
  2023.     sinfo.width=0;
  2024.     sinfo.height=0;
  2025.   }
  2026.   else
  2027.   {
  2028.     x=conv_info->entry[e].xcent[conv_sprites.frame];
  2029.     y=conv_info->entry[e].ycent[conv_sprites.frame];
  2030.     wimpt_complain(sprite_readsize(conv_sprites.area, current_id(&conv_sprites), &sinfo));
  2031.   }
  2032.  
  2033.   switch (hit)
  2034.   {
  2035.     case Centre_menu_centre:
  2036.       x=sinfo.width/2;
  2037.       y=sinfo.height/2;
  2038.       break;
  2039.  
  2040.     case Centre_menu_left:
  2041.       x=0;
  2042.       y=sinfo.height/2;
  2043.       break;
  2044.  
  2045.     case Centre_menu_right:
  2046.       x=sinfo.width-1;
  2047.       y=sinfo.height/2;
  2048.       break;
  2049.  
  2050.     case Centre_menu_top:
  2051.       x=sinfo.width/2;
  2052.       y=0;
  2053.       break;
  2054.  
  2055.     case Centre_menu_bottom:
  2056.       x=sinfo.width/2;
  2057.       y=sinfo.height-1;
  2058.       break;
  2059.  
  2060.     case Centre_menu_topleft:
  2061.       x=0;
  2062.       y=0;
  2063.       break;
  2064.  
  2065.     case Centre_menu_topright:
  2066.       x=sinfo.width-1;
  2067.       y=0;
  2068.       break;
  2069.  
  2070.     case Centre_menu_bottomleft:
  2071.       x=0;
  2072.       y=sinfo.height-1;
  2073.       break;
  2074.  
  2075.     case Centre_menu_bottomright:
  2076.       x=sinfo.width-1;
  2077.       y=sinfo.height-1;
  2078.       break;
  2079.       
  2080.     case Centre_menu_all:
  2081.       centre_menu_all();
  2082.       break;  
  2083.  
  2084.     case Centre_menu_help:
  2085.       open_textfile("FSPConv:Help.Centremenu");
  2086.       return;
  2087.       break;
  2088.   }
  2089.   lastcentre=hit;
  2090.   if (e != -1 && hit != Centre_menu_all)
  2091.   {
  2092.     conv_info->entry[e].xcent[conv_sprites.frame] = x;
  2093.     conv_info->entry[e].ycent[conv_sprites.frame] = y;
  2094.     remake_sprite_window(&conv_sprites);
  2095.   }
  2096. }
  2097.  
  2098. static void decode_type_menu(void *hitlist)
  2099. {
  2100.   int *hitno;
  2101.   hitno = (int *) hitlist;
  2102.   switch(hitno[0])
  2103.   {
  2104.     case Type_menu_fsp1:
  2105.       fsp_type = 1;
  2106.       remake_sprite_window(&conv_sprites);
  2107.       if (convert_dbox_open) begin_conversion (&conv_sprites);
  2108.       break;
  2109.  
  2110.     case Type_menu_fsp2:
  2111.       fsp_type = 2;
  2112.       remake_sprite_window(&conv_sprites);
  2113.       if (convert_dbox_open) begin_conversion (&conv_sprites);
  2114.       break;
  2115.  
  2116.     case Type_menu_help:
  2117.       open_textfile("FSPConv:Help.TypeMenu");
  2118.       break;
  2119.  
  2120.     default:
  2121.       break;
  2122.   }
  2123. }
  2124.  
  2125. static void decode_preshift_menu(void *hitlist)
  2126. {
  2127.   int *hitno;
  2128.   int e;
  2129.   hitno = (int *) hitlist;
  2130.   e=scan_conv_info(conv_sprites.number);
  2131.   switch (hitno[0])
  2132.   {
  2133.     case Preshift_menu_just0:
  2134.       if (e == -1 | fsp_type != 2) break;
  2135.       conv_info->entry[e].type=conv_info->entry[e].type & (Smask_str + Smask_stm) | Smask_0;
  2136.       fillin_sprite_window(sprite_dbox, &conv_sprites);
  2137.       break;
  2138.  
  2139.     case Preshift_menu_hlock:
  2140.       if (e == -1 | fsp_type != 2) break;
  2141.       conv_info->entry[e].type=Smask_str + Smask_stm + Smask_0;
  2142.       fillin_sprite_window(sprite_dbox, &conv_sprites);
  2143.       break;
  2144.  
  2145.     case Preshift_menu_0and2:
  2146.       if (e == -1 | fsp_type != 2) break;
  2147.       conv_info->entry[e].type=conv_info->entry[e].type & (Smask_str + Smask_stm) | (Smask_0+Smask_2);
  2148.       fillin_sprite_window(sprite_dbox, &conv_sprites);
  2149.       break;
  2150.  
  2151.     case Preshift_menu_all:
  2152.       if (e == -1 | fsp_type != 2) break;
  2153.       conv_info->entry[e].type=conv_info->entry[e].type |
  2154.         Smask_0+Smask_1+Smask_2+Smask_3+Smask_str+Smask_stm;
  2155.       fillin_sprite_window(sprite_dbox, &conv_sprites);
  2156.       break;
  2157.  
  2158.     case Preshift_menu_none:
  2159.       if (e == -1 | fsp_type != 2) break;
  2160.       conv_info->entry[e].type=0;
  2161.       fillin_sprite_window(sprite_dbox, &conv_sprites);
  2162.       break;
  2163.  
  2164.     case Preshift_menu_appall:
  2165.       if (e == -1 | fsp_type != 2) break;
  2166.       {
  2167.         int i;
  2168.         for (i=0; i<=conv_info->header.number; i++)
  2169.         {
  2170.           conv_info->entry[i].type = conv_info->entry[e].type;
  2171.         }
  2172.       }break;
  2173.  
  2174.  
  2175.     case Preshift_menu_help:
  2176.       open_textfile("FSPConv:Help.PreMenu");
  2177.       break;
  2178.  
  2179.     default:
  2180.       break;
  2181.   }
  2182. }
  2183.  
  2184. static void decode_sprite_menu(void *hitlist)
  2185. {
  2186.   int *hitno;
  2187.   hitno=(int *) hitlist;
  2188.   switch (hitno[0])
  2189.   {
  2190.     case Sprite_menu_convert:
  2191.       begin_conversion(&conv_sprites);
  2192.       break;
  2193.  
  2194.     case Sprite_menu_help:
  2195.       open_textfile("FSPConv:Help.SpriteHelp");
  2196.       break;
  2197.  
  2198.     case Sprite_menu_fake:
  2199.       open_fake_dbox();
  2200.       break;
  2201.  
  2202.     case Sprite_menu_discard:
  2203.       if (!conv_sprites.loaded) break;
  2204.       if (!conv_sprites.saved)
  2205.         if (dboxquery("Sprites are unsaved.  Do you still wish to discard them?") != dboxquery_YES) break;
  2206.       sprites_dispose(&conv_sprites);
  2207.       strcpy(conv_sprites.filename,"No Sprites");
  2208.       remake_sprite_window(&conv_sprites);
  2209.       break;
  2210.  
  2211.   }
  2212. }
  2213.  
  2214. static void generic_menuproc(void *hitlist)
  2215. {
  2216.   wimp_mousestr mouse;
  2217.   wimpt_complain(wimp_get_point_info(&mouse));
  2218.  
  2219.   switch (menu_type)
  2220.   {
  2221.     case M_iconbar:
  2222.       decode_bar_menu(hitlist);
  2223.       break;
  2224.  
  2225.  
  2226.     case M_sprite_number:
  2227.       if (mouse.bbits == wimp_BRIGHT)
  2228.         wimp_create_menu(menu_syshandle(sprite_number_menu), 0, 0);
  2229.       decode_number_menu(hitlist);
  2230.       break;
  2231.  
  2232.     case M_sprite_frame:
  2233.       if (mouse.bbits == wimp_BRIGHT)
  2234.         wimp_create_menu(menu_syshandle(sprite_frame_menu), 0, 0);
  2235.       decode_frame_menu(hitlist);
  2236.       break;
  2237.  
  2238.     case M_sprite_centre:
  2239.       if (mouse.bbits == wimp_BRIGHT)
  2240.         wimp_create_menu(menu_syshandle(sprite_centre_menu), 0, 0);
  2241.       decode_centre_menu(hitlist);
  2242.       break;
  2243.  
  2244.     case M_sprite_normal:
  2245.       if (mouse.bbits == wimp_BRIGHT)
  2246.         wimp_create_menu(menu_syshandle(sprite_menu), 0, 0);
  2247.       decode_sprite_menu(hitlist);
  2248.       break;
  2249.  
  2250.     case M_sprite_type:
  2251.       if (mouse.bbits == wimp_BRIGHT)
  2252.         wimp_create_menu(menu_syshandle(sprite_type_menu), 0, 0);
  2253.       decode_type_menu(hitlist);
  2254.       break;
  2255.  
  2256.     case M_sprite_preshift:
  2257.       if (mouse.bbits == wimp_BRIGHT)
  2258.         wimp_create_menu(menu_syshandle(sprite_preshift_menu), 0, 0);
  2259.       decode_preshift_menu(hitlist);
  2260.       break;
  2261.  
  2262.  
  2263.     default:
  2264.       break;
  2265.   }
  2266. }
  2267.  
  2268. static void forge_preshift(int i)
  2269. {
  2270.   decode_preshift_menu(&i);
  2271. }
  2272.  
  2273. static void sprite_event_handler(dbox d, void *handle)
  2274. {
  2275.   int f;
  2276.   wimp_mousestr mouse;
  2277.   wimpt_complain(wimp_get_point_info(&mouse));
  2278.   handle=handle;
  2279.   f=(int) dbox_get(d);
  2280.   check_number_incdec(d, f, Isprite_number);
  2281.   check_incdec(d, f, Isprite_frame);
  2282.   check_incdec(d, f, Isprite_xcent);
  2283.   check_incdec(d, f, Isprite_ycent);
  2284.  
  2285.   if (((f == Isprite_premenu) | (f == Isprite_typemenu)) && (mouse.bbits == 4))
  2286.     open_sprite_menu(&mouse);
  2287.  
  2288.   if (f == Isprite_all) forge_preshift(Preshift_menu_all);
  2289.   if (f == Isprite_none) forge_preshift(Preshift_menu_none);
  2290.   if (f == Isprite_hlock) forge_preshift(Preshift_menu_hlock);
  2291.  
  2292.   sprite_readfields(d, &conv_sprites);
  2293.  
  2294. }
  2295.  
  2296.  
  2297. static BOOL sprite_raw_event_handler(dbox d, void *v,  void *handle)
  2298. {
  2299.   wimp_eventstr *e;
  2300.   handle = handle;
  2301.   d=d;
  2302.  
  2303.   e= (wimp_eventstr *) v;
  2304.   switch (e->e)
  2305.   {
  2306.     case wimp_EREDRAW:
  2307.       redraw_sprite_window(&conv_sprites);
  2308.       return TRUE;
  2309.  
  2310.     case wimp_EOPEN:
  2311.       wimp_open_wind(&e->data.o);
  2312.       return TRUE;
  2313.  
  2314.     case wimp_ECLOSE:
  2315.       dbox_hide(sprite_dbox);
  2316.       if (convert_dbox_open)
  2317.       {
  2318.         dbox_dispose(&convert_dbox);
  2319.         convert_dbox_open = FALSE;
  2320.       }
  2321.       return FALSE;
  2322.  
  2323.  
  2324.     case wimp_EKEY:
  2325.       if (e->data.key.chcode == 13)
  2326.       {
  2327.         sprite_readfields(d, &conv_sprites);
  2328.       }
  2329.       return FALSE;
  2330.  
  2331.     case wimp_EBUT:
  2332.       if (e->data.but.m.bbits == wimp_BMID)
  2333.       {
  2334.         open_sprite_menu(&e->data.but.m);
  2335.         return TRUE;
  2336.       }
  2337.       return FALSE;
  2338.  
  2339.     case wimp_EMENU:
  2340.         generic_menuproc(&e->data.menu);
  2341.     return TRUE;
  2342.  
  2343.     case wimp_ESEND:
  2344.     case wimp_ESENDWANTACK:
  2345.     {
  2346.       switch (e->data.msg.hdr.action)
  2347.       {
  2348.         case wimp_MDATALOAD:   /* insert data */
  2349.           load_file(&conv_sprites);
  2350.           return TRUE;
  2351.  
  2352.         default: return FALSE;        /* ignore other messages */
  2353.       }
  2354.  
  2355.     }
  2356.  
  2357.     case wimp_EACK:
  2358.  
  2359.           if (e->data.msg.hdr.action == wimp_MDATAOPEN)
  2360.             start_task(e->data.msg.data.dataopen.name);
  2361.           return TRUE;
  2362.  
  2363.  
  2364.     case wimp_ENULL:
  2365.       convert_event();
  2366.       return TRUE;
  2367.  
  2368.     default:
  2369.       return FALSE;
  2370.   }
  2371. }
  2372.  
  2373. static void open_bar_menu(wimp_mousestr *m)
  2374. {
  2375.   menu_type=M_iconbar;
  2376.   wimpt_complain(wimp_create_menu(menu_syshandle(bar_menu), m->x-80, m->y+6*44));
  2377. }
  2378.  
  2379. static void bar_icon_handler(wimp_eventstr *e, void *handle)
  2380. {
  2381.   handle=handle;
  2382.   switch (e->e)
  2383.   {
  2384.     case wimp_EBUT:
  2385.       if (e->data.but.m.bbits == wimp_BMID)
  2386.       {
  2387.         open_bar_menu(&e->data.but.m);
  2388.         break;
  2389.       }
  2390.       if (e->data.but.m.bbits == wimp_BLEFT)
  2391.       {
  2392.         fillin_sprite_window(sprite_dbox, &conv_sprites);
  2393.         dbox_hide(sprite_dbox);
  2394.         dbox_showstatic(sprite_dbox);
  2395.         break;
  2396.       }
  2397.       if (e->data.but.m.bbits == wimp_BRIGHT)
  2398.       {
  2399.         begin_conversion(&conv_sprites);
  2400.         break;
  2401.       }
  2402.     break;
  2403.  
  2404.     case wimp_ESEND:
  2405.     case wimp_ESENDWANTACK:
  2406.     {
  2407.       switch (e->data.msg.hdr.action)
  2408.       {
  2409.         case wimp_MDATALOAD:   /* insert data */
  2410.           dbox_hide(sprite_dbox);
  2411.           dbox_showstatic(sprite_dbox);
  2412.           load_file(&conv_sprites);
  2413.           break;
  2414.  
  2415.         default: break;        /* ignore other messages */
  2416.       }
  2417.       break;
  2418.  
  2419.       default:
  2420.         break;
  2421.  
  2422.     }
  2423.   }
  2424. }
  2425.  
  2426.  
  2427.  
  2428.  
  2429. static void set_default_file(void)
  2430. {
  2431.   conv_info_valid=FALSE;
  2432.   conv_sprites.number=0;
  2433.   conv_sprites.loaded=FALSE;
  2434.   conv_sprites.area=0;
  2435.   conv_sprites.last_number=-1;
  2436.   strcpy(conv_sprites.name, "-");
  2437.   strcpy(save_filename,"null:FSPSprites");
  2438. }
  2439.  
  2440. /*  ----- Initialisation -----  */
  2441.  
  2442. static BOOL initialise(void)
  2443. {
  2444.   flex_init();
  2445.   heap_init(TRUE);
  2446.   wimpt_init(Prog_name);
  2447.   res_init(Prog_name);
  2448.   resspr_init();
  2449.   template_init();
  2450.   dbox_init();
  2451.  
  2452. /*-- Create window */
  2453.  
  2454.   if (sprite_dbox = dbox_new("Sprite"), sprite_dbox==0) return FALSE;
  2455.  
  2456.   dbox_raw_eventhandler(sprite_dbox, sprite_raw_event_handler, 0);
  2457.   dbox_eventhandler(sprite_dbox, sprite_event_handler, 0);
  2458.  
  2459.   sprite_whandle = dbox_syshandle(sprite_dbox);
  2460.  
  2461. /*-- Create Menu */
  2462.  
  2463.   if (bar_menu = menu_new(Prog_name,">Info,>Transparent,Convert...,Help,Quit"), bar_menu == NULL) return FALSE;
  2464.   if (sprite_menu = menu_new("Sprite","Convert...,>Fake Mode|Discard|Help"), sprite_menu == NULL) return FALSE;
  2465.   if (sprite_number_menu = menu_new("Number","1,2,3,4"), sprite_number_menu == NULL) return FALSE;
  2466.   if (sprite_frame_menu = menu_new("Frame","1,2,3,4"), sprite_frame_menu == NULL) return FALSE;
  2467.   if (sprite_centre_menu = menu_new("Centre","Centre,Left,Right,Top,Bottom,Top Left,Top Right,Bottom Left,Bottom Right|Apply to All|Help"), sprite_centre_menu == NULL) return FALSE;
  2468.   if (sprite_type_menu = menu_new("Type","FSP1,FSP2|Help"), sprite_type_menu == NULL) return FALSE;
  2469.   if (sprite_preshift_menu = menu_new("Preshift","All,None,Just 0,0 and 2|Apply to All|Help"), sprite_preshift_menu == NULL) return FALSE;
  2470.  
  2471.  
  2472.  /*-- Create Bar Icon */
  2473.  
  2474.   baricon(Prog_spr_name, Wimp_sprite_area, 0);
  2475.  
  2476. /* -- Attach everything -- */
  2477.  
  2478.   win_register_event_handler(win_ICONBAR, bar_icon_handler, 0);
  2479.   win_register_event_handler(win_ICONBARLOAD, bar_icon_handler, 0);
  2480.   win_claim_unknown_events(sprite_whandle);
  2481.  
  2482.   event_setmask(wimp_EMNULL | wimp_EMPTRENTER | wimp_EMPTRLEAVE);
  2483.  
  2484.   set_default_file();
  2485.  
  2486.   return TRUE;
  2487. }
  2488.  
  2489. int main()
  2490. {
  2491.    if (initialise())
  2492.   {
  2493.     while (TRUE)
  2494.       event_process();
  2495.   }
  2496.   return 0;
  2497. }
  2498.