/*  Gnometab -- a guitar tablature editor for GNOME
    Copyright (C) 2001  William L. Guelker

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <math.h>
#include <string.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <gnome.h>
#include "tab_canvas.h"
#include "tab_doc.h"
#include "interface.h"
#include "tab_objects.h"

static gboolean
validate_coords(gint staff, double x, double y)
{
    if (x < 50 || x > 740) return FALSE;
        
    
    switch (staff) {
        case 0:
            if (y <= 220 && y > 150) return TRUE;
            break;
        case 1:
            if (y <= 360 && y > 290) return TRUE;
            break;
        case 2:
            if (y <= 500 && y > 430) return TRUE;
            break;
        case 3:
            if (y <= 640 && y > 570) return TRUE;
            break;
        case 4:
            if (y <= 780 && y > 710) return TRUE;
            break;
        case 5:
            if (y <= 920 && y > 850) return TRUE;
            break;
        default:
            break;
    }
    return FALSE;
}

void 
create_text_entry_widget(GtabDoc *tab_doc, double x, double y)
{
    GtkWidget *num_entry;
    GtabChordLib *lib;
        
    lib = (GtabChordLib *)tab_doc->parent->chord_lib;
    
    find_staff(y);
        
    num_entry = gtk_entry_new();
    gtk_entry_set_max_length(GTK_ENTRY(num_entry), 2);
    
    cvs_num_entry = gnome_canvas_item_new
                        (tab_doc->staff_objects[current_staff],
                        gnome_canvas_widget_get_type(),
                        "widget", num_entry,
                        "x", x,
                        "y", y,
                        "anchor", GTK_ANCHOR_NORTH_WEST,
                        "width", 20.0,
                        "height", 20.0,
                        "size_pixels", TRUE,
                        NULL);
    gtk_entry_set_has_frame(GTK_ENTRY(num_entry), FALSE);
    
    g_signal_connect(GTK_OBJECT(num_entry),
                        "key_press_event",
                        (GtkSignalFunc) num_entry_key_press,
                        tab_doc);

    gtk_widget_show(num_entry);
    gtk_widget_grab_focus(num_entry);
    tab_doc->parent->current_tool = TOOL_TEXT_ENTRY;
    gtk_widget_set_sensitive(GTK_WIDGET(tab_doc->parent->toolmenu), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(tab_doc->parent->toolbox), FALSE);
    if (lib->visible) 
        gtk_widget_set_sensitive(GTK_WIDGET(lib->lib_canvas), FALSE);
    
    num_entry_bool = TRUE;
}

gint
num_entry_key_press(GtkWidget *num_entry, GdkEventKey *event, GtabDoc *tab_doc)
{
    double cvs_x;
    double cvs_y;
    gchar  text[6];
    xmlNodePtr tab_text_xml;
    GnomeCanvasItem *staff_item;
    double x1, y1, x2, y2;
    PangoFontDescription *font_string;
    GtabChordLib *lib;
    
    lib = (GtabChordLib *)tab_doc->parent->chord_lib;
    
    switch (event->keyval) {
        case GDK_Return:
            g_snprintf(text, 3, "%s", 
                gtk_entry_get_text(GTK_ENTRY(num_entry)));
    
            g_object_get(GTK_OBJECT(cvs_num_entry),
                            "x", &cvs_x,
                            "y", &cvs_y,
                            NULL);
        
            find_staff(cvs_y);
        
            gtk_object_destroy(GTK_OBJECT(cvs_num_entry));
                
            if (strlen(text) >= 1)    {
                
                font_string = pango_font_description_from_string(tab_doc->parent->tab_font);
                
                staff_item = gnome_canvas_item_new(tab_doc->staff_objects[current_staff], 
                                                gnome_canvas_text_get_type(),
                                                "text", text,
                                                "x", cvs_x,
                                                "y", cvs_y + 3.0,
                                                "anchor", GTK_ANCHOR_NORTH_WEST,
                                                "font_desc", font_string,
                                                "fill_color", "black",
                                                NULL);
            
                count_object(tab_doc, staff_item);
        
                gnome_canvas_item_get_bounds(staff_item, &x1, &y1, &x2, &y2);
                    
                tab_text_xml = xmlNewChild(tab_doc->staff_nodes[current_staff], NULL, 
                                                            "tab_text", NULL);
                                                            
                xmlSetProp(tab_text_xml, "text", text);
                xmlSetProp(tab_text_xml, "x1", float_to_char(x1));
                xmlSetProp(tab_text_xml, "y1", float_to_char(y1));
                xmlSetProp(tab_text_xml, "x2", float_to_char(x2));
                xmlSetProp(tab_text_xml, "y2", float_to_char(y2));
                xmlSetProp(tab_text_xml, "x_create", float_to_char(cvs_x));
                xmlSetProp(tab_text_xml, "y_create", float_to_char(cvs_y + 8));
                
                g_signal_connect(GTK_OBJECT(staff_item), "event", 
                                    (GtkSignalFunc) staff_object_event, tab_doc);
                g_object_set_data(G_OBJECT(staff_item), "node", tab_text_xml);
                pango_font_description_free(font_string);
                tab_doc->changed = TRUE;
            }
            num_entry_bool = FALSE;
            
            if (validate_coords(current_staff, cvs_x + 17.0, cvs_y)) {
                create_text_entry_widget(tab_doc, (cvs_x + 17.0), cvs_y);
            }
            else {
                create_text_entry_widget(tab_doc, cvs_x, cvs_y);
            }
            return (TRUE);
            break;
        case GDK_Escape:
            gtk_object_destroy(GTK_OBJECT(cvs_num_entry));
            num_entry_bool = FALSE;
            
            gnome_appbar_set_status(GNOME_APPBAR(tab_doc->parent->appbar), 
                                        "Current Tool: Text Entry");
            gtk_widget_set_sensitive(GTK_WIDGET(tab_doc->parent->toolmenu), TRUE);
            gtk_widget_set_sensitive(GTK_WIDGET(tab_doc->parent->toolbox), TRUE);
            if (lib->visible)
                gtk_widget_set_sensitive(GTK_WIDGET(lib->lib_canvas), TRUE);
            tab_doc->parent->current_tool = TOOL_NUM;
            return (TRUE);
            break;
        case GDK_Down:
            g_object_get(GTK_OBJECT(cvs_num_entry),
                            "x", &cvs_x,
                            "y", &cvs_y,
                            NULL);
        
            gtk_object_destroy(GTK_OBJECT(cvs_num_entry));
        
            find_staff(cvs_y);
        
            if (validate_coords(current_staff, cvs_x, cvs_y + 12.0)) {
                create_text_entry_widget(tab_doc, cvs_x, cvs_y + 12.0);
            }
            else {
                create_text_entry_widget(tab_doc, cvs_x, cvs_y);
            }
            
            return(TRUE);
            break;
        case GDK_Up:
            g_object_get(GTK_OBJECT(cvs_num_entry),
                            "x", &cvs_x,
                            "y", &cvs_y,
                            NULL);
            gtk_object_destroy(GTK_OBJECT(cvs_num_entry));
        
            find_staff(cvs_y);
            
            if (validate_coords(current_staff, cvs_x, cvs_y - 12.0)) {
                create_text_entry_widget(tab_doc, cvs_x, cvs_y - 12.0);
            }
            else {
                create_text_entry_widget(tab_doc, cvs_x, cvs_y);
            }
            
            return(TRUE);
            break;
        case GDK_Left:
            g_object_get(GTK_OBJECT(cvs_num_entry),
                            "x", &cvs_x,
                            "y", &cvs_y,
                            NULL);
            gtk_object_destroy(GTK_OBJECT(cvs_num_entry));
        
            find_staff(cvs_y);
        
            if (validate_coords(current_staff, cvs_x - 17.0, cvs_y)) {
                create_text_entry_widget(tab_doc, cvs_x - 17.0, cvs_y);
            }
            else {
                create_text_entry_widget(tab_doc, cvs_x, cvs_y);
            }
            
            return(TRUE);
            break;
        case GDK_Right:
            g_object_get(GTK_OBJECT(cvs_num_entry),
                            "x", &cvs_x,
                            "y", &cvs_y,
                            NULL);
            gtk_object_destroy(GTK_OBJECT(cvs_num_entry));
            
            find_staff(cvs_y);
        
            if (validate_coords(current_staff, cvs_x + 17.0, cvs_y)) {
                create_text_entry_widget(tab_doc, cvs_x + 17.0, cvs_y);
            }
            else {
                create_text_entry_widget(tab_doc, cvs_x, cvs_y);
            }
            
            return(TRUE);
            break;
        default:
            return (FALSE);
            break;
        }
}

void
create_bend(GtabDoc *tab_doc, double x, double y)
{
    GnomeCanvasItem *new_bend;
    GnomeCanvasPoints *points;
    xmlNodePtr tab_bend_xml;
    double start_x;
    double start_y;
    double x1, y1, x2, y2;
    
    find_staff(y);
    
    start_y = y - 2.0;
    start_x = x + 5.0;
    
    points = gnome_canvas_points_new(4);

    points->coords[0] = start_x;
    points->coords[1] = start_y;
    points->coords[2] = start_x + 4.0;
    points->coords[3] = start_y - 2.0;
    points->coords[4] = start_x + 8.0;
    points->coords[5] = start_y - 6.0;
    points->coords[6] = start_x + 10.0;
    points->coords[7] = start_y - 12.0;
    
    new_bend = gnome_canvas_item_new(tab_doc->staff_objects[current_staff],
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "navy blue",
                                    "width_pixels", 1,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", TRUE,
                                    "smooth", TRUE,
                                    "spline_steps", 8,    
                                    "arrow_shape_a", 4.0,
                                    "arrow_shape_b", 6.0,
                                    "arrow_shape_c", 4.0,  
                                    NULL);
    
    count_object(tab_doc, new_bend);
    
    gnome_canvas_points_unref(points);

    gnome_canvas_item_get_bounds(new_bend, &x1, &y1, &x2, &y2);
        
    tab_bend_xml = xmlNewChild(tab_doc->staff_nodes[current_staff], NULL, 
                                                "tab_bend", NULL);
                                                
    xmlSetProp(tab_bend_xml, "x1", float_to_char(x1));
    xmlSetProp(tab_bend_xml, "y1", float_to_char(y1));
    xmlSetProp(tab_bend_xml, "x2", float_to_char(x2));
    xmlSetProp(tab_bend_xml, "y2", float_to_char(y2));
    xmlSetProp(tab_bend_xml, "x_create", float_to_char(x));
    xmlSetProp(tab_bend_xml, "y_create", float_to_char(y));

    g_signal_connect(GTK_OBJECT(new_bend), "event", 
                        (GtkSignalFunc) staff_object_event, tab_doc);
    g_object_set_data(G_OBJECT(new_bend), "node", tab_bend_xml);
    tab_doc->changed = TRUE;
    set_title(tab_doc);
}

void 
create_slur(GtabDoc *tab_doc, double x, double y, 
            gint slur_type, gint positions)
{
    GnomeCanvasGroup *slur_group;
    GnomeCanvasItem *new_slur;
    GnomeCanvasPoints *points;
    xmlNodePtr tab_slur_xml;
    PangoFontDescription *font_string;
    double start_x;
    double start_y;
    double total_length;
    double x1, y1, x2, y2;
    
    find_staff(y);
    
    start_x = x;
    start_y = y - 5.0;
    total_length = 12*positions;
    
    points = gnome_canvas_points_new(6);

    points->coords[0] = start_x;
    points->coords[1] = start_y;
    points->coords[2] = start_x + (total_length/5.0);
    points->coords[3] = start_y - 4.0;
    points->coords[4] = start_x + 2*(total_length/5.0);
    points->coords[5] = start_y - 6.0;
    points->coords[6] = start_x + 3*(total_length/5.0);
    points->coords[7] = start_y - 6.0;
    points->coords[8] = start_x + 4*(total_length/5.0);
    points->coords[9] = start_y - 4.0;
    points->coords[10] = start_x + 5*(total_length/5.0);
    points->coords[11] = start_y;
    
    font_string = pango_font_description_from_string(tab_doc->parent->tab_font_tiny);
    
    slur_group = GNOME_CANVAS_GROUP(gnome_canvas_item_new
                                    (tab_doc->staff_objects[current_staff], 
                                        gnome_canvas_group_get_type(),
                                        NULL));
                                                                    
    new_slur = gnome_canvas_item_new(slur_group,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "navy blue",
                                    "width_pixels", 1,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "smooth", TRUE,
                                    "spline_steps", 8,    
                                    NULL);

    switch (slur_type)    {
        case SLUR_HAMMER:
            new_slur = gnome_canvas_item_new(slur_group,
                                            gnome_canvas_text_get_type(),
                                            "text", "h",
                                            "x", start_x + (total_length/2),
                                            "y", start_y - 8.0,
                                            "anchor", GTK_ANCHOR_SOUTH,
                                            "font_desc", font_string,
                                            "fill_color", "navy blue",
                                            NULL);
            break;
        case SLUR_PULLOFF:
            new_slur = gnome_canvas_item_new(slur_group,
                                            gnome_canvas_text_get_type(),
                                            "text", "p",
                                            "x", start_x + (total_length/2),
                                            "y", start_y - 8.0,
                                            "anchor", GTK_ANCHOR_SOUTH,
                                            "font_desc", font_string,
                                            "fill_color", "navy blue",
                                            NULL);
            break;
        
        case SLUR_SLIDE:
            new_slur = gnome_canvas_item_new(slur_group,
                                            gnome_canvas_text_get_type(),
                                            "text", "sl",
                                            "x", start_x + (total_length/2),
                                            "y", start_y - 8.0,
                                            "anchor", GTK_ANCHOR_SOUTH,
                                            "font_desc", font_string,
                                            "fill_color", "navy blue",
                                            NULL);
            break;
        case SLUR_TRILL:
            /* TODO: the right thing here */
        
            break;
        default:
            break;
    }
    
    count_object(tab_doc, GNOME_CANVAS_ITEM(slur_group));
    
    gnome_canvas_points_unref(points);

    gnome_canvas_item_get_bounds(GNOME_CANVAS_ITEM(slur_group), 
                                &x1, &y1, &x2, &y2);
    
    tab_slur_xml = xmlNewChild(tab_doc->staff_nodes[current_staff], NULL, 
                                                "tab_slur", NULL);
    
    xmlSetProp(tab_slur_xml, "x1", float_to_char(x1));
    xmlSetProp(tab_slur_xml, "y1", float_to_char(y1));
    xmlSetProp(tab_slur_xml, "x2", float_to_char(x2));
    xmlSetProp(tab_slur_xml, "y2", float_to_char(y2));
    xmlSetProp(tab_slur_xml, "x_create", float_to_char(x));
    xmlSetProp(tab_slur_xml, "y_create", float_to_char(y));
    xmlSetProp(tab_slur_xml, "positions", int_to_char(positions));
    xmlSetProp(tab_slur_xml, "type", int_to_char(slur_type));
    
    g_signal_connect(GTK_OBJECT(slur_group), "event", 
                        (GtkSignalFunc) staff_object_event, tab_doc);
    g_object_set_data(G_OBJECT(slur_group), "node", tab_slur_xml);
    
    pango_font_description_free(font_string);
    tab_doc->changed = TRUE;
    set_title(tab_doc);
}

