Esempio n. 1
0
/*****************************************************************************
 * Function:	_DtCanvasProcessSelection()
 *
 * Purpose:	Indicate an new point for a selection.
 *
 *****************************************************************************/
void
_DtCanvasProcessSelection (
    _DtCvHandle		canvas_handle,
    _DtCvUnit		x,
    _DtCvUnit		y,
    _DtCvSelectMode	mode)
{
    int			 i;
    _DtCanvasStruct	*canvas = (_DtCanvasStruct *) canvas_handle;
    _DtCvSelectData	 temp;

    switch (mode)
	  {
	case _DtCvSELECTION_CLEAR:
		CheckAndSwitchPoints(&(canvas->select_start),
							&(canvas->select_end));

	case _DtCvSELECTION_START:
		_DtCvDrawAreaWithFlags(canvas, canvas->select_start,
				canvas->select_end,
				_DtCvSELECTED_FLAG, 0,
				_DtCvBAD_TYPE, NULL);

		canvas->select_start = defaultSelect;
		if (mode == _DtCvSELECTION_START)
		    SearchForClosestLine(canvas, x, y, &(canvas->select_start));

		canvas->select_end   = canvas->select_start;
		break;

	case _DtCvSELECTION_END:
	case _DtCvSELECTION_UPDATE:
		SearchForClosestLine(canvas, x, y, &temp);

		AdjustSelection (canvas, temp);
		if (mode == _DtCvSELECTION_END)
		    CheckAndSwitchPoints(&(canvas->select_start),
							&(canvas->select_end));
		break;
      }
}
Esempio n. 2
0
/*****************************************************************************
 * Function:	GetSegsInArea()
 *
 * Purpose:	Retrieve the segments making up the selection.
 *
 *****************************************************************************/
