gchar *get_file_relative_path(const gchar *origin_dir, const gchar *dest_file) { gchar *dest_dir, *ret; dest_dir = g_path_get_dirname(dest_file); ret = relpath(origin_dir, dest_dir); if (ret) { gchar *dest_basename; dest_basename = g_path_get_basename(dest_file); if (g_strcmp0(ret, "./") != 0) { setptr(ret, g_build_filename(ret, dest_basename, NULL)); } else { setptr(ret, g_strdup(dest_basename)); } g_free(dest_basename); } g_free(dest_dir); return ret; }
//set the MOV void MOV::set(int type1, intptr_t val1, int type2, intptr_t val2) { //MOV-exclusive specials if (val1 == EAX && isreg(type1) && type2 == ptrfromreg(type1)) { MEMPTR* memptr = (MEMPTR*)(val2); if (memptr->reg1 == -1) { if (type1 == TREG32) bytes.assign("\xA1").append(to4bytes(memptr->constant)); else if (type1 == TREG16) bytes.assign("\x66\xA1").append(to4bytes(memptr->constant)); else if (type1 == TREG8) bytes.assign("\xA0").append(to4bytes(memptr->constant)); if (memptr->deletable) delete memptr; return; } } else if (val2 == EAX && isreg(type2) && type1 == ptrfromreg(type2)) { MEMPTR* memptr = (MEMPTR*)(val1); if (memptr->reg1 == -1) { if (type2 == TREG32) bytes.assign("\xA3").append(to4bytes(memptr->constant)); else if (type2 == TREG16) bytes.assign("\x66\xA3").append(to4bytes(memptr->constant)); else if (type2 == TREG8) bytes.assign("\xA2").append(to4bytes(memptr->constant)); if (memptr->deletable) delete memptr; return; } } //move data addresses if (type2 == TDATAADDRESS) { set(type1, val1, TCONSTANT, IMAGEBASE); tag = TAGOPXDATAADDRESS; tag2 = val2; tag3 = type1; tag4 = val1; //move code addresses } else if (type2 == TCODEADDRESS) { set(type1, val1, TCONSTANT, IMAGEBASE); tag = TAGOPXCODEADDRESS; tagp = val2; tag3 = type1; tag4 = val1; //regular setting } else if (type1 == TREG32) setreg(type1, val1, type2, val2, "", "", 0xB8, "", "\x8B"); else if (type1 == TREG16) setreg(type1, val1, type2, val2, "", "\x66", 0xB8, "", "\x66\x8B"); else if (type1 == TREG8) setreg(type1, val1, type2, val2, "", "", 0xB0, "", "\x8A"); else if (type1 == TDWORDPTR) setptr(type1, val1, type2, val2, "\x89", "", "\xC7", 0); else if (type1 == TWORDPTR) setptr(type1, val1, type2, val2, "\x66\x89", "", "\x66\xC7", 0); else if (type1 == TBYTEPTR) setptr(type1, val1, type2, val2, "\x88", "\xC6", "", 0); else if (isdataptr(type1)) setdataptr(type1, val1, type2, val2); }
static gboolean goto_compiler_file_line(const gchar *filename, gint line, gboolean focus_editor) { if (!filename || line <= -1) return FALSE; /* If the path doesn't exist, try the current document. * This happens when we receive build messages in the wrong order - after the * 'Leaving directory' messages */ if (!g_file_test(filename, G_FILE_TEST_EXISTS)) { gchar *cur_dir = utils_get_current_file_dir_utf8(); gchar *name; if (cur_dir) { /* we let the user know we couldn't find the parsed filename from the message window */ setptr(cur_dir, utils_get_locale_from_utf8(cur_dir)); name = g_path_get_basename(filename); setptr(name, g_build_path(G_DIR_SEPARATOR_S, cur_dir, name, NULL)); g_free(cur_dir); if (g_file_test(name, G_FILE_TEST_EXISTS)) { ui_set_statusbar(FALSE, _("Could not find file '%s' - trying the current document path."), filename); filename = name; } else g_free(name); } } { gchar *utf8_filename = utils_get_utf8_from_locale(filename); GeanyDocument *doc = document_find_by_filename(utf8_filename); GeanyDocument *old_doc = document_get_current(); g_free(utf8_filename); if (doc == NULL) /* file not already open */ doc = document_open_file(filename, FALSE, NULL, NULL); if (doc != NULL) { gboolean ret; if (! doc->changed && editor_prefs.use_indicators) /* if modified, line may be wrong */ editor_indicator_set_on_line(doc->editor, GEANY_INDICATOR_ERROR, line - 1); ret = navqueue_goto_line(old_doc, doc, line); if (ret && focus_editor) gtk_widget_grab_focus(GTK_WIDGET(doc->editor->sci)); return ret; } } return FALSE; }
static gchar * get_base_dir(const gchar * path) { gchar *test_dir; gchar *base; gchar *base_prev = NULL; if (g_file_test(path, G_FILE_TEST_IS_DIR)) base = g_strdup(path); else base = g_path_get_dirname(path); do { test_dir = g_build_filename(base, ".svn", NULL); if (!g_file_test(test_dir, G_FILE_TEST_IS_DIR)) { g_free(test_dir); break; } g_free(test_dir); g_free(base_prev); base_prev = base; base = g_path_get_dirname(base); /* check for svn layout */ test_dir = g_build_filename(base, "trunk", NULL); if (!g_file_test(test_dir, G_FILE_TEST_IS_DIR)) { g_free(test_dir); continue; } setptr(test_dir, g_build_filename(base, "branches", NULL)); if (!g_file_test(test_dir, G_FILE_TEST_IS_DIR)) { g_free(test_dir); continue; } setptr(test_dir, g_build_filename(base, "tags", NULL)); if (!g_file_test(test_dir, G_FILE_TEST_IS_DIR)) { g_free(test_dir); continue; } g_free(test_dir); break; } while (strcmp(base, base_prev) != 0); if (base_prev == NULL) { /* fallback for Subversion 1.7: try to climb up the tree until we * find a .svn subdirectory */ base_prev = find_subdir_path(path, ".svn"); } g_free(base); return base_prev; }
gchar * get_full_path(const gchar * location, const gchar * path) { gchar *dir; dir = g_path_get_dirname(location); setptr(dir, g_build_filename(dir, path, NULL)); setptr(dir, normpath(dir)); return dir; }
static void remove_foreach_project_filetype(gpointer data, gpointer user_data) { GeanyFiletype *ft = data; if (ft != NULL) { setptr(ft->projfilecmds, NULL); setptr(ft->projexeccmds, NULL); setptr(ft->projerror_regex_string, NULL); ft->project_list_entry = -1; } }
/* Returns: the full filename in locale encoding. */ static gchar *get_tree_path_filename(GtkTreePath *treepath) { GtkTreeModel *model = GTK_TREE_MODEL(file_store); GtkTreeIter iter; gchar *name; gtk_tree_model_get_iter(model, &iter, treepath); gtk_tree_model_get(model, &iter, FILEVIEW_COLUMN_NAME, &name, -1); setptr(name, utils_get_locale_from_utf8(name)); setptr(name, get_full_path(g_current_project->path, name)); return name; }
//set the ADD void ADD::set(int type1, intptr_t val1, int type2, intptr_t val2) { if (type1 == TREG32) setreg(type1, val1, type2, val2, "\x83", "\x81", 0xC0, "\x05", "\x03"); else if (type1 == TREG16) setreg(type1, val1, type2, val2, "\x66\x83", "\x66\x81", 0xC0, "\x66\x05", "\x66\x03"); else if (type1 == TREG8) setreg(type1, val1, type2, val2, "\x80", "", 0xC0, "\x04", "\x02"); else if (type1 == TDWORDPTR) setptr(type1, val1, type2, val2, "\x01", "\x83", "\x81", 0); else if (type1 == TWORDPTR) setptr(type1, val1, type2, val2, "\x66\x01", "\x66\x83", "\x66\x81", 0); else if (type1 == TBYTEPTR) setptr(type1, val1, type2, val2, string("\0", 1), "\x80", "", 0); else if (isdataptr(type1)) setdataptr(type1, val1, type2, val2); }
/* * Incorporate any new mail that has arrived since we first * started reading mail. */ int incfile(void) { off_t newsize; int omsgCount = msgCount; FILE *ibuf; ibuf = Fopen(mailname, "r"); if (ibuf == NULL) return (-1); holdsigs(); newsize = fsize(ibuf); if (newsize == 0) return (-1); /* mail box is now empty??? */ if (newsize < mailsize) return (-1); /* mail box has shrunk??? */ if (newsize == mailsize) return (0); /* no new mail */ setptr(ibuf, mailsize); setmsize(msgCount); mailsize = ftello(ibuf); (void)Fclose(ibuf); relsesigs(); return (msgCount - omsgCount); }
static void instantsave_document_new_cb(GObject *obj, GeanyDocument *doc, gpointer user_data) { if (enable_instantsave && doc->file_name == NULL) { gchar *new_filename; gint fd; GeanyFiletype *ft = doc->file_type; fd = g_file_open_tmp("gis_XXXXXX", &new_filename, NULL); if (fd != -1) close(fd); /* close the returned file descriptor as we only need the filename */ if (ft == NULL || ft->id == GEANY_FILETYPES_NONE) /* ft is NULL when a new file without template was opened, so use the * configured default file type */ ft = filetypes_lookup_by_name(instantsave_default_ft); if (ft != NULL) /* add the filetype's default extension to the new filename */ setptr(new_filename, g_strconcat(new_filename, ".", ft->extension, NULL)); doc->file_name = new_filename; if (doc->file_type->id == GEANY_FILETYPES_NONE) document_set_filetype(doc, filetypes_lookup_by_name(instantsave_default_ft)); /* force saving the file to enable all the related actions(tab name, filetype, etc.) */ document_save_file(doc, TRUE); } }
//set the SUB void SUB::set(int type1, intptr_t val1, int type2, intptr_t val2) { if (type1 == TREG32) setreg(type1, val1, type2, val2, "\x83", "\x81", 0xE8, "\x2D", "\x2B"); else if (type1 == TREG16) setreg(type1, val1, type2, val2, "\x66\x83", "\x66\x81", 0xE8, "\x66\x2D", "\x66\x2B"); else if (type1 == TREG8) setreg(type1, val1, type2, val2, "\x80", "", 0xE8, "\x2C", "\x2A"); else if (type1 == TDWORDPTR) setptr(type1, val1, type2, val2, "\x29", "\x83", "\x81", 0x28); else if (type1 == TWORDPTR) setptr(type1, val1, type2, val2, "\x66\x29", "\x66\x83", "\x66\x81", 0x28); else if (type1 == TBYTEPTR) setptr(type1, val1, type2, val2, "\x28", "\x80", "", 0x28); else if (isdataptr(type1)) setdataptr(type1, val1, type2, val2); }
//set the OR void OR::set(int type1, intptr_t val1, int type2, intptr_t val2) { if (type1 == TREG32) setreg(type1, val1, type2, val2, "\x83", "\x81", 0xC8, "\x0D", "\x0B"); else if (type1 == TREG16) setreg(type1, val1, type2, val2, "\x66\x83", "\x66\x81", 0xC8, "\x66\x0D", "\x66\x0B"); else if (type1 == TREG8) setreg(type1, val1, type2, val2, "\x80", "", 0xC8, "\x0C", "\x0A"); else if (type1 == TDWORDPTR) setptr(type1, val1, type2, val2, "\x09", "\x83", "\x81", 8); else if (type1 == TWORDPTR) setptr(type1, val1, type2, val2, "\x66\x09", "\x66\x83", "\x66\x81", 8); else if (type1 == TBYTEPTR) setptr(type1, val1, type2, val2, "\x08", "\x80", "", 8); else if (isdataptr(type1)) setdataptr(type1, val1, type2, val2); }
/* convert data with the specified encoding */ static gboolean handle_forced_encoding(BufferData *buffer, const gchar *forced_enc) { GeanyEncodingIndex enc_idx; if (utils_str_equal(forced_enc, "UTF-8")) { if (! g_utf8_validate(buffer->data, buffer->len, NULL)) { return FALSE; } } else { gchar *converted_text = encodings_convert_to_utf8_from_charset( buffer->data, buffer->size, forced_enc, FALSE); if (converted_text == NULL) { return FALSE; } else { setptr(buffer->data, converted_text); buffer->len = strlen(converted_text); } } enc_idx = encodings_scan_unicode_bom(buffer->data, buffer->size, NULL); buffer->bom = (enc_idx == GEANY_ENCODING_UTF_8); buffer->enc = g_strdup(forced_enc); return TRUE; }
const GAParameterList& GAGeneticAlgorithm::parameters(const char* filename, GABoolean flag){ params.read(filename, flag); for(int i=0; i<params.size(); i++) setptr(params[i].fullname(), params[i].value()); return params; }
static void menu_item_toggled_cb(GtkCheckMenuItem *menuitem, gpointer gdata) { GeanyDocument *doc; if (sc_ignore_callback) return; if (menuitem != NULL && GTK_IS_CHECK_MENU_ITEM(menuitem) && ! gtk_check_menu_item_get_active(menuitem)) { return; } doc = document_get_current(); /* Another language was chosen from the menu item, so make it default for this session. */ if (gdata != NULL) { setptr(sc_info->default_language, g_strdup(gdata)); sc_speller_reinit_enchant_dict(); sc_gui_update_menu(); update_labels(); } perform_check(doc); }
//set the CMP void CMP::set(int type1, intptr_t val1, int type2, intptr_t val2) { if (type1 == TREG32) setreg(type1, val1, type2, val2, "\x83", "\x81", 0xF8, "\x3D", "\x3B"); else if (type1 == TREG16) setreg(type1, val1, type2, val2, "\x66\x83", "\x66\x81", 0xF8, "\x66\x3D", "\x66\x3B"); else if (type1 == TREG8) setreg(type1, val1, type2, val2, "\x80", "", 0xF8, "\x3C", "\x3A"); else if (type1 == TDWORDPTR) setptr(type1, val1, type2, val2, "\x39", "\x83", "\x81", 0x38); else if (type1 == TWORDPTR) setptr(type1, val1, type2, val2, "\x66\x39", "\x66\x83", "\x66\x81", 0x38); else if (type1 == TBYTEPTR) setptr(type1, val1, type2, val2, "\x38", "\x80", "", 0x38); else if (isdataptr(type1)) setdataptr(type1, val1, type2, val2); }
//set the AND void AND::set(int type1, intptr_t val1, int type2, intptr_t val2) { if (type1 == TREG32) setreg(type1, val1, type2, val2, "\x83", "\x81", 0xE0, "\x25", "\x23"); else if (type1 == TREG16) setreg(type1, val1, type2, val2, "\x66\x83", "\x66\x81", 0xE0, "\x66\x25", "\x66\x23"); else if (type1 == TREG8) setreg(type1, val1, type2, val2, "\x80", "", 0xE0, "\x24", "\x22"); else if (type1 == TDWORDPTR) setptr(type1, val1, type2, val2, "\x21", "\x83", "\x81", 0x20); else if (type1 == TWORDPTR) setptr(type1, val1, type2, val2, "\x66\x21", "\x66\x83", "\x66\x81", 0x20); else if (type1 == TBYTEPTR) setptr(type1, val1, type2, val2, "\x20", "\x80", "", 0x20); else if (isdataptr(type1)) setdataptr(type1, val1, type2, val2); }
const GAParameterList& GAGeneticAlgorithm::parameters(STD_ISTREAM& is, GABoolean flag){ params.read(is, flag); for(int i=0; i<params.size(); i++) setptr(params[i].fullname(), params[i].value()); return params; }
//set the XOR void XOR::set(int type1, intptr_t val1, int type2, intptr_t val2) { if (type1 == TREG32) setreg(type1, val1, type2, val2, "\x83", "\x81", 0xF0, "\x35", "\x33"); else if (type1 == TREG16) setreg(type1, val1, type2, val2, "\x66\x83", "\x66\x81", 0xF0, "\x66\x35", "\x66\x33"); else if (type1 == TREG8) setreg(type1, val1, type2, val2, "\x80", "", 0xF0, "\x34", "\x32"); else if (type1 == TDWORDPTR) setptr(type1, val1, type2, val2, "\x31", "\x83", "\x81", 0x30); else if (type1 == TWORDPTR) setptr(type1, val1, type2, val2, "\x66\x31", "\x66\x83", "\x66\x81", 0x30); else if (type1 == TBYTEPTR) setptr(type1, val1, type2, val2, "\x30", "\x80", "", 0x30); else if (isdataptr(type1)) setdataptr(type1, val1, type2, val2); }
// This is a pretty ugly little hack to make doubles/floats work transparently. int GAGeneticAlgorithm::set(const char* name, double v) { int status=1; for(int i=0; i<params.size(); i++){ if(strcmp(name, params[i].fullname()) == 0 || strcmp(name, params[i].shrtname()) == 0){ if(params[i].type() == GAParameter::FLOAT){ float fval = (float)v; status = setptr(name, (void*)&fval); } else status = setptr(name, (void*)&v); } } return status; }
const GAParameterList& GAGeneticAlgorithm::parameters(int& argc, char **argv, GABoolean flag){ params.parse(argc, argv, flag); // get the args we understand for(int i=0; i<params.size(); i++) setptr(params[i].fullname(), params[i].value()); return params; }
/* Update project-related preferences after using the Preferences dialog. */ void project_apply_prefs(void) { GtkWidget *path_entry = ui_lookup_widget(ui_widgets.prefs_dialog, "project_file_path_entry"); const gchar *str; str = gtk_entry_get_text(GTK_ENTRY(path_entry)); setptr(local_prefs.project_file_path, g_strdup(str)); }
APR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, apr_seek_where_t where, apr_off_t *offset) { apr_off_t rv; thefile->eof_hit = 0; if (thefile->buffered) { int rc = EINVAL; apr_finfo_t finfo; file_lock(thefile); switch (where) { case APR_SET: rc = setptr(thefile, *offset); break; case APR_CUR: rc = setptr(thefile, thefile->filePtr - thefile->dataRead + thefile->bufpos + *offset); break; case APR_END: rc = apr_file_info_get_locked(&finfo, APR_FINFO_SIZE, thefile); if (rc == APR_SUCCESS) rc = setptr(thefile, finfo.size + *offset); break; } *offset = thefile->filePtr - thefile->dataRead + thefile->bufpos; file_unlock(thefile); return rc; } else { rv = lseek(thefile->filedes, *offset, where); if (rv == -1) { *offset = -1; return errno; } else { *offset = rv; return APR_SUCCESS; } } }
void dfread(long num, scrbuf5 *s) { long savpos = ptrpos; /* Workfile pos'n req'd on exit */ long l; /* Scratch */ scrbuf5 s5; /* For when a2 is NULL */ /* */ setptr(lintot + 1); /* Move to eof */ lngwrn = true; /* Not memrec */ fileio = false; /* File already mmap'd */ count = dcount; /* Lines read in from file */ state = 0; /* Normal state initially */ xxmode = dfmode; /* Set mode at map time */ if (s) xxprev = s; /* Use a2 */ else xxprev = &s5; xxprev->bcurs = 0; /* Cursor at column 1 on exit */ bytes = defend - defpos; /* Size remaining */ bufend = defend; /* End address of file */ prvpos = bufpos = defpos; /* Data starts here */ if (num == 1) { if (prclin()) deferd = false; else endLin(); } /* if(num==1) */ else for (l = 0; l < num; l++) /* Loop on lines */ { if (prclin()) /* Eof */ { deferd = false; break; } /* if()cntrlc&&ctlcak())||prclin()) */ endLin(); } /* for(l=0;l<num;l++) */ /* Finished with deferred file & want total lines */ if (!deferd && num == LONG_MAX) printf("%ld lines read.\r\n", count); dcount = count; /* Lines read in from file */ defpos = bufpos; /* Start of still-deferred data */ setptr(savpos); /* Restore old file pos'n */ } /* void dfread(long num,scrbuf5*s) */
static gchar *relpath(const gchar *origin_dir, const gchar *dest_dir) { gchar *origin, *dest; gchar **originv, **destv; gchar *ret = NULL; guint i, j; origin = tm_get_real_path(origin_dir); dest = tm_get_real_path(dest_dir); if (EMPTY(origin) || EMPTY(dest) || origin[0] != dest[0]) { g_free(origin); g_free(dest); return NULL; } originv = g_strsplit_set(g_path_skip_root(origin), "/\\", -1); destv = g_strsplit_set(g_path_skip_root(dest), "/\\", -1); for (i = 0; originv[i] != NULL && destv[i] != NULL; i++) if (g_strcmp0(originv[i], destv[i]) != 0) break; ret = g_strdup(""); for (j = i; originv[j] != NULL; j++) setptr(ret, g_build_filename(ret, "..", NULL)); for (j = i; destv[j] != NULL; j++) setptr(ret, g_build_filename(ret, destv[j], NULL)); if (strlen(ret) == 0) setptr(ret, g_strdup("./")); g_free(origin); g_free(dest); g_strfreev(originv); g_strfreev(destv); return ret; }
int main (int argc, char **argv) { const gchar *srcdir; gchar *env_str; gchar *path = NULL; GError *err = NULL; /* for autotools integration */ if (! (srcdir = g_getenv ("srcdir"))) { srcdir = "."; } /* possible arg to override */ if (argc == 2) { srcdir = argv[1]; } else if (argc > 2) { fprintf (stderr, "USAGE: %s SRCDIR", argv[0]); return 1; } g_type_init (); #define setptr(ptr, val) (ptr = (g_free (ptr), val)) setptr (path, g_build_filename (srcdir, "environ", NULL)); get_file_content (path, &env_str, FALSE); setptr (path, g_build_filename (srcdir, "success", NULL)); traverse_dir (path, success_tests_item, env_str); setptr (path, g_build_filename (srcdir, "fail", NULL)); traverse_dir (path, fail_tests_item, env_str); setptr (path, NULL); #undef setptr g_free (env_str); return 0; }
static void setup_config_file_menus(void) { gchar *f; f = utils_build_path(app->configdir, "filetype_extensions.conf", NULL); ui_add_config_file_menu_item(f, NULL, NULL); setptr(f, utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, "filetypes.common", NULL)); ui_add_config_file_menu_item(f, NULL, NULL); g_free(f); g_signal_connect(geany_object, "document-save", G_CALLBACK(on_document_save), NULL); }
static void read_template(const gchar *name, gint id) { gchar *fname = g_build_path(G_DIR_SEPARATOR_S, app->configdir, GEANY_TEMPLATES_SUBDIR, name, NULL); /* try system if user template doesn't exist */ if (!g_file_test(fname, G_FILE_TEST_EXISTS)) setptr(fname, g_build_path(G_DIR_SEPARATOR_S, app->datadir, GEANY_TEMPLATES_SUBDIR, name, NULL)); templates[id] = read_file(fname); g_free(fname); }
void gprj_project_rescan(void) { GSList *pattern_list = NULL; GSList *ignored_dirs_list = NULL; GSList *lst; GSList *elem; if (!g_prj) return; if (g_prj->generate_tags) g_hash_table_foreach(g_prj->file_tag_table, (GHFunc)workspace_remove_tag, NULL); g_hash_table_destroy(g_prj->file_tag_table); g_prj->file_tag_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); deferred_op_queue_clean(); pattern_list = get_precompiled_patterns(geany_data->app->project->file_patterns); ignored_dirs_list = get_precompiled_patterns(g_prj->ignored_dirs_patterns); lst = get_file_list(geany_data->app->project->base_path, pattern_list, ignored_dirs_list); for (elem = lst; elem != NULL; elem = g_slist_next(elem)) { char *path; TagObject *obj; obj = g_new0(TagObject, 1); obj->tag = NULL; path = tm_get_real_path(elem->data); if (path) { setptr(path, utils_get_utf8_from_locale(path)); g_hash_table_insert(g_prj->file_tag_table, path, obj); } } if (g_prj->generate_tags) g_hash_table_foreach(g_prj->file_tag_table, (GHFunc)workspace_add_tag, NULL); g_slist_foreach(lst, (GFunc) g_free, NULL); g_slist_free(lst); g_slist_foreach(pattern_list, (GFunc) g_pattern_spec_free, NULL); g_slist_free(pattern_list); g_slist_foreach(ignored_dirs_list, (GFunc) g_pattern_spec_free, NULL); g_slist_free(ignored_dirs_list); }
/* Compare two strings, ignoring case differences */ gint utils_str_casecmp (const gchar *s1, const gchar *s2) { gchar *tmp1, *tmp2; gint result; g_return_val_if_fail (s1 != NULL, 1); g_return_val_if_fail (s2 != NULL, -1); tmp1 = g_strdup (s1); tmp2 = g_strdup (s2); /* first ensure strings are UTF-8 */ if (! g_utf8_validate (s1, -1, NULL)) setptr (tmp1, g_locale_to_utf8 (s1, -1, NULL, NULL, NULL)); if (! g_utf8_validate (s2, -1, NULL)) setptr (tmp2, g_locale_to_utf8 (s2, -1, NULL, NULL, NULL)); if (tmp1 == NULL) { g_free (tmp2); return 1; } if (tmp2 == NULL) { g_free (tmp1); return -1; } /* then convert the strings into a case-insensitive form */ setptr (tmp1, g_utf8_strdown (tmp1, -1)); setptr (tmp2, g_utf8_strdown (tmp2, -1)); /* compare */ result = strcmp (tmp1, tmp2); g_free (tmp1); g_free (tmp2); return result; }