aboutsummaryrefslogtreecommitdiffstats
path: root/desktop.c
diff options
context:
space:
mode:
Diffstat (limited to 'desktop.c')
-rw-r--r--desktop.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/desktop.c b/desktop.c
new file mode 100644
index 0000000..d30d3c7
--- /dev/null
+++ b/desktop.c
@@ -0,0 +1,276 @@
+/*
+ * some code to handle desktop files
+ * http://www.freedesktop.org/Standards/desktop-entry-spec
+ *
+ * This is really very simple and basic: next to no locale handling,
+ * no caching, no other clever tricks ...
+ * ida + fbi only use the Comment= entry of .directory files.
+ *
+ * (c) 2004 Gerd Knorr <kraxel@bytesex.org>
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <iconv.h>
+#include <langinfo.h>
+
+#include "list.h"
+#include "desktop.h"
+
+extern int debug;
+
+/* ------------------------------------------------------------------------- */
+/* desktop files are in utf-8 */
+
+static int iconv_string(char *to, char *from,
+ char *src, char *dst, size_t max)
+{
+ size_t ilen = strlen(src);
+ size_t olen = max-1;
+ iconv_t ic;
+
+ ic = iconv_open(to,from);
+ if (NULL == ic)
+ return 0;
+
+ while (ilen > 0) {
+ if (-1 == iconv(ic,&src,&ilen,&dst,&olen)) {
+ /* skip + quote broken byte unless we are out of space */
+ if (E2BIG == errno)
+ break;
+ if (olen < 4)
+ break;
+ sprintf(dst,"\\x%02x",(int)(unsigned char)src[0]);
+ src += 1;
+ dst += 4;
+ ilen -= 1;
+ olen -= 4;
+ }
+ }
+ dst[0] = 0;
+ iconv_close(ic);
+ return max-1 - olen;
+}
+
+int utf8_to_locale(char *src, char *dst, size_t max)
+{
+ char *codeset = nl_langinfo(CODESET);
+ return iconv_string(codeset, "UTF-8", src, dst, max);
+}
+
+int locale_to_utf8(char *src, char *dst, size_t max)
+{
+ char *codeset = nl_langinfo(CODESET);
+ return iconv_string("UTF-8", codeset, src, dst, max);
+}
+
+/* ------------------------------------------------------------------------- */
+/* read/write desktop files */
+
+struct desktop_line {
+ struct list_head next;
+ char line[1024];
+};
+
+static int read_file(char *filename, struct list_head *file)
+{
+ struct desktop_line *l;
+ int len,count = 0;
+ FILE *fp;
+
+ INIT_LIST_HEAD(file);
+ fp = fopen(filename,"r");
+ if (NULL == fp) {
+ if (debug)
+ fprintf(stderr,"open %s: %s\n",filename,strerror(errno));
+ return 0;
+ }
+ for (;;) {
+ l = malloc(sizeof(*l));
+ memset(l,0,sizeof(*l));
+ if (NULL == fgets(l->line,sizeof(l->line),fp)) {
+ free(l);
+ break;
+ }
+ len = strlen(l->line);
+ if (l->line[len-1] == '\n')
+ l->line[len-1] = 0;
+ list_add_tail(&l->next,file);
+ count++;
+ }
+ fclose(fp);
+ return count;
+}
+
+static int write_file(char *filename, struct list_head *file)
+{
+ struct desktop_line *l;
+ struct list_head *item;
+ FILE *fp;
+
+ fp = fopen(filename,"w");
+ if (NULL == fp) {
+ fprintf(stderr,"open %s: %s\n",filename,strerror(errno));
+ return 0;
+ }
+ list_for_each(item,file) {
+ l = list_entry(item, struct desktop_line, next);
+ fprintf(fp,"%s\n",l->line);
+ }
+ fclose(fp);
+ return 0;
+}
+
+static int dump_file(struct list_head *file)
+{
+ struct desktop_line *l;
+ struct list_head *item;
+
+ fprintf(stderr,"\n");
+ fprintf(stderr,"+--------------------\n");
+ list_for_each(item,file) {
+ l = list_entry(item, struct desktop_line, next);
+ fprintf(stderr,"| %s\n",l->line);
+ }
+ return 0;
+}
+
+static int free_file(struct list_head *file)
+{
+ struct desktop_line *l;
+
+ while (!list_empty(file)) {
+ l = list_entry(file->next, struct desktop_line, next);
+ list_del(&l->next);
+ free(l);
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static char* get_entry(struct list_head *file, char *entry)
+{
+ struct desktop_line *l;
+ struct list_head *item;
+ int in_desktop_entry = 0;
+ int len = strlen(entry);
+
+ list_for_each(item,file) {
+ l = list_entry(item, struct desktop_line, next);
+ if (0 == strcmp(l->line,"[Desktop Entry]")) {
+ in_desktop_entry = 1;
+ continue;
+ }
+ if (0 == strncmp(l->line,"[",1)) {
+ in_desktop_entry = 0;
+ continue;
+ }
+ if (!in_desktop_entry)
+ continue;
+ if (0 == strncmp(l->line,entry,len))
+ return l->line+len;
+ }
+ return NULL;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int add_line(struct list_head *file, char *line)
+{
+ struct desktop_line *add;
+
+ add = malloc(sizeof(*add));
+ memset(add,0,sizeof(*add));
+ snprintf(add->line,sizeof(add->line),"%s",line);
+ list_add_tail(&add->next,file);
+ return 0;
+}
+
+static int add_entry(struct list_head *file, char *entry, char *value)
+{
+ struct desktop_line *l,*add;
+ struct list_head *item;
+
+ list_for_each(item,file) {
+ l = list_entry(item, struct desktop_line, next);
+ if (0 != strcmp(l->line,"[Desktop Entry]"))
+ continue;
+ add = malloc(sizeof(*add));
+ memset(add,0,sizeof(*add));
+ snprintf(add->line,sizeof(add->line),"%s%s",entry,value);
+ list_add(&add->next,item);
+ return 0;
+ }
+ return -1;
+}
+
+static int set_entry(struct list_head *file, char *type, char *entry, char *value)
+{
+ struct desktop_line *l;
+ struct list_head *item;
+ int in_desktop_entry = 0;
+ int len = strlen(entry);
+
+ list_for_each(item,file) {
+ l = list_entry(item, struct desktop_line, next);
+ if (0 == strcmp(l->line,"[Desktop Entry]")) {
+ in_desktop_entry = 1;
+ continue;
+ }
+ if (0 == strncmp(l->line,"[",1)) {
+ in_desktop_entry = 0;
+ continue;
+ }
+ if (!in_desktop_entry)
+ continue;
+ if (0 == strncmp(l->line,entry,len)) {
+ snprintf(l->line,sizeof(l->line),"%s%s",entry,value);
+ return 0;
+ }
+ }
+ if (0 != add_entry(file,entry,value)) {
+ add_line(file,"[Desktop Entry]");
+ add_entry(file,"Type=",type);
+ add_entry(file,entry,value);
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+/* public interface */
+
+int desktop_read_entry(char *filename, char *entry, char *dest, size_t max)
+{
+ struct list_head file;
+ char *value;
+ int rc = 0;
+
+ read_file(filename,&file);
+ if (debug)
+ dump_file(&file);
+ value = get_entry(&file,entry);
+ if (NULL != value) {
+ rc = utf8_to_locale(value,dest,max);
+ if (rc && debug)
+ fprintf(stderr,"# %s\n",dest);
+ };
+ free_file(&file);
+ return rc;
+}
+
+int desktop_write_entry(char *filename, char *type, char *entry, char *value)
+{
+ struct list_head file;
+ char utf8[1024];
+
+ read_file(filename,&file);
+ locale_to_utf8(value,utf8,sizeof(utf8));
+ set_entry(&file,"Directory",entry,utf8);
+ write_file(filename,&file);
+ free_file(&file);
+ return 0;
+}