This file is indexed.

/usr/include/klftools/klfiteratorsearchable.h is in libklatexformula4-dev 4.0.0-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
/***************************************************************************
 *   file klfiteratorsearchable.h
 *   This file is part of the KLatexFormula Project.
 *   Copyright (C) 2011 by Philippe Faist
 *   philippe.faist at bluewin.ch
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
/* $Id: klfiteratorsearchable.h 983 2016-12-31 21:03:44Z phfaist $ */

#ifndef KLF_ITERATORSEARCHABLE_H
#define KLF_ITERATORSEARCHABLE_H

#include <QDebug>
#include <QObject>
#include <QString>
#include <QApplication>
#include <QTime>
#include <QEvent>
#include <QLineEdit>

#include <klfdefs.h>
#include <klfsearchbar.h>


//! A Searchable object interface based on iterative searching
/** Most searchable displays work with iterators, or objects that behave as such. This can be, for example,
 * an integer position in a displayed list. When searchFind() is called, then usually the search iteratively
 * looks at all items in the list, until a match is found.
 *
 * This class implements an interface of such iterator-based searchable displays for use as a KLFSearchable,
 * to be searched with a KLFSearchBar for example.
 *
 * The \a iterator may be any object that:
 *  - can be (logically) incremented and decremeneted. (this does not have to be with the operators -- and ++)
 *  - can be compared for equality with ==
 *  - has a copy constructor
 * apart from these conditions, the iterator may be any data type (example: \c int, \c QModelIndex, ...)
 *
 * The functions searchIterBegin() and searchIterEnd() have to be implemented, to return respectively an
 * iterator position for the first valid displayed element, and an iterator for the one-after-last-valid
 * displayed item.
 *
 * The function searchIterAdvance(), by default uses operator-(Iter, int) and operator+(Iter, int) to
 * increment or decrement the iterator by one. If this is not the correct way to increment/decrement
 * an iterator, reimplement this function to perform the job correctly. (for example to walk with
 * QModelIndex'es in a tree view).
 *
 * The search functions defined in this class guarantee never to increment an iterator that is already
 * equal to searchIterEnd(), and never to decrement an operator that is equal to searchIterBegin().
 *
 * The searchIterMatches() has to be reimplemented to say whether the data displayed at the given position
 * matches with the query string.
 *
 * This class provides implementations for KLFSearchable's searchFind(), searchFindNext() and searchAbort().
 * Additionally, it provides searchIterFind(), searchIterFindNext() which are a bit more flexible than
 * KLFSearchable's base functions (for example by returning the match position!).
 */
template<class Iter>
class KLF_EXPORT KLFIteratorSearchable : public KLFPosSearchable
{
public:
  KLFIteratorSearchable() : KLFPosSearchable()
  {
  }

  virtual ~KLFIteratorSearchable()
  {
  }

  typedef Iter SearchIterator;


  // FUNCTIONS TO ACCESS SEARCHABLE DATA (REIMPLEMENT TO FIT YOUR NEEDS)

  /** Returns the first valid \c SearchIterator object. This should point to the element at top of the display, or be
   * equal to searchIterEnd() if the display is empty. */
  virtual SearchIterator searchIterBegin() = 0;

  /** Returns the one-after-last-valid \c SearchIterator object. This should NOT point to a valid object, however
   * it should either be equal to searchIterBegin() if the display is empty, or if searchIterPrev() is called
   * on it it should validly point on the last object in display. */
  virtual SearchIterator searchIterEnd() = 0;

  /** Increment or decrement iterator. The default implementation does <tt>pos+1</tt> or <tt>pos-1</tt>; you
   * can re-implement this function if your iterator cannot be incremented/decremented this way. */
  virtual SearchIterator searchIterAdvance(const SearchIterator& pos, bool forward) = 0;

  /** Increment iterator. Shortcut for searchIterAdvance() with \c forward = TRUE. */
  inline SearchIterator searchIterNext(const SearchIterator& pos) { return searchIterAdvance(pos, true); }

  /** Decrement iterator. Shortcut for searchIterAdvance() with \c forward = FALSE. */
  inline SearchIterator searchIterPrev(const SearchIterator& pos) { return searchIterAdvance(pos, false); }

  /** Returns the position from where we should start the search, given the current view situation. This
   * can be reimplemented to start the search for example from the current scroll position in the display.
   *
   * If \c forward is TRUE, then the search is about to be performed forward, otherwise it is about to
   * be performed in reverse direction.
   *
   * The default implementation returns searchIterEnd(). */
  virtual SearchIterator searchIterStartFrom(bool forward)
  {  Q_UNUSED(forward);  return searchIterEnd();  }