void 
create_bar(GtabDoc *tab_doc, double x, double y, gint bar_size)
{
    GnomeCanvasItem *new_bar;
    GnomeCanvasPoints *points;
    xmlNodePtr tab_bar_xml;
    double start_x;
    double start_y;
    double total_length;
    double x1, y1, x2, y2;
    
    find_staff(y);
    
    start_x = x;
    start_y = y + 5.0;
    total_length = 12*bar_size;

    points = gnome_canvas_points_new(6);

    points->coords[0] = start_x;
    points->coords[1] = start_y;
    points->coords[2] = start_x - 4.0;
    points->coords[3] = start_y - (total_length/5);
    points->coords[4] = start_x - 6.0;
    points->coords[5] = start_y - 2*(total_length/5);
    points->coords[6] = start_x - 6.0;
    points->coords[7] = start_y - 3*(total_length/5);
    points->coords[8] = start_x - 4.0;
    points->coords[9] = start_y - 4*(total_length/5);
    points->coords[10] = start_x;
    points->coords[11] = start_y - 5*(total_length/5);

    new_bar = gnome_canvas_item_new(tab_doc->staff_objects[current_staff],
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "navy blue",
                                    "width_pixels", 1,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "smooth", TRUE,
                                    "spline_steps", 8,    
                                    NULL);

    count_object(tab_doc, new_bar);
    
    gnome_canvas_points_unref(points);

    gnome_canvas_item_get_bounds(new_bar, &x1, &y1, &x2, &y2);
    
    tab_bar_xml = xmlNewChild(tab_doc->staff_nodes[current_staff], NULL, 
                                                "tab_bar", NULL);
                                                
    xmlSetProp(tab_bar_xml, "x1", float_to_char(x1));
    xmlSetProp(tab_bar_xml, "y1", float_to_char(y1));
    xmlSetProp(tab_bar_xml, "x2", float_to_char(x2));
    xmlSetProp(tab_bar_xml, "y2", float_to_char(y2));
    xmlSetProp(tab_bar_xml, "x_create", float_to_char(x));
    xmlSetProp(tab_bar_xml, "y_create", float_to_char(y));
    xmlSetProp(tab_bar_xml, "bar_size", int_to_char(bar_size));
    
    g_signal_connect(GTK_OBJECT(new_bar), "event", 
                        (GtkSignalFunc) staff_object_event, tab_doc);
    g_object_set_data(G_OBJECT(new_bar), "node", tab_bar_xml);
    tab_doc->changed = TRUE;
    set_title(tab_doc);
}

void
create_text(GtabDoc *tab_doc, double x, double y, gchar *text)
{
    xmlNodePtr tab_text_xml;
    GnomeCanvasItem *staff_item;
    double x1, y1, x2, y2;
    PangoFontDescription *font_string;
    
    find_staff(y);
    
    font_string = pango_font_description_from_string(tab_doc->parent->tab_font);

    staff_item = gnome_canvas_item_new(tab_doc->staff_objects[current_staff], 
                                        gnome_canvas_text_get_type(),
                                        "text", text,
                                        "x", x,
                                        "y", (y - 5.0),
                                        "anchor", GTK_ANCHOR_NORTH_WEST,
                                        "font_desc", font_string,
                                        "fill_color", "black",
                                        NULL);

    count_object(tab_doc, staff_item);
    gnome_canvas_item_get_bounds(staff_item, &x1, &y1, &x2, &y2);
    gnome_canvas_update_bbox(staff_item, (int) x1, (int) y1, (int) x2, (int) y2);
    tab_text_xml = xmlNewChild(tab_doc->staff_nodes[current_staff], NULL, 
                                                "tab_text", NULL);
    xmlSetProp(tab_text_xml, "x1", float_to_char(x1));
    xmlSetProp(tab_text_xml, "y1", float_to_char(y1));
    xmlSetProp(tab_text_xml, "x2", float_to_char(x2));
    xmlSetProp(tab_text_xml, "y2", float_to_char(y2));
    xmlSetProp(tab_text_xml, "x_create", float_to_char(x));
    xmlSetProp(tab_text_xml, "y_create", float_to_char(y));
    xmlSetProp(tab_text_xml, "text", text);
    
    g_signal_connect(GTK_OBJECT(staff_item), "event", 
                        (GtkSignalFunc) staff_object_event, tab_doc);
    g_object_set_data(G_OBJECT(staff_item), "node", tab_text_xml);

    pango_font_description_free(font_string);
    tab_doc->changed = TRUE;
    set_title(tab_doc);
}

void 
create_measure(GtabDoc *tab_doc, double x, double y)
{
    GnomeCanvasItem *new_measure;
    GnomeCanvasPoints *points;
    xmlNodePtr tab_measure_xml;
    double start_x;
    double start_y;
    double x1, y1, x2, y2;
    
    find_staff(y);
    
    start_x = x;
    start_y = (ceil(y/140))*140 - 60.0; /* moves y to bottom of staff */
    

    points = gnome_canvas_points_new(2);

    points->coords[0] = start_x;
    points->coords[1] = start_y;
    points->coords[2] = start_x;
    points->coords[3] = start_y - 60.0;
    
    new_measure = gnome_canvas_item_new(tab_doc->staff_objects[current_staff],
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 1,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "smooth", TRUE,
                                    "spline_steps", 8,    
                                    NULL);

    count_object(tab_doc, new_measure);
                                
    gnome_canvas_points_unref(points);

    gnome_canvas_item_get_bounds(new_measure, &x1, &y1, &x2, &y2);
    
    tab_measure_xml = xmlNewChild(tab_doc->staff_nodes[current_staff], NULL, 
                                                "tab_measure", NULL);
    xmlSetProp(tab_measure_xml, "x1", float_to_char(x1));
    xmlSetProp(tab_measure_xml, "y1", float_to_char(y1));
    xmlSetProp(tab_measure_xml, "x2", float_to_char(x2));
    xmlSetProp(tab_measure_xml, "y2", float_to_char(y2));
    xmlSetProp(tab_measure_xml, "x_create", float_to_char(x));
    xmlSetProp(tab_measure_xml, "y_create", float_to_char(y));
    
    g_signal_connect(GTK_OBJECT(new_measure), "event", 
                        (GtkSignalFunc) staff_object_event, tab_doc);
    g_object_set_data(G_OBJECT(new_measure), "node", tab_measure_xml);
    tab_doc->changed = TRUE;
    set_title(tab_doc);
}