static _DtCvStatus
GetSegsInArea (
    _DtCanvasStruct	*canvas,
    _DtCvSelectData	  *beg,
    _DtCvSelectData	  *end,
    _DtCvSegPts		***ret_segs,
    _DtCvUnit		  *ret_y1,
    _DtCvUnit		  *ret_y2)
{
    int			 cnt;
    int			 count;
    int			 start;
    int			 length;
    int			 lineCnt;
    int			 result = 0;
    _DtCvValue		 processing = True;
    _DtCvUnit		 minY;
    _DtCvUnit		 maxY;
    _DtCvUnit		 botY;
    _DtCvSelectData	 next;
    _DtCvSegPts		*newPt;
    _DtCvSegmentI	*pSeg;
    _DtCvDspLine	*lines = canvas->txt_lst;

    *ret_segs = NULL;

    if (beg->x == -1)
	return _DtCvSTATUS_NONE;

    /*
     * make sure the selection points are in the correct order.
     */
    CheckAndSwitchPoints(beg, end);

    /*
     * clear the processed bit
     */
    for (cnt = 0; cnt < canvas->txt_cnt; cnt++)
	_DtCvClearProcessed(lines[cnt]);

    /*
     * initialize the working structure
     * mark all the lines outside the selection regiion as invalid
     */
    next = *beg;
    MarkLinesOutsideBoundary(canvas, next.y, next.x, end->y, end->x);

    /*
     * start the minimum and maximum Y at this location.
     */
    minY = next.y;
    maxY = end->y;

    /*
     * is there a line at this location?
     */
    if (next.line_idx == -1)
      {
	/*
	 * find the first selected line within the region.
	 */
	if (FindNextMinY(lines, canvas->txt_cnt, -1, &next.y) == False)
	    processing = False;		/* empty of any text */
	else
	  {
	    /*
	     * now find the first line that is on this 'line' and
	     * the number of lines.
	     */
	    next.x  = 0;
	    lineCnt = FindMinX(lines, canvas->txt_cnt, next.y, &next.line_idx);
	    next.char_idx = 0;
          }
      }
    else /* find the number of lines on this 'line' */
	lineCnt = FindMinX(lines, canvas->txt_cnt, next.y, &cnt);

    /*
     * loop will there are segments to process
     */
    while (processing == True && result == 0)
      {
	/*
	 * process the next line of text.
	 */
	while (result == 0 && lineCnt > 0)
	  {
	    /*
	     * for each segment in this line (that is selected)
	     * create a segment point for it.
	     */
	    length = lines[next.line_idx].length;
	    start  = lines[next.line_idx].byte_index;

	    /*
	     * if this is the last line, shorten the length
	     * by the ending index.
	     */
	    if (next.line_idx == end->line_idx)
		length = end->char_idx;

	    /*
	     * move through the line's segments until we
	     * hit the segment starting the selection
	     */
	    pSeg = lines[next.line_idx].seg_ptr;
	    count = next.char_idx;
	    while (NULL != pSeg && 0 < count)
	      {
		/*
		 * get the byte count of this segment
		 */
		_DtCvGetWidthOfSegment(canvas, pSeg, start, length,
					&cnt, NULL, NULL);

		/*
		 * is the byte count of this segment larger than
		 * the starting index of the selection? If not,
		 * the selection is after this segment.
		 */
		if (count >= cnt)
		  {
		    start          = 0;
		    length        -= cnt;
		    pSeg           = pSeg->next_disp;
		  }
		else
		  {
		    length        -= count;
		    start          = start + count;
		  }
		count -= cnt;
	      }

	    while (0 == result && NULL != pSeg && 0 < length)
	      {
	        /*
		 * start with error condition. If the malloc works
	         * the error result gets reset to valid.
		 */
	        result = -1;
	        newPt = (_DtCvSegPts *) malloc (sizeof(_DtCvSegPts));
	        if (NULL != newPt)
		  {
		    /*
		     * indicate everything is okay.
		     */
		    result = 0;

		    /*
		     * get the width of this segment
		     */
		    _DtCvGetWidthOfSegment(canvas, pSeg, start, length,
							&cnt, NULL, NULL);

		    /*
		     * now set the segment point information and add it to the
		     * array of segment points.
		     */
	            newPt->offset  = start;
	            newPt->len     = cnt;
		    newPt->segment = pSeg;

		    *ret_segs = (_DtCvSegPts **) _DtCvAddPtrToArray(
							(void **) *ret_segs,
							(void  *)  newPt);
		    if (NULL == *ret_segs)
		        result = -1;

		    pSeg    = pSeg->next_disp;
		    length -= cnt;
		    start   = 0;
		  }
	      }

	    /*
	     * does this line extend below the selection y?
	     * if so, report it as the maximum y.
	     */
	    botY = lines[next.line_idx].baseline + lines[next.line_idx].descent;
	    if (botY > maxY)
		maxY = botY;

	    /*
	     * indicate this line has been processed.
	     */
	    _DtCvSetProcessed(lines[next.line_idx]);

	    /*
	     * get the next line
	     */
	    next.char_idx = 0;
	    lineCnt       = FindMinX(lines, canvas->txt_cnt, next.y,
							&next.line_idx);
	  }

	if (result == 0)
	  {
	    next.x = 0;
	    processing = FindNextMinY(lines,canvas->txt_cnt, -1, &next.y);
	    if (processing == True)
		lineCnt = FindMinX(lines,canvas->txt_cnt,next.y,&next.line_idx);
	  }
      }

    /*
     * if no errors, add a null to the array
     */
    if (0 != result)
      {
        *ret_segs = (_DtCvSegPts **) _DtCvAddPtrToArray((void **) *ret_segs,
							(void  *) NULL);
	if (NULL == *ret_segs)
	    result = -1; 
      }

    /*
     * if errors, free the segment points and return a bad status.
     */
    if (0 != result)
      {
	if (NULL != *ret_segs)
	  {
	    for (lineCnt = 0; NULL != (*ret_segs)[lineCnt]; lineCnt++)
		free((*ret_segs)[lineCnt]);
	    free(*ret_segs);
	  }
	return _DtCvSTATUS_BAD;
      }

    if (NULL != ret_y1)
	*ret_y1 = minY;
    
    if (NULL != ret_y2)
	*ret_y2 = minY;

    return _DtCvSTATUS_OK;
}