DirectMessage() private method

private DirectMessage ( int msg, IntPtr wParam, IntPtr lParam ) : IntPtr
msg int
wParam IntPtr
lParam IntPtr
return IntPtr
Example #1
0
 /// <summary>
 /// Given a document position which is filled with this indicator, will return the document position
 /// where the use of this indicator ends.
 /// </summary>
 /// <param name="position">A zero-based document position using this indicator.</param>
 /// <returns>The zero-based document position where the use of this indicator ends.</returns>
 /// <remarks>
 /// Specifying a <paramref name="position" /> which is not filled with this indicator will cause this method
 /// to return the end position of the range where this indicator is not in use (the negative space). If this
 /// indicator is not in use anywhere within the document the return value will be 0.
 /// </remarks>
 public int End(int position)
 {
     position = Helpers.Clamp(position, 0, scintilla.TextLength);
     position = scintilla.Lines.CharToBytePosition(position);
     position = scintilla.DirectMessage(NativeMethods.SCI_INDICATOREND, new IntPtr(Index), new IntPtr(position)).ToInt32();
     return(scintilla.Lines.ByteToCharPosition(position));
 }
Example #2
0
        /// <summary>
        ///     Removes all text and styles associated with the annotation.
        /// </summary>
        public virtual void Clear()
        {
            CheckInvalid();

            // Remove the annotation
            _scintilla.DirectMessage(NativeMethods.SCI_ANNOTATIONSETTEXT, new IntPtr(_lineIndex), IntPtr.Zero);
        }
Example #3
0
 public void Copy(bool copyLine)
 {
     if (copyLine)
     {
         Scintilla.DirectMessage(NativeMethods.SCI_COPYALLOWLINE, IntPtr.Zero, IntPtr.Zero);
     }
     else
     {
         Scintilla.DirectMessage(NativeMethods.SCI_COPY, IntPtr.Zero, IntPtr.Zero);
     }
 }
Example #4
0
        private static unsafe ArraySegment <byte> GetStyledText(Scintilla scintilla, int startBytePos, int endBytePos, bool addLineBreak)
        {
            Debug.Assert(endBytePos > startBytePos);

            // Make sure the range is styled
            scintilla.DirectMessage(NativeMethods.SCI_COLOURISE, new IntPtr(startBytePos), new IntPtr(endBytePos));

            var byteLength = (endBytePos - startBytePos);
            var buffer     = new byte[(byteLength * 2) + (addLineBreak ? 4 : 0) + 2];

            fixed(byte *bp = buffer)
            {
                NativeMethods.Sci_TextRange *tr = stackalloc NativeMethods.Sci_TextRange[1];
                tr->chrg.cpMin = startBytePos;
                tr->chrg.cpMax = endBytePos;
                tr->lpstrText  = new IntPtr(bp);

                scintilla.DirectMessage(NativeMethods.SCI_GETSTYLEDTEXT, IntPtr.Zero, new IntPtr(tr));
                byteLength *= 2;
            }

            // Add a line break?
            // We do this when this range is part of a rectangular selection.
            if (addLineBreak)
            {
                var style = buffer[byteLength - 1];

                buffer[byteLength++] = (byte)'\r';
                buffer[byteLength++] = style;
                buffer[byteLength++] = (byte)'\n';
                buffer[byteLength++] = style;

                // Fix-up the NULL terminator just in case
                buffer[byteLength]     = 0;
                buffer[byteLength + 1] = 0;
            }

            return(new ArraySegment <byte>(buffer, 0, byteLength));
        }
Example #5
0
        /// <summary>
        ///     Updates the classification of the characters specified.
        /// </summary>
        /// <param name="chars">The characters to reclassify.</param>
        /// <param name="classification">The new classification for the <paramref name="chars" />.</param>
        /// <remarks>
        ///     The default character classifications are suitable for most text and do not affect the lexing process.
        ///     Rather, character classifications specify how the <see cref="Scintilla" /> control interprets
        ///     characters for operations such as skipping or selecting a word. Specifying the classification of
        ///     Unicode characters is not supported.
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="chars" /> is null.</exception>
        /// <exception cref="ArgumentException">
        ///     One or more of the values specified in <paramref name="chars" /> is not an ASCII character.
        /// </exception>
        /// <exception cref="InvalidEnumArgumentException">
        ///     The value assigned to <paramref name="classification" /> is not one of the <see cref="CharClassification" /> values.
        /// </exception>
        public void ReclassifyChars(IEnumerable <char> chars, CharClassification classification)
        {
            if (chars == null)
            {
                throw new ArgumentNullException("chars");
            }

            if (!Enum.IsDefined(typeof(CharClassification), classification))
            {
                throw new InvalidEnumArgumentException("classification", (int)classification, typeof(CharClassification));
            }

            int msg;

            switch (classification)
            {
            case CharClassification.Whitespace:
                msg = NativeMethods.SCI_SETWHITESPACECHARS;
                break;

            case CharClassification.Word:
                msg = NativeMethods.SCI_SETWORDCHARS;
                break;

            default:
                msg = NativeMethods.SCI_SETPUNCTUATIONCHARS;
                break;
            }

            List <byte> bytes = new List <byte>();

            foreach (char c in chars)
            {
                if (c < 0 || c >= 256)
                {
                    throw new ArgumentException(Resources.Exception_MustBeASCII, "value");
                }

                bytes.Add((byte)c);
            }

            // Null terminator
            bytes.Add(0);

            unsafe
            {
                fixed(byte *bp = bytes.ToArray())
                Scintilla.DirectMessage(msg, IntPtr.Zero, (IntPtr)bp);
            }
        }
Example #6
0
        /// <summary>
        /// The number of lines displayed when a line of text is wrapped.
        /// </summary>
        /// <param name="lineIndex">The zero-based index of the line to count.</param>
        /// <returns>The numbers of display lines the line of text occupies.</returns>
        ///// <exception cref="ArgumentOutOfRangeException">
        ///// <paramref name="lineIndex"/> is less than 0 or greater than the line count.
        ///// </exception>
        public virtual int GetWrapCount(int lineIndex)
        {
            //if (lineIndex < 0 || lineIndex > _scintilla.Lines.Count)
            //{
            //    string paramName = "lineIndex";
            //    string message = string.Format(CultureInfo.InvariantCulture, Resources.Exception_MustBeNonNegativeAndLessThan, paramName, "the line count");
            //    throw new ArgumentOutOfRangeException(paramName, message);
            //}

            return(_scintilla.DirectMessage(NativeMethods.SCI_WRAPCOUNT, new IntPtr(lineIndex), IntPtr.Zero).ToInt32());
        }
Example #7
0
        /// <summary>
        /// Sets the marker symbol to a custom image.
        /// </summary>
        /// <param name="image">The Bitmap to use as a marker symbol.</param>
        /// <remarks>Calling this method will also update the <see cref="Symbol" /> property to <see cref="MarkerSymbol.RgbaImage" />.</remarks>
        public unsafe void DefineRgbaImage(Bitmap image)
        {
            if (image == null)
            {
                return;
            }

            scintilla.DirectMessage(NativeMethods.SCI_RGBAIMAGESETWIDTH, new IntPtr(image.Width));
            scintilla.DirectMessage(NativeMethods.SCI_RGBAIMAGESETHEIGHT, new IntPtr(image.Height));

            var bytes = Helpers.BitmapToArgb(image);

            fixed(byte *bp = bytes)
            scintilla.DirectMessage(NativeMethods.SCI_MARKERDEFINERGBAIMAGE, new IntPtr(Index), new IntPtr(bp));
        }
Example #8
0
        internal char[] GetClassificationChars(CharClassification classification)
        {
            Debug.Assert(Enum.IsDefined(typeof(CharClassification), classification));

            int msg;

            switch (classification)
            {
            case CharClassification.Whitespace:
                msg = NativeMethods.SCI_GETWHITESPACECHARS;
                break;

            case CharClassification.Word:
                msg = NativeMethods.SCI_GETWORDCHARS;
                break;

            default:
                msg = NativeMethods.SCI_GETPUNCTUATIONCHARS;
                break;
            }

            char[] chars;

            unsafe
            {
                byte *bp     = stackalloc byte[256]; // Max possible according to Scintilla code
                int   length = (int)Scintilla.DirectMessage(msg, IntPtr.Zero, (IntPtr)bp);
                chars = new char[length];

                for (int i = 0; i < length; i++)
                {
                    chars[i] = (char)bp[i];
                }
            }

            return(chars);
        }
