TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

444 lines
9.5KB

  1. /* This file is part of the KDE libraries
  2. Copyright (C) 2001-2003 Christoph Cullmann <cullmann@kde.org>
  3. Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
  4. Based on:
  5. KateTextLine : Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>
  6. This library is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU Library General Public
  8. License version 2 as published by the Free Software Foundation.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Library General Public License for more details.
  13. You should have received a copy of the GNU Library General Public License
  14. along with this library; see the file COPYING.LIB. If not, write to
  15. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. Boston, MA 02110-1301, USA.
  17. */
  18. #include "katetextline.h"
  19. #include "katerenderer.h"
  20. #include <tdeglobal.h>
  21. #include <tqregexp.h>
  22. KateTextLine::KateTextLine ()
  23. : m_flags(0)
  24. {
  25. }
  26. KateTextLine::~KateTextLine()
  27. {
  28. }
  29. void KateTextLine::insertText (uint pos, uint insLen, const TQChar *insText, uchar *insAttribs)
  30. {
  31. // nothing to do
  32. if (insLen == 0)
  33. return;
  34. // calc new textLen, store old
  35. uint oldTextLen = m_text.length();
  36. m_text.insert (pos, insText, insLen);
  37. uint textLen = m_text.length();
  38. // resize the array
  39. m_attributes.resize (textLen);
  40. // HA, insert behind text end, fill with spaces
  41. if (pos >= oldTextLen)
  42. {
  43. for (uint z = oldTextLen; z < pos; z++)
  44. m_attributes[z] = 0;
  45. }
  46. // HA, insert in text, move the old text behind pos
  47. else if (oldTextLen > 0)
  48. {
  49. for (int z = oldTextLen -1; z >= (int) pos; z--)
  50. m_attributes[z+insLen] = m_attributes[z];
  51. }
  52. // BUH, actually insert the new text
  53. for (uint z = 0; z < insLen; z++)
  54. {
  55. if (insAttribs == 0)
  56. m_attributes[z+pos] = 0;
  57. else
  58. m_attributes[z+pos] = insAttribs[z];
  59. }
  60. }
  61. void KateTextLine::removeText (uint pos, uint delLen)
  62. {
  63. // nothing to do
  64. if (delLen == 0)
  65. return;
  66. uint textLen = m_text.length();
  67. if (textLen == 0)
  68. return; // uh, again nothing real to do ;)
  69. if (pos >= textLen)
  70. return;
  71. if ((pos + delLen) > textLen)
  72. delLen = textLen - pos;
  73. // BU, MOVE THE OLD TEXT AROUND
  74. for (uint z = pos; z < textLen - delLen; z++)
  75. m_attributes[z] = m_attributes[z+delLen];
  76. m_text.remove (pos, delLen);
  77. m_attributes.resize (m_text.length ());
  78. }
  79. void KateTextLine::truncate(uint newLen)
  80. {
  81. if (newLen < m_text.length())
  82. {
  83. m_text.truncate (newLen);
  84. m_attributes.truncate (newLen);
  85. }
  86. }
  87. int KateTextLine::nextNonSpaceChar(uint pos) const
  88. {
  89. const uint len = m_text.length();
  90. const TQChar *unicode = m_text.unicode();
  91. for(uint i = pos; i < len; i++)
  92. {
  93. if(!unicode[i].isSpace())
  94. return i;
  95. }
  96. return -1;
  97. }
  98. int KateTextLine::previousNonSpaceChar(uint pos) const
  99. {
  100. const int len = m_text.length();
  101. if (pos >= (uint)len)
  102. pos = len - 1;
  103. const TQChar *unicode = m_text.unicode();
  104. for(int i = pos; i >= 0; i--)
  105. {
  106. if(!unicode[i].isSpace())
  107. return i;
  108. }
  109. return -1;
  110. }
  111. int KateTextLine::firstChar() const
  112. {
  113. return nextNonSpaceChar(0);
  114. }
  115. int KateTextLine::lastChar() const
  116. {
  117. return previousNonSpaceChar(m_text.length() - 1);
  118. }
  119. const TQChar *KateTextLine::firstNonSpace() const
  120. {
  121. int first = firstChar();
  122. return (first > -1) ? ((TQChar*)m_text.unicode())+first : m_text.unicode();
  123. }
  124. uint KateTextLine::indentDepth (uint tabwidth) const
  125. {
  126. uint d = 0;
  127. const uint len = m_text.length();
  128. const TQChar *unicode = m_text.unicode();
  129. for(uint i = 0; i < len; i++)
  130. {
  131. if(unicode[i].isSpace())
  132. {
  133. if (unicode[i] == TQChar('\t'))
  134. d += tabwidth - (d % tabwidth);
  135. else
  136. d++;
  137. }
  138. else
  139. return d;
  140. }
  141. return d;
  142. }
  143. bool KateTextLine::stringAtPos(uint pos, const TQString& match) const
  144. {
  145. const uint len = m_text.length();
  146. const uint matchlen = match.length();
  147. if ((pos+matchlen) > len)
  148. return false;
  149. // (pos > len) in case the uint pos was assigned a signed -1, pos+matchlen can
  150. // overflow again which (pos+matchlen > len) does not catch; see bugs #129263 and #129580
  151. Q_ASSERT(pos < len);
  152. const TQChar *unicode = m_text.unicode();
  153. const TQChar *matchUnicode = match.unicode();
  154. for (uint i=0; i < matchlen; i++)
  155. if (unicode[i+pos] != matchUnicode[i])
  156. return false;
  157. return true;
  158. }
  159. bool KateTextLine::startingWith(const TQString& match) const
  160. {
  161. const uint matchlen = match.length();
  162. if (matchlen > m_text.length())
  163. return false;
  164. const TQChar *unicode = m_text.unicode();
  165. const TQChar *matchUnicode = match.unicode();
  166. for (uint i=0; i < matchlen; i++)
  167. if (unicode[i] != matchUnicode[i])
  168. return false;
  169. return true;
  170. }
  171. bool KateTextLine::endingWith(const TQString& match) const
  172. {
  173. const uint matchlen = match.length();
  174. if (matchlen > m_text.length())
  175. return false;
  176. const TQChar *unicode = m_text.unicode();
  177. const TQChar *matchUnicode = match.unicode();
  178. uint start = m_text.length() - matchlen;
  179. for (uint i=0; i < matchlen; i++)
  180. if (unicode[start+i] != matchUnicode[i])
  181. return false;
  182. return true;
  183. }
  184. int KateTextLine::cursorX(uint pos, uint tabChars) const
  185. {
  186. uint x = 0;
  187. const uint n = kMin (pos, (uint)m_text.length());
  188. const TQChar *unicode = m_text.unicode();
  189. for ( uint z = 0; z < n; z++)
  190. {
  191. if (unicode[z] == TQChar('\t'))
  192. x += tabChars - (x % tabChars);
  193. else
  194. x++;
  195. }
  196. return x;
  197. }
  198. uint KateTextLine::lengthWithTabs (uint tabChars) const
  199. {
  200. uint x = 0;
  201. const uint len = m_text.length();
  202. const TQChar *unicode = m_text.unicode();
  203. for ( uint z = 0; z < len; z++)
  204. {
  205. if (unicode[z] == TQChar('\t'))
  206. x += tabChars - (x % tabChars);
  207. else
  208. x++;
  209. }
  210. return x;
  211. }
  212. bool KateTextLine::searchText (uint startCol, const TQString &text, uint *foundAtCol, uint *matchLen, bool casesensitive, bool backwards)
  213. {
  214. int index;
  215. if (backwards)
  216. {
  217. int col = startCol;
  218. uint l = text.length();
  219. // allow finding the string ending at eol
  220. if ( col == (int) m_text.length() ) ++startCol;
  221. do {
  222. index = m_text.findRev( text, col, casesensitive );
  223. col--;
  224. } while ( col >= 0 && l + index >= startCol );
  225. }
  226. else
  227. index = m_text.find (text, startCol, casesensitive);
  228. if (index > -1)
  229. {
  230. if (foundAtCol)
  231. (*foundAtCol) = index;
  232. if (matchLen)
  233. (*matchLen)=text.length();
  234. return true;
  235. }
  236. return false;
  237. }
  238. bool KateTextLine::searchText (uint startCol, const TQRegExp &regexp, uint *foundAtCol, uint *matchLen, bool backwards)
  239. {
  240. int index;
  241. if (backwards)
  242. {
  243. int col = startCol;
  244. // allow finding the string ending at eol
  245. if ( col == (int) m_text.length() ) ++startCol;
  246. do {
  247. index = regexp.searchRev (m_text, col);
  248. col--;
  249. } while ( col >= 0 && regexp.matchedLength() + index >= (int)startCol );
  250. }
  251. else
  252. index = regexp.search (m_text, startCol);
  253. if (index > -1)
  254. {
  255. if (foundAtCol)
  256. (*foundAtCol) = index;
  257. if (matchLen)
  258. (*matchLen)=regexp.matchedLength();
  259. return true;
  260. }
  261. return false;
  262. }
  263. char *KateTextLine::dump (char *buf, bool withHighlighting) const
  264. {
  265. uint l = m_text.length();
  266. char f = m_flags;
  267. if (!withHighlighting)
  268. f = f | KateTextLine::flagNoOtherData;
  269. memcpy(buf, (char *) &f, 1);
  270. buf += 1;
  271. memcpy(buf, &l, sizeof(uint));
  272. buf += sizeof(uint);
  273. memcpy(buf, (char *) m_text.unicode(), sizeof(TQChar)*l);
  274. buf += sizeof(TQChar) * l;
  275. if (!withHighlighting)
  276. return buf;
  277. memcpy(buf, (char *)m_attributes.data(), sizeof(uchar) * l);
  278. buf += sizeof (uchar) * l;
  279. uint lctx = m_ctx.size();
  280. uint lfold = m_foldingList.size();
  281. uint lind = m_indentationDepth.size();
  282. memcpy(buf, &lctx, sizeof(uint));
  283. buf += sizeof(uint);
  284. memcpy(buf, &lfold, sizeof(uint));
  285. buf += sizeof(uint);
  286. memcpy(buf, &lind, sizeof(uint));
  287. buf += sizeof(uint);
  288. memcpy(buf, (char *)m_ctx.data(), sizeof(short) * lctx);
  289. buf += sizeof (short) * lctx;
  290. memcpy(buf, (char *)m_foldingList.data(), sizeof(uint)*lfold);
  291. buf += sizeof (uint) * lfold;
  292. memcpy(buf, (char *)m_indentationDepth.data(), sizeof(unsigned short) * lind);
  293. buf += sizeof (unsigned short) * lind;
  294. return buf;
  295. }
  296. char *KateTextLine::restore (char *buf)
  297. {
  298. uint l = 0;
  299. char f = 0;
  300. memcpy((char *) &f, buf, 1);
  301. buf += 1;
  302. // text + context length read
  303. memcpy((char *) &l, buf, sizeof(uint));
  304. buf += sizeof(uint);
  305. // text + attributes
  306. m_text.setUnicode ((TQChar *) buf, l);
  307. buf += sizeof(TQChar) * l;
  308. // we just restore a KateTextLine from a buffer first time
  309. if (f & KateTextLine::flagNoOtherData)
  310. {
  311. m_flags = 0;
  312. if (f & KateTextLine::flagAutoWrapped)
  313. m_flags = m_flags | KateTextLine::flagAutoWrapped;
  314. // fill with clean empty attribs !
  315. m_attributes.fill (0, l);
  316. return buf;
  317. }
  318. else
  319. m_flags = f;
  320. m_attributes.duplicate ((uchar *) buf, l);
  321. buf += sizeof(uchar) * l;
  322. uint lctx = 0;
  323. uint lfold = 0;
  324. uint lind = 0;
  325. memcpy((char *) &lctx, buf, sizeof(uint));
  326. buf += sizeof(uint);
  327. memcpy((char *) &lfold, buf, sizeof(uint));
  328. buf += sizeof(uint);
  329. memcpy((char *) &lind, buf, sizeof(uint));
  330. buf += sizeof(uint);
  331. m_ctx.duplicate ((short *) buf, lctx);
  332. buf += sizeof(short) * lctx;
  333. m_foldingList.duplicate ((uint *) buf, lfold);
  334. buf += sizeof(uint)*lfold;
  335. m_indentationDepth.duplicate ((unsigned short *) buf, lind);
  336. buf += sizeof(unsigned short) * lind;
  337. return buf;
  338. }
  339. // kate: space-indent on; indent-width 2; replace-tabs on;