Source Code (Biggifier.c)

#include "Biggifier.h"

//variables for setting up and maintaining windows
Display *display;
Window window, root;
int win_width, win_height, old_width, old_height;
unsigned int root_width, root_height, root_depth;
unsigned long foreground, background;
GC gc;

// variables for magnification
XImage *tmp_image; // stores a temporary image used to created the magnified view
XImage *mag_image; // stores the image to be displayed
int tmp_image_border;

//variables for restore function
WindowSave *head;

//Gtk variables
guint idleMagnifyIndex;
guint zoom_level = 2;


/**************/
/* Begin Main */
/**************/
int main( int argc,
char *argv[] ) {
/* Make references to GUI componenets */
GtkWidget *window;
GtkWidget *positiontable; /* Table for movement positions */

GtkWidget *button_holder; /* Temp for button creation */
GtkWidget *main_v_box; /* Box for gui layout */
GtkWidget *v_box_left; /* Box for gui layout */
GtkWidget *v_box_right; /* Box for gui layout */
GtkWidget *h_box_buttons; /* Box for gui layout */
GtkWidget *box; /* Temp box for widget building */
GtkWidget *label; /* Temp label */
GtkTooltips *tooltips; /* Temp for setting tooltips on widgets */
GtkWidget *image; /* Image temp */


/* Begin program */
gtk_init (&argc, &argv);
setupMag();

/* Initialize window */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Biggifier");
gtk_container_set_border_width (GTK_CONTAINER (window), 3);
gtk_widget_set_usize (window, 310, 340);
gtk_window_set_policy (GTK_WINDOW (window), FALSE, FALSE, FALSE);;

/* Set handler for delete event for window */
g_signal_connect (G_OBJECT (window), "destroy",
G_CALLBACK (delete_event), NULL);

/* Begin layout creation
* Outline: main_v_box --> menu bar
* logo image
* h_box_buttons --> v_box_left --> button(zoom_onoff)
* Box(horiz) --> label, spin button
* button(invert_onoff)
* v_box_right --> position table
* button(smooth_onoff)
*/
main_v_box = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (window), main_v_box);

/* Add menu bar */
GtkItemFactoryEntry menu_entries[] = {
{ "/_File", NULL, NULL, 0, "<Branch>" },
{ "/File/_Quit", "<CTRL>Q", quit_callback, 1, "<Item>" },
{ "/_Info", NULL, NULL, 0, "<Branch>" },
{ "/Info/_About", "<CTRL>A", info_callback, 0, "<Item>" },
{ "/Info/_Help", "<CTRL>H", help_callback, 0, "<Item>" },
{ "/_Move...", NULL, NULL, 0, "<Branch>" },
{ "/Move.../Top Left", "<CTRL>7", move_callback, 7, "<Item>" },
{ "/Move.../Top Mid", "<CTRL>8", move_callback, 8, "<Item>" },
{ "/Move.../Top Right", "<CTRL>9", move_callback, 9, "<Item>" },
{ "/Move.../Mid Left", "<CTRL>4", move_callback, 4, "<Item>" },
{ "/Move.../Center", "<CTRL>5", move_callback, 5, "<Item>" },
{ "/Move.../Mid Right", "<CTRL>6", move_callback, 6, "<Item>" },
{ "/Move.../Bottom Left", "<CTRL>1", move_callback, 1, "<Item>" },
{ "/Move.../Bottom Mid", "<CTRL>2", move_callback, 2, "<Item>" },
{ "/Move.../Bottom Right","<CTRL>3", move_callback, 3, "<Item>" } };

GtkAccelGroup* accelgroup = gtk_accel_group_new();
GtkItemFactory* itemF = gtk_item_factory_new( GTK_TYPE_MENU_BAR, "<BigMAIN>", accelgroup);
guint size = sizeof (menu_entries) / sizeof (menu_entries[0]);
gtk_item_factory_create_items( itemF, size, menu_entries, window );
gtk_window_add_accel_group( GTK_WINDOW (window), accelgroup);
GtkWidget* menu_bar = gtk_item_factory_get_widget(itemF, "<BigMAIN>");