Example #9
0
        private static unsafe List<ArraySegment<byte>> GetStyledSegments(Scintilla scintilla, bool currentSelection, bool currentLine, int startBytePos, int endBytePos, out StyleData[] styles)
        {
            var segments = new List<ArraySegment<byte>>();
            if (currentSelection)
            {
                // Get each selection as a segment.
                // Rectangular selections are ordered top to bottom and have line breaks appended.
                var ranges = new List<Tuple<int, int>>();
                var selCount = scintilla.DirectMessage(NativeMethods.SCI_GETSELECTIONS).ToInt32();
                for (int i = 0; i < selCount; i++)
                {
                    var selStartBytePos = scintilla.DirectMessage(NativeMethods.SCI_GETSELECTIONNSTART, new IntPtr(i)).ToInt32();
                    var selEndBytePos = scintilla.DirectMessage(NativeMethods.SCI_GETSELECTIONNEND, new IntPtr(i)).ToInt32();

                    ranges.Add(Tuple.Create(selStartBytePos, selEndBytePos));
                }

                var selIsRect = scintilla.DirectMessage(NativeMethods.SCI_SELECTIONISRECTANGLE) != IntPtr.Zero;
                if (selIsRect)
                    ranges.OrderBy(r => r.Item1); // Sort top to bottom

                foreach (var range in ranges)
                {
                    var styledText = GetStyledText(scintilla, range.Item1, range.Item2, selIsRect);
                    segments.Add(styledText);
                }
            }
            else if (currentLine)
            {
                // Get the current line
                var mainSelection = scintilla.DirectMessage(NativeMethods.SCI_GETMAINSELECTION).ToInt32();
                var mainCaretPos = scintilla.DirectMessage(NativeMethods.SCI_GETSELECTIONNCARET, new IntPtr(mainSelection)).ToInt32();
                var lineIndex = scintilla.DirectMessage(NativeMethods.SCI_LINEFROMPOSITION, new IntPtr(mainCaretPos)).ToInt32();
                var lineStartBytePos = scintilla.DirectMessage(NativeMethods.SCI_POSITIONFROMLINE, new IntPtr(lineIndex)).ToInt32();
                var lineLength = scintilla.DirectMessage(NativeMethods.SCI_POSITIONFROMLINE, new IntPtr(lineIndex)).ToInt32();

                var styledText = GetStyledText(scintilla, lineStartBytePos, (lineStartBytePos + lineLength), false);
                segments.Add(styledText);
            }
            else // User-specified range
            {
                Debug.Assert(startBytePos != endBytePos);
                var styledText = GetStyledText(scintilla, startBytePos, endBytePos, false);
                segments.Add(styledText);
            }

            // Build a list of (used) styles
            styles = new StyleData[NativeMethods.STYLE_MAX + 1];

            styles[Style.Default].Used = true;
            styles[Style.Default].FontName = scintilla.Styles[Style.Default].Font;
            styles[Style.Default].SizeF = scintilla.Styles[Style.Default].SizeF;
            styles[Style.Default].Weight = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETWEIGHT, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();
            styles[Style.Default].Italic = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETITALIC, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();
            styles[Style.Default].Underline = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETUNDERLINE, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();
            styles[Style.Default].BackColor = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETBACK, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();
            styles[Style.Default].ForeColor = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETFORE, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();
            styles[Style.Default].Case = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETCASE, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();
            styles[Style.Default].Visible = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETVISIBLE, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();

            foreach (var seg in segments)
            {
                for (int i = 0; i < seg.Count; i += 2)
                {
                    var style = seg.Array[i + 1];
                    if (!styles[style].Used)
                    {
                        styles[style].Used = true;
                        styles[style].FontName = scintilla.Styles[style].Font;
                        styles[style].SizeF = scintilla.Styles[style].SizeF;
                        styles[style].Weight = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETWEIGHT, new IntPtr(style), IntPtr.Zero).ToInt32();
                        styles[style].Italic = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETITALIC, new IntPtr(style), IntPtr.Zero).ToInt32();
                        styles[style].Underline = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETUNDERLINE, new IntPtr(style), IntPtr.Zero).ToInt32();
                        styles[style].BackColor = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETBACK, new IntPtr(style), IntPtr.Zero).ToInt32();
                        styles[style].ForeColor = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETFORE, new IntPtr(style), IntPtr.Zero).ToInt32();
                        styles[style].Case = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETCASE, new IntPtr(style), IntPtr.Zero).ToInt32();
                        styles[style].Visible = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETVISIBLE, new IntPtr(style), IntPtr.Zero).ToInt32();
                    }
                }
            }

            return segments;
        }
Example #10
0
        private static unsafe void CopyRtf(Scintilla scintilla, StyleData[] styles, List<ArraySegment<byte>> styledSegments)
        {
            // NppExport -> NppExport.cpp
            // NppExport -> RTFExporter.cpp
            // http://en.wikipedia.org/wiki/Rich_Text_Format
            // https://msdn.microsoft.com/en-us/library/windows/desktop/ms649013.aspx
            // http://forums.codeguru.com/showthread.php?242982-Converting-pixels-to-twips
            // http://en.wikipedia.org/wiki/UTF-8

            try
            {
                // Calculate twips per space
                int twips;
                var fontStyle = FontStyle.Regular;
                if (styles[Style.Default].Weight >= 700)
                    fontStyle |= FontStyle.Bold;
                if (styles[Style.Default].Italic != 0)
                    fontStyle |= FontStyle.Italic;
                if (styles[Style.Default].Underline != 0)
                    fontStyle |= FontStyle.Underline;

                using (var graphics = scintilla.CreateGraphics())
                using (var font = new Font(styles[Style.Default].FontName, styles[Style.Default].SizeF, fontStyle))
                {
                    var width = graphics.MeasureString(" ", font).Width;
                    twips = (int)((width / graphics.DpiX) * 1440);
                    // TODO The twips value calculated seems too small on my computer
                }

                // Write RTF
                using (var ms = new NativeMemoryStream(styledSegments.Sum(s => s.Count)))
                using (var tw = new StreamWriter(ms, Encoding.ASCII))
                {
                    var tabWidth = scintilla.DirectMessage(NativeMethods.SCI_GETTABWIDTH).ToInt32();
                    var deftab = tabWidth * twips;

                    tw.WriteLine(@"{{\rtf1\ansi\deff0\deftab{0}", deftab);
                    tw.Flush();

                    // Build the font table
                    tw.Write(@"{\fonttbl");
                    tw.Write(@"{{\f0 {0};}}", styles[Style.Default].FontName);
                    var fontIndex = 1;
                    for (int i = 0; i < styles.Length; i++)
                    {
                        if (!styles[i].Used)
                            continue;

                        if (i == Style.Default)
                            continue;

                        // Not a completely unique list, but close enough
                        if (styles[i].FontName != styles[Style.Default].FontName)
                        {
                            styles[i].FontIndex = fontIndex++;
                            tw.Write(@"{{\f{0} {1};}}", styles[i].FontIndex, styles[i].FontName);
                        }
                    }
                    tw.WriteLine("}"); // fonttbl
                    tw.Flush();

                    // Build the color table
                    tw.Write(@"{\colortbl");
                    tw.Write(@"\red{0}\green{1}\blue{2};", (styles[Style.Default].ForeColor >> 0) & 0xFF, (styles[Style.Default].ForeColor >> 8) & 0xFF, (styles[Style.Default].ForeColor >> 16) & 0xFF);
                    tw.Write(@"\red{0}\green{1}\blue{2};", (styles[Style.Default].BackColor >> 0) & 0xFF, (styles[Style.Default].BackColor >> 8) & 0xFF, (styles[Style.Default].BackColor >> 16) & 0xFF);
                    styles[Style.Default].ForeColorIndex = 0;
                    styles[Style.Default].BackColorIndex = 1;
                    var colorIndex = 2;
                    for (int i = 0; i < styles.Length; i++)
                    {
                        if (!styles[i].Used)
                            continue;

                        if (i == Style.Default)
                            continue;

                        // Not a completely unique list, but close enough
                        if (styles[i].ForeColor != styles[Style.Default].ForeColor)
                        {
                            styles[i].ForeColorIndex = colorIndex++;
                            tw.Write(@"\red{0}\green{1}\blue{2};", (styles[i].ForeColor >> 0) & 0xFF, (styles[i].ForeColor >> 8) & 0xFF, (styles[i].ForeColor >> 16) & 0xFF);
                        }
                        else
                        {
                            styles[i].ForeColorIndex = styles[Style.Default].ForeColorIndex;
                        }

                        if (styles[i].BackColor != styles[Style.Default].BackColor)
                        {
                            styles[i].BackColorIndex = colorIndex++;
                            tw.Write(@"\red{0}\green{1}\blue{2};", (styles[i].BackColor >> 0) & 0xFF, (styles[i].BackColor >> 8) & 0xFF, (styles[i].BackColor >> 16) & 0xFF);
                        }
                        else
                        {
                            styles[i].BackColorIndex = styles[Style.Default].BackColorIndex;
                        }
                    }
                    tw.WriteLine("}"); // colortbl
                    tw.Flush();

                    // Start with the default style
                    tw.Write(@"\f{0}\fs{1}\cf{2}\chshdng0\chcbpat{3}\cb{3} ", styles[Style.Default].FontIndex, (int)(styles[Style.Default].SizeF * 2), styles[Style.Default].ForeColorIndex, styles[Style.Default].BackColorIndex);
                    if (styles[Style.Default].Italic != 0)
                        tw.Write(@"\i");
                    if (styles[Style.Default].Underline != 0)
                        tw.Write(@"\ul");
                    if (styles[Style.Default].Weight >= 700)
                        tw.Write(@"\b");

                    tw.AutoFlush = true;
                    var lastStyle = Style.Default;
                    var unicodeLineEndings = ((scintilla.DirectMessage(NativeMethods.SCI_GETLINEENDTYPESACTIVE).ToInt32() & NativeMethods.SC_LINE_END_TYPE_UNICODE) > 0);
                    foreach (var seg in styledSegments)
                    {
                        var endOffset = seg.Offset + seg.Count;
                        for (int i = seg.Offset; i < endOffset; i += 2)
                        {
                            var ch = seg.Array[i];
                            var style = seg.Array[i + 1];

                            if (lastStyle != style)
                            {
                                // Change the style
                                if (styles[lastStyle].FontIndex != styles[style].FontIndex)
                                    tw.Write(@"\f{0}", styles[style].FontIndex);
                                if (styles[lastStyle].SizeF != styles[style].SizeF)
                                    tw.Write(@"\fs{0}", (int)(styles[style].SizeF * 2));
                                if (styles[lastStyle].ForeColorIndex != styles[style].ForeColorIndex)
                                    tw.Write(@"\cf{0}", styles[style].ForeColorIndex);
                                if (styles[lastStyle].BackColorIndex != styles[style].BackColorIndex)
                                    tw.Write(@"\chshdng0\chcbpat{0}\cb{0}", styles[style].BackColorIndex);
                                if (styles[lastStyle].Italic != styles[style].Italic)
                                    tw.Write(@"\i{0}", styles[style].Italic != 0 ? "" : "0");
                                if (styles[lastStyle].Underline != styles[style].Underline)
                                    tw.Write(@"\ul{0}", styles[style].Underline != 0 ? "" : "0");
                                if (styles[lastStyle].Weight != styles[style].Weight)
                                {
                                    if (styles[style].Weight >= 700 && styles[lastStyle].Weight < 700)
                                        tw.Write(@"\b");
                                    else if (styles[style].Weight < 700 && styles[lastStyle].Weight >= 700)
                                        tw.Write(@"\b0");
                                }

                                // NOTE: We don't support StyleData.Visible and StyleData.Case in RTF

                                lastStyle = style;
                                tw.Write(" "); // Delimiter
                            }

                            switch (ch)
                            {
                                case (byte)'{':
                                    tw.Write(@"\{");
                                    break;

                                case (byte)'}':
                                    tw.Write(@"\}");
                                    break;

                                case (byte)'\\':
                                    tw.Write(@"\\");
                                    break;

                                case (byte)'\t':
                                    tw.Write(@"\tab ");
                                    break;

                                case (byte)'\r':
                                    if (i + 2 < endOffset)
                                    {
                                        if (seg.Array[i + 2] == (byte)'\n')
                                            i += 2;
                                    }

                                    // Either way, this is a line break
                                    goto case (byte)'\n';

                                case 0xC2:
                                    if (unicodeLineEndings && i + 2 < endOffset)
                                    {
                                        if (seg.Array[i + 2] == 0x85) // NEL \u0085
                                        {
                                            i += 2;
                                            goto case (byte)'\n';
                                        }
                                    }

                                    // Not a Unicode line break
                                    goto default;

                                case 0xE2:
                                    if (unicodeLineEndings && i + 4 < endOffset)
                                    {
                                        if (seg.Array[i + 2] == 0x80 && seg.Array[i + 4] == 0xA8) // LS \u2028
                                        {
                                            i += 4;
                                            goto case (byte)'\n';
                                        }
                                        else if (seg.Array[i + 2] == 0x80 && seg.Array[i + 4] == 0xA9) // PS \u2029
                                        {
                                            i += 4;
                                            goto case (byte)'\n';
                                        }
                                    }

                                    // Not a Unicode line break
                                    goto default;

                                case (byte)'\n':
                                    // All your line breaks are belong to us
                                    tw.WriteLine(@"\par");
                                    break;

                                default:

                                    if (ch == 0)
                                    {
                                        // Scintilla behavior is to allow control characters except for
                                        // NULL which will cause the Clipboard to truncate the string.
                                        tw.Write(" "); // Replace with space
                                        break;
                                    }

                                    if (ch > 0x7F)
                                    {
                                        // Treat as UTF-8 code point
                                        int unicode = 0;
                                        if (ch < 0xE0 && i + 2 < endOffset)
                                        {
                                            unicode |= ((0x1F & ch) << 6);
                                            unicode |= (0x3F & seg.Array[i + 2]);
                                            tw.Write(@"\u{0}?", unicode);
                                            i += 2;
                                            break;
                                        }
                                        else if (ch < 0xF0 && i + 4 < endOffset)
                                        {
                                            unicode |= ((0xF & ch) << 12);
                                            unicode |= ((0x3F & seg.Array[i + 2]) << 6);
                                            unicode |= (0x3F & seg.Array[i + 4]);
                                            tw.Write(@"\u{0}?", unicode);
                                            i += 4;
                                            break;
                                        }
                                        else if (ch < 0xF8 && i + 6 < endOffset)
                                        {
                                            unicode |= ((0x7 & ch) << 18);
                                            unicode |= ((0x3F & seg.Array[i + 2]) << 12);
                                            unicode |= ((0x3F & seg.Array[i + 4]) << 6);
                                            unicode |= (0x3F & seg.Array[i + 6]);
                                            tw.Write(@"\u{0}?", unicode);
                                            i += 6;
                                            break;
                                        }
                                    }

                                    // Regular ANSI char
                                    ms.WriteByte(ch);
                                    break;
                            }
                        }
                    }

                    tw.AutoFlush = false;
                    tw.WriteLine("}"); // rtf1
                    tw.Flush();

                    // Terminator
                    ms.WriteByte(0);

                    // var str = GetString(ms.Pointer, (int)ms.Length, Encoding.ASCII);
                    if (NativeMethods.SetClipboardData(CF_RTF, ms.Pointer) != IntPtr.Zero)
                        ms.FreeOnDispose = false; // Clipboard will free memory
                }
            }
            catch (Exception ex)
            {
                // Yes, we swallow any exceptions. That may seem like code smell but this matches
                // the behavior of the Clipboard class, Windows Forms controls, and native Scintilla.
                Debug.Fail(ex.Message, ex.ToString());
            }
        }
