void gui_window_set_title(struct gui_window *gw, const char *title) { if (gw == NULL) return; if (gw->root) { int l; char * conv; l = strlen(title)+1; if (utf8_to_local_encoding(title, l-1, &conv) == UTF8_CONVERT_OK ) { l = MIN((uint32_t)atari_sysinfo.aes_max_win_title_len, strlen(conv)); if(gw->title == NULL) gw->title = malloc(l); else gw->title = realloc(gw->title, l); strncpy(gw->title, conv, l); free( conv ); } else { l = MIN((size_t)atari_sysinfo.aes_max_win_title_len, strlen(title)); if(gw->title == NULL) gw->title = malloc(l); else gw->title = realloc(gw->title, l); strncpy(gw->title, title, l); } gw->title[l] = 0; if(input_window == gw) window_set_title(gw->root, gw->title); } }
/** * Core asks front end for clipboard contents. * * \param buffer UTF-8 text, allocated by front end, ownership yeilded to core * \param length Byte length of UTF-8 text in buffer */ void gui_get_clipboard(char **buffer, size_t *length) { char *clip; size_t clip_len; *length = 0; *buffer = 0; clip = scrap_txt_read(); if(clip == NULL) { return; } else { // clipboard is in atari encoding, convert it to utf8: char *utf8 = NULL; utf8_convert_ret ret; clip_len = strlen(clip); if (clip_len > 0) { ret = utf8_to_local_encoding(clip, clip_len, &utf8); if (ret == UTF8_CONVERT_OK && utf8 != NULL) { *buffer = utf8; *length = strlen(utf8); } else { assert(ret == UTF8_CONVERT_OK && utf8 != NULL); } } free(clip); } }
bool utf8_save_text(const char *utf8_text, const char *path) { utf8_convert_ret ret; char *conv; FILE *out; ret = utf8_to_local_encoding(utf8_text, strlen(utf8_text), &conv); if (ret != UTF8_CONVERT_OK) { LOG(("failed to convert to local encoding, return %d", ret)); return false; } out = fopen(path, "w"); if (out) { int res = fputs(conv, out); if (res < 0) { LOG(("Warning: writing data failed")); } res = fputs("\n", out); fclose(out); free(conv); return (res != EOF); } free(conv); return false; }
static void gui_set_clipboard(const char *buffer, size_t length, nsclipboard_styles styles[], int n_styles) { char *text; struct CSet cset = {0}; if(buffer == NULL) return; if(!(OpenIFF(iffh, IFFF_WRITE))) { if(!(PushChunk(iffh, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN))) { if(nsoption_bool(clipboard_write_utf8)) { if(!(PushChunk(iffh, 0, ID_CSET, 32))) { cset.CodeSet = 106; // UTF-8 WriteChunkBytes(iffh, &cset, 32); PopChunk(iffh); } } } else { PopChunk(iffh); } if(!(PushChunk(iffh, 0, ID_CHRS, IFFSIZE_UNKNOWN))) { if(nsoption_bool(clipboard_write_utf8)) { WriteChunkBytes(iffh, buffer, length); } else { if(utf8_to_local_encoding(buffer, length, &text) == NSERROR_OK) { char *p; p = text; while(*p != '\0') { if(*p == 0xa0) *p = 0x20; p++; } WriteChunkBytes(iffh, text, strlen(text)); ami_utf8_free(text); } } PopChunk(iffh); } else { PopChunk(iffh); } if(!(PushChunk(iffh, 0, ID_UTF8, IFFSIZE_UNKNOWN))) { WriteChunkBytes(iffh, buffer, length); PopChunk(iffh); } else { PopChunk(iffh); } CloseIFF(iffh); } }
char *ami_utf8_easy(const char *string) { char *localtext; if(utf8_to_local_encoding(string,strlen(string),&localtext) == NSERROR_OK) { return localtext; } else { return strdup(string); } }
/** * Core tells front end to put given text in clipboard * * \param buffer UTF-8 text, owned by core * \param length Byte length of UTF-8 text in buffer * \param styles Array of styles given to text runs, owned by core, or NULL * \param n_styles Number of text run styles in array */ void gui_set_clipboard(const char *buffer, size_t length, nsclipboard_styles styles[], int n_styles) { if (length > 0 && buffer != NULL) { // convert utf8 input to atari encoding: utf8_convert_ret ret; char *clip = NULL; ret = utf8_to_local_encoding(buffer,length, &clip); if (ret == UTF8_CONVERT_OK) { scrap_txt_write(clip); } else { assert(ret == UTF8_CONVERT_OK); } free(clip); } }
query_id query_user_xy(const char *query, const char *detail, const query_callback *cb, void *pw, const char *yes, const char *no, int x, int y) { struct gui_query_window *qw; char query_buffer[300]; os_error *error; wimp_icon *icn; int width; int len; int tx; char *local_text = NULL; nserror err; qw = malloc(sizeof(struct gui_query_window)); if (!qw) { warn_user("NoMemory", NULL); return QUERY_INVALID; } qw->cb = cb; qw->pw = pw; qw->id = next_id++; qw->default_confirm = false; if (next_id == QUERY_INVALID) next_id++; if (!yes) yes = messages_get("Yes"); if (!no) no = messages_get("No"); /* set the text of the 'Yes' button and size accordingly */ err = utf8_to_local_encoding(yes, 0, &local_text); if (err != NSERROR_OK) { assert(err != NSERROR_BAD_ENCODING); LOG(("utf8_to_local_encoding_failed")); local_text = NULL; } icn = &query_template->icons[ICON_QUERY_YES]; len = strlen(local_text ? local_text : yes); len = max(len, icn->data.indirected_text.size - 1); memcpy(icn->data.indirected_text.text, local_text ? local_text: yes, len); icn->data.indirected_text.text[len] = '\0'; free(local_text); local_text = NULL; error = xwimptextop_string_width(icn->data.indirected_text.text, len, &width); if (error) { LOG(("xwimptextop_string_width: 0x%x:%s", error->errnum, error->errmess)); width = len * 16; } if (!query_yes_width) query_yes_width = icn->extent.x1 - icn->extent.x0; width += 44; if (width < query_yes_width) width = query_yes_width; icn->extent.x0 = tx = icn->extent.x1 - width; /* set the text of the 'No' button and size accordingly */ err = utf8_to_local_encoding(no, 0, &local_text); if (err != NSERROR_OK) { assert(err != NSERROR_BAD_ENCODING); LOG(("utf8_to_local_encoding_failed")); local_text = NULL; } icn = &query_template->icons[ICON_QUERY_NO]; len = strlen(local_text ? local_text : no); len = max(len, icn->data.indirected_text.size - 1); memcpy(icn->data.indirected_text.text, local_text ? local_text : no, len); icn->data.indirected_text.text[len] = '\0'; free(local_text); local_text = NULL; if (!query_no_width) query_no_width = icn->extent.x1 - icn->extent.x0; icn->extent.x1 = tx - 16; error = xwimptextop_string_width(icn->data.indirected_text.text, len, &width); if (error) { LOG(("xwimptextop_string_width: 0x%x:%s", error->errnum, error->errmess)); width = len * 16; } width += 28; if (width < query_no_width) width = query_no_width; icn->extent.x0 = icn->extent.x1 - width; error = xwimp_create_window(query_template, &qw->window); if (error) { warn_user("WimpError", error->errmess); free(qw); return QUERY_INVALID; } snprintf(query_buffer, sizeof query_buffer, "%s %s", messages_get(query), detail ? detail : ""); query_buffer[sizeof query_buffer - 1] = 0; ro_gui_set_icon_string(qw->window, ICON_QUERY_MESSAGE, query_buffer, true); xwimp_set_icon_state(qw->window, ICON_QUERY_HELP, wimp_ICON_DELETED, wimp_ICON_DELETED); if (x >= 0 && y >= 0) { x -= tx - 8; y += (query_template->visible.y1 - query_template->visible.y0) / 2; ro_gui_dialog_open_xy(qw->window, x, y); } else ro_gui_dialog_open(qw->window); ro_gui_wimp_event_set_user_data(qw->window, qw); ro_gui_wimp_event_register_mouse_click(qw->window, ro_gui_query_click); ro_gui_wimp_event_register_cancel(qw->window, ICON_QUERY_NO); ro_gui_wimp_event_register_ok(qw->window, ICON_QUERY_YES, ro_gui_query_apply); ro_gui_wimp_event_register_close_window(qw->window, ro_gui_query_close); error = xwimp_set_caret_position(qw->window, (wimp_i)-1, 0, 0, 1 << 25, -1); if (error) { LOG(("xwimp_get_caret_position: 0x%x : %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); } /* put this query window at the head of our list */ if (gui_query_window_list) gui_query_window_list->prev = qw; qw->prev = NULL; qw->next = gui_query_window_list; gui_query_window_list = qw; return qw->id; }
void ro_gui_download_update_status(struct gui_download_window *dw) { char *received; char *total_size; char *speed; char time[20] = "?"; struct timeval t; float dt; unsigned int left; float rate; os_error *error; int width; char *local_status; utf8_convert_ret err; gettimeofday(&t, 0); dt = (t.tv_sec + 0.000001 * t.tv_usec) - (dw->last_time.tv_sec + 0.000001 * dw->last_time.tv_usec); if (dt == 0) dt = 0.001; total_size = human_friendly_bytesize(max(dw->received, dw->total_size)); if (dw->ctx) { rate = (dw->received - dw->last_received) / dt; received = human_friendly_bytesize(dw->received); /* A simple 'modified moving average' download rate calculation * to smooth out rate fluctuations: chosen for simplicity. */ dw->average_points++; dw->average_rate = ((dw->average_points - 1) * dw->average_rate + rate) / dw->average_points; speed = human_friendly_bytesize(dw->average_rate); if (dw->total_size) { float f; if (dw->average_rate > 0) { left = (dw->total_size - dw->received) / dw->average_rate; sprintf(time, "%u:%.2u", left / 60, left % 60); } /* convert to local encoding */ err = utf8_to_local_encoding( messages_get("Download"), 0, &local_status); if (err != UTF8_CONVERT_OK) { /* badenc should never happen */ assert(err != UTF8_CONVERT_BADENC); /* hide nomem error */ snprintf(dw->status, sizeof dw->status, messages_get("Download"), received, total_size, speed, time); } else { snprintf(dw->status, sizeof dw->status, local_status, received, total_size, speed, time); free(local_status); } f = (float) dw->received / (float) dw->total_size; width = download_progress_width * f; } else { left = t.tv_sec - dw->start_time.tv_sec; sprintf(time, "%u:%.2u", left / 60, left % 60); err = utf8_to_local_encoding( messages_get("DownloadU"), 0, &local_status); if (err != UTF8_CONVERT_OK) { /* badenc should never happen */ assert(err != UTF8_CONVERT_BADENC); /* hide nomem error */ snprintf(dw->status, sizeof dw->status, messages_get("DownloadU"), received, speed, time); } else { snprintf(dw->status, sizeof dw->status, local_status, received, speed, time); free(local_status); } /* length unknown, stay at 0 til finished */ width = 0; } } else { left = dw->last_time.tv_sec - dw->start_time.tv_sec; if (left == 0) left = 1; rate = (float) dw->received / (float) left; sprintf(time, "%u:%.2u", left / 60, left % 60); speed = human_friendly_bytesize(rate); err = utf8_to_local_encoding(messages_get("Downloaded"), 0, &local_status); if (err != UTF8_CONVERT_OK) { /* badenc should never happen */ assert(err != UTF8_CONVERT_BADENC); /* hide nomem error */ snprintf(dw->status, sizeof dw->status, messages_get("Downloaded"), total_size, speed, time); } else { snprintf(dw->status, sizeof dw->status, local_status, total_size, speed, time); free(local_status); } /* all done */ width = download_progress_width; } dw->last_time = t; dw->last_received = dw->received; error = xwimp_resize_icon(dw->window, ICON_DOWNLOAD_PROGRESS, download_progress_x0, download_progress_y0, download_progress_x0 + width, download_progress_y1); if (error) { LOG(("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); } error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_STATUS, 0, 0); if (error) { LOG(("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); } if (dw->ctx) schedule(100, ro_gui_download_update_status_wrapper, dw); else schedule_remove(ro_gui_download_update_status_wrapper, dw); }
struct gui_download_window *gui_download_window_create(download_context *ctx, struct gui_window *gui) { const char *url = download_context_get_url(ctx); const char *mime_type = download_context_get_mime_type(ctx); const char *temp_name; char *scheme = NULL; char *filename = NULL; struct gui_download_window *dw; bool space_warning = false; os_error *error; url_func_result res; char *local_path; utf8_convert_ret err; size_t i, last_dot; dw = malloc(sizeof *dw); if (!dw) { warn_user("NoMemory", 0); return 0; } dw->ctx = ctx; dw->saved = false; dw->close_confirmed = false; dw->error = false; dw->query = QUERY_INVALID; dw->received = 0; dw->total_size = download_context_get_total_length(ctx); strncpy(dw->url, url, sizeof dw->url); dw->url[sizeof dw->url - 1] = 0; dw->status[0] = 0; gettimeofday(&dw->start_time, 0); dw->last_time = dw->start_time; dw->last_received = 0; dw->file_type = 0; dw->average_rate = 0; dw->average_points = 0; /* Get scheme from URL */ res = url_scheme(url, &scheme); if (res == URL_FUNC_NOMEM) { warn_user("NoMemory", 0); free(dw); return 0; } else if (res == URL_FUNC_OK) { /* If we have a scheme and it's "file", then * attempt to use the local filetype directly */ if (strcasecmp(scheme, "file") == 0) { char *path = NULL; res = url_path(url, &path); if (res == URL_FUNC_NOMEM) { warn_user("NoMemory", 0); free(scheme); free(dw); return 0; } else if (res == URL_FUNC_OK) { char *raw_path = curl_unescape(path, strlen(path)); if (raw_path == NULL) { warn_user("NoMemory", 0); free(path); free(scheme); free(dw); return 0; } dw->file_type = ro_filetype_from_unix_path(raw_path); curl_free(raw_path); free(path); } } free(scheme); } /* If we still don't have a filetype (i.e. failed reading local * one or fetching a remote object), then use the MIME type */ if (dw->file_type == 0) { /* convert MIME type to RISC OS file type */ error = xmimemaptranslate_mime_type_to_filetype(mime_type, &(dw->file_type)); if (error) { LOG(("xmimemaptranslate_mime_type_to_filetype: 0x%x: %s", error->errnum, error->errmess)); warn_user("MiscError", error->errmess); dw->file_type = 0xffd; } } /* open temporary output file */ temp_name = ro_gui_download_temp_name(dw); if (!ro_gui_download_check_space(dw, temp_name, NULL)) { /* issue a warning but continue with the download because the user can save it to another medium whilst it's downloading */ space_warning = true; } error = xosfind_openoutw(osfind_NO_PATH | osfind_ERROR_IF_DIR, temp_name, 0, &dw->file); if (error) { LOG(("xosfind_openoutw: 0x%x: %s", error->errnum, error->errmess)); warn_user("SaveError", error->errmess); free(dw); return 0; } /* fill in download window icons */ download_template->icons[ICON_DOWNLOAD_URL].data.indirected_text.text = dw->url; download_template->icons[ICON_DOWNLOAD_URL].data.indirected_text.size = sizeof dw->url; download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text. text = dw->status; download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text. size = sizeof dw->status; sprintf(dw->sprite_name, "file_%.3x", dw->file_type); if (!ro_gui_wimp_sprite_exists(dw->sprite_name)) strcpy(dw->sprite_name, "file_xxx"); download_template->icons[ICON_DOWNLOAD_ICON].data.indirected_sprite.id = (osspriteop_id) dw->sprite_name; /* Get a suitable path- and leafname for the download. */ temp_name = download_context_get_filename(dw->ctx); if (temp_name == NULL) temp_name = messages_get("SaveObject"); if (temp_name != NULL) filename = strdup(temp_name); if (filename == NULL) { LOG(("Failed to establish download filename.")); warn_user("SaveError", error->errmess); free(dw); return 0; } for (i = 0, last_dot = (size_t) -1; filename[i] != '\0'; i++) { const char c = filename[i]; if (c == '.') { last_dot = i; filename[i] = '/'; } else if (c <= ' ' || strchr(":*#$&@^%\\", c) != NULL) filename[i] = '_'; } if (option_strip_extensions && last_dot != (size_t) -1) filename[last_dot] = '\0'; if (download_dir != NULL && strlen(download_dir) > 0) snprintf(dw->path, RO_DOWNLOAD_MAX_PATH_LEN, "%s.%s", download_dir, filename); else snprintf(dw->path, RO_DOWNLOAD_MAX_PATH_LEN, "%s", filename); err = utf8_to_local_encoding(dw->path, 0, &local_path); if (err != UTF8_CONVERT_OK) { /* badenc should never happen */ assert(err != UTF8_CONVERT_BADENC); LOG(("utf8_to_local_encoding failed")); warn_user("NoMemory", 0); free(dw); return 0; } else { strncpy(dw->path, local_path, sizeof dw->path); free(local_path); } download_template->icons[ICON_DOWNLOAD_PATH].data.indirected_text.text = dw->path; download_template->icons[ICON_DOWNLOAD_PATH].data.indirected_text.size = sizeof dw->path; download_template->icons[ICON_DOWNLOAD_DESTINATION].data. indirected_text.text = dw->path; download_template->icons[ICON_DOWNLOAD_DESTINATION].data. indirected_text.size = sizeof dw->path; download_template->icons[ICON_DOWNLOAD_DESTINATION].flags |= wimp_ICON_DELETED; /* create and open the download window */ error = xwimp_create_window(download_template, &dw->window); if (error) { LOG(("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); free(dw); return 0; } dw->prev = 0; dw->next = download_window_list; if (download_window_list) download_window_list->prev = dw; download_window_list = dw; ro_gui_download_update_status(dw); ro_gui_dialog_open(dw->window); ro_gui_wimp_event_set_user_data(dw->window, dw); ro_gui_wimp_event_register_mouse_click(dw->window, ro_gui_download_click); ro_gui_wimp_event_register_keypress(dw->window, ro_gui_download_keypress); ro_gui_wimp_event_register_close_window(dw->window, ro_gui_download_close); /* issue the warning now, so that it appears in front of the download * window! */ if (space_warning) warn_user("DownloadWarn", messages_get("NoDiscSpace")); return dw; }
/** * Suggest a leafname and sprite name for the given content. * * \param h content being saved * \param save_type type of save operation being performed * \param url used to determine leafname * \param leaf_buf buffer to receive suggested leafname. * \param leaf_len size of buffer to receive suggested leafname. * \param icon_buf buffer to receive sprite name. * \param icon_len size of buffer to receive icon name. */ static void ro_gui_save_set_state(struct hlcache_handle *h, gui_save_type save_type, const nsurl *url, char *leaf_buf, size_t leaf_len, char *icon_buf, size_t icon_len) { /* filename */ const char *name = gui_save_table[save_type].name; bool done = false; char *nice = NULL; nserror err; char *local_name; assert(icon_len >= 13); /* parameters that we need to remember */ gui_save_current_type = save_type; gui_save_content = h; /* suggest a filetype based upon the content */ gui_save_filetype = gui_save_table[save_type].filetype; if (!gui_save_filetype && h) { if (save_type == GUI_SAVE_OBJECT_NATIVE) { switch (ro_content_native_type(h)) { case osfile_TYPE_SPRITE: gui_save_filetype = osfile_TYPE_SPRITE; break; case osfile_TYPE_DRAW: gui_save_filetype = osfile_TYPE_DRAW; break; default: break; } } if (!gui_save_filetype) gui_save_filetype = ro_content_filetype(h); } /* leafname */ if ((url != NULL) && (nsurl_nice(url, &nice, nsoption_bool(strip_extensions)) == NSERROR_OK)) { size_t i; for (i = 0; nice[i]; i++) { if (nice[i] == '.') nice[i] = '/'; else if (nice[i] <= ' ' || strchr(":*#$&@^%\\", nice[i])) nice[i] = '_'; } name = nice; } else { name = messages_get(name); } /* filename is utf8 */ if (save_type == GUI_SAVE_COMPLETE && leaf_len > 0) { leaf_buf[0] = '!'; leaf_buf++; leaf_len--; } strncpy(leaf_buf, name, leaf_len); leaf_buf[leaf_len - 1] = 0; err = utf8_to_local_encoding(name, 0, &local_name); if (err != NSERROR_OK) { /* badenc should never happen */ assert(err != NSERROR_BAD_ENCODING); local_name = NULL; } if (local_name != NULL) name = local_name; /* sprite name used for icon and dragging */ if (save_type == GUI_SAVE_COMPLETE) { int index; /* Paint gets confused with uppercase characters and we need to convert spaces to hard spaces */ icon_buf[0] = '!'; for (index = 0; index < 11 && name[index]; ) { char ch = name[index]; if (ch == ' ') icon_buf[++index] = 0xa0; else icon_buf[++index] = tolower(ch); } memset(&icon_buf[index + 1], 0, 11 - index); icon_buf[12] = '\0'; if (ro_gui_save_create_thumbnail(h, icon_buf)) done = true; } if (!done) { osspriteop_header *sprite; os_error *error; sprintf(icon_buf, "file_%.3x", gui_save_filetype); error = ro_gui_wimp_get_sprite(icon_buf, &sprite); if (error && error->errnum == error_SPRITE_OP_DOESNT_EXIST) { /* try the 'unknown' filetype sprite as a fallback */ memcpy(icon_buf, "file_xxx", 9); error = ro_gui_wimp_get_sprite(icon_buf, &sprite); } if (error) { LOG("ro_gui_wimp_get_sprite: 0x%x: %s", error->errnum, error->errmess); ro_warn_user("MiscError", error->errmess); } else { /* the sprite area should always be large enough for * file_xxx sprites */ assert(sprite->size <= saveas_area->size - saveas_area->first); memcpy((byte*)saveas_area + saveas_area->first, sprite, sprite->size); saveas_area->sprite_count = 1; saveas_area->used = saveas_area->first + sprite->size; } } free(local_name); free(nice); }
/** * Translate a menu's textual content into the system local encoding * * \param menu The menu to translate * \return false if out of memory, true otherwise */ bool ro_gui_menu_translate(struct menu_definition *menu) { os_error *error; int alphabet; struct menu_definition_entry *entry; char *translated; nserror err; /* read current alphabet */ error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0, &alphabet); if (error) { LOG(("failed reading alphabet: 0x%x: %s", error->errnum, error->errmess)); /* assume Latin1 */ alphabet = territory_ALPHABET_LATIN1; } if (menu->current_encoding == alphabet) /* menu text is already in the correct encoding */ return true; /* translate root menu title text */ free(menu->menu->title_data.indirected_text.text); err = utf8_to_local_encoding(messages_get(menu->title_key), 0, &translated); if (err != NSERROR_OK) { assert(err != NSERROR_BAD_ENCODING); LOG(("utf8_to_enc failed")); return false; } /* and fill in WIMP menu field */ menu->menu->title_data.indirected_text.text = translated; /* now the menu entries */ for (entry = menu->entries; entry; entry = entry->next) { wimp_menu *submenu = entry->menu_entry->sub_menu; /* tranlate menu entry text */ free(entry->menu_entry->data.indirected_text.text); err = utf8_to_local_encoding(messages_get(entry->entry_key), 0, &translated); if (err != NSERROR_OK) { assert(err != NSERROR_BAD_ENCODING); LOG(("utf8_to_enc failed")); return false; } /* fill in WIMP menu fields */ entry->menu_entry->data.indirected_text.text = translated; entry->menu_entry->data.indirected_text.validation = (char *) -1; entry->menu_entry->data.indirected_text.size = strlen(translated); /* child menu title - this is the same as the text of * the parent menu entry, so just copy the pointer */ if (submenu != wimp_NO_SUB_MENU && IS_MENU(submenu)) { submenu->title_data.indirected_text.text = translated; } } /* finally, set the current encoding of the menu */ menu->current_encoding = alphabet; return true; }
static struct gui_download_window * gui_download_window_create(download_context *ctx, struct gui_window *gui) { nsurl *url = download_context_get_url(ctx); const char *temp_name; char *filename = NULL; struct gui_download_window *dw; bool space_warning = false; os_error *error; char *local_path; nserror err; size_t i, last_dot; dw = malloc(sizeof *dw); if (!dw) { ro_warn_user("NoMemory", 0); return 0; } dw->ctx = ctx; dw->saved = false; dw->close_confirmed = false; dw->error = false; dw->query = QUERY_INVALID; dw->received = 0; dw->total_size = download_context_get_total_length(ctx); /** @todo change this to take a reference to the nsurl and use * that value directly rather than using a fixed buffer. */ strncpy(dw->url, nsurl_access(url), sizeof dw->url); dw->url[sizeof dw->url - 1] = 0; dw->status[0] = 0; gettimeofday(&dw->start_time, 0); dw->last_time = dw->start_time; dw->last_received = 0; dw->file_type = 0; dw->average_rate = 0; dw->average_points = 0; /* get filetype */ err = download_ro_filetype(ctx, &dw->file_type); if (err != NSERROR_OK) { ro_warn_user(messages_get_errorcode(err), 0); free(dw); return 0; } /* open temporary output file */ temp_name = ro_gui_download_temp_name(dw); if (!ro_gui_download_check_space(dw, temp_name, NULL)) { /* issue a warning but continue with the download because the user can save it to another medium whilst it's downloading */ space_warning = true; } error = xosfind_openoutw(osfind_NO_PATH | osfind_ERROR_IF_DIR, temp_name, 0, &dw->file); if (error) { LOG("xosfind_openoutw: 0x%x: %s", error->errnum, error->errmess); ro_warn_user("SaveError", error->errmess); free(dw); return 0; } /* fill in download window icons */ download_template->icons[ICON_DOWNLOAD_URL].data.indirected_text.text = dw->url; download_template->icons[ICON_DOWNLOAD_URL].data.indirected_text.size = sizeof dw->url; download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text. text = dw->status; download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text. size = sizeof dw->status; sprintf(dw->sprite_name, "file_%.3x", dw->file_type); if (!ro_gui_wimp_sprite_exists(dw->sprite_name)) strcpy(dw->sprite_name, "file_xxx"); download_template->icons[ICON_DOWNLOAD_ICON].data.indirected_sprite.id = (osspriteop_id) dw->sprite_name; /* Get a suitable path- and leafname for the download. */ temp_name = download_context_get_filename(dw->ctx); if (temp_name == NULL) temp_name = messages_get("SaveObject"); if (temp_name != NULL) filename = strdup(temp_name); if (filename == NULL) { LOG("Failed to establish download filename."); ro_warn_user("SaveError", error->errmess); free(dw); return 0; } for (i = 0, last_dot = (size_t) -1; filename[i] != '\0'; i++) { const char c = filename[i]; if (c == '.') { last_dot = i; filename[i] = '/'; } else if (c <= ' ' || strchr(":*#$&@^%\\", c) != NULL) filename[i] = '_'; } if (nsoption_bool(strip_extensions) && last_dot != (size_t) -1) filename[last_dot] = '\0'; if (download_dir != NULL && strlen(download_dir) > 0) snprintf(dw->path, RO_DOWNLOAD_MAX_PATH_LEN, "%s.%s", download_dir, filename); else snprintf(dw->path, RO_DOWNLOAD_MAX_PATH_LEN, "%s", filename); free(filename); err = utf8_to_local_encoding(dw->path, 0, &local_path); if (err != NSERROR_OK) { /* badenc should never happen */ assert(err !=NSERROR_BAD_ENCODING); LOG("utf8_to_local_encoding failed"); ro_warn_user("NoMemory", 0); free(dw); return 0; } else { strncpy(dw->path, local_path, sizeof dw->path); free(local_path); } download_template->icons[ICON_DOWNLOAD_PATH].data.indirected_text.text = dw->path; download_template->icons[ICON_DOWNLOAD_PATH].data.indirected_text.size = sizeof dw->path; download_template->icons[ICON_DOWNLOAD_DESTINATION].data. indirected_text.text = dw->path; download_template->icons[ICON_DOWNLOAD_DESTINATION].data. indirected_text.size = sizeof dw->path; download_template->icons[ICON_DOWNLOAD_DESTINATION].flags |= wimp_ICON_DELETED; /* create and open the download window */ error = xwimp_create_window(download_template, &dw->window); if (error) { LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess); ro_warn_user("WimpError", error->errmess); free(dw); return 0; } dw->prev = 0; dw->next = download_window_list; if (download_window_list) download_window_list->prev = dw; download_window_list = dw; ro_gui_download_update_status(dw); ro_gui_dialog_open(dw->window); ro_gui_wimp_event_set_user_data(dw->window, dw); ro_gui_wimp_event_register_mouse_click(dw->window, ro_gui_download_click); ro_gui_wimp_event_register_keypress(dw->window, ro_gui_download_keypress); ro_gui_wimp_event_register_close_window(dw->window, ro_gui_download_close); /* issue the warning now, so that it appears in front of the download * window! */ if (space_warning) ro_warn_user("DownloadWarn", messages_get("NoDiscSpace")); return dw; }