void 
create_repeat_bar(GtabDoc *tab_doc, double x, double y, gboolean close)
{
    GnomeCanvasGroup *new_repeat_bar;
    GnomeCanvasItem *repeat_element;
    
    GnomeCanvasPoints *points;
    xmlNodePtr tab_repeat_xml;
    double start_x;
    double start_y;
    double x1, y1, x2, y2;
    
    find_staff(y);
    
    start_x = x;
    start_y = (ceil(y/140))*140 - 60.0; /* moves y to bottom of staff */
    

    points = gnome_canvas_points_new(2);

    points->coords[0] = start_x;
    points->coords[1] = start_y;
    points->coords[2] = start_x;
    points->coords[3] = start_y - 60.0;
    
    new_repeat_bar = GNOME_CANVAS_GROUP(gnome_canvas_item_new
                                        (tab_doc->staff_objects[current_staff],
                                        gnome_canvas_group_get_type(),
                                        NULL));
                                                                                    
    repeat_element = gnome_canvas_item_new(new_repeat_bar,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 1,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "smooth", TRUE,
                                    "spline_steps", 8,    
                                    NULL);

    points->coords[0] = points->coords[0] + 4.0;
    points->coords[2] = points->coords[2] + 4.0;

    repeat_element = gnome_canvas_item_new(new_repeat_bar,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 1,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "smooth", TRUE,
                                    "spline_steps", 8,    
                                    NULL);
    
    if (close == TRUE)    {
        points->coords[0] = points->coords[0] - 8.0;
        points->coords[2] = points->coords[2] - 6.0;
    }
    else    {
        points->coords[0] = points->coords[0] + 2.0;
        points->coords[2] = points->coords[2] + 4.0;
    }
    points->coords[1] = start_y - 28.0;
    points->coords[3] = start_y - 28.0;
    
    repeat_element = gnome_canvas_item_new(new_repeat_bar,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 1,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "smooth", TRUE,
                                    NULL);
        
    points->coords[1] = start_y - 32.0;
    points->coords[3] = start_y - 32.0;
    
    repeat_element = gnome_canvas_item_new(new_repeat_bar,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 1,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "smooth", TRUE,
                                    NULL);                    
                                    
    count_object(tab_doc, GNOME_CANVAS_ITEM(new_repeat_bar));
    gnome_canvas_item_get_bounds(GNOME_CANVAS_ITEM(new_repeat_bar),
                                    &x1, &y1, &x2, &y2);
    gnome_canvas_update_bbox(GNOME_CANVAS_ITEM(new_repeat_bar), 
                                    x1, y1, x2, y2);
    
    gnome_canvas_points_unref(points);

    tab_repeat_xml = xmlNewChild(tab_doc->staff_nodes[current_staff], NULL,
                                                "tab_repeat", NULL);
                                                
    xmlSetProp(tab_repeat_xml, "x1", float_to_char(x1));
    xmlSetProp(tab_repeat_xml, "y1", float_to_char(y1));
    xmlSetProp(tab_repeat_xml, "x2", float_to_char(x2));
    xmlSetProp(tab_repeat_xml, "y2", float_to_char(y2));
    xmlSetProp(tab_repeat_xml, "x_create", float_to_char(x));
    xmlSetProp(tab_repeat_xml, "y_create", float_to_char(y));
    xmlSetProp(tab_repeat_xml, "close", int_to_char(close));
    
    g_signal_connect(GTK_OBJECT(new_repeat_bar), "event", 
                        (GtkSignalFunc) staff_object_event, tab_doc);
    g_object_set_data(G_OBJECT(new_repeat_bar), "node", tab_repeat_xml);
    tab_doc->changed = TRUE;
    set_title(tab_doc);
}

void 
create_legato(GtabDoc *tab_doc, double x, double y, gint leg_size)
{
    GnomeCanvasItem *new_legato;
    GnomeCanvasPoints *points;
    xmlNodePtr tab_legato_xml;
    double start_x;
    double start_y;
    double total_length;
    double x1, y1, x2, y2;
    
    find_staff(y);
    
    start_x = x - 6.0;
    start_y = y + 6.0;
    total_length = 12*leg_size;

    points = gnome_canvas_points_new(21);

    points->coords[0] = start_x;
    points->coords[1] = start_y;
    points->coords[2] = start_x - 1.0;
    points->coords[3] = start_y - (total_length/20);
    points->coords[4] = start_x;
    points->coords[5] = start_y - 2*(total_length/20);
    points->coords[6] = start_x +  1.0;
    points->coords[7] = start_y - 3*(total_length/20);
    points->coords[8] = start_x;
    points->coords[9] = start_y - 4*(total_length/20);
    points->coords[10] = start_x - 1.0;
    points->coords[11] = start_y - 5*(total_length/20);
    points->coords[12] = start_x;
    points->coords[13] = start_y - 6*(total_length/20);
    points->coords[14] = start_x + 1.0;
    points->coords[15] = start_y - 7*(total_length/20);
    points->coords[16] = start_x;
    points->coords[17] = start_y - 8*(total_length/20);
    points->coords[18] = start_x - 1.0;
    points->coords[19] = start_y - 9*(total_length/20);
    points->coords[20] = start_x;
    points->coords[21] = start_y - 10*(total_length/20);
    points->coords[22] = start_x + 1.0;
    points->coords[23] = start_y - 11*(total_length/20);
    points->coords[24] = start_x;
    points->coords[25] = start_y - 12*(total_length/20);
    points->coords[26] = start_x - 1.0;
    points->coords[27] = start_y - 13*(total_length/20);
    points->coords[28] = start_x;
    points->coords[29] = start_y - 14*(total_length/20);
    points->coords[30] = start_x + 1.0;
    points->coords[31] = start_y - 15*(total_length/20);
    points->coords[32] = start_x;
    points->coords[33] = start_y - 16*(total_length/20);
    points->coords[34] = start_x - 1.0;
    points->coords[35] = start_y - 17*(total_length/20);
    points->coords[36] = start_x;
    points->coords[37] = start_y - 18*(total_length/20);
    points->coords[38] = start_x + 1.0;
    points->coords[39] = start_y - 19*(total_length/20);
    points->coords[40] = start_x;
    points->coords[41] = start_y - total_length;
    
    
    

    new_legato = gnome_canvas_item_new(tab_doc->staff_objects[current_staff],
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "navy blue",
                                    "width_pixels", 1,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "smooth", TRUE,
                                    "spline_steps", 1,    
                                    NULL);

    count_object(tab_doc, new_legato);
                                
    gnome_canvas_points_unref(points);

    gnome_canvas_item_get_bounds(new_legato, &x1, &y1, &x2, &y2);
    
    tab_legato_xml = xmlNewChild(tab_doc->staff_nodes[current_staff], NULL, 
                                                "tab_legato", NULL);
    xmlSetProp(tab_legato_xml, "x1", float_to_char(x1));
    xmlSetProp(tab_legato_xml, "y1", float_to_char(y1));
    xmlSetProp(tab_legato_xml, "x2", float_to_char(x2));
    xmlSetProp(tab_legato_xml, "y2", float_to_char(y2));
    xmlSetProp(tab_legato_xml, "x_create", float_to_char(x));
    xmlSetProp(tab_legato_xml, "y_create", float_to_char(y));
    xmlSetProp(tab_legato_xml, "legato_size", int_to_char(leg_size));
    g_signal_connect(GTK_OBJECT(new_legato), "event", 
                        (GtkSignalFunc) staff_object_event, tab_doc);
    g_object_set_data(G_OBJECT(new_legato), "node", tab_legato_xml);
    tab_doc->changed = TRUE;
    set_title(tab_doc);
}


void 
create_strum(GtabDoc *tab_doc, double x, double y, 
                gboolean upstroke, gint size)
{
    GnomeCanvasItem *new_strum;
    GnomeCanvasPoints *points;
    xmlNodePtr tab_strum_xml;
    double start_x;
    double start_y;
    double total_length;
    double x1, y1, x2, y2;
    gboolean down, up;

    find_staff(y);
    
    if (upstroke == TRUE)
    {
        down = FALSE;
        up = TRUE;
    }
    else
    {
        down = TRUE;
        up = FALSE;
    }
    
    start_y = y + 6.0;
    start_x = x + 1.0;
    
    total_length = 12*size - 5;
    points = gnome_canvas_points_new(2);

    points->coords[0] = start_x;
    points->coords[1] = start_y;
    points->coords[2] = start_x;
    points->coords[3] = start_y - total_length;
    
    
    new_strum = gnome_canvas_item_new(tab_doc->staff_objects[current_staff],
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "navy blue",
                                    "width_pixels", 1,
                                    "first_arrowhead", down,
                                    "last_arrowhead", up,
                                    "smooth", TRUE,
                                    "spline_steps", 1,    
                                    "arrow_shape_a", 4.0,
                                    "arrow_shape_b", 6.0,
                                    "arrow_shape_c", 4.0,  
                                    NULL);
    
    count_object(tab_doc, new_strum);
    
    gnome_canvas_points_unref(points);

    gnome_canvas_item_get_bounds(new_strum, &x1, &y1, &x2, &y2);
    
    tab_strum_xml = xmlNewChild(tab_doc->staff_nodes[current_staff], NULL, 
                                                "tab_strum", NULL);
    xmlSetProp(tab_strum_xml, "x1", float_to_char(x1 - 3.5));
    xmlSetProp(tab_strum_xml, "y1", float_to_char(y1));
    xmlSetProp(tab_strum_xml, "x2", float_to_char(x2 + 3.5));
    xmlSetProp(tab_strum_xml, "y2", float_to_char(y2));
    xmlSetProp(tab_strum_xml, "x_create", float_to_char(x));
    xmlSetProp(tab_strum_xml, "y_create", float_to_char(y));
    xmlSetProp(tab_strum_xml, "upstroke", int_to_char(upstroke));
    xmlSetProp(tab_strum_xml, "size", int_to_char(size));
    g_signal_connect(GTK_OBJECT(new_strum), "event", 
                        (GtkSignalFunc) staff_object_event, tab_doc);
    g_object_set_data(G_OBJECT(new_strum), "node", tab_strum_xml);
    tab_doc->changed = TRUE;
    set_title(tab_doc);
}