Example #11
0
        private static unsafe void CopyHtml(Scintilla scintilla, StyleData[] styles, List<ArraySegment<byte>> styledSegments)
        {
            // NppExport -> NppExport.cpp
            // NppExport -> HTMLExporter.cpp
            // http://blogs.msdn.com/b/jmstall/archive/2007/01/21/html-clipboard.aspx
            // http://blogs.msdn.com/b/jmstall/archive/2007/01/21/sample-code-html-clipboard.aspx
            // https://msdn.microsoft.com/en-us/library/windows/desktop/ms649015.aspx

            try
            {
                long pos = 0;
                byte[] bytes;

                // Write HTML
                using (var ms = new NativeMemoryStream(styledSegments.Sum(s => s.Count)))
                using (var tw = new StreamWriter(ms, new UTF8Encoding(false)))
                {
                    const int INDEX_START_HTML = 23;
                    const int INDEX_START_FRAGMENT = 65;
                    const int INDEX_END_FRAGMENT = 87;
                    const int INDEX_END_HTML = 41;

                    tw.WriteLine("Version:0.9");
                    tw.WriteLine("StartHTML:00000000");
                    tw.WriteLine("EndHTML:00000000");
                    tw.WriteLine("StartFragment:00000000");
                    tw.WriteLine("EndFragment:00000000");
                    tw.Flush();

                    // Patch header
                    pos = ms.Position;
                    ms.Seek(INDEX_START_HTML, SeekOrigin.Begin);
                    ms.Write((bytes = Encoding.ASCII.GetBytes(ms.Length.ToString("D8"))), 0, bytes.Length);
                    ms.Seek(pos, SeekOrigin.Begin);

                    tw.WriteLine("<html>");
                    tw.WriteLine("<head>");
                    tw.WriteLine(@"<meta charset=""utf-8"" />");
                    tw.WriteLine(@"<title>ScintillaNET v{0}</title>", scintilla.GetType().Assembly.GetName().Version.ToString(3));
                    tw.WriteLine("</head>");
                    tw.WriteLine("<body>");
                    tw.Flush();

                    // Patch header
                    pos = ms.Position;
                    ms.Seek(INDEX_START_FRAGMENT, SeekOrigin.Begin);
                    ms.Write((bytes = Encoding.ASCII.GetBytes(ms.Length.ToString("D8"))), 0, bytes.Length);
                    ms.Seek(pos, SeekOrigin.Begin);
                    tw.WriteLine("<!--StartFragment -->");

                    // Write the styles.
                    // We're doing the style tag in the body to include it in the "fragment".
                    tw.WriteLine(@"<style type=""text/css"" scoped="""">");
                    tw.Write("div#segments {");
                    tw.Write(" float: left;");
                    tw.Write(" white-space: pre;");
                    tw.Write(" line-height: {0}px;", scintilla.DirectMessage(NativeMethods.SCI_TEXTHEIGHT, new IntPtr(0)).ToInt32());
                    tw.Write(" background-color: #{0:X2}{1:X2}{2:X2};", (styles[Style.Default].BackColor >> 0) & 0xFF, (styles[Style.Default].BackColor >> 8) & 0xFF, (styles[Style.Default].BackColor >> 16) & 0xFF);
                    tw.WriteLine(" }");

                    for (int i = 0; i < styles.Length; i++)
                    {
                        if (!styles[i].Used)
                            continue;

                        tw.Write("span.s{0} {{", i);
                        tw.Write(@" font-family: ""{0}"";", styles[i].FontName);
                        tw.Write(" font-size: {0}pt;", styles[i].SizeF);
                        tw.Write(" font-weight: {0};", styles[i].Weight);
                        if (styles[i].Italic != 0)
                            tw.Write(" font-style: italic;");
                        if (styles[i].Underline != 0)
                            tw.Write(" text-decoration: underline;");
                        tw.Write(" background-color: #{0:X2}{1:X2}{2:X2};", (styles[i].BackColor >> 0) & 0xFF, (styles[i].BackColor >> 8) & 0xFF, (styles[i].BackColor >> 16) & 0xFF);
                        tw.Write(" color: #{0:X2}{1:X2}{2:X2};", (styles[i].ForeColor >> 0) & 0xFF, (styles[i].ForeColor >> 8) & 0xFF, (styles[i].ForeColor >> 16) & 0xFF);
                        switch ((StyleCase)styles[i].Case)
                        {
                            case StyleCase.Upper:
                                tw.Write(" text-transform: uppercase;");
                                break;
                            case StyleCase.Lower:
                                tw.Write(" text-transform: lowercase;");
                                break;
                        }

                        if (styles[i].Visible == 0)
                            tw.Write(" visibility: hidden;");
                        tw.WriteLine(" }");
                    }

                    tw.WriteLine("</style>");
                    tw.Write(@"<div id=""segments""><span class=""s{0}"">", Style.Default);
                    tw.Flush();

                    var tabSize = scintilla.DirectMessage(NativeMethods.SCI_GETTABWIDTH).ToInt32();
                    var tab = new string(' ', tabSize);

                    tw.AutoFlush = true;
                    var lastStyle = Style.Default;
                    var unicodeLineEndings = ((scintilla.DirectMessage(NativeMethods.SCI_GETLINEENDTYPESACTIVE).ToInt32() & NativeMethods.SC_LINE_END_TYPE_UNICODE) > 0);
                    foreach (var seg in styledSegments)
                    {
                        var endOffset = seg.Offset + seg.Count;
                        for (int i = seg.Offset; i < endOffset; i += 2)
                        {
                            var ch = seg.Array[i];
                            var style = seg.Array[i + 1];

                            if (lastStyle != style)
                            {
                                tw.Write(@"</span><span class=""s{0}"">", style);
                                lastStyle = style;
                            }

                            switch (ch)
                            {
                                case (byte)'<':
                                    tw.Write("&lt;");
                                    break;

                                case (byte)'>':
                                    tw.Write("&gt;");
                                    break;

                                case (byte)'&':
                                    tw.Write("&amp;");
                                    break;

                                case (byte)'\t':
                                    tw.Write(tab);
                                    break;

                                case (byte)'\r':
                                    if (i + 2 < endOffset)
                                    {
                                        if (seg.Array[i + 2] == (byte)'\n')
                                            i += 2;
                                    }

                                    // Either way, this is a line break
                                    goto case (byte)'\n';

                                case 0xC2:
                                    if (unicodeLineEndings && i + 2 < endOffset)
                                    {
                                        if (seg.Array[i + 2] == 0x85) // NEL \u0085
                                        {
                                            i += 2;
                                            goto case (byte)'\n';
                                        }
                                    }

                                    // Not a Unicode line break
                                    goto default;

                                case 0xE2:
                                    if (unicodeLineEndings && i + 4 < endOffset)
                                    {
                                        if (seg.Array[i + 2] == 0x80 && seg.Array[i + 4] == 0xA8) // LS \u2028
                                        {
                                            i += 4;
                                            goto case (byte)'\n';
                                        }
                                        else if (seg.Array[i + 2] == 0x80 && seg.Array[i + 4] == 0xA9) // PS \u2029
                                        {
                                            i += 4;
                                            goto case (byte)'\n';
                                        }
                                    }

                                    // Not a Unicode line break
                                    goto default;

                                case (byte)'\n':
                                    // All your line breaks are belong to us
                                    tw.Write("\r\n");
                                    break;

                                default:

                                    if (ch == 0)
                                    {
                                        // Scintilla behavior is to allow control characters except for
                                        // NULL which will cause the Clipboard to truncate the string.
                                        tw.Write(" "); // Replace with space
                                        break;
                                    }

                                    ms.WriteByte(ch);
                                    break;
                            }
                        }
                    }

                    tw.AutoFlush = false;
                    tw.WriteLine("</span></div>");
                    tw.Flush();

                    // Patch header
                    pos = ms.Position;
                    ms.Seek(INDEX_END_FRAGMENT, SeekOrigin.Begin);
                    ms.Write((bytes = Encoding.ASCII.GetBytes(ms.Length.ToString("D8"))), 0, bytes.Length);
                    ms.Seek(pos, SeekOrigin.Begin);
                    tw.WriteLine("<!--EndFragment-->");

                    tw.WriteLine("</body>");
                    tw.WriteLine("</html>");
                    tw.Flush();

                    // Patch header
                    pos = ms.Position;
                    ms.Seek(INDEX_END_HTML, SeekOrigin.Begin);
                    ms.Write((bytes = Encoding.ASCII.GetBytes(ms.Length.ToString("D8"))), 0, bytes.Length);
                    ms.Seek(pos, SeekOrigin.Begin);

                    // Terminator
                    ms.WriteByte(0);

                    var str = GetString(ms.Pointer, (int)ms.Length, Encoding.UTF8);
                    if (NativeMethods.SetClipboardData(CF_HTML, ms.Pointer) != IntPtr.Zero)
                        ms.FreeOnDispose = false; // Clipboard will free memory
                }
            }
            catch (Exception ex)
            {
                // Yes, we swallow any exceptions. That may seem like code smell but this matches
                // the behavior of the Clipboard class, Windows Forms controls, and native Scintilla.
                Debug.Fail(ex.Message, ex.ToString());
            }
        }
Example #12
0
        public static void Copy(Scintilla scintilla, CopyFormat format, bool useSelection, bool allowLine, int startBytePos, int endBytePos)
        {
            // Plain text
            if ((format & CopyFormat.Text) > 0)
            {
                if (useSelection)
                {
                    if (allowLine)
                        scintilla.DirectMessage(NativeMethods.SCI_COPYALLOWLINE);
                    else
                        scintilla.DirectMessage(NativeMethods.SCI_COPY);
                }
                else
                {
                    scintilla.DirectMessage(NativeMethods.SCI_COPYRANGE, new IntPtr(startBytePos), new IntPtr(endBytePos));
                }
            }

            // RTF and/or HTML
            if ((format & (CopyFormat.Rtf | CopyFormat.Html)) > 0)
            {
                // If we ever allow more than UTF-8, this will have to be revisited
                Debug.Assert(scintilla.DirectMessage(NativeMethods.SCI_GETCODEPAGE).ToInt32() == NativeMethods.SC_CP_UTF8);

                if (!registeredFormats)
                {
                    // Register non-standard clipboard formats.
                    // Scintilla -> ScintillaWin.cxx
                    // NppExport -> HTMLExporter.h
                    // NppExport -> RTFExporter.h

                    CF_LINESELECT = NativeMethods.RegisterClipboardFormat("MSDEVLineSelect");
                    CF_VSLINETAG = NativeMethods.RegisterClipboardFormat("VisualStudioEditorOperationsLineCutCopyClipboardTag");
                    CF_HTML = NativeMethods.RegisterClipboardFormat("HTML Format");
                    CF_RTF = NativeMethods.RegisterClipboardFormat("Rich Text Format");
                    registeredFormats = true;
                }

                var lineCopy = false;
                StyleData[] styles = null;
                List<ArraySegment<byte>> styledSegments = null;

                if (useSelection)
                {
                    var selIsEmpty = scintilla.DirectMessage(NativeMethods.SCI_GETSELECTIONEMPTY) != IntPtr.Zero;
                    if (selIsEmpty)
                    {
                        if (allowLine)
                        {
                            // Get the current line
                            styledSegments = GetStyledSegments(scintilla, false, true, 0, 0, out styles);
                            lineCopy = true;
                        }
                    }
                    else
                    {
                        // Get every selection
                        styledSegments = GetStyledSegments(scintilla, true, false, 0, 0, out styles);
                    }
                }
                else if (startBytePos != endBytePos)
                {
                    // User-specified range
                    styledSegments = GetStyledSegments(scintilla, false, false, startBytePos, endBytePos, out styles);
                }

                // If we have segments and can open the clipboard
                if (styledSegments != null && styledSegments.Count > 0 && NativeMethods.OpenClipboard(scintilla.Handle))
                {
                    if ((format & CopyFormat.Text) == 0)
                    {
                        // Do the things default (plain text) processing would normally give us
                        NativeMethods.EmptyClipboard();

                        if (lineCopy)
                        {
                            // Clipboard tags
                            NativeMethods.SetClipboardData(CF_LINESELECT, IntPtr.Zero);
                            NativeMethods.SetClipboardData(CF_VSLINETAG, IntPtr.Zero);
                        }
                    }

                    // RTF
                    if ((format & CopyFormat.Rtf) > 0)
                        CopyRtf(scintilla, styles, styledSegments);

                    // HTML
                    if ((format & CopyFormat.Html) > 0)
                        CopyHtml(scintilla, styles, styledSegments);

                    NativeMethods.CloseClipboard();
                }
            }
        }
Example #13
0
 /// <summary>
 /// Removes all text displayed in every <see cref="MarginType.Text" /> and <see cref="MarginType.RightText" /> margins.
 /// </summary>
 public void ClearAllText()
 {
     scintilla.DirectMessage(NativeMethods.SCI_MARGINTEXTCLEARALL);
 }
Example #14
0
 /// <summary>
 ///     Scrolls the display by the specified number of lines and columns.
 /// </summary>
 /// <param name="lines">The number of display lines to scroll. Positive numbers scroll down, negative numbers scroll up.</param>
 /// <param name="columns">The number of columns to scroll. Positive numbers scroll right, negative numbers scroll left.</param>
 public virtual void ScrollBy(int lines, int columns)
 {
     // NOTE: We reverse the order of the params
     _scintilla.DirectMessage(NativeMethods.SCI_LINESCROLL, new IntPtr(columns), new IntPtr(lines));
 }
Example #15
0
        private static unsafe void CopyHtml(Scintilla scintilla, StyleData[] styles, List <ArraySegment <byte> > styledSegments)
        {
            // NppExport -> NppExport.cpp
            // NppExport -> HTMLExporter.cpp
            // http://blogs.msdn.com/b/jmstall/archive/2007/01/21/html-clipboard.aspx
            // http://blogs.msdn.com/b/jmstall/archive/2007/01/21/sample-code-html-clipboard.aspx
            // https://msdn.microsoft.com/en-us/library/windows/desktop/ms649015.aspx

            try
            {
                long   pos = 0;
                byte[] bytes;

                // Write HTML
                using (var ms = new NativeMemoryStream(styledSegments.Sum(s => s.Count)))
                    using (var tw = new StreamWriter(ms, new UTF8Encoding(false)))
                    {
                        const int INDEX_START_HTML     = 23;
                        const int INDEX_START_FRAGMENT = 65;
                        const int INDEX_END_FRAGMENT   = 87;
                        const int INDEX_END_HTML       = 41;

                        tw.WriteLine("Version:0.9");
                        tw.WriteLine("StartHTML:00000000");
                        tw.WriteLine("EndHTML:00000000");
                        tw.WriteLine("StartFragment:00000000");
                        tw.WriteLine("EndFragment:00000000");
                        tw.Flush();

                        // Patch header
                        pos = ms.Position;
                        ms.Seek(INDEX_START_HTML, SeekOrigin.Begin);
                        ms.Write((bytes = Encoding.ASCII.GetBytes(ms.Length.ToString("D8"))), 0, bytes.Length);
                        ms.Seek(pos, SeekOrigin.Begin);

                        tw.WriteLine("<html>");
                        tw.WriteLine("<head>");
                        tw.WriteLine(@"<meta charset=""utf-8"" />");
                        tw.WriteLine(@"<title>ScintillaNET v{0}</title>", scintilla.GetType().Assembly.GetName().Version.ToString(3));
                        tw.WriteLine("</head>");
                        tw.WriteLine("<body>");
                        tw.Flush();

                        // Patch header
                        pos = ms.Position;
                        ms.Seek(INDEX_START_FRAGMENT, SeekOrigin.Begin);
                        ms.Write((bytes = Encoding.ASCII.GetBytes(ms.Length.ToString("D8"))), 0, bytes.Length);
                        ms.Seek(pos, SeekOrigin.Begin);
                        tw.WriteLine("<!--StartFragment -->");

                        // Write the styles.
                        // We're doing the style tag in the body to include it in the "fragment".
                        tw.WriteLine(@"<style type=""text/css"" scoped="""">");
                        tw.Write("div#segments {");
                        tw.Write(" float: left;");
                        tw.Write(" white-space: pre;");
                        tw.Write(" line-height: {0}px;", scintilla.DirectMessage(NativeMethods.SCI_TEXTHEIGHT, new IntPtr(0)).ToInt32());
                        tw.Write(" background-color: #{0:X2}{1:X2}{2:X2};", (styles[Style.Default].BackColor >> 0) & 0xFF, (styles[Style.Default].BackColor >> 8) & 0xFF, (styles[Style.Default].BackColor >> 16) & 0xFF);
                        tw.WriteLine(" }");

                        for (int i = 0; i < styles.Length; i++)
                        {
                            if (!styles[i].Used)
                            {
                                continue;
                            }

                            tw.Write("span.s{0} {{", i);
                            tw.Write(@" font-family: ""{0}"";", styles[i].FontName);
                            tw.Write(" font-size: {0}pt;", styles[i].SizeF);
                            tw.Write(" font-weight: {0};", styles[i].Weight);
                            if (styles[i].Italic != 0)
                            {
                                tw.Write(" font-style: italic;");
                            }
                            if (styles[i].Underline != 0)
                            {
                                tw.Write(" text-decoration: underline;");
                            }
                            tw.Write(" background-color: #{0:X2}{1:X2}{2:X2};", (styles[i].BackColor >> 0) & 0xFF, (styles[i].BackColor >> 8) & 0xFF, (styles[i].BackColor >> 16) & 0xFF);
                            tw.Write(" color: #{0:X2}{1:X2}{2:X2};", (styles[i].ForeColor >> 0) & 0xFF, (styles[i].ForeColor >> 8) & 0xFF, (styles[i].ForeColor >> 16) & 0xFF);
                            switch ((StyleCase)styles[i].Case)
                            {
                            case StyleCase.Upper:
                                tw.Write(" text-transform: uppercase;");
                                break;

                            case StyleCase.Lower:
                                tw.Write(" text-transform: lowercase;");
                                break;
                            }

                            if (styles[i].Visible == 0)
                            {
                                tw.Write(" visibility: hidden;");
                            }
                            tw.WriteLine(" }");
                        }

                        tw.WriteLine("</style>");
                        tw.Write(@"<div id=""segments""><span class=""s{0}"">", Style.Default);
                        tw.Flush();

                        var tabSize = scintilla.DirectMessage(NativeMethods.SCI_GETTABWIDTH).ToInt32();
                        var tab     = new string(' ', tabSize);

                        tw.AutoFlush = true;
                        var lastStyle          = Style.Default;
                        var unicodeLineEndings = ((scintilla.DirectMessage(NativeMethods.SCI_GETLINEENDTYPESACTIVE).ToInt32() & NativeMethods.SC_LINE_END_TYPE_UNICODE) > 0);
                        foreach (var seg in styledSegments)
                        {
                            var endOffset = seg.Offset + seg.Count;
                            for (int i = seg.Offset; i < endOffset; i += 2)
                            {
                                var ch    = seg.Array[i];
                                var style = seg.Array[i + 1];

                                if (lastStyle != style)
                                {
                                    tw.Write(@"</span><span class=""s{0}"">", style);
                                    lastStyle = style;
                                }

                                switch (ch)
                                {
                                case (byte)'<':
                                    tw.Write("&lt;");
                                    break;

                                case (byte)'>':
                                    tw.Write("&gt;");
                                    break;

                                case (byte)'&':
                                    tw.Write("&amp;");
                                    break;

                                case (byte)'\t':
                                    tw.Write(tab);
                                    break;

                                case (byte)'\r':
                                    if (i + 2 < endOffset)
                                    {
                                        if (seg.Array[i + 2] == (byte)'\n')
                                        {
                                            i += 2;
                                        }
                                    }

                                    // Either way, this is a line break
                                    goto case (byte)'\n';

                                case 0xC2:
                                    if (unicodeLineEndings && i + 2 < endOffset)
                                    {
                                        if (seg.Array[i + 2] == 0x85) // NEL \u0085
                                        {
                                            i += 2;
                                            goto case (byte)'\n';
                                        }
                                    }

                                    // Not a Unicode line break
                                    goto default;

                                case 0xE2:
                                    if (unicodeLineEndings && i + 4 < endOffset)
                                    {
                                        if (seg.Array[i + 2] == 0x80 && seg.Array[i + 4] == 0xA8) // LS \u2028
                                        {
                                            i += 4;
                                            goto case (byte)'\n';
                                        }
                                        else if (seg.Array[i + 2] == 0x80 && seg.Array[i + 4] == 0xA9) // PS \u2029
                                        {
                                            i += 4;
                                            goto case (byte)'\n';
                                        }
                                    }

                                    // Not a Unicode line break
                                    goto default;

                                case (byte)'\n':
                                    // All your line breaks are belong to us
                                    tw.Write("\r\n");
                                    break;

                                default:

                                    if (ch == 0)
                                    {
                                        // Scintilla behavior is to allow control characters except for
                                        // NULL which will cause the Clipboard to truncate the string.
                                        tw.Write(" "); // Replace with space
                                        break;
                                    }

                                    ms.WriteByte(ch);
                                    break;
                                }
                            }
                        }

                        tw.AutoFlush = false;
                        tw.WriteLine("</span></div>");
                        tw.Flush();

                        // Patch header
                        pos = ms.Position;
                        ms.Seek(INDEX_END_FRAGMENT, SeekOrigin.Begin);
                        ms.Write((bytes = Encoding.ASCII.GetBytes(ms.Length.ToString("D8"))), 0, bytes.Length);
                        ms.Seek(pos, SeekOrigin.Begin);
                        tw.WriteLine("<!--EndFragment-->");

                        tw.WriteLine("</body>");
                        tw.WriteLine("</html>");
                        tw.Flush();

                        // Patch header
                        pos = ms.Position;
                        ms.Seek(INDEX_END_HTML, SeekOrigin.Begin);
                        ms.Write((bytes = Encoding.ASCII.GetBytes(ms.Length.ToString("D8"))), 0, bytes.Length);
                        ms.Seek(pos, SeekOrigin.Begin);

                        // Terminator
                        ms.WriteByte(0);

                        var str = GetString(ms.Pointer, (int)ms.Length, Encoding.UTF8);
                        if (NativeMethods.SetClipboardData(CF_HTML, ms.Pointer) != IntPtr.Zero)
                        {
                            ms.FreeOnDispose = false; // Clipboard will free memory
                        }
                    }
            }
            catch (Exception ex)
            {
                // Yes, we swallow any exceptions. That may seem like code smell but this matches
                // the behavior of the Clipboard class, Windows Forms controls, and native Scintilla.
                Debug.Fail(ex.Message, ex.ToString());
            }
        }
