lib Library API Documentation

koparagcounter.cc

00001 /* This file is part of the KDE project 00002 Copyright (C) 2001 Shaheed Haque <srhaque@iee.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00017 Boston, MA 02111-1307, USA. 00018 */ 00019 00020 #include "koparagcounter.h" 00021 #include "kozoomhandler.h" 00022 #include "kotextformat.h" 00023 #include "kotextdocument.h" 00024 #include <kdebug.h> 00025 #include <qdom.h> 00026 00027 static KoTextParag * const INVALID_PARAG = (KoTextParag *)-1; 00028 00029 KoParagCounter::KoParagCounter() 00030 { 00031 m_numbering = NUM_NONE; 00032 m_style = STYLE_NONE; 00033 m_depth = 0; 00034 m_startNumber = 1; 00035 m_displayLevels = 1; 00036 m_restartCounter = false; 00037 m_customBulletChar = QChar( '-' ); 00038 m_customBulletFont = QString::null; 00039 m_align = Qt::AlignAuto; 00040 invalidate(); 00041 } 00042 00043 bool KoParagCounter::operator==( const KoParagCounter & c2 ) const 00044 { 00045 // ## This is kinda wrong. Unused fields (depending on the counter style) shouldn't be compared. 00046 return (m_numbering==c2.m_numbering && 00047 m_style==c2.m_style && 00048 m_depth==c2.m_depth && 00049 m_startNumber==c2.m_startNumber && 00050 m_displayLevels==c2.m_displayLevels && 00051 m_restartCounter==c2.m_restartCounter && 00052 m_prefix==c2.m_prefix && 00053 m_suffix==c2.m_suffix && 00054 m_customBulletChar==c2.m_customBulletChar && 00055 m_customBulletFont==c2.m_customBulletFont && 00056 m_align==c2.m_align && 00057 m_custom==c2.m_custom); 00058 00059 } 00060 00061 QString KoParagCounter::custom() const 00062 { 00063 return m_custom; 00064 } 00065 00066 QChar KoParagCounter::customBulletCharacter() const 00067 { 00068 return m_customBulletChar; 00069 } 00070 00071 QString KoParagCounter::customBulletFont() const 00072 { 00073 return m_customBulletFont; 00074 } 00075 00076 unsigned int KoParagCounter::depth() const 00077 { 00078 return m_depth; 00079 } 00080 00081 void KoParagCounter::invalidate() 00082 { 00083 m_cache.number = -1; 00084 m_cache.text = QString::null; 00085 m_cache.width = -1; 00086 m_cache.parent = INVALID_PARAG; 00087 m_cache.counterFormat = 0; 00088 } 00089 00090 bool KoParagCounter::isBullet( Style style ) // static 00091 { 00092 switch ( style ) 00093 { 00094 case STYLE_DISCBULLET: 00095 case STYLE_SQUAREBULLET: 00096 case STYLE_BOXBULLET: 00097 case STYLE_CIRCLEBULLET: 00098 case STYLE_CUSTOMBULLET: 00099 return true; 00100 default: 00101 return false; 00102 } 00103 } 00104 00105 bool KoParagCounter::isBullet() const 00106 { 00107 return isBullet( static_cast<Style>(m_style) ); 00108 } 00109 00110 void KoParagCounter::load( QDomElement & element ) 00111 { 00112 m_numbering = static_cast<Numbering>( element.attribute("numberingtype", "2").toInt() ); 00113 m_style = static_cast<Style>( element.attribute("type").toInt() ); 00114 // Old docs have this: 00115 if ( (Numbering)m_numbering == NUM_LIST && (Style)m_style == STYLE_NONE ) 00116 m_numbering = NUM_NONE; 00117 m_depth = element.attribute("depth").toInt(); 00118 m_customBulletChar = QChar( element.attribute("bullet").toInt() ); 00119 m_prefix = element.attribute("lefttext"); 00120 if ( m_prefix.lower() == "(null)" ) // very old kword thing 00121 m_prefix = QString::null; 00122 m_suffix = element.attribute("righttext"); 00123 if ( m_suffix.lower() == "(null)" ) 00124 m_suffix = QString::null; 00125 QString s = element.attribute("start"); 00126 if ( s.isEmpty() ) 00127 m_startNumber = 1; 00128 else if ( s[0].isDigit() ) 00129 m_startNumber = s.toInt(); 00130 else // support for very-old files 00131 m_startNumber = s.lower()[0].latin1() - 'a' + 1; 00132 s = element.attribute("display-levels"); 00133 if ( !s.isEmpty() ) 00134 m_displayLevels = QMIN( s.toInt(), m_depth+1 ); // can't be > depth+1 00135 else // Not specified -> compat with koffice-1.2: make equal to depth+1 00136 m_displayLevels = m_depth+1; 00137 m_customBulletFont = element.attribute("bulletfont"); 00138 m_custom = element.attribute("customdef"); 00139 m_align = element.attribute("align", "0").toInt(); //AlignAuto as defeult 00140 QString restart = element.attribute("restart"); 00141 m_restartCounter = (restart == "true") || (restart == "1"); 00142 invalidate(); 00143 } 00144 00145 int KoParagCounter::number( const KoTextParag *paragraph ) 00146 { 00147 // Return cached value if possible. 00148 if ( m_cache.number != -1 ) 00149 return m_cache.number; 00150 00151 // Should we start a new list? 00152 if ( m_restartCounter ) { 00153 m_cache.number = m_startNumber; 00154 return m_startNumber; 00155 } 00156 00157 // Go looking for another paragraph at the same level or higher level. 00158 // (This code shares logic with parent()) 00159 KoTextParag *otherParagraph = paragraph->prev(); 00160 KoParagCounter *otherCounter; 00161 00162 switch ( m_numbering ) 00163 { 00164 case NUM_NONE: 00165 // This should not occur! 00166 case NUM_FOOTNOTE: 00167 m_cache.number = 0; 00168 break; 00169 case NUM_CHAPTER: 00170 m_cache.number = m_startNumber; 00171 // Go upwards... 00172 while ( otherParagraph ) 00173 { 00174 otherCounter = otherParagraph->counter(); 00175 if ( otherCounter && // ...look at numbered paragraphs only 00176 ( (Numbering)otherCounter->m_numbering == NUM_CHAPTER ) && // ...same number type. 00177 ( otherCounter->m_depth <= m_depth ) ) // ...same or higher level. 00178 { 00179 if ( ( otherCounter->m_depth == m_depth ) && 00180 ( otherCounter->m_style == m_style ) ) 00181 { 00182 // Found a preceding paragraph of exactly our type! 00183 m_cache.number = otherCounter->number( otherParagraph ) + 1; 00184 } 00185 else 00186 { 00187 // Found a preceding paragraph of higher level! 00188 m_cache.number = m_startNumber; 00189 } 00190 break; 00191 } 00192 otherParagraph = otherParagraph->prev(); 00193 } 00194 break; 00195 case NUM_LIST: 00196 m_cache.number = m_startNumber; 00197 // Go upwards... 00198 while ( otherParagraph ) 00199 { 00200 otherCounter = otherParagraph->counter(); 00201 if ( otherCounter ) // look at numbered paragraphs only 00202 { 00203 if ( ( (Numbering)otherCounter->m_numbering == NUM_LIST ) && // ...same number type. 00204 !isBullet( static_cast<Style>(otherCounter->m_style) ) && // ...not a bullet 00205 ( otherCounter->m_depth <= m_depth ) ) // ...same or higher level. 00206 { 00207 if ( ( otherCounter->m_depth == m_depth ) && 00208 ( otherCounter->m_style == m_style ) ) 00209 { 00210 // Found a preceding paragraph of exactly our type! 00211 m_cache.number = otherCounter->number( otherParagraph ) + 1; 00212 } 00213 else 00214 { 00215 // Found a preceding paragraph of higher level! 00216 m_cache.number = m_startNumber; 00217 } 00218 break; 00219 } 00220 else 00221 if ( (Numbering)otherCounter->m_numbering == NUM_CHAPTER ) // ...heading number type. 00222 { 00223 m_cache.number = m_startNumber; 00224 break; 00225 } 00226 } 00227 /* else 00228 { 00229 // There is no counter at all. 00230 m_cache.number = m_startNumber; 00231 break; 00232 }*/ 00233 otherParagraph = otherParagraph->prev(); 00234 } 00235 break; 00236 } 00237 return m_cache.number; 00238 } 00239 00240 KoParagCounter::Numbering KoParagCounter::numbering() const 00241 { 00242 return static_cast<Numbering>(m_numbering); 00243 } 00244 00245 // Go looking for another paragraph at a higher level. 00246 KoTextParag *KoParagCounter::parent( const KoTextParag *paragraph ) 00247 { 00248 // Return cached value if possible. 00249 if ( m_cache.parent != INVALID_PARAG ) 00250 return m_cache.parent; 00251 00252 KoTextParag *otherParagraph = paragraph->prev(); 00253 KoParagCounter *otherCounter; 00254 00255 // (This code shares logic with number()) 00256 switch ( (Numbering)m_numbering ) 00257 { 00258 case NUM_NONE: 00259 // This should not occur! 00260 case NUM_FOOTNOTE: 00261 otherParagraph = 0L; 00262 break; 00263 case NUM_CHAPTER: 00264 // Go upwards while... 00265 while ( otherParagraph ) 00266 { 00267 otherCounter = otherParagraph->counter(); 00268 if ( otherCounter && // ...numbered paragraphs. 00269 ( (Numbering)otherCounter->m_numbering == NUM_CHAPTER ) && // ...same number type. 00270 ( otherCounter->m_depth < m_depth ) ) // ...higher level. 00271 { 00272 break; 00273 } 00274 otherParagraph = otherParagraph->prev(); 00275 } 00276 break; 00277 case NUM_LIST: 00278 // Go upwards while... 00279 while ( otherParagraph ) 00280 { 00281 otherCounter = otherParagraph->counter(); 00282 if ( otherCounter ) // ...numbered paragraphs. 00283 { 00284 if ( ( (Numbering)otherCounter->m_numbering == NUM_LIST ) && // ...same number type. 00285 !isBullet( static_cast<Style>(otherCounter->m_style) ) && // ...not a bullet 00286 ( otherCounter->m_depth < m_depth ) ) // ...higher level. 00287 { 00288 break; 00289 } 00290 else 00291 if ( (Numbering)otherCounter->m_numbering == NUM_CHAPTER ) // ...heading number type. 00292 { 00293 otherParagraph = 0L; 00294 break; 00295 } 00296 } 00297 otherParagraph = otherParagraph->prev(); 00298 } 00299 break; 00300 } 00301 m_cache.parent = otherParagraph; 00302 return m_cache.parent; 00303 } 00304 00305 QString KoParagCounter::prefix() const 00306 { 00307 return m_prefix; 00308 } 00309 00310 void KoParagCounter::save( QDomElement & element ) 00311 { 00312 element.setAttribute( "type", static_cast<int>( m_style ) ); 00313 element.setAttribute( "depth", m_depth ); 00314 if ( (Style)m_style == STYLE_CUSTOMBULLET ) 00315 { 00316 element.setAttribute( "bullet", m_customBulletChar.unicode() ); 00317 if ( !m_customBulletFont.isEmpty() ) 00318 element.setAttribute( "bulletfont", m_customBulletFont ); 00319 } 00320 if ( !m_prefix.isEmpty() ) 00321 element.setAttribute( "lefttext", m_prefix ); 00322 if ( !m_suffix.isEmpty() ) 00323 element.setAttribute( "righttext", m_suffix ); 00324 if ( m_startNumber != 1 ) 00325 element.setAttribute( "start", m_startNumber ); 00326 //if ( m_displayLevels != m_depth ) // see load() 00327 element.setAttribute( "display-levels", m_displayLevels ); 00328 // Don't need to save NUM_FOOTNOTE, it's updated right after loading 00329 if ( (Numbering)m_numbering != NUM_NONE && (Numbering)m_numbering != NUM_FOOTNOTE ) 00330 element.setAttribute( "numberingtype", static_cast<int>( m_numbering ) ); 00331 if ( !m_custom.isEmpty() ) 00332 element.setAttribute( "customdef", m_custom ); 00333 if ( m_restartCounter ) 00334 element.setAttribute( "restart", "true" ); 00335 if ( !m_cache.text.isEmpty() ) 00336 element.setAttribute( "text", m_cache.text ); 00337 element.setAttribute( "align", m_align ); 00338 } 00339 00340 void KoParagCounter::setCustom( QString c ) 00341 { 00342 m_custom = c; 00343 invalidate(); 00344 } 00345 00346 void KoParagCounter::setCustomBulletCharacter( QChar c ) 00347 { 00348 m_customBulletChar = c; 00349 invalidate(); 00350 } 00351 00352 void KoParagCounter::setCustomBulletFont( QString f ) 00353 { 00354 m_customBulletFont = f; 00355 invalidate(); 00356 } 00357 00358 void KoParagCounter::setDepth( unsigned int d ) 00359 { 00360 m_depth = d; 00361 invalidate(); 00362 } 00363 00364 void KoParagCounter::setNumbering( Numbering n ) 00365 { 00366 m_numbering = n; 00367 invalidate(); 00368 } 00369 00370 void KoParagCounter::setPrefix( QString p ) 00371 { 00372 m_prefix = p; 00373 invalidate(); 00374 } 00375 void KoParagCounter::setStartNumber( int s ) 00376 { 00377 m_startNumber = s; 00378 invalidate(); 00379 } 00380 00381 void KoParagCounter::setDisplayLevels( int l ) 00382 { 00383 m_displayLevels = l; 00384 invalidate(); 00385 } 00386 00387 void KoParagCounter::setAlignment( int a ) 00388 { 00389 m_align = a; 00390 invalidate(); 00391 } 00392 00393 void KoParagCounter::setStyle( Style s ) 00394 { 00395 m_style = s; 00396 invalidate(); 00397 } 00398 00399 void KoParagCounter::setSuffix( QString s ) 00400 { 00401 m_suffix = s; 00402 invalidate(); 00403 } 00404 00405 int KoParagCounter::startNumber() const 00406 { 00407 return m_startNumber; 00408 } 00409 00410 int KoParagCounter::displayLevels() const 00411 { 00412 return m_displayLevels; 00413 } 00414 00415 int KoParagCounter::alignment() const 00416 { 00417 return m_align; 00418 } 00419 00420 KoParagCounter::Style KoParagCounter::style() const 00421 { 00422 return static_cast<Style>(m_style); 00423 } 00424 00425 QString KoParagCounter::suffix() const 00426 { 00427 return m_suffix; 00428 } 00429 00430 bool KoParagCounter::restartCounter() const 00431 { 00432 return m_restartCounter; 00433 } 00434 00435 void KoParagCounter::setRestartCounter( bool restart ) 00436 { 00437 m_restartCounter = restart; 00438 invalidate(); 00439 } 00440 00441 // Return the text for that level only 00442 QString KoParagCounter::levelText( const KoTextParag *paragraph ) 00443 { 00444 bool bullet = isBullet( static_cast<Style>(m_style) ); 00445 00446 if ( bullet && (Numbering)m_numbering == NUM_CHAPTER ) { 00447 // Shome mishtake surely! (not sure how it can happen though) 00448 m_style = STYLE_NUM; 00449 bullet = false; 00450 } 00451 00452 QString text; 00453 if ( !bullet ) 00454 { 00455 // Ensure paragraph number is valid. 00456 number( paragraph ); 00457 00458 switch ( m_style ) 00459 { 00460 case STYLE_NONE: 00461 if ( (Numbering)m_numbering == NUM_LIST ) 00462 text = ' '; 00463 break; 00464 case STYLE_NUM: 00465 text.setNum( m_cache.number ); 00466 break; 00467 case STYLE_ALPHAB_L: 00468 text = makeAlphaLowerNumber( m_cache.number ); 00469 break; 00470 case STYLE_ALPHAB_U: 00471 text = makeAlphaUpperNumber( m_cache.number ); 00472 break; 00473 case STYLE_ROM_NUM_L: 00474 text = makeRomanNumber( m_cache.number ).lower(); 00475 break; 00476 case STYLE_ROM_NUM_U: 00477 text = makeRomanNumber( m_cache.number ).upper(); 00478 break; 00479 case STYLE_CUSTOM: 00480 default: // shut up compiler 00482 text.setNum( m_cache.number ); 00483 break; 00484 } 00485 } 00486 else 00487 { 00488 switch ( m_style ) 00489 { 00490 // --- these are used in export filters but are ignored by KoTextParag::drawLabel (for bulleted lists - which they are :)) --- 00491 case KoParagCounter::STYLE_DISCBULLET: 00492 text = '*'; 00493 break; 00494 case KoParagCounter::STYLE_SQUAREBULLET: 00495 text = '#'; 00496 break; 00497 case KoParagCounter::STYLE_BOXBULLET: 00498 text = '='; // think up a better character 00499 break; 00500 case KoParagCounter::STYLE_CIRCLEBULLET: 00501 text = 'o'; 00502 break; 00503 case KoParagCounter::STYLE_CUSTOMBULLET: 00504 text = m_customBulletChar; 00505 break; 00506 default: // shut up compiler 00507 break; 00508 } 00509 } 00510 return text; 00511 } 00512 00513 // Return the full text to be displayed 00514 QString KoParagCounter::text( const KoTextParag *paragraph ) 00515 { 00516 // Return cached value if possible. 00517 if ( !m_cache.text.isNull() ) 00518 return m_cache.text; 00519 00520 // If necessary, grab the text of the preceding levels. 00521 if ( m_displayLevels > 1 ) 00522 { 00523 KoTextParag* p = parent( paragraph ); 00524 int displayLevels = QMIN( m_displayLevels, m_depth+1 ); // can't be >depth+1 00525 for ( int level = 1 ; level < displayLevels ; ++level ) { 00526 //kdDebug() << "additional level=" << level << "/" << displayLevels-1 << endl; 00527 if ( p ) 00528 { 00529 KoParagCounter* counter = p->counter(); 00530 QString str = counter->levelText( p ); 00531 // If the preceding level is a bullet, replace it with blanks. 00532 if ( counter->isBullet() ) 00533 for ( unsigned i = 0; i < str.length(); i++ ) 00534 str[i] = ' '; 00535 00536 str.append('.'); // hardcoded on purpose (like OO) until anyone complains 00537 00538 // Find the number of missing parents, and add dummy text for them. 00539 int missingParents = m_depth - level - p->counter()->m_depth; 00540 //kdDebug() << "levelText = " << str << " missingParents=" << missingParents << endl; 00541 level += missingParents; 00542 for ( ; missingParents > 0 ; --missingParents ) 00543 // Each missing level adds a "0" 00544 str.append( "0." ); 00545 00546 m_cache.text.prepend( str ); 00547 // Prepare next iteration 00548 if ( level < displayLevels ) // no need to calc it if we won't use it 00549 p = counter->parent( p ); 00550 } 00551 else // toplevel parents are missing 00552 { 00553 // Special case for one-paragraph-documents like preview widgets 00554 KoTextDocument* textdoc = paragraph->textDocument(); 00555 if ( paragraph == textdoc->firstParag() && paragraph == textdoc->lastParag() ) 00556 m_cache.text.prepend( "1." ); 00557 else 00558 m_cache.text.prepend( "0." ); 00559 } 00560 } 00561 00562 } 00563 00564 //kdDebug() << "result: " << m_cache.text << " + " << levelText( paragraph ) << endl; 00565 // Now add text for this level. 00566 m_cache.text.append( levelText( paragraph ) ); 00567 00568 // Now apply prefix and suffix 00569 // We want the '.' to be before the number in a RTL parag, 00570 // but we can't paint the whole string using QPainter::RTL direction, otherwise 00571 // '10' becomes '01'. 00572 m_cache.text.prepend( paragraph->string()->isRightToLeft() ? suffix() : prefix() ); 00573 m_cache.text.append( paragraph->string()->isRightToLeft() ? prefix() : suffix() ); 00574 return m_cache.text; 00575 } 00576 00577 int KoParagCounter::width( const KoTextParag *paragraph ) 00578 { 00579 // Return cached value if possible. 00580 if ( m_cache.width != -1 && counterFormat( paragraph ) == m_cache.counterFormat ) 00581 return m_cache.width; 00582 00583 // Ensure paragraph text is valid. 00584 if ( m_cache.text.isNull() ) 00585 text( paragraph ); 00586 00587 // Now calculate width. 00588 if ( m_cache.counterFormat ) 00589 m_cache.counterFormat->removeRef(); 00590 m_cache.counterFormat = counterFormat( paragraph ); 00591 m_cache.counterFormat->addRef(); 00592 m_cache.width = 0; 00593 QString text = m_cache.text; 00594 if ( style() ==KoParagCounter::STYLE_CUSTOMBULLET && !text.isEmpty()) 00595 { 00596 text.append( " " ); // append a trailing space, see KoTextParag::drawLabel 00597 } 00598 else if ( !text.isEmpty() ) 00599 text.append( ' ' ); // append a trailing space, see KoTextParag::drawLabel 00600 QFontMetrics fm = m_cache.counterFormat->refFontMetrics(); 00601 for ( unsigned int i = 0; i < text.length(); i++ ) 00602 //m_cache.width += m_cache.counterFormat->width( text, i ); 00603 m_cache.width += fm.width( text[i] ); 00604 // Now go from 100%-zoom to LU 00605 m_cache.width = KoTextZoomHandler::ptToLayoutUnitPt( m_cache.width ); 00606 00607 //kdDebug(32500) << "KoParagCounter::width recalculated parag=" << paragraph << " text='" << text << "' width=" << m_cache.width << endl; 00608 return m_cache.width; 00609 } 00610 00611 int KoParagCounter::bulletX() 00612 { 00613 // width() must have been called first 00614 Q_ASSERT( m_cache.width != -1 ); 00615 Q_ASSERT( m_cache.counterFormat ); 00616 int x = 0; 00617 QFontMetrics fm = m_cache.counterFormat->refFontMetrics(); 00618 QString text = prefix(); 00619 for ( unsigned int i = 0; i < text.length(); i++ ) 00620 x += fm.width( text[i] ); 00621 // Now go from 100%-zoom to LU 00622 return KoTextZoomHandler::ptToLayoutUnitPt( x ); 00623 } 00624 00625 // Only exists to centralize code. Does no caching. 00626 KoTextFormat* KoParagCounter::counterFormat( const KoTextParag *paragraph ) 00627 { 00628 KoTextFormat* refFormat = paragraph->at( 0 )->format(); 00629 KoTextFormat format( *refFormat ); 00630 format.setVAlign( KoTextFormat::AlignNormal ); 00631 return paragraph->textDocument()->formatCollection()->format( &format ); 00632 /*paragraph->paragFormat()*/ 00633 } 00634 00636 00637 const QCString RNUnits[] = {"", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix"}; 00638 const QCString RNTens[] = {"", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"}; 00639 const QCString RNHundreds[] = {"", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"}; 00640 const QCString RNThousands[] = {"", "m", "mm", "mmm"}; 00641 00642 QString KoParagCounter::makeRomanNumber( int n ) 00643 { 00644 return QString::fromLatin1( RNThousands[ ( n / 1000 ) ] + 00645 RNHundreds[ ( n / 100 ) % 10 ] + 00646 RNTens[ ( n / 10 ) % 10 ] + 00647 RNUnits[ ( n ) % 10 ] ); 00648 } 00649 00650 QString KoParagCounter::makeAlphaUpperNumber( int n ) 00651 { 00652 QString tmp; 00653 char bottomDigit; 00654 while ( n > 26 ) 00655 { 00656 bottomDigit = (n-1) % 26; 00657 n = (n-1) / 26; 00658 tmp.prepend( QChar( 'A' + bottomDigit ) ); 00659 } 00660 tmp.prepend( QChar( 'A' + n -1 ) ); 00661 return tmp; 00662 } 00663 00664 QString KoParagCounter::makeAlphaLowerNumber( int n ) 00665 { 00666 QString tmp; 00667 char bottomDigit; 00668 while ( n > 26 ) 00669 { 00670 bottomDigit = (n-1) % 26; 00671 n = (n-1) / 26; 00672 tmp.prepend( QChar( 'a' + bottomDigit ) ); 00673 } 00674 tmp.prepend( QChar( 'a' + n - 1 ) ); 00675 return tmp; 00676 } 00677 00678 int KoParagCounter::fromRomanNumber( const QString &string ) 00679 { 00680 int ret = 0; 00681 int stringStart = 0; 00682 const int stringLen = string.length(); 00683 00684 for (int base = 1000; base >= 1 && stringStart < stringLen; base /= 10) 00685 { 00686 const QCString *rn; 00687 int rnNum; 00688 switch (base) 00689 { 00690 case 1000: 00691 rn = RNThousands; 00692 rnNum = sizeof (RNThousands) / sizeof (const QCString); 00693 break; 00694 case 100: 00695 rn = RNHundreds; 00696 rnNum = sizeof (RNHundreds) / sizeof (const QCString); 00697 break; 00698 case 10: 00699 rn = RNTens; 00700 rnNum = sizeof (RNTens) / sizeof (const QCString); 00701 break; 00702 case 1: 00703 default: 00704 rn = RNUnits; 00705 rnNum = sizeof (RNUnits) / sizeof (const QCString); 00706 break; 00707 } 00708 00709 // I _think_ this will work :) - Clarence 00710 for (int i = rnNum - 1; i >= 1; i--) 00711 { 00712 const int rnLength = rn[i].length(); 00713 if (string.mid(stringStart,rnLength) == (const char*)rn[i]) 00714 { 00715 ret += i * base; 00716 stringStart += rnLength; 00717 break; 00718 } 00719 } 00720 } 00721 00722 return (ret == 0 || stringStart != stringLen) ? -1 /*invalid value*/ : ret; 00723 } 00724 00725 int KoParagCounter::fromAlphaUpperNumber( const QString &string ) 00726 { 00727 int ret = 0; 00728 00729 const int len = string.length(); 00730 for (int i = 0; i < len; i++) 00731 { 00732 const int add = char(string[i]) - 'A' + 1; 00733 00734 if (add >= 1 && add <= 26) // _not_ < 26 00735 ret = ret * 26 + add; 00736 else 00737 { 00738 ret = -1; // invalid character 00739 break; 00740 } 00741 } 00742 00743 return (ret == 0) ? -1 /*invalid value*/ : ret; 00744 } 00745 00746 int KoParagCounter::fromAlphaLowerNumber( const QString &string ) 00747 { 00748 int ret = 0; 00749 00750 const int len = string.length(); 00751 for (int i = 0; i < len; i++) 00752 { 00753 const int add = char(string[i]) - 'a' + 1; 00754 00755 if (add >= 1 && add <= 26) // _not_ < 26 00756 ret = ret * 26 + add; 00757 else 00758 { 00759 ret = -1; // invalid character 00760 break; 00761 } 00762 } 00763 00764 return (ret == 0) ? -1 /*invalid value*/ : ret; 00765 }
KDE Logo
This file is part of the documentation for lib Library Version 1.3.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Sep 24 18:22:24 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003