Example #1
0
        public void EventTriggered(MHRoot pSource, int ev, MHUnion evData)
        {
            Logging.Log(Logging.MHLogLinks, "Event - " + MHLink.EventTypeToString(ev) + " from " + pSource.ObjectIdentifier.Printable());

            switch (ev)
            {
            case MHRoot.EventFirstItemPresented:
            case MHRoot.EventHeadItems:
            case MHRoot.EventHighlightOff:
            case MHRoot.EventHighlightOn:
            case MHRoot.EventIsAvailable:
            case MHRoot.EventIsDeleted:
            case MHRoot.EventIsDeselected:
            case MHRoot.EventIsRunning:
            case MHRoot.EventIsSelected:
            case MHRoot.EventIsStopped:
            case MHRoot.EventItemDeselected:
            case MHRoot.EventItemSelected:
            case MHRoot.EventLastItemPresented:
            case MHRoot.EventTailItems:
            case MHRoot.EventTestEvent:
            case MHRoot.EventTokenMovedFrom:
            case MHRoot.EventTokenMovedTo:
                // Synchronous events.  Fire any links that are waiting.
                // The UK MHEG describes this as the preferred interpretation.  We are checking the link
                // at the time we generate the event rather than queuing the synchronous events until
                // this elementary action is complete.  That matters if we are processing an elementary action
                // which will activate or deactivate links.
                CheckLinks(pSource.ObjectIdentifier, ev, evData);
                break;

            case MHRoot.EventAnchorFired:
            case MHRoot.EventAsyncStopped:
            case MHRoot.EventContentAvailable:
            case MHRoot.EventCounterTrigger:
            case MHRoot.EventCursorEnter:
            case MHRoot.EventCursorLeave:
            case MHRoot.EventEngineEvent:
            case MHRoot.EventEntryFieldFull:
            case MHRoot.EventInteractionCompleted:
            case MHRoot.EventStreamEvent:
            case MHRoot.EventStreamPlaying:
            case MHRoot.EventStreamStopped:
            case MHRoot.EventTimerFired:
            case MHRoot.EventUserInput:
            case MHRoot.EventFocusMoved:         // UK MHEG.  Generated by HyperText class
            case MHRoot.EventSliderValueChanged: // UK MHEG.  Generated by Slider class
            {
                // Asynchronous events.  Add to the event queue.
                MHAsynchEvent pEvent = new MHAsynchEvent();
                pEvent.EventSource = pSource;
                pEvent.EventType   = ev;
                pEvent.EventData   = evData;
                m_EventQueue.Add(pEvent);
            } break;
            }
        }
Example #2
0
 protected override void PrintArgs(TextWriter writer, int nTabs)
 {
     m_EventSource.Print(writer, 0);
     writer.Write(MHLink.EventTypeToString(m_EventType));
     writer.Write(" ");
     if (m_EventData.Type != MHParameter.P_Null)
     {
         m_EventData.Print(writer, 0);
     }
 }
Example #3
0
        // Add and remove links to and from the active link table.
        public void AddLink(MHLink pLink)
        {
#if DEBUG
            // Should not be there already.
            for (int i = 0; i < m_LinkTable.Count; i++)
            {
                Logging.Assert(pLink != m_LinkTable[i]);
            }
#endif
            m_LinkTable.Add(pLink);
        }
