/***************************************************************************** * Function: MarkLinesOutsideBoundary * *****************************************************************************/ static void MarkLinesOutsideBoundary ( _DtCanvasStruct *canvas, _DtCvUnit top_y, _DtCvUnit top_x, _DtCvUnit bot_y, _DtCvUnit bot_x) { int i; _DtCvUnit maxY; _DtCvUnit minY; _DtCvDspLine *lines = canvas->txt_lst; for (i = 0; i < canvas->txt_cnt; i++) { maxY = lines[i].baseline + lines[i].descent; minY = lines[i].baseline - lines[i].ascent; /* * is this line outside the boundary? * If so, mark it so it's not processed. */ if (maxY < top_y || minY > bot_y ) _DtCvSetProcessed(lines[i]); else { /* * does it straddle the top? */ if (_DtCvStraddlesPt(top_y, minY, maxY)) { /* * Does it begin before the selection? * If so, mark it so it's not processed. */ if (canvas->txt_lst[i].max_x <= top_x) _DtCvSetProcessed(lines[i]); } /* * does it straddle the bottom? */ if (_DtCvStraddlesPt(bot_y, minY, maxY)) { /* * Does it start after the selection? * If so, mark it so it's not processed. */ if (StartXOfLine(canvas, lines[i]) >= bot_x) _DtCvSetProcessed(lines[i]); } } } }
/***************************************************************************** * Function: BuildLine * *****************************************************************************/ static int BuildLine( _DtCanvasStruct *canvas, unsigned int mask, _DtCvUnit prev_y, _DtCvUnit target_x, int line_idx, int char_idx, int copy_cnt, _DtCvFlags end_flag, _DtCvUnit *ret_x, _DtCvUnit *ret_y, _DtCvPointer *ret_data) { _DtCvUnit topY; _DtCvUnit lastY; _DtCvDspLine *lines = canvas->txt_lst; _DtCvStringInfo strInfo = { NULL, 0, 1, NULL }; topY = lines[line_idx].baseline - lines[line_idx].ascent; if (topY > prev_y && canvas->virt_functions.build_selection != NULL) { int newLines; _DtCvUnit lineSize = canvas->metrics.line_height / 2; if (lineSize < 1) lineSize = 1; newLines = (topY - prev_y) / lineSize; while (newLines > 0) { newLines--; if ((*(canvas->virt_functions.build_selection))( canvas->client_data, _DtCvSTRING_TYPE, mask, ret_data, 0, 0, _DtCvEND_OF_LINE, (_DtCvPointer) &strInfo) != _DtCvSTATUS_OK) return -1; } } *ret_y = 0; *ret_x = AddSegmentToData (canvas, mask, target_x, line_idx, char_idx, copy_cnt, end_flag, ret_y, ret_data); _DtCvSetProcessed(lines[line_idx]); if (*ret_x == -1) return -1; return 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; }