gtk_box_pack_start (GTK_BOX (main_v_box), menu_bar, FALSE, FALSE, 3);
gtk_widget_show_all (menu_bar);

/* Add logo */
image = gtk_image_new_from_file ("/home/greg/biggifier/Data/logo.jpg");
gtk_box_pack_start (GTK_BOX (main_v_box), image, FALSE, FALSE, 3);
gtk_widget_show (image);

/* Build horiz box */
h_box_buttons = gtk_hbox_new (TRUE, 0);

/* Build first inner vert box */
v_box_left = gtk_vbox_new (FALSE, 0);

/* create new button, set up callback, pack it in vbox2, and display it */
label = gtk_label_new ("Magnification On/Off");
gtk_box_pack_start (GTK_BOX (v_box_left), label, TRUE, TRUE, 0);

button_holder = gtk_toggle_button_new ();
gtk_widget_set_usize (button_holder, 75, 75);
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (button_holder), TRUE);
image = gtk_image_new_from_file ("/home/greg/biggifier/Data/mag.jpg");
tooltips = gtk_tooltips_new();
gtk_tooltips_set_tip( tooltips, button_holder, "Enable/Disable Magnification", NULL);

gtk_container_add (GTK_CONTAINER (button_holder), image);

g_signal_connect (G_OBJECT (button_holder), "toggled",
G_CALLBACK (zoom_toggle_callback), NULL);
gtk_box_pack_start (GTK_BOX(v_box_left), button_holder, FALSE, FALSE, 10);
gtk_widget_show(label);
gtk_widget_show(image);
gtk_widget_show (button_holder);

/* set up scroll scale for selection of magnification: 1-10 in increments of 1 */
box = gtk_hbox_new (FALSE, 0);
label = gtk_label_new ("Zoom Factor x ");
gtk_box_pack_start (GTK_BOX(box), label, TRUE, TRUE, 0);
gtk_widget_show(label);

GtkWidget* adj = gtk_adjustment_new( 2.0, 2.0, 10.0, 1.0, 5.0, 5.0);
GtkWidget* spin_button = gtk_spin_button_new(GTK_ADJUSTMENT (adj), 0.0, 1);
gtk_spin_button_set_numeric( GTK_SPIN_BUTTON (spin_button), TRUE );
gtk_spin_button_set_snap_to_ticks( GTK_SPIN_BUTTON (spin_button), TRUE );
gtk_spin_button_set_update_policy( GTK_SPIN_BUTTON (spin_button), GTK_UPDATE_IF_VALID );
g_signal_connect (G_OBJECT (adj), "value_changed",
G_CALLBACK (zoomlevel_callback), (gpointer) spin_button);
gtk_widget_show(spin_button);
gtk_box_pack_start (GTK_BOX(box), spin_button, TRUE, TRUE, 0);
gtk_widget_show (box);
gtk_box_pack_start (GTK_BOX (v_box_left), box, FALSE, FALSE, 3);

/* set up other button in same fashion as first*/
label = gtk_label_new ( "Invert" );
button_holder = gtk_toggle_button_new ();
gtk_widget_set_usize (button_holder, 75, 75);
image = gtk_image_new_from_file ("/home/greg/biggifier/Data/invert.bmp");
g_signal_connect (G_OBJECT (button_holder), "toggled",
G_CALLBACK (invert_toggle_callback), NULL);
gtk_container_add (GTK_CONTAINER (button_holder), image);
gtk_tooltips_set_tip (tooltips, button_holder, "Invert colors", NULL);

gtk_box_pack_start(GTK_BOX (v_box_left), label, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX (v_box_left), button_holder, FALSE, FALSE, 2);
gtk_widget_show (label);
gtk_widget_show (image);
gtk_widget_show (button_holder);

