/***************************************************************************** * 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; } }
/***************************************************************************** * 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; }