/* * GTK ASTerisk MANager * Copyright (C) 2002, Digium * * Written by Mark Spencer * * All Rights Reserved * * Distributed under GNU GPL * * GTK specific GUI routine implementation */ #ifndef _WIN32 #else #include #include "win32dep.h" #define _WINSOCKAPI_ #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 #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;xaction_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;xaction_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;xaction_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;xaction_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;xaction_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, "" }, { "/_File/_Quit", "Q", quit_program, 0, "" }, { "/_Exten", NULL, NULL, 0, "" }, { "/_Exten/_New", "N", new_exten, 0, "" }, { "/_Exten/_Edit", "E", edit_exten, 0, "" }, { "/_Exten/_Delete", "D", del_exten, 0, "" }, }; static GtkItemFactoryEntry callentries[] = { { "/Title", NULL, NULL, 0, "" }, { "/Separator", NULL, NULL, 0, "" }, { "/_Redirect", "R", redirect_channel, 0, "" }, { "/_Hangup", "H", hangup_channel, 0, "" }, }; static GtkItemFactoryEntry extenentries[] = { { "/Title", NULL, NULL, 0, "" }, { "/Separator", NULL, NULL, 0, "" }, { "/_Invite", "I", invite_exten, 0, "" }, { "/_Originate", "O", originate_exten, 0, "" }, { "/_Delete", "D", del_exten, 0, "" }, { "/_Edit", "E", edit_exten, 0, "" }, }; 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;xrows;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;xrows;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, "", group); gtk_item_factory_create_items(fact, sizeof(entries) / sizeof(entries[0]), entries, NULL); menu = gtk_item_factory_get_widget(fact, ""); fact = gtk_item_factory_new(GTK_TYPE_MENU, "", group); gtk_item_factory_create_items(fact, sizeof(callentries) / sizeof(callentries[0]), callentries, NULL); callmenu = gtk_item_factory_get_widget(fact, ""); calltitle = gtk_item_factory_get_widget(fact, "/Title"); fact = gtk_item_factory_new(GTK_TYPE_MENU, "", group); gtk_item_factory_create_items(fact, sizeof(extenentries) / sizeof(extenentries[0]), extenentries, NULL); extenmenu = gtk_item_factory_get_widget(fact, ""); extentitle = gtk_item_factory_get_widget(fact, "/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; }