Example #1
0
void cairox_paint_curved_arrow(cairo_t *cr, ArrowHeadType head, CairoxPoint *coordinates, int points, double width, double zoom)
{
    int i = 0;

    cairo_set_line_width(cr, width * zoom);
    cairo_move_to(cr, zoom * coordinates[i].x, zoom * coordinates[i].y);

    if (points <= 2) {
        /* Not enough line segments for true curves: */
        cairox_paint_final_arrow_segment(cr, head, &coordinates[1], width, zoom);
    }
    else {
        while (++i < points-1) {
            double w1 = line_length(&coordinates[i-1], &coordinates[i]);
            double w2 = line_length(&coordinates[i+1], &coordinates[i]);
            double dw = MIN(w1, w2) / 2.0;
            CairoxPoint point_a;
//            CairoxPoint point_b;
            CairoxPoint centre;
            double slope_a, slope_b, radius;
            double angle1, angle2;

            /* Where does the arc start: */
            point_a.x = coordinates[i-1].x + (coordinates[i].x-coordinates[i-1].x)*(w1-dw)/w1;
            point_a.y = coordinates[i-1].y + (coordinates[i].y-coordinates[i-1].y)*(w1-dw)/w1;

            /* Where does the arc end: */
//            point_b.x = coordinates[i+1].x + (coordinates[i].x-coordinates[i+1].x)*(w2-dw)/w2;
//            point_b.y = coordinates[i+1].y + (coordinates[i].y-coordinates[i+1].y)*(w2-dw)/w2;

            slope_a = line_calculate_slope(&coordinates[i-1], &coordinates[i]);
            slope_b = line_calculate_slope(&coordinates[i+1], &coordinates[i]);

            radius = dw * tan((slope_b-slope_a)/2.0);

            /* arc is of size radius and goes from point_a to point_b */
            centre.x = point_a.x - radius * sin(slope_a);
            centre.y = point_a.y + radius * cos(slope_a);

            /* Draw a line segment in the appropriate direction: */
            cairo_line_to(cr, point_a.x, point_a.y);
            /* Now draw the arc: */
            if (radius < 0) {
                angle1 = slope_a + M_PI / 2.0;
                angle2 = slope_b - M_PI / 2.0;
                cairo_arc(cr, centre.x, centre.y, -radius, angle1, angle2);
            }
            else {
                angle1 = slope_a - M_PI / 2.0;
                angle2 = slope_b + M_PI / 2.0;
                cairo_arc_negative(cr, centre.x, centre.y, radius, angle1, angle2);
            }
        }
        cairox_paint_final_arrow_segment(cr, head, &coordinates[i-1], width, zoom);
    }
}
Example #2
0
void left(editor_t *ed, int select)
  {
  update_selection(ed, select);
  if (ed->col > 0)
    {
    ed->col--;
    }
  else
    {
    int newpos = prev_line(ed, ed->linepos);
    if (newpos < 0)
      return;

    ed->col = line_length(ed, newpos);
    ed->linepos = newpos;
    ed->line--;
    if (ed->line < ed->topline)
      {
      ed->toppos = ed->linepos;
      ed->topline = ed->line;
      ed->refresh = 1;
      }
    }

  ed->lastcol = ed->col;
  adjust(ed);
  }
Example #3
0
File: pi.cpp Project: ja999/sem5
int main(int argc, char **argv) {
  long long num_steps = NUM_STEPS;
  double step = 1. / (double)num_steps;
  double sequential_time;
  int slots = 0;

  if (argc > 1) {
    slots = atoi(argv[1]);
  }
  if (slots == 0) {
    slots = LINE_LENGTH_SLOTS;
  }

  sequential_time = test_function(sequential, "Sekwencyjnie", num_steps, step, 0);
  test_function(race, "Wyscig", num_steps, step, sequential_time);
  test_function(atomic, "Atomic", num_steps, step, sequential_time);
  test_function(reduction, "Redukcja", num_steps, step, sequential_time);
  test_function(false_sharing, "Uniewaznianie linii", num_steps, step, sequential_time);

  printf("Dlugosc linii pamieci: %u", line_length(num_steps / 10, 1. / ((double)(num_steps / 10)), slots));

  scanf(" %d", &slots);

  return 0;
}
Example #4
0
void right(editor_t *ed, int select)
  {
  update_selection(ed, select);
  if (ed->col < line_length(ed, ed->linepos))
    {
    ed->col++;
    }
  else
    {
    int newpos = next_line(ed, ed->linepos);
    if (newpos < 0)
      return;

    ed->col = 0;
    ed->linepos = newpos;
    ed->line++;

    if (ed->line >= ed->topline + ed->lines)
      {
      ed->toppos = next_line(ed, ed->toppos);
      ed->topline++;
      ed->refresh = 1;
      }
    }

  ed->lastcol = ed->col;
  adjust(ed);
  }
