Beispiel #1
0
/* build stuff necessary for rotate dialogue */
static void rotate_update_dialogue(void)
{
  error   err;
  int     w,h;
  int     d;
  int     extent;
  osbool  mask;
  os_mode mode;
  int     xeig,yeig;
  os_box  box;
  int     cx,cy;
  int     r;

  /* ensure we have a thumbnail ready */

  if (LOCALS.thumbnail == NULL)
    if (thumbnail_create(LOCALS.image,
                        &GLOBALS.choices.drawable,
                         GLOBALS.choices.rotate.max_thumb,
                        &LOCALS.thumbnail))
      return; /* failure */

  /* read thumbnail details */

  osspriteop_read_sprite_info(osspriteop_USER_AREA,
                              LOCALS.thumbnail,
             (osspriteop_id) "thumbnail",
                             &w,&h,
                             &mask,
                             &mode);

  /* convert dimensions to OS units */

  read_mode_vars(mode, &xeig, &yeig, NULL);

  w <<= xeig;
  h <<= yeig;

  /* get max dimension */

  d = ((w > h) ? w : h) * 362 / 256; /* 1.41421356 is approx 362/256 */

  /* enforce a minimum dimension so the buttons don't go outside the
   * window bounds */

  extent = (d < MIN_WIDTH) ? MIN_WIDTH : d;

  box.x0 =  0;
  box.y0 = -extent - BUTTON_HEIGHT;
  box.x1 =  extent;
  box.y1 =  0;
  window_set_submenu_extent(LOCALS.rotate_w, 15, &box);

  /* cache values */

  LOCALS.rotation = 0;
  LOCALS.flags    = 0;
  LOCALS.extent   = extent;

  /* the box formed by extent squared may be bigger than required due to
   * minimum size padding. centre our refresh area in this box. */

  cx =  extent / 2;
  cy = -extent / 2;
  r  = d / 2;

  LOCALS.redraw_area.x0 = cx - r;
  LOCALS.redraw_area.y0 = cy - r;
  LOCALS.redraw_area.x1 = cx + r;
  LOCALS.redraw_area.y1 = cy + r;

  /* adjust button positions */

  shift_buttons(&box);


  if (LOCALS.trans_tab)
  {
    free(LOCALS.trans_tab);
    LOCALS.trans_tab = NULL;
  }

  err = make_trans_tab(LOCALS.thumbnail,
      (osspriteop_id) "thumbnail",
                      &LOCALS.trans_tab);
  if (err)
    goto Failure;


  if (LOCALS.indicator.trans_tab)
  {
    free(LOCALS.indicator.trans_tab);
    LOCALS.indicator.trans_tab = NULL;
  }

  err = make_trans_tab((osspriteop_area *) window_get_sprite_area(),
                          (osspriteop_id) "rt-0",
                                           &LOCALS.indicator.trans_tab);
  if (err)
    goto Failure;


  /* must now refresh indicator and thumbnail */

  wimp_force_redraw(LOCALS.rotate_w, 0, -extent, extent, 0);

  return;


Failure:

  thumbnail_destroy(&LOCALS.thumbnail);

  if (LOCALS.trans_tab)
  {
    free(LOCALS.trans_tab);
    LOCALS.trans_tab = NULL;
  }

  if (LOCALS.indicator.trans_tab)
  {
    free(LOCALS.indicator.trans_tab);
    LOCALS.indicator.trans_tab = NULL;
  }

  return;
}
static bool browser_window_history__redraw_entry(struct history *history,
		struct history_entry *entry,
		int x0, int y0, int x1, int y1,
		int x, int y, bool clip,
		const struct redraw_context *ctx)
{
	const struct plotter_table *plot = ctx->plot;
	size_t char_offset;
	int actual_x;
	struct history_entry *child;
	colour c = entry == history->current ?
			HISTORY_COLOUR_SELECTED : HISTORY_COLOUR_FOREGROUND;
	int tailsize = 5;
	int xoffset = x - x0;
	int yoffset = y - y0;
        plot_style_t pstyle_history_rect = { 
            .stroke_type = PLOT_OP_TYPE_SOLID,
            .stroke_colour = c,
            .stroke_width = entry == history->current ? 3 : 1,
        };
	plot_font_style_t fstyle = *plot_style_font;

	if (clip) {
		struct rect rect;
		rect.x0 = x0 + xoffset;
		rect.y0 = y0 + yoffset;
		rect.x1 = x1 + xoffset;
		rect.y1 = y1 + yoffset;
		if(!plot->clip(&rect))
			return false;
	}

	if (!plot->bitmap(entry->x + xoffset, entry->y + yoffset, WIDTH, HEIGHT,
			entry->bitmap, 0xffffff, 0))
		return false;
	if (!plot->rectangle(entry->x - 1 + xoffset, 
                            entry->y - 1 + yoffset,
                            entry->x + xoffset + WIDTH, 
                            entry->y + yoffset + HEIGHT,
                            &pstyle_history_rect))
		return false;

	if (!nsfont.font_position_in_string(plot_style_font, entry->page.title,
			strlen(entry->page.title), WIDTH,
			&char_offset, &actual_x))
		return false;

	fstyle.background = HISTORY_COLOUR_BACKGROUND;
	fstyle.foreground = c;
	fstyle.weight = entry == history->current ? 900 : 400;

	if (!plot->text(entry->x + xoffset, entry->y + HEIGHT + 12 + yoffset,
			entry->page.title, char_offset, &fstyle))
		return false;

	for (child = entry->forward; child; child = child->next) {
		if (!plot->line(entry->x + WIDTH + xoffset,
				entry->y + HEIGHT / 2 + yoffset,
		      	entry->x + WIDTH + tailsize + xoffset,
				entry->y + HEIGHT / 2 + yoffset, 
			       plot_style_stroke_history))
			return false;
		if (!plot->line(entry->x + WIDTH + tailsize + xoffset,
			       entry->y + HEIGHT / 2 + yoffset,
			       child->x - tailsize +xoffset,
			       child->y + HEIGHT / 2 + yoffset,
			       plot_style_stroke_history))
			return false;
		if (!plot->line(child->x - tailsize + xoffset,
			       child->y + HEIGHT / 2 + yoffset,
			       child->x + xoffset, child->y +
			       			HEIGHT / 2 + yoffset,
			       plot_style_stroke_history))
			return false;
		if (!browser_window_history__redraw_entry(history, child,
				x0, y0, x1, y1, x, y, clip, ctx))
			return false;
	}

	return true;
}