static void 
create_tab_chord_name(GnomeCanvasGroup *staff_chord, double x, double y, 
                                        gchar *chrdname, xmlNodePtr nw_chrd, 
                                        GtabDoc *tab_doc)
{
    GnomeCanvasItem *grid_item;
    xmlNodePtr chrd_name_xml = NULL;
    PangoFontDescription *font_string;
    
    if (chords_above_staff) {
        font_string = pango_font_description_from_string(tab_doc->parent->tab_font_tiny);
    }
    else {
        font_string = pango_font_description_from_string(tab_doc->parent->tab_font);
    }

    
    grid_item = gnome_canvas_item_new(staff_chord,
                                    gnome_canvas_text_get_type(),
                                    "text", chrdname,
                                    "x", x + 43.0,
                                    "y", y + 12.0,
                                    "anchor", GTK_ANCHOR_SOUTH,
                                    "font_desc", font_string,
                                    "fill_color", "black",
                                    NULL);
    chrd_name_xml = xmlNewChild(nw_chrd, NULL, "chord_name", NULL);
    xmlSetProp(chrd_name_xml, "name_text", chrdname);
    pango_font_description_free(font_string);
}

static void 
create_tab_chord_text(GnomeCanvasGroup *staff_chord, double x, double y, 
                            double grid_x, double grid_y, 
                            xmlNodePtr nw_chrd, gchar *text, GtabDoc *tab_doc)
{
    GnomeCanvasItem *grid_item;
    xmlNodePtr chord_text_xml = NULL;
    double x1, y1, x2, y2;
    PangoFontDescription *font_string;
    
    if (chords_above_staff) {
        font_string = pango_font_description_from_string(tab_doc->parent->tab_font_tiny);
    }
    else {
        if (grid_x >= 84)    {
            font_string = pango_font_description_from_string(tab_doc->parent->tab_font_small);
                    
        }
        else    {
            font_string = pango_font_description_from_string(tab_doc->parent->tab_font);
        }
    }
    
    if (strlen(text) >= 1)    {
        grid_item = gnome_canvas_item_new(staff_chord, 
                                        gnome_canvas_text_get_type(),
                                        "text", text,
                                        "x", x + grid_x,
                                        "y", y + grid_y,
                                        "anchor", GTK_ANCHOR_NORTH_WEST,
                                        "font_desc", font_string,
                                        "fill_color", "firebrick4",
                                        NULL);
    
        gnome_canvas_item_get_bounds(grid_item, &x1, &y1, &x2, &y2);
            
        chord_text_xml = xmlNewChild(nw_chrd, NULL, "chord_text", NULL);
    
        xmlSetProp(chord_text_xml, "text", text);
        xmlSetProp(chord_text_xml, "x1", float_to_char(x1));
        xmlSetProp(chord_text_xml, "y1", float_to_char(y1));
        xmlSetProp(chord_text_xml, "x2", float_to_char(x2));
        xmlSetProp(chord_text_xml, "y2", float_to_char(y2));
        xmlSetProp(chord_text_xml, "x_create", float_to_char(grid_x));
        xmlSetProp(chord_text_xml, "y_create", float_to_char(grid_y - 12.0));
        
    }    
    
    pango_font_description_free(font_string);
}

static void 
create_tab_chord_bar(GnomeCanvasGroup *staff_chord, 
                            double x, double y,
                             double grid_x, double grid_y,    
                            gint positions, xmlNodePtr nw_chrd)
{
    GnomeCanvasItem *new_bar;
    GnomeCanvasPoints *points;
    xmlNodePtr chord_bar_xml;
    double start_x;
    double start_y;
    double total_length;
    double x1, y1, x2, y2;

    start_x = x + grid_x;
    start_y = y + grid_y - 17.0;
    total_length = 12*positions;
    
    points = gnome_canvas_points_new(6);

    points->coords[0] = start_x;
    points->coords[1] = start_y;
    points->coords[2] = start_x + (total_length/5);
    points->coords[3] = start_y - 4.0;
    points->coords[4] = start_x + 2*(total_length/5);
    points->coords[5] = start_y - 6.0;
    points->coords[6] = start_x + 3*(total_length/5);
    points->coords[7] = start_y - 6.0;
    points->coords[8] = start_x + 4*(total_length/5);
    points->coords[9] = start_y - 4.0;
    points->coords[10] = start_x + 5*(total_length/5);
    points->coords[11] = start_y;
    
    new_bar = gnome_canvas_item_new(staff_chord,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "firebrick4",
                                    "width_pixels", 1,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "smooth", TRUE,
                                    "spline_steps", 8,    
                                    NULL);

    gnome_canvas_points_unref(points);

    gnome_canvas_item_get_bounds(new_bar, &x1, &y1, &x2, &y2);
    gnome_canvas_update_bbox(new_bar, (int) x1 + 1, (int) y1 + 1,    
                                        (int) x2 + 1, (int) y2 + 1);
    
    chord_bar_xml = xmlNewChild(nw_chrd, NULL, "chord_bar", NULL);
    xmlSetProp(chord_bar_xml, "x1", float_to_char(x1 + 1.0));
    xmlSetProp(chord_bar_xml, "y1", float_to_char(y1 + 1.0));
    xmlSetProp(chord_bar_xml, "x2", float_to_char(x2 + 1.0));
    xmlSetProp(chord_bar_xml, "y2", float_to_char(y2 + 1.0));
    xmlSetProp(chord_bar_xml, "x_create", float_to_char(grid_x));
    xmlSetProp(chord_bar_xml, "y_create", float_to_char(grid_y - 12.0));
    xmlSetProp(chord_bar_xml, "positions", int_to_char(positions));
}

static void
create_chord_grid(GnomeCanvasGroup *staff_chord, double start_x, double start_y)
{
    GnomeCanvasItem *grid;
    GnomeCanvasPoints *points;
    double x;
      double y;
      gchar outline_color[12];
      
    for (x = start_x + 7.0; x <= start_x + 63.4; x = x + 14.0)    {
        
        for (y = start_y + 12.0; y <= start_y + 72.4; y = y + 12.0)    {
            
            if (y == start_y + 12.0)    {
                g_snprintf(outline_color, 11, "white");
            }
            else    {
                g_snprintf(outline_color, 11, "steel blue");
            }
            
            points = gnome_canvas_points_new(4);
            points->coords[0] = x;
            points->coords[1] = y;
            points->coords[2] = x + 14.0;
            points->coords[3] = y;
            points->coords[4] = x + 14.0;
            points->coords[5] = y + 12.0;
            points->coords[6] = x;
            points->coords[7] = y + 12.0;
            
            grid = gnome_canvas_item_new(staff_chord,
                                     gnome_canvas_polygon_get_type(),
                                     "points", points,
                                     "width_pixels", 1,
                                     "fill_color", "white",
                                     "outline_color", outline_color,
                                      NULL);
            
            gnome_canvas_points_unref(points);
            
            
        }
     }
    
}

void
translate_chord(GtabDoc *tab_doc, double x, double y, xmlDocPtr new_chord_doc)
{
    double grid_x, grid_y, affine_x, affine_y;
    xmlNodePtr nw_node = NULL;
    xmlNodePtr nw_chrd_node = NULL;
    GnomeCanvasGroup *staff_chord;
    gchar *tmp, *char_x, *char_y, *char_int, *char_text;
    double x1, y1, x2, y2;
    const double my_affine[6] = { 0.54, 0, 0, 0.54, 0, 0 };
    
    
    find_staff(y);

    staff_chord = GNOME_CANVAS_GROUP(gnome_canvas_item_new(
                    tab_doc->staff_objects[current_staff], 
                    gnome_canvas_group_get_type(), 
                    NULL));    
    affine_x = x;
    affine_y = y;
    
    if (chords_above_staff) {
        
        gnome_canvas_item_affine_relative(GNOME_CANVAS_ITEM(staff_chord), my_affine);
        affine_y = affine_y - 34.0;
        
        gnome_canvas_item_w2i(GNOME_CANVAS_ITEM(staff_chord), &affine_x, &affine_y);
        
    }
    
    create_chord_grid(staff_chord, affine_x, affine_y);
    
        
    nw_chrd_node = xmlNewChild(tab_doc->staff_nodes[current_staff], 
                                NULL,
                                "tab_chord", 
                                NULL);
    
    for (nw_node = new_chord_doc->xmlRootNode->children; 
            nw_node != NULL; nw_node = nw_node->next)    {
        
        if (xmlIsBlankNode(nw_node) == 1) continue;
            
        tmp = get_prop(nw_node, "active");
                
        if (!tmp)    {
            
            if (g_ascii_strcasecmp(nw_node->name, "chord_text") == 0)    {
                char_x = get_prop(nw_node, "x_create");
                char_y = get_prop(nw_node, "y_create");
                grid_x = atof(char_x);
                grid_y = atof(char_y) + 12.0;
                g_free(char_x);
                g_free(char_y);
                char_text = get_prop(nw_node, "text");
                
                create_tab_chord_text(staff_chord, affine_x, affine_y, grid_x, 
                                            grid_y, nw_chrd_node, char_text,
                                            tab_doc);
                g_free(char_text);
            }
            if (g_ascii_strcasecmp(nw_node->name, "chord_bar") == 0)    {
                char_x = get_prop(nw_node, "x_create");
                char_y = get_prop(nw_node, "y_create");
                grid_x = atof(char_x);
                grid_y = atof(char_y) + 12.0; 
                g_free(char_x);
                g_free(char_y);
                char_int = get_prop(nw_node, "positions");
                create_tab_chord_bar(staff_chord, affine_x, affine_y, grid_x, 
                                        grid_y, atoi(char_int), nw_chrd_node);
                g_free(char_int);
                
            }
            if (g_ascii_strcasecmp(nw_node->name, "chord_name") == 0)    {
                char_text = get_prop(nw_node, "name_text");
                create_tab_chord_name(staff_chord, affine_x, affine_y, 
                                        char_text, nw_chrd_node, tab_doc);
                g_free(char_text);
            }
        }
        g_free(tmp);
        
    }
        
    count_object(tab_doc, GNOME_CANVAS_ITEM(staff_chord));
    
    gnome_canvas_item_get_bounds(GNOME_CANVAS_ITEM(staff_chord), 
                                            &x1, &y1, &x2, &y2);
    
    xmlSetProp(nw_chrd_node, "x1", float_to_char(x1));
    xmlSetProp(nw_chrd_node, "y1", float_to_char(y1));
    xmlSetProp(nw_chrd_node, "x2", float_to_char(x2));
    xmlSetProp(nw_chrd_node, "y2", float_to_char(y2));
    xmlSetProp(nw_chrd_node, "x_create", float_to_char(x));
    xmlSetProp(nw_chrd_node, "y_create", float_to_char(y));
    
    xmlFreeDoc(new_chord_doc);
    g_signal_connect(GTK_OBJECT(staff_chord), "event", 
                        (GtkSignalFunc) staff_object_event, tab_doc);
    g_object_set_data(G_OBJECT(staff_chord), "node", nw_chrd_node);
    tab_doc->changed = TRUE;  
    set_title(tab_doc);
}