Example #5
0
static int line_length(char * text)
{
 if((!text[0]) ||
    (text[0]=='\n'))
     return 0;
  else 
    return 1 + line_length(&(text[1]));
}
Example #6
0
nyx::point text_extents(F const& fnt, std::string const& x, size_t maxx, size_t maxy)
{
    if (!maxx || !maxy)
    {
        return text_extents(fnt, x);
    }

    return nyx::point(maxx * average_char_width(fnt), maxy * line_length(fnt));
}
Example #7
0
static int find_closest_in_page(fz_stext_page *page, fz_point p)
{
	fz_stext_block *block;
	fz_stext_line *line;
	fz_stext_line *closest_line = NULL;
	int closest_idx = 0;
	float closest_dist = 1e30f;
	float this_dist;
	int idx = 0;

	for (block = page->first_block; block; block = block->next)
	{
		if (block->type != FZ_STEXT_BLOCK_TEXT)
			continue;
		for (line = block->u.t.first_line; line; line = line->next)
		{
			fz_rect box = line->bbox;
			if (p.x >= box.x0 && p.x <= box.x1)
			{
				if (p.y < box.y0)
					this_dist = dist2(box.y0 - p.y, 0);
				else if (p.y > box.y1)
					this_dist = dist2(p.y - box.y1, 0);
				else
					this_dist = 0;
			}
			else if (p.y >= box.y0 && p.y <= box.y1)
			{
				if (p.x < box.x0)
					this_dist = dist2(box.x0 - p.x, 0);
				else if (p.x > box.x1)
					this_dist = dist2(p.x - box.x1, 0);
				else
					this_dist = 0;
			}
			else
			{
				float dul = dist2(p.x - box.x0, p.y - box.y0);
				float dur = dist2(p.x - box.x1, p.y - box.y0);
				float dll = dist2(p.x - box.x0, p.y - box.y1);
				float dlr = dist2(p.x - box.x1, p.y - box.y1);
				this_dist = fz_min(fz_min(dul, dur), fz_min(dll, dlr));
			}
			if (this_dist < closest_dist)
			{
				closest_dist = this_dist;
				closest_line = line;
				closest_idx = idx;
			}
			idx += line_length(line);
		}
	}

	if (closest_line)
		return find_closest_in_line(closest_line, closest_idx, p);
	return 0;
}
Example #8
0
static int find_closest_in_line(fz_stext_line *line, int idx, fz_point p)
{
	fz_stext_char *ch;
	float closest_dist = 1e30f;
	int closest_idx = idx;

	if (line->dir.x > line->dir.y)
	{
		if (p.y < line->bbox.y0)
			return idx;
		if (p.y > line->bbox.y1)
			return idx + line_length(line);
	}
	else
	{
		if (p.x < line->bbox.x0)
			return idx + line_length(line);
		if (p.x > line->bbox.x1)
			return idx;
	}

	for (ch = line->first_char; ch; ch = ch->next)
	{
		float mid_x = (ch->quad.ul.x + ch->quad.ur.x + ch->quad.ll.x + ch->quad.lr.x) / 4;
		float mid_y = (ch->quad.ul.y + ch->quad.ur.y + ch->quad.ll.y + ch->quad.lr.y) / 4;
		float this_dist = dist2(p.x - mid_x, p.y - mid_y);
		if (this_dist < closest_dist)
		{
			closest_dist = this_dist;
			if (line->dir.x > line->dir.y)
				closest_idx = (p.x < mid_x) ? idx : idx+1;
			else
				closest_idx = (p.y < mid_y) ? idx : idx+1;
		}
		++idx;
	}
	return closest_idx;
}
Example #9
0
    inline point text_extents(Font const& fnt, std::string const& x, size_t maxx)
    {
        typedef typename Font::glyph_type glyph;

        BOOST_ASSERT(maxx != 0);

        point result(0, 0);
        size_t i = 0;

        while (i != x.size())
        {
            int w = 0;

            if (x[i] == ' ')
            {
                w = average_char_width(fnt);
            }
            else
            {
                glyph const& glyph_i = find_glyph(fnt, x[i]);

                w = glyph_i.view.width() + glyph_i.bearing.x;
            }

            ++i;

            for (int j = 0; j != maxx && i != x.size(); ++j, ++i)
            {
                if (x[i] == ' ')
                {
                    w += average_char_width(fnt);
                }
                else
                {
                    glyph const& glyph_j = find_glyph(fnt, x[i]);

                    w += kerning_distance(fnt, x[i - 1], x[i]);
                    w += glyph_j.view.width() + glyph_j.bearing.x;
                }
            }

            result.x = std::max(result.x, w);
            result.y += line_length(fnt);
        }

        return result;
    }
