/***************************************************************************** * 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: AdjustSelection * *****************************************************************************/ static void AdjustSelection ( _DtCanvasStruct *canvas, _DtCvSelectData next) { _DtCvSelectData start = canvas->select_start; _DtCvSelectData end = canvas->select_end; if (!(Equal(next, end))) { if (next.line_idx != -1 && next.line_idx == canvas->select_end.line_idx && next.char_idx != -1 && next.char_idx == canvas->select_end.char_idx) return; if (GreaterThan(next, end)) { if (LessThanEq(start, end)) _DtCvDrawAreaWithFlags (canvas, end, next, 0, _DtCvSELECTED_FLAG, _DtCvBAD_TYPE, NULL); else if (GreaterThanEq(start, next)) _DtCvDrawAreaWithFlags (canvas, end, next, _DtCvSELECTED_FLAG, 0, _DtCvBAD_TYPE, NULL); else /* end < start < next */ { _DtCvDrawAreaWithFlags (canvas, end , start, _DtCvSELECTED_FLAG, 0, _DtCvBAD_TYPE, NULL); _DtCvDrawAreaWithFlags (canvas, start, next , 0, _DtCvSELECTED_FLAG, _DtCvBAD_TYPE, NULL); } } else /* if (next < end) */ { if (LessThanEq(start, next)) _DtCvDrawAreaWithFlags (canvas, next, end, _DtCvSELECTED_FLAG, 0, _DtCvBAD_TYPE, NULL); else if (GreaterThanEq(start, end)) _DtCvDrawAreaWithFlags (canvas, next, end, 0, _DtCvSELECTED_FLAG, _DtCvBAD_TYPE, NULL); else /* next < start < end */ { _DtCvDrawAreaWithFlags (canvas, start, end , _DtCvSELECTED_FLAG, 0, _DtCvBAD_TYPE, NULL); _DtCvDrawAreaWithFlags (canvas, next , start, 0, _DtCvSELECTED_FLAG, _DtCvBAD_TYPE, NULL); } } } canvas->select_end = next; }
/***************************************************************************** * Function: _DtCanvasActivatePts() * * Purpose: Activate the points given. * *****************************************************************************/ _DtCvStatus _DtCanvasActivatePts ( _DtCvHandle canvas_handle, unsigned int mask, _DtCvPointInfo *info, _DtCvUnit *ret_y1, _DtCvUnit *ret_y2) { int markIdx; _DtCanvasStruct *canvas = (_DtCanvasStruct *) canvas_handle; _DtCvSelectData startSel = defaultSelect; _DtCvSelectData endSel = defaultSelect; _DtCvFlags flag; _DtCvSegmentI *firstSeg; #define REQUIRE_SEGS \ (_DtCvACTIVATE_MARK | _DtCvACTIVATE_SELECTION) /* * check to see if there is anything to do */ if (0 == mask) return _DtCvSTATUS_NONE; if ((mask & _DtCvACTIVATE_MARK) && (mask & _DtCvDEACTIVATE)) return _DtCvSTATUS_BAD; /* * Convert the segments into starting and ending positions. */ if (((mask & _DtCvDEACTIVATE) && NULL == info->client_data) || (mask & REQUIRE_SEGS)) { if (NULL == info || NULL == info->segs || _DtCvSTATUS_BAD == _DtCvCvtSegsToPts(canvas, info->segs, &startSel, &endSel, ret_y1, ret_y2, &firstSeg)) return _DtCvSTATUS_BAD; } /* * Activate as a selection */ if (mask & _DtCvACTIVATE_SELECTION) { _DtCanvasProcessSelection (canvas_handle, 0, 0, _DtCvSELECTION_CLEAR); canvas->select_start = startSel; canvas->select_end = endSel; _DtCvDrawAreaWithFlags (canvas, startSel, endSel, 0, _DtCvSELECTED_FLAG, _DtCvBAD_TYPE, NULL); } /* * Activate as a mark */ if (mask & _DtCvACTIVATE_MARK) { int travIdx; _DtCvUnit x; _DtCvUnit y; _DtCvUnit width; _DtCvUnit height; markIdx = _DtCvAddToMarkList(canvas, info->client_data, _DtCvIsMarkMaskOn(mask), &startSel, &endSel); if (-1 == markIdx) return _DtCvSTATUS_BAD; /* * now put the mark in the traversal list and merge it into the * proper place. */ travIdx = _DtCvGetNextTravEntry(canvas); if (-1 == travIdx || 0 != _DtCvSetTravEntryInfo(canvas, travIdx, _DtCvTraversalMark, firstSeg, markIdx, _DtCvTRUE) || 0 != _DtCvCalcMarkPos(canvas, markIdx, &x, &y, &width, &height) || 0 != _DtCvSetTravEntryPos(canvas, travIdx, x, y, width, height)) return _DtCvSTATUS_BAD; _DtCvSortTraversalList(canvas, _DtCvTRUE); /* * draw these segments marked. */ flag = _DtCvMARK_FLAG; if (_DtCvTRUE == canvas->marks[markIdx].on) flag |= _DtCvMARK_ON; _DtCvDrawAreaWithFlags (canvas, startSel, endSel, 0, flag, _DtCvBAD_TYPE, NULL); } /* * Clear the mark flag. */ else if (mask & _DtCvDEACTIVATE) { int travIdx; /* * is there anything to deacivate? */ if (NULL == canvas->marks || 0 == canvas->mark_cnt) return _DtCvSTATUS_BAD; /* * was client data specified? If so, then look for it and ignore * the segment data. */ markIdx = 0; if (NULL != info->client_data) { while (markIdx < canvas->mark_cnt && canvas->marks[markIdx].client_data != info->client_data) markIdx++; /* * initialize the selection points */ if (markIdx < canvas->mark_cnt) { startSel = canvas->marks[markIdx].beg; endSel = canvas->marks[markIdx].end; } } /* * look for the marked set using the segments. */ else { while (markIdx < canvas->mark_cnt && startSel.line_idx != canvas->marks[markIdx].beg.line_idx && startSel.char_idx != canvas->marks[markIdx].beg.char_idx && endSel.line_idx != canvas->marks[markIdx].end.line_idx && endSel.line_idx != canvas->marks[markIdx].end.char_idx) markIdx++; } if (markIdx >= canvas->mark_cnt) return _DtCvSTATUS_BAD; /* * draw these segments unmarked. */ flag = _DtCvMARK_FLAG; if (_DtCvTRUE == canvas->marks[markIdx].on) flag |= _DtCvMARK_ON; canvas->marks[markIdx].on = _DtCvFALSE; _DtCvDrawAreaWithFlags (canvas, startSel, endSel, flag, 0, _DtCvBAD_TYPE, NULL); /* * remove the mark from the traversal list * * first find the traversal entry of the mark and adjust any * traversal mark index values to reflect that the mark * list is about to shrink by 1. */ for (travIdx = 0; _DtCvTraversalMark != canvas->trav_lst[travIdx].type || markIdx != canvas->trav_lst[travIdx].idx; travIdx++) { /* * is this mark after the one being removed? * if so, decrease its index because it's about to move. */ if (_DtCvTraversalMark == canvas->trav_lst[travIdx].type && markIdx < canvas->trav_lst[travIdx].idx) canvas->trav_lst[travIdx].idx--; } /* * move the list of traversal entries to eliminate the mark entry. */ while (travIdx + 1 < canvas->trav_cnt) { canvas->trav_lst[travIdx] = canvas->trav_lst[travIdx + 1]; /* * is this a mark after the one being removed? * if so, decrease it's index because it's about to move. */ if (_DtCvTraversalMark == canvas->trav_lst[travIdx].type && markIdx < canvas->trav_lst[travIdx].idx) canvas->trav_lst[travIdx].idx--; travIdx++; } /* * update the traversal count and back up to the previous traversal * if the mark was at the end of the traversal list. */ canvas->trav_cnt--; if (canvas->cur_trav >= canvas->trav_cnt) canvas->cur_trav--; /* * move the list of marks up */ while (markIdx + 1 < canvas->mark_cnt) { canvas->marks[markIdx] = canvas->marks[markIdx + 1]; markIdx++; } canvas->mark_cnt--; } else if ((_DtCvACTIVATE_MARK_ON | _DtCvACTIVATE_MARK_OFF) & mask) { markIdx = 0; if (NULL != info && NULL != info->client_data) { while (markIdx < canvas->mark_cnt && canvas->marks[markIdx].client_data != info->client_data) markIdx++; /* * was a mark with this client data found? */ if (markIdx >= canvas->mark_cnt) return _DtCvSTATUS_BAD; } else { /* * are there any traversals? Is the current one sitting on a mark? */ if (0 == canvas->trav_cnt || -1 == canvas->cur_trav || _DtCvTraversalMark != canvas->trav_lst[canvas->cur_trav].type) return _DtCvSTATUS_BAD; /* * get the mark index */ markIdx = canvas->trav_lst[canvas->cur_trav].idx; } /* * is this different than what it is set at now? If not, do nothing. */ if (_DtCvIsMarkMaskOn(mask) == canvas->marks[markIdx].on) return _DtCvSTATUS_NONE; /* * set to mask value. */ canvas->marks[markIdx].on = _DtCvIsMarkMaskOn(mask); /* * set the flags correctly. */ flag = _DtCvMARK_FLAG; if (_DtCvTRUE == canvas->marks[markIdx].on) flag |= _DtCvMARK_ON; if (_DtCvTRUE == canvas->trav_on && markIdx == canvas->trav_lst[canvas->cur_trav].idx) flag |= _DtCvTRAVERSAL_FLAG; /* * draw the mark opposite what it was */ _DtCvDrawAreaWithFlags (canvas, canvas->marks[markIdx].beg, canvas->marks[markIdx].end, (flag ^ _DtCvMARK_ON), flag, _DtCvBAD_TYPE, NULL); } return _DtCvSTATUS_OK; }