static void 
tab_rhythm_vert_line(GtabDoc *tab_doc, GnomeCanvasGroup *rhythm_object, 
                            double start_x, double start_y)
{
    GnomeCanvasPoints *points;
    GnomeCanvasItem *new_rhythm_element;
    gint num_texts = 0;
    gint texts_index = 0;
    double end_y = 0;
    
    g_return_if_fail(start_x > 0);
    g_return_if_fail(GNOME_IS_CANVAS_GROUP(rhythm_object));
    
    find_staff(start_y);
    
    num_texts = find_rhythm_num_segs(tab_doc->staff_nodes[current_staff], start_x);
    
    if (num_texts != 0)    {
        for (texts_index = 0; texts_index < num_texts; texts_index++)    {
            
            end_y = find_rhythm_y2(tab_doc->staff_nodes[current_staff],
                                    start_x, num_texts, texts_index);

            if (end_y != 0)    {
                points = gnome_canvas_points_new(2);
        
                points->coords[0] = start_x;
                points->coords[1] = start_y - 1;
                points->coords[2] = start_x;
                points->coords[3] = end_y - 1;
                    
                new_rhythm_element = gnome_canvas_item_new(rhythm_object,
                                            gnome_canvas_line_get_type(),
                                            "points", points,
                                            "fill_color", "grey30",
                                            "width_pixels", 1,
                                            "first_arrowhead", FALSE,
                                            "last_arrowhead", FALSE,
                                            "smooth", TRUE,
                                            "spline_steps", 8,    
                                            NULL);
                gnome_canvas_points_unref(points);
                start_y = end_y - 12.0;
            }
        }
    }
}

static void
tab_rhythm_horiz_line(GnomeCanvasGroup *rhythm_object,
                           double start_x, double start_y, gboolean complete,
                            gboolean flat, gint direction)
{
    GnomeCanvasPoints *points;
    GnomeCanvasItem *new_rhythm_element;
    double end_x, end_y;
    
    g_return_if_fail(start_x > 0);
    g_return_if_fail(GNOME_IS_CANVAS_GROUP(rhythm_object));
    
    points = gnome_canvas_points_new(2);
    
    switch (direction) {
        case -1:
            end_x = start_x - 4.0;
            end_y = start_y;
            break;
        
        default:
            
            if (complete) {
                end_x = start_x + 17.0;
                end_y = start_y;
            }
            else {
                if (flat) {
                    end_x = start_x + 4.0;
                    end_y = start_y;
                }
                else {
                    end_x = start_x + 4.0;
                    end_y = start_y - 4.0;
                }
            }
            break;
        }
            
    points->coords[0] = start_x;
    points->coords[1] = start_y - 1;
    points->coords[2] = end_x;
    points->coords[3] = end_y - 1;
    new_rhythm_element = gnome_canvas_item_new(rhythm_object,
                                            gnome_canvas_line_get_type(),
                                            "points", points,
                                            "fill_color", "grey30",
                                            "width_pixels", 2,
                                            "first_arrowhead", FALSE,
                                            "last_arrowhead", FALSE,
                                            "smooth", TRUE,
                                            "spline_steps", 8,    
                                            NULL);
    gnome_canvas_points_unref(points);

}

static void 
tab_rhythm_dot(GnomeCanvasGroup *rhythm_object,
                           double start_x, double start_y)
{
    GnomeCanvasPoints *points;
    GnomeCanvasItem *new_rhythm_element;
    double end_x, end_y;

    g_return_if_fail(start_x > 0);
    g_return_if_fail(GNOME_IS_CANVAS_GROUP(rhythm_object));
    
    start_x = start_x + 2.0;
      end_x = start_x + 1.0;
      end_y = start_y;
 
      points = gnome_canvas_points_new(2);
        
    points->coords[0] = start_x;
    points->coords[1] = start_y;
    points->coords[2] = end_x;
    points->coords[3] = end_y;
    new_rhythm_element = gnome_canvas_item_new(rhythm_object,
                                            gnome_canvas_line_get_type(),
                                            "points", points,
                                            "fill_color", "grey30",
                                            "width_pixels", 2,
                                            "first_arrowhead", FALSE,
                                            "last_arrowhead", FALSE,
                                            "smooth", TRUE,
                                            "spline_steps", 8,    
                                            NULL);
    gnome_canvas_points_unref(points);

}

