public virtual void SearchAndExtractSubString(MHObjectRef success, MHSequence <MHParameter> args, MHEngine engine)
 {
     if (args.Size == 5)
     {
         // Find a substring within a string and return an index to the position
         // and the prefix to the substring.
         MHOctetString str          = new MHOctetString();
         MHOctetString searchString = new MHOctetString();
         GetString(args.GetAt(0), str, engine);
         int nStart = GetInt(args.GetAt(1), engine);
         if (nStart < 1)
         {
             nStart = 1;
         }
         GetString(args.GetAt(2), searchString, engine);
         // Strings are indexed from one.
         int nPos;
         for (nPos = nStart - 1; nPos <= str.Size - searchString.Size; nPos++)
         {
             int i;
             for (i = 0; i < searchString.Size; i++)
             {
                 if (searchString.GetAt(i) != str.GetAt(i + nPos))
                 {
                     break;                                               // Doesn't match
                 }
             }
             if (i == searchString.Size)
             {
                 break;                         // Found a match.
             }
         }
         // Set the results.
         MHParameter pResString = args.GetAt(3);
         MHParameter pResInt    = args.GetAt(4);
         SetSuccessFlag(success, true, engine); // Set this first.
         if (nPos <= str.Size - searchString.Size)
         {
             // Found
             // Set the index to the position AFTER the string, counting from 1.
             engine.FindObject(pResInt.GetReference()).SetVariableValue(new MHUnion(nPos + 1 + searchString.Size));
             // Return the sequence from nStart - 1 of length nPos - nStart + 1
             MHOctetString resultString = new MHOctetString(str, nStart - 1, nPos - nStart + 1);
             engine.FindObject(pResString.GetReference()).SetVariableValue(new MHUnion(resultString));
         }
         else
         {
             // Not found.  Set the result string to empty and the result index to -1
             engine.FindObject(pResInt.GetReference()).SetVariableValue(new MHUnion(-1));
             engine.FindObject(pResString.GetReference()).SetVariableValue(new MHUnion(new MHOctetString("")));
         }
     }
     else
     {
         SetSuccessFlag(success, false, engine);
     }
 }
 public virtual void SearchSubString(MHObjectRef success, MHSequence <MHParameter> args, MHEngine engine)
 {
     if (args.Size == 4)
     {
         // Find a substring within a string and return an index to the position.
         MHOctetString str          = new MHOctetString();
         MHOctetString searchString = new MHOctetString();
         GetString(args.GetAt(0), str, engine);
         int nStart = GetInt(args.GetAt(1), engine);
         if (nStart < 1)
         {
             nStart = 1;
         }
         GetString(args.GetAt(2), searchString, engine);
         // Strings are indexed from one.
         int nPos;
         for (nPos = nStart - 1; nPos <= str.Size - searchString.Size; nPos++)
         {
             int i;
             for (i = 0; i < searchString.Size; i++)
             {
                 if (searchString.GetAt(i) != str.GetAt(i + nPos))
                 {
                     break;
                 }
             }
             if (i == searchString.Size)
             {
                 break;                         // Found a match.
             }
         }
         // Set the result.
         MHParameter pResInt = args.GetAt(3);
         SetSuccessFlag(success, true, engine); // Set this first.
         if (nPos <= str.Size - searchString.Size)
         {                                      // Found
             // Set the index to the position of the string, counting from 1.
             engine.FindObject(pResInt.GetReference()).SetVariableValue(new MHUnion(nPos + 1));
         }
         else
         { // Not found.  Set the result index to -1
             engine.FindObject(pResInt.GetReference()).SetVariableValue(new MHUnion(-1));
         }
     }
     else
     {
         SetSuccessFlag(success, false, engine);
     }
 }
