summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/modplug/sndfile.cpp5
-rw-r--r--core/multimedia/opieplayer/vorbis/tremor/block.c6
-rw-r--r--core/multimedia/opieplayer/vorbis/tremor/info.c2
-rw-r--r--noncore/apps/opie-write/qrichtext.cpp69
-rw-r--r--noncore/settings/networksettings2/opietooth2/OTSDPAttribute.cpp3
-rw-r--r--noncore/settings/packagemanager/oipkgconfigdlg.cpp6
6 files changed, 62 insertions, 29 deletions
diff --git a/core/multimedia/opieplayer/modplug/sndfile.cpp b/core/multimedia/opieplayer/modplug/sndfile.cpp
index 1d0d610..799555c 100644
--- a/core/multimedia/opieplayer/modplug/sndfile.cpp
+++ b/core/multimedia/opieplayer/modplug/sndfile.cpp
@@ -1,1875 +1,1878 @@
1/* 1/*
2 * This program is free software; you can redistribute it and modify it 2 * This program is free software; you can redistribute it and modify it
3 * under the terms of the GNU General Public License as published by the 3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation; either version 2 of the license or (at your 4 * Free Software Foundation; either version 2 of the license or (at your
5 * option) any later version. 5 * option) any later version.
6 * 6 *
7 * Authors: Olivier Lapicque <olivierl@jps.net>, 7 * Authors: Olivier Lapicque <olivierl@jps.net>,
8 * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) 8 * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
9*/ 9*/
10 10
11#include <math.h> //for GCCFIX 11#include <math.h> //for GCCFIX
12#include "stdafx.h" 12#include "stdafx.h"
13#include "sndfile.h" 13#include "sndfile.h"
14 14
15#define MMCMP_SUPPORT 15#define MMCMP_SUPPORT
16 16
17#ifdef MMCMP_SUPPORT 17#ifdef MMCMP_SUPPORT
18extern BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength); 18extern BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength);
19#endif 19#endif
20 20
21// External decompressors 21// External decompressors
22extern void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter); 22extern void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter);
23extern WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n); 23extern WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n);
24extern int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen); 24extern int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen);
25extern DWORD ITReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n); 25extern DWORD ITReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n);
26extern void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215); 26extern void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215);
27extern void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215); 27extern void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215);
28 28
29 29
30 #define MAX_PACK_TABLES 3 30 #define MAX_PACK_TABLES 3
31 31
32 32
33// Compression table 33// Compression table
34static const signed char UnpackTable[MAX_PACK_TABLES][16] = 34static const signed char UnpackTable[MAX_PACK_TABLES][16] =
35//-------------------------------------------- 35//--------------------------------------------
36{ 36{
37 // CPU-generated dynamic table 37 // CPU-generated dynamic table
38 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 38 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
39 // u-Law table 39 // u-Law table
40 {0, 1, 2, 4, 8, 16, 32, 64, 40 {0, 1, 2, 4, 8, 16, 32, 64,
41 -1, -2, -4, -8, -16, -32, -48, -64}, 41 -1, -2, -4, -8, -16, -32, -48, -64},
42 // Linear table 42 // Linear table
43 {0, 1, 2, 3, 5, 7, 12, 19, 43 {0, 1, 2, 3, 5, 7, 12, 19,
44 -1, -2, -3, -5, -7, -12, -19, -31} 44 -1, -2, -3, -5, -7, -12, -19, -31}
45}; 45};
46 46
47 47
48////////////////////////////////////////////////////////// 48//////////////////////////////////////////////////////////
49// CSoundFile 49// CSoundFile
50 50
51CSoundFile::CSoundFile() 51CSoundFile::CSoundFile()
52//---------------------- 52//----------------------
53{ 53{
54 m_nType = MOD_TYPE_NONE; 54 m_nType = MOD_TYPE_NONE;
55 m_dwSongFlags = 0; 55 m_dwSongFlags = 0;
56 m_nChannels = 0; 56 m_nChannels = 0;
57 m_nMixChannels = 0; 57 m_nMixChannels = 0;
58 m_nSamples = 0; 58 m_nSamples = 0;
59 m_nInstruments = 0; 59 m_nInstruments = 0;
60 m_nPatternNames = 0; 60 m_nPatternNames = 0;
61 m_lpszPatternNames = NULL; 61 m_lpszPatternNames = NULL;
62 m_lpszSongComments = NULL; 62 m_lpszSongComments = NULL;
63 m_nFreqFactor = m_nTempoFactor = 128; 63 m_nFreqFactor = m_nTempoFactor = 128;
64 m_nMasterVolume = 128; 64 m_nMasterVolume = 128;
65 m_nMinPeriod = 0x20; 65 m_nMinPeriod = 0x20;
66 m_nMaxPeriod = 0x7FFF; 66 m_nMaxPeriod = 0x7FFF;
67 m_nRepeatCount = 0; 67 m_nRepeatCount = 0;
68 memset(Chn, 0, sizeof(Chn)); 68 memset(Chn, 0, sizeof(Chn));
69 memset(ChnMix, 0, sizeof(ChnMix)); 69 memset(ChnMix, 0, sizeof(ChnMix));
70 memset(Ins, 0, sizeof(Ins)); 70 memset(Ins, 0, sizeof(Ins));
71 memset(ChnSettings, 0, sizeof(ChnSettings)); 71 memset(ChnSettings, 0, sizeof(ChnSettings));
72 memset(Headers, 0, sizeof(Headers)); 72 memset(Headers, 0, sizeof(Headers));
73 memset(Order, 0xFF, sizeof(Order)); 73 memset(Order, 0xFF, sizeof(Order));
74 memset(Patterns, 0, sizeof(Patterns)); 74 memset(Patterns, 0, sizeof(Patterns));
75 memset(m_szNames, 0, sizeof(m_szNames)); 75 memset(m_szNames, 0, sizeof(m_szNames));
76 memset(m_MixPlugins, 0, sizeof(m_MixPlugins)); 76 memset(m_MixPlugins, 0, sizeof(m_MixPlugins));
77} 77}
78 78
79 79
80CSoundFile::~CSoundFile() 80CSoundFile::~CSoundFile()
81//----------------------- 81//-----------------------
82 { 82 {
83 Destroy(); 83 Destroy();
84} 84}
85 85
86 86
87BOOL CSoundFile::Create(LPCBYTE lpStream, DWORD dwMemLength) 87BOOL CSoundFile::Create(LPCBYTE lpStream, DWORD dwMemLength)
88//---------------------------------------------------------- 88//----------------------------------------------------------
89{ 89{
90 int i; 90 int i;
91 91
92 m_nType = MOD_TYPE_NONE; 92 m_nType = MOD_TYPE_NONE;
93 m_dwSongFlags = 0; 93 m_dwSongFlags = 0;
94 m_nChannels = 0; 94 m_nChannels = 0;
95 m_nMixChannels = 0; 95 m_nMixChannels = 0;
96 m_nSamples = 0; 96 m_nSamples = 0;
97 m_nInstruments = 0; 97 m_nInstruments = 0;
98 m_nFreqFactor = m_nTempoFactor = 128; 98 m_nFreqFactor = m_nTempoFactor = 128;
99 m_nMasterVolume = 128; 99 m_nMasterVolume = 128;
100 m_nDefaultGlobalVolume = 256; 100 m_nDefaultGlobalVolume = 256;
101 m_nGlobalVolume = 256; 101 m_nGlobalVolume = 256;
102 m_nOldGlbVolSlide = 0; 102 m_nOldGlbVolSlide = 0;
103 m_nDefaultSpeed = 6; 103 m_nDefaultSpeed = 6;
104 m_nDefaultTempo = 125; 104 m_nDefaultTempo = 125;
105 m_nPatternDelay = 0; 105 m_nPatternDelay = 0;
106 m_nFrameDelay = 0; 106 m_nFrameDelay = 0;
107 m_nNextRow = 0; 107 m_nNextRow = 0;
108 m_nRow = 0; 108 m_nRow = 0;
109 m_nPattern = 0; 109 m_nPattern = 0;
110 m_nCurrentPattern = 0; 110 m_nCurrentPattern = 0;
111 m_nNextPattern = 0; 111 m_nNextPattern = 0;
112 m_nRestartPos = 0; 112 m_nRestartPos = 0;
113 m_nMinPeriod = 16; 113 m_nMinPeriod = 16;
114 m_nMaxPeriod = 32767; 114 m_nMaxPeriod = 32767;
115 m_nSongPreAmp = 0x30; 115 m_nSongPreAmp = 0x30;
116 m_nPatternNames = 0; 116 m_nPatternNames = 0;
117 m_nMaxOrderPosition = 0; 117 m_nMaxOrderPosition = 0;
118 m_lpszPatternNames = NULL; 118 m_lpszPatternNames = NULL;
119 m_lpszSongComments = NULL; 119 m_lpszSongComments = NULL;
120 memset(Ins, 0, sizeof(Ins)); 120 memset(Ins, 0, sizeof(Ins));
121 memset(ChnMix, 0, sizeof(ChnMix)); 121 memset(ChnMix, 0, sizeof(ChnMix));
122 memset(Chn, 0, sizeof(Chn)); 122 memset(Chn, 0, sizeof(Chn));
123 memset(Headers, 0, sizeof(Headers)); 123 memset(Headers, 0, sizeof(Headers));
124 memset(Order, 0xFF, sizeof(Order)); 124 memset(Order, 0xFF, sizeof(Order));
125 memset(Patterns, 0, sizeof(Patterns)); 125 memset(Patterns, 0, sizeof(Patterns));
126 memset(m_szNames, 0, sizeof(m_szNames)); 126 memset(m_szNames, 0, sizeof(m_szNames));
127 memset(m_MixPlugins, 0, sizeof(m_MixPlugins)); 127 memset(m_MixPlugins, 0, sizeof(m_MixPlugins));
128 ResetMidiCfg(); 128 ResetMidiCfg();
129 for (UINT npt=0; npt<MAX_PATTERNS; npt++) PatternSize[npt] = 64; 129 for (UINT npt=0; npt<MAX_PATTERNS; npt++) PatternSize[npt] = 64;
130 for (UINT nch=0; nch<MAX_BASECHANNELS; nch++) 130 for (UINT nch=0; nch<MAX_BASECHANNELS; nch++)
131 { 131 {
132 ChnSettings[nch].nPan = 128; 132 ChnSettings[nch].nPan = 128;
133 ChnSettings[nch].nVolume = 64; 133 ChnSettings[nch].nVolume = 64;
134 ChnSettings[nch].dwFlags = 0; 134 ChnSettings[nch].dwFlags = 0;
135 ChnSettings[nch].szName[0] = 0; 135 ChnSettings[nch].szName[0] = 0;
136 } 136 }
137 if (lpStream) 137 if (lpStream)
138 { 138 {
139#ifdef MMCMP_SUPPORT 139#ifdef MMCMP_SUPPORT
140 BOOL bMMCmp = MMCMP_Unpack(&lpStream, &dwMemLength); 140 BOOL bMMCmp = MMCMP_Unpack(&lpStream, &dwMemLength);
141#endif 141#endif
142 if ((!ReadXM(lpStream, dwMemLength)) 142 if ((!ReadXM(lpStream, dwMemLength))
143 && (!ReadIT(lpStream, dwMemLength)) 143 && (!ReadIT(lpStream, dwMemLength))
144 && (!ReadS3M(lpStream, dwMemLength)) 144 && (!ReadS3M(lpStream, dwMemLength))
145 // && (!ReadWav(lpStream, dwMemLength)) 145 // && (!ReadWav(lpStream, dwMemLength))
146#ifndef MODPLUG_BASIC_SUPPORT 146#ifndef MODPLUG_BASIC_SUPPORT
147 && (!ReadSTM(lpStream, dwMemLength)) 147 && (!ReadSTM(lpStream, dwMemLength))
148 && (!ReadMed(lpStream, dwMemLength)) 148 && (!ReadMed(lpStream, dwMemLength))
149 && (!ReadMTM(lpStream, dwMemLength)) 149 && (!ReadMTM(lpStream, dwMemLength))
150 && (!ReadMDL(lpStream, dwMemLength)) 150 && (!ReadMDL(lpStream, dwMemLength))
151 && (!ReadDBM(lpStream, dwMemLength)) 151 && (!ReadDBM(lpStream, dwMemLength))
152 && (!Read669(lpStream, dwMemLength)) 152 && (!Read669(lpStream, dwMemLength))
153 && (!ReadFAR(lpStream, dwMemLength)) 153 && (!ReadFAR(lpStream, dwMemLength))
154 && (!ReadAMS(lpStream, dwMemLength)) 154 && (!ReadAMS(lpStream, dwMemLength))
155 && (!ReadOKT(lpStream, dwMemLength)) 155 && (!ReadOKT(lpStream, dwMemLength))
156 && (!ReadPTM(lpStream, dwMemLength)) 156 && (!ReadPTM(lpStream, dwMemLength))
157 && (!ReadUlt(lpStream, dwMemLength)) 157 && (!ReadUlt(lpStream, dwMemLength))
158 && (!ReadDMF(lpStream, dwMemLength)) 158 && (!ReadDMF(lpStream, dwMemLength))
159 && (!ReadDSM(lpStream, dwMemLength)) 159 && (!ReadDSM(lpStream, dwMemLength))
160 && (!ReadUMX(lpStream, dwMemLength)) 160 && (!ReadUMX(lpStream, dwMemLength))
161 && (!ReadAMF(lpStream, dwMemLength)) 161 && (!ReadAMF(lpStream, dwMemLength))
162 && (!ReadPSM(lpStream, dwMemLength)) 162 && (!ReadPSM(lpStream, dwMemLength))
163 && (!ReadMT2(lpStream, dwMemLength)) 163 && (!ReadMT2(lpStream, dwMemLength))
164#endif // MODPLUG_BASIC_SUPPORT 164#endif // MODPLUG_BASIC_SUPPORT
165 && (!ReadMod(lpStream, dwMemLength))) m_nType = MOD_TYPE_NONE; 165 && (!ReadMod(lpStream, dwMemLength))) m_nType = MOD_TYPE_NONE;
166#ifdef MMCMP_SUPPORT 166#ifdef MMCMP_SUPPORT
167 if (bMMCmp) 167 if (bMMCmp)
168 { 168 {
169 GlobalFreePtr(lpStream); 169 GlobalFreePtr(lpStream);
170 lpStream = NULL; 170 lpStream = NULL;
171 } 171 }
172#endif 172#endif
173 } 173 }
174 // Adjust song names 174 // Adjust song names
175 for (i=0; i<MAX_SAMPLES; i++) 175 for (i=0; i<MAX_SAMPLES; i++)
176 { 176 {
177 LPSTR p = m_szNames[i]; 177 LPSTR p = m_szNames[i];
178 int j = 31; 178 int j = 31;
179 p[j] = 0; 179 p[j] = 0;
180 while ((j>=0) && (p[j]<=' ')) p[j--] = 0; 180 while ((j>=0) && (p[j]<=' ')) p[j--] = 0;
181 while (j>=0) 181 while (j>=0)
182 { 182 {
183 if (((BYTE)p[j]) < ' ') p[j] = ' '; 183 if (((BYTE)p[j]) < ' ') p[j] = ' ';
184 j--; 184 j--;
185 } 185 }
186 } 186 }
187 // Adjust channels 187 // Adjust channels
188 for (i=0; i<MAX_BASECHANNELS; i++) 188 for (i=0; i<MAX_BASECHANNELS; i++)
189 { 189 {
190 if (ChnSettings[i].nVolume > 64) ChnSettings[i].nVolume = 64; 190 if (ChnSettings[i].nVolume > 64) ChnSettings[i].nVolume = 64;
191 if (ChnSettings[i].nPan > 256) ChnSettings[i].nPan = 128; 191 if (ChnSettings[i].nPan > 256) ChnSettings[i].nPan = 128;
192 Chn[i].nPan = ChnSettings[i].nPan; 192 Chn[i].nPan = ChnSettings[i].nPan;
193 Chn[i].nGlobalVol = ChnSettings[i].nVolume; 193 Chn[i].nGlobalVol = ChnSettings[i].nVolume;
194 Chn[i].dwFlags = ChnSettings[i].dwFlags; 194 Chn[i].dwFlags = ChnSettings[i].dwFlags;
195 Chn[i].nVolume = 256; 195 Chn[i].nVolume = 256;
196 Chn[i].nCutOff = 0x7F; 196 Chn[i].nCutOff = 0x7F;
197 } 197 }
198 // Checking instruments 198 // Checking instruments
199 MODINSTRUMENT *pins = Ins; 199 MODINSTRUMENT *pins = Ins;
200 200
201 for (i=0; i<MAX_INSTRUMENTS; i++, pins++) 201 for (i=0; i<MAX_INSTRUMENTS; i++, pins++)
202 { 202 {
203 if (pins->pSample) 203 if (pins->pSample)
204 { 204 {
205 if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength; 205 if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength;
206 if (pins->nLoopStart + 3 >= pins->nLoopEnd) 206 if (pins->nLoopStart + 3 >= pins->nLoopEnd)
207 { 207 {
208 pins->nLoopStart = 0; 208 pins->nLoopStart = 0;
209 pins->nLoopEnd = 0; 209 pins->nLoopEnd = 0;
210 } 210 }
211 if (pins->nSustainEnd > pins->nLength) pins->nSustainEnd = pins->nLength; 211 if (pins->nSustainEnd > pins->nLength) pins->nSustainEnd = pins->nLength;
212 if (pins->nSustainStart + 3 >= pins->nSustainEnd) 212 if (pins->nSustainStart + 3 >= pins->nSustainEnd)
213 { 213 {
214 pins->nSustainStart = 0; 214 pins->nSustainStart = 0;
215 pins->nSustainEnd = 0; 215 pins->nSustainEnd = 0;
216 } 216 }
217 } else 217 } else
218 { 218 {
219 pins->nLength = 0; 219 pins->nLength = 0;
220 pins->nLoopStart = 0; 220 pins->nLoopStart = 0;
221 pins->nLoopEnd = 0; 221 pins->nLoopEnd = 0;
222 pins->nSustainStart = 0; 222 pins->nSustainStart = 0;
223 pins->nSustainEnd = 0; 223 pins->nSustainEnd = 0;
224 } 224 }
225 if (!pins->nLoopEnd) pins->uFlags &= ~CHN_LOOP; 225 if (!pins->nLoopEnd) pins->uFlags &= ~CHN_LOOP;
226 if (!pins->nSustainEnd) pins->uFlags &= ~CHN_SUSTAINLOOP; 226 if (!pins->nSustainEnd) pins->uFlags &= ~CHN_SUSTAINLOOP;
227 if (pins->nGlobalVol > 64) pins->nGlobalVol = 64; 227 if (pins->nGlobalVol > 64) pins->nGlobalVol = 64;
228 } 228 }
229 // Check invalid instruments 229 // Check invalid instruments
230 while ((m_nInstruments > 0) && (!Headers[m_nInstruments])) m_nInstruments--; 230 while ((m_nInstruments > 0) && (!Headers[m_nInstruments])) m_nInstruments--;
231 // Set default values 231 // Set default values
232 if (m_nSongPreAmp < 0x20) m_nSongPreAmp = 0x20; 232 if (m_nSongPreAmp < 0x20) m_nSongPreAmp = 0x20;
233 if (m_nDefaultTempo < 32) m_nDefaultTempo = 125; 233 if (m_nDefaultTempo < 32) m_nDefaultTempo = 125;
234 if (!m_nDefaultSpeed) m_nDefaultSpeed = 6; 234 if (!m_nDefaultSpeed) m_nDefaultSpeed = 6;
235 m_nMusicSpeed = m_nDefaultSpeed; 235 m_nMusicSpeed = m_nDefaultSpeed;
236 m_nMusicTempo = m_nDefaultTempo; 236 m_nMusicTempo = m_nDefaultTempo;
237 m_nGlobalVolume = m_nDefaultGlobalVolume; 237 m_nGlobalVolume = m_nDefaultGlobalVolume;
238 m_nNextPattern = 0; 238 m_nNextPattern = 0;
239 m_nCurrentPattern = 0; 239 m_nCurrentPattern = 0;
240 m_nPattern = 0; 240 m_nPattern = 0;
241 m_nBufferCount = 0; 241 m_nBufferCount = 0;
242 m_nTickCount = m_nMusicSpeed; 242 m_nTickCount = m_nMusicSpeed;
243 m_nNextRow = 0; 243 m_nNextRow = 0;
244 m_nRow = 0; 244 m_nRow = 0;
245 if ((m_nRestartPos >= MAX_ORDERS) || (Order[m_nRestartPos] >= MAX_PATTERNS)) m_nRestartPos = 0; 245 if ((m_nRestartPos >= MAX_ORDERS) || (Order[m_nRestartPos] >= MAX_PATTERNS)) m_nRestartPos = 0;
246 // Load plugins 246 // Load plugins
247 if (gpMixPluginCreateProc) 247 if (gpMixPluginCreateProc)
248 { 248 {
249 for (UINT iPlug=0; iPlug<MAX_MIXPLUGINS; iPlug++) 249 for (UINT iPlug=0; iPlug<MAX_MIXPLUGINS; iPlug++)
250 { 250 {
251 if ((m_MixPlugins[iPlug].Info.dwPluginId1) 251 if ((m_MixPlugins[iPlug].Info.dwPluginId1)
252 || (m_MixPlugins[iPlug].Info.dwPluginId2)) 252 || (m_MixPlugins[iPlug].Info.dwPluginId2))
253 { 253 {
254 gpMixPluginCreateProc(&m_MixPlugins[iPlug]); 254 gpMixPluginCreateProc(&m_MixPlugins[iPlug]);
255 if (m_MixPlugins[iPlug].pMixPlugin) 255 if (m_MixPlugins[iPlug].pMixPlugin)
256 { 256 {
257 m_MixPlugins[iPlug].pMixPlugin->RestoreAllParameters(); 257 m_MixPlugins[iPlug].pMixPlugin->RestoreAllParameters();
258 } 258 }
259 } 259 }
260 } 260 }
261 } 261 }
262 if (m_nType) 262 if (m_nType)
263 { 263 {
264 UINT maxpreamp = 0x10+(m_nChannels*8); 264 UINT maxpreamp = 0x10+(m_nChannels*8);
265 if (maxpreamp > 100) maxpreamp = 100; 265 if (maxpreamp > 100) maxpreamp = 100;
266 if (m_nSongPreAmp > maxpreamp) m_nSongPreAmp = maxpreamp; 266 if (m_nSongPreAmp > maxpreamp) m_nSongPreAmp = maxpreamp;
267 return TRUE; 267 return TRUE;
268 } 268 }
269 return FALSE; 269 return FALSE;
270} 270}
271 271
272 272
273BOOL CSoundFile::Destroy() 273BOOL CSoundFile::Destroy()
274 274
275//------------------------ 275//------------------------
276{ 276{
277 int i; 277 int i;
278 for (i=0; i<MAX_PATTERNS; i++) if (Patterns[i]) 278 for (i=0; i<MAX_PATTERNS; i++) if (Patterns[i])
279 { 279 {
280 FreePattern(Patterns[i]); 280 FreePattern(Patterns[i]);
281 Patterns[i] = NULL; 281 Patterns[i] = NULL;
282 } 282 }
283 m_nPatternNames = 0; 283 m_nPatternNames = 0;
284 if (m_lpszPatternNames) 284 if (m_lpszPatternNames)
285 { 285 {
286 delete m_lpszPatternNames; 286 delete m_lpszPatternNames;
287 m_lpszPatternNames = NULL; 287 m_lpszPatternNames = NULL;
288 } 288 }
289 if (m_lpszSongComments) 289 if (m_lpszSongComments)
290 { 290 {
291 delete m_lpszSongComments; 291 delete m_lpszSongComments;
292 m_lpszSongComments = NULL; 292 m_lpszSongComments = NULL;
293 } 293 }
294 for (i=1; i<MAX_SAMPLES; i++) 294 for (i=1; i<MAX_SAMPLES; i++)
295 { 295 {
296 MODINSTRUMENT *pins = &Ins[i]; 296 MODINSTRUMENT *pins = &Ins[i];
297 if (pins->pSample) 297 if (pins->pSample)
298 { 298 {
299 FreeSample(pins->pSample); 299 FreeSample(pins->pSample);
300 pins->pSample = NULL; 300 pins->pSample = NULL;
301 } 301 }
302 } 302 }
303 for (i=0; i<MAX_INSTRUMENTS; i++) 303 for (i=0; i<MAX_INSTRUMENTS; i++)
304 { 304 {
305 if (Headers[i]) 305 if (Headers[i])
306 { 306 {
307 delete Headers[i]; 307 delete Headers[i];
308 Headers[i] = NULL; 308 Headers[i] = NULL;
309 } 309 }
310 } 310 }
311 for (i=0; i<MAX_MIXPLUGINS; i++) 311 for (i=0; i<MAX_MIXPLUGINS; i++)
312 { 312 {
313 if ((m_MixPlugins[i].nPluginDataSize) && (m_MixPlugins[i].pPluginData)) 313 if ((m_MixPlugins[i].nPluginDataSize) && (m_MixPlugins[i].pPluginData))
314 { 314 {
315 m_MixPlugins[i].nPluginDataSize = 0; 315 m_MixPlugins[i].nPluginDataSize = 0;
316 delete [] (signed char*)m_MixPlugins[i].pPluginData; 316 delete [] (signed char*)m_MixPlugins[i].pPluginData;
317 m_MixPlugins[i].pPluginData = NULL; 317 m_MixPlugins[i].pPluginData = NULL;
318 } 318 }
319 m_MixPlugins[i].pMixState = NULL; 319 m_MixPlugins[i].pMixState = NULL;
320 if (m_MixPlugins[i].pMixPlugin) 320 if (m_MixPlugins[i].pMixPlugin)
321 { 321 {
322 m_MixPlugins[i].pMixPlugin->Release(); 322 m_MixPlugins[i].pMixPlugin->Release();
323 m_MixPlugins[i].pMixPlugin = NULL; 323 m_MixPlugins[i].pMixPlugin = NULL;
324 } 324 }
325 } 325 }
326 m_nType = MOD_TYPE_NONE; 326 m_nType = MOD_TYPE_NONE;
327 m_nChannels = m_nSamples = m_nInstruments = 0; 327 m_nChannels = m_nSamples = m_nInstruments = 0;
328 return TRUE; 328 return TRUE;
329} 329}
330 330
331 331
332////////////////////////////////////////////////////////////////////////// 332//////////////////////////////////////////////////////////////////////////
333// Memory Allocation 333// Memory Allocation
334 334
335MODCOMMAND *CSoundFile::AllocatePattern(UINT rows, UINT nchns) 335MODCOMMAND *CSoundFile::AllocatePattern(UINT rows, UINT nchns)
336//------------------------------------------------------------ 336//------------------------------------------------------------
337{ 337{
338 MODCOMMAND *p = new MODCOMMAND[rows*nchns]; 338 MODCOMMAND *p = new MODCOMMAND[rows*nchns];
339 if (p) memset(p, 0, rows*nchns*sizeof(MODCOMMAND)); 339 if (p) memset(p, 0, rows*nchns*sizeof(MODCOMMAND));
340 return p; 340 return p;
341} 341}
342 342
343 343
344void CSoundFile::FreePattern(LPVOID pat) 344void CSoundFile::FreePattern(LPVOID pat)
345//-------------------------------------- 345//--------------------------------------
346{ 346{
347 if (pat) delete [] (signed char*)pat; 347 if (pat) delete [] (signed char*)pat;
348} 348}
349 349
350 350
351signed char* CSoundFile::AllocateSample(UINT nbytes) 351signed char* CSoundFile::AllocateSample(UINT nbytes)
352//------------------------------------------- 352//-------------------------------------------
353{ 353{
354 signed char * p = (signed char *)GlobalAllocPtr(GHND, (nbytes+39) & ~7); 354 signed char * p = (signed char *)GlobalAllocPtr(GHND, (nbytes+39) & ~7);
355 if (p) p += 16; 355 if (p) p += 16;
356 return p; 356 return p;
357} 357}
358 358
359 359
360void CSoundFile::FreeSample(LPVOID p) 360void CSoundFile::FreeSample(LPVOID p)
361//----------------------------------- 361//-----------------------------------
362{ 362{
363 if (p) 363 if (p)
364 { 364 {
365 GlobalFreePtr(((LPSTR)p)-16); 365 GlobalFreePtr(((LPSTR)p)-16);
366 } 366 }
367} 367}
368 368
369 369
370////////////////////////////////////////////////////////////////////////// 370//////////////////////////////////////////////////////////////////////////
371// Misc functions 371// Misc functions
372 372
373void CSoundFile::ResetMidiCfg() 373void CSoundFile::ResetMidiCfg()
374//----------------------------- 374//-----------------------------
375{ 375{
376 memset(&m_MidiCfg, 0, sizeof(m_MidiCfg)); 376 memset(&m_MidiCfg, 0, sizeof(m_MidiCfg));
377 lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_START*32], "FF"); 377 lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_START*32], "FF");
378 lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_STOP*32], "FC"); 378 lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_STOP*32], "FC");
379 lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEON*32], "9c n v"); 379 lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEON*32], "9c n v");
380 lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEOFF*32], "9c n 0"); 380 lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEOFF*32], "9c n 0");
381 lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM*32], "Cc p"); 381 lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM*32], "Cc p");
382 lstrcpy(&m_MidiCfg.szMidiSFXExt[0], "F0F000z"); 382 lstrcpy(&m_MidiCfg.szMidiSFXExt[0], "F0F000z");
383 for (int iz=0; iz<16; iz++) wsprintf(&m_MidiCfg.szMidiZXXExt[iz*32], "F0F001%02X", iz*8); 383 for (int iz=0; iz<16; iz++) wsprintf(&m_MidiCfg.szMidiZXXExt[iz*32], "F0F001%02X", iz*8);
384} 384}
385 385
386 386
387UINT CSoundFile::GetNumChannels() const 387UINT CSoundFile::GetNumChannels() const
388//------------------------------------- 388//-------------------------------------
389{ 389{
390 UINT n = 0; 390 UINT n = 0;
391 for (UINT i=0; i<m_nChannels; i++) if (ChnSettings[i].nVolume) n++; 391 for (UINT i=0; i<m_nChannels; i++) if (ChnSettings[i].nVolume) n++;
392 return n; 392 return n;
393} 393}
394 394
395 395
396UINT CSoundFile::GetSongComments(LPSTR s, UINT len, UINT linesize) 396UINT CSoundFile::GetSongComments(LPSTR s, UINT len, UINT linesize)
397//---------------------------------------------------------------- 397//----------------------------------------------------------------
398{ 398{
399 LPCSTR p = m_lpszSongComments; 399 LPCSTR p = m_lpszSongComments;
400 if (!p) return 0; 400 if (!p) return 0;
401 UINT i = 2, ln=0; 401 UINT i = 2, ln=0;
402 if ((len) && (s)) s[0] = '\x0D'; 402 if ((len) && (s)) s[0] = '\x0D';
403 if ((len > 1) && (s)) s[1] = '\x0A'; 403 if ((len > 1) && (s)) s[1] = '\x0A';
404 while ((*p)&& (i+2 < len)) 404 while ((*p)&& (i+2 < len))
405 { 405 {
406 BYTE c = (BYTE)*p++; 406 BYTE c = (BYTE)*p++;
407 if ((c == 0x0D) || ((c == ' ') && (ln >= linesize))) 407 if ((c == 0x0D) || ((c == ' ') && (ln >= linesize)))
408 { if (s) { s[i++] = '\x0D'; s[i++] = '\x0A'; } else i+= 2; ln=0; } 408 { if (s) { s[i++] = '\x0D'; s[i++] = '\x0A'; } else i+= 2; ln=0; }
409 else 409 else
410 if (c >= 0x20) { if (s) s[i++] = c; else i++; ln++; } 410 if (c >= 0x20) { if (s) s[i++] = c; else i++; ln++; }
411 } 411 }
412 if (s) s[i] = 0; 412 if (s) s[i] = 0;
413 return i; 413 return i;
414} 414}
415 415
416 416
417UINT CSoundFile::GetRawSongComments(LPSTR s, UINT len, UINT linesize) 417UINT CSoundFile::GetRawSongComments(LPSTR s, UINT len, UINT linesize)
418//------------------------------------------------------------------- 418//-------------------------------------------------------------------
419{ 419{
420 LPCSTR p = m_lpszSongComments; 420 LPCSTR p = m_lpszSongComments;
421 if (!p) return 0; 421 if (!p) return 0;
422 UINT i = 0, ln=0; 422 UINT i = 0, ln=0;
423 while ((*p)&& (i < len-1)) 423 while ((*p)&& (i < len-1))
424 { 424 {
425 BYTE c = (BYTE)*p++; 425 BYTE c = (BYTE)*p++;
426 if ((c == 0x0D)|| (c == 0x0A)) 426 if ((c == 0x0D)|| (c == 0x0A))
427 { 427 {
428 if (ln) 428 if (ln)
429 { 429 {
430 while (ln < linesize) { if (s) s[i] = ' '; i++; ln++; } 430 while (ln < linesize) { if (s) s[i] = ' '; i++; ln++; }
431 ln = 0; 431 ln = 0;
432 } 432 }
433 } else 433 } else
434 if ((c == ' ') && (!ln)) 434 if ((c == ' ') && (!ln))
435 { 435 {
436 UINT k=0; 436 UINT k=0;
437 while ((p[k]) && (p[k] >= ' '))k++; 437 while ((p[k]) && (p[k] >= ' '))k++;
438 if (k <= linesize) 438 if (k <= linesize)
439 { 439 {
440 if (s) s[i] = ' '; 440 if (s) s[i] = ' ';
441 i++; 441 i++;
442 ln++; 442 ln++;
443 } 443 }
444 } else 444 } else
445 { 445 {
446 if (s) s[i] = c; 446 if (s) s[i] = c;
447 i++; 447 i++;
448 ln++; 448 ln++;
449 if (ln == linesize) ln = 0; 449 if (ln == linesize) ln = 0;
450 } 450 }
451 } 451 }
452 if (ln) 452 if (ln)
453 { 453 {
454 while ((ln < linesize) && (i < len)) 454 while ((ln < linesize) && (i < len))
455 { 455 {
456 if (s) s[i] = ' '; 456 if (s) s[i] = ' ';
457 i++; 457 i++;
458 ln++; 458 ln++;
459 } 459 }
460 } 460 }
461 if (s) s[i] = 0; 461 if (s) s[i] = 0;
462 return i; 462 return i;
463} 463}
464 464
465 465
466BOOL CSoundFile::SetWaveConfig(UINT nRate,UINT nBits,UINT nChannels,BOOL bMMX) 466BOOL CSoundFile::SetWaveConfig(UINT nRate,UINT nBits,UINT nChannels,BOOL bMMX)
467//---------------------------------------------------------------------------- 467//----------------------------------------------------------------------------
468{ 468{
469 BOOL bReset = FALSE; 469 BOOL bReset = FALSE;
470 DWORD d = gdwSoundSetup & ~SNDMIX_ENABLEMMX; 470 DWORD d = gdwSoundSetup & ~SNDMIX_ENABLEMMX;
471 if (bMMX) d |= SNDMIX_ENABLEMMX; 471 if (bMMX) d |= SNDMIX_ENABLEMMX;
472 if ((gdwMixingFreq != nRate) || (gnBitsPerSample != nBits) || (gnChannels != nChannels) || (d != gdwSoundSetup)) bReset = TRUE; 472 if ((gdwMixingFreq != nRate) || (gnBitsPerSample != nBits) || (gnChannels != nChannels) || (d != gdwSoundSetup)) bReset = TRUE;
473 gnChannels = nChannels; 473 gnChannels = nChannels;
474 gdwSoundSetup = d; 474 gdwSoundSetup = d;
475 gdwMixingFreq = nRate; 475 gdwMixingFreq = nRate;
476 gnBitsPerSample = nBits; 476 gnBitsPerSample = nBits;
477 InitPlayer(bReset); 477 InitPlayer(bReset);
478 return TRUE; 478 return TRUE;
479} 479}
480 480
481 481
482BOOL CSoundFile::SetResamplingMode(UINT nMode) 482BOOL CSoundFile::SetResamplingMode(UINT nMode)
483//-------------------------------------------- 483//--------------------------------------------
484{ 484{
485 DWORD d = gdwSoundSetup & ~(SNDMIX_NORESAMPLING|SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE); 485 DWORD d = gdwSoundSetup & ~(SNDMIX_NORESAMPLING|SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE);
486 switch(nMode) 486 switch(nMode)
487 { 487 {
488 case SRCMODE_NEAREST:d |= SNDMIX_NORESAMPLING; break; 488 case SRCMODE_NEAREST:d |= SNDMIX_NORESAMPLING; break;
489 case SRCMODE_LINEAR:break; 489 case SRCMODE_LINEAR:break;
490 case SRCMODE_SPLINE:d |= SNDMIX_HQRESAMPLER; break; 490 case SRCMODE_SPLINE:d |= SNDMIX_HQRESAMPLER; break;
491 case SRCMODE_POLYPHASE:d |= (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE); break; 491 case SRCMODE_POLYPHASE:d |= (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE); break;
492 default: 492 default:
493 return FALSE; 493 return FALSE;
494 } 494 }
495 gdwSoundSetup = d; 495 gdwSoundSetup = d;
496 return TRUE; 496 return TRUE;
497} 497}
498 498
499 499
500BOOL CSoundFile::SetMasterVolume(UINT nVol, BOOL bAdjustAGC) 500BOOL CSoundFile::SetMasterVolume(UINT nVol, BOOL bAdjustAGC)
501//---------------------------------------------------------- 501//----------------------------------------------------------
502{ 502{
503 if (nVol < 1) nVol = 1; 503 if (nVol < 1) nVol = 1;
504 if (nVol > 0x200) nVol = 0x200;// x4 maximum 504 if (nVol > 0x200) nVol = 0x200;// x4 maximum
505 if ((nVol < m_nMasterVolume) && (nVol) && (gdwSoundSetup & SNDMIX_AGC) && (bAdjustAGC)) 505 if ((nVol < m_nMasterVolume) && (nVol) && (gdwSoundSetup & SNDMIX_AGC) && (bAdjustAGC))
506 { 506 {
507 gnAGC = gnAGC * m_nMasterVolume / nVol; 507 gnAGC = gnAGC * m_nMasterVolume / nVol;
508 if (gnAGC > AGC_UNITY) gnAGC = AGC_UNITY; 508 if (gnAGC > AGC_UNITY) gnAGC = AGC_UNITY;
509 } 509 }
510 m_nMasterVolume = nVol; 510 m_nMasterVolume = nVol;
511 return TRUE; 511 return TRUE;
512} 512}
513 513
514 514
515void CSoundFile::SetAGC(BOOL b) 515void CSoundFile::SetAGC(BOOL b)
516//----------------------------- 516//-----------------------------
517{ 517{
518 if (b) 518 if (b)
519 { 519 {
520 if (!(gdwSoundSetup & SNDMIX_AGC)) 520 if (!(gdwSoundSetup & SNDMIX_AGC))
521 { 521 {
522 gdwSoundSetup |= SNDMIX_AGC; 522 gdwSoundSetup |= SNDMIX_AGC;
523 gnAGC = AGC_UNITY; 523 gnAGC = AGC_UNITY;
524 } 524 }
525 } else gdwSoundSetup &= ~SNDMIX_AGC; 525 } else gdwSoundSetup &= ~SNDMIX_AGC;
526} 526}
527 527
528 528
529UINT CSoundFile::GetNumPatterns() const 529UINT CSoundFile::GetNumPatterns() const
530//------------------------------------- 530//-------------------------------------
531{ 531{
532 UINT i = 0; 532 UINT i = 0;
533 while ((i < MAX_ORDERS) && (Order[i] < 0xFF)) i++; 533 while ((i < MAX_ORDERS) && (Order[i] < 0xFF)) i++;
534 return i; 534 return i;
535} 535}
536 536
537 537
538UINT CSoundFile::GetNumInstruments() const 538UINT CSoundFile::GetNumInstruments() const
539//---------------------------------------- 539//----------------------------------------
540{ 540{
541 UINT n=0; 541 UINT n=0;
542 for (UINT i=0; i<MAX_INSTRUMENTS; i++) if (Ins[i].pSample) n++; 542 for (UINT i=0; i<MAX_INSTRUMENTS; i++) if (Ins[i].pSample) n++;
543 return n; 543 return n;
544} 544}
545 545
546 546
547UINT CSoundFile::GetMaxPosition() const 547UINT CSoundFile::GetMaxPosition() const
548//------------------------------------- 548//-------------------------------------
549{ 549{
550 UINT max = 0; 550 UINT max = 0;
551 UINT i = 0; 551 UINT i = 0;
552 552
553 while ((i < MAX_ORDERS) && (Order[i] != 0xFF)) 553 while ((i < MAX_ORDERS) && (Order[i] != 0xFF))
554 { 554 {
555 if (Order[i] < MAX_PATTERNS) max += PatternSize[Order[i]]; 555 if (Order[i] < MAX_PATTERNS) max += PatternSize[Order[i]];
556 i++; 556 i++;
557 } 557 }
558 return max; 558 return max;
559} 559}
560 560
561 561
562UINT CSoundFile::GetCurrentPos() const 562UINT CSoundFile::GetCurrentPos() const
563//------------------------------------ 563//------------------------------------
564{ 564{
565 UINT pos = 0; 565 UINT pos = 0;
566 566
567 for (UINT i=0; i<m_nCurrentPattern; i++) if (Order[i] < MAX_PATTERNS) 567 for (UINT i=0; i<m_nCurrentPattern; i++) if (Order[i] < MAX_PATTERNS)
568 pos += PatternSize[Order[i]]; 568 pos += PatternSize[Order[i]];
569 return pos + m_nRow; 569 return pos + m_nRow;
570} 570}
571 571
572 572
573void CSoundFile::SetCurrentPos(UINT nPos) 573void CSoundFile::SetCurrentPos(UINT nPos)
574//--------------------------------------- 574//---------------------------------------
575{ 575{
576 UINT i, nPattern; 576 UINT i, nPattern;
577 577
578 for (i=0; i<MAX_CHANNELS; i++) 578 for (i=0; i<MAX_CHANNELS; i++)
579 { 579 {
580 Chn[i].nNote = Chn[i].nNewNote = Chn[i].nNewIns = 0; 580 Chn[i].nNote = Chn[i].nNewNote = Chn[i].nNewIns = 0;
581 Chn[i].pInstrument = NULL; 581 Chn[i].pInstrument = NULL;
582 Chn[i].pHeader = NULL; 582 Chn[i].pHeader = NULL;
583 Chn[i].nPortamentoDest = 0; 583 Chn[i].nPortamentoDest = 0;
584 Chn[i].nCommand = 0; 584 Chn[i].nCommand = 0;
585 Chn[i].nPatternLoopCount = 0; 585 Chn[i].nPatternLoopCount = 0;
586 Chn[i].nPatternLoop = 0; 586 Chn[i].nPatternLoop = 0;
587 Chn[i].nFadeOutVol = 0; 587 Chn[i].nFadeOutVol = 0;
588 Chn[i].dwFlags |= CHN_KEYOFF|CHN_NOTEFADE; 588 Chn[i].dwFlags |= CHN_KEYOFF|CHN_NOTEFADE;
589 Chn[i].nTremorCount = 0; 589 Chn[i].nTremorCount = 0;
590 } 590 }
591 if (!nPos) 591 if (!nPos)
592 { 592 {
593 for (i=0; i<MAX_CHANNELS; i++) 593 for (i=0; i<MAX_CHANNELS; i++)
594 { 594 {
595 Chn[i].nPeriod = 0; 595 Chn[i].nPeriod = 0;
596 Chn[i].nPos = Chn[i].nLength = 0; 596 Chn[i].nPos = Chn[i].nLength = 0;
597 Chn[i].nLoopStart = 0; 597 Chn[i].nLoopStart = 0;
598 Chn[i].nLoopEnd = 0; 598 Chn[i].nLoopEnd = 0;
599 Chn[i].nROfs = Chn[i].nLOfs = 0; 599 Chn[i].nROfs = Chn[i].nLOfs = 0;
600 Chn[i].pSample = NULL; 600 Chn[i].pSample = NULL;
601 Chn[i].pInstrument = NULL; 601 Chn[i].pInstrument = NULL;
602 Chn[i].pHeader = NULL; 602 Chn[i].pHeader = NULL;
603 Chn[i].nCutOff = 0x7F; 603 Chn[i].nCutOff = 0x7F;
604 Chn[i].nResonance = 0; 604 Chn[i].nResonance = 0;
605 Chn[i].nLeftVol = Chn[i].nRightVol = 0; 605 Chn[i].nLeftVol = Chn[i].nRightVol = 0;
606 Chn[i].nNewLeftVol = Chn[i].nNewRightVol = 0; 606 Chn[i].nNewLeftVol = Chn[i].nNewRightVol = 0;
607 Chn[i].nLeftRamp = Chn[i].nRightRamp = 0; 607 Chn[i].nLeftRamp = Chn[i].nRightRamp = 0;
608 Chn[i].nVolume = 256; 608 Chn[i].nVolume = 256;
609 if (i < MAX_BASECHANNELS) 609 if (i < MAX_BASECHANNELS)
610 { 610 {
611 Chn[i].dwFlags = ChnSettings[i].dwFlags; 611 Chn[i].dwFlags = ChnSettings[i].dwFlags;
612 Chn[i].nPan = ChnSettings[i].nPan; 612 Chn[i].nPan = ChnSettings[i].nPan;
613 Chn[i].nGlobalVol = ChnSettings[i].nVolume; 613 Chn[i].nGlobalVol = ChnSettings[i].nVolume;
614 } else 614 } else
615 { 615 {
616 Chn[i].dwFlags = 0; 616 Chn[i].dwFlags = 0;
617 Chn[i].nPan = 128; 617 Chn[i].nPan = 128;
618 Chn[i].nGlobalVol = 64; 618 Chn[i].nGlobalVol = 64;
619 } 619 }
620 } 620 }
621 m_nGlobalVolume = m_nDefaultGlobalVolume; 621 m_nGlobalVolume = m_nDefaultGlobalVolume;
622 m_nMusicSpeed = m_nDefaultSpeed; 622 m_nMusicSpeed = m_nDefaultSpeed;
623 m_nMusicTempo = m_nDefaultTempo; 623 m_nMusicTempo = m_nDefaultTempo;
624 } 624 }
625 m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE); 625 m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE);
626 for (nPattern = 0; nPattern < MAX_ORDERS; nPattern++) 626 for (nPattern = 0; nPattern < MAX_ORDERS; nPattern++)
627 { 627 {
628 UINT ord = Order[nPattern]; 628 UINT ord = Order[nPattern];
629 if (ord == 0xFE) continue; 629 if (ord == 0xFE) continue;
630 if (ord == 0xFF) break; 630 if (ord == 0xFF) break;
631 if (ord < MAX_PATTERNS) 631 if (ord < MAX_PATTERNS)
632 { 632 {
633 if (nPos < (UINT)PatternSize[ord]) break; 633 if (nPos < (UINT)PatternSize[ord]) break;
634 nPos -= PatternSize[ord]; 634 nPos -= PatternSize[ord];
635 } 635 }
636 } 636 }
637 // Buggy position ? 637 // Buggy position ?
638 if ((nPattern >= MAX_ORDERS) 638 if ((nPattern >= MAX_ORDERS)
639 || (Order[nPattern] >= MAX_PATTERNS) 639 || (Order[nPattern] >= MAX_PATTERNS)
640 || (nPos >= PatternSize[Order[nPattern]])) 640 || (nPos >= PatternSize[Order[nPattern]]))
641 { 641 {
642 nPos = 0; 642 nPos = 0;
643 nPattern = 0; 643 nPattern = 0;
644 } 644 }
645 UINT nRow = nPos; 645 UINT nRow = nPos;
646 if ((nRow) && (Order[nPattern] < MAX_PATTERNS)) 646 if ((nRow) && (Order[nPattern] < MAX_PATTERNS))
647 { 647 {
648 MODCOMMAND *p = Patterns[Order[nPattern]]; 648 MODCOMMAND *p = Patterns[Order[nPattern]];
649 if ((p) && (nRow < PatternSize[Order[nPattern]])) 649 if ((p) && (nRow < PatternSize[Order[nPattern]]))
650 { 650 {
651 BOOL bOk = FALSE; 651 BOOL bOk = FALSE;
652 while ((!bOk) && (nRow > 0)) 652 while ((!bOk) && (nRow > 0))
653 { 653 {
654 UINT n = nRow * m_nChannels; 654 UINT n = nRow * m_nChannels;
655 for (UINT k=0; k<m_nChannels; k++, n++) 655 for (UINT k=0; k<m_nChannels; k++, n++)
656 { 656 {
657 if (p[n].note) 657 if (p[n].note)
658 { 658 {
659 bOk = TRUE; 659 bOk = TRUE;
660 break; 660 break;
661 } 661 }
662 } 662 }
663 if (!bOk) nRow--; 663 if (!bOk) nRow--;
664 } 664 }
665 } 665 }
666 } 666 }
667 m_nNextPattern = nPattern; 667 m_nNextPattern = nPattern;
668 m_nNextRow = nRow; 668 m_nNextRow = nRow;
669 m_nTickCount = m_nMusicSpeed; 669 m_nTickCount = m_nMusicSpeed;
670 m_nBufferCount = 0; 670 m_nBufferCount = 0;
671 m_nPatternDelay = 0; 671 m_nPatternDelay = 0;
672 m_nFrameDelay = 0; 672 m_nFrameDelay = 0;
673} 673}
674 674
675 675
676void CSoundFile::SetCurrentOrder(UINT nPos) 676void CSoundFile::SetCurrentOrder(UINT nPos)
677//----------------------------------------- 677//-----------------------------------------
678{ 678{
679 while ((nPos < MAX_ORDERS) && (Order[nPos] == 0xFE)) nPos++; 679 while ((nPos < MAX_ORDERS) && (Order[nPos] == 0xFE)) nPos++;
680 if ((nPos >= MAX_ORDERS) || (Order[nPos] >= MAX_PATTERNS)) return; 680 if ((nPos >= MAX_ORDERS) || (Order[nPos] >= MAX_PATTERNS)) return;
681 for (UINT j=0; j<MAX_CHANNELS; j++) 681 for (UINT j=0; j<MAX_CHANNELS; j++)
682 { 682 {
683 Chn[j].nPeriod = 0; 683 Chn[j].nPeriod = 0;
684 Chn[j].nNote = 0; 684 Chn[j].nNote = 0;
685 Chn[j].nPortamentoDest = 0; 685 Chn[j].nPortamentoDest = 0;
686 Chn[j].nCommand = 0; 686 Chn[j].nCommand = 0;
687 Chn[j].nPatternLoopCount = 0; 687 Chn[j].nPatternLoopCount = 0;
688 Chn[j].nPatternLoop = 0; 688 Chn[j].nPatternLoop = 0;
689 Chn[j].nTremorCount = 0; 689 Chn[j].nTremorCount = 0;
690 } 690 }
691 if (!nPos) 691 if (!nPos)
692 { 692 {
693 SetCurrentPos(0); 693 SetCurrentPos(0);
694 } else 694 } else
695 { 695 {
696 m_nNextPattern = nPos; 696 m_nNextPattern = nPos;
697 m_nRow = m_nNextRow = 0; 697 m_nRow = m_nNextRow = 0;
698 m_nPattern = 0; 698 m_nPattern = 0;
699 m_nTickCount = m_nMusicSpeed; 699 m_nTickCount = m_nMusicSpeed;
700 m_nBufferCount = 0; 700 m_nBufferCount = 0;
701 m_nTotalCount = 0; 701 m_nTotalCount = 0;
702 m_nPatternDelay = 0; 702 m_nPatternDelay = 0;
703 m_nFrameDelay = 0; 703 m_nFrameDelay = 0;
704 } 704 }
705 m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE); 705 m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE);
706} 706}
707 707
708 708
709void CSoundFile::ResetChannels() 709void CSoundFile::ResetChannels()
710//------------------------------ 710//------------------------------
711{ 711{
712 m_dwSongFlags &= ~(SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE); 712 m_dwSongFlags &= ~(SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE);
713 m_nBufferCount = 0; 713 m_nBufferCount = 0;
714 for (UINT i=0; i<MAX_CHANNELS; i++) 714 for (UINT i=0; i<MAX_CHANNELS; i++)
715 { 715 {
716 Chn[i].nROfs = Chn[i].nLOfs = 0; 716 Chn[i].nROfs = Chn[i].nLOfs = 0;
717 } 717 }
718} 718}
719 719
720 720
721void CSoundFile::LoopPattern(int nPat, int nRow) 721void CSoundFile::LoopPattern(int nPat, int nRow)
722//---------------------------------------------- 722//----------------------------------------------
723{ 723{
724 if ((nPat < 0) || (nPat >= MAX_PATTERNS) || (!Patterns[nPat])) 724 if ((nPat < 0) || (nPat >= MAX_PATTERNS) || (!Patterns[nPat]))
725 { 725 {
726 m_dwSongFlags &= ~SONG_PATTERNLOOP; 726 m_dwSongFlags &= ~SONG_PATTERNLOOP;
727 } else 727 } else
728 { 728 {
729 if ((nRow < 0) || (nRow >= PatternSize[nPat])) nRow = 0; 729 if ((nRow < 0) || (nRow >= PatternSize[nPat])) nRow = 0;
730 m_nPattern = nPat; 730 m_nPattern = nPat;
731 m_nRow = m_nNextRow = nRow; 731 m_nRow = m_nNextRow = nRow;
732 m_nTickCount = m_nMusicSpeed; 732 m_nTickCount = m_nMusicSpeed;
733 m_nPatternDelay = 0; 733 m_nPatternDelay = 0;
734 m_nFrameDelay = 0; 734 m_nFrameDelay = 0;
735 m_nBufferCount = 0; 735 m_nBufferCount = 0;
736 m_dwSongFlags |= SONG_PATTERNLOOP; 736 m_dwSongFlags |= SONG_PATTERNLOOP;
737 } 737 }
738} 738}
739 739
740 740
741UINT CSoundFile::GetBestSaveFormat() const 741UINT CSoundFile::GetBestSaveFormat() const
742//---------------------------------------- 742//----------------------------------------
743{ 743{
744 if ((!m_nSamples) || (!m_nChannels)) return MOD_TYPE_NONE; 744 if ((!m_nSamples) || (!m_nChannels)) return MOD_TYPE_NONE;
745 if (!m_nType) return MOD_TYPE_NONE; 745 if (!m_nType) return MOD_TYPE_NONE;
746 if (m_nType & (MOD_TYPE_MOD|MOD_TYPE_OKT)) 746 if (m_nType & (MOD_TYPE_MOD|MOD_TYPE_OKT))
747 return MOD_TYPE_MOD; 747 return MOD_TYPE_MOD;
748 if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_ULT|MOD_TYPE_FAR|MOD_TYPE_PTM)) 748 if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_ULT|MOD_TYPE_FAR|MOD_TYPE_PTM))
749 return MOD_TYPE_S3M; 749 return MOD_TYPE_S3M;
750 if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MED|MOD_TYPE_MTM|MOD_TYPE_MT2)) 750 if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MED|MOD_TYPE_MTM|MOD_TYPE_MT2))
751 return MOD_TYPE_XM; 751 return MOD_TYPE_XM;
752 return MOD_TYPE_IT; 752 return MOD_TYPE_IT;
753} 753}
754 754
755 755
756UINT CSoundFile::GetSaveFormats() const 756UINT CSoundFile::GetSaveFormats() const
757//------------------------------------- 757//-------------------------------------
758{ 758{
759 UINT n = 0; 759 UINT n = 0;
760 if ((!m_nSamples) || (!m_nChannels) || (m_nType == MOD_TYPE_NONE)) return 0; 760 if ((!m_nSamples) || (!m_nChannels) || (m_nType == MOD_TYPE_NONE)) return 0;
761 switch(m_nType) 761 switch(m_nType)
762 { 762 {
763 case MOD_TYPE_MOD:n = MOD_TYPE_MOD; 763 case MOD_TYPE_MOD:n = MOD_TYPE_MOD;
764 case MOD_TYPE_S3M:n = MOD_TYPE_S3M; 764 case MOD_TYPE_S3M:n = MOD_TYPE_S3M;
765 } 765 }
766 n |= MOD_TYPE_XM | MOD_TYPE_IT; 766 n |= MOD_TYPE_XM | MOD_TYPE_IT;
767 if (!m_nInstruments) 767 if (!m_nInstruments)
768 { 768 {
769 if (m_nSamples < 32) n |= MOD_TYPE_MOD; 769 if (m_nSamples < 32) n |= MOD_TYPE_MOD;
770 n |= MOD_TYPE_S3M; 770 n |= MOD_TYPE_S3M;
771 } 771 }
772 return n; 772 return n;
773} 773}
774 774
775 775
776UINT CSoundFile::GetSampleName(UINT nSample,LPSTR s) const 776UINT CSoundFile::GetSampleName(UINT nSample,LPSTR s) const
777//-------------------------------------------------------- 777//--------------------------------------------------------
778{ 778{
779 char sztmp[40] = ""; // changed from CHAR 779 char sztmp[40] = ""; // changed from CHAR
780 memcpy(sztmp, m_szNames[nSample],32); 780 memcpy(sztmp, m_szNames[nSample],32);
781 sztmp[31] = 0; 781 sztmp[31] = 0;
782 if (s) strcpy(s, sztmp); 782 if (s) strcpy(s, sztmp);
783 return strlen(sztmp); 783 return strlen(sztmp);
784} 784}
785 785
786 786
787UINT CSoundFile::GetInstrumentName(UINT nInstr,LPSTR s) const 787UINT CSoundFile::GetInstrumentName(UINT nInstr,LPSTR s) const
788//----------------------------------------------------------- 788//-----------------------------------------------------------
789{ 789{
790 char sztmp[40] = ""; // changed from CHAR 790 char sztmp[40] = ""; // changed from CHAR
791 if ((nInstr >= MAX_INSTRUMENTS) || (!Headers[nInstr])) 791 if ((nInstr >= MAX_INSTRUMENTS) || (!Headers[nInstr]))
792 { 792 {
793 if (s) *s = 0; 793 if (s) *s = 0;
794 return 0; 794 return 0;
795 } 795 }
796 INSTRUMENTHEADER *penv = Headers[nInstr]; 796 INSTRUMENTHEADER *penv = Headers[nInstr];
797 memcpy(sztmp, penv->name, 32); 797 memcpy(sztmp, penv->name, 32);
798 sztmp[31] = 0; 798 sztmp[31] = 0;
799 if (s) strcpy(s, sztmp); 799 if (s) strcpy(s, sztmp);
800 return strlen(sztmp); 800 return strlen(sztmp);
801} 801}
802 802
803 803
804#ifndef NO_PACKING 804#ifndef NO_PACKING
805UINT CSoundFile::PackSample(int &sample, int next) 805UINT CSoundFile::PackSample(int &sample, int next)
806//------------------------------------------------ 806//------------------------------------------------
807{ 807{
808 UINT i = 0; 808 UINT i = 0;
809 int delta = next - sample; 809 int delta = next - sample;
810 if (delta >= 0) 810 if (delta >= 0)
811 { 811 {
812 for (i=0; i<7; i++) if (delta <= (int)CompressionTable[i+1]) break; 812 for (i=0; i<7; i++) if (delta <= (int)CompressionTable[i+1]) break;
813 } else 813 } else
814 { 814 {
815 for (i=8; i<15; i++) if (delta >= (int)CompressionTable[i+1]) break; 815 for (i=8; i<15; i++) if (delta >= (int)CompressionTable[i+1]) break;
816 } 816 }
817 sample += (int)CompressionTable[i]; 817 sample += (int)CompressionTable[i];
818 return i; 818 return i;
819} 819}
820 820
821 821
822BOOL CSoundFile::CanPackSample(LPSTR pSample, UINT nLen, UINT nPacking, BYTE *result) 822BOOL CSoundFile::CanPackSample(LPSTR pSample, UINT nLen, UINT nPacking, BYTE *result)
823//----------------------------------------------------------------------------------- 823//-----------------------------------------------------------------------------------
824{ 824{
825 int pos, old, oldpos, besttable = 0; 825 int pos, old, oldpos, besttable = 0;
826 DWORD dwErr, dwTotal, dwResult; 826 DWORD dwErr, dwTotal, dwResult;
827 int i,j; 827 int i,j;
828 828
829 if (result) *result = 0; 829 if (result) *result = 0;
830 if ((!pSample) || (nLen < 1024)) return FALSE; 830 if ((!pSample) || (nLen < 1024)) return FALSE;
831 // Try packing with different tables 831 // Try packing with different tables
832 dwResult = 0; 832 dwResult = 0;
833 for (j=1; j<MAX_PACK_TABLES; j++) 833 for (j=1; j<MAX_PACK_TABLES; j++)
834 { 834 {
835 memcpy(CompressionTable, UnpackTable[j], 16); 835 memcpy(CompressionTable, UnpackTable[j], 16);
836 dwErr = 0; 836 dwErr = 0;
837 dwTotal = 1; 837 dwTotal = 1;
838 old = pos = oldpos = 0; 838 old = pos = oldpos = 0;
839 for (i=0; i<(int)nLen; i++) 839 for (i=0; i<(int)nLen; i++)
840 { 840 {
841 int s = (int)pSample[i]; 841 int s = (int)pSample[i];
842 PackSample(pos, s); 842 PackSample(pos, s);
843 dwErr += abs(pos - oldpos); 843 dwErr += abs(pos - oldpos);
844 dwTotal += abs(s - old); 844 dwTotal += abs(s - old);
845 old = s; 845 old = s;
846 oldpos = pos; 846 oldpos = pos;
847 } 847 }
848 dwErr = _muldiv(dwErr, 100, dwTotal); 848 dwErr = _muldiv(dwErr, 100, dwTotal);
849 if (dwErr >= dwResult) 849 if (dwErr >= dwResult)
850 { 850 {
851 dwResult = dwErr; 851 dwResult = dwErr;
852 besttable = j; 852 besttable = j;
853 } 853 }
854 } 854 }
855 memcpy(CompressionTable, UnpackTable[besttable], 16); 855 memcpy(CompressionTable, UnpackTable[besttable], 16);
856 if (result) 856 if (result)
857 { 857 {
858 if (dwResult > 100) *result= 100; else *result = (BYTE)dwResult; 858 if (dwResult > 100) *result= 100; else *result = (BYTE)dwResult;
859 } 859 }
860 return (dwResult >= nPacking) ? TRUE : FALSE; 860 return (dwResult >= nPacking) ? TRUE : FALSE;
861} 861}
862#endif // NO_PACKING 862#endif // NO_PACKING
863 863
864#ifndef MODPLUG_NO_FILESAVE 864#ifndef MODPLUG_NO_FILESAVE
865 865
866UINT CSoundFile::WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen) 866UINT CSoundFile::WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen)
867//----------------------------------------------------------------------------------- 867//-----------------------------------------------------------------------------------
868{ 868{
869 UINT len = 0, bufcount; 869 UINT len = 0, bufcount;
870 signed char buffer[4096]; 870 signed char buffer[4096];
871 signed char *pSample = (signed char *)pins->pSample; 871 signed char *pSample = (signed char *)pins->pSample;
872 UINT nLen = pins->nLength; 872 UINT nLen = pins->nLength;
873 873
874 if ((nMaxLen) && (nLen > nMaxLen)) nLen = nMaxLen; 874 if ((nMaxLen) && (nLen > nMaxLen)) nLen = nMaxLen;
875 if ((!pSample) || (f == NULL) || (!nLen)) return 0; 875 if ((!pSample) || (f == NULL) || (!nLen)) return 0;
876 switch(nFlags) 876 switch(nFlags)
877 { 877 {
878#ifndef NO_PACKING 878#ifndef NO_PACKING
879 // 3: 4-bit ADPCM data 879 // 3: 4-bit ADPCM data
880 case RS_ADPCM4: 880 case RS_ADPCM4:
881 { 881 {
882 int pos; 882 int pos;
883 len = (nLen + 1) / 2; 883 len = (nLen + 1) / 2;
884 fwrite(CompressionTable, 16, 1, f); 884 fwrite(CompressionTable, 16, 1, f);
885 bufcount = 0; 885 bufcount = 0;
886 pos = 0; 886 pos = 0;
887 for (UINT j=0; j<len; j++) 887 for (UINT j=0; j<len; j++)
888 { 888 {
889 BYTE b; 889 BYTE b;
890 // Sample #1 890 // Sample #1
891 b = PackSample(pos, (int)pSample[j*2]); 891 b = PackSample(pos, (int)pSample[j*2]);
892 // Sample #2 892 // Sample #2
893 b |= PackSample(pos, (int)pSample[j*2+1]) << 4; 893 b |= PackSample(pos, (int)pSample[j*2+1]) << 4;
894 buffer[bufcount++] = (signed char)b; 894 buffer[bufcount++] = (signed char)b;
895 if (bufcount >= sizeof(buffer)) 895 if (bufcount >= sizeof(buffer))
896 { 896 {
897 fwrite(buffer, 1, bufcount, f); 897 fwrite(buffer, 1, bufcount, f);
898 bufcount = 0; 898 bufcount = 0;
899 } 899 }
900 } 900 }
901 if (bufcount) fwrite(buffer, 1, bufcount, f); 901 if (bufcount) fwrite(buffer, 1, bufcount, f);
902 len += 16; 902 len += 16;
903 } 903 }
904 break; 904 break;
905#endif // NO_PACKING 905#endif // NO_PACKING
906 906
907 // 16-bit samples 907 // 16-bit samples
908 case RS_PCM16U: 908 case RS_PCM16U:
909 case RS_PCM16D: 909 case RS_PCM16D:
910 case RS_PCM16S: 910 case RS_PCM16S:
911 { 911 {
912 short int *p = (short int *)pSample; 912 short int *p = (short int *)pSample;
913 int s_old = 0, s_ofs; 913 int s_old = 0, s_ofs;
914 len = nLen * 2; 914 len = nLen * 2;
915 bufcount = 0; 915 bufcount = 0;
916 s_ofs = (nFlags == RS_PCM16U) ? 0x8000 : 0; 916 s_ofs = (nFlags == RS_PCM16U) ? 0x8000 : 0;
917 for (UINT j=0; j<nLen; j++) 917 for (UINT j=0; j<nLen; j++)
918 { 918 {
919 int s_new = *p; 919 int s_new = *p;
920 p++; 920 p++;
921 if (pins->uFlags & CHN_STEREO) 921 if (pins->uFlags & CHN_STEREO)
922 { 922 {
923 s_new = (s_new + (*p) + 1) >> 1; 923 s_new = (s_new + (*p) + 1) >> 1;
924 p++; 924 p++;
925 } 925 }
926 if (nFlags == RS_PCM16D) 926 if (nFlags == RS_PCM16D)
927 { 927 {
928 *((short *)(&buffer[bufcount])) = (short)(s_new - s_old); 928 *((short *)(&buffer[bufcount])) = (short)(s_new - s_old);
929 s_old = s_new; 929 s_old = s_new;
930 } else 930 } else
931 { 931 {
932 *((short *)(&buffer[bufcount])) = (short)(s_new + s_ofs); 932 *((short *)(&buffer[bufcount])) = (short)(s_new + s_ofs);
933 } 933 }
934 bufcount += 2; 934 bufcount += 2;
935 if (bufcount >= sizeof(buffer) - 1) 935 if (bufcount >= sizeof(buffer) - 1)
936 { 936 {
937 fwrite(buffer, 1, bufcount, f); 937 fwrite(buffer, 1, bufcount, f);
938 bufcount = 0; 938 bufcount = 0;
939 } 939 }
940 } 940 }
941 if (bufcount) fwrite(buffer, 1, bufcount, f); 941 if (bufcount) fwrite(buffer, 1, bufcount, f);
942 } 942 }
943 break; 943 break;
944 944
945 945
946 // 8-bit Stereo samples (not interleaved) 946 // 8-bit Stereo samples (not interleaved)
947 case RS_STPCM8S: 947 case RS_STPCM8S:
948 case RS_STPCM8U: 948 case RS_STPCM8U:
949 case RS_STPCM8D: 949 case RS_STPCM8D:
950 { 950 {
951 int s_ofs = (nFlags == RS_STPCM8U) ? 0x80 : 0; 951 int s_ofs = (nFlags == RS_STPCM8U) ? 0x80 : 0;
952 for (UINT iCh=0; iCh<2; iCh++) 952 for (UINT iCh=0; iCh<2; iCh++)
953 { 953 {
954 signed char *p = pSample + iCh; 954 signed char *p = pSample + iCh;
955 int s_old = 0; 955 int s_old = 0;
956 956
957 bufcount = 0; 957 bufcount = 0;
958 for (UINT j=0; j<nLen; j++) 958 for (UINT j=0; j<nLen; j++)
959 { 959 {
960 int s_new = *p; 960 int s_new = *p;
961 p += 2; 961 p += 2;
962 if (nFlags == RS_STPCM8D) 962 if (nFlags == RS_STPCM8D)
963 { 963 {
964 buffer[bufcount++] = (signed char)(s_new - s_old); 964 buffer[bufcount++] = (signed char)(s_new - s_old);
965 s_old = s_new; 965 s_old = s_new;
966 } else 966 } else
967 { 967 {
968 buffer[bufcount++] = (signed char)(s_new + s_ofs); 968 buffer[bufcount++] = (signed char)(s_new + s_ofs);
969 } 969 }
970 if (bufcount >= sizeof(buffer)) 970 if (bufcount >= sizeof(buffer))
971 { 971 {
972 fwrite(buffer, 1, bufcount, f); 972 fwrite(buffer, 1, bufcount, f);
973 bufcount = 0; 973 bufcount = 0;
974 } 974 }
975 } 975 }
976 if (bufcount) fwrite(buffer, 1, bufcount, f); 976 if (bufcount) fwrite(buffer, 1, bufcount, f);
977 } 977 }
978 } 978 }
979 len = nLen * 2; 979 len = nLen * 2;
980 break; 980 break;
981 981
982 // 16-bit Stereo samples (not interleaved) 982 // 16-bit Stereo samples (not interleaved)
983 case RS_STPCM16S: 983 case RS_STPCM16S:
984 case RS_STPCM16U: 984 case RS_STPCM16U:
985 case RS_STPCM16D: 985 case RS_STPCM16D:
986 { 986 {
987 int s_ofs = (nFlags == RS_STPCM16U) ? 0x8000 : 0; 987 int s_ofs = (nFlags == RS_STPCM16U) ? 0x8000 : 0;
988 for (UINT iCh=0; iCh<2; iCh++) 988 for (UINT iCh=0; iCh<2; iCh++)
989 { 989 {
990 signed short *p = ((signed short *)pSample) + iCh; 990 signed short *p = ((signed short *)pSample) + iCh;
991 int s_old = 0; 991 int s_old = 0;
992 992
993 bufcount = 0; 993 bufcount = 0;
994 for (UINT j=0; j<nLen; j++) 994 for (UINT j=0; j<nLen; j++)
995 { 995 {
996 int s_new = *p; 996 int s_new = *p;
997 p += 2; 997 p += 2;
998 if (nFlags == RS_STPCM16D) 998 if (nFlags == RS_STPCM16D)
999 { 999 {
1000 *((short *)(&buffer[bufcount])) = (short)(s_new - s_old); 1000 *((short *)(&buffer[bufcount])) = (short)(s_new - s_old);
1001 s_old = s_new; 1001 s_old = s_new;
1002 } else 1002 } else
1003 { 1003 {
1004 *((short *)(&buffer[bufcount])) = (short)(s_new + s_ofs); 1004 *((short *)(&buffer[bufcount])) = (short)(s_new + s_ofs);
1005 } 1005 }
1006 bufcount += 2; 1006 bufcount += 2;
1007 if (bufcount >= sizeof(buffer)) 1007 if (bufcount >= sizeof(buffer))
1008 { 1008 {
1009 fwrite(buffer, 1, bufcount, f); 1009 fwrite(buffer, 1, bufcount, f);
1010 bufcount = 0; 1010 bufcount = 0;
1011 } 1011 }
1012 } 1012 }
1013 if (bufcount) fwrite(buffer, 1, bufcount, f); 1013 if (bufcount) fwrite(buffer, 1, bufcount, f);
1014 } 1014 }
1015 } 1015 }
1016 len = nLen*4; 1016 len = nLen*4;
1017 break; 1017 break;
1018 1018
1019 //Stereo signed interleaved 1019 //Stereo signed interleaved
1020 case RS_STIPCM8S: 1020 case RS_STIPCM8S:
1021 case RS_STIPCM16S: 1021 case RS_STIPCM16S:
1022 len = nLen * 2; 1022 len = nLen * 2;
1023 if (nFlags == RS_STIPCM16S) len *= 2; 1023 if (nFlags == RS_STIPCM16S) len *= 2;
1024 fwrite(pSample, 1, len, f); 1024 fwrite(pSample, 1, len, f);
1025 break; 1025 break;
1026 1026
1027 // Default: assume 8-bit PCM data 1027 // Default: assume 8-bit PCM data
1028 default: 1028 default:
1029 len = nLen; 1029 len = nLen;
1030 bufcount = 0; 1030 bufcount = 0;
1031 { 1031 {
1032 signed char *p = pSample; 1032 signed char *p = pSample;
1033 int sinc = (pins->uFlags & CHN_16BIT) ? 2 : 1; 1033 int sinc = (pins->uFlags & CHN_16BIT) ? 2 : 1;
1034 int s_old = 0, s_ofs = (nFlags == RS_PCM8U) ? 0x80 : 0; 1034 int s_old = 0, s_ofs = (nFlags == RS_PCM8U) ? 0x80 : 0;
1035 if (pins->uFlags & CHN_16BIT) p++; 1035 if (pins->uFlags & CHN_16BIT) p++;
1036 for (UINT j=0; j<len; j++) 1036 for (UINT j=0; j<len; j++)
1037 { 1037 {
1038 int s_new = (signed char)(*p); 1038 int s_new = (signed char)(*p);
1039 p += sinc; 1039 p += sinc;
1040 if (pins->uFlags & CHN_STEREO) 1040 if (pins->uFlags & CHN_STEREO)
1041 { 1041 {
1042 s_new = (s_new + ((int)*p) + 1) >> 1; 1042 s_new = (s_new + ((int)*p) + 1) >> 1;
1043 p += sinc; 1043 p += sinc;
1044 } 1044 }
1045 if (nFlags == RS_PCM8D) 1045 if (nFlags == RS_PCM8D)
1046 { 1046 {
1047 buffer[bufcount++] = (signed char)(s_new - s_old); 1047 buffer[bufcount++] = (signed char)(s_new - s_old);
1048 s_old = s_new; 1048 s_old = s_new;
1049 } else 1049 } else
1050 { 1050 {
1051 buffer[bufcount++] = (signed char)(s_new + s_ofs); 1051 buffer[bufcount++] = (signed char)(s_new + s_ofs);
1052 } 1052 }
1053 if (bufcount >= sizeof(buffer)) 1053 if (bufcount >= sizeof(buffer))
1054 { 1054 {
1055 fwrite(buffer, 1, bufcount, f); 1055 fwrite(buffer, 1, bufcount, f);
1056 bufcount = 0; 1056 bufcount = 0;
1057 } 1057 }
1058 } 1058 }
1059 if (bufcount) fwrite(buffer, 1, bufcount, f); 1059 if (bufcount) fwrite(buffer, 1, bufcount, f);
1060 } 1060 }
1061 } 1061 }
1062 return len; 1062 return len;
1063} 1063}
1064 1064
1065#endif // MODPLUG_NO_FILESAVE 1065#endif // MODPLUG_NO_FILESAVE
1066 1066
1067 1067
1068// Flags: 1068// Flags:
1069 //0 = signed 8-bit PCM data (default) 1069 //0 = signed 8-bit PCM data (default)
1070 //1 = unsigned 8-bit PCM data 1070 //1 = unsigned 8-bit PCM data
1071 //2 = 8-bit ADPCM data with linear table 1071 //2 = 8-bit ADPCM data with linear table
1072 //3 = 4-bit ADPCM data 1072 //3 = 4-bit ADPCM data
1073 //4 = 16-bit ADPCM data with linear table 1073 //4 = 16-bit ADPCM data with linear table
1074 //5 = signed 16-bit PCM data 1074 //5 = signed 16-bit PCM data
1075 //6 = unsigned 16-bit PCM data 1075 //6 = unsigned 16-bit PCM data
1076 1076
1077 1077
1078UINT CSoundFile::ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR lpMemFile, DWORD dwMemLength) 1078UINT CSoundFile::ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR lpMemFile, DWORD dwMemLength)
1079//------------------------------------------------------------------------------------------------ 1079//------------------------------------------------------------------------------------------------
1080{ 1080{
1081 UINT len = 0, mem = pIns->nLength+6; 1081 UINT len = 0, mem = pIns->nLength+6;
1082 1082
1083 if ((!pIns) || (pIns->nLength < 4) || (!lpMemFile)) return 0; 1083 if ((!pIns) || (pIns->nLength < 4) || (!lpMemFile)) return 0;
1084 if (pIns->nLength > MAX_SAMPLE_LENGTH) pIns->nLength = MAX_SAMPLE_LENGTH; 1084 if (pIns->nLength > MAX_SAMPLE_LENGTH) pIns->nLength = MAX_SAMPLE_LENGTH;
1085 pIns->uFlags &= ~(CHN_16BIT|CHN_STEREO); 1085 pIns->uFlags &= ~(CHN_16BIT|CHN_STEREO);
1086 if (nFlags & RSF_16BIT) 1086 if (nFlags & RSF_16BIT)
1087 { 1087 {
1088 mem *= 2; 1088 mem *= 2;
1089 pIns->uFlags |= CHN_16BIT; 1089 pIns->uFlags |= CHN_16BIT;
1090 } 1090 }
1091 if (nFlags & RSF_STEREO) 1091 if (nFlags & RSF_STEREO)
1092 { 1092 {
1093 mem *= 2; 1093 mem *= 2;
1094 pIns->uFlags |= CHN_STEREO; 1094 pIns->uFlags |= CHN_STEREO;
1095 } 1095 }
1096 if ((pIns->pSample = AllocateSample(mem)) == NULL) 1096 if ((pIns->pSample = AllocateSample(mem)) == NULL)
1097 { 1097 {
1098 pIns->nLength = 0; 1098 pIns->nLength = 0;
1099 return 0; 1099 return 0;
1100 } 1100 }
1101 switch(nFlags) 1101 switch(nFlags)
1102 { 1102 {
1103 // 1: 8-bit unsigned PCM data 1103 // 1: 8-bit unsigned PCM data
1104 case RS_PCM8U: 1104 case RS_PCM8U:
1105 { 1105 {
1106 len = pIns->nLength; 1106 len = pIns->nLength;
1107 if (len > dwMemLength) len = pIns->nLength = dwMemLength; 1107 if (len > dwMemLength) len = pIns->nLength = dwMemLength;
1108 signed char *pSample = pIns->pSample; 1108 signed char *pSample = pIns->pSample;
1109 for (UINT j=0; j<len; j++) pSample[j] = (signed char)(lpMemFile[j] - 0x80); 1109 for (UINT j=0; j<len; j++) pSample[j] = (signed char)(lpMemFile[j] - 0x80);
1110 } 1110 }
1111 break; 1111 break;
1112 1112
1113 // 2: 8-bit ADPCM data with linear table 1113 // 2: 8-bit ADPCM data with linear table
1114 case RS_PCM8D: 1114 case RS_PCM8D:
1115 { 1115 {
1116 len = pIns->nLength; 1116 len = pIns->nLength;
1117 if (len > dwMemLength) break; 1117 if (len > dwMemLength) break;
1118 signed char *pSample = pIns->pSample; 1118 signed char *pSample = pIns->pSample;
1119 const signed char *p = (const signed char *)lpMemFile; 1119 const signed char *p = (const signed char *)lpMemFile;
1120 int delta = 0; 1120 int delta = 0;
1121 1121
1122 for (UINT j=0; j<len; j++) 1122 for (UINT j=0; j<len; j++)
1123 { 1123 {
1124 delta += p[j]; 1124 delta += p[j];
1125 *pSample++ = (signed char)delta; 1125 *pSample++ = (signed char)delta;
1126 } 1126 }
1127 } 1127 }
1128 break; 1128 break;
1129 1129
1130 // 3: 4-bit ADPCM data 1130 // 3: 4-bit ADPCM data
1131 case RS_ADPCM4: 1131 case RS_ADPCM4:
1132 { 1132 {
1133 len = (pIns->nLength + 1) / 2; 1133 len = (pIns->nLength + 1) / 2;
1134 if (len > dwMemLength - 16) break; 1134 if (len > dwMemLength - 16) break;
1135 memcpy(CompressionTable, lpMemFile, 16); 1135 memcpy(CompressionTable, lpMemFile, 16);
1136 lpMemFile += 16; 1136 lpMemFile += 16;
1137 signed char *pSample = pIns->pSample; 1137 signed char *pSample = pIns->pSample;
1138 signed char delta = 0; 1138 signed char delta = 0;
1139 for (UINT j=0; j<len; j++) 1139 for (UINT j=0; j<len; j++)
1140 { 1140 {
1141 BYTE b0 = (BYTE)lpMemFile[j]; 1141 BYTE b0 = (BYTE)lpMemFile[j];
1142 BYTE b1 = (BYTE)(lpMemFile[j] >> 4); 1142 BYTE b1 = (BYTE)(lpMemFile[j] >> 4);
1143 delta = (signed char)GetDeltaValue((int)delta, b0); 1143 delta = (signed char)GetDeltaValue((int)delta, b0);
1144 pSample[0] = delta; 1144 pSample[0] = delta;
1145 delta = (signed char)GetDeltaValue((int)delta, b1); 1145 delta = (signed char)GetDeltaValue((int)delta, b1);
1146 pSample[1] = delta; 1146 pSample[1] = delta;
1147 pSample += 2; 1147 pSample += 2;
1148 } 1148 }
1149 len += 16; 1149 len += 16;
1150 } 1150 }
1151 break; 1151 break;
1152 1152
1153 // 4: 16-bit ADPCM data with linear table 1153 // 4: 16-bit ADPCM data with linear table
1154 case RS_PCM16D: 1154 case RS_PCM16D:
1155 { 1155 {
1156 len = pIns->nLength * 2; 1156 len = pIns->nLength * 2;
1157 if (len > dwMemLength) break; 1157 if (len > dwMemLength) break;
1158 short int *pSample = (short int *)pIns->pSample; 1158 short int *pSample = (short int *)pIns->pSample;
1159 short int *p = (short int *)lpMemFile; 1159 short int *p = (short int *)lpMemFile;
1160 int delta16 = 0; 1160 int delta16 = 0;
1161 for (UINT j=0; j<len; j+=2) 1161 for (UINT j=0; j<len; j+=2)
1162 { 1162 {
1163 delta16 += bswapLE16(*p++); 1163 delta16 += bswapLE16(*p++);
1164 *pSample++ = (short int)delta16; 1164 *pSample++ = (short int)delta16;
1165 } 1165 }
1166 } 1166 }
1167 break; 1167 break;
1168 1168
1169 // 5: 16-bit signed PCM data 1169 // 5: 16-bit signed PCM data
1170 case RS_PCM16S: 1170 case RS_PCM16S:
1171 { 1171 {
1172 len = pIns->nLength * 2; 1172 len = pIns->nLength * 2;
1173 if (len <= dwMemLength) memcpy(pIns->pSample, lpMemFile, len); 1173 if (len <= dwMemLength) memcpy(pIns->pSample, lpMemFile, len);
1174 short int *pSample = (short int *)pIns->pSample; 1174 short int *pSample = (short int *)pIns->pSample;
1175 for (UINT j=0; j<len; j+=2) 1175 for (UINT j=0; j<len; j+=2)
1176 { 1176 {
1177 *pSample++ = bswapLE16(*pSample); 1177 *pSample++ = bswapLE16(*pSample);
1178 } 1178 }
1179 } 1179 }
1180 break; 1180 break;
1181 1181
1182 // 16-bit signed mono PCM motorola byte order 1182 // 16-bit signed mono PCM motorola byte order
1183 case RS_PCM16M: 1183 case RS_PCM16M:
1184 len = pIns->nLength * 2; 1184 len = pIns->nLength * 2;
1185 if (len > dwMemLength) len = dwMemLength & ~1; 1185 if (len > dwMemLength) len = dwMemLength & ~1;
1186 if (len > 1) 1186 if (len > 1)
1187 { 1187 {
1188 signed char *pSample = (signed char *)pIns->pSample; 1188 signed char *pSample = (signed char *)pIns->pSample;
1189 signed char *pSrc = (signed char *)lpMemFile; 1189 signed char *pSrc = (signed char *)lpMemFile;
1190 for (UINT j=0; j<len; j+=2) 1190 for (UINT j=0; j<len; j+=2)
1191 { 1191 {
1192 // pSample[j] = pSrc[j+1]; 1192 // pSample[j] = pSrc[j+1];
1193 // pSample[j+1] = pSrc[j]; 1193 // pSample[j+1] = pSrc[j];
1194 *((unsigned short *)(pSample+j)) = bswapBE16(*((unsigned short *)(pSrc+j))); 1194 *((unsigned short *)(pSample+j)) = bswapBE16(*((unsigned short *)(pSrc+j)));
1195 } 1195 }
1196 } 1196 }
1197 break; 1197 break;
1198 1198
1199 // 6: 16-bit unsigned PCM data 1199 // 6: 16-bit unsigned PCM data
1200 case RS_PCM16U: 1200 case RS_PCM16U:
1201 { 1201 {
1202 len = pIns->nLength * 2; 1202 len = pIns->nLength * 2;
1203 if (len > dwMemLength) break; 1203 if (len > dwMemLength) break;
1204 short int *pSample = (short int *)pIns->pSample; 1204 short int *pSample = (short int *)pIns->pSample;
1205 short int *pSrc = (short int *)lpMemFile; 1205 short int *pSrc = (short int *)lpMemFile;
1206 for (UINT j=0; j<len; j+=2) *pSample++ = bswapLE16(*(pSrc++)) - 0x8000; 1206 for (UINT j=0; j<len; j+=2) *pSample++ = bswapLE16(*(pSrc++)) - 0x8000;
1207 } 1207 }
1208 break; 1208 break;
1209 1209
1210 // 16-bit signed stereo big endian 1210 // 16-bit signed stereo big endian
1211 case RS_STPCM16M: 1211 case RS_STPCM16M:
1212 len = pIns->nLength * 2; 1212 len = pIns->nLength * 2;
1213 if (len*2 <= dwMemLength) 1213 if (len*2 <= dwMemLength)
1214 { 1214 {
1215 signed char *pSample = (signed char *)pIns->pSample; 1215 signed char *pSample = (signed char *)pIns->pSample;
1216 signed char *pSrc = (signed char *)lpMemFile; 1216 signed char *pSrc = (signed char *)lpMemFile;
1217 for (UINT j=0; j<len; j+=2) 1217 for (UINT j=0; j<len; j+=2)
1218 { 1218 {
1219 // pSample[j*2] = pSrc[j+1]; 1219 // pSample[j*2] = pSrc[j+1];
1220 // pSample[j*2+1] = pSrc[j]; 1220 // pSample[j*2+1] = pSrc[j];
1221 // pSample[j*2+2] = pSrc[j+1+len]; 1221 // pSample[j*2+2] = pSrc[j+1+len];
1222 // pSample[j*2+3] = pSrc[j+len]; 1222 // pSample[j*2+3] = pSrc[j+len];
1223 *((unsigned short *)(pSample+j*2)) = bswapBE16(*((unsigned short *)(pSrc+j))); 1223 *((unsigned short *)(pSample+j*2)) = bswapBE16(*((unsigned short *)(pSrc+j)));
1224 *((unsigned short *)(pSample+j*2+2)) = bswapBE16(*((unsigned short *)(pSrc+j+len))); 1224 *((unsigned short *)(pSample+j*2+2)) = bswapBE16(*((unsigned short *)(pSrc+j+len)));
1225 } 1225 }
1226 len *= 2; 1226 len *= 2;
1227 } 1227 }
1228 break; 1228 break;
1229 1229
1230 // 8-bit stereo samples 1230 // 8-bit stereo samples
1231 case RS_STPCM8S: 1231 case RS_STPCM8S:
1232 case RS_STPCM8U: 1232 case RS_STPCM8U:
1233 case RS_STPCM8D: 1233 case RS_STPCM8D:
1234 { 1234 {
1235 int iadd_l = 0, iadd_r = 0; 1235 int iadd_l = 0, iadd_r = 0;
1236 if (nFlags == RS_STPCM8U) { iadd_l = iadd_r = -128; } 1236 if (nFlags == RS_STPCM8U) { iadd_l = iadd_r = -128; }
1237 len = pIns->nLength; 1237 len = pIns->nLength;
1238 signed char *psrc = (signed char *)lpMemFile; 1238 signed char *psrc = (signed char *)lpMemFile;
1239 signed char *pSample = (signed char *)pIns->pSample; 1239 signed char *pSample = (signed char *)pIns->pSample;
1240 if (len*2 > dwMemLength) break; 1240 if (len*2 > dwMemLength) break;
1241 for (UINT j=0; j<len; j++) 1241 for (UINT j=0; j<len; j++)
1242 { 1242 {
1243 pSample[j*2] = (signed char)(psrc[0] + iadd_l); 1243 pSample[j*2] = (signed char)(psrc[0] + iadd_l);
1244 pSample[j*2+1] = (signed char)(psrc[len] + iadd_r); 1244 pSample[j*2+1] = (signed char)(psrc[len] + iadd_r);
1245 psrc++; 1245 psrc++;
1246 if (nFlags == RS_STPCM8D) 1246 if (nFlags == RS_STPCM8D)
1247 { 1247 {
1248 iadd_l = pSample[j*2]; 1248 iadd_l = pSample[j*2];
1249 iadd_r = pSample[j*2+1]; 1249 iadd_r = pSample[j*2+1];
1250 } 1250 }
1251 } 1251 }
1252 len *= 2; 1252 len *= 2;
1253 } 1253 }
1254 break; 1254 break;
1255 1255
1256 // 16-bit stereo samples 1256 // 16-bit stereo samples
1257 case RS_STPCM16S: 1257 case RS_STPCM16S:
1258 case RS_STPCM16U: 1258 case RS_STPCM16U:
1259 case RS_STPCM16D: 1259 case RS_STPCM16D:
1260 { 1260 {
1261 int iadd_l = 0, iadd_r = 0; 1261 int iadd_l = 0, iadd_r = 0;
1262 if (nFlags == RS_STPCM16U) { iadd_l = iadd_r = -0x8000; } 1262 if (nFlags == RS_STPCM16U) { iadd_l = iadd_r = -0x8000; }
1263 len = pIns->nLength; 1263 len = pIns->nLength;
1264 short int *psrc = (short int *)lpMemFile; 1264 short int *psrc = (short int *)lpMemFile;
1265 short int *pSample = (short int *)pIns->pSample; 1265 short int *pSample = (short int *)pIns->pSample;
1266 if (len*4 > dwMemLength) break; 1266 if (len*4 > dwMemLength) break;
1267 for (UINT j=0; j<len; j++) 1267 for (UINT j=0; j<len; j++)
1268 { 1268 {
1269 pSample[j*2] = (short int) (bswapLE16(psrc[0]) + iadd_l); 1269 pSample[j*2] = (short int) (bswapLE16(psrc[0]) + iadd_l);
1270 pSample[j*2+1] = (short int) (bswapLE16(psrc[len]) + iadd_r); 1270 pSample[j*2+1] = (short int) (bswapLE16(psrc[len]) + iadd_r);
1271 psrc++; 1271 psrc++;
1272 if (nFlags == RS_STPCM16D) 1272 if (nFlags == RS_STPCM16D)
1273 { 1273 {
1274 iadd_l = pSample[j*2]; 1274 iadd_l = pSample[j*2];
1275 iadd_r = pSample[j*2+1]; 1275 iadd_r = pSample[j*2+1];
1276 } 1276 }
1277 } 1277 }
1278 len *= 4; 1278 len *= 4;
1279 } 1279 }
1280 break; 1280 break;
1281 1281
1282 // IT 2.14 compressed samples 1282 // IT 2.14 compressed samples
1283 case RS_IT2148: 1283 case RS_IT2148:
1284 case RS_IT21416: 1284 case RS_IT21416:
1285 case RS_IT2158: 1285 case RS_IT2158:
1286 case RS_IT21516: 1286 case RS_IT21516:
1287 len = dwMemLength; 1287 len = dwMemLength;
1288 if (len < 4) break; 1288 if (len < 4) break;
1289 if ((nFlags == RS_IT2148) || (nFlags == RS_IT2158)) 1289 if ((nFlags == RS_IT2148) || (nFlags == RS_IT2158))
1290 ITUnpack8Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT2158)); 1290 ITUnpack8Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT2158));
1291 else 1291 else
1292 ITUnpack16Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT21516)); 1292 ITUnpack16Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT21516));
1293 break; 1293 break;
1294 1294
1295#ifndef MODPLUG_BASIC_SUPPORT 1295#ifndef MODPLUG_BASIC_SUPPORT
1296#ifndef FASTSOUNDLIB 1296#ifndef FASTSOUNDLIB
1297 // 8-bit interleaved stereo samples 1297 // 8-bit interleaved stereo samples
1298 case RS_STIPCM8S: 1298 case RS_STIPCM8S:
1299 case RS_STIPCM8U: 1299 case RS_STIPCM8U:
1300 { 1300 {
1301 int iadd = 0; 1301 int iadd = 0;
1302 if (nFlags == RS_STIPCM8U) { iadd = -0x80; } 1302 if (nFlags == RS_STIPCM8U) { iadd = -0x80; }
1303 len = pIns->nLength; 1303 len = pIns->nLength;
1304 if (len*2 > dwMemLength) len = dwMemLength >> 1; 1304 if (len*2 > dwMemLength) len = dwMemLength >> 1;
1305 LPBYTE psrc = (LPBYTE)lpMemFile; 1305 LPBYTE psrc = (LPBYTE)lpMemFile;
1306 LPBYTE pSample = (LPBYTE)pIns->pSample; 1306 LPBYTE pSample = (LPBYTE)pIns->pSample;
1307 for (UINT j=0; j<len; j++) 1307 for (UINT j=0; j<len; j++)
1308 { 1308 {
1309 pSample[j*2] = (signed char)(psrc[0] + iadd); 1309 pSample[j*2] = (signed char)(psrc[0] + iadd);
1310 pSample[j*2+1] = (signed char)(psrc[1] + iadd); 1310 pSample[j*2+1] = (signed char)(psrc[1] + iadd);
1311 psrc+=2; 1311 psrc+=2;
1312 } 1312 }
1313 len *= 2; 1313 len *= 2;
1314 } 1314 }
1315 break; 1315 break;
1316 1316
1317 // 16-bit interleaved stereo samples 1317 // 16-bit interleaved stereo samples
1318 case RS_STIPCM16S: 1318 case RS_STIPCM16S:
1319 case RS_STIPCM16U: 1319 case RS_STIPCM16U:
1320 { 1320 {
1321 int iadd = 0; 1321 int iadd = 0;
1322 if (nFlags == RS_STIPCM16U) iadd = -32768; 1322 if (nFlags == RS_STIPCM16U) iadd = -32768;
1323 len = pIns->nLength; 1323 len = pIns->nLength;
1324 if (len*4 > dwMemLength) len = dwMemLength >> 2; 1324 if (len*4 > dwMemLength) len = dwMemLength >> 2;
1325 short int *psrc = (short int *)lpMemFile; 1325 short int *psrc = (short int *)lpMemFile;
1326 short int *pSample = (short int *)pIns->pSample; 1326 short int *pSample = (short int *)pIns->pSample;
1327 for (UINT j=0; j<len; j++) 1327 for (UINT j=0; j<len; j++)
1328 { 1328 {
1329 pSample[j*2] = (short int)(bswapLE16(psrc[0]) + iadd); 1329 pSample[j*2] = (short int)(bswapLE16(psrc[0]) + iadd);
1330 pSample[j*2+1] = (short int)(bswapLE16(psrc[1]) + iadd); 1330 pSample[j*2+1] = (short int)(bswapLE16(psrc[1]) + iadd);
1331 psrc += 2; 1331 psrc += 2;
1332 } 1332 }
1333 len *= 4; 1333 len *= 4;
1334 } 1334 }
1335 break; 1335 break;
1336 1336
1337 // AMS compressed samples 1337 // AMS compressed samples
1338 case RS_AMS8: 1338 case RS_AMS8:
1339 case RS_AMS16: 1339 case RS_AMS16:
1340 len = 9; 1340 len = 9;
1341 if (dwMemLength > 9) 1341 if (dwMemLength > 9)
1342 { 1342 {
1343 const char *psrc = lpMemFile; 1343 const char *psrc = lpMemFile;
1344 char packcharacter = lpMemFile[8], *pdest = (char *)pIns->pSample; 1344 char packcharacter = lpMemFile[8], *pdest = (char *)pIns->pSample;
1345 len += bswapLE32(*((LPDWORD)(lpMemFile+4))); 1345 len += bswapLE32(*((LPDWORD)(lpMemFile+4)));
1346 if (len > dwMemLength) len = dwMemLength; 1346 if (len > dwMemLength) len = dwMemLength;
1347 UINT dmax = pIns->nLength; 1347 UINT dmax = pIns->nLength;
1348 if (pIns->uFlags & CHN_16BIT) dmax <<= 1; 1348 if (pIns->uFlags & CHN_16BIT) dmax <<= 1;
1349 AMSUnpack(psrc+9, len-9, pdest, dmax, packcharacter); 1349 AMSUnpack(psrc+9, len-9, pdest, dmax, packcharacter);
1350 } 1350 }
1351 break; 1351 break;
1352 1352
1353 // PTM 8bit delta to 16-bit sample 1353 // PTM 8bit delta to 16-bit sample
1354 case RS_PTM8DTO16: 1354 case RS_PTM8DTO16:
1355 { 1355 {
1356 len = pIns->nLength * 2; 1356 len = pIns->nLength * 2;
1357 if (len > dwMemLength) break; 1357 if (len > dwMemLength) break;
1358 signed char *pSample = (signed char *)pIns->pSample; 1358 signed char *pSample = (signed char *)pIns->pSample;
1359 signed char delta8 = 0; 1359 signed char delta8 = 0;
1360 for (UINT j=0; j<len; j++) 1360 for (UINT j=0; j<len; j++)
1361 { 1361 {
1362 delta8 += lpMemFile[j]; 1362 delta8 += lpMemFile[j];
1363 *pSample++ = delta8; 1363 *pSample++ = delta8;
1364 } 1364 }
1365 WORD *pSampleW = (WORD *)pIns->pSample; 1365 WORD *pSampleW = (WORD *)pIns->pSample;
1366 for (UINT j=0; j<len; j+=2) // swaparoni! 1366 for (UINT j=0; j<len; j+=2) // swaparoni!
1367 { 1367 {
1368 *pSampleW++ = bswapLE16(*pSampleW); 1368 *pSampleW++ = bswapLE16(*pSampleW);
1369 } 1369 }
1370 } 1370 }
1371 break; 1371 break;
1372 1372
1373 // Huffman MDL compressed samples 1373 // Huffman MDL compressed samples
1374 case RS_MDL8: 1374 case RS_MDL8:
1375 case RS_MDL16: 1375 case RS_MDL16:
1376 len = dwMemLength; 1376 len = dwMemLength;
1377 if (len >= 4) 1377 if (len >= 4)
1378 { 1378 {
1379 LPBYTE pSample = (LPBYTE)pIns->pSample; 1379 LPBYTE pSample = (LPBYTE)pIns->pSample;
1380 LPBYTE ibuf = (LPBYTE)lpMemFile; 1380 LPBYTE ibuf = (LPBYTE)lpMemFile;
1381 DWORD bitbuf = bswapLE32(*((DWORD *)ibuf)); 1381 DWORD bitbuf = bswapLE32(*((DWORD *)ibuf));
1382 UINT bitnum = 32; 1382 UINT bitnum = 32;
1383 BYTE dlt = 0, lowbyte = 0; 1383 BYTE dlt = 0, lowbyte = 0;
1384 ibuf += 4; 1384 ibuf += 4;
1385 for (UINT j=0; j<pIns->nLength; j++) 1385 for (UINT j=0; j<pIns->nLength; j++)
1386 { 1386 {
1387 BYTE hibyte; 1387 BYTE hibyte;
1388 BYTE sign; 1388 BYTE sign;
1389 if (nFlags == RS_MDL16) lowbyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 8); 1389 if (nFlags == RS_MDL16) lowbyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 8);
1390 sign = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 1); 1390 sign = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 1);
1391 if (MDLReadBits(bitbuf, bitnum, ibuf, 1)) 1391 if (MDLReadBits(bitbuf, bitnum, ibuf, 1))
1392 { 1392 {
1393 hibyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 3); 1393 hibyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 3);
1394 } else 1394 } else
1395 { 1395 {
1396 hibyte = 8; 1396 hibyte = 8;
1397 while (!MDLReadBits(bitbuf, bitnum, ibuf, 1)) hibyte += 0x10; 1397 while (!MDLReadBits(bitbuf, bitnum, ibuf, 1)) hibyte += 0x10;
1398 hibyte += MDLReadBits(bitbuf, bitnum, ibuf, 4); 1398 hibyte += MDLReadBits(bitbuf, bitnum, ibuf, 4);
1399 } 1399 }
1400 if (sign) hibyte = ~hibyte; 1400 if (sign) hibyte = ~hibyte;
1401 dlt += hibyte; 1401 dlt += hibyte;
1402 if (nFlags != RS_MDL16) 1402 if (nFlags != RS_MDL16)
1403 pSample[j] = dlt; 1403 pSample[j] = dlt;
1404 else 1404 else
1405 { 1405 {
1406 pSample[j<<1] = lowbyte; 1406 pSample[j<<1] = lowbyte;
1407 pSample[(j<<1)+1] = dlt; 1407 pSample[(j<<1)+1] = dlt;
1408 } 1408 }
1409 } 1409 }
1410 } 1410 }
1411 break; 1411 break;
1412 1412
1413 case RS_DMF8: 1413 case RS_DMF8:
1414 case RS_DMF16: 1414 case RS_DMF16:
1415 len = dwMemLength; 1415 len = dwMemLength;
1416 if (len >= 4) 1416 if (len >= 4)
1417 { 1417 {
1418 UINT maxlen = pIns->nLength; 1418 UINT maxlen = pIns->nLength;
1419 if (pIns->uFlags & CHN_16BIT) maxlen <<= 1; 1419 if (pIns->uFlags & CHN_16BIT) maxlen <<= 1;
1420 LPBYTE ibuf = (LPBYTE)lpMemFile, ibufmax = (LPBYTE)(lpMemFile+dwMemLength); 1420 LPBYTE ibuf = (LPBYTE)lpMemFile, ibufmax = (LPBYTE)(lpMemFile+dwMemLength);
1421 len = DMFUnpack((LPBYTE)pIns->pSample, ibuf, ibufmax, maxlen); 1421 len = DMFUnpack((LPBYTE)pIns->pSample, ibuf, ibufmax, maxlen);
1422 } 1422 }
1423 break; 1423 break;
1424 1424
1425#ifdef MODPLUG_TRACKER 1425#ifdef MODPLUG_TRACKER
1426 // PCM 24-bit signed -> load sample, and normalize it to 16-bit 1426 // PCM 24-bit signed -> load sample, and normalize it to 16-bit
1427 case RS_PCM24S: 1427 case RS_PCM24S:
1428 case RS_PCM32S: 1428 case RS_PCM32S:
1429 len = pIns->nLength * 3; 1429 len = pIns->nLength * 3;
1430 if (nFlags == RS_PCM32S) len += pIns->nLength; 1430 if (nFlags == RS_PCM32S) len += pIns->nLength;
1431 if (len > dwMemLength) break; 1431 if (len > dwMemLength) break;
1432 if (len > 4*8) 1432 if (len > 4*8)
1433 { 1433 {
1434 UINT slsize = (nFlags == RS_PCM32S) ? 4 : 3; 1434 UINT slsize = (nFlags == RS_PCM32S) ? 4 : 3;
1435 LPBYTE pSrc = (LPBYTE)lpMemFile; 1435 LPBYTE pSrc = (LPBYTE)lpMemFile;
1436 LONG max = 255; 1436 LONG max = 255;
1437 if (nFlags == RS_PCM32S) pSrc++; 1437 if (nFlags == RS_PCM32S) pSrc++;
1438 for (UINT j=0; j<len; j+=slsize) 1438 for (UINT j=0; j<len; j+=slsize)
1439 { 1439 {
1440 LONG l = ((((pSrc[j+2] << 8) + pSrc[j+1]) << 8) + pSrc[j]) << 8; 1440 LONG l = ((((pSrc[j+2] << 8) + pSrc[j+1]) << 8) + pSrc[j]) << 8;
1441 l /= 256; 1441 l /= 256;
1442 if (l > max) max = l; 1442 if (l > max) max = l;
1443 if (-l > max) max = -l; 1443 if (-l > max) max = -l;
1444 } 1444 }
1445 max = (max / 128) + 1; 1445 max = (max / 128) + 1;
1446 signed short *pDest = (signed short *)pIns->pSample; 1446 signed short *pDest = (signed short *)pIns->pSample;
1447 for (UINT k=0; k<len; k+=slsize) 1447 for (UINT k=0; k<len; k+=slsize)
1448 { 1448 {
1449 LONG l = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8; 1449 LONG l = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8;
1450 *pDest++ = (signed short)(l / max); 1450 *pDest++ = (signed short)(l / max);
1451 } 1451 }
1452 } 1452 }
1453 break; 1453 break;
1454 1454
1455 // Stereo PCM 24-bit signed -> load sample, and normalize it to 16-bit 1455 // Stereo PCM 24-bit signed -> load sample, and normalize it to 16-bit
1456 case RS_STIPCM24S: 1456 case RS_STIPCM24S:
1457 case RS_STIPCM32S: 1457 case RS_STIPCM32S:
1458 len = pIns->nLength * 6; 1458 len = pIns->nLength * 6;
1459 if (nFlags == RS_STIPCM32S) len += pIns->nLength * 2; 1459 if (nFlags == RS_STIPCM32S) len += pIns->nLength * 2;
1460 if (len > dwMemLength) break; 1460 if (len > dwMemLength) break;
1461 if (len > 8*8) 1461 if (len > 8*8)
1462 { 1462 {
1463 UINT slsize = (nFlags == RS_STIPCM32S) ? 4 : 3; 1463 UINT slsize = (nFlags == RS_STIPCM32S) ? 4 : 3;
1464 LPBYTE pSrc = (LPBYTE)lpMemFile; 1464 LPBYTE pSrc = (LPBYTE)lpMemFile;
1465 LONG max = 255; 1465 LONG max = 255;
1466 if (nFlags == RS_STIPCM32S) pSrc++; 1466 if (nFlags == RS_STIPCM32S) pSrc++;
1467 for (UINT j=0; j<len; j+=slsize) 1467 for (UINT j=0; j<len; j+=slsize)
1468 { 1468 {
1469 LONG l = ((((pSrc[j+2] << 8) + pSrc[j+1]) << 8) + pSrc[j]) << 8; 1469 LONG l = ((((pSrc[j+2] << 8) + pSrc[j+1]) << 8) + pSrc[j]) << 8;
1470 l /= 256; 1470 l /= 256;
1471 if (l > max) max = l; 1471 if (l > max) max = l;
1472 if (-l > max) max = -l; 1472 if (-l > max) max = -l;
1473 } 1473 }
1474 max = (max / 128) + 1; 1474 max = (max / 128) + 1;
1475 signed short *pDest = (signed short *)pIns->pSample; 1475 signed short *pDest = (signed short *)pIns->pSample;
1476 for (UINT k=0; k<len; k+=slsize) 1476 for (UINT k=0; k<len; k+=slsize)
1477 { 1477 {
1478 LONG lr = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8; 1478 LONG lr = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8;
1479 k += slsize; 1479 k += slsize;
1480 LONG ll = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8; 1480 LONG ll = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8;
1481 pDest[0] = (signed short)ll; 1481 pDest[0] = (signed short)ll;
1482 pDest[1] = (signed short)lr; 1482 pDest[1] = (signed short)lr;
1483 pDest += 2; 1483 pDest += 2;
1484 } 1484 }
1485 } 1485 }
1486 break; 1486 break;
1487 1487
1488 // 16-bit signed big endian interleaved stereo 1488 // 16-bit signed big endian interleaved stereo
1489 case RS_STIPCM16M: 1489 case RS_STIPCM16M:
1490 { 1490 {
1491 len = pIns->nLength; 1491 len = pIns->nLength;
1492 if (len*4 > dwMemLength) len = dwMemLength >> 2; 1492 if (len*4 > dwMemLength) len = dwMemLength >> 2;
1493 LPCBYTE psrc = (LPCBYTE)lpMemFile; 1493 LPCBYTE psrc = (LPCBYTE)lpMemFile;
1494 short int *pSample = (short int *)pIns->pSample; 1494 short int *pSample = (short int *)pIns->pSample;
1495 for (UINT j=0; j<len; j++) 1495 for (UINT j=0; j<len; j++)
1496 { 1496 {
1497 pSample[j*2] = (signed short)(((UINT)psrc[0] << 8) | (psrc[1])); 1497 pSample[j*2] = (signed short)(((UINT)psrc[0] << 8) | (psrc[1]));
1498 pSample[j*2+1] = (signed short)(((UINT)psrc[2] << 8) | (psrc[3])); 1498 pSample[j*2+1] = (signed short)(((UINT)psrc[2] << 8) | (psrc[3]));
1499 psrc += 4; 1499 psrc += 4;
1500 } 1500 }
1501 len *= 4; 1501 len *= 4;
1502 } 1502 }
1503 break; 1503 break;
1504 1504
1505#endif // MODPLUG_TRACKER 1505#endif // MODPLUG_TRACKER
1506#endif // !FASTSOUNDLIB 1506#endif // !FASTSOUNDLIB
1507#endif // !MODPLUG_BASIC_SUPPORT 1507#endif // !MODPLUG_BASIC_SUPPORT
1508 1508
1509 // Default: 8-bit signed PCM data 1509 // Default: 8-bit signed PCM data
1510 default: 1510 default:
1511 len = pIns->nLength; 1511 len = pIns->nLength;
1512 if (len > dwMemLength) len = pIns->nLength = dwMemLength; 1512 if (len > dwMemLength) len = pIns->nLength = dwMemLength;
1513 memcpy(pIns->pSample, lpMemFile, len); 1513 memcpy(pIns->pSample, lpMemFile, len);
1514 } 1514 }
1515 if (len > dwMemLength) 1515 if (len > dwMemLength)
1516 { 1516 {
1517 if (pIns->pSample) 1517 if (pIns->pSample)
1518 { 1518 {
1519 pIns->nLength = 0; 1519 pIns->nLength = 0;
1520 FreeSample(pIns->pSample); 1520 FreeSample(pIns->pSample);
1521 pIns->pSample = NULL; 1521 pIns->pSample = NULL;
1522 } 1522 }
1523 return 0; 1523 return 0;
1524 } 1524 }
1525 AdjustSampleLoop(pIns); 1525 AdjustSampleLoop(pIns);
1526 return len; 1526 return len;
1527} 1527}
1528 1528
1529 1529
1530void CSoundFile::AdjustSampleLoop(MODINSTRUMENT *pIns) 1530void CSoundFile::AdjustSampleLoop(MODINSTRUMENT *pIns)
1531//---------------------------------------------------- 1531//----------------------------------------------------
1532{ 1532{
1533 if (!pIns->pSample) return; 1533 if (!pIns->pSample) return;
1534 if (pIns->nLoopEnd > pIns->nLength) pIns->nLoopEnd = pIns->nLength; 1534 if (pIns->nLoopEnd > pIns->nLength) pIns->nLoopEnd = pIns->nLength;
1535 if (pIns->nLoopStart+2 >= pIns->nLoopEnd) 1535 if (pIns->nLoopStart+2 >= pIns->nLoopEnd)
1536 { 1536 {
1537 pIns->nLoopStart = pIns->nLoopEnd = 0; 1537 pIns->nLoopStart = pIns->nLoopEnd = 0;
1538 pIns->uFlags &= ~CHN_LOOP; 1538 pIns->uFlags &= ~CHN_LOOP;
1539 } 1539 }
1540 UINT len = pIns->nLength; 1540 UINT len = pIns->nLength;
1541 if (pIns->uFlags & CHN_16BIT) 1541 if (pIns->uFlags & CHN_16BIT)
1542 { 1542 {
1543 short int *pSample = (short int *)pIns->pSample; 1543 short int *pSample = (short int *)pIns->pSample;
1544 // Adjust end of sample 1544 // Adjust end of sample
1545 if (pIns->uFlags & CHN_STEREO) 1545 if (pIns->uFlags & CHN_STEREO)
1546 { 1546 {
1547 pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2]; 1547 pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2];
1548 pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1]; 1548 pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1];
1549 } else 1549 } else
1550 { 1550 {
1551 pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1]; 1551 pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1];
1552 } 1552 }
1553 if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) 1553 if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP)
1554 { 1554 {
1555 // Fix bad loops 1555 // Fix bad loops
1556 if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & MOD_TYPE_S3M)) 1556 if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & MOD_TYPE_S3M))
1557 { 1557 {
1558 pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart]; 1558 pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart];
1559 pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1]; 1559 pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1];
1560 pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2]; 1560 pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2];
1561 pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3]; 1561 pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3];
1562 pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4]; 1562 pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4];
1563 } 1563 }
1564 } 1564 }
1565 } else 1565 } else
1566 { 1566 {
1567 signed char *pSample = pIns->pSample; 1567 signed char *pSample = pIns->pSample;
1568#ifndef FASTSOUNDLIB 1568#ifndef FASTSOUNDLIB
1569 // Crappy samples (except chiptunes) ? 1569 // Crappy samples (except chiptunes) ?
1570 if ((pIns->nLength > 0x100) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M)) 1570 if ((pIns->nLength > 0x100) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M))
1571 && (!(pIns->uFlags & CHN_STEREO))) 1571 && (!(pIns->uFlags & CHN_STEREO)))
1572 { 1572 {
1573 int smpend = pSample[pIns->nLength-1], smpfix = 0, kscan; 1573 int smpend = pSample[pIns->nLength-1], smpfix = 0, kscan;
1574 for (kscan=pIns->nLength-1; kscan>0; kscan--) 1574 for (kscan=pIns->nLength-1; kscan>0; kscan--)
1575 { 1575 {
1576 smpfix = pSample[kscan-1]; 1576 smpfix = pSample[kscan-1];
1577 if (smpfix != smpend) break; 1577 if (smpfix != smpend) break;
1578 } 1578 }
1579 int delta = smpfix - smpend; 1579 int delta = smpfix - smpend;
1580 if (((!(pIns->uFlags & CHN_LOOP)) || (kscan > (int)pIns->nLoopEnd)) 1580 if (((!(pIns->uFlags & CHN_LOOP)) || (kscan > (int)pIns->nLoopEnd))
1581 && ((delta < -8) || (delta > 8))) 1581 && ((delta < -8) || (delta > 8)))
1582 { 1582 {
1583 while (kscan<(int)pIns->nLength) 1583 while (kscan<(int)pIns->nLength)
1584 { 1584 {
1585 if (!(kscan & 7)) 1585 if (!(kscan & 7))
1586 { 1586 {
1587 if (smpfix > 0) smpfix--; 1587 if (smpfix > 0) smpfix--;
1588 if (smpfix < 0) smpfix++; 1588 if (smpfix < 0) smpfix++;
1589 } 1589 }
1590 pSample[kscan] = (signed char)smpfix; 1590 pSample[kscan] = (signed char)smpfix;
1591 kscan++; 1591 kscan++;
1592 } 1592 }
1593 } 1593 }
1594 } 1594 }
1595#endif 1595#endif
1596 // Adjust end of sample 1596 // Adjust end of sample
1597 if (pIns->uFlags & CHN_STEREO) 1597 if (pIns->uFlags & CHN_STEREO)
1598 { 1598 {
1599 pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2]; 1599 pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2];
1600 pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1]; 1600 pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1];
1601 } else 1601 } else
1602 { 1602 {
1603 pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1]; 1603 pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1];
1604 } 1604 }
1605 if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) 1605 if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP)
1606 { 1606 {
1607 if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M))) 1607 if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M)))
1608 { 1608 {
1609 pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart]; 1609 pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart];
1610 pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1]; 1610 pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1];
1611 pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2]; 1611 pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2];
1612 pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3]; 1612 pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3];
1613 pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4]; 1613 pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4];
1614 } 1614 }
1615 } 1615 }
1616 } 1616 }
1617} 1617}
1618 1618
1619 1619
1620///////////////////////////////////////////////////////////// 1620/////////////////////////////////////////////////////////////
1621// Transpose <-> Frequency conversions 1621// Transpose <-> Frequency conversions
1622 1622
1623// returns 8363*2^((transp*128+ftune)/(12*128)) 1623// returns 8363*2^((transp*128+ftune)/(12*128))
1624DWORD CSoundFile::TransposeToFrequency(int transp, int ftune) 1624DWORD CSoundFile::TransposeToFrequency(int transp, int ftune)
1625//----------------------------------------------------------- 1625//-----------------------------------------------------------
1626{ 1626{
1627 //---GCCFIX: Removed assembly. 1627 //---GCCFIX: Removed assembly.
1628 return (DWORD)(8363*pow(2, (transp*128+ftune)/(1536))); 1628 return (DWORD)(8363*pow(2, (transp*128+ftune)/(1536)));
1629 1629
1630#ifdef WIN32 1630#ifdef WIN32
1631 const float _fbase = 8363; 1631 const float _fbase = 8363;
1632 const float _factor = 1.0f/(12.0f*128.0f); 1632 const float _factor = 1.0f/(12.0f*128.0f);
1633 int result; 1633 int result;
1634 DWORD freq; 1634 DWORD freq;
1635 1635
1636 transp = (transp << 7) + ftune; 1636 transp = (transp << 7) + ftune;
1637 _asm { 1637 _asm {
1638 fild transp 1638 fild transp
1639 fld _factor 1639 fld _factor
1640 fmulp st(1), st(0) 1640 fmulp st(1), st(0)
1641 fist result 1641 fist result
1642 fisub result 1642 fisub result
1643 f2xm1 1643 f2xm1
1644 fild result 1644 fild result
1645 fld _fbase 1645 fld _fbase
1646 fscale 1646 fscale
1647 fstp st(1) 1647 fstp st(1)
1648 fmul st(1), st(0) 1648 fmul st(1), st(0)
1649 faddp st(1), st(0) 1649 faddp st(1), st(0)
1650 fistp freq 1650 fistp freq
1651 } 1651 }
1652 UINT derr = freq % 11025; 1652 UINT derr = freq % 11025;
1653 if (derr <= 8) freq -= derr; 1653 if (derr <= 8) freq -= derr;
1654 if (derr >= 11015) freq += 11025-derr; 1654 if (derr >= 11015) freq += 11025-derr;
1655 derr = freq % 1000; 1655 derr = freq % 1000;
1656 if (derr <= 5) freq -= derr; 1656 if (derr <= 5) freq -= derr;
1657 if (derr >= 995) freq += 1000-derr; 1657 if (derr >= 995) freq += 1000-derr;
1658 return freq; 1658 return freq;
1659#endif 1659#endif
1660} 1660}
1661 1661
1662 1662
1663// returns 12*128*log2(freq/8363) 1663// returns 12*128*log2(freq/8363)
1664int CSoundFile::FrequencyToTranspose(DWORD freq) 1664int CSoundFile::FrequencyToTranspose(DWORD freq)
1665//---------------------------------------------- 1665//----------------------------------------------
1666{ 1666{
1667 //---GCCFIX: Removed assembly. 1667 //---GCCFIX: Removed assembly.
1668 return int(1536*(log(freq/8363)/log(2))); 1668 return int(1536*(log(freq/8363)/log(2)));
1669 1669
1670#ifdef WIN32 1670#ifdef WIN32
1671 const float _f1_8363 = 1.0f / 8363.0f; 1671 const float _f1_8363 = 1.0f / 8363.0f;
1672 const float _factor = 128 * 12; 1672 const float _factor = 128 * 12;
1673 LONG result; 1673 LONG result;
1674 1674
1675 if (!freq) return 0; 1675 if (!freq) return 0;
1676 _asm { 1676 _asm {
1677 fld _factor 1677 fld _factor
1678 fild freq 1678 fild freq
1679 fld _f1_8363 1679 fld _f1_8363
1680 fmulp st(1), st(0) 1680 fmulp st(1), st(0)
1681 fyl2x 1681 fyl2x
1682 fistp result 1682 fistp result
1683 } 1683 }
1684 return result; 1684 return result;
1685#endif 1685#endif
1686} 1686}
1687 1687
1688 1688
1689void CSoundFile::FrequencyToTranspose(MODINSTRUMENT *psmp) 1689void CSoundFile::FrequencyToTranspose(MODINSTRUMENT *psmp)
1690//-------------------------------------------------------- 1690//--------------------------------------------------------
1691{ 1691{
1692 int f2t = FrequencyToTranspose(psmp->nC4Speed); 1692 int f2t = FrequencyToTranspose(psmp->nC4Speed);
1693 int transp = f2t >> 7; 1693 int transp = f2t >> 7;
1694 int ftune = f2t & 0x7F; 1694 int ftune = f2t & 0x7F;
1695 if (ftune > 80) 1695 if (ftune > 80)
1696 { 1696 {
1697 transp++; 1697 transp++;
1698 ftune -= 128; 1698 ftune -= 128;
1699 } 1699 }
1700 if (transp > 127) transp = 127; 1700 if (transp > 127) transp = 127;
1701 if (transp < -127) transp = -127; 1701 if (transp < -127) transp = -127;
1702 psmp->RelativeTone = transp; 1702 psmp->RelativeTone = transp;
1703 psmp->nFineTune = ftune; 1703 psmp->nFineTune = ftune;
1704} 1704}
1705 1705
1706 1706
1707void CSoundFile::CheckCPUUsage(UINT nCPU) 1707void CSoundFile::CheckCPUUsage(UINT nCPU)
1708//--------------------------------------- 1708//---------------------------------------
1709{ 1709{
1710 if (nCPU > 100) nCPU = 100; 1710 if (nCPU > 100) nCPU = 100;
1711 gnCPUUsage = nCPU; 1711 gnCPUUsage = nCPU;
1712 if (nCPU < 90) 1712 if (nCPU < 90)
1713 { 1713 {
1714 m_dwSongFlags &= ~SONG_CPUVERYHIGH; 1714 m_dwSongFlags &= ~SONG_CPUVERYHIGH;
1715 } else 1715 } else
1716 if ((m_dwSongFlags & SONG_CPUVERYHIGH) && (nCPU >= 94)) 1716 if ((m_dwSongFlags & SONG_CPUVERYHIGH) && (nCPU >= 94))
1717 { 1717 {
1718 UINT i=MAX_CHANNELS; 1718 UINT i=MAX_CHANNELS;
1719 while (i >= 8) 1719 while (i >= 8)
1720 { 1720 {
1721 i--; 1721 i--;
1722 if (Chn[i].nLength) 1722 if (Chn[i].nLength)
1723 { 1723 {
1724 Chn[i].nLength = Chn[i].nPos = 0; 1724 Chn[i].nLength = Chn[i].nPos = 0;
1725 nCPU -= 2; 1725 nCPU -= 2;
1726 if (nCPU < 94) break; 1726 if (nCPU < 94) break;
1727 } 1727 }
1728 } 1728 }
1729 } else 1729 } else
1730 if (nCPU > 90) 1730 if (nCPU > 90)
1731 { 1731 {
1732 m_dwSongFlags |= SONG_CPUVERYHIGH; 1732 m_dwSongFlags |= SONG_CPUVERYHIGH;
1733 } 1733 }
1734} 1734}
1735 1735
1736 1736
1737BOOL CSoundFile::SetPatternName(UINT nPat, LPCSTR lpszName) 1737BOOL CSoundFile::SetPatternName(UINT nPat, LPCSTR lpszName)
1738//--------------------------------------------------------- 1738//---------------------------------------------------------
1739{ 1739{
1740 char szName[MAX_PATTERNNAME] = ""; // changed from CHAR 1740 char szName[MAX_PATTERNNAME] = ""; // changed from CHAR
1741 if (nPat >= MAX_PATTERNS) return FALSE; 1741 if (nPat >= MAX_PATTERNS) return FALSE;
1742 if (lpszName) lstrcpyn(szName, lpszName, MAX_PATTERNNAME); 1742 if (lpszName)
1743 lstrcpyn(szName, lpszName, MAX_PATTERNNAME);
1744 else
1745 return FALSE;
1743 szName[MAX_PATTERNNAME-1] = 0; 1746 szName[MAX_PATTERNNAME-1] = 0;
1744 if (!m_lpszPatternNames) m_nPatternNames = 0; 1747 if (!m_lpszPatternNames) m_nPatternNames = 0;
1745 if (nPat >= m_nPatternNames) 1748 if (nPat >= m_nPatternNames)
1746 { 1749 {
1747 if (!lpszName[0]) return TRUE; 1750 if (!lpszName[0]) return TRUE;
1748 UINT len = (nPat+1)*MAX_PATTERNNAME; 1751 UINT len = (nPat+1)*MAX_PATTERNNAME;
1749 char *p = new char[len]; // changed from CHAR 1752 char *p = new char[len]; // changed from CHAR
1750 if (!p) return FALSE; 1753 if (!p) return FALSE;
1751 memset(p, 0, len); 1754 memset(p, 0, len);
1752 if (m_lpszPatternNames) 1755 if (m_lpszPatternNames)
1753 { 1756 {
1754 memcpy(p, m_lpszPatternNames, m_nPatternNames * MAX_PATTERNNAME); 1757 memcpy(p, m_lpszPatternNames, m_nPatternNames * MAX_PATTERNNAME);
1755 delete m_lpszPatternNames; 1758 delete m_lpszPatternNames;
1756 m_lpszPatternNames = NULL; 1759 m_lpszPatternNames = NULL;
1757 } 1760 }
1758 m_lpszPatternNames = p; 1761 m_lpszPatternNames = p;
1759 m_nPatternNames = nPat + 1; 1762 m_nPatternNames = nPat + 1;
1760 } 1763 }
1761 memcpy(m_lpszPatternNames + nPat * MAX_PATTERNNAME, szName, MAX_PATTERNNAME); 1764 memcpy(m_lpszPatternNames + nPat * MAX_PATTERNNAME, szName, MAX_PATTERNNAME);
1762 return TRUE; 1765 return TRUE;
1763} 1766}
1764 1767
1765 1768
1766BOOL CSoundFile::GetPatternName(UINT nPat, LPSTR lpszName, UINT cbSize) const 1769BOOL CSoundFile::GetPatternName(UINT nPat, LPSTR lpszName, UINT cbSize) const
1767//--------------------------------------------------------------------------- 1770//---------------------------------------------------------------------------
1768{ 1771{
1769 if ((!lpszName) || (!cbSize)) return FALSE; 1772 if ((!lpszName) || (!cbSize)) return FALSE;
1770 lpszName[0] = 0; 1773 lpszName[0] = 0;
1771 if (cbSize > MAX_PATTERNNAME) cbSize = MAX_PATTERNNAME; 1774 if (cbSize > MAX_PATTERNNAME) cbSize = MAX_PATTERNNAME;
1772 if ((m_lpszPatternNames) && (nPat < m_nPatternNames)) 1775 if ((m_lpszPatternNames) && (nPat < m_nPatternNames))
1773 { 1776 {
1774 memcpy(lpszName, m_lpszPatternNames + nPat * MAX_PATTERNNAME, cbSize); 1777 memcpy(lpszName, m_lpszPatternNames + nPat * MAX_PATTERNNAME, cbSize);
1775 lpszName[cbSize-1] = 0; 1778 lpszName[cbSize-1] = 0;
1776 return TRUE; 1779 return TRUE;
1777 } 1780 }
1778 return FALSE; 1781 return FALSE;
1779} 1782}
1780 1783
1781 1784
1782#ifndef FASTSOUNDLIB 1785#ifndef FASTSOUNDLIB
1783 1786
1784UINT CSoundFile::DetectUnusedSamples(BOOL *pbIns) 1787UINT CSoundFile::DetectUnusedSamples(BOOL *pbIns)
1785//----------------------------------------------- 1788//-----------------------------------------------
1786{ 1789{
1787 UINT nExt = 0; 1790 UINT nExt = 0;
1788 1791
1789 if (!pbIns) return 0; 1792 if (!pbIns) return 0;
1790 if (m_nInstruments) 1793 if (m_nInstruments)
1791 { 1794 {
1792 memset(pbIns, 0, MAX_SAMPLES * sizeof(BOOL)); 1795 memset(pbIns, 0, MAX_SAMPLES * sizeof(BOOL));
1793 for (UINT ipat=0; ipat<MAX_PATTERNS; ipat++) 1796 for (UINT ipat=0; ipat<MAX_PATTERNS; ipat++)
1794 { 1797 {
1795 MODCOMMAND *p = Patterns[ipat]; 1798 MODCOMMAND *p = Patterns[ipat];
1796 if (p) 1799 if (p)
1797 { 1800 {
1798 UINT jmax = PatternSize[ipat] * m_nChannels; 1801 UINT jmax = PatternSize[ipat] * m_nChannels;
1799 for (UINT j=0; j<jmax; j++, p++) 1802 for (UINT j=0; j<jmax; j++, p++)
1800 { 1803 {
1801 if ((p->note) && (p->note <= 120)) 1804 if ((p->note) && (p->note <= 120))
1802 { 1805 {
1803 if ((p->instr) && (p->instr < MAX_INSTRUMENTS)) 1806 if ((p->instr) && (p->instr < MAX_INSTRUMENTS))
1804 { 1807 {
1805 INSTRUMENTHEADER *penv = Headers[p->instr]; 1808 INSTRUMENTHEADER *penv = Headers[p->instr];
1806 if (penv) 1809 if (penv)
1807 { 1810 {
1808 UINT n = penv->Keyboard[p->note-1]; 1811 UINT n = penv->Keyboard[p->note-1];
1809 if (n < MAX_SAMPLES) pbIns[n] = TRUE; 1812 if (n < MAX_SAMPLES) pbIns[n] = TRUE;
1810 } 1813 }
1811 } else 1814 } else
1812 { 1815 {
1813 for (UINT k=1; k<=m_nInstruments; k++) 1816 for (UINT k=1; k<=m_nInstruments; k++)
1814 { 1817 {
1815 INSTRUMENTHEADER *penv = Headers[k]; 1818 INSTRUMENTHEADER *penv = Headers[k];
1816 if (penv) 1819 if (penv)
1817 { 1820 {
1818 UINT n = penv->Keyboard[p->note-1]; 1821 UINT n = penv->Keyboard[p->note-1];
1819 if (n < MAX_SAMPLES) pbIns[n] = TRUE; 1822 if (n < MAX_SAMPLES) pbIns[n] = TRUE;
1820 } 1823 }
1821 } 1824 }
1822 } 1825 }
1823 } 1826 }
1824 } 1827 }
1825 } 1828 }
1826 } 1829 }
1827 for (UINT ichk=1; ichk<=m_nSamples; ichk++) 1830 for (UINT ichk=1; ichk<=m_nSamples; ichk++)
1828 { 1831 {
1829 if ((!pbIns[ichk]) && (Ins[ichk].pSample)) nExt++; 1832 if ((!pbIns[ichk]) && (Ins[ichk].pSample)) nExt++;
1830 } 1833 }
1831 } 1834 }
1832 return nExt; 1835 return nExt;
1833} 1836}
1834 1837
1835 1838
1836BOOL CSoundFile::RemoveSelectedSamples(BOOL *pbIns) 1839BOOL CSoundFile::RemoveSelectedSamples(BOOL *pbIns)
1837//------------------------------------------------- 1840//-------------------------------------------------
1838{ 1841{
1839 if (!pbIns) return FALSE; 1842 if (!pbIns) return FALSE;
1840 for (UINT j=1; j<MAX_SAMPLES; j++) 1843 for (UINT j=1; j<MAX_SAMPLES; j++)
1841 { 1844 {
1842 if ((!pbIns[j]) && (Ins[j].pSample)) 1845 if ((!pbIns[j]) && (Ins[j].pSample))
1843 { 1846 {
1844 DestroySample(j); 1847 DestroySample(j);
1845 if ((j == m_nSamples) && (j > 1)) m_nSamples--; 1848 if ((j == m_nSamples) && (j > 1)) m_nSamples--;
1846 } 1849 }
1847 } 1850 }
1848 return TRUE; 1851 return TRUE;
1849} 1852}
1850 1853
1851 1854
1852BOOL CSoundFile::DestroySample(UINT nSample) 1855BOOL CSoundFile::DestroySample(UINT nSample)
1853//------------------------------------------ 1856//------------------------------------------
1854{ 1857{
1855 if ((!nSample) || (nSample >= MAX_SAMPLES)) return FALSE; 1858 if ((!nSample) || (nSample >= MAX_SAMPLES)) return FALSE;
1856 if (!Ins[nSample].pSample) return TRUE; 1859 if (!Ins[nSample].pSample) return TRUE;
1857 MODINSTRUMENT *pins = &Ins[nSample]; 1860 MODINSTRUMENT *pins = &Ins[nSample];
1858 signed char *pSample = pins->pSample; 1861 signed char *pSample = pins->pSample;
1859 pins->pSample = NULL; 1862 pins->pSample = NULL;
1860 pins->nLength = 0; 1863 pins->nLength = 0;
1861 pins->uFlags &= ~(CHN_16BIT); 1864 pins->uFlags &= ~(CHN_16BIT);
1862 for (UINT i=0; i<MAX_CHANNELS; i++) 1865 for (UINT i=0; i<MAX_CHANNELS; i++)
1863 { 1866 {
1864 if (Chn[i].pSample == pSample) 1867 if (Chn[i].pSample == pSample)
1865 { 1868 {
1866 Chn[i].nPos = Chn[i].nLength = 0; 1869 Chn[i].nPos = Chn[i].nLength = 0;
1867 Chn[i].pSample = Chn[i].pCurrentSample = NULL; 1870 Chn[i].pSample = Chn[i].pCurrentSample = NULL;
1868 } 1871 }
1869 } 1872 }
1870 FreeSample(pSample); 1873 FreeSample(pSample);
1871 return TRUE; 1874 return TRUE;
1872} 1875}
1873 1876
1874#endif // FASTSOUNDLIB 1877#endif // FASTSOUNDLIB
1875 1878
diff --git a/core/multimedia/opieplayer/vorbis/tremor/block.c b/core/multimedia/opieplayer/vorbis/tremor/block.c
index 8949253..7b5531b 100644
--- a/core/multimedia/opieplayer/vorbis/tremor/block.c
+++ b/core/multimedia/opieplayer/vorbis/tremor/block.c
@@ -1,453 +1,455 @@
1/******************************************************************** 1/********************************************************************
2 * * 2 * *
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * 3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
4 * * 4 * *
5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * * 8 * *
9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * 9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * 10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
11 * * 11 * *
12 ******************************************************************** 12 ********************************************************************
13 13
14 function: PCM data vector blocking, windowing and dis/reassembly 14 function: PCM data vector blocking, windowing and dis/reassembly
15 15
16 ********************************************************************/ 16 ********************************************************************/
17 17
18#include <stdio.h> 18#include <stdio.h>
19#include <stdlib.h> 19#include <stdlib.h>
20#include <string.h> 20#include <string.h>
21#include "ogg.h" 21#include "ogg.h"
22#include "ivorbiscodec.h" 22#include "ivorbiscodec.h"
23#include "codec_internal.h" 23#include "codec_internal.h"
24 24
25#include "window.h" 25#include "window.h"
26#include "registry.h" 26#include "registry.h"
27#include "misc.h" 27#include "misc.h"
28 28
29static int ilog(unsigned int v){ 29static int ilog(unsigned int v){
30 int ret=0; 30 int ret=0;
31 if(v)--v; 31 if(v)--v;
32 while(v){ 32 while(v){
33 ret++; 33 ret++;
34 v>>=1; 34 v>>=1;
35 } 35 }
36 return(ret); 36 return(ret);
37} 37}
38 38
39/* pcm accumulator examples (not exhaustive): 39/* pcm accumulator examples (not exhaustive):
40 40
41 <-------------- lW ----------------> 41 <-------------- lW ---------------->
42 <--------------- W ----------------> 42 <--------------- W ---------------->
43: .....|..... _______________ | 43: .....|..... _______________ |
44: .''' | '''_--- | |\ | 44: .''' | '''_--- | |\ |
45:.....''' |_____--- '''......| | \_______| 45:.....''' |_____--- '''......| | \_______|
46:.................|__________________|_______|__|______| 46:.................|__________________|_______|__|______|
47 |<------ Sl ------>| > Sr < |endW 47 |<------ Sl ------>| > Sr < |endW
48 |beginSl |endSl | |endSr 48 |beginSl |endSl | |endSr
49 |beginW |endlW |beginSr 49 |beginW |endlW |beginSr
50 50
51 51
52 |< lW >| 52 |< lW >|
53 <--------------- W ----------------> 53 <--------------- W ---------------->
54 | | .. ______________ | 54 | | .. ______________ |
55 | | ' `/ | ---_ | 55 | | ' `/ | ---_ |
56 |___.'___/`. | ---_____| 56 |___.'___/`. | ---_____|
57 |_______|__|_______|_________________| 57 |_______|__|_______|_________________|
58 | >|Sl|< |<------ Sr ----->|endW 58 | >|Sl|< |<------ Sr ----->|endW
59 | | |endSl |beginSr |endSr 59 | | |endSl |beginSr |endSr
60 |beginW | |endlW 60 |beginW | |endlW
61 mult[0] |beginSl mult[n] 61 mult[0] |beginSl mult[n]
62 62
63 <-------------- lW -----------------> 63 <-------------- lW ----------------->
64 |<--W-->| 64 |<--W-->|
65: .............. ___ | | 65: .............. ___ | |
66: .''' |`/ \ | | 66: .''' |`/ \ | |
67:.....''' |/`....\|...| 67:.....''' |/`....\|...|
68:.........................|___|___|___| 68:.........................|___|___|___|
69 |Sl |Sr |endW 69 |Sl |Sr |endW
70 | | |endSr 70 | | |endSr
71 | |beginSr 71 | |beginSr
72 | |endSl 72 | |endSl
73 |beginSl 73 |beginSl
74 |beginW 74 |beginW
75*/ 75*/
76 76
77/* block abstraction setup *********************************************/ 77/* block abstraction setup *********************************************/
78 78
79#ifndef WORD_ALIGN 79#ifndef WORD_ALIGN
80#define WORD_ALIGN 8 80#define WORD_ALIGN 8
81#endif 81#endif
82 82
83int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){ 83int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
84 memset(vb,0,sizeof(*vb)); 84 memset(vb,0,sizeof(*vb));
85 vb->vd=v; 85 vb->vd=v;
86 vb->localalloc=0; 86 vb->localalloc=0;
87 vb->localstore=NULL; 87 vb->localstore=NULL;
88 88
89 return(0); 89 return(0);
90} 90}
91 91
92void *_vorbis_block_alloc(vorbis_block *vb,long bytes){ 92void *_vorbis_block_alloc(vorbis_block *vb,long bytes){
93 bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1); 93 bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1);
94 if(bytes+vb->localtop>vb->localalloc){ 94 if(bytes+vb->localtop>vb->localalloc){
95 /* can't just _ogg_realloc... there are outstanding pointers */ 95 /* can't just _ogg_realloc... there are outstanding pointers */
96 if(vb->localstore){ 96 if(vb->localstore){
97 struct alloc_chain *link=(struct alloc_chain *)_ogg_malloc(sizeof(*link)); 97 struct alloc_chain *link=(struct alloc_chain *)_ogg_malloc(sizeof(*link));
98 vb->totaluse+=vb->localtop; 98 vb->totaluse+=vb->localtop;
99 link->next=vb->reap; 99 link->next=vb->reap;
100 link->ptr=vb->localstore; 100 link->ptr=vb->localstore;
101 vb->reap=link; 101 vb->reap=link;
102 } 102 }
103 /* highly conservative */ 103 /* highly conservative */
104 vb->localalloc=bytes; 104 vb->localalloc=bytes;
105 vb->localstore=_ogg_malloc(vb->localalloc); 105 vb->localstore=_ogg_malloc(vb->localalloc);
106 vb->localtop=0; 106 vb->localtop=0;
107 } 107 }
108 { 108 {
109 void *ret=(void *)(((char *)vb->localstore)+vb->localtop); 109 void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
110 vb->localtop+=bytes; 110 vb->localtop+=bytes;
111 return ret; 111 return ret;
112 } 112 }
113} 113}
114 114
115/* reap the chain, pull the ripcord */ 115/* reap the chain, pull the ripcord */
116void _vorbis_block_ripcord(vorbis_block *vb){ 116void _vorbis_block_ripcord(vorbis_block *vb){
117 /* reap the chain */ 117 /* reap the chain */
118 struct alloc_chain *reap=vb->reap; 118 struct alloc_chain *reap=vb->reap;
119 while(reap){ 119 while(reap){
120 struct alloc_chain *next=reap->next; 120 struct alloc_chain *next=reap->next;
121 _ogg_free(reap->ptr); 121 _ogg_free(reap->ptr);
122 memset(reap,0,sizeof(*reap)); 122 memset(reap,0,sizeof(*reap));
123 _ogg_free(reap); 123 _ogg_free(reap);
124 reap=next; 124 reap=next;
125 } 125 }
126 /* consolidate storage */ 126 /* consolidate storage */
127 if(vb->totaluse){ 127 if(vb->totaluse){
128 vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc); 128 vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc);
129 vb->localalloc+=vb->totaluse; 129 vb->localalloc+=vb->totaluse;
130 vb->totaluse=0; 130 vb->totaluse=0;
131 } 131 }
132 132
133 /* pull the ripcord */ 133 /* pull the ripcord */
134 vb->localtop=0; 134 vb->localtop=0;
135 vb->reap=NULL; 135 vb->reap=NULL;
136} 136}
137 137
138int vorbis_block_clear(vorbis_block *vb){ 138int vorbis_block_clear(vorbis_block *vb){
139 _vorbis_block_ripcord(vb); 139 _vorbis_block_ripcord(vb);
140 if(vb->localstore)_ogg_free(vb->localstore); 140 if(vb->localstore)_ogg_free(vb->localstore);
141 141
142 memset(vb,0,sizeof(*vb)); 142 memset(vb,0,sizeof(*vb));
143 return(0); 143 return(0);
144} 144}
145 145
146static int _vds_init(vorbis_dsp_state *v,vorbis_info *vi){ 146static int _vds_init(vorbis_dsp_state *v,vorbis_info *vi){
147 int i; 147 int i;
148 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 148 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
149 private_state *b=NULL; 149 private_state *b=NULL;
150 150
151 memset(v,0,sizeof(*v)); 151 memset(v,0,sizeof(*v));
152 b=(private_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b))); 152 b=(private_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b)));
153 153
154 v->vi=vi; 154 v->vi=vi;
155 b->modebits=ilog(ci->modes); 155 b->modebits=ilog(ci->modes);
156 156
157 /* Vorbis I uses only window type 0 */ 157 /* Vorbis I uses only window type 0 */
158 b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2); 158 b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2);
159 b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2); 159 b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2);
160 160
161 /* finish the codebooks */ 161 /* finish the codebooks */
162 if(!ci->fullbooks){ 162 if(!ci->fullbooks){
163 ci->fullbooks=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); 163 ci->fullbooks=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
164 for(i=0;i<ci->books;i++){ 164 for(i=0;i<ci->books;i++){
165 vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]); 165 vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]);
166 /* decode codebooks are now standalone after init */ 166 /* decode codebooks are now standalone after init */
167 vorbis_staticbook_destroy(ci->book_param[i]); 167 vorbis_staticbook_destroy(ci->book_param[i]);
168 ci->book_param[i]=NULL; 168 ci->book_param[i]=NULL;
169 } 169 }
170 } 170 }
171 171
172 v->pcm_storage=ci->blocksizes[1]; 172 v->pcm_storage=ci->blocksizes[1];
173 v->pcm=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcm)); 173 v->pcm=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcm));
174 v->pcmret=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcmret)); 174 v->pcmret=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcmret));
175 for(i=0;i<vi->channels;i++) 175 for(i=0;i<vi->channels;i++)
176 v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i])); 176 v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
177 177
178 /* all 1 (large block) or 0 (small block) */ 178 /* all 1 (large block) or 0 (small block) */
179 /* explicitly set for the sake of clarity */ 179 /* explicitly set for the sake of clarity */
180 v->lW=0; /* previous window size */ 180 v->lW=0; /* previous window size */
181 v->W=0; /* current window size */ 181 v->W=0; /* current window size */
182 182
183 /* initialize all the mapping/backend lookups */ 183 /* initialize all the mapping/backend lookups */
184 b->mode=(vorbis_look_mapping **)_ogg_calloc(ci->modes,sizeof(*b->mode)); 184 b->mode=(vorbis_look_mapping **)_ogg_calloc(ci->modes,sizeof(*b->mode));
185 for(i=0;i<ci->modes;i++){ 185 for(i=0;i<ci->modes;i++){
186 int mapnum=ci->mode_param[i]->mapping; 186 int mapnum=ci->mode_param[i]->mapping;
187 int maptype=ci->map_type[mapnum]; 187 int maptype=ci->map_type[mapnum];
188 b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i], 188 b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i],
189 ci->map_param[mapnum]); 189 ci->map_param[mapnum]);
190 } 190 }
191 return(0); 191 return(0);
192} 192}
193 193
194int vorbis_synthesis_restart(vorbis_dsp_state *v){ 194int vorbis_synthesis_restart(vorbis_dsp_state *v){
195 vorbis_info *vi=v->vi; 195 vorbis_info *vi=v->vi;
196 codec_setup_info *ci; 196 codec_setup_info *ci;
197 197
198 if(!v->backend_state)return -1; 198 if(!v->backend_state)return -1;
199 if(!vi)return -1; 199 if(!vi)return -1;
200 ci=vi->codec_setup; 200 ci=vi->codec_setup;
201 if(!ci)return -1; 201 if(!ci)return -1;
202 202
203 v->centerW=ci->blocksizes[1]/2; 203 v->centerW=ci->blocksizes[1]/2;
204 v->pcm_current=v->centerW; 204 v->pcm_current=v->centerW;
205 205
206 v->pcm_returned=-1; 206 v->pcm_returned=-1;
207 v->granulepos=-1; 207 v->granulepos=-1;
208 v->sequence=-1; 208 v->sequence=-1;
209 ((private_state *)(v->backend_state))->sample_count=-1; 209 ((private_state *)(v->backend_state))->sample_count=-1;
210 210
211 return(0); 211 return(0);
212} 212}
213 213
214int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ 214int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
215 _vds_init(v,vi); 215 _vds_init(v,vi);
216 vorbis_synthesis_restart(v); 216 vorbis_synthesis_restart(v);
217 217
218 return(0); 218 return(0);
219} 219}
220 220
221void vorbis_dsp_clear(vorbis_dsp_state *v){ 221void vorbis_dsp_clear(vorbis_dsp_state *v){
222 int i; 222 int i;
223 if(v){ 223 if(v){
224 vorbis_info *vi=v->vi; 224 vorbis_info *vi=v->vi;
225 codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL); 225 codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL);
226 private_state *b=(private_state *)v->backend_state; 226 private_state *b=(private_state *)v->backend_state;
227 227
228 if(v->pcm){ 228 if(v->pcm){
229 for(i=0;i<vi->channels;i++) 229 if (vi) {
230 if(v->pcm[i])_ogg_free(v->pcm[i]); 230 for(i=0;i<vi->channels;i++)
231 if(v->pcm[i])_ogg_free(v->pcm[i]);
232 }
231 _ogg_free(v->pcm); 233 _ogg_free(v->pcm);
232 if(v->pcmret)_ogg_free(v->pcmret); 234 if(v->pcmret)_ogg_free(v->pcmret);
233 } 235 }
234 236
235 /* free mode lookups; these are actually vorbis_look_mapping structs */ 237 /* free mode lookups; these are actually vorbis_look_mapping structs */
236 if(ci){ 238 if(ci){
237 for(i=0;i<ci->modes;i++){ 239 for(i=0;i<ci->modes;i++){
238 int mapnum=ci->mode_param[i]->mapping; 240 int mapnum=ci->mode_param[i]->mapping;
239 int maptype=ci->map_type[mapnum]; 241 int maptype=ci->map_type[mapnum];
240 if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]); 242 if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]);
241 } 243 }
242 } 244 }
243 245
244 if(b){ 246 if(b){
245 if(b->mode)_ogg_free(b->mode); 247 if(b->mode)_ogg_free(b->mode);
246 _ogg_free(b); 248 _ogg_free(b);
247 } 249 }
248 250
249 memset(v,0,sizeof(*v)); 251 memset(v,0,sizeof(*v));
250 } 252 }
251} 253}
252 254
253/* Unlike in analysis, the window is only partially applied for each 255/* Unlike in analysis, the window is only partially applied for each
254 block. The time domain envelope is not yet handled at the point of 256 block. The time domain envelope is not yet handled at the point of
255 calling (as it relies on the previous block). */ 257 calling (as it relies on the previous block). */
256 258
257int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ 259int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
258 vorbis_info *vi=v->vi; 260 vorbis_info *vi=v->vi;
259 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 261 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
260 private_state *b=v->backend_state; 262 private_state *b=v->backend_state;
261 int i,j; 263 int i,j;
262 264
263 if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL); 265 if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL);
264 266
265 v->lW=v->W; 267 v->lW=v->W;
266 v->W=vb->W; 268 v->W=vb->W;
267 v->nW=-1; 269 v->nW=-1;
268 270
269 if((v->sequence==-1)|| 271 if((v->sequence==-1)||
270 (v->sequence+1 != vb->sequence)){ 272 (v->sequence+1 != vb->sequence)){
271 v->granulepos=-1; /* out of sequence; lose count */ 273 v->granulepos=-1; /* out of sequence; lose count */
272 b->sample_count=-1; 274 b->sample_count=-1;
273 } 275 }
274 276
275 v->sequence=vb->sequence; 277 v->sequence=vb->sequence;
276 278
277 if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly 279 if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly
278 was called on block */ 280 was called on block */
279 int n=ci->blocksizes[v->W]/2; 281 int n=ci->blocksizes[v->W]/2;
280 int n0=ci->blocksizes[0]/2; 282 int n0=ci->blocksizes[0]/2;
281 int n1=ci->blocksizes[1]/2; 283 int n1=ci->blocksizes[1]/2;
282 284
283 int thisCenter; 285 int thisCenter;
284 int prevCenter; 286 int prevCenter;
285 287
286 if(v->centerW){ 288 if(v->centerW){
287 thisCenter=n1; 289 thisCenter=n1;
288 prevCenter=0; 290 prevCenter=0;
289 }else{ 291 }else{
290 thisCenter=0; 292 thisCenter=0;
291 prevCenter=n1; 293 prevCenter=n1;
292 } 294 }
293 295
294 /* v->pcm is now used like a two-stage double buffer. We don't want 296 /* v->pcm is now used like a two-stage double buffer. We don't want
295 to have to constantly shift *or* adjust memory usage. Don't 297 to have to constantly shift *or* adjust memory usage. Don't
296 accept a new block until the old is shifted out */ 298 accept a new block until the old is shifted out */
297 299
298 /* overlap/add PCM */ 300 /* overlap/add PCM */
299 301
300 for(j=0;j<vi->channels;j++){ 302 for(j=0;j<vi->channels;j++){
301 /* the overlap/add section */ 303 /* the overlap/add section */
302 if(v->lW){ 304 if(v->lW){
303 if(v->W){ 305 if(v->W){
304 /* large/large */ 306 /* large/large */
305 ogg_int32_t *pcm=v->pcm[j]+prevCenter; 307 ogg_int32_t *pcm=v->pcm[j]+prevCenter;
306 ogg_int32_t *p=vb->pcm[j]; 308 ogg_int32_t *p=vb->pcm[j];
307 for(i=0;i<n1;i++) 309 for(i=0;i<n1;i++)
308 pcm[i]+=p[i]; 310 pcm[i]+=p[i];
309 }else{ 311 }else{
310 /* large/small */ 312 /* large/small */
311 ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2; 313 ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
312 ogg_int32_t *p=vb->pcm[j]; 314 ogg_int32_t *p=vb->pcm[j];
313 for(i=0;i<n0;i++) 315 for(i=0;i<n0;i++)
314 pcm[i]+=p[i]; 316 pcm[i]+=p[i];
315 } 317 }
316 }else{ 318 }else{
317 if(v->W){ 319 if(v->W){
318 /* small/large */ 320 /* small/large */
319 ogg_int32_t *pcm=v->pcm[j]+prevCenter; 321 ogg_int32_t *pcm=v->pcm[j]+prevCenter;
320 ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2; 322 ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2;
321 for(i=0;i<n0;i++) 323 for(i=0;i<n0;i++)
322 pcm[i]+=p[i]; 324 pcm[i]+=p[i];
323 for(;i<n1/2+n0/2;i++) 325 for(;i<n1/2+n0/2;i++)
324 pcm[i]=p[i]; 326 pcm[i]=p[i];
325 }else{ 327 }else{
326 /* small/small */ 328 /* small/small */
327 ogg_int32_t *pcm=v->pcm[j]+prevCenter; 329 ogg_int32_t *pcm=v->pcm[j]+prevCenter;
328 ogg_int32_t *p=vb->pcm[j]; 330 ogg_int32_t *p=vb->pcm[j];
329 for(i=0;i<n0;i++) 331 for(i=0;i<n0;i++)
330 pcm[i]+=p[i]; 332 pcm[i]+=p[i];
331 } 333 }
332 } 334 }
333 335
334 /* the copy section */ 336 /* the copy section */
335 { 337 {
336 ogg_int32_t *pcm=v->pcm[j]+thisCenter; 338 ogg_int32_t *pcm=v->pcm[j]+thisCenter;
337 ogg_int32_t *p=vb->pcm[j]+n; 339 ogg_int32_t *p=vb->pcm[j]+n;
338 for(i=0;i<n;i++) 340 for(i=0;i<n;i++)
339 pcm[i]=p[i]; 341 pcm[i]=p[i];
340 } 342 }
341 } 343 }
342 344
343 if(v->centerW) 345 if(v->centerW)
344 v->centerW=0; 346 v->centerW=0;
345 else 347 else
346 v->centerW=n1; 348 v->centerW=n1;
347 349
348 /* deal with initial packet state; we do this using the explicit 350 /* deal with initial packet state; we do this using the explicit
349 pcm_returned==-1 flag otherwise we're sensitive to first block 351 pcm_returned==-1 flag otherwise we're sensitive to first block
350 being short or long */ 352 being short or long */
351 353
352 if(v->pcm_returned==-1){ 354 if(v->pcm_returned==-1){
353 v->pcm_returned=thisCenter; 355 v->pcm_returned=thisCenter;
354 v->pcm_current=thisCenter; 356 v->pcm_current=thisCenter;
355 }else{ 357 }else{
356 v->pcm_returned=prevCenter; 358 v->pcm_returned=prevCenter;
357 v->pcm_current=prevCenter+ 359 v->pcm_current=prevCenter+
358 ci->blocksizes[v->lW]/4+ 360 ci->blocksizes[v->lW]/4+
359 ci->blocksizes[v->W]/4; 361 ci->blocksizes[v->W]/4;
360 } 362 }
361 363
362 } 364 }
363 365
364 /* track the frame number... This is for convenience, but also 366 /* track the frame number... This is for convenience, but also
365 making sure our last packet doesn't end with added padding. If 367 making sure our last packet doesn't end with added padding. If
366 the last packet is partial, the number of samples we'll have to 368 the last packet is partial, the number of samples we'll have to
367 return will be past the vb->granulepos. 369 return will be past the vb->granulepos.
368 370
369 This is not foolproof! It will be confused if we begin 371 This is not foolproof! It will be confused if we begin
370 decoding at the last page after a seek or hole. In that case, 372 decoding at the last page after a seek or hole. In that case,
371 we don't have a starting point to judge where the last frame 373 we don't have a starting point to judge where the last frame
372 is. For this reason, vorbisfile will always try to make sure 374 is. For this reason, vorbisfile will always try to make sure
373 it reads the last two marked pages in proper sequence */ 375 it reads the last two marked pages in proper sequence */
374 376
375 if(b->sample_count==-1){ 377 if(b->sample_count==-1){
376 b->sample_count=0; 378 b->sample_count=0;
377 }else{ 379 }else{
378 b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; 380 b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
379 } 381 }
380 382
381 if(v->granulepos==-1){ 383 if(v->granulepos==-1){
382 if(vb->granulepos!=-1){ /* only set if we have a position to set to */ 384 if(vb->granulepos!=-1){ /* only set if we have a position to set to */
383 385
384 v->granulepos=vb->granulepos; 386 v->granulepos=vb->granulepos;
385 387
386 /* is this a short page? */ 388 /* is this a short page? */
387 if(b->sample_count>v->granulepos){ 389 if(b->sample_count>v->granulepos){
388 /* corner case; if this is both the first and last audio page, 390 /* corner case; if this is both the first and last audio page,
389 then spec says the end is cut, not beginning */ 391 then spec says the end is cut, not beginning */
390 if(vb->eofflag){ 392 if(vb->eofflag){
391 /* trim the end */ 393 /* trim the end */
392 /* no preceeding granulepos; assume we started at zero (we'd 394 /* no preceeding granulepos; assume we started at zero (we'd
393 have to in a short single-page stream) */ 395 have to in a short single-page stream) */
394 /* granulepos could be -1 due to a seek, but that would result 396 /* granulepos could be -1 due to a seek, but that would result
395 in a long coun`t, not short count */ 397 in a long coun`t, not short count */
396 398
397 v->pcm_current-=(b->sample_count-v->granulepos); 399 v->pcm_current-=(b->sample_count-v->granulepos);
398 }else{ 400 }else{
399 /* trim the beginning */ 401 /* trim the beginning */
400 v->pcm_returned+=(b->sample_count-v->granulepos); 402 v->pcm_returned+=(b->sample_count-v->granulepos);
401 if(v->pcm_returned>v->pcm_current) 403 if(v->pcm_returned>v->pcm_current)
402 v->pcm_returned=v->pcm_current; 404 v->pcm_returned=v->pcm_current;
403 } 405 }
404 406
405 } 407 }
406 408
407 } 409 }
408 }else{ 410 }else{
409 v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; 411 v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
410 if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){ 412 if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
411 413
412 if(v->granulepos>vb->granulepos){ 414 if(v->granulepos>vb->granulepos){
413 long extra=v->granulepos-vb->granulepos; 415 long extra=v->granulepos-vb->granulepos;
414 416
415 if(extra) 417 if(extra)
416 if(vb->eofflag){ 418 if(vb->eofflag){
417 /* partial last frame. Strip the extra samples off */ 419 /* partial last frame. Strip the extra samples off */
418 v->pcm_current-=extra; 420 v->pcm_current-=extra;
419 } /* else {Shouldn't happen *unless* the bitstream is out of 421 } /* else {Shouldn't happen *unless* the bitstream is out of
420 spec. Either way, believe the bitstream } */ 422 spec. Either way, believe the bitstream } */
421 } /* else {Shouldn't happen *unless* the bitstream is out of 423 } /* else {Shouldn't happen *unless* the bitstream is out of
422 spec. Either way, believe the bitstream } */ 424 spec. Either way, believe the bitstream } */
423 v->granulepos=vb->granulepos; 425 v->granulepos=vb->granulepos;
424 } 426 }
425 } 427 }
426 428
427 /* Update, cleanup */ 429 /* Update, cleanup */
428 430
429 if(vb->eofflag)v->eofflag=1; 431 if(vb->eofflag)v->eofflag=1;
430 return(0); 432 return(0);
431} 433}
432 434
433/* pcm==NULL indicates we just want the pending samples, no more */ 435/* pcm==NULL indicates we just want the pending samples, no more */
434int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm){ 436int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm){
435 vorbis_info *vi=v->vi; 437 vorbis_info *vi=v->vi;
436 if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){ 438 if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
437 if(pcm){ 439 if(pcm){
438 int i; 440 int i;
439 for(i=0;i<vi->channels;i++) 441 for(i=0;i<vi->channels;i++)
440 v->pcmret[i]=v->pcm[i]+v->pcm_returned; 442 v->pcmret[i]=v->pcm[i]+v->pcm_returned;
441 *pcm=v->pcmret; 443 *pcm=v->pcmret;
442 } 444 }
443 return(v->pcm_current-v->pcm_returned); 445 return(v->pcm_current-v->pcm_returned);
444 } 446 }
445 return(0); 447 return(0);
446} 448}
447 449
448int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){ 450int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){
449 if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL); 451 if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL);
450 v->pcm_returned+=bytes; 452 v->pcm_returned+=bytes;
451 return(0); 453 return(0);
452} 454}
453 455
diff --git a/core/multimedia/opieplayer/vorbis/tremor/info.c b/core/multimedia/opieplayer/vorbis/tremor/info.c
index 941695e..3499ae4 100644
--- a/core/multimedia/opieplayer/vorbis/tremor/info.c
+++ b/core/multimedia/opieplayer/vorbis/tremor/info.c
@@ -1,354 +1,354 @@
1/******************************************************************** 1/********************************************************************
2 * * 2 * *
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * 3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
4 * * 4 * *
5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * * 8 * *
9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * 9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 *
10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * 10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
11 * * 11 * *
12 ******************************************************************** 12 ********************************************************************
13 13
14 function: maintain the info structure, info <-> header packets 14 function: maintain the info structure, info <-> header packets
15 15
16 ********************************************************************/ 16 ********************************************************************/
17 17
18/* general handling of the header and the vorbis_info structure (and 18/* general handling of the header and the vorbis_info structure (and
19 substructures) */ 19 substructures) */
20 20
21#include <stdlib.h> 21#include <stdlib.h>
22#include <string.h> 22#include <string.h>
23#include <ctype.h> 23#include <ctype.h>
24#include "ogg.h" 24#include "ogg.h"
25#include "ivorbiscodec.h" 25#include "ivorbiscodec.h"
26#include "codec_internal.h" 26#include "codec_internal.h"
27#include "codebook.h" 27#include "codebook.h"
28#include "registry.h" 28#include "registry.h"
29#include "window.h" 29#include "window.h"
30#include "misc.h" 30#include "misc.h"
31#include "os.h" 31#include "os.h"
32 32
33/* helpers */ 33/* helpers */
34static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){ 34static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
35 while(bytes--){ 35 while(bytes--){
36 *buf++=oggpack_read(o,8); 36 *buf++=oggpack_read(o,8);
37 } 37 }
38} 38}
39 39
40void vorbis_comment_init(vorbis_comment *vc){ 40void vorbis_comment_init(vorbis_comment *vc){
41 memset(vc,0,sizeof(*vc)); 41 memset(vc,0,sizeof(*vc));
42} 42}
43 43
44/* This is more or less the same as strncasecmp - but that doesn't exist 44/* This is more or less the same as strncasecmp - but that doesn't exist
45 * everywhere, and this is a fairly trivial function, so we include it */ 45 * everywhere, and this is a fairly trivial function, so we include it */
46static int tagcompare(const char *s1, const char *s2, int n){ 46static int tagcompare(const char *s1, const char *s2, int n){
47 int c=0; 47 int c=0;
48 while(c < n){ 48 while(c < n){
49 if(toupper(s1[c]) != toupper(s2[c])) 49 if(toupper(s1[c]) != toupper(s2[c]))
50 return !0; 50 return !0;
51 c++; 51 c++;
52 } 52 }
53 return 0; 53 return 0;
54} 54}
55 55
56char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){ 56char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){
57 long i; 57 long i;
58 int found = 0; 58 int found = 0;
59 int taglen = strlen(tag)+1; /* +1 for the = we append */ 59 int taglen = strlen(tag)+1; /* +1 for the = we append */
60 char *fulltag = (char *)alloca(taglen+ 1); 60 char *fulltag = (char *)alloca(taglen+ 1);
61 61
62 strcpy(fulltag, tag); 62 strcpy(fulltag, tag);
63 strcat(fulltag, "="); 63 strcat(fulltag, "=");
64 64
65 for(i=0;i<vc->comments;i++){ 65 for(i=0;i<vc->comments;i++){
66 if(!tagcompare(vc->user_comments[i], fulltag, taglen)){ 66 if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
67 if(count == found) 67 if(count == found)
68 /* We return a pointer to the data, not a copy */ 68 /* We return a pointer to the data, not a copy */
69 return vc->user_comments[i] + taglen; 69 return vc->user_comments[i] + taglen;
70 else 70 else
71 found++; 71 found++;
72 } 72 }
73 } 73 }
74 return NULL; /* didn't find anything */ 74 return NULL; /* didn't find anything */
75} 75}
76 76
77int vorbis_comment_query_count(vorbis_comment *vc, char *tag){ 77int vorbis_comment_query_count(vorbis_comment *vc, char *tag){
78 int i,count=0; 78 int i,count=0;
79 int taglen = strlen(tag)+1; /* +1 for the = we append */ 79 int taglen = strlen(tag)+1; /* +1 for the = we append */
80 char *fulltag = (char *)alloca(taglen+1); 80 char *fulltag = (char *)alloca(taglen+1);
81 strcpy(fulltag,tag); 81 strcpy(fulltag,tag);
82 strcat(fulltag, "="); 82 strcat(fulltag, "=");
83 83
84 for(i=0;i<vc->comments;i++){ 84 for(i=0;i<vc->comments;i++){
85 if(!tagcompare(vc->user_comments[i], fulltag, taglen)) 85 if(!tagcompare(vc->user_comments[i], fulltag, taglen))
86 count++; 86 count++;
87 } 87 }
88 88
89 return count; 89 return count;
90} 90}
91 91
92void vorbis_comment_clear(vorbis_comment *vc){ 92void vorbis_comment_clear(vorbis_comment *vc){
93 if(vc){ 93 if(vc){
94 long i; 94 long i;
95 for(i=0;i<vc->comments;i++) 95 for(i=0;i<vc->comments;i++)
96 if(vc->user_comments[i])_ogg_free(vc->user_comments[i]); 96 if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
97 if(vc->user_comments)_ogg_free(vc->user_comments); 97 if(vc->user_comments)_ogg_free(vc->user_comments);
98 if(vc->comment_lengths)_ogg_free(vc->comment_lengths); 98 if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
99 if(vc->vendor)_ogg_free(vc->vendor); 99 if(vc->vendor)_ogg_free(vc->vendor);
100 memset(vc,0,sizeof(*vc));
100 } 101 }
101 memset(vc,0,sizeof(*vc));
102} 102}
103 103
104/* blocksize 0 is guaranteed to be short, 1 is guarantted to be long. 104/* blocksize 0 is guaranteed to be short, 1 is guarantted to be long.
105 They may be equal, but short will never ge greater than long */ 105 They may be equal, but short will never ge greater than long */
106int vorbis_info_blocksize(vorbis_info *vi,int zo){ 106int vorbis_info_blocksize(vorbis_info *vi,int zo){
107 codec_setup_info *ci = (codec_setup_info *)vi->codec_setup; 107 codec_setup_info *ci = (codec_setup_info *)vi->codec_setup;
108 return ci ? ci->blocksizes[zo] : -1; 108 return ci ? ci->blocksizes[zo] : -1;
109} 109}
110 110
111/* used by synthesis, which has a full, alloced vi */ 111/* used by synthesis, which has a full, alloced vi */
112void vorbis_info_init(vorbis_info *vi){ 112void vorbis_info_init(vorbis_info *vi){
113 memset(vi,0,sizeof(*vi)); 113 memset(vi,0,sizeof(*vi));
114 vi->codec_setup=(codec_setup_info *)_ogg_calloc(1,sizeof(codec_setup_info)); 114 vi->codec_setup=(codec_setup_info *)_ogg_calloc(1,sizeof(codec_setup_info));
115} 115}
116 116
117void vorbis_info_clear(vorbis_info *vi){ 117void vorbis_info_clear(vorbis_info *vi){
118 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 118 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
119 int i; 119 int i;
120 120
121 if(ci){ 121 if(ci){
122 122
123 for(i=0;i<ci->modes;i++) 123 for(i=0;i<ci->modes;i++)
124 if(ci->mode_param[i])_ogg_free(ci->mode_param[i]); 124 if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
125 125
126 for(i=0;i<ci->maps;i++) /* unpack does the range checking */ 126 for(i=0;i<ci->maps;i++) /* unpack does the range checking */
127 _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); 127 _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
128 128
129 for(i=0;i<ci->floors;i++) /* unpack does the range checking */ 129 for(i=0;i<ci->floors;i++) /* unpack does the range checking */
130 _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); 130 _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
131 131
132 for(i=0;i<ci->residues;i++) /* unpack does the range checking */ 132 for(i=0;i<ci->residues;i++) /* unpack does the range checking */
133 _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]); 133 _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
134 134
135 for(i=0;i<ci->books;i++){ 135 for(i=0;i<ci->books;i++){
136 if(ci->book_param[i]){ 136 if(ci->book_param[i]){
137 /* knows if the book was not alloced */ 137 /* knows if the book was not alloced */
138 vorbis_staticbook_destroy(ci->book_param[i]); 138 vorbis_staticbook_destroy(ci->book_param[i]);
139 } 139 }
140 if(ci->fullbooks) 140 if(ci->fullbooks)
141 vorbis_book_clear(ci->fullbooks+i); 141 vorbis_book_clear(ci->fullbooks+i);
142 } 142 }
143 if(ci->fullbooks) 143 if(ci->fullbooks)
144 _ogg_free(ci->fullbooks); 144 _ogg_free(ci->fullbooks);
145 145
146 _ogg_free(ci); 146 _ogg_free(ci);
147 } 147 }
148 148
149 memset(vi,0,sizeof(*vi)); 149 memset(vi,0,sizeof(*vi));
150} 150}
151 151
152/* Header packing/unpacking ********************************************/ 152/* Header packing/unpacking ********************************************/
153 153
154static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ 154static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
155 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 155 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
156 if(!ci)return(OV_EFAULT); 156 if(!ci)return(OV_EFAULT);
157 157
158 vi->version=oggpack_read(opb,32); 158 vi->version=oggpack_read(opb,32);
159 if(vi->version!=0)return(OV_EVERSION); 159 if(vi->version!=0)return(OV_EVERSION);
160 160
161 vi->channels=oggpack_read(opb,8); 161 vi->channels=oggpack_read(opb,8);
162 vi->rate=oggpack_read(opb,32); 162 vi->rate=oggpack_read(opb,32);
163 163
164 vi->bitrate_upper=oggpack_read(opb,32); 164 vi->bitrate_upper=oggpack_read(opb,32);
165 vi->bitrate_nominal=oggpack_read(opb,32); 165 vi->bitrate_nominal=oggpack_read(opb,32);
166 vi->bitrate_lower=oggpack_read(opb,32); 166 vi->bitrate_lower=oggpack_read(opb,32);
167 167
168 ci->blocksizes[0]=1<<oggpack_read(opb,4); 168 ci->blocksizes[0]=1<<oggpack_read(opb,4);
169 ci->blocksizes[1]=1<<oggpack_read(opb,4); 169 ci->blocksizes[1]=1<<oggpack_read(opb,4);
170 170
171 if(vi->rate<1)goto err_out; 171 if(vi->rate<1)goto err_out;
172 if(vi->channels<1)goto err_out; 172 if(vi->channels<1)goto err_out;
173 if(ci->blocksizes[0]<64)goto err_out; 173 if(ci->blocksizes[0]<64)goto err_out;
174 if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out; 174 if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
175 if(ci->blocksizes[1]>8192)goto err_out; 175 if(ci->blocksizes[1]>8192)goto err_out;
176 176
177 if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ 177 if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
178 178
179 return(0); 179 return(0);
180 err_out: 180 err_out:
181 vorbis_info_clear(vi); 181 vorbis_info_clear(vi);
182 return(OV_EBADHEADER); 182 return(OV_EBADHEADER);
183} 183}
184 184
185static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ 185static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
186 int i; 186 int i;
187 int vendorlen=oggpack_read(opb,32); 187 int vendorlen=oggpack_read(opb,32);
188 if(vendorlen<0)goto err_out; 188 if(vendorlen<0)goto err_out;
189 vc->vendor=(char *)_ogg_calloc(vendorlen+1,1); 189 vc->vendor=(char *)_ogg_calloc(vendorlen+1,1);
190 _v_readstring(opb,vc->vendor,vendorlen); 190 _v_readstring(opb,vc->vendor,vendorlen);
191 vc->comments=oggpack_read(opb,32); 191 vc->comments=oggpack_read(opb,32);
192 if(vc->comments<0)goto err_out; 192 if(vc->comments<0)goto err_out;
193 vc->user_comments=(char **)_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments)); 193 vc->user_comments=(char **)_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
194 vc->comment_lengths=(int *)_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths)); 194 vc->comment_lengths=(int *)_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
195 195
196 for(i=0;i<vc->comments;i++){ 196 for(i=0;i<vc->comments;i++){
197 int len=oggpack_read(opb,32); 197 int len=oggpack_read(opb,32);
198 if(len<0)goto err_out; 198 if(len<0)goto err_out;
199 vc->comment_lengths[i]=len; 199 vc->comment_lengths[i]=len;
200 vc->user_comments[i]=(char *)_ogg_calloc(len+1,1); 200 vc->user_comments[i]=(char *)_ogg_calloc(len+1,1);
201 _v_readstring(opb,vc->user_comments[i],len); 201 _v_readstring(opb,vc->user_comments[i],len);
202 } 202 }
203 if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ 203 if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
204 204
205 return(0); 205 return(0);
206 err_out: 206 err_out:
207 vorbis_comment_clear(vc); 207 vorbis_comment_clear(vc);
208 return(OV_EBADHEADER); 208 return(OV_EBADHEADER);
209} 209}
210 210
211/* all of the real encoding details are here. The modes, books, 211/* all of the real encoding details are here. The modes, books,
212 everything */ 212 everything */
213static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ 213static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
214 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 214 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
215 int i; 215 int i;
216 if(!ci)return(OV_EFAULT); 216 if(!ci)return(OV_EFAULT);
217 217
218 /* codebooks */ 218 /* codebooks */
219 ci->books=oggpack_read(opb,8)+1; 219 ci->books=oggpack_read(opb,8)+1;
220 /*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/ 220 /*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/
221 for(i=0;i<ci->books;i++){ 221 for(i=0;i<ci->books;i++){
222 ci->book_param[i]=(static_codebook *)_ogg_calloc(1,sizeof(*ci->book_param[i])); 222 ci->book_param[i]=(static_codebook *)_ogg_calloc(1,sizeof(*ci->book_param[i]));
223 if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out; 223 if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out;
224 } 224 }
225 225
226 /* time backend settings */ 226 /* time backend settings */
227 ci->times=oggpack_read(opb,6)+1; 227 ci->times=oggpack_read(opb,6)+1;
228 /*ci->time_type=_ogg_malloc(ci->times*sizeof(*ci->time_type));*/ 228 /*ci->time_type=_ogg_malloc(ci->times*sizeof(*ci->time_type));*/
229 /*ci->time_param=_ogg_calloc(ci->times,sizeof(void *));*/ 229 /*ci->time_param=_ogg_calloc(ci->times,sizeof(void *));*/
230 for(i=0;i<ci->times;i++){ 230 for(i=0;i<ci->times;i++){
231 ci->time_type[i]=oggpack_read(opb,16); 231 ci->time_type[i]=oggpack_read(opb,16);
232 if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out; 232 if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out;
233 /* ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb); 233 /* ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb);
234 Vorbis I has no time backend */ 234 Vorbis I has no time backend */
235 /*if(!ci->time_param[i])goto err_out;*/ 235 /*if(!ci->time_param[i])goto err_out;*/
236 } 236 }
237 237
238 /* floor backend settings */ 238 /* floor backend settings */
239 ci->floors=oggpack_read(opb,6)+1; 239 ci->floors=oggpack_read(opb,6)+1;
240 /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/ 240 /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/
241 /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/ 241 /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/
242 for(i=0;i<ci->floors;i++){ 242 for(i=0;i<ci->floors;i++){
243 ci->floor_type[i]=oggpack_read(opb,16); 243 ci->floor_type[i]=oggpack_read(opb,16);
244 if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; 244 if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
245 ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); 245 ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
246 if(!ci->floor_param[i])goto err_out; 246 if(!ci->floor_param[i])goto err_out;
247 } 247 }
248 248
249 /* residue backend settings */ 249 /* residue backend settings */
250 ci->residues=oggpack_read(opb,6)+1; 250 ci->residues=oggpack_read(opb,6)+1;
251 /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/ 251 /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/
252 /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/ 252 /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/
253 for(i=0;i<ci->residues;i++){ 253 for(i=0;i<ci->residues;i++){
254 ci->residue_type[i]=oggpack_read(opb,16); 254 ci->residue_type[i]=oggpack_read(opb,16);
255 if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; 255 if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
256 ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); 256 ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
257 if(!ci->residue_param[i])goto err_out; 257 if(!ci->residue_param[i])goto err_out;
258 } 258 }
259 259
260 /* map backend settings */ 260 /* map backend settings */
261 ci->maps=oggpack_read(opb,6)+1; 261 ci->maps=oggpack_read(opb,6)+1;
262 /*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/ 262 /*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/
263 /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/ 263 /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/
264 for(i=0;i<ci->maps;i++){ 264 for(i=0;i<ci->maps;i++){
265 ci->map_type[i]=oggpack_read(opb,16); 265 ci->map_type[i]=oggpack_read(opb,16);
266 if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; 266 if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
267 ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); 267 ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
268 if(!ci->map_param[i])goto err_out; 268 if(!ci->map_param[i])goto err_out;
269 } 269 }
270 270
271 /* mode settings */ 271 /* mode settings */
272 ci->modes=oggpack_read(opb,6)+1; 272 ci->modes=oggpack_read(opb,6)+1;
273 /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/ 273 /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/
274 for(i=0;i<ci->modes;i++){ 274 for(i=0;i<ci->modes;i++){
275 ci->mode_param[i]=(vorbis_info_mode *)_ogg_calloc(1,sizeof(*ci->mode_param[i])); 275 ci->mode_param[i]=(vorbis_info_mode *)_ogg_calloc(1,sizeof(*ci->mode_param[i]));
276 ci->mode_param[i]->blockflag=oggpack_read(opb,1); 276 ci->mode_param[i]->blockflag=oggpack_read(opb,1);
277 ci->mode_param[i]->windowtype=oggpack_read(opb,16); 277 ci->mode_param[i]->windowtype=oggpack_read(opb,16);
278 ci->mode_param[i]->transformtype=oggpack_read(opb,16); 278 ci->mode_param[i]->transformtype=oggpack_read(opb,16);
279 ci->mode_param[i]->mapping=oggpack_read(opb,8); 279 ci->mode_param[i]->mapping=oggpack_read(opb,8);
280 280
281 if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; 281 if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
282 if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; 282 if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
283 if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; 283 if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
284 } 284 }
285 285
286 if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ 286 if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
287 287
288 return(0); 288 return(0);
289 err_out: 289 err_out:
290 vorbis_info_clear(vi); 290 vorbis_info_clear(vi);
291 return(OV_EBADHEADER); 291 return(OV_EBADHEADER);
292} 292}
293 293
294/* The Vorbis header is in three packets; the initial small packet in 294/* The Vorbis header is in three packets; the initial small packet in
295 the first page that identifies basic parameters, a second packet 295 the first page that identifies basic parameters, a second packet
296 with bitstream comments and a third packet that holds the 296 with bitstream comments and a third packet that holds the
297 codebook. */ 297 codebook. */
298 298
299int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){ 299int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
300 oggpack_buffer opb; 300 oggpack_buffer opb;
301 301
302 if(op){ 302 if(op){
303 oggpack_readinit(&opb,op->packet); 303 oggpack_readinit(&opb,op->packet);
304 304
305 /* Which of the three types of header is this? */ 305 /* Which of the three types of header is this? */
306 /* Also verify header-ness, vorbis */ 306 /* Also verify header-ness, vorbis */
307 { 307 {
308 char buffer[6]; 308 char buffer[6];
309 int packtype=oggpack_read(&opb,8); 309 int packtype=oggpack_read(&opb,8);
310 memset(buffer,0,6); 310 memset(buffer,0,6);
311 _v_readstring(&opb,buffer,6); 311 _v_readstring(&opb,buffer,6);
312 if(memcmp(buffer,"vorbis",6)){ 312 if(memcmp(buffer,"vorbis",6)){
313 /* not a vorbis header */ 313 /* not a vorbis header */
314 return(OV_ENOTVORBIS); 314 return(OV_ENOTVORBIS);
315 } 315 }
316 switch(packtype){ 316 switch(packtype){
317 case 0x01: /* least significant *bit* is read first */ 317 case 0x01: /* least significant *bit* is read first */
318 if(!op->b_o_s){ 318 if(!op->b_o_s){
319 /* Not the initial packet */ 319 /* Not the initial packet */
320 return(OV_EBADHEADER); 320 return(OV_EBADHEADER);
321 } 321 }
322 if(vi->rate!=0){ 322 if(vi->rate!=0){
323 /* previously initialized info header */ 323 /* previously initialized info header */
324 return(OV_EBADHEADER); 324 return(OV_EBADHEADER);
325 } 325 }
326 326
327 return(_vorbis_unpack_info(vi,&opb)); 327 return(_vorbis_unpack_info(vi,&opb));
328 328
329 case 0x03: /* least significant *bit* is read first */ 329 case 0x03: /* least significant *bit* is read first */
330 if(vi->rate==0){ 330 if(vi->rate==0){
331 /* um... we didn't get the initial header */ 331 /* um... we didn't get the initial header */
332 return(OV_EBADHEADER); 332 return(OV_EBADHEADER);
333 } 333 }
334 334
335 return(_vorbis_unpack_comment(vc,&opb)); 335 return(_vorbis_unpack_comment(vc,&opb));
336 336
337 case 0x05: /* least significant *bit* is read first */ 337 case 0x05: /* least significant *bit* is read first */
338 if(vi->rate==0 || vc->vendor==NULL){ 338 if(vi->rate==0 || vc->vendor==NULL){
339 /* um... we didn;t get the initial header or comments yet */ 339 /* um... we didn;t get the initial header or comments yet */
340 return(OV_EBADHEADER); 340 return(OV_EBADHEADER);
341 } 341 }
342 342
343 return(_vorbis_unpack_books(vi,&opb)); 343 return(_vorbis_unpack_books(vi,&opb));
344 344
345 default: 345 default:
346 /* Not a valid vorbis header type */ 346 /* Not a valid vorbis header type */
347 return(OV_EBADHEADER); 347 return(OV_EBADHEADER);
348 break; 348 break;
349 } 349 }
350 } 350 }
351 } 351 }
352 return(OV_EBADHEADER); 352 return(OV_EBADHEADER);
353} 353}
354 354
diff --git a/noncore/apps/opie-write/qrichtext.cpp b/noncore/apps/opie-write/qrichtext.cpp
index f040f1e..768da44 100644
--- a/noncore/apps/opie-write/qrichtext.cpp
+++ b/noncore/apps/opie-write/qrichtext.cpp
@@ -1,7834 +1,7857 @@
1/**************************************************************************** 1/****************************************************************************
2** $Id$ 2** $Id$
3** 3**
4** Implementation of the internal Qt classes dealing with rich text 4** Implementation of the internal Qt classes dealing with rich text
5** 5**
6** Created : 990101 6** Created : 990101
7** 7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. 8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9** 9**
10** This file is part of the kernel module of the Qt GUI Toolkit. 10** This file is part of the kernel module of the Qt GUI Toolkit.
11** 11**
12** This file may be distributed under the terms of the Q Public License 12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file 13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file. 14** LICENSE.QPL included in the packaging of this file.
15** 15**
16** This file may be distributed and/or modified under the terms of the 16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software 17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the 18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file. 19** packaging of this file.
20** 20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition 21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License 22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software. 23** Agreement provided with the Software.
24** 24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27** 27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for 28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements. 29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information. 30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information. 31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32** 32**
33** Contact info@trolltech.com if any conditions of this licensing are 33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you. 34** not clear to you.
35** 35**
36**********************************************************************/ 36**********************************************************************/
37 37
38#include "qrichtext_p.h" 38#include "qrichtext_p.h"
39 39
40/* OPIE */ 40/* OPIE */
41#include <opie2/odebug.h> 41#include <opie2/odebug.h>
42using namespace Opie::Core; 42using namespace Opie::Core;
43 43
44/* QT */ 44/* QT */
45#include "qdragobject.h" 45#include "qdragobject.h"
46#include "qpaintdevicemetrics.h" 46#include "qpaintdevicemetrics.h"
47#include "qdrawutil.h" 47#include "qdrawutil.h"
48#include "qcleanuphandler.h" 48#include "qcleanuphandler.h"
49 49
50/* STD */ 50/* STD */
51#include <stdlib.h> 51#include <stdlib.h>
52 52
53using namespace Qt3; 53using namespace Qt3;
54 54
55static QTextCursor* richTextExportStart = 0; 55static QTextCursor* richTextExportStart = 0;
56static QTextCursor* richTextExportEnd = 0; 56static QTextCursor* richTextExportEnd = 0;
57 57
58static QTextFormatCollection *qFormatCollection = 0; 58static QTextFormatCollection *qFormatCollection = 0;
59 59
60const int border_tolerance = 2; 60const int border_tolerance = 2;
61 61
62#ifdef Q_WS_WIN 62#ifdef Q_WS_WIN
63#include "qt_windows.h" 63#include "qt_windows.h"
64#endif 64#endif
65 65
66#define QChar_linesep QChar(0x2028U) 66#define QChar_linesep QChar(0x2028U)
67 67
68static inline bool is_printer( QPainter *p ) 68static inline bool is_printer( QPainter *p )
69{ 69{
70 if ( !p || !p->device() ) 70 if ( !p || !p->device() )
71 return FALSE; 71 return FALSE;
72 return p->device()->devType() == QInternal::Printer; 72 return p->device()->devType() == QInternal::Printer;
73} 73}
74 74
75static inline int scale( int value, QPainter *painter ) 75static inline int scale( int value, QPainter *painter )
76{ 76{
77 if ( is_printer( painter ) ) { 77 if ( is_printer( painter ) ) {
78 QPaintDeviceMetrics metrics( painter->device() ); 78 QPaintDeviceMetrics metrics( painter->device() );
79#if defined(Q_WS_X11) 79#if defined(Q_WS_X11)
80 value = value * metrics.logicalDpiY() / QPaintDevice::x11AppDpiY(); 80 value = value * metrics.logicalDpiY() / QPaintDevice::x11AppDpiY();
81#elif defined (Q_WS_WIN) 81#elif defined (Q_WS_WIN)
82 HDC hdc = GetDC( 0 ); 82 HDC hdc = GetDC( 0 );
83 int gdc = GetDeviceCaps( hdc, LOGPIXELSY ); 83 int gdc = GetDeviceCaps( hdc, LOGPIXELSY );
84 if ( gdc ) 84 if ( gdc )
85 value = value * metrics.logicalDpiY() / gdc; 85 value = value * metrics.logicalDpiY() / gdc;
86 ReleaseDC( 0, hdc ); 86 ReleaseDC( 0, hdc );
87#elif defined (Q_WS_MAC) 87#elif defined (Q_WS_MAC)
88 value = value * metrics.logicalDpiY() / 75; // ##### FIXME 88 value = value * metrics.logicalDpiY() / 75; // ##### FIXME
89#elif defined (Q_WS_QWS) 89#elif defined (Q_WS_QWS)
90 value = value * metrics.logicalDpiY() / 75; 90 value = value * metrics.logicalDpiY() / 75;
91#endif 91#endif
92 } 92 }
93 return value; 93 return value;
94} 94}
95 95
96// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 96// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
97 97
98void QTextCommandHistory::addCommand( QTextCommand *cmd ) 98void QTextCommandHistory::addCommand( QTextCommand *cmd )
99{ 99{
100 if ( current < (int)history.count() - 1 ) { 100 if ( current < (int)history.count() - 1 ) {
101 QPtrList<QTextCommand> commands; 101 QPtrList<QTextCommand> commands;
102 commands.setAutoDelete( FALSE ); 102 commands.setAutoDelete( FALSE );
103 103
104 for( int i = 0; i <= current; ++i ) { 104 for( int i = 0; i <= current; ++i ) {
105 commands.insert( i, history.at( 0 ) ); 105 commands.insert( i, history.at( 0 ) );
106 history.take( 0 ); 106 history.take( 0 );
107 } 107 }
108 108
109 commands.append( cmd ); 109 commands.append( cmd );
110 history.clear(); 110 history.clear();
111 history = commands; 111 history = commands;
112 history.setAutoDelete( TRUE ); 112 history.setAutoDelete( TRUE );
113 } else { 113 } else {
114 history.append( cmd ); 114 history.append( cmd );
115 } 115 }
116 116
117 if ( (int)history.count() > steps ) 117 if ( (int)history.count() > steps )
118 history.removeFirst(); 118 history.removeFirst();
119 else 119 else
120 ++current; 120 ++current;
121} 121}
122 122
123QTextCursor *QTextCommandHistory::undo( QTextCursor *c ) 123QTextCursor *QTextCommandHistory::undo( QTextCursor *c )
124{ 124{
125 if ( current > -1 ) { 125 if ( current > -1 ) {
126 QTextCursor *c2 = history.at( current )->unexecute( c ); 126 QTextCursor *c2 = history.at( current )->unexecute( c );
127 --current; 127 --current;
128 return c2; 128 return c2;
129 } 129 }
130 return 0; 130 return 0;
131} 131}
132 132
133QTextCursor *QTextCommandHistory::redo( QTextCursor *c ) 133QTextCursor *QTextCommandHistory::redo( QTextCursor *c )
134{ 134{
135 if ( current > -1 ) { 135 if ( current > -1 ) {
136 if ( current < (int)history.count() - 1 ) { 136 if ( current < (int)history.count() - 1 ) {
137 ++current; 137 ++current;
138 return history.at( current )->execute( c ); 138 return history.at( current )->execute( c );
139 } 139 }
140 } else { 140 } else {
141 if ( history.count() > 0 ) { 141 if ( history.count() > 0 ) {
142 ++current; 142 ++current;
143 return history.at( current )->execute( c ); 143 return history.at( current )->execute( c );
144 } 144 }
145 } 145 }
146 return 0; 146 return 0;
147} 147}
148 148
149bool QTextCommandHistory::isUndoAvailable() 149bool QTextCommandHistory::isUndoAvailable()
150{ 150{
151 return current > -1; 151 return current > -1;
152} 152}
153 153
154bool QTextCommandHistory::isRedoAvailable() 154bool QTextCommandHistory::isRedoAvailable()
155{ 155{
156 return current > -1 && current < (int)history.count() - 1 || current == -1 && history.count() > 0; 156 return current > -1 && current < (int)history.count() - 1 || current == -1 && history.count() > 0;
157} 157}
158 158
159// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 159// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
160 160
161QTextDeleteCommand::QTextDeleteCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str, 161QTextDeleteCommand::QTextDeleteCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str,
162 const QByteArray& oldStyleInfo ) 162 const QByteArray& oldStyleInfo )
163 : QTextCommand( d ), id( i ), index( idx ), parag( 0 ), text( str ), styleInformation( oldStyleInfo ) 163 : QTextCommand( d ), id( i ), index( idx ), parag( 0 ), text( str ), styleInformation( oldStyleInfo )
164{ 164{
165 for ( int j = 0; j < (int)text.size(); ++j ) { 165 for ( int j = 0; j < (int)text.size(); ++j ) {
166 if ( text[ j ].format() ) 166 if ( text[ j ].format() )
167 text[ j ].format()->addRef(); 167 text[ j ].format()->addRef();
168 } 168 }
169} 169}
170 170
171QTextDeleteCommand::QTextDeleteCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str ) 171QTextDeleteCommand::QTextDeleteCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str )
172 : QTextCommand( 0 ), id( -1 ), index( idx ), parag( p ), text( str ) 172 : QTextCommand( 0 ), id( -1 ), index( idx ), parag( p ), text( str )
173{ 173{
174 for ( int i = 0; i < (int)text.size(); ++i ) { 174 for ( int i = 0; i < (int)text.size(); ++i ) {
175 if ( text[ i ].format() ) 175 if ( text[ i ].format() )
176 text[ i ].format()->addRef(); 176 text[ i ].format()->addRef();
177 } 177 }
178} 178}
179 179
180QTextDeleteCommand::~QTextDeleteCommand() 180QTextDeleteCommand::~QTextDeleteCommand()
181{ 181{
182 for ( int i = 0; i < (int)text.size(); ++i ) { 182 for ( int i = 0; i < (int)text.size(); ++i ) {
183 if ( text[ i ].format() ) 183 if ( text[ i ].format() )
184 text[ i ].format()->removeRef(); 184 text[ i ].format()->removeRef();
185 } 185 }
186 text.resize( 0 ); 186 text.resize( 0 );
187} 187}
188 188
189QTextCursor *QTextDeleteCommand::execute( QTextCursor *c ) 189QTextCursor *QTextDeleteCommand::execute( QTextCursor *c )
190{ 190{
191 QTextParagraph *s = doc ? doc->paragAt( id ) : parag; 191 QTextParagraph *s = doc ? doc->paragAt( id ) : parag;
192 if ( !s ) { 192 if ( !s && doc ) {
193 owarn << "can't locate parag at " << id << ", last parag: " << doc->lastParagraph()->paragId() << "" << oendl; 193 owarn << "can't locate parag at " << id << ", last parag: " << doc->lastParagraph()->paragId() << "" << oendl;
194 return 0; 194 return 0;
195 } else if ( !doc ) {
196 owarn << "No valid doc" << oendl;
197 return 0;
195 } 198 }
196 199
197 cursor.setParagraph( s ); 200 cursor.setParagraph( s );
198 cursor.setIndex( index ); 201 cursor.setIndex( index );
199 int len = text.size(); 202 int len = text.size();
200 if ( c ) 203 if ( c )
201 *c = cursor; 204 *c = cursor;
202 if ( doc ) { 205 if ( doc ) {
203 doc->setSelectionStart( QTextDocument::Temp, cursor ); 206 doc->setSelectionStart( QTextDocument::Temp, cursor );
204 for ( int i = 0; i < len; ++i ) 207 for ( int i = 0; i < len; ++i )
205 cursor.gotoNextLetter(); 208 cursor.gotoNextLetter();
206 doc->setSelectionEnd( QTextDocument::Temp, cursor ); 209 doc->setSelectionEnd( QTextDocument::Temp, cursor );
207 doc->removeSelectedText( QTextDocument::Temp, &cursor ); 210 doc->removeSelectedText( QTextDocument::Temp, &cursor );
208 if ( c ) 211 if ( c )
209 *c = cursor; 212 *c = cursor;
210 } else { 213 } else {
211 s->remove( index, len ); 214 s->remove( index, len );
212 } 215 }
213 216
214 return c; 217 return c;
215} 218}
216 219
217QTextCursor *QTextDeleteCommand::unexecute( QTextCursor *c ) 220QTextCursor *QTextDeleteCommand::unexecute( QTextCursor *c )
218{ 221{
219 QTextParagraph *s = doc ? doc->paragAt( id ) : parag; 222 QTextParagraph *s = doc ? doc->paragAt( id ) : parag;
220 if ( !s ) { 223 if ( !s && doc ) {
221 owarn << "can't locate parag at " << id << ", last parag: " << doc->lastParagraph()->paragId() << "" << oendl; 224 owarn << "can't locate parag at " << id << ", last parag: " << doc->lastParagraph()->paragId() << "" << oendl;
222 return 0; 225 return 0;
226 } else if ( !doc ) {
227 owarn << "No valid doc" << oendl;
228 return 0;
223 } 229 }
224 230
225 cursor.setParagraph( s ); 231 cursor.setParagraph( s );
226 cursor.setIndex( index ); 232 cursor.setIndex( index );
227 QString str = QTextString::toString( text ); 233 QString str = QTextString::toString( text );
228 cursor.insert( str, TRUE, &text ); 234 cursor.insert( str, TRUE, &text );
229 cursor.setParagraph( s ); 235 cursor.setParagraph( s );
230 cursor.setIndex( index ); 236 cursor.setIndex( index );
231 if ( c ) { 237 if ( c ) {
232 c->setParagraph( s ); 238 c->setParagraph( s );
233 c->setIndex( index ); 239 c->setIndex( index );
234 for ( int i = 0; i < (int)text.size(); ++i ) 240 for ( int i = 0; i < (int)text.size(); ++i )
235 c->gotoNextLetter(); 241 c->gotoNextLetter();
242 } else {
243 owarn << "No valid cursor" << oendl;
244 return 0;
236 } 245 }
237 246
238 if ( !styleInformation.isEmpty() ) { 247 if ( !styleInformation.isEmpty() ) {
239 QDataStream styleStream( styleInformation, IO_ReadOnly ); 248 QDataStream styleStream( styleInformation, IO_ReadOnly );
240 int num; 249 int num;
241 styleStream >> num; 250 styleStream >> num;
242 QTextParagraph *p = s; 251 QTextParagraph *p = s;
243 while ( num-- && p ) { 252 while ( num-- && p ) {
244 p->readStyleInformation( styleStream ); 253 p->readStyleInformation( styleStream );
245 p = p->next(); 254 p = p->next();
246 } 255 }
247 } 256 }
248 s = cursor.paragraph(); 257 s = cursor.paragraph();
249 while ( s ) { 258 while ( s ) {
250 s->format(); 259 s->format();
251 s->setChanged( TRUE ); 260 s->setChanged( TRUE );
252 if ( s == c->paragraph() ) 261 if ( s == c->paragraph() )
253 break; 262 break;
254 s = s->next(); 263 s = s->next();
255 } 264 }
256 265
257 return &cursor; 266 return &cursor;
258} 267}
259 268
260QTextFormatCommand::QTextFormatCommand( QTextDocument *d, int sid, int sidx, int eid, int eidx, 269QTextFormatCommand::QTextFormatCommand( QTextDocument *d, int sid, int sidx, int eid, int eidx,
261 const QMemArray<QTextStringChar> &old, QTextFormat *f, int fl ) 270 const QMemArray<QTextStringChar> &old, QTextFormat *f, int fl )
262 : QTextCommand( d ), startId( sid ), startIndex( sidx ), endId( eid ), endIndex( eidx ), format( f ), oldFormats( old ), flags( fl ) 271 : QTextCommand( d ), startId( sid ), startIndex( sidx ), endId( eid ), endIndex( eidx ), format( f ), oldFormats( old ), flags( fl )
263{ 272{
264 format = d->formatCollection()->format( f ); 273 format = d->formatCollection()->format( f );
265 for ( int j = 0; j < (int)oldFormats.size(); ++j ) { 274 for ( int j = 0; j < (int)oldFormats.size(); ++j ) {
266 if ( oldFormats[ j ].format() ) 275 if ( oldFormats[ j ].format() )
267 oldFormats[ j ].format()->addRef(); 276 oldFormats[ j ].format()->addRef();
268 } 277 }
269} 278}
270 279
271QTextFormatCommand::~QTextFormatCommand() 280QTextFormatCommand::~QTextFormatCommand()
272{ 281{
273 format->removeRef(); 282 format->removeRef();
274 for ( int j = 0; j < (int)oldFormats.size(); ++j ) { 283 for ( int j = 0; j < (int)oldFormats.size(); ++j ) {
275 if ( oldFormats[ j ].format() ) 284 if ( oldFormats[ j ].format() )
276 oldFormats[ j ].format()->removeRef(); 285 oldFormats[ j ].format()->removeRef();
277 } 286 }
278} 287}
279 288
280QTextCursor *QTextFormatCommand::execute( QTextCursor *c ) 289QTextCursor *QTextFormatCommand::execute( QTextCursor *c )
281{ 290{
282 QTextParagraph *sp = doc->paragAt( startId ); 291 QTextParagraph *sp = doc->paragAt( startId );
283 QTextParagraph *ep = doc->paragAt( endId ); 292 QTextParagraph *ep = doc->paragAt( endId );
284 if ( !sp || !ep ) 293 if ( !sp || !ep )
285 return c; 294 return c;
286 295
287 QTextCursor start( doc ); 296 QTextCursor start( doc );
288 start.setParagraph( sp ); 297 start.setParagraph( sp );
289 start.setIndex( startIndex ); 298 start.setIndex( startIndex );
290 QTextCursor end( doc ); 299 QTextCursor end( doc );
291 end.setParagraph( ep ); 300 end.setParagraph( ep );
292 end.setIndex( endIndex ); 301 end.setIndex( endIndex );
293 302
294 doc->setSelectionStart( QTextDocument::Temp, start ); 303 doc->setSelectionStart( QTextDocument::Temp, start );
295 doc->setSelectionEnd( QTextDocument::Temp, end ); 304 doc->setSelectionEnd( QTextDocument::Temp, end );
296 doc->setFormat( QTextDocument::Temp, format, flags ); 305 doc->setFormat( QTextDocument::Temp, format, flags );
297 doc->removeSelection( QTextDocument::Temp ); 306 doc->removeSelection( QTextDocument::Temp );
298 if ( endIndex == ep->length() ) 307 if ( endIndex == ep->length() )
299 end.gotoLeft(); 308 end.gotoLeft();
300 *c = end; 309 *c = end;
301 return c; 310 return c;
302} 311}
303 312
304QTextCursor *QTextFormatCommand::unexecute( QTextCursor *c ) 313QTextCursor *QTextFormatCommand::unexecute( QTextCursor *c )
305{ 314{
306 QTextParagraph *sp = doc->paragAt( startId ); 315 QTextParagraph *sp = doc->paragAt( startId );
307 QTextParagraph *ep = doc->paragAt( endId ); 316 QTextParagraph *ep = doc->paragAt( endId );
308 if ( !sp || !ep ) 317 if ( !sp || !ep )
309 return 0; 318 return 0;
310 319
311 int idx = startIndex; 320 int idx = startIndex;
312 int fIndex = 0; 321 int fIndex = 0;
313 for ( ;; ) { 322 for ( ;; ) {
314 if ( oldFormats.at( fIndex ).c == '\n' ) { 323 if ( oldFormats.at( fIndex ).c == '\n' ) {
315 if ( idx > 0 ) { 324 if ( idx > 0 ) {
316 if ( idx < sp->length() && fIndex > 0 ) 325 if ( idx < sp->length() && fIndex > 0 )
317 sp->setFormat( idx, 1, oldFormats.at( fIndex - 1 ).format() ); 326 sp->setFormat( idx, 1, oldFormats.at( fIndex - 1 ).format() );
318 if ( sp == ep ) 327 if ( sp == ep )
319 break; 328 break;
320 sp = sp->next(); 329 sp = sp->next();
321 idx = 0; 330 idx = 0;
322 } 331 }
323 fIndex++; 332 fIndex++;
324 } 333 }
325 if ( oldFormats.at( fIndex ).format() ) 334 if ( oldFormats.at( fIndex ).format() )
326 sp->setFormat( idx, 1, oldFormats.at( fIndex ).format() ); 335 sp->setFormat( idx, 1, oldFormats.at( fIndex ).format() );
327 idx++; 336 idx++;
328 fIndex++; 337 fIndex++;
329 if ( fIndex >= (int)oldFormats.size() ) 338 if ( fIndex >= (int)oldFormats.size() )
330 break; 339 break;
331 if ( idx >= sp->length() ) { 340 if ( idx >= sp->length() ) {
332 if ( sp == ep ) 341 if ( sp == ep )
333 break; 342 break;
334 sp = sp->next(); 343 sp = sp->next();
335 idx = 0; 344 idx = 0;
336 } 345 }
337 } 346 }
338 347
339 QTextCursor end( doc ); 348 QTextCursor end( doc );
340 end.setParagraph( ep ); 349 end.setParagraph( ep );
341 end.setIndex( endIndex ); 350 end.setIndex( endIndex );
342 if ( endIndex == ep->length() ) 351 if ( endIndex == ep->length() )
343 end.gotoLeft(); 352 end.gotoLeft();
344 *c = end; 353 *c = end;
345 return c; 354 return c;
346} 355}
347 356
348QTextStyleCommand::QTextStyleCommand( QTextDocument *d, int fParag, int lParag, const QByteArray& beforeChange ) 357QTextStyleCommand::QTextStyleCommand( QTextDocument *d, int fParag, int lParag, const QByteArray& beforeChange )
349 : QTextCommand( d ), firstParag( fParag ), lastParag( lParag ), before( beforeChange ) 358 : QTextCommand( d ), firstParag( fParag ), lastParag( lParag ), before( beforeChange )
350{ 359{
351 after = readStyleInformation( d, fParag, lParag ); 360 after = readStyleInformation( d, fParag, lParag );
352} 361}
353 362
354 363
355QByteArray QTextStyleCommand::readStyleInformation( QTextDocument* doc, int fParag, int lParag ) 364QByteArray QTextStyleCommand::readStyleInformation( QTextDocument* doc, int fParag, int lParag )
356{ 365{
357 QByteArray style; 366 QByteArray style;
358 QTextParagraph *p = doc->paragAt( fParag ); 367 QTextParagraph *p = doc->paragAt( fParag );
359 if ( !p ) 368 if ( !p )
360 return style; 369 return style;
361 QDataStream styleStream( style, IO_WriteOnly ); 370 QDataStream styleStream( style, IO_WriteOnly );
362 int num = lParag - fParag + 1; 371 int num = lParag - fParag + 1;
363 styleStream << num; 372 styleStream << num;
364 while ( num -- && p ) { 373 while ( num -- && p ) {
365 p->writeStyleInformation( styleStream ); 374 p->writeStyleInformation( styleStream );
366 p = p->next(); 375 p = p->next();
367 } 376 }
368 return style; 377 return style;
369} 378}
370 379
371void QTextStyleCommand::writeStyleInformation( QTextDocument* doc, int fParag, const QByteArray& style ) 380void QTextStyleCommand::writeStyleInformation( QTextDocument* doc, int fParag, const QByteArray& style )
372{ 381{
373 QTextParagraph *p = doc->paragAt( fParag ); 382 QTextParagraph *p = doc->paragAt( fParag );
374 if ( !p ) 383 if ( !p )
375 return; 384 return;
376 QDataStream styleStream( style, IO_ReadOnly ); 385 QDataStream styleStream( style, IO_ReadOnly );
377 int num; 386 int num;
378 styleStream >> num; 387 styleStream >> num;
379 while ( num-- && p ) { 388 while ( num-- && p ) {
380 p->readStyleInformation( styleStream ); 389 p->readStyleInformation( styleStream );
381 p = p->next(); 390 p = p->next();
382 } 391 }
383} 392}
384 393
385QTextCursor *QTextStyleCommand::execute( QTextCursor *c ) 394QTextCursor *QTextStyleCommand::execute( QTextCursor *c )
386{ 395{
387 writeStyleInformation( doc, firstParag, after ); 396 writeStyleInformation( doc, firstParag, after );
388 return c; 397 return c;
389} 398}
390 399
391QTextCursor *QTextStyleCommand::unexecute( QTextCursor *c ) 400QTextCursor *QTextStyleCommand::unexecute( QTextCursor *c )
392{ 401{
393 writeStyleInformation( doc, firstParag, before ); 402 writeStyleInformation( doc, firstParag, before );
394 return c; 403 return c;
395} 404}
396 405
397// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 406// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
398 407
399QTextCursor::QTextCursor( QTextDocument *d ) 408QTextCursor::QTextCursor( QTextDocument *d )
400 : idx( 0 ), tmpIndex( -1 ), ox( 0 ), oy( 0 ), 409 : idx( 0 ), tmpIndex( -1 ), ox( 0 ), oy( 0 ),
401 valid( TRUE ) 410 valid( TRUE )
402{ 411{
403 para = d ? d->firstParagraph() : 0; 412 para = d ? d->firstParagraph() : 0;
404} 413}
405 414
406QTextCursor::QTextCursor( const QTextCursor &c ) 415QTextCursor::QTextCursor( const QTextCursor &c )
407{ 416{
408 ox = c.ox; 417 ox = c.ox;
409 oy = c.oy; 418 oy = c.oy;
410 idx = c.idx; 419 idx = c.idx;
411 para = c.para; 420 para = c.para;
412 tmpIndex = c.tmpIndex; 421 tmpIndex = c.tmpIndex;
413 indices = c.indices; 422 indices = c.indices;
414 paras = c.paras; 423 paras = c.paras;
415 xOffsets = c.xOffsets; 424 xOffsets = c.xOffsets;
416 yOffsets = c.yOffsets; 425 yOffsets = c.yOffsets;
417 valid = c.valid; 426 valid = c.valid;
418} 427}
419 428
420QTextCursor &QTextCursor::operator=( const QTextCursor &c ) 429QTextCursor &QTextCursor::operator=( const QTextCursor &c )
421{ 430{
422 ox = c.ox; 431 ox = c.ox;
423 oy = c.oy; 432 oy = c.oy;
424 idx = c.idx; 433 idx = c.idx;
425 para = c.para; 434 para = c.para;
426 tmpIndex = c.tmpIndex; 435 tmpIndex = c.tmpIndex;
427 indices = c.indices; 436 indices = c.indices;
428 paras = c.paras; 437 paras = c.paras;
429 xOffsets = c.xOffsets; 438 xOffsets = c.xOffsets;
430 yOffsets = c.yOffsets; 439 yOffsets = c.yOffsets;
431 valid = c.valid; 440 valid = c.valid;
432 441
433 return *this; 442 return *this;
434} 443}
435 444
436bool QTextCursor::operator==( const QTextCursor &c ) const 445bool QTextCursor::operator==( const QTextCursor &c ) const
437{ 446{
438 return para == c.para && idx == c.idx; 447 return para == c.para && idx == c.idx;
439} 448}
440 449
441int QTextCursor::totalOffsetX() const 450int QTextCursor::totalOffsetX() const
442{ 451{
443 int xoff = ox; 452 int xoff = ox;
444 for ( QValueStack<int>::ConstIterator xit = xOffsets.begin(); xit != xOffsets.end(); ++xit ) 453 for ( QValueStack<int>::ConstIterator xit = xOffsets.begin(); xit != xOffsets.end(); ++xit )
445 xoff += *xit; 454 xoff += *xit;
446 return xoff; 455 return xoff;
447} 456}
448 457
449int QTextCursor::totalOffsetY() const 458int QTextCursor::totalOffsetY() const
450{ 459{
451 int yoff = oy; 460 int yoff = oy;
452 for ( QValueStack<int>::ConstIterator yit = yOffsets.begin(); yit != yOffsets.end(); ++yit ) 461 for ( QValueStack<int>::ConstIterator yit = yOffsets.begin(); yit != yOffsets.end(); ++yit )
453 yoff += *yit; 462 yoff += *yit;
454 return yoff; 463 return yoff;
455} 464}
456 465
457void QTextCursor::gotoIntoNested( const QPoint &globalPos ) 466void QTextCursor::gotoIntoNested( const QPoint &globalPos )
458{ 467{
459 if ( !para ) 468 if ( !para )
460 return; 469 return;
461 push(); 470 push();
462 ox = 0; 471 ox = 0;
463 int bl, y; 472 int bl, y;
464 para->lineHeightOfChar( idx, &bl, &y ); 473 para->lineHeightOfChar( idx, &bl, &y );
465 oy = y + para->rect().y(); 474 oy = y + para->rect().y();
466 QPoint p( globalPos.x() - offsetX(), globalPos.y() - offsetY() ); 475 QPoint p( globalPos.x() - offsetX(), globalPos.y() - offsetY() );
467 Q_ASSERT( para->at( idx )->isCustom() ); 476 Q_ASSERT( para->at( idx )->isCustom() );
468 ox = para->at( idx )->x; 477 ox = para->at( idx )->x;
469 478
470 QTextDocument* doc = document(); 479 QTextDocument* doc = document();
471 para->at( idx )->customItem()->enterAt( this, doc, para, idx, ox, oy, p ); 480 para->at( idx )->customItem()->enterAt( this, doc, para, idx, ox, oy, p );
472} 481}
473 482
474void QTextCursor::invalidateNested() 483void QTextCursor::invalidateNested()
475{ 484{
476 QValueStack<QTextParagraph*>::Iterator it = paras.begin(); 485 QValueStack<QTextParagraph*>::Iterator it = paras.begin();
477 QValueStack<int>::Iterator it2 = indices.begin(); 486 QValueStack<int>::Iterator it2 = indices.begin();
478 for ( ; it != paras.end(); ++it, ++it2 ) { 487 for ( ; it != paras.end(); ++it, ++it2 ) {
479 if ( *it == para ) 488 if ( *it == para )
480 continue; 489 continue;
481 (*it)->invalidate( 0 ); 490 (*it)->invalidate( 0 );
482 if ( (*it)->at( *it2 )->isCustom() ) 491 if ( (*it)->at( *it2 )->isCustom() )
483 (*it)->at( *it2 )->customItem()->invalidate(); 492 (*it)->at( *it2 )->customItem()->invalidate();
484 } 493 }
485} 494}
486 495
487void QTextCursor::insert( const QString &str, bool checkNewLine, QMemArray<QTextStringChar> *formatting ) 496void QTextCursor::insert( const QString &str, bool checkNewLine, QMemArray<QTextStringChar> *formatting )
488{ 497{
489 tmpIndex = -1; 498 tmpIndex = -1;
490 bool justInsert = TRUE; 499 bool justInsert = TRUE;
491 QString s( str ); 500 QString s( str );
492#if defined(Q_WS_WIN) 501#if defined(Q_WS_WIN)
493 if ( checkNewLine ) { 502 if ( checkNewLine ) {
494 int i = 0; 503 int i = 0;
495 while ( ( i = s.find( '\r', i ) ) != -1 ) 504 while ( ( i = s.find( '\r', i ) ) != -1 )
496 s.remove( i ,1 ); 505 s.remove( i ,1 );
497 } 506 }
498#endif 507#endif
499 if ( checkNewLine ) 508 if ( checkNewLine )
500 justInsert = s.find( '\n' ) == -1; 509 justInsert = s.find( '\n' ) == -1;
501 if ( justInsert ) { // we ignore new lines and insert all in the current para at the current index 510 if ( justInsert ) { // we ignore new lines and insert all in the current para at the current index
502 para->insert( idx, s.unicode(), s.length() ); 511 para->insert( idx, s.unicode(), s.length() );
503 if ( formatting ) { 512 if ( formatting ) {
504 for ( int i = 0; i < (int)s.length(); ++i ) { 513 for ( int i = 0; i < (int)s.length(); ++i ) {
505 if ( formatting->at( i ).format() ) { 514 if ( formatting->at( i ).format() ) {
506 formatting->at( i ).format()->addRef(); 515 formatting->at( i ).format()->addRef();
507 para->string()->setFormat( idx + i, formatting->at( i ).format(), TRUE ); 516 para->string()->setFormat( idx + i, formatting->at( i ).format(), TRUE );
508 } 517 }
509 } 518 }
510 } 519 }
511 idx += s.length(); 520 idx += s.length();
512 } else { // we split at new lines 521 } else { // we split at new lines
513 int start = -1; 522 int start = -1;
514 int end; 523 int end;
515 int y = para->rect().y() + para->rect().height(); 524 int y = para->rect().y() + para->rect().height();
516 int lastIndex = 0; 525 int lastIndex = 0;
517 do { 526 do {
518 end = s.find( '\n', start + 1 ); // find line break 527 end = s.find( '\n', start + 1 ); // find line break
519 if ( end == -1 ) // didn't find one, so end of line is end of string 528 if ( end == -1 ) // didn't find one, so end of line is end of string
520 end = s.length(); 529 end = s.length();
521 int len = (start == -1 ? end : end - start - 1); 530 int len = (start == -1 ? end : end - start - 1);
522 if ( len > 0 ) // insert the line 531 if ( len > 0 ) // insert the line
523 para->insert( idx, s.unicode() + start + 1, len ); 532 para->insert( idx, s.unicode() + start + 1, len );
524 else 533 else
525 para->invalidate( 0 ); 534 para->invalidate( 0 );
526 if ( formatting ) { // set formats to the chars of the line 535 if ( formatting ) { // set formats to the chars of the line
527 for ( int i = 0; i < len; ++i ) { 536 for ( int i = 0; i < len; ++i ) {
528 if ( formatting->at( i + lastIndex ).format() ) { 537 if ( formatting->at( i + lastIndex ).format() ) {
529 formatting->at( i + lastIndex ).format()->addRef(); 538 formatting->at( i + lastIndex ).format()->addRef();
530 para->string()->setFormat( i + idx, formatting->at( i + lastIndex ).format(), TRUE ); 539 para->string()->setFormat( i + idx, formatting->at( i + lastIndex ).format(), TRUE );
531 } 540 }
532 } 541 }
533 lastIndex += len; 542 lastIndex += len;
534 } 543 }
535 start = end; // next start is at the end of this line 544 start = end; // next start is at the end of this line
536 idx += len; // increase the index of the cursor to the end of the inserted text 545 idx += len; // increase the index of the cursor to the end of the inserted text
537 if ( s[end] == '\n' ) { // if at the end was a line break, break the line 546 if ( s[end] == '\n' ) { // if at the end was a line break, break the line
538 splitAndInsertEmptyParagraph( FALSE, TRUE ); 547 splitAndInsertEmptyParagraph( FALSE, TRUE );
539 para->setEndState( -1 ); 548 para->setEndState( -1 );
540 para->prev()->format( -1, FALSE ); 549 para->prev()->format( -1, FALSE );
541 lastIndex++; 550 lastIndex++;
542 } 551 }
543 552
544 } while ( end < (int)s.length() ); 553 } while ( end < (int)s.length() );
545 554
546 para->format( -1, FALSE ); 555 para->format( -1, FALSE );
547 int dy = para->rect().y() + para->rect().height() - y; 556 int dy = para->rect().y() + para->rect().height() - y;
548 QTextParagraph *p = para; 557 QTextParagraph *p = para;
549 p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 ); 558 p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 );
550 p = p->next(); 559 p = p->next();
551 while ( p ) { 560 while ( p ) {
552 p->setParagId( p->prev()->paragId() + 1 ); 561 p->setParagId( p->prev()->paragId() + 1 );
553 p->move( dy ); 562 p->move( dy );
554 p->invalidate( 0 ); 563 p->invalidate( 0 );
555 p->setEndState( -1 ); 564 p->setEndState( -1 );
556 p = p->next(); 565 p = p->next();
557 } 566 }
558 } 567 }
559 568
560 int h = para->rect().height(); 569 int h = para->rect().height();
561 para->format( -1, TRUE ); 570 para->format( -1, TRUE );
562 if ( h != para->rect().height() ) 571 if ( h != para->rect().height() )
563 invalidateNested(); 572 invalidateNested();
564 else if ( para->document() && para->document()->parent() ) 573 else if ( para->document() && para->document()->parent() )
565 para->document()->nextDoubleBuffered = TRUE; 574 para->document()->nextDoubleBuffered = TRUE;
566} 575}
567 576
568void QTextCursor::gotoLeft() 577void QTextCursor::gotoLeft()
569{ 578{
570 if ( para->string()->isRightToLeft() ) 579 if ( para->string()->isRightToLeft() )
571 gotoNextLetter(); 580 gotoNextLetter();
572 else 581 else
573 gotoPreviousLetter(); 582 gotoPreviousLetter();
574} 583}
575 584
576void QTextCursor::gotoPreviousLetter() 585void QTextCursor::gotoPreviousLetter()
577{ 586{
578 tmpIndex = -1; 587 tmpIndex = -1;
579 588
580 if ( idx > 0 ) { 589 if ( idx > 0 ) {
581 idx--; 590 idx--;
582 const QTextStringChar *tsc = para->at( idx ); 591 const QTextStringChar *tsc = para->at( idx );
583 if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) 592 if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() )
584 processNesting( EnterEnd ); 593 processNesting( EnterEnd );
585 } else if ( para->prev() ) { 594 } else if ( para->prev() ) {
586 para = para->prev(); 595 para = para->prev();
587 while ( !para->isVisible() && para->prev() ) 596 while ( !para->isVisible() && para->prev() )
588 para = para->prev(); 597 para = para->prev();
589 idx = para->length() - 1; 598 idx = para->length() - 1;
590 } else if ( nestedDepth() ) { 599 } else if ( nestedDepth() ) {
591 pop(); 600 pop();
592 processNesting( Prev ); 601 processNesting( Prev );
593 if ( idx == -1 ) { 602 if ( idx == -1 ) {
594 pop(); 603 pop();
595 if ( idx > 0 ) { 604 if ( idx > 0 ) {
596 idx--; 605 idx--;
597 } else if ( para->prev() ) { 606 } else if ( para->prev() ) {
598 para = para->prev(); 607 para = para->prev();
599 idx = para->length() - 1; 608 idx = para->length() - 1;
600 } 609 }
601 } 610 }
602 } 611 }
603} 612}
604 613
605void QTextCursor::push() 614void QTextCursor::push()
606{ 615{
607 indices.push( idx ); 616 indices.push( idx );
608 paras.push( para ); 617 paras.push( para );
609 xOffsets.push( ox ); 618 xOffsets.push( ox );
610 yOffsets.push( oy ); 619 yOffsets.push( oy );
611} 620}
612 621
613void QTextCursor::pop() 622void QTextCursor::pop()
614{ 623{
615 if ( indices.isEmpty() ) 624 if ( indices.isEmpty() )
616 return; 625 return;
617 idx = indices.pop(); 626 idx = indices.pop();
618 para = paras.pop(); 627 para = paras.pop();
619 ox = xOffsets.pop(); 628 ox = xOffsets.pop();
620 oy = yOffsets.pop(); 629 oy = yOffsets.pop();
621} 630}
622 631
623void QTextCursor::restoreState() 632void QTextCursor::restoreState()
624{ 633{
625 while ( !indices.isEmpty() ) 634 while ( !indices.isEmpty() )
626 pop(); 635 pop();
627} 636}
628 637
629bool QTextCursor::place( const QPoint &p, QTextParagraph *s, bool link ) 638bool QTextCursor::place( const QPoint &p, QTextParagraph *s, bool link )
630{ 639{
631 QPoint pos( p ); 640 QPoint pos( p );
632 QRect r; 641 QRect r;
633 QTextParagraph *str = s; 642 QTextParagraph *str = s;
634 if ( pos.y() < s->rect().y() ) 643 if ( pos.y() < s->rect().y() )
635 pos.setY( s->rect().y() ); 644 pos.setY( s->rect().y() );
636 while ( s ) { 645 while ( s ) {
637 r = s->rect(); 646 r = s->rect();
638 r.setWidth( document() ? document()->width() : QWIDGETSIZE_MAX ); 647 r.setWidth( document() ? document()->width() : QWIDGETSIZE_MAX );
639 if ( s->isVisible() ) 648 if ( s->isVisible() )
640 str = s; 649 str = s;
641 if ( pos.y() >= r.y() && pos.y() <= r.y() + r.height() || !s->next() ) 650 if ( pos.y() >= r.y() && pos.y() <= r.y() + r.height() || !s->next() )
642 break; 651 break;
643 s = s->next(); 652 s = s->next();
644 } 653 }
645 654
646 if ( !s || !str ) 655 if ( !s || !str )
647 return FALSE; 656 return FALSE;
648 657
649 s = str; 658 s = str;
650 659
651 setParagraph( s ); 660 setParagraph( s );
652 int y = s->rect().y(); 661 int y = s->rect().y();
653 int lines = s->lines(); 662 int lines = s->lines();
654 QTextStringChar *chr = 0; 663 QTextStringChar *chr = 0;
655 int index = 0; 664 int index = 0;
656 int i = 0; 665 int i = 0;
657 int cy = 0; 666 int cy = 0;
658 int ch = 0; 667 int ch = 0;
659 for ( ; i < lines; ++i ) { 668 for ( ; i < lines; ++i ) {
660 chr = s->lineStartOfLine( i, &index ); 669 chr = s->lineStartOfLine( i, &index );
661 cy = s->lineY( i ); 670 cy = s->lineY( i );
662 ch = s->lineHeight( i ); 671 ch = s->lineHeight( i );
663 if ( !chr ) 672 if ( !chr )
664 return FALSE; 673 return FALSE;
665 if ( pos.y() <= y + cy + ch ) 674 if ( pos.y() <= y + cy + ch )
666 break; 675 break;
667 } 676 }
668 int nextLine; 677 int nextLine;
669 if ( i < lines - 1 ) 678 if ( i < lines - 1 )
670 s->lineStartOfLine( i+1, &nextLine ); 679 s->lineStartOfLine( i+1, &nextLine );
671 else 680 else
672 nextLine = s->length(); 681 nextLine = s->length();
673 i = index; 682 i = index;
674 int x = s->rect().x(); 683 int x = s->rect().x();
675 if ( pos.x() < x ) 684 if ( pos.x() < x )
676 pos.setX( x + 1 ); 685 pos.setX( x + 1 );
677 int cw; 686 int cw;
678 int curpos = s->length()-1; 687 int curpos = s->length()-1;
679 int dist = 10000000; 688 int dist = 10000000;
680 bool inCustom = FALSE; 689 bool inCustom = FALSE;
681 while ( i < nextLine ) { 690 while ( i < nextLine ) {
682 chr = s->at(i); 691 chr = s->at(i);
683 int cpos = x + chr->x; 692 int cpos = x + chr->x;
684 cw = s->string()->width( i ); 693 cw = s->string()->width( i );
685 if ( chr->isCustom() && chr->customItem()->isNested() ) { 694 if ( chr->isCustom() && chr->customItem()->isNested() ) {
686 if ( pos.x() >= cpos && pos.x() <= cpos + cw && 695 if ( pos.x() >= cpos && pos.x() <= cpos + cw &&
687 pos.y() >= y + cy && pos.y() <= y + cy + chr->height() ) { 696 pos.y() >= y + cy && pos.y() <= y + cy + chr->height() ) {
688 inCustom = TRUE; 697 inCustom = TRUE;
689 curpos = i; 698 curpos = i;
690 break; 699 break;
691 } 700 }
692 } else { 701 } else {
693 if( chr->rightToLeft ) 702 if( chr->rightToLeft )
694 cpos += cw; 703 cpos += cw;
695 int d = cpos - pos.x(); 704 int d = cpos - pos.x();
696 bool dm = d < 0 ? !chr->rightToLeft : chr->rightToLeft; 705 bool dm = d < 0 ? !chr->rightToLeft : chr->rightToLeft;
697 if ( QABS( d ) < dist || (dist == d && dm == TRUE ) ) { 706 if ( QABS( d ) < dist || (dist == d && dm == TRUE ) ) {
698 dist = QABS( d ); 707 dist = QABS( d );
699 if ( !link || pos.x() >= x + chr->x ) 708 if ( !link || pos.x() >= x + chr->x )
700 curpos = i; 709 curpos = i;
701 } 710 }
702 } 711 }
703 i++; 712 i++;
704 } 713 }
705 setIndex( curpos ); 714 setIndex( curpos );
706 715
707 if ( inCustom && para->document() && para->at( curpos )->isCustom() && para->at( curpos )->customItem()->isNested() ) { 716 if ( inCustom && para->document() && para->at( curpos )->isCustom() && para->at( curpos )->customItem()->isNested() ) {
708 QTextDocument *oldDoc = para->document(); 717 QTextDocument *oldDoc = para->document();
709 gotoIntoNested( pos ); 718 gotoIntoNested( pos );
710 if ( oldDoc == para->document() ) 719 if ( oldDoc == para->document() )
711 return TRUE; 720 return TRUE;
712 QPoint p( pos.x() - offsetX(), pos.y() - offsetY() ); 721 QPoint p( pos.x() - offsetX(), pos.y() - offsetY() );
713 if ( !place( p, document()->firstParagraph(), link ) ) 722 if ( !place( p, document()->firstParagraph(), link ) )
714 pop(); 723 pop();
715 } 724 }
716 return TRUE; 725 return TRUE;
717} 726}
718 727
719void QTextCursor::processNesting( Operation op ) 728void QTextCursor::processNesting( Operation op )
720{ 729{
721 if ( !para->document() ) 730 if ( !para->document() )
722 return; 731 return;
723 QTextDocument* doc = para->document(); 732 QTextDocument* doc = para->document();
724 push(); 733 push();
725 ox = para->at( idx )->x; 734 ox = para->at( idx )->x;
726 int bl, y; 735 int bl, y;
727 para->lineHeightOfChar( idx, &bl, &y ); 736 para->lineHeightOfChar( idx, &bl, &y );
728 oy = y + para->rect().y(); 737 oy = y + para->rect().y();
729 bool ok = FALSE; 738 bool ok = FALSE;
730 739
731 switch ( op ) { 740 switch ( op ) {
732 case EnterBegin: 741 case EnterBegin:
733 ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy ); 742 ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy );
734 break; 743 break;
735 case EnterEnd: 744 case EnterEnd:
736 ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy, TRUE ); 745 ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy, TRUE );
737 break; 746 break;
738 case Next: 747 case Next:
739 ok = para->at( idx )->customItem()->next( this, doc, para, idx, ox, oy ); 748 ok = para->at( idx )->customItem()->next( this, doc, para, idx, ox, oy );
740 break; 749 break;
741 case Prev: 750 case Prev:
742 ok = para->at( idx )->customItem()->prev( this, doc, para, idx, ox, oy ); 751 ok = para->at( idx )->customItem()->prev( this, doc, para, idx, ox, oy );
743 break; 752 break;
744 case Down: 753 case Down:
745 ok = para->at( idx )->customItem()->down( this, doc, para, idx, ox, oy ); 754 ok = para->at( idx )->customItem()->down( this, doc, para, idx, ox, oy );
746 break; 755 break;
747 case Up: 756 case Up:
748 ok = para->at( idx )->customItem()->up( this, doc, para, idx, ox, oy ); 757 ok = para->at( idx )->customItem()->up( this, doc, para, idx, ox, oy );
749 break; 758 break;
750 } 759 }
751 if ( !ok ) 760 if ( !ok )
752 pop(); 761 pop();
753} 762}
754 763
755void QTextCursor::gotoRight() 764void QTextCursor::gotoRight()
756{ 765{
757 if ( para->string()->isRightToLeft() ) 766 if ( para->string()->isRightToLeft() )
758 gotoPreviousLetter(); 767 gotoPreviousLetter();
759 else 768 else
760 gotoNextLetter(); 769 gotoNextLetter();
761} 770}
762 771
763void QTextCursor::gotoNextLetter() 772void QTextCursor::gotoNextLetter()
764{ 773{
765 tmpIndex = -1; 774 tmpIndex = -1;
766 775
767 const QTextStringChar *tsc = para->at( idx ); 776 const QTextStringChar *tsc = para->at( idx );
768 if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) { 777 if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) {
769 processNesting( EnterBegin ); 778 processNesting( EnterBegin );
770 return; 779 return;
771 } 780 }
772 781
773 if ( idx < para->length() - 1 ) { 782 if ( idx < para->length() - 1 ) {
774 idx++; 783 idx++;
775 } else if ( para->next() ) { 784 } else if ( para->next() ) {
776 para = para->next(); 785 para = para->next();
777 while ( !para->isVisible() && para->next() ) 786 while ( !para->isVisible() && para->next() )
778 para = para->next(); 787 para = para->next();
779 idx = 0; 788 idx = 0;
780 } else if ( nestedDepth() ) { 789 } else if ( nestedDepth() ) {
781 pop(); 790 pop();
782 processNesting( Next ); 791 processNesting( Next );
783 if ( idx == -1 ) { 792 if ( idx == -1 ) {
784 pop(); 793 pop();
785 if ( idx < para->length() - 1 ) { 794 if ( idx < para->length() - 1 ) {
786 idx++; 795 idx++;
787 } else if ( para->next() ) { 796 } else if ( para->next() ) {
788 para = para->next(); 797 para = para->next();
789 idx = 0; 798 idx = 0;
790 } 799 }
791 } 800 }
792 } 801 }
793} 802}
794 803
795void QTextCursor::gotoUp() 804void QTextCursor::gotoUp()
796{ 805{
797 int indexOfLineStart; 806 int indexOfLineStart;
798 int line; 807 int line;
799 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); 808 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line );
800 if ( !c ) 809 if ( !c )
801 return; 810 return;
802 811
803 tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart ); 812 tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart );
804 if ( indexOfLineStart == 0 ) { 813 if ( indexOfLineStart == 0 ) {
805 if ( !para->prev() ) { 814 if ( !para->prev() ) {
806 if ( !nestedDepth() ) 815 if ( !nestedDepth() )
807 return; 816 return;
808 pop(); 817 pop();
809 processNesting( Up ); 818 processNesting( Up );
810 if ( idx == -1 ) { 819 if ( idx == -1 ) {
811 pop(); 820 pop();
812 if ( !para->prev() ) 821 if ( !para->prev() )
813 return; 822 return;
814 idx = tmpIndex = 0; 823 idx = tmpIndex = 0;
815 } else { 824 } else {
816 tmpIndex = -1; 825 tmpIndex = -1;
817 return; 826 return;
818 } 827 }
819 } 828 }
820 QTextParagraph *p = para->prev(); 829 QTextParagraph *p = para->prev();
821 while ( p && !p->isVisible() ) 830 while ( p && !p->isVisible() )
822 p = p->prev(); 831 p = p->prev();
823 if ( p ) 832 if ( p )
824 para = p; 833 para = p;
825 int lastLine = para->lines() - 1; 834 int lastLine = para->lines() - 1;
826 if ( !para->lineStartOfLine( lastLine, &indexOfLineStart ) ) 835 if ( !para->lineStartOfLine( lastLine, &indexOfLineStart ) )
827 return; 836 return;
828 if ( indexOfLineStart + tmpIndex < para->length() ) 837 if ( indexOfLineStart + tmpIndex < para->length() )
829 idx = indexOfLineStart + tmpIndex; 838 idx = indexOfLineStart + tmpIndex;
830 else 839 else
831 idx = para->length() - 1; 840 idx = para->length() - 1;
832 } else { 841 } else {
833 --line; 842 --line;
834 int oldIndexOfLineStart = indexOfLineStart; 843 int oldIndexOfLineStart = indexOfLineStart;
835 if ( !para->lineStartOfLine( line, &indexOfLineStart ) ) 844 if ( !para->lineStartOfLine( line, &indexOfLineStart ) )
836 return; 845 return;
837 if ( indexOfLineStart + tmpIndex < oldIndexOfLineStart ) 846 if ( indexOfLineStart + tmpIndex < oldIndexOfLineStart )
838 idx = indexOfLineStart + tmpIndex; 847 idx = indexOfLineStart + tmpIndex;
839 else 848 else
840 idx = oldIndexOfLineStart - 1; 849 idx = oldIndexOfLineStart - 1;
841 } 850 }
842} 851}
843 852
844void QTextCursor::gotoDown() 853void QTextCursor::gotoDown()
845{ 854{
846 int indexOfLineStart; 855 int indexOfLineStart;
847 int line; 856 int line;
848 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); 857 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line );
849 if ( !c ) 858 if ( !c )
850 return; 859 return;
851 860
852 tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart ); 861 tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart );
853 if ( line == para->lines() - 1 ) { 862 if ( line == para->lines() - 1 ) {
854 if ( !para->next() ) { 863 if ( !para->next() ) {
855 if ( !nestedDepth() ) 864 if ( !nestedDepth() )
856 return; 865 return;
857 pop(); 866 pop();
858 processNesting( Down ); 867 processNesting( Down );
859 if ( idx == -1 ) { 868 if ( idx == -1 ) {
860 pop(); 869 pop();
861 if ( !para->next() ) 870 if ( !para->next() )
862 return; 871 return;
863 idx = tmpIndex = 0; 872 idx = tmpIndex = 0;
864 } else { 873 } else {
865 tmpIndex = -1; 874 tmpIndex = -1;
866 return; 875 return;
867 } 876 }
868 } 877 }
869 QTextParagraph *s = para->next(); 878 QTextParagraph *s = para->next();
870 while ( s && !s->isVisible() ) 879 while ( s && !s->isVisible() )
871 s = s->next(); 880 s = s->next();
872 if ( s ) 881 if ( s )
873 para = s; 882 para = s;
874 if ( !para->lineStartOfLine( 0, &indexOfLineStart ) ) 883 if ( !para->lineStartOfLine( 0, &indexOfLineStart ) )
875 return; 884 return;
876 int end; 885 int end;
877 if ( para->lines() == 1 ) 886 if ( para->lines() == 1 )
878 end = para->length(); 887 end = para->length();
879 else 888 else
880 para->lineStartOfLine( 1, &end ); 889 para->lineStartOfLine( 1, &end );
881 if ( indexOfLineStart + tmpIndex < end ) 890 if ( indexOfLineStart + tmpIndex < end )
882 idx = indexOfLineStart + tmpIndex; 891 idx = indexOfLineStart + tmpIndex;
883 else 892 else
884 idx = end - 1; 893 idx = end - 1;
885 } else { 894 } else {
886 ++line; 895 ++line;
887 int end; 896 int end;
888 if ( line == para->lines() - 1 ) 897 if ( line == para->lines() - 1 )
889 end = para->length(); 898 end = para->length();
890 else 899 else
891 para->lineStartOfLine( line + 1, &end ); 900 para->lineStartOfLine( line + 1, &end );
892 if ( !para->lineStartOfLine( line, &indexOfLineStart ) ) 901 if ( !para->lineStartOfLine( line, &indexOfLineStart ) )
893 return; 902 return;
894 if ( indexOfLineStart + tmpIndex < end ) 903 if ( indexOfLineStart + tmpIndex < end )
895 idx = indexOfLineStart + tmpIndex; 904 idx = indexOfLineStart + tmpIndex;
896 else 905 else
897 idx = end - 1; 906 idx = end - 1;
898 } 907 }
899} 908}
900 909
901void QTextCursor::gotoLineEnd() 910void QTextCursor::gotoLineEnd()
902{ 911{
903 tmpIndex = -1; 912 tmpIndex = -1;
904 int indexOfLineStart; 913 int indexOfLineStart;
905 int line; 914 int line;
906 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); 915 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line );
907 if ( !c ) 916 if ( !c )
908 return; 917 return;
909 918
910 if ( line == para->lines() - 1 ) { 919 if ( line == para->lines() - 1 ) {
911 idx = para->length() - 1; 920 idx = para->length() - 1;
912 } else { 921 } else {
913 c = para->lineStartOfLine( ++line, &indexOfLineStart ); 922 c = para->lineStartOfLine( ++line, &indexOfLineStart );
914 indexOfLineStart--; 923 indexOfLineStart--;
915 idx = indexOfLineStart; 924 idx = indexOfLineStart;
916 } 925 }
917} 926}
918 927
919void QTextCursor::gotoLineStart() 928void QTextCursor::gotoLineStart()
920{ 929{
921 tmpIndex = -1; 930 tmpIndex = -1;
922 int indexOfLineStart; 931 int indexOfLineStart;
923 int line; 932 int line;
924 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); 933 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line );
925 if ( !c ) 934 if ( !c )
926 return; 935 return;
927 936
928 idx = indexOfLineStart; 937 idx = indexOfLineStart;
929} 938}
930 939
931void QTextCursor::gotoHome() 940void QTextCursor::gotoHome()
932{ 941{
933 if ( topParagraph()->document() ) 942 if ( topParagraph()->document() )
934 gotoPosition( topParagraph()->document()->firstParagraph() ); 943 gotoPosition( topParagraph()->document()->firstParagraph() );
935 else 944 else
936 gotoLineStart(); 945 gotoLineStart();
937} 946}
938 947
939void QTextCursor::gotoEnd() 948void QTextCursor::gotoEnd()
940{ 949{
941 if ( topParagraph()->document() && topParagraph()->document()->lastParagraph()->isValid() ) 950 if ( topParagraph()->document() && topParagraph()->document()->lastParagraph()->isValid() )
942 gotoPosition( topParagraph()->document()->lastParagraph(), 951 gotoPosition( topParagraph()->document()->lastParagraph(),
943 topParagraph()->document()->lastParagraph()->length() - 1); 952 topParagraph()->document()->lastParagraph()->length() - 1);
944 else 953 else
945 gotoLineEnd(); 954 gotoLineEnd();
946} 955}
947 956
948void QTextCursor::gotoPageUp( int visibleHeight ) 957void QTextCursor::gotoPageUp( int visibleHeight )
949{ 958{
950 int targetY = globalY() - visibleHeight; 959 int targetY = globalY() - visibleHeight;
951 QTextParagraph* old; int index; 960 QTextParagraph* old; int index;
952 do { 961 do {
953 old = para; index = idx; 962 old = para; index = idx;
954 gotoUp(); 963 gotoUp();
955 } while ( (old != para || index != idx) && globalY() > targetY ); 964 } while ( (old != para || index != idx) && globalY() > targetY );
956} 965}
957 966
958void QTextCursor::gotoPageDown( int visibleHeight ) 967void QTextCursor::gotoPageDown( int visibleHeight )
959{ 968{
960 int targetY = globalY() + visibleHeight; 969 int targetY = globalY() + visibleHeight;
961 QTextParagraph* old; int index; 970 QTextParagraph* old; int index;
962 do { 971 do {
963 old = para; index = idx; 972 old = para; index = idx;
964 gotoDown(); 973 gotoDown();
965 } while ( (old != para || index != idx) && globalY() < targetY ); 974 } while ( (old != para || index != idx) && globalY() < targetY );
966} 975}
967 976
968void QTextCursor::gotoWordRight() 977void QTextCursor::gotoWordRight()
969{ 978{
970 if ( para->string()->isRightToLeft() ) 979 if ( para->string()->isRightToLeft() )
971 gotoPreviousWord(); 980 gotoPreviousWord();
972 else 981 else
973 gotoNextWord(); 982 gotoNextWord();
974} 983}
975 984
976void QTextCursor::gotoWordLeft() 985void QTextCursor::gotoWordLeft()
977{ 986{
978 if ( para->string()->isRightToLeft() ) 987 if ( para->string()->isRightToLeft() )
979 gotoNextWord(); 988 gotoNextWord();
980 else 989 else
981 gotoPreviousWord(); 990 gotoPreviousWord();
982} 991}
983 992
984void QTextCursor::gotoPreviousWord() 993void QTextCursor::gotoPreviousWord()
985{ 994{
986 gotoPreviousLetter(); 995 gotoPreviousLetter();
987 tmpIndex = -1; 996 tmpIndex = -1;
988 QTextString *s = para->string(); 997 QTextString *s = para->string();
989 bool allowSame = FALSE; 998 bool allowSame = FALSE;
990 if ( idx == ((int)s->length()-1) ) 999 if ( idx == ((int)s->length()-1) )
991 return; 1000 return;
992 for ( int i = idx; i >= 0; --i ) { 1001 for ( int i = idx; i >= 0; --i ) {
993 if ( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' || 1002 if ( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
994 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) { 1003 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) {
995 if ( !allowSame ) 1004 if ( !allowSame )
996 continue; 1005 continue;
997 idx = i + 1; 1006 idx = i + 1;
998 return; 1007 return;
999 } 1008 }
1000 if ( !allowSame && !( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' || 1009 if ( !allowSame && !( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
1001 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) ) 1010 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) )
1002 allowSame = TRUE; 1011 allowSame = TRUE;
1003 } 1012 }
1004 idx = 0; 1013 idx = 0;
1005} 1014}
1006 1015
1007void QTextCursor::gotoNextWord() 1016void QTextCursor::gotoNextWord()
1008{ 1017{
1009 tmpIndex = -1; 1018 tmpIndex = -1;
1010 QTextString *s = para->string(); 1019 QTextString *s = para->string();
1011 bool allowSame = FALSE; 1020 bool allowSame = FALSE;
1012 for ( int i = idx; i < (int)s->length(); ++i ) { 1021 for ( int i = idx; i < (int)s->length(); ++i ) {
1013 if ( ! (s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' || 1022 if ( ! (s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
1014 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';') ) { 1023 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';') ) {
1015 if ( !allowSame ) 1024 if ( !allowSame )
1016 continue; 1025 continue;
1017 idx = i; 1026 idx = i;
1018 return; 1027 return;
1019 } 1028 }
1020 if ( !allowSame && ( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' || 1029 if ( !allowSame && ( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
1021 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) ) 1030 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) )
1022 allowSame = TRUE; 1031 allowSame = TRUE;
1023 1032
1024 } 1033 }
1025 1034
1026 if ( idx < ((int)s->length()-1) ) { 1035 if ( idx < ((int)s->length()-1) ) {
1027 gotoLineEnd(); 1036 gotoLineEnd();
1028 } else if ( para->next() ) { 1037 } else if ( para->next() ) {
1029 QTextParagraph *p = para->next(); 1038 QTextParagraph *p = para->next();
1030 while ( p && !p->isVisible() ) 1039 while ( p && !p->isVisible() )
1031 p = p->next(); 1040 p = p->next();
1032 if ( s ) { 1041 if ( s ) {
1033 para = p; 1042 para = p;
1034 idx = 0; 1043 idx = 0;
1035 } 1044 }
1036 } else { 1045 } else {
1037 gotoLineEnd(); 1046 gotoLineEnd();
1038 } 1047 }
1039} 1048}
1040 1049
1041bool QTextCursor::atParagStart() 1050bool QTextCursor::atParagStart()
1042{ 1051{
1043 return idx == 0; 1052 return idx == 0;
1044} 1053}
1045 1054
1046bool QTextCursor::atParagEnd() 1055bool QTextCursor::atParagEnd()
1047{ 1056{
1048 return idx == para->length() - 1; 1057 return idx == para->length() - 1;
1049} 1058}
1050 1059
1051void QTextCursor::splitAndInsertEmptyParagraph( bool ind, bool updateIds ) 1060void QTextCursor::splitAndInsertEmptyParagraph( bool ind, bool updateIds )
1052{ 1061{
1053 if ( !para->document() ) 1062 if ( !para->document() )
1054 return; 1063 return;
1055 tmpIndex = -1; 1064 tmpIndex = -1;
1056 QTextFormat *f = 0; 1065 QTextFormat *f = 0;
1057 if ( para->document()->useFormatCollection() ) { 1066 if ( para->document()->useFormatCollection() ) {
1058 f = para->at( idx )->format(); 1067 f = para->at( idx )->format();
1059 if ( idx == para->length() - 1 && idx > 0 ) 1068 if ( idx == para->length() - 1 && idx > 0 )
1060 f = para->at( idx - 1 )->format(); 1069 f = para->at( idx - 1 )->format();
1061 if ( f->isMisspelled() ) { 1070 if ( f->isMisspelled() ) {
1062 f->removeRef(); 1071 f->removeRef();
1063 f = para->document()->formatCollection()->format( f->font(), f->color() ); 1072 f = para->document()->formatCollection()->format( f->font(), f->color() );
1064 } 1073 }
1065 } 1074 }
1066 1075
1067 if ( atParagEnd() ) { 1076 if ( atParagEnd() ) {
1068 QTextParagraph *n = para->next(); 1077 QTextParagraph *n = para->next();
1069 QTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds ); 1078 QTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds );
1070 if ( f ) 1079 if ( f )
1071 s->setFormat( 0, 1, f, TRUE ); 1080 s->setFormat( 0, 1, f, TRUE );
1072 s->copyParagData( para ); 1081 s->copyParagData( para );
1073 if ( ind ) { 1082 if ( ind ) {
1074 int oi, ni; 1083 int oi, ni;
1075 s->indent( &oi, &ni ); 1084 s->indent( &oi, &ni );
1076 para = s; 1085 para = s;
1077 idx = ni; 1086 idx = ni;
1078 } else { 1087 } else {
1079 para = s; 1088 para = s;
1080 idx = 0; 1089 idx = 0;
1081 } 1090 }
1082 } else if ( atParagStart() ) { 1091 } else if ( atParagStart() ) {
1083 QTextParagraph *p = para->prev(); 1092 QTextParagraph *p = para->prev();
1084 QTextParagraph *s = para->document()->createParagraph( para->document(), p, para, updateIds ); 1093 QTextParagraph *s = para->document()->createParagraph( para->document(), p, para, updateIds );
1085 if ( f ) 1094 if ( f )
1086 s->setFormat( 0, 1, f, TRUE ); 1095 s->setFormat( 0, 1, f, TRUE );
1087 s->copyParagData( para ); 1096 s->copyParagData( para );
1088 if ( ind ) { 1097 if ( ind ) {
1089 s->indent(); 1098 s->indent();
1090 s->format(); 1099 s->format();
1091 indent(); 1100 indent();
1092 para->format(); 1101 para->format();
1093 } 1102 }
1094 } else { 1103 } else {
1095 QString str = para->string()->toString().mid( idx, 0xFFFFFF ); 1104 QString str = para->string()->toString().mid( idx, 0xFFFFFF );
1096 QTextParagraph *n = para->next(); 1105 QTextParagraph *n = para->next();
1097 QTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds ); 1106 QTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds );
1098 s->copyParagData( para ); 1107 s->copyParagData( para );
1099 s->remove( 0, 1 ); 1108 s->remove( 0, 1 );
1100 s->append( str, TRUE ); 1109 s->append( str, TRUE );
1101 for ( uint i = 0; i < str.length(); ++i ) { 1110 for ( uint i = 0; i < str.length(); ++i ) {
1102 QTextStringChar* tsc = para->at( idx + i ); 1111 QTextStringChar* tsc = para->at( idx + i );
1103 s->setFormat( i, 1, tsc->format(), TRUE ); 1112 s->setFormat( i, 1, tsc->format(), TRUE );
1104 if ( tsc->isCustom() ) { 1113 if ( tsc->isCustom() ) {
1105 QTextCustomItem * item = tsc->customItem(); 1114 QTextCustomItem * item = tsc->customItem();
1106 s->at( i )->setCustomItem( item ); 1115 s->at( i )->setCustomItem( item );
1107 tsc->loseCustomItem(); 1116 tsc->loseCustomItem();
1108 } 1117 }
1109 if ( tsc->isAnchor() ) 1118 if ( tsc->isAnchor() )
1110 s->at( i )->setAnchor( tsc->anchorName(), 1119 s->at( i )->setAnchor( tsc->anchorName(),
1111 tsc->anchorHref() ); 1120 tsc->anchorHref() );
1112 } 1121 }
1113 para->truncate( idx ); 1122 para->truncate( idx );
1114 if ( ind ) { 1123 if ( ind ) {
1115 int oi, ni; 1124 int oi, ni;
1116 s->indent( &oi, &ni ); 1125 s->indent( &oi, &ni );
1117 para = s; 1126 para = s;
1118 idx = ni; 1127 idx = ni;
1119 } else { 1128 } else {
1120 para = s; 1129 para = s;
1121 idx = 0; 1130 idx = 0;
1122 } 1131 }
1123 } 1132 }
1124 1133
1125 invalidateNested(); 1134 invalidateNested();
1126} 1135}
1127 1136
1128bool QTextCursor::remove() 1137bool QTextCursor::remove()
1129{ 1138{
1130 tmpIndex = -1; 1139 tmpIndex = -1;
1131 if ( !atParagEnd() ) { 1140 if ( !atParagEnd() ) {
1132 para->remove( idx, 1 ); 1141 para->remove( idx, 1 );
1133 int h = para->rect().height(); 1142 int h = para->rect().height();
1134 para->format( -1, TRUE ); 1143 para->format( -1, TRUE );
1135 if ( h != para->rect().height() ) 1144 if ( h != para->rect().height() )
1136 invalidateNested(); 1145 invalidateNested();
1137 else if ( para->document() && para->document()->parent() ) 1146 else if ( para->document() && para->document()->parent() )
1138 para->document()->nextDoubleBuffered = TRUE; 1147 para->document()->nextDoubleBuffered = TRUE;
1139 return FALSE; 1148 return FALSE;
1140 } else if ( para->next() ) { 1149 } else if ( para->next() ) {
1141 para->join( para->next() ); 1150 para->join( para->next() );
1142 invalidateNested(); 1151 invalidateNested();
1143 return TRUE; 1152 return TRUE;
1144 } 1153 }
1145 return FALSE; 1154 return FALSE;
1146} 1155}
1147 1156
1148void QTextCursor::indent() 1157void QTextCursor::indent()
1149{ 1158{
1150 int oi = 0, ni = 0; 1159 int oi = 0, ni = 0;
1151 para->indent( &oi, &ni ); 1160 para->indent( &oi, &ni );
1152 if ( oi == ni ) 1161 if ( oi == ni )
1153 return; 1162 return;
1154 1163
1155 if ( idx >= oi ) 1164 if ( idx >= oi )
1156 idx += ni - oi; 1165 idx += ni - oi;
1157 else 1166 else
1158 idx = ni; 1167 idx = ni;
1159} 1168}
1160 1169
1161// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1170// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1162 1171
1163QTextDocument::QTextDocument( QTextDocument *p ) 1172QTextDocument::QTextDocument( QTextDocument *p )
1164 : par( p ), parentPar( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 ) 1173 : par( p ), parentPar( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 )
1165{ 1174{
1166 fCollection = new QTextFormatCollection; 1175 fCollection = new QTextFormatCollection;
1167 init(); 1176 init();
1168} 1177}
1169 1178
1170QTextDocument::QTextDocument( QTextDocument *p, QTextFormatCollection *f ) 1179QTextDocument::QTextDocument( QTextDocument *p, QTextFormatCollection *f )
1171 : par( p ), parentPar( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 ) 1180 : par( p ), parentPar( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 )
1172{ 1181{
1173 fCollection = f; 1182 fCollection = f;
1174 init(); 1183 init();
1175} 1184}
1176 1185
1177void QTextDocument::init() 1186void QTextDocument::init()
1178{ 1187{
1179 oTextValid = TRUE; 1188 oTextValid = TRUE;
1180 mightHaveCustomItems = FALSE; 1189 mightHaveCustomItems = FALSE;
1181 if ( par ) 1190 if ( par )
1182 par->insertChild( this ); 1191 par->insertChild( this );
1183 pProcessor = 0; 1192 pProcessor = 0;
1184 useFC = TRUE; 1193 useFC = TRUE;
1185 pFormatter = 0; 1194 pFormatter = 0;
1186 indenter = 0; 1195 indenter = 0;
1187 fParag = 0; 1196 fParag = 0;
1188 txtFormat = Qt::AutoText; 1197 txtFormat = Qt::AutoText;
1189 preferRichText = FALSE; 1198 preferRichText = FALSE;
1190 pages = FALSE; 1199 pages = FALSE;
1191 focusIndicator.parag = 0; 1200 focusIndicator.parag = 0;
1192 minw = 0; 1201 minw = 0;
1193 wused = 0; 1202 wused = 0;
1194 minwParag = curParag = 0; 1203 minwParag = curParag = 0;
1195 align = AlignAuto; 1204 align = AlignAuto;
1196 nSelections = 1; 1205 nSelections = 1;
1197 1206
1198 setStyleSheet( QStyleSheet::defaultSheet() ); 1207 setStyleSheet( QStyleSheet::defaultSheet() );
1199 factory_ = QMimeSourceFactory::defaultFactory(); 1208 factory_ = QMimeSourceFactory::defaultFactory();
1200 contxt = QString::null; 1209 contxt = QString::null;
1201 1210
1202 underlLinks = par ? par->underlLinks : TRUE; 1211 underlLinks = par ? par->underlLinks : TRUE;
1203 backBrush = 0; 1212 backBrush = 0;
1204 buf_pixmap = 0; 1213 buf_pixmap = 0;
1205 nextDoubleBuffered = FALSE; 1214 nextDoubleBuffered = FALSE;
1206 1215
1207 if ( par ) 1216 if ( par )
1208 withoutDoubleBuffer = par->withoutDoubleBuffer; 1217 withoutDoubleBuffer = par->withoutDoubleBuffer;
1209 else 1218 else
1210 withoutDoubleBuffer = FALSE; 1219 withoutDoubleBuffer = FALSE;
1211 1220
1212 lParag = fParag = createParagraph( this, 0, 0 ); 1221 lParag = fParag = createParagraph( this, 0, 0 );
1213 1222
1214 cx = 0; 1223 cx = 0;
1215 cy = 2; 1224 cy = 2;
1216 if ( par ) 1225 if ( par )
1217 cx = cy = 0; 1226 cx = cy = 0;
1218 cw = 600; 1227 cw = 600;
1219 vw = 0; 1228 vw = 0;
1220 flow_ = new QTextFlow; 1229 flow_ = new QTextFlow;
1221 flow_->setWidth( cw ); 1230 flow_->setWidth( cw );
1222 1231
1223 leftmargin = rightmargin = 4; 1232 leftmargin = rightmargin = 4;
1224 scaleFontsFactor = 1; 1233 scaleFontsFactor = 1;
1225 1234
1226 1235
1227 selectionColors[ Standard ] = QApplication::palette().color( QPalette::Active, QColorGroup::Highlight ); 1236 selectionColors[ Standard ] = QApplication::palette().color( QPalette::Active, QColorGroup::Highlight );
1228 selectionText[ Standard ] = TRUE; 1237 selectionText[ Standard ] = TRUE;
1229 commandHistory = new QTextCommandHistory( 100 ); 1238 commandHistory = new QTextCommandHistory( 100 );
1230 tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8; 1239 tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8;
1231} 1240}
1232 1241
1233QTextDocument::~QTextDocument() 1242QTextDocument::~QTextDocument()
1234{ 1243{
1235 if ( par ) 1244 if ( par )
1236 par->removeChild( this ); 1245 par->removeChild( this );
1237 clear(); 1246 clear();
1238 delete commandHistory; 1247 delete commandHistory;
1239 delete flow_; 1248 delete flow_;
1240 if ( !par ) 1249 if ( !par )
1241 delete pFormatter; 1250 delete pFormatter;
1242 delete fCollection; 1251 delete fCollection;
1243 delete pProcessor; 1252 delete pProcessor;
1244 delete buf_pixmap; 1253 delete buf_pixmap;
1245 delete indenter; 1254 delete indenter;
1246 delete backBrush; 1255 delete backBrush;
1247 if ( tArray ) 1256 if ( tArray )
1248 delete [] tArray; 1257 delete [] tArray;
1249} 1258}
1250 1259
1251void QTextDocument::clear( bool createEmptyParag ) 1260void QTextDocument::clear( bool createEmptyParag )
1252{ 1261{
1253 if ( flow_ ) 1262 if ( flow_ )
1254 flow_->clear(); 1263 flow_->clear();
1255 while ( fParag ) { 1264 while ( fParag ) {
1256 QTextParagraph *p = fParag->next(); 1265 QTextParagraph *p = fParag->next();
1257 delete fParag; 1266 delete fParag;
1258 fParag = p; 1267 fParag = p;
1259 } 1268 }
1260 fParag = lParag = 0; 1269 fParag = lParag = 0;
1261 if ( createEmptyParag ) 1270 if ( createEmptyParag )
1262 fParag = lParag = createParagraph( this ); 1271 fParag = lParag = createParagraph( this );
1263 selections.clear(); 1272 selections.clear();
1264 oText = QString::null; 1273 oText = QString::null;
1265 oTextValid = TRUE; 1274 oTextValid = TRUE;
1266} 1275}
1267 1276
1268int QTextDocument::widthUsed() const 1277int QTextDocument::widthUsed() const
1269{ 1278{
1270 return wused + border_tolerance; 1279 return wused + border_tolerance;
1271} 1280}
1272 1281
1273int QTextDocument::height() const 1282int QTextDocument::height() const
1274{ 1283{
1275 int h = 0; 1284 int h = 0;
1276 if ( lParag ) 1285 if ( lParag )
1277 h = lParag->rect().top() + lParag->rect().height() + 1; 1286 h = lParag->rect().top() + lParag->rect().height() + 1;
1278 int fh = flow_->boundingRect().bottom(); 1287 int fh = flow_->boundingRect().bottom();
1279 return QMAX( h, fh ); 1288 return QMAX( h, fh );
1280} 1289}
1281 1290
1282 1291
1283 1292
1284QTextParagraph *QTextDocument::createParagraph( QTextDocument *d, QTextParagraph *pr, QTextParagraph *nx, bool updateIds ) 1293QTextParagraph *QTextDocument::createParagraph( QTextDocument *d, QTextParagraph *pr, QTextParagraph *nx, bool updateIds )
1285{ 1294{
1286 return new QTextParagraph( d, pr, nx, updateIds ); 1295 return new QTextParagraph( d, pr, nx, updateIds );
1287} 1296}
1288 1297
1289bool QTextDocument::setMinimumWidth( int needed, int used, QTextParagraph *p ) 1298bool QTextDocument::setMinimumWidth( int needed, int used, QTextParagraph *p )
1290{ 1299{
1291 if ( needed == -1 ) { 1300 if ( needed == -1 ) {
1292 minw = 0; 1301 minw = 0;
1293 wused = 0; 1302 wused = 0;
1294 p = 0; 1303 p = 0;
1295 } 1304 }
1296 if ( p == minwParag ) { 1305 if ( p == minwParag ) {
1297 minw = needed; 1306 minw = needed;
1298 emit minimumWidthChanged( minw ); 1307 emit minimumWidthChanged( minw );
1299 } else if ( needed > minw ) { 1308 } else if ( needed > minw ) {
1300 minw = needed; 1309 minw = needed;
1301 minwParag = p; 1310 minwParag = p;
1302 emit minimumWidthChanged( minw ); 1311 emit minimumWidthChanged( minw );
1303 } 1312 }
1304 wused = QMAX( wused, used ); 1313 wused = QMAX( wused, used );
1305 wused = QMAX( wused, minw ); 1314 wused = QMAX( wused, minw );
1306 cw = QMAX( minw, cw ); 1315 cw = QMAX( minw, cw );
1307 return TRUE; 1316 return TRUE;
1308} 1317}
1309 1318
1310void QTextDocument::setPlainText( const QString &text ) 1319void QTextDocument::setPlainText( const QString &text )
1311{ 1320{
1312 clear(); 1321 clear();
1313 preferRichText = FALSE; 1322 preferRichText = FALSE;
1314 oTextValid = TRUE; 1323 oTextValid = TRUE;
1315 oText = text; 1324 oText = text;
1316 1325
1317 int lastNl = 0; 1326 int lastNl = 0;
1318 int nl = text.find( '\n' ); 1327 int nl = text.find( '\n' );
1319 if ( nl == -1 ) { 1328 if ( nl == -1 ) {
1320 lParag = createParagraph( this, lParag, 0 ); 1329 lParag = createParagraph( this, lParag, 0 );
1321 if ( !fParag ) 1330 if ( !fParag )
1322 fParag = lParag; 1331 fParag = lParag;
1323 QString s = text; 1332 QString s = text;
1324 if ( !s.isEmpty() ) { 1333 if ( !s.isEmpty() ) {
1325 if ( s[ (int)s.length() - 1 ] == '\r' ) 1334 if ( s[ (int)s.length() - 1 ] == '\r' )
1326 s.remove( s.length() - 1, 1 ); 1335 s.remove( s.length() - 1, 1 );
1327 lParag->append( s ); 1336 lParag->append( s );
1328 } 1337 }
1329 } else { 1338 } else {
1330 for (;;) { 1339 for (;;) {
1331 lParag = createParagraph( this, lParag, 0 ); 1340 lParag = createParagraph( this, lParag, 0 );
1332 if ( !fParag ) 1341 if ( !fParag )
1333 fParag = lParag; 1342 fParag = lParag;
1334 QString s = text.mid( lastNl, nl - lastNl ); 1343 QString s = text.mid( lastNl, nl - lastNl );
1335 if ( !s.isEmpty() ) { 1344 if ( !s.isEmpty() ) {
1336 if ( s[ (int)s.length() - 1 ] == '\r' ) 1345 if ( s[ (int)s.length() - 1 ] == '\r' )
1337 s.remove( s.length() - 1, 1 ); 1346 s.remove( s.length() - 1, 1 );
1338 lParag->append( s ); 1347 lParag->append( s );
1339 } 1348 }
1340 if ( nl == 0xffffff ) 1349 if ( nl == 0xffffff )
1341 break; 1350 break;
1342 lastNl = nl + 1; 1351 lastNl = nl + 1;
1343 nl = text.find( '\n', nl + 1 ); 1352 nl = text.find( '\n', nl + 1 );
1344 if ( nl == -1 ) 1353 if ( nl == -1 )
1345 nl = 0xffffff; 1354 nl = 0xffffff;
1346 } 1355 }
1347 } 1356 }
1348 if ( !lParag ) 1357 if ( !lParag )
1349 lParag = fParag = createParagraph( this, 0, 0 ); 1358 lParag = fParag = createParagraph( this, 0, 0 );
1350} 1359}
1351 1360
1352struct Q_EXPORT QTextDocumentTag { 1361struct Q_EXPORT QTextDocumentTag {
1353 QTextDocumentTag(){} 1362 QTextDocumentTag(){}
1354 QTextDocumentTag( const QString&n, const QStyleSheetItem* s, const QTextFormat& f ) 1363 QTextDocumentTag( const QString&n, const QStyleSheetItem* s, const QTextFormat& f )
1355 :name(n),style(s), format(f), alignment(Qt3::AlignAuto), direction(QChar::DirON),liststyle(QStyleSheetItem::ListDisc) { 1364 :name(n),style(s), format(f), alignment(Qt3::AlignAuto), direction(QChar::DirON),liststyle(QStyleSheetItem::ListDisc) {
1356 wsm = QStyleSheetItem::WhiteSpaceNormal; 1365 wsm = QStyleSheetItem::WhiteSpaceNormal;
1357 } 1366 }
1358 QString name; 1367 QString name;
1359 const QStyleSheetItem* style; 1368 const QStyleSheetItem* style;
1360 QString anchorHref; 1369 QString anchorHref;
1361 QStyleSheetItem::WhiteSpaceMode wsm; 1370 QStyleSheetItem::WhiteSpaceMode wsm;
1362 QTextFormat format; 1371 QTextFormat format;
1363 int alignment : 16; 1372 int alignment : 16;
1364 int direction : 5; 1373 int direction : 5;
1365 QStyleSheetItem::ListStyle liststyle; 1374 QStyleSheetItem::ListStyle liststyle;
1366 1375
1367 QTextDocumentTag( const QTextDocumentTag& t ) { 1376 QTextDocumentTag( const QTextDocumentTag& t ) {
1368 name = t.name; 1377 name = t.name;
1369 style = t.style; 1378 style = t.style;
1370 anchorHref = t.anchorHref; 1379 anchorHref = t.anchorHref;
1371 wsm = t.wsm; 1380 wsm = t.wsm;
1372 format = t.format; 1381 format = t.format;
1373 alignment = t.alignment; 1382 alignment = t.alignment;
1374 direction = t.direction; 1383 direction = t.direction;
1375 liststyle = t.liststyle; 1384 liststyle = t.liststyle;
1376 } 1385 }
1377 QTextDocumentTag& operator=(const QTextDocumentTag& t) { 1386 QTextDocumentTag& operator=(const QTextDocumentTag& t) {
1378 name = t.name; 1387 name = t.name;
1379 style = t.style; 1388 style = t.style;
1380 anchorHref = t.anchorHref; 1389 anchorHref = t.anchorHref;
1381 wsm = t.wsm; 1390 wsm = t.wsm;
1382 format = t.format; 1391 format = t.format;
1383 alignment = t.alignment; 1392 alignment = t.alignment;
1384 direction = t.direction; 1393 direction = t.direction;
1385 liststyle = t.liststyle; 1394 liststyle = t.liststyle;
1386 return *this; 1395 return *this;
1387 } 1396 }
1388 1397
1389#if defined(Q_FULL_TEMPLATE_INSTANTIATION) 1398#if defined(Q_FULL_TEMPLATE_INSTANTIATION)
1390 bool operator==( const QTextDocumentTag& ) const { return FALSE; } 1399 bool operator==( const QTextDocumentTag& ) const { return FALSE; }
1391#endif 1400#endif
1392}; 1401};
1393 1402
1394 1403
1395#define NEWPAR do{ if ( !hasNewPar) { \ 1404#define NEWPAR do { \
1396 if ( !textEditMode && curpar && curpar->length()>1 && curpar->at( curpar->length()-2)->c == QChar_linesep ) \ 1405 if ( !hasNewPar) { \
1397 curpar->remove( curpar->length()-2, 1 ); \ 1406 if ( !curpar ) { \
1398 curpar = createParagraph( this, curpar, curpar->next() ); styles.append( vec ); vec = 0;} \ 1407 owarn << "no current paragraph" << oendl; \
1399 hasNewPar = TRUE; \ 1408 return; \
1400 curpar->rtext = TRUE; \ 1409 } \
1401 curpar->align = curtag.alignment; \ 1410 if ( !textEditMode && curpar && curpar->length()>1 && curpar->at( curpar->length()-2)->c == QChar_linesep ) \
1402 curpar->lstyle = curtag.liststyle; \ 1411 curpar->remove( curpar->length()-2, 1 ); \
1403 curpar->litem = ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ); \ 1412 curpar = createParagraph( this, curpar, curpar->next() ); styles.append( vec ); \
1404 curpar->str->setDirection( (QChar::Direction)curtag.direction ); \ 1413 if ( !curpar ) { \
1405 space = TRUE; \ 1414 owarn << "failed in creating a new paragraph" << oendl; \
1406 delete vec; vec = new QPtrVector<QStyleSheetItem>( (uint)tags.count() + 1); \ 1415 return; \
1407 int i = 0; \ 1416 } \
1408 for ( QValueStack<QTextDocumentTag>::Iterator it = tags.begin(); it != tags.end(); ++it ) \ 1417 vec = 0; \
1409 vec->insert( i++, (*it).style ); \ 1418 } \
1410 vec->insert( i, curtag.style ); \ 1419 hasNewPar = TRUE; \
1411 }while(FALSE) 1420 curpar->rtext = TRUE; \
1412 1421 curpar->align = curtag.alignment; \
1422 curpar->lstyle = curtag.liststyle; \
1423 curpar->litem = ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ); \
1424 curpar->str->setDirection( (QChar::Direction)curtag.direction ); \
1425 space = TRUE; \
1426 delete vec; \
1427 vec = new QPtrVector<QStyleSheetItem>( (uint)tags.count() + 1); \
1428 int i = 0; \
1429 for ( QValueStack<QTextDocumentTag>::Iterator it = tags.begin(); it != tags.end(); ++it ) \
1430 vec->insert( i++, (*it).style ); \
1431 vec->insert( i, curtag.style ); \
1432 } while ( FALSE )
1413 1433
1414void QTextDocument::setRichText( const QString &text, const QString &context ) 1434void QTextDocument::setRichText( const QString &text, const QString &context )
1415{ 1435{
1416 if ( !context.isEmpty() ) 1436 if ( !context.isEmpty() )
1417 setContext( context ); 1437 setContext( context );
1418 clear(); 1438 clear();
1419 fParag = lParag = createParagraph( this ); 1439 fParag = lParag = createParagraph( this );
1420 oTextValid = TRUE; 1440 oTextValid = TRUE;
1421 oText = text; 1441 oText = text;
1422 setRichTextInternal( text ); 1442 setRichTextInternal( text );
1423 fParag->rtext = TRUE; 1443 fParag->rtext = TRUE;
1424} 1444}
1425 1445
1426void QTextDocument::setRichTextInternal( const QString &text, QTextCursor* cursor ) 1446void QTextDocument::setRichTextInternal( const QString &text, QTextCursor* cursor )
1427{ 1447{
1428 QTextParagraph* curpar = lParag; 1448 QTextParagraph* curpar = lParag;
1429 int pos = 0; 1449 int pos = 0;
1430 QValueStack<QTextDocumentTag> tags; 1450 QValueStack<QTextDocumentTag> tags;
1431 QTextDocumentTag initag( "", sheet_->item(""), *formatCollection()->defaultFormat() ); 1451 QTextDocumentTag initag( "", sheet_->item(""), *formatCollection()->defaultFormat() );
1432 QTextDocumentTag curtag = initag; 1452 QTextDocumentTag curtag = initag;
1433 bool space = TRUE; 1453 bool space = TRUE;
1434 bool canMergeLi = FALSE; 1454 bool canMergeLi = FALSE;
1435 1455
1436 bool textEditMode = FALSE; 1456 bool textEditMode = FALSE;
1437 1457
1438 const QChar* doc = text.unicode(); 1458 const QChar* doc = text.unicode();
1439 int length = text.length(); 1459 int length = text.length();
1440 bool hasNewPar = curpar->length() <= 1; 1460 bool hasNewPar = curpar->length() <= 1;
1441 QString anchorName; 1461 QString anchorName;
1442 1462
1443 // style sheet handling for margin and line spacing calculation below 1463 // style sheet handling for margin and line spacing calculation below
1444 QTextParagraph* stylesPar = curpar; 1464 QTextParagraph* stylesPar = curpar;
1445 QPtrVector<QStyleSheetItem>* vec = 0; 1465 QPtrVector<QStyleSheetItem>* vec = 0;
1446 QPtrList< QPtrVector<QStyleSheetItem> > styles; 1466 QPtrList< QPtrVector<QStyleSheetItem> > styles;
1447 styles.setAutoDelete( TRUE ); 1467 styles.setAutoDelete( TRUE );
1448 1468
1449 if ( cursor ) { 1469 if ( cursor ) {
1450 cursor->splitAndInsertEmptyParagraph(); 1470 cursor->splitAndInsertEmptyParagraph();
1451 QTextCursor tmp = *cursor; 1471 QTextCursor tmp = *cursor;
1452 tmp.gotoPreviousLetter(); 1472 tmp.gotoPreviousLetter();
1453 stylesPar = curpar = tmp.paragraph(); 1473 stylesPar = curpar = tmp.paragraph();
1454 hasNewPar = TRUE; 1474 hasNewPar = TRUE;
1455 textEditMode = TRUE; 1475 textEditMode = TRUE;
1456 } else { 1476 } else {
1457 NEWPAR; 1477 NEWPAR;
1458 } 1478 }
1459 1479
1460 // set rtext spacing to FALSE for the initial paragraph. 1480 // set rtext spacing to FALSE for the initial paragraph.
1461 curpar->rtext = FALSE; 1481 curpar->rtext = FALSE;
1462 1482
1463 QString wellKnownTags = "br hr wsp table qt body meta title"; 1483 QString wellKnownTags = "br hr wsp table qt body meta title";
1464 1484
1465 while ( pos < length ) { 1485 while ( pos < length ) {
1466 if ( hasPrefix(doc, length, pos, '<' ) ){ 1486 if ( hasPrefix(doc, length, pos, '<' ) ){
1467 if ( !hasPrefix( doc, length, pos+1, QChar('/') ) ) { 1487 if ( !hasPrefix( doc, length, pos+1, QChar('/') ) ) {
1468 // open tag 1488 // open tag
1469 QMap<QString, QString> attr; 1489 QMap<QString, QString> attr;
1470 bool emptyTag = FALSE; 1490 bool emptyTag = FALSE;
1471 QString tagname = parseOpenTag(doc, length, pos, attr, emptyTag); 1491 QString tagname = parseOpenTag(doc, length, pos, attr, emptyTag);
1472 if ( tagname.isEmpty() ) 1492 if ( tagname.isEmpty() )
1473 continue; // nothing we could do with this, probably parse error 1493 continue; // nothing we could do with this, probably parse error
1474 1494
1475 const QStyleSheetItem* nstyle = sheet_->item(tagname); 1495 const QStyleSheetItem* nstyle = sheet_->item(tagname);
1476 1496
1477 if ( nstyle ) { 1497 if ( nstyle ) {
1478 // we might have to close some 'forgotten' tags 1498 // we might have to close some 'forgotten' tags
1479 while ( !nstyle->allowedInContext( curtag.style ) ) { 1499 while ( !nstyle->allowedInContext( curtag.style ) ) {
1480 QString msg; 1500 QString msg;
1481 msg.sprintf( "QText Warning: Document not valid ( '%s' not allowed in '%s' #%d)", 1501 msg.sprintf( "QText Warning: Document not valid ( '%s' not allowed in '%s' #%d)",
1482 tagname.ascii(), curtag.style->name().ascii(), pos); 1502 tagname.ascii(), curtag.style->name().ascii(), pos);
1483 sheet_->error( msg ); 1503 sheet_->error( msg );
1484 if ( tags.isEmpty() ) 1504 if ( tags.isEmpty() )
1485 break; 1505 break;
1486 curtag = tags.pop(); 1506 curtag = tags.pop();
1487 } 1507 }
1488 1508
1489 /* special handling for p and li for HTML 1509 /* special handling for p and li for HTML
1490 compatibility. We do not want to embed blocks in 1510 compatibility. We do not want to embed blocks in
1491 p, and we do not want new blocks inside non-empty 1511 p, and we do not want new blocks inside non-empty
1492 lis. Plus we want to merge empty lis sometimes. */ 1512 lis. Plus we want to merge empty lis sometimes. */
1493 if( nstyle->displayMode() == QStyleSheetItem::DisplayListItem ) { 1513 if( nstyle->displayMode() == QStyleSheetItem::DisplayListItem ) {
1494 canMergeLi = TRUE; 1514 canMergeLi = TRUE;
1495 } else if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock ) { 1515 } else if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock ) {
1496 while ( curtag.style->name() == "p" ) { 1516 while ( curtag.style->name() == "p" ) {
1497 if ( tags.isEmpty() ) 1517 if ( tags.isEmpty() )
1498 break; 1518 break;
1499 curtag = tags.pop(); 1519 curtag = tags.pop();
1500 } 1520 }
1501 1521
1502 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { 1522 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) {
1503 // we are in a li and a new block comes along 1523 // we are in a li and a new block comes along
1504 if ( nstyle->name() == "ul" || nstyle->name() == "ol" ) 1524 if ( nstyle->name() == "ul" || nstyle->name() == "ol" )
1505 hasNewPar = FALSE; // we want an empty li (like most browsers) 1525 hasNewPar = FALSE; // we want an empty li (like most browsers)
1506 if ( !hasNewPar ) { 1526 if ( !hasNewPar ) {
1507 /* do not add new blocks inside 1527 /* do not add new blocks inside
1508 non-empty lis */ 1528 non-empty lis */
1509 while ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { 1529 while ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) {
1510 if ( tags.isEmpty() ) 1530 if ( tags.isEmpty() )
1511 break; 1531 break;
1512 curtag = tags.pop(); 1532 curtag = tags.pop();
1513 } 1533 }
1514 } else if ( canMergeLi ) { 1534 } else if ( canMergeLi ) {
1515 /* we have an empty li and a block 1535 /* we have an empty li and a block
1516 comes along, merge them */ 1536 comes along, merge them */
1517 nstyle = curtag.style; 1537 nstyle = curtag.style;
1518 } 1538 }
1519 canMergeLi = FALSE; 1539 canMergeLi = FALSE;
1520 } 1540 }
1521 } 1541 }
1522 } 1542 }
1523 1543
1524 QTextCustomItem* custom = 0; 1544 QTextCustomItem* custom = 0;
1525 1545
1526 // some well-known tags, some have a nstyle, some not 1546 // some well-known tags, some have a nstyle, some not
1527 if ( wellKnownTags.find( tagname ) != -1 ) { 1547 if ( wellKnownTags.find( tagname ) != -1 ) {
1528 if ( tagname == "br" ) { 1548 if ( tagname == "br" ) {
1529 emptyTag = space = TRUE; 1549 emptyTag = space = TRUE;
1530 int index = QMAX( curpar->length(),1) - 1; 1550 int index = QMAX( curpar->length(),1) - 1;
1531 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); 1551 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor );
1532 curpar->append( QChar_linesep ); 1552 curpar->append( QChar_linesep );
1533 curpar->setFormat( index, 1, &format ); 1553 curpar->setFormat( index, 1, &format );
1534 } else if ( tagname == "hr" ) { 1554 } else if ( tagname == "hr" ) {
1535 emptyTag = space = TRUE; 1555 emptyTag = space = TRUE;
1536 custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); 1556 custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this );
1537 NEWPAR; 1557 NEWPAR;
1538 } else if ( tagname == "table" ) { 1558 } else if ( tagname == "table" ) {
1539 emptyTag = space = TRUE; 1559 emptyTag = space = TRUE;
1540 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); 1560 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor );
1541 curpar->setAlignment( curtag.alignment ); 1561 curpar->setAlignment( curtag.alignment );
1542 custom = parseTable( attr, format, doc, length, pos, curpar ); 1562 custom = parseTable( attr, format, doc, length, pos, curpar );
1543 } else if ( tagname == "qt" || tagname == "body" ) { 1563 } else if ( tagname == "qt" || tagname == "body" ) {
1544 if ( attr.contains( "bgcolor" ) ) { 1564 if ( attr.contains( "bgcolor" ) ) {
1545 QBrush *b = new QBrush( QColor( attr["bgcolor"] ) ); 1565 QBrush *b = new QBrush( QColor( attr["bgcolor"] ) );
1546 setPaper( b ); 1566 setPaper( b );
1547 } 1567 }
1548 if ( attr.contains( "background" ) ) { 1568 if ( attr.contains( "background" ) ) {
1549 QImage img; 1569 QImage img;
1550 QString bg = attr["background"]; 1570 QString bg = attr["background"];
1551 const QMimeSource* m = factory_->data( bg, contxt ); 1571 const QMimeSource* m = factory_->data( bg, contxt );
1552 if ( !m ) { 1572 if ( !m ) {
1553 owarn << "QRichText: no mimesource for " << bg.latin1() << "" << oendl; 1573 owarn << "QRichText: no mimesource for " << bg.latin1() << "" << oendl;
1554 } else { 1574 } else {
1555 if ( !QImageDrag::decode( m, img ) ) { 1575 if ( !QImageDrag::decode( m, img ) ) {
1556 owarn << "QTextImage: cannot decode " << bg.latin1() << "" << oendl; 1576 owarn << "QTextImage: cannot decode " << bg.latin1() << "" << oendl;
1557 } 1577 }
1558 } 1578 }
1559 if ( !img.isNull() ) { 1579 if ( !img.isNull() ) {
1560 QPixmap pm; 1580 QPixmap pm;
1561 pm.convertFromImage( img ); 1581 pm.convertFromImage( img );
1562 QBrush *b = new QBrush( QColor(), pm ); 1582 QBrush *b = new QBrush( QColor(), pm );
1563 setPaper( b ); 1583 setPaper( b );
1564 } 1584 }
1565 } 1585 }
1566 if ( attr.contains( "text" ) ) { 1586 if ( attr.contains( "text" ) ) {
1567 QColor c( attr["text"] ); 1587 QColor c( attr["text"] );
1568 if ( formatCollection()->defaultFormat()->color() != c ) { 1588 if ( formatCollection()->defaultFormat()->color() != c ) {
1569 QDict<QTextFormat> formats = formatCollection()->dict(); 1589 QDict<QTextFormat> formats = formatCollection()->dict();
1570 QDictIterator<QTextFormat> it( formats ); 1590 QDictIterator<QTextFormat> it( formats );
1571 while ( it.current() ) { 1591 while ( it.current() ) {
1572 if ( it.current() == formatCollection()->defaultFormat() ) { 1592 if ( it.current() == formatCollection()->defaultFormat() ) {
1573 ++it; 1593 ++it;
1574 continue; 1594 continue;
1575 } 1595 }
1576 it.current()->setColor( c ); 1596 it.current()->setColor( c );
1577 ++it; 1597 ++it;
1578 } 1598 }
1579 formatCollection()->defaultFormat()->setColor( c ); 1599 formatCollection()->defaultFormat()->setColor( c );
1580 curtag.format.setColor( c ); 1600 curtag.format.setColor( c );
1581 } 1601 }
1582 } 1602 }
1583 if ( attr.contains( "link" ) ) 1603 if ( attr.contains( "link" ) )
1584 linkColor = QColor( attr["link"] ); 1604 linkColor = QColor( attr["link"] );
1585 if ( attr.contains( "title" ) ) 1605 if ( attr.contains( "title" ) )
1586 attribs.replace( "title", attr["title"] ); 1606 attribs.replace( "title", attr["title"] );
1587 1607
1588 if ( textEditMode ) { 1608 if ( textEditMode ) {
1589 if ( attr.contains("style" ) ) { 1609 if ( attr.contains("style" ) ) {
1590 QString a = attr["style"]; 1610 QString a = attr["style"];
1591 for ( int s = 0; s < a.contains(';')+1; s++ ) { 1611 for ( int s = 0; s < a.contains(';')+1; s++ ) {
1592 QString style = QTextDocument::section( a, ";", s, s ); 1612 QString style = QTextDocument::section( a, ";", s, s );
1593 if ( style.startsWith("font-size:" ) && QTextDocument::endsWith(style, "pt") ) { 1613 if ( style.startsWith("font-size:" ) && QTextDocument::endsWith(style, "pt") ) {
1594 scaleFontsFactor = double( formatCollection()->defaultFormat()->fn.pointSize() ) / 1614 scaleFontsFactor = double( formatCollection()->defaultFormat()->fn.pointSize() ) /
1595 style.mid( 10, style.length() - 12 ).toInt(); 1615 style.mid( 10, style.length() - 12 ).toInt();
1596 } 1616 }
1597 } 1617 }
1598 } 1618 }
1599 nstyle = 0; // ignore body in textEditMode 1619 nstyle = 0; // ignore body in textEditMode
1600 } 1620 }
1601 // end qt- and body-tag handling 1621 // end qt- and body-tag handling
1602 } else if ( tagname == "meta" ) { 1622 } else if ( tagname == "meta" ) {
1603 if ( attr["name"] == "qrichtext" && attr["content"] == "1" ) 1623 if ( attr["name"] == "qrichtext" && attr["content"] == "1" )
1604 textEditMode = TRUE; 1624 textEditMode = TRUE;
1605 } else if ( tagname == "title" ) { 1625 } else if ( tagname == "title" ) {
1606 QString title; 1626 QString title;
1607 while ( pos < length ) { 1627 while ( pos < length ) {
1608 if ( hasPrefix( doc, length, pos, QChar('<') ) && hasPrefix( doc, length, pos+1, QChar('/') ) && 1628 if ( hasPrefix( doc, length, pos, QChar('<') ) && hasPrefix( doc, length, pos+1, QChar('/') ) &&
1609 parseCloseTag( doc, length, pos ) == "title" ) 1629 parseCloseTag( doc, length, pos ) == "title" )
1610 break; 1630 break;
1611 title += doc[ pos ]; 1631 title += doc[ pos ];
1612 ++pos; 1632 ++pos;
1613 } 1633 }
1614 attribs.replace( "title", title ); 1634 attribs.replace( "title", title );
1615 } 1635 }
1616 } // end of well-known tag handling 1636 } // end of well-known tag handling
1617 1637
1618 if ( !custom ) // try generic custom item 1638 if ( !custom ) // try generic custom item
1619 custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); 1639 custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this );
1620 1640
1621 if ( !nstyle && !custom ) // we have no clue what this tag could be, ignore it 1641 if ( !nstyle && !custom ) // we have no clue what this tag could be, ignore it
1622 continue; 1642 continue;
1623 1643
1624 if ( custom ) { 1644 if ( custom ) {
1625 int index = QMAX( curpar->length(),1) - 1; 1645 int index = QMAX( curpar->length(),1) - 1;
1626 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); 1646 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor );
1627 curpar->append( QChar('*') ); 1647 curpar->append( QChar('*') );
1628 curpar->setFormat( index, 1, &format ); 1648 curpar->setFormat( index, 1, &format );
1629 curpar->at( index )->setCustomItem( custom ); 1649 curpar->at( index )->setCustomItem( custom );
1630 if ( !curtag.anchorHref.isEmpty() ) 1650 if ( !curtag.anchorHref.isEmpty() )
1631 curpar->at(index)->setAnchor( QString::null, curtag.anchorHref ); 1651 curpar->at(index)->setAnchor( QString::null, curtag.anchorHref );
1632 if ( !anchorName.isEmpty() ) { 1652 if ( !anchorName.isEmpty() ) {
1633 curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() ); 1653 curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() );
1634 anchorName = QString::null; 1654 anchorName = QString::null;
1635 } 1655 }
1636 registerCustomItem( custom, curpar ); 1656 registerCustomItem( custom, curpar );
1637 hasNewPar = FALSE; 1657 hasNewPar = FALSE;
1638 } else if ( !emptyTag ) { 1658 } else if ( !emptyTag ) {
1639 /* if we do nesting, push curtag on the stack, 1659 /* if we do nesting, push curtag on the stack,
1640 otherwise reinint curag. */ 1660 otherwise reinint curag. */
1641 if ( curtag.style->name() != tagname || nstyle->selfNesting() ) { 1661 if ( curtag.style->name() != tagname || nstyle->selfNesting() ) {
1642 tags.push( curtag ); 1662 tags.push( curtag );
1643 } else { 1663 } else {
1644 if ( !tags.isEmpty() ) 1664 if ( !tags.isEmpty() )
1645 curtag = tags.top(); 1665 curtag = tags.top();
1646 else 1666 else
1647 curtag = initag; 1667 curtag = initag;
1648 } 1668 }
1649 1669
1650 curtag.name = tagname; 1670 curtag.name = tagname;
1651 curtag.style = nstyle; 1671 curtag.style = nstyle;
1652 curtag.name = tagname; 1672 curtag.name = tagname;
1653 curtag.style = nstyle; 1673 curtag.style = nstyle;
1654 if ( int(nstyle->whiteSpaceMode()) != QStyleSheetItem::Undefined ) 1674 if ( int(nstyle->whiteSpaceMode()) != QStyleSheetItem::Undefined )
1655 curtag.wsm = nstyle->whiteSpaceMode(); 1675 curtag.wsm = nstyle->whiteSpaceMode();
1656 1676
1657 /* ignore whitespace for inline elements if there 1677 /* ignore whitespace for inline elements if there
1658 was already one*/ 1678 was already one*/
1659 if ( !textEditMode && curtag.wsm == QStyleSheetItem::WhiteSpaceNormal 1679 if ( !textEditMode && curtag.wsm == QStyleSheetItem::WhiteSpaceNormal
1660 && ( space || nstyle->displayMode() != QStyleSheetItem::DisplayInline ) ) 1680 && ( space || nstyle->displayMode() != QStyleSheetItem::DisplayInline ) )
1661 eatSpace( doc, length, pos ); 1681 eatSpace( doc, length, pos );
1662 1682
1663 curtag.format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); 1683 curtag.format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor );
1664 if ( nstyle->isAnchor() ) { 1684 if ( nstyle->isAnchor() ) {
1665 if ( !anchorName.isEmpty() ) 1685 if ( !anchorName.isEmpty() )
1666 anchorName += "#" + attr["name"]; 1686 anchorName += "#" + attr["name"];
1667 else 1687 else
1668 anchorName = attr["name"]; 1688 anchorName = attr["name"];
1669 curtag.anchorHref = attr["href"]; 1689 curtag.anchorHref = attr["href"];
1670 } 1690 }
1671 1691
1672 if ( nstyle->alignment() != QStyleSheetItem::Undefined ) 1692 if ( nstyle->alignment() != QStyleSheetItem::Undefined )
1673 curtag.alignment = nstyle->alignment(); 1693 curtag.alignment = nstyle->alignment();
1674 1694
1675 if ( (int) nstyle->listStyle() != QStyleSheetItem::Undefined ) 1695 if ( (int) nstyle->listStyle() != QStyleSheetItem::Undefined )
1676 curtag.liststyle = nstyle->listStyle(); 1696 curtag.liststyle = nstyle->listStyle();
1677 1697
1678 if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock 1698 if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock
1679 || nstyle->displayMode() == QStyleSheetItem::DisplayListItem ) { 1699 || nstyle->displayMode() == QStyleSheetItem::DisplayListItem ) {
1680 1700
1681 if ( nstyle->name() == "ol" || nstyle->name() == "ul" || nstyle->name() == "li") { 1701 if ( nstyle->name() == "ol" || nstyle->name() == "ul" || nstyle->name() == "li") {
1682 QString type = attr["type"]; 1702 QString type = attr["type"];
1683 if ( !type.isEmpty() ) { 1703 if ( !type.isEmpty() ) {
1684 if ( type == "1" ) { 1704 if ( type == "1" ) {
1685 curtag.liststyle = QStyleSheetItem::ListDecimal; 1705 curtag.liststyle = QStyleSheetItem::ListDecimal;
1686 } else if ( type == "a" ) { 1706 } else if ( type == "a" ) {
1687 curtag.liststyle = QStyleSheetItem::ListLowerAlpha; 1707 curtag.liststyle = QStyleSheetItem::ListLowerAlpha;
1688 } else if ( type == "A" ) { 1708 } else if ( type == "A" ) {
1689 curtag.liststyle = QStyleSheetItem::ListUpperAlpha; 1709 curtag.liststyle = QStyleSheetItem::ListUpperAlpha;
1690 } else { 1710 } else {
1691 type = type.lower(); 1711 type = type.lower();
1692 if ( type == "square" ) 1712 if ( type == "square" )
1693 curtag.liststyle = QStyleSheetItem::ListSquare; 1713 curtag.liststyle = QStyleSheetItem::ListSquare;
1694 else if ( type == "disc" ) 1714 else if ( type == "disc" )
1695 curtag.liststyle = QStyleSheetItem::ListDisc; 1715 curtag.liststyle = QStyleSheetItem::ListDisc;
1696 else if ( type == "circle" ) 1716 else if ( type == "circle" )
1697 curtag.liststyle = QStyleSheetItem::ListCircle; 1717 curtag.liststyle = QStyleSheetItem::ListCircle;
1698 } 1718 }
1699 } 1719 }
1700 } 1720 }
1701 1721
1702 1722
1703 /* Internally we treat ordered and bullet 1723 /* Internally we treat ordered and bullet
1704 lists the same for margin calculations. In 1724 lists the same for margin calculations. In
1705 order to have fast pointer compares in the 1725 order to have fast pointer compares in the
1706 xMargin() functions we restrict ourselves to 1726 xMargin() functions we restrict ourselves to
1707 <ol>. Once we calculate the margins in the 1727 <ol>. Once we calculate the margins in the
1708 parser rathern than later, the unelegance of 1728 parser rathern than later, the unelegance of
1709 this approach goes awy 1729 this approach goes awy
1710 */ 1730 */
1711 if ( nstyle->name() == "ul" ) 1731 if ( nstyle->name() == "ul" )
1712 curtag.style = sheet_->item( "ol" ); 1732 curtag.style = sheet_->item( "ol" );
1713 1733
1714 if ( attr.contains( "align" ) ) { 1734 if ( attr.contains( "align" ) ) {
1715 QString align = attr["align"]; 1735 QString align = attr["align"];
1716 if ( align == "center" ) 1736 if ( align == "center" )
1717 curtag.alignment = Qt::AlignCenter; 1737 curtag.alignment = Qt::AlignCenter;
1718 else if ( align == "right" ) 1738 else if ( align == "right" )
1719 curtag.alignment = Qt::AlignRight; 1739 curtag.alignment = Qt::AlignRight;
1720 else if ( align == "justify" ) 1740 else if ( align == "justify" )
1721 curtag.alignment = Qt3::AlignJustify; 1741 curtag.alignment = Qt3::AlignJustify;
1722 } 1742 }
1723 if ( attr.contains( "dir" ) ) { 1743 if ( attr.contains( "dir" ) ) {
1724 QString dir = attr["dir"]; 1744 QString dir = attr["dir"];
1725 if ( dir == "rtl" ) 1745 if ( dir == "rtl" )
1726 curtag.direction = QChar::DirR; 1746 curtag.direction = QChar::DirR;
1727 else if ( dir == "ltr" ) 1747 else if ( dir == "ltr" )
1728 curtag.direction = QChar::DirL; 1748 curtag.direction = QChar::DirL;
1729 } 1749 }
1730 1750
1731 NEWPAR; 1751 NEWPAR;
1732 1752
1733 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { 1753 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) {
1734 if ( attr.contains( "value " ) ) 1754 if ( attr.contains( "value " ) )
1735 curpar->setListValue( attr["value"].toInt() ); 1755 curpar->setListValue( attr["value"].toInt() );
1736 } 1756 }
1737 1757
1738 if ( attr.contains( "style" ) ) { 1758 if ( attr.contains( "style" ) ) {
1739 QString a = attr["style"]; 1759 QString a = attr["style"];
1740 bool ok = TRUE; 1760 bool ok = TRUE;
1741 for ( int s = 0; ok && s < a.contains(';')+1; s++ ) { 1761 for ( int s = 0; ok && s < a.contains(';')+1; s++ ) {
1742 QString style = QTextDocument::section( a, ";", s, s ); 1762 QString style = QTextDocument::section( a, ";", s, s );
1743 if ( style.startsWith("margin-top:" ) && QTextDocument::endsWith(style, "px") ) 1763 if ( style.startsWith("margin-top:" ) && QTextDocument::endsWith(style, "px") )
1744 curpar->utm = 1+style.mid(11, style.length() - 13).toInt(&ok); 1764 curpar->utm = 1+style.mid(11, style.length() - 13).toInt(&ok);
1745 else if ( style.startsWith("margin-bottom:" ) && QTextDocument::endsWith(style, "px") ) 1765 else if ( style.startsWith("margin-bottom:" ) && QTextDocument::endsWith(style, "px") )
1746 curpar->ubm = 1+style.mid(14, style.length() - 16).toInt(&ok); 1766 curpar->ubm = 1+style.mid(14, style.length() - 16).toInt(&ok);
1747 else if ( style.startsWith("margin-left:" ) && QTextDocument::endsWith(style, "px") ) 1767 else if ( style.startsWith("margin-left:" ) && QTextDocument::endsWith(style, "px") )
1748 curpar->ulm = 1+style.mid(12, style.length() - 14).toInt(&ok); 1768 curpar->ulm = 1+style.mid(12, style.length() - 14).toInt(&ok);
1749 else if ( style.startsWith("margin-right:" ) && QTextDocument::endsWith(style, "px") ) 1769 else if ( style.startsWith("margin-right:" ) && QTextDocument::endsWith(style, "px") )
1750 curpar->urm = 1+style.mid(13, style.length() - 15).toInt(&ok); 1770 curpar->urm = 1+style.mid(13, style.length() - 15).toInt(&ok);
1751 else if ( style.startsWith("text-indent:" ) && QTextDocument::endsWith(style, "px") ) 1771 else if ( style.startsWith("text-indent:" ) && QTextDocument::endsWith(style, "px") )
1752 curpar->uflm = 1+style.mid(12, style.length() - 14).toInt(&ok); 1772 curpar->uflm = 1+style.mid(12, style.length() - 14).toInt(&ok);
1753 } 1773 }
1754 if ( !ok ) // be pressmistic 1774 if ( !ok ) // be pressmistic
1755 curpar->utm = curpar->ubm = curpar->urm = curpar->ulm = 0; 1775 curpar->utm = curpar->ubm = curpar->urm = curpar->ulm = 0;
1756 } 1776 }
1757 } 1777 }
1758 } 1778 }
1759 } else { 1779 } else {
1760 QString tagname = parseCloseTag( doc, length, pos ); 1780 QString tagname = parseCloseTag( doc, length, pos );
1761 if ( tagname.isEmpty() ) 1781 if ( tagname.isEmpty() )
1762 continue; // nothing we could do with this, probably parse error 1782 continue; // nothing we could do with this, probably parse error
1763 if ( !sheet_->item( tagname ) ) // ignore unknown tags 1783 if ( !sheet_->item( tagname ) ) // ignore unknown tags
1764 continue; 1784 continue;
1765 1785
1766 // we close a block item. Since the text may continue, we need to have a new paragraph 1786 // we close a block item. Since the text may continue, we need to have a new paragraph
1767 bool needNewPar = curtag.style->displayMode() == QStyleSheetItem::DisplayBlock 1787 bool needNewPar = curtag.style->displayMode() == QStyleSheetItem::DisplayBlock
1768 || curtag.style->displayMode() == QStyleSheetItem::DisplayListItem; 1788 || curtag.style->displayMode() == QStyleSheetItem::DisplayListItem;
1769 1789
1770 1790
1771 // html slopiness: handle unbalanched tag closing 1791 // html slopiness: handle unbalanched tag closing
1772 while ( curtag.name != tagname ) { 1792 while ( curtag.name != tagname ) {
1773 QString msg; 1793 QString msg;
1774 msg.sprintf( "QText Warning: Document not valid ( '%s' not closed before '%s' #%d)", 1794 msg.sprintf( "QText Warning: Document not valid ( '%s' not closed before '%s' #%d)",
1775 curtag.name.ascii(), tagname.ascii(), pos); 1795 curtag.name.ascii(), tagname.ascii(), pos);
1776 sheet_->error( msg ); 1796 sheet_->error( msg );
1777 if ( tags.isEmpty() ) 1797 if ( tags.isEmpty() )
1778 break; 1798 break;
1779 curtag = tags.pop(); 1799 curtag = tags.pop();
1780 } 1800 }
1781 1801
1782 1802
1783 // close the tag 1803 // close the tag
1784 if ( !tags.isEmpty() ) 1804 if ( !tags.isEmpty() )
1785 curtag = tags.pop(); 1805 curtag = tags.pop();
1786 else 1806 else
1787 curtag = initag; 1807 curtag = initag;
1788 1808
1789 if ( needNewPar ) { 1809 if ( needNewPar ) {
1790 if ( textEditMode && tagname == "p" ) // preserve empty paragraphs 1810 if ( textEditMode && tagname == "p" ) // preserve empty paragraphs
1791 hasNewPar = FALSE; 1811 hasNewPar = FALSE;
1792 NEWPAR; 1812 NEWPAR;
1793 } 1813 }
1794 } 1814 }
1795 } else { 1815 } else {
1796 // normal contents 1816 // normal contents
1797 QString s; 1817 QString s;
1798 QChar c; 1818 QChar c;
1799 while ( pos < length && !hasPrefix(doc, length, pos, QChar('<') ) ){ 1819 while ( pos < length && !hasPrefix(doc, length, pos, QChar('<') ) ){
1800 if ( textEditMode ) { 1820 if ( textEditMode ) {
1801 // text edit mode: we handle all white space but ignore newlines 1821 // text edit mode: we handle all white space but ignore newlines
1802 c = parseChar( doc, length, pos, QStyleSheetItem::WhiteSpacePre ); 1822 c = parseChar( doc, length, pos, QStyleSheetItem::WhiteSpacePre );
1803 if ( c == QChar_linesep ) 1823 if ( c == QChar_linesep )
1804 break; 1824 break;
1805 } else { 1825 } else {
1806 int l = pos; 1826 int l = pos;
1807 c = parseChar( doc, length, pos, curtag.wsm ); 1827 c = parseChar( doc, length, pos, curtag.wsm );
1808 1828
1809 // in white space pre mode: treat any space as non breakable 1829 // in white space pre mode: treat any space as non breakable
1810 if ( c == ' ' && curtag.wsm == QStyleSheetItem::WhiteSpacePre ) 1830 if ( c == ' ' && curtag.wsm == QStyleSheetItem::WhiteSpacePre )
1811 c = QChar::nbsp; 1831 c = QChar::nbsp;
1812 1832
1813 if ( c == ' ' || c == QChar_linesep ) { 1833 if ( c == ' ' || c == QChar_linesep ) {
1814 /* avoid overlong paragraphs by forcing a new 1834 /* avoid overlong paragraphs by forcing a new
1815 paragraph after 4096 characters. This case can 1835 paragraph after 4096 characters. This case can
1816 occur when loading undiscovered plain text 1836 occur when loading undiscovered plain text
1817 documents in rich text mode. Instead of hanging 1837 documents in rich text mode. Instead of hanging
1818 forever, we do the trick. 1838 forever, we do the trick.
1819 */ 1839 */
1820 if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && s.length() > 4096 ) do { 1840 if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && s.length() > 4096 ) do {
1821 if ( doc[l] == '\n' ) { 1841 if ( doc[l] == '\n' ) {
1822 hasNewPar = FALSE; // for a new paragraph ... 1842 hasNewPar = FALSE; // for a new paragraph ...
1823 NEWPAR; 1843 NEWPAR;
1824 hasNewPar = FALSE; // ... and make it non-reusable 1844 hasNewPar = FALSE; // ... and make it non-reusable
1825 c = '\n'; // make sure we break below 1845 c = '\n'; // make sure we break below
1826 break; 1846 break;
1827 } 1847 }
1828 } while ( ++l < pos ); 1848 } while ( ++l < pos );
1829 } 1849 }
1830 } 1850 }
1831 1851
1832 if ( c == '\n' ) 1852 if ( c == '\n' )
1833 break; // break on newlines, pre delievers a QChar_linesep 1853 break; // break on newlines, pre delievers a QChar_linesep
1834 1854
1835 bool c_isSpace = c.isSpace() && c.unicode() != 0x00a0U && !textEditMode; 1855 bool c_isSpace = c.isSpace() && c.unicode() != 0x00a0U && !textEditMode;
1836 1856
1837 if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && c_isSpace && space ) 1857 if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && c_isSpace && space )
1838 continue; 1858 continue;
1839 if ( c == '\r' ) 1859 if ( c == '\r' )
1840 continue; 1860 continue;
1841 space = c_isSpace; 1861 space = c_isSpace;
1842 s += c; 1862 s += c;
1843 } 1863 }
1844 if ( !s.isEmpty() && curtag.style->displayMode() != QStyleSheetItem::DisplayNone ) { 1864 if ( !s.isEmpty() && curtag.style->displayMode() != QStyleSheetItem::DisplayNone ) {
1845 hasNewPar = FALSE; 1865 hasNewPar = FALSE;
1846 int index = QMAX( curpar->length(),1) - 1; 1866 int index = QMAX( curpar->length(),1) - 1;
1847 curpar->append( s ); 1867 curpar->append( s );
1848 QTextFormat* f = formatCollection()->format( &curtag.format ); 1868 QTextFormat* f = formatCollection()->format( &curtag.format );
1849 curpar->setFormat( index, s.length(), f, FALSE ); // do not use collection because we have done that already 1869 curpar->setFormat( index, s.length(), f, FALSE ); // do not use collection because we have done that already
1850 f->ref += s.length() -1; // that what friends are for... 1870 f->ref += s.length() -1; // that what friends are for...
1851 if ( !curtag.anchorHref.isEmpty() ) { 1871 if ( !curtag.anchorHref.isEmpty() ) {
1852 for ( int i = 0; i < int(s.length()); i++ ) 1872 for ( int i = 0; i < int(s.length()); i++ )
1853 curpar->at(index + i)->setAnchor( QString::null, curtag.anchorHref ); 1873 curpar->at(index + i)->setAnchor( QString::null, curtag.anchorHref );
1854 } 1874 }
1855 if ( !anchorName.isEmpty() ) { 1875 if ( !anchorName.isEmpty() ) {
1856 curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() ); 1876 curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() );
1857 anchorName = QString::null; 1877 anchorName = QString::null;
1858 } 1878 }
1859 } 1879 }
1860 } 1880 }
1861 } 1881 }
1862 if ( hasNewPar && curpar != fParag && !cursor ) { 1882 if ( hasNewPar && curpar != fParag && !cursor ) {
1863 // cleanup unused last paragraphs 1883 // cleanup unused last paragraphs
1864 curpar = curpar->p; 1884 curpar = curpar->p;
1865 delete curpar->n; 1885 delete curpar->n;
1866 } 1886 }
1867 if ( !anchorName.isEmpty() ) { 1887 if ( !anchorName.isEmpty() ) {
1868 curpar->at(curpar->length() - 1)->setAnchor( anchorName, curpar->at( curpar->length() - 1 )->anchorHref() ); 1888 curpar->at(curpar->length() - 1)->setAnchor( anchorName, curpar->at( curpar->length() - 1 )->anchorHref() );
1869 anchorName = QString::null; 1889 anchorName = QString::null;
1870 } 1890 }
1871 1891
1872 1892
1873 setRichTextMarginsInternal( styles, stylesPar ); 1893 setRichTextMarginsInternal( styles, stylesPar );
1874 1894
1875 if ( cursor ) { 1895 if ( cursor ) {
1876 cursor->gotoPreviousLetter(); 1896 cursor->gotoPreviousLetter();
1877 cursor->remove(); 1897 cursor->remove();
1878 } 1898 }
1879 1899
1880} 1900}
1881 1901
1882void QTextDocument::setRichTextMarginsInternal( QPtrList< QPtrVector<QStyleSheetItem> >& styles, QTextParagraph* stylesPar ) 1902void QTextDocument::setRichTextMarginsInternal( QPtrList< QPtrVector<QStyleSheetItem> >& styles, QTextParagraph* stylesPar )
1883{ 1903{
1884 // margin and line spacing calculation 1904 // margin and line spacing calculation
1885 QPtrVector<QStyleSheetItem>* prevStyle = 0; 1905 QPtrVector<QStyleSheetItem>* prevStyle = 0;
1886 QPtrVector<QStyleSheetItem>* curStyle = styles.first(); 1906 QPtrVector<QStyleSheetItem>* curStyle = styles.first();
1887 QPtrVector<QStyleSheetItem>* nextStyle = styles.next(); 1907 QPtrVector<QStyleSheetItem>* nextStyle = styles.next();
1888 while ( stylesPar ) { 1908 while ( stylesPar ) {
1889 if ( !curStyle ) { 1909 if ( !curStyle ) {
1890 stylesPar = stylesPar->next(); 1910 stylesPar = stylesPar->next();
1891 prevStyle = curStyle; 1911 prevStyle = curStyle;
1892 curStyle = nextStyle; 1912 curStyle = nextStyle;
1893 nextStyle = styles.next(); 1913 nextStyle = styles.next();
1894 continue; 1914 continue;
1895 } 1915 }
1896 1916
1897 int i, mar; 1917 int i, mar;
1898 QStyleSheetItem* mainStyle = curStyle->size() ? (*curStyle)[curStyle->size()-1] : 0; 1918 QStyleSheetItem* mainStyle = (*curStyle)[curStyle->size()-1];
1899 if ( mainStyle && mainStyle->displayMode() == QStyleSheetItem::DisplayListItem ) 1919 if ( !mainStyle )
1920 return;
1921
1922 if ( mainStyle->displayMode() == QStyleSheetItem::DisplayListItem )
1900 stylesPar->setListItem( TRUE ); 1923 stylesPar->setListItem( TRUE );
1901 int numLists = 0; 1924 int numLists = 0;
1902 for ( i = 0; i < (int)curStyle->size(); ++i ) { 1925 for ( i = 0; i < (int)curStyle->size(); ++i ) {
1903 if ( (*curStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock 1926 if ( (*curStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock
1904 && int((*curStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined ) 1927 && int((*curStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined )
1905 numLists++; 1928 numLists++;
1906 } 1929 }
1907 stylesPar->ldepth = numLists; 1930 stylesPar->ldepth = numLists;
1908 if ( stylesPar->next() && nextStyle ) { 1931 if ( stylesPar->next() && nextStyle ) {
1909 // also set the depth of the next paragraph, required for the margin calculation 1932 // also set the depth of the next paragraph, required for the margin calculation
1910 numLists = 0; 1933 numLists = 0;
1911 for ( i = 0; i < (int)nextStyle->size(); ++i ) { 1934 for ( i = 0; i < (int)nextStyle->size(); ++i ) {
1912 if ( (*nextStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock 1935 if ( (*nextStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock
1913 && int((*nextStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined ) 1936 && int((*nextStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined )
1914 numLists++; 1937 numLists++;
1915 } 1938 }
1916 stylesPar->next()->ldepth = numLists; 1939 stylesPar->next()->ldepth = numLists;
1917 } 1940 }
1918 1941
1919 // do the top margin 1942 // do the top margin
1920 QStyleSheetItem* item = mainStyle; 1943 QStyleSheetItem* item = mainStyle;
1921 int m; 1944 int m;
1922 if (stylesPar->utm > 0 ) { 1945 if (stylesPar->utm > 0 ) {
1923 m = stylesPar->utm-1; 1946 m = stylesPar->utm-1;
1924 stylesPar->utm = 0; 1947 stylesPar->utm = 0;
1925 } else { 1948 } else {
1926 m = QMAX(0, item->margin( QStyleSheetItem::MarginTop ) ); 1949 m = QMAX(0, item->margin( QStyleSheetItem::MarginTop ) );
1927 if ( item->displayMode() == QStyleSheetItem::DisplayListItem 1950 if ( item->displayMode() == QStyleSheetItem::DisplayListItem
1928 && stylesPar->ldepth ) 1951 && stylesPar->ldepth )
1929 m /= stylesPar->ldepth; 1952 m /= stylesPar->ldepth;
1930 } 1953 }
1931 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { 1954 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
1932 item = (*curStyle)[ i ]; 1955 item = (*curStyle)[ i ];
1933 if ( prevStyle && i < (int) prevStyle->size() && 1956 if ( prevStyle && i < (int) prevStyle->size() &&
1934 ( item->displayMode() == QStyleSheetItem::DisplayBlock && 1957 ( item->displayMode() == QStyleSheetItem::DisplayBlock &&
1935 (*prevStyle)[ i ] == item ) ) 1958 (*prevStyle)[ i ] == item ) )
1936 break; 1959 break;
1937 // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags 1960 // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags
1938 if ( int(item->listStyle()) != QStyleSheetItem::Undefined && 1961 if ( int(item->listStyle()) != QStyleSheetItem::Undefined &&
1939 ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) ) 1962 ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) )
1940 continue; 1963 continue;
1941 mar = QMAX( 0, item->margin( QStyleSheetItem::MarginTop ) ); 1964 mar = QMAX( 0, item->margin( QStyleSheetItem::MarginTop ) );
1942 m = QMAX( m, mar ); 1965 m = QMAX( m, mar );
1943 } 1966 }
1944 stylesPar->utm = m - stylesPar->topMargin(); 1967 stylesPar->utm = m - stylesPar->topMargin();
1945 1968
1946 // do the bottom margin 1969 // do the bottom margin
1947 item = mainStyle; 1970 item = mainStyle;
1948 if (stylesPar->ubm > 0 ) { 1971 if (stylesPar->ubm > 0 ) {
1949 m = stylesPar->ubm-1; 1972 m = stylesPar->ubm-1;
1950 stylesPar->ubm = 0; 1973 stylesPar->ubm = 0;
1951 } else { 1974 } else {
1952 m = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) ); 1975 m = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) );
1953 if ( item->displayMode() == QStyleSheetItem::DisplayListItem 1976 if ( item->displayMode() == QStyleSheetItem::DisplayListItem
1954 && stylesPar->ldepth ) 1977 && stylesPar->ldepth )
1955 m /= stylesPar->ldepth; 1978 m /= stylesPar->ldepth;
1956 } 1979 }
1957 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { 1980 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
1958 item = (*curStyle)[ i ]; 1981 item = (*curStyle)[ i ];
1959 if ( nextStyle && i < (int) nextStyle->size() && 1982 if ( nextStyle && i < (int) nextStyle->size() &&
1960 ( item->displayMode() == QStyleSheetItem::DisplayBlock && 1983 ( item->displayMode() == QStyleSheetItem::DisplayBlock &&
1961 (*nextStyle)[ i ] == item ) ) 1984 (*nextStyle)[ i ] == item ) )
1962 break; 1985 break;
1963 // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags 1986 // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags
1964 if ( int(item->listStyle()) != QStyleSheetItem::Undefined && 1987 if ( int(item->listStyle()) != QStyleSheetItem::Undefined &&
1965 ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) ) 1988 ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) )
1966 continue; 1989 continue;
1967 mar = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) ); 1990 mar = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) );
1968 m = QMAX( m, mar ); 1991 m = QMAX( m, mar );
1969 } 1992 }
1970 stylesPar->ubm = m - stylesPar->bottomMargin(); 1993 stylesPar->ubm = m - stylesPar->bottomMargin();
1971 1994
1972 // do the left margin, simplyfied 1995 // do the left margin, simplyfied
1973 item = mainStyle; 1996 item = mainStyle;
1974 if (stylesPar->ulm > 0 ) { 1997 if (stylesPar->ulm > 0 ) {
1975 m = stylesPar->ulm-1; 1998 m = stylesPar->ulm-1;
1976 stylesPar->ulm = 0; 1999 stylesPar->ulm = 0;
1977 } else { 2000 } else {
1978 m = QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) ); 2001 m = QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) );
1979 } 2002 }
1980 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { 2003 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
1981 item = (*curStyle)[ i ]; 2004 item = (*curStyle)[ i ];
1982 m += QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) ); 2005 m += QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) );
1983 } 2006 }
1984 stylesPar->ulm = m - stylesPar->leftMargin(); 2007 stylesPar->ulm = m - stylesPar->leftMargin();
1985 2008
1986 // do the right margin, simplyfied 2009 // do the right margin, simplyfied
1987 item = mainStyle; 2010 item = mainStyle;
1988 if (stylesPar->urm > 0 ) { 2011 if (stylesPar->urm > 0 ) {
1989 m = stylesPar->urm-1; 2012 m = stylesPar->urm-1;
1990 stylesPar->urm = 0; 2013 stylesPar->urm = 0;
1991 } else { 2014 } else {
1992 m = QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) ); 2015 m = QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) );
1993 } 2016 }
1994 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { 2017 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
1995 item = (*curStyle)[ i ]; 2018 item = (*curStyle)[ i ];
1996 m += QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) ); 2019 m += QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) );
1997 } 2020 }
1998 stylesPar->urm = m - stylesPar->rightMargin(); 2021 stylesPar->urm = m - stylesPar->rightMargin();
1999 2022
2000 // do the first line margin, which really should be called text-indent 2023 // do the first line margin, which really should be called text-indent
2001 item = mainStyle; 2024 item = mainStyle;
2002 if (stylesPar->uflm > 0 ) { 2025 if (stylesPar->uflm > 0 ) {
2003 m = stylesPar->uflm-1; 2026 m = stylesPar->uflm-1;
2004 stylesPar->uflm = 0; 2027 stylesPar->uflm = 0;
2005 } else { 2028 } else {
2006 m = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) ); 2029 m = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) );
2007 } 2030 }
2008 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { 2031 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
2009 item = (*curStyle)[ i ]; 2032 item = (*curStyle)[ i ];
2010 mar = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) ); 2033 mar = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) );
2011 m = QMAX( m, mar ); 2034 m = QMAX( m, mar );
2012 } 2035 }
2013 stylesPar->uflm =m - stylesPar->firstLineMargin(); 2036 stylesPar->uflm =m - stylesPar->firstLineMargin();
2014 2037
2015 // do the bogus line "spacing", which really is just an extra margin 2038 // do the bogus line "spacing", which really is just an extra margin
2016 item = mainStyle; 2039 item = mainStyle;
2017 for ( i = (int)curStyle->size() - 1 ; i >= 0; --i ) { 2040 for ( i = (int)curStyle->size() - 1 ; i >= 0; --i ) {
2018 item = (*curStyle)[ i ]; 2041 item = (*curStyle)[ i ];
2019 if ( item->lineSpacing() != QStyleSheetItem::Undefined ) { 2042 if ( item->lineSpacing() != QStyleSheetItem::Undefined ) {
2020 stylesPar->ulinespacing = item->lineSpacing(); 2043 stylesPar->ulinespacing = item->lineSpacing();
2021 if ( formatCollection() && 2044 if ( formatCollection() &&
2022 stylesPar->ulinespacing < formatCollection()->defaultFormat()->height() ) 2045 stylesPar->ulinespacing < formatCollection()->defaultFormat()->height() )
2023 stylesPar->ulinespacing += formatCollection()->defaultFormat()->height(); 2046 stylesPar->ulinespacing += formatCollection()->defaultFormat()->height();
2024 break; 2047 break;
2025 } 2048 }
2026 } 2049 }
2027 2050
2028 stylesPar = stylesPar->next(); 2051 stylesPar = stylesPar->next();
2029 prevStyle = curStyle; 2052 prevStyle = curStyle;
2030 curStyle = nextStyle; 2053 curStyle = nextStyle;
2031 nextStyle = styles.next(); 2054 nextStyle = styles.next();
2032 } 2055 }
2033} 2056}
2034 2057
2035void QTextDocument::setText( const QString &text, const QString &context ) 2058void QTextDocument::setText( const QString &text, const QString &context )
2036{ 2059{
2037 focusIndicator.parag = 0; 2060 focusIndicator.parag = 0;
2038 selections.clear(); 2061 selections.clear();
2039 if ( txtFormat == Qt::AutoText && QStyleSheet::mightBeRichText( text ) || 2062 if ( txtFormat == Qt::AutoText && QStyleSheet::mightBeRichText( text ) ||
2040 txtFormat == Qt::RichText ) 2063 txtFormat == Qt::RichText )
2041 setRichText( text, context ); 2064 setRichText( text, context );
2042 else 2065 else
2043 setPlainText( text ); 2066 setPlainText( text );
2044} 2067}
2045 2068
2046QString QTextDocument::plainText() const 2069QString QTextDocument::plainText() const
2047{ 2070{
2048 QString buffer; 2071 QString buffer;
2049 QString s; 2072 QString s;
2050 QTextParagraph *p = fParag; 2073 QTextParagraph *p = fParag;
2051 while ( p ) { 2074 while ( p ) {
2052 if ( !p->mightHaveCustomItems ) { 2075 if ( !p->mightHaveCustomItems ) {
2053 s = p->string()->toString(); 2076 s = p->string()->toString();
2054 } else { 2077 } else {
2055 for ( int i = 0; i < p->length() - 1; ++i ) { 2078 for ( int i = 0; i < p->length() - 1; ++i ) {
2056 if ( p->at( i )->isCustom() ) { 2079 if ( p->at( i )->isCustom() ) {
2057 if ( p->at( i )->customItem()->isNested() ) { 2080 if ( p->at( i )->customItem()->isNested() ) {
2058 s += "\n"; 2081 s += "\n";
2059 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 2082 QTextTable *t = (QTextTable*)p->at( i )->customItem();
2060 QPtrList<QTextTableCell> cells = t->tableCells(); 2083 QPtrList<QTextTableCell> cells = t->tableCells();
2061 for ( QTextTableCell *c = cells.first(); c; c = cells.next() ) 2084 for ( QTextTableCell *c = cells.first(); c; c = cells.next() )
2062 s += c->richText()->plainText() + "\n"; 2085 s += c->richText()->plainText() + "\n";
2063 s += "\n"; 2086 s += "\n";
2064 } 2087 }
2065 } else { 2088 } else {
2066 s += p->at( i )->c; 2089 s += p->at( i )->c;
2067 } 2090 }
2068 } 2091 }
2069 } 2092 }
2070 s.remove( s.length() - 1, 1 ); 2093 s.remove( s.length() - 1, 1 );
2071 if ( p->next() ) 2094 if ( p->next() )
2072 s += "\n"; 2095 s += "\n";
2073 buffer += s; 2096 buffer += s;
2074 p = p->next(); 2097 p = p->next();
2075 } 2098 }
2076 return buffer; 2099 return buffer;
2077} 2100}
2078 2101
2079static QString align_to_string( int a ) 2102static QString align_to_string( int a )
2080{ 2103{
2081 if ( a & Qt::AlignRight ) 2104 if ( a & Qt::AlignRight )
2082 return " align=\"right\""; 2105 return " align=\"right\"";
2083 if ( a & Qt::AlignHCenter ) 2106 if ( a & Qt::AlignHCenter )
2084 return " align=\"center\""; 2107 return " align=\"center\"";
2085 if ( a & Qt3::AlignJustify ) 2108 if ( a & Qt3::AlignJustify )
2086 return " align=\"justify\""; 2109 return " align=\"justify\"";
2087 return QString::null; 2110 return QString::null;
2088} 2111}
2089 2112
2090static QString direction_to_string( int d ) 2113static QString direction_to_string( int d )
2091{ 2114{
2092 if ( d != QChar::DirON ) 2115 if ( d != QChar::DirON )
2093 return ( d == QChar::DirL? " dir=\"ltr\"" : " dir=\"rtl\"" ); 2116 return ( d == QChar::DirL? " dir=\"ltr\"" : " dir=\"rtl\"" );
2094 return QString::null; 2117 return QString::null;
2095} 2118}
2096 2119
2097static QString list_value_to_string( int v ) 2120static QString list_value_to_string( int v )
2098{ 2121{
2099 if ( v != -1 ) 2122 if ( v != -1 )
2100 return " listvalue=\"" + QString::number( v ) + "\""; 2123 return " listvalue=\"" + QString::number( v ) + "\"";
2101 return QString::null; 2124 return QString::null;
2102} 2125}
2103 2126
2104static QString list_style_to_string( int v ) 2127static QString list_style_to_string( int v )
2105{ 2128{
2106 switch( v ) { 2129 switch( v ) {
2107 case QStyleSheetItem::ListDecimal: return "\"1\""; 2130 case QStyleSheetItem::ListDecimal: return "\"1\"";
2108 case QStyleSheetItem::ListLowerAlpha: return "\"a\""; 2131 case QStyleSheetItem::ListLowerAlpha: return "\"a\"";
2109 case QStyleSheetItem::ListUpperAlpha: return "\"A\""; 2132 case QStyleSheetItem::ListUpperAlpha: return "\"A\"";
2110 case QStyleSheetItem::ListDisc: return "\"disc\""; 2133 case QStyleSheetItem::ListDisc: return "\"disc\"";
2111 case QStyleSheetItem::ListSquare: return "\"square\""; 2134 case QStyleSheetItem::ListSquare: return "\"square\"";
2112 case QStyleSheetItem::ListCircle: return "\"circle\""; 2135 case QStyleSheetItem::ListCircle: return "\"circle\"";
2113 default: 2136 default:
2114 return QString::null; 2137 return QString::null;
2115 } 2138 }
2116} 2139}
2117 2140
2118static inline bool list_is_ordered( int v ) 2141static inline bool list_is_ordered( int v )
2119{ 2142{
2120 return v == QStyleSheetItem::ListDecimal || 2143 return v == QStyleSheetItem::ListDecimal ||
2121 v == QStyleSheetItem::ListLowerAlpha || 2144 v == QStyleSheetItem::ListLowerAlpha ||
2122 v == QStyleSheetItem::ListUpperAlpha; 2145 v == QStyleSheetItem::ListUpperAlpha;
2123} 2146}
2124 2147
2125 2148
2126static QString margin_to_string( QStyleSheetItem* style, int t, int b, int l, int r, int fl ) 2149static QString margin_to_string( QStyleSheetItem* style, int t, int b, int l, int r, int fl )
2127{ 2150{
2128 QString s; 2151 QString s;
2129 if ( l > 0 ) 2152 if ( l > 0 )
2130 s += QString(!!s?";":"") + "margin-left:" + QString::number(l+QMAX(0,style->margin(QStyleSheetItem::MarginLeft))) + "px"; 2153 s += QString(!!s?";":"") + "margin-left:" + QString::number(l+QMAX(0,style->margin(QStyleSheetItem::MarginLeft))) + "px";
2131 if ( r > 0 ) 2154 if ( r > 0 )
2132 s += QString(!!s?";":"") + "margin-right:" + QString::number(r+QMAX(0,style->margin(QStyleSheetItem::MarginRight))) + "px"; 2155 s += QString(!!s?";":"") + "margin-right:" + QString::number(r+QMAX(0,style->margin(QStyleSheetItem::MarginRight))) + "px";
2133 if ( t > 0 ) 2156 if ( t > 0 )
2134 s += QString(!!s?";":"") + "margin-top:" + QString::number(t+QMAX(0,style->margin(QStyleSheetItem::MarginTop))) + "px"; 2157 s += QString(!!s?";":"") + "margin-top:" + QString::number(t+QMAX(0,style->margin(QStyleSheetItem::MarginTop))) + "px";
2135 if ( b > 0 ) 2158 if ( b > 0 )
2136 s += QString(!!s?";":"") + "margin-bottom:" + QString::number(b+QMAX(0,style->margin(QStyleSheetItem::MarginBottom))) + "px"; 2159 s += QString(!!s?";":"") + "margin-bottom:" + QString::number(b+QMAX(0,style->margin(QStyleSheetItem::MarginBottom))) + "px";
2137 if ( fl > 0 ) 2160 if ( fl > 0 )
2138 s += QString(!!s?";":"") + "text-indent:" + QString::number(fl+QMAX(0,style->margin(QStyleSheetItem::MarginFirstLine))) + "px"; 2161 s += QString(!!s?";":"") + "text-indent:" + QString::number(fl+QMAX(0,style->margin(QStyleSheetItem::MarginFirstLine))) + "px";
2139 if ( !!s ) 2162 if ( !!s )
2140 return " style=\"" + s + "\""; 2163 return " style=\"" + s + "\"";
2141 return QString::null; 2164 return QString::null;
2142} 2165}
2143 2166
2144QString QTextDocument::richText() const 2167QString QTextDocument::richText() const
2145{ 2168{
2146 QString s = ""; 2169 QString s = "";
2147 if ( !par ) { 2170 if ( !par ) {
2148 s += "<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body style=\"font-size:" ; 2171 s += "<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body style=\"font-size:" ;
2149 s += QString::number( formatCollection()->defaultFormat()->font().pointSize() ); 2172 s += QString::number( formatCollection()->defaultFormat()->font().pointSize() );
2150 s += "pt;font-family:"; 2173 s += "pt;font-family:";
2151 s += formatCollection()->defaultFormat()->font().family(); 2174 s += formatCollection()->defaultFormat()->font().family();
2152 s +="\">"; 2175 s +="\">";
2153 } 2176 }
2154 QTextParagraph* p = fParag; 2177 QTextParagraph* p = fParag;
2155 2178
2156 QStyleSheetItem* item_p = styleSheet()->item("p"); 2179 QStyleSheetItem* item_p = styleSheet()->item("p");
2157 QStyleSheetItem* item_ul = styleSheet()->item("ul"); 2180 QStyleSheetItem* item_ul = styleSheet()->item("ul");
2158 QStyleSheetItem* item_ol = styleSheet()->item("ol"); 2181 QStyleSheetItem* item_ol = styleSheet()->item("ol");
2159 QStyleSheetItem* item_li = styleSheet()->item("li"); 2182 QStyleSheetItem* item_li = styleSheet()->item("li");
2160 if ( !item_p || !item_ul || !item_ol || !item_li ) { 2183 if ( !item_p || !item_ul || !item_ol || !item_li ) {
2161 owarn << "QTextEdit: cannot export HTML due to insufficient stylesheet (lack of p, ul, ol, or li)" << oendl; 2184 owarn << "QTextEdit: cannot export HTML due to insufficient stylesheet (lack of p, ul, ol, or li)" << oendl;
2162 return QString::null; 2185 return QString::null;
2163 } 2186 }
2164 int pastListDepth = 0; 2187 int pastListDepth = 0;
2165 int listDepth = 0; 2188 int listDepth = 0;
2166 int futureListDepth = 0; 2189 int futureListDepth = 0;
2167 QMemArray<int> listStyles(10); 2190 QMemArray<int> listStyles(10);
2168 2191
2169 while ( p ) { 2192 while ( p ) {
2170 listDepth = p->listDepth(); 2193 listDepth = p->listDepth();
2171 if ( listDepth < pastListDepth ) { 2194 if ( listDepth < pastListDepth ) {
2172 for ( int i = listDepth+1; i <= pastListDepth; i++ ) 2195 for ( int i = listDepth+1; i <= pastListDepth; i++ )
2173 s += list_is_ordered( listStyles[i] ) ? "</ol>" : "</ul>"; 2196 s += list_is_ordered( listStyles[i] ) ? "</ol>" : "</ul>";
2174 s += '\n'; 2197 s += '\n';
2175 } else if ( listDepth > pastListDepth ) { 2198 } else if ( listDepth > pastListDepth ) {
2176 s += '\n'; 2199 s += '\n';
2177 listStyles.resize( QMAX( (int)listStyles.size(), listDepth+1 ) ); 2200 listStyles.resize( QMAX( (int)listStyles.size(), listDepth+1 ) );
2178 QString list_type; 2201 QString list_type;
2179 listStyles[listDepth] = p->listStyle(); 2202 listStyles[listDepth] = p->listStyle();
2180 if ( !list_is_ordered( p->listStyle() ) || item_ol->listStyle() != p->listStyle() ) 2203 if ( !list_is_ordered( p->listStyle() ) || item_ol->listStyle() != p->listStyle() )
2181 list_type = " type=" + list_style_to_string( p->listStyle() ); 2204 list_type = " type=" + list_style_to_string( p->listStyle() );
2182 for ( int i = pastListDepth; i < listDepth; i++ ) { 2205 for ( int i = pastListDepth; i < listDepth; i++ ) {
2183 s += list_is_ordered( p->listStyle() ) ? "<ol" : "<ul" ; 2206 s += list_is_ordered( p->listStyle() ) ? "<ol" : "<ul" ;
2184 s += list_type + ">"; 2207 s += list_type + ">";
2185 } 2208 }
2186 } else { 2209 } else {
2187 s += '\n'; 2210 s += '\n';
2188 } 2211 }
2189 2212
2190 QString ps = p->richText(); 2213 QString ps = p->richText();
2191 2214
2192 // for the bottom margin we need to know whether we are at the end of a list 2215 // for the bottom margin we need to know whether we are at the end of a list
2193 futureListDepth = 0; 2216 futureListDepth = 0;
2194 if ( listDepth > 0 && p->next() ) 2217 if ( listDepth > 0 && p->next() )
2195 futureListDepth = p->next()->listDepth(); 2218 futureListDepth = p->next()->listDepth();
2196 2219
2197 if ( richTextExportStart && richTextExportStart->paragraph() ==p && 2220 if ( richTextExportStart && richTextExportStart->paragraph() ==p &&
2198 richTextExportStart->index() == 0 ) 2221 richTextExportStart->index() == 0 )
2199 s += "<selstart/>"; 2222 s += "<selstart/>";
2200 2223
2201 if ( p->isListItem() ) { 2224 if ( p->isListItem() ) {
2202 s += "<li"; 2225 s += "<li";
2203 if ( p->listStyle() != listStyles[listDepth] ) 2226 if ( p->listStyle() != listStyles[listDepth] )
2204 s += " type=" + list_style_to_string( p->listStyle() ); 2227 s += " type=" + list_style_to_string( p->listStyle() );
2205 s +=align_to_string( p->alignment() ); 2228 s +=align_to_string( p->alignment() );
2206 s += margin_to_string( item_li, p->utm, p->ubm, p->ulm, p->urm, p->uflm ); 2229 s += margin_to_string( item_li, p->utm, p->ubm, p->ulm, p->urm, p->uflm );
2207 s += list_value_to_string( p->listValue() ); 2230 s += list_value_to_string( p->listValue() );
2208 s += direction_to_string( p->direction() ); 2231 s += direction_to_string( p->direction() );
2209 s +=">"; 2232 s +=">";
2210 s += ps; 2233 s += ps;
2211 s += "</li>"; 2234 s += "</li>";
2212 } else { 2235 } else {
2213 // normal paragraph item 2236 // normal paragraph item
2214 s += "<p"; 2237 s += "<p";
2215 s += align_to_string( p->alignment() ); 2238 s += align_to_string( p->alignment() );
2216 s += margin_to_string( item_p, p->utm, p->ubm, p->ulm, p->urm, p->uflm ); 2239 s += margin_to_string( item_p, p->utm, p->ubm, p->ulm, p->urm, p->uflm );
2217 s +=direction_to_string( p->direction() ); 2240 s +=direction_to_string( p->direction() );
2218 s += ">"; 2241 s += ">";
2219 s += ps; 2242 s += ps;
2220 s += "</p>"; 2243 s += "</p>";
2221 } 2244 }
2222 pastListDepth = listDepth; 2245 pastListDepth = listDepth;
2223 p = p->next(); 2246 p = p->next();
2224 } 2247 }
2225 while ( listDepth > 0 ) { 2248 while ( listDepth > 0 ) {
2226 s += list_is_ordered( listStyles[listDepth] ) ? "</ol>" : "</ul>"; 2249 s += list_is_ordered( listStyles[listDepth] ) ? "</ol>" : "</ul>";
2227 listDepth--; 2250 listDepth--;
2228 } 2251 }
2229 2252
2230 if ( !par ) 2253 if ( !par )
2231 s += "\n</body></html>\n"; 2254 s += "\n</body></html>\n";
2232 2255
2233 return s; 2256 return s;
2234} 2257}
2235 2258
2236QString QTextDocument::text() const 2259QString QTextDocument::text() const
2237{ 2260{
2238 if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText ) 2261 if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText )
2239 return richText(); 2262 return richText();
2240 return plainText(); 2263 return plainText();
2241} 2264}
2242 2265
2243QString QTextDocument::text( int parag ) const 2266QString QTextDocument::text( int parag ) const
2244{ 2267{
2245 QTextParagraph *p = paragAt( parag ); 2268 QTextParagraph *p = paragAt( parag );
2246 if ( !p ) 2269 if ( !p )
2247 return QString::null; 2270 return QString::null;
2248 2271
2249 if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText ) 2272 if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText )
2250 return p->richText(); 2273 return p->richText();
2251 else 2274 else
2252 return p->string()->toString(); 2275 return p->string()->toString();
2253} 2276}
2254 2277
2255void QTextDocument::invalidate() 2278void QTextDocument::invalidate()
2256{ 2279{
2257 QTextParagraph *s = fParag; 2280 QTextParagraph *s = fParag;
2258 while ( s ) { 2281 while ( s ) {
2259 s->invalidate( 0 ); 2282 s->invalidate( 0 );
2260 s = s->next(); 2283 s = s->next();
2261 } 2284 }
2262} 2285}
2263 2286
2264void QTextDocument::selectionStart( int id, int &paragId, int &index ) 2287void QTextDocument::selectionStart( int id, int &paragId, int &index )
2265{ 2288{
2266 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2289 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2267 if ( it == selections.end() ) 2290 if ( it == selections.end() )
2268 return; 2291 return;
2269 QTextDocumentSelection &sel = *it; 2292 QTextDocumentSelection &sel = *it;
2270 paragId = !sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId(); 2293 paragId = !sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId();
2271 index = !sel.swapped ? sel.startCursor.index() : sel.endCursor.index(); 2294 index = !sel.swapped ? sel.startCursor.index() : sel.endCursor.index();
2272} 2295}
2273 2296
2274QTextCursor QTextDocument::selectionStartCursor( int id) 2297QTextCursor QTextDocument::selectionStartCursor( int id)
2275{ 2298{
2276 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2299 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2277 if ( it == selections.end() ) 2300 if ( it == selections.end() )
2278 return QTextCursor( this ); 2301 return QTextCursor( this );
2279 QTextDocumentSelection &sel = *it; 2302 QTextDocumentSelection &sel = *it;
2280 if ( sel.swapped ) 2303 if ( sel.swapped )
2281 return sel.endCursor; 2304 return sel.endCursor;
2282 return sel.startCursor; 2305 return sel.startCursor;
2283} 2306}
2284 2307
2285QTextCursor QTextDocument::selectionEndCursor( int id) 2308QTextCursor QTextDocument::selectionEndCursor( int id)
2286{ 2309{
2287 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2310 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2288 if ( it == selections.end() ) 2311 if ( it == selections.end() )
2289 return QTextCursor( this ); 2312 return QTextCursor( this );
2290 QTextDocumentSelection &sel = *it; 2313 QTextDocumentSelection &sel = *it;
2291 if ( !sel.swapped ) 2314 if ( !sel.swapped )
2292 return sel.endCursor; 2315 return sel.endCursor;
2293 return sel.startCursor; 2316 return sel.startCursor;
2294} 2317}
2295 2318
2296void QTextDocument::selectionEnd( int id, int &paragId, int &index ) 2319void QTextDocument::selectionEnd( int id, int &paragId, int &index )
2297{ 2320{
2298 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2321 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2299 if ( it == selections.end() ) 2322 if ( it == selections.end() )
2300 return; 2323 return;
2301 QTextDocumentSelection &sel = *it; 2324 QTextDocumentSelection &sel = *it;
2302 paragId = sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId(); 2325 paragId = sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId();
2303 index = sel.swapped ? sel.startCursor.index() : sel.endCursor.index(); 2326 index = sel.swapped ? sel.startCursor.index() : sel.endCursor.index();
2304} 2327}
2305 2328
2306void QTextDocument::addSelection( int id ) 2329void QTextDocument::addSelection( int id )
2307{ 2330{
2308 nSelections = QMAX( nSelections, id + 1 ); 2331 nSelections = QMAX( nSelections, id + 1 );
2309} 2332}
2310 2333
2311static void setSelectionEndHelper( int id, QTextDocumentSelection &sel, QTextCursor &start, QTextCursor &end ) 2334static void setSelectionEndHelper( int id, QTextDocumentSelection &sel, QTextCursor &start, QTextCursor &end )
2312{ 2335{
2313 QTextCursor c1 = start; 2336 QTextCursor c1 = start;
2314 QTextCursor c2 = end; 2337 QTextCursor c2 = end;
2315 if ( sel.swapped ) { 2338 if ( sel.swapped ) {
2316 c1 = end; 2339 c1 = end;
2317 c2 = start; 2340 c2 = start;
2318 } 2341 }
2319 2342
2320 c1.paragraph()->removeSelection( id ); 2343 c1.paragraph()->removeSelection( id );
2321 c2.paragraph()->removeSelection( id ); 2344 c2.paragraph()->removeSelection( id );
2322 if ( c1.paragraph() != c2.paragraph() ) { 2345 if ( c1.paragraph() != c2.paragraph() ) {
2323 c1.paragraph()->setSelection( id, c1.index(), c1.paragraph()->length() - 1 ); 2346 c1.paragraph()->setSelection( id, c1.index(), c1.paragraph()->length() - 1 );
2324 c2.paragraph()->setSelection( id, 0, c2.index() ); 2347 c2.paragraph()->setSelection( id, 0, c2.index() );
2325 } else { 2348 } else {
2326 c1.paragraph()->setSelection( id, QMIN( c1.index(), c2.index() ), QMAX( c1.index(), c2.index() ) ); 2349 c1.paragraph()->setSelection( id, QMIN( c1.index(), c2.index() ), QMAX( c1.index(), c2.index() ) );
2327 } 2350 }
2328 2351
2329 sel.startCursor = start; 2352 sel.startCursor = start;
2330 sel.endCursor = end; 2353 sel.endCursor = end;
2331 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() ) 2354 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() )
2332 sel.swapped = sel.startCursor.index() > sel.endCursor.index(); 2355 sel.swapped = sel.startCursor.index() > sel.endCursor.index();
2333} 2356}
2334 2357
2335bool QTextDocument::setSelectionEnd( int id, const QTextCursor &cursor ) 2358bool QTextDocument::setSelectionEnd( int id, const QTextCursor &cursor )
2336{ 2359{
2337 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2360 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2338 if ( it == selections.end() ) 2361 if ( it == selections.end() )
2339 return FALSE; 2362 return FALSE;
2340 QTextDocumentSelection &sel = *it; 2363 QTextDocumentSelection &sel = *it;
2341 2364
2342 QTextCursor start = sel.startCursor; 2365 QTextCursor start = sel.startCursor;
2343 QTextCursor end = cursor; 2366 QTextCursor end = cursor;
2344 2367
2345 if ( start == end ) { 2368 if ( start == end ) {
2346 removeSelection( id ); 2369 removeSelection( id );
2347 setSelectionStart( id, cursor ); 2370 setSelectionStart( id, cursor );
2348 return TRUE; 2371 return TRUE;
2349 } 2372 }
2350 2373
2351 if ( sel.endCursor.paragraph() == end.paragraph() ) { 2374 if ( sel.endCursor.paragraph() == end.paragraph() ) {
2352 setSelectionEndHelper( id, sel, start, end ); 2375 setSelectionEndHelper( id, sel, start, end );
2353 return TRUE; 2376 return TRUE;
2354 } 2377 }
2355 2378
2356 bool inSelection = FALSE; 2379 bool inSelection = FALSE;
2357 QTextCursor c( this ); 2380 QTextCursor c( this );
2358 QTextCursor tmp = sel.startCursor; 2381 QTextCursor tmp = sel.startCursor;
2359 if ( sel.swapped ) 2382 if ( sel.swapped )
2360 tmp = sel.endCursor; 2383 tmp = sel.endCursor;
2361 tmp.restoreState(); 2384 tmp.restoreState();
2362 QTextCursor tmp2 = cursor; 2385 QTextCursor tmp2 = cursor;
2363 tmp2.restoreState(); 2386 tmp2.restoreState();
2364 c.setParagraph( tmp.paragraph()->paragId() < tmp2.paragraph()->paragId() ? tmp.paragraph() : tmp2.paragraph() ); 2387 c.setParagraph( tmp.paragraph()->paragId() < tmp2.paragraph()->paragId() ? tmp.paragraph() : tmp2.paragraph() );
2365 bool hadStart = FALSE; 2388 bool hadStart = FALSE;
2366 bool hadEnd = FALSE; 2389 bool hadEnd = FALSE;
2367 bool hadStartParag = FALSE; 2390 bool hadStartParag = FALSE;
2368 bool hadEndParag = FALSE; 2391 bool hadEndParag = FALSE;
2369 bool hadOldStart = FALSE; 2392 bool hadOldStart = FALSE;
2370 bool hadOldEnd = FALSE; 2393 bool hadOldEnd = FALSE;
2371 bool leftSelection = FALSE; 2394 bool leftSelection = FALSE;
2372 sel.swapped = FALSE; 2395 sel.swapped = FALSE;
2373 for ( ;; ) { 2396 for ( ;; ) {
2374 if ( c == start ) 2397 if ( c == start )
2375 hadStart = TRUE; 2398 hadStart = TRUE;
2376 if ( c == end ) 2399 if ( c == end )
2377 hadEnd = TRUE; 2400 hadEnd = TRUE;
2378 if ( c.paragraph() == start.paragraph() ) 2401 if ( c.paragraph() == start.paragraph() )
2379 hadStartParag = TRUE; 2402 hadStartParag = TRUE;
2380 if ( c.paragraph() == end.paragraph() ) 2403 if ( c.paragraph() == end.paragraph() )
2381 hadEndParag = TRUE; 2404 hadEndParag = TRUE;
2382 if ( c == sel.startCursor ) 2405 if ( c == sel.startCursor )
2383 hadOldStart = TRUE; 2406 hadOldStart = TRUE;
2384 if ( c == sel.endCursor ) 2407 if ( c == sel.endCursor )
2385 hadOldEnd = TRUE; 2408 hadOldEnd = TRUE;
2386 2409
2387 if ( !sel.swapped && 2410 if ( !sel.swapped &&
2388 ( hadEnd && !hadStart || 2411 ( hadEnd && !hadStart ||
2389 hadEnd && hadStart && start.paragraph() == end.paragraph() && start.index() > end.index() ) ) 2412 hadEnd && hadStart && start.paragraph() == end.paragraph() && start.index() > end.index() ) )
2390 sel.swapped = TRUE; 2413 sel.swapped = TRUE;
2391 2414
2392 if ( c == end && hadStartParag || 2415 if ( c == end && hadStartParag ||
2393 c == start && hadEndParag ) { 2416 c == start && hadEndParag ) {
2394 QTextCursor tmp = c; 2417 QTextCursor tmp = c;
2395 tmp.restoreState(); 2418 tmp.restoreState();
2396 if ( tmp.paragraph() != c.paragraph() ) { 2419 if ( tmp.paragraph() != c.paragraph() ) {
2397 int sstart = tmp.paragraph()->selectionStart( id ); 2420 int sstart = tmp.paragraph()->selectionStart( id );
2398 tmp.paragraph()->removeSelection( id ); 2421 tmp.paragraph()->removeSelection( id );
2399 tmp.paragraph()->setSelection( id, sstart, tmp.index() ); 2422 tmp.paragraph()->setSelection( id, sstart, tmp.index() );
2400 } 2423 }
2401 } 2424 }
2402 2425
2403 if ( inSelection && 2426 if ( inSelection &&
2404 ( c == end && hadStart || c == start && hadEnd ) ) 2427 ( c == end && hadStart || c == start && hadEnd ) )
2405 leftSelection = TRUE; 2428 leftSelection = TRUE;
2406 else if ( !leftSelection && !inSelection && ( hadStart || hadEnd ) ) 2429 else if ( !leftSelection && !inSelection && ( hadStart || hadEnd ) )
2407 inSelection = TRUE; 2430 inSelection = TRUE;
2408 2431
2409 bool noSelectionAnymore = hadOldStart && hadOldEnd && leftSelection && !inSelection && !c.paragraph()->hasSelection( id ) && c.atParagEnd(); 2432 bool noSelectionAnymore = hadOldStart && hadOldEnd && leftSelection && !inSelection && !c.paragraph()->hasSelection( id ) && c.atParagEnd();
2410 c.paragraph()->removeSelection( id ); 2433 c.paragraph()->removeSelection( id );
2411 if ( inSelection ) { 2434 if ( inSelection ) {
2412 if ( c.paragraph() == start.paragraph() && start.paragraph() == end.paragraph() ) { 2435 if ( c.paragraph() == start.paragraph() && start.paragraph() == end.paragraph() ) {
2413 c.paragraph()->setSelection( id, QMIN( start.index(), end.index() ), QMAX( start.index(), end.index() ) ); 2436 c.paragraph()->setSelection( id, QMIN( start.index(), end.index() ), QMAX( start.index(), end.index() ) );
2414 } else if ( c.paragraph() == start.paragraph() && !hadEndParag ) { 2437 } else if ( c.paragraph() == start.paragraph() && !hadEndParag ) {
2415 c.paragraph()->setSelection( id, start.index(), c.paragraph()->length() - 1 ); 2438 c.paragraph()->setSelection( id, start.index(), c.paragraph()->length() - 1 );
2416 } else if ( c.paragraph() == end.paragraph() && !hadStartParag ) { 2439 } else if ( c.paragraph() == end.paragraph() && !hadStartParag ) {
2417 c.paragraph()->setSelection( id, end.index(), c.paragraph()->length() - 1 ); 2440 c.paragraph()->setSelection( id, end.index(), c.paragraph()->length() - 1 );
2418 } else if ( c.paragraph() == end.paragraph() && hadEndParag ) { 2441 } else if ( c.paragraph() == end.paragraph() && hadEndParag ) {
2419 c.paragraph()->setSelection( id, 0, end.index() ); 2442 c.paragraph()->setSelection( id, 0, end.index() );
2420 } else if ( c.paragraph() == start.paragraph() && hadStartParag ) { 2443 } else if ( c.paragraph() == start.paragraph() && hadStartParag ) {
2421 c.paragraph()->setSelection( id, 0, start.index() ); 2444 c.paragraph()->setSelection( id, 0, start.index() );
2422 } else { 2445 } else {
2423 c.paragraph()->setSelection( id, 0, c.paragraph()->length() - 1 ); 2446 c.paragraph()->setSelection( id, 0, c.paragraph()->length() - 1 );
2424 } 2447 }
2425 } 2448 }
2426 2449
2427 if ( leftSelection ) 2450 if ( leftSelection )
2428 inSelection = FALSE; 2451 inSelection = FALSE;
2429 2452
2430 if ( noSelectionAnymore ) 2453 if ( noSelectionAnymore )
2431 break; 2454 break;
2432 // *ugle*hack optimization 2455 // *ugle*hack optimization
2433 QTextParagraph *p = c.paragraph(); 2456 QTextParagraph *p = c.paragraph();
2434 if ( p->mightHaveCustomItems || p == start.paragraph() || p == end.paragraph() || p == lastParagraph() ) { 2457 if ( p->mightHaveCustomItems || p == start.paragraph() || p == end.paragraph() || p == lastParagraph() ) {
2435 c.gotoNextLetter(); 2458 c.gotoNextLetter();
2436 if ( p == lastParagraph() && c.atParagEnd() ) 2459 if ( p == lastParagraph() && c.atParagEnd() )
2437 break; 2460 break;
2438 } else { 2461 } else {
2439 if ( p->document()->parent() ) 2462 if ( p->document()->parent() )
2440 do { 2463 do {
2441 c.gotoNextLetter(); 2464 c.gotoNextLetter();
2442 } while ( c.paragraph() == p ); 2465 } while ( c.paragraph() == p );
2443 else 2466 else
2444 c.setParagraph( p->next() ); 2467 c.setParagraph( p->next() );
2445 } 2468 }
2446 } 2469 }
2447 2470
2448 if ( !sel.swapped ) 2471 if ( !sel.swapped )
2449 sel.startCursor.paragraph()->setSelection( id, sel.startCursor.index(), sel.startCursor.paragraph()->length() - 1 ); 2472 sel.startCursor.paragraph()->setSelection( id, sel.startCursor.index(), sel.startCursor.paragraph()->length() - 1 );
2450 2473
2451 sel.startCursor = start; 2474 sel.startCursor = start;
2452 sel.endCursor = end; 2475 sel.endCursor = end;
2453 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() ) 2476 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() )
2454 sel.swapped = sel.startCursor.index() > sel.endCursor.index(); 2477 sel.swapped = sel.startCursor.index() > sel.endCursor.index();
2455 2478
2456 setSelectionEndHelper( id, sel, start, end ); 2479 setSelectionEndHelper( id, sel, start, end );
2457 2480
2458 return TRUE; 2481 return TRUE;
2459} 2482}
2460 2483
2461void QTextDocument::selectAll( int id ) 2484void QTextDocument::selectAll( int id )
2462{ 2485{
2463 removeSelection( id ); 2486 removeSelection( id );
2464 2487
2465 QTextDocumentSelection sel; 2488 QTextDocumentSelection sel;
2466 sel.swapped = FALSE; 2489 sel.swapped = FALSE;
2467 QTextCursor c( this ); 2490 QTextCursor c( this );
2468 2491
2469 c.setParagraph( fParag ); 2492 c.setParagraph( fParag );
2470 c.setIndex( 0 ); 2493 c.setIndex( 0 );
2471 sel.startCursor = c; 2494 sel.startCursor = c;
2472 2495
2473 c.setParagraph( lParag ); 2496 c.setParagraph( lParag );
2474 c.setIndex( lParag->length() - 1 ); 2497 c.setIndex( lParag->length() - 1 );
2475 sel.endCursor = c; 2498 sel.endCursor = c;
2476 2499
2477 selections.insert( id, sel ); 2500 selections.insert( id, sel );
2478 2501
2479 QTextParagraph *p = fParag; 2502 QTextParagraph *p = fParag;
2480 while ( p ) { 2503 while ( p ) {
2481 p->setSelection( id, 0, p->length() - 1 ); 2504 p->setSelection( id, 0, p->length() - 1 );
2482 p = p->next(); 2505 p = p->next();
2483 } 2506 }
2484 2507
2485 for ( QTextDocument *d = childList.first(); d; d = childList.next() ) 2508 for ( QTextDocument *d = childList.first(); d; d = childList.next() )
2486 d->selectAll( id ); 2509 d->selectAll( id );
2487} 2510}
2488 2511
2489bool QTextDocument::removeSelection( int id ) 2512bool QTextDocument::removeSelection( int id )
2490{ 2513{
2491 if ( !selections.contains( id ) ) 2514 if ( !selections.contains( id ) )
2492 return FALSE; 2515 return FALSE;
2493 2516
2494 QTextDocumentSelection &sel = selections[ id ]; 2517 QTextDocumentSelection &sel = selections[ id ];
2495 2518
2496 QTextCursor start = sel.swapped ? sel.endCursor : sel.startCursor; 2519 QTextCursor start = sel.swapped ? sel.endCursor : sel.startCursor;
2497 QTextCursor end = sel.swapped ? sel.startCursor : sel.endCursor; 2520 QTextCursor end = sel.swapped ? sel.startCursor : sel.endCursor;
2498 QTextParagraph* p = 0; 2521 QTextParagraph* p = 0;
2499 while ( start != end ) { 2522 while ( start != end ) {
2500 if ( p != start.paragraph() ) { 2523 if ( p != start.paragraph() ) {
2501 p = start.paragraph(); 2524 p = start.paragraph();
2502 p->removeSelection( id ); 2525 p->removeSelection( id );
2503 } 2526 }
2504 start.gotoNextLetter(); 2527 start.gotoNextLetter();
2505 } 2528 }
2506 selections.remove( id ); 2529 selections.remove( id );
2507 return TRUE; 2530 return TRUE;
2508} 2531}
2509 2532
2510QString QTextDocument::selectedText( int id, bool asRichText ) const 2533QString QTextDocument::selectedText( int id, bool asRichText ) const
2511{ 2534{
2512 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id ); 2535 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id );
2513 if ( it == selections.end() ) 2536 if ( it == selections.end() )
2514 return QString::null; 2537 return QString::null;
2515 2538
2516 QTextDocumentSelection sel = *it; 2539 QTextDocumentSelection sel = *it;
2517 2540
2518 2541
2519 QTextCursor c1 = sel.startCursor; 2542 QTextCursor c1 = sel.startCursor;
2520 QTextCursor c2 = sel.endCursor; 2543 QTextCursor c2 = sel.endCursor;
2521 if ( sel.swapped ) { 2544 if ( sel.swapped ) {
2522 c2 = sel.startCursor; 2545 c2 = sel.startCursor;
2523 c1 = sel.endCursor; 2546 c1 = sel.endCursor;
2524 } 2547 }
2525 2548
2526 /* 3.0.3 improvement: Make it possible to get a reasonable 2549 /* 3.0.3 improvement: Make it possible to get a reasonable
2527 selection inside a table. This approach is very conservative: 2550 selection inside a table. This approach is very conservative:
2528 make sure that both cursors have the same depth level and point 2551 make sure that both cursors have the same depth level and point
2529 to paragraphs within the same text document. 2552 to paragraphs within the same text document.
2530 2553
2531 Meaning if you select text in two table cells, you will get the 2554 Meaning if you select text in two table cells, you will get the
2532 entire table. This is still far better than the 3.0.2, where 2555 entire table. This is still far better than the 3.0.2, where
2533 you always got the entire table. 2556 you always got the entire table.
2534 2557
2535 ### Fix this properly when refactoring 2558 ### Fix this properly when refactoring
2536 */ 2559 */
2537 while ( c2.nestedDepth() > c1.nestedDepth() ) 2560 while ( c2.nestedDepth() > c1.nestedDepth() )
2538 c2.oneUp(); 2561 c2.oneUp();
2539 while ( c1.nestedDepth() > c2.nestedDepth() ) 2562 while ( c1.nestedDepth() > c2.nestedDepth() )
2540 c1.oneUp(); 2563 c1.oneUp();
2541 while ( c1.nestedDepth() && c2.nestedDepth() && 2564 while ( c1.nestedDepth() && c2.nestedDepth() &&
2542 c1.paragraph()->document() != c2.paragraph()->document() ) { 2565 c1.paragraph()->document() != c2.paragraph()->document() ) {
2543 c1.oneUp(); 2566 c1.oneUp();
2544 c2.oneUp(); 2567 c2.oneUp();
2545 } 2568 }
2546 // do not trust sel_swapped with tables. Fix this properly when refactoring as well 2569 // do not trust sel_swapped with tables. Fix this properly when refactoring as well
2547 if ( c1.paragraph()->paragId() > c2.paragraph()->paragId() || 2570 if ( c1.paragraph()->paragId() > c2.paragraph()->paragId() ||
2548 (c1.paragraph() == c2.paragraph() && c1.index() > c2.index() ) ) { 2571 (c1.paragraph() == c2.paragraph() && c1.index() > c2.index() ) ) {
2549 QTextCursor tmp = c1; 2572 QTextCursor tmp = c1;
2550 c2 = c1; 2573 c2 = c1;
2551 c1 = tmp; 2574 c1 = tmp;
2552 } 2575 }
2553 2576
2554 // end selection 3.0.3 improvement 2577 // end selection 3.0.3 improvement
2555 2578
2556 if ( asRichText && !parent() ) { 2579 if ( asRichText && !parent() ) {
2557 richTextExportStart = &c1; 2580 richTextExportStart = &c1;
2558 richTextExportEnd = &c2; 2581 richTextExportEnd = &c2;
2559 2582
2560 QString sel = richText(); 2583 QString sel = richText();
2561 int from = sel.find( "<selstart/>" ); 2584 int from = sel.find( "<selstart/>" );
2562 int to = sel.findRev( "<selend/>" ); 2585 int to = sel.findRev( "<selend/>" );
2563 if ( from >= 0 && from <= to ) 2586 if ( from >= 0 && from <= to )
2564 sel = sel.mid( from, to - from ); 2587 sel = sel.mid( from, to - from );
2565 richTextExportStart = richTextExportEnd = 0; 2588 richTextExportStart = richTextExportEnd = 0;
2566 return sel; 2589 return sel;
2567 } 2590 }
2568 2591
2569 QString s; 2592 QString s;
2570 if ( c1.paragraph() == c2.paragraph() ) { 2593 if ( c1.paragraph() == c2.paragraph() ) {
2571 QTextParagraph *p = c1.paragraph(); 2594 QTextParagraph *p = c1.paragraph();
2572 int end = c2.index(); 2595 int end = c2.index();
2573 if ( p->at( QMAX( 0, end - 1 ) )->isCustom() ) 2596 if ( p->at( QMAX( 0, end - 1 ) )->isCustom() )
2574 ++end; 2597 ++end;
2575 if ( !p->mightHaveCustomItems ) { 2598 if ( !p->mightHaveCustomItems ) {
2576 s += p->string()->toString().mid( c1.index(), end - c1.index() ); 2599 s += p->string()->toString().mid( c1.index(), end - c1.index() );
2577 } else { 2600 } else {
2578 for ( int i = c1.index(); i < end; ++i ) { 2601 for ( int i = c1.index(); i < end; ++i ) {
2579 if ( p->at( i )->isCustom() ) { 2602 if ( p->at( i )->isCustom() ) {
2580 if ( p->at( i )->customItem()->isNested() ) { 2603 if ( p->at( i )->customItem()->isNested() ) {
2581 s += "\n"; 2604 s += "\n";
2582 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 2605 QTextTable *t = (QTextTable*)p->at( i )->customItem();
2583 QPtrList<QTextTableCell> cells = t->tableCells(); 2606 QPtrList<QTextTableCell> cells = t->tableCells();
2584 for ( QTextTableCell *c = cells.first(); c; c = cells.next() ) 2607 for ( QTextTableCell *c = cells.first(); c; c = cells.next() )
2585 s += c->richText()->plainText() + "\n"; 2608 s += c->richText()->plainText() + "\n";
2586 s += "\n"; 2609 s += "\n";
2587 } 2610 }
2588 } else { 2611 } else {
2589 s += p->at( i )->c; 2612 s += p->at( i )->c;
2590 } 2613 }
2591 } 2614 }
2592 } 2615 }
2593 } else { 2616 } else {
2594 QTextParagraph *p = c1.paragraph(); 2617 QTextParagraph *p = c1.paragraph();
2595 int start = c1.index(); 2618 int start = c1.index();
2596 while ( p ) { 2619 while ( p ) {
2597 int end = p == c2.paragraph() ? c2.index() : p->length() - 1; 2620 int end = p == c2.paragraph() ? c2.index() : p->length() - 1;
2598 if ( p == c2.paragraph() && p->at( QMAX( 0, end - 1 ) )->isCustom() ) 2621 if ( p == c2.paragraph() && p->at( QMAX( 0, end - 1 ) )->isCustom() )
2599 ++end; 2622 ++end;
2600 if ( !p->mightHaveCustomItems ) { 2623 if ( !p->mightHaveCustomItems ) {
2601 s += p->string()->toString().mid( start, end - start ); 2624 s += p->string()->toString().mid( start, end - start );
2602 if ( p != c2.paragraph() ) 2625 if ( p != c2.paragraph() )
2603 s += "\n"; 2626 s += "\n";
2604 } else { 2627 } else {
2605 for ( int i = start; i < end; ++i ) { 2628 for ( int i = start; i < end; ++i ) {
2606 if ( p->at( i )->isCustom() ) { 2629 if ( p->at( i )->isCustom() ) {
2607 if ( p->at( i )->customItem()->isNested() ) { 2630 if ( p->at( i )->customItem()->isNested() ) {
2608 s += "\n"; 2631 s += "\n";
2609 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 2632 QTextTable *t = (QTextTable*)p->at( i )->customItem();
2610 QPtrList<QTextTableCell> cells = t->tableCells(); 2633 QPtrList<QTextTableCell> cells = t->tableCells();
2611 for ( QTextTableCell *c = cells.first(); c; c = cells.next() ) 2634 for ( QTextTableCell *c = cells.first(); c; c = cells.next() )
2612 s += c->richText()->plainText() + "\n"; 2635 s += c->richText()->plainText() + "\n";
2613 s += "\n"; 2636 s += "\n";
2614 } 2637 }
2615 } else { 2638 } else {
2616 s += p->at( i )->c; 2639 s += p->at( i )->c;
2617 } 2640 }
2618 } 2641 }
2619 } 2642 }
2620 start = 0; 2643 start = 0;
2621 if ( p == c2.paragraph() ) 2644 if ( p == c2.paragraph() )
2622 break; 2645 break;
2623 p = p->next(); 2646 p = p->next();
2624 } 2647 }
2625 } 2648 }
2626 // ### workaround for plain text export until we get proper 2649 // ### workaround for plain text export until we get proper
2627 // mime types: turn unicode line seperators into the more 2650 // mime types: turn unicode line seperators into the more
2628 // widely understood \n. Makes copy and pasting code snipplets 2651 // widely understood \n. Makes copy and pasting code snipplets
2629 // from within Assistent possible 2652 // from within Assistent possible
2630 QChar* uc = (QChar*) s.unicode(); 2653 QChar* uc = (QChar*) s.unicode();
2631 for ( uint ii = 0; ii < s.length(); ii++ ) 2654 for ( uint ii = 0; ii < s.length(); ii++ )
2632 if ( uc[(int)ii] == QChar_linesep ) 2655 if ( uc[(int)ii] == QChar_linesep )
2633 uc[(int)ii] = QChar('\n'); 2656 uc[(int)ii] = QChar('\n');
2634 return s; 2657 return s;
2635} 2658}
2636 2659
2637void QTextDocument::setFormat( int id, QTextFormat *f, int flags ) 2660void QTextDocument::setFormat( int id, QTextFormat *f, int flags )
2638{ 2661{
2639 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id ); 2662 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id );
2640 if ( it == selections.end() ) 2663 if ( it == selections.end() )
2641 return; 2664 return;
2642 2665
2643 QTextDocumentSelection sel = *it; 2666 QTextDocumentSelection sel = *it;
2644 2667
2645 QTextCursor c1 = sel.startCursor; 2668 QTextCursor c1 = sel.startCursor;
2646 QTextCursor c2 = sel.endCursor; 2669 QTextCursor c2 = sel.endCursor;
2647 if ( sel.swapped ) { 2670 if ( sel.swapped ) {
2648 c2 = sel.startCursor; 2671 c2 = sel.startCursor;
2649 c1 = sel.endCursor; 2672 c1 = sel.endCursor;
2650 } 2673 }
2651 2674
2652 c2.restoreState(); 2675 c2.restoreState();
2653 c1.restoreState(); 2676 c1.restoreState();
2654 2677
2655 if ( c1.paragraph() == c2.paragraph() ) { 2678 if ( c1.paragraph() == c2.paragraph() ) {
2656 c1.paragraph()->setFormat( c1.index(), c2.index() - c1.index(), f, TRUE, flags ); 2679 c1.paragraph()->setFormat( c1.index(), c2.index() - c1.index(), f, TRUE, flags );
2657 return; 2680 return;
2658 } 2681 }
2659 2682
2660 c1.paragraph()->setFormat( c1.index(), c1.paragraph()->length() - c1.index(), f, TRUE, flags ); 2683 c1.paragraph()->setFormat( c1.index(), c1.paragraph()->length() - c1.index(), f, TRUE, flags );
2661 QTextParagraph *p = c1.paragraph()->next(); 2684 QTextParagraph *p = c1.paragraph()->next();
2662 while ( p && p != c2.paragraph() ) { 2685 while ( p && p != c2.paragraph() ) {
2663 p->setFormat( 0, p->length(), f, TRUE, flags ); 2686 p->setFormat( 0, p->length(), f, TRUE, flags );
2664 p = p->next(); 2687 p = p->next();
2665 } 2688 }
2666 c2.paragraph()->setFormat( 0, c2.index(), f, TRUE, flags ); 2689 c2.paragraph()->setFormat( 0, c2.index(), f, TRUE, flags );
2667} 2690}
2668 2691
2669void QTextDocument::removeSelectedText( int id, QTextCursor *cursor ) 2692void QTextDocument::removeSelectedText( int id, QTextCursor *cursor )
2670{ 2693{
2671 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2694 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2672 if ( it == selections.end() ) 2695 if ( it == selections.end() )
2673 return; 2696 return;
2674 2697
2675 QTextDocumentSelection sel = *it; 2698 QTextDocumentSelection sel = *it;
2676 2699
2677 QTextCursor c1 = sel.startCursor; 2700 QTextCursor c1 = sel.startCursor;
2678 QTextCursor c2 = sel.endCursor; 2701 QTextCursor c2 = sel.endCursor;
2679 if ( sel.swapped ) { 2702 if ( sel.swapped ) {
2680 c2 = sel.startCursor; 2703 c2 = sel.startCursor;
2681 c1 = sel.endCursor; 2704 c1 = sel.endCursor;
2682 } 2705 }
2683 2706
2684 // ### no support for editing tables yet 2707 // ### no support for editing tables yet
2685 if ( c1.nestedDepth() || c2.nestedDepth() ) 2708 if ( c1.nestedDepth() || c2.nestedDepth() )
2686 return; 2709 return;
2687 2710
2688 c2.restoreState(); 2711 c2.restoreState();
2689 c1.restoreState(); 2712 c1.restoreState();
2690 2713
2691 *cursor = c1; 2714 *cursor = c1;
2692 removeSelection( id ); 2715 removeSelection( id );
2693 2716
2694 if ( c1.paragraph() == c2.paragraph() ) { 2717 if ( c1.paragraph() == c2.paragraph() ) {
2695 c1.paragraph()->remove( c1.index(), c2.index() - c1.index() ); 2718 c1.paragraph()->remove( c1.index(), c2.index() - c1.index() );
2696 return; 2719 return;
2697 } 2720 }
2698 2721
2699 if ( c1.paragraph() == fParag && c1.index() == 0 && 2722 if ( c1.paragraph() == fParag && c1.index() == 0 &&
2700 c2.paragraph() == lParag && c2.index() == lParag->length() - 1 ) 2723 c2.paragraph() == lParag && c2.index() == lParag->length() - 1 )
2701 cursor->setValid( FALSE ); 2724 cursor->setValid( FALSE );
2702 2725
2703 bool didGoLeft = FALSE; 2726 bool didGoLeft = FALSE;
2704 if ( c1.index() == 0 && c1.paragraph() != fParag ) { 2727 if ( c1.index() == 0 && c1.paragraph() != fParag ) {
2705 cursor->gotoPreviousLetter(); 2728 cursor->gotoPreviousLetter();
2706 if ( cursor->isValid() ) 2729 if ( cursor->isValid() )
2707 didGoLeft = TRUE; 2730 didGoLeft = TRUE;
2708 } 2731 }
2709 2732
2710 c1.paragraph()->remove( c1.index(), c1.paragraph()->length() - 1 - c1.index() ); 2733 c1.paragraph()->remove( c1.index(), c1.paragraph()->length() - 1 - c1.index() );
2711 QTextParagraph *p = c1.paragraph()->next(); 2734 QTextParagraph *p = c1.paragraph()->next();
2712 int dy = 0; 2735 int dy = 0;
2713 QTextParagraph *tmp; 2736 QTextParagraph *tmp;
2714 while ( p && p != c2.paragraph() ) { 2737 while ( p && p != c2.paragraph() ) {
2715 tmp = p->next(); 2738 tmp = p->next();
2716 dy -= p->rect().height(); 2739 dy -= p->rect().height();
2717 delete p; 2740 delete p;
2718 p = tmp; 2741 p = tmp;
2719 } 2742 }
2720 c2.paragraph()->remove( 0, c2.index() ); 2743 c2.paragraph()->remove( 0, c2.index() );
2721 while ( p ) { 2744 while ( p ) {
2722 p->move( dy ); 2745 p->move( dy );
2723 p->invalidate( 0 ); 2746 p->invalidate( 0 );
2724 p->setEndState( -1 ); 2747 p->setEndState( -1 );
2725 p = p->next(); 2748 p = p->next();
2726 } 2749 }
2727 2750
2728 c1.paragraph()->join( c2.paragraph() ); 2751 c1.paragraph()->join( c2.paragraph() );
2729 2752
2730 if ( didGoLeft ) 2753 if ( didGoLeft )
2731 cursor->gotoNextLetter(); 2754 cursor->gotoNextLetter();
2732} 2755}
2733 2756
2734void QTextDocument::indentSelection( int id ) 2757void QTextDocument::indentSelection( int id )
2735{ 2758{
2736 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2759 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2737 if ( it == selections.end() ) 2760 if ( it == selections.end() )
2738 return; 2761 return;
2739 2762
2740 QTextDocumentSelection sel = *it; 2763 QTextDocumentSelection sel = *it;
2741 QTextParagraph *startParag = sel.startCursor.paragraph(); 2764 QTextParagraph *startParag = sel.startCursor.paragraph();
2742 QTextParagraph *endParag = sel.endCursor.paragraph(); 2765 QTextParagraph *endParag = sel.endCursor.paragraph();
2743 if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) { 2766 if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) {
2744 endParag = sel.startCursor.paragraph(); 2767 endParag = sel.startCursor.paragraph();
2745 startParag = sel.endCursor.paragraph(); 2768 startParag = sel.endCursor.paragraph();
2746 } 2769 }
2747 2770
2748 QTextParagraph *p = startParag; 2771 QTextParagraph *p = startParag;
2749 while ( p && p != endParag ) { 2772 while ( p && p != endParag ) {
2750 p->indent(); 2773 p->indent();
2751 p = p->next(); 2774 p = p->next();
2752 } 2775 }
2753} 2776}
2754 2777
2755void QTextDocument::addCommand( QTextCommand *cmd ) 2778void QTextDocument::addCommand( QTextCommand *cmd )
2756{ 2779{
2757 commandHistory->addCommand( cmd ); 2780 commandHistory->addCommand( cmd );
2758} 2781}
2759 2782
2760QTextCursor *QTextDocument::undo( QTextCursor *c ) 2783QTextCursor *QTextDocument::undo( QTextCursor *c )
2761{ 2784{
2762 return commandHistory->undo( c ); 2785 return commandHistory->undo( c );
2763} 2786}
2764 2787
2765QTextCursor *QTextDocument::redo( QTextCursor *c ) 2788QTextCursor *QTextDocument::redo( QTextCursor *c )
2766{ 2789{
2767 return commandHistory->redo( c ); 2790 return commandHistory->redo( c );
2768} 2791}
2769 2792
2770bool QTextDocument::find( QTextCursor& cursor, const QString &e, bool cs, bool wo, bool forward ) 2793bool QTextDocument::find( QTextCursor& cursor, const QString &e, bool cs, bool wo, bool forward )
2771{ 2794{
2772 removeSelection( Standard ); 2795 removeSelection( Standard );
2773 QTextParagraph *p = 0; 2796 QTextParagraph *p = 0;
2774 QString expr = e; 2797 QString expr = e;
2775 // if we search for 'word only' than we have to be sure that 2798 // if we search for 'word only' than we have to be sure that
2776 // the expression contains no space or punct character at the 2799 // the expression contains no space or punct character at the
2777 // beginning or in the end. Otherwise we would run into a 2800 // beginning or in the end. Otherwise we would run into a
2778 // endlessloop. 2801 // endlessloop.
2779 if ( wo ) { 2802 if ( wo ) {
2780 for ( ;; ) { 2803 for ( ;; ) {
2781 if ( expr[ 0 ].isSpace() || expr[ 0 ].isPunct() ) 2804 if ( expr[ 0 ].isSpace() || expr[ 0 ].isPunct() )
2782 expr = expr.right( expr.length() - 1 ); 2805 expr = expr.right( expr.length() - 1 );
2783 else 2806 else
2784 break; 2807 break;
2785 } 2808 }
2786 for ( ;; ) { 2809 for ( ;; ) {
2787 if ( expr.at( expr.length() - 1 ).isSpace() || expr.at( expr.length() - 1 ).isPunct() ) 2810 if ( expr.at( expr.length() - 1 ).isSpace() || expr.at( expr.length() - 1 ).isPunct() )
2788 expr = expr.left( expr.length() - 1 ); 2811 expr = expr.left( expr.length() - 1 );
2789 else 2812 else
2790 break; 2813 break;
2791 } 2814 }
2792 } 2815 }
2793 for (;;) { 2816 for (;;) {
2794 if ( p != cursor.paragraph() ) { 2817 if ( p != cursor.paragraph() ) {
2795 p = cursor.paragraph(); 2818 p = cursor.paragraph();
2796 QString s = cursor.paragraph()->string()->toString(); 2819 QString s = cursor.paragraph()->string()->toString();
2797 int start = cursor.index(); 2820 int start = cursor.index();
2798 for ( ;; ) { 2821 for ( ;; ) {
2799 int res = forward ? s.find( expr, start, cs ) : s.findRev( expr, start, cs ); 2822 int res = forward ? s.find( expr, start, cs ) : s.findRev( expr, start, cs );
2800 int end = res + expr.length(); 2823 int end = res + expr.length();
2801 if ( res == -1 || ( !forward && start < end ) ) 2824 if ( res == -1 || ( !forward && start < end ) )
2802 break; 2825 break;
2803 if ( !wo || ( ( res == 0 || s[ res - 1 ].isSpace() || s[ res - 1 ].isPunct() ) && 2826 if ( !wo || ( ( res == 0 || s[ res - 1 ].isSpace() || s[ res - 1 ].isPunct() ) &&
2804 ( end == (int)s.length() || s[ end ].isSpace() || s[ end ].isPunct() ) ) ) { 2827 ( end == (int)s.length() || s[ end ].isSpace() || s[ end ].isPunct() ) ) ) {
2805 removeSelection( Standard ); 2828 removeSelection( Standard );
2806 cursor.setIndex( forward ? end : res ); 2829 cursor.setIndex( forward ? end : res );
2807 setSelectionStart( Standard, cursor ); 2830 setSelectionStart( Standard, cursor );
2808 cursor.setIndex( forward ? res : end ); 2831 cursor.setIndex( forward ? res : end );
2809 setSelectionEnd( Standard, cursor ); 2832 setSelectionEnd( Standard, cursor );
2810 return TRUE; 2833 return TRUE;
2811 } 2834 }
2812 start = res + (forward ? 1 : -1); 2835 start = res + (forward ? 1 : -1);
2813 } 2836 }
2814 } 2837 }
2815 if ( forward ) { 2838 if ( forward ) {
2816 if ( cursor.paragraph() == lastParagraph() && cursor.atParagEnd () ) 2839 if ( cursor.paragraph() == lastParagraph() && cursor.atParagEnd () )
2817 break; 2840 break;
2818 cursor.gotoNextLetter(); 2841 cursor.gotoNextLetter();
2819 } else { 2842 } else {
2820 if ( cursor.paragraph() == firstParagraph() && cursor.atParagStart() ) 2843 if ( cursor.paragraph() == firstParagraph() && cursor.atParagStart() )
2821 break; 2844 break;
2822 cursor.gotoPreviousLetter(); 2845 cursor.gotoPreviousLetter();
2823 } 2846 }
2824 } 2847 }
2825 return FALSE; 2848 return FALSE;
2826} 2849}
2827 2850
2828void QTextDocument::setTextFormat( Qt::TextFormat f ) 2851void QTextDocument::setTextFormat( Qt::TextFormat f )
2829{ 2852{
2830 txtFormat = f; 2853 txtFormat = f;
2831 if ( fParag == lParag && fParag->length() <= 1 ) 2854 if ( fParag == lParag && fParag->length() <= 1 )
2832 fParag->rtext = ( f == Qt::RichText ); 2855 fParag->rtext = ( f == Qt::RichText );
2833} 2856}
2834 2857
2835Qt::TextFormat QTextDocument::textFormat() const 2858Qt::TextFormat QTextDocument::textFormat() const
2836{ 2859{
2837 return txtFormat; 2860 return txtFormat;
2838} 2861}
2839 2862
2840bool QTextDocument::inSelection( int selId, const QPoint &pos ) const 2863bool QTextDocument::inSelection( int selId, const QPoint &pos ) const
2841{ 2864{
2842 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( selId ); 2865 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( selId );
2843 if ( it == selections.end() ) 2866 if ( it == selections.end() )
2844 return FALSE; 2867 return FALSE;
2845 2868
2846 QTextDocumentSelection sel = *it; 2869 QTextDocumentSelection sel = *it;
2847 QTextParagraph *startParag = sel.startCursor.paragraph(); 2870 QTextParagraph *startParag = sel.startCursor.paragraph();
2848 QTextParagraph *endParag = sel.endCursor.paragraph(); 2871 QTextParagraph *endParag = sel.endCursor.paragraph();
2849 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() && 2872 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() &&
2850 sel.startCursor.paragraph()->selectionStart( selId ) == sel.endCursor.paragraph()->selectionEnd( selId ) ) 2873 sel.startCursor.paragraph()->selectionStart( selId ) == sel.endCursor.paragraph()->selectionEnd( selId ) )
2851 return FALSE; 2874 return FALSE;
2852 if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) { 2875 if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) {
2853 endParag = sel.startCursor.paragraph(); 2876 endParag = sel.startCursor.paragraph();
2854 startParag = sel.endCursor.paragraph(); 2877 startParag = sel.endCursor.paragraph();
2855 } 2878 }
2856 2879
2857 QTextParagraph *p = startParag; 2880 QTextParagraph *p = startParag;
2858 while ( p ) { 2881 while ( p ) {
2859 if ( p->rect().contains( pos ) ) { 2882 if ( p->rect().contains( pos ) ) {
2860 bool inSel = FALSE; 2883 bool inSel = FALSE;
2861 int selStart = p->selectionStart( selId ); 2884 int selStart = p->selectionStart( selId );
2862 int selEnd = p->selectionEnd( selId ); 2885 int selEnd = p->selectionEnd( selId );
2863 int y = 0; 2886 int y = 0;
2864 int h = 0; 2887 int h = 0;
2865 for ( int i = 0; i < p->length(); ++i ) { 2888 for ( int i = 0; i < p->length(); ++i ) {
2866 if ( i == selStart ) 2889 if ( i == selStart )
2867 inSel = TRUE; 2890 inSel = TRUE;
2868 if ( i == selEnd ) 2891 if ( i == selEnd )
2869 break; 2892 break;
2870 if ( p->at( i )->lineStart ) { 2893 if ( p->at( i )->lineStart ) {
2871 y = (*p->lineStarts.find( i ))->y; 2894 y = (*p->lineStarts.find( i ))->y;
2872 h = (*p->lineStarts.find( i ))->h; 2895 h = (*p->lineStarts.find( i ))->h;
2873 } 2896 }
2874 if ( pos.y() - p->rect().y() >= y && pos.y() - p->rect().y() <= y + h ) { 2897 if ( pos.y() - p->rect().y() >= y && pos.y() - p->rect().y() <= y + h ) {
2875 if ( inSel && pos.x() >= p->at( i )->x && 2898 if ( inSel && pos.x() >= p->at( i )->x &&
2876 pos.x() <= p->at( i )->x + p->at( i )->format()->width( p->at( i )->c ) ) 2899 pos.x() <= p->at( i )->x + p->at( i )->format()->width( p->at( i )->c ) )
2877 return TRUE; 2900 return TRUE;
2878 } 2901 }
2879 } 2902 }
2880 } 2903 }
2881 if ( pos.y() < p->rect().y() ) 2904 if ( pos.y() < p->rect().y() )
2882 break; 2905 break;
2883 if ( p == endParag ) 2906 if ( p == endParag )
2884 break; 2907 break;
2885 p = p->next(); 2908 p = p->next();
2886 } 2909 }
2887 2910
2888 return FALSE; 2911 return FALSE;
2889} 2912}
2890 2913
2891void QTextDocument::doLayout( QPainter *p, int w ) 2914void QTextDocument::doLayout( QPainter *p, int w )
2892{ 2915{
2893 minw = wused = 0; 2916 minw = wused = 0;
2894 if ( !is_printer( p ) ) 2917 if ( !is_printer( p ) )
2895 p = 0; 2918 p = 0;
2896 withoutDoubleBuffer = ( p != 0 ); 2919 withoutDoubleBuffer = ( p != 0 );
2897 QPainter * oldPainter = QTextFormat::painter(); 2920 QPainter * oldPainter = QTextFormat::painter();
2898 QTextFormat::setPainter( p ); 2921 QTextFormat::setPainter( p );
2899 flow_->setWidth( w ); 2922 flow_->setWidth( w );
2900 cw = w; 2923 cw = w;
2901 vw = w; 2924 vw = w;
2902 QTextParagraph *parag = fParag; 2925 QTextParagraph *parag = fParag;
2903 while ( parag ) { 2926 while ( parag ) {
2904 parag->invalidate( 0 ); 2927 parag->invalidate( 0 );
2905 if ( p ) 2928 if ( p )
2906 parag->adjustToPainter( p ); 2929 parag->adjustToPainter( p );
2907 parag->format(); 2930 parag->format();
2908 parag = parag->next(); 2931 parag = parag->next();
2909 } 2932 }
2910 QTextFormat::setPainter( oldPainter ); 2933 QTextFormat::setPainter( oldPainter );
2911} 2934}
2912 2935
2913QPixmap *QTextDocument::bufferPixmap( const QSize &s ) 2936QPixmap *QTextDocument::bufferPixmap( const QSize &s )
2914{ 2937{
2915 if ( !buf_pixmap ) 2938 if ( !buf_pixmap )
2916 buf_pixmap = new QPixmap( s.expandedTo( QSize(1,1) ) ); 2939 buf_pixmap = new QPixmap( s.expandedTo( QSize(1,1) ) );
2917 else if ( buf_pixmap->size() != s ) 2940 else if ( buf_pixmap->size() != s )
2918 buf_pixmap->resize( s.expandedTo( buf_pixmap->size() ) ); 2941 buf_pixmap->resize( s.expandedTo( buf_pixmap->size() ) );
2919 return buf_pixmap; 2942 return buf_pixmap;
2920} 2943}
2921 2944
2922void QTextDocument::draw( QPainter *p, const QRect &rect, const QColorGroup &cg, const QBrush *paper ) 2945void QTextDocument::draw( QPainter *p, const QRect &rect, const QColorGroup &cg, const QBrush *paper )
2923{ 2946{
2924 if ( !firstParagraph() ) 2947 if ( !firstParagraph() )
2925 return; 2948 return;
2926 2949
2927 if ( paper ) { 2950 if ( paper ) {
2928 p->setBrushOrigin( 0, 0 ); 2951 p->setBrushOrigin( 0, 0 );
2929 2952
2930 p->fillRect( rect, *paper ); 2953 p->fillRect( rect, *paper );
2931 } 2954 }
2932 2955
2933 if ( formatCollection()->defaultFormat()->color() != cg.text() ) 2956 if ( formatCollection()->defaultFormat()->color() != cg.text() )
2934 setDefaultFormat( formatCollection()->defaultFormat()->font(), cg.text() ); 2957 setDefaultFormat( formatCollection()->defaultFormat()->font(), cg.text() );
2935 2958
2936 QTextParagraph *parag = firstParagraph(); 2959 QTextParagraph *parag = firstParagraph();
2937 while ( parag ) { 2960 while ( parag ) {
2938 if ( !parag->isValid() ) 2961 if ( !parag->isValid() )
2939 parag->format(); 2962 parag->format();
2940 int y = parag->rect().y(); 2963 int y = parag->rect().y();
2941 QRect pr( parag->rect() ); 2964 QRect pr( parag->rect() );
2942 pr.setX( 0 ); 2965 pr.setX( 0 );
2943 pr.setWidth( QWIDGETSIZE_MAX ); 2966 pr.setWidth( QWIDGETSIZE_MAX );
2944 if ( !rect.isNull() && !rect.intersects( pr ) ) { 2967 if ( !rect.isNull() && !rect.intersects( pr ) ) {
2945 parag = parag->next(); 2968 parag = parag->next();
2946 continue; 2969 continue;
2947 } 2970 }
2948 p->translate( 0, y ); 2971 p->translate( 0, y );
2949 if ( rect.isValid() ) 2972 if ( rect.isValid() )
2950 parag->paint( *p, cg, 0, FALSE, rect.x(), rect.y(), rect.width(), rect.height() ); 2973 parag->paint( *p, cg, 0, FALSE, rect.x(), rect.y(), rect.width(), rect.height() );
2951 else 2974 else
2952 parag->paint( *p, cg, 0, FALSE ); 2975 parag->paint( *p, cg, 0, FALSE );
2953 p->translate( 0, -y ); 2976 p->translate( 0, -y );
2954 parag = parag->next(); 2977 parag = parag->next();
2955 if ( !flow()->isEmpty() ) 2978 if ( !flow()->isEmpty() )
2956 flow()->drawFloatingItems( p, rect.x(), rect.y(), rect.width(), rect.height(), cg, FALSE ); 2979 flow()->drawFloatingItems( p, rect.x(), rect.y(), rect.width(), rect.height(), cg, FALSE );
2957 } 2980 }
2958} 2981}
2959 2982
2960void QTextDocument::drawParagraph( QPainter *p, QTextParagraph *parag, int cx, int cy, int cw, int ch, 2983void QTextDocument::drawParagraph( QPainter *p, QTextParagraph *parag, int cx, int cy, int cw, int ch,
2961 QPixmap *&doubleBuffer, const QColorGroup &cg, 2984 QPixmap *&doubleBuffer, const QColorGroup &cg,
2962 bool drawCursor, QTextCursor *cursor, bool resetChanged ) 2985 bool drawCursor, QTextCursor *cursor, bool resetChanged )
2963{ 2986{
2964 QPainter *painter = 0; 2987 QPainter *painter = 0;
2965 if ( resetChanged ) 2988 if ( resetChanged )
2966 parag->setChanged( FALSE ); 2989 parag->setChanged( FALSE );
2967 QRect ir( parag->rect() ); 2990 QRect ir( parag->rect() );
2968 bool useDoubleBuffer = !parag->document()->parent(); 2991 bool useDoubleBuffer = !parag->document()->parent();
2969 if ( !useDoubleBuffer && parag->document()->nextDoubleBuffered ) 2992 if ( !useDoubleBuffer && parag->document()->nextDoubleBuffered )
2970 useDoubleBuffer = TRUE; 2993 useDoubleBuffer = TRUE;
2971 if ( is_printer( p ) ) 2994 if ( is_printer( p ) )
2972 useDoubleBuffer = FALSE; 2995 useDoubleBuffer = FALSE;
2973 2996
2974 if ( useDoubleBuffer ) { 2997 if ( useDoubleBuffer ) {
2975 painter = new QPainter; 2998 painter = new QPainter;
2976 if ( cx >= 0 && cy >= 0 ) 2999 if ( cx >= 0 && cy >= 0 )
2977 ir = ir.intersect( QRect( cx, cy, cw, ch ) ); 3000 ir = ir.intersect( QRect( cx, cy, cw, ch ) );
2978 if ( !doubleBuffer || 3001 if ( !doubleBuffer ||
2979 ir.width() > doubleBuffer->width() || 3002 ir.width() > doubleBuffer->width() ||
2980 ir.height() > doubleBuffer->height() ) { 3003 ir.height() > doubleBuffer->height() ) {
2981 doubleBuffer = bufferPixmap( ir.size() ); 3004 doubleBuffer = bufferPixmap( ir.size() );
2982 painter->begin( doubleBuffer ); 3005 painter->begin( doubleBuffer );
2983 } else { 3006 } else {
2984 painter->begin( doubleBuffer ); 3007 painter->begin( doubleBuffer );
2985 } 3008 }
2986 } else { 3009 } else {
2987 painter = p; 3010 painter = p;
2988 painter->translate( ir.x(), ir.y() ); 3011 painter->translate( ir.x(), ir.y() );
2989 } 3012 }
2990 3013
2991 painter->setBrushOrigin( -ir.x(), -ir.y() ); 3014 painter->setBrushOrigin( -ir.x(), -ir.y() );
2992 3015
2993 if ( useDoubleBuffer || is_printer( painter ) ) 3016 if ( useDoubleBuffer || is_printer( painter ) )
2994 painter->fillRect( QRect( 0, 0, ir.width(), ir.height() ), parag->backgroundBrush( cg ) ); 3017 painter->fillRect( QRect( 0, 0, ir.width(), ir.height() ), parag->backgroundBrush( cg ) );
2995 else if ( cursor && cursor->paragraph() == parag ) 3018 else if ( cursor && cursor->paragraph() == parag )
2996 painter->fillRect( QRect( parag->at( cursor->index() )->x, 0, 2, ir.height() ), 3019 painter->fillRect( QRect( parag->at( cursor->index() )->x, 0, 2, ir.height() ),
2997 parag->backgroundBrush( cg ) ); 3020 parag->backgroundBrush( cg ) );
2998 3021
2999 painter->translate( -( ir.x() - parag->rect().x() ), 3022 painter->translate( -( ir.x() - parag->rect().x() ),
3000 -( ir.y() - parag->rect().y() ) ); 3023 -( ir.y() - parag->rect().y() ) );
3001 parag->paint( *painter, cg, drawCursor ? cursor : 0, TRUE, cx, cy, cw, ch ); 3024 parag->paint( *painter, cg, drawCursor ? cursor : 0, TRUE, cx, cy, cw, ch );
3002 3025
3003 if ( useDoubleBuffer ) { 3026 if ( useDoubleBuffer ) {
3004 delete painter; 3027 delete painter;
3005 painter = 0; 3028 painter = 0;
3006 p->drawPixmap( ir.topLeft(), *doubleBuffer, QRect( QPoint( 0, 0 ), ir.size() ) ); 3029 p->drawPixmap( ir.topLeft(), *doubleBuffer, QRect( QPoint( 0, 0 ), ir.size() ) );
3007 } else { 3030 } else {
3008 painter->translate( -ir.x(), -ir.y() ); 3031 painter->translate( -ir.x(), -ir.y() );
3009 } 3032 }
3010 3033
3011 if ( useDoubleBuffer ) { 3034 if ( useDoubleBuffer ) {
3012 if ( parag->rect().x() + parag->rect().width() < parag->document()->x() + parag->document()->width() ) { 3035 if ( parag->rect().x() + parag->rect().width() < parag->document()->x() + parag->document()->width() ) {
3013 p->fillRect( parag->rect().x() + parag->rect().width(), parag->rect().y(), 3036 p->fillRect( parag->rect().x() + parag->rect().width(), parag->rect().y(),
3014 ( parag->document()->x() + parag->document()->width() ) - 3037 ( parag->document()->x() + parag->document()->width() ) -
3015 ( parag->rect().x() + parag->rect().width() ), 3038 ( parag->rect().x() + parag->rect().width() ),
3016 parag->rect().height(), cg.brush( QColorGroup::Base ) ); 3039 parag->rect().height(), cg.brush( QColorGroup::Base ) );
3017 } 3040 }
3018 } 3041 }
3019 3042
3020 parag->document()->nextDoubleBuffered = FALSE; 3043 parag->document()->nextDoubleBuffered = FALSE;
3021} 3044}
3022 3045
3023QTextParagraph *QTextDocument::draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg, 3046QTextParagraph *QTextDocument::draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg,
3024 bool onlyChanged, bool drawCursor, QTextCursor *cursor, bool resetChanged ) 3047 bool onlyChanged, bool drawCursor, QTextCursor *cursor, bool resetChanged )
3025{ 3048{
3026 if ( withoutDoubleBuffer || par && par->withoutDoubleBuffer ) { 3049 if ( withoutDoubleBuffer || par && par->withoutDoubleBuffer ) {
3027 withoutDoubleBuffer = TRUE; 3050 withoutDoubleBuffer = TRUE;
3028 QRect r; 3051 QRect r;
3029 draw( p, r, cg ); 3052 draw( p, r, cg );
3030 return 0; 3053 return 0;
3031 } 3054 }
3032 withoutDoubleBuffer = FALSE; 3055 withoutDoubleBuffer = FALSE;
3033 3056
3034 if ( !firstParagraph() ) 3057 if ( !firstParagraph() )
3035 return 0; 3058 return 0;
3036 3059
3037 if ( cx < 0 && cy < 0 ) { 3060 if ( cx < 0 && cy < 0 ) {
3038 cx = 0; 3061 cx = 0;
3039 cy = 0; 3062 cy = 0;
3040 cw = width(); 3063 cw = width();
3041 ch = height(); 3064 ch = height();
3042 } 3065 }
3043 3066
3044 QTextParagraph *lastFormatted = 0; 3067 QTextParagraph *lastFormatted = 0;
3045 QTextParagraph *parag = firstParagraph(); 3068 QTextParagraph *parag = firstParagraph();
3046 3069
3047 QPixmap *doubleBuffer = 0; 3070 QPixmap *doubleBuffer = 0;
3048 QPainter painter; 3071 QPainter painter;
3049 3072
3050 bool fullWidthSelection = FALSE; 3073 bool fullWidthSelection = FALSE;
3051 while ( parag ) { 3074 while ( parag ) {
3052 lastFormatted = parag; 3075 lastFormatted = parag;
3053 if ( !parag->isValid() ) 3076 if ( !parag->isValid() )
3054 parag->format(); 3077 parag->format();
3055 3078
3056 QRect pr = parag->rect(); 3079 QRect pr = parag->rect();
3057 if ( fullWidthSelection ) 3080 if ( fullWidthSelection )
3058 pr.setWidth( parag->document()->width() ); 3081 pr.setWidth( parag->document()->width() );
3059 if ( pr.y() > cy + ch ) 3082 if ( pr.y() > cy + ch )
3060 goto floating; 3083 goto floating;
3061 if ( !pr.intersects( QRect( cx, cy, cw, ch ) ) || ( onlyChanged && !parag->hasChanged() ) ) { 3084 if ( !pr.intersects( QRect( cx, cy, cw, ch ) ) || ( onlyChanged && !parag->hasChanged() ) ) {
3062 parag = parag->next(); 3085 parag = parag->next();
3063 continue; 3086 continue;
3064 } 3087 }
3065 3088
3066 drawParagraph( p, parag, cx, cy, cw, ch, doubleBuffer, cg, drawCursor, cursor, resetChanged ); 3089 drawParagraph( p, parag, cx, cy, cw, ch, doubleBuffer, cg, drawCursor, cursor, resetChanged );
3067 parag = parag->next(); 3090 parag = parag->next();
3068 } 3091 }
3069 3092
3070 parag = lastParagraph(); 3093 parag = lastParagraph();
3071 3094
3072 floating: 3095 floating:
3073 if ( parag->rect().y() + parag->rect().height() < parag->document()->height() ) { 3096 if ( parag->rect().y() + parag->rect().height() < parag->document()->height() ) {
3074 if ( !parag->document()->parent() ) { 3097 if ( !parag->document()->parent() ) {
3075 p->fillRect( 0, parag->rect().y() + parag->rect().height(), parag->document()->width(), 3098 p->fillRect( 0, parag->rect().y() + parag->rect().height(), parag->document()->width(),
3076 parag->document()->height() - ( parag->rect().y() + parag->rect().height() ), 3099 parag->document()->height() - ( parag->rect().y() + parag->rect().height() ),
3077 cg.brush( QColorGroup::Base ) ); 3100 cg.brush( QColorGroup::Base ) );
3078 } 3101 }
3079 if ( !flow()->isEmpty() ) { 3102 if ( !flow()->isEmpty() ) {
3080 QRect cr( cx, cy, cw, ch ); 3103 QRect cr( cx, cy, cw, ch );
3081 flow()->drawFloatingItems( p, cr.x(), cr.y(), cr.width(), cr.height(), cg, FALSE ); 3104 flow()->drawFloatingItems( p, cr.x(), cr.y(), cr.width(), cr.height(), cg, FALSE );
3082 } 3105 }
3083 } 3106 }
3084 3107
3085 if ( buf_pixmap && buf_pixmap->height() > 300 ) { 3108 if ( buf_pixmap && buf_pixmap->height() > 300 ) {
3086 delete buf_pixmap; 3109 delete buf_pixmap;
3087 buf_pixmap = 0; 3110 buf_pixmap = 0;
3088 } 3111 }
3089 3112
3090 return lastFormatted; 3113 return lastFormatted;
3091} 3114}
3092 3115
3093/* 3116/*
3094 #### this function only sets the default font size in the format collection 3117 #### this function only sets the default font size in the format collection
3095 */ 3118 */
3096void QTextDocument::setDefaultFormat( const QFont &font, const QColor &color ) 3119void QTextDocument::setDefaultFormat( const QFont &font, const QColor &color )
3097{ 3120{
3098 bool reformat = font != fCollection->defaultFormat()->font(); 3121 bool reformat = font != fCollection->defaultFormat()->font();
3099 for ( QTextDocument *d = childList.first(); d; d = childList.next() ) 3122 for ( QTextDocument *d = childList.first(); d; d = childList.next() )
3100 d->setDefaultFormat( font, color ); 3123 d->setDefaultFormat( font, color );
3101 fCollection->updateDefaultFormat( font, color, sheet_ ); 3124 fCollection->updateDefaultFormat( font, color, sheet_ );
3102 3125
3103 if ( !reformat ) 3126 if ( !reformat )
3104 return; 3127 return;
3105 tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8; 3128 tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8;
3106 3129
3107 // invalidate paragraphs and custom items 3130 // invalidate paragraphs and custom items
3108 QTextParagraph *p = fParag; 3131 QTextParagraph *p = fParag;
3109 while ( p ) { 3132 while ( p ) {
3110 p->invalidate( 0 ); 3133 p->invalidate( 0 );
3111 for ( int i = 0; i < p->length() - 1; ++i ) 3134 for ( int i = 0; i < p->length() - 1; ++i )
3112 if ( p->at( i )->isCustom() ) 3135 if ( p->at( i )->isCustom() )
3113 p->at( i )->customItem()->invalidate(); 3136 p->at( i )->customItem()->invalidate();
3114 p = p->next(); 3137 p = p->next();
3115 } 3138 }
3116} 3139}
3117 3140
3118void QTextDocument::registerCustomItem( QTextCustomItem *i, QTextParagraph *p ) 3141void QTextDocument::registerCustomItem( QTextCustomItem *i, QTextParagraph *p )
3119{ 3142{
3120 if ( i && i->placement() != QTextCustomItem::PlaceInline ) { 3143 if ( i && i->placement() != QTextCustomItem::PlaceInline ) {
3121 flow_->registerFloatingItem( i ); 3144 flow_->registerFloatingItem( i );
3122 p->registerFloatingItem( i ); 3145 p->registerFloatingItem( i );
3123 i->setParagraph( p ); 3146 i->setParagraph( p );
3124 } 3147 }
3125 p->mightHaveCustomItems = mightHaveCustomItems = TRUE; 3148 p->mightHaveCustomItems = mightHaveCustomItems = TRUE;
3126} 3149}
3127 3150
3128void QTextDocument::unregisterCustomItem( QTextCustomItem *i, QTextParagraph *p ) 3151void QTextDocument::unregisterCustomItem( QTextCustomItem *i, QTextParagraph *p )
3129{ 3152{
3130 flow_->unregisterFloatingItem( i ); 3153 flow_->unregisterFloatingItem( i );
3131 p->unregisterFloatingItem( i ); 3154 p->unregisterFloatingItem( i );
3132 i->setParagraph( 0 ); 3155 i->setParagraph( 0 );
3133} 3156}
3134 3157
3135bool QTextDocument::hasFocusParagraph() const 3158bool QTextDocument::hasFocusParagraph() const
3136{ 3159{
3137 return !!focusIndicator.parag; 3160 return !!focusIndicator.parag;
3138} 3161}
3139 3162
3140QString QTextDocument::focusHref() const 3163QString QTextDocument::focusHref() const
3141{ 3164{
3142 return focusIndicator.href; 3165 return focusIndicator.href;
3143} 3166}
3144 3167
3145bool QTextDocument::focusNextPrevChild( bool next ) 3168bool QTextDocument::focusNextPrevChild( bool next )
3146{ 3169{
3147 if ( !focusIndicator.parag ) { 3170 if ( !focusIndicator.parag ) {
3148 if ( next ) { 3171 if ( next ) {
3149 focusIndicator.parag = fParag; 3172 focusIndicator.parag = fParag;
3150 focusIndicator.start = 0; 3173 focusIndicator.start = 0;
3151 focusIndicator.len = 0; 3174 focusIndicator.len = 0;
3152 } else { 3175 } else {
3153 focusIndicator.parag = lParag; 3176 focusIndicator.parag = lParag;
3154 focusIndicator.start = lParag->length(); 3177 focusIndicator.start = lParag->length();
3155 focusIndicator.len = 0; 3178 focusIndicator.len = 0;
3156 } 3179 }
3157 } else { 3180 } else {
3158 focusIndicator.parag->setChanged( TRUE ); 3181 focusIndicator.parag->setChanged( TRUE );
3159 } 3182 }
3160 focusIndicator.href = QString::null; 3183 focusIndicator.href = QString::null;
3161 3184
3162 if ( next ) { 3185 if ( next ) {
3163 QTextParagraph *p = focusIndicator.parag; 3186 QTextParagraph *p = focusIndicator.parag;
3164 int index = focusIndicator.start + focusIndicator.len; 3187 int index = focusIndicator.start + focusIndicator.len;
3165 while ( p ) { 3188 while ( p ) {
3166 for ( int i = index; i < p->length(); ++i ) { 3189 for ( int i = index; i < p->length(); ++i ) {
3167 if ( p->at( i )->isAnchor() ) { 3190 if ( p->at( i )->isAnchor() ) {
3168 p->setChanged( TRUE ); 3191 p->setChanged( TRUE );
3169 focusIndicator.parag = p; 3192 focusIndicator.parag = p;
3170 focusIndicator.start = i; 3193 focusIndicator.start = i;
3171 focusIndicator.len = 0; 3194 focusIndicator.len = 0;
3172 focusIndicator.href = p->at( i )->anchorHref(); 3195 focusIndicator.href = p->at( i )->anchorHref();
3173 while ( i < p->length() ) { 3196 while ( i < p->length() ) {
3174 if ( !p->at( i )->isAnchor() ) 3197 if ( !p->at( i )->isAnchor() )
3175 return TRUE; 3198 return TRUE;
3176 focusIndicator.len++; 3199 focusIndicator.len++;
3177 i++; 3200 i++;
3178 } 3201 }
3179 } else if ( p->at( i )->isCustom() ) { 3202 } else if ( p->at( i )->isCustom() ) {
3180 if ( p->at( i )->customItem()->isNested() ) { 3203 if ( p->at( i )->customItem()->isNested() ) {
3181 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 3204 QTextTable *t = (QTextTable*)p->at( i )->customItem();
3182 QPtrList<QTextTableCell> cells = t->tableCells(); 3205 QPtrList<QTextTableCell> cells = t->tableCells();
3183 // first try to continue 3206 // first try to continue
3184 QTextTableCell *c; 3207 QTextTableCell *c;
3185 bool resetCells = TRUE; 3208 bool resetCells = TRUE;
3186 for ( c = cells.first(); c; c = cells.next() ) { 3209 for ( c = cells.first(); c; c = cells.next() ) {
3187 if ( c->richText()->hasFocusParagraph() ) { 3210 if ( c->richText()->hasFocusParagraph() ) {
3188 if ( c->richText()->focusNextPrevChild( next ) ) { 3211 if ( c->richText()->focusNextPrevChild( next ) ) {
3189 p->setChanged( TRUE ); 3212 p->setChanged( TRUE );
3190 focusIndicator.parag = p; 3213 focusIndicator.parag = p;
3191 focusIndicator.start = i; 3214 focusIndicator.start = i;
3192 focusIndicator.len = 0; 3215 focusIndicator.len = 0;
3193 focusIndicator.href = c->richText()->focusHref(); 3216 focusIndicator.href = c->richText()->focusHref();
3194 return TRUE; 3217 return TRUE;
3195 } else { 3218 } else {
3196 resetCells = FALSE; 3219 resetCells = FALSE;
3197 c = cells.next(); 3220 c = cells.next();
3198 break; 3221 break;
3199 } 3222 }
3200 } 3223 }
3201 } 3224 }
3202 // now really try 3225 // now really try
3203 if ( resetCells ) 3226 if ( resetCells )
3204 c = cells.first(); 3227 c = cells.first();
3205 for ( ; c; c = cells.next() ) { 3228 for ( ; c; c = cells.next() ) {
3206 if ( c->richText()->focusNextPrevChild( next ) ) { 3229 if ( c->richText()->focusNextPrevChild( next ) ) {
3207 p->setChanged( TRUE ); 3230 p->setChanged( TRUE );
3208 focusIndicator.parag = p; 3231 focusIndicator.parag = p;
3209 focusIndicator.start = i; 3232 focusIndicator.start = i;
3210 focusIndicator.len = 0; 3233 focusIndicator.len = 0;
3211 focusIndicator.href = c->richText()->focusHref(); 3234 focusIndicator.href = c->richText()->focusHref();
3212 return TRUE; 3235 return TRUE;
3213 } 3236 }
3214 } 3237 }
3215 } 3238 }
3216 } 3239 }
3217 } 3240 }
3218 index = 0; 3241 index = 0;
3219 p = p->next(); 3242 p = p->next();
3220 } 3243 }
3221 } else { 3244 } else {
3222 QTextParagraph *p = focusIndicator.parag; 3245 QTextParagraph *p = focusIndicator.parag;
3223 int index = focusIndicator.start - 1; 3246 int index = focusIndicator.start - 1;
3224 if ( focusIndicator.len == 0 && index < focusIndicator.parag->length() - 1 ) 3247 if ( focusIndicator.len == 0 && index < focusIndicator.parag->length() - 1 )
3225 index++; 3248 index++;
3226 while ( p ) { 3249 while ( p ) {
3227 for ( int i = index; i >= 0; --i ) { 3250 for ( int i = index; i >= 0; --i ) {
3228 if ( p->at( i )->isAnchor() ) { 3251 if ( p->at( i )->isAnchor() ) {
3229 p->setChanged( TRUE ); 3252 p->setChanged( TRUE );
3230 focusIndicator.parag = p; 3253 focusIndicator.parag = p;
3231 focusIndicator.start = i; 3254 focusIndicator.start = i;
3232 focusIndicator.len = 0; 3255 focusIndicator.len = 0;
3233 focusIndicator.href = p->at( i )->anchorHref(); 3256 focusIndicator.href = p->at( i )->anchorHref();
3234 while ( i >= -1 ) { 3257 while ( i >= -1 ) {
3235 if ( i < 0 || !p->at( i )->isAnchor() ) { 3258 if ( i < 0 || !p->at( i )->isAnchor() ) {
3236 focusIndicator.start++; 3259 focusIndicator.start++;
3237 return TRUE; 3260 return TRUE;
3238 } 3261 }
3239 if ( i < 0 ) 3262 if ( i < 0 )
3240 break; 3263 break;
3241 focusIndicator.len++; 3264 focusIndicator.len++;
3242 focusIndicator.start--; 3265 focusIndicator.start--;
3243 i--; 3266 i--;
3244 } 3267 }
3245 } else if ( p->at( i )->isCustom() ) { 3268 } else if ( p->at( i )->isCustom() ) {
3246 if ( p->at( i )->customItem()->isNested() ) { 3269 if ( p->at( i )->customItem()->isNested() ) {
3247 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 3270 QTextTable *t = (QTextTable*)p->at( i )->customItem();
3248 QPtrList<QTextTableCell> cells = t->tableCells(); 3271 QPtrList<QTextTableCell> cells = t->tableCells();
3249 // first try to continue 3272 // first try to continue
3250 QTextTableCell *c; 3273 QTextTableCell *c;
3251 bool resetCells = TRUE; 3274 bool resetCells = TRUE;
3252 for ( c = cells.last(); c; c = cells.prev() ) { 3275 for ( c = cells.last(); c; c = cells.prev() ) {
3253 if ( c->richText()->hasFocusParagraph() ) { 3276 if ( c->richText()->hasFocusParagraph() ) {
3254 if ( c->richText()->focusNextPrevChild( next ) ) { 3277 if ( c->richText()->focusNextPrevChild( next ) ) {
3255 p->setChanged( TRUE ); 3278 p->setChanged( TRUE );
3256 focusIndicator.parag = p; 3279 focusIndicator.parag = p;
3257 focusIndicator.start = i; 3280 focusIndicator.start = i;
3258 focusIndicator.len = 0; 3281 focusIndicator.len = 0;
3259 focusIndicator.href = c->richText()->focusHref(); 3282 focusIndicator.href = c->richText()->focusHref();
3260 return TRUE; 3283 return TRUE;
3261 } else { 3284 } else {
3262 resetCells = FALSE; 3285 resetCells = FALSE;
3263 c = cells.prev(); 3286 c = cells.prev();
3264 break; 3287 break;
3265 } 3288 }
3266 } 3289 }
3267 if ( cells.at() == 0 ) 3290 if ( cells.at() == 0 )
3268 break; 3291 break;
3269 } 3292 }
3270 // now really try 3293 // now really try
3271 if ( resetCells ) 3294 if ( resetCells )
3272 c = cells.last(); 3295 c = cells.last();
3273 for ( ; c; c = cells.prev() ) { 3296 for ( ; c; c = cells.prev() ) {
3274 if ( c->richText()->focusNextPrevChild( next ) ) { 3297 if ( c->richText()->focusNextPrevChild( next ) ) {
3275 p->setChanged( TRUE ); 3298 p->setChanged( TRUE );
3276 focusIndicator.parag = p; 3299 focusIndicator.parag = p;
3277 focusIndicator.start = i; 3300 focusIndicator.start = i;
3278 focusIndicator.len = 0; 3301 focusIndicator.len = 0;
3279 focusIndicator.href = c->richText()->focusHref(); 3302 focusIndicator.href = c->richText()->focusHref();
3280 return TRUE; 3303 return TRUE;
3281 } 3304 }
3282 if ( cells.at() == 0 ) 3305 if ( cells.at() == 0 )
3283 break; 3306 break;
3284 } 3307 }
3285 } 3308 }
3286 } 3309 }
3287 } 3310 }
3288 p = p->prev(); 3311 p = p->prev();
3289 if ( p ) 3312 if ( p )
3290 index = p->length() - 1; 3313 index = p->length() - 1;
3291 } 3314 }
3292 } 3315 }
3293 3316
3294 focusIndicator.parag = 0; 3317 focusIndicator.parag = 0;
3295 3318
3296 return FALSE; 3319 return FALSE;
3297} 3320}
3298 3321
3299int QTextDocument::length() const 3322int QTextDocument::length() const
3300{ 3323{
3301 int l = 0; 3324 int l = 0;
3302 QTextParagraph *p = fParag; 3325 QTextParagraph *p = fParag;
3303 while ( p ) { 3326 while ( p ) {
3304 l += p->length() - 1; // don't count trailing space 3327 l += p->length() - 1; // don't count trailing space
3305 p = p->next(); 3328 p = p->next();
3306 } 3329 }
3307 return l; 3330 return l;
3308} 3331}
3309 3332
3310// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3333// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3311 3334
3312int QTextFormat::width( const QChar &c ) const 3335int QTextFormat::width( const QChar &c ) const
3313{ 3336{
3314 if ( c.unicode() == 0xad ) // soft hyphen 3337 if ( c.unicode() == 0xad ) // soft hyphen
3315 return 0; 3338 return 0;
3316 if ( !pntr || !pntr->isActive() ) { 3339 if ( !pntr || !pntr->isActive() ) {
3317 if ( c == '\t' ) 3340 if ( c == '\t' )
3318 return fm.width( 'x' ) * 8; 3341 return fm.width( 'x' ) * 8;
3319 if ( ha == AlignNormal ) { 3342 if ( ha == AlignNormal ) {
3320 int w; 3343 int w;
3321 if ( c.row() ) 3344 if ( c.row() )
3322 w = fm.width( c ); 3345 w = fm.width( c );
3323 else 3346 else
3324 w = widths[ c.unicode() ]; 3347 w = widths[ c.unicode() ];
3325 if ( w == 0 && !c.row() ) { 3348 if ( w == 0 && !c.row() ) {
3326 w = fm.width( c ); 3349 w = fm.width( c );
3327 ( (QTextFormat*)this )->widths[ c.unicode() ] = w; 3350 ( (QTextFormat*)this )->widths[ c.unicode() ] = w;
3328 } 3351 }
3329 return w; 3352 return w;
3330 } else { 3353 } else {
3331 QFont f( fn ); 3354 QFont f( fn );
3332 if ( usePixelSizes ) 3355 if ( usePixelSizes )
3333 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 3356 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
3334 else 3357 else
3335 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 3358 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
3336 QFontMetrics fm_( f ); 3359 QFontMetrics fm_( f );
3337 return fm_.width( c ); 3360 return fm_.width( c );
3338 } 3361 }
3339 } 3362 }
3340 3363
3341 QFont f( fn ); 3364 QFont f( fn );
3342 if ( ha != AlignNormal ) { 3365 if ( ha != AlignNormal ) {
3343 if ( usePixelSizes ) 3366 if ( usePixelSizes )
3344 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 3367 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
3345 else 3368 else
3346 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 3369 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
3347 } 3370 }
3348 pntr->setFont( f ); 3371 pntr->setFont( f );
3349 3372
3350 return pntr->fontMetrics().width( c ); 3373 return pntr->fontMetrics().width( c );
3351} 3374}
3352 3375
3353int QTextFormat::width( const QString &str, int pos ) const 3376int QTextFormat::width( const QString &str, int pos ) const
3354{ 3377{
3355 int w = 0; 3378 int w = 0;
3356 if ( str[ pos ].unicode() == 0xad ) 3379 if ( str[ pos ].unicode() == 0xad )
3357 return w; 3380 return w;
3358 if ( !pntr || !pntr->isActive() ) { 3381 if ( !pntr || !pntr->isActive() ) {
3359 if ( ha == AlignNormal ) { 3382 if ( ha == AlignNormal ) {
3360 w = fm.width( str[ pos ] ); 3383 w = fm.width( str[ pos ] );
3361 } else { 3384 } else {
3362 QFont f( fn ); 3385 QFont f( fn );
3363 if ( usePixelSizes ) 3386 if ( usePixelSizes )
3364 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 3387 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
3365 else 3388 else
3366 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 3389 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
3367 QFontMetrics fm_( f ); 3390 QFontMetrics fm_( f );
3368 w = fm_.width( str[ pos ] ); 3391 w = fm_.width( str[ pos ] );
3369 } 3392 }
3370 } else { 3393 } else {
3371 QFont f( fn ); 3394 QFont f( fn );
3372 if ( ha != AlignNormal ) { 3395 if ( ha != AlignNormal ) {
3373 if ( usePixelSizes ) 3396 if ( usePixelSizes )
3374 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 3397 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
3375 else 3398 else
3376 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 3399 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
3377 } 3400 }
3378 pntr->setFont( f ); 3401 pntr->setFont( f );
3379 w = pntr->fontMetrics().width( str[ pos ] ); 3402 w = pntr->fontMetrics().width( str[ pos ] );
3380 } 3403 }
3381 return w; 3404 return w;
3382} 3405}
3383 3406
3384// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3407// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3385 3408
3386QTextString::QTextString() 3409QTextString::QTextString()
3387{ 3410{
3388 bidiDirty = FALSE; 3411 bidiDirty = FALSE;
3389 bidi = FALSE; 3412 bidi = FALSE;
3390 rightToLeft = FALSE; 3413 rightToLeft = FALSE;
3391 dir = QChar::DirON; 3414 dir = QChar::DirON;
3392} 3415}
3393 3416
3394QTextString::QTextString( const QTextString &s ) 3417QTextString::QTextString( const QTextString &s )
3395{ 3418{
3396 bidiDirty = s.bidiDirty; 3419 bidiDirty = s.bidiDirty;
3397 bidi = s.bidi; 3420 bidi = s.bidi;
3398 rightToLeft = s.rightToLeft; 3421 rightToLeft = s.rightToLeft;
3399 dir = s.dir; 3422 dir = s.dir;
3400 data = s.subString(); 3423 data = s.subString();
3401} 3424}
3402 3425
3403void QTextString::insert( int index, const QString &s, QTextFormat *f ) 3426void QTextString::insert( int index, const QString &s, QTextFormat *f )
3404{ 3427{
3405 insert( index, s.unicode(), s.length(), f ); 3428 insert( index, s.unicode(), s.length(), f );
3406} 3429}
3407 3430
3408void QTextString::insert( int index, const QChar *unicode, int len, QTextFormat *f ) 3431void QTextString::insert( int index, const QChar *unicode, int len, QTextFormat *f )
3409{ 3432{
3410 int os = data.size(); 3433 int os = data.size();
3411 data.resize( data.size() + len ); 3434 data.resize( data.size() + len );
3412 if ( index < os ) { 3435 if ( index < os ) {
3413 memmove( data.data() + index + len, data.data() + index, 3436 memmove( data.data() + index + len, data.data() + index,
3414 sizeof( QTextStringChar ) * ( os - index ) ); 3437 sizeof( QTextStringChar ) * ( os - index ) );
3415 } 3438 }
3416 for ( int i = 0; i < len; ++i ) { 3439 for ( int i = 0; i < len; ++i ) {
3417 data[ (int)index + i ].x = 0; 3440 data[ (int)index + i ].x = 0;
3418 data[ (int)index + i ].lineStart = 0; 3441 data[ (int)index + i ].lineStart = 0;
3419 data[ (int)index + i ].d.format = 0; 3442 data[ (int)index + i ].d.format = 0;
3420 data[ (int)index + i ].type = QTextStringChar::Regular; 3443 data[ (int)index + i ].type = QTextStringChar::Regular;
3421 data[ (int)index + i ].rightToLeft = 0; 3444 data[ (int)index + i ].rightToLeft = 0;
3422 data[ (int)index + i ].startOfRun = 0; 3445 data[ (int)index + i ].startOfRun = 0;
3423 data[ (int)index + i ].c = unicode[i]; 3446 data[ (int)index + i ].c = unicode[i];
3424 data[ (int)index + i ].setFormat( f ); 3447 data[ (int)index + i ].setFormat( f );
3425 } 3448 }
3426 bidiDirty = TRUE; 3449 bidiDirty = TRUE;
3427} 3450}
3428 3451
3429QTextString::~QTextString() 3452QTextString::~QTextString()
3430{ 3453{
3431 clear(); 3454 clear();
3432} 3455}
3433 3456
3434void QTextString::insert( int index, QTextStringChar *c, bool doAddRefFormat ) 3457void QTextString::insert( int index, QTextStringChar *c, bool doAddRefFormat )
3435{ 3458{
3436 int os = data.size(); 3459 int os = data.size();
3437 data.resize( data.size() + 1 ); 3460 data.resize( data.size() + 1 );
3438 if ( index < os ) { 3461 if ( index < os ) {
3439 memmove( data.data() + index + 1, data.data() + index, 3462 memmove( data.data() + index + 1, data.data() + index,
3440 sizeof( QTextStringChar ) * ( os - index ) ); 3463 sizeof( QTextStringChar ) * ( os - index ) );
3441 } 3464 }
3442 data[ (int)index ].c = c->c; 3465 data[ (int)index ].c = c->c;
3443 data[ (int)index ].x = 0; 3466 data[ (int)index ].x = 0;
3444 data[ (int)index ].lineStart = 0; 3467 data[ (int)index ].lineStart = 0;
3445 data[ (int)index ].rightToLeft = 0; 3468 data[ (int)index ].rightToLeft = 0;
3446 data[ (int)index ].d.format = 0; 3469 data[ (int)index ].d.format = 0;
3447 data[ (int)index ].type = QTextStringChar::Regular; 3470 data[ (int)index ].type = QTextStringChar::Regular;
3448 if ( doAddRefFormat && c->format() ) 3471 if ( doAddRefFormat && c->format() )
3449 c->format()->addRef(); 3472 c->format()->addRef();
3450 data[ (int)index ].setFormat( c->format() ); 3473 data[ (int)index ].setFormat( c->format() );
3451 bidiDirty = TRUE; 3474 bidiDirty = TRUE;
3452} 3475}
3453 3476
3454void QTextString::truncate( int index ) 3477void QTextString::truncate( int index )
3455{ 3478{
3456 index = QMAX( index, 0 ); 3479 index = QMAX( index, 0 );
3457 index = QMIN( index, (int)data.size() - 1 ); 3480 index = QMIN( index, (int)data.size() - 1 );
3458 if ( index < (int)data.size() ) { 3481 if ( index < (int)data.size() ) {
3459 for ( int i = index + 1; i < (int)data.size(); ++i ) { 3482 for ( int i = index + 1; i < (int)data.size(); ++i ) {
3460 if ( !(data[ i ].type == QTextStringChar::Regular) ) { 3483 if ( !(data[ i ].type == QTextStringChar::Regular) ) {
3461 delete data[ i ].customItem(); 3484 delete data[ i ].customItem();
3462 if ( data[ i ].d.custom->format ) 3485 if ( data[ i ].d.custom->format )
3463 data[ i ].d.custom->format->removeRef(); 3486 data[ i ].d.custom->format->removeRef();
3464 delete data[ i ].d.custom; 3487 delete data[ i ].d.custom;
3465 data[ i ].d.custom = 0; 3488 data[ i ].d.custom = 0;
3466 } else if ( data[ i ].format() ) { 3489 } else if ( data[ i ].format() ) {
3467 data[ i ].format()->removeRef(); 3490 data[ i ].format()->removeRef();
3468 } 3491 }
3469 } 3492 }
3470 } 3493 }
3471 data.truncate( index ); 3494 data.truncate( index );
3472 bidiDirty = TRUE; 3495 bidiDirty = TRUE;
3473} 3496}
3474 3497
3475void QTextString::remove( int index, int len ) 3498void QTextString::remove( int index, int len )
3476{ 3499{
3477 for ( int i = index; i < (int)data.size() && i - index < len; ++i ) { 3500 for ( int i = index; i < (int)data.size() && i - index < len; ++i ) {
3478 if ( !(data[ i ].type == QTextStringChar::Regular) ) { 3501 if ( !(data[ i ].type == QTextStringChar::Regular) ) {
3479 delete data[ i ].customItem(); 3502 delete data[ i ].customItem();
3480 if ( data[ i ].d.custom->format ) 3503 if ( data[ i ].d.custom->format )
3481 data[ i ].d.custom->format->removeRef(); 3504 data[ i ].d.custom->format->removeRef();
3482 delete data[ i ].d.custom; 3505 delete data[ i ].d.custom;
3483 data[ i ].d.custom = 0; 3506 data[ i ].d.custom = 0;
3484 } else if ( data[ i ].format() ) { 3507 } else if ( data[ i ].format() ) {
3485 data[ i ].format()->removeRef(); 3508 data[ i ].format()->removeRef();
3486 } 3509 }
3487 } 3510 }
3488 memmove( data.data() + index, data.data() + index + len, 3511 memmove( data.data() + index, data.data() + index + len,
3489 sizeof( QTextStringChar ) * ( data.size() - index - len ) ); 3512 sizeof( QTextStringChar ) * ( data.size() - index - len ) );
3490 data.resize( data.size() - len ); 3513 data.resize( data.size() - len );
3491 bidiDirty = TRUE; 3514 bidiDirty = TRUE;
3492} 3515}
3493 3516
3494void QTextString::clear() 3517void QTextString::clear()
3495{ 3518{
3496 for ( int i = 0; i < (int)data.count(); ++i ) { 3519 for ( int i = 0; i < (int)data.count(); ++i ) {
3497 if ( !(data[ i ].type == QTextStringChar::Regular) ) { 3520 if ( !(data[ i ].type == QTextStringChar::Regular) ) {
3498 delete data[ i ].customItem(); 3521 delete data[ i ].customItem();
3499 if ( data[ i ].d.custom->format ) 3522 if ( data[ i ].d.custom->format )
3500 data[ i ].d.custom->format->removeRef(); 3523 data[ i ].d.custom->format->removeRef();
3501 delete data[ i ].d.custom; 3524 delete data[ i ].d.custom;
3502 data[ i ].d.custom = 0; 3525 data[ i ].d.custom = 0;
3503 } else if ( data[ i ].format() ) { 3526 } else if ( data[ i ].format() ) {
3504 data[ i ].format()->removeRef(); 3527 data[ i ].format()->removeRef();
3505 } 3528 }
3506 } 3529 }
3507 data.resize( 0 ); 3530 data.resize( 0 );
3508} 3531}
3509 3532
3510void QTextString::setFormat( int index, QTextFormat *f, bool useCollection ) 3533void QTextString::setFormat( int index, QTextFormat *f, bool useCollection )
3511{ 3534{
3512 if ( useCollection && data[ index ].format() ) 3535 if ( useCollection && data[ index ].format() )
3513 data[ index ].format()->removeRef(); 3536 data[ index ].format()->removeRef();
3514 data[ index ].setFormat( f ); 3537 data[ index ].setFormat( f );
3515} 3538}
3516 3539
3517void QTextString::checkBidi() const 3540void QTextString::checkBidi() const
3518{ 3541{
3519 bool rtlKnown = FALSE; 3542 bool rtlKnown = FALSE;
3520 if ( dir == QChar::DirR ) { 3543 if ( dir == QChar::DirR ) {
3521 ((QTextString *)this)->bidi = TRUE; 3544 ((QTextString *)this)->bidi = TRUE;
3522 ((QTextString *)this)->rightToLeft = TRUE; 3545 ((QTextString *)this)->rightToLeft = TRUE;
3523 rtlKnown = TRUE; 3546 rtlKnown = TRUE;
3524 return; 3547 return;
3525 } else if ( dir == QChar::DirL ) { 3548 } else if ( dir == QChar::DirL ) {
3526 ((QTextString *)this)->rightToLeft = FALSE; 3549 ((QTextString *)this)->rightToLeft = FALSE;
3527 rtlKnown = TRUE; 3550 rtlKnown = TRUE;
3528 } else { 3551 } else {
3529 ((QTextString *)this)->rightToLeft = FALSE; 3552 ((QTextString *)this)->rightToLeft = FALSE;
3530 } 3553 }
3531 3554
3532 int len = data.size(); 3555 int len = data.size();
3533 const QTextStringChar *c = data.data(); 3556 const QTextStringChar *c = data.data();
3534 ((QTextString *)this)->bidi = FALSE; 3557 ((QTextString *)this)->bidi = FALSE;
3535 while( len ) { 3558 while( len ) {
3536 if ( !rtlKnown ) { 3559 if ( !rtlKnown ) {
3537 switch( c->c.direction() ) 3560 switch( c->c.direction() )
3538 { 3561 {
3539 case QChar::DirL: 3562 case QChar::DirL:
3540 case QChar::DirLRO: 3563 case QChar::DirLRO:
3541 case QChar::DirLRE: 3564 case QChar::DirLRE:
3542 ((QTextString *)this)->rightToLeft = FALSE; 3565 ((QTextString *)this)->rightToLeft = FALSE;
3543 rtlKnown = TRUE; 3566 rtlKnown = TRUE;
3544 break; 3567 break;
3545 case QChar::DirR: 3568 case QChar::DirR:
3546 case QChar::DirAL: 3569 case QChar::DirAL:
3547 case QChar::DirRLO: 3570 case QChar::DirRLO:
3548 case QChar::DirRLE: 3571 case QChar::DirRLE:
3549 ((QTextString *)this)->rightToLeft = TRUE; 3572 ((QTextString *)this)->rightToLeft = TRUE;
3550 rtlKnown = TRUE; 3573 rtlKnown = TRUE;
3551 break; 3574 break;
3552 default: 3575 default:
3553 break; 3576 break;
3554 } 3577 }
3555 } 3578 }
3556 uchar row = c->c.row(); 3579 uchar row = c->c.row();
3557 if( (row > 0x04 && row < 0x09) || (row > 0xfa && row < 0xff) ) { 3580 if( (row > 0x04 && row < 0x09) || (row > 0xfa && row < 0xff) ) {
3558 ((QTextString *)this)->bidi = TRUE; 3581 ((QTextString *)this)->bidi = TRUE;
3559 if ( rtlKnown ) 3582 if ( rtlKnown )
3560 return; 3583 return;
3561 } 3584 }
3562 len--; 3585 len--;
3563 ++c; 3586 ++c;
3564 } 3587 }
3565} 3588}
3566 3589
3567void QTextDocument::setStyleSheet( QStyleSheet *s ) 3590void QTextDocument::setStyleSheet( QStyleSheet *s )
3568{ 3591{
3569 if ( !s ) 3592 if ( !s )
3570 return; 3593 return;
3571 sheet_ = s; 3594 sheet_ = s;
3572 list_tm = list_bm = par_tm = par_bm = 12; 3595 list_tm = list_bm = par_tm = par_bm = 12;
3573 list_lm = 40; 3596 list_lm = 40;
3574 li_tm = li_bm = 0; 3597 li_tm = li_bm = 0;
3575 QStyleSheetItem* item = s->item( "ol" ); 3598 QStyleSheetItem* item = s->item( "ol" );
3576 if ( item ) { 3599 if ( item ) {
3577 list_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop )); 3600 list_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop ));
3578 list_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom )); 3601 list_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom ));
3579 list_lm = QMAX(0,item->margin( QStyleSheetItem::MarginLeft )); 3602 list_lm = QMAX(0,item->margin( QStyleSheetItem::MarginLeft ));
3580 } 3603 }
3581 if ( (item = s->item( "li" ) ) ) { 3604 if ( (item = s->item( "li" ) ) ) {
3582 li_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop )); 3605 li_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop ));
3583 li_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom )); 3606 li_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom ));
3584 } 3607 }
3585 if ( (item = s->item( "p" ) ) ) { 3608 if ( (item = s->item( "p" ) ) ) {
3586 par_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop )); 3609 par_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop ));
3587 par_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom )); 3610 par_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom ));
3588 } 3611 }
3589} 3612}
3590 3613
3591void QTextDocument::setUnderlineLinks( bool b ) { 3614void QTextDocument::setUnderlineLinks( bool b ) {
3592 underlLinks = b; 3615 underlLinks = b;
3593 for ( QTextDocument *d = childList.first(); d; d = childList.next() ) 3616 for ( QTextDocument *d = childList.first(); d; d = childList.next() )
3594 d->setUnderlineLinks( b ); 3617 d->setUnderlineLinks( b );
3595} 3618}
3596 3619
3597void QTextStringChar::setFormat( QTextFormat *f ) 3620void QTextStringChar::setFormat( QTextFormat *f )
3598{ 3621{
3599 if ( type == Regular ) { 3622 if ( type == Regular ) {
3600 d.format = f; 3623 d.format = f;
3601 } else { 3624 } else {
3602 if ( !d.custom ) { 3625 if ( !d.custom ) {
3603 d.custom = new CustomData; 3626 d.custom = new CustomData;
3604 d.custom->custom = 0; 3627 d.custom->custom = 0;
3605 } 3628 }
3606 d.custom->format = f; 3629 d.custom->format = f;
3607 } 3630 }
3608} 3631}
3609 3632
3610void QTextStringChar::setCustomItem( QTextCustomItem *i ) 3633void QTextStringChar::setCustomItem( QTextCustomItem *i )
3611{ 3634{
3612 if ( type == Regular ) { 3635 if ( type == Regular ) {
3613 QTextFormat *f = format(); 3636 QTextFormat *f = format();
3614 d.custom = new CustomData; 3637 d.custom = new CustomData;
3615 d.custom->format = f; 3638 d.custom->format = f;
3616 } else { 3639 } else {
3617 delete d.custom->custom; 3640 delete d.custom->custom;
3618 } 3641 }
3619 d.custom->custom = i; 3642 d.custom->custom = i;
3620 type = (type == Anchor ? CustomAnchor : Custom); 3643 type = (type == Anchor ? CustomAnchor : Custom);
3621} 3644}
3622 3645
3623void QTextStringChar::loseCustomItem() 3646void QTextStringChar::loseCustomItem()
3624{ 3647{
3625 if ( type == Custom ) { 3648 if ( type == Custom ) {
3626 QTextFormat *f = d.custom->format; 3649 QTextFormat *f = d.custom->format;
3627 d.custom->custom = 0; 3650 d.custom->custom = 0;
3628 delete d.custom; 3651 delete d.custom;
3629 type = Regular; 3652 type = Regular;
3630 d.format = f; 3653 d.format = f;
3631 } else if ( type == CustomAnchor ) { 3654 } else if ( type == CustomAnchor ) {
3632 d.custom->custom = 0; 3655 d.custom->custom = 0;
3633 type = Anchor; 3656 type = Anchor;
3634 } 3657 }
3635} 3658}
3636 3659
3637QString QTextStringChar::anchorName() const 3660QString QTextStringChar::anchorName() const
3638{ 3661{
3639 if ( type == Regular ) 3662 if ( type == Regular )
3640 return QString::null; 3663 return QString::null;
3641 else 3664 else
3642 return d.custom->anchorName; 3665 return d.custom->anchorName;
3643} 3666}
3644 3667
3645QString QTextStringChar::anchorHref() const 3668QString QTextStringChar::anchorHref() const
3646{ 3669{
3647 if ( type == Regular ) 3670 if ( type == Regular )
3648 return QString::null; 3671 return QString::null;
3649 else 3672 else
3650 return d.custom->anchorHref; 3673 return d.custom->anchorHref;
3651} 3674}
3652 3675
3653void QTextStringChar::setAnchor( const QString& name, const QString& href ) 3676void QTextStringChar::setAnchor( const QString& name, const QString& href )
3654{ 3677{
3655 if ( type == Regular ) { 3678 if ( type == Regular ) {
3656 QTextFormat *f = format(); 3679 QTextFormat *f = format();
3657 d.custom = new CustomData; 3680 d.custom = new CustomData;
3658 d.custom->custom = 0; 3681 d.custom->custom = 0;
3659 d.custom->format = f; 3682 d.custom->format = f;
3660 type = Anchor; 3683 type = Anchor;
3661 } else if ( type == Custom ) { 3684 } else if ( type == Custom ) {
3662 type = CustomAnchor; 3685 type = CustomAnchor;
3663 } 3686 }
3664 d.custom->anchorName = name; 3687 d.custom->anchorName = name;
3665 d.custom->anchorHref = href; 3688 d.custom->anchorHref = href;
3666} 3689}
3667 3690
3668 3691
3669int QTextString::width( int idx ) const 3692int QTextString::width( int idx ) const
3670{ 3693{
3671 int w = 0; 3694 int w = 0;
3672 QTextStringChar *c = &at( idx ); 3695 QTextStringChar *c = &at( idx );
3673 if ( c->c.unicode() == 0xad || c->c.unicode() == 0x2028 ) 3696 if ( c->c.unicode() == 0xad || c->c.unicode() == 0x2028 )
3674 return 0; 3697 return 0;
3675 if( c->isCustom() ) { 3698 if( c->isCustom() ) {
3676 if( c->customItem()->placement() == QTextCustomItem::PlaceInline ) 3699 if( c->customItem()->placement() == QTextCustomItem::PlaceInline )
3677 w = c->customItem()->width; 3700 w = c->customItem()->width;
3678 } else { 3701 } else {
3679 int r = c->c.row(); 3702 int r = c->c.row();
3680 if( r < 0x06 || r > 0x1f ) 3703 if( r < 0x06 || r > 0x1f )
3681 w = c->format()->width( c->c ); 3704 w = c->format()->width( c->c );
3682 else { 3705 else {
3683 // complex text. We need some hacks to get the right metric here 3706 // complex text. We need some hacks to get the right metric here
3684 QString str; 3707 QString str;
3685 int pos = 0; 3708 int pos = 0;
3686 if( idx > 4 ) 3709 if( idx > 4 )
3687 pos = idx - 4; 3710 pos = idx - 4;
3688 int off = idx - pos; 3711 int off = idx - pos;
3689 int end = QMIN( length(), idx + 4 ); 3712 int end = QMIN( length(), idx + 4 );
3690 while ( pos < end ) { 3713 while ( pos < end ) {
3691 str += at(pos).c; 3714 str += at(pos).c;
3692 pos++; 3715 pos++;
3693 } 3716 }
3694 w = c->format()->width( str, off ); 3717 w = c->format()->width( str, off );
3695 } 3718 }
3696 } 3719 }
3697 return w; 3720 return w;
3698} 3721}
3699 3722
3700QMemArray<QTextStringChar> QTextString::subString( int start, int len ) const 3723QMemArray<QTextStringChar> QTextString::subString( int start, int len ) const
3701{ 3724{
3702 if ( len == 0xFFFFFF ) 3725 if ( len == 0xFFFFFF )
3703 len = data.size(); 3726 len = data.size();
3704 QMemArray<QTextStringChar> a; 3727 QMemArray<QTextStringChar> a;
3705 a.resize( len ); 3728 a.resize( len );
3706 for ( int i = 0; i < len; ++i ) { 3729 for ( int i = 0; i < len; ++i ) {
3707 QTextStringChar *c = &data[ i + start ]; 3730 QTextStringChar *c = &data[ i + start ];
3708 a[ i ].c = c->c; 3731 a[ i ].c = c->c;
3709 a[ i ].x = 0; 3732 a[ i ].x = 0;
3710 a[ i ].lineStart = 0; 3733 a[ i ].lineStart = 0;
3711 a[ i ].rightToLeft = 0; 3734 a[ i ].rightToLeft = 0;
3712 a[ i ].d.format = 0; 3735 a[ i ].d.format = 0;
3713 a[ i ].type = QTextStringChar::Regular; 3736 a[ i ].type = QTextStringChar::Regular;
3714 a[ i ].setFormat( c->format() ); 3737 a[ i ].setFormat( c->format() );
3715 if ( c->format() ) 3738 if ( c->format() )
3716 c->format()->addRef(); 3739 c->format()->addRef();
3717 } 3740 }
3718 return a; 3741 return a;
3719} 3742}
3720 3743
3721// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3744// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3722 3745
3723QTextParagraph::QTextParagraph( QTextDocument *d, QTextParagraph *pr, QTextParagraph *nx, bool updateIds ) 3746QTextParagraph::QTextParagraph( QTextDocument *d, QTextParagraph *pr, QTextParagraph *nx, bool updateIds )
3724 : invalid( 0 ), p( pr ), n( nx ), docOrPseudo( d ), 3747 : invalid( 0 ), p( pr ), n( nx ), docOrPseudo( d ),
3725 changed(FALSE), firstFormat(TRUE), firstPProcess(TRUE), needPreProcess(FALSE), fullWidth(TRUE), 3748 changed(FALSE), firstFormat(TRUE), firstPProcess(TRUE), needPreProcess(FALSE), fullWidth(TRUE),
3726 lastInFrame(FALSE), visible(TRUE), breakable(TRUE), movedDown(FALSE), 3749 lastInFrame(FALSE), visible(TRUE), breakable(TRUE), movedDown(FALSE),
3727 mightHaveCustomItems(FALSE), hasdoc( d != 0 ), litem(FALSE), rtext(FALSE), 3750 mightHaveCustomItems(FALSE), hasdoc( d != 0 ), litem(FALSE), rtext(FALSE),
3728 align( 0 ),mSelections( 0 ), 3751 align( 0 ),mSelections( 0 ),
3729 mFloatingItems( 0 ), lstyle( QStyleSheetItem::ListDisc ), 3752 mFloatingItems( 0 ), lstyle( QStyleSheetItem::ListDisc ),
3730 utm( 0 ), ubm( 0 ), ulm( 0 ), urm( 0 ), uflm( 0 ), ulinespacing( 0 ), 3753 utm( 0 ), ubm( 0 ), ulm( 0 ), urm( 0 ), uflm( 0 ), ulinespacing( 0 ),
3731 tArray(0), tabStopWidth(0), eData( 0 ), ldepth( 0 ) 3754 tArray(0), tabStopWidth(0), eData( 0 ), ldepth( 0 )
3732{ 3755{
3733 lstyle = QStyleSheetItem::ListDisc; 3756 lstyle = QStyleSheetItem::ListDisc;
3734 if ( !hasdoc ) 3757 if ( !hasdoc )
3735 docOrPseudo = new QTextParagraphPseudoDocument; 3758 docOrPseudo = new QTextParagraphPseudoDocument;
3736 bgcol = 0; 3759 bgcol = 0;
3737 list_val = -1; 3760 list_val = -1;
3738 QTextFormat* defFormat = formatCollection()->defaultFormat(); 3761 QTextFormat* defFormat = formatCollection()->defaultFormat();
3739 if ( !hasdoc ) { 3762 if ( !hasdoc ) {
3740 tabStopWidth = defFormat->width( 'x' ) * 8; 3763 tabStopWidth = defFormat->width( 'x' ) * 8;
3741 pseudoDocument()->commandHistory = new QTextCommandHistory( 100 ); 3764 pseudoDocument()->commandHistory = new QTextCommandHistory( 100 );
3742 } 3765 }
3743 3766
3744 if ( p ) 3767 if ( p )
3745 p->n = this; 3768 p->n = this;
3746 if ( n ) 3769 if ( n )
3747 n->p = this; 3770 n->p = this;
3748 3771
3749 3772
3750 if ( !p && hasdoc ) 3773 if ( !p && hasdoc )
3751 document()->setFirstParagraph( this ); 3774 document()->setFirstParagraph( this );
3752 if ( !n && hasdoc ) 3775 if ( !n && hasdoc )
3753 document()->setLastParagraph( this ); 3776 document()->setLastParagraph( this );
3754 3777
3755 state = -1; 3778 state = -1;
3756 3779
3757 if ( p ) 3780 if ( p )
3758 id = p->id + 1; 3781 id = p->id + 1;
3759 else 3782 else
3760 id = 0; 3783 id = 0;
3761 if ( n && updateIds ) { 3784 if ( n && updateIds ) {
3762 QTextParagraph *s = n; 3785 QTextParagraph *s = n;
3763 while ( s ) { 3786 while ( s ) {
3764 s->id = s->p->id + 1; 3787 s->id = s->p->id + 1;
3765 s->invalidateStyleCache(); 3788 s->invalidateStyleCache();
3766 s = s->n; 3789 s = s->n;
3767 } 3790 }
3768 } 3791 }
3769 3792
3770 str = new QTextString(); 3793 str = new QTextString();
3771 str->insert( 0, " ", formatCollection()->defaultFormat() ); 3794 str->insert( 0, " ", formatCollection()->defaultFormat() );
3772} 3795}
3773 3796
3774QTextParagraph::~QTextParagraph() 3797QTextParagraph::~QTextParagraph()
3775{ 3798{
3776 delete str; 3799 delete str;
3777 if ( hasdoc ) { 3800 if ( hasdoc ) {
3778 register QTextDocument *doc = document(); 3801 register QTextDocument *doc = document();
3779 if ( this == doc->minwParag ) { 3802 if ( this == doc->minwParag ) {
3780 doc->minwParag = 0; 3803 doc->minwParag = 0;
3781 doc->minw = 0; 3804 doc->minw = 0;
3782 } 3805 }
3783 if ( this == doc->curParag ) 3806 if ( this == doc->curParag )
3784 doc->curParag = 0; 3807 doc->curParag = 0;
3785 } else { 3808 } else {
3786 delete pseudoDocument(); 3809 delete pseudoDocument();
3787 } 3810 }
3788 if ( tArray ) 3811 if ( tArray )
3789 delete [] tArray; 3812 delete [] tArray;
3790 delete eData; 3813 delete eData;
3791 QMap<int, QTextLineStart*>::Iterator it = lineStarts.begin(); 3814 QMap<int, QTextLineStart*>::Iterator it = lineStarts.begin();
3792 for ( ; it != lineStarts.end(); ++it ) 3815 for ( ; it != lineStarts.end(); ++it )
3793 delete *it; 3816 delete *it;
3794 if ( mSelections ) 3817 if ( mSelections )
3795 delete mSelections; 3818 delete mSelections;
3796 if ( mFloatingItems ) 3819 if ( mFloatingItems )
3797 delete mFloatingItems; 3820 delete mFloatingItems;
3798 if ( p ) 3821 if ( p )
3799 p->setNext( n ); 3822 p->setNext( n );
3800 if ( n ) 3823 if ( n )
3801 n->setPrev( p ); 3824 n->setPrev( p );
3802} 3825}
3803 3826
3804void QTextParagraph::setNext( QTextParagraph *s ) 3827void QTextParagraph::setNext( QTextParagraph *s )
3805{ 3828{
3806 n = s; 3829 n = s;
3807 if ( !n && hasdoc ) 3830 if ( !n && hasdoc )
3808 document()->setLastParagraph( this ); 3831 document()->setLastParagraph( this );
3809} 3832}
3810 3833
3811void QTextParagraph::setPrev( QTextParagraph *s ) 3834void QTextParagraph::setPrev( QTextParagraph *s )
3812{ 3835{
3813 p = s; 3836 p = s;
3814 if ( !p && hasdoc ) 3837 if ( !p && hasdoc )
3815 document()->setFirstParagraph( this ); 3838 document()->setFirstParagraph( this );
3816} 3839}
3817 3840
3818void QTextParagraph::invalidate( int chr ) 3841void QTextParagraph::invalidate( int chr )
3819{ 3842{
3820 if ( invalid < 0 ) 3843 if ( invalid < 0 )
3821 invalid = chr; 3844 invalid = chr;
3822 else 3845 else
3823 invalid = QMIN( invalid, chr ); 3846 invalid = QMIN( invalid, chr );
3824 if ( mFloatingItems ) { 3847 if ( mFloatingItems ) {
3825 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) 3848 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() )
3826 i->ypos = -1; 3849 i->ypos = -1;
3827 } 3850 }
3828 invalidateStyleCache(); 3851 invalidateStyleCache();
3829} 3852}
3830 3853
3831void QTextParagraph::invalidateStyleCache() 3854void QTextParagraph::invalidateStyleCache()
3832{ 3855{
3833 if ( list_val < 0 ) 3856 if ( list_val < 0 )
3834 list_val = -1; 3857 list_val = -1;
3835} 3858}
3836 3859
3837 3860
3838void QTextParagraph::insert( int index, const QString &s ) 3861void QTextParagraph::insert( int index, const QString &s )
3839{ 3862{
3840 insert( index, s.unicode(), s.length() ); 3863 insert( index, s.unicode(), s.length() );
3841} 3864}
3842 3865
3843void QTextParagraph::insert( int index, const QChar *unicode, int len ) 3866void QTextParagraph::insert( int index, const QChar *unicode, int len )
3844{ 3867{
3845 if ( hasdoc && !document()->useFormatCollection() && document()->preProcessor() ) 3868 if ( hasdoc && !document()->useFormatCollection() && document()->preProcessor() )
3846 str->insert( index, unicode, len, 3869 str->insert( index, unicode, len,
3847 document()->preProcessor()->format( QTextPreProcessor::Standard ) ); 3870 document()->preProcessor()->format( QTextPreProcessor::Standard ) );
3848 else 3871 else
3849 str->insert( index, unicode, len, formatCollection()->defaultFormat() ); 3872 str->insert( index, unicode, len, formatCollection()->defaultFormat() );
3850 invalidate( index ); 3873 invalidate( index );
3851 needPreProcess = TRUE; 3874 needPreProcess = TRUE;
3852} 3875}
3853 3876
3854void QTextParagraph::truncate( int index ) 3877void QTextParagraph::truncate( int index )
3855{ 3878{
3856 str->truncate( index ); 3879 str->truncate( index );
3857 insert( length(), " " ); 3880 insert( length(), " " );
3858 needPreProcess = TRUE; 3881 needPreProcess = TRUE;
3859} 3882}
3860 3883
3861void QTextParagraph::remove( int index, int len ) 3884void QTextParagraph::remove( int index, int len )
3862{ 3885{
3863 if ( index + len - str->length() > 0 ) 3886 if ( index + len - str->length() > 0 )
3864 return; 3887 return;
3865 for ( int i = index; i < index + len; ++i ) { 3888 for ( int i = index; i < index + len; ++i ) {
3866 QTextStringChar *c = at( i ); 3889 QTextStringChar *c = at( i );
3867 if ( hasdoc && c->isCustom() ) { 3890 if ( hasdoc && c->isCustom() ) {
3868 document()->unregisterCustomItem( c->customItem(), this ); 3891 document()->unregisterCustomItem( c->customItem(), this );
3869 } 3892 }
3870 } 3893 }
3871 str->remove( index, len ); 3894 str->remove( index, len );
3872 invalidate( 0 ); 3895 invalidate( 0 );
3873 needPreProcess = TRUE; 3896 needPreProcess = TRUE;
3874} 3897}
3875 3898
3876void QTextParagraph::join( QTextParagraph *s ) 3899void QTextParagraph::join( QTextParagraph *s )
3877{ 3900{
3878 int oh = r.height() + s->r.height(); 3901 int oh = r.height() + s->r.height();
3879 n = s->n; 3902 n = s->n;
3880 if ( n ) 3903 if ( n )
3881 n->p = this; 3904 n->p = this;
3882 else if ( hasdoc ) 3905 else if ( hasdoc )
3883 document()->setLastParagraph( this ); 3906 document()->setLastParagraph( this );
3884 3907
3885 int start = str->length(); 3908 int start = str->length();
3886 if ( length() > 0 && at( length() - 1 )->c == ' ' ) { 3909 if ( length() > 0 && at( length() - 1 )->c == ' ' ) {
3887 remove( length() - 1, 1 ); 3910 remove( length() - 1, 1 );
3888 --start; 3911 --start;
3889 } 3912 }
3890 append( s->str->toString(), TRUE ); 3913 append( s->str->toString(), TRUE );
3891 3914
3892 for ( int i = 0; i < s->length(); ++i ) { 3915 for ( int i = 0; i < s->length(); ++i ) {
3893 if ( !hasdoc || document()->useFormatCollection() ) { 3916 if ( !hasdoc || document()->useFormatCollection() ) {
3894 s->str->at( i ).format()->addRef(); 3917 s->str->at( i ).format()->addRef();
3895 str->setFormat( i + start, s->str->at( i ).format(), TRUE ); 3918 str->setFormat( i + start, s->str->at( i ).format(), TRUE );
3896 } 3919 }
3897 if ( s->str->at( i ).isCustom() ) { 3920 if ( s->str->at( i ).isCustom() ) {
3898 QTextCustomItem * item = s->str->at( i ).customItem(); 3921 QTextCustomItem * item = s->str->at( i ).customItem();
3899 str->at( i + start ).setCustomItem( item ); 3922 str->at( i + start ).setCustomItem( item );
3900 s->str->at( i ).loseCustomItem(); 3923 s->str->at( i ).loseCustomItem();
3901 if ( hasdoc ) { 3924 if ( hasdoc ) {
3902 document()->unregisterCustomItem( item, s ); 3925 document()->unregisterCustomItem( item, s );
3903 document()->registerCustomItem( item, this ); 3926 document()->registerCustomItem( item, this );
3904 } 3927 }
3905 } 3928 }
3906 if ( s->str->at( i ).isAnchor() ) { 3929 if ( s->str->at( i ).isAnchor() ) {
3907 str->at( i + start ).setAnchor( s->str->at( i ).anchorName(), 3930 str->at( i + start ).setAnchor( s->str->at( i ).anchorName(),
3908 s->str->at( i ).anchorHref() ); 3931 s->str->at( i ).anchorHref() );
3909 } 3932 }
3910 } 3933 }
3911 3934
3912 if ( !extraData() && s->extraData() ) { 3935 if ( !extraData() && s->extraData() ) {
3913 setExtraData( s->extraData() ); 3936 setExtraData( s->extraData() );
3914 s->setExtraData( 0 ); 3937 s->setExtraData( 0 );
3915 } else if ( extraData() && s->extraData() ) { 3938 } else if ( extraData() && s->extraData() ) {
3916 extraData()->join( s->extraData() ); 3939 extraData()->join( s->extraData() );
3917 } 3940 }
3918 delete s; 3941 delete s;
3919 invalidate( 0 ); 3942 invalidate( 0 );
3920 r.setHeight( oh ); 3943 r.setHeight( oh );
3921 needPreProcess = TRUE; 3944 needPreProcess = TRUE;
3922 if ( n ) { 3945 if ( n ) {
3923 QTextParagraph *s = n; 3946 QTextParagraph *s = n;
3924 s->invalidate( 0 ); 3947 s->invalidate( 0 );
3925 while ( s ) { 3948 while ( s ) {
3926 s->id = s->p->id + 1; 3949 s->id = s->p->id + 1;
3927 s->state = -1; 3950 s->state = -1;
3928 s->needPreProcess = TRUE; 3951 s->needPreProcess = TRUE;
3929 s->changed = TRUE; 3952 s->changed = TRUE;
3930 s->invalidateStyleCache(); 3953 s->invalidateStyleCache();
3931 s = s->n; 3954 s = s->n;
3932 } 3955 }
3933 } 3956 }
3934 format(); 3957 format();
3935 state = -1; 3958 state = -1;
3936} 3959}
3937 3960
3938void QTextParagraph::move( int &dy ) 3961void QTextParagraph::move( int &dy )
3939{ 3962{
3940 if ( dy == 0 ) 3963 if ( dy == 0 )
3941 return; 3964 return;
3942 changed = TRUE; 3965 changed = TRUE;
3943 r.moveBy( 0, dy ); 3966 r.moveBy( 0, dy );
3944 if ( mFloatingItems ) { 3967 if ( mFloatingItems ) {
3945 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) 3968 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() )
3946 i->ypos += dy; 3969 i->ypos += dy;
3947 } 3970 }
3948 if ( p ) 3971 if ( p )
3949 p->lastInFrame = TRUE; 3972 p->lastInFrame = TRUE;
3950 3973
3951 // do page breaks if required 3974 // do page breaks if required
3952 if ( hasdoc && document()->isPageBreakEnabled() ) { 3975 if ( hasdoc && document()->isPageBreakEnabled() ) {
3953 int shift; 3976 int shift;
3954 if ( ( shift = document()->formatter()->formatVertically( document(), this ) ) ) { 3977 if ( ( shift = document()->formatter()->formatVertically( document(), this ) ) ) {
3955 if ( p ) 3978 if ( p )
3956 p->setChanged( TRUE ); 3979 p->setChanged( TRUE );
3957 dy += shift; 3980 dy += shift;
3958 } 3981 }
3959 } 3982 }
3960} 3983}
3961 3984
3962void QTextParagraph::format( int start, bool doMove ) 3985void QTextParagraph::format( int start, bool doMove )
3963{ 3986{
3964 if ( !str || str->length() == 0 || !formatter() ) 3987 if ( !str || str->length() == 0 || !formatter() )
3965 return; 3988 return;
3966 3989
3967 if ( hasdoc && 3990 if ( hasdoc &&
3968 document()->preProcessor() && 3991 document()->preProcessor() &&
3969 ( needPreProcess || state == -1 ) ) 3992 ( needPreProcess || state == -1 ) )
3970 document()->preProcessor()->process( document(), this, invalid <= 0 ? 0 : invalid ); 3993 document()->preProcessor()->process( document(), this, invalid <= 0 ? 0 : invalid );
3971 needPreProcess = FALSE; 3994 needPreProcess = FALSE;
3972 3995
3973 if ( invalid == -1 ) 3996 if ( invalid == -1 )
3974 return; 3997 return;
3975 3998
3976 r.moveTopLeft( QPoint( documentX(), p ? p->r.y() + p->r.height() : documentY() ) ); 3999 r.moveTopLeft( QPoint( documentX(), p ? p->r.y() + p->r.height() : documentY() ) );
3977 if ( p ) 4000 if ( p )
3978 p->lastInFrame = FALSE; 4001 p->lastInFrame = FALSE;
3979 4002
3980 movedDown = FALSE; 4003 movedDown = FALSE;
3981 bool formattedAgain = FALSE; 4004 bool formattedAgain = FALSE;
3982 4005
3983 formatAgain: 4006 formatAgain:
3984 4007
3985 r.setWidth( documentWidth() ); 4008 r.setWidth( documentWidth() );
3986 if ( hasdoc && mFloatingItems ) { 4009 if ( hasdoc && mFloatingItems ) {
3987 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) { 4010 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) {
3988 i->ypos = r.y(); 4011 i->ypos = r.y();
3989 if ( i->placement() == QTextCustomItem::PlaceRight ) { 4012 if ( i->placement() == QTextCustomItem::PlaceRight ) {
3990 i->xpos = r.x() + r.width() - i->width; 4013 i->xpos = r.x() + r.width() - i->width;
3991 } 4014 }
3992 } 4015 }
3993 } 4016 }
3994 QMap<int, QTextLineStart*> oldLineStarts = lineStarts; 4017 QMap<int, QTextLineStart*> oldLineStarts = lineStarts;
3995 lineStarts.clear(); 4018 lineStarts.clear();
3996 int y = formatter()->format( document(), this, start, oldLineStarts ); 4019 int y = formatter()->format( document(), this, start, oldLineStarts );
3997 4020
3998 4021
3999 r.setWidth( QMAX( r.width(), formatter()->minimumWidth() ) ); 4022 r.setWidth( QMAX( r.width(), formatter()->minimumWidth() ) );
4000 4023
4001 4024
4002 QMap<int, QTextLineStart*>::Iterator it = oldLineStarts.begin(); 4025 QMap<int, QTextLineStart*>::Iterator it = oldLineStarts.begin();
4003 4026
4004 for ( ; it != oldLineStarts.end(); ++it ) 4027 for ( ; it != oldLineStarts.end(); ++it )
4005 delete *it; 4028 delete *it;
4006 4029
4007 QTextStringChar *c = 0; 4030 QTextStringChar *c = 0;
4008 // do not do this on mac, as the paragraph 4031 // do not do this on mac, as the paragraph
4009 // with has to be the full document width on mac as the selections 4032 // with has to be the full document width on mac as the selections
4010 // always extend completely to the right. This is a bit unefficient, 4033 // always extend completely to the right. This is a bit unefficient,
4011 // as this results in a bigger double buffer than needed but ok for 4034 // as this results in a bigger double buffer than needed but ok for
4012 // now. 4035 // now.
4013 if ( lineStarts.count() == 1 ) { 4036 if ( lineStarts.count() == 1 ) {
4014 if ( !string()->isBidi() ) { 4037 if ( !string()->isBidi() ) {
4015 c = &str->at( str->length() - 1 ); 4038 c = &str->at( str->length() - 1 );
4016 r.setWidth( c->x + str->width( str->length() - 1 ) ); 4039 r.setWidth( c->x + str->width( str->length() - 1 ) );
4017 } else { 4040 } else {
4018 r.setWidth( lineStarts[0]->w ); 4041 r.setWidth( lineStarts[0]->w );
4019 } 4042 }
4020 } 4043 }
4021 4044
4022 if ( !hasdoc ) { // qt_format_text bounding rect handling 4045 if ( !hasdoc ) { // qt_format_text bounding rect handling
4023 it = lineStarts.begin(); 4046 it = lineStarts.begin();
4024 int usedw = 0; 4047 int usedw = 0;
4025 for ( ; it != lineStarts.end(); ++it ) 4048 for ( ; it != lineStarts.end(); ++it )
4026 usedw = QMAX( usedw, (*it)->w ); 4049 usedw = QMAX( usedw, (*it)->w );
4027 if ( r.width() <= 0 ) { 4050 if ( r.width() <= 0 ) {
4028 // if the user specifies an invalid rect, this means that the 4051 // if the user specifies an invalid rect, this means that the
4029 // bounding box should grow to the width that the text actually 4052 // bounding box should grow to the width that the text actually
4030 // needs 4053 // needs
4031 r.setWidth( usedw ); 4054 r.setWidth( usedw );
4032 } else { 4055 } else {
4033 r.setWidth( QMIN( usedw, r.width() ) ); 4056 r.setWidth( QMIN( usedw, r.width() ) );
4034 } 4057 }
4035 } 4058 }
4036 4059
4037 if ( y != r.height() ) 4060 if ( y != r.height() )
4038 r.setHeight( y ); 4061 r.setHeight( y );
4039 4062
4040 if ( !visible ) { 4063 if ( !visible ) {
4041 r.setHeight( 0 ); 4064 r.setHeight( 0 );
4042 } else { 4065 } else {
4043 int minw = formatter()->minimumWidth(); 4066 int minw = formatter()->minimumWidth();
4044 int wused = formatter()->widthUsed(); 4067 int wused = formatter()->widthUsed();
4045 wused = QMAX( minw, wused ); 4068 wused = QMAX( minw, wused );
4046 if ( hasdoc ) { 4069 if ( hasdoc ) {
4047 document()->setMinimumWidth( minw, wused, this ); 4070 document()->setMinimumWidth( minw, wused, this );
4048 } else { 4071 } else {
4049 pseudoDocument()->minw = QMAX( pseudoDocument()->minw, minw ); 4072 pseudoDocument()->minw = QMAX( pseudoDocument()->minw, minw );
4050 pseudoDocument()->wused = QMAX( pseudoDocument()->wused, wused ); 4073 pseudoDocument()->wused = QMAX( pseudoDocument()->wused, wused );
4051 } 4074 }
4052 } 4075 }
4053 4076
4054 // do page breaks if required 4077 // do page breaks if required
4055 if ( hasdoc && document()->isPageBreakEnabled() ) { 4078 if ( hasdoc && document()->isPageBreakEnabled() ) {
4056 int shift = document()->formatter()->formatVertically( document(), this ); 4079 int shift = document()->formatter()->formatVertically( document(), this );
4057 if ( shift && !formattedAgain ) { 4080 if ( shift && !formattedAgain ) {
4058 formattedAgain = TRUE; 4081 formattedAgain = TRUE;
4059 goto formatAgain; 4082 goto formatAgain;
4060 } 4083 }
4061 } 4084 }
4062 4085
4063 if ( n && doMove && n->invalid == -1 && r.y() + r.height() != n->r.y() ) { 4086 if ( n && doMove && n->invalid == -1 && r.y() + r.height() != n->r.y() ) {
4064 int dy = ( r.y() + r.height() ) - n->r.y(); 4087 int dy = ( r.y() + r.height() ) - n->r.y();
4065 QTextParagraph *s = n; 4088 QTextParagraph *s = n;
4066 bool makeInvalid = p && p->lastInFrame; 4089 bool makeInvalid = p && p->lastInFrame;
4067 while ( s && dy ) { 4090 while ( s && dy ) {
4068 if ( !s->isFullWidth() ) 4091 if ( !s->isFullWidth() )
4069 makeInvalid = TRUE; 4092 makeInvalid = TRUE;
4070 if ( makeInvalid ) 4093 if ( makeInvalid )
4071 s->invalidate( 0 ); 4094 s->invalidate( 0 );
4072 s->move( dy ); 4095 s->move( dy );
4073 if ( s->lastInFrame ) 4096 if ( s->lastInFrame )
4074 makeInvalid = TRUE; 4097 makeInvalid = TRUE;
4075 s = s->n; 4098 s = s->n;
4076 } 4099 }
4077 } 4100 }
4078 4101
4079 firstFormat = FALSE; 4102 firstFormat = FALSE;
4080 changed = TRUE; 4103 changed = TRUE;
4081 invalid = -1; 4104 invalid = -1;
4082 //##### string()->setTextChanged( FALSE ); 4105 //##### string()->setTextChanged( FALSE );
4083} 4106}
4084 4107
4085int QTextParagraph::lineHeightOfChar( int i, int *bl, int *y ) const 4108int QTextParagraph::lineHeightOfChar( int i, int *bl, int *y ) const
4086{ 4109{
4087 if ( !isValid() ) 4110 if ( !isValid() )
4088 ( (QTextParagraph*)this )->format(); 4111 ( (QTextParagraph*)this )->format();
4089 4112
4090 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.end(); 4113 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.end();
4091 --it; 4114 --it;
4092 for ( ;; ) { 4115 for ( ;; ) {
4093 if ( i >= it.key() ) { 4116 if ( i >= it.key() ) {
4094 if ( bl ) 4117 if ( bl )
4095 *bl = ( *it )->baseLine; 4118 *bl = ( *it )->baseLine;
4096 if ( y ) 4119 if ( y )
4097 *y = ( *it )->y; 4120 *y = ( *it )->y;
4098 return ( *it )->h; 4121 return ( *it )->h;
4099 } 4122 }
4100 if ( it == lineStarts.begin() ) 4123 if ( it == lineStarts.begin() )
4101 break; 4124 break;
4102 --it; 4125 --it;
4103 } 4126 }
4104 4127
4105 owarn << "QTextParagraph::lineHeightOfChar: couldn't find lh for " << i << "" << oendl; 4128 owarn << "QTextParagraph::lineHeightOfChar: couldn't find lh for " << i << "" << oendl;
4106 return 15; 4129 return 15;
4107} 4130}
4108 4131
4109QTextStringChar *QTextParagraph::lineStartOfChar( int i, int *index, int *line ) const 4132QTextStringChar *QTextParagraph::lineStartOfChar( int i, int *index, int *line ) const
4110{ 4133{
4111 if ( !isValid() ) 4134 if ( !isValid() )
4112 ( (QTextParagraph*)this )->format(); 4135 ( (QTextParagraph*)this )->format();
4113 4136
4114 int l = (int)lineStarts.count() - 1; 4137 int l = (int)lineStarts.count() - 1;
4115 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.end(); 4138 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.end();
4116 --it; 4139 --it;
4117 for ( ;; ) { 4140 for ( ;; ) {
4118 if ( i >= it.key() ) { 4141 if ( i >= it.key() ) {
4119 if ( index ) 4142 if ( index )
4120 *index = it.key(); 4143 *index = it.key();
4121 if ( line ) 4144 if ( line )
4122 *line = l; 4145 *line = l;
4123 return &str->at( it.key() ); 4146 return &str->at( it.key() );
4124 } 4147 }
4125 if ( it == lineStarts.begin() ) 4148 if ( it == lineStarts.begin() )
4126 break; 4149 break;
4127 --it; 4150 --it;
4128 --l; 4151 --l;
4129 } 4152 }
4130 4153
4131 owarn << "QTextParagraph::lineStartOfChar: couldn't find " << i << "" << oendl; 4154 owarn << "QTextParagraph::lineStartOfChar: couldn't find " << i << "" << oendl;
4132 return 0; 4155 return 0;
4133} 4156}
4134 4157
4135int QTextParagraph::lines() const 4158int QTextParagraph::lines() const
4136{ 4159{
4137 if ( !isValid() ) 4160 if ( !isValid() )
4138 ( (QTextParagraph*)this )->format(); 4161 ( (QTextParagraph*)this )->format();
4139 4162
4140 return (int)lineStarts.count(); 4163 return (int)lineStarts.count();
4141} 4164}
4142 4165
4143QTextStringChar *QTextParagraph::lineStartOfLine( int line, int *index ) const 4166QTextStringChar *QTextParagraph::lineStartOfLine( int line, int *index ) const
4144{ 4167{
4145 if ( !isValid() ) 4168 if ( !isValid() )
4146 ( (QTextParagraph*)this )->format(); 4169 ( (QTextParagraph*)this )->format();
4147 4170
4148 if ( line >= 0 && line < (int)lineStarts.count() ) { 4171 if ( line >= 0 && line < (int)lineStarts.count() ) {
4149 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin(); 4172 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
4150 while ( line-- > 0 ) 4173 while ( line-- > 0 )
4151 ++it; 4174 ++it;
4152 int i = it.key(); 4175 int i = it.key();
4153 if ( index ) 4176 if ( index )
4154 *index = i; 4177 *index = i;
4155 return &str->at( i ); 4178 return &str->at( i );
4156 } 4179 }
4157 4180
4158 owarn << "QTextParagraph::lineStartOfLine: couldn't find " << line << "" << oendl; 4181 owarn << "QTextParagraph::lineStartOfLine: couldn't find " << line << "" << oendl;
4159 return 0; 4182 return 0;
4160} 4183}
4161 4184
4162int QTextParagraph::leftGap() const 4185int QTextParagraph::leftGap() const
4163{ 4186{
4164 if ( !isValid() ) 4187 if ( !isValid() )
4165 ( (QTextParagraph*)this )->format(); 4188 ( (QTextParagraph*)this )->format();
4166 4189
4167 int line = 0; 4190 int line = 0;
4168 int x = str->at(0).x; /* set x to x of first char */ 4191 int x = str->at(0).x; /* set x to x of first char */
4169 if ( str->isBidi() ) { 4192 if ( str->isBidi() ) {
4170 for ( int i = 1; i < str->length()-1; ++i ) 4193 for ( int i = 1; i < str->length()-1; ++i )
4171 x = QMIN(x, str->at(i).x); 4194 x = QMIN(x, str->at(i).x);
4172 return x; 4195 return x;
4173 } 4196 }
4174 4197
4175 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin(); 4198 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
4176 while (line < (int)lineStarts.count()) { 4199 while (line < (int)lineStarts.count()) {
4177 int i = it.key(); /* char index */ 4200 int i = it.key(); /* char index */
4178 x = QMIN(x, str->at(i).x); 4201 x = QMIN(x, str->at(i).x);
4179 ++it; 4202 ++it;
4180 ++line; 4203 ++line;
4181 } 4204 }
4182 return x; 4205 return x;
4183} 4206}
4184 4207
4185void QTextParagraph::setFormat( int index, int len, QTextFormat *f, bool useCollection, int flags ) 4208void QTextParagraph::setFormat( int index, int len, QTextFormat *f, bool useCollection, int flags )
4186{ 4209{
4187 if ( !f ) 4210 if ( !f )
4188 return; 4211 return;
4189 if ( index < 0 ) 4212 if ( index < 0 )
4190 index = 0; 4213 index = 0;
4191 if ( index > str->length() - 1 ) 4214 if ( index > str->length() - 1 )
4192 index = str->length() - 1; 4215 index = str->length() - 1;
4193 if ( index + len >= str->length() ) 4216 if ( index + len >= str->length() )
4194 len = str->length() - index; 4217 len = str->length() - index;
4195 4218
4196 QTextFormatCollection *fc = 0; 4219 QTextFormatCollection *fc = 0;
4197 if ( useCollection ) 4220 if ( useCollection )
4198 fc = formatCollection(); 4221 fc = formatCollection();
4199 QTextFormat *of; 4222 QTextFormat *of;
4200 for ( int i = 0; i < len; ++i ) { 4223 for ( int i = 0; i < len; ++i ) {
4201 of = str->at( i + index ).format(); 4224 of = str->at( i + index ).format();
4202 if ( !changed && f->key() != of->key() ) 4225 if ( !changed && f->key() != of->key() )
4203 changed = TRUE; 4226 changed = TRUE;
4204 if ( invalid == -1 && 4227 if ( invalid == -1 &&
4205 ( f->font().family() != of->font().family() || 4228 ( f->font().family() != of->font().family() ||
4206 f->font().pointSize() != of->font().pointSize() || 4229 f->font().pointSize() != of->font().pointSize() ||
4207 f->font().weight() != of->font().weight() || 4230 f->font().weight() != of->font().weight() ||
4208 f->font().italic() != of->font().italic() || 4231 f->font().italic() != of->font().italic() ||
4209 f->vAlign() != of->vAlign() ) ) { 4232 f->vAlign() != of->vAlign() ) ) {
4210 invalidate( 0 ); 4233 invalidate( 0 );
4211 } 4234 }
4212 if ( flags == -1 || flags == QTextFormat::Format || !fc ) { 4235 if ( flags == -1 || flags == QTextFormat::Format || !fc ) {
4213 if ( fc ) 4236 if ( fc )
4214 f = fc->format( f ); 4237 f = fc->format( f );
4215 str->setFormat( i + index, f, useCollection ); 4238 str->setFormat( i + index, f, useCollection );
4216 } else { 4239 } else {
4217 QTextFormat *fm = fc->format( of, f, flags ); 4240 QTextFormat *fm = fc->format( of, f, flags );
4218 str->setFormat( i + index, fm, useCollection ); 4241 str->setFormat( i + index, fm, useCollection );
4219 } 4242 }
4220 } 4243 }
4221} 4244}
4222 4245
4223void QTextParagraph::indent( int *oldIndent, int *newIndent ) 4246void QTextParagraph::indent( int *oldIndent, int *newIndent )
4224{ 4247{
4225 if ( !hasdoc || !document()->indent() || isListItem() ) { 4248 if ( !hasdoc || !document()->indent() || isListItem() ) {
4226 if ( oldIndent ) 4249 if ( oldIndent )
4227 *oldIndent = 0; 4250 *oldIndent = 0;
4228 if ( newIndent ) 4251 if ( newIndent )
4229 *newIndent = 0; 4252 *newIndent = 0;
4230 if ( oldIndent && newIndent ) 4253 if ( oldIndent && newIndent )
4231 *newIndent = *oldIndent; 4254 *newIndent = *oldIndent;
4232 return; 4255 return;
4233 } 4256 }
4234 document()->indent()->indent( document(), this, oldIndent, newIndent ); 4257 document()->indent()->indent( document(), this, oldIndent, newIndent );
4235} 4258}
4236 4259
4237void QTextParagraph::paint( QPainter &painter, const QColorGroup &cg, QTextCursor *cursor, bool drawSelections, 4260void QTextParagraph::paint( QPainter &painter, const QColorGroup &cg, QTextCursor *cursor, bool drawSelections,
4238 int clipx, int clipy, int clipw, int cliph ) 4261 int clipx, int clipy, int clipw, int cliph )
4239{ 4262{
4240 if ( !visible ) 4263 if ( !visible )
4241 return; 4264 return;
4242 QTextStringChar *chr = 0; 4265 QTextStringChar *chr = 0;
4243 int i, y, h, baseLine, xstart, xend; 4266 int i, y, h, baseLine, xstart, xend;
4244 i = y =h = baseLine = 0; 4267 i = y =h = baseLine = 0;
4245 QRect cursorRect; 4268 QRect cursorRect;
4246 drawSelections &= ( mSelections != 0 ); 4269 drawSelections &= ( mSelections != 0 );
4247 // macintosh full-width selection style 4270 // macintosh full-width selection style
4248 bool fullWidthStyle = FALSE; 4271 bool fullWidthStyle = FALSE;
4249 int fullSelectionWidth = 0; 4272 int fullSelectionWidth = 0;
4250 if ( drawSelections && fullWidthStyle ) 4273 if ( drawSelections && fullWidthStyle )
4251 fullSelectionWidth = (hasdoc ? document()->width() : r.width()); 4274 fullSelectionWidth = (hasdoc ? document()->width() : r.width());
4252 4275
4253 QString qstr = str->toString(); 4276 QString qstr = str->toString();
4254 // ### workaround so that \n are not drawn, actually this should 4277 // ### workaround so that \n are not drawn, actually this should
4255 // be fixed in QFont somewhere (under Windows you get ugly boxes 4278 // be fixed in QFont somewhere (under Windows you get ugly boxes
4256 // otherwise) 4279 // otherwise)
4257 QChar* uc = (QChar*) qstr.unicode(); 4280 QChar* uc = (QChar*) qstr.unicode();
4258 for ( uint ii = 0; ii < qstr.length(); ii++ ) 4281 for ( uint ii = 0; ii < qstr.length(); ii++ )
4259 if ( uc[(int)ii]== '\n' || uc[(int)ii] == QChar_linesep || uc[(int)ii] == '\t' ) 4282 if ( uc[(int)ii]== '\n' || uc[(int)ii] == QChar_linesep || uc[(int)ii] == '\t' )
4260 uc[(int)ii] = 0x20; 4283 uc[(int)ii] = 0x20;
4261 4284
4262 int line = -1; 4285 int line = -1;
4263 int paintStart = 0; 4286 int paintStart = 0;
4264 int selection = -1; 4287 int selection = -1;
4265 for ( i = 0; i < length(); i++ ) { 4288 for ( i = 0; i < length(); i++ ) {
4266 chr = at( i ); 4289 chr = at( i );
4267 4290
4268 // we flush at end of document 4291 // we flush at end of document
4269 bool flush = i== length()-1; 4292 bool flush = i== length()-1;
4270 bool selectionStateChanged = FALSE; 4293 bool selectionStateChanged = FALSE;
4271 if ( !flush ) { 4294 if ( !flush ) {
4272 QTextStringChar *nextchr = at( i+1 ); 4295 QTextStringChar *nextchr = at( i+1 );
4273 // we flush at end of line 4296 // we flush at end of line
4274 flush |= nextchr->lineStart; 4297 flush |= nextchr->lineStart;
4275 // we flush on format changes 4298 // we flush on format changes
4276 flush |= ( nextchr->format() != chr->format() ); 4299 flush |= ( nextchr->format() != chr->format() );
4277 // we flush on anchor changes 4300 // we flush on anchor changes
4278 flush |= ( nextchr->isAnchor() != chr->isAnchor() ); 4301 flush |= ( nextchr->isAnchor() != chr->isAnchor() );
4279 // we flush on start of run 4302 // we flush on start of run
4280 flush |= nextchr->startOfRun; 4303 flush |= nextchr->startOfRun;
4281 // we flush on bidi changes 4304 // we flush on bidi changes
4282 flush |= ( nextchr->rightToLeft != chr->rightToLeft ); 4305 flush |= ( nextchr->rightToLeft != chr->rightToLeft );
4283 // we flush on tab 4306 // we flush on tab
4284 flush |= ( chr->c == '\t' ); 4307 flush |= ( chr->c == '\t' );
4285 // we flush on soft hypens 4308 // we flush on soft hypens
4286 flush |= ( chr->c.unicode() == 0xad ); 4309 flush |= ( chr->c.unicode() == 0xad );
4287 // we flush on custom items 4310 // we flush on custom items
4288 flush |= chr->isCustom(); 4311 flush |= chr->isCustom();
4289 // we flush before custom items 4312 // we flush before custom items
4290 flush |= nextchr->isCustom(); 4313 flush |= nextchr->isCustom();
4291 // when painting justified, we flush on spaces 4314 // when painting justified, we flush on spaces
4292 if ((alignment() & Qt3::AlignJustify) == Qt3::AlignJustify ) 4315 if ((alignment() & Qt3::AlignJustify) == Qt3::AlignJustify )
4293 flush |= QTextFormatter::isBreakable( str, i ); 4316 flush |= QTextFormatter::isBreakable( str, i );
4294 // we flush when the string is getting too long 4317 // we flush when the string is getting too long
4295 flush |= ( i - paintStart >= 256 ); 4318 flush |= ( i - paintStart >= 256 );
4296 // we flush when the selection state changes 4319 // we flush when the selection state changes
4297 if ( drawSelections ) { 4320 if ( drawSelections ) {
4298 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->begin(); 4321 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->begin();
4299 it != mSelections->end(); ++it ) 4322 it != mSelections->end(); ++it )
4300 selectionStateChanged |=( (*it).start == i || (*it).start == i+1 || (*it).end == i+1 ); 4323 selectionStateChanged |=( (*it).start == i || (*it).start == i+1 || (*it).end == i+1 );
4301 flush |= selectionStateChanged; 4324 flush |= selectionStateChanged;
4302 } 4325 }
4303 } 4326 }
4304 4327
4305 // init a new line 4328 // init a new line
4306 if ( chr->lineStart ) { 4329 if ( chr->lineStart ) {
4307 if (fullWidthStyle && drawSelections && selection >= 0) 4330 if (fullWidthStyle && drawSelections && selection >= 0)
4308 painter.fillRect( xend, y, fullSelectionWidth - xend, h, 4331 painter.fillRect( xend, y, fullSelectionWidth - xend, h,
4309 (selection == QTextDocument::Standard || !hasdoc) ? 4332 (selection == QTextDocument::Standard || !hasdoc) ?
4310 cg.color( QColorGroup::Highlight ) : 4333 cg.color( QColorGroup::Highlight ) :
4311 document()->selectionColor( selection ) ); 4334 document()->selectionColor( selection ) );
4312 ++line; 4335 ++line;
4313 paintStart = i; 4336 paintStart = i;
4314 lineInfo( line, y, h, baseLine ); 4337 lineInfo( line, y, h, baseLine );
4315 if ( clipy != -1 && cliph != 0 && y + r.y() - h > clipy + cliph ) { // outside clip area, leave 4338 if ( clipy != -1 && cliph != 0 && y + r.y() - h > clipy + cliph ) { // outside clip area, leave
4316 break; 4339 break;
4317 } 4340 }
4318 4341
4319 // if this is the first line and we are a list item, draw the the bullet label 4342 // if this is the first line and we are a list item, draw the the bullet label
4320 if ( line == 0 && isListItem() ) 4343 if ( line == 0 && isListItem() )
4321 drawLabel( &painter, chr->x, y, 0, 0, baseLine, cg ); 4344 drawLabel( &painter, chr->x, y, 0, 0, baseLine, cg );
4322 } 4345 }
4323 4346
4324 // check for cursor mark 4347 // check for cursor mark
4325 if ( cursor && this == cursor->paragraph() && i == cursor->index() ) { 4348 if ( cursor && this == cursor->paragraph() && i == cursor->index() ) {
4326 QTextStringChar *c = i == 0 ? chr : chr - 1; 4349 QTextStringChar *c = i == 0 ? chr : chr - 1;
4327 cursorRect.setRect( cursor->x() , y + baseLine - c->format()->ascent(), 4350 cursorRect.setRect( cursor->x() , y + baseLine - c->format()->ascent(),
4328 1, c->format()->height() ); 4351 1, c->format()->height() );
4329 } 4352 }
4330 4353
4331 // check if we are in a selection and store which one it is 4354 // check if we are in a selection and store which one it is
4332 selection = -1; 4355 selection = -1;
4333 if ( drawSelections ) { 4356 if ( drawSelections ) {
4334 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->begin(); 4357 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->begin();
4335 it != mSelections->end(); ++it ) 4358 it != mSelections->end(); ++it )
4336 if ( (*it).start <= i && i < (*it).end + ( (*it).end == length()-1 && n && n->hasSelection(it.key()) ) ? 1:0 4359 if ( (*it).start <= i && i < (*it).end + ( (*it).end == length()-1 && n && n->hasSelection(it.key()) ) ? 1:0
4337 // exclude the standard selection from printing 4360 // exclude the standard selection from printing
4338 && (it.key() != QTextDocument::Standard || !is_printer( &painter) ) ) { 4361 && (it.key() != QTextDocument::Standard || !is_printer( &painter) ) ) {
4339 selection = it.key(); 4362 selection = it.key();
4340 break; 4363 break;
4341 } 4364 }
4342 } 4365 }
4343 4366
4344 if ( flush ) { // something changed, draw what we have so far 4367 if ( flush ) { // something changed, draw what we have so far
4345 if ( chr->rightToLeft ) { 4368 if ( chr->rightToLeft ) {
4346 xstart = chr->x; 4369 xstart = chr->x;
4347 xend = at( paintStart )->x + str->width( paintStart ); 4370 xend = at( paintStart )->x + str->width( paintStart );
4348 } else { 4371 } else {
4349 xstart = at( paintStart )->x; 4372 xstart = at( paintStart )->x;
4350 if ( !selectionStateChanged && i < length() - 1 && !str->at( i + 1 ).lineStart ) 4373 if ( !selectionStateChanged && i < length() - 1 && !str->at( i + 1 ).lineStart )
4351 xend = str->at( i + 1 ).x; 4374 xend = str->at( i + 1 ).x;
4352 else 4375 else
4353 xend = chr->x + str->width( i ); 4376 xend = chr->x + str->width( i );
4354 } 4377 }
4355 4378
4356 if ( (clipx == -1 || clipw == -1) || (xend >= clipx && xstart <= clipx + clipw) ) { 4379 if ( (clipx == -1 || clipw == -1) || (xend >= clipx && xstart <= clipx + clipw) ) {
4357 if ( !chr->isCustom() ) 4380 if ( !chr->isCustom() )
4358 drawString( painter, qstr, paintStart, i - paintStart + 1, xstart, y, 4381 drawString( painter, qstr, paintStart, i - paintStart + 1, xstart, y,
4359 baseLine, xend-xstart, h, selection, 4382 baseLine, xend-xstart, h, selection,
4360 chr, cg, chr->rightToLeft ); 4383 chr, cg, chr->rightToLeft );
4361 else if ( chr->customItem()->placement() == QTextCustomItem::PlaceInline ) 4384 else if ( chr->customItem()->placement() == QTextCustomItem::PlaceInline )
4362 chr->customItem()->draw( &painter, chr->x, y, 4385 chr->customItem()->draw( &painter, chr->x, y,
4363 clipx == -1 ? clipx : (clipx - r.x()), 4386 clipx == -1 ? clipx : (clipx - r.x()),
4364 clipy == -1 ? clipy : (clipy - r.y()), 4387 clipy == -1 ? clipy : (clipy - r.y()),
4365 clipw, cliph, cg, selection >= 0 ); 4388 clipw, cliph, cg, selection >= 0 );
4366 } 4389 }
4367 paintStart = i+1; 4390 paintStart = i+1;
4368 } 4391 }
4369 4392
4370 } 4393 }
4371 4394
4372 if (fullWidthStyle && drawSelections && selection >= 0 && next() && next()->mSelections) 4395 if (fullWidthStyle && drawSelections && selection >= 0 && next() && next()->mSelections)
4373 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = next()->mSelections->begin(); 4396 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = next()->mSelections->begin();
4374 it != next()->mSelections->end(); ++it ) 4397 it != next()->mSelections->end(); ++it )
4375 if (((*it).start) == 0) { 4398 if (((*it).start) == 0) {
4376 painter.fillRect( xend, y, fullSelectionWidth - xend, h, 4399 painter.fillRect( xend, y, fullSelectionWidth - xend, h,
4377 (selection == QTextDocument::Standard || !hasdoc) ? 4400 (selection == QTextDocument::Standard || !hasdoc) ?
4378 cg.color( QColorGroup::Highlight ) : 4401 cg.color( QColorGroup::Highlight ) :
4379 document()->selectionColor( selection ) ); 4402 document()->selectionColor( selection ) );
4380 break; 4403 break;
4381 } 4404 }
4382 4405
4383 // time to draw the cursor 4406 // time to draw the cursor
4384 const int cursor_extent = 4; 4407 const int cursor_extent = 4;
4385 if ( !cursorRect.isNull() && cursor && 4408 if ( !cursorRect.isNull() && cursor &&
4386 ((clipx == -1 || clipw == -1) || (cursorRect.right()+cursor_extent >= clipx && cursorRect.left()-cursor_extent <= clipx + clipw)) ) { 4409 ((clipx == -1 || clipw == -1) || (cursorRect.right()+cursor_extent >= clipx && cursorRect.left()-cursor_extent <= clipx + clipw)) ) {
4387 painter.fillRect( cursorRect, cg.color( QColorGroup::Text ) ); 4410 painter.fillRect( cursorRect, cg.color( QColorGroup::Text ) );
4388 painter.save(); 4411 painter.save();
4389 if ( string()->isBidi() ) { 4412 if ( string()->isBidi() ) {
4390 if ( at( cursor->index() )->rightToLeft ) { 4413 if ( at( cursor->index() )->rightToLeft ) {
4391 painter.setPen( Qt::black ); 4414 painter.setPen( Qt::black );
4392 painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); 4415 painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 );
4393 painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); 4416 painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 );
4394 } else { 4417 } else {
4395 painter.setPen( Qt::black ); 4418 painter.setPen( Qt::black );
4396 painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); 4419 painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 );
4397 painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); 4420 painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 );
4398 } 4421 }
4399 } 4422 }
4400 painter.restore(); 4423 painter.restore();
4401 } 4424 }
4402} 4425}
4403 4426
4404//#define BIDI_DEBUG 4427//#define BIDI_DEBUG
4405 4428
4406void QTextParagraph::drawString( QPainter &painter, const QString &s, int start, int len, int xstart, 4429void QTextParagraph::drawString( QPainter &painter, const QString &s, int start, int len, int xstart,
4407 int y, int baseLine, int w, int h, int selection, 4430 int y, int baseLine, int w, int h, int selection,
4408 QTextStringChar *formatChar, const QColorGroup& cg, 4431 QTextStringChar *formatChar, const QColorGroup& cg,
4409 bool rightToLeft ) 4432 bool rightToLeft )
4410{ 4433{
4411 int i = start + len - 1; 4434 int i = start + len - 1;
4412 bool plainText = hasdoc ? document()->textFormat() == Qt::PlainText : FALSE; 4435 bool plainText = hasdoc ? document()->textFormat() == Qt::PlainText : FALSE;
4413 QTextFormat* format = formatChar->format(); 4436 QTextFormat* format = formatChar->format();
4414 QString str( s ); 4437 QString str( s );
4415 if ( str[ (int)str.length() - 1 ].unicode() == 0xad ) 4438 if ( str[ (int)str.length() - 1 ].unicode() == 0xad )
4416 str.remove( str.length() - 1, 1 ); 4439 str.remove( str.length() - 1, 1 );
4417 if ( !plainText || hasdoc && format->color() != document()->formatCollection()->defaultFormat()->color() ) 4440 if ( !plainText || hasdoc && format->color() != document()->formatCollection()->defaultFormat()->color() )
4418 painter.setPen( QPen( format->color() ) ); 4441 painter.setPen( QPen( format->color() ) );
4419 else 4442 else
4420 painter.setPen( cg.text() ); 4443 painter.setPen( cg.text() );
4421 painter.setFont( format->font() ); 4444 painter.setFont( format->font() );
4422 4445
4423 if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() ) { 4446 if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() ) {
4424 if ( format->useLinkColor() ) { 4447 if ( format->useLinkColor() ) {
4425 if ( document()->linkColor.isValid() ) 4448 if ( document()->linkColor.isValid() )
4426 painter.setPen( document()->linkColor ); 4449 painter.setPen( document()->linkColor );
4427 else 4450 else
4428 painter.setPen( QPen( Qt::blue ) ); 4451 painter.setPen( QPen( Qt::blue ) );
4429 } 4452 }
4430 if ( document()->underlineLinks() ) { 4453 if ( document()->underlineLinks() ) {
4431 QFont fn = format->font(); 4454 QFont fn = format->font();
4432 fn.setUnderline( TRUE ); 4455 fn.setUnderline( TRUE );
4433 painter.setFont( fn ); 4456 painter.setFont( fn );
4434 } 4457 }
4435 } 4458 }
4436 4459
4437 if ( selection >= 0 ) { 4460 if ( selection >= 0 ) {
4438 if ( !hasdoc || document()->invertSelectionText( selection ) ) 4461 if ( !hasdoc || document()->invertSelectionText( selection ) )
4439 painter.setPen( cg.color( QColorGroup::HighlightedText ) ); 4462 painter.setPen( cg.color( QColorGroup::HighlightedText ) );
4440 painter.fillRect( xstart, y, w, h, 4463 painter.fillRect( xstart, y, w, h,
4441 (selection == QTextDocument::Standard || !hasdoc) ? 4464 (selection == QTextDocument::Standard || !hasdoc) ?
4442 cg.color( QColorGroup::Highlight ) : document()->selectionColor( selection ) ); 4465 cg.color( QColorGroup::Highlight ) : document()->selectionColor( selection ) );
4443 } 4466 }
4444 4467
4445 if ( str[ start ] != '\t' && str[ start ].unicode() != 0xad ) { 4468 if ( str[ start ] != '\t' && str[ start ].unicode() != 0xad ) {
4446 if ( format->vAlign() == QTextFormat::AlignNormal ) { 4469 if ( format->vAlign() == QTextFormat::AlignNormal ) {
4447 painter.drawText( xstart, y + baseLine, str.mid( start ), len ); 4470 painter.drawText( xstart, y + baseLine, str.mid( start ), len );
4448#ifdef BIDI_DEBUG 4471#ifdef BIDI_DEBUG
4449 painter.save(); 4472 painter.save();
4450 painter.setPen ( Qt::red ); 4473 painter.setPen ( Qt::red );
4451 painter.drawLine( xstart, y, xstart, y + baseLine ); 4474 painter.drawLine( xstart, y, xstart, y + baseLine );
4452 painter.drawLine( xstart, y + baseLine/2, xstart + 10, y + baseLine/2 ); 4475 painter.drawLine( xstart, y + baseLine/2, xstart + 10, y + baseLine/2 );
4453 int w = 0; 4476 int w = 0;
4454 int i = 0; 4477 int i = 0;
4455 while( i < len ) 4478 while( i < len )
4456 w += painter.fontMetrics().charWidth( str, start + i++ ); 4479 w += painter.fontMetrics().charWidth( str, start + i++ );
4457 painter.setPen ( Qt::blue ); 4480 painter.setPen ( Qt::blue );
4458 painter.drawLine( xstart + w - 1, y, xstart + w - 1, y + baseLine ); 4481 painter.drawLine( xstart + w - 1, y, xstart + w - 1, y + baseLine );
4459 painter.drawLine( xstart + w - 1, y + baseLine/2, xstart + w - 1 - 10, y + baseLine/2 ); 4482 painter.drawLine( xstart + w - 1, y + baseLine/2, xstart + w - 1 - 10, y + baseLine/2 );
4460 painter.restore(); 4483 painter.restore();
4461#endif 4484#endif
4462 } else if ( format->vAlign() == QTextFormat::AlignSuperScript ) { 4485 } else if ( format->vAlign() == QTextFormat::AlignSuperScript ) {
4463 QFont f( painter.font() ); 4486 QFont f( painter.font() );
4464 if ( format->fontSizesInPixels() ) 4487 if ( format->fontSizesInPixels() )
4465 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 4488 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
4466 else 4489 else
4467 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 4490 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
4468 painter.setFont( f ); 4491 painter.setFont( f );
4469 painter.drawText( xstart, y + baseLine - ( painter.fontMetrics().height() / 2 ), 4492 painter.drawText( xstart, y + baseLine - ( painter.fontMetrics().height() / 2 ),
4470 str.mid( start ), len ); 4493 str.mid( start ), len );
4471 } else if ( format->vAlign() == QTextFormat::AlignSubScript ) { 4494 } else if ( format->vAlign() == QTextFormat::AlignSubScript ) {
4472 QFont f( painter.font() ); 4495 QFont f( painter.font() );
4473 if ( format->fontSizesInPixels() ) 4496 if ( format->fontSizesInPixels() )
4474 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 4497 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
4475 else 4498 else
4476 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 4499 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
4477 painter.setFont( f ); 4500 painter.setFont( f );
4478 painter.drawText( xstart, y + baseLine + painter.fontMetrics().height() / 6, str.mid( start ), len ); 4501 painter.drawText( xstart, y + baseLine + painter.fontMetrics().height() / 6, str.mid( start ), len );
4479 } 4502 }
4480 } 4503 }
4481 if ( i + 1 < length() && at( i + 1 )->lineStart && at( i )->c.unicode() == 0xad ) { 4504 if ( i + 1 < length() && at( i + 1 )->lineStart && at( i )->c.unicode() == 0xad ) {
4482 painter.drawText( xstart + w, y + baseLine, "\xad" ); 4505 painter.drawText( xstart + w, y + baseLine, "\xad" );
4483 } 4506 }
4484 if ( format->isMisspelled() ) { 4507 if ( format->isMisspelled() ) {
4485 painter.save(); 4508 painter.save();
4486 painter.setPen( QPen( Qt::red, 1, Qt::DotLine ) ); 4509 painter.setPen( QPen( Qt::red, 1, Qt::DotLine ) );
4487 painter.drawLine( xstart, y + baseLine + 1, xstart + w, y + baseLine + 1 ); 4510 painter.drawLine( xstart, y + baseLine + 1, xstart + w, y + baseLine + 1 );
4488 painter.restore(); 4511 painter.restore();
4489 } 4512 }
4490 4513
4491 i -= len; 4514 i -= len;
4492 4515
4493 if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() && 4516 if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() &&
4494 document()->focusIndicator.parag == this && 4517 document()->focusIndicator.parag == this &&
4495 ( document()->focusIndicator.start >= i && 4518 ( document()->focusIndicator.start >= i &&
4496 document()->focusIndicator.start + document()->focusIndicator.len <= i + len || 4519 document()->focusIndicator.start + document()->focusIndicator.len <= i + len ||
4497 document()->focusIndicator.start <= i && 4520 document()->focusIndicator.start <= i &&
4498 document()->focusIndicator.start + document()->focusIndicator.len >= i + len ) ) { 4521 document()->focusIndicator.start + document()->focusIndicator.len >= i + len ) ) {
4499 painter.drawWinFocusRect( QRect( xstart, y, w, h ) ); 4522 painter.drawWinFocusRect( QRect( xstart, y, w, h ) );
4500 } 4523 }
4501 4524
4502} 4525}
4503 4526
4504void QTextParagraph::drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg ) 4527void QTextParagraph::drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg )
4505{ 4528{
4506 QRect r ( x, y, w, h ); 4529 QRect r ( x, y, w, h );
4507 QStyleSheetItem::ListStyle s = listStyle(); 4530 QStyleSheetItem::ListStyle s = listStyle();
4508 4531
4509 p->save(); 4532 p->save();
4510 QTextFormat *format = at( 0 )->format(); 4533 QTextFormat *format = at( 0 )->format();
4511 if ( format ) { 4534 if ( format ) {
4512 p->setPen( format->color() ); 4535 p->setPen( format->color() );
4513 p->setFont( format->font() ); 4536 p->setFont( format->font() );
4514 } 4537 }
4515 QFontMetrics fm( p->fontMetrics() ); 4538 QFontMetrics fm( p->fontMetrics() );
4516 int size = fm.lineSpacing() / 3; 4539 int size = fm.lineSpacing() / 3;
4517 4540
4518 switch ( s ) { 4541 switch ( s ) {
4519 case QStyleSheetItem::ListDecimal: 4542 case QStyleSheetItem::ListDecimal:
4520 case QStyleSheetItem::ListLowerAlpha: 4543 case QStyleSheetItem::ListLowerAlpha:
4521 case QStyleSheetItem::ListUpperAlpha: 4544 case QStyleSheetItem::ListUpperAlpha:
4522 { 4545 {
4523 if ( list_val == -1 ) { // uninitialised list value, calcluate the right one 4546 if ( list_val == -1 ) { // uninitialised list value, calcluate the right one
4524 int depth = listDepth(); 4547 int depth = listDepth();
4525 list_val--; 4548 list_val--;
4526 // ### evil, square and expensive. This needs to be done when formatting, not when painting 4549 // ### evil, square and expensive. This needs to be done when formatting, not when painting
4527 QTextParagraph* s = prev(); 4550 QTextParagraph* s = prev();
4528 int depth_s; 4551 int depth_s;
4529 while ( s && (depth_s = s->listDepth()) >= depth ) { 4552 while ( s && (depth_s = s->listDepth()) >= depth ) {
4530 if ( depth_s == depth && s->isListItem() ) 4553 if ( depth_s == depth && s->isListItem() )
4531 list_val--; 4554 list_val--;
4532 s = s->prev(); 4555 s = s->prev();
4533 } 4556 }
4534 } 4557 }
4535 4558
4536 int n = list_val; 4559 int n = list_val;
4537 if ( n < -1 ) 4560 if ( n < -1 )
4538 n = -n - 1; 4561 n = -n - 1;
4539 QString l; 4562 QString l;
4540 switch ( s ) { 4563 switch ( s ) {
4541 case QStyleSheetItem::ListLowerAlpha: 4564 case QStyleSheetItem::ListLowerAlpha:
4542 if ( n < 27 ) { 4565 if ( n < 27 ) {
4543 l = QChar( ('a' + (char) (n-1))); 4566 l = QChar( ('a' + (char) (n-1)));
4544 break; 4567 break;
4545 } 4568 }
4546 case QStyleSheetItem::ListUpperAlpha: 4569 case QStyleSheetItem::ListUpperAlpha:
4547 if ( n < 27 ) { 4570 if ( n < 27 ) {
4548 l = QChar( ('A' + (char) (n-1))); 4571 l = QChar( ('A' + (char) (n-1)));
4549 break; 4572 break;
4550 } 4573 }
4551 break; 4574 break;
4552 default: //QStyleSheetItem::ListDecimal: 4575 default: //QStyleSheetItem::ListDecimal:
4553 l.setNum( n ); 4576 l.setNum( n );
4554 break; 4577 break;
4555 } 4578 }
4556 l += QString::fromLatin1(". "); 4579 l += QString::fromLatin1(". ");
4557 p->drawText( r.right() - fm.width( l ), r.top() + base, l ); 4580 p->drawText( r.right() - fm.width( l ), r.top() + base, l );
4558 } 4581 }
4559 break; 4582 break;
4560 case QStyleSheetItem::ListSquare: 4583 case QStyleSheetItem::ListSquare:
4561 { 4584 {
4562 QRect er( r.right() - size * 2, r.top() + fm.height() / 2 - size / 2, size, size ); 4585 QRect er( r.right() - size * 2, r.top() + fm.height() / 2 - size / 2, size, size );
4563 p->fillRect( er , cg.brush( QColorGroup::Text ) ); 4586 p->fillRect( er , cg.brush( QColorGroup::Text ) );
4564 } 4587 }
4565 break; 4588 break;
4566 case QStyleSheetItem::ListCircle: 4589 case QStyleSheetItem::ListCircle:
4567 { 4590 {
4568 QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size); 4591 QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size);
4569 p->drawEllipse( er ); 4592 p->drawEllipse( er );
4570 } 4593 }
4571 break; 4594 break;
4572 case QStyleSheetItem::ListDisc: 4595 case QStyleSheetItem::ListDisc:
4573 default: 4596 default:
4574 { 4597 {
4575 p->setBrush( cg.brush( QColorGroup::Text )); 4598 p->setBrush( cg.brush( QColorGroup::Text ));
4576 QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size); 4599 QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size);
4577 p->drawEllipse( er ); 4600 p->drawEllipse( er );
4578 p->setBrush( Qt::NoBrush ); 4601 p->setBrush( Qt::NoBrush );
4579 } 4602 }
4580 break; 4603 break;
4581 } 4604 }
4582 4605
4583 p->restore(); 4606 p->restore();
4584} 4607}
4585 4608
4586void QTextParagraph::readStyleInformation( QDataStream& stream ) 4609void QTextParagraph::readStyleInformation( QDataStream& stream )
4587{ 4610{
4588 int int_align, int_lstyle; 4611 int int_align, int_lstyle;
4589 uchar uchar_litem, uchar_rtext, uchar_dir; 4612 uchar uchar_litem, uchar_rtext, uchar_dir;
4590 stream >> int_align >> int_lstyle >> utm >> ubm >> ulm >> urm >> uflm 4613 stream >> int_align >> int_lstyle >> utm >> ubm >> ulm >> urm >> uflm
4591 >> ulinespacing >> ldepth >> uchar_litem >> uchar_rtext >> uchar_dir; 4614 >> ulinespacing >> ldepth >> uchar_litem >> uchar_rtext >> uchar_dir;
4592 align = int_align; lstyle = (QStyleSheetItem::ListStyle) int_lstyle; 4615 align = int_align; lstyle = (QStyleSheetItem::ListStyle) int_lstyle;
4593 litem = uchar_litem; rtext = uchar_rtext; str->setDirection( (QChar::Direction)uchar_dir ); 4616 litem = uchar_litem; rtext = uchar_rtext; str->setDirection( (QChar::Direction)uchar_dir );
4594 QTextParagraph* s = prev() ? prev() : this; 4617 QTextParagraph* s = prev() ? prev() : this;
4595 while ( s ) { 4618 while ( s ) {
4596 s->invalidate( 0 ); 4619 s->invalidate( 0 );
4597 s = s->next(); 4620 s = s->next();
4598 } 4621 }
4599} 4622}
4600 4623
4601void QTextParagraph::writeStyleInformation( QDataStream& stream ) const 4624void QTextParagraph::writeStyleInformation( QDataStream& stream ) const
4602{ 4625{
4603 stream << (int) align << (int) lstyle << utm << ubm << ulm << urm << uflm << ulinespacing << ldepth << (uchar)litem << (uchar)rtext << (uchar)str->direction(); 4626 stream << (int) align << (int) lstyle << utm << ubm << ulm << urm << uflm << ulinespacing << ldepth << (uchar)litem << (uchar)rtext << (uchar)str->direction();
4604} 4627}
4605 4628
4606 4629
4607 4630
4608void QTextParagraph::setListDepth( int depth ) { 4631void QTextParagraph::setListDepth( int depth ) {
4609 if ( !hasdoc || depth == ldepth ) 4632 if ( !hasdoc || depth == ldepth )
4610 return; 4633 return;
4611 ldepth = depth; 4634 ldepth = depth;
4612 QTextParagraph* s = prev() ? prev() : this; 4635 QTextParagraph* s = prev() ? prev() : this;
4613 while ( s ) { 4636 while ( s ) {
4614 s->invalidate( 0 ); 4637 s->invalidate( 0 );
4615 s = s->next(); 4638 s = s->next();
4616 } 4639 }
4617} 4640}
4618 4641
4619int *QTextParagraph::tabArray() const 4642int *QTextParagraph::tabArray() const
4620{ 4643{
4621 int *ta = tArray; 4644 int *ta = tArray;
4622 if ( !ta && hasdoc ) 4645 if ( !ta && hasdoc )
4623 ta = document()->tabArray(); 4646 ta = document()->tabArray();
4624 return ta; 4647 return ta;
4625} 4648}
4626 4649
4627int QTextParagraph::nextTab( int, int x ) 4650int QTextParagraph::nextTab( int, int x )
4628{ 4651{
4629 int *ta = tArray; 4652 int *ta = tArray;
4630 if ( hasdoc ) { 4653 if ( hasdoc ) {
4631 if ( !ta ) 4654 if ( !ta )
4632 ta = document()->tabArray(); 4655 ta = document()->tabArray();
4633 tabStopWidth = document()->tabStopWidth(); 4656 tabStopWidth = document()->tabStopWidth();
4634 } 4657 }
4635 if ( ta ) { 4658 if ( ta ) {
4636 int i = 0; 4659 int i = 0;
4637 while ( ta[ i ] ) { 4660 while ( ta[ i ] ) {
4638 if ( ta[ i ] >= x ) 4661 if ( ta[ i ] >= x )
4639 return tArray[ i ]; 4662 return tArray[ i ];
4640 ++i; 4663 ++i;
4641 } 4664 }
4642 return tArray[ 0 ]; 4665 return tArray[ 0 ];
4643 } else { 4666 } else {
4644 int d; 4667 int d;
4645 if ( tabStopWidth != 0 ) 4668 if ( tabStopWidth != 0 )
4646 d = x / tabStopWidth; 4669 d = x / tabStopWidth;
4647 else 4670 else
4648 return x; 4671 return x;
4649 return tabStopWidth * ( d + 1 ); 4672 return tabStopWidth * ( d + 1 );
4650 } 4673 }
4651} 4674}
4652 4675
4653void QTextParagraph::adjustToPainter( QPainter *p ) 4676void QTextParagraph::adjustToPainter( QPainter *p )
4654{ 4677{
4655 for ( int i = 0; i < length(); ++i ) { 4678 for ( int i = 0; i < length(); ++i ) {
4656 if ( at( i )->isCustom() ) 4679 if ( at( i )->isCustom() )
4657 at( i )->customItem()->adjustToPainter( p ); 4680 at( i )->customItem()->adjustToPainter( p );
4658 } 4681 }
4659} 4682}
4660 4683
4661QTextFormatCollection *QTextParagraph::formatCollection() const 4684QTextFormatCollection *QTextParagraph::formatCollection() const
4662{ 4685{
4663 if ( hasdoc ) 4686 if ( hasdoc )
4664 return document()->formatCollection(); 4687 return document()->formatCollection();
4665 if ( !qFormatCollection ) { 4688 if ( !qFormatCollection ) {
4666 qFormatCollection = new QTextFormatCollection; 4689 qFormatCollection = new QTextFormatCollection;
4667 static QSingleCleanupHandler<QTextFormatCollection> qtfCleanup; 4690 static QSingleCleanupHandler<QTextFormatCollection> qtfCleanup;
4668 qtfCleanup.set( &qFormatCollection ); 4691 qtfCleanup.set( &qFormatCollection );
4669 } 4692 }
4670 return qFormatCollection; 4693 return qFormatCollection;
4671} 4694}
4672 4695
4673QString QTextParagraph::richText() const 4696QString QTextParagraph::richText() const
4674{ 4697{
4675 QString s; 4698 QString s;
4676 QTextStringChar *formatChar = 0; 4699 QTextStringChar *formatChar = 0;
4677 QString spaces; 4700 QString spaces;
4678 bool doStart = richTextExportStart && richTextExportStart->paragraph() == this; 4701 bool doStart = richTextExportStart && richTextExportStart->paragraph() == this;
4679 bool doEnd = richTextExportEnd && richTextExportEnd->paragraph() == this; 4702 bool doEnd = richTextExportEnd && richTextExportEnd->paragraph() == this;
4680 int i; 4703 int i;
4681 for ( i = 0; i < length()-1; ++i ) { 4704 for ( i = 0; i < length()-1; ++i ) {
4682 if ( doStart && i && richTextExportStart->index() == i ) 4705 if ( doStart && i && richTextExportStart->index() == i )
4683 s += "<selstart/>"; 4706 s += "<selstart/>";
4684 if ( doEnd && richTextExportEnd->index() == i ) 4707 if ( doEnd && richTextExportEnd->index() == i )
4685 s += "<selend/>"; 4708 s += "<selend/>";
4686 QTextStringChar *c = &str->at( i ); 4709 QTextStringChar *c = &str->at( i );
4687 if ( c->isAnchor() && !c->anchorName().isEmpty() ) { 4710 if ( c->isAnchor() && !c->anchorName().isEmpty() ) {
4688 if ( c->anchorName().contains( '#' ) ) { 4711 if ( c->anchorName().contains( '#' ) ) {
4689 QStringList l = QStringList::split( '#', c->anchorName() ); 4712 QStringList l = QStringList::split( '#', c->anchorName() );
4690 for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it ) 4713 for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it )
4691 s += "<a name=\"" + *it + "\"></a>"; 4714 s += "<a name=\"" + *it + "\"></a>";
4692 } else { 4715 } else {
4693 s += "<a name=\"" + c->anchorName() + "\"></a>"; 4716 s += "<a name=\"" + c->anchorName() + "\"></a>";
4694 } 4717 }
4695 } 4718 }
4696 if ( !formatChar ) { 4719 if ( !formatChar ) {
4697 s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(), 4720 s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(),
4698 0, QString::null, c->anchorHref() ); 4721 0, QString::null, c->anchorHref() );
4699 formatChar = c; 4722 formatChar = c;
4700 } else if ( ( formatChar->format()->key() != c->format()->key() ) || 4723 } else if ( ( formatChar->format()->key() != c->format()->key() ) ||
4701 (c->anchorHref() != formatChar->anchorHref() ) ) { 4724 (c->anchorHref() != formatChar->anchorHref() ) ) {
4702 s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(), 4725 s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(),
4703 formatChar->format() , formatChar->anchorHref(), c->anchorHref() ); 4726 formatChar->format() , formatChar->anchorHref(), c->anchorHref() );
4704 formatChar = c; 4727 formatChar = c;
4705 } 4728 }
4706 if ( c->c == '<' ) 4729 if ( c->c == '<' )
4707 s += "&lt;"; 4730 s += "&lt;";
4708 else if ( c->c == '>' ) 4731 else if ( c->c == '>' )
4709 s += "&gt;"; 4732 s += "&gt;";
4710 else if ( c->isCustom() ) 4733 else if ( c->isCustom() )
4711 s += c->customItem()->richText(); 4734 s += c->customItem()->richText();
4712 else if ( c->c == '\n' || c->c == QChar_linesep ) 4735 else if ( c->c == '\n' || c->c == QChar_linesep )
4713 s += "<br />"; // space on purpose for compatibility with Netscape, Lynx & Co. 4736 s += "<br />"; // space on purpose for compatibility with Netscape, Lynx & Co.
4714 else 4737 else
4715 s += c->c; 4738 s += c->c;
4716 } 4739 }
4717 if ( doEnd && richTextExportEnd->index() == i ) 4740 if ( doEnd && richTextExportEnd->index() == i )
4718 s += "<selend/>"; 4741 s += "<selend/>";
4719 if ( formatChar ) 4742 if ( formatChar )
4720 s += formatChar->format()->makeFormatEndTags( formatCollection()->defaultFormat(), formatChar->anchorHref() ); 4743 s += formatChar->format()->makeFormatEndTags( formatCollection()->defaultFormat(), formatChar->anchorHref() );
4721 return s; 4744 return s;
4722} 4745}
4723 4746
4724void QTextParagraph::addCommand( QTextCommand *cmd ) 4747void QTextParagraph::addCommand( QTextCommand *cmd )
4725{ 4748{
4726 if ( !hasdoc ) 4749 if ( !hasdoc )
4727 pseudoDocument()->commandHistory->addCommand( cmd ); 4750 pseudoDocument()->commandHistory->addCommand( cmd );
4728 else 4751 else
4729 document()->commands()->addCommand( cmd ); 4752 document()->commands()->addCommand( cmd );
4730} 4753}
4731 4754
4732QTextCursor *QTextParagraph::undo( QTextCursor *c ) 4755QTextCursor *QTextParagraph::undo( QTextCursor *c )
4733{ 4756{
4734 if ( !hasdoc ) 4757 if ( !hasdoc )
4735 return pseudoDocument()->commandHistory->undo( c ); 4758 return pseudoDocument()->commandHistory->undo( c );
4736 return document()->commands()->undo( c ); 4759 return document()->commands()->undo( c );
4737} 4760}
4738 4761
4739QTextCursor *QTextParagraph::redo( QTextCursor *c ) 4762QTextCursor *QTextParagraph::redo( QTextCursor *c )
4740{ 4763{
4741 if ( !hasdoc ) 4764 if ( !hasdoc )
4742 return pseudoDocument()->commandHistory->redo( c ); 4765 return pseudoDocument()->commandHistory->redo( c );
4743 return document()->commands()->redo( c ); 4766 return document()->commands()->redo( c );
4744} 4767}
4745 4768
4746int QTextParagraph::topMargin() const 4769int QTextParagraph::topMargin() const
4747{ 4770{
4748 int m = 0; 4771 int m = 0;
4749 if ( rtext ) { 4772 if ( rtext ) {
4750 m = isListItem() ? (document()->li_tm/QMAX(1,listDepth())) : document()->par_tm; 4773 m = isListItem() ? (document()->li_tm/QMAX(1,listDepth())) : document()->par_tm;
4751 if ( listDepth() == 1 &&( !prev() || prev()->listDepth() < listDepth() ) ) 4774 if ( listDepth() == 1 &&( !prev() || prev()->listDepth() < listDepth() ) )
4752 m = QMAX( m, document()->list_tm ); 4775 m = QMAX( m, document()->list_tm );
4753 } 4776 }
4754 m += utm; 4777 m += utm;
4755 return scale( m, QTextFormat::painter() ); 4778 return scale( m, QTextFormat::painter() );
4756} 4779}
4757 4780
4758int QTextParagraph::bottomMargin() const 4781int QTextParagraph::bottomMargin() const
4759{ 4782{
4760 int m = 0; 4783 int m = 0;
4761 if ( rtext ) { 4784 if ( rtext ) {
4762 m = isListItem() ? (document()->li_bm/QMAX(1,listDepth())) : document()->par_bm; 4785 m = isListItem() ? (document()->li_bm/QMAX(1,listDepth())) : document()->par_bm;
4763 if ( listDepth() == 1 &&( !next() || next()->listDepth() < listDepth() ) ) 4786 if ( listDepth() == 1 &&( !next() || next()->listDepth() < listDepth() ) )
4764 m = QMAX( m, document()->list_bm ); 4787 m = QMAX( m, document()->list_bm );
4765 } 4788 }
4766 m += ubm; 4789 m += ubm;
4767 return scale( m, QTextFormat::painter() ); 4790 return scale( m, QTextFormat::painter() );
4768} 4791}
4769 4792
4770int QTextParagraph::leftMargin() const 4793int QTextParagraph::leftMargin() const
4771{ 4794{
4772 int m = ulm; 4795 int m = ulm;
4773 if ( listDepth() ) 4796 if ( listDepth() )
4774 m += listDepth() * document()->list_lm; 4797 m += listDepth() * document()->list_lm;
4775 return scale( m, QTextFormat::painter() ); 4798 return scale( m, QTextFormat::painter() );
4776} 4799}
4777 4800
4778int QTextParagraph::firstLineMargin() const 4801int QTextParagraph::firstLineMargin() const
4779{ 4802{
4780 int m = uflm; 4803 int m = uflm;
4781 return scale( m, QTextFormat::painter() ); 4804 return scale( m, QTextFormat::painter() );
4782} 4805}
4783 4806
4784int QTextParagraph::rightMargin() const 4807int QTextParagraph::rightMargin() const
4785{ 4808{
4786 int m = urm; 4809 int m = urm;
4787 return scale( m, QTextFormat::painter() ); 4810 return scale( m, QTextFormat::painter() );
4788} 4811}
4789 4812
4790int QTextParagraph::lineSpacing() const 4813int QTextParagraph::lineSpacing() const
4791{ 4814{
4792 int l = ulinespacing; 4815 int l = ulinespacing;
4793 l = scale( l, QTextFormat::painter() ); 4816 l = scale( l, QTextFormat::painter() );
4794 return l; 4817 return l;
4795} 4818}
4796 4819
4797void QTextParagraph::copyParagData( QTextParagraph *parag ) 4820void QTextParagraph::copyParagData( QTextParagraph *parag )
4798{ 4821{
4799 rtext = parag->rtext; 4822 rtext = parag->rtext;
4800 lstyle = parag->lstyle; 4823 lstyle = parag->lstyle;
4801 ldepth = parag->ldepth; 4824 ldepth = parag->ldepth;
4802 litem = parag->litem; 4825 litem = parag->litem;
4803 align = parag->align; 4826 align = parag->align;
4804 utm = parag->utm; 4827 utm = parag->utm;
4805 ubm = parag->ubm; 4828 ubm = parag->ubm;
4806 urm = parag->urm; 4829 urm = parag->urm;
4807 ulm = parag->ulm; 4830 ulm = parag->ulm;
4808 uflm = parag->uflm; 4831 uflm = parag->uflm;
4809 ulinespacing = parag->ulinespacing; 4832 ulinespacing = parag->ulinespacing;
4810 QColor *c = parag->backgroundColor(); 4833 QColor *c = parag->backgroundColor();
4811 if ( c ) 4834 if ( c )
4812 setBackgroundColor( *c ); 4835 setBackgroundColor( *c );
4813 str->setDirection( parag->str->direction() ); 4836 str->setDirection( parag->str->direction() );
4814} 4837}
4815 4838
4816void QTextParagraph::show() 4839void QTextParagraph::show()
4817{ 4840{
4818 if ( visible || !hasdoc ) 4841 if ( visible || !hasdoc )
4819 return; 4842 return;
4820 visible = TRUE; 4843 visible = TRUE;
4821} 4844}
4822 4845
4823void QTextParagraph::hide() 4846void QTextParagraph::hide()
4824{ 4847{
4825 if ( !visible || !hasdoc ) 4848 if ( !visible || !hasdoc )
4826 return; 4849 return;
4827 visible = FALSE; 4850 visible = FALSE;
4828} 4851}
4829 4852
4830void QTextParagraph::setDirection( QChar::Direction d ) 4853void QTextParagraph::setDirection( QChar::Direction d )
4831{ 4854{
4832 if ( str && str->direction() != d ) { 4855 if ( str && str->direction() != d ) {
4833 str->setDirection( d ); 4856 str->setDirection( d );
4834 invalidate( 0 ); 4857 invalidate( 0 );
4835 } 4858 }
4836} 4859}
4837 4860
4838QChar::Direction QTextParagraph::direction() const 4861QChar::Direction QTextParagraph::direction() const
4839{ 4862{
4840 return (str ? str->direction() : QChar::DirON ); 4863 return (str ? str->direction() : QChar::DirON );
4841} 4864}
4842 4865
4843void QTextParagraph::setChanged( bool b, bool recursive ) 4866void QTextParagraph::setChanged( bool b, bool recursive )
4844{ 4867{
4845 changed = b; 4868 changed = b;
4846 if ( recursive ) { 4869 if ( recursive ) {
4847 if ( document() && document()->parentParagraph() ) 4870 if ( document() && document()->parentParagraph() )
4848 document()->parentParagraph()->setChanged( b, recursive ); 4871 document()->parentParagraph()->setChanged( b, recursive );
4849 } 4872 }
4850} 4873}
4851 4874
4852// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4875// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4853 4876
4854 4877
4855QTextPreProcessor::QTextPreProcessor() 4878QTextPreProcessor::QTextPreProcessor()
4856{ 4879{
4857} 4880}
4858 4881
4859// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4882// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4860 4883
4861QTextFormatter::QTextFormatter() 4884QTextFormatter::QTextFormatter()
4862 : thisminw(0), thiswused(0), wrapEnabled( TRUE ), wrapColumn( -1 ), biw( FALSE ) 4885 : thisminw(0), thiswused(0), wrapEnabled( TRUE ), wrapColumn( -1 ), biw( FALSE )
4863{ 4886{
4864} 4887}
4865 4888
4866QTextLineStart *QTextFormatter::formatLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line, 4889QTextLineStart *QTextFormatter::formatLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line,
4867 QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space ) 4890 QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space )
4868{ 4891{
4869#ifndef QT_NO_COMPLEXTEXT 4892#ifndef QT_NO_COMPLEXTEXT
4870 if( string->isBidi() ) 4893 if( string->isBidi() )
4871 return bidiReorderLine( parag, string, line, startChar, lastChar, align, space ); 4894 return bidiReorderLine( parag, string, line, startChar, lastChar, align, space );
4872#endif 4895#endif
4873 int start = (startChar - &string->at(0)); 4896 int start = (startChar - &string->at(0));
4874 int last = (lastChar - &string->at(0) ); 4897 int last = (lastChar - &string->at(0) );
4875 // do alignment Auto == Left in this case 4898 // do alignment Auto == Left in this case
4876 if ( align & Qt::AlignHCenter || align & Qt::AlignRight ) { 4899 if ( align & Qt::AlignHCenter || align & Qt::AlignRight ) {
4877 if ( align & Qt::AlignHCenter ) 4900 if ( align & Qt::AlignHCenter )
4878 space /= 2; 4901 space /= 2;
4879 for ( int j = start; j <= last; ++j ) 4902 for ( int j = start; j <= last; ++j )
4880 string->at( j ).x += space; 4903 string->at( j ).x += space;
4881 } else if ( align & Qt3::AlignJustify ) { 4904 } else if ( align & Qt3::AlignJustify ) {
4882 int numSpaces = 0; 4905 int numSpaces = 0;
4883 // End at "last-1", the last space ends up with a width of 0 4906 // End at "last-1", the last space ends up with a width of 0
4884 for ( int j = last-1; j >= start; --j ) { 4907 for ( int j = last-1; j >= start; --j ) {
4885 // Start at last tab, if any. 4908 // Start at last tab, if any.
4886 if ( string->at( j ).c == '\t' ) { 4909 if ( string->at( j ).c == '\t' ) {
4887 start = j+1; 4910 start = j+1;
4888 break; 4911 break;
4889 } 4912 }
4890 if( isBreakable( string, j ) ) { 4913 if( isBreakable( string, j ) ) {
4891 numSpaces++; 4914 numSpaces++;
4892 } 4915 }
4893 } 4916 }
4894 int toAdd = 0; 4917 int toAdd = 0;
4895 for ( int k = start + 1; k <= last; ++k ) { 4918 for ( int k = start + 1; k <= last; ++k ) {
4896 if( isBreakable( string, k ) && numSpaces ) { 4919 if( isBreakable( string, k ) && numSpaces ) {
4897 int s = space / numSpaces; 4920 int s = space / numSpaces;
4898 toAdd += s; 4921 toAdd += s;
4899 space -= s; 4922 space -= s;
4900 numSpaces--; 4923 numSpaces--;
4901 } 4924 }
4902 string->at( k ).x += toAdd; 4925 string->at( k ).x += toAdd;
4903 } 4926 }
4904 } 4927 }
4905 4928
4906 if ( last >= 0 && last < string->length() ) 4929 if ( last >= 0 && last < string->length() )
4907 line->w = string->at( last ).x + string->width( last ); 4930 line->w = string->at( last ).x + string->width( last );
4908 else 4931 else
4909 line->w = 0; 4932 line->w = 0;
4910 4933
4911 return new QTextLineStart(); 4934 return new QTextLineStart();
4912} 4935}
4913 4936
4914#ifndef QT_NO_COMPLEXTEXT 4937#ifndef QT_NO_COMPLEXTEXT
4915 4938
4916#ifdef BIDI_DEBUG 4939#ifdef BIDI_DEBUG
4917#include <iostream> 4940#include <iostream>
4918#endif 4941#endif
4919 4942
4920// collects one line of the paragraph and transforms it to visual order 4943// collects one line of the paragraph and transforms it to visual order
4921QTextLineStart *QTextFormatter::bidiReorderLine( QTextParagraph * /*parag*/, QTextString *text, QTextLineStart *line, 4944QTextLineStart *QTextFormatter::bidiReorderLine( QTextParagraph * /*parag*/, QTextString *text, QTextLineStart *line,
4922 QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space ) 4945 QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space )
4923{ 4946{
4924 int start = (startChar - &text->at(0)); 4947 int start = (startChar - &text->at(0));
4925 int last = (lastChar - &text->at(0) ); 4948 int last = (lastChar - &text->at(0) );
4926 4949
4927 QBidiControl *control = new QBidiControl( line->context(), line->status ); 4950 QBidiControl *control = new QBidiControl( line->context(), line->status );
4928 QString str; 4951 QString str;
4929 str.setUnicode( 0, last - start + 1 ); 4952 str.setUnicode( 0, last - start + 1 );
4930 // fill string with logically ordered chars. 4953 // fill string with logically ordered chars.
4931 QTextStringChar *ch = startChar; 4954 QTextStringChar *ch = startChar;
4932 QChar *qch = (QChar *)str.unicode(); 4955 QChar *qch = (QChar *)str.unicode();
4933 while ( ch <= lastChar ) { 4956 while ( ch <= lastChar ) {
4934 *qch = ch->c; 4957 *qch = ch->c;
4935 qch++; 4958 qch++;
4936 ch++; 4959 ch++;
4937 } 4960 }
4938 int x = startChar->x; 4961 int x = startChar->x;
4939 4962
4940 QPtrList<QTextRun> *runs; 4963 QPtrList<QTextRun> *runs;
4941 runs = QComplexText::bidiReorderLine(control, str, 0, last - start + 1, 4964 runs = QComplexText::bidiReorderLine(control, str, 0, last - start + 1,
4942 (text->isRightToLeft() ? QChar::DirR : QChar::DirL) ); 4965 (text->isRightToLeft() ? QChar::DirR : QChar::DirL) );
4943 4966
4944 // now construct the reordered string out of the runs... 4967 // now construct the reordered string out of the runs...
4945 4968
4946 int numSpaces = 0; 4969 int numSpaces = 0;
4947 // set the correct alignment. This is a bit messy.... 4970 // set the correct alignment. This is a bit messy....
4948 if( align == Qt3::AlignAuto ) { 4971 if( align == Qt3::AlignAuto ) {
4949 // align according to directionality of the paragraph... 4972 // align according to directionality of the paragraph...
4950 if ( text->isRightToLeft() ) 4973 if ( text->isRightToLeft() )
4951 align = Qt::AlignRight; 4974 align = Qt::AlignRight;
4952 } 4975 }
4953 4976
4954 if ( align & Qt::AlignHCenter ) 4977 if ( align & Qt::AlignHCenter )
4955 x += space/2; 4978 x += space/2;
4956 else if ( align & Qt::AlignRight ) 4979 else if ( align & Qt::AlignRight )
4957 x += space; 4980 x += space;
4958 else if ( align & Qt3::AlignJustify ) { 4981 else if ( align & Qt3::AlignJustify ) {
4959 // End at "last-1", the last space ends up with a width of 0 4982 // End at "last-1", the last space ends up with a width of 0
4960 for ( int j = last-1; j >= start; --j ) { 4983 for ( int j = last-1; j >= start; --j ) {
4961 // Start at last tab, if any. 4984 // Start at last tab, if any.
4962 if ( text->at( j ).c == '\t' ) { 4985 if ( text->at( j ).c == '\t' ) {
4963 start = j+1; 4986 start = j+1;
4964 break; 4987 break;
4965 } 4988 }
4966 if( isBreakable( text, j ) ) { 4989 if( isBreakable( text, j ) ) {
4967 numSpaces++; 4990 numSpaces++;
4968 } 4991 }
4969 } 4992 }
4970 } 4993 }
4971 int toAdd = 0; 4994 int toAdd = 0;
4972 bool first = TRUE; 4995 bool first = TRUE;
4973 QTextRun *r = runs->first(); 4996 QTextRun *r = runs->first();
4974 int xmax = -0xffffff; 4997 int xmax = -0xffffff;
4975 while ( r ) { 4998 while ( r ) {
4976 if(r->level %2) { 4999 if(r->level %2) {
4977 // odd level, need to reverse the string 5000 // odd level, need to reverse the string
4978 int pos = r->stop + start; 5001 int pos = r->stop + start;
4979 while(pos >= r->start + start) { 5002 while(pos >= r->start + start) {
4980 QTextStringChar *c = &text->at(pos); 5003 QTextStringChar *c = &text->at(pos);
4981 if( numSpaces && !first && isBreakable( text, pos ) ) { 5004 if( numSpaces && !first && isBreakable( text, pos ) ) {
4982 int s = space / numSpaces; 5005 int s = space / numSpaces;
4983 toAdd += s; 5006 toAdd += s;
4984 space -= s; 5007 space -= s;
4985 numSpaces--; 5008 numSpaces--;
4986 } else if ( first ) { 5009 } else if ( first ) {
4987 first = FALSE; 5010 first = FALSE;
4988 if ( c->c == ' ' ) 5011 if ( c->c == ' ' )
4989 x -= c->format()->width( ' ' ); 5012 x -= c->format()->width( ' ' );
4990 } 5013 }
4991 c->x = x + toAdd; 5014 c->x = x + toAdd;
4992 c->rightToLeft = TRUE; 5015 c->rightToLeft = TRUE;
4993 c->startOfRun = FALSE; 5016 c->startOfRun = FALSE;
4994 int ww = 0; 5017 int ww = 0;
4995 if ( c->c.unicode() >= 32 || c->c == '\t' || c->c == '\n' || c->isCustom() ) { 5018 if ( c->c.unicode() >= 32 || c->c == '\t' || c->c == '\n' || c->isCustom() ) {
4996 ww = text->width( pos ); 5019 ww = text->width( pos );
4997 } else { 5020 } else {
4998 ww = c->format()->width( ' ' ); 5021 ww = c->format()->width( ' ' );
4999 } 5022 }
5000 if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww; 5023 if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww;
5001 x += ww; 5024 x += ww;
5002 pos--; 5025 pos--;
5003 } 5026 }
5004 } else { 5027 } else {
5005 int pos = r->start + start; 5028 int pos = r->start + start;
5006 while(pos <= r->stop + start) { 5029 while(pos <= r->stop + start) {
5007 QTextStringChar* c = &text->at(pos); 5030 QTextStringChar* c = &text->at(pos);
5008 if( numSpaces && !first && isBreakable( text, pos ) ) { 5031 if( numSpaces && !first && isBreakable( text, pos ) ) {
5009 int s = space / numSpaces; 5032 int s = space / numSpaces;
5010 toAdd += s; 5033 toAdd += s;
5011 space -= s; 5034 space -= s;
5012 numSpaces--; 5035 numSpaces--;
5013 } else if ( first ) { 5036 } else if ( first ) {
5014 first = FALSE; 5037 first = FALSE;
5015 if ( c->c == ' ' ) 5038 if ( c->c == ' ' )
5016 x -= c->format()->width( ' ' ); 5039 x -= c->format()->width( ' ' );
5017 } 5040 }
5018 c->x = x + toAdd; 5041 c->x = x + toAdd;
5019 c->rightToLeft = FALSE; 5042 c->rightToLeft = FALSE;
5020 c->startOfRun = FALSE; 5043 c->startOfRun = FALSE;
5021 int ww = 0; 5044 int ww = 0;
5022 if ( c->c.unicode() >= 32 || c->c == '\t' || c->isCustom() ) { 5045 if ( c->c.unicode() >= 32 || c->c == '\t' || c->isCustom() ) {
5023 ww = text->width( pos ); 5046 ww = text->width( pos );
5024 } else { 5047 } else {
5025 ww = c->format()->width( ' ' ); 5048 ww = c->format()->width( ' ' );
5026 } 5049 }
5027 if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww; 5050 if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww;
5028 x += ww; 5051 x += ww;
5029 pos++; 5052 pos++;
5030 } 5053 }
5031 } 5054 }
5032 text->at( r->start + start ).startOfRun = TRUE; 5055 text->at( r->start + start ).startOfRun = TRUE;
5033 r = runs->next(); 5056 r = runs->next();
5034 } 5057 }
5035 5058
5036 line->w = xmax + 10; 5059 line->w = xmax + 10;
5037 QTextLineStart *ls = new QTextLineStart( control->context, control->status ); 5060 QTextLineStart *ls = new QTextLineStart( control->context, control->status );
5038 delete control; 5061 delete control;
5039 delete runs; 5062 delete runs;
5040 return ls; 5063 return ls;
5041} 5064}
5042#endif 5065#endif
5043 5066
5044bool QTextFormatter::isBreakable( QTextString *string, int pos ) 5067bool QTextFormatter::isBreakable( QTextString *string, int pos )
5045{ 5068{
5046 const QChar &c = string->at( pos ).c; 5069 const QChar &c = string->at( pos ).c;
5047 char ch = c.latin1(); 5070 char ch = c.latin1();
5048 if ( c == QChar_linesep ) 5071 if ( c == QChar_linesep )
5049 return TRUE; 5072 return TRUE;
5050 if ( c.isSpace() && ch != '\n' && c.unicode() != 0x00a0U ) 5073 if ( c.isSpace() && ch != '\n' && c.unicode() != 0x00a0U )
5051 return TRUE; 5074 return TRUE;
5052 if ( c.unicode() == 0xad ) // soft hyphen 5075 if ( c.unicode() == 0xad ) // soft hyphen
5053 return TRUE; 5076 return TRUE;
5054 if ( !ch ) { 5077 if ( !ch ) {
5055 // not latin1, need to do more sophisticated checks for other scripts 5078 // not latin1, need to do more sophisticated checks for other scripts
5056 uchar row = c.row(); 5079 uchar row = c.row();
5057 if ( row == 0x0e ) { 5080 if ( row == 0x0e ) {
5058 // 0e00 - 0e7f == Thai 5081 // 0e00 - 0e7f == Thai
5059 if ( c.cell() < 0x80 ) { 5082 if ( c.cell() < 0x80 ) {
5060#ifdef HAVE_THAI_BREAKS 5083#ifdef HAVE_THAI_BREAKS
5061 // check for thai 5084 // check for thai
5062 if( string != cachedString ) { 5085 if( string != cachedString ) {
5063 // build up string of thai chars 5086 // build up string of thai chars
5064 QTextCodec *thaiCodec = QTextCodec::codecForMib(2259); 5087 QTextCodec *thaiCodec = QTextCodec::codecForMib(2259);
5065 if ( !thaiCache ) 5088 if ( !thaiCache )
5066 thaiCache = new QCString; 5089 thaiCache = new QCString;
5067 if ( !thaiIt ) 5090 if ( !thaiIt )
5068 thaiIt = ThBreakIterator::createWordInstance(); 5091 thaiIt = ThBreakIterator::createWordInstance();
5069 *thaiCache = thaiCodec->fromUnicode( s->string() ); 5092 *thaiCache = thaiCodec->fromUnicode( s->string() );
5070 } 5093 }
5071 thaiIt->setText(thaiCache->data()); 5094 thaiIt->setText(thaiCache->data());
5072 for(int i = thaiIt->first(); i != thaiIt->DONE; i = thaiIt->next() ) { 5095 for(int i = thaiIt->first(); i != thaiIt->DONE; i = thaiIt->next() ) {
5073 if( i == pos ) 5096 if( i == pos )
5074 return TRUE; 5097 return TRUE;
5075 if( i > pos ) 5098 if( i > pos )
5076 return FALSE; 5099 return FALSE;
5077 } 5100 }
5078 return FALSE; 5101 return FALSE;
5079#else 5102#else
5080 // if we don't have a thai line breaking lib, allow 5103 // if we don't have a thai line breaking lib, allow
5081 // breaks everywhere except directly before punctuation. 5104 // breaks everywhere except directly before punctuation.
5082 return TRUE; 5105 return TRUE;
5083#endif 5106#endif
5084 } else 5107 } else
5085 return FALSE; 5108 return FALSE;
5086 } 5109 }
5087 if ( row < 0x11 ) // no asian font 5110 if ( row < 0x11 ) // no asian font
5088 return FALSE; 5111 return FALSE;
5089 if ( row > 0x2d && row < 0xfb || row == 0x11 ) 5112 if ( row > 0x2d && row < 0xfb || row == 0x11 )
5090 // asian line breaking. Everywhere allowed except directly 5113 // asian line breaking. Everywhere allowed except directly
5091 // in front of a punctuation character. 5114 // in front of a punctuation character.
5092 return TRUE; 5115 return TRUE;
5093 } 5116 }
5094 return FALSE; 5117 return FALSE;
5095} 5118}
5096 5119
5097void QTextFormatter::insertLineStart( QTextParagraph *parag, int index, QTextLineStart *ls ) 5120void QTextFormatter::insertLineStart( QTextParagraph *parag, int index, QTextLineStart *ls )
5098{ 5121{
5099 if ( index > 0 ) { // we can assume that only first line starts are insrted multiple times 5122 if ( index > 0 ) { // we can assume that only first line starts are insrted multiple times
5100 parag->lineStartList().insert( index, ls ); 5123 parag->lineStartList().insert( index, ls );
5101 return; 5124 return;
5102 } 5125 }
5103 QMap<int, QTextLineStart*>::Iterator it; 5126 QMap<int, QTextLineStart*>::Iterator it;
5104 if ( ( it = parag->lineStartList().find( index ) ) == parag->lineStartList().end() ) { 5127 if ( ( it = parag->lineStartList().find( index ) ) == parag->lineStartList().end() ) {
5105 parag->lineStartList().insert( index, ls ); 5128 parag->lineStartList().insert( index, ls );
5106 } else { 5129 } else {
5107 delete *it; 5130 delete *it;
5108 parag->lineStartList().remove( it ); 5131 parag->lineStartList().remove( it );
5109 parag->lineStartList().insert( index, ls ); 5132 parag->lineStartList().insert( index, ls );
5110 } 5133 }
5111} 5134}
5112 5135
5113 5136
5114/* Standard pagebreak algorithm using QTextFlow::adjustFlow. Returns 5137/* Standard pagebreak algorithm using QTextFlow::adjustFlow. Returns
5115 the shift of the paragraphs bottom line. 5138 the shift of the paragraphs bottom line.
5116 */ 5139 */
5117int QTextFormatter::formatVertically( QTextDocument* doc, QTextParagraph* parag ) 5140int QTextFormatter::formatVertically( QTextDocument* doc, QTextParagraph* parag )
5118{ 5141{
5119 int oldHeight = parag->rect().height(); 5142 int oldHeight = parag->rect().height();
5120 QMap<int, QTextLineStart*>& lineStarts = parag->lineStartList(); 5143 QMap<int, QTextLineStart*>& lineStarts = parag->lineStartList();
5121 QMap<int, QTextLineStart*>::Iterator it = lineStarts.begin(); 5144 QMap<int, QTextLineStart*>::Iterator it = lineStarts.begin();
5122 int h = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin() ) / 2: 0; 5145 int h = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin() ) / 2: 0;
5123 for ( ; it != lineStarts.end() ; ++it ) { 5146 for ( ; it != lineStarts.end() ; ++it ) {
5124 QTextLineStart * ls = it.data(); 5147 QTextLineStart * ls = it.data();
5125 ls->y = h; 5148 ls->y = h;
5126 QTextStringChar *c = &parag->string()->at(it.key()); 5149 QTextStringChar *c = &parag->string()->at(it.key());
5127 if ( c && c->customItem() && c->customItem()->ownLine() ) { 5150 if ( c && c->customItem() && c->customItem()->ownLine() ) {
5128 int h = c->customItem()->height; 5151 int h = c->customItem()->height;
5129 c->customItem()->pageBreak( parag->rect().y() + ls->y + ls->baseLine - h, doc->flow() ); 5152 c->customItem()->pageBreak( parag->rect().y() + ls->y + ls->baseLine - h, doc->flow() );
5130 int delta = c->customItem()->height - h; 5153 int delta = c->customItem()->height - h;
5131 ls->h += delta; 5154 ls->h += delta;
5132 if ( delta ) 5155 if ( delta )
5133 parag->setMovedDown( TRUE ); 5156 parag->setMovedDown( TRUE );
5134 } else { 5157 } else {
5135 int shift = doc->flow()->adjustFlow( parag->rect().y() + ls->y, ls->w, ls->h ); 5158 int shift = doc->flow()->adjustFlow( parag->rect().y() + ls->y, ls->w, ls->h );
5136 ls->y += shift; 5159 ls->y += shift;
5137 if ( shift ) 5160 if ( shift )
5138 parag->setMovedDown( TRUE ); 5161 parag->setMovedDown( TRUE );
5139 } 5162 }
5140 h = ls->y + ls->h; 5163 h = ls->y + ls->h;
5141 } 5164 }
5142 int m = parag->bottomMargin(); 5165 int m = parag->bottomMargin();
5143 if ( !parag->next() ) 5166 if ( !parag->next() )
5144 m = 0; 5167 m = 0;
5145 else 5168 else
5146 m = QMAX(m, parag->next()->topMargin() ) / 2; 5169 m = QMAX(m, parag->next()->topMargin() ) / 2;
5147 h += m; 5170 h += m;
5148 parag->setHeight( h ); 5171 parag->setHeight( h );
5149 return h - oldHeight; 5172 return h - oldHeight;
5150} 5173}
5151 5174
5152// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5175// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5153 5176
5154QTextFormatterBreakInWords::QTextFormatterBreakInWords() 5177QTextFormatterBreakInWords::QTextFormatterBreakInWords()
5155{ 5178{
5156} 5179}
5157 5180
5158#define SPACE(s) doc?(s>0?s:0):s 5181#define SPACE(s) doc?(s>0?s:0):s
5159 5182
5160int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParagraph *parag, 5183int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParagraph *parag,
5161 int start, const QMap<int, QTextLineStart*> & ) 5184 int start, const QMap<int, QTextLineStart*> & )
5162{ 5185{
5163 QTextStringChar *c = 0; 5186 QTextStringChar *c = 0;
5164 QTextStringChar *firstChar = 0; 5187 QTextStringChar *firstChar = 0;
5165 int left = doc ? parag->leftMargin() + doc->leftMargin() : 0; 5188 int left = doc ? parag->leftMargin() + doc->leftMargin() : 0;
5166 int x = left + ( doc ? parag->firstLineMargin() : 0 ); 5189 int x = left + ( doc ? parag->firstLineMargin() : 0 );
5167 int dw = parag->documentVisibleWidth() - ( doc ? doc->rightMargin() : 0 ); 5190 int dw = parag->documentVisibleWidth() - ( doc ? doc->rightMargin() : 0 );
5168 int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0; 5191 int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0;
5169 int h = y; 5192 int h = y;
5170 int len = parag->length(); 5193 int len = parag->length();
5171 if ( doc ) 5194 if ( doc )
5172 x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 4 ); 5195 x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 4 );
5173 int rm = parag->rightMargin(); 5196 int rm = parag->rightMargin();
5174 int w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5197 int w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5175 bool fullWidth = TRUE; 5198 bool fullWidth = TRUE;
5176 int minw = 0; 5199 int minw = 0;
5177 int wused = 0; 5200 int wused = 0;
5178 bool wrapEnabled = isWrapEnabled( parag ); 5201 bool wrapEnabled = isWrapEnabled( parag );
5179 5202
5180 start = 0; //######### what is the point with start?! (Matthias) 5203 start = 0; //######### what is the point with start?! (Matthias)
5181 if ( start == 0 ) 5204 if ( start == 0 )
5182 c = &parag->string()->at( 0 ); 5205 c = &parag->string()->at( 0 );
5183 5206
5184 int i = start; 5207 int i = start;
5185 QTextLineStart *lineStart = new QTextLineStart( y, y, 0 ); 5208 QTextLineStart *lineStart = new QTextLineStart( y, y, 0 );
5186 insertLineStart( parag, 0, lineStart ); 5209 insertLineStart( parag, 0, lineStart );
5187 5210
5188 QPainter *painter = QTextFormat::painter(); 5211 QPainter *painter = QTextFormat::painter();
5189 5212
5190 int col = 0; 5213 int col = 0;
5191 int ww = 0; 5214 int ww = 0;
5192 QChar lastChr; 5215 QChar lastChr;
5193 for ( ; i < len; ++i, ++col ) { 5216 for ( ; i < len; ++i, ++col ) {
5194 if ( c ) 5217 if ( c )
5195 lastChr = c->c; 5218 lastChr = c->c;
5196 c = &parag->string()->at( i ); 5219 c = &parag->string()->at( i );
5197 c->rightToLeft = FALSE; 5220 c->rightToLeft = FALSE;
5198 // ### the lines below should not be needed 5221 // ### the lines below should not be needed
5199 if ( painter ) 5222 if ( painter )
5200 c->format()->setPainter( painter ); 5223 c->format()->setPainter( painter );
5201 if ( i > 0 ) { 5224 if ( i > 0 ) {
5202 c->lineStart = 0; 5225 c->lineStart = 0;
5203 } else { 5226 } else {
5204 c->lineStart = 1; 5227 c->lineStart = 1;
5205 firstChar = c; 5228 firstChar = c;
5206 } 5229 }
5207 if ( c->c.unicode() >= 32 || c->isCustom() ) { 5230 if ( c->c.unicode() >= 32 || c->isCustom() ) {
5208 ww = parag->string()->width( i ); 5231 ww = parag->string()->width( i );
5209 } else if ( c->c == '\t' ) { 5232 } else if ( c->c == '\t' ) {
5210 int nx = parag->nextTab( i, x - left ) + left; 5233 int nx = parag->nextTab( i, x - left ) + left;
5211 if ( nx < x ) 5234 if ( nx < x )
5212 ww = w - x; 5235 ww = w - x;
5213 else 5236 else
5214 ww = nx - x; 5237 ww = nx - x;
5215 } else { 5238 } else {
5216 ww = c->format()->width( ' ' ); 5239 ww = c->format()->width( ' ' );
5217 } 5240 }
5218 5241
5219 if ( c->isCustom() && c->customItem()->ownLine() ) { 5242 if ( c->isCustom() && c->customItem()->ownLine() ) {
5220 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5243 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5221 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5244 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5222 c->customItem()->resize( w - x ); 5245 c->customItem()->resize( w - x );
5223 w = dw; 5246 w = dw;
5224 y += h; 5247 y += h;
5225 h = c->height(); 5248 h = c->height();
5226 lineStart = new QTextLineStart( y, h, h ); 5249 lineStart = new QTextLineStart( y, h, h );
5227 insertLineStart( parag, i, lineStart ); 5250 insertLineStart( parag, i, lineStart );
5228 c->lineStart = 1; 5251 c->lineStart = 1;
5229 firstChar = c; 5252 firstChar = c;
5230 x = 0xffffff; 5253 x = 0xffffff;
5231 continue; 5254 continue;
5232 } 5255 }
5233 5256
5234 if ( wrapEnabled && 5257 if ( wrapEnabled &&
5235 ( wrapAtColumn() == -1 && x + ww > w || 5258 ( wrapAtColumn() == -1 && x + ww > w ||
5236 wrapAtColumn() != -1 && col >= wrapAtColumn() ) ) { 5259 wrapAtColumn() != -1 && col >= wrapAtColumn() ) ) {
5237 x = doc ? parag->document()->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5260 x = doc ? parag->document()->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5238 w = dw; 5261 w = dw;
5239 y += h; 5262 y += h;
5240 h = c->height(); 5263 h = c->height();
5241 lineStart = formatLine( parag, parag->string(), lineStart, firstChar, SPACE(c-1) ); 5264 lineStart = formatLine( parag, parag->string(), lineStart, firstChar, SPACE(c-1) );
5242 lineStart->y = y; 5265 lineStart->y = y;
5243 insertLineStart( parag, i, lineStart ); 5266 insertLineStart( parag, i, lineStart );
5244 lineStart->baseLine = c->ascent(); 5267 lineStart->baseLine = c->ascent();
5245 lineStart->h = c->height(); 5268 lineStart->h = c->height();
5246 c->lineStart = 1; 5269 c->lineStart = 1;
5247 firstChar = c; 5270 firstChar = c;
5248 col = 0; 5271 col = 0;
5249 if ( wrapAtColumn() != -1 ) 5272 if ( wrapAtColumn() != -1 )
5250 minw = QMAX( minw, w ); 5273 minw = QMAX( minw, w );
5251 } else if ( lineStart ) { 5274 } else if ( lineStart ) {
5252 lineStart->baseLine = QMAX( lineStart->baseLine, c->ascent() ); 5275 lineStart->baseLine = QMAX( lineStart->baseLine, c->ascent() );
5253 h = QMAX( h, c->height() ); 5276 h = QMAX( h, c->height() );
5254 lineStart->h = h; 5277 lineStart->h = h;
5255 } 5278 }
5256 5279
5257 c->x = x; 5280 c->x = x;
5258 x += ww; 5281 x += ww;
5259 wused = QMAX( wused, x ); 5282 wused = QMAX( wused, x );
5260 } 5283 }
5261 5284
5262 int m = parag->bottomMargin(); 5285 int m = parag->bottomMargin();
5263 if ( !parag->next() ) 5286 if ( !parag->next() )
5264 m = 0; 5287 m = 0;
5265 else 5288 else
5266 m = QMAX(m, parag->next()->topMargin() ) / 2; 5289 m = QMAX(m, parag->next()->topMargin() ) / 2;
5267 parag->setFullWidth( fullWidth ); 5290 parag->setFullWidth( fullWidth );
5268 y += h + m; 5291 y += h + m;
5269 if ( doc ) 5292 if ( doc )
5270 minw += doc->rightMargin(); 5293 minw += doc->rightMargin();
5271 if ( !wrapEnabled ) 5294 if ( !wrapEnabled )
5272 minw = QMAX(minw, wused); 5295 minw = QMAX(minw, wused);
5273 5296
5274 thisminw = minw; 5297 thisminw = minw;
5275 thiswused = wused; 5298 thiswused = wused;
5276 return y; 5299 return y;
5277} 5300}
5278 5301
5279// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5302// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5280 5303
5281QTextFormatterBreakWords::QTextFormatterBreakWords() 5304QTextFormatterBreakWords::QTextFormatterBreakWords()
5282{ 5305{
5283} 5306}
5284 5307
5285#define DO_FLOW( lineStart ) do{ if ( doc && doc->isPageBreakEnabled() ) { \ 5308#define DO_FLOW( lineStart ) do{ if ( doc && doc->isPageBreakEnabled() ) { \
5286 int yflow = lineStart->y + parag->rect().y();\ 5309 int yflow = lineStart->y + parag->rect().y();\
5287 int shift = doc->flow()->adjustFlow( yflow, dw, lineStart->h ); \ 5310 int shift = doc->flow()->adjustFlow( yflow, dw, lineStart->h ); \
5288 lineStart->y += shift;\ 5311 lineStart->y += shift;\
5289 y += shift;\ 5312 y += shift;\
5290 }}while(FALSE) 5313 }}while(FALSE)
5291 5314
5292int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParagraph *parag, 5315int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParagraph *parag,
5293 int start, const QMap<int, QTextLineStart*> & ) 5316 int start, const QMap<int, QTextLineStart*> & )
5294{ 5317{
5295 QTextStringChar *c = 0; 5318 QTextStringChar *c = 0;
5296 QTextStringChar *firstChar = 0; 5319 QTextStringChar *firstChar = 0;
5297 QTextString *string = parag->string(); 5320 QTextString *string = parag->string();
5298 int left = doc ? parag->leftMargin() + doc->leftMargin() : 0; 5321 int left = doc ? parag->leftMargin() + doc->leftMargin() : 0;
5299 int x = left + ( doc ? parag->firstLineMargin() : 0 ); 5322 int x = left + ( doc ? parag->firstLineMargin() : 0 );
5300 int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0; 5323 int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0;
5301 int h = y; 5324 int h = y;
5302 int len = parag->length(); 5325 int len = parag->length();
5303 if ( doc ) 5326 if ( doc )
5304 x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 0 ); 5327 x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 0 );
5305 int dw = parag->documentVisibleWidth() - ( doc ? ( left != x ? 0 : doc->rightMargin() ) : 0 ); 5328 int dw = parag->documentVisibleWidth() - ( doc ? ( left != x ? 0 : doc->rightMargin() ) : 0 );
5306 5329
5307 int curLeft = x; 5330 int curLeft = x;
5308 int rm = parag->rightMargin(); 5331 int rm = parag->rightMargin();
5309 int rdiff = doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 0 ) : 0; 5332 int rdiff = doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 0 ) : 0;
5310 int w = dw - rdiff; 5333 int w = dw - rdiff;
5311 bool fullWidth = TRUE; 5334 bool fullWidth = TRUE;
5312 int marg = left + rdiff; 5335 int marg = left + rdiff;
5313 int minw = 0; 5336 int minw = 0;
5314 int wused = 0; 5337 int wused = 0;
5315 int tminw = marg; 5338 int tminw = marg;
5316 int linespacing = doc ? parag->lineSpacing() : 0; 5339 int linespacing = doc ? parag->lineSpacing() : 0;
5317 bool wrapEnabled = isWrapEnabled( parag ); 5340 bool wrapEnabled = isWrapEnabled( parag );
5318 5341
5319 start = 0; 5342 start = 0;
5320 if ( start == 0 ) 5343 if ( start == 0 )
5321 c = &parag->string()->at( 0 ); 5344 c = &parag->string()->at( 0 );
5322 5345
5323 int i = start; 5346 int i = start;
5324 QTextLineStart *lineStart = new QTextLineStart( y, y, 0 ); 5347 QTextLineStart *lineStart = new QTextLineStart( y, y, 0 );
5325 insertLineStart( parag, 0, lineStart ); 5348 insertLineStart( parag, 0, lineStart );
5326 int lastBreak = -1; 5349 int lastBreak = -1;
5327 int tmpBaseLine = 0, tmph = 0; 5350 int tmpBaseLine = 0, tmph = 0;
5328 bool lastWasNonInlineCustom = FALSE; 5351 bool lastWasNonInlineCustom = FALSE;
5329 5352
5330 int align = parag->alignment(); 5353 int align = parag->alignment();
5331 if ( align == Qt3::AlignAuto && doc && doc->alignment() != Qt3::AlignAuto ) 5354 if ( align == Qt3::AlignAuto && doc && doc->alignment() != Qt3::AlignAuto )
5332 align = doc->alignment(); 5355 align = doc->alignment();
5333 5356
5334 align &= Qt3::AlignHorizontal_Mask; 5357 align &= Qt3::AlignHorizontal_Mask;
5335 5358
5336 QPainter *painter = QTextFormat::painter(); 5359 QPainter *painter = QTextFormat::painter();
5337 int col = 0; 5360 int col = 0;
5338 int ww = 0; 5361 int ww = 0;
5339 QChar lastChr; 5362 QChar lastChr;
5340 for ( ; i < len; ++i, ++col ) { 5363 for ( ; i < len; ++i, ++col ) {
5341 if ( c ) 5364 if ( c )
5342 lastChr = c->c; 5365 lastChr = c->c;
5343 // ### next line should not be needed 5366 // ### next line should not be needed
5344 if ( painter ) 5367 if ( c && painter )
5345 c->format()->setPainter( painter ); 5368 c->format()->setPainter( painter );
5346 c = &string->at( i ); 5369 c = &string->at( i );
5347 c->rightToLeft = FALSE; 5370 c->rightToLeft = FALSE;
5348 if ( i > 0 && (x > curLeft || ww == 0) || lastWasNonInlineCustom ) { 5371 if ( i > 0 && (x > curLeft || ww == 0) || lastWasNonInlineCustom ) {
5349 c->lineStart = 0; 5372 c->lineStart = 0;
5350 } else { 5373 } else {
5351 c->lineStart = 1; 5374 c->lineStart = 1;
5352 firstChar = c; 5375 firstChar = c;
5353 } 5376 }
5354 5377
5355 if ( c->isCustom() && c->customItem()->placement() != QTextCustomItem::PlaceInline ) 5378 if ( c->isCustom() && c->customItem()->placement() != QTextCustomItem::PlaceInline )
5356 lastWasNonInlineCustom = TRUE; 5379 lastWasNonInlineCustom = TRUE;
5357 else 5380 else
5358 lastWasNonInlineCustom = FALSE; 5381 lastWasNonInlineCustom = FALSE;
5359 5382
5360 if ( c->c.unicode() >= 32 || c->isCustom() ) { 5383 if ( c->c.unicode() >= 32 || c->isCustom() ) {
5361 ww = string->width( i ); 5384 ww = string->width( i );
5362 } else if ( c->c == '\t' ) { 5385 } else if ( c->c == '\t' ) {
5363 int nx = parag->nextTab( i, x - left ) + left; 5386 int nx = parag->nextTab( i, x - left ) + left;
5364 if ( nx < x ) 5387 if ( nx < x )
5365 ww = w - x; 5388 ww = w - x;
5366 else 5389 else
5367 ww = nx - x; 5390 ww = nx - x;
5368 } else { 5391 } else {
5369 ww = c->format()->width( ' ' ); 5392 ww = c->format()->width( ' ' );
5370 } 5393 }
5371 5394
5372 // last character ("invisible" space) has no width 5395 // last character ("invisible" space) has no width
5373 if ( i == len - 1 ) 5396 if ( i == len - 1 )
5374 ww = 0; 5397 ww = 0;
5375 5398
5376 QTextCustomItem* ci = c->customItem(); 5399 QTextCustomItem* ci = c->customItem();
5377 if ( c->isCustom() && ci->ownLine() ) { 5400 if ( c->isCustom() && ci->ownLine() ) {
5378 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5401 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5379 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5402 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5380 QTextLineStart *lineStart2 = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) ); 5403 QTextLineStart *lineStart2 = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) );
5381 ci->resize( w - x); 5404 ci->resize( w - x);
5382 if ( ci->width < w - x ) { 5405 if ( ci->width < w - x ) {
5383 if ( align & Qt::AlignHCenter ) 5406 if ( align & Qt::AlignHCenter )
5384 x = ( w - ci->width ) / 2; 5407 x = ( w - ci->width ) / 2;
5385 else if ( align & Qt::AlignRight ) { 5408 else if ( align & Qt::AlignRight ) {
5386 x = w - ci->width; 5409 x = w - ci->width;
5387 } 5410 }
5388 } 5411 }
5389 c->x = x; 5412 c->x = x;
5390 curLeft = x; 5413 curLeft = x;
5391 if ( i == 0 || !isBreakable( string, i - 1 ) || string->at( i - 1 ).lineStart == 0 ) { 5414 if ( i == 0 || !isBreakable( string, i - 1 ) || string->at( i - 1 ).lineStart == 0 ) {
5392 y += QMAX( h, QMAX( tmph, linespacing ) ); 5415 y += QMAX( h, QMAX( tmph, linespacing ) );
5393 tmph = c->height(); 5416 tmph = c->height();
5394 h = tmph; 5417 h = tmph;
5395 lineStart = lineStart2; 5418 lineStart = lineStart2;
5396 lineStart->y = y; 5419 lineStart->y = y;
5397 insertLineStart( parag, i, lineStart ); 5420 insertLineStart( parag, i, lineStart );
5398 c->lineStart = 1; 5421 c->lineStart = 1;
5399 firstChar = c; 5422 firstChar = c;
5400 } else { 5423 } else {
5401 tmph = c->height(); 5424 tmph = c->height();
5402 h = tmph; 5425 h = tmph;
5403 delete lineStart2; 5426 delete lineStart2;
5404 } 5427 }
5405 lineStart->h = h; 5428 lineStart->h = h;
5406 lineStart->baseLine = h; 5429 lineStart->baseLine = h;
5407 tmpBaseLine = lineStart->baseLine; 5430 tmpBaseLine = lineStart->baseLine;
5408 lastBreak = -2; 5431 lastBreak = -2;
5409 x = 0xffffff; 5432 x = 0xffffff;
5410 minw = QMAX( minw, tminw ); 5433 minw = QMAX( minw, tminw );
5411 5434
5412 int tw = ci->minimumWidth() + ( doc ? doc->leftMargin() : 0 ); 5435 int tw = ci->minimumWidth() + ( doc ? doc->leftMargin() : 0 );
5413 if ( tw < QWIDGETSIZE_MAX ) 5436 if ( tw < QWIDGETSIZE_MAX )
5414 tminw = tw; 5437 tminw = tw;
5415 else 5438 else
5416 tminw = marg; 5439 tminw = marg;
5417 wused = QMAX( wused, ci->width ); 5440 wused = QMAX( wused, ci->width );
5418 continue; 5441 continue;
5419 } else if ( c->isCustom() && ci->placement() != QTextCustomItem::PlaceInline ) { 5442 } else if ( c->isCustom() && ci->placement() != QTextCustomItem::PlaceInline ) {
5420 int tw = ci->minimumWidth(); 5443 int tw = ci->minimumWidth();
5421 if ( tw < QWIDGETSIZE_MAX ) 5444 if ( tw < QWIDGETSIZE_MAX )
5422 minw = QMAX( minw, tw ); 5445 minw = QMAX( minw, tw );
5423 } 5446 }
5424 5447
5425 bool lastWasOwnLineCustomItem = lastBreak == -2; 5448 bool lastWasOwnLineCustomItem = lastBreak == -2;
5426 bool hadBreakableChar = lastBreak != -1; 5449 bool hadBreakableChar = lastBreak != -1;
5427 bool lastWasHardBreak = lastChr == QChar_linesep; 5450 bool lastWasHardBreak = lastChr == QChar_linesep;
5428 5451
5429 // we break if 5452 // we break if
5430 // 1. the last character was a hard break (QChar_linesep) or 5453 // 1. the last character was a hard break (QChar_linesep) or
5431 // 2. the last charater was a own-line custom item (eg. table or ruler) or 5454 // 2. the last charater was a own-line custom item (eg. table or ruler) or
5432 // 3. wrapping was enabled, it was not a space and following 5455 // 3. wrapping was enabled, it was not a space and following
5433 // condition is true: We either had a breakable character 5456 // condition is true: We either had a breakable character
5434 // previously or we ar allowed to break in words and - either 5457 // previously or we ar allowed to break in words and - either
5435 // we break at w pixels and the current char would exceed that 5458 // we break at w pixels and the current char would exceed that
5436 // or - we break at a column and the current character would 5459 // or - we break at a column and the current character would
5437 // exceed that. 5460 // exceed that.
5438 if ( lastWasHardBreak || lastWasOwnLineCustomItem || 5461 if ( lastWasHardBreak || lastWasOwnLineCustomItem ||
5439 ( wrapEnabled && 5462 ( wrapEnabled &&
5440 ( (!c->c.isSpace() && (hadBreakableChar || allowBreakInWords()) && 5463 ( (!c->c.isSpace() && (hadBreakableChar || allowBreakInWords()) &&
5441 ( (wrapAtColumn() == -1 && x + ww > w) || 5464 ( (wrapAtColumn() == -1 && x + ww > w) ||
5442 (wrapAtColumn() != -1 && col >= wrapAtColumn()) ) ) ) 5465 (wrapAtColumn() != -1 && col >= wrapAtColumn()) ) ) )
5443 ) 5466 )
5444 ) { 5467 ) {
5445 if ( wrapAtColumn() != -1 ) 5468 if ( wrapAtColumn() != -1 )
5446 minw = QMAX( minw, x + ww ); 5469 minw = QMAX( minw, x + ww );
5447 // if a break was forced (no breakable char, hard break or own line custom item), break immediately.... 5470 // if a break was forced (no breakable char, hard break or own line custom item), break immediately....
5448 if ( !hadBreakableChar || lastWasHardBreak || lastWasOwnLineCustomItem ) { 5471 if ( !hadBreakableChar || lastWasHardBreak || lastWasOwnLineCustomItem ) {
5449 if ( lineStart ) { 5472 if ( lineStart ) {
5450 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine ); 5473 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine );
5451 h = QMAX( h, tmph ); 5474 h = QMAX( h, tmph );
5452 lineStart->h = h; 5475 lineStart->h = h;
5453 DO_FLOW( lineStart ); 5476 DO_FLOW( lineStart );
5454 } 5477 }
5455 lineStart = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) ); 5478 lineStart = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) );
5456 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5479 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5457 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5480 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5458 if ( !doc && c->c == '\t' ) { // qt_format_text tab handling 5481 if ( !doc && c->c == '\t' ) { // qt_format_text tab handling
5459 int nx = parag->nextTab( i, x - left ) + left; 5482 int nx = parag->nextTab( i, x - left ) + left;
5460 if ( nx < x ) 5483 if ( nx < x )
5461 ww = w - x; 5484 ww = w - x;
5462 else 5485 else
5463 ww = nx - x; 5486 ww = nx - x;
5464 } 5487 }
5465 curLeft = x; 5488 curLeft = x;
5466 y += QMAX( h, linespacing ); 5489 y += QMAX( h, linespacing );
5467 tmph = c->height(); 5490 tmph = c->height();
5468 h = 0; 5491 h = 0;
5469 lineStart->y = y; 5492 lineStart->y = y;
5470 insertLineStart( parag, i, lineStart ); 5493 insertLineStart( parag, i, lineStart );
5471 lineStart->baseLine = c->ascent(); 5494 lineStart->baseLine = c->ascent();
5472 lineStart->h = c->height(); 5495 lineStart->h = c->height();
5473 c->lineStart = 1; 5496 c->lineStart = 1;
5474 firstChar = c; 5497 firstChar = c;
5475 tmpBaseLine = lineStart->baseLine; 5498 tmpBaseLine = lineStart->baseLine;
5476 lastBreak = -1; 5499 lastBreak = -1;
5477 col = 0; 5500 col = 0;
5478 } else { // ... otherwise if we had a breakable char, break there 5501 } else { // ... otherwise if we had a breakable char, break there
5479 DO_FLOW( lineStart ); 5502 DO_FLOW( lineStart );
5480 i = lastBreak; 5503 i = lastBreak;
5481 lineStart = formatLine( parag, string, lineStart, firstChar, parag->at( lastBreak ),align, SPACE(w - string->at( i ).x) ); 5504 lineStart = formatLine( parag, string, lineStart, firstChar, parag->at( lastBreak ),align, SPACE(w - string->at( i ).x) );
5482 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5505 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5483 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5506 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5484 if ( !doc && c->c == '\t' ) { // qt_format_text tab handling 5507 if ( !doc && c->c == '\t' ) { // qt_format_text tab handling
5485 int nx = parag->nextTab( i, x - left ) + left; 5508 int nx = parag->nextTab( i, x - left ) + left;
5486 if ( nx < x ) 5509 if ( nx < x )
5487 ww = w - x; 5510 ww = w - x;
5488 else 5511 else
5489 ww = nx - x; 5512 ww = nx - x;
5490 } 5513 }
5491 curLeft = x; 5514 curLeft = x;
5492 y += QMAX( h, linespacing ); 5515 y += QMAX( h, linespacing );
5493 tmph = c->height(); 5516 tmph = c->height();
5494 h = tmph; 5517 h = tmph;
5495 lineStart->y = y; 5518 lineStart->y = y;
5496 insertLineStart( parag, i + 1, lineStart ); 5519 insertLineStart( parag, i + 1, lineStart );
5497 lineStart->baseLine = c->ascent(); 5520 lineStart->baseLine = c->ascent();
5498 lineStart->h = c->height(); 5521 lineStart->h = c->height();
5499 c->lineStart = 1; 5522 c->lineStart = 1;
5500 firstChar = c; 5523 firstChar = c;
5501 tmpBaseLine = lineStart->baseLine; 5524 tmpBaseLine = lineStart->baseLine;
5502 lastBreak = -1; 5525 lastBreak = -1;
5503 col = 0; 5526 col = 0;
5504 tminw = marg; 5527 tminw = marg;
5505 continue; 5528 continue;
5506 } 5529 }
5507 } else if ( lineStart && isBreakable( string, i ) ) { 5530 } else if ( lineStart && isBreakable( string, i ) ) {
5508 if ( len <= 2 || i < len - 1 ) { 5531 if ( len <= 2 || i < len - 1 ) {
5509 tmpBaseLine = QMAX( tmpBaseLine, c->ascent() ); 5532 tmpBaseLine = QMAX( tmpBaseLine, c->ascent() );
5510 tmph = QMAX( tmph, c->height() ); 5533 tmph = QMAX( tmph, c->height() );
5511 } 5534 }
5512 minw = QMAX( minw, tminw ); 5535 minw = QMAX( minw, tminw );
5513 tminw = marg + ww; 5536 tminw = marg + ww;
5514 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine ); 5537 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine );
5515 h = QMAX( h, tmph ); 5538 h = QMAX( h, tmph );
5516 lineStart->h = h; 5539 lineStart->h = h;
5517 if ( i < len - 2 || c->c != ' ' ) 5540 if ( i < len - 2 || c->c != ' ' )
5518 lastBreak = i; 5541 lastBreak = i;
5519 } else { 5542 } else {
5520 tminw += ww; 5543 tminw += ww;
5521 int belowBaseLine = QMAX( tmph - tmpBaseLine, c->height()- c->ascent() ); 5544 int belowBaseLine = QMAX( tmph - tmpBaseLine, c->height()- c->ascent() );
5522 tmpBaseLine = QMAX( tmpBaseLine, c->ascent() ); 5545 tmpBaseLine = QMAX( tmpBaseLine, c->ascent() );
5523 tmph = tmpBaseLine + belowBaseLine; 5546 tmph = tmpBaseLine + belowBaseLine;
5524 } 5547 }
5525 5548
5526 c->x = x; 5549 c->x = x;
5527 x += ww; 5550 x += ww;
5528 wused = QMAX( wused, x ); 5551 wused = QMAX( wused, x );
5529 } 5552 }
5530 5553
5531 // ### hack. The last char in the paragraph is always invisible, 5554 // ### hack. The last char in the paragraph is always invisible,
5532 // ### and somehow sometimes has a wrong format. It changes 5555 // ### and somehow sometimes has a wrong format. It changes
5533 // ### between // layouting and printing. This corrects some 5556 // ### between // layouting and printing. This corrects some
5534 // ### layouting errors in BiDi mode due to this. 5557 // ### layouting errors in BiDi mode due to this.
5535 if ( len > 1 && !c->isAnchor() ) { 5558 if ( len > 1 && !c->isAnchor() ) {
5536 c->format()->removeRef(); 5559 c->format()->removeRef();
5537 c->setFormat( string->at( len - 2 ).format() ); 5560 c->setFormat( string->at( len - 2 ).format() );
5538 c->format()->addRef(); 5561 c->format()->addRef();
5539 } 5562 }
5540 5563
5541 if ( lineStart ) { 5564 if ( lineStart ) {
5542 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine ); 5565 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine );
5543 h = QMAX( h, tmph ); 5566 h = QMAX( h, tmph );
5544 lineStart->h = h; 5567 lineStart->h = h;
5545 // last line in a paragraph is not justified 5568 // last line in a paragraph is not justified
5546 if ( align == Qt3::AlignJustify || lastChr == QChar_linesep ) 5569 if ( align == Qt3::AlignJustify || lastChr == QChar_linesep )
5547 align = Qt3::AlignAuto; 5570 align = Qt3::AlignAuto;
5548 DO_FLOW( lineStart ); 5571 DO_FLOW( lineStart );
5549 lineStart = formatLine( parag, string, lineStart, firstChar, c, align, SPACE(w - x) ); 5572 lineStart = formatLine( parag, string, lineStart, firstChar, c, align, SPACE(w - x) );
5550 delete lineStart; 5573 delete lineStart;
5551 } 5574 }
5552 5575
5553 minw = QMAX( minw, tminw ); 5576 minw = QMAX( minw, tminw );
5554 if ( doc ) 5577 if ( doc )
5555 minw += doc->rightMargin(); 5578 minw += doc->rightMargin();
5556 5579
5557 int m = parag->bottomMargin(); 5580 int m = parag->bottomMargin();
5558 if ( !parag->next() ) 5581 if ( !parag->next() )
5559 m = 0; 5582 m = 0;
5560 else 5583 else
5561 m = QMAX(m, parag->next()->topMargin() ) / 2; 5584 m = QMAX(m, parag->next()->topMargin() ) / 2;
5562 parag->setFullWidth( fullWidth ); 5585 parag->setFullWidth( fullWidth );
5563 y += QMAX( h, linespacing ) + m; 5586 y += QMAX( h, linespacing ) + m;
5564 5587
5565 wused += rm; 5588 wused += rm;
5566 if ( !wrapEnabled || wrapAtColumn() != -1 ) 5589 if ( !wrapEnabled || wrapAtColumn() != -1 )
5567 minw = QMAX(minw, wused); 5590 minw = QMAX(minw, wused);
5568 5591
5569 // This is the case where we are breaking wherever we darn well please 5592 // This is the case where we are breaking wherever we darn well please
5570 // in cases like that, the minw should not be the length of the entire 5593 // in cases like that, the minw should not be the length of the entire
5571 // word, because we necessarily want to show the word on the whole line. 5594 // word, because we necessarily want to show the word on the whole line.
5572 // example: word wrap in iconview 5595 // example: word wrap in iconview
5573 if ( allowBreakInWords() && minw > wused ) 5596 if ( allowBreakInWords() && minw > wused )
5574 minw = wused; 5597 minw = wused;
5575 5598
5576 thisminw = minw; 5599 thisminw = minw;
5577 thiswused = wused; 5600 thiswused = wused;
5578 return y; 5601 return y;
5579} 5602}
5580 5603
5581// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5604// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5582 5605
5583QTextIndent::QTextIndent() 5606QTextIndent::QTextIndent()
5584{ 5607{
5585} 5608}
5586 5609
5587// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5610// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5588 5611
5589QTextFormatCollection::QTextFormatCollection() 5612QTextFormatCollection::QTextFormatCollection()
5590 : cKey( 307 ) 5613 : cKey( 307 )
5591{ 5614{
5592 defFormat = new QTextFormat( QApplication::font(), 5615 defFormat = new QTextFormat( QApplication::font(),
5593 QApplication::palette().color( QPalette::Active, QColorGroup::Text ) ); 5616 QApplication::palette().color( QPalette::Active, QColorGroup::Text ) );
5594 lastFormat = cres = 0; 5617 lastFormat = cres = 0;
5595 cflags = -1; 5618 cflags = -1;
5596 cKey.setAutoDelete( TRUE ); 5619 cKey.setAutoDelete( TRUE );
5597 cachedFormat = 0; 5620 cachedFormat = 0;
5598} 5621}
5599 5622
5600QTextFormatCollection::~QTextFormatCollection() 5623QTextFormatCollection::~QTextFormatCollection()
5601{ 5624{
5602 delete defFormat; 5625 delete defFormat;
5603} 5626}
5604 5627
5605QTextFormat *QTextFormatCollection::format( QTextFormat *f ) 5628QTextFormat *QTextFormatCollection::format( QTextFormat *f )
5606{ 5629{
5607 if ( f->parent() == this || f == defFormat ) { 5630 if ( f->parent() == this || f == defFormat ) {
5608 lastFormat = f; 5631 lastFormat = f;
5609 lastFormat->addRef(); 5632 lastFormat->addRef();
5610 return lastFormat; 5633 return lastFormat;
5611 } 5634 }
5612 5635
5613 if ( f == lastFormat || ( lastFormat && f->key() == lastFormat->key() ) ) { 5636 if ( f == lastFormat || ( lastFormat && f->key() == lastFormat->key() ) ) {
5614 lastFormat->addRef(); 5637 lastFormat->addRef();
5615 return lastFormat; 5638 return lastFormat;
5616 } 5639 }
5617 5640
5618 QTextFormat *fm = cKey.find( f->key() ); 5641 QTextFormat *fm = cKey.find( f->key() );
5619 if ( fm ) { 5642 if ( fm ) {
5620 lastFormat = fm; 5643 lastFormat = fm;
5621 lastFormat->addRef(); 5644 lastFormat->addRef();
5622 return lastFormat; 5645 return lastFormat;
5623 } 5646 }
5624 5647
5625 if ( f->key() == defFormat->key() ) 5648 if ( f->key() == defFormat->key() )
5626 return defFormat; 5649 return defFormat;
5627 5650
5628 lastFormat = createFormat( *f ); 5651 lastFormat = createFormat( *f );
5629 lastFormat->collection = this; 5652 lastFormat->collection = this;
5630 cKey.insert( lastFormat->key(), lastFormat ); 5653 cKey.insert( lastFormat->key(), lastFormat );
5631 return lastFormat; 5654 return lastFormat;
5632} 5655}
5633 5656
5634QTextFormat *QTextFormatCollection::format( QTextFormat *of, QTextFormat *nf, int flags ) 5657QTextFormat *QTextFormatCollection::format( QTextFormat *of, QTextFormat *nf, int flags )
5635{ 5658{
5636 if ( cres && kof == of->key() && knf == nf->key() && cflags == flags ) { 5659 if ( cres && kof == of->key() && knf == nf->key() && cflags == flags ) {
5637 cres->addRef(); 5660 cres->addRef();
5638 return cres; 5661 return cres;
5639 } 5662 }
5640 5663
5641 cres = createFormat( *of ); 5664 cres = createFormat( *of );
5642 kof = of->key(); 5665 kof = of->key();
5643 knf = nf->key(); 5666 knf = nf->key();
5644 cflags = flags; 5667 cflags = flags;
5645 if ( flags & QTextFormat::Bold ) 5668 if ( flags & QTextFormat::Bold )
5646 cres->fn.setBold( nf->fn.bold() ); 5669 cres->fn.setBold( nf->fn.bold() );
5647 if ( flags & QTextFormat::Italic ) 5670 if ( flags & QTextFormat::Italic )
5648 cres->fn.setItalic( nf->fn.italic() ); 5671 cres->fn.setItalic( nf->fn.italic() );
5649 if ( flags & QTextFormat::Underline ) 5672 if ( flags & QTextFormat::Underline )
5650 cres->fn.setUnderline( nf->fn.underline() ); 5673 cres->fn.setUnderline( nf->fn.underline() );
5651 if ( flags & QTextFormat::StrikeOut ) 5674 if ( flags & QTextFormat::StrikeOut )
5652 cres->fn.setStrikeOut( nf->fn.strikeOut() ); 5675 cres->fn.setStrikeOut( nf->fn.strikeOut() );
5653 if ( flags & QTextFormat::Family ) 5676 if ( flags & QTextFormat::Family )
5654 cres->fn.setFamily( nf->fn.family() ); 5677 cres->fn.setFamily( nf->fn.family() );
5655 if ( flags & QTextFormat::Size ) { 5678 if ( flags & QTextFormat::Size ) {
5656 if ( of->usePixelSizes ) 5679 if ( of->usePixelSizes )
5657 cres->fn.setPixelSize( nf->fn.pixelSize() ); 5680 cres->fn.setPixelSize( nf->fn.pixelSize() );
5658 else 5681 else
5659 cres->fn.setPointSize( nf->fn.pointSize() ); 5682 cres->fn.setPointSize( nf->fn.pointSize() );
5660 } 5683 }
5661 if ( flags & QTextFormat::Color ) 5684 if ( flags & QTextFormat::Color )
5662 cres->col = nf->col; 5685 cres->col = nf->col;
5663 if ( flags & QTextFormat::Misspelled ) 5686 if ( flags & QTextFormat::Misspelled )
5664 cres->missp = nf->missp; 5687 cres->missp = nf->missp;
5665 if ( flags & QTextFormat::VAlign ) 5688 if ( flags & QTextFormat::VAlign )
5666 cres->ha = nf->ha; 5689 cres->ha = nf->ha;
5667 cres->update(); 5690 cres->update();
5668 5691
5669 QTextFormat *fm = cKey.find( cres->key() ); 5692 QTextFormat *fm = cKey.find( cres->key() );
5670 if ( !fm ) { 5693 if ( !fm ) {
5671 cres->collection = this; 5694 cres->collection = this;
5672 cKey.insert( cres->key(), cres ); 5695 cKey.insert( cres->key(), cres );
5673 } else { 5696 } else {
5674 delete cres; 5697 delete cres;
5675 cres = fm; 5698 cres = fm;
5676 cres->addRef(); 5699 cres->addRef();
5677 } 5700 }
5678 5701
5679 return cres; 5702 return cres;
5680} 5703}
5681 5704
5682QTextFormat *QTextFormatCollection::format( const QFont &f, const QColor &c ) 5705QTextFormat *QTextFormatCollection::format( const QFont &f, const QColor &c )
5683{ 5706{
5684 if ( cachedFormat && cfont == f && ccol == c ) { 5707 if ( cachedFormat && cfont == f && ccol == c ) {
5685 cachedFormat->addRef(); 5708 cachedFormat->addRef();
5686 return cachedFormat; 5709 return cachedFormat;
5687 } 5710 }
5688 5711
5689 QString key = QTextFormat::getKey( f, c, FALSE, QTextFormat::AlignNormal ); 5712 QString key = QTextFormat::getKey( f, c, FALSE, QTextFormat::AlignNormal );
5690 cachedFormat = cKey.find( key ); 5713 cachedFormat = cKey.find( key );
5691 cfont = f; 5714 cfont = f;
5692 ccol = c; 5715 ccol = c;
5693 5716
5694 if ( cachedFormat ) { 5717 if ( cachedFormat ) {
5695 cachedFormat->addRef(); 5718 cachedFormat->addRef();
5696 return cachedFormat; 5719 return cachedFormat;
5697 } 5720 }
5698 5721
5699 if ( key == defFormat->key() ) 5722 if ( key == defFormat->key() )
5700 return defFormat; 5723 return defFormat;
5701 5724
5702 cachedFormat = createFormat( f, c ); 5725 cachedFormat = createFormat( f, c );
5703 cachedFormat->collection = this; 5726 cachedFormat->collection = this;
5704 cKey.insert( cachedFormat->key(), cachedFormat ); 5727 cKey.insert( cachedFormat->key(), cachedFormat );
5705 if ( cachedFormat->key() != key ) 5728 if ( cachedFormat->key() != key )
5706 owarn << "ASSERT: keys for format not identical: '" << cachedFormat->key().latin1() << " '" << key.latin1() << "'" << oendl; 5729 owarn << "ASSERT: keys for format not identical: '" << cachedFormat->key().latin1() << " '" << key.latin1() << "'" << oendl;
5707 return cachedFormat; 5730 return cachedFormat;
5708} 5731}
5709 5732
5710void QTextFormatCollection::remove( QTextFormat *f ) 5733void QTextFormatCollection::remove( QTextFormat *f )
5711{ 5734{
5712 if ( lastFormat == f ) 5735 if ( lastFormat == f )
5713 lastFormat = 0; 5736 lastFormat = 0;
5714 if ( cres == f ) 5737 if ( cres == f )
5715 cres = 0; 5738 cres = 0;
5716 if ( cachedFormat == f ) 5739 if ( cachedFormat == f )
5717 cachedFormat = 0; 5740 cachedFormat = 0;
5718 cKey.remove( f->key() ); 5741 cKey.remove( f->key() );
5719} 5742}
5720 5743
5721#define UPDATE( up, lo, rest ) \ 5744#define UPDATE( up, lo, rest ) \
5722 if ( font.lo##rest() != defFormat->fn.lo##rest() && fm->fn.lo##rest() == defFormat->fn.lo##rest() ) \ 5745 if ( font.lo##rest() != defFormat->fn.lo##rest() && fm->fn.lo##rest() == defFormat->fn.lo##rest() ) \
5723 fm->fn.set##up##rest( font.lo##rest() ) 5746 fm->fn.set##up##rest( font.lo##rest() )
5724 5747
5725void QTextFormatCollection::updateDefaultFormat( const QFont &font, const QColor &color, QStyleSheet *sheet ) 5748void QTextFormatCollection::updateDefaultFormat( const QFont &font, const QColor &color, QStyleSheet *sheet )
5726{ 5749{
5727 QDictIterator<QTextFormat> it( cKey ); 5750 QDictIterator<QTextFormat> it( cKey );
5728 QTextFormat *fm; 5751 QTextFormat *fm;
5729 bool usePixels = font.pointSize() == -1; 5752 bool usePixels = font.pointSize() == -1;
5730 bool changeSize = usePixels ? font.pixelSize() != defFormat->fn.pixelSize() : 5753 bool changeSize = usePixels ? font.pixelSize() != defFormat->fn.pixelSize() :
5731 font.pointSize() != defFormat->fn.pointSize(); 5754 font.pointSize() != defFormat->fn.pointSize();
5732 int base = usePixels ? font.pixelSize() : font.pointSize(); 5755 int base = usePixels ? font.pixelSize() : font.pointSize();
5733 while ( ( fm = it.current() ) ) { 5756 while ( ( fm = it.current() ) ) {
5734 ++it; 5757 ++it;
5735 UPDATE( F, f, amily ); 5758 UPDATE( F, f, amily );
5736 UPDATE( W, w, eight ); 5759 UPDATE( W, w, eight );
5737 UPDATE( B, b, old ); 5760 UPDATE( B, b, old );
5738 UPDATE( I, i, talic ); 5761 UPDATE( I, i, talic );
5739 UPDATE( U, u, nderline ); 5762 UPDATE( U, u, nderline );
5740 if ( changeSize ) { 5763 if ( changeSize ) {
5741 fm->stdSize = base; 5764 fm->stdSize = base;
5742 fm->usePixelSizes = usePixels; 5765 fm->usePixelSizes = usePixels;
5743 if ( usePixels ) 5766 if ( usePixels )
5744 fm->fn.setPixelSize( fm->stdSize ); 5767 fm->fn.setPixelSize( fm->stdSize );
5745 else 5768 else
5746 fm->fn.setPointSize( fm->stdSize ); 5769 fm->fn.setPointSize( fm->stdSize );
5747 sheet->scaleFont( fm->fn, fm->logicalFontSize ); 5770 sheet->scaleFont( fm->fn, fm->logicalFontSize );
5748 } 5771 }
5749 if ( color.isValid() && color != defFormat->col && fm->col == defFormat->col ) 5772 if ( color.isValid() && color != defFormat->col && fm->col == defFormat->col )
5750 fm->col = color; 5773 fm->col = color;
5751 fm->update(); 5774 fm->update();
5752 } 5775 }
5753 5776
5754 defFormat->fn = font; 5777 defFormat->fn = font;
5755 defFormat->col = color; 5778 defFormat->col = color;
5756 defFormat->update(); 5779 defFormat->update();
5757 defFormat->stdSize = base; 5780 defFormat->stdSize = base;
5758 defFormat->usePixelSizes = usePixels; 5781 defFormat->usePixelSizes = usePixels;
5759 5782
5760 updateKeys(); 5783 updateKeys();
5761} 5784}
5762 5785
5763// the keys in cKey have changed, rebuild the hashtable 5786// the keys in cKey have changed, rebuild the hashtable
5764void QTextFormatCollection::updateKeys() 5787void QTextFormatCollection::updateKeys()
5765{ 5788{
5766 if ( cKey.isEmpty() ) 5789 if ( cKey.isEmpty() )
5767 return; 5790 return;
5768 cKey.setAutoDelete( FALSE ); 5791 cKey.setAutoDelete( FALSE );
5769 QTextFormat** formats = new QTextFormat*[ cKey.count() + 1 ]; 5792 QTextFormat** formats = new QTextFormat*[ cKey.count() + 1 ];
5770 QTextFormat **f = formats; 5793 QTextFormat **f = formats;
5771 QDictIterator<QTextFormat> it( cKey ); 5794 QDictIterator<QTextFormat> it( cKey );
5772 while ( ( *f = it.current() ) ) { 5795 while ( ( *f = it.current() ) ) {
5773 ++it; 5796 ++it;
5774 ++f; 5797 ++f;
5775 } 5798 }
5776 cKey.clear(); 5799 cKey.clear();
5777 for ( f = formats; *f; f++ ) 5800 for ( f = formats; *f; f++ )
5778 cKey.insert( (*f)->key(), *f ); 5801 cKey.insert( (*f)->key(), *f );
5779 cKey.setAutoDelete( TRUE ); 5802 cKey.setAutoDelete( TRUE );
5780 delete [] formats; 5803 delete [] formats;
5781} 5804}
5782 5805
5783 5806
5784 5807
5785// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5808// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5786 5809
5787void QTextFormat::setBold( bool b ) 5810void QTextFormat::setBold( bool b )
5788{ 5811{
5789 if ( b == fn.bold() ) 5812 if ( b == fn.bold() )
5790 return; 5813 return;
5791 fn.setBold( b ); 5814 fn.setBold( b );
5792 update(); 5815 update();
5793} 5816}
5794 5817
5795void QTextFormat::setMisspelled( bool b ) 5818void QTextFormat::setMisspelled( bool b )
5796{ 5819{
5797 if ( b == (bool)missp ) 5820 if ( b == (bool)missp )
5798 return; 5821 return;
5799 missp = b; 5822 missp = b;
5800 update(); 5823 update();
5801} 5824}
5802 5825
5803void QTextFormat::setVAlign( VerticalAlignment a ) 5826void QTextFormat::setVAlign( VerticalAlignment a )
5804{ 5827{
5805 if ( a == ha ) 5828 if ( a == ha )
5806 return; 5829 return;
5807 ha = a; 5830 ha = a;
5808 update(); 5831 update();
5809} 5832}
5810 5833
5811void QTextFormat::setItalic( bool b ) 5834void QTextFormat::setItalic( bool b )
5812{ 5835{
5813 if ( b == fn.italic() ) 5836 if ( b == fn.italic() )
5814 return; 5837 return;
5815 fn.setItalic( b ); 5838 fn.setItalic( b );
5816 update(); 5839 update();
5817} 5840}
5818 5841
5819void QTextFormat::setUnderline( bool b ) 5842void QTextFormat::setUnderline( bool b )
5820{ 5843{
5821 if ( b == fn.underline() ) 5844 if ( b == fn.underline() )
5822 return; 5845 return;
5823 fn.setUnderline( b ); 5846 fn.setUnderline( b );
5824 update(); 5847 update();
5825} 5848}
5826 5849
5827void QTextFormat::setStrikeOut( bool b ) 5850void QTextFormat::setStrikeOut( bool b )
5828{ 5851{
5829 if ( b == fn.strikeOut() ) 5852 if ( b == fn.strikeOut() )
5830 return; 5853 return;
5831 fn.setStrikeOut( b ); 5854 fn.setStrikeOut( b );
5832 update(); 5855 update();
5833} 5856}
5834 5857
5835void QTextFormat::setFamily( const QString &f ) 5858void QTextFormat::setFamily( const QString &f )
5836{ 5859{
5837 if ( f == fn.family() ) 5860 if ( f == fn.family() )
5838 return; 5861 return;
5839 fn.setFamily( f ); 5862 fn.setFamily( f );
5840 update(); 5863 update();
5841} 5864}
5842 5865
5843void QTextFormat::setPointSize( int s ) 5866void QTextFormat::setPointSize( int s )
5844{ 5867{
5845 if ( s == fn.pointSize() ) 5868 if ( s == fn.pointSize() )
5846 return; 5869 return;
5847 fn.setPointSize( s ); 5870 fn.setPointSize( s );
5848 usePixelSizes = FALSE; 5871 usePixelSizes = FALSE;
5849 update(); 5872 update();
5850} 5873}
5851 5874
5852void QTextFormat::setFont( const QFont &f ) 5875void QTextFormat::setFont( const QFont &f )
5853{ 5876{
5854 if ( f == fn && !k.isEmpty() ) 5877 if ( f == fn && !k.isEmpty() )
5855 return; 5878 return;
5856 fn = f; 5879 fn = f;
5857 update(); 5880 update();
5858} 5881}
5859 5882
5860void QTextFormat::setColor( const QColor &c ) 5883void QTextFormat::setColor( const QColor &c )
5861{ 5884{
5862 if ( c == col ) 5885 if ( c == col )
5863 return; 5886 return;
5864 col = c; 5887 col = c;
5865 update(); 5888 update();
5866} 5889}
5867 5890
5868QString QTextFormat::makeFormatChangeTags( QTextFormat* defaultFormat, QTextFormat *f, 5891QString QTextFormat::makeFormatChangeTags( QTextFormat* defaultFormat, QTextFormat *f,
5869 const QString& oldAnchorHref, const QString& anchorHref ) const 5892 const QString& oldAnchorHref, const QString& anchorHref ) const
5870{ 5893{
5871 QString tag; 5894 QString tag;
5872 if ( f ) 5895 if ( f )
5873 tag += f->makeFormatEndTags( defaultFormat, oldAnchorHref ); 5896 tag += f->makeFormatEndTags( defaultFormat, oldAnchorHref );
5874 5897
5875 if ( !anchorHref.isEmpty() ) 5898 if ( !anchorHref.isEmpty() )
5876 tag += "<a href=\"" + anchorHref + "\">"; 5899 tag += "<a href=\"" + anchorHref + "\">";
5877 5900
5878 if ( font() != defaultFormat->font() 5901 if ( font() != defaultFormat->font()
5879 || vAlign() != defaultFormat->vAlign() 5902 || vAlign() != defaultFormat->vAlign()
5880 || color().rgb() != defaultFormat->color().rgb() ) { 5903 || color().rgb() != defaultFormat->color().rgb() ) {
5881 QString s; 5904 QString s;
5882 if ( font().family() != defaultFormat->font().family() ) 5905 if ( font().family() != defaultFormat->font().family() )
5883 s += QString(!!s?";":"") + "font-family:" + fn.family(); 5906 s += QString(!!s?";":"") + "font-family:" + fn.family();
5884 if ( font().italic() && font().italic() != defaultFormat->font().italic() ) 5907 if ( font().italic() && font().italic() != defaultFormat->font().italic() )
5885 s += QString(!!s?";":"") + "font-style:" + (font().italic() ? "italic" : "normal"); 5908 s += QString(!!s?";":"") + "font-style:" + (font().italic() ? "italic" : "normal");
5886 if ( font().pointSize() != defaultFormat->font().pointSize() ) 5909 if ( font().pointSize() != defaultFormat->font().pointSize() )
5887 s += QString(!!s?";":"") + "font-size:" + QString::number( fn.pointSize() ) + "pt"; 5910 s += QString(!!s?";":"") + "font-size:" + QString::number( fn.pointSize() ) + "pt";
5888 if ( font().weight() != defaultFormat->font().weight() ) 5911 if ( font().weight() != defaultFormat->font().weight() )
5889 s += QString(!!s?";":"") + "font-weight:" + QString::number( fn.weight() * 8 ); 5912 s += QString(!!s?";":"") + "font-weight:" + QString::number( fn.weight() * 8 );
5890 if ( font().underline() != defaultFormat->font().underline() ) 5913 if ( font().underline() != defaultFormat->font().underline() )
5891 s += QString(!!s?";":"") + "text-decoration:" + ( font().underline() ? "underline" : "none"); 5914 s += QString(!!s?";":"") + "text-decoration:" + ( font().underline() ? "underline" : "none");
5892 if ( vAlign() != defaultFormat->vAlign() ) { 5915 if ( vAlign() != defaultFormat->vAlign() ) {
5893 s += QString(!!s?";":"") + "vertical-align:"; 5916 s += QString(!!s?";":"") + "vertical-align:";
5894 if ( vAlign() == QTextFormat::AlignSuperScript ) 5917 if ( vAlign() == QTextFormat::AlignSuperScript )
5895 s += "super"; 5918 s += "super";
5896 else if ( vAlign() == QTextFormat::AlignSubScript ) 5919 else if ( vAlign() == QTextFormat::AlignSubScript )
5897 s += "sub"; 5920 s += "sub";
5898 else 5921 else
5899 s += "normal"; 5922 s += "normal";
5900 } 5923 }
5901 if ( color().rgb() != defaultFormat->color().rgb() ) 5924 if ( color().rgb() != defaultFormat->color().rgb() )
5902 s += QString(!!s?";":"") + "color:" + col.name(); 5925 s += QString(!!s?";":"") + "color:" + col.name();
5903 if ( !s.isEmpty() ) 5926 if ( !s.isEmpty() )
5904 tag += "<span style=\"" + s + "\">"; 5927 tag += "<span style=\"" + s + "\">";
5905 } 5928 }
5906 5929
5907 return tag; 5930 return tag;
5908} 5931}
5909 5932
5910QString QTextFormat::makeFormatEndTags( QTextFormat* defaultFormat, const QString& anchorHref ) const 5933QString QTextFormat::makeFormatEndTags( QTextFormat* defaultFormat, const QString& anchorHref ) const
5911{ 5934{
5912 QString tag; 5935 QString tag;
5913 if ( font().family() != defaultFormat->font().family() 5936 if ( font().family() != defaultFormat->font().family()
5914 || font().pointSize() != defaultFormat->font().pointSize() 5937 || font().pointSize() != defaultFormat->font().pointSize()
5915 || font().weight() != defaultFormat->font().weight() 5938 || font().weight() != defaultFormat->font().weight()
5916 || font().italic() != defaultFormat->font().italic() 5939 || font().italic() != defaultFormat->font().italic()
5917 || font().underline() != defaultFormat->font().underline() 5940 || font().underline() != defaultFormat->font().underline()
5918 || font().strikeOut() != defaultFormat->font().strikeOut() 5941 || font().strikeOut() != defaultFormat->font().strikeOut()
5919 || vAlign() != defaultFormat->vAlign() 5942 || vAlign() != defaultFormat->vAlign()
5920 || color().rgb() != defaultFormat->color().rgb() ) 5943 || color().rgb() != defaultFormat->color().rgb() )
5921 tag += "</span>"; 5944 tag += "</span>";
5922 if ( !anchorHref.isEmpty() ) 5945 if ( !anchorHref.isEmpty() )
5923 tag += "</a>"; 5946 tag += "</a>";
5924 return tag; 5947 return tag;
5925} 5948}
5926 5949
5927QTextFormat QTextFormat::makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr, double scaleFontsFactor ) const 5950QTextFormat QTextFormat::makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr, double scaleFontsFactor ) const
5928{ 5951{
5929 QTextFormat format(*this); 5952 QTextFormat format(*this);
5930 if (!style ) 5953 if (!style )
5931 return format; 5954 return format;
5932 5955
5933 if ( !style->isAnchor() && style->color().isValid() ) { 5956 if ( !style->isAnchor() && style->color().isValid() ) {
5934 // the style is not an anchor and defines a color. 5957 // the style is not an anchor and defines a color.
5935 // It might be used inside an anchor and it should 5958 // It might be used inside an anchor and it should
5936 // override the link color. 5959 // override the link color.
5937 format.linkColor = FALSE; 5960 format.linkColor = FALSE;
5938 } 5961 }
5939 switch ( style->verticalAlignment() ) { 5962 switch ( style->verticalAlignment() ) {
5940 case QStyleSheetItem::VAlignBaseline: 5963 case QStyleSheetItem::VAlignBaseline:
5941 format.setVAlign( QTextFormat::AlignNormal ); 5964 format.setVAlign( QTextFormat::AlignNormal );
5942 break; 5965 break;
5943 case QStyleSheetItem::VAlignSuper: 5966 case QStyleSheetItem::VAlignSuper:
5944 format.setVAlign( QTextFormat::AlignSuperScript ); 5967 format.setVAlign( QTextFormat::AlignSuperScript );
5945 break; 5968 break;
5946 case QStyleSheetItem::VAlignSub: 5969 case QStyleSheetItem::VAlignSub:
5947 format.setVAlign( QTextFormat::AlignSubScript ); 5970 format.setVAlign( QTextFormat::AlignSubScript );
5948 break; 5971 break;
5949 } 5972 }
5950 5973
5951 if ( style->fontWeight() != QStyleSheetItem::Undefined ) 5974 if ( style->fontWeight() != QStyleSheetItem::Undefined )
5952 format.fn.setWeight( style->fontWeight() ); 5975 format.fn.setWeight( style->fontWeight() );
5953 if ( style->fontSize() != QStyleSheetItem::Undefined ) { 5976 if ( style->fontSize() != QStyleSheetItem::Undefined ) {
5954 format.fn.setPointSize( style->fontSize() ); 5977 format.fn.setPointSize( style->fontSize() );
5955 } else if ( style->logicalFontSize() != QStyleSheetItem::Undefined ) { 5978 } else if ( style->logicalFontSize() != QStyleSheetItem::Undefined ) {
5956 format.logicalFontSize = style->logicalFontSize(); 5979 format.logicalFontSize = style->logicalFontSize();
5957 if ( format.usePixelSizes ) 5980 if ( format.usePixelSizes )
5958 format.fn.setPixelSize( format.stdSize ); 5981 format.fn.setPixelSize( format.stdSize );
5959 else 5982 else
5960 format.fn.setPointSize( format.stdSize ); 5983 format.fn.setPointSize( format.stdSize );
5961 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); 5984 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize );
5962 } else if ( style->logicalFontSizeStep() ) { 5985 } else if ( style->logicalFontSizeStep() ) {
5963 format.logicalFontSize += style->logicalFontSizeStep(); 5986 format.logicalFontSize += style->logicalFontSizeStep();
5964 if ( format.usePixelSizes ) 5987 if ( format.usePixelSizes )
5965 format.fn.setPixelSize( format.stdSize ); 5988 format.fn.setPixelSize( format.stdSize );
5966 else 5989 else
5967 format.fn.setPointSize( format.stdSize ); 5990 format.fn.setPointSize( format.stdSize );
5968 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); 5991 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize );
5969 } 5992 }
5970 if ( !style->fontFamily().isEmpty() ) 5993 if ( !style->fontFamily().isEmpty() )
5971 format.fn.setFamily( style->fontFamily() ); 5994 format.fn.setFamily( style->fontFamily() );
5972 if ( style->color().isValid() ) 5995 if ( style->color().isValid() )
5973 format.col = style->color(); 5996 format.col = style->color();
5974 if ( style->definesFontItalic() ) 5997 if ( style->definesFontItalic() )
5975 format.fn.setItalic( style->fontItalic() ); 5998 format.fn.setItalic( style->fontItalic() );
5976 if ( style->definesFontUnderline() ) 5999 if ( style->definesFontUnderline() )
5977 format.fn.setUnderline( style->fontUnderline() ); 6000 format.fn.setUnderline( style->fontUnderline() );
5978 if ( style->definesFontStrikeOut() ) 6001 if ( style->definesFontStrikeOut() )
5979 format.fn.setStrikeOut( style->fontStrikeOut() ); 6002 format.fn.setStrikeOut( style->fontStrikeOut() );
5980 6003
5981 6004
5982 if ( style->name() == "font") { 6005 if ( style->name() == "font") {
5983 if ( attr.contains("color") ) { 6006 if ( attr.contains("color") ) {
5984 QString s = attr["color"]; 6007 QString s = attr["color"];
5985 if ( !s.isEmpty() ) { 6008 if ( !s.isEmpty() ) {
5986 format.col.setNamedColor( s ); 6009 format.col.setNamedColor( s );
5987 format.linkColor = FALSE; 6010 format.linkColor = FALSE;
5988 } 6011 }
5989 } 6012 }
5990 if ( attr.contains("face") ) { 6013 if ( attr.contains("face") ) {
5991 QString a = attr["face"]; 6014 QString a = attr["face"];
5992 QString family = QTextDocument::section( a, ",", 0, 0 ); 6015 QString family = QTextDocument::section( a, ",", 0, 0 );
5993 if ( !!family ) 6016 if ( !!family )
5994 format.fn.setFamily( family ); 6017 format.fn.setFamily( family );
5995 } 6018 }
5996 if ( attr.contains("size") ) { 6019 if ( attr.contains("size") ) {
5997 QString a = attr["size"]; 6020 QString a = attr["size"];
5998 int n = a.toInt(); 6021 int n = a.toInt();
5999 if ( a[0] == '+' || a[0] == '-' ) 6022 if ( a[0] == '+' || a[0] == '-' )
6000 n += format.logicalFontSize; 6023 n += format.logicalFontSize;
6001 format.logicalFontSize = n; 6024 format.logicalFontSize = n;
6002 if ( format.usePixelSizes ) 6025 if ( format.usePixelSizes )
6003 format.fn.setPixelSize( format.stdSize ); 6026 format.fn.setPixelSize( format.stdSize );
6004 else 6027 else
6005 format.fn.setPointSize( format.stdSize ); 6028 format.fn.setPointSize( format.stdSize );
6006 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); 6029 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize );
6007 } 6030 }
6008 } 6031 }
6009 if ( attr.contains("style" ) ) { 6032 if ( attr.contains("style" ) ) {
6010 QString a = attr["style"]; 6033 QString a = attr["style"];
6011 for ( int s = 0; s < a.contains(';')+1; s++ ) { 6034 for ( int s = 0; s < a.contains(';')+1; s++ ) {
6012 QString style = QTextDocument::section( a, ";", s, s ); 6035 QString style = QTextDocument::section( a, ";", s, s );
6013 if ( style.startsWith("font-size:" ) && QTextDocument::endsWith(style, "pt") ) { 6036 if ( style.startsWith("font-size:" ) && QTextDocument::endsWith(style, "pt") ) {
6014 format.logicalFontSize = 0; 6037 format.logicalFontSize = 0;
6015 format.setPointSize( int( scaleFontsFactor * style.mid( 10, style.length() - 12 ).toInt() ) ); 6038 format.setPointSize( int( scaleFontsFactor * style.mid( 10, style.length() - 12 ).toInt() ) );
6016 } if ( style.startsWith("font-style:" ) ) { 6039 } if ( style.startsWith("font-style:" ) ) {
6017 QString s = style.mid( 11 ).stripWhiteSpace(); 6040 QString s = style.mid( 11 ).stripWhiteSpace();
6018 if ( s == "normal" ) 6041 if ( s == "normal" )
6019 format.fn.setItalic( FALSE ); 6042 format.fn.setItalic( FALSE );
6020 else if ( s == "italic" || s == "oblique" ) 6043 else if ( s == "italic" || s == "oblique" )
6021 format.fn.setItalic( TRUE ); 6044 format.fn.setItalic( TRUE );
6022 } else if ( style.startsWith("font-weight:" ) ) { 6045 } else if ( style.startsWith("font-weight:" ) ) {
6023 QString s = style.mid( 12 ); 6046 QString s = style.mid( 12 );
6024 bool ok = TRUE; 6047 bool ok = TRUE;
6025 int n = s.toInt( &ok ); 6048 int n = s.toInt( &ok );
6026 if ( ok ) 6049 if ( ok )
6027 format.fn.setWeight( n/8 ); 6050 format.fn.setWeight( n/8 );
6028 } else if ( style.startsWith("font-family:" ) ) { 6051 } else if ( style.startsWith("font-family:" ) ) {
6029 format.fn.setFamily( QTextDocument::section(style.mid(12),",",0,0).stripWhiteSpace() ); 6052 format.fn.setFamily( QTextDocument::section(style.mid(12),",",0,0).stripWhiteSpace() );
6030 } else if ( style.startsWith("text-decoration:" ) ) { 6053 } else if ( style.startsWith("text-decoration:" ) ) {
6031 QString s = style.mid( 16 ).stripWhiteSpace(); 6054 QString s = style.mid( 16 ).stripWhiteSpace();
6032 format.fn.setUnderline( s == "underline" ); 6055 format.fn.setUnderline( s == "underline" );
6033 } else if ( style.startsWith("vertical-align:" ) ) { 6056 } else if ( style.startsWith("vertical-align:" ) ) {
6034 QString s = style.mid( 15 ).stripWhiteSpace(); 6057 QString s = style.mid( 15 ).stripWhiteSpace();
6035 if ( s == "sub" ) 6058 if ( s == "sub" )
6036 format.setVAlign( QTextFormat::AlignSubScript ); 6059 format.setVAlign( QTextFormat::AlignSubScript );
6037 else if ( s == "super" ) 6060 else if ( s == "super" )
6038 format.setVAlign( QTextFormat::AlignSuperScript ); 6061 format.setVAlign( QTextFormat::AlignSuperScript );
6039 else 6062 else
6040 format.setVAlign( QTextFormat::AlignNormal ); 6063 format.setVAlign( QTextFormat::AlignNormal );
6041 } else if ( style.startsWith("color:" ) ) { 6064 } else if ( style.startsWith("color:" ) ) {
6042 format.col.setNamedColor( style.mid(6) ); 6065 format.col.setNamedColor( style.mid(6) );
6043 format.linkColor = FALSE; 6066 format.linkColor = FALSE;
6044 } 6067 }
6045 } 6068 }
6046 } 6069 }
6047 6070
6048 format.update(); 6071 format.update();
6049 return format; 6072 return format;
6050} 6073}
6051 6074
6052struct QPixmapInt 6075struct QPixmapInt
6053{ 6076{
6054 QPixmapInt() : ref( 0 ) {} 6077 QPixmapInt() : ref( 0 ) {}
6055 QPixmap pm; 6078 QPixmap pm;
6056 int ref; 6079 int ref;
6057}; 6080};
6058 6081
6059static QMap<QString, QPixmapInt> *pixmap_map = 0; 6082static QMap<QString, QPixmapInt> *pixmap_map = 0;
6060 6083
6061QTextImage::QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context, 6084QTextImage::QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context,
6062 QMimeSourceFactory &factory ) 6085 QMimeSourceFactory &factory )
6063 : QTextCustomItem( p ), reg( 0 ) 6086 : QTextCustomItem( p ), reg( 0 )
6064{ 6087{
6065 width = height = 0; 6088 width = height = 0;
6066 if ( attr.contains("width") ) 6089 if ( attr.contains("width") )
6067 width = attr["width"].toInt(); 6090 width = attr["width"].toInt();
6068 if ( attr.contains("height") ) 6091 if ( attr.contains("height") )
6069 height = attr["height"].toInt(); 6092 height = attr["height"].toInt();
6070 6093
6071 QString imageName = attr["src"]; 6094 QString imageName = attr["src"];
6072 6095
6073 if (!imageName) 6096 if (!imageName)
6074 imageName = attr["source"]; 6097 imageName = attr["source"];
6075 6098
6076 if ( !imageName.isEmpty() ) { 6099 if ( !imageName.isEmpty() ) {
6077 imgId = QString( "%1,%2,%3,%4" ).arg( imageName ).arg( width ).arg( height ).arg( (ulong)&factory ); 6100 imgId = QString( "%1,%2,%3,%4" ).arg( imageName ).arg( width ).arg( height ).arg( (ulong)&factory );
6078 if ( !pixmap_map ) 6101 if ( !pixmap_map )
6079 pixmap_map = new QMap<QString, QPixmapInt>; 6102 pixmap_map = new QMap<QString, QPixmapInt>;
6080 if ( pixmap_map->contains( imgId ) ) { 6103 if ( pixmap_map->contains( imgId ) ) {
6081 QPixmapInt& pmi = pixmap_map->operator[](imgId); 6104 QPixmapInt& pmi = pixmap_map->operator[](imgId);
6082 pm = pmi.pm; 6105 pm = pmi.pm;
6083 pmi.ref++; 6106 pmi.ref++;
6084 width = pm.width(); 6107 width = pm.width();
6085 height = pm.height(); 6108 height = pm.height();
6086 } else { 6109 } else {
6087 QImage img; 6110 QImage img;
6088 const QMimeSource* m = 6111 const QMimeSource* m =
6089 factory.data( imageName, context ); 6112 factory.data( imageName, context );
6090 if ( !m ) { 6113 if ( !m ) {
6091 owarn << "QTextImage: no mimesource for " << imageName.latin1() << "" << oendl; 6114 owarn << "QTextImage: no mimesource for " << imageName.latin1() << "" << oendl;
6092 } 6115 }
6093 else { 6116 else {
6094 if ( !QImageDrag::decode( m, img ) ) { 6117 if ( !QImageDrag::decode( m, img ) ) {
6095 owarn << "QTextImage: cannot decode " << imageName.latin1() << "" << oendl; 6118 owarn << "QTextImage: cannot decode " << imageName.latin1() << "" << oendl;
6096 } 6119 }
6097 } 6120 }
6098 6121
6099 if ( !img.isNull() ) { 6122 if ( !img.isNull() ) {
6100 if ( width == 0 ) { 6123 if ( width == 0 ) {
6101 width = img.width(); 6124 width = img.width();
6102 if ( height != 0 ) { 6125 if ( height != 0 ) {
6103 width = img.width() * height / img.height(); 6126 width = img.width() * height / img.height();
6104 } 6127 }
6105 } 6128 }
6106 if ( height == 0 ) { 6129 if ( height == 0 ) {
6107 height = img.height(); 6130 height = img.height();
6108 if ( width != img.width() ) { 6131 if ( width != img.width() ) {
6109 height = img.height() * width / img.width(); 6132 height = img.height() * width / img.width();
6110 } 6133 }
6111 } 6134 }
6112 if ( img.width() != width || img.height() != height ){ 6135 if ( img.width() != width || img.height() != height ){
6113#ifndef QT_NO_IMAGE_SMOOTHSCALE 6136#ifndef QT_NO_IMAGE_SMOOTHSCALE
6114 img = img.smoothScale(width, height); 6137 img = img.smoothScale(width, height);
6115#endif 6138#endif
6116 width = img.width(); 6139 width = img.width();
6117 height = img.height(); 6140 height = img.height();
6118 } 6141 }
6119 pm.convertFromImage( img ); 6142 pm.convertFromImage( img );
6120 } 6143 }
6121 if ( !pm.isNull() ) { 6144 if ( !pm.isNull() ) {
6122 QPixmapInt& pmi = pixmap_map->operator[](imgId); 6145 QPixmapInt& pmi = pixmap_map->operator[](imgId);
6123 pmi.pm = pm; 6146 pmi.pm = pm;
6124 pmi.ref++; 6147 pmi.ref++;
6125 } 6148 }
6126 } 6149 }
6127 if ( pm.mask() ) { 6150 if ( pm.mask() ) {
6128 QRegion mask( *pm.mask() ); 6151 QRegion mask( *pm.mask() );
6129 QRegion all( 0, 0, pm.width(), pm.height() ); 6152 QRegion all( 0, 0, pm.width(), pm.height() );
6130 reg = new QRegion( all.subtract( mask ) ); 6153 reg = new QRegion( all.subtract( mask ) );
6131 } 6154 }
6132 } 6155 }
6133 6156
6134 if ( pm.isNull() && (width*height)==0 ) 6157 if ( pm.isNull() && (width*height)==0 )
6135 width = height = 50; 6158 width = height = 50;
6136 6159
6137 place = PlaceInline; 6160 place = PlaceInline;
6138 if ( attr["align"] == "left" ) 6161 if ( attr["align"] == "left" )
6139 place = PlaceLeft; 6162 place = PlaceLeft;
6140 else if ( attr["align"] == "right" ) 6163 else if ( attr["align"] == "right" )
6141 place = PlaceRight; 6164 place = PlaceRight;
6142 6165
6143 tmpwidth = width; 6166 tmpwidth = width;
6144 tmpheight = height; 6167 tmpheight = height;
6145 6168
6146 attributes = attr; 6169 attributes = attr;
6147} 6170}
6148 6171
6149QTextImage::~QTextImage() 6172QTextImage::~QTextImage()
6150{ 6173{
6151 delete reg; 6174 delete reg;
6152 if ( pixmap_map && pixmap_map->contains( imgId ) ) { 6175 if ( pixmap_map && pixmap_map->contains( imgId ) ) {
6153 QPixmapInt& pmi = pixmap_map->operator[](imgId); 6176 QPixmapInt& pmi = pixmap_map->operator[](imgId);
6154 pmi.ref--; 6177 pmi.ref--;
6155 if ( !pmi.ref ) { 6178 if ( !pmi.ref ) {
6156 pixmap_map->remove( imgId ); 6179 pixmap_map->remove( imgId );
6157 if ( pixmap_map->isEmpty() ) { 6180 if ( pixmap_map->isEmpty() ) {
6158 delete pixmap_map; 6181 delete pixmap_map;
6159 pixmap_map = 0; 6182 pixmap_map = 0;
6160 } 6183 }
6161 } 6184 }
6162 } 6185 }
6163} 6186}
6164 6187
6165QString QTextImage::richText() const 6188QString QTextImage::richText() const
6166{ 6189{
6167 QString s; 6190 QString s;
6168 s += "<img "; 6191 s += "<img ";
6169 QMap<QString, QString>::ConstIterator it = attributes.begin(); 6192 QMap<QString, QString>::ConstIterator it = attributes.begin();
6170 for ( ; it != attributes.end(); ++it ) 6193 for ( ; it != attributes.end(); ++it )
6171 s += it.key() + "=" + *it + " "; 6194 s += it.key() + "=" + *it + " ";
6172 s += ">"; 6195 s += ">";
6173 return s; 6196 return s;
6174} 6197}
6175 6198
6176void QTextImage::adjustToPainter( QPainter* p ) 6199void QTextImage::adjustToPainter( QPainter* p )
6177{ 6200{
6178 width = scale( tmpwidth, p ); 6201 width = scale( tmpwidth, p );
6179 height = scale( tmpheight, p ); 6202 height = scale( tmpheight, p );
6180} 6203}
6181 6204
6182#if !defined(Q_WS_X11) 6205#if !defined(Q_WS_X11)
6183#include <qbitmap.h> 6206#include <qbitmap.h>
6184#include "qcleanuphandler.h" 6207#include "qcleanuphandler.h"
6185static QPixmap *qrt_selection = 0; 6208static QPixmap *qrt_selection = 0;
6186static QSingleCleanupHandler<QPixmap> qrt_cleanup_pixmap; 6209static QSingleCleanupHandler<QPixmap> qrt_cleanup_pixmap;
6187static void qrt_createSelectionPixmap( const QColorGroup &cg ) 6210static void qrt_createSelectionPixmap( const QColorGroup &cg )
6188{ 6211{
6189 qrt_selection = new QPixmap( 2, 2 ); 6212 qrt_selection = new QPixmap( 2, 2 );
6190 qrt_cleanup_pixmap.set( &qrt_selection ); 6213 qrt_cleanup_pixmap.set( &qrt_selection );
6191 qrt_selection->fill( Qt::color0 ); 6214 qrt_selection->fill( Qt::color0 );
6192 QBitmap m( 2, 2 ); 6215 QBitmap m( 2, 2 );
6193 m.fill( Qt::color1 ); 6216 m.fill( Qt::color1 );
6194 QPainter p( &m ); 6217 QPainter p( &m );
6195 p.setPen( Qt::color0 ); 6218 p.setPen( Qt::color0 );
6196 for ( int j = 0; j < 2; ++j ) { 6219 for ( int j = 0; j < 2; ++j ) {
6197 p.drawPoint( j % 2, j ); 6220 p.drawPoint( j % 2, j );
6198 } 6221 }
6199 p.end(); 6222 p.end();
6200 qrt_selection->setMask( m ); 6223 qrt_selection->setMask( m );
6201 qrt_selection->fill( cg.highlight() ); 6224 qrt_selection->fill( cg.highlight() );
6202} 6225}
6203#endif 6226#endif
6204 6227
6205void QTextImage::draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ) 6228void QTextImage::draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected )
6206{ 6229{
6207 if ( placement() != PlaceInline ) { 6230 if ( placement() != PlaceInline ) {
6208 x = xpos; 6231 x = xpos;
6209 y = ypos; 6232 y = ypos;
6210 } 6233 }
6211 6234
6212 if ( pm.isNull() ) { 6235 if ( pm.isNull() ) {
6213 p->fillRect( x , y, width, height, cg.dark() ); 6236 p->fillRect( x , y, width, height, cg.dark() );
6214 return; 6237 return;
6215 } 6238 }
6216 6239
6217 if ( is_printer( p ) ) { 6240 if ( is_printer( p ) ) {
6218 p->drawPixmap( x, y, pm ); 6241 p->drawPixmap( x, y, pm );
6219 return; 6242 return;
6220 } 6243 }
6221 6244
6222 if ( placement() != PlaceInline && !QRect( xpos, ypos, width, height ).intersects( QRect( cx, cy, cw, ch ) ) ) 6245 if ( placement() != PlaceInline && !QRect( xpos, ypos, width, height ).intersects( QRect( cx, cy, cw, ch ) ) )
6223 return; 6246 return;
6224 6247
6225 if ( placement() == PlaceInline ) 6248 if ( placement() == PlaceInline )
6226 p->drawPixmap( x , y, pm ); 6249 p->drawPixmap( x , y, pm );
6227 else 6250 else
6228 p->drawPixmap( cx , cy, pm, cx - x, cy - y, cw, ch ); 6251 p->drawPixmap( cx , cy, pm, cx - x, cy - y, cw, ch );
6229 6252
6230 if ( selected && placement() == PlaceInline && is_printer( p ) ) { 6253 if ( selected && placement() == PlaceInline && is_printer( p ) ) {
6231#if defined(Q_WS_X11) 6254#if defined(Q_WS_X11)
6232 p->fillRect( QRect( QPoint( x, y ), pm.size() ), QBrush( cg.highlight(), QBrush::Dense4Pattern) ); 6255 p->fillRect( QRect( QPoint( x, y ), pm.size() ), QBrush( cg.highlight(), QBrush::Dense4Pattern) );
6233#else // in WIN32 Dense4Pattern doesn't work correctly (transparency problem), so work around it 6256#else // in WIN32 Dense4Pattern doesn't work correctly (transparency problem), so work around it
6234 if ( !qrt_selection ) 6257 if ( !qrt_selection )
6235 qrt_createSelectionPixmap( cg ); 6258 qrt_createSelectionPixmap( cg );
6236 p->drawTiledPixmap( x, y, pm.width(), pm.height(), *qrt_selection ); 6259 p->drawTiledPixmap( x, y, pm.width(), pm.height(), *qrt_selection );
6237#endif 6260#endif
6238 } 6261 }
6239} 6262}
6240 6263
6241void QTextHorizontalLine::adjustToPainter( QPainter* p ) 6264void QTextHorizontalLine::adjustToPainter( QPainter* p )
6242{ 6265{
6243 height = scale( tmpheight, p ); 6266 height = scale( tmpheight, p );
6244} 6267}
6245 6268
6246 6269
6247QTextHorizontalLine::QTextHorizontalLine( QTextDocument *p, const QMap<QString, QString> &attr, 6270QTextHorizontalLine::QTextHorizontalLine( QTextDocument *p, const QMap<QString, QString> &attr,
6248 const QString &, 6271 const QString &,
6249 QMimeSourceFactory & ) 6272 QMimeSourceFactory & )
6250 : QTextCustomItem( p ) 6273 : QTextCustomItem( p )
6251{ 6274{
6252 height = tmpheight = 8; 6275 height = tmpheight = 8;
6253 if ( attr.find( "color" ) != attr.end() ) 6276 if ( attr.find( "color" ) != attr.end() )
6254 color = QColor( *attr.find( "color" ) ); 6277 color = QColor( *attr.find( "color" ) );
6255} 6278}
6256 6279
6257QTextHorizontalLine::~QTextHorizontalLine() 6280QTextHorizontalLine::~QTextHorizontalLine()
6258{ 6281{
6259} 6282}
6260 6283
6261QString QTextHorizontalLine::richText() const 6284QString QTextHorizontalLine::richText() const
6262{ 6285{
6263 return "<hr>"; 6286 return "<hr>";
6264} 6287}
6265 6288
6266void QTextHorizontalLine::draw( QPainter* p, int x, int y, int , int , int , int , const QColorGroup& cg, bool selected ) 6289void QTextHorizontalLine::draw( QPainter* p, int x, int y, int , int , int , int , const QColorGroup& cg, bool selected )
6267{ 6290{
6268 QRect r( x, y, width, height); 6291 QRect r( x, y, width, height);
6269 if ( is_printer( p ) ) { 6292 if ( is_printer( p ) ) {
6270 QPen oldPen = p->pen(); 6293 QPen oldPen = p->pen();
6271 if ( !color.isValid() ) 6294 if ( !color.isValid() )
6272 p->setPen( QPen( cg.text(), height/8 ) ); 6295 p->setPen( QPen( cg.text(), height/8 ) );
6273 else 6296 else
6274 p->setPen( QPen( color, height/8 ) ); 6297 p->setPen( QPen( color, height/8 ) );
6275 p->drawLine( r.left()-1, y + height / 2, r.right() + 1, y + height / 2 ); 6298 p->drawLine( r.left()-1, y + height / 2, r.right() + 1, y + height / 2 );
6276 p->setPen( oldPen ); 6299 p->setPen( oldPen );
6277 } else { 6300 } else {
6278 QColorGroup g( cg ); 6301 QColorGroup g( cg );
6279 if ( color.isValid() ) 6302 if ( color.isValid() )
6280 g.setColor( QColorGroup::Dark, color ); 6303 g.setColor( QColorGroup::Dark, color );
6281 if ( selected ) 6304 if ( selected )
6282 p->fillRect( r.left(), y, r.right(), y + height, g.highlight() ); 6305 p->fillRect( r.left(), y, r.right(), y + height, g.highlight() );
6283 qDrawShadeLine( p, r.left() - 1, y + height / 2, r.right() + 1, y + height / 2, g, TRUE, height / 8 ); 6306 qDrawShadeLine( p, r.left() - 1, y + height / 2, r.right() + 1, y + height / 2, g, TRUE, height / 8 );
6284 } 6307 }
6285} 6308}
6286 6309
6287 6310
6288/*****************************************************************/ 6311/*****************************************************************/
6289// Small set of utility functions to make the parser a bit simpler 6312// Small set of utility functions to make the parser a bit simpler
6290// 6313//
6291 6314
6292bool QTextDocument::hasPrefix(const QChar* doc, int length, int pos, QChar c) 6315bool QTextDocument::hasPrefix(const QChar* doc, int length, int pos, QChar c)
6293{ 6316{
6294 if ( pos >= length ) 6317 if ( pos >= length )
6295 return FALSE; 6318 return FALSE;
6296 return doc[ pos ].lower() == c.lower(); 6319 return doc[ pos ].lower() == c.lower();
6297} 6320}
6298 6321
6299bool QTextDocument::hasPrefix( const QChar* doc, int length, int pos, const QString& s ) 6322bool QTextDocument::hasPrefix( const QChar* doc, int length, int pos, const QString& s )
6300{ 6323{
6301 if ( pos + (int) s.length() >= length ) 6324 if ( pos + (int) s.length() >= length )
6302 return FALSE; 6325 return FALSE;
6303 for ( int i = 0; i < (int)s.length(); i++ ) { 6326 for ( int i = 0; i < (int)s.length(); i++ ) {
6304 if ( doc[ pos + i ].lower() != s[ i ].lower() ) 6327 if ( doc[ pos + i ].lower() != s[ i ].lower() )
6305 return FALSE; 6328 return FALSE;
6306 } 6329 }
6307 return TRUE; 6330 return TRUE;
6308} 6331}
6309 6332
6310static bool qt_is_cell_in_use( QPtrList<QTextTableCell>& cells, int row, int col ) 6333static bool qt_is_cell_in_use( QPtrList<QTextTableCell>& cells, int row, int col )
6311{ 6334{
6312 for ( QTextTableCell* c = cells.first(); c; c = cells.next() ) { 6335 for ( QTextTableCell* c = cells.first(); c; c = cells.next() ) {
6313 if ( row >= c->row() && row < c->row() + c->rowspan() 6336 if ( row >= c->row() && row < c->row() + c->rowspan()
6314 && col >= c->column() && col < c->column() + c->colspan() ) 6337 && col >= c->column() && col < c->column() + c->colspan() )
6315 return TRUE; 6338 return TRUE;
6316 } 6339 }
6317 return FALSE; 6340 return FALSE;
6318} 6341}
6319 6342
6320QTextCustomItem* QTextDocument::parseTable( const QMap<QString, QString> &attr, const QTextFormat &fmt, 6343QTextCustomItem* QTextDocument::parseTable( const QMap<QString, QString> &attr, const QTextFormat &fmt,
6321 const QChar* doc, int length, int& pos, QTextParagraph *curpar ) 6344 const QChar* doc, int length, int& pos, QTextParagraph *curpar )
6322{ 6345{
6323 6346
6324 QTextTable* table = new QTextTable( this, attr ); 6347 QTextTable* table = new QTextTable( this, attr );
6325 int row = -1; 6348 int row = -1;
6326 int col = -1; 6349 int col = -1;
6327 6350
6328 QString rowbgcolor; 6351 QString rowbgcolor;
6329 QString rowalign; 6352 QString rowalign;
6330 QString tablebgcolor = attr["bgcolor"]; 6353 QString tablebgcolor = attr["bgcolor"];
6331 6354
6332 QPtrList<QTextTableCell> multicells; 6355 QPtrList<QTextTableCell> multicells;
6333 6356
6334 QString tagname; 6357 QString tagname;
6335 (void) eatSpace(doc, length, pos); 6358 (void) eatSpace(doc, length, pos);
6336 while ( pos < length) { 6359 while ( pos < length) {
6337 if (hasPrefix(doc, length, pos, QChar('<')) ){ 6360 if (hasPrefix(doc, length, pos, QChar('<')) ){
6338 if (hasPrefix(doc, length, pos+1, QChar('/'))) { 6361 if (hasPrefix(doc, length, pos+1, QChar('/'))) {
6339 tagname = parseCloseTag( doc, length, pos ); 6362 tagname = parseCloseTag( doc, length, pos );
6340 if ( tagname == "table" ) { 6363 if ( tagname == "table" ) {
6341 return table; 6364 return table;
6342 } 6365 }
6343 } else { 6366 } else {
6344 QMap<QString, QString> attr2; 6367 QMap<QString, QString> attr2;
6345 bool emptyTag = FALSE; 6368 bool emptyTag = FALSE;
6346 tagname = parseOpenTag( doc, length, pos, attr2, emptyTag ); 6369 tagname = parseOpenTag( doc, length, pos, attr2, emptyTag );
6347 if ( tagname == "tr" ) { 6370 if ( tagname == "tr" ) {
6348 rowbgcolor = attr2["bgcolor"]; 6371 rowbgcolor = attr2["bgcolor"];
6349 rowalign = attr2["align"]; 6372 rowalign = attr2["align"];
6350 row++; 6373 row++;
6351 col = -1; 6374 col = -1;
6352 } 6375 }
6353 else if ( tagname == "td" || tagname == "th" ) { 6376 else if ( tagname == "td" || tagname == "th" ) {
6354 col++; 6377 col++;
6355 while ( qt_is_cell_in_use( multicells, row, col ) ) { 6378 while ( qt_is_cell_in_use( multicells, row, col ) ) {
6356 col++; 6379 col++;
6357 } 6380 }
6358 6381
6359 if ( row >= 0 && col >= 0 ) { 6382 if ( row >= 0 && col >= 0 ) {
6360 const QStyleSheetItem* s = sheet_->item(tagname); 6383 const QStyleSheetItem* s = sheet_->item(tagname);
6361 if ( !attr2.contains("bgcolor") ) { 6384 if ( !attr2.contains("bgcolor") ) {
6362 if (!rowbgcolor.isEmpty() ) 6385 if (!rowbgcolor.isEmpty() )
6363 attr2["bgcolor"] = rowbgcolor; 6386 attr2["bgcolor"] = rowbgcolor;
6364 else if (!tablebgcolor.isEmpty() ) 6387 else if (!tablebgcolor.isEmpty() )
6365 attr2["bgcolor"] = tablebgcolor; 6388 attr2["bgcolor"] = tablebgcolor;
6366 } 6389 }
6367 if ( !attr2.contains("align") ) { 6390 if ( !attr2.contains("align") ) {
6368 if (!rowalign.isEmpty() ) 6391 if (!rowalign.isEmpty() )
6369 attr2["align"] = rowalign; 6392 attr2["align"] = rowalign;
6370 } 6393 }
6371 6394
6372 // extract the cell contents 6395 // extract the cell contents
6373 int end = pos; 6396 int end = pos;
6374 while ( end < length 6397 while ( end < length
6375 && !hasPrefix( doc, length, end, "</td") 6398 && !hasPrefix( doc, length, end, "</td")
6376 && !hasPrefix( doc, length, end, "<td") 6399 && !hasPrefix( doc, length, end, "<td")
6377 && !hasPrefix( doc, length, end, "</th") 6400 && !hasPrefix( doc, length, end, "</th")
6378 && !hasPrefix( doc, length, end, "<th") 6401 && !hasPrefix( doc, length, end, "<th")
6379 && !hasPrefix( doc, length, end, "<td") 6402 && !hasPrefix( doc, length, end, "<td")
6380 && !hasPrefix( doc, length, end, "</tr") 6403 && !hasPrefix( doc, length, end, "</tr")
6381 && !hasPrefix( doc, length, end, "<tr") 6404 && !hasPrefix( doc, length, end, "<tr")
6382 && !hasPrefix( doc, length, end, "</table") ) { 6405 && !hasPrefix( doc, length, end, "</table") ) {
6383 if ( hasPrefix( doc, length, end, "<table" ) ) { // nested table 6406 if ( hasPrefix( doc, length, end, "<table" ) ) { // nested table
6384 int nested = 1; 6407 int nested = 1;
6385 ++end; 6408 ++end;
6386 while ( end < length && nested != 0 ) { 6409 while ( end < length && nested != 0 ) {
6387 if ( hasPrefix( doc, length, end, "</table" ) ) 6410 if ( hasPrefix( doc, length, end, "</table" ) )
6388 nested--; 6411 nested--;
6389 if ( hasPrefix( doc, length, end, "<table" ) ) 6412 if ( hasPrefix( doc, length, end, "<table" ) )
6390 nested++; 6413 nested++;
6391 end++; 6414 end++;
6392 } 6415 }
6393 } 6416 }
6394 end++; 6417 end++;
6395 } 6418 }
6396 QTextTableCell* cell = new QTextTableCell( table, row, col, 6419 QTextTableCell* cell = new QTextTableCell( table, row, col,
6397 attr2, s, fmt.makeTextFormat( s, attr2, scaleFontsFactor ), 6420 attr2, s, fmt.makeTextFormat( s, attr2, scaleFontsFactor ),
6398 contxt, *factory_, sheet_, 6421 contxt, *factory_, sheet_,
6399 QString( doc, length).mid( pos, end - pos ) ); 6422 QString( doc, length).mid( pos, end - pos ) );
6400 cell->richText()->parentPar = curpar; 6423 cell->richText()->parentPar = curpar;
6401 if ( cell->colspan() > 1 || cell->rowspan() > 1 ) 6424 if ( cell->colspan() > 1 || cell->rowspan() > 1 )
6402 multicells.append( cell ); 6425 multicells.append( cell );
6403 col += cell->colspan()-1; 6426 col += cell->colspan()-1;
6404 pos = end; 6427 pos = end;
6405 } 6428 }
6406 } 6429 }
6407 } 6430 }
6408 6431
6409 } else { 6432 } else {
6410 ++pos; 6433 ++pos;
6411 } 6434 }
6412 } 6435 }
6413 return table; 6436 return table;
6414} 6437}
6415 6438
6416bool QTextDocument::eatSpace(const QChar* doc, int length, int& pos, bool includeNbsp ) 6439bool QTextDocument::eatSpace(const QChar* doc, int length, int& pos, bool includeNbsp )
6417{ 6440{
6418 int old_pos = pos; 6441 int old_pos = pos;
6419 while (pos < length && doc[pos].isSpace() && ( includeNbsp || (doc[pos] != QChar::nbsp ) ) ) 6442 while (pos < length && doc[pos].isSpace() && ( includeNbsp || (doc[pos] != QChar::nbsp ) ) )
6420 pos++; 6443 pos++;
6421 return old_pos < pos; 6444 return old_pos < pos;
6422} 6445}
6423 6446
6424bool QTextDocument::eat(const QChar* doc, int length, int& pos, QChar c) 6447bool QTextDocument::eat(const QChar* doc, int length, int& pos, QChar c)
6425{ 6448{
6426 bool ok = pos < length && doc[pos] == c; 6449 bool ok = pos < length && doc[pos] == c;
6427 if ( ok ) 6450 if ( ok )
6428 pos++; 6451 pos++;
6429 return ok; 6452 return ok;
6430} 6453}
6431/*****************************************************************/ 6454/*****************************************************************/
6432 6455
6433struct Entity { 6456struct Entity {
6434 const char * name; 6457 const char * name;
6435 Q_UINT16 code; 6458 Q_UINT16 code;
6436}; 6459};
6437 6460
6438static const Entity entitylist [] = { 6461static const Entity entitylist [] = {
6439 { "AElig", 0x00c6 }, 6462 { "AElig", 0x00c6 },
6440 { "Aacute", 0x00c1 }, 6463 { "Aacute", 0x00c1 },
6441 { "Acirc", 0x00c2 }, 6464 { "Acirc", 0x00c2 },
6442 { "Agrave", 0x00c0 }, 6465 { "Agrave", 0x00c0 },
6443 { "Alpha", 0x0391 }, 6466 { "Alpha", 0x0391 },
6444 { "AMP", 38 }, 6467 { "AMP", 38 },
6445 { "Aring", 0x00c5 }, 6468 { "Aring", 0x00c5 },
6446 { "Atilde", 0x00c3 }, 6469 { "Atilde", 0x00c3 },
6447 { "Auml", 0x00c4 }, 6470 { "Auml", 0x00c4 },
6448 { "Beta", 0x0392 }, 6471 { "Beta", 0x0392 },
6449 { "Ccedil", 0x00c7 }, 6472 { "Ccedil", 0x00c7 },
6450 { "Chi", 0x03a7 }, 6473 { "Chi", 0x03a7 },
6451 { "Dagger", 0x2021 }, 6474 { "Dagger", 0x2021 },
6452 { "Delta", 0x0394 }, 6475 { "Delta", 0x0394 },
6453 { "ETH", 0x00d0 }, 6476 { "ETH", 0x00d0 },
6454 { "Eacute", 0x00c9 }, 6477 { "Eacute", 0x00c9 },
6455 { "Ecirc", 0x00ca }, 6478 { "Ecirc", 0x00ca },
6456 { "Egrave", 0x00c8 }, 6479 { "Egrave", 0x00c8 },
6457 { "Epsilon", 0x0395 }, 6480 { "Epsilon", 0x0395 },
6458 { "Eta", 0x0397 }, 6481 { "Eta", 0x0397 },
6459 { "Euml", 0x00cb }, 6482 { "Euml", 0x00cb },
6460 { "Gamma", 0x0393 }, 6483 { "Gamma", 0x0393 },
6461 { "GT", 62 }, 6484 { "GT", 62 },
6462 { "Iacute", 0x00cd }, 6485 { "Iacute", 0x00cd },
6463 { "Icirc", 0x00ce }, 6486 { "Icirc", 0x00ce },
6464 { "Igrave", 0x00cc }, 6487 { "Igrave", 0x00cc },
6465 { "Iota", 0x0399 }, 6488 { "Iota", 0x0399 },
6466 { "Iuml", 0x00cf }, 6489 { "Iuml", 0x00cf },
6467 { "Kappa", 0x039a }, 6490 { "Kappa", 0x039a },
6468 { "Lambda", 0x039b }, 6491 { "Lambda", 0x039b },
6469 { "LT", 60 }, 6492 { "LT", 60 },
6470 { "Mu", 0x039c }, 6493 { "Mu", 0x039c },
6471 { "Ntilde", 0x00d1 }, 6494 { "Ntilde", 0x00d1 },
6472 { "Nu", 0x039d }, 6495 { "Nu", 0x039d },
6473 { "OElig", 0x0152 }, 6496 { "OElig", 0x0152 },
6474 { "Oacute", 0x00d3 }, 6497 { "Oacute", 0x00d3 },
6475 { "Ocirc", 0x00d4 }, 6498 { "Ocirc", 0x00d4 },
6476 { "Ograve", 0x00d2 }, 6499 { "Ograve", 0x00d2 },
6477 { "Omega", 0x03a9 }, 6500 { "Omega", 0x03a9 },
6478 { "Omicron", 0x039f }, 6501 { "Omicron", 0x039f },
6479 { "Oslash", 0x00d8 }, 6502 { "Oslash", 0x00d8 },
6480 { "Otilde", 0x00d5 }, 6503 { "Otilde", 0x00d5 },
6481 { "Ouml", 0x00d6 }, 6504 { "Ouml", 0x00d6 },
6482 { "Phi", 0x03a6 }, 6505 { "Phi", 0x03a6 },
6483 { "Pi", 0x03a0 }, 6506 { "Pi", 0x03a0 },
6484 { "Prime", 0x2033 }, 6507 { "Prime", 0x2033 },
6485 { "Psi", 0x03a8 }, 6508 { "Psi", 0x03a8 },
6486 { "QUOT", 34 }, 6509 { "QUOT", 34 },
6487 { "Rho", 0x03a1 }, 6510 { "Rho", 0x03a1 },
6488 { "Scaron", 0x0160 }, 6511 { "Scaron", 0x0160 },
6489 { "Sigma", 0x03a3 }, 6512 { "Sigma", 0x03a3 },
6490 { "THORN", 0x00de }, 6513 { "THORN", 0x00de },
6491 { "Tau", 0x03a4 }, 6514 { "Tau", 0x03a4 },
6492 { "Theta", 0x0398 }, 6515 { "Theta", 0x0398 },
6493 { "Uacute", 0x00da }, 6516 { "Uacute", 0x00da },
6494 { "Ucirc", 0x00db }, 6517 { "Ucirc", 0x00db },
6495 { "Ugrave", 0x00d9 }, 6518 { "Ugrave", 0x00d9 },
6496 { "Upsilon", 0x03a5 }, 6519 { "Upsilon", 0x03a5 },
6497 { "Uuml", 0x00dc }, 6520 { "Uuml", 0x00dc },
6498 { "Xi", 0x039e }, 6521 { "Xi", 0x039e },
6499 { "Yacute", 0x00dd }, 6522 { "Yacute", 0x00dd },
6500 { "Yuml", 0x0178 }, 6523 { "Yuml", 0x0178 },
6501 { "Zeta", 0x0396 }, 6524 { "Zeta", 0x0396 },
6502 { "aacute", 0x00e1 }, 6525 { "aacute", 0x00e1 },
6503 { "acirc", 0x00e2 }, 6526 { "acirc", 0x00e2 },
6504 { "acute", 0x00b4 }, 6527 { "acute", 0x00b4 },
6505 { "aelig", 0x00e6 }, 6528 { "aelig", 0x00e6 },
6506 { "agrave", 0x00e0 }, 6529 { "agrave", 0x00e0 },
6507 { "alefsym", 0x2135 }, 6530 { "alefsym", 0x2135 },
6508 { "alpha", 0x03b1 }, 6531 { "alpha", 0x03b1 },
6509 { "amp", 38 }, 6532 { "amp", 38 },
6510 { "and", 0x22a5 }, 6533 { "and", 0x22a5 },
6511 { "ang", 0x2220 }, 6534 { "ang", 0x2220 },
6512 { "apos", 0x0027 }, 6535 { "apos", 0x0027 },
6513 { "aring", 0x00e5 }, 6536 { "aring", 0x00e5 },
6514 { "asymp", 0x2248 }, 6537 { "asymp", 0x2248 },
6515 { "atilde", 0x00e3 }, 6538 { "atilde", 0x00e3 },
6516 { "auml", 0x00e4 }, 6539 { "auml", 0x00e4 },
6517 { "bdquo", 0x201e }, 6540 { "bdquo", 0x201e },
6518 { "beta", 0x03b2 }, 6541 { "beta", 0x03b2 },
6519 { "brvbar", 0x00a6 }, 6542 { "brvbar", 0x00a6 },
6520 { "bull", 0x2022 }, 6543 { "bull", 0x2022 },
6521 { "cap", 0x2229 }, 6544 { "cap", 0x2229 },
6522 { "ccedil", 0x00e7 }, 6545 { "ccedil", 0x00e7 },
6523 { "cedil", 0x00b8 }, 6546 { "cedil", 0x00b8 },
6524 { "cent", 0x00a2 }, 6547 { "cent", 0x00a2 },
6525 { "chi", 0x03c7 }, 6548 { "chi", 0x03c7 },
6526 { "circ", 0x02c6 }, 6549 { "circ", 0x02c6 },
6527 { "clubs", 0x2663 }, 6550 { "clubs", 0x2663 },
6528 { "cong", 0x2245 }, 6551 { "cong", 0x2245 },
6529 { "copy", 0x00a9 }, 6552 { "copy", 0x00a9 },
6530 { "crarr", 0x21b5 }, 6553 { "crarr", 0x21b5 },
6531 { "cup", 0x222a }, 6554 { "cup", 0x222a },
6532 { "curren", 0x00a4 }, 6555 { "curren", 0x00a4 },
6533 { "dArr", 0x21d3 }, 6556 { "dArr", 0x21d3 },
6534 { "dagger", 0x2020 }, 6557 { "dagger", 0x2020 },
6535 { "darr", 0x2193 }, 6558 { "darr", 0x2193 },
6536 { "deg", 0x00b0 }, 6559 { "deg", 0x00b0 },
6537 { "delta", 0x03b4 }, 6560 { "delta", 0x03b4 },
6538 { "diams", 0x2666 }, 6561 { "diams", 0x2666 },
6539 { "divide", 0x00f7 }, 6562 { "divide", 0x00f7 },
6540 { "eacute", 0x00e9 }, 6563 { "eacute", 0x00e9 },
6541 { "ecirc", 0x00ea }, 6564 { "ecirc", 0x00ea },
6542 { "egrave", 0x00e8 }, 6565 { "egrave", 0x00e8 },
6543 { "empty", 0x2205 }, 6566 { "empty", 0x2205 },
6544 { "emsp", 0x2003 }, 6567 { "emsp", 0x2003 },
6545 { "ensp", 0x2002 }, 6568 { "ensp", 0x2002 },
6546 { "epsilon", 0x03b5 }, 6569 { "epsilon", 0x03b5 },
6547 { "equiv", 0x2261 }, 6570 { "equiv", 0x2261 },
6548 { "eta", 0x03b7 }, 6571 { "eta", 0x03b7 },
6549 { "eth", 0x00f0 }, 6572 { "eth", 0x00f0 },
6550 { "euml", 0x00eb }, 6573 { "euml", 0x00eb },
6551 { "euro", 0x20ac }, 6574 { "euro", 0x20ac },
6552 { "exist", 0x2203 }, 6575 { "exist", 0x2203 },
6553 { "fnof", 0x0192 }, 6576 { "fnof", 0x0192 },
6554 { "forall", 0x2200 }, 6577 { "forall", 0x2200 },
6555 { "frac12", 0x00bd }, 6578 { "frac12", 0x00bd },
6556 { "frac14", 0x00bc }, 6579 { "frac14", 0x00bc },
6557 { "frac34", 0x00be }, 6580 { "frac34", 0x00be },
6558 { "frasl", 0x2044 }, 6581 { "frasl", 0x2044 },
6559 { "gamma", 0x03b3 }, 6582 { "gamma", 0x03b3 },
6560 { "ge", 0x2265 }, 6583 { "ge", 0x2265 },
6561 { "gt", 62 }, 6584 { "gt", 62 },
6562 { "hArr", 0x21d4 }, 6585 { "hArr", 0x21d4 },
6563 { "harr", 0x2194 }, 6586 { "harr", 0x2194 },
6564 { "hearts", 0x2665 }, 6587 { "hearts", 0x2665 },
6565 { "hellip", 0x2026 }, 6588 { "hellip", 0x2026 },
6566 { "iacute", 0x00ed }, 6589 { "iacute", 0x00ed },
6567 { "icirc", 0x00ee }, 6590 { "icirc", 0x00ee },
6568 { "iexcl", 0x00a1 }, 6591 { "iexcl", 0x00a1 },
6569 { "igrave", 0x00ec }, 6592 { "igrave", 0x00ec },
6570 { "image", 0x2111 }, 6593 { "image", 0x2111 },
6571 { "infin", 0x221e }, 6594 { "infin", 0x221e },
6572 { "int", 0x222b }, 6595 { "int", 0x222b },
6573 { "iota", 0x03b9 }, 6596 { "iota", 0x03b9 },
6574 { "iquest", 0x00bf }, 6597 { "iquest", 0x00bf },
6575 { "isin", 0x2208 }, 6598 { "isin", 0x2208 },
6576 { "iuml", 0x00ef }, 6599 { "iuml", 0x00ef },
6577 { "kappa", 0x03ba }, 6600 { "kappa", 0x03ba },
6578 { "lArr", 0x21d0 }, 6601 { "lArr", 0x21d0 },
6579 { "lambda", 0x03bb }, 6602 { "lambda", 0x03bb },
6580 { "lang", 0x2329 }, 6603 { "lang", 0x2329 },
6581 { "laquo", 0x00ab }, 6604 { "laquo", 0x00ab },
6582 { "larr", 0x2190 }, 6605 { "larr", 0x2190 },
6583 { "lceil", 0x2308 }, 6606 { "lceil", 0x2308 },
6584 { "ldquo", 0x201c }, 6607 { "ldquo", 0x201c },
6585 { "le", 0x2264 }, 6608 { "le", 0x2264 },
6586 { "lfloor", 0x230a }, 6609 { "lfloor", 0x230a },
6587 { "lowast", 0x2217 }, 6610 { "lowast", 0x2217 },
6588 { "loz", 0x25ca }, 6611 { "loz", 0x25ca },
6589 { "lrm", 0x200e }, 6612 { "lrm", 0x200e },
6590 { "lsaquo", 0x2039 }, 6613 { "lsaquo", 0x2039 },
6591 { "lsquo", 0x2018 }, 6614 { "lsquo", 0x2018 },
6592 { "lt", 60 }, 6615 { "lt", 60 },
6593 { "macr", 0x00af }, 6616 { "macr", 0x00af },
6594 { "mdash", 0x2014 }, 6617 { "mdash", 0x2014 },
6595 { "micro", 0x00b5 }, 6618 { "micro", 0x00b5 },
6596 { "middot", 0x00b7 }, 6619 { "middot", 0x00b7 },
6597 { "minus", 0x2212 }, 6620 { "minus", 0x2212 },
6598 { "mu", 0x03bc }, 6621 { "mu", 0x03bc },
6599 { "nabla", 0x2207 }, 6622 { "nabla", 0x2207 },
6600 { "nbsp", 0x00a0 }, 6623 { "nbsp", 0x00a0 },
6601 { "ndash", 0x2013 }, 6624 { "ndash", 0x2013 },
6602 { "ne", 0x2260 }, 6625 { "ne", 0x2260 },
6603 { "ni", 0x220b }, 6626 { "ni", 0x220b },
6604 { "not", 0x00ac }, 6627 { "not", 0x00ac },
6605 { "notin", 0x2209 }, 6628 { "notin", 0x2209 },
6606 { "nsub", 0x2284 }, 6629 { "nsub", 0x2284 },
6607 { "ntilde", 0x00f1 }, 6630 { "ntilde", 0x00f1 },
6608 { "nu", 0x03bd }, 6631 { "nu", 0x03bd },
6609 { "oacute", 0x00f3 }, 6632 { "oacute", 0x00f3 },
6610 { "ocirc", 0x00f4 }, 6633 { "ocirc", 0x00f4 },
6611 { "oelig", 0x0153 }, 6634 { "oelig", 0x0153 },
6612 { "ograve", 0x00f2 }, 6635 { "ograve", 0x00f2 },
6613 { "oline", 0x203e }, 6636 { "oline", 0x203e },
6614 { "omega", 0x03c9 }, 6637 { "omega", 0x03c9 },
6615 { "omicron", 0x03bf }, 6638 { "omicron", 0x03bf },
6616 { "oplus", 0x2295 }, 6639 { "oplus", 0x2295 },
6617 { "or", 0x22a6 }, 6640 { "or", 0x22a6 },
6618 { "ordf", 0x00aa }, 6641 { "ordf", 0x00aa },
6619 { "ordm", 0x00ba }, 6642 { "ordm", 0x00ba },
6620 { "oslash", 0x00f8 }, 6643 { "oslash", 0x00f8 },
6621 { "otilde", 0x00f5 }, 6644 { "otilde", 0x00f5 },
6622 { "otimes", 0x2297 }, 6645 { "otimes", 0x2297 },
6623 { "ouml", 0x00f6 }, 6646 { "ouml", 0x00f6 },
6624 { "para", 0x00b6 }, 6647 { "para", 0x00b6 },
6625 { "part", 0x2202 }, 6648 { "part", 0x2202 },
6626 { "percnt", 0x0025 }, 6649 { "percnt", 0x0025 },
6627 { "permil", 0x2030 }, 6650 { "permil", 0x2030 },
6628 { "perp", 0x22a5 }, 6651 { "perp", 0x22a5 },
6629 { "phi", 0x03c6 }, 6652 { "phi", 0x03c6 },
6630 { "pi", 0x03c0 }, 6653 { "pi", 0x03c0 },
6631 { "piv", 0x03d6 }, 6654 { "piv", 0x03d6 },
6632 { "plusmn", 0x00b1 }, 6655 { "plusmn", 0x00b1 },
6633 { "pound", 0x00a3 }, 6656 { "pound", 0x00a3 },
6634 { "prime", 0x2032 }, 6657 { "prime", 0x2032 },
6635 { "prod", 0x220f }, 6658 { "prod", 0x220f },
6636 { "prop", 0x221d }, 6659 { "prop", 0x221d },
6637 { "psi", 0x03c8 }, 6660 { "psi", 0x03c8 },
6638 { "quot", 34 }, 6661 { "quot", 34 },
6639 { "rArr", 0x21d2 }, 6662 { "rArr", 0x21d2 },
6640 { "radic", 0x221a }, 6663 { "radic", 0x221a },
6641 { "rang", 0x232a }, 6664 { "rang", 0x232a },
6642 { "raquo", 0x00bb }, 6665 { "raquo", 0x00bb },
6643 { "rarr", 0x2192 }, 6666 { "rarr", 0x2192 },
6644 { "rceil", 0x2309 }, 6667 { "rceil", 0x2309 },
6645 { "rdquo", 0x201d }, 6668 { "rdquo", 0x201d },
6646 { "real", 0x211c }, 6669 { "real", 0x211c },
6647 { "reg", 0x00ae }, 6670 { "reg", 0x00ae },
6648 { "rfloor", 0x230b }, 6671 { "rfloor", 0x230b },
6649 { "rho", 0x03c1 }, 6672 { "rho", 0x03c1 },
6650 { "rlm", 0x200f }, 6673 { "rlm", 0x200f },
6651 { "rsaquo", 0x203a }, 6674 { "rsaquo", 0x203a },
6652 { "rsquo", 0x2019 }, 6675 { "rsquo", 0x2019 },
6653 { "sbquo", 0x201a }, 6676 { "sbquo", 0x201a },
6654 { "scaron", 0x0161 }, 6677 { "scaron", 0x0161 },
6655 { "sdot", 0x22c5 }, 6678 { "sdot", 0x22c5 },
6656 { "sect", 0x00a7 }, 6679 { "sect", 0x00a7 },
6657 { "shy", 0x00ad }, 6680 { "shy", 0x00ad },
6658 { "sigma", 0x03c3 }, 6681 { "sigma", 0x03c3 },
6659 { "sigmaf", 0x03c2 }, 6682 { "sigmaf", 0x03c2 },
6660 { "sim", 0x223c }, 6683 { "sim", 0x223c },
6661 { "spades", 0x2660 }, 6684 { "spades", 0x2660 },
6662 { "sub", 0x2282 }, 6685 { "sub", 0x2282 },
6663 { "sube", 0x2286 }, 6686 { "sube", 0x2286 },
6664 { "sum", 0x2211 }, 6687 { "sum", 0x2211 },
6665 { "sup1", 0x00b9 }, 6688 { "sup1", 0x00b9 },
6666 { "sup2", 0x00b2 }, 6689 { "sup2", 0x00b2 },
6667 { "sup3", 0x00b3 }, 6690 { "sup3", 0x00b3 },
6668 { "sup", 0x2283 }, 6691 { "sup", 0x2283 },
6669 { "supe", 0x2287 }, 6692 { "supe", 0x2287 },
6670 { "szlig", 0x00df }, 6693 { "szlig", 0x00df },
6671 { "tau", 0x03c4 }, 6694 { "tau", 0x03c4 },
6672 { "there4", 0x2234 }, 6695 { "there4", 0x2234 },
6673 { "theta", 0x03b8 }, 6696 { "theta", 0x03b8 },
6674 { "thetasym", 0x03d1 }, 6697 { "thetasym", 0x03d1 },
6675 { "thinsp", 0x2009 }, 6698 { "thinsp", 0x2009 },
6676 { "thorn", 0x00fe }, 6699 { "thorn", 0x00fe },
6677 { "tilde", 0x02dc }, 6700 { "tilde", 0x02dc },
6678 { "times", 0x00d7 }, 6701 { "times", 0x00d7 },
6679 { "trade", 0x2122 }, 6702 { "trade", 0x2122 },
6680 { "uArr", 0x21d1 }, 6703 { "uArr", 0x21d1 },
6681 { "uacute", 0x00fa }, 6704 { "uacute", 0x00fa },
6682 { "uarr", 0x2191 }, 6705 { "uarr", 0x2191 },
6683 { "ucirc", 0x00fb }, 6706 { "ucirc", 0x00fb },
6684 { "ugrave", 0x00f9 }, 6707 { "ugrave", 0x00f9 },
6685 { "uml", 0x00a8 }, 6708 { "uml", 0x00a8 },
6686 { "upsih", 0x03d2 }, 6709 { "upsih", 0x03d2 },
6687 { "upsilon", 0x03c5 }, 6710 { "upsilon", 0x03c5 },
6688 { "uuml", 0x00fc }, 6711 { "uuml", 0x00fc },
6689 { "weierp", 0x2118 }, 6712 { "weierp", 0x2118 },
6690 { "xi", 0x03be }, 6713 { "xi", 0x03be },
6691 { "yacute", 0x00fd }, 6714 { "yacute", 0x00fd },
6692 { "yen", 0x00a5 }, 6715 { "yen", 0x00a5 },
6693 { "yuml", 0x00ff }, 6716 { "yuml", 0x00ff },
6694 { "zeta", 0x03b6 }, 6717 { "zeta", 0x03b6 },
6695 { "zwj", 0x200d }, 6718 { "zwj", 0x200d },
6696 { "zwnj", 0x200c }, 6719 { "zwnj", 0x200c },
6697 { "", 0x0000 } 6720 { "", 0x0000 }
6698}; 6721};
6699 6722
6700 6723
6701 6724
6702 6725
6703 6726
6704static QMap<QCString, QChar> *html_map = 0; 6727static QMap<QCString, QChar> *html_map = 0;
6705static void qt_cleanup_html_map() 6728static void qt_cleanup_html_map()
6706{ 6729{
6707 delete html_map; 6730 delete html_map;
6708 html_map = 0; 6731 html_map = 0;
6709} 6732}
6710 6733
6711static QMap<QCString, QChar> *htmlMap() 6734static QMap<QCString, QChar> *htmlMap()
6712{ 6735{
6713 if ( !html_map ) { 6736 if ( !html_map ) {
6714 html_map = new QMap<QCString, QChar>; 6737 html_map = new QMap<QCString, QChar>;
6715 qAddPostRoutine( qt_cleanup_html_map ); 6738 qAddPostRoutine( qt_cleanup_html_map );
6716 6739
6717 const Entity *ent = entitylist; 6740 const Entity *ent = entitylist;
6718 while( ent->code ) { 6741 while( ent->code ) {
6719 html_map->insert( ent->name, QChar(ent->code) ); 6742 html_map->insert( ent->name, QChar(ent->code) );
6720 ent++; 6743 ent++;
6721 } 6744 }
6722 } 6745 }
6723 return html_map; 6746 return html_map;
6724} 6747}
6725 6748
6726QChar QTextDocument::parseHTMLSpecialChar(const QChar* doc, int length, int& pos) 6749QChar QTextDocument::parseHTMLSpecialChar(const QChar* doc, int length, int& pos)
6727{ 6750{
6728 QCString s; 6751 QCString s;
6729 pos++; 6752 pos++;
6730 int recoverpos = pos; 6753 int recoverpos = pos;
6731 while ( pos < length && doc[pos] != ';' && !doc[pos].isSpace() && pos < recoverpos + 6) { 6754 while ( pos < length && doc[pos] != ';' && !doc[pos].isSpace() && pos < recoverpos + 6) {
6732 s += doc[pos]; 6755 s += doc[pos];
6733 pos++; 6756 pos++;
6734 } 6757 }
6735 if (doc[pos] != ';' && !doc[pos].isSpace() ) { 6758 if (doc[pos] != ';' && !doc[pos].isSpace() ) {
6736 pos = recoverpos; 6759 pos = recoverpos;
6737 return '&'; 6760 return '&';
6738 } 6761 }
6739 pos++; 6762 pos++;
6740 6763
6741 if ( s.length() > 1 && s[0] == '#') { 6764 if ( s.length() > 1 && s[0] == '#') {
6742 int num = s.mid(1).toInt(); 6765 int num = s.mid(1).toInt();
6743 if ( num == 151 ) // ### hack for designer manual 6766 if ( num == 151 ) // ### hack for designer manual
6744 return '-'; 6767 return '-';
6745 return num; 6768 return num;
6746 } 6769 }
6747 6770
6748 QMap<QCString, QChar>::Iterator it = htmlMap()->find(s); 6771 QMap<QCString, QChar>::Iterator it = htmlMap()->find(s);
6749 if ( it != htmlMap()->end() ) { 6772 if ( it != htmlMap()->end() ) {
6750 return *it; 6773 return *it;
6751 } 6774 }
6752 6775
6753 pos = recoverpos; 6776 pos = recoverpos;
6754 return '&'; 6777 return '&';
6755} 6778}
6756 6779
6757QString QTextDocument::parseWord(const QChar* doc, int length, int& pos, bool lower) 6780QString QTextDocument::parseWord(const QChar* doc, int length, int& pos, bool lower)
6758{ 6781{
6759 QString s; 6782 QString s;
6760 6783
6761 if (doc[pos] == '"') { 6784 if (doc[pos] == '"') {
6762 pos++; 6785 pos++;
6763 while ( pos < length && doc[pos] != '"' ) { 6786 while ( pos < length && doc[pos] != '"' ) {
6764 s += doc[pos]; 6787 s += doc[pos];
6765 pos++; 6788 pos++;
6766 } 6789 }
6767 eat(doc, length, pos, '"'); 6790 eat(doc, length, pos, '"');
6768 } else { 6791 } else {
6769 static QString term = QString::fromLatin1("/>"); 6792 static QString term = QString::fromLatin1("/>");
6770 while( pos < length && 6793 while( pos < length &&
6771 (doc[pos] != '>' && !hasPrefix( doc, length, pos, term)) 6794 (doc[pos] != '>' && !hasPrefix( doc, length, pos, term))
6772 && doc[pos] != '<' 6795 && doc[pos] != '<'
6773 && doc[pos] != '=' 6796 && doc[pos] != '='
6774 && !doc[pos].isSpace()) 6797 && !doc[pos].isSpace())
6775 { 6798 {
6776 if ( doc[pos] == '&') 6799 if ( doc[pos] == '&')
6777 s += parseHTMLSpecialChar( doc, length, pos ); 6800 s += parseHTMLSpecialChar( doc, length, pos );
6778 else { 6801 else {
6779 s += doc[pos]; 6802 s += doc[pos];
6780 pos++; 6803 pos++;
6781 } 6804 }
6782 } 6805 }
6783 if (lower) 6806 if (lower)
6784 s = s.lower(); 6807 s = s.lower();
6785 } 6808 }
6786 return s; 6809 return s;
6787} 6810}
6788 6811
6789QChar QTextDocument::parseChar(const QChar* doc, int length, int& pos, QStyleSheetItem::WhiteSpaceMode wsm ) 6812QChar QTextDocument::parseChar(const QChar* doc, int length, int& pos, QStyleSheetItem::WhiteSpaceMode wsm )
6790{ 6813{
6791 if ( pos >= length ) 6814 if ( pos >= length )
6792 return QChar::null; 6815 return QChar::null;
6793 6816
6794 QChar c = doc[pos++]; 6817 QChar c = doc[pos++];
6795 6818
6796 if (c == '<' ) 6819 if (c == '<' )
6797 return QChar::null; 6820 return QChar::null;
6798 6821
6799 if ( c.isSpace() && c != QChar::nbsp ) { 6822 if ( c.isSpace() && c != QChar::nbsp ) {
6800 if ( wsm == QStyleSheetItem::WhiteSpacePre ) { 6823 if ( wsm == QStyleSheetItem::WhiteSpacePre ) {
6801 if ( c == '\n' ) 6824 if ( c == '\n' )
6802 return QChar_linesep; 6825 return QChar_linesep;
6803 else 6826 else
6804 return c; 6827 return c;
6805 } else { // non-pre mode: collapse whitespace except nbsp 6828 } else { // non-pre mode: collapse whitespace except nbsp
6806 while ( pos< length && 6829 while ( pos< length &&
6807 doc[pos].isSpace() && doc[pos] != QChar::nbsp ) 6830 doc[pos].isSpace() && doc[pos] != QChar::nbsp )
6808 pos++; 6831 pos++;
6809 if ( wsm == QStyleSheetItem::WhiteSpaceNoWrap ) 6832 if ( wsm == QStyleSheetItem::WhiteSpaceNoWrap )
6810 return QChar::nbsp; 6833 return QChar::nbsp;
6811 else 6834 else
6812 return ' '; 6835 return ' ';
6813 } 6836 }
6814 } 6837 }
6815 else if ( c == '&' ) 6838 else if ( c == '&' )
6816 return parseHTMLSpecialChar( doc, length, --pos ); 6839 return parseHTMLSpecialChar( doc, length, --pos );
6817 else 6840 else
6818 return c; 6841 return c;
6819} 6842}
6820 6843
6821QString QTextDocument::parseOpenTag(const QChar* doc, int length, int& pos, 6844QString QTextDocument::parseOpenTag(const QChar* doc, int length, int& pos,
6822 QMap<QString, QString> &attr, bool& emptyTag) 6845 QMap<QString, QString> &attr, bool& emptyTag)
6823{ 6846{
6824 emptyTag = FALSE; 6847 emptyTag = FALSE;
6825 pos++; 6848 pos++;
6826 if ( hasPrefix(doc, length, pos, '!') ) { 6849 if ( hasPrefix(doc, length, pos, '!') ) {
6827 if ( hasPrefix( doc, length, pos+1, "--")) { 6850 if ( hasPrefix( doc, length, pos+1, "--")) {
6828 pos += 3; 6851 pos += 3;
6829 // eat comments 6852 // eat comments
6830 QString pref = QString::fromLatin1("-->"); 6853 QString pref = QString::fromLatin1("-->");
6831 while ( !hasPrefix(doc, length, pos, pref ) && pos < length ) 6854 while ( !hasPrefix(doc, length, pos, pref ) && pos < length )
6832 pos++; 6855 pos++;
6833 if ( hasPrefix(doc, length, pos, pref ) ) { 6856 if ( hasPrefix(doc, length, pos, pref ) ) {
6834 pos += 3; 6857 pos += 3;
6835 eatSpace(doc, length, pos, TRUE); 6858 eatSpace(doc, length, pos, TRUE);
6836 } 6859 }
6837 emptyTag = TRUE; 6860 emptyTag = TRUE;
6838 return QString::null; 6861 return QString::null;
6839 } 6862 }
6840 else { 6863 else {
6841 // eat strange internal tags 6864 // eat strange internal tags
6842 while ( !hasPrefix(doc, length, pos, '>') && pos < length ) 6865 while ( !hasPrefix(doc, length, pos, '>') && pos < length )
6843 pos++; 6866 pos++;
6844 if ( hasPrefix(doc, length, pos, '>') ) { 6867 if ( hasPrefix(doc, length, pos, '>') ) {
6845 pos++; 6868 pos++;
6846 eatSpace(doc, length, pos, TRUE); 6869 eatSpace(doc, length, pos, TRUE);
6847 } 6870 }
6848 return QString::null; 6871 return QString::null;
6849 } 6872 }
6850 } 6873 }
6851 6874
6852 QString tag = parseWord(doc, length, pos ); 6875 QString tag = parseWord(doc, length, pos );
6853 eatSpace(doc, length, pos, TRUE); 6876 eatSpace(doc, length, pos, TRUE);
6854 static QString term = QString::fromLatin1("/>"); 6877 static QString term = QString::fromLatin1("/>");
6855 static QString s_TRUE = QString::fromLatin1("TRUE"); 6878 static QString s_TRUE = QString::fromLatin1("TRUE");
6856 6879
6857 while (doc[pos] != '>' && ! (emptyTag = hasPrefix(doc, length, pos, term) )) { 6880 while (doc[pos] != '>' && ! (emptyTag = hasPrefix(doc, length, pos, term) )) {
6858 QString key = parseWord(doc, length, pos ); 6881 QString key = parseWord(doc, length, pos );
6859 eatSpace(doc, length, pos, TRUE); 6882 eatSpace(doc, length, pos, TRUE);
6860 if ( key.isEmpty()) { 6883 if ( key.isEmpty()) {
6861 // error recovery 6884 // error recovery
6862 while ( pos < length && doc[pos] != '>' ) 6885 while ( pos < length && doc[pos] != '>' )
6863 pos++; 6886 pos++;
6864 break; 6887 break;
6865 } 6888 }
6866 QString value; 6889 QString value;
6867 if (hasPrefix(doc, length, pos, '=') ){ 6890 if (hasPrefix(doc, length, pos, '=') ){
6868 pos++; 6891 pos++;
6869 eatSpace(doc, length, pos); 6892 eatSpace(doc, length, pos);
6870 value = parseWord(doc, length, pos, FALSE); 6893 value = parseWord(doc, length, pos, FALSE);
6871 } 6894 }
6872 else 6895 else
6873 value = s_TRUE; 6896 value = s_TRUE;
6874 attr.insert(key.lower(), value ); 6897 attr.insert(key.lower(), value );
6875 eatSpace(doc, length, pos, TRUE); 6898 eatSpace(doc, length, pos, TRUE);
6876 } 6899 }
6877 6900
6878 if (emptyTag) { 6901 if (emptyTag) {
6879 eat(doc, length, pos, '/'); 6902 eat(doc, length, pos, '/');
6880 eat(doc, length, pos, '>'); 6903 eat(doc, length, pos, '>');
6881 } 6904 }
6882 else 6905 else
6883 eat(doc, length, pos, '>'); 6906 eat(doc, length, pos, '>');
6884 6907
6885 return tag; 6908 return tag;
6886} 6909}
6887 6910
6888QString QTextDocument::parseCloseTag( const QChar* doc, int length, int& pos ) 6911QString QTextDocument::parseCloseTag( const QChar* doc, int length, int& pos )
6889{ 6912{
6890 pos++; 6913 pos++;
6891 pos++; 6914 pos++;
6892 QString tag = parseWord(doc, length, pos ); 6915 QString tag = parseWord(doc, length, pos );
6893 eatSpace(doc, length, pos, TRUE); 6916 eatSpace(doc, length, pos, TRUE);
6894 eat(doc, length, pos, '>'); 6917 eat(doc, length, pos, '>');
6895 return tag; 6918 return tag;
6896} 6919}
6897 6920
6898QTextFlow::QTextFlow() 6921QTextFlow::QTextFlow()
6899{ 6922{
6900 w = pagesize = 0; 6923 w = pagesize = 0;
6901 leftItems.setAutoDelete( FALSE ); 6924 leftItems.setAutoDelete( FALSE );
6902 rightItems.setAutoDelete( FALSE ); 6925 rightItems.setAutoDelete( FALSE );
6903} 6926}
6904 6927
6905QTextFlow::~QTextFlow() 6928QTextFlow::~QTextFlow()
6906{ 6929{
6907} 6930}
6908 6931
6909void QTextFlow::clear() 6932void QTextFlow::clear()
6910{ 6933{
6911 leftItems.clear(); 6934 leftItems.clear();
6912 rightItems.clear(); 6935 rightItems.clear();
6913} 6936}
6914 6937
6915void QTextFlow::setWidth( int width ) 6938void QTextFlow::setWidth( int width )
6916{ 6939{
6917 w = width; 6940 w = width;
6918} 6941}
6919 6942
6920int QTextFlow::adjustLMargin( int yp, int, int margin, int space ) 6943int QTextFlow::adjustLMargin( int yp, int, int margin, int space )
6921{ 6944{
6922 for ( QTextCustomItem* item = leftItems.first(); item; item = leftItems.next() ) { 6945 for ( QTextCustomItem* item = leftItems.first(); item; item = leftItems.next() ) {
6923 if ( item->ypos == -1 ) 6946 if ( item->ypos == -1 )
6924 continue; 6947 continue;
6925 if ( yp >= item->ypos && yp < item->ypos + item->height ) 6948 if ( yp >= item->ypos && yp < item->ypos + item->height )
6926 margin = QMAX( margin, item->xpos + item->width + space ); 6949 margin = QMAX( margin, item->xpos + item->width + space );
6927 } 6950 }
6928 return margin; 6951 return margin;
6929} 6952}
6930 6953
6931int QTextFlow::adjustRMargin( int yp, int, int margin, int space ) 6954int QTextFlow::adjustRMargin( int yp, int, int margin, int space )
6932{ 6955{
6933 for ( QTextCustomItem* item = rightItems.first(); item; item = rightItems.next() ) { 6956 for ( QTextCustomItem* item = rightItems.first(); item; item = rightItems.next() ) {
6934 if ( item->ypos == -1 ) 6957 if ( item->ypos == -1 )
6935 continue; 6958 continue;
6936 if ( yp >= item->ypos && yp < item->ypos + item->height ) 6959 if ( yp >= item->ypos && yp < item->ypos + item->height )
6937 margin = QMAX( margin, w - item->xpos - space ); 6960 margin = QMAX( margin, w - item->xpos - space );
6938 } 6961 }
6939 return margin; 6962 return margin;
6940} 6963}
6941 6964
6942 6965
6943int QTextFlow::adjustFlow( int y, int /*w*/, int h ) 6966int QTextFlow::adjustFlow( int y, int /*w*/, int h )
6944{ 6967{
6945 if ( pagesize > 0 ) { // check pages 6968 if ( pagesize > 0 ) { // check pages
6946 int yinpage = y % pagesize; 6969 int yinpage = y % pagesize;
6947 if ( yinpage <= border_tolerance ) 6970 if ( yinpage <= border_tolerance )
6948 return border_tolerance - yinpage; 6971 return border_tolerance - yinpage;
6949 else 6972 else
6950 if ( yinpage + h > pagesize - border_tolerance ) 6973 if ( yinpage + h > pagesize - border_tolerance )
6951 return ( pagesize - yinpage ) + border_tolerance; 6974 return ( pagesize - yinpage ) + border_tolerance;
6952 } 6975 }
6953 return 0; 6976 return 0;
6954} 6977}
6955 6978
6956void QTextFlow::unregisterFloatingItem( QTextCustomItem* item ) 6979void QTextFlow::unregisterFloatingItem( QTextCustomItem* item )
6957{ 6980{
6958 leftItems.removeRef( item ); 6981 leftItems.removeRef( item );
6959 rightItems.removeRef( item ); 6982 rightItems.removeRef( item );
6960} 6983}
6961 6984
6962void QTextFlow::registerFloatingItem( QTextCustomItem* item ) 6985void QTextFlow::registerFloatingItem( QTextCustomItem* item )
6963{ 6986{
6964 if ( item->placement() == QTextCustomItem::PlaceRight ) { 6987 if ( item->placement() == QTextCustomItem::PlaceRight ) {
6965 if ( !rightItems.contains( item ) ) 6988 if ( !rightItems.contains( item ) )
6966 rightItems.append( item ); 6989 rightItems.append( item );
6967 } else if ( item->placement() == QTextCustomItem::PlaceLeft && 6990 } else if ( item->placement() == QTextCustomItem::PlaceLeft &&
6968 !leftItems.contains( item ) ) { 6991 !leftItems.contains( item ) ) {
6969 leftItems.append( item ); 6992 leftItems.append( item );
6970 } 6993 }
6971} 6994}
6972 6995
6973QRect QTextFlow::boundingRect() const 6996QRect QTextFlow::boundingRect() const
6974{ 6997{
6975 QRect br; 6998 QRect br;
6976 QPtrListIterator<QTextCustomItem> l( leftItems ); 6999 QPtrListIterator<QTextCustomItem> l( leftItems );
6977 while( l.current() ) { 7000 while( l.current() ) {
6978 br = br.unite( l.current()->geometry() ); 7001 br = br.unite( l.current()->geometry() );
6979 ++l; 7002 ++l;
6980 } 7003 }
6981 QPtrListIterator<QTextCustomItem> r( rightItems ); 7004 QPtrListIterator<QTextCustomItem> r( rightItems );
6982 while( r.current() ) { 7005 while( r.current() ) {
6983 br = br.unite( r.current()->geometry() ); 7006 br = br.unite( r.current()->geometry() );
6984 ++r; 7007 ++r;
6985 } 7008 }
6986 return br; 7009 return br;
6987} 7010}
6988 7011
6989 7012
6990void QTextFlow::drawFloatingItems( QPainter* p, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ) 7013void QTextFlow::drawFloatingItems( QPainter* p, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected )
6991{ 7014{
6992 QTextCustomItem *item; 7015 QTextCustomItem *item;
6993 for ( item = leftItems.first(); item; item = leftItems.next() ) { 7016 for ( item = leftItems.first(); item; item = leftItems.next() ) {
6994 if ( item->xpos == -1 || item->ypos == -1 ) 7017 if ( item->xpos == -1 || item->ypos == -1 )
6995 continue; 7018 continue;
6996 item->draw( p, item->xpos, item->ypos, cx, cy, cw, ch, cg, selected ); 7019 item->draw( p, item->xpos, item->ypos, cx, cy, cw, ch, cg, selected );
6997 } 7020 }
6998 7021
6999 for ( item = rightItems.first(); item; item = rightItems.next() ) { 7022 for ( item = rightItems.first(); item; item = rightItems.next() ) {
7000 if ( item->xpos == -1 || item->ypos == -1 ) 7023 if ( item->xpos == -1 || item->ypos == -1 )
7001 continue; 7024 continue;
7002 item->draw( p, item->xpos, item->ypos, cx, cy, cw, ch, cg, selected ); 7025 item->draw( p, item->xpos, item->ypos, cx, cy, cw, ch, cg, selected );
7003 } 7026 }
7004} 7027}
7005 7028
7006// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7029// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7007 7030
7008void QTextCustomItem::pageBreak( int /*y*/ , QTextFlow* /*flow*/ ) 7031void QTextCustomItem::pageBreak( int /*y*/ , QTextFlow* /*flow*/ )
7009{ 7032{
7010} 7033}
7011 7034
7012QTextTable::QTextTable( QTextDocument *p, const QMap<QString, QString> & attr ) 7035QTextTable::QTextTable( QTextDocument *p, const QMap<QString, QString> & attr )
7013 : QTextCustomItem( p ) 7036 : QTextCustomItem( p )
7014{ 7037{
7015 cells.setAutoDelete( FALSE ); 7038 cells.setAutoDelete( FALSE );
7016 cellspacing = 2; 7039 cellspacing = 2;
7017 if ( attr.contains("cellspacing") ) 7040 if ( attr.contains("cellspacing") )
7018 cellspacing = attr["cellspacing"].toInt(); 7041 cellspacing = attr["cellspacing"].toInt();
7019 cellpadding = 1; 7042 cellpadding = 1;
7020 if ( attr.contains("cellpadding") ) 7043 if ( attr.contains("cellpadding") )
7021 cellpadding = attr["cellpadding"].toInt(); 7044 cellpadding = attr["cellpadding"].toInt();
7022 border = innerborder = 0; 7045 border = innerborder = 0;
7023 if ( attr.contains("border" ) ) { 7046 if ( attr.contains("border" ) ) {
7024 QString s( attr["border"] ); 7047 QString s( attr["border"] );
7025 if ( s == "TRUE" ) 7048 if ( s == "TRUE" )
7026 border = 1; 7049 border = 1;
7027 else 7050 else
7028 border = attr["border"].toInt(); 7051 border = attr["border"].toInt();
7029 } 7052 }
7030 us_b = border; 7053 us_b = border;
7031 7054
7032 innerborder = us_ib = border ? 1 : 0; 7055 innerborder = us_ib = border ? 1 : 0;
7033 7056
7034 if ( border ) 7057 if ( border )
7035 cellspacing += 2; 7058 cellspacing += 2;
7036 7059
7037 us_ib = innerborder; 7060 us_ib = innerborder;
7038 us_cs = cellspacing; 7061 us_cs = cellspacing;
7039 us_cp = cellpadding; 7062 us_cp = cellpadding;
7040 outerborder = cellspacing + border; 7063 outerborder = cellspacing + border;
7041 us_ob = outerborder; 7064 us_ob = outerborder;
7042 layout = new QGridLayout( 1, 1, cellspacing ); 7065 layout = new QGridLayout( 1, 1, cellspacing );
7043 7066
7044 fixwidth = 0; 7067 fixwidth = 0;
7045 stretch = 0; 7068 stretch = 0;
7046 if ( attr.contains("width") ) { 7069 if ( attr.contains("width") ) {
7047 bool b; 7070 bool b;
7048 QString s( attr["width"] ); 7071 QString s( attr["width"] );
7049 int w = s.toInt( &b ); 7072 int w = s.toInt( &b );
7050 if ( b ) { 7073 if ( b ) {
7051 fixwidth = w; 7074 fixwidth = w;
7052 } else { 7075 } else {
7053 s = s.stripWhiteSpace(); 7076 s = s.stripWhiteSpace();
7054 if ( s.length() > 1 && s[ (int)s.length()-1 ] == '%' ) 7077 if ( s.length() > 1 && s[ (int)s.length()-1 ] == '%' )
7055 stretch = s.left( s.length()-1).toInt(); 7078 stretch = s.left( s.length()-1).toInt();
7056 } 7079 }
7057 } 7080 }
7058 7081
7059 place = PlaceInline; 7082 place = PlaceInline;
7060 if ( attr["align"] == "left" ) 7083 if ( attr["align"] == "left" )
7061 place = PlaceLeft; 7084 place = PlaceLeft;
7062 else if ( attr["align"] == "right" ) 7085 else if ( attr["align"] == "right" )
7063 place = PlaceRight; 7086 place = PlaceRight;
7064 cachewidth = 0; 7087 cachewidth = 0;
7065 attributes = attr; 7088 attributes = attr;
7066 pageBreakFor = -1; 7089 pageBreakFor = -1;
7067} 7090}
7068 7091
7069QTextTable::~QTextTable() 7092QTextTable::~QTextTable()
7070{ 7093{
7071 delete layout; 7094 delete layout;
7072} 7095}
7073 7096
7074QString QTextTable::richText() const 7097QString QTextTable::richText() const
7075{ 7098{
7076 QString s; 7099 QString s;
7077 s = "<table "; 7100 s = "<table ";
7078 QMap<QString, QString>::ConstIterator it = attributes.begin(); 7101 QMap<QString, QString>::ConstIterator it = attributes.begin();
7079 for ( ; it != attributes.end(); ++it ) 7102 for ( ; it != attributes.end(); ++it )
7080 s += it.key() + "=" + *it + " "; 7103 s += it.key() + "=" + *it + " ";
7081 s += ">\n"; 7104 s += ">\n";
7082 7105
7083 int lastRow = -1; 7106 int lastRow = -1;
7084 bool needEnd = FALSE; 7107 bool needEnd = FALSE;
7085 QPtrListIterator<QTextTableCell> it2( cells ); 7108 QPtrListIterator<QTextTableCell> it2( cells );
7086 while ( it2.current() ) { 7109 while ( it2.current() ) {
7087 QTextTableCell *cell = it2.current(); 7110 QTextTableCell *cell = it2.current();
7088 ++it2; 7111 ++it2;
7089 if ( lastRow != cell->row() ) { 7112 if ( lastRow != cell->row() ) {
7090 if ( lastRow != -1 ) 7113 if ( lastRow != -1 )
7091 s += "</tr>\n"; 7114 s += "</tr>\n";
7092 s += "<tr>"; 7115 s += "<tr>";
7093 lastRow = cell->row(); 7116 lastRow = cell->row();
7094 needEnd = TRUE; 7117 needEnd = TRUE;
7095 } 7118 }
7096 s += "<td"; 7119 s += "<td";
7097 it = cell->attributes.begin(); 7120 it = cell->attributes.begin();
7098 for ( ; it != cell->attributes.end(); ++it ) 7121 for ( ; it != cell->attributes.end(); ++it )
7099 s += " " + it.key() + "=" + *it; 7122 s += " " + it.key() + "=" + *it;
7100 s += ">"; 7123 s += ">";
7101 s += cell->richText()->richText(); 7124 s += cell->richText()->richText();
7102 s += "</td>"; 7125 s += "</td>";
7103 } 7126 }
7104 if ( needEnd ) 7127 if ( needEnd )
7105 s += "</tr>\n"; 7128 s += "</tr>\n";
7106 s += "</table>\n"; 7129 s += "</table>\n";
7107 return s; 7130 return s;
7108} 7131}
7109 7132
7110void QTextTable::adjustToPainter( QPainter* p ) 7133void QTextTable::adjustToPainter( QPainter* p )
7111{ 7134{
7112 cellspacing = scale( us_cs, p ); 7135 cellspacing = scale( us_cs, p );
7113 cellpadding = scale( us_cp, p ); 7136 cellpadding = scale( us_cp, p );
7114 border = scale( us_b , p ); 7137 border = scale( us_b , p );
7115 innerborder = scale( us_ib, p ); 7138 innerborder = scale( us_ib, p );
7116 outerborder = scale( us_ob ,p ); 7139 outerborder = scale( us_ob ,p );
7117 width = 0; 7140 width = 0;
7118 cachewidth = 0; 7141 cachewidth = 0;
7119 for ( QTextTableCell* cell = cells.first(); cell; cell = cells.next() ) 7142 for ( QTextTableCell* cell = cells.first(); cell; cell = cells.next() )
7120 cell->adjustToPainter( p ); 7143 cell->adjustToPainter( p );
7121} 7144}
7122 7145
7123void QTextTable::adjustCells( int y , int shift ) 7146void QTextTable::adjustCells( int y , int shift )
7124{ 7147{
7125 QPtrListIterator<QTextTableCell> it( cells ); 7148 QPtrListIterator<QTextTableCell> it( cells );
7126 QTextTableCell* cell; 7149 QTextTableCell* cell;
7127 bool enlarge = FALSE; 7150 bool enlarge = FALSE;
7128 while ( ( cell = it.current() ) ) { 7151 while ( ( cell = it.current() ) ) {
7129 ++it; 7152 ++it;
7130 QRect r = cell->geometry(); 7153 QRect r = cell->geometry();
7131 if ( y <= r.top() ) { 7154 if ( y <= r.top() ) {
7132 r.moveBy(0, shift ); 7155 r.moveBy(0, shift );
7133 cell->setGeometry( r ); 7156 cell->setGeometry( r );
7134 enlarge = TRUE; 7157 enlarge = TRUE;
7135 } else if ( y <= r.bottom() ) { 7158 } else if ( y <= r.bottom() ) {
7136 r.rBottom() += shift; 7159 r.rBottom() += shift;
7137 cell->setGeometry( r ); 7160 cell->setGeometry( r );
7138 enlarge = TRUE; 7161 enlarge = TRUE;
7139 } 7162 }
7140 } 7163 }
7141 if ( enlarge ) 7164 if ( enlarge )
7142 height += shift; 7165 height += shift;
7143} 7166}
7144 7167
7145void QTextTable::pageBreak( int yt, QTextFlow* flow ) 7168void QTextTable::pageBreak( int yt, QTextFlow* flow )
7146{ 7169{
7147 if ( flow->pageSize() <= 0 ) 7170 if ( flow->pageSize() <= 0 )
7148 return; 7171 return;
7149 if ( layout && pageBreakFor > 0 && pageBreakFor != yt ) { 7172 if ( layout && pageBreakFor > 0 && pageBreakFor != yt ) {
7150 layout->invalidate(); 7173 layout->invalidate();
7151 int h = layout->heightForWidth( width-2*outerborder ); 7174 int h = layout->heightForWidth( width-2*outerborder );
7152 layout->setGeometry( QRect(0, 0, width-2*outerborder, h) ); 7175 layout->setGeometry( QRect(0, 0, width-2*outerborder, h) );
7153 height = layout->geometry().height()+2*outerborder; 7176 height = layout->geometry().height()+2*outerborder;
7154 } 7177 }
7155 pageBreakFor = yt; 7178 pageBreakFor = yt;
7156 QPtrListIterator<QTextTableCell> it( cells ); 7179 QPtrListIterator<QTextTableCell> it( cells );
7157 QTextTableCell* cell; 7180 QTextTableCell* cell;
7158 while ( ( cell = it.current() ) ) { 7181 while ( ( cell = it.current() ) ) {
7159 ++it; 7182 ++it;
7160 int y = yt + outerborder + cell->geometry().y(); 7183 int y = yt + outerborder + cell->geometry().y();
7161 int shift = flow->adjustFlow( y - cellspacing, width, cell->richText()->height() + 2*cellspacing ); 7184 int shift = flow->adjustFlow( y - cellspacing, width, cell->richText()->height() + 2*cellspacing );
7162 adjustCells( y - outerborder - yt, shift ); 7185 adjustCells( y - outerborder - yt, shift );
7163 } 7186 }
7164} 7187}
7165 7188
7166 7189
7167void QTextTable::draw(QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ) 7190void QTextTable::draw(QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected )
7168{ 7191{
7169 if ( placement() != PlaceInline ) { 7192 if ( placement() != PlaceInline ) {
7170 x = xpos; 7193 x = xpos;
7171 y = ypos; 7194 y = ypos;
7172 } 7195 }
7173 7196
7174 for (QTextTableCell* cell = cells.first(); cell; cell = cells.next() ) { 7197 for (QTextTableCell* cell = cells.first(); cell; cell = cells.next() ) {
7175 if ( cx < 0 && cy < 0 || 7198 if ( cx < 0 && cy < 0 ||
7176 QRect( cx, cy, cw, ch ).intersects( QRect( x + outerborder + cell->geometry().x(), 7199 QRect( cx, cy, cw, ch ).intersects( QRect( x + outerborder + cell->geometry().x(),
7177 y + outerborder + cell->geometry().y(), 7200 y + outerborder + cell->geometry().y(),
7178 cell->geometry().width(), cell->geometry().height() ) ) ) { 7201 cell->geometry().width(), cell->geometry().height() ) ) ) {
7179 cell->draw( p, x+outerborder, y+outerborder, cx, cy, cw, ch, cg, selected ); 7202 cell->draw( p, x+outerborder, y+outerborder, cx, cy, cw, ch, cg, selected );
7180 if ( border ) { 7203 if ( border ) {
7181 QRect r( x+outerborder+cell->geometry().x() - innerborder, 7204 QRect r( x+outerborder+cell->geometry().x() - innerborder,
7182 y+outerborder+cell->geometry().y() - innerborder, 7205 y+outerborder+cell->geometry().y() - innerborder,
7183 cell->geometry().width() + 2 * innerborder, 7206 cell->geometry().width() + 2 * innerborder,
7184 cell->geometry().height() + 2 * innerborder ); 7207 cell->geometry().height() + 2 * innerborder );
7185 if ( is_printer( p ) ) { 7208 if ( is_printer( p ) ) {
7186 QPen oldPen = p->pen(); 7209 QPen oldPen = p->pen();
7187 QRect r2 = r; 7210 QRect r2 = r;
7188 r2.setLeft( r2.left() + innerborder/2 ); 7211 r2.setLeft( r2.left() + innerborder/2 );
7189 r2.setTop( r2.top() + innerborder/2 ); 7212 r2.setTop( r2.top() + innerborder/2 );
7190 r2.setRight( r2.right() - innerborder/2 ); 7213 r2.setRight( r2.right() - innerborder/2 );
7191 r2.setBottom( r2.bottom() - innerborder/2 ); 7214 r2.setBottom( r2.bottom() - innerborder/2 );
7192 p->setPen( QPen( cg.text(), innerborder ) ); 7215 p->setPen( QPen( cg.text(), innerborder ) );
7193 p->drawRect( r2 ); 7216 p->drawRect( r2 );
7194 p->setPen( oldPen ); 7217 p->setPen( oldPen );
7195 } else { 7218 } else {
7196 int s = QMAX( cellspacing-2*innerborder, 0); 7219 int s = QMAX( cellspacing-2*innerborder, 0);
7197 if ( s ) { 7220 if ( s ) {
7198 p->fillRect( r.left()-s, r.top(), s+1, r.height(), cg.button() ); 7221 p->fillRect( r.left()-s, r.top(), s+1, r.height(), cg.button() );
7199 p->fillRect( r.right(), r.top(), s+1, r.height(), cg.button() ); 7222 p->fillRect( r.right(), r.top(), s+1, r.height(), cg.button() );
7200 p->fillRect( r.left()-s, r.top()-s, r.width()+2*s, s, cg.button() ); 7223 p->fillRect( r.left()-s, r.top()-s, r.width()+2*s, s, cg.button() );
7201 p->fillRect( r.left()-s, r.bottom(), r.width()+2*s, s, cg.button() ); 7224 p->fillRect( r.left()-s, r.bottom(), r.width()+2*s, s, cg.button() );
7202 } 7225 }
7203 qDrawShadePanel( p, r, cg, TRUE, innerborder ); 7226 qDrawShadePanel( p, r, cg, TRUE, innerborder );
7204 } 7227 }
7205 } 7228 }
7206 } 7229 }
7207 } 7230 }
7208 if ( border ) { 7231 if ( border ) {
7209 QRect r ( x, y, width, height ); 7232 QRect r ( x, y, width, height );
7210 if ( is_printer( p ) ) { 7233 if ( is_printer( p ) ) {
7211 QRect r2 = r; 7234 QRect r2 = r;
7212 r2.setLeft( r2.left() + border/2 ); 7235 r2.setLeft( r2.left() + border/2 );
7213 r2.setTop( r2.top() + border/2 ); 7236 r2.setTop( r2.top() + border/2 );
7214 r2.setRight( r2.right() - border/2 ); 7237 r2.setRight( r2.right() - border/2 );
7215 r2.setBottom( r2.bottom() - border/2 ); 7238 r2.setBottom( r2.bottom() - border/2 );
7216 QPen oldPen = p->pen(); 7239 QPen oldPen = p->pen();
7217 p->setPen( QPen( cg.text(), border ) ); 7240 p->setPen( QPen( cg.text(), border ) );
7218 p->drawRect( r2 ); 7241 p->drawRect( r2 );
7219 p->setPen( oldPen ); 7242 p->setPen( oldPen );
7220 } else { 7243 } else {
7221 int s = border+QMAX( cellspacing-2*innerborder, 0); 7244 int s = border+QMAX( cellspacing-2*innerborder, 0);
7222 if ( s ) { 7245 if ( s ) {
7223 p->fillRect( r.left(), r.top(), s, r.height(), cg.button() ); 7246 p->fillRect( r.left(), r.top(), s, r.height(), cg.button() );
7224 p->fillRect( r.right()-s, r.top(), s, r.height(), cg.button() ); 7247 p->fillRect( r.right()-s, r.top(), s, r.height(), cg.button() );
7225 p->fillRect( r.left(), r.top(), r.width(), s, cg.button() ); 7248 p->fillRect( r.left(), r.top(), r.width(), s, cg.button() );
7226 p->fillRect( r.left(), r.bottom()-s, r.width(), s, cg.button() ); 7249 p->fillRect( r.left(), r.bottom()-s, r.width(), s, cg.button() );
7227 } 7250 }
7228 qDrawShadePanel( p, r, cg, FALSE, border ); 7251 qDrawShadePanel( p, r, cg, FALSE, border );
7229 } 7252 }
7230 } 7253 }
7231 7254
7232} 7255}
7233 7256
7234int QTextTable::minimumWidth() const 7257int QTextTable::minimumWidth() const
7235{ 7258{
7236 return (layout ? layout->minimumSize().width() : 0) + 2 * outerborder; 7259 return (layout ? layout->minimumSize().width() : 0) + 2 * outerborder;
7237} 7260}
7238 7261
7239void QTextTable::resize( int nwidth ) 7262void QTextTable::resize( int nwidth )
7240{ 7263{
7241 if ( fixwidth && cachewidth != 0 ) 7264 if ( fixwidth && cachewidth != 0 )
7242 return; 7265 return;
7243 if ( nwidth == cachewidth ) 7266 if ( nwidth == cachewidth )
7244 return; 7267 return;
7245 7268
7246 7269
7247 cachewidth = nwidth; 7270 cachewidth = nwidth;
7248 int w = nwidth; 7271 int w = nwidth;
7249 7272
7250 format( w ); 7273 format( w );
7251 7274
7252 if ( stretch ) 7275 if ( stretch )
7253 nwidth = nwidth * stretch / 100; 7276 nwidth = nwidth * stretch / 100;
7254 7277
7255 width = nwidth; 7278 width = nwidth;
7256 layout->invalidate(); 7279 layout->invalidate();
7257 int shw = layout->sizeHint().width() + 2*outerborder; 7280 int shw = layout->sizeHint().width() + 2*outerborder;
7258 int mw = layout->minimumSize().width() + 2*outerborder; 7281 int mw = layout->minimumSize().width() + 2*outerborder;
7259 if ( stretch ) 7282 if ( stretch )
7260 width = QMAX( mw, nwidth ); 7283 width = QMAX( mw, nwidth );
7261 else 7284 else
7262 width = QMAX( mw, QMIN( nwidth, shw ) ); 7285 width = QMAX( mw, QMIN( nwidth, shw ) );
7263 7286
7264 if ( fixwidth ) 7287 if ( fixwidth )
7265 width = fixwidth; 7288 width = fixwidth;
7266 7289
7267 layout->invalidate(); 7290 layout->invalidate();
7268 mw = layout->minimumSize().width() + 2*outerborder; 7291 mw = layout->minimumSize().width() + 2*outerborder;
7269 width = QMAX( width, mw ); 7292 width = QMAX( width, mw );
7270 7293
7271 int h = layout->heightForWidth( width-2*outerborder ); 7294 int h = layout->heightForWidth( width-2*outerborder );
7272 layout->setGeometry( QRect(0, 0, width-2*outerborder, h) ); 7295 layout->setGeometry( QRect(0, 0, width-2*outerborder, h) );
7273 height = layout->geometry().height()+2*outerborder; 7296 height = layout->geometry().height()+2*outerborder;
7274} 7297}
7275 7298
7276void QTextTable::format( int w ) 7299void QTextTable::format( int w )
7277{ 7300{
7278 for ( int i = 0; i < (int)cells.count(); ++i ) { 7301 for ( int i = 0; i < (int)cells.count(); ++i ) {
7279 QTextTableCell *cell = cells.at( i ); 7302 QTextTableCell *cell = cells.at( i );
7280 QRect r = cell->geometry(); 7303 QRect r = cell->geometry();
7281 r.setWidth( w - 2*outerborder ); 7304 r.setWidth( w - 2*outerborder );
7282 cell->setGeometry( r ); 7305 cell->setGeometry( r );
7283 } 7306 }
7284} 7307}
7285 7308
7286void QTextTable::addCell( QTextTableCell* cell ) 7309void QTextTable::addCell( QTextTableCell* cell )
7287{ 7310{
7288 cells.append( cell ); 7311 cells.append( cell );
7289 layout->addMultiCell( cell, cell->row(), cell->row() + cell->rowspan()-1, 7312 layout->addMultiCell( cell, cell->row(), cell->row() + cell->rowspan()-1,
7290 cell->column(), cell->column() + cell->colspan()-1 ); 7313 cell->column(), cell->column() + cell->colspan()-1 );
7291} 7314}
7292 7315
7293bool QTextTable::enter( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy, bool atEnd ) 7316bool QTextTable::enter( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy, bool atEnd )
7294{ 7317{
7295 currCell.remove( c ); 7318 currCell.remove( c );
7296 if ( !atEnd ) 7319 if ( !atEnd )
7297 return next( c, doc, parag, idx, ox, oy ); 7320 return next( c, doc, parag, idx, ox, oy );
7298 currCell.insert( c, cells.count() ); 7321 currCell.insert( c, cells.count() );
7299 return prev( c, doc, parag, idx, ox, oy ); 7322 return prev( c, doc, parag, idx, ox, oy );
7300} 7323}
7301 7324
7302bool QTextTable::enterAt( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy, const QPoint &pos ) 7325bool QTextTable::enterAt( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy, const QPoint &pos )
7303{ 7326{
7304 currCell.remove( c ); 7327 currCell.remove( c );
7305 int lastCell = -1; 7328 int lastCell = -1;
7306 int lastY = -1; 7329 int lastY = -1;
7307 int i; 7330 int i;
7308 for ( i = 0; i < (int)cells.count(); ++i ) { 7331 for ( i = 0; i < (int)cells.count(); ++i ) {
7309 QTextTableCell *cell = cells.at( i ); 7332 QTextTableCell *cell = cells.at( i );
7310 if ( !cell ) 7333 if ( !cell )
7311 continue; 7334 continue;
7312 QRect r( cell->geometry().x(), 7335 QRect r( cell->geometry().x(),
7313 cell->geometry().y(), 7336 cell->geometry().y(),
7314 cell->geometry().width() + 2 * innerborder + 2 * outerborder, 7337 cell->geometry().width() + 2 * innerborder + 2 * outerborder,
7315 cell->geometry().height() + 2 * innerborder + 2 * outerborder ); 7338 cell->geometry().height() + 2 * innerborder + 2 * outerborder );
7316 7339
7317 if ( r.left() <= pos.x() && r.right() >= pos.x() ) { 7340 if ( r.left() <= pos.x() && r.right() >= pos.x() ) {
7318 if ( cell->geometry().y() > lastY ) { 7341 if ( cell->geometry().y() > lastY ) {
7319 lastCell = i; 7342 lastCell = i;
7320 lastY = cell->geometry().y(); 7343 lastY = cell->geometry().y();
7321 } 7344 }
7322 if ( r.top() <= pos.y() && r.bottom() >= pos.y() ) { 7345 if ( r.top() <= pos.y() && r.bottom() >= pos.y() ) {
7323 currCell.insert( c, i ); 7346 currCell.insert( c, i );
7324 break; 7347 break;
7325 } 7348 }
7326 } 7349 }
7327 } 7350 }
7328 if ( i == (int) cells.count() ) 7351 if ( i == (int) cells.count() )
7329 return FALSE; // no cell found 7352 return FALSE; // no cell found
7330 7353
7331 if ( currCell.find( c ) == currCell.end() ) { 7354 if ( currCell.find( c ) == currCell.end() ) {
7332 if ( lastY != -1 ) 7355 if ( lastY != -1 )
7333 currCell.insert( c, lastCell ); 7356 currCell.insert( c, lastCell );
7334 else 7357 else
7335 return FALSE; 7358 return FALSE;
7336 } 7359 }
7337 7360
7338 QTextTableCell *cell = cells.at( *currCell.find( c ) ); 7361 QTextTableCell *cell = cells.at( *currCell.find( c ) );
7339 if ( !cell ) 7362 if ( !cell )
7340 return FALSE; 7363 return FALSE;
7341 doc = cell->richText(); 7364 doc = cell->richText();
7342 parag = doc->firstParagraph(); 7365 parag = doc->firstParagraph();
7343 idx = 0; 7366 idx = 0;
7344 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); 7367 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
7345 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; 7368 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
7346 return TRUE; 7369 return TRUE;
7347} 7370}
7348 7371
7349bool QTextTable::next( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy ) 7372bool QTextTable::next( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy )
7350{ 7373{
7351 int cc = -1; 7374 int cc = -1;
7352 if ( currCell.find( c ) != currCell.end() ) 7375 if ( currCell.find( c ) != currCell.end() )
7353 cc = *currCell.find( c ); 7376 cc = *currCell.find( c );
7354 if ( cc > (int)cells.count() - 1 || cc < 0 ) 7377 if ( cc > (int)cells.count() - 1 || cc < 0 )
7355 cc = -1; 7378 cc = -1;
7356 currCell.remove( c ); 7379 currCell.remove( c );
7357 currCell.insert( c, ++cc ); 7380 currCell.insert( c, ++cc );
7358 if ( cc >= (int)cells.count() ) { 7381 if ( cc >= (int)cells.count() ) {
7359 currCell.insert( c, 0 ); 7382 currCell.insert( c, 0 );
7360 QTextCustomItem::next( c, doc, parag, idx, ox, oy ); 7383 QTextCustomItem::next( c, doc, parag, idx, ox, oy );
7361 QTextTableCell *cell = cells.first(); 7384 QTextTableCell *cell = cells.first();
7362 if ( !cell ) 7385 if ( !cell )
7363 return FALSE; 7386 return FALSE;
7364 doc = cell->richText(); 7387 doc = cell->richText();
7365 idx = -1; 7388 idx = -1;
7366 return TRUE; 7389 return TRUE;
7367 } 7390 }
7368 7391
7369 if ( currCell.find( c ) == currCell.end() ) 7392 if ( currCell.find( c ) == currCell.end() )
7370 return FALSE; 7393 return FALSE;
7371 QTextTableCell *cell = cells.at( *currCell.find( c ) ); 7394 QTextTableCell *cell = cells.at( *currCell.find( c ) );
7372 if ( !cell ) 7395 if ( !cell )
7373 return FALSE; 7396 return FALSE;
7374 doc = cell->richText(); 7397 doc = cell->richText();
7375 parag = doc->firstParagraph(); 7398 parag = doc->firstParagraph();
7376 idx = 0; 7399 idx = 0;
7377 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); 7400 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
7378 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; 7401 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
7379 return TRUE; 7402 return TRUE;
7380} 7403}
7381 7404
7382bool QTextTable::prev( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy ) 7405bool QTextTable::prev( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy )
7383{ 7406{
7384 int cc = -1; 7407 int cc = -1;
7385 if ( currCell.find( c ) != currCell.end() ) 7408 if ( currCell.find( c ) != currCell.end() )
7386 cc = *currCell.find( c ); 7409 cc = *currCell.find( c );
7387 if ( cc > (int)cells.count() - 1 || cc < 0 ) 7410 if ( cc > (int)cells.count() - 1 || cc < 0 )
7388 cc = cells.count(); 7411 cc = cells.count();
7389 currCell.remove( c ); 7412 currCell.remove( c );
7390 currCell.insert( c, --cc ); 7413 currCell.insert( c, --cc );
7391 if ( cc < 0 ) { 7414 if ( cc < 0 ) {
7392 currCell.insert( c, 0 ); 7415 currCell.insert( c, 0 );
7393 QTextCustomItem::prev( c, doc, parag, idx, ox, oy ); 7416 QTextCustomItem::prev( c, doc, parag, idx, ox, oy );
7394 QTextTableCell *cell = cells.first(); 7417 QTextTableCell *cell = cells.first();
7395 if ( !cell ) 7418 if ( !cell )
7396 return FALSE; 7419 return FALSE;
7397 doc = cell->richText(); 7420 doc = cell->richText();
7398 idx = -1; 7421 idx = -1;
7399 return TRUE; 7422 return TRUE;
7400 } 7423 }
7401 7424
7402 if ( currCell.find( c ) == currCell.end() ) 7425 if ( currCell.find( c ) == currCell.end() )
7403 return FALSE; 7426 return FALSE;
7404 QTextTableCell *cell = cells.at( *currCell.find( c ) ); 7427 QTextTableCell *cell = cells.at( *currCell.find( c ) );
7405 if ( !cell ) 7428 if ( !cell )
7406 return FALSE; 7429 return FALSE;
7407 doc = cell->richText(); 7430 doc = cell->richText();
7408 parag = doc->lastParagraph(); 7431 parag = doc->lastParagraph();
7409 idx = parag->length() - 1; 7432 idx = parag->length() - 1;
7410 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); 7433 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
7411 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; 7434 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
7412 return TRUE; 7435 return TRUE;
7413} 7436}
7414 7437
7415bool QTextTable::down( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy ) 7438bool QTextTable::down( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy )
7416{ 7439{
7417 if ( currCell.find( c ) == currCell.end() ) 7440 if ( currCell.find( c ) == currCell.end() )
7418 return FALSE; 7441 return FALSE;
7419 QTextTableCell *cell = cells.at( *currCell.find( c ) ); 7442 QTextTableCell *cell = cells.at( *currCell.find( c ) );
7420 if ( cell->row_ == layout->numRows() - 1 ) { 7443 if ( cell->row_ == layout->numRows() - 1 ) {
7421 currCell.insert( c, 0 ); 7444 currCell.insert( c, 0 );
7422 QTextCustomItem::down( c, doc, parag, idx, ox, oy ); 7445 QTextCustomItem::down( c, doc, parag, idx, ox, oy );
7423 QTextTableCell *cell = cells.first(); 7446 QTextTableCell *cell = cells.first();
7424 if ( !cell ) 7447 if ( !cell )
7425 return FALSE; 7448 return FALSE;
7426 doc = cell->richText(); 7449 doc = cell->richText();
7427 idx = -1; 7450 idx = -1;
7428 return TRUE; 7451 return TRUE;
7429 } 7452 }
7430 7453
7431 int oldRow = cell->row_; 7454 int oldRow = cell->row_;
7432 int oldCol = cell->col_; 7455 int oldCol = cell->col_;
7433 if ( currCell.find( c ) == currCell.end() ) 7456 if ( currCell.find( c ) == currCell.end() )
7434 return FALSE; 7457 return FALSE;
7435 int cc = *currCell.find( c ); 7458 int cc = *currCell.find( c );
7436 for ( int i = cc; i < (int)cells.count(); ++i ) { 7459 for ( int i = cc; i < (int)cells.count(); ++i ) {
7437 cell = cells.at( i ); 7460 cell = cells.at( i );
7438 if ( cell->row_ > oldRow && cell->col_ == oldCol ) { 7461 if ( cell->row_ > oldRow && cell->col_ == oldCol ) {
7439 currCell.insert( c, i ); 7462 currCell.insert( c, i );
7440 break; 7463 break;
7441 } 7464 }
7442 } 7465 }
7443 doc = cell->richText(); 7466 doc = cell->richText();
7444 if ( !cell ) 7467 if ( !cell )
7445 return FALSE; 7468 return FALSE;
7446 parag = doc->firstParagraph(); 7469 parag = doc->firstParagraph();
7447 idx = 0; 7470 idx = 0;
7448 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); 7471 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
7449 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; 7472 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
7450 return TRUE; 7473 return TRUE;
7451} 7474}
7452 7475
7453bool QTextTable::up( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy ) 7476bool QTextTable::up( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy )
7454{ 7477{
7455 if ( currCell.find( c ) == currCell.end() ) 7478 if ( currCell.find( c ) == currCell.end() )
7456 return FALSE; 7479 return FALSE;
7457 QTextTableCell *cell = cells.at( *currCell.find( c ) ); 7480 QTextTableCell *cell = cells.at( *currCell.find( c ) );
7458 if ( cell->row_ == 0 ) { 7481 if ( cell->row_ == 0 ) {
7459 currCell.insert( c, 0 ); 7482 currCell.insert( c, 0 );
7460 QTextCustomItem::up( c, doc, parag, idx, ox, oy ); 7483 QTextCustomItem::up( c, doc, parag, idx, ox, oy );
7461 QTextTableCell *cell = cells.first(); 7484 QTextTableCell *cell = cells.first();
7462 if ( !cell ) 7485 if ( !cell )
7463 return FALSE; 7486 return FALSE;
7464 doc = cell->richText(); 7487 doc = cell->richText();
7465 idx = -1; 7488 idx = -1;
7466 return TRUE; 7489 return TRUE;
7467 } 7490 }
7468 7491
7469 int oldRow = cell->row_; 7492 int oldRow = cell->row_;
7470 int oldCol = cell->col_; 7493 int oldCol = cell->col_;
7471 if ( currCell.find( c ) == currCell.end() ) 7494 if ( currCell.find( c ) == currCell.end() )
7472 return FALSE; 7495 return FALSE;
7473 int cc = *currCell.find( c ); 7496 int cc = *currCell.find( c );
7474 for ( int i = cc; i >= 0; --i ) { 7497 for ( int i = cc; i >= 0; --i ) {
7475 cell = cells.at( i ); 7498 cell = cells.at( i );
7476 if ( cell->row_ < oldRow && cell->col_ == oldCol ) { 7499 if ( cell->row_ < oldRow && cell->col_ == oldCol ) {
7477 currCell.insert( c, i ); 7500 currCell.insert( c, i );
7478 break; 7501 break;
7479 } 7502 }
7480 } 7503 }
7481 doc = cell->richText(); 7504 doc = cell->richText();
7482 if ( !cell ) 7505 if ( !cell )
7483 return FALSE; 7506 return FALSE;
7484 parag = doc->lastParagraph(); 7507 parag = doc->lastParagraph();
7485 idx = parag->length() - 1; 7508 idx = parag->length() - 1;
7486 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); 7509 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
7487 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; 7510 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
7488 return TRUE; 7511 return TRUE;
7489} 7512}
7490 7513
7491QTextTableCell::QTextTableCell( QTextTable* table, 7514QTextTableCell::QTextTableCell( QTextTable* table,
7492 int row, int column, 7515 int row, int column,
7493 const QMap<QString, QString> &attr, 7516 const QMap<QString, QString> &attr,
7494 const QStyleSheetItem* /*style*/, // ### use them 7517 const QStyleSheetItem* /*style*/, // ### use them
7495 const QTextFormat& /*fmt*/, const QString& context, 7518 const QTextFormat& /*fmt*/, const QString& context,
7496 QMimeSourceFactory &factory, QStyleSheet *sheet, 7519 QMimeSourceFactory &factory, QStyleSheet *sheet,
7497 const QString& doc) 7520 const QString& doc)
7498{ 7521{
7499 cached_width = -1; 7522 cached_width = -1;
7500 cached_sizehint = -1; 7523 cached_sizehint = -1;
7501 7524
7502 maxw = QWIDGETSIZE_MAX; 7525 maxw = QWIDGETSIZE_MAX;
7503 minw = 0; 7526 minw = 0;
7504 7527
7505 parent = table; 7528 parent = table;
7506 row_ = row; 7529 row_ = row;
7507 col_ = column; 7530 col_ = column;
7508 stretch_ = 0; 7531 stretch_ = 0;
7509 richtext = new QTextDocument( table->parent ); 7532 richtext = new QTextDocument( table->parent );
7510 richtext->setTableCell( this ); 7533 richtext->setTableCell( this );
7511 QString a = *attr.find( "align" ); 7534 QString a = *attr.find( "align" );
7512 if ( !a.isEmpty() ) { 7535 if ( !a.isEmpty() ) {
7513 a = a.lower(); 7536 a = a.lower();
7514 if ( a == "left" ) 7537 if ( a == "left" )
7515 richtext->setAlignment( Qt::AlignLeft ); 7538 richtext->setAlignment( Qt::AlignLeft );
7516 else if ( a == "center" ) 7539 else if ( a == "center" )
7517 richtext->setAlignment( Qt::AlignHCenter ); 7540 richtext->setAlignment( Qt::AlignHCenter );
7518 else if ( a == "right" ) 7541 else if ( a == "right" )
7519 richtext->setAlignment( Qt::AlignRight ); 7542 richtext->setAlignment( Qt::AlignRight );
7520 } 7543 }
7521 align = 0; 7544 align = 0;
7522 QString va = *attr.find( "valign" ); 7545 QString va = *attr.find( "valign" );
7523 if ( !va.isEmpty() ) { 7546 if ( !va.isEmpty() ) {
7524 va = va.lower(); 7547 va = va.lower();
7525 if ( va == "center" ) 7548 if ( va == "center" )
7526 align |= Qt::AlignVCenter; 7549 align |= Qt::AlignVCenter;
7527 else if ( va == "bottom" ) 7550 else if ( va == "bottom" )
7528 align |= Qt::AlignBottom; 7551 align |= Qt::AlignBottom;
7529 } 7552 }
7530 richtext->setFormatter( table->parent->formatter() ); 7553 richtext->setFormatter( table->parent->formatter() );
7531 richtext->setUseFormatCollection( table->parent->useFormatCollection() ); 7554 richtext->setUseFormatCollection( table->parent->useFormatCollection() );
7532 richtext->setMimeSourceFactory( &factory ); 7555 richtext->setMimeSourceFactory( &factory );
7533 richtext->setStyleSheet( sheet ); 7556 richtext->setStyleSheet( sheet );
7534 richtext->setDefaultFormat( table->parent->formatCollection()->defaultFormat()->font(), 7557 richtext->setDefaultFormat( table->parent->formatCollection()->defaultFormat()->font(),
7535 table->parent->formatCollection()->defaultFormat()->color() ); 7558 table->parent->formatCollection()->defaultFormat()->color() );
7536 richtext->setRichText( doc, context ); 7559 richtext->setRichText( doc, context );
7537 rowspan_ = 1; 7560 rowspan_ = 1;
7538 colspan_ = 1; 7561 colspan_ = 1;
7539 if ( attr.contains("colspan") ) 7562 if ( attr.contains("colspan") )
7540 colspan_ = attr["colspan"].toInt(); 7563 colspan_ = attr["colspan"].toInt();
7541 if ( attr.contains("rowspan") ) 7564 if ( attr.contains("rowspan") )
7542 rowspan_ = attr["rowspan"].toInt(); 7565 rowspan_ = attr["rowspan"].toInt();
7543 7566
7544 background = 0; 7567 background = 0;
7545 if ( attr.contains("bgcolor") ) { 7568 if ( attr.contains("bgcolor") ) {
7546 background = new QBrush(QColor( attr["bgcolor"] )); 7569 background = new QBrush(QColor( attr["bgcolor"] ));
7547 } 7570 }
7548 7571
7549 7572
7550 hasFixedWidth = FALSE; 7573 hasFixedWidth = FALSE;
7551 if ( attr.contains("width") ) { 7574 if ( attr.contains("width") ) {
7552 bool b; 7575 bool b;
7553 QString s( attr["width"] ); 7576 QString s( attr["width"] );
7554 int w = s.toInt( &b ); 7577 int w = s.toInt( &b );
7555 if ( b ) { 7578 if ( b ) {
7556 maxw = w; 7579 maxw = w;
7557 minw = maxw; 7580 minw = maxw;
7558 hasFixedWidth = TRUE; 7581 hasFixedWidth = TRUE;
7559 } else { 7582 } else {
7560 s = s.stripWhiteSpace(); 7583 s = s.stripWhiteSpace();
7561 if ( s.length() > 1 && s[ (int)s.length()-1 ] == '%' ) 7584 if ( s.length() > 1 && s[ (int)s.length()-1 ] == '%' )
7562 stretch_ = s.left( s.length()-1).toInt(); 7585 stretch_ = s.left( s.length()-1).toInt();
7563 } 7586 }
7564 } 7587 }
7565 7588
7566 attributes = attr; 7589 attributes = attr;
7567 7590
7568 parent->addCell( this ); 7591 parent->addCell( this );
7569} 7592}
7570 7593
7571QTextTableCell::~QTextTableCell() 7594QTextTableCell::~QTextTableCell()
7572{ 7595{
7573 delete background; 7596 delete background;
7574 background = 0; 7597 background = 0;
7575 delete richtext; 7598 delete richtext;
7576 richtext = 0; 7599 richtext = 0;
7577} 7600}
7578 7601
7579QSize QTextTableCell::sizeHint() const 7602QSize QTextTableCell::sizeHint() const
7580{ 7603{
7581 int extra = 2 * ( parent->innerborder + parent->cellpadding + border_tolerance); 7604 int extra = 2 * ( parent->innerborder + parent->cellpadding + border_tolerance);
7582 int used = richtext->widthUsed() + extra; 7605 int used = richtext->widthUsed() + extra;
7583 7606
7584 if (stretch_ ) { 7607 if (stretch_ ) {
7585 int w = parent->width * stretch_ / 100 - 2*parent->cellspacing - 2*parent->cellpadding; 7608 int w = parent->width * stretch_ / 100 - 2*parent->cellspacing - 2*parent->cellpadding;
7586 return QSize( QMIN( w, maxw ), 0 ).expandedTo( minimumSize() ); 7609 return QSize( QMIN( w, maxw ), 0 ).expandedTo( minimumSize() );
7587 } 7610 }
7588 7611
7589 return QSize( used, 0 ).expandedTo( minimumSize() ); 7612 return QSize( used, 0 ).expandedTo( minimumSize() );
7590} 7613}
7591 7614
7592QSize QTextTableCell::minimumSize() const 7615QSize QTextTableCell::minimumSize() const
7593{ 7616{
7594 int extra = 2 * ( parent->innerborder + parent->cellpadding + border_tolerance); 7617 int extra = 2 * ( parent->innerborder + parent->cellpadding + border_tolerance);
7595 return QSize( QMAX( richtext->minimumWidth() + extra, minw), 0 ); 7618 return QSize( QMAX( richtext->minimumWidth() + extra, minw), 0 );
7596} 7619}
7597 7620
7598QSize QTextTableCell::maximumSize() const 7621QSize QTextTableCell::maximumSize() const
7599{ 7622{
7600 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ); 7623 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
7601} 7624}
7602 7625
7603QSizePolicy::ExpandData QTextTableCell::expanding() const 7626QSizePolicy::ExpandData QTextTableCell::expanding() const
7604{ 7627{
7605 return QSizePolicy::BothDirections; 7628 return QSizePolicy::BothDirections;
7606} 7629}
7607 7630
7608bool QTextTableCell::isEmpty() const 7631bool QTextTableCell::isEmpty() const
7609{ 7632{
7610 return FALSE; 7633 return FALSE;
7611} 7634}
7612void QTextTableCell::setGeometry( const QRect& r ) 7635void QTextTableCell::setGeometry( const QRect& r )
7613{ 7636{
7614 int extra = 2 * ( parent->innerborder + parent->cellpadding ); 7637 int extra = 2 * ( parent->innerborder + parent->cellpadding );
7615 if ( r.width() != cached_width ) 7638 if ( r.width() != cached_width )
7616 richtext->doLayout( QTextFormat::painter(), r.width() - extra ); 7639 richtext->doLayout( QTextFormat::painter(), r.width() - extra );
7617 cached_width = r.width(); 7640 cached_width = r.width();
7618 geom = r; 7641 geom = r;
7619} 7642}
7620 7643
7621QRect QTextTableCell::geometry() const 7644QRect QTextTableCell::geometry() const
7622{ 7645{
7623 return geom; 7646 return geom;
7624} 7647}
7625 7648
7626bool QTextTableCell::hasHeightForWidth() const 7649bool QTextTableCell::hasHeightForWidth() const
7627{ 7650{
7628 return TRUE; 7651 return TRUE;
7629} 7652}
7630 7653
7631int QTextTableCell::heightForWidth( int w ) const 7654int QTextTableCell::heightForWidth( int w ) const
7632{ 7655{
7633 int extra = 2 * ( parent->innerborder + parent->cellpadding ); 7656 int extra = 2 * ( parent->innerborder + parent->cellpadding );
7634 w = QMAX( minw, w ); 7657 w = QMAX( minw, w );
7635 7658
7636 if ( cached_width != w ) { 7659 if ( cached_width != w ) {
7637 QTextTableCell* that = (QTextTableCell*) this; 7660 QTextTableCell* that = (QTextTableCell*) this;
7638 that->richtext->doLayout( QTextFormat::painter(), w - extra ); 7661 that->richtext->doLayout( QTextFormat::painter(), w - extra );
7639 that->cached_width = w; 7662 that->cached_width = w;
7640 } 7663 }
7641 return richtext->height() + extra; 7664 return richtext->height() + extra;
7642} 7665}
7643 7666
7644void QTextTableCell::adjustToPainter( QPainter* p ) 7667void QTextTableCell::adjustToPainter( QPainter* p )
7645{ 7668{
7646 QTextParagraph *parag = richtext->firstParagraph(); 7669 QTextParagraph *parag = richtext->firstParagraph();
7647 while ( parag ) { 7670 while ( parag ) {
7648 parag->adjustToPainter( p ); 7671 parag->adjustToPainter( p );
7649 parag = parag->next(); 7672 parag = parag->next();
7650 } 7673 }
7651} 7674}
7652 7675
7653int QTextTableCell::horizontalAlignmentOffset() const 7676int QTextTableCell::horizontalAlignmentOffset() const
7654{ 7677{
7655 return parent->cellpadding; 7678 return parent->cellpadding;
7656} 7679}
7657 7680
7658int QTextTableCell::verticalAlignmentOffset() const 7681int QTextTableCell::verticalAlignmentOffset() const
7659{ 7682{
7660 if ( (align & Qt::AlignVCenter ) == Qt::AlignVCenter ) 7683 if ( (align & Qt::AlignVCenter ) == Qt::AlignVCenter )
7661 return ( geom.height() - richtext->height() ) / 2; 7684 return ( geom.height() - richtext->height() ) / 2;
7662 else if ( ( align & Qt::AlignBottom ) == Qt::AlignBottom ) 7685 else if ( ( align & Qt::AlignBottom ) == Qt::AlignBottom )
7663 return geom.height() - parent->cellpadding - richtext->height() ; 7686 return geom.height() - parent->cellpadding - richtext->height() ;
7664 return parent->cellpadding; 7687 return parent->cellpadding;
7665} 7688}
7666 7689
7667void QTextTableCell::draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool ) 7690void QTextTableCell::draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool )
7668{ 7691{
7669 if ( cached_width != geom.width() ) { 7692 if ( cached_width != geom.width() ) {
7670 int extra = 2 * ( parent->innerborder + parent->cellpadding ); 7693 int extra = 2 * ( parent->innerborder + parent->cellpadding );
7671 richtext->doLayout( p, geom.width() - extra ); 7694 richtext->doLayout( p, geom.width() - extra );
7672 cached_width = geom.width(); 7695 cached_width = geom.width();
7673 } 7696 }
7674 QColorGroup g( cg ); 7697 QColorGroup g( cg );
7675 if ( background ) 7698 if ( background )
7676 g.setBrush( QColorGroup::Base, *background ); 7699 g.setBrush( QColorGroup::Base, *background );
7677 else if ( richtext->paper() ) 7700 else if ( richtext->paper() )
7678 g.setBrush( QColorGroup::Base, *richtext->paper() ); 7701 g.setBrush( QColorGroup::Base, *richtext->paper() );
7679 7702
7680 p->save(); 7703 p->save();
7681 p->translate( x + geom.x(), y + geom.y() ); 7704 p->translate( x + geom.x(), y + geom.y() );
7682 if ( background ) 7705 if ( background )
7683 p->fillRect( 0, 0, geom.width(), geom.height(), *background ); 7706 p->fillRect( 0, 0, geom.width(), geom.height(), *background );
7684 else if ( richtext->paper() ) 7707 else if ( richtext->paper() )
7685 p->fillRect( 0, 0, geom.width(), geom.height(), *richtext->paper() ); 7708 p->fillRect( 0, 0, geom.width(), geom.height(), *richtext->paper() );
7686 7709
7687 p->translate( horizontalAlignmentOffset(), verticalAlignmentOffset() ); 7710 p->translate( horizontalAlignmentOffset(), verticalAlignmentOffset() );
7688 7711
7689 QRegion r; 7712 QRegion r;
7690 if ( cx >= 0 && cy >= 0 ) 7713 if ( cx >= 0 && cy >= 0 )
7691 richtext->draw( p, cx - ( x + horizontalAlignmentOffset() + geom.x() ), 7714 richtext->draw( p, cx - ( x + horizontalAlignmentOffset() + geom.x() ),
7692 cy - ( y + geom.y() + verticalAlignmentOffset() ), 7715 cy - ( y + geom.y() + verticalAlignmentOffset() ),
7693 cw, ch, g, FALSE, FALSE, 0 ); 7716 cw, ch, g, FALSE, FALSE, 0 );
7694 else 7717 else
7695 richtext->draw( p, -1, -1, -1, -1, g, FALSE, FALSE, 0 ); 7718 richtext->draw( p, -1, -1, -1, -1, g, FALSE, FALSE, 0 );
7696 7719
7697 p->restore(); 7720 p->restore();
7698} 7721}
7699 7722
7700QString QTextDocument::section( QString str, const QString &sep, int start, int end ) 7723QString QTextDocument::section( QString str, const QString &sep, int start, int end )
7701{ 7724{
7702 const QChar *uc = str.unicode(); 7725 const QChar *uc = str.unicode();
7703 if ( !uc ) 7726 if ( !uc )
7704 return QString(); 7727 return QString();
7705 QString _sep = sep; 7728 QString _sep = sep;
7706 const QChar *uc_sep = _sep.unicode(); 7729 const QChar *uc_sep = _sep.unicode();
7707 if(!uc_sep) 7730 if(!uc_sep)
7708 return QString(); 7731 return QString();
7709 bool match = FALSE, last_match = TRUE; 7732 bool match = FALSE, last_match = TRUE;
7710 7733
7711 //find start 7734 //find start
7712 int n = str.length(), sep_len = _sep.length(); 7735 int n = str.length(), sep_len = _sep.length();
7713 const QChar *begin = start < 0 ? uc + n : uc; 7736 const QChar *begin = start < 0 ? uc + n : uc;
7714 while(start) { 7737 while(start) {
7715 match = FALSE; 7738 match = FALSE;
7716 int c = 0; 7739 int c = 0;
7717 for(const QChar *tmp = start < 0 ? begin - sep_len : begin; 7740 for(const QChar *tmp = start < 0 ? begin - sep_len : begin;
7718 c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) { 7741 c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) {
7719 if( *tmp != *(uc_sep + c) ) 7742 if( *tmp != *(uc_sep + c) )
7720 break; 7743 break;
7721 if(c == sep_len - 1) { 7744 if(c == sep_len - 1) {
7722 match = TRUE; 7745 match = TRUE;
7723 break; 7746 break;
7724 } 7747 }
7725 } 7748 }
7726 last_match = match; 7749 last_match = match;
7727 7750
7728 if(start < 0) { 7751 if(start < 0) {
7729 if(match) { 7752 if(match) {
7730 begin -= sep_len; 7753 begin -= sep_len;
7731 if(!++start) 7754 if(!++start)
7732 break; 7755 break;
7733 } else { 7756 } else {
7734 if(start == -1 && begin == uc) 7757 if(start == -1 && begin == uc)
7735 break; 7758 break;
7736 begin--; 7759 begin--;
7737 } 7760 }
7738 } else { 7761 } else {
7739 if(match) { 7762 if(match) {
7740 if(!--start) 7763 if(!--start)
7741 break; 7764 break;
7742 begin += sep_len; 7765 begin += sep_len;
7743 } else { 7766 } else {
7744 if(start == 1 && begin == uc + n) 7767 if(start == 1 && begin == uc + n)
7745 break; 7768 break;
7746 begin++; 7769 begin++;
7747 } 7770 }
7748 } 7771 }
7749 if(begin > uc + n || begin < uc) 7772 if(begin > uc + n || begin < uc)
7750 return QString(); 7773 return QString();
7751 } 7774 }
7752 if(match) 7775 if(match)
7753 begin+=sep_len; 7776 begin+=sep_len;
7754 if(begin > uc + n || begin < uc) 7777 if(begin > uc + n || begin < uc)
7755 return QString(); 7778 return QString();
7756 7779
7757 //now find last 7780 //now find last
7758 match = FALSE; 7781 match = FALSE;
7759 const QChar *last = end < 0 ? uc + n : uc; 7782 const QChar *last = end < 0 ? uc + n : uc;
7760 if(end == -1) { 7783 if(end == -1) {
7761 int c = 0; 7784 int c = 0;
7762 for(const QChar *tmp = end < 0 ? last - sep_len : last; 7785 for(const QChar *tmp = end < 0 ? last - sep_len : last;
7763 c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) { 7786 c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) {
7764 if( *tmp != *(uc_sep + c) ) 7787 if( *tmp != *(uc_sep + c) )
7765 break; 7788 break;
7766 if(c == sep_len - 1) { 7789 if(c == sep_len - 1) {
7767 match = TRUE; 7790 match = TRUE;
7768 break; 7791 break;
7769 } 7792 }
7770 } 7793 }
7771 } else { 7794 } else {
7772 end++; 7795 end++;
7773 last_match = TRUE; 7796 last_match = TRUE;
7774 while(end) { 7797 while(end) {
7775 match = FALSE; 7798 match = FALSE;
7776 int c = 0; 7799 int c = 0;
7777 for(const QChar *tmp = end < 0 ? last - sep_len : last; 7800 for(const QChar *tmp = end < 0 ? last - sep_len : last;
7778 c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) { 7801 c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) {
7779 if( *tmp != *(uc_sep + c) ) 7802 if( *tmp != *(uc_sep + c) )
7780 break; 7803 break;
7781 if(c == sep_len - 1) { 7804 if(c == sep_len - 1) {
7782 match = TRUE; 7805 match = TRUE;
7783 break; 7806 break;
7784 } 7807 }
7785 } 7808 }
7786 last_match = match; 7809 last_match = match;
7787 7810
7788 if(end < 0) { 7811 if(end < 0) {
7789 if(match) { 7812 if(match) {
7790 if(!++end) 7813 if(!++end)
7791 break; 7814 break;
7792 last -= sep_len; 7815 last -= sep_len;
7793 } else { 7816 } else {
7794 last--; 7817 last--;
7795 } 7818 }
7796 } else { 7819 } else {
7797 if(match) { 7820 if(match) {
7798 last += sep_len; 7821 last += sep_len;
7799 if(!--end) 7822 if(!--end)
7800 break; 7823 break;
7801 } else { 7824 } else {
7802 last++; 7825 last++;
7803 } 7826 }
7804 } 7827 }
7805 if(last >= uc + n) { 7828 if(last >= uc + n) {
7806 last = uc + n; 7829 last = uc + n;
7807 break; 7830 break;
7808 } else if(last < uc) { 7831 } else if(last < uc) {
7809 return QString(); 7832 return QString();
7810 } 7833 }
7811 } 7834 }
7812 } 7835 }
7813 if(match) 7836 if(match)
7814 last -= sep_len; 7837 last -= sep_len;
7815 if(last < uc || last > uc + n || begin >= last) 7838 if(last < uc || last > uc + n || begin >= last)
7816 return QString(); 7839 return QString();
7817 7840
7818 //done 7841 //done
7819 return QString(begin, last - begin); 7842 return QString(begin, last - begin);
7820} 7843}
7821 7844
7822bool QTextDocument::endsWith( QString str, const QString &s) 7845bool QTextDocument::endsWith( QString str, const QString &s)
7823{ 7846{
7824 if ( str.isNull() ) 7847 if ( str.isNull() )
7825 return s.isNull(); 7848 return s.isNull();
7826 int pos = str.length() - s.length(); 7849 int pos = str.length() - s.length();
7827 if ( pos < 0 ) 7850 if ( pos < 0 )
7828 return FALSE; 7851 return FALSE;
7829 for ( uint i = 0; i < s.length(); i++ ) { 7852 for ( uint i = 0; i < s.length(); i++ ) {
7830 if ( str.unicode()[pos+i] != s[(int)i] ) 7853 if ( str.unicode()[pos+i] != s[(int)i] )
7831 return FALSE; 7854 return FALSE;
7832 } 7855 }
7833 return TRUE; 7856 return TRUE;
7834} 7857}
diff --git a/noncore/settings/networksettings2/opietooth2/OTSDPAttribute.cpp b/noncore/settings/networksettings2/opietooth2/OTSDPAttribute.cpp
index 9069c09..3fd877f 100644
--- a/noncore/settings/networksettings2/opietooth2/OTSDPAttribute.cpp
+++ b/noncore/settings/networksettings2/opietooth2/OTSDPAttribute.cpp
@@ -1,329 +1,332 @@
1//-*-c++-*- 1//-*-c++-*-
2/*************************************************************************** 2/***************************************************************************
3 * Copyright (C) 2003 by Fred Schaettgen * 3 * Copyright (C) 2003 by Fred Schaettgen *
4 * kdebluetooth@schaettgen.de * 4 * kdebluetooth@schaettgen.de *
5 * * 5 * *
6 * This program is free software; you can redistribute it and/or modify * 6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by * 7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or * 8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. * 9 * (at your option) any later version. *
10 ***************************************************************************/ 10 ***************************************************************************/
11 11
12#include <assert.h> 12#include <assert.h>
13#include <qregexp.h> 13#include <qregexp.h>
14#include <opie2/odebug.h> 14#include <opie2/odebug.h>
15 15
16#include <OTUUID.h> 16#include <OTUUID.h>
17#include <OTSDPAttribute.h> 17#include <OTSDPAttribute.h>
18 18
19using namespace Opietooth2; 19using namespace Opietooth2;
20 20
21OTSDPAttribute::OTSDPAttribute() { 21OTSDPAttribute::OTSDPAttribute() {
22 type = INVALID; 22 type = INVALID;
23 memset( &Value, 0, sizeof( Value ) ); 23 memset( &Value, 0, sizeof( Value ) );
24} 24}
25 25
26OTSDPAttribute::~OTSDPAttribute() { 26OTSDPAttribute::~OTSDPAttribute() {
27 if( type == INT ) { 27 if( type == INT ) {
28 delete Value.intVal; 28 delete Value.intVal;
29 } else if( type == UUID ) { 29 } else if( type == UUID ) {
30 delete Value.uuidVal; 30 delete Value.uuidVal;
31 } else if( type == UINT ) { 31 } else if( type == UINT ) {
32 delete Value.uintVal; 32 delete Value.uintVal;
33 } else if( type == STRING || 33 } else if( type == STRING ||
34 type == URL 34 type == URL
35 ) { 35 ) {
36 delete Value.stringVal; 36 delete Value.stringVal;
37 } else if( type == ALTERNATIVE || 37 } else if( type == ALTERNATIVE ||
38 type == SEQUENCE 38 type == SEQUENCE
39 ) { 39 ) {
40 delete Value.sequenceVal; 40 delete Value.sequenceVal;
41 } 41 }
42} 42}
43 43
44OTSDPAttribute::OTSDPAttribute( sdp_data_t * attrib ) { 44OTSDPAttribute::OTSDPAttribute( sdp_data_t * attrib ) {
45 setNil(); 45 setNil();
46 switch( attrib->dtd ) { 46 switch( attrib->dtd ) {
47 case SDP_DATA_NIL: // Nil type 47 case SDP_DATA_NIL: // Nil type
48 { setNil(); 48 { setNil();
49 break; 49 break;
50 } 50 }
51 case SDP_UINT8: // Unsigned integer 51 case SDP_UINT8: // Unsigned integer
52 setUInt(attrib->val.uint8); 52 setUInt(attrib->val.uint8);
53 break; 53 break;
54 case SDP_UINT16: // Unsigned integer 54 case SDP_UINT16: // Unsigned integer
55 setUInt(attrib->val.uint16); 55 setUInt(attrib->val.uint16);
56 break; 56 break;
57 case SDP_UINT32: // Unsigned integer 57 case SDP_UINT32: // Unsigned integer
58 setUInt(attrib->val.uint32); 58 setUInt(attrib->val.uint32);
59 break; 59 break;
60 case SDP_UINT64: // Unsigned integer 60 case SDP_UINT64: // Unsigned integer
61 setUInt(attrib->val.uint64); 61 setUInt(attrib->val.uint64);
62 break; 62 break;
63 case SDP_UINT128: // Unsigned integer 63 case SDP_UINT128: // Unsigned integer
64 // setUInt(attrib->val.uint16); 64 // setUInt(attrib->val.uint16);
65 assert(false); // BUG/TODO: uint128 integers not supported 65 assert(false); // BUG/TODO: uint128 integers not supported
66 break; 66 break;
67 case SDP_INT8: // Unsigned integer 67 case SDP_INT8: // Unsigned integer
68 setInt(attrib->val.int8); 68 setInt(attrib->val.int8);
69 break; 69 break;
70 case SDP_INT16: // Unsigned integer 70 case SDP_INT16: // Unsigned integer
71 setInt(attrib->val.int16); 71 setInt(attrib->val.int16);
72 break; 72 break;
73 case SDP_INT32: // Unsigned integer 73 case SDP_INT32: // Unsigned integer
74 setInt(attrib->val.int32); 74 setInt(attrib->val.int32);
75 break; 75 break;
76 case SDP_INT64: // Unsigned integer 76 case SDP_INT64: // Unsigned integer
77 setInt(attrib->val.int64); 77 setInt(attrib->val.int64);
78 break; 78 break;
79 case SDP_INT128: // Unsigned integer 79 case SDP_INT128: // Unsigned integer
80 // newAttr.setInt(attrib->val.uint16); 80 // newAttr.setInt(attrib->val.uint16);
81 assert(false); // BUG/TODO: uint128 integers not supported 81 assert(false); // BUG/TODO: uint128 integers not supported
82 break; 82 break;
83 case SDP_UUID16: 83 case SDP_UUID16:
84 { OTUUID id; 84 { OTUUID id;
85 ::uuid_t uuidVal = attrib->val.uuid; 85 ::uuid_t uuidVal = attrib->val.uuid;
86 id.setUUID32(uuidVal.value.uuid16); 86 id.setUUID32(uuidVal.value.uuid16);
87 setUUID(id ); 87 setUUID(id );
88 } 88 }
89 break; 89 break;
90 case SDP_UUID32: 90 case SDP_UUID32:
91 { OTUUID id; 91 { OTUUID id;
92 ::uuid_t uuidVal = attrib->val.uuid; 92 ::uuid_t uuidVal = attrib->val.uuid;
93 id.setUUID32(uuidVal.value.uuid32); 93 id.setUUID32(uuidVal.value.uuid32);
94 setUUID(id ); 94 setUUID(id );
95 } 95 }
96 break; 96 break;
97 case SDP_UUID128: 97 case SDP_UUID128:
98 { OTUUID id; 98 { OTUUID id;
99 ::uuid_t uuidVal = attrib->val.uuid; 99 ::uuid_t uuidVal = attrib->val.uuid;
100 uint64_t* v128; 100 uint64_t* v128;
101 v128 = reinterpret_cast<uint64_t*>(&(uuidVal.value.uuid128)); 101 v128 = reinterpret_cast<uint64_t*>(&(uuidVal.value.uuid128));
102 id.setUUID128(v128[0], v128[1]); 102 id.setUUID128(v128[0], v128[1]);
103 setUUID(id ); 103 setUUID(id );
104 } 104 }
105 break; 105 break;
106 case SDP_TEXT_STR_UNSPEC : 106 case SDP_TEXT_STR_UNSPEC :
107 case SDP_TEXT_STR8 : 107 case SDP_TEXT_STR8 :
108 case SDP_TEXT_STR16 : 108 case SDP_TEXT_STR16 :
109 case SDP_TEXT_STR32 : 109 case SDP_TEXT_STR32 :
110 setString( QString(attrib->val.str) ); 110 setString( QString(attrib->val.str) );
111 break; 111 break;
112 case SDP_URL_STR_UNSPEC : 112 case SDP_URL_STR_UNSPEC :
113 case SDP_URL_STR8 : 113 case SDP_URL_STR8 :
114 case SDP_URL_STR16 : 114 case SDP_URL_STR16 :
115 case SDP_URL_STR32 : 115 case SDP_URL_STR32 :
116 setURL( QString(attrib->val.str) ); 116 setURL( QString(attrib->val.str) );
117 break; 117 break;
118 case SDP_BOOL: 118 case SDP_BOOL:
119 setBool( attrib->val.int8 != 0); 119 setBool( attrib->val.int8 != 0);
120 break; 120 break;
121 case SDP_SEQ_UNSPEC : 121 case SDP_SEQ_UNSPEC :
122 case SDP_SEQ8 : 122 case SDP_SEQ8 :
123 case SDP_SEQ16 : 123 case SDP_SEQ16 :
124 case SDP_SEQ32 : 124 case SDP_SEQ32 :
125 case SDP_ALT_UNSPEC : 125 case SDP_ALT_UNSPEC :
126 case SDP_ALT8 : 126 case SDP_ALT8 :
127 case SDP_ALT16 : 127 case SDP_ALT16 :
128 case SDP_ALT32 : 128 case SDP_ALT32 :
129 { AttributeVector subAttribs; 129 { AttributeVector subAttribs;
130 OTSDPAttribute * Attr; 130 OTSDPAttribute * Attr;
131 sdp_data_t* subAttrib = attrib->val.dataseq; 131 sdp_data_t* subAttrib = attrib->val.dataseq;
132 132
133 for (; subAttrib; subAttrib = subAttrib->next) { 133 for (; subAttrib; subAttrib = subAttrib->next) {
134 134
135 Attr = new OTSDPAttribute(subAttrib); 135 Attr = new OTSDPAttribute(subAttrib);
136 subAttribs.resize( subAttribs.size() + 1 ); 136 subAttribs.resize( subAttribs.size() + 1 );
137 subAttribs.insert( subAttribs.size() - 1, Attr ); 137 subAttribs.insert( subAttribs.size() - 1, Attr );
138 } 138 }
139 139
140 if( attrib->dtd == SDP_ALT_UNSPEC || 140 if( attrib->dtd == SDP_ALT_UNSPEC ||
141 attrib->dtd == SDP_ALT8 || 141 attrib->dtd == SDP_ALT8 ||
142 attrib->dtd == SDP_ALT16 || 142 attrib->dtd == SDP_ALT16 ||
143 attrib->dtd == SDP_ALT32 ) { 143 attrib->dtd == SDP_ALT32 ) {
144 setAlternative(subAttribs); 144 setAlternative(subAttribs);
145 } else { 145 } else {
146 setSequence(subAttribs); 146 setSequence(subAttribs);
147 } 147 }
148 break; 148 break;
149 } 149 }
150 } // end case 150 } // end case
151} 151}
152 152
153QString OTSDPAttribute::toString( void ) { 153QString OTSDPAttribute::toString( void ) {
154 QString S; 154 QString S;
155 switch( type ) { 155 switch( type ) {
156 case INVALID : 156 case INVALID :
157 S = "invalid"; 157 S = "invalid";
158 break; 158 break;
159 case NIL : 159 case NIL :
160 S = "NIL"; 160 S = "NIL";
161 break; 161 break;
162 case UINT : 162 case UINT :
163 S = Value.uintVal->toString(); 163 S = Value.uintVal->toString();
164 break; 164 break;
165 case INT : 165 case INT :
166 S = Value.intVal->toString(); 166 S = Value.intVal->toString();
167 break; 167 break;
168 case UUID : 168 case UUID :
169 S = Value.uuidVal->toString(); 169 S = Value.uuidVal->toString();
170 break; 170 break;
171 case BOOLEAN : 171 case BOOLEAN :
172 S = (Value.boolVal) ? "true" : "false"; 172 S = (Value.boolVal) ? "true" : "false";
173 break; 173 break;
174 case STRING : 174 case STRING :
175 S = *(Value.stringVal); 175 S = *(Value.stringVal);
176 break; 176 break;
177 case URL : 177 case URL :
178 S = *(Value.stringVal); 178 S = *(Value.stringVal);
179 break; 179 break;
180 case SEQUENCE : 180 case SEQUENCE :
181 S.sprintf( "Sequence(%d)", Value.sequenceVal->count() ); 181 S.sprintf( "Sequence(%d)", Value.sequenceVal->count() );
182 break; 182 break;
183 case ALTERNATIVE : 183 case ALTERNATIVE :
184 S.sprintf( "Alternative(%d)", Value.sequenceVal->count() ); 184 S.sprintf( "Alternative(%d)", Value.sequenceVal->count() );
185 break; 185 break;
186 case UNKNOWN : 186 case UNKNOWN :
187 S = "unknown"; 187 S = "unknown";
188 break; 188 break;
189 } 189 }
190 return S; 190 return S;
191} 191}
192 192
193void OTSDPAttribute::setNil() { 193void OTSDPAttribute::setNil() {
194 type = NIL; 194 type = NIL;
195} 195}
196 196
197void OTSDPAttribute::setInt(const OTSDPAttribute::int128_t & val) { 197void OTSDPAttribute::setInt(const OTSDPAttribute::int128_t & val) {
198 type = INT; 198 type = INT;
199 Value.intVal = new int128_t( val ); 199 Value.intVal = new int128_t( val );
200} 200}
201 201
202void OTSDPAttribute::setUInt(const uint128_t & val) { 202void OTSDPAttribute::setUInt(const uint128_t & val) {
203 type = UINT; 203 type = UINT;
204 Value.uintVal = new uint128_t(val); 204 Value.uintVal = new uint128_t(val);
205} 205}
206 206
207void OTSDPAttribute::setUUID(const OTUUID & val) { 207void OTSDPAttribute::setUUID(const OTUUID & val) {
208 type = UUID; 208 type = UUID;
209 Value.uuidVal = new OTUUID( val ); 209 Value.uuidVal = new OTUUID( val );
210} 210}
211 211
212void OTSDPAttribute::setBool(bool val) { 212void OTSDPAttribute::setBool(bool val) {
213 type = BOOLEAN; 213 type = BOOLEAN;
214 Value.boolVal = val; 214 Value.boolVal = val;
215} 215}
216 216
217void OTSDPAttribute::setString( const QString & val) { 217void OTSDPAttribute::setString( const QString & val) {
218 type = STRING; 218 type = STRING;
219 Value.stringVal = new QString( val ); 219 Value.stringVal = new QString( val );
220} 220}
221 221
222void OTSDPAttribute::setURL( const QString & val) { 222void OTSDPAttribute::setURL( const QString & val) {
223 type = URL; 223 type = URL;
224 Value.stringVal = new QString(val); 224 Value.stringVal = new QString(val);
225} 225}
226 226
227void OTSDPAttribute::setSequence(const AttributeVector& val) { 227void OTSDPAttribute::setSequence(const AttributeVector& val) {
228 type = SEQUENCE; 228 type = SEQUENCE;
229 Value.sequenceVal = new AttributeVector(); 229 Value.sequenceVal = new AttributeVector();
230 Value.sequenceVal->setAutoDelete( TRUE ); 230 Value.sequenceVal->setAutoDelete( TRUE );
231 *Value.sequenceVal = val; 231 *Value.sequenceVal = val;
232} 232}
233 233
234void OTSDPAttribute::setAlternative(const AttributeVector& val) { 234void OTSDPAttribute::setAlternative(const AttributeVector& val) {
235 type = ALTERNATIVE; 235 type = ALTERNATIVE;
236 Value.sequenceVal = new AttributeVector(); 236 Value.sequenceVal = new AttributeVector();
237 Value.sequenceVal->setAutoDelete( TRUE ); 237 Value.sequenceVal->setAutoDelete( TRUE );
238 *Value.sequenceVal = val; 238 *Value.sequenceVal = val;
239} 239}
240 240
241QString OTSDPAttribute::getString() { 241QString OTSDPAttribute::getString() {
242 assert(type == STRING); 242 assert(type == STRING);
243 return *Value.stringVal; 243 return *Value.stringVal;
244} 244}
245 245
246QString OTSDPAttribute::getURL() { 246QString OTSDPAttribute::getURL() {
247 assert(type == URL); 247 assert(type == URL);
248 return *Value.stringVal; 248 return *Value.stringVal;
249} 249}
250 250
251const OTSDPAttribute::int128_t & OTSDPAttribute::getInt() { 251const OTSDPAttribute::int128_t & OTSDPAttribute::getInt() {
252 assert(type == INT); 252 assert(type == INT);
253 return *Value.intVal; 253 return *Value.intVal;
254} 254}
255 255
256 256
257const OTSDPAttribute::uint128_t & OTSDPAttribute::getUInt() { 257const OTSDPAttribute::uint128_t & OTSDPAttribute::getUInt() {
258 assert(type == UINT); 258 assert(type == UINT);
259 return *Value.uintVal; 259 return *Value.uintVal;
260} 260}
261 261
262const OTUUID & OTSDPAttribute::getUUID() { 262const OTUUID & OTSDPAttribute::getUUID() {
263 assert(type == UUID); 263 assert(type == UUID);
264 return *Value.uuidVal; 264 return *Value.uuidVal;
265} 265}
266 266
267bool OTSDPAttribute::getBool() { 267bool OTSDPAttribute::getBool() {
268 assert(type == BOOLEAN); 268 assert(type == BOOLEAN);
269 return Value.boolVal; 269 return Value.boolVal;
270} 270}
271 271
272AttributeVector * OTSDPAttribute::getSequence() { 272AttributeVector * OTSDPAttribute::getSequence() {
273 assert(type == SEQUENCE); 273 assert(type == SEQUENCE);
274 return Value.sequenceVal; 274 return Value.sequenceVal;
275} 275}
276 276
277AttributeVector * OTSDPAttribute::getAlternative() { 277AttributeVector * OTSDPAttribute::getAlternative() {
278 assert(type == ALTERNATIVE); 278 assert(type == ALTERNATIVE);
279 return Value.sequenceVal; 279 return Value.sequenceVal;
280} 280}
281 281
282UUIDVector OTSDPAttribute::getAllUUIDs() { 282UUIDVector OTSDPAttribute::getAllUUIDs() {
283 283
284 UUIDVector uuids; 284 UUIDVector uuids;
285 285
286 if (getType() == UUID) { 286 if (getType() == UUID) {
287 uuids.resize( uuids.size()+1 ); 287 uuids.resize( uuids.size()+1 );
288 uuids[uuids.size()-1] = getUUID(); 288 uuids[uuids.size()-1] = getUUID();
289 } else { 289 } else {
290 AttributeVector * subAttributes = 0 ; 290 AttributeVector * subAttributes = 0 ;
291 291
292 if (getType() == SEQUENCE) { 292 if (getType() == SEQUENCE) {
293 subAttributes = getSequence(); 293 subAttributes = getSequence();
294 } else if (getType() == ALTERNATIVE) { 294 } else if (getType() == ALTERNATIVE) {
295 subAttributes = getAlternative(); 295 subAttributes = getAlternative();
296 } 296 }
297 297
298 if (!subAttributes)
299 return 0;
300
298 int os; 301 int os;
299 for( unsigned int i = 0; i < subAttributes->count(); i++ ) { 302 for( unsigned int i = 0; i < subAttributes->count(); i++ ) {
300 UUIDVector subUUIDs = (*subAttributes)[i]->getAllUUIDs(); 303 UUIDVector subUUIDs = (*subAttributes)[i]->getAllUUIDs();
301 304
302 os = uuids.size(); 305 os = uuids.size();
303 uuids.resize( uuids.size()+subUUIDs.count() ); 306 uuids.resize( uuids.size()+subUUIDs.count() );
304 307
305 for( unsigned int k = 0; k < subUUIDs.count(); k++ ) { 308 for( unsigned int k = 0; k < subUUIDs.count(); k++ ) {
306 uuids[os + k] = subUUIDs[k]; 309 uuids[os + k] = subUUIDs[k];
307 } 310 }
308 } 311 }
309 } 312 }
310 return uuids; 313 return uuids;
311} 314}
312 315
313static char * Attr2String[] = { 316static char * Attr2String[] = {
314 "Invalid", 317 "Invalid",
315 "Nil", 318 "Nil",
316 "UInt", 319 "UInt",
317 "int", 320 "int",
318 "UUID", 321 "UUID",
319 "Boolean", 322 "Boolean",
320 "String", 323 "String",
321 "Sequence", 324 "Sequence",
322 "Alternative", 325 "Alternative",
323 "URL", 326 "URL",
324 "Unknown" 327 "Unknown"
325}; 328};
326 329
327const char * OTSDPAttribute::getTypeString() { 330const char * OTSDPAttribute::getTypeString() {
328 return Attr2String[type]; 331 return Attr2String[type];
329} 332}
diff --git a/noncore/settings/packagemanager/oipkgconfigdlg.cpp b/noncore/settings/packagemanager/oipkgconfigdlg.cpp
index d014378..78a18f7 100644
--- a/noncore/settings/packagemanager/oipkgconfigdlg.cpp
+++ b/noncore/settings/packagemanager/oipkgconfigdlg.cpp
@@ -1,716 +1,718 @@
1/* 1/*
2                 This file is part of the Opie Project 2                 This file is part of the Opie Project
3 3
4 Copyright (C)2004, 2005 Dan Williams <drw@handhelds.org> 4 Copyright (C)2004, 2005 Dan Williams <drw@handhelds.org>
5 =. 5 =.
6 .=l. 6 .=l.
7           .>+-= 7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can 8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under 9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public 10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software 11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License, 12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version. 13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_. 14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that 15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY; 16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17 : ..    .:,     . . . without even the implied warranty of 17 : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A 18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU 19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more 20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details. 21++=   -.     .`     .: details.
22:     =  ...= . :.=- 22:     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU 23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with 24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB. 25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation, 26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330, 27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA. 28 Boston, MA 02111-1307, USA.
29*/ 29*/
30 30
31#include "oipkgconfigdlg.h" 31#include "oipkgconfigdlg.h"
32 32
33#include <opie2/ofiledialog.h> 33#include <opie2/ofiledialog.h>
34#include <opie2/oresource.h> 34#include <opie2/oresource.h>
35 35
36#include <qpe/qpeapplication.h> 36#include <qpe/qpeapplication.h>
37 37
38#include <qcheckbox.h> 38#include <qcheckbox.h>
39#include <qcombobox.h> 39#include <qcombobox.h>
40#include <qgroupbox.h> 40#include <qgroupbox.h>
41#include <qlabel.h> 41#include <qlabel.h>
42#include <qlineedit.h> 42#include <qlineedit.h>
43#include <qlistbox.h> 43#include <qlistbox.h>
44#include <qpushbutton.h> 44#include <qpushbutton.h>
45#include <qscrollview.h> 45#include <qscrollview.h>
46#include <qwhatsthis.h> 46#include <qwhatsthis.h>
47 47
48OIpkgConfigDlg::OIpkgConfigDlg( OIpkg *ipkg, bool installOptions, QWidget *parent ) 48OIpkgConfigDlg::OIpkgConfigDlg( OIpkg *ipkg, bool installOptions, QWidget *parent )
49 : QDialog( parent, QString::null, true, WStyle_ContextHelp ) 49 : QDialog( parent, QString::null, true, WStyle_ContextHelp )
50 , m_ipkg( ipkg ) 50 , m_ipkg( ipkg )
51 , m_configs( 0l ) 51 , m_configs( 0l )
52 , m_installOptions( installOptions ) 52 , m_installOptions( installOptions )
53 , m_serverCurrent( -1 ) 53 , m_serverCurrent( -1 )
54 , m_destCurrent( -1 ) 54 , m_destCurrent( -1 )
55 , m_layout( this, 2, 4 ) 55 , m_layout( this, 2, 4 )
56 , m_tabWidget( this ) 56 , m_tabWidget( this )
57{ 57{
58 setCaption( tr( "Configuration" ) ); 58 setCaption( tr( "Configuration" ) );
59 59
60 // Initialize configuration widgets 60 // Initialize configuration widgets
61 if ( !installOptions ) 61 if ( !installOptions )
62 { 62 {
63 initServerWidget(); 63 initServerWidget();
64 initDestinationWidget(); 64 initDestinationWidget();
65 initProxyWidget(); 65 initProxyWidget();
66 } 66 }
67 initOptionsWidget(); 67 initOptionsWidget();
68 68
69 // Load configuration information 69 // Load configuration information
70 initData(); 70 initData();
71 71
72 // Setup tabs for all info 72 // Setup tabs for all info
73 m_layout.addWidget( &m_tabWidget ); 73 m_layout.addWidget( &m_tabWidget );
74 if ( !m_installOptions ) 74 if ( !m_installOptions )
75 { 75 {
76 m_tabWidget.addTab( m_serverWidget, "packagemanager/servertab", tr( "Servers" ) ); 76 m_tabWidget.addTab( m_serverWidget, "packagemanager/servertab", tr( "Servers" ) );
77 m_tabWidget.addTab( m_destWidget, "packagemanager/desttab", tr( "Destinations" ) ); 77 m_tabWidget.addTab( m_destWidget, "packagemanager/desttab", tr( "Destinations" ) );
78 m_tabWidget.addTab( m_proxyWidget, "packagemanager/proxytab", tr( "Proxies" ) ); 78 m_tabWidget.addTab( m_proxyWidget, "packagemanager/proxytab", tr( "Proxies" ) );
79 m_tabWidget.addTab( m_optionsWidget, "exec", tr( "Options" ) ); 79 m_tabWidget.addTab( m_optionsWidget, "exec", tr( "Options" ) );
80 m_tabWidget.setCurrentTab( tr( "Servers" ) ); 80 m_tabWidget.setCurrentTab( tr( "Servers" ) );
81 } 81 }
82 else 82 else
83 { 83 {
84 m_tabWidget.addTab( m_optionsWidget, "exec", tr( "Options" ) ); 84 m_tabWidget.addTab( m_optionsWidget, "exec", tr( "Options" ) );
85 } 85 }
86} 86}
87 87
88void OIpkgConfigDlg::accept() 88void OIpkgConfigDlg::accept()
89{ 89{
90 // Save server, destination and proxy configuration 90 // Save server, destination and proxy configuration
91 if ( !m_installOptions ) 91 if ( !m_installOptions )
92 { 92 {
93 // Update proxy information before saving settings 93 // Update proxy information before saving settings
94 OConfItem *confItem = m_ipkg->findConfItem( OConfItem::Option, "http_proxy" ); 94 OConfItem *confItem = m_ipkg->findConfItem( OConfItem::Option, "http_proxy" );
95 if ( confItem ) 95 if ( confItem )
96 { 96 {
97 confItem->setValue( m_proxyHttpServer->text() ); 97 confItem->setValue( m_proxyHttpServer->text() );
98 confItem->setActive( m_proxyHttpActive->isChecked() ); 98 confItem->setActive( m_proxyHttpActive->isChecked() );
99 } 99 }
100 else 100 else
101 m_configs->append( new OConfItem( OConfItem::Option, "http_proxy", 101 m_configs->append( new OConfItem( OConfItem::Option, "http_proxy",
102 m_proxyHttpServer->text(), QString::null, 102 m_proxyHttpServer->text(), QString::null,
103 m_proxyHttpActive->isChecked() ) ); 103 m_proxyHttpActive->isChecked() ) );
104 104
105 confItem = m_ipkg->findConfItem( OConfItem::Option, "ftp_proxy" ); 105 confItem = m_ipkg->findConfItem( OConfItem::Option, "ftp_proxy" );
106 if ( confItem ) 106 if ( confItem )
107 { 107 {
108 confItem->setValue( m_proxyFtpServer->text() ); 108 confItem->setValue( m_proxyFtpServer->text() );
109 confItem->setActive( m_proxyFtpActive->isChecked() ); 109 confItem->setActive( m_proxyFtpActive->isChecked() );
110 } 110 }
111 else 111 else
112 m_configs->append( new OConfItem( OConfItem::Option, "ftp_proxy", 112 m_configs->append( new OConfItem( OConfItem::Option, "ftp_proxy",
113 m_proxyFtpServer->text(), QString::null, 113 m_proxyFtpServer->text(), QString::null,
114 m_proxyFtpActive->isChecked() ) ); 114 m_proxyFtpActive->isChecked() ) );
115 115
116 confItem = m_ipkg->findConfItem( OConfItem::Option, "proxy_username" ); 116 confItem = m_ipkg->findConfItem( OConfItem::Option, "proxy_username" );
117 if ( confItem ) 117 if ( confItem )
118 confItem->setValue( m_proxyUsername->text() ); 118 confItem->setValue( m_proxyUsername->text() );
119 else 119 else
120 m_configs->append( new OConfItem( OConfItem::Option, "proxy_username", 120 m_configs->append( new OConfItem( OConfItem::Option, "proxy_username",
121 m_proxyUsername->text() ) ); 121 m_proxyUsername->text() ) );
122 122
123 confItem = m_ipkg->findConfItem( OConfItem::Option, "proxy_password" ); 123 confItem = m_ipkg->findConfItem( OConfItem::Option, "proxy_password" );
124 if ( confItem ) 124 if ( confItem )
125 confItem->setValue( m_proxyPassword->text() ); 125 confItem->setValue( m_proxyPassword->text() );
126 else 126 else
127 m_configs->append( new OConfItem( OConfItem::Option, "proxy_password", 127 m_configs->append( new OConfItem( OConfItem::Option, "proxy_password",
128 m_proxyPassword->text() ) ); 128 m_proxyPassword->text() ) );
129 129
130 QString listsDir = m_optSourceLists->text(); 130 QString listsDir = m_optSourceLists->text();
131 if ( listsDir == QString::null || listsDir == "" ) 131 if ( listsDir == QString::null || listsDir == "" )
132 listsDir = "/usr/lib/ipkg/lists"; // TODO - use proper libipkg define 132 listsDir = "/usr/lib/ipkg/lists"; // TODO - use proper libipkg define
133 confItem = m_ipkg->findConfItem( OConfItem::Other, "lists_dir" ); 133 confItem = m_ipkg->findConfItem( OConfItem::Other, "lists_dir" );
134 if ( confItem ) 134 if ( confItem )
135 confItem->setValue( listsDir ); 135 confItem->setValue( listsDir );
136 else 136 else
137 m_configs->append( new OConfItem( OConfItem::Other, "lists_dir", 137 m_configs->append( new OConfItem( OConfItem::Other, "lists_dir",
138 listsDir, "name" ) ); 138 listsDir, "name" ) );
139 139
140 m_ipkg->setConfigItems( m_configs ); 140 m_ipkg->setConfigItems( m_configs );
141 } 141 }
142 142
143 // Save options configuration 143 // Save options configuration
144 int options = 0; 144 int options = 0;
145 if ( m_optForceDepends->isChecked() ) 145 if ( m_optForceDepends->isChecked() )
146 options |= FORCE_DEPENDS; 146 options |= FORCE_DEPENDS;
147 if ( m_optForceReinstall->isChecked() ) 147 if ( m_optForceReinstall->isChecked() )
148 options |= FORCE_REINSTALL; 148 options |= FORCE_REINSTALL;
149 if ( m_optForceRemove->isChecked() ) 149 if ( m_optForceRemove->isChecked() )
150 options |= FORCE_REMOVE; 150 options |= FORCE_REMOVE;
151 if ( m_optForceOverwrite->isChecked() ) 151 if ( m_optForceOverwrite->isChecked() )
152 options |= FORCE_OVERWRITE; 152 options |= FORCE_OVERWRITE;
153 if ( m_optForceRecursive->isChecked() ) 153 if ( m_optForceRecursive->isChecked() )
154 options |= FORCE_RECURSIVE; 154 options |= FORCE_RECURSIVE;
155 if ( m_optVerboseWget->isChecked() ) 155 if ( m_optVerboseWget->isChecked() )
156 options |= FORCE_VERBOSE_WGET; 156 options |= FORCE_VERBOSE_WGET;
157 m_ipkg->setIpkgExecOptions( options ); 157 m_ipkg->setIpkgExecOptions( options );
158 m_ipkg->setIpkgExecVerbosity( m_optVerboseIpkg->currentItem() ); 158 m_ipkg->setIpkgExecVerbosity( m_optVerboseIpkg->currentItem() );
159 159
160 QDialog::accept(); 160 QDialog::accept();
161} 161}
162 162
163void OIpkgConfigDlg::reject() 163void OIpkgConfigDlg::reject()
164{ 164{
165 if ( m_configs ) 165 if ( m_configs )
166 delete m_configs; 166 delete m_configs;
167} 167}
168 168
169void OIpkgConfigDlg::initServerWidget() 169void OIpkgConfigDlg::initServerWidget()
170{ 170{
171 m_serverWidget = new QWidget( this ); 171 m_serverWidget = new QWidget( this );
172 172
173 // Initialize UI 173 // Initialize UI
174 QVBoxLayout *vb = new QVBoxLayout( m_serverWidget ); 174 QVBoxLayout *vb = new QVBoxLayout( m_serverWidget );
175 QScrollView *sv = new QScrollView( m_serverWidget ); 175 QScrollView *sv = new QScrollView( m_serverWidget );
176 vb->addWidget( sv, 0, 0 ); 176 vb->addWidget( sv, 0, 0 );
177 sv->setResizePolicy( QScrollView::AutoOneFit ); 177 sv->setResizePolicy( QScrollView::AutoOneFit );
178 sv->setFrameStyle( QFrame::NoFrame ); 178 sv->setFrameStyle( QFrame::NoFrame );
179 QWidget *container = new QWidget( sv->viewport() ); 179 QWidget *container = new QWidget( sv->viewport() );
180 sv->addChild( container ); 180 sv->addChild( container );
181 QGridLayout *layout = new QGridLayout( container, 2, 3, 2, 4 ); 181 QGridLayout *layout = new QGridLayout( container, 2, 3, 2, 4 );
182 182
183 m_serverList = new QListBox( container ); 183 m_serverList = new QListBox( container );
184 QWhatsThis::add( m_serverList, tr( "This is a list of all servers configured. Select one here to edit or delete, or add a new one below." ) ); 184 QWhatsThis::add( m_serverList, tr( "This is a list of all servers configured. Select one here to edit or delete, or add a new one below." ) );
185 m_serverList->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) ); 185 m_serverList->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
186 connect( m_serverList, SIGNAL(highlighted(int)), this, SLOT(slotServerSelected(int)) ); 186 connect( m_serverList, SIGNAL(highlighted(int)), this, SLOT(slotServerSelected(int)) );
187 layout->addMultiCellWidget( m_serverList, 0, 0, 0, 2 ); 187 layout->addMultiCellWidget( m_serverList, 0, 0, 0, 2 );
188 188
189 QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "new", Opie::Core::OResource::SmallIcon ), 189 QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "new", Opie::Core::OResource::SmallIcon ),
190 tr( "New" ), container ); 190 tr( "New" ), container );
191 btn->setMinimumHeight( AppLnk::smallIconSize()+4 ); 191 btn->setMinimumHeight( AppLnk::smallIconSize()+4 );
192 QWhatsThis::add( btn, tr( "Tap here to create a new entry. Fill in the fields below and then tap on Update." ) ); 192 QWhatsThis::add( btn, tr( "Tap here to create a new entry. Fill in the fields below and then tap on Update." ) );
193 connect( btn, SIGNAL(clicked()), this, SLOT(slotServerNew()) ); 193 connect( btn, SIGNAL(clicked()), this, SLOT(slotServerNew()) );
194 layout->addWidget( btn, 1, 0 ); 194 layout->addWidget( btn, 1, 0 );
195 195
196 m_serverEditBtn = new QPushButton( Opie::Core::OResource::loadPixmap( "edit", Opie::Core::OResource::SmallIcon ), 196 m_serverEditBtn = new QPushButton( Opie::Core::OResource::loadPixmap( "edit", Opie::Core::OResource::SmallIcon ),
197 tr( "Edit" ), container ); 197 tr( "Edit" ), container );
198 m_serverEditBtn->setMinimumHeight( AppLnk::smallIconSize()+4 ); 198 m_serverEditBtn->setMinimumHeight( AppLnk::smallIconSize()+4 );
199 m_serverEditBtn->setEnabled( false ); 199 m_serverEditBtn->setEnabled( false );
200 QWhatsThis::add( m_serverEditBtn, tr( "Tap here to edit the entry selected above." ) ); 200 QWhatsThis::add( m_serverEditBtn, tr( "Tap here to edit the entry selected above." ) );
201 connect( m_serverEditBtn, SIGNAL(clicked()), this, SLOT(slotServerEdit()) ); 201 connect( m_serverEditBtn, SIGNAL(clicked()), this, SLOT(slotServerEdit()) );
202 layout->addWidget( m_serverEditBtn, 1, 1 ); 202 layout->addWidget( m_serverEditBtn, 1, 1 );
203 203
204 m_serverDeleteBtn = new QPushButton( Opie::Core::OResource::loadPixmap( "trash", Opie::Core::OResource::SmallIcon ), 204 m_serverDeleteBtn = new QPushButton( Opie::Core::OResource::loadPixmap( "trash", Opie::Core::OResource::SmallIcon ),
205 tr( "Delete" ), container ); 205 tr( "Delete" ), container );
206 m_serverDeleteBtn->setMinimumHeight( AppLnk::smallIconSize()+4 ); 206 m_serverDeleteBtn->setMinimumHeight( AppLnk::smallIconSize()+4 );
207 m_serverDeleteBtn->setEnabled( false ); 207 m_serverDeleteBtn->setEnabled( false );
208 QWhatsThis::add( m_serverDeleteBtn, tr( "Tap here to delete the entry selected above." ) ); 208 QWhatsThis::add( m_serverDeleteBtn, tr( "Tap here to delete the entry selected above." ) );
209 connect( m_serverDeleteBtn, SIGNAL(clicked()), this, SLOT(slotServerDelete()) ); 209 connect( m_serverDeleteBtn, SIGNAL(clicked()), this, SLOT(slotServerDelete()) );
210 layout->addWidget( m_serverDeleteBtn, 1, 2 ); 210 layout->addWidget( m_serverDeleteBtn, 1, 2 );
211} 211}
212 212
213void OIpkgConfigDlg::initDestinationWidget() 213void OIpkgConfigDlg::initDestinationWidget()
214{ 214{
215 m_destWidget = new QWidget( this ); 215 m_destWidget = new QWidget( this );
216 216
217 // Initialize UI 217 // Initialize UI
218 QVBoxLayout *vb = new QVBoxLayout( m_destWidget ); 218 QVBoxLayout *vb = new QVBoxLayout( m_destWidget );
219 QScrollView *sv = new QScrollView( m_destWidget ); 219 QScrollView *sv = new QScrollView( m_destWidget );
220 vb->addWidget( sv, 0, 0 ); 220 vb->addWidget( sv, 0, 0 );
221 sv->setResizePolicy( QScrollView::AutoOneFit ); 221 sv->setResizePolicy( QScrollView::AutoOneFit );
222 sv->setFrameStyle( QFrame::NoFrame ); 222 sv->setFrameStyle( QFrame::NoFrame );
223 QWidget *container = new QWidget( sv->viewport() ); 223 QWidget *container = new QWidget( sv->viewport() );
224 sv->addChild( container ); 224 sv->addChild( container );
225 QGridLayout *layout = new QGridLayout( container, 2, 3, 2, 4 ); 225 QGridLayout *layout = new QGridLayout( container, 2, 3, 2, 4 );
226 226
227 m_destList = new QListBox( container ); 227 m_destList = new QListBox( container );
228 QWhatsThis::add( m_destList, tr( "This is a list of all destinations configured for this device. Select one here to edit or delete, or add a new one below." ) ); 228 QWhatsThis::add( m_destList, tr( "This is a list of all destinations configured for this device. Select one here to edit or delete, or add a new one below." ) );
229 m_destList->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) ); 229 m_destList->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
230 connect( m_destList, SIGNAL(highlighted(int)), this, SLOT(slotDestSelected(int)) ); 230 connect( m_destList, SIGNAL(highlighted(int)), this, SLOT(slotDestSelected(int)) );
231 layout->addMultiCellWidget( m_destList, 0, 0, 0, 2 ); 231 layout->addMultiCellWidget( m_destList, 0, 0, 0, 2 );
232 232
233 QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "new", Opie::Core::OResource::SmallIcon ), 233 QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "new", Opie::Core::OResource::SmallIcon ),
234 tr( "New" ), container ); 234 tr( "New" ), container );
235 btn->setMinimumHeight( AppLnk::smallIconSize()+4 ); 235 btn->setMinimumHeight( AppLnk::smallIconSize()+4 );
236 QWhatsThis::add( btn, tr( "Tap here to create a new entry. Fill in the fields below and then tap on Update." ) ); 236 QWhatsThis::add( btn, tr( "Tap here to create a new entry. Fill in the fields below and then tap on Update." ) );
237 connect( btn, SIGNAL(clicked()), this, SLOT(slotDestNew()) ); 237 connect( btn, SIGNAL(clicked()), this, SLOT(slotDestNew()) );
238 layout->addWidget( btn, 1, 0 ); 238 layout->addWidget( btn, 1, 0 );
239 239
240 m_destEditBtn = new QPushButton( Opie::Core::OResource::loadPixmap( "edit", Opie::Core::OResource::SmallIcon ), 240 m_destEditBtn = new QPushButton( Opie::Core::OResource::loadPixmap( "edit", Opie::Core::OResource::SmallIcon ),
241 tr( "Edit" ), container ); 241 tr( "Edit" ), container );
242 m_destEditBtn->setMinimumHeight( AppLnk::smallIconSize()+4 ); 242 m_destEditBtn->setMinimumHeight( AppLnk::smallIconSize()+4 );
243 m_destEditBtn->setEnabled( false ); 243 m_destEditBtn->setEnabled( false );
244 QWhatsThis::add( m_destEditBtn, tr( "Tap here to edit the entry selected above." ) ); 244 QWhatsThis::add( m_destEditBtn, tr( "Tap here to edit the entry selected above." ) );
245 connect( m_destEditBtn, SIGNAL(clicked()), this, SLOT(slotDestEdit()) ); 245 connect( m_destEditBtn, SIGNAL(clicked()), this, SLOT(slotDestEdit()) );
246 layout->addWidget( m_destEditBtn, 1, 1 ); 246 layout->addWidget( m_destEditBtn, 1, 1 );
247 247
248 m_destDeleteBtn = new QPushButton( Opie::Core::OResource::loadPixmap( "trash", Opie::Core::OResource::SmallIcon ), 248 m_destDeleteBtn = new QPushButton( Opie::Core::OResource::loadPixmap( "trash", Opie::Core::OResource::SmallIcon ),
249 tr( "Delete" ), container ); 249 tr( "Delete" ), container );
250 m_destDeleteBtn->setMinimumHeight( AppLnk::smallIconSize()+4 ); 250 m_destDeleteBtn->setMinimumHeight( AppLnk::smallIconSize()+4 );
251 m_destDeleteBtn->setEnabled( false ); 251 m_destDeleteBtn->setEnabled( false );
252 QWhatsThis::add( m_destDeleteBtn, tr( "Tap here to delete the entry selected above." ) ); 252 QWhatsThis::add( m_destDeleteBtn, tr( "Tap here to delete the entry selected above." ) );
253 connect( m_destDeleteBtn, SIGNAL(clicked()), this, SLOT(slotDestDelete()) ); 253 connect( m_destDeleteBtn, SIGNAL(clicked()), this, SLOT(slotDestDelete()) );
254 layout->addWidget( m_destDeleteBtn, 1, 2 ); 254 layout->addWidget( m_destDeleteBtn, 1, 2 );
255} 255}
256 256
257void OIpkgConfigDlg::initProxyWidget() 257void OIpkgConfigDlg::initProxyWidget()
258{ 258{
259 m_proxyWidget = new QWidget( this ); 259 m_proxyWidget = new QWidget( this );
260 260
261 // Initialize UI 261 // Initialize UI
262 QVBoxLayout *vb = new QVBoxLayout( m_proxyWidget ); 262 QVBoxLayout *vb = new QVBoxLayout( m_proxyWidget );
263 QScrollView *sv = new QScrollView( m_proxyWidget ); 263 QScrollView *sv = new QScrollView( m_proxyWidget );
264 vb->addWidget( sv, 0, 0 ); 264 vb->addWidget( sv, 0, 0 );
265 sv->setResizePolicy( QScrollView::AutoOneFit ); 265 sv->setResizePolicy( QScrollView::AutoOneFit );
266 sv->setFrameStyle( QFrame::NoFrame ); 266 sv->setFrameStyle( QFrame::NoFrame );
267 QWidget *container = new QWidget( sv->viewport() ); 267 QWidget *container = new QWidget( sv->viewport() );
268 sv->addChild( container ); 268 sv->addChild( container );
269 QGridLayout *layout = new QGridLayout( container, 4, 2, 2, 4 ); 269 QGridLayout *layout = new QGridLayout( container, 4, 2, 2, 4 );
270 270
271 // HTTP proxy server configuration 271 // HTTP proxy server configuration
272 QGroupBox *grpbox = new QGroupBox( 0, Qt::Vertical, tr( "HTTP Proxy" ), container ); 272 QGroupBox *grpbox = new QGroupBox( 0, Qt::Vertical, tr( "HTTP Proxy" ), container );
273 grpbox->layout()->setSpacing( 2 ); 273 grpbox->layout()->setSpacing( 2 );
274 grpbox->layout()->setMargin( 4 ); 274 grpbox->layout()->setMargin( 4 );
275 layout->addMultiCellWidget( grpbox, 0, 0, 0, 1 ); 275 layout->addMultiCellWidget( grpbox, 0, 0, 0, 1 );
276 QVBoxLayout *grplayout = new QVBoxLayout( grpbox->layout() ); 276 QVBoxLayout *grplayout = new QVBoxLayout( grpbox->layout() );
277 m_proxyHttpServer = new QLineEdit( grpbox ); 277 m_proxyHttpServer = new QLineEdit( grpbox );
278 QWhatsThis::add( m_proxyHttpServer, tr( "Enter the URL address of the HTTP proxy server here." ) ); 278 QWhatsThis::add( m_proxyHttpServer, tr( "Enter the URL address of the HTTP proxy server here." ) );
279 grplayout->addWidget( m_proxyHttpServer ); 279 grplayout->addWidget( m_proxyHttpServer );
280 m_proxyHttpActive = new QCheckBox( tr( "Enabled" ), grpbox ); 280 m_proxyHttpActive = new QCheckBox( tr( "Enabled" ), grpbox );
281 QWhatsThis::add( m_proxyHttpActive, tr( "Tap here to enable or disable the HTTP proxy server." ) ); 281 QWhatsThis::add( m_proxyHttpActive, tr( "Tap here to enable or disable the HTTP proxy server." ) );
282 grplayout->addWidget( m_proxyHttpActive ); 282 grplayout->addWidget( m_proxyHttpActive );
283 283
284 // FTP proxy server configuration 284 // FTP proxy server configuration
285 grpbox = new QGroupBox( 0, Qt::Vertical, tr( "FTP Proxy" ), container ); 285 grpbox = new QGroupBox( 0, Qt::Vertical, tr( "FTP Proxy" ), container );
286 grpbox->layout()->setSpacing( 2 ); 286 grpbox->layout()->setSpacing( 2 );
287 grpbox->layout()->setMargin( 4 ); 287 grpbox->layout()->setMargin( 4 );
288 layout->addMultiCellWidget( grpbox, 1, 1, 0, 1 ); 288 layout->addMultiCellWidget( grpbox, 1, 1, 0, 1 );
289 grplayout = new QVBoxLayout( grpbox->layout() ); 289 grplayout = new QVBoxLayout( grpbox->layout() );
290 m_proxyFtpServer = new QLineEdit( grpbox ); 290 m_proxyFtpServer = new QLineEdit( grpbox );
291 QWhatsThis::add( m_proxyFtpServer, tr( "Enter the URL address of the FTP proxy server here." ) ); 291 QWhatsThis::add( m_proxyFtpServer, tr( "Enter the URL address of the FTP proxy server here." ) );
292 grplayout->addWidget( m_proxyFtpServer ); 292 grplayout->addWidget( m_proxyFtpServer );
293 m_proxyFtpActive = new QCheckBox( tr( "Enabled" ), grpbox ); 293 m_proxyFtpActive = new QCheckBox( tr( "Enabled" ), grpbox );
294 QWhatsThis::add( m_proxyFtpActive, tr( "Tap here to enable or disable the FTP proxy server." ) ); 294 QWhatsThis::add( m_proxyFtpActive, tr( "Tap here to enable or disable the FTP proxy server." ) );
295 grplayout->addWidget( m_proxyFtpActive ); 295 grplayout->addWidget( m_proxyFtpActive );
296 296
297 // Proxy server username and password configuration 297 // Proxy server username and password configuration
298 QLabel *label = new QLabel( tr( "Username:" ), container ); 298 QLabel *label = new QLabel( tr( "Username:" ), container );
299 QWhatsThis::add( label, tr( "Enter the username for the proxy servers here." ) ); 299 QWhatsThis::add( label, tr( "Enter the username for the proxy servers here." ) );
300 layout->addWidget( label, 2, 0 ); 300 layout->addWidget( label, 2, 0 );
301 m_proxyUsername = new QLineEdit( container ); 301 m_proxyUsername = new QLineEdit( container );
302 QWhatsThis::add( m_proxyUsername, tr( "Enter the username for the proxy servers here." ) ); 302 QWhatsThis::add( m_proxyUsername, tr( "Enter the username for the proxy servers here." ) );
303 layout->addWidget( m_proxyUsername, 2, 1 ); 303 layout->addWidget( m_proxyUsername, 2, 1 );
304 304
305 label = new QLabel( tr( "Password:" ), container ); 305 label = new QLabel( tr( "Password:" ), container );
306 QWhatsThis::add( label, tr( "Enter the password for the proxy servers here." ) ); 306 QWhatsThis::add( label, tr( "Enter the password for the proxy servers here." ) );
307 layout->addWidget( label, 3, 0 ); 307 layout->addWidget( label, 3, 0 );
308 m_proxyPassword = new QLineEdit( container ); 308 m_proxyPassword = new QLineEdit( container );
309 QWhatsThis::add( m_proxyPassword, tr( "Enter the password for the proxy servers here." ) ); 309 QWhatsThis::add( m_proxyPassword, tr( "Enter the password for the proxy servers here." ) );
310 layout->addWidget( m_proxyPassword, 3, 1 ); 310 layout->addWidget( m_proxyPassword, 3, 1 );
311} 311}
312 312
313void OIpkgConfigDlg::initOptionsWidget() 313void OIpkgConfigDlg::initOptionsWidget()
314{ 314{
315 m_optionsWidget = new QWidget( this ); 315 m_optionsWidget = new QWidget( this );
316 316
317 // Initialize UI 317 // Initialize UI
318 QVBoxLayout *vb = new QVBoxLayout( m_optionsWidget ); 318 QVBoxLayout *vb = new QVBoxLayout( m_optionsWidget );
319 QScrollView *sv = new QScrollView( m_optionsWidget ); 319 QScrollView *sv = new QScrollView( m_optionsWidget );
320 vb->addWidget( sv, 0, 0 ); 320 vb->addWidget( sv, 0, 0 );
321 sv->setResizePolicy( QScrollView::AutoOneFit ); 321 sv->setResizePolicy( QScrollView::AutoOneFit );
322 sv->setFrameStyle( QFrame::NoFrame ); 322 sv->setFrameStyle( QFrame::NoFrame );
323 QWidget *container = new QWidget( sv->viewport() ); 323 QWidget *container = new QWidget( sv->viewport() );
324 sv->addChild( container ); 324 sv->addChild( container );
325 QGridLayout *layout = new QGridLayout( container, 8, 2, 2, 4 ); 325 QGridLayout *layout = new QGridLayout( container, 8, 2, 2, 4 );
326 326
327 m_optForceDepends = new QCheckBox( tr( "Force Depends" ), container ); 327 m_optForceDepends = new QCheckBox( tr( "Force Depends" ), container );
328 QWhatsThis::add( m_optForceDepends, tr( "Tap here to enable or disable the '-force-depends' option for Ipkg." ) ); 328 QWhatsThis::add( m_optForceDepends, tr( "Tap here to enable or disable the '-force-depends' option for Ipkg." ) );
329 layout->addMultiCellWidget( m_optForceDepends, 0, 0, 0, 1 ); 329 layout->addMultiCellWidget( m_optForceDepends, 0, 0, 0, 1 );
330 330
331 m_optForceReinstall = new QCheckBox( tr( "Force Reinstall" ), container ); 331 m_optForceReinstall = new QCheckBox( tr( "Force Reinstall" ), container );
332 QWhatsThis::add( m_optForceReinstall, tr( "Tap here to enable or disable the '-force-reinstall' option for Ipkg." ) ); 332 QWhatsThis::add( m_optForceReinstall, tr( "Tap here to enable or disable the '-force-reinstall' option for Ipkg." ) );
333 layout->addMultiCellWidget( m_optForceReinstall, 1, 1, 0, 1 ); 333 layout->addMultiCellWidget( m_optForceReinstall, 1, 1, 0, 1 );
334 334
335 m_optForceRemove = new QCheckBox( tr( "Force Remove" ), container ); 335 m_optForceRemove = new QCheckBox( tr( "Force Remove" ), container );
336 QWhatsThis::add( m_optForceRemove, tr( "Tap here to enable or disable the '-force-removal-of-dependent-packages' option for Ipkg." ) ); 336 QWhatsThis::add( m_optForceRemove, tr( "Tap here to enable or disable the '-force-removal-of-dependent-packages' option for Ipkg." ) );
337 layout->addMultiCellWidget( m_optForceRemove, 2, 2, 0, 1 ); 337 layout->addMultiCellWidget( m_optForceRemove, 2, 2, 0, 1 );
338 338
339 m_optForceOverwrite = new QCheckBox( tr( "Force Overwrite" ), container ); 339 m_optForceOverwrite = new QCheckBox( tr( "Force Overwrite" ), container );
340 QWhatsThis::add( m_optForceOverwrite, tr( "Tap here to enable or disable the '-force-overwrite' option for Ipkg." ) ); 340 QWhatsThis::add( m_optForceOverwrite, tr( "Tap here to enable or disable the '-force-overwrite' option for Ipkg." ) );
341 layout->addMultiCellWidget( m_optForceOverwrite, 3, 3, 0, 1 ); 341 layout->addMultiCellWidget( m_optForceOverwrite, 3, 3, 0, 1 );
342 342
343 m_optForceRecursive = new QCheckBox( tr( "Force Recursive" ), container ); 343 m_optForceRecursive = new QCheckBox( tr( "Force Recursive" ), container );
344 QWhatsThis::add( m_optForceRecursive, tr( "Tap here to enable or disable the '-recursive' option for Ipkg." ) ); 344 QWhatsThis::add( m_optForceRecursive, tr( "Tap here to enable or disable the '-recursive' option for Ipkg." ) );
345 layout->addMultiCellWidget( m_optForceRecursive, 4, 4, 0, 1 ); 345 layout->addMultiCellWidget( m_optForceRecursive, 4, 4, 0, 1 );
346 346
347 m_optVerboseWget = new QCheckBox( tr( "Verbose fetch" ), container ); 347 m_optVerboseWget = new QCheckBox( tr( "Verbose fetch" ), container );
348 QWhatsThis::add( m_optVerboseWget, tr( "Tap here to enable or disable the '-verbose_wget' option for Ipkg." ) ); 348 QWhatsThis::add( m_optVerboseWget, tr( "Tap here to enable or disable the '-verbose_wget' option for Ipkg." ) );
349 layout->addMultiCellWidget( m_optVerboseWget, 5, 5, 0, 1 ); 349 layout->addMultiCellWidget( m_optVerboseWget, 5, 5, 0, 1 );
350 350
351 QLabel *l = new QLabel( tr( "Information level:" ), container ); 351 QLabel *l = new QLabel( tr( "Information level:" ), container );
352 QWhatsThis::add( l, tr( "Select information level for Ipkg." ) ); 352 QWhatsThis::add( l, tr( "Select information level for Ipkg." ) );
353 layout->addMultiCellWidget( l, 6, 6, 0, 1 ); 353 layout->addMultiCellWidget( l, 6, 6, 0, 1 );
354 354
355 m_optVerboseIpkg = new QComboBox( container ); 355 m_optVerboseIpkg = new QComboBox( container );
356 QWhatsThis::add( m_optVerboseIpkg, tr( "Select information level for Ipkg." ) ); 356 QWhatsThis::add( m_optVerboseIpkg, tr( "Select information level for Ipkg." ) );
357 m_optVerboseIpkg->insertItem( tr( "Errors only" ) ); 357 m_optVerboseIpkg->insertItem( tr( "Errors only" ) );
358 m_optVerboseIpkg->insertItem( tr( "Normal messages" ) ); 358 m_optVerboseIpkg->insertItem( tr( "Normal messages" ) );
359 m_optVerboseIpkg->insertItem( tr( "Informative messages" ) ); 359 m_optVerboseIpkg->insertItem( tr( "Informative messages" ) );
360 m_optVerboseIpkg->insertItem( tr( "Troubleshooting output" ) ); 360 m_optVerboseIpkg->insertItem( tr( "Troubleshooting output" ) );
361 layout->addMultiCellWidget( m_optVerboseIpkg, 7, 7, 0, 1 ); 361 layout->addMultiCellWidget( m_optVerboseIpkg, 7, 7, 0, 1 );
362 362
363 l = new QLabel( tr( "Package source lists directory:" ), container ); 363 l = new QLabel( tr( "Package source lists directory:" ), container );
364 QWhatsThis::add( l, tr( "Enter the directory where package source feed information is stored." ) ); 364 QWhatsThis::add( l, tr( "Enter the directory where package source feed information is stored." ) );
365 layout->addMultiCellWidget( l, 8, 8, 0, 1 ); 365 layout->addMultiCellWidget( l, 8, 8, 0, 1 );
366 366
367 m_optSourceLists = new QLineEdit( container ); 367 m_optSourceLists = new QLineEdit( container );
368 QWhatsThis::add( m_optSourceLists, tr( "Enter the directory where package source feed information is stored." ) ); 368 QWhatsThis::add( m_optSourceLists, tr( "Enter the directory where package source feed information is stored." ) );
369 layout->addWidget( m_optSourceLists, 9, 0 ); 369 layout->addWidget( m_optSourceLists, 9, 0 );
370 370
371 QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "folder", Opie::Core::OResource::SmallIcon ), 371 QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "folder", Opie::Core::OResource::SmallIcon ),
372 QString::null, container ); 372 QString::null, container );
373 btn->setMinimumHeight( AppLnk::smallIconSize()+4 ); 373 btn->setMinimumHeight( AppLnk::smallIconSize()+4 );
374 btn->setMaximumWidth( btn->height() ); 374 btn->setMaximumWidth( btn->height() );
375 QWhatsThis::add( btn, tr( "Tap here to select the directory where package source feed information is stored." ) ); 375 QWhatsThis::add( btn, tr( "Tap here to select the directory where package source feed information is stored." ) );
376 connect( btn, SIGNAL(clicked()), this, SLOT(slotOptSelectSourceListsPath()) ); 376 connect( btn, SIGNAL(clicked()), this, SLOT(slotOptSelectSourceListsPath()) );
377 layout->addWidget( btn, 9, 1 ); 377 layout->addWidget( btn, 9, 1 );
378 378
379 layout->addItem( new QSpacerItem( 1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding ) ); 379 layout->addItem( new QSpacerItem( 1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding ) );
380} 380}
381 381
382void OIpkgConfigDlg::initData() 382void OIpkgConfigDlg::initData()
383{ 383{
384 // Read ipkg configuration (server/destination/proxy) information 384 // Read ipkg configuration (server/destination/proxy) information
385 if ( m_ipkg && !m_installOptions ) 385 if ( m_ipkg && !m_installOptions )
386 { 386 {
387 m_configs = m_ipkg->configItems(); 387 m_configs = m_ipkg->configItems();
388 if ( m_configs ) 388 if ( m_configs )
389 { 389 {
390 for ( OConfItemListIterator configIt( *m_configs ); configIt.current(); ++configIt ) 390 for ( OConfItemListIterator configIt( *m_configs ); configIt.current(); ++configIt )
391 { 391 {
392 OConfItem *config = configIt.current(); 392 OConfItem *config = configIt.current();
393 393
394 // Add configuration item to the appropriate dialog controls 394 // Add configuration item to the appropriate dialog controls
395 if ( config ) 395 if ( config )
396 { 396 {
397 switch ( config->type() ) 397 switch ( config->type() )
398 { 398 {
399 case OConfItem::Source : m_serverList->insertItem( config->name() ); break; 399 case OConfItem::Source : m_serverList->insertItem( config->name() ); break;
400 case OConfItem::Destination : m_destList->insertItem( config->name() ); break; 400 case OConfItem::Destination : m_destList->insertItem( config->name() ); break;
401 case OConfItem::Option : 401 case OConfItem::Option :
402 { 402 {
403 if ( config->name() == "http_proxy" ) 403 if ( config->name() == "http_proxy" )
404 { 404 {
405 m_proxyHttpServer->setText( config->value() ); 405 m_proxyHttpServer->setText( config->value() );
406 m_proxyHttpActive->setChecked( config->active() ); 406 m_proxyHttpActive->setChecked( config->active() );
407 } 407 }
408 else if ( config->name() == "ftp_proxy" ) 408 else if ( config->name() == "ftp_proxy" )
409 { 409 {
410 m_proxyFtpServer->setText( config->value() ); 410 m_proxyFtpServer->setText( config->value() );
411 m_proxyFtpActive->setChecked( config->active() ); 411 m_proxyFtpActive->setChecked( config->active() );
412 } 412 }
413 else if ( config->name() == "proxy_username" ) 413 else if ( config->name() == "proxy_username" )
414 { 414 {
415 m_proxyUsername->setText( config->value() ); 415 m_proxyUsername->setText( config->value() );
416 } 416 }
417 else if ( config->name() == "proxy_password" ) 417 else if ( config->name() == "proxy_password" )
418 { 418 {
419 m_proxyPassword->setText( config->value() ); 419 m_proxyPassword->setText( config->value() );
420 } 420 }
421 } 421 }
422 break; 422 break;
423 case OConfItem::Other : 423 case OConfItem::Other :
424 { 424 {
425 if ( config->name() == "lists_dir" ) 425 if ( config->name() == "lists_dir" )
426 m_optSourceLists->setText( config->value() ); 426 m_optSourceLists->setText( config->value() );
427 else // TODO - use proper libipkg define 427 else // TODO - use proper libipkg define
428 m_optSourceLists->setText( "/usr/lib/ipkg/lists" ); 428 m_optSourceLists->setText( "/usr/lib/ipkg/lists" );
429 } 429 }
430 break; 430 break;
431 default : break; 431 default : break;
432 }; 432 };
433 } 433 }
434 } 434 }
435 } 435 }
436 } 436 }
437 437
438 // Get Ipkg execution options 438 // Get Ipkg execution options
439 int options = m_ipkg->ipkgExecOptions(); 439 int options = 0;
440 if ( m_ipkg )
441 options = m_ipkg->ipkgExecOptions();
440 if ( options & FORCE_DEPENDS ) 442 if ( options & FORCE_DEPENDS )
441 m_optForceDepends->setChecked( true ); 443 m_optForceDepends->setChecked( true );
442 if ( options & FORCE_REINSTALL ) 444 if ( options & FORCE_REINSTALL )
443 m_optForceReinstall->setChecked( true ); 445 m_optForceReinstall->setChecked( true );
444 if ( options & FORCE_REMOVE ) 446 if ( options & FORCE_REMOVE )
445 m_optForceRemove->setChecked( true ); 447 m_optForceRemove->setChecked( true );
446 if ( options & FORCE_OVERWRITE ) 448 if ( options & FORCE_OVERWRITE )
447 m_optForceOverwrite->setChecked( true ); 449 m_optForceOverwrite->setChecked( true );
448 if ( options & FORCE_RECURSIVE ) 450 if ( options & FORCE_RECURSIVE )
449 m_optForceRecursive->setChecked( true ); 451 m_optForceRecursive->setChecked( true );
450 if ( options & FORCE_VERBOSE_WGET ) 452 if ( options & FORCE_VERBOSE_WGET )
451 m_optVerboseWget->setChecked( true ); 453 m_optVerboseWget->setChecked( true );
452 454
453 m_optVerboseIpkg->setCurrentItem( m_ipkg->ipkgExecVerbosity() ); 455 m_optVerboseIpkg->setCurrentItem( ( m_ipkg ? m_ipkg->ipkgExecVerbosity() : 0 ) );
454} 456}
455 457
456void OIpkgConfigDlg::slotServerSelected( int index ) 458void OIpkgConfigDlg::slotServerSelected( int index )
457{ 459{
458 m_serverCurrent = index; 460 m_serverCurrent = index;
459 461
460 // Enable Edit and Delete buttons 462 // Enable Edit and Delete buttons
461 m_serverEditBtn->setEnabled( true ); 463 m_serverEditBtn->setEnabled( true );
462 m_serverDeleteBtn->setEnabled( true ); 464 m_serverDeleteBtn->setEnabled( true );
463} 465}
464 466
465void OIpkgConfigDlg::slotServerNew() 467void OIpkgConfigDlg::slotServerNew()
466{ 468{
467 OConfItem *server = new OConfItem( OConfItem::Source ); 469 OConfItem *server = new OConfItem( OConfItem::Source );
468 470
469 OIpkgServerDlg dlg( server, this ); 471 OIpkgServerDlg dlg( server, this );
470 if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted ) 472 if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted )
471 { 473 {
472 // Add to configuration option list 474 // Add to configuration option list
473 m_configs->append( server ); 475 m_configs->append( server );
474 m_configs->sort(); 476 m_configs->sort();
475 477
476 // Add to server list 478 // Add to server list
477 m_serverList->insertItem( server->name() ); 479 m_serverList->insertItem( server->name() );
478 m_serverList->setCurrentItem( m_serverList->count() ); 480 m_serverList->setCurrentItem( m_serverList->count() );
479 } 481 }
480 else 482 else
481 delete server; 483 delete server;
482} 484}
483 485
484void OIpkgConfigDlg::slotServerEdit() 486void OIpkgConfigDlg::slotServerEdit()
485{ 487{
486 // Find selected server in list 488 // Find selected server in list
487 OConfItem *server = m_ipkg->findConfItem( OConfItem::Source, m_serverList->currentText() ); 489 OConfItem *server = m_ipkg->findConfItem( OConfItem::Source, m_serverList->currentText() );
488 490
489 // Edit server 491 // Edit server
490 if ( server ) 492 if ( server )
491 { 493 {
492 QString origName = server->name(); 494 QString origName = server->name();
493 OIpkgServerDlg dlg( server, this ); 495 OIpkgServerDlg dlg( server, this );
494 if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted ) 496 if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted )
495 { 497 {
496 // Check to see if name has changed, if so update the server list 498 // Check to see if name has changed, if so update the server list
497 if ( server->name() != origName ) 499 if ( server->name() != origName )
498 m_serverList->changeItem( server->name(), m_serverCurrent ); 500 m_serverList->changeItem( server->name(), m_serverCurrent );
499 } 501 }
500 } 502 }
501} 503}
502 504
503void OIpkgConfigDlg::slotServerDelete() 505void OIpkgConfigDlg::slotServerDelete()
504{ 506{
505 // Find selected server in list 507 // Find selected server in list
506 OConfItem *server = m_ipkg->findConfItem( OConfItem::Source, m_serverList->currentText() ); 508 OConfItem *server = m_ipkg->findConfItem( OConfItem::Source, m_serverList->currentText() );
507 509
508 // Delete server 510 // Delete server
509 if ( server ) 511 if ( server )
510 { 512 {
511 m_configs->removeRef( server ); 513 m_configs->removeRef( server );
512 m_serverList->removeItem( m_serverCurrent ); 514 m_serverList->removeItem( m_serverCurrent );
513 } 515 }
514} 516}
515 517
516void OIpkgConfigDlg::slotDestSelected( int index ) 518void OIpkgConfigDlg::slotDestSelected( int index )
517{ 519{
518 m_destCurrent = index; 520 m_destCurrent = index;
519 521
520 // Enable Edit and Delete buttons 522 // Enable Edit and Delete buttons
521 m_destEditBtn->setEnabled( true ); 523 m_destEditBtn->setEnabled( true );
522 m_destDeleteBtn->setEnabled( true ); 524 m_destDeleteBtn->setEnabled( true );
523} 525}
524 526
525void OIpkgConfigDlg::slotDestNew() 527void OIpkgConfigDlg::slotDestNew()
526{ 528{
527 OConfItem *dest = new OConfItem( OConfItem::Destination ); 529 OConfItem *dest = new OConfItem( OConfItem::Destination );
528 530
529 OIpkgDestDlg dlg( dest, this ); 531 OIpkgDestDlg dlg( dest, this );
530 if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted ) 532 if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted )
531 { 533 {
532 // Add to configuration option list 534 // Add to configuration option list
533 m_configs->append( dest ); 535 m_configs->append( dest );
534 m_configs->sort(); 536 m_configs->sort();
535 537
536 // Add to destination list 538 // Add to destination list
537 m_destList->insertItem( dest->name() ); 539 m_destList->insertItem( dest->name() );
538 m_destList->setCurrentItem( m_destList->count() ); 540 m_destList->setCurrentItem( m_destList->count() );
539 } 541 }
540 else 542 else
541 delete dest; 543 delete dest;
542} 544}
543 545
544void OIpkgConfigDlg::slotDestEdit() 546void OIpkgConfigDlg::slotDestEdit()
545{ 547{
546 // Find selected destination in list 548 // Find selected destination in list
547 OConfItem *dest = m_ipkg->findConfItem( OConfItem::Destination, m_destList->currentText() ); 549 OConfItem *dest = m_ipkg->findConfItem( OConfItem::Destination, m_destList->currentText() );
548 550
549 // Edit destination 551 // Edit destination
550 if ( dest ) 552 if ( dest )
551 { 553 {
552 QString origName = dest->name(); 554 QString origName = dest->name();
553 OIpkgDestDlg dlg( dest, this ); 555 OIpkgDestDlg dlg( dest, this );
554 if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted ) 556 if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted )
555 { 557 {
556 // Check to see if name has changed, if so update the dest list 558 // Check to see if name has changed, if so update the dest list
557 if ( dest->name() != origName ) 559 if ( dest->name() != origName )
558 m_destList->changeItem( dest->name(), m_destCurrent ); 560 m_destList->changeItem( dest->name(), m_destCurrent );
559 } 561 }
560 } 562 }
561} 563}
562 564
563void OIpkgConfigDlg::slotDestDelete() 565void OIpkgConfigDlg::slotDestDelete()
564{ 566{
565 // Find selected destination in list 567 // Find selected destination in list
566 OConfItem *destination = m_ipkg->findConfItem( OConfItem::Destination, m_destList->currentText() ); 568 OConfItem *destination = m_ipkg->findConfItem( OConfItem::Destination, m_destList->currentText() );
567 569
568 // Delete destination 570 // Delete destination
569 if ( destination ) 571 if ( destination )
570 { 572 {
571 m_configs->removeRef( destination ); 573 m_configs->removeRef( destination );
572 m_destList->removeItem( m_destCurrent ); 574 m_destList->removeItem( m_destCurrent );
573 } 575 }
574} 576}
575 577
576void OIpkgConfigDlg::slotOptSelectSourceListsPath() 578void OIpkgConfigDlg::slotOptSelectSourceListsPath()
577{ 579{
578 QString path = Opie::Ui::OFileDialog::getDirectory( 0, m_optSourceLists->text() ); 580 QString path = Opie::Ui::OFileDialog::getDirectory( 0, m_optSourceLists->text() );
579 if ( path.at( path.length() - 1 ) == '/' ) 581 if ( path.at( path.length() - 1 ) == '/' )
580 path.truncate( path.length() - 1 ); 582 path.truncate( path.length() - 1 );
581 if ( !path.isNull() ) 583 if ( !path.isNull() )
582 m_optSourceLists->setText( path ); 584 m_optSourceLists->setText( path );
583} 585}
584 586
585OIpkgServerDlg::OIpkgServerDlg( OConfItem *server, QWidget *parent ) 587OIpkgServerDlg::OIpkgServerDlg( OConfItem *server, QWidget *parent )
586 : QDialog( parent, QString::null, true, WStyle_ContextHelp ) 588 : QDialog( parent, QString::null, true, WStyle_ContextHelp )
587 , m_server( server ) 589 , m_server( server )
588{ 590{
589 setCaption( tr( "Edit Server" ) ); 591 setCaption( tr( "Edit Server" ) );
590 592
591 // Initialize UI 593 // Initialize UI
592 QVBoxLayout *layout = new QVBoxLayout( this, 2, 4 ); 594 QVBoxLayout *layout = new QVBoxLayout( this, 2, 4 );
593 595
594 m_active = new QCheckBox( tr( "Active" ), this ); 596 m_active = new QCheckBox( tr( "Active" ), this );
595 QWhatsThis::add( m_active, tr( "Tap here to indicate whether this entry is active or not." ) ); 597 QWhatsThis::add( m_active, tr( "Tap here to indicate whether this entry is active or not." ) );
596 layout->addWidget( m_active ); 598 layout->addWidget( m_active );
597 599
598 layout->addStretch(); 600 layout->addStretch();
599 601
600 QLabel *label = new QLabel( tr( "Name:" ), this ); 602 QLabel *label = new QLabel( tr( "Name:" ), this );
601 QWhatsThis::add( label, tr( "Enter the name of this entry here." ) ); 603 QWhatsThis::add( label, tr( "Enter the name of this entry here." ) );
602 layout->addWidget( label ); 604 layout->addWidget( label );
603 m_name = new QLineEdit( this ); 605 m_name = new QLineEdit( this );
604 QWhatsThis::add( m_name, tr( "Enter the name of this entry here." ) ); 606 QWhatsThis::add( m_name, tr( "Enter the name of this entry here." ) );
605 layout->addWidget( m_name ); 607 layout->addWidget( m_name );
606 608
607 layout->addStretch(); 609 layout->addStretch();
608 610
609 label = new QLabel( tr( "Address:" ), this ); 611 label = new QLabel( tr( "Address:" ), this );
610 QWhatsThis::add( label, tr( "Enter the URL address of this entry here." ) ); 612 QWhatsThis::add( label, tr( "Enter the URL address of this entry here." ) );
611 layout->addWidget( label ); 613 layout->addWidget( label );
612 m_location = new QLineEdit( this ); 614 m_location = new QLineEdit( this );
613 QWhatsThis::add( m_location, tr( "Enter the URL address of this entry here." ) ); 615 QWhatsThis::add( m_location, tr( "Enter the URL address of this entry here." ) );
614 layout->addWidget( m_location ); 616 layout->addWidget( m_location );
615 617
616 layout->addStretch(); 618 layout->addStretch();
617 619
618 m_compressed = new QCheckBox( tr( "Compressed server feed" ), this ); 620 m_compressed = new QCheckBox( tr( "Compressed server feed" ), this );
619 QWhatsThis::add( m_compressed, tr( "Tap here to indicate whether the server support compressed archives or not." ) ); 621 QWhatsThis::add( m_compressed, tr( "Tap here to indicate whether the server support compressed archives or not." ) );
620 layout->addWidget( m_compressed ); 622 layout->addWidget( m_compressed );
621 623
622 // Populate initial information 624 // Populate initial information
623 if ( m_server ) 625 if ( m_server )
624 { 626 {
625 m_name->setText( m_server->name() ); 627 m_name->setText( m_server->name() );
626 m_location->setText( m_server->value() ); 628 m_location->setText( m_server->value() );
627 m_compressed->setChecked( m_server->features().contains( "Compressed" ) ); 629 m_compressed->setChecked( m_server->features().contains( "Compressed" ) );
628 m_active->setChecked( m_server->active() ); 630 m_active->setChecked( m_server->active() );
629 } 631 }
630} 632}
631 633
632void OIpkgServerDlg::accept() 634void OIpkgServerDlg::accept()
633{ 635{
634 // Save information entered 636 // Save information entered
635 QString name = m_name->text(); 637 QString name = m_name->text();
636 name.replace( QRegExp( " " ), "_" ); 638 name.replace( QRegExp( " " ), "_" );
637 m_server->setName( name ); 639 m_server->setName( name );
638 m_server->setValue( m_location->text() ); 640 m_server->setValue( m_location->text() );
639 m_compressed->isChecked() ? m_server->setFeatures( "Compressed" ) 641 m_compressed->isChecked() ? m_server->setFeatures( "Compressed" )
640 : m_server->setFeatures( QString::null ); 642 : m_server->setFeatures( QString::null );
641 m_server->setActive( m_active->isChecked() ); 643 m_server->setActive( m_active->isChecked() );
642 644
643 QDialog::accept(); 645 QDialog::accept();
644} 646}
645 647
646OIpkgDestDlg::OIpkgDestDlg( OConfItem *dest, QWidget *parent ) 648OIpkgDestDlg::OIpkgDestDlg( OConfItem *dest, QWidget *parent )
647 : QDialog( parent, QString::null, true, WStyle_ContextHelp ) 649 : QDialog( parent, QString::null, true, WStyle_ContextHelp )
648 , m_dest( dest ) 650 , m_dest( dest )
649{ 651{
650 setCaption( tr( "Edit Destination" ) ); 652 setCaption( tr( "Edit Destination" ) );
651 653
652 // Initialize UI 654 // Initialize UI
653 QVBoxLayout *layout = new QVBoxLayout( this, 2, 4 ); 655 QVBoxLayout *layout = new QVBoxLayout( this, 2, 4 );
654 656
655 m_active = new QCheckBox( tr( "Active" ), this ); 657 m_active = new QCheckBox( tr( "Active" ), this );
656 QWhatsThis::add( m_active, tr( "Tap here to indicate whether this entry is active or not." ) ); 658 QWhatsThis::add( m_active, tr( "Tap here to indicate whether this entry is active or not." ) );
657 layout->addWidget( m_active ); 659 layout->addWidget( m_active );
658 660
659 layout->addStretch(); 661 layout->addStretch();
660 662
661 QLabel *label = new QLabel( tr( "Name:" ), this ); 663 QLabel *label = new QLabel( tr( "Name:" ), this );
662 QWhatsThis::add( label, tr( "Enter the name of this entry here." ) ); 664 QWhatsThis::add( label, tr( "Enter the name of this entry here." ) );
663 layout->addWidget( label ); 665 layout->addWidget( label );
664 m_name = new QLineEdit( this ); 666 m_name = new QLineEdit( this );
665 QWhatsThis::add( m_name, tr( "Enter the name of this entry here." ) ); 667 QWhatsThis::add( m_name, tr( "Enter the name of this entry here." ) );
666 layout->addWidget( m_name ); 668 layout->addWidget( m_name );
667 669
668 layout->addStretch(); 670 layout->addStretch();
669 671
670 label = new QLabel( tr( "Location:" ), this ); 672 label = new QLabel( tr( "Location:" ), this );
671 QWhatsThis::add( label, tr( "Enter the absolute directory path of this entry here." ) ); 673 QWhatsThis::add( label, tr( "Enter the absolute directory path of this entry here." ) );
672 layout->addWidget( label ); 674 layout->addWidget( label );
673 675
674 QHBoxLayout *layout2 = new QHBoxLayout( this, 2, 4 ); 676 QHBoxLayout *layout2 = new QHBoxLayout( this, 2, 4 );
675 layout->addLayout( layout2 ); 677 layout->addLayout( layout2 );
676 678
677 m_location = new QLineEdit( this ); 679 m_location = new QLineEdit( this );
678 QWhatsThis::add( m_location, tr( "Enter the absolute directory path of this entry here." ) ); 680 QWhatsThis::add( m_location, tr( "Enter the absolute directory path of this entry here." ) );
679 layout2->addWidget( m_location ); 681 layout2->addWidget( m_location );
680 QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "folder", Opie::Core::OResource::SmallIcon ), 682 QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "folder", Opie::Core::OResource::SmallIcon ),
681 QString::null, this ); 683 QString::null, this );
682 btn->setMaximumWidth( btn->height() ); 684 btn->setMaximumWidth( btn->height() );
683 QWhatsThis::add( btn, tr( "Tap here to select the desired location." ) ); 685 QWhatsThis::add( btn, tr( "Tap here to select the desired location." ) );
684 connect( btn, SIGNAL(clicked()), this, SLOT(slotSelectPath()) ); 686 connect( btn, SIGNAL(clicked()), this, SLOT(slotSelectPath()) );
685 layout2->addWidget( btn ); 687 layout2->addWidget( btn );
686 688
687 // Populate initial information 689 // Populate initial information
688 if ( m_dest ) 690 if ( m_dest )
689 { 691 {
690 m_name->setText( m_dest->name() ); 692 m_name->setText( m_dest->name() );
691 m_location->setText( m_dest->value() ); 693 m_location->setText( m_dest->value() );
692 m_active->setChecked( m_dest->active() ); 694 m_active->setChecked( m_dest->active() );
693 } 695 }
694} 696}
695 697
696void OIpkgDestDlg::accept() 698void OIpkgDestDlg::accept()
697{ 699{
698 // Save information entered 700 // Save information entered
699 QString name = m_name->text(); 701 QString name = m_name->text();
700 name.replace( QRegExp( " " ), "_" ); 702 name.replace( QRegExp( " " ), "_" );
701 m_dest->setName( name ); 703 m_dest->setName( name );
702 m_dest->setValue( m_location->text() ); 704 m_dest->setValue( m_location->text() );
703 m_dest->setActive( m_active->isChecked() ); 705 m_dest->setActive( m_active->isChecked() );
704 706
705 QDialog::accept(); 707 QDialog::accept();
706} 708}
707 709
708void OIpkgDestDlg::slotSelectPath() 710void OIpkgDestDlg::slotSelectPath()
709{ 711{
710 QString path = Opie::Ui::OFileDialog::getDirectory( 0, m_location->text() ); 712 QString path = Opie::Ui::OFileDialog::getDirectory( 0, m_location->text() );
711 if ( path.at( path.length() - 1 ) == '/' ) 713 if ( path.at( path.length() - 1 ) == '/' )
712 path.truncate( path.length() - 1 ); 714 path.truncate( path.length() - 1 );
713 if ( !path.isNull() ) 715 if ( !path.isNull() )
714 m_location->setText( path ); 716 m_location->setText( path );
715} 717}
716 718