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 @@ -1550,326 +1550,329 @@ void CSoundFile::AdjustSampleLoop(MODINSTRUMENT *pIns) { pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1]; } if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) { // Fix bad loops if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & MOD_TYPE_S3M)) { pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart]; pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1]; pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2]; pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3]; pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4]; } } } else { signed char *pSample = pIns->pSample; #ifndef FASTSOUNDLIB // Crappy samples (except chiptunes) ? if ((pIns->nLength > 0x100) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M)) && (!(pIns->uFlags & CHN_STEREO))) { int smpend = pSample[pIns->nLength-1], smpfix = 0, kscan; for (kscan=pIns->nLength-1; kscan>0; kscan--) { smpfix = pSample[kscan-1]; if (smpfix != smpend) break; } int delta = smpfix - smpend; if (((!(pIns->uFlags & CHN_LOOP)) || (kscan > (int)pIns->nLoopEnd)) && ((delta < -8) || (delta > 8))) { while (kscan<(int)pIns->nLength) { if (!(kscan & 7)) { if (smpfix > 0) smpfix--; if (smpfix < 0) smpfix++; } pSample[kscan] = (signed char)smpfix; kscan++; } } } #endif // Adjust end of sample if (pIns->uFlags & CHN_STEREO) { pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2]; pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1]; } else { pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1]; } if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) { if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M))) { pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart]; pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1]; pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2]; pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3]; pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4]; } } } } ///////////////////////////////////////////////////////////// // Transpose <-> Frequency conversions // returns 8363*2^((transp*128+ftune)/(12*128)) DWORD CSoundFile::TransposeToFrequency(int transp, int ftune) //----------------------------------------------------------- { //---GCCFIX: Removed assembly. return (DWORD)(8363*pow(2, (transp*128+ftune)/(1536))); #ifdef WIN32 const float _fbase = 8363; const float _factor = 1.0f/(12.0f*128.0f); int result; DWORD freq; transp = (transp << 7) + ftune; _asm { fild transp fld _factor fmulp st(1), st(0) fist result fisub result f2xm1 fild result fld _fbase fscale fstp st(1) fmul st(1), st(0) faddp st(1), st(0) fistp freq } UINT derr = freq % 11025; if (derr <= 8) freq -= derr; if (derr >= 11015) freq += 11025-derr; derr = freq % 1000; if (derr <= 5) freq -= derr; if (derr >= 995) freq += 1000-derr; return freq; #endif } // returns 12*128*log2(freq/8363) int CSoundFile::FrequencyToTranspose(DWORD freq) //---------------------------------------------- { //---GCCFIX: Removed assembly. return int(1536*(log(freq/8363)/log(2))); #ifdef WIN32 const float _f1_8363 = 1.0f / 8363.0f; const float _factor = 128 * 12; LONG result; if (!freq) return 0; _asm { fld _factor fild freq fld _f1_8363 fmulp st(1), st(0) fyl2x fistp result } return result; #endif } void CSoundFile::FrequencyToTranspose(MODINSTRUMENT *psmp) //-------------------------------------------------------- { int f2t = FrequencyToTranspose(psmp->nC4Speed); int transp = f2t >> 7; int ftune = f2t & 0x7F; if (ftune > 80) { transp++; ftune -= 128; } if (transp > 127) transp = 127; if (transp < -127) transp = -127; psmp->RelativeTone = transp; psmp->nFineTune = ftune; } void CSoundFile::CheckCPUUsage(UINT nCPU) //--------------------------------------- { if (nCPU > 100) nCPU = 100; gnCPUUsage = nCPU; if (nCPU < 90) { m_dwSongFlags &= ~SONG_CPUVERYHIGH; } else if ((m_dwSongFlags & SONG_CPUVERYHIGH) && (nCPU >= 94)) { UINT i=MAX_CHANNELS; while (i >= 8) { i--; if (Chn[i].nLength) { Chn[i].nLength = Chn[i].nPos = 0; nCPU -= 2; if (nCPU < 94) break; } } } else if (nCPU > 90) { m_dwSongFlags |= SONG_CPUVERYHIGH; } } BOOL CSoundFile::SetPatternName(UINT nPat, LPCSTR lpszName) //--------------------------------------------------------- { char szName[MAX_PATTERNNAME] = ""; // changed from CHAR if (nPat >= MAX_PATTERNS) return FALSE; - if (lpszName) lstrcpyn(szName, lpszName, MAX_PATTERNNAME); + if (lpszName) + lstrcpyn(szName, lpszName, MAX_PATTERNNAME); + else + return FALSE; szName[MAX_PATTERNNAME-1] = 0; if (!m_lpszPatternNames) m_nPatternNames = 0; if (nPat >= m_nPatternNames) { if (!lpszName[0]) return TRUE; UINT len = (nPat+1)*MAX_PATTERNNAME; char *p = new char[len]; // changed from CHAR if (!p) return FALSE; memset(p, 0, len); if (m_lpszPatternNames) { memcpy(p, m_lpszPatternNames, m_nPatternNames * MAX_PATTERNNAME); delete m_lpszPatternNames; m_lpszPatternNames = NULL; } m_lpszPatternNames = p; m_nPatternNames = nPat + 1; } memcpy(m_lpszPatternNames + nPat * MAX_PATTERNNAME, szName, MAX_PATTERNNAME); return TRUE; } BOOL CSoundFile::GetPatternName(UINT nPat, LPSTR lpszName, UINT cbSize) const //--------------------------------------------------------------------------- { if ((!lpszName) || (!cbSize)) return FALSE; lpszName[0] = 0; if (cbSize > MAX_PATTERNNAME) cbSize = MAX_PATTERNNAME; if ((m_lpszPatternNames) && (nPat < m_nPatternNames)) { memcpy(lpszName, m_lpszPatternNames + nPat * MAX_PATTERNNAME, cbSize); lpszName[cbSize-1] = 0; return TRUE; } return FALSE; } #ifndef FASTSOUNDLIB UINT CSoundFile::DetectUnusedSamples(BOOL *pbIns) //----------------------------------------------- { UINT nExt = 0; if (!pbIns) return 0; if (m_nInstruments) { memset(pbIns, 0, MAX_SAMPLES * sizeof(BOOL)); for (UINT ipat=0; ipat<MAX_PATTERNS; ipat++) { MODCOMMAND *p = Patterns[ipat]; if (p) { UINT jmax = PatternSize[ipat] * m_nChannels; for (UINT j=0; j<jmax; j++, p++) { if ((p->note) && (p->note <= 120)) { if ((p->instr) && (p->instr < MAX_INSTRUMENTS)) { INSTRUMENTHEADER *penv = Headers[p->instr]; if (penv) { UINT n = penv->Keyboard[p->note-1]; if (n < MAX_SAMPLES) pbIns[n] = TRUE; } } else { for (UINT k=1; k<=m_nInstruments; k++) { INSTRUMENTHEADER *penv = Headers[k]; if (penv) { UINT n = penv->Keyboard[p->note-1]; if (n < MAX_SAMPLES) pbIns[n] = TRUE; } } } } } } } for (UINT ichk=1; ichk<=m_nSamples; ichk++) { if ((!pbIns[ichk]) && (Ins[ichk].pSample)) nExt++; } } return nExt; } BOOL CSoundFile::RemoveSelectedSamples(BOOL *pbIns) //------------------------------------------------- { if (!pbIns) return FALSE; for (UINT j=1; j<MAX_SAMPLES; j++) { if ((!pbIns[j]) && (Ins[j].pSample)) { DestroySample(j); if ((j == m_nSamples) && (j > 1)) m_nSamples--; } } return TRUE; } BOOL CSoundFile::DestroySample(UINT nSample) //------------------------------------------ { if ((!nSample) || (nSample >= MAX_SAMPLES)) return FALSE; if (!Ins[nSample].pSample) return TRUE; MODINSTRUMENT *pins = &Ins[nSample]; signed char *pSample = pins->pSample; pins->pSample = NULL; pins->nLength = 0; pins->uFlags &= ~(CHN_16BIT); for (UINT i=0; i<MAX_CHANNELS; i++) { if (Chn[i].pSample == pSample) { Chn[i].nPos = Chn[i].nLength = 0; Chn[i].pSample = Chn[i].pCurrentSample = NULL; } } FreeSample(pSample); return TRUE; } #endif // FASTSOUNDLIB 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 @@ -37,386 +37,388 @@ static int ilog(unsigned int v){ } /* pcm accumulator examples (not exhaustive): <-------------- lW ----------------> <--------------- W ----------------> : .....|..... _______________ | : .''' | '''_--- | |\ | :.....''' |_____--- '''......| | \_______| :.................|__________________|_______|__|______| |<------ Sl ------>| > Sr < |endW |beginSl |endSl | |endSr |beginW |endlW |beginSr |< lW >| <--------------- W ----------------> | | .. ______________ | | | ' `/ | ---_ | |___.'___/`. | ---_____| |_______|__|_______|_________________| | >|Sl|< |<------ Sr ----->|endW | | |endSl |beginSr |endSr |beginW | |endlW mult[0] |beginSl mult[n] <-------------- lW -----------------> |<--W-->| : .............. ___ | | : .''' |`/ \ | | :.....''' |/`....\|...| :.........................|___|___|___| |Sl |Sr |endW | | |endSr | |beginSr | |endSl |beginSl |beginW */ /* block abstraction setup *********************************************/ #ifndef WORD_ALIGN #define WORD_ALIGN 8 #endif int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){ memset(vb,0,sizeof(*vb)); vb->vd=v; vb->localalloc=0; vb->localstore=NULL; return(0); } void *_vorbis_block_alloc(vorbis_block *vb,long bytes){ bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1); if(bytes+vb->localtop>vb->localalloc){ /* can't just _ogg_realloc... there are outstanding pointers */ if(vb->localstore){ struct alloc_chain *link=(struct alloc_chain *)_ogg_malloc(sizeof(*link)); vb->totaluse+=vb->localtop; link->next=vb->reap; link->ptr=vb->localstore; vb->reap=link; } /* highly conservative */ vb->localalloc=bytes; vb->localstore=_ogg_malloc(vb->localalloc); vb->localtop=0; } { void *ret=(void *)(((char *)vb->localstore)+vb->localtop); vb->localtop+=bytes; return ret; } } /* reap the chain, pull the ripcord */ void _vorbis_block_ripcord(vorbis_block *vb){ /* reap the chain */ struct alloc_chain *reap=vb->reap; while(reap){ struct alloc_chain *next=reap->next; _ogg_free(reap->ptr); memset(reap,0,sizeof(*reap)); _ogg_free(reap); reap=next; } /* consolidate storage */ if(vb->totaluse){ vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc); vb->localalloc+=vb->totaluse; vb->totaluse=0; } /* pull the ripcord */ vb->localtop=0; vb->reap=NULL; } int vorbis_block_clear(vorbis_block *vb){ _vorbis_block_ripcord(vb); if(vb->localstore)_ogg_free(vb->localstore); memset(vb,0,sizeof(*vb)); return(0); } static int _vds_init(vorbis_dsp_state *v,vorbis_info *vi){ int i; codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; private_state *b=NULL; memset(v,0,sizeof(*v)); b=(private_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b))); v->vi=vi; b->modebits=ilog(ci->modes); /* Vorbis I uses only window type 0 */ b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2); b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2); /* finish the codebooks */ if(!ci->fullbooks){ ci->fullbooks=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); for(i=0;i<ci->books;i++){ vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]); /* decode codebooks are now standalone after init */ vorbis_staticbook_destroy(ci->book_param[i]); ci->book_param[i]=NULL; } } v->pcm_storage=ci->blocksizes[1]; v->pcm=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcm)); v->pcmret=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcmret)); for(i=0;i<vi->channels;i++) v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i])); /* all 1 (large block) or 0 (small block) */ /* explicitly set for the sake of clarity */ v->lW=0; /* previous window size */ v->W=0; /* current window size */ /* initialize all the mapping/backend lookups */ b->mode=(vorbis_look_mapping **)_ogg_calloc(ci->modes,sizeof(*b->mode)); for(i=0;i<ci->modes;i++){ int mapnum=ci->mode_param[i]->mapping; int maptype=ci->map_type[mapnum]; b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i], ci->map_param[mapnum]); } return(0); } int vorbis_synthesis_restart(vorbis_dsp_state *v){ vorbis_info *vi=v->vi; codec_setup_info *ci; if(!v->backend_state)return -1; if(!vi)return -1; ci=vi->codec_setup; if(!ci)return -1; v->centerW=ci->blocksizes[1]/2; v->pcm_current=v->centerW; v->pcm_returned=-1; v->granulepos=-1; v->sequence=-1; ((private_state *)(v->backend_state))->sample_count=-1; return(0); } int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ _vds_init(v,vi); vorbis_synthesis_restart(v); return(0); } void vorbis_dsp_clear(vorbis_dsp_state *v){ int i; if(v){ vorbis_info *vi=v->vi; codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL); private_state *b=(private_state *)v->backend_state; if(v->pcm){ - for(i=0;i<vi->channels;i++) - if(v->pcm[i])_ogg_free(v->pcm[i]); + if (vi) { + for(i=0;i<vi->channels;i++) + if(v->pcm[i])_ogg_free(v->pcm[i]); + } _ogg_free(v->pcm); if(v->pcmret)_ogg_free(v->pcmret); } /* free mode lookups; these are actually vorbis_look_mapping structs */ if(ci){ for(i=0;i<ci->modes;i++){ int mapnum=ci->mode_param[i]->mapping; int maptype=ci->map_type[mapnum]; if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]); } } if(b){ if(b->mode)_ogg_free(b->mode); _ogg_free(b); } memset(v,0,sizeof(*v)); } } /* Unlike in analysis, the window is only partially applied for each block. The time domain envelope is not yet handled at the point of calling (as it relies on the previous block). */ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ vorbis_info *vi=v->vi; codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; private_state *b=v->backend_state; int i,j; if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL); v->lW=v->W; v->W=vb->W; v->nW=-1; if((v->sequence==-1)|| (v->sequence+1 != vb->sequence)){ v->granulepos=-1; /* out of sequence; lose count */ b->sample_count=-1; } v->sequence=vb->sequence; if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly was called on block */ int n=ci->blocksizes[v->W]/2; int n0=ci->blocksizes[0]/2; int n1=ci->blocksizes[1]/2; int thisCenter; int prevCenter; if(v->centerW){ thisCenter=n1; prevCenter=0; }else{ thisCenter=0; prevCenter=n1; } /* v->pcm is now used like a two-stage double buffer. We don't want to have to constantly shift *or* adjust memory usage. Don't accept a new block until the old is shifted out */ /* overlap/add PCM */ for(j=0;j<vi->channels;j++){ /* the overlap/add section */ if(v->lW){ if(v->W){ /* large/large */ ogg_int32_t *pcm=v->pcm[j]+prevCenter; ogg_int32_t *p=vb->pcm[j]; for(i=0;i<n1;i++) pcm[i]+=p[i]; }else{ /* large/small */ ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2; ogg_int32_t *p=vb->pcm[j]; for(i=0;i<n0;i++) pcm[i]+=p[i]; } }else{ if(v->W){ /* small/large */ ogg_int32_t *pcm=v->pcm[j]+prevCenter; ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2; for(i=0;i<n0;i++) pcm[i]+=p[i]; for(;i<n1/2+n0/2;i++) pcm[i]=p[i]; }else{ /* small/small */ ogg_int32_t *pcm=v->pcm[j]+prevCenter; ogg_int32_t *p=vb->pcm[j]; for(i=0;i<n0;i++) pcm[i]+=p[i]; } } /* the copy section */ { ogg_int32_t *pcm=v->pcm[j]+thisCenter; ogg_int32_t *p=vb->pcm[j]+n; for(i=0;i<n;i++) pcm[i]=p[i]; } } if(v->centerW) v->centerW=0; else v->centerW=n1; /* deal with initial packet state; we do this using the explicit pcm_returned==-1 flag otherwise we're sensitive to first block being short or long */ if(v->pcm_returned==-1){ v->pcm_returned=thisCenter; v->pcm_current=thisCenter; }else{ v->pcm_returned=prevCenter; v->pcm_current=prevCenter+ ci->blocksizes[v->lW]/4+ ci->blocksizes[v->W]/4; } } /* track the frame number... This is for convenience, but also making sure our last packet doesn't end with added padding. If the last packet is partial, the number of samples we'll have to return will be past the vb->granulepos. This is not foolproof! It will be confused if we begin decoding at the last page after a seek or hole. In that case, we don't have a starting point to judge where the last frame is. For this reason, vorbisfile will always try to make sure it reads the last two marked pages in proper sequence */ if(b->sample_count==-1){ b->sample_count=0; }else{ b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; } if(v->granulepos==-1){ if(vb->granulepos!=-1){ /* only set if we have a position to set to */ v->granulepos=vb->granulepos; /* is this a short page? */ if(b->sample_count>v->granulepos){ /* corner case; if this is both the first and last audio page, then spec says the end is cut, not beginning */ if(vb->eofflag){ /* trim the end */ /* no preceeding granulepos; assume we started at zero (we'd have to in a short single-page stream) */ /* granulepos could be -1 due to a seek, but that would result in a long coun`t, not short count */ v->pcm_current-=(b->sample_count-v->granulepos); }else{ /* trim the beginning */ v->pcm_returned+=(b->sample_count-v->granulepos); if(v->pcm_returned>v->pcm_current) v->pcm_returned=v->pcm_current; } } } }else{ v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){ if(v->granulepos>vb->granulepos){ long extra=v->granulepos-vb->granulepos; if(extra) if(vb->eofflag){ /* partial last frame. Strip the extra samples off */ v->pcm_current-=extra; } /* else {Shouldn't happen *unless* the bitstream is out of spec. Either way, believe the bitstream } */ } /* else {Shouldn't happen *unless* the bitstream is out of spec. Either way, believe the bitstream } */ 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,293 +1,293 @@ /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: maintain the info structure, info <-> header packets ********************************************************************/ /* general handling of the header and the vorbis_info structure (and substructures) */ #include <stdlib.h> #include <string.h> #include <ctype.h> #include "ogg.h" #include "ivorbiscodec.h" #include "codec_internal.h" #include "codebook.h" #include "registry.h" #include "window.h" #include "misc.h" #include "os.h" /* helpers */ static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){ while(bytes--){ *buf++=oggpack_read(o,8); } } void vorbis_comment_init(vorbis_comment *vc){ memset(vc,0,sizeof(*vc)); } /* This is more or less the same as strncasecmp - but that doesn't exist * everywhere, and this is a fairly trivial function, so we include it */ static int tagcompare(const char *s1, const char *s2, int n){ int c=0; while(c < n){ if(toupper(s1[c]) != toupper(s2[c])) return !0; c++; } return 0; } char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){ long i; int found = 0; int taglen = strlen(tag)+1; /* +1 for the = we append */ char *fulltag = (char *)alloca(taglen+ 1); strcpy(fulltag, tag); strcat(fulltag, "="); for(i=0;i<vc->comments;i++){ if(!tagcompare(vc->user_comments[i], fulltag, taglen)){ if(count == found) /* We return a pointer to the data, not a copy */ return vc->user_comments[i] + taglen; else found++; } } return NULL; /* didn't find anything */ } int vorbis_comment_query_count(vorbis_comment *vc, char *tag){ int i,count=0; int taglen = strlen(tag)+1; /* +1 for the = we append */ char *fulltag = (char *)alloca(taglen+1); strcpy(fulltag,tag); strcat(fulltag, "="); for(i=0;i<vc->comments;i++){ if(!tagcompare(vc->user_comments[i], fulltag, taglen)) count++; } return count; } void vorbis_comment_clear(vorbis_comment *vc){ if(vc){ long i; for(i=0;i<vc->comments;i++) if(vc->user_comments[i])_ogg_free(vc->user_comments[i]); if(vc->user_comments)_ogg_free(vc->user_comments); if(vc->comment_lengths)_ogg_free(vc->comment_lengths); if(vc->vendor)_ogg_free(vc->vendor); + memset(vc,0,sizeof(*vc)); } - memset(vc,0,sizeof(*vc)); } /* blocksize 0 is guaranteed to be short, 1 is guarantted to be long. They may be equal, but short will never ge greater than long */ int vorbis_info_blocksize(vorbis_info *vi,int zo){ codec_setup_info *ci = (codec_setup_info *)vi->codec_setup; return ci ? ci->blocksizes[zo] : -1; } /* used by synthesis, which has a full, alloced vi */ void vorbis_info_init(vorbis_info *vi){ memset(vi,0,sizeof(*vi)); vi->codec_setup=(codec_setup_info *)_ogg_calloc(1,sizeof(codec_setup_info)); } void vorbis_info_clear(vorbis_info *vi){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; int i; if(ci){ for(i=0;i<ci->modes;i++) if(ci->mode_param[i])_ogg_free(ci->mode_param[i]); for(i=0;i<ci->maps;i++) /* unpack does the range checking */ _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); for(i=0;i<ci->floors;i++) /* unpack does the range checking */ _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); for(i=0;i<ci->residues;i++) /* unpack does the range checking */ _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]); for(i=0;i<ci->books;i++){ if(ci->book_param[i]){ /* knows if the book was not alloced */ vorbis_staticbook_destroy(ci->book_param[i]); } if(ci->fullbooks) vorbis_book_clear(ci->fullbooks+i); } if(ci->fullbooks) _ogg_free(ci->fullbooks); _ogg_free(ci); } memset(vi,0,sizeof(*vi)); } /* Header packing/unpacking ********************************************/ static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; if(!ci)return(OV_EFAULT); vi->version=oggpack_read(opb,32); if(vi->version!=0)return(OV_EVERSION); vi->channels=oggpack_read(opb,8); vi->rate=oggpack_read(opb,32); vi->bitrate_upper=oggpack_read(opb,32); vi->bitrate_nominal=oggpack_read(opb,32); vi->bitrate_lower=oggpack_read(opb,32); ci->blocksizes[0]=1<<oggpack_read(opb,4); ci->blocksizes[1]=1<<oggpack_read(opb,4); if(vi->rate<1)goto err_out; if(vi->channels<1)goto err_out; if(ci->blocksizes[0]<64)goto err_out; if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out; if(ci->blocksizes[1]>8192)goto err_out; if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ return(0); err_out: vorbis_info_clear(vi); return(OV_EBADHEADER); } static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ int i; int vendorlen=oggpack_read(opb,32); if(vendorlen<0)goto err_out; vc->vendor=(char *)_ogg_calloc(vendorlen+1,1); _v_readstring(opb,vc->vendor,vendorlen); vc->comments=oggpack_read(opb,32); if(vc->comments<0)goto err_out; vc->user_comments=(char **)_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments)); vc->comment_lengths=(int *)_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths)); for(i=0;i<vc->comments;i++){ int len=oggpack_read(opb,32); if(len<0)goto err_out; vc->comment_lengths[i]=len; vc->user_comments[i]=(char *)_ogg_calloc(len+1,1); _v_readstring(opb,vc->user_comments[i],len); } if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ return(0); err_out: vorbis_comment_clear(vc); return(OV_EBADHEADER); } /* all of the real encoding details are here. The modes, books, everything */ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; int i; if(!ci)return(OV_EFAULT); /* codebooks */ ci->books=oggpack_read(opb,8)+1; /*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/ for(i=0;i<ci->books;i++){ ci->book_param[i]=(static_codebook *)_ogg_calloc(1,sizeof(*ci->book_param[i])); if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out; } /* time backend settings */ ci->times=oggpack_read(opb,6)+1; /*ci->time_type=_ogg_malloc(ci->times*sizeof(*ci->time_type));*/ /*ci->time_param=_ogg_calloc(ci->times,sizeof(void *));*/ for(i=0;i<ci->times;i++){ ci->time_type[i]=oggpack_read(opb,16); if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out; /* ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb); Vorbis I has no time backend */ /*if(!ci->time_param[i])goto err_out;*/ } /* floor backend settings */ ci->floors=oggpack_read(opb,6)+1; /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/ /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/ for(i=0;i<ci->floors;i++){ ci->floor_type[i]=oggpack_read(opb,16); if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); if(!ci->floor_param[i])goto err_out; } /* residue backend settings */ ci->residues=oggpack_read(opb,6)+1; /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/ /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/ for(i=0;i<ci->residues;i++){ ci->residue_type[i]=oggpack_read(opb,16); if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); if(!ci->residue_param[i])goto err_out; } /* map backend settings */ ci->maps=oggpack_read(opb,6)+1; /*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/ /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/ for(i=0;i<ci->maps;i++){ ci->map_type[i]=oggpack_read(opb,16); if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); if(!ci->map_param[i])goto err_out; } /* mode settings */ ci->modes=oggpack_read(opb,6)+1; /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/ for(i=0;i<ci->modes;i++){ ci->mode_param[i]=(vorbis_info_mode *)_ogg_calloc(1,sizeof(*ci->mode_param[i])); ci->mode_param[i]->blockflag=oggpack_read(opb,1); ci->mode_param[i]->windowtype=oggpack_read(opb,16); ci->mode_param[i]->transformtype=oggpack_read(opb,16); ci->mode_param[i]->mapping=oggpack_read(opb,8); if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; } if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ return(0); err_out: vorbis_info_clear(vi); return(OV_EBADHEADER); } 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,427 +1,436 @@ /**************************************************************************** ** $Id$ ** ** Implementation of the internal Qt classes dealing with rich text ** ** Created : 990101 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qrichtext_p.h" /* OPIE */ #include <opie2/odebug.h> using namespace Opie::Core; /* QT */ #include "qdragobject.h" #include "qpaintdevicemetrics.h" #include "qdrawutil.h" #include "qcleanuphandler.h" /* STD */ #include <stdlib.h> using namespace Qt3; static QTextCursor* richTextExportStart = 0; static QTextCursor* richTextExportEnd = 0; static QTextFormatCollection *qFormatCollection = 0; const int border_tolerance = 2; #ifdef Q_WS_WIN #include "qt_windows.h" #endif #define QChar_linesep QChar(0x2028U) static inline bool is_printer( QPainter *p ) { if ( !p || !p->device() ) return FALSE; return p->device()->devType() == QInternal::Printer; } static inline int scale( int value, QPainter *painter ) { if ( is_printer( painter ) ) { QPaintDeviceMetrics metrics( painter->device() ); #if defined(Q_WS_X11) value = value * metrics.logicalDpiY() / QPaintDevice::x11AppDpiY(); #elif defined (Q_WS_WIN) HDC hdc = GetDC( 0 ); int gdc = GetDeviceCaps( hdc, LOGPIXELSY ); if ( gdc ) value = value * metrics.logicalDpiY() / gdc; ReleaseDC( 0, hdc ); #elif defined (Q_WS_MAC) value = value * metrics.logicalDpiY() / 75; // ##### FIXME #elif defined (Q_WS_QWS) value = value * metrics.logicalDpiY() / 75; #endif } return value; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void QTextCommandHistory::addCommand( QTextCommand *cmd ) { if ( current < (int)history.count() - 1 ) { QPtrList<QTextCommand> commands; commands.setAutoDelete( FALSE ); for( int i = 0; i <= current; ++i ) { commands.insert( i, history.at( 0 ) ); history.take( 0 ); } commands.append( cmd ); history.clear(); history = commands; history.setAutoDelete( TRUE ); } else { history.append( cmd ); } if ( (int)history.count() > steps ) history.removeFirst(); else ++current; } QTextCursor *QTextCommandHistory::undo( QTextCursor *c ) { if ( current > -1 ) { QTextCursor *c2 = history.at( current )->unexecute( c ); --current; return c2; } return 0; } QTextCursor *QTextCommandHistory::redo( QTextCursor *c ) { if ( current > -1 ) { if ( current < (int)history.count() - 1 ) { ++current; return history.at( current )->execute( c ); } } else { if ( history.count() > 0 ) { ++current; return history.at( current )->execute( c ); } } return 0; } bool QTextCommandHistory::isUndoAvailable() { return current > -1; } bool QTextCommandHistory::isRedoAvailable() { return current > -1 && current < (int)history.count() - 1 || current == -1 && history.count() > 0; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ QTextDeleteCommand::QTextDeleteCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str, const QByteArray& oldStyleInfo ) : QTextCommand( d ), id( i ), index( idx ), parag( 0 ), text( str ), styleInformation( oldStyleInfo ) { for ( int j = 0; j < (int)text.size(); ++j ) { if ( text[ j ].format() ) text[ j ].format()->addRef(); } } QTextDeleteCommand::QTextDeleteCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str ) : QTextCommand( 0 ), id( -1 ), index( idx ), parag( p ), text( str ) { for ( int i = 0; i < (int)text.size(); ++i ) { if ( text[ i ].format() ) text[ i ].format()->addRef(); } } QTextDeleteCommand::~QTextDeleteCommand() { for ( int i = 0; i < (int)text.size(); ++i ) { if ( text[ i ].format() ) text[ i ].format()->removeRef(); } text.resize( 0 ); } QTextCursor *QTextDeleteCommand::execute( QTextCursor *c ) { QTextParagraph *s = doc ? doc->paragAt( id ) : parag; - if ( !s ) { + if ( !s && doc ) { owarn << "can't locate parag at " << id << ", last parag: " << doc->lastParagraph()->paragId() << "" << oendl; return 0; + } else if ( !doc ) { + owarn << "No valid doc" << oendl; + return 0; } cursor.setParagraph( s ); cursor.setIndex( index ); int len = text.size(); if ( c ) *c = cursor; if ( doc ) { doc->setSelectionStart( QTextDocument::Temp, cursor ); for ( int i = 0; i < len; ++i ) cursor.gotoNextLetter(); doc->setSelectionEnd( QTextDocument::Temp, cursor ); doc->removeSelectedText( QTextDocument::Temp, &cursor ); if ( c ) *c = cursor; } else { s->remove( index, len ); } return c; } QTextCursor *QTextDeleteCommand::unexecute( QTextCursor *c ) { QTextParagraph *s = doc ? doc->paragAt( id ) : parag; - if ( !s ) { + if ( !s && doc ) { owarn << "can't locate parag at " << id << ", last parag: " << doc->lastParagraph()->paragId() << "" << oendl; return 0; + } else if ( !doc ) { + owarn << "No valid doc" << oendl; + return 0; } cursor.setParagraph( s ); cursor.setIndex( index ); QString str = QTextString::toString( text ); cursor.insert( str, TRUE, &text ); cursor.setParagraph( s ); cursor.setIndex( index ); if ( c ) { c->setParagraph( s ); c->setIndex( index ); for ( int i = 0; i < (int)text.size(); ++i ) c->gotoNextLetter(); + } else { + owarn << "No valid cursor" << oendl; + return 0; } if ( !styleInformation.isEmpty() ) { QDataStream styleStream( styleInformation, IO_ReadOnly ); int num; styleStream >> num; QTextParagraph *p = s; while ( num-- && p ) { p->readStyleInformation( styleStream ); p = p->next(); } } s = cursor.paragraph(); while ( s ) { s->format(); s->setChanged( TRUE ); if ( s == c->paragraph() ) break; s = s->next(); } return &cursor; } QTextFormatCommand::QTextFormatCommand( QTextDocument *d, int sid, int sidx, int eid, int eidx, const QMemArray<QTextStringChar> &old, QTextFormat *f, int fl ) : QTextCommand( d ), startId( sid ), startIndex( sidx ), endId( eid ), endIndex( eidx ), format( f ), oldFormats( old ), flags( fl ) { format = d->formatCollection()->format( f ); for ( int j = 0; j < (int)oldFormats.size(); ++j ) { if ( oldFormats[ j ].format() ) oldFormats[ j ].format()->addRef(); } } QTextFormatCommand::~QTextFormatCommand() { format->removeRef(); for ( int j = 0; j < (int)oldFormats.size(); ++j ) { if ( oldFormats[ j ].format() ) oldFormats[ j ].format()->removeRef(); } } QTextCursor *QTextFormatCommand::execute( QTextCursor *c ) { QTextParagraph *sp = doc->paragAt( startId ); QTextParagraph *ep = doc->paragAt( endId ); if ( !sp || !ep ) return c; QTextCursor start( doc ); start.setParagraph( sp ); start.setIndex( startIndex ); QTextCursor end( doc ); end.setParagraph( ep ); end.setIndex( endIndex ); doc->setSelectionStart( QTextDocument::Temp, start ); doc->setSelectionEnd( QTextDocument::Temp, end ); doc->setFormat( QTextDocument::Temp, format, flags ); doc->removeSelection( QTextDocument::Temp ); if ( endIndex == ep->length() ) end.gotoLeft(); *c = end; return c; } QTextCursor *QTextFormatCommand::unexecute( QTextCursor *c ) { QTextParagraph *sp = doc->paragAt( startId ); QTextParagraph *ep = doc->paragAt( endId ); if ( !sp || !ep ) return 0; int idx = startIndex; int fIndex = 0; for ( ;; ) { if ( oldFormats.at( fIndex ).c == '\n' ) { if ( idx > 0 ) { if ( idx < sp->length() && fIndex > 0 ) sp->setFormat( idx, 1, oldFormats.at( fIndex - 1 ).format() ); if ( sp == ep ) break; sp = sp->next(); idx = 0; } fIndex++; } if ( oldFormats.at( fIndex ).format() ) sp->setFormat( idx, 1, oldFormats.at( fIndex ).format() ); idx++; fIndex++; if ( fIndex >= (int)oldFormats.size() ) break; if ( idx >= sp->length() ) { if ( sp == ep ) break; sp = sp->next(); idx = 0; } } QTextCursor end( doc ); end.setParagraph( ep ); end.setIndex( endIndex ); if ( endIndex == ep->length() ) end.gotoLeft(); *c = end; return c; } QTextStyleCommand::QTextStyleCommand( QTextDocument *d, int fParag, int lParag, const QByteArray& beforeChange ) : QTextCommand( d ), firstParag( fParag ), lastParag( lParag ), before( beforeChange ) { after = readStyleInformation( d, fParag, lParag ); } QByteArray QTextStyleCommand::readStyleInformation( QTextDocument* doc, int fParag, int lParag ) { QByteArray style; QTextParagraph *p = doc->paragAt( fParag ); if ( !p ) return style; QDataStream styleStream( style, IO_WriteOnly ); int num = lParag - fParag + 1; styleStream << num; while ( num -- && p ) { p->writeStyleInformation( styleStream ); p = p->next(); } return style; } void QTextStyleCommand::writeStyleInformation( QTextDocument* doc, int fParag, const QByteArray& style ) { QTextParagraph *p = doc->paragAt( fParag ); if ( !p ) return; QDataStream styleStream( style, IO_ReadOnly ); int num; styleStream >> num; while ( num-- && p ) { p->readStyleInformation( styleStream ); p = p->next(); } } QTextCursor *QTextStyleCommand::execute( QTextCursor *c ) { writeStyleInformation( doc, firstParag, after ); return c; } QTextCursor *QTextStyleCommand::unexecute( QTextCursor *c ) { writeStyleInformation( doc, firstParag, before ); return c; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ QTextCursor::QTextCursor( QTextDocument *d ) : idx( 0 ), tmpIndex( -1 ), ox( 0 ), oy( 0 ), valid( TRUE ) { para = d ? d->firstParagraph() : 0; } QTextCursor::QTextCursor( const QTextCursor &c ) { ox = c.ox; oy = c.oy; idx = c.idx; para = c.para; tmpIndex = c.tmpIndex; indices = c.indices; paras = c.paras; xOffsets = c.xOffsets; yOffsets = c.yOffsets; valid = c.valid; } QTextCursor &QTextCursor::operator=( const QTextCursor &c ) { ox = c.ox; oy = c.oy; idx = c.idx; para = c.para; tmpIndex = c.tmpIndex; indices = c.indices; @@ -1203,402 +1212,413 @@ void QTextDocument::init() backBrush = 0; buf_pixmap = 0; nextDoubleBuffered = FALSE; if ( par ) withoutDoubleBuffer = par->withoutDoubleBuffer; else withoutDoubleBuffer = FALSE; lParag = fParag = createParagraph( this, 0, 0 ); cx = 0; cy = 2; if ( par ) cx = cy = 0; cw = 600; vw = 0; flow_ = new QTextFlow; flow_->setWidth( cw ); leftmargin = rightmargin = 4; scaleFontsFactor = 1; selectionColors[ Standard ] = QApplication::palette().color( QPalette::Active, QColorGroup::Highlight ); selectionText[ Standard ] = TRUE; commandHistory = new QTextCommandHistory( 100 ); tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8; } QTextDocument::~QTextDocument() { if ( par ) par->removeChild( this ); clear(); delete commandHistory; delete flow_; if ( !par ) delete pFormatter; delete fCollection; delete pProcessor; delete buf_pixmap; delete indenter; delete backBrush; if ( tArray ) delete [] tArray; } void QTextDocument::clear( bool createEmptyParag ) { if ( flow_ ) flow_->clear(); while ( fParag ) { QTextParagraph *p = fParag->next(); delete fParag; fParag = p; } fParag = lParag = 0; if ( createEmptyParag ) fParag = lParag = createParagraph( this ); selections.clear(); oText = QString::null; oTextValid = TRUE; } int QTextDocument::widthUsed() const { return wused + border_tolerance; } int QTextDocument::height() const { int h = 0; if ( lParag ) h = lParag->rect().top() + lParag->rect().height() + 1; int fh = flow_->boundingRect().bottom(); return QMAX( h, fh ); } QTextParagraph *QTextDocument::createParagraph( QTextDocument *d, QTextParagraph *pr, QTextParagraph *nx, bool updateIds ) { return new QTextParagraph( d, pr, nx, updateIds ); } bool QTextDocument::setMinimumWidth( int needed, int used, QTextParagraph *p ) { if ( needed == -1 ) { minw = 0; wused = 0; p = 0; } if ( p == minwParag ) { minw = needed; emit minimumWidthChanged( minw ); } else if ( needed > minw ) { minw = needed; minwParag = p; emit minimumWidthChanged( minw ); } wused = QMAX( wused, used ); wused = QMAX( wused, minw ); cw = QMAX( minw, cw ); return TRUE; } void QTextDocument::setPlainText( const QString &text ) { clear(); preferRichText = FALSE; oTextValid = TRUE; oText = text; int lastNl = 0; int nl = text.find( '\n' ); if ( nl == -1 ) { lParag = createParagraph( this, lParag, 0 ); if ( !fParag ) fParag = lParag; QString s = text; if ( !s.isEmpty() ) { if ( s[ (int)s.length() - 1 ] == '\r' ) s.remove( s.length() - 1, 1 ); lParag->append( s ); } } else { for (;;) { lParag = createParagraph( this, lParag, 0 ); if ( !fParag ) fParag = lParag; QString s = text.mid( lastNl, nl - lastNl ); if ( !s.isEmpty() ) { if ( s[ (int)s.length() - 1 ] == '\r' ) s.remove( s.length() - 1, 1 ); lParag->append( s ); } if ( nl == 0xffffff ) break; lastNl = nl + 1; nl = text.find( '\n', nl + 1 ); if ( nl == -1 ) nl = 0xffffff; } } if ( !lParag ) lParag = fParag = createParagraph( this, 0, 0 ); } struct Q_EXPORT QTextDocumentTag { QTextDocumentTag(){} QTextDocumentTag( const QString&n, const QStyleSheetItem* s, const QTextFormat& f ) :name(n),style(s), format(f), alignment(Qt3::AlignAuto), direction(QChar::DirON),liststyle(QStyleSheetItem::ListDisc) { wsm = QStyleSheetItem::WhiteSpaceNormal; } QString name; const QStyleSheetItem* style; QString anchorHref; QStyleSheetItem::WhiteSpaceMode wsm; QTextFormat format; int alignment : 16; int direction : 5; QStyleSheetItem::ListStyle liststyle; QTextDocumentTag( const QTextDocumentTag& t ) { name = t.name; style = t.style; anchorHref = t.anchorHref; wsm = t.wsm; format = t.format; alignment = t.alignment; direction = t.direction; liststyle = t.liststyle; } QTextDocumentTag& operator=(const QTextDocumentTag& t) { name = t.name; style = t.style; anchorHref = t.anchorHref; wsm = t.wsm; format = t.format; alignment = t.alignment; direction = t.direction; liststyle = t.liststyle; return *this; } #if defined(Q_FULL_TEMPLATE_INSTANTIATION) bool operator==( const QTextDocumentTag& ) const { return FALSE; } #endif }; -#define NEWPAR do{ if ( !hasNewPar) { \ - if ( !textEditMode && curpar && curpar->length()>1 && curpar->at( curpar->length()-2)->c == QChar_linesep ) \ - curpar->remove( curpar->length()-2, 1 ); \ - curpar = createParagraph( this, curpar, curpar->next() ); styles.append( vec ); vec = 0;} \ - hasNewPar = TRUE; \ - curpar->rtext = TRUE; \ - curpar->align = curtag.alignment; \ - curpar->lstyle = curtag.liststyle; \ - curpar->litem = ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ); \ - curpar->str->setDirection( (QChar::Direction)curtag.direction ); \ - space = TRUE; \ - delete vec; vec = new QPtrVector<QStyleSheetItem>( (uint)tags.count() + 1); \ - int i = 0; \ - for ( QValueStack<QTextDocumentTag>::Iterator it = tags.begin(); it != tags.end(); ++it ) \ - vec->insert( i++, (*it).style ); \ - vec->insert( i, curtag.style ); \ - }while(FALSE) - +#define NEWPAR do { \ + if ( !hasNewPar) { \ + if ( !curpar ) { \ + owarn << "no current paragraph" << oendl; \ + return; \ + } \ + if ( !textEditMode && curpar && curpar->length()>1 && curpar->at( curpar->length()-2)->c == QChar_linesep ) \ + curpar->remove( curpar->length()-2, 1 ); \ + curpar = createParagraph( this, curpar, curpar->next() ); styles.append( vec ); \ + if ( !curpar ) { \ + owarn << "failed in creating a new paragraph" << oendl; \ + return; \ + } \ + vec = 0; \ + } \ + hasNewPar = TRUE; \ + curpar->rtext = TRUE; \ + curpar->align = curtag.alignment; \ + curpar->lstyle = curtag.liststyle; \ + curpar->litem = ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ); \ + curpar->str->setDirection( (QChar::Direction)curtag.direction ); \ + space = TRUE; \ + delete vec; \ + vec = new QPtrVector<QStyleSheetItem>( (uint)tags.count() + 1); \ + int i = 0; \ + for ( QValueStack<QTextDocumentTag>::Iterator it = tags.begin(); it != tags.end(); ++it ) \ + vec->insert( i++, (*it).style ); \ + vec->insert( i, curtag.style ); \ + } while ( FALSE ) void QTextDocument::setRichText( const QString &text, const QString &context ) { if ( !context.isEmpty() ) setContext( context ); clear(); fParag = lParag = createParagraph( this ); oTextValid = TRUE; oText = text; setRichTextInternal( text ); fParag->rtext = TRUE; } void QTextDocument::setRichTextInternal( const QString &text, QTextCursor* cursor ) { QTextParagraph* curpar = lParag; int pos = 0; QValueStack<QTextDocumentTag> tags; QTextDocumentTag initag( "", sheet_->item(""), *formatCollection()->defaultFormat() ); QTextDocumentTag curtag = initag; bool space = TRUE; bool canMergeLi = FALSE; bool textEditMode = FALSE; const QChar* doc = text.unicode(); int length = text.length(); bool hasNewPar = curpar->length() <= 1; QString anchorName; // style sheet handling for margin and line spacing calculation below QTextParagraph* stylesPar = curpar; QPtrVector<QStyleSheetItem>* vec = 0; QPtrList< QPtrVector<QStyleSheetItem> > styles; styles.setAutoDelete( TRUE ); if ( cursor ) { cursor->splitAndInsertEmptyParagraph(); QTextCursor tmp = *cursor; tmp.gotoPreviousLetter(); stylesPar = curpar = tmp.paragraph(); hasNewPar = TRUE; textEditMode = TRUE; } else { NEWPAR; } // set rtext spacing to FALSE for the initial paragraph. curpar->rtext = FALSE; QString wellKnownTags = "br hr wsp table qt body meta title"; while ( pos < length ) { if ( hasPrefix(doc, length, pos, '<' ) ){ if ( !hasPrefix( doc, length, pos+1, QChar('/') ) ) { // open tag QMap<QString, QString> attr; bool emptyTag = FALSE; QString tagname = parseOpenTag(doc, length, pos, attr, emptyTag); if ( tagname.isEmpty() ) continue; // nothing we could do with this, probably parse error const QStyleSheetItem* nstyle = sheet_->item(tagname); if ( nstyle ) { // we might have to close some 'forgotten' tags while ( !nstyle->allowedInContext( curtag.style ) ) { QString msg; msg.sprintf( "QText Warning: Document not valid ( '%s' not allowed in '%s' #%d)", tagname.ascii(), curtag.style->name().ascii(), pos); sheet_->error( msg ); if ( tags.isEmpty() ) break; curtag = tags.pop(); } /* special handling for p and li for HTML compatibility. We do not want to embed blocks in p, and we do not want new blocks inside non-empty lis. Plus we want to merge empty lis sometimes. */ if( nstyle->displayMode() == QStyleSheetItem::DisplayListItem ) { canMergeLi = TRUE; } else if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock ) { while ( curtag.style->name() == "p" ) { if ( tags.isEmpty() ) break; curtag = tags.pop(); } if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { // we are in a li and a new block comes along if ( nstyle->name() == "ul" || nstyle->name() == "ol" ) hasNewPar = FALSE; // we want an empty li (like most browsers) if ( !hasNewPar ) { /* do not add new blocks inside non-empty lis */ while ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { if ( tags.isEmpty() ) break; curtag = tags.pop(); } } else if ( canMergeLi ) { /* we have an empty li and a block comes along, merge them */ nstyle = curtag.style; } canMergeLi = FALSE; } } } QTextCustomItem* custom = 0; // some well-known tags, some have a nstyle, some not if ( wellKnownTags.find( tagname ) != -1 ) { if ( tagname == "br" ) { emptyTag = space = TRUE; int index = QMAX( curpar->length(),1) - 1; QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); curpar->append( QChar_linesep ); curpar->setFormat( index, 1, &format ); } else if ( tagname == "hr" ) { emptyTag = space = TRUE; custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); NEWPAR; } else if ( tagname == "table" ) { emptyTag = space = TRUE; QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); curpar->setAlignment( curtag.alignment ); custom = parseTable( attr, format, doc, length, pos, curpar ); } else if ( tagname == "qt" || tagname == "body" ) { if ( attr.contains( "bgcolor" ) ) { QBrush *b = new QBrush( QColor( attr["bgcolor"] ) ); setPaper( b ); } if ( attr.contains( "background" ) ) { QImage img; QString bg = attr["background"]; const QMimeSource* m = factory_->data( bg, contxt ); if ( !m ) { owarn << "QRichText: no mimesource for " << bg.latin1() << "" << oendl; } else { if ( !QImageDrag::decode( m, img ) ) { owarn << "QTextImage: cannot decode " << bg.latin1() << "" << oendl; } } if ( !img.isNull() ) { QPixmap pm; pm.convertFromImage( img ); QBrush *b = new QBrush( QColor(), pm ); setPaper( b ); } } if ( attr.contains( "text" ) ) { QColor c( attr["text"] ); if ( formatCollection()->defaultFormat()->color() != c ) { QDict<QTextFormat> formats = formatCollection()->dict(); QDictIterator<QTextFormat> it( formats ); while ( it.current() ) { if ( it.current() == formatCollection()->defaultFormat() ) { ++it; continue; } it.current()->setColor( c ); ++it; } formatCollection()->defaultFormat()->setColor( c ); curtag.format.setColor( c ); } } if ( attr.contains( "link" ) ) linkColor = QColor( attr["link"] ); if ( attr.contains( "title" ) ) attribs.replace( "title", attr["title"] ); if ( textEditMode ) { if ( attr.contains("style" ) ) { QString a = attr["style"]; for ( int s = 0; s < a.contains(';')+1; s++ ) { QString style = QTextDocument::section( a, ";", s, s ); if ( style.startsWith("font-size:" ) && QTextDocument::endsWith(style, "pt") ) { scaleFontsFactor = double( formatCollection()->defaultFormat()->fn.pointSize() ) / style.mid( 10, style.length() - 12 ).toInt(); } } } nstyle = 0; // ignore body in textEditMode } // end qt- and body-tag handling } else if ( tagname == "meta" ) { if ( attr["name"] == "qrichtext" && attr["content"] == "1" ) textEditMode = TRUE; @@ -1706,386 +1726,389 @@ void QTextDocument::setRichTextInternal( const QString &text, QTextCursor* curso xMargin() functions we restrict ourselves to <ol>. Once we calculate the margins in the parser rathern than later, the unelegance of this approach goes awy */ if ( nstyle->name() == "ul" ) curtag.style = sheet_->item( "ol" ); if ( attr.contains( "align" ) ) { QString align = attr["align"]; if ( align == "center" ) curtag.alignment = Qt::AlignCenter; else if ( align == "right" ) curtag.alignment = Qt::AlignRight; else if ( align == "justify" ) curtag.alignment = Qt3::AlignJustify; } if ( attr.contains( "dir" ) ) { QString dir = attr["dir"]; if ( dir == "rtl" ) curtag.direction = QChar::DirR; else if ( dir == "ltr" ) curtag.direction = QChar::DirL; } NEWPAR; if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { if ( attr.contains( "value " ) ) curpar->setListValue( attr["value"].toInt() ); } if ( attr.contains( "style" ) ) { QString a = attr["style"]; bool ok = TRUE; for ( int s = 0; ok && s < a.contains(';')+1; s++ ) { QString style = QTextDocument::section( a, ";", s, s ); if ( style.startsWith("margin-top:" ) && QTextDocument::endsWith(style, "px") ) curpar->utm = 1+style.mid(11, style.length() - 13).toInt(&ok); else if ( style.startsWith("margin-bottom:" ) && QTextDocument::endsWith(style, "px") ) curpar->ubm = 1+style.mid(14, style.length() - 16).toInt(&ok); else if ( style.startsWith("margin-left:" ) && QTextDocument::endsWith(style, "px") ) curpar->ulm = 1+style.mid(12, style.length() - 14).toInt(&ok); else if ( style.startsWith("margin-right:" ) && QTextDocument::endsWith(style, "px") ) curpar->urm = 1+style.mid(13, style.length() - 15).toInt(&ok); else if ( style.startsWith("text-indent:" ) && QTextDocument::endsWith(style, "px") ) curpar->uflm = 1+style.mid(12, style.length() - 14).toInt(&ok); } if ( !ok ) // be pressmistic curpar->utm = curpar->ubm = curpar->urm = curpar->ulm = 0; } } } } else { QString tagname = parseCloseTag( doc, length, pos ); if ( tagname.isEmpty() ) continue; // nothing we could do with this, probably parse error if ( !sheet_->item( tagname ) ) // ignore unknown tags continue; // we close a block item. Since the text may continue, we need to have a new paragraph bool needNewPar = curtag.style->displayMode() == QStyleSheetItem::DisplayBlock || curtag.style->displayMode() == QStyleSheetItem::DisplayListItem; // html slopiness: handle unbalanched tag closing while ( curtag.name != tagname ) { QString msg; msg.sprintf( "QText Warning: Document not valid ( '%s' not closed before '%s' #%d)", curtag.name.ascii(), tagname.ascii(), pos); sheet_->error( msg ); if ( tags.isEmpty() ) break; curtag = tags.pop(); } // close the tag if ( !tags.isEmpty() ) curtag = tags.pop(); else curtag = initag; if ( needNewPar ) { if ( textEditMode && tagname == "p" ) // preserve empty paragraphs hasNewPar = FALSE; NEWPAR; } } } else { // normal contents QString s; QChar c; while ( pos < length && !hasPrefix(doc, length, pos, QChar('<') ) ){ if ( textEditMode ) { // text edit mode: we handle all white space but ignore newlines c = parseChar( doc, length, pos, QStyleSheetItem::WhiteSpacePre ); if ( c == QChar_linesep ) break; } else { int l = pos; c = parseChar( doc, length, pos, curtag.wsm ); // in white space pre mode: treat any space as non breakable if ( c == ' ' && curtag.wsm == QStyleSheetItem::WhiteSpacePre ) c = QChar::nbsp; if ( c == ' ' || c == QChar_linesep ) { /* avoid overlong paragraphs by forcing a new paragraph after 4096 characters. This case can occur when loading undiscovered plain text documents in rich text mode. Instead of hanging forever, we do the trick. */ if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && s.length() > 4096 ) do { if ( doc[l] == '\n' ) { hasNewPar = FALSE; // for a new paragraph ... NEWPAR; hasNewPar = FALSE; // ... and make it non-reusable c = '\n'; // make sure we break below break; } } while ( ++l < pos ); } } if ( c == '\n' ) break; // break on newlines, pre delievers a QChar_linesep bool c_isSpace = c.isSpace() && c.unicode() != 0x00a0U && !textEditMode; if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && c_isSpace && space ) continue; if ( c == '\r' ) continue; space = c_isSpace; s += c; } if ( !s.isEmpty() && curtag.style->displayMode() != QStyleSheetItem::DisplayNone ) { hasNewPar = FALSE; int index = QMAX( curpar->length(),1) - 1; curpar->append( s ); QTextFormat* f = formatCollection()->format( &curtag.format ); curpar->setFormat( index, s.length(), f, FALSE ); // do not use collection because we have done that already f->ref += s.length() -1; // that what friends are for... if ( !curtag.anchorHref.isEmpty() ) { for ( int i = 0; i < int(s.length()); i++ ) curpar->at(index + i)->setAnchor( QString::null, curtag.anchorHref ); } if ( !anchorName.isEmpty() ) { curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() ); anchorName = QString::null; } } } } if ( hasNewPar && curpar != fParag && !cursor ) { // cleanup unused last paragraphs curpar = curpar->p; delete curpar->n; } if ( !anchorName.isEmpty() ) { curpar->at(curpar->length() - 1)->setAnchor( anchorName, curpar->at( curpar->length() - 1 )->anchorHref() ); anchorName = QString::null; } setRichTextMarginsInternal( styles, stylesPar ); if ( cursor ) { cursor->gotoPreviousLetter(); cursor->remove(); } } void QTextDocument::setRichTextMarginsInternal( QPtrList< QPtrVector<QStyleSheetItem> >& styles, QTextParagraph* stylesPar ) { // margin and line spacing calculation QPtrVector<QStyleSheetItem>* prevStyle = 0; QPtrVector<QStyleSheetItem>* curStyle = styles.first(); QPtrVector<QStyleSheetItem>* nextStyle = styles.next(); while ( stylesPar ) { if ( !curStyle ) { stylesPar = stylesPar->next(); prevStyle = curStyle; curStyle = nextStyle; nextStyle = styles.next(); continue; } int i, mar; - QStyleSheetItem* mainStyle = curStyle->size() ? (*curStyle)[curStyle->size()-1] : 0; - if ( mainStyle && mainStyle->displayMode() == QStyleSheetItem::DisplayListItem ) + QStyleSheetItem* mainStyle = (*curStyle)[curStyle->size()-1]; + if ( !mainStyle ) + return; + + if ( mainStyle->displayMode() == QStyleSheetItem::DisplayListItem ) stylesPar->setListItem( TRUE ); int numLists = 0; for ( i = 0; i < (int)curStyle->size(); ++i ) { if ( (*curStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock && int((*curStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined ) numLists++; } stylesPar->ldepth = numLists; if ( stylesPar->next() && nextStyle ) { // also set the depth of the next paragraph, required for the margin calculation numLists = 0; for ( i = 0; i < (int)nextStyle->size(); ++i ) { if ( (*nextStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock && int((*nextStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined ) numLists++; } stylesPar->next()->ldepth = numLists; } // do the top margin QStyleSheetItem* item = mainStyle; int m; if (stylesPar->utm > 0 ) { m = stylesPar->utm-1; stylesPar->utm = 0; } else { m = QMAX(0, item->margin( QStyleSheetItem::MarginTop ) ); if ( item->displayMode() == QStyleSheetItem::DisplayListItem && stylesPar->ldepth ) m /= stylesPar->ldepth; } for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { item = (*curStyle)[ i ]; if ( prevStyle && i < (int) prevStyle->size() && ( item->displayMode() == QStyleSheetItem::DisplayBlock && (*prevStyle)[ i ] == item ) ) break; // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags if ( int(item->listStyle()) != QStyleSheetItem::Undefined && ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) ) continue; mar = QMAX( 0, item->margin( QStyleSheetItem::MarginTop ) ); m = QMAX( m, mar ); } stylesPar->utm = m - stylesPar->topMargin(); // do the bottom margin item = mainStyle; if (stylesPar->ubm > 0 ) { m = stylesPar->ubm-1; stylesPar->ubm = 0; } else { m = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) ); if ( item->displayMode() == QStyleSheetItem::DisplayListItem && stylesPar->ldepth ) m /= stylesPar->ldepth; } for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { item = (*curStyle)[ i ]; if ( nextStyle && i < (int) nextStyle->size() && ( item->displayMode() == QStyleSheetItem::DisplayBlock && (*nextStyle)[ i ] == item ) ) break; // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags if ( int(item->listStyle()) != QStyleSheetItem::Undefined && ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) ) continue; mar = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) ); m = QMAX( m, mar ); } stylesPar->ubm = m - stylesPar->bottomMargin(); // do the left margin, simplyfied item = mainStyle; if (stylesPar->ulm > 0 ) { m = stylesPar->ulm-1; stylesPar->ulm = 0; } else { m = QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) ); } for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { item = (*curStyle)[ i ]; m += QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) ); } stylesPar->ulm = m - stylesPar->leftMargin(); // do the right margin, simplyfied item = mainStyle; if (stylesPar->urm > 0 ) { m = stylesPar->urm-1; stylesPar->urm = 0; } else { m = QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) ); } for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { item = (*curStyle)[ i ]; m += QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) ); } stylesPar->urm = m - stylesPar->rightMargin(); // do the first line margin, which really should be called text-indent item = mainStyle; if (stylesPar->uflm > 0 ) { m = stylesPar->uflm-1; stylesPar->uflm = 0; } else { m = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) ); } for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { item = (*curStyle)[ i ]; mar = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) ); m = QMAX( m, mar ); } stylesPar->uflm =m - stylesPar->firstLineMargin(); // do the bogus line "spacing", which really is just an extra margin item = mainStyle; for ( i = (int)curStyle->size() - 1 ; i >= 0; --i ) { item = (*curStyle)[ i ]; if ( item->lineSpacing() != QStyleSheetItem::Undefined ) { stylesPar->ulinespacing = item->lineSpacing(); if ( formatCollection() && stylesPar->ulinespacing < formatCollection()->defaultFormat()->height() ) stylesPar->ulinespacing += formatCollection()->defaultFormat()->height(); break; } } stylesPar = stylesPar->next(); prevStyle = curStyle; curStyle = nextStyle; nextStyle = styles.next(); } } void QTextDocument::setText( const QString &text, const QString &context ) { focusIndicator.parag = 0; selections.clear(); if ( txtFormat == Qt::AutoText && QStyleSheet::mightBeRichText( text ) || txtFormat == Qt::RichText ) setRichText( text, context ); else setPlainText( text ); } QString QTextDocument::plainText() const { QString buffer; QString s; QTextParagraph *p = fParag; while ( p ) { if ( !p->mightHaveCustomItems ) { s = p->string()->toString(); } else { for ( int i = 0; i < p->length() - 1; ++i ) { if ( p->at( i )->isCustom() ) { if ( p->at( i )->customItem()->isNested() ) { s += "\n"; QTextTable *t = (QTextTable*)p->at( i )->customItem(); QPtrList<QTextTableCell> cells = t->tableCells(); for ( QTextTableCell *c = cells.first(); c; c = cells.next() ) s += c->richText()->plainText() + "\n"; s += "\n"; } } else { s += p->at( i )->c; } } } s.remove( s.length() - 1, 1 ); if ( p->next() ) s += "\n"; buffer += s; p = p->next(); } return buffer; } static QString align_to_string( int a ) { if ( a & Qt::AlignRight ) return " align=\"right\""; if ( a & Qt::AlignHCenter ) return " align=\"center\""; if ( a & Qt3::AlignJustify ) return " align=\"justify\""; return QString::null; } static QString direction_to_string( int d ) { @@ -5152,385 +5175,385 @@ int QTextFormatter::formatVertically( QTextDocument* doc, QTextParagraph* parag // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ QTextFormatterBreakInWords::QTextFormatterBreakInWords() { } #define SPACE(s) doc?(s>0?s:0):s int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> & ) { QTextStringChar *c = 0; QTextStringChar *firstChar = 0; int left = doc ? parag->leftMargin() + doc->leftMargin() : 0; int x = left + ( doc ? parag->firstLineMargin() : 0 ); int dw = parag->documentVisibleWidth() - ( doc ? doc->rightMargin() : 0 ); int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0; int h = y; int len = parag->length(); if ( doc ) x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 4 ); int rm = parag->rightMargin(); int w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); bool fullWidth = TRUE; int minw = 0; int wused = 0; bool wrapEnabled = isWrapEnabled( parag ); start = 0; //######### what is the point with start?! (Matthias) if ( start == 0 ) c = ¶g->string()->at( 0 ); int i = start; QTextLineStart *lineStart = new QTextLineStart( y, y, 0 ); insertLineStart( parag, 0, lineStart ); QPainter *painter = QTextFormat::painter(); int col = 0; int ww = 0; QChar lastChr; for ( ; i < len; ++i, ++col ) { if ( c ) lastChr = c->c; c = ¶g->string()->at( i ); c->rightToLeft = FALSE; // ### the lines below should not be needed if ( painter ) c->format()->setPainter( painter ); if ( i > 0 ) { c->lineStart = 0; } else { c->lineStart = 1; firstChar = c; } if ( c->c.unicode() >= 32 || c->isCustom() ) { ww = parag->string()->width( i ); } else if ( c->c == '\t' ) { int nx = parag->nextTab( i, x - left ) + left; if ( nx < x ) ww = w - x; else ww = nx - x; } else { ww = c->format()->width( ' ' ); } if ( c->isCustom() && c->customItem()->ownLine() ) { x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); c->customItem()->resize( w - x ); w = dw; y += h; h = c->height(); lineStart = new QTextLineStart( y, h, h ); insertLineStart( parag, i, lineStart ); c->lineStart = 1; firstChar = c; x = 0xffffff; continue; } if ( wrapEnabled && ( wrapAtColumn() == -1 && x + ww > w || wrapAtColumn() != -1 && col >= wrapAtColumn() ) ) { x = doc ? parag->document()->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; w = dw; y += h; h = c->height(); lineStart = formatLine( parag, parag->string(), lineStart, firstChar, SPACE(c-1) ); lineStart->y = y; insertLineStart( parag, i, lineStart ); lineStart->baseLine = c->ascent(); lineStart->h = c->height(); c->lineStart = 1; firstChar = c; col = 0; if ( wrapAtColumn() != -1 ) minw = QMAX( minw, w ); } else if ( lineStart ) { lineStart->baseLine = QMAX( lineStart->baseLine, c->ascent() ); h = QMAX( h, c->height() ); lineStart->h = h; } c->x = x; x += ww; wused = QMAX( wused, x ); } int m = parag->bottomMargin(); if ( !parag->next() ) m = 0; else m = QMAX(m, parag->next()->topMargin() ) / 2; parag->setFullWidth( fullWidth ); y += h + m; if ( doc ) minw += doc->rightMargin(); if ( !wrapEnabled ) minw = QMAX(minw, wused); thisminw = minw; thiswused = wused; return y; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ QTextFormatterBreakWords::QTextFormatterBreakWords() { } #define DO_FLOW( lineStart ) do{ if ( doc && doc->isPageBreakEnabled() ) { \ int yflow = lineStart->y + parag->rect().y();\ int shift = doc->flow()->adjustFlow( yflow, dw, lineStart->h ); \ lineStart->y += shift;\ y += shift;\ }}while(FALSE) int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> & ) { QTextStringChar *c = 0; QTextStringChar *firstChar = 0; QTextString *string = parag->string(); int left = doc ? parag->leftMargin() + doc->leftMargin() : 0; int x = left + ( doc ? parag->firstLineMargin() : 0 ); int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0; int h = y; int len = parag->length(); if ( doc ) x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 0 ); int dw = parag->documentVisibleWidth() - ( doc ? ( left != x ? 0 : doc->rightMargin() ) : 0 ); int curLeft = x; int rm = parag->rightMargin(); int rdiff = doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 0 ) : 0; int w = dw - rdiff; bool fullWidth = TRUE; int marg = left + rdiff; int minw = 0; int wused = 0; int tminw = marg; int linespacing = doc ? parag->lineSpacing() : 0; bool wrapEnabled = isWrapEnabled( parag ); start = 0; if ( start == 0 ) c = ¶g->string()->at( 0 ); int i = start; QTextLineStart *lineStart = new QTextLineStart( y, y, 0 ); insertLineStart( parag, 0, lineStart ); int lastBreak = -1; int tmpBaseLine = 0, tmph = 0; bool lastWasNonInlineCustom = FALSE; int align = parag->alignment(); if ( align == Qt3::AlignAuto && doc && doc->alignment() != Qt3::AlignAuto ) align = doc->alignment(); align &= Qt3::AlignHorizontal_Mask; QPainter *painter = QTextFormat::painter(); int col = 0; int ww = 0; QChar lastChr; for ( ; i < len; ++i, ++col ) { if ( c ) lastChr = c->c; // ### next line should not be needed - if ( painter ) + if ( c && painter ) c->format()->setPainter( painter ); c = &string->at( i ); c->rightToLeft = FALSE; if ( i > 0 && (x > curLeft || ww == 0) || lastWasNonInlineCustom ) { c->lineStart = 0; } else { c->lineStart = 1; firstChar = c; } if ( c->isCustom() && c->customItem()->placement() != QTextCustomItem::PlaceInline ) lastWasNonInlineCustom = TRUE; else lastWasNonInlineCustom = FALSE; if ( c->c.unicode() >= 32 || c->isCustom() ) { ww = string->width( i ); } else if ( c->c == '\t' ) { int nx = parag->nextTab( i, x - left ) + left; if ( nx < x ) ww = w - x; else ww = nx - x; } else { ww = c->format()->width( ' ' ); } // last character ("invisible" space) has no width if ( i == len - 1 ) ww = 0; QTextCustomItem* ci = c->customItem(); if ( c->isCustom() && ci->ownLine() ) { x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); QTextLineStart *lineStart2 = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) ); ci->resize( w - x); if ( ci->width < w - x ) { if ( align & Qt::AlignHCenter ) x = ( w - ci->width ) / 2; else if ( align & Qt::AlignRight ) { x = w - ci->width; } } c->x = x; curLeft = x; if ( i == 0 || !isBreakable( string, i - 1 ) || string->at( i - 1 ).lineStart == 0 ) { y += QMAX( h, QMAX( tmph, linespacing ) ); tmph = c->height(); h = tmph; lineStart = lineStart2; lineStart->y = y; insertLineStart( parag, i, lineStart ); c->lineStart = 1; firstChar = c; } else { tmph = c->height(); h = tmph; delete lineStart2; } lineStart->h = h; lineStart->baseLine = h; tmpBaseLine = lineStart->baseLine; lastBreak = -2; x = 0xffffff; minw = QMAX( minw, tminw ); int tw = ci->minimumWidth() + ( doc ? doc->leftMargin() : 0 ); if ( tw < QWIDGETSIZE_MAX ) tminw = tw; else tminw = marg; wused = QMAX( wused, ci->width ); continue; } else if ( c->isCustom() && ci->placement() != QTextCustomItem::PlaceInline ) { int tw = ci->minimumWidth(); if ( tw < QWIDGETSIZE_MAX ) minw = QMAX( minw, tw ); } bool lastWasOwnLineCustomItem = lastBreak == -2; bool hadBreakableChar = lastBreak != -1; bool lastWasHardBreak = lastChr == QChar_linesep; // we break if // 1. the last character was a hard break (QChar_linesep) or // 2. the last charater was a own-line custom item (eg. table or ruler) or // 3. wrapping was enabled, it was not a space and following // condition is true: We either had a breakable character // previously or we ar allowed to break in words and - either // we break at w pixels and the current char would exceed that // or - we break at a column and the current character would // exceed that. if ( lastWasHardBreak || lastWasOwnLineCustomItem || ( wrapEnabled && ( (!c->c.isSpace() && (hadBreakableChar || allowBreakInWords()) && ( (wrapAtColumn() == -1 && x + ww > w) || (wrapAtColumn() != -1 && col >= wrapAtColumn()) ) ) ) ) ) { if ( wrapAtColumn() != -1 ) minw = QMAX( minw, x + ww ); // if a break was forced (no breakable char, hard break or own line custom item), break immediately.... if ( !hadBreakableChar || lastWasHardBreak || lastWasOwnLineCustomItem ) { if ( lineStart ) { lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine ); h = QMAX( h, tmph ); lineStart->h = h; DO_FLOW( lineStart ); } lineStart = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) ); x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); if ( !doc && c->c == '\t' ) { // qt_format_text tab handling int nx = parag->nextTab( i, x - left ) + left; if ( nx < x ) ww = w - x; else ww = nx - x; } curLeft = x; y += QMAX( h, linespacing ); tmph = c->height(); h = 0; lineStart->y = y; insertLineStart( parag, i, lineStart ); lineStart->baseLine = c->ascent(); lineStart->h = c->height(); c->lineStart = 1; firstChar = c; tmpBaseLine = lineStart->baseLine; lastBreak = -1; col = 0; } else { // ... otherwise if we had a breakable char, break there DO_FLOW( lineStart ); i = lastBreak; lineStart = formatLine( parag, string, lineStart, firstChar, parag->at( lastBreak ),align, SPACE(w - string->at( i ).x) ); x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); if ( !doc && c->c == '\t' ) { // qt_format_text tab handling int nx = parag->nextTab( i, x - left ) + left; if ( nx < x ) ww = w - x; else ww = nx - x; } curLeft = x; y += QMAX( h, linespacing ); tmph = c->height(); h = tmph; lineStart->y = y; insertLineStart( parag, i + 1, lineStart ); lineStart->baseLine = c->ascent(); lineStart->h = c->height(); c->lineStart = 1; firstChar = c; tmpBaseLine = lineStart->baseLine; lastBreak = -1; col = 0; tminw = marg; continue; } } else if ( lineStart && isBreakable( string, i ) ) { if ( len <= 2 || i < len - 1 ) { tmpBaseLine = QMAX( tmpBaseLine, c->ascent() ); tmph = QMAX( tmph, c->height() ); } minw = QMAX( minw, tminw ); tminw = marg + ww; lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine ); h = QMAX( h, tmph ); lineStart->h = h; if ( i < len - 2 || c->c != ' ' ) lastBreak = i; } else { tminw += ww; int belowBaseLine = QMAX( tmph - tmpBaseLine, c->height()- c->ascent() ); tmpBaseLine = QMAX( tmpBaseLine, c->ascent() ); tmph = tmpBaseLine + belowBaseLine; } c->x = x; x += ww; wused = QMAX( wused, x ); } // ### hack. The last char in the paragraph is always invisible, // ### and somehow sometimes has a wrong format. It changes // ### between // layouting and printing. This corrects some // ### layouting errors in BiDi mode due to this. if ( len > 1 && !c->isAnchor() ) { c->format()->removeRef(); 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 @@ -106,224 +106,227 @@ OTSDPAttribute::OTSDPAttribute( sdp_data_t * attrib ) { case SDP_TEXT_STR_UNSPEC : case SDP_TEXT_STR8 : case SDP_TEXT_STR16 : case SDP_TEXT_STR32 : setString( QString(attrib->val.str) ); break; case SDP_URL_STR_UNSPEC : case SDP_URL_STR8 : case SDP_URL_STR16 : case SDP_URL_STR32 : setURL( QString(attrib->val.str) ); break; case SDP_BOOL: setBool( attrib->val.int8 != 0); break; case SDP_SEQ_UNSPEC : case SDP_SEQ8 : case SDP_SEQ16 : case SDP_SEQ32 : case SDP_ALT_UNSPEC : case SDP_ALT8 : case SDP_ALT16 : case SDP_ALT32 : { AttributeVector subAttribs; OTSDPAttribute * Attr; sdp_data_t* subAttrib = attrib->val.dataseq; for (; subAttrib; subAttrib = subAttrib->next) { Attr = new OTSDPAttribute(subAttrib); subAttribs.resize( subAttribs.size() + 1 ); subAttribs.insert( subAttribs.size() - 1, Attr ); } if( attrib->dtd == SDP_ALT_UNSPEC || attrib->dtd == SDP_ALT8 || attrib->dtd == SDP_ALT16 || attrib->dtd == SDP_ALT32 ) { setAlternative(subAttribs); } else { setSequence(subAttribs); } break; } } // end case } QString OTSDPAttribute::toString( void ) { QString S; switch( type ) { case INVALID : S = "invalid"; break; case NIL : S = "NIL"; break; case UINT : S = Value.uintVal->toString(); break; case INT : S = Value.intVal->toString(); break; case UUID : S = Value.uuidVal->toString(); break; case BOOLEAN : S = (Value.boolVal) ? "true" : "false"; break; case STRING : S = *(Value.stringVal); break; case URL : S = *(Value.stringVal); break; case SEQUENCE : S.sprintf( "Sequence(%d)", Value.sequenceVal->count() ); break; case ALTERNATIVE : S.sprintf( "Alternative(%d)", Value.sequenceVal->count() ); break; case UNKNOWN : S = "unknown"; break; } return S; } void OTSDPAttribute::setNil() { type = NIL; } void OTSDPAttribute::setInt(const OTSDPAttribute::int128_t & val) { type = INT; Value.intVal = new int128_t( val ); } void OTSDPAttribute::setUInt(const uint128_t & val) { type = UINT; Value.uintVal = new uint128_t(val); } void OTSDPAttribute::setUUID(const OTUUID & val) { type = UUID; Value.uuidVal = new OTUUID( val ); } void OTSDPAttribute::setBool(bool val) { type = BOOLEAN; Value.boolVal = val; } void OTSDPAttribute::setString( const QString & val) { type = STRING; Value.stringVal = new QString( val ); } void OTSDPAttribute::setURL( const QString & val) { type = URL; Value.stringVal = new QString(val); } void OTSDPAttribute::setSequence(const AttributeVector& val) { type = SEQUENCE; Value.sequenceVal = new AttributeVector(); Value.sequenceVal->setAutoDelete( TRUE ); *Value.sequenceVal = val; } void OTSDPAttribute::setAlternative(const AttributeVector& val) { type = ALTERNATIVE; Value.sequenceVal = new AttributeVector(); Value.sequenceVal->setAutoDelete( TRUE ); *Value.sequenceVal = val; } QString OTSDPAttribute::getString() { assert(type == STRING); return *Value.stringVal; } QString OTSDPAttribute::getURL() { assert(type == URL); return *Value.stringVal; } const OTSDPAttribute::int128_t & OTSDPAttribute::getInt() { assert(type == INT); return *Value.intVal; } const OTSDPAttribute::uint128_t & OTSDPAttribute::getUInt() { assert(type == UINT); return *Value.uintVal; } const OTUUID & OTSDPAttribute::getUUID() { assert(type == UUID); return *Value.uuidVal; } bool OTSDPAttribute::getBool() { assert(type == BOOLEAN); return Value.boolVal; } AttributeVector * OTSDPAttribute::getSequence() { assert(type == SEQUENCE); return Value.sequenceVal; } AttributeVector * OTSDPAttribute::getAlternative() { assert(type == ALTERNATIVE); return Value.sequenceVal; } UUIDVector OTSDPAttribute::getAllUUIDs() { UUIDVector uuids; if (getType() == UUID) { uuids.resize( uuids.size()+1 ); uuids[uuids.size()-1] = getUUID(); } else { AttributeVector * subAttributes = 0 ; if (getType() == SEQUENCE) { subAttributes = getSequence(); } else if (getType() == ALTERNATIVE) { subAttributes = getAlternative(); } + if (!subAttributes) + return 0; + int os; for( unsigned int i = 0; i < subAttributes->count(); i++ ) { UUIDVector subUUIDs = (*subAttributes)[i]->getAllUUIDs(); os = uuids.size(); uuids.resize( uuids.size()+subUUIDs.count() ); for( unsigned int k = 0; k < subUUIDs.count(); k++ ) { uuids[os + k] = subUUIDs[k]; } } } return uuids; } static char * Attr2String[] = { "Invalid", "Nil", "UInt", "int", "UUID", "Boolean", "String", "Sequence", "Alternative", "URL", "Unknown" }; const char * OTSDPAttribute::getTypeString() { return Attr2String[type]; } 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 @@ -247,399 +247,401 @@ void OIpkgConfigDlg::initDestinationWidget() m_destDeleteBtn = new QPushButton( Opie::Core::OResource::loadPixmap( "trash", Opie::Core::OResource::SmallIcon ), tr( "Delete" ), container ); m_destDeleteBtn->setMinimumHeight( AppLnk::smallIconSize()+4 ); m_destDeleteBtn->setEnabled( false ); QWhatsThis::add( m_destDeleteBtn, tr( "Tap here to delete the entry selected above." ) ); connect( m_destDeleteBtn, SIGNAL(clicked()), this, SLOT(slotDestDelete()) ); layout->addWidget( m_destDeleteBtn, 1, 2 ); } void OIpkgConfigDlg::initProxyWidget() { m_proxyWidget = new QWidget( this ); // Initialize UI QVBoxLayout *vb = new QVBoxLayout( m_proxyWidget ); QScrollView *sv = new QScrollView( m_proxyWidget ); vb->addWidget( sv, 0, 0 ); sv->setResizePolicy( QScrollView::AutoOneFit ); sv->setFrameStyle( QFrame::NoFrame ); QWidget *container = new QWidget( sv->viewport() ); sv->addChild( container ); QGridLayout *layout = new QGridLayout( container, 4, 2, 2, 4 ); // HTTP proxy server configuration QGroupBox *grpbox = new QGroupBox( 0, Qt::Vertical, tr( "HTTP Proxy" ), container ); grpbox->layout()->setSpacing( 2 ); grpbox->layout()->setMargin( 4 ); layout->addMultiCellWidget( grpbox, 0, 0, 0, 1 ); QVBoxLayout *grplayout = new QVBoxLayout( grpbox->layout() ); m_proxyHttpServer = new QLineEdit( grpbox ); QWhatsThis::add( m_proxyHttpServer, tr( "Enter the URL address of the HTTP proxy server here." ) ); grplayout->addWidget( m_proxyHttpServer ); m_proxyHttpActive = new QCheckBox( tr( "Enabled" ), grpbox ); QWhatsThis::add( m_proxyHttpActive, tr( "Tap here to enable or disable the HTTP proxy server." ) ); grplayout->addWidget( m_proxyHttpActive ); // FTP proxy server configuration grpbox = new QGroupBox( 0, Qt::Vertical, tr( "FTP Proxy" ), container ); grpbox->layout()->setSpacing( 2 ); grpbox->layout()->setMargin( 4 ); layout->addMultiCellWidget( grpbox, 1, 1, 0, 1 ); grplayout = new QVBoxLayout( grpbox->layout() ); m_proxyFtpServer = new QLineEdit( grpbox ); QWhatsThis::add( m_proxyFtpServer, tr( "Enter the URL address of the FTP proxy server here." ) ); grplayout->addWidget( m_proxyFtpServer ); m_proxyFtpActive = new QCheckBox( tr( "Enabled" ), grpbox ); QWhatsThis::add( m_proxyFtpActive, tr( "Tap here to enable or disable the FTP proxy server." ) ); grplayout->addWidget( m_proxyFtpActive ); // Proxy server username and password configuration QLabel *label = new QLabel( tr( "Username:" ), container ); QWhatsThis::add( label, tr( "Enter the username for the proxy servers here." ) ); layout->addWidget( label, 2, 0 ); m_proxyUsername = new QLineEdit( container ); QWhatsThis::add( m_proxyUsername, tr( "Enter the username for the proxy servers here." ) ); layout->addWidget( m_proxyUsername, 2, 1 ); label = new QLabel( tr( "Password:" ), container ); QWhatsThis::add( label, tr( "Enter the password for the proxy servers here." ) ); layout->addWidget( label, 3, 0 ); m_proxyPassword = new QLineEdit( container ); QWhatsThis::add( m_proxyPassword, tr( "Enter the password for the proxy servers here." ) ); layout->addWidget( m_proxyPassword, 3, 1 ); } void OIpkgConfigDlg::initOptionsWidget() { m_optionsWidget = new QWidget( this ); // Initialize UI QVBoxLayout *vb = new QVBoxLayout( m_optionsWidget ); QScrollView *sv = new QScrollView( m_optionsWidget ); vb->addWidget( sv, 0, 0 ); sv->setResizePolicy( QScrollView::AutoOneFit ); sv->setFrameStyle( QFrame::NoFrame ); QWidget *container = new QWidget( sv->viewport() ); sv->addChild( container ); QGridLayout *layout = new QGridLayout( container, 8, 2, 2, 4 ); m_optForceDepends = new QCheckBox( tr( "Force Depends" ), container ); QWhatsThis::add( m_optForceDepends, tr( "Tap here to enable or disable the '-force-depends' option for Ipkg." ) ); layout->addMultiCellWidget( m_optForceDepends, 0, 0, 0, 1 ); m_optForceReinstall = new QCheckBox( tr( "Force Reinstall" ), container ); QWhatsThis::add( m_optForceReinstall, tr( "Tap here to enable or disable the '-force-reinstall' option for Ipkg." ) ); layout->addMultiCellWidget( m_optForceReinstall, 1, 1, 0, 1 ); m_optForceRemove = new QCheckBox( tr( "Force Remove" ), container ); QWhatsThis::add( m_optForceRemove, tr( "Tap here to enable or disable the '-force-removal-of-dependent-packages' option for Ipkg." ) ); layout->addMultiCellWidget( m_optForceRemove, 2, 2, 0, 1 ); m_optForceOverwrite = new QCheckBox( tr( "Force Overwrite" ), container ); QWhatsThis::add( m_optForceOverwrite, tr( "Tap here to enable or disable the '-force-overwrite' option for Ipkg." ) ); layout->addMultiCellWidget( m_optForceOverwrite, 3, 3, 0, 1 ); m_optForceRecursive = new QCheckBox( tr( "Force Recursive" ), container ); QWhatsThis::add( m_optForceRecursive, tr( "Tap here to enable or disable the '-recursive' option for Ipkg." ) ); layout->addMultiCellWidget( m_optForceRecursive, 4, 4, 0, 1 ); m_optVerboseWget = new QCheckBox( tr( "Verbose fetch" ), container ); QWhatsThis::add( m_optVerboseWget, tr( "Tap here to enable or disable the '-verbose_wget' option for Ipkg." ) ); layout->addMultiCellWidget( m_optVerboseWget, 5, 5, 0, 1 ); QLabel *l = new QLabel( tr( "Information level:" ), container ); QWhatsThis::add( l, tr( "Select information level for Ipkg." ) ); layout->addMultiCellWidget( l, 6, 6, 0, 1 ); m_optVerboseIpkg = new QComboBox( container ); QWhatsThis::add( m_optVerboseIpkg, tr( "Select information level for Ipkg." ) ); m_optVerboseIpkg->insertItem( tr( "Errors only" ) ); m_optVerboseIpkg->insertItem( tr( "Normal messages" ) ); m_optVerboseIpkg->insertItem( tr( "Informative messages" ) ); m_optVerboseIpkg->insertItem( tr( "Troubleshooting output" ) ); layout->addMultiCellWidget( m_optVerboseIpkg, 7, 7, 0, 1 ); l = new QLabel( tr( "Package source lists directory:" ), container ); QWhatsThis::add( l, tr( "Enter the directory where package source feed information is stored." ) ); layout->addMultiCellWidget( l, 8, 8, 0, 1 ); m_optSourceLists = new QLineEdit( container ); QWhatsThis::add( m_optSourceLists, tr( "Enter the directory where package source feed information is stored." ) ); layout->addWidget( m_optSourceLists, 9, 0 ); QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "folder", Opie::Core::OResource::SmallIcon ), QString::null, container ); btn->setMinimumHeight( AppLnk::smallIconSize()+4 ); btn->setMaximumWidth( btn->height() ); QWhatsThis::add( btn, tr( "Tap here to select the directory where package source feed information is stored." ) ); connect( btn, SIGNAL(clicked()), this, SLOT(slotOptSelectSourceListsPath()) ); layout->addWidget( btn, 9, 1 ); layout->addItem( new QSpacerItem( 1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding ) ); } void OIpkgConfigDlg::initData() { // Read ipkg configuration (server/destination/proxy) information if ( m_ipkg && !m_installOptions ) { m_configs = m_ipkg->configItems(); if ( m_configs ) { for ( OConfItemListIterator configIt( *m_configs ); configIt.current(); ++configIt ) { OConfItem *config = configIt.current(); // Add configuration item to the appropriate dialog controls if ( config ) { switch ( config->type() ) { case OConfItem::Source : m_serverList->insertItem( config->name() ); break; case OConfItem::Destination : m_destList->insertItem( config->name() ); break; case OConfItem::Option : { if ( config->name() == "http_proxy" ) { m_proxyHttpServer->setText( config->value() ); m_proxyHttpActive->setChecked( config->active() ); } else if ( config->name() == "ftp_proxy" ) { m_proxyFtpServer->setText( config->value() ); m_proxyFtpActive->setChecked( config->active() ); } else if ( config->name() == "proxy_username" ) { m_proxyUsername->setText( config->value() ); } else if ( config->name() == "proxy_password" ) { m_proxyPassword->setText( config->value() ); } } break; case OConfItem::Other : { if ( config->name() == "lists_dir" ) m_optSourceLists->setText( config->value() ); else // TODO - use proper libipkg define m_optSourceLists->setText( "/usr/lib/ipkg/lists" ); } break; default : break; }; } } } } // Get Ipkg execution options - int options = m_ipkg->ipkgExecOptions(); + int options = 0; + if ( m_ipkg ) + options = m_ipkg->ipkgExecOptions(); if ( options & FORCE_DEPENDS ) m_optForceDepends->setChecked( true ); if ( options & FORCE_REINSTALL ) m_optForceReinstall->setChecked( true ); if ( options & FORCE_REMOVE ) m_optForceRemove->setChecked( true ); if ( options & FORCE_OVERWRITE ) m_optForceOverwrite->setChecked( true ); if ( options & FORCE_RECURSIVE ) m_optForceRecursive->setChecked( true ); if ( options & FORCE_VERBOSE_WGET ) m_optVerboseWget->setChecked( true ); - m_optVerboseIpkg->setCurrentItem( m_ipkg->ipkgExecVerbosity() ); + m_optVerboseIpkg->setCurrentItem( ( m_ipkg ? m_ipkg->ipkgExecVerbosity() : 0 ) ); } void OIpkgConfigDlg::slotServerSelected( int index ) { m_serverCurrent = index; // Enable Edit and Delete buttons m_serverEditBtn->setEnabled( true ); m_serverDeleteBtn->setEnabled( true ); } void OIpkgConfigDlg::slotServerNew() { OConfItem *server = new OConfItem( OConfItem::Source ); OIpkgServerDlg dlg( server, this ); if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted ) { // Add to configuration option list m_configs->append( server ); m_configs->sort(); // Add to server list m_serverList->insertItem( server->name() ); m_serverList->setCurrentItem( m_serverList->count() ); } else delete server; } void OIpkgConfigDlg::slotServerEdit() { // Find selected server in list OConfItem *server = m_ipkg->findConfItem( OConfItem::Source, m_serverList->currentText() ); // Edit server if ( server ) { QString origName = server->name(); OIpkgServerDlg dlg( server, this ); if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted ) { // Check to see if name has changed, if so update the server list if ( server->name() != origName ) m_serverList->changeItem( server->name(), m_serverCurrent ); } } } void OIpkgConfigDlg::slotServerDelete() { // Find selected server in list OConfItem *server = m_ipkg->findConfItem( OConfItem::Source, m_serverList->currentText() ); // Delete server if ( server ) { m_configs->removeRef( server ); m_serverList->removeItem( m_serverCurrent ); } } void OIpkgConfigDlg::slotDestSelected( int index ) { m_destCurrent = index; // Enable Edit and Delete buttons m_destEditBtn->setEnabled( true ); m_destDeleteBtn->setEnabled( true ); } void OIpkgConfigDlg::slotDestNew() { OConfItem *dest = new OConfItem( OConfItem::Destination ); OIpkgDestDlg dlg( dest, this ); if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted ) { // Add to configuration option list m_configs->append( dest ); m_configs->sort(); // Add to destination list m_destList->insertItem( dest->name() ); m_destList->setCurrentItem( m_destList->count() ); } else delete dest; } void OIpkgConfigDlg::slotDestEdit() { // Find selected destination in list OConfItem *dest = m_ipkg->findConfItem( OConfItem::Destination, m_destList->currentText() ); // Edit destination if ( dest ) { QString origName = dest->name(); OIpkgDestDlg dlg( dest, this ); if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted ) { // Check to see if name has changed, if so update the dest list if ( dest->name() != origName ) m_destList->changeItem( dest->name(), m_destCurrent ); } } } void OIpkgConfigDlg::slotDestDelete() { // Find selected destination in list OConfItem *destination = m_ipkg->findConfItem( OConfItem::Destination, m_destList->currentText() ); // Delete destination if ( destination ) { m_configs->removeRef( destination ); m_destList->removeItem( m_destCurrent ); } } void OIpkgConfigDlg::slotOptSelectSourceListsPath() { QString path = Opie::Ui::OFileDialog::getDirectory( 0, m_optSourceLists->text() ); if ( path.at( path.length() - 1 ) == '/' ) path.truncate( path.length() - 1 ); if ( !path.isNull() ) m_optSourceLists->setText( path ); } OIpkgServerDlg::OIpkgServerDlg( OConfItem *server, QWidget *parent ) : QDialog( parent, QString::null, true, WStyle_ContextHelp ) , m_server( server ) { setCaption( tr( "Edit Server" ) ); // Initialize UI QVBoxLayout *layout = new QVBoxLayout( this, 2, 4 ); m_active = new QCheckBox( tr( "Active" ), this ); QWhatsThis::add( m_active, tr( "Tap here to indicate whether this entry is active or not." ) ); layout->addWidget( m_active ); layout->addStretch(); QLabel *label = new QLabel( tr( "Name:" ), this ); QWhatsThis::add( label, tr( "Enter the name of this entry here." ) ); layout->addWidget( label ); m_name = new QLineEdit( this ); QWhatsThis::add( m_name, tr( "Enter the name of this entry here." ) ); layout->addWidget( m_name ); layout->addStretch(); label = new QLabel( tr( "Address:" ), this ); QWhatsThis::add( label, tr( "Enter the URL address of this entry here." ) ); layout->addWidget( label ); m_location = new QLineEdit( this ); QWhatsThis::add( m_location, tr( "Enter the URL address of this entry here." ) ); layout->addWidget( m_location ); layout->addStretch(); m_compressed = new QCheckBox( tr( "Compressed server feed" ), this ); QWhatsThis::add( m_compressed, tr( "Tap here to indicate whether the server support compressed archives or not." ) ); layout->addWidget( m_compressed ); // Populate initial information if ( m_server ) { m_name->setText( m_server->name() ); m_location->setText( m_server->value() ); m_compressed->setChecked( m_server->features().contains( "Compressed" ) ); m_active->setChecked( m_server->active() ); } } void OIpkgServerDlg::accept() { // Save information entered QString name = m_name->text(); name.replace( QRegExp( " " ), "_" ); m_server->setName( name ); m_server->setValue( m_location->text() ); m_compressed->isChecked() ? m_server->setFeatures( "Compressed" ) : m_server->setFeatures( QString::null ); m_server->setActive( m_active->isChecked() ); QDialog::accept(); } |