Ejemplo n.º 1
0
FX_ENTRY void FX_CALL
grDrawVertexArrayContiguous(FxU32 mode, FxU32 Count, void *pointers, FxU32 stride)
{
  LOG("grDrawVertexArrayContiguous(%d,%d,%d)\r\n", mode, Count, stride);

  if(nvidia_viewport_hack && !render_to_texture)
  {
    glViewport(0, viewport_offset, viewport_width, viewport_height);
    nvidia_viewport_hack = 0;
  }

  if(stride != 156)
  {
	  LOGINFO("Incompatible stride\n");
  }

  reloadTexture();

  if(need_to_compile) compile_shader();

  vbo_enable();

  switch(mode)
  {
  case GR_TRIANGLE_STRIP:
    vbo_buffer(GL_TRIANGLE_STRIP,0,Count,pointers);
    break;
  case GR_TRIANGLE_FAN:
    vbo_buffer(GL_TRIANGLE_FAN,0,Count,pointers);
    break;
  default:
    display_warning("grDrawVertexArrayContiguous : unknown mode : %x", mode);
  }
}
Ejemplo n.º 2
0
FX_ENTRY void FX_CALL
grCullMode( GrCullMode_t mode )
{
  LOG("grCullMode(%d)\r\n", mode);
  static int oldmode = -1, oldinv = -1;
  culling_mode = mode;
  if (inverted_culling == oldinv && oldmode == mode)
    return;
  oldmode = mode;
  oldinv = inverted_culling;
  switch(mode)
  {
  case GR_CULL_DISABLE:
    glDisable(GL_CULL_FACE);
    break;
  case GR_CULL_NEGATIVE:
    if (!inverted_culling)
      glCullFace(GL_FRONT);
    else
      glCullFace(GL_BACK);
    glEnable(GL_CULL_FACE);
    break;
  case GR_CULL_POSITIVE:
    if (!inverted_culling)
      glCullFace(GL_BACK);
    else
      glCullFace(GL_FRONT);
    glEnable(GL_CULL_FACE);
    break;
  default:
    display_warning("unknown cull mode : %x", mode);
  }
}
Ejemplo n.º 3
0
int main() {
	// declare the required data structures
	char *word_ptr;
	bool keep_going = true;

	// initialize and start the file system data structures
	startup_memory_system();
	display_warning("main: memory manager started");

	// accept and process user commands until directed to stop
	do {
		keep_going = process_next_command();
	} while (keep_going);

	display_warning("main: memory manager stopped");
	return 0;
}
Ejemplo n.º 4
0
FX_ENTRY void FX_CALL
grCoordinateSpace( GrCoordinateSpaceMode_t mode )
{
  LOG("grCoordinateSpace(%d)\r\n", mode);
  switch(mode)
  {
  case GR_WINDOW_COORDS:
    break;
  default:
    display_warning("unknwown coordinate space : %x", mode);
  }
}
Ejemplo n.º 5
0
FX_ENTRY FxU32 FX_CALL 
grTexTextureMemRequired( FxU32     evenOdd,
                                 GrTexInfo *info   )
{
    int width, height;
    WriteLog(M64MSG_VERBOSE, "grTextureMemRequired(%d)\r\n", evenOdd);
    if (info->largeLodLog2 != info->smallLodLog2) display_warning("grTexTextureMemRequired : loading more than one LOD");

    if (info->aspectRatioLog2 < 0)
    {
        height = 1 << info->largeLodLog2;
        width = height >> -info->aspectRatioLog2;
    }
Ejemplo n.º 6
0
FX_ENTRY void FX_CALL
grDepthBufferFunction( GrCmpFnc_t function )
{
  LOG("grDepthBufferFunction(%d)\r\n", function);
  switch(function)
  {
  case GR_CMP_GEQUAL:
    if (w_buffer_mode)
      glDepthFunc(GL_LEQUAL);
    else
      glDepthFunc(GL_GEQUAL);
    break;
  case GR_CMP_LEQUAL:
    if (w_buffer_mode)
      glDepthFunc(GL_GEQUAL);
    else
      glDepthFunc(GL_LEQUAL);
    break;
  case GR_CMP_LESS:
    if (w_buffer_mode)
      glDepthFunc(GL_GREATER);
    else
      glDepthFunc(GL_LESS);
    break;
  case GR_CMP_ALWAYS:
    glDepthFunc(GL_ALWAYS);
    break;
  case GR_CMP_EQUAL:
    glDepthFunc(GL_EQUAL);
    break;
  case GR_CMP_GREATER:
    if (w_buffer_mode)
      glDepthFunc(GL_LESS);
    else
      glDepthFunc(GL_GREATER);
    break;
  case GR_CMP_NEVER:
    glDepthFunc(GL_NEVER);
    break;
  case GR_CMP_NOTEQUAL:
    glDepthFunc(GL_NOTEQUAL);
    break;

  default:
    display_warning("unknown depth buffer function : %x", function);
  }
}
Ejemplo n.º 7
0
FX_ENTRY void FX_CALL
grVertexLayout(FxU32 param, FxI32 offset, FxU32 mode)
{
  LOG("grVertexLayout(%d,%d,%d)\r\n", param, offset, mode);
  switch(param)
  {
  case GR_PARAM_XY:
    xy_en = mode;
    xy_off = offset;
    break;
  case GR_PARAM_Z:
    z_en = mode;
    z_off = offset;
    break;
  case GR_PARAM_Q:
    q_en = mode;
    q_off = offset;
    break;
  case GR_PARAM_FOG_EXT:
    fog_ext_en = mode;
    fog_ext_off = offset;
    break;
  case GR_PARAM_PARGB:
    pargb_en = mode;
    pargb_off = offset;
    break;
  case GR_PARAM_ST0:
    st0_en = mode;
    st0_off = offset;
    break;
  case GR_PARAM_ST1:
    st1_en = mode;
    st1_off = offset;
    break;
  default:
    display_warning("unknown grVertexLayout parameter : %x", param);
  }
}
Ejemplo n.º 8
0
bool process_next_command() {
	char command[COMMAND_SIZE + 1];
	int pid, address;

	printf("\nrequest: > ");
	fgets(command, sizeof command, stdin);

	// process the entered command
	if (sscanf(command, "begin p%d", &pid) == 1) {
		mem_begin(pid);

	} else if (sscanf(command, "read p%d %d", &pid, &address) == 2) {
		mem_read(pid, address);

	} else if (sscanf(command, "write p%d %d", &pid, &address) == 2) {
		mem_write(pid, address);

	} else if (sscanf(command, "end p%d", &pid) == 1) {
		mem_end(pid);

	} else if (strncmp(command, "view", 4) == 0) {
		view_memory_system();

	} else if (strncmp(command, "warnings", 8) == 0) {
		if (messages) { printf(" sys !> warnings have been turned off\n"); }
			else { printf(" sys !> warnings are on\n"); }
		messages = !messages;

	} else if (strncmp(command, "stop", 4) == 0) {
		return false;

	} else {
		display_warning("main: unrecognized command");
	}

	return true;
}
Ejemplo n.º 9
0
FX_ENTRY void FX_CALL
grDrawVertexArray(FxU32 mode, FxU32 Count, void *pointers2)
{
  void **pointers = (void**)pointers2;
  LOG("grDrawVertexArray(%d,%d)\r\n", mode, Count);

  if(nvidia_viewport_hack && !render_to_texture)
  {
    glViewport(0, viewport_offset, viewport_width, viewport_height);
    nvidia_viewport_hack = 0;
  }

  reloadTexture();

  if(need_to_compile) compile_shader();

  if(mode != GR_TRIANGLE_FAN)
  {
    display_warning("grDrawVertexArray : unknown mode : %x", mode);
  }

  vbo_enable();
  vbo_buffer(GL_TRIANGLE_FAN,0,Count,pointers[0]);
}
Ejemplo n.º 10
0
FX_ENTRY void FX_CALL
grDepthBufferMode( GrDepthBufferMode_t mode )
{
  LOG("grDepthBufferMode(%d)\r\n", mode);
  switch(mode)
  {
  case GR_DEPTHBUFFER_DISABLE:
    glDisable(GL_DEPTH_TEST);
    w_buffer_mode = 0;
    return;
  case GR_DEPTHBUFFER_WBUFFER:
  case GR_DEPTHBUFFER_WBUFFER_COMPARE_TO_BIAS:
    glEnable(GL_DEPTH_TEST);
    w_buffer_mode = 1;
    break;
  case GR_DEPTHBUFFER_ZBUFFER:
  case GR_DEPTHBUFFER_ZBUFFER_COMPARE_TO_BIAS:
    glEnable(GL_DEPTH_TEST);
    w_buffer_mode = 0;
    break;
  default:
    display_warning("unknown depth buffer mode : %x", mode);
  }
}
Ejemplo n.º 11
0
void slide_delete(void)
{
	// Local variables
	GString				*message;					// Used to construct message strings
	GtkTreePath			*new_path;					// Temporary path
	gint				num_slides;					// Number of slides in the whole slide list
	GtkTreePath			*old_path = NULL;			// The old path, which we'll free
	gint				slide_position;				// Which slide in the slide list we are deleting
	GtkTreeSelection	*film_strip_selector;		//
	GtkTreeIter			selection_iter;				//
	undo_history_data	*undo_item_data = NULL;		// Memory structure undo history items are created in


	// Are we trying to delete the only slide in the project (not good)?
	set_slides(g_list_first(get_slides()));
	num_slides = g_list_length(get_slides());
	if (1 == num_slides)
	{
		// Yes we are, so give a warning message and don't delete the slide
		message = g_string_new(NULL);
		g_string_printf(message, "%s ED462: %s", _("Error"), _("You must leave at least one slide in a project."));
		display_warning(message->str);
		g_string_free(message, TRUE);
		return;
	}

	// Determine where the slide is positioned in the project
	slide_position = g_list_position(get_slides(), get_current_slide());

	// Create and store the undo history item for this slide
	undo_item_data = g_new0(undo_history_data, 1);
	undo_item_data->layer_data_new = NULL;  // NULL means not set
	undo_item_data->layer_data_old = NULL;  // NULL means not set
	undo_item_data->position_new = -1;  // -1 means not set
	undo_item_data->position_old = slide_position;
	undo_item_data->slide_data = get_current_slide_data();
	undo_history_add_item(UNDO_DELETE_SLIDE, undo_item_data, TRUE);

	// Remove the current slide from the slide list
	set_slides(g_list_remove_link(get_slides(), get_current_slide()));

	// Remove the current slide from the film strip
	film_strip_selector = gtk_tree_view_get_selection(GTK_TREE_VIEW(get_film_strip_view()));
	gtk_tree_selection_get_selected(film_strip_selector, NULL, &selection_iter);
	gtk_list_store_remove(GTK_LIST_STORE(get_film_strip_store()), &selection_iter);

	// * Update the currently selected slide to point to the next slide *
	if (num_slides == (slide_position + 1))
	{
		// If we're deleting the last slide, we'll need to point to the previous one instead
		slide_position--;
	}
	set_current_slide(g_list_nth(get_slides(), slide_position));

	// Select the next thumbnail in the film strip and scroll to display it
	gtk_tree_view_get_cursor(GTK_TREE_VIEW(get_film_strip_view()), &new_path, NULL);
	if (NULL != new_path)
		old_path = new_path;  // Make a backup of the old path, so we can free it
	new_path = gtk_tree_path_new_from_indices(slide_position, -1);
	gtk_tree_view_set_cursor(GTK_TREE_VIEW(get_film_strip_view()), new_path, NULL, FALSE);
	gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(get_film_strip_view()), new_path, NULL, TRUE, 0.5, 0.0);
	if (NULL != old_path)
		gtk_tree_path_free(old_path);  // Free the old path

	// Redraw the timeline
	draw_timeline();

	// Redraw the workspace
	draw_workspace();

	// Set the changes made variable
	set_changes_made(TRUE);

	// Update the status bar
	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(get_status_bar()), _(" Slide deleted"));
	gdk_flush();
}
Ejemplo n.º 12
0
int main(void)
{
   ALLEGRO_DISPLAY *display;
   ALLEGRO_FONT *font;
   ALLEGRO_CONFIG *config;
   ALLEGRO_EVENT_QUEUE *queue;
   bool write = false;
   bool flip = false;
   bool quit;

   if (!al_init()) {
      abort_example("Could not init Allegro.\n");
   }

   al_init_font_addon();
   al_init_image_addon();
   al_install_keyboard();
   al_install_mouse();

   /* Read parameters from ex_vsync.ini. */
   config = al_load_config_file("ex_vsync.ini");
   if (!config) {
      config = al_create_config();
      write = true;
   }

   /* 0 -> Driver chooses.
    * 1 -> Force vsync on.
    * 2 -> Force vsync off.
    */
   vsync = option(config, "vsync", 0);

   fullscreen = option(config, "fullscreen", 0);
   frequency = option(config, "frequency", 0);

   /* Write the file back (so a template is generated on first run). */
   if (write) {
      al_save_config_file("ex_vsync.ini", config);
   }
   al_destroy_config(config);

   /* Vsync 1 means force on, 2 means forced off. */
   if (vsync)
      al_set_new_display_option(ALLEGRO_VSYNC, vsync, ALLEGRO_SUGGEST);
   
   /* Force fullscreen mode. */
   if (fullscreen) {
      al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW);
      /* Set a monitor frequency. */
      if (frequency)
         al_set_new_display_refresh_rate(frequency);
   }

   display = al_create_display(640, 480);
   if (!display) {
      abort_example("Error creating display.\n");
   }

   font = al_load_font("data/a4_font.tga", 0, 0);
   if (!font) {
      abort_example("Failed to load a4_font.tga\n");
   }

   queue = al_create_event_queue();
   al_register_event_source(queue, al_get_keyboard_event_source());
   al_register_event_source(queue, al_get_mouse_event_source());
   al_register_event_source(queue, al_get_display_event_source(display));

   quit = display_warning(queue, font);
   al_flush_event_queue(queue);

   while (!quit) {
      ALLEGRO_EVENT event;

      /* With vsync, this will appear as a 50% gray screen (maybe
       * flickering a bit depending on monitor frequency).
       * Without vsync, there will be black/white shearing all over.
       */
      if (flip)
         al_clear_to_color(al_map_rgb_f(1, 1, 1));
      else
         al_clear_to_color(al_map_rgb_f(0, 0, 0));
      
      al_flip_display();

      flip = !flip;

      while (al_get_next_event(queue, &event)) {
         switch (event.type) {
            case ALLEGRO_EVENT_DISPLAY_CLOSE:
               quit = true;

            case ALLEGRO_EVENT_KEY_DOWN:
               if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
                  quit = true;
         }
      }
      /* Let's not go overboard and limit flipping at 1000 Hz. Without
       * this my system locks up and requires a hard reboot :P
       */
      al_rest(0.001);
   }

   al_destroy_font(font);
   al_destroy_event_queue(queue);  

   return 0;
}
Ejemplo n.º 13
0
FX_ENTRY void FX_CALL
grDrawVertexArrayContiguous(FxU32 mode, FxU32 Count, void *pointers, FxU32 stride)
{
  unsigned int i;
  float *x, *y, *q, *s0, *t0, *s1, *t1, *z, *fog;
  unsigned char *pargb;
  LOG("grDrawVertexArrayContiguous(%d,%d,%d)\r\n", mode, Count, stride);

  if(nvidia_viewport_hack && !render_to_texture)
  {
    glViewport(0, viewport_offset, viewport_width, viewport_height);
    nvidia_viewport_hack = 0;
  }

  reloadTexture();

  if(need_to_compile) compile_shader();

  switch(mode)
  {
  case GR_TRIANGLE_STRIP:
    glBegin(GL_TRIANGLE_STRIP);
    break;
  case GR_TRIANGLE_FAN:
    glBegin(GL_TRIANGLE_FAN);
    break;
  default:
    display_warning("grDrawVertexArrayContiguous : unknown mode : %x", mode);
  }

  for (i=0; i<Count; i++)
  {
    x = (float*)((unsigned char*)pointers+stride*i) + xy_off/sizeof(float);
    y = (float*)((unsigned char*)pointers+stride*i) + xy_off/sizeof(float) + 1;
    z = (float*)((unsigned char*)pointers+stride*i) + z_off/sizeof(float);
    q = (float*)((unsigned char*)pointers+stride*i) + q_off/sizeof(float);
    pargb = (unsigned char*)pointers+stride*i + pargb_off;
    s0 = (float*)((unsigned char*)pointers+stride*i) + st0_off/sizeof(float);
    t0 = (float*)((unsigned char*)pointers+stride*i) + st0_off/sizeof(float) + 1;
    s1 = (float*)((unsigned char*)pointers+stride*i) + st1_off/sizeof(float);
    t1 = (float*)((unsigned char*)pointers+stride*i) + st1_off/sizeof(float) + 1;
    fog = (float*)((unsigned char*)pointers+stride*i) + fog_ext_off/sizeof(float);

    //if(*fog == 0.0f) *fog = 1.0f;

    if (nbTextureUnits > 2)
    {
      if (st0_en)
        glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *s0 / *q / (float)tex1_width,
        ytex(0, *t0 / *q / (float)tex1_height));
      if (st1_en)
        glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *s1 / *q / (float)tex0_width,
        ytex(1, *t1 / *q / (float)tex0_height));
    }
    else
    {
      if (st0_en)
        glTexCoord2f(*s0 / *q / (float)tex0_width,
        ytex(0, *t0 / *q / (float)tex0_height));
    }
    if (pargb_en)
      glColor4f(pargb[2]/255.0f, pargb[1]/255.0f, pargb[0]/255.0f, pargb[3]/255.0f);
    if (fog_enabled && fog_coord_support)
    {
      if(!fog_ext_en || fog_enabled != 2)
        glSecondaryColor3f((1.0f / *q) / 255.0f, 0.0f, 0.0f);
      else
        glSecondaryColor3f((1.0f / *fog) / 255.0f, 0.0f, 0.0f);
    }

    glVertex4f((*x - (float)widtho) / (float)(width/2) / *q,
      -(*y - (float)heighto) / (float)(height/2) / *q, ZCALC(*z, *q), 1.0f / *q);
  }
  glEnd();
}
gboolean working_area_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
	// Local variables
	gint				box_height;					// Height of the bounding box
	gint				box_width;					// Width of the bounding box
	GList				*collision_list = NULL;
	guint				count_int;
	gint				finish_x;					// X position at the layer objects finish time
	gint				finish_y;					// Y position at the layer objects finish time
	GList				*layer_pointer;
	GString				*message;					// Used to construct message strings
	guint				num_collisions;
	gint				onscreen_bottom;			// Y coordinate of bounding box bottom
	gint				onscreen_left;				// X coordinate of bounding box left
	gint				onscreen_right;				// X coordinate of bounding box right
	gint				onscreen_top;				// Y coordinate of bounding box top
	gint				pixmap_height;				// Height of the front store
	gint				pixmap_width;				// Width of the front store
	gfloat				scaled_height_ratio;		// Used to calculate a vertical scaling ratio
	gfloat				scaled_width_ratio;			// Used to calculate a horizontal scaling ratio
	gint				selected_row;				// Holds the number of the row that is selected
	gint				start_x;					// X position at the layer objects start time
	gint				start_y;					// Y position at the layer objects start time
	layer 				*this_layer_data;			// Pointer to the data for the selected layer
	slide				*this_slide_data;			// Alias to make things easier
	guint				tmp_int;					// Temporary integer


	// Only do this function if we have a front store available and a project loaded
	if ((NULL == get_front_store()) || (FALSE == get_project_active()))
	{
		return TRUE;
	}

	// Set the delete key focus to be layers
	set_delete_focus(FOCUS_LAYER);

	// Change the focus of the window to be this widget
	gtk_widget_grab_focus(GTK_WIDGET(widget));

	// Initialise some things
	this_slide_data = get_current_slide_data();
	gdk_drawable_get_size(GDK_PIXMAP(get_front_store()), &pixmap_width, &pixmap_height);

	// Check for primary mouse button click
	if (1 != event->button)
	{
		// Not a primary mouse click, so return
		return TRUE;
	}

	// Reset the mouse drag toggle
	set_mouse_dragging(FALSE);

	// Check if this was a double mouse click.  If it was, open an edit dialog
	if (GDK_2BUTTON_PRESS == event->type)
	{
		// Open an edit dialog
		layer_edit();

		return TRUE;
	}

	// Check if this was a triple mouse click.  If it was, ignore it
	if (GDK_3BUTTON_PRESS == event->type)
	{
		return TRUE;
	}

	// If we're presently creating a new highlight layer, store the mouse coordinates
	if (TYPE_HIGHLIGHT == get_new_layer_selected())
	{
		// Save the mouse coordinates
		set_stored_x(event->x);
		set_stored_y(event->y);

		// Reset the invalidation area
		set_invalidation_end_x(event->x);
		set_invalidation_end_y(event->y);
		set_invalidation_start_x(event->x - 1);
		set_invalidation_start_y(event->y - 1);

		return TRUE;
	}

	// If the user has clicked on the start or end points for the selected layer, we
	// don't want to do the collision detection below that changes layers
	if (END_POINTS_INACTIVE == get_end_point_status())
	{
		// * Check if the user is clicking on the layer start or end points *

		// Calculate the height and width scaling values for the main drawing area at its present size
		scaled_height_ratio = (gfloat) get_project_height() / (gfloat) pixmap_height;
		scaled_width_ratio = (gfloat) get_project_width() / (gfloat) pixmap_width;

		// Determine which row is selected in the time line
		selected_row = time_line_get_selected_layer_num(this_slide_data->timeline_widget);
		layer_pointer = g_list_first(this_slide_data->layers);
		this_layer_data = g_list_nth_data(layer_pointer, selected_row);

		// If the layer data isn't accessible, then don't run this function
		if (NULL == this_layer_data)
		{
			return TRUE;
		}

		// Calculate start and end points
		finish_x = (this_layer_data->x_offset_finish / scaled_width_ratio) + END_POINT_HORIZONTAL_OFFSET;
		finish_y = (this_layer_data->y_offset_finish / scaled_height_ratio) + END_POINT_VERTICAL_OFFSET;
		start_x = (this_layer_data->x_offset_start / scaled_width_ratio) + END_POINT_HORIZONTAL_OFFSET;
		start_y = (this_layer_data->y_offset_start / scaled_height_ratio) + END_POINT_VERTICAL_OFFSET;

		// Is the user clicking on an end point?
		if (((event->x >= start_x)							// Start point
			&& (event->x <= start_x + END_POINT_WIDTH)
			&& (event->y >= start_y)
			&& (event->y <= start_y + END_POINT_HEIGHT)) ||
			((event->x >= finish_x)							// End point
			&& (event->x <= finish_x + END_POINT_WIDTH)
			&& (event->y >= finish_y)
			&& (event->y <= finish_y + END_POINT_HEIGHT)))
		{
			// Retrieve the layer size information
			switch (this_layer_data->object_type)
			{
				case TYPE_EMPTY:
					// We can't drag an empty layer, so reset things and return
					set_mouse_dragging(FALSE);
					set_end_point_status(END_POINTS_INACTIVE);
					set_stored_x(-1);
					set_stored_y(-1);
					return TRUE;

				case TYPE_HIGHLIGHT:
					box_width = ((layer_highlight *) this_layer_data->object_data)->width;
					box_height = ((layer_highlight *) this_layer_data->object_data)->height;
					break;

				case TYPE_GDK_PIXBUF:
					// If this is the background layer, then we ignore it
					if (TRUE == this_layer_data->background)
					{
						set_mouse_dragging(FALSE);
						set_end_point_status(END_POINTS_INACTIVE);
						set_stored_x(-1);
						set_stored_y(-1);
						return TRUE;
					}

					// No it's not, so process it
					box_width = ((layer_image *) this_layer_data->object_data)->width;
					box_height = ((layer_image *) this_layer_data->object_data)->height;
					break;

				case TYPE_MOUSE_CURSOR:
					box_width = ((layer_mouse *) this_layer_data->object_data)->width;
					box_height = ((layer_mouse *) this_layer_data->object_data)->height;
					break;

				case TYPE_TEXT:
					box_width = ((layer_text *) this_layer_data->object_data)->rendered_width;
					box_height = ((layer_text *) this_layer_data->object_data)->rendered_height;
					break;

				default:
					message = g_string_new(NULL);
					g_string_printf(message, "%s ED377: %s", _("Error"), _("Unknown layer type."));
					display_warning(message->str);
					g_string_free(message, TRUE);

					return TRUE;  // Unknown layer type, so no idea how to extract the needed data for the next code
			}

			// Work out the bounding box boundaries (scaled)
			if ((event->x >= start_x)							// Left
				&& (event->x <= start_x + END_POINT_WIDTH)		// Right
				&& (event->y >= start_y)						// Top
				&& (event->y <= start_y + END_POINT_HEIGHT))	// Bottom
			{
				// Start point clicked
				onscreen_left = this_layer_data->x_offset_start / scaled_width_ratio;
				onscreen_top = this_layer_data->y_offset_start / scaled_width_ratio;;
				onscreen_right = (this_layer_data->x_offset_start + box_width) / scaled_height_ratio;
				onscreen_bottom = (this_layer_data->y_offset_start + box_height) / scaled_height_ratio;
			} else
			{
				// End point clicked
				onscreen_left = this_layer_data->x_offset_finish / scaled_width_ratio;
				onscreen_top = this_layer_data->y_offset_finish / scaled_width_ratio;;
				onscreen_right = (this_layer_data->x_offset_finish + box_width) / scaled_height_ratio;
				onscreen_bottom = (this_layer_data->y_offset_finish + box_height) / scaled_height_ratio;
			}

			// Ensure the bounding box doesn't go out of bounds
			onscreen_left = CLAMP(onscreen_left, 2, pixmap_width - 2);
			onscreen_top = CLAMP(onscreen_top, 2, pixmap_height - 2);
			onscreen_right = CLAMP(onscreen_right, 2, pixmap_width - 2);
			onscreen_bottom = CLAMP(onscreen_bottom, 2, pixmap_height - 2);

			// Draw a bounding box onscreen
			draw_bounding_box(onscreen_left, onscreen_top, onscreen_right, onscreen_bottom);

			// End point clicked, so we return in order to avoid the collision detection
			return TRUE;
		}
	}

	// * Do collision detection here to determine if the user has clicked on a layer's object *

	this_slide_data = get_current_slide_data();
	calculate_object_boundaries();
	collision_list = detect_collisions(collision_list, event->x, event->y);
	if (NULL == collision_list)
	{
		// If there was no collision, then select the background layer
		time_line_set_selected_layer_num(this_slide_data->timeline_widget, this_slide_data->num_layers - 1);  // *Needs* the -1, don't remove

		// Clear any existing handle box
		gdk_draw_drawable(GDK_DRAWABLE(get_main_drawing_area()->window), GDK_GC(get_main_drawing_area()->style->fg_gc[GTK_WIDGET_STATE(get_main_drawing_area())]),
				GDK_PIXMAP(get_front_store()), 0, 0, 0, 0, -1, -1);

		// Reset the stored mouse coordinates
		set_stored_x(-1);
		set_stored_y(-1);

		// Free the memory allocated during the collision detection
		g_list_free(collision_list);
		collision_list = NULL;

		return TRUE;
	}

	// * To get here there must have been at least one collision *

	// Save the mouse coordinates
	set_stored_x(event->x);
	set_stored_y(event->y);

	// Determine which layer the user has selected in the timeline
	selected_row = time_line_get_selected_layer_num(this_slide_data->timeline_widget);

	// Is the presently selected layer in the collision list?
	collision_list = g_list_first(collision_list);
	num_collisions = g_list_length(collision_list);
	for (count_int = 0; count_int < num_collisions; count_int++)
	{
		collision_list = g_list_first(collision_list);
		collision_list = g_list_nth(collision_list, count_int);
		layer_pointer = g_list_first(this_slide_data->layers);
		tmp_int = g_list_position(layer_pointer, ((boundary_box *) collision_list->data)->layer_ptr);
		if (tmp_int == selected_row)
		{
			// Return if the presently selected row is in the collision list, as we don't want to change our selected layer
			return TRUE;
		}
	}

	// * To get here, the presently selected layer wasn't in the collision list *

	// The presently selected row is not in the collision list, so move the selection row to the first collision
	collision_list = g_list_first(collision_list);
	selected_row = g_list_position(this_slide_data->layers, ((boundary_box *) collision_list->data)->layer_ptr);
	time_line_set_selected_layer_num(this_slide_data->timeline_widget, selected_row);

	// Draw a handle box around the new selected object
	draw_handle_box();

	// Free the memory allocated during the collision detection
	g_list_free(collision_list);
	collision_list = NULL;

	return TRUE;
}
Ejemplo n.º 15
0
gboolean swf_add_mouse_click(SWFMovie this_movie, gint click_type)
{
	// Local variables
	gfloat				click_duration;
	guint				click_frames;
	GString				*click_name;				// The name of the mouse click sound we'll need to play
	guint				i;							// Counter
	GString				*message;					// Used to construct message strings
	SWFDisplayItem 		sound_display_item;
	FILE				*sound_file;				// The file we load the sound from
	SWFMovieClip		sound_movie_clip;			// Movie clip specifically to hold a sound
	SWFSoundStream 		sound_stream;				// The sound we use gets loaded into this
	gchar				*sound_pathname = NULL;		// Full pathname to a sound file to load is constructed in this
	SWFAction			swf_action;					// Used when constructing action script


	// Initialisation
	click_name = g_string_new(NULL);

	// Determine the sound file to load
	switch (click_type)
	{
		case MOUSE_LEFT_ONE:
		case MOUSE_RIGHT_ONE:
		case MOUSE_MIDDLE_ONE:

			// If we've already added the sound to the movie, we don't need to add it again
			if (FALSE == get_mouse_click_single_added())
			{
				// Single click mouse sound
				sound_pathname = g_build_path(G_DIR_SEPARATOR_S, SOUND_DIR, "mouse_single_click.mp3", NULL);

				// Make sure we only add this click sound once
				set_mouse_click_single_added(TRUE);
			}

			click_name = g_string_assign(click_name, "mousesingleclick");
			click_duration = 0.5;
			break;

		case MOUSE_LEFT_DOUBLE:
		case MOUSE_RIGHT_DOUBLE:
		case MOUSE_MIDDLE_DOUBLE:

			// If we've already added the sound to the movie, we don't need to add it again
			if (FALSE == get_mouse_click_double_added())
			{
				// Double click mouse sound
				sound_pathname = g_build_path(G_DIR_SEPARATOR_S, SOUND_DIR, "mouse_double_click.mp3", NULL);

				// Make sure we only add this click sound once
				set_mouse_click_double_added(TRUE);
			}

			click_name = g_string_assign(click_name, "mousedoubleclick");
			click_duration = 0.5;
			break;

		case MOUSE_LEFT_TRIPLE:
		case MOUSE_RIGHT_TRIPLE:
		case MOUSE_MIDDLE_TRIPLE:

			// If we've already added the sound to the movie, we don't need to add it again
			if (FALSE == get_mouse_click_triple_added())
			{
				// Triple click mouse sound
				sound_pathname = g_build_path(G_DIR_SEPARATOR_S, SOUND_DIR, "mouse_triple_click.mp3", NULL);

				// Make sure we only add this click sound once
				set_mouse_click_triple_added(TRUE);
			}

			click_name = g_string_assign(click_name, "mousetripleclick");
			click_duration = 0.5;
			break;
	}

	if (NULL != sound_pathname)
	{
		// Create the sound object we'll be using
		if (get_debug_level()) printf("%s: '%s'\n", _("Full path name to sound file is"), sound_pathname);

		// Load the sound file
		sound_file = fopen(sound_pathname, "rb");
		if (NULL == sound_file)
		{
			// Something went wrong when loading the sound file, so return
			message = g_string_new(NULL);
			g_string_printf(message, "%s ED412: %s", _("Error"), _("Something went wrong when opening a mouse click sound file."));
			display_warning(message->str);
			g_string_free(message, TRUE);
			return FALSE;
		}
		sound_stream = newSWFSoundStream(sound_file);

		// Create a new movie clip file, containing only the sound
		sound_movie_clip = newSWFMovieClip();

		// Ensure the clip doesn't start out playing nor keep looping
		swf_action = compileSWFActionCode("this.stop(); ");
		SWFMovieClip_add(sound_movie_clip, (SWFBlock) swf_action);
		SWFMovieClip_nextFrame(sound_movie_clip);

		// Add the sound stream to the sound movie clip
		SWFMovieClip_setSoundStream(sound_movie_clip, sound_stream, 1);
		SWFMovieClip_nextFrame(sound_movie_clip);

		// Add extra frames to allow the click to play it's full length
		click_frames = roundf(click_duration * get_frames_per_second());
		for (i = 0; i < click_frames; i++)
		{
			SWFMovieClip_nextFrame(sound_movie_clip);
		}

		// Add the sound movie clip to the swf movie
		sound_display_item = SWFMovie_add(this_movie, (SWFBlock) sound_movie_clip);

		// Name the display item
		SWFDisplayItem_setName(sound_display_item, click_name->str);

		// Ensure the object is at the correct display depth
		SWFDisplayItem_setDepth(sound_display_item, 1000 + click_type); // Trying to pick a non conflicting depth
	}

	// Free the memory allocated in this functions
	g_string_free(click_name, TRUE);

	return TRUE;
}
Ejemplo n.º 16
0
layer *read_mouse_layer(xmlDocPtr document, xmlNodePtr this_node)
{
	// Local variables
	GString				*message;					// Used to construct message strings
	layer				*tmp_layer;					// Temporary layer
	layer_mouse			*tmp_mouse_ob;				// Temporary mouse layer object
	xmlChar				*tmp_xmlChar;				// Temporary xmlChar pointer
	gboolean			usable_input = TRUE;		// Used as a flag to indicate if all validation was successful
	gfloat				*validated_gfloat;			// Receives known good gfloat values from the validation function
	guint				*validated_guint;			// Receives known good guint values from the validation function
	GString				*validated_string;			// Receives known good strings from the validation function


	// Initialisation
	message = g_string_new(NULL);

	// Construct a new mouse pointer layer
	tmp_mouse_ob = g_new0(layer_mouse, 1);
	tmp_layer = g_new0(layer, 1);
	tmp_layer->object_type = TYPE_MOUSE_CURSOR;
	tmp_layer->object_data = (GObject *) tmp_mouse_ob;
	tmp_layer->external_link = g_string_new(NULL);
	tmp_layer->visible = TRUE;
	tmp_layer->background = FALSE;
	tmp_layer->external_link_window = g_string_new("_self");
	tmp_layer->start_time = 0.0;
	tmp_layer->transition_in_type = TRANS_LAYER_NONE;
	tmp_layer->transition_in_duration = 0.0;
	tmp_layer->duration = get_default_layer_duration();
	tmp_layer->transition_out_type = TRANS_LAYER_NONE;
	tmp_layer->transition_out_duration = 0.0;

	// Load the highlight layer values
	while (NULL != this_node)
	{
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "x_offset_start")))
		{
			// Get the starting x offset
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_guint = validate_value(X_OFFSET, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_guint)
			{
				g_string_printf(message, "%s ED248: %s", _("Error"), _("There was something wrong with an x offset start value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
				tmp_layer->x_offset_start = 0;  // Fill in the value, just to be safe
			} else
			{
				tmp_layer->x_offset_start = *validated_guint;
				g_free(validated_guint);
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "y_offset_start")))
		{
			// Get the starting y offset
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_guint = validate_value(Y_OFFSET, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_guint)
			{
				g_string_printf(message, "%s ED249: %s", _("Error"), _("There was something wrong with a y offset start value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
				tmp_layer->y_offset_start = 0;  // Fill in the value, just to be safe
			} else
			{
				tmp_layer->y_offset_start = *validated_guint;
				g_free(validated_guint);
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "x_offset_finish")))
		{
			// Get the finishing x offset
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_guint = validate_value(X_OFFSET, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_guint)
			{
				g_string_printf(message, "%s ED250: %s", _("Error"), _("There was something wrong with an x offset finish value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
				tmp_layer->x_offset_finish = 0;  // Fill in the value, just to be safe
			} else
			{
				tmp_layer->x_offset_finish = *validated_guint;
				g_free(validated_guint);
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "y_offset_finish")))
		{
			// Get the finishing y offset
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_guint = validate_value(Y_OFFSET, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_guint)
			{
				g_string_printf(message, "%s ED251: %s", _("Error"), _("There was something wrong with a y offset finish value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
				tmp_layer->y_offset_finish = 0;  // Fill in the value, just to be safe
			} else
			{
				tmp_layer->y_offset_finish = *validated_guint;
				g_free(validated_guint);
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "width")))
		{
			// Get the width
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_guint = validate_value(LAYER_WIDTH, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_guint)
			{
				g_string_printf(message, "%s ED252: %s", _("Error"), _("There was something wrong with a layer width value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
				tmp_mouse_ob->width = 1;  // Fill in the value, just to be safe
			} else
			{
				tmp_mouse_ob->width = *validated_guint;
				g_free(validated_guint);
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "height")))
		{
			// Get the height
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_guint = validate_value(LAYER_HEIGHT, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_guint)
			{
				g_string_printf(message, "%s ED253: %s", _("Error"), _("There was something wrong with a layer height value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
				tmp_mouse_ob->height = 1;  // Fill in the value, just to be safe
			} else
			{
				tmp_mouse_ob->height = *validated_guint;
				g_free(validated_guint);
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "click")))
		{
			// Get the mouse click type
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_string = validate_value(MOUSE_CLICK, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_string)
			{
				g_string_printf(message, "%s ED254: %s", _("Error"), _("There was something wrong with a mouse click value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
				tmp_mouse_ob->click = MOUSE_NONE;  // Fill in the value, just to be safe
			} else
			{
				tmp_mouse_ob->click = MOUSE_NONE;  // Set the default
				if (0 == g_ascii_strncasecmp(validated_string->str, "left_one", 8))
					tmp_mouse_ob->click = MOUSE_LEFT_ONE;
				if (0 == g_ascii_strncasecmp(validated_string->str, "left_double", 11))
					tmp_mouse_ob->click = MOUSE_LEFT_DOUBLE;
				if (0 == g_ascii_strncasecmp(validated_string->str, "left_triple", 11))
					tmp_mouse_ob->click = MOUSE_LEFT_TRIPLE;
				if (0 == g_ascii_strncasecmp(validated_string->str, "right_one", 9))
					tmp_mouse_ob->click = MOUSE_RIGHT_ONE;
				if (0 == g_ascii_strncasecmp(validated_string->str, "right_double", 12))
					tmp_mouse_ob->click = MOUSE_RIGHT_DOUBLE;
				if (0 == g_ascii_strncasecmp(validated_string->str, "right_triple", 12))
					tmp_mouse_ob->click = MOUSE_RIGHT_TRIPLE;
				if (0 == g_ascii_strncasecmp(validated_string->str, "middle_one", 10))
					tmp_mouse_ob->click = MOUSE_MIDDLE_ONE;
				if (0 == g_ascii_strncasecmp(validated_string->str, "middle_double", 13))
					tmp_mouse_ob->click = MOUSE_MIDDLE_DOUBLE;
				if (0 == g_ascii_strncasecmp(validated_string->str, "middle_triple", 13))
					tmp_mouse_ob->click = MOUSE_MIDDLE_TRIPLE;
				g_string_free(validated_string, TRUE);
				validated_string = NULL;
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "start_time")))
		{
			// Get the start time
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_gfloat = validate_value(LAYER_DURATION, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_gfloat)
			{
				g_string_printf(message, "%s ED344: %s", _("Error"), _("There was something wrong with a layer start time value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
				tmp_layer->start_time = 0;  // Fill in the value, just to be safe
			} else
			{
				tmp_layer->start_time = *validated_gfloat;
				g_free(validated_gfloat);
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "duration")))
		{
			// Get the finish frame
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_gfloat = validate_value(LAYER_DURATION, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_gfloat)
			{
				g_string_printf(message, "%s ED345: %s", _("Error"), _("There was something wrong with a layer duration value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
				tmp_layer->duration = 0;  // Fill in the value, just to be safe
			} else
			{
				tmp_layer->duration = *validated_gfloat;
				g_free(validated_gfloat);
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "visible")))
		{
			// Get the visibility
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_guint = validate_value(LAYER_VISIBLE, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_guint)
			{
				g_string_printf(message, "%s ED257: %s", _("Error"), _("There was something wrong with a layer visibility value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
				tmp_layer->visible = 0;  // Fill in the value, just to be safe
			} else
			{
				tmp_layer->visible = *validated_guint;
				g_free(validated_guint);
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "name")))
		{
			// Get the name of the layer
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_string = validate_value(LAYER_NAME, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_string)
			{
				g_string_printf(message, "%s ED258: %s", _("Error"), _("There was something wrong with a layer name value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
				tmp_layer->name = g_string_new("Empty");  // Fill in the value, just to be safe
			} else
			{
				tmp_layer->name = validated_string;  // We keep the validated string instead of copying then freeing it
				validated_string = NULL;
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "external_link")))
		{
			// Get the URL associated with the layer
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_string = validate_value(EXTERNAL_LINK, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_string)
			{
				g_string_printf(message, "%s ED259: %s", _("Error"), _("There was something wrong with an external link value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
			} else
			{
				tmp_layer->external_link = g_string_assign(tmp_layer->external_link, validated_string->str);
				g_string_free(validated_string,TRUE);
				validated_string = NULL;
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "external_link_window")))
		{
			// Get the window to open the URL associated with the layer
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_string = validate_value(EXTERNAL_LINK_WINDOW, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_string)
			{
				g_string_printf(message, "%s ED260: %s", _("Error"), _("There was something wrong with an external link target window value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
			} else
			{
				tmp_layer->external_link_window = g_string_assign(tmp_layer->external_link_window, validated_string->str);
				g_string_free(validated_string,TRUE);
				validated_string = NULL;
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "transition_in_type")))
		{
			// Get the type of transition in
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_string = validate_value(TRANSITION_TYPE, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_string)
			{
				g_string_printf(message, "%s ED321: %s", _("Error"), _("There was something wrong with a transition in type value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
			} else
			{
				if (0 == g_ascii_strncasecmp(validated_string->str, "fade", 4))
				{
					tmp_layer->transition_in_type = TRANS_LAYER_FADE;
				} else
				{
					tmp_layer->transition_in_type = TRANS_LAYER_NONE;
				}
				g_string_free(validated_string, TRUE);
				validated_string = NULL;
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "transition_in_duration")))
		{
			// Get the transition in duration
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_gfloat = validate_value(TRANSITION_DURATION, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_gfloat)
			{
				g_string_printf(message, "%s ED322: %s", _("Error"), _("There was something wrong with a transition in duration value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
				tmp_layer->transition_in_duration = 1;  // Fill in the value, just to be safe
			} else
			{
				tmp_layer->transition_in_duration = *validated_gfloat;
				g_free(validated_gfloat);
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "transition_out_type")))
		{
			// Get the type of transition out
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_string = validate_value(TRANSITION_TYPE, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_string)
			{
				g_string_printf(message, "%s ED323: %s", _("Error"), _("There was something wrong with a transition out type value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
			} else
			{
				if (0 == g_ascii_strncasecmp(validated_string->str, "fade", 4))
				{
					tmp_layer->transition_out_type = TRANS_LAYER_FADE;
				} else
				{
					tmp_layer->transition_out_type = TRANS_LAYER_NONE;
				}
				g_string_free(validated_string, TRUE);
				validated_string = NULL;
			}
		}
		if ((!xmlStrcmp(this_node->name, (const xmlChar *) "transition_out_duration")))
		{
			// Get the transition out duration
			tmp_xmlChar = xmlNodeListGetString(document, this_node->xmlChildrenNode, 1);
			validated_gfloat = validate_value(TRANSITION_DURATION, V_CHAR, tmp_xmlChar);
			xmlFree(tmp_xmlChar);
			if (NULL == validated_gfloat)
			{
				g_string_printf(message, "%s ED324: %s", _("Error"), _("There was something wrong with a transition out duration value in the project file."));
				display_warning(message->str);
				usable_input = FALSE;
				tmp_layer->transition_out_duration = 1;  // Fill in the value, just to be safe
			} else
			{
				tmp_layer->transition_out_duration = *validated_gfloat;
				g_free(validated_gfloat);
			}
		}
		this_node = this_node->next;
	}

	// Free memory allocated in this function
	g_string_free(message, TRUE);

	// Return the validated mouse layer, or an indicator of failure
	if (TRUE == usable_input)
	{
		return tmp_layer;
	} else
	{
		// Free the newly allocated mouse layer data, as it didn't pass validation, so we won't use it
		layer_free(tmp_layer);
		return NULL;
	}
}
Ejemplo n.º 17
0
void *validate_value(gint value_id, gint input_type, void *value)
{
	// Local variables
	guint				base_type;
	guint				capabilities;
	gboolean			capability_check;
	gchar				*conversion_buffer = NULL;			// Used when converting between unicode character types
	gchar				*decimal_point;
	GString				*error_string;
	gchar				input_char;
	gunichar			input_char_unicode;
	gchar				*input_ptr;
	struct lconv		*locale_info;
	gboolean			match_found;
	gint				output_gint;
	gint				*output_gint_ptr;
	gfloat				output_gfloat;
	gfloat				*output_gfloat_ptr;
	GString				*output_gstring;
	guint				output_guint;
	guint				*output_guint_ptr;
	guint				string_counter;
	gint				string_length;
	gint				string_max;
	guint				string_min;
	gfloat				value_max;
	gfloat				value_min;


	// Initialise various things
	base_type = get_valid_fields_base_type(value_id);
	capabilities = get_valid_fields_capabilities(value_id);
	input_ptr = (gchar *) value;
	output_gstring = g_string_new(NULL);
	locale_info = localeconv();
	decimal_point = locale_info->decimal_point;

	switch (base_type)
	{
		case V_CHAR:

			// * We're validating a char or string *

			// We can only validate string input for this type of value
			if (V_CHAR != input_type)
			{
				return NULL;
			}

			// Get the length of the input string
			string_max = get_valid_fields_max_value(value_id);
			string_min = get_valid_fields_min_value(value_id);
			string_length = g_utf8_strlen(input_ptr, -1);

			// If the length of the string isn't in the acceptable range, return NULL
			if (string_length < string_min)
				return NULL;
			if ((string_length > string_max) && (-1 != string_max))  // -1 for string_max means "no maximum limit"
				return NULL;
			if (0 == string_length)
			{
				// 0 length string, so we just return it
				return output_gstring;
			}

			// Sanitise each character of the input string
			for (string_counter = 0; string_counter < string_length; string_counter++)
			{
				// Get the next character
				input_char_unicode = g_utf8_get_char_validated(input_ptr, -1);
				if ((gunichar)-1 == input_char_unicode)
				{
					// The returned character was not a valid unicode character, so we indicate failure
					return NULL;
				}
				if ((gunichar)-2 == input_char_unicode)
				{
					// The returned character was not a valid unicode character, so we indicate failure
					return NULL;
				}

				// Convert the character to UTF-8 so we can process it
				conversion_buffer = g_ucs4_to_utf8(&input_char_unicode, 1, NULL, NULL, NULL);

				// Determine which character we're examining
				if (TRUE == g_unichar_isalnum(input_char_unicode))
				{
					// It's a standard unicode alphanumeric character, so we accept it as is
					g_string_append_printf(output_gstring, "%s", conversion_buffer);
					input_ptr = g_utf8_find_next_char(input_ptr, NULL);
				}
				else
				{
					// * The input wasn't a standard alphanumic character, so check if it *
					// * is one of the characters in the capabilities list for this field *
					match_found = FALSE;
					capability_check = V_ANY_UNICHAR & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have any valid unicode character
						if (TRUE == g_unichar_validate(input_char_unicode))
						{
							// Yes, this is a valid unicode character
							match_found = TRUE;
							g_string_append_printf(output_gstring, "%s", conversion_buffer);
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_SPACES & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have spaces
						if (0 == g_strcmp0(" ", conversion_buffer))
						{
							// Yes, this is a space character
							match_found = TRUE;
							g_string_append_printf(output_gstring, "%s", conversion_buffer);
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_FULL_STOP & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have full stops
						if (0 == g_strcmp0(".", conversion_buffer))
						{
							// Yes, this is a full stop character
							match_found = TRUE;
							g_string_append_printf(output_gstring, "%s", conversion_buffer);
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_HYPENS & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have hypens
						if (0 == g_strcmp0("-", conversion_buffer))
						{
							// Yes, this is a hypen character
							match_found = TRUE;
							g_string_append_printf(output_gstring, "%s", conversion_buffer);
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_UNDERSCORES & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have underscores
						if (0 == g_strcmp0("_", conversion_buffer))
						{
							// Yes, this is an underscore character
							match_found = TRUE;
							g_string_append_printf(output_gstring, "%s", conversion_buffer);
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_PATH_SEP & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have path separator characters ('/', '\')
						if ((0 == g_strcmp0("/", conversion_buffer)) || (0 == g_strcmp0("\\", conversion_buffer)))
						{
							// Yes, this is a path separator character
							match_found = TRUE;
							output_gstring = g_string_append_c(output_gstring, G_DIR_SEPARATOR);  // Output the OS correct version
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_EQUALS & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have equals signs
						if (0 == g_strcmp0("=", conversion_buffer))
						{
							// Yes, this is an equals sign character
							match_found = TRUE;
							g_string_append_printf(output_gstring, "%s", conversion_buffer);
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_FORWARD_SLASHES & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have forward slashes
						if (0 == g_strcmp0("/", conversion_buffer))
						{
							// Yes, this is a forward slash character
							match_found = TRUE;
							g_string_append_printf(output_gstring, "%s", conversion_buffer);
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_NEW_LINES & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have new line characters
						if (0 == g_strcmp0("\n", conversion_buffer))
						{
							// Yes, this is a new line character
							match_found = TRUE;
							output_gstring = g_string_append_c(output_gstring, '\n');
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_PLUSES & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have pluses
						if (0 == g_strcmp0("+", conversion_buffer))
						{
							// Yes, this is a plus character
							match_found = TRUE;
							g_string_append_printf(output_gstring, "%s", conversion_buffer);
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_PERCENT & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have the percent sign
						if (0 == g_strcmp0("%", conversion_buffer))
						{
							// Yes, this is a percent sign
							match_found = TRUE;
							g_string_append_printf(output_gstring, "%s", conversion_buffer);
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_COLON & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have colons
						if (0 == g_strcmp0(":", conversion_buffer))
						{
							// Yes, this is a colon character
							match_found = TRUE;
							g_string_append_printf(output_gstring, "%s", conversion_buffer);
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_AT & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have the at symbol
						if (0 == g_strcmp0("@", conversion_buffer))
						{
							// Yes, this is an at character
							match_found = TRUE;
							g_string_append_printf(output_gstring, "%s", conversion_buffer);
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_QUESTION & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have the question mark
						if (0 == g_strcmp0("?", conversion_buffer))
						{
							// Yes, this is a question mark character
							match_found = TRUE;
							g_string_append_printf(output_gstring, "%s", conversion_buffer);
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}
					capability_check = V_AMPERSAND & capabilities;
					if (FALSE != capability_check)
					{
						// This field is allowed to have the ampersand character
						if (0 == g_strcmp0("&", conversion_buffer))
						{
							// Yes, this is an ampersand character
							match_found = TRUE;
							g_string_append_printf(output_gstring, "%s", conversion_buffer);
							input_ptr = g_utf8_find_next_char(input_ptr, NULL);
							continue;
						}
					}

					// The character we are checking is not in the list of valid inputs for this field
					if (FALSE == match_found)
					{
						g_free(conversion_buffer);
						g_string_free(output_gstring, TRUE);
						return NULL;
					}
				}
			}

			// Remove any leading and/or trailing white space
			output_gstring->str = g_strstrip(output_gstring->str);
			output_gstring->len = strlen(output_gstring->str);

			// Recheck the length of the output string
			if (output_gstring->len < string_min)
			{
				g_free(conversion_buffer);
				g_string_free(output_gstring, TRUE);
				return NULL;
			}

			// Free the memory used so far
			if (0 != string_length)
			{
				g_free(conversion_buffer);
			}

			// The string seems to be valid, so return it for use
			return output_gstring;

			break;

		case V_FLOAT_UNSIGNED:

			// * We're validating an unsigned float *

			// If we're working with string input, we need to convert it to a float first
			if (V_CHAR == input_type)
			{
				// * We're working with string input *

				// Get the length of the input string
				string_length = strlen((gchar *) value);
	
				// Sanitise each character of the input string
				for (string_counter = 0; string_counter < string_length; string_counter++)
				{
					input_char = ((gchar *) value)[string_counter];

					// Check for decimal digits
					if (TRUE == g_ascii_isdigit(input_char))
					{
						output_gstring = g_string_append_c(output_gstring, input_char);
					}
					else
					{
						// This field is allowed to have full stops.  Is this character a full stop?
						if (0 == g_ascii_strncasecmp(".", &input_char, 1))
						{
							// Yes, this is a full stop character
							output_gstring = g_string_append_c(output_gstring, *decimal_point);
							match_found = TRUE;
							continue;
						}

						// This field is allowed to have commas (equiv to full stop in some locales).  Is this character a comma?
						if (0 == g_ascii_strncasecmp(",", &input_char, 1))
						{
							// Yes, this is a comma character
							output_gstring = g_string_append_c(output_gstring, *decimal_point);
							match_found = TRUE;
							continue;
						}

						// The character we are checking is not in the list of valid inputs for this field
						if (FALSE == match_found)
						{
							g_string_free(output_gstring, TRUE);
							return NULL;
						}
					}
				}

				// Convert the string to a float
				output_gfloat = (gfloat) g_strtod(output_gstring->str, NULL);
			}
			else
			{
				// We're working with a float input, so just copy the value directly
				output_gfloat = *((gfloat *) value);
			}

			// Is the float value within the defined bounds?
			value_max = get_valid_fields_max_value(value_id);
			value_min = get_valid_fields_min_value(value_id);
			if ((output_gfloat < value_min) || (output_gfloat > value_max))
			{
				// Value is out of bounds, so fail
				g_string_free(output_gstring, TRUE);
				return NULL;
			}

			// The value looks ok, so we copy it to newly allocated memory, to pass it back
			output_gfloat_ptr = g_try_new0(gfloat, 1);
			if (NULL == output_gfloat_ptr)
			{
				// Unable to allocate memory for the new value, so fail
				g_string_free(output_gstring, TRUE);
				return NULL;
			}
			*output_gfloat_ptr = output_gfloat;

			// Free the string memory allocated in this function
			g_string_free(output_gstring, TRUE);

			return output_gfloat_ptr;

		case V_INT_UNSIGNED:

			// * We're validating an unsigned integer *

			// If we're working with string input, we need to convert it to an integer first
			if (V_CHAR == input_type)
			{
				// * We're working with string input *

				// Get the length of the input string
				string_length = strlen((gchar *) value);
	
				// Sanitise each character of the input string
				for (string_counter = 0; string_counter < string_length; string_counter++)
				{
					input_char = ((gchar *) value)[string_counter];

					// Check for decimal digits
					if (TRUE == g_ascii_isdigit(input_char))
					{
						output_gstring = g_string_append_c(output_gstring, input_char);
					}
					else
					{
						// This wasn't a valid character
						g_string_free(output_gstring, TRUE);
						return NULL;
					}
				}

				// Convert the string to an integer
				output_guint = atoi(output_gstring->str);
			}
			else
			{
				// We're working with integer input, so just copy the value directly
				output_guint = *((guint *) value);
			}

			// Is the integer value within the defined bounds?
			value_max = get_valid_fields_max_value(value_id);
			value_min = get_valid_fields_min_value(value_id);
			if ((output_guint < value_min) || (output_guint > value_max))
			{
				// Value is out of bounds, so fail
				g_string_free(output_gstring, TRUE);
				return NULL;
			}

			// The value looks ok, so we copy it to newly allocated memory, to pass it back
			output_guint_ptr = g_try_new0(guint, 1);
			if (NULL == output_guint_ptr)
			{
				// Unable to allocate memory for the new value, so fail
				g_string_free(output_gstring, TRUE);
				return NULL;
			}
			*output_guint_ptr = output_guint;

			// Free the string memory allocated in this function
			g_string_free(output_gstring, TRUE);

			return output_guint_ptr;

		case V_INT_SIGNED:

			// * We're validating a signed integer *

			// If we're working with string input, we need to convert it to an integer first
			if (V_CHAR == input_type)
			{
				// * We're working with string input *

				// Get the length of the input string
				string_length = strlen((gchar *) value);

				// Sanitise each character of the input string
				for (string_counter = 0; string_counter < string_length; string_counter++)
				{
					input_char = ((gchar *) value)[string_counter];

					// Check for decimal digits
					if (TRUE == g_ascii_isdigit(input_char))
					{
						output_gstring = g_string_append_c(output_gstring, input_char);
					}
					else
					{
						// * The input wasn't a standard digit character, so check if it *
						// * is one of the characters in the capabilities list for this field *
						match_found = FALSE;
						capability_check = V_HYPENS & capabilities;
						if (FALSE != capability_check)
						{
							// This field is allowed to have hypens
							if (0 == g_ascii_strncasecmp("-", &input_char, 1))
							{
								// Yes, this is a hypen character
								match_found = TRUE;
								g_string_append_printf(output_gstring, "%s", "-");
							}
						}

						// The character we are checking is not in the list of valid inputs for this field
						if (FALSE == match_found)
						{
							g_string_free(output_gstring, TRUE);
							return NULL;
						}
					}
				}

				// Convert the string to an integer
				output_gint = atoi(output_gstring->str);
			}
			else
			{
				// We're working with integer input, so just copy the value directly
				output_gint = *((gint *) value);
			}

			// Is the integer value within the defined bounds?
			value_max = get_valid_fields_max_value(value_id);
			value_min = get_valid_fields_min_value(value_id);
			if ((output_gint < value_min) || (output_gint > value_max))
			{
				// Value is out of bounds, so fail
				g_string_free(output_gstring, TRUE);
				return NULL;
			}

			// The value looks ok, so we copy it to newly allocated memory, to pass it back
			output_gint_ptr = g_try_new0(gint, 1);
			if (NULL == output_gint_ptr)
			{
				// Unable to allocate memory for the new value, so fail
				g_string_free(output_gstring, TRUE);
				return NULL;
			}
			*output_gint_ptr = output_gint;

			// Free the string memory allocated in this function
			g_string_free(output_gstring, TRUE);

			return output_gint_ptr;

		case V_RESOLUTION:

				// * We're working with a resolution (text string) input.  i.e. '1920x1200 pixels' *

				// Get the length of the input string
				string_length = strlen((gchar *) value);
				string_max = get_valid_fields_max_value(value_id);
				string_min = get_valid_fields_min_value(value_id);

				// If the length of the string isn't in the acceptable range, return NULL
				if ((string_length < string_min) || (string_length > string_max))
					return NULL;

				// Sanitise each character of the input string
				for (string_counter = 0; string_counter < string_length; string_counter++)
				{
					input_char = ((gchar *) value)[string_counter];

					// Check for decimal digits
					if (TRUE == g_ascii_isdigit(input_char))
					{
						output_gstring = g_string_append_c(output_gstring, input_char);
					}
					else
					{
						match_found = FALSE;

						// This field is allowed to have the ' ' and 'x' characters .  Is this character one of those?
						if (0 == g_ascii_strncasecmp(" ", &input_char, 1))
						{
							// Yes, this is a space character, so we've already collected the required resolution
							// info and we can just return the resolution part of the string so far

							// Remove any leading and/or trailing white space
							output_gstring->str = g_strstrip(output_gstring->str);
							output_gstring->len = strlen(output_gstring->str);

							// Recheck the length of the output string
							if ((string_length < string_min) || (string_length > string_max))
								return NULL;

							// The string seems to be valid, so return it for use
							return output_gstring;
						}
						if (0 == g_ascii_strncasecmp("x", &input_char, 1))
						{
							// Yes, this is a 'x' character
							output_gstring = g_string_append_c(output_gstring, 'x');
							match_found = TRUE;
							continue;
						}
						if (FALSE == match_found)
						{
							// This wasn't a valid character
							g_string_free(output_gstring, TRUE);
							return NULL;
						}
					}
				}

				// Remove any leading and/or trailing white space
				output_gstring->str = g_strstrip(output_gstring->str);
				output_gstring->len = strlen(output_gstring->str);

				// Recheck the length of the output string
				if ((string_length < string_min) || (string_length > string_max))
					return NULL;

				// The string seems to be valid, so return it for use
				return output_gstring;

		case V_ZOOM:

			// * We're working with a zoom level.  i.e. "100%" or "Fit to width" *

			// Get the length of the input string
			string_length = g_utf8_strlen((gchar *) value, -1);
			string_max = get_valid_fields_max_value(value_id);
			string_min = get_valid_fields_min_value(value_id);

			// If the length of the string isn't in the acceptable range, return NULL
			if ((string_length < string_min) || (string_length > string_max))
				return NULL;

			// If the string is "Fit to width" or a localised version of it
			if ((0 == g_strcmp0("Fit to width", (gchar *) value)) || (0 == g_strcmp0(_("Fit to width"), (gchar *) value)))
			{
				// Yes, this is the "Fit to width" value
				output_gstring = g_string_assign(output_gstring, value);
				return output_gstring;
			}

			// * The incoming string isn't the "Fit to width" value, *
			// * so should only consist of decimal characters and '%' *

			// Sanitise each character of the input string
			for (string_counter = 0; string_counter < string_length; string_counter++)
			{
				input_char = ((gchar *) value)[string_counter];

				// Check for decimal digits
				if (TRUE == g_ascii_isdigit(input_char))
				{
					output_gstring = g_string_append_c(output_gstring, input_char);
					continue;
				}
				// Check for '%' character
				if (0 == g_ascii_strncasecmp("%", &input_char, 1))
				{
					// Yes, this is a '%' character
					output_gstring = g_string_append_c(output_gstring, '%');
					continue;
				}
				// This wasn't a valid character
				g_string_free(output_gstring, TRUE);
				return NULL;
			}

			return output_gstring;

		default:

			// Unknown value type, we should never get here
			error_string = g_string_new(NULL);
			g_string_printf(error_string, "%s ED119: %s - '%s'", _("Error"), _("Unknown value passed to validation function"), get_valid_fields_name(value_id));
			display_warning(error_string->str);
			g_string_free(error_string, TRUE);

			return NULL;
	}

	// If we get here, then something went wrong!
	return NULL;
}
GtkTextBuffer *gtk_text_buffer_duplicate(GtkTextBuffer *source_buffer)
{
	// Local variables
	gchar				*conversion_buffer;			// Used when converting between unicode character types
	GtkTextIter			end_iter;
	GtkTextIter			end_iter_minus_one;
	gint				end_offset;
	gint				i;
	guint				loop_counter;
	GtkTextIter 		loop_iter;
	GtkTextBuffer		*new_text_buffer;
	guint				num_tags;
	GtkTextIter			source_buffer_end;
	GtkTextIter			source_buffer_start;
	gint				start_offset;
	GSList				*tag_list;
	GtkTextTag			*tag_ptr;
	gunichar			temp_char;
	GString				*temp_gstring;


	// Validate the tags in the source buffer
	text_layer_dialog_validate_buffer_tag_quantity(GTK_TEXT_BUFFER(source_buffer));

	// Initialise various things
	temp_gstring = g_string_new(NULL);

	// Create a new text buffer
	new_text_buffer = gtk_text_buffer_new(get_text_tags_table());

	// Get the bounds of the source buffer
	gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(source_buffer), &source_buffer_start, &source_buffer_end);
	gtk_text_iter_order(&source_buffer_start, &source_buffer_end);

	// Scan through the source text buffer one character at a time, getting the character and the tags that apply to it
	start_offset = gtk_text_iter_get_offset(&source_buffer_start);
	end_offset = gtk_text_iter_get_offset(&source_buffer_end);
	for (i = 0; i < end_offset; i++)
	{
		// Copy one character from the source text buffer to the new destination text buffer
		gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(source_buffer), &loop_iter, i);
		temp_char = gtk_text_iter_get_char(&loop_iter);
		conversion_buffer = g_ucs4_to_utf8(&temp_char, 1, NULL, NULL, NULL);
		if (NULL == conversion_buffer)
		{
			g_string_printf(temp_gstring, "%s ED441: %s", _("Error"), _("Could not convert unicode character from ucs4 to utf8."));
			display_warning(temp_gstring->str);
			continue;
		}

		// Validate the retrieved character
		if (TRUE != g_unichar_validate(temp_char))
		{
			// Something other than a unicode character was retrieved
			g_string_printf(temp_gstring, "%s ED442: %s", _("Error"), _("Invalid unicode character found in text."));
			display_warning(temp_gstring->str);
			continue;
		}
		gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(new_text_buffer), conversion_buffer, -1);
		g_free(conversion_buffer);

		// Copy the tags from the character in the source buffer to the new character in the destination buffer
		tag_list = gtk_text_iter_get_tags(&loop_iter);
		num_tags = g_slist_length(tag_list);
		gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(new_text_buffer), &end_iter);
		end_iter_minus_one = end_iter;
		gtk_text_iter_backward_char(&end_iter_minus_one);
		for (loop_counter = 0; loop_counter < num_tags; loop_counter++)
		{
			// Copy each tag from the source text buffer to the destination one
			tag_ptr = g_slist_nth_data(tag_list, loop_counter);
			gtk_text_buffer_apply_tag(GTK_TEXT_BUFFER(new_text_buffer), tag_ptr, &end_iter_minus_one, &end_iter);
		}
		g_slist_free(tag_list);
	}
	g_string_free(temp_gstring, TRUE);

	// Validate the tags in the duplicated buffer
	text_layer_dialog_validate_buffer_tag_quantity(GTK_TEXT_BUFFER(new_text_buffer));

	// Return the duplicated text buffer
	return new_text_buffer;
}