Example #3
0
        // UK MHEG. Interpret the font attributes.
        protected void InterpretAttributes(MHOctetString attrs, out int style, out int size, out int lineSpace, out int letterSpace)
        {
            // Set the defaults.
            style = 0; size = 0x18; lineSpace = 0x18; letterSpace = 0;
            if (attrs.Size == 5)            // Short form.
            {
                style     = attrs.GetAt(0); // Only the bottom nibble is significant.
                size      = attrs.GetAt(1);
                lineSpace = attrs.GetAt(2);
                // Is this big-endian or little-endian?  Assume big.
                letterSpace = attrs.GetAt(3) * 256 + attrs.GetAt(4);
                if (letterSpace > 32767)
                {
                    letterSpace -= 65536;                      // Signed.
                }
            }
            else   // Textual form.
            {
                String str = attrs.ToString() + ".";
                Logging.Assert(str != null);
                int q = str.IndexOf('.'); // Find the terminating dot
                if (q != -1)              // plain, italic etc.
                {
                    string type = str.Substring(0, q);
                    str = str.Substring(q + 1);
                    if (type.Equals("italic"))
                    {
                        style = 1;
                    }
                    else if (type.Equals("bold"))
                    {
                        style = 2;
                    }
                    else if (type.Equals("bold-italic"))
                    {
                        style = 3;
                    }
                    // else it's plain.
                    q = str.IndexOf('.');
                }
                if (q != -1)   // Size
                {
                    string s = str.Substring(0, q);
                    str  = str.Substring(q + 1);
                    size = Convert.ToInt32(s);
                    if (size == 0)
                    {
                        size = 0x18;
                    }

                    q = str.IndexOf('.'); // Find the next dot.
                }
                if (q != -1)              // lineSpacing
                {
                    string ls = str.Substring(0, q);
                    str       = str.Substring(q + 1);
                    lineSpace = Convert.ToInt32(ls);
                    if (lineSpace == 0)
                    {
                        size = 0x18;
                    }

                    q = str.IndexOf('.'); // Find the next dot.
                }
                if (q != -1)              // letter spacing.  May be zero or negative
                {
                    string ls = str.Substring(0, q);
                    letterSpace = Convert.ToInt32(ls);
                }
            }
        }