/* Finalize this vert. box */
gtk_widget_show (v_box_left);
gtk_box_pack_start(GTK_BOX (h_box_buttons), v_box_left, TRUE, TRUE, 10);

/*Build second inner vert box*/
v_box_right = gtk_vbox_new (FALSE, 0);

/* set up 3x3 table and add to box */
box = gtk_frame_new( "Move To" );
positiontable = gtk_table_new( 3, 3, TRUE );
int m = 0;
int n = 0;
for (; m < 3; m++) {
for (; n < 3; n++) {
button_holder = gtk_button_new();
gtk_table_attach_defaults( GTK_TABLE (positiontable), button_holder, n, n +1, m, m+1);
gtk_widget_show(button_holder);
}
n = 0;
}

gtk_table_set_row_spacings( GTK_TABLE (positiontable), 1);
gtk_table_set_col_spacings( GTK_TABLE (positiontable), 1);
gtk_container_add (GTK_CONTAINER (box), positiontable); /* Because it's a frame, not a box */
gtk_box_pack_start(GTK_BOX (v_box_right), box, TRUE, TRUE, 0);
gtk_widget_set_usize (box, 145, 140);
gtk_widget_show (box);
gtk_widget_show (positiontable);

/*Add buttons to this vert. box within a horiz box: help, quit*/
label = gtk_label_new( "Smoothing" );
button_holder = gtk_toggle_button_new();
gtk_widget_set_usize (button_holder, 75, 75);
image = gtk_image_new_from_file ("/home/greg/biggifier/Data/unsmooth.jpg");
g_signal_connect (G_OBJECT (button_holder), "toggled",
G_CALLBACK (smooth_toggle_callback), NULL);
gtk_tooltips_set_tip (tooltips, button_holder, "Activate/Deactivate Smoothing", NULL);
gtk_container_add (GTK_CONTAINER (button_holder), image);

gtk_box_pack_start(GTK_BOX (v_box_right), label, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX (v_box_right), button_holder, FALSE, FALSE, 2);
gtk_widget_show(image);
gtk_widget_show(label);
gtk_widget_show(button_holder);

/* Finalize the second vert. box*/
gtk_widget_show (v_box_right);
gtk_box_pack_start(GTK_BOX (h_box_buttons), v_box_right, TRUE, TRUE, 10);

/* Finalize the main horiz. box*/
gtk_box_pack_start(GTK_BOX (main_v_box), h_box_buttons, TRUE, TRUE, 0);
gtk_widget_show (h_box_buttons);

/* Finalize window and wait in gtkmain */
gtk_widget_show (main_v_box);
gtk_widget_show (window);

/*Add the magnify function to gtk_main's idle processes and wait in gtk_main */
idleMagnifyIndex = gtk_idle_add(GTK_SIGNAL_FUNC (magnify), &zoom_level);
gtk_main ();

return 0;
}//endmain


/*********************************/
/* GTK Widget Callback Functions */
/*********************************/

/* Callback for toggling the zoom */
void zoom_toggle_callback( GtkWidget *button, gpointer stuff ) {
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) {
idleMagnifyIndex = gtk_idle_add(GTK_SIGNAL_FUNC (magnify), &zoom_level);
}
else {
gtk_idle_remove(idleMagnifyIndex);
}
}

/* Callback for changing the zoom level */
void zoomlevel_callback ( GtkWidget *adj, gpointer spinwheel ) {
zoom_level = gtk_spin_button_get_value ( spinwheel );
}

/* Callback for toggling color inversion */
void invert_toggle_callback ( GtkWidget* button, gpointer stuff ){
}

/* Callback for toggling smooth functions */
void smooth_toggle_callback ( GtkWidget* button, gpointer stuff ){
GtkWidget* new_image;
GList* list = gtk_container_get_children ( GTK_CONTAINER (button) );
gtk_container_remove ( GTK_CONTAINER (button), list -> data);

if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) {
new_image = gtk_image_new_from_file ("/home/greg/biggifier/Data/smooth.jpg");
}
else {
new_image = gtk_image_new_from_file ("/home/greg/biggifier/Data/unsmooth.jpg");
}