  /** See if the data pointed at by \c pos matches the query string \c queryString. Return TRUE if it
   * does match, or FALSE if it does not match.
   *
   * \c pos is garanteed to point on a valid object (this function will never be called with \c pos
   * equal to searchIterEnd()). */
  virtual bool searchIterMatches(const SearchIterator& pos, const QString& queryString) = 0;


  /** Virtual handler for the subclass to act upon the result of a search. A subclass may for example
   * want to select the matched item in a list to make it conspicuous to the user.
   *
   * \c resultMatchPosition is the position of the item that matched the search. If \c resultMatchPosition
   * is equal to searchIterEnd(), then the search failed (no match was found). (Note in this case
   * calling searchFindNext() again will wrap the search).
   *
   * The base implementation does nothing. */
  virtual void searchPerformed(const SearchIterator& resultMatchPosition, bool found, const QString& queryString)
  {  Q_UNUSED(resultMatchPosition); Q_UNUSED(found); Q_UNUSED(queryString);  }

  /** Virtual handler that is called when the current search position moves, eg. we moved to next match.
   * For example, reimplement this function to select the corresponding item in a list (possibly scrolling the
   * list) to display the matching item to the user.  */
  virtual void searchMoveToIterPos(const SearchIterator& pos)
  {  Q_UNUSED(pos);  }

  /** Virtual handler for the subclass to act upon the result of a search. Same as
   * searchPerformed(const SearchIterator&, bool, const QString&), but with less pararmeters. This function
   * is exactly called when the other function is called, too.
   */
  virtual void searchPerformed(const SearchIterator& resultMatchPosition)
  {  Q_UNUSED(resultMatchPosition);  }


  /* Aborts the search.
   *
   * If you reimplement this function to perform additional actions when aborting searches, make sure you
   * call the base class implementation, since searchAbort() may be called by the event loop while
   * refreshing the GUI during an active search, in which case the base implementation of this function
   * tells the search to stop.
   */
  virtual void searchAborted()
  {
    setSearchInterruptRequested(true);
  }



  // REIMPLEMENTATIONS THAT TRANSLATE POS OBJECTS TO ITERATORS
  // ... don't reimplement unless really necessary.

  virtual Pos searchStartFrom(bool forward)
  {
    KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
    return posForIterator(searchIterStartFrom(forward));
  }

  /** Reimplemented from KLFPosSearchable. This function calls the searchPerformed(const SearchIterator&)
   * functions. In subclasses, reimplement one of those instead. */
  virtual void searchPerformed(const QString& queryString, bool found, const Pos& pos)
  {
    searchPerformed(iteratorForPos(pos), found, queryString);
    searchPerformed(iteratorForPos(pos));
  }

  virtual void searchMoveToPos(const Pos& pos)
  {
    searchMoveToIterPos(iteratorForPos(pos));
  }


  // FUNCTIONS THAT PERFORM THE SEARCH
  // ... don't reimplement unless _ABSOLUTELY_ necessary.

  //! Find occurence of a search string
  /** Extension of searchFind(). Looks for \c queryString starting at position \c startPos.
   *
   * This function returns the position to the first match, or searchIterEnd() if no match was found.
   *
   * This function starts searching immediately after \c startPos, in forward direction, if \c forward is
   * TRUE, and searches immediately before from c startPos, in reverse direction, if \c forward is FALSE.
   *
   * This function need not be reimplemented, the default implementation should suffice for most cases.
   */
  virtual SearchIterator searchIterFind(const SearchIterator& startPos, const QString& queryString, bool forward)
  {
    KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
    Q_UNUSED(queryString) ;
    klfDbg( " s="<<queryString<<" from "<<startPos<<" forward="<<forward
	    <<"; searchQueryString()="<<searchQueryString() ) ;
    pCurPos = startPos;
    SearchIterator it = searchIterFindNext(forward);
    return it;
  }

  //! Find the next occurence of previous search string
  /** Extension of searchFindNext(), in that this function returns the position of the next match.
   *
   * Returns searchIterEnd() if no match was found.
   *
   * This function need not be reimplemented, the default implementation should suffice for most cases. */
  virtual SearchIterator searchIterFindNext(bool forward)
  {
    KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;

    if (searchQueryString().isEmpty()) {
      klfDbg("empty search query string.") ;
      return tee_notify_search_result(searchIterEnd());
    }
    
    QTime t;
    
    bool found = false;
    while ( ! found ) {
      klfDbg("advancing iterator in search... pCurPos="<<pCurPos) ;
      // advance iterator.
      
      pCurPos = safe_cycl_advance_iterator(pCurPos, forward);

      klfDbg("advanced. pCurPos="<<pCurPos) ;

      // stop if we reached the end
      if (pCurPos == searchIterEnd())
	break;
      
      // at this point pCurPos points on something valid
      
      if ( searchIterMatches(pCurPos, searchQueryString()) ) {
	found = true;
	break;
      }
      
      // call application's processEvents() from time to time to prevent GUI from freezing
      if (t.elapsed() > 150) {
	qApp->processEvents();
	if (searchHasInterruptRequested()) {
	  klfDbg("interrupting...") ;
	  break;
	}
	t.restart();
      }
    }
    if (found) {
      klfDbg( "found "<<searchQueryString()<<" at "<<pCurPos ) ;
      return tee_notify_search_result(pCurPos);
    }
    
    // not found
    return tee_notify_search_result(searchIterEnd());
  }