void 
create_tab_rhythm(GtabDoc *tab_doc, Tab_Rhythm rhythm, double x, double y)        
{
    static GnomeCanvasGroup *new_rhythm_group;
    static xmlNodePtr tab_rhythm_xml;
    static xmlNodePtr tab_rhythm_elements[4];
    gdouble x1 = 0;
    gdouble y1 = 0;
    gdouble x2 = 0;
    gdouble y2 = 0;
    gdouble dot_y = 0;
    gboolean flat = FALSE;
    
    find_staff(y);
    switch (current_staff)
    {
        case 1:
            y = 377.0;
            break;
        case 2:
            y = 517.0;
            break;
        case 3:
            y = 657.0;
            break;
        case 4:
            y = 797.0;

            break;
        case 5:
            y = 937.0;
            break;
        default:
            y = 237.0;
            break;
    }
    
    new_rhythm_group = GNOME_CANVAS_GROUP(gnome_canvas_item_new(
                                            tab_doc->staff_objects[current_staff], 
                                                gnome_canvas_group_get_type(), 
                                                NULL));    
    g_return_if_fail(new_rhythm_group != NULL);
    
    /* Here we go -- this is really messy */
    
    dot_y = y;
    
    if (rhythm.pos1.active == TRUE)    {
        
        if (rhythm.pos1.value >= 2) {
            tab_rhythm_vert_line(tab_doc, new_rhythm_group, x, y);
        }
        
        if (rhythm.pos1.value > 4)    {
            if (rhythm.pos2.value > 4 && rhythm.pos2.active == TRUE)    {
                tab_rhythm_horiz_line(new_rhythm_group, x, 
                                                    y, TRUE, TRUE, 1);
                flat = TRUE;
            }
            else    {
                tab_rhythm_horiz_line(new_rhythm_group, x, 
                                                    y, FALSE, FALSE, 1);
            }
        }
        if (rhythm.pos1.value > 8)    {
            dot_y -= 3.0;
            
            if (rhythm.pos2.value > 8 && rhythm.pos2.active == TRUE)    {
                tab_rhythm_horiz_line(new_rhythm_group, x, 
                                                y - 3.0, TRUE, TRUE, 1);
                flat = TRUE;
            }
            else    {
                if (flat) {
                    tab_rhythm_horiz_line(new_rhythm_group, x, 
                                                y - 3.0, FALSE, TRUE, 1);
                }
                else {
                    tab_rhythm_horiz_line(new_rhythm_group, x, 
                                                y - 3.0, FALSE, FALSE, 1);
                }
            }
        }
        if (rhythm.pos1.value > 16)    {
            dot_y -= 3.0;
            
            if (rhythm.pos2.value > 16 && rhythm.pos2.active == TRUE)    {
                tab_rhythm_horiz_line(new_rhythm_group, x, 
                                                y - 6.0, TRUE, TRUE, 1);
                flat = TRUE;
            }
            else    {
                if (flat) {
                    tab_rhythm_horiz_line(new_rhythm_group, x, 
                                                y - 6.0, FALSE, TRUE, 1);
                }
                else {
                    tab_rhythm_horiz_line(new_rhythm_group, x, 
                                                y - 6.0, FALSE, FALSE, 1);
                }
            }
        }
        if (rhythm.pos1.dotted == TRUE)    {
            if (!flat) dot_y -= 3.0;
            tab_rhythm_dot(new_rhythm_group, x, dot_y - 4.0);
        }
    }
    
    if (rhythm.pos2.active == TRUE)    {
        dot_y = y;
        flat = FALSE;
        
        if (rhythm.pos2.value >= 2) {
            tab_rhythm_vert_line(tab_doc, new_rhythm_group, x + 17.0, y);
        }
        
        if (rhythm.pos2.value > 4)    {
            if (rhythm.pos3.value > 4 && rhythm.pos3.active == TRUE)    {
                tab_rhythm_horiz_line(new_rhythm_group, x + 17.0,
                                                y, TRUE, TRUE, 1);
                flat = TRUE;
            }
            else    {
                if (rhythm.pos1.active == FALSE || rhythm.pos1.value <= 4)    {
                      tab_rhythm_horiz_line(new_rhythm_group, x + 17.0, 
                                                y, FALSE, FALSE, 1);
                }
            }
        }
        if (rhythm.pos2.value > 8)    {
            dot_y -= 3.0;
            
            if (rhythm.pos3.value > 8 && rhythm.pos3.active == TRUE)    {
                tab_rhythm_horiz_line(new_rhythm_group, x + 17.0, 
                                                y - 3.0, TRUE, TRUE, 1);
                flat = TRUE;
            }
            else    {
                if (rhythm.pos1.active == FALSE || rhythm.pos1.value <= 4)    {
                    if (flat) {
                        tab_rhythm_horiz_line(new_rhythm_group, x + 17.0, 
                                                y - 3.0, FALSE, TRUE, 1);
                    }
                    else {
                        tab_rhythm_horiz_line(new_rhythm_group, x + 17.0, 
                                                y - 3.0, FALSE, FALSE, 1);
                    }
                }
                else {
                    if (rhythm.pos1.value <= 8) {
                        tab_rhythm_horiz_line(new_rhythm_group, x + 17.0, 
                                                y - 3.0, FALSE, TRUE, -1);
                    }
                }
            }
        }
        
        if (rhythm.pos2.value > 16)    {
            dot_y -= 3.0;
            
            if (rhythm.pos3.value > 16 && rhythm.pos3.active == TRUE)    {
                tab_rhythm_horiz_line(new_rhythm_group, x + 17.0, 
                                                y - 6.0, TRUE, TRUE, 1);
                flat = TRUE;
            }
            else    {
                if (rhythm.pos1.active == FALSE || rhythm.pos1.value <= 4)    {
                    if (flat) {
                        tab_rhythm_horiz_line(new_rhythm_group, x + 17.0, 
                                                y - 6.0, FALSE, TRUE, 1);
                    }
                    else {
                        tab_rhythm_horiz_line(new_rhythm_group, x + 17.0, 
                                                y - 6.0, FALSE, FALSE, 1);
                    }
                }
                else {
                    if (rhythm.pos1.value <= 16) {
                        if (rhythm.pos3.value <= 4 ||
                            rhythm.pos3.active == FALSE) {
                                tab_rhythm_horiz_line(new_rhythm_group, x + 17.0, 
                                                y - 6.0, FALSE, TRUE, -1);   
                        }
                        else {
                            tab_rhythm_horiz_line(new_rhythm_group, x + 17.0, 
                                                y - 6.0, FALSE, TRUE, 1);
                        }
                    }
                }    
            }
        }
        if (rhythm.pos2.dotted == TRUE)    {
            if (!flat) dot_y -= 3.0;
            tab_rhythm_dot(new_rhythm_group, x + 17.0, dot_y - 4.0);
        }
    }
    
    if (rhythm.pos3.active == TRUE)    {
        
        dot_y = y;
        flat = FALSE;
        
        if (rhythm.pos3.value >= 2) {
            tab_rhythm_vert_line(tab_doc, new_rhythm_group, x + 34.0, y);
        }
        
        if (rhythm.pos3.value > 4)    {
            if (rhythm.pos4.value > 4 && rhythm.pos4.active == TRUE)    {
                tab_rhythm_horiz_line(new_rhythm_group, x + 34.0, 
                                                y, TRUE, TRUE, 1);
                flat = TRUE;
            }
            else    {
                if (rhythm.pos2.active == FALSE || rhythm.pos2.value <= 4)    {
                      tab_rhythm_horiz_line(new_rhythm_group, x + 34.0, 
                                                y, FALSE, FALSE, 1);
                }
            }
        }
        if (rhythm.pos3.value > 8)    {
            dot_y -= 3.0;
            
            if (rhythm.pos4.value > 8 && rhythm.pos4.active == TRUE)    {
                tab_rhythm_horiz_line(new_rhythm_group, x + 34.0, 
                                                y - 3.0, TRUE, TRUE, 1);
                flat = TRUE;
            }
            else    {
                if (rhythm.pos2.active == FALSE || rhythm.pos2.value <= 4)    {
                    if (flat) {
                        tab_rhythm_horiz_line(new_rhythm_group, x + 34.0, 
                                                y - 3.0, FALSE, TRUE, 1);
                    }
                    else {
                        tab_rhythm_horiz_line(new_rhythm_group, x + 34.0, 
                                                y - 3.0, FALSE, FALSE, 1);
                    }
                }
                else {
                    if (rhythm.pos2.value <= 8) {
                        tab_rhythm_horiz_line(new_rhythm_group, x + 34.0, 
                                                y - 3.0, FALSE, TRUE, -1);
                    }
                }
            }
        }
        if (rhythm.pos3.value > 16)    {
            dot_y -= 3.0;
            
            if (rhythm.pos4.value > 16 && rhythm.pos4.active == TRUE)    {
                tab_rhythm_horiz_line(new_rhythm_group, x + 34.0, 
                                                y - 6.0, TRUE, TRUE, 1);
                flat = TRUE;
            }
            else    {
                if (rhythm.pos2.active == FALSE || rhythm.pos2.value <= 4)    {
                    if (flat) {
                        tab_rhythm_horiz_line(new_rhythm_group, x + 34.0, 
                                                    y - 6.0, FALSE, TRUE, 1);
                    }
                    else {
                        tab_rhythm_horiz_line(new_rhythm_group, x + 34.0, 
                                                    y - 6.0, FALSE, FALSE, 1);
                    }
                }
                else {
                    if (rhythm.pos2.value <= 16) {
                        if (rhythm.pos4.value <= 4 ||
                            rhythm.pos4.active == FALSE) {
                                tab_rhythm_horiz_line(new_rhythm_group, x + 34.0, 
                                                    y - 6.0, FALSE, TRUE, -1);
                        }
                        else {
                            tab_rhythm_horiz_line(new_rhythm_group, x + 34.0, 
                                                    y - 6.0, FALSE, TRUE, 1);
                        }
                    }
                }
            }
        }
        if (rhythm.pos3.dotted == TRUE)    {
            if (!flat) dot_y -= 3.0;
            tab_rhythm_dot(new_rhythm_group, x + 34.0, dot_y - 4.0);
        }
    }
    
    if (rhythm.pos4.active == TRUE)    {
        dot_y = y;
        if (rhythm.pos4.value >= 2) {
            tab_rhythm_vert_line(tab_doc, new_rhythm_group, x + 51.0, y);
        }
        
        if (rhythm.pos4.value > 4) {
            if (rhythm.pos3.value <= 4 || rhythm.pos3.active == FALSE) {
                tab_rhythm_horiz_line(new_rhythm_group, x + 51.0, y, 
                                        FALSE, FALSE, 1);
            }
        }
        
        if (rhythm.pos4.value > 8) {
            if (rhythm.pos3.value <= 4 || rhythm.pos3.active == FALSE) {
                dot_y -= 3.0;
                tab_rhythm_horiz_line(new_rhythm_group, x + 51.0, y - 3.0,
                                        FALSE, FALSE, 1);
            }
            else {
                if (rhythm.pos3.value <= 8) {
                    tab_rhythm_horiz_line(new_rhythm_group, x + 51.0, y - 3.0, 
                                        FALSE, TRUE, -1);
                }
            }
        }
        
        if (rhythm.pos4.value > 16) {
            if (rhythm.pos3.value <= 4 || rhythm.pos3.value == FALSE) {
                dot_y -= 3.0;
                tab_rhythm_horiz_line(new_rhythm_group, x + 51.0, y - 6.0,
                                        FALSE, FALSE, 1);
            }
            else {
                if (rhythm.pos3.value <= 16) {
                    tab_rhythm_horiz_line(new_rhythm_group, x + 51.0, y - 6.0,
                                        FALSE, TRUE, -1);
                }
            }
        }
        
        if (rhythm.pos4.dotted == TRUE)    {
            if (!flat) dot_y -= 3.0;
            tab_rhythm_dot(new_rhythm_group, x + 51.0, dot_y - 4.0);
        }
    }


    count_object(tab_doc, GNOME_CANVAS_ITEM(new_rhythm_group));
    
    gnome_canvas_item_lower_to_bottom(GNOME_CANVAS_ITEM(new_rhythm_group));
    
    gnome_canvas_item_get_bounds(GNOME_CANVAS_ITEM(new_rhythm_group), 
                                &x1, &y1, &x2, &y2);
    
    gnome_canvas_update_bbox(GNOME_CANVAS_ITEM(new_rhythm_group),
                            (int) x1, (int) y1,
                            (int) x2, (int) y2);
    
    tab_rhythm_xml = xmlNewChild(tab_doc->staff_nodes[current_staff], NULL, 
                                                "tab_rhythm", NULL);
    xmlSetProp(tab_rhythm_xml, "x1", float_to_char(x1));
    xmlSetProp(tab_rhythm_xml, "y1", float_to_char(y1));
    xmlSetProp(tab_rhythm_xml, "x2", float_to_char(x2));
    xmlSetProp(tab_rhythm_xml, "y2", float_to_char(y2));
    xmlSetProp(tab_rhythm_xml, "x_create", float_to_char(x));
    xmlSetProp(tab_rhythm_xml, "y_create", float_to_char(y));
    
    tab_rhythm_elements[0] = xmlNewChild(tab_rhythm_xml, NULL, "pos1", NULL);
    xmlSetProp(tab_rhythm_elements[0], "active", 
                int_to_char(rhythm.pos1.active));
    xmlSetProp(tab_rhythm_elements[0], "value", 
                int_to_char(rhythm.pos1.value));
    xmlSetProp(tab_rhythm_elements[0], "dotted", 
                int_to_char(rhythm.pos1.dotted));
    tab_rhythm_elements[1] = xmlNewChild(tab_rhythm_xml, NULL, "pos2", NULL);
    xmlSetProp(tab_rhythm_elements[1], "active", 
                int_to_char(rhythm.pos2.active));
    xmlSetProp(tab_rhythm_elements[1], "value", 
                int_to_char(rhythm.pos2.value));
    xmlSetProp(tab_rhythm_elements[1], "dotted", 
                int_to_char(rhythm.pos2.dotted));
    tab_rhythm_elements[2] = xmlNewChild(tab_rhythm_xml, NULL, "pos3", NULL);
    xmlSetProp(tab_rhythm_elements[2], "active", 
                int_to_char(rhythm.pos3.active));
    xmlSetProp(tab_rhythm_elements[2], "value", 
                int_to_char(rhythm.pos3.value));
    xmlSetProp(tab_rhythm_elements[2], "dotted", 
                int_to_char(rhythm.pos3.dotted));
    tab_rhythm_elements[3] = xmlNewChild(tab_rhythm_xml, NULL, "pos4", NULL);
    xmlSetProp(tab_rhythm_elements[3], "active", 
                int_to_char(rhythm.pos4.active));
    xmlSetProp(tab_rhythm_elements[3], "value", 
                int_to_char(rhythm.pos4.value));
    xmlSetProp(tab_rhythm_elements[3], "dotted", 
                int_to_char(rhythm.pos4.dotted));
    
    g_signal_connect(GTK_OBJECT(new_rhythm_group), "event", 
                        (GtkSignalFunc) staff_object_event, tab_doc);
    g_object_set_data(G_OBJECT(new_rhythm_group), "node", tab_rhythm_xml);
    tab_doc->changed = TRUE;
    set_title(tab_doc);
}

gint 
find_rhythm_num_segs(xmlNodePtr staff_node, double x)
{
    /* this function figures out how many text items are in the current pos */
    xmlNodePtr prey2;
    double prey_x1;
    gchar *tmp, *tmp2;
    gint found_index = 0;
    gint is_str_strum, is_str_text;
    
    for (prey2 = staff_node->children; prey2 != NULL; prey2 = prey2->next)    {
        
        if (xmlIsBlankNode(prey2) == 1) continue;
            
        tmp = get_prop(prey2, "active");
        if (tmp == NULL)    {
            is_str_strum = g_ascii_strcasecmp(prey2->name, "tab_strum");
            is_str_text = g_ascii_strcasecmp(prey2->name, "tab_text");
            if (is_str_strum == 0 || is_str_text == 0)    {
                tmp2 = get_prop(prey2, "x1");
                prey_x1 = atof(tmp2);
                
                g_free(tmp2);
                
                if (prey_x1 >= (x-3) && prey_x1 <= (x+3))    {
                    found_index++;
                }
                if ((x - prey_x1) >= 3.1 && (x - prey_x1) <= 3.9)    {
                    if (is_str_strum == 0)    {
                        found_index++;
                    }
                }
                
                    
            }
             
        }
        g_free(tmp);
    }
    
    return(found_index);
}