Example #16
0
 private int GetIndent(ScintillaNET.Scintilla scin, int line)
 {
     return(scin.DirectMessage(SCI_GETLINEINDENTATION, new IntPtr(line), (IntPtr)null).ToInt32());
 }
Example #17
0
 public void Cut()
 {
     Scintilla.DirectMessage(NativeMethods.SCI_CUT, IntPtr.Zero, IntPtr.Zero);
 }
Example #18
0
 private void SetIndent(ScintillaNET.Scintilla scin, int line, int indent)
 {
     scin.DirectMessage(SCI_SETLINEINDENTATION, new IntPtr(line), new IntPtr(indent));
 }
Example #19
0
        private static unsafe List <ArraySegment <byte> > GetStyledSegments(Scintilla scintilla, bool currentSelection, bool currentLine, int startBytePos, int endBytePos, out StyleData[] styles)
        {
            var segments = new List <ArraySegment <byte> >();

            if (currentSelection)
            {
                // Get each selection as a segment.
                // Rectangular selections are ordered top to bottom and have line breaks appended.
                var ranges   = new List <Tuple <int, int> >();
                var selCount = scintilla.DirectMessage(NativeMethods.SCI_GETSELECTIONS).ToInt32();
                for (int i = 0; i < selCount; i++)
                {
                    var selStartBytePos = scintilla.DirectMessage(NativeMethods.SCI_GETSELECTIONNSTART, new IntPtr(i)).ToInt32();
                    var selEndBytePos   = scintilla.DirectMessage(NativeMethods.SCI_GETSELECTIONNEND, new IntPtr(i)).ToInt32();

                    ranges.Add(Tuple.Create(selStartBytePos, selEndBytePos));
                }

                var selIsRect = scintilla.DirectMessage(NativeMethods.SCI_SELECTIONISRECTANGLE) != IntPtr.Zero;
                if (selIsRect)
                {
                    ranges.OrderBy(r => r.Item1); // Sort top to bottom
                }
                foreach (var range in ranges)
                {
                    var styledText = GetStyledText(scintilla, range.Item1, range.Item2, selIsRect);
                    segments.Add(styledText);
                }
            }
            else if (currentLine)
            {
                // Get the current line
                var mainSelection    = scintilla.DirectMessage(NativeMethods.SCI_GETMAINSELECTION).ToInt32();
                var mainCaretPos     = scintilla.DirectMessage(NativeMethods.SCI_GETSELECTIONNCARET, new IntPtr(mainSelection)).ToInt32();
                var lineIndex        = scintilla.DirectMessage(NativeMethods.SCI_LINEFROMPOSITION, new IntPtr(mainCaretPos)).ToInt32();
                var lineStartBytePos = scintilla.DirectMessage(NativeMethods.SCI_POSITIONFROMLINE, new IntPtr(lineIndex)).ToInt32();
                var lineLength       = scintilla.DirectMessage(NativeMethods.SCI_POSITIONFROMLINE, new IntPtr(lineIndex)).ToInt32();

                var styledText = GetStyledText(scintilla, lineStartBytePos, (lineStartBytePos + lineLength), false);
                segments.Add(styledText);
            }
            else // User-specified range
            {
                Debug.Assert(startBytePos != endBytePos);
                var styledText = GetStyledText(scintilla, startBytePos, endBytePos, false);
                segments.Add(styledText);
            }

            // Build a list of (used) styles
            styles = new StyleData[NativeMethods.STYLE_MAX + 1];

            styles[Style.Default].Used      = true;
            styles[Style.Default].FontName  = scintilla.Styles[Style.Default].Font;
            styles[Style.Default].SizeF     = scintilla.Styles[Style.Default].SizeF;
            styles[Style.Default].Weight    = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETWEIGHT, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();
            styles[Style.Default].Italic    = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETITALIC, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();
            styles[Style.Default].Underline = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETUNDERLINE, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();
            styles[Style.Default].BackColor = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETBACK, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();
            styles[Style.Default].ForeColor = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETFORE, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();
            styles[Style.Default].Case      = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETCASE, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();
            styles[Style.Default].Visible   = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETVISIBLE, new IntPtr(Style.Default), IntPtr.Zero).ToInt32();

            foreach (var seg in segments)
            {
                for (int i = 0; i < seg.Count; i += 2)
                {
                    var style = seg.Array[i + 1];
                    if (!styles[style].Used)
                    {
                        styles[style].Used      = true;
                        styles[style].FontName  = scintilla.Styles[style].Font;
                        styles[style].SizeF     = scintilla.Styles[style].SizeF;
                        styles[style].Weight    = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETWEIGHT, new IntPtr(style), IntPtr.Zero).ToInt32();
                        styles[style].Italic    = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETITALIC, new IntPtr(style), IntPtr.Zero).ToInt32();
                        styles[style].Underline = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETUNDERLINE, new IntPtr(style), IntPtr.Zero).ToInt32();
                        styles[style].BackColor = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETBACK, new IntPtr(style), IntPtr.Zero).ToInt32();
                        styles[style].ForeColor = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETFORE, new IntPtr(style), IntPtr.Zero).ToInt32();
                        styles[style].Case      = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETCASE, new IntPtr(style), IntPtr.Zero).ToInt32();
                        styles[style].Visible   = scintilla.DirectMessage(NativeMethods.SCI_STYLEGETVISIBLE, new IntPtr(style), IntPtr.Zero).ToInt32();
                    }
                }
            }

            return(segments);
        }