Example #10
0
int parsebuf::seek_in_line(int i)
{
#if 1
    abort();
    return 0; // Suppress warning.
#else
    if (i > 0) {
	size_t len = line_length();
	if ((unsigned)i > len) i = len;
    }
    else if (i < -1) i = -1;
    int new_pos = seekoff(pos_at_line_start + i, ios::beg);
    if (new_pos == EOF)
	return tell_in_line();
    else return new_pos - pos_at_line_start;
#endif
}
Example #11
0
void div_latex_display_file(FILE *outfile, divisor *pDiv)
{
    smallint counter;

    // First print coefficient of lambda
    if (pDiv->lambda != 1)
	fprintf(outfile, " %d \\lambda\n", pDiv->lambda);
    else
	fprintf(outfile, " \\lambda\n", pDiv->lambda);
    
    // Next print the delta's using line commands
    for (counter = 0 ; counter < line_length(pDiv->pDelta) ; counter++)
	if (line_data(pDiv->pDelta, counter) != 1)
	    fprintf(outfile, " - %d \\delta_%d\n", 
		    line_data(pDiv->pDelta, counter), counter);
	else
	    fprintf(outfile, " - \\delta_%d\n", 
		    line_data(pDiv->pDelta, counter), counter);

}
Example #12
0
void bottom(editor_t *ed, int select)
  {
  update_selection(ed, select);
  for (;;)
    {
    int newpos = next_line(ed, ed->linepos);
    if (newpos < 0) break;

    ed->linepos = newpos;
    ed->line++;

    if (ed->line >= ed->topline + ed->lines)
      {
      ed->toppos = next_line(ed, ed->toppos);
      ed->topline++;
      ed->refresh = 1;
      }
    }
  ed->col = ed->lastcol = line_length(ed, ed->linepos);
  adjust(ed);
  }
Example #13
0
    inline point text_extents(Font const& fnt, std::string const& x)
    {
        typedef typename Font::glyph_type glyph;

        point result(0, 0);

        if (x.empty())
            return result;

        if (x[0] == ' ')
        {
            result.x = average_char_width(fnt);
        }
        else
        {
            glyph const& first = find_glyph(fnt, x[0]);

            result.x = first.view.width() + first.bearing.x;
        }

        result.y = line_length(fnt);

        for (size_t i = 1; i != x.size(); ++i)
        {
            if (x[i] == ' ')
            {
                result.x += average_char_width(fnt);
            }
            else
            {
                glyph const& g = find_glyph(fnt, x[i]);

                result.x += kerning_distance(fnt, x[i - 1], x[i]);
                result.x += g.view.width() + g.bearing.x;
            }
        }

        return result;
    }