  // reimplemented from KLFPosSearchable (do not reimplement)

  virtual Pos searchFind(const QString& queryString, const Pos& fromPos, bool forward)
  {
    KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
    klfDbg("queryString="<<queryString<<"; searchQueryString="<<searchQueryString()) ;
    SearchIterator startit = iteratorForPos(fromPos);
    SearchIterator matchit = searchIterFind(startit, queryString, forward);
    return posForIterator(matchit);
  }


  /** Advances iterator \c it safely, that means it increments or decrements the iterator while always
   * making sure not to perform illegal operations like increment an iterator that has arrived at
   * searchIterEnd() and making sure not to decrement an iterator that has arrived at searchIterBegin().
   *
   * Iterators that have arrived to searchIterEnd() or searchIterBegin(), when again incremented (resp.
   * decremented), wrap around and start again from the other end. Namely decrementing an iterator equal
   * to searchIterBegin() will give you searchIterEnd() and incrementing searchIterEnd() will yield
   * searchIterBegin().
   *
   * \bug THIS FUNCITON IS _VERY_ CLOSE TO \ref searchAdvanceIteratorCycle ! DON'T DUPLICATE CODE !
   */
  SearchIterator searchAdvanceIteratorSafe(const SearchIterator& it, int n = 1)
  {
    if (n == 0)
      return it;
    bool forward = (n>0);
    if (n < 0)
      n = -n;
    // 'n' is number of steps (positive) to perform in direction 'forward'
    SearchIterator a = it;
    while (n--)
      a = safe_cycl_advance_iterator(a, forward);

    return a;
  }

  /** Advances the iterator \c it by \c n steps (which may be negative). If the end is reached,
   * the iterator wraps back to the beginning. if \c skipEnd is true, then the position when
   * it is equal to searchIterEnd() is skipped. */
  SearchIterator searchAdvanceIteratorCycle(const SearchIterator& it, int n = 1, bool skipEnd = false)
  {
    bool forward = (n >= 0);
    if (!forward)
      n = -n;
    SearchIterator it2 = it;
    while (n--) {
      it2 = safe_cycl_advance_iterator(it2, forward);
      if (it2 == searchIterEnd() && skipEnd)
	it2 = safe_cycl_advance_iterator(it2, forward);
    }
    return it2;
  }

protected:

  inline SearchIterator searchCurrentIterPos() const { return pCurPos; }

private:
  /** The current I-Search position */
  SearchIterator pCurPos;


  struct IterPosData : public KLFPosSearchable::Pos::PosData {
    IterPosData(Iter iterator) : it(iterator) { }

    Iter it;

    virtual bool equals(KLFPosSearchable::Pos::PosData * other) const
    {
      IterPosData * itpd = dynamic_cast<IterPosData*>(other);
      KLF_ASSERT_NOT_NULL(itpd, "posdata of pos ptr `other' is NULL!", return false; ) ;
      return  (it == itpd->it) ;
    }
  };

  SearchIterator iteratorForPos(const KLFPosSearchable::Pos& p)
  {
    KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
    if (!p.valid())
      return searchIterEnd();
    IterPosData *itpd = p.data<IterPosData>();
    KLF_ASSERT_NOT_NULL(itpd, "posdata of pos `p' is NULL!", return searchIterEnd() ) ;
    return itpd->it;
  }
  KLFPosSearchable::Pos posForIterator(const SearchIterator& it)
  {
    KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
    Pos p = Pos();
    if (it == searchIterEnd())
      return p; // an invalid pos
    p.posdata = new IterPosData(it);
    return p;
  }

  inline SearchIterator tee_notify_search_result(const SearchIterator& iter)
  {
    searchPerformed(iter);
    return iter;
  }

  inline SearchIterator safe_cycl_advance_iterator(const SearchIterator& it, bool forward)
  {
    if (forward) {
      if (it == searchIterEnd())
	return searchIterBegin();
      return searchIterNext(it);
    } else {
      if (it == searchIterBegin())
	return searchIterEnd();
      return searchIterPrev(it);
    }
  }
};



#endif