Example #20
0
        private static unsafe void CopyRtf(Scintilla scintilla, StyleData[] styles, List <ArraySegment <byte> > styledSegments)
        {
            // NppExport -> NppExport.cpp
            // NppExport -> RTFExporter.cpp
            // http://en.wikipedia.org/wiki/Rich_Text_Format
            // https://msdn.microsoft.com/en-us/library/windows/desktop/ms649013.aspx
            // http://forums.codeguru.com/showthread.php?242982-Converting-pixels-to-twips
            // http://en.wikipedia.org/wiki/UTF-8

            try
            {
                // Calculate twips per space
                int twips;
                var fontStyle = FontStyle.Regular;
                if (styles[Style.Default].Weight >= 700)
                {
                    fontStyle |= FontStyle.Bold;
                }
                if (styles[Style.Default].Italic != 0)
                {
                    fontStyle |= FontStyle.Italic;
                }
                if (styles[Style.Default].Underline != 0)
                {
                    fontStyle |= FontStyle.Underline;
                }

                using (var graphics = scintilla.CreateGraphics())
                    using (var font = new Font(styles[Style.Default].FontName, styles[Style.Default].SizeF, fontStyle))
                    {
                        var width = graphics.MeasureString(" ", font).Width;
                        twips = (int)((width / graphics.DpiX) * 1440);
                        // TODO The twips value calculated seems too small on my computer
                    }

                // Write RTF
                using (var ms = new NativeMemoryStream(styledSegments.Sum(s => s.Count)))
                    using (var tw = new StreamWriter(ms, Encoding.ASCII))
                    {
                        var tabWidth = scintilla.DirectMessage(NativeMethods.SCI_GETTABWIDTH).ToInt32();
                        var deftab   = tabWidth * twips;

                        tw.WriteLine(@"{{\rtf1\ansi\deff0\deftab{0}", deftab);
                        tw.Flush();

                        // Build the font table
                        tw.Write(@"{\fonttbl");
                        tw.Write(@"{{\f0 {0};}}", styles[Style.Default].FontName);
                        var fontIndex = 1;
                        for (int i = 0; i < styles.Length; i++)
                        {
                            if (!styles[i].Used)
                            {
                                continue;
                            }

                            if (i == Style.Default)
                            {
                                continue;
                            }

                            // Not a completely unique list, but close enough
                            if (styles[i].FontName != styles[Style.Default].FontName)
                            {
                                styles[i].FontIndex = fontIndex++;
                                tw.Write(@"{{\f{0} {1};}}", styles[i].FontIndex, styles[i].FontName);
                            }
                        }
                        tw.WriteLine("}"); // fonttbl
                        tw.Flush();

                        // Build the color table
                        tw.Write(@"{\colortbl");
                        tw.Write(@"\red{0}\green{1}\blue{2};", (styles[Style.Default].ForeColor >> 0) & 0xFF, (styles[Style.Default].ForeColor >> 8) & 0xFF, (styles[Style.Default].ForeColor >> 16) & 0xFF);
                        tw.Write(@"\red{0}\green{1}\blue{2};", (styles[Style.Default].BackColor >> 0) & 0xFF, (styles[Style.Default].BackColor >> 8) & 0xFF, (styles[Style.Default].BackColor >> 16) & 0xFF);
                        styles[Style.Default].ForeColorIndex = 0;
                        styles[Style.Default].BackColorIndex = 1;
                        var colorIndex = 2;
                        for (int i = 0; i < styles.Length; i++)
                        {
                            if (!styles[i].Used)
                            {
                                continue;
                            }

                            if (i == Style.Default)
                            {
                                continue;
                            }

                            // Not a completely unique list, but close enough
                            if (styles[i].ForeColor != styles[Style.Default].ForeColor)
                            {
                                styles[i].ForeColorIndex = colorIndex++;
                                tw.Write(@"\red{0}\green{1}\blue{2};", (styles[i].ForeColor >> 0) & 0xFF, (styles[i].ForeColor >> 8) & 0xFF, (styles[i].ForeColor >> 16) & 0xFF);
                            }
                            else
                            {
                                styles[i].ForeColorIndex = styles[Style.Default].ForeColorIndex;
                            }

                            if (styles[i].BackColor != styles[Style.Default].BackColor)
                            {
                                styles[i].BackColorIndex = colorIndex++;
                                tw.Write(@"\red{0}\green{1}\blue{2};", (styles[i].BackColor >> 0) & 0xFF, (styles[i].BackColor >> 8) & 0xFF, (styles[i].BackColor >> 16) & 0xFF);
                            }
                            else
                            {
                                styles[i].BackColorIndex = styles[Style.Default].BackColorIndex;
                            }
                        }
                        tw.WriteLine("}"); // colortbl
                        tw.Flush();

                        // Start with the default style
                        tw.Write(@"\f{0}\fs{1}\cf{2}\chshdng0\chcbpat{3}\cb{3} ", styles[Style.Default].FontIndex, (int)(styles[Style.Default].SizeF * 2), styles[Style.Default].ForeColorIndex, styles[Style.Default].BackColorIndex);
                        if (styles[Style.Default].Italic != 0)
                        {
                            tw.Write(@"\i");
                        }
                        if (styles[Style.Default].Underline != 0)
                        {
                            tw.Write(@"\ul");
                        }
                        if (styles[Style.Default].Weight >= 700)
                        {
                            tw.Write(@"\b");
                        }

                        tw.AutoFlush = true;
                        var lastStyle          = Style.Default;
                        var unicodeLineEndings = ((scintilla.DirectMessage(NativeMethods.SCI_GETLINEENDTYPESACTIVE).ToInt32() & NativeMethods.SC_LINE_END_TYPE_UNICODE) > 0);
                        foreach (var seg in styledSegments)
                        {
                            var endOffset = seg.Offset + seg.Count;
                            for (int i = seg.Offset; i < endOffset; i += 2)
                            {
                                var ch    = seg.Array[i];
                                var style = seg.Array[i + 1];

                                if (lastStyle != style)
                                {
                                    // Change the style
                                    if (styles[lastStyle].FontIndex != styles[style].FontIndex)
                                    {
                                        tw.Write(@"\f{0}", styles[style].FontIndex);
                                    }
                                    if (styles[lastStyle].SizeF != styles[style].SizeF)
                                    {
                                        tw.Write(@"\fs{0}", (int)(styles[style].SizeF * 2));
                                    }
                                    if (styles[lastStyle].ForeColorIndex != styles[style].ForeColorIndex)
                                    {
                                        tw.Write(@"\cf{0}", styles[style].ForeColorIndex);
                                    }
                                    if (styles[lastStyle].BackColorIndex != styles[style].BackColorIndex)
                                    {
                                        tw.Write(@"\chshdng0\chcbpat{0}\cb{0}", styles[style].BackColorIndex);
                                    }
                                    if (styles[lastStyle].Italic != styles[style].Italic)
                                    {
                                        tw.Write(@"\i{0}", styles[style].Italic != 0 ? "" : "0");
                                    }
                                    if (styles[lastStyle].Underline != styles[style].Underline)
                                    {
                                        tw.Write(@"\ul{0}", styles[style].Underline != 0 ? "" : "0");
                                    }
                                    if (styles[lastStyle].Weight != styles[style].Weight)
                                    {
                                        if (styles[style].Weight >= 700 && styles[lastStyle].Weight < 700)
                                        {
                                            tw.Write(@"\b");
                                        }
                                        else if (styles[style].Weight < 700 && styles[lastStyle].Weight >= 700)
                                        {
                                            tw.Write(@"\b0");
                                        }
                                    }

                                    // NOTE: We don't support StyleData.Visible and StyleData.Case in RTF

                                    lastStyle = style;
                                    tw.Write(" "); // Delimiter
                                }

                                switch (ch)
                                {
                                case (byte)'{':
                                    tw.Write(@"\{");
                                    break;

                                case (byte)'}':
                                    tw.Write(@"\}");
                                    break;

                                case (byte)'\\':
                                    tw.Write(@"\\");
                                    break;

                                case (byte)'\t':
                                    tw.Write(@"\tab ");
                                    break;

                                case (byte)'\r':
                                    if (i + 2 < endOffset)
                                    {
                                        if (seg.Array[i + 2] == (byte)'\n')
                                        {
                                            i += 2;
                                        }
                                    }

                                    // Either way, this is a line break
                                    goto case (byte)'\n';

                                case 0xC2:
                                    if (unicodeLineEndings && i + 2 < endOffset)
                                    {
                                        if (seg.Array[i + 2] == 0x85) // NEL \u0085
                                        {
                                            i += 2;
                                            goto case (byte)'\n';
                                        }
                                    }

                                    // Not a Unicode line break
                                    goto default;

                                case 0xE2:
                                    if (unicodeLineEndings && i + 4 < endOffset)
                                    {
                                        if (seg.Array[i + 2] == 0x80 && seg.Array[i + 4] == 0xA8) // LS \u2028
                                        {
                                            i += 4;
                                            goto case (byte)'\n';
                                        }
                                        else if (seg.Array[i + 2] == 0x80 && seg.Array[i + 4] == 0xA9) // PS \u2029
                                        {
                                            i += 4;
                                            goto case (byte)'\n';
                                        }
                                    }

                                    // Not a Unicode line break
                                    goto default;

                                case (byte)'\n':
                                    // All your line breaks are belong to us
                                    tw.WriteLine(@"\par");
                                    break;

                                default:

                                    if (ch == 0)
                                    {
                                        // Scintilla behavior is to allow control characters except for
                                        // NULL which will cause the Clipboard to truncate the string.
                                        tw.Write(" "); // Replace with space
                                        break;
                                    }

                                    if (ch > 0x7F)
                                    {
                                        // Treat as UTF-8 code point
                                        int unicode = 0;
                                        if (ch < 0xE0 && i + 2 < endOffset)
                                        {
                                            unicode |= ((0x1F & ch) << 6);
                                            unicode |= (0x3F & seg.Array[i + 2]);
                                            tw.Write(@"\u{0}?", unicode);
                                            i += 2;
                                            break;
                                        }
                                        else if (ch < 0xF0 && i + 4 < endOffset)
                                        {
                                            unicode |= ((0xF & ch) << 12);
                                            unicode |= ((0x3F & seg.Array[i + 2]) << 6);
                                            unicode |= (0x3F & seg.Array[i + 4]);
                                            tw.Write(@"\u{0}?", unicode);
                                            i += 4;
                                            break;
                                        }
                                        else if (ch < 0xF8 && i + 6 < endOffset)
                                        {
                                            unicode |= ((0x7 & ch) << 18);
                                            unicode |= ((0x3F & seg.Array[i + 2]) << 12);
                                            unicode |= ((0x3F & seg.Array[i + 4]) << 6);
                                            unicode |= (0x3F & seg.Array[i + 6]);
                                            tw.Write(@"\u{0}?", unicode);
                                            i += 6;
                                            break;
                                        }
                                    }

                                    // Regular ANSI char
                                    ms.WriteByte(ch);
                                    break;
                                }
                            }
                        }

                        tw.AutoFlush = false;
                        tw.WriteLine("}"); // rtf1
                        tw.Flush();

                        // Terminator
                        ms.WriteByte(0);

                        // var str = GetString(ms.Pointer, (int)ms.Length, Encoding.ASCII);
                        if (NativeMethods.SetClipboardData(CF_RTF, ms.Pointer) != IntPtr.Zero)
                        {
                            ms.FreeOnDispose = false; // Clipboard will free memory
                        }
                    }
            }
            catch (Exception ex)
            {
                // Yes, we swallow any exceptions. That may seem like code smell but this matches
                // the behavior of the Clipboard class, Windows Forms controls, and native Scintilla.
                Debug.Fail(ex.Message, ex.ToString());
            }
        }