Example #14
0
void adjust(editor_t *ed)
  {
  int col;
  int ll = line_length(ed, ed->linepos);
  ed->col = ed->lastcol;
  if (ed->col > ll)
    ed->col = ll;

  col = column(ed, ed->linepos, ed->col);
  while (col < ed->margin)
    {
    ed->margin -= 4;
    if (ed->margin < 0)
      ed->margin = 0;
    ed->refresh = 1;
    }

  while (col - ed->margin >= ed->cols)
    {
    ed->margin += 4;
    ed->refresh = 1;
    }
  }
double point_line_dist(Point a, Line l)
{
	return abs(cross_product(l.a - a, l.b - a) / line_length(l));
}
Example #16
0
void moveto(editor_t *ed, int pos, int center)
  {
  int scroll = 0;
  for (;;)
    {
    int cur = ed->linepos + ed->col;
    if (pos < cur)
      {
      if (pos >= ed->linepos)
        {
        ed->col = pos - ed->linepos;
        }
      else
        {
        ed->col = 0;
        ed->linepos = prev_line(ed, ed->linepos);
        ed->line--;

        if (ed->topline > ed->line)
          {
          ed->toppos = ed->linepos;
          ed->topline--;
          ed->refresh = 1;
          scroll = 1;
          }
        }
      }
    else if (pos > cur)
      {
      int next = next_line(ed, ed->linepos);
      if (next == -1)
        {
        ed->col = line_length(ed, ed->linepos);
        break;
        }
      else if (pos < next)
        {
        ed->col = pos - ed->linepos;
        }
      else
        {
        ed->col = 0;
        ed->linepos = next;
        ed->line++;

        if (ed->line >= ed->topline + ed->lines)
          {
          ed->toppos = next_line(ed, ed->toppos);
          ed->topline++;
          ed->refresh = 1;
          scroll = 1;
          }
        }
      }
    else
      {
      break;
      }
    }

  if (scroll && center)
    {
    int tl = ed->line - ed->lines / 2;
    if (tl < 0) tl = 0;
    for (;;)
      {
      if (ed->topline > tl)
        {
        ed->toppos = prev_line(ed, ed->toppos);
        ed->topline--;
        }
      else if (ed->topline < tl)
        {
        ed->toppos = next_line(ed, ed->toppos);
        ed->topline++;
        }
      else
        {
        break;
        }
      }
    }
  }
Example #17
0
void advance_to_sequence_name(FILE * alignment_file_pointer)
{
	// Skip sequence line, TODO make this work properly
	line_length(alignment_file_pointer);
}
Example #18
0
void end(editor_t *ed, int select)
  {
  update_selection(ed, select);
  ed->col = ed->lastcol = line_length(ed, ed->linepos);
  adjust(ed);
  }
