2001-02-23 07:48:14 +00:00
|
|
|
/*****************************************************************************
|
2003-11-16 10:55:07 +00:00
|
|
|
* $Id: main.cc,v 1.26 2003/11/16 10:55:07 andreas99 Exp $
|
2001-02-23 07:48:14 +00:00
|
|
|
* Copyright (C) 2000, Mishoo
|
|
|
|
* Author: Mihai Bazon Email: mishoo@fenrir.infoiasi.ro
|
|
|
|
*
|
|
|
|
* Distributed under the terms of the GNU General Public License. You are
|
|
|
|
* free to use/modify/distribute this program as long as you comply to the
|
|
|
|
* terms of the GNU General Public License, version 2 or above, at your
|
|
|
|
* option, and provided that this copyright notice remains intact.
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2011-04-20 17:38:44 +00:00
|
|
|
#include <X11/Xlib.h>
|
2001-02-23 07:48:14 +00:00
|
|
|
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <gdk/gdkkeysyms.h>
|
2011-04-20 17:38:44 +00:00
|
|
|
#include <gdk/gdkx.h>
|
2001-02-23 07:48:14 +00:00
|
|
|
|
|
|
|
#include <string>
|
2001-05-05 22:11:17 +00:00
|
|
|
#include <iostream>
|
2002-08-16 10:30:18 +00:00
|
|
|
#include <sstream>
|
2001-07-31 10:56:44 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <algorithm>
|
2002-08-16 10:30:18 +00:00
|
|
|
#include <iterator>
|
2003-11-16 10:55:07 +00:00
|
|
|
|
2001-02-23 07:48:14 +00:00
|
|
|
using namespace std;
|
|
|
|
|
2002-08-17 13:19:31 +00:00
|
|
|
#ifdef MTRACE
|
|
|
|
#include <mcheck.h>
|
|
|
|
#endif
|
|
|
|
|
2001-07-31 10:56:44 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
2002-06-05 19:39:18 +00:00
|
|
|
#include "gtkcompletionline.h"
|
|
|
|
#include "prefs.h"
|
2020-09-07 09:10:20 +00:00
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
W_TEXT_STYLE_NORMAL,
|
|
|
|
W_TEXT_STYLE_NOTFOUND,
|
|
|
|
W_TEXT_STYLE_NOTUNIQUE,
|
|
|
|
W_TEXT_STYLE_UNIQUE,
|
|
|
|
};
|
2002-06-05 19:39:18 +00:00
|
|
|
|
2020-09-08 13:27:06 +00:00
|
|
|
static void gmrun_exit (void);
|
|
|
|
|
2002-08-16 10:30:18 +00:00
|
|
|
// defined in gtkcompletionline.cc
|
|
|
|
int get_words(GtkCompletionLine *object, vector<string>& words);
|
|
|
|
string quote_string(const string& str);
|
2002-06-05 19:39:18 +00:00
|
|
|
|
2001-07-27 08:01:02 +00:00
|
|
|
struct gigi
|
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
GtkWidget *w1;
|
|
|
|
GtkWidget *w2;
|
2001-07-27 08:01:02 +00:00
|
|
|
};
|
|
|
|
|
2003-11-16 10:43:32 +00:00
|
|
|
/// BEGIN: TIMEOUT MANAGEMENT
|
|
|
|
|
2001-07-31 10:56:44 +00:00
|
|
|
static gint search_off_timeout(struct gigi *g);
|
|
|
|
|
2003-11-16 10:43:32 +00:00
|
|
|
static guint g_search_off_timeout_id = 0;
|
|
|
|
|
|
|
|
static void remove_search_off_timeout()
|
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
if (g_search_off_timeout_id) {
|
|
|
|
g_source_remove(g_search_off_timeout_id);
|
|
|
|
g_search_off_timeout_id = 0;
|
|
|
|
}
|
2003-11-16 10:43:32 +00:00
|
|
|
}
|
|
|
|
|
2020-01-14 17:17:09 +00:00
|
|
|
static void add_search_off_timeout(guint32 timeout, struct gigi *g, GSourceFunc func = 0)
|
2003-11-16 10:43:32 +00:00
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
remove_search_off_timeout();
|
|
|
|
if (!func)
|
|
|
|
func = GSourceFunc(search_off_timeout);
|
|
|
|
g_search_off_timeout_id = g_timeout_add(timeout, func, g);
|
2003-11-16 10:43:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// END: TIMEOUT MANAGEMENT
|
|
|
|
|
2020-01-15 11:44:21 +00:00
|
|
|
// https://unix.stackexchange.com/questions/457584/gtk3-change-text-color-in-a-label-raspberry-pi
|
2020-09-07 07:56:19 +00:00
|
|
|
static void set_info_text_color (GtkWidget *w, const char *text, int spec)
|
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
char *markup = NULL;
|
2020-09-07 07:56:19 +00:00
|
|
|
static const char * colors[] = {
|
|
|
|
"black", /* W_TEXT_STYLE_NORMAL */
|
|
|
|
"red", /* W_TEXT_STYLE_NOTFOUND */
|
|
|
|
"blue", /* W_TEXT_STYLE_NOTUNIQUE */
|
|
|
|
"green", /* W_TEXT_STYLE_UNIQUE */
|
|
|
|
};
|
|
|
|
markup = g_markup_printf_escaped ("<span foreground=\"%s\">%s</span>",
|
|
|
|
colors[spec], text);
|
2020-01-15 23:47:38 +00:00
|
|
|
if (markup) {
|
|
|
|
gtk_label_set_markup (GTK_LABEL (w), markup);
|
|
|
|
g_free(markup);
|
|
|
|
}
|
2001-02-23 07:48:14 +00:00
|
|
|
}
|
|
|
|
|
2002-08-16 10:30:18 +00:00
|
|
|
static void
|
2017-06-11 10:37:18 +00:00
|
|
|
run_the_command(const std::string& command, struct gigi* g)
|
2002-08-16 10:30:18 +00:00
|
|
|
{
|
2020-09-07 07:48:07 +00:00
|
|
|
const char * cmd = command.c_str();
|
|
|
|
GError * error = NULL;
|
|
|
|
gboolean success;
|
|
|
|
int argc;
|
|
|
|
char ** argv;
|
|
|
|
success = g_shell_parse_argv (cmd, &argc, &argv, &error);
|
|
|
|
if (!success) {
|
|
|
|
set_info_text_color (g->w1, error->message, W_TEXT_STYLE_NOTFOUND);
|
|
|
|
g_error_free (error);
|
|
|
|
add_search_off_timeout (3000, g);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
success = g_spawn_async (NULL, argv, NULL,
|
|
|
|
G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error);
|
|
|
|
if (argv) {
|
|
|
|
g_strfreev (argv);
|
|
|
|
}
|
|
|
|
if (success) {
|
2020-09-08 13:27:06 +00:00
|
|
|
gmrun_exit ();
|
2020-09-07 07:48:07 +00:00
|
|
|
} else {
|
|
|
|
set_info_text_color (g->w1, error->message, W_TEXT_STYLE_NOTFOUND);
|
|
|
|
g_error_free (error);
|
|
|
|
add_search_off_timeout (3000, g);
|
2020-01-15 23:47:38 +00:00
|
|
|
}
|
2002-08-16 10:30:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_ext_handler(GtkCompletionLine *cl, const char* ext, struct gigi* g)
|
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
string cmd;
|
|
|
|
if (ext && configuration.get_ext_handler(ext, cmd)) {
|
|
|
|
string str("Handler: ");
|
|
|
|
size_t pos = cmd.find_first_of(" \t");
|
|
|
|
if (pos == string::npos)
|
|
|
|
str += cmd;
|
|
|
|
else
|
|
|
|
str += cmd.substr(0, pos);
|
|
|
|
gtk_label_set_text(GTK_LABEL(g->w2), str.c_str());
|
|
|
|
gtk_widget_show(g->w2);
|
|
|
|
// gtk_timeout_add(1000, GSourceFunc(search_off_timeout), g);
|
|
|
|
} else {
|
|
|
|
search_off_timeout(g);
|
|
|
|
}
|
2002-08-16 10:30:18 +00:00
|
|
|
}
|
2001-05-16 14:39:31 +00:00
|
|
|
|
2018-01-28 16:06:29 +00:00
|
|
|
static void on_compline_runwithterm(GtkCompletionLine *cl, struct gigi* g)
|
2001-05-03 07:44:14 +00:00
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
string command(g_locale_from_utf8 (gtk_entry_get_text(GTK_ENTRY(cl)),
|
|
|
|
-1,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL));
|
|
|
|
string tmp;
|
|
|
|
string term;
|
|
|
|
|
|
|
|
string::size_type i;
|
|
|
|
i = command.find_first_not_of(" \t");
|
|
|
|
|
|
|
|
if (i != string::npos) {
|
|
|
|
if (!configuration.get_string("TermExec", term)) {
|
|
|
|
term = "xterm -e";
|
|
|
|
}
|
|
|
|
tmp = term;
|
|
|
|
tmp += " ";
|
|
|
|
tmp += command;
|
|
|
|
} else {
|
|
|
|
if (!configuration.get_string("Terminal", term)) {
|
|
|
|
tmp = "xterm";
|
|
|
|
} else {
|
|
|
|
tmp = term;
|
|
|
|
}
|
|
|
|
}
|
2001-05-05 22:11:17 +00:00
|
|
|
|
2001-05-06 11:39:24 +00:00
|
|
|
#ifdef DEBUG
|
2020-01-15 23:47:38 +00:00
|
|
|
cerr << tmp << endl;
|
2001-05-06 11:39:24 +00:00
|
|
|
#endif
|
|
|
|
|
2020-01-15 23:47:38 +00:00
|
|
|
cl->hist->append(command.c_str());
|
|
|
|
cl->hist->sync_the_file();
|
|
|
|
run_the_command(tmp.c_str(), g);
|
2001-05-03 07:44:14 +00:00
|
|
|
}
|
|
|
|
|
2018-01-28 16:06:29 +00:00
|
|
|
static gint search_off_timeout(struct gigi *g)
|
2001-07-17 15:57:19 +00:00
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
set_info_text_color(g->w1, "Run program:", W_TEXT_STYLE_NORMAL);
|
|
|
|
gtk_widget_hide(g->w2);
|
2020-08-24 12:24:34 +00:00
|
|
|
g_search_off_timeout_id = 0;
|
2020-01-15 23:47:38 +00:00
|
|
|
return FALSE;
|
2001-07-17 15:57:19 +00:00
|
|
|
}
|
|
|
|
|
2001-07-26 07:47:41 +00:00
|
|
|
static void
|
|
|
|
on_compline_unique(GtkCompletionLine *cl, struct gigi *g)
|
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
set_info_text_color(g->w1, "unique", W_TEXT_STYLE_UNIQUE);
|
|
|
|
add_search_off_timeout(1000, g);
|
2001-07-26 07:47:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_compline_notunique(GtkCompletionLine *cl, struct gigi *g)
|
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
set_info_text_color(g->w1, "not unique", W_TEXT_STYLE_NOTUNIQUE);
|
|
|
|
add_search_off_timeout(1000, g);
|
2001-07-26 07:47:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_compline_incomplete(GtkCompletionLine *cl, struct gigi *g)
|
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
set_info_text_color(g->w1, "not found", W_TEXT_STYLE_NOTFOUND);
|
|
|
|
add_search_off_timeout(1000, g);
|
2001-07-26 07:47:41 +00:00
|
|
|
}
|
|
|
|
|
2001-07-17 15:57:19 +00:00
|
|
|
static void
|
2001-07-18 07:24:11 +00:00
|
|
|
on_search_mode(GtkCompletionLine *cl, struct gigi *g)
|
2001-07-17 15:57:19 +00:00
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
if (cl->hist_search_mode != GCL_SEARCH_OFF) {
|
|
|
|
gtk_widget_show(g->w2);
|
|
|
|
gtk_label_set_text(GTK_LABEL(g->w1), "Search:");
|
|
|
|
gtk_label_set_text(GTK_LABEL(g->w2), cl->hist_word->c_str());
|
|
|
|
} else {
|
|
|
|
gtk_widget_hide(g->w2);
|
|
|
|
gtk_label_set_text(GTK_LABEL(g->w1), "Search OFF");
|
|
|
|
add_search_off_timeout(1000, g);
|
|
|
|
}
|
2001-07-17 15:57:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_search_letter(GtkCompletionLine *cl, GtkWidget *label)
|
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
gtk_label_set_text(GTK_LABEL(label), cl->hist_word->c_str());
|
2001-07-17 15:57:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2001-07-18 07:24:11 +00:00
|
|
|
search_fail_timeout(struct gigi *g)
|
2001-07-17 15:57:19 +00:00
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
set_info_text_color(g->w1, "Search:", W_TEXT_STYLE_NOTUNIQUE);
|
|
|
|
return FALSE;
|
2001-07-17 15:57:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-07-18 07:24:11 +00:00
|
|
|
on_search_not_found(GtkCompletionLine *cl, struct gigi *g)
|
2001-07-17 15:57:19 +00:00
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
set_info_text_color(g->w1, "Not Found!", W_TEXT_STYLE_NOTFOUND);
|
|
|
|
add_search_off_timeout(1000, g, GSourceFunc(search_fail_timeout));
|
2001-07-17 15:57:19 +00:00
|
|
|
}
|
|
|
|
|
2018-01-28 16:06:29 +00:00
|
|
|
static bool url_check(GtkCompletionLine *cl, struct gigi *g)
|
2001-07-27 08:01:02 +00:00
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
string text(g_locale_from_utf8 (gtk_entry_get_text(GTK_ENTRY(cl)),
|
|
|
|
-1,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL));
|
|
|
|
|
|
|
|
string::size_type i;
|
|
|
|
string::size_type sp;
|
|
|
|
|
|
|
|
sp = text.find_first_not_of(" \t");
|
|
|
|
if (sp == string::npos) return true;
|
|
|
|
text = text.substr(sp);
|
|
|
|
|
|
|
|
sp = text.find_first_of(" \t");
|
|
|
|
i = text.find(":");
|
|
|
|
|
|
|
|
if (i != string::npos && i < sp) {
|
|
|
|
// URL entered...
|
|
|
|
string url(text.substr(i + 1));
|
|
|
|
string url_type(text.substr(0, i));
|
|
|
|
string url_handler;
|
|
|
|
|
|
|
|
if (configuration.get_string(string("URL_") + url_type, url_handler)) {
|
|
|
|
string::size_type j = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
j = url_handler.find("%s", j);
|
|
|
|
if (j != string::npos) {
|
|
|
|
url_handler.replace(j, 2, url);
|
|
|
|
}
|
|
|
|
} while (j != string::npos);
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
do {
|
|
|
|
j = url_handler.find("%u", j);
|
|
|
|
if (j != string::npos) {
|
|
|
|
url_handler.replace(j, 2, text);
|
|
|
|
}
|
|
|
|
} while (j != string::npos);
|
|
|
|
|
|
|
|
cl->hist->append(text.c_str());
|
|
|
|
cl->hist->sync_the_file();
|
|
|
|
run_the_command(url_handler.c_str(), g);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
set_info_text_color(g->w1,
|
|
|
|
(string("No URL handler for [") + url_type + "]").c_str(),
|
|
|
|
W_TEXT_STYLE_NOTFOUND);
|
|
|
|
add_search_off_timeout(1000, g);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2001-07-27 08:01:02 +00:00
|
|
|
}
|
|
|
|
|
2018-01-28 16:06:29 +00:00
|
|
|
static bool ext_check(GtkCompletionLine *cl, struct gigi *g)
|
2002-08-16 10:30:18 +00:00
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
vector<string> words;
|
|
|
|
get_words(cl, words);
|
|
|
|
vector<string>::const_iterator
|
|
|
|
i = words.begin(),
|
|
|
|
i_end = words.end();
|
|
|
|
|
2018-01-25 11:25:40 +00:00
|
|
|
|
|
|
|
GRegex *regex = g_regex_new (" ", G_REGEX_OPTIMIZE, G_REGEX_MATCH_NOTEMPTY, NULL);
|
2020-01-15 23:47:38 +00:00
|
|
|
while (i != i_end) {
|
2018-01-25 11:25:40 +00:00
|
|
|
gchar *quoted = g_regex_replace_literal (
|
|
|
|
regex, (*i++).c_str(), -1, 0, "\\ ", G_REGEX_MATCH_NOTEMPTY, NULL);
|
|
|
|
const string w = quoted;
|
2020-01-15 23:47:38 +00:00
|
|
|
if (w[0] == '/') {
|
|
|
|
// absolute path, check for extension
|
|
|
|
size_t pos = w.rfind('.');
|
|
|
|
if (pos != string::npos) {
|
|
|
|
// we have extension
|
|
|
|
string ext = w.substr(pos + 1);
|
|
|
|
string ext_handler;
|
|
|
|
if (configuration.get_ext_handler(ext, ext_handler)) {
|
|
|
|
// we have the handler
|
|
|
|
pos = ext_handler.find("%s");
|
|
|
|
if (pos != string::npos)
|
|
|
|
ext_handler.replace(pos, 2, w);
|
|
|
|
cl->hist->append(w.c_str());
|
|
|
|
cl->hist->sync_the_file();
|
|
|
|
run_the_command(ext_handler.c_str(), g);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-01-25 11:25:40 +00:00
|
|
|
g_free(quoted);
|
2020-01-15 23:47:38 +00:00
|
|
|
// FIXME: for now we check only one entry
|
|
|
|
break;
|
|
|
|
}
|
2018-01-25 11:25:40 +00:00
|
|
|
g_regex_unref(regex);
|
2020-01-15 23:47:38 +00:00
|
|
|
|
|
|
|
return false;
|
2002-08-16 10:30:18 +00:00
|
|
|
}
|
|
|
|
|
2018-01-28 16:06:29 +00:00
|
|
|
static void on_compline_activated(GtkCompletionLine *cl, struct gigi *g)
|
2001-07-27 08:01:02 +00:00
|
|
|
{
|
2020-01-15 23:47:38 +00:00
|
|
|
if (url_check(cl, g))
|
|
|
|
return;
|
|
|
|
if (ext_check(cl, g))
|
|
|
|
return;
|
|
|
|
|
|
|
|
string command = g_locale_from_utf8 (gtk_entry_get_text(GTK_ENTRY(cl)),
|
|
|
|
-1,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
string::size_type i;
|
|
|
|
i = command.find_first_not_of(" \t");
|
|
|
|
|
|
|
|
if (i != string::npos) {
|
|
|
|
string::size_type j = command.find_first_of(" \t", i);
|
|
|
|
string progname = command.substr(i, j - i);
|
|
|
|
list<string> term_progs;
|
|
|
|
if (configuration.get_string_list("AlwaysInTerm", term_progs)) {
|
2001-10-19 08:59:40 +00:00
|
|
|
#ifdef DEBUG
|
2020-01-15 23:47:38 +00:00
|
|
|
cerr << "---" << std::endl;
|
|
|
|
std::copy(term_progs.begin(), term_progs.end(),
|
|
|
|
std::ostream_iterator<string>(cerr, "\n"));
|
|
|
|
cerr << "---" << std::endl;
|
2001-10-19 08:59:40 +00:00
|
|
|
#endif
|
2020-01-15 23:47:38 +00:00
|
|
|
list<string>::const_iterator w =
|
|
|
|
std::find(term_progs.begin(), term_progs.end(), progname);
|
|
|
|
if (w != term_progs.end()) {
|
|
|
|
on_compline_runwithterm(cl, g);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cl->hist->append(command.c_str());
|
|
|
|
cl->hist->sync_the_file();
|
|
|
|
run_the_command(command, g);
|
|
|
|
}
|
2001-07-27 08:01:02 +00:00
|
|
|
}
|
|
|
|
|
2020-09-08 13:27:06 +00:00
|
|
|
// =============================================================
|
|
|
|
// MAIN
|
|
|
|
|
|
|
|
void gmrun_exit(void)
|
|
|
|
{
|
|
|
|
gtk_main_quit ();
|
|
|
|
}
|
2011-04-20 17:38:44 +00:00
|
|
|
|
2001-02-23 07:48:14 +00:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
2020-09-07 03:45:49 +00:00
|
|
|
GtkWidget *dialog, * main_vbox;
|
2020-01-15 23:47:38 +00:00
|
|
|
GtkWidget *compline;
|
|
|
|
GtkWidget *label_search;
|
|
|
|
struct gigi g;
|
2011-04-20 17:38:44 +00:00
|
|
|
|
2002-08-17 13:19:31 +00:00
|
|
|
#ifdef MTRACE
|
2020-01-15 23:47:38 +00:00
|
|
|
mtrace();
|
2002-08-17 13:19:31 +00:00
|
|
|
#endif
|
|
|
|
|
2020-01-15 23:47:38 +00:00
|
|
|
gtk_init(&argc, &argv);
|
2001-07-17 15:57:19 +00:00
|
|
|
|
2020-01-18 11:53:04 +00:00
|
|
|
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
2020-01-15 23:47:38 +00:00
|
|
|
dialog = gtk_dialog_new();
|
2020-01-18 11:53:04 +00:00
|
|
|
gtk_window_set_transient_for( (GtkWindow*)dialog, (GtkWindow*)window );
|
2020-01-15 23:47:38 +00:00
|
|
|
gtk_widget_realize(dialog);
|
2020-09-07 03:45:49 +00:00
|
|
|
main_vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
|
2020-01-15 10:41:08 +00:00
|
|
|
|
2020-07-16 12:11:21 +00:00
|
|
|
// this removes the title bar..
|
|
|
|
GdkWindow *gwin = gtk_widget_get_window (GTK_WIDGET(dialog));
|
|
|
|
gdk_window_set_decorations (gwin, GDK_DECOR_BORDER);
|
2020-01-15 23:47:38 +00:00
|
|
|
|
2020-07-16 12:11:21 +00:00
|
|
|
gtk_widget_set_name (GTK_WIDGET (dialog), "gmrun");
|
|
|
|
gtk_window_set_title (GTK_WINDOW(window), "A simple launcher with completion");
|
2020-07-16 11:21:35 +00:00
|
|
|
|
2020-01-15 23:47:38 +00:00
|
|
|
gtk_container_set_border_width(GTK_CONTAINER(dialog), 4);
|
2020-09-07 04:14:20 +00:00
|
|
|
g_signal_connect(G_OBJECT(dialog), "destroy",
|
2020-09-08 13:27:06 +00:00
|
|
|
G_CALLBACK(gmrun_exit), NULL);
|
2020-01-15 23:47:38 +00:00
|
|
|
|
2020-08-24 11:27:26 +00:00
|
|
|
GtkWidget *hhbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
|
2020-09-07 03:45:49 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox), hhbox, FALSE, FALSE, 0);
|
2020-01-15 23:47:38 +00:00
|
|
|
|
|
|
|
GtkWidget *label = gtk_label_new("Run program:");
|
2020-09-07 03:45:49 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX(hhbox), label, FALSE, FALSE, 10);
|
2020-09-07 10:46:51 +00:00
|
|
|
gtkcompat_widget_set_halign_left (GTK_WIDGET (label));
|
2020-01-15 23:47:38 +00:00
|
|
|
|
|
|
|
label_search = gtk_label_new("");
|
2020-09-07 10:46:51 +00:00
|
|
|
gtk_box_pack_end (GTK_BOX (hhbox), label_search, TRUE, TRUE, 10);
|
|
|
|
gtkcompat_widget_set_halign_right (GTK_WIDGET (label_search));
|
2020-01-15 23:47:38 +00:00
|
|
|
|
|
|
|
compline = gtk_completion_line_new();
|
2020-09-07 03:45:49 +00:00
|
|
|
gtk_widget_set_name (compline, "gmrun_compline");
|
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox), compline, TRUE, TRUE, 0);
|
|
|
|
|
2020-01-15 23:47:38 +00:00
|
|
|
int prefs_width;
|
|
|
|
if (!configuration.get_int("Width", prefs_width))
|
|
|
|
prefs_width = 500;
|
|
|
|
|
|
|
|
// don't show files starting with "." by default
|
|
|
|
if (!configuration.get_int("ShowDotFiles", GTK_COMPLETION_LINE(compline)->show_dot_files))
|
|
|
|
GTK_COMPLETION_LINE(compline)->show_dot_files = 0;
|
|
|
|
{
|
|
|
|
int tmp;
|
|
|
|
if (configuration.get_int("TabTimeout", tmp))
|
|
|
|
((GtkCompletionLine*)compline)->tabtimeout = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
g.w1 = label;
|
|
|
|
g.w2 = label_search;
|
|
|
|
|
|
|
|
gtk_widget_set_size_request(compline, prefs_width, -1);
|
2020-09-07 04:14:20 +00:00
|
|
|
g_signal_connect(G_OBJECT(compline), "cancel",
|
2020-09-08 13:27:06 +00:00
|
|
|
G_CALLBACK(gmrun_exit), NULL);
|
2020-09-07 04:14:20 +00:00
|
|
|
g_signal_connect(G_OBJECT(compline), "activate",
|
2020-01-15 23:47:38 +00:00
|
|
|
G_CALLBACK(on_compline_activated), &g);
|
2020-09-07 04:14:20 +00:00
|
|
|
g_signal_connect(G_OBJECT(compline), "runwithterm",
|
2020-01-15 23:47:38 +00:00
|
|
|
G_CALLBACK(on_compline_runwithterm), &g);
|
|
|
|
|
2020-09-07 04:14:20 +00:00
|
|
|
g_signal_connect(G_OBJECT(compline), "unique",
|
2020-01-15 23:47:38 +00:00
|
|
|
G_CALLBACK(on_compline_unique), &g);
|
2020-09-07 04:14:20 +00:00
|
|
|
g_signal_connect(G_OBJECT(compline), "notunique",
|
2020-01-15 23:47:38 +00:00
|
|
|
G_CALLBACK(on_compline_notunique), &g);
|
2020-09-07 04:14:20 +00:00
|
|
|
g_signal_connect(G_OBJECT(compline), "incomplete",
|
2020-01-15 23:47:38 +00:00
|
|
|
G_CALLBACK(on_compline_incomplete), &g);
|
|
|
|
|
2020-09-07 04:14:20 +00:00
|
|
|
g_signal_connect(G_OBJECT(compline), "search_mode",
|
2020-01-15 23:47:38 +00:00
|
|
|
G_CALLBACK(on_search_mode), &g);
|
2020-09-07 04:14:20 +00:00
|
|
|
g_signal_connect(G_OBJECT(compline), "search_not_found",
|
2020-01-15 23:47:38 +00:00
|
|
|
G_CALLBACK(on_search_not_found), &g);
|
2020-09-07 04:14:20 +00:00
|
|
|
g_signal_connect(G_OBJECT(compline), "search_letter",
|
2020-01-15 23:47:38 +00:00
|
|
|
G_CALLBACK(on_search_letter), label_search);
|
|
|
|
|
2020-09-07 04:14:20 +00:00
|
|
|
g_signal_connect(G_OBJECT(compline), "ext_handler",
|
2020-01-15 23:47:38 +00:00
|
|
|
G_CALLBACK(on_ext_handler), &g);
|
|
|
|
|
|
|
|
int shows_last_history_item;
|
|
|
|
if (!configuration.get_int("ShowLast", shows_last_history_item)) {
|
|
|
|
shows_last_history_item = 0;
|
|
|
|
}
|
|
|
|
if (shows_last_history_item) {
|
|
|
|
gtk_completion_line_last_history_item(GTK_COMPLETION_LINE(compline));
|
|
|
|
}
|
|
|
|
|
|
|
|
int prefs_top = 80;
|
|
|
|
int prefs_left = 100;
|
|
|
|
configuration.get_int("Top", prefs_top);
|
|
|
|
configuration.get_int("Left", prefs_left);
|
|
|
|
|
2020-07-17 05:42:11 +00:00
|
|
|
// --geometry / parse commandline options
|
|
|
|
char *geometry_str = NULL;
|
|
|
|
GError *error = NULL;
|
2020-08-24 11:27:09 +00:00
|
|
|
GOptionContext *context = NULL;
|
2020-07-17 05:42:11 +00:00
|
|
|
static GOptionEntry entries[] =
|
|
|
|
{
|
|
|
|
{ "geometry", 'g', 0, G_OPTION_ARG_STRING, &geometry_str, "This option specifies the initial size and location of the window.", NULL },
|
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
context = g_option_context_new (NULL);
|
|
|
|
g_option_context_add_main_entries (context, entries, NULL);
|
|
|
|
g_option_context_add_group (context, gtk_get_option_group (TRUE));
|
|
|
|
if (!g_option_context_parse (context, &argc, &argv, &error))
|
|
|
|
{
|
|
|
|
g_print ("option parsing failed: %s\n", error->message);
|
2020-08-24 11:27:09 +00:00
|
|
|
if (context) g_option_context_free (context);
|
|
|
|
if (error) g_error_free (error);
|
|
|
|
if (geometry_str) g_free (geometry_str);
|
2020-07-17 05:42:11 +00:00
|
|
|
exit (1);
|
|
|
|
}
|
2020-08-24 11:27:09 +00:00
|
|
|
if (context) g_option_context_free (context);
|
|
|
|
if (error) g_error_free (error);
|
2020-07-17 05:42:11 +00:00
|
|
|
// --
|
|
|
|
|
|
|
|
if (!geometry_str) {
|
|
|
|
gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ALWAYS);
|
|
|
|
} else {
|
|
|
|
// --geometry WxH+X+Y
|
|
|
|
// width x height + posX + posY
|
|
|
|
gint64 width, height, posX, posY;
|
|
|
|
char *Wstr, *Hstr, *Xstr, *Ystr;
|
|
|
|
Wstr = Hstr = Xstr = Ystr = NULL;
|
|
|
|
|
|
|
|
Xstr = strchr (geometry_str, '+');
|
|
|
|
if (Xstr) { // +posX+posY
|
|
|
|
*Xstr = 0;
|
|
|
|
Xstr++; // posX+posY
|
|
|
|
Ystr = strchr (Xstr, '+');
|
|
|
|
if (Ystr) { // +posY
|
|
|
|
*Ystr = 0;
|
|
|
|
Ystr++; // posY
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Xstr && Ystr && *Xstr && *Ystr) {
|
|
|
|
posX = strtoll (Xstr, NULL, 0);
|
|
|
|
posY = strtoll (Ystr, NULL, 0);
|
|
|
|
///fprintf (stderr, "x: %" G_GINT64_FORMAT "\ny: %" G_GINT64_FORMAT "\n", posX, posY);
|
|
|
|
gtk_window_move (GTK_WINDOW (dialog), posX, posY);
|
|
|
|
}
|
|
|
|
|
|
|
|
Hstr = strchr (geometry_str, 'x');
|
|
|
|
if (Hstr) { // WxH
|
|
|
|
*Hstr = 0;
|
|
|
|
Hstr++; // H
|
|
|
|
Wstr = geometry_str;
|
|
|
|
width = strtoll (Wstr, NULL, 0);
|
|
|
|
height = strtoll (Hstr, NULL, 0);
|
|
|
|
///fprintf (stderr, "w: %" G_GINT64_FORMAT "\nh: %" G_GINT64_FORMAT "\n", width, height);
|
|
|
|
gtk_window_set_default_size (GTK_WINDOW (dialog), width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (geometry_str);
|
|
|
|
}
|
2020-09-07 09:07:54 +00:00
|
|
|
// end of --geometry
|
|
|
|
|
|
|
|
// window icon
|
|
|
|
GtkIconTheme * theme = gtk_icon_theme_get_default ();
|
2020-09-08 05:13:51 +00:00
|
|
|
GdkPixbuf * icon = gtk_icon_theme_load_icon (theme, "gmrun", 48, GTK_ICON_LOOKUP_USE_BUILTIN, &error);
|
2020-09-07 09:07:54 +00:00
|
|
|
if (error) {
|
|
|
|
g_object_set (dialog, "icon-name", "gtk-execute", NULL);
|
|
|
|
g_error_free (error);
|
|
|
|
} else {
|
|
|
|
gtk_window_set_icon (GTK_WINDOW (dialog), icon);
|
|
|
|
g_object_unref (icon);
|
|
|
|
}
|
2020-01-15 23:47:38 +00:00
|
|
|
|
2020-09-07 03:46:29 +00:00
|
|
|
gtk_widget_show_all (dialog);
|
2020-01-15 23:47:38 +00:00
|
|
|
|
|
|
|
gtk_window_set_focus(GTK_WINDOW(dialog), compline);
|
|
|
|
|
|
|
|
gtk_main();
|
2001-02-23 07:48:14 +00:00
|
|
|
}
|
2003-11-16 10:43:32 +00:00
|
|
|
|