Example #21
0
        private static unsafe ArraySegment<byte> GetStyledText(Scintilla scintilla, int startBytePos, int endBytePos, bool addLineBreak)
        {
            Debug.Assert(endBytePos > startBytePos);

            // Make sure the range is styled
            scintilla.DirectMessage(NativeMethods.SCI_COLOURISE, new IntPtr(startBytePos), new IntPtr(endBytePos));

            var byteLength = (endBytePos - startBytePos);
            var buffer = new byte[(byteLength * 2) + (addLineBreak ? 4 : 0) + 2];
            fixed (byte* bp = buffer)
            {
                NativeMethods.Sci_TextRange* tr = stackalloc NativeMethods.Sci_TextRange[1];
                tr->chrg.cpMin = startBytePos;
                tr->chrg.cpMax = endBytePos;
                tr->lpstrText = new IntPtr(bp);

                scintilla.DirectMessage(NativeMethods.SCI_GETSTYLEDTEXT, IntPtr.Zero, new IntPtr(tr));
                byteLength *= 2;
            }

            // Add a line break?
            // We do this when this range is part of a rectangular selection.
            if (addLineBreak)
            {
                var style = buffer[byteLength - 1];

                buffer[byteLength++] = (byte)'\r';
                buffer[byteLength++] = style;
                buffer[byteLength++] = (byte)'\n';
                buffer[byteLength++] = style;

                // Fix-up the NULL terminator just in case
                buffer[byteLength] = 0;
                buffer[byteLength + 1] = 0;
            }

            return new ArraySegment<byte>(buffer, 0, byteLength);
        }
