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