home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / dreamscape / source / Dreamscape / Sources / low-level / c / datasave next >
Encoding:
Text File  |  1996-09-10  |  6.1 KB  |  196 lines

  1.  
  2. /* low-level.c.datasave
  3.  *
  4.  * Dreamscape - C++ class library for RISC OS
  5.  * Copyright (c) 1996 Mark Seaborn <mseaborn@argonet.co.uk>
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Library General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2 of the License, or (at your option) any later version.
  11.  * See the Dreamscape documentation for more information.
  12.  */
  13.  
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include "OS:wimp.h"
  17.  
  18. #include "datasave.h"
  19. #include "wimpmsg.h"
  20. #include "task.h"
  21.  
  22.  
  23. static const dscape_datasave_client *client = 0;
  24. static const dscape_datasave_element *current_element;
  25. static void *transfer_data = 0;
  26. static size_t transfer_size, sent_size;
  27. static bool initialised = 0;
  28.  
  29. static bool message_data_save_ack(const wimp_message *message, void *handle);
  30. static bool message_data_load_ack(const wimp_message *message, void *handle);
  31. static bool message_ram_fetch(const wimp_message *message, void *handle);
  32.  
  33. void dscape_datasave_initialise(void)
  34. {
  35.   if(!initialised++) {
  36.     dscape_wimpmsg_register_handler(message_DATA_SAVE_ACK,
  37.     message_data_save_ack, 0);
  38.     dscape_wimpmsg_register_handler(message_DATA_LOAD_ACK,
  39.     message_data_load_ack, 0);
  40.     dscape_wimpmsg_register_handler(message_RAM_FETCH, message_ram_fetch, 0);
  41.   }
  42. }
  43.  
  44. void dscape_datasave_finalise(void)
  45. {
  46.   if(initialised--) {
  47.     dscape_wimpmsg_deregister_handler(message_DATA_SAVE_ACK,
  48.     message_data_save_ack, 0);
  49.     dscape_wimpmsg_deregister_handler(message_DATA_LOAD_ACK,
  50.     message_data_load_ack, 0);
  51.     dscape_wimpmsg_deregister_handler(message_RAM_FETCH,
  52.     message_ram_fetch, 0);
  53.   }
  54. }
  55.  
  56. void dscape_datasave_data_transfer(const dscape_datasave_client *nclient,
  57.     const dscape_datasave_info *info)
  58. {
  59.   wimp_message message;
  60.   dscape_datasave_element *e;
  61.  
  62.   client = nclient;
  63.   current_element = client->elements;
  64.   transfer_data = 0;
  65.  
  66.   if(client->save_starting) client->save_starting(client->handle);
  67.   message.action = message_DATA_SAVE;
  68.   message.my_ref = message.your_ref = 0;
  69.   message.data.data_xfer.w = info->window;
  70.   message.data.data_xfer.i = info->icon;
  71.   message.data.data_xfer.pos.x = info->pos.x;
  72.   message.data.data_xfer.pos.y = info->pos.y;
  73.  
  74.   message.data.data_xfer.est_size = 0;
  75.   for(e=client->elements; e; e=e->next) {
  76.     switch(e->type) {
  77.     case dscape_datasave_simple_element_no:
  78.       message.data.data_xfer.est_size += e->data.simple.size;
  79.       break;
  80.     case dscape_datasave_complex_element_no:
  81.       if(e->data.complex.estimate_size) message.data.data_xfer.est_size +=
  82.         e->data.complex.estimate_size(e->data.complex.handle);
  83.       break;
  84.     }
  85.   }
  86.   message.data.data_xfer.file_type = info->type;
  87.   strcpy(message.data.data_xfer.file_name, info->leaf_name);
  88.   message.size = (strlen(message.data.data_xfer.file_name) + 48) & ~3;
  89.   wimp_send_message_to_window(wimp_USER_MESSAGE, &message, info->window,
  90.     info->icon);
  91. }
  92.  
  93. static bool message_data_save_ack(const wimp_message *message, void *handle)
  94. {
  95.   FILE *file;
  96.   dscape_datasave_element *e;
  97.   wimp_message reply;
  98.  
  99.   if(!client) return 1;
  100.   file = fopen(message->data.data_xfer.file_name, "wb");
  101.   for(e=client->elements; e; e=e->next) {
  102.     switch(e->type) {
  103.     case dscape_datasave_simple_element_no:
  104.       fwrite(e->data.simple.data, e->data.simple.size, 1, file);
  105.       break;
  106.     case dscape_datasave_complex_element_no:
  107.       if(e->data.complex.output_data) {
  108.         e->data.complex.output_data(file, e->data.complex.handle);
  109.       }
  110.       else if(e->data.complex.initialise_data) {
  111.         void *data;
  112.         size_t size;
  113.         e->data.complex.initialise_data(&data, &size,
  114.         e->data.complex.handle);
  115.         fwrite(data, size, 1, file);
  116.         if(e->data.complex.finalise_data)
  117.           e->data.complex.finalise_data(data, size, e->data.complex.handle);
  118.       }
  119.       break;
  120.     }
  121.   }
  122.   fclose(file);
  123.  
  124.   if(message->data.data_xfer.est_size != -1 && client->save_safe)
  125.     client->save_safe(message->data.data_xfer.file_name, client->handle);
  126.  
  127.   reply = *message;
  128.   reply.your_ref = message->my_ref;
  129.   reply.my_ref = message->your_ref;
  130.   reply.action = message_DATA_LOAD;
  131.   wimp_send_message(wimp_USER_MESSAGE, &reply, message->sender);
  132.   return 1;
  133. }
  134.  
  135. static bool message_data_load_ack(const wimp_message *message, void *handle)
  136. {
  137.   if(!client) return 1;
  138.  
  139.   if(client->save_completed) client->save_completed(client->handle);
  140.   client = 0;
  141.   return 1;
  142. }
  143.  
  144. static bool message_ram_fetch(const wimp_message *message, void *handle)
  145. {
  146.   wimp_message reply;
  147.   size_t message_sent = 0;
  148.   if(!client) return 1;
  149.  
  150.   reply = *message;
  151.   reply.your_ref = message->my_ref;
  152.   reply.my_ref = message->your_ref;
  153.   reply.action = message_RAM_TRANSMIT;
  154.  
  155.   while(current_element && message_sent < message->data.ram_xfer.size) {
  156.     size_t now_sending;
  157.     if(!transfer_data) {
  158.       sent_size = 0;
  159.       switch(current_element->type) {
  160.       case dscape_datasave_simple_element_no:
  161.         transfer_data = current_element->data.simple.data;
  162.         transfer_size = current_element->data.simple.size;
  163.         break;
  164.       case dscape_datasave_complex_element_no:
  165.         if(!current_element->data.complex.initialise_data) continue;
  166.         current_element->data.complex.initialise_data(&transfer_data,
  167.           &transfer_size, current_element->data.complex.handle);
  168.         break;
  169.       }
  170.     }
  171.     now_sending = transfer_size - sent_size;
  172.     if(now_sending > reply.data.ram_xfer.size)
  173.       now_sending = reply.data.ram_xfer.size;
  174.     wimp_transfer_block(dscape_task_get_handle(), (byte *) transfer_data +
  175.     sent_size, message->sender, message->data.ram_xfer.addr,
  176.     now_sending);
  177.     message_sent += now_sending;
  178.     sent_size += now_sending;
  179.  
  180.     if(sent_size >= transfer_size) {
  181.       switch(current_element->type) {
  182.       case dscape_datasave_complex_element_no:
  183.         if(current_element->data.complex.finalise_data)
  184.           current_element->data.complex.finalise_data(transfer_data,
  185.         transfer_size, current_element->data.complex.handle);
  186.         break;
  187.       }
  188.       transfer_data = 0;
  189.       current_element = current_element->next;
  190.     }
  191.   }
  192.   reply.data.ram_xfer.size = message_sent;
  193.   wimp_send_message(wimp_USER_MESSAGE, &reply, message->sender);
  194.   return 1;
  195. }
  196.