/**
 * Find the history entry at a position.
 *
 * \param  entry  entry to search from
 * \param  x      coordinate
 * \param  y      coordinate
 * \return  an entry if found, 0 if none
 */

static struct history_entry *browser_window_history__find_position(
		struct history_entry *entry, int x, int y)
{
	struct history_entry *child;
	struct history_entry *found;

	if (!entry)
		return 0;

	if (entry->x <= x && x <= entry->x + WIDTH &&
			entry->y <= y && y <= entry->y + HEIGHT)
		return entry;

	for (child = entry->forward; child; child = child->next) {
		found = browser_window_history__find_position(child, x, y);
		if (found)
			return found;
	}

	return 0;
}

/**
 * Enumerate subentries in history
 * See also history_enumerate()
 *
 * \param	bw		The browser window to enumerate history of
 * \param	entry		entry to start enumeration at
 * \param	cb			callback function
 * \param	ud			context pointer passed to cb
 * \return	true to continue enumeration, false to cancel
 */
static bool browser_window_history__enumerate_entry(
		const struct browser_window *bw,
		const struct history_entry *entry,
		browser_window_history_enumerate_cb cb,
		void *ud)
{
	const struct history_entry *child;

	if (!cb(bw, entry->x, entry->y,
			entry->x + WIDTH, entry->y + HEIGHT,
			entry, ud))
		return false;

	for (child = entry->forward; child; child = child->next) {
		if (!browser_window_history__enumerate_entry(bw, child,
				cb, ud))
			return false;
	}

	return true;
}


/* -------------------------------------------------------------------------- */


/**
 * Create a new history tree for a browser window window.
 *
 * \param  bw	browser window to create history for.
 *
 * \return  NSERROR_OK or appropriate error otherwise
 */

nserror browser_window_history_create(struct browser_window *bw)
{
	struct history *history;

	bw->history = NULL;

	history = calloc(1, sizeof *history);
	if (!history) {
		warn_user("NoMemory", 0);
		return NSERROR_NOMEM;
	}
	history->width = RIGHT_MARGIN / 2;
	history->height = BOTTOM_MARGIN / 2;

	bw->history = history;
	return NSERROR_OK;
}