Example #4
0
        // Set this up from the parse tree.
        public override void Initialise(MHParseNode p, MHEngine engine)
        {
            // Set to empty before we start (just in case).
            engine.GetGroupId().Copy("");

            base.Initialise(p, engine);

            // Must be an external reference with an object number of zero.
            Logging.Assert(m_ObjectIdentifier.ObjectNo == 0 && m_ObjectIdentifier.GroupId.Size != 0);

            // Set the group id for the rest of the group to this.
            engine.GetGroupId().Copy(m_ObjectIdentifier.GroupId);

            // Some of the information is irrelevant.
            //  MHParseNode pStdId = p.GetNamedArg(C_STANDARD_IDENTIFIER);
            //  MHParseNode pStdVersion = p.GetNamedArg(C_STANDARD_VERSION);
            //  MHParseNode pObjectInfo = p.GetNamedArg(C_OBJECT_INFORMATION);

            MHParseNode pOnStartUp = p.GetNamedArg(ASN1Codes.C_ON_START_UP);

            if (pOnStartUp != null)
            {
                m_StartUp.Initialise(pOnStartUp, engine);
            }
            MHParseNode pOnCloseDown = p.GetNamedArg(ASN1Codes.C_ON_CLOSE_DOWN);

            if (pOnCloseDown != null)
            {
                m_CloseDown.Initialise(pOnCloseDown, engine);
            }
            MHParseNode pOriginalGCPrio = p.GetNamedArg(ASN1Codes.C_ORIGINAL_GC_PRIORITY);

            if (pOriginalGCPrio != null)
            {
                m_nOrigGroupCachePriority = pOriginalGCPrio.GetArgN(0).GetIntValue();
            }

            // Ignore the other stuff at the moment.
            MHParseNode pItems = p.GetNamedArg(ASN1Codes.C_ITEMS);

            if (pItems == null)
            {
                p.Failure("Missing :Items block");
            }
            for (int i = 0; i < pItems.GetArgCount(); i++)
            {
                MHParseNode  pItem       = pItems.GetArgN(i);
                MHIngredient pIngredient = null;

                // Generate the particular kind of ingredient.
                switch (pItem.GetTagNo())
                {
                case ASN1Codes.C_RESIDENT_PROGRAM: pIngredient = new MHResidentProgram(); break;

//  NOT UK                  case ASN1Codes.C_REMOTE_PROGRAM: pIngredient = new MHRemoteProgram(); break;
//  NOT UK                  case ASN1Codes.C_INTERCHANGED_PROGRAM: pIngredient = new MHInterChgProgram(); break;
//  NOT UK                  case ASN1Codes.C_PALETTE: pIngredient = new MHPalette(); break;
//  NOT UK                  case ASN1Codes.C_FONT: pIngredient = new MHFont(); break;
//  NOT UK                  case ASN1Codes.C_CURSOR_SHAPE: pIngredient = new MHCursorShape(); break;
                case ASN1Codes.C_BOOLEAN_VARIABLE: pIngredient = new MHBooleanVar(); break;

                case ASN1Codes.C_INTEGER_VARIABLE: pIngredient = new MHIntegerVar(); break;

                case ASN1Codes.C_OCTET_STRING_VARIABLE: pIngredient = new MHOctetStrVar(); break;

                case ASN1Codes.C_OBJECT_REF_VARIABLE: pIngredient = new MHObjectRefVar(); break;

                case ASN1Codes.C_CONTENT_REF_VARIABLE: pIngredient = new MHContentRefVar(); break;

                case ASN1Codes.C_LINK: pIngredient = new MHLink(); break;

                case ASN1Codes.C_STREAM: pIngredient = new MHStream(); break;

                case ASN1Codes.C_BITMAP: pIngredient = new MHBitmap(); break;

                case ASN1Codes.C_LINE_ART: pIngredient = new MHLineArt(); break;

                case ASN1Codes.C_DYNAMIC_LINE_ART: pIngredient = new MHDynamicLineArt(); break;

                case ASN1Codes.C_RECTANGLE: pIngredient = new MHRectangle(); break;

// NOT UK                   case ASN1Codes.C_HOTSPOT: pIngredient = new MHHotSpot(); break;
// NOT UK                   case ASN1Codes.C_SWITCH_BUTTON: pIngredient = new MHSwitchButton(); break;
// NOT UK                   case ASN1Codes.C_PUSH_BUTTON: pIngredient = new MHPushButton(); break;
                case ASN1Codes.C_TEXT: pIngredient = new MHText(); break;

                case ASN1Codes.C_ENTRY_FIELD: pIngredient = new MHEntryField(); break;

                case ASN1Codes.C_HYPER_TEXT: pIngredient = new MHHyperText(); break;

                case ASN1Codes.C_SLIDER: pIngredient = new MHSlider(); break;

                case ASN1Codes.C_TOKEN_GROUP: pIngredient = new MHTokenGroup(); break;

                case ASN1Codes.C_LIST_GROUP: pIngredient = new MHListGroup(); break;

                default:
                    // So we find out about these when debugging.
                    Logging.Log(Logging.MHLogError, "'" + pItem.GetTagNo() + "' tag not in switch");
                    Logging.Assert(false);

                    // Future proofing: ignore any ingredients that we don't know about.
                    // Obviously these can only arise in the binary coding.
                    break;
                }
                if (pIngredient != null)
                {
                    // Initialise it from its argments.
                    pIngredient.Initialise(pItem, engine);
                    // Remember the highest numbered ingredient
                    if (pIngredient.ObjectIdentifier.ObjectNo > m_nLastId)
                    {
                        m_nLastId = pIngredient.ObjectIdentifier.ObjectNo;
                    }
                    // Add it to the ingedients of this group.
                    m_Items.Append(pIngredient);
                }
            }
        }
