Esempio n. 1
0
        /// <summary>
        /// handles the notifications send by npp and scintilla to the plugin
        /// </summary>
        public static void OnNppNotification(SCNotification nc)
        {
            try {
                uint code = nc.nmhdr.code;

                // Plugin waiting to be started...
                if (!PluginIsReady)
                {
                    switch (code)
                    {
                    case (uint)NppNotif.NPPN_TBMODIFICATION:
                        // this is the event that we want to respond to, it sets the toolbar icons
                        UnmanagedExports.NppFuncItems.RefreshItems();
                        Plug.DoNppNeedToolbarImages();
                        return;

                    case (uint)NppNotif.NPPN_READY:
                        // notify plugins that all the procedures of launch of notepad are done
                        ActionsAfterUpdateUi = new Queue <Action>();
                        Npp.UpdateCurrentSci();     // init current scintilla
                        UiThread.Init();
                        PluginIsReady = Plug.DoNppReady();
                        // call OnNppReady then OnPlugReady if it all went ok
                        if (PluginIsReady)
                        {
                            Plug.DoPlugStart();
                            OnNppNotification(new SCNotification((uint)NppNotif.NPPN_BUFFERACTIVATED));      // simulate buffer activated

                            // set hooks on mouse/keyboard
                            SetHooks();
                        }
                        return;

                    case (uint)NppNotif.NPPN_SHUTDOWN:
                        // uninstall hooks on mouse/keyboard
                        UninstallHooks();
                        UiThread.Close();
                        Plug.DoNppShutDown();
                        return;

                    case (uint)NppNotif.NPPN_CANCELSHUTDOWN:
                        PluginIsReady = true;
                        return;
                    }
                }
                else
                {
                    // the plugin is fully loaded and ready to do stuff

                    if ((uint)SciNotif.SCN_NOTIF_BEGIN < code && code < (uint)SciNotif.SCN_NOTIF_END)
                    {
                        switch (code)
                        {
                        // --------------------------------------------------------
                        // Scintilla message
                        // --------------------------------------------------------
                        case (uint)SciNotif.SCN_CHARADDED:
                            // called each time the user add a char in the current scintilla
                            // It's actually better to use the SCI_MODIFIED instead, this notification
                            // is not always called when it should! (ex not called for /t)
                            return;

                        case (uint)SciNotif.SCN_UPDATEUI:
                            while (ActionsAfterUpdateUi.Any())
                            {
                                ActionsAfterUpdateUi.Dequeue()();
                            }
                            Plug.OnSciUpdateUi(nc);
                            return;

                        case (uint)SciNotif.SCN_MODIFIED:
                            // This notification is sent when the text or styling of the document changes or is about to change
                            // (note : this notif isn't sent when the user SWITCHES to tab file (already opened in another tab) !
                            // But it is sent when the user opens a NEW file)
                            bool deletedText            = (nc.modificationType & (int)SciModificationMod.SC_MOD_DELETETEXT) != 0;
                            bool insertedText           = (nc.modificationType & (int)SciModificationMod.SC_MOD_INSERTTEXT) != 0;
                            bool undo                   = (nc.modificationType & (int)SciModificationMod.SC_PERFORMED_UNDO) != 0;
                            bool redo                   = (nc.modificationType & (int)SciModificationMod.SC_PERFORMED_REDO) != 0;
                            bool singleCharModification = false;

                            if ((insertedText || deletedText) && !ScnModifiedDisabled)
                            {
                                var encoding = Sci.Encoding;
                                Npp.CurrentSci.Lines.OnScnModified(nc, !deletedText, encoding);     // register line modifications
                                if (!undo && !redo)
                                {
                                    // if the text has changed
                                    unsafe {
                                        var nbCarets = Sci.Selection.Count;
                                        if (_currentCaret > 0)
                                        {
                                            _currentCaret++;
                                            if (_currentCaret <= nbCarets)
                                            {
                                                return;
                                            }
                                            // then it is the first caret again, we can handle the char
                                            _currentCaret = 0;
                                        }
                                        if (nbCarets > 1)
                                        {
                                            _currentCaret++;
                                        }

                                        // only 1 char appears to be modified
                                        if (nc.length <= 2)
                                        {
                                            // get the char
                                            var bytes   = (byte *)nc.text;
                                            var arrbyte = new byte[nc.length];
                                            int index;
                                            for (index = 0; index < nc.length; index++)
                                            {
                                                arrbyte[index] = bytes[index];
                                            }
                                            var c       = encoding.GetChars(arrbyte);
                                            var cLength = c.Length;
                                            // do we really have a 1 char input?
                                            if (cLength == 1 || (cLength == 2 && c[0] == '\r'))
                                            {
                                                if (insertedText)
                                                {
                                                    ActionsAfterUpdateUi.Enqueue(() => Plug.OnCharAdded(c[0], nc.position));
                                                }
                                                else
                                                {
                                                    ActionsAfterUpdateUi.Enqueue(() => Plug.OnCharDeleted(c[0], nc.position));
                                                }
                                                singleCharModification = true;
                                            }
                                        }
                                    }
                                }
                                ActionsAfterUpdateUi.Enqueue(() => Plug.OnTextModified(nc, insertedText, deletedText, singleCharModification, undo, redo));
                            }

                            return;

                        case (uint)SciNotif.SCN_STYLENEEDED:
                            // if we use the contained lexer, we will receive this notification and we will have to style the text
                            Plug.OnStyleNeeded(Sci.GetEndStyled(), nc.position);
                            return;

                        case (uint)SciNotif.SCN_MARGINCLICK:
                            // called each time the user click on a margin
                            Plug.OnSciMarginClick(nc);
                            return;

                        case (uint)SciNotif.SCN_MODIFYATTEMPTRO:
                            // Code a checkout when trying to modify a read-only file
                            return;

                        case (uint)SciNotif.SCN_DWELLSTART:
                            // when the user hover at a fixed position for too long
                            Plug.OnSciDwellStart();
                            return;

                        case (uint)SciNotif.SCN_DWELLEND:
                            // when he moves his cursor
                            Plug.OnSciDwellEnd();
                            return;
                        }
                    }
                    else if ((uint)NppNotif.NPPN_NOTIF_BEGIN < code && code < (uint)NppNotif.NPPN_NOTIF_END)
                    {
                        // --------------------------------------------------------
                        // Npp message
                        // --------------------------------------------------------
                        switch (code)
                        {
                        case (uint)NppNotif.NPPN_BUFFERACTIVATED:
                            // the user changes the current document (this event is called when the current document is switched (via the tabs)
                            // and also when a new file is opened in npp
                            Npp.UpdateCurrentSci();       // update current scintilla
                            Npp.CurrentSci.Lines.Reset(); // register new lines
                            NppBufferActivated();
                            return;

                        case (uint)NppNotif.NPPN_FILERENAMED:
                            // the user can open a .txt and rename it as a .p
                            NppBufferActivated();
                            return;

                        case (uint)NppNotif.NPPN_FILESAVED:
                            // the user can open a .txt and save it as a .p
                            NppBufferActivated();

                            Plug.DoNppDocumentSaved();
                            return;

                        case (uint)NppNotif.NPPN_FILEBEFORELOAD:
                            // fire when a file is opened
                            // When loading a new file into NPP, the events fired are (in order) :
                            // NPPN_FILEBEFORELOAD > SCN_MODIFIED > NPPN_FILEBEFOREOPEN > NPPN_FILEOPENED > NPPN_BUFFERACTIVATED
                            // we deactivate the SCN_MODIFIED between NPPN_FILEBEFORELOAD and NPPN_FILEBEFOREOPEN
                            ScnModifiedDisabled = true;
                            Plug.DoNppFileBeforeLoad();
                            return;

                        case (uint)NppNotif.NPPN_FILEBEFOREOPEN:
                            ScnModifiedDisabled = false;
                            return;

                        case (uint)NppNotif.NPPN_FILEOPENED:
                            // on file opened
                            Plug.OnNppFileOpened();
                            return;

                        case (uint)NppNotif.NPPN_FILEBEFORECLOSE:
                            // on file closed
                            Plug.OnNppFileBeforeClose();
                            return;

                        case (uint)NppNotif.NPPN_LANGCHANGED:
                            // on lang type changed
                            Plug.OnLangChanged();
                            NppBufferActivated();
                            return;

                        case (uint)NppNotif.NPPN_WORDSTYLESUPDATED:
                            // The styles have been modified
                            Npp.StylersXml.Reload();
                            // unfortunatly, if the user changed of styler.xml file (he selected another theme) then we
                            // will incorrectly read the styles since we have to wait for the config.xml to be updated
                            // and it only updates on npp shutdown
                            return;

                        case (uint)NppNotif.NPPN_BEFORESHUTDOWN:
                            // prevent the plugin from handling a lot of events when npp is about to shutdown
                            PluginIsReady = false;
                            return;
                        }
                    }
                }
            } catch (Exception e) {
                ErrorHandler.ShowErrors(e, "Error in beNotified : code = " + nc.nmhdr.code);
            }
        }
Esempio n. 2
0
 /// <summary>
 /// Reload current file
 /// </summary>
 public void Reload(bool askConfirmation)
 {
     Npp.Reload(Path, askConfirmation);
 }