1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include <precomp.h> 29 #include <toolkit/out_position.hxx> 30 31 32 // NOT FULLY DEFINED SERVICES 33 34 35 36 namespace output 37 { 38 39 40 41 namespace 42 { 43 44 const int C_nAssumedMaxLinkLength = 500; 45 46 void move_ToParent( 47 Node * & io_node, 48 intt i_levels = 1 ); 49 50 void 51 move_ToParent( Node * & io_node, 52 intt i_levels ) 53 { 54 for ( intt n = 0; n < i_levels; ++n ) 55 { 56 csv_assert(io_node != 0); 57 io_node = io_node->Parent(); 58 } 59 } 60 61 62 63 } // namepace anonymous 64 65 66 67 Position::Position() 68 : sFile(), 69 pDirectory(&Node::Null_()) 70 { 71 } 72 73 74 Position::Position( Node & i_directory, 75 const String & i_file ) 76 : sFile(i_file), 77 pDirectory(&i_directory) 78 { 79 } 80 81 Position::Position( const Position & i_directory, 82 const String & i_sDifferentFile ) 83 : sFile(i_sDifferentFile), 84 pDirectory(i_directory.pDirectory) 85 { 86 } 87 88 89 Position::~Position() 90 { 91 } 92 93 94 Position & 95 Position::operator=( Node & i_node ) 96 { 97 pDirectory = &i_node; 98 sFile.clear(); 99 return *this; 100 } 101 102 Position & 103 Position::operator+=( const String & i_nodeName ) 104 { 105 csv_assert(pDirectory != 0); 106 107 pDirectory = &pDirectory->Provide_Child(i_nodeName); 108 sFile.clear(); 109 110 return *this; 111 } 112 113 Position & 114 Position::operator-=( intt i_levels ) 115 { 116 csv_assert(pDirectory != 0); 117 118 for ( intt i = i_levels; i > 0; --i ) 119 { 120 pDirectory = pDirectory->Parent(); 121 if (pDirectory == 0) 122 { 123 pDirectory = &Node::Null_(); 124 i = 0; 125 } 126 } 127 sFile.clear(); 128 129 return *this; 130 } 131 132 String 133 Position::LinkToRoot( const String & ) const 134 { 135 StreamLock sl(C_nAssumedMaxLinkLength); 136 return sl() << get_UpLink(Depth()) << c_str; 137 } 138 139 void 140 Position::Get_LinkTo( StreamStr & o_result, 141 const Position & i_destination, 142 const String & i_localLabel ) const 143 { 144 Node * p1 = pDirectory; 145 Node * p2 = i_destination.pDirectory; 146 147 intt diff = Depth() - i_destination.Depth(); 148 intt pathLength1 = 0; 149 intt pathLength2 = 0; 150 151 if ( diff > 0 ) 152 { 153 pathLength1 = diff; 154 move_ToParent(p1,pathLength1); 155 } 156 else if ( diff < 0 ) 157 { 158 pathLength2 = -diff; 159 move_ToParent(p2,pathLength2); 160 } 161 162 while ( p1 != p2 ) 163 { 164 move_ToParent(p1); 165 move_ToParent(p2); 166 ++pathLength1; 167 ++pathLength2; 168 } 169 170 o_result << get_UpLink(pathLength1); 171 i_destination.pDirectory->Get_Path(o_result, pathLength2); 172 o_result << i_destination.sFile; 173 if (i_localLabel.length()) 174 o_result << "#" << i_localLabel; 175 } 176 177 void 178 Position::Get_LinkToRoot( StreamStr & o_result, 179 const String & ) const 180 { 181 o_result << get_UpLink(Depth()); 182 } 183 184 void 185 Position::Set( Node & i_node, 186 const String & i_file ) 187 { 188 sFile = i_file; 189 pDirectory = &i_node; 190 } 191 192 193 194 195 const char * 196 get_UpLink(uintt i_depth) 197 { 198 static const uintt 199 C_nMaxDepth = 30; 200 static const char 201 C_sUpLinkArray[3*C_nMaxDepth+1] = 202 "../../../../../../../../../../" 203 "../../../../../../../../../../" 204 "../../../../../../../../../../"; 205 static const char * 206 C_sUpLink = &C_sUpLinkArray[0]; 207 208 if ( i_depth <= C_nMaxDepth ) 209 { 210 return C_sUpLink + 3*(C_nMaxDepth - i_depth); 211 } 212 else 213 { // not THREAD fast 214 static std::vector<char> 215 aRet; 216 uintt nNeededSize = i_depth * 3 + 1; 217 218 if (aRet.size() < nNeededSize) 219 { 220 aRet.resize(nNeededSize); 221 char * pEnd = &aRet[nNeededSize-1]; 222 *pEnd = '\0'; 223 224 for ( char * pFill = &(*aRet.begin()); 225 pFill != pEnd; 226 pFill += 3 ) 227 { 228 memcpy(pFill, C_sUpLink, 3); 229 } 230 } // end if 231 232 return &aRet[aRet.size() - 1 - 3*i_depth]; 233 } 234 } 235 236 237 238 239 } // namespace output 240