Example #5
0
        private void NextSym()
        {
            while (true)
            {
                switch (m_ch)
                {
                case '\n':
                    m_lineCount++; // And drop to next
                    goto case ' ';

                case ' ':
                case '\r':
                case '\t':
                case '\f':
                    // Skip white space.
                    GetNextChar();
                    continue;

                case '/':
                {     // Comment.
                    GetNextChar();
                    if (m_ch != '/')
                    {
                        Error("Malformed comment");
                    }
                    do
                    {
                        GetNextChar();
                    } while (m_ch != '\n' && m_ch != '\f' && m_ch != '\r');
                    continue;     // Next symbol
                }

                case ':': // Start of a tag
                {
                    m_nType = PTTag;
                    char[] buff = new char[MAX_TAG_LENGTH + 1];
                    int    p    = 0;
                    do
                    {
                        buff[p++] = (char)m_ch;
                        GetNextChar();
                        if (p == MAX_TAG_LENGTH)
                        {
                            break;
                        }
                    } while ((m_ch >= 'a' && m_ch <= 'z') || (m_ch >= 'A' && m_ch <= 'Z'));

                    // Look it up and return it if it's found.
                    m_nTag = FindTag(new string(buff, 0, p));
                    if (m_nTag >= 0)
                    {
                        return;
                    }
                    // Unrecognised tag.
                    Error("Unrecognised tag");
                    break;
                }

                case '"': // Start of a string
                {
                    m_nType = PTString;
                    // MHEG strings can include NULLs.  For the moment we pass back the length and also
                    // null-terminate the strings.
                    StringBuilder sb = new StringBuilder();
                    while (true)
                    {
                        GetNextChar();
                        if (m_ch == '"')
                        {
                            break;                  // Finished the string.
                        }
                        if (m_ch == '\\')
                        {
                            GetNextChar();                   // Escape character. Include the next char in the string.
                        }
                        if (m_ch == '\n' || m_ch == '\r')
                        {
                            Error("Unterminated string");
                        }

                        sb.Append((char)m_ch);
                    }
                    GetNextChar();     // Skip the closing quote
                    m_String        = sb.ToString();
                    m_nStringLength = sb.Length;
                    return;
                }

                case '\'': // Start of a string using quoted printable
                {
                    m_nType = PTString;
                    StringBuilder sb = new StringBuilder();
                    // Quotable printable strings contain escape sequences beginning with the
                    // escape character '='.  The strings can span lines but each line must
                    // end with an equal sign.
                    while (true)
                    {
                        GetNextChar();
                        if (m_ch == '\'')
                        {
                            break;
                        }
                        if (m_ch == '\n')
                        {
                            Error("Unterminated string");
                        }
                        if (m_ch == '=')       // Special code in quoted-printable.
                        // Should be followed by two hex digits or by white space and a newline.
                        {
                            GetNextChar();
                            if (m_ch == ' ' || m_ch == '\t' || m_ch == '\r' || m_ch == '\n')
                            {
                                // White space.  Remove everything up to the newline.
                                while (m_ch != '\n')
                                {
                                    if (!(m_ch == ' ' || m_ch == '\t' || m_ch == '\r'))
                                    {
                                        Error("Malformed quoted printable string");
                                    }
                                    GetNextChar();
                                }
                                continue;     // continue with the first character on the next line
                            }
                            else
                            {
                                int nByte = 0;
                                if (m_ch >= '0' && m_ch <= '9')
                                {
                                    nByte = m_ch - '0';
                                }
                                else if (m_ch >= 'A' && m_ch <= 'F')
                                {
                                    nByte = m_ch - 'A' + 10;
                                }
                                else if (m_ch >= 'a' && m_ch <= 'f')
                                {
                                    nByte = m_ch - 'a' + 10;
                                }
                                else
                                {
                                    Error("Malformed quoted printable string");
                                }
                                nByte *= 16;
                                GetNextChar();
                                if (m_ch >= '0' && m_ch <= '9')
                                {
                                    nByte += m_ch - '0';
                                }
                                else if (m_ch >= 'A' && m_ch <= 'F')
                                {
                                    nByte += m_ch - 'A' + 10;
                                }
                                else if (m_ch >= 'a' && m_ch <= 'f')
                                {
                                    nByte += m_ch - 'a' + 10;
                                }
                                else
                                {
                                    Error("Malformed quoted printable string");
                                }
                                m_ch = nByte;     // Put this into the string.
                            }
                        }
                        // We grow the buffer to the largest string in the input.

                        sb.Append((char)m_ch);
                    }
                    GetNextChar();     // Skip the closing quote
                    m_String        = sb.ToString();
                    m_nStringLength = sb.Length;
                    return;
                }

                case '`':                  // Start of a string using base 64
                    // These can, presumably span lines.
                    Logging.Assert(false); // TODO
                    break;

                case '#':                  // Start of 3-byte hex constant.
                    Logging.Assert(false); // TODO
                    break;

                case '-':
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                {
                    m_nType = PTInt;
                    bool negative = m_ch == '-';
                    if (negative)
                    {
                        GetNextChar();
                        if (m_ch < '0' || m_ch > '9')
                        {
                            Error("Expected digit after '-'");
                        }
                    }
                    // Start of a number.  Hex can be represented as 0xn.
                    // Strictly speaking hex values cannot be preceded by a minus sign.
                    m_nInt = m_ch - '0';
                    GetNextChar();
                    if (m_nInt == 0 && (m_ch == 'x' || m_ch == 'X'))
                    {
                        throw new MHEGException("TODO");
//                            ASSERT(FALSE); // TODO
                    }
                    while (m_ch >= '0' && m_ch <= '9')
                    {
                        m_nInt = m_nInt * 10 + m_ch - '0';
                        // TODO: What about overflow?
                        GetNextChar();
                    }
                    if (negative)
                    {
                        m_nInt = -m_nInt;
                    }
                    return;
                }

                case 'a':
                case 'b':
                case 'c':
                case 'd':
                case 'e':
                case 'f':
                case 'g':
                case 'h':
                case 'i':
                case 'j':
                case 'k':
                case 'l':
                case 'm':
                case 'n':
                case 'o':
                case 'p':
                case 'q':
                case 'r':
                case 's':
                case 't':
                case 'u':
                case 'v':
                case 'w':
                case 'x':
                case 'y':
                case 'z':
                case 'A':
                case 'B':
                case 'C':
                case 'D':
                case 'E':
                case 'F':
                case 'G':
                case 'H':
                case 'I':
                case 'J':
                case 'K':
                case 'L':
                case 'M':
                case 'N':
                case 'O':
                case 'P':
                case 'Q':
                case 'R':
                case 'S':
                case 'T':
                case 'U':
                case 'V':
                case 'W':
                case 'X':
                case 'Y':
                case 'Z':
                {     // Start of an enumerated type.
                    m_nType = PTEnum;
                    char[] buff = new char[MAX_ENUM + 1];
                    int    p    = 0;
                    do
                    {
                        buff[p++] = (char)m_ch;
                        GetNextChar();
                        if (p == MAX_ENUM)
                        {
                            break;
                        }
                    }while ((m_ch >= 'a' && m_ch <= 'z') || (m_ch >= 'A' && m_ch <= 'Z') || m_ch == '-');
                    string b = new string(buff, 0, p);
                    if (b.Equals("NULL"))
                    {
                        m_nType = PTNull; return;
                    }
                    if (b.Equals("true"))
                    {
                        m_nType = PTBool; m_fBool = true; return;
                    }
                    if (b.Equals("false"))
                    {
                        m_nType = PTBool; m_fBool = false; return;
                    }
                    // Look up the tag in all the tables.  Fortunately all the enumerations
                    // are distinct so we don't need to know the context.

                    m_nInt = MHLink.GetEventType(b);
                    if (m_nInt > 0)
                    {
                        return;
                    }

                    m_nInt = MHText.GetJustification(b);
                    if (m_nInt > 0)
                    {
                        return;
                    }
                    m_nInt = MHText.GetLineOrientation(b);
                    if (m_nInt > 0)
                    {
                        return;
                    }
                    m_nInt = MHText.GetStartCorner(b);
                    if (m_nInt > 0)
                    {
                        return;
                    }


                    // Check the colour table.  If it's there generate a string containing the colour info.
                    for (int i = 0; i < colourTable.Length; i++)
                    {
                        if (b.ToLower().Equals(colourTable[i].name))
                        {
                            m_nType = PTString;
                            string str = new string((char)colourTable[i].red, 1);
                            str            += (char)colourTable[i].green;
                            str            += (char)colourTable[i].blue;
                            str            += (char)colourTable[i].alpha;
                            m_String        = str;
                            m_nStringLength = 4;
                            return;
                        }
                    }

                    Error("Unrecognised enumeration");
                    break;
                }

                case '{': // Start of a "section".
                    // The standard indicates that open brace followed by a tag should be written
                    // as a single word.  We'll be more lenient and allow spaces or comments between them.
                    m_nType = PTStartSection;
                    GetNextChar();
                    return;

                case '}': // End of a "section".
                    m_nType = PTEndSection;
                    GetNextChar();
                    return;

                case '(': // Start of a sequence.
                    m_nType = PTStartSeq;
                    GetNextChar();
                    return;

                case ')': // End of a sequence.
                    m_nType = PTEndSeq;
                    GetNextChar();
                    return;

                case -1:
                    m_nType = PTEOF;
                    return;

                default:
                    Error("Unknown character");
                    GetNextChar();
                    break;
                }
            }
        }