Example #4
0
        // UK MHEG specifies the use of the Tiresias font and broadcasters appear to
        // assume that all MHEG applications will lay the text out in the same way.

        // Recreate the image.
        protected void Redraw()
        {
            if (!RunningStatus || m_pDisplay == null)
            {
                return;
            }
            if (m_nBoxWidth == 0 || m_nBoxHeight == 0)
            {
                return;                                        // Can't draw zero sized boxes.
            }
            m_pDisplay.SetSize(m_nBoxWidth, m_nBoxHeight);
            m_pDisplay.Clear();

            MHRgba textColour = GetColour(m_textColour);
            // Process any escapes in the text and construct the text arrays.
            MHSequence <MHTextLine> theText = new MHSequence <MHTextLine>();
            // Set up the first item on the first line.
            MHTextItem pCurrItem = new MHTextItem();
            MHTextLine pCurrLine = new MHTextLine();

            pCurrLine.Items.Append(pCurrItem);
            theText.Append(pCurrLine);
            Stack <MHRgba> m_ColourStack = new Stack <MHRgba>(); // Stack to handle nested colour codes.

            m_ColourStack.Push(textColour);
            pCurrItem.Colour = textColour;

            int i = 0;

            while (i < m_Content.Size)
            {
                char ch = m_Content.GetAt(i++);

                if (ch == '\t')   // Tab - start a new item if we have any text in the existing one.
                {
                    if (pCurrItem.Text.Size != 0)
                    {
                        pCurrItem = pCurrItem.NewItem();
                        pCurrLine.Items.Append(pCurrItem);
                    }
                    pCurrItem.TabCount++;
                }

                else if (ch == '\r')   // CR - line break.
                // TODO: Two CRs next to one another are treated as </P> rather than <BR><BR>
                // This should also include the sequence CRLFCRLF.
                {
                    pCurrLine = new MHTextLine();
                    theText.Append(pCurrLine);
                    pCurrItem = pCurrItem.NewItem();
                    pCurrLine.Items.Append(pCurrItem);
                }

                else if (ch == 0x1b)   // Escape - special codes.
                {
                    if (i == m_Content.Size)
                    {
                        break;
                    }
                    char code = m_Content.GetAt(i);
                    // The only codes we are interested in are the start and end of colour.
                    // TODO: We may also need "bold" and some hypertext colours.

                    if (code >= 0x40 && code <= 0x5e)   // Start code
                    // Start codes are followed by a parameter count and a number of parameter bytes.
                    {
                        if (++i == m_Content.Size)
                        {
                            break;
                        }
                        char paramCount = m_Content.GetAt(i);
                        i++;
                        if (code == 0x43 && paramCount == 4 && i + paramCount <= m_Content.Size)
                        {
                            // Start of colour.
                            if (pCurrItem.Text.Size != 0)
                            {
                                pCurrItem = pCurrItem.NewItem(); pCurrLine.Items.Append(pCurrItem);
                            }
                            pCurrItem.Colour = new MHRgba(m_Content.GetAt(i), m_Content.GetAt(i + 1),
                                                          m_Content.GetAt(i + 2), 255 - m_Content.GetAt(i + 3));
                            // Push this colour onto the colour stack.
                            m_ColourStack.Push(pCurrItem.Colour);
                        }
                        else
                        {
                            Logging.Log(Logging.MHLogWarning, "Unknown text escape code " + code);
                        }
                        i += paramCount;                   // Skip the parameters
                    }
                    else if (code >= 0x60 && code <= 0x7e) // End code.
                    {
                        i++;
                        if (code == 0x63)
                        {
                            if (m_ColourStack.Count > 1)
                            {
                                m_ColourStack.Pop();
                                // Start a new item since we're using a new colour.
                                if (pCurrItem.Text.Size != 0)
                                {
                                    pCurrItem = pCurrItem.NewItem();
                                    pCurrLine.Items.Append(pCurrItem);
                                }
                                // Set the subsequent text in the colour we're using now.
                                pCurrItem.Colour = m_ColourStack.Peek();
                            }
                        }
                    }
                }

                else if (ch <= 0x1f)
                {
                    // Certain characters including LF and the marker codes between 0x1c and 0x1f are
                    // explicitly intended to be ignored.  Include all the other codes.
                }

                else   // Add to the current text.
                {
                    int nStart = i - 1;
                    while (i < m_Content.Size && m_Content.GetAt(i) >= 0x20)
                    {
                        i++;
                    }
                    pCurrItem.Text.Append(new MHOctetString(m_Content, nStart, i - nStart));
                }
            }


            // Set up the initial attributes.
            int style, size, lineSpace, letterSpace;

            InterpretAttributes(m_fontAttrs, out style, out size, out lineSpace, out letterSpace);
            // Create a font with this information.
            m_pDisplay.SetFont(size, (style & 2) != 0, (style & 1) != 0);

            // Calculate the layout of each section.
            for (i = 0; i < theText.Size; i++)
            {
                MHTextLine pLine = theText.GetAt(i);
                pLine.LineWidth = 0;
                for (int j = 0; j < pLine.Items.Size; j++)
                {
                    MHTextItem pItem = pLine.Items.GetAt(j);
                    // Set any tabs.
                    for (int k = 0; k < pItem.TabCount; k++)
                    {
                        pLine.LineWidth += TABSTOP - pLine.LineWidth % TABSTOP;
                    }

                    if (pItem.UnicodeLength == 0)
                    { // Convert UTF-8 to Unicode.
                        int s = pItem.Text.Size;
                        pItem.Unicode       = pItem.Text.ToString();
                        pItem.UnicodeLength = pItem.Unicode.Length;
                    }
                    // Fit the text onto the line.
                    int nFullText = pItem.UnicodeLength;
                    // Get the box size and update pItem.m_nUnicode to the number that will fit.
                    Rectangle rect = m_pDisplay.GetBounds(pItem.Unicode, ref nFullText, m_nBoxWidth - pLine.LineWidth);
                    if (nFullText == pItem.UnicodeLength || !m_fTextWrap)
                    {
                        // All the characters fit or we're not wrapping.
                        pItem.Width      = rect.Width;
                        pLine.LineWidth += rect.Width;
                    }

                    /*                   else if (m_fTextWrap)
                     *                 { // No, we have to word-wrap.
                     *                     int nTruncated = pItem.UnicodeLength; // Just in case.
                     *                     // Now remove characters until we find a word-break character.
                     *                     while (pItem.UnicodeLength > 0 && pItem.Unicode[pItem.UnicodeLength] != ' ') pItem.UnicodeLength--;
                     *                     // If there are now word-break characters we truncate the text.
                     *                     if (pItem.UnicodeLength == 0) pItem.UnicodeLength = nTruncated;
                     *                     // Special case to avoid infinite loop if the box is very narrow.
                     *                     if (pItem.UnicodeLength == 0) pItem.UnicodeLength = 1;
                     *
                     *                     // We need to move the text we've cut off this line into a new line.
                     *                     int nNewWidth = nFullText - pItem.UnicodeLength;
                     *                     int nNewStart = pItem.UnicodeLength;
                     *                     // Remove any spaces at the start of the new section.
                     *                     while (nNewWidth != 0 && pItem.Unicode[nNewStart] == ' ') { nNewStart++; nNewWidth--; }
                     *                     if (nNewWidth != 0) {
                     *                         // Create a new line from the extra text.
                     *                         MHTextLine pNewLine = new MHTextLine();
                     *                         theText.InsertAt(pNewLine, i+1);
                     *                         // The first item on the new line is the rest of the text.
                     *                         MHTextItem pNewItem = pItem.NewItem();
                     *                         pNewLine.Items.Append(pNewItem);
                     *                         pNewItem.Unicode = pItem.Unicode.Substring(nNewStart, nNewWidth);
                     *                         pNewItem.UnicodeLength = nNewWidth;
                     *                     }
                     *                     // Remove any spaces at the end of the old section.  If we don't do that and
                     *                     // we are centering or right aligning the text we'll get it wrong.
                     *                     while (pItem.UnicodeLength > 1 && pItem.Unicode[pItem.UnicodeLength - 1] == ' ') pItem.UnicodeLength--;
                     *                     int uniLength = pItem.UnicodeLength;
                     *                     rect = m_pDisplay.GetBounds(pItem.Unicode, ref uniLength, 0);
                     *                     pItem.Width = rect.Width;
                     *                     pLine.LineWidth += rect.Width;
                     *                 }
                     */}
            }

            // Now output the text.
            int yOffset = 0;
            // If there isn't space for all the lines we should drop extra lines.
            int nNumLines = theText.Size;

            do
            {
                if (m_VertJ == End)
                {
                    yOffset = m_nBoxHeight - nNumLines * lineSpace;
                }
                else if (m_VertJ == Centre)
                {
                    yOffset = (m_nBoxHeight - nNumLines * lineSpace) / 2;
                }
                if (yOffset < 0)
                {
                    nNumLines--;
                }
            } while (yOffset < 0);

            for (i = 0; i < nNumLines; i++)
            {
                MHTextLine pLine   = theText.GetAt(i);
                int        xOffset = 0;
                if (m_HorizJ == End)
                {
                    xOffset = m_nBoxWidth - pLine.LineWidth;
                }
                else if (m_HorizJ == Centre)
                {
                    xOffset = (m_nBoxWidth - pLine.LineWidth) / 2;
                }
                //ASSERT(xOffset >= 0);

                for (int j = 0; j < pLine.Items.Size; j++)
                {
                    MHTextItem pItem = pLine.Items.GetAt(j);
                    // Tab across if necessary.
                    for (int k = 0; k < pItem.TabCount; k++)
                    {
                        xOffset += TABSTOP - xOffset % TABSTOP;
                    }
                    if (pItem.Unicode.Length != 0)           // We may have blank lines.
                    {
                        m_pDisplay.AddText(xOffset, yOffset, // Jas removed this cos it doesn't make sense yOffset + lineSpace
                                           pItem.Unicode.Substring(0, pItem.UnicodeLength), pItem.Colour);
                    }
                    xOffset += pItem.Width;
                }
                yOffset += lineSpace;
                if (yOffset + lineSpace > m_nBoxHeight)
                {
                    break;
                }
            }
        }
        public virtual void FormatDate(MHObjectRef success, MHSequence <MHParameter> args, MHEngine engine)
        {
            if (args.Size == 4)
            {
                // This is a bit like strftime but not quite.
                MHOctetString format = new MHOctetString();
                GetString(args.GetAt(0), format, engine);
                int date = GetInt(args.GetAt(1), engine); // As produced in GCD
                int time = GetInt(args.GetAt(2), engine);

                string result = "";

                DateTime dt = new DateTime(1858, 11, 17);
                dt = dt.AddDays(date).AddSeconds(time);

                for (int i = 0; i < format.Size; i++)
                {
                    char   ch = format.GetAt(i);
                    string part; // Largest text is 4 chars for a year + null terminator
                    if (ch == '%')
                    {
                        i++;
                        if (i == format.Size)
                        {
                            break;
                        }
                        ch = format.GetAt(i);
                        switch (ch)
                        {
                        case 'Y': part = dt.ToString("yyyy"); break;

                        case 'y': part = dt.ToString("yy"); break;

                        case 'X': part = dt.ToString("MM"); break;

                        case 'x': part = dt.ToString("%M"); break;

                        case 'D': part = dt.ToString("dd"); break;

                        case 'd': part = dt.ToString("%d"); break;

                        case 'H': part = dt.ToString("HH"); break;

                        case 'h': part = dt.ToString("%H"); break;

                        case 'I': part = dt.ToString("hh"); break;

                        case 'i': part = dt.ToString("%h"); break;

                        case 'M': part = dt.ToString("mm"); break;

                        case 'm': part = dt.ToString("%m"); break;

                        case 'S': part = dt.ToString("ss"); break;

                        case 's': part = dt.ToString("%s"); break;

                        // TODO: These really should be localised.
                        case 'A': part = dt.ToString("tt"); break;

                        case 'a': part = dt.ToString("tt").ToLower(); break;

                        default: part = ""; break;
                        }
                        result += part;
                    }
                    else
                    {
                        result += ch;
                    }
                }
                MHOctetString theResult  = new MHOctetString(result);
                MHParameter   pResString = args.GetAt(3);
                engine.FindObject(pResString.GetReference()).SetVariableValue(new MHUnion(theResult));
                SetSuccessFlag(success, true, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }