first try to journal_store_get_latest_id() for sqlite
[k8lowj.git] / src / link.c
blob1833d30c79a8d650cfea785a54658c6cb1f888f9
1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2003 Evan Martin <evan@livejournal.com>
4 * vim: tabstop=4 shiftwidth=4 noexpandtab :
5 */
7 #include "gtk-all.h"
8 #include <gdk/gdkkeysyms.h>
9 #include <gdk/gdktypes.h>
10 #include <stdio.h>
11 #include "util-gtk.h"
12 #include "conf.h"
13 #include "jamdoc.h"
14 #include "util.h"
16 typedef struct {
17 GtkWidget *dlg;
18 GtkWidget *etext, *ruser, *euser, *rurl, *eurl;
19 JamDoc *doc;
20 gint sel_type, clip_type;
21 gchar *sel_input, *clip_input;
22 } LinkDialog;
24 static void
25 select_toggled(GtkToggleButton *tb, GtkWidget *focus) {
26 if (gtk_toggle_button_get_active(tb))
27 gtk_widget_grab_focus(focus);
30 static void
31 entry_focus_cb(GtkWidget *w, GdkEventFocus *e, GtkToggleButton *radio) {
32 gtk_toggle_button_set_active(radio, TRUE);
35 static GtkWidget*
36 radio_option(GSList *g, GtkWidget **radio, GtkWidget **entry,
37 const char *caption, const char *label, const char *initial) {
38 GtkWidget *vbox;
40 vbox = gtk_vbox_new(FALSE, 0);
41 *radio = gtk_radio_button_new_with_mnemonic(g, caption);
42 gtk_box_pack_start(GTK_BOX(vbox), *radio, FALSE, FALSE, 0);
44 *entry = gtk_entry_new();
45 gtk_entry_set_activates_default(GTK_ENTRY(*entry), TRUE);
46 g_signal_connect(G_OBJECT(*entry), "focus-in-event",
47 G_CALLBACK(entry_focus_cb), *radio);
48 if (initial)
49 gtk_entry_set_text(GTK_ENTRY(*entry), initial);
50 gtk_widget_set_size_request(*entry, 75, -1);
51 g_signal_connect(G_OBJECT(*radio), "toggled",
52 G_CALLBACK(select_toggled), *entry);
53 g_signal_connect(G_OBJECT(*radio), "activate",
54 G_CALLBACK(select_toggled), *entry);
56 if (label) {
57 GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
58 gtk_box_pack_start(GTK_BOX(hbox),
59 gtk_label_new(label),
60 FALSE, FALSE, 0);
61 gtk_box_pack_start(GTK_BOX(hbox), *entry, TRUE, TRUE, 0);
62 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
63 } else {
64 gtk_box_pack_start(GTK_BOX(vbox), *entry, TRUE, TRUE, 0);
67 return vbox;
70 #if !GLIB_CHECK_VERSION(2,2,0)
71 static gboolean
72 g_str_has_prefix(const gchar *str, const gchar *prefix) {
73 return (strncmp(str, prefix, strlen(prefix)) == 0);
75 #endif
77 #if 0
78 gchar*
79 link_magic(LinkRequest *lr) {
80 gchar *a, *b;
81 if (! ((lr->clip_type | lr->sel_type) & JAM_SELECTION_HAS_URL))
82 return NULL;
84 xml_escape(&lr->clip_input);
86 /* boo for no list primitives in c */
87 if (lr->clip_type & JAM_SELECTION_HAS_URL) {
88 a = lr->clip_input; b = lr->sel_input;
89 } else {
90 b = lr->clip_input; a = lr->sel_input;
93 return g_strdup_printf("<a href=\"%s\">%s</a>", a, b);
95 #endif
97 static void
98 make_link_dialog(LinkDialog *ld, GtkWindow *win, gboolean livejournal) {
99 GtkWidget *vbox;
100 GtkWidget *subbox;
101 GSList *rgroup;
103 ld->dlg = gtk_dialog_new_with_buttons(_("Make Link"),
104 win, GTK_DIALOG_MODAL,
105 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
106 GTK_STOCK_OK, GTK_RESPONSE_OK,
107 NULL);
108 gtk_dialog_set_default_response(GTK_DIALOG(ld->dlg), GTK_RESPONSE_OK);
110 vbox = gtk_vbox_new(FALSE, 10);
112 ld->etext = gtk_entry_new();
113 gtk_entry_set_activates_default(GTK_ENTRY(ld->etext), TRUE);
114 subbox = labelled_box_new(_("Link _Text:"), ld->etext);
115 gtk_box_pack_start(GTK_BOX(vbox), subbox, FALSE, FALSE, 0);
117 gtk_box_pack_start(GTK_BOX(vbox),
118 radio_option(NULL, &ld->rurl, &ld->eurl, _("_URL:"), NULL, ""),
119 FALSE, FALSE, 0);
121 rgroup = gtk_radio_button_get_group(GTK_RADIO_BUTTON(ld->rurl));
123 if (livejournal) {
124 gtk_box_pack_start(GTK_BOX(vbox),
125 radio_option(rgroup, &ld->ruser, &ld->euser,
126 _("_LiveJournal User:"), ".../users/", ""),
127 FALSE, FALSE, 0);
130 jam_dialog_set_contents(GTK_DIALOG(ld->dlg), vbox);
133 static gboolean
134 has_url(char *buf) {
135 if (!buf || buf[0] == 0) return FALSE;
136 /* just test a few of the obvious ones... */
137 if (g_str_has_prefix(buf, "http://") ||
138 g_str_has_prefix(buf, "ftp://") ||
139 g_str_has_suffix(buf, ".com") ||
140 g_str_has_suffix(buf, ".net") ||
141 g_str_has_suffix(buf, ".org"))
142 return TRUE;
143 return FALSE;
146 static void
147 prepopulate_fields(LinkDialog *ld, char *bufsel) {
148 GtkClipboard *clipboard;
149 char *clipsel, *url = NULL;
151 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
152 clipsel = gtk_clipboard_wait_for_text(clipboard);
154 if (bufsel && has_url(bufsel)) {
155 url = bufsel;
156 } else if (clipsel && has_url(clipsel)) {
157 url = clipsel;
160 if (bufsel)
161 gtk_entry_set_text(GTK_ENTRY(ld->etext), bufsel);
162 if (url) {
163 char *niceurl;
164 if (g_str_has_prefix(url, "http://") ||
165 g_str_has_prefix(url, "ftp://")) {
166 niceurl = url;
167 } else {
168 niceurl = g_strdup_printf("http://%s", url);
170 gtk_entry_set_text(GTK_ENTRY(ld->eurl), niceurl);
171 if (niceurl != url)
172 g_free(niceurl);
175 g_free(clipsel);
178 static char*
179 get_link(LinkDialog *ld, JamAccount *acc) {
180 char *url, *user, *text;
181 char *link = NULL;
183 url = gtk_editable_get_chars(GTK_EDITABLE(ld->eurl), 0, -1);
184 xml_escape(&url);
185 user = gtk_editable_get_chars(GTK_EDITABLE(ld->euser), 0, -1);
186 xml_escape(&user);
187 text = gtk_editable_get_chars(GTK_EDITABLE(ld->etext), 0, -1);
188 xml_escape(&text);
190 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ld->rurl))) {
191 /* build a "url" link. */
192 link = g_strdup_printf("<noindex><a href=\"%s\" rel=\"nofollow\" rel=\"noreferrer\" style=\"text-decoration:overline\">%s</a></noindex>", url, text);
193 } else if (ld->ruser && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ld->ruser))) {
194 /* build a "friends" link. */
195 LJServer *server = jam_account_lj_get_server(JAM_ACCOUNT_LJ(acc));
196 g_free(url);
197 url = g_strdup(server->url);
198 xml_escape(&url);
199 link = g_strdup_printf("<noindex><a href=\"%s/users/%s\" rel=\"nofollow\" rel=\"noreferrer\" style=\"text-decoration:overline\">%s</a></noindex>",
200 url, user, text);
202 g_free(url);
203 g_free(user);
204 g_free(text);
206 return link;
209 void
210 link_dialog_run(GtkWindow *win, JamDoc *doc) {
211 STACK(LinkDialog, ld);
212 GtkTextBuffer *buffer;
213 GtkTextIter start, end;
214 char *sel = NULL;
215 char *link;
217 JamAccount *acc = jam_doc_get_account(doc);
218 make_link_dialog(ld, win, JAM_ACCOUNT_IS_LJ(acc));
220 buffer = jam_doc_get_text_buffer(doc);
221 if (gtk_text_buffer_get_selection_bounds(buffer, &start, &end))
222 sel = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
223 prepopulate_fields(ld, sel);
224 g_free(sel);
226 if (gtk_dialog_run(GTK_DIALOG(ld->dlg)) != GTK_RESPONSE_OK) {
227 gtk_widget_destroy(ld->dlg);
228 return;
231 link = get_link(ld, acc);
233 gtk_widget_destroy(ld->dlg);
235 if (link) {
236 gtk_text_buffer_begin_user_action(buffer);
237 gtk_text_buffer_delete(buffer, &start, &end);
238 gtk_text_buffer_insert(buffer, &start, link, -1);
239 gtk_text_buffer_end_user_action(buffer);
240 g_free(link);