gtk_container_add (GTK_CONTAINER (button), new_image);
gtk_widget_show(new_image);
}

/* Callback for displaying the help file */
void help_callback ( ){
/*Open help file and get input */
FILE* helpFile = fopen("/home/greg/biggifier/Data/Help.bgf", "r");
char string[2000]; //Allocate memory for string
int next_open = 0; //Next open position in the string
char next;

if (helpFile == NULL) return;

/*Make text display componenets, starting cursor at last position */
GtkWidget *text_view = gtk_text_view_new ();
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
gtk_text_view_set_editable (GTK_TEXT_VIEW (text_view), FALSE);

/* Read entire file to buffer while the lines aren't repeating (EoF not reached)*/
next = getc(helpFile);
while ( next != EOF ) {
string[next_open] = next;
next_open++;
next = getc(helpFile);
}

fclose(helpFile);
gtk_text_buffer_set_text (buffer, string, next_open);

/* Put text in scrolled view window */
GtkWidget* scrwin = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrwin),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_add ( GTK_CONTAINER(scrwin), text_view );
gtk_widget_set_usize (scrwin, 450, 300);

/* Build dialog and display buffer */
GtkWidget* dialog = gtk_dialog_new_with_buttons( "Help", NULL, GTK_DIALOG_MODAL, NULL);
GtkWidget* image = gtk_image_new_from_file ("/home/greg/biggifier/Data/help.jpg");

GtkWidget* OK_Button = gtk_button_new_with_label ("OK");
g_signal_connect_swapped (G_OBJECT (OK_Button), "clicked",
G_CALLBACK (gtk_widget_destroy), G_OBJECT (dialog));

/* Finalize dialog */
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), image, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), scrwin, TRUE, TRUE, 3);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), OK_Button, FALSE, FALSE, 3);
gtk_widget_show(OK_Button);
gtk_widget_show(image);
gtk_widget_show(text_view);
gtk_widget_show (scrwin);
gtk_widget_show(dialog);
}

/* Callback for displaying the info dialog */
void info_callback (gpointer window, guint action, GtkWidget* menu){
GtkWidget* dialog = gtk_dialog_new_with_buttons( "Info", GTK_WINDOW (window), GTK_DIALOG_MODAL, NULL);
GtkWidget* image = gtk_image_new_from_file ("/home/greg/biggifier/Data/logo.jpg");
GtkWidget* label = gtk_label_new ("Biggifier v1.0, by\n\tGreg Bowman\n\tLucas Cook\n\tChris Huang"
"\nCreated April 2003.");

GtkWidget* OK_Button = gtk_button_new_with_label ("OK");
g_signal_connect_swapped (G_OBJECT (OK_Button), "clicked",
G_CALLBACK (gtk_widget_destroy), G_OBJECT (dialog));

gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), image, TRUE, TRUE, 3);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), label, TRUE, TRUE, 3);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), OK_Button, TRUE, TRUE, 3);
gtk_widget_show (image);
gtk_widget_show (label);
gtk_widget_show (OK_Button);
gtk_widget_show (dialog);
}

/* Callback for changing position on screen */
void move_callback ( gpointer window, guint moveTo, GtkWidget* menu) {
}


/* Quit procedure: end magnification, end GUI */
void quit_callback (gpointer window, guint action, GtkWidget* menu ) {
killMag();
gtk_widget_destroy (GTK_WIDGET (window));
}

/* Termination */
gboolean delete_event( GtkWidget *widget,
GdkEvent *event,
gpointer data ){
gtk_main_quit ();
return FALSE;
}


/***************************/
/* Magnification Functions */
/***************************/


