1 /* Title: -> c.xferrecv
2 * Purpose: general purpose import of data by dragging icon
7 /*----- Licensing note ----------------------------------------------------*
9 * This file is part of Straylight's Steel library.
11 * Steel is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
16 * Steel is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with Steel. If not, write to the Free Software Foundation,
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
45 #define XOS_ReadVarVal 0x20023
56 static wimp_t xferrecv_sendertask ;
57 static wimp_msgstr xferrecv_ack ;
59 static xferrecv_buffer_processor xferrecv_processbuff ;
60 static char *xferrecv_buffer ;
61 static int xferrecv_buffersize ;
62 static int xferrecv_state ;
63 static int xferrecv_msgid ;
65 static flex_ptr xferrecv__flex;
66 static int xferrecv__returnBlockSize;
68 static char xferrecv__nameToImport[256];
71 static int xferrecv__fileissafe ;
73 int xferrecv_checkinsert(char **filename)
76 wimp_eventstr *e = wimpt_last_event();
78 if ((e->e==wimp_ESENDWANTACK || e->e == wimp_ESEND) &&
79 (e->data.msg.hdr.action == wimp_MDATALOAD ||
80 e->data.msg.hdr.action == wimp_MDATAOPEN))
82 tracef4("xferrecv_checkinsert returning filetype %x: %d %d %d\n",
83 e->data.msg.data.dataload.type,
84 scrap_ref,e->data.msg.hdr.your_ref,e->data.msg.hdr.my_ref) ;
85 xferrecv__fileissafe = e->data.msg.hdr.your_ref != scrap_ref ||
87 xferrecv_ack.hdr.action = wimp_MDATALOADOK ;
88 xferrecv_ack.hdr.size = sizeof(wimp_msghdr) ;
89 xferrecv_sendertask = e->data.msg.hdr.task ;
90 xferrecv_ack.hdr.your_ref = e->data.msg.hdr.my_ref ;
91 *filename = e->data.msg.data.dataload.name ;
92 if (xferrecv__fileissafe)
93 strcpy(xferrecv__nameToImport,*filename);
94 return e->data.msg.data.dataload.type ;
99 void xferrecv_insertfileok(void)
101 /* An insert has been completed successfully. This sends an acknowledge back
102 to the original application. */
104 tracef0("xferrecv_insertfileok\n") ;
106 if (!xferrecv__fileissafe)
108 tracef0("Must delete scrap file\n") ;
109 os_cli("%remove <Wimp$Scrap>") ;
112 (void) wimp_sendmessage(wimp_ESEND, &xferrecv_ack, xferrecv_sendertask);
115 int xferrecv_checkprint(char **filename)
117 wimp_eventstr *e = wimpt_last_event();
119 if ((e->e==wimp_ESENDWANTACK || e->e == wimp_ESEND) &&
120 (e->data.msg.hdr.action == wimp_MPrintTypeOdd))
122 tracef4("xferrecv_checkprint returning filetype %x: %d %d %d\n",
123 e->data.msg.data.print.type,
124 scrap_ref,e->data.msg.hdr.your_ref,e->data.msg.hdr.my_ref) ;
126 xferrecv__fileissafe = 0 ;
127 xferrecv_ack.hdr.action = wimp_MPrintTypeKnown ;
128 xferrecv_ack.hdr.size = sizeof(wimp_msghdr)+sizeof(wimp_msgprint) ;
129 xferrecv_sendertask = e->data.msg.hdr.task ;
130 xferrecv_ack.hdr.your_ref = e->data.msg.hdr.my_ref ;
131 *filename = e->data.msg.data.print.name ;
132 return e->data.msg.data.print.type ;
138 void xferrecv_printfileok(int type)
140 xferrecv_ack.data.print.type = type ;
141 (void) wimp_sendmessage(wimp_ESEND, &xferrecv_ack, xferrecv_sendertask);
144 int xferrecv_checkimport(int *estsize)
146 wimp_eventstr *e = wimpt_last_event();
148 if ((e->e==wimp_ESENDWANTACK || e->e == wimp_ESEND) &&
149 e->data.msg.hdr.action == wimp_MDATASAVE)
151 xferrecv_ack.hdr.size = sizeof(wimp_msghdr) + sizeof(wimp_msgdatasaveok) ;
152 xferrecv_sendertask = e->data.msg.hdr.task ;
153 xferrecv_ack.hdr.your_ref = e->data.msg.hdr.my_ref ;
154 xferrecv_ack.hdr.action = wimp_MDATASAVEOK ;
155 xferrecv_ack.data.datasaveok.w = e->data.msg.data.datasave.w ;
156 xferrecv_ack.data.datasaveok.i = e->data.msg.data.datasave.i ;
157 xferrecv_ack.data.datasaveok.x = e->data.msg.data.datasave.x ;
158 xferrecv_ack.data.datasaveok.y = e->data.msg.data.datasave.y ;
159 xferrecv_ack.data.datasaveok.type = e->data.msg.data.datasave.type ;
160 *estsize = xferrecv_ack.data.datasaveok.estsize
161 = e->data.msg.data.datasave.estsize ;
162 strcpy(xferrecv__nameToImport,e->data.msg.data.datasave.leaf);
163 tracef2("xferrecv_checkimport returning filetype %x from %d\n",
164 e->data.msg.data.datasave.type,xferrecv_sendertask) ;
166 return xferrecv_ack.data.datasaveok.type = e->data.msg.data.datasave.type ;
172 * char *xferrecv_nameToImport(void)
175 * Returns the name of the file to import (full pathname if available).
178 * A pointer to a read-only string.
181 char *xferrecv_nameToImport(void)
183 return (xferrecv__nameToImport);
186 static void xferrecv_sendRAMFETCH(void)
188 char *addr = xferrecv_ack.data.ramfetch.addr ;
189 int size = xferrecv_ack.data.ramfetch.nbytes ;
190 int action = xferrecv_ack.hdr.action ;
192 tracef2("xferrecv_sendRAMFETCH with buffer %x, size %d :",
193 (int) xferrecv_buffer,xferrecv_buffersize) ;
195 xferrecv_ack.hdr.action = wimp_MRAMFETCH ;
196 xferrecv_ack.data.ramfetch.addr = xferrecv_buffer ;
197 xferrecv_ack.data.ramfetch.nbytes = xferrecv_buffersize ;
198 (void) wimp_sendmessage(wimp_ESENDWANTACK,
200 xferrecv_sendertask);
201 xferrecv_msgid = xferrecv_ack.hdr.my_ref ;
203 tracef1(" ramfetch msg id %d\n",xferrecv_msgid) ;
205 xferrecv_ack.data.ramfetch.addr=addr ;
206 xferrecv_ack.data.ramfetch.nbytes=size ;
207 xferrecv_ack.hdr.action = action ;
210 static BOOL xferrecv_unknown_events(wimp_eventstr *e, void *handle)
215 tracef("xferrecv_unknown_events %d %d %d %d %d\n",e->e,
216 e->data.msg.hdr.action,e->data.msg.hdr.my_ref,
217 e->data.msg.hdr.your_ref,xferrecv_msgid) ;
220 if ((e->e == wimp_ESEND || e->e == wimp_ESENDWANTACK) &&
221 e->data.msg.hdr.your_ref == xferrecv_msgid &&
222 e->data.msg.hdr.action == wimp_MRAMTRANSMIT)
224 tracef2("xferrecv got ramtransmit of %d into %d\n",
225 e->data.msg.data.ramtransmit.nbyteswritten,xferrecv_buffersize) ;
226 if (e->data.msg.data.ramtransmit.nbyteswritten == xferrecv_buffersize)
228 /* other end has filled our buffer; better try and allocate some more
230 if (xferrecv_processbuff(&xferrecv_buffer, &xferrecv_buffersize))
233 tracef2("users buffer processor set buffer %x, size %d\n",
234 (int) xferrecv_buffer, xferrecv_buffersize) ;
236 xferrecv_ack.hdr.your_ref = e->data.msg.hdr.my_ref ;
237 xferrecv_sendRAMFETCH() ;
238 xferrecv_state = xferrecv_state_Talk ;
242 tracef0("users buffer processor failed: break down\n") ;
243 xferrecv_state = xferrecv_state_Broken ;
248 tracef0("xferrecv had final ramtransmit; set done state\n") ;
249 xferrecv_state = xferrecv_state_Done ;
250 xferrecv_buffersize=e->data.msg.data.ramtransmit.nbyteswritten;
251 if (xferrecv_buffersize!=0)
253 if (!xferrecv_processbuff(&xferrecv_buffer, &xferrecv_buffersize))
254 xferrecv_state = xferrecv_state_Broken ;
256 xferrecv_buffersize = e->data.msg.data.ramtransmit.nbyteswritten ;
259 else if (e->e == wimp_EACK && e->data.msg.hdr.my_ref == xferrecv_msgid)
261 tracef0("xferrecv ramfetch bounced: ") ;
262 /* got our message back */
263 if (xferrecv_state == xferrecv_state_Ask)
264 xferrecv_importByScrap();
267 tracef0("tell the user the protocol fell down\n") ;
268 werr(0, msgs_lookup("xferrecv2:Data transfer failed.")) ;
270 xferrecv_state = xferrecv_state_Broken ;
278 * void xferrecv_importByScrap(void)
281 * Tells xferrecv not to bother with RAM transfer, but to use the
282 * <Wimp$Scrap> file instead. It checks that the system variables and
283 * everything are set up right beforehand.
286 void xferrecv_importByScrap(void)
289 tracef0("ask for Wimp$Scrap transfer\n") ;
291 /* first check that variable exists */
292 r.r[0] = (int) "Wimp$Scrap" ;
297 os_swix(XOS_ReadVarVal, &r) ;
300 werr(0,msgs_lookup("xferrecv1:Can't transfer file (use *Set Wimp$Scrap <filename>)")) ;
303 strcpy(xferrecv_ack.data.datasaveok.name, "<Wimp$Scrap>") ;
304 xferrecv_ack.data.datasaveok.estsize = -1 ; /* file is not safe with us */
305 (void) wimp_sendmessage(wimp_ESEND, &xferrecv_ack, xferrecv_sendertask);
306 scrap_ref = xferrecv_ack.hdr.my_ref ;
310 int xferrecv_doimport(char *buf, int size, xferrecv_buffer_processor p)
313 /* Receives data into the buffer; calls the buffer processor if the buffer
314 given becomes full. Returns TRUE if the transaction completed sucessfully.
317 win_add_unknown_event_processor(xferrecv_unknown_events, 0) ;
319 tracef0("xferrecv_doimport entered\n") ;
320 xferrecv_processbuff = p ;
321 xferrecv_buffer = buf ;
322 xferrecv_buffersize = size ;
323 xferrecv_sendRAMFETCH() ;
324 xferrecv_state = xferrecv_state_Ask ;
325 xferrecv__fileissafe = FALSE ;
330 } while (xferrecv_state < xferrecv_state_Done) ;
332 win_remove_unknown_event_processor(xferrecv_unknown_events, 0) ;
334 return (xferrecv_state == xferrecv_state_Done ? xferrecv_buffersize : -1 ) ;
338 * BOOL xferrecv__returnBlockBuffProcessor(char **buff,int *size)
341 * Buffer processor for xferrecv_returnImportedBlock.
344 static BOOL xferrecv__returnBlockBuffProcessor(char **buff,int *size)
346 if (!flex_extend(xferrecv__flex,xferrecv__returnBlockSize+8192))
348 xferrecv__returnBlockSize+=8192;
355 * int xferrecv_returnImportedBlock(flex_ptr p)
358 * Performs the data import if possible, and returns with the block filled
359 * with *ALL* the imported data i.e. it obviates the need of any work on
360 * your part for the data transfer. This is the life, huh? If anything
361 * went wrong, it returns -1 as for xferrecv_doimport
364 * flex_ptr p == flex pointer to nothing in particular (certainly not a
365 * flex block - one is allocated for you). Remember to free it after
366 * you've read all the data! Also ensure that flex has been initialised.
367 * If there is no data to import (i.e. the import failed) then p is freed
368 * of any data that may have been stored there.
371 * -1 for failure, or the total size of the imported data for success
374 int xferrecv_returnImportedBlock(flex_ptr p)
377 if (!flex_alloc(p,xferrecv_ack.data.datasaveok.estsize))
379 xferrecv__returnBlockSize=xferrecv_ack.data.datasaveok.estsize;
380 if (xferrecv_doimport(*p,xferrecv_ack.data.datasaveok.estsize,
381 xferrecv__returnBlockBuffProcessor)==-1)
386 return (xferrecv__returnBlockSize);
389 BOOL xferrecv_file_is_safe()
391 return xferrecv__fileissafe ;