Example #19
0
void buffer_cutcopy (buffer_t *buf, int cut, int shape, int start_y, int start_x, int end_y, int end_x)
{
	static char temp[MAX_BUF];
	int     a, b, terminator;
	int     diff;
	line_t *l;
	line_t *next;
	line_t *top = NULL;
	char   *s;
	pad_t  *p = e->cpad;
	int     len, copied_len, line_len;
	int     start, end, intab;
	int     modified = 0;

	l = LINE_get_line_at (p, start_y);
	if (l == NULL)
		l = p->line_head;

	for (a = start_y; a <= end_y && l != p->line_head; a++)
	{
		next = l->next;

		if (l->str == NULL)
			s = "";
		else
			s = l->str->data;

		if (shape & REGION_LINEAR)
		{
			len = strlen (s);
			if (a == start_y)
			{
				start = get_string_pos (start_x, s, &intab);
				s += (start > len) ? len : start;
				len = strlen(s);
			}
			else
				start = 0;

			if (a == end_y)
			{
				end = get_string_pos (end_x - (a == start_y ? start_x : 1), s, &intab);
					
				strncpy (temp, s, MAX_BUF);
				terminator = end + 1;
				if(terminator >= MAX_BUF) terminator = MAX_BUF - 1;
				temp[terminator] = '\0';

				s = temp;
			}

			line_len = line_length(l) + 1; /* get the visible line length (not the same as str len) */

			/* if we are not on the last line, 
			   or the cursor is past the end of the line and it starts before the end of the line */
			if (a != end_y || (end_x > line_len && !(a == start_y && start > line_len)))
			{
				string_append (buf->str, "%s\n", s);

				if (cut)
				{
					if (a != start_y)
						LINE_remove (p, l);
					else
						string_remove (l->str, start, len);

					modified = 1;
				}
			} else { /* last line */
				/* TODO: when end_x > line_len we need to include the newline and merge with the next line */
				string_append (buf->str, "%s", s);

				if (cut)
				{
					string_remove (l->str, start, end + 1);

					if (start_y != end_y && top)
					{
						if (l->str)
							string_append (top->str, l->str->data);

						LINE_remove (p, l);
					}
					modified = 1;
				}
			}

			if (a == start_y) top = l;
		}
		else /* REGION_RECT */
		{
			start = get_string_pos (start_x, s, &intab);
			end   = get_string_pos (end_x,   s, &intab);

			len = end - start;
			terminator = len;
			if(terminator >= MAX_BUF) terminator = MAX_BUF - 1;
			if ((size_t)start <= strlen (s)) {
				s += start;
				strncpy (temp, s, terminator);
			}
			temp[terminator] = '\0';

			copied_len = strlen (temp);
			diff       = len - copied_len;

			for (b = 0; b < diff && ((copied_len + b) < MAX_BUF); b++)
				temp[copied_len + b] = ' ';

			if (a != end_y)
				string_append (buf->str, "%s\n", temp);
			else
				string_append (buf->str, "%s", temp);

			if (cut) {
				string_remove (l->str, start, len);
				modified = 1;
			}
		}

		l = next;
	}

	if (modified)
		pad_modified (e->cpad);
}
Example #20
0
void advance_to_sequence(FILE * alignment_file_pointer)
{
	// Skip first line since its a comment, ToDo make this better by doing a regex on the line
	line_length(alignment_file_pointer);
}
Example #21
0
int main(int argc, char *argv[])
{
    struct GModule *module;
    struct Option *in_opt, *layer_opt, *out_opt, *length_opt, *units_opt, *vertices_opt;
    
    struct Map_info In, Out;
    struct line_pnts *Points, *Points2;
    struct line_cats *Cats;

    int line, nlines, layer;
    double length = -1;
    int vertices = 0;
    double (*line_length) ();
    int latlon = 0;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("geometry"));
    module->description = _("Splits vector lines to shorter segments.");
    
    in_opt = G_define_standard_option(G_OPT_V_INPUT);

    layer_opt = G_define_standard_option(G_OPT_V_FIELD_ALL);

    out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
    
    length_opt = G_define_option();
    length_opt->key = "length";
    length_opt->type = TYPE_DOUBLE;
    length_opt->required = NO;
    length_opt->multiple = NO;
    length_opt->description = _("Maximum segment length");

    units_opt = G_define_option();
    units_opt->key = "units";
    units_opt->type = TYPE_STRING;
    units_opt->required = NO;
    units_opt->multiple = NO;
    units_opt->options = "meters,kilometers,feet,miles,nautmiles";
    units_opt->answer = "meters";
    units_opt->description = _("Length units");
    
    vertices_opt = G_define_option();
    vertices_opt->key = "vertices";
    vertices_opt->type = TYPE_INTEGER;
    vertices_opt->required = NO;
    vertices_opt->multiple = NO;
    vertices_opt->description = _("Maximum number of vertices in segment");
    
    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);
    
    if ((length_opt->answer && vertices_opt->answer) ||
	!(length_opt->answer || vertices_opt->answer))
	G_fatal_error(_("Use either length or vertices"));

    line_length = NULL;

    if (length_opt->answer) {
	length = atof(length_opt->answer);
	if (length <= 0)
	    G_fatal_error(_("Length must be positive but is %g"), length);

	/* convert length to meters */
	if (strcmp(units_opt->answer, "meters") == 0)
	    /* do nothing */ ;
	else if (strcmp(units_opt->answer, "kilometers") == 0)
	    length *= FROM_KILOMETERS;
	else if (strcmp(units_opt->answer, "feet") == 0)
	    length *= FROM_FEET;
	else if (strcmp(units_opt->answer, "miles") == 0)
	    length *= FROM_MILES;
	else if (strcmp(units_opt->answer, "nautmiles") == 0)
	    length *= FROM_NAUTMILES;
	else
	    G_fatal_error(_("Unknown unit %s"), units_opt->answer); 

	/* set line length function */
	if ((latlon = (G_projection() == PROJECTION_LL)) == 1)
	    line_length = Vect_line_geodesic_length;
	else {
	    double factor;
	    
	    line_length = Vect_line_length;
	    
	    /* convert length to map units */
	    if ((factor = G_database_units_to_meters_factor()) == 0)
		G_fatal_error(_("Can not get projection units"));
	    else {
		/* meters to units */
		length = length / factor;
	    }
	}
	G_verbose_message(_("length in %s: %g"), (latlon ? "meters" : "map units"), length);
    }

    if (vertices_opt->answer) {
	vertices = atoi(vertices_opt->answer);
	if (vertices < 2)
	    G_fatal_error(_("Number of vertices must be at least 2"));
    }
    
    Vect_set_open_level(2);
    Vect_open_old2(&In, in_opt->answer, "", layer_opt->answer);
    layer = Vect_get_field_number(&In, layer_opt->answer);
    
    Vect_open_new(&Out, out_opt->answer, Vect_is_3d(&In));
    
    Vect_copy_head_data(&In, &Out);
    Vect_hist_copy(&In, &Out);
    Vect_hist_command(&Out);
    Vect_copy_tables(&In, &Out, layer);
    
    Points = Vect_new_line_struct();
    Points2 = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    nlines = Vect_get_num_lines(&In);

    for (line = 1; line <= nlines; line++) {
	int ltype;

	G_percent(line, nlines, 1);

	if (!Vect_line_alive(&In, line))
	    continue;

	ltype = Vect_read_line(&In, Points, Cats, line);

	if (layer != -1 && !Vect_cat_get(Cats, layer, NULL))
	  continue;

	if (ltype & GV_LINES) {
	    if (length > 0) {
		double l, from, to, step;

		l = line_length(Points);

		if (l <= length) {
		    Vect_write_line(&Out, ltype, Points, Cats);
		}
		else {
		    int n, i;

		    n = ceil(l / length);
		    if (latlon)
			l = Vect_line_length(Points);

		    step = l / n;
		    from = 0.;

		    for (i = 0; i < n; i++) {
			int ret;
			double x, y, z;

			if (i == n - 1) {
			    to = l;	/* to be sure that it goes to end */
			}
			else {
			    to = from + step;
			}

			ret = Vect_line_segment(Points, from, to, Points2);
			if (ret == 0) {
			    G_warning(_("Unable to make line segment: %f - %f (line length = %f)"),
				      from, to, l);
			    continue;
			}

			/* To be sure that the coordinates are identical */
			if (i > 0) {
			    Points2->x[0] = x;
			    Points2->y[0] = y;
			    Points2->z[0] = z;
			}
			if (i == n - 1) {
			    Points2->x[Points2->n_points - 1] =
				Points->x[Points->n_points - 1];
			    Points2->y[Points2->n_points - 1] =
				Points->y[Points->n_points - 1];
			    Points2->z[Points2->n_points - 1] =
				Points->z[Points->n_points - 1];
			}

			Vect_write_line(&Out, ltype, Points2, Cats);

			/* last point */
			x = Points2->x[Points2->n_points - 1];
			y = Points2->y[Points2->n_points - 1];
			z = Points2->z[Points2->n_points - 1];

			from += step;
		    }
		}
	    }
	    else {
		int start = 0;	/* number of coordinates written */

		while (start < Points->n_points - 1) {
		    int i, v;

		    Vect_reset_line(Points2);
		    for (i = 0; i < vertices; i++) {
			v = start + i;
			if (v == Points->n_points)
			    break;

			Vect_append_point(Points2, Points->x[v], Points->y[v],
					  Points->z[v]);
		    }

		    Vect_write_line(&Out, ltype, Points2, Cats);

		    start = v;
		}
	    }
	}
	else {
	    Vect_write_line(&Out, ltype, Points, Cats);
	}
    }

    Vect_close(&In);
    Vect_build(&Out);
    Vect_close(&Out);
    
    exit(EXIT_SUCCESS);
}
/** Find an arbitrary number of delimited strings at the end of a file.  This
 * function provides the core of our last-lines-loader implementation.
 *
 * @param fd File descriptor to operate on.  This must be opened for reading.
 *
 * @param bytes Delimiter sequence.
 *
 * @param bytes_length Number of significant bytes in @p bytes.
 *
 * @param count Number of tail sequences to find.
 *
 * @param out Destination string array.
 */
