3
* glspi_app.c - This file is part of the Lua scripting plugin for the Geany IDE
4
* See the file "geanylua.c" for copyright information.
12
#define NEED_FAIL_ARG_TYPE
16
static gint glspi_pluginver(lua_State* L)
20
"Copyright (c) 2007-2008 "PLUGIN_AUTHOR", et al.\n"
21
"Compiled on "__DATE__" at "__TIME__" for Geany API version %d\n"
22
"Released under version 2 of the GNU General Public License.\n"
24
PLUGIN_NAME, PLUGIN_VER, PLUGIN_DESC, MY_GEANY_API_VER);
29
static gint glspi_tools(lua_State* L)
32
SetTableStr("browser", geany_data->tool_prefs->browser_cmd);
33
SetTableStr("make", geany_data->tool_prefs->make_cmd);
34
SetTableStr("term", geany_data->tool_prefs->term_cmd);
35
SetTableStr("grep", geany_data->tool_prefs->grep_cmd);
36
SetTableStr("action", geany_data->tool_prefs->context_action_cmd);
41
static gint glspi_template(lua_State* L)
44
SetTableStr("developer", geany_data->template_prefs->developer);
45
SetTableStr("company", geany_data->template_prefs->company);
46
SetTableStr("mail", geany_data->template_prefs->mail);
47
SetTableStr("initial", geany_data->template_prefs->initials);
48
SetTableStr("version", geany_data->template_prefs->version);
54
static gint glspi_project(lua_State* L)
56
GeanyProject *project = geany->app->project;
60
SetTableStr("name", project->name);
61
SetTableStr("desc", project->description);
62
SetTableStr("file", project->file_name);
63
SetTableStr("base", project->base_path);
64
SetTableStr("exec", project->run_cmd);
65
if (project->file_patterns && *project->file_patterns) {
66
gchar *tmp=g_strjoinv(";", project->file_patterns);
67
SetTableStr("mask", tmp);
76
static gchar *glspi_script_dir = NULL;
78
static gint glspi_appinfo(lua_State* L)
80
GeanyApp *app = geany->app;
83
SetTableBool("debug", app->debug_mode);
84
SetTableStr("configdir", app->configdir);
85
SetTableStr("datadir", app->datadir);
86
SetTableStr("docdir", app->docdir);
87
SetTableStr("scriptdir", glspi_script_dir);
88
lua_pushstring(L,"template");
92
lua_pushstring(L,"tools");
97
lua_pushstring(L,"project");
108
#define CLIPBOARD gtk_clipboard_get(GDK_SELECTION_PRIMARY)
110
static gint glspi_xsel(lua_State* L)
112
if (lua_gettop(L)>0) {
113
if (lua_isstring(L,1)) {
115
const gchar*txt=lua_tolstring(L,1,&len);
116
gtk_clipboard_set_text(CLIPBOARD,txt,len);
122
gchar *txt=gtk_clipboard_wait_for_text(CLIPBOARD);
124
lua_pushstring(L,txt);
127
lua_pushstring(L,"");
134
static gint glspi_xsel(lua_State* L) { return 0; }
140
static gint glspi_signal(lua_State* L) {
141
const gchar*widname,*signame;
145
if ((lua_gettop(L)<2)||!lua_isstring(L,2) ) { return FAIL_STRING_ARG(2); }
146
if (!lua_isstring(L,1) ) { return FAIL_STRING_ARG(1); }
147
widname=lua_tostring(L,1);
148
signame=lua_tostring(L,2);
149
w=ui_lookup_widget(main_widgets->window, widname);
151
lua_pushfstring(L, _("Error in module \"%s\" at function %s():\n"
152
"widget \"%s\" not found for argument #1.\n "),
153
LUA_MODULE_NAME, &__FUNCTION__[6], widname);
157
typeid=G_OBJECT_TYPE(w);
158
sigid=g_signal_lookup(signame,typeid);
160
lua_pushfstring(L, _("Error in module \"%s\" at function %s() argument #2:\n"
161
"widget \"%s\" has no signal named \"%s\".\n "),
162
LUA_MODULE_NAME, &__FUNCTION__[6], widname, signame);
167
g_signal_emit(w, sigid, 0);
176
#define realpath(src,dst) _fullpath((dst),(src),_MAX_PATH)
182
typedef int (*statfunc) (const char *fn, struct stat *st);
184
static gint glspi_stat(lua_State* L)
189
if (lua_gettop(L)<1) { return FAIL_STRING_ARG(1); }
190
if (lua_gettop(L)>=2) {
191
if (!lua_isboolean(L,2)) { return FAIL_BOOL_ARG(2); }
192
sf=lua_toboolean(L,2)?lstat:stat;
194
if (!lua_isstring(L,1)) { return FAIL_STRING_ARG(1); }
195
fn=lua_tostring(L,1);
198
switch ( st.st_mode & S_IFMT) {
199
case S_IFBLK:ft="b"; break;
200
case S_IFCHR:ft="c"; break;
201
case S_IFDIR:ft="d"; break;
202
case S_IFIFO:ft="f"; break;
203
case S_IFREG:ft="r"; break;
205
case S_IFLNK:ft="l"; break;
206
case S_IFSOCK:ft="s"; break;
210
SetTableNum("size",st.st_size);
211
SetTableNum("time",st.st_mtime);
212
SetTableStr("type",ft);
213
SetTableBool("read", (access(fn,R_OK)==0));
214
SetTableBool("write", (access(fn,W_OK)==0));
215
SetTableBool("exec", (access(fn,X_OK)==0));
219
lua_pushstring(L, strerror(errno));
224
static gint glspi_basename(lua_State* L)
226
if (lua_gettop(L)>=1) {
228
const gchar *fn=NULL;
229
if (!lua_isstring(L,1)) { return FAIL_STRING_ARG(1); }
230
fn=lua_tostring(L,1);
231
bn=g_path_get_basename(fn);
232
lua_pushstring(L,bn);
240
static gint glspi_dirname(lua_State* L)
242
if (lua_gettop(L)>=1) {
244
const gchar *fn=NULL;
245
if (!lua_isstring(L,1)) { return FAIL_STRING_ARG(1); }
246
fn=lua_tostring(L,1);
247
dn=g_path_get_dirname(fn);
248
lua_pushstring(L,dn);
258
static gint glspi_fullpath(lua_State* L)
260
if (lua_gettop(L)>=1) {
262
const gchar *fn=NULL;
263
if (!lua_isstring(L,1)) { return FAIL_STRING_ARG(1); }
264
fn=lua_tostring(L,1);
265
rp=realpath(fn,NULL);
267
lua_pushstring(L,rp);
277
static gint dirlist_closure(lua_State *L)
279
GDir*dir=lua_touserdata(L,lua_upvalueindex(1));
280
const gchar*entry=g_dir_read_name(dir);
282
lua_pushstring(L,entry);
292
static gint glspi_dirlist(lua_State* L)
297
if (lua_gettop(L)>=1) {
298
if (!lua_isstring(L,1)) { return FAIL_STRING_ARG(1); }
299
dn=lua_tostring(L,1);
301
dir=g_dir_open(dn,0,&err);
303
lua_pushlightuserdata(L,dir);
304
lua_pushcclosure(L,&dirlist_closure,1);
307
lua_pushfstring(L, "Error in module \"%s\" at function %s() argument #2\n%s",
308
LUA_MODULE_NAME, &__FUNCTION__[6],err?err->message:"Error reading directory."
310
if (err) {g_error_free(err);}
319
static gint glspi_wkdir(lua_State* L)
321
if (lua_gettop(L)== 0 ) {
322
gchar*wd=getcwd(NULL,0);
324
lua_pushstring(L,wd);
329
if (!lua_isstring(L,1)) { return FAIL_STRING_ARG(1); }
330
if ( chdir(lua_tostring(L,1)) == 0 ) {
331
lua_pushboolean(L,TRUE);
334
lua_pushboolean(L,FALSE);
335
lua_pushstring(L, strerror(errno));
342
#include "glspi_keycmd.h"
344
static GHashTable*key_cmd_hash=NULL;
346
static void glspi_init_key_cmd_hash(void)
349
key_cmd_hash=g_hash_table_new(g_str_hash,g_str_equal);
350
for (i=0;key_cmd_hash_entries[i].name; i++) {
352
key_cmd_hash,key_cmd_hash_entries[i].name,&key_cmd_hash_entries[i]);
357
static void glspi_free_key_cmd_hash(void) {
359
g_hash_table_destroy(key_cmd_hash);
364
void glspi_set_key_cmd_hash(gboolean create) {
366
glspi_init_key_cmd_hash ();
368
glspi_free_key_cmd_hash();
374
#define lookup_key_cmd_str(cmd) g_hash_table_lookup(key_cmd_hash,cmd);
377
static gint glspi_keycmd(lua_State* L)
379
KeyCmdHashEntry*he=NULL;
380
if (lua_gettop(L)<1) {return FAIL_STRING_ARG(1); }
381
if (lua_isstring(L,1)) {
385
memset(cmdbuf,'\0', sizeof(cmdbuf));
386
strncpy(cmdbuf,lua_tostring(L,1),sizeof(cmdbuf)-1);
387
for (i=0;cmdbuf[i];i++) {cmdbuf[i]=g_ascii_toupper(cmdbuf[i]);}
389
if (strncmp(cmdname,"GEANY_",6)==0) {
391
if (strncmp(cmdname,"KEYS_",5)==0) {
395
he=lookup_key_cmd_str(cmdname);
396
} else { return FAIL_STRING_ARG(1); }
399
L, _( "Error in module \"%s\" at function %s():\n"
400
"unknown command \"%s\" given for argument #1.\n"),
401
LUA_MODULE_NAME, &__FUNCTION__[6], lua_tostring(L,1));
405
keybindings_send_command(he->group, he->key_id);
410
static gint glspi_launch(lua_State* L)
412
gint argc=lua_gettop(L);
417
if (argc==0) { return FAIL_STRING_ARG(1); }
418
for (i=1;i<=argc;i++) {
419
if (!lua_isstring(L,i)) { return FAIL_STRING_ARG(i); }
421
argv=g_malloc0(sizeof(gchar *)*argc+1);
422
for (i=0;i<argc;i++) {
423
argv[i]=(g_strdup(lua_tostring(L,i+1)));
425
rv=g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &err);
427
lua_pushboolean(L,rv);
428
if (rv) { return 1; }
429
lua_pushstring(L,err->message);
435
static guint My_Shift_L=0;
436
static guint My_Shift_R=0;
437
static guint My_Control_L=0;
438
static guint My_Control_R=0;
439
static guint My_Alt_L=0;
440
static guint My_Alt_R=0;
445
#include <X11/Xlib.h>
446
#include <X11/keysym.h>
447
#include <sys/time.h>
450
#define IsShift ( (My_Shift_L == ev->xkey.keycode) || (My_Shift_R == ev->xkey.keycode) )
452
#define IsCtrl ( (My_Control_L == ev->xkey.keycode) || (My_Control_R == ev->xkey.keycode) )
453
#define IsAlt ( (My_Alt_L == ev->xkey.keycode) || (My_Alt_R == ev->xkey.keycode) )
455
#define IsCtrlAlt ( IsCtrl || IsAlt )
457
typedef struct _KeyGrabData {
463
static GdkFilterReturn keygrab_cb(GdkXEvent *xevent, GdkEvent *event, gpointer data)
465
XEvent*ev = (XEvent*) xevent;
466
GdkKeymapKey *km = (GdkKeymapKey*) data;
472
if (!IsCtrlAlt) km->group=1; /* Flag to know we have keydown before keyup */
474
return GDK_FILTER_REMOVE;
480
if ((km->group==1)&&(!IsCtrlAlt)) { /* OK, we already got our keydown */
482
km->level=(ev->xkey.state & ShiftMask)?1:0;
483
km->keycode=ev->xkey.keycode;
486
return GDK_FILTER_REMOVE;
490
return GDK_FILTER_CONTINUE;
493
static void dosleep(void)
495
struct timespec req, rem;
498
nanosleep(&req, &rem);
503
#define dosleep() Sleep(1)
505
#define IsShift ( (My_Shift_L == msg->wParam) || (My_Shift_R == msg->wParam) )
507
#define IsCtrl ( (My_Control_L == msg->wParam) || (My_Control_R == msg->wParam) )
508
#define IsAlt ( (My_Alt_L == msg->wParam) || (My_Alt_R == msg->wParam) )
510
#define IsCtrlAlt ( IsCtrl || IsAlt )
513
static GdkFilterReturn keygrab_cb(GdkXEvent *xevent, GdkEvent *event, gpointer data)
515
MSG*msg = (MSG*) xevent;
516
GdkKeymapKey *km = (GdkKeymapKey*) data;
517
switch (msg->message) {
522
if (!IsCtrlAlt) km->group=1; /* Flag to know we have keydown before keyup */
524
return GDK_FILTER_REMOVE;
530
if ((km->group==1)&&(!IsCtrlAlt)) { /* OK, we already got our keydown */
532
km->level=HIBYTE(GetKeyState(VK_SHIFT))?1:0;
533
km->keycode=msg->wParam;
536
return GDK_FILTER_REMOVE;
540
return GDK_FILTER_CONTINUE;
547
#include <gdk/gdkkeysyms.h>
548
static gint init_key(guint keyval){
549
GdkKeymapKey *kmk=NULL;
552
if (gdk_keymap_get_entries_for_keyval(NULL,keyval,&kmk,&n_keys)) {
559
#define InitKey(code,value) if (!code) { code=init_key(value); }
561
static gint glspi_keygrab(lua_State* L)
563
GeanyDocument*doc=NULL;
564
const gchar*prompt=NULL;
565
GdkKeymapKey km={0,0,0};
567
km.group=0; /* Note: we hijack this field to use as a flag for first keydown. */
569
InitKey(My_Shift_L, GDK_Shift_L);
570
InitKey(My_Shift_R, GDK_Shift_R);
571
InitKey(My_Control_L, GDK_Control_L);
572
InitKey(My_Control_R, GDK_Control_R);
573
InitKey(My_Alt_L, GDK_Alt_L);
574
InitKey(My_Alt_R, GDK_Alt_R);
575
if (lua_gettop(L)>0) {
576
if (!lua_isstring(L,1)) {return FAIL_STRING_ARG(1); }
577
prompt=lua_tostring(L,1);
578
doc=document_get_current();
581
if (prompt && doc && doc->is_valid ) {
582
gint fvl=scintilla_send_message(doc->editor->sci,SCI_GETFIRSTVISIBLELINE, 0,0);
583
gint pos=sci_get_position_from_line(doc->editor->sci, fvl+1);
584
scintilla_send_message(doc->editor->sci,SCI_CALLTIPSHOW,pos+3, (gint)prompt);
586
gdk_window_add_filter(main_widgets->window->window, keygrab_cb, &km);
588
while (gtk_events_pending()) {
589
if (km.group==2) { break; }
590
gtk_main_iteration();
592
if (km.group==2) { break; }
594
} while (km.group!=2);
596
gdk_window_remove_filter(main_widgets->window->window, keygrab_cb, &km);
597
if (prompt && doc && doc->is_valid) {
598
sci_send_command(doc->editor->sci, SCI_CALLTIPCANCEL);
600
km.group=0; /* reset the hijacked flag before passing to GDK */
601
lua_pushstring(L, gdk_keyval_name(gdk_keymap_lookup_key(NULL, &km)));
608
static const struct luaL_reg glspi_app_funcs[] = {
609
{"pluginver", glspi_pluginver},
610
{"appinfo", glspi_appinfo},
611
{"xsel", glspi_xsel},
612
{"signal", glspi_signal},
613
{"stat", glspi_stat},
614
{"basename", glspi_basename},
615
{"dirname", glspi_dirname},
616
{"fullpath", glspi_fullpath},
617
{"dirlist", glspi_dirlist},
618
{"wkdir", glspi_wkdir},
619
{"keycmd", glspi_keycmd},
620
{"launch", glspi_launch},
621
{"keygrab", glspi_keygrab},
625
void glspi_init_app_funcs(lua_State *L, gchar*script_dir) {
626
glspi_script_dir = script_dir;
627
luaL_register(L, NULL,glspi_app_funcs);