home *** CD-ROM | disk | FTP | other *** search
-
- /* low-level.c.datasave
- *
- * Dreamscape - C++ class library for RISC OS
- * Copyright (c) 1996 Mark Seaborn <mseaborn@argonet.co.uk>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- * See the Dreamscape documentation for more information.
- */
-
- #include <string.h>
- #include <stdio.h>
- #include "OS:wimp.h"
-
- #include "datasave.h"
- #include "wimpmsg.h"
- #include "task.h"
-
-
- static const dscape_datasave_client *client = 0;
- static const dscape_datasave_element *current_element;
- static void *transfer_data = 0;
- static size_t transfer_size, sent_size;
- static bool initialised = 0;
-
- static bool message_data_save_ack(const wimp_message *message, void *handle);
- static bool message_data_load_ack(const wimp_message *message, void *handle);
- static bool message_ram_fetch(const wimp_message *message, void *handle);
-
- void dscape_datasave_initialise(void)
- {
- if(!initialised++) {
- dscape_wimpmsg_register_handler(message_DATA_SAVE_ACK,
- message_data_save_ack, 0);
- dscape_wimpmsg_register_handler(message_DATA_LOAD_ACK,
- message_data_load_ack, 0);
- dscape_wimpmsg_register_handler(message_RAM_FETCH, message_ram_fetch, 0);
- }
- }
-
- void dscape_datasave_finalise(void)
- {
- if(initialised--) {
- dscape_wimpmsg_deregister_handler(message_DATA_SAVE_ACK,
- message_data_save_ack, 0);
- dscape_wimpmsg_deregister_handler(message_DATA_LOAD_ACK,
- message_data_load_ack, 0);
- dscape_wimpmsg_deregister_handler(message_RAM_FETCH,
- message_ram_fetch, 0);
- }
- }
-
- void dscape_datasave_data_transfer(const dscape_datasave_client *nclient,
- const dscape_datasave_info *info)
- {
- wimp_message message;
- dscape_datasave_element *e;
-
- client = nclient;
- current_element = client->elements;
- transfer_data = 0;
-
- if(client->save_starting) client->save_starting(client->handle);
- message.action = message_DATA_SAVE;
- message.my_ref = message.your_ref = 0;
- message.data.data_xfer.w = info->window;
- message.data.data_xfer.i = info->icon;
- message.data.data_xfer.pos.x = info->pos.x;
- message.data.data_xfer.pos.y = info->pos.y;
-
- message.data.data_xfer.est_size = 0;
- for(e=client->elements; e; e=e->next) {
- switch(e->type) {
- case dscape_datasave_simple_element_no:
- message.data.data_xfer.est_size += e->data.simple.size;
- break;
- case dscape_datasave_complex_element_no:
- if(e->data.complex.estimate_size) message.data.data_xfer.est_size +=
- e->data.complex.estimate_size(e->data.complex.handle);
- break;
- }
- }
- message.data.data_xfer.file_type = info->type;
- strcpy(message.data.data_xfer.file_name, info->leaf_name);
- message.size = (strlen(message.data.data_xfer.file_name) + 48) & ~3;
- wimp_send_message_to_window(wimp_USER_MESSAGE, &message, info->window,
- info->icon);
- }
-
- static bool message_data_save_ack(const wimp_message *message, void *handle)
- {
- FILE *file;
- dscape_datasave_element *e;
- wimp_message reply;
-
- if(!client) return 1;
- file = fopen(message->data.data_xfer.file_name, "wb");
- for(e=client->elements; e; e=e->next) {
- switch(e->type) {
- case dscape_datasave_simple_element_no:
- fwrite(e->data.simple.data, e->data.simple.size, 1, file);
- break;
- case dscape_datasave_complex_element_no:
- if(e->data.complex.output_data) {
- e->data.complex.output_data(file, e->data.complex.handle);
- }
- else if(e->data.complex.initialise_data) {
- void *data;
- size_t size;
- e->data.complex.initialise_data(&data, &size,
- e->data.complex.handle);
- fwrite(data, size, 1, file);
- if(e->data.complex.finalise_data)
- e->data.complex.finalise_data(data, size, e->data.complex.handle);
- }
- break;
- }
- }
- fclose(file);
-
- if(message->data.data_xfer.est_size != -1 && client->save_safe)
- client->save_safe(message->data.data_xfer.file_name, client->handle);
-
- reply = *message;
- reply.your_ref = message->my_ref;
- reply.my_ref = message->your_ref;
- reply.action = message_DATA_LOAD;
- wimp_send_message(wimp_USER_MESSAGE, &reply, message->sender);
- return 1;
- }
-
- static bool message_data_load_ack(const wimp_message *message, void *handle)
- {
- if(!client) return 1;
-
- if(client->save_completed) client->save_completed(client->handle);
- client = 0;
- return 1;
- }
-
- static bool message_ram_fetch(const wimp_message *message, void *handle)
- {
- wimp_message reply;
- size_t message_sent = 0;
- if(!client) return 1;
-
- reply = *message;
- reply.your_ref = message->my_ref;
- reply.my_ref = message->your_ref;
- reply.action = message_RAM_TRANSMIT;
-
- while(current_element && message_sent < message->data.ram_xfer.size) {
- size_t now_sending;
- if(!transfer_data) {
- sent_size = 0;
- switch(current_element->type) {
- case dscape_datasave_simple_element_no:
- transfer_data = current_element->data.simple.data;
- transfer_size = current_element->data.simple.size;
- break;
- case dscape_datasave_complex_element_no:
- if(!current_element->data.complex.initialise_data) continue;
- current_element->data.complex.initialise_data(&transfer_data,
- &transfer_size, current_element->data.complex.handle);
- break;
- }
- }
- now_sending = transfer_size - sent_size;
- if(now_sending > reply.data.ram_xfer.size)
- now_sending = reply.data.ram_xfer.size;
- wimp_transfer_block(dscape_task_get_handle(), (byte *) transfer_data +
- sent_size, message->sender, message->data.ram_xfer.addr,
- now_sending);
- message_sent += now_sending;
- sent_size += now_sending;
-
- if(sent_size >= transfer_size) {
- switch(current_element->type) {
- case dscape_datasave_complex_element_no:
- if(current_element->data.complex.finalise_data)
- current_element->data.complex.finalise_data(transfer_data,
- transfer_size, current_element->data.complex.handle);
- break;
- }
- transfer_data = 0;
- current_element = current_element->next;
- }
- }
- reply.data.ram_xfer.size = message_sent;
- wimp_send_message(wimp_USER_MESSAGE, &reply, message->sender);
- return 1;
- }
-