| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130 |
- //*****************************************************************************
- //
- // string.c - Routines for drawing text.
- //
- // Copyright (c) 2007-2010 Texas Instruments Incorporated. All rights reserved.
- // Software License Agreement
- //
- // Texas Instruments (TI) is supplying this software for use solely and
- // exclusively on TI's microcontroller products. The software is owned by
- // TI and/or its suppliers, and is protected under applicable copyright
- // laws. You may not combine this software with "viral" open-source
- // software in order to form a larger program.
- //
- // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
- // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
- // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
- // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
- // DAMAGES, FOR ANY REASON WHATSOEVER.
- //
- // This is part of revision 6288 of the Stellaris Graphics Library.
- //
- //*****************************************************************************
- #include "debug.h"
- #include "grlib.h"
- //*****************************************************************************
- //
- //! \addtogroup primitives_api
- //! @{
- //
- //*****************************************************************************
- //*****************************************************************************
- //
- // The character printed by GrStringDraw in place of any character in the
- // string which does not appear in the font.
- //
- //*****************************************************************************
- #define ABSENT_CHAR_REPLACEMENT '.'
- //*****************************************************************************
- //
- // Counts the number of zeros at the start of a word. This macro uses
- // compiler-specific constructs to perform an inline insertion of the "clz"
- // instruction, which counts the leading zeros directly.
- //
- //*****************************************************************************
- #if defined(ewarm)
- #include <intrinsics.h>
- #define NumLeadingZeros(x) __CLZ(x)
- #elif defined(codered) || defined(gcc) || defined(sourcerygxx)
- #define NumLeadingZeros(x) __extension__ \
- ({ \
- register unsigned int __ret, __inp = x; \
- __asm__("clz %0, %1" : "=r" (__ret) : "r" (__inp)); \
- __ret; \
- })
- #elif defined(rvmdk) || defined(__ARMCC_VERSION)
- #define NumLeadingZeros(x) __clz(x)
- #elif defined(ccs)
- //
- // The CCS/TI compiler _norm intrinsic function will generate an inline CLZ
- // instruction.
- //
- #define NumLeadingZeros(x) _norm(x)
- #else
- // Compiler independent code for counting Number of leading zeros in a number.
- // This is to be used when the Processor doesnt support asm code to count the zeros.
- unsigned char NumLeadingZeros(unsigned int x)
- {
- register unsigned char count = 0;//sizeof(x)*8;
-
- if (x == 0)
- {
- return 32;
- }
- while(x)
- {
- if(!(x & 0xFF000000))
- {
- count = count+8;
- x = x << 8;
- }
- else
- {
- while(!(x & 0x80000000))
- {
- x = x << 1;
- count++;
- }
- break;
- }
- }
- return count;
- }
-
- #endif
-
- //*****************************************************************************
- //
- //! Determines the width of a string.
- //!
- //! \param pContext is a pointer to the drawing context to use.
- //! \param pcString is the string in question.
- //! \param lLength is the length of the string.
- //!
- //! This function determines the width of a string (or portion of the string)
- //! when drawn with a particular font. The \e lLength parameter allows a
- //! portion of the string to be examined without having to insert a NULL
- //! character at the stopping point (would not be possible if the string was
- //! located in flash); specifying a length of -1 will cause the width of the
- //! entire string to be computed.
- //!
- //! \return Returns the width of the string in pixels.
- //
- //*****************************************************************************
- int
- GrStringWidthGet(const tContext *pContext, const char *pcString, int lLength)
- {
- const unsigned short *pusOffset;
- const unsigned char *pucData;
- int lWidth;
- //
- // Check the arguments.
- //
- ASSERT(pContext);
- ASSERT(pcString);
- //
- // Get some pointers to relevant information in the font to make things
- // easier, and give the compiler a hint about extraneous loads that it can
- // avoid.
- //
- pucData = pContext->pFont->pucData;
- pusOffset = pContext->pFont->pusOffset;
- //
- // Loop through the characters in the string.
- //
- for(lWidth = 0; *pcString && lLength; pcString++, lLength--)
- {
- //
- // Get a pointer to the font data for the next character from the
- // string. If there is not a glyph for the next character, replace it
- // with a ".".
- //
- if((*pcString >= ' ') && (*pcString <= '~'))
- {
- //
- // Add the width of this character as drawn with the given font.
- //
- lWidth += pucData[pusOffset[*pcString - ' '] + 1];
- }
- else
- {
- //
- // This character does not exist in the font so replace it with
- // a '.' instead. This matches the approach taken in GrStringDraw
- // and ensures that the width returned here represents the
- // rendered dimension of the string.
- //
- lWidth += pucData[pusOffset[ABSENT_CHAR_REPLACEMENT - ' '] + 1];
- }
- }
- //
- // Return the width of the string.
- //
- return(lWidth);
- }
- //*****************************************************************************
- //
- //! Draws a string.
- //!
- //! \param pContext is a pointer to the drawing context to use.
- //! \param pcString is a pointer to the string to be drawn.
- //! \param lLength is the number of characters from the string that should be
- //! drawn on the screen.
- //! \param lX is the X coordinate of the upper left corner of the string
- //! position on the screen.
- //! \param lY is the Y coordinate of the upper left corner of the string
- //! position on the screen.
- //! \param bOpaque is true of the background of each character should be drawn
- //! and false if it should not (leaving the background as is).
- //!
- //! This function draws a string of test on the screen. The \e lLength
- //! parameter allows a portion of the string to be examined without having to
- //! insert a NULL character at the stopping point (which would not be possible
- //! if the string was located in flash); specifying a length of -1 will cause
- //! the entire string to be rendered (subject to clipping).
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- GrStringDraw(const tContext *pContext, const char *pcString, int lLength,
- int lX, int lY, unsigned int bOpaque)
- {
- int lIdx, lX0, lY0, lCount, lOff, lOn, lBit;
- const unsigned char *pucData;
- tContext sCon;
- //
- // Check the arguments.
- //
- ASSERT(pContext);
- ASSERT(pcString);
- //
- // Copy the drawing context into a local structure that can be modified.
- //
- sCon = *pContext;
- //
- // Loop through the characters in the string.
- //
- while(*pcString && lLength--)
- {
- //
- // Stop drawing the string if the right edge of the clipping region has
- // been exceeded.
- //
- if(lX > sCon.sClipRegion.sXMax)
- {
- break;
- }
- //
- // Get a pointer to the font data for the next character from the
- // string. If there is not a glyph for the next character, replace it
- // with a ".".
- //
- if((*pcString >= ' ') && (*pcString <= '~'))
- {
- pucData = (sCon.pFont->pucData +
- sCon.pFont->pusOffset[*pcString++ - ' ']);
- }
- else
- {
- pucData = (sCon.pFont->pucData +
- sCon.pFont->pusOffset[ABSENT_CHAR_REPLACEMENT - ' ']);
- pcString++;
- }
- //
- // See if the entire character is to the left of the clipping region.
- //
- if((lX + pucData[1]) < sCon.sClipRegion.sXMin)
- {
- //
- // Increment the X coordinate by the width of the character.
- //
- lX += pucData[1];
- //
- // Go to the next character in the string.
- //
- continue;
- }
- //
- // Loop through the bytes in the encoded data for this glyph.
- //
- for(lIdx = 2, lX0 = 0, lBit = 0, lY0 = 0; lIdx < pucData[0]; )
- {
- //
- // See if the bottom of the clipping region has been exceeded.
- //
- if((lY + lY0) > sCon.sClipRegion.sYMax)
- {
- //
- // Stop drawing this character.
- //
- break;
- }
- //
- // See if the font is uncompressed.
- //
- if(sCon.pFont->ucFormat == FONT_FMT_UNCOMPRESSED)
- {
- //
- // Count the number of off pixels from this position in the
- // glyph image.
- //
- for(lOff = 0; lIdx < pucData[0]; )
- {
- //
- // Get the number of zero pixels at this position.
- //
- lCount = NumLeadingZeros(pucData[lIdx] << (24 + lBit));
- //
- // If there were more than 8, then it is a "false" result
- // since it counted beyond the end of the current byte.
- // Therefore, simply limit it to the number of pixels
- // remaining in this byte.
- //
- if(lCount > 8)
- {
- lCount = 8 - lBit;
- }
- //
- // Increment the number of off pixels.
- //
- lOff += lCount;
- //
- // Increment the bit position within the byte.
- //
- lBit += lCount;
- //
- // See if the end of the byte has been reached.
- //
- if(lBit == 8)
- {
- //
- // Advance to the next byte and continue counting off
- // pixels.
- //
- lBit = 0;
- lIdx++;
- }
- else
- {
- //
- // Since the end of the byte was not reached, there
- // must be an on pixel. Therefore, stop counting off
- // pixels.
- //
- break;
- }
- }
- //
- // Count the number of on pixels from this position in the
- // glyph image.
- //
- for(lOn = 0; lIdx < pucData[0]; )
- {
- //
- // Get the number of one pixels at this location (by
- // inverting the data and counting the number of zeros).
- //
- lCount = NumLeadingZeros(~(pucData[lIdx] << (24 + lBit)));
- //
- // If there were more than 8, then it is a "false" result
- // since it counted beyond the end of the current byte.
- // Therefore, simply limit it to the number of pixels
- // remaining in this byte.
- //
- if(lCount > 8)
- {
- lCount = 8 - lBit;
- }
- //
- // Increment the number of on pixels.
- //
- lOn += lCount;
- //
- // Increment the bit position within the byte.
- //
- lBit += lCount;
- //
- // See if the end of the byte has been reached.
- //
- if(lBit == 8)
- {
- //
- // Advance to the next byte and continue counting on
- // pixels.
- //
- lBit = 0;
- lIdx++;
- }
- else
- {
- //
- // Since the end of the byte was not reached, there
- // must be an off pixel. Therefore, stop counting on
- // pixels.
- //
- break;
- }
- }
- }
- //
- // Otherwise, the font is compressed with a pixel RLE scheme.
- //
- else
- {
- //
- // See if this is a byte that encodes some on and off pixels.
- //
- if(pucData[lIdx])
- {
- //
- // Extract the number of off pixels.
- //
- lOff = (pucData[lIdx] >> 4) & 15;
- //
- // Extract the number of on pixels.
- //
- lOn = pucData[lIdx] & 15;
- //
- // Skip past this encoded byte.
- //
- lIdx++;
- }
- //
- // Otherwise, see if this is a repeated on pixel byte.
- //
- else if(pucData[lIdx + 1] & 0x80)
- {
- //
- // There are no off pixels in this encoding.
- //
- lOff = 0;
- //
- // Extract the number of on pixels.
- //
- lOn = (pucData[lIdx + 1] & 0x7f) * 8;
- //
- // Skip past these two encoded bytes.
- //
- lIdx += 2;
- }
- //
- // Otherwise, this is a repeated off pixel byte.
- //
- else
- {
- //
- // Extract the number of off pixels.
- //
- lOff = pucData[lIdx + 1] * 8;
- //
- // There are no on pixels in this encoding.
- //
- lOn = 0;
- //
- // Skip past these two encoded bytes.
- //
- lIdx += 2;
- }
- }
- //
- // Loop while there are any off pixels.
- //
- while(lOff)
- {
- //
- // See if the bottom of the clipping region has been exceeded.
- //
- if((lY + lY0) > sCon.sClipRegion.sYMax)
- {
- //
- // Ignore the remainder of the on pixels.
- //
- break;
- }
- //
- // See if there is more than one on pixel that will fit onto
- // the current row.
- //
- if((lOff > 1) && ((lX0 + 1) < pucData[1]))
- {
- //
- // Determine the number of on pixels that will fit on this
- // row.
- //
- lCount = (((lX0 + lOff) > pucData[1]) ? pucData[1] - lX0 :
- lOff);
- //
- // If this row is within the clipping region, draw a
- // horizontal line that corresponds to the sequence of on
- // pixels.
- //
- if(((lY + lY0) >= sCon.sClipRegion.sYMin) && bOpaque)
- {
- sCon.ulForeground = pContext->ulBackground;
- GrLineDrawH(&sCon, lX + lX0, lX + lX0 + lCount - 1,
- lY + lY0);
- }
- //
- // Decrement the count of on pixels by the number on this
- // row.
- //
- lOff -= lCount;
- //
- // Increment the X offset by the number of on pixels.
- //
- lX0 += lCount;
- }
- //
- // Otherwise, there is only a single on pixel that can be
- // drawn.
- //
- else
- {
- //
- // If this pixel is within the clipping region, then draw
- // it.
- //
- if(((lX + lX0) >= sCon.sClipRegion.sXMin) &&
- ((lX + lX0) <= sCon.sClipRegion.sXMax) &&
- ((lY + lY0) >= sCon.sClipRegion.sYMin) && bOpaque)
- {
- DpyPixelDraw(pContext->pDisplay, lX + lX0, lY + lY0,
- pContext->ulBackground);
- }
- //
- // Decrement the count of on pixels.
- //
- lOff--;
- //
- // Increment the X offset.
- //
- lX0++;
- }
- //
- // See if the X offset has reached the right side of the
- // character glyph.
- //
- if(lX0 == pucData[1])
- {
- //
- // Increment the Y offset.
- //
- lY0++;
- //
- // Reset the X offset to the left side of the character
- // glyph.
- //
- lX0 = 0;
- }
- }
- //
- // Loop while there are any on pixels.
- //
- while(lOn)
- {
- //
- // See if the bottom of the clipping region has been exceeded.
- //
- if((lY + lY0) > sCon.sClipRegion.sYMax)
- {
- //
- // Ignore the remainder of the on pixels.
- //
- break;
- }
- //
- // See if there is more than one on pixel that will fit onto
- // the current row.
- //
- if((lOn > 1) && ((lX0 + 1) < pucData[1]))
- {
- //
- // Determine the number of on pixels that will fit on this
- // row.
- //
- lCount = (((lX0 + lOn) > pucData[1]) ? pucData[1] - lX0 :
- lOn);
- //
- // If this row is within the clipping region, draw a
- // horizontal line that corresponds to the sequence of on
- // pixels.
- //
- if((lY + lY0) >= sCon.sClipRegion.sYMin)
- {
- sCon.ulForeground = pContext->ulForeground;
- GrLineDrawH(&sCon, lX + lX0, lX + lX0 + lCount - 1,
- lY + lY0);
- }
- //
- // Decrement the count of on pixels by the number on this
- // row.
- //
- lOn -= lCount;
- //
- // Increment the X offset by the number of on pixels.
- //
- lX0 += lCount;
- }
- //
- // Otherwise, there is only a single on pixel that can be
- // drawn.
- //
- else
- {
- //
- // If this pixel is within the clipping region, then draw
- // it.
- //
- if(((lX + lX0) >= sCon.sClipRegion.sXMin) &&
- ((lX + lX0) <= sCon.sClipRegion.sXMax) &&
- ((lY + lY0) >= sCon.sClipRegion.sYMin))
- {
- DpyPixelDraw(pContext->pDisplay, lX + lX0, lY + lY0,
- pContext->ulForeground);
- }
- //
- // Decrement the count of on pixels.
- //
- lOn--;
- //
- // Increment the X offset.
- //
- lX0++;
- }
- //
- // See if the X offset has reached the right side of the
- // character glyph.
- //
- if(lX0 == pucData[1])
- {
- //
- // Increment the Y offset.
- //
- lY0++;
- //
- // Reset the X offset to the left side of the character
- // glyph.
- //
- lX0 = 0;
- }
- }
- }
- //
- // Increment the X coordinate by the width of the character.
- //
- lX += pucData[1];
- }
- }
- //*****************************************************************************
- //
- // Definitions and variables used by the decompression routine for the string
- // table.
- //
- //*****************************************************************************
- #define SC_MAX_INDEX 2047
- #define SC_IS_NULL 0x0000ffff
- #define SC_GET_LEN(v) ((v) >> (32 - 5))
- #define SC_GET_INDEX(v) (((v) >> 16) & SC_MAX_INDEX)
- #define SC_GET_OFF(v) ((v) & SC_IS_NULL)
- #define SC_FLAG_COMPRESSED 0x00008000
- #define SC_OFFSET_M 0x00007fff
- //*****************************************************************************
- //
- // The globals that hold the shortcuts to various locations and values in the
- // table.
- //
- //*****************************************************************************
- static const unsigned int *g_pulStringTable;
- static const unsigned short *g_pusLanguageTable;
- static const unsigned char *g_pucStringData;
- static unsigned short g_usLanguage;
- static unsigned short g_usNumLanguages;
- static unsigned short g_usNumStrings;
- //*****************************************************************************
- //
- //! This function sets the location of the current string table.
- //!
- //! \param pvTable is a pointer to a string table that was generated by the
- //! string compression utility.
- //!
- //! This function is used to set the string table to use for strings in an
- //! application. This string table is created by the string compression
- //! utility. This function is used to swap out multiple string tables if the
- //! application requires more than one table. It does not allow using more
- //! than one string table at a time.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- GrStringTableSet(const void *pvTable)
- {
- //
- // Save the number of languages and number of strings.
- //
- g_usNumStrings = ((unsigned short *)pvTable)[0];
- g_usNumLanguages = ((unsigned short *)pvTable)[1];
- //
- // Save a pointer to the Language Identifier table.
- //
- g_pusLanguageTable = (unsigned short *)pvTable + 2;
- //
- // Save a pointer to the String Index table.
- //
- g_pulStringTable = (unsigned int *)(g_pusLanguageTable +
- g_usNumLanguages);
- //
- // Save a pointer to the String Data.
- //
- g_pucStringData = (unsigned char *)(g_pulStringTable +
- (g_usNumStrings * g_usNumLanguages));
- }
- //*****************************************************************************
- //
- //! This function sets the current language for strings returned by the
- //! GrStringGet() function.
- //!
- //! \param usLangID is one of the language identifiers provided in the string
- //! table.
- //!
- //! This function is used to set the language identifier for the strings
- //! returned by the GrStringGet() function. The \e usLangID parameter should
- //! match one of the identifiers that was included in the string table. These
- //! are provided in a header file in the graphics library and must match the
- //! values that were passed through the sting compression utility.
- //!
- //! \return This function returns 0 if the language was not found and a
- //! non-zero value if the laguage was found.
- //
- //*****************************************************************************
- unsigned int
- GrStringLanguageSet(unsigned short usLangID)
- {
- int iLang;
- //
- // Search for the requested language.
- //
- for(iLang = 0; iLang < g_usNumLanguages; iLang++)
- {
- //
- // Once found, break out and save the new language.
- //
- if(g_pusLanguageTable[iLang] == usLangID)
- {
- break;
- }
- }
- //
- // Only accept the language if it was found, otherwise continue using
- // previous language.
- //
- if(iLang != g_usNumLanguages)
- {
- g_usLanguage = iLang;
- return(1);
- }
- return(0);
- }
- //*****************************************************************************
- //
- //! This function returns a string from the current string table.
- //!
- //! \param iIndex is the index of the string to retrieve.
- //! \param pcData is the pointer to the buffer to store the string into.
- //! \param ulSize is the size of the buffer provided by pcData.
- //!
- //! This function will return a string from the string table in the language
- //! set by the GrStringLanguageSet() function. The value passed in \e iIndex
- //! parameter is the string that is being requested and will be returned in
- //! the buffer provided in the \e pcData parameter. The amount of data
- //! returned will be limited by the ulSize parameter.
- //!
- //! \return Returns the number of valid bytes returned in the \e pcData buffer.
- //
- //*****************************************************************************
- unsigned int
- GrStringGet(int iIndex, char *pcData, unsigned int ulSize)
- {
- unsigned int ulLen, ulOffset, ulSubCode[16];
- int iPos, iIdx, iBit, iSkip, iBuf;
- unsigned char *pucBufferOut;
- const unsigned char *pucString;
- ASSERT(iIndex < g_usNumStrings);
- ASSERT(pcData != 0);
- //
- // Initialize the output buffer state.
- //
- iPos = 0;
- pucBufferOut = 0;
- //
- // if built up from another string, we need to process that
- // this could nest multiple layers, so we follow in
- //
- ulSubCode[iPos] = g_pulStringTable[(g_usLanguage * g_usNumStrings) +
- iIndex];
- if(SC_GET_LEN(ulSubCode[iPos]))
- {
- //
- // recurse down
- //
- while(iPos < 16)
- {
- //
- // Copy over the partial (if any) from a previous string.
- //
- iIdx = SC_GET_INDEX(ulSubCode[iPos++]);
- ulSubCode[iPos] = g_pulStringTable[(g_usLanguage *
- g_usNumStrings) + iIdx];
- if(!SC_GET_LEN(ulSubCode[iPos]))
- {
- //
- // not linked, just string
- //
- break;
- }
- }
- }
- //
- // Now work backwards out.
- //
- iIdx = 0;
- //
- // Build up the string in pieces.
- //
- while(iPos >= 0)
- {
- //
- // Get the offset in string table.
- //
- ulOffset = SC_GET_OFF(ulSubCode[iPos]);
- if(ulOffset == SC_IS_NULL)
- {
- //
- // An empty string.
- //
- pcData[iIdx] = 0;
- }
- else if(ulOffset & SC_FLAG_COMPRESSED)
- {
- //
- // This is a compressed string so initialize the pointer to the
- // compressed data.
- //
- pucString = g_pucStringData + (ulOffset & SC_OFFSET_M);
- //
- // Initialize the bit variables.
- //
- iBit = 0;
- iSkip = 0;
- //
- // Make a pointer to the current buffer out location.
- //
- pucBufferOut = (unsigned char *)pcData + iIdx;
- //
- // If the out buffer is beyond the maximum size then just break
- // out and return what we have so far.
- //
- if((char *)pucBufferOut > (pcData + ulSize))
- {
- break;
- }
- //
- // Now build up real string by decompressing bits.
- //
- if(!SC_GET_LEN(ulSubCode[iPos]) && SC_GET_INDEX(ulSubCode[iPos]))
- {
- iSkip = SC_GET_INDEX(ulSubCode[iPos]);
- if(iPos)
- {
- ulLen = SC_GET_LEN(ulSubCode[iPos-1]);
- }
- else
- {
- ulLen = (iSkip & 0x3f);
- }
- iSkip >>= 6;
- iIdx += ulLen;
- ulLen += iSkip;
- }
- else if(iPos)
- {
- //
- // Get the length of the partial string.
- //
- ulLen = SC_GET_LEN(ulSubCode[iPos-1]) - iIdx;
- iIdx += ulLen;
- }
- else if(!SC_GET_LEN(ulSubCode[0]) && SC_GET_INDEX(ulSubCode[0]))
- {
- ulLen = SC_GET_INDEX(ulSubCode[0]);
- iSkip = ulLen >> 6;
- ulLen = (ulLen & 0x3f) + iSkip;
- }
- else
- {
- //
- // Arbitrary as null character ends the string.
- //
- ulLen = 1024;
- }
- for(; ulLen; ulLen--)
- {
- //
- // Packed 6 bits for each char
- //
- *pucBufferOut = (*pucString >> iBit) & 0x3f;
- if(iBit >= 2)
- {
- *pucBufferOut |= (*++pucString << (8-iBit)) & 0x3f;
- }
- iBit = (iBit + 6) & 0x7;
- if(!*pucBufferOut)
- {
- //
- // end of string
- //
- break;
- }
- if(iSkip)
- {
- iSkip--;
- continue;
- }
- //
- // Put back removed bit
- //
- *pucBufferOut |= 0x40;
- //
- // Now look for a few special chars we mapped up into other
- // characters.
- //
- if(*pucBufferOut == '`')
- {
- *pucBufferOut = ' ';
- }
- else if(*pucBufferOut == '~')
- {
- *pucBufferOut = '-';
- }
- else if(*pucBufferOut == 0x7f)
- {
- *pucBufferOut = '.';
- }
- else if(*pucBufferOut == '\\')
- {
- *pucBufferOut = ':';
- }
- //
- // Increment the pointer and break out if the pointer is now
- // beyond the end of the buffer provided.
- //
- pucBufferOut++;
- if((char *)pucBufferOut >= (pcData + ulSize))
- {
- break;
- }
- }
- }
- else if(iPos)
- {
- //
- // Part of another string
- //
- ulLen = SC_GET_LEN(ulSubCode[iPos - 1]) - iIdx;
- //
- // Prevent this copy from going beyond the end of the buffer
- // provided.
- //
- if((iIdx + ulLen) > ulSize)
- {
- ulLen = ulSize - iIdx;
- }
- //
- // Copy this portion of the string to the output buffer.
- //
- for(iBuf = 0; iBuf < ulLen; iBuf++)
- {
- pcData[iIdx + iBuf] = g_pucStringData[ulOffset + iBuf];
- }
- iIdx += ulLen;
- }
- else if(SC_GET_INDEX(ulSubCode[0]) && !SC_GET_LEN(ulSubCode[0]))
- {
- //
- // Copy this portion of the string to the output buffer.
- //
- for(iBuf = 0; iBuf < SC_GET_INDEX(ulSubCode[0]); iBuf++)
- {
- if((iIdx + iBuf) < ulSize)
- {
- pcData[iIdx + iBuf] = g_pucStringData[ulOffset + iBuf];
- }
- else
- {
- break;
- }
- }
- }
- else
- {
- //
- // The last piece is the string ending
- //
- for(iBuf = 0; iBuf < (ulSize - iIdx); iBuf++)
- {
- //
- // Copy the string to the output buffer.
- //
- pcData[iIdx + iBuf] = g_pucStringData[ulOffset + iBuf];
- //
- // If a null is hit then terminate the copy.
- //
- if(pcData[iIdx + iBuf] == 0)
- {
- break;
- }
- }
- }
- iPos--;
- }
- //
- // Return the number of bytes copied into the output buffer.
- //
- if(pucBufferOut)
- {
- ulLen = ((unsigned int)pucBufferOut - (unsigned int)pcData);
- //
- // Null terminate the string if there is room.
- //
- if(ulLen < ulSize)
- {
- pcData[ulLen] = 0;
- }
- }
- else
- {
- ulLen = 0;
- }
- return(ulLen);
- }
- //*****************************************************************************
- //
- // Close the Doxygen group.
- //! @}
- //
- //*****************************************************************************
|