static inline size_t
find_tail_sequences(int fd, const char* bytes, size_t bytes_length, size_t count, wxArrayString& out)
{
    size_t count_added ( 0 );

    /* We overlap the file reads a little to avoid splitting (and thus missing) the
       delimiter sequence.  */
    const size_t read_overlap ( bytes_length - 1 );
    const size_t read_size ( BUFSIZ );

    const off_t log_length ( lseek(fd, 0, SEEK_END) );
    bool have_last_pos ( false );
    char buf[read_size];
    off_t last_found_pos ( 0 );
    off_t last_read_position ( log_length + read_overlap );

    /* We read `read_size'-byte blocks of the file, starting at the end and working backwards. */
    while ( count_added < count && last_read_position > 0 ) {
        off_t read_position ( next_read_position(last_read_position, read_size, read_overlap) );
        size_t bytes_read ( pread(fd, buf, std::min(static_cast<off_t>(read_size), last_read_position - read_position), read_position) );

        /* In each block, we search for `bytes', starting at the end.  */
        for ( ssize_t i = bytes_read - read_overlap - 1; i >= 0; i-- ) {
            if ( !strncmp((buf + i), bytes, bytes_length) ) {
                off_t this_found_pos ( read_position + i );

                if ( have_last_pos && count_added < count ) {
                    size_t line_length ( last_found_pos - this_found_pos - bytes_length );

                    if ( line_length > 0 ) {
                        char* source ( NULL );

                        if ( last_found_pos >= read_position + (off_t) bytes_read ) {
                            source = new char[ line_length + 1];
                            memset(source, 0, line_length + 1);

                            if ( pread(fd, source, line_length, this_found_pos + bytes_length) < (ssize_t) line_length ) {
                                wxLogWarning(_T("ChatLog::find_tail_sequences: Read-byte count less than expected"));
                            }
                        } else {
                            source = buf + i + bytes_length;
                        }

                        if (  strncmp(source, "##", 2) != 0 ) {
                            out.Insert(wxString(L'\0', 0), 0);
                            wxLogMessage(_T("ChatLog::find_tail_sequences: fetching write buffer for %lu bytes"), sizeof(wxChar) * (line_length + 1));
#if !defined(HAVE_WX28) || defined(SL_QT_MODE)
                            wxStringBufferLength outzero_buf(out[0], sizeof(wxChar) * (line_length + 1));
                            wxConvUTF8.ToWChar(outzero_buf, line_length, source);
                            outzero_buf.SetLength(line_length);
#else
                            wxConvUTF8.MB2WC(out[0].GetWriteBuf(sizeof(wxChar) * (line_length + 1)), source, line_length);
                            out[0].UngetWriteBuf(line_length);
#endif

                            ++count_added;
                        }

                        if ( last_found_pos >= read_position + (off_t) bytes_read )
                            delete[] source;

                        if ( count_added >= count )
                            i = -1; /* short-circuit the `for' loop. */
                    }
                }
                last_found_pos = this_found_pos;
                have_last_pos = true;
                i -= bytes_length - 1;
            }
        }

        last_read_position = read_position;
    }

    return count_added;
}