double 
find_rhythm_y2(xmlNodePtr staff_node, double x, gint total, gint index)
{
    // this function finds the bottom y of text 
    // to which rhythm is being assigned
    
    xmlNodePtr prey2;
    double prey_y2 = 0.0;
    double prey_x1 =0.0;
    gchar *tmp, *char_x, *char_y;
    double found_ys[total];
    gint sort_index = 0.0;
    gint sort_ref = 0.0;
    gint found_index = 0.0;
    double holder = 0.0;
    gint is_str_strum, is_str_text;
        
    found_index = 0;
    
    for (prey2 = staff_node->children; prey2 != NULL; prey2 = prey2->next)    {
        
        if (xmlIsBlankNode(prey2) == 1) continue;
            
        tmp = get_prop(prey2, "active");    
        
        if (tmp == NULL)    {
            is_str_strum = g_ascii_strcasecmp(prey2->name, "tab_strum");
            is_str_text = g_ascii_strcasecmp(prey2->name, "tab_text");
            if (is_str_strum == 0 || is_str_text == 0)    {
                char_x = get_prop(prey2, "x1");
                char_y = get_prop(prey2, "y2");
                prey_x1 = atof(char_x);
                prey_y2 = atof(char_y);
                g_free(char_x);
                g_free(char_y);
                
                if (prey_x1 >= (x - 1.5) && prey_x1 <= (x + 1.5))    {
                    found_ys[found_index] = prey_y2;
                    found_index++;
                
                } 
                if ((x - prey_x1) >= 3.1 && (x - prey_x1) <= 3.9)    {
                    if (is_str_strum == 0)    {
                        // fprintf(stderr, "entering tab_strum code\n");
                        found_ys[found_index] = prey_y2;
                        found_index++;
                    }
                }
                                                
            }
            
             
        }
        g_free(tmp);
    }

    /* the array should be in descending order */
    /* hopefully a bubble sort */
    for (sort_index = 0; sort_index < total; sort_index++)    {
        for(sort_ref = sort_index; sort_ref < total; sort_ref++)    {
            if (found_ys[sort_index] < found_ys[sort_ref])    {
                holder = found_ys[sort_index];
                found_ys[sort_index] = found_ys[sort_ref];
                found_ys[sort_ref] = holder;
            }
        }
    }
    return(found_ys[index]);
    
}

void 
create_timesig(GtabDoc *tab_doc, double x, double y, gint beats, gint beatval)
{
    GnomeCanvasItem *new_timesig_beats;
    GnomeCanvasItem *new_timesig_beatval;
    GnomeCanvasGroup *timesig;
    xmlNodePtr tab_timesig;
    PangoFontDescription *font_string;
    double x1, y1, x2, y2;

    font_string = pango_font_description_from_string(tab_doc->parent->tab_font_large);
    
    find_staff(y);
    switch (current_staff)    {

        case 1:
            y = 300.0;
            break;
        case 2:
            y = 440.0;
            break;
        case 3:
            y = 580.0;
            break;
        case 4:
            y = 720.0;
            break;
        case 5:
            y = 860.0;
            break;
        default:
            y = 160.0;
            break;
    }
    
    timesig = GNOME_CANVAS_GROUP
                (gnome_canvas_item_new(tab_doc->staff_objects[current_staff], 
                                        gnome_canvas_group_get_type(),
                                        NULL));
    new_timesig_beats = gnome_canvas_item_new(timesig, 
                            gnome_canvas_text_get_type(),
                            "text", int_to_char(beats),
                            "x", x,
                            "y", y + 5.0,
                            "anchor", GTK_ANCHOR_NORTH_WEST,
                            "font_desc", font_string,
                            "fill_color", "black",
                            NULL);
    
    new_timesig_beatval = gnome_canvas_item_new(timesig,
                            gnome_canvas_text_get_type(),
                            "text", int_to_char(beatval),
                            "x", x,
                            "y", y + 35.0,
                            "anchor", GTK_ANCHOR_NORTH_WEST,
                            "font_desc", font_string,
                            "fill_color", "black",
                            NULL);
    
    gnome_canvas_item_get_bounds(GNOME_CANVAS_ITEM(timesig), 
                                            &x1, &y1, &x2, &y2);
    
    count_object(tab_doc, GNOME_CANVAS_ITEM(timesig));
    tab_timesig = xmlNewChild(tab_doc->staff_nodes[current_staff], NULL, 
                                            "tab_timesig", NULL);
    
    xmlSetProp(tab_timesig, "x1", float_to_char(x1));
    xmlSetProp(tab_timesig, "y1", float_to_char(y1));
    xmlSetProp(tab_timesig, "x2", float_to_char(x2));
    xmlSetProp(tab_timesig, "y2", float_to_char(y2));
    xmlSetProp(tab_timesig, "x_create", float_to_char(x));
    xmlSetProp(tab_timesig, "y_create", float_to_char(y));
    xmlSetProp(tab_timesig, "beats", int_to_char(beats));
    xmlSetProp(tab_timesig, "beatval", int_to_char(beatval));
    
    g_signal_connect(GTK_OBJECT(timesig), "event", 
                        (GtkSignalFunc) staff_object_event, tab_doc);
    g_object_set_data(G_OBJECT(timesig), "node", tab_timesig);
    
    pango_font_description_free(font_string);
    tab_doc->changed = TRUE;
    set_title(tab_doc);
}
    
void 
create_comment(GtabDoc *tab_doc, double x, double y, G_CONST_RETURN gchar *comment)
{
    GnomeCanvasGroup *comment_group;
    GnomeCanvasItem *comment_line;
    GnomeCanvasItem *comment_text;
    GnomeCanvasPoints *points;
    PangoFontDescription *font_string;
    xmlNodePtr tab_comment;
    double y_start;
    double x1, y1, x2, y2;
    
    y_start = y;
    
    find_staff(y);
    switch (current_staff)    {
        case 1:
            y = 280.0;
            break;
        case 2:
            y = 420.0;
            break;
        case 3:
            y = 560.0;
            break;
        case 4:
            y = 700.0;
            break;
        case 5:
            y = 840.0;
            break;
        default:
            y = 140.0;
            break;
    }
    
    font_string = pango_font_description_from_string(tab_doc->parent->tab_font_small);
    
    comment_group = GNOME_CANVAS_GROUP
                    (gnome_canvas_item_new(tab_doc->staff_objects[current_staff], 
                                            gnome_canvas_group_get_type(),
                                            NULL));
    points = gnome_canvas_points_new(2);
    points->coords[0] = x;
    points->coords[1] = y_start;
    points->coords[2] = x + 10.0;
    points->coords[3] = y;
    comment_line = gnome_canvas_item_new(comment_group,
                                            gnome_canvas_line_get_type(),
                                            "points", points,
                                            "fill_color", "grey30",
                                            "width_pixels", 1,
                                            "first_arrowhead", FALSE,
                                            "last_arrowhead", FALSE,
                                            "smooth", TRUE,
                                            "spline_steps", 1,    
                                            NULL);
    gnome_canvas_points_unref(points);
    
    comment_text = gnome_canvas_item_new(comment_group, 
                                        gnome_canvas_text_get_type(),
                                        "text", comment,
                                        "x", x + 10.0,
                                        "y", y,
                                        "anchor", GTK_ANCHOR_SOUTH,
                                        "font_desc", font_string,
                                        "fill_color", "grey30",
                                        NULL);
                                                                
    gnome_canvas_item_get_bounds(GNOME_CANVAS_ITEM(comment_group), 
                                                &x1, &y1, &x2, &y2);
    
    count_object(tab_doc, GNOME_CANVAS_ITEM(comment_group));
    tab_comment = xmlNewChild(tab_doc->staff_nodes[current_staff], NULL, 
                                            "tab_comment", NULL);
    
    xmlSetProp(tab_comment, "x1", float_to_char(x1));
    xmlSetProp(tab_comment, "y1", float_to_char(y1));
    xmlSetProp(tab_comment, "x2", float_to_char(x2));
    xmlSetProp(tab_comment, "y2", float_to_char(y2));

    xmlSetProp(tab_comment, "x_create", float_to_char(x));
    xmlSetProp(tab_comment, "y_create", float_to_char(y_start));
    xmlSetProp(tab_comment, "text", comment);
    
    g_signal_connect(GTK_OBJECT(comment_group), "event", 
                            (GtkSignalFunc) staff_object_event, tab_doc);
    g_object_set_data(G_OBJECT(comment_group), "node", tab_comment);
    
    pango_font_description_free(font_string);
    tab_doc->changed = TRUE;
    set_title(tab_doc);
}

static void
eighth_rest_squiggle(double start_x, double start_y, GnomeCanvasGroup *rest)
{
    GnomeCanvasItem *rest_element1, *rest_element2;
    GnomeCanvasPoints *morepoints;
    
    morepoints = gnome_canvas_points_new(4);
            
    morepoints->coords[0] = start_x;
    morepoints->coords[1] = start_y;
    morepoints->coords[2] = start_x + 2.5;
    morepoints->coords[3] = start_y - 2.5;
    morepoints->coords[4] = start_x + 5.0;
    morepoints->coords[5] = start_y;
    morepoints->coords[6] = start_x + 2.5;
    morepoints->coords[7] = start_y + 2.5;
    rest_element1 = gnome_canvas_item_new(rest,
                            gnome_canvas_polygon_get_type(),
                            "points", morepoints,
                            "fill_color", "black",
                            NULL);
        
    morepoints->coords[0] = start_x + 2.5;
    morepoints->coords[1] = start_y - 2.5;
    morepoints->coords[2] = start_x + 7.5;
    morepoints->coords[3] = start_y + 0.5;
    morepoints->coords[4] = start_x + 10.5;
    morepoints->coords[5] = start_y + 0.5;
    morepoints->coords[6] = start_x + 13.5;
    morepoints->coords[7] = start_y - 2.5;
    
    rest_element2 = gnome_canvas_item_new(rest,
                            gnome_canvas_line_get_type(),
                            "points", morepoints,
                            "fill_color", "black",
                            "width_pixels", 1,
                            "first_arrowhead", FALSE,
                            "last_arrowhead", FALSE,
                            "spline_steps", 1,    
                            NULL);
    gnome_canvas_points_unref(morepoints);
}

