//---------------------------------------------------------------------------
/*
  010 Editor Script to dump strings found in the open file
  2011/03/04 v0.0.1

  Source code put in public domain by Didier Stevens, no Copyright
  https://DidierStevens.com
  Use at your own risk

  History:
    2011/03/02: start development with 010 Editor v3.1.3
    2011/03/03: added UNICODE support
    2011/03/04: added selection
  Todo:

*/
//---------------------------------------------------------------------------

#define MIN_LENGTH 5

int IsPrintable(uchar ucByte)
{
    return ucByte >= 0x20 && ucByte <= 0x7F;
}

void PrintASCIIString(int64 iStart, int64 iEnd)
{
    Printf("A %08x: ", iStart);
    while (iStart < iEnd)
        Printf("%c", ReadByte(iStart++));
    Printf("\n");
}

void SearchASCIIStrings(int64 iStart, int64 iSize)
{
    int64 iIter;
    int64 iStringStart = -1;
    uchar ucByte;

    for (iIter = iStart; iIter - iStart < iSize; iIter++)
    {
        ucByte = ReadUByte(iIter);
        if (IsPrintable(ucByte))
        {
            if (iStringStart == -1)
                iStringStart = iIter;
            else if (iIter - iStart + 1 == iSize && iIter - iStringStart + 1 >= MIN_LENGTH)
                PrintASCIIString(iStringStart, iIter + 1);
        }
        else if (iStringStart != -1)
        {
            if (iIter - iStringStart >= MIN_LENGTH)
                PrintASCIIString(iStringStart, iIter);
            iStringStart = -1;
        }
    }
}

void PrintUNICODEString(int64 iStart, int64 iLength)
{
    Printf("U %08x: ", iStart);
    while (iLength > 0)
    {
        Printf("%c", ReadByte(iStart));
        iStart += 2;
        iLength--;
    }
    Printf("\n");
}

int64 CheckForUNICODEString(int64 iStart, int64 iSize)
{
    uchar ucByte1;
    uchar ucByte2;
    int64 iStringLength;

    iStringLength = 0;

    while (1)
    {
        ucByte1 = ReadUByte(iStart + iStringLength * 2);
        if (!IsPrintable(ucByte1))
            return iStringLength;
        if (iStart + iStringLength * 2 + 1 >= iSize)
            return iStringLength;
        ucByte2 = ReadUByte(iStart + iStringLength * 2 + 1);
        if (0 != ucByte2)
            return iStringLength;
        iStringLength++;
    }
}

void SearchUNICODEStrings(int64 iStart, int64 iSize)
{
    int64 iIter;
    int64 iStringLength;

    for (iIter = iStart; iIter - iStart < iSize; 0)
    {
        iStringLength = CheckForUNICODEString(iIter, iStart + iSize);
        if (iStringLength >= MIN_LENGTH)
            PrintUNICODEString(iIter, iStringLength);
        if (0 == iStringLength)
            iIter++;
        else
            iIter += iStringLength * 2;
    }
}

void Main(void)
{
    int64 iStart;
    int64 iSize;

    iSize = GetSelSize();
    if (0 == iSize)
    {
        iStart = 0;
        iSize = FileSize();
    }
    else
        iStart = GetSelStart();
    SearchASCIIStrings(iStart, iSize);
    SearchUNICODEStrings(iStart, iSize);
}

Main();
