File indexing completed on 2024-04-21 16:34:02
0001 /* 0002 This file is part of the Okteta Gui library, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2003, 2008-2009 Friedrich W. H. Kossebau <kossebau@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #include "bytearraytableranges.hpp" 0010 #include "bytearraytableranges_p.hpp" 0011 0012 // lib 0013 #include "bytearraytablelayout.hpp" 0014 // Okteta core 0015 #include <Okteta/ArrayChangeMetricsList> 0016 0017 namespace Okteta { 0018 0019 ByteArrayTableRanges::ByteArrayTableRanges(ByteArrayTableLayout* layout) 0020 : d_ptr(new ByteArrayTableRangesPrivate(layout)) 0021 { 0022 } 0023 0024 ByteArrayTableRanges::~ByteArrayTableRanges() = default; 0025 0026 void ByteArrayTableRanges::reset() 0027 { 0028 Q_D(ByteArrayTableRanges); 0029 mSelection.cancel(); 0030 FirstWordSelection.unset(); 0031 mMarking.unset(); 0032 ChangedRanges.clear(); 0033 d->previousSelection = mSelection; 0034 } 0035 0036 void ByteArrayTableRanges::setMarking(const AddressRange& marking) 0037 { 0038 if (mMarking == marking) { 0039 return; 0040 } 0041 0042 const bool hadMarking = mMarking.isValid(); 0043 if (hadMarking) { 0044 addChangedRange(mMarking); 0045 } 0046 0047 mMarking = marking; 0048 0049 const bool hasNewMarking = mMarking.isValid(); 0050 if (hasNewMarking) { 0051 addChangedRange(mMarking); 0052 } 0053 } 0054 0055 void ByteArrayTableRanges::removeFurtherSelections() 0056 { 0057 for (int i = 1; i < noOfSelections(); ++i) { 0058 removeSelection(i); 0059 } 0060 } 0061 0062 void ByteArrayTableRanges::setSelection(const AddressRange& selection) 0063 { 0064 bool Changed = mSelection.isValid(); 0065 if (Changed) { 0066 addChangedRange(mSelection.range()); 0067 } 0068 mSelection = selection; 0069 addChangedRange(mSelection.range()); 0070 } 0071 0072 void ByteArrayTableRanges::setSelectionStart(Address startIndex) 0073 { 0074 bool Changed = mSelection.isValid(); 0075 if (Changed) { 0076 addChangedRange(mSelection.range()); 0077 } 0078 0079 mSelection.setStart(startIndex); 0080 } 0081 0082 void ByteArrayTableRanges::setSelectionEnd(Address EndIndex) 0083 { 0084 AddressRange OldSelection = mSelection.range(); 0085 mSelection.setEnd(EndIndex); 0086 0087 // TODO: think about rather building a diff of the sections 0088 if (!OldSelection.isValid()) { 0089 addChangedRange(mSelection.range()); 0090 return; 0091 } 0092 if (!mSelection.isValid()) { 0093 addChangedRange(OldSelection); 0094 return; 0095 } 0096 0097 if (OldSelection == mSelection.range()) { 0098 return; 0099 } 0100 Address CS; 0101 Address CE; 0102 // changes at the end? 0103 if (mSelection.start() == OldSelection.start()) { 0104 CS = OldSelection.nextBehindEnd(); 0105 CE = mSelection.end(); 0106 if (CE < CS) { 0107 CS = mSelection.nextBehindEnd(); 0108 CE = OldSelection.end(); 0109 } 0110 } 0111 // changes at the start? 0112 else if (mSelection.end() == OldSelection.end()) { 0113 CS = OldSelection.start(); 0114 CE = mSelection.nextBeforeStart(); 0115 if (CE < CS) { 0116 CS = mSelection.start(); 0117 CE = OldSelection.nextBeforeStart(); 0118 } 0119 } 0120 // change over the anchor 0121 else { 0122 CS = OldSelection.start(); 0123 CE = mSelection.end(); 0124 if (CE < CS) { 0125 CS = mSelection.start(); 0126 CE = OldSelection.end(); 0127 } 0128 } 0129 AddressRange C(CS, CE); 0130 0131 bool Changed = C.isValid(); 0132 if (Changed) { 0133 addChangedRange(C); 0134 } 0135 return; 0136 } 0137 0138 AddressRange ByteArrayTableRanges::removeSelection(int id) 0139 { 0140 if (id > 0) { 0141 return AddressRange(); 0142 } 0143 0144 AddressRange range = mSelection.range(); 0145 bool Changed = range.isValid(); 0146 if (Changed) { 0147 addChangedRange(range); 0148 } 0149 0150 mSelection.cancel(); 0151 FirstWordSelection.unset(); 0152 0153 return range; 0154 } 0155 0156 bool ByteArrayTableRanges::overlapsSelection(Address FirstIndex, Address LastIndex, Address* startIndex, Address* endIndex) const 0157 { 0158 if (mSelection.range().overlaps(AddressRange(FirstIndex, LastIndex))) { 0159 *startIndex = mSelection.start(); 0160 *endIndex = mSelection.end(); 0161 return true; 0162 } 0163 return false; 0164 } 0165 0166 bool ByteArrayTableRanges::overlapsMarking(Address FirstIndex, Address LastIndex, Address* startIndex, Address* endIndex) const 0167 { 0168 if (mMarking.overlaps(AddressRange(FirstIndex, LastIndex))) { 0169 *startIndex = mMarking.start(); 0170 *endIndex = mMarking.end(); 0171 return true; 0172 } 0173 return false; 0174 } 0175 0176 const AddressRange* ByteArrayTableRanges::firstOverlappingSelection(const AddressRange& Range) const 0177 { 0178 return mSelection.range().overlaps(Range) ? &mSelection.range() : nullptr; 0179 } 0180 0181 const AddressRange* ByteArrayTableRanges::overlappingMarking(const AddressRange& Range) const 0182 { 0183 return mMarking.overlaps(Range) ? &mMarking : nullptr; 0184 } 0185 0186 /* 0187 bool ByteArrayTableRanges::overlapsChanges( Address FirstIndex, Address LastIndex, Address* startIndex, Address* endIndex ) const 0188 { 0189 for( CoordRangeList::const_iterator S=ChangedRanges.begin(); S!=ChangedRanges.end(); ++S ) 0190 { 0191 if( (*S).overlaps(KBuff(FirstIndex,LastIndex)) ) 0192 { 0193 *startIndex = (*S).start(); 0194 *endIndex = (*S).end(); 0195 return true; 0196 } 0197 } 0198 0199 return false; 0200 } 0201 0202 bool ByteArrayTableRanges::overlapsChanges( AddressRange Indizes, AddressRange *ChangedRange ) const 0203 { 0204 for( AddressRangeList::const_iterator S=ChangedRanges.begin(); S!=ChangedRanges.end(); ++S ) 0205 { 0206 if( (*S).overlaps(Indizes) ) 0207 { 0208 *ChangedRange = *S; 0209 return true; 0210 } 0211 } 0212 0213 return false; 0214 } 0215 */ 0216 0217 bool ByteArrayTableRanges::overlapsChanges(const CoordRange& Range, CoordRange* ChangedRange) const 0218 { 0219 // TODO: add a lastusedrange pointer for quicker access 0220 return std::any_of(ChangedRanges.begin(), ChangedRanges.end(), 0221 [Range, ChangedRange](const CoordRange& changedRange) mutable { 0222 if (changedRange.overlaps(Range)) { 0223 *ChangedRange = changedRange; 0224 return true; 0225 } 0226 return false; 0227 }); 0228 } 0229 0230 void ByteArrayTableRanges::addChangedOffsetLines(const LineRange& changedLines) 0231 { 0232 if (mChangedOffsetLines.isEmpty()) { 0233 mChangedOffsetLines = changedLines; 0234 mModified = true; 0235 } else { 0236 mChangedOffsetLines.extendTo(changedLines); 0237 } 0238 } 0239 0240 void ByteArrayTableRanges::addChangedRange(Address startIndex, Address endIndex) 0241 { 0242 addChangedRange(AddressRange(startIndex, endIndex)); 0243 } 0244 0245 void ByteArrayTableRanges::addChangedRange(const AddressRange& range) 0246 { 0247 Q_D(ByteArrayTableRanges); 0248 // qCDebug(LOG_OKTETA_GUI) << "adding change range "<<S.start()<<","<<S.end(); 0249 addChangedRange(d->layout->coordRangeOfIndizes(range)); 0250 } 0251 0252 void ByteArrayTableRanges::addChangedRange(const CoordRange& range) 0253 { 0254 ChangedRanges.addCoordRange(range); 0255 // qCDebug(LOG_OKTETA_GUI) << "as range "<<NewRange.start().pos()<<","<<NewRange.start().line()<<"-" 0256 // <<NewRange.end().pos()<<","<<NewRange.end().line()<<endl; 0257 0258 mModified = true; 0259 } 0260 0261 void ByteArrayTableRanges::resetChangedRanges() 0262 { 0263 mChangedOffsetLines.unset(); 0264 ChangedRanges.clear(); 0265 mModified = false; 0266 } 0267 0268 void ByteArrayTableRanges::takeHasSelectionChanged(bool* hasSelectionChanged, bool* selectionChanged) 0269 { 0270 Q_D(ByteArrayTableRanges); 0271 0272 const bool hadSelection = d->previousSelection.isValid(); 0273 const bool hasSelection = mSelection.isValid(); 0274 *hasSelectionChanged = (hadSelection != hasSelection); 0275 0276 *selectionChanged = (d->previousSelection != mSelection); 0277 0278 if (*selectionChanged) { 0279 d->previousSelection = mSelection; 0280 } 0281 } 0282 0283 void ByteArrayTableRanges::setFirstWordSelection(const AddressRange& range) 0284 { 0285 FirstWordSelection = range; 0286 setSelection(FirstWordSelection); 0287 } 0288 0289 void ByteArrayTableRanges::ensureWordSelectionForward(bool Forward) 0290 { 0291 // in the anchor not on the right side? 0292 if (mSelection.isForward() != Forward) { 0293 setSelectionEnd(Forward ? FirstWordSelection.start() : FirstWordSelection.nextBehindEnd()); 0294 0295 mSelection.setForward(Forward); 0296 } 0297 } 0298 0299 void ByteArrayTableRanges::adaptToChanges(const ArrayChangeMetricsList& changeList, Size oldLength) 0300 { 0301 for (const ArrayChangeMetrics& change : changeList) { 0302 // TODO: change parameters to ArrayChangeMetrics 0303 switch (change.type()) 0304 { 0305 case ArrayChangeMetrics::Replacement: 0306 { 0307 oldLength += change.lengthChange(); 0308 const Address offset = change.offset(); 0309 const Size diff = change.lengthChange(); 0310 const Address behindLast = (diff == 0) ? offset + change.insertLength() : 0311 (diff < 0) ? oldLength - diff : 0312 oldLength; 0313 addChangedRange(offset, behindLast - 1); 0314 0315 if (mSelection.isValid()) { 0316 mSelection.adaptToReplacement(offset, change.removeLength(), change.insertLength()); 0317 } 0318 if (mMarking.isValid()) { 0319 mMarking.adaptToReplacement(offset, change.removeLength(), change.insertLength()); 0320 } 0321 break; 0322 } 0323 case ArrayChangeMetrics::Swapping: 0324 addChangedRange(change.offset(), change.secondEnd()); 0325 0326 if (mSelection.isValid()) { 0327 mSelection.adaptToSwap(change.offset(), change.secondStart(), change.secondLength()); 0328 } 0329 // TODO: 0330 // if( mMarking.isValid() ) 0331 // mMarking.adaptToSwap( change.offset(), change.secondStart(), change.secondLength() ); 0332 default: 0333 ; 0334 } 0335 } 0336 } 0337 0338 }