//Initialize magnification window
void setupMag() {
int screen;
XWindowAttributes xwa;

// variables for obtaining data about windows hierarchy
Window root_return;
int x_return, y_return;
unsigned int border_width_return, depth_return;

//variables for getting all children windows of root
//and moving/resizing them so not under biggifier
Window parent_return;
Window *children;
int num_children, n;
int safe_y,sib_width, sib_height;
unsigned int safe_height;

//connect to the X server
display = XOpenDisplay ("");
if (display == NULL) {
fprintf (stderr, "cannot connect to server\n");
exit (EXIT_FAILURE);
}

//get default screen
screen = DefaultScreen (display);

//get black and white representation on current screen
background = WhitePixel (display, screen);
foreground = BlackPixel (display, screen);

//get root window
root = DefaultRootWindow(display);

//set up gc based on root window
XGetWindowAttributes (display, root, &xwa);
root_width = xwa.width;
root_height = xwa.height;
root_depth = xwa.depth;
gc = XCreateGC(display, root, 0, NULL);

//create window to hold magnified view
win_width = root_width;
old_width = win_width;
win_height = root_width/6;
old_height = win_height;
window = XCreateSimpleWindow (display,
root, 0, 0, win_width, win_height, 2,
foreground, background);

//initialize variables needed for magnification loop
tmp_image_border = 50;
mag_image = XGetImage(display, root, 0, 0, win_width,
win_height, ~0L, ZPixmap);
tmp_image = XGetImage(display, root, 0, 0,
win_width + ( 2 * tmp_image_border ),
win_height + ( 2 * tmp_image_border ),
~0L, ZPixmap);

//set up restore
setupRestore();

//get child windows of root and resize/move them so
//not behind biggifier
XQueryTree(display, root, &root_return,
&parent_return, &children, &num_children);
XFree(children);
safe_y = win_height + 30; //integer a fudge factor so entire window visible
safe_height = root_height - safe_y;
for(n=0; n<num_children; n++) {
//updates info so doesn't crash if another
//program closed while looping through and
//moving things
XQueryTree(display, root, &root_return,
&parent_return, &children, &num_children);
XGetGeometry(display, children[n], &root_return,
&x_return, &y_return, &sib_width,
&sib_height, &border_width_return,
&depth_return);
if((children[n] != window) && //so doesn't try to resize ibiggifier
(y_return < win_height) //so only resizes things behind biggifier
) {
if(sib_height > safe_height)
XMoveResizeWindow(display, children[n],
x_return, safe_y, sib_width,
safe_height);
else
XMoveResizeWindow(display, children[n],
x_return, safe_y, sib_width,
sib_height);
}
XFree(children);
}

/* pop this window up on the screen */
XMapWindow(display, window);

//wait for MapNotifyEvent, signal that ll is ready
XSelectInput(display, window, StructureNotifyMask);
for(;;) {
XEvent e;
XNextEvent(display, &e);
if(e.type == MapNotify)
break;
}
}//end setupMag
// variables for obtaining data about windows hierarchy
void magnify(guint* zoom_level) {
static XImage *screen_shot; // stores the image grabbed from the screen

// variables for obtaining data about windows hierarchy
Window root_return;
int x_return, y_return;
unsigned int border_width_return, depth_return;

//variables for getting mouse position and zooming in re
Window r, w;
int r_xpos, r_ypos, w_xpos, w_ypos;
unsigned int mask_return;
int x, y;
int zoom = *zoom_level;

//variables for finding cursor pos in magnified view
int cur_xpos, cur_ypos, tmp_xpos, tmp_ypos;

//variables for getting all children windows of root
//and moving/resizing them so not under biggifier
Window parent_return;
Window *children;
int num_children, n;
int safe_y,sib_width, sib_height;
unsigned int safe_height;

//move to top of screen
XMoveWindow(display, window, 0, 0);

//get child windows of root and resize/move them so
//not behind biggifier
XQueryTree(display, root, &root_return,
&parent_return, &children, &num_children);
XFree(children);
safe_y = win_height + 30; //integer a fudge factor so entire window visible
safe_height = root_height - safe_y;
for(n=0; n<num_children; n++) {
//updates info so doesn't crash if another
//program closed while looping through and
//moving things
XQueryTree(display, root, &root_return,
&parent_return, &children, &num_children);
XGetGeometry(display, children[n], &root_return,
&x_return, &y_return, &sib_width,
&sib_height, &border_width_return,
&depth_return);
if((children[n] != window) && //so doesn't try to resize ibiggifier
((sib_width != root_width) && //so doesn't try to resize desktop
(sib_height != root_height)) &&
(y_return < win_height) //so only resizes things behind biggifier
) {
if(sib_height > safe_height)
XMoveResizeWindow(display, children[n],
x_return, safe_y, sib_width,
safe_height);
else
XMoveResizeWindow(display, children[n],
x_return, safe_y, sib_width,
sib_height);
}
XFree(children);
}

//change neccessary values if user resizes window
XGetGeometry(display, window, &root_return, &x_return, &y_return, &win_width, &win_height, &border_width_return, &depth_return);
if(!(win_width == old_width) || !(win_height == old_height)) {
XFree(mag_image);
mag_image = XGetImage(display, root, 0, 0, win_width, win_height, ~0L, ZPixmap);
old_width = win_width;
old_height = win_height;
}

//get mouse position
XQueryPointer(display, window, &r, &w, &r_xpos, &r_ypos, &w_xpos, &w_ypos, &mask_return);

//get coordinates of upper left corner of box cenetered at cursor
x = r_xpos - win_width/(2*zoom);
y = r_ypos - win_height/(2*zoom);

//grab a portion of the screen around cursor making sure not to try to get coordinates outside of root window
if(x < 0)
x = 0;
else if(x > root_width - win_width/zoom)
x = root_width - win_width/zoom;
if(y < safe_y)
y = safe_y;
else if(y > root_height - win_height/zoom)
y = root_height - win_height/zoom;
screen_shot = XGetImage(display, root, x, y, win_width/zoom, win_height/zoom, ~0L, ZPixmap);

//put in cross-hairs for cursor
cur_xpos = r_xpos - x;
cur_ypos = r_ypos - y;
// variables for obtaining data about windows hierarchyXPutPixel(screen_shot, cur_xpos, cur_ypos, background);

//put in horizontal part
tmp_xpos = cur_xpos + 1;
tmp_ypos = cur_ypos;
if((tmp_xpos >= 0) && (tmp_xpos <= win_width/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, foreground);
tmp_xpos = cur_xpos + 2;
if((tmp_xpos >= 0) && (tmp_xpos <= win_width/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, foreground);
tmp_xpos = cur_xpos + 3;
if((tmp_xpos >= 0) && (tmp_xpos <= win_width/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, foreground);
tmp_xpos = cur_xpos + 4;
if((tmp_xpos >= 0) && (tmp_xpos <= win_width/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, background);
tmp_xpos = cur_xpos - 1;
if((tmp_xpos >= 0) && (tmp_xpos <= win_width/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, foreground);
tmp_xpos = cur_xpos - 2;
if((tmp_xpos >= 0) && (tmp_xpos <= win_width/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, foreground);
tmp_xpos = cur_xpos - 3;
if((tmp_xpos >= 0) && (tmp_xpos <= win_width/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, foreground);
tmp_xpos = cur_xpos - 4;
if((tmp_xpos >= 0) && (tmp_xpos <= win_width/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, background);

//put in vertical part of cross-hair
tmp_xpos = cur_xpos;
tmp_ypos = cur_ypos + 1;
if((tmp_ypos >= 0) && (tmp_ypos < win_height/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, foreground);
tmp_ypos = cur_ypos + 2;
if((tmp_ypos >= 0) && (tmp_ypos < win_height/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, foreground);
tmp_ypos = cur_ypos + 3;
if((tmp_ypos >= 0) && (tmp_ypos < win_height/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, foreground);
tmp_ypos = cur_ypos + 4;
if((tmp_ypos >= 0) && (tmp_ypos < win_height/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, background);
tmp_ypos = cur_ypos - 1;
if((tmp_ypos >= 0) && (tmp_ypos < win_height/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, foreground);
tmp_ypos = cur_ypos - 2;
if((tmp_ypos >= 0) && (tmp_ypos < win_height/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, foreground);
tmp_ypos = cur_ypos - 3;
if((tmp_ypos >= 0) && (tmp_ypos < win_height/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, foreground);
tmp_ypos = cur_ypos - 4;
if((tmp_ypos >= 0) && (tmp_ypos < win_height/zoom))
XPutPixel(screen_shot, tmp_xpos, tmp_ypos, background);

//magnify image
MagXImage(screen_shot, win_width/zoom, win_height/zoom, mag_image, zoom);

//display image
XPutImage(display, window, gc, mag_image, 0, 0, 0, 0, win_width, win_height);

XFree(screen_shot);

//keep window on top
XRaiseWindow(display, window);

/* flush X request queue to server */
XFlush (display);
}//end magnify

void killMag() {
restore();
XDestroyWindow(display, window);
XCloseDisplay (display);
}//end killMag

void MagXImage(XImage *x1, int width, int height, XImage *x2, int z) {
int x, y, i, j;
unsigned long pix;
for(x=0; x<width; x++)
for(y=0; y<height; y++) {
pix = XGetPixel(x1, x, y);
for(i=x*z; i<(x+1)*z; i++)
for(j=y*z; j<(y+1)*z; j++) {
XPutPixel(x2, i, j, pix);
}
}
}//end MagXImage

void setupRestore() {
WindowSave *new_win; // stores attributes of a window before Biggifier executed

// variables for obtaining data about windows hierarchy
Window root_return;
int x_return, y_return;
unsigned int border_width_return, depth_return;

//variables for getting all children windows of root
//and moving/resizing them so not under biggifier
Window parent_return;
Window *children;
int num_children, n;
int sib_width, sib_height;

head = NULL;

//save positions/sizes of all windows open before biggifier in WindowSave structs
XQueryTree(display, root, &root_return,
&parent_return, &children, &num_children);
XFree(children);
for(n=0; n<num_children; n++) {
//updates info so doesn't crash if another
//program closed while looping through and
//moving things
XQueryTree(display, root, &root_return,
&parent_return, &children, &num_children);
XGetGeometry(display, children[n], &root_return,
&x_return, &y_return, &sib_width,
&sib_height, &border_width_return,
&depth_return);
if(children[n] != window) {
new_win = (WindowSave *)malloc(sizeof(WindowSave));
new_win->x = x_return;
new_win->y = y_return;
new_win->width = sib_width;
new_win->height = sib_height;
new_win->id = children[n];
new_win->next = head;
head = new_win;
}
XFree(children);
}
}//end setupRestore

void restore() {
WindowSave *win; // used to retrieve attributes of a window before Biggifier executed

// variables for obtaining data about windows hierarchy
Window root_return;

//variables for getting all children windows of root
//and moving/resizing them so not under biggifier
Window parent_return;
Window *children;
int num_children;

win = head;

//reset size/position of windows that were open before biggifier
while(win != NULL) {
XQueryTree(display, root, &root_return,
&parent_return, &children, &num_children);
if(contains(children, num_children, win->id))
XMoveResizeWindow(display, win->id, win->x, win->y, win->width, win->height);
win = win->next;
XFree(children);
}
}//end restore

int contains(Window wins[], unsigned int children, Window id) {
int n, return_value;
return_value = 0;
for(n=0; n<children; n++) {
if(wins[n] == id)
return_value = 1;
}
return return_value;
}//end contains