/**
 * Clone a bw's history tree for new bw
 *
 * \param  existing	browser window with history to clone.
 * \param  clone	browser window to make cloned history for.
 *
 * \return  NSERROR_OK or appropriate error otherwise
 */

nserror browser_window_history_clone(const struct browser_window *existing,
		struct browser_window *clone)
{
	struct history *new_history;

	clone->history = NULL;

	if (existing == NULL || existing->history == NULL ||
			existing->history->start == NULL)
		/* Nothing to clone, create new history for clone window */
		return browser_window_history_create(clone);

	/* Make cloned history */
	new_history = malloc(sizeof *new_history);
	if (!new_history)
		return NSERROR_NOMEM;

	clone->history = new_history;
	memcpy(new_history, existing->history, sizeof *new_history);

	new_history->start = browser_window_history__clone_entry(new_history,
			new_history->start);
	if (!new_history->start) {
		LOG(("Insufficient memory to clone history"));
		warn_user("NoMemory", 0);
		browser_window_history_destroy(clone);
		clone->history = NULL;
		return NSERROR_NOMEM;
	}

	return NSERROR_OK;
}


/**
 * Insert a url into the history tree.
 *
 * \param  bw       browser window with history object
 * \param  content  content to add to history
 * \param  frag_id  fragment identifier, or NULL.
 *
 * The page is added after the current entry and becomes current.
 */


void browser_window_history_add(struct browser_window *bw,
		struct hlcache_handle *content, lwc_string *frag_id)
{
	struct history *history;
	struct history_entry *entry;
	nsurl *nsurl = hlcache_handle_get_url(content);
	char *title;
	struct bitmap *bitmap;

	assert(bw);
	assert(bw->history);
	assert(content);

	history = bw->history;

	/* allocate space */
	entry = malloc(sizeof *entry);
	if (entry == NULL)
		return;

	title = strdup(content_get_title(content));
	if (title == NULL) {
		warn_user("NoMemory", 0);
		free(entry);
		return;
	}

	entry->page.url = nsurl_ref(nsurl);
	entry->page.frag_id = frag_id ? lwc_string_ref(frag_id) : 0;

	entry->page.title = title;
	entry->back = history->current;
	entry->next = 0;
	entry->forward = entry->forward_pref = entry->forward_last = 0;
	entry->children = 0;
	entry->bitmap = 0;
	if (history->current) {
		if (history->current->forward_last)
			history->current->forward_last->next = entry;
		else
			history->current->forward = entry;
		history->current->forward_pref = entry;
		history->current->forward_last = entry;
		history->current->children++;
	} else {
		history->start = entry;
	}
	history->current = entry;

	/* if we have a thumbnail, don't update until the page has finished
	 * loading */
	bitmap = urldb_get_thumbnail(nsurl);
	if (!bitmap) {
		LOG(("Creating thumbnail for %s", nsurl_access(nsurl)));
		bitmap = bitmap_create(WIDTH, HEIGHT,
				BITMAP_NEW | BITMAP_CLEAR_MEMORY |
				BITMAP_OPAQUE);
		if (!bitmap) {
			warn_user("NoMemory", 0);
			return;
		}
		if (thumbnail_create(content, bitmap, nsurl) == false) {
			/* Thumbnailing failed. Ignore it silently */
			bitmap_destroy(bitmap);
			bitmap = NULL;
		}
	}
	entry->bitmap = bitmap;

	browser_window_history__layout(history);
}


/**
 * Update the thumbnail for the current entry.
 *
 * \param  history  opaque history structure, as returned by history_create()
 * \param  content  content for current entry
 */

void browser_window_history_update(struct browser_window *bw,
		struct hlcache_handle *content)
{
	struct history *history;
	char *title;

	assert(bw != NULL);

	history = bw->history;

	if (!history || !history->current || !history->current->bitmap)
		return;

	assert(history->current->page.url);
	assert(history->current->page.title);

	title = strdup(content_get_title(content));
	if (!title) {
		warn_user("NoMemory", 0);
		return;
	}

	assert(title);
	free(history->current->page.title);
	history->current->page.title = title;

	thumbnail_create(content, history->current->bitmap, NULL);
}


/**
 * Free a history structure.
 *
 * \param  history  opaque history structure, as returned by history_create()
 */

void browser_window_history_destroy(struct browser_window *bw)
{
	assert(bw != NULL);

	if (bw->history == NULL)
		return;

	browser_window_history__free_entry(bw->history->start);
	free(bw->history);

	bw->history = NULL;
}