Example #6
0
        public void RemoveLink(MHLink pLink)
        {
            bool fRes = m_LinkTable.Remove(pLink);

            Logging.Assert(fRes); // The link should have been there.
        }
Example #7
0
        public int RunAll()
        {
            // Request to boot or reboot
            if (m_fBooting)
            {
                // Reset everything
                m_ApplicationStack.Clear();
                m_EventQueue.Clear();
                m_ExternContentTable.Clear();
                m_LinkTable.Clear();

                // UK MHEG applications boot from ~//a or ~//startup.  Actually the initial
                // object can also be explicitly given in the
                MHObjectRef startObj = new MHObjectRef();
                startObj.ObjectNo = 0;
                startObj.GroupId.Copy(new MHOctetString("~//a"));
                // Launch will block until either it finds the appropriate object and
                // begins the application or discovers that the file definitely isn't
                // present in the carousel.  It is possible that the object might appear
                // if one of the containing directories is updated.
                if (!Launch(startObj))
                {
                    startObj.GroupId.Copy(new MHOctetString("~//startup"));
                    if (!Launch(startObj))
                    {
                        //Logging.Log(Logging.MHLogError, "Unable to launch application");
                        return(-1);
                    }
                }
                m_fBooting = false;
            }

            int nNextTime = 0;

            do
            {
                // Check to see if we need to close.
                if (m_Context.CheckStop())
                {
                    return(0);
                }

                // Run queued actions.
                RunActions();
                // Now the action stack is empty process the next asynchronous event.
                // Processing one event may affect how subsequent events are handled.

                // Check to see if some files we're waiting for have arrived.
                // This could result in ContentAvailable events.
                CheckContentRequests();

                // Check the timers.  This may result in timer events being raised.
                if (CurrentScene() != null)
                {
                    int next = CurrentScene().CheckTimers(this);
                    if (nNextTime == 0 || nNextTime > next)
                    {
                        nNextTime = next;
                    }
                }
                if (CurrentApp() != null)
                {
                    // The UK MHEG profile allows applications to have timers.
                    int nAppTime = CurrentApp().CheckTimers(this);
                    if (nAppTime != 0 && (nNextTime == 0 || nAppTime < nNextTime))
                    {
                        nNextTime = nAppTime;
                    }
                }
                if (m_ExternContentTable.Count != 0)
                {
                    // If we have an outstanding request for external content we need to set a timer.
                    if (nNextTime == 0 || nNextTime > CONTENT_CHECK_TIME)
                    {
                        nNextTime = CONTENT_CHECK_TIME;
                    }
                }

                if (m_EventQueue.Count != 0)
                {
                    MHAsynchEvent pEvent = m_EventQueue[0];
                    Logging.Log(Logging.MHLogLinks, "Asynchronous event dequeued - " + MHLink.EventTypeToString(pEvent.EventType)
                                + " from " + pEvent.EventSource.ObjectIdentifier.Printable());
                    CheckLinks(pEvent.EventSource.ObjectIdentifier, pEvent.EventType, pEvent.EventData);
                    m_EventQueue.Remove(pEvent);
                }
            } while (m_EventQueue.Count != 0 || m_ActionStack.Count != 0);

            // Redraw the display if necessary.
            if (!IsRegionEmpty(m_redrawRegion))
            {
                m_Context.RequireRedraw(m_redrawRegion);
                m_redrawRegion = new Region();
                m_redrawRegion.MakeEmpty();
            }

            return(nNextTime);
        }