void 
create_rest(GtabDoc *tab_doc, double x, double y, gint value, gboolean dotted)
{
    GnomeCanvasGroup *new_rest;
    GnomeCanvasItem *rest_element1, *rest_element2, 
                    *rest_element3, *rest_element4;
    GnomeCanvasPoints *points = NULL;
    GnomeCanvasPoints *morepoints = NULL;
    xmlNodePtr tab_rest_xml;
    double start_x;
    double start_y;
    double x1, y1, x2, y2;
    
    find_staff(y);
    
    start_x = x;
    start_y = y;
    
    //start_y = (ceil(y/140))*140 - 90.0; /* moves y to middle of staff */
    
    new_rest = GNOME_CANVAS_GROUP
                (gnome_canvas_item_new(tab_doc->staff_objects[current_staff],
                                        gnome_canvas_group_get_type(),
                                        NULL));
    /* points = gnome_canvas_points_new(2); */
    
    switch (value)    {
        case 1:
            points = gnome_canvas_points_new(2);
            points->coords[0] = start_x;
            points->coords[1] = start_y - 4.0;
            points->coords[2] = start_x + 12;
            points->coords[3] = start_y - 4.0;
    
            rest_element1 = gnome_canvas_item_new(new_rest,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 2,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "spline_steps", 1,    
                                    NULL);

            points->coords[0] = points->coords[0] + 3.0;
            points->coords[2] = points->coords[2] - 3.0;
            points->coords[1] = points->coords[1] + 2.0;
            points->coords[3] = points->coords[1];
            
            rest_element2 = gnome_canvas_item_new(new_rest,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 4,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "spline_steps", 1,    
                                    NULL);
            
            gnome_canvas_points_unref(points);
            break;
        case 2:
            points = gnome_canvas_points_new(2);
            
            points->coords[0] = start_x;
            points->coords[1] = start_y + 5.0;
            points->coords[2] = start_x + 12;
            points->coords[3] = start_y + 5.0;
    
            rest_element1 = gnome_canvas_item_new(new_rest,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 2,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "spline_steps", 1,    
                                    NULL);

            points->coords[0] = points->coords[0] + 3.0;
            points->coords[2] = points->coords[2] - 3.0;
            points->coords[1] = points->coords[1] - 2.0;
            points->coords[3] = points->coords[1];
            
            rest_element2 = gnome_canvas_item_new(new_rest,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 4,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "spline_steps", 1,    
                                    NULL);
            
            gnome_canvas_points_unref(points);
            
            break;
        case 8:
            points = gnome_canvas_points_new(2);
            
            eighth_rest_squiggle((start_x - 4.5), (start_y - 4.5), new_rest);
            
            points->coords[0] = start_x + 9.0;
            points->coords[1] = start_y - 7.0;
            points->coords[2] = start_x + 5.0;
            points->coords[3] = start_y + 8.0;
            
            rest_element3 = gnome_canvas_item_new(new_rest,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 2,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "spline_steps", 1,    
                                    "smooth", TRUE,
                                    NULL);
                                    
            gnome_canvas_points_unref(points);

            break;
            
        case 16:
            points = gnome_canvas_points_new(2);
            
            eighth_rest_squiggle((start_x - 4.5), (start_y - 4.5), new_rest);
            eighth_rest_squiggle((start_x - 5.5), (start_y - 1.0), new_rest);

            points->coords[0] = start_x + 9.0;
            points->coords[1] = start_y - 7.0;
            points->coords[2] = start_x + 5.0;
            points->coords[3] = start_y + 8.0;
            
            rest_element3 = gnome_canvas_item_new(new_rest,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 2,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "spline_steps", 1,    
                                    "smooth", TRUE,
                                    NULL);
                                    
            gnome_canvas_points_unref(points);
            break;
            
        case 32:
            points = gnome_canvas_points_new(2);
            
            eighth_rest_squiggle((start_x - 4.5), (start_y - 4.5), new_rest);
            eighth_rest_squiggle((start_x - 5.5), (start_y - 1.0), new_rest);
            eighth_rest_squiggle((start_x - 6.5), (start_y + 2.5), new_rest);
        
            points->coords[0] = start_x + 9.0;
            points->coords[1] = start_y - 7.0;
            points->coords[2] = start_x + 5.0;
            points->coords[3] = start_y + 8.0;
            
            rest_element3 = gnome_canvas_item_new(new_rest,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 2,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "spline_steps", 1,    
                                    "smooth", TRUE,
                                    NULL);
                                    
            gnome_canvas_points_unref(points);
            break;
            
        default:
            
            points = gnome_canvas_points_new(2);
            morepoints = gnome_canvas_points_new(5);
            
            points->coords[0] = start_x;
            points->coords[1] = start_y - 10.0;
            points->coords[2] = start_x + 4.0;
            points->coords[3] = start_y - 5.0;
    
            rest_element1 = gnome_canvas_item_new(new_rest,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 2,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "spline_steps", 1,    
                                    "smooth", TRUE,
                                    NULL);

            points->coords[0] = start_x + 4.0;
            points->coords[1] = start_y - 5.0;
            points->coords[2] = start_x - 1.0;
            points->coords[3] = start_y;
                        
            rest_element2 = gnome_canvas_item_new(new_rest,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 5,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "spline_steps", 1,    
                                    NULL);
            
            points->coords[0] = start_x - 1.0;
            points->coords[1] = start_y;
            points->coords[2] = start_x + 6.0;
            points->coords[3] = start_y + 8.0;
            rest_element3 = gnome_canvas_item_new(new_rest,
                                    gnome_canvas_line_get_type(),
                                    "points", points,
                                    "fill_color", "black",
                                    "width_pixels", 2,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "spline_steps", 1,    
                                    NULL);
                                    
            morepoints->coords[0] = start_x + 6.0;
            morepoints->coords[1] = start_y + 8.0;
            morepoints->coords[2] = start_x + 3.0;
            morepoints->coords[3] = start_y + 5.0;
            morepoints->coords[4] = start_x;
            morepoints->coords[5] = start_y + 6.0;
            morepoints->coords[6] = start_x - 1.0;
            morepoints->coords[7] = start_y + 9.0;
            morepoints->coords[8] = start_x + 1.0;
            morepoints->coords[9] = start_y + 12.0;
            
            rest_element4 = gnome_canvas_item_new(new_rest,
                                    gnome_canvas_line_get_type(),
                                    "points", morepoints,
                                    "fill_color", "black",
                                    "width_pixels", 2,
                                    "first_arrowhead", FALSE,
                                    "last_arrowhead", FALSE,
                                    "smooth", TRUE,
                                    "spline_steps", 1,    
                                    NULL); 
            
            gnome_canvas_points_unref(points);
            gnome_canvas_points_unref(morepoints);
            break;
    }
    
    
    count_object(tab_doc, GNOME_CANVAS_ITEM(new_rest));
    
    gnome_canvas_item_get_bounds(GNOME_CANVAS_ITEM(new_rest), 
                                            &x1, &y1, &x2, &y2);
        
    tab_rest_xml = xmlNewChild(tab_doc->staff_nodes[current_staff], NULL, 
                                                "tab_rest", NULL);
    xmlSetProp(tab_rest_xml, "x1", float_to_char(x1));
    xmlSetProp(tab_rest_xml, "y1", float_to_char(y1));
    xmlSetProp(tab_rest_xml, "x2", float_to_char(x2));
    xmlSetProp(tab_rest_xml, "y2", float_to_char(y2));
    xmlSetProp(tab_rest_xml, "x_create", float_to_char(x));
    xmlSetProp(tab_rest_xml, "y_create", float_to_char(y));
    xmlSetProp(tab_rest_xml, "value", int_to_char(value));
    xmlSetProp(tab_rest_xml, "dotted", int_to_char(dotted));
    
    g_signal_connect(GTK_OBJECT(new_rest), "event", 
                        (GtkSignalFunc) staff_object_event, tab_doc);
    g_object_set_data(G_OBJECT(new_rest), "node", tab_rest_xml);
    tab_doc->changed = TRUE;    
    set_title(tab_doc);
}


void 
create_doc_props(GtabDoc *tab_doc)
{
    GnomeCanvasItem *title;
    GnomeCanvasItem *artist;
    GnomeCanvasItem *tuning;
    GnomeCanvasItem *pagenumber;
    PangoFontDescription *font_string_regular;
    PangoFontDescription *font_string_large;
    gchar *title_char, *artist_char, *tuning_char;
    
    
    if (tab_doc->properties != NULL) gtk_object_destroy(GTK_OBJECT(tab_doc->properties));
    
    font_string_regular = pango_font_description_from_string(tab_doc->parent->tab_font);
    font_string_large = pango_font_description_from_string(tab_doc->parent->tab_font_large);
    
    title_char = get_prop(tab_doc->doc_props, "title");
    artist_char = get_prop(tab_doc->doc_props, "artist");
    tuning_char = get_prop(tab_doc->doc_props, "tuning");
    
    tab_doc->properties = GNOME_CANVAS_GROUP
                (gnome_canvas_item_new(tab_doc->canvas_group, 
                                        gnome_canvas_group_get_type(),
                                        NULL));
    if (title_char) {
        title = gnome_canvas_item_new(tab_doc->properties, 
                                        gnome_canvas_text_get_type(),
                                        "text", title_char,
                                        "x", 50.0,
                                        "y", 40.0,
                                        "anchor", GTK_ANCHOR_NORTH_WEST,
                                        "font_desc", font_string_large,
                                        "fill_color", "black",
                                        NULL);
    }
    
    if (artist_char) {
        artist = gnome_canvas_item_new(tab_doc->properties, 
                                        gnome_canvas_text_get_type(),
                                        "text", artist_char,
                                        "x", 50.0,
                                        "y", 70.0,
                                        "anchor", GTK_ANCHOR_NORTH_WEST,
                                        "font_desc", font_string_regular,
                                        "fill_color", "black",
                                        NULL);
    }
    
    if (tuning_char) {
        tuning = gnome_canvas_item_new(tab_doc->properties, gnome_canvas_text_get_type(),
                                        "text", tuning_char,
                                        "x", 750.0,
                                        "y", 70.0,
                                        "anchor", GTK_ANCHOR_NORTH_EAST,
                                        "font_desc", font_string_regular,
                                        "fill_color", "black",
                                        NULL);
    }
    
    if (atoi(tab_doc->current_page) > 1) {
        pagenumber = gnome_canvas_item_new(tab_doc->properties, gnome_canvas_text_get_type(),
                                        "text", tab_doc->current_page,
                                        "x", 750.0,
                                        "y", 40.0,
                                        "anchor", GTK_ANCHOR_NORTH_EAST,
                                        "font_desc", font_string_regular,
                                        "fill_color", "black",
                                        NULL);
    }
    
    g_free(title_char);
    g_free(artist_char);
    g_free(tuning_char);
    pango_font_description_free(font_string_regular);
    pango_font_description_free(font_string_large);
    tab_doc->changed = TRUE;
    set_title(tab_doc);
}

void 
count_object(GtabDoc *tab_doc, GnomeCanvasItem *staff_obj)
{
    tab_doc->obj_counter = g_list_prepend(tab_doc->obj_counter, (gpointer ) staff_obj);
    
}
    
gint
get_rhythm_value(G_CONST_RETURN gchar *fraction)
{
    if (g_ascii_strcasecmp(fraction, "1/1") == 0) return(1);
    if (g_ascii_strcasecmp(fraction, "1/2") == 0) return(2);
    if (g_ascii_strcasecmp(fraction, "1/8") == 0) return(8);
    if (g_ascii_strcasecmp(fraction, "1/16") == 0) return (16);
    if (g_ascii_strcasecmp(fraction, "1/32") == 0) return (32);
    return(4);
}

gint
get_rest_value(G_CONST_RETURN gchar *fraction)
{
    if (g_ascii_strcasecmp(fraction, "whole") == 0) return(1);
    if (g_ascii_strcasecmp(fraction, "1/2") == 0) return(2);
    if (g_ascii_strcasecmp(fraction, "1/8") == 0) return(8);
    if (g_ascii_strcasecmp(fraction, "1/16") == 0) return (16);
    if (g_ascii_strcasecmp(fraction, "1/32") == 0) return (32);
    return(4);
}

