summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <marcel-hollerbach@t-online.de>2017-11-30 11:26:27 +0100
committerMarcel Hollerbach <marcel-hollerbach@t-online.de>2017-11-30 18:03:38 +0100
commitadaf7eac7a267f552b5b17dcc5992af6f082fa32 (patch)
tree375d1ed79ecce5fa64ef1edbd1819e106ecb765a
inital wiked!
-rw-r--r--.gitmodules3
-rw-r--r--AUTHORS1
-rw-r--r--COPYING25
-rw-r--r--ChangeLog0
-rw-r--r--NEWS0
-rw-r--r--README1
-rw-r--r--meson.build31
-rw-r--r--module.desktop7
m---------src/jsmn0
-rw-r--r--src/main.c147
-rw-r--r--src/meson.build24
-rw-r--r--src/wiki.c190
-rw-r--r--src/wiki.h36
13 files changed, 465 insertions, 0 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..8b0173e
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
1[submodule "git/wiked/src/jsmn"]
2 path = src/jsmn
3 url = https://github.com/zserge/jsmn.git
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..115ac3c
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
Marcel Hollerbach <marcel-hollerbach@t-online.de>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..f60652c
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,25 @@
1Copyright notice for Enlightenment:
2
3Copyright (C) 2017 Marcel Hollerbach and various contributors (see AUTHORS)
4
5All rights reserved.
6
7Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are met:
9
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
17INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
18FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
22OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..79eedb7
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
git submodule --init --update
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..251b479
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,31 @@
1project('wiked', 'c')
2
3e = dependency('enlightenment')
4
5dir_module_e = e.get_pkgconfig_variable('modules')
6release = e.get_pkgconfig_variable('release')
7host_os = host_machine.system()
8cc = meson.get_compiler('c')
9
10if host_os == 'linux'
11 if cc.has_header_symbol('features.h', '__UCLIBC__')
12 host_os = 'linux-uclibc'
13 elif cc.has_header_symbol('features.h', '__dietlibc__')
14 host_os = 'linux-dietlibc'
15 else
16 host_os = 'linux-gnu'
17 endif
18endif
19module_arch = '@0@-@1@-@2@'.format(host_os, host_machine.cpu_family(), release)
20
21install_mod_dir = join_paths(dir_module_e, meson.project_name())
22install_dir = join_paths(install_mod_dir, module_arch)
23
24config_h = configuration_data()
25config_h.set_quoted('MODULE_DIR', install_dir)
26
27subdir('src')
28
29configure_file(output: 'config.h', install: false, configuration: config_h)
30
31install_data('module.desktop', install_dir : install_mod_dir)
diff --git a/module.desktop b/module.desktop
new file mode 100644
index 0000000..d8a8da4
--- /dev/null
+++ b/module.desktop
@@ -0,0 +1,7 @@
1[Desktop Entry]
2Encoding=UTF-8
3Type=Link
4Name=YOUR-MODULE
5Comment=description
6Icon=preferences-desktop-wallpaper
7X-Enlightenment-ModuleType=settings
diff --git a/src/jsmn b/src/jsmn
new file mode 160000
Subproject 35086597a72d94d8393e6a90b96e553d714085b
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..1c53923
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,147 @@
1#include "wiki.h"
2#include <Ecore_Con.h>
3#include <Elementary.h>
4
5static Ecore_Timer *timer = NULL;
6static Wiki *w;
7
8static void
9_wiki_item_clicked_twice(void *data EINA_UNUSED, Evas_Object *obj, void *event_info)
10{
11 Eina_Strbuf *buf;
12
13 buf = eina_strbuf_new();
14 eina_strbuf_append(buf, "xdg-open ");
15 eina_strbuf_append(buf, elm_object_item_data_get(event_info));
16
17 system(eina_strbuf_release(buf));
18}
19
20static Eina_Value
21_wiki_arrived(void *data, const Eina_Value value, const Eina_Future *f)
22{
23 Evas_Object *win, *entry = data, *list;
24
25 //this creates a new popup due to runner
26 win = elm_win_add(elm_win_get(entry), "win", ELM_WIN_POPUP_MENU);
27 elm_win_alpha_set(win, 1);
28
29 list = elm_list_add(win);
30 evas_object_smart_callback_add(list, "clicked,double", _wiki_item_clicked_twice, NULL);
31
32 for (int i = 0; i < eina_value_array_count(&value); ++i)
33 {
34 const char *url, *desc, *name;
35
36 //get the data from the eina value
37 Eina_Value list_val;
38 Eina_Value *st = eina_value_struct_new(public_wiki_struct());
39
40 eina_value_array_get(&value, i, &list_val);
41
42 eina_value_set(st, list_val);
43
44 eina_value_struct_get(st, "name", &name);
45 eina_value_struct_get(st, "description", &desc);
46 eina_value_struct_get(st, "url", &url);
47
48 eina_value_free(st);
49
50 //append it to the list
51 Elm_Object_Item *item = elm_list_item_append(list, name, NULL, NULL, NULL, url);
52 elm_object_item_tooltip_text_set(item, desc);
53 }
54
55 evas_object_size_hint_min_set(list, 200, 150);
56 evas_object_show(list);
57
58 elm_win_resize_object_add(win, list);
59
60 evas_object_show(win);
61
62 return value;
63}
64
65
66/*
67int main(int argc, char const *argv[])
68{
69 ecore_init();
70 ecore_con_init();
71 ecore_con_url_init();
72 Wiki *w;
73
74 w = wiki_new(ecore_main_loop_get(), "en.wikipedia.org");
75
76
77 ecore_main_loop_begin();
78
79 ecore_con_url_shutdown();
80 ecore_con_shutdown();
81 ecore_shutdown();
82 return 0;
83}
84*/
85static Eina_Bool
86_done(void *data)
87{
88 Eina_Future *p;
89 const char *search_text = elm_object_text_get(data);
90
91 //if there is search text, then search the wiki
92 if (search_text && strlen(search_text) != 0)
93 {
94 p = wiki_remote_fetch(w, search_text);
95 eina_future_then(p, _wiki_arrived, data);
96 }
97
98 timer = NULL;
99 return ECORE_CALLBACK_CANCEL;
100}
101
102static void
103_changed(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
104{
105 //for the case a timer is still there, extend it
106 if (timer)
107 ecore_timer_reset(timer);
108 //otherwise just create a new timer
109 else
110 timer = ecore_timer_add(0.5, _done, obj);
111}
112
113
114int elm_main(int argc, char *argv[])
115{
116 Evas_Object *win, *o;
117
118 //create the wiki instance
119 w = wiki_new(ecore_main_loop_get(), "en.wikipedia.org");
120
121 //new window
122 win = elm_win_add(NULL, "wiked", ELM_WIN_BASIC);
123 elm_win_title_set(win, "Wiked");
124 elm_win_autodel_set(win, EINA_TRUE);
125 elm_win_alpha_set(win, EINA_TRUE);
126
127 //setup the entry we prompt from
128 o = elm_entry_add(win);
129 evas_object_smart_callback_add(o, "changed", _changed, NULL);
130 elm_entry_single_line_set(o, EINA_TRUE);
131 elm_entry_scrollable_set(o, EINA_TRUE);
132 evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
133 evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
134 evas_object_show(o);
135
136 elm_win_resize_object_add(win, o);
137 evas_object_show(win);
138
139 //run app RUN!
140 elm_run();
141
142 //shutdown!
143 wiki_free(w);
144 return 0;
145}
146
147ELM_MAIN();
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 0000000..2e33ef8
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,24 @@
1e = dependency('enlightenment')
2
3src = [
4 # 'e_mod_main.c',
5 'wiki.h',
6 'wiki.c',
7 'jsmn/jsmn.c',
8 'jsmn/jsmn.h',
9 'main.c'
10]
11
12#module = shared_module('module',
13# src,
14 # dependencies : e,
15 # install_dir: install_dir,
16 # install: true,
17 # name_prefix: '')
18
19executable('tester',
20 src,
21 dependencies: e,
22 install_dir: install_dir,
23 install: true
24)
diff --git a/src/wiki.c b/src/wiki.c
new file mode 100644
index 0000000..2a0352a
--- /dev/null
+++ b/src/wiki.c
@@ -0,0 +1,190 @@
1
2#define EFL_EO_API_SUPPORT
3#define EFL_BETA_API_SUPPORT
4
5
6#include <stdlib.h>
7#include <stdio.h>
8#include <string.h>
9#include <Ecore.h>
10#include <Ecore_Con.h>
11#include <Eina.h>
12
13#include "jsmn/jsmn.h"
14#include "wiki.h"
15
16typedef enum {
17 FUTURE_STATE_PENING = 0,
18 FUTURE_STATE_DONE = 1,
19} Future_State;
20
21//=============================================================================
22
23struct _Wiki
24{
25 Efl_Loop *loop;
26 char *remote;
27};
28
29//
30Wiki*
31wiki_new(Efl_Loop *loop, const char *remote)
32{
33 Wiki *wiki = calloc(1, sizeof(Wiki));
34
35 wiki->remote = strdup(remote);
36 wiki->loop = loop;
37
38 return wiki;
39}
40
41void
42wiki_free(Wiki *w)
43{
44 free(w->remote);
45 free(w);
46}
47
48typedef struct {
49 Ecore_Con_Url *url;
50 Eina_Strbuf *buf;
51 Eina_Promise *future;
52 Ecore_Event_Handler *ev_data, *ev_complete;
53} Request_Data;
54
55EINA_VALUE_STRUCT_DESC_DEFINE(wiki_struct, NULL, sizeof(Wiki_Remote_Article),
56 {"name", EINA_VALUE_TYPE_STRINGSHARE, offsetof(Wiki_Remote_Article, name)},
57 {"description", EINA_VALUE_TYPE_STRINGSHARE, offsetof(Wiki_Remote_Article, description)},
58 {"url", EINA_VALUE_TYPE_STRINGSHARE, offsetof(Wiki_Remote_Article, url)}
59)
60
61PUBLIC Eina_Value_Struct_Desc*
62public_wiki_struct(void)
63{
64 return wiki_struct();
65}
66
67static void
68_request_data_free(Request_Data *d)
69{
70 ecore_event_handler_del(d->ev_data);
71 ecore_event_handler_del(d->ev_complete);
72 ecore_con_url_free(d->url);
73 eina_strbuf_free(d->buf);
74 free(d);
75}
76
77static Eina_Bool
78_data_get(void *data, int type, void *event_info)
79{
80 Request_Data *d = data;
81 Ecore_Con_Event_Url_Data *ev = event_info;
82
83 if (ev->url_con != d->url) return ECORE_CALLBACK_PASS_ON;
84
85 eina_strbuf_append_length(d->buf, ((const char*) &ev->data[0]), ev->size);
86
87 return ECORE_CALLBACK_PASS_ON;
88}
89
90static Eina_Value*
91_binbuf_to_array(Eina_Strbuf *buf)
92{
93 jsmn_parser p;
94 jsmntok_t tok[1024];
95 jsmntok_t *name, *description, *url;
96 int number_results;
97
98
99 Eina_Value *array = eina_value_array_new(EINA_VALUE_TYPE_STRUCT, 0);
100
101 jsmn_init(&p);
102 jsmn_parse(&p, eina_strbuf_string_get(buf), eina_strbuf_length_get(buf), tok, 1024);
103
104 EINA_SAFETY_ON_FALSE_RETURN_VAL(tok[0].type == JSMN_ARRAY, array);
105 EINA_SAFETY_ON_FALSE_RETURN_VAL(tok[0].size == 4, array);
106 EINA_SAFETY_ON_FALSE_RETURN_VAL(tok[1].type == JSMN_STRING, array);
107
108 number_results = tok[2].size;
109
110 name = tok + 1 + 2;
111 description = name + 1 + number_results;
112 url = description + 1 + number_results;
113
114 eina_value_free(array);
115 array = eina_value_array_new(EINA_VALUE_TYPE_STRUCT, number_results);
116
117 for (int i = 0; i < number_results; ++i) {
118 Eina_Value *str = eina_value_struct_new(wiki_struct());
119 Eina_Value_Struct st;
120
121 eina_value_struct_set(str, "name", eina_strbuf_release(
122 eina_strbuf_substr_get(buf, name[i].start, name[i].end - name[i].start))
123 );
124 eina_value_struct_set(str, "description", eina_strbuf_release(
125 eina_strbuf_substr_get(buf, description[i].start, description[i].end - description[i].start))
126 );
127 eina_value_struct_set(str, "url", eina_strbuf_release(
128 eina_strbuf_substr_get(buf, url[i].start, url[i].end - url[i].start))
129 );
130
131 eina_value_get(str, &st);
132
133 eina_value_array_append(array, st);
134 }
135
136 return array;
137}
138
139static Eina_Bool
140_data_complete(void *data, int type, void *event_info)
141{
142 Ecore_Con_Event_Url_Complete *ev = event_info;
143 Request_Data *d = data;
144 Eina_Value *array;
145
146 if (ev->url_con != d->url) return ECORE_CALLBACK_PASS_ON;
147
148 if (!(ev->status >= 200 && ev->status <= 226))
149 {
150 eina_promise_reject(d->future, EINA_ERROR_VALUE_FAILED);
151 }
152 else
153 {
154 array = _binbuf_to_array(d->buf);
155 eina_promise_resolve(d->future, *array);
156
157 }
158
159 _request_data_free(d);
160 return ECORE_CALLBACK_DONE;
161}
162
163static void
164_remote_fetch_cancel(void *data, const Eina_Promise *dead_promise)
165{
166 Request_Data *d = data;
167
168 _request_data_free(d);
169}
170
171Eina_Future*
172wiki_remote_fetch(Wiki *w, const char *search_text)
173{
174 Request_Data *data = calloc(1, sizeof(Request_Data));
175 Eina_Promise *p = eina_promise_new(efl_loop_future_scheduler_get(w->loop), _remote_fetch_cancel, data);
176 Eina_Strbuf *buf = eina_strbuf_new();
177
178 eina_strbuf_append_printf(buf, "%s/w/api.php?action=opensearch&search=%s", w->remote, search_text);
179
180 data->url = ecore_con_url_new(eina_strbuf_string_get(buf));
181 data->buf = eina_strbuf_new();
182 data->future = p;
183
184 data->ev_data = ecore_event_handler_add(ECORE_CON_EVENT_URL_DATA, _data_get, data);
185 data->ev_complete = ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE, _data_complete, data);
186 ecore_con_url_get(data->url);
187
188 eina_strbuf_free(buf);
189 return eina_future_new(p);
190}
diff --git a/src/wiki.h b/src/wiki.h
new file mode 100644
index 0000000..97b9371
--- /dev/null
+++ b/src/wiki.h
@@ -0,0 +1,36 @@
1#ifndef WIKI_H
2#define WIKI_H
3
4#define EFL_EO_API_SUPPORT
5#define EFL_BETA_API_SUPPORT
6
7#define PUBLIC __attribute__ ((visibility ("default")))
8
9#include <Eina.h>
10#include <Ecore.h>
11
12typedef struct _Wiki Wiki;
13
14typedef struct _Wiki_Future Wiki_Future;
15
16typedef struct {
17 const char *name;
18 const char *description;
19 const char *url;
20} Wiki_Remote_Article;
21
22typedef struct {
23 Wiki_Remote_Article *article;
24 unsigned int number;
25} Wiki_Remote_Request;
26
27typedef void (Wiki_Future_Request_Done_Cb)(void *data, Wiki_Remote_Request *req);
28
29//
30PUBLIC Wiki* wiki_new(Efl_Loop *loop, const char *remote);
31PUBLIC void wiki_free(Wiki *w);
32PUBLIC Eina_Future* wiki_remote_fetch(Wiki *w, const char *search_text);
33PUBLIC Eina_Value_Struct_Desc* public_wiki_struct(void);
34//
35void wiki_remote_request_free(Wiki_Remote_Request *req);
36#endif