static GlpkFileVersion gnm_glpk_detect_version (GnmGlpk *lp, GsfInputTextline *tl) { GnmSubSolver *subsol = lp->parent; gsf_off_t cur = gsf_input_tell (GSF_INPUT (tl)); GlpkFileVersion ver = GLPK_UNKNOWN; const char *line; unsigned cols, rows; if ((line = gsf_input_textline_utf8_gets (tl)) == NULL) goto out; if (sscanf (line, "%u %u", &rows, &cols) == 2 && cols == g_hash_table_size (subsol->cell_from_name)) { ver = GLPK_457; if (gnm_solver_debug ()) g_printerr ("Detected version 4.57 file format\n"); goto out; } if ((line[0] == 'c' || line[0] == 's') && line[1] == ' ') { ver = GLPK_458; if (gnm_solver_debug ()) g_printerr ("Detected version 4.58 file format\n"); goto out; } out: // Extra seek due to gsf bug gsf_input_seek (GSF_INPUT (tl), cur + 1, G_SEEK_SET); gsf_input_seek (GSF_INPUT (tl), cur, G_SEEK_SET); return ver; }
static void go_help_display (CBHelpPaths const *paths) { #ifdef GOFFICE_WITH_GNOME gnome_help_display (paths->app, paths->link, NULL); #elif defined(G_OS_WIN32) static GHashTable* context_help_map = NULL; guint id; if (!context_help_map) { GsfInput *input; GsfInputTextline *textline; GError *err = NULL; gchar *mapfile = g_strconcat (paths->app, ".hhmap", NULL); gchar *path = g_build_filename (paths->data_dir, "doc", "C", mapfile, NULL); g_free (mapfile); if (!(input = gsf_input_stdio_new (path, &err)) || !(textline = (GsfInputTextline *) gsf_input_textline_new (input))) go_gtk_notice_dialog (NULL, GTK_MESSAGE_ERROR, "Cannot open '%s': %s", path, err ? err->message : "failed to create gsf-input-textline"); else { gchar *line, *topic; gulong id, i = 1; context_help_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); while ((line = gsf_input_textline_utf8_gets (textline)) != NULL) { if (!(id = strtoul (line, &topic, 10))) { go_gtk_notice_dialog (NULL, GTK_MESSAGE_ERROR, "Invalid topic id at line %lu in %s: '%s'", i, path, line); continue; } for (; *topic == ' '; ++topic); g_hash_table_insert (context_help_map, g_strdup (topic), (gpointer)id); } g_object_unref (G_OBJECT (textline)); } if (input) g_object_unref (G_OBJECT (input)); g_free (path); } if (!(id = (guint) g_hash_table_lookup (context_help_map, paths->link))) go_gtk_notice_dialog (NULL, GTK_MESSAGE_ERROR, "Topic '%s' not found.", paths->link); else { gchar *chmfile = g_strconcat (paths->app, ".chm", NULL); gchar *path = g_build_filename (paths->data_dir, "doc", "C", chmfile, NULL); g_free (chmfile); if (!HtmlHelp (GetDesktopWindow (), path, HH_HELP_CONTEXT, id)) go_gtk_notice_dialog (NULL, GTK_MESSAGE_ERROR, "Failed to spawn HtmlHelp"); g_free (path); } #else go_gtk_notice_dialog (NULL, GTK_MESSAGE_ERROR, "TODO : launch help browser for %s", paths->link); #endif }
/** * gsf_input_textline_ascii_gets: * @textline: #GsfInputTextline * * A utility routine to read things line by line from the underlying source. * Trailing newlines and carriage returns are stripped, and the resultant buffer * can be edited. * * Returns: (transfer none): the string read, or %NULL on eof. **/ unsigned char * gsf_input_textline_ascii_gets (GsfInputTextline *textline) { return gsf_input_textline_utf8_gets (textline); }
static void gnm_glpk_read_solution (GnmGlpk *lp) { GnmSubSolver *subsol = lp->parent; GnmSolver *sol = GNM_SOLVER (subsol); GsfInput *input; GsfInputTextline *tl = NULL; const char *line; GnmSolverResult *result = NULL; GnmSolverSensitivity *sensitivity = NULL; enum { SEC_UNKNOWN, SEC_ROWS, SEC_COLUMNS } state; gboolean has_integer; GSList *l; input = gsf_input_stdio_new (lp->result_filename, NULL); if (!input) goto fail; tl = GSF_INPUT_TEXTLINE (gsf_input_textline_new (input)); g_object_unref (input); result = g_object_new (GNM_SOLVER_RESULT_TYPE, NULL); result->solution = g_new0 (gnm_float, sol->input_cells->len); sensitivity = gnm_solver_sensitivity_new (sol); /* * glpsol's output format is different if there are any integer * constraint. Go figure. */ has_integer = sol->params->options.assume_discrete; for (l = sol->params->constraints; !has_integer && l; l = l->next) { GnmSolverConstraint *c = l->data; has_integer = (c->type == GNM_SOLVER_INTEGER || c->type == GNM_SOLVER_BOOLEAN); } switch (gnm_glpk_detect_version (lp, tl)) { case GLPK_457: if (gnm_glpk_read_solution_457 (lp, tl, result, sensitivity, has_integer)) goto fail; break; case GLPK_458: if (gnm_glpk_read_solution_458 (lp, tl, result, sensitivity, has_integer)) goto fail; break; default: goto fail; } g_object_unref (tl); tl = NULL; // ---------------------------------------- if (!lp->ranges_filename) goto done; input = gsf_input_stdio_new (lp->ranges_filename, NULL); if (!input) goto fail; tl = GSF_INPUT_TEXTLINE (gsf_input_textline_new (input)); g_object_unref (input); state = SEC_UNKNOWN; // We are reading a file intended for human consumption. // That is unfortunately because it implies rounding, for example. // The information does not appear to be available elsewhere. while ((line = gsf_input_textline_utf8_gets (tl)) != NULL) { gchar **items, **items2 = NULL; int len, len2 = 0; if (g_str_has_prefix (line, " No. Row name")) { state = SEC_ROWS; continue; } else if (g_str_has_prefix (line, " No. Column name")) { state = SEC_COLUMNS; continue; } else if (g_ascii_isalpha (line[0])) { state = SEC_UNKNOWN; continue; } if (state == SEC_UNKNOWN) continue; items = my_strsplit (line); len = g_strv_length (items); if (len == 10 && g_ascii_isdigit (items[0][0])) { line = gsf_input_textline_utf8_gets (tl); if (line) { items2 = my_strsplit (line); len2 = g_strv_length (items2); } } if (len == 10 && len2 == 6 && state == SEC_COLUMNS) { gnm_float low = parse_number (items[7]); gnm_float high = parse_number (items2[3]); GnmCell const *cell = gnm_sub_solver_find_cell (lp->parent, items[1]); int idx = gnm_solver_cell_index (sol, cell); if (idx >= 0) { sensitivity->vars[idx].low = low; sensitivity->vars[idx].high = high; } } if (len == 10 && len2 == 6 && state == SEC_ROWS) { gnm_float low = parse_number (items[6]); gnm_float high = parse_number (items2[2]); int cidx = gnm_sub_solver_find_constraint (lp->parent, items[1]); if (cidx >= 0) { sensitivity->constraints[cidx].low = low; sensitivity->constraints[cidx].high = high; } } g_strfreev (items); g_strfreev (items2); } g_object_unref (tl); // ---------------------------------------- done: gnm_solver_set_status (sol, GNM_SOLVER_STATUS_DONE); g_object_set (subsol, "result", result, NULL); g_object_unref (result); g_object_set (subsol, "sensitivity", sensitivity, NULL); g_object_unref (sensitivity); return; fail: if (tl) g_object_unref (tl); if (result) g_object_unref (result); if (sensitivity) g_object_unref (sensitivity); gnm_solver_set_status (sol, GNM_SOLVER_STATUS_ERROR); }
static gboolean gnm_glpk_read_solution_457 (GnmGlpk *lp, GsfInputTextline *tl, GnmSolverResult *result, GnmSolverSensitivity *sensitivity, gboolean has_integer) { GnmSubSolver *subsol = lp->parent; const char *line; unsigned cols, rows, c, r; int pstat, dstat; gnm_float val; if ((line = gsf_input_textline_utf8_gets (tl)) == NULL) goto fail; if (sscanf (line, "%u %u", &rows, &cols) != 2 || cols != g_hash_table_size (subsol->cell_from_name)) goto fail; if ((line = gsf_input_textline_utf8_gets (tl)) == NULL) goto fail; if (has_integer ? sscanf (line, "%d %" GNM_SCANF_g, &pstat, &val) != 2 : sscanf (line, "%d %d %" GNM_SCANF_g, &pstat, &dstat, &val) != 3) goto fail; result->value = val; switch (pstat) { case 2: case 5: result->quality = GNM_SOLVER_RESULT_OPTIMAL; break; case 1: /* "Undefined" -- see #611407 */ case 3: case 4: result->quality = GNM_SOLVER_RESULT_INFEASIBLE; break; case 6: result->quality = GNM_SOLVER_RESULT_UNBOUNDED; break; default: goto fail; } for (r = 0; r < rows; r++) { gnm_float pval, dval; unsigned rstat; unsigned cidx = r; if ((line = gsf_input_textline_utf8_gets (tl)) == NULL) goto fail; if (has_integer) continue; if (sscanf (line, "%u %" GNM_SCANF_g " %" GNM_SCANF_g, &rstat, &pval, &dval) != 3) goto fail; sensitivity->constraints[cidx].shadow_price = dval; } for (c = 0; c < cols; c++) { gnm_float pval, dval; unsigned cstat; unsigned idx = c; if ((line = gsf_input_textline_utf8_gets (tl)) == NULL) goto fail; if (has_integer ? sscanf (line, "%" GNM_SCANF_g, &pval) != 1 : sscanf (line, "%u %" GNM_SCANF_g " %" GNM_SCANF_g, &cstat, &pval, &dval) != 3) goto fail; result->solution[idx] = pval; if (!has_integer) sensitivity->vars[idx].reduced_cost = dval; } // Success return FALSE; fail: return TRUE; }