Example #22
0
        public static string GetHtml(Scintilla scintilla, int startBytePos, int endBytePos)
        {
            // If we ever allow more than UTF-8, this will have to be revisited
            Debug.Assert(scintilla.DirectMessage(NativeMethods.SCI_GETCODEPAGE).ToInt32() == NativeMethods.SC_CP_UTF8);

            if (startBytePos == endBytePos)
                return string.Empty;

            StyleData[] styles = null;
            List<ArraySegment<byte>> styledSegments = GetStyledSegments(scintilla, false, false, startBytePos, endBytePos, out styles);

            using (var ms = new NativeMemoryStream(styledSegments.Sum(s => s.Count))) // Hint
            using (var sw = new StreamWriter(ms, new UTF8Encoding(false)))
            {
                // Write the styles
                sw.WriteLine(@"<style type=""text/css"" scoped="""">");
                sw.Write("div#segments {");
                sw.Write(" float: left;");
                sw.Write(" white-space: pre;");
                sw.Write(" line-height: {0}px;", scintilla.DirectMessage(NativeMethods.SCI_TEXTHEIGHT, new IntPtr(0)).ToInt32());
                sw.Write(" background-color: #{0:X2}{1:X2}{2:X2};", (styles[Style.Default].BackColor >> 0) & 0xFF, (styles[Style.Default].BackColor >> 8) & 0xFF, (styles[Style.Default].BackColor >> 16) & 0xFF);
                sw.WriteLine(" }");

                for (int i = 0; i < styles.Length; i++)
                {
                    if (!styles[i].Used)
                        continue;

                    sw.Write("span.s{0} {{", i);
                    sw.Write(@" font-family: ""{0}"";", styles[i].FontName);
                    sw.Write(" font-size: {0}pt;", styles[i].SizeF);
                    sw.Write(" font-weight: {0};", styles[i].Weight);
                    if (styles[i].Italic != 0)
                        sw.Write(" font-style: italic;");
                    if (styles[i].Underline != 0)
                        sw.Write(" text-decoration: underline;");
                    sw.Write(" background-color: #{0:X2}{1:X2}{2:X2};", (styles[i].BackColor >> 0) & 0xFF, (styles[i].BackColor >> 8) & 0xFF, (styles[i].BackColor >> 16) & 0xFF);
                    sw.Write(" color: #{0:X2}{1:X2}{2:X2};", (styles[i].ForeColor >> 0) & 0xFF, (styles[i].ForeColor >> 8) & 0xFF, (styles[i].ForeColor >> 16) & 0xFF);
                    switch ((StyleCase)styles[i].Case)
                    {
                        case StyleCase.Upper:
                            sw.Write(" text-transform: uppercase;");
                            break;
                        case StyleCase.Lower:
                            sw.Write(" text-transform: lowercase;");
                            break;
                    }

                    if (styles[i].Visible == 0)
                        sw.Write(" visibility: hidden;");

                    sw.WriteLine(" }");
                }

                sw.WriteLine("</style>");

                var unicodeLineEndings = ((scintilla.DirectMessage(NativeMethods.SCI_GETLINEENDTYPESACTIVE).ToInt32() & NativeMethods.SC_LINE_END_TYPE_UNICODE) > 0);
                var tabSize = scintilla.DirectMessage(NativeMethods.SCI_GETTABWIDTH).ToInt32();
                var tab = new string(' ', tabSize);
                var lastStyle = Style.Default;

                // Write the styled text
                sw.Write(@"<div id=""segments""><span class=""s{0}"">", Style.Default);
                sw.Flush();
                sw.AutoFlush = true;

                foreach (var seg in styledSegments)
                {
                    var endOffset = seg.Offset + seg.Count;
                    for (int i = seg.Offset; i < endOffset; i += 2)
                    {
                        var ch = seg.Array[i];
                        var style = seg.Array[i + 1];

                        if (lastStyle != style)
                        {
                            sw.Write(@"</span><span class=""s{0}"">", style);
                            lastStyle = style;
                        }

                        switch (ch)
                        {
                            case (byte)'<':
                                sw.Write("&lt;");
                                break;

                            case (byte)'>':
                                sw.Write("&gt;");
                                break;

                            case (byte)'&':
                                sw.Write("&amp;");
                                break;

                            case (byte)'\t':
                                sw.Write(tab);
                                break;

                            case (byte)'\r':
                                if (i + 2 < endOffset)
                                {
                                    if (seg.Array[i + 2] == (byte)'\n')
                                        i += 2;
                                }

                                // Either way, this is a line break
                                goto case (byte)'\n';

                            case 0xC2:
                                if (unicodeLineEndings && i + 2 < endOffset)
                                {
                                    if (seg.Array[i + 2] == 0x85) // NEL \u0085
                                    {
                                        i += 2;
                                        goto case (byte)'\n';
                                    }
                                }

                                // Not a Unicode line break
                                goto default;

                            case 0xE2:
                                if (unicodeLineEndings && i + 4 < endOffset)
                                {
                                    if (seg.Array[i + 2] == 0x80 && seg.Array[i + 4] == 0xA8) // LS \u2028
                                    {
                                        i += 4;
                                        goto case (byte)'\n';
                                    }
                                    else if (seg.Array[i + 2] == 0x80 && seg.Array[i + 4] == 0xA9) // PS \u2029
                                    {
                                        i += 4;
                                        goto case (byte)'\n';
                                    }
                                }

                                // Not a Unicode line break
                                goto default;

                            case (byte)'\n':
                                // All your line breaks are belong to us
                                sw.Write("\r\n");
                                break;

                            default:

                                if (ch == 0)
                                {
                                    // Replace NUL with space
                                    sw.Write(" ");
                                    break;
                                }

                                ms.WriteByte(ch);
                                break;
                        }
                    }
                }

                sw.AutoFlush = false;
                sw.WriteLine("</span></div>");
                sw.Flush();

                return GetString(ms.Pointer, (int)ms.Length, Encoding.UTF8);
            }
        }
Example #23
0
 /// <summary>
 /// Expands any parent folds to ensure the line is visible.
 /// </summary>
 public void EnsureVisible()
 {
     scintilla.DirectMessage(NativeMethods.SCI_ENSUREVISIBLE, new IntPtr(Index));
 }
Example #24
0
        public static void Copy(Scintilla scintilla, CopyFormat format, bool useSelection, bool allowLine, int startBytePos, int endBytePos)
        {
            // Plain text
            if ((format & CopyFormat.Text) > 0)
            {
                if (useSelection)
                {
                    if (allowLine)
                    {
                        scintilla.DirectMessage(NativeMethods.SCI_COPYALLOWLINE);
                    }
                    else
                    {
                        scintilla.DirectMessage(NativeMethods.SCI_COPY);
                    }
                }
                else
                {
                    scintilla.DirectMessage(NativeMethods.SCI_COPYRANGE, new IntPtr(startBytePos), new IntPtr(endBytePos));
                }
            }

            // RTF and/or HTML
            if ((format & (CopyFormat.Rtf | CopyFormat.Html)) > 0)
            {
                // If we ever allow more than UTF-8, this will have to be revisited
                Debug.Assert(scintilla.DirectMessage(NativeMethods.SCI_GETCODEPAGE).ToInt32() == NativeMethods.SC_CP_UTF8);

                if (!registeredFormats)
                {
                    // Register non-standard clipboard formats.
                    // Scintilla -> ScintillaWin.cxx
                    // NppExport -> HTMLExporter.h
                    // NppExport -> RTFExporter.h

                    CF_LINESELECT     = NativeMethods.RegisterClipboardFormat("MSDEVLineSelect");
                    CF_VSLINETAG      = NativeMethods.RegisterClipboardFormat("VisualStudioEditorOperationsLineCutCopyClipboardTag");
                    CF_HTML           = NativeMethods.RegisterClipboardFormat("HTML Format");
                    CF_RTF            = NativeMethods.RegisterClipboardFormat("Rich Text Format");
                    registeredFormats = true;
                }

                var         lineCopy = false;
                StyleData[] styles   = null;
                List <ArraySegment <byte> > styledSegments = null;

                if (useSelection)
                {
                    var selIsEmpty = scintilla.DirectMessage(NativeMethods.SCI_GETSELECTIONEMPTY) != IntPtr.Zero;
                    if (selIsEmpty)
                    {
                        if (allowLine)
                        {
                            // Get the current line
                            styledSegments = GetStyledSegments(scintilla, false, true, 0, 0, out styles);
                            lineCopy       = true;
                        }
                    }
                    else
                    {
                        // Get every selection
                        styledSegments = GetStyledSegments(scintilla, true, false, 0, 0, out styles);
                    }
                }
                else if (startBytePos != endBytePos)
                {
                    // User-specified range
                    styledSegments = GetStyledSegments(scintilla, false, false, startBytePos, endBytePos, out styles);
                }

                // If we have segments and can open the clipboard
                if (styledSegments != null && styledSegments.Count > 0 && NativeMethods.OpenClipboard(scintilla.Handle))
                {
                    if ((format & CopyFormat.Text) == 0)
                    {
                        // Do the things default (plain text) processing would normally give us
                        NativeMethods.EmptyClipboard();

                        if (lineCopy)
                        {
                            // Clipboard tags
                            NativeMethods.SetClipboardData(CF_LINESELECT, IntPtr.Zero);
                            NativeMethods.SetClipboardData(CF_VSLINETAG, IntPtr.Zero);
                        }
                    }

                    // RTF
                    if ((format & CopyFormat.Rtf) > 0)
                    {
                        CopyRtf(scintilla, styles, styledSegments);
                    }

                    // HTML
                    if ((format & CopyFormat.Html) > 0)
                    {
                        CopyHtml(scintilla, styles, styledSegments);
                    }

                    NativeMethods.CloseClipboard();
                }
            }
        }
Example #25
0
 public void Copy(int startPosition, int endPosition)
 {
     Scintilla.DirectMessage(NativeMethods.SCI_COPYRANGE, new IntPtr(startPosition), new IntPtr(endPosition));
 }
Example #26
0
 /// <summary>
 /// Navigates the caret to the start of the line.
 /// </summary>
 /// <remarks>Any selection is discarded.</remarks>
 public void Goto()
 {
     scintilla.DirectMessage(NativeMethods.SCI_GOTOLINE, new IntPtr(Index));
 }
Example #27
0
 public void Paste()
 {
     Scintilla.DirectMessage(NativeMethods.SCI_PASTE, IntPtr.Zero, IntPtr.Zero);
 }
Example #28
0
 public void Join(int startLine, int endLine)
 {
     NativeScintilla.SetTargetStart(startLine);
     NativeScintilla.SetTargetEnd(endLine);
     Scintilla.DirectMessage(NativeMethods.SCI_LINESJOIN, IntPtr.Zero, IntPtr.Zero);
 }