Elementary : use binary mode for fopen()
[framework/uifw/elementary.git] / src / bin / test_store.c
1 #include <Elementary.h>
2
3 #ifdef HAVE_CONFIG_H
4 # include "elementary_config.h"
5 #endif
6 #ifndef ELM_LIB_QUICKLAUNCH
7
8 typedef struct _My_Item My_Item;
9
10 struct _My_Item
11 {
12   char *from, *subject, *date, *head_content;
13 };
14
15 // callbacks just to see user interacting with genlist
16 static void
17 _st_selected(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
18 {
19    printf("selected: %p\n", event_info);
20 }
21
22 static void
23 _st_double_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
24 {
25    printf("double clicked: %p\n", event_info);
26 }
27
28 static void
29 _st_longpress(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
30 {
31    printf("longpress %p\n", event_info);
32 }
33
34 // store callbacks to handle loading/parsing/freeing of store items from src
35 static Elm_Genlist_Item_Class itc1 =
36 {
37   "message", { NULL, NULL, NULL, NULL, NULL }, NULL
38 };
39
40 static const Elm_Store_Item_Mapping it1_mapping[] =
41 {
42   {
43     ELM_STORE_ITEM_MAPPING_LABEL,
44       "elm.title.1", ELM_STORE_ITEM_MAPPING_OFFSET(My_Item, from),
45       { .empty = {
46         EINA_TRUE
47       } } },
48   {
49     ELM_STORE_ITEM_MAPPING_LABEL,
50       "elm.title.2", ELM_STORE_ITEM_MAPPING_OFFSET(My_Item, subject),
51       { .empty = {
52         EINA_TRUE
53       } } },
54   {
55     ELM_STORE_ITEM_MAPPING_LABEL,
56       "elm.text", ELM_STORE_ITEM_MAPPING_OFFSET(My_Item, head_content),
57       { .empty = {
58         EINA_TRUE
59       } } },
60   {
61     ELM_STORE_ITEM_MAPPING_ICON,
62       "elm.swallow.icon", 0,
63       { .icon = {
64         48, 48,
65         ELM_ICON_LOOKUP_THEME_FDO,
66         EINA_TRUE, EINA_FALSE,
67         EINA_TRUE,
68         EINA_FALSE, EINA_FALSE,
69       } } },
70   {
71     ELM_STORE_ITEM_MAPPING_CUSTOM,
72       "elm.swallow.end", 0,
73       { .custom = {
74         NULL
75       } } },
76   ELM_STORE_ITEM_MAPPING_END
77 };
78
79
80 ////// **** WARNING ***********************************************************
81 ////   * This function runs inside a thread outside efl mainloop. Be careful! *
82 //     ************************************************************************
83 static Eina_Bool
84 _st_store_list(void *data __UNUSED__, Elm_Store_Item_Info *item_info)
85 {
86   Elm_Store_Item_Info_Filesystem *info = (Elm_Store_Item_Info_Filesystem *)item_info;
87   int id;
88   char sort_id[7];
89
90   // create a sort id based on the filename itself assuming it is a numeric
91   // value like the id number in mh mail folders which is what this test
92   // uses as a data source
93   char *file = strrchr(info->path, '/');
94   if (file) file++;
95   else file = info->path;
96   id = atoi(file);
97   sort_id[0] = ((id >> 30) & 0x3f) + 32;
98   sort_id[1] = ((id >> 24) & 0x3f) + 32;
99   sort_id[2] = ((id >> 18) & 0x3f) + 32;
100   sort_id[3] = ((id >> 12) & 0x3f) + 32;
101   sort_id[4] = ((id >>  6) & 0x3f) + 32;
102   sort_id[5] = ((id >>  0) & 0x3f) + 32;
103   sort_id[6] = 0;
104   info->base.sort_id = strdup(sort_id);
105   // choose the item genlist item class to use (only item style should be
106   // provided by the app, store will fill everything else in, so it also
107   // has to be writable
108   info->base.item_class = &itc1; // based on item info - return the item class wanted (only style field used - rest reset to internal funcs store sets up to get label/icon etc)
109   info->base.mapping = it1_mapping;
110   info->base.data = NULL; // if we can already parse and load all of item here and want to - set this
111   return EINA_TRUE; // return true to include this, false not to
112 }
113 //     ************************************************************************
114 ////   * End of separate thread function.                                     *
115 ////// ************************************************************************
116
117 ////// **** WARNING ***********************************************************
118 ////   * This function runs inside a thread outside efl mainloop. Be careful! *
119 //     ************************************************************************
120 static void
121 _st_store_fetch(void *data __UNUSED__, Elm_Store_Item *sti)
122 {
123   const char *path = elm_store_item_filesystem_path_get(sti);
124   My_Item *myit;
125   FILE *f;
126   char buf[4096], *p;
127   Eina_Bool have_content = EINA_FALSE;
128   char *content = NULL, *content_pos = NULL, *content_end = NULL;
129
130   // if we already have my item data - skip
131   if (elm_store_item_data_get(sti)) return;
132   // open the mail file and parse it
133   f = fopen(path, "rb");
134   if (!f) return;
135
136   // alloc my item in memory that holds data to show in the list
137   myit = calloc(1, sizeof(My_Item));
138   if (!myit)
139     {
140       fclose(f);
141       return;
142     }
143   while (fgets(buf, sizeof(buf), f))
144     {
145       if (!have_content)
146         {
147           if (!isblank(buf[0]))
148             {
149               // get key: From:, Subject: etc.
150               if (!strncmp(buf, "From:", 5))
151                 {
152                   p = buf + 5;
153                   while ((*p) && (isblank(*p))) p++;
154                   p = strdup(p);
155                   if (p)
156                     {
157                       myit->from = p;
158                       p = strchr(p, '\n');
159                       if (p) *p = 0;
160                     }
161                 }
162               else if (!strncmp(buf, "Subject:", 8))
163                 {
164                   p = buf + 8;
165                   while ((*p) && (isblank(*p))) p++;
166                   p = strdup(p);
167                   if (p)
168                     {
169                       myit->subject = p;
170                       p = strchr(p, '\n');
171                       if (p) *p = 0;
172                     }
173                 }
174               else if (!strncmp(buf, "Date:", 5))
175                 {
176                   p = buf + 5;
177                   while ((*p) && (isblank(*p))) p++;
178                   p = strdup(p);
179                   if (p)
180                     {
181                       myit->date = p;
182                       p = strchr(p, '\n');
183                       if (p) *p = 0;
184                     }
185                 }
186               else if (buf[0] == '\n') // begin of content
187                 have_content = EINA_TRUE;
188             }
189         }
190       else
191         {
192           // get first 320 bytes of content/body
193           if (!content)
194             {
195               content = calloc(1, 320);
196               content_pos = content;
197               content_end = content + 319;
198             }
199           strncat(content_pos, buf, content_end - content_pos - 1);
200           content_pos = content + strlen(content);
201         }
202     }
203   fclose(f);
204   myit->head_content = elm_entry_utf8_to_markup(content);
205   free(content);
206   elm_store_item_data_set(sti, myit);
207 }
208 //     ************************************************************************
209 ////   * End of separate thread function.                                     *
210 ////// ************************************************************************
211
212 static void
213 _st_store_unfetch(void *data __UNUSED__, Elm_Store_Item *sti)
214 {
215   My_Item *myit = elm_store_item_data_get(sti);
216   if (!myit) return;
217   if (myit->from) free(myit->from);
218   if (myit->subject) free(myit->subject);
219   if (myit->date) free(myit->date);
220   if (myit->head_content) free(myit->head_content);
221   free(myit);
222   elm_store_item_data_set(sti, NULL);
223 }
224
225 void
226 test_store(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
227 {
228   Evas_Object *win, *bg, *gl, *bx;
229
230   Elm_Store *st;
231
232   win = elm_win_add(NULL, "store", ELM_WIN_BASIC);
233   elm_win_title_set(win, "Store");
234   elm_win_autodel_set(win, 1);
235
236   bg = elm_bg_add(win);
237   elm_win_resize_object_add(win, bg);
238   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
239   evas_object_show(bg);
240
241   bx = elm_box_add(win);
242   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
243   elm_win_resize_object_add(win, bx);
244   evas_object_show(bx);
245
246   gl = elm_genlist_add(win);
247   elm_genlist_height_for_width_mode_set(gl, EINA_TRUE);
248   evas_object_smart_callback_add(gl, "selected", _st_selected, NULL);
249   evas_object_smart_callback_add(gl, "clicked,double", _st_double_clicked, NULL);
250   evas_object_smart_callback_add(gl, "longpressed", _st_longpress, NULL);
251   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
252   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
253   elm_box_pack_end(bx, gl);
254   evas_object_show(gl);
255
256   st = elm_store_filesystem_new();
257   elm_store_list_func_set(st, _st_store_list, NULL);
258   elm_store_fetch_func_set(st, _st_store_fetch, NULL);
259   //elm_store_fetch_thread_set(st, EINA_FALSE);
260   elm_store_unfetch_func_set(st, _st_store_unfetch, NULL);
261   elm_store_sorted_set(st, EINA_TRUE);
262   elm_store_target_genlist_set(st, gl);
263   elm_store_filesystem_directory_set(st, "./store");
264
265   evas_object_resize(win, 480, 800);
266   evas_object_show(win);
267 }
268 #endif