home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 3 / PDCD_3.iso / utilities / utilsm / mkdrawf / !Drawf / Source / c / drawf
Encoding:
Text File  |  1995-05-05  |  18.5 KB  |  628 lines

  1. /* Wimp front end for mkdrawf and decdrawf
  2.  */
  3.  
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7.  
  8. #ifdef THROWBACK
  9. #include "dde.h"
  10. #endif
  11.  
  12. #include "load+save.h"
  13. #include "wimp.h"
  14.  
  15. #define err_base (1<<30)
  16. #define appname "Drawf"
  17. #define spr_file "<Drawf$Dir>.Sprites"
  18. #define tem_file "<Drawf$Dir>.Templates"
  19.  
  20. /* Icons in the Options window.
  21.  */
  22. enum {
  23.   oi_mdf_frame=0,    oi_mdf_title=1,
  24.   oi_tagfile_opt=2,    oi_tagfile_icon=3,    oi_tagfile_name=4,
  25.   oi_ddf_frame=5,    oi_ddf_title=6,
  26.   oi_sprfile_opt=7,    oi_sprfile_icon=8,    oi_sprfile_name=9,
  27.   oi_jpegpfx_opt=10,    oi_jpegpfx_icon=11,    oi_jpegpfx_name=12,
  28.   oi_gen_frame=13,    oi_gen_title=14,
  29.   oi_run=15,        oi_run_always=16
  30. };
  31.  
  32. enum {
  33.   sv_icon=0,    sv_name=1,    sv_ok=2
  34. };
  35.  
  36. static int wimp_version=0;
  37.  
  38. /*------------------------------------------------------------------------*/
  39.  
  40. /* Icon block etc for icon-bar icon.
  41.  */
  42. static Icon_info baricon = {
  43.   0, { {0,0,92,68},0x7000011A,"" }
  44. };
  45.  
  46. /* Main menu.
  47.  */
  48. static mblock(3) menu = {
  49.   "Drawf",
  50.   7,2,7,0,
  51.   72,48,0,
  52.   { {0,0,0x07009021,"Info"},
  53.     {0,-1,0x07009021,"Options"},
  54.     {128,-1,0x07009021,"Quit"} }
  55. };
  56.  
  57. /* List of messages we're interested in.
  58.  */
  59. static int messages[]={1,2,3,4,0};
  60.  
  61. /*------------------------------------------------------------------------*/
  62.  
  63. /* Error messages.
  64.  */
  65. static err_block(44)
  66.   out_of_date  = { err_base,"This application requires RISC OS 3." },
  67.   no_templates = { err_base+1,"I can't open my Templates file." },
  68.   no_sprites   = { err_base+2,"I can't open my Sprites file." },
  69.   no_window    = { err_base+3,"My Templates file is broken!" },
  70.   cw_failed    = { err_base+4,"I failed to create a window." },
  71.   ci_failed    = { err_base+5,"I failed to create an icon." },
  72.   aargh        = { err_base+6,"Something really nasty went wrong!" },
  73.   no_memory    = { err_base+7,"I've run out of memory." },
  74.   im_busy      = { err_base+8,"Sorry, but I'm busy. Try again later." },
  75.   no_errfile   = { err_base+9,"I couldn't open an error log file." },
  76.   save_failed  = { err_base+10,"Something went wrong trying to save that." },
  77.   too_long     = { err_base+11,"That command line is too long." };
  78.  
  79. /* |opting_icon| is usually 0.
  80.  * While dragging an icon from the Options window, or waiting for
  81.  * the DataSaveAck after doing so, it's the icon number of the
  82.  * icon in that window which we dragged.
  83.  */
  84. static int opting_icon=0;
  85.  
  86. /* Non-obvious fact: |output_name| contains a non-empty string
  87.  * if and only if there is an output file waiting to be saved.
  88.  * In that case, it contains the name of that file.
  89.  * Similarly for |err_name|.
  90.  */
  91. static char output_name[256]="",err_name[256]="";
  92. static long err_zero=0;    /* size of error file before prog runs */
  93.  
  94. /* While we're doing this sort of thing, we might as well also
  95.  * have a buffer for putting commands in.
  96.  * It might be useful for other things, too...
  97.  * The longest command we ever issue contains 5 pathnames and
  98.  * some other stuff.
  99.  * This also needs to be big enough for the window block for
  100.  * the Options window; ditto for the Save window. No trouble.
  101.  */
  102. #define scratch_size 1400
  103. static char scratch[scratch_size];
  104.  
  105. /* Another magic number of a similar sort:
  106.  * This needs to be bigger than the total size of any window (including
  107.  * indirected data).
  108.  * At the moment the Options window is getting close, so be careful.
  109.  */
  110. #define winbuf_size 1600
  111.  
  112. /* |lose(err)| reports the error, exits and dies.
  113.  * Its arg should point to an error block of some sort.
  114.  */
  115. static void lose(const void *e) {
  116.   if (wimp_version>0) {
  117.     wimp_reporterror((error_block*)e,1,appname);
  118.     wimp_closedown(); }
  119.   else
  120.     fputs(((char*)e)+4,stderr);
  121.   if (*err_name) remove(err_name);
  122.   if (*output_name) remove(output_name);
  123.   exit(0);
  124. }
  125.  
  126. /* |err(x)| reports the error, but doesn't exit.
  127.  */
  128. static void err(const void *e) {
  129.   wimp_reporterror((error_block*)e,1,appname);
  130. }
  131.  
  132. /* |finish()| exits without an error.
  133.  */
  134. static void finish(void) {
  135.   wimp_closedown();
  136.   if (*err_name) remove(err_name);
  137.   if (*output_name) remove(output_name);
  138.   exit(0);
  139. }
  140.  
  141. static void *xmalloc(int n) {
  142.   void *p=malloc(n);
  143.   if (!p) lose(&no_memory);
  144.   return p;
  145. }
  146.  
  147. /* Window and icon handles, etc.
  148.  */
  149. static int info_handle,*info_inddata;
  150. static int opt_handle,*opt_inddata;
  151. static int save_handle,*save_inddata;
  152. static int baricon_handle=-1;
  153. static int *sprite_area=0;
  154.  
  155. /*------------------------------------------------------------------------*/
  156.  
  157. /* Various bits of state.
  158.  */
  159.  
  160. static int open_tagfile=0;
  161. static int use_spritefile=0;
  162. static int use_prefix=0;
  163. static char *tagfile_name=0;
  164. static char *spritefile_name=0;
  165. static char *jpeg_prefix=0;
  166. static char *save_ftype=0;
  167. static char *save_name=0;
  168. static char *save_title;
  169.  
  170. /*------------------------------------------------------------------------*/
  171.  
  172. /* Forward-declare event handlers.
  173.  */
  174. static int do_close(int,int*);
  175. static int do_click(int,int*);
  176. static int do_dragbox(int,int*);
  177. static int do_menu(int,int*);
  178. static int do_message(int,int*);
  179.  
  180. /*------------------------------------------------------------------------*/
  181.  
  182. /* Find the template for window |name|, put its indirected data ptr at |inddata|
  183.  * and return the window handle.
  184.  */
  185. static int create_window(const char *name, void *space, int **inddata) {
  186.   int handle,tsize,isize;
  187.   if (wimp_xtemplate(name,&tsize,&isize,0,0)<0) lose(&no_window);
  188.   if (tsize>winbuf_size) lose(&cw_failed);
  189.   *inddata=xmalloc(isize);
  190.   if (wimp_loadtemplate(name,space,*inddata,isize,(char*)-1,0,0)<0)
  191.     lose(&no_window);
  192.   if ((handle=wimp_createwindow(space))<0) lose(&cw_failed);
  193.   return handle;
  194. }
  195.  
  196. /* Turn a control-terminated string into a null-terminated one.
  197.  */
  198. void sanitise(char *s) {
  199.   char c;
  200.   while ((c=*s++)>=32) ;
  201.   s[-1]=0;
  202. }
  203.  
  204. /* Do all the usual Wimp initialisation things: create windows and icons
  205.  * and menus, and so on.
  206.  * Exit in an appropriate way if something goes wrong.
  207.  */
  208. static void init_wimp(void) {
  209.   /* Become a Wimp task. */
  210.   void *space=xmalloc(winbuf_size);
  211.   wimp_version=wimp_initialise(310,"Drawf",messages);
  212.   if (wimp_version<0) lose(&aargh);
  213.   if (wimp_version<310) lose(&out_of_date);
  214.   /* Create windows. */
  215.   if (wimp_opentemplate(tem_file)) lose(&no_templates);
  216.   info_handle=create_window("Info",space,&info_inddata);
  217.   opt_handle=create_window("Options",space,&opt_inddata);
  218.   save_handle=create_window("Save",space,&save_inddata);
  219.   save_title=((char**)space)[18]+5; /* actually points to "decdrawf output" */
  220.   free(space);
  221.   /* Fill in menu. */
  222.   menu.items[0].leads_to.window=info_handle;
  223.   /* Bits of writable data. */
  224.   { Icon_block *i;
  225.     i=wimp_geticonstate(opt_handle,oi_tagfile_name);
  226.     tagfile_name=i->data.indtext.text;
  227.     sanitise(tagfile_name);
  228.     i=wimp_geticonstate(opt_handle,oi_sprfile_name);
  229.     spritefile_name=i->data.indtext.text;
  230.     sanitise(spritefile_name);
  231.     i=wimp_geticonstate(opt_handle,oi_jpegpfx_name);
  232.     jpeg_prefix=i->data.indtext.text;
  233.     sanitise(jpeg_prefix);
  234.     i=wimp_geticonstate(save_handle,sv_icon);
  235.     save_ftype=i->data.indsprite.name+5;    /* points to "fff" or "aff" */
  236.     sanitise(save_ftype);
  237.     i=wimp_geticonstate(save_handle,sv_name);
  238.     save_name=i->data.indtext.text;
  239.     sanitise(save_name);
  240.   }
  241.   /* Close the template file, before we forget. */
  242.   wimp_closetemplate();
  243.   /* Load sprites. */
  244.   { int ssize=file_size(spr_file);
  245.     if (ssize<0) lose(&no_sprites);
  246.     sprite_area=xmalloc(ssize+4);
  247.     sprite_area[0]=ssize;
  248.     if (load_file(spr_file,sprite_area+1)!=ssize) lose(&no_sprites); }
  249.   /* Create iconbar icon. */
  250.   baricon.window=-7;
  251.   baricon.block.data.indsprite.name="drawf";
  252.   baricon.block.data.indsprite.area=sprite_area;
  253.   baricon.block.data.indsprite.length=5;
  254.   if ((baricon_handle=wimp_createicon(0,&baricon))<0) lose(&ci_failed);
  255.   /* Set up event handlers. */
  256.   wimpfns[reason_close]=do_close;
  257.   wimpfns[reason_click]=do_click;
  258.   wimpfns[reason_dragbox]=do_dragbox;
  259.   wimpfns[reason_menu]=do_menu;
  260.   wimpfns[reason_message]=
  261.    wimpfns[reason_message_rec]=
  262.    wimpfns[reason_message_ack]=do_message;
  263.   /* We're done. */
  264. }
  265.  
  266. /*------------------------------------------------------------------------*/
  267.  
  268. /* Shade or unshade icons n+1,n+2 in the options window
  269.  * according to the selection state of icon n. Also toggle
  270.  * that state; it's the *new* state that matters.
  271.  * Returns 1<<21 for selected, else 0.
  272.  */
  273. static int maybe_shade(int n) {
  274.   int t = wimp_geticonstate(opt_handle,n)->flags.val;
  275.   int u = (t&=(1<<21))<<1;
  276.   wimp_seticonstate(opt_handle,n,1<<21,0);
  277.   wimp_seticonstate(opt_handle,n+1,u,1<<22);
  278.   wimp_seticonstate(opt_handle,n+2,u,1<<22);
  279.   return t^(1<<21);
  280. }
  281.  
  282. /* Leafname from pathname.
  283.  */
  284. static const char *leaf(const char *s) {
  285.   const char *t=s;
  286.   char c;
  287.   while (c=*t++)
  288.     if (c=='.'||c==':') s=t;
  289.   return s;
  290. }
  291.  
  292. /* Leafname, or empty string if no path.
  293.  */
  294. static const char *leaf0(const char *s) {
  295.   const char *t=leaf(s);
  296.   return t==s ? (const char *)"" : t;    /* (const char *)"" ... ludicrous */
  297. }
  298.  
  299. /* Leafname of a name in indirected text of icon n in window w.
  300.  */
  301. #define leafname(w,n) leaf(wimp_geticonstate((w),(n))->data.indtext.text)
  302.  
  303. /*------------------------------------------------------------------------*/
  304.  
  305. #ifdef THROWBACK
  306. static int using_dde=0;
  307. #endif
  308.  
  309. /* When we start a task, we must make sure the command line is
  310.  * no longer than 256c; otherwise something barfs in a big way
  311.  * and crashes the machine irrevocably (well, it does with my
  312.  * machine anyway).
  313.  */
  314. static int start_task(const char *s) {
  315.   if (
  316. #ifdef THROWBACK
  317.       using_dde ||
  318. #endif
  319.       strlen(s)<256) return wimp_starttask(s);
  320.   err(&too_long); return -1;
  321. }
  322.  
  323. /* Create the error file.
  324.  */
  325. static void create_errors(const char *prog, const char *input) {
  326.   FILE *f=fopen(err_name,"w");
  327.   if (!f) { err(&no_errfile); *err_name=0; return; }
  328. #ifdef THROWBACK
  329.   using_dde=dde_exists();
  330. #endif
  331.   fprintf(f,"Errors and warnings from %s:\n"
  332.             "Input file: %s\n"
  333.             "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
  334.             "~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n",
  335.            prog,input);
  336.   err_zero=ftell(f);
  337.   fclose(f);
  338. }
  339.  
  340. #ifdef THROWBACK
  341.  
  342. /* If we have the DDE available, we can do throwback:
  343.  * go through the file and send the relevant info to
  344.  * the DDEUtils SWIs.
  345.  */
  346. static void do_throwback(const char *name) {
  347.   FILE *f=fopen(err_name,"r");
  348.   unsigned int l; char *cp;
  349.   throwback_start();
  350.   throwback_filename(name);
  351.   while (fgets(scratch,256,f)) {
  352.     sanitise(scratch);
  353.     if (!strncmp(scratch,"Line ",5)) continue;
  354.     l=strtoul(scratch+5,&cp,10);
  355.     if (*cp==':' && (l || (cp!=scratch+5))) {
  356.       /* Looks like a real error message. Assume it is. */
  357.       int ty;
  358.       if (cp[1]=='w') { ty=0; cp+=10; }
  359.       else if (cp[1]=='e') { ty=1; cp+=8; }
  360.       else if (cp[1]=='f') { ty=2; cp+=14; }
  361.       throwback_error(name,l,ty,cp);
  362.     }
  363.   }
  364.   throwback_end();
  365.   fclose(f);
  366. }
  367.  
  368. #endif
  369.  
  370. /* Actually save the file. To be more precise: copy it to the
  371.  * right place.
  372.  * Return 0 for failure, 1 for success.
  373.  */
  374. static int do_really_save(void) {
  375.   /* copy from to ~CDF~V */
  376.   sprintf(scratch,"Copy %s %s ~CDF~V",output_name,save_name);
  377.   start_task(scratch);
  378.   *output_name=0;
  379.   wimp_closewindow(&save_handle);
  380.   return 1;
  381. }
  382.  
  383. /* Do the first things needed for a launch.
  384.  */
  385. static void begin_launch(const char *name) {
  386.   strcpy(save_name,leaf0(name));
  387.   if (*output_name) remove(output_name);
  388.   if (*err_name) remove(err_name);
  389.   tmpnam(output_name);
  390.   tmpnam(err_name);
  391.   hourglass_start(50);
  392. }
  393.  
  394. /* And the last.
  395.  */
  396. static void finish_launch(char c, const char *name) {
  397.   /* Run mkdrawf or decdrawf. */
  398.   int no_err=1<<21;
  399.   int z=start_task(scratch);
  400.   hourglass_off();
  401.   if (z) { err(&aargh); return; }
  402.   /* Get the error file opened by a text editor, or else send its contents
  403.    * to whatever's doing throwback. But don't do any of this if there weren't
  404.    * any diagnostics.
  405.    * We don't delete the error file at this point, because the Filer_Run
  406.    * won't take place instantaneously. It's deleted next time we need to
  407.    * use an error file...
  408.    */
  409.   if (*err_name) {
  410.     if (file_size(err_name)!=err_zero) {
  411.       no_err=0;
  412. #ifdef THROWBACK
  413.       if (using_dde && c=='a') {
  414.         do_throwback(name);
  415.         remove(err_name);
  416.         *err_name=0; }
  417.       else {
  418. #endif
  419.         sprintf(scratch,"Filer_Run %s",err_name);
  420.         start_task(scratch);
  421. #ifdef THROWBACK
  422.       }
  423. #endif
  424.     } else { remove(err_name); *err_name=0; }
  425.   }
  426.   /* If appropriate, Filer_Run the output file. */
  427.   if (wimp_geticonstate(opt_handle,oi_run_always)->flags.val&(1<<21)
  428.       || wimp_geticonstate(opt_handle,oi_run)->flags.val&no_err) {
  429.     sprintf(scratch,"Filer_Run %s",output_name);
  430.     start_task(scratch);
  431.   }
  432.   /* Now open the Save window. */
  433.   strcpy(save_title,c=='a'?"mkdrawf output":"decdrawf output");
  434.   *save_ftype=c;
  435.   { int *block=(int*)scratch;
  436.     block[0]=save_handle;
  437.     wimp_getwindowinfo(block);
  438.     wimp_openwindow(block);
  439.   }
  440. }
  441.  
  442. /* Launch mkdrawf. |name| is the name of the input file.
  443.  */
  444. static void launch_mkdrawf(const char *name) {
  445.   begin_launch(name);
  446.   create_errors("mkdrawf",name);
  447.   /* mkdrawf input output 2>>errs -t tags */
  448.   sprintf(scratch,"mkdrawf -e %s %s %s%s%s%s",
  449.           name,output_name,
  450.           *err_name?"2>>":"",err_name,
  451.           open_tagfile?" -t ":"",open_tagfile?tagfile_name:"");
  452.   finish_launch('a',name);
  453. }
  454.  
  455. static void launch_decdrawf(const char *name) {
  456.   begin_launch(name);
  457.   create_errors("decdrawf",name);
  458.   /* decdrawf input >output 2>>errs -s sprites -j jpeg */
  459.   sprintf(scratch,"decdrawf -e %s >%s %s%s%s%s%s%s",
  460.           name,output_name,
  461.           *err_name?"2>>":"",err_name,
  462.           use_spritefile?" -s ":"",use_spritefile?spritefile_name:"",
  463.           use_prefix?" -j ":"",use_prefix?jpeg_prefix:"");
  464.   finish_launch('f',name);
  465. }
  466.  
  467. /*------------------------------------------------------------------------*/
  468.  
  469. /* Event handlers.
  470.  */
  471.  
  472. static int do_close(int reason, int *block) {
  473.   reason=reason;
  474.   if (block[0]==save_handle) {
  475.     if (*output_name) { remove(output_name); *output_name=0; }
  476.     if (*err_name) { remove(err_name); *err_name=0; }
  477.   }
  478.   wimp_closewindow(block);
  479.   return 0;
  480. }
  481.  
  482. static int do_click(int reason, int *block) {
  483.   int but=block[2], win=block[3], icn=block[4];
  484.   reason=reason;
  485.   /* block[2..4]: buttons, window, icon */
  486.   if (win==-2 && icn==baricon_handle && but==2)
  487.     wimp_createmenu((Menu_block*)&menu,block[0]-64,240);
  488.   if (but==2) return 0;    /* ignore Menu clicks */
  489.   if (win==save_handle) {
  490.     if (icn==sv_icon && but==64) {
  491.       if (opting_icon) err(&im_busy);
  492.       else begin_drag(save_handle,wimp_geticonstate(save_handle,icn));
  493.     }
  494.     else if (icn==sv_ok && but==4)
  495.       do_really_save();
  496.     return 0;
  497.   }
  498.   if (win!=opt_handle) return 0;
  499.   /* We now know it's in the options window. Which {ic|butt}on? */
  500.   if (but==4) {
  501.     switch(icn) {
  502.       case oi_tagfile_opt: open_tagfile=maybe_shade(oi_tagfile_opt); break;
  503.       case oi_sprfile_opt: use_spritefile=maybe_shade(oi_sprfile_opt); break;
  504.       case oi_jpegpfx_opt: use_prefix=maybe_shade(oi_jpegpfx_opt); break;
  505.     }
  506.     return 0; }
  507.   if (but!=64) return 0;    /* not drag */
  508.   if (icn!=oi_tagfile_icon &&    /* must be one of the file icons */
  509.       icn!=oi_sprfile_icon &&
  510.       icn!=oi_jpegpfx_icon) return 0;
  511.   if (opting_icon) { err(&im_busy); return 0; }
  512.   begin_drag(opt_handle,wimp_geticonstate(opt_handle,icn));
  513.   opting_icon=icn;
  514.   return 0;
  515. }
  516.  
  517. static int do_dragbox(int reason, int *block) {
  518.   reason=reason;
  519.   wimp_getpointerinfo(block+2);
  520.   if (block[5]==opt_handle) { opting_icon=0; return 0; }
  521.   block[7]=block[2];    /* x */
  522.   block[8]=block[3];    /* y */
  523.   block[3]=0;    /* your_ref: original message */
  524.   block[4]=1;    /* Message_DataSave */
  525.       /* block[5..8] filled in already */
  526.   block[9]=0;    /* estimated size in bytes */
  527.   block[10]=(*save_ftype=='a')?0xAFF:0xFFF;
  528.   strcpy((char*)(block+11),
  529.     opting_icon ? leafname(opt_handle,opting_icon+1)
  530.                 : leaf(save_name));
  531.   block[0]=(strlen((char*)(block+11))+48)&~3;
  532.   wimp_sendmessage4(reason_message_rec,block,block[5],block[6]);
  533.                   /* window handle serves as taskID */
  534.   return 0;
  535. }
  536.  
  537. static int do_menu(int reason, int *block) {
  538.   reason=reason;
  539.   if (block[0]==1) {
  540.     /* Open Options window. */
  541.     int *b=(int*)scratch;
  542.     b[0]=opt_handle;
  543.     wimp_getwindowinfo(b);
  544.     wimp_openwindow(b); }
  545.   else if (block[0]==2) finish();
  546.   return 0;
  547. }
  548.  
  549. static int do_message(int reason, int *block) {
  550.   reason=reason;
  551.   switch(block[4]) {
  552.     case 0:    /* Message_Quit */
  553.       finish();
  554.     case 1:    /* Message_DataSave */
  555.       if (reason==19 && block[1]==task_handle) {
  556.         /* Returned to sender ... */
  557.         opting_icon=0;
  558.         return 0; }
  559.       if (block[5]!=-2 || *output_name) return 0;
  560.       block[0]=60;        /* size of block */
  561.       block[3]=block[2];    /* your_ref */
  562.       block[4]=2;        /* DataSaveAck */
  563.       block[9]=-1;        /* not safe */
  564.       strcpy((char*)(block+11),"<Wimp$Scrap>");
  565.       wimp_sendmessage(reason_message,block,block[1]);
  566.       break;
  567.     case 2:    /* Message_DataSaveAck */
  568.       if (opting_icon) {
  569.         char *z;
  570.         if (block[1]==task_handle) {
  571.           opting_icon=0; return 0; }
  572.         switch(opting_icon) {
  573.           case oi_tagfile_icon: z=tagfile_name; break;
  574.           case oi_sprfile_icon: z=spritefile_name; break;
  575.           case oi_jpegpfx_icon: z=jpeg_prefix; break;
  576.           default: return 0; /* shouldn't happen */
  577.         }
  578.         strcpy(z,(char*)(block+11));
  579.         wimp_seticonstate(opt_handle,opting_icon+1,0,0);
  580.         opting_icon=0; return 0;
  581.         /* *Don't* send DataLoad: we haven't saved anything! */
  582.       } else {
  583.         strcpy(save_name,(char*)(block+11));
  584.         wimp_seticonstate(save_handle,sv_name,0,0);
  585.         do_really_save();
  586.         block[3]=block[2];    /* your_ref */
  587.         block[4]=3;        /* DataLoad */
  588.         wimp_sendmessage(reason_message_rec,block,block[1]);
  589.       }
  590.       break;
  591.     case 3:    /* Message_DataLoad */
  592.       if (reason==19 && block[1]==task_handle) {
  593.         /* Returned to sender ... */
  594.         err(&save_failed);
  595.         return 0;
  596.       }
  597.       if (block[5]!=-2) return 0;    /* not iconbar icon */
  598. #if 0
  599.       if (block[1]==task_handle && saving) {
  600.         remove(output_name); *output_name=0; busy=0; saving=0;
  601.         err(&save_failed); return 0; }
  602. #endif
  603.       switch(block[10]) {
  604.         case 0xFFF: case 0xFE4:
  605.           launch_mkdrawf((char*)(block+11)); break;
  606.         case 0xAFF: launch_decdrawf((char*)(block+11)); break;
  607.         default: return 0;    /* don't know how to deal with that... */
  608.       }
  609.       /* Better be polite and acknowledge the message */
  610.       block[3]=block[2];    /* your_ref */
  611.       block[4]=4;        /* DataLoadAck */
  612.       wimp_sendmessage(reason_message,block,block[1]);
  613.       break;
  614.     case 4:    /* Message_DataLoadAck */
  615.       break;
  616.   }
  617.   return 0;
  618. }
  619.  
  620. int main(void) {
  621.   init_wimp();
  622.   while (1)
  623.     wimp_poll(mask_null|mask_ptr_leaving|mask_ptr_entering|
  624.               mask_losecaret|mask_gaincaret);
  625.   /* Not reached: */
  626.   return 0;
  627. }
  628.