/*
* GTK ASTerisk MANager
* Copyright (C) 2002, Digium
*
* Written by Mark Spencer <markster@digium.com>
*
* All Rights Reserved
*
* Distributed under GNU GPL
*
* GTK specific GUI routine implementation
*/
#ifndef _WIN32
#else
#include <winsock.h>
#include "win32dep.h"
#define _WINSOCKAPI_
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <gtk/gtk.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <db.h>
#include <math.h>
#include <time.h>
#include "gtklink.h"
#include "gastman.h"
#include "art/phone.xpm"
#include "art/phone2.xpm"
#include "art/red_on.xpm"
#include "art/red_off.xpm"
#include "art/green_on.xpm"
#include "art/green_off.xpm"
#include "art/inkwell.xpm"
#include "art/tinyphone.xpm"
#ifdef NO_PIXBUF
#include "art/tinycaller.xpm"
#else
#include <gdk-pixbuf/gdk-pixbuf.h>
#endif
#ifndef _WIN32
#define ICON_PATH "/usr/X11R6/share/gastman/icons"
#else
#define ICON_PATH_SIZE 256
static char icon_path[ICON_PATH_SIZE];
#endif
static GtkWidget *window;
static GtkWidget *dialog;
static GtkWidget *canvas;
static GtkWidget *callmenu;
static GtkWidget *calltitle;
static GtkWidget *extenmenu;
static GtkWidget *extentitle;
static GtkWidget *tabs;
static GtkWidget *extenlist;
static GtkWidget *calllist;
static GtkWidget *qlist;
static GtkWidget *cmdtextbox;
static GtkWidget *cmdentry;
static GdkFont *clifont;
static GtkTooltips *tips;
#define CVAL(x) ((x * (65532/256)))
static GdkColor colors[] = {
{red: CVAL(190), green: CVAL(196), blue: CVAL(209) }, /* Gray */
{red: CVAL(255), green: CVAL(253), blue: CVAL(219) }, /* Yellow */
{red: CVAL(229), green: CVAL(252), blue: CVAL(201) }, /* Green */
{red: CVAL(251), green: CVAL(181), blue: CVAL(255) }, /* Magenta */
};
static int choice = -1;
static int remember = 0;
static int fdio = -1;
static int fdfd = -1;
static int usegreen = 1;
static GtkWidget *ew; /* Button for the "Don't ask again" */
static char *yesno[2] = { "Yes", "No" };
static char *ok[1] = { "OK" };
static char *okcancel[2] = { "OK", "Cancel" };
static GtkTargetEntry target_entry = { "internal" };
static int format = 0;
static char *formats[] =
{
"tiny",
"small",
"medium",
"big",
};
struct gui_object {
int type;
char name[80];
char icon[80];
char ident[80];
char text[256];
GtkWidget *widget;
GtkWidget *pixmap;
GtkWidget *label;
GtkWidget *labelw;
GdkPixmap *pm;
GdkBitmap *bm;
GtkWidget *led;
void *pvt;
int size;
int onoff;
struct gui_object *next;
} *objects = NULL;
struct gui_queue {
int type;
char name[80];
char queue[80];
char icon[80];
char ident[80];
char text[256];
time_t offset;
time_t base;
int position;
GtkWidget *pixmap;
GdkPixmap *pm;
GdkBitmap *bm;
void *pvt;
int size;
int onoff;
struct gui_queue *next;
} *queues = NULL;
struct gui_link {
struct gui_object *obj1;
struct gui_object *obj2;
GtkWidget *widget;
struct gui_link *next;
} *links = NULL;
/* In some flavours of Windows we can not reliably get a home dir */
char* gui_get_home_dir(void)
{
/* g_get_home_dir works for Win NT,2000 and *nix */
if(g_get_home_dir())
return (char*)g_get_home_dir();
else
#ifndef _WIN32
return "/etc";
#else
return "C:";
#endif
}
/* WIN32 - icons should be in install dir */
char* gui_get_icon_path(void)
{
#ifdef _WIN32
_getcwd(icon_path, ICON_PATH_SIZE);
if((strlen(icon_path) + strlen(G_DIR_SEPARATOR_S "icons")) < ICON_PATH_SIZE) {
strcat(icon_path, G_DIR_SEPARATOR_S "icons");
return icon_path;
}
else
return NULL;
#else
return ICON_PATH;
#endif
}
static void gui_minirun(void)
{
while(g_main_iteration(FALSE));
}
static void fix_icon(GdkWindow *w)
{
GdkPixmap *gdk_pixmap;
GdkBitmap *gdk_pixmap_mask;
gdk_pixmap = gdk_pixmap_create_from_xpm_d(w, &gdk_pixmap_mask, NULL, tinyphone_xpm);
gdk_window_set_icon(w, NULL, gdk_pixmap, gdk_pixmap_mask);
}
static int make_pixmap_from_object(struct gui_object *object)
{
char fn[256];
snprintf(fn, sizeof(fn), "%s" G_DIR_SEPARATOR_S "%s-%s.xpm", gui_get_icon_path(), object->icon, formats[format + object->size]);
object->pm = gdk_pixmap_create_from_xpm(window->window, &object->bm, NULL, fn);
object->pixmap = gtk_pixmap_new(object->pm, object->bm);
gdk_pixmap_unref(object->pm);
gdk_bitmap_unref(object->bm);
return 0;
}
static GtkWidget *make_pixmap_from_file(GtkWidget *window, const char *icon, int size)
{
char fn[256];
GdkPixmap *pm;
GdkBitmap *bm;
GtkWidget *pixmap;
snprintf(fn, sizeof(fn), "%s" G_DIR_SEPARATOR_S "%s-%s.xpm", gui_get_icon_path(), icon, formats[size]);
pm = gdk_pixmap_create_from_xpm(window->window, &bm, NULL, fn);
pixmap = gtk_pixmap_new(pm, bm);
gdk_pixmap_unref(pm);
gdk_bitmap_unref(bm);
return pixmap;
}
static GtkWidget *make_pixmap_from_data(GtkWidget *window, char **data)
{
GdkPixmap *pm;
GdkBitmap *bm;
GtkWidget *w;
pm = gdk_pixmap_create_from_xpm_d(window->window, &bm, NULL, data);
w = gtk_pixmap_new(pm, bm);
gdk_pixmap_unref(pm);
gdk_bitmap_unref(bm);
gtk_widget_show(w);
return w;
}
static struct gui_object *current = NULL;
static struct gui_queue *qcurrent = NULL;
static int xof, yof, origx, origy;
static DB *db;
int gui_object_location(struct gui_object *obj, int *x, int *y)
{
if (obj && obj->widget) {
*x = obj->widget->allocation.x;
*y = obj->widget->allocation.y;
return 0;
} else
return -1;
}
static char *loc_file(void)
{
static char fn[256];
snprintf(fn, sizeof(fn), "%s" G_DIR_SEPARATOR_S ".gastman", gui_get_home_dir());
#ifndef _WIN32
mkdir(fn, 0777);
#else
_mkdir(fn);
#endif
if (gui_get_home_dir()) {
snprintf(fn, sizeof(fn), "%s" G_DIR_SEPARATOR_S ".gastman"
G_DIR_SEPARATOR_S "locations", gui_get_home_dir());
return fn;
}
return NULL;
}
static void resize_canvas(void)
{
int maxx=0, maxy=0, x, y;
struct gui_object *cur;
cur = objects;
while(cur) {
x = cur->widget->allocation.x + cur->widget->allocation.width;
if (x > maxx)
maxx = x;
y = cur->widget->allocation.y + cur->widget->allocation.width;
if (y > maxy)
maxy = y;
cur = cur->next;
}
gtk_layout_set_size(GTK_LAYOUT(canvas), maxx, maxy);
}
#if 0
void gtk_widget_modify_bg(GtkWidget *w, GtkStateType state, GdkColor *color)
{
GtkStyle *s;
s = gtk_style_copy(gtk_widget_get_style(w));
if (s) {
gtk_widget_set_style(w, s);
s->bg[state].red = color->red;
s->bg[state].green = color->green;
s->bg[state].blue = color->blue;
gdk_color_alloc(gtk_widget_get_colormap(w), &s->bg[state]);
}
}
#endif
void gui_object_set_led(struct gui_object *obj, int on)
{
GtkWidget *w, *old;
int x,y;
if (obj->led && (obj->onoff != on)) {
gui_minirun();
if (on)
w = make_pixmap_from_data(canvas, usegreen ? green_on : red_on);
else
w = make_pixmap_from_data(canvas, usegreen ? green_off : red_off);
old = obj->led;
x = obj->widget->allocation.x - 20;
y = obj->widget->allocation.y;
gtk_widget_destroy(old);
obj->led = w;
gtk_layout_put(GTK_LAYOUT(canvas), obj->led, x, y);
obj->onoff = on;
}
}
int gui_link(struct gui_object *obj1, struct gui_object *obj2)
{
struct gui_link *cur;
/* See if the link is there already */
cur = links;
while(cur) {
if (((cur->obj1 == obj1) && (cur->obj2 == obj2)) ||
((cur->obj1 == obj2) && (cur->obj2 == obj1)))
break;
cur = cur->next;
}
if (!cur) {
cur = g_new0(struct gui_link, 1);
cur->widget = gtk_link_new();
cur->obj1 = obj1;
cur->obj2 = obj2;
gtk_widget_show(cur->widget);
gtk_layout_put(GTK_LAYOUT(canvas), cur->widget, 0, 0);
cur->next = links;
links = cur;
}
gtk_link_set_coords(GTK_LINK(cur->widget),
obj1->widget->allocation.x + obj1->widget->allocation.width/2,
obj1->widget->allocation.y + obj1->widget->allocation.height/2,
obj2->widget->allocation.x + obj2->widget->allocation.width/2,
obj2->widget->allocation.y + obj2->widget->allocation.height/2);
return 0;
}
int gui_unlink(struct gui_object *obj1, struct gui_object *obj2)
{
struct gui_link *cur, *prev, *curn;
/* See if the link is there already */
cur = links;
prev = NULL;
while(cur) {
curn = cur->next;
if (((cur->obj1 == obj1) && (!obj2 || (cur->obj2 == obj2))) ||
((!obj2 || (cur->obj1 == obj2)) && (cur->obj2 == obj1))) {
if (prev)
prev->next = cur->next;
else
links = cur->next;
gtk_widget_destroy(cur->widget);
free(cur);
} else
prev = cur;
cur = curn;
}
return 0;
}
static int gui_update_links(struct gui_object *obj1)
{
struct gui_link *cur;
/* See if the link is there already */
cur = links;
while(cur) {
if ((cur->obj1 == obj1) || (cur->obj2 == obj1)) {
gtk_link_set_coords(GTK_LINK(cur->widget),
cur->obj1->widget->allocation.x + cur->obj1->widget->allocation.width/2,
cur->obj1->widget->allocation.y + cur->obj1->widget->allocation.height/2,
cur->obj2->widget->allocation.x + cur->obj2->widget->allocation.width/2,
cur->obj2->widget->allocation.y + cur->obj2->widget->allocation.height/2);
}
cur = cur->next;
}
return 0;
}
int gui_object_move(struct gui_object *obj, int newx, int newy)
{
if (newx < 0) newx = 0;
if (newy < 0) newy = 0;
gtk_layout_move(GTK_LAYOUT(canvas), obj->labelw, newx +
obj->widget->allocation.width - obj->labelw->allocation.width, newy - 30);
gtk_layout_move(GTK_LAYOUT(canvas), obj->widget, newx, newy);
if (obj->led)
gtk_layout_move(GTK_LAYOUT(canvas), obj->led, newx - 20, newy);
gui_minirun();
resize_canvas();
gui_update_links(obj);
return 0;
}
static void redirect_channel(gpointer callback_data, guint callback_action, GtkWidget *widget)
{
if (current)
gastman_redirect(current->pvt);
}
static void hangup_channel(gpointer callback_data, guint callback_action, GtkWidget *widget)
{
if (current)
gastman_hangup(current->pvt);
}
static void move_object_near(struct gui_object *obj, struct gui_object *cur, int *origx, int *origy)
{
int cx, cy, crad, orad, rad;
int xdiff, ydiff;
float hlen;
/* Change where we're going to return the object so that it stays
reasonably close to where we dropped it */
cx = cur->widget->allocation.x + cur->widget->allocation.width/2;
cy = cur->widget->allocation.y + cur->widget->allocation.height/2;
crad = cur->widget->allocation.width/2;
if (crad < cur->widget->allocation.height/2)
crad = cur->widget->allocation.height/2;
orad = obj->widget->allocation.width/2;
if (orad < obj->widget->allocation.height)
orad = obj->widget->allocation.height/2;
rad = orad + crad + 40;
/* Okay, we found the center of both object and their radius. Now
calculate the new position based on the old */
xdiff = cx - *origx;
ydiff = cy - *origy;
hlen = sqrt(((float)(xdiff*xdiff)) + ((float)(ydiff*ydiff)));
xdiff *= (((float)rad) / hlen);
ydiff *= (((float)rad) / hlen);
*origx = cx - xdiff;
*origy = cy - ydiff;
}
void gui_move_near(struct gui_object *dst, struct gui_object *src)
{
int x,y;
gtk_layout_freeze(GTK_LAYOUT(canvas));
x = src->widget->allocation.x;
y = src->widget->allocation.y;
move_object_near(src, dst, &x, &y);
gui_object_move(src, x, y);
gtk_layout_thaw(GTK_LAYOUT(canvas));
}
struct gui_object *over_location(struct gui_object *obj, int x, int y)
{
struct gui_object *cur;
cur = objects;
while(cur) {
if ((cur != obj) &&
(cur->widget->allocation.x < x) &&
(cur->widget->allocation.x + cur->widget->allocation.width > x) &&
(cur->widget->allocation.y < y) &&
(cur->widget->allocation.y + cur->widget->allocation.height > y)) {
return cur;
}
cur = cur->next;
}
return NULL;
}
struct gui_object *over_object(struct gui_object *obj)
{
int x,y;
x = obj->widget->allocation.x + xof;
y = obj->widget->allocation.y + yof;
return over_location(obj, x, y);
}
static void check_drop(struct gui_object *obj)
{
int res;
struct gui_object *cur;
if ((cur = over_object(obj))) {
res = gastman_pre_drag_drop(obj->pvt, cur->pvt);
if (res > 0)
move_object_near(obj, cur, &origx, &origy);
/* Return the object to its original position */
gtk_layout_freeze(GTK_LAYOUT(canvas));
gui_object_move(obj, origx, origy);
gtk_layout_thaw(GTK_LAYOUT(canvas));
if (res > -1)
gastman_drag_drop(obj->pvt, cur->pvt);
}
}
static int bbutton;
static int btime;
int gui_show_chan_menu(void)
{
char tmp[256];
snprintf(tmp, sizeof(tmp), "%s Ops", current->name);
gtk_label_set_text(GTK_LABEL(GTK_BIN(calltitle)->child), tmp);
xof = -9999;
gtk_menu_popup(GTK_MENU(callmenu), NULL, NULL, NULL, NULL, bbutton, btime);
return 0;
}
int gui_show_exten_menu(void)
{
char tmp[256];
snprintf(tmp, sizeof(tmp), "%s Ops", current->name);
gtk_label_set_text(GTK_LABEL(GTK_BIN(extentitle)->child), tmp);
xof = -9999;
gtk_menu_popup(GTK_MENU(extenmenu), NULL, NULL, NULL, NULL, bbutton, btime);
return 0;
}
static int object_event(GtkObject *thing, GdkEvent *event, struct gui_object *obj)
{
GdkEventButton *eb = (GdkEventButton*)event;
int tookit = FALSE;
int newx, newy;
switch(event->type) {
case GDK_2BUTTON_PRESS:
if (eb->button == 1) {
gastman_double_click(obj->pvt);
}
break;
case GDK_BUTTON_PRESS:
if (eb->button == 1) {
tookit = TRUE;
current = obj;
xof = eb->x;
yof = eb->y;
/* Correct for what we're clicking on in case it's not the widget */
xof -= (current->widget->allocation.x - GTK_WIDGET(thing)->allocation.x);
yof -= (current->widget->allocation.y - GTK_WIDGET(thing)->allocation.y);
origx = current->widget->allocation.x;
origy = current->widget->allocation.y;
gastman_object_select(obj->pvt);
} else if (eb->button == 3) {
current = obj;
bbutton = eb->button;
btime = eb->time;
gastman_right_click(obj->pvt);
tookit = TRUE;
}
break;
case GDK_MOTION_NOTIFY:
if (current && (current == obj) && (xof > -9999)) {
gtk_widget_get_pointer(canvas, &newx, &newy);
newx -= xof;
newy -= yof;
gtk_layout_freeze(GTK_LAYOUT(canvas));
gui_object_move(current, newx, newy);
gtk_layout_thaw(GTK_LAYOUT(canvas));
tookit = TRUE;
}
break;
case GDK_BUTTON_RELEASE:
if ((eb->button == 1) && current) {
tookit = TRUE;
check_drop(current);
current = NULL;
}
break;
default:
break;
}
if (thing && tookit)
gtk_signal_emit_stop_by_name(thing, "event");
return tookit;
}
static int gui_save_object(struct gui_object *cur)
{
char tmp[256];
DBT key, data;
int res;
if (db && cur) {
if (strlen(cur->ident)) {
snprintf(tmp, sizeof(tmp), "%d:%d", cur->widget->allocation.x, cur->widget->allocation.y);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = cur->ident;
key.size = strlen(cur->ident) + 1;
data.data = tmp;
data.size = strlen(tmp) + 1;
#ifdef __FreeBSD__
if ((res = db->put(db, &key, &data, 0)))
#else
if ((res = db->put(db, NULL, &key, &data, 0)))
#endif
fprintf(stderr, "Unable to save '%s' location\n", cur->ident);
}
}
return 0;
}
static int update_queue(char *queuename, int pos);
void gui_del_object(struct gui_object *obj)
{
struct gui_object *cur, *prev;
int row;
if (!obj)
return;
gui_unlink(obj, NULL);
if (obj == current)
current = NULL;
cur = objects;
prev = NULL;
while(cur) {
if (cur == obj) {
if (prev)
prev->next = obj->next;
else
objects = obj->next;
break;
}
prev = cur;
cur = cur->next;
}
gui_save_object(obj);
gtk_widget_destroy(obj->labelw);
gtk_widget_destroy(obj->widget);
if (obj->led)
gtk_widget_destroy(obj->led);
if ((row = gtk_clist_find_row_from_data(GTK_CLIST(calllist), obj)) > -1)
gtk_clist_remove(GTK_CLIST(calllist), row);
else if ((row = gtk_clist_find_row_from_data(GTK_CLIST(extenlist), obj)) > -1)
gtk_clist_remove(GTK_CLIST(extenlist), row);
free(obj);
}
void gui_del_queue(struct gui_queue *obj)
{
struct gui_queue *cur, *prev;
int row;
cur = queues;
prev = NULL;
while(cur) {
if (cur == obj) {
if (prev)
prev->next = obj->next;
else
queues = obj->next;
break;
}
prev = cur;
cur = cur->next;
}
if ((row = gtk_clist_find_row_from_data(GTK_CLIST(qlist), obj)) > -1)
gtk_clist_remove(GTK_CLIST(qlist), row);
update_queue(obj->queue, obj->position);
free(obj);
}
void gui_object_set_tooltip(struct gui_object *obj, char *tip)
{
if (!obj)
return;
gtk_tooltips_set_tip(tips, obj->widget, tip, NULL);
}
void gui_object_set_text(struct gui_object *obj, char *text)
{
if (!obj)
return;
gtk_label_set_text(GTK_LABEL(GTK_BIN(GTK_BIN(GTK_BIN(obj->labelw)->child)->child)->child), text);
}
struct gui_object * gui_add_object(char *name, char *text, char *icon, char *ident, void *pvt, int size, int withled, int type)
{
struct gui_object *obj;
GtkWidget *w, *w2;
GtkWidget *list = NULL;
GdkPixmap *pm = NULL;
GdkBitmap *bm = NULL;
char *l[10];
int x = 0, y = 0;
int res;
int row;
obj = g_new0(struct gui_object, 1);
if (!obj)
return NULL;
memset(&l, 0, sizeof(l));
obj->next = objects;
objects = obj;
strncpy(obj->name, name, sizeof(obj->name) - 1);
strncpy(obj->icon, icon, sizeof(obj->icon) - 1);
strncpy(obj->ident, ident, sizeof(obj->ident) - 1);
strncpy(obj->text, text, sizeof(obj->text) - 1);
obj->size = size;
make_pixmap_from_object(obj);
obj->label = gtk_label_new(text);
obj->widget = gtk_event_box_new();
obj->labelw = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(obj->labelw), GTK_SHADOW_ETCHED_OUT);
w = gtk_event_box_new();
w2 = gtk_event_box_new();
gtk_container_set_border_width(GTK_CONTAINER(obj->labelw), 10);
gtk_container_add(GTK_CONTAINER(obj->widget), obj->pixmap);
gtk_container_add(GTK_CONTAINER(w), obj->label);
gtk_container_add(GTK_CONTAINER(w2), w);
gtk_container_set_border_width(GTK_CONTAINER(w), 1);
gtk_container_add(GTK_CONTAINER(obj->labelw), w2);
gtk_widget_modify_bg(w2, GTK_STATE_NORMAL, &colors[type]);
gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &colors[type]);
gtk_widget_show_all(obj->widget);
gtk_widget_show_all(obj->labelw);
gtk_widget_shape_combine_mask(obj->widget, obj->bm, 0,0);
gtk_signal_connect(GTK_OBJECT(w2), "event", GTK_SIGNAL_FUNC(object_event), obj);
gtk_signal_connect(GTK_OBJECT(obj->widget), "event", GTK_SIGNAL_FUNC(object_event), obj);
obj->type = type;
obj->pvt = pvt;
if (withled) {
obj->led = make_pixmap_from_data(canvas, usegreen ? green_off : red_off);
gtk_widget_show_all(obj->led);
}
gtk_layout_freeze(GTK_LAYOUT(canvas));
gtk_layout_put(GTK_LAYOUT(canvas), obj->widget, 0, 0);
gtk_layout_put(GTK_LAYOUT(canvas), obj->labelw, 0, 0);
if (obj->led) {
gtk_layout_put(GTK_LAYOUT(canvas), obj->led, 0, 0);
gtk_widget_realize(obj->led);
}
l[0] = obj->text;
if (type == TYPE_CALL) {
list = calllist;
#ifdef NO_PIXBUF
pm = gdk_pixmap_create_from_xpm_d(window->window, &bm, NULL, tinycaller_xpm);
#endif
} else if (type == TYPE_EXTEN) {
list = extenlist;
#ifdef NO_PIXBUF
pm = gdk_pixmap_create_from_xpm_d(window->window, &bm, NULL, tinyphone_xpm);
#endif
}
if (list) {
#ifndef NO_PIXBUF
GdkPixbuf *pb = NULL;
GdkPixbuf *pb2;
char fn[256];
snprintf(fn, sizeof(fn), "%s" G_DIR_SEPARATOR_S "%s-%s.xpm", gui_get_icon_path(), obj->icon, formats[3]);
#if (GDK_PIXBUF_MAJOR > 1)
pb2 = gdk_pixbuf_new_from_file(fn, NULL);
#else
pb2 = gdk_pixbuf_new_from_file(fn);
#endif
if (pb2) {
pb = gdk_pixbuf_scale_simple(pb2, 20, 20, GDK_INTERP_BILINEAR);
gdk_pixbuf_unref(pb2);
} else
fprintf(stderr, "Unable to open %s\n", fn);
gdk_pixbuf_render_pixmap_and_mask(pb, &pm, &bm, 10);
gdk_pixbuf_unref(pb);
#endif
row = gtk_clist_prepend(GTK_CLIST(list), l);
gtk_clist_set_row_data(GTK_CLIST(list), row, obj);
gtk_clist_set_pixtext(GTK_CLIST(list), row, 0, obj->text, 2, pm, bm);
}
gtk_widget_realize(obj->widget);
gtk_widget_realize(obj->labelw);
if (db && strlen(obj->ident)) {
DBT key, data;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = obj->ident;
key.size = strlen(obj->ident) + 1;
#ifdef __FreeBSD__
if (!(res = db->get(db, &key, &data, 0))) {
#else
if (!(res = db->get(db, NULL, &key, &data, 0))) {
#endif
if (((char *)data.data)[data.size - 1] != '\0')
fprintf(stderr, "Not null terminated?!? (%s, %d)\n", (char *)data.data, data.size);
else if (sscanf((char *)data.data, "%d:%d", &x, &y) != 2)
fprintf(stderr, "Whoa, weird...\n");
else {
char old_ident[80];
get_old_ident(obj->pvt, old_ident, 80);
key.data = old_ident;
key.size = strlen(old_ident) + 1;
#ifdef __FreeBSD__
if (!(res = db->get(db, &key, &data, 0)))
#else
if (!(res = db->get(db, NULL, &key, &data, 0)))
#endif
sscanf((char *)data.data, "%d:%d", &x, &y);
}
}
}
if (!x && !y) {
/* Try up to 50 times to find a random position that isn't on anything */
int tries = 50;
do {
x = (rand() % (canvas->allocation.width - 150)) + 75;
y = (rand() % (canvas->allocation.height - 150)) + 75;
x -= obj->widget->allocation.width/2;
y -= obj->widget->allocation.height/2;
if (!over_location(obj, x, y) &&
!over_location(obj, x + obj->widget->allocation.width, y + obj->widget->allocation.height))
break;
} while (--tries);
}
gui_minirun();
gui_object_move(obj, x, y);
#if 0
printf("Added object to canvas\n");
#endif
gtk_layout_thaw(GTK_LAYOUT(canvas));
return obj;
}
struct gui_queue * gui_add_queue(char *name, char *qname, char *icon, void *pvt, int type)
{
struct gui_queue *obj;
GdkPixmap *pm = NULL;
GdkBitmap *bm = NULL;
GtkWidget *list;
char *l[10];
int row;
obj = g_new0(struct gui_queue, 1);
if (!obj)
return NULL;
#if 0
printf("Adding '%s' to queue '%s' to %p\n", name, qname, obj);
#endif
memset(&l, 0, sizeof(l));
obj->next = queues;
queues = obj;
if (name)
strncpy(obj->name, name, sizeof(obj->name) - 1);
if (icon)
strncpy(obj->icon, icon, sizeof(obj->icon) - 1);
strncpy(obj->queue, qname, sizeof(obj->queue) - 1);
obj->type = type;
obj->pvt = pvt;
l[0] = strlen(obj->name) ? "" : obj->queue;
l[2] = obj->name;
if ((type == TYPE_QUEUE) || (type == TYPE_QUEUENAME)) {
list = qlist;
#ifdef NO_PIXBUF
pm = gdk_pixmap_create_from_xpm_d(window->window, &bm, NULL, tinycaller_xpm);
#endif
}
if (list) {
#ifndef NO_PIXBUF
GdkPixbuf *pb = NULL;
GdkPixbuf *pb2=NULL;
char fn[256]="";
if (strlen(obj->icon)) {
snprintf(fn, sizeof(fn), "%s" G_DIR_SEPARATOR_S "%s-%s.xpm", gui_get_icon_path(), obj->icon, formats[3]);
#if (GDK_PIXBUF_MAJOR > 1)
pb2 = gdk_pixbuf_new_from_file(fn, NULL);
#else
pb2 = gdk_pixbuf_new_from_file(fn);
#endif
}
if (pb2) {
pb = gdk_pixbuf_scale_simple(pb2, 20, 20, GDK_INTERP_BILINEAR);
gdk_pixbuf_unref(pb2);
gdk_pixbuf_render_pixmap_and_mask(pb, &pm, &bm, 10);
gdk_pixbuf_unref(pb);
} else if (strlen(obj->icon))
fprintf(stderr, "Unable to open %s\n", fn);
#endif
row = gtk_clist_prepend(GTK_CLIST(list), l);
gtk_clist_set_row_data(GTK_CLIST(list), row, obj);
if (pm && bm)
gtk_clist_set_pixtext(GTK_CLIST(list), row, 2, obj->name, 2, pm, bm);
gtk_clist_sort(GTK_CLIST(qlist));
}
gui_minirun();
return obj;
}
static FILE *open_config_file(char *filename, char *mode)
{
char fn[256];
char *home = gui_get_home_dir();
snprintf(fn, sizeof(fn), "%s" G_DIR_SEPARATOR_S ".gastman", home);
#ifndef _WIN32
mkdir(fn, 0755);
#else
_mkdir(fn);
#endif
snprintf(fn, sizeof(fn), "%s" G_DIR_SEPARATOR_S ".gastman" G_DIR_SEPARATOR_S "%s", home, filename);
return fopen(fn, mode);
}
static int check_entity(char *entity)
{
FILE *f;
char buf[256];
int res = 0;
f = open_config_file("confirms.txt", "r");
while(f && !feof(f)) {
fgets(buf, sizeof(buf), f);
if (!feof(f) && strlen(buf)) {
/* Trim trailing \n */
buf[strlen(buf) -1] = '\0';
if (!strcmp(entity, buf)) {
res = 1;
break;
}
}
}
if (f) fclose(f);
return res;
}
static int add_entity(char *entity)
{
FILE *f;
f = open_config_file("confirms.txt", "a");
if (f) {
fprintf(f, "%s\n", entity);
fclose(f);
}
return 0;
}
int gui_init(int *argc, char **argv[])
{
char *fn = loc_file();
int res = 0;
if (fn) {
#ifdef __FreeBSD__
if (!(db = dbopen(fn, O_CREAT | O_RDWR, 0664, DB_BTREE, NULL))) {
fprintf(stderr, "Unable to open db\n");
#else
if (!(res = db_create(&db, NULL, 0))) {
#if (DB_VERSION_MAJOR > 4) || ((DB_VERSION_MAJOR > 3) && (DB_VERSION_MINOR > 0))
if ((res = db->open(db, NULL, fn,NULL, DB_BTREE, DB_CREATE, 0664)))
#else
if ((res = db->open(db, fn,NULL, DB_BTREE, DB_CREATE, 0664)))
#endif
fprintf(stderr, "Unable to open db: %s\n", db_strerror(res));
} else {
fprintf(stderr, "Unable to create db: %s\n", db_strerror(res));
db->close(db, 0);
db = NULL;
#endif
}
}
gtk_init(argc, argv);
srand(time(NULL));
return res;
}
void dialog_answer(GtkWidget *widget, gpointer data)
{
if (ew && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ew))) {
remember = 1;
}
gtk_widget_destroy(dialog);
dialog = NULL;
choice = (int)(long)data;
}
static GtkWidget *entry;
static GtkWidget *combo;
static char *outmsg;
static int outmsglen;
void entry_answer(GtkWidget *widget, gpointer data)
{
choice = (int)(long)data;
if (!choice) {
strncpy(outmsg, gtk_entry_get_text(GTK_ENTRY(entry)), outmsglen - 1);
} else
strcpy(outmsg, "");
gtk_widget_destroy(dialog);
dialog = NULL;
}
void combo_answer(GtkWidget *widget, gpointer data)
{
GtkCombo *combo2 = GTK_COMBO(combo);
choice = (int)(long)data;
if (!choice) {
char *extra;
strncpy(outmsg, gtk_entry_get_text(GTK_ENTRY(combo2->entry)), outmsglen - 1);
if ((extra = strstr(outmsg, " (")))
extra[0] = '\0';
} else
strcpy(outmsg, "");
gtk_widget_destroy(dialog);
dialog = NULL;
}
static char lastcmd[512];
void command_ready(GtkWidget *widget, gpointer data)
{
const char *s;
gtk_entry_set_editable(GTK_ENTRY(cmdentry), FALSE);
s = gtk_entry_get_text(GTK_ENTRY(cmdentry));
snprintf(lastcmd, sizeof(lastcmd), "-- %s --", s);
gastman_run_command(s);
gtk_entry_set_text(GTK_ENTRY(cmdentry), "");
gtk_entry_set_editable(GTK_ENTRY(cmdentry), TRUE);
}
int gui_get_user_input(char *title, char *msg, char *buf, int buflen)
{
GtkWidget *button;
GtkWidget *tw;
GtkWidget *vbox, *hbox;
GtkWidget *icon;
char rtext[256];
int x;
int choices = 2;
snprintf(rtext, sizeof(rtext),"GAstMan: %s", title);
dialog = gtk_dialog_new();
tw = gtk_label_new(msg);
gtk_window_set_title(GTK_WINDOW(dialog), rtext);
gtk_widget_realize(dialog);
fix_icon(dialog->window);
gtk_widget_show(tw);
vbox = gtk_vbox_new(FALSE, 0);
hbox = gtk_hbox_new(FALSE, 0);
icon = make_pixmap_from_data(dialog, inkwell_xpm);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), icon, FALSE, FALSE, 10);
gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 10);
gtk_box_pack_start(GTK_BOX(vbox), tw, TRUE, TRUE, 15);
gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 10);
entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 5);
gtk_signal_connect(GTK_OBJECT(entry), "activate", GTK_SIGNAL_FUNC(entry_answer), (gpointer)(long)0);
choice = -1;
for (x=0;x<choices;x++) {
button = gtk_button_new_with_label(okcancel[x]);
gtk_widget_set_usize(button, 80, 30);
gtk_widget_show(button);
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(entry_answer), (gpointer)(long)x);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 10);
}
gtk_widget_grab_focus(entry);
if (window)
gtk_widget_set_sensitive(window, FALSE);
outmsg = buf;
outmsglen = buflen;
gtk_window_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
gtk_widget_show_all(dialog);
/* Block as long as dialog is here */
while(dialog)
gtk_main_iteration_do(1);
if (window)
gtk_widget_set_sensitive(window, TRUE);
return choice;
}
int gui_get_hostname(char *buf, int buflen)
{
GtkWidget *button;
GtkWidget *tw;
GtkWidget *vbox, *hbox;
GtkWidget *icon;
GList *list = NULL;
char *rtext = "GAstman: Select hostname";
int x;
int choices = 2;
DIR *gastman_dir;
struct dirent *gastman_dirent;
static char fn[256];
snprintf(fn, sizeof(fn), "%s" G_DIR_SEPARATOR_S ".gastman", gui_get_home_dir());
gastman_dir = opendir(fn);
while (( gastman_dirent = readdir(gastman_dir) )) {
char *thedot;
if ( gastman_dirent->d_name[0] == '.' )
continue;
if (( thedot = strstr(gastman_dirent->d_name, ".extens") )) {
char *copy;
struct hostent *hostent;
thedot[0] = '\0';
if ((hostent = gethostbyname(gastman_dirent->d_name))) {
struct in_addr addr;
memcpy(&addr, hostent->h_addr_list[0], sizeof(addr));
if (strcmp(inet_ntoa(addr), gastman_dirent->d_name)) {
copy = alloca(strlen(gastman_dirent->d_name) + strlen(inet_ntoa(addr)) + 4);
if (copy) {
sprintf(copy, "%s (%s)", gastman_dirent->d_name, inet_ntoa(addr));
list = g_list_append(list, copy);
}
} else {
copy = alloca(strlen(gastman_dirent->d_name) + 1);
if (copy) {
strcpy(copy, gastman_dirent->d_name);
list = g_list_append(list, copy);
}
}
} else {
copy = alloca(strlen(gastman_dirent->d_name) + 1);
if (copy) {
strcpy(copy, gastman_dirent->d_name);
list = g_list_append(list, copy);
}
}
}
}
closedir(gastman_dir);
dialog = gtk_dialog_new();
tw = gtk_label_new("Select or enter the hostname you wish to connect to:");
gtk_window_set_title(GTK_WINDOW(dialog), rtext);
gtk_widget_realize(dialog);
fix_icon(dialog->window);
gtk_widget_show(tw);
vbox = gtk_vbox_new(FALSE, 0);
hbox = gtk_hbox_new(FALSE, 0);
icon = make_pixmap_from_data(dialog, inkwell_xpm);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), icon, FALSE, FALSE, 10);
gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 10);
gtk_box_pack_start(GTK_BOX(vbox), tw, TRUE, TRUE, 15);
gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 10);
combo = gtk_combo_new();
gtk_combo_set_case_sensitive(GTK_COMBO(combo), FALSE);
gtk_combo_set_value_in_list(GTK_COMBO(combo), FALSE, FALSE);
gtk_combo_set_use_arrows(GTK_COMBO(combo), TRUE);
gtk_combo_set_use_arrows_always(GTK_COMBO(combo), TRUE);
gtk_combo_set_popdown_strings(GTK_COMBO(combo), list);
gtk_box_pack_start(GTK_BOX(vbox), combo, FALSE, FALSE, 5);
/* gtk_signal_connect(GTK_OBJECT(GTK_COMBO(combo)), "activate", GTK_SIGNAL_FUNC(combo_answer), (gpointer)(long)0); */
choice = -1;
for (x=0;x<choices;x++) {
button = gtk_button_new_with_label(okcancel[x]);
gtk_widget_set_usize(button, 80, 30);
gtk_widget_show(button);
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(combo_answer), (gpointer)(long)x);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 10);
}
gtk_widget_grab_focus(combo);
if (window)
gtk_widget_set_sensitive(window, FALSE);
outmsg = buf;
outmsglen = buflen;
gtk_window_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
gtk_widget_show_all(dialog);
/* Block as long as dialog is here */
while(dialog)
gtk_main_iteration_do(1);
if (window)
gtk_widget_set_sensitive(window, TRUE);
/* Clean up associated memory */
g_list_free(list);
return choice;
}
int gui_ask_maybe(char *title, char *text, char *entity, int choices, int def, char *ctext[])
{
GtkWidget *button;
GtkWidget *tw;
GtkWidget *defw = NULL;
char rtext[256];
int x;
choice = -1;
remember = 0;
if (entity) {
if (check_entity(entity)) {
printf("Using default answer for '%s'\n", entity);
return def;
}
}
if (!choices) {
/* Reasonable defaults */
choices = 1;
ctext = ok;
}
snprintf(rtext, sizeof(rtext),"GAstMan: %s", title);
dialog = gtk_dialog_new();
gtk_widget_realize(dialog);
fix_icon(dialog->window);
tw = gtk_label_new(text);
gtk_window_set_title(GTK_WINDOW(dialog), rtext);
gtk_widget_show(tw);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), tw, TRUE, TRUE, 5);
gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 10);
if (entity) {
ew = gtk_check_button_new_with_label("Do not ask me again");
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), ew, TRUE, TRUE, 5);
} else
ew = NULL;
for (x=0;x<choices;x++) {
button = gtk_button_new_with_label(ctext[x]);
if (x == def)
defw = button;
gtk_widget_set_usize(button, 80, 30);
gtk_widget_show(button);
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dialog_answer), (gpointer)(long)x);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 10);
}
if (defw)
gtk_widget_grab_focus(defw);
if (window)
gtk_widget_set_sensitive(window, FALSE);
gtk_window_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
gtk_widget_show_all(dialog);
/* Block as long as dialog is here */
while(dialog)
gtk_main_iteration_do(1);
if (remember) {
if (!check_entity(entity))
add_entity(entity);
}
if (window)
gtk_widget_set_sensitive(window, TRUE);
return choice;
}
static GtkWidget *username;
static GtkWidget *password;
static char **ruser, **rpass;
void login_answer(GtkWidget *widget, gpointer data)
{
static char uname[256];
static char pword[256];
strncpy(uname, gtk_entry_get_text(GTK_ENTRY(username)), sizeof(uname) - 1);
strncpy(pword, gtk_entry_get_text(GTK_ENTRY(password)), sizeof(pword) - 1);
gtk_widget_destroy(dialog);
dialog = NULL;
choice = (int)(long)data;
*ruser = uname;
*rpass = pword;
}
int gui_login(char **user, char **pass, char *hostname)
{
GtkWidget *button;
GtkWidget *tw, *defw;
GtkWidget *table;
GtkWidget *icon;
char *ctext[] = { "Login", "Cancel" };
int choices = 2;
char rtext[256];
int x;
snprintf(rtext, sizeof(rtext),"GAstMan: %s login", hostname);
dialog = gtk_dialog_new();
gtk_widget_realize(dialog);
fix_icon(dialog->window);
table = gtk_table_new(3, 3, 0);
gtk_table_set_row_spacings(GTK_TABLE(table), 5);
gtk_table_set_col_spacing(GTK_TABLE(table), 0, 15);
gtk_table_set_col_spacing(GTK_TABLE(table), 1, 15);
icon = make_pixmap_from_data(dialog, phone_xpm);
gtk_table_attach_defaults(GTK_TABLE(table), icon, 0, 1, 0, 3);
tw = gtk_label_new("Host: ");
gtk_misc_set_alignment(GTK_MISC(tw), 0.0f, 0.5f);
gtk_widget_show(tw);
gtk_table_attach_defaults(GTK_TABLE(table), tw, 1, 2, 0, 1);
tw = gtk_label_new(hostname);
gtk_misc_set_alignment(GTK_MISC(tw), 0.0f, 0.5f);
gtk_widget_show(tw);
gtk_table_attach_defaults(GTK_TABLE(table), tw, 2, 3, 0, 1);
tw = gtk_label_new("Username: ");
gtk_misc_set_alignment(GTK_MISC(tw), 0.0f, 0.5f);
gtk_widget_show(tw);
gtk_table_attach_defaults(GTK_TABLE(table), tw, 1, 2, 1, 2);
defw = username = gtk_entry_new();
gtk_widget_show(username);
gtk_widget_set_usize(username, 80, 0);
gtk_table_attach_defaults(GTK_TABLE(table), username, 2, 3, 1, 2);
tw = gtk_label_new("Password: ");
gtk_misc_set_alignment(GTK_MISC(tw), 0.0f, 0.5f);
gtk_widget_show(tw);
gtk_table_attach_defaults(GTK_TABLE(table), tw, 1, 2, 2, 3);
password = gtk_entry_new();
gtk_widget_set_usize(password, 80, 0);
gtk_entry_set_visibility(GTK_ENTRY(password), FALSE);
gtk_widget_show(password);
gtk_table_attach_defaults(GTK_TABLE(table), password, 2, 3, 2, 3);
gtk_signal_connect_object(GTK_OBJECT(username), "activate", GTK_SIGNAL_FUNC(gtk_widget_grab_focus), GTK_OBJECT(password));
gtk_window_set_title(GTK_WINDOW(dialog), rtext);
gtk_widget_show(table);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 5);
gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 10);
for (x=0;x<choices;x++) {
button = gtk_button_new_with_label(ctext[x]);
if (!x)
gtk_signal_connect_object(GTK_OBJECT(password), "activate", GTK_SIGNAL_FUNC(gtk_widget_grab_focus), GTK_OBJECT(button));
gtk_widget_set_usize(button, 80, 30);
gtk_widget_show(button);
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(login_answer), (gpointer)(long)x);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 10);
}
if (defw)
gtk_widget_grab_focus(defw);
if (window)
gtk_widget_set_sensitive(window, FALSE);
gtk_window_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
gtk_widget_show_all(dialog);
ruser = user;
rpass = pass;
/* Block as long as dialog is here */
while(dialog)
gtk_main_iteration_do(1);
if (window)
gtk_widget_set_sensitive(window, TRUE);
return choice;
}
static GtkWidget *icon_widget_new(void)
{
DIR *dir;
struct dirent *de;
char search[256];
char tmp[256];
char *t;
GtkWidget *w;
GList *l = NULL;
/* Make them only take our stuff */
w = gtk_combo_new();
gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(w)->entry), FALSE);
snprintf(search, sizeof(search), "-%s.xpm", formats[format + 1]);
if ((dir = opendir(gui_get_icon_path()))) {
while((de = readdir(dir))) {
strncpy(tmp, de->d_name, sizeof(tmp) - 1);
if ((t = strstr(tmp, search))) {
if (t[strlen(search)] == '\0') {
*t = '\0';
/* Add this entry */
l = g_list_append(l, strdup(tmp));
}
}
}
closedir(dir);
}
gtk_combo_set_popdown_strings(GTK_COMBO(w), l);
return w;
}
static GtkWidget *extenw;
static GtkWidget *iconw;
static GtkWidget *labelw;
static GtkWidget *chanw;
static char **rexten, **ricon, **rlabel, **rchans;
void exten_answer(GtkWidget *widget, gpointer data)
{
static char exten[256];
static char icon[256];
static char label[256];
static char chans[256];
strncpy(exten, gtk_entry_get_text(GTK_ENTRY(extenw)), sizeof(exten) - 1);
strncpy(chans, gtk_entry_get_text(GTK_ENTRY(chanw)), sizeof(chans) - 1);
strncpy(icon, gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(iconw)->entry)), sizeof(icon) - 1);
strncpy(label, gtk_entry_get_text(GTK_ENTRY(labelw)), sizeof(label) - 1);
gtk_widget_destroy(dialog);
dialog = NULL;
choice = (int)(long)data;
*rexten = exten;
*ricon = icon;
*rlabel = label;
*rchans = chans;
}
/* Preview icon and frame */
static GtkWidget *pframe;
static GtkWidget *picon;
static void change_icon(GtkWidget *w)
{
const char *newn;
newn = gtk_entry_get_text(GTK_ENTRY(w));
if (strlen(newn)) {
gtk_widget_destroy(picon);
picon = make_pixmap_from_file(dialog, newn, 2);
gtk_widget_show(picon);
gtk_container_add(GTK_CONTAINER(pframe), picon);
}
}
int gui_exten(char **exten, char **chans, char **icon, char **label, char *title)
{
GtkWidget *button;
GtkWidget *tw, *defw;
GtkWidget *siconw;
GtkWidget *table;
char *ctext[] = { "Add", "Cancel" };
int choices = 2;
char rtext[256];
int x;
snprintf(rtext, sizeof(rtext),"GAstMan: %s", title);
dialog = gtk_dialog_new();
table = gtk_table_new(4, 4, 0);
gtk_table_set_row_spacings(GTK_TABLE(table), 5);
gtk_table_set_col_spacings(GTK_TABLE(table), 5);
gtk_widget_realize(dialog);
fix_icon(dialog->window);
siconw = make_pixmap_from_data(dialog, phone2_xpm);
gtk_table_attach_defaults(GTK_TABLE(table), siconw, 0, 1, 0, 4);
tw = gtk_label_new("Extension: ");
gtk_misc_set_alignment(GTK_MISC(tw), 0.0f, 0.5f);
gtk_widget_show(tw);
gtk_table_attach_defaults(GTK_TABLE(table), tw, 1, 2, 0, 1);
defw = extenw = gtk_entry_new();
if (*exten) {
ctext[0] = "Update";
gtk_entry_set_text(GTK_ENTRY(extenw), *exten);
}
gtk_widget_show(extenw);
gtk_table_attach_defaults(GTK_TABLE(table), extenw, 2, 3, 0, 1);
tw = gtk_label_new("Name: ");
gtk_misc_set_alignment(GTK_MISC(tw), 0.0f, 0.5f);
gtk_widget_show(tw);
gtk_table_attach_defaults(GTK_TABLE(table), tw, 1, 2, 1, 2);
labelw = gtk_entry_new();
if (*label)
gtk_entry_set_text(GTK_ENTRY(labelw), *label);
gtk_widget_show(labelw);
gtk_table_attach_defaults(GTK_TABLE(table), labelw, 2, 3, 1, 2);
tw = gtk_label_new("Icon: ");
gtk_misc_set_alignment(GTK_MISC(tw), 0.0f, 0.5f);
gtk_widget_show(tw);
gtk_table_attach_defaults(GTK_TABLE(table), tw, 1, 2, 2, 3);
iconw = icon_widget_new();
if (*icon)
gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(iconw)->entry), *icon);
gtk_signal_connect(GTK_OBJECT(GTK_COMBO(iconw)->entry), "changed", GTK_SIGNAL_FUNC(change_icon), NULL);
/* Preview icon */
picon = make_pixmap_from_file(dialog, (char*)gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(iconw)->entry)), 2);
pframe = gtk_frame_new("Icon Preview");
gtk_container_add(GTK_CONTAINER(pframe), picon);
gtk_widget_set_usize(pframe, 150, 150);
gtk_table_attach_defaults(GTK_TABLE(table), pframe, 3, 4, 0, 4);
gtk_table_set_col_spacing(GTK_TABLE(table), 2, 10);
gtk_widget_show(iconw);
gtk_table_attach_defaults(GTK_TABLE(table), iconw, 2, 3, 2, 3);
tw = gtk_label_new("Channels: ");
gtk_misc_set_alignment(GTK_MISC(tw), 0.0f, 0.5f);
gtk_widget_show(tw);
gtk_table_attach_defaults(GTK_TABLE(table), tw, 1, 2, 3, 4);
chanw = gtk_entry_new();
if (*chans)
gtk_entry_set_text(GTK_ENTRY(chanw), *chans);
gtk_widget_show(chanw);
gtk_table_attach_defaults(GTK_TABLE(table), chanw, 2, 3, 3, 4);
gtk_signal_connect_object(GTK_OBJECT(extenw), "activate", GTK_SIGNAL_FUNC(gtk_widget_grab_focus), GTK_OBJECT(iconw));
gtk_window_set_title(GTK_WINDOW(dialog), rtext);
gtk_widget_show(table);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 5);
gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 10);
for (x=0;x<choices;x++) {
button = gtk_button_new_with_label(ctext[x]);
if (!x)
gtk_signal_connect_object(GTK_OBJECT(labelw), "activate", GTK_SIGNAL_FUNC(gtk_widget_grab_focus), GTK_OBJECT(button));
gtk_widget_set_usize(button, 80, 30);
gtk_widget_show(button);
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(exten_answer), (gpointer)(long)x);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 10);
}
if (defw)
gtk_widget_grab_focus(defw);
if (window)
gtk_widget_set_sensitive(window, FALSE);
gtk_window_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
gtk_widget_show_all(dialog);
rexten = exten;
ricon = icon;
rlabel = label;
rchans = chans;
/* Block as long as dialog is here */
while(dialog)
gtk_main_iteration_do(1);
if (window)
gtk_widget_set_sensitive(window, TRUE);
return choice;
}
int gui_ask(char *title, char *text, int choices, int def, char *ctext[])
{
return gui_ask_maybe(title, text, NULL, choices, def, ctext);
}
int gui_yesno(char *title, char *text, int defaultyes)
{
if (!gui_ask(title, text, 2, defaultyes ? 0 : 1, yesno))
return 1;
return 0;
}
int gui_show_message(char *title, char *text)
{
gui_ask(title, text, 1, 0, okcancel);
return 0;
}
int gui_confirm(char *title, char *text, int defaultyes, char *entity)
{
if (!gui_ask_maybe(title, text, entity, 2, defaultyes ? 0 : 1, yesno))
return 1;
return 0;
}
static GtkWidget *doingw;
static GtkWidget *dtext;
int gui_show_doing(char *title, char *text)
{
char rtext[256];
snprintf(rtext, sizeof(rtext),"GAstMan: %s", title);
if (!doingw) {
doingw = gtk_dialog_new();
dtext = gtk_label_new(text);
gtk_widget_show(dtext);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(doingw)->vbox), dtext, TRUE, TRUE, 5);
gtk_window_position(GTK_WINDOW(doingw), GTK_WIN_POS_CENTER);
gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(doingw)->vbox), 10);
} else {
gtk_label_set_text(GTK_LABEL(dtext), text);
}
gtk_window_set_title(GTK_WINDOW(doingw), rtext);
if (window)
gtk_widget_set_sensitive(window, FALSE);
gtk_widget_show_all(doingw);
while(!gtk_main_iteration_do(0));
return 0;
}
int gui_hide_doing(void)
{
if (doingw) {
gtk_widget_destroy(doingw);
doingw = NULL;
}
if (window)
gtk_widget_set_sensitive(window, TRUE);
while(!gtk_main_iteration_do(0));
return 0;
}
static void dataready(void *ign, int fd, GdkInputCondition c)
{
gastman_input_ready();
}
int gui_watch_fd(int fd)
{
fdio = gdk_input_add(fd, GDK_INPUT_READ, dataready, NULL);
fdfd = fd;
return 0;
}
int gui_run(void)
{
gtk_main();
return 0;
}
int gui_exit(void)
{
struct gui_object *cur;
char tmp2[256];
char tmp[256];
DBT key, data;
int res;
/* Save positions of icons if they have identities */
if (db) {
cur = objects;
while(cur) {
gui_save_object(cur);
cur = cur->next;
}
if (window) {
snprintf(tmp, sizeof(tmp), "%d:%d", window->allocation.width, window->allocation.height);
snprintf(tmp2, sizeof(tmp2), "[%s]window", gastman_curhost());
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = tmp2;
key.size = strlen(tmp2) + 1;
data.data = tmp;
data.size = strlen(tmp) + 1;
#ifdef __FreeBSD__
if ((res = db->put(db, &key, &data, 0)))
#else
if ((res = db->put(db, NULL, &key, &data, 0)))
#endif
fprintf(stderr, "Unable to save window location\n");
}
#ifdef __FreeBSD__
db->close(db);
#else
db->close(db, 0);
#endif
}
gtk_exit(0);
return 0;
}
static void quit_program(gpointer callback_data, guint callback_action, GtkWidget *widget)
{
gastman_quit();
}
static void new_exten(gpointer callback_data, guint callback_action, GtkWidget *widget)
{
gastman_add_exten();
}
static void edit_exten(gpointer callback_data, guint callback_action, GtkWidget *widget)
{
if (current)
gastman_double_click(current->pvt);
}
static void del_exten(gpointer callback_data, guint callback_action, GtkWidget *widget)
{
if (current)
gastman_del_exten(current->pvt);
}
static void originate_exten(gpointer callback_data, guint callback_action, GtkWidget *widget)
{
if (current)
gastman_originate_exten(current->pvt);
}
static void invite_exten(gpointer callback_data, guint callback_action, GtkWidget *widget)
{
if (current)
gastman_invite_exten(current->pvt);
}
static void list_select(GtkWidget *w, gint row, gint column, GdkEventButton *eb, gpointer data)
{
struct gui_object *obj;
GdkPixmap *pm = NULL;
GdkBitmap *bm = NULL;
char *text;
guint8 spacing;
obj = gtk_clist_get_row_data(GTK_CLIST(w), row);
if (!eb)
return;
current = obj;
if (eb->button == 1) {
gtk_clist_get_pixtext(GTK_CLIST(w), row, 0, &text, &spacing, &pm, &bm);
gtk_drag_set_default_icon(gdk_colormap_get_system(), pm, bm, 10, 10);
gastman_object_select(obj->pvt);
} else if (eb->button == 3) {
bbutton = eb->button;
btime = eb->time;
gastman_right_click(obj->pvt);
}
}
static void qlist_select(GtkWidget *w, gint row, gint column, GdkEventButton *eb, gpointer data)
{
struct gui_queue *obj;
GdkPixmap *pm = NULL;
GdkBitmap *bm = NULL;
char *text;
guint8 spacing;
obj = gtk_clist_get_row_data(GTK_CLIST(w), row);
if (!eb)
return;
if (obj->type != TYPE_QUEUE) {
qcurrent = NULL;
return;
}
qcurrent = obj;
if (eb->button == 1) {
gtk_clist_get_pixtext(GTK_CLIST(w), row, 0, &text, &spacing, &pm, &bm);
gtk_drag_set_default_icon(gdk_colormap_get_system(), pm, bm, 10, 10);
gastman_queue_select(obj->pvt);
}
#if 0
else if (eb->button == 3) {
bbutton = eb->button;
btime = eb->time;
gastman_right_click(obj->pvt);
}
#endif
}
static GtkItemFactoryEntry entries[] = {
{ "/_File", NULL, NULL, 0, "<Branch>" },
{ "/_File/_Quit", "<CTRL>Q", quit_program, 0, "<Item>" },
{ "/_Exten", NULL, NULL, 0, "<Branch>" },
{ "/_Exten/_New", "<CTRL>N", new_exten, 0, "<Item>" },
{ "/_Exten/_Edit", "<CTRL>E", edit_exten, 0, "<Item>" },
{ "/_Exten/_Delete", "<CTRL>D", del_exten, 0, "<Item>" },
};
static GtkItemFactoryEntry callentries[] = {
{ "/Title", NULL, NULL, 0, "<Item>" },
{ "/Separator", NULL, NULL, 0, "<Separator>" },
{ "/_Redirect", "<CTRL>R", redirect_channel, 0, "<Item>" },
{ "/_Hangup", "<CTRL>H", hangup_channel, 0, "<Item>" },
};
static GtkItemFactoryEntry extenentries[] = {
{ "/Title", NULL, NULL, 0, "<Item>" },
{ "/Separator", NULL, NULL, 0, "<Separator>" },
{ "/_Invite", "<CTRL>I", invite_exten, 0, "<Item>" },
{ "/_Originate", "<CTRL>O", originate_exten, 0, "<Item>" },
{ "/_Delete", "<CTRL>D", del_exten, 0, "<Item>" },
{ "/_Edit", "<CTRL>E", edit_exten, 0, "<Item>" },
};
static int schedid = -1;
static int updateid = -1;
int sillytimeout(void *ign)
{
schedid = -1;
printf("Whee!\n");
return 0;
}
int gui_run_a_little(int *timeout)
{
struct timeval start, end;
gettimeofday(&start, NULL);
if (schedid > -1)
gtk_timeout_remove(schedid);
schedid = gtk_timeout_add(*timeout, sillytimeout, NULL);
gtk_main_iteration_do(1);
gettimeofday(&end, NULL);
if (*timeout >= 0) {
*timeout -= (end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec)/1000;
if (*timeout < 0)
*timeout = 0;
}
return 0;
}
static GtkWidget *statusbar;
static int statusid;
int gui_status(char *str)
{
gtk_statusbar_pop(GTK_STATUSBAR(statusbar), statusid);
gtk_statusbar_push(GTK_STATUSBAR(statusbar), statusid, str);
return 0;
}
int gui_set_icon(int nformat)
{
format = nformat;
return 0;
}
static void qdnd_picked(GtkWidget *widget, GdkDragContext *dc, GtkSelectionData *selection_data, guint info, guint t, gpointer data)
{
struct gui_queue *obj;
int row;
if (GTK_CLIST(widget)->selection_end)
row = (gint) (long)GTK_CLIST(widget)->selection_end->data;
else
return;
obj = gtk_clist_get_row_data(GTK_CLIST(widget), row);
gtk_selection_data_set(selection_data, GDK_SELECTION_TYPE_ATOM, 8, (char *)&obj, sizeof(obj));
}
static void qdnd_dropped(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, GtkSelectionData *selection_data, guint info, guint t, gpointer data)
{
struct gui_queue *src, *dst;
int row, column;
int res;
if (widget == NULL)
return;
if (!selection_data || (selection_data->length < sizeof(src)))
return;
if (!gtk_clist_get_selection_info(GTK_CLIST(widget), x, y, &row, &column))
return;
memcpy(&src, selection_data->data, sizeof(src));
dst = gtk_clist_get_row_data(GTK_CLIST(widget), row);
if (dst != src) {
res = gastman_pre_drag_drop(src->pvt, dst->pvt);
if (res > -1)
gastman_drag_drop(src->pvt, dst->pvt);
}
}
static void dnd_picked(GtkWidget *widget, GdkDragContext *dc, GtkSelectionData *selection_data, guint info, guint t, gpointer data)
{
struct gui_object *obj;
int row;
if (GTK_CLIST(widget)->selection_end)
row = (gint) (long)GTK_CLIST(widget)->selection_end->data;
else
return;
obj = gtk_clist_get_row_data(GTK_CLIST(widget), row);
gtk_selection_data_set(selection_data, GDK_SELECTION_TYPE_ATOM, 8, (char *)&obj, sizeof(obj));
}
static void dnd_dropped(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, GtkSelectionData *selection_data, guint info, guint t, gpointer data)
{
struct gui_object *src, *dst;
int row, column;
int res;
if (widget == NULL)
return;
if (!selection_data || (selection_data->length < sizeof(src)))
return;
if (!gtk_clist_get_selection_info(GTK_CLIST(widget), x, y, &row, &column))
return;
memcpy(&src, selection_data->data, sizeof(src));
dst = gtk_clist_get_row_data(GTK_CLIST(widget), row);
if (dst != src) {
res = gastman_pre_drag_drop(src->pvt, dst->pvt);
if (res > -1)
gastman_drag_drop(src->pvt, dst->pvt);
}
}
void gui_object_set_callinfo(struct gui_object *obj, char *callerid, char *linked, char *location, struct gui_object *cobj, struct gui_object *eobj)
{
int row, row2;
GdkPixmap *cpm = NULL, *epm = NULL;
GdkBitmap *cbm = NULL, *ebm = NULL;
#if 0
printf("Being called... ('%s', '%s', '%s')\n", linked, location, callerid);
#endif
row = gtk_clist_find_row_from_data(GTK_CLIST(calllist), obj);
if (row > -1) {
gtk_clist_set_text(GTK_CLIST(calllist), row, 1, callerid);
if (cobj && (row2 = gtk_clist_find_row_from_data(GTK_CLIST(calllist), cobj)) > -1) {
gtk_clist_get_pixtext(GTK_CLIST(calllist), row2, 0, NULL, NULL, &cpm, &cbm);
}
if (eobj && (row2 = gtk_clist_find_row_from_data(GTK_CLIST(extenlist), eobj)) > -1) {
gtk_clist_get_pixtext(GTK_CLIST(extenlist), row2, 0, NULL, NULL, &epm, &ebm);
}
if (cpm && cbm)
gtk_clist_set_pixtext(GTK_CLIST(calllist), row, 2, linked, 5, cpm, cbm);
else
gtk_clist_set_text(GTK_CLIST(calllist), row, 2, linked);
if (epm && ebm)
gtk_clist_set_pixtext(GTK_CLIST(calllist), row, 3, location, 5, epm, ebm);
else
gtk_clist_set_text(GTK_CLIST(calllist), row, 3, location);
}
#if 0
printf("Done called... ('%s', '%s')\n", linked, location);
#endif
}
static int qupdate(void *ign)
{
int wait;
int x;
struct gui_queue *obj;
char swait[40];
time_t now;
time(&now);
for (x=0;x<GTK_CLIST(qlist)->rows;x++) {
obj = gtk_clist_get_row_data(GTK_CLIST(qlist), x);
if (obj->type == TYPE_QUEUE) {
wait = now - obj->base + obj->offset;
if (wait > 3600)
snprintf(swait, sizeof(swait), "%d:%02d:%02d", wait/3600, (wait % 3600) / 60, wait % 60);
else
snprintf(swait, sizeof(swait), "%d:%02d", wait / 60, wait % 60);
gtk_clist_set_text(GTK_CLIST(qlist), x, 4, swait);
}
}
return 1;
}
static int update_queue(char *queuename, int pos)
{
int x;
struct gui_queue *obj;
char spos[40];
time_t now;
time(&now);
for (x=0;x<GTK_CLIST(qlist)->rows;x++) {
obj = gtk_clist_get_row_data(GTK_CLIST(qlist), x);
if (obj->type == TYPE_QUEUE) {
if (!strcasecmp(queuename, obj->queue) && (obj->position > pos)) {
obj->position--;
snprintf(spos, sizeof(spos), "%d", obj->position);
gtk_clist_set_text(GTK_CLIST(qlist), x, 1, spos);
}
}
}
return 1;
}
int queuesort(GtkCList *clist, const void *ptr1, const void *ptr2)
{
int res;
const GtkCListRow *row1, *row2;
const struct gui_queue *q1, *q2;
row1 = ptr1;
row2 = ptr2;
q1 = row1->data;
q2 = row2->data;
if (!q1 || !q2)
return 0;
res = strcasecmp(q1->queue, q2->queue);
if (!res) {
res = q1->position > q2->position;
}
return res;
}
void gui_queue_set_callinfo(struct gui_queue *obj, char *callerid, int position, int wait)
{
int row;
GdkPixmap *cpm = NULL;
GdkBitmap *cbm = NULL;
char sposition[40];
#if 0
printf("Being called... ('%s', '%d', '%d')\n", callerid, position, wait);
#endif
row = gtk_clist_find_row_from_data(GTK_CLIST(qlist), obj);
if (row > -1) {
time(&obj->base);
obj->offset = wait;
obj->position = position;
gtk_clist_set_text(GTK_CLIST(qlist), row, 3, callerid);
snprintf(sposition, sizeof(sposition), "%d", position);
gtk_clist_set_text(GTK_CLIST(qlist), row, 1, sposition);
if (cpm && cbm)
gtk_clist_set_pixtext(GTK_CLIST(qlist), row, 3, callerid, 5, cpm, cbm);
else
gtk_clist_set_text(GTK_CLIST(qlist), row, 3, callerid);
gtk_clist_sort(GTK_CLIST(qlist));
} else
printf("Weird, not found...\n");
#if 0
printf("Done called... ('%s', '%s')\n", linked, location);
#endif
}
void gui_queue_set_queueinfo(struct gui_queue *obj, int current, int max)
{
int row;
char status[40];
row = gtk_clist_find_row_from_data(GTK_CLIST(qlist), obj);
if (row > -1) {
if (max)
snprintf(status, sizeof(status), " %d of %d calls", current, max);
else
snprintf(status, sizeof(status), " %d calls", current);
gtk_clist_set_text(GTK_CLIST(qlist), row, 2, status);
} else
printf("Weird, not found...\n");
#if 0
printf("Done called... ('%s', '%s')\n", linked, location);
#endif
}
static char *ctitles[] = {
"Channel",
"Caller*ID",
"Linked to",
"Location",
};
static char *qtitles[] = {
"Queue",
"Position",
"Channel",
"Caller",
"Hold Time",
};
void gui_cli_result(char *s)
{
char *o;
float p;
GtkStyle *style;
style = gtk_widget_get_style(cmdtextbox);
gtk_text_freeze(GTK_TEXT(cmdtextbox));
o = gtk_editable_get_chars(GTK_EDITABLE(cmdtextbox), 0, -1);
gtk_editable_delete_text(GTK_EDITABLE(cmdtextbox), 0, -1);
gtk_text_insert(GTK_TEXT(cmdtextbox), clifont, &style->fg[GTK_STATE_INSENSITIVE], NULL, o, -1);
gtk_text_insert(GTK_TEXT(cmdtextbox), clifont, &colors[3], NULL, lastcmd, -1);
/* Apparently we *have* to insert something here, or it will crash, go figure */
if (!s || !strlen(s))
s = " \n";
gtk_text_insert(GTK_TEXT(cmdtextbox), clifont, NULL, NULL, "\n", -1);
gtk_text_thaw(GTK_TEXT(cmdtextbox));
p = GTK_TEXT(cmdtextbox)->vadj->upper;
p -= (float)(cmdtextbox->allocation.height - 1.0);
if (p < 0.0)
p = 0.0;
gtk_adjustment_set_value(GTK_TEXT(cmdtextbox)->vadj, p);
gtk_text_insert(GTK_TEXT(cmdtextbox), clifont, NULL, NULL, s, -1);
gtk_editable_set_position(GTK_EDITABLE(cmdtextbox), -1);
g_free(o);
}
static int focus_tabs(GtkObject *thing, GdkEvent *event, struct gui_object *obj)
{
if (event->type == GDK_BUTTON_RELEASE)
gtk_widget_grab_focus(cmdentry);
return FALSE;
}
static int command_event(GtkObject *thing, GdkEvent *event, struct gui_object *obj)
{
GdkEventKey *ek;
int keyval;
int flags;
int pos;
int absorbed = FALSE;
char *s;
if (event->type == GDK_KEY_PRESS) {
ek = (GdkEventKey *)event;
keyval = ek->keyval & 0xff;
flags = (ek->keyval & 0xff00) >> 8;
if (keyval == 0x9) {
/* Tab pressed -- command complete... */
gtk_widget_set_sensitive(GTK_WIDGET(thing), FALSE);
#if (GTK_MAJOR_VERSION > 1)
pos = GTK_ENTRY(thing)->current_pos;
#else
pos = GTK_EDITABLE(thing)->current_pos;
#endif
s = gastman_complete(gtk_entry_get_text(GTK_ENTRY(thing)), &pos);
gtk_entry_set_text(GTK_ENTRY(thing), s);
gtk_widget_set_sensitive(GTK_WIDGET(thing), TRUE);
gtk_widget_grab_focus(GTK_WIDGET(thing));
gtk_entry_select_region(GTK_ENTRY(thing), pos, pos);
absorbed = TRUE;
} else if (flags == 0xff) {
if (keyval == 0x52) {
s = gastman_prevhist();
if (s) {
gtk_entry_set_text(GTK_ENTRY(thing), s);
gtk_entry_set_position(GTK_ENTRY(thing), -1);
} else
gdk_beep();
absorbed = 1;
} else if (keyval == 0x54) {
s = gastman_nexthist();
if (s) {
gtk_entry_set_text(GTK_ENTRY(thing), s);
gtk_entry_set_position(GTK_ENTRY(thing), -1);
} else {
gtk_entry_set_text(GTK_ENTRY(thing), "");
gtk_entry_set_position(GTK_ENTRY(thing), -1);
gdk_beep();
}
absorbed = 1;
}
}
}
return absorbed;
}
int gui_show_box(char *host)
{
char buf[256];
GtkWidget *vbox;
GtkWidget *menu;
GtkWidget *sw;
GtkWidget *tw;
GtkWidget *pane;
GtkWidget *frame;
GtkWidget *qframe;
GtkWidget *hbox;
GtkItemFactory *fact;
GtkAccelGroup *group;
int xwin=640,ywin=480;
/* The purely graphical piece */
snprintf(buf, sizeof(buf), "Asterisk Manager at %s", host);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_realize(window);
fix_icon(window->window);
group = gtk_accel_group_new();
fact = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<GastManMain>", group);
gtk_item_factory_create_items(fact, sizeof(entries) / sizeof(entries[0]), entries, NULL);
menu = gtk_item_factory_get_widget(fact, "<GastManMain>");
fact = gtk_item_factory_new(GTK_TYPE_MENU, "<GastCallMenu>", group);
gtk_item_factory_create_items(fact, sizeof(callentries) / sizeof(callentries[0]), callentries, NULL);
callmenu = gtk_item_factory_get_widget(fact, "<GastCallMenu>");
calltitle = gtk_item_factory_get_widget(fact, "<GastCallMenu>/Title");
fact = gtk_item_factory_new(GTK_TYPE_MENU, "<GastExtenMenu>", group);
gtk_item_factory_create_items(fact, sizeof(extenentries) / sizeof(extenentries[0]), extenentries, NULL);
extenmenu = gtk_item_factory_get_widget(fact, "<GastExtenMenu>");
extentitle = gtk_item_factory_get_widget(fact, "<GastExtenMenu>/Title");
statusbar = gtk_statusbar_new();
statusid = gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), "status");
tips = gtk_tooltips_new();
canvas = gtk_layout_new(NULL, NULL);
gtk_widget_modify_bg(canvas, GTK_STATE_NORMAL, &colors[COLOR_GRAY]);
sw = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(sw), canvas);
gtk_container_set_border_width(GTK_CONTAINER(sw), 1);
frame = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
gtk_container_add(GTK_CONTAINER(frame), sw);
/* Make notebook */
tabs = gtk_notebook_new();
gtk_notebook_append_page(GTK_NOTEBOOK(tabs), frame, gtk_label_new("Graphical View"));
gtk_signal_connect(GTK_OBJECT(tabs), "event", GTK_SIGNAL_FUNC(focus_tabs), NULL);
/* List of calls and extensions */
pane = gtk_vpaned_new();
calllist = gtk_clist_new_with_titles(4, ctitles);
gtk_clist_set_column_auto_resize(GTK_CLIST(calllist), 0, TRUE);
gtk_clist_set_column_auto_resize(GTK_CLIST(calllist), 1, TRUE);
gtk_clist_set_column_auto_resize(GTK_CLIST(calllist), 2, TRUE);
gtk_clist_set_column_auto_resize(GTK_CLIST(calllist), 3, TRUE);
gtk_signal_connect(GTK_OBJECT(calllist), "select_row", GTK_SIGNAL_FUNC(list_select), NULL);
gtk_clist_set_selection_mode(GTK_CLIST(calllist), GTK_SELECTION_BROWSE);
gtk_clist_set_shadow_type(GTK_CLIST(calllist), GTK_SHADOW_IN);
gtk_clist_set_row_height(GTK_CLIST(calllist), 20);
gtk_clist_set_button_actions(GTK_CLIST(calllist), 2, GTK_BUTTON_SELECTS);
gtk_drag_source_set(calllist, GDK_BUTTON1_MASK, &target_entry, 1, GDK_ACTION_MOVE | GDK_ACTION_COPY);
gtk_signal_connect(GTK_OBJECT(calllist), "drag_data_get", GTK_SIGNAL_FUNC(dnd_picked), NULL);
gtk_signal_connect(GTK_OBJECT(calllist), "drag_data_received", GTK_SIGNAL_FUNC(dnd_dropped), NULL);
/* Queue status */
qlist = gtk_clist_new_with_titles(5, qtitles);
gtk_clist_set_column_auto_resize(GTK_CLIST(qlist), 0, TRUE);
gtk_clist_set_column_auto_resize(GTK_CLIST(qlist), 1, TRUE);
gtk_clist_set_column_auto_resize(GTK_CLIST(qlist), 2, TRUE);
gtk_clist_set_column_auto_resize(GTK_CLIST(qlist), 3, TRUE);
gtk_clist_set_column_auto_resize(GTK_CLIST(qlist), 4, TRUE);
gtk_clist_set_compare_func(GTK_CLIST(qlist), queuesort);
gtk_signal_connect(GTK_OBJECT(qlist), "select_row", GTK_SIGNAL_FUNC(qlist_select), NULL);
gtk_clist_set_selection_mode(GTK_CLIST(qlist), GTK_SELECTION_BROWSE);
gtk_clist_set_shadow_type(GTK_CLIST(qlist), GTK_SHADOW_IN);
gtk_clist_set_row_height(GTK_CLIST(qlist), 20);
gtk_clist_set_button_actions(GTK_CLIST(qlist), 2, GTK_BUTTON_SELECTS);
gtk_drag_source_set(qlist, GDK_BUTTON1_MASK, &target_entry, 1, GDK_ACTION_MOVE | GDK_ACTION_COPY);
gtk_signal_connect(GTK_OBJECT(qlist), "drag_data_get", GTK_SIGNAL_FUNC(qdnd_picked), NULL);
gtk_signal_connect(GTK_OBJECT(qlist), "drag_data_received", GTK_SIGNAL_FUNC(qdnd_dropped), NULL);
qframe = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(qframe), GTK_SHADOW_IN);
gtk_container_add(GTK_CONTAINER(qframe), qlist);
extenlist = gtk_clist_new(1);
gtk_signal_connect(GTK_OBJECT(extenlist), "select_row", GTK_SIGNAL_FUNC(list_select), NULL);
gtk_clist_set_selection_mode(GTK_CLIST(extenlist), GTK_SELECTION_BROWSE);
gtk_clist_set_shadow_type(GTK_CLIST(extenlist), GTK_SHADOW_IN);
gtk_clist_set_row_height(GTK_CLIST(extenlist), 20);
gtk_clist_set_button_actions(GTK_CLIST(extenlist), 2, GTK_BUTTON_SELECTS);
gtk_drag_dest_set(extenlist, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, &target_entry, 1, GDK_ACTION_MOVE | GDK_ACTION_COPY);
gtk_drag_source_set(extenlist, GDK_BUTTON1_MASK, &target_entry, 1, GDK_ACTION_MOVE | GDK_ACTION_COPY);
gtk_signal_connect(GTK_OBJECT(extenlist), "drag_data_get", GTK_SIGNAL_FUNC(dnd_picked), NULL);
gtk_signal_connect(GTK_OBJECT(extenlist), "drag_data_received", GTK_SIGNAL_FUNC(dnd_dropped), NULL);
vbox = gtk_vbox_new(FALSE, 2);
gtk_box_pack_start(GTK_BOX(vbox), (tw = gtk_label_new("Active Channels:")), FALSE, FALSE, 0);
gtk_misc_set_alignment(GTK_MISC(tw), 0.01f, 0.5f);
sw = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(sw), calllist);
gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
gtk_paned_pack1(GTK_PANED(pane), vbox, 1, 1);
vbox = gtk_vbox_new(FALSE, 2);
gtk_box_pack_start(GTK_BOX(vbox), (tw = gtk_label_new("Extensions:")), FALSE, FALSE, 0);
gtk_misc_set_alignment(GTK_MISC(tw), 0.01f, 0.5f);
sw = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(sw), extenlist);
gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
gtk_paned_pack2(GTK_PANED(pane), vbox, 1, 1);
gtk_container_set_border_width(GTK_CONTAINER(pane), 5);
gtk_notebook_append_page(GTK_NOTEBOOK(tabs), pane, gtk_label_new("List View"));
gtk_notebook_append_page(GTK_NOTEBOOK(tabs), qframe, gtk_label_new("Call Queues"));
/* Command window */
vbox = gtk_vbox_new(FALSE, 0);
hbox = gtk_hbox_new(FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
cmdtextbox = gtk_text_new(FALSE, FALSE);
gtk_text_set_word_wrap(GTK_TEXT(cmdtextbox), FALSE);
gtk_text_set_line_wrap(GTK_TEXT(cmdtextbox), FALSE);
sw = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(sw), cmdtextbox);
cmdentry = gtk_entry_new();
gtk_signal_connect(GTK_OBJECT(cmdentry), "activate", GTK_SIGNAL_FUNC(command_ready), (gpointer)(long)0);
gtk_signal_connect(GTK_OBJECT(cmdentry), "event", GTK_SIGNAL_FUNC(command_event), NULL);
gtk_widget_grab_focus(cmdentry);
gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
clifont = gdk_font_load("-*-clean-*-*-*-*-16-*-*-*-*-*-*-*");
gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("CLI>"), FALSE, FALSE, 0);
gtk_box_pack_end(GTK_BOX(hbox), cmdentry, TRUE, TRUE, 2);
gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
gtk_notebook_append_page(GTK_NOTEBOOK(tabs), vbox, gtk_label_new("Command Window"));
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_box_pack_start(GTK_BOX(vbox), menu, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), tabs, TRUE, TRUE, 0);
gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
gtk_window_set_title(GTK_WINDOW(window), buf);
if (db) {
int res;
DBT key, data;
char tmp2[256];
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
snprintf(tmp2, sizeof(tmp2), "[%s]window", gastman_curhost());
key.data = tmp2;
key.size = strlen(tmp2) + 1;
#ifdef __FreeBSD__
if (!(res = db->get(db, &key, &data, 0))) {
#else
if (!(res = db->get(db, NULL, &key, &data, 0))) {
#endif
if (((char *)data.data)[data.size - 1] != '\0')
fprintf(stderr, "Not null terminated?!?\n");
else if (sscanf((char *)data.data, "%d:%d", &xwin, &ywin) != 2)
fprintf(stderr, "Whoa, weird...\n");
}
}
gtk_widget_set_usize(window, xwin, ywin);
gtk_window_set_policy(GTK_WINDOW(window), 1, 1, 0);
gtk_window_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(quit_program), NULL);
gtk_widget_show_all(window);
updateid = gtk_timeout_add(1000, qupdate, NULL);
gui_status("Manager Ready.");
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1